From 3381b6517e9f8138170b71038b6478afd9555d05 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 9 Jun 2018 12:37:15 +0100 Subject: [PATCH 0001/1007] abstract_tcp_server2: fix busy calling of idle IO service This would make monerod use 100% CPU when running with torsocks without Tor running --- contrib/epee/include/net/abstract_tcp_server2.inl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 91a94c21e..bc54acae4 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -383,7 +383,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) //ask it inside(!) critical region if we still able to go in event wait... size_t cnt = socket_.get_io_service().poll_one(); if(!cnt) - misc_utils::sleep_no_w(0); + misc_utils::sleep_no_w(1); } return true; @@ -836,7 +836,9 @@ POP_WARNINGS { try { - io_service_.run(); + size_t cnt = io_service_.run(); + if (cnt == 0) + misc_utils::sleep_no_w(1); } catch(const std::exception& ex) { From 579383c26b3cc8f29e09a55bc24446b9141f4f87 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Wed, 19 Sep 2018 13:39:01 +0100 Subject: [PATCH 0002/1007] simplewallet: Add Unicode input_line [Ryo backport] --- src/common/util.cpp | 28 +++++++++++++++++ src/common/util.h | 3 ++ src/simplewallet/simplewallet.cpp | 50 ++----------------------------- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index c56c77505..2a1d49af0 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -939,4 +939,32 @@ std::string get_nix_version_display_string() } return newval; } + +#ifdef _WIN32 + std::string input_line_win() + { + HANDLE hConIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); + DWORD oldMode; + + FlushConsoleInputBuffer(hConIn); + GetConsoleMode(hConIn, &oldMode); + SetConsoleMode(hConIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT); + + wchar_t buffer[1024]; + DWORD read; + + ReadConsoleW(hConIn, buffer, sizeof(buffer)/sizeof(wchar_t)-1, &read, nullptr); + buffer[read] = 0; + + SetConsoleMode(hConIn, oldMode); + CloseHandle(hConIn); + + int size_needed = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL); + std::string buf(size_needed, '\0'); + WideCharToMultiByte(CP_UTF8, 0, buffer, -1, &buf[0], size_needed, NULL, NULL); + buf.pop_back(); //size_needed includes null that we needed to have space for + return buf; + } +#endif + } diff --git a/src/common/util.h b/src/common/util.h index 0e0b50520..ce773bd38 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -235,4 +235,7 @@ namespace tools boost::optional> parse_subaddress_lookahead(const std::string& str); std::string glob_to_regex(const std::string &val); +#ifdef _WIN32 + std::string input_line_win(); +#endif } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index e535b6d27..9b7d7694d 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -138,47 +138,6 @@ namespace const command_line::arg_descriptor< std::vector > arg_command = {"command", ""}; -#ifdef WIN32 - // Translate from CP850 to UTF-8; - // std::getline for a Windows console returns a string in CP437 or CP850; as simplewallet, - // like all of Monero, is assumed to work internally with UTF-8 throughout, even on Windows - // (although only implemented partially), a translation to UTF-8 is needed for input. - // - // Note that if a program is started inside the MSYS2 shell somebody already translates - // console input to UTF-8, but it's not clear how one could detect that in order to avoid - // double-translation; this code here thus breaks UTF-8 input within a MSYS2 shell, - // unfortunately. - // - // Note also that input for passwords is NOT translated, to remain compatible with any - // passwords containing special characters that predate this switch to UTF-8 support. - template - static T cp850_to_utf8(const T &cp850_str) - { - boost::locale::generator gen; - gen.locale_cache_enabled(true); - std::locale loc = gen("en_US.CP850"); - const boost::locale::conv::method_type how = boost::locale::conv::default_method; - T result; - const char *begin = cp850_str.data(); - const char *end = begin + cp850_str.size(); - result.reserve(end-begin); - typedef std::back_insert_iterator inserter_type; - inserter_type inserter(result); - boost::locale::utf::code_point c; - while(begin!=end) { - c=boost::locale::utf::utf_traits::template decode(begin,end); - if(c==boost::locale::utf::illegal || c==boost::locale::utf::incomplete) { - if(how==boost::locale::conv::stop) - throw boost::locale::conv::conversion_error(); - } - else { - boost::locale::utf::utf_traits::template encode(c,inserter); - } - } - return result; - } -#endif - std::string input_line(const std::string& prompt) { #ifdef HAVE_READLINE @@ -187,9 +146,10 @@ namespace std::cout << prompt; std::string buf; +#ifdef _WIN32 + buf = tools::input_line_win(); +#else std::getline(std::cin, buf); -#ifdef WIN32 - buf = cp850_to_utf8(buf); #endif return epee::string_tools::trim(buf); @@ -209,10 +169,6 @@ namespace epee::wipeable_string buf = pwd_container->password(); -#ifdef WIN32 - buf = cp850_to_utf8(buf); -#endif - buf.trim(); return buf; } From 341b3931ed79dd0b16a04e8a1468179ba5dd22c2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 20 Sep 2018 13:31:45 +0000 Subject: [PATCH 0003/1007] cryptonote_core: warn when the block rate deviates from expectations The warning threshold is set to allow a false positive every ten days on average. --- src/cryptonote_core/blockchain.cpp | 9 +++++ src/cryptonote_core/blockchain.h | 5 +++ src/cryptonote_core/cryptonote_core.cpp | 47 +++++++++++++++++++++++++ src/cryptonote_core/cryptonote_core.h | 8 +++++ 4 files changed, 69 insertions(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 3751d6473..e94024ae5 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -880,6 +880,15 @@ difficulty_type Blockchain::get_difficulty_for_next_block() return diff; } //------------------------------------------------------------------ +std::vector Blockchain::get_last_block_timestamps(unsigned int blocks) const +{ + std::vector timestamps(blocks); + uint64_t height = m_db->height(); + while (blocks--) + timestamps[blocks] = m_db->get_block_timestamp(height - blocks - 1); + return timestamps; +} +//------------------------------------------------------------------ // This function removes blocks from the blockchain until it gets to the // position where the blockchain switch started and then re-adds the blocks // that had been removed. diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 50ceccd0f..f56068db8 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -943,6 +943,11 @@ namespace cryptonote */ void on_new_tx_from_block(const cryptonote::transaction &tx); + /** + * @brief returns the timestamps of the last N blocks + */ + std::vector get_last_block_timestamps(unsigned int blocks) const; + private: // TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 7cbf414b7..7f8c60f73 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1471,6 +1471,7 @@ namespace cryptonote m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this)); m_check_updates_interval.do_call(boost::bind(&core::check_updates, this)); m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this)); + m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this)); m_miner.on_idle(); m_mempool.on_idle(); return true; @@ -1655,6 +1656,52 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------- + double factorial(unsigned int n) + { + if (n <= 1) + return 1.0; + double f = n; + while (n-- > 1) + f *= n; + return f; + } + //----------------------------------------------------------------------------------------------- + static double probability(unsigned int blocks, unsigned int expected) + { + // https://www.umass.edu/wsp/resources/poisson/#computing + return pow(expected, blocks) / (factorial(blocks) * exp(expected)); + } + //----------------------------------------------------------------------------------------------- + bool core::check_block_rate() + { + if (m_offline || m_target_blockchain_height > get_current_blockchain_height()) + { + MDEBUG("Not checking block rate, offline or syncing"); + return true; + } + + static constexpr double threshold = 1. / (864000 / DIFFICULTY_TARGET_V2); // one false positive every 10 days + + const time_t now = time(NULL); + const std::vector timestamps = m_blockchain_storage.get_last_block_timestamps(60); + + static const unsigned int seconds[] = { 5400, 1800, 600 }; + for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n) + { + unsigned int b = 0; + for (time_t ts: timestamps) b += ts >= now - seconds[n]; + const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V2); + MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")"); + if (p < threshold) + { + MWARNING("There were " << b << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Monero network or under attack. Or it could be just sheer bad luck."); + break; // no need to look further + } + } + + return true; + } + //----------------------------------------------------------------------------------------------- void core::set_target_blockchain_height(uint64_t target_blockchain_height) { m_target_blockchain_height = target_blockchain_height; diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index b40575ae9..b2be05bf4 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -935,6 +935,13 @@ namespace cryptonote */ bool check_disk_space(); + /** + * @brief checks block rate, and warns if it's too slow + * + * @return true on success, false otherwise + */ + bool check_block_rate(); + bool m_test_drop_download = true; //!< whether or not to drop incoming blocks (for testing) uint64_t m_test_drop_download_height = 0; //!< height under which to drop incoming blocks, if doing so @@ -959,6 +966,7 @@ namespace cryptonote epee::math_helper::once_a_time_seconds<60*2, false> m_txpool_auto_relayer; //!< interval for checking re-relaying txpool transactions epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space + epee::math_helper::once_a_time_seconds<90, false> m_block_rate_interval; //!< interval for checking block rate std::atomic m_starter_message_showed; //!< has the "daemon will sync now" message been shown? From 8110bea34bc36827e31288f1e89d6c7efa0c6e5b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 28 Sep 2018 15:22:20 +0000 Subject: [PATCH 0004/1007] dns_utils: refresh list of usable DNSSEC servers A few of them are now returning invalid replies. --- src/common/dns_utils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 3f2bde620..f2b270981 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -46,10 +46,11 @@ namespace bf = boost::filesystem; static const char *DEFAULT_DNS_PUBLIC_ADDR[] = { "194.150.168.168", // CCC (Germany) - "81.3.27.54", // Lightning Wire Labs (Germany) - "31.3.135.232", // OpenNIC (Switzerland) "80.67.169.40", // FDN (France) - "209.58.179.186", // Cyberghost (Singapore) + "89.233.43.71", // http://censurfridns.dk (Denmark) + "109.69.8.51", // punCAT (Spain) + "77.109.148.137", // Xiala.net (Switzerland) + "193.58.251.251", // SkyDNS (Russia) }; static boost::mutex instance_lock; From bef1750f650b0c7d62c8306dc1a74855a2a4d6a0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 28 Sep 2018 15:27:46 +0000 Subject: [PATCH 0005/1007] unit_tests: fix longstanding DNS related unit test --- tests/unit_tests/address_from_url.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/address_from_url.cpp b/tests/unit_tests/address_from_url.cpp index f174738fd..f6c0ad105 100644 --- a/tests/unit_tests/address_from_url.cpp +++ b/tests/unit_tests/address_from_url.cpp @@ -109,7 +109,7 @@ TEST(AddressFromURL, Failure) { bool dnssec_result = false; - std::vector addresses = tools::dns_utils::addresses_from_url("example.invalid", dnssec_result); + std::vector addresses = tools::dns_utils::addresses_from_url("example.veryinvalid", dnssec_result); // for a non-existing domain such as "example.invalid", the non-existence is proved with NSEC records ASSERT_TRUE(dnssec_result); From fa942ef610ef9fa32a3d6b8a8d6106e141f418c8 Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Sat, 29 Sep 2018 14:42:10 +0200 Subject: [PATCH 0006/1007] daemon: silence daemon update warnings on testnet --- src/cryptonote_core/blockchain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0e175cdbe..2c7032238 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -137,8 +137,8 @@ static const struct { { 6, 971400, 0, 1501709789 }, { 7, 1057027, 0, 1512211236 }, - { 8, 1057058, 0, 1515967497 }, - { 9, 1057778, 0, 1515967498 }, + { 8, 1057058, 0, 1533211200 }, + { 9, 1057778, 0, 1533297600 }, }; static const uint64_t testnet_hard_fork_version_1_till = 624633; From 2a44e13658aff63692094eb30fef9376b1ba0c10 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Tue, 25 Sep 2018 15:54:01 +0200 Subject: [PATCH 0007/1007] Merge pull request #4441 6f5360b3 bump version to 0.13.0.1 (Riccardo Spagni) From ff0d7a767894a6c71ceb5d1e0d4cb740b407d8d1 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 21:51:50 +0200 Subject: [PATCH 0008/1007] Merge pull request #4406 7964d4f8 wallet2: handle corner case in picking fake outputs (moneromooo-monero) --- src/wallet/wallet2.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 75178845a..33699cb79 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6723,11 +6723,23 @@ void wallet2::get_outs(std::vector> } // while we still need more mixins + uint64_t num_usable_outs = num_outs; + bool allow_blackballed = false; while (num_found < requested_outputs_count) { // if we've gone through every possible output, we've gotten all we can - if (seen_indices.size() == num_outs) - break; + if (seen_indices.size() == num_usable_outs) + { + // there is a first pass which rejects blackballed outputs, then a second pass + // which allows them if we don't have enough non blackballed outputs to reach + // the required amount of outputs (since consensus does not care about blackballed + // outputs, we still need to reach the minimum ring size) + if (allow_blackballed) + break; + MINFO("Not enough non blackballed outputs, we'll allow blackballed ones"); + allow_blackballed = true; + num_usable_outs = num_outs; + } // get a random output index from the DB. If we've already seen it, // return to the top of the loop and try again, otherwise add it to the @@ -6801,14 +6813,26 @@ void wallet2::get_outs(std::vector> if (seen_indices.count(i)) continue; - if (is_output_blackballed(std::make_pair(amount, i))) // don't add blackballed outputs + if (!allow_blackballed && is_output_blackballed(std::make_pair(amount, i))) // don't add blackballed outputs + { + --num_usable_outs; continue; + } seen_indices.emplace(i); LOG_PRINT_L2("picking " << i << " as " << type); req.outputs.push_back({amount, i}); ++num_found; } + + // if we had enough unusable outputs, we might fall off here and still + // have too few outputs, so we stuff with one to keep counts good, and + // we'll error out later + while (num_found < requested_outputs_count) + { + req.outputs.push_back({amount, 0}); + ++num_found; + } } // sort the subsection, to ensure the daemon doesn't know which output is ours From 2fbf38ee918894a92f2f058c5551d81d34e215c9 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Wed, 26 Sep 2018 00:36:34 +0200 Subject: [PATCH 0009/1007] Fix 32bit depends builds Add architecture flags when cmake invokes gcc manually. Add 32bit to Travis. --- .travis.yml | 2 ++ contrib/depends/toolchain.cmake.in | 4 ++++ src/blockchain_utilities/CMakeLists.txt | 2 ++ src/blocks/CMakeLists.txt | 12 +++++++++--- src/daemon/CMakeLists.txt | 2 ++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9368c3ff2..ca3a24ae8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,8 @@ env: - HOST=arm-linux-gnueabihf PACKAGES="gperf g++-arm-linux-gnueabihf" # ARM v8 - HOST=aarch64-linux-gnu PACKAGES="gperf g++-aarch64-linux-gnu" +# i686 Win + - HOST=i686-w64-mingw32 PACKAGES="python3 nsis g++-mingw-w64-i686" # i686 Linux - HOST=i686-pc-linux-gnu PACKAGES="gperf cmake g++-multilib bc python3-zmq" RUN_TESTS=true # Win64 diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index 375533557..bde7497b3 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -78,5 +78,9 @@ elseif(ARCHITECTURE STREQUAL "aarch64") set(BUILD_64 ON) endif() +if(ARCHITECTURE STREQUAL "i686" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + SET(LINUX_32 ON) +endif() + #Create a new global cmake flag that indicates building with depends set (DEPENDS true) diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 37bca671f..ecd7b754c 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -32,6 +32,8 @@ if(PER_BLOCK_CHECKPOINT) add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) elseif(APPLE AND NOT DEPENDS) add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) else() add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) endif() diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index cf3f0b354..ebb5408cc 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -30,9 +30,15 @@ if(APPLE) add_library(blocks STATIC blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) else() - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + if(LINUX_32) + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + else() + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + endif() add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) endif() diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index b1c4b711d..f645836a4 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -32,6 +32,8 @@ if(PER_BLOCK_CHECKPOINT) add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) elseif(APPLE AND NOT DEPENDS) add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) else() add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) endif() From 402349760f699fe512e9ba97328a5f8827f0c003 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:10:48 +0200 Subject: [PATCH 0010/1007] Merge pull request #4407 43a06350 ringdb: use cursors to be a bit faster (moneromooo-monero) --- src/wallet/ringdb.cpp | 15 ++++++++------- tests/unit_tests/ringdb.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index e9fc6866d..e5995e7fb 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -398,6 +398,8 @@ bool ringdb::blackball_worker(const std::vector> & epee::misc_utils::auto_scope_leave_caller txn_dtor = epee::misc_utils::create_scope_leave_handler([&](){if (tx_active) mdb_txn_abort(txn);}); tx_active = true; + dbr = mdb_cursor_open(txn, dbi_blackballs, &cursor); + THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create cursor for blackballs table: " + std::string(mdb_strerror(dbr))); MDB_val key, data; for (const std::pair &output: outputs) @@ -411,25 +413,22 @@ bool ringdb::blackball_worker(const std::vector> & { case BLACKBALL_BLACKBALL: MDEBUG("Blackballing output " << output.first << "/" << output.second); - dbr = mdb_put(txn, dbi_blackballs, &key, &data, MDB_APPENDDUP); + dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP); if (dbr == MDB_KEYEXIST) dbr = 0; break; case BLACKBALL_UNBLACKBALL: MDEBUG("Unblackballing output " << output.first << "/" << output.second); - dbr = mdb_del(txn, dbi_blackballs, &key, &data); - if (dbr == MDB_NOTFOUND) - dbr = 0; + dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH); + if (dbr == 0) + dbr = mdb_cursor_del(cursor, 0); break; case BLACKBALL_QUERY: - dbr = mdb_cursor_open(txn, dbi_blackballs, &cursor); - THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create cursor for blackballs table: " + std::string(mdb_strerror(dbr))); dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH); THROW_WALLET_EXCEPTION_IF(dbr && dbr != MDB_NOTFOUND, tools::error::wallet_internal_error, "Failed to lookup in blackballs table: " + std::string(mdb_strerror(dbr))); ret = dbr != MDB_NOTFOUND; if (dbr == MDB_NOTFOUND) dbr = 0; - mdb_cursor_close(cursor); break; case BLACKBALL_CLEAR: break; @@ -439,6 +438,8 @@ bool ringdb::blackball_worker(const std::vector> & THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to query blackballs table: " + std::string(mdb_strerror(dbr))); } + mdb_cursor_close(cursor); + if (op == BLACKBALL_CLEAR) { dbr = mdb_drop(txn, dbi_blackballs, 0); diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp index 416ae0890..0d92049ac 100644 --- a/tests/unit_tests/ringdb.cpp +++ b/tests/unit_tests/ringdb.cpp @@ -150,6 +150,30 @@ TEST(blackball, found) ASSERT_TRUE(ringdb.blackballed(OUTPUT_1)); } +TEST(blackball, vector) +{ + RingDB ringdb; + std::vector> outputs; + outputs.push_back(std::make_pair(0, 1)); + outputs.push_back(std::make_pair(10, 3)); + outputs.push_back(std::make_pair(10, 4)); + outputs.push_back(std::make_pair(10, 8)); + outputs.push_back(std::make_pair(20, 0)); + outputs.push_back(std::make_pair(20, 1)); + outputs.push_back(std::make_pair(30, 5)); + ASSERT_TRUE(ringdb.blackball(outputs)); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(0, 1))); + ASSERT_FALSE(ringdb.blackballed(std::make_pair(10, 2))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 3))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 4))); + ASSERT_FALSE(ringdb.blackballed(std::make_pair(10, 5))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 8))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(20, 0))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(20, 1))); + ASSERT_FALSE(ringdb.blackballed(std::make_pair(20, 2))); + ASSERT_TRUE(ringdb.blackballed(std::make_pair(30, 5))); +} + TEST(blackball, unblackball) { RingDB ringdb; From e4130e6ae6314b7364e0411edd84f3c0fdc0b5e5 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:11:13 +0200 Subject: [PATCH 0011/1007] Merge pull request #4409 7a056f44 WalletAPI: multisigSignData bug fixed (naughtyfox) --- src/wallet/api/pending_transaction.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index 8d200220d..913e3156f 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.cpp @@ -200,7 +200,11 @@ std::string PendingTransactionImpl::multisigSignData() { throw std::runtime_error("wallet is not multisig"); } - auto cipher = m_wallet.m_wallet->save_multisig_tx(m_pending_tx); + tools::wallet2::multisig_tx_set txSet; + txSet.m_ptx = m_pending_tx; + txSet.m_signers = m_signers; + auto cipher = m_wallet.m_wallet->save_multisig_tx(txSet); + return epee::string_tools::buff_to_hex_nodelimer(cipher); } catch (const std::exception& e) { m_status = Status_Error; From cd5638f894954a8424af6bd22f4386b121e5dc8f Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:11:32 +0200 Subject: [PATCH 0012/1007] Merge pull request #4417 a21da905 Wallet: use unique_ptr for WalletImpl members (oneiric) --- src/wallet/api/wallet.cpp | 26 ++++++++++---------------- src/wallet/api/wallet.h | 12 ++++++------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5827e4d1a..96e5c8629 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -376,15 +376,15 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds) , m_rebuildWalletCache(false) , m_is_connected(false) { - m_wallet = new tools::wallet2(static_cast(nettype), kdf_rounds, true); - m_history = new TransactionHistoryImpl(this); - m_wallet2Callback = new Wallet2CallbackImpl(this); + m_wallet = std::make_unique(static_cast(nettype), kdf_rounds, true); + m_history = std::make_unique(this); + m_wallet2Callback = std::make_unique(this); m_wallet->callback(m_wallet2Callback); m_refreshThreadDone = false; m_refreshEnabled = false; - m_addressBook = new AddressBookImpl(this); - m_subaddress = new SubaddressImpl(this); - m_subaddressAccount = new SubaddressAccountImpl(this); + m_addressBook = std::make_unique(this); + m_subaddress = std::make_unique(this); + m_subaddressAccount = std::make_unique(this); m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS; @@ -405,12 +405,6 @@ WalletImpl::~WalletImpl() close(false); // do not store wallet as part of the closing activities // Stop refresh thread stopRefresh(); - delete m_wallet2Callback; - delete m_history; - delete m_addressBook; - delete m_subaddress; - delete m_subaddressAccount; - delete m_wallet; LOG_PRINT_L1(__FUNCTION__ << " finished"); } @@ -1551,22 +1545,22 @@ void WalletImpl::disposeTransaction(PendingTransaction *t) TransactionHistory *WalletImpl::history() { - return m_history; + return m_history.get(); } AddressBook *WalletImpl::addressBook() { - return m_addressBook; + return m_addressBook.get(); } Subaddress *WalletImpl::subaddress() { - return m_subaddress; + return m_subaddress.get(); } SubaddressAccount *WalletImpl::subaddressAccount() { - return m_subaddressAccount; + return m_subaddressAccount.get(); } void WalletImpl::setListener(WalletListener *l) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 64350cee7..5963a7607 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -215,16 +215,16 @@ class WalletImpl : public Wallet friend class SubaddressImpl; friend class SubaddressAccountImpl; - tools::wallet2 * m_wallet; + std::unique_ptr m_wallet; mutable boost::mutex m_statusMutex; mutable int m_status; mutable std::string m_errorString; std::string m_password; - TransactionHistoryImpl * m_history; - Wallet2CallbackImpl * m_wallet2Callback; - AddressBookImpl * m_addressBook; - SubaddressImpl * m_subaddress; - SubaddressAccountImpl * m_subaddressAccount; + std::unique_ptr m_history; + std::unique_ptr m_wallet2Callback; + std::unique_ptr m_addressBook; + std::unique_ptr m_subaddress; + std::unique_ptr m_subaddressAccount; // multi-threaded refresh stuff std::atomic m_refreshEnabled; From 876282fd6956ee6a39447f189b5ab82c1f388bac Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:11:50 +0200 Subject: [PATCH 0013/1007] Merge pull request #4424 92d1da28 unit_tests: fix build with GCC 5.4.0 on ubuntu (moneromooo-monero) --- tests/unit_tests/is_hdd.cpp | 4 ++-- tests/unit_tests/wipeable_string.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit_tests/is_hdd.cpp b/tests/unit_tests/is_hdd.cpp index 1be670e5e..040af4f47 100644 --- a/tests/unit_tests/is_hdd.cpp +++ b/tests/unit_tests/is_hdd.cpp @@ -6,12 +6,12 @@ TEST(is_hdd, linux_os_root) { std::string path = "/"; - EXPECT_TRUE(tools::is_hdd(path.c_str())); + EXPECT_TRUE(tools::is_hdd(path.c_str()) != boost::none); } #else TEST(is_hdd, unknown_os) { std::string path = ""; - EXPECT_FALSE(tools::is_hdd(path.c_str())); + EXPECT_FALSE(tools::is_hdd(path.c_str()) != boost::none); } #endif diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp index 65718fd45..44e050c5c 100644 --- a/tests/unit_tests/wipeable_string.cpp +++ b/tests/unit_tests/wipeable_string.cpp @@ -194,13 +194,13 @@ TEST(wipeable_string, parse_hexstr) ASSERT_EQ(boost::none, epee::wipeable_string("0").parse_hexstr()); ASSERT_EQ(boost::none, epee::wipeable_string("000").parse_hexstr()); - ASSERT_TRUE((s = epee::wipeable_string("").parse_hexstr())); + ASSERT_TRUE((s = epee::wipeable_string("").parse_hexstr()) != boost::none); ASSERT_EQ(*s, ""); - ASSERT_TRUE((s = epee::wipeable_string("00").parse_hexstr())); + ASSERT_TRUE((s = epee::wipeable_string("00").parse_hexstr()) != boost::none); ASSERT_EQ(*s, epee::wipeable_string("", 1)); - ASSERT_TRUE((s = epee::wipeable_string("41").parse_hexstr())); + ASSERT_TRUE((s = epee::wipeable_string("41").parse_hexstr()) != boost::none); ASSERT_EQ(*s, epee::wipeable_string("A")); - ASSERT_TRUE((s = epee::wipeable_string("414243").parse_hexstr())); + ASSERT_TRUE((s = epee::wipeable_string("414243").parse_hexstr()) != boost::none); ASSERT_EQ(*s, epee::wipeable_string("ABC")); } From 8e07e26555acdf1d6e9feb11f3f77475adf22cc9 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:12:14 +0200 Subject: [PATCH 0014/1007] Merge pull request #4425 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a69271fa Fixed a typo (Piotr Kąkol) --- cmake/CheckLinkerFlag.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake index a3879d0be..2b507ab71 100644 --- a/cmake/CheckLinkerFlag.cmake +++ b/cmake/CheckLinkerFlag.cmake @@ -39,7 +39,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE) endif() set(${VARIABLE} "" CACHE INTERNAL "Have linker flag ${flag}") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if the ${flag} linker flag is suppored " + "Determining if the ${flag} linker flag is supported " "failed with the following output:\n" "${OUTPUT}\n\n") endif() From 54d883d826fd345e3636bf2b781b91e6d07782b1 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:12:31 +0200 Subject: [PATCH 0015/1007] Merge pull request #4427 83debef9 wallet_rpc_server: remove verbose field in incoming_transfers query (moneromooo-monero) --- src/wallet/wallet_rpc_server.cpp | 2 +- src/wallet/wallet_rpc_server_commands_defs.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e6eb64d12..27631187c 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1554,7 +1554,7 @@ namespace tools rpc_transfers.global_index = td.m_global_output_index; rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(td.m_txid); rpc_transfers.subaddr_index = {td.m_subaddr_index.major, td.m_subaddr_index.minor}; - rpc_transfers.key_image = req.verbose && td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : ""; + rpc_transfers.key_image = td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : ""; res.transfers.push_back(rpc_transfers); } } diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 2168e0f71..81ea22928 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -883,13 +883,11 @@ namespace wallet_rpc std::string transfer_type; uint32_t account_index; std::set subaddr_indices; - bool verbose; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(transfer_type) KV_SERIALIZE(account_index) KV_SERIALIZE(subaddr_indices) - KV_SERIALIZE(verbose) END_KV_SERIALIZE_MAP() }; From 365a9d0c09684e13da7dd36e1258ecd65e964c4c Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:12:56 +0200 Subject: [PATCH 0016/1007] Merge pull request #4434 89288863 README: mention ASAN usage alongside valgrind (moneromooo-monero) --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ac40f08d3..d16b21528 100644 --- a/README.md +++ b/README.md @@ -666,9 +666,19 @@ Type `run` to run monerod ### Analysing memory corruption -We use the tool `valgrind` for this. +There are two tools available: -Run with `valgrind /path/to/monerod`. It will be slow. +* ASAN + +Configure Monero with the -D SANITIZE=ON cmake flag, eg: + + cd build/debug && cmake -D SANITIZE=ON -D CMAKE_BUILD_TYPE=Debug ../.. + +You can then run the monero tools normally. Performance will typically halve. + +* valgrind + +Install valgrind and run as `valgrind /path/to/monerod`. It will be very slow. ### LMDB From b710d780268de63e77cd0d0a3efaf733819f4897 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:13:16 +0200 Subject: [PATCH 0017/1007] Merge pull request #4439 174f31bf simplewallet: don't complain about payment id on pool mined blocks (moneromooo-monero) --- src/simplewallet/simplewallet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 302d2a999..06655ed69 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4157,10 +4157,11 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) { crypto::hash8 payment_id8 = crypto::null_hash8; + crypto::hash payment_id = crypto::null_hash; if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) message_writer() << tr("NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead"); - else + else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) message_writer(console_color_red, false) << tr("WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead"); } From b4ec67b2f7a9a9ca25783dec8598422de0d89149 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:13:34 +0200 Subject: [PATCH 0018/1007] Merge pull request #4443 b2972927 osx compilation fix: missing boost libs added (Dusan Klinec) --- contrib/epee/src/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index 0b5e7ae6c..bc437deb9 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -54,7 +54,9 @@ endif() target_link_libraries(epee PUBLIC easylogging + ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} PRIVATE ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) From 09fb2bb5f895410a401f699f3d621d52fe12bee3 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:14:09 +0200 Subject: [PATCH 0019/1007] Merge pull request #4445 fe125647 Fixup RENAME_DB() macro (Howard Chu) --- src/blockchain_db/lmdb/db_lmdb.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index b0f3ca5f0..d8f7df5f7 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -3490,7 +3490,17 @@ void BlockchainLMDB::fixup() BlockchainDB::fixup(); } -#define RENAME_DB(name) \ +#define RENAME_DB(name) do { \ + char n2[] = name; \ + MDB_dbi tdbi; \ + n2[sizeof(n2)-2]--; \ + /* play some games to put (name) on a writable page */ \ + result = mdb_dbi_open(txn, n2, MDB_CREATE, &tdbi); \ + if (result) \ + throw0(DB_ERROR(lmdb_error("Failed to create " + std::string(n2) + ": ", result).c_str())); \ + result = mdb_drop(txn, tdbi, 1); \ + if (result) \ + throw0(DB_ERROR(lmdb_error("Failed to delete " + std::string(n2) + ": ", result).c_str())); \ k.mv_data = (void *)name; \ k.mv_size = sizeof(name)-1; \ result = mdb_cursor_open(txn, 1, &c_cur); \ @@ -3500,7 +3510,7 @@ void BlockchainLMDB::fixup() if (result) \ throw0(DB_ERROR(lmdb_error("Failed to get DB record for " name ": ", result).c_str())); \ ptr = (char *)k.mv_data; \ - ptr[sizeof(name)-2]++ + ptr[sizeof(name)-2]++; } while(0) #define LOGIF(y) if (ELPP->vRegistry()->allowed(y, "global")) From 5bcead236fc1c9c095403d96d2aa5273f5443815 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:14:28 +0200 Subject: [PATCH 0020/1007] Merge pull request #4446 69da14e1 fixes make debug compilation on OSX (Dusan Klinec) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 994d47691..a7746371e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -769,7 +769,7 @@ else() endif() if(APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -DGTEST_HAS_TR1_TUPLE=0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -DGTEST_HAS_TR1_TUPLE=0") endif() set(DEBUG_FLAGS "-g3") From 8e98ed8c713ec1a12b81665d924d13571493f346 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:14:56 +0200 Subject: [PATCH 0021/1007] Merge pull request #4448 6a781408 Make depends use self built clang for darwin (TheCharlatan) --- CMakeLists.txt | 12 ++++++++---- contrib/depends/packages/hidapi-darwin.mk | 2 +- contrib/depends/packages/packages.mk | 2 +- contrib/depends/packages/sodium-darwin.mk | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7746371e..fc0ecb14b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -883,10 +883,14 @@ list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS}) if (HIDAPI_FOUND) if (APPLE) - find_library(COREFOUNDATION CoreFoundation) - find_library(IOKIT IOKit) - list(APPEND EXTRA_LIBRARIES ${IOKIT}) - list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION}) + if(DEPENDS) + list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit") + else() + find_library(COREFOUNDATION CoreFoundation) + find_library(IOKIT IOKit) + list(APPEND EXTRA_LIBRARIES ${IOKIT}) + list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION}) + endif() endif() if (WIN32) list(APPEND EXTRA_LIBRARIES setupapi) diff --git a/contrib/depends/packages/hidapi-darwin.mk b/contrib/depends/packages/hidapi-darwin.mk index 1fbbb59e0..014aba578 100644 --- a/contrib/depends/packages/hidapi-darwin.mk +++ b/contrib/depends/packages/hidapi-darwin.mk @@ -11,7 +11,7 @@ endef define $(package)_config_cmds ./bootstrap &&\ - $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" + $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" CC="$(host_prefix)/native/bin/$($(package)_cc)" endef define $(package)_build_cmds diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index 13ba37628..9bfbff7d9 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -4,7 +4,7 @@ native_packages := native_ccache wallet_packages=bdb darwin_native_packages = native_biplist native_ds_store native_mac_alias -darwin_packages += sodium-darwin hidapi-darwin +darwin_packages = sodium-darwin hidapi-darwin linux_packages = eudev libusb hidapi-linux diff --git a/contrib/depends/packages/sodium-darwin.mk b/contrib/depends/packages/sodium-darwin.mk index 796bead16..59c6d1ec6 100644 --- a/contrib/depends/packages/sodium-darwin.mk +++ b/contrib/depends/packages/sodium-darwin.mk @@ -5,13 +5,14 @@ $(package)_file_name=libsodium-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 define $(package)_set_vars +$(package)_build_opts_darwin=OS=Darwin LIBTOOL="$($(package)_libtool)" $(package)_config_opts=--enable-static $(package)_config_opts+=--prefix=$(host_prefix) endef define $(package)_config_cmds ./autogen.sh &&\ - $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" + $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" CC="$(host_prefix)/native/bin/$($(package)_cc)" endef define $(package)_build_cmds From 2ec0d780c497d6ef68314fbda7d32cba41a58bf1 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:15:31 +0200 Subject: [PATCH 0022/1007] Merge pull request #4449 17142ec9 malloc scratchpad for all supported android archs (m2049r) --- src/crypto/slow-hash.c | 43 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 80bf4e06f..40cfb0461 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -1040,10 +1040,37 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u } } +#ifdef FORCE_USE_HEAP +STATIC INLINE void* aligned_malloc(size_t size, size_t align) +{ + void *result; +#ifdef _MSC_VER + result = _aligned_malloc(size, align); +#else + if (posix_memalign(&result, align, size)) result = NULL; +#endif + return result; +} + +STATIC INLINE void aligned_free(void *ptr) +{ +#ifdef _MSC_VER + _aligned_free(ptr); +#else + free(ptr); +#endif +} +#endif /* FORCE_USE_HEAP */ + void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { RDATA_ALIGN16 uint8_t expandedKey[240]; + +#ifndef FORCE_USE_HEAP RDATA_ALIGN16 uint8_t hp_state[MEMORY]; +#else + uint8_t *hp_state = (uint8_t *)aligned_malloc(MEMORY,16); +#endif uint8_t text[INIT_SIZE_BYTE]; RDATA_ALIGN16 uint64_t a[2]; @@ -1129,6 +1156,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int memcpy(state.init, text, INIT_SIZE_BYTE); hash_permutation(&state.hs); extra_hashes[state.hs.b[0] & 3](&state, 200, hash); + +#ifdef FORCE_USE_HEAP + aligned_free(hp_state); +#endif } #else /* aarch64 && crypto */ @@ -1270,8 +1301,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int #ifndef FORCE_USE_HEAP uint8_t long_state[MEMORY]; #else - uint8_t *long_state = NULL; - long_state = (uint8_t *)malloc(MEMORY); + uint8_t *long_state = (uint8_t *)malloc(MEMORY); #endif if (prehashed) { @@ -1449,7 +1479,12 @@ union cn_slow_hash_state { #pragma pack(pop) void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) { +#ifndef FORCE_USE_HEAP uint8_t long_state[MEMORY]; +#else + uint8_t *long_state = (uint8_t *)malloc(MEMORY); +#endif + union cn_slow_hash_state state; uint8_t text[INIT_SIZE_BYTE]; uint8_t a[AES_BLOCK_SIZE]; @@ -1534,6 +1569,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int /*memcpy(hash, &state, 32);*/ extra_hashes[state.hs.b[0] & 3](&state, 200, hash); oaes_free((OAES_CTX **) &aes_ctx); + +#ifdef FORCE_USE_HEAP + free(long_state); +#endif } #endif From e9512585430b84e2ee47d4069a3e5903c6e47961 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:15:52 +0200 Subject: [PATCH 0023/1007] Merge pull request #4456 06d05c21 device: set device name correctly if key_on_device is set (Dusan Klinec) --- src/wallet/wallet2.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 33699cb79..95474ce34 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3282,9 +3282,16 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ encrypted_secret_keys = field_encrypted_secret_keys; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string()); - if (m_device_name.empty() && field_device_name_found) + if (m_device_name.empty()) { - m_device_name = field_device_name; + if (field_device_name_found) + { + m_device_name = field_device_name; + } + else + { + m_device_name = m_key_device_type == hw::device::device_type::LEDGER ? "Ledger" : "default"; + } } } else From 4e3bff92ab4517d7eaa8a03fb1731283ce231342 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:16:19 +0200 Subject: [PATCH 0024/1007] Merge pull request #4457 85318e78 build: set ARCH_FLAG before compiler/linker flag checks (xiphon) --- CMakeLists.txt | 68 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc0ecb14b..c31c14350 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -529,6 +529,40 @@ else() endif() endif() endif() + + option(NO_AES "Explicitly disable AES support" ${NO_AES}) + + if(NO_AES) + message(STATUS "AES support explicitly disabled") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_AES") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_AES") + elseif(NOT ARM AND NOT PPC64LE AND NOT PPC64 AND NOT PPC AND NOT S390X) + message(STATUS "AES support enabled") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") + elseif(PPC64LE OR PPC64 OR PPC) + message(STATUS "AES support not available on POWER") + elseif(S390X) + message(STATUS "AES support not available on s390x") + elseif(ARM6) + message(STATUS "AES support not available on ARMv6") + elseif(ARM7) + message(STATUS "AES support not available on ARMv7") + elseif(ARM8) + CHECK_CXX_ACCEPTS_FLAG("-march=${ARCH}+crypto" ARCH_PLUS_CRYPTO) + if(ARCH_PLUS_CRYPTO) + message(STATUS "Crypto extensions enabled for ARMv8") + set(ARCH_FLAG "-march=${ARCH}+crypto") + else() + message(STATUS "Crypto extensions unavailable on your ARMv8 device") + endif() + else() + message(STATUS "AES support disabled") + endif() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH_FLAG}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAG}") + set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized") if(NOT MINGW) set(WARNINGS_AS_ERRORS_FLAG "-Werror") @@ -639,38 +673,8 @@ else() message(STATUS "Using C++ security hardening flags: ${CXX_SECURITY_FLAGS}") message(STATUS "Using linker security hardening flags: ${LD_SECURITY_FLAGS}") - option(NO_AES "Explicitly disable AES support" ${NO_AES}) - - if(NO_AES) - message(STATUS "AES support explicitly disabled") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_AES") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_AES") - elseif(NOT ARM AND NOT PPC64LE AND NOT PPC64 AND NOT PPC AND NOT S390X) - message(STATUS "AES support enabled") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") - elseif(PPC64LE OR PPC64 OR PPC) - message(STATUS "AES support not available on POWER") - elseif(S390X) - message(STATUS "AES support not available on s390x") - elseif(ARM6) - message(STATUS "AES support not available on ARMv6") - elseif(ARM7) - message(STATUS "AES support not available on ARMv7") - elseif(ARM8) - CHECK_CXX_ACCEPTS_FLAG("-march=${ARCH}+crypto" ARCH_PLUS_CRYPTO) - if(ARCH_PLUS_CRYPTO) - message(STATUS "Crypto extensions enabled for ARMv8") - set(ARCH_FLAG "-march=${ARCH}+crypto") - else() - message(STATUS "Crypto extensions unavailable on your ARMv8 device") - endif() - else() - message(STATUS "AES support disabled") - endif() - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}") # With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that From 9a54d0033e1104a264ddf05cc7e00bbbac12fba5 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:16:40 +0200 Subject: [PATCH 0025/1007] Merge pull request #4458 921b0fb1 use default create_address_file argument (m2049r) --- src/wallet/api/wallet.cpp | 4 ++-- src/wallet/wallet2.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 96e5c8629..3d4e981ea 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -603,7 +603,7 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path, LOG_PRINT_L1("Generated new view only wallet from keys"); } if(has_spendkey && !has_viewkey) { - m_wallet->generate(path, password, spendkey, true, false, false); + m_wallet->generate(path, password, spendkey, true, false); setSeedLanguage(language); LOG_PRINT_L1("Generated deterministic wallet from spend key with seed language: " + language); } @@ -623,7 +623,7 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p m_recoveringFromDevice = true; try { - m_wallet->restore(path, password, device_name, false); + m_wallet->restore(path, password, device_name); LOG_PRINT_L1("Generated new wallet from device: " + device_name); } catch (const std::exception& e) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index acbc09c36..db1ac7e42 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -554,7 +554,7 @@ namespace tools * \param device_name name of HW to use * \param create_address_file Whether to create an address file */ - void restore(const std::string& wallet_, const epee::wipeable_string& password, const std::string &device_name, bool create_address_file); + void restore(const std::string& wallet_, const epee::wipeable_string& password, const std::string &device_name, bool create_address_file = false); /*! * \brief Creates a multisig wallet From effcbf2060a48b01779a713fe66c82714a7fb7f2 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:17:00 +0200 Subject: [PATCH 0026/1007] Merge pull request #4459 bcf3f6af fuzz_tests: catch unhandled exceptions (moneromooo-monero) 3ebd05d4 miner: restore stream flags after changing them (moneromooo-monero) a093092e levin_protocol_handler_async: do not propagate exception through dtor (moneromooo-monero) 1eebb82b net_helper: do not propagate exceptions through dtor (moneromooo-monero) fb6a3630 miner: do not propagate exceptions through dtor (moneromooo-monero) 2e2139ff epee: do not propagate exception through dtor (moneromooo-monero) 0749a8bd db_lmdb: do not propagate exceptions in dtor (moneromooo-monero) 1b0afeeb wallet_rpc_server: exit cleanly on unhandled exceptions (moneromooo-monero) 418a9936 unit_tests: catch unhandled exceptions (moneromooo-monero) ea7f9543 threadpool: do not propagate exceptions through the dtor (moneromooo-monero) 6e855422 gen_multisig: nice exit on unhandled exception (moneromooo-monero) 53df2deb db_lmdb: catch error in mdb_stat calls during migration (moneromooo-monero) e67016dd blockchain_blackball: catch failure to commit db transaction (moneromooo-monero) 661439f4 mlog: don't remove old logs if we failed to rename the current file (moneromooo-monero) 5fdcda50 easylogging++: test for NULL before dereference (moneromooo-monero) 7ece1550 performance_test: fix bad last argument calling add_arg (moneromooo-monero) a085da32 unit_tests: add check for page size > 0 before dividing (moneromooo-monero) d8b1ec8b unit_tests: use std::shared_ptr to shut coverity up about leaks (moneromooo-monero) 02563bf4 simplewallet: top level exception catcher to print nicer messages (moneromooo-monero) c57a65b2 blockchain_blackball: fix shift range for 32 bit archs (moneromooo-monero) --- contrib/epee/include/console_handler.h | 3 +- .../net/levin_protocol_handler_async.h | 6 ++ contrib/epee/include/net/net_helper.h | 3 +- contrib/epee/src/mlog.cpp | 7 +- external/easylogging++/easylogging++.cc | 4 +- src/blockchain_db/lmdb/db_lmdb.cpp | 21 ++++-- .../blockchain_blackball.cpp | 8 ++- src/common/threadpool.cpp | 3 +- src/cryptonote_basic/miner.cpp | 6 +- src/gen_multisig/gen_multisig.cpp | 4 +- src/simplewallet/simplewallet.cpp | 4 +- src/wallet/wallet_rpc_server.cpp | 3 + tests/fuzz/fuzzer.cpp | 4 ++ tests/performance_tests/main.cpp | 8 +-- tests/unit_tests/main.cpp | 4 ++ tests/unit_tests/mlocker.cpp | 69 ++++++++++--------- 16 files changed, 101 insertions(+), 56 deletions(-) diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 0e22a971c..2ccf5b095 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -63,7 +63,8 @@ namespace epee ~async_stdin_reader() { - stop(); + try { stop(); } + catch (...) { /* ignore */ } } #ifdef HAVE_READLINE diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 0b1fe05fa..e9853ee26 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -275,6 +275,9 @@ class async_protocol_handler } virtual ~async_protocol_handler() { + try + { + m_deletion_initiated = true; if(m_connection_initialized) { @@ -288,6 +291,9 @@ class async_protocol_handler CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); MTRACE(m_connection_context << "~async_protocol_handler()"); + + } + catch (...) { /* ignore */ } } bool start_outer_call() diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 2c2efcd82..94744ac21 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -106,7 +106,8 @@ namespace net_utils ~blocked_mode_client() { //profile_tools::local_coast lc("~blocked_mode_client()", 3); - shutdown(); + try { shutdown(); } + catch(...) { /* ignore */ } } inline diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index cd9867ff5..61d853ef4 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -137,7 +137,12 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); el::Helpers::installPreRollOutCallback([filename_base, max_log_files](const char *name, size_t){ std::string rname = generate_log_filename(filename_base.c_str()); - rename(name, rname.c_str()); + int ret = rename(name, rname.c_str()); + if (ret < 0) + { + // can't log a failure, but don't do the file removal below + return; + } if (max_log_files != 0) { std::vector found_files; diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index b438fa543..a4bdad4cf 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -1975,11 +1975,11 @@ void VRegistry::setCategories(const char* categories, bool clear) { m_cached_allowed_categories.clear(); m_categoriesString.clear(); } + if (!categories) + return; if (!m_categoriesString.empty()) m_categoriesString += ","; m_categoriesString += categories; - if (!categories) - return; bool isCat = true; bool isLevel = false; diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index d8f7df5f7..824598f8c 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1145,7 +1145,10 @@ BlockchainLMDB::~BlockchainLMDB() // batch transaction shouldn't be active at this point. If it is, consider it aborted. if (m_batch_active) - batch_abort(); + { + try { batch_abort(); } + catch (...) { /* ignore */ } + } if (m_open) close(); } @@ -3589,7 +3592,9 @@ void BlockchainLMDB::migrate_0_1() throw0(DB_ERROR(lmdb_error("Failed to open a cursor for block_heights: ", result).c_str())); if (!i) { MDB_stat ms; - mdb_stat(txn, m_block_heights, &ms); + result = mdb_stat(txn, m_block_heights, &ms); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to query block_heights table: ", result).c_str())); i = ms.ms_entries; } } @@ -3692,7 +3697,9 @@ void BlockchainLMDB::migrate_0_1() throw0(DB_ERROR(lmdb_error("Failed to open a cursor for block_timestamps: ", result).c_str())); if (!i) { MDB_stat ms; - mdb_stat(txn, m_block_info, &ms); + result = mdb_stat(txn, m_block_info, &ms); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to query block_info table: ", result).c_str())); i = ms.ms_entries; } } @@ -3812,7 +3819,9 @@ void BlockchainLMDB::migrate_0_1() throw0(DB_ERROR(lmdb_error("Failed to open a cursor for spent_keys: ", result).c_str())); if (!i) { MDB_stat ms; - mdb_stat(txn, m_hf_versions, &ms); + result = mdb_stat(txn, m_hf_versions, &ms); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to query hf_versions table: ", result).c_str())); i = ms.ms_entries; } } @@ -3967,7 +3976,9 @@ void BlockchainLMDB::migrate_0_1() throw0(DB_ERROR(lmdb_error("Failed to open a cursor for txs: ", result).c_str())); if (!i) { MDB_stat ms; - mdb_stat(txn, m_txs, &ms); + result = mdb_stat(txn, m_txs, &ms); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to query txs table: ", result).c_str())); i = ms.ms_entries; if (i) { MDB_val_set(pk, "txblk"); diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 1c6e54d10..5eb2acc79 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -401,7 +401,8 @@ static bool for_all_transactions(const std::string &filename, uint64_t &start_id } mdb_cursor_close(cur); - mdb_txn_commit(txn); + dbr = mdb_txn_commit(txn); + if (dbr) throw std::runtime_error("Failed to commit db transaction: " + std::string(mdb_strerror(dbr))); tx_active = false; mdb_dbi_close(env, dbi); mdb_env_close(env); @@ -471,7 +472,8 @@ static uint64_t find_first_diverging_transaction(const std::string &first_filena for (int i = 0; i < 2; ++i) { mdb_cursor_close(cur[i]); - mdb_txn_commit(txn[i]); + dbr = mdb_txn_commit(txn[i]); + if (dbr) throw std::runtime_error("Failed to query transaction: " + std::string(mdb_strerror(dbr))); tx_active[i] = false; mdb_dbi_close(env[i], dbi[i]); mdb_env_close(env[i]); @@ -675,7 +677,7 @@ static uint64_t get_ring_subset_instances(MDB_txn *txn, uint64_t amount, const s uint64_t extra = 0; std::vector subset; subset.reserve(ring.size()); - for (uint64_t mask = 1; mask < (1u << ring.size()) - 1; ++mask) + for (uint64_t mask = 1; mask < (((uint64_t)1) << ring.size()) - 1; ++mask) { subset.resize(0); for (size_t i = 0; i < ring.size(); ++i) diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 6b69e2a12..5ea04a353 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -57,7 +57,8 @@ threadpool::~threadpool() { has_work.notify_all(); } for (size_t i = 0; i(total_hr)/static_cast(m_last_hash_rates.size()); + const auto flags = std::cout.flags(); const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << precision << ENDL; + std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << flags << precision << ENDL; } } m_last_hr_merge_time = misc_utils::get_tick_count(); diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index f11f442bc..69be70e1b 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -167,6 +167,8 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str int main(int argc, char* argv[]) { + TRY_ENTRY(); + po::options_description desc_params(wallet_args::tr("Wallet options")); command_line::add_arg(desc_params, arg_filename_base); command_line::add_arg(desc_params, arg_scheme); @@ -254,5 +256,5 @@ int main(int argc, char* argv[]) return 1; return 0; - //CATCH_ENTRY_L0("main", 1); + CATCH_ENTRY_L0("main", 1); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 06655ed69..7c68de3f3 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -8073,6 +8073,8 @@ void simple_wallet::commit_or_save(std::vector& ptx_ //---------------------------------------------------------------------------------------------------- int main(int argc, char* argv[]) { + TRY_ENTRY(); + #ifdef WIN32 // Activate UTF-8 support for Boost filesystem classes on Windows std::locale::global(boost::locale::generator().generate("")); @@ -8167,5 +8169,5 @@ int main(int argc, char* argv[]) w.deinit(); } return 0; - //CATCH_ENTRY_L0("main", 1); + CATCH_ENTRY_L0("main", 1); } diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 27631187c..5991e0cc2 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3457,6 +3457,8 @@ class t_executor final std::string const t_executor::NAME = "Wallet RPC Daemon"; int main(int argc, char** argv) { + TRY_ENTRY(); + namespace po = boost::program_options; const auto arg_wallet_file = wallet_args::arg_wallet_file(); @@ -3500,4 +3502,5 @@ int main(int argc, char** argv) { } return daemonizer::daemonize(argc, const_cast(argv), t_executor{}, *vm) ? 0 : 1; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/fuzzer.cpp b/tests/fuzz/fuzzer.cpp index 032ff049a..ab14e2b79 100644 --- a/tests/fuzz/fuzzer.cpp +++ b/tests/fuzz/fuzzer.cpp @@ -46,6 +46,8 @@ static int __AFL_LOOP(int) int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer) { + TRY_ENTRY(); + if (argc < 2) { std::cout << "usage: " << argv[0] << " " << "" << std::endl; @@ -69,4 +71,6 @@ int run_fuzzer(int argc, const char **argv, Fuzzer &fuzzer) } return 0; + + CATCH_ENTRY_L0("run_fuzzer", 1); } diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 7c5135c65..87a1573c2 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -75,10 +75,10 @@ int main(int argc, char** argv) const command_line::arg_descriptor arg_verbose = { "verbose", "Verbose output", false }; const command_line::arg_descriptor arg_stats = { "stats", "Including statistics (min/median)", false }; const command_line::arg_descriptor arg_loop_multiplier = { "loop-multiplier", "Run for that many times more loops", 1 }; - command_line::add_arg(desc_options, arg_filter, ""); - command_line::add_arg(desc_options, arg_verbose, ""); - command_line::add_arg(desc_options, arg_stats, ""); - command_line::add_arg(desc_options, arg_loop_multiplier, ""); + command_line::add_arg(desc_options, arg_filter); + command_line::add_arg(desc_options, arg_verbose); + command_line::add_arg(desc_options, arg_stats); + command_line::add_arg(desc_options, arg_loop_multiplier); po::variables_map vm; bool r = command_line::handle_error_helper(desc_options, [&]() diff --git a/tests/unit_tests/main.cpp b/tests/unit_tests/main.cpp index 13b62cbb4..f7251a09e 100644 --- a/tests/unit_tests/main.cpp +++ b/tests/unit_tests/main.cpp @@ -53,6 +53,8 @@ namespace cryptonote { template class t_cryptonote_protocol_handler data{new char[8 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data), 1); - epee::mlocker *m1 = new epee::mlocker(BASE(data) + 2 * page_size, 1); - epee::mlocker *m2 = new epee::mlocker(BASE(data) + 3 * page_size, 1); + std::shared_ptr m0{new epee::mlocker(BASE(data), 1)}; + std::shared_ptr m1{new epee::mlocker(BASE(data) + 2 * page_size, 1)}; + std::shared_ptr m2{new epee::mlocker(BASE(data) + 3 * page_size, 1)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 3); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 3); - delete m0; - delete m1; - delete m2; + m0 = NULL; + m1 = NULL; + m2 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -65,14 +65,14 @@ TEST(mlocker, distinct_full_page) const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[8 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data), page_size); - epee::mlocker *m1 = new epee::mlocker(BASE(data) + 2 * page_size, page_size); - epee::mlocker *m2 = new epee::mlocker(BASE(data) + 3 * page_size, page_size); + std::shared_ptr m0{new epee::mlocker(BASE(data), page_size)}; + std::shared_ptr m1{new epee::mlocker(BASE(data) + 2 * page_size, page_size)}; + std::shared_ptr m2{new epee::mlocker(BASE(data) + 3 * page_size, page_size)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 3); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 3); - delete m0; - delete m1; - delete m2; + m0 = NULL; + m1 = NULL; + m2 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -84,16 +84,16 @@ TEST(mlocker, identical) const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[8 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data) + page_size, 32); - epee::mlocker *m1 = new epee::mlocker(BASE(data) + page_size, 32); - epee::mlocker *m2 = new epee::mlocker(BASE(data) + page_size, 32); + std::shared_ptr m0{new epee::mlocker(BASE(data) + page_size, 32)}; + std::shared_ptr m1{new epee::mlocker(BASE(data) + page_size, 32)}; + std::shared_ptr m2{new epee::mlocker(BASE(data) + page_size, 32)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 3); - delete m1; + m1 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 2); - delete m0; - delete m2; + m0 = NULL; + m2 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -105,16 +105,16 @@ TEST(mlocker, overlapping_small) const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[8 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data), 32); - epee::mlocker *m1 = new epee::mlocker(BASE(data) + 16, 32); - epee::mlocker *m2 = new epee::mlocker(BASE(data) + 8, 32); + std::shared_ptr m0{new epee::mlocker(BASE(data), 32)}; + std::shared_ptr m1{new epee::mlocker(BASE(data) + 16, 32)}; + std::shared_ptr m2{new epee::mlocker(BASE(data) + 8, 32)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 3); - delete m1; + m1 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 2); - delete m2; - delete m0; + m2 = NULL; + m0 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -126,16 +126,16 @@ TEST(mlocker, multi_page) const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[8 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data) + page_size, page_size * 3); + std::shared_ptr m0{new epee::mlocker(BASE(data) + page_size, page_size * 3)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 3); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 1); - epee::mlocker *m1 = new epee::mlocker(BASE(data) + page_size * 7, page_size); + std::shared_ptr m1{new epee::mlocker(BASE(data) + page_size * 7, page_size)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 4); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 2); - delete m0; + m0 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 1); - delete m1; + m1 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -147,10 +147,10 @@ TEST(mlocker, cross_page) const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[2 * page_size]}; - epee::mlocker *m0 = new epee::mlocker(BASE(data) + page_size - 1, 2); + std::shared_ptr m0{new epee::mlocker(BASE(data) + page_size - 1, 2)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 2); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 1); - delete m0; + m0 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } @@ -158,21 +158,22 @@ TEST(mlocker, cross_page) TEST(mlocker, redundant) { const size_t page_size = epee::mlocker::get_page_size(); + ASSERT_TRUE(page_size > 0); const size_t base_pages = epee::mlocker::get_num_locked_pages(); const size_t base_objects = epee::mlocker::get_num_locked_objects(); std::unique_ptr data{new char[2 * page_size]}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); - epee::mlocker *m0 = new epee::mlocker(BASE(data), 32); + std::shared_ptr m0{new epee::mlocker(BASE(data), 32)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 1); - epee::mlocker *m1 = new epee::mlocker(BASE(data), 32); + std::shared_ptr m1{new epee::mlocker(BASE(data), 32)}; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 2); - delete m1; + m1 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 1); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 1); - delete m0; + m0 = NULL; ASSERT_EQ(epee::mlocker::get_num_locked_pages(), base_pages + 0); ASSERT_EQ(epee::mlocker::get_num_locked_objects(), base_objects + 0); } From 4a2664f743bcbfe47b15e20c22c966a54f91090e Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:17:21 +0200 Subject: [PATCH 0027/1007] Merge pull request #4461 7dd11711 wallet2: fix transfers between subaddresses hitting the sanity check (moneromooo-monero) --- src/wallet/wallet2.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 95474ce34..a60874af9 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1707,10 +1707,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } // remove change sent to the spending subaddress account from the list of received funds + uint64_t sub_change = 0; for (auto i = tx_money_got_in_outs.begin(); i != tx_money_got_in_outs.end();) { if (subaddr_account && i->first.major == *subaddr_account) + { + sub_change += i->second; i = tx_money_got_in_outs.erase(i); + } else ++i; } @@ -1755,7 +1759,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote } } - uint64_t total_received_2 = 0; + uint64_t total_received_2 = sub_change; for (const auto& i : tx_money_got_in_outs) total_received_2 += i.second; if (total_received_1 != total_received_2) From 83d8f03c2338e865ce72f4e2d46d43a48530ab10 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Sat, 29 Sep 2018 22:18:08 +0200 Subject: [PATCH 0028/1007] Merge pull request #4333 73403004 add --block-notify to monerod and --tx-notify to monero-wallet-{cli,rpc} (moneromooo-monero) --- src/common/CMakeLists.txt | 4 ++ src/common/exec.cpp | 88 +++++++++++++++++++++++++ src/common/exec.h | 36 ++++++++++ src/common/notify.cpp | 61 +++++++++++++++++ src/common/notify.h | 49 ++++++++++++++ src/cryptonote_core/blockchain.cpp | 5 ++ src/cryptonote_core/blockchain.h | 11 ++++ src/cryptonote_core/cryptonote_core.cpp | 17 +++++ src/wallet/wallet2.cpp | 24 +++++++ src/wallet/wallet2.h | 5 ++ 10 files changed, 300 insertions(+) create mode 100644 src/common/exec.cpp create mode 100644 src/common/exec.h create mode 100644 src/common/notify.cpp create mode 100644 src/common/notify.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e89dbbc24..9b83f149f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -34,9 +34,11 @@ set(common_sources dns_utils.cpp download.cpp error.cpp + exec.cpp expect.cpp util.cpp i18n.cpp + notify.cpp password.cpp perf_timer.cpp threadpool.cpp @@ -58,9 +60,11 @@ set(common_private_headers dns_utils.h download.h error.h + exec.h expect.h http_connection.h int-util.h + notify.h pod-class.h rpc_client.h scoped_message_writer.h diff --git a/src/common/exec.cpp b/src/common/exec.cpp new file mode 100644 index 000000000..41b8f1378 --- /dev/null +++ b/src/common/exec.cpp @@ -0,0 +1,88 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include +#include +#include +#include + +#include "misc_log_ex.h" +#include "exec.h" + +namespace tools +{ + +int exec(const char *filename, char * const argv[], bool wait) +{ + pid_t pid = fork(); + if (pid < 0) + { + MERROR("Error forking: " << strerror(errno)); + return -1; + } + + // child + if (pid == 0) + { + char *envp[] = {NULL}; + execve(filename, argv, envp); + MERROR("Failed to execve: " << strerror(errno)); + return -1; + } + + // parent + if (pid > 0) + { + if (!wait) + return 0; + + while (1) + { + int wstatus = 0; + pid_t w = waitpid(pid, &wstatus, WUNTRACED | WCONTINUED); + if (w < 0) { + MERROR("Error waiting for child: " << strerror(errno)); + return -1; + } + if (WIFEXITED(wstatus)) + { + MINFO("Child exited with " << WEXITSTATUS(wstatus)); + return WEXITSTATUS(wstatus); + } + if (WIFSIGNALED(wstatus)) + { + MINFO("Child killed by " << WEXITSTATUS(wstatus)); + return WEXITSTATUS(wstatus); + } + } + } + MERROR("Secret passage found"); + return -1; +} + +} diff --git a/src/common/exec.h b/src/common/exec.h new file mode 100644 index 000000000..4d2037798 --- /dev/null +++ b/src/common/exec.h @@ -0,0 +1,36 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#pragma once + +namespace tools +{ + +int exec(const char *filename, char * const argv[], bool wait); + +} diff --git a/src/common/notify.cpp b/src/common/notify.cpp new file mode 100644 index 000000000..b7869ad84 --- /dev/null +++ b/src/common/notify.cpp @@ -0,0 +1,61 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include +#include "misc_log_ex.h" +#include "file_io_utils.h" +#include "exec.h" +#include "notify.h" + +namespace tools +{ + +Notify::Notify(const char *spec) +{ + CHECK_AND_ASSERT_THROW_MES(spec, "Null spec"); + + boost::split(args, spec, boost::is_any_of(" ")); + CHECK_AND_ASSERT_THROW_MES(args.size() > 0, "Failed to parse spec"); + filename = args[0]; + CHECK_AND_ASSERT_THROW_MES(epee::file_io_utils::is_file_exist(filename), "File not found: " << filename); +} + +int Notify::notify(const char *parameter) +{ + std::vector margs = args; + for (std::string &s: margs) + boost::replace_all(s, "%s", parameter); + + char **cargs = (char**)alloca(sizeof(char*) * (margs.size() + 1)); + for (size_t n = 0; n < margs.size(); ++n) + cargs[n] = (char*)margs[n].c_str(); + cargs[margs.size()] = NULL; + return tools::exec(filename.c_str(), cargs, false); +} + +} diff --git a/src/common/notify.h b/src/common/notify.h new file mode 100644 index 000000000..81aacebb0 --- /dev/null +++ b/src/common/notify.h @@ -0,0 +1,49 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#pragma once + +#include +#include + +namespace tools +{ + +class Notify +{ +public: + Notify(const char *spec); + + int notify(const char *parameter); + +private: + std::string filename; + std::vector args; +}; + +} diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0e175cdbe..fb4dcef7c 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -52,6 +52,7 @@ #include "cryptonote_core.h" #include "ringct/rctSigs.h" #include "common/perf_timer.h" +#include "common/notify.h" #if defined(PER_BLOCK_CHECKPOINT) #include "blocks/blocks.h" #endif @@ -3552,6 +3553,10 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& get_difficulty_for_next_block(); // just to cache it invalidate_block_template_cache(); + std::shared_ptr block_notify = m_block_notify; + if (block_notify) + block_notify->notify(epee::string_tools::pod_to_hex(id).c_str()); + return true; } //------------------------------------------------------------------ diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 50ceccd0f..ab66fac8b 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -55,6 +55,8 @@ #include "cryptonote_basic/hardfork.h" #include "blockchain_db/blockchain_db.h" +namespace tools { class Notify; } + namespace cryptonote { class tx_memory_pool; @@ -705,6 +707,13 @@ namespace cryptonote void set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint64_t sync_threshold, blockchain_db_sync_mode sync_mode, bool fast_sync); + /** + * @brief sets a block notify object to call for every new block + * + * @param notify the notify object to cal at every new block + */ + void set_block_notify(const std::shared_ptr ¬ify) { m_block_notify = notify; } + /** * @brief Put DB in safe sync mode */ @@ -1032,6 +1041,8 @@ namespace cryptonote uint64_t m_btc_expected_reward; bool m_btc_valid; + std::shared_ptr m_block_notify; + /** * @brief collects the keys for all outputs being "spent" as an input * diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 3e3d3c19c..69e3c708b 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -53,6 +53,7 @@ using namespace epee; #include "ringct/rctTypes.h" #include "blockchain_db/blockchain_db.h" #include "ringct/rctSigs.h" +#include "common/notify.h" #include "version.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -167,6 +168,11 @@ namespace cryptonote , "Set maximum txpool weight in bytes." , DEFAULT_TXPOOL_MAX_WEIGHT }; + static const command_line::arg_descriptor arg_block_notify = { + "block-notify" + , "Run a program for each new block, '%s' will be replaced by the block hash" + , "" + }; //----------------------------------------------------------------------------------------------- core::core(i_cryptonote_protocol* pprotocol): @@ -276,6 +282,7 @@ namespace cryptonote command_line::add_arg(desc, arg_offline); command_line::add_arg(desc, arg_disable_dns_checkpoints); command_line::add_arg(desc, arg_max_txpool_weight); + command_line::add_arg(desc, arg_block_notify); miner::init_options(desc); BlockchainDB::init_options(desc); @@ -545,6 +552,16 @@ namespace cryptonote m_blockchain_storage.set_user_options(blocks_threads, sync_on_blocks, sync_threshold, sync_mode, fast_sync); + try + { + if (!command_line::is_arg_defaulted(vm, arg_block_notify)) + m_blockchain_storage.set_block_notify(std::shared_ptr(new tools::Notify(command_line::get_arg(vm, arg_block_notify).c_str()))); + } + catch (const std::exception &e) + { + MERROR("Failed to parse block notify spec"); + } + const std::pair regtest_hard_forks[3] = {std::make_pair(1, 0), std::make_pair(Blockchain::get_hard_fork_heights(MAINNET).back().version, 1), std::make_pair(0, 0)}; const cryptonote::test_options regtest_test_options = { regtest_hard_forks diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a60874af9..299b4afeb 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -66,6 +66,7 @@ using namespace epee; #include "memwipe.h" #include "common/base58.h" #include "common/dns_utils.h" +#include "common/notify.h" #include "ringct/rctSigs.h" #include "ringdb.h" @@ -162,6 +163,7 @@ struct options { }; const command_line::arg_descriptor kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1}; const command_line::arg_descriptor hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""}; + const command_line::arg_descriptor tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" }; }; void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file) @@ -268,6 +270,17 @@ std::unique_ptr make_basic(const boost::program_options::variabl boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir); wallet->set_ring_database(ringdb_path.string()); wallet->device_name(device_name); + + try + { + if (!command_line::is_arg_defaulted(vm, opts.tx_notify)) + wallet->set_tx_notify(std::shared_ptr(new tools::Notify(command_line::get_arg(vm, opts.tx_notify).c_str()))); + } + catch (const std::exception &e) + { + MERROR("Failed to parse tx notify spec"); + } + return wallet; } @@ -838,6 +851,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.shared_ringdb_dir); command_line::add_arg(desc_params, opts.kdf_rounds); command_line::add_arg(desc_params, opts.hw_device); + command_line::add_arg(desc_params, opts.tx_notify); } std::unique_ptr wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter) @@ -1328,6 +1342,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::vector outs; std::unordered_map tx_money_got_in_outs; // per receiving subaddress index crypto::public_key tx_pub_key = null_pkey; + bool notify = false; std::vector local_tx_extra_fields; if (tx_cache_data.tx_extra_fields.empty()) @@ -1567,6 +1582,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index); } total_received_1 += amount; + notify = true; } else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount) { @@ -1634,6 +1650,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index); } total_received_1 += extra_amount; + notify = true; } } } @@ -1794,6 +1811,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote LOG_PRINT_L2("Payment found in " << (pool ? "pool" : "block") << ": " << payment_id << " / " << payment.m_tx_hash << " / " << payment.m_amount); } } + + if (notify) + { + std::shared_ptr tx_notify = m_tx_notify; + if (tx_notify) + tx_notify->notify(epee::string_tools::pod_to_hex(txid).c_str()); + } } //---------------------------------------------------------------------------------------------------- void wallet2::process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index db1ac7e42..497dd486f 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -68,6 +68,7 @@ namespace tools { class ringdb; class wallet2; + class Notify; class wallet_keys_unlocker { @@ -1176,6 +1177,8 @@ namespace tools void change_password(const std::string &filename, const epee::wipeable_string &original_password, const epee::wipeable_string &new_password); + void set_tx_notify(const std::shared_ptr ¬ify) { m_tx_notify = notify; } + private: /*! * \brief Stores wallet information to wallet file. @@ -1353,6 +1356,8 @@ namespace tools boost::optional m_encrypt_keys_after_refresh; bool m_unattended; + + std::shared_ptr m_tx_notify; }; } BOOST_CLASS_VERSION(tools::wallet2, 25) From 31559e6ad251437f8c1eb2c5624bd19e972d9534 Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Sat, 29 Sep 2018 23:11:59 +0200 Subject: [PATCH 0029/1007] Update unbound submodule to 7f23967 Fixes building in MSYS2 with openssl 1.1.1 --- external/unbound | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/unbound b/external/unbound index d3724dfa5..7f2396795 160000 --- a/external/unbound +++ b/external/unbound @@ -1 +1 @@ -Subproject commit d3724dfa553429d368c27aef160f02f5e8b8075f +Subproject commit 7f23967954736dcaa366806b9eaba7e2bdfede11 From 6da36ea05745f2ca8821d3b1d3e185e0ad0c9c60 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 30 Sep 2018 08:10:30 +0000 Subject: [PATCH 0030/1007] wallet2_api: blackball/unblackball now take two parameters amount and offset (instead of pubkey) --- src/wallet/api/wallet.cpp | 22 ++++++++++++++++++++++ src/wallet/api/wallet.h | 3 ++- src/wallet/api/wallet2_api.h | 5 ++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 3d4e981ea..236928348 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2146,6 +2146,28 @@ bool WalletImpl::blackballOutputs(const std::vector &outputs, bool return true; } +bool WalletImpl::blackballOutput(const std::string &amount, const std::string &offset) +{ + uint64_t raw_amount, raw_offset; + if (!epee::string_tools::get_xtype_from_string(raw_amount, amount)) + { + setStatusError(tr("Failed to parse output amount")); + return false; + } + if (!epee::string_tools::get_xtype_from_string(raw_offset, offset)) + { + setStatusError(tr("Failed to parse output offset")); + return false; + } + bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset)); + if (!ret) + { + setStatusError(tr("Failed to blackball output")); + return false; + } + return true; +} + bool WalletImpl::unblackballOutput(const std::string &amount, const std::string &offset) { uint64_t raw_amount, raw_offset; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 5963a7607..8e2af347d 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -182,7 +182,8 @@ class WalletImpl : public Wallet virtual std::string getDefaultDataDir() const override; virtual bool lightWalletLogin(bool &isNewWallet) const override; virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override; - virtual bool blackballOutputs(const std::vector &pubkeys, bool add) override; + virtual bool blackballOutputs(const std::vector &outputs, bool add) override; + virtual bool blackballOutput(const std::string &amount, const std::string &offset) override; virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override; virtual bool getRing(const std::string &key_image, std::vector &ring) const override; virtual bool getRings(const std::string &txid, std::vector>> &rings) const override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index e0d491705..68ea26262 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -881,7 +881,10 @@ struct Wallet virtual bool rescanSpent() = 0; //! blackballs a set of outputs - virtual bool blackballOutputs(const std::vector &pubkeys, bool add) = 0; + virtual bool blackballOutputs(const std::vector &outputs, bool add) = 0; + + //! blackballs an output + virtual bool blackballOutput(const std::string &amount, const std::string &offset) = 0; //! unblackballs an output virtual bool unblackballOutput(const std::string &amount, const std::string &offset) = 0; From fa9e54b6eec065ece76312cc3f1abff2424fdc42 Mon Sep 17 00:00:00 2001 From: xiphon Date: Sun, 30 Sep 2018 02:42:22 +0000 Subject: [PATCH 0031/1007] build: fix gcc false positive 'stringop-overflow' warning --- src/cryptonote_core/cryptonote_tx_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index fb2af9ceb..4bc33b56b 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -127,7 +127,7 @@ namespace cryptonote out_amounts[1] += out_amounts[0]; for (size_t n = 1; n < out_amounts.size(); ++n) out_amounts[n - 1] = out_amounts[n]; - out_amounts.resize(out_amounts.size() - 1); + out_amounts.pop_back(); } } else From 98c922582346850faa315d8d1f95a0a9257ccbc5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 1 Oct 2018 09:13:22 +0000 Subject: [PATCH 0032/1007] unit_tests: add a notifier test --- tests/unit_tests/CMakeLists.txt | 7 +++- tests/unit_tests/notify.cpp | 57 ++++++++++++++++++++++++++++++ tests/unit_tests/test_notifier.cpp | 54 ++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/notify.cpp create mode 100644 tests/unit_tests/test_notifier.cpp diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index d6bcbde46..e248ed965 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -61,6 +61,7 @@ set(unit_tests_sources mul_div.cpp multiexp.cpp multisig.cpp + notify.cpp parse_amount.cpp random.cpp serialization.cpp @@ -122,4 +123,8 @@ SET_PROPERTY(SOURCE memwipe.cpp PROPERTY COMPILE_FLAGS -Ofast) add_test( NAME unit_tests - COMMAND unit_tests --data-dir "${TEST_DATA_DIR}") + COMMAND unit_tests --data-dir "${TEST_DATA_DIR} --binary-dir ${CMAKE_BINARY_DIR}") + +add_executable(test_notifier test_notifier.cpp) +target_link_libraries(test_notifier ${EXTRA_LIBRARIES}) +set_property(TARGET test_notifier PROPERTY FOLDER "tests") diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp new file mode 100644 index 000000000..d6811c6bd --- /dev/null +++ b/tests/unit_tests/notify.cpp @@ -0,0 +1,57 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include "gtest/gtest.h" + +#include + +#include "misc_language.h" +#include "string_tools.h" +#include "file_io_utils.h" +#include "common/notify.h" + +TEST(notify, works) +{ + char name_template[] = "/tmp/monero-notify-unit-test-XXXXXX"; + int fd = mkstemp(name_template); + ASSERT_TRUE(fd >= 0); + close(fd); + + const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier " + name_template + " %s"; + + tools::Notify notify(spec.c_str()); + notify.notify("1111111111111111111111111111111111111111111111111111111111111111"); + + epee::misc_utils::sleep_no_w(100); + + std::string s; + ASSERT_TRUE(epee::file_io_utils::load_file_to_string(name_template, s)); + ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111"); + + boost::filesystem::remove(name_template); +} diff --git a/tests/unit_tests/test_notifier.cpp b/tests/unit_tests/test_notifier.cpp new file mode 100644 index 000000000..7fd9809c5 --- /dev/null +++ b/tests/unit_tests/test_notifier.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + if (argc < 3) + { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + const char *filename = argv[1]; + const char *hash = argv[2]; + + FILE *f = fopen(filename, "a+"); + if (!f) + { + fprintf(stderr, "error opening file %s: %s\n", filename, strerror(errno)); + return 1; + } + fprintf(f, "%s", hash); + fclose(f); + + return 0; +} From 25e5890d37a1b243d4b8aadb45743d715bd4d0f9 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 1 Oct 2018 11:18:50 +0000 Subject: [PATCH 0033/1007] wallet: fix --generate-from-json using wrong password --- src/common/password.cpp | 4 ++++ src/common/password.h | 1 + src/simplewallet/simplewallet.cpp | 4 +++- src/wallet/wallet2.cpp | 13 +++++++++---- src/wallet/wallet2.h | 2 +- src/wallet/wallet_rpc_server.cpp | 3 ++- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/common/password.cpp b/src/common/password.cpp index 5671c4a4e..b32bedae2 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -221,6 +221,10 @@ namespace tools : m_password(std::move(password)) { } + password_container::password_container(const epee::wipeable_string& password) noexcept + : m_password(password) + { + } password_container::~password_container() noexcept { diff --git a/src/common/password.h b/src/common/password.h index 529881e40..beb98283b 100644 --- a/src/common/password.h +++ b/src/common/password.h @@ -47,6 +47,7 @@ namespace tools //! `password` is used as password password_container(std::string&& password) noexcept; + password_container(const epee::wipeable_string& password) noexcept; //! \return A password from stdin TTY prompt or `std::cin` pipe. static boost::optional prompt(bool verify, const char *mesage = "Password", bool hide_input = true); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 7c68de3f3..90f8535d7 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3275,7 +3275,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) { try { - m_wallet = tools::wallet2::make_from_json(vm, false, m_generate_from_json, password_prompter); + auto rc = tools::wallet2::make_from_json(vm, false, m_generate_from_json, password_prompter); + m_wallet = std::move(rc.first); + password = rc.second.password(); m_wallet_file = m_wallet->path(); } catch (const std::exception &e) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 299b4afeb..b657fcd9f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -313,7 +313,7 @@ boost::optional get_password(const boost::program_opt return password_prompter(verify ? tr("Enter a new password for the wallet") : tr("Wallet password"), verify); } -std::unique_ptr generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, bool unattended, const options& opts, const std::function(const char *, bool)> &password_prompter) +std::pair, tools::password_container> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, bool unattended, const options& opts, const std::function(const char *, bool)> &password_prompter) { const bool testnet = command_line::get_arg(vm, opts.testnet); const bool stagenet = command_line::get_arg(vm, opts.stagenet); @@ -323,6 +323,7 @@ std::unique_ptr generate_from_json(const std::string& json_file, false. Gcc will coerce this into unique_ptr(nullptr), but clang correctly fails. This large wrapper is for the use of that macro */ std::unique_ptr wallet; + epee::wipeable_string password; const auto do_generate = [&]() -> bool { std::string buf; if (!epee::file_io_utils::load_file_to_string(json_file, buf)) { @@ -460,10 +461,12 @@ std::unique_ptr generate_from_json(const std::string& json_file, if (!field_seed.empty()) { wallet->generate(field_filename, field_password, recovery_key, recover, false, create_address_file); + password = field_password; } else if (field_viewkey.empty() && !field_spendkey.empty()) { wallet->generate(field_filename, field_password, spendkey, recover, false, create_address_file); + password = field_password; } else { @@ -490,6 +493,7 @@ std::unique_ptr generate_from_json(const std::string& json_file, THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Address must be specified in order to create watch-only wallet")); } wallet->generate(field_filename, field_password, address, viewkey, create_address_file); + password = field_password; } else { @@ -497,6 +501,7 @@ std::unique_ptr generate_from_json(const std::string& json_file, THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key")); } wallet->generate(field_filename, field_password, address, spendkey, viewkey, create_address_file); + password = field_password; } } } @@ -509,9 +514,9 @@ std::unique_ptr generate_from_json(const std::string& json_file, if (do_generate()) { - return wallet; + return {std::move(wallet), tools::password_container(password)}; } - return nullptr; + return {nullptr, tools::password_container{}}; } static void throw_on_rpc_response_error(const boost::optional &status, const char *method) @@ -854,7 +859,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.tx_notify); } -std::unique_ptr wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter) +std::pair, tools::password_container> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter) { const options opts{}; return generate_from_json(json_file, vm, unattended, opts, password_prompter); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 497dd486f..7857f36f1 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -177,7 +177,7 @@ namespace tools static void init_options(boost::program_options::options_description& desc_params); //! Uses stdin and stdout. Returns a wallet2 if no errors. - static std::unique_ptr make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter); + static std::pair, password_container> make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function(const char *, bool)> &password_prompter); //! Uses stdin and stdout. Returns a wallet2 and password for `wallet_file` if no errors. static std::pair, password_container> diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5991e0cc2..8b15359cc 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3352,7 +3352,8 @@ class t_daemon { try { - wal = tools::wallet2::make_from_json(vm, true, from_json, password_prompt); + auto rc = tools::wallet2::make_from_json(vm, true, from_json, password_prompt); + wal = std::move(rc.first); } catch (const std::exception &e) { From 2c74b1a1c42d2763ce9ad773f96309546c9dbbe1 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 1 Oct 2018 14:46:32 +0000 Subject: [PATCH 0034/1007] wallet_rpc_server: include all transfer records for a txid Since subaddresses were added, a tx can now create more than one payment --- src/wallet/wallet_rpc_server.cpp | 22 +++++++++++++------- src/wallet/wallet_rpc_server_commands_defs.h | 4 +++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5991e0cc2..cd519a815 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2173,8 +2173,8 @@ namespace tools for (std::list>::const_iterator i = payments.begin(); i != payments.end(); ++i) { if (i->second.m_tx_hash == txid) { - fill_transfer_entry(res.transfer, i->second.m_tx_hash, i->first, i->second); - return true; + res.transfers.resize(res.transfers.size() + 1); + fill_transfer_entry(res.transfers.back(), i->second.m_tx_hash, i->first, i->second); } } @@ -2183,8 +2183,8 @@ namespace tools for (std::list>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) { if (i->first == txid) { - fill_transfer_entry(res.transfer, i->first, i->second); - return true; + res.transfers.resize(res.transfers.size() + 1); + fill_transfer_entry(res.transfers.back(), i->first, i->second); } } @@ -2193,8 +2193,8 @@ namespace tools for (std::list>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { if (i->first == txid) { - fill_transfer_entry(res.transfer, i->first, i->second); - return true; + res.transfers.resize(res.transfers.size() + 1); + fill_transfer_entry(res.transfers.back(), i->first, i->second); } } @@ -2205,11 +2205,17 @@ namespace tools for (std::list>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) { if (i->second.m_pd.m_tx_hash == txid) { - fill_transfer_entry(res.transfer, i->first, i->second); - return true; + res.transfers.resize(res.transfers.size() + 1); + fill_transfer_entry(res.transfers.back(), i->first, i->second); } } + if (!res.transfers.empty()) + { + res.transfer = res.transfers.front(); // backward compat + return true; + } + er.code = WALLET_RPC_ERROR_CODE_WRONG_TXID; er.message = "Transaction not found."; return false; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 81ea22928..e46745339 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 3 +#define WALLET_RPC_VERSION_MINOR 4 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -1399,9 +1399,11 @@ namespace wallet_rpc struct response { transfer_entry transfer; + std::list transfers; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(transfer); + KV_SERIALIZE(transfers); END_KV_SERIALIZE_MAP() }; }; From 9f3963e8235826704b7bc6ef9e3b90613a72e16c Mon Sep 17 00:00:00 2001 From: naughtyfox Date: Thu, 12 Jul 2018 12:55:52 +0300 Subject: [PATCH 0035/1007] Arbitrary M/N multisig schemes: * support in wallet2 * support in monero-wallet-cli * support in monero-wallet-rpc * support in wallet api * support in monero-gen-trusted-multisig * unit tests for multisig wallets creation --- src/gen_multisig/gen_multisig.cpp | 15 +- src/multisig/multisig.cpp | 44 +- src/multisig/multisig.h | 24 +- src/simplewallet/simplewallet.cpp | 61 ++- src/simplewallet/simplewallet.h | 1 + src/wallet/api/wallet.cpp | 14 + src/wallet/api/wallet.h | 1 + src/wallet/api/wallet2_api.h | 6 + src/wallet/wallet2.cpp | 402 ++++++++++++++----- src/wallet/wallet2.h | 17 + src/wallet/wallet_rpc_server.cpp | 51 ++- src/wallet/wallet_rpc_server.h | 2 + src/wallet/wallet_rpc_server_commands_defs.h | 25 ++ tests/core_tests/chaingen.h | 2 +- tests/unit_tests/multisig.cpp | 179 ++++----- 15 files changed, 625 insertions(+), 219 deletions(-) diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index f11f442bc..9749ba13f 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -130,8 +130,8 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str ss << " " << name << std::endl; } - // finalize step if needed - if (!extra_info[0].empty()) + //exchange keys unless exchange_multisig_keys returns no extra info + while (!extra_info[0].empty()) { std::unordered_set pkeys; std::vector signers(total); @@ -145,11 +145,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str } for (size_t n = 0; n < total; ++n) { - if (!wallets[n]->finalize_multisig(pwd_container->password(), pkeys, signers)) - { - tools::fail_msg_writer() << genms::tr("Error finalizing multisig"); - return false; - } + extra_info[n] = wallets[n]->exchange_multisig_keys(pwd_container->password(), pkeys, signers); } } @@ -244,11 +240,6 @@ int main(int argc, char* argv[]) return 1; } - if (threshold != total-1 && threshold != total) - { - tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported"); - return 1; - } bool create_address_file = command_line::get_arg(*vm, arg_create_address_file); if (!generate_multisig(threshold, total, basename, testnet ? TESTNET : stagenet ? STAGENET : MAINNET, create_address_file)) return 1; diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index a0a788b7d..33d0a312f 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -84,6 +84,43 @@ namespace cryptonote } } //----------------------------------------------------------------- + std::vector generate_multisig_derivations(const account_keys &keys, const std::vector &derivations) + { + std::vector multisig_keys; + crypto::secret_key blinded_skey = get_multisig_blinded_secret_key(keys.m_spend_secret_key); + for (const auto &k: derivations) + { + rct::key d = rct::scalarmultKey(rct::pk2rct(k), rct::sk2rct(blinded_skey)); + multisig_keys.push_back(rct::rct2pk(d)); + } + + return multisig_keys; + } + //----------------------------------------------------------------- + crypto::secret_key calculate_multisig_signer_key(const std::vector& multisig_keys) + { + rct::key secret_key = rct::zero(); + for (const auto &k: multisig_keys) + { + sc_add(secret_key.bytes, secret_key.bytes, (const unsigned char*)k.data); + } + + return rct::rct2sk(secret_key); + } + //----------------------------------------------------------------- + std::vector calculate_multisig_keys(const std::vector& derivations) + { + std::vector multisig_keys; + multisig_keys.reserve(derivations.size()); + + for (const auto &k: derivations) + { + multisig_keys.emplace_back(get_multisig_blinded_secret_key(rct::rct2sk(rct::pk2rct(k)))); + } + + return multisig_keys; + } + //----------------------------------------------------------------- crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector &skeys) { rct::key view_skey = rct::sk2rct(get_multisig_blinded_secret_key(skey)); @@ -92,7 +129,7 @@ namespace cryptonote return rct::rct2sk(view_skey); } //----------------------------------------------------------------- - crypto::public_key generate_multisig_N1_N_spend_public_key(const std::vector &pkeys) + crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector &pkeys) { rct::key spend_public_key = rct::identity(); for (const auto &pk: pkeys) @@ -141,4 +178,9 @@ namespace cryptonote return true; } //----------------------------------------------------------------- + uint32_t multisig_rounds_required(uint32_t participants, uint32_t threshold) + { + CHECK_AND_ASSERT_THROW_MES(participants >= threshold, "participants must be greater or equal than threshold"); + return participants - threshold + 1; + } } diff --git a/src/multisig/multisig.h b/src/multisig/multisig.h index f95611441..93a756812 100644 --- a/src/multisig/multisig.h +++ b/src/multisig/multisig.h @@ -41,9 +41,31 @@ namespace cryptonote crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key); void generate_multisig_N_N(const account_keys &keys, const std::vector &spend_keys, std::vector &multisig_keys, rct::key &spend_skey, rct::key &spend_pkey); void generate_multisig_N1_N(const account_keys &keys, const std::vector &spend_keys, std::vector &multisig_keys, rct::key &spend_skey, rct::key &spend_pkey); + /** + * @brief generate_multisig_derivations performs common DH key derivation. + * Each middle round in M/N scheme is DH exchange of public multisig keys of other participants multiplied by secret spend key of current participant. + * this functions does the following: new multisig key = secret spend * public multisig key + * @param keys - current wallet's keys + * @param derivations - public multisig keys of other participants + * @return new public multisig keys derived from previous round. This data needs to be exchange with other participants + */ + std::vector generate_multisig_derivations(const account_keys &keys, const std::vector &derivations); + crypto::secret_key calculate_multisig_signer_key(const std::vector& derivations); + /** + * @brief calculate_multisig_keys. Calculates secret multisig keys from others' participants ones as follows: mi = H(Mi) + * @param derivations - others' participants public multisig keys. + * @return vector of current wallet's multisig secret keys + */ + std::vector calculate_multisig_keys(const std::vector& derivations); crypto::secret_key generate_multisig_view_secret_key(const crypto::secret_key &skey, const std::vector &skeys); - crypto::public_key generate_multisig_N1_N_spend_public_key(const std::vector &pkeys); + /** + * @brief generate_multisig_M_N_spend_public_key calculates multisig wallet's spend public key by summing all of public multisig keys + * @param pkeys unique public multisig keys + * @return multisig wallet's spend public key + */ + crypto::public_key generate_multisig_M_N_spend_public_key(const std::vector &pkeys); bool generate_multisig_key_image(const account_keys &keys, size_t multisig_key_index, const crypto::public_key& out_key, crypto::key_image& ki); void generate_multisig_LR(const crypto::public_key pkey, const crypto::secret_key &k, crypto::public_key &L, crypto::public_key &R); bool generate_multisig_composite_key_image(const account_keys &keys, const std::unordered_map& subaddresses, const crypto::public_key& out_key, const crypto::public_key &tx_public_key, const std::vector& additional_tx_public_keys, size_t real_output_index, const std::vector &pkis, crypto::key_image &ki); + uint32_t multisig_rounds_required(uint32_t participants, uint32_t threshold); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 302d2a999..cf6f64173 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -968,7 +968,7 @@ bool simple_wallet::make_multisig(const std::vector &args) { success_msg_writer() << tr("Another step is needed"); success_msg_writer() << multisig_extra_info; - success_msg_writer() << tr("Send this multisig info to all other participants, then use finalize_multisig [...] with others' multisig info"); + success_msg_writer() << tr("Send this multisig info to all other participants, then use exchange_multisig_keys [...] with others' multisig info"); return true; } } @@ -1042,6 +1042,61 @@ bool simple_wallet::finalize_multisig(const std::vector &args) return true; } +bool simple_wallet::exchange_multisig_keys(const std::vector &args) { + bool ready; + if (m_wallet->key_on_device()) + { + fail_msg_writer() << tr("command not supported by HW wallet"); + return true; + } + if (!m_wallet->multisig(&ready)) + { + fail_msg_writer() << tr("This wallet is not multisig"); + return true; + } + if (ready) + { + fail_msg_writer() << tr("This wallet is already finalized"); + return true; + } + + const auto orig_pwd_container = get_and_verify_password(); + if(orig_pwd_container == boost::none) + { + fail_msg_writer() << tr("Your original password was incorrect."); + return true; + } + + if (args.size() < 2) + { + fail_msg_writer() << tr("usage: exchange_multisig_keys [...]"); + return true; + } + + try + { + std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args); + if (!multisig_extra_info.empty()) + { + message_writer() << tr("Another step is needed"); + message_writer() << multisig_extra_info; + message_writer() << tr("Send this multisig info to all other participants, then use exchange_multisig_keys [...] with others' multisig info"); + return true; + } else { + uint32_t threshold, total; + m_wallet->multisig(NULL, &threshold, &total); + success_msg_writer() << tr("Multisig wallet has been successfully created. Current wallet type: ") << threshold << "/" << total; + } + } + catch (const std::exception &e) + { + fail_msg_writer() << tr("Failed to perform multisig keys exchange: ") << e.what(); + return true; + } + + return true; +} + bool simple_wallet::export_multisig(const std::vector &args) { bool ready; @@ -2552,6 +2607,10 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::finalize_multisig, this, _1), tr("finalize_multisig [...]"), tr("Turn this wallet into a multisig wallet, extra step for N-1/N wallets")); + m_cmd_binder.set_handler("exchange_multisig_keys", + boost::bind(&simple_wallet::exchange_multisig_keys, this, _1), + tr("exchange_multisig_keys [...]"), + tr("Performs extra multisig keys exchange rounds. Needed for arbitrary M/N multisig wallets")); m_cmd_binder.set_handler("export_multisig_info", boost::bind(&simple_wallet::export_multisig, this, _1), tr("export_multisig_info "), diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 2d23d6248..39b715b73 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -210,6 +210,7 @@ namespace cryptonote bool prepare_multisig(const std::vector& args); bool make_multisig(const std::vector& args); bool finalize_multisig(const std::vector &args); + bool exchange_multisig_keys(const std::vector &args); bool export_multisig(const std::vector& args); bool import_multisig(const std::vector& args); bool accept_loaded_tx(const tools::wallet2::multisig_tx_set &txs); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 5827e4d1a..a7fc3dcd7 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1187,6 +1187,20 @@ string WalletImpl::makeMultisig(const vector& info, uint32_t threshold) return string(); } +std::string WalletImpl::exchangeMultisigKeys(const std::vector &info) { + try { + clearStatus(); + checkMultisigWalletNotReady(m_wallet); + + return m_wallet->exchange_multisig_keys(epee::wipeable_string(m_password), info); + } catch (const exception& e) { + LOG_ERROR("Error on exchanging multisig keys: ") << e.what(); + setStatusError(string(tr("Failed to make multisig: ")) + e.what()); + } + + return string(); +} + bool WalletImpl::finalizeMultisig(const vector& extraMultisigInfo) { try { clearStatus(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 64350cee7..8c20af347 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -137,6 +137,7 @@ class WalletImpl : public Wallet MultisigState multisig() const override; std::string getMultisigInfo() const override; std::string makeMultisig(const std::vector& info, uint32_t threshold) override; + std::string exchangeMultisigKeys(const std::vector &info) override; bool finalizeMultisig(const std::vector& extraMultisigInfo) override; bool exportMultisigImages(std::string& images) override; size_t importMultisigImages(const std::vector& images) override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index e0d491705..184c0aa73 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -706,6 +706,12 @@ struct Wallet * @return in case of N / N wallets returns empty string since no more key exchanges needed. For N - 1 / N wallets returns base58 encoded extra multisig info */ virtual std::string makeMultisig(const std::vector& info, uint32_t threshold) = 0; + /** + * @brief exchange_multisig_keys - provides additional key exchange round for arbitrary multisig schemes (like N-1/N, M/N) + * @param info - base58 encoded key derivations returned by makeMultisig or exchangeMultisigKeys function call + * @return new info string if more rounds required or an empty string if wallet creation is done + */ + virtual std::string exchangeMultisigKeys(const std::vector &info) = 0; /** * @brief finalizeMultisig - finalizes N - 1 / N multisig wallets creation * @param extraMultisigInfo - wallet participants' extra multisig info obtained with makeMultisig call diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 75178845a..841c5c2ab 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -121,6 +121,7 @@ using namespace cryptonote; #define FIRST_REFRESH_GRANULARITY 1024 static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; +static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; namespace { @@ -132,6 +133,42 @@ namespace dir /= ".shared-ringdb"; return dir.string(); } + + std::string pack_multisignature_keys(const std::string& prefix, const std::vector& keys, const crypto::secret_key& signer_secret_key) + { + std::string data; + crypto::public_key signer; + CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(signer_secret_key, signer), "Failed to derive public spend key"); + data += std::string((const char *)&signer, sizeof(crypto::public_key)); + + for (const auto &key: keys) + { + data += std::string((const char *)&key, sizeof(crypto::public_key)); + } + + data.resize(data.size() + sizeof(crypto::signature)); + + crypto::hash hash; + crypto::cn_fast_hash(data.data(), data.size() - sizeof(crypto::signature), hash); + crypto::signature &signature = *(crypto::signature*)&data[data.size() - sizeof(crypto::signature)]; + crypto::generate_signature(hash, signer, signer_secret_key, signature); + + return MULTISIG_EXTRA_INFO_MAGIC + tools::base58::encode(data); + } + + std::vector secret_keys_to_public_keys(const std::vector& keys) + { + std::vector public_keys; + public_keys.reserve(keys.size()); + + std::transform(keys.begin(), keys.end(), std::back_inserter(public_keys), [] (const crypto::secret_key& k) -> crypto::public_key { + crypto::public_key p; + CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(k, p), "Failed to derive public spend key"); + return p; + }); + + return public_keys; + } } namespace @@ -758,6 +795,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_callback(0), m_trusted_daemon(false), m_nettype(nettype), + m_multisig_rounds_passed(0), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), @@ -2885,6 +2923,7 @@ bool wallet2::clear() m_address_book.clear(); m_subaddresses.clear(); m_subaddress_labels.clear(); + m_multisig_rounds_passed = 0; return true; } @@ -2899,6 +2938,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable { std::string account_data; std::string multisig_signers; + std::string multisig_derivations; cryptonote::account_base account = m_account; crypto::chacha_key key; @@ -2951,6 +2991,14 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable CHECK_AND_ASSERT_MES(r, false, "failed to serialize wallet multisig signers"); value.SetString(multisig_signers.c_str(), multisig_signers.length()); json.AddMember("multisig_signers", value, json.GetAllocator()); + + r = ::serialization::dump_binary(m_multisig_derivations, multisig_derivations); + CHECK_AND_ASSERT_MES(r, false, "failed to serialize wallet multisig derivations"); + value.SetString(multisig_derivations.c_str(), multisig_derivations.length()); + json.AddMember("multisig_derivations", value, json.GetAllocator()); + + value2.SetUint(m_multisig_rounds_passed); + json.AddMember("multisig_rounds_passed", value2, json.GetAllocator()); } value2.SetInt(m_always_confirm_transfers ? 1 :0); @@ -3123,6 +3171,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_multisig = false; m_multisig_threshold = 0; m_multisig_signers.clear(); + m_multisig_rounds_passed = 0; + m_multisig_derivations.clear(); m_always_confirm_transfers = false; m_print_ring_members = false; m_default_mixin = 0; @@ -3181,6 +3231,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_multisig = field_multisig; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, multisig_threshold, unsigned int, Uint, m_multisig, 0); m_multisig_threshold = field_multisig_threshold; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, multisig_rounds_passed, unsigned int, Uint, false, 0); + m_multisig_rounds_passed = field_multisig_rounds_passed; if (m_multisig) { if (!json.HasMember("multisig_signers")) @@ -3201,6 +3253,24 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ LOG_ERROR("Field multisig_signers found in JSON, but failed to parse"); return false; } + + //previous version of multisig does not have this field + if (json.HasMember("multisig_derivations")) + { + if (!json["multisig_derivations"].IsString()) + { + LOG_ERROR("Field multisig_derivations found in JSON, but not String"); + return false; + } + const char *field_multisig_derivations = json["multisig_derivations"].GetString(); + std::string multisig_derivations = std::string(field_multisig_derivations, field_multisig_derivations + json["multisig_derivations"].GetStringLength()); + r = ::serialization::parse_binary(multisig_derivations, m_multisig_derivations); + if (!r) + { + LOG_ERROR("Field multisig_derivations found in JSON, but failed to parse"); + return false; + } + } } GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, always_confirm_transfers, int, Int, false, true); m_always_confirm_transfers = field_always_confirm_transfers; @@ -3829,12 +3899,12 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, CHECK_AND_ASSERT_THROW_MES(!view_keys.empty(), "empty view keys"); CHECK_AND_ASSERT_THROW_MES(view_keys.size() == spend_keys.size(), "Mismatched view/spend key sizes"); CHECK_AND_ASSERT_THROW_MES(threshold > 1 && threshold <= spend_keys.size() + 1, "Invalid threshold"); - CHECK_AND_ASSERT_THROW_MES(threshold == spend_keys.size() || threshold == spend_keys.size() + 1, "Unsupported threshold case"); std::string extra_multisig_info; - crypto::hash hash; - - clear(); + std::vector multisig_keys; + rct::key spend_pkey = rct::identity(); + rct::key spend_skey; + std::vector multisig_signers; // decrypt keys epee::misc_utils::auto_scope_leave_caller keys_reencryptor; @@ -3847,43 +3917,78 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this, chacha_key]() { m_account.encrypt_keys(chacha_key); m_account.decrypt_viewkey(chacha_key); }); } - MINFO("Creating spend key..."); - std::vector multisig_keys; - rct::key spend_pkey, spend_skey; + // In common multisig scheme there are 4 types of key exchange rounds: + // 1. First round is exchange of view secret keys and public spend keys. + // 2. Middle round is exchange of derivations: Ki = b * Mj, where b - spend secret key, + // M - public multisig key (in first round it equals to public spend key), K - new public multisig key. + // 3. Secret spend establishment round sets your secret multisig keys as follows: kl = H(Ml), where M - is *your* public multisig key, + // k - secret multisig key used to sign transactions. k and M are sets of keys, of course. + // And secret spend key as the sum of all participant's secret multisig keys + // 4. Last round establishes multisig wallet's public spend key. Participants exchange their public multisig keys + // and calculate common spend public key as sum of all unique participants' public multisig keys. + // Note that N/N scheme has only first round. N-1/N has 2 rounds: first and last. Common M/N has all 4 rounds. + + // IMPORTANT: wallet's public spend key is not equal to secret_spend_key * G! + // Wallet's public spend key is the sum of unique public multisig keys of all participants. + // secret_spend_key * G = public signer key + if (threshold == spend_keys.size() + 1) { + // In N / N case we only need to do one round and calculate secret multisig keys and new secret spend key + MINFO("Creating spend key..."); + + // Calculates all multisig keys and spend key cryptonote::generate_multisig_N_N(get_account().get_keys(), spend_keys, multisig_keys, spend_skey, spend_pkey); + + // Our signer key is b * G, where b is secret spend key. + multisig_signers = spend_keys; + multisig_signers.push_back(get_multisig_signer_public_key(get_account().get_keys().m_spend_secret_key)); } - else if (threshold == spend_keys.size()) + else { - cryptonote::generate_multisig_N1_N(get_account().get_keys(), spend_keys, multisig_keys, spend_skey, spend_pkey); + // We just got public spend keys of all participants and deriving multisig keys (set of Mi = b * Bi). + // note that derivations are public keys as DH exchange suppose it to be + auto derivations = cryptonote::generate_multisig_derivations(get_account().get_keys(), spend_keys); - // We need an extra step, so we package all the composite public keys - // we know about, and make a signed string out of them - std::string data; - crypto::public_key signer; - CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(rct::rct2sk(spend_skey), signer), "Failed to derive public spend key"); - data += std::string((const char *)&signer, sizeof(crypto::public_key)); + spend_pkey = rct::identity(); + multisig_signers = std::vector(spend_keys.size() + 1, crypto::null_pkey); - for (const auto &msk: multisig_keys) + if (threshold == spend_keys.size()) { - rct::key pmsk = rct::scalarmultBase(rct::sk2rct(msk)); - data += std::string((const char *)&pmsk, sizeof(crypto::public_key)); + // N - 1 / N case + + // We need an extra step, so we package all the composite public keys + // we know about, and make a signed string out of them + MINFO("Creating spend key..."); + + // Calculating set of our secret multisig keys as follows: mi = H(Mi), + // where mi - secret multisig key, Mi - others' participants public multisig key + multisig_keys = cryptonote::calculate_multisig_keys(derivations); + + // calculating current participant's spend secret key as sum of all secret multisig keys for current participant. + // IMPORTANT: participant's secret spend key is not an entire wallet's secret spend! + // Entire wallet's secret spend is sum of all unique secret multisig keys + // among all of participants and is not held by anyone! + spend_skey = rct::sk2rct(cryptonote::calculate_multisig_signer_key(multisig_keys)); + + // Preparing data for the last round to calculate common public spend key. The data contains public multisig keys. + extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, secret_keys_to_public_keys(multisig_keys), rct::rct2sk(spend_skey)); } + else + { + // M / N case + MINFO("Preparing keys for next exchange round..."); - data.resize(data.size() + sizeof(crypto::signature)); - crypto::cn_fast_hash(data.data(), data.size() - sizeof(signature), hash); - crypto::signature &signature = *(crypto::signature*)&data[data.size() - sizeof(crypto::signature)]; - crypto::generate_signature(hash, signer, rct::rct2sk(spend_skey), signature); + // Preparing data for middle round - packing new public multisig keys to exchage with others. + extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, derivations, m_account.get_keys().m_spend_secret_key); + spend_skey = rct::sk2rct(m_account.get_keys().m_spend_secret_key); - extra_multisig_info = std::string("MultisigxV1") + tools::base58::encode(data); - } - else - { - CHECK_AND_ASSERT_THROW_MES(false, "Unsupported threshold case"); + // Need to store middle keys to be able to proceed in case of wallet shutdown. + m_multisig_derivations = derivations; + } } - // the multisig view key is shared by all, make one all can derive + clear(); MINFO("Creating view key..."); crypto::secret_key view_skey = cryptonote::generate_multisig_view_secret_key(get_account().get_keys().m_view_secret_key, view_keys); @@ -3895,18 +4000,10 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, m_account_public_address = m_account.get_keys().m_account_address; m_watch_only = false; m_multisig = true; - m_multisig_threshold = threshold; m_key_device_type = hw::device::device_type::SOFTWARE; - - if (threshold == spend_keys.size() + 1) - { - m_multisig_signers = spend_keys; - m_multisig_signers.push_back(get_multisig_signer_public_key()); - } - else - { - m_multisig_signers = std::vector(spend_keys.size() + 1, crypto::null_pkey); - } + m_multisig_threshold = threshold; + m_multisig_signers = multisig_signers; + ++m_multisig_rounds_passed; // re-encrypt keys keys_reencryptor = epee::misc_utils::auto_scope_leave_caller(); @@ -3921,13 +4018,147 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, return extra_multisig_info; } -std::string wallet2::make_multisig(const epee::wipeable_string &password, - const std::vector &info, - uint32_t threshold) +std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &password, + const std::vector &info) +{ + THROW_WALLET_EXCEPTION_IF(info.empty(), + error::wallet_internal_error, "Empty multisig info"); + + if (info[0].substr(0, MULTISIG_EXTRA_INFO_MAGIC.size()) != MULTISIG_EXTRA_INFO_MAGIC) + { + THROW_WALLET_EXCEPTION_IF(false, + error::wallet_internal_error, "Unsupported info string"); + } + + std::vector signers; + std::unordered_set pkeys; + + THROW_WALLET_EXCEPTION_IF(!unpack_extra_multisig_info(info, signers, pkeys), + error::wallet_internal_error, "Bad extra multisig info"); + + return exchange_multisig_keys(password, pkeys, signers); +} + +std::string wallet2::exchange_multisig_keys(const epee::wipeable_string &password, + std::unordered_set derivations, + std::vector signers) +{ + CHECK_AND_ASSERT_THROW_MES(!derivations.empty(), "empty pkeys"); + CHECK_AND_ASSERT_THROW_MES(!signers.empty(), "empty signers"); + + bool ready = false; + CHECK_AND_ASSERT_THROW_MES(multisig(&ready), "The wallet is not multisig"); + CHECK_AND_ASSERT_THROW_MES(!ready, "Multisig wallet creation process has already been finished"); + + // keys are decrypted + epee::misc_utils::auto_scope_leave_caller keys_reencryptor; + if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only) + { + crypto::chacha_key chacha_key; + crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds); + m_account.encrypt_viewkey(chacha_key); + m_account.decrypt_keys(chacha_key); + keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this, chacha_key]() { m_account.encrypt_keys(chacha_key); m_account.decrypt_viewkey(chacha_key); }); + } + + if (m_multisig_rounds_passed == multisig_rounds_required(m_multisig_signers.size(), m_multisig_threshold) - 1) + { + // the last round is passed and we have to calculate spend public key + // add ours if not included + crypto::public_key local_signer = get_multisig_signer_public_key(); + + if (std::find(signers.begin(), signers.end(), local_signer) == signers.end()) + { + signers.push_back(local_signer); + for (const auto &msk: get_account().get_multisig_keys()) + { + derivations.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(msk)))); + } + } + + CHECK_AND_ASSERT_THROW_MES(signers.size() == m_multisig_signers.size(), "Bad signers size"); + + // Summing all of unique public multisig keys to calculate common public spend key + crypto::public_key spend_public_key = cryptonote::generate_multisig_M_N_spend_public_key(std::vector(derivations.begin(), derivations.end())); + m_account_public_address.m_spend_public_key = spend_public_key; + m_account.finalize_multisig(spend_public_key); + + m_multisig_signers = signers; + std::sort(m_multisig_signers.begin(), m_multisig_signers.end(), [](const crypto::public_key &e0, const crypto::public_key &e1){ return memcmp(&e0, &e1, sizeof(e0)); }); + + ++m_multisig_rounds_passed; + m_multisig_derivations.clear(); + + // keys are encrypted again + keys_reencryptor = epee::misc_utils::auto_scope_leave_caller(); + + if (!m_wallet_file.empty()) + { + bool r = store_keys(m_keys_file, password, false); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); + + if (boost::filesystem::exists(m_wallet_file + ".address.txt")) + { + r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype)); + if(!r) MERROR("String with address text not saved"); + } + } + + m_subaddresses.clear(); + m_subaddress_labels.clear(); + add_subaddress_account(tr("Primary account")); + + if (!m_wallet_file.empty()) + store(); + + return {}; + } + + // Below are either middle or secret spend key establishment rounds + + for (const auto& key: m_multisig_derivations) + derivations.erase(key); + + // Deriving multisig keys (set of Mi = b * Bi) according to DH from other participants' multisig keys. + auto new_derivations = cryptonote::generate_multisig_derivations(get_account().get_keys(), std::vector(derivations.begin(), derivations.end())); + + std::string extra_multisig_info; + if (m_multisig_rounds_passed == multisig_rounds_required(m_multisig_signers.size(), m_multisig_threshold) - 2) // next round is last + { + // Next round is last therefore we are performing secret spend establishment round as described above. + MINFO("Creating spend key..."); + + // Calculating our secret multisig keys by hashing our public multisig keys. + auto multisig_keys = cryptonote::calculate_multisig_keys(std::vector(new_derivations.begin(), new_derivations.end())); + // And summing it to get personal secret spend key + crypto::secret_key spend_skey = cryptonote::calculate_multisig_signer_key(multisig_keys); + + m_account.make_multisig(m_account.get_keys().m_view_secret_key, spend_skey, rct::rct2pk(rct::identity()), multisig_keys); + + // Packing public multisig keys to exchange with others and calculate common public spend key in the last round + extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, secret_keys_to_public_keys(multisig_keys), spend_skey); + } + else + { + // This is just middle round + MINFO("Preparing keys for next exchange round..."); + extra_multisig_info = pack_multisignature_keys(MULTISIG_EXTRA_INFO_MAGIC, new_derivations, m_account.get_keys().m_spend_secret_key); + m_multisig_derivations = new_derivations; + } + + ++m_multisig_rounds_passed; + + create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt")); + return extra_multisig_info; +} + +void wallet2::unpack_multisig_info(const std::vector& info, + std::vector &public_keys, + std::vector &secret_keys) const { // parse all multisig info - std::vector secret_keys(info.size()); - std::vector public_keys(info.size()); + public_keys.resize(info.size()); + secret_keys.resize(info.size()); for (size_t i = 0; i < info.size(); ++i) { THROW_WALLET_EXCEPTION_IF(!verify_multisig_info(info[i], secret_keys[i], public_keys[i]), @@ -3971,75 +4202,51 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, "Found local spend public key, but not local view secret key - something very weird"); } } +} +std::string wallet2::make_multisig(const epee::wipeable_string &password, + const std::vector &info, + uint32_t threshold) +{ + std::vector secret_keys(info.size()); + std::vector public_keys(info.size()); + unpack_multisig_info(info, public_keys, secret_keys); return make_multisig(password, secret_keys, public_keys, threshold); } bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unordered_set pkeys, std::vector signers) { - CHECK_AND_ASSERT_THROW_MES(!pkeys.empty(), "empty pkeys"); - - // keys are decrypted - epee::misc_utils::auto_scope_leave_caller keys_reencryptor; - if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only) - { - crypto::chacha_key chacha_key; - crypto::generate_chacha_key(password.data(), password.size(), chacha_key, m_kdf_rounds); - m_account.encrypt_viewkey(chacha_key); - m_account.decrypt_keys(chacha_key); - keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this, chacha_key]() { m_account.encrypt_keys(chacha_key); m_account.decrypt_viewkey(chacha_key); }); - } + exchange_multisig_keys(password, pkeys, signers); + return true; +} - // add ours if not included - crypto::public_key local_signer; - CHECK_AND_ASSERT_THROW_MES(crypto::secret_key_to_public_key(get_account().get_keys().m_spend_secret_key, local_signer), - "Failed to derive public spend key"); - if (std::find(signers.begin(), signers.end(), local_signer) == signers.end()) +bool wallet2::unpack_extra_multisig_info(const std::vector& info, + std::vector &signers, + std::unordered_set &pkeys) const +{ + // parse all multisig info + signers.resize(info.size(), crypto::null_pkey); + for (size_t i = 0; i < info.size(); ++i) { - signers.push_back(local_signer); - for (const auto &msk: get_account().get_multisig_keys()) - { - pkeys.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(msk)))); - } + if (!verify_extra_multisig_info(info[i], pkeys, signers[i])) + { + return false; + } } - CHECK_AND_ASSERT_THROW_MES(signers.size() == m_multisig_signers.size(), "Bad signers size"); - - crypto::public_key spend_public_key = cryptonote::generate_multisig_N1_N_spend_public_key(std::vector(pkeys.begin(), pkeys.end())); - m_account_public_address.m_spend_public_key = spend_public_key; - m_account.finalize_multisig(spend_public_key); - - m_multisig_signers = signers; - std::sort(m_multisig_signers.begin(), m_multisig_signers.end(), [](const crypto::public_key &e0, const crypto::public_key &e1){ return memcmp(&e0, &e1, sizeof(e0)); }); - - // keys are encrypted again - keys_reencryptor = epee::misc_utils::auto_scope_leave_caller(); - - create_keys_file(m_wallet_file, false, password, boost::filesystem::exists(m_wallet_file + ".address.txt")); - - m_subaddresses.clear(); - m_subaddress_labels.clear(); - add_subaddress_account(tr("Primary account")); - - if (!m_wallet_file.empty()) - store(); - return true; } bool wallet2::finalize_multisig(const epee::wipeable_string &password, const std::vector &info) { - // parse all multisig info std::unordered_set public_keys; - std::vector signers(info.size(), crypto::null_pkey); - for (size_t i = 0; i < info.size(); ++i) + std::vector signers; + if (!unpack_extra_multisig_info(info, signers, public_keys)) { - if (!verify_extra_multisig_info(info[i], public_keys, signers[i])) - { - MERROR("Bad multisig info"); - return false; - } + MERROR("Bad multisig info"); + return false; } + return finalize_multisig(password, public_keys, signers); } @@ -4102,14 +4309,13 @@ bool wallet2::verify_multisig_info(const std::string &data, crypto::secret_key & bool wallet2::verify_extra_multisig_info(const std::string &data, std::unordered_set &pkeys, crypto::public_key &signer) { - const size_t header_len = strlen("MultisigxV1"); - if (data.size() < header_len || data.substr(0, header_len) != "MultisigxV1") + if (data.size() < MULTISIG_EXTRA_INFO_MAGIC.size() || data.substr(0, MULTISIG_EXTRA_INFO_MAGIC.size()) != MULTISIG_EXTRA_INFO_MAGIC) { MERROR("Multisig info header check error"); return false; } std::string decoded; - if (!tools::base58::decode(data.substr(header_len), decoded)) + if (!tools::base58::decode(data.substr(MULTISIG_EXTRA_INFO_MAGIC.size()), decoded)) { MERROR("Multisig info decoding error"); return false; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index acbc09c36..440ac709b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -573,6 +573,14 @@ namespace tools const std::vector &view_keys, const std::vector &spend_keys, uint32_t threshold); + std::string exchange_multisig_keys(const epee::wipeable_string &password, + const std::vector &info); + /*! + * \brief Any but first round of keys exchange + */ + std::string exchange_multisig_keys(const epee::wipeable_string &password, + std::unordered_set pkeys, + std::vector signers); /*! * \brief Finalizes creation of a multisig wallet */ @@ -1245,6 +1253,12 @@ namespace tools bool get_rct_distribution(uint64_t &start_height, std::vector &distribution); uint64_t get_segregation_fork_height() const; + void unpack_multisig_info(const std::vector& info, + std::vector &public_keys, + std::vector &secret_keys) const; + bool unpack_extra_multisig_info(const std::vector& info, + std::vector &signers, + std::unordered_set &pkeys) const; void cache_tx_data(const cryptonote::transaction& tx, const crypto::hash &txid, tx_cache_data &tx_cache_data) const; @@ -1295,6 +1309,9 @@ namespace tools bool m_multisig; /*!< if > 1 spend secret key will not match spend public key */ uint32_t m_multisig_threshold; std::vector m_multisig_signers; + //in case of general M/N multisig wallet we should perform N - M + 1 key exchange rounds and remember how many rounds are passed. + uint32_t m_multisig_rounds_passed; + std::vector m_multisig_derivations; bool m_always_confirm_transfers; bool m_print_ring_members; bool m_store_tx_info; /*!< request txkey to be returned in RPC, and store in the wallet cache file */ diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e6eb64d12..b8379448d 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3119,7 +3119,7 @@ namespace tools return false; } - if (req.multisig_info.size() < threshold - 1) + if (req.multisig_info.size() < 1 || req.multisig_info.size() > total) { er.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED; er.message = "Needs multisig info from more participants"; @@ -3146,6 +3146,55 @@ namespace tools return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_exchange_multisig_keys(const wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::request& req, wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::response& res, epee::json_rpc::error& er) + { + if (!m_wallet) return not_open(er); + if (m_restricted) + { + er.code = WALLET_RPC_ERROR_CODE_DENIED; + er.message = "Command unavailable in restricted mode."; + return false; + } + bool ready; + uint32_t threshold, total; + if (!m_wallet->multisig(&ready, &threshold, &total)) + { + er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; + er.message = "This wallet is not multisig"; + return false; + } + + if (ready) + { + er.code = WALLET_RPC_ERROR_CODE_ALREADY_MULTISIG; + er.message = "This wallet is multisig, and already finalized"; + return false; + } + + if (req.multisig_info.size() < 1 || req.multisig_info.size() > total) + { + er.code = WALLET_RPC_ERROR_CODE_THRESHOLD_NOT_REACHED; + er.message = "Needs multisig info from more participants"; + return false; + } + + try + { + res.multisig_info = m_wallet->exchange_multisig_keys(req.password, req.multisig_info); + if (res.multisig_info.empty()) + { + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + } + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = std::string("Error calling exchange_multisig_info: ") + e.what(); + return false; + } + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_sign_multisig(const wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::response& res, epee::json_rpc::error& er) { if (!m_wallet) return not_open(er); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index ab7917a78..ab896aa3b 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -141,6 +141,7 @@ namespace tools MAP_JON_RPC_WE("export_multisig_info", on_export_multisig, wallet_rpc::COMMAND_RPC_EXPORT_MULTISIG) MAP_JON_RPC_WE("import_multisig_info", on_import_multisig, wallet_rpc::COMMAND_RPC_IMPORT_MULTISIG) MAP_JON_RPC_WE("finalize_multisig", on_finalize_multisig, wallet_rpc::COMMAND_RPC_FINALIZE_MULTISIG) + MAP_JON_RPC_WE("exchange_multisig_keys", on_exchange_multisig_keys, wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS) MAP_JON_RPC_WE("sign_multisig", on_sign_multisig, wallet_rpc::COMMAND_RPC_SIGN_MULTISIG) MAP_JON_RPC_WE("submit_multisig", on_submit_multisig, wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG) MAP_JON_RPC_WE("get_version", on_get_version, wallet_rpc::COMMAND_RPC_GET_VERSION) @@ -218,6 +219,7 @@ namespace tools bool on_export_multisig(const wallet_rpc::COMMAND_RPC_EXPORT_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_EXPORT_MULTISIG::response& res, epee::json_rpc::error& er); bool on_import_multisig(const wallet_rpc::COMMAND_RPC_IMPORT_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IMPORT_MULTISIG::response& res, epee::json_rpc::error& er); bool on_finalize_multisig(const wallet_rpc::COMMAND_RPC_FINALIZE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_FINALIZE_MULTISIG::response& res, epee::json_rpc::error& er); + bool on_exchange_multisig_keys(const wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::request& req, wallet_rpc::COMMAND_RPC_EXCHANGE_MULTISIG_KEYS::response& res, epee::json_rpc::error& er); bool on_sign_multisig(const wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_SIGN_MULTISIG::response& res, epee::json_rpc::error& er); bool on_submit_multisig(const wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_MULTISIG::response& res, epee::json_rpc::error& er); bool on_get_version(const wallet_rpc::COMMAND_RPC_GET_VERSION::request& req, wallet_rpc::COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& er); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 2168e0f71..c769929f5 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1990,6 +1990,31 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_EXCHANGE_MULTISIG_KEYS + { + struct request + { + std::string password; + std::vector multisig_info; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(password) + KV_SERIALIZE(multisig_info) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string address; + std::string multisig_info; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(multisig_info) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_SIGN_MULTISIG { struct request diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 34b205ae5..c9e1640aa 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -593,7 +593,7 @@ inline bool do_replay_file(const std::string& filename) std::vector spend_public_keys; \ for (const auto &k: all_multisig_keys) \ spend_public_keys.push_back(k); \ - crypto::public_key spend_pkey = cryptonote::generate_multisig_N1_N_spend_public_key(spend_public_keys); \ + crypto::public_key spend_pkey = cryptonote::generate_multisig_M_N_spend_public_key(spend_public_keys); \ for (size_t msidx = 0; msidx < total; ++msidx) \ account[msidx].finalize_multisig(spend_pkey); \ } \ diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp index 83924c7af..7268f2690 100644 --- a/tests/unit_tests/multisig.cpp +++ b/tests/unit_tests/multisig.cpp @@ -49,9 +49,19 @@ static const struct { "9t6Hn946u3eah5cuncH1hB5hGzsTUoevtf4SY7MHN5NgJZh2SFWsyVt3vUhuHyRKyrCQvr71Lfc1AevG3BXE11PQFoXDtD8", "bbd3175ef9fd9f5eefdc43035f882f74ad14c4cf1799d8b6f9001bc197175d02" + }, + { + "9zmAWoNyNPbgnYSm3nJNpAKHm6fCcs3MR94gBWxp9MCDUiMUhyYFfyQETUDLPF7DP6ZsmNo6LRxwPP9VmhHNxKrER9oGigT", + "f2efae45bef1917a7430cda8fcffc4ee010e3178761aa41d4628e23b1fe2d501" + }, + { + "9ue8NJMg3WzKxTtmjeXzWYF5KmU6dC7LHEt9wvYdPn2qMmoFUa8hJJHhSHvJ46UEwpDyy5jSboNMRaDBKwU54NT42YcNUp5", + "a4cef54ed3fd61cd78a2ceb82ecf85a903ad2db9a86fb77ff56c35c56016280a" } }; +static const size_t KEYS_COUNT = 5; + static void make_wallet(unsigned int idx, tools::wallet2 &wallet) { ASSERT_TRUE(idx < sizeof(test_addresses) / sizeof(test_addresses[0])); @@ -76,126 +86,87 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet) } } -static void make_M_2_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, unsigned int M) +static std::vector exchange_round(std::vector& wallets, const std::vector& mis) { - ASSERT_TRUE(M <= 2); - - make_wallet(0, wallet0); - make_wallet(1, wallet1); - - std::vector sk0(1), sk1(1); - std::vector pk0(1), pk1(1); - - wallet0.decrypt_keys(""); - std::string mi0 = wallet0.get_multisig_info(); - wallet0.encrypt_keys(""); - wallet1.decrypt_keys(""); - std::string mi1 = wallet1.get_multisig_info(); - wallet1.encrypt_keys(""); - - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi1, sk0[0], pk0[0])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi0, sk1[0], pk1[0])); - - ASSERT_FALSE(wallet0.multisig() || wallet1.multisig()); - wallet0.make_multisig("", sk0, pk0, M); - wallet1.make_multisig("", sk1, pk1, M); - - ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet1.get_account().get_public_address_str(cryptonote::TESTNET)); - - bool ready; - uint32_t threshold, total; - ASSERT_TRUE(wallet0.multisig(&ready, &threshold, &total)); - ASSERT_TRUE(ready); - ASSERT_TRUE(threshold == M); - ASSERT_TRUE(total == 2); - ASSERT_TRUE(wallet1.multisig(&ready, &threshold, &total)); - ASSERT_TRUE(ready); - ASSERT_TRUE(threshold == M); - ASSERT_TRUE(total == 2); + std::vector new_infos; + for (size_t i = 0; i < wallets.size(); ++i) { + new_infos.push_back(wallets[i].exchange_multisig_keys("", mis)); + } + + return new_infos; } -static void make_M_3_wallet(tools::wallet2 &wallet0, tools::wallet2 &wallet1, tools::wallet2 &wallet2, unsigned int M) +static void make_wallets(std::vector& wallets, unsigned int M) { - ASSERT_TRUE(M <= 3); - - make_wallet(0, wallet0); - make_wallet(1, wallet1); - make_wallet(2, wallet2); - - std::vector sk0(2), sk1(2), sk2(2); - std::vector pk0(2), pk1(2), pk2(2); - - wallet0.decrypt_keys(""); - std::string mi0 = wallet0.get_multisig_info(); - wallet0.encrypt_keys(""); - wallet1.decrypt_keys(""); - std::string mi1 = wallet1.get_multisig_info(); - wallet1.encrypt_keys(""); - wallet2.decrypt_keys(""); - std::string mi2 = wallet2.get_multisig_info(); - wallet2.encrypt_keys(""); - - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi1, sk0[0], pk0[0])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi2, sk0[1], pk0[1])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi0, sk1[0], pk1[0])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi2, sk1[1], pk1[1])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi0, sk2[0], pk2[0])); - ASSERT_TRUE(tools::wallet2::verify_multisig_info(mi1, sk2[1], pk2[1])); - - ASSERT_FALSE(wallet0.multisig() || wallet1.multisig() || wallet2.multisig()); - std::string mxi0 = wallet0.make_multisig("", sk0, pk0, M); - std::string mxi1 = wallet1.make_multisig("", sk1, pk1, M); - std::string mxi2 = wallet2.make_multisig("", sk2, pk2, M); - - const size_t nset = !mxi0.empty() + !mxi1.empty() + !mxi2.empty(); - ASSERT_TRUE((M < 3 && nset == 3) || (M == 3 && nset == 0)); - - if (nset > 0) - { - std::unordered_set pkeys; - std::vector signers(3, crypto::null_pkey); - ASSERT_TRUE(tools::wallet2::verify_extra_multisig_info(mxi0, pkeys, signers[0])); - ASSERT_TRUE(tools::wallet2::verify_extra_multisig_info(mxi1, pkeys, signers[1])); - ASSERT_TRUE(tools::wallet2::verify_extra_multisig_info(mxi2, pkeys, signers[2])); - ASSERT_TRUE(pkeys.size() == 3); - ASSERT_TRUE(wallet0.finalize_multisig("", pkeys, signers)); - ASSERT_TRUE(wallet1.finalize_multisig("", pkeys, signers)); - ASSERT_TRUE(wallet2.finalize_multisig("", pkeys, signers)); + ASSERT_TRUE(wallets.size() > 1 && wallets.size() <= KEYS_COUNT); + ASSERT_TRUE(M <= wallets.size()); + + std::vector mis(wallets.size()); + + for (size_t i = 0; i < wallets.size(); ++i) { + make_wallet(i, wallets[i]); + + wallets[i].decrypt_keys(""); + mis[i] = wallets[i].get_multisig_info(); + wallets[i].encrypt_keys(""); + } + + for (auto& wallet: wallets) { + ASSERT_FALSE(wallet.multisig() || wallet.multisig() || wallet.multisig()); + } + + std::vector mxis; + for (size_t i = 0; i < wallets.size(); ++i) { + // it's ok to put all of multisig keys in this function. it throws in case of error + mxis.push_back(wallets[i].make_multisig("", mis, M)); } - ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet1.get_account().get_public_address_str(cryptonote::TESTNET)); - ASSERT_TRUE(wallet0.get_account().get_public_address_str(cryptonote::TESTNET) == wallet2.get_account().get_public_address_str(cryptonote::TESTNET)); - - bool ready; - uint32_t threshold, total; - ASSERT_TRUE(wallet0.multisig(&ready, &threshold, &total)); - ASSERT_TRUE(ready); - ASSERT_TRUE(threshold == M); - ASSERT_TRUE(total == 3); - ASSERT_TRUE(wallet1.multisig(&ready, &threshold, &total)); - ASSERT_TRUE(ready); - ASSERT_TRUE(threshold == M); - ASSERT_TRUE(total == 3); - ASSERT_TRUE(wallet2.multisig(&ready, &threshold, &total)); - ASSERT_TRUE(ready); - ASSERT_TRUE(threshold == M); - ASSERT_TRUE(total == 3); + while (!mxis[0].empty()) { + mxis = exchange_round(wallets, mxis); + } + + for (size_t i = 0; i < wallets.size(); ++i) { + ASSERT_TRUE(mxis[i].empty()); + bool ready; + uint32_t threshold, total; + ASSERT_TRUE(wallets[i].multisig(&ready, &threshold, &total)); + ASSERT_TRUE(ready); + ASSERT_TRUE(threshold == M); + ASSERT_TRUE(total == wallets.size()); + + if (i != 0) { + // "equals" is transitive relation so we need only to compare first wallet's address to each others' addresses. no need to compare 0's address with itself. + ASSERT_TRUE(wallets[0].get_account().get_public_address_str(cryptonote::TESTNET) == wallets[i].get_account().get_public_address_str(cryptonote::TESTNET)); + } + } } TEST(multisig, make_2_2) { - tools::wallet2 wallet0, wallet1; - make_M_2_wallet(wallet0, wallet1, 2); + std::vector wallets(2); + make_wallets(wallets, 2); } TEST(multisig, make_3_3) { - tools::wallet2 wallet0, wallet1, wallet2; - make_M_3_wallet(wallet0, wallet1, wallet2, 3); + std::vector wallets(3); + make_wallets(wallets, 3); } TEST(multisig, make_2_3) { - tools::wallet2 wallet0, wallet1, wallet2; - make_M_3_wallet(wallet0, wallet1, wallet2, 2); + std::vector wallets(3); + make_wallets(wallets, 2); +} + +TEST(multisig, make_2_4) +{ + std::vector wallets(4); + make_wallets(wallets, 2); +} + +TEST(multisig, make_2_5) +{ + std::vector wallets(5); + make_wallets(wallets, 2); } From 9acf42d3719a3237b99bc66089b49c86fbb9b467 Mon Sep 17 00:00:00 2001 From: naughtyfox Date: Tue, 17 Jul 2018 12:44:46 +0300 Subject: [PATCH 0036/1007] Multisig M/N functionality core tests added --- tests/core_tests/chaingen.h | 43 +------- tests/core_tests/chaingen_main.cpp | 10 ++ tests/core_tests/multisig.cpp | 152 ++++++++++++++++++++++++++++- tests/core_tests/multisig.h | 60 ++++++++++++ 4 files changed, 223 insertions(+), 42 deletions(-) diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index c9e1640aa..6b9277a30 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -544,6 +544,7 @@ inline bool do_replay_file(const std::string& filename) } return do_replay_events(events); } + //-------------------------------------------------------------------------- #define GENERATE_ACCOUNT(account) \ cryptonote::account_base account; \ @@ -556,47 +557,7 @@ inline bool do_replay_file(const std::string& filename) { \ for (size_t msidx = 0; msidx < total; ++msidx) \ account[msidx].generate(); \ - std::unordered_set all_multisig_keys; \ - std::vector> view_keys(total); \ - std::vector> spend_keys(total); \ - for (size_t msidx = 0; msidx < total; ++msidx) \ - { \ - for (size_t msidx_inner = 0; msidx_inner < total; ++msidx_inner) \ - { \ - if (msidx_inner != msidx) \ - { \ - crypto::secret_key vkh = cryptonote::get_multisig_blinded_secret_key(account[msidx_inner].get_keys().m_view_secret_key); \ - view_keys[msidx].push_back(vkh); \ - crypto::secret_key skh = cryptonote::get_multisig_blinded_secret_key(account[msidx_inner].get_keys().m_spend_secret_key); \ - crypto::public_key pskh; \ - crypto::secret_key_to_public_key(skh, pskh); \ - spend_keys[msidx].push_back(pskh); \ - } \ - } \ - } \ - for (size_t msidx = 0; msidx < total; ++msidx) \ - { \ - std::vector multisig_keys; \ - crypto::secret_key spend_skey; \ - crypto::public_key spend_pkey; \ - if (threshold == total) \ - cryptonote::generate_multisig_N_N(account[msidx].get_keys(), spend_keys[msidx], multisig_keys, (rct::key&)spend_skey, (rct::key&)spend_pkey); \ - else \ - cryptonote::generate_multisig_N1_N(account[msidx].get_keys(), spend_keys[msidx], multisig_keys, (rct::key&)spend_skey, (rct::key&)spend_pkey); \ - crypto::secret_key view_skey = cryptonote::generate_multisig_view_secret_key(account[msidx].get_keys().m_view_secret_key, view_keys[msidx]); \ - account[msidx].make_multisig(view_skey, spend_skey, spend_pkey, multisig_keys); \ - for (const auto &k: multisig_keys) \ - all_multisig_keys.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(k)))); \ - } \ - if (threshold < total) \ - { \ - std::vector spend_public_keys; \ - for (const auto &k: all_multisig_keys) \ - spend_public_keys.push_back(k); \ - crypto::public_key spend_pkey = cryptonote::generate_multisig_M_N_spend_public_key(spend_public_keys); \ - for (size_t msidx = 0; msidx < total; ++msidx) \ - account[msidx].finalize_multisig(spend_pkey); \ - } \ + make_multisig_accounts(account, threshold); \ } while(0) #define MAKE_ACCOUNT(VEC_EVENTS, account) \ diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index abc412318..84254cfdb 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -223,6 +223,16 @@ int main(int argc, char* argv[]) GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1__no_threshold); GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_2_no_threshold); GENERATE_AND_PLAY(gen_multisig_tx_invalid_33_1_3_no_threshold); + GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2); + GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_2_many_inputs); + GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2); + GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_2_many_inputs); + GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234); + GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_234_many_inputs); + GENERATE_AND_PLAY(gen_multisig_tx_valid_24_1_no_signers); + GENERATE_AND_PLAY(gen_multisig_tx_valid_25_1_no_signers); + GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_no_signers); + GENERATE_AND_PLAY(gen_multisig_tx_valid_48_1_23_no_threshold); GENERATE_AND_PLAY(gen_bp_tx_valid_1); GENERATE_AND_PLAY(gen_bp_tx_invalid_1_1); diff --git a/tests/core_tests/multisig.cpp b/tests/core_tests/multisig.cpp index 46cc0ff35..fe5feb942 100644 --- a/tests/core_tests/multisig.cpp +++ b/tests/core_tests/multisig.cpp @@ -41,6 +41,87 @@ using namespace cryptonote; //#define NO_MULTISIG +void make_multisig_accounts(std::vector& account, uint32_t threshold) +{ + std::vector all_view_keys; + std::vector> derivations(account.size()); + //storage for all set of multisig derivations and spend public key (in first round) + std::unordered_set exchanging_keys; + + for (size_t msidx = 0; msidx < account.size(); ++msidx) + { + crypto::secret_key vkh = cryptonote::get_multisig_blinded_secret_key(account[msidx].get_keys().m_view_secret_key); + all_view_keys.push_back(vkh); + + crypto::secret_key skh = cryptonote::get_multisig_blinded_secret_key(account[msidx].get_keys().m_spend_secret_key); + crypto::public_key pskh; + crypto::secret_key_to_public_key(skh, pskh); + + derivations[msidx].push_back(pskh); + exchanging_keys.insert(pskh); + } + + uint32_t roundsTotal = 1; + if (threshold < account.size()) + roundsTotal = account.size() - threshold; + + //secret multisig keys of every account + std::vector> multisig_keys(account.size()); + std::vector spend_skey(account.size()); + std::vector spend_pkey(account.size()); + for (uint32_t round = 0; round < roundsTotal; ++round) + { + std::unordered_set roundKeys; + for (size_t msidx = 0; msidx < account.size(); ++msidx) + { + // subtracting one's keys from set of all unique keys is the same as key exchange + auto myKeys = exchanging_keys; + for (const auto& d: derivations[msidx]) + myKeys.erase(d); + + if (threshold == account.size()) + { + cryptonote::generate_multisig_N_N(account[msidx].get_keys(), std::vector(myKeys.begin(), myKeys.end()), multisig_keys[msidx], (rct::key&)spend_skey[msidx], (rct::key&)spend_pkey[msidx]); + } + else + { + derivations[msidx] = cryptonote::generate_multisig_derivations(account[msidx].get_keys(), std::vector(myKeys.begin(), myKeys.end())); + roundKeys.insert(derivations[msidx].begin(), derivations[msidx].end()); + } + } + + exchanging_keys = roundKeys; + roundKeys.clear(); + } + + std::unordered_set all_multisig_keys; + for (size_t msidx = 0; msidx < account.size(); ++msidx) + { + std::unordered_set view_keys(all_view_keys.begin(), all_view_keys.end()); + view_keys.erase(all_view_keys[msidx]); + + crypto::secret_key view_skey = cryptonote::generate_multisig_view_secret_key(account[msidx].get_keys().m_view_secret_key, std::vector(view_keys.begin(), view_keys.end())); + if (threshold < account.size()) + { + multisig_keys[msidx] = cryptonote::calculate_multisig_keys(derivations[msidx]); + spend_skey[msidx] = cryptonote::calculate_multisig_signer_key(multisig_keys[msidx]); + } + account[msidx].make_multisig(view_skey, spend_skey[msidx], spend_pkey[msidx], multisig_keys[msidx]); + for (const auto &k: multisig_keys[msidx]) { + all_multisig_keys.insert(rct::rct2pk(rct::scalarmultBase(rct::sk2rct(k)))); + } + } + + if (threshold < account.size()) + { + std::vector public_keys(std::vector(all_multisig_keys.begin(), all_multisig_keys.end())); + crypto::public_key spend_pkey = cryptonote::generate_multisig_M_N_spend_public_key(public_keys); + + for (size_t msidx = 0; msidx < account.size(); ++msidx) + account[msidx].finalize_multisig(spend_pkey); + } +} + //---------------------------------------------------------------------------------------------------------------------- // Tests @@ -55,7 +136,6 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector= 2, false, "Bad scheme"); CHECK_AND_ASSERT_MES(threshold <= total, false, "Bad scheme"); - CHECK_AND_ASSERT_MES(threshold >= total - 1, false, "Unsupported scheme"); #ifdef NO_MULTISIG CHECK_AND_ASSERT_MES(total <= 5, false, "Unsupported scheme"); #endif @@ -480,6 +560,48 @@ bool gen_multisig_tx_valid_89_3_1245789::generate(std::vector& return generate_with(events, 2, mixin, amount_paid, true, 8, 9, 3, {1, 2, 4, 5, 7, 8, 9}, NULL, NULL); } +bool gen_multisig_tx_valid_24_1_2::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL); +} + +bool gen_multisig_tx_valid_24_1_2_many_inputs::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 4, mixin, amount_paid, true, 2, 4, 1, {2}, NULL, NULL); +} + +bool gen_multisig_tx_valid_25_1_2::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL); +} + +bool gen_multisig_tx_valid_25_1_2_many_inputs::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 4, mixin, amount_paid, true, 2, 5, 1, {2}, NULL, NULL); +} + +bool gen_multisig_tx_valid_48_1_234::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL); +} + +bool gen_multisig_tx_valid_48_1_234_many_inputs::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 4, mixin, amount_paid, true, 4, 8, 1, {2, 3, 4}, NULL, NULL); +} + bool gen_multisig_tx_invalid_22_1__no_threshold::generate(std::vector& events) const { const size_t mixin = 4; @@ -521,3 +643,31 @@ bool gen_multisig_tx_invalid_45_5_23_no_threshold::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, false, 2, 4, 1, {}, NULL, NULL); +} + +bool gen_multisig_tx_valid_25_1_no_signers::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, false, 2, 5, 1, {}, NULL, NULL); +} + +bool gen_multisig_tx_valid_48_1_no_signers::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {}, NULL, NULL); +} + +bool gen_multisig_tx_valid_48_1_23_no_threshold::generate(std::vector& events) const +{ + const size_t mixin = 4; + const uint64_t amount_paid = 10000; + return generate_with(events, 2, mixin, amount_paid, false, 4, 8, 1, {2, 3}, NULL, NULL); +} diff --git a/tests/core_tests/multisig.h b/tests/core_tests/multisig.h index f0157a6d1..9e4cb3a23 100644 --- a/tests/core_tests/multisig.h +++ b/tests/core_tests/multisig.h @@ -161,6 +161,42 @@ struct gen_multisig_tx_valid_89_3_1245789: public gen_multisig_tx_validation_bas }; template<> struct get_test_options: public get_test_options {}; +struct gen_multisig_tx_valid_24_1_2: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_24_1_2_many_inputs: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_25_1_2: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_25_1_2_many_inputs: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_48_1_234: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_48_1_234_many_inputs: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + // invalid struct gen_multisig_tx_invalid_22_1__no_threshold: public gen_multisig_tx_validation_base { @@ -197,3 +233,27 @@ struct gen_multisig_tx_invalid_45_5_23_no_threshold: public gen_multisig_tx_vali bool generate(std::vector& events) const; }; template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_24_1_no_signers: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_25_1_no_signers: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_48_1_no_signers: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; + +struct gen_multisig_tx_valid_48_1_23_no_threshold: public gen_multisig_tx_validation_base +{ + bool generate(std::vector& events) const; +}; +template<> struct get_test_options: public get_test_options {}; From d5541e44feaa2be10c6a4ffb2746d59bb01a2b26 Mon Sep 17 00:00:00 2001 From: xiphon Date: Mon, 1 Oct 2018 06:39:37 +0000 Subject: [PATCH 0037/1007] common: Windows 'spawn' support for tx and block notifications --- src/common/CMakeLists.txt | 4 +-- src/common/notify.cpp | 13 +++---- src/common/{exec.cpp => spawn.cpp} | 57 ++++++++++++++++++++++++++++-- src/common/{exec.h => spawn.h} | 2 +- 4 files changed, 65 insertions(+), 11 deletions(-) rename src/common/{exec.cpp => spawn.cpp} (64%) rename src/common/{exec.h => spawn.h} (95%) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9b83f149f..aed9bfee7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -34,13 +34,13 @@ set(common_sources dns_utils.cpp download.cpp error.cpp - exec.cpp expect.cpp util.cpp i18n.cpp notify.cpp password.cpp perf_timer.cpp + spawn.cpp threadpool.cpp updates.cpp aligned.c) @@ -60,7 +60,6 @@ set(common_private_headers dns_utils.h download.h error.h - exec.h expect.h http_connection.h int-util.h @@ -74,6 +73,7 @@ set(common_private_headers i18n.h password.h perf_timer.h + spawn.h stack_trace.h threadpool.h updates.h diff --git a/src/common/notify.cpp b/src/common/notify.cpp index b7869ad84..cadc68ea7 100644 --- a/src/common/notify.cpp +++ b/src/common/notify.cpp @@ -29,12 +29,17 @@ #include #include "misc_log_ex.h" #include "file_io_utils.h" -#include "exec.h" +#include "spawn.h" #include "notify.h" namespace tools { +/* + TODO: + - Improve tokenization to handle paths containing whitespaces, quotes, etc. + - Windows unicode support (implies implementing unicode command line parsing code) +*/ Notify::Notify(const char *spec) { CHECK_AND_ASSERT_THROW_MES(spec, "Null spec"); @@ -51,11 +56,7 @@ int Notify::notify(const char *parameter) for (std::string &s: margs) boost::replace_all(s, "%s", parameter); - char **cargs = (char**)alloca(sizeof(char*) * (margs.size() + 1)); - for (size_t n = 0; n < margs.size(); ++n) - cargs[n] = (char*)margs[n].c_str(); - cargs[margs.size()] = NULL; - return tools::exec(filename.c_str(), cargs, false); + return tools::spawn(filename.c_str(), margs, false); } } diff --git a/src/common/exec.cpp b/src/common/spawn.cpp similarity index 64% rename from src/common/exec.cpp rename to src/common/spawn.cpp index 41b8f1378..59f11675c 100644 --- a/src/common/exec.cpp +++ b/src/common/spawn.cpp @@ -29,16 +29,68 @@ #include #include #include +#ifdef _WIN32 +#include +#include +#include +#else #include +#endif #include "misc_log_ex.h" -#include "exec.h" +#include "spawn.h" namespace tools { -int exec(const char *filename, char * const argv[], bool wait) +int spawn(const char *filename, const std::vector& args, bool wait) { +#ifdef _WIN32 + std::string joined = boost::algorithm::join(args, " "); + char *commandLine = !joined.empty() ? &joined[0] : nullptr; + STARTUPINFOA si = {}; + si.cb = sizeof(si); + PROCESS_INFORMATION pi; + if (!CreateProcessA(filename, commandLine, nullptr, nullptr, false, 0, nullptr, nullptr, &si, &pi)) + { + MERROR("CreateProcess failed. Error code " << GetLastError()); + return -1; + } + + BOOST_SCOPE_EXIT(&pi) + { + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } + BOOST_SCOPE_EXIT_END + + if (!wait) + { + return 0; + } + + DWORD result = WaitForSingleObject(pi.hProcess, INFINITE); + if (result != WAIT_OBJECT_0) + { + MERROR("WaitForSingleObject failed. Result " << result << ", error code " << GetLastError()); + return -1; + } + + DWORD exitCode; + if (!GetExitCodeProcess(pi.hProcess, &exitCode)) + { + MERROR("GetExitCodeProcess failed. Error code " << GetLastError()); + return -1; + } + + MINFO("Child exited with " << exitCode); + return static_cast(exitCode); +#else + char **argv = (char**)alloca(sizeof(char*) * (args.size() + 1)); + for (size_t n = 0; n < args.size(); ++n) + argv[n] = (char*)args[n].c_str(); + argv[args.size()] = NULL; + pid_t pid = fork(); if (pid < 0) { @@ -83,6 +135,7 @@ int exec(const char *filename, char * const argv[], bool wait) } MERROR("Secret passage found"); return -1; +#endif } } diff --git a/src/common/exec.h b/src/common/spawn.h similarity index 95% rename from src/common/exec.h rename to src/common/spawn.h index 4d2037798..c90a0f790 100644 --- a/src/common/exec.h +++ b/src/common/spawn.h @@ -31,6 +31,6 @@ namespace tools { -int exec(const char *filename, char * const argv[], bool wait); +int spawn(const char *filename, const std::vector& args, bool wait); } From 5ec929fb3a01c3dfa7409debe1f585e2aff229a3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 1 Oct 2018 21:25:56 +0000 Subject: [PATCH 0038/1007] daemon: do not display uptime when not known --- src/daemon/rpc_command_executor.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 6b6c88907..6464d372f 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -442,7 +442,8 @@ bool t_rpc_command_executor::show_status() { } } - tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections, uptime %ud %uh %um %us") + std::stringstream str; + str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections") % (unsigned long long)ires.height % (unsigned long long)net_height % get_sync_percentage(ires) @@ -455,12 +456,21 @@ bool t_rpc_command_executor::show_status() { % (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked") % (unsigned)ires.outgoing_connections_count % (unsigned)ires.incoming_connections_count - % (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0) - % (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0)) - % (unsigned int)floor(fmod((uptime / 60.0), 60.0)) - % (unsigned int)fmod(uptime, 60.0) ; + // restricted RPC does not disclose start time + if (ires.start_time) + { + str << boost::format(", uptime %ud %uh %um %us") + % (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0) + % (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0)) + % (unsigned int)floor(fmod((uptime / 60.0), 60.0)) + % (unsigned int)fmod(uptime, 60.0) + ; + } + + tools::success_msg_writer() << str.str(); + return true; } From bccd88ddf5f09a7bf774b3437a6396ac9953aad5 Mon Sep 17 00:00:00 2001 From: doy-lee Date: Wed, 26 Sep 2018 12:38:39 +0000 Subject: [PATCH 0039/1007] wallet2: clear found out for every tx key Avoids triggering the sanity check --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 299b4afeb..14077bc9b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1339,7 +1339,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote // (that is, the prunable stuff may or may not be included) if (!miner_tx && !pool) process_unconfirmed(txid, tx, height); - std::vector outs; std::unordered_map tx_money_got_in_outs; // per receiving subaddress index crypto::public_key tx_pub_key = null_pkey; bool notify = false; @@ -1362,6 +1361,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote uint64_t total_received_1 = 0; while (!tx.vout.empty()) { + std::vector outs; // if tx.vout is not empty, we loop through all tx pubkeys tx_extra_pub_key pub_key_field; From 7c790f11f207ffad5e8ba857a1d1640cae815cee Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Tue, 2 Oct 2018 16:14:20 +0100 Subject: [PATCH 0040/1007] Fix rtxn usage in BlockchainLMDB::get_estimated_batch_size Should only stop the rtxn if we actually started it Fixes Coverity 184960 --- src/blockchain_db/lmdb/db_lmdb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 824598f8c..bd91f308a 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -649,7 +649,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin { MDB_txn *rtxn; mdb_txn_cursors *rcurs; - block_rtxn_start(&rtxn, &rcurs); + bool my_rtxn = block_rtxn_start(&rtxn, &rcurs); for (uint64_t block_num = block_start; block_num <= block_stop; ++block_num) { // we have access to block weight, which will be greater or equal to block size, @@ -661,7 +661,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin // some blocks were to be skipped for being outliers. ++num_blocks_used; } - block_rtxn_stop(); + if (my_rtxn) block_rtxn_stop(); avg_block_size = total_block_size / num_blocks_used; MDEBUG("average block size across recent " << num_blocks_used << " blocks: " << avg_block_size); } From e5108a294a7d4fd923665e059a6eb90b0ab5a337 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 2 Oct 2018 08:39:47 +0000 Subject: [PATCH 0041/1007] Catch more exceptions in dtors Misc coverity reports --- contrib/epee/include/misc_language.h | 3 ++- src/common/threadpool.cpp | 10 ++++++++++ tests/crypto/main.cpp | 3 +++ tests/fuzz/base58.cpp | 2 ++ tests/fuzz/block.cpp | 2 ++ tests/fuzz/bulletproof.cpp | 2 ++ tests/fuzz/cold-outputs.cpp | 2 ++ tests/fuzz/cold-transaction.cpp | 2 ++ tests/fuzz/http-client.cpp | 2 ++ tests/fuzz/levin.cpp | 2 ++ tests/fuzz/load_from_binary.cpp | 2 ++ tests/fuzz/load_from_json.cpp | 2 ++ tests/fuzz/parse_url.cpp | 2 ++ tests/fuzz/signature.cpp | 2 ++ tests/fuzz/transaction.cpp | 2 ++ tests/net_load_tests/clt.cpp | 2 ++ tests/net_load_tests/srv.cpp | 2 ++ 17 files changed, 43 insertions(+), 1 deletion(-) diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index d5157365c..7e4eb337d 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -147,7 +147,8 @@ namespace misc_utils {} ~call_befor_die() { - m_func(); + try { m_func(); } + catch (...) { /* ignore */ } } }; diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 5ea04a353..37825e31d 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -51,11 +51,19 @@ threadpool::threadpool(unsigned int max_threads) : running(true), active(0) { } threadpool::~threadpool() { + try { const boost::unique_lock lock(mutex); running = false; has_work.notify_all(); } + catch (...) + { + // if the lock throws, we're just do it without a lock and hope, + // since the alternative is terminate + running = false; + has_work.notify_all(); + } for (size_t i = 0; i lock(mt); if (num) MERROR("wait should have been called before waiter dtor - waiting now"); } + catch (...) { /* ignore */ } try { wait(NULL); diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp index e5406f771..cc3b53b83 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.cpp @@ -35,6 +35,7 @@ #include #include "warnings.h" +#include "misc_log_ex.h" #include "crypto/crypto.h" #include "crypto/hash.h" #include "crypto-tests.h" @@ -59,6 +60,7 @@ bool operator !=(const key_derivation &a, const key_derivation &b) { DISABLE_GCC_WARNING(maybe-uninitialized) int main(int argc, char *argv[]) { + TRY_ENTRY(); fstream input; string cmd; size_t test = 0; @@ -266,4 +268,5 @@ int main(int argc, char *argv[]) { error = true; } return error ? 1 : 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/base58.cpp b/tests/fuzz/base58.cpp index 49516dd83..a4857bdd1 100644 --- a/tests/fuzz/base58.cpp +++ b/tests/fuzz/base58.cpp @@ -68,7 +68,9 @@ int Base58Fuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); Base58Fuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/block.cpp b/tests/fuzz/block.cpp index 2df77b046..eed3b94b2 100644 --- a/tests/fuzz/block.cpp +++ b/tests/fuzz/block.cpp @@ -61,6 +61,8 @@ int BlockFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); BlockFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/bulletproof.cpp b/tests/fuzz/bulletproof.cpp index 2f4dfd0ea..2f3a2f8d1 100644 --- a/tests/fuzz/bulletproof.cpp +++ b/tests/fuzz/bulletproof.cpp @@ -65,6 +65,8 @@ int BulletproofFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); BulletproofFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index 59b59810c..488a3b931 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -95,7 +95,9 @@ int ColdOutputsFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ColdOutputsFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp index da33dc318..fa3041ba3 100644 --- a/tests/fuzz/cold-transaction.cpp +++ b/tests/fuzz/cold-transaction.cpp @@ -97,6 +97,8 @@ int ColdTransactionFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ColdTransactionFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/http-client.cpp b/tests/fuzz/http-client.cpp index cd52643d9..909325832 100644 --- a/tests/fuzz/http-client.cpp +++ b/tests/fuzz/http-client.cpp @@ -92,7 +92,9 @@ int HTTPClientFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); HTTPClientFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp index 4ced1837f..d0c5803f5 100644 --- a/tests/fuzz/levin.cpp +++ b/tests/fuzz/levin.cpp @@ -341,7 +341,9 @@ int LevinFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); LevinFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/load_from_binary.cpp b/tests/fuzz/load_from_binary.cpp index 8f96c454f..89f122902 100644 --- a/tests/fuzz/load_from_binary.cpp +++ b/tests/fuzz/load_from_binary.cpp @@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); PortableStorageFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/load_from_json.cpp b/tests/fuzz/load_from_json.cpp index b0c1a9bf3..083555f7e 100644 --- a/tests/fuzz/load_from_json.cpp +++ b/tests/fuzz/load_from_json.cpp @@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); PortableStorageFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/parse_url.cpp b/tests/fuzz/parse_url.cpp index 8812cf9c2..fb5754a70 100644 --- a/tests/fuzz/parse_url.cpp +++ b/tests/fuzz/parse_url.cpp @@ -68,7 +68,9 @@ int ParseURLFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); ParseURLFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp index 6dadf960d..f82ada8b4 100644 --- a/tests/fuzz/signature.cpp +++ b/tests/fuzz/signature.cpp @@ -92,6 +92,8 @@ int SignatureFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); SignatureFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/fuzz/transaction.cpp b/tests/fuzz/transaction.cpp index b3349c383..934bd4685 100644 --- a/tests/fuzz/transaction.cpp +++ b/tests/fuzz/transaction.cpp @@ -61,6 +61,8 @@ int TransactionFuzzer::run(const std::string &filename) int main(int argc, const char **argv) { + TRY_ENTRY(); TransactionFuzzer fuzzer; return run_fuzzer(argc, argv, fuzzer); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/net_load_tests/clt.cpp b/tests/net_load_tests/clt.cpp index a65e02cab..4ae50d064 100644 --- a/tests/net_load_tests/clt.cpp +++ b/tests/net_load_tests/clt.cpp @@ -628,6 +628,7 @@ TEST_F(net_load_test_clt, permament_open_and_close_and_connections_closed_by_ser int main(int argc, char** argv) { + TRY_ENTRY(); tools::on_startup(); epee::debug::get_set_enable_assert(true, false); //set up logging options @@ -635,4 +636,5 @@ int main(int argc, char** argv) ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp index 6518d9117..dc3772127 100644 --- a/tests/net_load_tests/srv.cpp +++ b/tests/net_load_tests/srv.cpp @@ -215,6 +215,7 @@ namespace int main(int argc, char** argv) { + TRY_ENTRY(); tools::on_startup(); //set up logging options mlog_configure(mlog_get_default_log_path("net_load_tests_srv.log"), true); @@ -233,4 +234,5 @@ int main(int argc, char** argv) if (!tcp_server.run_server(thread_count, true)) return 2; return 0; + CATCH_ENTRY_L0("main", 1); } From 758d7684863b8ff001758c4360ed7087245eac03 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 2 Oct 2018 09:54:38 +0000 Subject: [PATCH 0042/1007] connection_basic: remove unused floating time start time --- contrib/epee/include/net/connection_basic.hpp | 3 --- contrib/epee/src/connection_basic.cpp | 7 ------- 2 files changed, 10 deletions(-) diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 095e747a5..7e8750047 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -92,7 +92,6 @@ class connection_basic { // not-templated base class for rapid developmet of som critical_section m_send_que_lock; std::list m_send_que; volatile bool m_is_multithreaded; - double m_start_time; /// Strand to ensure the connection's handlers are not called concurrently. boost::asio::io_service::strand strand_; /// Socket for the connection. @@ -112,8 +111,6 @@ class connection_basic { // not-templated base class for rapid developmet of som void logger_handle_net_write(size_t size); // network data written void logger_handle_net_read(size_t size); // network data read - void set_start_time(); - // config for rate limit static void set_rate_up_limit(uint64_t limit); diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index dea1928a7..9ab485839 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -250,22 +250,15 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q } } -void connection_basic::set_start_time() { - CRITICAL_REGION_LOCAL( network_throttle_manager::m_lock_get_global_throttle_out ); - m_start_time = network_throttle_manager::get_global_throttle_out().get_time_seconds(); -} void connection_basic::do_send_handler_write(const void* ptr , size_t cb ) { // No sleeping here; sleeping is done once and for all in connection::handle_write MTRACE("handler_write (direct) - before ASIO write, for packet="<::handle_write MTRACE("handler_write (after write, from queue="< Date: Tue, 2 Oct 2018 12:13:57 +0000 Subject: [PATCH 0043/1007] abstract_tcp_server2: move m_period to subclass This is where it is actually used, and initialized --- contrib/epee/include/net/abstract_tcp_server2.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index b2c05ebb0..3f726a352 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -246,7 +246,6 @@ namespace net_utils m_timer(io_serice) {} boost::asio::deadline_timer m_timer; - uint64_t m_period; }; template @@ -262,25 +261,27 @@ namespace net_utils { return m_handler(); } + uint64_t m_period; }; template bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms) { - boost::shared_ptr ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); + boost::shared_ptr> ptr(new idle_callback_conext(io_service_, t_callback, timeout_ms)); //needed call handler here ?... ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); + ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); return true; } - bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr ptr) + template + bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr> ptr) { //if handler return false - he don't want to be called anymore if(!ptr->call_handler()) return true; ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period)); - ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); + ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server::global_timer_handler, this, ptr)); return true; } From 00901e9c938dc801e963f98825c2ab5976fa8cc5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 2 Oct 2018 12:14:44 +0000 Subject: [PATCH 0044/1007] epee: initialize a few data members where it seems to be appropriate --- contrib/epee/include/net/levin_protocol_handler_async.h | 4 +++- contrib/epee/src/network_throttle-detail.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index e9853ee26..08aa1d468 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -99,7 +99,7 @@ class async_protocol_handler_config size_t get_connections_count(); void set_handler(levin_commands_handler* handler, void (*destroy)(levin_commands_handler*) = NULL); - async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE) + async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) {} ~async_protocol_handler_config() { set_handler(NULL, NULL); } void del_out_connections(size_t count); @@ -272,6 +272,8 @@ class async_protocol_handler m_wait_count = 0; m_oponent_protocol_ver = 0; m_connection_initialized = false; + m_invoke_buf_ready = 0; + m_invoke_result_code = LEVIN_ERROR_CONNECTION; } virtual ~async_protocol_handler() { diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index 7eeade3a1..28c85bb78 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -146,6 +146,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri m_network_add_cost = 128; m_network_minimal_segment = 256; m_network_max_segment = 1024*1024; + m_start_time = 0; m_any_packet_yet = false; m_slot_size = 1.0; // hard coded in few places m_target_speed = 16 * 1024; // other defaults are probably defined in the command-line parsing code when this class is used e.g. as main global throttle From 7f2ad1a768cd89c3e873c8d1750fe72f4ec47003 Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Wed, 3 Oct 2018 01:06:03 +0200 Subject: [PATCH 0045/1007] functional_tests: fix linking on Windows --- tests/functional_tests/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/functional_tests/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt index 7a2a7fbd1..4b21b945c 100644 --- a/tests/functional_tests/CMakeLists.txt +++ b/tests/functional_tests/CMakeLists.txt @@ -26,6 +26,10 @@ # 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. +if(WIN32) + set(EXTRA_LIBRARIES "${EXTRA_LIBRARIES};bcrypt") +endif() + set(functional_tests_sources main.cpp transactions_flow_test.cpp From 0a9bd1b3c2ed5b6be91e2bd11c5d9219d414b52a Mon Sep 17 00:00:00 2001 From: K3v1n Kur14k053 Date: Wed, 3 Oct 2018 18:41:28 +0530 Subject: [PATCH 0046/1007] Move cross compiling steps into proper heading As per #3430 --- README.md | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index d16b21528..45954680e 100644 --- a/README.md +++ b/README.md @@ -479,7 +479,7 @@ Then you can run make as usual. # Get binaries docker cp monero-android:/opt/android/monero/build/release/bin . -### Building portable statically linked binaries (Cross Compiling) +### Building portable statically linked binaries By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets: @@ -491,6 +491,25 @@ By default, in either dynamically or statically linked builds, binaries target t * ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems * ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems +### Cross Compiling + +You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system. Go to `contrib/depends` and type: + +* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries. +* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc +* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev +* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc +* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686 +* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf + +The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names. +Then go back to the source dir and type: + +* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends//share/toolchain.cmake``` +Where is one of the above mentioned targets. + +Using `depends` might also be easier to compile Monero on Windows than using MSys. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above. + ## Installing Monero from a package **DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.** @@ -534,22 +553,6 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of Packaging for your favorite distribution would be a welcome contribution! -You can also cross-compile binaries on linux for windows and macos with the depends system. Go to contrib/depends and type: - -* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries. -* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc -* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev -* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc -* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686 -* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf - -The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names. -Then go back to the source dir and type for example for windows 64bit: - -* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends/x86_64-w64-mingw32``` - -Using depends might also be easier to compile monero on windows than using msys. Activate windows subsystem for linux (for example ubuntu) install the apt build-essentials and follow the depends steps as depicted above. - ## Running monerod The build places the binary in `bin/` sub-directory within the build directory From 34a85e0cc395a9e8995ab46100fe5c6e5f9f1fd8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 3 Oct 2018 20:43:46 +0000 Subject: [PATCH 0047/1007] wallet2: disable height based segregation It can still be enable via DNS if a key reusing fork pops up --- src/wallet/wallet2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e6ab10756..5bdc75b13 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -114,9 +114,9 @@ using namespace cryptonote; #define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\003" -#define SEGREGATION_FORK_HEIGHT 1546000 -#define TESTNET_SEGREGATION_FORK_HEIGHT 1000000 -#define STAGENET_SEGREGATION_FORK_HEIGHT 1000000 +#define SEGREGATION_FORK_HEIGHT 99999999 +#define TESTNET_SEGREGATION_FORK_HEIGHT 99999999 +#define STAGENET_SEGREGATION_FORK_HEIGHT 99999999 #define SEGREGATION_FORK_VICINITY 1500 /* blocks */ #define FIRST_REFRESH_GRANULARITY 1024 From 02d3ef7bdae7d1dd7a9a6f4fee24631cf9403278 Mon Sep 17 00:00:00 2001 From: xiphon Date: Thu, 4 Oct 2018 00:01:09 +0000 Subject: [PATCH 0048/1007] blocks: use auto-generated .c files instead of 'LD -r -b binary' --- CMakeLists.txt | 5 +- src/blockchain_utilities/CMakeLists.txt | 20 +---- .../blockchain_import.cpp | 8 +- src/blocks/CMakeLists.txt | 35 ++++---- src/blocks/blockexports.c | 87 ------------------- src/blocks/blocks.cpp | 31 +++++++ src/blocks/blocks.dat | 0 src/blocks/blocks.h | 14 ++- src/cryptonote_config.h | 1 + src/cryptonote_core/CMakeLists.txt | 7 -- src/cryptonote_core/blockchain.cpp | 29 +++---- src/cryptonote_core/blockchain.h | 18 +++- src/cryptonote_core/cryptonote_core.cpp | 4 +- src/cryptonote_core/cryptonote_core.h | 3 +- src/daemon/CMakeLists.txt | 21 +---- src/daemon/core.h | 8 +- src/device/CMakeLists.txt | 7 -- 17 files changed, 113 insertions(+), 185 deletions(-) delete mode 100644 src/blocks/blockexports.c create mode 100644 src/blocks/blocks.cpp delete mode 100644 src/blocks/blocks.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index c31c14350..829a7e96c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,6 +180,9 @@ set(PER_BLOCK_CHECKPOINT 1) if(PER_BLOCK_CHECKPOINT) add_definitions("-DPER_BLOCK_CHECKPOINT") + set(Blocks "blocks") +else() + set(Blocks "") endif() list(INSERT CMAKE_MODULE_PATH 0 @@ -655,12 +658,10 @@ else() add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED) if (noexecstack_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack") - set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack) endif() add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED) if (noexecheap_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap") - set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap) endif() # some windows linker bits diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index ecd7b754c..873bf552c 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -26,20 +26,6 @@ # 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. -set(blocksdat "") -if(PER_BLOCK_CHECKPOINT) - if(APPLE AND DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(APPLE AND NOT DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(LINUX_32) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - endif() - set(blocksdat "blocksdat.o") -endif() - set(blockchain_import_sources blockchain_import.cpp bootstrap_file.cpp @@ -119,8 +105,7 @@ monero_private_headers(blockchain_depth monero_add_executable(blockchain_import ${blockchain_import_sources} - ${blockchain_import_private_headers} - ${blocksdat}) + ${blockchain_import_private_headers}) target_link_libraries(blockchain_import PRIVATE @@ -132,7 +117,8 @@ target_link_libraries(blockchain_import ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + ${Blocks}) if(ARCH_WIDTH) target_compile_definitions(blockchain_import diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 9ec768d26..134969dc4 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -37,6 +37,7 @@ #include "misc_log_ex.h" #include "bootstrap_file.h" #include "bootstrap_serialization.h" +#include "blocks/blocks.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() @@ -758,7 +759,12 @@ int main(int argc, char* argv[]) { core.disable_dns_checkpoints(true); - if (!core.init(vm, NULL)) +#if defined(PER_BLOCK_CHECKPOINT) + GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; +#else + GetCheckpointsCallback get_checkpoints = nullptr; +#endif + if (!core.init(vm, nullptr, nullptr, get_checkpoints)) { std::cerr << "Failed to initialize core" << ENDL; return 1; diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index ebb5408cc..bedda3b88 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -26,20 +26,23 @@ # 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. -if(APPLE) - add_library(blocks STATIC blockexports.c) - set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) -else() - if(LINUX_32) - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) - else() - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) - endif() - add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) - set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) -endif() +set(GENERATED_SOURCES "") +foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks) + set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c") + list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE}) + set(INPUT_DAT_FILE "${BLOB_NAME}.dat") + add_custom_command( + OUTPUT ${OUTPUT_C_SOURCE} + MAIN_DEPENDENCY ${INPUT_DAT_FILE} + COMMAND + cd ${CMAKE_CURRENT_BINARY_DIR} && + echo "'#include\t'" > ${OUTPUT_C_SOURCE} && + echo -n "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} && + od -v -An -w1 -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "':a;N;$$!ba;s/\\n/,/g'" >> ${OUTPUT_C_SOURCE} && + echo "'};'" >> ${OUTPUT_C_SOURCE} && + echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE} + ) +endforeach() + +add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES}) diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c deleted file mode 100644 index 0154b0413..000000000 --- a/src/blocks/blockexports.c +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#if defined(__APPLE__) -#include -#ifdef BUILD_SHARED_LIBS -#if !defined(__LP64__) -const struct mach_header _mh_execute_header; -#else -const struct mach_header_64 _mh_execute_header; -#endif -#else -#if !defined(__LP64__) -extern const struct mach_header _mh_execute_header; -#else -extern const struct mach_header_64 _mh_execute_header; -#endif -#endif - -const unsigned char *get_blocks_dat_start(int testnet, int stagenet) -{ - size_t size; - if (testnet) - return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); - else if (stagenet) - return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); - else - return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); -} - -size_t get_blocks_dat_size(int testnet, int stagenet) -{ - size_t size; - if (testnet) - getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); - else if (stagenet) - getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); - else - getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); - return size; -} - -#else - -#if defined(_WIN32) && !defined(_WIN64) -#define _binary_blocks_start binary_blocks_dat_start -#define _binary_blocks_end binary_blocks_dat_end -#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start -#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end -#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start -#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end -#else -#define _binary_blocks_start _binary_blocks_dat_start -#define _binary_blocks_end _binary_blocks_dat_end -#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start -#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end -#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start -#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end -#endif - -extern const unsigned char _binary_blocks_start[]; -extern const unsigned char _binary_blocks_end[]; -extern const unsigned char _binary_testnet_blocks_start[]; -extern const unsigned char _binary_testnet_blocks_end[]; -extern const unsigned char _binary_stagenet_blocks_start[]; -extern const unsigned char _binary_stagenet_blocks_end[]; - -const unsigned char *get_blocks_dat_start(int testnet, int stagenet) -{ - if (testnet) - return _binary_testnet_blocks_start; - else if (stagenet) - return _binary_stagenet_blocks_start; - else - return _binary_blocks_start; -} - -size_t get_blocks_dat_size(int testnet, int stagenet) -{ - if (testnet) - return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start); - else if (stagenet) - return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start); - else - return (size_t) (_binary_blocks_end - _binary_blocks_start); -} - -#endif diff --git a/src/blocks/blocks.cpp b/src/blocks/blocks.cpp new file mode 100644 index 000000000..0661f8448 --- /dev/null +++ b/src/blocks/blocks.cpp @@ -0,0 +1,31 @@ +#include "blocks.h" + +#include + +extern const unsigned char checkpoints[]; +extern const size_t checkpoints_len; +extern const unsigned char stagenet_blocks[]; +extern const size_t stagenet_blocks_len; +extern const unsigned char testnet_blocks[]; +extern const size_t testnet_blocks_len; + +namespace blocks +{ + + const std::unordered_map, std::hash> CheckpointsByNetwork = { + {cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}, + {cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}}, + {cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}} + }; + + const epee::span GetCheckpointsData(cryptonote::network_type network) + { + const auto it = CheckpointsByNetwork.find(network); + if (it != CheckpointsByNetwork.end()) + { + return it->second; + } + return nullptr; + } + +} diff --git a/src/blocks/blocks.dat b/src/blocks/blocks.dat deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h index ec683f47e..14e391319 100644 --- a/src/blocks/blocks.h +++ b/src/blocks/blocks.h @@ -1,16 +1,12 @@ #ifndef SRC_BLOCKS_BLOCKS_H_ #define SRC_BLOCKS_BLOCKS_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include "cryptonote_config.h" +#include "span.h" -const unsigned char *get_blocks_dat_start(int testnet, int stagenet); -size_t get_blocks_dat_size(int testnet, int stagenet); - -#ifdef __cplusplus +namespace blocks +{ + const epee::span GetCheckpointsData(cryptonote::network_type network); } -#endif - #endif /* SRC_BLOCKS_BLOCKS_H_ */ diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index a6858ce7c..c62eeb738 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -30,6 +30,7 @@ #pragma once +#include #include #include diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 72844db66..231489fdb 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -41,12 +41,6 @@ set(cryptonote_core_private_headers tx_pool.h cryptonote_tx_utils.h) -if(PER_BLOCK_CHECKPOINT) - set(Blocks "blocks") -else() - set(Blocks "") -endif() - monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) monero_add_library(cryptonote_core @@ -69,5 +63,4 @@ target_link_libraries(cryptonote_core ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} PRIVATE - ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index eb869b795..6c6e024e4 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -53,9 +53,6 @@ #include "ringct/rctSigs.h" #include "common/perf_timer.h" #include "common/notify.h" -#if defined(PER_BLOCK_CHECKPOINT) -#include "blocks/blocks.h" -#endif #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "blockchain" @@ -341,7 +338,7 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty) +bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback get_checkpoints/* = nullptr*/) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_tx_pool); @@ -439,7 +436,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline #if defined(PER_BLOCK_CHECKPOINT) if (m_nettype != FAKECHAIN) - load_compiled_in_block_hashes(); + load_compiled_in_block_hashes(get_checkpoints); #endif MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); @@ -4404,19 +4401,21 @@ void Blockchain::cancel() #if defined(PER_BLOCK_CHECKPOINT) static const char expected_block_hashes_hash[] = "954cb2bbfa2fe6f74b2cdd22a1a4c767aea249ad47ad4f7c9445f0f03260f511"; -void Blockchain::load_compiled_in_block_hashes() +void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints) { - const bool testnet = m_nettype == TESTNET; - const bool stagenet = m_nettype == STAGENET; - if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0) + if (get_checkpoints == nullptr || !m_fast_sync) { - MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); - + return; + } + const epee::span checkpoints = get_checkpoints(m_nettype); + if (!checkpoints.empty()) + { + MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)"); if (m_nettype == MAINNET) { // first check hash crypto::hash hash; - if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) + if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash)) { MERROR("Failed to hash precomputed blocks data"); return; @@ -4436,9 +4435,9 @@ void Blockchain::load_compiled_in_block_hashes() } } - if (get_blocks_dat_size(testnet, stagenet) > 4) + if (checkpoints.size() > 4) { - const unsigned char *p = get_blocks_dat_start(testnet, stagenet); + const unsigned char *p = checkpoints.data(); const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24); if (nblocks > (std::numeric_limits::max() - 4) / sizeof(hash)) { @@ -4446,7 +4445,7 @@ void Blockchain::load_compiled_in_block_hashes() return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); - if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed) + if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && checkpoints.size() >= size_needed) { p += sizeof(uint32_t); m_blocks_hash_of_hashes.reserve(nblocks); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index ab66fac8b..9b67765b5 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -38,9 +38,11 @@ #include #include #include +#include #include #include +#include "span.h" #include "syncobj.h" #include "string_tools.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -73,6 +75,15 @@ namespace cryptonote db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O) }; + /** + * @brief Callback routine that returns checkpoints data for specific network type + * + * @param network network type + * + * @return checkpoints data, empty span if there ain't any checkpoints for specific network type + */ + typedef std::function(cryptonote::network_type network)> GetCheckpointsCallback; + /************************************************************************/ /* */ /************************************************************************/ @@ -117,10 +128,11 @@ namespace cryptonote * @param offline true if running offline, else false * @param test_options test parameters * @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled + * @param get_checkpoints if set, will be called to get checkpoints data * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0); + bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0, const GetCheckpointsCallback get_checkpoints = nullptr); /** * @brief Initialize the Blockchain state @@ -1369,8 +1381,10 @@ namespace cryptonote * A (possibly empty) set of block hashes can be compiled into the * monero daemon binary. This function loads those hashes into * a useful state. + * + * @param get_checkpoints if set, will be called to get checkpoints data */ - void load_compiled_in_block_hashes(); + void load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints); /** * @brief expands v2 transaction data from blockchain diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 69e3c708b..3882a14ae 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -389,7 +389,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options) + bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback get_checkpoints/* = nullptr */) { start_time = std::time(nullptr); @@ -567,7 +567,7 @@ namespace cryptonote regtest_hard_forks }; const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty); - r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty); + r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty, get_checkpoints); r = m_mempool.init(max_txpool_weight); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 58fe5b7b5..882568330 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -244,10 +244,11 @@ namespace cryptonote * @param vm command line parameters * @param config_subdir subdirectory for config storage * @param test_options configuration options for testing + * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL); + bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback get_checkpoints = nullptr); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index f645836a4..117790455 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -26,20 +26,6 @@ # 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. -set(blocksdat "") -if(PER_BLOCK_CHECKPOINT) - if(APPLE AND DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(APPLE AND NOT DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(LINUX_32) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - endif() - set(blocksdat "blocksdat.o") -endif() - set(daemon_sources command_parser_executor.cpp command_server.cpp @@ -81,9 +67,7 @@ monero_private_headers(daemon monero_add_executable(daemon ${daemon_sources} ${daemon_headers} - ${daemon_private_headers} - ${blocksdat} -) + ${daemon_private_headers}) target_link_libraries(daemon PRIVATE rpc @@ -106,7 +90,8 @@ target_link_libraries(daemon ${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + ${Blocks}) set_property(TARGET daemon PROPERTY OUTPUT_NAME "monerod") diff --git a/src/daemon/core.h b/src/daemon/core.h index 475f418d6..eda8894a6 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -28,6 +28,7 @@ #pragma once +#include "blocks/blocks.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" @@ -85,7 +86,12 @@ class t_core final //initialize core here MGINFO("Initializing core..."); std::string config_subdir = get_config_subdir(); - if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str())) +#if defined(PER_BLOCK_CHECKPOINT) + cryptonote::GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; +#else + cryptonote::GetCheckpointsCallback get_checkpoints = nullptr; +#endif + if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints)) { return false; } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 8f446f42a..727134f75 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -58,12 +58,6 @@ endif() set(device_private_headers) -if(PER_BLOCK_CHECKPOINT) - set(Blocks "blocks") -else() - set(Blocks "") -endif() - monero_private_headers(device ${device_private_headers}) @@ -79,5 +73,4 @@ target_link_libraries(device ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} PRIVATE - ${Blocks} ${EXTRA_LIBRARIES}) From 5c4fe3d4a5973217f866568907af6ae3a9d2c5eb Mon Sep 17 00:00:00 2001 From: sanecito Date: Thu, 4 Oct 2018 01:43:16 -0700 Subject: [PATCH 0049/1007] Create Japanese file, add translations for "Monero::AddressBookImpl" and "Wallet" Contexts --- translations/monero_ja.ts | 4066 +++++++++++++++++++++++++++++++++++++ 1 file changed, 4066 insertions(+) create mode 100644 translations/monero_ja.ts diff --git a/translations/monero_ja.ts b/translations/monero_ja.ts new file mode 100644 index 000000000..ac5065d7d --- /dev/null +++ b/translations/monero_ja.ts @@ -0,0 +1,4066 @@ + + + + + Monero::AddressBookImpl + + + Invalid destination address + 不正な宛先アドレス + + + + Invalid payment ID. Short payment ID should only be used in an integrated address + 不正なペイメントIDありっます。インテグレーテットアドレスにだけ短いペイメントIDを使えます + + + + Invalid payment ID + 不正なペイメントID + + + + Integrated address and long payment ID can't be used at the same time + 同じ時にインテグレーテットアドレスと長いペイメントIDを使えません + + + + Monero::PendingTransactionImpl + + + Attempting to save transaction to file, but specified file(s) exist. Exiting to not risk overwriting. File: + + + + + Failed to write transaction(s) to file + + + + + daemon is busy. Please try again later. + + + + + no connection to daemon. Please make sure daemon is running. + + + + + transaction %s was rejected by daemon with status: + + + + + . Reason: + + + + + Unknown exception: + + + + + Unhandled exception + + + + + Monero::UnsignedTransactionImpl + + + This is a watch only wallet + + + + + + Failed to sign transaction + + + + + Claimed change does not go to a paid address + + + + + Claimed change is larger than payment to the change address + + + + + Change goes to more than one address + + + + + sending %s to %s + + + + + with no destinations + + + + + %s change to %s + + + + + no change + + + + + Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu. %s + + + + + Monero::WalletImpl + + + payment id has invalid format, expected 16 or 64 character hex string: + + + + + Failed to add short payment id: + + + + + + daemon is busy. Please try again later. + + + + + + no connection to daemon. Please make sure daemon is running. + + + + + + RPC error: + + + + + + not enough outputs for specified ring size + + + + + + found outputs to use + + + + + Please sweep unmixable outputs. + + + + + failed to get random outputs to mix + + + + + + not enough money to transfer, available only %s, sent amount %s + + + + + failed to parse address + + + + + failed to parse secret spend key + + + + + No view key supplied, cancelled + + + + + failed to parse secret view key + + + + + failed to verify secret spend key + + + + + spend key does not match address + + + + + failed to verify secret view key + + + + + view key does not match address + + + + + failed to generate new wallet: + + + + + Failed to send import wallet request + + + + + Failed to load unsigned transactions + + + + + Failed to load transaction from file + + + + + Wallet is view only + + + + + failed to save file + + + + + Key images can only be imported with a trusted daemon + + + + + Failed to import key images: + + + + + Failed to get subaddress label: + + + + + Failed to set subaddress label: + + + + + failed to get random outputs to mix: %s + + + + + + not enough money to transfer, overall balance only %s, sent amount %s + + + + + + not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee) + + + + + + output amount + + + + + + transaction was not constructed + + + + + + transaction %s was rejected by daemon with status: + + + + + + one of destinations is zero + + + + + + failed to find a suitable way to split transactions + + + + + + unknown transfer error: + + + + + + internal error: + + + + + + unexpected error: + + + + + + unknown error + + + + + + + + + + Failed to parse txid + + + + + no tx keys found for this txid + + + + + + Failed to parse tx key + + + + + + + + Failed to parse address + + + + + Address must not be a subaddress + + + + + Rescan spent can only be used with a trusted daemon + + + + + Wallet + + + Failed to parse address + + + + + Failed to parse key + + + + + failed to verify key + + + + + key does not match address + + + + + command_line + + + yes + + + + + no + + + + + cryptonote::rpc_args + + + Specify IP to bind RPC server + + + + + Specify username[:password] required for RPC server + + + + + Confirm rpc-bind-ip value is NOT a loopback (local) IP + + + + + Specify a comma separated list of origins to allow cross origin resource sharing + + + + + Invalid IP address given for -- + + + + + permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with -- + + + + + Username specified with -- + + + + + + cannot be empty + + + + + requires RPC server password -- + + + + + cryptonote::simple_wallet + + + Commands: + + + + + failed to read wallet password + + + + + invalid password + + + + + set seed: needs an argument. available options: language + + + + + set: unrecognized argument(s) + + + + + wallet file path not valid: + + + + + Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting. + + + + + usage: payment_id + + + + + needs an argument + + + + + + + + + + + + + + 0 or 1 + + + + + 0, 1, 2, 3, or 4 + + + + + + unsigned integer + + + + + NOTE: the following 25 words can be used to recover access to your wallet. Write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. + + + + + + --restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file + + + + + specify a recovery parameter with the --electrum-seed="words list here" + + + + + specify a wallet path with --generate-new-wallet (not --wallet-file) + + + + + wallet failed to connect to daemon: + + + + + Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version. + + + + + List of available languages for your wallet's seed: + + + + + Enter the number corresponding to the language of your choice: + + + + + You had been using a deprecated version of the wallet. Please use the new seed that we provide. + + + + + + + Generated new wallet: + + + + + + + failed to generate new wallet: + + + + + Opened watch-only wallet + + + + + Opened wallet + + + + + You had been using a deprecated version of the wallet. Please proceed to upgrade your wallet. + + + + + + You had been using a deprecated version of the wallet. Your wallet file format is being upgraded now. + + + + + + failed to load wallet: + + + + + Use the "help" command to see the list of available commands. + + + + + + Wallet data saved + + + + + Mining started in daemon + + + + + mining has NOT been started: + + + + + Mining stopped in daemon + + + + + mining has NOT been stopped: + + + + + Blockchain saved + + + + + + + Height + + + + + transaction + + + + + spent + + + + + unsupported transaction format + + + + + Starting refresh... + + + + + Refresh done, blocks received: + + + + + + payment id has invalid format, expected 16 or 64 character hex string: + + + + + bad locked_blocks parameter: + + + + + + + a single transaction cannot use more than one payment id: + + + + + + + + failed to set up payment id, though it was decoded correctly + + + + + + + + + + + + transaction cancelled. + + + + + + Is this okay anyway? (Y/Yes/N/No): + + + + + There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): + + + + + Failed to check for backlog: + + + + + + +Transaction + + + + + + Spending from address index %d + + + + + + + WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy. + + + + + + Sending %s. + + + + + Your transaction needs to be split into %llu transactions. This will result in a transaction fee being applied to each transaction, for a total fee of %s + + + + + The transaction fee is %s + + + + + , of which %s is dust from change + + + + + . + + + + + A total of %s from dust change will be sent to dust address + + + + + . +This transaction will unlock on block %llu, in approximately %s days (assuming 2 minutes per block) + + + + + + + + + + + + Failed to write transaction(s) to file + + + + + + + + + + + + Unsigned transaction(s) successfully written to file: + + + + + No unmixable outputs found + + + + + No address given + + + + + failed to parse Payment ID + + + + + usage: sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] + + + + + failed to parse key image + + + + + No outputs found + + + + + Multiple transactions are created, which is not supposed to happen + + + + + The transaction uses multiple or no inputs, which is not supposed to happen + + + + + missing threshold amount + + + + + invalid amount threshold + + + + + donations are not enabled on the testnet + + + + + usage: donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] + + + + + Claimed change does not go to a paid address + + + + + Claimed change is larger than payment to the change address + + + + + sending %s to %s + + + + + dummy output(s) + + + + + with no destinations + + + + + Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): + + + + + This is a multisig wallet, it can only sign with sign_multisig + + + + + usage: sign_transfer [export] + + + + + Failed to sign transaction + + + + + Failed to sign transaction: + + + + + Transaction raw hex data exported to + + + + + Failed to load transaction from file + + + + + + RPC error: + + + + + wallet is watch-only and has no spend key + + + + + + + Your original password was incorrect. + + + + + Error with wallet rewrite: + + + + + priority must be 0, 1, 2, 3, or 4 + + + + + + priority must be 0, 1, 2, 3, or 4 + + + + + invalid unit + + + + + + invalid count: must be an unsigned integer + + + + + invalid value + + + + + usage: set_log <log_level_number_0-4> | <categories> + + + + + (Y/Yes/N/No): + + + + + + bad m_restore_height parameter: + + + + + date format must be YYYY-MM-DD + + + + + Restore height is: + + + + + + Is this okay? (Y/Yes/N/No): + + + + + Daemon is local, assuming trusted + + + + + Password for new watch-only wallet + + + + + invalid arguments. Please use start_mining [<number_of_threads>] [do_bg_mining] [ignore_battery], <number_of_threads> should be from 1 to + + + + + internal error: + + + + + + + unexpected error: + + + + + + + + + + + + + unknown error + + + + + refresh failed: + + + + + Blocks received: + + + + + unlocked balance: + + + + + + + amount + + + + + false + + + + + Unknown command: + + + + + Command usage: + + + + + Command description: + + + + + wallet is multisig but not yet finalized + + + + + Enter optional seed encryption passphrase, empty to see raw seed + + + + + Failed to retrieve seed + + + + + wallet is multisig and has no seed + + + + + Cannot connect to daemon + + + + + Current fee is %s monero per kB + + + + + Error: failed to estimate backlog array size: + + + + + Error: bad estimated backlog array size + + + + + (current) + + + + + %u block (%u minutes) backlog at priority %u%s + + + + + %u to %u block (%u to %u minutes) backlog at priority %u + + + + + No backlog at priority + + + + + + This wallet is already multisig + + + + + + wallet is watch-only and cannot be made multisig + + + + + + This wallet has been used before, please use a new wallet to create a multisig wallet + + + + + Your password is incorrect. + + + + + Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info + + + + + This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants + + + + + usage: make_multisig <threshold> <multisiginfo1> [<multisiginfo2>...] + + + + + Invalid threshold + + + + + Another step is needed + + + + + Send this multisig info to all other participants, then use finalize_multisig <info1> [<info2>...] with others' multisig info + + + + + Error creating multisig: + + + + + Error creating multisig: new wallet is not multisig + + + + + multisig address: + + + + + + + This wallet is not multisig + + + + + This wallet is already finalized + + + + + usage: finalize_multisig <multisiginfo1> [<multisiginfo2>...] + + + + + Failed to finalize multisig + + + + + Failed to finalize multisig: + + + + + + + + + This multisig wallet is not yet finalized + + + + + usage: export_multisig_info <filename> + + + + + Error exporting multisig info: + + + + + Multisig info exported to + + + + + usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant + + + + + Multisig info imported + + + + + Failed to import multisig info: + + + + + Failed to update spent status after importing multisig info: + + + + + Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run "rescan_spent" + + + + + + + This is not a multisig wallet + + + + + usage: sign_multisig <filename> + + + + + Failed to sign multisig transaction + + + + + Multisig error: + + + + + Failed to sign multisig transaction: + + + + + It may be relayed to the network with submit_multisig + + + + + usage: submit_multisig <filename> + + + + + + Failed to load multisig transaction from file + + + + + + Multisig transaction signed by only %u signers, needs %u more signatures + + + + + + Transaction successfully submitted, transaction + + + + + + You can check its status by using the `show_transfers` command. + + + + + usage: export_raw_multisig <filename> + + + + + Failed to export multisig transaction to file + + + + + Saved exported multisig transaction file(s): + + + + + + + ring size must be an integer >= + + + + + could not change default ring size + + + + + Invalid height + + + + + start_mining [<number_of_threads>] [bg_mining] [ignore_battery] + + + + + Start mining in the daemon (bg_mining and ignore_battery are optional booleans). + + + + + Stop mining in the daemon. + + + + + set_daemon <host>[:<port>] + + + + + Set another daemon to connect to. + + + + + Save the current blockchain data. + + + + + Synchronize the transactions and balance. + + + + + balance [detail] + + + + + Show the wallet's balance of the currently selected account. + + + + + incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] + + + + + Show the incoming transfers, all or filtered by availability and address index. + + + + + payments <PID_1> [<PID_2> ... <PID_N>] + + + + + Show the payments for the given payment IDs. + + + + + Show the blockchain height. + + + + + transfer_original [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] + + + + + Transfer <amount> to <address> using an older transaction building algorithm. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + + + + transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] + + + + + Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + + + + locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>] + + + + + Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + + + + Send all unmixable outputs to yourself with ring_size 1 + + + + + sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] + + + + + Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. + + + + + sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] + + + + + Send all unlocked outputs below the threshold to an address. + + + + + sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] + + + + + Send a single output of the given key image to an address without change. + + + + + donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] + + + + + Donate <amount> to the development team (donate.getmonero.org). + + + + + sign_transfer <file> + + + + + Sign a transaction from a <file>. + + + + + Submit a signed transaction from a file. + + + + + set_log <level>|{+,-,}<categories> + + + + + Change the current log detail (level must be <0-4>). + + + + + account + account new <label text with white spaces allowed> + account switch <index> + account label <index> <label text with white spaces allowed> + account tag <tag_name> <account_index_1> [<account_index_2> ...] + account untag <account_index_1> [<account_index_2> ...] + account tag_description <tag_name> <description> + + + + + If no arguments are specified, the wallet shows all the existing accounts along with their balances. +If the "new" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty). +If the "switch" argument is specified, the wallet switches to the account specified by <index>. +If the "label" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text. +If the "tag" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, .... +If the "untag" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed. +If the "tag_description" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>. + + + + + address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>] + + + + + If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the wallet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text. + + + + + integrated_address [<payment_id> | <address>] + + + + + Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID + + + + + address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)] + + + + + Print all entries in the address book, optionally adding/deleting an entry to/from it. + + + + + Save the wallet data. + + + + + Save a watch-only keys file. + + + + + Display the private view key. + + + + + Display the private spend key. + + + + + Display the Electrum-style mnemonic seed + + + + + set <option> [<value>] + + + + + Available options: + seed language + Set the wallet's seed language. + always-confirm-transfers <1|0> + Whether to confirm unsplit txes. + print-ring-members <1|0> + Whether to print detailed information about ring members during confirmation. + store-tx-info <1|0> + Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference. + default-ring-size <n> + Set the default ring size (default and minimum is 5). + auto-refresh <1|0> + Whether to automatically synchronize new blocks from the daemon. + refresh-type <full|optimize-coinbase|no-coinbase|default> + Set the wallet's refresh behaviour. + priority [0|1|2|3|4] + Set the fee to default/unimportant/normal/elevated/priority. + confirm-missing-payment-id <1|0> + ask-password <1|0> + unit <monero|millinero|micronero|nanonero|piconero> + Set the default monero (sub-)unit. + min-outputs-count [n] + Try to keep at least that many outputs of value at least min-outputs-value. + min-outputs-value [n] + Try to keep at least min-outputs-count outputs of at least that value. + merge-destinations <1|0> + Whether to merge multiple payments to the same destination address. + confirm-backlog <1|0> + Whether to warn if there is transaction backlog. + confirm-backlog-threshold [n] + Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks. + refresh-from-block-height [n] + Set the height before which to ignore blocks. + auto-low-priority <1|0> + Whether to automatically use the low priority fee level when it's safe to do so. + + + + + Display the encrypted Electrum-style mnemonic seed. + + + + + Rescan the blockchain for spent outputs. + + + + + get_tx_key <txid> + + + + + Get the transaction key (r) for a given <txid>. + + + + + check_tx_key <txid> <txkey> <address> + + + + + Check the amount going to <address> in <txid>. + + + + + get_tx_proof <txid> <address> [<message>] + + + + + Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key. + + + + + check_tx_proof <txid> <address> <signature_file> [<message>] + + + + + Check the proof for funds going to <address> in <txid> with the challenge string <message> if any. + + + + + get_spend_proof <txid> [<message>] + + + + + Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>. + + + + + check_spend_proof <txid> <signature_file> [<message>] + + + + + Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>. + + + + + get_reserve_proof (all|<amount>) [<message>] + + + + + Generate a signature proving that you own at least this much, optionally with a challenge string <message>. +If 'all' is specified, you prove the entire sum of all of your existing accounts' balances. +Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account. + + + + + check_reserve_proof <address> <signature_file> [<message>] + + + + + Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>. + + + + + show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + + + + + Show the incoming/outgoing transfers within an optional height range. + + + + + unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] + + + + + Show the unspent outputs of a specified address within an optional amount range. + + + + + Rescan the blockchain from scratch. + + + + + set_tx_note <txid> [free text note] + + + + + Set an arbitrary string note for a <txid>. + + + + + get_tx_note <txid> + + + + + Get a string note for a txid. + + + + + set_description [free text note] + + + + + Set an arbitrary description for the wallet. + + + + + Get the description of the wallet. + + + + + Show the wallet's status. + + + + + Show the wallet's information. + + + + + sign <file> + + + + + Sign the contents of a file. + + + + + verify <filename> <address> <signature> + + + + + Verify a signature on the contents of a file. + + + + + export_key_images <file> + + + + + Export a signed set of key images to a <file>. + + + + + import_key_images <file> + + + + + Import a signed key images list and verify their spent status. + + + + + export_outputs <file> + + + + + Export a set of outputs owned by this wallet. + + + + + import_outputs <file> + + + + + Import a set of outputs owned by this wallet. + + + + + show_transfer <txid> + + + + + Show information about a transfer to/from this address. + + + + + Change the wallet's password. + + + + + Generate a new random full size payment id. These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids. + + + + + Print the information about the current fee and transaction backlog. + + + + + Export data needed to create a multisig wallet + + + + + make_multisig <threshold> <string1> [<string>...] + + + + + Turn this wallet into a multisig wallet + + + + + finalize_multisig <string> [<string>...] + + + + + Turn this wallet into a multisig wallet, extra step for N-1/N wallets + + + + + export_multisig_info <filename> + + + + + Export multisig info for other participants + + + + + import_multisig_info <filename> [<filename>...] + + + + + Import multisig info from other participants + + + + + sign_multisig <filename> + + + + + Sign a multisig transaction from a file + + + + + submit_multisig <filename> + + + + + Submit a signed multisig transaction from a file + + + + + export_raw_multisig_tx <filename> + + + + + Export a signed multisig transaction to a file + + + + + help [<command>] + + + + + Show the help section or the documentation about a <command>. + + + + + integer >= + + + + + block height + + + + + No wallet found with that name. Confirm creation of new wallet named: + + + + + can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name" and --generate-from-json="jsonfilename" + + + + + can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic + + + + + --restore-multisig-wallet uses --generate-new-wallet, not --wallet-file + + + + + specify a recovery parameter with the --electrum-seed="multisig seed here" + + + + + Multisig seed failed verification + + + + + Enter seed encryption passphrase, empty if none + + + + + + This address is a subaddress which cannot be used here. + + + + + Error: expected M/N, but got: + + + + + Error: expected N > 1 and N <= M, but got: + + + + + Error: M/N is currently unsupported. + + + + + Generating master wallet from %u of %u multisig wallet keys + + + + + failed to parse secret view key + + + + + failed to verify secret view key + + + + + Secret spend key (%u of %u): + + + + + Error: M/N is currently unsupported + + + + + Restore height + + + + + Still apply restore height? (Y/Yes/N/No): + + + + + Warning: using an untrusted daemon at %s, privacy will be lessened + + + + + Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command. + + + + + Your wallet has been generated! +To start synchronizing with the daemon, use the "refresh" command. +Use the "help" command to see the list of available commands. +Use "help <command>" to see a command's documentation. +Always use the "exit" command when closing monero-wallet-cli to save +your current session's state. Otherwise, you might need to synchronize +your wallet again (your wallet keys are NOT at risk in any case). + + + + + + failed to generate new mutlisig wallet + + + + + Generated new %u/%u multisig wallet: + + + + + Opened %u/%u multisig wallet%s + + + + + Use "help <command>" to see a command's documentation. + + + + + + wallet is multisig and cannot save a watch-only version + + + + + missing daemon URL argument + + + + + Unexpected array length - Exited simple_wallet::set_daemon() + + + + + This does not seem to be a valid daemon URL. + + + + + + txid + + + + + + idx + + + + + (Some owned outputs have partial key images - import_multisig_info needed) + + + + + Currently selected account: [ + + + + + ] + + + + + Tag: + + + + + (No tag assigned) + + + + + Balance per address: + + + + + Address + + + + + + Balance + + + + + + Unlocked balance + + + + + Outputs + + + + + + Label + + + + + %8u %6s %21s %21s %7u %21s + + + + + usage: balance [detail] + + + + + + usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + + + + + spent + + + + + global index + + + + + tx id + + + + + + addr index + + + + + No incoming transfers + + + + + No incoming available transfers + + + + + No incoming unavailable transfers + + + + + expected at least one payment ID + + + + + payment + + + + + transaction + + + + + height + + + + + unlock time + + + + + No payments with id + + + + + + + failed to get blockchain height: + + + + + + + + + failed to connect to the daemon + + + + + +Transaction %llu/%llu: txid=%s + + + + + +Input %llu/%llu: amount=%s + + + + + failed to get output: + + + + + output key's originating block height shouldn't be higher than the blockchain height + + + + + +Originating block heights: + + + + + +| + + + + + + | + + + + + + +Warning: Some input keys being spent are from + + + + + , which can break the anonymity of ring signature. Make sure this is intentional! + + + + + + Ring size must not be 0 + + + + + + ring size %u is too small, minimum is %u + + + + + wrong number of arguments + + + + + + + No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): + + + + + + No outputs found, or daemon is not ready + + + + + Transaction successfully saved to + + + + + + , txid + + + + + Failed to save transaction to + + + + + + Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No): + + + + + + + Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): + + + + + Donating + + + + + This is a watch only wallet + + + + + usage: show_transfer <txid> + + + + + Double spend seen on the network: this transaction may or may not end up being mined + + + + + Transaction ID not found + + + + + true + + + + + failed to parse refresh type + + + + + + wallet is watch-only and has no seed + + + + + + wallet is non-deterministic and has no seed + + + + + + wallet is watch-only and cannot transfer + + + + + could not change default priority + + + + + full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase) + + + + + monero, millinero, micronero, nanonero, piconero + + + + + Wallet name not valid. Please try again or use Ctrl-C to quit. + + + + + Wallet and key files found, loading... + + + + + Key file found but not wallet file. Regenerating... + + + + + Key file not found. Failed to open wallet: + + + + + Generating new wallet... + + + + + Electrum-style word list failed verification + + + + + + + + + + + + + + No data supplied, cancelled + + + + + + + + + + + + + + + + failed to parse address + + + + + + failed to parse view key secret key + + + + + + failed to verify view key secret key + + + + + + + view key does not match standard address + + + + + + + + + account creation failed + + + + + + + failed to parse spend key secret key + + + + + + failed to verify spend key secret key + + + + + + spend key does not match standard address + + + + + failed to open account + + + + + + + + + wallet is null + + + + + + invalid language choice entered. Please try again. + + + + + + View key: + + + + + You may want to remove the file "%s" and try again + + + + + failed to deinitialize wallet + + + + + + + this command requires a trusted daemon. Enable with --trusted-daemon + + + + + blockchain can't be saved: + + + + + + daemon is busy. Please try again later. + + + + + + no connection to daemon. Please make sure daemon is running. + + + + + refresh error: + + + + + Balance: + + + + + pubkey + + + + + key image + + + + + + unlocked + + + + + ringct + + + + + T + + + + + F + + + + + locked + + + + + RingCT + + + + + - + + + + + payment ID has invalid format, expected 16 or 64 character hex string: + + + + + failed to get spent status + + + + + the same transaction + + + + + blocks that are temporally very close + + + + + Locked blocks too high, max 1000000 (˜4 yrs) + + + + + + Good signature + + + + + + + Bad signature + + + + + usage: integrated_address [payment ID] + + + + + Standard address: + + + + + failed to parse payment ID or address + + + + + usage: address_book [(add (<address> [pid <long or short payment id>])|<integrated address> [<description possibly with whitespaces>])|(delete <index>)] + + + + + failed to parse payment ID + + + + + failed to parse index + + + + + Address book is empty. + + + + + Index: + + + + + + Address: + + + + + Payment ID: + + + + + + Description: + + + + + usage: set_tx_note [txid] free text note + + + + + usage: get_tx_note [txid] + + + + + usage: sign <filename> + + + + + wallet is watch-only and cannot sign + + + + + + + + failed to read file + + + + + usage: check_tx_proof <txid> <address> <signature_file> [<message>] + + + + + + + failed to load signature file + + + + + usage: get_spend_proof <txid> [<message>] + + + + + wallet is watch-only and cannot generate the proof + + + + + usage: check_spend_proof <txid> <signature_file> [<message>] + + + + + usage: get_reserve_proof (all|<amount>) [<message>] + + + + + The reserve proof can be generated only by a full wallet + + + + + usage: check_reserve_proof <address> <signature_file> [<message>] + + + + + Address must not be a subaddress + + + + + Good signature -- total: %s, spent: %s, unspent: %s + + + + + usage: show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + + + + + [Double spend seen on the network: this transaction may or may not end up being mined] + + + + + usage: unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] + + + + + There is no unspent output in the specified address + + + + + (no daemon) + + + + + (out of sync) + + + + + (Untitled account) + + + + + + + + + + failed to parse index: + + + + + + specify an index between 0 and + + + + + usage: + account + account new <label text with white spaces allowed> + account switch <index> + account label <index> <label text with white spaces allowed> + account tag <tag_name> <account_index_1> [<account_index_2> ...] + account untag <account_index_1> [<account_index_2> ...] + account tag_description <tag_name> <description> + + + + + +Grand total: + Balance: + + + + + , unlocked balance: + + + + + Untagged accounts: + + + + + Tag %s is unregistered. + + + + + Accounts with tag: + + + + + Tag's description: + + + + + Account + + + + + %c%8u %6s %21s %21s %21s + + + + + ---------------------------------------------------------------------------------- + + + + + %15s %21s %21s + + + + + Primary address + + + + + (used) + + + + + (Untitled address) + + + + + <index_min> is already out of bound + + + + + <index_max> exceeds the bound + + + + + usage: address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> ] + + + + + + Integrated addresses can only be created for account 0 + + + + + Integrated address: %s, payment ID: %s + + + + + Subaddress: + + + + + usage: get_description + + + + + no description found + + + + + description found: + + + + + Filename: + + + + + Watch only + + + + + %u/%u multisig%s + + + + + Normal + + + + + Type: + + + + + Testnet: + + + + + Yes + + + + + No + + + + + This wallet is multisig and cannot sign + + + + + usage: verify <filename> <address> <signature> + + + + + Bad signature from + + + + + Good signature from + + + + + usage: export_key_images <filename> + + + + + wallet is watch-only and cannot export key images + + + + + + + failed to save file + + + + + Signed key images exported to + + + + + usage: import_key_images <filename> + + + + + usage: export_outputs <filename> + + + + + Outputs exported to + + + + + usage: import_outputs <filename> + + + + + + + + amount is wrong: + + + + + expected number from 0 to + + + + + Sweeping + + + + + Money successfully sent, transaction: + + + + + Change goes to more than one address + + + + + %s change to %s + + + + + no change + + + + + + + Transaction successfully signed to file + + + + + usage: get_tx_key <txid> + + + + + + + + + + + + + failed to parse txid + + + + + Tx key: + + + + + no tx keys found for this txid + + + + + usage: get_tx_proof <txid> <address> [<message>] + + + + + + + signature file saved to: + + + + + + + failed to save signature file + + + + + usage: check_tx_key <txid> <txkey> <address> + + + + + + failed to parse tx key + + + + + + + error: + + + + + + received + + + + + + in txid + + + + + + received nothing in txid + + + + + + WARNING: this transaction is not yet included in the blockchain! + + + + + + This transaction has %u confirmations + + + + + + WARNING: failed to determine number of confirmations! + + + + + bad min_height parameter: + + + + + bad max_height parameter: + + + + + in + + + + + + out + + + + + failed + + + + + pending + + + + + <min_amount> should be smaller than <max_amount> + + + + + +Amount: + + + + + , number of keys: + + + + + + + + + + +Min block height: + + + + + +Max block height: + + + + + +Min amount found: + + + + + +Max amount found: + + + + + +Total count: + + + + + +Bin size: + + + + + +Outputs per *: + + + + + count + ^ + + + + + + | + + + + + + + + + + + +--> block height + + + + + + ^ + + + + + ^ + + + + + + + + + + + wallet + + + + + + Random payment ID: + + + + + Matching integrated address: + + + + + genms + + + Base filename (-1, -2, etc suffixes will be appended as needed) + + + + + Give threshold and participants at once as M/N + + + + + How many participants will share parts of the multisig wallet + + + + + How many signers are required to sign a valid transaction + + + + + Create testnet multisig wallets + + + + + Generating %u %u/%u multisig wallets + + + + + Error verifying multisig extra info + + + + + Error finalizing multisig + + + + + Generated multisig wallets for address + + + + + Error creating multisig wallets: + + + + + This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other + + + + + Error: expected N/M, but got: + + + + + + Error: either --scheme or both of --threshold and --participants may be given + + + + + Error: expected N > 1 and N <= M, but got N==%u and M==%d + + + + + Error: --filename-base is required + + + + + Error: unsupported scheme: only N/N and N-1/N are supported + + + + + sw + + + Generate new wallet and save it to <arg> + + + + + Generate incoming-only wallet from view key + + + + + Generate deterministic wallet from spend key + + + + + Generate wallet from private keys + + + + + Generate a master wallet from multisig wallet keys + + + + + Language for mnemonic + + + + + Specify Electrum seed for wallet recovery/creation + + + + + Recover wallet using Electrum-style mnemonic seed + + + + + Recover multisig wallet using Electrum-style mnemonic seed + + + + + Generate non-deterministic view and spend keys + + + + + Enable commands which rely on a trusted daemon + + + + + Allow communicating with a daemon that uses a different RPC version + + + + + Restore from specific blockchain height + + + + + The newly created transaction will not be relayed to the monero network + + + + + daemon is busy. Please try again later. + + + + + possibly lost connection to daemon + + + + + Error: + + + + + This is the command line monero wallet. It needs to connect to a monero +daemon to work correctly. + + + + + Failed to initialize wallet + + + + + tools::wallet2 + + + Use daemon instance at <host>:<port> + + + + + Use daemon instance at host <arg> instead of localhost + + + + + Wallet password file + + + + + Use daemon instance at port <arg> instead of 18081 + + + + + For testnet. Daemon must also be launched with --testnet flag + + + + + Restricts to view-only commands + + + + + can't specify daemon host or port more than once + + + + + can't specify more than one of --password and --password-file + + + + + the password file specified could not be read + + + + + Failed to load file + + + + + Wallet password (escape/quote as needed) + + + + + Specify username[:password] for daemon RPC client + + + + + no password specified; use --prompt-for-password to prompt for a password + + + + + Failed to parse JSON + + + + + Version %u too new, we can only grok up to %u + + + + + failed to parse view key secret key + + + + + + + failed to verify view key secret key + + + + + failed to parse spend key secret key + + + + + + + failed to verify spend key secret key + + + + + Electrum-style word list failed verification + + + + + At least one of Electrum-style word list and private view key and private spend key must be specified + + + + + Both Electrum-style word list and private key(s) specified + + + + + invalid address + + + + + view key does not match standard address + + + + + spend key does not match standard address + + + + + Cannot generate deprecated wallets from JSON + + + + + failed to parse address: + + + + + Address must be specified in order to create watch-only wallet + + + + + failed to generate new wallet: + + + + + + + + + + + + Primary account + + + + + No funds received in this tx. + + + + + failed to read file + + + + + tools::wallet_rpc_server + + + Daemon is local, assuming trusted + + + + + Failed to create directory + + + + + Failed to create directory %s: %s + + + + + Cannot specify -- + + + + + and -- + + + + + Failed to create file + + + + + . Check permissions or remove file + + + + + Error writing to file + + + + + RPC username/password is stored in file + + + + + Tag %s is unregistered. + + + + + Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee) + + + + + This is the RPC monero wallet. It needs to connect to a monero +daemon to work correctly. + + + + + Can't specify more than one of --wallet-file and --generate-from-json + + + + + Must specify --wallet-file or --generate-from-json or --wallet-dir + + + + + Loading wallet... + + + + + + Saving wallet... + + + + + + Successfully saved + + + + + Successfully loaded + + + + + Wallet initialization failed: + + + + + Failed to initialize wallet RPC server + + + + + Starting wallet RPC server + + + + + Failed to run wallet: + + + + + Stopped wallet RPC server + + + + + Failed to save wallet: + + + + + wallet_args + + + + + Wallet options + + + + + Generate wallet from JSON format file + + + + + Use wallet <arg> + + + + + Max number of threads to use for a parallel job + + + + + Specify log file + + + + + Config file + + + + + General options + + + + + This is the command line monero wallet. It needs to connect to a monero +daemon to work correctly. + + + + + Can't find config file + + + + + Logging to: + + + + + Logging to %s + + + + + Usage: + + + + From c5928bdec6e59acbdc4b1a076755e8e7324fce1a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 4 Oct 2018 13:37:41 +0000 Subject: [PATCH 0050/1007] wallet2_api: fix build with C++14 --- src/wallet/api/wallet.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 236928348..58a6db689 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -96,6 +96,9 @@ namespace { throw runtime_error("Multisig wallet is not finalized yet"); } } + void checkMultisigWalletReady(const std::unique_ptr &wallet) { + return checkMultisigWalletReady(wallet.get()); + } void checkMultisigWalletNotReady(const tools::wallet2* wallet) { if (!wallet) { @@ -111,6 +114,9 @@ namespace { throw runtime_error("Multisig wallet is already finalized"); } } + void checkMultisigWalletNotReady(const std::unique_ptr &wallet) { + return checkMultisigWalletNotReady(wallet.get()); + } } struct Wallet2CallbackImpl : public tools::i_wallet2_callback @@ -376,15 +382,15 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds) , m_rebuildWalletCache(false) , m_is_connected(false) { - m_wallet = std::make_unique(static_cast(nettype), kdf_rounds, true); - m_history = std::make_unique(this); - m_wallet2Callback = std::make_unique(this); - m_wallet->callback(m_wallet2Callback); + m_wallet.reset(new tools::wallet2(static_cast(nettype), kdf_rounds, true)); + m_history.reset(new TransactionHistoryImpl(this)); + m_wallet2Callback.reset(new Wallet2CallbackImpl(this)); + m_wallet->callback(m_wallet2Callback.get()); m_refreshThreadDone = false; m_refreshEnabled = false; - m_addressBook = std::make_unique(this); - m_subaddress = std::make_unique(this); - m_subaddressAccount = std::make_unique(this); + m_addressBook.reset(new AddressBookImpl(this)); + m_subaddress.reset(new SubaddressImpl(this)); + m_subaddressAccount.reset(new SubaddressAccountImpl(this)); m_refreshIntervalMillis = DEFAULT_REFRESH_INTERVAL_MILLIS; @@ -399,6 +405,7 @@ WalletImpl::~WalletImpl() { LOG_PRINT_L1(__FUNCTION__); + m_wallet->callback(NULL); // Pause refresh thread - prevents refresh from starting again pauseRefresh(); // Close wallet - stores cache and stops ongoing refresh operation From a061353254826d7c2904081bd80519763f097061 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Wed, 19 Sep 2018 13:39:17 +0100 Subject: [PATCH 0051/1007] secure_pwd_reader: Add proper Unicode handling [Ryo contribution] --- src/common/password.cpp | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/common/password.cpp b/src/common/password.cpp index 5671c4a4e..6ff160595 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -56,8 +56,6 @@ namespace bool read_from_tty(epee::wipeable_string& pass, bool hide_input) { - static constexpr const char BACKSPACE = 8; - HANDLE h_cin = ::GetStdHandle(STD_INPUT_HANDLE); DWORD mode_old; @@ -67,32 +65,46 @@ namespace bool r = true; pass.reserve(tools::password_container::max_password_size); + std::vector chlen; + chlen.reserve(tools::password_container::max_password_size); while (pass.size() < tools::password_container::max_password_size) { DWORD read; - char ch; - r = (TRUE == ::ReadConsoleA(h_cin, &ch, 1, &read, NULL)); + wchar_t ucs2_ch; + r = (TRUE == ::ReadConsoleW(h_cin, &ucs2_ch, 1, &read, NULL)); r &= (1 == read); + if (!r) { break; } - else if (ch == '\n' || ch == '\r') + else if (ucs2_ch == L'\n' || ucs2_ch == L'\r') { std::cout << std::endl; break; } - else if (ch == BACKSPACE) + else if (ucs2_ch == L'\b') { if (!pass.empty()) { - pass.pop_back(); + int len = chlen.back(); + chlen.pop_back(); + while(len-- > 0) + pass.pop_back(); } + continue; } - else - { - pass.push_back(ch); - } + + char utf8_ch[8] = {0}; + int len; + if((len = WideCharToMultiByte(CP_UTF8, 0, &ucs2_ch, 1, utf8_ch, sizeof(utf8_ch), NULL, NULL)) <= 0) + break; + + if(pass.size() + len >= tools::password_container::max_password_size) + break; + + chlen.push_back(len); + pass += utf8_ch; } ::SetConsoleMode(h_cin, mode_old); From 3b402ebb85979528fdc779778c19a01ef169ef34 Mon Sep 17 00:00:00 2001 From: Jkat Date: Thu, 4 Oct 2018 14:43:14 -0400 Subject: [PATCH 0052/1007] Updating Monero GUI repo link in README.i18n.md --- README.i18n.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.i18n.md b/README.i18n.md index 504fc9e75..a3bd8070e 100644 --- a/README.i18n.md +++ b/README.i18n.md @@ -3,7 +3,7 @@ Monero daemon internationalization The Monero command line tools can be translated in various languages. If you wish to contribute and need help/support, contact the [Monero Localization Workgroup on Taiga](https://taiga.getmonero.org/project/erciccione-monero-localization/) or come chat on `#monero-translations` (Freenode/IRC, riot/matrix, MatterMost) -In order to use the same translation workflow as the [Monero Core GUI](https://github.com/monero-project/monero-core), they use Qt Linguist translation files. However, to avoid the dependencies on Qt this normally implies, they use a custom loader to read those files at runtime. +In order to use the same translation workflow as the [Monero Core GUI](https://github.com/monero-project/monero-gui), they use Qt Linguist translation files. However, to avoid the dependencies on Qt this normally implies, they use a custom loader to read those files at runtime. ### Tools for translators From 9a856697246f245795f8d8e18f635237c80f64c8 Mon Sep 17 00:00:00 2001 From: AnythingTechPro Date: Thu, 4 Oct 2018 22:12:53 -0400 Subject: [PATCH 0053/1007] rpc: fixed typo in JSON command error response message --- src/rpc/core_rpc_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index be511a2d2..d8f556d3e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1090,7 +1090,7 @@ namespace cryptonote { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to tx pub key in coinbase extra"); + LOG_ERROR("Failed to get tx pub key in coinbase extra"); return false; } res.reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); From ee71ba9869c37e92cb56590bb344e6e937d91c54 Mon Sep 17 00:00:00 2001 From: sanecito Date: Fri, 5 Oct 2018 00:39:23 -0700 Subject: [PATCH 0054/1007] Add translations for Monero::PendingTransactionImpl, command_line Contexts --- translations/monero_ja.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/translations/monero_ja.ts b/translations/monero_ja.ts index ac5065d7d..939f9188f 100644 --- a/translations/monero_ja.ts +++ b/translations/monero_ja.ts @@ -29,42 +29,42 @@ Attempting to save transaction to file, but specified file(s) exist. Exiting to not risk overwriting. File: - + ファイルは既に存在するのでファイルに取引を書き出せなかった。上書きしないにエグジットしてます。ファイル: Failed to write transaction(s) to file - + ファイルに取引を書き出せなかった daemon is busy. Please try again later. - + デーモン忙しいです。後でもう一度試してください。 no connection to daemon. Please make sure daemon is running. - + デーモンの接続が確立ありません。デーモンが実行中になっていることを確認してください。 transaction %s was rejected by daemon with status: - + 取引 %s がデーモンによって拒否しました。ステータス: . Reason: - + 。 理由: Unknown exception: - + 未知の例外: Unhandled exception - + 未処理の例外 @@ -385,22 +385,22 @@ Failed to parse address - + アドレスを解析できませんでした Failed to parse key - + キーを解析できませんでした failed to verify key - + キーを検証できませんでした key does not match address - + キーがアドレスと一致しませんでした @@ -408,12 +408,12 @@ yes - + はい no - + いいえ From fb3593c22e08a74adddf4403fa13ff36cee20045 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Thu, 4 Oct 2018 15:07:00 +0200 Subject: [PATCH 0055/1007] Add check if submodules need to be updated Adds CMake check that pulls from the different git remotes and checks if there is any output. --- CMakeLists.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c31c14350..b890965f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,25 @@ else() message(STATUS "Building without build tag") endif() +if(NOT MANUAL_SUBMODULES) + find_package(Git) + if(GIT_FOUND) + message(STATUS "Checking submodules") + execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/miniupnp && git rev-parse HEAD" OUTPUT_VARIABLE miniupnpLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/unbound && git rev-parse HEAD" OUTPUT_VARIABLE unboundLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson && git rev-parse HEAD" OUTPUT_VARIABLE rapidjsonLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/miniupnp | awk '{print $3}'" OUTPUT_VARIABLE miniupnpCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/unbound | awk '{print $3}'" OUTPUT_VARIABLE unboundCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson | awk '{print $3}'" OUTPUT_VARIABLE rapidjsonCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + string(COMPARE EQUAL "${miniupnpLocalHead}" "${miniupnpCheckedHead}" miniupnpUpToDate) + string(COMPARE EQUAL "${unboundLocalHead}" "${unboundCheckedHead}" unboundUpToDate) + string(COMPARE EQUAL "${rapidjsonLocalHead}" "${rapidjsonCheckedHead}" rapidjsonUpToDate) + if (NOT miniupnpUpToDate OR NOT unboundUpToDate OR NOT rapidjsonUpToDate) + message(FATAL_ERROR "Submodules not up to date. Please update with git subdmoule init && git submodule update, or run cmake with -DMANUAL_SUBMODULES=1") + endif() + endif() +endif() + set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG ${OPT_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${OPT_FLAGS_RELEASE}") From 977df6315fa9aab63c4f3155e565c93aa49e5463 Mon Sep 17 00:00:00 2001 From: Guillaume LE VAILLANT Date: Sat, 6 Oct 2018 10:12:38 +0200 Subject: [PATCH 0056/1007] Fix some calls to the translation function Some strings were not detected by lupdate because "tr() cannot be called without context". --- src/gen_multisig/gen_multisig.cpp | 2 +- src/simplewallet/simplewallet.cpp | 82 +- src/wallet/wallet2.cpp | 4 +- translations/monero.ts | 4283 ++++++++++++++++++----------- 4 files changed, 2686 insertions(+), 1685 deletions(-) diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index 69be70e1b..b69ca52ff 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -104,7 +104,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str wallets[n]->decrypt_keys(pwd_container->password()); if (!tools::wallet2::verify_multisig_info(wallets[n]->get_multisig_info(), sk[n], pk[n])) { - tools::fail_msg_writer() << tr("Failed to verify multisig info"); + tools::fail_msg_writer() << genms::tr("Failed to verify multisig info"); return false; } wallets[n]->encrypt_keys(pwd_container->password()); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index a1d6eb590..3112280c9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -180,14 +180,14 @@ namespace auto pwd_container = tools::password_container::prompt(verify, prompt); if (!pwd_container) { - tools::fail_msg_writer() << tr("failed to read wallet password"); + tools::fail_msg_writer() << sw::tr("failed to read wallet password"); } return pwd_container; } boost::optional default_password_prompter(bool verify) { - return password_prompter(verify ? tr("Enter a new password for the wallet") : tr("Wallet password"), verify); + return password_prompter(verify ? sw::tr("Enter a new password for the wallet") : sw::tr("Wallet password"), verify); } inline std::string interpret_rpc_response(bool ok, const std::string& status) @@ -265,7 +265,7 @@ namespace } else { - fail_msg_writer() << tr("invalid argument: must be either 0/1, true/false, y/n, yes/no"); + fail_msg_writer() << sw::tr("invalid argument: must be either 0/1, true/false, y/n, yes/no"); return false; } } @@ -321,18 +321,18 @@ namespace std::string dnssec_str; if (dnssec_valid) { - dnssec_str = tr("DNSSEC validation passed"); + dnssec_str = sw::tr("DNSSEC validation passed"); } else { - dnssec_str = tr("WARNING: DNSSEC validation was unsuccessful, this address may not be correct!"); + dnssec_str = sw::tr("WARNING: DNSSEC validation was unsuccessful, this address may not be correct!"); } std::stringstream prompt; - prompt << tr("For URL: ") << url + prompt << sw::tr("For URL: ") << url << ", " << dnssec_str << std::endl - << tr(" Monero Address = ") << addresses[0] + << sw::tr(" Monero Address = ") << addresses[0] << std::endl - << tr("Is this OK? (Y/n) ") + << sw::tr("Is this OK? (Y/n) ") ; // prompt the user for confirmation given the dns query and dnssec status std::string confirm_dns_ok = input_line(prompt.str()); @@ -342,7 +342,7 @@ namespace } if (!command_line::is_yes(confirm_dns_ok)) { - std::cout << tr("you have cancelled the transfer request") << std::endl; + std::cout << sw::tr("you have cancelled the transfer request") << std::endl; return {}; } return addresses[0]; @@ -363,7 +363,7 @@ namespace uint32_t subaddr_index; if(!epee::string_tools::get_xtype_from_string(subaddr_index, subaddr_index_str)) { - fail_msg_writer() << tr("failed to parse index: ") << subaddr_index_str; + fail_msg_writer() << sw::tr("failed to parse index: ") << subaddr_index_str; subaddr_indices.clear(); return false; } @@ -376,7 +376,7 @@ namespace { auto r = tools::parse_subaddress_lookahead(str); if (!r) - fail_msg_writer() << tr("invalid format for subaddress lookahead; must be :"); + fail_msg_writer() << sw::tr("invalid format for subaddress lookahead; must be :"); return r; } @@ -389,27 +389,27 @@ namespace } catch (const tools::error::daemon_busy&) { - fail_msg_writer() << tr("daemon is busy. Please try again later."); + fail_msg_writer() << sw::tr("daemon is busy. Please try again later."); } catch (const tools::error::no_connection_to_daemon&) { - fail_msg_writer() << tr("no connection to daemon. Please make sure daemon is running."); + fail_msg_writer() << sw::tr("no connection to daemon. Please make sure daemon is running."); } catch (const tools::error::wallet_rpc_error& e) { LOG_ERROR("RPC error: " << e.to_string()); - fail_msg_writer() << tr("RPC error: ") << e.what(); + fail_msg_writer() << sw::tr("RPC error: ") << e.what(); } catch (const tools::error::get_outs_error &e) { - fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); + fail_msg_writer() << sw::tr("failed to get random outputs to mix: ") << e.what(); } catch (const tools::error::not_enough_unlocked_money& e) { LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); - fail_msg_writer() << tr("Not enough money in unlocked balance"); + fail_msg_writer() << sw::tr("Not enough money in unlocked balance"); warn_of_possible_attack = false; } catch (const tools::error::not_enough_money& e) @@ -417,7 +417,7 @@ namespace LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % print_money(e.available()) % print_money(e.tx_amount())); - fail_msg_writer() << tr("Not enough money in unlocked balance"); + fail_msg_writer() << sw::tr("Not enough money in unlocked balance"); warn_of_possible_attack = false; } catch (const tools::error::tx_not_possible& e) @@ -427,30 +427,30 @@ namespace print_money(e.tx_amount() + e.fee()) % print_money(e.tx_amount()) % print_money(e.fee())); - fail_msg_writer() << tr("Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees"); + fail_msg_writer() << sw::tr("Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees"); warn_of_possible_attack = false; } catch (const tools::error::not_enough_outs_to_mix& e) { auto writer = fail_msg_writer(); - writer << tr("not enough outputs for specified ring size") << " = " << (e.mixin_count() + 1) << ":"; + writer << sw::tr("not enough outputs for specified ring size") << " = " << (e.mixin_count() + 1) << ":"; for (std::pair outs_for_amount : e.scanty_outs()) { - writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second; + writer << "\n" << sw::tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << sw::tr("found outputs to use") << " = " << outs_for_amount.second; } - writer << tr("Please use sweep_unmixable."); + writer << sw::tr("Please use sweep_unmixable."); } catch (const tools::error::tx_not_constructed&) - { - fail_msg_writer() << tr("transaction was not constructed"); + { + fail_msg_writer() << sw::tr("transaction was not constructed"); warn_of_possible_attack = false; } catch (const tools::error::tx_rejected& e) { - fail_msg_writer() << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status(); + fail_msg_writer() << (boost::format(sw::tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status(); std::string reason = e.reason(); if (!reason.empty()) - fail_msg_writer() << tr("Reason: ") << reason; + fail_msg_writer() << sw::tr("Reason: ") << reason; } catch (const tools::error::tx_sum_overflow& e) { @@ -459,38 +459,38 @@ namespace } catch (const tools::error::zero_destination&) { - fail_msg_writer() << tr("one of destinations is zero"); + fail_msg_writer() << sw::tr("one of destinations is zero"); warn_of_possible_attack = false; } catch (const tools::error::tx_too_big& e) { - fail_msg_writer() << tr("failed to find a suitable way to split transactions"); + fail_msg_writer() << sw::tr("failed to find a suitable way to split transactions"); warn_of_possible_attack = false; } catch (const tools::error::transfer_error& e) { LOG_ERROR("unknown transfer error: " << e.to_string()); - fail_msg_writer() << tr("unknown transfer error: ") << e.what(); + fail_msg_writer() << sw::tr("unknown transfer error: ") << e.what(); } catch (const tools::error::multisig_export_needed& e) { LOG_ERROR("Multisig error: " << e.to_string()); - fail_msg_writer() << tr("Multisig error: ") << e.what(); + fail_msg_writer() << sw::tr("Multisig error: ") << e.what(); warn_of_possible_attack = false; } catch (const tools::error::wallet_internal_error& e) { LOG_ERROR("internal error: " << e.to_string()); - fail_msg_writer() << tr("internal error: ") << e.what(); + fail_msg_writer() << sw::tr("internal error: ") << e.what(); } catch (const std::exception& e) { LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << tr("unexpected error: ") << e.what(); + fail_msg_writer() << sw::tr("unexpected error: ") << e.what(); } if (warn_of_possible_attack) - fail_msg_writer() << tr("There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a transaction immediately. Alternatively, connect to another node so the original node cannot correlate information."); + fail_msg_writer() << sw::tr("There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a transaction immediately. Alternatively, connect to another node so the original node cannot correlate information."); } bool check_file_overwrite(const std::string &filename) @@ -500,10 +500,10 @@ namespace { if (boost::ends_with(filename, ".keys")) { - fail_msg_writer() << boost::format(tr("File %s likely stores wallet private keys! Use a different file name.")) % filename; + fail_msg_writer() << boost::format(sw::tr("File %s likely stores wallet private keys! Use a different file name.")) % filename; return false; } - return command_line::is_yes(input_line((boost::format(tr("File %s already exists. Are you sure to overwrite it? (Y/Yes/N/No): ")) % filename).str())); + return command_line::is_yes(input_line((boost::format(sw::tr("File %s already exists. Are you sure to overwrite it? (Y/Yes/N/No): ")) % filename).str())); } return true; } @@ -6577,16 +6577,16 @@ static std::string get_human_readable_timespan(std::chrono::seconds seconds) { uint64_t ts = seconds.count(); if (ts < 60) - return std::to_string(ts) + tr(" seconds"); + return std::to_string(ts) + sw::tr(" seconds"); if (ts < 3600) - return std::to_string((uint64_t)(ts / 60)) + tr(" minutes"); + return std::to_string((uint64_t)(ts / 60)) + sw::tr(" minutes"); if (ts < 3600 * 24) - return std::to_string((uint64_t)(ts / 3600)) + tr(" hours"); + return std::to_string((uint64_t)(ts / 3600)) + sw::tr(" hours"); if (ts < 3600 * 24 * 30.5) - return std::to_string((uint64_t)(ts / (3600 * 24))) + tr(" days"); + return std::to_string((uint64_t)(ts / (3600 * 24))) + sw::tr(" days"); if (ts < 3600 * 24 * 365.25) - return std::to_string((uint64_t)(ts / (3600 * 24 * 30.5))) + tr(" months"); - return tr("a long time"); + return std::to_string((uint64_t)(ts / (3600 * 24 * 30.5))) + sw::tr(" months"); + return sw::tr("a long time"); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_transfers(const std::vector &args_) @@ -8096,7 +8096,7 @@ int main(int argc, char* argv[]) if (!command.empty()) { if (!w.process_command(command)) - fail_msg_writer() << tr("Unknown command: ") << command.front(); + fail_msg_writer() << sw::tr("Unknown command: ") << command.front(); w.stop(); w.deinit(); } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5bdc75b13..303e2fb5f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -258,7 +258,7 @@ std::unique_ptr make_basic(const boost::program_options::variabl trusted_daemon = false; if (tools::is_local_address(daemon_address)) { - MINFO(tr("Daemon is local, assuming trusted")); + MINFO(tools::wallet2::tr("Daemon is local, assuming trusted")); trusted_daemon = true; } } @@ -310,7 +310,7 @@ boost::optional get_password(const boost::program_opt THROW_WALLET_EXCEPTION_IF(!password_prompter, tools::error::wallet_internal_error, tools::wallet2::tr("no password specified; use --prompt-for-password to prompt for a password")); - return password_prompter(verify ? tr("Enter a new password for the wallet") : tr("Wallet password"), verify); + return password_prompter(verify ? tools::wallet2::tr("Enter a new password for the wallet") : tools::wallet2::tr("Wallet password"), verify); } std::pair, tools::password_container> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, bool unattended, const options& opts, const std::function(const char *, bool)> &password_prompter) diff --git a/translations/monero.ts b/translations/monero.ts index 5f0ba0c7c..8d4ee7ab8 100644 --- a/translations/monero.ts +++ b/translations/monero.ts @@ -27,45 +27,55 @@ Monero::PendingTransactionImpl - + Attempting to save transaction to file, but specified file(s) exist. Exiting to not risk overwriting. File: - + Failed to write transaction(s) to file - + daemon is busy. Please try again later. - + no connection to daemon. Please make sure daemon is running. - + transaction %s was rejected by daemon with status: - + . Reason: - + Unknown exception: - + Unhandled exception + + + Couldn't multisig sign data: + + + + + Couldn't sign multisig transaction: + + Monero::UnsignedTransactionImpl @@ -124,281 +134,406 @@ Monero::WalletImpl - + payment id has invalid format, expected 16 or 64 character hex string: - + Failed to add short payment id: - - + + daemon is busy. Please try again later. - - + + no connection to daemon. Please make sure daemon is running. - - + + RPC error: - - - not enough outputs for specified ring size + + failed to get outputs to mix: %s - - - found outputs to use + + + not enough outputs for specified ring size - - Please sweep unmixable outputs. + + + found outputs to use - - failed to get random outputs to mix + + Please sweep unmixable outputs. - - + + not enough money to transfer, available only %s, sent amount %s - + failed to parse address - + failed to parse secret spend key - - No view key supplied, cancelled + + Neither view key nor spend key supplied, cancelled - + failed to parse secret view key - + failed to verify secret spend key - + spend key does not match address - + failed to verify secret view key - + view key does not match address - + + failed to generate new wallet: - + + Electrum seed is empty + + + + + Electrum-style word list failed verification + + + + Failed to send import wallet request - + Failed to load unsigned transactions - + Failed to load transaction from file - + Wallet is view only - + failed to save file - + Key images can only be imported with a trusted daemon - + Failed to import key images: - + Failed to get subaddress label: - + Failed to set subaddress label: - - failed to get random outputs to mix: %s + + Failed to get multisig info: + + + + + Failed to make multisig: + + + + + Failed to finalize multisig wallet creation + + + + + Failed to finalize multisig wallet creation: + + + + + Failed to export multisig images: + + + + + Failed to parse imported multisig images + + + + + Failed to import multisig images: + + + + + Failed to check for partial multisig key images: + + + + + Failed to restore multisig transaction: + + + + + Invalid destination address + + + + + Invalid output: - - + + not enough money to transfer, overall balance only %s, sent amount %s - - + + not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee) - - + + output amount - - + + transaction was not constructed - - + + transaction %s was rejected by daemon with status: - - + + one of destinations is zero - - + + failed to find a suitable way to split transactions - - + + unknown transfer error: - - + + internal error: - - + + unexpected error: - - + + unknown error - - - - - - + + failed to get outputs to mix + + + + + + + + + + Failed to parse txid - + no tx keys found for this txid - - + + Failed to parse tx key - - - - + + + + Failed to parse address - + Address must not be a subaddress - + + The wallet must be in multisig ready state + + + + + Given string is not a key + + + + Rescan spent can only be used with a trusted daemon + + + Failed to set blackballed outputs + + + + + + Failed to parse output amount + + + + + + Failed to parse output offset + + + + + Failed to blackball output + + + + + Failed to unblackball output + + + + + + Failed to parse key image + + + + + Failed to get ring + + + + + Failed to get rings + + + + + Failed to set ring + + Wallet - + Failed to parse address - + Failed to parse key - + failed to verify key - + key does not match address @@ -449,18 +584,18 @@ - + Username specified with -- - - + + cannot be empty - + requires RPC server password -- @@ -468,2531 +603,3408 @@ cryptonote::simple_wallet - - Commands: + + Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version. - - failed to read wallet password + + Enter the number corresponding to the language of your choice: - - invalid password + + There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): - - set seed: needs an argument. available options: language + + + Spending from address index %d + - - set: unrecognized argument(s) + + Sending %s. - - wallet file path not valid: + + Your transaction needs to be split into %llu transactions. This will result in a transaction fee being applied to each transaction, for a total fee of %s - - Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting. + + The transaction fee is %s - - usage: payment_id + + , of which %s is dust from change - - needs an argument + + A total of %s from dust change will be sent to dust address - - - - - - - - - - - 0 or 1 + + . +This transaction will unlock on block %llu, in approximately %s days (assuming 2 minutes per block) - - 0, 1, 2, 3, or 4 + + Not enough money in unlocked balance - - - unsigned integer + + No address given - - NOTE: the following 25 words can be used to recover access to your wallet. Write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. - + + missing lockedblocks parameter - - --restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file + + bad locked_blocks parameter - - specify a recovery parameter with the --electrum-seed="words list here" + + failed to parse Payment ID - - specify a wallet path with --generate-new-wallet (not --wallet-file) + + failed to parse key image - - wallet failed to connect to daemon: + + No outputs found - - Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version. + + Multiple transactions are created, which is not supposed to happen - - List of available languages for your wallet's seed: + + The transaction uses multiple or no inputs, which is not supposed to happen - - Enter the number corresponding to the language of your choice: + + Money successfully sent, transaction: - - You had been using a deprecated version of the wallet. Please use the new seed that we provide. - + + missing threshold amount - - - Generated new wallet: + + invalid amount threshold - - - - failed to generate new wallet: + + donations are not enabled on the testnet or on the stagenet - - Opened watch-only wallet + + usage: donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] - - Opened wallet + + Claimed change does not go to a paid address - - You had been using a deprecated version of the wallet. Please proceed to upgrade your wallet. - + + Claimed change is larger than payment to the change address - - You had been using a deprecated version of the wallet. Your wallet file format is being upgraded now. - + + Change goes to more than one address - - failed to load wallet: + + sending %s to %s - - Use the "help" command to see the list of available commands. - + + dummy output(s) - - Wallet data saved + + with no destinations - - Mining started in daemon + + no change - - mining has NOT been started: + + Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): - - Mining stopped in daemon + + (Y/Yes/N/No): - - mining has NOT been stopped: + + + + Is this okay? (Y/Yes/N/No): - - Blockchain saved + + Daemon is local, assuming trusted - - - - Height + + Password for new watch-only wallet - - transaction + + false - - spent + + Commands: - - unsupported transaction format + + Unknown command: - - Starting refresh... + + Command usage: - - Refresh done, blocks received: + + Command description: - - - payment id has invalid format, expected 16 or 64 character hex string: + + wallet is watch-only and has no spend key - - bad locked_blocks parameter: + + + + + + + + + + + + + + + + + + + + + + command not supported by HW wallet - - - - a single transaction cannot use more than one payment id: + + + wallet is watch-only and has no seed - - - - - failed to set up payment id, though it was decoded correctly + + wallet is multisig but not yet finalized - - - - - - - - - transaction cancelled. + + + wallet is non-deterministic and has no seed - - - Is this okay anyway? (Y/Yes/N/No): + + Failed to retrieve seed - - There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): + + wallet is multisig and has no seed - - Failed to check for backlog: + + Incorrect password - - - -Transaction + + + + Your original password was incorrect. - - - Spending from address index %d - + + Error with wallet rewrite: - - - WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy. - + + usage: payment_id - - Sending %s. + + + Random payment ID: - - Your transaction needs to be split into %llu transactions. This will result in a transaction fee being applied to each transaction, for a total fee of %s + + Cannot connect to daemon - - The transaction fee is %s + + Current fee is %s %s per %s - - , of which %s is dust from change + + Error: failed to estimate backlog array size: - - . + + Error: bad estimated backlog array size - - A total of %s from dust change will be sent to dust address + + (current) - - . -This transaction will unlock on block %llu, in approximately %s days (assuming 2 minutes per block) + + %u block (%u minutes) backlog at priority %u%s - - - - - - - - - Failed to write transaction(s) to file + + %u to %u block (%u to %u minutes) backlog at priority %u - - - - - - - - - Unsigned transaction(s) successfully written to file: + + No backlog at priority - - No unmixable outputs found + + + This wallet is already multisig - - No address given + + + wallet is watch-only and cannot be made multisig - - failed to parse Payment ID + + + This wallet has been used before, please use a new wallet to create a multisig wallet - - usage: sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] + + Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info - - failed to parse key image + + This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants - - No outputs found + + usage: make_multisig <threshold> <multisiginfo1> [<multisiginfo2>...] - - Multiple transactions are created, which is not supposed to happen + + Invalid threshold - - The transaction uses multiple or no inputs, which is not supposed to happen + + Another step is needed - - missing threshold amount + + Send this multisig info to all other participants, then use finalize_multisig <info1> [<info2>...] with others' multisig info - - invalid amount threshold + + Error creating multisig: - - donations are not enabled on the testnet + + Error creating multisig: new wallet is not multisig - - usage: donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] + + multisig address: - - Claimed change does not go to a paid address + + + + This wallet is not multisig - - Claimed change is larger than payment to the change address + + This wallet is already finalized - - sending %s to %s + + usage: finalize_multisig <multisiginfo1> [<multisiginfo2>...] - - dummy output(s) + + Failed to finalize multisig - - with no destinations + + Failed to finalize multisig: - - Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): + + + + + + This multisig wallet is not yet finalized - - This is a multisig wallet, it can only sign with sign_multisig + + usage: export_multisig_info <filename> - - usage: sign_transfer [export] + + + + failed to save file - - Failed to sign transaction + + Error exporting multisig info: - - Failed to sign transaction: + + Multisig info exported to - - Transaction raw hex data exported to + + usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant - - Failed to load transaction from file + + + + + failed to read file - - - RPC error: + + Multisig info imported - - wallet is watch-only and has no spend key + + Failed to import multisig info: - - - - Your original password was incorrect. + + Failed to update spent status after importing multisig info: - - Error with wallet rewrite: + + Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run "rescan_spent" - - priority must be 0, 1, 2, 3, or 4 + + + + This is not a multisig wallet - - - priority must be 0, 1, 2, 3, or 4 + + usage: sign_multisig <filename> - - invalid unit + + Failed to sign multisig transaction - - - invalid count: must be an unsigned integer + + Multisig error: - - invalid value + + Failed to sign multisig transaction: - - usage: set_log <log_level_number_0-4> | <categories> + + + + Transaction successfully signed to file - - (Y/Yes/N/No): + + It may be relayed to the network with submit_multisig - - - bad m_restore_height parameter: + + usage: submit_multisig <filename> - - date format must be YYYY-MM-DD + + + Failed to load multisig transaction from file - - Restore height is: + + + Multisig transaction signed by only %u signers, needs %u more signatures - - - Is this okay? (Y/Yes/N/No): + + + Transaction successfully submitted, transaction - - Daemon is local, assuming trusted + + + You can check its status by using the `show_transfers` command. - - Password for new watch-only wallet + + + + + + + + + + unknown error - - invalid arguments. Please use start_mining [<number_of_threads>] [do_bg_mining] [ignore_battery], <number_of_threads> should be from 1 to + + usage: export_raw_multisig <filename> - - internal error: + + Failed to export multisig transaction to file - - - - unexpected error: + + Saved exported multisig transaction file(s): - - - - - - - - - - unknown error + + + + unexpected error: - - refresh failed: + + usage: print_ring <key_image|txid> - - Blocks received: + + + Invalid key image - - unlocked balance: + + Invalid txid - - - - amount + + Key image either not spent, or spent with mixin 0 - - false + + Failed to get key image ring: - - Unknown command: + + File doesn't exist - - Command usage: + + Invalid ring specification: - - Command description: + + Invalid key image: - - wallet is multisig but not yet finalized + + Invalid ring type, expected relative or abosolute: - - Enter optional seed encryption passphrase, empty to see raw seed + + + Error reading line: - - Failed to retrieve seed + + Invalid ring: - - wallet is multisig and has no seed + + Invalid relative ring: - - Cannot connect to daemon + + Invalid absolute ring: - - Current fee is %s monero per kB + + Failed to set ring for key image: - - Error: failed to estimate backlog array size: + + Continuing. - - Error: bad estimated backlog array size + + usage: set_ring <filename> | ( <key_image> absolute|relative <index> [<index>...] ) - - (current) + + Missing absolute or relative keyword - - %u block (%u minutes) backlog at priority %u%s + + + invalid index: must be a strictly positive unsigned integer - - %u to %u block (%u to %u minutes) backlog at priority %u + + invalid index: indices wrap - - No backlog at priority + + invalid index: indices should be in strictly ascending order - - - This wallet is already multisig + + failed to set ring - - - wallet is watch-only and cannot be made multisig + + Bad argument: - - - This wallet has been used before, please use a new wallet to create a multisig wallet + + should be "add" - - Your password is incorrect. + + Failed to open file - - Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info + + Failed to blackball output: - - This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants + + + Failed to unblackball output: - - usage: make_multisig <threshold> <multisiginfo1> [<multisiginfo2>...] + + Blackballed: - - Invalid threshold + + not blackballed: - - Another step is needed + + Failed to save known rings: - - Send this multisig info to all other participants, then use finalize_multisig <info1> [<info2>...] with others' multisig info + + + wallet is watch-only and cannot transfer - - Error creating multisig: + + + + ring size must be an integer >= - - Error creating multisig: new wallet is not multisig + + + WARNING: this is a non default ring size, which may harm your privacy. Default is recommended. - - multisig address: + + could not change default ring size - - - - This wallet is not multisig + + + + priority must be either 0, 1, 2, 3, or 4, or one of: - - This wallet is already finalized + + could not change default priority - - usage: finalize_multisig <multisiginfo1> [<multisiginfo2>...] + + invalid unit - - Failed to finalize multisig + + + invalid count: must be an unsigned integer - - Failed to finalize multisig: + + invalid value - - - - - - This multisig wallet is not yet finalized + + + Invalid height - - usage: export_multisig_info <filename> + + start_mining [<number_of_threads>] [bg_mining] [ignore_battery] - - Error exporting multisig info: + + Start mining in the daemon (bg_mining and ignore_battery are optional booleans). - - Multisig info exported to + + Stop mining in the daemon. - - usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant + + set_daemon <host>[:<port>] [trusted|untrusted] - - Multisig info imported + + Set another daemon to connect to. - - Failed to import multisig info: + + Save the current blockchain data. - - Failed to update spent status after importing multisig info: + + Synchronize the transactions and balance. - - Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run "rescan_spent" + + balance [detail] - - - - This is not a multisig wallet + + Show the wallet's balance of the currently selected account. - - usage: sign_multisig <filename> + + incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] - - Failed to sign multisig transaction + + Show the incoming transfers, all or filtered by availability and address index. - - Multisig error: + + payments <PID_1> [<PID_2> ... <PID_N>] - - Failed to sign multisig transaction: + + Show the payments for the given payment IDs. - - It may be relayed to the network with submit_multisig + + Show the blockchain height. - - usage: submit_multisig <filename> + + locked_sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <lockblocks> [<payment_id>] - - - Failed to load multisig transaction from file + + Send all unlocked balance to an address and lock it for <lockblocks> (max. 1000000). If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. <priority> is the priority of the sweep. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. - - - Multisig transaction signed by only %u signers, needs %u more signatures + + Send all unmixable outputs to yourself with ring_size 1 - - - Transaction successfully submitted, transaction + + sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] - - - You can check its status by using the `show_transfers` command. + + Send all unlocked outputs below the threshold to an address. - - usage: export_raw_multisig <filename> + + Send a single output of the given key image to an address without change. - - Failed to export multisig transaction to file + + donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] - - Saved exported multisig transaction file(s): + + Donate <amount> to the development team (donate.getmonero.org). - - - - ring size must be an integer >= + + sign_transfer [export_raw] - - could not change default ring size + + Sign a transaction from a file. If the parameter "export_raw" is specified, transaction raw hex data suitable for the daemon RPC /sendrawtransaction is exported. - - Invalid height + + Submit a signed transaction from a file. - - start_mining [<number_of_threads>] [bg_mining] [ignore_battery] + + set_log <level>|{+,-,}<categories> - - Start mining in the daemon (bg_mining and ignore_battery are optional booleans). + + Change the current log detail (level must be <0-4>). - - Stop mining in the daemon. + + account + account new <label text with white spaces allowed> + account switch <index> + account label <index> <label text with white spaces allowed> + account tag <tag_name> <account_index_1> [<account_index_2> ...] + account untag <account_index_1> [<account_index_2> ...] + account tag_description <tag_name> <description> - - set_daemon <host>[:<port>] + + If no arguments are specified, the wallet shows all the existing accounts along with their balances. +If the "new" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty). +If the "switch" argument is specified, the wallet switches to the account specified by <index>. +If the "label" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text. +If the "tag" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, .... +If the "untag" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed. +If the "tag_description" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>. - - Set another daemon to connect to. + + address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>] - - Save the current blockchain data. + + If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the wallet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text. - - Synchronize the transactions and balance. + + integrated_address [<payment_id> | <address>] - - balance [detail] + + Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID - - Show the wallet's balance of the currently selected account. + + address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)] - - incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] + + Print all entries in the address book, optionally adding/deleting an entry to/from it. - - Show the incoming transfers, all or filtered by availability and address index. + + Save the wallet data. - - payments <PID_1> [<PID_2> ... <PID_N>] + + Save a watch-only keys file. - - Show the payments for the given payment IDs. + + Display the private view key. - - Show the blockchain height. + + Display the private spend key. - - transfer_original [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] + + Display the Electrum-style mnemonic seed - - Transfer <amount> to <address> using an older transaction building algorithm. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + set <option> [<value>] - - transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] + + Display the encrypted Electrum-style mnemonic seed. - - Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + Rescan the blockchain for spent outputs. - - locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>] + + get_tx_key <txid> - - Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) + + Get the transaction key (r) for a given <txid>. - - Send all unmixable outputs to yourself with ring_size 1 + + set_tx_key <txid> <tx_key> - - sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] + + Set the transaction key (r) for a given <txid> in case the tx was made by some other device or 3rd party wallet. - - Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. + + check_tx_key <txid> <txkey> <address> - - sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] + + Check the amount going to <address> in <txid>. - - Send all unlocked outputs below the threshold to an address. + + get_tx_proof <txid> <address> [<message>] - - sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] + + Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key. - - Send a single output of the given key image to an address without change. + + check_tx_proof <txid> <address> <signature_file> [<message>] - - donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] + + Check the proof for funds going to <address> in <txid> with the challenge string <message> if any. + + + + + get_spend_proof <txid> [<message>] + + + + + Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>. + + + + + check_spend_proof <txid> <signature_file> [<message>] + + + + + Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>. + + + + + get_reserve_proof (all|<amount>) [<message>] + + + + + Generate a signature proving that you own at least this much, optionally with a challenge string <message>. +If 'all' is specified, you prove the entire sum of all of your existing accounts' balances. +Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account. + + + + + check_reserve_proof <address> <signature_file> [<message>] + + + + + Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>. + + + + + show_transfers [in|out|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + + + + + Show the incoming/outgoing transfers within an optional height range. + + + + + unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] + + + + + Show the unspent outputs of a specified address within an optional amount range. + + + + + Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself. + + + + + set_tx_note <txid> [free text note] + + + + + Set an arbitrary string note for a <txid>. + + + + + get_tx_note <txid> + + + + + Get a string note for a txid. + + + + + set_description [free text note] + + + + + Set an arbitrary description for the wallet. + + + + + Get the description of the wallet. + + + + + Show the wallet's status. + + + + + Show the wallet's information. + + + + + sign <file> + + + + + Sign the contents of a file. + + + + + verify <filename> <address> <signature> + + + + + Verify a signature on the contents of a file. + + + + + export_key_images <file> + + + + + Export a signed set of key images to a <file>. + + + + + import_key_images <file> + + + + + Import a signed key images list and verify their spent status. + + + + + hw_reconnect + + + + + Attempts to reconnect HW wallet. + + + + + export_outputs <file> + + + + + Export a set of outputs owned by this wallet. + + + + + import_outputs <file> + + + + + Import a set of outputs owned by this wallet. + + + + + show_transfer <txid> + + + + + Show information about a transfer to/from this address. + + + + + Change the wallet's password. + + + + + Generate a new random full size payment id. These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids. + + + + + Print the information about the current fee and transaction backlog. + + + + + Export data needed to create a multisig wallet + + + + + make_multisig <threshold> <string1> [<string>...] + + + + + Turn this wallet into a multisig wallet + + + + + finalize_multisig <string> [<string>...] + + + + + Turn this wallet into a multisig wallet, extra step for N-1/N wallets + + + + + export_multisig_info <filename> + + + + + Export multisig info for other participants + + + + + import_multisig_info <filename> [<filename>...] + + + + + Import multisig info from other participants + + + + + sign_multisig <filename> + + + + + Sign a multisig transaction from a file + + + + + submit_multisig <filename> + + + + + Submit a signed multisig transaction from a file + + + + + export_raw_multisig_tx <filename> + + + + + Export a signed multisig transaction to a file + + + + + print_ring <key_image> | <txid> + + + + + Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) + + + + + set_ring <filename> | ( <key_image> absolute|relative <index> [<index>...] ) + + + + + Set the ring used for a given key image, so it can be reused in a fork + + + + + save_known_rings + + + + + Save known rings to the shared rings database + + + + + Blackball output(s) so they never get selected as fake outputs in a ring + + + + + Unblackballs an output so it may get selected as a fake output in a ring + + + + + Checks whether an output is blackballed + + + + + version + + + + + Returns version information + + + + + help [<command>] + + + + + Show the help section or the documentation about a <command>. + + + + + needs an argument + + + + + set seed: needs an argument. available options: language + + + + + + + + + + + + + + + + 0 or 1 + + + + + integer >= + + + + + full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase) + + + + + 0, 1, 2, 3, or 4, or one of + + + + + 0|1|2 (or never|action|decrypt) + + + + + monero, millinero, micronero, nanonero, piconero + + + + + + + unsigned integer + + + + + + + amount + + + + + block height + + + + + <major>:<minor> + + + + + set: unrecognized argument(s) + + + + + usage: set_log <log_level_number_0-4> | <categories> + + + + + wrong number range, use: set_log <log_level_number_0-4> | <categories> + + + + + Wallet name not valid. Please try again or use Ctrl-C to quit. + + + + + Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting. + + + + + Wallet and key files found, loading... + + + + + Key file found but not wallet file. Regenerating... + + + + + Key file not found. Failed to open wallet: + + + + + No wallet found with that name. Confirm creation of new wallet named: + + + + + Generating new wallet... + + + + + NOTE: the following 25 words can be used to recover access to your wallet. Write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. + + + + + + Can't specify more than one of --testnet and --stagenet + + + + + can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name", --generate-from-json="jsonfilename" and --generate-from-device="wallet_name" + + + + + can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic + + + + + --restore-multisig-wallet uses --generate-new-wallet, not --wallet-file + + + + + --restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file + + + + + specify a recovery parameter with the --electrum-seed="multisig seed here" + + + + + specify a recovery parameter with the --electrum-seed="words list here" + + + + + Multisig seed failed verification + + + + + Electrum-style word list failed verification + + + + + + + + + + + + + + No data supplied, cancelled + + + + + + + + + + + + + + + + failed to parse address + + + + + + This address is a subaddress which cannot be used here. + + + + + + failed to parse view key secret key + + + + + + failed to verify view key secret key + + + + + + + view key does not match standard address + + + + + + + + + + account creation failed + + + + + + + failed to parse spend key secret key + + + + + + failed to verify spend key secret key + + + + + + spend key does not match standard address + + + + + Error: expected M/N, but got: + + + + + Error: expected N > 1 and N <= M, but got: + + + + + Error: M/N is currently unsupported. + + + + + Generating master wallet from %u of %u multisig wallet keys + + + + + failed to parse secret view key + + + + + failed to verify secret view key + + + + + Secret spend key (%u of %u): + + + + + Error: M/N is currently unsupported + + + + + No restore height is specified. + + + + + Assumed you are creating a new account, restore will be done from current estimated blockchain height. + + + + + Use --restore-height if you want to restore an already setup account from a specific height + + + + + account creation aborted + + + + + specify a wallet path with --generate-new-wallet (not --wallet-file) + + + + + + bad m_restore_height parameter: + + + + + date format must be YYYY-MM-DD + + + + + Restore height is: + + + + + Restore height + + + + + Still apply restore height? (Y/Yes/N/No): + + + + + can't specify --subaddress-lookahead and --wallet-file at the same time + + + + + failed to open account + + + + + + + + + wallet is null + + + + + Warning: using an untrusted daemon at %s, privacy will be lessened + + + + + Failed to initialize ring database: privacy enhancing features will be inactive + + + + + wallet failed to connect to daemon: + + + + + Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command. + + + + + List of available languages for your wallet's seed: + + + + + If your display freezes, exit blind with ^C, then run again with --use-english-language-names + + + + + + invalid language choice entered. Please try again. + + + + + + invalid password - - Donate <amount> to the development team (donate.getmonero.org). + + You had been using a deprecated version of the wallet. Please use the new seed that we provide. + - - sign_transfer <file> + + + Generated new wallet: - - Sign a transaction from a <file>. + + View key: - - Submit a signed transaction from a file. + + + + + failed to generate new wallet: - - set_log <level>|{+,-,}<categories> + + Your wallet has been generated! +To start synchronizing with the daemon, use the "refresh" command. +Use the "help" command to see the list of available commands. +Use "help <command>" to see a command's documentation. +Always use the "exit" command when closing monero-wallet-cli to save +your current session's state. Otherwise, you might need to synchronize +your wallet again (your wallet keys are NOT at risk in any case). + - - Change the current log detail (level must be <0-4>). + + Generated new wallet on hw device: - - account - account new <label text with white spaces allowed> - account switch <index> - account label <index> <label text with white spaces allowed> - account tag <tag_name> <account_index_1> [<account_index_2> ...] - account untag <account_index_1> [<account_index_2> ...] - account tag_description <tag_name> <description> + + failed to generate new mutlisig wallet - - If no arguments are specified, the wallet shows all the existing accounts along with their balances. -If the "new" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty). -If the "switch" argument is specified, the wallet switches to the account specified by <index>. -If the "label" argument is specified, the wallet sets the label of the account specified by <index> to the provided label text. -If the "tag" argument is specified, a tag <tag_name> is assigned to the specified accounts <account_index_1>, <account_index_2>, .... -If the "untag" argument is specified, the tags assigned to the specified accounts <account_index_1>, <account_index_2> ..., are removed. -If the "tag_description" argument is specified, the tag <tag_name> is assigned an arbitrary text <description>. + + Generated new %u/%u multisig wallet: - - address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>] + + wallet file path not valid: - - If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the wallet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text. + + Key file not found. Failed to open wallet - - integrated_address [<payment_id> | <address>] + + Opened watch-only wallet - - Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID + + Opened %u/%u multisig wallet%s - - address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)] + + Opened wallet - - Print all entries in the address book, optionally adding/deleting an entry to/from it. + + You had been using a deprecated version of the wallet. Please proceed to upgrade your wallet. + - - Save the wallet data. + + You had been using a deprecated version of the wallet. Your wallet file format is being upgraded now. + - - Save a watch-only keys file. + + failed to load wallet: - - Display the private view key. + + Use the "help" command to see the list of available commands. + - - Display the private spend key. + + Use "help <command>" to see a command's documentation. + - - Display the Electrum-style mnemonic seed + + failed to deinitialize wallet - - set <option> [<value>] + + Wallet data saved - - Available options: - seed language - Set the wallet's seed language. - always-confirm-transfers <1|0> - Whether to confirm unsplit txes. - print-ring-members <1|0> - Whether to print detailed information about ring members during confirmation. - store-tx-info <1|0> - Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference. - default-ring-size <n> - Set the default ring size (default and minimum is 5). - auto-refresh <1|0> - Whether to automatically synchronize new blocks from the daemon. - refresh-type <full|optimize-coinbase|no-coinbase|default> - Set the wallet's refresh behaviour. - priority [0|1|2|3|4] - Set the fee to default/unimportant/normal/elevated/priority. - confirm-missing-payment-id <1|0> - ask-password <1|0> - unit <monero|millinero|micronero|nanonero|piconero> - Set the default monero (sub-)unit. - min-outputs-count [n] - Try to keep at least that many outputs of value at least min-outputs-value. - min-outputs-value [n] - Try to keep at least min-outputs-count outputs of at least that value. - merge-destinations <1|0> - Whether to merge multiple payments to the same destination address. - confirm-backlog <1|0> - Whether to warn if there is transaction backlog. - confirm-backlog-threshold [n] - Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks. - refresh-from-block-height [n] - Set the height before which to ignore blocks. - auto-low-priority <1|0> - Whether to automatically use the low priority fee level when it's safe to do so. + + wallet is multisig and cannot save a watch-only version - - Display the encrypted Electrum-style mnemonic seed. + + failed to read wallet password - - Rescan the blockchain for spent outputs. + + Watch only wallet saved as: - - get_tx_key <txid> + + Failed to save watch only wallet: - - Get the transaction key (r) for a given <txid>. + + + + this command requires a trusted daemon. Enable with --trusted-daemon - - check_tx_key <txid> <txkey> <address> + + invalid arguments. Please use start_mining [<number_of_threads>] [do_bg_mining] [ignore_battery] - - Check the amount going to <address> in <txid>. + + Mining started in daemon - - get_tx_proof <txid> <address> [<message>] + + mining has NOT been started: - - Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key. + + Mining stopped in daemon - - check_tx_proof <txid> <address> <signature_file> [<message>] + + mining has NOT been stopped: - - Check the proof for funds going to <address> in <txid> with the challenge string <message> if any. + + missing daemon URL argument - - get_spend_proof <txid> [<message>] + + Unexpected array length - Exited simple_wallet::set_daemon() - - Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>. + + Expected trusted or untrusted, got - - check_spend_proof <txid> <signature_file> [<message>] + + trusted - - Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>. + + untrusted - - get_reserve_proof (all|<amount>) [<message>] + + This does not seem to be a valid daemon URL. - - Generate a signature proving that you own at least this much, optionally with a challenge string <message>. -If 'all' is specified, you prove the entire sum of all of your existing accounts' balances. -Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account. + + Blockchain saved - - check_reserve_proof <address> <signature_file> [<message>] + + blockchain can't be saved: - - Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>. + + + Height - - show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + + + txid - - Show the incoming/outgoing transfers within an optional height range. + + + idx - - unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] + + NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead - - Show the unspent outputs of a specified address within an optional amount range. + + WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead - - Rescan the blockchain from scratch. + + spent - - set_tx_note <txid> [free text note] + + Enter password - - Set an arbitrary string note for a <txid>. + + Starting refresh... - - get_tx_note <txid> + + Refresh done, blocks received: - - Get a string note for a txid. + + + daemon is busy. Please try again later. - - set_description [free text note] + + + no connection to daemon. Please make sure daemon is running. - - Set an arbitrary description for the wallet. + + + RPC error: - - Get the description of the wallet. + + refresh error: - - Show the wallet's status. + + internal error: - - Show the wallet's information. + + refresh failed: - - sign <file> + + Blocks received: - - Sign the contents of a file. + + (Some owned outputs have partial key images - import_multisig_info needed) - - verify <filename> <address> <signature> + + (Some owned outputs have missing key images - import_key_images needed) - - Verify a signature on the contents of a file. + + Currently selected account: [ - - export_key_images <file> + + ] - - Export a signed set of key images to a <file>. + + (No tag assigned) - - import_key_images <file> + + Tag: - - Import a signed key images list and verify their spent status. + + Balance: - - export_outputs <file> + + unlocked balance: - - Export a set of outputs owned by this wallet. + + Balance per address: - - import_outputs <file> + + Address - - Import a set of outputs owned by this wallet. + + + Balance - - show_transfer <txid> + + + Unlocked balance - - Show information about a transfer to/from this address. + + Outputs - - Change the wallet's password. + + + Label + + + + + %8u %6s %21s %21s %7u %21s + + + + + usage: balance [detail] + + + + + + usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + + + + + pubkey + + + + + key image + + + + + spent + + + + + + unlocked + + + + + ringct + + + + + global index + + + + + tx id + + + + + + addr index + + + + + T + + + + + F + + + + + locked + + + + + RingCT + + + + + - + + + + + No incoming transfers - - Generate a new random full size payment id. These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids. + + No incoming available transfers - - Print the information about the current fee and transaction backlog. + + No incoming unavailable transfers - - Export data needed to create a multisig wallet + + expected at least one payment ID - - make_multisig <threshold> <string1> [<string>...] + + payment - - Turn this wallet into a multisig wallet + + transaction - - finalize_multisig <string> [<string>...] + + height - - Turn this wallet into a multisig wallet, extra step for N-1/N wallets + + unlock time - - export_multisig_info <filename> + + No payments with id - - Export multisig info for other participants + + payment ID has invalid format, expected 16 or 64 character hex string: - - import_multisig_info <filename> [<filename>...] + + + + + failed to get blockchain height: - - Import multisig info from other participants + + failed to get spent status - - sign_multisig <filename> + + + + + + failed to connect to the daemon - - Sign a multisig transaction from a file + + +Transaction %llu/%llu: txid=%s - - submit_multisig <filename> + + failed to find construction data for tx input - - Submit a signed multisig transaction from a file + + +Input %llu/%llu: amount=%s - - export_raw_multisig_tx <filename> + + failed to get output: - - Export a signed multisig transaction to a file + + output key's originating block height shouldn't be higher than the blockchain height - - help [<command>] + + +Originating block heights: - - Show the help section or the documentation about a <command>. + + +| - - integer >= + + + | + - - block height + + +Warning: Some input keys being spent are from - - No wallet found with that name. Confirm creation of new wallet named: + + the same transaction - - can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name" and --generate-from-json="jsonfilename" + + blocks that are temporally very close - - can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic + + , which can break the anonymity of ring signature. Make sure this is intentional! - - --restore-multisig-wallet uses --generate-new-wallet, not --wallet-file + + + + Ring size must not be 0 - - specify a recovery parameter with the --electrum-seed="multisig seed here" + + + + ring size %u is too small, minimum is %u - - Multisig seed failed verification + + + + ring size %u is too large, maximum is %u - - Enter seed encryption passphrase, empty if none + + wrong number of arguments - - - This address is a subaddress which cannot be used here. + + payment id failed to encode - - Error: expected M/N, but got: + + failed to parse short payment ID from URI - - Error: expected N > 1 and N <= M, but got: + + + Invalid last argument: - - Error: M/N is currently unsupported. + + a single transaction cannot use more than one payment id - - Generating master wallet from %u of %u multisig wallet keys + + failed to parse payment id, though it was detected - - failed to parse secret view key + + usage: %s [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id>] - - failed to verify secret view key + + + Failed to parse number of outputs - - Secret spend key (%u of %u): + + + Amount of outputs should be greater than 0 - - Error: M/N is currently unsupported + + payment id has invalid format, expected 16 or 64 character hex string: - - Restore height + + + Unencrypted payment IDs are bad for privacy: ask the recipient to use subaddresses instead - - Still apply restore height? (Y/Yes/N/No): + + bad locked_blocks parameter: - - Warning: using an untrusted daemon at %s, privacy will be lessened + + + Locked blocks too high, max 1000000 (˜4 yrs) - - Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command. + + + a single transaction cannot use more than one payment id: - - Your wallet has been generated! -To start synchronizing with the daemon, use the "refresh" command. -Use the "help" command to see the list of available commands. -Use "help <command>" to see a command's documentation. -Always use the "exit" command when closing monero-wallet-cli to save -your current session's state. Otherwise, you might need to synchronize -your wallet again (your wallet keys are NOT at risk in any case). - + + + + + failed to set up payment id, though it was decoded correctly - - failed to generate new mutlisig wallet + + + + + amount is wrong: - - Generated new %u/%u multisig wallet: + + expected number from 0 to - - Opened %u/%u multisig wallet%s + + + + No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): - - Use "help <command>" to see a command's documentation. - + + + + + + + + + transaction cancelled. - - wallet is multisig and cannot save a watch-only version + + + No outputs found, or daemon is not ready - - missing daemon URL argument + + + Is this okay anyway? (Y/Yes/N/No): - - Unexpected array length - Exited simple_wallet::set_daemon() + + Failed to check for backlog: - - This does not seem to be a valid daemon URL. + + + +Transaction - - - txid + + + WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy. + - - - idx + + . - - (Some owned outputs have partial key images - import_multisig_info needed) + + + + + + + + + Failed to write transaction(s) to file - - Currently selected account: [ + + + + + + + + + Unsigned transaction(s) successfully written to file: - - ] + + No unmixable outputs found - - Tag: + + Sweeping - - (No tag assigned) + + + Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No): - - Balance per address: + + + + Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): - - Address + + Normal - - - Balance + + Type: - - - Unlocked balance + + Network type: - - Outputs + + Testnet - - - Label + + Stagenet - - %8u %6s %21s %21s %7u %21s + + Mainnet - - usage: balance [detail] + + usage: sign <filename> - - - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + + wallet is watch-only and cannot sign - - spent + + This wallet is multisig and cannot sign - - global index + + usage: verify <filename> <address> <signature> - - tx id + + Bad signature from - - - addr index + + Good signature from - - No incoming transfers + + usage: export_key_images <filename> - - No incoming available transfers + + wallet is watch-only and cannot export key images - - No incoming unavailable transfers + + Signed key images exported to - - expected at least one payment ID + + usage: import_key_images <filename> - - payment + + command only supported by HW wallet - - transaction + + Failed to reconnect device - - height + + Failed to reconnect device: - - unlock time + + usage: export_outputs <filename> - - No payments with id + + Outputs exported to - - - - failed to get blockchain height: + + usage: import_outputs <filename> - - - - - - failed to connect to the daemon + + usage: show_transfer <txid> - - -Transaction %llu/%llu: txid=%s + + Double spend seen on the network: this transaction may or may not end up being mined - - -Input %llu/%llu: amount=%s + + Transaction ID not found - - failed to get output: + + Transaction successfully saved to - - output key's originating block height shouldn't be higher than the blockchain height + + + , txid - - -Originating block heights: + + Failed to save transaction to - - -| + + true - - - | - + + failed to parse refresh type - - -Warning: Some input keys being spent are from + + Enter optional seed offset passphrase, empty to see raw seed - - , which can break the anonymity of ring signature. Make sure this is intentional! + + Enter seed offset passphrase, empty if none - - - Ring size must not be 0 + + You may want to remove the file "%s" and try again - - - ring size %u is too small, minimum is %u + + Discarding %s of unmixable outputs that cannot be spent, which can be undone by "rescan_spent". Is this okay? (Y/Yes/N/No): - - wrong number of arguments + + Donating %s %s to The Monero Project (donate.getmonero.org or %s). - - - - No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): + + This is a multisig wallet, it can only sign with sign_multisig - - - No outputs found, or daemon is not ready + + This is a watch only wallet - - Transaction successfully saved to + + usage: sign_transfer [export_raw] - - - , txid + + Failed to sign transaction - - Failed to save transaction to + + Failed to sign transaction: - - - Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No): + + Transaction raw hex data exported to - - - - Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): + + Failed to load transaction from file - - Donating + + usage: get_tx_key <txid> - - This is a watch only wallet + + + + + + + + + + + failed to parse txid - - usage: show_transfer <txid> + + Tx key: - - Double spend seen on the network: this transaction may or may not end up being mined + + no tx keys found for this txid - - Transaction ID not found + + usage: set_tx_key <txid> <tx_key> - - true + + + + failed to parse tx_key - - failed to parse refresh type + + Tx key successfully stored. - - - wallet is watch-only and has no seed + + Failed to store tx key: - - - wallet is non-deterministic and has no seed + + usage: get_tx_proof <txid> <address> [<message>] - - - wallet is watch-only and cannot transfer + + + + signature file saved to: - - could not change default priority + + + + failed to save signature file - - full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase) + + + + error: - - monero, millinero, micronero, nanonero, piconero + + usage: check_tx_key <txid> <txkey> <address> - - Wallet name not valid. Please try again or use Ctrl-C to quit. + + + failed to parse tx key - - Wallet and key files found, loading... + + + received - - Key file found but not wallet file. Regenerating... + + + in txid - - Key file not found. Failed to open wallet: + + + WARNING: this transaction is not yet included in the blockchain! - - Generating new wallet... + + + WARNING: failed to determine number of confirmations! - - Electrum-style word list failed verification + + + received nothing in txid - - - - - - - - - - - No data supplied, cancelled + + usage: check_tx_proof <txid> <address> <signature_file> [<message>] - - - - - - - - - - - - - failed to parse address + + + + failed to load signature file - - - failed to parse view key secret key + + + Good signature - - - failed to verify view key secret key + + + + Bad signature - - - - view key does not match standard address + + usage: get_spend_proof <txid> [<message>] - - - - - - account creation failed + + wallet is watch-only and cannot generate the proof - - - - failed to parse spend key secret key + + usage: check_spend_proof <txid> <signature_file> [<message>] - - - failed to verify spend key secret key + + usage: get_reserve_proof (all|<amount>) [<message>] - - - spend key does not match standard address + + The reserve proof can be generated only by a full wallet - - failed to open account + + usage: check_reserve_proof <address> <signature_file> [<message>] - - - - - - wallet is null + + Address must not be a subaddress - - - invalid language choice entered. Please try again. - + + usage: show_transfers [in|out|all|pending|failed|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] - - View key: + + bad min_height parameter: - - You may want to remove the file "%s" and try again + + bad max_height parameter: - - failed to deinitialize wallet + + block - - - - this command requires a trusted daemon. Enable with --trusted-daemon + + in - - blockchain can't be saved: + + + out - - - daemon is busy. Please try again later. + + [Double spend seen on the network: this transaction may or may not end up being mined] - - - no connection to daemon. Please make sure daemon is running. + + failed - - refresh error: + + pending - - Balance: + + usage: unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] - - pubkey + + <min_amount> should be smaller than <max_amount> - - key image + + There is no unspent output in the specified address - - - unlocked + + +Amount: - - ringct + + , number of keys: - - T + + - - F + + +Min block height: - - locked + + +Max block height: - - RingCT + + +Min amount found: - - - + + +Max amount found: - - payment ID has invalid format, expected 16 or 64 character hex string: + + +Total count: - - failed to get spent status + + +Bin size: - - the same transaction + + +Outputs per *: - - blocks that are temporally very close + + count + ^ + - - Locked blocks too high, max 1000000 (˜4 yrs) + + | - - - Good signature + + + - - - - Bad signature + + +--> block height + - - usage: integrated_address [payment ID] + + ^ - - Standard address: + + ^ + - - failed to parse payment ID or address + + - - usage: address_book [(add (<address> [pid <long or short payment id>])|<integrated address> [<description possibly with whitespaces>])|(delete <index>)] + + Warning: this will lose any information which can not be recovered from the blockchain. - - failed to parse payment ID + + This includes destination addresses, tx secret keys, tx notes, etc - - failed to parse index + + Rescan anyway ? (Y/Yes/N/No): - - Address book is empty. + + Good signature -- total: %s, spent: %s, unspent: %s - - Index: + + usage: blackball <amount>/<offset> | <filename> [add] - - - Address: + + First line is not an amount - - Payment ID: + + Invalid output: - - - Description: + + Invalid output key, and file doesn't exist - - usage: set_tx_note [txid] free text note + + usage: unblackball <amount>/<offset> - - usage: get_tx_note [txid] + + + Invalid output - - usage: sign <filename> + + usage: blackballed <amount>/<offset> - - wallet is watch-only and cannot sign + + WARNING: from v8, ring size will be fixed and this setting will be ignored. - - - - - failed to read file + + invalid argument: must be either 0/never, 1/action, or 2/encrypt/decrypt - - usage: check_tx_proof <txid> <address> <signature_file> [<message>] + + transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [<payment_id>] - - - - failed to load signature file + + Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included) - - usage: get_spend_proof <txid> [<message>] + + locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <addr> <amount>) <lockblocks> [<payment_id>] - - wallet is watch-only and cannot generate the proof + + Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included) - - usage: check_spend_proof <txid> <signature_file> [<message>] + + sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id>] - - usage: get_reserve_proof (all|<amount>) [<message>] + + Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. If the parameter "outputs=<N>" is specified and N > 0, wallet splits the transaction into N even outputs. - - The reserve proof can be generated only by a full wallet + + sweep_single [<priority>] [<ring_size>] [outputs=<N>] <key_image> <address> [<payment_id>] - - usage: check_reserve_proof <address> <signature_file> [<message>] + + Available options: + seed language + Set the wallet's seed language. + always-confirm-transfers <1|0> + Whether to confirm unsplit txes. + print-ring-members <1|0> + Whether to print detailed information about ring members during confirmation. + store-tx-info <1|0> + Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference. + default-ring-size <n> + Set the default ring size (default and minimum is 5). + auto-refresh <1|0> + Whether to automatically synchronize new blocks from the daemon. + refresh-type <full|optimize-coinbase|no-coinbase|default> + Set the wallet's refresh behaviour. + priority [0|1|2|3|4] + Set the fee to default/unimportant/normal/elevated/priority. + confirm-missing-payment-id <1|0> + ask-password <0|1|2 (or never|action|decrypt)> + unit <monero|millinero|micronero|nanonero|piconero> + Set the default monero (sub-)unit. + min-outputs-count [n] + Try to keep at least that many outputs of value at least min-outputs-value. + min-outputs-value [n] + Try to keep at least min-outputs-count outputs of at least that value. + merge-destinations <1|0> + Whether to merge multiple payments to the same destination address. + confirm-backlog <1|0> + Whether to warn if there is transaction backlog. + confirm-backlog-threshold [n] + Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks. + refresh-from-block-height [n] + Set the height before which to ignore blocks. + auto-low-priority <1|0> + Whether to automatically use the low priority fee level when it's safe to do so. + segregate-pre-fork-outputs <1|0> + Set this if you intend to spend outputs on both Monero AND a key reusing fork. + key-reuse-mitigation2 <1|0> + Set this if you are not sure whether you will spend on a key reusing Monero fork later. +subaddress-lookahead <major>:<minor> + Set the lookahead sizes for the subaddress hash table. + Set this if you are not sure whether you will spend on a key reusing Monero fork later. + segregation-height <n> + Set to the height of a key reusing fork you want to use, 0 to use default. - - Address must not be a subaddress + + blackball <amount>/<offset> | <filename> [add] - - Good signature -- total: %s, spent: %s, unspent: %s + + unblackball <amount>/<offset> - - usage: show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + + blackballed <amount>/<offset> - - [Double spend seen on the network: this transaction may or may not end up being mined] + + Password needed (%s) - use the refresh command - - usage: unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] + + usage: sweep_single [<priority>] [<ring_size>] [outputs=<N>] <key_image> <address> [<payment_id>] - - There is no unspent output in the specified address + + wallet - + (no daemon) - + (out of sync) - + (Untitled account) - - - - - - + + + + + + failed to parse index: - - + + specify an index between 0 and - + usage: account account new <label text with white spaces allowed> @@ -3004,695 +4016,629 @@ Warning: Some input keys being spent are from - + Grand total: Balance: - + , unlocked balance: - + Untagged accounts: - + Tag %s is unregistered. - + Accounts with tag: - + Tag's description: - + Account - + %c%8u %6s %21s %21s %21s - + ---------------------------------------------------------------------------------- - + %15s %21s %21s - + Primary address - + (used) - + (Untitled address) - + <index_min> is already out of bound - + <index_max> exceeds the bound - + usage: address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> ] - - - Integrated addresses can only be created for account 0 - - - - - Integrated address: %s, payment ID: %s - - - - - Subaddress: - - - - - usage: get_description - - - - - no description found - - - - - description found: - - - - - Filename: - - - - - Watch only + + usage: integrated_address [payment ID] - - %u/%u multisig%s + + + Integrated addresses can only be created for account 0 - - Normal + + Matching integrated address: - - Type: + + Integrated address: %s, payment ID: %s - - Testnet: + + Subaddress: - - Yes + + Standard address: - - No + + failed to parse payment ID or address - - This wallet is multisig and cannot sign + + usage: address_book [(add (<address> [pid <long or short payment id>])|<integrated address> [<description possibly with whitespaces>])|(delete <index>)] - - usage: verify <filename> <address> <signature> + + failed to parse payment ID - - Bad signature from + + failed to parse index - - Good signature from + + Address book is empty. - - usage: export_key_images <filename> + + Index: - - wallet is watch-only and cannot export key images + + + Address: - - - - failed to save file + + Payment ID: - - Signed key images exported to + + + Description: - - usage: import_key_images <filename> + + usage: set_tx_note [txid] free text note - - usage: export_outputs <filename> + + usage: get_tx_note [txid] - - Outputs exported to + + usage: get_description - - usage: import_outputs <filename> + + no description found - - - - - amount is wrong: + + description found: - - expected number from 0 to + + Filename: - - Sweeping + + Watch only - - Money successfully sent, transaction: + + %u/%u multisig%s - - Change goes to more than one address + + %s change to %s - - %s change to %s + + + This transaction has %u confirmations + + + genms - - no change + + Base filename (-1, -2, etc suffixes will be appended as needed) - - - - Transaction successfully signed to file + + Give threshold and participants at once as M/N - - usage: get_tx_key <txid> + + How many participants will share parts of the multisig wallet - - - - - - - - - - failed to parse txid + + How many signers are required to sign a valid transaction - - Tx key: + + Create testnet multisig wallets - - no tx keys found for this txid + + Create stagenet multisig wallets - - usage: get_tx_proof <txid> <address> [<message>] + + Create an address file for new wallets - - - - signature file saved to: + + Generating %u %u/%u multisig wallets - - - - failed to save signature file + + Failed to verify multisig info - - usage: check_tx_key <txid> <txkey> <address> + + Error verifying multisig extra info - - - failed to parse tx key + + Error finalizing multisig - - - - error: + + Generated multisig wallets for address - - - received + + Error creating multisig wallets: - - - in txid + + This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other - - - received nothing in txid + + Error: Can't specify more than one of --testnet and --stagenet - - - WARNING: this transaction is not yet included in the blockchain! + + Error: expected N/M, but got: - - - This transaction has %u confirmations + + + Error: either --scheme or both of --threshold and --participants may be given - - - WARNING: failed to determine number of confirmations! + + Error: expected N > 1 and N <= M, but got N==%u and M==%d - - bad min_height parameter: + + Error: --filename-base is required - - bad max_height parameter: + + Error: unsupported scheme: only N/N and N-1/N are supported + + + sw - - in + + Generate new wallet and save it to <arg> - - - out + + Generate new wallet from device and save it to <arg> - - failed + + Generate incoming-only wallet from view key - - pending + + Generate deterministic wallet from spend key - - <min_amount> should be smaller than <max_amount> + + Generate wallet from private keys - - -Amount: + + Generate a master wallet from multisig wallet keys - - , number of keys: + + Language for mnemonic - - + + Specify Electrum seed for wallet recovery/creation - - -Min block height: + + Recover wallet using Electrum-style mnemonic seed - - -Max block height: + + Recover multisig wallet using Electrum-style mnemonic seed - - -Min amount found: + + Generate non-deterministic view and spend keys - - -Max amount found: + + failed to read wallet password - - -Total count: + + Enter a new password for the wallet - - -Bin size: + + Wallet password - - -Outputs per *: + + invalid argument: must be either 0/1, true/false, y/n, yes/no - - count - ^ - + + DNSSEC validation passed - - | + + WARNING: DNSSEC validation was unsuccessful, this address may not be correct! - - + + + For URL: - - +--> block height - + + Monero Address = - - ^ + + Is this OK? (Y/n) - - ^ - + + you have cancelled the transfer request - - + + failed to parse index: - - wallet + + invalid format for subaddress lookahead; must be <major>:<minor> - - - Random payment ID: + + no connection to daemon. Please make sure daemon is running. - - Matching integrated address: + + RPC error: - - - genms - - Base filename (-1, -2, etc suffixes will be appended as needed) + + failed to get random outputs to mix: - - Give threshold and participants at once as M/N + + + Not enough money in unlocked balance - - How many participants will share parts of the multisig wallet + + Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees - - How many signers are required to sign a valid transaction + + not enough outputs for specified ring size - - Create testnet multisig wallets + + output amount - - Generating %u %u/%u multisig wallets + + found outputs to use - - Error verifying multisig extra info + + Please use sweep_unmixable. - - Error finalizing multisig + + transaction was not constructed - - Generated multisig wallets for address + + transaction %s was rejected by daemon with status: - - Error creating multisig wallets: + + Reason: - - This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other + + one of destinations is zero - - Error: expected N/M, but got: + + failed to find a suitable way to split transactions - - - Error: either --scheme or both of --threshold and --participants may be given + + unknown transfer error: - - Error: expected N > 1 and N <= M, but got N==%u and M==%d + + Multisig error: - - Error: --filename-base is required + + internal error: - - Error: unsupported scheme: only N/N and N-1/N are supported + + unexpected error: - - - sw - - Generate new wallet and save it to <arg> + + There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a transaction immediately. Alternatively, connect to another node so the original node cannot correlate information. - - Generate incoming-only wallet from view key + + File %s likely stores wallet private keys! Use a different file name. - - Generate deterministic wallet from spend key + + File %s already exists. Are you sure to overwrite it? (Y/Yes/N/No): - - Generate wallet from private keys + + seconds - - Generate a master wallet from multisig wallet keys + + minutes - - Language for mnemonic + + hours - - Specify Electrum seed for wallet recovery/creation + + days - - Recover wallet using Electrum-style mnemonic seed + + months - - Recover multisig wallet using Electrum-style mnemonic seed + + a long time - - Generate non-deterministic view and spend keys + + This is the command line monero wallet. It needs to connect to a monero +daemon to work correctly. +WARNING: Do not reuse your Monero keys on another fork, UNLESS this fork has key reuse mitigations built in. Doing so will harm your privacy. - - Enable commands which rely on a trusted daemon + + Unknown command: - + Allow communicating with a daemon that uses a different RPC version - + Restore from specific blockchain height - + The newly created transaction will not be relayed to the monero network - - daemon is busy. Please try again later. + + Create an address file for new wallets - - possibly lost connection to daemon + + Display English language names - - Error: + + + daemon is busy. Please try again later. - - This is the command line monero wallet. It needs to connect to a monero -daemon to work correctly. + + possibly lost connection to daemon + + + + + Error: - + Failed to initialize wallet @@ -3700,299 +4646,354 @@ daemon to work correctly. tools::wallet2 - + Use daemon instance at <host>:<port> - + Use daemon instance at host <arg> instead of localhost - + Wallet password file - + Use daemon instance at port <arg> instead of 18081 - + For testnet. Daemon must also be launched with --testnet flag - - Restricts to view-only commands - - - - + can't specify daemon host or port more than once - + can't specify more than one of --password and --password-file - + the password file specified could not be read - + Failed to load file - + Wallet password (escape/quote as needed) - + + Enable commands which rely on a trusted daemon + + + + + Disable commands which rely on a trusted daemon + + + + Specify username[:password] for daemon RPC client - + + For stagenet. Daemon must also be launched with --stagenet flag + + + + + Set shared ring database path + + + + + Number of rounds for the key derivation function + + + + + HW device to use + + + + + --trusted-daemon and --untrusted-daemon are both seen, assuming untrusted + + + + + Daemon is local, assuming trusted + + + + no password specified; use --prompt-for-password to prompt for a password - + + Enter a new password for the wallet + + + + + Wallet password + + + + Failed to parse JSON - + Version %u too new, we can only grok up to %u - + failed to parse view key secret key - - - + + + failed to verify view key secret key - + failed to parse spend key secret key - - - + + + failed to verify spend key secret key - + Electrum-style word list failed verification - - At least one of Electrum-style word list and private view key and private spend key must be specified + + At least one of either an Electrum-style word list, private view key, or private spend key must be specified - + Both Electrum-style word list and private key(s) specified - + invalid address - + view key does not match standard address - + spend key does not match standard address - + Cannot generate deprecated wallets from JSON - + failed to parse address: - + Address must be specified in order to create watch-only wallet - + failed to generate new wallet: - - - - - - - - + + Password is needed to compute key image for incoming monero + + + + + Invalid password: password is needed to compute key image for incoming monero + + + + + + Primary account - + No funds received in this tx. - + failed to read file - - - tools::wallet_rpc_server - - Daemon is local, assuming trusted + + Set subaddress lookahead sizes to <major>:<minor> + + + tools::wallet_rpc_server - + Failed to create directory - + Failed to create directory %s: %s - + Cannot specify -- - + and -- - + Failed to create file - + . Check permissions or remove file - + Error writing to file - + RPC username/password is stored in file - + Tag %s is unregistered. - + Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee) - + This is the RPC monero wallet. It needs to connect to a monero daemon to work correctly. - + + Can't specify more than one of --testnet and --stagenet + + + + Can't specify more than one of --wallet-file and --generate-from-json - + Must specify --wallet-file or --generate-from-json or --wallet-dir - + Loading wallet... - - + + Saving wallet... - - + + Successfully saved - + Successfully loaded - + Wallet initialization failed: - + Failed to initialize wallet RPC server - + Starting wallet RPC server - + Failed to run wallet: - + Stopped wallet RPC server - + Failed to save wallet: @@ -4000,9 +5001,9 @@ daemon to work correctly. wallet_args - - - + + + Wallet options @@ -4017,48 +5018,48 @@ daemon to work correctly. - + Max number of threads to use for a parallel job - + Specify log file - + Config file - + General options - + This is the command line monero wallet. It needs to connect to a monero daemon to work correctly. - + Can't find config file - + Logging to: - + Logging to %s - + Usage: From 3d722db487ab106443d1d30a0b4209c86b9b7f7a Mon Sep 17 00:00:00 2001 From: Guillaume LE VAILLANT Date: Sat, 6 Oct 2018 16:08:16 +0200 Subject: [PATCH 0057/1007] wallet-cli: Update French translation --- translations/monero_fr.ts | 3770 +++++++++++++++++++++++-------------- 1 file changed, 2390 insertions(+), 1380 deletions(-) diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts index 957d2a382..bac742c56 100644 --- a/translations/monero_fr.ts +++ b/translations/monero_fr.ts @@ -27,45 +27,55 @@ Monero::PendingTransactionImpl - + Attempting to save transaction to file, but specified file(s) exist. Exiting to not risk overwriting. File: - Tentative d'enregistrement d'une transaction dans un fichier, mais le fichier spécifié existe déjà. Sortie pour ne pas risquer de l'écraser. Fichier : + Tentative d'enregistrement d'une transaction dans un fichier, mais le fichier spécifié existe déjà. Sortie pour ne pas risquer de l'écraser. Fichier : - + Failed to write transaction(s) to file Échec de l'écriture de(s) transaction(s) dans le fichier - + daemon is busy. Please try again later. le démon est occupé. Veuillez réessayer plus tard. - + no connection to daemon. Please make sure daemon is running. pas de connexion au démon. Veuillez vous assurer que le démon fonctionne. - + transaction %s was rejected by daemon with status: - la transaction %s a été rejetée par le démon avec le statut : + la transaction %s a été rejetée par le démon avec le statut : - + . Reason: - . Raison : + . Raison : - + Unknown exception: - Exception inconnue : + Exception inconnue : - + Unhandled exception Exception non gérée + + + Couldn't multisig sign data: + Signature multisig des données impossible : + + + + Couldn't sign multisig transaction: + Signature multisig de la transaction impossible : + Monero::UnsignedTransactionImpl @@ -124,281 +134,406 @@ Monero::WalletImpl - + payment id has invalid format, expected 16 or 64 character hex string: - format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : + format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : - + Failed to add short payment id: - Échec de l'ajout de l'ID de paiement court : + Échec de l'ajout de l'ID de paiement court : - - + + daemon is busy. Please try again later. le démon est occupé. Veuillez réessayer plus tard. - - + + no connection to daemon. Please make sure daemon is running. pas de connexion au démon. Veuillez vous assurer que le démon fonctionne. - - + + RPC error: - Erreur RPC : + Erreur RPC : - - + + not enough outputs for specified ring size pas assez de sorties pour la taille de cercle spécifiée - - + + found outputs to use sorties à utiliser trouvées - + Please sweep unmixable outputs. Veuillez balayer les sorties non mélangeables. - - failed to get random outputs to mix - échec de la récupération de sorties aléatoires à mélanger - - - - + + not enough money to transfer, available only %s, sent amount %s pas assez de fonds pour le transfert, montant disponible %s, montant envoyé %s - + failed to parse address échec de l'analyse de l'adresse - + failed to parse secret spend key échec de l'analyse de la clé secrète de dépense - - No view key supplied, cancelled - Pas de clé d'audit fournie, annulation - - - + failed to parse secret view key échec de l'analyse de la clé secrète d'audit - + failed to verify secret spend key échec de la vérification de la clé secrète de dépense - + spend key does not match address la clé de dépense ne correspond pas à l'adresse - + failed to verify secret view key échec de la vérification de la clé secrète d'audit - + view key does not match address la clé d'audit ne correspond pas à l'adresse - + + failed to generate new wallet: - échec de la génération du nouveau portefeuille : + échec de la génération du nouveau portefeuille : - + Failed to send import wallet request Échec de l'envoi de la requête d'importation de portefeuille - + Failed to load unsigned transactions Échec du chargement des transaction non signées - + Failed to load transaction from file Échec du chargement de la transaction du fichier - + Wallet is view only Portefeuille d'audit uniquement - + failed to save file échec de l'enregistrement du fichier - + Key images can only be imported with a trusted daemon Les images de clé ne peuvent être importées qu'avec un démon de confiance - + Failed to import key images: - Échec de l'importation des images de clé : + Échec de l'importation des images de clé : - + Failed to get subaddress label: - Échec de la récupération de l'étiquette de sous-adresse : + Échec de la récupération de l'étiquette de sous-adresse : - + Failed to set subaddress label: - Échec de l'affectation de l'étiquette de sous-adresse : + Échec de l'affectation de l'étiquette de sous-adresse : + + + + Neither view key nor spend key supplied, cancelled + Ni clé d'audit ni clé de dépense fournie, annulation + + + + Electrum seed is empty + La phrase Electrum est vide + + + + Electrum-style word list failed verification + Échec de la vérification de la liste de mots de style Electrum + + + + Failed to get multisig info: + Échec de la récupération des infos multisig : + + + + Failed to make multisig: + Échec de la création multisig : + + + + Failed to finalize multisig wallet creation + Échec de la finalisation de la création du portefeuille multisig + + + + Failed to finalize multisig wallet creation: + Échec de la finalisation de la création du portefeuille multisig : + + + + Failed to export multisig images: + Échec de l'exportation des images multisig : + + + + Failed to parse imported multisig images + Échec de l'analyse des images multisig importées + + + + Failed to import multisig images: + Échec de l'importation des images multisig : - - failed to get random outputs to mix: %s - échec de la récupération de sorties aléatoires à mélanger : %s + + Failed to check for partial multisig key images: + Échec de la vérification des images de clé multisig partielles : + + + + Failed to restore multisig transaction: + Échec de la restauration de la transaction multisig : + + + + Invalid destination address + Adresse de destination invalide + + + + failed to get outputs to mix: %s + échec de la récupération de sorties à mélanger : %s - - + + not enough money to transfer, overall balance only %s, sent amount %s pas assez de fonds pour le transfer, solde global disponible %s, montant envoyé %s - - + + not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee) pas assez de fonds pour le transfert, montant disponible %s, montant envoyé %s = %s + %s (frais) - - + + output amount montant de la sortie - - + + transaction was not constructed la transaction n'a pas été construite - - + + transaction %s was rejected by daemon with status: - la transaction %s a été rejetée par le démon avec le statut : + la transaction %s a été rejetée par le démon avec le statut : - - + + one of destinations is zero une des destinations est zéro - - + + failed to find a suitable way to split transactions échec de la recherche d'une façon adéquate de scinder les transactions - - + + unknown transfer error: - erreur de transfert inconnue : + erreur de transfert inconnue : - - + + internal error: - erreur interne : + erreur interne : - - + + unexpected error: - erreur inattendue : + erreur inattendue : - - + + unknown error erreur inconnue - - - - - - + + failed to get outputs to mix + échec de la récupération de sorties à mélanger + + + + + + + + + Failed to parse txid Échec de l'analyse de l'ID de transaction - + no tx keys found for this txid aucune clé de transaction trouvée pour cet ID de transaction - - + + Failed to parse tx key Échec de l'analyse de la clé de transaction - - - - + + + + Failed to parse address Échec de l'analyse de l'adresse - + Address must not be a subaddress L'adresse ne doit pas être une sous-adresse - + + The wallet must be in multisig ready state + Le portefeuille doit être multisig et prêt + + + + Given string is not a key + La chaîne entrée n'est pas une clé + + + Rescan spent can only be used with a trusted daemon Réexaminer les dépenses ne peut se faire qu'avec un démon de confiance + + + Invalid output: + Sortie invalide : + + + + Failed to set blackballed outputs + Échec de l'affectation des sorties blackboulées + + + + + Failed to parse output amount + Échec de l'analyse du montant de la sortie + + + + + Failed to parse output offset + Échec de l'analyse de l'offset de la sortie + + + + Failed to blackball output + Échec du blackboulage de la sortie + + + + Failed to unblackball output + Échec du déblackboulage de la sortie + + + + + Failed to parse key image + Échec de l'analyse de l'image de clé + + + + Failed to get ring + Échec de la récupération du cercle + + + + Failed to get rings + Échec de la récupération des cercles + + + + Failed to set ring + Échec de l'affectation du cercle + Wallet - + Failed to parse address Échec de l'analyse de l'adresse - + Failed to parse key Échec de l'analyse de la clé - + failed to verify key Échec de la vérification de la clé - + key does not match address la clé ne correspond pas à l'adresse @@ -449,18 +584,18 @@ autorise les connexions entrantes non cryptées venant de l'extérieur. Considérez plutôt un tunnel SSH ou un proxy SSL. Outrepasser avec -- - + Username specified with -- Le nom d'utilisateur spécifié avec -- - - + + cannot be empty ne peut pas être vide - + requires RPC server password -- nécessite le mot de passe du serveur RPC -- @@ -468,1127 +603,1009 @@ cryptonote::simple_wallet - + Commands: - Commandes : + Commandes : - + failed to read wallet password échec de la lecture du mot de passe du portefeuille - + invalid password mot de passe invalide - + set seed: needs an argument. available options: language - set seed : requiert un argument. options disponibles : language + set seed : requiert un argument. options disponibles : language - + set: unrecognized argument(s) - set : argument(s) non reconnu(s) + set : argument(s) non reconnu(s) - + wallet file path not valid: - chemin du fichier portefeuille non valide : + chemin du fichier portefeuille non valide : - + Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting. Tentative de génération ou de restauration d'un portefeuille, mais le fichier spécifié existe déjà. Sortie pour ne pas risquer de l'écraser. - + usage: payment_id - usage : payment_id + usage : payment_id - + needs an argument requiert un argument - - - - - - - - - - + + + + + + + + + + + + 0 or 1 0 ou 1 - - 0, 1, 2, 3, or 4 - 0, 1, 2, 3 ou 4 - - - - + + + unsigned integer entier non signé - + NOTE: the following 25 words can be used to recover access to your wallet. Write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. - VEUILLEZ NOTER : les 25 mots suivants peuvent être utilisés pour restaurer votre portefeuille. Veuillez les écrire sur papier et les garder dans un endroit sûr. Ne les gardez pas dans un courriel ou dans un service de stockage de fichiers hors de votre contrôle. + VEUILLEZ NOTER : les 25 mots suivants peuvent être utilisés pour restaurer votre portefeuille. Veuillez les écrire sur papier et les garder dans un endroit sûr. Ne les gardez pas dans un courriel ou dans un service de stockage de fichiers hors de votre contrôle. - + --restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file --restore-deterministic-wallet utilise --generate-new-wallet, pas --wallet-file - + specify a recovery parameter with the --electrum-seed="words list here" spécifiez un paramètre de récupération avec --electrum-seed="liste de mots ici" - + specify a wallet path with --generate-new-wallet (not --wallet-file) spécifiez un chemin de portefeuille avec --generate-new-wallet (pas --wallet-file) - + wallet failed to connect to daemon: - échec de la connexion du portefeuille au démon : + échec de la connexion du portefeuille au démon : - + Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version. - Le démon utilise une version majeure de RPC (%u) différente de celle du portefeuille (%u) : %s. Mettez l'un des deux à jour, ou utilisez --allow-mismatched-daemon-version. + Le démon utilise une version majeure de RPC (%u) différente de celle du portefeuille (%u) : %s. Mettez l'un des deux à jour, ou utilisez --allow-mismatched-daemon-version. - + List of available languages for your wallet's seed: - Liste des langues disponibles pour la phrase mnémonique de votre portefeuille : + Liste des langues disponibles pour la phrase mnémonique de votre portefeuille : - + Enter the number corresponding to the language of your choice: - Entrez le nombre correspondant à la langue de votre choix : + Entrez le nombre correspondant à la langue de votre choix : - + You had been using a deprecated version of the wallet. Please use the new seed that we provide. Vous avez utilisé une version obsolète du portefeuille. Veuillez dorénavant utiliser la nouvelle phrase mnémonique que nous fournissons. - - + + Generated new wallet: - Nouveau portefeuille généré : + Nouveau portefeuille généré : - - - + + + + failed to generate new wallet: - échec de la génération du nouveau portefeuille : + échec de la génération du nouveau portefeuille : - + Opened watch-only wallet Ouverture du portefeuille d'audit - + Opened wallet Ouverture du portefeuille - + You had been using a deprecated version of the wallet. Please proceed to upgrade your wallet. Vous avez utilisé une version obsolète du portefeuille. Veuillez procéder à la mise à jour de votre portefeuille. - + You had been using a deprecated version of the wallet. Your wallet file format is being upgraded now. Vous avez utilisé une version obsolète du portefeuille. Le format de votre fichier portefeuille est en cours de mise à jour. - + failed to load wallet: - échec du chargement du portefeuille : + échec du chargement du portefeuille : - + Use the "help" command to see the list of available commands. Utilisez la commande "help" pour voir la liste des commandes disponibles. - + Wallet data saved Données du portefeuille sauvegardées - + Mining started in daemon La mine a démarré dans le démon - + mining has NOT been started: - la mine n'a PAS démarré : + la mine n'a PAS démarré : - + Mining stopped in daemon La mine a été stoppée dans le démon - + mining has NOT been stopped: - la mine n'a PAS été stoppée : + la mine n'a PAS été stoppée : - + Blockchain saved Chaîne de blocs sauvegardée - - - + + Height Hauteur - - transaction - transaction - - - + spent dépensé - - unsupported transaction format - format de transaction non supporté - - - + Starting refresh... Démarrage du rafraîchissement... - + Refresh done, blocks received: - Rafraîchissement effectué, blocs reçus : + Rafraîchissement effectué, blocs reçus : - - + payment id has invalid format, expected 16 or 64 character hex string: - format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : + format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : - + bad locked_blocks parameter: - mauvais paramètre locked_blocks : + mauvais paramètre locked_blocks : - - - + + a single transaction cannot use more than one payment id: - une unique transaction ne peut pas utiliser plus d'un ID de paiement : + une unique transaction ne peut pas utiliser plus d'un ID de paiement : - - - - + + + + failed to set up payment id, though it was decoded correctly échec de la définition de l'ID de paiement, bien qu'il ait été décodé correctement - - - - - - - - + + + + + + + + transaction cancelled. transaction annulée. - - + + Is this okay anyway? (Y/Yes/N/No): - Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : + Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : - + There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): - Il y a actuellement un arriéré de %u blocs à ce niveau de frais. Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : + Il y a actuellement un arriéré de %u blocs à ce niveau de frais. Est-ce correct quand même ? (Y/Yes/Oui/N/No/Non) : - + Failed to check for backlog: - Échec de la vérification du backlog : + Échec de la vérification du backlog : - - + + Transaction Transaction - - + + Spending from address index %d Dépense depuis l'adresse d'index %d - - + + WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy. - ATTENTION : Des sorties de multiples adresses sont utilisées ensemble, ce qui pourrait potentiellement compromettre votre confidentialité. + ATTENTION : Des sorties de multiples adresses sont utilisées ensemble, ce qui pourrait potentiellement compromettre votre confidentialité. - + Sending %s. Envoi de %s. - + Your transaction needs to be split into %llu transactions. This will result in a transaction fee being applied to each transaction, for a total fee of %s Votre transaction doit être scindée en %llu transactions. Il en résulte que des frais de transaction doivent être appliqués à chaque transaction, pour un total de %s - + The transaction fee is %s Les frais de transaction sont de %s - + , of which %s is dust from change , dont %s est de la poussière de monnaie rendue - + . . - + A total of %s from dust change will be sent to dust address Un total de %s de poussière de monnaie rendue sera envoyé à une adresse de poussière - + . This transaction will unlock on block %llu, in approximately %s days (assuming 2 minutes per block) . Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s jours (en supposant 2 minutes par bloc) - - - - - - - - + + + + + + + + Failed to write transaction(s) to file Échec de l'écriture de(s) transaction(s) dans le fichier - - - - - - - - + + + + + + + + Unsigned transaction(s) successfully written to file: - Transaction(s) non signée(s) écrite(s) dans le fichier avec succès : + Transaction(s) non signée(s) écrite(s) dans le fichier avec succès : - + No unmixable outputs found Aucune sortie non mélangeable trouvée - + No address given Aucune adresse fournie - + failed to parse Payment ID échec de l'analyse de l'ID de paiement - - usage: sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] - usage : sweep_single [<priorité>] [<taille_cercle>] <image_clé> <adresse> [<ID_paiement>] - - - + failed to parse key image échec de l'analyse de l'image de clé - + No outputs found Pas de sorties trouvées - + Multiple transactions are created, which is not supposed to happen De multiples transactions sont crées, ce qui n'est pas supposé arriver - + The transaction uses multiple or no inputs, which is not supposed to happen La transaction utilise aucune ou de multiples entrées, ce qui n'est pas supposé arriver - + missing threshold amount montant seuil manquant - + invalid amount threshold montant seuil invalide - - donations are not enabled on the testnet - les dons ne sont pas activés sur le réseau testnet - - - + usage: donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] - usage : donate [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <montant> [<ID_paiement>] + usage : donate [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <montant> [<ID_paiement>] - + Claimed change does not go to a paid address La monnaie réclamée ne va pas à une adresse payée - + Claimed change is larger than payment to the change address La monnaie réclamée est supérieure au paiement à l'adresse de monnaie - + sending %s to %s envoi de %s à %s - + dummy output(s) sortie(s) factice(s) - + with no destinations sans destination - + Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): - %lu transactions chargées, pour %s, frais %s, %s, %s, taille de cercle minimum %lu, %s. %sEst-ce correct ? (Y/Yes/Oui/N/No/Non) : + %lu transactions chargées, pour %s, frais %s, %s, %s, taille de cercle minimum %lu, %s. %sEst-ce correct ? (Y/Yes/Oui/N/No/Non) : - + This is a multisig wallet, it can only sign with sign_multisig Ceci est un portefeuille multisig, il ne peut signer qu'avec sign_multisig - - usage: sign_transfer [export] - usage : sign_transfer [export] - - - + Failed to sign transaction Échec de signature de transaction - + Failed to sign transaction: - Échec de signature de transaction : + Échec de signature de transaction : - + Transaction raw hex data exported to Données brutes hex de la transaction exportées vers - + Failed to load transaction from file Échec du chargement de la transaction du fichier - - + + RPC error: - Erreur RPC : + Erreur RPC : - + wallet is watch-only and has no spend key c'est un portefeuille d'audit et il n'a pas de clé de dépense - - - + + + Your original password was incorrect. Votre mot de passe original est incorrect. - + Error with wallet rewrite: - Erreur avec la réécriture du portefeuille : - - - - priority must be 0, 1, 2, 3, or 4 - la priorité doit être 0, 1, 2, 3 ou 4 - - - - - priority must be 0, 1, 2, 3, or 4 - la priorité doit être 0, 1, 2, 3 ou 4 + Erreur avec la réécriture du portefeuille : - + invalid unit unité invalide - - + + invalid count: must be an unsigned integer - nombre invalide : un entier non signé est attendu + nombre invalide : un entier non signé est attendu - + invalid value valeur invalide - + usage: set_log <log_level_number_0-4> | <categories> - usage : set_log <niveau_de_journalisation_0-4> | <catégories> + usage : set_log <niveau_de_journalisation_0-4> | <catégories> - + (Y/Yes/N/No): - (Y/Yes/Oui/N/No/Non) : + (Y/Yes/Oui/N/No/Non) : - - + + bad m_restore_height parameter: - mauvais paramètre m_restore_height : + mauvais paramètre m_restore_height : - + date format must be YYYY-MM-DD le format de date doit être AAAA-MM-JJ - + Restore height is: - La hauteur de restauration est : + La hauteur de restauration est : - - + + + Is this okay? (Y/Yes/N/No): - Est-ce correct ? (Y/Yes/Oui/N/No/Non) : + Est-ce correct ? (Y/Yes/Oui/N/No/Non) : - + Daemon is local, assuming trusted Le démon est local, supposons qu'il est de confiance - + Password for new watch-only wallet Mot de passe pour le nouveau portefeuille d'audit - - invalid arguments. Please use start_mining [<number_of_threads>] [do_bg_mining] [ignore_battery], <number_of_threads> should be from 1 to - arguments invalides. Veuillez utiliser start_mining [<nombre_de_threads>] [mine_en_arrière_plan] [ignorer_batterie], <nombre_de_threads> devrait être entre 1 et - - - + internal error: - erreur interne : + erreur interne : - - - + + + unexpected error: - erreur inattendue : - - - - - - - - - - - + erreur inattendue : + + + + + + + + + + + unknown error erreur inconnue - + refresh failed: - échec du rafraîchissement : + échec du rafraîchissement : - + Blocks received: - Blocs reçus : + Blocs reçus : - + unlocked balance: - solde débloqué : + solde débloqué : - - - + + + amount montant - + false faux - + Unknown command: - Commande inconnue : + Commande inconnue : - + Command usage: - Usage de la commande : + Usage de la commande : - + Command description: - Description de la commande : + Description de la commande : - + wallet is multisig but not yet finalized le portefeuille est multisig mais pas encore finalisé - - Enter optional seed encryption passphrase, empty to see raw seed - Entrer une phrase de passe facultative pour le chiffrement de la phrase mnémonique, effacer pour voir la phrase mnémonique brute - - - + Failed to retrieve seed Échec de la récupération de la phrase mnémonique - + wallet is multisig and has no seed le portefeuille est multisig et n'a pas de phrase mnémonique - + Cannot connect to daemon Impossible de se connecter au démon - - Current fee is %s monero per kB - Les frais sont actuellement de %s monero par kO - - - + Error: failed to estimate backlog array size: - Erreur : échec de l'estimation de la taille du tableau d'arriéré : + Erreur : échec de l'estimation de la taille du tableau d'arriéré : - + Error: bad estimated backlog array size - Erreur : mauvaise estimation de la taille du tableau d'arriéré + Erreur : mauvaise estimation de la taille du tableau d'arriéré - + (current) (actuel) - + %u block (%u minutes) backlog at priority %u%s arriéré de %u bloc(s) (%u minutes) à la priorité %u%s - + %u to %u block (%u to %u minutes) backlog at priority %u arriéré de %u à %u bloc(s) (%u à %u minutes) à la priorité %u - + No backlog at priority Pas d'arriéré à la priorité - - + + This wallet is already multisig Le portefeuille est déjà multisig - - + + wallet is watch-only and cannot be made multisig c'est un portefeuille d'audit et il ne peut pas être tranformé en multisig - - + + This wallet has been used before, please use a new wallet to create a multisig wallet Ce portefeuille a été utilisé auparavant, veuillez utiliser un nouveau portefeuille pour créer un portefeuille multisig - - Your password is incorrect. - Votre mot de passe est incorrect. - - - + Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info Envoyez ces infos multisig à tous les autres participants, ensuite utilisez make_multisig <seuil> <info1> [<info2>...] avec les infos multisig des autres - + This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants Ceci inclut la clé PRIVÉE d'audit, donc ne doit être divulgué qu'aux participants de ce portefeuille multisig - + usage: make_multisig <threshold> <multisiginfo1> [<multisiginfo2>...] - usage : make_multisig <seuil> <multisiginfo1> [<multisiginfo2>...] + usage : make_multisig <seuil> <multisiginfo1> [<multisiginfo2>...] - + Invalid threshold Seuil invalide - + Another step is needed Une autre étape est nécessaire - + Send this multisig info to all other participants, then use finalize_multisig <info1> [<info2>...] with others' multisig info Envoyez ces infos multisig à tous les autres participants, ensuite utilisez finalize_multisig <info1> [<info2>...] avec les infos multisig des autres - + Error creating multisig: - Erreur de création multisig : + Erreur de création multisig : - + Error creating multisig: new wallet is not multisig - Erreur de création multisig : le nouveau portefeuille n'est pas multisig + Erreur de création multisig : le nouveau portefeuille n'est pas multisig - + multisig address: - adresse multisig : + adresse multisig : - - - + + + This wallet is not multisig Ce portefeuille n'est pas multisig - + This wallet is already finalized Ce portefeuille est déjà finalisé - + usage: finalize_multisig <multisiginfo1> [<multisiginfo2>...] - usage : finalize_multisig <multisiginfo1> [<multisiginfo2>...] + usage : finalize_multisig <multisiginfo1> [<multisiginfo2>...] - + Failed to finalize multisig Échec de finalisation multisig - + Failed to finalize multisig: - Échec de finalisation multisig : + Échec de finalisation multisig : - - - - - + + + + + This multisig wallet is not yet finalized Ce portefeuille multisig n'est pas encore finalisé - + usage: export_multisig_info <filename> - usage : export_multisig_info <nom_fichier> + usage : export_multisig_info <nom_fichier> - + Error exporting multisig info: - Erreur d'importation des infos multisig : + Erreur d'importation des infos multisig : - + Multisig info exported to Infos multisig exportées vers - + usage: import_multisig_info <filename1> [<filename2>...] - one for each other participant - usage : import_multisig_info <nom_fichier1> [<nom_fichier2>...] - un pour chaque autre participant + usage : import_multisig_info <nom_fichier1> [<nom_fichier2>...] - un pour chaque autre participant - + Multisig info imported Infos multisig importées - + Failed to import multisig info: - Échec de l'importation des infos multisig : + Échec de l'importation des infos multisig : - + Failed to update spent status after importing multisig info: - Échec de la mise à jour de l'état des dépenses après l'importation des infos multisig : + Échec de la mise à jour de l'état des dépenses après l'importation des infos multisig : - + Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run "rescan_spent" Pas un démon de confiance, l'état des dépenses peut être incorrect. Utilisez un démon de confiance et executez "rescan_spent" - - - + + + This is not a multisig wallet Ceci n'est pas un portefeuille multisig - + usage: sign_multisig <filename> - usage : sign_multisig <nom_fichier> + usage : sign_multisig <nom_fichier> - + Failed to sign multisig transaction Échec de la signature de la transaction multisig - + Multisig error: - Erreur multisig : + Erreur multisig : - + Failed to sign multisig transaction: - Échec de la signature de la transaction multisig : + Échec de la signature de la transaction multisig : - + It may be relayed to the network with submit_multisig Elle peut être transmise au réseau avec submit_multisig - + usage: submit_multisig <filename> - usage : submit_multisig <nom_fichier> + usage : submit_multisig <nom_fichier> - - + + Failed to load multisig transaction from file Échec du chargement de la transaction multisig du fichier - - + + Multisig transaction signed by only %u signers, needs %u more signatures Transaction multisig signée par %u signataire(s) seulement, nécessite %u signature(s) de plus - - + + Transaction successfully submitted, transaction Transaction transmise avec succès, transaction - - + + You can check its status by using the `show_transfers` command. Vous pouvez vérifier son statut en utilisant la commane 'show_transfers'. - + usage: export_raw_multisig <filename> - usage : export_raw_multisig <nom_fichier> + usage : export_raw_multisig <nom_fichier> - + Failed to export multisig transaction to file Échec de l'exportation de la transaction multisig vers le fichier - + Saved exported multisig transaction file(s): - Transaction multisig enregistrée dans le(s) fichier(s) : + Transaction multisig enregistrée dans le(s) fichier(s) : - - - + + + ring size must be an integer >= la taille de cercle doit être un nombre entier >= - + could not change default ring size échec du changement de la taille de cercle par défaut - + + Invalid height Hauteur invalide - + start_mining [<number_of_threads>] [bg_mining] [ignore_battery] start_mining [<nombre_de_threads>] [mine_arrière_plan] [ignorer_batterie] - + Start mining in the daemon (bg_mining and ignore_battery are optional booleans). Démarrer la mine dans le démon (mine_arrière_plan et ignorer_batterie sont des booléens facultatifs). - + Stop mining in the daemon. Arrêter la mine dans le démon. - - set_daemon <host>[:<port>] - set_daemon <hôte>[:<port>] - - - + Set another daemon to connect to. Spécifier un autre démon auquel se connecter. - + Save the current blockchain data. Sauvegarder les données actuelles de la châine de blocs. - + Synchronize the transactions and balance. Synchroniser les transactions et le solde. - + balance [detail] solde [détail] - + Show the wallet's balance of the currently selected account. Afficher le solde du compte actuellement sélectionné. - + incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] - + Show the incoming transfers, all or filtered by availability and address index. Afficher les transferts entrants, tous ou filtrés par disponibilité et index d'adresse. - + payments <PID_1> [<PID_2> ... <PID_N>] payments <PID_1> [<PID_2> ... <PID_N>] - + Show the payments for the given payment IDs. Afficher les paiements pour les IDs de paiement donnés. - + Show the blockchain height. Afficher la hauteur de la chaîne de blocs. - - transfer_original [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] - transfer_original [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> [<ID_paiement>] - - - - Transfer <amount> to <address> using an older transaction building algorithm. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) - Transférer <montant> à <adresse> en utilisant un algorithme de construction de transaction plus ancien. Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus) - - - - transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>] - transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> [<ID_paiement>] - - - - Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) - Transférer <montant> à <adresse> Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus) - - - - locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>] - locked_transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <montant> <blocs_verrou> [<ID_paiement>] - - - - Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included) - Transférer <montant> à <adresse> et le verrouiller pendant <blocs_verrou> (max 1000000). Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus) - - - + Send all unmixable outputs to yourself with ring_size 1 Envoyer toutes les sorties non mélangeables à vous-même avec une taille de cercle de 1 - - sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] - sweep_all [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> [<ID_paiement>] - - - - Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. - Envoyer tout le solde débloqué à une adresse. Si le paramètre "index<N1>[,<N2>,...]" est spécifié, le portefeuille balaye les sorties reçues par ces indices d'adresse. Si il est omis, le portefeuille choisit un index d'adresse à utiliser aléatoirement. - - - + sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> [<payment_id>] sweep_below <montant_seuil> [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> [<ID_paiement>] - + Send all unlocked outputs below the threshold to an address. Envoyer toutes les sorties débloquées d'un montant inférieur au seuil à une adresse. - - sweep_single [<priority>] [<ring_size>] <key_image> <address> [<payment_id>] - sweep_single [<priorité>] [<taille_cercle>] <image_clé> <adresse> [<ID_payment>] - - - + Send a single output of the given key image to an address without change. Envoyer une unique sortie ayant une image de clé donnée à une adresse sans rendu de monnaie. - + donate [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <amount> [<payment_id>] donate [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <montant> [<ID_paiement>] - + Donate <amount> to the development team (donate.getmonero.org). Donner <montant> à l'équipe de développement (donate.getmonero.org). - - sign_transfer <file> - sign_transfer <fichier> - - - - Sign a transaction from a <file>. - Signer une transaction d'un <fichier>. - - - + Submit a signed transaction from a file. Transmettre une transaction signée d'un fichier. - + set_log <level>|{+,-,}<categories> set_log <niveau>|{+,-,}<catégories> - + Change the current log detail (level must be <0-4>). Changer le niveau de détail du journal (le niveau doit être <0-4>). - + account account new <label text with white spaces allowed> account switch <index> @@ -1605,7 +1622,7 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j account tag_description <mot_clé> <description> - + If no arguments are specified, the wallet shows all the existing accounts along with their balances. If the "new" argument is specified, the wallet creates a new account with its label initialized by the provided label text (which can be empty). If the "switch" argument is specified, the wallet switches to the account specified by <index>. @@ -1622,215 +1639,137 @@ Si l'argument "untag" est spécifié, les mots clés assignés au Si l'argument "tag_description" est spécifié, le texte arbitraire <description> est assigné au mot clé <mot_clé>. - + address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>] address [ new <texte étiquette avec espaces autorisés> | all | <index_min> [<index_max>] | label <index> <texte étiquette avec espaces autorisés>] - - If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the walllet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text. - Si aucun argument n'est spécifié ou si <index> est spécifié, le portefeuille affiche l'adresse par défaut ou l'adresse spécifiée. Si "all" est spécifié, le portefeuille affiche toutes les adresses existantes dans le comptes actuellement sélectionné. Si "new" est spécifié, le portefeuille crée une nouvelle adresse avec le texte d'étiquette fourni (qui peut être vide). Si "label" est spécifié, le portefeuille affecte le texte fourni à l'étiquette de l'adresse spécifiée par <index>. - - - + integrated_address [<payment_id> | <address>] integrated_address [<ID_paiement> | <adresse>] - + Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID Encoder un ID de paiement dans une adresse intégrée pour l'adresse publique du portefeuille actuel (en l'absence d'argument un ID de paiement aléatoire est utilisé), ou décoder une adresse intégrée en une adresse standard et un ID de paiement - + address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)] address_book [(add ((<adresse> [pid <id>])|<adresse intégrée>) [<description avec éventuellement des espaces>])|(delete <index>)] - + Print all entries in the address book, optionally adding/deleting an entry to/from it. Afficher toutes les entrées du carnet d'adresses, optionnellement en y ajoutant/supprimant une entrée. - + Save the wallet data. Sauvegarder les données du portefeuille. - + Save a watch-only keys file. Sauvegarder un fichier de clés d'audit. - + Display the private view key. Afficher la clé privée d'audit. - + Display the private spend key. Afficher la clé privée de dépense. - + Display the Electrum-style mnemonic seed Afficher la phrase mnémonique de style Electrum - + set <option> [<value>] set <option> [<valeur>] - - Available options: - seed language - Set the wallet's seed language. - always-confirm-transfers <1|0> - Whether to confirm unsplit txes. - print-ring-members <1|0> - Whether to print detailed information about ring members during confirmation. - store-tx-info <1|0> - Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference. - default-ring-size <n> - Set the default ring size (default and minimum is 5). - auto-refresh <1|0> - Whether to automatically synchronize new blocks from the daemon. - refresh-type <full|optimize-coinbase|no-coinbase|default> - Set the wallet's refresh behaviour. - priority [0|1|2|3|4] - Set the fee to default/unimportant/normal/elevated/priority. - confirm-missing-payment-id <1|0> - ask-password <1|0> - unit <monero|millinero|micronero|nanonero|piconero> - Set the default monero (sub-)unit. - min-outputs-count [n] - Try to keep at least that many outputs of value at least min-outputs-value. - min-outputs-value [n] - Try to keep at least min-outputs-count outputs of at least that value. - merge-destinations <1|0> - Whether to merge multiple payments to the same destination address. - confirm-backlog <1|0> - Whether to warn if there is transaction backlog. - confirm-backlog-threshold [n] - Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks. - refresh-from-block-height [n] - Set the height before which to ignore blocks. - auto-low-priority <1|0> - Whether to automatically use the low priority fee level when it's safe to do so. - Options disponibles : - seed langue - Définir la langue de la phrase mnémonique. - always-confirm-transfers <1|0> - Confirmation des transactions non divisées. - print-ring-members <1|0> - Affichage d'informations détaillées sur les membres du cercle lors de la confirmation. - store-tx-info <1|0> - Sauvegarde des informations des transactions sortantes (adresse de destination, ID de paiement, clé secrète de transaction) pour référence ultérieure. - default-ring-size <n> - Définir la taille de cercle par défaut (la valeur par défaut est le minimum 5). - auto-refresh <1|0> - Synchronisation automatique des nouveaux blocs du démon. - refresh-type <full|optimize-coinbase|no-coinbase|default> - Définir le comportement du rafraîchissement du portefeuille. - priority [0|1|2|3|4] - Utiliser les frais pour la priorité par défaut/peu importante/normale/élevée/prioritaire. - confirm-missing-payment-id <1|0> - ask-password <1|0> - unit <monero|millinero|micronero|nanonero|piconero> - Définir la (sous-)unité monero par défaut. - min-outputs-count [n] - Essayer de garder au moins ce nombre de sorties d'une valeur d'au moins min-outputs-value. - min-outputs-value [n] - Essayer de garder au moins min-outputs-count sorties d'au moins cette valeur. - merge-destinations <1|0> - Fusion des paiements multiples vers la même adresse de destination. - confirm-backlog <1|0> - Avertir s'il y a un arriéré de transactions. - confirm-backlog-threshold [n] - Définir un seuil pour confirm-backlog pour avertir seulement si l'arriéré de transactions est supérieur à n blocs. - refresh-from-block-height [n] - Définir la hauteur avant laquelle les blocs sont ignorés. - auto-low-priority <1|0> - Utilisation automatique du niveau de frais pour la priorité basse, lorsqu'il est sûr de le faire. - - - + Display the encrypted Electrum-style mnemonic seed. Afficher la phrase mnémonique de style Electrum chiffrée. - + Rescan the blockchain for spent outputs. Rescanner la chaîne de blocs pour trouver les sorties dépensées. - + get_tx_key <txid> get_tx_key <ID_transaction> - + Get the transaction key (r) for a given <txid>. Obtenir la clé de transaction (r) pour un <ID_transaction> donné. - + check_tx_key <txid> <txkey> <address> check_tx_key <ID_transaction> <clé_transaction> <adresse> - + Check the amount going to <address> in <txid>. Vérifier le montant allant à <adresse> dans <ID_transaction>. - + get_tx_proof <txid> <address> [<message>] get_tx_proof <ID_transaction> <adresse> [<message>] - + Generate a signature proving funds sent to <address> in <txid>, optionally with a challenge string <message>, using either the transaction secret key (when <address> is not your wallet's address) or the view secret key (otherwise), which does not disclose the secret key. Générer une signature prouvant l'envoi de fonds à <adresse> dans <ID_transaction>, optionnellement avec un <message> comme challenge, en utilisant soit la clé secrète de transaction (quand <adresse> n'est pas l'adresse de votre portefeuille) soit la clé secrète d'audit (dans le cas contraire), tout en ne divulgant pas la clé secrète. - + check_tx_proof <txid> <address> <signature_file> [<message>] check_tx_proof <ID_transaction> <adresse> <fichier_signature> [<message>] - + Check the proof for funds going to <address> in <txid> with the challenge string <message> if any. Vérifier la validité de la preuve de fonds allant à <adresse> dans <ID_transaction> avec le <message> de challenge s'il y en a un. - + get_spend_proof <txid> [<message>] get_spend_proof <ID_transaction> [<message>] - + Generate a signature proving that you generated <txid> using the spend secret key, optionally with a challenge string <message>. Générer une signature prouvant que vous avez créé <ID_transaction> en utilisant la clé secrète de dépense, optionnellement avec un <message> comme challenge. - + check_spend_proof <txid> <signature_file> [<message>] check_spend_proof <ID_transaction> <fichier_signature> [<message>] - + Check a signature proving that the signer generated <txid>, optionally with a challenge string <message>. Vérifier la validité de la preuve que le signataire a créé <ID_transaction>, optionnellement avec un <message> comme challenge. - + get_reserve_proof (all|<amount>) [<message>] get_reserve_proof (all|<montant>) [<message>] - + Generate a signature proving that you own at least this much, optionally with a challenge string <message>. If 'all' is specified, you prove the entire sum of all of your existing accounts' balances. Otherwise, you prove the reserve of the smallest possible amount above <amount> available in your current account. @@ -1839,368 +1778,348 @@ Si 'all' est spécifié, vous prouvez la somme totale des soldes de to Sinon, vous prouvez le plus petit solde supérieur à <montant> dans votre compte actuel. - + check_reserve_proof <address> <signature_file> [<message>] check_reserve_proof <adresse> <fichier_signature> [<message>] - + Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>. Vérifier la validité d'une signature prouvant que le propriétaire d'une <adresse> détient au moins un montant, optionnellement avec un <message> comme challenge. - - show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] - show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]] - - - + Show the incoming/outgoing transfers within an optional height range. Afficher les transferts entrants/sortants dans un interval de hauteurs facultatif. - + unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] unspent_outputs [index=<N1>[,<N2>,...]] [<montant_min> [<montant_max>]] - + Show the unspent outputs of a specified address within an optional amount range. Afficher les sorties non dépensées d'une adresse spécifique dans un interval de montants facultatif. - - Rescan the blockchain from scratch. - Rescanner la chaîne de blocs en partant de zéro. - - - + set_tx_note <txid> [free text note] set_tx_note <ID_transaction> [texte de la note] - + Set an arbitrary string note for a <txid>. Définir un texte arbitraire comme note pour <ID_transaction>. - + get_tx_note <txid> get_tx_note <ID_transaction> - + Get a string note for a txid. Obtenir le texte de la note pour <ID_transaction>. - + set_description [free text note] set_description [texte] - + Set an arbitrary description for the wallet. Définir un texte arbitraire comme description du portefeuille. - + Get the description of the wallet. Obtenir la description du portefeuille. - + Show the wallet's status. Afficher l'état du portefeuille. - + Show the wallet's information. Afficher les informations du portefeuille. - + sign <file> sign <fichier> - + Sign the contents of a file. Signer le contenu d'un fichier. - + verify <filename> <address> <signature> verify <fichier> <adresse> <signature> - + Verify a signature on the contents of a file. Vérifier la signature du contenu d'un fichier. - + export_key_images <file> export_key_images <fichier> - + Export a signed set of key images to a <file>. Exported un ensemble signé d'images de clé vers un <fichier>. - + import_key_images <file> import_key_images <fichier> - + Import a signed key images list and verify their spent status. Importer un ensemble signé d'images de clé et vérifier si elles correspondent à des dépenses. - + export_outputs <file> export_outputs <fichier> - + Export a set of outputs owned by this wallet. Exporter un ensemble de sorties possédées par ce portefeuille. - + import_outputs <file> import_outputs <fichier> - + Import a set of outputs owned by this wallet. Importer un ensemble de sorties possédées par ce portefeuille. - + show_transfer <txid> show_transfer <ID_transaction> - + Show information about a transfer to/from this address. Afficher les information à propos d'un transfert vers/depuis cette adresse. - + Change the wallet's password. Changer le mot de passe du portefeuille. - + Generate a new random full size payment id. These will be unencrypted on the blockchain, see integrated_address for encrypted short payment ids. Générer un nouvel ID de paiement long aléatoire. Ceux-ci sont en clair dans la chaîne de blocs, voir integrated_address pour les IDs de paiement courts cryptés. - + Print the information about the current fee and transaction backlog. Afficher les informations à propos des frais et arriéré de transactions actuels. - + Export data needed to create a multisig wallet Exporter les données nécessaires pour créer un portefeuille multisig - + make_multisig <threshold> <string1> [<string>...] make_multisig <seuil> <chaîne_caractères1> [<chaîne_caractères>...] - + Turn this wallet into a multisig wallet Transformer ce portefeuille en portefeuille multisig - + finalize_multisig <string> [<string>...] finalize_multisig <chaîne_caractères> [<chaîne_caractères>...] - + Turn this wallet into a multisig wallet, extra step for N-1/N wallets Transformer ce portefeuille en portefeuille multisig, étape supplémentaire pour les portefeuilles N-1/N - + export_multisig_info <filename> export_multisig_info <fichier> - + Export multisig info for other participants Exporter les infos multisig pour les autres participants - + import_multisig_info <filename> [<filename>...] import_multisig_info <fichier> [<fichier>...] - + Import multisig info from other participants Importer les infos multisig des autres participants - + sign_multisig <filename> sign_multisig <fichier> - + Sign a multisig transaction from a file Signer une transaction multisig d'un fichier - + submit_multisig <filename> submit_multisig <fichier> - + Submit a signed multisig transaction from a file Transmettre une transaction multisig signée d'un fichier - + export_raw_multisig_tx <filename> export_raw_multisig_tx <fichier> - + Export a signed multisig transaction to a file Exporter une transaction multisig signée vers un fichier - + help [<command>] help [<commande>] - + Show the help section or the documentation about a <command>. Afficher la section d'aide ou la documentation d'une <commande>. - + integer >= entier >= - + block height hauteur de bloc - + No wallet found with that name. Confirm creation of new wallet named: - Aucun portefeuille avec ce nom trouvé. Confirmer la création d'un nouveau portefeuille nommé : - - - - can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name" and --generate-from-json="jsonfilename" - impossible de spécifier plus d'une option parmis --generate-new-wallet="nom_portefeuille", --wallet-file="nom_portefeuille", --generate-from-view-key="nom_portefeuille", --generate-from-spend-key="nom_portefeuille", --generate-from-keys="nom_portefeuille", --generate-from-multisig-keys="nom_portefeuille" and --generate-from-json="nom_fichier_json" + Aucun portefeuille avec ce nom trouvé. Confirmer la création d'un nouveau portefeuille nommé : - + can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic impossible de spécifier à la fois --restore-deterministic-wallet ou --restore-multisig-wallet et --non-deterministic - + --restore-multisig-wallet uses --generate-new-wallet, not --wallet-file --restore-multisig-wallet utilise --generate-new-wallet, pas --wallet-file - + specify a recovery parameter with the --electrum-seed="multisig seed here" spécifiez un paramètre de récupération avec --electrum-seed="phrase mnémonique multisig ici" - + Multisig seed failed verification Échec de la vérification de la phrase mnémonique multisig - - Enter seed encryption passphrase, empty if none - Entrer une phrase de passe pour le chiffrement de la phrase mnémonique, vide si aucune - - - - + + This address is a subaddress which cannot be used here. Cette adresse est une sous-adresse qui ne peut pas être utilisée ici. - + Error: expected M/N, but got: - Erreur : M/N attendu, mais lu : + Erreur : M/N attendu, mais lu : - + Error: expected N > 1 and N <= M, but got: - Erreur : N > 1 et N <= M attendu, mais lu : + Erreur : N > 1 et N <= M attendu, mais lu : - + Error: M/N is currently unsupported. - Erreur : M/N n'est actuellement pas supporté. + Erreur : M/N n'est actuellement pas supporté. - + Generating master wallet from %u of %u multisig wallet keys Génération du portefeuille principal à partir de %u de %u clés de portefeuille multisig - + failed to parse secret view key échec de l'analyse de la clé secrète d'audit - + failed to verify secret view key échec de la vérification de la clé secrète d'audit - + Secret spend key (%u of %u): - Clé secrète de dépense (%u de %u) : + Clé secrète de dépense (%u de %u) : - + Error: M/N is currently unsupported - Erreur : M/N n'est actuellement pas supporté + Erreur : M/N n'est actuellement pas supporté - + Restore height Hauteur de restauration - + Still apply restore height? (Y/Yes/N/No): - Appliquer la hauteur de restauration quand même ? (Y/Yes/Oui/N/No/Non) : + Appliquer la hauteur de restauration quand même ? (Y/Yes/Oui/N/No/Non) : - + Warning: using an untrusted daemon at %s, privacy will be lessened - Attention : en n'utilisant %s qui n'est pas un démon de confiance, la confidentialité sera réduite + Attention : en n'utilisant %s qui n'est pas un démon de confiance, la confidentialité sera réduite - + Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command. Le démon n'est pas lancé ou un mauvais port a été fourni. Veuillez vous assurer que le démon fonctionne ou changez l'adresse de démon avec la commande 'set_daemon'. - + Your wallet has been generated! To start synchronizing with the daemon, use the "refresh" command. Use the "help" command to see the list of available commands. @@ -2219,852 +2138,1668 @@ votre portefeuille à nouveau (mais les clés de votre portefeuille ne risquent - + failed to generate new mutlisig wallet échec de la génération du nouveau portefeuille multisig - + Generated new %u/%u multisig wallet: - Nouveau portefeuille multisig %u/%u généré : + Nouveau portefeuille multisig %u/%u généré : - + Opened %u/%u multisig wallet%s Portefeuille multisig %u/%u ouvert%s - + Use "help <command>" to see a command's documentation. Utilisez "help <commande>" pour voir la documentation d'une commande. - + wallet is multisig and cannot save a watch-only version c'est un portefeuille multisig et il ne peut pas sauvegarder une version d'audit - + missing daemon URL argument URL du démon manquante en argument - + Unexpected array length - Exited simple_wallet::set_daemon() Taille de tableau inattendue - Sortie de simple_wallet::set_daemon() - + This does not seem to be a valid daemon URL. Ceci semble ne pas être une URL de démon valide. - - + + txid ID transaction - - + + idx index - + (Some owned outputs have partial key images - import_multisig_info needed) (Certaines sorties ont des images de clé partielles - import_multisig_info requis) - + Currently selected account: [ - Compte actuellement sélectionné : [ + Compte actuellement sélectionné : [ - + ] ] - + Tag: - Mot clé : + Mot clé : - + (No tag assigned) (Pas de mot clé assigné) - + Balance per address: - Solde par adresse : + Solde par adresse : - + Address Adresse - - + + Balance Solde - - + + Unlocked balance Solde débloqué - + Outputs Sorties - - + + Label Étiquette - + %8u %6s %21s %21s %7u %21s %8u %6s %21s %21s %7u %21s - + usage: balance [detail] - usage : balance [detail] + usage : balance [detail] - - + + usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] - + spent dépensé - + global index index global - + tx id ID de transaction - - + + addr index index adresse - + No incoming transfers Aucun transfert entrant - + No incoming available transfers Aucun transfert entrant disponible - + No incoming unavailable transfers Aucun transfert entrant non disponible - + expected at least one payment ID au moins un ID de paiement attendu - + payment paiement - + transaction transaction - + height hauteur - + unlock time durée de déverrouillage - + No payments with id Aucun paiement avec l'ID - - - + + + + failed to get blockchain height: - échec de la récupération de la hauteur de la chaîne de blocs : + échec de la récupération de la hauteur de la chaîne de blocs : - - - - - + + + + + failed to connect to the daemon échec de la connexion au démon - + Transaction %llu/%llu: txid=%s -Transaction %llu/%llu : ID=%s +Transaction %llu/%llu : ID=%s - + Input %llu/%llu: amount=%s -Entrée %llu/%llu : montant=%s +Entrée %llu/%llu : montant=%s - + failed to get output: - échec de la récupération de la sortie : + échec de la récupération de la sortie : - + output key's originating block height shouldn't be higher than the blockchain height la hauteur du bloc d'origine de la clé de la sortie ne devrait pas être supérieure à celle de la chaîne de blocs - + Originating block heights: -Hauteurs des blocs d'origine : +Hauteurs des blocs d'origine : - + | | - - + + | | - + Warning: Some input keys being spent are from -Attention : Certaines clés d'entrées étant dépensées sont issues de +Attention : Certaines clés d'entrées étant dépensées sont issues de - + , which can break the anonymity of ring signature. Make sure this is intentional! , ce qui peut casser l'anonymat du cercle de signature. Assurez-vous que c'est intentionnel ! - - + + + Ring size must not be 0 La taille de cercle ne doit pas être 0 - - + + + ring size %u is too small, minimum is %u la taille de cercle %u est trop petite, le minimum est %u - + wrong number of arguments mauvais nombre d'arguments - - - + + + No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): - Aucun ID de paiement n'est inclus dans cette transaction. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : + Aucun ID de paiement n'est inclus dans cette transaction. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : - - + + No outputs found, or daemon is not ready Aucune sortie trouvée, ou le démon n'est pas prêt - + + command only supported by HW wallet + commande supportée uniquement par un portefeuille matériel + + + + Failed to reconnect device + Échec de la reconnexion à l'appareil + + + + Failed to reconnect device: + Échec de la reconnexion à l'appareil : + + + Transaction successfully saved to Transaction sauvegardée avec succès dans - - + + , txid , ID transaction - + Failed to save transaction to Échec de la sauvegarde de la transaction dans - - + + Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No): - Balayage de %s dans %llu transactions pour des frais totaux de %s. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : + Balayage de %s dans %llu transactions pour des frais totaux de %s. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : - - - + + + Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): - Balayage de %s pour des frais totaux de %s. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : - - - - Donating - Don de + Balayage de %s pour des frais totaux de %s. Est-ce correct ? (Y/Yes/Oui/N/No/Non) : - + This is a watch only wallet Ceci est un portefeuille d'audit - + usage: show_transfer <txid> - usage : show_transfer <ID_de_transaction> + usage : show_transfer <ID_de_transaction> - + Double spend seen on the network: this transaction may or may not end up being mined - Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée + Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée - + Transaction ID not found ID de transaction non trouvé - + true vrai - + failed to parse refresh type échec de l'analyse du type de rafraîchissement - - + + + + + + + + + + + + + + + + + + + + + + command not supported by HW wallet + commande non supportée par le portefeuille matériel + + + + wallet is watch-only and has no seed c'est un portefeuille d'audit et il n'a pas de phrase mnémonique - - + + wallet is non-deterministic and has no seed c'est un portefeuille non déterministe et il n'a pas de phrase mnémonique - - + + Enter optional seed offset passphrase, empty to see raw seed + Entrer une phrase de passe facultative pour le décalage de la phrase mnémonique, effacer pour voir la phrase mnémonique brute + + + + Incorrect password + Mot de passe invalide + + + + Current fee is %s %s per %s + Les frais sont actuellement de %s %s par %s + + + + usage: print_ring <key_image|txid> + usage : print_ring <image clé|ID transaction> + + + + + Invalid key image + Image de clé invalide + + + + Invalid txid + ID de transaction invalide + + + + Key image either not spent, or spent with mixin 0 + Image de clé soit non dépensée, soit dépensée avec 0 mélange + + + + Failed to get key image ring: + Échec de la récupération du cercle de l'image de clé : + + + + File doesn't exist + Le fichier d'existe pas + + + + Invalid ring specification: + Spécification de cercle invalide : + + + + Invalid key image: + Image de clé invalide : + + + + Invalid ring type, expected relative or abosolute: + Type de cercle invalide, "relative" ou "absolute" attendu : + + + + + Error reading line: + Erreur lors de la lecture de la ligne : + + + + Invalid ring: + Cercle invalide : + + + + Invalid relative ring: + Cercle relatif invalide : + + + + Invalid absolute ring: + Cercle absolu invalide : + + + + Failed to set ring for key image: + Échec de l'affectation du cercle pour l'image de clé : + + + + Continuing. + On continue. + + + + usage: set_ring <filename> | ( <key_image> absolute|relative <index> [<index>...] ) + usage : set_ring <nom_fichier> | ( <image_clé> absolute|relative <index> [<index>...] ) + + + + Missing absolute or relative keyword + Mot clé "absolute" ou "relative" manquant + + + + + invalid index: must be a strictly positive unsigned integer + index invalide : doit être un nombre entier strictement positif + + + + invalid index: indices wrap + index invalide : boucle des indices + + + + invalid index: indices should be in strictly ascending order + index invalide : les indices doivent être en ordre strictement croissant + + + + failed to set ring + échec de l'affectation du cercle + + + + usage: blackball <amount>/<offset> | <filename> [add] + usage : blackball <montant>/<offset> | <nom_fichier> [add] + + + + First line is not an amount + La première ligne n'est pas un montant + + + + Invalid output: + Sortie invalide : + + + + Bad argument: + Mauvais argument : + + + + should be "add" + devrait être "add" + + + + Failed to open file + Échec de l'ouverture du fichier + + + + Invalid output key, and file doesn't exist + Clé de sortie invalide, et le fichier n'existe pas + + + + Failed to blackball output: + Échec du blackboulage de la sortie : + + + + usage: unblackball <amount>/<offset> + usage : unblackball <montant>/<offset> + + + + + Invalid output + Sortie invalide + + + + + Failed to unblackball output: + Échec du déblackboulage de la sortie : + + + + usage: blackballed <amount>/<offset> + usage : blackballed <montant>/<offset> + + + + Blackballed: + Blackboulé : + + + + not blackballed: + non blackboulé : + + + + Failed to save known rings: + Échec de la sauvegarde des cercles connus : + + + + wallet is watch-only and cannot transfer c'est un portefeuille d'audit et il ne peut pas transférer - + + + WARNING: this is a non default ring size, which may harm your privacy. Default is recommended. + ATTENTION : ceci c'est pas la taille de cercle par défaut, ce qui peut nuire à votre confidentialité. La valeur par défaut est recommandée. + + + + WARNING: from v8, ring size will be fixed and this setting will be ignored. + ATTENTION : ) partir de v8, la taille de cercle sera fixée et ce paramètre sera ignoré. + + + + + + priority must be either 0, 1, 2, 3, or 4, or one of: + la priorité doit être 0, 1, 2, 3, 4 ou l'une de : + + + could not change default priority échec du changement de la priorité par défaut - + + invalid argument: must be either 0/never, 1/action, or 2/encrypt/decrypt + argument invalide : doit être soit 0/never, 1/action, ou 2/encrypt/decrypt + + + + set_daemon <host>[:<port>] [trusted|untrusted] + set_daemon <hôte>[:<port>] [trusted|untrusted] + + + + transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <address> <amount>) [<payment_id>] + transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] (<URI> | <adresse> <montant>) [<ID_paiement>] + + + + Transfer <amount> to <address>. If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included) + Transférer <montant> à <adresse> Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <URI_2> ou <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus) + + + + locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] (<URI> | <addr> <amount>) <lockblocks> [<payment_id>] + locked_transfer [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] (<URI> | <adresse> <montant>) <blocs_verrou> [<ID_paiement>] + + + + Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter "index=<N1>[,<N2>,...]" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. Multiple payments can be made at once by adding URI_2 or <address_2> <amount_2> etcetera (before the payment ID, if it's included) + Transférer <montant> à <adresse> et le verrouiller pendant <blocs_verrou> (max 1000000). Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par les adresses de ces indices. Si il est omis, le portefeuille choisit les indices d'adresse à utiliser aléatoirement. Dans tous les cas, il essaye de ne pas combiner des sorties de multiples adresses. <priorité> est la priorité de la transaction. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. De multiples paiements peuvent être réalisés d'un coup en ajoutant <URI_2> ou <adresse_2> <montant_2> et cetera (avant l'ID de paiement, si il est inclus) + + + + locked_sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <lockblocks> [<payment_id>] + locked_sweep_all [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] <adresse> <blocs_verrou> [<ID_paiement>] + + + + Send all unlocked balance to an address and lock it for <lockblocks> (max. 1000000). If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. <priority> is the priority of the sweep. The higher the priority, the higher the transaction fee. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command "set priority") is used. <ring_size> is the number of inputs to include for untraceability. + Transférer tout le solde débloqué à une adresse et le verrouiller pendant <blocs_verrou> (max 1000000). Si le paramètre "index=<N1>[,<N2>,...]" est spécifié, le portefeuille utilise les sorties reçues par ces indices d'adresse. Si il est omis, le portefeuille choisit un index d'adresse à utiliser aléatoirement. <priorité> est la priorité du balayage. Plus la priorité est haute, plus les frais de transaction sont élévés. Les valeurs valides par ordre de priorité (de la plus basse à la plus haute) sont : unimportant, normal, elevated, priority. Si elle est omise, la valeur par défaut (voir la commande "set priority") est utilisée. <taille_cercle> est le nombre d'entrées à inclure pour l'intraçabilité. + + + + sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id>] + sweep_all [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] [outputs=<N>] <adresse> [<ID_paiement>] + + + + Send all unlocked balance to an address. If the parameter "index<N1>[,<N2>,...]" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. If the parameter "outputs=<N>" is specified and N > 0, wallet splits the transaction into N even outputs. + Envoyer tout le solde débloqué à une adresse. Si le paramètre "index<N1>[,<N2>,...]" est spécifié, le portefeuille balaye les sorties reçues par ces indices d'adresse. Si il est omis, le portefeuille choisit un index d'adresse à utiliser aléatoirement. Si le paramètre "outputs=<N>" est spécifié et N > 0, le portefeuille scinde la transaction en N sorties égales. + + + + sweep_single [<priority>] [<ring_size>] [outputs=<N>] <key_image> <address> [<payment_id>] + sweep_single [<priorité>] [<taille_cercle>] [outputs=<N>] <image_clé> <adresse> [<ID_paiement>] + + + + sign_transfer [export_raw] + sign_transfer [export_raw] + + + + Sign a transaction from a file. If the parameter "export_raw" is specified, transaction raw hex data suitable for the daemon RPC /sendrawtransaction is exported. + Signer une transaction à partir d'un fichier. Si le paramètre "export_raw" est spécifié, les données brutes hexadécimales adaptées au RPC /sendrawtransaction du démon sont exportées. + + + + If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If "all" is specified, the wallet shows all the existing addresses in the currently selected account. If "new " is specified, the wallet creates a new address with the provided label text (which can be empty). If "label" is specified, the wallet sets the label of the address specified by <index> to the provided label text. + Si aucun argument n'est spécifié ou si <index> est spécifié, le portefeuille affiche l'adresse par défaut ou l'adresse spécifiée. Si "all" est spécifié, le portefeuille affiche toutes les adresses existantes dans le comptes actuellement sélectionné. Si "new" est spécifié, le portefeuille crée une nouvelle adresse avec le texte d'étiquette fourni (qui peut être vide). Si "label" est spécifié, le portefeuille affecte le texte fourni à l'étiquette de l'adresse spécifiée par <index>. + + + + Available options: + seed language + Set the wallet's seed language. + always-confirm-transfers <1|0> + Whether to confirm unsplit txes. + print-ring-members <1|0> + Whether to print detailed information about ring members during confirmation. + store-tx-info <1|0> + Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference. + default-ring-size <n> + Set the default ring size (default and minimum is 5). + auto-refresh <1|0> + Whether to automatically synchronize new blocks from the daemon. + refresh-type <full|optimize-coinbase|no-coinbase|default> + Set the wallet's refresh behaviour. + priority [0|1|2|3|4] + Set the fee to default/unimportant/normal/elevated/priority. + confirm-missing-payment-id <1|0> + ask-password <0|1|2 (or never|action|decrypt)> + unit <monero|millinero|micronero|nanonero|piconero> + Set the default monero (sub-)unit. + min-outputs-count [n] + Try to keep at least that many outputs of value at least min-outputs-value. + min-outputs-value [n] + Try to keep at least min-outputs-count outputs of at least that value. + merge-destinations <1|0> + Whether to merge multiple payments to the same destination address. + confirm-backlog <1|0> + Whether to warn if there is transaction backlog. + confirm-backlog-threshold [n] + Set a threshold for confirm-backlog to only warn if the transaction backlog is greater than n blocks. + refresh-from-block-height [n] + Set the height before which to ignore blocks. + auto-low-priority <1|0> + Whether to automatically use the low priority fee level when it's safe to do so. + segregate-pre-fork-outputs <1|0> + Set this if you intend to spend outputs on both Monero AND a key reusing fork. + key-reuse-mitigation2 <1|0> + Set this if you are not sure whether you will spend on a key reusing Monero fork later. +subaddress-lookahead <major>:<minor> + Set the lookahead sizes for the subaddress hash table. + Set this if you are not sure whether you will spend on a key reusing Monero fork later. + segregation-height <n> + Set to the height of a key reusing fork you want to use, 0 to use default. + Options disponibles : + seed langue + Définir la langue de la phrase mnémonique. + always-confirm-transfers <1|0> + Confirmation des transactions non scindées. + print-ring-members <1|0> + Affichage d'informations détaillées sur les membres du cercle lors de la confirmation. + store-tx-info <1|0> + Sauvegarde des informations des transactions sortantes (adresse de destination, ID de paiement, clé secrète de transaction) pour référence ultérieure. + default-ring-size <n> + Définir la taille de cercle par défaut (la valeur par défaut est le minimum 5). + auto-refresh <1|0> + Synchronisation automatique des nouveaux blocs du démon. + refresh-type <full|optimize-coinbase|no-coinbase|default> + Définir le comportement du rafraîchissement du portefeuille. + priority [0|1|2|3|4] + Utiliser les frais pour la priorité par défaut/peu importante/normale/élevée/prioritaire. + confirm-missing-payment-id <1|0> + ask-password <0|1|2 (ou never|action|decrypt)> + unit <monero|millinero|micronero|nanonero|piconero> + Définir la (sous-)unité monero par défaut. + min-outputs-count [n] + Essayer de garder au moins ce nombre de sorties d'une valeur d'au moins min-outputs-value. + min-outputs-value [n] + Essayer de garder au moins min-outputs-count sorties d'au moins cette valeur. + merge-destinations <1|0> + Fusion des paiements multiples vers la même adresse de destination. + confirm-backlog <1|0> + Avertir s'il y a un arriéré de transactions. + confirm-backlog-threshold [n] + Définir un seuil pour confirm-backlog pour avertir seulement si l'arriéré de transactions est supérieur à n blocs. + refresh-from-block-height [n] + Définir la hauteur avant laquelle les blocs sont ignorés. + auto-low-priority <1|0> + Utilisation automatique du niveau de frais pour la priorité basse, lorsqu'il est sûr de le faire. + segregate-pre-fork-outputs <1|0> + Activez ceci si vous prévoyez de dépenser des sorties à la fois avec Monero ET un fork réutilisant les clés. + key-reuse-mitigation2 <1|0> + Activez ceci si vous n'êtes pas sûr de ne jamais utiliser un fork réutilisant les clés. + subaddress-lookahead <majeur>:<mineur> + Définir les nombres de sous-adresse à inclure par anticipation dans la table de hachage des sous-adresses. + segregation-height <n> + Définir la hauteur d'un fork réutilisant les clés que vous voulez utiliser, 0 par défaut. + + + + set_tx_key <txid> <tx_key> + set_tx_key <ID_transaction> <clé_transaction> + + + + Set the transaction key (r) for a given <txid> in case the tx was made by some other device or 3rd party wallet. + Définir la clé de transaction (r) pour un <ID_transaction> donné au cas où cette clé ait été créée par un appareil ou portefeuille tiers. + + + + show_transfers [in|out|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + show_transfers [in|out|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]] + + + + Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself. + Rescanner la chaîne de blocs à partir du début, en perdant toute information qui ne peut pas être retrouvée à partir de la chaîne elle même. + + + + hw_reconnect + hw_reconnect + + + + Attempts to reconnect HW wallet. + Essayer de se reconnecter à un portefeuille matériel. + + + + print_ring <key_image> | <txid> + print_ring <image_clé> | <ID_transaction> + + + + Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) + Afficher le(s) cercle(s) utilisé(s) pour dépenser une image de clé ou une transaction (si la taille de cercle est > 1) + + + + set_ring <filename> | ( <key_image> absolute|relative <index> [<index>...] ) + set_ring <nom_fichier> | ( <image_clé> absolute|relative <index> [<index>...] ) + + + + Set the ring used for a given key image, so it can be reused in a fork + Définir le cercle utilisé pour une image de clé donnée, afin de pouvoir le réutiliser dans un fork + + + + save_known_rings + save_known_rings + + + + Save known rings to the shared rings database + Sauvegarder les cercles connus dans la base de données des cercles partagés + + + + blackball <amount>/<offset> | <filename> [add] + blackball <montant>/<offset> | <nom_fichier> [add] + + + + Blackball output(s) so they never get selected as fake outputs in a ring + Blackbouler des sorties pour qu'elles ne soient jamais sélectionnées comme leurres dans un cercle + + + + unblackball <amount>/<offset> + unblackball <montant>/<offset> + + + + Unblackballs an output so it may get selected as a fake output in a ring + Déblackbouler une sortie pour qu'elle puisse être sélectionnée comme leurre dans un cercle + + + + blackballed <amount>/<offset> + blackballed <montant>/<offset> + + + + Checks whether an output is blackballed + Vérifier si une sortie est blackboulée + + + + version + version + + + + Returns version information + Retourne les informations de version + + + full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase) full (le plus lent, aucune supposition); optimize-coinbase (rapide, suppose que la récompense de bloc est payée à une unique adresse); no-coinbase (le plus rapide, suppose que l'on ne reçoit aucune récompense de bloc), default (comme optimize-coinbase) - + + 0, 1, 2, 3, or 4, or one of + 0, 1, 2, 3, 4 ou l'une de + + + + 0|1|2 (or never|action|decrypt) + 0|1|2 (ou never|action|decrypt) + + + monero, millinero, micronero, nanonero, piconero monero, millinero, micronero, nanonero, piconero - + + <major>:<minor> + <majeur>:<mineur> + + + + wrong number range, use: set_log <log_level_number_0-4> | <categories> + nombre hors interval, utilisez : set_log <niveau_de_journalisation_0-4> | <catégories> + + + Wallet name not valid. Please try again or use Ctrl-C to quit. Nom de portefeuille non valide. Veuillez réessayer ou utilisez Ctrl-C pour quitter. - + Wallet and key files found, loading... Fichier portefeuille et fichier de clés trouvés, chargement... - + Key file found but not wallet file. Regenerating... Fichier de clés trouvé mais pas le fichier portefeuille. Régénération... - + Key file not found. Failed to open wallet: - Fichier de clés non trouvé. Échec de l'ouverture du portefeuille : + Fichier de clés non trouvé. Échec de l'ouverture du portefeuille : - + Generating new wallet... Génération du nouveau portefeuille... - + + Can't specify more than one of --testnet and --stagenet + Impossible de spécifier plus d'une option parmis --testnet et --stagenet + + + + can't specify more than one of --generate-new-wallet="wallet_name", --wallet-file="wallet_name", --generate-from-view-key="wallet_name", --generate-from-spend-key="wallet_name", --generate-from-keys="wallet_name", --generate-from-multisig-keys="wallet_name", --generate-from-json="jsonfilename" and --generate-from-device="wallet_name" + impossible de spécifier plus d'une option parmis --generate-new-wallet="nom_portefeuille", --wallet-file="nom_portefeuille", --generate-from-view-key="nom_portefeuille", --generate-from-spend-key="nom_portefeuille", --generate-from-keys="nom_portefeuille", --generate-from-multisig-keys="nom_portefeuille", --generate-from-json="nom_fichier_json" et --generate-from-device="nom_portefeuille" + + + Electrum-style word list failed verification Échec de la vérification de la liste de mots de style Electrum - - - - - - - - - - + + Enter seed offset passphrase, empty if none + Entrer une phrase de passe pour le décalage de la phrase mnémonique, vide si aucun + + + + + + + + + + + + No data supplied, cancelled Pas de données fournies, annulation - - - - - - - - - - - - + + + + + + + + + + + + failed to parse address échec de l'analyse de l'adresse - - + + failed to parse view key secret key échec de l'analyse de la clé secrète d'audit - - + + failed to verify view key secret key échec de la vérification de la clé secrète d'audit - - - + + + view key does not match standard address la clé d'audit ne correspond pas à l'adresse standard - - - - - + + + + + + account creation failed échec de la création du compte - - - + + + failed to parse spend key secret key échec de l'analyse de la clé secrète de dépense - - + + failed to verify spend key secret key échec de la vérification de la clé secrète de dépense - - + + spend key does not match standard address la clé de dépense ne correspond pas à l'adresse standard - + + No restore height is specified. + Aucune hauteur de restauration n'est spécifiée. + + + + Assumed you are creating a new account, restore will be done from current estimated blockchain height. + Nous supposons que vous créez un nouveau compte, la restauration sera faite à partir d'une hauteur de la chaîne de blocs estimée. + + + + Use --restore-height if you want to restore an already setup account from a specific height + Utilisez --restore-height si vous voulez restaurer un compte existant à partir d'une hauteur spécifique + + + + account creation aborted + création du compte annulée + + + + can't specify --subaddress-lookahead and --wallet-file at the same time + Impossible de spécifier --subaddress-lookahead et --wallet-file en même temps + + + failed to open account échec de l'ouverture du compte - - - - - + + + + + wallet is null portefeuille est nul - - + + Failed to initialize ring database: privacy enhancing features will be inactive + Impossible d'initialiser la base de données des cercles : les fonctions d'amélioration de la confidentialité seront inactives + + + + If your display freezes, exit blind with ^C, then run again with --use-english-language-names + Si votre affichage se bloque, quittez en aveugle avec ^C, puis lancer à nouveau en utilisant --use-english-language-names + + + + invalid language choice entered. Please try again. choix de langue passé invalide. Veuillez réessayer. - + View key: - Clé d'audit : + Clé d'audit : + + + + Generated new wallet on hw device: + Nouveau portefeuille généré sur l'appareil : - + + Key file not found. Failed to open wallet + Fichier des clés non trouvé. Échec d'ouverture du portefeuille + + + You may want to remove the file "%s" and try again Vous pourriez vouloir supprimer le fichier "%s" et réessayer - + failed to deinitialize wallet échec de la désinitialisation du portefeuille - - - + + Watch only wallet saved as: + Portefeuille d'audit sauvegardé vers : + + + + Failed to save watch only wallet: + Échec de la sauvegarde du portefeuille d'audit : + + + + + this command requires a trusted daemon. Enable with --trusted-daemon cette commande requiert un démon de confiance. Activer avec --trusted-daemon - + + invalid arguments. Please use start_mining [<number_of_threads>] [do_bg_mining] [ignore_battery] + arguments invalides. Veuillez utiliser start_mining [<nombre_de_threads>] [do_bg_mining] [ignore_battery] + + + + Expected trusted or untrusted, got + "trusted" ou "untrusted" attendu, mais lu + + + + trusted + de confiance + + + + untrusted + non fiable + + + blockchain can't be saved: - la chaîne de blocs ne peut pas être sauvegardée : + la chaîne de blocs ne peut pas être sauvegardée : + + + + NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead + NOTE: cette transaction utilise un ID de paiement chiffré: veuillez considérer l'utilisation de sous-adresses à la place + + + + WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead + ATTENTION: cette transaction utilise un ID de paiement non chiffré: veuillez considérer l'utilisation de sous-adresses à la place + + + + Password needed (%s) - use the refresh command + Mot de passe requis (%s) - utilisez la commande refresh + + + + Enter password + Entrez le mot de passe - - + + daemon is busy. Please try again later. le démon est occupé. Veuillez réessayer plus tard. - - + + no connection to daemon. Please make sure daemon is running. pas de connexion au démon. Veuillez vous assurer que le démon fonctionne. - + refresh error: - erreur du rafraîchissement : + erreur du rafraîchissement : - + + (Some owned outputs have missing key images - import_key_images needed) + (Il manque les images de clé de certaines sorties - import_key_images requis) + + + Balance: - Solde : + Solde : - + pubkey clé publique - + key image image de clé - - + + unlocked déverrouillé - + ringct ringct - + T V - + F F - + locked vérrouillé - + RingCT RingCT - + - - - + payment ID has invalid format, expected 16 or 64 character hex string: - format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : + format d'identifiant de paiement invalide, 16 ou 64 caractères hexadécimaux attendus : - + failed to get spent status échec de la récupération du statut de dépense - - the same transaction - la même transaction + + failed to find construction data for tx input + échec de la recherche des données pour contruire l'entrée de la transaction + + + + the same transaction + la même transaction + + + + blocks that are temporally very close + blocs très proches dans le temps + + + + + + ring size %u is too large, maximum is %u + la taille de cercle %u est trop grande, le maximum est %u + + + + + Unencrypted payment IDs are bad for privacy: ask the recipient to use subaddresses instead + Les ID de paiment non chiffrés sont mauvais pour la confidentialité : demandez au bénéficiaire d'utiliser les sous-adresses à la place + + + + payment id failed to encode + échec de l'encodage de l'ID de paiement + + + + + Locked blocks too high, max 1000000 (˜4 yrs) + Nombre de blocs verrou trop élévé, 1000000 max (˜4 ans) + + + + failed to parse short payment ID from URI + échec de l'analyse de l'ID de paiement court à partir de l'URI + + + + + Invalid last argument: + Dernier argument invalide : + + + + a single transaction cannot use more than one payment id + une unique transaction ne peut pas utiliser plus d'un ID de paiement + + + + failed to parse payment id, though it was detected + échec de l'analyse de l'ID de paiement, bien qu'il ait été détecté + + + + Not enough money in unlocked balance + Pas assez de fonds dans le solde débloqué + + + + Discarding %s of unmixable outputs that cannot be spent, which can be undone by "rescan_spent". Is this okay? (Y/Yes/N/No): + On se débarrasse de %s de sorties non mélangeables qui ne peuvent pas être dépensées, ce qui peut être défait avec "rescan_spent". Est-ce d'accord ? (Y/Yes/N/No) : + + + + usage: %s [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] [outputs=<N>] <address> [<payment_id>] + usage: %s [index=<N1>[,<N2>,...]] [<priorité>] [<taille_cercle>] [outputs=<N>] <adresse> [<ID_paiement>] + + + + missing lockedblocks parameter + paramètre blocs_verrou manquant + + + + bad locked_blocks parameter + mauvais paramètre blocs_verrou + + + + + Failed to parse number of outputs + Échec de l'analyse du nombre de sorties + + + + + Amount of outputs should be greater than 0 + Le nombre de sorties doit être supérieur à 0 + + + + usage: sweep_single [<priority>] [<ring_size>] [outputs=<N>] <key_image> <address> [<payment_id>] + usage : sweep_single [<priorité>] [<taille_cercle>] [outputs=<N>] <image_clé> <adresse> [<ID_paiement>] + + + + donations are not enabled on the testnet or on the stagenet + les dons ne sont pas activés sur les réseaux testnet et stagenet + + + + Donating %s %s to The Monero Project (donate.getmonero.org or %s). + Don de %s %s à The Monero Project (donate.getmonero.org ou %s). + + + + usage: sign_transfer [export_raw] + usage : sign_transfer [export_raw] + + + + usage: set_tx_key <txid> <tx_key> + usage : set_tx_key <ID_transaction> <clé_transaction> + + + + + + failed to parse tx_key + échec de l'analyse de la clé de transaction - - blocks that are temporally very close - blocs très proches dans le temps + + Tx key successfully stored. + Clé de transaction sauvegardée avec succès. - - Locked blocks too high, max 1000000 (˜4 yrs) - Nombre de blocs verrou trop élévé, 1000000 max (˜4 ans) + + Failed to store tx key: + Échec de la sauvegarde de la clé de transaction : - - + + Good signature Bonne signature - - - + + + Bad signature Mauvaise signature - + + usage: show_transfers [in|out|all|pending|failed|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] + usage : show_transfers [in|out|all|pending|failed|coinbase] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]] + + + + block + bloc + + + + Warning: this will lose any information which can not be recovered from the blockchain. + Attention : ceci pedra toute information qui ne peut pas être retrouvée à partir de la chaîne de blocs. + + + + This includes destination addresses, tx secret keys, tx notes, etc + Ceci inclut les adresses de destination, les clé secrètes de transaction, les notes de transaction, etc + + + + Rescan anyway ? (Y/Yes/N/No): + Rescanner quand même ? (Y/Yes/N/No) : + + + usage: integrated_address [payment ID] - usage : integrated_address [ID paiement] + usage : integrated_address [ID paiement] - + Standard address: - Adresse standard : + Adresse standard : - + failed to parse payment ID or address échec de l'analyse de l'ID de paiement ou de l'adresse - + usage: address_book [(add (<address> [pid <long or short payment id>])|<integrated address> [<description possibly with whitespaces>])|(delete <index>)] - usage : address_book [(add (<adresse> [pid <ID de paiement long ou court>])|<adresse integrée> [<description avec des espaces possible>])|(delete <index>)] + usage : address_book [(add (<adresse> [pid <ID de paiement long ou court>])|<adresse integrée> [<description avec des espaces possible>])|(delete <index>)] - + failed to parse payment ID échec de l'analyse de l'ID de paiement - + failed to parse index échec de l'analyse de l'index - + Address book is empty. Le carnet d'adresses est vide. - + Index: - Index : + Index : - - + + Address: - Adresse : + Adresse : - + Payment ID: - ID de paiement : + ID de paiement : - - + + Description: - Description : + Description : - + usage: set_tx_note [txid] free text note - usage : set_tx_note [ID transaction] note de texte libre + usage : set_tx_note [ID transaction] note de texte libre - + usage: get_tx_note [txid] - usage : get_tx_note [ID transaction] + usage : get_tx_note [ID transaction] + + + + Network type: + Type de réseau : + + + + Testnet + Testnet + + + + Stagenet + Stagenet + + + + Mainnet + Mainnet - + usage: sign <filename> - usage : sign <fichier> + usage : sign <fichier> - + wallet is watch-only and cannot sign c'est un portefeuille d'audit et il ne peut pas signer - - - - + + + + failed to read file échec de la lecture du fichier - + usage: check_tx_proof <txid> <address> <signature_file> [<message>] - usage : check_tx_proof <ID_transaction> <adresse> <fichier_signature> [<message>] + usage : check_tx_proof <ID_transaction> <adresse> <fichier_signature> [<message>] - - - + + + failed to load signature file échec du chargement du fichier signature - + usage: get_spend_proof <txid> [<message>] - usage : get_spend_proof <ID_transaction> [<message>] + usage : get_spend_proof <ID_transaction> [<message>] - + wallet is watch-only and cannot generate the proof c'est un portefeuille d'audit et il ne peut générer de preuve - + usage: check_spend_proof <txid> <signature_file> [<message>] - usage : check_spend_proof <ID_transaction> <fichier_signature> [<message>] + usage : check_spend_proof <ID_transaction> <fichier_signature> [<message>] - + usage: get_reserve_proof (all|<amount>) [<message>] - usage : get_reserve_proof (all|<montant>) [<message>] + usage : get_reserve_proof (all|<montant>) [<message>] - + The reserve proof can be generated only by a full wallet La preuve de réserve ne peut être généré que par un portefeuille complet - + usage: check_reserve_proof <address> <signature_file> [<message>] - usage : check_reserve_proof <adresse> <fichier_signature> [<message>] + usage : check_reserve_proof <adresse> <fichier_signature> [<message>] - + Address must not be a subaddress L'adresse ne doit pas être une sous-adresse - + Good signature -- total: %s, spent: %s, unspent: %s - Bonne signature -- total : %s, dépensé : %s, non dépensé : %s - - - - usage: show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] - usage : show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<hauteur_min> [<hauteur_max>]] + Bonne signature -- total : %s, dépensé : %s, non dépensé : %s - + [Double spend seen on the network: this transaction may or may not end up being mined] - [Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée] + [Double dépense détectée sur le réseau : cette transaction sera peut-être invalidée] - + usage: unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]] - usage : unspent_outputs [index=<N1>[,<N2>,...]] [<montant_min> [<montant_max>]] + usage : unspent_outputs [index=<N1>[,<N2>,...]] [<montant_min> [<montant_max>]] - + There is no unspent output in the specified address Il n'y a pas de sortie non dépensée pour l'adresse spécifiée - + (no daemon) (pas de démon) - + (out of sync) (désynchronisé) - + (Untitled account) (compte sans nom) - - - - - - + + + + + + failed to parse index: - échec de l'analyse de l'index : + échec de l'analyse de l'index : - - + + specify an index between 0 and specifiez un index entre 0 et - + usage: account account new <label text with white spaces allowed> @@ -3073,7 +3808,7 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < account tag <tag_name> <account_index_1> [<account_index_2> ...] account untag <account_index_1> [<account_index_2> ...] account tag_description <tag_name> <description> - usage : + usage : account account new <texte étiquette avec espaces autorisés> account switch <index> @@ -3083,472 +3818,458 @@ Attention : Certaines clés d'entrées étant dépensées sont issues de < account tag_description <mot_clé> <description> - + Grand total: Balance: -Somme finale : - Solde : +Somme finale : + Solde : - + , unlocked balance: - , solde débloqué : + , solde débloqué : - + Untagged accounts: - Comptes sans mot clé : + Comptes sans mot clé : - + Tag %s is unregistered. Le mot clé %s n'est pas enregistré. - + Accounts with tag: - Comptes avec mot clé : + Comptes avec mot clé : - + Tag's description: - Description du mot clé : + Description du mot clé : - + Account Compte - + %c%8u %6s %21s %21s %21s %c%8u %6s %21s %21s %21s - + ---------------------------------------------------------------------------------- ---------------------------------------------------------------------------------- - + %15s %21s %21s %15s %21s %21s - + Primary address Adresse primaire - + (used) (utilisé) - + (Untitled address) (adresse sans nom) - + <index_min> is already out of bound <index_min> est déjà hors limite - + <index_max> exceeds the bound <index_max> excède la limite - + usage: address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed> ] - usage : address [ new <texte étiquette avec espaces autorisés> | all | <index_min> [<index_max>] | label <index> <texte étiquette avec espaces autorisés>] + usage : address [ new <texte étiquette avec espaces autorisés> | all | <index_min> [<index_max>] | label <index> <texte étiquette avec espaces autorisés>] - - + + Integrated addresses can only be created for account 0 Les adresses intégrées ne peuvent être créées que pour le compte 0 - + Integrated address: %s, payment ID: %s - Adresse intégrée : %s, ID de paiement : %s + Adresse intégrée : %s, ID de paiement : %s - + Subaddress: - Sous-adresse : + Sous-adresse : - + usage: get_description - usage : get_description + usage : get_description - + no description found pas de description trouvée - + description found: - description trouvée : + description trouvée : - + Filename: - Fichier : + Fichier : - + Watch only Audit - + %u/%u multisig%s Multisig %u/%u%s - + Normal Normal - + Type: - Type : - - - - Testnet: - Testnet : - - - - Yes - Oui - - - - No - Non + Type : - + This wallet is multisig and cannot sign C'est un portefeuille multisig et il ne peut pas signer - + usage: verify <filename> <address> <signature> - usage : verify <fichier> <adresse> <signature> + usage : verify <fichier> <adresse> <signature> - + Bad signature from Mauvaise signature de - + Good signature from Bonne signature de - + usage: export_key_images <filename> - usage : export_key_images <fichier> + usage : export_key_images <fichier> - + wallet is watch-only and cannot export key images c'est un portefeuille d'audit et il ne peut pas exporter les images de clé - - - + + + failed to save file échec de l'enregistrement du fichier - + Signed key images exported to Images de clé signées exportées vers - + usage: import_key_images <filename> - usage : import_key_images <fichier> + usage : import_key_images <fichier> - + usage: export_outputs <filename> - usage : export_outputs <fichier> + usage : export_outputs <fichier> - + Outputs exported to Sorties exportées vers - + usage: import_outputs <filename> - usage : import_outputs <fichier> + usage : import_outputs <fichier> - - - - + + + + amount is wrong: - montant erroné : + montant erroné : - + expected number from 0 to attend un nombre de 0 à - + Sweeping Balayage de - + Money successfully sent, transaction: - Fonds envoyés avec succès, transaction : + Fonds envoyés avec succès, transaction : - + Change goes to more than one address La monnaie rendue va à plus d'une adresse - + %s change to %s %s de monnaie rendue à %s - + no change sans monnaie rendue - - - + + + Transaction successfully signed to file Transaction signée avec succès dans le fichier - + usage: get_tx_key <txid> - usage : get_tx_key <ID transaction> - - - - - - - - - - - + usage : get_tx_key <ID transaction> + + + + + + + + + + + + failed to parse txid échec de l'analyse de l'ID de transaction - + Tx key: - Clé de transaction : + Clé de transaction : - + no tx keys found for this txid aucune clé de transaction trouvée pour cet ID de transaction - + usage: get_tx_proof <txid> <address> [<message>] - usage : get_tx_proof <ID_transaction> <adresse> [<message>] + usage : get_tx_proof <ID_transaction> <adresse> [<message>] - - - + + + signature file saved to: - fichier signature sauvegardé dans : + fichier signature sauvegardé dans : - - - + + + failed to save signature file échec de la sauvegarde du fichier signature - + usage: check_tx_key <txid> <txkey> <address> - usage : check_tx_key <ID transaction> <clé transaction> <adresse> + usage : check_tx_key <ID transaction> <clé transaction> <adresse> - - + + failed to parse tx key échec de l'analyse de la clé de transaction - - - + + + error: - erreur : + erreur : - - + + received a reçu - - + + in txid dans la transaction - - + + received nothing in txid n'a rien reçu dans la transaction - - + + WARNING: this transaction is not yet included in the blockchain! - ATTENTION : cette transaction n'est pas encore inclue dans la chaîne de blocs ! + ATTENTION : cette transaction n'est pas encore inclue dans la chaîne de blocs ! - - + + This transaction has %u confirmations Cette transaction a %u confirmations - - + + WARNING: failed to determine number of confirmations! - ATTENTION : échec de la détermination du nombre de confirmations ! + ATTENTION : échec de la détermination du nombre de confirmations ! - + bad min_height parameter: - mauvais paramètre hauteur_minimum : + mauvais paramètre hauteur_minimum : - + bad max_height parameter: - mauvais paramètre hauteur_maximum : + mauvais paramètre hauteur_maximum : - + in reçu - - + + out payé - + failed échoué - + pending en attente - + <min_amount> should be smaller than <max_amount> <montant_minimum> doit être inférieur à <montant_maximum> - + Amount: -Montant : +Montant : - + , number of keys: - , nombre de clés : + , nombre de clés : - + - + Min block height: -Hauteur de bloc minimum : +Hauteur de bloc minimum : - + Max block height: -Hauteur de bloc maximum : +Hauteur de bloc maximum : - + Min amount found: -Montant minimum trouvé : +Montant minimum trouvé : - + Max amount found: -Montant maximum trouvé : +Montant maximum trouvé : - + Total count: -Compte total : +Compte total : - + Bin size: -Taille de classe : +Taille de classe : - + Outputs per *: -Sorties par * : +Sorties par * : - + count ^ @@ -3557,54 +4278,54 @@ Sorties par * : - + | | - + + + - + +--> block height +--> hauteur de bloc - + ^ ^ - + ^ ^ - + - + wallet portefeuille - - + + Random payment ID: - ID de paiement aléatoire : + ID de paiement aléatoire : - + Matching integrated address: - Adresse intégrée correspondante : + Adresse intégrée correspondante : @@ -3621,7 +4342,7 @@ Sorties par * : - How many participants wil share parts of the multisig wallet + How many participants will share parts of the multisig wallet Combien de participants partageront des parts du portefeuille multisig @@ -3632,161 +4353,395 @@ Sorties par * : Create testnet multisig wallets - Créer un portefeuille multisig testnet + Créer des portefeuilles multisig testnet + + + + Create stagenet multisig wallets + Créer des portefeuilles multisig stagenet + + + + Create an address file for new wallets + Créer un fichier d'adresse pour les nouveaux portefeuilles - + Generating %u %u/%u multisig wallets Génération de %u portefeuilles multisig %u/%u - + + Failed to verify multisig info + Échec de la vérification des infos multisig + + + Error verifying multisig extra info Erreur de vérification des infos multisig supplémentaires - + Error finalizing multisig Erreur de finalisation multisig - + Generated multisig wallets for address Portefeuilles multisig générés pour l'adresse - + Error creating multisig wallets: - Erreur de création des portefeuilles multisig : + Erreur de création des portefeuilles multisig : - + This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other Ce programme génère un ensemble de portefeuilles multisig - n'utilisez cette méthode plus simple que si tous les participants se font confiance - + + Error: Can't specify more than one of --testnet and --stagenet + Erreur: Impossible de spécifier plus d'une option parmis --testnet et --stagenet + + + Error: expected N/M, but got: - Erreur : N/M attendu, mais lu : + Erreur : N/M attendu, mais lu : - - + + Error: either --scheme or both of --threshold and --participants may be given - Erreur : soit --scheme soit --threshold et --participants doivent être indiqués + Erreur : soit --scheme soit --threshold et --participants doivent être indiqués - + Error: expected N > 1 and N <= M, but got N==%u and M==%d - Erreur : N > 1 et N <= M attendu, mais lu N==%u et M==%d + Erreur : N > 1 et N <= M attendu, mais lu N==%u et M==%d - + Error: --filename-base is required - Erreur : --filename-base est requis + Erreur : --filename-base est requis - + Error: unsupported scheme: only N/N and N-1/N are supported - Erreur : schéma non supporté : seuls N/N et N-1/N sont supportés + Erreur : schéma non supporté : seuls N/N et N-1/N sont supportés sw - + Generate new wallet and save it to <arg> Générer un nouveau portefeuille et le sauvegarder dans <arg> - + + Generate new wallet from device and save it to <arg> + Générer un nouveau portefeuille à partir de l'appareil et le sauvegarder dans <arg> + + + Generate incoming-only wallet from view key Générer un portefeuille d'audit à partir d'une clé d'audit - + Generate deterministic wallet from spend key Générer un portefeuille déterministe à partir d'une clé de dépense - + Generate wallet from private keys Générer un portefeuille à partir de clés privées - + Generate a master wallet from multisig wallet keys Générer un portefeuille principal à partir de clés de portefeuille multisig - + Language for mnemonic Langue de la phrase mnémonique - + Specify Electrum seed for wallet recovery/creation Spécifier la phrase mnémonique Electrum pour la récupération/création d'un portefeuille - + Recover wallet using Electrum-style mnemonic seed Récupérer un portefeuille en utilisant une phrase mnémonique de style Electrum - + Recover multisig wallet using Electrum-style mnemonic seed Récupérer un portefeuille multisig en utilisant une phrase mnémonique de style Electrum - + Generate non-deterministic view and spend keys Générer des clés d'audit et de dépense non déterministes - - Enable commands which rely on a trusted daemon - Activer les commandes qui dépendent d'un démon de confiance + + invalid argument: must be either 0/1, true/false, y/n, yes/no + argument invalide : doit être soit 0/1, true/false, y/n, yes/no - + + DNSSEC validation passed + Validation DNSSEC réussie + + + + WARNING: DNSSEC validation was unsuccessful, this address may not be correct! + ATTENTION: la validation DNSSEC a échoué, cette adresse n'est peut être pas correcte ! + + + + For URL: + Pour l'URL : + + + + Monero Address = + Adresse Monero = + + + + Is this OK? (Y/n) + Est-ce correct ? (Y/n) + + + + you have cancelled the transfer request + vous avez annulé la demande de transfert + + + + failed to parse index: + échec de l'analyse de l'index : + + + + invalid format for subaddress lookahead; must be <major>:<minor> + format invalide pour l'anticipation des sous-addresses; doit être <majeur>:<mineur> + + + + no connection to daemon. Please make sure daemon is running. + pas de connexion au démon. Veuillez vous assurer que le démon fonctionne. + + + + RPC error: + Erreur RPC : + + + + failed to get random outputs to mix: + échec de la récupération de sorties aléatoires à mélanger : + + + + + Not enough money in unlocked balance + Pas assez de fonds dans le solde débloqué + + + + Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees + Impossible de trouver une façon de créer les transactions. Ceci est souvent dû à de la poussière si petite qu'elle ne peut pas payer ses propres frais, ou à une tentative d'envoi d'un montant supérieur au solde débloqué, ou à un montant restant insuffisant pour payer les frais + + + + not enough outputs for specified ring size + pas assez de sorties pour la taille de cercle spécifiée + + + + output amount + montant de la sortie + + + + found outputs to use + sorties à utiliser trouvées + + + + Please use sweep_unmixable. + Veuillez utiliser sweep_unmixable. + + + + transaction was not constructed + la transaction n'a pas été construite + + + + transaction %s was rejected by daemon with status: + la transaction %s a été rejetée par le démon avec le statut : + + + + Reason: + Raison : + + + + one of destinations is zero + une des destinations est zéro + + + + failed to find a suitable way to split transactions + échec de la recherche d'une façon adéquate de scinder les transactions + + + + unknown transfer error: + erreur de transfert inconnue : + + + + Multisig error: + Erreur multisig : + + + + internal error: + erreur interne : + + + + unexpected error: + erreur inattendue : + + + + There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a transaction immediately. Alternatively, connect to another node so the original node cannot correlate information. + Il y a eu une erreur, ce qui pourrait signifier que le noeud essaye de vous faire réessayer de créer une transaction, pour tenter d'identifier quelles sorties sont les votres. Ou il pourrait s'agir d'une erreur de bonne foi. Il pourrait être prudent de se déconnecter de ce noeud, et de ne pas essayer d'envoyer une transaction immédiatement. Ou sinon, se connecter à un autre noeud pour que le noeud original ne puisse pas corréler les informations. + + + + File %s likely stores wallet private keys! Use a different file name. + Le fichier %s contient probablement des clés privées de portefeuille ! Utilisez un nom de fichier différent. + + + + File %s already exists. Are you sure to overwrite it? (Y/Yes/N/No): + Le fichier %s existe déjà. Êtes vous sûr de vouloir l'écraser ? (Y/Yes/N/No) : + + + + seconds + secondes + + + + minutes + minutes + + + + hours + heures + + + + days + jours + + + + months + mois + + + + a long time + longtemps + + + + This is the command line monero wallet. It needs to connect to a monero +daemon to work correctly. +WARNING: Do not reuse your Monero keys on another fork, UNLESS this fork has key reuse mitigations built in. Doing so will harm your privacy. + Ceci est le portefeuille monero en ligne de commande. +Il a besoin de se connecter à un démon monero pour fonctionner correctement. +ATTENTION : Ne réutilisez pas vos clés Monero avec un autre fork, À MOINS QUE ce fork inclue des mitigations contre la réutilisation des clés. Faire ceci nuira à votre confidentialité. + + + + Unknown command: + Commande inconnue : + + + Allow communicating with a daemon that uses a different RPC version Autoriser la communication avec un démon utilisant une version de RPC différente - + Restore from specific blockchain height Restaurer à partir d'une hauteur de bloc spécifique - + The newly created transaction will not be relayed to the monero network La transaction nouvellement créée ne sera pas transmise au réseau monero - + + Create an address file for new wallets + Créer un fichier d'adresse pour les nouveaux portefeuilles + + + + Display English language names + Afficher les noms de langue en anglais + + + + failed to read wallet password + échec de la lecture du mot de passe du portefeuille + + + + Enter a new password for the wallet + Entrer un nouveau mot de passe pour le portefeuille + + + + Wallet password + Mot de passe du portefeuille + + + + daemon is busy. Please try again later. le démon est occupé. Veuillez réessayer plus tard. - + possibly lost connection to daemon connexion avec le démon peut-être perdue - + Error: - Erreur : - - - - This is the command line monero wallet. It needs to connect to a monero -daemon to work correctly. - Ceci est le portefeuille monero en ligne de commande. Il a besoin de se -connecter à un démon monero pour fonctionner correctement. + Erreur : - + Failed to initialize wallet Échec de l'initialisation du portefeuille @@ -3794,310 +4749,365 @@ connecter à un démon monero pour fonctionner correctement. tools::wallet2 - + Use daemon instance at <host>:<port> Utiliser l'instance de démon située à <hôte>:<port> - + Use daemon instance at host <arg> instead of localhost Utiliser l'instance de démon située à l'hôte <arg> au lieu de localhost - + Wallet password file Fichier mot de passe du portefeuille - + Use daemon instance at port <arg> instead of 18081 Utiliser l'instance de démon située au port <arg> au lieu de 18081 - + For testnet. Daemon must also be launched with --testnet flag Pour testnet, le démon doit aussi être lancé avec l'option --testnet - - Restricts to view-only commands - Restreindre aux commandes en lecture-seule - - - + can't specify daemon host or port more than once impossible de spécifier l'hôte ou le port du démon plus d'une fois - + can't specify more than one of --password and --password-file impossible de spécifier plus d'une option parmis --password et --password-file - + the password file specified could not be read le fichier mot de passe spécifié n'a pas pu être lu - + Failed to load file Échec du chargement du fichier - + Wallet password (escape/quote as needed) Mot de passe du portefeuille (échapper/citer si nécessaire) - + + Enable commands which rely on a trusted daemon + Activer les commandes qui dépendent d'un démon de confiance + + + + Disable commands which rely on a trusted daemon + Désactiver les commandes qui dépendent d'un démon de confiance + + + Specify username[:password] for daemon RPC client Spécifier le nom_utilisateur:[mot_de_passe] pour le client RPC du démon - + + For stagenet. Daemon must also be launched with --stagenet flag + Pour stagenet, le démon doit aussi être lancé avec l'option --stagenet + + + + Set shared ring database path + Définir le chemin de la base de donnée de cercles partagés + + + + Number of rounds for the key derivation function + Nombre de rondes de la fonction de dérivation de clé + + + + HW device to use + Portefeuille matériel à utiliser + + + + --trusted-daemon and --untrusted-daemon are both seen, assuming untrusted + --trusted-daemon et --untrusted-daemon présents simultanément, --untrusted-daemon choisi + + + + Daemon is local, assuming trusted + Le démon est local, supposons qu'il est de confiance + + + no password specified; use --prompt-for-password to prompt for a password pas de mot de passe spécifié; utilisez --prompt-for-password pour demander un mot de passe - + + Enter a new password for the wallet + Entrer un nouveau mot de passe pour le portefeuille + + + + Wallet password + Mot de passe du portefeuille + + + Failed to parse JSON Échec de l'analyse JSON - + Version %u too new, we can only grok up to %u Version %u trop récente, on comprend au mieux %u - + failed to parse view key secret key échec de l'analyse de la clé secrète d'audit - - - + + + failed to verify view key secret key échec de la vérification de la clé secrète d'audit - + failed to parse spend key secret key échec de l'analyse de la clé secrète de dépense - - - + + + failed to verify spend key secret key échec de la vérification de la clé secrète de dépense - + Electrum-style word list failed verification Échec de la vérification de la liste de mots de style Electrum - - At least one of Electrum-style word list and private view key and private spend key must be specified + + At least one of either an Electrum-style word list, private view key, or private spend key must be specified Il faut spécifier au moins une des options parmis la liste de mots de style Electrum, la clé privée d'audit et la clé privée de dépense - + Both Electrum-style word list and private key(s) specified Liste de mots de style Electrum et clé privée spécifiées en même temps - + invalid address adresse invalide - + view key does not match standard address la clé d'audit ne correspond pas à l'adresse standard - + spend key does not match standard address la clé de dépense ne correspond pas à l'adresse standard - + Cannot generate deprecated wallets from JSON Impossible de générer un portefeuille obsolète à partir de JSON - + failed to parse address: - échec de l'analyse de l'adresse : + échec de l'analyse de l'adresse : - + Address must be specified in order to create watch-only wallet L'adresse doit être spécifiée afin de créer un portefeuille d'audit - + failed to generate new wallet: - échec de la génération du nouveau portefeuille : + échec de la génération du nouveau portefeuille : - - - - - - - - + + Password is needed to compute key image for incoming monero + Le mot de passe est requis pour calculer l'image de clé pour les moneros entrants + + + + Invalid password: password is needed to compute key image for incoming monero + Mot de passe invalide : le mot de passe est requis pour calculer l'image de clé pour les moneros entrants + + + + + Primary account Compte primaire - + No funds received in this tx. Aucun fonds n'a été reçu dans cette transaction. - + failed to read file échec de la lecture du fichier + + + Set subaddress lookahead sizes to <major>:<minor> + Définir les tailles d'anticipation des sous-addresses à <majeur>:<mineur> + tools::wallet_rpc_server - - Daemon is local, assuming trusted - Le démon est local, supposons qu'il est de confiance - - - + Failed to create directory Échec de la création du répertoire - + Failed to create directory %s: %s - Échec de la création du répertoire %s : %s + Échec de la création du répertoire %s : %s - + Cannot specify -- Impossible de spécifier -- - + and -- et -- - + Failed to create file Échec de la création du fichier - + . Check permissions or remove file . Vérifiez les permissions ou supprimez le fichier - + Error writing to file Erreur d'écriture dans le fichier - + RPC username/password is stored in file nom_utilisateur/mot_de_passe RPC sauvegardé dans le fichier - + Tag %s is unregistered. Le mot clé %s n'est pas enregistré. - + Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee) - Transaction impossible. Solde disponible : %s, montant de la transaction %s = %s + %s (frais) + Transaction impossible. Solde disponible : %s, montant de la transaction %s = %s + %s (frais) - + This is the RPC monero wallet. It needs to connect to a monero daemon to work correctly. Ceci est le portefeuille monero par RPC. Il a besoin de se connecter à un démon monero pour fonctionner correctement. - + Can't specify more than one of --wallet-file and --generate-from-json Impossible de spécifier plus d'une option parmis --wallet-file et --generate-from-json - + + Can't specify more than one of --testnet and --stagenet + Impossible de spécifier plus d'une option parmis --testnet et --stagenet + + + Must specify --wallet-file or --generate-from-json or --wallet-dir --wallet-file, --generate-from-json ou --wallet-dir doit être spécifié - + Loading wallet... Chargement du portefeuille... - - + + Saving wallet... Sauvegarde du portefeuille... - - + + Successfully saved Sauvegardé avec succès - + Successfully loaded Chargé avec succès - + Wallet initialization failed: - Échec de l'initialisation du portefeuille : + Échec de l'initialisation du portefeuille : - + Failed to initialize wallet RPC server Échec de l'initialisation du serveur RPC du portefeuille - + Starting wallet RPC server Démarrage du serveur RPC du portefeuille - + Failed to run wallet: - Échec du lancement du portefeuille : + Échec du lancement du portefeuille : - + Stopped wallet RPC server Arrêt du serveur RPC du portefeuille - + Failed to save wallet: - Échec de la sauvegarde du portefeuille : + Échec de la sauvegarde du portefeuille : wallet_args - - - + + + Wallet options Options du portefeuille @@ -4112,51 +5122,51 @@ connecter à un démon monero pour fonctionner correctement. Utiliser le portefeuille <arg> - + Max number of threads to use for a parallel job Nombre maximum de threads à utiliser pour les travaux en parallèle - + Specify log file Spécifier le fichier journal - + Config file Fichier de configuration - + General options Options générales - + This is the command line monero wallet. It needs to connect to a monero daemon to work correctly. Ceci est le portefeuille monero en ligne de commande. Il a besoin de se connecter à un démon monero pour fonctionner correctement. - + Can't find config file Impossible de trouver le fichier de configuration - + Logging to: - Journalisation dans : + Journalisation dans : - + Logging to %s Journalisation dans %s - + Usage: - Usage : + Usage : From cbdd6b910b3140f8ef317bd02ad1398bccff3bf0 Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Sat, 6 Oct 2018 13:57:23 +0200 Subject: [PATCH 0058/1007] Linux: Fix building of static binaries with hw device support This should enable building static binaries on Linux systems where dependencies are already built with -fPIC, such as Ubuntu 18.04. --- cmake/FindHIDAPI.cmake | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cmake/FindHIDAPI.cmake b/cmake/FindHIDAPI.cmake index a689fb4eb..9b45dcc4c 100644 --- a/cmake/FindHIDAPI.cmake +++ b/cmake/FindHIDAPI.cmake @@ -39,6 +39,20 @@ find_package_handle_standard_args(HIDAPI if(HIDAPI_FOUND) set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}") + if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux")) + find_library(LIBUSB-1.0_LIBRARY usb-1.0) + find_library(LIBUDEV_LIBRARY udev) + if(LIBUSB-1.0_LIBRARY) + set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUSB-1.0_LIBRARY}") + if(LIBUDEV_LIBRARY) + set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUDEV_LIBRARY}") + else() + message(WARNING "libudev library not found, binaries may fail to link.") + endif() + else() + message(WARNING "libusb-1.0 library not found, binaries may fail to link.") + endif() + endif() set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}") endif() From 0656050f76c8aa9cd8845b0ddcc1df3f3fa378c0 Mon Sep 17 00:00:00 2001 From: Lafudoci Date: Sun, 7 Oct 2018 09:52:10 +0800 Subject: [PATCH 0059/1007] README: update MSYS2 dependencies for Ledger --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d16b21528..bce41f5cf 100644 --- a/README.md +++ b/README.md @@ -317,11 +317,11 @@ application. To build for 64-bit Windows: - pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium + pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi To build for 32-bit Windows: - pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium + pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi * Open the MingW shell via `MinGW-w64-Win64 Shell` shortcut on 64-bit Windows or `MinGW-w64-Win64 Shell` shortcut on 32-bit Windows. Note that if you are From 9907ea0694ecf025258fd1b28e3dcc8c2c1b54d0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 3 Aug 2018 10:21:08 +0000 Subject: [PATCH 0060/1007] cryptonote: sort tx_extra fields This removes some small amount of fingerprinting entropy. There is no consensus rule to require this since this field is technically free form, and a transaction is free to have custom data in it. --- src/cryptonote_basic/cryptonote_basic.h | 1 - .../cryptonote_format_utils.cpp | 85 +++++++++++++++++++ .../cryptonote_format_utils.h | 2 + src/cryptonote_core/cryptonote_tx_utils.cpp | 6 ++ tests/unit_tests/test_tx_utils.cpp | 84 ++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index d4558ef7b..b0eabb0aa 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -47,7 +47,6 @@ #include "crypto/crypto.h" #include "crypto/hash.h" #include "misc_language.h" -#include "tx_extra.h" #include "ringct/rctTypes.h" #include "device/device.hpp" diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 428be1c9c..0231a032e 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -376,6 +376,91 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + template + static bool pick(binary_archive &ar, std::vector &fields, uint8_t tag) + { + std::vector::iterator it; + while ((it = std::find_if(fields.begin(), fields.end(), [](const tx_extra_field &f) { return f.type() == typeid(T); })) != fields.end()) + { + bool r = ::do_serialize(ar, tag); + CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field"); + r = ::do_serialize(ar, boost::get(*it)); + CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra field"); + fields.erase(it); + } + return true; + } + //--------------------------------------------------------------- + bool sort_tx_extra(const std::vector& tx_extra, std::vector &sorted_tx_extra, bool allow_partial) + { + std::vector tx_extra_fields; + + if(tx_extra.empty()) + { + sorted_tx_extra.clear(); + return true; + } + + std::string extra_str(reinterpret_cast(tx_extra.data()), tx_extra.size()); + std::istringstream iss(extra_str); + binary_archive ar(iss); + + bool eof = false; + size_t processed = 0; + while (!eof) + { + tx_extra_field field; + bool r = ::do_serialize(ar, field); + if (!r) + { + MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); + if (!allow_partial) + return false; + break; + } + tx_extra_fields.push_back(field); + processed = iss.tellg(); + + std::ios_base::iostate state = iss.rdstate(); + eof = (EOF == iss.peek()); + iss.clear(state); + } + if (!::serialization::check_stream_state(ar)) + { + MWARNING("failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); + if (!allow_partial) + return false; + } + MTRACE("Sorted " << processed << "/" << tx_extra.size()); + + std::ostringstream oss; + binary_archive nar(oss); + + // sort by: + if (!pick(nar, tx_extra_fields, TX_EXTRA_TAG_PUBKEY)) return false; + if (!pick(nar, tx_extra_fields, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS)) return false; + if (!pick(nar, tx_extra_fields, TX_EXTRA_NONCE)) return false; + if (!pick(nar, tx_extra_fields, TX_EXTRA_MERGE_MINING_TAG)) return false; + if (!pick(nar, tx_extra_fields, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG)) return false; + if (!pick(nar, tx_extra_fields, TX_EXTRA_TAG_PADDING)) return false; + + // if not empty, someone added a new type and did not add a case above + if (!tx_extra_fields.empty()) + { + MERROR("tx_extra_fields not empty after sorting, someone forgot to add a case above"); + return false; + } + + std::string oss_str = oss.str(); + if (allow_partial && processed < tx_extra.size()) + { + MDEBUG("Appending unparsed data"); + oss_str += std::string((const char*)tx_extra.data() + processed, tx_extra.size() - processed); + } + sorted_tx_extra = std::vector(oss_str.begin(), oss_str.end()); + return true; + } + //--------------------------------------------------------------- crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra, size_t pk_index) { std::vector tx_extra_fields; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 8a5296d5b..b40db4668 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -31,6 +31,7 @@ #pragma once #include "blobdatatype.h" #include "cryptonote_basic_impl.h" +#include "tx_extra.h" #include "account.h" #include "subaddress_index.h" #include "include_base_utils.h" @@ -64,6 +65,7 @@ namespace cryptonote } bool parse_tx_extra(const std::vector& tx_extra, std::vector& tx_extra_fields); + bool sort_tx_extra(const std::vector& tx_extra, std::vector &sorted_tx_extra, bool allow_partial = false); crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra, size_t pk_index = 0); crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0); crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index = 0); diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 071ce591e..1e5a7fb23 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -38,6 +38,7 @@ using namespace epee; #include "cryptonote_tx_utils.h" #include "cryptonote_config.h" #include "cryptonote_basic/miner.h" +#include "cryptonote_basic/tx_extra.h" #include "crypto/crypto.h" #include "crypto/hash.h" #include "ringct/rctSigs.h" @@ -84,6 +85,8 @@ namespace cryptonote if(!extra_nonce.empty()) if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) return false; + if (!sort_tx_extra(tx.extra, tx.extra)) + return false; txin_gen in; in.height = height; @@ -434,6 +437,9 @@ namespace cryptonote add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys); } + if (!sort_tx_extra(tx.extra, tx.extra)) + return false; + //check money if(summary_outs_money > summary_inputs_money ) { diff --git a/tests/unit_tests/test_tx_utils.cpp b/tests/unit_tests/test_tx_utils.cpp index 8a9f983e6..55c76c3b6 100644 --- a/tests/unit_tests/test_tx_utils.cpp +++ b/tests/unit_tests/test_tx_utils.cpp @@ -33,6 +33,8 @@ #include #include "common/util.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/tx_extra.h" #include "cryptonote_core/cryptonote_tx_utils.h" namespace @@ -203,3 +205,85 @@ TEST(validate_parse_amount_case, validate_parse_amount) r = cryptonote::parse_amount(res, "1 00.00 00"); ASSERT_FALSE(r); } + +TEST(sort_tx_extra, empty) +{ + std::vector extra, sorted; + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted)); + ASSERT_EQ(extra, sorted); +} + +TEST(sort_tx_extra, pubkey) +{ + std::vector sorted; + const uint8_t extra_arr[] = {1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted)); + ASSERT_EQ(extra, sorted); +} + +TEST(sort_tx_extra, two_pubkeys) +{ + std::vector sorted; + const uint8_t extra_arr[] = {1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230, + 1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted)); + ASSERT_EQ(extra, sorted); +} + +TEST(sort_tx_extra, keep_order) +{ + std::vector sorted; + const uint8_t extra_arr[] = {1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230, + 2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted)); + ASSERT_EQ(extra, sorted); +} + +TEST(sort_tx_extra, switch_order) +{ + std::vector sorted; + const uint8_t extra_arr[] = {2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230}; + const uint8_t expected_arr[] = {1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, + 80, 63, 198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230, + 2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted)); + std::vector expected(&expected_arr[0], &expected_arr[0] + sizeof(expected_arr)); + ASSERT_EQ(expected, sorted); +} + +TEST(sort_tx_extra, invalid) +{ + std::vector sorted; + const uint8_t extra_arr[] = {1}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_FALSE(cryptonote::sort_tx_extra(extra, sorted)); +} + +TEST(sort_tx_extra, invalid_suffix_strict) +{ + std::vector sorted; + const uint8_t extra_arr[] = {2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_FALSE(cryptonote::sort_tx_extra(extra, sorted)); +} + +TEST(sort_tx_extra, invalid_suffix_partial) +{ + std::vector sorted; + const uint8_t extra_arr[] = {2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + const uint8_t expected_arr[] = {2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + std::vector extra(&extra_arr[0], &extra_arr[0] + sizeof(extra_arr)); + ASSERT_TRUE(cryptonote::sort_tx_extra(extra, sorted, true)); + std::vector expected(&expected_arr[0], &expected_arr[0] + sizeof(expected_arr)); + ASSERT_EQ(sorted, expected); +} From 21a624af23b0322d69f07d066dfa6e493afffd4f Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Sun, 7 Oct 2018 19:16:22 +0200 Subject: [PATCH 0061/1007] Consolidate HID depends makefiles into single recipe Make sure all required dependencies are linked statically, by only providing the static libraries. --- contrib/depends/packages/eudev.mk | 2 +- contrib/depends/packages/hidapi-darwin.mk | 23 ------------------- contrib/depends/packages/hidapi-linux.mk | 28 ----------------------- contrib/depends/packages/hidapi.mk | 8 ++++++- contrib/depends/packages/packages.mk | 7 +++--- contrib/depends/packages/sodium-darwin.mk | 2 +- contrib/depends/packages/sodium.mk | 2 +- contrib/depends/toolchain.cmake.in | 3 +++ 8 files changed, 16 insertions(+), 59 deletions(-) delete mode 100644 contrib/depends/packages/hidapi-darwin.mk delete mode 100644 contrib/depends/packages/hidapi-linux.mk diff --git a/contrib/depends/packages/eudev.mk b/contrib/depends/packages/eudev.mk index 08752909f..e754c0f20 100644 --- a/contrib/depends/packages/eudev.mk +++ b/contrib/depends/packages/eudev.mk @@ -5,7 +5,7 @@ $(package)_file_name=$($(package)_version).tar.gz $(package)_sha256_hash=a96ecb8637667897b8bd4dee4c22c7c5f08b327be45186e912ce6bc768385852 define $(package)_set_vars - $(package)_config_opts=--disable-gudev --disable-introspection --disable-hwdb --disable-manpages + $(package)_config_opts=--disable-gudev --disable-introspection --disable-hwdb --disable-manpages --disable-shared endef define $(package)_config_cmds diff --git a/contrib/depends/packages/hidapi-darwin.mk b/contrib/depends/packages/hidapi-darwin.mk deleted file mode 100644 index 014aba578..000000000 --- a/contrib/depends/packages/hidapi-darwin.mk +++ /dev/null @@ -1,23 +0,0 @@ -package=hidapi-darwin -$(package)_version=0.8.0-rc1 -$(package)_download_path=https://github.com/signal11/hidapi/archive -$(package)_file_name=hidapi-$($(package)_version).tar.gz -$(package)_sha256_hash=3c147200bf48a04c1e927cd81589c5ddceff61e6dac137a605f6ac9793f4af61 - -define $(package)_set_vars -$(package)_config_opts=--enable-static -$(package)_config_opts+=--prefix=$(host_prefix) -endef - -define $(package)_config_cmds - ./bootstrap &&\ - $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" CC="$(host_prefix)/native/bin/$($(package)_cc)" -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/contrib/depends/packages/hidapi-linux.mk b/contrib/depends/packages/hidapi-linux.mk deleted file mode 100644 index b2a499915..000000000 --- a/contrib/depends/packages/hidapi-linux.mk +++ /dev/null @@ -1,28 +0,0 @@ -package=hidapi-linux -$(package)_version=0.8.0-rc1 -$(package)_download_path=https://github.com/signal11/hidapi/archive -$(package)_file_name=hidapi-$($(package)_version).tar.gz -$(package)_sha256_hash=3c147200bf48a04c1e927cd81589c5ddceff61e6dac137a605f6ac9793f4af61 -$(package)_dependencies=libusb eudev - -define $(package)_set_vars -$(package)_config_opts=--enable-static -$(package)_config_opts+=--prefix=$(host_prefix) -$(package)_config_opts+=libudev_LIBS="-L$(host_prefix)/lib -ludev" -$(package)_config_opts+=libudev_CFLAGS=-I$(host_prefix)/include -$(package)_config_opts+=libusb_LIBS="-L$(host_prefix)/lib -lusb-1.0" -$(package)_config_opts+=libusb_CFLAGS=-I$(host_prefix)/include/libusb-1.0 -endef - -define $(package)_config_cmds - ./bootstrap &&\ - $($(package)_autoconf) $($(package)_config_opts) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/contrib/depends/packages/hidapi.mk b/contrib/depends/packages/hidapi.mk index b6b228643..d4dd80e22 100644 --- a/contrib/depends/packages/hidapi.mk +++ b/contrib/depends/packages/hidapi.mk @@ -3,10 +3,16 @@ $(package)_version=0.8.0-rc1 $(package)_download_path=https://github.com/signal11/hidapi/archive $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=3c147200bf48a04c1e927cd81589c5ddceff61e6dac137a605f6ac9793f4af61 +$(package)_linux_dependencies=libusb eudev define $(package)_set_vars -$(package)_config_opts=--enable-static +$(package)_config_opts=--enable-static --disable-shared $(package)_config_opts+=--prefix=$(host_prefix) +$(package)_config_opts_darwin+=RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" CC="$(host_prefix)/native/bin/$($(package)_cc)" +$(package)_config_opts_linux+=libudev_LIBS="-L$(host_prefix)/lib -ludev" +$(package)_config_opts_linux+=libudev_CFLAGS=-I$(host_prefix)/include +$(package)_config_opts_linux+=libusb_LIBS="-L$(host_prefix)/lib -lusb-1.0" +$(package)_config_opts_linux+=libusb_CFLAGS=-I$(host_prefix)/include/libusb-1.0 endef define $(package)_config_cmds diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index 9bfbff7d9..f814c14d6 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -1,12 +1,12 @@ -packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt +packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt hidapi native_packages := native_ccache wallet_packages=bdb darwin_native_packages = native_biplist native_ds_store native_mac_alias -darwin_packages = sodium-darwin hidapi-darwin +darwin_packages = sodium-darwin -linux_packages = eudev libusb hidapi-linux +linux_packages = eudev libusb ifeq ($(host_os),linux) packages += unwind @@ -15,7 +15,6 @@ endif ifeq ($(host_os),mingw32) packages += icu4c packages += sodium -packages += hidapi endif ifneq ($(build_os),darwin) diff --git a/contrib/depends/packages/sodium-darwin.mk b/contrib/depends/packages/sodium-darwin.mk index 59c6d1ec6..d8e3de352 100644 --- a/contrib/depends/packages/sodium-darwin.mk +++ b/contrib/depends/packages/sodium-darwin.mk @@ -6,7 +6,7 @@ $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe define $(package)_set_vars $(package)_build_opts_darwin=OS=Darwin LIBTOOL="$($(package)_libtool)" -$(package)_config_opts=--enable-static +$(package)_config_opts=--enable-static --disable-shared $(package)_config_opts+=--prefix=$(host_prefix) endef diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk index 0e6668062..c38121bf7 100644 --- a/contrib/depends/packages/sodium.mk +++ b/contrib/depends/packages/sodium.mk @@ -5,7 +5,7 @@ $(package)_file_name=libsodium-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 define $(package)_set_vars -$(package)_config_opts=--enable-static +$(package)_config_opts=--enable-static --disable-shared $(package)_config_opts+=--prefix=$(host_prefix) endef diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index bde7497b3..f8548a724 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -18,6 +18,9 @@ SET(LIBUNWIND_INCLUDE_DIR @prefix@/include) SET(LIBUNWIND_LIBRARIES @prefix@/lib/libunwind.a) SET(LIBUNWIND_LIBRARY_DIRS @prefix@/lib) +SET(LIBUSB-1.0_LIBRARY @prefix@/lib/libusb-1.0.a) +SET(LIBUDEV_LIBRARY @prefix@/lib/libudev.a) + SET(ZMQ_INCLUDE_PATH @prefix@/include) SET(ZMQ_LIB @prefix@/lib/libzmq.a) From f9485a36cf4515dfa5bb4148260a818c1184723e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 7 Oct 2018 17:43:03 +0000 Subject: [PATCH 0062/1007] tests: update crypto tests data file after PRNG changes --- tests/crypto/tests.txt | 1124 ++++++++++++++++++++-------------------- 1 file changed, 562 insertions(+), 562 deletions(-) diff --git a/tests/crypto/tests.txt b/tests/crypto/tests.txt index 0ae6a05b7..46f815e72 100644 --- a/tests/crypto/tests.txt +++ b/tests/crypto/tests.txt @@ -346,6 +346,7 @@ random_scalar 347065b13ad735ff9e1cd8b471aca4f97d7690b326173fecbbd78528a6d8990e random_scalar a843cbb2a416c655669cbf1a5f452beddba17c8f5c17711c9af6d2580b4b890a random_scalar 93dba1d862d13f16c84fb050117483e48d5821979a4bf468901cf954f6b86d0c random_scalar 307e5c1c1643cba6aec9b1f7c67fde082ff1686c6a53376b2b4a8a84af2c3f0f +random_scalar f02178e283466b8e7747fff209c242dc90b0a4df7f1bb98acb81c6d2332d8806 random_scalar b92d6b60e266e5ffddd530548d77dfb7a3b251748acd16f6ffefab5ecdf2f902 random_scalar 9e6d32f8ac881f5821a146969b33b89dd16e4dfcaa1dcae522aa080021caee0f random_scalar 17072c56bfe20546f15c8bd14e91c861d7795bedd3bedf9120233c4e289c7906 @@ -382,6 +383,7 @@ random_scalar 63b1db6f0a4f98a26e783eb8fb73fb16ea0da816e47eb9231dd00a60e7517c03 random_scalar ffe2b3d84d08d7bcc36695a1d57c5c0d835d8e76fcc9b961e017ed111ee4850f random_scalar f881be752da6bdb31e29f1228760870668550fb793a091fc67d580d236a5c108 random_scalar 013171a3c5ed17b2701874a1f15ec2ef281ec5f5304a497696c611755e39170e +random_scalar 5948ec05726a52adda2ca05c00e9767397ea64fd51dd94ae3bf62772e033d106 random_scalar 69ca89c140209055502cadbb190b818c5305a297786a198c647061e7a7dd5f0e random_scalar 56d497bf314bf6d27cbeed9c7834ec67836b6f9f007e1992164c106b705e8408 random_scalar f0d3539042a82a700d7b8797ef0d7658f5b1b4b8e9689b0c34dd9f2a4262ea0a @@ -406,6 +408,8 @@ random_scalar 0a560a580866b38724402d5d912b827f1fb2964af948dbe0496afa145793bd0d random_scalar bafb7d180deec27520223d6fba4b9abfcff9c141c1fed61a595b788dc6645b01 random_scalar 929e298412d697287b61cdcb0d0afa266ff954aed449e15f49f6f55121e99006 random_scalar 29b159c4069d33395f3eedb93dd4122f9287dc1f55114250b3dc8061bb09970c +random_scalar 2cc4a07721223b3c7764b571e229adb3b6db1452d4b7a2337218e40d34949d03 +random_scalar 7a0e422abc8a0410cc5a98231bb3a987c1d1b669094ab76bc9d618a9789bd300 random_scalar ef5b9b18e232056b91a0b73da1fa364e7192b9276df3c428d5e3556b4fe9f402 random_scalar 7d58f02afa1c64da5e2e05e7b703c53553e914e66c25a5dfb88063c05bcb7500 random_scalar a7c8d18c3f879578f1bf331323358e7c7feecdb58b508444a6466504b6ead009 @@ -413,7 +417,9 @@ random_scalar 0ae41c5656bb3d3a899df86a4b93db9eb7776fe76430025e759387d4df5e320a random_scalar 43ed981404a1cf024c24484477941a7a92285723c0f47d6d57f4e1c66a28ce06 random_scalar 939019df6ff9b3e37034a70527468f51a91099b29917772b12e475cec11eab07 random_scalar cbcb6c3f15934e47741922a5593ae52e4bac95553f3a409742463a1350641800 +random_scalar 1e462b2dcf2617965ce4fac23a5ac97fb37168f9f32fa37583c2c2b63ca5a30b random_scalar 4ea2293558b34a5276e2ce4155f56073a3c6ec68d61695b62ae1459d7996020c +random_scalar c5f696c5c3f721cfe767f7121b2740f7fe450d53aa1eeb590a465ec25a9db700 random_scalar 1477be630f529286ba32d34e15bb95e910146b61cb7b9758964233d17add960f random_scalar 05595b226f810185b71c4bf9b93700f060dd40ea5a4dadfae05906688ff0820c random_scalar 8d4b632a555e02e8537afa2084f545e74fb75cf2955129316c4f2540b667c009 @@ -424,9 +430,11 @@ random_scalar 9d79792bf4708c06fa59f14af6141658a4b778a738ca2bcd1088f45df23f3e0d random_scalar a056651374d7df2ed89c3e37ef9072063281aecd4ff95e48767da04c1fd71206 random_scalar 005253f190dd9d70b900859b3057ef8f5cb01a99af2874b3abcb3a629d51a805 random_scalar 9376111937238f6c53309773217cc89364f8697ea5f3d05ae47adb9174cef201 +random_scalar 9d118c28ab31cfbdc323ac2015a6d5b9b1da84363833d7543a34d617d02b810e random_scalar 1cb13c17e9005e6b38f21ae7013ae9507ade4590b24e5f2b54f842c62993040d random_scalar c2bd6ec6c68431943f0b4d24b97aa83a4f6b465fb5dd9d9c1f73c26286c3500c random_scalar 699eef9c8339ed18ae8129866549a7b6145cd05ea46c7e072491acf0dabc1206 +random_scalar a08326104d8ff1a0ee83b7996c5904a47175c0b7ff206e13cf24d09ec07eef06 random_scalar 4eab216fcf6a99336807269418930e2c02544c3029a281b0ade0b34b71ac6c04 random_scalar cee08c6dc0cee0f301a27733019fcb15888af5c0674d87867ca6629f13622f03 random_scalar 4eb667a0a18c1e79586a74ec59a13331eba48da3f45d83617ac817955e25b00c @@ -448,6 +456,7 @@ random_scalar 5b515323f0a7d7ebafd8d628ef4f32925a6225ea92ec1410bc47d87c33044d06 random_scalar 9816f6ccd6703afcc53026ae742dba2881cdd9fe4e60f16c46f3eed92dde1906 random_scalar c6cf65615f4eeb1b7c883663a3ead84a3e631dae7a2e5c12bb33e0f340e8ac0a random_scalar d915348a86948774d7ea9ecb5dd9dc7ef822d7ef31446e9f0a05a7009ffcdf04 +random_scalar 29104e7b6320b15a4098472bd959836d808d92d85a9e3e2fb89eedc84557d305 random_scalar f9918366b633b8fbe442783869f88e5a231fac34fc9a34782d2cd09b6254e60f random_scalar a443ed5b8e5d178184c940534da5d6139bb2e0dce6a6ecde3f9fc040cea0640c random_scalar aa2bdf5311d205af876f8f0d65a603097a618f58fa9b436fad0856d768fc6b03 @@ -457,6 +466,7 @@ random_scalar 86b64d3333d929a312b847a99956a6e343518f7eed681b21cc81e7e9b690d600 random_scalar 6cf210cbba801072afa883a4db5dea1121b5a0fab727a046f6d08d1b76addb0f random_scalar 1244e035744c4ebb6388543e6938850afd96a7e2b08035a03943d54eb4883206 random_scalar 0254b1c7310f6597914ae0a40ae832ba1c7796011e93df17ba760420ca0a2d0d +random_scalar 91feed7f2c484292d469cd86204f91a42135ab5cdf4d1cb8603334471869a500 random_scalar 7fa680a145f0220c50f677b75d4e39280f74da8e583c7e66518ba12a2862fe0b random_scalar d5e6ae512163e2a522bc94a163e03b1e558e287496c8132cacdb4350513fa50c random_scalar d7a99dfbed9dcd878c9d42d2c205e23fb9bf0b0036be1a60cf023f6a5b9d6909 @@ -484,9 +494,11 @@ random_scalar cce38a425d652f4f0ac8e5ebd99eb05a111b51602e0f4527533325b015e70a05 random_scalar 3798a47b4cdb21595d3fb5cf314347284771427f90dadaef72016f1904681206 random_scalar 789fac4d4d7c47b88f8ca9a3cccc633aabadd8ff51337236b5d3c79cd8912c0a random_scalar b9ea6cb523026f955cb221bb6cc0ad69dc4124b788045a024c941cc447b15401 +random_scalar 0c79a5ce56ce0f3781420721d39961a4121eb5b3021a26d8a8ce7b918e194804 random_scalar a5cbf16377db957b2fb6eb28d188ebdf0823bb93c7341c904959952d16d7da0a random_scalar 1d72637b2f247a0e22fe6cbf180a1ed2a4997697b798d793794b073ab11efe0e random_scalar 6262411ffff10f36232a43afef4ae397b5c65d90fd4bd1ebc0ea177c37f7cf0b +random_scalar 07401995e944c75398aa7ae889d4f98a25620b066bf44088ed271d53a1287702 random_scalar 4b43cc16ecb7dae45cdf9b09e79538bc96371dbd08253a1605d44d525732de0b random_scalar a7e65b1eac2b19da0c5c91717a5487d1f9871b869010790d73fc3553c0953302 random_scalar 2042fa43e1deacd9e831f479d4d2ccc166aae9d0b14445adcc9e9604509f140e @@ -512,6 +524,7 @@ random_scalar bbe7ceee833f824b63fa02b6a49a3a96527fabe6d97b3edff98555498b991b04 random_scalar a319115555a4114e4d68d0427c7e80cce22f3ec01b988949be420b2ca446a40f random_scalar 6e61bcaeb19eac83173799404df79cbf3dd1d6a811b6ac6f1a6b9548a5b12500 random_scalar 13aba81a8841745c078302b4464e26df22cfc420b0c7592a917564df71abd00e +random_scalar 1b9f988c823a596c9bdfe1dccb709b83004ba6bd7abf59a13857cc3f73f99d09 random_scalar b17a5eefdbdd01be4c7ee398f0cac2d71863f8a76c1937f2bc206947ff941c0e random_scalar e9f4aed4bebb6a0696eaa9e325ca919a80730bcf23e5f4e711558a59c819dd07 random_scalar 9b39c9258a4af69da0a90b5afbf007eb8223448b2d24092100f61351302acd08 @@ -533,17 +546,20 @@ random_scalar 226d1f82fb68da5da182a8ec88a4f317cc51c280fd50d2048c7f5991edf03a01 random_scalar 42aaf88cf69e4558541ea582afffd26d90652d062dda640a14412d751ef37e0c random_scalar c87a1f9b1aa80f71d1c78d57c21fe47d7f56aa2d4f397f72fb2af8ef2a401b04 random_scalar 23344bcfa22e85cbd315f370075e3af849f361f7a2e960626564855071b1f004 +random_scalar 288a3ac4adc51aa9a09a55e76e66979447bb5c7f7a23de539bf4021636dc9006 random_scalar a1dfa3cc72b59b1e4bd70e25b10107f1a0e4270f09a07122845379cf56dac104 random_scalar 46b1f9a4a2d23ef6f65190d0d763d0484d5a43e075840ba522586e956b824906 random_scalar 0df69f6758ce363fe6090e9ea60b8e4e62506cb032a16c4d4cff29e8ceb7a10c random_scalar 41322acad808cc6b332d7ce9ac45b3ec216596186e4d2e1524414b1e56174f0c random_scalar 555b681ba25e17cf7a493db2360887ec410df0d1531a21fdb3a70080313c170d +random_scalar 6195bd5aec348dddf3b5a3e80538c1908d4f4fd5da6282a5d68458fc6d08bd05 random_scalar 493d080d01bcf337fa7e81cb9467ee528e245413fb3d100323dbda0c1429310e random_scalar 0d6bd8be3a66d83039fe5abb78c2258bbd028ca211416f3c011a49f358ae0e0e random_scalar 3a872ce933eaaf2f9c845fa8c73651300f5bcfcd59b6faaef12a2f368cd1c30f random_scalar e63184fb512ed19db445caeae0adfee4e373ba93116c661bc60dae380133a104 random_scalar efab70caabf4a2a5a67f12ea27171df5ec4e3394c8f3b352effb47a558c35604 random_scalar 7de9e6ee6a1ba4019077114e83e29078f89ebbebe688248ca3acc3c8539eb80f +random_scalar 410deab0d9c6c4f4f2764ef001280c1d427655d9d814806e2d88f12cad8d2c07 random_scalar 64825ec5a071749732ce7354e234a0293828de98a98c3a563662e509b7072a05 random_scalar dba5ec762e38f676ca8a85876c0bb3c11ab57838893793ff81a47c767261380a random_scalar 22f506889b19f0f699dcce8e3d9bdbe16d91a6105a26e8b3f95e8cb17be20001 @@ -560,11 +576,13 @@ random_scalar f352cd628d86bd73fa5f3c947b9f838d00966bd2915d988ed8bd2067cf8c840e random_scalar c5ab4129d42396221bbb4274a20b231f7507cb0b65911f765a943751800fb90a random_scalar dc8c5d0e642ee21c437fff0f77a08b9a4795c467f3c50354083148b796fbfe08 random_scalar 329b4c0b05d1ce5621612491328cac7f1509001fb5f373a66e8e52090b91fa0d +random_scalar 3514f1428d2cbbcc00c44d43626bdfd8071aab4fccd719da2bcdfcd10339e707 random_scalar 152e4e3f2801194a38b7213fcd2e53859ed22d3e176700921b044db74acaa903 random_scalar 17cd1a31b9b315713c2a6e8295419645918bf8ffa1670441d4dcbac6fcda9c00 random_scalar a8e83c4ddf185d7b048ca69a96753bd055071f43ba4bbd1ce9527b172a796e0c random_scalar ac881d61a4fc26880ff82fe4fce254c5db672b6500ce05658104a39c9792d30d random_scalar 44bd5a9744c3ca92f9429e31a26c1e8206fa88d6b0109767df3dd6b5e081d701 +random_scalar 245923963a0928b1ce93b0282d7e9c5c675edae28cb86c9de2c988f634427603 random_scalar df585700d24b16794d4e931a26fd3ebd666604cf0be40acc032e9e704153f905 random_scalar 444ec7f3eba365d9e5fa91b4fd19df66b4f982ebb76d6a18a2c6f220ede2b001 random_scalar 3f2569c0d441efbb3a15aa01ec773eb67d52bf2563fcb6828497c24d0b64c60e @@ -573,24 +591,6 @@ random_scalar 8dcd442061dcd332fe0ac86c5f97d00cc59c8029f18acc3b5e9de5e8fb910401 random_scalar 40a6e2b2469b93dcd95aec551033180583f1509c3dbc484b54ca2e5a3fd8a702 random_scalar 6d87007ff22b03e9b11a97ef2b7d16171d2f6e3b79970f261e1d3236a179d307 random_scalar e4de14222ccd095e68bef9a3405b778dcdfe6ef5aa178142cfd2819d623ba60f -random_scalar 42bf10f06625682a429c62ee0856ae168d4214aa254732ecfe67fc73cd2be606 -random_scalar bfb5ff7e7b27b0d32d822ea3abce41d30078b9de1e9dba88944ce558d3991c00 -random_scalar 1ce399ce3590215c271c7872d0e7b3b958e108d40b1319ff31a42d5b83ade90d -random_scalar c50084e02284eddb75cf7f0655b63eef571177042bc9e5dc29df3ed4f54b0408 -random_scalar 578d31434a982bb5ec6ce9a931199c7a42176f04264a35ad71847fe06781d80c -random_scalar ca3ae8837892a88874f8c675fd4ebfc59fca8d98e056093f25d88bb07908600e -random_scalar 259ea7deeacd6a38f0d9619cdab2774dbbb93b1d17cb32b3051fc5906c9b1e0d -random_scalar f59d75c0834df84b4aae8c73523388c4eb57c125fdfd0cdc52389751673d3902 -random_scalar 04b222b3c67335aad76448daa244472f40f6764d851cd047e3206d8ac32c0c07 -random_scalar 63ef886fcd7cc534d1e141d64f5af699633c6ce9eb6e4c104ef03300f150a901 -random_scalar e4fac60ab7fb0c2c2c32039cfba4760c6c22a5c2f3c437c50a43b198d817a601 -random_scalar 8b57cb35f1a0714a904896ce7e9a515d7083259f1d325355910c5ef6c79fd90c -random_scalar dc84b8cfce597f499ffbd52829f4dbfb3b110a3482b168c223bbe24cd5aa4800 -random_scalar 3d7d972adc1b1279f71a6eaa4deb8c05a73be74345c7e862ced54822be0f7309 -random_scalar b4129d530f956b59b0bfdfb2036f4ae189cc96c9086bdca921cd348bde327403 -random_scalar 14144a16940145ae1c8ffc09cf5cd15f640d774bb78b95b756de5d7f9af47606 -random_scalar c9e4e8fd6916595ec1b92fcefd2313df304b05856716c8c7ed6b5589f0f72c07 -random_scalar 7b12882ce5338bad3fb9245e65254a8140552f6c89e95a799daeb817d602e109 hash_to_scalar 59d28aeade98016722948bf596af0b7deb5dd641f1aa2a906bd4e1 7d0b25809fc4032a81dd5b0f721a2b21f7f68157c834374f580876f5d91f7409 hash_to_scalar 60d9a4b96951481ab458 b0955682b297dbcae4a5c1b6f21addb211d6180632b538472045b5d592c38109 hash_to_scalar 7d535b4896ddc350a5fdff 7bb1a59783be93ada537801f31ef52b0d2ea135a084c47cbad9a7c6b0d2c990f @@ -847,6 +847,25 @@ hash_to_scalar ea753ba82b4573d428d526de89daccdfa7a33079aa9c9ac3 d9bf5688fed9c3f4 hash_to_scalar 2a5d772c76aae0040915ffd7 8227a0904298e726cedb75746b0a3b41662002b4ed8fa05c2110e4a15bfd310c hash_to_scalar 585900d92342cb8448c944f97d1642 acfa0d43b9c6a91810b0fa1bd42f0d9e077f7f5a62f9d9aaff8418e1130ea508 hash_to_scalar 2ace 427f5090283713a2a8448285f2a22cc8cf5374845766b6370425e2319e40f50d +generate_keys 6f04c33790c0d5879c7973af36464038c3e79cb901e08275b06ab53840df8e8b 42bf10f06625682a429c62ee0856ae168d4214aa254732ecfe67fc73cd2be606 +generate_keys cac7e372a9332f9f485a5264ef94c9acff59e6b6e07cbde280db814f1e3ccf70 bfb5ff7e7b27b0d32d822ea3abce41d30078b9de1e9dba88944ce558d3991c00 +generate_keys 99cf2fc6491cc07af8091c523b5dc6b529890cbef1dfd88399ab144f12777a4d 1ce399ce3590215c271c7872d0e7b3b958e108d40b1319ff31a42d5b83ade90d +generate_keys 07bd418f13dfb48349e9020cfa7f7c681ae60b7bf3576e276a87d15fa3481bab c50084e02284eddb75cf7f0655b63eef571177042bc9e5dc29df3ed4f54b0408 +generate_keys 6959bea2e23e768ca118ca6bef61c16c3a0f3bc2c181aaa217af9269f475cc73 578d31434a982bb5ec6ce9a931199c7a42176f04264a35ad71847fe06781d80c +generate_keys 1b91041175dce27cbba3b57647cc627e752d3d6fa2c4947c906b5fe0aa954c65 ca3ae8837892a88874f8c675fd4ebfc59fca8d98e056093f25d88bb07908600e +generate_keys 99231689da7da67d1aa9a6ef95481dce47cf2c5f5f28e091c416679607167e29 259ea7deeacd6a38f0d9619cdab2774dbbb93b1d17cb32b3051fc5906c9b1e0d +generate_keys ca8a2f621cfc7aa3efcd7ddf55dce5352e757b38aca0869b050c0a27824e5c5e f59d75c0834df84b4aae8c73523388c4eb57c125fdfd0cdc52389751673d3902 +generate_keys 9aa4e062b9a48cc714439b4e47617a9d5fbc2c228aa82374c44b8f1ef75dc073 04b222b3c67335aad76448daa244472f40f6764d851cd047e3206d8ac32c0c07 +generate_keys 8f9e37e637eb0d03252c1529e9094523ce3d943bb7166b7bb33e0d3c528be075 63ef886fcd7cc534d1e141d64f5af699633c6ce9eb6e4c104ef03300f150a901 +generate_keys 7d04eae257ce0b0fd73b6f829aaaa6096c314556f10b5b2c9a6c14744a2caa74 e4fac60ab7fb0c2c2c32039cfba4760c6c22a5c2f3c437c50a43b198d817a601 +generate_keys 7db81818126806d012314d9c0977b6766e6bf8fed716b939d4a13c0d5ce0fff1 8b57cb35f1a0714a904896ce7e9a515d7083259f1d325355910c5ef6c79fd90c +generate_keys da2246c24d068cf260d6ed03049ea48861cd62f20aeb6d4104d3711594c91766 166f341e6174d70a5347642e13992828e70b155768a4f586e45de094729dd10b +generate_keys 64a247eef6087d86e1e9fa048a3c181fdb1728431f29ba738634bdc38f02a859 dc84b8cfce597f499ffbd52829f4dbfb3b110a3482b168c223bbe24cd5aa4800 +generate_keys f3251e2a54bdc6226db4f2982a0ad7e7d5f60171014f06d080e4664fef49d16f 3d7d972adc1b1279f71a6eaa4deb8c05a73be74345c7e862ced54822be0f7309 +generate_keys 3afa5bc3d1316591af2a0337df8ab5353cfc439851a547fc0d4dff53e0a1f0f7 b4129d530f956b59b0bfdfb2036f4ae189cc96c9086bdca921cd348bde327403 +generate_keys 8d857a5f44109593c7b859a168bf7d73cb3fe5dfdd75adab90abe6f6293a693e 14144a16940145ae1c8ffc09cf5cd15f640d774bb78b95b756de5d7f9af47606 +generate_keys a3a78058f2a52cdad57c4d07e35fc3e6137e225848df7b4162afba93474dd007 c9e4e8fd6916595ec1b92fcefd2313df304b05856716c8c7ed6b5589f0f72c07 +generate_keys cff0c7170a41395b0658ee42b76545c45360736b973ab2f31f6f227b9415df67 7b12882ce5338bad3fb9245e65254a8140552f6c89e95a799daeb817d602e109 generate_keys 14565db661b4d3c24df2607fa517e0176d15d1f6be4c469f8b1a6fee0fd46f73 6f407d2247d035a94dce1dc64077dee8767960630a94822c5ee44002c610e70e generate_keys c2b496447b7c5a05499760171e36eca65959c6bddd8f51d5f165ad8451274700 cdb7cd68d4213a845c5a6cf909c055a889c558b18839c21a891705b6bfbd5d05 generate_keys 31e48168da03e468e7794fbb3e1c026b53e2f62d9034e52ed7e1435ac8d7ef57 703f93f1f47b7491569f96367e1f18a321c849d7e083122caf903d28b3dc7904 @@ -866,8 +885,11 @@ generate_keys 87dda05d85a76f76814ab7c069875892dfafb68649e16a5706ba57a4eae30efb 7 generate_keys f78d0ba130522ee4b2e53c0ee547a4923fc2666dbb2567fef4cdcfc5c427deed ecd3d3bf8c5078362014aebfabddf2287f961a59e2c30404542c383a1f9dbf05 generate_keys b8626776e5277e182f432f9bb1735ecbed074bea3e842ffbe736c7fec5a9cc8a 0d74c9368c5342e4fd27d17b1048bc8b31bc45864699871fc54884a1da442604 generate_keys 9189676a8a29486b7b910cb5114c6fbfc2c3693fec52bb3fa07acbc8bada4aea 247061ef4faaffcbfc89fe16f4f4285177ac4a0adcd26b46e10ff87a1f6b5b01 +generate_keys 6e9fe8a457fe8e2c2013ac83ed542aae68ef16a4fe87ad23661bf15d0616aff4 d73518ee96870788fc9a1942508d21f9f24aff835c67f70a5b439d884120c60c generate_keys 1837653add3f972d755fc9f78274e7f77d6c4ca59fdf468ab58c34697971405c 686716d5aa4feda8ca873a53311ea48e2b4a378dce95ed72ce050f0545d93305 +generate_keys 593a60fd41c6a4d5be1316d08c7a491efab86a9bbb0588ecc58149029cfab207 24a25290ff10f81469ec2e362c1accf27ebb4f2b7c3671bf45588284f22ced0e generate_keys 78437f4e3619da94f50d541f3fdc24087fd4a9bea64101f4fa00c242234b43ec 4ee58dcaf14a4ace28c69e5ed88c67c69330a0d0b7a15337003dc44fc2f4db0c +generate_keys d6d531dd6a4fa9145fa37995c81122717ceb3b79563c2eea17ec12b544057a7b a64c8c8de2bf5a19f5559aca3087885411772ef0ffc0d8f4337142f82a36e405 generate_keys 6176bbd85b15f6d2cef74376d248250b482f4649553a01f9db323c222a41580b 5536ed1a93335a0dba2aed5315c7b51207f0b78994d2bc5d17d974e9e7904c01 generate_keys bca1355ca382dc99c1c3dc0cf412e8f2efbcc23e0cc110afc764dc4b5e36e9c2 9c8072a9583c9778cc7dd9e9d3ce1a2c22c18af5e87d14801279568a1acf0902 generate_keys c974c6be8d21d7760719f33b3f3d5c34dff1dc1551f96196978e82575dffe926 fbcf6d11000fab789e43e5c454f286dadb35fa652481e845516a157285b9790b @@ -905,6 +927,7 @@ generate_keys fc4c1d2c1e8ebe78b301cb545a0d2099466b5f5d6793e2fc9bea6b94b2952a38 6 generate_keys 84e8a4694e36749e1f95b169ab0c1873b81161ddc9bcf6f3db1df45a60973c88 da963600cb3925f146650425dde10cd0cedb8d5fb31b4125dbb780a151bd750c generate_keys 4c0255d6d504c882ba9c70bfa008fce37b64bf6c3f0e28766516a4420ae81e26 6657308e8186f157d0cf3a904204a5f45571bcf2ec9cd447918edd483b57fa0c generate_keys 73cff6accb2477274d9c7be7ef9acd6af4601c451273846dcdc18009e0ad2438 9c0f09a10b8a612e567d1b7535a9c01264550d36b08a0e3f23f540de4e94a607 +generate_keys 82cde0c1473dd7bb6c030d58760fb4d4ab78b22cf160817ddcf94ed454e2c9a1 9b8233db7e14c5dcc03d4195f7c596fab68caf5374aa9a79c879b337cf58c80d generate_keys 50a99c17fd6ec8c9a7e2adda758e472f3bf333ee38e8679fb650dc61823a8cb3 06def25052d92ded8abfb5797daba02b61eb3d30df2542e1147906f170fc8e00 generate_keys 7fb9833ef15b807d0a8ed849ac64ac3d57fd0622608e4726c9da0dc1427e1b9e 3526b4818e2efe4dacaa9cdbc6aaaa2f6f4ca8856e1f24565fa7cf20570f240f generate_keys 7003d681d1bdae4e9c0463f97f04d103e013546190453af9e55a1ed5dda89be0 d3f12639669bd1443c08b44afe51a31778ad669daad197713e74cc8b2ca6f80a @@ -943,10 +966,13 @@ generate_keys 39ba5391b0ff5320950406ce07d88e63eed0fc5e457566eafd735438aa0c4763 8 generate_keys 02171a639079d57ecdf6d744bf089d3c7465e69f57603a3935a58345918c3d3a 92fa05e212d1b7057eb90d65bd2ceeb0c7fbc038d391ce1137604d9ec908630b generate_keys 4760d333319da5f9b83d76aad3fd934bfe7066d8dadab26bc752775a5567628f 4cbfff9bdd253172badb89ac8a8430e0d1f8e6869f05a1a7dd73a1e4352a1708 generate_keys 7ce83069c7ecacf944dc818a3679bb8580f2fb0016150636e1a7b51848056e00 736495ac6065995dbf1c9574f477431b912d412e6d54d8bdd3e9becd826a0e0d +generate_keys aa9fed9d7c5d2ae29e411b14a050b01ee12ee971d351f5ab96cd77f95eb78739 40db3b6b043a9e7f1ea8b02137998332b7038fd500682f552c818f3d36d8a708 generate_keys 729f7bb3f7d4e9d626929655fc0616e53abdd9d8131137c2582473b749e1e0c6 125d58bfed4f4b39cf9ffe3827e837babcaef948409cb9b499deed35bfab8a00 +generate_keys 013064368a149fb0108f10a0304cb0b40ac31bfffb7d58153e54f9aa2bc515d1 02ddbcaaa5cccb808212ef624d5a296d6b1475b737a542577e66323053f8f80a generate_keys c8d4adb5355a141bb00600579fa12523397ea283cda27dff8800d34285612859 b4cadf8f6607c0c467dd7795008fbf4311658b3fbcb2b3c26d970d454174df06 generate_keys 078c902693d54e9c6fbc14aacfa9f324415402f4533fb07345b698755dd3b8e4 248f95d8f173aadc378c161f70d324efdd3439907acbedecedc5d025e2d91e09 generate_keys b0ea07474c878e538f7cfe261099db55cba704bcbc5a0fa59ec3a2eba068bf04 a8d7990e8189631f82692180369e2893bc02a9a4dbf15fbaf616636db068c80a +generate_keys 6359cbdb328f49ee109d4dcbd19a8caae0b8949436e2ef06db1289e61fad66d0 4c77970ef160b05f7d93f021317bebe82d3c184f81cbe90bc6fc7cd27a08e50e generate_keys b56953cd97fab52e8a7b5715776f26a25722dc05d474801f5f51bb309d7729b2 b8db3b576fc280c644de282d1afe3dff6a1c792064bd95ed6b65678dc0877d06 generate_keys e0e791293fcefc5c6276347bf8cc3231a52119e66f36f2e4d750158a1f4ce7c8 d3a5f8cab604960fca614fa407a0b3d15354bb9770939d399acb96353365ac08 generate_keys 0d5774f9fb3346f4719d4c3b38760d1f3f700e3d74cac45f96d8b5cfcf014c13 74c691b430c940b73e655dac205f21da6d386c62daf0b1886343935205aecc06 @@ -960,6 +986,7 @@ generate_keys 0c52370043fa3a4d3f40e0f95f9b7ad0da5f5ad4104f49736847e6971b09082f a generate_keys ec87c62cd426718595d1ebbc43370b0409121e8c9d0ba5ceda8119a505c3ffe6 0993d873d5e694427bad3108b48a9182f111301a7daa8af2860588fbf4e6a802 generate_keys 1dd166362a3bde3c56b961ed3fa7694db8325f81414893c903e435a2a44bfa4e fe83a5b475519f6d0ec35fde10e70f753b76e1070a7538196e7ebd6a4d5d0506 generate_keys 0d6bfbe8e454c19a693312f55a87dd720a94e0bc00f09aad6292ebd6b5ee371b 286313c582243c4cf636c02a8cda434ebd86eb3eb8d532ddbdcd498a6850ff07 +generate_keys 411e029fca2f856f1c631de7f69e18cf197f526c160dce37c050f7951006176a 76306894fea0e7140fac32464cba705d022237ae920a3f53804d1582db98410c generate_keys ad6d7326d9cdc0337b953f00151c6d4533c026fa0a6eaef57f4065b6beb3eb11 38d2f407ffa6c9c158f6f8342aabe612cab54e276c7e66e00bbad6fd6a5b2f05 generate_keys 530824d34e0da18eba2230acaad119317f213091c1a428bb1c8308dedd00068f 7a7eb057281f3fdc69f5c80da07ddf15e6dfcdf60e4f6eb7af7bd4bb2b2f8509 generate_keys e67712f62552111211414e0a080b51fde0d521507d1cac94a472d766beb08192 78a91e5961b5d7ba0bd334abee6f670fef5683fe0b3ddb3b4871f2c8bdd5d30c @@ -967,6 +994,7 @@ generate_keys e8de3c189f345c2616c48bd8969ea74d3f6471e2a30c33ba90b943c52527466c 2 generate_keys 1dbb4cc7afea96bfe782b747a6d86a9d944fe2542bf12bf9de7f5bd7e8913547 e98890f85285b4bbf02434eab047dcabb7547b9a9e395b13fdf5a01b7f9ba808 generate_keys 172f3d7f2c2aaf1cc43679981cd1bade2af95d8aa0cfd56a36ba9b6e778ceae8 93c72a1f7ca32272bb41120f1ef5dac3ff656a85b3e5b2563cf5a3749008f50b generate_keys 627dbf760b3159778aa35e1ff1a7b580aca57c77d3b1374dd8773f3b99f34cd0 7c6d58e466f728b78df5bb53eaa8d1c360ca486e6c5d20e869a1703e1c4b2704 +generate_keys eae948788ee0013f51c36f4ffc8bdff414df7edc773db4bd8aec318145cc1fd0 79e7035e58a75caba395221a3319b8d9c851b0c4526f8e9e0dcf5cbcf0b67201 generate_keys 00218cbcbe7e647bc23c95c5e1db95adf0b796d749896da45635124377345b7b 51f6fe7bb3a93c1805cacf222271fb59e7abe48ea122d1e7db39c22d0e693f08 generate_keys 4737fe0445416507aa37539c160ae2ed536c520c523a19369bb4f4fee5b85b85 11532fa7590844d1a9d7a49c29d351a42c14bf7c85c0def65637de146cecc000 generate_keys b44afbc96003f1776485ee8e094bc1d9715efee50f54fad4e4fa701c2c7f61b0 1e43234502a6569ea8b119704eefbcd8196aad4fd2323bc7a1d0574f6cd1ea0c @@ -997,6 +1025,7 @@ generate_keys 497c1259c6f4b963ee6d66beaadd17ec250f2b3b0e6ef10839d6a5fa473f14ee a generate_keys 685dd1514e5b3201083086bb3a6f3232add6975af2d613c11035a4e2cfb0012c 6ab0feb875dd4a8b61c12070057e388aee3809ee8df299e20a042edb7860b109 generate_keys a9d3c7f8c3d47d49ec014460c304326ece7809c979cac0538107ced8e6b538b1 9e2227f40cbe11c4882cd5d5d52f0fd3ce17440d79d4bd6170809113017d0c06 generate_keys e3d46eaa9e91834c3e93ac494f222f45afae96d742636234426544b3226cd109 beb5442cb4b56ebc80a6ad8dfb4f59e9036b465db4eee84293f0107a2308920b +generate_keys baaa20d83bd8829e7c5d1884aee8b8882e701aebbefd6c38e0d6160abae1b021 8899f9ae9dc3566b60246a53a2986150844f08d2c2290844d8ad1c6cdb672a0f generate_keys 667e432b6832985a6cc77c3977e1c408f32d12f1cf137a0eac9ea921be57d9c6 9e693fc3ff80004544c3f498709698318afc408fe548bf40286092ec260e9b0d generate_keys 09b3b22d4b1d5461d8b1912a6abe1f61dcdfeca07ee68b82a1aebabf5a9fda58 094fdb8c5278753544877e0c63cac4c6268b89029e6e855141845a2ddfa5bd04 generate_keys b8db2d557d26fc54a4f06fee7b27578504721aad3ddf12e7e087c2472095f5a9 032989e40d1c51c132d04e69d497097dd463cf97a54509d06038333ed015280e @@ -1004,6 +1033,7 @@ generate_keys 1e0d777e3e35f8c2577a36e7f259745999897803806d747264fb0dfb745b9a2d 4 generate_keys 70c8740757549c8bad55c6c4297d52f02ecdcedf867580eb5069306df18b1606 fa0b21cb212522255a98829af7dbd18efd7f6fcd049f70dd590d982c1609850c generate_keys 511cf9f41e05bf81b34f5ca978efce4f484444f9ad6b901c7b9a2301a8bbc8c7 e7f4fcff0cdbbef5ddf59d1992aafdfa70e00ae405bd322c2d258a392b345c08 generate_keys 8e0757f3ab2147542dacf8aba416894dd6dd514f04bb57adb4ff0be8e954a4d3 4e68d261da8ff63b55f3abff9e10dfa5d974e79d9fbcd2673b9e997a8e770f0e +generate_keys 8fd2dc3679bb6cffeaed8cb3796a014c7a1fcda7ac8b72e3d2798eaec11b22e4 8342806f47c3c3212b6ecfd0c81b9c0eb1732f1a1f318f94000509e3b2320505 generate_keys df151b966a8ac6fee74d85baebfdb9867fd913283bea5e199c908fbfad97241c 05b32b61deee7c6743a7c62cbfe40d8820aabe22883f264021d924dd50598303 generate_keys 57ec524745ad184a059b40c77d64b73d4b6368ec13c7777f983151b50d638ae4 19aff48224747bbf8d34603e7fbcbdf2ac5988a32bdd87a01fa2ab112b010104 generate_keys d081dd8388f51ea462669d14930a19e115c8b8bce8948c362b210d765bc27be6 d637b6977bde5fb34d03f2d1dc4c7123963e769ea69c70a3a2a1a55048d54109 @@ -1026,6 +1056,7 @@ generate_keys 9635fbfd280948f00e3a8f08437afcf9795d25bd56c6c1d932e78d74b06de8b2 2 generate_keys acd801fbd2ddf6a7458dcdcee9475c91cf99fb0cb240c29a316e1ca2fa37a0d1 914eb553f9ddb51fbdec59c7cbb9f87c2509739947db32cee1c30d5f6154670b generate_keys eb843677a1586ca2c60bc5681f4e1898f8f74bd5f8dd503871707ddb275166b4 c679b63a4217e000255d6d7107fdef6d976db30334e1e7059eafc15c5fca3b09 generate_keys 33c9f09bad0b13d00ef984335a1bef40ab5377de6f221c9663603a95b066eac8 c44e6d257fddfbda3af3c8834511973cb661b3e7002908992cb9992e2d97b802 +generate_keys 9491111dae13afa554a2a5932b82bd69e2d0f5e52a3186d35cc892ee3e74fbd7 1dbbaea3c72a3e88b5bf56963304abb95e8a6d156f8f24bcb98c433be3012308 generate_keys 3bf9e0af1a4cfcb76410cf3088f67671e86082840a9207c9607b892618855428 47f5b062568e836719924bd1e4fe2c9aba9c355d4e303c8a59b7abc4eb309c0f generate_keys 43fc36dd5710c6862d20ba045730a32fcac8f263ca5b6896f83a1adb63574a2d 808c71423f6287fc1a79d3ce70f0925e03d6dfebf8ec0238483efd6f6e6a8801 generate_keys 7095c419f290911e6506600d91f1c4cdcdbab57a3b8cbf7f8f2c2c28ed1ecff6 e3f060245dfe2b1e04422743e4d12083369cf45b6e0cae916b7b0371508e0b0f @@ -1036,6 +1067,7 @@ generate_keys 669a57b7146dae91840f394a25e6bca109cfa17f21e42c442d5faa8a823152a1 7 generate_keys 4ce60531b8cb519cf2a78ac06daaa17830b58bb535903c28111f4c00be925764 a55eb1ab79b8c75ce902e9064ca0ad3778d21337dec97bc92a574856b65eb30d generate_keys 50f71761a3eeae6b534e984983bc0549442ac92335794c7b07a7c073c0b7d38c a9f879e65598776e7d91558abc53ee124952355557c767cd3a4dd80cb44d2401 generate_keys 389955b3d095ec81c36208dd641b40cf203f7241c665139715d902fd002ed26e 60f3072e7f6f7d759d5fb403e362091ecfc42298df047bc781b073ab4cad540f +generate_keys 8d73e4b8829f0dc2e82eae9ae25b5f363490cc54fb24ff154eaf11f31c84a15e d36fe0cc948a256aa82dd7b1cb35e77c9072c78819e8b2f7449d549b54fba305 generate_keys a565e6f6d965b9d52e4e7b5c5fae99f9180f8156c9414892228752bc9f77e797 c6b7f89c0317aa07ce75aec0ae9fd4d3368406ef75ae9ee05bcb93272df87a01 generate_keys 8edfe959281a6c723c0526442f2dafeef42ebd37082e7ba6255f6c0a55613e60 f512c30785bbb51bf8375798fef078588f75fbe83720dc9a08594496c48c780b generate_keys ceaf8ba28373243b75bf687d11c7c2c98ad7d5d7ada3b43a9baa3ed9feff20b6 71eb92bbcb7148a2d95eecfc8261f3f6ff11e9390100c60282a60ea14805c209 @@ -1071,38 +1103,6 @@ generate_keys d81d76ba2c93b2adb371649378bd7753c4eb8142d747a7594b3a8dae69b0e375 a generate_keys 562bea1c058b5678aaa558776122a626ff0181167f57f78f25160e27b7a3e20b 6e9aaff46815c66d4c34e8cb3c9d4cd39c2601936c248ba5efec1cb3a7619108 generate_keys abc4b53bb43840770afb0643ddc423890364863511927950b1cf8ad39c242a64 ed1c7cabfab7eb0511dd82d5bfbe93eef17fa5e324d107901db280c46fa8b105 generate_keys b3197deb5a1d42a1b8e60d6c305618b7768c4c1fdf40fe9d4d89525eadb6ad6d 56d5d0122cc5246094338d9ee1c39fbdeb2b7e541dc46b79b7cb26e11e9bdb0d -generate_keys 338a5e980d24a9425cbd090355725975285d7c4c4bf869a8008e04fb55657ba9 6cfbe833b5621ac5085c60b27056f982ec1aecbf9421ee53fc84ab186738eb08 -generate_keys 2099d8091ee581abef48157f6de3e12ed8bcd4b609aaad357e1b228029f5177b ade0e6103101077cc4fc930d84796d91d79d53a126aaadb24263ee1fb17cc501 -generate_keys b2c5fdd235b30135ccc5be70c3c22cc2f93c7570550f79e1f7a2172782b8ed8b 2c45c6b5ff95a6787197a5b10c71311e773d57fa25697516c8cd6af765907f0f -generate_keys ad3eb2cda5c708a3f3374c1b8b143b2cf98afa5de266a552641251455b4cf0a9 c4483d14855aafc5d5c228b4a98da0656bc6b6a5b29ad1da3e34b8210c248c08 -generate_keys 6ff21081a27ff16b9d8ea2ca2b9027f98016a47ba29db437d8f497888a875e5b f78f6da277de036296d5ac65102b8dc519b80c47e2884805f0cd880883918e06 -generate_keys ab310aa5deb6f3e06c4b7fafe5074576675c290fca8342537d309e69edc4ac10 1235768ea6594cb5382af6e7ea8b3f2f3a35ba7f6410bb4d812a4dab9793b302 -generate_keys b94d4bb952473740d23195d4059794dbba28f371da9882f357b8c97f6e508c9a 0c77805834933bf0d7b592fec876ec5faadd05fc6630cabad7145322f5974f05 -generate_keys 5456e980a80276df07ef25181b7241132f3d81d036b3804f876e468a9243fc8e ad5a20b594a1e93d54948d7402e88182ad056424d5193b404b494a74ae29770b -generate_keys 2d288c9f5b551bf525ac7a3658fca13de29da34c6dbf845c98fc7823d1c45687 d78dddff8fe4b48943f6e0ebc7db1228b2af22498f19a88e5d3249b35831280f -generate_keys 6820655049885d86f6cbfe99599ea1202b21b7154749f030a875e23789fa868b a94ed2d9f358c0b3cda2113a28825708ecbf7e51e12f5eb3fd1f5e9fa8792a08 -generate_keys dd1dcc14a48f40f9ccb8eb21187147ec69d26b863e43633fbc4a4bfc103c9050 ce4b8b954babb07072db3dd628c2c56ae5b3bbb8e49efe0ec9f290d55fb5c404 -generate_keys ba413857badb50fb5d061080ab8d98c61609d44251630ac17bc372832ee91936 ead0d08793a756854671c1d526b30a2a37a31e62ff4e1d6168ea0d3b804f770c -generate_keys 922073a150f80d0ba376ab552131a72c73b95a9c81f9dffad03112c5801a7d30 63e122396b196c4af18b15c724123b0801d0dc920d0071988d4c3ffe6828d007 -generate_keys 02321dcd8751ed49d82db9e72bb347f393434d057a4279bd89045ab68aaaf7ac 0feab9cc7ecf85d27f947cfe53c390182fb077b4d52887fcb4d3e86257311b07 -generate_keys 55521b8de00b9ca73e83b015e26dd2656b31c608c992391bd556c9433eaad627 5a042d48700db6b4bc508975d771002eabe11ad36cf634a0c3eebc963d6dae09 -generate_keys 0a57cd9a3c5831f4c291860f81e0a85ca70d18292e4ecf87823349f9cf6a4d36 28fe6d3b4f96ff0763b7a1c27bcab75ac0cb4121203ebe1044285254b0f1c705 -generate_keys 72d9e8a001677654dade5639673b0ab22fd74f4a7b7249049af54991084499e8 47331f977b73c8d3f504f6267c4fb548aff45ab474624337df08627875689e0e -generate_keys f223f63cd65695034890fdf26f68ed0d4e0fa6388974993fc46ef4193f3e4a04 ad6d6b470eba69dcc558856cb1cfec5d7968024372f073d1fbd5b70ef99f7b0d -generate_keys 3efd50e50252c3f97d58a5b59a3692bf07f5107f3c78627c23918dae0b134d0d 7939b1c0b51b4ef008f4b0f408e2e4bc12d25d16a5015ce3351206e263c0ec0e -generate_keys 0d86f9c06a59f65d58797b0da53a6649f4dae67775b49d7ab33a840c015486ee 300f0728eec27699be487cf1213776550c5c57f49ca05e7cca6c4be0eb3e7803 -generate_keys 0a2b1189e1382f89ef7ee33026df16f5e73316d6c530b55327327cf7e438dc93 2ed988eda95ee210e2ce5e717771410a659a2b68e199d2bcc3fe26426c52f406 -generate_keys 84ed9a78a1a9540c56598b2a53e1702567f0ef1adec43080f9453b9537739be4 5408f0126dcc80f0701bc882832d1eac6f5babb4fa976ce87e60a32b437eec08 -generate_keys d65669aa48c36c7decf86f120fd3078848d4568d9a337a9e8af78de4fba59039 7955a64af6e4e4f7fdf24668088666f8df8b793ea77d3e1105f7fe53a4f36909 -generate_keys 23ad296961cbcd310e41eecf365a95fa1183dc4b1d892bc4ecc29327bd273fa4 e7bc1af4b4703bdfad76174e4329af1607872983eb4249477d9323646e8bba09 -generate_keys ae6b3edd13d95cd970dffe4d997299258b9d77da7883701c5e7baec6a2b60787 068ca8e94dec061db5539c1d8ec8e2d53f6b249303777e3e45fc1fb39153ab0a -generate_keys ce7a204cfefdad743e2dd1d06eebd6333a150e0ce7f9102973a279f650e54b5b f10a00f97468e5cba6a79f66bf2a3dbc0c8500b56ed7c98077c9f73f2a751d09 -generate_keys c6224f99251225aaa138d756a5715ec3b6e64844cb09451d85340b88cfaaa812 5d14a4482e4d15db92f848b5fdc8076e97b74cb52d775d3e9f6f1e8fe42a1c0a -generate_keys 4f4182d8ec8c7e0ac7d1c3ab41d79212713a0f657b82d7054cec14ca71c96315 9442c2aa1710d99383d4cf48cb2f89f986699d426c5432bbc8bf0575ff56f500 -generate_keys 22a110dab4e71cfcf9a2d4067c74e37de177201e28ff5411f81eabe34ddace51 83160ff6147970103181024292dbd1fa96c070311c5c98a0f12f324809fc020f -generate_keys f188155d50a8f83e99115c1725e5cdc9466c47ad17f7a8ac2fa38eac9cd46013 26d0f8bd1eab7a3dc9a701457bf9f107cbdec8f38bac901af8d188c103968904 -generate_keys 506bd71758bce525b6e4215e8f25c9da13a32222262e70aa2e59464487133c61 83cf4c6b69e53cbcf20ab0ff28a7cdc74a1ae6477d26c062af12fb096f81d809 -generate_keys 9436667a054df080fdf7aa01d54bfe3ce366433579e2451f79fd17c91b2a01ef 40f3d7f8068ee7b451e02305f8f192bf86bbe6b3ad7c0138a77a55542440430d check_key c2cb3cf3840aa9893e00ec77093d3d44dba7da840b51c48462072d58d8efd183 false check_key bd85a61bae0c101d826cbed54b1290f941d26e70607a07fc6f0ad611eb8f70a6 true check_key 328f81cad4eba24ab2bad7c0e56b1e2e7346e625bcb06ae649aef3ffa0b8bef3 false @@ -2547,262 +2547,262 @@ derive_secret_key d76fed84dce0fc00392419d6453cbe540a5750ab795c74b32309fbe000de16 derive_secret_key 2a300cc0c66bc939134a64d0c7647667ad2bda2c9617215a082ac6312aa3ef49 517850 bd18c8e907248bc5cf0a342af0acca3c22a8595aaf37280c61f0e4d772a9c102 4c07dab384e9f7a69789974fcc1296a64c1093c770413d9cc1b0e73a0e55aa0d derive_secret_key cb99d2c0c11ae7c9274de77f8883bcc78d5ef2ed7d77cc024982ceac07cfa2e5 900712766 3dfd746c1318742d7f374508d2131e5da8117f79d7aa32dbc14788933781620f 3103a53e415e8044c484c8e38a756601d18c092b0e60cf20f833aad242feee0e derive_secret_key a2eb32b0e18438b8fccebd078c7a8c419d76edd7a163aadd80d9cc1097da4845 683919645 8fc1e8972e4a8e4d429d2116c2993c3a9f0405e195d9db1ad6ee5c130d661b06 8287a1a390b3c726746829c8e6cecc47d76203b50eb8d4ac58cc43954558550a -generate_signature f63c961bb5086f07773645716d9013a5169590fd7033a3bc9be571c7442c4c98 b8970905fbeaa1d0fd89659bab506c2f503e60670b7afd1cb56a4dfe8383f38f 7bb35441e077be8bb8d77d849c926bf1dd0e696c1c83017e648c20513d2d6907 82dc395b7fea160c4d3a4825da723bb91679b63781cf32d1cbb9d6e9bec92d05be00246f1162b8127419f2e9b02692a1911ddbff68d2e5cd0e0bee60f12f270b -generate_signature 2ade1389a860c9249a42e45d32a9fdc29286c8dc0c8ea1216ba786c74517eefc aa2521256174ef6566618a6468c7b8a71ce2dca398be2290148b813710d12f7e 344a6ad0374b6ae8278e3f226d58e8bb2796e89141eb0ac37cff8552b158260e 94d0f3c942de0edbe8e20478fd7e82c6d90a34c0951f55ba120df66b1ef36805afd4c172b88b9344a5a19c76ad2737803700280a7fee8c304a0174168bc56508 -generate_signature 5e91901e800a1959b4ec07a2eeaa3a9b28893029a26e8ef5d13adde490e5df91 486dfb4904d81b1bdaf865dc07ff71145d1bf8a9e0c160b9c817315f6cb30398 6a05fa0a97e172c9a8f5d2e24851ce87bb649a46c34b33330ae71d0d24a4e70a d7ba7ce64bfaaeb85c8a1ccf038069010a0271f903d5991e331864be958e0908e9e2cbff97f41c74fad5a692262fa89c9608208eccd7864d88deef7062827c0c -generate_signature 03e29bd7435541f8b12830d68fa31a8976a7a2750e4942f36cf834506f3f1b17 3a9768ff7593e63e615433567e9f2d7167a934a9afe7fbe587f0502942ed4ff6 b1b9f0cdb59910598538708eea87ad5114ee9eaae0bc5c62907688d6adc60004 9fcd306d5514b6b598880fa1d529a4fdf6fb7dc72261db0e40665ecec8ecf702f638fed709d71c1746974053644e12dc80bc32ce1afa17f1c8277eea3ebf480b -generate_signature 5eeeeea12358c1ca323e2bb7f7c4f4d4f64082739f196e5505a116760af245bd 238cb505dcad22cca64e100b9b0a3133b44dec7a6a0abe198f6563a1df53a3cd ba2c8fa6cba86ddc91f810519281abeb43554e43ade7bdb3c238bec0bdd12e01 241223aeb98514ad177e864ef93b19b3746d2c75fd3f75317f7c2822ee3e43031ff189159e7dcad21e1fc9c7af603dd960190644566b41d249f014ef0c367909 -generate_signature f3f9ac0a5f5323f4af5441d5700f9d520e6cf41ea441ba045716b591e743cad8 73c0232f4a68d26578542b4d1e02287b995aef419200f78b3294f1c1dbf979e8 9758db88417ec357419b8e7ef2a75d2c65bdb800d27f6203aa54b5609955780f 4cd6430d0e115a554533d9c34856bb96481108cbb8f4d51ee696a97ac9668d0c033fa070873c8d51b8b89347f739fafb93368e6be41c8504a388dfb4dfebe70a -generate_signature 0c85328313e78623d436a1e3cf04ebadfd0178d4b230004469ff8e995fde6d11 c1429c3c7676607688349d6727135bb442466932035cda069ab2463b97387d59 1e58bd527b1ba1014ad772c523700434791a4d4c005f2ffb81fddfccd03bd304 5d0bdc0ce2ecd4f56a70ee6d4d3d794d2d75663be235345a08eeaed41795eb0747ce02e226dd4ae18b10d384dd2b20ae2d331f0a74e22670baca1b777adf8c02 -generate_signature 9d2ea8622e9d46d17a568571332f14d6be90a40df1aebeec20f8418a5f94ab55 f8b705820107149e4845f2a3f3bd045a55944aebf35d1104632450bba4141db3 d699d458752018ca3ca82433e6fac7547030990c923e4192978ef179ad4aeb06 f6ac03c0aeb13106e3c7d892a8f8cae495958e0ab45c3b73e15d3eee0c97f008cbe20124ff7c1047281e709c420eb68af616f41c7edb54945ea7a03b0cf4c700 -generate_signature de9240454aec3ea2ae6e13ca9457e43003991b9d0f75a4b25117e1ae66617ea2 ef02c34f64ca98543ae5b871197e413a7ccbc008f2366a2552f2cb5f852d8ef0 05cfc28bb9cbe0c4d02d8692f40fcc864665b118064f1bd31a347baeed24240e d9b53a764068be0a0ae22ede9f6aa109e5cb5c6a01628b6d87046c259cca1906c60db6d383b94811f45445da4fa33ef1077f9d59f37d96057f211e773022c005 -generate_signature 806c083034f5bfc469e68a490f512a3c6cc3d21d043dc3f9d4941f5a9fac609a 65aa36a44250dc1e5985676f193b23119f7d5f9e0291e6643fa55ac70b1ebdb4 5f5cbfd6c2d5e22b703db1c64163cc0bb674a1bad00cdc77ee51001af5f8af04 3449eebc2f98c2ae81ea1dee4b860693f2af5e9806a935d9d6f40c42beb5ab0d40b73ba8e77db1eacaea02bf1d342b5f9ebea4186bed8a961f56cd4b7029860c -generate_signature 413c368f9b4327907fb6bcccbbdc0540acab58dcf1a860c98a4340448ca4ef4b e37df5cfb5f8ff60b822d3550bdc498a7557e1c11d82a035782931854b996b27 4dfcc2bbad477e1cfc6076408fc85ff9f3381dbc2ca5f6b61b4423a29f372d06 a3b95073fa4b6349e116b8abb70b31afb53de79472e0075601c43df0f6a3f70116fd4a6ab88604e4d122638f4d0883bf928adf466bf296a38fe72a5e0f8d5207 -generate_signature 3932123f3c95fdb21bc6fc74042f39eec45e588d707fbb7036983f3597382bb4 8b0138170662561e8b4e32f0821d21d187c62e7939903ee747aed3b1bb277d2c 649ae266093e93d0968f31ccf4d0b9307abf1e50b7d2b811f74c9b83f58ab00a 2906551a86e553adce26514dc6f935d02639962760c4e040f0a14e5d15d1900220f02fd7e6ec00a9cfd62cc62253508526c17d80a58464949cb167d6caba950b -generate_signature d17ab44dd70f88e19f0e8ba88a413fc18b2a1ce0ed712d6d110a191c9a284236 38bba4ea01a82f0c16f36f4f3387d6015f2c703cf211f6b73936db53645ef2a4 9d7af7de69861c61d3c8c6f2022e360a6cc8a647a4f3cfbeae6c14f46265da03 132ffe4f3b2bd28b82aae9c202c556f3963f0416457c6721874a6c212ca818091b7286db323f26bd56fc0462edad2a5b4dda0c8fb0a4934e30c21153f46a1d09 -generate_signature 7dd81bb4dcd4d74f4c034a4b6a51a49662ad34a2687401ca00e8a628a298ef44 5edda4da92d8227684c8e30c940a9d4f9ac51c9f1e1c9216e826e6de3212f47b cd386423bdae74357991ad01bae929b6ba9d65803d00f06fc9f0ee34a764bb0c 1fbd451cf374e11e6826fee71c4733e398986bfa21b1d956a915d99ca34a44088961bc45fc3c47d484ae517fc4381e3874800b16ee86039c3043072123507102 -generate_signature 2e8abcd827b3c90a24a65d29e229b5bf59ded9b13ca77f51a98fccb37cf9775c 10df138936f814628662c2cbdb25dd7820c310d7974bc74314131f8423880dba 0d8d845fd386f1f47c4e92d6861026d697215a396f3eb7eb76cd478dd6c1220a 15a2b65a8a9540b1ecbc079d72af458911434db49200bc61aba7cc037ffc6e0df211472b53884922224c8a6e09f9e8801b59dd554ac856356a69fc14a389fa02 -generate_signature 83e42343a638dba6fb5d78e1b9c11e236425b432c77deac3ad098b93ad73f14e 3e855c996c5341e02e85737a2b03e98491037d91721cecaa17a83c2c4d5741f8 87be0823f5741f09e2f0c1a3337afddcf1533dd10e0b28efa8b1147c9ef3a703 26d8904ca8d3266cc821d2b47f0e9706b8421ddff2d8ad45e128d27686471e01d030bbd9f0afa09aa28b331a1ed8b770b157100f7c85f4cb5e4ca69c2231da00 -generate_signature 206fef6045a5e44f87bc7acd4bdcd271e1c55cc8e42f5943f1f0b1b3dc0fcc54 9d32cb01bec30e0d7dc921f1ce44b5a829fd84c37e4304e4f910cb9df501af4b 8adec55623bd61bbf39d72e3f891419b5264af1bfaca43278dd86a944ec04c0d 855cce36bf8774d2aeb4025a20bee96ac9f447f98907387213ccee5b66763008980b2b19b8aac1984d202ec6d030916bf84cabd1536360e2601e3636bba2fa04 -generate_signature 0f1d0617a849e1266d6741e17e8fd8a4af392577ba27783ed203377cce7514af bee8f6fdc7360d9acd4a4076ddb2f572d9e9306940b39e5bdae031db28f201e4 95f785c3db1b8ba26e660e9ae8a60af20a00289d984a83c852482c505d1a940a 84cfae0ce5ac0f6de3cf01a41e321d771bef0e120c69269c5d17f3364e59cb025e3f6195270469d16b1654e1da59559e184d382cb631e22f916a813c3a0cd30d -generate_signature fc47da4563a05a5334fc291b1730ccad835e9469f417987ed3d95aa041ca2aaf 0c1ad3f7c9e60987a84a3525a4dfbec5ad69f276ecb32e3c0880ce69befa4810 50b84ef4f4178228d07435d3105b0fe52ac7d2bfd38da43875579fe65a7efb0a 7124e58514e1959b3042cea4d6483b77f47c31ec61c741f51e85e64c0a557a06057e1321cc689cf27e455061e17228b7c6b90dcace53032eb36eb761e881d506 -generate_signature 02cb1e9244aa1f6736d8aa1d5428b30658756bd318bc938d5fd704d97e4a5d9f d52a28a31f59208e4e41f6473e6bd9229ab6a809b228fae3d8f0a6bc3a34eba0 c6fa9ba77466112e1d268891c5cee9f88d091a93c06cd4ba23bd034cb3d0840c e6ab7b36f234da2d16d6fd72c8efa27518dc21eab5318af59bbdcf30413c110990e878c8fb8092d11c724b828d8e098523ad79eb7f88223f69f8d29343845208 -generate_signature 62eb41777076bd1a90450e80e77cb1aca6a5f08e2320128b704b663402759d01 8e83ce60900fabed38fb560505d26420775f10ad6729b209992816101c1c4cae 14fcd95cd127e1218c11fa267c46f8c2d5c1c736e53f8bd2bf084693d1114404 9f53cefc1a5da70b6d8ad309db890f3755ad994dd0d5ee5ba778d050c09c410221f525d06864e6c48c13232aa1827db5e48d9b0212a4c166f367daa59946c208 -generate_signature b862759c98652ca2b1522a556729103de96cfe831b3ce615547ba70c5f622c0f b7827c8b2edc9b4014cf4421f1c9792c012ac3264b15204596652d5854bc7673 1e62f5b7eb5d2bf88032c98edc74a9c138969cfee15f4cb69990feabc0f8840c 7991860be6e8a268f69d5de5292f5dd566000389bade3053790a52e39c84540e4d5b3a42d3960649adc93143f08f947c03842c01cfa98a3b3351e0f7d075e407 -generate_signature cd35a8dc333ac5f33f3e12831a0a2f9ee03c7f421dffd7900b7661e76b056f4a 31ea2dbe369fc7a4514f3f826cd259eb8baa6bfbf22fbc2ef520d98be6e821dd ae4ef972bdf190ee205caaee156166e180e054993709bed5ac96bfd80e8b7401 9984acbd99cfdc3c0ae03a8b2fc4db337318ab1d734502fa22a55dba9418220a923a3b25f1be8df1440c66d1f5ae2b3fe53d7700a935080866250c3756211e0f -generate_signature 5dee08dd0f483aa67e0b2539c362eca5c4529961935d56f661ba641e5efa7e30 be75e0ce86b68a72f7487fec4857a7a6a188176ebcb9192123ff98c49bd2b4b1 b13ba6bfe9c23671e7bbc4a6380c1ab6c61b09db58220d28781d8ecb1b37e609 1be9e2597fc39bd0363857f3b6b65e86734a9a699fa017a7fe63b70ddfd4ad019feefd8d8cae3426490a2b34d7654a8da016e1f0585216ee5558b5fcae821a07 -generate_signature e88cf519e819375fc59bc8de8ba403278999311c7490290f2f5438306bdaf339 ce99f73115a02e03f42a1b583dc3cfd5fd1747c1400d1b6df73e1a3ddf616932 0a33216348544ad80a652433253b6921c0599d3a80e4b2d4a0477cb121e08104 9e59ee9fddd64321f4ee22b73d27c43d4da50ecdaf5a41e57a732c4c5718ea0d53b0cc6ea733b311eb68e7376a15c2c2f804ba2a18fa2e3ad6adbc1a0fe30905 -generate_signature 82a2377ac1c6a103cc0b955ea1ed3fcc41bbfbf6416b31984f28aaacaf4e2a94 535ce02ef72e89bd86e0fbd9f8f0197a99b11f81128f5179044e4e6d0f5f1a93 dcf1736d7a4306330ffd64315b2122c5b55bdf115dd52680d5ce798893b62a02 15936525f24ad06264e8a75c014cdba6fb11f11d5ef1bb9e1dc4cb1c34a6cc081dcf1068fbf519f387a028a68c05dbdc10024e78b7d4717f709b0f3b58aa1501 -generate_signature b207af5749179b6f2b30f48f2e0c19d90b6655cdeeb3fc37f656321f50ab1508 b2b43995a5ad7f51c6c71d29e1991f431444b5e73019b3d36fca05bc566bcf41 b1e043b1b9f4c280f798aa59c2f62e46c4abbc65ceb17349f4d11b867937ad0d e82bd2ee59da43eee8137763be0c87d94db840743dca70e9d2f6a8dd85f9110ca63c7b62ef1f5737bdcf54109889a28f719364bc68b0278e31b4425f8e6ec20d -generate_signature 63e53137888836ef30cd6a93d34a0fa749fcd9459bafcf143da29956a6f35060 4762dfaa39af96a85ae746326693ca87d82a008b96c84792ed1c570abaaa81b5 723eaeaf84c9dae7476aabdc5fd409a0faa7c61ba8b424ff78d299b9480d5a02 700574c73278532462d73ce2bd90bd049815abba8436580cd7c0e5834033d705d984d2466d02231b70559d84ddef9e5756938790cbe93fa1e3731900543e4500 -generate_signature 4cd5f4b8cbbe735336d469aa8f2f7c7e5195d60f897b9a81b599b2e045850705 4a6dea121c196f56360e8c17273f1b94827efe1f24cbcdb9d3ed61b9a207b73a a8e62911309f4d4fe0bb6284fc4e3cf4fc5b08e3812e27328f68c2a6c278440e b7f46c071cfc09be24152dac2e6803d042f6802259f5da4c672243d90887b2007e89de8647749d9a89111bc793b3872bd4ba9023d67fb1b2eeb642a3ed477d02 -generate_signature 7687ef751d6533aca6c911d70bbc4a8c5252fbd3112969a9a40b9e1dd041756d d17a5002e137731bdad6600b5ea02b520efcd1005008c6f1244deb839ea041cc c848b5aec4dd76bd8e33c37ac65e884699fdd7b5c7a905801f2f46c56f783005 1f1a36b19a97bc4860a97a7a4dabdb70f75257d0cd69c5ffa7670ad5940dae01921a6218ebb957dba2d5c13c06aa2185116b1bb146d168436b376a1ce8523505 -generate_signature 7f75ac1c1d1832d78136ae9459b070982eb03e91fb4b686f17e60be644127d2f bf2d56a4e6d6f7eb153f31bd9f39d23a9e8d06ab8f906c716dde473fb2d16554 c901408e3a9a52cd7b95db0a8a5550aad0af38190c082f5d8228e5587367f500 8d578c33ef47b681ddd5407a631c72a78efadd74515697e2fe6be0afb1b31b0dd5064c6aaf236eafe2d1b06433dbc2cd9637e02685c3915ae3b88cb768ddaa06 -generate_signature 1772e5a77a57fd69d6ce9a68c81bd9c4f81579741103a177bf584819a656e1b2 2ed6932a62fa064c9c2e39c7ab0ddbb6786dc849286af8e35655a58cc9be79da b9446a654072103d6e331cea1425472e0782b532ba9e235d61ced65ad6ff3705 e6aa025a2ab35bb9f141ef2e7cf8b4d18aa5e83649273c2f19199b90901969064d97ae17c96b207fea4fcf4e139bc0c516a747fe927e119c2b9f3a2d1f615108 -generate_signature 8bd02d71480ae9f17e999ca813b837402c999bedc4374d416e6aa9e233818f7f e0380564647a85532bf68ecb662fd8299921c8c51982b6310b4a6806bc056dca 9df00a62dfe8ffe27a34b7bc6a24a10d7f147d620f3ed78953930fb845598a09 6c8dd0c7a57927317469a5b6351666095cbf9c234da786cc7126033885103c04c0a83dce35c4f1a43820defa9cb713c707573b7ec62a4ef36b123bb87aa85700 -generate_signature fda1233d780d70dbc9580c2b80ef1806a8ea2df30c317f7891462d96fa4d66af 5f769cca4be9aeb809e9803160b179b1a7bb7cab0e2b0f6311c9e29a8db20de8 076d27b6f85be7acbfbdb38d1b22e1d75c139072f7ae9d33bfb7590b474abf08 56d25ca5d6b9d69b90938f898340f8b8a4e575e0a247193ce8a3307178ae7504c6405de28ee8f385e7a58059f45e884a97325c27d9d79f9c649972fcd8c5f806 -generate_signature 80a147a42fa1e4f83d3915888f5c22ad71f92c0b2e1dbef9657330912baac097 add3133bbd5b10f3b34304864277b2a335b3625afe0d188ea6f60ba7302cacf3 911a315f1f7c21c97b7dd0385da95b6bb06de39796a538d909d51bfc07439700 1093f3472fa816e92a742c899f06e3b8b22ba9e9ac9212ad652ac91df7feb60f16cdf4f7ca6369b9bc6959acd7ce2271b8d1486c98ba2059342f59ebf33dba06 -generate_signature 870ef0ebf5756b28ffbdd4cb65c2abfe6bbc366408ba42940376e91c750473fa 7c91e023da55901252f69ef58bf56329bb7ab688f444df00c1dfa80916a1851d 1752295c9937a10004ca9884b676bf4cd5608e4fb882f733ba1d91093257320a b52257abefcf92febfdd84a62c6df43938ac0cec9d64d6ea6fc6739f3c6eb0060a06eeaaf5feda7b63e7868e3afd068fc669703bc4524d6de74106e7f7512c0d -generate_signature 711f84e938e19a461e28c770573ba9220b84b233ef6494e1600b432333bed7e8 2fa1edf5af46532c7d290322f145d44487bdc39de5b60d365f9d2937de5bc4d8 86b9d8c1124989a8d5704873ee831f1620e580799fd46e507e55c9dbb2bde40c 6b3e238d3fa1428dec940f3f10f7cbf75c6024cb518e72700c5feff1a8cf5e0f366eaf202c6fbc2afcc987f4e76d56f09649d250bc98e9fe0fc1d122ea70db0d -generate_signature 182159820cf794a0a367e94e6181cd2bce0aa7e8628c89f2aca4315136d58bd9 6252042e2d1f1694b73799d9f4bb777e7019ca1655c73dd79715e42f473f6c29 f34fe47fd0f4e59854e9b1740c91336978ef9b72bd07b2cbc601319adb261a05 c079d67bcde1dd9bafe531e6abdab409792a7e41de64dde26205829fa99e33056108d71a6e48e7d48cdb5a581a3d457bd3daee313893fdbfbf6181d3ed4ce104 -generate_signature ac1490c8b703addaf061bda16c13c0ddd4ab06da053317ebba240be4e794b7d6 14d9ac957f7b65d0a8e55488d62a60325caa227bd28aec1d6a4f7fdb83a2b6d5 1d9d9a3c2200e2a127b68b06b432714b585dfca9fc8bc46c44e1a7fe7462fe07 d51fb46dc7233fb29d8c183e1bea7c2c015cc52e76403c05fc0b213c4f9e5702b4784fc70ab883bb857df5f3b64cbad205fbf28946eb6b86f7c66f2ad6fbfc03 -generate_signature 6712b724736993684f7380ac03ead9b3df8c8d0f131d4ea99ade9d153671a3ab 69f90161bfbeae0720a5e0463f15814ff8267d8b742c2eb612f387f08cf32c30 74d48447a77283726f32f5e726074f1e3173d05a55b9e14796d2ea5436f0ce0d f533fea5941d67585bc65d61e8c661460b1fb5a354dc581e271dc4ea10e1a008163acbf86a5c9f9e6515ba7ddd5ff0301b690c04777f9eecab05ed6a8f2c5505 -generate_signature 2796b04ccbd3ecb7ca3182d12bce035edcc049e6eb7226977e914c22b406939c e02e549729c483263547dfb5e4280d5e4ebe90a7140c79c0eae07ddcd91f2266 a81f6fdda8b3c5efda411f6ae5830c151c1e09ddee44fcae52128e2b4fba540b fbc28bf52e6a2f2c8117c68d3533e71f4538163905ec09e7ef97263b3935b1048abc8959313ac3517ad54b3b973c6cee9854138a8f59679d27f2ef22c2989600 -generate_signature 6b07f68fe4e8de6a194532606d0f64bb2561abd14d66cf4dac2526f8a5f40763 e21eb4c04c5abd7c4b12e434560c636a9c0fb4df380a207a93321e1865a7aece c194dbf0de2af2b96b1af7fa24b4b29f1291088413c9f26ed98954856c411d0e 2ae3c1b1128a4fbeaa74ca1fc3ef5d647e3863952a7a0ee6c001ae7f19a2fc0a4a7abbbc4a846f36099f45bc398f9b29047b48d7a97cdd8d2e1d7dc4ac24ca0b -generate_signature 17bf7d4f22e2e16297c3105c5ea01f9d7210b77a02d2ddc8d9263b536c1c51e4 94fc695c28959e0d68fe1dfaea0bde1a2b11be6eede96a4ab65b68ef0a98c082 bc021c4b80b42671b43227544c185fbbd90d29b5d2f110d5030aca995d0e2905 8df0f6c7b2233d0ea35e48c8670e9eb6911a691dcc0116c87a265426e3b3e1092ec5edef5010453722f5f8b115f15e9601681e82ddea327cd188c5f0dc8b7c0e -generate_signature 0833ccd1e71d03cf19ab214685f348fa88e711bdbc6e7106047b64a151fb6c57 f6064b733fbce4e1200382adaf77d93c542a673573fa492cd4260fe28b14ee16 01f9a1785bfd24fa38af0a5d0c8324f8946b9d0583222c53772e69367597490c 4a4a9e8994c948660dc08a7742f1a11da0e0ad992ff1438d3bfab12af3dbc8093d9e9228a539e9c0281791b7b33de73c4fd67af4c04705e4aba4c1df70b25308 -generate_signature 2185872fb1e5cfada7668e6914ffc05f1c5fde38a7319e79010a8c1fc1c2bf28 23bc7fc2dcc89856410f5f2a006f4030d7880226ec512f8ce22926c569b557e1 e8ff76b5f7d00a8b8e6e2fa40b7385dd86692bb197cbf1220f3b59f00e149604 a3d8d403e81bbf654d0d3914e8e3f1c7cd76d332c7f3f2e8ff12952e5f7208056f0dfccb8cbbc22e822fdbfb5d75b1328544f1542f9df165b78a4e238b936406 -generate_signature 690194220a436c23dd6863d2b7ab4ac41cfe4ec6a6bc6843f1efd4388f37ee46 950f222148c84dbf4d586e7f7a2b53fdc43e45e034d0363883f50059302e5074 46d06e7cd27acea2c4094cbc3ead11d40b800fdde1a0fc1f687048e2b7ac8602 905a28806225128eb7d1ef47c6a27431170f5374390591f69ea98772cbff6608296be2412af3610ec8fc3e9d492d11cddff156e90763cc62c427603795225d01 -generate_signature f2f674fe63b53dbeddd1966c2b3a3fc7d647f63190bd0a183908f782ee65b60b b75b075e9ce254f9efe7baf09897c5f58263397a0cedd458ed8c123a552e08c8 5f2ef89fa9956057bbd7654f09ce75f82188214ad1c75d8a1edb1f954689310b f3d64d9b473ed27e34187713fe55193925c6c53143c1c740913160d6214f6a00bf412c34081a30e1863b4d5a4e1f67a50be806fe81003b611ef42dad9a97330b -generate_signature 98e1472b88f2580a68a4b10b0634bfdd859590805b67e9b2cf8b76be25c57942 1edb8eededb14db7343fc79bba30422af90e92c739492ba1abca24a33808668f a8e7bac4b9bedd6cf89f709fc97a5d9c7180cf8cfe36fea26f3931192366d200 151ea077a6afbd59a303864bfd2f0a0882f87724fd72f03c20597a92cec8800cb71afbb4dbc536e3661572cf637e8691029e84782ce38d3a2010215ceb48af0a -generate_signature 1ad499a52576270197f365c0268892d44b73e9130f70c5fced7746498ef531c8 2394d9a89125d99e13502169301dedda64cb38509465e972b6f20c7f098d851b fe04a7d2a3e4e8c2a870c774483ef0b122b8c01813914e59042fbb76a59a3a07 07933a6c63a4dd7838ae7757cb42d0ee3c5e807a136d0a8d3d50e9e2f4ac2205485f670eb484ca18a4297ee3d5adfe7766a86f6ece6d4e87403d65aae92c6509 -generate_signature 43038508a053508376f5d0595bd8cba556610e673b8291a322a2b9c72dd4b214 4934f2132f6ca4a2aaebe35ee547f935fcb28588e8061d7da267ae0954bcc987 041a55efcb7dd92f6fd6c2c2ae8c93af8d6248a27cf51c3d3770a0712783ff02 4c05071b1ffce1a1735437f06dd8227870a8a1e6afeea04f313cb1dc28afed06213f52a3d24b0511d19052014a56bd3fb4d3eadb73276aa2e5a010bf4b8e1800 -generate_signature 4f9141ce176f61503a42ad71e3713b8a52dc56505809c8d6d98baabafc4e9910 516aba422fc25e0533ff24157c263ec3a284e1dcea2a8a04972b00c29df0dea0 23a237bff637b3008b429465d3223cf820ca4db0d75084831ab81808d4878006 02a732f3701b59a4420ffe5c5fb238ab6d0f03032d2a855d2cfc1bc668ba630ed4273345ae0279871c1d8195a529666bd0913a346234101b568e2db483ae8704 -generate_signature 13dd60b4ae30f8146fdc6a54eb8018493742413dfd267f18bf0d21b380dcba18 8b85dd2808f4a567bbe3bc67bd11209c98fdd6d177678afe6cbc6fff19fa2d76 396068b93693fcc4afac343f8955a705d3fdcec131495c1b131e0ee9fc7ff80c 7f1208925f3c8014a5dc3360660865d6b8e57520c715868e540965e8e41ded0812d602d58d26a4a411bce1b6113bfbffb2bce4ced22fa844cb4694d4b0ae1404 -generate_signature 72b57bd7a1dc353f62cad2299a225484014343a40ce052f66ef2bdd581f3d5c5 57427bb8fc70228d84e191047948c9bcd9582c8f1b3118f56064eda938857a33 daf6de1663b64ca4fb7660058f16926e1fa33175f298249183c6c8d862712d08 96979747c606aa3dbb54d2dce4ebb8e9369216eae26c04635ca8963e4024b8054f42b97aac8bcaaed63917e53576e4921e451a9e7c9fa9daf11ac36888718507 -generate_signature 0e5824738082572ccd6c9ac2b97e37412b432a6bb4a1101234bf77d2a2a1109b 9ddbc2b910f572818af16baf273026b8cac3e6b7f2fa540a9bec2b38d2020dcd 3f4b0832a84cebc9377eadef2fc78a62f6f32576258c8d2424d7dc7669213d08 dad4f5c4eeae91ba65dc3793bbaddf37e18c1616adbb8863d306d78de10f2b0782e8cabaa9b7224f461c2dd7796ad43f0ced94f24a96caee506a85ae66641000 -generate_signature 459f98423e876494700752609232d068596b762ef006c299750cb3ff573b0104 c2fc73baa1d5897f75668116cab853bf359f156e24b19a745966512f6835bae8 9ae7c3212e6695e0f5668d062b2291b27bc45affa1f77b9bd65951914a842d05 7ee993ea51f836088a5ee78c56cf11e49d1c92f65d3b20930486fd3fda87040fd6af90fbe5a9e38efba148ab5c28795b043642ae76688629647e068c630a880d -generate_signature 6d176d259af7ee75ad769376ea2a5ab9accd9a9f4d878192759f5dadec194f35 2317f20756c1462f4d69d36275fc14958419769167eb526fe6a4f3007036d474 1bb97762a71f9aa32b2f7733f1fe1e0bfe8e654ee6f8361f83a61a22f32d5101 93a10eb03ca166d256fb193f4b57aca1ec0a570375e55d77bf5f97be15a2e800c5815b3b727c9c8be61355018ff3bb0c0abaf20332edf92fc4d80b674c7b5401 -generate_signature 88989b9365a33a6a6870f4978d8a68c2b310f7f6f6bcc3c7342fee9a2985400b 09ff1ab9622a87b66f39804ce7b84c1620456e83bd2ac9fce8cf3c8564170543 f3cf70e5732cf0b4fbf81f78e95bddd0166aa597c2a932ca16d9e90a2742c80c 777f41771e4af5d397ff4ec6bca78510e06a8d13eed74a53679d40bf23798d0d8a1c247ebc86bfe877badac16ae5c589bf9e1b729f427ec944e3ba70f8458d02 -generate_signature 72f08a3499045d8e2a14b4872a89a7b53756fd3dc0e538ece7093168c6f88b06 26ebd8fc7bf1a0c6c1c8f55f701d66411ce6d2d2a70f87c2a5ca42e0f8c8b359 75c532399d4cd4475ab2714f0da1f6b1f131ce4f18144b69c99259c58b5ac203 ab59dda6eaba38b990c9010cee0970928bcb976e5db234aa8baaef67bd38b10cd40c6ca3bba133b5aa281b95dda4a5b705b88b0520e07386336444ca4c11db09 -generate_signature 9dcccae9215809a2a124f8a3bf62b5bbdd0ebe6d7710586c5355c7a7283b0e43 cfe96abf54cf0ab6895ee0a7c9fb90ec9ccd654fd526c36d2370398cfb7e8f6c 911e17b1af1be9f9446dda5d6d03de66c64d0a785b60a03ab7b26e2068c77101 6e7f046ef3a3175511576089e60cd9db1f415b1eb0ce81b334b55b52b7ed040e2d8f6f103b71c1c19e7ffe1415433dbe1838fd88e7acb219c19cab1186c1cc04 -generate_signature 841ac5bce833dbb72069a88c959cc59561e7f05baaf63bb7fdc98a4d6e1dbeaa f3e8bb769efab6217972ced819551c79f29bc32a131a2ba05ab26c33d62c6ebd 858dde600179ebea9ab1806ab8e41ed2abb320ba593faea28eafbb5a7f989206 6679adc8583aa23d5b167d4a8653bfa7638c1b8c383d58b0fb827e4c92991c01e813d60d8221ddd25d638797cbbd38a59f7fa5e582afa4445220eb4a63983805 -generate_signature c570dde787ce9fcc3d48c5ada9054346455ab9a11a1d65b0eb223547bd39d7d6 426ccc3e1c17db41bb5c975d08279f1451c00976216271c9bf221910ad1eb8c6 4979107437a699a931e67dc36312a1c0b5b5edd3a60c1b3dee3c12596e500107 b1ddeb09a0ce43f0ab3817e5619da7168e784d8086e60b30214392839aba2d0a7eaae3b6c4f206d7a4b8640d6068b447bd9d129156fb2db30fe1896695eef80c -generate_signature 62e8187f216da0c992208f3f7afde4e5ee42e0c09ed9897b010430170bb87350 91eb9815ec0a5d2d2b98bde3a097db217a922089e11c4b15d9e4109b6c534b56 4d2234323011d6837889e21b7482c69925eb483ba5b367ca48f5360cd92ce708 5bffb00d0dfd3abdd2d2d6253b2f3276eef954107cf6a64a020de2afeeac4307916569625c8703fbe5e5cb95919da8eb23fbdbaf42f734f22428469dcd1bd908 -generate_signature 49d7e10bd4a42988f7b202cce474c577619f9bea53a7914de4d295b8529aec80 2daf7743268523b94442ce3f0be3910f40771a4f18a22b52f3132b6b5ab2b3cd 5e6e1c05e2e836a936e17a1765b30165f3851ab56ca1e38ac459c8b7a81a2004 aa8f7f10e3da2efd297659e0ac753c6fa3faddf72a4860c5f554a6671d1cd901a9a63c340360fb81dd6bf9f0c6a525682ac8f232ee5c17f76e07bafc5a97580a -generate_signature 51c27e54ec56e597dedeb33c6f2fe379383a8df301688f95e37fb695ce64b1e0 01487d5868e86da7cbfbf00ae1bdf8faf8d51a40c5be011a1ef11a2734616a38 e844859d1b9a5328533fb41383c1ed108a110e6413c044cfec538975bddc8405 9ab80828e02be66b482b0ad956aff1fe9cb947f314fd5d799556c8c6689a7901a35f49c69c05b4990a75405d39d88dd25cfa2cb05e9316b05e97240f81d88007 -generate_signature a26bbb54e14b7f7587fdf8b0c308bb80e3bd626c20a6980cc08b9f25317aa00a f248b297c284ef1114629819876d311bc01926a75899ab339891b4270ffaadf0 7c7af96309f390370a9a5031b9bd524936233f5f806b9c45f3821b91da8b8706 6f3a02fc2e6c79648a9238d75b9f71c2604364d2f81f9b8b4374ecff91e15000a2319cc8bbc046322ccfb91566a4d1c93b67c499b61eaff0f96fb3b650bc7002 -generate_signature 18937794c31d063933d48dde3fe7b5c6709f931e139fdd3cbae74e68abfc5cfa 4abf6a6c47126af111ab9761d8136bbbefef57cc6eb6ae4693803ac915351fc6 4acac844a196b1754f42f9af15c6aa9893bd00b5f466fb691ef396149171ca00 a7961fd5ed608061cafc6f83eb2ce21a0399dfe8733c899eaeaf3d5b6b26ab0a700b2599bf08f70e20acfc449b7fe889d2b7895097e936bcd5a97f5fdb45fe0d -generate_signature 0b32c806869d8b25e120317582013a95c995f9347814e4e37f6b948b4ba1e2f2 47397e6dbce5916e87dff2a55c63e49d1bdc826d4ead31401d47cc0a37d99352 c852e5ba498eb8b9686557309591b1e9b0533a07c97bc6a8186c036bee2f420f 5f2b0f0f0d745b96fc05f9cf0c57549452a32b1f36f5b6e34af8ecbf962bde07a9c60870865456ab0c0ed6a3babbdce3c2ac89a28b851e37b1b151a635fa2e0a -generate_signature bb5e240d1bc7e986e6e929dea3095830fa11b51fefae6cb1bdc8e060775905e3 7ae97231c99afe3dcd855aa587f1acf5f62ea0c61cba1e0c14b0fe4fd26a7b1c 25cb0101d7914aa49cd52abc533a7cdc00f174ba107cdd6788a1f64ff0ae390c 0fee95662712429ca9cae0921418f8dbf15accf71ac28157ee57256dc074ac04863125ab2850db5948f51cb7e9a00f521f7b8369d2f3485891250d7101945d0b -generate_signature 30d230c4ebda0c60892e470dc95ec1152b00c8176c6a93ca73b3057cc7c1a494 20200fa0969e8ecccde73758c864cd4079a9efc8476776755390b9a56800be07 4cce1e28f0c62eb772138560e232b27c44ec7ecb7081bfbe07de7d7281c3da04 88478670f74a44813a8b95aed7b939c730a7c302f3d473af5da9b0ea27db8800b7a584a51b98200176de2a0ced978802bb0e0f6063042f6bab0e901eaceaf001 -generate_signature f1dabb3ce43a519e5899d465abc054635e9fb30f3d49dbacf2dbb54725041d61 2be7da84b3e47473568338ddf79a8c87b22f29ef4295ae6c6ca463df3102278e 8831f066a87841b2beaed0f20b93da8cc730e303bd135ca540511c6f697f7f04 e742a94c268b69f404d8d0b9d025f99e0b3a297c79cda1c90d8f482e900969013c5a4a59cbb4ac94b0dfc7a0ff3f99d04f950da5e94cd66b8034b481d8f3550e -generate_signature 5d60c456bf82803cb3830fa2de437c377f5f0ce42b762a0d2a5847b95d6d4400 38aa6f868aba852ee5f2c2444212088ca48268451ad0bdf5b42d020db2eab246 208ca6972527da0e4333b6d756e5c3f336d70f1af86ee8088b050e73dd51810c 4dd34aebfaa17a9db10270137e87cde2d7795df757078a51bfd63e4a0b7b1a04c93f48bd6ffb2e21d31b1c2675e22e1e60869fce534fa61f84cf3ef4dbb7510e -generate_signature 58bf45b4eb8cdd324173894cbb55511bc69ab649e1dc79311bbfa58c6c0f9275 a429e66f32ec3d35fa825eb5b6357f4daaffcac3a11c47ceb80ef1114a06a217 c3330d61f993dd6652cba521461f4280d83330119a6ae92681b708ab32418904 8666e962966cd44f2f1bbaaa102b192e4f86f9518895522c8437d5cd070b8503de647dc701fca446ca46bc2bdc838021b551c13d5113e362879a430da425d80c -generate_signature 2229a90c79f0e3dc230cc3919066d3e4b385ec53b0559f7ca8b611ee2f29e12d 83d93b52f0df0fcfb3d6e2b13ad01ef38c494090c18014296eed91a5d988b2ac 3e286618640c874daa6e36dfb01b5e2d1f5d77b8d9ca6f5ae5b7ebe659b46709 7738834b40e26f543dec2c8f94289ba12db18a023274390e8911bd2faf2239055063d397e3a939e9fed08c4b88dd2d18bf97ccfcc66483764f3eb494594d7c0f -generate_signature 9e47f640aaee7ab2e09c8fc12a32a531768258c5135eb8e521965d8708eff2e8 a8411a8de998e4b6be239be96460ec6d4f4a8b616b94f77347838212ce4b8613 cc4598110b1aff2282997a410e7cbd837e12a98461a6c6ffc307b77a323f0b06 0d40ba0f2254f4631bf4749320781b75da6c877a536ee6592ce03983cf4e7a0a1bb35353383b77864bf849dd496cbab8094935ef331052c976fc2086c4c04204 -generate_signature 1fbd47cacc32270ecfe0bda8b1b1bd9ae4e03a794016a2696eab9cb0ce2c40dc 41d8ee40da7c75784b464f1b2fe89409f898fc57f395b46ed0038e98c184aba2 ce061c022ad0ad3125b6cc34b0d27291874d29575b10e1d44528ded224b1500d df75e84e803edc61ebb345d6cd96e28f0a30e0e455839d841c18c236671f8a05e9410f779ce84447376c3b0312aa52595bbee530966426713f5c68e353ae3109 -generate_signature 0756833a04e57930ad436ed6e50995529036c5b55db3f9ef070a000ea7b3b668 ef541d76406b4b71299d45937ffac3a4d284b61faa8644775e346ec6f6eda51f efe31b98bdb433b3535e792aafb0373d66952196bf564dee8c02ca0dabeee40b 3ab06c0ef27583ee933857bf6f8c195736b52dcdc23098853616cc1d7a07220f63ce77582cea5bd9c8daff96609ab2a57575927986047a54c5833ffdb67ce309 -generate_signature c5d9d4483c4b9b23e21c259fa19136f0c69cf2cee896945510e95141ffbb195d 39e841d4ac6335babb18e8d9e47e1c75111639709335a1310db0ce2edf686871 6a2b88bfe8a66655b29e20294d715cccec610efa3503cafcbcb5323d8e618400 185a330e61a207ace347f4ade91bf02edf89b6f8433c80564cd03461ed9360052528e631badc4e3c8c18bfb8aba9c493646cfe098e84da1a542b3fd8ec7db601 -generate_signature 8bc9f9c21660ee20ffa666e7be110d8accd2d1be0550aa5bb3b4ae905418b060 14b57372138f3995b35fbb964ed0481969684f0338470a637e183b9780191372 85465783ede0e697db9aedcaba7f2aad3f4fda534db37b9654a3325dd4361302 498697da4ac1809e3eb302b77255da7d3c837ff28475c5f8aa573d6b19a5770bc0ba352d8969758646cf2f228944f29d8d58b04b026f45a0bf55d1c67eb0e109 -generate_signature 7ed3d902f3ee03f81674c4452bb1cf33c0601fd27e25d5aed0b618b55aaf7167 458fa36ccf56bcf966910083e625c7efd4114daee53c45f288ec2cddeb444aae 3a0e8fec3301b4906383419798381d28a2a26e9249a58097734dfde9b9be370d 1c6c6f2efc425c9a479214dff275a1af5f878a5ce4544746875c4b40adc057098424b3f108aa13aa47190e3360837a5630b0d5d487911ac366c0d49426b4340a -generate_signature d95b625b3397e7726956f869e61df3634ee46b08a914a6a0b10b9e427a9179da f2cc630788dd65572d325ce0895de974fa3d56e07717ce2776ea51a32a542644 921c6a6d736c246dc6bef590f359f7093b32d56b05cd8639c7e94541caa2a504 eba26d1aea4ff26bd2c2bfb8e1273598158fb06beca35d4bf5438346d17f2f0e94fc260310c6772989965f6a4d435c7091ffc774769336d0f24de616caa45203 -generate_signature d17c7a1189954c38343e20e2b8e8a290e294753072895948d184cf0d1c3193c1 2cfe22dd27f8b7041cddd1b8111a29a1c56b35989aabe9edafab342a484f372c 9317e035d8bc4a451e52ff94e5594885823ad2cdc7eedf66c5231a4f81bddd0b 90744f8faec7ad521de63578935e614f5c017a11fc22d215638377377ba6c80ccdcf147278879b9e501f67d027a1aa230a7f7133addcb4486484a1ebe3e51a03 -generate_signature 9387ebacbf7d29655f65513d886d006af10a8c75a11cbcfef8f530a72fbfc972 006e6a957483b2f082fae65ffd18fd525bdff0d774dc20ca0b48b9cd8f592b2d 811da01862356cb02275a0c7878185670732b10c7de15ce1b2dc9ace1dbd8e09 27b0b5f87521c91b211454442d72d9a3723aba68369f9c8364fc6117a28c2f0249848764fbaf65399c46c025194aa6f5c86cbac127c26f99deed8d553d555408 -generate_signature 307a4932ef8f15539d70e8721dfa1a4142ba4ed7b2a734f8fb37ffd31f72accc e48b91027d713f4e5ec7d0fe315589b36d6bc6ec338e218f31eeea8862209922 0fc991a39d51dbfb559047a95078e8cee3210760eb9c0ca860e5fa48e267be01 297decad20d429f93736693898f434f0efd936f8e271056184693248fc60c70bf6a126e76e14a535722ac8732373c6a8e593540d9ad695c64ecc9b2c24a24204 -generate_signature 4366484aed2052c6c28d935b2300b5a4e5172bd79d96a37393df3584c0020b2c 39ed6f8df7c2d04ca843e2e76bac2c6a4de490f9c8d1c4ff16b70df13588a4f0 de879609d955fb6ddb4b0609fabb4e49fbc7ec017952681f911552eac8ed2d0a 651f4cf9e28b6ec1c5ff34f3e8a2b0a8ff29ae0e8c2bf22f030186a77764d20c8a72f89f358e6c727db157042730c3cdc029da1186aaccbcaafbe17ac6e9ae0f -generate_signature aeac4a1e1552df635de365394f86621ee2f21f7561a71a63c07fffd53fdbdc0f a6a9623f5791d0194199f52ea1e4c77be18a94541e9fc8d86b591ac8f1c0c3a1 c4ffa6e43fad2e9e558118f7b5a1cd2196453f91e1aa3691013209c7f7bfd40b b37b64b57d2a2227c7f47591dc189ca368e39b92c8308c064af7fac34c578d01e13e37bc10269f2e974fc1814172d9f4ccd983cc7d74c48fb57b95abd67cbc04 -generate_signature ed905056a502fe94edd1c28b3f65491330b58a1e2563dbb8d8369651a2b30cb1 fe89f71bf6d52874eb89f234baff8c878ccd22c5c614ad18eac64f1d49ee00db 9826bb63674eb73980eab3d333d90b1ecdd18a227a34e729ac4aa4c679570708 ac774fce9ca2a9bce0b22d8c3a0144e938766fd6b33a8f6f573d61a7d00d140d548b820edd507aa7665a0676206f14e97a97497c09a6ce8718dcca0e8dd56608 -generate_signature 327024bcbf89837e82f4af135ab5bbbae710d4fdbfd771423dba6d089d62ecbf 089a1ffc8c9ee8b28e3181694127146615db3ca57d4f808e375b0844d68e4ba7 9c7c12aa4310db31790ed6c9041b711f0c742fe3c903e3093e2589de9279130c 9484e5fdeb9bb78ae4cab30b1bca3a9616959c19d7e8b284a3f10e5da8406708c2590dfe2e5fadc55bbd97ee7ade1a36f160c3ae7416c1f030ba568301742e07 -generate_signature 5fca639815dc14114fa452346ca15db70f4f3c13a1bd1dd2e5cc6633bd884a97 0acae623f287aa3b9758a36ebef615ce9aaa16f619d3cf56b7ceb515e2ea5c27 11569cbb68a9b17a1ac43c5b6b87a9c94e269ac507541b87accb5681fda30a04 bed44ccd0bd1cf2ca84310dc64deb9dbc606548bef95b98256799c6b728b2b0a33073f8b3fe2c7218a0b8d3ae3b489ef247c7680d8804feca0302ecc39ac7b05 -generate_signature 0f217303b1076cd895641ff1751d2d469def5e140e0d61dc1a4239c3decdb382 d0cdd348b338fd12dd2602b2d5a872e820e1d9cd6f0b2df9c5c4a04e49559a62 fad9edd7ad17647a02d8f2077b9ff3c0fc755e5eb071165bf902654e7ff1050c 903699943a3dad0bd4fd72b80380767beaf83b352fbebab074ba926776b5b105503cc3ce924fb520c580ef21641d75c1dc1c9392dc8d706e9da9501c47152c09 -generate_signature 254a879d64f8532e5f281149b52a68bcd96c2148f33e3bf7cabb4dfc3450043d db123979ed900409c0090c74705fc059ff72c4e1ed05656b117327e7d3f68d4a e39e1a551efa30ce0b2461796147ebd86394c8c0abcd8fa8118fbd7cb5f7920f d44cfd92bfc3e6822b638dd0234d287c099741fa4939645ed4144453d4f5830740c55ca4d9847bb38454cc11e44a46908cc26a76ff256104acef9ca11986030c -generate_signature e65ec30c477ec561fd8dfcdd1a3b89c099ee7c415de5e780618433c3209b9824 e45c9e7b6341e47a07e794556c9cf91869cb97291fecabe4867e036060c81ed5 860e36d4b74b80737704a4db0ac58e4181d807b6a0ccb4064dee200de67ae603 7953e307c61b9b0097afc72b588f53237ff3ab1d85b3c5cb773c6ffbe695fd0affddddc9e293702cc9b312b377b91cedf50085bb7fb914e1bfe83c4598995404 -generate_signature e701f76a8a06647e5e10c677a9fc17ac37c628580bccc5500f34381536b88b9f 1bfe84084ebb54bfe97e3701eb27cd77e585f510270dff9b22aec8a688d0512c c7d74b95fddc2dcfbfa0ef72aa1078f62b786f5c0d0650782a2913b5a22ca609 13617b56d84c4e269981e2eec20b8924b4af22bd686d2504c46859ea49811303ff3f01a20c9816e81746a80e88d5df1a5238232ab3699d4c34565f6bf412b30c -generate_signature f220bdb877fbf2bad58a7e98cdaffc0047f8d4512cf884e45c484d5b2a19275c c37d89b27a7449d9015b93669810f35faf07908d5fbf4d93ebceed9c1021770d e4692ca12eccebdd039f9d234a083b49a184b7d241025e4b27d022fb9f46c802 649f3ced8a90210f95324e8ccb7fe3048302743a133c7e6992b79751dc855a062083fc8b932967fac79d0a497164b20b0fd234fc6c7bb3da9f389ecc03215202 -generate_signature 2de9420d201089ef5c3c1fdc2ecb69446de59b44b84813d4f2c60c4762cba262 ea272022926e4b6059728e63ea0530c064280312e22e82419a5463b34b5d223a eef8d695f5b62c90c77bfd4a4e257de3defea7eb93cd546db2f0c448deb08d0f 689a32023340b961e528ff696ebcb0763f3fbdac8c1ff23e72ec3c542ea1f1014af7ce1810fcda6a4b71daebfa4369040b3e54d40a40934f08294ce064f3de00 -generate_signature d22270489687f1aefc08d45cb567859a5a7f0fc6bb4346ff56be386f3c64ba68 b231b42bafbff5286ccf0828fa423487e3edfafdb3cf84b4333b92f7c5f8e005 3d6b4f25367114c0fd1922209e6d6ddb062c959f0643d6b5f5a54aa7a8dd850a 39d8bf2d2134e3ac428ea055350b17470a0a31a59e4ccacf49859c2cd123010313f312176309f64fe2c06ace20d3a027765d1cf0dd73a595e3f1bf0582417501 -generate_signature 0f80ee01c68b1c0fa0f72a6890a523e2f941a934d5aea5a37756fc9308e3d149 40485d2af8f529aad1cdce430971bf593c40ea5f650c65d24ef2f3a1d6e09844 ba73077ab95f6b2185b68884e757c95ff288af975d70f54e6ddf75446b59ef0b 6284f664f1eaa327e9614ae44ce702e465a3f3eeb58cdadf97cf715dbb2acc02db17d32bc9fb0f9336156fa512283930c3ed1dda52e7b1d1f3f1c82d15b2b50d -generate_signature fb9279828f9075e43491950ee0a6b55f2740a03e2803e20e9baf42a71845db16 a60c8215f4c3144d397db32359b1638a94bd48efb4921488be9bb2dbac2d3621 24d0feecf4a09080ce8cfd390619e0f0c9185278b712b9a22f23fe6d1b028105 4b919c7b5a5387a1d791cd9067f08c77ac3b05306825bcaffeaa6303f06c8d08f32a80e2f40f3cf3f073a4af3718e10edd74db85c0a2b4be60adb5bc4abd8606 -generate_signature 1853a3886d3421c884701015146416e2372be5dff4804a87c367d69a14ce1674 a469f283112cb9e1247cb12358e1d1f0c2c1efeeb0311b4921a4ec3c2fa6149b ec7f0053fb49ae322026d8dc884d02e4784fef17469b85415f4bb269f833410c 349af7c50f673ec3b90f2a3e7bde23ce1d592730064d2724703a94349440b205418c43ad614ad88b6975c230411878ea43d76962e0d370246943875126e42f01 -generate_signature 87a4d1813017c757f2fc7adbb6346bc711619edaa8531378e25686bdde9b54fc 8e1cf8a065ebb111aeaee0458198b02e9df18e357e60604aeaa62f0e7e81fb47 d75a74c80860cb58614643bde56d7d0793c57750af954f4fe949e08d73e14402 0cf654c8d5dd5e5e48a61e3eba21e68b6b862fd26ea66a409ebe60f6b0d67d0c87dbb4859132f7c7f87639dfa107b3a198c3f912b4d9a22937e2d9d83f630a0a -generate_signature 36332e7b2431dd072a158803b24744d01b69f096aee41407d70ccebda99984db f37969dd37feb2205fa2d7c87d62bba58a675b9ee08caabd2496886059a5aee4 fce10979cba19bc179dadec71cdbf640bb3fcdd3afd07dc0e61124d293ae7209 2adc6d4481f5ba5c18bf7393944f7c8879ec4c8055241f7c1835b514261d5606acce13d49a141285ab9cf45d33de4da1ab86acc47f49cf4df4081634db7f9b0a -generate_signature 2c7db34f2f249ab08724d1a679fe855bfab2ed68228668c7e712b4760a839f63 ac948ab799b000d6125355c96a4c7c2f7918831e2cdb86c66f75a84ab3b588d8 711ee793591c685bde7f3b136751e5a39d55f0cdcdac03631ece1622a5982904 9891c04238700e30e40643aa0d7446d218dd0f0a976192743e52464428e33f0e5c94cae2fa5e8197846d8f4fcc0198f26dda091e1e692ef61a22de077d7a7900 -generate_signature 9f92e54ff6d3c2033a5ce9135c8f079a93f0a7ff4c94467d856fc63c0e96fbc4 c6407e167719e2dc8e9e9d719b1ba7be2797eed2e43dd27b02e8b7affc6ba801 9a3b191d1806472ff03203d5602b9cb73d3f0262cdf56ad70d20119941f83e00 b254c6dab28e8caa175c8efd122106baa69e785af9228445c324ca3306059d0378186b1bddb287b4351ec38b05131da322bd8d1809c6a4a76dd3ec7658ed5201 -generate_signature a70f0611b8337641f0d45cdffc56bfaec855fabfeb6fcd3da1292206b4a03309 0baef43d5b9d89ad7572c413b531381745af1dcfd1ae90d4b20f0f78080f2ccb 9e5527c3b3da09edcebf39183c5d912e28f47befb833177726833e281748c909 91674393a0af7360c4d8db85d49c8c8f373e347d3d38e8f1e6f74aaffe46610da791ffd69ebd3181a705f041701a423d1b9f6bab51b6ab6725794812b93ba205 -generate_signature 878f172b5f34e0b18a55df0ca544d7dab961eed79e07fc4689a0a3be8b3ecc72 03971f351d3e118213c1762bb564a2b56e3df37d3217665f16f5193fb82f8a5d 213d506a9731bcdf5bf8c3968d89e7385ee573aba69d1572c3604cdc29e9a200 3938dbbdc1f3d9301eb69faef8997bf406f7dd811a047c721e33986d159f3b070214cd952883adda3bbe9906b818b4375670e1f5dcffe14104d91b395defe101 -generate_signature d5c32a4a81da9af917c63f72b91c14e0a8fa93413572b702cbb3e9594481deb1 b558e0724567f7b4b08318ffe6b0dd0b53cc4a876ad1530692f286b068d19f9f d5a64d1b5c47ae79629ecb770ccdf0bffb1148869360958202ddffb2b5a6340d bc781f0fac469bf1cf36ece152f554b5f325e64625f1b23ba28ced2c47253c0a45acec1edbffa92ee5b2053a119124aac075a0a684fc8c192e4281042500e70e -generate_signature b3f0024e9682ccfeb0d69b0c6d2f0911526899190e7f0fb4eb1e600da16aa63f 019ce545f3b46419d987730c551e1787ccfa158bb42a8f203631fc211e492c6c f03757ea2d5b66ba968b93e5109593e8ec7f4c6809f15c6f6d881b1f76435909 b0662b8d31c13e202584a8f3f524c3a32f3c5156399cb2c941768ca348c5500faf22d81f40bf6be393615f47a063abe63664090bce0c1e86d43d6887cd76aa03 -generate_signature 0b18efa336170b3a6683dc486d1f36b6c4cbe86eb310388f71cdf70e143d0aec 987eb3e73980b221b2524179565720f451786f8de2b3407c8b5716ef683c15b4 d3db1e882a144f312d1dc307d8bdd2eaab5816804329bc36430803d23744530c f4591ad8762bac85c540c6d4bc56233bfafa00217d914604bc2a70bb3466c00b64f65d79d07884123667d1f11ba04143adec52f56e34e8f62c2e9f54e08d7204 -generate_signature 69ae4cedd012737619b29be8065ede9f93b324b50252024d928ef04c543a79b3 35a734465352db4e813f76b446da1c00dc703317f1ce52c8a35a0cd571074568 ebc39ce202ec647da79c7af3ce6ddf307fc44de800a68a255c2e7dc7ff997204 548dc54f0ef555150fe479752a77bcfd9f68bbdc4d80a4d39277e789d6f0eb0447e21e023dc2d08ea5dabf2ed8c73deccc57ed7b38da5f141db2f7bd25c60a0c -generate_signature 065fbb38e8325511ceb9aa041f32aac98a5dc8cfb06a85c98853b25cdfc47057 281b3c8844fa282b064d56acc83e92c8e6568c3a628645f63e40a07aee80aeb5 bca17611de2f9642df95a938f64894a4079ad06f842cfaa9bac087fbaca3e70c a1cd7e79b21d9d740a112ed49167b9e56fa4b618680a6ae3089d06ab95f8e20f97b694a587a2e43640fff2278f488e3a7f8aafd6395cbd98ef5c216761be9904 -generate_signature c13ed90a542fd070e07610a0fee13cd42f8753f3448591ef9c9f57ad721fe9d7 02cb435d82524b0d03853e29c7ec0920556b85fa12886b063cf64345dba55483 e90a0b4646cdded432d27a6204c67a76b8a3db2dfe0bb2ac6957d68e6aa72304 26469332b2791f8178c8998d738b04d405522643014666a81ade8f9ffccf29024b339f8dbb46216e3d077ff7417ec561ab7912143248ab4dab6f7355efed6a04 -generate_signature 7badd2f8d2dd8198990738617145e90c87880b95d5c875be0cd7be0dc25e7839 240b3d620b61537d7fcbde252e9de6da442bdce4e24cf4bcb9d13b50206129d4 9d9c7c91e5d71920ff7db53015814d4360eb7e398cd6ce8233c2a1dcc54ae40a 39937b610f93007ad70b22d0acb3b52ab42e2442607870e18c6f4ab31b22940366825f88437798285b03cd220b0a3300258b0f0ea996add9892e427c3fceea00 -generate_signature c537ab8551726c4d7ade51835585bf7850fbbc1d57f9245fe1b29618e2aa5c30 1ef9913d379ce22e9f97757c68fc5414e73a27e69a55ca223cb5eba854888d90 c3f5baf38db5121dfb177a0cac1d6bc423ee0c8f7c1323d9b691b07489006b07 75991f162cf2991b4b9d8b9fb1c04821a8edd8efc19f76410655b64e235c450fd2e6003a33f13a58dabd88cc5731dee3b9bb17cc56f83a5ba52618977524cc01 -generate_signature 696aed47faaac314742d0e6386548c68617dee798a83105d3746747fd06d0cbf 279e1bd9754759a921c232f37d744d7b57531a302245dbb54f95259aaf923c12 28bec44d3dde67ee976fa0761ff650fb0d9ac60e74725e4c5ba3d7a0575eb90d 12feb731bf04c38293aa30b77c2f00868646d26c08a7fc9eb1c341ece5695d0c9f9d80580972a86a3d327a938fe95115ae113d8595abad0cf4ee1aab460b650c -generate_signature 0215e850ee377ac137b6f9ac06809bd6cfc31918bd0a372155f28d45c65eac25 45621dd9f0fd09053bb23b178886d7f258045154ce90a9576d708f0d92ac656e 0da2f7254d9796a93c9ebb3fafe40d398726941e469c6f8deffc9c32c2b5d00f 12ac07a817e0f19add9ade660c64c8f31661070859379581169753a30cc92404326a55421cfa2c864f9b7555f0f5e4beaa03c64ba16d2d2756fa32efd8c33302 -generate_signature 877a11a34fea5898e4643861721def338135c5cf6dfe1a6fc6777e77fc68d245 9e47630b2a88e9f86555a6a8462a435c0ac2c45bbb85115add2c4ba3dd578031 a3322e75481f1ae1eb9828f57a2b4cc1c786167aeb54547c36c936600747ac0c 705522c688f93fd8baba824ab73ce15588fb6e160a71abb9667639eeca0d5a02dfbccf5ad9c34d80fb194739d945fe328e436607de135244a43f70aa459ab10e -generate_signature 191a17e4ab9fe35c2b1ff3190967be43353c62dba427e461cc6a2dca6b12228c c7312755cd3546fc800b0af704752069cbd24d4d132f4af435c149d1024da97c faeadb6cc780147a42bd6d1968169e088a0b5b5025171ec01fe7ce17155b7d00 6502829ab5c8f077d473ec70b50c7145cd61518e6efe4b2840009557e361f804928acda8f80037f48cc7da3f93056653a73c2dff82d269442895d79d8882c70e -generate_signature 37bcb62ac859e2e85caa766836436533bb47f58b8748f921d3b1bbb81f9b51e4 bc46c4cd6ca4c15d76864b66439d46e8f8ccd846e899f18ad782d6a3608e0c49 28fff080636d9950ecd5dc362736734a75a72851823c7e01e7489b28c462ce06 bba8d06542aa7b119265acfa49aafebf229ffa8c63c6a95c09e0e2d01f461e07936d7f0da1f92cf5b32294d1f5c8d62f455d114cce8f53539d84b6877a3fdb0d -generate_signature 42a48c4a50b87313860ea656a1df5698aec2a2f8d03e69ab24c7f9c7f7f66056 e4e4c0e5cd007712ed5120892e21b0615217230b1370f9a531192e09f5463f1f 0f98ce51f4aae0b3c5c549fac5d94fe0587e38f298354f36e6a259843322740a 4cf47185f64306d939efb8e368a61be874fd320758c1513045a4c667bb10510f3e454b2b83b451782a63da46b24be69a83226ef0dd5ee5f4b757eae763b53801 -generate_signature 2280cec561410c47170e37a38805c146ac1a8b73c1691537fdd9d10a9c430579 21ffbe4f3e0ef3bd589689c0f2c35bb702f121d83d8d1ca62554220c1da72e56 a2cb2795994ed3ff548fe707d64f59369cc6e893ee2ce9830ffa526b2f41f402 e19cd4211041838a1ddfe3cab324e14c537282b3bd9b0344ab1b9dbaf22dca05235b6d085399858d883c977140ea3bfc9b6dffa2d3c1b12f43b3946ea5acc70e -generate_signature 7df35cef6dfe5607c06a64a38510e5c42093c703a88d5d76dfa97b14a0f6add8 9211c6183c199f81e344d3650c92b83c96bbbacd6ae654d8644b76a21611ae07 16b3d5bc1949ecae9e4db756c129c71889214a5af2ff78aa8a479a0c5d0ff90c a3c92bd6865aef52b3628faa710bdeecc44fb1f0da779d9d9c02c3a5ae7cd00d4d9229cb46fc73c4c2c3327e5c0f5418e09b1d707e93a92efcf40a7039295a0b -generate_signature 4991a192c5c493c47372771fde392802036834e9fa14ebf5c4696e40420a4c39 61c0eedb78215458d3c724551d7220f92b8f70aa656514de7fb209b26728a083 ff600a4ce0fabd6602b51e9636ff9b8b9e102f1da91f00376aa2e50411deaf08 1922bcd73daab892e6a580495396892833fd190e8eb074a26121a62b49a7dc01613318d3b418a5fc243d4d50156cb7fb5e2b5839116b0f4808ca280c38738204 -generate_signature e9d7fa57a984dd1d9c7a93125fe69f4d408c821d7c17d199ca494d16405c0daf c536bcc2db715ae003881137da965ff0e30dbbee0f4e29d5a439547b8cd48175 1148d655f1e23fec319f04dcf5c5ddf131fc182b50e39334ec0f312e25429700 61c507d190a114f2a3ab92463ce038563314c164c327c1c37e7b1530f33ad505376b070639bc51423d12aa326492894c577c3c511589599ad1d293c0d7ffdf04 -generate_signature 9c619840f7234b099d0995b905a15ddce999775aa1720f0bc9477bbf0c5525ab 4d8720590ddcf790a1baac573dda9ddf0efc21223335b15a23189fa67f515ea7 dee02eb9d27969ffdbe6f7c22642936e5965f3124fdbb0c51b1c44856c075a04 645d6f8120f7a12bf694408541a72e5e1c08085f4e2f63815d19c8bade6299057093aa996838bc753823d01bd3fb9543cb94d289c6a4befe6597c319c7993e02 -generate_signature 4e5d10eaeddd0acead90bb49b03e73b84e966bb05d63055031cacc8ea5e49aa3 e2c8684aab1e9860370e94d295bac00283208ebdd29910d54c9a28477daf6551 4487e8f01f0ebfd7b1870e7a1cdcd86470fe644de11161309114f120683b3509 b2b1fb0378592a0a1e8d4df646e96c34bd2647a3f5fab66318a9b686699d340273b6c8d482c55a3dcb559bcea7a59ce37abc3f71d9ec403a3f519ff5789f9f0f -generate_signature 8db465446cb5848044acf5826a3c8baea057859846b551238a0536dae39ef712 f3a88b4793016d12031ffa76a5da01dfb771e9255e8de871769717199b83ccdb 3ddbbf3cf5f282afd370de5d33dbd8464b805bf4d7c74be2410eefcb5072da01 0ddcc237fcc5c3a08eb2b5fabfd440b7e89cd94835bd491131a2c71143962b02765ade7dc00ab791af75f610c6124e15d11c796e29af8210014655a08feae904 -generate_signature 24979bf7adb7f8b840a3524c3d3bbcb73490e50e71400632d824f420427df802 78057cddcf685984606870f37a2f0d76e4ba59d169722729695edf4934528856 fb691338b3fe0cd1a272b7ff7e363727c66689c1c7cfca7c007a5543b3abd401 8ae1c701c68851de8a8af85d420c0d1953ab9d05465979b9ea009d54c96cc303b1bb1d12e471ec77109dab9c17a6806caa1c8c2c9e0702f3bec8ce16f786a60f -generate_signature 8866f2c3e0566f73f173a7e0f9e33cf8b1795fde4cb09deeb1efb17dd82ece33 28c508eeeda24bbaa55dbb312f534292bb1d8ca09cc34ceba36a3db1ae5aca9a bed8a7e6bc28ff86ed87c5f54d91f8fd381a2fa9057b6d38b095245dca1b3708 8f718f3e412d251bc6b2339f9e66632bdf4331236e8c4107d73879ac26bbe807a50e5bdfc96b80e20c6f5547d1cb4bd07821c7cc62b2969f53ad1cd37d3de20e -generate_signature 421c152f337614c5a007b4eeba8d4299f7fab313c1e4fa935048288d4b2531d3 862b1dfbfbe3934696a9ad41adf2022714feb99e5a1936ba2dd4cc08edd7166d fcc52b66e50a4761eabbbdba3fa82f2e391db31ed1be585ba5a936c31dc36400 90abd70c347048d47bfd4c7a8a99226f339706cbb60f6c0014b28ad2674be00e5b8acdfc5d3d5c47cb3fd7c4430ce61035e3f227ac4e73bedbcc024d0269e10c -generate_signature cd4eaba1978fc73de4114aca7dc6708308e72a8a861c96c2eaa13dd06f2e82cc 88855b172e2e512fc6ae2bb6e1252670210b17fe4c021f97ce7245ef5e0766b7 fb333a06054d22771b8422f547838f14f4b868e6c0ffc7abaf52643b36e25a0d 4e9779439de8cf8f1f5f52cb204affb110829c4b813c758d095705f01076ce0303eed8e0dc54164f580e7dc30c4b954cfad72dc474a4ee7d5906df93899eef09 -generate_signature 38d2cc1cc489bb0af029d12f1ed624bec71d68c0713f1fd7f5d367efe71d72d3 3b3df37e4fbb3a730b5f9c5a1f7adc45dd2fb2c05d1e141d939536b6f55065d6 f10b5d6fc5830989df088c2a1a9bdf95c37781bc8990b95beeaff246b858770b 8ab91d8d59c11c7fee692e1e0d89efc7aca705d0a37cc3fbf7189f3f7638350e5aff672891f3b387975e55699a7994b76a1e65729923cb404d75ab83e5421402 -generate_signature 017a5495b9f777b45cd256eb87cd298ae9d346caef147cbbb916d95a6b61c677 e8d23a7fa523a7d1d59d23f5929cdf9872ad01eb77347b076121b2a8d24289a7 d77e90cfc8bdced4c2957514ad1dd3ee2b4e841f843dc2cd711df92d31225801 a4d9d842ee79f9fd09637d8b1cbe3464257285962ef8f063065ef57576a79c05156b616c5ca01c54bd394bb03195ad1a3fcd16c06f35ddd253d356f91746f806 -generate_signature 5cdee6559376c9ce870c83b06a6492b019ec54bd0058c2051813cf600bdf25d9 a2def558fd26b3e1b9f1d13b131a324ebffe1412ac2d043f7395f060e35f4780 29e13e332419405883c0103dbabdd28035a4be98f8216230d4a31072ffdbad0f 8c7dbf5351690e1cf84235b8ba57b8227ca87d62349a882de275c2e83f44d8087e1b087fb19330d9b2fb2b144cd01b8801b3ad4d9377344953da1e9fccf79103 -generate_signature e5f7e794c78196616415dad78d3d07439809df7c7443e44b82e54c6faa5bacc8 6fb3a5c5d7b694b63f29ebaafa2cb101d455d95d1b30c51d2027714c6048d81b ce2794dac0a5fab2074829050ff0f631ed916adb97c110d1d9c01f11fc572005 4de61dcac6c2964dba30ca6c8d0bb2dde316f7dfbd1da8e18e1c200663400706499938f22cac48d0a03a7206e9bc48bc62cd4fc898fe3c9f16e65b059d36d705 -generate_signature 5283cc05c1a813496774fe331d90989baca3a8932ed5d6ca1633a96e9881deb0 c776290262741f162cc11cd2c6ac606330a0c53fa543cadf061d844ef306920b 7012ea2ec897d4db791c283cb2f878103fb6e29c831549f2c11fb306a3f33301 727afe80ee09679925d76b89d6bcbbf274ef85c67ff689fbaa1478eeec71bb0d142d8f759199ae5fa11e9d588c77ebe7c16b85e7a969c34fe570ce372c792400 -generate_signature c7769cf2307480649f60e6b97930ec24d3ad128375546675b9da306de670ab0c 3cedc8256aa3d7844139e180826e005f8619adfa8a493da9e824181e4cc007ec 4514bdaf0b277950569d81b5195c63f14fdaadf1156dbb3ee16f3aebe2cccb09 d21dde1a7f581d9582459e573c621a989de819e6b778b528c024ea1be7137b0ad3752080d9eb66364f9ef322ffaa013146cbaabf8876159af8d80b8c211bee0d -generate_signature 0020398fa58108e0b0e5356b87113093b1e657fc5aaa229a2cbed766a1343b13 dbda7c364135fe9237e54e87c742a1174d17d3e70a08051780ebe274e399a4cb 12160063e4e47b248ec37339a3e62e920b41da6ed6b9ef1dfcc1f48a17c0490c bb8c5825747475467cda1d925b752f89d51292ba8b2d08d2abf5ee8b993f3b0dcb63d6cb31358a0c651ea96d7ee85084291de45ec36ae8588a2797a147afff04 -generate_signature b1e43d4e2cadb0e60c8791fe13909d0226ddc2fbc5bd25f73466910ed0ab3f2e a1926c9a221e847a653ec6136e4e23768ee329db20a7a5986b51c0b35eb73d15 5b0d93ac7c30cb138102c03ca6b27291e5adf76d82bc88862bcb3af8df86d308 c4e83d8bb69c4826754c500f1bbbc42e146188ee476abb992d14d9f524d5430e254d80c1337b57acb14b45b0c2ada760e7d3e341e6abc92de12c1aa2e2e4c207 -generate_signature c5e0e0a1d97e19628730750589a954c02102545c18f7bb05ef3e9eb8cbe36523 e4a4af78733fe9a3b297bf135e8b57181d8c0e39ecf9a5a7ce1898db57b18b17 7d29486ba52c61fc5ba24e42ae6f1861f161a0063f102ae3e86c480b52d5a40a 97c123af28998c087fb7d0085b1979754d9cf8851c9e6be628fbd35869b91b04a03d59f8f274897b69dd06ed24514d6780b4d5510e9f4b86eb548e86d10c0205 -generate_signature 81bb454381f1614e7e5764e88664dc47f825d18ed5710899d1e5968169d7bf58 1bce52512bbb39ddb4dbe9a10cd12314ce08fb7ca6b20d8a0855b334b5416a17 8fcbfbb6f711655ccec1b456597b0ce4a5c81adfe9523721503d36f5d5be5708 6d7fe9b31473594ecdaaf69fc4f4fa21857bcc94882978af178bc4abbba44d0f11aa2838ad1dbbf27bc4bf7469e262817a36449d522827f750489699d514c903 -generate_signature 8c9949bde07909984cec9d462c7e1de28f0d47d143790a686bee51d4983556dd fb6fb90c091135388023524466045bfca011113099973ceaf2d6dc4fa0aafbbe 8dd9d958ef607e46a14f742e8581c903661935e2257f24e852ced3f7edc5ca0e 5ff8a67a870444f90c7d34984e07026c171a31cad991dd45f3b50d28069e7e08c3f13e5a2a238c82913be7d8182dd52ce335dd5b19980f8d063fede845a2bd01 -generate_signature ab5556f1489abbd7a0c8c877a18313617887be7ba186a8e0a2d50e9d94a578c8 e7f84cf6411ca6bba208b07ab26e48a09b779a1e7bc907ed587a1d7ebc39e273 601f584a65a16dd59e6a1b86310a66a11192cd5ee68a4943ec38bbbb1bb9370f 2a25addea0c69a5c989407a493d14afec4f81511ea82ec51e73917fc6fea950c8b30997a3b5e72de722d3930c66ec245b732c91d7cd1519463307cd613d41204 -generate_signature 47fb94c340262e3cab3ffb03e06695bfbdc2439807cf26620c8cfe4395391309 a5f429dd825be9eb1b76f7300754a454844d07d1627312b14c70a4ea4e4566ab 7747b7704dbf86b1d338f3d49649e43009e7525edb11e684294fdf1d6fbfb708 6a474e70bb7d0ff1855058a03a42139f553b6eae29d4822b901ca2ce149e140fccd8f98e14c7f8cc9182fe2b88d9864644b2dfc0fc26d2477e0baf9ceb3cb40c -generate_signature 6ba24acafdbcf7ca8125c560f585d33fc166ae363adc8f0422c2242f6a2adad0 b27456386a01d84300fe0695bcb594296fedc0b2ea31e1a176cfa49eafa0e5a5 237401f9b747baaabeb8d8df6f526f00a6331288118c5aceb343908fea8ff708 a139daebc42068703c73c9c8c2b5c0534d7f9a80d282be54a2522dd40ff0cb05f1023cf88611610f45abd326f17851fdf9f8d1a078e966c89fc65b8368b1090b -generate_signature c8dc5ec96cda8c740358be0754fdb8644a33bbdb9352ba63ba8c8ebb19f7a240 d9041763f43939ba1b6015c369bf8596a53584891e45b20f4031ecbeff20b36d 849e6afd48fbab23161a1dfb7d3b60151dbc4b288596726ac07b2fa4fab68109 e2613136e1e553778259c66401fef46552d217a95e57d1dc2c0cfb4921e4ed0ccc13ab2422bbd3bef6731863085c2bcfcfe78af97025e5e8306d791a0fa48807 -generate_signature b6d466f81e80d56104e09dcbc4bcb94e4f095ad48c635aa14f74c106ae57b9d0 005a126a81f80baa89c897c921f562aa44afb0a7f317e2cc2988197f980fad94 08042ce99fa8ff0a4c082fc1ba66bb11f8c94ba9ae38b4f37aa050a3345b2808 195e69f5b202fe7e5b096a0a75935a7f8555ea4803f36ef4ef9cd0c2ddb7170827ab7ece6c669cf144794f4acc6cfbe301995a2fc177265c3f258c958845160b -generate_signature 8c442d20262492d6075a482a853037319738a944e8ced7a26c236008348cd06a 1543c07acd90bdcc1ed42560b2129f52db09965732e1ad75da5df80f851e0a30 5abba5c682b23a2e44b9b426abcea8faecc8da15f0d124fa428cd21ab523490a 8cc7857d265d81243eff39e9921aab33ec737487c692237c3e34267368aabd0c291a0889df4f806e79e91256f67178a763afe05460438301a31ae483165a8b0a -generate_signature 6f7951c7ca70cbe7abe0d6befe5a5a10559b7d05a56fba3280266361a919b07b 2a08f949c037c51b3bc036e3779b6dac628a9fa2561087d15c029de399596209 77f07519b561abd91c4bf4a10be08deb641537d7503102d30b8403bae936910b c366fdd82651f709018875c712e5a98c9bb5faf23ef1fc38e1b31cf074d9b00e72c18d2b2eff556ca99db887d6ad230622010fcf18f773a5ed6016c1d19f190f -generate_signature 22b1dcde0d75d009c1f37df37ed0a79e162049ac2ee48681e312244d540b046a e340d157c047d55d82817a49b51f3c1d39a82d38876a05050dc5296c12a2b6df 8fbe0766b15d4fa7542756b1cc33a62bfe2da4f7f00ca30dfcccd7d63d6a350e 0d99f9fa0c628c56a78bc9204b7b1a8f8bc412c18e45f6036b7bb2b65012c207bd5825ba2a48641a1918672c134fedc6a9c3d47181a03b3508a2b5861bab8e0d -generate_signature e1552258578c4238b55b9c096f1da86bc399ebe8c55df9dd6d0468ce939a7695 98557f788cbd01ac0b77f5e4bd2c0aa65c58cc61b49f5842a53f898461d22ce6 7d052de95e7e055d117709ca3ffbd6294edb2b0698b549f623327a7856d18b0d d3c98fae5f8da3441f45e5ae03ff4f1271938ddcc94e2f29353e6b591e74710b476f6e89a706ddfeb1b67e315f58ca516adde708c250393498eef78f07c37404 -generate_signature 9ef760bfb089f081576ef619c98fa69e80bff76db56853759a98359944af31f7 1e2022577b355dee237be685fc8704c73ec09fb448ce3ac9224c7cb26ed7cac3 e9d5ed5d17eb81635b3f44bbde735d506a1b1002fc963369db98c2da1fb9990f 90a58b604d5b1b720b4a797ad74d7da0993ee84b40d88f031d176da5d4d4f1056407367e4902cb87c789855c93bb39c4a74bbc6e08dc20c4b659dead53bfd002 -generate_signature d48118e8850b94a1d6536e8ad26424db5ff6a8856837b5f2b759991cecc0ea79 76acc258e905aa60091cd19a0453c086bc63fbe6a9b9f9713c5a59e4a1f65735 e7eb8679919eec79d95612ea8d4f42d3dba03c92997a8db4ea7ee670bbda580a 8b0ddd2d0e9e9b97505aa443be20bd7bc77038c15100fee0fa6123caf3bbaa0ccc14e332aa3a7be9052719c3e200596943bbd27cf64696d0a437f6a137fab70c -generate_signature 95b23e89020f166b62f1a0ee717a478c07b3c96d697a3a5e1eda873c407511a8 8d7c53fca9f208f436d9b1a921daa731f79e537a6aa1f54b809aa4ad9b33b860 b702f52f1dfe951d4cbafe535089128cfdf8e3c62e95238614d230bc783fed09 5572be8bb8a2ab96f18d54837dcb8be02bc2c65091f3a8f30dd00c0907a46d0721a0b578492273c43dd256a7260690831ddb1ac3c7924b4f214140b76aaf4107 -generate_signature 73017e127a3cd7c8a9f97f80ccfe6804c5bb683b22b6242a307aa84f2b2e5663 f17f920f113d54ccf8790951b2963d35165c852ed0cf7c6f5da3c1af2874f7b4 7dd05f2bed1ebd7b1bba8060fcad9368c9c114e49ff553273cdca2adbe5b7c02 65a02f3ca050e4130426df233322c51046c0347da04bb4527a18848aded1060db8b12909341828014027287bda5e8bfb10e9e0501c8d077ab1139c84085fed05 -generate_signature 5df7c3d6ef2ed1b6140e0c52d836594ae75adfe243cddc0cc11e253674ea1d3c 5d45e0470b6d249abde6354c3db9e980c56705786c11bef17f94a31cf7d05d95 60e30994ebb7c53ad955faef54e0abf7d7aff8932af097db250fb56099712b06 8297fac84932b47a5ea32d0f030aec465b863a89d8cc8f67d39594bcb887e2011b70b6f270c80731b612193ce974cdec769183dcf107bd8b944f550a523c3d09 -generate_signature 5e1dbdf1b13c9e0be80b4f4e10a2bf29144fa2e66553e81fb50f2f7b55633f1e 4cb10093b5c9cda140ec668a576def490cf7453635bb4921cb9ef8c8e909ee52 067e27cc60b9d9da528aaa8a48ee6cb30418189c8f6bb0d5710dc1074dfbd605 dc5bef213742edc6e1790f5d755b66a09631abca0b31f433806eb7ffa038b707f8b430770c72ce06f5bada556a2d305e56119a2e96577636a108deb5c2ac8407 -generate_signature a08e5b2e08d5f1c70edac02d97b7174e348c6d4bbc201485245e8578efdb2f5b 4a10b74ec6c5ba4cca27a473ff6022c3618b2e3c24625708add88767da62e3f6 50262cbb867b9feef014c6d0f301838bb92b66a8f2109e67d036129096168900 98f69d3e1949a6074e0591f826d9c781e697e7bd4b61a8aba9e4f6954092ab03c1154d32ffd177de61da82df4b051a1d764025f5dd6b2698372d44e04a087c05 -generate_signature 07edba63a2c0fdb2e02bb8b8e6b531d2a542b0674e24f5ed1f3ef2583d2d9eb6 8c1059bbe4a373948ede638667da04f8caf05aaafecbad08de797a804f2e65e3 abdbf74be8cba1d22bf91057a94b1f12a063acd976e4410152a07de48b290b00 b7a94f9645f804354366ee550d8ec34d0cfb9379728b6ba10c80271752d76406cd9101aacdce3beb15f8600ff2e98f7035a1ca5c1c42c98b5700e02ff354d804 -generate_signature 5dfe35eb9c70c55e285e3e9121651110e8daf329a1d3110bb342341f0b13e285 898082df3ceb5d2e96fd5400b22bc169e04d3ad581a63de9ea638eed30a1f63d 1e83a05b9ccc0daeb952e2d6b5cfdd414fca43664ed0ecdd30c5eadf7a8ad20c 67a177c1f3a4a3d4781086fe5a1c452a5ed8df5f3ac32a89c32c54f23b441f09aa749c2539584cbf6927839dc33d08c5b93f95ac7760ca8e0e25d015c7d6e101 -generate_signature bcface283643b5f6fa0140dafff732ff07f4345abf3770523489ab4ff2731c58 85dc41f9264298c7ad08099dd2b20682dfa4c9798e69695f9626f644ef7c7980 b23d6a04cf867f63aa2e6a26784d5c7a00afe68a37af3069248177b77b50c506 537d655129d447345c89dc76ae04ddb1004286825de2deb3283779d188e7ea0230df1c620660d0f4df07c572ed6e6c99b8d072e6f8fa096fab174b2349d21a07 -generate_signature 79444422974fda912b29426d4fb4e8900953d14b8a04b2b48a3370fbf6e0d34d 55c8b685946d2e1720c290ff6c2bab2643e35f6edaf04476dbed56472ccfa242 eabb6c32344af64e15d351011ece8fb6cb2309ecaff2d43d819f59389bf57607 32033a5fb3bc9eca2153666445a6a2b8c699f8204d28771f52612de606ba9500f0c194fcfdd61fff79878871752448d032161d1e9bfd5d1393203cc0dc08dd0c -generate_signature d2c081f5d9a76df2448bf6aaa021331d6e0fc87e31b6fee0bcdcfd499d2dd94e df1afbf7c09126a407fc34b118985ccf41c4e82427e6dcbfb0d3897cd3705d8a 56db60488923ad7e0575b143e71ce05d93e6d273a5bd445cf74ac9d8336c230d c736fd99b281712a1212086ac772cc29b0f4cfec900467802b7e12e5211e7802fcb0541900d9a3c9ce8383ed1e8f01d8417821503576503c2e8030e245030401 -generate_signature 8153ce2a925a6437aa445072075b5cae447affcc86b452290e5aadd91e446e9d a504a848e87137e24df67b8330d7dce41efb6a3ffe99ca69d7a2775bb4ff66a3 58a649099831b7343c6800ced12204ed25408aa9b1525d2f8aef6b8a40cfa908 985b0fd42c384ba1376b0fdbffc9a2023cb5201c74465e963c1ac2e526378a020171ef1b0c55db424db2b49a358b9b081141a60ba98f7086b0c02a084dcdb20e -generate_signature f85e575bcd9427a761197581a05d22e3784e602cc471d88ddef5ed4e6ef26ac1 e4582873da79806344aeabdac709ce261fbeeee546d0068c3d17a64527aa1cbc 1090799dccb3d243647defbe3ae894d316d68d4539a134d8aa86f3a4116be203 8ef01495537f359c3ba907a589b2573ec7815ddf3a036fee401348c6396401037af7d6845ad871f268e837a3f5f787d3aff09996a1671de340a522db90e2e30a -generate_signature ac157e1a76bd72924e77dbf97e15469a4da1be6d154a8974aca1d77da7592e93 f4005a9e2341967cae9307f262d87c064163d0997d9f039a2488fb044d449604 7f8c5592166b6445aa14fa0b765d3908f8ac9af1c6de0f01544ea95c487e9c04 b0f7b82f81ce75f0efc950dbd91e5441cc5ebaeded0e219f1e27c284ae0b29021ab13a375ddcc82188e714809ced5c71cc9421155cd8a55d5c327ec5a3c8340c -generate_signature f135a8ea135688e2cf612a1517c305ba88b556d3d0f5c3cbda706bd485993c1a 5ad2fec0008abc302e993a7e03a99358e7113ad6cce435c81d440463e39fef88 5a0e0b8724a44adf7eeb27ed8cdbd6a11d9f1a00d0729f6325910ca6783dd500 ea713e35ca9040e21cbfb9cecbcf940f6ed77929297c655165f874a8b75b2c082ab4d576b1f2628acb419b520f9d3e47705842a69c80665b4562492a3f270803 -generate_signature 2f37a11507b767b81357f9d03bce2d6f92cbd79af252ec737a2126e1f1a59fa0 2030a8eea7a816364dd23b81655dbd00e10edc8f40b5139cc49506db9fe12c44 907f88dde3d47b78945ba4180c53fab25024bc009aa678b34c6958c3af14a00d 85edbd0eedecd157d416be391fbcd59c075df166a9ee4c6f5c196de9da006309e0aacb072e5279259b7c39357b4db00bb74f60f9b543481aa6e4047eba52cf00 -generate_signature 40f923c6bbde2b5aa8ae568a53594738edcc102ae77d2eb2ba13250bb3701aff 3d0d965e35f87612a3d53ac8b62ae4e7d4aa2f1cd3a6fe3a258ebe91457a810f f88b02b56a6d583e5ee52898fd7124270a1de3aae61ddb45e3fd4d272ca49e01 cc37543dea1809a63cec611b8014559e7ec8b809be43b555fd251d095165a2032510695f9867aefa456c6c97c2548e3f931783a033d756a90b984004998dea00 -generate_signature 3c4a9e9af77301f53f078bb5780d71d3b14e55457fb26308647706d88e7e8ec9 41a6ad8332efccc56dbcfb936c84a1e608467d9f58aad447e7cedc9c091b8f33 6ae28d2f4d72100a1638132f6c363d2d65c73f2f6e9e6ef883775ce3eee94401 8ed9b2162d0ae8f284eaccdf5054062251e8683a4f092b1eeb14ab47ecc5bf0d38ca546b4a2b37a58763e7ee5c97bc5185e0baae593a85c5e9a7e26d0c491b0c -generate_signature 6e361cb98046db1c58738f54bfa5e24003ad2843625089084112d3e956781da1 a40a310dbf5128eb712aa9ee5d339f8c0e78c90e8e44977ec83a6138b6191627 ce3e7483fae52df03b7c08d8f30fa43fa505f0a7948889282f5e46b0882db500 28ff04002010f15563ea46bc3bffc3be7624f1f2c6356216af436807fa5a7d01f6d5f737e8d24fd52cf00da44c2af6333b3b1db2c356f9b6604e5171906a280e -generate_signature ba7df37a2d75e962d42d31a91525075ac836100ed1a78ae4e978afa432a1235a b4ccbeb6c17e719c79942b74b81a3cfb5ccd63e0c06b12fa88f9e90cd9e8a1e0 a35bbaaf8d8fcf421d4307e3a52f63d382b8ff35c7f6e5f7a6eb0a7adfd02f04 8cbb0917f41e745c78d3531b8f7e0ba05bb0ace0ed6c89d257943a156fa90604a9b1abf636c591c2f355718dbc203a22ce93301e85027a99c4d6630a84afca0b -generate_signature 81599211da2f1378330d2bf7f86e0686947fa402578cee048c6fd648a909f2b6 865b484252a23a1697c736ddf81d44674d9b51fcbaaf5bddf88061402ac65189 8509f1f20c25d821fe6057863277222b54399eba3712721c82c174d81650080f 598064b49145d11cd8d1ab8d2d0e713422a63cbf8e518017001a17701cf947096649918903eb3b025cb489bf9005c395c91ce69c9e02a88cab281d11b2a4ae09 -generate_signature 9655414428a87d11c0bbed9af0bb32010c4847cfdf75ebf4a8c73c1d5500f44f 53bc48c7306182d958147ed4510dc3c1e5b3ccfc16938f1a7d757ce7ca2fdeac dc1506e5b95e1d6e6e06ecceb4b8cfaa00daf3d6fa26fb672374ffeceb0cb505 5d34f44b0fe9495d3dc8ca88b622c59d425ad572ac3323b66de955018fc47b046074b2bcf0a4b9e1210704f289669d66fe3c249ec18b81f94b440d23e43db50f -generate_signature 3e1ad25eb7a1dc33c84bfb09d73d946aee497638ea639157e1eed1739bd0a84e b507cad326ce68772dd3cb43c31bdd70cd71d722bb551d209d53449c232f5055 c06773a6b15d1409ccf3bb4182509cd418fee29a93d966c511809b19eaae4d06 ed34e9763f481ac9f530a2300a2b2408f17d2ba824238b5b001548911a8ae605e3d0f703fc48090f670131215ae93226aa201a3c2b2c57436e29437ec5176407 -generate_signature 36bd8cd274466d762f8bd459e5f32dbd7662fed9bcb44b76276e793701c7f5dc df9013de104e242aec33250ee64a3019fb7ad37bc06a421c60ac21626c9ddd6f 6342d56599a678fca61f584facc41e316f0bf152165767f50e3346b7ec74a208 098e0c722c4e5b695884e0e9d8db72025f782f300ec65d50e28d673f07f5e30ae6748341058b0710230d6437ff7c03f11ce89e0ae2c699880d008e1372d7e80c -generate_signature 829f725bd1ec12e3c244c4b0006499fbff693b33d0797c043334ec591a8d64d7 fc559b71cc887e98088cc873b9d7c69d104276e257cb28197644f49e8854e69f 36228dd0b09d05703d7f8b5235b94958439b8a95b43c8e09b577a0fe6b26a901 b26c169aa7c95e62a447bc55d495cd624a36446066a5fae340f58c3c0af69108747c9322f2dd55deb910ae261d458da4e8977129c1648c9ec14af92477c45605 -generate_signature b2fbde52043e979fae4cbfaa1fc218bb87b87b21410c498be62c5b288f0a59d9 fa437eb7611028c6141280c056fdcdd20912575cb57d652f78034f7afaa5e0a1 df1288522dc2cbca4473941856c0f24952f69b5c9efbe6df24396ae25ea91105 220618c019f4e7789d59419056198a5c96385545dee117b50715276a9def240caa09e94601ccf2e5febdd31ef445b0536dc64835c320da8f5d557b05e0ec4902 -generate_signature d21de662f0d58c9f746f0984fc3691a3d0bb0776e539a2282207b8ebd8e5ca85 679397579f31b061479734bc5fb2218c577503f35827c815f22bf53761c272d9 b04aca24dcc7f0c6d04c3c676a6efe8062fd5618d16155ba2a0e4d0485332c0c f83ff67418174b6d532b1e19ee545980a04bf777db1135c4464f8908288a6500f134aa66add8a9d075f40eda38a673d00d3df3cc1c8b77781aa79d64e7aaa808 -generate_signature 44c6eecba5511adb489dfb05815e764f933553baf1acfb6e9cebe010337b24c0 a08e4416e02f056c71ea72e2eb1f8a89f669fbc225a7254e4c8d0f8d39ebd1d3 40f60e9ef735a23ffe2ac767726ae743f2844fd7e8981a96cef85096359c230b b57c11aa25f65165904d994ddc4c067b55ec61420982b193f8e81394958aa20865cb62037440212a43c99d169b1ee478195f9430f887b1e6bd3f8b1a84618c02 -generate_signature c36bf112fe3f11d4a33a28c8f7e96e18c0a561eda487ccc7e441439405c5b339 5d764a790fb3442a21aef48510e95dac552d0f34c2b03289ab11faf21623c451 ec45f5dcff2cae290875866dcb122645d1b88cece607be63783c3e088cba410e 518393c79d1a3a0b5ae250a27c0b7ee8b82a914612b272d9fb45797546fa0a06b185cf414ca709da8b821ec3059ced87592ea4e7342884e9c668e7ce94ee470c -generate_signature e642c5bd2b451b20aab856686bab22f6987a7b5330c2491ad9d43059cb5b17a7 e5c73f7ca70afc4019ba044c177ab7ba3b57070effd788ec950e23f766617ae2 1430d7db432dbcf48c88f489017aadb6bc4a4dd30dd68245e281359e7bc6610c 46052008fcab7b25e4359e1345f8be3bcd3a1b95c195dc4fcfde127089ddbc05a4aa6fe16e0b9ac5be528cbe4e0f9fe1879d056ccdf0752db1938127178e1202 -generate_signature 0b427120304ff23f1906c33972a5ddfabc833455e1c00b4ad522dde15f401237 45df3d7b2ff3ea6a638a360019b6998dff96ba9c11ec454fa763b75ed9e21891 07290dd0ccfcf302d33d38e5b943f338a40e63fce395f47984e7edfb617e3509 ca2c0e4daaff01c720910cc7948ba52167f1fc98c1950eb80a125f626615200e477a125c37a8f71afd9ae9ef3a949f9a07c9b252ee26f7feb32fb30ceb62330e -generate_signature 5ada550217e164eb59ea6506858ae1ab537c9cc15d362f94570255e558911490 891681f48e13a2f0f2a7e189995a87f9af3f3b4aad553deae50f38455eae34ae 9f12a804897eef85dc4f89885958acdab399cea0cbb6c7bd2e2b40185bf53201 33ed93954590ebd70631c2d87c5360bb086ccc0d54c861d3256e697f83ece3006b87cf05601e8c37c8f6489a7f9b44c6ea6519aa901d30012068dab793feef01 -generate_signature dc200cfb46b99ed1789b022df4462e679fffde969ef75181470fe77d2f659224 a8987ff64be78dc7120fa7c7caf8dad90e4b8dc44597769eefc67df636c26062 4f5a3321915e3c9922eb7704a158f64d27d32192687412d28748d2ed4636900b e67fb58146ddb2ab786b9b6eeec4d27f940f05fae39abf908d3c40bfccc53103399e987219901700c5682eaa9490b025047bbc1177c69c7e9db460c7d20c2006 -generate_signature 7462d6b416e428b5c0ee3f90ca39575495955b720ad0e7e4c2955c1ccaae1888 36260bf759635f1628c16ab8a85e22d20d9554f6811bf2d7d2b0e724088c8567 2f37c7a26aabe14e904c61e256d5e2857adb8e94c3d28a57950bd68b5677f302 359e004fac509564560233cc6220dc6feb544e1f001b750870a9d05a5b70410aacb04b1c95236c62230c6dbdb7b3411e10c7f24248e9993ee7bce144f6657306 -generate_signature 51e9571c4b6814a631509d7b43dda8a19fbd9c5536c3355c3b9ec28fc7d4aea8 cf237efdc47a5fbb1063f9851704177751b2bb6dd40f35a35bc49acd95e11370 a37484d7875c479c3df673457b1d82b1d8fc80df5274aae7d1aeb39fe2aa310f 5157c7399de7cb42cc16040646d8f81fc98ae57b3247855858dab76b29ad9906b18bb08515693f3ef3079e76d540f9e36b172a39adbb0940f71a4cc15cf5bc03 -generate_signature 512f462d431403b24c18924eaeddf9d911d5c614d2a5e274c21933a136cd8e10 20f1bb98259c891bfcb5e11793ad38c2ca863d739f7a2c53bf5f74c9472b8fd6 8f92a6e203eb6d8ea988a11177aa370bf142928fb93c466bf18ab55b50492e08 60de330b3a97e9609bfe15d805202ab8f57a41b569b7538562586ec2d30aee0933bcef65a5dab7377410eec4834243e1997668ac9a2a86710549996a93306d0d -generate_signature c67ceead9a67e5bb1211538a0c96cb3605da36f1fe2a8664de0f134781a85889 25adad7475f476c9c02b9fcd3c7865d261e5da7261031256dea250c71f305bf0 8a451763e81d056b3622ff5db2432b5ac52a4565735d1f399d7fe44f409b6109 fac0c7fd890eaaf93e177812032578a0caae37b310555566847f97305bb9d509737ac895d56cddb77b09ffba78a3c1778ffcde410115b732b11d2f713224330c -generate_signature 8744e27a87056f551083b1240834edfdf4576a4b8c4db7e93c03bec8f714b842 ee8c02e0eb978f310eeca705aa7a4bfe38cc10a9a92e8458f5656dbcb22a604f ebba71caa77c769b5c0920033be75dcd8e1af9a19c97c4cfad52bd52efb3cd02 ea958d0b7abeb37e780241004e2fb8db25f6fcd886121d22e9bae96ac5ebc40902ed767cb77f9bafc9125a8a2eb2930bce6bfd43584165f93fbfaa4639f2ab01 -generate_signature 01b5d99e68a458de21c085b50147ba1f67b0930144fa77ee5d4e1d37e91da1aa a928416ec7f0a87dbded403c87fcb073528cd4f90651ab9e3bbdd14ca61b6e46 370f367e7ea29b50ead04f5195c6b0486923c4e7109c8fb79b1059059378b302 3af8752964ef33888081ed30f3d4120aa6d7b1df1db8b2ca246ef21e68aa650452341252e93e7d5e906a7ddc06a56b18f5f99f26212f31e1639e00c267846503 -generate_signature fe682bde8ff2a30f81d616c05b9b356e32b3b6f11fc4f58c133d7b9082f3fe84 dd191591dd57a04d33124ce1af1ada602b3f5304b15d4a90aa0732d72742f501 c2b494b0c63900df29f46d4ff2e56a644aee5cad4105aa0123bd9809d675df04 f62b33ef2864c9d3535938d4852a388563ea188624c7352fba3d557dd9f568028e00056bc1a022d0df98dbe43c09ff3cb012a4b9d628acec222c2b6ba749760e -generate_signature 96a71cd74467e3b95e4dd8874535ab8fe7710ec4956aff40dae1e7849bcd4c24 c55e53a61395c80d8adddafc2bb1224f1e64ca8014fd13d809c86d7b5e299e0a 84356cbf4af292e87e3b7fc328cfe45d5bab67b784405de76533fa4fe049d702 b9fc15218a12c8c4e3011dcef1c0e9a223f0e1c0aac84727216185769e887a0a6585ea87b4ab6163f897d47fa2c245d1826fc1fb4fcfd301c8cd36eff1321a08 -generate_signature 7332333e4bedbc6291e64c3acb32779b6bb94493e83e676da1ea8e7ac593cf7b fc9dd303f58dbb87fd82695b463e1197a265279031cf9ae5a6a7e6dafe2f0fb4 9fabb96d4292617086a3a9c0dc084bb6118f73eeb602a6fb3082a37fe6d7a40f 820c0611ae2d1ed5b63426b9a927de46ea98aac9fde0d5ab4e1528da95fd9b070bf88d17158fb76c96fb0ea53873db6d982256e3c7dbfb2ee32b47ea795ac80c -generate_signature b15d619a2e307fc4e1848688c3388deb8f2e0eea38328cae0886adeb42474204 5d2eedf3536c0d1857d75190f3da8f9e214dd170790722c0ec90b5876f46fa1b f107b7b3f7e17ed25504d36574d01318cea43a84b0c275d097ba0cb83e872601 a80d36596e68768a67a49f82eca4cf829305da2881cc5f06c4cad88a6702470cdc184b82d209b4568f7f22c944862bbac4f336a004b561baa78a91f74872da02 -generate_signature bfd9fa1f474799d11ab3ef3abae59c17b300b8cb899b2fcbfacec678cc77bdb2 362bbd5e5c95c7e1adb900a3c6c5a67b5f050e58ceb6917bfd037abc61457f23 4bb72c886f3d978943afdd5c1e53882caa6b323e0c0836a1485156c569c2b604 887dc3e64c5fad7f37794818ebf4fd319560b637e5387907dbbfe8c569e8de0be34e3f2728226f28fb66dd8f6be93da4223d289f55c50b66fa23f30c0cb7d504 -generate_signature 3b8254fb834017e439bf4c9db7a54b8d72cfdfe734e64e3db94bc42761e52a64 3f1a3561b18915b34bf1b451fa01ce6b9e2124719b4f3843da1caa106f5e724b a9439b2e768ea849b35fe3e8f31fafd2460343374600031aadc7a047d8f4650d 570b9687c0cdfa89cc409b28bdd896e71d13a35169ab67eff7a9cc0fba83420e3dcb2ec7b42c81166d1c4880f4462ff84473c1c9e3889c24c4caa8aff322b50e -generate_signature eee51b7ed448e86eb34c493bb7cde32b654a2c3b94734b54e313b44705736194 9cf9b0c581562977e791eaab88f9574ac7e7b173077b3e67283fa00ae448d19c 7e0763abac9d638732d9cd91c7662b13b14067fb458dd8c13329ba76d9685a01 c3a02a98e1337aaf74fcc83c83ca9db4016b5bcf2db29ad1a1281f267571b101449e9afb50bbdfc780251ec5fce344118c65730a54c99f5c30dd4a9c26c94b05 -generate_signature 4d0fe60a2d913071d88b67d806b451e5217b66279c8a366ea50df32dc7f019f0 30be371fcd62d0aa789bec1511074649e012bafde098d1997867cfd1a1c00020 14ae35724fef1e5136b485fd319f2ddfa31858c2f6e8718016ac61c7bc09a00c c30b2d22bbdad1d644beeda9621902da4336a0a03dbafbf707b681e983ea920e071c59a3c7a01f6f2c2c1dd4d0c1bcd089b02e509402579e6b96511d02f4f204 -generate_signature 52558464c45be054502fd7a95873356906175f45d96a123a679c61293ea82c59 f2df74450892e64b630c1bd242ad6d6eeb74eaaa37817359f0ca6ceedadac351 fe2330bb3f97ebcb29060bad76f122164f4f376f1dfece45ec8e1b74a9d73304 96ce07548ab12899a7ef013774b816759664c77b66340d9fc47754071d0bec06ce4356b4fd402974d447522307f0a29e350997d4cba56c7fe09f85a56b16cb05 -generate_signature 110cb3d607cf3cdeaedf72bb5e757beaaf33735c4e0a6c9d36e15c3bc44f46a9 299e119e03f8698bb3f91c0383fc2fa3566893b430c4181ae75da3b6db52a14c 5f8e1334f8edd3031ae48b6167b69ee954b2dc825d96c1a66115f3e0dd19bc0d 3519a213bd6d92898c750739c323f9b3dcc5beed7d87b374bb0e8efa5b3fe40bbe27cf0794652468c3dc55aaf4069c38b174043aab8db2553579e6468701b609 -generate_signature b9c72e905e48aa099d4618aa4be67625490d93c298ae9a3ad50bd3051825ba5e a2d1ca5b1280a41694c3378e2346b3f9ec16d27905a7d9f1ade0aead412fdc5c 2fd3f1486114d6f267cce879108ab62839c678eb46a846383c25904f47719605 38869854fbe5866df44cba649eec3ba9ac48b74a87fd445b89238b9953cf5d05d6a8b9f592e02745fd11dbca46b4026f8f77a4f52c37e3ce702f88514e54360a -generate_signature a61d5acf702d80aad1e60667f5186d692d03c291015af38ff48b3f627dfb6c93 794e3180afac94b50792ae3b11ab01c8ef4e02973b3c2efa5b3110d2cc5bc5fd 89a145b6365dbcd67ad36878174eab5d3278b2da8a0724fc6b9fff3dadfdf103 c1ff8f8badfb9df0e5618d7e5615184536733acf02c4b7f551fd1ca846c7a20c1ac285c6dddb3b067d30c57e693306dc4333efa84ac82b63d7d546a67fe58902 -generate_signature d0666d9f44a461d56c2c6c35bd098282042d7ab5b4138f80b22b98b940df2543 c97f167d5fdccb9158ab96824c60752f6a1034e163b96da179cc42a8d6f8cea9 443d72bd61cb9ce36ac11839333cab61bc85506b91dec9ae8d0071fe9805ea0c 69625e0ee4bff373f0c0fec580f93fb195c69c56f78cee8544429845c25b1505a9655db1ad290cf2a3b7f4b7b0ddac7da963fa0716ad5d04867dfeb44f6e8e05 -generate_signature dd4e6582d6f65498b6e6dbf35f5dcdfab52f90a8eb7ef7391111bcbe7066929e 1200b5eac5cf70e9c52da437ab1d7da3ad5f951f65baee0ba8aa02ffe69a3675 b72904a3d7180d9c2c16e090c52051ebbebe0ba8376e2defd850bdd698fb6f09 52d652dcae18e38ae04487e6dd838bb836baf5008a00e43293a972e10b68bb0c307c1272212b6f43ba86dd609aa80024ef2def3774c67cc7375d3ea820937d0b -generate_signature 6a1c4227f59b75fd001623aef3687fafa8eff103526023aa6676e8f08fe3c15b 1613c592fccc2e0031487aed9aefc3eb0b86ffefea0f014173bdb28acf4e8bb3 bb93bcb48a4efa8ae0b0fc9393653f2696c77603e9fc3bc1956473f04f64e402 aebf47ce25241355f9716c17a4caaf93b0c30b47dba5e76481ee1353c45a010b7f06061edbce4f9cf24033f0d55beee957c8b79fe534f3c519337ad7cb7cbf02 -generate_signature 2677f450f708876541bbae6ec7030aa87d2f7599bb4f669c190b8df2b62daf66 7a85581bd21fdad5609a84478a9e61a084ab78021c7bb0fdcd6c9efad8cfcbb9 26971f12134601802ef62ff5dacb99e5e0e08ea2455861e63af3cfcbb8cc050b 1d1fb428beee08dcdd0e056e7dff12298596e63139e2261521e1653c14a70b0795c6ecfc6a663c821aaf09f81d9453cfb57a056e7206eae08149aef628abb809 -generate_signature 15bbccb57984f152d62b0c82f12d732b75068118fc3062805c157c33b9f35741 cae0a132e7e32e55906039a7f510d940cbf4dc16543beb1004b636866635a5d5 6d16a1ed565e148f653ae3c20a978dea4f2bdf009dfc8d9e66a201c9d184e906 ca9c6492373de8523df5acc2995d5e64a041b14f0260916e0413971f0741520c9d2e834fc706c8f1c3d34ef90199090d28f5f18b08020e905da1c2c1b463c005 -generate_signature dba1e5cb897f3a931ca00c61296c26aa6edaaaa95d844e8cb29a8818e5d3cf40 8011fbc326c27242f794f1c93e7e616ae847badaae42e30ce345ee2054752490 9b02000c18cbce2c5bd97d9e572ef1124b710bc4bf820b5e740c6f52185fdc04 6bf32ef5a08b67abc7a6785e3d9ac927f7350aebc28fe816558cff2b643dea0a45c4e555b9c4d118ed8ac0a241b9a7ad1467b50ef63659e92acbe306d7fbe307 -generate_signature e9257b43c57e17027c955dc21454cdb41cc59ad29307468ecc595466470519ea 5c841fc7705e9f0691444e3833e84b946f0978500e66dd187b6b4011e2bc5722 ad7c20800b766bfc8d97bd71fdd21b3390f9b5dea4a763ec94209e832add0c0e 2762069c8d0c14985163c29a3c826787f2b7ce36cf7bd338955e0f421fcd070cfda5f2246426e0ae016d0bd14a39bde575d1824e262ce79da377856b583a6b04 -generate_signature 49a91500dd7fd49dedfc127ad940124684ceb5d0d298fd708906728551ce059b d19aa3856ff99afd3a621c339cd5688ad3d108e313cc6a12e76b857a56c8b254 8120cda41048d6102dd2ad998972b345886573e7caa4955df7c3b6632f96a50f d929b5ecf6206fd6106c82e73c0617760c6304d91cb0666a1f13659f5eb9d90658dba6067bc1a45030f7ac837e919d7493cee33c242bc3607d7393fe08b2f20b -generate_signature ee3d3c574231cab4d8b8de5b127423e88ce63d30ffba94e44b7cb52d933c4551 c7c4c1ebb9ac8a9ab8c71bd032c95bf4d76ed79fe8ac53265f8d2e0ff0913e5e 685985d5d94c9702bc73c58eecd4f2c69aed4b5ec1136af0636ee81d94c2530f ed0fb86ed300cbcbb6e08756005255b7c830f4fef04866543d852f70a18d9f0fdfbfec42faa466e4ecf82d4a4f17dcf827dc7fc77cd2f42690f6f5d06f9c2d01 -generate_signature 1473d8159b8f7ea02a7227be5ddd874e9c6e3c114708f7c46de729a81f0379bb 7d995c9eed1ff652f954617817f772dfeaad1ebb968c3b4260c22bcc6aa2e764 302201443d6fcdfd98585792085a7b7e804ea4a79bca8fd6b1d24d9ec30eb10a c2a4b12dc28da79accc33ea50f4a3a89cc2a34b114c84741c2a412dd6aa60206176084d12503129ddfb39667911e7ee96b71de75915bb51a2db6d6c1c885db0a -generate_signature e0b62a10aa27778f06ce587a439179f6be9a444588be2fc6c61fec24e4cbfae9 b31d7350dc561bdd04634b1c65d4d07721b21be061f4ea6779a1a9f0268830fe 033f706a513a3102241553f06fcdbaa4f1899f9776f51584495e0eea1195c906 3256c679796cc12208f70c7a3a897c90222f9aa0c8f5c7bf5baab592b2ed7e0abf0b5ecd176ba9aae4b89cbe6937242d395d68de45eee745e7d1a1990b1f1a08 -generate_signature ce6fe431c9d841f2f7494d0c214ed3f4d470b1de679e30d0980137dc8cca5369 7c4883ca0408e5279b4333cd5970366e7d2cae46e88bfa9efd5b9554b8677438 bf876c480666daf828d4b5aed26b853372ea58355c370ece915600f127dc2a04 7b028a068f221b9e086bcf0b190563c6b70ee19f805f28d1360229d239060a0f3e263e09505a28a2675a3d3f4981d296d1be63b13048bff9042f3428477cc109 -generate_signature ea984e9cc588ddcbd884642c0c1eb40dd85cb049f22688a80f42b0835b3d2721 4e200ad1863ddbec552c937ea0f28577d93959185269c21b5b0a2faf11738582 144de89fdc0a762c28f54d7cfe1d9c7c1dce3d1b520bc8e6b1df39405708b505 8accfb3a1e3f3474503b36612b54ea4f5d25ea35f23e07f571482db5b3a0150a46c0ef2a4b74e2a84d3ce9bda75053453aca35d360064b14c216ba18b115bd08 -generate_signature 298dbd2126d0276c1d95e2e5220bd529b25c16ca670094a667fd3397c7b7b22b afb3b9bb1769caea17f4102c3e59eecabdc9108195d33f0129307af251f8f330 f17b90b7c4bd2169f7f1f5816f8f72a2bbfc03c4617b957db3ffc04b6e42a303 fef52b0852b12a2f9b9029939b23ee6be96171025a4c9c01f39710183456330442a8a3471e0acbc221ea06188ccd73dd76c6c2be87412d81dded3d9eed3c4c0f -generate_signature 9c5c87cc348b763b29665e7e9fc83c2ee425c57bc610856179879b5fc644dcc6 67894b54c0628bb6c56ee847b712253782a9b02a506dab960a5b8eb9e613215f 082fff76e7d834c3034b37eba3aaa231b1b190ea3514791beaadd4b3daaf5508 6c154567386602e698b0e97befc089b8600d1d87248554a9ecdf1c56f3e83c071041058835c497c5fe26d2103648f816fa5c08560a7edc725f2c643bb3052704 -generate_signature ab263c0d9626de5860ea22e2f999676b455641c23e9edd517f420c01e84cd2ce 1ecb565cdd6da4bb6f6cfa57e75940630360f663cf56cc716f1b949419f9b6e9 d22ef716713fc60b11e619292c44ec432fe7bd4cf582544fcf2ebce23d566009 3ca0890d5c72635b0060612f0d6a78383dab96cd050164b5fe2698618f57810844f4e5b6d71252566fe40345351a049b90fb33b360f75adc6aa2d04a3cd30108 -generate_signature 2acd9cb6a9418f90b507b15bd258878fab69afebd0cdc57ade4719ab89be32d3 814c8efa712bed141ffa2e72b2317dcba9e917330523946c2a97e8af3f992fe3 199e9c09c85ff00f9431ef41d7d9a56aa05cb9d09f548d2fad7a783eb2faa400 043e7c233d8d74cc9448ba023767c896b4c24b6222ee85e7089edf7684431c05eed29ea1d580c2bc32bacf54b566c070dc441639636f670372b18235ee450a0c -generate_signature b8aeb16bf5d31ae4fe7e321da12d8defa7923946e197390f0a1696526099cb03 eefaf0226cbb5685e2770e2b72a0de26f30c9ef5673053fd64e762d9efea370f 4e524c57a12abdf684c05bd99eab65efb947ff2a50b1f27ceef7f4cd268afe05 7ea54ff6e9e18258a4eaf50aecb8b8631e5585d0c5fc0455a294210dbb4b81031c3fc6b4c3b46875cb4673a76479363b0b69651f44f46626601967486febc007 -generate_signature 4fbbf6dcbbf50f92d5f60b467c9bcd4921b756691660b2ac73b256e6b614acc5 0453e634c6c63a0dd1a999307b2c9da357b54fc1e89eedd1240f6501475d35b6 ee840259b97e841cdd17946b4b4acbcb90c7bc05996fea802825c62f18c00902 612d2ebe0aa2091ad0830f5bd38d8aa853a575447fa209b23a92d5433ab86c08e00ae2d043720912c08ecf3fc9ba8b632ee79dcd7625f1ddcadc4ef96bf5930f -generate_signature 7038946351d9332520e91640e4ea8aad9642e66a9661c1e62a519a3e03d24f57 9bbd178c6a6bc802cc56f0565ba7ef52eec02c1f0098a3fb1a958aa1885e4d63 f68267ea33101df63bb15fcff1bc528b032d770fe69a0b6f0341c614e7ee5d01 ea8870dcef734dde892415bf0cdf3da8b692cde8f53aaa87e5a04bb29b31a00bed141061199d3bcf302d22cb987ea6cf116aa41e06e2ffe87d6dbf65e868710e -generate_signature e8e5ae2e4f4f51cff909a6a73d0a24be6e049cdf32af893b6156a9f3bd7a0613 54e78d50e27c98418a28d0972af5ff4f7e6a5f2e212d792871f4395a4e0842fd 873ea1693f04187e4b39eeb4395d38e2b12494f3a426dc3ef1bb58a2c0a55608 074767a64b02256244ad61512d18e388b01ecca6f1cc59ce543844c2d5175b046b54b1df249f9a76ca88cc5978549955d434e90d8c9fd7bbd90a5207fb34410d -generate_signature abdb0a9f87e46a82240bcc77f5aa5f8c0981398731f7bc392b1e7f2d569c491e e8551e4b00aa9a74084250f33285a955efc56a310bd287d97ce3f213eb51f97d d28b26262099d372ce35d41e3a289d793b425a62205f0f22fe348510120fbe00 372168122486de89b42e7212bffca1d12f8b823548e546118527171aad5f0a00342160275980d62b506db43eaf8e4aaed7f860652e642640640da626d7f0db00 -generate_signature b6e7c69d55fd322626930ec53729cc2975b911706721a48e41ca406146cb63c4 58a63d82e3245e9771435211f2b415c5739c99370d08011e0baa1b502302b16f e1e4f2327b82c6fd7fbd35905d91056df0c8df6702eb282487ac55b3801adc06 92e1da2b471004dd692acb02de5c81e9894026b5110faea46a507ade972686014d1356c54064ed8be0767e1fb384117adf2de59486249b7eec8cde356a72bf09 -generate_signature 98d1fa8e6b508971d25a7147eedd2347f076b72729a35f9b1a81203ff85c810d d1e1c86421a34483152b3cc8bb124d140fdd638210ee1bf0df30c80b54e61343 5acdd92d2c8eb54a0ea6d466f5c2718d703a5108ffd352b6f8ff70f2baa9010b cd14e80fae2e57e8763ea261ee8047934e99e56ed1714358c5f467aa4c6762084a886cb3e8d308cbe647b6f03550a0232cf9cc7792fe74e068248968665faf02 -generate_signature 91dcff5d1d7ec3854de213306e4e744ca4c04176d4b20830d1a2012e6cb026ce 15b09f757df19ae41ef4e9050d0be8e76c151b20a7f4f792748f83aa14b7e0bc a9e865fee7d1469c369dd683d7808d5ec65cd0f035dd5e09c1eb034a7396c305 ad16e6770c959eaedc99847d78717a0114d4ea2ff2a5aebcc9ffab231937ac0f97e3a1aeb7a08db20eee6cb56cea3652bc124357f1bce24d23c8b59490e3fd09 -generate_signature 9291ce37db25aa4c373266a7aa25d585206492949c8ca4671eb7e470c6a85778 9d35b6133fee1dca194f7a64e8c1dd4a03a76e3805cfbcf80c9c42f9a45e91a0 6716b59ebdead7684c13ead0a4aef3fea77cda742bed36b3dee1d66a475d0309 adcf1f74fc81b559c8f283bf102539961b601efae456613e178daa6071135402aeb0b8995923906a7478380d5856bb1c685d09d73e77726ad3140e392f42020d -generate_signature d2dfb2e50813260e6bda0a4150ad893b32f99b2dec47ca8402f0ab8ae30603cd 7b8bd1f571d5083a8316fd99efd6a3a3dc54d87d78425ce1f46185a2cdb18a95 5d76e12ac8050665387e1c8af4e18308d9f227b0decf22355fefab31ce1df804 50ae30997a05830cecea0569708e71a09bbd80433808b9d603b83dfebbab6e0da3ede4c988d6cc5fc88deeb84849a8684f41ff62b4a9a377a78c8d1101bf6b0b -generate_signature 7ba6dedecefb1d24c087c994a2ce612e568fe90b47eabd04a9f44a9196cc7d06 ee5a5d892f36ba3ec29b259ef936c1a14085caf56e5419ce2c85dc356750231b 648229308a95c52f19b3011f816050496d77dc42afff59adfbfa851ff4da470f 8bd877bf496b8fcbb981a040e3f3562fc4049213e7b4b99a625da77c3557290c8b00a9c7eca02f73af59bcd5f517f57cdfb0fe2ebfeaced50857bb7c1d12d305 -generate_signature e53c575148d6502987c90b32ebc374a2ee76fdb167b4bcc2fd963aa3293a50d3 db099a6c2dab7de4916d3b2e21c2bf1f89f24280c29a4802ee27899089353573 9a34773656675cdf07d64bde08eb98585b9719cb9d52d919d54d70047639b508 01b2fcdd617661bc28e35e737fcd1a9d658f919f605bcfb27445f5a6284b1b046ef2b70f47126243e7ba20ef28de050b2681692297d38ae7931c40a056719d0d -generate_signature aa909b74b14671e3c56b0aa0a39e956897151694e42d90f502f5426606a4bd3d a2481756e3204a51d40c8088e69851185a29c962f97c800a88102b812606ca0a 47d0d3279058134729f860e7e0dec0943115dfe22f052ef7756b5bc263aa030c 01fa19ae7795d56841a2acb8d8e0ee9922e10832ee3c9ece45516afa1ee4470061c5a64d8d5d5a853f2665640559b1e6866f3c8de5472ff69b5816f53ec7960a -generate_signature 09719be164df8ab8ffd5d4b6820d1520992afbf6fa717cec48964f3af489af51 3798b31c7c0f929e70268010839042b76df746c4f46b0e219521eb73e89a0d4c 516de341e7a3e73b96f2a8e3c0427bb73eb04fdc967f6e0d2b87135c0ad72907 458e445ff7bba518d30d20d3eae97975574c3207e0e8b49e58c39bb72abe8d0549673bc9f0101dbbd8bfefc403872f834690c11906d40563a8fac2ea94deae05 -generate_signature 95bc343c1fbc1ac7fc31c617f0944c8a5caa4b91977bad385ddb7b72133b9918 3b510a05791831d9d86d268a3c56f48b40bb3b2854236f4a1457aa573f1e3616 83ed82fb8ea18afb5ad9664ad412d2a9ad5d36119aa08eae5ae48d3b6e979c06 57b902b0934f8f8716502758edc678fc1ce9d145b236b715ae91706e78f8fc05a09c96d05a176e349e966c21336aa2bfa3a69773aa8c5f65cde3d0ce786f1f0f -generate_signature aaa59d9c7b9745cc62775f1a565de3e704ea082feeaabf91897c163e9c453057 f1d8a8a9d1ca40c3c1985276b8dbad02f9b05b308633f8d53ddd23fde382046c 38b8d2d9729218db5231f4e46c2641bc43983320d493eba916c9d99aaac88208 a26c43b0acc8a3372f401bbcd727231da599c0129e05a7be0c5d35fa0b407d007cd0a5334a8484bdc1c060547da745560bbbe325b13a77d8043c1c34aafb2a08 -generate_signature f4433ab65909fad4afe06cdab382d2fe7b1f2d12a47ddf3c4c634bc9cddbd52f 320c05d188d2ecaecc06c15352dedd207739ebde86133f7152b3b83074764778 d34800b40f3d39319a844b8a85c65bc8e7aee303a7b8e423d2efc1c4c48a6704 91f495d13061dc36c89a6b593bf09d8b69adc30b37e5c0a15d6fff53184d1f012f94bff895c797f33afb05e2ddfe982de47ae8189217ac655c05734ef1d9b401 -generate_signature 121cda7dd82e45d586ec16c5ea52fb38026dc84d3acf8b53d9b14c752bbac650 5af2a1a8a88c0e0b53e555a7077a737c2cea050b7dbc0ba3d8ca2ad037c908e7 007af32d54c623c7eeda1e02984238b6799b08db17e3a4231daff62ab3d1640b fac776b68d0563207fd2bc29e074fb0fa0c417c1637b0a376951ca1a0bd41a0f097c31c28f04010c8d310c3a5c13ed73ecf04ef7da7f794fa5b2c872facd580d -generate_signature 4adacb5f6d707bc06145c6c445ef70db86145b78af456ee5d687530713f153dc 2d96e3dd0c90587368b586dfc7954d5d6ecf04523d0797a0fedfba91f65649b1 1f8093909e4e249adbd396d9296980bf6b65164dc6ea679d955b98502622de03 b97963c1c9161edde2149181d3bf17f18d3cb3333771b377ea768bbeb3f69e0cf6771d0a1ff8553dd669165c88db009c1e21446127da78fbd5bd524c46e09704 -generate_signature 86034412d429483e52eaa4f8e3426f920886f5a7302f9733b60c3368f8feda5d f47f3d62360154548b01b27b8e20bb653569dd2e0d8f3e2e4926563b19d2905e 383927c522c2201332dac111a750e15bfdda86b1d47483a11624290569a4f808 e4a23b97db60f54bf1f294e37135294b06e7c6fbef11a931f14722498aedb70b9c1729839c09fec4aeacd074c9feb3d973f3176a1f104ef8c2ec49214b008c02 -generate_signature 891ce05ba0c25b7d2409dd83487ffb0328f515d0dd77bf1c2503e33370f8cb99 0103c4ef2f18527e1630510bc27ff5966b018199c0b82a4a0d62815c74f1d0b7 fb1bf90759993320f4e16f3237c2d63dfddf6594f21c74e20267d61a8bf7520c fdfe25319020489bb7b7620fbe8eff7aa797aa8d6f454934f2151bef4088390e1557c87b3205a07f8e6d14cfc77bd99911e4416adbe8622e5302c1b63c4e990b -generate_signature 268378aaf9b6403f036e24e356e90d67c3b82edb01180fb7d135e895283237b0 32b9fbd425dc1a9e2d6c693699594bc310737d3954b8dcd5f3bec5a056a4e63d fa028fb4484c90b355655014f1f20eaa711d1d61ed8e200b718b46d475603506 548cd3a0d3232bad8329d0e95d97227100736766eef062dd19dd0fcbce2f7d00a8eda6e24c9dcd7c9dd93e364d12be694b874954ae66fe34aa6c197a4d003109 -generate_signature 4c1124a23917f12efbf34c9c90b1a079667aa900b78b8a77297f55e50c3d6e21 ea3392bb6cb736c3053fe90bc64917412190b673f2d1db93338414fafbd15414 54cff91e78a84670f568167ee279e72cb0a32ecf75544b5e4d49ea5a77a92003 04505da749d2eee35cf9c644216dba9941a5b342e23be04062bab1b636548601d88a241af1e02fa14a4ec666b29643bc9c07ca640bcfd001f93075d90ce94a04 -generate_signature 112cd2bc459cc678065ba583a09c83d962e385cb546523901ec4d5b47425d0e3 0693ef1cfdc58c35a00dee5477fa4d8c73422294c88b8f9d826dbc414dec2306 a3d6655a3bcdb2baf44248a541141a67018c9080001457e165ec29d2c3248600 b290e9849810e5835e1d0a0b08049f7940f831a121d098a2d2ea899879cc880398b0467b8c71188455b6532a59500cf5e644d15b408befb2bde9cd2080360c08 -generate_signature 2de379049e28fe930809c36f1062769665d4133d4d668a718b84f9183332a2a4 29aa902ba683847b1b59f09ee480e1814454bc72c48fb3884540d369f1a9f2b9 de444332bd0fcd47f6c1a5b7fc7ae1bb544a2298672288f04effaa04aa7d940c 33aadb26e603ccf402cc1a7f441c063b10c72b064fc9bf9574efcf107d6c5109cdfd79fcf8ce7525d96141cb4e92464eecf51c00af4f29e8d77ad5a73410dc00 -generate_signature 0d2ff1cf8e58881dbe688be73ce844772c6696636469eb8ca9086a3ee2ce07a3 a743a9ed747abc154394fa822224212c3f7cb9fdfcb40a24a142740d1644de9b 08281ab64eca078a437c7f10208d0f5692ae85f6603fcd1d9e8ec2bcf9f64d00 0136e3f553f90dfcd9bfa978da2b9528ef4c55a70c5a9ca71af3e6cb3c9e7f064b2fe3f5350e63577dac7660966cc2b36b73ce2bf2764fed129cb56f4ed1850e -generate_signature 7104100649edb970e649881d4059faee3e51e221a3ae07fc33d944eb6c192322 c10ad6f4972dc849e2bac69e549929822102071d43f404abe8049a529b9c930b 0e060a4fef0a46f9c3d8702b38f82270e76124aac1f6a8e1ec402aa9e7812b02 2d9ece3e8a1470022fd9741ffb1469d458a786e876d3a994bb285366c912f5032cb116d577a457ec4609bcb672f68ff87a5036f81a41ce2b61efd00df6dd270b -generate_signature 995be2688f3f7354dc17d7fbd48e010611de9d84247e1e738be9faae777d20f9 89d352fce80cc5dba45a618468866cbb9414f5fdf608ed5dde3fb446fd665c20 791941512b24ea359aafcf96ae0d9a7f7c24d34e2177eb1822dcf12776580506 811e28243cd55c3f185efa2b6cf544411cb30cafcf688244471cf6111bb8840cb3b9c7b0e3ce1a15d9ff0a70029457a86c2919a68b43c15970ae804e5fc1b500 -generate_signature 77262429448c69ae1fc4c99b652c282af2082b046a227b57dcd724f56ba0a696 9b605f01f72e9fa6faffa84481b9e609f7b1e20b8a33b46b16cceb7f5c0cf411 b912862268d63a977c75fbfe9aa7008190758367379862024232c0cd2504000c 03c825f7d6220da4c28556383578e182da4c266bae998a083f67ef45d8a86a0867ff545d797ed8b7d86952f086cbe8fbc7d4f724dadc39dd5488b067c88f2e09 -generate_signature 382537401e042257c1a0c6062ea8ed101da3193a6cac540d675354f12f7cab82 1c209e65076e9d4dbfb5762f3d1f59896da89efddec6d696a4498303f67d667f fdc2f3443bb4f28cda3ee7cda5255d36a89a983b91361700b63b87db477d1108 74776b5babd9fa36478a8f1139a793df63451c8cb4a4c01caf846b31d9c3560b4b395609f436a68433dc043526a54ac5cbfb6a73febc4f76c6076bd477cfd706 -generate_signature 55b89623ad6f7b1d2ed599d2a04d8236f2d3fb8b337ba9704439193ac7956889 eceb2e5ac867b1603e9c61890aafe7871b3583d38c0a9f4084573497bed466a8 cb1a0a38f92fcf57064b0b1e666693cd1abe9a2b42cd4c7c667c933e3ae1340f a7f8b754cab3e57c1de0343bad94d46cd46cc787871ea186d8093c3feea1580e5980a17520269cd32b183bc15e6068ddc6efdfe203b8303b61214ceb9dead40f -generate_signature 22c3ac4d3466742eef52c67e784050c30b5d5ba7b9235e4fed8190ec18cc50ff 628a568ca8cc07afb1ce46b3f78af000a37dc9bca3fb8f73d7d5e697b267fd3a 0e180e4841d5de78630e900c364dec44daf2f74e72066cc609eb917995a8cb01 2e1dbdd3f768386ce44085d32e74358acc219f00e28bfdc355293bdfbed17c0d4b6bc3da9474caacda128a9d1b8b402e7a4ff1f1d2dd312608e203e2445e2103 -generate_signature 8bcdbe48e967d9e68775be61493e60f6c5488427caa85c0c42b3ca3aff756b75 5de2c451223d0cc7293ca1826c02215c6b519bf3ee0e5b91483990c6250d808e e8b26635c9a1fa4b7f9165b745abbd45cba7258b6420187ee6e4325a89b0e802 66020a81a792108ae070b7878fe7764d6f8e062a323c66b4bca765bef739fc08e60683cff028e280280e5febdedee2265a022b4d9cbbdccc03bee47143a6fe04 -generate_signature 37b33cb52f44b8c43a0d619ba8270eeb2ee657c0e70734a05c2de878f77ab540 7f5ce9f0aff75716477a94c13dbcf878a8a2513920dc40fd2a29814555ce1629 f8afe1e242f39bf2b08c35d6d18aca0900a1e5ae729efe56892919484b5e8c03 e690a20785106553dee2b3d789599dfe94d2c3eab0131aaeb3f408afc0a90a02cb37c6ab2f9f0025c4732477c7413b0d86e69d16dbb4ccb8f003166242372704 -generate_signature 069bfa548d79462cd27ad3720842430f2c4947532513a36f0e012097b77e6a7b e6ebb1f4eae6ec2d813b9213050ac47c0054723d754685452f112551e9e6619a 6cb63dc9d194448e748210d8bae8bbee8e0cb494bcec2b51ae06c9f1478b740f 35819d13ae03277e24bf54f6c1b6bdaf8f67797818da95db1c75a7652f22640a14b45a160d4f5d333e15ab11403d04f457a1bc23c6cf9e1c0c7b81660315a80e -generate_signature 3fbde8fc46fb4f1001ac7fd712760e0d8ada351c2d2c28b6da74bbf9e2795c80 79ae18c7007b1a790ddf2e6080615398ca77b4d06c1b2f7e536cd6b8ddd5a21f 70f8219f8b4d2567a4771051f2988b84f137a4f84cb26f081843908c7d959809 d9e9d7a9ccbc3f77374632d807c2c2d6986c30c0075ee21f634e3f21ddc2910bb1b4a879cfcde156ac9d3bcdd524eb9505647190c07f2b45e9291a8c1ae7200b -generate_signature 7b752d6c0cc3750012b98ff0a4fb325eab31e8bbc0dcd995d9932215386e4582 9519b641893b754f8224bec54da6b5c06730c3f4c7d4704f2999a21b46a30032 0e931c71c9a3789e25f79e722cd6858d0fff3f5198597b056247b9cacbffa20b e89357d5b3c4606102f77e417a4abe0b13d10134ded514bd2da9a305f611a801eae9be74a4db727fa2323172612bc1f1ab4fb074c9ee963998fd1cef2b67a609 -generate_signature e64074ccd0cfb5b56a89cb07faa1386061fc4853b0b2211d87a7af02bc3fc0fb 7072faef529d5daf4fb8663574a4ed86a7fa17e5cf10f09190e280500a216738 d6d77164dd8a1f6859e8a814d2a17367b8a8fcb5e6bdf345d74ad6d70658520a 939e1ba922c1b0ea5ee22a63712187e49d58388310fb12bed9788987ed731005290feb84c4c144bec363cde9039ddd80b7a73799a00a3134952742d7c90a0907 +generate_signature f63c961bb5086f07773645716d9013a5169590fd7033a3bc9be571c7442c4c98 b8970905fbeaa1d0fd89659bab506c2f503e60670b7afd1cb56a4dfe8383f38f 7bb35441e077be8bb8d77d849c926bf1dd0e696c1c83017e648c20513d2d6907 4d8c8c3be3b3165d800a9e6b5b0d683a6130b21b1b03183f488739b463b23e0e74ac4bff5f97acadbdb95118259119e74e24d40207a3ff114f4bd635f141ed00 +generate_signature 2ade1389a860c9249a42e45d32a9fdc29286c8dc0c8ea1216ba786c74517eefc aa2521256174ef6566618a6468c7b8a71ce2dca398be2290148b813710d12f7e 344a6ad0374b6ae8278e3f226d58e8bb2796e89141eb0ac37cff8552b158260e e3569d302fcc809b332a5d6f0d42ae84fb225db9b7ca53627778b9e9923658026766a79960d227ac503e818ab1bd684ebe71ec544a744db2de6fb260324ad80d +generate_signature 5e91901e800a1959b4ec07a2eeaa3a9b28893029a26e8ef5d13adde490e5df91 486dfb4904d81b1bdaf865dc07ff71145d1bf8a9e0c160b9c817315f6cb30398 6a05fa0a97e172c9a8f5d2e24851ce87bb649a46c34b33330ae71d0d24a4e70a e5adf895a9a23295fe525e03906b9021d597bdc9b4595c76e63792c8bc819709cfc5f29e3ef1718ddb658103d96d3f641279615ae8f8710e39de4d692f9ccb04 +generate_signature 03e29bd7435541f8b12830d68fa31a8976a7a2750e4942f36cf834506f3f1b17 3a9768ff7593e63e615433567e9f2d7167a934a9afe7fbe587f0502942ed4ff6 b1b9f0cdb59910598538708eea87ad5114ee9eaae0bc5c62907688d6adc60004 951c9d15d656d80bb867ee265656e9c3c9ed4ebe564fdf6b753d9e775aa6bf0a2e2dce5775b6568dbf5c7c107a8e358e6991ed9ff928aee9507d89d801024e06 +generate_signature 5eeeeea12358c1ca323e2bb7f7c4f4d4f64082739f196e5505a116760af245bd 238cb505dcad22cca64e100b9b0a3133b44dec7a6a0abe198f6563a1df53a3cd ba2c8fa6cba86ddc91f810519281abeb43554e43ade7bdb3c238bec0bdd12e01 5f0c0c9c621c1d348dc56a36a46d2866cc746ebec36acb3ab2dc3c024277910ba125c0d04e26325332d2087ac35996dee755e1556a0ebbb3b565449f5415c108 +generate_signature f3f9ac0a5f5323f4af5441d5700f9d520e6cf41ea441ba045716b591e743cad8 73c0232f4a68d26578542b4d1e02287b995aef419200f78b3294f1c1dbf979e8 9758db88417ec357419b8e7ef2a75d2c65bdb800d27f6203aa54b5609955780f 387281536437e866f40ebc0029de970472d354303e6d21986e5ecdb50dce1d0054ac1389ad3c426d2d07687e45f7c3b4c53a86e9da6de44aea88e98143713809 +generate_signature 0c85328313e78623d436a1e3cf04ebadfd0178d4b230004469ff8e995fde6d11 c1429c3c7676607688349d6727135bb442466932035cda069ab2463b97387d59 1e58bd527b1ba1014ad772c523700434791a4d4c005f2ffb81fddfccd03bd304 eb65c0cc2f7d0ca4390ad40c0f75e2c60ca5b828541ba80fcabf2f36888e8c01c4ca4d07c8e6270a34e9beb19349736bb3b61362444fbf2bffd73a3bd0ae100d +generate_signature 9d2ea8622e9d46d17a568571332f14d6be90a40df1aebeec20f8418a5f94ab55 f8b705820107149e4845f2a3f3bd045a55944aebf35d1104632450bba4141db3 d699d458752018ca3ca82433e6fac7547030990c923e4192978ef179ad4aeb06 9b43bed7a0c1d27d439d1478bd0108c2aa98fd8c780484a48a55d789e04fdb0a78cb723c922e8b0466d5cbfb62ee0c1d2414005fdc6df90bba066e71d017010b +generate_signature de9240454aec3ea2ae6e13ca9457e43003991b9d0f75a4b25117e1ae66617ea2 ef02c34f64ca98543ae5b871197e413a7ccbc008f2366a2552f2cb5f852d8ef0 05cfc28bb9cbe0c4d02d8692f40fcc864665b118064f1bd31a347baeed24240e 5e2163e82b1727adec933d8f73d5ae805aeffe51550bbdf89fdd030854ca0104d47b481dd8b2bef4d44b8494347d34c295675a5ef1a0eba2d85f8993b4a29700 +generate_signature 806c083034f5bfc469e68a490f512a3c6cc3d21d043dc3f9d4941f5a9fac609a 65aa36a44250dc1e5985676f193b23119f7d5f9e0291e6643fa55ac70b1ebdb4 5f5cbfd6c2d5e22b703db1c64163cc0bb674a1bad00cdc77ee51001af5f8af04 1986cb79885b54276cbb3c6330c7a955c18c49b1204c178d66341453f3d755079992c20890d46cb6582af356649fc8cef4c98a83aac5d5d7bc38a0753e4bb105 +generate_signature 413c368f9b4327907fb6bcccbbdc0540acab58dcf1a860c98a4340448ca4ef4b e37df5cfb5f8ff60b822d3550bdc498a7557e1c11d82a035782931854b996b27 4dfcc2bbad477e1cfc6076408fc85ff9f3381dbc2ca5f6b61b4423a29f372d06 5f1f16e996d5d4a6f1cbaf88542be7a7b2cf9e06c408235f54ec5fc59b6071052a0d3e74cb0930b2d46718b0b4557bb8564919ecb5953cd36a41ac3b355c3f08 +generate_signature 3932123f3c95fdb21bc6fc74042f39eec45e588d707fbb7036983f3597382bb4 8b0138170662561e8b4e32f0821d21d187c62e7939903ee747aed3b1bb277d2c 649ae266093e93d0968f31ccf4d0b9307abf1e50b7d2b811f74c9b83f58ab00a dfc3ed48098f4ead6e4e5c33c18fe6e8eb6a563fbf363a40979b38c378691405c38ff813bfe3987084347acaa93b97d2cd37b13ba47b66ab31867fcceac04006 +generate_signature d17ab44dd70f88e19f0e8ba88a413fc18b2a1ce0ed712d6d110a191c9a284236 38bba4ea01a82f0c16f36f4f3387d6015f2c703cf211f6b73936db53645ef2a4 9d7af7de69861c61d3c8c6f2022e360a6cc8a647a4f3cfbeae6c14f46265da03 e031d959720f83a0f04f302bf8492a3c7fcb1fccc446a1e364fe117e368e550e88e72fb0061c08ec7b83a87c8b79db8aba22c33c806a2e9e340cb669e2b91b04 +generate_signature 7dd81bb4dcd4d74f4c034a4b6a51a49662ad34a2687401ca00e8a628a298ef44 5edda4da92d8227684c8e30c940a9d4f9ac51c9f1e1c9216e826e6de3212f47b cd386423bdae74357991ad01bae929b6ba9d65803d00f06fc9f0ee34a764bb0c 98555f5b2c317473d260bb94d34f19a07422570d25d770a2557d45fa489eee0fd9a109405cf766ec662c72234c476eb644e0b1a90e92bf07401fb0563dced801 +generate_signature 2e8abcd827b3c90a24a65d29e229b5bf59ded9b13ca77f51a98fccb37cf9775c 10df138936f814628662c2cbdb25dd7820c310d7974bc74314131f8423880dba 0d8d845fd386f1f47c4e92d6861026d697215a396f3eb7eb76cd478dd6c1220a cb10c75c6eaa37b25ab74bf5a523313df87ce3ef598480f0227d5ae417de850227892573c9efb37dc3903dd40e7811cc055aabddb8a9e07059474f0dd21da10f +generate_signature 83e42343a638dba6fb5d78e1b9c11e236425b432c77deac3ad098b93ad73f14e 3e855c996c5341e02e85737a2b03e98491037d91721cecaa17a83c2c4d5741f8 87be0823f5741f09e2f0c1a3337afddcf1533dd10e0b28efa8b1147c9ef3a703 8e34de7d4e66db9b0b04b363ba42d0faedf095b81b4749bfc7ca4a5573fd310cb9e49a4482580dd382561b199977fcd9dfbbba8fce869bcc157b8f133d5fb70a +generate_signature 206fef6045a5e44f87bc7acd4bdcd271e1c55cc8e42f5943f1f0b1b3dc0fcc54 9d32cb01bec30e0d7dc921f1ce44b5a829fd84c37e4304e4f910cb9df501af4b 8adec55623bd61bbf39d72e3f891419b5264af1bfaca43278dd86a944ec04c0d 9d96c90b88d56f55b0d679fb56aebf4e53fe6c7e46ed32f9d08bf15c4838b00ef70befe91286aefd77be10b0ce2c264c70c27561f7c8b0c1d7224868ee4b0602 +generate_signature 0f1d0617a849e1266d6741e17e8fd8a4af392577ba27783ed203377cce7514af bee8f6fdc7360d9acd4a4076ddb2f572d9e9306940b39e5bdae031db28f201e4 95f785c3db1b8ba26e660e9ae8a60af20a00289d984a83c852482c505d1a940a dfb3bc264686d40e63d514ec0be3b93c6125100df8a59a9c6bddf356a456660069d020d13f012e196053851d02058db9e8b0836ef51395151de088e0cc2d8707 +generate_signature fc47da4563a05a5334fc291b1730ccad835e9469f417987ed3d95aa041ca2aaf 0c1ad3f7c9e60987a84a3525a4dfbec5ad69f276ecb32e3c0880ce69befa4810 50b84ef4f4178228d07435d3105b0fe52ac7d2bfd38da43875579fe65a7efb0a 24890c5066fb2f8e30f6e67665931aeaebfaf423f0f8d1eb07af4f4e505eb602b9442ed605bd51c2b1e6745546fa874306379b4d3adb9dbf45cab720579dde00 +generate_signature 02cb1e9244aa1f6736d8aa1d5428b30658756bd318bc938d5fd704d97e4a5d9f d52a28a31f59208e4e41f6473e6bd9229ab6a809b228fae3d8f0a6bc3a34eba0 c6fa9ba77466112e1d268891c5cee9f88d091a93c06cd4ba23bd034cb3d0840c 2340164e8c084fb808947d22e89450d2d20e28f356607b28a0d67c2784f1a404ea3b14479a6e92a108d4b67800a549e0ba1d41b600a09c932c7c0b5c7ca3710d +generate_signature 62eb41777076bd1a90450e80e77cb1aca6a5f08e2320128b704b663402759d01 8e83ce60900fabed38fb560505d26420775f10ad6729b209992816101c1c4cae 14fcd95cd127e1218c11fa267c46f8c2d5c1c736e53f8bd2bf084693d1114404 bad17dc5bb36c42d7890b70b528ef63d8c3ea1fd96c8d1cb9761433649f00208e83e6a4a0218f55db8f50dbed3303f513fbea540e0160bc01702ba91c95e8b06 +generate_signature b862759c98652ca2b1522a556729103de96cfe831b3ce615547ba70c5f622c0f b7827c8b2edc9b4014cf4421f1c9792c012ac3264b15204596652d5854bc7673 1e62f5b7eb5d2bf88032c98edc74a9c138969cfee15f4cb69990feabc0f8840c 94b53456f54fe5f377ed7bed4aaaea0a2426817affa4ce1d9368dd0eaf839507d8463a8d07b87fecad0b8f3e8090f8b73c15b4a0357220a1f4481f7d68139305 +generate_signature cd35a8dc333ac5f33f3e12831a0a2f9ee03c7f421dffd7900b7661e76b056f4a 31ea2dbe369fc7a4514f3f826cd259eb8baa6bfbf22fbc2ef520d98be6e821dd ae4ef972bdf190ee205caaee156166e180e054993709bed5ac96bfd80e8b7401 fa87e0d00cdfe9e7668f1c84e725c122972435fd3cafe92511d80619f7ca02080ae868bcd919d42b4b6df93cbbd758ae3219d30f6a8766caf721cffbab34c103 +generate_signature 5dee08dd0f483aa67e0b2539c362eca5c4529961935d56f661ba641e5efa7e30 be75e0ce86b68a72f7487fec4857a7a6a188176ebcb9192123ff98c49bd2b4b1 b13ba6bfe9c23671e7bbc4a6380c1ab6c61b09db58220d28781d8ecb1b37e609 fc9bd4f87d96f1eeee5599b72c36630a34e16ec63d36471b3b624d00130b7e0fa93ba2836e5c4cfd447c0ebe1ed9e872cf17ea13bbb3c1b3ba97443bdd60a009 +generate_signature e88cf519e819375fc59bc8de8ba403278999311c7490290f2f5438306bdaf339 ce99f73115a02e03f42a1b583dc3cfd5fd1747c1400d1b6df73e1a3ddf616932 0a33216348544ad80a652433253b6921c0599d3a80e4b2d4a0477cb121e08104 b03c4bff969812e0ed3b6bf6eac8b5d8f2f6827c63c8a2be82c8237a1eb327097d30d45d47f22bbf0a32436e396114f61c22706654f8f27acc64cda2bf584606 +generate_signature 82a2377ac1c6a103cc0b955ea1ed3fcc41bbfbf6416b31984f28aaacaf4e2a94 535ce02ef72e89bd86e0fbd9f8f0197a99b11f81128f5179044e4e6d0f5f1a93 dcf1736d7a4306330ffd64315b2122c5b55bdf115dd52680d5ce798893b62a02 d865090cd027afa520a64196a92f4be2520aee4d44d59ae6c66f73af8c19e00ed4b4168c27049146aa7ae1a915aec7f65d9ba09921081f52895204fd064cf303 +generate_signature b207af5749179b6f2b30f48f2e0c19d90b6655cdeeb3fc37f656321f50ab1508 b2b43995a5ad7f51c6c71d29e1991f431444b5e73019b3d36fca05bc566bcf41 b1e043b1b9f4c280f798aa59c2f62e46c4abbc65ceb17349f4d11b867937ad0d 2b9b4abbc8e41439a5cdccf35129d5721f44a54469c64424f33fb8859e0025047867a4b8971df6be7ab35e0fa73d4d663058202290c4738d89a7717180a9a102 +generate_signature 63e53137888836ef30cd6a93d34a0fa749fcd9459bafcf143da29956a6f35060 4762dfaa39af96a85ae746326693ca87d82a008b96c84792ed1c570abaaa81b5 723eaeaf84c9dae7476aabdc5fd409a0faa7c61ba8b424ff78d299b9480d5a02 0bb2300897337f9f23867d4f9eac99c8094e3d2bfbe809aa5b1798cf4792f00864a34b002010f4b9874f38df4247eb751032292b9ced49c481703b6146019600 +generate_signature 4cd5f4b8cbbe735336d469aa8f2f7c7e5195d60f897b9a81b599b2e045850705 4a6dea121c196f56360e8c17273f1b94827efe1f24cbcdb9d3ed61b9a207b73a a8e62911309f4d4fe0bb6284fc4e3cf4fc5b08e3812e27328f68c2a6c278440e 3fe4a94a06011548f6985840deb85e892888f74aad4f2d61605dec5de1283c06f336fe45fb42ee9598d123b9664546d9627446bf822fee1bed66fb0c37aadb07 +generate_signature 7687ef751d6533aca6c911d70bbc4a8c5252fbd3112969a9a40b9e1dd041756d d17a5002e137731bdad6600b5ea02b520efcd1005008c6f1244deb839ea041cc c848b5aec4dd76bd8e33c37ac65e884699fdd7b5c7a905801f2f46c56f783005 13f1c63f1da9cf9f05efc3f6bb5b82e890e05297eec49f7b69b29da59eb99808f0383d4e1d817dd48f81b7770cd0e9794a1fecb9445624f1088a32ad3618a304 +generate_signature 7f75ac1c1d1832d78136ae9459b070982eb03e91fb4b686f17e60be644127d2f bf2d56a4e6d6f7eb153f31bd9f39d23a9e8d06ab8f906c716dde473fb2d16554 c901408e3a9a52cd7b95db0a8a5550aad0af38190c082f5d8228e5587367f500 7452689f4d73345954b6da7aa3048de09f1dc0dacee70168973f00780d34510db41dd089450165b1375c7a509b5892cd923b94c8294970812d0a61618a77a901 +generate_signature 1772e5a77a57fd69d6ce9a68c81bd9c4f81579741103a177bf584819a656e1b2 2ed6932a62fa064c9c2e39c7ab0ddbb6786dc849286af8e35655a58cc9be79da b9446a654072103d6e331cea1425472e0782b532ba9e235d61ced65ad6ff3705 5cd59d0325eccd855bda74e74c61b4fee156342fad767f909402384f85c572011e689e35337eef1115bca4b3667b41be119fe0515a2bb50aebc78ee54d0e510d +generate_signature 8bd02d71480ae9f17e999ca813b837402c999bedc4374d416e6aa9e233818f7f e0380564647a85532bf68ecb662fd8299921c8c51982b6310b4a6806bc056dca 9df00a62dfe8ffe27a34b7bc6a24a10d7f147d620f3ed78953930fb845598a09 79ad42ba9dbe845a78fd000d5d9725e5220daf385d8346def2c3674f8111790fa79bf6344d2d59a04db72e2bad673b157fb5d850b7970f9726ee6e597caa2b08 +generate_signature fda1233d780d70dbc9580c2b80ef1806a8ea2df30c317f7891462d96fa4d66af 5f769cca4be9aeb809e9803160b179b1a7bb7cab0e2b0f6311c9e29a8db20de8 076d27b6f85be7acbfbdb38d1b22e1d75c139072f7ae9d33bfb7590b474abf08 be0090335595f6d8a968977ef4c5d224e9d7e3be73f9bcaab911a89ef0dd9a0c822cd80e112280e279f9d780013764479ab0b38afa640b192759d140fb6de204 +generate_signature 80a147a42fa1e4f83d3915888f5c22ad71f92c0b2e1dbef9657330912baac097 add3133bbd5b10f3b34304864277b2a335b3625afe0d188ea6f60ba7302cacf3 911a315f1f7c21c97b7dd0385da95b6bb06de39796a538d909d51bfc07439700 9c8131da15c29878b0cfe7c0ac80cc518b983b35a2c1d8fe5ad4981c613dcb0dc5cef2e269febadd3075f9ebed11e39c86733df873d2f4dca99b1da1d933e802 +generate_signature 870ef0ebf5756b28ffbdd4cb65c2abfe6bbc366408ba42940376e91c750473fa 7c91e023da55901252f69ef58bf56329bb7ab688f444df00c1dfa80916a1851d 1752295c9937a10004ca9884b676bf4cd5608e4fb882f733ba1d91093257320a e07b84c4a1cee61148c271ff4645b6d4e286ef19b43b06a47763ae853df7ee03ee3e2651cc7164837d102359df9f7c506c5c8fe46621f79c73cf6ed1c7c50b0f +generate_signature 711f84e938e19a461e28c770573ba9220b84b233ef6494e1600b432333bed7e8 2fa1edf5af46532c7d290322f145d44487bdc39de5b60d365f9d2937de5bc4d8 86b9d8c1124989a8d5704873ee831f1620e580799fd46e507e55c9dbb2bde40c f8c7f8de98d08b0f41a067446a2497a67db6d850454123b3b4e876cdcb364009a71e6507c7cb15196d89a3cccae5b9b4c4759d5b5d8efbcb3feed3003a79cf09 +generate_signature 182159820cf794a0a367e94e6181cd2bce0aa7e8628c89f2aca4315136d58bd9 6252042e2d1f1694b73799d9f4bb777e7019ca1655c73dd79715e42f473f6c29 f34fe47fd0f4e59854e9b1740c91336978ef9b72bd07b2cbc601319adb261a05 c7787c0be53ead0f6e8c1c1cbdcf087331a9302f07c24c0ade0c744db9345807a71e928d3f98494e74fb7b3c0673b423fbd5d66e27bfc726dafa6dcd8543cd03 +generate_signature ac1490c8b703addaf061bda16c13c0ddd4ab06da053317ebba240be4e794b7d6 14d9ac957f7b65d0a8e55488d62a60325caa227bd28aec1d6a4f7fdb83a2b6d5 1d9d9a3c2200e2a127b68b06b432714b585dfca9fc8bc46c44e1a7fe7462fe07 d8007ec1580bc67da3dd7be58cec212bafd13faff58721c580e8e57b100c910449771d1ca65e02f7c4a5a6f2c6cb34a64581a06da6c9270970d22f1debd8f70d +generate_signature 6712b724736993684f7380ac03ead9b3df8c8d0f131d4ea99ade9d153671a3ab 69f90161bfbeae0720a5e0463f15814ff8267d8b742c2eb612f387f08cf32c30 74d48447a77283726f32f5e726074f1e3173d05a55b9e14796d2ea5436f0ce0d 03fd411245c78410dae2b63eda12a8e249fa7c4e6c4ad5605bd0bca852d96c074065fe1ac1137e09edc01a9b9fc9fd0adac2c91a4b1548b1a70a9fa18bdbc103 +generate_signature 2796b04ccbd3ecb7ca3182d12bce035edcc049e6eb7226977e914c22b406939c e02e549729c483263547dfb5e4280d5e4ebe90a7140c79c0eae07ddcd91f2266 a81f6fdda8b3c5efda411f6ae5830c151c1e09ddee44fcae52128e2b4fba540b e7da92bd940ae43f087d2355b514d83ac5ca27f8051c60673b2941672137460957da4f336e04c6fd64fa340ba7fe911a34ef41bfd0a1c9f2ed425c4ab7c4a202 +generate_signature 6b07f68fe4e8de6a194532606d0f64bb2561abd14d66cf4dac2526f8a5f40763 e21eb4c04c5abd7c4b12e434560c636a9c0fb4df380a207a93321e1865a7aece c194dbf0de2af2b96b1af7fa24b4b29f1291088413c9f26ed98954856c411d0e 2c5b10304dfcda3e6240b39fa88294655fb285a554b4ef1253e499b0eb82af0c74c8a7005a63158a1f5f4c80ee3f4615b6a4146b32b44f772438b050c271f400 +generate_signature 17bf7d4f22e2e16297c3105c5ea01f9d7210b77a02d2ddc8d9263b536c1c51e4 94fc695c28959e0d68fe1dfaea0bde1a2b11be6eede96a4ab65b68ef0a98c082 bc021c4b80b42671b43227544c185fbbd90d29b5d2f110d5030aca995d0e2905 9ec9bfc25af333e4c8dfe2bb785f6029712560aa66336b299cc059a7839f5e07b583057b5b2a142624527f01ce7813bcee80cb4fbdf565ef31722c613dd89407 +generate_signature 0833ccd1e71d03cf19ab214685f348fa88e711bdbc6e7106047b64a151fb6c57 f6064b733fbce4e1200382adaf77d93c542a673573fa492cd4260fe28b14ee16 01f9a1785bfd24fa38af0a5d0c8324f8946b9d0583222c53772e69367597490c 3881203d75206d6ee0831eb00258784f682775dad9a10b3710f2fefa3bbede0d3e598276b78a5ed5a9507a827d57b4e3b1e0abc84f18b3aa120566dbb1557f00 +generate_signature 2185872fb1e5cfada7668e6914ffc05f1c5fde38a7319e79010a8c1fc1c2bf28 23bc7fc2dcc89856410f5f2a006f4030d7880226ec512f8ce22926c569b557e1 e8ff76b5f7d00a8b8e6e2fa40b7385dd86692bb197cbf1220f3b59f00e149604 6a4810337dbc74875df912919dc658a5476bcd76ab0263105799668b023c680f836ea16d4dac7b9d7f7723fe12b26f6cf4244b6a7452183323d0d938e01eb003 +generate_signature 690194220a436c23dd6863d2b7ab4ac41cfe4ec6a6bc6843f1efd4388f37ee46 950f222148c84dbf4d586e7f7a2b53fdc43e45e034d0363883f50059302e5074 46d06e7cd27acea2c4094cbc3ead11d40b800fdde1a0fc1f687048e2b7ac8602 873bfd482dc6d1e22f64d4ee18526dba999c0731ae911c51fa9198a6073414089322b8f94e37211e419cf9d1714f1a8437b66d497f6fcfd156a49d0dd75d6d0c +generate_signature f2f674fe63b53dbeddd1966c2b3a3fc7d647f63190bd0a183908f782ee65b60b b75b075e9ce254f9efe7baf09897c5f58263397a0cedd458ed8c123a552e08c8 5f2ef89fa9956057bbd7654f09ce75f82188214ad1c75d8a1edb1f954689310b d2de07a25787aeb8821440b619fff7d1b9a82b053a0f7efd7d366b6572a90c095d8c28fe20224a5da33dca2e3beda32449c7d5ac7afdbc4f3d6a28b1d4041f04 +generate_signature 98e1472b88f2580a68a4b10b0634bfdd859590805b67e9b2cf8b76be25c57942 1edb8eededb14db7343fc79bba30422af90e92c739492ba1abca24a33808668f a8e7bac4b9bedd6cf89f709fc97a5d9c7180cf8cfe36fea26f3931192366d200 5220cb39057da3c36ec7f381e45228ea8d1b328ad6a11d1de8a2ca6ac0981e0039af8c61ed7924f294ca0043037e09244a3840ed5d974c2bd94afc9484721805 +generate_signature 1ad499a52576270197f365c0268892d44b73e9130f70c5fced7746498ef531c8 2394d9a89125d99e13502169301dedda64cb38509465e972b6f20c7f098d851b fe04a7d2a3e4e8c2a870c774483ef0b122b8c01813914e59042fbb76a59a3a07 efb3beb859868981d7820b1d93a7b7dff27bfaa97f3cd39e39dbc169475a970afb92f2e9e57cecf2bdc92108a430f1bc3e9fbec5f9bee2059e674a2242b7db00 +generate_signature 43038508a053508376f5d0595bd8cba556610e673b8291a322a2b9c72dd4b214 4934f2132f6ca4a2aaebe35ee547f935fcb28588e8061d7da267ae0954bcc987 041a55efcb7dd92f6fd6c2c2ae8c93af8d6248a27cf51c3d3770a0712783ff02 45d1666274e4b447bfc6e15cd245cfe31215de447e119febe90871a1def9a4096a247a4125eb5a34fdf0c5f33f40b730df3ade36d50c8aaa7cee61852869bf02 +generate_signature 4f9141ce176f61503a42ad71e3713b8a52dc56505809c8d6d98baabafc4e9910 516aba422fc25e0533ff24157c263ec3a284e1dcea2a8a04972b00c29df0dea0 23a237bff637b3008b429465d3223cf820ca4db0d75084831ab81808d4878006 ea508d64e99281c3d3c721a40c0303b24375a6fb1c09849afe1368f40f3682011a50587992d09c2ff5c9701ec1e9a4bbab29e8c3e1b450a77ef56e4b9b53ff0b +generate_signature 13dd60b4ae30f8146fdc6a54eb8018493742413dfd267f18bf0d21b380dcba18 8b85dd2808f4a567bbe3bc67bd11209c98fdd6d177678afe6cbc6fff19fa2d76 396068b93693fcc4afac343f8955a705d3fdcec131495c1b131e0ee9fc7ff80c 3360cc5e1c167861ed00cf29e33af7ac6723b1d3fc87671974177519cb1cbe043de7c698f31c777b9aab37257133f74e7ae02a077e69c779010a83a73ea3e003 +generate_signature 72b57bd7a1dc353f62cad2299a225484014343a40ce052f66ef2bdd581f3d5c5 57427bb8fc70228d84e191047948c9bcd9582c8f1b3118f56064eda938857a33 daf6de1663b64ca4fb7660058f16926e1fa33175f298249183c6c8d862712d08 52241f8421b92a6db7f3cb5e4354c57377186cb363ebda0bc6b19a3b76d9ce0de2765ffacc1033296492a3674ebbe8c7c7b5e1ef227d6af878ac975cf3af8b01 +generate_signature 0e5824738082572ccd6c9ac2b97e37412b432a6bb4a1101234bf77d2a2a1109b 9ddbc2b910f572818af16baf273026b8cac3e6b7f2fa540a9bec2b38d2020dcd 3f4b0832a84cebc9377eadef2fc78a62f6f32576258c8d2424d7dc7669213d08 e6c4a2c09df2ab7b792e81362d5bb40849d7cbaa04fb1503a418ef49d14edb08ca87e0439c9bd7ee98a777cb6f56e2c7d1b7868ab4d3bc645acf364d2cd4e80c +generate_signature 459f98423e876494700752609232d068596b762ef006c299750cb3ff573b0104 c2fc73baa1d5897f75668116cab853bf359f156e24b19a745966512f6835bae8 9ae7c3212e6695e0f5668d062b2291b27bc45affa1f77b9bd65951914a842d05 4a9e7a5b8714ba08405cab94b3eca9b8efebf50d78ac1cafef4d78308d1ecc0481225b5f8b1ce2f8648c4ff736e6278ad7b2355aaa7d7642c9da210c63306008 +generate_signature 6d176d259af7ee75ad769376ea2a5ab9accd9a9f4d878192759f5dadec194f35 2317f20756c1462f4d69d36275fc14958419769167eb526fe6a4f3007036d474 1bb97762a71f9aa32b2f7733f1fe1e0bfe8e654ee6f8361f83a61a22f32d5101 e3487b2e542c212cc9cd0067052510381bf89147114aad6c12e00d85b3859100d2eaf2f56590d1cf27cde84498525522606460563840d6155d4ca13df7628002 +generate_signature 88989b9365a33a6a6870f4978d8a68c2b310f7f6f6bcc3c7342fee9a2985400b 09ff1ab9622a87b66f39804ce7b84c1620456e83bd2ac9fce8cf3c8564170543 f3cf70e5732cf0b4fbf81f78e95bddd0166aa597c2a932ca16d9e90a2742c80c c2a29a2768211cba83d97f3f27497e4d40fa7048b36d49e66c4f156630dca30adfd23077795540ea4609e23a8c8f9296af2f8a0921f4173763064ed537f2b00e +generate_signature 72f08a3499045d8e2a14b4872a89a7b53756fd3dc0e538ece7093168c6f88b06 26ebd8fc7bf1a0c6c1c8f55f701d66411ce6d2d2a70f87c2a5ca42e0f8c8b359 75c532399d4cd4475ab2714f0da1f6b1f131ce4f18144b69c99259c58b5ac203 0937f5a52694d976464189e4c581668a445808c888c3cba9c6fc69ae7b3fe806f807784ac31b73939fa44b1a723ed81ce93816f54e3eb4c6224c3316424d7b00 +generate_signature 9dcccae9215809a2a124f8a3bf62b5bbdd0ebe6d7710586c5355c7a7283b0e43 cfe96abf54cf0ab6895ee0a7c9fb90ec9ccd654fd526c36d2370398cfb7e8f6c 911e17b1af1be9f9446dda5d6d03de66c64d0a785b60a03ab7b26e2068c77101 3779bcce6cc446fb4a76dfa8c6719116ff1c9890905565439b811ac3394761072475da7ee0c42cca24fd7c94f74e26496575c166c8aaae33ff9a6a632353c50a +generate_signature 841ac5bce833dbb72069a88c959cc59561e7f05baaf63bb7fdc98a4d6e1dbeaa f3e8bb769efab6217972ced819551c79f29bc32a131a2ba05ab26c33d62c6ebd 858dde600179ebea9ab1806ab8e41ed2abb320ba593faea28eafbb5a7f989206 a39b20db47238bb0f548ae4b2e09d5daa739227058f19a613597519199393f00c55f5527d81fc4dac4f70e66c0b28a5a68b151bd04cb700e8422c911385b180e +generate_signature c570dde787ce9fcc3d48c5ada9054346455ab9a11a1d65b0eb223547bd39d7d6 426ccc3e1c17db41bb5c975d08279f1451c00976216271c9bf221910ad1eb8c6 4979107437a699a931e67dc36312a1c0b5b5edd3a60c1b3dee3c12596e500107 25ccc9d2c4e0c722e9dacfa13cef0ccd6c1a9bdfed94f816e74efb8e86bbcd0fc4c184d6065bf72a9a98c801823be224fab86cc5c42d40a94eef7865c84f8305 +generate_signature 62e8187f216da0c992208f3f7afde4e5ee42e0c09ed9897b010430170bb87350 91eb9815ec0a5d2d2b98bde3a097db217a922089e11c4b15d9e4109b6c534b56 4d2234323011d6837889e21b7482c69925eb483ba5b367ca48f5360cd92ce708 503d9bdef5dcd1d1b2ee257ab142f2d7cf104e25f48f5e7f809c7a78fe7c230c96cd3ac35dff748263ca9cfa8dafdfd87fd0c735c1ff5f9d54b016c19688f50a +generate_signature 49d7e10bd4a42988f7b202cce474c577619f9bea53a7914de4d295b8529aec80 2daf7743268523b94442ce3f0be3910f40771a4f18a22b52f3132b6b5ab2b3cd 5e6e1c05e2e836a936e17a1765b30165f3851ab56ca1e38ac459c8b7a81a2004 7f55cc8a43b4eba3fc2a5f46fffd0d497df66e76a0b626f2fa20118853009a0669f29b9b4fabe0162fbb9e8870c3903a8db13b04311dc29701dc99a6caa90a01 +generate_signature 51c27e54ec56e597dedeb33c6f2fe379383a8df301688f95e37fb695ce64b1e0 01487d5868e86da7cbfbf00ae1bdf8faf8d51a40c5be011a1ef11a2734616a38 e844859d1b9a5328533fb41383c1ed108a110e6413c044cfec538975bddc8405 015582aa8f817c1618e040896477e4cb62909b0ea007d20bc8a8c3958d5e920ace7d32f5c91a9e0125bf8220356ebfae0f38454087046fcef6c6e5378d527b0f +generate_signature a26bbb54e14b7f7587fdf8b0c308bb80e3bd626c20a6980cc08b9f25317aa00a f248b297c284ef1114629819876d311bc01926a75899ab339891b4270ffaadf0 7c7af96309f390370a9a5031b9bd524936233f5f806b9c45f3821b91da8b8706 7fe2bb58e7362f90ac1ef98041a773ec6fb8c465e45c98da0a6b4fcb2e4316054dc228cc069239a6555d1a71193a5f72c50f1ddb074a4e75db884d60cb221507 +generate_signature 18937794c31d063933d48dde3fe7b5c6709f931e139fdd3cbae74e68abfc5cfa 4abf6a6c47126af111ab9761d8136bbbefef57cc6eb6ae4693803ac915351fc6 4acac844a196b1754f42f9af15c6aa9893bd00b5f466fb691ef396149171ca00 b404976ed6971555320c5bbe25d84d1319dd6dc7c27610cb6ecd64365e8a1a0f4b6571150fb70d9b1a6423d4c7d6c42ad82a84857efa4fc8a434a62d78104909 +generate_signature 0b32c806869d8b25e120317582013a95c995f9347814e4e37f6b948b4ba1e2f2 47397e6dbce5916e87dff2a55c63e49d1bdc826d4ead31401d47cc0a37d99352 c852e5ba498eb8b9686557309591b1e9b0533a07c97bc6a8186c036bee2f420f af4e4856ec42b7aa72d086166be7f955b25f7122fc3a0de1dbbd5629033b4202ffb4dc7914ca906c7f6d01eef2363378feadd95b0fdc3ffb70aa5f95aee6d909 +generate_signature bb5e240d1bc7e986e6e929dea3095830fa11b51fefae6cb1bdc8e060775905e3 7ae97231c99afe3dcd855aa587f1acf5f62ea0c61cba1e0c14b0fe4fd26a7b1c 25cb0101d7914aa49cd52abc533a7cdc00f174ba107cdd6788a1f64ff0ae390c 2a8a92ac1f138eb8b0bbff67cd560934b57539d35bea3fe3e9d6c27bf06f2609214c4f6e08d8695315cc5f7ded5903e5f452c95c2d2f0f34710ba118cb8d2e02 +generate_signature 30d230c4ebda0c60892e470dc95ec1152b00c8176c6a93ca73b3057cc7c1a494 20200fa0969e8ecccde73758c864cd4079a9efc8476776755390b9a56800be07 4cce1e28f0c62eb772138560e232b27c44ec7ecb7081bfbe07de7d7281c3da04 338ef30be4b480429471b654c2c3b718ba81ad2f4a14945d0ba5a26d097a69003a863ab4b89b8d60ec611c5be670187d8878076ed511612dea33421010ba830c +generate_signature f1dabb3ce43a519e5899d465abc054635e9fb30f3d49dbacf2dbb54725041d61 2be7da84b3e47473568338ddf79a8c87b22f29ef4295ae6c6ca463df3102278e 8831f066a87841b2beaed0f20b93da8cc730e303bd135ca540511c6f697f7f04 2eca25854b9ba1f1c6d8c8741ced2638fba66c583ab48bc3ce6c76307823a100ece3022cc59fa1b89e85e8d99f5e724aa99b05ade28994d0314673ffd0fa6204 +generate_signature 5d60c456bf82803cb3830fa2de437c377f5f0ce42b762a0d2a5847b95d6d4400 38aa6f868aba852ee5f2c2444212088ca48268451ad0bdf5b42d020db2eab246 208ca6972527da0e4333b6d756e5c3f336d70f1af86ee8088b050e73dd51810c 8a674dce74e1515af9cab426630b1ed01ef1a2989dc9386fbf21a1da47a341076c0e50bb3dc1c55b02f958deab49d2a3241f1a23bdd67c944f1578214c24cb0f +generate_signature 58bf45b4eb8cdd324173894cbb55511bc69ab649e1dc79311bbfa58c6c0f9275 a429e66f32ec3d35fa825eb5b6357f4daaffcac3a11c47ceb80ef1114a06a217 c3330d61f993dd6652cba521461f4280d83330119a6ae92681b708ab32418904 a1144daf6103277399a873711ffca30c4544723a2f406a2067afc1294c77760162adb58006d7ecf56a820e3d63f2ff0d3b740a1a803fda34783d820a43d35d05 +generate_signature 2229a90c79f0e3dc230cc3919066d3e4b385ec53b0559f7ca8b611ee2f29e12d 83d93b52f0df0fcfb3d6e2b13ad01ef38c494090c18014296eed91a5d988b2ac 3e286618640c874daa6e36dfb01b5e2d1f5d77b8d9ca6f5ae5b7ebe659b46709 3b899b5e2649bb28fcbe417a052f41d1b0517de3d0066d1f5d93e2cfebae3905b7c1200449c780c191d4cbb7705422e0fff1bf1b05ad3ac4c939b3ff3fe52c03 +generate_signature 9e47f640aaee7ab2e09c8fc12a32a531768258c5135eb8e521965d8708eff2e8 a8411a8de998e4b6be239be96460ec6d4f4a8b616b94f77347838212ce4b8613 cc4598110b1aff2282997a410e7cbd837e12a98461a6c6ffc307b77a323f0b06 34f38868d728155535a0de9c2d2d219acc84c99c927211035f08826578d4d609cbda56fb3184a3c9e4935ad86cab83576fdecc074c1c4bf92f75d5d1e5c7a807 +generate_signature 1fbd47cacc32270ecfe0bda8b1b1bd9ae4e03a794016a2696eab9cb0ce2c40dc 41d8ee40da7c75784b464f1b2fe89409f898fc57f395b46ed0038e98c184aba2 ce061c022ad0ad3125b6cc34b0d27291874d29575b10e1d44528ded224b1500d 4a4c8233ba1ab2f05712e0af21d7e9d38e758c603b11092b9bd1e36a65020705c26e9a9064b6fba349c24c4a0230490eeba2ceee353af5e2558dcd5a356ec90a +generate_signature 0756833a04e57930ad436ed6e50995529036c5b55db3f9ef070a000ea7b3b668 ef541d76406b4b71299d45937ffac3a4d284b61faa8644775e346ec6f6eda51f efe31b98bdb433b3535e792aafb0373d66952196bf564dee8c02ca0dabeee40b a8cae65d2cbf994cc0904c02612c25b9c6ce727f85ad2dcfca97c0c5625f650ec4d9d41a86b5f554dc4f9b2af8cde1423d5a596b37ae8450298b35079ce5eb03 +generate_signature c5d9d4483c4b9b23e21c259fa19136f0c69cf2cee896945510e95141ffbb195d 39e841d4ac6335babb18e8d9e47e1c75111639709335a1310db0ce2edf686871 6a2b88bfe8a66655b29e20294d715cccec610efa3503cafcbcb5323d8e618400 7cf5ee670ec1be776f72abf6540c382815d4ed1d6152e1d776871c7769d22c0783809d7debeb670da8e3131f3d92867f62b8327fc51e3c8138bc52d5a39e4603 +generate_signature 8bc9f9c21660ee20ffa666e7be110d8accd2d1be0550aa5bb3b4ae905418b060 14b57372138f3995b35fbb964ed0481969684f0338470a637e183b9780191372 85465783ede0e697db9aedcaba7f2aad3f4fda534db37b9654a3325dd4361302 11c0069e241ee95c599ed17155b0b7b290b11d747756ef850bee4c32fa21710726394ab1e2936e55bc570f067df43b967d1ed0b02772c63cc3cf8bff0d87a206 +generate_signature 7ed3d902f3ee03f81674c4452bb1cf33c0601fd27e25d5aed0b618b55aaf7167 458fa36ccf56bcf966910083e625c7efd4114daee53c45f288ec2cddeb444aae 3a0e8fec3301b4906383419798381d28a2a26e9249a58097734dfde9b9be370d 367e03c6f0f4958b4aae37bc623e23c029c3cb3f8880f334b2695bbd36d66708d5eb4bcd118c1d98429a09fbf7fcf2a0f7edee796d040634d1816d8947c65207 +generate_signature d95b625b3397e7726956f869e61df3634ee46b08a914a6a0b10b9e427a9179da f2cc630788dd65572d325ce0895de974fa3d56e07717ce2776ea51a32a542644 921c6a6d736c246dc6bef590f359f7093b32d56b05cd8639c7e94541caa2a504 298283996884ae9121ec7334866bda5b6c2eba5f2ad24684fe4eb5b7be70ea03408daad76a8998070549d5c4c9573ad940581cf4a3085bd90216b386d1dd460f +generate_signature d17c7a1189954c38343e20e2b8e8a290e294753072895948d184cf0d1c3193c1 2cfe22dd27f8b7041cddd1b8111a29a1c56b35989aabe9edafab342a484f372c 9317e035d8bc4a451e52ff94e5594885823ad2cdc7eedf66c5231a4f81bddd0b db863411b28fe28387e63641a68d749f3482e77cac071edf321d7310a884780de72c0ac3d2624f2b20dfaaa76706cfe7de984d220306dc0585082f296fe52f0d +generate_signature 9387ebacbf7d29655f65513d886d006af10a8c75a11cbcfef8f530a72fbfc972 006e6a957483b2f082fae65ffd18fd525bdff0d774dc20ca0b48b9cd8f592b2d 811da01862356cb02275a0c7878185670732b10c7de15ce1b2dc9ace1dbd8e09 99bdbbd78277f0c91d639554125f86cc05191e9059a730406621383d321b210c23efba37fc10de0fc4a4404b36c1fd08a51a005d35a59065cba54654d8b48d01 +generate_signature 307a4932ef8f15539d70e8721dfa1a4142ba4ed7b2a734f8fb37ffd31f72accc e48b91027d713f4e5ec7d0fe315589b36d6bc6ec338e218f31eeea8862209922 0fc991a39d51dbfb559047a95078e8cee3210760eb9c0ca860e5fa48e267be01 25f98df0de5032f7ff04f9d88e6a52e980560050e159648869f1c1a89dfe2d0ba93c6704740a4858afd5f5b0afb1c6bb6352e1c6fe20829d408851f9c77c620f +generate_signature 4366484aed2052c6c28d935b2300b5a4e5172bd79d96a37393df3584c0020b2c 39ed6f8df7c2d04ca843e2e76bac2c6a4de490f9c8d1c4ff16b70df13588a4f0 de879609d955fb6ddb4b0609fabb4e49fbc7ec017952681f911552eac8ed2d0a 68a5c32667677cbaddc26ba53373dedb3d01856464970c51d100ef578e520e0cb041b0d2f26dd07a45ac701544b0da8acbf4d5e687b54219b38f52b6fa4a7209 +generate_signature aeac4a1e1552df635de365394f86621ee2f21f7561a71a63c07fffd53fdbdc0f a6a9623f5791d0194199f52ea1e4c77be18a94541e9fc8d86b591ac8f1c0c3a1 c4ffa6e43fad2e9e558118f7b5a1cd2196453f91e1aa3691013209c7f7bfd40b fdbaba776d6e5d712d156001d7cd0e5a553b82e3f47a38a41d20c32a8d434706b5503e0fe2bd9c002796ee6daf7b043a280d78ce606649fb7fe096468a898802 +generate_signature ed905056a502fe94edd1c28b3f65491330b58a1e2563dbb8d8369651a2b30cb1 fe89f71bf6d52874eb89f234baff8c878ccd22c5c614ad18eac64f1d49ee00db 9826bb63674eb73980eab3d333d90b1ecdd18a227a34e729ac4aa4c679570708 dbe59b9cd64e6bac53ffb2fdfcd435110422375678060189cfbeb4fe1ce86109be9666aca6288261542a76878e0622ec69737b0ac2a652534cdf6dff93a4b309 +generate_signature 327024bcbf89837e82f4af135ab5bbbae710d4fdbfd771423dba6d089d62ecbf 089a1ffc8c9ee8b28e3181694127146615db3ca57d4f808e375b0844d68e4ba7 9c7c12aa4310db31790ed6c9041b711f0c742fe3c903e3093e2589de9279130c e5316ad5754f17a634c4b42ff468e4c947d71f4fab436d48006eb240c2daae06cf7c22ea2808bafc702cc87d18021e18a3d64ca1c0c72667438ebf11516aec06 +generate_signature 5fca639815dc14114fa452346ca15db70f4f3c13a1bd1dd2e5cc6633bd884a97 0acae623f287aa3b9758a36ebef615ce9aaa16f619d3cf56b7ceb515e2ea5c27 11569cbb68a9b17a1ac43c5b6b87a9c94e269ac507541b87accb5681fda30a04 0b5ad5a099e313af65823d12e62b592294b84ed7f3afba7ea93fdb114d7271024904f7226d47049e133c618bfa6b637e7ad2af7d38cab5309076166edec63c03 +generate_signature 0f217303b1076cd895641ff1751d2d469def5e140e0d61dc1a4239c3decdb382 d0cdd348b338fd12dd2602b2d5a872e820e1d9cd6f0b2df9c5c4a04e49559a62 fad9edd7ad17647a02d8f2077b9ff3c0fc755e5eb071165bf902654e7ff1050c 90fb5f72cb658cc1a3c0ca2825e4d5f537fe41fc3daf56389a2e583b5d4084077dd3e3aa872223f18d7a6ce32f9f41ddd488cc2324f1181f8755b63897d47803 +generate_signature 254a879d64f8532e5f281149b52a68bcd96c2148f33e3bf7cabb4dfc3450043d db123979ed900409c0090c74705fc059ff72c4e1ed05656b117327e7d3f68d4a e39e1a551efa30ce0b2461796147ebd86394c8c0abcd8fa8118fbd7cb5f7920f 25e422d0be58daff492e940b63b0789323e6576419e968baeb0f50886b16030d0d061a633bb530a81d3132fa4c5ae8560e3189f0d8f374e56b15cded5ed78908 +generate_signature e65ec30c477ec561fd8dfcdd1a3b89c099ee7c415de5e780618433c3209b9824 e45c9e7b6341e47a07e794556c9cf91869cb97291fecabe4867e036060c81ed5 860e36d4b74b80737704a4db0ac58e4181d807b6a0ccb4064dee200de67ae603 9584488bc22bf89b434a1336ae8782135ead120ca7ffa5f433bd04b0d58e5002f9ec4f1b289c49695830f3e65e9073b862c85cd6ddd37602a6027b131547d006 +generate_signature e701f76a8a06647e5e10c677a9fc17ac37c628580bccc5500f34381536b88b9f 1bfe84084ebb54bfe97e3701eb27cd77e585f510270dff9b22aec8a688d0512c c7d74b95fddc2dcfbfa0ef72aa1078f62b786f5c0d0650782a2913b5a22ca609 b828a3b11fe142d18fbf618af1fcb32a7af30b4f46a517a9095f9f2a84c6970f973540fa9d18da9fd3e16d36399834bdbfed9b0d36902f968f04e0b55976e00d +generate_signature f220bdb877fbf2bad58a7e98cdaffc0047f8d4512cf884e45c484d5b2a19275c c37d89b27a7449d9015b93669810f35faf07908d5fbf4d93ebceed9c1021770d e4692ca12eccebdd039f9d234a083b49a184b7d241025e4b27d022fb9f46c802 c064488791109a0790e9e4f42ce833764f9b950d1736a2f41d6ef147d706450decc0c664a4c7fc5149cc09c8e62f642de4e2d744d9d6d3571f30c61c836f5308 +generate_signature 2de9420d201089ef5c3c1fdc2ecb69446de59b44b84813d4f2c60c4762cba262 ea272022926e4b6059728e63ea0530c064280312e22e82419a5463b34b5d223a eef8d695f5b62c90c77bfd4a4e257de3defea7eb93cd546db2f0c448deb08d0f a086005e4a7d2d691071907000230bfbbad3390f349f82cef80cf6767bd75e0dec606b02818ce432397e201a79f5fb42faa018994ca7e2c789cadc98f71b1708 +generate_signature d22270489687f1aefc08d45cb567859a5a7f0fc6bb4346ff56be386f3c64ba68 b231b42bafbff5286ccf0828fa423487e3edfafdb3cf84b4333b92f7c5f8e005 3d6b4f25367114c0fd1922209e6d6ddb062c959f0643d6b5f5a54aa7a8dd850a 16b0c04de8cef9191c82efb19dba677954f517015484acb8b6dea5a57f458c03e1e92846badf1708cd559c174ebc2fa57d830a6752ed1cc06467c0be99d0190b +generate_signature 0f80ee01c68b1c0fa0f72a6890a523e2f941a934d5aea5a37756fc9308e3d149 40485d2af8f529aad1cdce430971bf593c40ea5f650c65d24ef2f3a1d6e09844 ba73077ab95f6b2185b68884e757c95ff288af975d70f54e6ddf75446b59ef0b bd98fb637f018b9fef99da2655d1af03730bf9328ac7425362ce3b84b4a8e90bcc112eaa3ddd9b4812fd335f60c389ec3a91af79d8bb59a8ed09f502de899b06 +generate_signature fb9279828f9075e43491950ee0a6b55f2740a03e2803e20e9baf42a71845db16 a60c8215f4c3144d397db32359b1638a94bd48efb4921488be9bb2dbac2d3621 24d0feecf4a09080ce8cfd390619e0f0c9185278b712b9a22f23fe6d1b028105 35cf88adf40263482815c30b6f768e8eaae6d7f32249a1ba6dcf8a3b256f2e072ec609635da7beb565a553a09527d34f1ff9e0d5504f98c9bb3cbc6d33995305 +generate_signature 1853a3886d3421c884701015146416e2372be5dff4804a87c367d69a14ce1674 a469f283112cb9e1247cb12358e1d1f0c2c1efeeb0311b4921a4ec3c2fa6149b ec7f0053fb49ae322026d8dc884d02e4784fef17469b85415f4bb269f833410c 739306ce1972cf3e0341d83f77f8ec43da75adc4240ad801b46b57d3fa54190d40c90bf957c8a410c1395b5889a3f30838357fbc7e8cd17f15777c829c5ffd0c +generate_signature 87a4d1813017c757f2fc7adbb6346bc711619edaa8531378e25686bdde9b54fc 8e1cf8a065ebb111aeaee0458198b02e9df18e357e60604aeaa62f0e7e81fb47 d75a74c80860cb58614643bde56d7d0793c57750af954f4fe949e08d73e14402 199c92f8a1abdb6903d4ce7f8fda12d9f5bf22f00ea4066cfd3d8c7687de5204508880c4c9e4fd42edc7a333dceba1882b3059abcbdce643e46e8eadb4c8a808 +generate_signature 36332e7b2431dd072a158803b24744d01b69f096aee41407d70ccebda99984db f37969dd37feb2205fa2d7c87d62bba58a675b9ee08caabd2496886059a5aee4 fce10979cba19bc179dadec71cdbf640bb3fcdd3afd07dc0e61124d293ae7209 90364254b41cea89c5464a82a6835f89edb8a965cd10c24240036bc16d1b250300ea72a7f3353331f02635df81499c11a3addaf62f0c8e175596aa6b41ff0209 +generate_signature 2c7db34f2f249ab08724d1a679fe855bfab2ed68228668c7e712b4760a839f63 ac948ab799b000d6125355c96a4c7c2f7918831e2cdb86c66f75a84ab3b588d8 711ee793591c685bde7f3b136751e5a39d55f0cdcdac03631ece1622a5982904 c2fd3aa8794549c193ea064c358cbfa93f580b231ae8b923d40e9b7dfe82e5059e63e2822fd16b5820eb0afe46f8f364d3a9d83f71a7e0d406b6a942da773e00 +generate_signature 9f92e54ff6d3c2033a5ce9135c8f079a93f0a7ff4c94467d856fc63c0e96fbc4 c6407e167719e2dc8e9e9d719b1ba7be2797eed2e43dd27b02e8b7affc6ba801 9a3b191d1806472ff03203d5602b9cb73d3f0262cdf56ad70d20119941f83e00 ede68859e81d18868e8abb438eaeff27ae05e717b56ecc8ee5f7fb79978fa90817625d4bd942cc71157d63f4a237138ed9fdaf50028bec40e7e2c959c39a2601 +generate_signature a70f0611b8337641f0d45cdffc56bfaec855fabfeb6fcd3da1292206b4a03309 0baef43d5b9d89ad7572c413b531381745af1dcfd1ae90d4b20f0f78080f2ccb 9e5527c3b3da09edcebf39183c5d912e28f47befb833177726833e281748c909 c9e9d8909c0e8dcdee4b0ed4303981e07640828a2b8e5f98efc9e3343132f70689cbaf2b91e76234ca85a7a91fb8da68550e496f79cefee8076cd552e9be360d +generate_signature 878f172b5f34e0b18a55df0ca544d7dab961eed79e07fc4689a0a3be8b3ecc72 03971f351d3e118213c1762bb564a2b56e3df37d3217665f16f5193fb82f8a5d 213d506a9731bcdf5bf8c3968d89e7385ee573aba69d1572c3604cdc29e9a200 13e179eed35b869797e1896da4d546a71e4b896447e2393e940081541d1587029c40bc96d6f7216262cbf98c2a09eba791a9503229f1dd63098ec90308739f07 +generate_signature d5c32a4a81da9af917c63f72b91c14e0a8fa93413572b702cbb3e9594481deb1 b558e0724567f7b4b08318ffe6b0dd0b53cc4a876ad1530692f286b068d19f9f d5a64d1b5c47ae79629ecb770ccdf0bffb1148869360958202ddffb2b5a6340d aaa5d73a65d56b2a8435b904a0185d0c6f81e492e4a9f098958865793f0ebf03015a210f04201d8293b1dd12cfdfa5c2eb9c26f6aa2f4173728b86106eecd30d +generate_signature b3f0024e9682ccfeb0d69b0c6d2f0911526899190e7f0fb4eb1e600da16aa63f 019ce545f3b46419d987730c551e1787ccfa158bb42a8f203631fc211e492c6c f03757ea2d5b66ba968b93e5109593e8ec7f4c6809f15c6f6d881b1f76435909 043251f2e9026d8b0e34084847820c3965746a1a1a017538da078b476b8ebb012753aafea088c997bbe33b7ce3062bd838d6eef14383279a47ef7db3e7eaa401 +generate_signature 0b18efa336170b3a6683dc486d1f36b6c4cbe86eb310388f71cdf70e143d0aec 987eb3e73980b221b2524179565720f451786f8de2b3407c8b5716ef683c15b4 d3db1e882a144f312d1dc307d8bdd2eaab5816804329bc36430803d23744530c 72f0be4b9c5ae0fc46a078da0b0dbb79c697842f46a93cb6cd6396edd6030308ab77fc89d46c2039b0f6502682a11ac0800d13fd7d4ca0781c58e5766b7d7a01 +generate_signature 69ae4cedd012737619b29be8065ede9f93b324b50252024d928ef04c543a79b3 35a734465352db4e813f76b446da1c00dc703317f1ce52c8a35a0cd571074568 ebc39ce202ec647da79c7af3ce6ddf307fc44de800a68a255c2e7dc7ff997204 1eceefb57b45fd04d82eca32250e01e69d59afbf3a1ae4864ff0b89ad88f620f0b56c19fd19f440f5c00c66754bb8e0c94bc4278302988676ab259e52e25cc03 +generate_signature 065fbb38e8325511ceb9aa041f32aac98a5dc8cfb06a85c98853b25cdfc47057 281b3c8844fa282b064d56acc83e92c8e6568c3a628645f63e40a07aee80aeb5 bca17611de2f9642df95a938f64894a4079ad06f842cfaa9bac087fbaca3e70c 31d6ce571ea3aea0ccc47f3cc6c476306ae680c872b114db8fa036e0e223d70a10546247efb71e8884897f427fec3c36adbc472897cd1a36081296c2e39a7508 +generate_signature c13ed90a542fd070e07610a0fee13cd42f8753f3448591ef9c9f57ad721fe9d7 02cb435d82524b0d03853e29c7ec0920556b85fa12886b063cf64345dba55483 e90a0b4646cdded432d27a6204c67a76b8a3db2dfe0bb2ac6957d68e6aa72304 8dc9f87a4499ce17b34ebba2cedd68bcfd69424b02a7b17dc616fdc38701c304760b3bed175395de2dca56fa556027f9d796652848d0ad5cad294a22304f3309 +generate_signature 7badd2f8d2dd8198990738617145e90c87880b95d5c875be0cd7be0dc25e7839 240b3d620b61537d7fcbde252e9de6da442bdce4e24cf4bcb9d13b50206129d4 9d9c7c91e5d71920ff7db53015814d4360eb7e398cd6ce8233c2a1dcc54ae40a 3a9e123e474d48dfb1aafb3b94e64eaa2db9a2080bf7588e2241c3782790c109ab8692ae5b95c40fce03b3a0e65a6c32acd18360ec3384c3b44cce7c1671c60f +generate_signature c537ab8551726c4d7ade51835585bf7850fbbc1d57f9245fe1b29618e2aa5c30 1ef9913d379ce22e9f97757c68fc5414e73a27e69a55ca223cb5eba854888d90 c3f5baf38db5121dfb177a0cac1d6bc423ee0c8f7c1323d9b691b07489006b07 79ef50f1d6fb5fecc8b4889556c9636320aa7a70ed2f79b03ef9ac0345745f026a9f3cf456b11ca909020decc176e9f685a026680cb7f8ab28690a922e7a450f +generate_signature 696aed47faaac314742d0e6386548c68617dee798a83105d3746747fd06d0cbf 279e1bd9754759a921c232f37d744d7b57531a302245dbb54f95259aaf923c12 28bec44d3dde67ee976fa0761ff650fb0d9ac60e74725e4c5ba3d7a0575eb90d c0aa4aa9692dfa2eac7de552ce7f28db9511ccdcf78078ff77dc17ea40c9580dbe618432fccbf259000b2327299e3a8a678bf446869ebedddf00757b5d72d600 +generate_signature 0215e850ee377ac137b6f9ac06809bd6cfc31918bd0a372155f28d45c65eac25 45621dd9f0fd09053bb23b178886d7f258045154ce90a9576d708f0d92ac656e 0da2f7254d9796a93c9ebb3fafe40d398726941e469c6f8deffc9c32c2b5d00f b88e5207eb2578abec6c0bbb59a86c4238d868aade8ac1433ef9c6e6e18c5902832887fddb21ca755215ec73543cc2ad13021868f726b54c161960586cd92004 +generate_signature 877a11a34fea5898e4643861721def338135c5cf6dfe1a6fc6777e77fc68d245 9e47630b2a88e9f86555a6a8462a435c0ac2c45bbb85115add2c4ba3dd578031 a3322e75481f1ae1eb9828f57a2b4cc1c786167aeb54547c36c936600747ac0c 9e46a956ff7599b3ac5f3927964ee265aa101f64f8a474d50571a16d8b4d8d0f78405175c104fd1366773e3e7c2a716fc2db8324bc8f4946c681562bf9741205 +generate_signature 191a17e4ab9fe35c2b1ff3190967be43353c62dba427e461cc6a2dca6b12228c c7312755cd3546fc800b0af704752069cbd24d4d132f4af435c149d1024da97c faeadb6cc780147a42bd6d1968169e088a0b5b5025171ec01fe7ce17155b7d00 962cf93f683aef368f8e2890f0541a694f47d781c2e1bd0ac6fe09c33985d10918b870e6961fddea524d654c42be61b7ac64d5d88ba18dcf09728f95bb66e000 +generate_signature 37bcb62ac859e2e85caa766836436533bb47f58b8748f921d3b1bbb81f9b51e4 bc46c4cd6ca4c15d76864b66439d46e8f8ccd846e899f18ad782d6a3608e0c49 28fff080636d9950ecd5dc362736734a75a72851823c7e01e7489b28c462ce06 06b118cc6d3daf76853e79ef4189c28e9ad90dd1775469556219898db0b0ae0236d34e1110af16bd3ca11b5c7d01cf10d774819b7698daffbb0bd70134d0f808 +generate_signature 42a48c4a50b87313860ea656a1df5698aec2a2f8d03e69ab24c7f9c7f7f66056 e4e4c0e5cd007712ed5120892e21b0615217230b1370f9a531192e09f5463f1f 0f98ce51f4aae0b3c5c549fac5d94fe0587e38f298354f36e6a259843322740a 4c8986e523a9a84ece8ca24540c85e24d797e8293612cb608c6de8c8896ac408265e13590313d03b2b3295b3f6db6fca1ca30de377da86aa17f7f3e393019504 +generate_signature 2280cec561410c47170e37a38805c146ac1a8b73c1691537fdd9d10a9c430579 21ffbe4f3e0ef3bd589689c0f2c35bb702f121d83d8d1ca62554220c1da72e56 a2cb2795994ed3ff548fe707d64f59369cc6e893ee2ce9830ffa526b2f41f402 1641215c1460262c438c1009cabac6664d7fdc87b82bf6a2ec2169807f6a2b0d9900f15e1e3ac58554b1147d6530f3ca75807ee8a8524e91e3ae48a4df6bdc04 +generate_signature 7df35cef6dfe5607c06a64a38510e5c42093c703a88d5d76dfa97b14a0f6add8 9211c6183c199f81e344d3650c92b83c96bbbacd6ae654d8644b76a21611ae07 16b3d5bc1949ecae9e4db756c129c71889214a5af2ff78aa8a479a0c5d0ff90c 8bddaf50c0154f316a0aa1c12dad2d3559af4e477d8e3c61ced389609b26cd0ef3c2d3fc6e129893f14ca79ed0a6c7f5a61c2f8bb5eba6f0e8f52281542a5201 +generate_signature 4991a192c5c493c47372771fde392802036834e9fa14ebf5c4696e40420a4c39 61c0eedb78215458d3c724551d7220f92b8f70aa656514de7fb209b26728a083 ff600a4ce0fabd6602b51e9636ff9b8b9e102f1da91f00376aa2e50411deaf08 e0921c2778c1fb90a0891ddd377301f49f74dac323a8571ce1db7e0c770ec609b0cadce3b0842250bbc71390406195c84877d7c247dbf700ce82cccaac01e70c +generate_signature e9d7fa57a984dd1d9c7a93125fe69f4d408c821d7c17d199ca494d16405c0daf c536bcc2db715ae003881137da965ff0e30dbbee0f4e29d5a439547b8cd48175 1148d655f1e23fec319f04dcf5c5ddf131fc182b50e39334ec0f312e25429700 fd7da19d78cca772035aec81420f3d1cb2917a54d0c419fc74f9eb51c7b3e30b4ed803843094220845b8b21967e3fe06da3609422337b3db9e7020ffb9ce2a02 +generate_signature 9c619840f7234b099d0995b905a15ddce999775aa1720f0bc9477bbf0c5525ab 4d8720590ddcf790a1baac573dda9ddf0efc21223335b15a23189fa67f515ea7 dee02eb9d27969ffdbe6f7c22642936e5965f3124fdbb0c51b1c44856c075a04 943f356fa0ab617bd2c91bf2a12c72d47d2a18debda66943325ac5300bda830d5ba528ee4e0eebc21851bd1e2f7eeeee20dfeb236e615e805b53489b40fdb203 +generate_signature 4e5d10eaeddd0acead90bb49b03e73b84e966bb05d63055031cacc8ea5e49aa3 e2c8684aab1e9860370e94d295bac00283208ebdd29910d54c9a28477daf6551 4487e8f01f0ebfd7b1870e7a1cdcd86470fe644de11161309114f120683b3509 b6e37c1f8ab82f987dc2d91e8ab0e42af4d816e8bb76be04da74f2d520d03a024025d595a20ef831e8af6231516c3a2f06e29e19a970a95ac50e9e13bced9608 +generate_signature 8db465446cb5848044acf5826a3c8baea057859846b551238a0536dae39ef712 f3a88b4793016d12031ffa76a5da01dfb771e9255e8de871769717199b83ccdb 3ddbbf3cf5f282afd370de5d33dbd8464b805bf4d7c74be2410eefcb5072da01 1b3e07ee1f304789926c40dbeed125b861321c7e917b1c2da66e95b8401a2209a02f4ccfcd9d7f9d0cb2c171d675b60e9f0c3a7b8fa8b8ec3dce46fd4795200c +generate_signature 24979bf7adb7f8b840a3524c3d3bbcb73490e50e71400632d824f420427df802 78057cddcf685984606870f37a2f0d76e4ba59d169722729695edf4934528856 fb691338b3fe0cd1a272b7ff7e363727c66689c1c7cfca7c007a5543b3abd401 bafd700e423e566c07e38446db0609473023db1b26154a5fe9cb23a3d8d6a90b7cbf663e71739cb55fe72d2b78f78961a328274e575d2eaba9a7128b173a9004 +generate_signature 8866f2c3e0566f73f173a7e0f9e33cf8b1795fde4cb09deeb1efb17dd82ece33 28c508eeeda24bbaa55dbb312f534292bb1d8ca09cc34ceba36a3db1ae5aca9a bed8a7e6bc28ff86ed87c5f54d91f8fd381a2fa9057b6d38b095245dca1b3708 9505253708cbcd42f31eb240d62e79f7b2ecf56ef9713882f5379e4b7c97390487c3dd18e822486477c748023dbba046a0697c68d1e12de8ee93be9ca438700f +generate_signature 421c152f337614c5a007b4eeba8d4299f7fab313c1e4fa935048288d4b2531d3 862b1dfbfbe3934696a9ad41adf2022714feb99e5a1936ba2dd4cc08edd7166d fcc52b66e50a4761eabbbdba3fa82f2e391db31ed1be585ba5a936c31dc36400 7375b1b507d136d6517845943f3cd7afd9eba9a43049890d445d2db8969d480dbea4ad60624406878d621884724b21778c5440f8ae128bd35fa55a69ec9a720a +generate_signature cd4eaba1978fc73de4114aca7dc6708308e72a8a861c96c2eaa13dd06f2e82cc 88855b172e2e512fc6ae2bb6e1252670210b17fe4c021f97ce7245ef5e0766b7 fb333a06054d22771b8422f547838f14f4b868e6c0ffc7abaf52643b36e25a0d cd7c83b5573b8b087d6d478154b35f5d9c4e90a9319a55769e15b011e84a320ecc58e702fcb7fa483fb22e56caef52d0c886fb4adc13c4466b2d1814e705b503 +generate_signature 38d2cc1cc489bb0af029d12f1ed624bec71d68c0713f1fd7f5d367efe71d72d3 3b3df37e4fbb3a730b5f9c5a1f7adc45dd2fb2c05d1e141d939536b6f55065d6 f10b5d6fc5830989df088c2a1a9bdf95c37781bc8990b95beeaff246b858770b 14c4e9372cf5ad1b8a5bc0721620c3cbfe0590d4879a2ae12e17c8a5f0e3db07e7e8fc57a0b96e195a869cf22bd54c2d2f5a536cb15dcdd965853ff0c7865708 +generate_signature 017a5495b9f777b45cd256eb87cd298ae9d346caef147cbbb916d95a6b61c677 e8d23a7fa523a7d1d59d23f5929cdf9872ad01eb77347b076121b2a8d24289a7 d77e90cfc8bdced4c2957514ad1dd3ee2b4e841f843dc2cd711df92d31225801 b86bda79c4a54ed1b3be29e8f79f84ca8a8b04bf95a64dbdf61bd83eb33dd509a9a2b24f96ba9c79b04c428c14e83f11cf0af52ab5977543700d6e6d9867960f +generate_signature 5cdee6559376c9ce870c83b06a6492b019ec54bd0058c2051813cf600bdf25d9 a2def558fd26b3e1b9f1d13b131a324ebffe1412ac2d043f7395f060e35f4780 29e13e332419405883c0103dbabdd28035a4be98f8216230d4a31072ffdbad0f 9baeda2f7a7f9fa051ee0485d67c6e07ab063b4c28f88e67dfb1db25879ec60d48983339e33c0da1cffa49bfa5f3c18131b80f7e3e5e9209d812dbf42ba5360d +generate_signature e5f7e794c78196616415dad78d3d07439809df7c7443e44b82e54c6faa5bacc8 6fb3a5c5d7b694b63f29ebaafa2cb101d455d95d1b30c51d2027714c6048d81b ce2794dac0a5fab2074829050ff0f631ed916adb97c110d1d9c01f11fc572005 2e0a5e8d8dcee1b6047f892a801fddbcc6d53548e6297217a21b9bbf5aed0e090fd05e5ca8b23562ba47119c074bcc778bb1fbd8674a6907f5d21cb1b39f4b01 +generate_signature 5283cc05c1a813496774fe331d90989baca3a8932ed5d6ca1633a96e9881deb0 c776290262741f162cc11cd2c6ac606330a0c53fa543cadf061d844ef306920b 7012ea2ec897d4db791c283cb2f878103fb6e29c831549f2c11fb306a3f33301 20567c1a203be8c928969ecfa3f4cd02b9e2327bd4a5dee6eb9b477dd2c7570fe443bb37b16b36883d75ee9a74ce6b0e54fe6da64744a7fa81627de178c6e30d +generate_signature c7769cf2307480649f60e6b97930ec24d3ad128375546675b9da306de670ab0c 3cedc8256aa3d7844139e180826e005f8619adfa8a493da9e824181e4cc007ec 4514bdaf0b277950569d81b5195c63f14fdaadf1156dbb3ee16f3aebe2cccb09 6b6ea4d7c021f2bd8d7838bde814e0ee06f6b48e6ed911784083e007c52fdb069523c21d143b1fa06a2ae985e568a7c56c08b23c297a29ac73f4c2c402273d08 +generate_signature 0020398fa58108e0b0e5356b87113093b1e657fc5aaa229a2cbed766a1343b13 dbda7c364135fe9237e54e87c742a1174d17d3e70a08051780ebe274e399a4cb 12160063e4e47b248ec37339a3e62e920b41da6ed6b9ef1dfcc1f48a17c0490c 496cd583810035ae1efa4abf04b4b3cb0d614c49f92b52315f23804c7138e205648112b530aebd2448fc1a0f3c11248e2d909b88878a154e5ead8dd065d2de08 +generate_signature b1e43d4e2cadb0e60c8791fe13909d0226ddc2fbc5bd25f73466910ed0ab3f2e a1926c9a221e847a653ec6136e4e23768ee329db20a7a5986b51c0b35eb73d15 5b0d93ac7c30cb138102c03ca6b27291e5adf76d82bc88862bcb3af8df86d308 e1c54cb8ed14d49435fe92aea76da0fdf48e711d4b441479b312b6d1f9ac9e004b25422c12a75eb90a2f1d1cb853922fa9921c47b140010f5ae83b7ca20aab02 +generate_signature c5e0e0a1d97e19628730750589a954c02102545c18f7bb05ef3e9eb8cbe36523 e4a4af78733fe9a3b297bf135e8b57181d8c0e39ecf9a5a7ce1898db57b18b17 7d29486ba52c61fc5ba24e42ae6f1861f161a0063f102ae3e86c480b52d5a40a fca60122e6c7fe89d2b6a1197b1028e398e50197d972aafccdab57c5c7937a0bdd02a6eb61a8632f6a5a9273ec91ab687b84c565d872922eb436227e2591d807 +generate_signature 81bb454381f1614e7e5764e88664dc47f825d18ed5710899d1e5968169d7bf58 1bce52512bbb39ddb4dbe9a10cd12314ce08fb7ca6b20d8a0855b334b5416a17 8fcbfbb6f711655ccec1b456597b0ce4a5c81adfe9523721503d36f5d5be5708 e0dd435102eafd52ddd4a251dcf98bac2be2ab053425a2e1ff8773b3ac4841071f0aad81e429f8f47bc0aac08582c5cac1334115bcd3419d4a86543ea08cee0a +generate_signature 8c9949bde07909984cec9d462c7e1de28f0d47d143790a686bee51d4983556dd fb6fb90c091135388023524466045bfca011113099973ceaf2d6dc4fa0aafbbe 8dd9d958ef607e46a14f742e8581c903661935e2257f24e852ced3f7edc5ca0e 74301eb101db6dadc1d304aac85a76f5453be8ed11229ef2e89bf7342fb391099d8a8f4bd07fbed6dad2f894d6e9578e3da2e8ea4d77e2632faf062e14365409 +generate_signature ab5556f1489abbd7a0c8c877a18313617887be7ba186a8e0a2d50e9d94a578c8 e7f84cf6411ca6bba208b07ab26e48a09b779a1e7bc907ed587a1d7ebc39e273 601f584a65a16dd59e6a1b86310a66a11192cd5ee68a4943ec38bbbb1bb9370f 680ff8b998b48570dec897fc70b17d0663b25210ad75989e7aeaa1beccb27d0e622cc19314b0c4a87505c7ed8b4d9dd98f53cfb402ab8ba426d2a33fe3de760d +generate_signature 47fb94c340262e3cab3ffb03e06695bfbdc2439807cf26620c8cfe4395391309 a5f429dd825be9eb1b76f7300754a454844d07d1627312b14c70a4ea4e4566ab 7747b7704dbf86b1d338f3d49649e43009e7525edb11e684294fdf1d6fbfb708 274887fe1f2ea5100877a98acdf60652de23296bc4a7e905542e71409f2e8c0af5ee8ab0022dcf7d6df904b03f77c340967cc411238b40bb8492008198b0a40e +generate_signature 6ba24acafdbcf7ca8125c560f585d33fc166ae363adc8f0422c2242f6a2adad0 b27456386a01d84300fe0695bcb594296fedc0b2ea31e1a176cfa49eafa0e5a5 237401f9b747baaabeb8d8df6f526f00a6331288118c5aceb343908fea8ff708 73b63f6bf7c37cb934cbab1c56e7f7bf6dc8fe9cdd89e7c033e8955edd8afb0658fb8aa2000a1949dbd7f98ced499590263e0158e4c8db08c2de202fa04eff04 +generate_signature c8dc5ec96cda8c740358be0754fdb8644a33bbdb9352ba63ba8c8ebb19f7a240 d9041763f43939ba1b6015c369bf8596a53584891e45b20f4031ecbeff20b36d 849e6afd48fbab23161a1dfb7d3b60151dbc4b288596726ac07b2fa4fab68109 7af65b5232c51ac365e36e02484888735135a3ddc8d8d2b38fd9519cdfdda1057d84a0210e0f8542e343cb2902cc8def4aa137dcd718ddbed23ba7e91b21fa09 +generate_signature b6d466f81e80d56104e09dcbc4bcb94e4f095ad48c635aa14f74c106ae57b9d0 005a126a81f80baa89c897c921f562aa44afb0a7f317e2cc2988197f980fad94 08042ce99fa8ff0a4c082fc1ba66bb11f8c94ba9ae38b4f37aa050a3345b2808 103b1fdb329b70fcb457dd523342bc7d10d72a6862295479c076d5fb2d543d062c4969c9c2851935a064692bc8db3e713f1adebb6da4569176eef2274aac2d0f +generate_signature 8c442d20262492d6075a482a853037319738a944e8ced7a26c236008348cd06a 1543c07acd90bdcc1ed42560b2129f52db09965732e1ad75da5df80f851e0a30 5abba5c682b23a2e44b9b426abcea8faecc8da15f0d124fa428cd21ab523490a 1333a41088023c697bd6a345f07173c0feac05d30b9ee093d87acfbbc21b0d06ac809857413677b9cc6365b8eb6c1fd6ee8dac3e9285fb339a0e6e84478b380f +generate_signature 6f7951c7ca70cbe7abe0d6befe5a5a10559b7d05a56fba3280266361a919b07b 2a08f949c037c51b3bc036e3779b6dac628a9fa2561087d15c029de399596209 77f07519b561abd91c4bf4a10be08deb641537d7503102d30b8403bae936910b 9ec220c03b30944d7d256160a6d05830840a5b1b601b4a93fd15deacc0e53d07fbe8f74f9fa1fce78ea1dedeac95c19d8c9fddf2694db8fa002d8d2d9af82f0d +generate_signature 22b1dcde0d75d009c1f37df37ed0a79e162049ac2ee48681e312244d540b046a e340d157c047d55d82817a49b51f3c1d39a82d38876a05050dc5296c12a2b6df 8fbe0766b15d4fa7542756b1cc33a62bfe2da4f7f00ca30dfcccd7d63d6a350e 5099d909d0cf0ad066691ef161321be92c4dcb3b875c36c81992fb2cd9e5c50736827b9191b2ceb8e88e760c135f680ab41b7c9c96552e104c270a1dbef4be0e +generate_signature e1552258578c4238b55b9c096f1da86bc399ebe8c55df9dd6d0468ce939a7695 98557f788cbd01ac0b77f5e4bd2c0aa65c58cc61b49f5842a53f898461d22ce6 7d052de95e7e055d117709ca3ffbd6294edb2b0698b549f623327a7856d18b0d 26f9f45117650b4718b3672a487cee8cacc12b31a775fceca7ac9bc826f2950ef33310de1bbe633af6a2bf01bd5a9a348e45f14a99acb5157944eaaa582cec03 +generate_signature 9ef760bfb089f081576ef619c98fa69e80bff76db56853759a98359944af31f7 1e2022577b355dee237be685fc8704c73ec09fb448ce3ac9224c7cb26ed7cac3 e9d5ed5d17eb81635b3f44bbde735d506a1b1002fc963369db98c2da1fb9990f 2f68949f1affa927b4baebd572faf3cbf69a7236a105794ccd005f863c023308bf5879fb6429ef9c92b01bcfd761bba51594400ac61660827c1318dd2a811607 +generate_signature d48118e8850b94a1d6536e8ad26424db5ff6a8856837b5f2b759991cecc0ea79 76acc258e905aa60091cd19a0453c086bc63fbe6a9b9f9713c5a59e4a1f65735 e7eb8679919eec79d95612ea8d4f42d3dba03c92997a8db4ea7ee670bbda580a bcd4c0845fb835023515bcbe31b9d3d7fe06a9ec8d3b34a3900c49bc57e58d09b2b2c1ac9a0827fa4a717e19081071cab8ca7f1b27af8df5eda0df201d447a05 +generate_signature 95b23e89020f166b62f1a0ee717a478c07b3c96d697a3a5e1eda873c407511a8 8d7c53fca9f208f436d9b1a921daa731f79e537a6aa1f54b809aa4ad9b33b860 b702f52f1dfe951d4cbafe535089128cfdf8e3c62e95238614d230bc783fed09 804ce87bd376374c5dc2bb3c97059e59b259952f5916d4a80ec0d2918ed3fe09e1cd4047553e6f3c34971e0506b44e2f20bdedd75ec3505e42cd8d8c3345250c +generate_signature 73017e127a3cd7c8a9f97f80ccfe6804c5bb683b22b6242a307aa84f2b2e5663 f17f920f113d54ccf8790951b2963d35165c852ed0cf7c6f5da3c1af2874f7b4 7dd05f2bed1ebd7b1bba8060fcad9368c9c114e49ff553273cdca2adbe5b7c02 08e18f3fd9e861a6fd6788147ab634b5ddae00aaa66a7faa2e57a7c26011c7090482dc1a4f89a5f09cbd47beabe922bb3c4ed5c9dd3ac8caef40e6131d69bc04 +generate_signature 5df7c3d6ef2ed1b6140e0c52d836594ae75adfe243cddc0cc11e253674ea1d3c 5d45e0470b6d249abde6354c3db9e980c56705786c11bef17f94a31cf7d05d95 60e30994ebb7c53ad955faef54e0abf7d7aff8932af097db250fb56099712b06 3be465b2b16cff9ea84f679da3a344eb6be15e1084e5eaabb2e6d4f941e93c02584bd648ef975371b12f4d7163f196a8b7825c7255926899d62c12bc771b2f0b +generate_signature 5e1dbdf1b13c9e0be80b4f4e10a2bf29144fa2e66553e81fb50f2f7b55633f1e 4cb10093b5c9cda140ec668a576def490cf7453635bb4921cb9ef8c8e909ee52 067e27cc60b9d9da528aaa8a48ee6cb30418189c8f6bb0d5710dc1074dfbd605 84a811de4cfec277e86884886445184aac35cf380b2c96872cf73e1dcce7d406a6fd8ed618efa3f5739958fbf1fb5cef9b9f60969c4af9247add0628e4de880a +generate_signature a08e5b2e08d5f1c70edac02d97b7174e348c6d4bbc201485245e8578efdb2f5b 4a10b74ec6c5ba4cca27a473ff6022c3618b2e3c24625708add88767da62e3f6 50262cbb867b9feef014c6d0f301838bb92b66a8f2109e67d036129096168900 949237d915e5061336f56862da9cf22a1937dd36370a4e24a5ed76a7e60c2b00a729ac97961f80310c3a7256f1d08b8b67b4ae9574a660ba0231217ecafc1607 +generate_signature 07edba63a2c0fdb2e02bb8b8e6b531d2a542b0674e24f5ed1f3ef2583d2d9eb6 8c1059bbe4a373948ede638667da04f8caf05aaafecbad08de797a804f2e65e3 abdbf74be8cba1d22bf91057a94b1f12a063acd976e4410152a07de48b290b00 5031fb1105e40f919f7c215d76503a15ed57136bcaa643f23e9dc1bcf627ad080e62b036c4afc066698144dcf0cbce68a60dd68e03810ace41de2b40b5891002 +generate_signature 5dfe35eb9c70c55e285e3e9121651110e8daf329a1d3110bb342341f0b13e285 898082df3ceb5d2e96fd5400b22bc169e04d3ad581a63de9ea638eed30a1f63d 1e83a05b9ccc0daeb952e2d6b5cfdd414fca43664ed0ecdd30c5eadf7a8ad20c f0c814483e7da4f267fa954900aea16e1fc34232ade15aa043ee4ede5eedce0a52e91123decfc494e9813f9738868da0ef3ca3830538925419c43afcbda53b0c +generate_signature bcface283643b5f6fa0140dafff732ff07f4345abf3770523489ab4ff2731c58 85dc41f9264298c7ad08099dd2b20682dfa4c9798e69695f9626f644ef7c7980 b23d6a04cf867f63aa2e6a26784d5c7a00afe68a37af3069248177b77b50c506 da9db5010ae27d8469f09cddb6052e8f3a181f4865b25c88e0f8ac99aa4bc50e3d7792c6a31d4bb221435ecb23d169f8ef0df4bc9a3cae2c74d1d05157d2f90f +generate_signature 79444422974fda912b29426d4fb4e8900953d14b8a04b2b48a3370fbf6e0d34d 55c8b685946d2e1720c290ff6c2bab2643e35f6edaf04476dbed56472ccfa242 eabb6c32344af64e15d351011ece8fb6cb2309ecaff2d43d819f59389bf57607 eb44c37ad7bb78c8b81321d5d7dbc1e147c46a4cf8b08c3a1a7e321e29820905fe2638865001d440c9dea705583d33d9183999efeab79004475f860fe1b32b0f +generate_signature d2c081f5d9a76df2448bf6aaa021331d6e0fc87e31b6fee0bcdcfd499d2dd94e df1afbf7c09126a407fc34b118985ccf41c4e82427e6dcbfb0d3897cd3705d8a 56db60488923ad7e0575b143e71ce05d93e6d273a5bd445cf74ac9d8336c230d 8a61fe62cf20736645f05274e4e023368d207254d743d6ef4a7eb001bb9a470e29067ca10dcc31eef0158beabd600bdf2488684238ac0b554010b874ed968401 +generate_signature 8153ce2a925a6437aa445072075b5cae447affcc86b452290e5aadd91e446e9d a504a848e87137e24df67b8330d7dce41efb6a3ffe99ca69d7a2775bb4ff66a3 58a649099831b7343c6800ced12204ed25408aa9b1525d2f8aef6b8a40cfa908 7f414c45741426f4060ff6b99c2564b9f5540467fd74edc7d8ebe1e1b6e1e5019bf981e062680459835beae15d5bf4e44a7d0dbb6e8ccf9f03aa348e2e64ad01 +generate_signature f85e575bcd9427a761197581a05d22e3784e602cc471d88ddef5ed4e6ef26ac1 e4582873da79806344aeabdac709ce261fbeeee546d0068c3d17a64527aa1cbc 1090799dccb3d243647defbe3ae894d316d68d4539a134d8aa86f3a4116be203 e0f877d1434214b474a69d631d874e260281cd084f9666b692d7af504cd23905ba29d48dc9045343d0c0cac00f31beb7a115c460a986a597ec4a5d1955edd303 +generate_signature ac157e1a76bd72924e77dbf97e15469a4da1be6d154a8974aca1d77da7592e93 f4005a9e2341967cae9307f262d87c064163d0997d9f039a2488fb044d449604 7f8c5592166b6445aa14fa0b765d3908f8ac9af1c6de0f01544ea95c487e9c04 705fd3c4826b2c722036ff838773ee061395ab1b8395b01ab87655313e845a0c3735d90aab37d0a7df8bfb2c090797dd6b6bdee2e35c7d7721e86e60dec82806 +generate_signature f135a8ea135688e2cf612a1517c305ba88b556d3d0f5c3cbda706bd485993c1a 5ad2fec0008abc302e993a7e03a99358e7113ad6cce435c81d440463e39fef88 5a0e0b8724a44adf7eeb27ed8cdbd6a11d9f1a00d0729f6325910ca6783dd500 c86e974e823c9b62811093b86885aef47f6c154a3a399acf088a7ae9dd2378099126801f27d89286775431f5599bdaf8d1e03077cd0aa529389efe2690f7a508 +generate_signature 2f37a11507b767b81357f9d03bce2d6f92cbd79af252ec737a2126e1f1a59fa0 2030a8eea7a816364dd23b81655dbd00e10edc8f40b5139cc49506db9fe12c44 907f88dde3d47b78945ba4180c53fab25024bc009aa678b34c6958c3af14a00d 180b1a09682ee9e68193ed9384fa5cb3bb368a40cb7478f56f6a090e43bfb80963cdb74d972f5c61ac79ba1be47b7cb60a84b416cbd8d19e2572764b5224db04 +generate_signature 40f923c6bbde2b5aa8ae568a53594738edcc102ae77d2eb2ba13250bb3701aff 3d0d965e35f87612a3d53ac8b62ae4e7d4aa2f1cd3a6fe3a258ebe91457a810f f88b02b56a6d583e5ee52898fd7124270a1de3aae61ddb45e3fd4d272ca49e01 4993c3374a6a3e7f60e9d932b4f103ad3cf373fe51af1fe6635b42179ef89e00afe8faecc1f8001a803764e577de812d6c0a80216cb6b9ead34cf204b2f96408 +generate_signature 3c4a9e9af77301f53f078bb5780d71d3b14e55457fb26308647706d88e7e8ec9 41a6ad8332efccc56dbcfb936c84a1e608467d9f58aad447e7cedc9c091b8f33 6ae28d2f4d72100a1638132f6c363d2d65c73f2f6e9e6ef883775ce3eee94401 3d6fcbac9b2a1afcb0bc477e82c42dec5e49c3b01e7e804dcc1f2e453ec360064ae9b36bdebad20ef352b4cf29acc698c2726b603a4344b3361dbf79ac3e2002 +generate_signature 6e361cb98046db1c58738f54bfa5e24003ad2843625089084112d3e956781da1 a40a310dbf5128eb712aa9ee5d339f8c0e78c90e8e44977ec83a6138b6191627 ce3e7483fae52df03b7c08d8f30fa43fa505f0a7948889282f5e46b0882db500 e890d0e5d69a392a65bcb6bc57d4a0677e4f8df82c711da94dab88b766dc2f0d5b52597c22266e321c8a255a0bcc4fd6303d37094e9166fc8f9d2ec17505290d +generate_signature ba7df37a2d75e962d42d31a91525075ac836100ed1a78ae4e978afa432a1235a b4ccbeb6c17e719c79942b74b81a3cfb5ccd63e0c06b12fa88f9e90cd9e8a1e0 a35bbaaf8d8fcf421d4307e3a52f63d382b8ff35c7f6e5f7a6eb0a7adfd02f04 902512946bdfb12fb7f5bc8f7d4a753ac6c581d6cc6ee3997917772a3715e908e748a6a61f51fd8eafd52e89d12bc1389206fce217e2af2f7769056189a16706 +generate_signature 81599211da2f1378330d2bf7f86e0686947fa402578cee048c6fd648a909f2b6 865b484252a23a1697c736ddf81d44674d9b51fcbaaf5bddf88061402ac65189 8509f1f20c25d821fe6057863277222b54399eba3712721c82c174d81650080f 77a3ec2e3ae64f15629e767ab2f3442cd109789b5372490e19167f7412543b0d45402dfd640900b901186c877bb60d526c0476bc8de1126a83877a47bf76140a +generate_signature 9655414428a87d11c0bbed9af0bb32010c4847cfdf75ebf4a8c73c1d5500f44f 53bc48c7306182d958147ed4510dc3c1e5b3ccfc16938f1a7d757ce7ca2fdeac dc1506e5b95e1d6e6e06ecceb4b8cfaa00daf3d6fa26fb672374ffeceb0cb505 4f20297b06023fdbb7f5dfa32abd287b084d82fd72b52ede9c9b525b08becf0d00706c4e573fc475551c3a2254e0f67a8dd314782a96244f228890482011f202 +generate_signature 3e1ad25eb7a1dc33c84bfb09d73d946aee497638ea639157e1eed1739bd0a84e b507cad326ce68772dd3cb43c31bdd70cd71d722bb551d209d53449c232f5055 c06773a6b15d1409ccf3bb4182509cd418fee29a93d966c511809b19eaae4d06 137c9cc3aecbb4e49a42c45fbbf77c031151bbdc7fd35feb44d74ef5a055910b780a27d8f836e2990649cd0028051b4b6b0e8e1943fa75ad6a0acec60a030903 +generate_signature 36bd8cd274466d762f8bd459e5f32dbd7662fed9bcb44b76276e793701c7f5dc df9013de104e242aec33250ee64a3019fb7ad37bc06a421c60ac21626c9ddd6f 6342d56599a678fca61f584facc41e316f0bf152165767f50e3346b7ec74a208 e262625367d30443ec5187b2834305321c20ba4f50ebe669a6f0bed6882e77040559f3e8666c07d85e2d2782f4d48aec33595b98c366b1fcf3ef759dafe1e00f +generate_signature 829f725bd1ec12e3c244c4b0006499fbff693b33d0797c043334ec591a8d64d7 fc559b71cc887e98088cc873b9d7c69d104276e257cb28197644f49e8854e69f 36228dd0b09d05703d7f8b5235b94958439b8a95b43c8e09b577a0fe6b26a901 5822be12556e1f78bf9bdc9a39e09bbfd6b2ae65ffc484ac018b45297e2f570ea4ae05dc51ec1d52a48f29eec8d7d8aab4443762f7883f263399b4686fb26108 +generate_signature b2fbde52043e979fae4cbfaa1fc218bb87b87b21410c498be62c5b288f0a59d9 fa437eb7611028c6141280c056fdcdd20912575cb57d652f78034f7afaa5e0a1 df1288522dc2cbca4473941856c0f24952f69b5c9efbe6df24396ae25ea91105 0914679fc5d261a5a97300b85f879e56f50fec3ff74a4d2fc13ae749aac537079efedba78da81e8d5195d7c7df20d9b0072d2a03983f11f9284c7c846bf1590e +generate_signature d21de662f0d58c9f746f0984fc3691a3d0bb0776e539a2282207b8ebd8e5ca85 679397579f31b061479734bc5fb2218c577503f35827c815f22bf53761c272d9 b04aca24dcc7f0c6d04c3c676a6efe8062fd5618d16155ba2a0e4d0485332c0c d2400b26900561811a0d6a0891cfe2d05421d4d82a036190f5125ca425b03a0fc3deeb20ea20971aa06c14f555617d3da9d14fd29573ceb74379c96de23a7b0e +generate_signature 44c6eecba5511adb489dfb05815e764f933553baf1acfb6e9cebe010337b24c0 a08e4416e02f056c71ea72e2eb1f8a89f669fbc225a7254e4c8d0f8d39ebd1d3 40f60e9ef735a23ffe2ac767726ae743f2844fd7e8981a96cef85096359c230b 94e41eb1e78e2c59de237965faa07f88d8e4e7ea7c2e6ad7f13250dfcb85f10c728b46ddc5022dc6a22045a9915878506c83c8e1bb2c0a8919bcfd9007b10201 +generate_signature c36bf112fe3f11d4a33a28c8f7e96e18c0a561eda487ccc7e441439405c5b339 5d764a790fb3442a21aef48510e95dac552d0f34c2b03289ab11faf21623c451 ec45f5dcff2cae290875866dcb122645d1b88cece607be63783c3e088cba410e bdcd151abf8779d168a31044c53ee4134e8dea28b24d821ed30abbb34800ff04b74987a0b71403029c7b72bd1eb4282c62fd310506cd552751bcc20657f40b02 +generate_signature e642c5bd2b451b20aab856686bab22f6987a7b5330c2491ad9d43059cb5b17a7 e5c73f7ca70afc4019ba044c177ab7ba3b57070effd788ec950e23f766617ae2 1430d7db432dbcf48c88f489017aadb6bc4a4dd30dd68245e281359e7bc6610c 5d7fbfa4716dcfb866bc2ee9b58c8ee400baa052adf113af0a2ff2d8ab2d560a3dc929357fff96de69401cbe17e67d411a20f98f803b51185ecd58da410f4607 +generate_signature 0b427120304ff23f1906c33972a5ddfabc833455e1c00b4ad522dde15f401237 45df3d7b2ff3ea6a638a360019b6998dff96ba9c11ec454fa763b75ed9e21891 07290dd0ccfcf302d33d38e5b943f338a40e63fce395f47984e7edfb617e3509 236b0ac251430fbd87d4bcae96974308f786f1dd3152c28f30b25c1baf198909142caed0894374de2b846293b0a9c1433652c77523fa78af97ffa68c2cfb6f00 +generate_signature 5ada550217e164eb59ea6506858ae1ab537c9cc15d362f94570255e558911490 891681f48e13a2f0f2a7e189995a87f9af3f3b4aad553deae50f38455eae34ae 9f12a804897eef85dc4f89885958acdab399cea0cbb6c7bd2e2b40185bf53201 b5ed4bf90e630e17150ab395b4ae857cb8185a771727cdc5041478957ad0f6028b64a1787e4d089295c4899277cba970ee4828331cd9e21c0b5a2b99f4418b0c +generate_signature dc200cfb46b99ed1789b022df4462e679fffde969ef75181470fe77d2f659224 a8987ff64be78dc7120fa7c7caf8dad90e4b8dc44597769eefc67df636c26062 4f5a3321915e3c9922eb7704a158f64d27d32192687412d28748d2ed4636900b 37033a8af69311b97c925a08d37effb494386eaeb75c72cfbe8f58fbb245be06fd8059843010949036bb411447d1ceabe0e6b57c7b5e920d72e465ed545b7b00 +generate_signature 7462d6b416e428b5c0ee3f90ca39575495955b720ad0e7e4c2955c1ccaae1888 36260bf759635f1628c16ab8a85e22d20d9554f6811bf2d7d2b0e724088c8567 2f37c7a26aabe14e904c61e256d5e2857adb8e94c3d28a57950bd68b5677f302 2bad91d4787750b59d1600f813e44035f199462ab4bc0b1d37bcccd1b8c39709d8705e625ac74d6fe755e6a9b2996f379581c854e2571535623834f0502ac505 +generate_signature 51e9571c4b6814a631509d7b43dda8a19fbd9c5536c3355c3b9ec28fc7d4aea8 cf237efdc47a5fbb1063f9851704177751b2bb6dd40f35a35bc49acd95e11370 a37484d7875c479c3df673457b1d82b1d8fc80df5274aae7d1aeb39fe2aa310f 82282a98295212a21a356089e9b207af1691cc530ad9847c2c62e8bbebec550df2844f503f81141710593462c56dc449cea9b2ee9e45344a66b4855a1912f90f +generate_signature 512f462d431403b24c18924eaeddf9d911d5c614d2a5e274c21933a136cd8e10 20f1bb98259c891bfcb5e11793ad38c2ca863d739f7a2c53bf5f74c9472b8fd6 8f92a6e203eb6d8ea988a11177aa370bf142928fb93c466bf18ab55b50492e08 339539dbed870e0478783f855dfe1f830a9da95ce4c20871b7a9437351c8b807526ac7befb58df9dd78a5327299f0503e65e57e960f973c1687da6877faf8e06 +generate_signature c67ceead9a67e5bb1211538a0c96cb3605da36f1fe2a8664de0f134781a85889 25adad7475f476c9c02b9fcd3c7865d261e5da7261031256dea250c71f305bf0 8a451763e81d056b3622ff5db2432b5ac52a4565735d1f399d7fe44f409b6109 22c7f9e735c6670acc67a95b3d3c8a5ba1ac748e5cd1d0a2c5b71d1a98827604c6221ff707de08c2bb57b53e2d0dbcd90abdb28c9da2bdadfb75895139a90b01 +generate_signature 8744e27a87056f551083b1240834edfdf4576a4b8c4db7e93c03bec8f714b842 ee8c02e0eb978f310eeca705aa7a4bfe38cc10a9a92e8458f5656dbcb22a604f ebba71caa77c769b5c0920033be75dcd8e1af9a19c97c4cfad52bd52efb3cd02 8646cf7643a3aca7a34766cd1c66caa5ec51ffd9fcc559cbed7473adedf3b900f7f8bbfe4496a67dc933a64fa17c054a4cb2cdca778a3ccf8d349e6041fa480c +generate_signature 01b5d99e68a458de21c085b50147ba1f67b0930144fa77ee5d4e1d37e91da1aa a928416ec7f0a87dbded403c87fcb073528cd4f90651ab9e3bbdd14ca61b6e46 370f367e7ea29b50ead04f5195c6b0486923c4e7109c8fb79b1059059378b302 e4c72bada89b238cd8be001c31d23c4a133b64c7e2f1685276e3b3d9c2234d09549a0881dff2ebc784fe32fe3e2243515ad476452d2c60bc3e9e2e2379f4a305 +generate_signature fe682bde8ff2a30f81d616c05b9b356e32b3b6f11fc4f58c133d7b9082f3fe84 dd191591dd57a04d33124ce1af1ada602b3f5304b15d4a90aa0732d72742f501 c2b494b0c63900df29f46d4ff2e56a644aee5cad4105aa0123bd9809d675df04 46b21d13b96473614ac7c0d02c601bc868f0fc0fcdb6055169ea5805826b530f29f17560c89522177a491deb6eb8992b6ba05f41bb1a322b7ac7ae3bc2b64707 +generate_signature 96a71cd74467e3b95e4dd8874535ab8fe7710ec4956aff40dae1e7849bcd4c24 c55e53a61395c80d8adddafc2bb1224f1e64ca8014fd13d809c86d7b5e299e0a 84356cbf4af292e87e3b7fc328cfe45d5bab67b784405de76533fa4fe049d702 675301cfd32ff37661814c7330c8d8a8ae3e24bc1261a42391c284ba62e04800181ed6e94cbf93900214f12ec30755d4f907df382513f2957c86eccc49f41002 +generate_signature 7332333e4bedbc6291e64c3acb32779b6bb94493e83e676da1ea8e7ac593cf7b fc9dd303f58dbb87fd82695b463e1197a265279031cf9ae5a6a7e6dafe2f0fb4 9fabb96d4292617086a3a9c0dc084bb6118f73eeb602a6fb3082a37fe6d7a40f 2c1a9f028c3d2b32155b01a5f8c582544cdde6339edebd7f3d76f4c13490600e96d38c95eaceec32e2f131b0a9397838b8cb42f780c19ff5a7c36e68e4deb508 +generate_signature b15d619a2e307fc4e1848688c3388deb8f2e0eea38328cae0886adeb42474204 5d2eedf3536c0d1857d75190f3da8f9e214dd170790722c0ec90b5876f46fa1b f107b7b3f7e17ed25504d36574d01318cea43a84b0c275d097ba0cb83e872601 29023024c75f7ed826cfaaec74b65e5ca1bfa33b2f0d243cf4c9cecbefe00201992aaeb2c5ea5f82e26851478beee039d5df5c96aa35020570bff48ce3a0920f +generate_signature bfd9fa1f474799d11ab3ef3abae59c17b300b8cb899b2fcbfacec678cc77bdb2 362bbd5e5c95c7e1adb900a3c6c5a67b5f050e58ceb6917bfd037abc61457f23 4bb72c886f3d978943afdd5c1e53882caa6b323e0c0836a1485156c569c2b604 e748a1abfdcda647d39a8fadab90bb188abe998265b7ef57297c06d968714d09772dd7fda3ed39566683c2efc739b0d620b21ae98582a93ef73b0660e10fcb04 +generate_signature 3b8254fb834017e439bf4c9db7a54b8d72cfdfe734e64e3db94bc42761e52a64 3f1a3561b18915b34bf1b451fa01ce6b9e2124719b4f3843da1caa106f5e724b a9439b2e768ea849b35fe3e8f31fafd2460343374600031aadc7a047d8f4650d bd317c6b254ab2e61936bc56d0cb7cb62b8b338d77b3c2e1b712266f06bd080cce6a7fbddee59e7b08335066cffca021e69d92ed29e741d501fc2f5978232706 +generate_signature eee51b7ed448e86eb34c493bb7cde32b654a2c3b94734b54e313b44705736194 9cf9b0c581562977e791eaab88f9574ac7e7b173077b3e67283fa00ae448d19c 7e0763abac9d638732d9cd91c7662b13b14067fb458dd8c13329ba76d9685a01 6d301b174b139fa13bc256f735f57576fbbf549972b81e27495267ff22711609c71a7fa2a62fcfbd32772317e6eee6b34ab48f1bef28dce7e03bc1a2bbd53400 +generate_signature 4d0fe60a2d913071d88b67d806b451e5217b66279c8a366ea50df32dc7f019f0 30be371fcd62d0aa789bec1511074649e012bafde098d1997867cfd1a1c00020 14ae35724fef1e5136b485fd319f2ddfa31858c2f6e8718016ac61c7bc09a00c ab70c4bed07544e9274e5024429a9a19399aec1d87a8543f47c7d711470eb70dd7c7a6a4c6bec508fc7d2fd264f930326c2cbb7cc27ba86df571b3c5864cf008 +generate_signature 52558464c45be054502fd7a95873356906175f45d96a123a679c61293ea82c59 f2df74450892e64b630c1bd242ad6d6eeb74eaaa37817359f0ca6ceedadac351 fe2330bb3f97ebcb29060bad76f122164f4f376f1dfece45ec8e1b74a9d73304 cdde8b482122d1b619b0fd32bc53accca12b36c44805085fd70e2708df416202d67a8d88cdee6f4208ef21b2d8049ad4e29ff70ea77fb6186934035c24eb1101 +generate_signature 110cb3d607cf3cdeaedf72bb5e757beaaf33735c4e0a6c9d36e15c3bc44f46a9 299e119e03f8698bb3f91c0383fc2fa3566893b430c4181ae75da3b6db52a14c 5f8e1334f8edd3031ae48b6167b69ee954b2dc825d96c1a66115f3e0dd19bc0d f20b445501d16dbf341e9d47aa3dc2287b55a79a1b1cfa2f66d5018fab72080fbb3ca626e6118010a384c2f702ef146eb57e41901b1bd30ca06cba56e5a0a307 +generate_signature b9c72e905e48aa099d4618aa4be67625490d93c298ae9a3ad50bd3051825ba5e a2d1ca5b1280a41694c3378e2346b3f9ec16d27905a7d9f1ade0aead412fdc5c 2fd3f1486114d6f267cce879108ab62839c678eb46a846383c25904f47719605 81d097e25c91dfe2315b8f93cd6f91e319753f57e9ff6e9438ad456238e4a50b1034bf01d5e1e21e1fe6b5915f26f942146b5747aeffe72f419ff390a25c3908 +generate_signature a61d5acf702d80aad1e60667f5186d692d03c291015af38ff48b3f627dfb6c93 794e3180afac94b50792ae3b11ab01c8ef4e02973b3c2efa5b3110d2cc5bc5fd 89a145b6365dbcd67ad36878174eab5d3278b2da8a0724fc6b9fff3dadfdf103 e9523cd800341c43e0dd14a8ea794ebaaee58531ff98bfe7546969082cb758093a9e4532f4e4701195d703fc102cfe75e955ffe7b0c2a43cf53d05649c488a06 +generate_signature d0666d9f44a461d56c2c6c35bd098282042d7ab5b4138f80b22b98b940df2543 c97f167d5fdccb9158ab96824c60752f6a1034e163b96da179cc42a8d6f8cea9 443d72bd61cb9ce36ac11839333cab61bc85506b91dec9ae8d0071fe9805ea0c 90b07fe43d85974768e23c059d9b5055b08931c9bc20effbf6d050340c2f2a0e1a97db5d0c4793d3fe77d5ae26635415e3ce5efc1606044365654a9e996ba105 +generate_signature dd4e6582d6f65498b6e6dbf35f5dcdfab52f90a8eb7ef7391111bcbe7066929e 1200b5eac5cf70e9c52da437ab1d7da3ad5f951f65baee0ba8aa02ffe69a3675 b72904a3d7180d9c2c16e090c52051ebbebe0ba8376e2defd850bdd698fb6f09 b7da055de4dd535d7ff9422c62f752acd75e48e6e8cc2fc1cf713766c3905e0f505d669abf2e4a5e372c8a6b8f559838c2bbab0867a7e6fb9fd4cbd53425c506 +generate_signature 6a1c4227f59b75fd001623aef3687fafa8eff103526023aa6676e8f08fe3c15b 1613c592fccc2e0031487aed9aefc3eb0b86ffefea0f014173bdb28acf4e8bb3 bb93bcb48a4efa8ae0b0fc9393653f2696c77603e9fc3bc1956473f04f64e402 18cd092bc73f02cf80536903b2f54f75db3a4c9ca9fc6e2b0d5dfc78cda09b0c29c02f4c5ac14e564759caee18a1da5918f956466afd18a5ff58c6a3b79c0a03 +generate_signature 2677f450f708876541bbae6ec7030aa87d2f7599bb4f669c190b8df2b62daf66 7a85581bd21fdad5609a84478a9e61a084ab78021c7bb0fdcd6c9efad8cfcbb9 26971f12134601802ef62ff5dacb99e5e0e08ea2455861e63af3cfcbb8cc050b cbff686c9db467574d01391198f1fdbb2bd2be584a70fe183a88d260eb017c077f1d0b8e485fab40325a2fd3eacb9389f7403f2785592f02cd2262bdfd2b370b +generate_signature 15bbccb57984f152d62b0c82f12d732b75068118fc3062805c157c33b9f35741 cae0a132e7e32e55906039a7f510d940cbf4dc16543beb1004b636866635a5d5 6d16a1ed565e148f653ae3c20a978dea4f2bdf009dfc8d9e66a201c9d184e906 454824000b5486b964a3f52e4cb7a54c2f59b9999c8f67831fa4e0499ffeb50a7d36bb7f2b3570b9225abb5e74bea580db0e697a18099f151a259b28ee05c704 +generate_signature dba1e5cb897f3a931ca00c61296c26aa6edaaaa95d844e8cb29a8818e5d3cf40 8011fbc326c27242f794f1c93e7e616ae847badaae42e30ce345ee2054752490 9b02000c18cbce2c5bd97d9e572ef1124b710bc4bf820b5e740c6f52185fdc04 97a13eccd2d807dcc737bee9ed59a69aa630dec7860855e1ffcdc733a26f7c052dc7fcf7eab11915c7739567d1e2a72a2690a6dfa46f953574df94b1a1af1b03 +generate_signature e9257b43c57e17027c955dc21454cdb41cc59ad29307468ecc595466470519ea 5c841fc7705e9f0691444e3833e84b946f0978500e66dd187b6b4011e2bc5722 ad7c20800b766bfc8d97bd71fdd21b3390f9b5dea4a763ec94209e832add0c0e 7ec5262e186734402e716ad856de09c243df362f6e0bf25090b6871ba125570f727863e4a84363479f74e198721ac10f827ee1d3afb90b62c5068ed345ed8600 +generate_signature 49a91500dd7fd49dedfc127ad940124684ceb5d0d298fd708906728551ce059b d19aa3856ff99afd3a621c339cd5688ad3d108e313cc6a12e76b857a56c8b254 8120cda41048d6102dd2ad998972b345886573e7caa4955df7c3b6632f96a50f 0154950234e23af654f925db75e160cd8f0bb35465162ade260eb076949e5702c163dfae3aae0854ae8b562122cb84ce8b1a5d635e7d3d11f4bbc336f03f6804 +generate_signature ee3d3c574231cab4d8b8de5b127423e88ce63d30ffba94e44b7cb52d933c4551 c7c4c1ebb9ac8a9ab8c71bd032c95bf4d76ed79fe8ac53265f8d2e0ff0913e5e 685985d5d94c9702bc73c58eecd4f2c69aed4b5ec1136af0636ee81d94c2530f 211bdedab227f588636ba329c6b2b267353fc7dd2f632f4e86b7bcaf890b3008833e6dfced83f50d985b4c6e20b10bf6f027e760861ac9c16e7293716ab3d400 +generate_signature 1473d8159b8f7ea02a7227be5ddd874e9c6e3c114708f7c46de729a81f0379bb 7d995c9eed1ff652f954617817f772dfeaad1ebb968c3b4260c22bcc6aa2e764 302201443d6fcdfd98585792085a7b7e804ea4a79bca8fd6b1d24d9ec30eb10a a89cbd6e854a2fc7495c4703fec6bf15d3b8ab93a791e413d99f15bad0e3020592a43f7df9780d9b2ca6d869f74631e380d0644a4aa07f44cd7f63fff7f9bc03 +generate_signature e0b62a10aa27778f06ce587a439179f6be9a444588be2fc6c61fec24e4cbfae9 b31d7350dc561bdd04634b1c65d4d07721b21be061f4ea6779a1a9f0268830fe 033f706a513a3102241553f06fcdbaa4f1899f9776f51584495e0eea1195c906 466319a5d827a73c8959e75421e1a664fb5fd4005d3c43d884544bfac7b5fd091c1f008e0cbfff0dcf5d6bd684e883a166702e60c2b0605bb6f1d3412fd6df03 +generate_signature ce6fe431c9d841f2f7494d0c214ed3f4d470b1de679e30d0980137dc8cca5369 7c4883ca0408e5279b4333cd5970366e7d2cae46e88bfa9efd5b9554b8677438 bf876c480666daf828d4b5aed26b853372ea58355c370ece915600f127dc2a04 85414259188aedc51ba52ad359dd7ed42bb26f722678ddfed3c3b6d52dcef400a72ac3d0a615ea47e37549b6907ec5b6c61cf33708348b008d52426ae1242d09 +generate_signature ea984e9cc588ddcbd884642c0c1eb40dd85cb049f22688a80f42b0835b3d2721 4e200ad1863ddbec552c937ea0f28577d93959185269c21b5b0a2faf11738582 144de89fdc0a762c28f54d7cfe1d9c7c1dce3d1b520bc8e6b1df39405708b505 ae51262262a823bf3980bdc0b0f2434a79abf0b5c58b35608602a219f766f80792e60a0ee5bc3126991098d90dabb127ff1b958f69f0b053caf1e1c95f4eab08 +generate_signature 298dbd2126d0276c1d95e2e5220bd529b25c16ca670094a667fd3397c7b7b22b afb3b9bb1769caea17f4102c3e59eecabdc9108195d33f0129307af251f8f330 f17b90b7c4bd2169f7f1f5816f8f72a2bbfc03c4617b957db3ffc04b6e42a303 119f4c615cc94d3441ab0e7d80b38fdf67fc248f44af479243881b9d95e5f5066366c68625364c3d457e6b9510892198715d2a9e26c40a7a9f5421d242037b01 +generate_signature 9c5c87cc348b763b29665e7e9fc83c2ee425c57bc610856179879b5fc644dcc6 67894b54c0628bb6c56ee847b712253782a9b02a506dab960a5b8eb9e613215f 082fff76e7d834c3034b37eba3aaa231b1b190ea3514791beaadd4b3daaf5508 0b2fafa75654a9475c203ffd8bdf68eb5ccf5d9d45416192e9c17acbdcfc0e095b2f27da63396e4b675912b8287f737c061580e037279ab0965dd8b440530909 +generate_signature ab263c0d9626de5860ea22e2f999676b455641c23e9edd517f420c01e84cd2ce 1ecb565cdd6da4bb6f6cfa57e75940630360f663cf56cc716f1b949419f9b6e9 d22ef716713fc60b11e619292c44ec432fe7bd4cf582544fcf2ebce23d566009 98a7193f04fbdb698010b06a64c8788b3e515b514d36e04cc5b3a384a9fd5b0f774fddc20429b293e6fd951a5fb624f368dcd4cc0dc077db4319b0aa13cf2901 +generate_signature 2acd9cb6a9418f90b507b15bd258878fab69afebd0cdc57ade4719ab89be32d3 814c8efa712bed141ffa2e72b2317dcba9e917330523946c2a97e8af3f992fe3 199e9c09c85ff00f9431ef41d7d9a56aa05cb9d09f548d2fad7a783eb2faa400 90b6d1e6a0fcf64c0a62cb94f16f7eaf50b88954ecbaa65f97644ed137732200f981355b9f2a30b76b9277aed25d44b37141383f96f0fa435b7f0385d662010e +generate_signature b8aeb16bf5d31ae4fe7e321da12d8defa7923946e197390f0a1696526099cb03 eefaf0226cbb5685e2770e2b72a0de26f30c9ef5673053fd64e762d9efea370f 4e524c57a12abdf684c05bd99eab65efb947ff2a50b1f27ceef7f4cd268afe05 620de71f6f844d9276122bf200e757ea8fa38e690f38ac6800cec1673ba64d0de43c4aca2bd0923d38d0545cc5b04652f29fe495570b5dc0daab4d9349ae2c0f +generate_signature 4fbbf6dcbbf50f92d5f60b467c9bcd4921b756691660b2ac73b256e6b614acc5 0453e634c6c63a0dd1a999307b2c9da357b54fc1e89eedd1240f6501475d35b6 ee840259b97e841cdd17946b4b4acbcb90c7bc05996fea802825c62f18c00902 9b81f9e7fa4839c114fb78bc6d8fb38b1d6032cb23345b467267e56c4d76bc0e35293a1829abeee61faf70698266a274c91799a2e6e1ffa62c1d1bdcab9e6a0f +generate_signature 7038946351d9332520e91640e4ea8aad9642e66a9661c1e62a519a3e03d24f57 9bbd178c6a6bc802cc56f0565ba7ef52eec02c1f0098a3fb1a958aa1885e4d63 f68267ea33101df63bb15fcff1bc528b032d770fe69a0b6f0341c614e7ee5d01 5f4b4211998242f68c29fe381ce56763e6781e20741cac081a50ce0cb535710ab14984706aecd21825be565f1042d5cb0fc8722e5d3de062fec1030d1d26d20d +generate_signature e8e5ae2e4f4f51cff909a6a73d0a24be6e049cdf32af893b6156a9f3bd7a0613 54e78d50e27c98418a28d0972af5ff4f7e6a5f2e212d792871f4395a4e0842fd 873ea1693f04187e4b39eeb4395d38e2b12494f3a426dc3ef1bb58a2c0a55608 7161a8faa117477f6b943ec1ce4f28518bec2b517d08a442d05520d17e33400807ae101923b353c193d158f0b192f147efa3e32c867bec890121c99dab495502 +generate_signature abdb0a9f87e46a82240bcc77f5aa5f8c0981398731f7bc392b1e7f2d569c491e e8551e4b00aa9a74084250f33285a955efc56a310bd287d97ce3f213eb51f97d d28b26262099d372ce35d41e3a289d793b425a62205f0f22fe348510120fbe00 a5a40edf34100f4f7158abebaa700ea38cfc65f8d3cff61f413ae225fc8a6505607471c6e0d0d3bb5b36a6b81700a39c4d15f2090f216d003ea6d8de21c1d005 +generate_signature b6e7c69d55fd322626930ec53729cc2975b911706721a48e41ca406146cb63c4 58a63d82e3245e9771435211f2b415c5739c99370d08011e0baa1b502302b16f e1e4f2327b82c6fd7fbd35905d91056df0c8df6702eb282487ac55b3801adc06 dc6c6bbc0d93c2c7f4a5ad30b45301d62a133fdca1439486a274fa3d1fe6e702633d12045668604095f840da7cdacc611b3740c22843d13014cd7cc1311b270e +generate_signature 98d1fa8e6b508971d25a7147eedd2347f076b72729a35f9b1a81203ff85c810d d1e1c86421a34483152b3cc8bb124d140fdd638210ee1bf0df30c80b54e61343 5acdd92d2c8eb54a0ea6d466f5c2718d703a5108ffd352b6f8ff70f2baa9010b 71dbc320ffde437f501015672bef041796a87294c116b4427a46f491b3a2b6016e74d506626738ed7f0135006403762c6f7a764e05a1632bf69c2e540acc5c07 +generate_signature 91dcff5d1d7ec3854de213306e4e744ca4c04176d4b20830d1a2012e6cb026ce 15b09f757df19ae41ef4e9050d0be8e76c151b20a7f4f792748f83aa14b7e0bc a9e865fee7d1469c369dd683d7808d5ec65cd0f035dd5e09c1eb034a7396c305 0dbdf01fc7e53195ad9276404fd80cf44aabad5eb35dda24dc3b693d93e9510321f4655b8ce801e179c29d844f165e39e4b8598c253e6351902181ac66afa007 +generate_signature 9291ce37db25aa4c373266a7aa25d585206492949c8ca4671eb7e470c6a85778 9d35b6133fee1dca194f7a64e8c1dd4a03a76e3805cfbcf80c9c42f9a45e91a0 6716b59ebdead7684c13ead0a4aef3fea77cda742bed36b3dee1d66a475d0309 333e7053a5380dccd063e503c5b7804a67b2602ae86c936b7edd6433dfdd390aa9b4cee2986e18eaf793361b42c69ac498054278793cc6ae0bb7cb1576477507 +generate_signature d2dfb2e50813260e6bda0a4150ad893b32f99b2dec47ca8402f0ab8ae30603cd 7b8bd1f571d5083a8316fd99efd6a3a3dc54d87d78425ce1f46185a2cdb18a95 5d76e12ac8050665387e1c8af4e18308d9f227b0decf22355fefab31ce1df804 74cc5795a093ab0703e3658b13cd06a43856a8cce0600484e5ef439a90f57b0531d4fd659a5f4408b1668a91cd24182543b5f18621f273e261f9f39c75513202 +generate_signature 7ba6dedecefb1d24c087c994a2ce612e568fe90b47eabd04a9f44a9196cc7d06 ee5a5d892f36ba3ec29b259ef936c1a14085caf56e5419ce2c85dc356750231b 648229308a95c52f19b3011f816050496d77dc42afff59adfbfa851ff4da470f a83511035b49ad8c7e8b2364ac0b9479b68cb5faa718a94d17cdd0975dbea50591ebfbf42f6306888dc286b04e1d981332b9af27df8edf513a5079f27a88990d +generate_signature e53c575148d6502987c90b32ebc374a2ee76fdb167b4bcc2fd963aa3293a50d3 db099a6c2dab7de4916d3b2e21c2bf1f89f24280c29a4802ee27899089353573 9a34773656675cdf07d64bde08eb98585b9719cb9d52d919d54d70047639b508 2096f9e9ab033afeee8ac2289cd163b14c77777ac1ed933e8141b778f376d80b3ebfbf400c54a06d6bd65d35b42364c4aae8f111b04134bb1ca656ff7d96b70c +generate_signature aa909b74b14671e3c56b0aa0a39e956897151694e42d90f502f5426606a4bd3d a2481756e3204a51d40c8088e69851185a29c962f97c800a88102b812606ca0a 47d0d3279058134729f860e7e0dec0943115dfe22f052ef7756b5bc263aa030c 73aaee6e2e060f3694b6f43aa545cd3b8ea46f98b2f2042418c4c0bcccd0ed088c4ef6e9ba9a387f658afaf0accd57027cd9066b9c16aee086d6308df631180b +generate_signature 09719be164df8ab8ffd5d4b6820d1520992afbf6fa717cec48964f3af489af51 3798b31c7c0f929e70268010839042b76df746c4f46b0e219521eb73e89a0d4c 516de341e7a3e73b96f2a8e3c0427bb73eb04fdc967f6e0d2b87135c0ad72907 d9fe0e18d772a2c5a952b48b465672dd1d7aeaa577c7860e5a4fc1ea793a9f06c512c29e07efe624c1827a1d98539183cf8b426238bd19d1248400711bff660b +generate_signature 95bc343c1fbc1ac7fc31c617f0944c8a5caa4b91977bad385ddb7b72133b9918 3b510a05791831d9d86d268a3c56f48b40bb3b2854236f4a1457aa573f1e3616 83ed82fb8ea18afb5ad9664ad412d2a9ad5d36119aa08eae5ae48d3b6e979c06 04537ca77df512dd2b7c2221c0efca3dbf245a53834b36fa9796ef36f15c78088e423204a1fb8dfddd38ed481c2d240606570f049eecd0f2426a7ffdd2959c05 +generate_signature aaa59d9c7b9745cc62775f1a565de3e704ea082feeaabf91897c163e9c453057 f1d8a8a9d1ca40c3c1985276b8dbad02f9b05b308633f8d53ddd23fde382046c 38b8d2d9729218db5231f4e46c2641bc43983320d493eba916c9d99aaac88208 156f367a85ded5d3ba6312da17ff5ed633c921fa208d42f84a46a89a0efbe50c3fd45db8337d59f09c71305638aea28f1a742474ffba4b0b82f5b274f73d990a +generate_signature f4433ab65909fad4afe06cdab382d2fe7b1f2d12a47ddf3c4c634bc9cddbd52f 320c05d188d2ecaecc06c15352dedd207739ebde86133f7152b3b83074764778 d34800b40f3d39319a844b8a85c65bc8e7aee303a7b8e423d2efc1c4c48a6704 91912604506f1354d0ebfe8627919affc172cea295a7b23deb76f441bbb7170510d56f62f506cb7ce2c49bc68766612e749ff9c20612112bf74f0579f60d730f +generate_signature 121cda7dd82e45d586ec16c5ea52fb38026dc84d3acf8b53d9b14c752bbac650 5af2a1a8a88c0e0b53e555a7077a737c2cea050b7dbc0ba3d8ca2ad037c908e7 007af32d54c623c7eeda1e02984238b6799b08db17e3a4231daff62ab3d1640b e28d3cbb8ac6d890dd13651888b9786d1e290cf9d15e85e9033b70b0c7c9e10edf0b169a08dabb7ca9686304f6eccc4a4419732a1d28c3170b02f9b1ed815106 +generate_signature 4adacb5f6d707bc06145c6c445ef70db86145b78af456ee5d687530713f153dc 2d96e3dd0c90587368b586dfc7954d5d6ecf04523d0797a0fedfba91f65649b1 1f8093909e4e249adbd396d9296980bf6b65164dc6ea679d955b98502622de03 d6f5f3410d592f961a60fd6b491d83342afe0296b80fe7ac187384684097da04d7ff27f33b313e9682fe3cf40e2ebe483914af24f1063cdc71ae8d3fcc4a4901 +generate_signature 86034412d429483e52eaa4f8e3426f920886f5a7302f9733b60c3368f8feda5d f47f3d62360154548b01b27b8e20bb653569dd2e0d8f3e2e4926563b19d2905e 383927c522c2201332dac111a750e15bfdda86b1d47483a11624290569a4f808 a6a30b194d0aca299634d987586c3fabff01e1c6298f252fca4d86fa80d7a70f6ac3ffaad7207affe8597417f36e408f899667211a4b771be824e6afb8c7e40f +generate_signature 891ce05ba0c25b7d2409dd83487ffb0328f515d0dd77bf1c2503e33370f8cb99 0103c4ef2f18527e1630510bc27ff5966b018199c0b82a4a0d62815c74f1d0b7 fb1bf90759993320f4e16f3237c2d63dfddf6594f21c74e20267d61a8bf7520c 3e87b08bdf0ce44c6cebd512268f4c121adeacea1de178cd26bf141208231f06ef01e0a9d5b53aa839a11ad18dd7c419022507890f79bae7e5971e9923950b09 +generate_signature 268378aaf9b6403f036e24e356e90d67c3b82edb01180fb7d135e895283237b0 32b9fbd425dc1a9e2d6c693699594bc310737d3954b8dcd5f3bec5a056a4e63d fa028fb4484c90b355655014f1f20eaa711d1d61ed8e200b718b46d475603506 98e042418febfaad6c4439ea522216bf948b73134c5bde454317d7ce746cf9052268c5715c4b75ea078925f2c38e63695dd5555d5e747b884775684e4ef7070d +generate_signature 4c1124a23917f12efbf34c9c90b1a079667aa900b78b8a77297f55e50c3d6e21 ea3392bb6cb736c3053fe90bc64917412190b673f2d1db93338414fafbd15414 54cff91e78a84670f568167ee279e72cb0a32ecf75544b5e4d49ea5a77a92003 e312ba94001f7daa74bec81e592584fc81a64265fc52cd50b53749980e5f7c08c0171070b787dc05a2f8f3c6c9c8f73cf393498bdb2fe49101b6f43ca96a0508 +generate_signature 112cd2bc459cc678065ba583a09c83d962e385cb546523901ec4d5b47425d0e3 0693ef1cfdc58c35a00dee5477fa4d8c73422294c88b8f9d826dbc414dec2306 a3d6655a3bcdb2baf44248a541141a67018c9080001457e165ec29d2c3248600 7db175555dbedefbc5d11e9d53ce989d5905941fb7ecf68d4f4406e1b860db049885870621bad1733c394bff92439fe9553c49e0193609436c9da83ea35efb0d +generate_signature 2de379049e28fe930809c36f1062769665d4133d4d668a718b84f9183332a2a4 29aa902ba683847b1b59f09ee480e1814454bc72c48fb3884540d369f1a9f2b9 de444332bd0fcd47f6c1a5b7fc7ae1bb544a2298672288f04effaa04aa7d940c e18bfa9531f2dc3be33f8c65c7e72fab9e0d377f2aef5f284ae55523327e09089a7b69a2cca10c24c9bcf3292b17c266057d489443dc489b6ecca2961c2e9002 +generate_signature 0d2ff1cf8e58881dbe688be73ce844772c6696636469eb8ca9086a3ee2ce07a3 a743a9ed747abc154394fa822224212c3f7cb9fdfcb40a24a142740d1644de9b 08281ab64eca078a437c7f10208d0f5692ae85f6603fcd1d9e8ec2bcf9f64d00 94e06838684a7d42210d145ce3bb0a3af17cd9c8e9269ba03b326e41fdbadd0cb175e2155699cf9855a94efbae919416b3232d4b4a91d229dc294e608ec15901 +generate_signature 7104100649edb970e649881d4059faee3e51e221a3ae07fc33d944eb6c192322 c10ad6f4972dc849e2bac69e549929822102071d43f404abe8049a529b9c930b 0e060a4fef0a46f9c3d8702b38f82270e76124aac1f6a8e1ec402aa9e7812b02 cf60c2066ee25e8c4f88571413a5277b793031796b9e3ce789236cd15c93d20c7a26daf3a8d9729e19d6fe3f62f3a24487baf959f4d55ee0c737e93c7c2b000c +generate_signature 995be2688f3f7354dc17d7fbd48e010611de9d84247e1e738be9faae777d20f9 89d352fce80cc5dba45a618468866cbb9414f5fdf608ed5dde3fb446fd665c20 791941512b24ea359aafcf96ae0d9a7f7c24d34e2177eb1822dcf12776580506 588715d6bf8162263ab4984bbf1f264366afbe8d62a3e08a2af4250578d4af07b2a8e7a36925a2248c328ea585f830df5f03a7a04cbc351ad451b98351d52706 +generate_signature 77262429448c69ae1fc4c99b652c282af2082b046a227b57dcd724f56ba0a696 9b605f01f72e9fa6faffa84481b9e609f7b1e20b8a33b46b16cceb7f5c0cf411 b912862268d63a977c75fbfe9aa7008190758367379862024232c0cd2504000c 300d12ab9700ef5255e02aac6aa389bf05d0ff1bb66f6be966b48a186df1b3035896f690b5174e38822ff7eef74009eca902cd1b6490fbb2dcb736d055f54e07 +generate_signature 382537401e042257c1a0c6062ea8ed101da3193a6cac540d675354f12f7cab82 1c209e65076e9d4dbfb5762f3d1f59896da89efddec6d696a4498303f67d667f fdc2f3443bb4f28cda3ee7cda5255d36a89a983b91361700b63b87db477d1108 202c665707b18b265040467c06fb3909508d2db2f77b6bbbb6891b09cd5d5d05b00ddcbf87fc7ce47af0605acdb94b145d6b31879d3a75b87786fde9c091d407 +generate_signature 55b89623ad6f7b1d2ed599d2a04d8236f2d3fb8b337ba9704439193ac7956889 eceb2e5ac867b1603e9c61890aafe7871b3583d38c0a9f4084573497bed466a8 cb1a0a38f92fcf57064b0b1e666693cd1abe9a2b42cd4c7c667c933e3ae1340f 14a0a8f8066129721a4ab94808d4115f769af3290cb580386bd1b9cfe05c690cbcbef2b272818204d660f27b70c51e6c57e66569b9470b2df37706083c2a1c0f +generate_signature 22c3ac4d3466742eef52c67e784050c30b5d5ba7b9235e4fed8190ec18cc50ff 628a568ca8cc07afb1ce46b3f78af000a37dc9bca3fb8f73d7d5e697b267fd3a 0e180e4841d5de78630e900c364dec44daf2f74e72066cc609eb917995a8cb01 dde10641b93f100df1fea2a623493f901521fd3596837080dd11dfaa6dc39807a94a9c871daafc3cbfb3b59b3f986a995649284c03787c559a495c6459d5b007 +generate_signature 8bcdbe48e967d9e68775be61493e60f6c5488427caa85c0c42b3ca3aff756b75 5de2c451223d0cc7293ca1826c02215c6b519bf3ee0e5b91483990c6250d808e e8b26635c9a1fa4b7f9165b745abbd45cba7258b6420187ee6e4325a89b0e802 6cf7d7d52cc46ffaba43332cd15b11646fd32240d50806504988344a5e1e850411d777a982d5dc737c9be327e05578074835b2aeac88e83d9d357d4d16602500 +generate_signature 37b33cb52f44b8c43a0d619ba8270eeb2ee657c0e70734a05c2de878f77ab540 7f5ce9f0aff75716477a94c13dbcf878a8a2513920dc40fd2a29814555ce1629 f8afe1e242f39bf2b08c35d6d18aca0900a1e5ae729efe56892919484b5e8c03 6d8225e08b9e87e411a095d8567c5247b9ad0e4a20f3c315d4ddbdbf47cd900b06ffa84ca6f438d6abe48bca459fbe4e4bbfc93f4bb373a8127cce97a34c020d +generate_signature 069bfa548d79462cd27ad3720842430f2c4947532513a36f0e012097b77e6a7b e6ebb1f4eae6ec2d813b9213050ac47c0054723d754685452f112551e9e6619a 6cb63dc9d194448e748210d8bae8bbee8e0cb494bcec2b51ae06c9f1478b740f d2a1f62bb022fb37ac968167b4ee5bfc643a56b87ff87b3291d3f8e05f0b0d0ee44ac410207ea5cbeca6e81c7e0923544399bb1e685d2f7e4e7bd57ed3519f08 +generate_signature 3fbde8fc46fb4f1001ac7fd712760e0d8ada351c2d2c28b6da74bbf9e2795c80 79ae18c7007b1a790ddf2e6080615398ca77b4d06c1b2f7e536cd6b8ddd5a21f 70f8219f8b4d2567a4771051f2988b84f137a4f84cb26f081843908c7d959809 11d6603993ff0a4d34d7dbb6a7b412d69210fe16c34c3b2b0cdcbd6fdb857609d9c358093fe963fd64114cb3c5e924dc656e3525e673f03687388be92b21200a +generate_signature 7b752d6c0cc3750012b98ff0a4fb325eab31e8bbc0dcd995d9932215386e4582 9519b641893b754f8224bec54da6b5c06730c3f4c7d4704f2999a21b46a30032 0e931c71c9a3789e25f79e722cd6858d0fff3f5198597b056247b9cacbffa20b 4382d6553c00e04a84615e7b58ebbfedf18d9387b4efe975615f5175d464030676474828e4b05caed3aebdb9813791f492c522f364f21c1805270e6c472be605 +generate_signature e64074ccd0cfb5b56a89cb07faa1386061fc4853b0b2211d87a7af02bc3fc0fb 7072faef529d5daf4fb8663574a4ed86a7fa17e5cf10f09190e280500a216738 d6d77164dd8a1f6859e8a814d2a17367b8a8fcb5e6bdf345d74ad6d70658520a 2ffab2c3970c814be63e38fde4f5f23d60f19eb7d24200995712ad643d0bb9096bf728c1ac616e417882f9956da4b15a96ab3e4c5f301d2f75a40eb0167e920d check_signature 57fd3427123988a99aae02ce20312b61a88a39692f3462769947467c6e4c3961 a5e61831eb296ad2b18e4b4b00ec0ff160e30b2834f8d1eda4f28d9656a2ec75 cd89c4cbb1697ebc641e77fdcd843ff9b2feaf37cfeee078045ef1bb8f0efe0bb5fd0131fbc314121d9c19e046aea55140165441941906a757e574b8b775c008 true check_signature 92c1259cddde43602eeac1ab825dc12ffc915c9cfe57abcca04c8405df338359 9fa6c7fd338517c7d45b3693fbc91d4a28cd8cc226c4217f3e2694ae89a6f3dc b027582f0d05bacb3ebe4e5f12a8a9d65e987cc1e99b759dca3fee84289efa5124ad37550b985ed4f2db0ab6f44d2ebbc195a7123fd39441d3a57e0f70ecf608 false check_signature f8628174b471912e7b51aceecd9373d22824065cee93ff899968819213d338c3 8a7d608934a96ae5f1f141f8aa45a2f0ba5819ad668b22d6a12ad6e366bbc467 d7e827fbc168a81b401be58c919b7bcf2d7934fe10da6082970a1eb9d98ca609c660855ae5617aeed466c5fd832daa405ee83aef69f0c2661bfa7edf91ca6201 true @@ -4198,262 +4198,262 @@ generate_key_image b9adc45192d3096748f58c6aa4180c1084ee1c78a116c3480ec522b542021 generate_key_image d8e79793544bab0ad58fdfc3c1bed3759f34dd272a16d487172013ee7a0eb516 d033ad38553f7da7820e2d808f89e13ece56cabbf599e8f89346998bc2607609 0d65336c2af006c30b9b3726e6785765d35bfca27272c7f6b886ed39c9f138da generate_key_image 1b70e47678324ca44632276550876be0e3507884e8ad9e268788d5e03f7119f1 0fc5090c2d4d32178cd217509da32aa88966e3ec90fc0e1ff5ee6ad42f038107 f06ecd7a0b5ae6a98c1d711dd7bee77f6262f84df6ad013a355b5cf823863ed0 generate_key_image 7427c053014583ecd07e81e1c917906c381af54a7ecaba8498225518a156bae9 d9e07405029a8bd4ba75dbda93756228e18674e3138d2f7b2e7796ee7430ee01 1253d396a6e7a2bff50c1fdf54bb90157727fa20466fac74e9138355b17092e9 -generate_ring_signature f23065c28a04de5d38606f37b7cf29c680c06c2a9bc00b2bb3bac696f9df5c61 7046e48f17ddaaebb928ae39dbe62c23441f01ed40d23fbf5f07e5a352d06197 16 9cf7b3138ddeb90d60b31bbad6458bd58bcad71192d37e69444b28f9450ab37b fe25432b3e417e7123b3b55661f9d8e01b9238c801feec00d01b0a144439126d 1af5776b1bddd8ea5e775e035ae7a3fbfa2e08401f7bb01162ca7d2c9ce21aa6 8138759a1d698a79ba0ee523980c7899f5833ccd15f9c224a02c44accc46ed71 00cc8407088c92ac28aaeebfa3de0f699de189923fb7fc18daf1361a7356c203 6493d68aec79197563b65b4d202665da993a27318538b46678aba6df7475e6ef 2193c3b3e8c038d3ee84d30a3e6b8ccbdf29b25f9b576953907b28a3abe41689 3f4692db3e0e194005497b99f5097938659fb00906b308e4413ab07d20d21ca2 5adf105a86dd1d4579bfb3bbd362119122bbf9517c089273570189f368919f60 8e2b0684c678a5e9500332e375fe28f9ce127e1d847a56aa198f81d02afecc3d 75cd3c47a8d0616d4f7374f3b652e2b4dcbedc826b8b0f22c8f2b12d8449171b b26567ad1bc3e39a4d59795b347cf852c35944498d5ab3537ed76f63111bc196 a78edb131426ca91e0a25be0197578a4d4d2876d18313a940814d8c8e65f493e 943aa48aa6dec62a8f30eb16e796196e3a35569203e58067228c8b496a739d4e f9d1ef180af3b08d9ae7ee9dbb687591bdd3f8fd2b1912de622cce6a9e0d25ba dc6c4e0b458a8f3b47d5841dda4b34bd01c845031421c8fc34d90f2356564fd7 f7738841783117a5206b00b4054df1949312437643b353459e02552d2c69f10c 6 35543c375bef62446decba5b701b9d6ab6fa9ef7496a34fa69dd7b356154e70b48d8f5edac9e6747108e4988d460dfbf8e01b5a5bb1092128602117ae1ea63019ccd049cf57ad4ab59814ff218c68373b596effcd7ac9724c80ef24e9cee6609314223945883af4b688a3332e184a9af97fe5e32d9b1935c20e4f01640833b04fdbcd33f12b644e8214c0e614feb23560912cd9331ccf18ad2192937faeb280c6226e186f3eaabbfd7a91d17e7d601fee1ae1507427378cdf6606b03b49ef1030bc1f997c876d799ded665411db272572baf71147d98c72ce9d74586242ed70cc304bca4eec61392564be36699228037ae4e0f30a3b6dbc3ec04b749a8c7f00a1039e06e5448a63ac0f19b7210ca123b8c6391d9d480fe77ee3a3d12f03a0c0d659f299507c415e168f12f7cff9f3a7340616f59edd1814208fb226dd17af0088f35efd0468bc02d1bd4bca546c5767fb776e4988775cfecfb54e5d2a2322a00d6f600c11298a426ce745fd1c8cf83125ed1d0999e62fe8d6b97b1ace6d19905b92407f16854b13f2950c692a7dc2bec6754bcb4a2461e15921baab1b29451003ff160934f063c8a9fad444a2ef25a767016d080f5ac72856a8b58a63e0fe809c3e08eba1d970a3d975d0a0731411f6fa073c2fd9cfe587dd76187643bd3280b96fd38e180420bfa66b7c84ebd30bc9a0258dbead563ba6eb9563058b5d5340ee1d00b24d4edd26b0884e171cbaeeef242cdda9a9b0d6264f55edc671d0c5e01197bfa84ffe3d19b41a8efa617bb340ed0deaba427a803a980665738de666e08432f9e4702bcb37a7161288bf9a4a15f1c7a876aaac365c6d17589a1b63a7a0f80b9f6c1596d9eff3bd4bb4dbac571711314b9dfcd37f1e7a4968248aec47e0c4ea897fec99aa22d8a24064cc1e4d5c53ca2c4b2c2f4d21af89187edb294100e00568f5c1a9423b58a98e734a084d097dd288b63ade91a39844a9d3ca828d5086153b0ea8dea0f853b12579dae0cebad5e5cb47fb1ee2382351c61c689be6d04a82c71c8c6908cda5bfd613378d2adae734ce11093a4420a32a1347e82ef4e034311fd57012c4378908fe1c71568647703d5c16451bc7422ff395e1bf37c3806f4dc672590fe3dfd459796f2661535cba870df5452843db1dd6e98533596080148f3a3d390249fe7d5e40797722496f97bbb68544b38e9e20aff7e99c6e1aa0a9bbbbff6a2cecf105f1abad5f41323cf60a2ea069609e3f480ae1f2bb9dff201c071a7892bd5e212d17e8af5d050058daa2b2a2d380ff0612bb00bc30332b10e67c5e5e5e97be66492e1b081243c53b094ae85d13d0a6994004a9609745b740829ee72857f6de48c90b06ddb3284050c7ca1fa73349295ed9c255186ec64c40b14c13ce99a70f75257d5a3a608429506a6d2dc93c3fa08ea455cc4b7921bae00 -generate_ring_signature 89226689e486049662075f55d46361d821c5ede1fc172581458207aeb3d7374b 4048d63774cf0e3d73059b76c1160f5b36fae2add758c0b5d0a76eccf459081b 2 68943d3665e40eaa5d8ce9a3279e70e9d00afa0cea15d6671e024efcdad2900c fb89cf7108eb3b68243e732e820d716e11a0baa0def8d2d837ab998a9bd642c0 f75b48b628a7f3fd1dce1055f7c0b81c36454e012dc7ead8d5528c11cd52990d 1 095d3a0d3188d2d30e9e662efc69e56060644722f1b37e1d24c831844b322507546a80f5655838f461937500ce799358fe2e589e12175a6614897e8f52ab26068fdf38533987e67574068cfe9f4336818c30667aa4b9db5cc201a15a67899d0945eb2fc328d4a5f9343b2b3041492c3584fc0c63c4648c948f3ab4dac7d9b40a -generate_ring_signature b5d8229ce74db9826924b3c6e5caef7e7e5bf671ed19fc11be2989dd3c47931b cce45b0c2c85b4210b5b11644afc9395fcb69ba98603adddb5553445e9ec7b6c 144 0be075ebeaf99a172e8e39e394767c3a3f987767dd4980c63801034626594ae6 73fccd68f4dddcedf7206f4928e50477501c1efd04ac95c240bcdb1311abe7d7 82d86f2cee19fa0019fdd5680e9f5bc9a0a19fd20fe801693646eb80029cd721 5028c84c1470faabaa794544bdc8cd2c711465def027442c68cbb51d8b26a173 cd8f47f244cc2c434906ff8a3b05cb0cc6237dfca4df80f54f737ed73a8de6c9 b5820b71fcb114db2922d51ff6ce2243fee94e0b2b325539c7ca31701a291b9b f8935af82ec3e9e25665a07e742a0db3ab87cac8f9aa8765bf50edde6b039370 3ccbd63146f9d7b10b80d92ee369e723579b31d62d93c6792de1a4eb498cfb3f cd2d042ef2fe9c3cabe3092cae589b3ac93bc006c44191ec547645ccf67afdff e2d93bf17b1a2fea61e957bfc3e8a9f354ec7716fca36d9d3147608eb3af97c2 8a48888c11261fb5a99f7d446d679b545f9053b2daf6c82afafe43f8ddc2b6e0 1d5a580055cadbb839eee43d38dddb20d970ab5c1a9e2f05c553d299cf495774 f502b134474771d28c63829de5e2cbb68f561ac4424979ad81d9561c77c9a8e5 1d0c147249493a9cc4c6a08a5e1b787bcafe06363736cfa165b1a01347160495 5ac2b45e81b6098c0039a2af48d87b98e39923f3140768b797ca3d33929ac7ab 3859ceeb597d189dc18be59daa68d39bfc2361b820524631bc05e22b78ff775e 96dcad77dc296cfb3929634e642229bb0f748cc674266991ed53d64956d6677d 3035e9feb91d2bdc3917a8c58b76600141a4333dc94499e36b9a75509ec9278a 78b57f73d0d54237460f950433f02b23a8b73fd686db4872dbbaccfd93e4962d bbc589f174313a7862b5cdbe0bdce6ddac58d6167fdd906bf255e3e98ec79160 cf34f7674a32ea2273517d25472e5bcc686f3f461c734e4e93a302b4c9439d0b f880e06bdefa123e7b6a09ba0e0de33fde7cf7ec3b792abb07ad06107e192f73 988521245df44f9840aab96fd90af3c22455058e24eda4f2e33e1269dff4430b ebf20602e0afa497d66b8e34e5269ed831e970f912310e178c1414d25ca71c35 5efd0c9703fc2e020379534b469c526171091147c59d2552a871823c11821e6c 943dc0fc80c35556a653903f09cee980d4f66d9e7179dc26ace15aed32cfb9c0 274eec520fb3250395785dc104e5b914ff88a4d7f9da7e07da6c0830b2f3a1c2 560f145a25c13e0a1f6d9d79edd399d5afc6b09e3103c09f1d77b11a975e3b2c 3b13f3fe0e4428737929f2e13aa57f675e7e3688d8b7b0475d0a950a730d354f c0c4ddf2f2fbf1c0c8ec3873285ffd498b594cb5714c851c27e1397d386e12bb 81ae0f6596c54518ccad5d592123c5960e17b589686cadf3b530b185d93048f7 4ca1879a6b680cbc2024fb37a2a17853767e884cd8e2ad20c2499fbdb53d57bf 56d56a1d537d1f9bdc2505bec8cd238d765e1bed5c245c1054422520d7204ab3 b3c4e1763c0bdb20cd468a13560fd0ec0576d167a3d3d62523067e8e23a2ece4 90805b8b9ad99246003275c1dab6d1bc2dd6bb12454ac381c662048c5bc54738 dfea8fcc3267c854025ec6c917b696c1905e23282ccc042d81ab3e37782380c7 d86baafc5adb032b78d5a7e2047b619544d0d97236d79002d3a091897fa0c48d d1f6ee6693c03674a865ff5f24316e48f844784161afffa57f0bec4d098f01de 9ac006713f84fa6e3bcef13946203f85dfdddac7a471ccc417a65fb929c52d3b 9cbfc2677c60a2cf155dbdcb8065778c7428f6ce8524f483d67eb45e7e9ce463 ab7bd7860210e59ad3231d0309b591d1032b6af933d59506641e55b659efcda3 7d5e773ac67fb198cd86d94f52d8949d3a44bf213980e2e9355451e65d5d3888 3f34184c4cc8f2d7fff24871d02347f522a690866c695f2c7592cd37ce48f9bc 6674fa097442f932e1e25123d663672e2de17b2385b8c41a6a509c46f89e324a 234a35e2f0da5e2182c2450e90101cf1690235894fe8ff5cf7036e03d4423865 f2c8967a786fe891000838ae56ee84891df8dad799971bd87ad9e3aa0dc1d03a 0484249715649583e496f21fec59eb4c35553761ab82b3bf85ce18e67c184ade f6104748641de70509aaaf7330d390f45ed534ef38bb11ebf52ce8e6b1f9cc42 beb938142360b3b1f0933990a5c0e65180d77c2923b2aa2a3f6250c153c8dd13 518d918bf968bdcd664b6bf24e865348f7093ed723e0293ee86a2402b87e5df4 e86e665a415da43c81bb03d895151814ec4c045147a4bcfe37a014a846f26436 1a11a329f7530ab7b31198f03d8d29754ffe53af384fe5d4db3fe90ffa3360a1 cbf7a677e205f9ad968df137584d4c90438505a629dd6b5f3c4f822564b41c8f 903ea1173296e05bc70d6ecaab59f1a6ae55ba8b428d5ea9a3a5e4217ab5dd49 aba326ca541d77ebc99dda5c1ecc21a07010c2945ce9d5d18a2bc753fcc4156c cc007e712cac3f9d64f16ed07dadddf934b1b9373247e0e8d350e5a2551ee0b7 14200d798b42df0eccfa9f36ad0e18f1aef0021e9d3ae7912e71bf4efa947f29 658b34f8f8f575805b075dd65b5493b737b1d8b6ba122a55a25f7053f23da8da 146f311fe86024f1a81034d6c9bda14c3d4728fdbc030901a1ad577bef3ca5a0 9eb53c235a0298a92643833c1705b6bbbbf99e254a74e93a63b1443934ee7aa2 ca1831e48ac62ded5bba90fb71d61fcc7704151495bd72e05c62f780cf9b519c 4d1d68714278a5333173e703409b4303912cf3b44133102fe9eee8842306fe08 4ec22758002566d15055dc51f1386907f7104dd011c8337f1b36fb29e881bdd6 0c90d65ca0d89c7835d5cc8f185c6abefcc68c0fde058a516ddc19aae133f6af 548f850b0f17d7b21e8c1a0d77785253b05737045b944364c157b942d094e5b2 d0607ab0ba606a0765283abdc2db799ab04c5c63edde5554396e28a87c5bcdd8 51d421c5fb161cb1c883e2e81930d9f848c5eb587aa2092431afe368fef3e0ae 5ece9e7ca0757f3342408b957d8a0848fdee5938251626670255ebb0a75ae101 5579c81801b58b99d1238f2253651b143d8e3ec4cc69f0ef5fd5483d216e1319 7bcaa05b83bb272070bb8987bd618c24e45311b57085b5b6a33f3e1ab804c4bb 89d7c2d2338e0b5fe50d17efd1a567460b484d1dccf9d528efa6757d5233c85e cef2cf9153cb0ba4f39713613ba40ff9cad9cbb7e518fda13e721c329e6e38b0 8a831f7a9a03d40371d569427e1c00b4c6b59a804135c90849fb0abeeb203bbc a71b0481ffb4425af168570f2b0b415ed1fc1c181204e21a27fa5862d8a63c6b 99fedf8d43745d034e111b8cc7d99e54d18b53c40a428d2628365b2b720a67e7 d2575e2b349a45027aea08f5b423ae42950e39fd365891533196026f6cd2d496 e081393f25372bf4f1aee37b8bb04921fb8f6aa0fedc1143ad9fce6de55243e1 ac4168afb6887345c8491a395b777fc2ce312372c6655295faed65742ac69bfe 5472335979b474db10d62e368bd14c7fa3681e2aa3310ab5175d47b9b23d4861 3e70485ea10a5d0763c84c5dd9e09a25adf926965c59c0d7d1345a60d0ce6024 ea6173b067f377d97a79537f532b8d2343567e92cb9dc977e772cdc6129447e6 da151c45da028df365edf5ffb819db00f38ceb10fa687d629f958d653c7f7753 4d94eb70a30b0c63513a4f09907f972fa82a2f941be6bd9ca914641ebe8553bc 3907706663fca37513a9a30facd133017aa772f69731be6d4deb4f40047ccc48 32d52817b46b90f7cd04c2aad2ba6f8d44c8082ba397c60b0d982c5c7aa9a8f7 8abe3186bbb742c573ac355421962942ab2c75facc6c898ee4a19a03b2526ddc 9bcbd8770aeeeeda57a9a2dda3b526e5abd65acbfe8b68ab4fb346da066c476d 010c68c46034de748d583b050e2715d98ba852735272e8d11d6e527bf1a40cf9 3407b8a4d8c5b985a20d33d3896cde2cb823320fa4f7a8f2385dc320d83d5ddb 53a7e5fb8541fa6abcbe75a39cd9b0352119fcc84e724a515f3442d4a558c55d 73becebdf4b4ddea87969a7d672b4778586a5711226e7ea72b6d615bd6eaca29 96cc838b65be8f2cc82682aae4948d766751bdcdb162b399f73b2d1b28a47492 2a0780dc42a9aa0ff3cda976a46510ea79ade528d57c66131da66f29046669ba c0e71216cc5e4dbd872b783181fc19b8c838881b8c7feeb7b679bfa700c5f00f f7b1094d3f05868b1d8f82468e3e63d6ee98a2556190e8ebdeeddbe739662e70 7cd1ae917e9fe9b2250d118b320a611c42907668a2a916430086e79fdc31624a 6c02f8d8d410727f698344007fde07f7bb260eff705a031fcca93387c0538136 d0f96ccb71432fa05978ec91f83d522bc6237dbc29a28ef02c9019f7674df4fd 0754988d535e9b8e840d17088c97eb0484b9086fde51eb499f9079c8694b9092 b45a7849a1b66581d71acd062609a406e78566c94863ae128f4dd89db838b09b f2c392a9b334780a36990057be799cd2d96d9544b3388563fac448e2a8e61ba5 ba1ac60d28e8fe4266f7e99ba5dcfdf2c3f03688836b6e39295b4f08356e5e39 3cb51ec951027e73f76394226b502c12549883591c82f40998d70a24433c584b 6349964aa8486223d4b70c8b8fe69145525bd91ef6628e1c6cdd2ce0ba04c266 290f25e23204297c88d4e709a0ca24e3cbc54b657393ed8569e1d9f5110cc2ef 0ff7d6198640d9e511867fc6f6eb733728d4087cbf803cd6fda69743415dfa0a b11f6e8f2fb83fd784b1281372023354d58d84ff26c24f6fd7701537406c00be 0b5a3a445240b4151eaf074d6be3c50bc54fbb69db6f1eae09b6c146e81f87d2 a70b418a5ea1f707725dd25fdb646fc10411acf4ee3495c160e56057d469be7f ba5d677d820274a39f795af23e660a8fa619f6213d0c99051f93006a472105a1 da947bc68bb177db418974a50388357ba6c0c7f7d1c269c6c7e7ac12013aa388 b8fface27affd9eabd46e85658c00b2d1a187938e70aaa0401ce2645e1faadc9 01950f516b23727d50e930d6a7f982701200cc9b4f91e5fdc24fae0621df0648 d1525f7d9ef2244122bc256f431b58a53f348af292547b970214c78677d96748 928e5176379bd48f34ef5acbf25898ddde6fc2de80783d71d01dda12f38a85e5 c4e9fb2607e4e77d6be6651e8f3252ee3b0cb4612adbf38432d8cc40a25b6423 e8c78da2f6c26bec3eb9d0c8e54d7169a780b4eb3a67f60a7be45b3b347950c5 5f198b0d848e36526f7159ede1b985ef4ac6981ec31d337efe6fe896236b48b5 d49ad6a6b2bb67adb3503179d1c79163385eee4ee6169fc060058b8ddb9fd401 80bef6ec30689b27bfee132087ec9308d11746263f7dd4313c400cf98a45724a ccc998e5dc245cedcc864285e40a6453fd2e443a687e0695e1f36887168dc5a2 c6b95bf4bf9d0514ef8f69abba93cf993c4731598e9bef7ac7d1df9b5cd868b0 571028b516c0d6f51d1b7809fd5066494fde172fb962f2a95d9091cc231bb462 f039561da33396d6cf7f3d5234c3b624981a193128904f296a2d49539c5a5354 c254db3225ffbe528992738a1c2a2d659a2b69b7823d5dca1f074768b2d0fa1d 26e8fb8d19c19f48c8a4a6fc8c7ae07d81a20e338b26ebf71eb6fe9cbedf82e6 20c5dc8182e869ee3b7824eb8f3aa8bbe41cbe85fef2416a116a781cc761c459 627f6fa349be0f4fcc820ebab0c373d346081727c41b3e41f6908401c55ca8d9 dd81b44f36eacc86416c791de3b6bab04d52f8a001cb805f71a09572a8dee99a 621a8ccbf534ee9b37d39f83a6f02768bc0bbdd56a9ffad301c905f43f95df1f c0662a10f78456cc0b271e278563c6b269dbf1cf6ebe5cdda87c07b735aa2e64 49f3a3193e87521d12becc9ef14c623e844f1f1a6f55fd6c2704390268f45d90 6623968079cf82cc14b56fc0eb73faf93b4cb5a4f6e1c56f12e2978aca03f6f4 c9f349184647ab482890e8f118a92abb469f62c2756b599706898a7ba2709a8e ab17adae0cb94f56924e7aa5e4dbb18b640fecbeb23f3728694a071af7efdeb1 d3b700aecd64ee52833e70c957c2d6d3f3325321786e4ec6fcd95a4645e016a8 a6e161b23862fcf9f036fa3627f2887089f79bb4e9df6587a23cf40079e07a02 44354eb4d4a96bd9dee8a8e74f2596f5cf117eb2137057758b012ef761ebb94b c66e82e556e827481441c89dbb03bc57e7fbeed3b684ded48c276056bec9fac7 1376ca9c2e462f8d22aac18d284d5ea20b8614a86b30fbe073baeb41074cc51e e098ba48f7f5f85336e47ff10a3edca5eeda1bf9717de3f4262a80e77ab93674 2779e3d23b90fb744d69d5812b0c06bd17ef83d509fd6d5a86cdfd534dceaab8 d66a3585928fcb67eb352804e9905ac7bca6d6011fe5f7e3c15df19a6f9d55c0 9892556bf022ceda7b1f04aaf0328ec0220e468010a235b760069df477789167 d089b93676963402c9ca2305200908ef13f6e5e5539cbd865b44cf6b32499b02 106 12ca358808284501952f9d157c7ae6252b38ab014d01f7781042dcdfda02e708b909ccc8c6ae1162c01cd0616b02665ec2b146c8776e4503297b488531b2bb041e946ffae962ad1ba018cad7faf9d9e40fafa26088ace24e47dc61fecccc5901d0a6aa2c60b46f5d85c7c184df48f93a13976e4937c4b4aba35ace357207290b533951d9f6c6ac7c9639fe0a9a6e3a636d5a2018417b1611ef71e4b90b6a6e04f0228e8ba1d9feab59d8c2c4ccd50cec13c9220cf741f33efd941a17b2af5f02b4c010e33221163023d0b53f3d9caea1e8f42b1c0fa6439ff27e281b03ffe90429d4a22401ac332ab6a4663d66cbc568ab77ef541767796e28213fec2fad380976fd9e62881a69c8dda41c0684cc1bf23471bfc67f5c3dfb3b1e18e9181f310c7fa0c8365f54eb77eb5e642f4836173c987ecddaf709f99a59808f2f091a950e8bcdd07c454e97b82a0e4d14a4414436fcee3574e38234778e7eeec57770b401746958056d6d066a78b66ddd3ab65f31a02f5084bb71ccee24b789e5e13c7305c75ec1ec0f5397383f79bbffc16b3149f7e9a9c5c67478edd0a099bf5a17bf0d018167e32fa63da653646fdf400314364c030a132255eee57c0879683871770cae9d5feb91e8e948d1e973bff68f4cdd78e17134b778ce5ebdd658664533850369bd04189dcd5d94f903604ff517699922246ce4ae265604fbb845347c9d330724d673d721dc97b486fa47625a896efefdf5fe3c41e2b792d23cc8448aac8704f88353b139d1f4e749171a854755a600fa206a1dcfad73af9dce6d9398f2320b48e7a63c58e960fe5b63abd9c8602b2cd36ead9964320e96f746985cfeecc70d4fe1bea9512f98590e946ef76396b2f39149f8506ef93f1be530b92aef5bfc05abc726f85a930f0dbc87ce4123a9ff3b7cfecab3ebdbec6362e0d09efcc8200ca33710350165506a0354d7bf52eb935ba2092289b4f0bbffaf1754fdbbda3a004120813d4fc1e280ef9348c521aa2c986702c1e27a6454acf0feca067147a60ac68bbc269541a50be4c3c5d4c58ee5045ea260982cf8860f4f12d317a42cac0ada69f1b81fc961f6e053caf7c9ea205548d6a7a2a19b531ce9c02573af35ac07fbdc7030937897b8280d70b23f50be0e974179da72a4cc901a88829052d00c0edff5f34b1132999a30d339c079b682efe2270a6a8bc80952ea40117cf0418705b495a0aaa1de3b3a00d04c24232e71449406aba31debd36e5704bbcbce16300826f9623ad2442a239e608ba8eff2a76fbc8b20ff0c60055d1c6fc63f8b72a90c54ff3ee9addffe43e2764bc2d1dca5a7a717ad3e7f395324f88ae7213131ba0dca4aafe2f3c2a5c295294fe689913ccd24947e839dddceb7b7ee2ace87d94d0bd45994ccb16cde1e6de3042d7f3a81244b5e16b03c39fd48e8227c57a294db0f1f1200823cd481fa10cbf07a80b9eb4d5033865e678fe641b90cdf25860a4b07650be4a63a78fbdc1928f147c77e3e1d254dd82bd21e773808525b51b2aa4a0ac2d9d5f330514b1d5bbc059b2598237ab3e419789690b9fd98a2a3311fa67401986d1559144238410aa30acfedfea75b45e65fb3a33add72a5f838bb4f0b04063db28fbd61d4b6c63b69c24c2dd7e6f5f6ce16b914166094e1bd6043c5885208cc5d6ff63f22416e3b7741de9deaf690fea9e4e8642861a2a6a601699bddb800070a41dc4b951351279bed44eede61bdae90f85879376dc7303a849ee0360101ccbe7d4b6dd26c95c5805c3a5ff9eadaa415f751b77cac21c34102e03899920a569fdee21083a63dd9616286747fb47f7faaa08346a77d2f5bec34062f8d9905975bfd3bf35e757dc3752d788c3c112f5765db63967fcfc9f2f4ea5ca2009d00a8a2339796ecee04e4028e9b4e23ad338a6629d4a64816d80f7e55e6e280040f0d2f5e6ed0a59be64c16c193902a1336c05a5999f490e9f3476c9f897058e50039ae25ab0087921748d1f5a38a55c86c3b2f792d057e2959ad2d48fe7fef5103b92a7cd703b264836b89295fca913526bc2922e1c499ab4a85deb5e1a94643067ce40d6b4cdf9d45ea104e2305879bb0c0d9f15c2e4e93c12c569e5299d0bf0559a45b658444dc1e7f2c606cfbb2c544cf63f3cec1586f9449a5bbbe8fff6e0fa9e595b3fb97337b69c58a096e4196d0e9dcdceb68d1c32bd91b0eb5b8744d0a2b142f169253f3025f6627bf22ac3e01e7c6ead6f585af692999a4ff8e9b6d0473c8786a72f0f9a11513d163b1944040ab80bbc56852dd8dd47b880e57eedb06bd0094cfff52ea997c6142034406d89216cbb18a6663d3912e67803db1cf730ab8914aa760106f7b7cd3bcf1b33d1a1cb4ec7c3ee6dea62fbb0c5f44f610f30b3647e3db2883b0534e992dac3909d23b51aa02ac96663414a3b09f53b0cee5043307e95d656cb9ea8a0e000112bb160e39313e9fcefb7d764f4168a19e97030167bc345f3985ecdc0ae589687f34018e622c9385e775bb81efca3e96bc5bf0032c331b3a4ffc143edf7a4f2bd55e6a3ce4751635b8bd30f7cc212aced57db80df13f6f5d273cebd940fe7d4ef8e1d5b4d79b2520408a6d61e8113fc1d9b3c40084ede09f602e7de1397382c6263deeb994b3f956207a53031b506559ee08c200f49977be6e025edd360167303c736d118b1e1796146c169d56ce0792a8290c00943e4cba899c458b051a2d0437b2a7da18a300b5343ce85a19675584b982650b4b291526b70ce2a68304dd5bd9cedcfd4f41357f267ec839bc24d3c6f5906f03d197a921815e124cca619cfee719c432823cb9bc0a95abe35b1c8b4a563d3b06126f8b9673c78ffaab50b9bd4bdaa3926c0561d32b33cb6ea34908a0ad53a705e57f73c18b3ad711972eb968516d32491d98e554c5fc5d531295a549e50a850d09d7a1783ddbb9d4ac2c463a9a85d444cac5b283fd860b6bbb6ee4e74121dc06538721d7a375142cd0b619aa84d1b4f66bb97769847c379df060b4df904da108c045e484cd96e3b3bc7c92d313d7e8133174005806a4b1eb12eb61cc9b26e5026ded5e5a65d20c2a6361de60e93a991814ddfa2ac987d6dbbd238658a620840ff3cde5277c9f0d3c4e06ad1ae6da8a0d45033a6163a3655754d9c5124e80670f30cb163d3e175f199e1db6d54de4ca15910002f2d4cd807592e886acd088310d55b7960c3677d0bf7364db5d9faae209122188961c0e19d47ea116eeb3389d04fd5e53f8fa3ad2b72f302152df460c07950094367a6bb1c76e6c6bc57a463405816f4a3ea003d322e04206b1d79fc07cfee9c26899b71c41c572cc9846a2490f3cb90d79d2d9b13addbb1744aadfe6473f585ae9cd37d56f50eac555b5edf9007826b85fe5cd787ea3744ba57ba705cce3c8f1c172fdd8d10aef72f88cc6900bd7cc665ceaca2f742e129d6d457c77ea8630a56670950cc5df597e3035e2bf02925e7b8555dac8940caa133da12cdd0e18d348f1c54a8b20816c5e17631bc107327a04e107d2181f7a9b86e36e8c1dcd902029a662532303174ea41871a0e4036fe809e71e57ce6b82b3f0a5d6af93e5fdd82452a9c1ff96a58efbf5039a5604c27493b8927a4f318a4dd2c10d5d317a491d63d8d522886b750affb5335b0f0af956aa02414dc94a755ee5dbb21326ea6524e0fe5397f85041e405846ac13b02719a18005ad8cf9a92de839f2951b739206ffb75ab4d4f98516422ce3970dc037241c1a85f18a2c774f0905356743b6f994cf09ccc5db2b89b79689858c5ac09394a265f1bf60f0e4a426e019baf72812e6c3ab377d17b8483630979a2d9ab07139a4f4ac5b764e174a7f4f1388d42bbb7f4f658dbfe2178503384630f018e02130c924bca3bd982ada71e0a7d24a7024c7ac3b61ddfae959ec41b5a44626a003c0e19524e8058007d1315f3278804dae559360574eb4e162784f99a7062d9098a23f04bbbe96d806eff78a217573a2bb6da2cfda5c0f7f5ab9337f22322eb0c58e7cdc2a0f23f82103f9f64030b1f25626abd1664f958ba0f2c6359253977005373a8a035698f6c9f2e592654470687b77e4b9535365250020a82348d3cf7052066b3881500f5c46ca4db97dbc0ab3783cef970a1f4d4f1b3ba87e6e90c1c0961d6638104a1821fa03b30022e66031ec15d668e3ea0e3ff72484dd337f2e30bf606a62b4e320187c95edb7cc225b3c428b8098765fb5b028856eb4f7cff670d04d102ef4a28d1c3cb141db212e1ade287f8975b036eabc2538bad8baddeca04ef5705055d00e5caad11d51478a6e53a34f5b8956a9000bdd51358d5690f5f01dd15e0b0884fa6fc2f7ff5052d5af34dcc4eb596f2a62a068245dd95301f6c026886eacc4dd7c770c94d626ec59b4cc49846ba34aae25a25fd3f4705bcbe47093bb01765dbecbb0096fdad3e35fa76cab6a2965185515ba474ae7eab967f2f01bb9bd7a4335f2841ddba012b5dd9741ee884425f66a477fe46d71e1e6c002a0d7099c010c316806f99ffa8e73388f0218d6b9da1c37c370cfd699a5ac460fb06e81ff7e4a1f835b0894e8cf3646c8cb2b5963b3c9059142277d70b1f978784056666709772b91aebcafc0f2b468b90b7a71a2a56cf1043d308ced8249990490392bc459edad192c5220388a41852bdd62c8831b8a93907eefdc3eb376aa9d00309d5c81c1241fbfae37b68002a0d5c436cb8048c677d691517edc681dd956a0046476866472751d616964ebb2296389d16cd346d67d20a11da12bb80dcfc3d09b6de8a494dc39788dd9780fafde080a7148998517381aae05454c249555a910bd91b65f157041086ac9d0506bd4da32de55a64d06327bf8d225a41994c279c04fd051ce9bef0810d0ddc1b4e9dd1618ea9657adb8259f7878437cf583e09ad02b86fceeeab290cc6b812d591f7d4f9e9143d55610fd20932c17bb39dc950cb09ffb1e40b7b681605de2a915f84dccff50541d34f34f568ec629df5c4b185df04b95ec5f33f182eb4e25af99f91af440df26c6a397e990b93f7c441ac11ee8b0ec5a5832e7b4aa073d0de29f59afbdff435aa08384ccaa65c8f70b36faa0172020e4c23df23f5d489bde5f319ed31f55a85974fc5330035939bf3094a9b3c4f016ce1dc1b99076516849282a50790aecc381f06128fb588e78da1ba33ea9ca60dc246eb01857d17db0a6d669b08c3b3e2967851e43bb886cd33cf8828f5d6a8067147f9a9ac544c315cad56622bc9ead8b69afadc81fe20b632b4296d45d4580aae69e644e6c23069ffcc93d8cf45c7205b775ded3032bfbc2209e84740bc9d077630f79c3ade66ec0c9c4d7c3bb848fc25225bdea462b00e1b8bbefba0b50302c96c69ac2c9c9e57974a733dd2125e6ccc395ca7c7a87bdc7861a12206098900aac2bb5e974bea2f90cfc592f964b122f5525bec0453ae8af8cb7896ddd62f00ca5fa63d050e757a738c34012e18f327bbe622dd30f6e4b54108b9b8f9f47c0109baf7f34fdfd95a61d4b2c7f3c59fc5ecd52961791f297f73d7623d525cf90b5bf0cd7a784f1e7d8eca92e509d4feae8f556b1626cbe8c047d5d290ed01a90469c140a3445aaf633fb2bed3c2b2a30312b98ec18fa00881857373c6a7b5510db5b319c4afe634b7c56395c5447a37b32091ff79f244290569847d1b5d1d920efe05b3e8ada5e3cb3add037dbcb32f2e3bb144472721adc042cc8906ecbbbc0c0e65ad1678b619a6148e6f264379d1dd27545fb43ff133694b0104722bda9d0954c0d5cb4d4ad62b1acedc844574016f914cb7261ad693a398c68664760a3d07acc185fe4bf033f50338f410fdf64199231521c2cc907c11ee0b72591f30970c7f6a05e89b205c71091cb66718438b5d7aca900e0a43d183e81bd2c8916f85060fdf685718e72f06950f08009fa7fde9a4edb0905288b49c366eb2a74b74f9059b8790114ff22c88688fd88098790cbc5d9f7855c9f9c4cefcb3b2800e83210d8e10864f1e5b8adc1427b7769d0fb80050e5faf4e75aa2871f97f59eb7e3ba0bd5eea6e4ae1ec85148e1c6535c1c97902251a05ba805f9716990785e400eab0ebe6a542869fae6089701e147c3a0f1057fe3a8740e04371b47f658daf896190c1743591cce483e4a95e9687647e5d8f24e58ae184717b3db9dee01449bb2e70fe5ed585a5b1e82dc52a25ef942ed8610255f29a5ec564a74b524952548e19606656f08578dae8a9b702ffa20959ed2d8cc72a904bde19ad490720ecc8a5a2f0079245cea98e69cd0b5fe83de7223f87075dc27e0240efc7a8c4054c152e3f30e4e83430bad0b9df601f1173dec4f4a41fd86c9da322b278d780cffa9e255c8053c43d5f6c29271dfeab06d7c104d727e80ab3487d5cbd7489d347a547954cb06439e54d365a7f0a8866ed10b2c24872a5dc31a92f15c5ba43b643080a4d33c0684c9c6632c70768b85ff9e8e7afebb6971c04939d50a272d6824a176b98321008292850bde080906ccf687b3098fd7f1a674c3b6527d409718f0c2715285e80eabad6f381653c4203106b6fef8c313ef0467637bfa6941270e7daeea13fc66091a8e36185b216b720de9a791940ce5cb12bbcd0ff46f870153425ab6454ab90baabf1450feea5338a34a6bd522c6930b9c6b3449ef6dc8c03722df572aa67c0f9c8efb9c8b7198ea5330e2affccdb140a9f826c581b0b027d07883578634670a7e061d4bbdd58d5857ab0c9d986cf306c4fcdcb272d265e075bbcde4c181a408b42476e2cf978b3600353f31ff6e662b3944fd847df1a8a3473fcee22f7f0c040e7920dd689cd49db14cb0728c95fb167ce35a559dab70cc09a5f452c6ef1f0fbacc213d5427aa83d2c63c9bc684131b4907c996c4268a13a7bb0c8d5f568c0434c872682b1ba76a37e771449b836ef0a3dcc735a4f7b1f6474ac0bb1f83880f907ce30c4d53814b3ed8301e4f80e0dfe0f93b02b414d3ad092e0448e984700e97edc1d530054568013e5b75a35e53e31b4e1859a45bd06a8bfe2b0529e3ae0c247755958b4017459d25c7db42eee699e3f5b3662f745643f951bb4212687006ab9547d3d295f869b368fc2d79da4823985e3c102a08f3c90fc2279cf7bccc07a10fbb2ac32008011503d73f8a1350928dc17d99f9ea2a60e10c1849b1d9db011b46ad84459f09ac9b181591d7c812979c60559c71f7fa297457e23fbb85e7038380cc22aa0bfbc334d25edfdbc557aa132f3d6eb5c81b86cb4166d893369006b3631002d920ef7d77440dbfc90c73b2e924e546d7352c00047309f68a2c960fc834a9aa81e81cba608d4f67351a6ecd4bfea5975c0718b63321fed600d96204559d4283a2dccbb1c69c9820767bdad4fa1f0ceb7c2344789ba31bcf3803840d77ccba76ab24e507d792be01684713569d0bd89d18d889775ac28fb5afc52c096e39421d23eb728fd897ab9361592d32623ecf5a9e50e30bcf38740c0c9c8c0a0159d691266f9d373392883203fee2ad141568774463270aec890720233d050568398d1495f04ffc7f8ab8c5062e54baededa2d6bef603948bb45bd42fc9e906e21f374dd4c8e3f9f6b6ef6a25f2fddfc28cc0a26650a427cc1d2484b48d4b057e673d61e211a92a1476f8a49409d1888401bf3ed7bad2bfac236afcc2f7dc07e2d6a1ee882e4e1ff2ecd346b62cd7fa96cad3b8219661deb2cce2c96d60f201a7ebae5d5013b888020978f8139308c90e79ecdfcb659104fa9266a6ec9b2c02e4ff5ba9618a02c636e01c29661d6cc1de76c9d635c450c2ed9b9f41d391910d0717729c780f064ee7a1ae8b26cc9c3e0d0bd7e0d25419d5826aca18a4731e0238cd2afffa7baa3c10701073f6d9d474e8d3671b7a8b4f36f75ee984412c1e02cdfa21bbb5061a692c7d7f4b571aad1247901cc7567668228fc26de45a3981022474182a3eb16e922a00f54c30a44344a1a9b96cc839dc849f1b0723a3a04c05fd65770c644910c94651b72bd8332266aa3506f62461b9a15b39bdbfd368110bb124f08dc469084f7e9e132ac61c33f2ac7174e51d3a37f7b685e2a57536240302b5e58ffdeceec86aa75608f9b7705e55040a165a021d83ec058e6005a6fa0a780350f3dd779389b2a7e8926a8c6e2b7394addcae0266bc76706954489c0c003dc292098e5c4a49c12f000b823da13f5e15cbbe2c1553bb53d84ec4996cb00f8db5042d1c2c592be597839dce5b1989f93f4a7c30bd0104ab99150519b41e018cada1b7bd77724db7551d20ffcb9bd4be1618dc95960ad2b2b5ddfe405b520736104c1245e15b3792afd4f70bf24f20c5084978edea150818d98b96afe03a0f0019c4baf17a250276d745507085ba3ccb0ba4a72f5f9e413d1c82b8b980880959be53f7bb88d06987a6e48f14cf88444c4f082a1639a4ea77cb3cec5f593405dcd8840bbc906f2afef9c452b733311c31fc86f71c39f222ca7f8a2733fe3d05d47905e7f9089f9e279c89a041a3d62ddc751fa179800932bb53f26632232706f1d3457801391443dc5ad2df07fe3c9d191b02ca459e0c30a73fa3bb1899280c0078c67117226c2ee9992a13daee82cddc136fc5fd6c5b1ab2e76eac7003c304521da52df2c5b1b613ceda50549e589d08870d26cddc46fd91df60aa731494095416779cb7927bc3e82f02f01f14cfa2b5f838cb46be26b497d799bd5b945d032085b5a36d26e797266f12a94ac496a526747589a5a0bf2aee4693892715940abd7ea0167596a6bd5b17eabf3e0d7bb0947700c0e1f93aaefd7b4ba09ae38c08e7253f7e5fef906a1aa77b8dfbc359110028decca1db222dbdbb98bffa4faf0e4698287fb73a159242b186d7333af5ba773014e4590a0b2df739f34925778a0e2eb3ea471969630637a872abb5c7cb6f6e43a4f230ccd55f29377a1ee945fd01fc97aff901da84bf65a2ffc68dccc8c6ae80d7e4eb97650fc9d793276cea1b07dd4d6b8361aff22758e78fa21ad5ba314fc71a514fdba96117c7975cfe0d8a0cec4f89f12f5224d480c79bd55a7210a9c7801c026ccb885ab769051a3fa94a0633ace23b654a26e77c8313ddaa82dc2155f3e5417a1485c30d78a3bfc25ad10a93a0277d24b07aee0407d4283d1c8666fe83ba22262ca39655be9d3378f0af044ba52a9a72b01b20efc515ce65314d6728e50775ae83c16e7a05e58bbbfceb0d2990630f425232da59c19c6b020ef3d51e855d756bae6c4d11205de62efd730268be7cb5c64fc50cc0f8717219f2eec52a7cd06d4b3212fea635ba138548d20099d9d806ab7ea5309e5d76d35e4a27ffce2355488abcf8efae2b94a8715b6108c9a4c24178b694379be9ab9aa317fbefc2e3f67a99a3cf33def91cec49ffb501605fdf79694e12ca5a51b3398935e5bc195ffa77c09ab164126cf19d193d97062d610aff995c3dcc6410dd7258298c71434529215fcce74cc8d70d9018e6e00d707fdfcedca40050908a5c977b1b49c46d45a79fcae9d6134400d9b294e8320cb97b2b52496cf80a1f06ea9c7178d289d54d957ef8198152a155682da469b60746b139e6b52ce56ae931e8bb2a964a2584977936383bcd8783ad53eb1f51c008705be4be7ffa7ec6f055e53e590d0f2f60ab705d7f5bcb24f8d2168282b8e3031a338324b2a38d55ad44eb4026ca5adcc45f6e01aad25858f17f16e7f3e1880e4be40597bd72caa0a236e51d6a1216be205cf05b66a3dbd02d0d2fa507a3ef0537429ece34bad65101bfeaddf6288eadb3303e4c4ee313b7267daf20c0e9a301207e9f572e9e37ef376f0b1019d493e5f3d7bbd50467b8cfca2406902d75ec0579b6425f4361ee8c8ce4dc04f045995bb74527501f885563729aa9c84d18a10a3d1170e2111a6fda3b4f52cd1ed9e4dec02f2c81a0a1f1c6f4601916daa4400b57a507ed3a677ec6dbf95dbf7a5ed94c0f933124e073ba5b959f3652d27e6b073cfb78982410780c2300f564c0b4e689530a6464508f1d52c361225f3403b909674b46560d717ecf83896f2d7f9288cfdd34cea3df36bf12747f59c8d176930f1fbf4a13694628c4d238308c5577b0d42c1a7ca9aca6c623e460c6829de02c097ac48ecfdab55f4f7a43b0755749b792c36f2083c35b51e2af567038cb5ce90ae29c99d8b0bcc8d1d72c31f162832c8b8289ddf4ff393e790f7c49504be78e06cd638dded60e3fd27815e03ad7e1cb9a4cc2c46df00fe0719ab0a4f4c9b418065176e8126924f3dd323edf30c99a39e60e89d350604cc47554233e02e562590696dd7fe1cb307ce6d94d5e63f7872f751a8bb956b111c5d02efc949165f4b700fe766276c37bbb7d2075bbc2559e71cae5e42729f1419cc7f34292b8bcfb750835395b7271f667603008f358a423b3effd543525b7cd45a9e2d1342619f0580520051fd65bd303470e17e6b57a1de37ba1b4b53e403ef242252d60a7b626d2094b0a6751bdc36640511ca8aada38d1c80e97b68b9daa85cc04cc66aa48282004ddb1e09a179c6a011e39d42bb593a604edead19b7283cf93625676e27883590e0997428c85e25f69bd82ad882455b4af8f461b1074828bff4e4b4b2e4d25e706a113ed83382e08f716771910f88f3cf3e9ae50c7591527008482cd91bd0a4808d30e2258961fa2c08caca1288a766f88352bf1ba5bc383a28065ec63feddc1007e259ec20eadcc56a9256aac2a24f4294fb64ef8ea0d070ffeee714f67a3f20cb41582b5d72012cff3443f3aaed1a9bd2b83ae4005f7d1c7d6b48fa747546906d5186c7d26a5fa4a8f98b2bc74a541bfa0ea13073fc3549fc559046efe257e0ca2d4d75805e9a179ae82ace920c95f817954db949020974c914b5414423dfc0f440f240595f3d3d8e2b596a02beabb0a98a41e33b1c1de7f93f1275cb8395f03c0b02c94097d4b64d805029338fd15018e6104aff703450e82ca501023e29209b10eccce95abb990080a662dbcef3eda5ba29e37953583fe398c345fc5399d02be48a37bf3bcee1e54f13951099deeb0a95176225487f5e0d6fec0b28045a105fb739ce47c1a7029e70f78d1e9558d29f91a974890dcecbfcc38bfd9a2446c0e87b0f2767b6ed56c8e57cdc6bcb2cac59ae9e1996b11b50f96cc0f083bad6e0085270b9f0d882926588be9b46b2e2fe2528fac404301488c1bbee3fe2fe85b015406c34ac576e2efabe850c4f364dd4f3219c353196251ac4fe4fa998148b00a36d304107c7c64b4b4e9b0fe6c140638be41527302c0acb9fb51ccd5746dd20c1b7538618d428e2cc35d6e74cfd8a8198d8f193e91c98a9d56c3f2f89cf19002c8f96a047328e1f6f68e6e510e50b09f9a5a847fbda2f922aba35edf111f2a0983e741ee2e0cc2476bb912c2df27fee86c8c0a2640894b578a8b67fb3064a0090233a8bd6310a39a6075cd752844cb5ee6f924b410a84b41542f17d88af5010a3b912e5e37bd4ec0433c6429e944b0e1232b4ecde6bcf1b96a6d5104d770c2044fa4d1c3885bc26d780fc66a322353888158d18f6e089af0b02165d6f72d0006ea36ffa5f86627182ca1faddaf9e86d85521e3baae571bc0524987513f0b8406d353ede948f9920c4172a12143902caa700e7ea9e2d91c8dfb681da16ac0240ace547c18836051f38a34f8c406ed36064ec88bde6712d7e6cee851fe4ca83b0fd6536d7dc540a442fb92a96aa0c98f3db85ed731608cf86d7329b8766bea31053204e0635f65d7d55b65c76a1100ccfed34ede7a456872636d6ef547040b5e040aeea6beed27a6acf5e4a0f91c56ac29b819648959d56a06e822046802687e0aa5c4170953888b62db3b528ce3e2b4ce9d86b3a6bf4c190d589cd93865eafc001170fdacc5fb7dec5df5254f7c5278beb2bea0875b7043c4a5d04bfd7bc4400ce0fa5a3f133e33b4f66728191fdcf2e9994773a6c8846a1f8f21fda4993b2c0378686f2cc5ed21e59afe37f98ce0743b92143c0e83457da706eb0efa82fef60e6d0e4e72da366d9eb614207e1a509789f414d1b0a05a7c8e91aaf1fd4550b40cc0d59139e181bdae41f9e510a650014bdb24df5d9b61b111e408b28c9ec5b808c242393af934775d6b7cb48f29783e07fecf21b3f7ece63b712869d5c6dd9b0ed47ae62af3517698f33abfea850b1f34ede4ea89bad89919e73ba5488e120903db1ab87a677a101a03fd2cf2031bd5f27c943966f4c38bdb2f8ac3b85282260c1fa7be5014d236465411f906db6826391ecd77703442c294af2c6c19ea347a0443944798199b945a432025b3d8b1b6e07843e0fb424d8677ab849c2287dc3d0259d60a342d8607a23ce03776aae6d5a19db6ff8868071b9b76d90f29dc077304b1a82125d513992687f26d0f80aaab57c924035843514153bc3476b19ac7700093c48adbbcf83357c4d8bff882b466e9b49ec773621bc22e7d6bb9155ac0ca003e4afd8419fec08143d5924585375929c10c9f6614613c18cb86e9c32257f007c6d3d556bb6b80a269af77e665c01a76e260934b35f179d98a2c03b973222b0a7a48eb439c17d011e66708e35f8302d8612af85d4cb941ca4feff430fddef001155c30767941cedda2027618f381cf77a89801f8d8ea38454b9f98a5c330550f3a79bfb010d0e451f7ae598c143c69d8bb400192d0c5dbdadbb183a08ec727019f521d7aa990524faea91fc83950380d37becb055809c177ab0b28cee792f20e6744493028bbf4acc8f0934aef8a31e9c647a5948742e694d088faef8f5f10025ccaf3eb9e6f00f652d92f376786066b34a56dd2a96b7a990cc03bd5e3d2670bc182ab95bc9428782bdf3d24f8efacf8014a5da84cd0d43d6c55b799223d970be2610fe5c0a06b48fed19eb8791315f88221416c193fcda5857dcdbac38526091da71286ff9f828d7dabdf409014b904a9ffa677e0f5d5c0ce6ef97f88860a0bd0fec565ad9bdfc070eb1aadfd81995549dabcf1ad2261501808b6aa6a2b820f -generate_ring_signature e8020add6aebab8ca5f8b49f2072f631745887fa205d8db1a3aa1b5a4e232d81 dd963b8d2145bd369feed2501aeac1de2fa16ecb1b7cb93564535a6dbccbb3c0 2 9f1c652d42539ae6c7a43a5118d5890a4e1b386b3a400ebd8f2dd5687626dd55 90a86ceb7951f7b5668205c22e8d2c9953d0e44773f7d0159618a8a0238a53b6 5e6dd5608134fa4c64007aecaa340a0f379d1a5c6d4adbf017a239eba303c808 0 a6805f5877b33f74a206d4092d7eea8e2efd63c5d12a63fc9b32e4689d846c02b7c408786c434e9f21003b678e952d6b863c2557bb894fa8aa157ebbe1f2c107c239cc506f5fdb39e31f953d45b3856536ed5eb90904e91b43ea15aecede950853d506cd5165102b11f920a9f25058836404ae1747fc8d1fb20c6837b7fb8107 -generate_ring_signature 3e592f32788ec54e3f10560b1380761329df534096ec12251382a96f8cab7eba 0b72892038d4248c430d1ac93f4985a8bb9b43fdf457a83618b7045980b8e6a2 1 526c98024c9a4fa8c6ccad5101f4afc972fdeb228620d774669c13ec4d029cb7 0741f944319e0c4678f4a414a12c6956cf9d4b3ad04a40cd6030e47ab7e9700e 0 62661198eca5aa9e2747f9ce4242ae394bf740a7cf8b837e27c7553fc8c27b027c8f99a5290b41f7f8c5da350cbe14a399abb7785726a2c3db0f291033a54f07 -generate_ring_signature 701268c079222197470218f73587bdeb19c3620f25d1511042edabd0efcae448 c2b7340137942802b68be0a9cd0deb826a43f7645807c8f4179c64b11021c36a 1 515cc1cbddabcae11062f52ba676265114a44372719b9b5dcff7865cfbbf1568 20966d94502e95dffb45bf07173991a5c0ebca48c0941c8c6705f7370bb2340b 0 6379173fb83310313f391b13b27eb636613c7676ccf5fe73683251ba45acef04f64b90c1f8bc81199d8afcb05892025a39cba255946d68ebd0b03d3fa6dd9407 -generate_ring_signature 847a7cdd3eda4d087626d16b975bd8dea19bd914d35051759ccd76080649a606 a05d0004f793a217255613e5b533efd58bf1d00e9ffe7d1062aa6eaff00bf614 29 60fa9da64e6873d5585d7c6b445aa994181e460fcf9c4edf9c2562432034c418 319cab68723c9c65b13df37ec1080812e182838e83f12a49d72aa8b82f8a906d e0d78f852a658ba8e2812978927a42caaad783594e463b73d25bad7ebf602a5d e5d6e07c783c40cf86479b179ae2c3064df13826f6ef66d1b5bb458788f628ad 97d175ad6b1daeb14df659240d2e567b269604bcbe62615efc1acbb3ebdad4de 5915b9e450d09664efa12f6477a526084e9a1c16c814f366e4175cf03f0bdeaf b08b9168207c344ec1f1addf104b06f4d396fe0a703c6fa22676549e221a9819 e28dd982bb083b405c5888a05b7ff932026a2d163febf55f7f8425df7a2381e4 b6cc0bc087d836d4e29e5ead0bfe51998943e147c259a851e138e931d6ee2cea 6bc6641ed933fd309190317c1b43bf34a7fa205b2cfb041c9f8d51da1775c09b 2438d50597d45379e848462033a037b7281eb6b3acd259a5190d9279e79a3d15 eec728d14ce0721d82e552a13d446866f3e43c5fd45d8459f6517aca1f703e38 6fbf0ca4da28ff0d2457d63f48864662748274eb304d6c22e3bfc83296ae0deb 51aed9ec8aaf554276b3397a30f18f76eef129585a5ac056ad9db42d6b062ab0 6d3b31ca3c9fcfc03be971f1107ec82cc5f5be67a0cf280c899ab566ee3c3cf9 acbf10cf496ccbba0ce691cfcfb240d1392c583288e0dca2b562710f0acabf5c b227447474e2fdbd382e6dc62061f4313c040bd951dd46d380b1fc4b8dfdb341 93ae8143cbcd9604e8862ee5d5942e90114e5133fd55052cd2d9c266a858dc85 2d90f8a4ed2e98285e9ab6938ef20da123f365b84f3b269b3ed03dc885e2c86d f7a9bc8f7901886e7f5b6a62c0f09022281d213e043df961c9bc61554ef4c8b7 58cdbcbb72356615330903011bf7267c8f2d7d61abfa88789d43567e51c7cfeb 742e0b7bfc9382859b7531e43e11e99c1ec1089ee901d502f116742194f78534 bed2b49b3170073561c62fbbcc1397c1e82ec0a252299234709a02b5badbe17f 6c7802b9d92c53b2b8ec8f761a260e680f92b4577485b5f516fc594984381047 3f32e6f5e41eb10431e1113916f94976f4fcc9db76edfdcde37cbd20a22756e3 9031e2a54db5f2d4358cc9486e5b25626c40afc5c43b20e260b0bc301d85bc41 02dca47cae77e6ec54842ae1a80f341adda1e0f5f78d016a06d1bc5595b7574b 65399dff20e45ceeb08f30f42a1e4f45c7c086e2a5f5c30f0645acea610cf4d8 894d72f759785abdc31f519d816040dedbb4df5af332187e9265eb1d4051da06 6f6da025d6473c5c0f30402add3b401e177f144bae5f907af5febe3ce32aac0d 7 11c10414428f2bfdf99191225d6767088b905a4b596dd124289af61b099d6f08d47e7b9a89e2812dbc0f2a49680edd181e2bebb5e15fa87f01e9758ebee6350d8a5d984a00b76a6c82fdd828a0631b4c271befaddea4ec77982da720e02d5e082767fbf8ff0ffc90572ee67f276758591416170972b6501bc83a009286d1cd000c6f7e3b509c26589d2782cf5e556c4096b68c61d72043246245e57277e240032143c68e626a892e073bef554aa840977d9e637098dbd3c149fc92db141d3e0ec4ae1c4300b47617e692f63799ccf08faa33cf444dc33889a068c8112f11220a489a634cdbc16ade92da3bdc970926336ff3c0589a495115eba06d023fe1c80edb81dfcee82bec113d7e478c54f89a25c4d87b33b0677a08ce1647da9fd5a70d85f5b6789e95e8a9c5c54d1ca3d56ddaa0cc56571e98dac6ab82455d1ffdae07c232de878e49181acc0b2cc33eb51d02d3540cae91135333d96b15e47a1ade0285267963070e9303e693d1f1cdb799c045a80ce380cde6a08a194e69a7db16055c92773704fb7fbf4929cb25623be299b398a6dabd6d028014541fc54613000422bf12e32d5fcd899aa4600b0c13e03aa95b26ba1f976b6b33a735af0a94e201b195216e3e2c8bf23501a74589f55a7bcc0370fb7928c76d44d493576d745a0e69f792b234fad8d472ea3f9570fbc297759d70f3673a6932a36a8d42ae3a2d0632376ac191dcdd0f9fc25abfe6ac8e5720f0ba12c13b473da46160be19e34f0b0d09e59545bed2e5b5c2523ce95c2e8ade3ee566256ad9a2dfe68e044c28d80721dcab0a0410570204bb849d12f5796e5bfe4b826e3c0bbb8210fb8dcfe1ad09a77969ca81e43525c5e9de8126cce2d34dd44dbcaf9807bd48464250ca18660161e0c2e111d0682be317670b272d2d698e6c4df1af8eb89daf6975a1710fa80a43bf38befdbb32382c28495af05e15623b6a9c404835da42f6d908d7b14a7b08a136dbdedb979f2b1b29cb9efa5aa58a7ccb839481c505ed76acbe83ca444f09cf15e2ee6139a4f56482f974ee9bdc1b72b315b31a8f8f40cc799902c93f220f30efa8cd4c550e6954e98cc93edf724a803e9b1b7c59c9f3dcd2476a5689590cb0a9e07dd0b4671d8ea129ed9f6a8ed7bc182f549b1dc87669da307c062088050dbc1feb24ef1ca535a8e0d16aabae5aaa6a92edc7151365f61b8139e3ce2e013cb588a239717d7fbef9d6aa0a46411dc3d26ea264d9e579509e45d6f7ac430e891401287e65713cd8939e85b4bb6eb292382d72e20333ef1e04feab76232b01e2b5e39c6d76cf8e678781e13cec166ee0405105174738b535d75f49b133f50aaf5ea2e08ac22474622cd7ab47d87d9ef026f3b4875f9206cdd0b4fb67e7b503ab99d29c2abd8a57d19c3b7225fa02eda9f53479188a5abc4ef7c47b17b0e20c7b8ea2ba759ed56b60a3bd77d0cabd871a0d90f5dc4687e1a91a56ba5c8aa30f9455d249122b3e9b266b251ab7d3b3560bde4ac77729eef6fdb70ab6f0f3420d4c66941021d6b0f888459af5d8a85dbd623910f8d0ec9c8d8996e4197903140a18818b582c110b1e17a1ceb342e4a042344b5ba7e3562136ea695d671578020c8677fb7b87d8fd1750429ddca808393f73fe8d01df03215de4eb0f594f92a605212e90f5ba99ceff394d935c4343014f0d25d855f53510e3043ca5a9003bca09dccd86de85e691d62a48402c6c6120f5a5cf64fce30149e569e01a68b42940053829fcb64a97a4f5b72930c8aa53c589b77a7f1a049e8ae41db16e50098e5006a3d97942750f7131ec74910bee4355e9532bac1a8f0bde476a70a2b7e6105f0656bcb519cebab51b2b34f3e48790f04c981c3424e626a9cee484acfedd42230935e1ab4d9f09860856fe1a3938f348008aa004a92a9ecace3ab54e2dae9b27026df7dbed07e7cb94a78a9c1c32eee7b54c81a80b8c3b5026d55bbf0fb561480a1de994b35ad106b178075e375cd701082883d6d27d5759fa388307562e8596059913b1c893e7f3e156b98aa3e7c5f5fd2a86465e069c36bf90db125b1198860ca3d4947fe14081d916ecb615a593ac25024aeb307eca1532536434fa1d139900e9050ed7af73b9890a34b9e7acd17cab1737085a9fde11f66b54154d62c4c709f71d041f19618482eb9baea9b500cf4d82c1bfdef1808e692d634c85c592670a8d78702b6a6fed879fbb6a6d95ec70dc4e1d3db9e47db31371b54ce682cbb90f8b364e970d343b3bb1c324a5af0a29c7ce439fd8b75bfc95c465623b5ad6c907a64734e690bb24d448353588fd9390a3af6f793aa4d9c1a2892534442cf8aa059d11f4bac838da49957a15a224626d4ed8d6a4a5d45ecb10e6ddeb9a969adf0e33be898686ad6043ae392e01a8b5bef2076064b91d998a8c20bba36e25bacb013b8dae6750a0f85bea108f5ad2ac20775cec6e45a6f5063dfc228295f2f72106efcd080aeec05dd8b026a1d9fcd673238444975d4a59331e991a85032c45e106b02dc8eddebfe9330263b407207da6a304c02a27b9e8d0f4c33f59160dc8b20b93a58e8e4d0b3b4fd661d4f97a0b10038c863a4f3377db58d575d1b0ed523a00 -generate_ring_signature 21b7918f07df71bb61eea02d6eaf44427254d6929fed711b69702a07f2581ee1 2170c653c773adf0ca992a320751335723a37f418473b51e05f39f4c56ca0158 198 a7310ff48dae857eff6a14d2feaa21e9d2002f36130b16460b6c39a4a7f9fcfa 638c6ab8292f8350eba3e282099ff5bf2157e249d6d8f4817c1710f650107663 15a1047de62574f925b50199dab771affb8f588651f52d19fd6412c40510ec84 fb40ef2ea3d9c88142c8014b364e0e0c7a3c588e5f45c8588e54450d51b426aa ca504e824c28187e327b5d7ae7199a246f73858407bcade0f3ec9b4d51678d6b acfc1fa1a602a4e8d7b40f5db21b12cd4fee3db4ad9dc873f6b2f835573ff911 a0c976e070ae6c6ac4950b098f25fd6152cce78b02f9c781500fc12714ca63a0 4bcd175516e2d4f9b189dc916c29ea08625a10439ea0a81ba3ff909ecf188edf 8c68075275c103c3581e9e0c3b70687278dc986cdf603376d8257e4d5d95808a a27f6a62d4aa751c9240553e0a3997eb518033004ffad5ef037ee51358bc6d2c 738354933226891098ecc542f68555f2d16326e5dbb8f8c2fc91db0d93db6c11 37b94158c61cbbd44dca406bf67c8d4c13e7d0c8c7e9d6794d5d29f576c477c7 dc71ccc63377eaa777e6f591ac890132d59e63dfd9fc26d1ac5d90e995fe2bd8 a9c3655c5e63cfaff27b9b7553d34b8dcb632d8d7eb60685904c589665e02996 35b199d68a146841cc6b62ef32f7fcd470c6ba3ac20bf4bde67ab988875ca553 7e00d706b974eb2cdec2dc4de1e71773dc7c7dea234749b3dcd9cb6ceb3d68f8 515e89a78026305838e4e059b0ee9573c61017b25e92bba60f61ecfd06118880 9fdbcc0a4a7b68abb0cc94571b407ebb3300c1a37cd1d629dcfcfa8ec982afce fe328fd284ef8f8ef08babe0357c39c1afc76657b3fb3e76948c546dadb5ae55 473046fbfc71a93af79fe516e88dd2cd2e4a129346fdafeb8458a887434020be 76025b240fd55cd3f0d7618cb987353c22ee6ff017f68aadf246af80d8f53a1a a3e4ef02949475560168d74e757d636ce95390013a9f7598e5751c785a0a3558 ca46eeb8fbe1b6f71eb46039987aa3a0333b2423000e28c8ef91bbf96574b5a3 756fc67e7addf14dd110af278b6025f47b721604970da8af89988004a74f30c8 430ee30d84f2bf7dd3d73f6cc7d25970b0da0e44b346203eaaba6b87c8d1bc49 f0bf365b8ef1c4af3c1489f969def37f165f60bf90c4b1e7d1e64caac02e0d00 90d8d60b866aff84be78562d69efb7c75ef8ad43a6dbf8180c7f3bfa55385f42 81fae7a46b3206690ba6592ec7ea31908b6b7426eafcdf4b72a7d867db80c290 47dd69f8405178eaaeeb253b81d9854ca3a5cf4dee853c9f09e5c018a888a990 3dbd9c96886f5ef5ea553af02f558c12699a62aef89f0959d36c11b9613edb5a b6e92ea527b2d00198bf9d08c2349346bb9d2e52f9a58f6f21886762a8bee77c 5137c2a7ef939c6dd71c516956c0bad82ecce452fbd92d80ad2f893d5db044bb 83b98b57a098b4606091163dd68af52900d995955054bfbf8dc5be2e285e67da a34e7a7bd0709f83d3e8edf3f4703e8e78f5a8328b8b537001ccd78a1fea0099 04bb7b526f22df2a7fdd7dd6d96a996dfc840d3c52e51407e6e02fb48653c17b f85f3534c07f3ede1fe71fa8ae9c41a7a6a8ca0114807f27c3a648e67d010c0d 30772180f96ce761ddb6bba60e078ad2697edb3b6368fd6b5532cb556a14a927 246288f7cfa451ceed0911a552bb87eec77673a9ea63868c95fa1a5cd2595d28 5ed823adf2b16c339daf9a63307143086bbd5d9bd48ad7884e12342177b93873 98d730c7b3ecf9a20d36270912edfb78e51f7d57783caa5f0fb73aca4a98faac c9b1c8b87c927d1ff20e8e11be50ac120ea712d56c79bbd2b0b4a7cdc380f0e6 e016f3e3bca138e242edf9b041cc9fe41ebbd76758fd4648b617c8566227d19d b4785c29d4cf5ec8136a91d82b37f00d32cd9f5c0cc4ed9f98d89e9e12321501 d7530c1336052f7fbad4f88f42f7b93a70d824ffedfc0c677b021ba884f54a2b 8a2b6f62da42c1c2345040a426a328224b6e1dde8046031bc38aa198fc946495 8ab5343f36337e7292f19f4f0cf0ed20f7129cb685d46960181ef8ddca615f6c eb77146a3a92895571947e4624b52f76349eea5415a1f0b64cafe44a1d86d427 144403c29b2301fd621b2192d294770c43271c4b1a65aa8bed9820928939f9e4 6fb15a7b933b936a2b00a1c574f114c8f1fb55109c0db8fbb1f6aa0cedd24411 5c098c6ddcc9775715a8712cc941dc760043b1be592cc1e794ae2df2674bd12e 3d3aef339088b60d7de300b385eb5740bd7c45dab071724717e85d10dfac35d0 1f965c8bf7cf38446d5cbbca496b9f4e1316598c9714ba751abd6279ba119fbf b50c8380cee5ab2db21d19d3790fb04dab6abc77ff660d9249ba511823270917 50f3f18353606ecf073b404fa9fd25dd89081fb2558fa739fac549332d81f426 b317387602d238b8f8e60dd59cc63418f3c911bf08e27e743802a6056d7dbe6b a67b3f52133c365193b3d0b07a770ac1a9ae2f968357f405ec0c5dc764d9e89d 51fb034fc77c16548c523577fb83026394dffcda641352e07f261046aedc29f4 cda39cdbcdee442b798ac1c3eca2c9fd9029387c5b9d6e4931ea007c69c1438b 5eabf6be3369f04af85cc3d9ea07eb7d36d5e8c917bb4ac82f65f783087fbef3 b93813588e0e1c30066efbaeaa1305afd7f3bd335fce47e11eba8613c2332277 2ab4bef429a6b5516c179036065c2f051e75cd0d39f5be376db50fbe7d7b524c 4ba8c45569fb7f9633d85db9c3e614fee637bc57f7d8366cdf43384b1c07d5ce 1c6be33f9df30233ee408d93647939aec0a74010acdcb1aadcc828378bc2ba7a 3a5440df19aa23f49469bb5a49f03e94dc8e1518f9acfc64d2992a424c3ecaae 9e251605352bc394ae6cbc7075e8d83fd2c7b8de90c327a3c3682e1b146fe87a 806ad4707c67355f8cef4711357215018aaa16178497d0b7870c27d8319772d8 f6ef4a8771330a3b101dcda998edd72efb655dc5a061dffa72f20fccce62a05f 458caee8a3eb73594db714221608f3ec2e8307b7bfe4ae6076a695ecb329c105 430bf3feb7d8c15d59db56c928803fcc586b1388a9f55864c9509af0263b1583 3c481cab8ee77c6c9182c23a0813c673b5a79f9e39ba968911926127b90fecde 354c79b857a63799189c3fd2ed192c9c5ad45649389191442c4d5d3d653430dc 06f2fd30509dcdbeb9f1b1dadf07a2c1a0f07f0c09ed89eed7aea5d177ec4293 185158f86c6ae379c94c02a972d6a2b7b509611c01fd464e42d1f4b6108312cf dc9c395819a1a1a4d441c34f826100fa164d746dec8e4ec67e2957cdb66bf496 3b2180d54f65060b21d0e3908eb9e61d51d401c3dc6ba7f9a6b6601ae9fc25da 1dfd4f86dab80474c115ced9f14e9654b8c0bfe960d4783ea749a04af99b329d 2836b7ec30ceff00da114f97fb42827adae4f851c960a82f3afc7649b15f9af0 e2f4901c3f23a57de9bb273e7c475a6e95cd151b0f124913ff8793a54e86b00d 3dd28896b87d391d35d51a898a534d20f08d7551e7b6e94bf1620e35016a8d56 29dc089a27b31456ac0015c122b2f01fd3c2df6a7198068ade70e56790b5bfe2 5f9f159b1955da1e199020a276d8775f5ddd405986545bfaa6d760be0b4f43d2 ddf00a1730b611dcf862d320af05aa81bb4f514d36c7debb5ba42e098a1afcc9 68e9c66c54501f39a8a15ae6ae4264acbab0b5d80de355e451d5290baae5c5a3 7b408eb753d2fcaff19e4660d42d3bdd8ef59e2064b85432b324090d59131996 6b0a02f9766c59032201c2c5b04453741921cd65d5150740d99155d2dca6e647 5c06dd72b563394a34e43ac353e54551486d2be717327ec3907e4eecf84f389d 416ac45ccdbcd8b039df9243151e7b150d9c8d5ceb663049bddf4fdc5b13d35c eea9d96242a44976de1526661b40a94932999919479b04d5c542b354f7fca5b5 2d3473d34a84358e2088f6aa6d9fc1035e3bc513ea613fd6604589f0befc56cf 33f7f9c42a7a1f400f64885a3b8f754f7a37cd240568ed89eb4b3bcfcf627adf b10bf05f99f3580191561caf04194fcdeb7b2354aba272159f16dde7688a458d a191c822cd757e136bf17d7b3255d2fabd55b92fa07c3fd2e7769290ccf759d1 6dccd76d0adc94bdc5a3ef4530edb326e205dacf527efb8f46c7be4e21ed9a0d 6f6c9c24f0a9dfc75ba05a829af930df9c90641e35647ac8d9dfe3bf162e345f 4bf557d5904b29c5ebfd6e8bd11eaa8c1ab125a5617c0e26d999afd1da4c69bf c5e1cb8996e6e9c445f5272b25f89ef9f89be61bdf71688f066a8156701b3c14 70e3172770643e04ec34ac004259f8d2219259abd222f89650f41861d47b1fe9 e6be521972ea378c4cf5c41d0776217078f891f04f630497c98e9e4cdcf0eee9 5bf7784a3925c89933199fea56841277e029bdb8e4dfe7ac78b8467d8f84c97f 70f5ad88720513a888301c9bd51a0d5dbe12de43df5d52293153547de0d4f8fc a62e3849fe1b727cf71319308e67d346bb3fc735e27152893b63ee238d0af39a 241c0ba2326a2cb22561110bfb366b7e6a6eadafea230a61dcfd4a9f6b4dcba6 568c41fd4e61caac83dd975631219405341201cc7afa1abc9853ae67a0a80713 b50eadeb0d534b9d1d089862655f4fb15c60763edc542dbe8b55bcded4e16027 f96b13a63ba656428ec73c7d5f6b22a5cbaaf54426b49252428af975333aa980 087e4e0d721080d22ae9b7163c846daa8f5b589a6691e8963c5da8025f9624a2 e24e5da5e60393b9553fc0a0b7a519fce15c3909ed4d79b1204a67dcde2e4569 8892499bdfe206daa5cd2355d77651010f3d4bd3dba9d9f031bff0754c270479 decfbffe3e059ea424c13a18e0825f19128bf74d3bb8bf0ea9f16c77e2ad2e83 cdd209bf4caeeb585551e50944ec07a319f3dffd5b09a012d18f5f96468b52d4 a85025abaeb2656c57b586cc1b592d49b01b6041f84b7c76d74de7ff226361f3 4698f35cd4064410373adcf01d1a5cc9975401fdd593451d29c8fa8685284791 776ad642d6cd0f9c3272ab6cc24064c5ce287d0c4c0c970bf796249515244965 815a7d461b39d605d0cf09624a01741b100d7d8fe7f5a43be593ac631e5f1ad6 3e06f180ec6b34f02d9fb05ad6b1e18f61c86b30ff481ddc5998f454d1e66557 053342a00d7f7e7d63094f10f2db6aeea8bc2a4604bcf0780b06f670780f5fc9 0e0b9d2d83b917845a3f5e73a04137a499d9e6fa8b867ab98bfa82b5fd76ddd7 8a7478a0b93dcc275f706f458a0f3f7022ac8812b1a0b3fb59a17ff33887a926 2aa41062284cb512431c3da7a24fd4dfca3b3b9d4746e9c281f0a6530c77bdb6 d2aa71095261507fdf7ff02a66ec2f810fb4cf25a1cc061f2fd9e6cd991d29d8 749d7d4fb454e0441786b0b83405adc7521b9133be1e9069e98b0b4a0a019742 9402fb817cb1bdf0ec3b3ea7f0e6de5af7ba40e5dc449a4604ffbddeca3d4bc6 7fb5ad8c1c39dc05b6b9f5683b0bfe3453a36ccffab3d7dfe8b0b24c9affd6eb 1d5beb87c516b2f164cf9b133359af4170f80919ec18b0c32130ac1b72384813 d7a29f1eb4fbf3d5e59c92fc82de7b21ae3dd5592fe5bf14ca947cb07f91f294 7c4414a285d08785d7ea218d851629f3ea64cde0db5f122a7d1234f2846679c1 da461281fb75f952c2d820e634628c9b7ad8bc85b2652066514dbd5081a8f001 24ed659f872fe2ab6ee3ad8e503aebee8871399ef6e8173a9a93f3c927c9a006 302b8bb71116213bb79816efe7111d60102a43e2553085ac726b3e9de9ebca63 ebf8a047c74fce459c1cfb3a267c973f22be621e82ddbdbf5c0fb8e94d8dedd0 82ff33c38beeae7ebc65ea166ca06e0838209719d9f68574bb0403e7a07951c9 856688e811d72ab66cf00280841d83d21d9a5982f971ca1b1406e5c205ccbeff 9314feb63caa7c71cc0c2e1957cd334732875c8da47356dae4982c32eabc902c ec90e690723155d6a5ba149f7070c142f367020035f3c9f7fe394f4c67ff5bcc 222caed12c17c95bacec54ca61a7eb3e37710521dd268815f025c082fa8249df 532fe8d1a928b1715dfc99a1e2fbc51fe9dc599badb35c31bbcbaeb53377253d d41e747309374c7b1d87c86affee4d0747b7a1d9fd1d127b54891d896008c6c1 89170b10570cdb10d9e191a8a73cd46f8b9698db908daf7fb1dc9c7ea34e2c92 4c7c8409f431e936708106858f52c7c54b59bbf7485f66533ca079bc93128903 e2e9f74f6d1ab74bcb1c276143e6bacc3656fa372ae0c55d86365d4bf87f387a 71370d72ac3428b928fb2eb392b7f9b08b1e332c5571b720b1062e60600d4566 3fd75f265802ca0b4e7dc1b45f2248cda782bcc3b60571b72ef62b3980fe4801 094c60456ae08e383c95c2dcf3bc2e3c067762548d57b89bb7bfff28ea5de068 af19c103bb8c17788e90adeeab90d5744cf8f7272b83c51dd1c5076e9da6568f c51e9883759ff945e2072a319879dd1940f8298b2752fdc99c3eab5162a9b9be bea441eae3c9b9554bbdd4f797920a478705209d2c837dfe6a43f76df9102375 68ca55b4f18a7ce36e32f68f31d6e55e0f6056eafe2066d1f4f10a1d36e4aa61 746d492d44cdee213b7b1ba63f380d3582cc84b187c115f13489cda5fa7e56ef 89407326a649e5a0904d2f02dd4e488f88a020c40a9f91671fd3f7c2212f00c8 a28169cb023c0f991bb0035546a78d954d0cee7235bd52bcf88a5df99b557f56 19c17f8474d5daf47659a9864cf1af09a594663270eca53da879650400469a92 10ffea22bad2190a153341c2b0d21cb3a4f907b8a7e926ab8d0c41382e4b8058 5e0f853d144bd9e6f460d06a4a3a39f150448b88835b4532c41b2587fd4c0af7 31754c5684b404654bca97ea38f2c00ad3e5f4ffdb97fbc8668ec58694724d82 b32e6d9773921282689cc369c0312f5a0451e66ea941e6448c98f8e981d48acf b147c1c3510eeb037c72cb71dc37425e963685f84f32a50cc01fd408d0bf4d20 57d2c9657c3e9a7296bb505297e55796b77f5d3db2f4fb1f09d23771ac62f398 b25cf9566236c3997d4d997f3d5670f676c13965d4a4a66fdf6900fc4883618f b7b93b8daffc9d5a4e47f4757a70e21a66df2f452bef667140299482f3173478 7098f7acbb510ee3f9c0499b2395d96f852d21376186f275f02cd7b2d87faff3 8c6ece212cade6da775e5f059b0efec5bb6136903d3e5ce07edb1ae45854b6bc 94887bf7a0fd4b7fd0d2da3bd78c13923ba3416a1e4e84c90aec94b860541a56 176b865ea64c0020c7e8371ffee45df70ee0f2bea422735c30201ee2aa31771b 45b58bb64bac42231f7f98469abbb0ef075568d99de4d3ebe2a480fb52cc6c95 10fdf36454f77b8909acf5478166555bcb2474be93a5cfe6d4c882c05e08d3de 4b0d03f74f8a5dadc9ac19dd2b0811f5b73b4dc60972dc052a656803510b8e86 c275c94455f1a680592271bbc61593c4dfbb38fbcad68743c1500cacfb542d03 bbde1fe13a989e8ae0ccb8260d4c1f3330a337dec7cd5c20dee2ad781610329f 50c2ae0be35cad3b9f25102f68b7e69310e1829d36ff52d23a7a000b31caef02 35bb8d2683e7e25d64547774b2c9e8553c295c367129a53cd2ed7447393358da f8e1f760cc5b69685e8d68d6d023fd5760790bed603f69b3148fb4d245d07e29 ea4174e4e5a6844c93f511af95d507c45c939ceaee14b0a033f2c93fe8f5a040 4f117a7382d9d5c50861b62a8ec5e5905ffa6633ec41b00bd61d0ffee78dd05a a88c98a8ef1d64f1395a7029525d0de4b131db3cda25b1a401c723c64cb5e357 617280cb8f8e0e0f42c62c53c732e87ca4fa192b578c1120e40905df9e8d8194 c409b94d1cab6ccadb8460b3d131cc18becb84159897e15edd646ec4dd4fdb9b 2e42617d8e1bea79f0f399443fbd5f15947ae5e52abe17726ddb03ed0d256d86 6a73186410df4cd8670032cbfb4b62b0b7f95ba4d2c3bad16d5a053f71515852 7205bdadd2305aea4b0082ec7bc8a2a8856edee2560e02741a775f7a0ed2e1b2 cc7ba0caffb42807788c1eb7944ab97f8fe62b73c41300131853c968347864f2 78d4acabd2f716af0d52789f27bf35ac8bfe3b95ebdf90437010ef89324fe1e2 98198945989839786c18edf339f538c065e83985d97dd7eabec1baddef389457 603d891e289f2b8ca96b43ad5c54d284beea789a4ae319517833723feb4ea9d5 8eec45e1c95eb6a99c6223b40f6b9e740709941c848df5ee5c4a1b23f100e68c 948afeeaf126f4fe582998b6cf014b9ce21b3a7e0cd439f40be5384f5c7ec905 2702a8ef3481001ff530a56006930329e095a1f73543b515159a0412d53303cd 1d0c05dcbc95d9a736871d7c12f9bf6b0455de0c6d19a17f90680a39e974b96c c92cbe487bb69a8bfd16a8fd9b4f2c272f564208f1f6a39694ef3a72b7f1c236 5d8db733373e9343d771cc78b6f7fa5b5fac0e5b7b55ef6115c7611fca121150 ff9701d74d4540e1b6494044cb26d0d1edc2c6df60c5f646753b256ef187fcf8 c414793da4b592458d92c8116978ae7a5d3bfaf0adf1a0799427907987098949 83184b7d1d49adaccd9662c4004306d458a42d88d16088ee50ec8d82c9d23256 35905e97de54db871c52e900b7b28c9524050c8508f547ca355122781dfb8dda a177e03fee74823cd5498a30bb30defbf7fcb04a77c7a03ea9a53f166196138a c589143a5a14b61399ac8303294231661f6871f01fb323b645415f9a6f854e54 223d256da69a41c4391235895d0afc14513ad9b8bbfa6c19475a07287bd591dc 6da1397c2980f41a9802a535ec35e3c605cc0af558a2c08a44435c086491c85d 2570acf82514e472c79a88e3baaf0f070386b8e68f783292237d920b3155de1c 59d4fd0553f2577e6817728152a7c6dc652fe69f78bdb2a95feaaeb37e8dda0d 65 8619ccdc28e2c6ad1d78acc92278d57a8f67b2f17243c989d806ffe59d470e0154bef575da6bc9213fc861f00b0dbc60cc124632454f326ebb0edbf5b6527705e9e8fa3faf0ea5fdd4643b19b8a4191645b2b36b254157e273c9f2d34112740e751449ad399729c427232f19bbad4b21080ee37f7812bd2bbb174aefa587aa049a397458ace132f31682b42b50678a800f038266f590468358708702607c8c0b9dc74668e4adceb9365329eb3124df574a7301f380d1465f20129aff946dc40ff8f798a70db172f131d99059aaf02f41665e4f254c9118fc038cd5b8092c6300a821b6e253d4eee95aa27c4253e930280c4bf9bbf75bd99837ee057acc859708a9d71940c311eac800ea335c5d310e2e8a19596ecfe59a7d3531cdece333d000462c667537566ce1ded1c0dd80c6a70cbebb9f02927fec35f316d703f72e8c0fd74b3d4a98e56edfca97de5297c078d66cb9668fca12fbf03423a81cdb3a300d7b61e9559f2e94c329160fd948a5b7204b45355aa6569a3e233fa11a82d0dc0b559b57d4855cdadd13898e09753bb96f57404868dccaa0633f4b3e301c7a2b04147407cad47b749acddbc47cf5d3f307baf60b61212ddefe25e0edcff45996035726b23470e2034dfd16d66d94afad189c770462be9c376310e5eb0225248b0c24ff29dcec252b9843c1cf114a648a9231aa00d5aef14a030ce316d49bf03c05387d203e7e5d9494624da459fee468acb9b7934ae0085370637fe52b7ab9460b14cd0d520dafd6bc2deac6b6f1c13cf413ab5db88f89c2a8b4ea9e1a93aab70affc11fdee8abc3089ee6e1884ceef07750e84e8db2248cf102310de1eb1fb90529ef9d91a7d49a0b6f0f302f37ce9c90ba0b3262616eeeb07ee2e139363d560346f3cefb3fef6c230d941e02b0bd2946ef33739d306eb474698204084a9df50d15e15605c3ae43960c8855a435b50bab454eb029141dae3f0eda3948c0a17d064a12b1f40476ac9010c208006f2a8d795d4a595575fef8a7257163312956bd0a7adfc45a48f4146771713cf7c02385bb4d46398a269b6818be8e391e2b4bd20134cb5f46d5e77a9405a6cd8d9f9b5c0a118ea14284e54e45f4874755de3b62045e2eb67c18934e466ebb7e9fc3fd7eae3e12777e4d7cc88f0daf5fa4bed48b0a80d6fde30f428409f0ac45f6da42eea8a92704cf023f81180442d199d7112c0c1631d4ea6dff7a25fc2bb7e20fcb489655987c6a11f17843e971057f40f7c106fb406ebc6cbaa4b0c89ec9aadd5464d75b61b7b9747fbba7783cab8c352dbc04c11cebcc22b9cd0b8c78b48fdc1acbbcfde6fa95844d20c376c9951936b7b1057c4414feb1b11c8e6c202a73bd927fda047873872a0c8da681d88c71021101026cf7e33c1ff022ec9b564780327eea91519e662a3340c5ad3162a372ab528a04c8638338996fc1a3362c7f05c4cf1a6f74a5fa61a4f2a3dc0a3306160387cb08ccc82274c00a0b42f99b9b1d111a5f8561b217ba8dbff6abcc1f1cd33015c607c32c5abf3f9d1c3ebb6f31dd68ba054fd550511e909124a2207c601168fd2809db97499c12bd13a71460b334ea392d563d1d80226a003e6e945ba6cce2a5370da0026e4e14a612b7285fa13b8a5852022a9faebf32f41acfecd049e19d0e7709671bcb9b962392b13c2e3ec8a2828cb0dbb1abe6b4ccf15c1aa97dd85fe86600626e03b74ba14ddf3045c3d94535784e48f7e20711b6b3cb5af8616bfb65f202f1bb7fc50dd4f26a16444647726e888fc7171405e08b2fdcb54878ddaaf1d800408064d928a3750185c1fedfd6b10a1975bf367cfbebe3029328c3201e3c6001ac793dfebbd53e9633d213f3f5ba00ec363bde58c60579047ce155233c147503648a46c96c253b0c250830b48374b9116fdb2375d6eec013f6649f3c22f33a0ad452c0a066fb8129ebe3e2299907fea24be3aba9f9d6bc743c6a08d92aa53800b54774478c747793eb01de09e64d97cce9f5a4614e2e27c7be4a57e478f1010f0b22061f85a6e65424d788bd560f0545de3a3fcb531ed19973fb401b8411d0089ac008d4d1a241779c7ef6568998815c55771fcab927d1b98cd9efca0ec399047a4c32e548d8a412dbd7f5a7b9e4f53cd645dbdaa5671652075211672a6ecb0d12ef177b2bf9013d34de12d92b8e1bda88905b83c8a45bebfb4d3e257135530349153fcdf84bbda1cbbdd403a0bdd9b3a33bec2ee9218c929cf691a89ecf5c0837ab939d7fcd31166cf83c90b2a677deb9c95e32814f74862fed3f0da8d77c0a0073ecce0431b0bb1158474ebb47f9fd237b3c45c1c63427f65cd3d6aee0f6075965df8f4ff7d2261b767e848a92bff7a0b5477a8cafd81bf91f941b9790560c6762a4db9a3805662864cd9c434780f239532f963dcf037e8c7fc5dd90a8c40872a9d160cc02d3aa8cc5ee51e55cc7251bb7c16d26efcbde48250ac7a6025708ebae57af842db5e3f30490bcf3054b5bf29765275d36ebfa6ec14e6692ca7b08e79658911350f679a4ff16653c3a7653a6f6b996d75a31d39c9e3d8fee15ac05881b0d067849c1381ae8a90024690ffcf8d8d36159c89caa2075b28e6cec550f75f0d56f322fc053f167b7d5de29867ae55b39f500e3127dd5eabc414b788800d7a4869f8548a77c68403609874d7ea599f16a04c9af7d1bce9e9884a27c8e08de49b964af7acbcf4b6a64ed4d6732d706c773d49ba6d15d15dbbea0a1e1f107e4ad91686cfde00e1406a5727d392e39b0528a3d9cc8afe25c55019b648f1504675f5c655f3b0d5bd7fc0de79daae393941f7e3d6621936b38d75802665153095b9e2dcd8c5e495311516b6e9a29c68af47687f1e2fcfb0e7dcc3118c0ffc20b4f0030e725b3c797ea9ff31dc2312bdc841bfddae3a358081df509e35e32b7038a41c1d2a015a7479de99e7575eb1ac25d09495f3b2962679d897c6faa113d01f8bc4c637577d93105e09d07843577d77400b049caf01ab348b70df2534aa50032fe7fdc815ececc6055c8d665b89acaed8186f8c728000a6fc4a068e9d2d2018bc2edf6bcec75f602c7b1867dc4a44d86843da1e88ee5ac82fe8e646bd5fe03cb14e2075ae8c1ff0667aa25ed66d586538c9a2cc0c05e4a5cada5949fac0405f9770e5bd48b9df949c2dcb334fca76358b899b27aad42902d16368b2775f405ccd6a893b9219967feb9e6f78b65cdbeba2ef33eeb1850fb1e8c874331b5060394d7bd816e57bfe6d425c78009ad38d5959eba0907f4f623414f48a64ed29a0b3150dab4744e50b68deeddadbcf0d5d6a3f19357b71713795b9db801f9063409a5b9bd2889051ac8082c8406c1f050a3f7a876c32dfb3d8edee7496eeb470c038c544b91224a3e2278092d54eba976eecd43668a24424e6309c9d5766910f80a3a714c000349003201a98290cb27478a1cc3b0317ac491a77608e0d7d3aa9f0b3cd418e7723de85fbbf3047595abb95edda645fc9f8d5f524756a25ae92f65054b0c77e21df51b08ea79521bcb9125ca1d4e509e04a0bdf44ac57c9438b834069d6b058e49fd85809a264f917fa25bf18c42bd6e95f7b33f0e83667178d7c0035a31b535e410a4a8fc1c46ef3b9a8ef06cc8e0e4aeb18aad6fe199e9dea04c0b482d778577827c300e7f03ce6a94ea91e6b41f3170a6925d5b67912a483e4b0797b7224679b8eb9046a594b0b19eff6fb0ecc68ee65d4f1ddbeb99fc0fe9430bb8ad16cf8b5044a0c27f41dd400b4a04acea2a2ffcadc5d99fbdae288ae3470c75c8da1a399872cbd1cdc12d464f7665d99fbd1be64c35d16d029ae0a15ea0007966aef16ed991c5d4a42b3b18932d43fc3ccb35f6a1ba3ef1d41c0603ac350cd33241cbb9ee8d02517b23fcf0cddab42676e7a321107287133afaab9a5d820cc6da5fe00f2eaa6888df02005d1534855c27d061b098b233fb46ea3e08e9530df53acc8397c577edfa2d270052fed476c5d822a112b6c18c2da94b11fb74e40b0fe0f9e2cf2209606d85299d00961e68688ae637d73a5323774282abef3bae021655638e7e794ce2791257b7621426e23eda15900a51cf4a2b2ff06d1b03ab016887196f2924918fc7ac7d85d355ccdee64ccd37efc65f61fe08b95afa6ea707cc12cf4b2007a589d0a9cb0098956f6e773c534e5cdf10fc0bf595e315e0a10023cbed13710de59ab19d0709682e0a28b204ecd3f0e993491b42ace027dca90b03a61c06b3683280e8e3a6a59d45aaf3743fa0fc480ce505a0c1f8f750a51a0bb4fe3845c35c2c79e158125123f4eb6d062763aea26b5da6797b29147d82c90cc7a8384a2beb58f3909b191ca5cda1f90f23b9452a6c59ca88f28b9512e6db0833ad81ba4c035d1944373aa7e845b94ce5950f688060422422812a8584c15b02f6469a4314f8c65fb35748832a4607ff723cec81cf00483bbf6255d706dc8d0b1c4d2e41b5cc7b5f11dc642ba4b1b089726d61b5e2fd2d20fe6e19b9aeed7d03f0d5c389041985e7a55f5279d0db38950831517df9d963d1423b84b7ef2edc0865c008f1ea007294666a132ba012ccbec1bacb30aaf7167d9894cdde49541d06bd257308c8ee2ecf9b40f66892cca437886328e33ea0501d2ae4bd9fa8255a0ea68b13d1548020eb4a96a265fe2b0ada77f2c45c8e31f4d8d02c73e168ba510f8e9a7664f9b51a53a3f4719c702fb114118a77a886a18755cf650b74f510780dc7106e4c7b7796b6965b1b6b070f7570fe673fe5dd550c6054d42326154aa9051a6d458e3fd0bf430de5661e8759aee5f40398d3b2d04fbd767d36ef544e950979562bfab1663605125b24cbc31847b5f1ca6ce2dc1b841d170bb331da3e41018d341439f63deea85e184f2074dce5c7ac98ea6429a6088ea88a423cfb731405955b752f27f57a68beaf0e49f7845cf5be6802b2ad8d736652f8dd5240a8950223f25bb109f8cc9f0571ddd95afd80b693c08ea4967583430fbf49409df5ab00b6092f8d11774439830a1592c34fc1219bd3f146af29ed45838f4e9ce60b7508fdf12ea11f8759ae7d496e9294189ea5454407834a14765be3b879d5cfab880e51b97a28f8c03ac304e1c047b6cceb4b043f39204d85c16b62d9de496806ff0f3e64ca2a09768da9c8d87c1a48f6734929de357ac5443882b45f9e8a0c6b2805e8583bffbde9e414ec5c8828942f8a250348abc75b7486c0799f6f7cae46e10cedb4db291dc472948c5fc4dda302071395bfaeb0d9b835a8c93057b518ae240be119af0d5b12b0fb832e155a04292c3edd4cda39c3378d6a6de9d1f18506ba00951a0f872c11f979255978ca843314548a40c265df2da63a110b2b9453886807ee1ce3b5587cefd18b73ae783002cd32ce04f6190b61ce0a246fc45b3c875602258f3f709de654cfeba37d15464368959020480aa4801d5d4a954c7916ce890060393b1549c5dcbb22506a2f1543138d18358f56f89aa45c083c4ad2594c4b054825506b4a7600ace9b95e53fc6062b2ca26272f8186dec23d33b2ad49144a0763a155a15cb6b30b5db2baeb241ff372a3680eed3e18a74bd7037e588292450fc7581de41966fe04ac299fd6e165338cc84e99ef5eb2d3a922aa4a15fe5a0d0c8c2f6a9c9c66e8b56eabf5e59273751a4dcd3994c1f6a9d8c2b4cfa00fd70002b8c631a4b1067e3aa48a3be7386652d6c93b0b9c853e74622d0a85f4aeefbc013d43c6d2c986c6346c2d0630a3ecc57c3e6605bd405dd20971ea15bae56e3c00ea3660f570d1752cc93cdd6c363233eab0a08b39d866ac6915160e955dfe570d8c6c1570bc35f55e28f62f65be59697b21fa3ebee111d7ef89230a4e71de7b0da7bbb30bff9e204acd0e6167b325099efbd85abf1f5d24def8d41e261c3c7f0b626a6f7f2508322f74a53733d6617f44a01de0f5502770d50e2d67d9562ca90a6e603b933cc04dbb66ff167c73ba11c4e325796ca86b6963e46ee5f44d2af40c72ab07623694e5c89ba23f1b35c3c4ac3c75548e1937f0f8849cf387fef0b409082cebd4edd726121be4a0c143e6c15a67f5e12ed65a807074f89aef087df00972692dc609a25c25ec1dff2205d1ea29ffcc023c7f48d26c0fea90c343a69f09f60e62f272d0f250b7b54f437fc958a1a1dc5a17b4fda42389a8de1aaa8e3f093713d8d876169a96de91d5bcce65245dbab31bb28d1dafdd3e23aa0288a55608e03791dbded1afd0a6aa4da0c2325f0a9aa2c2596ac27ea93119be3e7969140c03613754b08717fd3396815370e51f7391c5c7d080ebb910c12b6042a54f5909879d5ec494e4bc4a5b05398036b4b5f18502b27a14f4284b4cb61d380e2ae5075171d9394087c2eb4dc8b661a9307213acc391d81d624c154bd318fc910c6f0fb3307a50ff853123da75c9b4a1b4dec32cbd0de838fa160a9710ae3410cdb909e22182738123b078cfdfd1e1bd8eaf644658aee061ab568dfb5976449d87e10dff356bf6603976870a325e19781ef9f50730bfb51f2a75b7e9f4fc6d32560602cdb294f9b3b75f59aefbcf291050c11984c3d771ebde6a2e43b963408dbf720b4b0e91b623f0e5313babc2afbe23bdf8859d10adc00cf9f603d09998fcfa61080dbb860e66ac12b00e5310d28dae46b0ce7ac9ccda376c846870038b0f6f6201d7247ca3a707f2454ce652d7cb063a2c7e90acefa22ba4ace0c65acb89942f0d50f27e1e816eefff571c553d884bd1253e4bdd7f2e37c3d13bef47498264f0040408146405617b176719968e1170d301f28506b1978a1504b46d456a2407cd0dd6bdc96730b8ec017a7d4f6f82d55843d53821064a2819d29d2e92390f56120f987d2469caeb61bbebba56ca01efc2f6793e5da5fecebf3efaa2ea11575e2a0dc6bcd5c56a89c7e5d27776c03ecd85b941d93b0a7305b075f245a0080e70950c38c2cc6c45880dc5248fc782337bc42050d574d1a06a7a7fccce5116067da00feb64ddb8b2feee90a8e86837f074f3002c9ce46961fb8f612ee9cbc1d174300f6e3ac8469a53dd1fa5415796b77fab1560322eb4ae4e3a8106d2a850a8d33606937b62904d2b9062dd6eb0c33849de483afdf44231d33fd3ccf99d5980c1320704a5f76c98af11cf0e511969ab427a46862ae0f11f81161b3e2f907c3d617807efbc8e302fabbbaa4a0ea144b9d1a6fd82fab540d50273031bafd0a91424e008725ce7614bebea99bca36df951f2b0aac4bba241a455a4ab67ab1ac34c43df0ff6f959fb16e85e96aa007c1cae47ada270e4e2f75c0ce67ade4711b0fb8e0801ef88aa18f3e93e2db9bb83f37ab0bcc501a4198bf621e0552d322fdde50be3044b738bf708f222ccd15ebcfa958a7c37e0c42ac868ebb63f02f17f73ac0eca0e3f53d58ebc2f9a53b525648ee5b530e85822c46f45d42c8691ce74e28ed74201e42ac54558906c736f171d29ae2e8daf214d99aaebbfb07c2cc989fa6743100bcb5694ce121d8ec922db8bf98ed386854239e9c9c1d47bf3f57361363701b80bc1e2ef1b6ac58376bae767bde780898b42b12e92941ff9d15e30d28653af42086267f504bc795caaa946744f357061fadd0bcd6309562e26716560c7af2ab30816b8fb2c166aa2b5e62fa63c3b86966bc8c5668a681183621e5420b962589d062b448e3c1af43e20d2801a043417980a333734d0724bc34732f55be216373b0d20914859f22d99f7649ae5d4f74033d1918feb9b4f195789a3976803f1450e08c3439952413fdae92345a1245c598d29c098d1e73ca1432c775d966b5f82e50c300b503f9e85f354659034a2c2084f8bfd2df1467363d92de86507f5b03ed20637b8d97ed228fa49540c73319e577a3a4dbcb7308e5a6bce3de199ea088d160e467df57311278e27b0365fad5d715f975eb4a8d726cd28dbfed324a97e90ef0bb182ab8f03b6208a475f039ecb161218272c9c0842cfacd93a247c9a7c02fa0490a09fcc70e019be229aca0605af8d1ef594c3885b224dba3dd8813df2e07c0894ca783dbc2d65c8197910cf6ba8d51389dc6f5216eb96682eb935f7a26c5f084647dce628d3e98854e1f469760f0789749d1cd880f922f368ff28617a79e10fda7e049d2ede21f6c2d65bfa67a1b959df7e8bdbb3020889f9a041704e230106c36d7a491ea04dc03603a16156eaa80ef870ddc6c56e55e25b781042c087b507d32a7ddcd293c361b502b03a219f36630f2d63633bab05efdaecddc9d11c690d97cae2eda7a09f76515645d297d0870a527348d40f2a0526c3f5144a86e0f00d00a5de45c2e80c8c20da3826ce6f26cc05d4bd43642d78fd2fdac2d88ff20c0603466a40858264b68fccc45825230d3fb92407fa31255b563e2aae5da95e250a395402f0a0b5cdae20ab9fb0182fca2068cb169469ecae7ddd8e9f35cb52e10e997858c84baf694dd0e64a3e85845764cf118b3e47d757d46098867ab3c3d905fbaf67754e7be88022cde8be52fc45fd2b7e57fdd95ed51a27edd6ec9a35f10c1709122eca8dd74305fdeec2b42c7e1b811796eb55bb0419a0a973e6a58ecd0907b2895750bf9523fcfb11da42f486caf875c30f1438f5a178d7805245f77a02eab182431371e47138ef925319a53f1c00f8005ce451b110c109da51ef4503060c3c64b7082a29a9dce8c76b836100a20ef38ad60b67bf1a899e55e5627fcd09d84c37bdb751339b3951235a1501eb2c16dd4c9b9b6ed55fe12e631e90a98d03517197d9e750a34a33f8a6b7fc98b06364fca1af3330a9162dff90543e70f500f02c3c570cd00cdd196f82a8544651eb05c7b24291a01c39c7d27cdaeee73104fc1d59cb7944c5b2bfd853ff20d2bc5c1751f082c8673eb1712a67bf0b984602aaf86f745d1b235759d9fc38408c3875d8fbc8742f8131ff700db8f2846f1d0a89d95fdc6a36eb97d27fe0c4041cd9042b0506ff8896c325f42c58f4a39ea007903b8454bce3f4e634cc39ae01f5ecf7d3ae0330e9e3c91ad6280e80601f1c0fae0527dd18a0888bf05fb6635054a68147d93de570106f96bb2610e1ccfecc0da6748c9ad8083dc79bf2201aece849503015f6c426b0c3b349acb2a469424d0f905731152f2a2d171917405e87ed37d48e823ff53d03e4ab48cb3e5289afc306d34db3792a13cea3fe62f50d59da6029266eb8b63aeaedf9ebde9572a5a4da04d84d28417aa4128f8485efc4cb77943bb99dd408b11e0cb5b0c13b5b7a537b0df6e654723d31dc9865331d759c3b5a8ad8b0ea3175c3f4db121fa8e30e4803044bd283e711f19a75b5239ff019a4bc8204ece6c3578fefd9dcc54014f2a65e042e6f6a4d60eb691a86017edde3e1b2d827da7c097d36c5c5debbb52002eec604306cfc09e9bd2ea65e5007d445778762137bededafd865248016044f13369b045e8e78aca11d79bb9179f593bba08505517fc8c0c413d995ca170ada7241ae0fcb056ec90c62805059555b5d61d9701df410c7399050e04b3e04d5e04c6b3303709c963901a4ec97bcc8332f3ee7f1bd57d63f7527c138e7b6a91c4cecd5f101d272b3fe1b8e7a67f2aa07e618e260386a6e391107c9df1bbd2989f8e4941804571c477e01e4701a1fa24a4eb30015d6702819d8614933bb9dd4700f6375f40e1b925839ee72af586aa73d6e32fbec1fe09d448a14411cd5dc292b9572151509821d36edc1f2534da4d3bcb9ed3adc1e9f706c1727474d3f214a07f01b22550db5e9e90b7dc50069ed2bb578f43d3d9421588361fd9f0516cba3787360cbea0eb8f968333db3c32a9e5f3cb3a76c8ca2fe4f29a0463712620de1dcae7c10880966996e8abcc12e74b213f4dcce7cfe464ad04b2d13c2741a22bc644fc730e20d5ee18d903f99ad6e5a3b63be8aa8577fee5217882c9e37288e00e51c61740d0e4c8a4a7987da408caaa41fffc403013cdfc1dc8c20886d10decd3453e521c60a07af3ec48551a4eb3f2e205ce62130fbf2c2a33d9c70fc191410abbde079c70fa78b4c393723bf0821d161c93552c3efd44ced20819ed504afb6f1e062f6020ccb9e3ef29f2d31deb64c18df2adb3c11fd3c85580db856c8c969efb5eae98c0f192bc444c795856e7c505aece56c907540d27eb974b051139dd977eb95abec05883dd7d2d63941ea51fe96269bbd5d5b513eae06f05dfd16c87443d85166800a41156691ae0624f17753d009f617f393788c45a61269f075873c6f8397298001c0446b0e65ac06b2f1638ebe323eae67c2cceae871a7d43513f40106c1cc600991b2b540f9ba0791a62f653345b84e60d9af3035b5547339e5de94faf1e1c7048656e3c02058d27227a8bae162d58a94a1b0826105c8ce4e7fa47a63373314041bff965ed9b4865377974b56296095b8dff9d370844c83828b18f3fc3db7490c92e529529e6d1dd8dce73b6dbeaf4f3dc1a0ed214041967b263397d0025d1b0065dce22184ed29d330daaf1e2c4aeb92f26d4cd2547e49e8ea046491ffd8290994ad32ab152b6bdf786a490a5a787d8a2b7914aa4872f0dc8431fe510dfb770a6c7b96153f0734dec6ba7b33d0a96e4f4b84292790682ae8be0bcb7a3975500c4fe6225ac229ffdbabfafda099d8d74863d2193a40fde9fb085031a5c2a0560f85cbc2bb6f2965447abc910d5b2ae7bd3302c824b8aa6c60e8278b87287a23080cd8ffb18796b4ed7232f5d61b06cacd65916e802dca4e629b58e642bea251071d4cbf2a64d4e17bd50ecaf689579cec3728ac6af1c9b8c1af0af27297eff30dfe1dd9cb3a649ff36c6f435b06c75969379ba03a44c8be04d1fa34f5f719b0044437b3b01533d0047171e60b40deea816521e87dd71713fdbea62656b5d28a07793089a9f2aa5d246ec6a67bcda429333f980dca81acf675cfbb802cc2965606bc0e9ac2634848137e0b6852761d845a65e1c080ae8c902cbb3d52f769ae9a0f246f62674e15f0a4f39536213d2b9a1332cfb79a9f279fee42972630200c3d03d12343c11c1ed4e9a99bce2cb4fdc7f5c43e453f968b35450238ee85009ecf0cce1fe8bfef4e21922da07be3c1bf11e59c74ce7ad2a327c29c34494b6a212b02b8b15e885e48c15778fc14508ac006714ee9f068b0e4ca94d9c67d1f7cbd570876c9892d293668d96413fe0e532f289d6212f53fb5479c54e28a7d930be29c0c30ae890d52a52bc42689c909c2de568e454ceda568d69e829a62ba831cec280e02c7f32a223d221a7504ceedf7baf8afd54d33e5aab241cc088a6f6ba068c20d825824334318c894e5f76bbcba1ed965de24efef30ee2820fef0e875b6c78601916fc12f38e0e7b61ea0cd8e616a0bdb478781f94a7f19eb0d8ff14836eb1a0693e8dbb22f9e8a9d1ed5589d58459d37c8d4a144ba6afc5c4f6d381db86ac806e3d1e6974f9b22f564dae18a830f7fd3460ca6ef64c12e25d9a4b2c427a24c0903302905106e03ff340492459d9a110d60f1edaee07a761cb225a24243eacc0567238e3362e4c1351658c2d03829d852d92e27011c657e7a8d6762be6f19af0157a037ddd48f20ffbd4bdb98bb35c3d82f903a9b4e428a1484fe191115f2890c7f0ce4a27dd1a31ed687d789399e1205c371315a2c9fc32a42a51099065b480435b7115dfc38115e861e6cd42b0a11e1a12965f598a6d332d5720743bd455105bc886ddb9ab24a2c2423804022f8697cfefe0c4d49bc9cc6f9c254cc657ad200f22df5a306948d6dc8db7e460d8d3f4c58a6c7fa4c993b389167113a95da820cf648670dc3e8ac1db2706a22f13c5c8337e3b548f57b27fadb16a1252696870485c769cdd1dcff083b494972661b3f69ad3c093d40b9efaf40c0f420e02ac20e141ad97c2990473e015ded0c0325f364b023df9974521ddda33ac23adaf9c2044a0ca8a7c4f85e25726f239225925d8cfa19ff4b080639e171368bcd78e39d008a4e23d98b94af3d8d7d86c3dc5f2d2580a3c4d65d5b75d0f080a6f21c8a390f7c3649a4eaddb6097fed596aef580ecc5b746cb48ff059fa4b972d30dc6c18039fe01210ed4449f8b2799c7a84484f6c3ab72aaa331fb77ef6d20aebd19a6f051c19317c09f28e311b3480f5af428beeb9a5f8274fe4829166c36d1b30586008a13711cb0879a5730a750ac2357ad688625fc0ac6eb25e5388bc9e206215a5067eef2c8822160eaf6ea86ee04b44936fdbcc51a15a264e98f21578695a8ccc025bca762c35c2bba953f73efcd4b59306e004b64f570f74043d8889a6b950aa04aa7acbb7020c56def0fe9991767d6010247391023ddf9d19b3d9149412147c00d9c3defadff5936e0289b5615fb0f2e5575d11875b00395e911a2325d3a8b50150700099f6f6fce6655bbeece1988be8786a3157b48b488f8a7d213ec3267d09dc087e8f02393db3977eaaf0a8cb41417832d485a46cf1418dd99eba4f2e7f06a32c2da22fd18c58d7efde55476e207f53ab708e7ba0818902b145395fc5e90d1ce303b2ad97692b34bf025b850c4bf7695c95f3917e39183318033816d1ec0faa8e6d1ee814bba5c2f106ac18d7a5ac720f6bbc57745ea502fd6ddcbe901904c6f4d492d55422b1d939aa37f4481f178c4251622e60382d34fbc42b28892701a5fa2b3446a8cc9268e22ffa08ffe8b28bed706cbbe8d18848ed733374c3e00ae00a730ad101ba3e26ff62006157d2389fb51bad93e6ca8df9ad860f8cd35b04875a7942e67f030a94003b2b1f89a6a186d89dad03cbb69ad9c4a213c9e942032786d1cc3e27d4587da9e989818f2265be650c2c9c0493d75bd843650cd056043ab228b14401f8e14de34ea7ea22c67a22a66874950e966f593cc96996678009a6371cd3ca47dc5c8dc9a293bb94864e2190ea72cac53aefe69c49b30923f20e957eb8a89c25039bcff8e3c88b3bc1506f4b463f5e2618d02afc814aa679a60a77958a78bb1b8749898d1e6ada33a359ade49990094f80f117145e0ad7e05a028b2005e9bdb3b4af2046b9c55c5e9d50d1ce418152b83aecade4453c6555fb0dfdc9095edd62d6f5cd6798bef9a0daaaa7bc5d482b101eac0d7432bdd501bf098909a5f0d08ce4213b4cdd6e94b984a8d99d9920d07c624343aa5eb5565acb0a8a6e1992229d45ed28e01d3a174997ab83b036678475f20664f26b3e74ec1e0165301cd5959fb5e47a65f77c7e07e1070be6620fda4fd62c631a75761c24200ae87d177250d67405733e9d3985d51319b3c5c388bbea41d399caa208b7d2b20b62c9cc9681f7a6fc957f07727b873ab8902ae07be2f8a8434c4fb6e3a58d6006d3949f9ebb6b787a3b7364327bf9ef36975cb13e54ef01468f9d6026b25c3508f634d81840a616cb80d9dc4760b0f1bfd679e355941c18652f1db8412d0d4a0192a10622979b03330152746d9e1e1f0e2947433decf380d7893b99263de67309e33ddcec71f5d3b60cd371feafed4bf4c4977436946cb40ae8de1c415ead3d02e2912195a67b6dc2323b7af8d68dc6b38ba484e09f20b5862e54f4312e3ab2003ab0b118d8e91c5251c48ce461ea48845e059e37ec3d74da5df0742eabb4cb07eede7482fea99b8f7115ba538e132462f67baabb32c045c6df60acc33f144a04f1774122b913ecafe6ecb941f7645a0f9c8c2490cf5e0243b45424074bd44c0870e2406a8693fe26a3f4239d4cb96a03eecd070184f419df7a325f1920efd50848e21b0a9eb6423046538d2af0069be8383a4a7868bb88fe41ad1001d81a0a07aba556c51ce361d4ce9ef2805486f12083d3bed46a2a1697c8d079b93294ce0aa32a9ddd9fed90b13993b3467eb32a355b302ce65ddb27a2c7fc1a43828d0c0995ba9f35c26baa2a1382ddef196c88b0f5da61347fa76f726dc0bd41bfb31108dfb4b0cef03dd95605d0db16ef2659a9a75f875e82ecd12ebd37beb400fa1201c9b40660f31603dd2452965816ff34d5a688ad3345e5e599c2d5f8d2638ce10b4615d4c53f9c722c878448847825af375e6dffbb41dd6b034c784ef6303a340ad741d62841d9743a7c7ca5a9369a99e8d2af76598057ce0b86f52c200d4b6e07fc352aef26ff5df78b20b5c4d8c88c328f9a837e24438d778c2f9aca54c52b0bd02a99e4db1b1c69d052f8e866b58387b06656522d26c66450bc9616ada61e03e33ebf0ae51bba5351bab2a0216927470e07044330500597ca62254a3164490abbd69eac97dbc210646b8c9427f356a370662164523464b4df8377b069fccd0526542a947a61059c6e06aeeae3f67e86974d115e010c36033bce5077fbae5509d760976cf825131ac8977393498c26bf1f6d1494f967d3a200f1e7b24c774e0301742a0521b549345c70106df78eec3542d301a4d8b85aba0d799ea3487cc70ab2630e249286faa9a370e2e22dc06e9f591421e0b9ed9b8d2f31f1e39f1e05058487aa6ae732ca7396505d0e413840b37dd5662882f569539cbf589c2c22b008ed6ae4711606c183dfb8c2da4554eecad31e79dcd0f159443d476ff68283e605ef15df0e1cfbdb7ce7e7e448620192f9723c3e935cf618e432c843c0112aa0003518e7c7fe49c5e6f23666a3ad14db368305a7438b8f19fe8f76c19c993aa20e8adda3139e2884e426479f48fccaf4b30798223157a707db2185c402bafe960de39b3e8641f0958bf7522e2f7c5880b13bdfd957208c58937210c9821ecdbf07442766cf49e759e6a0b0cb7acf82dadd5787e850f2dff3b5ac1ba94a7e765404c04821d5546ac9019350ef9ccda1194d0b2c404e0a5110ca58db45367ce42a0a6783f1bc7248d916872b3c8cbbc7cafdbee470ca3902341ac3f3ef715b40f206a264e816aa64cd0d2ae620f4453c6d2cc9bfa7f8dcfcbcf85a519016801612071ec0cf46f0f96168c3cf05affa63fe0c35e7b8334ae9bc0a8fb979a3f8bd66033ce6b12a8f2642718513de717581b0e96fb705d33717c6e8b68d9b5298f4b4036672ccc3ea040017f47f053e6ff4eaa141e249c6b3823c109393d01ff695d0018898bc980e07fa21c4d13d1f7423496253378234d207b8df126453ecda45510ee8a9c72f3bf391ef02a1d5d22fcc2679ea15c556b2e65e353ae5ffde93c4860e3e707baf5dbcc7b7a7b90d62866ca9a5f32c57446bc6ddffa8a853dac13c9e075d6bed5611a6306a4aab3c6794eed8ebf211e626726571b4418f8d3a20841c04a7868e746afcfd209c9202493f43c9b4a1bd64ddef9ee4a32fb7a5a728d5d9058067060228680bcfc8ed2b61ddb0bb91cdd3b8f5cd983555784c70dd72fb7f0e2cc8930ab6e613a9ad39ad96a78fe487a591f17e44861e372e4aa4cfbabbb60acf6a57090e4d7920ae8b3eac3bd851b5e2eed9280711ee2dbfcdd505ff628105e215e95fa96f56479865cdf855b2c88dd519804fe1d17b6d50c6aeaaaebe050a9564a565b8c651e1fbc257519323d3ea81db8df0906f4d75d540a93a881a580cefe685b776710f5d0892fe810d05690e4602d96bfcee5f1630077ebd8d3c0b039bfa6b3e0bcbab5320b9a02f3469e4c2e85e1d8248ff47d0a45453ad0842450bb76227a4cd005089f9dc5de3446799bf6f6b595098e864284fceeae5e736ec04341ee35f04371f9ac88d6745e3a39fac3be447a4528a95a7203e7503a8d80a042849fa8be0c0b70fb18f8605d6e266a67b13571c3fcd3cf97be922e97c62250afda7d81dbdad5426de95f5a504f825ca7efbc941513224ec52075ffb35e47002b413313c358797bc3be7d1f52a28d7f5afedc885dcf8eb61cd257433be9eec08197106371052b755febe36f540f35555af99e4942e300677f8071c733ba15607f5fe58d2a0769637f0c9aab23c3b972669de8b1b87c1462c896c6d6301d50f0cddc0329ac8738dde283ea9951e989c6a7535b1aad713dab64d8f5e9d20195108fcecfa9c89b1a201ffe5218878c8540203903ed4dca085c868b79b088b1192032141fab809fa08e920a0767cad8478a3cc96f259b81397e91158f1a7f05b0d0aa3847dec955badfbb23a4a97d18d5cebcb56af68af0ea428508bb0ed1093e207a81bae5776271bc27d88ad08139c0f2d560e0808c450ae986470c9137f80330f1857d6c3331facd095111c9fe3c44314b59b9653d231b7b74bf699b343fe3b04cfe233fd697c63b84eeb2df4dee760237e1d10cdc3fe488d8833c04b3bb6570ab92ef5298bc82bf8d01b24205a15e27d487ee1501c2805f9dd9fd2d86a04d10d0159fd0ba00c339148ef6cd3cac552c3015b9e48c89ffa3e02837115b0dfbd0eb169b1c14bf56a53a2ca2a051bf9dafdaabe677c6105230bf0ad96041b67140754b2eacc0c9886b3ca369a0700bf4f3f2db789016baf7be8922129e579f3ae03077531acfb6254f9162f111301f060cab2699dba7a05ef95acf896a1af71fa069ab594a8bede80d3738e1c3aa48f682a1a4cc955672767a62f60b35e6172a501e31a066cfc40673580eb891e3a81983b2427ddfef901ae0049d7bff333e494092bfb22b821f4936460338f50402f68e475df8dbc9592fe44f1a3da49e683fe087f28033ec7c8913ffda7f4291e5e949defbf9ec734883af192124cae8573130c6d3c87c28c62b7e6fe5b0b54808e4e8a16ee60a749abb43a4baa3f2693e7c60492d1f0cd10fb27e19af3252c7d4e82c38e26a345a57befe541b771477b839204a6b73ab27ae97af8014d1cbf7cae900f63f8613883e584402191f9a7baf84a07fb5d210f2f240c2bbdf1d3ad98e518302dbeb981a724275fa084872d96de6c024e2b9c22e9db344bccfb5e3ad5825a1307738265471d98275130afb08ec6fa0cf43e224b17447304534f24af08ff0de68ab29d268bb47b81d1a543e7a1f37f022b417701a2d39fdd05446ce4761fd20e1fbf550ccdddf6d2cdfea409200dbd09e6b1058fb68bc9d2a73856256a80cb5583dded609adbad45bacc9f89be5678006341b862439fffd1b222278e884e6679e8ec99c22972173bd90576629db9eb03def1c4e41f0d8199094214bdde0b37e3a010295eaacae2c4649ddbaa6b7b4107c5f1169b96f135fe7d3dff750f8926ba02150e86bf34014ceb9a60c06fbf620fef05a11601f9c686a9eb4a4d13d87ddbfc17c21098932eb793b1e76017febd07627337536611c5402b7be621a79392d8ae62e3d842cc93cc621ad76d256f4101bdd6d5171a01d087467b4996e49db2ffba41b6912eb9500a05fa287e98440b06fa7ab58a0ec46de5085a82907ed4948ae740421598ab2a48731d15a40cac9e0d1f9c9a9954eeedad3a6c0432e421de87493896d2936e72cddf9905ec2392a508d69e11a75e0dca5ca047215504de09373cfec95216a2c12498f02be10f500605bc1893cabf0034e4402487c30857fbaebec2a4b975fba5ba1a5774d519f65803b6b0e207092c6c6beab86a2b38c7d77280f0d4b2f9c1e4c29c7b25222f0d3c088f9c77980918b82c3c6cc72225b8ccba0f56af2a22213c1a1e098c4558c92a078be8d6426b66fc603ca58848192c8626e87b9ac6af978d87ec84ce603c0f9a04e6864df7cf775796650d164be2f3ef3e5874f841916f81b82cde610d5f06dc032060d0e6ccec47e89e52e94c32be9cb0d5dde9bed80ffe3e6814ea1628bd470b1424ace2d760d639dceacaf5d84787030e66d19033bc2585744aca9c3219f40da5ca77015f25078d93376dff7e79f99851845e08144d1bd75e67b86472d7db0b13a2d10d70e9e95eea44e1ef8801ad6b8a1fd5ea8e0d7d41acbca35fd5172d0426aca11f22227d93ed45177d729ec3f20cce42043a1e6268a8f4bd686179290ec06ee8214c0b85f5fe0353423e5f6a68f96395e57455fe900f736da8bedf7300 -generate_ring_signature 25dd893cae76d6ac1932f11696af4d23ced5c7f8c9b26c443513e7460ec16ecd 5d9938750d6d01d3cae39ec888e440f33fec671feccd0a5bcb83a0bdfda37022 6 c29716ea74a2eee8270fcfaab52d6eb58c02084e6c0ee1efece22d8ff5ac9ea1 85179c988425643a848188ae78fbb0c39eb912d731fd789ba04016020e904dd7 5dbf0ab5804b5052e98871ef45eb1d79fc94177d6cfde3574f118c0418a84aca 3053056e01b44a45d9d4137e3fc8cf10b86865dfce0f9773fdbb459b0b305c41 e35ae435c1147ab31281c1a79c2d3a31678be7e87050d041c61aab1dca9b74e4 e451cf5197c665cf0ceb5a9d7b93d139051f56e11bc31ef258f56c9023b94d80 c53355e6c89359655240817ebebc88e2a7c039a53e718bd076dadbe8b166fa0b 4 d9f5266b90401909e533b6bb9a2dbcd9517f34c6d8bcf830fbc95698c2c0710a786cfc9a950d1ab2cb4885b3c948eba9fe36f1fe42091fb6f34abbc41c6ad5071a09761444050112cb6ccb9fcfef7c9dc7fbd4475e46a0a63005f166240d8c09c5b83cbd9e453fc71911f51ed37bb4896532cc3d53a6ac00c1bba7897330f005001d2117bc7a36c4f41a4b8c90f7cc5b32b425bfc1e4ce222df4eb71d73ed200465fd075f642b6fb1fbe431ed72d11007711038fa568281d82f90b4970f4900131f1bcfbea19ee8e20b0d6f827900775ea58af01191ebe7db53e48716561540263b7c513a5ae81f26ac31a337b86d383e272ebceef0764e89b6164299f4fe20d271549deea01834bcc0912aee097eff70f16d138a4f40ddd54b9085b6150b30b6596979bbf97c1db3e592efc328213060041bcd113a10b1522fce9524f34830070cc220f71982e10178bf0dea9bb1a80e8e363d8481bcd1b9d237a769ccd6807beef50c53be11df97b967e32f7954e08887adea0ed8c32cef99fefdbb5bf1007 -generate_ring_signature 2f1a0d247c8827dba4d4ce33f142f157e2f1767529fc7c19c789f00cf6ffd688 3374f89c3f99dad856ba5ce07e7c38dfeec5b312427bb33c8e1b8c372c6f61e8 15 41a94a5d8abcebc4c87b58bd560596b715bd33edb75aa248955b5e4602960ffe d30add0397722f8cd6238bbc36ef02a1351b0bfd5a462151a57cb156e477a909 8ab0a8764b7ce7c3c10a7e6d201732c6ff4fa5ccc9e2c6e25256db8f88c19467 c12136781dc3aa8a1dfe8fa588c768f3f5b73acda82626cb380ebc0e42a3edce 571d28f9270ca75dabb42b076a8f7febfdecdc966b0c106c4541cb6820380f2c c9e639cb8b24ec739970c8f7d87bea123690fd4f1edd394cac1fe570109db396 84321e4fe650871a21b17061c6581701f5acddb389d49e4cfb8a65bf37fadf7c cbbc7e4105af837cc47494fc5b5e78735a33190f1dce55e2657d2d538ae6fe95 d8d75ba6364a1ef06d0dcda3ab45bb2c245d7abd7dca3574a5f48c3f5c10f3cd 74effe798cf28847c01bf6276a0c24f5be7e6c52a3968b7df9b8545a692bd9d8 72740510584e7b51328029f4bc32a40c715d892cb00f70fe60f7912cd7b7ccfb 518813c1abe65ebdf8bfa96b139e171b30da00b3619fc258770bb316410d8488 bfe01ebd9d90edab131dffccbdb58cacd599d5f0a3fab24690c7e932f2f06835 9d8fa00ff4874b2f6cd130a224a2d2df214f27977224132d1d84a5ea13a85493 d780603fca86efa77fe4d7a9d35617b56e6b1f1cbae974bc5ca9ab4b37f94388 783590cb03f14936ac520b8b90b9a59ee656aa1a35a60774c23c0b120e0ad40a 12 4795468c5f610d05cade4a06010821bfca0b8e9dcf16bf9c69c51d6d89c1100c184f6b85e4a83b59275e963b26aba2ebe3b47ae682a18043eaf71d34cef8c10383c91ff64f199a422f471c9d82c8a0b15946d047c2b09fdb061da7d17ddec40ca7d70cc4ac563d3d9c1bb82b78081f49e574408d79efa00c89c589d7d09d1003e17e7144d1a7d0a47b51953698a34aee5c7e82cd9a2fb4824329f13fc52401010856cb7d009b399683444b19c01b5c2822880175a286471b7b3073c30c98f60d54b16afd9098d3c81bd703733ed3f660b11fdecf6e04adc7a4c61054373acb098a50d8fa28e392a45acf5886e9fd1ca5a55718bf375dae3744b3f0c1af778e0efd174dda8c174ae65c54bf11f5478b5d2b487251f03a97f960e33deac289670df962c2c7b34fd8c9b734a94f2024200f1386de23c23cca5fc416e2393d19550a3bd81744e8d58c08ec03d6bb8e016918b40d92d54011072e8e53bc69e4d2c602cbe593bc35f06cc7256d87aea75e48eecee9d5277a3f38e7154cbb530ba6360f88c225473ff147b3f5fdad3edf8647367b9ec35f577687fb3290cc171b70560cfc171eeb216fa4af87417ab49e842aa8f5ae11041142dc239aefafc7b2fbfc0867c5ea0f842eebd1339dbe9e0731805ffff8c3119a895b35efbe760a503cd5044d1efe829cf952b8bdeecb18496e0ab500e011d7a33fbc90d907b8699abd0005ca6ad6a9eadf74d402e34ae6daf7dc96556d3ef46ac11b9ea94b88204f80ad074e4c5374da9d10f1dfb5e12fb9bd559810c2a96b00484d0b69aaa098d6f2020334fa86d03b316c3ee47c92679bcf4dee94228ae4b52502792ec47f4af77c650a83421becd7269fb177ad26b8596d5ccb37a825d270c9b4838360d94dcd31f00567eed2d33df5614eaa0c6bc94e76cf9d608fd90523ab9164c85dcaf731965801dddd7ddf01b4d5f411e6c8ac484c464d06c28f06d0572695337935daab3ffc0e3dbdd30abb3b182b610768847ebc4b118a4f3d71e8edf474afec079409b7ee0cacc2dfb73400dfc39a9790a1b4d1ff6ff3eb961bafc8c8ce189ef8558f71fc06afb3401e3be6741c8c536355378797d52013031a092901917bf0eacd70d24307ed638249581ab6ee5490471dbbcf857818787fc7c8ff4365e3aa73b244993b08b4dd9cd47b97ed67628b4c2beef1d1fc6799eb4618bacdbfb6c1069c49749e0e337c761992e99221e83f1397ad42df28b35c9fd4c62278a01c44ad00bfe6b50834fe93efaab7fcaa3b8014e4d9b82f66c7a5013755790096889b6e90130d0d024c23c7eb8bc9999a3bb45464aac4f27a857b7a72f487c9c6bbc952ccf24aba0f -generate_ring_signature da547499dc76464e031e5ff7ee251b23e86a65e7ef4a702f49430dbc1a3224cb 33d203426218d7f5ba88cfe70ee0255b22f15cd23d1e7fe94e02fb4d7a835de4 1 86b01d9ccfb40a5020a4d522c02855924147e974f4909a1f15afed38ffdea8c5 55adae1b399bf6a36b775e369894601a26a5395e5092e93f1717e75dbf74f60c 0 56605a7e0eeb0789131bf1a8a46e034a040e7acf98cf30e9224db6fa7821ff021e650c9ce8b6edbe6e7897604f9e0b5673ff50aa491120d00d14c16a47967b06 -generate_ring_signature e7e69c7adb279f38f2e2f05051fd992a11149a8998d1369be08f3dc277fae761 85bbeb775e94cc97da84eb667dbc70a26e60a5276454ef41a97e0aabfb8c2e2f 56 18d09a4f9592883fcd32ff6593cec77b9f973837f03d16996ca2cc33651992c6 974af2b4ef03f64b3051a9a18ee09ebe5ee860ade199631490bbdf6d8de269af 0f9b58c9eb9bb3211deb53ef5b997c8aa68ebb9357ae4b827e6042248e07525d 582bcbfbd1c46085fc27008c081b8c3190d8295ba3ee29a28a811c8dc7ddf87b 46e691e35acd711297c564b251cb5b279d11936e67afe44f321a83e7b2362157 254a0add41690908429a4349aa13813cb4b18b08659017515816181971d80324 97f30a5f6836526a6cff058d570b292595e8b056f740b325334712e9c197b8e0 5848a77ebae6530b5cbb1d1f479109604dd9491182c4f4537f3d857b160f63fe fecb6d36c025378dd87880402a8ea775376954bad2bdd78ba5614c793c0f9c8c 172a5304befb1ceefbcc22bf34479c924f29afd264a3ac3b426cbef3df1e1903 7bdbe1fa6447623cc54d957d4870e2be682aabc434db57e31db09b1472774c85 394ef3d1104938454158def95ef99ce4614a373235912fad5dc6bea68e9d8b41 23e1141711a551670210262fa8a59271dce5a05939d906a5d3cd7ec5277c1da5 969dde51d1fac502a370b8bf4f40d13824fc919670d4671b402a294b6a89bb08 0509b587aa1566227473c0867249948630965f4f94a6b024dcc64faab4cd0e66 7e0462bb2cb462c7af329b6bcc6b9664a2643cd6e360cfd14bf7eb53544c999e 738ec5605320e83f6fd439853de054cf99d9b320916ca3c26c53b914e6aa490d c1613e126399c42bae1c4750d814dd533c406db959abdd275b3d9c3e72984c24 d588bbe6c2c2744068758a5d6e259d1cf02473af17a1368e62932688eb7764c1 26d840d38fa305151e8873b14a441f42c864d873ffd7aa2c7c278109a446bdb8 66ff84c63ae19639ccacc7b493892f8f26ceeb3dd6d8f063859449da9d5b13ff 828787793865161872024f6ba77dba847f0873be2562afd85a64bfa0f453adb7 1874b21b0a18b6b43318736c3b53d871bc491695f5d86c8811ad8b2aa8464648 8f1df6bc7f2a2ca7a7d00f475fa487409a0f4155d2bcb2db1e9b007cd9368b83 40b39d643696c1517209c946e7e797b4c1cee0b339464c9e8b13ae28d9434afe b3621ef2364d2a8a9f38aabb9b624b932300046569e9fb026d36c7e73a3e8fc4 3115f7a4b63d229c5182da0a3f624de6c7e2b50e13a7da14a322f0de69595418 7146996c40e7e9570671539d471235c7baef7387ba12f1fc06602fc973a3ffa8 ddae2cda3fa2d25bb4a412f4aedcdd206274bcdbae18a3d6b4c25d978f8f5dfa 124c68d03ba3fd815102f4ec1e16016e6335ed47d9637771c426c49dfd87b1b7 19a1d656e101999c3b1457e995d8a0977c18bed779deb21ef832e7795d4d9044 b69f73ce720530c3fa94f7f6f0b1c6c8e5466a89b97be80739187695970f6871 ffebe2f897378da204d5e8338caf629744fe910569166768481b76d0934e5e0d cfcdf78c7fe82f7fd14a6766d4cf608d6eb92af30bf11ce79348bb2422c1ae8e 7af0a5c4137717bee0db0faf10813515b700be3b04d639490226b047a32b660c 8e824733a807d4fdb63c7621b6838f70054b9a069c3e8b8e36c7b7a2fde41de4 b51e86c2ca33303c307c9d1080f5066ffd47b67dd1a1a368d4bfe5def1fdcad4 f271285616306d959f3ee158276b7c35364191836ceabae3d5f532d1c2f6cb0b 0634672a39f8f196a86e8afd3028b1ee852026e53b57ab5dbfb36024bb3801bb 84b77938a69db65b4f705507f9a052aea980fb5827062570470bf1674772cbf4 b3f1ae595027df180e6d1ec987e7d4faaa5832d72c759f6c4b33fbec5c197248 b3aa197ab9bc1411a0088271908462c745ad08ba0b6bc52b82300760d1edf3e2 764478333c006629e5be2ede6050b6a9e19f84bfcc9af0cb606bca2a7fd6ff57 42ede624cf6b0648b2219d84e2800f86295b45b2d62c400911936b00d23e8eec c6d188b2593f276c9d8af38786e8dc83fc3f4888357576e0ce1f817c6f4ed0e7 e54f8c15e52301951fae217b400db2f8a42aa824f182bd97e979d38cc6beac71 815eb621be2111a52233f936689d47fa18695b52431435cf969ea1521abfca97 c39db1d00d3dfb57a9e61d8921569686b0cbe20e69915cd65c9530c8bc7840c2 88841ef6d698114e8a73b56a437acaf9dff3fae7edbf85394ceea8d0a0abac7d a10006d29887038ae2678d8ccf83cc66f6e30cea14f3776dbf3b1064b572680f 867185b15807549d9248eec40382c0c2efdddd0b6c18a884ab811bf0ba074dcb e2408a5abedc5ca9c397b10df9eb1d4f327fd875932544769b9b6ba124131669 390f5c7be19c6f50c0645efd3d416b1c740d38d7f95fc6983f5297921026518c 5368d661c76b57e15f8e4cf676aa0c8179bad2cf815856a97ad48db1deca7db0 87494de9d4062f589bd263b6fc826dd85c6b81b66583d6abb6fb6cd5954dd296 a353830ac2b086e36537b57320da789652df3df9b6bbe6f963e9cd6941758aef a0d9ff166385807b7eb58ccbd283e08e6b2194e0dc82ef190b3dcb15bcb3160d 15 6d5be642649373a485d93b635e7b4b608e15ed664094ff04ffdbd9ef00277409df1cf044d760ed37391cb3a7d3dbe2332ca6b0d652ce2c5d1b35b95e9fb74d0f797f35c1916cb24c1ce85d73502dfd68a769b20ffda253e770fb27b5714bd60a8d31acf18cff3d7a2b763bd939b21bc332ba28c068b1760adc7e018a1c3ff70142d7e1178b7561605bef5a3b6a62f410cf385ea585da77d7e0cad50ecc867d0b032d81ae2bdf963829d776d6170ba2e38748a2fdd54af88fe026c0e71f3b400d556bb8959f4b6b87650c265bc69bd7ca9697b35193be51bef4a4ca254e642608961f2e99fcfecb08d694c4e5df1041a94516bb0472d37fe4c4bb33c934a03f02c80d96894faa8deb1a0a69dbed56586e82767f4f8a31490caa5da1ac2ab2ec07172aacefe8462da0db1b53aa3c8f16acee5b59ebaf2f2903d9bd119caf67a50ceb3b384daa28947e5e027a54a3cfb754da13b9ca1a774544f6bf8395b4ca2a0e969a54290577430ea00809519d78faed7555a4a92ffa7874390ee882a197f103fd4fb021a80d8cefdc9c1a790c99dbd68db603c68231298b55cc627514b0740099c4ca2b2cc40d33e34346dfa24fc0ce0a28c6c0deb63a3b6af5a591ae75b400d73c4c8ff622bd8b4337e809c4c9c90143d8a3d1fb69beba8cf049e7e55a28018ea4f895f41ce920aff00f6cad64091797d75ed9611bbd76f4c1edfc2fbb9109185901047ee6603e965c1afa0ec7d3fd32f76cd1955951a4587854aa579ad70759b1fc9504ead94a40d72f184812e48bfea4d48d07c045f27869a0e96a467a00729b9482b9a81006a19513a71ce69cfa5b85fb2b05e9f60050ac9963dd197c0ad71ab74b4d9fbbf1329ec64e12b3b9f3cb2af9fb341468267bdab35721c8ef02287721349eaf9dcfe74fe3b7461d396c69c69acfbd1e1f2beafb83b69d9b580ce8a7180c7fa6613da4d8c5964199f721fce9ae1cf81bf624cc830039df3cab0eed2b6b3f7302193417b0f6f69c537cbdf35aa5782d2f7ea2120f353d7737a40e60f37bc9e42b2295119a73b26a02ef305e19a95deb7b11cc9ff2816ba54afa04c1c02a86298dc2e635877ae4b89bafe609b4717a7055413316cd3b7d8e50e1093e5c399d6cef49fa008500881e08ca9ee88eed262e9f5bf8d23b1685e3017e027ea19ca4cf81dabcc6870da3dcea89314baf3097d841d264d70211358c519602d6d3dbed6fef64d0a54011a6a9a5a9ceb76f0d9342d12099c2ca3ce24c5a510f9b437400a55a0e64c66c8cca64674f96c7ffad87d228f1c25f111f8c8a6912006b192025c195651aa235b4dd768e647eb314efe335e682041e44b1667775c80cee245a64a7f7d3be3c120035aef4d2e6221c1cba57f87e940cdbfd4bf51bbe0676ca07d04739a081de9c87bd212eb87569cd67a1db6d9dde4717d59937149f0ff8a6e7da7c33eb9cf085916e64264310211232975e7cbb648aa375a4a8c9930d1fb29ab9bfb5fb6e4653d5889d8ca50fbaa8edc0cf9c6943403a5b755886b107af9beea17a8af1aa42cd45c0b573251727fe4c9028a74bf5b44e3c5e1322bf0b6388af808d35299a46a24f30c267bacc064731acfe5b84ee14d56064b9571c0ecbc6d2e047e40933cdc8f80cfcea96abea330cc502808795f54291a87ce1c10a7a626b83d533cdac92732035b66c614c73f488e349b221a9c2d9e947dc97af0b4a1207fc51203c1099ad7f45d28460bbc90d217fadd14ce8a62e794b6be28b02e57e34e51a30072523d9e8dfaf5df9b6e0db98096429a9dd9a865e9f0bbad4058ae95488e213cb0d9c3b01847514cf1fb3c8041baa1232c15d980fd59fb2cb0b55dd785d86ac352756241355b71307563dea63f95354ea6ada82d292582fba01fd9e3fa1157eea6d21f72fe6808dfd315137ceefa5348632dbdbe2a2c18ecf0d3411818f032acb787f3878e7973ec56a1f9d11eb3f80d12212b9c65df1090f0d0ce8e33979626891b94125d44bca4b4e1a819a393f3769cd35636a561972830e1bd067aac618529b3b740817f813310538b427934b1d8b5664f51bb81ef69006b756ec86a0d1974c468b81bd261a82aa7cf6c3e5dbff7e47dd800699ec44250e5e7e745345230d76757cfe212205102005e1eecfbbd174f2ff2817eba8272b016c1581a7de86d0674bc977bd2126d3881f73bca9e5baab80bfb9297441a8f4095803e8e9f9b130b5a1d3321a0125409458516b9ddc776284906e2d11978b450583228d5312c26f06407fed2530b4486f5c0d4f7fe69621d0a517d112400a2e03e56ffaac6f2591b36f2d9b8a81d1324dfc4a5ee127071879eed655fe2d142702dbaaac7ab12f8f9925a59907cd8e215c753a2def62c0edda08f4c8f38c07e205e141e359721a07a29e38ad6656fe976fcb16f5ac48d4dc54a4aca18549f6780788f92d6f37fa7d740cc28563592e4be3beb36e7a19d425b513f680294dcdd600bc027bc8b38023ace1e70df496d6a97222d206703a961ae58af861946ba5310fb9b9d93d1849ea15dd3d67965fa8e37c2406226566f36f7204b5018c8d6920000c37e799d501c0da22952a51409377b74a6cbc6a556dce192f036dd570234806fb5c747c12bb32789602d68b972299d430de3f924c309583a6edfb933199380d4681e5df110e82ff578c03dc2942285c882f36dbdcb1522d1adc05b65f5eb50d77aeeae6961a64c94f93c980a693b939a5a672da14f66abf068742b72f898c015e984d533ec98d21a270d368d1589ce066d630fc7e0ed088a98c9cb496ef3703e191f76973085f5a72963a765a2be72e6722a9e6ab3ea9d51e26278e37bd63058bafb4aa684d718c77d7f14e27128e60d9336d59079ca1feeefd1df6ec46b808030de2041d368cfb418241b792982df1479d07bca84fd1d626fa6c6f23605603a1a857aa4b4c552ec42e71e38bbd254f85dd9c1e3d62d99a5c1ce74861e9dc0c30ae397eef0e27c776d30d3ebc9dfdae013819905d7d7f20395159ff0095be07ddff48205ec3bfe1b0b645bd63b5e7d9963f60592164fad0ffcaa152a1634c09d275d541a0abed1810a30bf6025a231f62621661e0692a6526cc6dc007c7db05af9b4f6a1b83d9dde96d1ec97eb7fe8147c7bd6fad8d5a113806dba66d330e02b30078367c0cc49cbee6d0a8077f1458bc3280fe6f596554622c5b50e43a7d0d8bb02bbc9d2384038874a58a3dbd8af35905369a76ca1a84b73e12d0dd62d20e7fd20a9177089eadd274ed09ef2be773e216722f0c76119022ad83f885009001e46091a17abde7b3af9a74ff5350783153bbc488e0e6c2260e918e1fbb121407e29323952c59ddec35b7a760c4c89bfbe620171287a4aa6898c9a187b2827b041efded978dbf705f18f424780e789f2c74bf010d9457cbf89673c275cf79f70ff0b0793da151462b629842e81d8290fb17b419bca9dd6b356ceb415fb1e40f0efba14eacc9702368b688b0df12bf0229a95193f3aeb68727b9555d368306c30b9f4de41c5630cc09be6a34770814535f8b8b5b0530a2184216c62e64576d2c01d4fb7c0f7765fb29e1ab5a4a5e626285e9e8af0fa6ced707c3c36fe2ae14fa00e5b467e54bf7bbe2da3f6b37c714ed21c7927beaca338b08ae9094cca8d6f80cab3bde49b255a8851a0bf55024c9370d65224680a06af15ae28645fc4be38706894be22ec8b0859f7ba6883bd06c8ecec7e5d29a1f5b3d71f36e544b1cd7f500806e1dd4da697aeb779a8934ae6c83e59e81526a02321b790736c26b20002a082e60fac8edf157cb37ec8aa66a6658ce45459a1fb0c3299cff18c4120371340540b1216954dad34c5865277ea3c53e70d954acf265b57e8c2c0444f29a12ad0866cb496a4a114616bcf558d6f2165a2bde3fcb08e6f532761970ee9d99722c0dff77a3c3f10810c91c2f38069ea3aca2886a45af5a0ce80278c59bd46cb4260c410a215919f04b38d7112709e729e41fc1e139410b96017401135eab589e800d4e5d175b4ccb3f09144224390be942f3e8cf8f77c9a7bef263b90df2402fe60276d0dbe9f18c6c682869721e30e1fa326545983d216abdac8e5813ce81fecd02a889e6497833d270609dbb4318520a80a80f0b99a68d1526c3bc9f99371ce20ca85ef2c02a89c1eab25d6e5b60829d6344a031bf0fad62a670b7a53ac21fcc02ecee08fa66123a0be39535a89237570b3c8869f97fef1b2227443b13e586850a7f90e6453e2f7908fd432b8c2425c7818995c423c4ab7d92f88893b8388b5f06e89713115e636eb34c216813afd2027e1daa5821aced4c156f600a94d03d1b0ec0f7f3d44c59223e3d99ae164321dc475bbb9e27d2be9673c423f36e56504d0173f0e54eeeb4497cf84098028817e5c86b6f7b3b852358a65968a1d93ff468025b044eaa2648e1c5353cc3fa60de7aadf7b9e066bf65cfff7257209800241d0c0292974c4ab2f65c38d5ce61e976cebb1d20a894740be4d37a8b73dcd692130e7be0fc910f784bd2b823e55c3c3a0f577fcc0165cd54b632bcb0aa75cfbb4906771735ae1c81ca52aefcee14ad3926b2849ff7f3e1ecb7d31d117f3668a6f809bbce90d190ebeb9f5409b81482408cd107dc82ca96bf65d8f231721f2daa6006d66c66b2c1a0b35cc68a9de2b998595dc30595cb6a29366cbc5711b786c0fe08c47b44fb7dd3fc8799d9ffc7185e064c0e8f57a3e79b6cb0c1a76f6970feb807cccde40480637b909daf8982d5b1c0b661f0173948bfe8981a7837736f880004a4e9f5e70831fe78dedc73ad08e08497b7bbbd84496a821675f0718937f5fa0bf2eb93c5466fba6888abe3ef242149021a5ea5fcc18b8a4be8cf065d6dba4203d9bd771b46c1767256c7782a3c582f9dda2db7b358caa4fb8f593479ad77c808e3edcc61f64433b090450e0bc34212bc28eadcad8d4b8b34c9d42b071be4af01c9d831e88bd88d13c9fd56d0f97ada04e3672a8d21d464cbe916929ce401fa09ba83ee90dfebaffea9537c47ce6b1a7a0c4166b35cc10fbb5642362458416501 -generate_ring_signature 8d502bf01a32e567707adbea7c5b07946c8a91ed1231dabbb363bb6c475debe8 797d78be1bd8f1fa9f586e9710621bd3d480427b45588fdfe8b845b12414974e 1 bf227dd9be0cb17b4cafdeae98527a2bd5f22d56f4a4449af561a5c7e9979411 c1d63edbfe8e5ccc53d5c54f571718b81448166bc241c68f09aa1fc0f337d60e 0 55678fbecb38f36b01de860d0fdae27ffcdf030d4b252b87e18cbbd7111a3901be5451378335f8a4bb33f178b30bd2224f930d56d4f12fe6b7cdf7d4b4166803 -generate_ring_signature a360d6c579fda6e77d9d8f7c5670c5a3e56dd67f9bbeb9a2a51ef4fc846c9e4c efe52ab1e05aa48518f70282135dbffc35e61066c0ff77f69dca8f4f77cf26a7 2 5f4e6fe57d228860581b1597387794778018d9508ae293cacef275f3f380f949 7f855f04ad22ae8e65f0dd48b9140295e23165c1bdc44c2e9caac8f7a4d47690 742392bd543557e97a5c79270150105e0e05099b7db61d2f07f2a4ae1b0bf301 1 78aacede410e8f9d85721ffde4f07085507b6f54df9ae9a8861a043a1200e803f03b472e949701e039688103038a5a525aac1dae6540aa91ed4ce9c2024dcb0547a1ce7072e2d6dc7ae3b9696873d977f87eb7fd722956ff20bd539fc3169b0a09601304820fe4e691d1b50338281744ee1080a92a13ffb432c0ba8b8681e501 -generate_ring_signature f06ada276b4cb15bfe0baf1973b4159c4ae03306b3d1cb6624410d84ff75ed8c 33f1bb96ac7545b8d506cf2332fb5c1221d7833e8f1a58c7e72e7ea0c3a85f44 1 59ebef8302f5943bdd11879b6b4e3bcf098eb70a56e44871a3e6097b2a38f682 11e1c3f3d5d9187ead09f8679cb2172afc020766ce0de7ae29998b7af9895b01 0 fbdbc9c9747925ab3f1e2cbe191652533733de632f24038155d03e5ae585450d1bc1ee2f4990860677d2c9a3d39b4658fef54562ef05b331960239718359d908 -generate_ring_signature 4bf0339d9f8d053c5508af5620f121860191aefa336297ae61c07ab16e830e95 4b74cb953354a6d552dd2093fe6547018f2ee804b950c00ae2cd959d9edffa02 249 b273d48608383a643e8f4fc7a3218d79135807e1f01bafdfd131a6ebb066f53f 13a87abbe6ebc9c0a6a758e2bee754d629c0f0e3c9a8c922f2d6b84ed1d09563 41368a4bca9b547d015b4c88063bc4c61bcda812a31c5fa1380cb9917d91bfe2 7adc855900644fe40f6fcad939d2ef3d2ad64c78c67081eafd47aa014fbcf569 327c96fa149e38b3e54f28f3462c9e66df4c74a6ba7957eb9fc52a91fdaf7dad 421af8feeb282c03a8fb30a7837837641c153fbd43a8331acc28b1c4a9e86bf0 61281e80c633170d98119dfb0fdb35405f8ad76b0f0d867185ff43116abe96f4 2e25524e65bfc6c97f57a92766d15c394e46386ec49d2749df2d45bf52daf1b8 47ee6c2a1c29f513e09d89f74fa7b86a39fc4468cb648f74e0fbc1e48d8f6d98 09e04617608530d57ace72efad388ae1ae3947c0466c5b430b9dbf351f392867 ddbf7d3d8bf539aee1727a3eda3737f18ab63ffdf80651c5597e10fe6676ec56 135947fdaa00c8fef0bee2b1a8e843746094317d6feaca3c12b15d10154979e3 203b1c508ae96f42485d43de27fdb3075f3be201748e51ff0facd328399ff2e0 c336b25aa242b63ae73f67e1bf193f50fa8f40e59110b69e76db94ed57886d6f 8b285837b4f1690849e2b7766d9f530218aebb3e2ff9110a7b149378dba033d3 563db591fe4810c041d6fee4423947f244f35e819f0638b691b2b9fc77cad430 03e7898c213d50755f382dc62e36599c1d3dd87b6c9e0159472ed2f9f334c0c0 22e97507ef3b946b063e25d97f5212b6494d2696f9971ff5d54475ca9dcc1afa 229b32794f12ebb14c367f5f92290fd8190e14a65aeff3fc78aab3f8637b2f5c d6a8b2d32e3fd2fb5d1c71bf9fc51c0095033217feda93d973e49308f5694ee1 babc6af36f56c37f9d1cfe50d88c6e7a1403d9ca9cda788a01669a8ab6f050ca f07adec8757f7740eb2403d1a4b1c29bc591f5f90aa3c8cfa17035b07f0e6937 040390e90391a7eddab4f52925efa58dfaf935ae202267ec0f2aa535266dedff 84a82b340c5ba88f1359f113fbf717a945ccf2baa3b1561f347a70a83eb3727a ed06ddbbcfe612935bb53add5ef26d3e763e820f62d549af2713be22c6c6ee48 422ce5b6fb4e39f0846ce3a429a03fd2dc53df54f806b5ecf1dde1f2b004b074 0de9902ce29035edeec28692133417787524ed249b1cc1e2a1c000c2f35d563c 51c3352d40a920458a2e73a32198bfc93a72732d434b1138050ab8574cbab540 777b6aeae382f6d39fc2e613dd90a4228c2e8d69b3c56a84f250996a3ccc401a 2a324732d151575134c39e80275ea6aefaeb038346fe08314bcc90cda45b75fe 99a2da7d0817ebd800f5c2dc62649fc202068cae2692760a4b5bc17950249a05 3b8676f56b6358890bd11968a18e40f0fa56155aad8f89967a9aa37d8297b177 c0c464a4bd5d573e1bdffb58dad5697660e675a9e9e63858449b89b267271a7d e649468d35445f60819fe76f8780023b5a1ea23f116398ffeb4b4620c68e344a 05e7d38bebe36c388c980a9df464f018f48681ba297ba940cd46853b52300819 56f4fe13aead9eb250187d3f55bad323522841e0b5fed2257cf419692be899a4 acbfda9c0407409f6363b3718432409a2c56ead586ea6f8625aece0d48fbb29b 0bfa3d79778d063ad3675a485bbb8f8baca3296368409d81aa25ed3da324199a 800a29bcac3c088906ddba33ed1cd9e8ad0335d5075ddcfd28ded381179fd5a0 7dffeda14c5e22bd9cb1269ac3326a6a617b1bc277a77f5066aa2676dd6b9d40 8b786c7df9fb0e695678e9cfc79771bc84badd695e7285ac75bff9d6a07c7b8a 11bab52ae903cf6d7eea8a8f14da338ab52829ae7abbd6826e0c96cb1d8ce098 6e0219a5b11dfdc9ac7e6a8ebce4bac2b775a98a12697f8ce2afa792dce8553e a45f1f5479673fcea8ac0680f92089b115fc939bbf97094a430ab849ffea4dd9 e5aaf69d15c087793936a53d679544d2634ff9db1b81cd2266629c5b5d6048e7 bcfd31af3666aea09e3255e835fd931019b944af779af8e22428b713d942694a d320bc2b9ee9a777749dcb6c40e59a9eff375737cdc0c9e63539e89264e922b5 00910267ec94f2cef9ab012f1884518fac66acc140e82bf9684319d438792eb8 b13f3a4fe4429f8c34ca50fd9649193a1d9d42939280df3d40baf029c08fea85 79ddc3b230713949fac670ca6ee8442ab77d3987ad1855a856b20ff8c184fbd0 b9cf848cf9d1aae5f0d066e281b3eb0d447851c688123e4823dbf3bc5ff84929 3ff30f29ca0f5d56e3114205f032febe2c7ce3dcb778ed20d0fde85e42d44a69 49f1c860b9653e21a699f11dc10a11cde10d311512294622594c7fdce67fb8b8 8b18920f526da2a285481fd308428fc2a125c257155fe8b9c439e100c1f4299e c3b822f191fac8d362d2262efde806e5bb0a468290708fd31d6fa83890363a8e 114fc1213163e40d2f246906455a7edbd3070157b2089bbf0f23ebcd4576e7bb f39aaa33d3a77cfc664fab4560c47c230af7809cbff25f6806c59918296e95c4 c5a3eb0d203d502d830ffa7ac764c029b2890cd5c7c48aeffb793dda0e35f206 ecefa373bd1cba2ad4b04d5f2921218abf99f0825cf482c3540f94432cf01c45 3d4313281bc933e2bedbd7cad99fd60f1748256df79c08936d2162bde71fbeea 0ae2cc5b6d3b36b676cf08f4a9b4d754339dfa0d0ea5ce5abf5470b4726d09b5 6990d8de84993016435ca8f23aa18a7e72dae4d8d7e232994f7fa5657d34fcad 3cffa4c6b3aec0efe4e7e977e5f8a7294ee5c99dd5c0ddaaa3fe23351c941d85 a2d0b812fd1c7d191eeb61567298981e36b340c134c78da944f8a2203352e8cd f455055f5002146f5bbded6001d7ce6cd58e7e274caee50cdefba3613388a0da 477131a096bacef938be8fb54088a9004b29aba49f4579c33ca52deac5a8e5ab 67080c465a248f515e86b58bdbe91ff272cd23b08b2a7efe4d69f47e0ac85fdf bec5ac0c0b01a028ea0b29369e79e1c81eff46e9e69031ac3cac91aaf4db462d 2ccacdc26da82afaeeefb377043620a661bac86ff30ac720a847275c3b22ef41 6b20b96ecbbaaff46371c8c5094ee3af5250e9171c3207804bd0ce83c486b5c7 77d1c2e2a5b9048ad9c2200cd77495505c851fe1d0e4872f46de66b7af209ef1 fcd862e7cc429f954f422dd13ae8bb48dc029bbcf9b914244b7ef0a20102a155 3ede83a52d68d2fe4f8d6e721aeb809bfdcc0b38882d41e41dc2087c2b197f26 e38fa088d56b933da20b16848fe1310e4243513dd3c729f4032f74d47891ac8b ff44c21ca0af4dbc2e0dc012ee8e122de372f0d530db0d68cecac9f2a7c33b73 3b9903664c6ef51dc655f45f82de37b954dd70a37af1a45eccff40c492f797a3 1f70a93f7b6b459fa011b5e7bf421d5108430c443b1849f09e23aadbafdf2b22 b957c51631fe2c2dae71100ece8911fa410088a255dfc3521c0b1299d1ec89b2 b4c2e3669df39ada556b367b6cc9ad80b49d3ee765b54f288f31eaedf947aae9 bec54b546520ce1edf6def1e99bdd92fe35fc090f3d7ec249ea4ad7ddd998d5d c0105b38734b5a317dbeeca88fd34ea91633d4eaa90171724a420512a1769f48 34d20eccf3554bc5cfeab0839a5da3af1026be554b8006c91e495014f47a98a2 89b6ae04aa15388f5286393aec911d4ae16fa9e1c6cf991a8edc93ca27511c02 dd8ed17a2d4ed78da78446870808e79b46bd9302b686b72600575324c9a18e72 9127b0709d801ac54b8d550285a6a4e30a77f84a532eaab6c337a1bef97dd1cb aa0c38fd5fad2f1302e5983a9a09ae83edc730a32610a7dd102475624720588f 1b614f9407aa350b5cc5c52ccbc788e943a3f3d6e6a75e332103c7cb52503e2b 7bb824ad656dd32ad9c9ca1deddc41a3589f3fb9673ecb1621da283659139d26 8bb69321746fb816425ac5848e3d941decc629180993180572a2d673766d217f 17a6eb6175bd025118254836943f75898ff81a9cf26cd18202665bfd15c98e16 efa75e34a18284a2434c5b59d0c28891b998b2120a274cabc2d6757225c1b746 4866748e5ce204fef81c801a58339108a51e6d3fea7e5e2c879b22b358aee2e5 eadb7e4fa4a23a04f7eaff1faf8cd72b98215fe213ea9404398c3d942551249f bf44973880920ae02da88d1293672bddb4c5ca8d2c7d128cb244e480618cbef8 466f9c575f9eecb3f26664d593dff14960f4c68b3545a704b99594cec3f63060 b57feeda8456b15539b5d24c1aab860b97cdb498b629f81d57ec233e4111007e 4915b38ba83896e3f34bd08451300e26d5ef5d8d8af7518ac0592d19845b4464 d0524fd7c02630ab477ab113cbd21b5347063c933529fa01813d43a0d7d80d5b 27e89f490f81f8b21f9a08539970ea149b3a18196d54edae47105e2c21262498 a159d840849c5682a7fcc45335e329c3f4f65a0370bd835c70b2ebdc08d2eb83 b6876311d19355a2bcb0990f7b3fb98639eb5306af6624767cbde5013246cf8e c9351e40f566cd7e30de47c39154f598902d0d2a4f78eee4b37cc5412b2a6aab 1e30ceae50d00e8a0e87c28e46713011b4d911da0642468a47b95b98c33f4cdf 0c0f7add9e8f5c60117f50951765739424cf52757f48455162770e2642b44c90 e72c4aad3a76f21c7f40a8f7726b4f25c887fa11de547e5174e57d146462e764 49ae88514ddd003ef502e13b4ac56270888953a5802a5859961459a4c702cb31 acba3157ed52715ab3c0ce192c822fc4d317e84e360103c3cee3115c70a601d8 b05947d43cd215f923d48dc386c3f992351c5034c9112763bc2f89d9b4c323bc 0995423fc0a5997c95e07d3c4e16bade98d1885670ff48e59929c59c6c91fdfb 722c55efaea965818c6588b5b72f63a5b5036964ce66c662b0d01e85417e03fc bf2a2562576c9108ff535b04e023ade892ffe832c81deb4ab1cf69df767ac1fb bd6bfeb30c62acdf53af007c5fffe06ac6479fdc1582dfea2e5100dcda23950b 0c597284b35c159e09adee3c5f2b4383ea00488302714851b99f0fc6a774b7f1 86af1fe8506d70599b9f8f277f4a9467bff5f11c7838feeade171b6d62c109da 3ba725fc3c37b7c284b280ecbd3030d15b99008537d072da46609f1118322170 0185bccbc5d27113551e4eaf0dac7a724fc0c5bd8e03ab58891a5af79d0c4540 a03be24b919fc712ccef8e92f8402b32a5ac2e6ed435f13a01ac0adbe4cfff04 13a37f625c969172b64012f9c07ea8f87606f9a44bca086f77b72126dbae08b4 c370773fc793e240c04a6c6b44ce8c6bc06bbbf85cad228c299a0fe0a30ce63a d1c0b2fdcc1f83f9ff3808ed8246a6bcec7818eb8aa2f985a1cffb4bc71240bc 8df94b166ba97d7b5d3cbc0efac70565d5fd8f1bb7676765433122d3241476eb baed16c73411d8331650189ebe4b53fe9bf2237abe48579f14fd362fa1eca68d 968e2c6632c17127cae014ebf9c72942da77624a3c7e850b821a3b35cf3fc089 042d32521b49938a514044f1d65e69d2e74e3382f9044dc58d33d762f6a3483c 5f6ca5b45a1bac1ce6f04d42b6eef09ccdad558e1b3d5737fdd4c1947d57580c b8f960e7d188503d9c23b47eaac1ebb6ecf00558059a2062d3ff4916dabeb00e ac773dc9ce7620b6372078649fdb96ab0036c6524d2c24af9cb2054372306681 dcc1a2b1cdd61951167bcf580126f4d91854144f410ed394af5a29732c430935 399c3cff7cadc89baed9290842c4d689768b41dbd3402aee4751e4e6dc83cd83 cba3fddbbbde39fb6f01534b8049452ffe7e1837d28e466c0929c7726b5bb3d2 a525c1b382c198a32c710f6d1bbba6ed75ed85bad57ade17efe1deef3cbebfbe b10695a3567eb36d140a8c81b364477e724812c5d5cdd77631f756a678965fd6 100f2e875351cfa296de66052c4a83ae00c2f40bb97eadd1e7ea0068e524c568 65373bf6d75c43fd82031c030df1cbb1f2e54fe11dd9152d06f67784437a8c6b 10900f24d787db19021c7f6ffd05ccd2c1485bc9ad50bea77b5f7e2dd4d168b5 9206d8d7772a8042bd9b3ccae4d1e897dee041227269589a85225df73d51d8e9 e2196925ba83980352a4583ecfc2609194bea93e43702e1efab71c76eb99a77e 5555834ada3f35ac16555078158b1e129d347b2815d0cee6e17bb1db04fab190 9e411227937e25b05de329d88b29a3281e1471c26ee51636edd7b2bdb54532b5 cd812857f0c9592e899749df1d1ca06a4ec898e2d459fd463b87644ca1a80952 c336f88981b39cd2835bb54ff9d40dbaace66bb32005c266e4697d072fcc59fe 2f96e2125d594ad89999559a2d49f196ae3a075651d34351aa729147fbae4c21 d7f34bf026e0f3eb8f989d50f7fe2ca31e3e84f322bab7d956379b6ca67eb8c5 4ee15b8fecc0cd747a0813b82a98727e6557d35636210fa25046ba2ec63f6778 5c024d33681e72ce084e049ac978cdf05f2f690f9eb9c3c0a2f667e9feae4114 eca951b655f40be30b5139801f0eb195e6c1236dc1de5eb982a64ddc5f3e0ee0 b1ec1fe38059d22a2361a3698b04b3633f8c5e90f94e1b2e67c7b0a83d0ba135 249dc9cd75683ea99a1a6d78b941d25f54240f025218ca113c1d10e83e1e0844 395735c24e6403b5f9b3bf6cfec617ac4afaaa68e3861320c6ddc0c3dbba3e3b b88c05ad20d89d50304c08620f6b7f4ef80c50a95cc2877fecd2b929658de37c f4d13f28d1c3d0b5424b8ac845becb99c0c63fdf0d50c36a72a2b49bd64c4486 5eb59459759a26c15ede5971790bcf73fca4ef0bca2b2d2c712ce5d7551c7bbf f1eb0ea50f8c27d0914231446e3fadb7f0f4076b236bd76d15a2178043f15b1f 042c13be06da921788250ae0fe2169ccfd7b8f58258f6a03f0eeeb9ee4b056cb 3e8805215ac6b972a2007adbec893c526522a43ef8817e16dd09637946cdfe01 82f05de9344173995217794bc4d6a239f157038e41858fb49d73eefcc4ce979f 779060ea9dcf24e80010259572f453b743c818fe22d78f73c178f4f8e15f8340 8578dabb1c0d7d98f5e8cdcf2aead724a8fef51d24850eac7acc4ec67de107eb c8959add000fef8da12a32535810a4629c9f3005990500c472ca0c115a0f57aa bdbef5249d2f3fff40c7bbbf5293987ef976bdb15d410a62dbbc80f5066cfab3 82cf3f9a8c5131e29b1b1cbc9f3d48594fe30a5a0faf9f7b4d3518ff44905567 cb5a1a999801bf308a00933438df9adc4ec64b82a91cc819f46fdfa4dc63cd10 a2b5ff7c5043db55d1ba34b94dfbbda40c407393b2b5cdade2a01296d6a2d6cc cd9f89e414c961caf06f311ec8dd62f3941f116b42ee2220f6cf8730af87f225 94f778566f9ef6a3eb371752f76cf66523306c2ded5612d187210140dbe8ffca 1fee562d0e19adb7274d1bef2616122f37fcab620c31b259095758c361749193 2753541527a5f28886b6079e94031216be897533dc3aea2ecfad2d3b34c14a0d 74f9cf2e7284f89e175f7da2ef898edfb392ff850bd0469cec5b2999ea27e413 0822f78b4c9670073a76bbb206aeaa9f56d2d4c37115cbfef360375fc2bc498a e3bbbc6efaace48edb5dcce9a82bdf8b1a01ffef4e0ba272695ed17f31ee0ba6 9c249607b3ec14755909b1a4b96576864490c7c6cf077222f40e604089c2ab78 845830b099308bb31cf8d202681d2f42a709ef7a7ff29f25fcb340b8f6f1af21 f18514f95167651c539492ddcc5a154da18999f6fb5ca844c6661f113f36505d 1095e5095d519c92794caecc036b98052f8f8ab7dbac113cc144734cf6e732c0 4fc7a8f505c45e9cea40249551027ea08f7dbfc56f2cfc7dba28a31f8ed09695 faf4bd877cac477edefae6746b50518756026be3f58c3e283325f8b3c68546c9 ec3ad5ebc4dacec3ed641ec9aff310f11f6528b186175affc0dc3ac494280e90 6762ea15a154777659755f3e952190a37166ece974ab87c0f0ae41fd7e919646 6218aa86f87c50c1d29d74530fc73096cc5770e41c34bed1094ddc66835326cd 6c6e8e95cecfdbca5a6a3f81efcbbec3f6822c94abd6824b0b2ff04d8e005a28 42529960daf5e9fcf69f0378c7fab63dc04a440b590129d09190b43adb33877e 34da8e22d7ac3501057278a7976adcdfceb2f0946f9295163c42b9969f349de8 3567172889fa533c80d6345fc3bc669824b16091528a9ac6363a49555b3b1839 83d3c5a2dc852c1de0fdfddfe67bdabd232e7e786aeabc536e469cdc5a96100a fba85c323676f6f3d712a7fe174a74291ac8a7093279ca4770e2fb8b53292245 9f745cf4495ccdc23902bec531bfe44ee6608599bf528860fe615b5e64cf22cc ec2408378662a405bda9cacafda3bc482bf0ca4a5c3ecda11822ed66dd23ccf4 e6e2a769bb7bc694d5334699e807b312b31dcb84f12c098e9ebe730aa0aba197 86d5f8f8b1ceb931231e7955ac295f22b7dd5cbd5474c6f17ae9c67bde08b7a6 872a5aa1c00ab676ff697bc965082db4b84c9c5912b13cd73e238205b968f6c9 98e88fb15b4e7149d36a4d96369605702421a82536601f0d92a8a22a00196a74 b90582eb1cbf5d567bedb375902a66f452aedcc9fa4e610361b1994ce9756c9c 46f7eac37dadeb7d586f1f2154fb93224ffef25dbdcf5a50fbe2058fe4af4fa6 1f7515f2e3b6b0adc19d28b1733b596f408b3e01efd7a1c32d8a730687c83303 d9095d067e48593259474e88b1bc9d7c1b8f7c9fd6dad38541738577faf674a2 13b7e9dad168b21952ab494ae468f7eb3622eef3c93754dc85ea5076395b8d6f c53c69379620465b2ca2c0b55e292b41771066169b131d8ede8d958de335a124 f0f67b6cba0a5e26f0fb871f3102afe16c95dcfb3984d36f77158c55c2116055 83d6462bb79bd75ed33ac87b5a7792c49f6a7c6ad2fd9462846a7dab0bd5ccd4 e105fda7964432c084b06d5a4ec3ae8bfab30b85fad2ac5e12bc91f570f06c1f 7281cf80a74a1ec7881cb6173e8c82a9878a07ff0642d24408eeda7de48bf6c0 8841e7f99d72d4523a6434bf2f7654354f5d262a9f25d06dc5387cfb53201fa0 7221681239e07f9604d5e68a46965faf97af8c651600abf993177a340f6e88d3 113159560276fff26c42d020fea67f3d02536350cbd7b4ea36f76c70c300624f 14152448ea110c2a7f6efe4bf7173821cc7436646378634944164141e862c083 3f85f4b21ba09576235a74bf59ee99fc7690159934ac709639927a12598de4db 0ffb0791b151164266c3f61fee62371ad4b847681e39f11545fd7e79c8049a87 deab05a92357a34e87684d48570d216eb3a600a40ce746851bd80e33ec1c68e1 704537fe1c46b6175756a847e8a6c8a4eac68c3834e18f1aea4159e867b4afe8 9432b7a32bf0e82599f4c89b837400ad18bd09a29678d52f9ef0fe672e5db9e7 72915931e01acf984fb517b671b1c2a48bde0650bcc8dde11ecdc957deb2ee0b f0abb70c156aa44e30f7ecbe678f9ee9c0036c8912b737f31356714014a28026 93af6cfb7d315152248a3f5832795c53ccfef807bf889c9e08d7159ba5c7bbae 5cdcfbd85daddd4f1342a440b80663d03545d138fa31afadf45f8f97d6215145 bc67d0bbc9c1e729334eb1f625be3f76271f67075e080ff2101f608cfa6c9243 647f856b3e4a7f5b9f0edbc3c2086a14d97c4cfd940804e93e7fa38d4657fb8b b04035320466e030fe02365fc9835b0a13c75e171dfc1fcbcd058af05fe9a193 f804d2682dca7dcdf909155f817115f585dceb66b4cbcc513460e48dfe2e0ccb ca00d1eae1ad641fd240af58d71dd5d1b360773df738f76475f9ddce0743c053 99de32f96953e27f7fc7d6ace8082625adad8f875af5ccf98271211f6ffbf168 cb72c37155f98e712331a709f85b2b4cc137c3065c93b9a8750612e0bbc55797 ac942c8126db13a0a40d133df902ded357717d0cb8791d9c2b1b62586ec0e7c7 09e99ca05570543f80cbcf9c6381e19e8d5f21c00d96c9d04620219b842cb88b 6c754834e8f10b4f7c63b15b62bcd51232d514d1cb6542d44b84a84ce6d35c14 9cb2a9c1e1b3d50718d06faed604122745d6a0c4b7218428d2a40da6694b0b20 37fa13a595721d0ffeda06edcf2a9192aca945e8f845f39c850361060779bf8a f6a1fb231730587cff8331eafaffe84c036062f58c23313d0366d227f936dc0f c4352ee007fa39a2d837e554c96e3ea9c5f30bc131ee4bfee4691af41093e8f8 7888f2ce93dd67b62dbd401a649f2bb53030cdaf63958062a3afc269c65aa1ae d4beedaaab33b1ca7a62d8e3922a9066cc57cda6f5f53a1821c4b93663acf2a0 86c01b16025f966d766445addbe03d51be961d39f02611b1be6d52ce2e65ae03 61f2347d273c611883aeb9d63b502cfbb03935e4dc57815f89b2d960ca5f852d 88de1640f8120b16fe3cccfc6cbafdc3b2cad4aad54cbbddce71dca7e5a93d56 234e16921e47d84dca0ecde65723ffac02962de45664eaeb48f886f502f127f9 a7cc083d50070f1f751506a25c920ced9af70758dcbc609018ea29d2bbd92378 2114d7509873f58a86c60bfc37cfdcfd9a9b3d6bcd9adb7ea2f872ebf105362a cd8022df16cfa6aaa2e4ba5a2a387ea45695489724e472b48af3002557a76ab6 8deef1f124f6471ba33742a17098f6bb74c0d78a02ef47d303d616e393eb4519 48b56089969f9016e90b1a0aa3bab624a76ffd2d5bf7f8938269b114591141b2 9f18576b44e23d3c53213b7b7e4ac62a106282fa4561b3909c2e8576dedf414e 6839dda8b939921fce2234d2de861429ef0e896e8bf53734c49a7d9f9987f2b2 b52f6b08edcdfe3b6c7913e9da807d82e25a549e36202b8a8950f0a14fbc58d3 558d9906fe2fe216003200d96b368d4277f950cba6ec1949be6e42f0bbf522fa f369d7d155899f1fb4351c2a580c78ba591f7389ade0a8be48104a149dba7f13 06ff79895fbdc3db1d298456ae015ed3b7d61ebe3c69df56878fa9d6bd4522de 6e90d3ac10d5efe134def9d541f0d840c09ad7cdbc80e7ae326c132abdc919f5 b51705d06714d270bc2acfce33937dd15cb0329952c899d6f4304c7476adacca eea364ab4655adc1d2af1dac26b24fd8a6554abd57925dd4bbed807d6c40dc3a f815a1d1b99c386ede5a04765bfddcd83bdcf4d3c43cbe2eb768e9064bca8bfe 542eec4353c7aee91d9415ba2fd07311a3936640f91f1b061f1a1fb62d0fdd0c 127 f6f5272c51d08e7f2454fbb8213aa3aad68414f224bdcd1e0fa238ca82565a0737db268e942b8221d43f6d5ad5f751e01d3864fe74c79fe973a6dae825862c07cc550f75dbea9f1044f346c20b727c1e2e31dca662203da8878d752edbf2d30d84a121f2d7cb38553a2b6d9ebaed085c06a89e2603eb0cf7e73073dfeaf9100f578b6615edef6ad73157a48c635c1ca974cc0ccdfef58df188ca036bc7064209af61c971ed8c191256bf0563412f83045919d7829a689bd515f113dd76f4ed0bc231f97abecdfa358f1b2c2aa38cdf661413f4127dcd6312b36840c4b4db16035002fc9e92a5bab000d78aeddbc23ea79b04044c457266f908770d3a1190ae0be9d330cc701054c5e829810763157646421e9600c96030ae9ba1b65c6cec7a00ae260fa5592851022883dd31d7bb527512e57b7978c10752c90dd5b9ca84910c4599655f20925c01dbe73d7824b8d96cf59b0813ec0f2d17535365a4f125cd00df621e6bc3bbf50c57c7ac08c48874c0c6d5b96ab3b24f22c025377260e64b0cb6b85c55995d1692049a9fb4b85a20befa6285ba0005b6f272f7ea52488c9002c2c99f17fa41261bf5eef9e0378abde20a562d9c9ed0dc3047e947337550ea0112949780af154b550bf663372363cd9611b61c0ea6138b4e6fce02216bcee503839b440d9e199636a516ecfdf0a3bb61ae40cac3b8f965a2708fd5cce9446b09293285edafdba94dcd7630e06bd7f15d65b01d9e9cf6a9202cd12a96db6c830317f950ab055d9eec8caf96533802508c07a4e89ab64b73bea2c83d8628906a085682584a09356cec579d85c62b891431532fc920aaa713474df0f992c9464f0b9355e2f41a7ee0e26fd7c836012d1c6cbbe5b4cd4da0cf33e4040fc2f438b2016912743580a0d2ab9f6b86e0558b356778aa2f08f9043f735ea37b826ddfe2029484ca684535826a460fcc3b3ee3b698cf08c8ebc7f8e5ea773414b0895f830bccc2633a7ff3f73350d99ecda55303ae712c9942a9c1c6153e84052077e7e40b9c8f247d4c2b84a6dfc34ecd70975354802f8cfcdbd528122b210f2c4e15830bfd42c45dc9a3db6446ee242ba0208eda031fa6fa028d3b56cc37b14e2110880f16fdbf0d85a4fd50e26a0ca5eedeae8df2e88b3c7699d57b9daf18b1946f1a00061a75b9bcd55c5d04fbee6353f0e002aa24321779cc9c05e9e2a305be81e00dac9f8dfa9b1300eab133603176e4b97acaba4958fa18a1661cdf97382cf46204e5b6f454f5bdfbbad171049b065dd9b8181b06301b1dcf9fe37badeb9b238b0756052a6d5c160caeac8a0ecc84e0958e4d9569cbb2e7bf0189b4f99651939a06d30accbe9e34c87019d24e6621fdce5fa06196b6151b584054d370c0ccf5c107edba400f99f70873468f72a31056a8be38c4562825402bc674af096bc5670306137b0470e771b7a1b3e5e7c98dd10d99d93ae87f2379abc9a485568b4827b200e992660b0aba8ba239080c46c9f81c4abffe8e9851812c9397f4cb7baced450f2752189331d2926594927b159436b12d8aaa120673c1e4719ec533757251e90b07e0964caad10de6618cd27c815535d12d900402f00f766b6c7ec4c8df8bf60db4b5fbbcf8dc387a6828e1fd6bedb3f577fafaacca60ae124e8eb8d199027a0d2fd53964fe753c0b22c02aaf67f7050330480ec675e9e7d8704cbceca66e9d0d87e6582b7ac5b8f2a72d497eeced7e441b9db7a2bec6fbdd32a8154337bfda0482b0c935ad4fe720bacfa874af01f4375441eea1d2aadb2a666d90ca4dadf20b6108bfe7d794d5fad99bbc8c96fc58c44b7a597584fff96ef9ca2a31191cf102e432f92a20e47c898fb778dba7fd5eca605d431167d1a8ec67a8a07ef061cf0a0ba1adca9bfbce010d94fcc84e3380ba5e91b1389e0fd0577d178f2bef9fdb0efe5fa661963ec5f75d709d829c23029fcad65d229ac575d690263b7d708fc50a129a04a8ef845885cb390c1240b4b5a9f91bb5e7bb55071297c9a1fc9261b0080ead26f8188ac0c4ebe7813ab5cfe0579940a8fc5270d06bd090ac40ba663c09e43bb9bed41831d2642ef2478dd4140123418749b2553d990106417e5ad593051b2b21c2710fc3cb572ea10401c1b3b7cecd75aa859f4f3c81ab25e318f7f8086bcd6b76f3c532a83d67c72ab6fa27d5c583e6e90add31689a97ff7020f1f406961f23167a25460e7f59f67f039b2ff65fe687bfa4833211099d37ab8907fc0cc0d6a2317fea72da832ecea55897f8cae9fcf9f53381790ed7eb0703eaffc207507d1240cbcd8614317f6cf3ee5d8ac6365da5816685a6b2913a92bdd2b99b0036ca88f66f1977e7fdf35d0becca6e21c069273f38b269a510b65d06959e720865db712649429c3dcc0344b6cae3ec645e0592d211eb213ffdebb8a15c0f8f09278c8c2b6e0df86bf0d2adecd7cbbaef29a043d0d4273f499126c3657ac397041f492383154eb1018a44b6b91731a710dde36a94c31eed10d1f2271293e2ca05a58d0b258cf7663baa635001224517fe0b2181961d0d988c3c352db63d4e1a0fd50468edf239b6052c62fcce17fc6fa7dfca201e09423b332d82db8dd199540e8bb6c8aa9f0be4358beffcf6cd87b0e7ef1a33afcd617e5d1b94cdff69834c0695be85136b5d49c063ac2b09b06abf03a45698e0125ab938cc2448f1e1118d028201d602f8294ea1a94682fcc8e86d9a20e908fd75226c7d3ca761c78f9c90068b16e334b0530ef5fc980c8ce52fd8126f1964f9fb40a3cc1f84aded8080740573cb4d3fec577be13253d7e790de0c57190774244348d28bce8bb5f395f10d0507a2189ed7c500d5b8fd26a16a5ddc5f06678df168a5549f5b3be5898f24a50ed94e8c841aca1fb02f2dbaa74d07518f170dfa67a1c364d3e99d193ce2ae120bbdc028442a3d83d92813fc8364ad96216ce029474aa35e1b4f47744b7af9af06eecd6547628b2737906c10de34cdd61de2b3f30dc1c6179bd4dd6dbc97c1660f156b932010ba9be9606ed98d63fbf97461799fd1771208645bc384b992b0ce0378e9ecd4d6fad69fdd36d1aa789b60917b46bfbe95fa388d25657ab912717c0d9caabf5a2010c0e0d31048e89fdb72c02556922a04bfe49d568d360985da360576e4f78bf949ad04f13df9fb3060437d7c39f12aa7e373960ac89511eb49470ef5d9dba36cac787ac18ad82d6ef17e2342661122d93887078f054fd0d1ec580a7efad90580186b319445d40695985d9ceba28f6d2cf24ca84caec98ef7a08a0d3f853f7f8409bb2b75f573266df603e76c3bce920245d1a48d7ef3d103136f0b3001e074374100ed373ddc5a32b52fb9cebe98cc173fb3c26b9bcaa9e1df880e529b1b337599d9243ec0f1ec8dce857cba0d8d4c9ae0b0a2be67d57a948114037fd6b02b7c1cd4a7f48bb58158e959efe95608f06ba39ac5c26b81dac2799108e907f0ad19176d2b92ae91b6bb765ee25edbca1ed61b722350fd394cc518040b8af75d139ce28cc739076e52f6045ca8b6d956e5d054fdcf443eb747bdec6d039f36063f87d29e3b29c593d5072b63d5677874ea22b5127c7c4495a85060550eeec8563ce78a8182a190e23a2d17f1147b29a87464a0ece325629b0de7c8b60db316c071da14a4f261391b6887974ce0395f9a5507cbcedc8145197b21053c0b70b006aec59af5ce8a7f67a8e6290987a345287fe1c095755c69172a899a0e08c10fcde691aeb320caec3dfeb291bc3d893a77a6a59b1df837f71dbad054630ac6d5a3b7f8da3200bed089078d78a29db62e66325d737f0076c0aa724bec250610b4eed9f6152be083d56fc480b5d10166ec6a769e692b0cd0bd1ced906368025fd4bd1c4f24c8cc6d2d7668bd5e33e858b71318c7d9d78596e753d536c9060619f2d34b3237a75eafca86b9de47d830063a981159cf8d9ddc927a7b7a21fe0a68d25467b6e3dbd08c7923e8b431e1149c09237ff983656a8dcf78926e214e00eba584507a4321eba6fcfeb88da46a100cb6b39235e7ea4f1f4b6c4b7738cc0356eaaf013735b2fd615cf3c741790e9132617c4a5f01e7359705bc875489000a5e39248f8b8923f8799e90ca6cc942b94bbd83c43941d0b10ede9b6ce0c97700ce736a399acaba6e86bc2efb5bae695bab4f63d5bd55af52360bb02c4a10fc0564047a8cffb4e4b9b3c939d7331b4f17ca5071b24851c1bcd42ada4785b52e0a1ae3954fb75862cf31db7df00265c0bc85426c21e9f5996a789d45f56e35c304fe5063a297ac690bb1d529e6fd4ad9caca5df5ed74b1a82ccc7655c6c5cf1305ef906cf807693044a7fa18a2f432286693d40577757dafbe9665f8b5fa69200774c2492237e705316331f5a624d3400e4e7971dda2c5d4cf9f112f67753bc90cf86f09d26b1a9ece4fee6c6005e1b6d9be8efd92c43824f470db90e94763af0cc8aeaa0601a4f4b7f286940235bbb5eecb60796dfafe1f58a53f566ed4c1df04bff2e17e3dd053a89325943da3685cc01cd0671b81d7890ade28ee591e98240c3c97bc5ddcf320be785b8f3e8f5bbfba6bfaafb65b5f4973f7ac763b80f1c80d76752408a19982d742492daf4dfa1079323309a405685c25c8bf0db264e72a02dbbf683f785744fb9d49e3a0b0f3bc4abd79e8da34788c7c4c9a0d75cd09ad0b308c3f9e869924a1ea21b4e0404d322ec6a0eabaa4654da8d1d72375ba34010c0cf4b230625c002cd48db7258ae08898c00de27a6db101e08995e608a6b7830d5b1e0d60f8089cf0c6056a0ec6d53d56461b681b0af3b0073a6771380b92710a7defd12fbf2a821b13985988458af7e6848b21af018ee3003345afe072bf0a0c685b4bda91a0bfaca848b854ee91e22f107ab30e9af064f0326c92bdc8b1c1025cca3bcb692866578f69f498c130710274d64da47d0320fa8bb8088a15951f0ca0a46abece0a151ef2996c3f359f9e781151e60820c9215d45bd29bcfc188402ce1f960541d4967d04f3fefaf06a0fadd21d8622a36896daed78cde05ca9a10ed44dcc73301c8410bd83ee68add1407f268c44d501aba7039e03b12673245306ef7bfb910d3f7c53bbfee36fd8850964ff419db6b144d99b740638640468de0383a1e8b75d666f943b5f640a5ae0443442a76ae0daff5ab06dff374577edd00469382c476ad38c8248966f702284ff6357a320c17ab5147dd654ded11eb2020f51aaaa2afcb5be03a90fa799e53d94d2768b3dad2bfe3d3d020895dd08869903d78e554bea74e08ac15f095d189b72b2467b365c76ddfcc8ac84855902b5fb050837eb69cc78ba404b020425aabe290d683d1adaa1fbabadca63a44f69bea90e42f4f9f7809f1aa1ddd76906f9f1da1e9a21dd5caab197ff0c048cca1aec290db5b1f1fd3cb20ef4bff26b417de9a754352af14ab44ffcfa4b8541c4beac6e089ea0beedbec2fdd8115ef3b9adf9388e35cdf597196d86bc0679fab663b7c00728ab5373b5b822215c6a8ab23249c9e863b7c72ec29c1b1cf9fc964c5f2ce605b65062a1d546660eb74455a4584959cd66eac8ddd39af96d273f1f21b0a6c808cb9a5c0b9482b248fa98a04f546cf0f5e177125d137ae4b223ed40531fe13d0f7c265c4f1494ce3ea449faf5f416af4564354eb23d2c5ce0fabaeb2244b0420ce1c19c752b4a14f531574c851e4002fa20bbb57405ff19fbe48edcfb2eea6d08a6169e3ed737fc2739d15d99fd722bb76f6ccd49a6de5d0a2cb8833f5288820898a7358f4165f5fae0372f4c857e6cffe477e2bfd42f54848e9196f18dc9fe0c6dd1480014dd1cfd1edc84b2c7ab3df7d7b77e66d8346ed9f1d701ea8b66350ff919a35ec6bed8324124a21bb567369f979deee7984ad81a9d4abb931d1c590c44e058e154508a6f7e5d8bc2d47657c0863f8f00faba53fac0f328dbe6764904f7171500dc91630d7691408f36af7a36c521a39ae7db3e9ededbb9eccffa9f0201a6d22698036497a9bd9af50a2907dbb9fb5b74d9bbd3676d2f74f06bb6500bfbf9b3113b9a1a660813d7f4ab733d6270dd78ba376c4fb81281386c1616d3011ee894d15f41b0df104ab39f9e081e8a66428f9fcdab1b747db91b18353c6d0c7ad4c4be69155d31afea6b5ffa1d5c07544722602546ab26f357eb501f5f8e0293cd216f24a61e600d29a8447aaa426c3cbb8e23cff63b72c95cebe1601dfa055d81e57dfcf7ee3336565992e8c9007ee5adb57dfe6fa14791c68d8539144b06369dfeb7fefee359122e8640668cf3781f13c32f1e2818c9b88954f4a3e0df0f5cd9a1c909e2e15c52673808680a917bf9a8eb6c5ae4fec927661c1d2f63080b4fe29b8e1cd3c872edecc42229a8429b512844c3eb2a2293f1bebc87900a9b0c43cb43e52b1b94e1d2ad05770c89d56c7253b596bd6fa9fd678fe372c4b38a09a530040ed0cb575afec3ec1312eb467af7e7f12638f5355aa41f2f5490346d0db5615192b833523409103857a662cd4fb09549a927ace386e4b56829d937410b49dfe90e1b335f3e94df0d279fd8e9ea05918e9e47c06e057ec5d2abaf6b1a0355b7718580bf466c2f1638f9f1ae6180d3de3158dca3f0a3d1db2a9238d9700bb961ddb1ca3c094279a872e0b1dbb54864b56a3bc644c6d1a73def1c966236023babba52a55dc7fe4e20a7bd2f02734ae38c6d63074327406eb0c2732b6ac900145d11743d7c53c466dca4fb94f539d917375f9faa8627a88cf9e77d8a51e90d33da02857e8da7f02394c3a12c6056fab7f1a1ed17b26b3f08f47cef6b58e60bf5c2942e27fdeeb2aad46837efc1042dcf14c39c93156395bdd9c4028f26ed05baa074e27ae32471222d38455de395c75af840f30085db30f330bdd4b8b1960ad257c1847a5a1a184a2f3afcd3e501945516c030a8b16d37d9391cfc550af80208c7d821db20b25a5deb2a430ddffb80a4ea65a63a738d01c363beb18769760949863e1271c39d812e1067384c50a2fd66eb6491694a81045746bffb1615cb01c77761e32963cf54330714d55524a498832f338065f8a6421b9722cf05e1270a28e2a6c54c3aeeab40ce7177e1d398697c192c3774c9ec8e3593f6bee067130c4a366e51e325360fdf41709f5b6e75a26ecd4349409871af244f9f208b89680f7bf91af4becf97ec1c1a049e5e0bccc380007b4679986dc232b62b85ecd6f105c71450705fa92e032f1ac7b49f27e1be078dc039f5e678fe2731195a20f27307e4303b096fe9772d397c20fc3f19c1cd148609701ad90a6c567bf3bdc507a109b6e45d36ab4c78f27b29a84274d0d52e2202427b5863fdd958c723c51057f20288b0b8a93cf95cf10841197cec5db2f2491535e72026325c23dfd14f6ed8ef0387a12ba95c642a3d198d8ebbbf0eb1de63d4b481d721de518769d0eb79d90809b4844ba44c3317e623018efdeae26e261d0c9e739a5c266a0e8f4eab15593100d577e005c6095f0ba18b2da8d5617d2853bf9f2afed1cf9d5a4481eab86e940de066f2ed877ca8938eb88804de011c14d48d740d47efd1907120d01179a362026f7bf35a3bdb64aed04d2ac4779a0faba8e9f705c5200135fc1ed93924db780295b3a2d9ba83ff76ede97eecef7c8df3e2d2b6808508628dd07b02e3d95cab0fa694555f36c424d754a16e0e4c6b9418e6a4a1bf37848b3ebbc2586397faee09a1b7aff4fe9567009a24209f21079c2b28d96c3a11cf47e45c29b7d98b01780a947ad2e2d43a2fd2b1b8d4e6672af2565864074a06c5580152da38cbf13ce50183239eafda1e75efc406b1830b3daca498e1ee2b9d4a0b298c2f1fadec1f08099a45a7f6637f40f413842f9c7e97d0ae25c59ae9e67e7330d1b4732e01072503f2ee1fef93160b5f3555f5c79c87e9407235198dcdbb378eae108c3e778728012b74cdbd81178ec8ca4dcc907729da68aa45bd89021760143eb74a2303afdb0d85228fda3f71d7317d801e3c36d381de8a5449c58e91c8e74b4a40f8dbc34f0932e36e529bfca9dc7d900b68fdddc8ebca8540ba98af4606a54dfd63442b900760bb60f37d4502e20b777195aa3b9ac6367fcbd24517d68c635067ee72c7a004222ee374cb9cce3dfae04908c9a831938587d62afc3fc3bedd7ebd4d1985900b2ee7742c9759db20e5103a408003251ba743b32a609b6e4d26c4c3539329b90837aac13d5882d3f1cddb23ff159da0324b5bba80584955e25cf74743cf0358029e5173c4abf7fcb45b3f3474ad5fae005277830bb350cc2ac3ff23022f9db500761a4d7c865dd3879e70f9b95c30d33dd3f5eae15c6438ffea0565c042b61403238839bbbad45acac67c7b2ff31639c8fd940ac5f82e2f924130671035412503ba250c182f0757b2f03ef3c563de668f216b3b47e5ad0b338f0734351ccf9e019326de888ddd9e40ae7a9cf16be264a44dbeb550611d638503dbfd367c6dce000835fa7b54ff314f6c7d5ea3c86dbb01f8e600bef4d212c915e39ff84bd46402ed8f11207a4dcaedac8302a3398fe5c49ecafb8f16d69aa87074694b7ffd7004d0a0b05e0fba91ba7eab1dca90b2e504d4c3716b92a3a5792344eeaf7c67800f88ef4bdc37ec0b8bd89f13f8a0d823f2a9eeea9857bf5a58e5314d7dbf1e3e08676c80988456341c0475358d4d0606ad1d65cb5ef340367d9ee055788873500eb5662cb7c47ac9fabfe1c28d71f1a8daf2390d71959db7fd31adbc6b1c6b2606b6d6114d7ff9f33dd8734f1860276d98d43bfac59171a1a4328efe5724f12106a104982e892c3b6859673a1aa0717a51f8932122f1623f2aa8cf3af9e8ad3d0bbfcf2169589266f138171dc5fd4006f8d26789b89e77b8311452c0d08a994804d292e4cd9d0c82350091a198ec34ac08e6a290d1a5a01530b79ecb2095b99f05fab30c12837c0ef97938c7b9c9f6c83495a6fa452ad45eb308baf37c11558303607ddf4471169bd91b3687c71dab024ecb88d48176932c2e840928e2f2017b07508af8d56189eb156493e63c4384cdb6a8a1ec78043d517c43b8d06c32c5ff02407f6117a8c102ef670b616d068dcf557c66b04c140377ec3ba5a9d1cd11230f3d8e6bf14eef37e3d2adc17e3e8ee8c3ebd374f6f3c64fe6d90dfb2c7eccba06a2177eeac7d16641ab8bee79eb9d506f203f643e348c2beb3ce4943d28bf4a0c4e9a67536e8ce38ecfe6a76a24d72f9ff5a7a7bb9dedc8d70caabbda5f16ef04e792b848696797201fa1cde6519d9eae1ad056911566c62b40bafc0e50c0020ec0c8d282593c702f2d09aaa782a341034194906ef0529e48a31c25a024c49e0c96ce4fadc96bc72e08202636ca3de7cc9eadcccb1e37c3f9f6b19b2df3cb8608e4c9ac778cbfc638983a79973f17168421450890221a725927812146afe57e0f346e84a38f3634549088048dcd645389fc3802e3386cfb5b3034cdf9904e1f0e567bd2df52d7ba5580dc6b99a738f3d64979055e4f13915ab582908c12a9e60a1a60f042bca9518c9c804bab036e5b45993a1bf1cf8ce5f03551892ab398460d437e72c8f301bcd9e9a61159b6a5e0bafa7d46c6c908c23a3902fc1eb05cc103ad80b7306fd55d753631589887742ee5611a147ba5b4e01a671102e12c895309097e045a6f80d7fc456d501e6d85d6e8b0efc4a31f03346d844467a6f042e30bab627e91cfca7aba0f2adefff8916f4608f16c28d9b8448d422041129832cd01c163bb381f696b0504e1d5a895443da2a606521b443934c44e64d07eb33eb00a1fe0d0fb1f79291639fe4bfe4101eceeaaf4f32e6a241256a8f843c97c14ba07ad64446868655f4fb78873f81e388c04286277f9ab1c620966b4ff2cdc7acd0ed8ed072e45b7fd48aef7f7569aa8311a19721b2793db09cd4799afaca643bd05da67356950a26836259c009420d81518a54f7debd7b1bf1570e14f11473c6a0bab9495700c5a4aa68eae805c57482a990e9657aa169d1973b9140b54632d2c0ef4d08934c09dd9a2604435a165ed47a27b9422951d0fac8cf9691ed3643f460be1fa096b6cf3439d46074891329cbe5ddd1a8748448873ea1e705b3ee720b50613011f3ff0d7bdb41ac162db156e8ae50f991dd10c9cab055d6aeb5eba58830730c767e0574887d79e58df086e2fed39b9538a8b8128bf57df57a78c6b971200f6a776b5be33ac2bc9242b4a65d4f5fa249e2b788ed808990cf010d42459ea06038df864091398619b2600d79aafd88aa3e99f40bbb1cce8ba2b305c50680e0d5ceede4cb5fea7c327ffcc7a9a6971bb6242831a2281b401b17933318cf5fc0ce4085772d797bd0d5c67b0db3d436aadbcfe4341908ba1b663a3b7b3c0a16c0665f49a03679da9909d84732a7b481af771fb1f3a172425b189e58ffd898a1f004c277bbeea7b0886f13bed84cf27a497367be6d4406e7939e3ab878d6cc96600d520ba28362821c7e61161ab8bbb90f770d0d4a08be8b8bab1dd68219201600c7315a3bee80212e24b16d8ca0ec6472de07726ee5796947dc0987186ff4b910751cdddfe4bf97da4767ba5cc098c606c7553c2928ae06d8e7fc714b3dc90b2009d1579e5253688b050fd10e0643f8e21b4390c0b7dc94a75ad95d727f417ae02030fabf2b30d59bd0f2c3bd1debf741d6287e19a989e6ccfb7d677c31d7d2e0c6d49703f63aac66123dd81ebba7bfa2558c46fe3cea4f97920f7079ff43ec30a3a8985904607379f864d700668e0855000d03e95324eebed56753d9d575e7006eb15fbbb4369263916869299b96a665684b99b43fd18d85b0e1642018c00e90be38a4b08893bc4edad8145701a23c922586ae398012fb4dde8d1176d1043050ad25f5784763cd210e58303641b9d42bb988ed9e738a228781da76105afb0ea0be9f31104bc65f28847d0fb25db9171a5f24c540e7b5aa0a737d5a9d7468a5400e87af021e9577004a8240a65287823cc13d327d603bf6658ebf66c8b6bcfb70f3cdcb4caab4d515bba51bd982670fd81a510a17a8c795ccd9c75890a785f83091b07cbf70d1a7c42f4d914fdeecb81004a41ac79f737aa7917277593f510eb077c477963bcb9ed7e345225ab6f08ff7d96b48543e48f6e0e5c6dd700fb173a0e5cb13bb26b35d0f01f02b1665eefb50d684e6957e4bbd9bc7c49d05452e8e9083270b4311bad39b944309d06a457d360f8bcea6a12e3793b56487e83679a8505be1a1e01baedf7229f1a387bef9fcef9ea88f3383047d8259430108d0df2f20737117f584c047ce37477d0c6427f18e353d06401e43df5ec45daf6b9e405d40d5f087ce513d30f284fbd47cb2bd24d853396155941c1ea0484a68d651b5039047ca0723348881f2c7ed69dc869cea6ae34b5c8e78176211676e1de6e2978e00248d8b06414b569ef0d2506f4c1cb672197a63c2852f51d20681516f512c9bb0c5afe772d9f7ec463c95f2380c4aed521b9ee115ef9fe72a4d744fac2ec86790f8ec3935737a80b9ea172f0610010858314b877c714becd2846cf3a77c7204d00de2153cbdf65a00c510e88817c8bd36c659958335c8275df2b64a0ed531d490eea214806e57569773b395f1de784b9760d721a1fb01b6621e59239bbf65e660cfc3bd18b943e13d8f3141508c1593d7c4154f4c03d139fe5e437a94ed715d50e54861407d588c70710ec243319f70844333810db88d39f846233a913c56a4f01e3165268c3c2381a7f4387eed231dbbd104dd88e6c7d12beb04fe9b2151dc807cde1efaf306047b51c1cba7d4e2aca517f63fb76947678e597512cfa9638610289925501b11044f779bd89a28fc078faff70cc5a2556730f57451d4f938dd10c761bf3f74b54d16a7986dde2cf74d8735a4e4d10d0fcbbc34b3b11f3221f2f0341842fccbc5317c243a7c7e71d04fb9fdbf77d62a4124c9edb387bcfda2e2207f7c1b80590ed0dc17f5c99213e62fe333046e53a5f199804bb113ce591116a0da14138759d1be9d78d966b7b7b76cd8e0bf846a90e929d63d98ed6251be5e60467e09023caf72f15b5907a87eb7a2c1767a9c5b6b4875654c913cfd9b414f60c61b042042705a0fb4864af34cb3de603246d193a23bcd28685ca36e7df7dfc0c879640e4196ba8090693e0799dd4e7e744bcac839b5c0f43a376039709016d03ec5d2e4a800606228b0d3334b7f2af41c383f2f2744461fed225332e76f7e80afeac8486c6ecfa8fec61fc9413c0b46ba83a8e757f3c7af9fffb980324f194013425cb1b0ab66ee3d4ea97acf13dc7e30c28e99b87aa0c1813e3f34a31e9790198702e32d1fef764baa5815a43f8ad47305d01fd5546ea965edf1fa2eb07940081e383b0d8f51d7c92c5b40fd9280049d802667c6b6ca54db5eb0788d06119016a5a0ff93c3606ff7c8ecbdd5ab2491895641283dd384375b535dcce6ae1670372e01c878f54519c394998e89c7dc05211c954cb1622d5a69ed2250fef7de0063da98aa80bd252c2eef2de3e69b0c7a491769b92dacdfaee6debb70425e71e0bd0e9247bd963f2f0da2c4e89b2db8271e6c7d887fa11b8ca1fab0dc7d0ef8508222e223daad8c6c994506c17d358880f5e659d2aea50ec0a2f6edfad3fc891043dbcd783595dd8c2f6bf4cdbb8785a9f23a02a57e398a8b476507082d36bfa0e4fd218026ef7fb57191f47e204212f0b7678fd7d2fc6262517d74dfa482ac802739d140871c445ab7ecd2e586b10ab534a1637deb06be35d2c4cc1037128b700e16bed7f18385f34762c706a05761698714d07a06ac144b6c33bd9a1b57ccd031a9d5979a9a0c6338636add6fd4938e1c9862f4efa99c57165986171e3c768076c52591db5adcb2116e3a7ec40704674dc55eb8bb425024f451165aca11ee3094cd39d0f46e81ce7cb78085bd0f7209acbbcf098877bb77a891bb82e93139207057a2c8280da90a19edc35aad99ffe53a8537d3fcbd688906b94f0aec0aac6020fbe00766aa389917604db0d2fab72d7a1dd226dc40e2c8ea028be4be9fbad056b1e5991814332c37b59e8f9803db4e5e112ae8eac808b144f8647b4aaf806046dcc70f6a063dd9b4c353364c3007ff4fe4ae201e8a09a44a71dc9be05d5440d56da880d131df7c07182c6d0f4771ef2185cc3c1117e6e27c8b8c028a7d2a200f67a54c09cbe831a11f10656eb29abe70865a58ff5b16547b66e43d9eba55301bfac7e816e1086d6aa5d945edc47aa2dbc3a05389aa5ef71eb572a9bff765e0fa99eb8a787e56cd76990a887f0797230595f9b7722cf846f666540a7b6cf4e062fd4d13c92ceb2734bbb3f9e6a8f96f0d8310ad06af7cefaf1a6b8fa1d207c01265e5b2c50119661793b1cc203cd1fdd7d4257dc6535573460769e70da9d880ed5a462582399d4598704f2447d55f2e5678a181383b880f8917f81ea95e24b0a5b793d39fbc49da3eb1376184f89b5d48e3f4902310af5a17c3e997298febc0faec23707682363d8b9ea42b296a753e1c60a680e9f322fdd43119f289ee6fd0f442b239a2a8f5573315386f4e3a3091fc828db38ed8fb2fa7cdd9b52c2d7c40091304233de71dafa3008834f9280024d64e71f1caf8ab56959584f0a4ca86f062fcb56937b8c363dc0029dd5640bb7edc956e5713cb160f16c470de501af3101b06cc4bbba50ae95ea9fbfc2307b773dd17f1784cc9666b6e12d0d76e4866a09a5e711a12649993fa2acfec8c87ae7848ddc7c19e0202760232cea03b2a3660be2442c50595a3f6e640fd6baa44aeeab598e23890ce9aeff723045a439e7aa056eff3f136a7fb6c1d8f668cfbc8381aec6e502888cebd59e86be130f70ceaf0ae99bcc212cc504c1a822615356dd59b7eaa2f2006a67a0e2784bd57bf13ed90711f977c7d878d8ea2cffa7fcfa0802857873c9f06c3f549c33ebddbba0d75307da9fd4af0ad22c9affbd884d3d951fe7ea0231edc769d4a31a2ca2ecb4d83d00b660769c4416a6a442df1b6b4337a00b26161a08a159d38a988b6bbf409cbe0a276ab86eefe55531b030f88636a1da4a49b367c8625223a021b34234cae15a032088ede9e297b984dd15dd9cf867852d13455c92e7acb814421c1d58b9ac6f05b8483a37ad1f03bfb44c8edbee017793791dbe4e7a8eee99cd9037c71444e80b3ef718d6e1c8700b7e4febf9af0802e995b9193c90c482eebc5e648223b70707e3937b32605b460958b1606050f39fc8ba8d509e2ec1bdb44fb8abd9e086d3077e284e8401d8b841f59b750edcd097ed6813eef543762b4fe8d57c837e73c008a61f7b1b8d79d6ba12b1149d62b04ba74e26555809f2175b0239a547fd1cb00d803a1fc30dc63a5a081787ee466e21e5548aed50ed088db550f9807ecb51d508c91edbb5a03bb916fe4ded89a4494eac0c4827a3d0f9e6d83c701b7c024feb02eccc294ab17d746af62284a19bbcd5246c334dc42a47859463b1d81f5a4c5b09ddef8a085401deaf6a92bd0abfcd7d5917494a7393166153dde6402404d4b00dab3c9b2f8f49ab31d44e9ac2a30842843c40390d92d0d1867e0110803b0e490c7cf611e6c1a940fa9b751f52f421b6be69da012d0776fd6fa0389b764dd63b0f46925671ff31c16487617c103731ad8f4e9200f8ac3d2846d96838d07605ee0a61927185da7faeeaf41e94965e85b1b61826fe781035011014bdf4d57f6aac0e5db1d12c6eeefe5b8a1146d4f3f2722384637286c8397d8da307e60986add30899b97c94311a3011bcedcc8a4d9808b3b7e01e24e734976b6810f2bdeaae110539a9b3765f8711d25908266824982f2696008ba5eabb13db1962c0ebcb6a2d0128771967353c97a8f3d2f3b5eb83506a66bcba62e1aecc51d701e502cdfe62060cb7895e73d9538e4223bdfd5f9b84744751b49d22150175b434e649884a550b1a583b02280ae89a3debb6392499dbb7afa07e9426f93d729cb30546168ef00ff4300e49476fd32411f4a9ab225be8a0e8981e917ea0c66b29b219b68ec98504b4bfa74e6f4a079df903fc696deddab0554f84294ebf615e0e2896fa0410e6081f44c4fa89cc57f9c879ad72f64c0a29294d89573278ebed4cdb8540e1b1930eb292c28a9351932f919d1822cfd5f9925a27601a805c62004a6d07c305cf2904581754da372bb1eb7a4e098fd72b164c94bc77df17dd129e037c195e8a45350bf548dfd637b2a441e3d13aa1bdd73931fc76063733498c12441389208a31320e0f03e1ab2bdd4c4264916a562d5567c2a7cca1896ef63685bdf2dc2cd493e80192f688999c983d4966eb2e4a79c12544aaeade2b68193ac1008e16207cd63907babdf19724c32dff882558a3d88a31e92746bde83051fa5ed97cd744ebcf4e0770fb70ed4f7f1876660e145cb04709636a36a47adf0724582c43dccc08f1cc0c25a5d6b3463c120eb9a26c0c1b38524f39c57efb00a41fa0e4cfdcf299996803d414b588ff20e9544a8bf6a3e192035ed080d8b6996a1036bc97516589816a09be4ce86af24e3fbad7b8e36092461a4769bedda2f052e24dab1a6fd21740b90f7442f46ea9f845705f1a6230c67cc476c386c4cc705b7df09f2e2852972396064f68bb7a89b7fb511c637d92bbb418809c548744b33e4a48eca2c436c0b4250c24432cdcb38a5bd8e9f93de511584b25d4e0089905fc7df7b2b8bc26a6dc830a6a086c3c008c24360947f56c95694002da7c19214a3343efd3bfc816a244c608ada515200e21642c0bde287ea3561fce1b550a5b07f8975bceb05d1eaf9335093bf549ce7d8db9133f415b4e57200b43fe72822fef269ccb514a27e86af55d0c403ed72ee1708826aee2a6fc5747b73d839a72af63e01c3e8beecdab49e37f0389d6fa5566c5ad7f2b7204ed06409c4fc7bd9891eb4a9b2762ccb6186f6738065b7149a343029a5677998b993842c24f99086c80826de1636e895cb4ea529408af6de27393b35d724106ad6df6f9d55da7dc553931b2a8cd0c664676bd7cd80e7304927b2338edefb4ac744cea67bba59882014cd5f2a7deb155bd13165e9a03d09e25c3ef33cad96afb67c8d7668a07c7efd4a5b8fa2edd9e5768a297cb070f379580cf977d1e52d2ca1b61daf24a5ce80f656dfa089916a902a9da8c279b076e193cfdb98dd4a726643cfd32c2d926c1739210d3bacd4d6f93d73323451f0525592977876e1d0da311a6b2a7912ead066f090a8aacfb1449ddcaaca3286502b951e1bdb5fd1035fd825cbf397b558b665a2f5ac91c03898845e70c91e9d202895f7bb57a6cd561752f8f5ebd03fd1ca406be3ee19fe6d0d09755b7ed69ae08fd1866ef43621706bd2003c795702bb5151772b7bd3543cac064d3b65acca10cfd19210f992ae64c6389eed1c3905af1de4eed95e257ee8cdb2eb19d6f76dc06530bfd8a3a9d36fe1eb093d688bcc59d146c1d9c5de5eb6aeed0b43a5175fb033930f539b022addf12951d9819afcafd36c8a89fcdbf9c832119796f5b05230fb0cc5a0bd1c7a9b831f31a4d44a5ebeaac29e94bfa6099057d5ee05b7a54b40941a55703d40e45707f616c09ccf95a2785278d335f08b03df960ff97369d6800df3c1e27ee35295a2fa662b05e844d21f4dc319ca545d61be3732c01daf17b0503ddcb047282427c699c1fa5cb72b0d4c156dc2d5d31952e29b99de823516903714309ac840cc4a194abab1d4d370c0daaa26262a0c467398bf8c492f3fbba0a1e00adfa80b22310b65efcd6a8ca1f6070a12a74e9b3d1bb6cdc2e1e0cde5a0cfaba84a315ae1ad1aebc725205f10d925278abf3aaf053e88d95a924983cc10a20224df24ba4209ef7a2513eedd9a065e9ffebe3cae6d6c09fcf73c448c86a080b2936b8910e02b2c0ac9a0e19dcd35d8a2a8b72b1d0306f66aed67875f0b30e64bf180e8c9996622a50f41281a39b401b8c40cb00bc5ef2c8a13068a93da409b43f5f79a7d933efe6664837e1b7d92559b3b50847f71d87a127687b83f91b0619e3d2ad152cb0059277f9d221bbcc1e46d36757523b5b8256d7cf0c3f63ee0353b4f35e9c8b1b1ad97063370ff034e56623ff50ddafacd0d0a83140b88414087130eb92d138864af151615850ac692de53a0ccfa76d8b52bc5613a67d068e0d3c2a307ea6bdc7d3639b99971f94a0c7d7844ba75b796f1bb53f919d9dfb580f238817cdc2b4d5d6dde99114cced3fb5c780358d4463642ff0c656cc2fcf03025b95d9f07211d4c7618d7578b9626cf2d432bfa7e8a523a933ca0b5098e3dd00ae9d9843bd62ccbcdbe9ec51577b83de3355b8409f9df755c3d158dcb76d2f038a0e96db5c220cb20cba1064db7496301a0e876e563a385762b02afcff8e0f014268acad0c91b5df656be0af1054492995fdcb9d5030d4f3cec4b05e9cd3590d3b57aa520ed47149d5a39fdd0ae41168ff0db03eb46d4996fb41769691b24802fbcd8d03a02a3600ec20f151dc53acb43ce49cf35096d44340d18471216d4a0f339cb39677d5608f1788ba30190c000fda661d0df28b76966c1acd077109520cb236a7aafde0343af9693f4645c1b9b5b22f8dbb045af0c08a0e3661f8a3c1038cef8a1218be58327021838ddcfc032b6fbeaedf8476575acfeff95aed5d5f011154814b4ab400f7137eeddbb45f311b6e4dda472f609bba3633e69f99186305eeb293c0b19afd542f67efdd09e35efd3953bbc1999fc0444e94da0e232ac20572fe2abd5d3742135e85a7323f0d15540e890b26b1a9e3a426fc2aefeace4009ea9678e36c05c9ce9cdee9a1b31c39d6cb080f41e11b78d71f0e6365cec8c609b188a19dc5b6e3be592b0887d371da701886e5aa688438d98f0e38dc24f9ba052d1e422cc8093a23500de0945531edbf2026205a93d3c5a1be946dab7669710a8f183ec5df11d474411e952c138a26b0306ceebc71924efc8a1a1987c9af7e096db3d82e56fb4df40b862e455cd5276c7448bbe49f7d8f4c8a6df97168afa40b20e30e1ad005451fb88f7abcc5c80a115ec131376c868ad72302eb98641ea203610d3ca88d67e238833084249a04a5977285fa039ad1b2bc555aab1ac3ba2d077881438fb75f4322c2331bded7a94ced0620b0ecd0bc9333ed34a958555949017cac51cbc12842f17479432a460076cba44f79e7a2ac8214cb42c03ef4fda80f188c02823ad6e164e70340cf13bff49b17d81f8b324aa41835ea00add450f30e366f6906d09a32154cb4b4108c0adc78b29d0297636202a8093f4617a5be6b091d9c71004ff9a9d80ef062da4d2fc24dd3116b9d28a9b1493d92368f0cf5d60bf8237516b36d6cd93fd6f74cf93c1a8bfa5f07663bb494a53629e6958ffe1c0f692894052a574c6dd22ec996883c7aa4f6ba92f0fd16f970562d36994e3479014c3280402591a4778338e11b262d8092a03a95b834708a47d313297884993e0db4701d2b8d52c3b6801889bb3eb337683ed94c6d52430aa40359a743c7cb030d25cfb0aeaa122e45f7234360f8641ce35e3a9e556120cb8164f29edf8b249b0904e2342371e7acc03cb54891e23abb8ecf31934027720fd96879ec2f01fb3c0e7130c26f8b4796f71794f829d007b33d821d6265a3c52256d89f838c160e900b534c8492855b9a3c396b732f6cebbeceea7bbd45d13f45e6583477a3ecd5f30fc26717574be178e7b88491248b4bab741ac8648aeda84c788b6c7514cb74870ce6c73d249eadd3864c674d5ad07061757b71b8455386667ddf99f9cfd2012904a5ff2cf8e33895f81107b921a403bad6829eecead7759dd0848319cdf24d3c0f566f170146390e66944c7c30090f89772f26eccccffdf5a55329f4f0f6b99708dbc23cca128087e4614148dc6cb4d140881a447ab05b0a81eb990d478766be037029e717883a2b8d086058c7982be9ac8a6b4285b9e129527d82a3e2cc2d510f03b5df875f98d64912902a2391f2130ccf51b38049dbf9c09dcb129e177c1409c535c25792b5a06d9c04bd3614a24678af538e62733eb8c84b96da4334cebe0b007e8920c587c90e23c016aeab216f4f2686a48420dd27535f6604f479062809c6bdf4c89ce740c5e4edb084c58606749fd8ae668c899b2baadcbfa04e872f0be5cb4fede713f963bfe26bb9306cb6eafd66cda1d59a9c01b03908e67fd6e6081e7e63b6c8c5365cd556412ceff9a960e0add9ff593d5c93ff7de119009d4d0be9f17982ae291f4a484bd008988845f684f2396e081026fc0e2e389864586605a220bd787a6d0af480f87ea13f9da4f80edc734556e98a18a0f5a00c0fee3f0daa4d10c2fc0086092f430f0685dc74fdf9a72eb9e7cbb9af2c00469d25d9c90aecd0531dca4da73c37ee32e7a29d8eec597971002fd9f1b848725f7df62c910edcb2ce33c0ce5fe29a870a8a3bc6cdb8cfecf69e6d2e6fdcb78995dc7b400a075d0cab2ddc617a2b5fb1fb4740602afa055bbde4e255cc6dd8c93264a185400c44392912856cb50c001e778577aae3cd5cc45ed4ba415d81b0ddb620de598f02511e40461b530d2d4528143d29c6539849104e1030b161f274d28f398bb9bf06f7e485f08dcbb24079d2891af11a4cee246cc00e39be0ecff091db9accc50406459d589a094d071a48777e0e67976f936f17d9d2c852af130fda59389c5556082efe0e1f82379993ba1b78ad9d74f3b5e3957864364ac1abfe375d53949f5e0d154ac58f75d82542c9a353506bbfb43222acd118919a50afed33e4479f0e3d0cb56aac4e16e3dfd1796ef25934311fed6c63a03aea63a15bdb90929819bf790e6a8392abdac98bbaf7190b5c23e0f9e6a1b17278f63c25bb3b4883eba7a72901337e45204e438fffa2f9432aa56358aacb1752b7762f107170f63e125743db0e71e347a6a372d42088437a82a3c8c822299cf53a2d232cb022abace3d9d10a0279cf36cb7f22992ad1c932332c4784b34b6dc6280fcc5d5450fb1ef83f06ba03b575cabca822f0f2619e6df17754abfb17bef65863ab7b9767559e030e7f2b09a495e432f207e86e35bf5511d275c24fcfa39e5c33a3bef45fa4850a5f754d0b05f8da75998716f11f2ab3e239d9b92414e68aa2514f4ce2c5432cbfa6b7ae0c88be1edcc887b83eb25a24fdb45444d7c2d80178657bc2965860314681bb6f0a47973946b7971f7c0fa30414ecb1ee0b831797029daf7ae7d2a9996f1c24150f01fe5c11c52156a489f24979cb6a9d81a602ab8d74f41049b2f910a2d7d7110472b0ecb0fff0977172881c3863a317430cf4b6f0587397ec0b551d485f448307fff4d0dd5a64b68a51246df2185d5e55a192c9beddf15f6e4c52c8af6cafc1082cf0822be81c3e6106f20347bbf89eef97977e3ff36b373ed5a5c240b0074a054739634ef47351f23b7f9b88e532de50daf2688afe8f3486d3f0436c12e6540ded35d9e359b031ab6fa5894587b310caa37c388f292898b59f5bdb188b2149042c102623e44458c0ee65da3eeecb8cc414fd2deba119a3d63d98cff3c5e7450e908805c2feecb5d4a38b30d064d634a826f30118c758d128f5ddb456412190013a113289a6f8288e8ffc52a57d76ee2773572f990fae8885f46236a501654c0c681ba1a96ebb0263413ccc676371bce12bea4aa571f75007e0c1bf2fbd5d070f10d6ee56da9e33b666f9aa1bcc65e77446778e36b90d73fac0ed234b99b7cb047e0823ef0810bc0df0d112fab6cb8adead50546c9ee51524303c5596c278ce09ca7bac9adb097a5107e7d12967b9282837c0b3a2fe23965995ed99e0afd03a02e48176d2520545458b1f97894cc12013e935c8d4c6b3753e722f89d27871c801fca3b2b28b74834ef660436aac8db385ddd527d56a0cd1281238ff12063c410f36d0e69d6c833e0c5506c3c6b74b7cc89ea809652ce34f8f0cc7f8716c1a650381d495392f65ceb0088a21db78c17b9a7071a4ab44f524a03f2a760b3c10a60c3cbeeb5917879f9e16576bb728c9ed1f81cadab42b7445a1c3717e814c413502f249cbfc3cce057f2b81ff8b8f2eb881b485e0b85117670150a6f27ae08140030b744d3360273cdd55a3b5b6e61f3a2558921f677c641226eccb0987311d4700fc18c5e054cdd2353278441734289f43eced9da67adda821906ab15e6d2a7a0331ae751bc9a24c0a7fcf50fd4a3b0869bf90f32ea74039028df67ca5f1a4af06c8e3b90654cc103164699e2557a0e70b08484d3710ec5eb464e09afb7acbdf06a2384ca8a5f7d20f8774f76f8953c9efa1499078cb5522dcbd388785c3dc6601e703316a8feb8248fcb4168ba07fbb84cc5f8c7a53fc216aa5fb8ff5326ec60ba8b52ec669604eecc21bb1d9196dcae9fa11be70ea815c810039c8dc7768750db9968b55a1cf80374cd1a040d3d905fe37795ff48540aa5cd692af0e5685cf042165352d19e2a18da963e2651176dd89338890a86e03142685a6e98c44a0a208e6b8ee605a78bb905de42ccb197b4e35a5aefec5971b7f30d31f782307d2820dfb1f8523fe42af6c77eb4c03d1d5750d808dfbe69eb66b2b3bde178f57200c04b4028fa57fb748566f32f86add2c36dc4fbf21a7466cd51c1e925d73f312d20d9054be0672bb3884618739ff3a1edae980b54984f3dcc5c242bb34b3a5db6c0bfeec3fec1eb158cbe99a5b1b20f3b074f209184bc6c1a9c37f510631132ba90410b7289be357be0d939988323fe8048efe4b5496f918acd999b993e9567b57005e6456035e81097aaf85ac6f79ca25de0eb12cc36a30153b53a085454386610c595638d714ea3b53e767055cb2baa80b2854307b68df1580d045d25ff54cc00c4ed60b2b14d20e37a8d31c7006344dfe6025d2f4300315135d3c921a1230a9044f8e3d52a2db7ecd35541d49c94a1de24f669813dfe40fea5b54526c317c4701949ec3b4a38396bfa5f85c42040d1f5bb9c2bcb87db3072df7e2ed50111fc10b539eba3da5855afea320f3aeec539445a962570d9e234a7cf155bc207f97f60ff50f5fddbb337d8c24a3b8b9cced609eacafeb6b4ae7c981094437ed5c61e70b1b2f9186074046f43f58aeed909ff45d26ef4d5d8f8624ba8978ac93360f650d5cfb71737230c505816f1d1a819e7a7896a3fc0cf3c768ef6b3a1840dffd8d064e684c6e660369139da4ffcc213fbfdb0c400f80efc6a3d71a6da7d02c20200c624aa3e3a08dfc5bafdaff23c062ea5529b3c9d759224fd28bfc124bf7fe1b0a3b1db8a825b89888b305199a30ef93ada4d7328877d3214e2cf731a13f854200cad72002d8a072cacacb7c8c45d78f63d7781beef1f08f7d1a60962ee432ad02c8dd50bb503a47d1c7bcfb9c94fa17547add3fa2df94dd70b5e12b155443490c152e835ac2c957a667837dbd33229df6f66d94ea5737e538136ca0e34e8e13052563ce91fafdfccb437ed12f537db1632c3c86e234e91baa7f90904ba3fb4b08 -generate_ring_signature 1013e6d2970665fae054a3bd9fe5e1ed9e80e081cdb6ca240c0f517f1b415cab 0af5247217901d271584c54159546c10a1d682cd243e66a945af30b5eb427cd2 2 8eb838cd7d2596dde1caac7f8c29e081333098096355a3888f6cef9ad54b4c43 ecb9686dedf61fc294b3c96c56ea43d6e57500ca683d8ce93e4212bce07e71a3 f36383ca3516a2e053540ebabe435e3b57cebf3890478f221c4aeb0b8bd4e30d 1 5484e5a1a5eebab7fe9c5ffebc40638130b616c1c0e871f738111a67c932250159a2df1eafcebde2368b6d7291b768c20a68f940daa05fcc367fb2a615f3bc09fbfe3e0d111bc83ca7f45b95d327c42413c3ffd4bd829327b72bb26c9e767b02ec6f64e6fd42859876c8e413adde1602e0df2493e231708871d470bafa019f00 -generate_ring_signature 0b5ec78693ba8b68d4c52d569772840dda48ff5fb748ffa833e5392392c55dd4 be1f92e110606c4de9745e00fcc25187beeb7caef967abd9c355cc032245326c 2 3957312d5af6b690f318ccacc696d12ae70a51a5e59169a823de76c16418908f 4c4a89e48bcc7beb356d78e9d9455a67c53f4624c53254135d0f665562c388f3 6360f4e3a558da8015355552ef2b95fe491529953bb454449caf53a3169f6f0c 0 39446c0f44183224293aee6da91cda0f8549d4f9a6e97bf25885d6c27c54a30264f42140efc29fd3f9cd0ac126447d81b63b9482d3efc9ee7e53249049f1510a9af989c77712b05c7f140163bca32ee53f45cdc7e154f9e43d5bb42125f557035a5dd8a275f82824428f7cd221d5498c4eaa93d37ead3dccdf37fc0951b7a80b -generate_ring_signature a8ae168867259e89dfddb607d8121f78d9bd1afe3b56bdf7f8d44f328c407626 29c15d05cf7408ed0252e1d25c47b8fa0c34878017937a285dc037fe48c3d9dd 4 38aafb4066b703586c33d7c055353712cea2a8fc42bb1af683af4d52194ae229 e258caa68a2c25529b6d845e6477ddd241646d89135d3e860f9138582b0e2156 fe25ca5baae2ae89f703b0d17d0e9ab8c314eb69ee1b5ad3ccc2f178f7a13a89 ff91b9cb17606444470257f1b2520fd7c7eee2e9f62fa284d96c423fbb32c32e ff3f205bd350797a39e072c715c24902a909dab05fa8b7e3338d2ef69a85fa00 0 0d5b8e10f9212477428a4040ec94961378f55b92484cbf1eb216323e6a7e5f0d5d4bd9f066e33af0048007d98781c7591a91472fdaf00048eb43be05f12ef900e68928686d330670987b84b71a12c3245d2e1976309b5e669a9b05fb5601720f38ab2c3814697d6bd0b9aae8d91602cbd952274ce4fd09c96f6e7ce4496c6001a3a4e04163dd315434bace9ef858a959fc709e12256c62068a866eaeddbf8204137611ddadeb5812a3c965e39550d0e2ba2ba93b11c1127d99946bfb80b17c0e604987b7ee0533d46090cb0264fef70845ef779d667b7dbc4ea6b32340730d0c4b71db29fb59eff5b24e1d157fdd12b65e61e4874fcdf4a5246940c67be92a0c -generate_ring_signature 6f7c9d02e53d619372700dcfbde7105963e017372fbe2918ff0331191453ff60 11bbdfd15b4d972900e7d088fe7971daa6acc8e8d97e2414e8f44fa0acce27f7 217 a9d2c0e8a6674d829f4d758c0dfdc0adaa073d9ffa6456c2d06cb7ed9c7a7359 ef1c7c48c75f1ba091bff82de93d8ff68f7bc31da2ce87c8569e7443d359c5f4 044e3b84c6acf627a821ab990f7085c93abd290e5930767d6a177982d6ca67e9 781b4c9fb9e32d73d2d1b963ce415c90cb1844416f7dd13280e1146ba1fc4e5e 05d8c1d8841d0e5eff67f665ef58e5aedd799e1b9949443cc414932ef536fd46 7cf07260320c63fdaca80f7b8ff9eb61bb4f9a9d3a27cbf0c93834cf93fc259d cbb0202ac483c7c3b838c1fd4ca2f1bb47e91b0fbe6bd10b1e45da586d6ef64c 25ddec4e59d2ee1da3a0736e7aaba1969c8c4baeb25b45f7414ecc3a39f94e98 0dcc6715cb35ec3f1d7808ff671b2433657e4384ad77c6e24f3fb40ce407ff9b 207324c43b3cb524a6cf244595d44d9a9fb6bc5dee499308b95ae8a226feaae9 32e51b3211ffb05469bfaf5366e9818fad3265923f4fb734acfdebee7c183342 f3745f3cc4453c17488dec37617c06e24c7d05bcfb9449c21e93c310aefa4a44 55cca614e77dcc4ba78cec6c46f38d3d0172ad2da45c4693733b845449b7211a d01bdb20dda9148e2ae0b71cce5ea5914848f79e3072f0b248ec7950fb0cb32d a7b51154c60f197d723af16e4e0f324a901b4b26393a71669d0e5a621b6a4c26 038d389b297f53b1d35e64b92e579422c93528a82caa3742747cf55212a7d9f8 9255e412cd98623b34f764d2a55c443d3675ddc1d67e70af7d3903cfa80ea18b 0dfe3c5dcedd604a467aa13cc1ae316c1f077eabb02803dc06de657126484f3b 5ed0e9819d6e2d0d113f1edd978e543056ef6e4bc431f95f2076d0d2fb475d2b 18ea161052684b291829d5246f410d2a10844b60733a978571e2aac29b8498f2 7e2e83d2284a89f30052c7d3607e88bf658f9fbb1bfedebc419fe3aafcc484ac d7d0b95c8140094761ed4460afb84bac314b952bae09bd0031961209a56791e6 76492fbe42a3e2e00f6b98c207bd06dc8a2b9211bd27154f2938fa0e81d54589 dd2d108646f82c50e2e1a84de94cb2bf50d660d604182dd87ddf620ed3751c7e 43b77c3b8b7b4f57657194ea5c26858d5d60849b5c2fde7b9e2db9b2593959af 68d833ef2995aa4b3ecd512361d4f99c912d20e152976be8471b18e5f82d7a5a 80ea13958354db6fb72d24ca091ccc979e37e8f5e866097a199f726a15ed0df7 568bbc6de62162897808b97c17cdcc6bc1986534dd5f3e48a8c39a0c2a5a345a d052a818e54496d2db412bf4ee41ed0152510bc19a0863a59def191336be7393 e9202d3178b1ba5cd5de88ae45610a543418e844e9b99b443292218dc1abf21c cdb6149924a134413884a183d5d5e4f88d37a7c7a85897f5d7349ffc66571910 64066a9b8f720038d5094cea5c59a4d87f09a121bbded687e2913561b7462d3f fb6d221ac1fcf65a9d188165549d595bff987464ff5e99ad035deb282d42dc93 a4ee1970e64f9e52e882efe800594e98f29e8aecf4ea3b662f95fab5b9e94447 ff21f495bd4634f38c0e1e162f3946cc0a593f7c738833cc83737a3cbbe2b808 5160ac5ea648b08a8219878f0fe2a2dead686c3ffa490bdaf76f5aa70ddc8474 7d432689aabb6ad473dffe72c3fd10f332fc667806187a1d0523272d69671da9 17e4a72c95f54d277c7ba2bad16f634ee82bf403c3b2af475acda08042017fc0 7c8d25f7cb1a3c7c76eb0f1a0afcff5e0acd6bc497c99c2aef04284e58cda7b6 a2f0a4e90c503240cfed6db5ebc3730fbe73dcd04e083c5c74e4e992b4bfcd19 61731b0a82a84272a3484abb794d41f8aa35f7ad7c15eda62119994fa82e1be8 9d0cb6dcb296c7a1d9f315d9f3cd1ee319a32cdb26f6ff29eb60864d1653435b c57d7d5187cf78f06a2b4192f4b2af9e6e3b5323f1923d520d675ad716b67e7b 66865357df4a203d0365078d80e8393f91157836e16592ce129aff41de009be4 6fa3380a808f73acf4636741ddf415cf2968b5c66822a3d9db9231b981319118 4705319d29971da7992ed65e5edf5a5d4ab65312ee5a555f92230dff85a8f6a8 84e4c913f2f98cdf68913c688ab2660ac1f77034c2007fa33bce2832450129b5 a2d9ef7d02cea31f517947a914a9731b731ed66c50eeb27c152ab8f3cdbe7f78 a4ebe351b09a08e8c9f508938034395f032d7992a67671a6feca145caa354cf5 584b6866fa954938d5a134b840a801dd0eac1a17c24e45e13f4566bde3e9a140 5abd93a726c61acdc9505a30eebd91df1453e1d7cff7d2ec334d986b08f71672 a6931ec1d2b21862f1cb935fb0d1b52791d8f916c2afb9937b51fa2317f493c5 8209bdfb0f4967a4855efb9c48b019d21ef2d17d2e768ec86de7bc57f36c916b 301e708d9fc079acf118ce1623a4d2eefd5ae3765883eb7ae06f0df59f0a9225 7da0a633b9c97d588d0c4f011db498f7fe262f15de189c77d0052e522e624f3d 69680b2e40a4ec561e8a753bf932feed7e401ab505e55305226121dc14084cd8 1cc70e12f5b2cc86a4c5fece7524a4bb842a4ea57944518d035f3f2f68b44b47 69a0efbd545b2662c8a6b04aeeb37fa58011570dd1133d95b47d544cafa3c81a 91ebc540692be156388b17ec9936efeaeabfa760bf334286cfce9ee9832a299f ffd00880cf9aff6051b7a16388171b8a2fcbe54862015476c77f7b3fc46d7086 c95389fa96f525e20aa521de82876391681fc1e62c92c80253f609775e0ad584 a72805faa42fac4965162a569cfa86887b8e6df3f9155d6a87d9f3c8c03c8cc9 e4f035aa88e869257fb5938c550db6d3400f4a1ad9338d412d04c2f60ba7c11b 9284397d95cdba29d6ea6df1609a48b96117cdbee19e841be496b79337d63281 012c09af03e3d3d7f48221672c5bf4e05dff3716d744647807627d9d7ed75e52 b9c9d1f834c86d1113d8536412829692e6794731e2cb85934f3add8ca5296295 70f4428a1f36c543107dee9931b378e738af47b4c960e2360521281ed01db82b 2245991898701a04d0702da058f30eac9f2eb869566bf5b0832f41449834994d debb66dadd879e7875cdd1fcc2e0c73a7164e295829ccd0af5ca6a44897e4ddd 3a094f9d7b3d011c97897ca7cb55c1e4aee5d2833ef5cb56a9d7c1aaf043e359 20072e748ddbda7f5a4f6a9f30c4e7a640997e5ecf97f15bf0cdb068c14d823c e5dffd9502a42b8638da63500706cde697dc42cf941636a3775d4ecf5f11563b 2decf150e5e635c47b67ff2c4c2f1c3cb74d15724c050b985a0d37e01e067646 8ab05fc816919f8017dfad54062e9f93d2f8cee3c011cc077e442df75c3ba0f1 5929f00cbc961bc693eb17131b6f89de73cd2137a6112d482346fdce4da3072f cd245415fca9190b3f5fa2b229f8ebca3aab2e084f01d0638afa99edd2c817f4 a71c52bd92541494e4a389f667ca59f34923911e17ef4ba923a04d238f89401d 8ae0b7bba43ec4b225e4829ffa00d0fa6f995f4ff93ce9237c645a7d7708b078 3a55518cedb46f2b1edeecdf56914a8f2de3605df30995fb2c331100dd73063d b249212b901d73152d5d6575a1ef5f27079ee8a6660c6dba3f0d70ab18079d5d 09cece2cec55abe14f6c5d3681e6a3da9e3bd75442369ace34915c8a725ec880 1710aa52ba925feafc4477ca73dec7dc11805e393642e5a444442989be1def0d b993ca971ea66dad353f6f5c338b6a2c8aecef15bd79ba03838a82c845172440 c9d8a3bcf7523dcc38d1a5ab4ca71c999310589e9712f54d8bdc13075d9602ef 12e8d6c4b4ccbab7ad98baecd77ccc8a1666474a1d9717e227750f22d6f46016 04a3246f91e86c0cea76b123bc08903dfdce13e5bc1710c656cca5d859148cf2 92494c362575eb4a19462b1b14067534a465d331ac233bd770adc155a0e9f805 6baf277853495cf5482fe08582d79a957f70e0a878e86bceaa9af967a3a1afdb 2b5fa12f48497ae1fb670b936287f03f1c473281dd42b594dbdcde4079ddfbaa fd9f84887a617768d79b3492844be5b8da294e3ea016c1e51bce26a36e72577d e7da58d7aaa13fea9936eb28114f9b7f0ef4997414b569aa895500c0afab20b0 5e0faad0e8d55ecad29d0ac6316e17bcc9eade3bda7aa3006d03a2e9fdef7e08 50c555404f87b93e52de103c405c9fb1cb3c19586a0b90422061c4dd513cb58b e6e9e2aed640f9c58d0e2645f8ff308af33d8c8e8124c0a61c8ecc9ca28dbda5 959d3c613b4151b28c1fb35569fd3d89d1e6d276af4030b77cfe5ee22ea7c11a 404dc708e03dfe8f28ba1ba88f2e5db8757a3a67edf5c430ef6f889711b1971b 12256a5cc36afdb2cde8d58f6b6c996cb4dbb3eabc9ef530f9b93466d53d99d6 1e423eb530434bf15bae5f8a7c2bdbaf7b1c10501a6609dd2446636d90a332ea ad60a07f8e4093ee17b949b1deb91f62e1ab72595402d45062978df4c3266819 1379f3a747a040ef4e5073b3ad4e33e8c31902c87dd3d61e6c08c94c979f78f0 33efe37673f13b2ad5a982ba809af30d7480efb4892f14364b1275f8cf4fbed9 d4271609be30b70ce95cf10b2c25bfae6eafe50af6dea2d8306a760db35eac85 c7d1569541855b69bf0546034f9b48afa641bbd532d38388e96cf1768b9af4e8 2aad5b98da163fb561c7595a5949383a6b9a0805f8b0e2a8844e045e11cfbc22 1358ce01434faf7c8e9b2dade15bd514c7e92c6dec4855c2d10683f45bc6095e c3e37be5881f20a1ab5ce33605713ace69020f4d9969b735dd84e6aed56c86ed 846c51c4b6eeaf711c7aab321c05262e21d1327d367bd5fe08c0e92be077c490 ece46633e4e417898ed86f20cec69668d6e04f5215f80fd8d9b7fd1f310c337d f104dab4913ff4d456ef784b0ee10a7bd79f6693e37c670bde2fff363f2a090c da677636d4db6c721915564b13e6b53d12ef075590f76dae676e4c53d67410dc 04a4fb6c35c38360ce5fdc268739e2ef6a2beed8ff7bc95460d62b5adf68f8dc 5e7559290137fd3d83706e5e7c1121883c359fedbbb94c8ca4b2680733d8b0c6 479b7e2475c7de034efd81859b61288b803c456684be12537de7aa99b5d127be 402fd78886359830d6839113804b636a85d473ead1920c9932cef4d9cea5c6f5 5cb4b5011651d2c69e636f81ca0d841807209d841a739bf2961d1480c4edfc55 d07f7d8beae6750468330d553fe1978cb404f4a1e2488c753a5d0749ae524636 7295ff8a66d12b4818b5f35d91f2b0ad70ccc7443130792f4e484a782db7f8e5 fee7468ba7194735b76a6416aa03e803afb3bc66077f65a4fc666a8670813a73 b1b2854a6dbc4cd826dfe66b8c34253af6c3860502bb629ebd8d4fe071fcd1a6 7df1fe7319b51ad76d1d6e9115456c2100b8fa74e46c3059ae65b32c756464ed a07ae5f7e8c60a6ee0b6bc0cd2b4cac1e60a964e98b4da967722bd3d03409a54 2c89e51f3e4a9ca6c0d283ebfc97ed96edbf16fb0f327548617e86b89e5f8dfc 8e6b6ae609a6940736bfc9a50a7b299b0274d9ccf03351d2a8f7694e398abb2e 2ea8b51ffa4de90f3cb2bb07ff59893aa13de7c32b7726ce1006dc88317161fc 904a28f7389923ee6374cb5d32e08197e899cfc066c96682cf3b0fbc3b72ca1b 729ed8fb818480801cb35ce3253ee767255cac0031cb70b47ce4388e1c28a3ac aff0ba9017e8179fff3df916b714c215b85d094907124b4ff5899450665b8da8 27f59c289add2c9470af149c956ff3b04f5c6388926b2984c24e5b6756c847c3 fec3cb7c1fd7fa60da89c019ead2d966e06fc052096442d3142226ff0fdb82fa 42d091f65225d2e064d979404ab5754f7ca4bad7c51406376fba94c4fd0b88d0 2bfb9b80fdadd222bb08bb790e6d188fc54419aa279c9b21c0951548674341bf 2916e5d0c9a9138cc0166320366ff1a1f7c1f491a64159f903e7a2025441ce63 405628a15b6d835366899c6daa9030494dd33216415a88e6d9645aed8c89b0e7 3b2656ab204b8472eaefa1dff67a0f1302d9aa9a1ad8f23b5481a685c6a856de c11e154bd9f80cc376fa95f3fc8fa3af606256855b354b639b4df67b8e8640dd 8bd2ebe7318b454747d500f3833246e8a3edda5913577d9871e7501f4c4c65db a720d5a5a7242952dfe68637045142b76dff814195f426dcc20d317213720e33 ecadd044840a168f7e83a8f2b3f67f5d49131f75fe3322cfacaaff9ef68a0e86 a23c3b773dc8374a0b50173d6dd2a5b29ce66b0d1d62dfef1560462e5a41cdfc d0a8fe4d361bff92a2c8d77aee367a097c301b1a0dd518cf136f8dbe5af9fdc8 f604bcb4374ee29b3c8e4041d27a08ef094ebbcb4ed19559f7515401dca0744a fbbddb30feff43c8798c2c6ddfe3e8b19ec2d3ce405e1f0ea1d6c148e9491dff 54b2dbdc5399e72856119bf552be5cb3974ddf1a7de015d7e5da1ee02b0dfaa2 4eca7debb202e342051c049226f8cb4767442f13e712d3a1742857e3188fe879 829dd2aae457f9465995c79a10cc1c03488a95de1b8dc12ee74ca66325a7be88 ad6d9c33f993edb38182239144b58430aced85e701780364ae9faa243fa7a217 e78c8e16cc112e8b526ae3496bc19f9fade6fa6778173a88dd0bc18f7262e2c5 31ea3fb778c29313a09ce9665a52949dd6ef52d9fd514ace880300a6f2dd1f2f 8615a6a3d70967d960dc0bc48e8ea0ebf59d8b39a5cd8a99266288f4e8316284 65f76789b071a4e9354db6f980cd2c35f1eaea62e32f34fa1a7e4b341606ab3e d5f40047e69e7b5f819b276bc2d277a11c9937813d5924e467b8c9bc81d215f9 355b0bf3c48b6f3b738c8562887e0ddf6f7fc04d1456d202e6ba02014a4c90c2 d137ab92a2881eced4293511a819679cbbc89008d21075ee21c6bb5b046215d6 86332fbeb6b2f50aa906a49247b09f207c425f17f0d2e7a8a2deb585bbf0eaed 58bcdce587e6eed7609d388a55b05e4240a61b568e9e5141591ce8629c238fe0 d6097f96caa48e380a7ad94df021698e525aa113791a2b8be91a7974d29de2f0 a9cae6409dab5099d26ec34a41f9d646663cdc941ef0862ecd384d27cf2e9a34 2751d3a661a51328185df4ed66658f02393f90c3350eda059a4c71b9d1ed9f67 a989804de21383e46dd2155ec0dbe2f5c127f7cd97a127ad4b7c76f017493f87 7c337941ed522a8f61149434e903942c595e0bf68a19eee809e500395ecffe04 d531d3a090f7b9feeaf254438852eee405bf412d41c053023716198d98f8d0f5 625cecc397c1b67441730cd1701986484c2b24b5c32ca61321ece2c4283c6a05 9f0fa0d4e8999b7adf27f9b31824a7c309b23d2be2ee83e851df8c2b660360f2 407b0bfe39971b9e0037dd79db93d164d079f8e00dcb8d4085dc8b41f91772a9 5455a1f8e7e7cc1374f610eaa089086fa7446610e74aa8bb4afda37715091f27 cbcb2b6fdca0f6e72f741e8ca88271c52d913d93784d69e70f16d6da7477ad98 db1e3d9df06599d6485e2ff371d4a600b43ccc249bbc6309c3f9a36de1f3af1b 406725971985265d7a2888e91b955ed40f4e3d1cedeacb710f8051c53cbaf49f 8b28e249da7f5c9280c01249572cba2e6eecc970a93bac53bcb4b9c8e6e640bf ae00617c7b499f288834e52a64504210be9fa398d113ef39525d6a85ce757c40 0677a6fd22fc12cf3dcdca106e05ee8fd18759b78598eedb7e176ac44d65e2d4 8e60bf4afee39109eea9edac28875c31f30e6e280d898a00f796d85de041eb6e cc7249762d8dc1bc2cbfe83e5a3a28842a48e6bf29c4e78c9f115cfc27bf8bf7 a6810203173aa88357dfed1f35beee6d73e38da78a7583b329810a06c46dac5d 431f2e1fe54a13aa3aad164e339cf6463b8190db5f5632d4c096b08e100246f0 e03c6d93874e0ec2c8ee0d238382040d455a55dc0923fd0b2afc1bd1f7d399a6 73b62b31b6ebcc9937dbbe4ac6907609a68d6eb4feb51f7e70afcc912d22623f afde6010128e5d4fd46a0c2afc6d12b4216b51e092dc050097ad9cee3b6148c2 cf660b8abca78a389af858c41ca235fa127cb86098964a5dda309ace3ff34c32 f74fbd3f2d3da14032200763a61edfb019f6a34492184702cb800ea889bf37d6 e74dfa1a4004ddfac92d41d388572a5f255982d40e207189e2c1892dc5af1130 6bf7dc128af4e7c039f52093b80cabbf0342f923cb372712fb012edc469607e8 ea3f3eed317815434b64a8c02647bb49933a341363351fb463198d6bfdfe1ab0 bf607ade73d9fbdf67d6f66f4757bd85f8084a1de1a5411217720e2875b94722 91d0180661702425c83970e04fdf5bb86511516c400f6618c9f66e60fa79b70f a4175d3185abd7a03ad7d139907322418577644a7394c77cda9092e937a1b401 31f2b49a2f3df0b3966ea20984843e4d40df5d3a115cc71923142d2cc9a5a339 12cbd557508932dad07402d9fe599cdf290d8e13404a7f0bbc30cb0e8f6fb051 e87e1757f7257a30b7fa51fda581127a5ae9df6f3a63c79ea0592b63dd431d51 624357831afe4f7f4acac70c457280b1e5e3d3ceb7d6642a7c5062f71bb73df5 beb1b43f58b59c7926aba3b5a873c614d008ae6220a12623680f2e7d571f2931 61ee7bc796acbfa157a882721938f4c6a38ea7c5780bca69f09d11bdbf4c6bcb 6be6cce2d2daa1c1dc937f44c7b290880f72e849a178f0fde7c451bbb16cc960 c6701e6389ea37f45b9faa73b44dc412c43e15f63827f73253251048d0d1aaf1 3bd90e4ae4ec59c20955a8786436fe323545d7d76dd86e977fae235710c2770d 86e7e8fae2623b5072bee6585705ad8c6a35467053011a29a2902bddf28f2e97 f975164d0117adc42dba23154292e0d9907eb1300524f9f146430763f27fe1a4 b1f1177dcdb89c3330fe6137eecd4e3f9f613456e32db51fa3f334882640166f 507565d88391e24f45e3219a723a2201a02c40c5cd88b3e16e7ab8d36d3f0442 682acb51bb734a6c5a8184f716a0b2bc890dd14d80a268d9ca697cbad6d2aef5 d6b05b529283e658771e12cb8db03e805a6f377515d2ee11ce71bee3f22b3f58 a3b057a1933ed0381d0cd89166e7b2cc8c3613f9cdd92cd109d86b4ffb842490 bd337f0b6ac1634f12c067493bcc741b21581dbcd5eecfd1386b4b50803a5beb d46971f3d8b4f9fbb71a71cc887646ffdf1ac95e40c8374881aed95f4e60d6e6 8a3249e79c08af225720d75c7736a07fa6cf863eea4eaaad647788c43b8f4ba6 f25ff9ae361b090d43b63274a411a1b5d4536307bf4c2aa857c3d515ef26335c c306224eb6323a16ab68eac94a38649236d1124f55b7bdec67c8961e411f1fc5 fbdf0163bdbb52808c79b0670c091b39c906583b379eab71153db54af0fa64db 01834dbe726bb20cfd6e8304bd14ca1f2ad2a92c6e0676640ba2306661d886d8 163b7b5864dea3f7fa0a7205004588c2f58326f0a93ec6f4ed42db249b46552c d4c93ebeb66d6eafebd24ff97dd405b61dabb318122177de4b20916eed1ddf99 68800a101d30377b7cc7ec21e5e5ba8f31098a1426f09c5713c59838faa86a1e 697c8ff36a824ab70fdedf3b4890e0e4d767f4894c7a4fe02753715e4e5504b6 169089c3de0a304c16958b81bc597b22424e08e4b44effcbfdc53cfb7ca32592 f7f4aac8edd8081a5d88e1bf2a1d8af7fc495f279183c1cc8ae9c2a2559acd6e 102abb0de31c22bd64ca47ae288a2ec0945640c9d8736361c8e7e5c70193bd6a 44ad04132ef42640626b75cdb2e4aef4bd6f8cbf52b5097db6ed3d89cf980c5c d97cb6a5a0a76ded4893fe31663fb9e463d6734281adbff52fb386a34c14f60e 109 2ab539574397ba927cb3765db0725c77fcfa104ebc28f5cc7df9590017f50c0ffb69b18235d8aac8dc6ae5633bdb798125e4563374ffe1101f3091e171c05b0696e527af64a6f26f5772c5e761662fd1be77b5a634cc90aac53560348d1ab406375a6c25a0637011115b19fbc97ff87915371a465a4e7b5c5cfc4ab93351d30d03a7f7eaf533d1a565b0466c6677447ddadf1917c7fd74d820680fc45ec44309b2eaa4afc831c86f5e0b6739f3ec3611406493bbd856bdee63bafbccd3d222079bdf9224f907b2932091c14b4966dca07037e2b940bad1f771349a8688019303e279500b5341d9bcde8b026ac5bf20adb4d863641b115f91cc05de3ff5b88c017c17f1ebf944b3ffe9cbed76cb5e62c4024fd9edb4789dc5242a85024f10400bd5e08d49c0da204e8fa386f0684c76fa71a0e04e0e4c85d243c35bb862e92502430d93b77a7fa933d244a3d5e1454f5156eb33d0afee52d5cb6ecc0a789e8a0a1206cf0af1a2257460156ce57d259ff26d97de532a85cfae7a32d9ecf6146a0bd90b978e139942308728387b664956d3c0772cbfb0c21166227af1ed91d7be087c2d1db2d674c9b6c31228ce3bcdb7749eef5be76a58493f55e4e56f6fa86209fa93497763dd4d43bd51c9e297c1deb3c45bcd62816c07319ce6a570e741d805cf4330989568c73cb019078b783ed9cd28f9ff8eec3fa2fa593cc75367f0020b904cba6412c12559102dc94ee4aac8a6a213c7f6413f9999feb72beae3dcf40b3dc3e3b6629e25510225ce4d4be09b915a5061ea2914dc90156b99f7b66e76049c0abfdc7c1da5ad18b1b7b4a5342a0070861f9d5794cfedb180445b926404017d8538feb0d26d31f2e68642a05a9842a76676f24813c79de2e9aaaa7f77db01ea67345bc597f1eac0f31af9af264bb9a3de2776f40fb96c05ed451b86a41f0d4f93c16e63cb57ff22ecc58b68481bee10ec2941f07a46973d9953b1686b0400b99d8fc707d2bc99c664860edff5c4375a0a6ee51219d96d1aa5b55142992f0b8f50d63dd0c7e18009b0e00e4cc5ff0a7e56727f8881d67a26372b85a92cd8082cea588a2e1fbf931f4511922d1bcc49bdcc334886a8cd2e4d42b30be533400df7ea0a629abe35b25d818f06e191de7576aa67604f087b3b593bc61ae30ab5023fd1d299aab64ac0005ba51e9adc25a0ccdfd61a9774aee4387ca5e08ccd940647db087089d6de9c507a5c370a9eca57014a955152166210061e6bef2fb5400a0d945ba0479d964e34a8321569d4ebbf86b5860f199a3c071a352097a3cc0003fe90986a13e3741408b5d2cc1d1e2dd4b3de0e6d943f7eea895af9731587b40df2d61cc1fea009fb5b4d71444a0062e54dd1a034820042a5a0c92329e4dd680508922657fcf444ab8cffa20ad32a2d9f9346c15e9113f51d93123eecf47f0802094660d26a37b1e572308238bcc0cd9d8fc6b76e85002912f36daf80ba94df0c41f1f63bacada9e91b96129f3bcc32ceb7fe39f8e3b35f038fbff14343617a05fdfcbdf0fd7c95321c2e30656d0dcadeaa0f123191959d4d3a940b75cb5e690c95f01b74b4e507fa357ea52cd17dd3909ad06738a5ed827ebda05bbb779b5d01a237b61232b70b62a386ee666a37e516da038d66796c5d1deb9925e7d38888076f7520ee2bfce81e1cff19db41e2e4b433a568ca2d020e63e9ec32da36b03b0670768237eb9f9f2a1e08823922726dba9e360876cbcf8d45392b3a069f3dfc061cae79024b95f0f0129f00ac7929a7d2af75c8934790c5cbcaf478ab9a1b280da048fd10f9b3bab48289c97c0b4338c0509e8f33f401519c19b2d6a91bb1a50c219d5d8696684568efd5d7832b7067280ce6de10de865cea3b9fa64fdcb5060a4d9eba424bd850bf3c3e3bdf86711b6717443fdb41a75a7be98b521ce4f3110e2f5e1923feafbb7c2f543b27465efe799991557b91aa02521e17903b3d9e890256d96357d42a8262e0753f78358d4e1d8f9ec870b721753c24c360ab7b96010435d4fe18f9033b4e01b90f2b474e0236e4d7e0f8fdeea3ec2ddf42c634b4f30eda2b4b57664a1feabeb6c5b830cd528d2faf4ffe6fbb5edc2df3083652f5300f00ce253bb745a9fa3e68f74c5c51bf76fed485f91e7ff87b189d5132853f7b0eb3731bedc94b8d44d5095a38cb5112615093af4a6c5c5a4055a1bea6c57dc40197fe3bd02cacc1fac9cc171b3d3c93d007c589d32c8ce39a6395bee54ab4c70c49ed8d98549c8ce7cd777195cb37734cb7c5e4906b93ee7dc030ca89cee72801b28ee0476a687aeb29892612ec89d4a49ad9113ae7d90e7f5104d1bbcb8db40cac1b7696e00f0ce928abf27843c3f510297d6e61771b54ff05df506a0b51250b5cc7ec66a96eb6628c114b76772ce95720f8be86e70db1ad9043316189ea3a0427f34696bfd245a14fc0de21c86b45ade67b638f262e9db2f1a2c37e56e9e70e7576ff2464ae7aaee52187953e75bbca98808661124ea8fe023133058caf320aa1dd4718a69db643e74434b2a95173adaa8b368a2c5be1eb9b8f9e30c55f5d00035c36f18ee46d4ac09e9c5eff16c4ada6ddcad77b4c8569ca691ff68555200a2b4dd099ceecee0b2b201f289009824e05ac1e4aea0ddb5326326300934c10039dc637d91ab8cf5a54e5913fa620681a3002434126622bf19e6a97b9e8a7b90f9e3f006b897d570cf860a0b5bd967e04e8e8495c9dbfbaa2a5ad3a02115a1f0459149d0f19bb5bf9a79923e6a5be882f96b4fd0bc7f82c560fdc003735cc5807a1625f508e67e150e7c941205d0028c7ebb1f2c092df8e4a68d68d3dba310e06e68c82cc25f595a4881994c1f80f38edfaa8c8375b2acbdf9c99808dab3cb30c000195641983bbf143df4d0fbdcaa368370be391a4dfb67608d9f708525a8d047607bfc17a6909a140fd052a2172ec5b4a09bf4753579af625c53ff427fc480062cb7b2b600d218fa80fb69c47f1cca0b24fe667a5fdb18549e342c9626c5209a33dc4bd4cf490d5cee8150294a62e6b47644fa1cf038e7d8bf410bed465b002628ac65dae09897921645d3babafc0b14e33cb1658c8b1d494eafe549b934d0f41d9d79effdd520a743978d95c1f45bf00b7937be5a5e11d8c150ecec6a5b2006cdb59a6f5d31fa6a9044b3481914678a4185ff2c8edeae59cc5f794ec14d200e0b02a5e054dd69d2e084ec1e3f19bd18045a3e7d23364dd701457684a1f5d0983aea621ce9b1d0d4c2bfd6f4a8aec14414a88e72b2b4e2e60586d15b31a8709d5a543c2d40a68d425ac62eae33a1236fe2fa4db40100697c86e378afcb827066d2fb9a2a8f99b1471fdcf57e0b1b4579663504ce8f5defd276042bafcfff40e5085a85b84e62e90742369840db4b840b002ab0aaf9e3dfd66bfa2840292d70260a5ab3a2dd78cec36eae2a3fc75cfc7409a7f25b920c47e3636e51a2948430931737e2b54317ff7e7a39330b3de5d9ecd168a853604e4fad95b906cd20e4e066be7ea8dcbb55a7460234e2d25287bfc63a9e8d2b483d6c9f5b384fb1be43303b4e0f05965f251b27075d0092abf046a41f9293a546d055917046b6294dd8a0cfdea4e4849f947601b71cebd532d1122bf1168352aa3b47b804f4df5dcded80a9e4a7c5ec51ac379e5e6e44506a3b8d9a8ccd5edf4dfc29b8d45510287e1dd043bac541747509b337340c861b668a96b0caef40f839af9c3a2ec7d1a0b003d08e5a862203299a6b33c7e90245d6a97d826fc3ed8aa956f716102494f7da57c0c80e6e6444c7bfe81845b3d6585449ac12feb52be0540db7ed561969beeb86100899600da327d85edc873df996aabf3850d10837f2cd2cb1f52306d36828e4903ed07edb1335be9e2ca601c8a769df8c14544d570ef7b82c43e29c2c756b15907f748696e286230c1740a84b7b3109d71fa0c9a13beb7ee9d7a5cc7a22bb48a0af50e034e682e77eee558e3c4e0fc7d1997beaa8bb37e273e05d93137417ee407cc7d0f4e1eddff640966d0899cc9eb4a15cfaa5cf7ec4053b91a148fd9e2010185e55f18ccf8c6264735d7789995f424543e9cd6cf19a90a40e2e8b3b5d6970f60898d8ca9ee619e1ef72aa59801218e88706dd2f559128931868935f36bdf0f531bcc33d1415cd6b371987378bf6de11f38f21b517002990bd5c7a216ba660b281fe162661405551e7f22c522c03e4a84715f030189d04060b9562d7e02640bd7d46ccc62a1441086994d03de0f439908366f42063e9bcdc3923587853e010a8f4037807311f557e91492309dc1fd978029c129a93e6ab730ffefd4a7e36b09b6cc6e6cd55f5f66c103d73df7c0bd5529f5ced6db1b80ffa1e7e4a79809f405f0b941c1426aa3aa0b986eb9b2fe233d069374b6129bf43164a578f8bc97180abee95966f374a152519229421b10c4398fd75f81b7586e061028e453ce97e5048a6c30ff82cbb1bc5a3842d355b905ce071093ec72903008bf21bace5173740d0a91a24717dc2da92ba1566197170bf5ca68bcc983abf14c9f724ec11dd38d01e901fcc15e7a483eab8390166af3777b404a37702b30499b29b5b8face9d5505fa43654b5768e86c762f34dde105419eef3d278ac44b1ce94b8cfcccc9b870057a6cf3ff9bc832ac073eab16485d18339fd61c9e335848d7a67e00885538b70da4755c62c32bab34d733a42a378eae4065bc7468af477cadbc0a436883e3440a50ac5b87ca7d006ca26dc9d4f9f18fb69a4e9138746a619f7021f2a84182170874b35e32be8ffe2ce6ad40dbef331872c1e37cd8d5aafdbf52cc9ab03b4e9e08f7e01288c6fba50a7d796d421743e2f0f0aa69283995e497cd921e7ec4d03f0cd72315c5c6fab09ca88909d87fdfbcdcad94386fe69fd7bc597283961239c50f9bbf205898b551a48538f2c404573a41a472349ee0e0ccd6eba51b50834480001070c066202a9d067672b717e48c12b56084ec5f5a2604f1147ad7aecc08d3091d6c665fdcf6e6d753f8eda978b3a6ab1b0873946b221db0aa32eee159dccd019422f7dc42d7d8bda3536ceff5f5d309fe0e52072d175a409d2ceb5b01088c0ed8e0b6a5e1ae8108f7255dec01e61e9983cd8293bb90afeed229e3ecd5d412022535644b031ed2e8a600988b1eddc0aaff553c1a37665e34d48b1ae5d8855e067e54e07c65ac11abd632e0fb85ce84ab72582fa1706387d97e5c90b8402221000ccf28ca27d89062093cf40613e170aeb382d6fbc4e5f3c5766cadd962d40b0d275ff1e57060049cb23434b8591505e4ff4f33b5ec7c52cac57188eb69511d0ce5bafe933ebe096290a54b2e6ff47b6793897f38bf3924043c20d1cbf0300e010a73bc31a7f986f6c24002e8f65c2a89bd124f799fea9eb2a5c960f14801800ea0d204a6734af867a177bc0e738a4763dab837f947a1b2607fc1aca9649d290fc4e9eb7e6250fbc914e68485cdfc5178cf307b2e7e7a1b92a7b99911bcf10d031cf4d8a00c1edd02b79420a85215896723d67f4040c9f64a90482cb2e727e20b20e741ba840f844881f0370fd093d978ee6b36106722d1e4bf3ce6b6ce804a005a79bb43bc9281d0c2905387fbab5759128c6c0729679b57daccba60655bcb06d706e0f3dc843ffed0493ba5808c9fd2ba910e8bbd10cacc89f98d6ea181be030c794a9ceea7f1234f7a1df4a04158099c2bd10366b75753a457f28bbdbf0b003ee45243bd69538c7808ae0fc2e6bc67ca08408e476beff3f31f96bfb12df504c5452fe546ea8c4fe2735e945da1a5ab9569cb0b458034155c70ad9721dc6a0a79b2806d32bed1dd14716b4420052bc4a31943e5781479ffa95d04d4569f380a0667b21486b9fe028ef0e38a3ccc336c148c6a8eb5abfcb0cf891cc202f98f0ac7bb2faf0ecb8c3fa04bdf3cf97a4840707816d55f176612969b4ae9ddadc9033cf2c771ccbb27caf62871ad28c362772702f0801e62a29c286480b15b0c0c05bfc9222afdc84b3a6b376643ccefd0cb20c0d3dceb4c71828f1d02eb1d52a20490ef35e86c034002a6c15ade69bd290697dff156c2d32757ef578ede89619b030622ee254a99c7e6b4c814db98ec2b840f9f855073728a46461cd20b5ebbcd0ba39a7e2f663702a896a2a8a9bbde904e3aa0109e771b589c233ca3298e2f780b5b7ae2690d9c83ef2bef308bfcc994b675e22f55ccb02d577e775af863c3d80c3aecb2f71a2d6d4150c6b2cc6230e735f8895d3758e8279f12b133e2f784a0027e884d42b6f29fd99a2e7a650a80c458c3492cfebf6882dc73c4241d2d3f270f6f86ad5580198c8747ba0350009d505a69f4219d0005175ad000cc8883f76a0c80563ee30dab3a1fba92df4ed28e23a43641b62224c741e4c854344a5608fd029eeff1ad9be6a3ead5536770b88c8d8e7d5b04773d24a249a3f3f086110aac00ad9ce3a2a45630d01c9563256de8941c17a980b8d8ee306d13f5ec2d4505ab0acfd5463d61ef55ddead0ac93e5127513115c5fabb393f292fc5af4711a6b2908c58dcbc1743285aca1b3213e368d7eb5270118a58e7a41cc3ffbb3a7266970060e1127ba0446330b28f5113760753c74783edaf4a7291ccded3627faf64f3100c3892e6e07ffdc4f2bd7836ecf1af568b56b20ca9fded07dde63bd1e98a0580f084d79ee2446356f43b5d6a39b13defa6baf4a444eb7b211d24913033e30900a73c1544e023ccaf14aecb16ff7933544d9f27f8ed0c1b3fc8014635d6db1660955957ab5687d79cda35d6b0c48f4ea3d504c07ad46ff79b29c6cf9d22238d60d3b3b3abece46a228f53b3b604c21a669cafd94db64bce6a6ade854a99f813c07bf0b4190910204a594416588e483bd382144c989be97dccee2fab64c29505d0a1637f003e553841345bc0738a4bfe6a0047fae501a2c4b765cb829bc415bd20f06669b32671e30562adb1804c9f06efd81a9791981f0e66669e481f06ab5e60ff1e3d5d04f77541a8b37189299e9732b2caad7ec05d6d539c6a973c72a061603ced3b45a9c30d479dc5e2abf04094e78444de011630bc14ef46ad9397afb010e2d631724971ed168c92395b2e4a4faa4eca1f1a4f4234e1d5ba1db3d38382a012bdc552d7a85abbb116e92c0904078179b9356574c0776ef995bca962de0f600d97b23a31c780efeeb90710faf591f55dbe4375719575b5ef47494a4236a1a0bbcb903928330b031ac9e26df4d1117391e58ee746bab3b9c001749f13a072904c861dbc8e98d6638e3f4c9bfdadd8dff8fbeb02319f139c662a0f64c238e53007b065b4e40476922dcf25d6b940fbd2d23d0960133bbe7f5e76c14d094ffcb038c8aa436a74ca1c794adc53a8f8d88b75f870dc58568c70b88803dd35944fb082015403989f8d613ff4c73cd3073472d2ecd5ffe05c62b17708b85d4cabc380debffb1dc47a2c5622ae60fde5d8b42a0b50ec65a96c3d0ff5c0566118936bb0a066218c4daae3a29ca18df18632675a1d41135f3674e06e4bba29700550af700ae35114614576580d38aeb360fd15f942f93a198fef462c9333a7dadf4a26a071af4a5f762c1761957889da5d2c46c4b765dce4878d0582cff3cbf785263e2031b81cc165de524226bb781c10e1fddd68ba07b7ba0b7afd34e43467f63bd1902e49f59e41848402a46e6612aa84209272305cad2cf163f507761438a356e2d08521fe168037e6e4f0551d5daa08e3fffa8e759dd7a15d05395344b4bddcbba0ff32c5a448d978b757b164e64bb13d06c1d191519282befc4e8c4e117d520dc050f8acf7d136c248a1e2737aa3e68a80a18c26a602b2bab791c66374723b81a0881ad60279ef5c9111ffd86b839ac13d65a6bd9fbe32eebc9c91b53947d4ce105e8a03f2f0c1f63b9a5f2a2879e44307e1b9349a03ee622e55d7d9b029dac07027fbc310b1f84bdb801f6279b40827d384b818ba4bde847771bcbfb9749dece0f1fac2936633ec35da024fb8d5bf7870845fb5d5d981050e4b6267a4563af60050784cc9c1ca6e6666965aadfedd0850b0195f3730594294a72c6841b0fad7003b2ae869bf6f02baa394a5c4d5a254178c36c0f6c5e07275d78bd9e3bb8f35c0ef3ac447fd2bf1e93c8441a965a40210037156c0ad09c3e2cd5d6fb1db715e206d85147539c3a2a57f6e6cb24c172d4cb79d2bf69c4fbbb186619be3a3ee6d90685c668b6dbcee2cd48704aa5b983478fc00a273458e044b167706718b3bf3a0887a5aac2c299f84bfa50347a6f94298574404a89e17a6621177fdca18f3b950c81076e0d0ed7098f20bfcd9312bcbbf9194ee3b3893006a9d7f6e456ee8b880d9e4c0555f82b6871cc2001bc2013b6247b9a11bcc469d268660edcdc7310c4015a55d2c16f3e1e4456e02cfb15852ed8b08d69981bb5ddf2df9dbdb983cf8a07ddfd0d4304990050d185268b1b5a513cd30198a5d2119e719674f1f210b8e709db3b8852af23e1af2f80eee291136b3c8855741e85f1bfbb4feef6575f7afa08820ec92d1e25a0b3dcfad4a398952c1e308db2edd8c1f8b9ea5d431930231102f61d0561c6f156e78f2c8fdc8868ab80e27e9dc346b7a894a2290f5c0a25e701a468128b291447086e8c4cd8298fddbc5a6bfe724b30007cd6d5d96ef34a290271643027b820a2b5a421aa861c5ada4aef3d90f41fdeb9f90368635fed309b0c703aea81773b8d5bac2c149504c8e9e959da9f55635954eba89683aaced77b02f6ea5e532dd35717f9cf145ada78a03a0aa2fcf2f96339c3e566c3249350d704decb459da508308724aeb097fe49507db4c9a241546ebf0444a613055e91fb025fed75f11eac2d11e38405d2bf322e097f82bba18b0242b7c0fa0300c0bd6705d8b2ef4602765ab42403c26e2f93fb9c1bcd5ca4eeb8a720181190062cfa8203314ac686cd33c7d17a0c2a4ee391f17a917b2550a918ddc3d48840f807e35604671d15f822bd84d6fdd478ec8e3883800189e5b9333120babb27c2d7f35549074d5533eb3e9effb39c34f1e48410144c8aad730667b327229d9bf7b34281a60fe692ced291ca32300721c703d2a5a05bd041dcb95ceec68fd38c5070933aba079902287954f15e3a267fcf74ca95d5ec5bd730da32970d3b54c398bfd8aba902e050ab0cb28e0cdf5a778a9555aee22bb282a19d947281e9e5ed4ebe51e62c09508fa400022b75eb2a053b3ea18793296a812ee39d545e524cef6ef5a9f9470fa8bd8b05e62bf92619c20e66b5c40646ca576add5f396a71ef2df6597a8569020ad23caca82e05abffb7202c57c9874eb11118efdd549bd99005db53d59f350a4c8098fc00aee7ac921a4910853a98ac739fc457a763cbc7fdbf30d6b84d9c03ef4c4e5264f6f4c40f2b4a96105f0a24bbf9f783efe180f321fa21ddfcc1f000aa92823ffc2b573735e1377e71c7e30681d7e4c5ad14df41d1d440167d4bae09fe1ead3fce7f59f5fa8204b7b4f4276a90eec6d9a84ff72a65d2bbfaf7429a066794987432996bf120959f9d11c73975d100261d4dbc79fb3a348512d4c0590724824e7524b124e893cb36ae31bfbad002bd992fc0872fcbd92fe4709291750e50da7cea4dacc882851dfe91d7c517bba5b37c444353f1fc375d81d8f885a0066086e8d7920a7ddd8ef8769ddd9494207569369b56db79b05158e8d83ccdc009f989019f354d7c430210a5ec0ef60cde654f923293ce5149f9d0653fb90bbb0199e30b2728c8d27d71fe48d75b8bb58e082930f13903d121a81032a3f36dcf0e0959c8854208af4723bf52cfcaf160ed079d2e3cee5ed394cce41fdc3e81c200e7fc92eace14c5d7b3ff0ce264ada30f9dc08814b69c19d9127aa16817e1270621634c735a4a3016262824c35ee1bc28ab98e5c9b61a10f2f58aff80174ca107ed3bffb66b0df1d42f2bcd206c12bc0963ec2a7b7998b7a77894f673970c9401d6843acbe4814d40e21c8e5b14d841b80c55db86830054c1a8136760b43ff90dbcee62840119d91648a2c284c72375064e43a18412d30e05847fa7bd4623cc0dd0a5aefd575e4bfa66c2a43a44c1d11688010ef167ad09f47d4ba99b5cf0c002e832384356159c23ed1c87a8d44164dbba2a6db51ed8f8e8c018aeb9daf2ad04aeaaa8a38bda081ac6bcf68b223e5607eea6c35675ac83dc1f63d3bc1b77da0ecc20c5d70c0455484921be7dbdcfaa1880d9b0cd42d61d044706de97b8540607f8dd6ce1b8d84a76d3be26feaccdb57f4975efe99b88aaa91c66d4e6cea9210270fcc25a96d56557195f108bcbaa312dd90b19d77139cce0d45884a22622920497ae02c4632a97f5297e3a348251c023cc7bc89d3920f23f9009b17782ce890bec77fa359f14cd967e85a9357157321e820713200555008b10929370506d22017850867feb8ba0f89989a2cc71810b612a72d7f7d4965911d9ca7828a5772f0a90dafcf4776117ca1a012c3a7445e2abf6620606414516d3e562a6925bf83a0e358c22d4f2672f1648818c3a35ae3009cbf3dbd34e7eecd69f5e9cc54d646a025faad585ff6dd20a83d2ef8433578277a4ff1ddd1b46f9f35b2e6909bb446d06987214fc9a1471ff80d0d37a4df04e285354263a2b9fc8a842ffe5e23c6ff207c0c031af56fc199028005e87628c897a0c6ad4254ed87643c9a5f4dcbf5dff09b432867bcd7ab1040cbdd17d72036313fc24f6fbffcfa6684896b92aef4dfb07c6c28b6b31315831fa6481c7d2b4d3ab3ddedcc0aaaa1bc79171eb8ef676590dda214657362641f440ad87e70854f6275a7b6da27918e4e8d16c8957c70d650d552424ccd52431060b64f996b319a91d4257531d8b96fec2abadda7c82f8ea0c0f2bc9c457cbbbccc2efe29f70adaaa233ec94f36a1cb08b9dca32e51ada68074d600f10b393db2ce0de4fcc6daaa2b9296488f8cf682e3a4d49f1faf8fba804351847f218c87dbe85687a363911441c9b558cc5ed454f9d9fcd263633f287016f21ce184814856dab7936bb6e1501afa43657b5cdc69fe0fd51addfd812870bf81d159c3b19baf08a76aeea0fd6c0dc762e755309d1d6f3d2a1cff366a3e807cd549d514dec42bdc5e615d8ee5783983792c534dd9da4912a40ce57c6eda10ec29c4fdab90101123e07ebd65a35e91db03c107019c05811f919fa85e6cc6a0124f7eb2bf6e97e640d298ea69f1a651a98db3aaa6dab9cb3639508d7bec2f40a0da6f693315d4b3d3a1d0a17bc1be300a3ea90a8ce6350174fdfc9d74d4e970b8658e3f18877a0d52d234a809e62b04607c7183f44060110d65e3faaca400004427415c8d97ebc15320e4f79672e8f959a29376bb5546a8fe539bb5fe344df06498ecb20f169b2a6c7ffec9c48e23e95772f4e581d678351e51a37ae3c131d0cd939d9e23d0c47475314fab9b8e1745f383089c35ae4d3d8a47703a628a76e056b34bc57e918e55f2a5ecd35ade34eca1abaff86210254e51eaa6166506c490d85119b88d7726c17c38878a4c7bbb4b44375fa7ba85d47e345c97cd643e4dc0bd3c0f07b5e4aba145fbb608b9f47c5511b83df8ae9730e92019b0d7d62672d053f904c8affb4366a819b1f057e1d0a165e065e7b23ed0832c0ce4e4379ed3e0a96b85b1c0166f320524f10def2803a4f767b2a90f579a939646a6de77693930ff6eff52b7d9b962013a6aca7dc9140c8ac8b2df68fb8b72fcab97803c280850ba3df73574602b238d826033bc1cd2072c572539b47f71bb221c2ba8da231fa0a76dc35001b0f3cd38cfc314fe79d78b2a1d18474c6bab85b426d08c1df8faf02a38f035ee4bffcc4babab8558fbb7733f273bd89f6bfb1498fca8ee78b971200e7bd7c06c0c83518a2db75fb6fb0f765b6a5fba1f76aab60a210dc26bafebd04d105925b78a1f2f5fd83be5a9f4ff0944609b3458bde93e2f0d0599b79b9aa03b80ffc056e001e43bf73ed2587754c3fe62a1b0a597cb5c3f2788e41368d110082045b3ec5ff1cf549d2bc3a89b1ec602b1983966b618e74782a506c09c1a208ab8aea966da08289ecd73f9ac6970e84dcb5c99fcc13ab1938eceb7d146669023e757e2e27abe42b28d20cc72da606aec4d895a6c6a2734f85b6e78444fa720cf30ab910d4fbf81a7ed6c858055f0655f4d0b4fb37041a37f97d5cea13dd0c007b8164d579b377bba70c9bbd4f98a9cef1fe3d7c5c9435daf70ecd1827b3fe067cfd63b611415417d20e85c1e89740592ccf4a59844d2ba40f2a21ea132205029b63b09ef8f5367272ccee350da5929b671dd56a30e4849eb54b369bb45d880d9b822a4c3dff9486f05faba6a81f3c0655df686f520df93dbc1ef98fad0e600017a5ff725f3562cdb4f29a9f4bf5d0b51a3345ec6c7d4ded504a11076f379f051e539a6d9ab6d06cf26bdee71283cbf0e741ff8e10c9a1f5d53750a836e3c00ba31af2d74c3f2bf44a644aecf2510e21e0b4e0ab997ce26c82f2f699835521046edf1258b097204b62c1a070dfba6daf55c67c59c48b28d1a586cd493713e801901d6f1e717123b75b9ed1164ea44c07ca4131f1cd2799bee2cdf29735b0b80699ea5372d18635fe2bfa3c950e0482427df03d40c4adc50f1db42a3e94a7af0b0e479064193f147db1ab422c340c6e1a67389d89047f8c5dda887bc78600740094716c074059508d333eece20c516a628e3deb722df58009d96475639319ee03086d26db422c9b7fc7036d7406746a8f368b2e903609b930fceacaf151e9980f9c58de852374785c2d3a14194bd43f7c4833bda2260086c4c7e594be2326b60f05cd27166aa69154f1972251606ac671751623931dd32f433990ba44f4d1570c266e1c5464a21b0a3c5cf66a3a9c357b230ec6be5b1a6df533746482fc0344024ac8e69f61491a50861e7f17edd012377dab92f11283a46ba0540d21221e040fcea1ea30fc16bb84a302260211ad28067189996e5338433f3a181eecddff9c0ddf7f4ddf64149b69e73812adee8265368fed21b6c588d68067b4886c8fccdb04f304fea744c0fa2af7b23b111f839223ed247641b8c00262d506d7391bfa6a0c170c14f5602762f77f5251ae2367540d3f19b8b22eda0cc374fda732eb5330001fde81195a6d12e7e1e00c2148c308a11cbf26a65dd4666596933653b33adb0392f78f4ce83591266dfd94507280528be5d1554bcaf86ccd6ab62ca2004e39065a79b85ceb47600ba9cb33d71248bc42e3ce447db2b8090958704907b6871f0ed7a8e6c47d315c39389d75d7158bc79ec293c1d7725aed037f7940764d85740a8454e9f1de641e90033843d67a19938db831833a079a483dce50a34b89c4bd0f92061e9acaac00860aa556e3a6d77c1b4ea36477547b452dae3f4657f798af0cb14870e5a6af4a77aedcaacc8257299a3ef81682391dbefdc7282b4f052f550be7e0bd6dc73e9833c905f7db40c9773b4f658564bc277d683950f2ba6871270b34880168eb8805be7b5c90d0533c811bc406711dd529b77cae3ec93566adc407fa33cddc6703b16a4c1756ec5eaadfb52e8ece9af6faca60bc70a79ed295b601caeb1f563e667145f0dcf626425e721b1aef9321100d56d190f5451df30eef07ce08d22b213d1414c3682f8baf9cd4cd40a6aaec89e8a2e2e823c18eab98b90268308ce9b4e55a45fa6b9e67eafb71b9047a6730093f4d82ed71ac05d96e810dd79ca714eda18deeba0f7fa515725ff1c738c9095abd384044de3a27fc7b21006d15b40b55340a94c0e5724c85007ce4787d37e2e08a62456aed9b79ac8ec30224d011447b9ab3e45c36b2ea8c233cf4085c6d72b46f6dc461346d0f9e802104c99c0b44fff1f27e8b54c87b12bf8debca6c534c83e4bfc1229d25ea5b160208393f9210e4352ee401641b6836d47fab468c34b6d67ecf3cb35c92893a361b07d5ad4a9f3b8378a3f1326a7d0455073aafec91eea2343650614f5db977f5a50adecf79bde069710420e8fea3bbffb97bf1aad738d2aa439588eed39fb642a30a532ed98fa2cd1ba0984b4ca47ec6c01376820985bfccbadc84feb67c5f10b50e801fe2c66f1a6d106dfa416b010fa353c656a18b3cc9e7b67ae64f32993d8806ff36c7d0fd9dde762f0832fd177ff6abdd023b79820470c4d06c4a216b4e1804d6e9ed4a9a30ffa11b933d89b92fdfbf8b1e7e103fc8899027046401d9e1f905652e03458b59fa8429d5c40feafe7c20cb5753efdc6aeccd55b0e32884188602f170783a4505fe8961a3fdb8698eaf5311b5d4cee97451db95ec6d835640eb07fae7a1d5b60721c2ebe336577fd0118b3f8cce7a6d279bff09a9259d66212408bbcce120a2ce1dd45d9c01605a6373e7a9ce7ac5e8f756b21b518eae1f128f05f95d22bfa3b4858e9dfe7adbba447ba09e90c7438b24c974c921b82b8cba310ba8f3b6a17c05aaf652604c15a2d17f47915b4548a577bfab8c5de6b9268e4d09cd6e5fc3b4d694d872392983d4c88647b53807c72129c03b429967bacab4620e38b7a6994d1451b0d1bcc3694ad5a98cbea059fcf9d26dfcd87c9b2611c5f30ed80f22363a671634f82ecee8a5e5735005c1fc9519b8d3cf79165654e21fe601be71d6c665af686b8940e4a5ce7d7460f70d35812b6dddd2ca1b92e3db3883094dbbbcb55a3bea997e9e60c4bd80499eba49067414f21156aed234b6c1a69b0f30cb8d708bf34a43fe2d1bf764e84a2e22d23995b89812fc6d1b2c47ba82720f7d97c279383135c3876c1173f021c312be46027a8228e931a71ba185f784590d9a09b789bafc6604a37b8a0b0b3090ed02a8c886f39f2bff159121b3ef0d4c07dde6fcda2c176638fd5d08c1678cc8becaf57c093fea4bfbf9f173918de49907f8d44fd477ef07fe43e5bd07c6cf2f8ba369c4656a5ff86389e928c62e346b02c7689696549f38ce7c9461a11405ff59b813b7fec52e8fb4e55fb6d3511ec5026378c74d73ea9a024af2c3b4fd885c017914ce7d0b0258d3fbab210541068a035cdccda0df52fe83ab758bc953e45096fe20cc575305acea52cf30aabe9d5d0fadedc5c16bc5be2e7a419f13a525ea2e482f20e14ea9236f59fc9bd5f8fa7a0dc7b7c8c45ccf354fa2467a91211dbdb2c73fbefb9a33fea234add273c2530009feaea50320102f4313301b882c080d2627bbe5556aa6b005044aac9f1008bc0abb7d0beac67928a451623eeb09db18332e60aefea1d07c6e719befd54da3a70f0e5d2b7ced91ae5c620e7e50dd109244bb2a49325972661b0084a3108969940197bc542f896909ff33c8eb4afa44019e9e28408ac3082bb41a53bad633f33109bc54c7dd2c34eb8f7d222d5ed688e313581673e26a294805b035e5eed2dc5d0cb3170db160fdfbca232a8f216c8e2c0adb9dc52d1411c42aa1b3de2746e4f90d6de5785c50f671b158f1c383829f4a9c7ff02b9db0deb49389e9a0d67d3f660829a5d982aa0f9f36bc8c43a7f73d745e198f90ab5522461b5135fba79249550ea9af2ec14a4412c0a36db71e72071e47ab14770c29cfac535b352920ee4e240c6674ca76be39e63846316afb101602e3f22d9776b7f965796cd310ebf1fcc7001092d4699182ad99b836b48704d663c493fb073643f30a50c3e982fd6342bb035f41c3d846aacfd45ea0584b656720fce0178cc9b55353fe89a0861b5e30280fce01d5ac0ed99428b2a20dc74d37f6036282eae971a2cec5dd4bab5f040aee0e4f4f2cf412baa3f94416c77c76e2e2d60287b5d4071dc88a185a83bfc60f010be5aacc7c4ecb42830f80d8e23e141c3c556335e0fe4ca52c9728a0d5554aa90fcbc533ebf11e39a5aa2e3c67180502f8b84972570e44e38a333ad9e25dce2302700eed4ca6d9536c579767a1d017ed28129d2c11d5d5d838dc73ea9406dbb50c18c2b2fdc8051a596fcae1b960a8a80b85ddf8b0b630a55dc9407d1cde281d076bc20384046a5dd2c0119c247a0f54bfa4aacff29218c46e6784e26962d0c50555775330e97640982447796a3c9c780e394111ce1257e50eaa8318b76598010e6458c00d070ea208ec2c6b84ab84c9b96056f2b6b806d13fa78e5fbef9fe9a057b77b3d089f06192eb0d97c1255642f2a101b7e2bea51e2c7243a257717f0203981213bb89ceba129d8b3da69b3bfa361e61d27d6b33b2ba5a9640365583fa056eb802e125c4d8b05207c11a6b63c1902ee8061d0acfafec338ec7ae405f500a0c948176248899ab96289407b2a0f9fdb7bde951c2f34c0959361d71e1dab30300ac4d93cd7c61bd2aa60cef26889a61de24f2cc526df392671d111f047ffb0a2e28074dfe315108c299dc32f2b528345cdcaa91553f580679ecb9338625800a862d1a96c86d14e25b920cb996b706875b5dcd58c2fe9079f3a229cd63506602c6ab0a980f23c860a21d720ab13bdb5dae34e4bbdd2b9c21855e113f8bdede0d63ba000e6c5f251525672b99176229dd7246d3238f89ed34d69d7cefd0198d03ea3658ac8fbad80f44b1602df08369705712cb7c5818f87d4063a27641eec90cadf9ca154871222da6e60815f2ec08ba3acc31c21ccd3357b348450ef0361c0925f849e754a914e6062c1d96176acda35fc6f639d967aab7a825023a036fa4004cd7d7cbfa9769491244409616bff61dbc200d250324eda3063a32c9502f8d06a26cc8eccd445d1a14abdafba0635cac7978fb18fa7fed7e2e31bb4ab9806606585d465766b44ea8fb5a516cee70fade1751baa5d4bc3066a8a90ee0b7cc7402ad642540990254b86f08ea45753ea104baff6b5fd57fbc2148f92226866f1a0ca782835dcb7599fb614f1c26030e7b2de088a2bf56a95adcfcb297f5ed63fe01aa5b95d13cc99579c7e6e8c4e502d6887bddb3b2c5f6fce7375e73070f91cc013085152f71b4763851aa83d6c829d7f72a2e778723d89ad3e77149047218ff077f3cd92091a1642c25b02c581a5cba5d047e7370add238abf3282ecd76946308dfee51a8914216eeb339d4978180dff40847869922f7f040344a77b76b5eb00333595a120c628c2ff92e4edc44b6e5efc359e0024b2d8459c1559149ce1de805e4f057399d93d47404178649356289c7d9fc29893bea6e90afb83ce184771b0b21764b1add18068b4e76fe8f73138c2a66fef7eed06d005b59adf5ddea68f60de53c378e744ea3bd6fdca265dbd761cc641698204937239991e1cddb49b89d0ad558fd3a776a9fec7b75c61fd39ef9c543749920a08dd8b89333ae168db1d608e8f9d5111fccb0b6e210e8e47dedc92a6f40880377613825ab4667fd0287710f98607e291246fdc9d0dfd5723e56f521f5c1ebf56ffc53e498869b74c40dd106018fac9787b0a836d25170986fb2a2830d6341ed45c99bbaf4b1a3893b30ca0f95b4962d0d5d966d4b06fb53a9cb0f99fe8f2f07f8175e9f16c6b74e3c5da700d650138abf1c55a43e69fbf2c9bf83eb24470ec1151baf6a1f829d51ae73030d9d5cfc6390d49932e4cb31974aaa2012d4a3a8c84588c01fe1147e463265990ff26720d70b4c6db955e2c1fd1915e47c7089820982c5bb81a844c8e012ebac08e1eb3a460f00a7a3435ca40f6a5c7ba8ad03411f4b2e3bfe94707e44f910cb010ba2b6c108d102c66f6a4783a06bba3797057881f17856a157b2e4a2393f3f0d1fa764523f363a7a8b59f10dd79275107acd1540775918677463e5a4a934c801ba7cf231688d9507794486dcab53bd886276e9ea13a2d7740ff0c387e2dcc104b532e24a39c6e3fabe529399597df3e85e23797eb505b17440c9f227625a6f0a8b73c9095082b50deb4c6c105a1e9b0bd4dbe0384eeddc8ca12f3091f1aa4203cdc7eff07ff6f27a0b825b192859be9fc6f381894fe98cfd1034325c04c59602e927d948965309ae621da6e167be1e3f2c9520067de4ff6cc2564691c6038507d3c8fb09b10e96e7a8847092765bb5d6d38aee5d39940608837be71cb24d8f0fb564e354e6accce164bd45273ce198c0d0c819e78e868f992170b0efce6bcd0ffdaf09c94b129113f8c6ecea34f30fcc76383ed9e7978e9806395ab15201590d40aed8a7bae628dbe33da05152d5be7d1d30b634bc98951bd7ff95ffdf018a004375f5eb45f5d940d98d8d1a22eb4485c7fd0857dbbe18805bd2a255f22dd60d83c26dc38179241aaaf3c92b23b61861c21d25ea5ad5ed07c471bf8b8f1bbc0118754e125914f3c2dc92e05af909dafc5436880f8f2f6e2a922a39cc54b241079a9a796de6fd96cfc3191c5429d8ded0136737462f822287c7730aa972155104a16f8ff9696a14cc8c83ba3dbe17fcc453910df037be3ed3829746ab68321c0743b9877196268c16f9f51d09f0f89f828f28ecb171aa13f15791399dcc8ee304fb20cc3b23e3330c442460b809468688b23133bb28a1b9c6d45ca8344ae7b70c40b7c480d4c1beed41d66326fc8b40356a285cf81876230fb2963cbf86da8b0e7f40fc5892b6103f2753b496fb65a4109fd004814ed6814fb8006922f6633c0e91bd34b4e2150f9ce1b5a264f3deaa5ee707126736cece2455eedccaff4a2406879de383ccaa21aa76bc38c9451746cd1de6152d3ffac10aa3d8d3880fdc3308b775283bacf20df252f0b77b1ce0dd87217f0c6045cf761e81733b3be4b55f08c14a19ffe72883161860d83ea44d0bde966e5bcd8cffa6b2d23cca316121ee0d544955a46cd3ddda4adaad6b3067c52e5cf27a47efc0ffd238f04d1725d00e0c6750a28bda45bd6a7230ff62057e561a0798aabb90297eb9e6ada53b5b91aa0aa24b49b81877ed9d0496fa6832b40d44872607d2f9f757c64e1b61e239f21502f7489c3fe2a5c4e0503a37b880f63348a81ffb1d9f47eafe2f281eccecbcb601e632dc45b91aa739939f67ed85218e974b0598c729a598770de520629d9ae80ed53c8be585b80456e19ba160fc9403f5444133b54ac109697bd25f524cdafb0d7cfc6579663cd67d01806becddd1e41f603cd71a852f443c66f5accd61c8c901d6574233f3729ce9dc23b251e345f3c9e26a9fde480c80a86196195d820c8d0edb3d643354db09efd245fec2b5fa87069bde57dea4385b6a30b8125e7576640629685fefe514a297bb3fc1705cf630540cda0be703efc10d14b3150deac7fa0dc2141ed9e2f0231bc073d74b7275991df189ba67a6a24136f11c0605bea51a0e88a87a4b0b732f296480abe26f8227febfc48469b0f25d5f89a23cf2c661fa0d363f0720339f76ef75d0ee7113b966b596c51326fc450d70e44450c6a623820f06991c7c896c7b0091ae83b4a4fc277e1daf6c26bf7b632fd97d8504f6536b0c4a0112c1ed00b9efcd4c088146a13b555c9c682a49a2aae35f0bff031ab070029a3d43f80ca442eec5a208dce3b9107ae2037c2ec22e8925f2308b0fbc69bb0c00ffe0135414b9608090d1bc165e7ef850d001a777bf7974b84e79170ee6630334a814a7eee3a48d127c1c4d0bb530eae9cb0bedeb64db6b7334b44c085fa601621177ba74c7f241f3a4bd8d6ed7e47bf25743b07dc9bff7702bb6b3a0714501 -generate_ring_signature 7d40505d96cc9812cda2ecf10be26e35068ef21403fc13a3fe0374f1752bdc3b 58399ed2f6ab0ef8e44f8baabd4b7668e5d9e0ce163b55fde697dc1f57b65176 2 a0f1b1b883584dd18faeaee8affa2076a50d7783086353a9b7d4877f0c23bd55 9c840d84c4e8d918410d5efcfaad94d5be97b5a16738f9ba27c1301e30adc367 bc309edac23260a587d0ead081229e22a1a46029e24bfc99b8d264f0cb550e02 1 d6afc4599903292281883fd892d8372b724bf3458c823300b6937bee4a4f370efafadcc48b857117b2a637573ac27b223f5d6771da6bf22d49ce4ad0253e23026687f79d6b1cd60ff025077161a031fd03f0c681ee2e1b0fd0affa880ea4c8019ab724976ac6539647755f19bc8cd84a236a9da390aab80d2064774dac0b5907 -generate_ring_signature d2b1be9c36ccec50df11eb89ccada0a0d065fafc1a4b7296d85180598d0208fb 790464d130c590b15283bdb524cdc611c1dfe90ed958cfdd1c61f4a8c610e971 3 c760502af5bd01024b414aa8e6ec3291d24a119c069e5394023daa44cf502a35 304177d3c97d2ea31afd6600fab36a15763c2a7d6fd2b179aaf9adf4a6d93288 5c01ec55a849da5d9c141a1da2cadd189c7cc4302866056619bcf541c0ff4c0b 67567e52f4f0d0b41c1b633d3ff41eb5a3af5abbb4b71ea61b57dc39e433bd01 2 b4a0ab8acdba36d8ad4fd610eed13b76770f511f8a1eeb988d6b69a25b647e0e4629d9ebd3e3aec6c364169cb13f4e4f10d4a98b81ccda56791a9d49041fe50528fea8203bdcb4e758fbca191e924dac1f617a5c0466496bc65109b36a921b051533fb23aada0dbd4510e2c8800cc147f99ff12bc5ee255e3412facb2987dd00afa61477ad739f781feea48d750df61a17a8ad2528529c8f34ba0c824e8cb60f3d206c54ec1165646db5cafeb9b547109e7a48e02545a37744eb0b8b9a6e850e -generate_ring_signature 6a7157bd5b7abb0dbf254d14383ec158061c39beb909e371c736bc053821894e 319ca2b6bf52f500ee46fa4e19e07878690597cea71cfd1294d689377803b4bc 2 f579fbadb5fe3ef087c03567db8a70b8b40670bd8e77c9cc58a519e55fa91265 75e979d40c24323138df595858e567668aa8085c2adae4cd9a72ce08499f99f9 0e8eda5e20345e1e85b44af5a172c57f1b7ab0a80d4323bb560058b4bca9aa07 0 2b025b95211a8775c1312a47c4ca764dde880d6084695dd7c15536245370e10624ac36a4d79a760daee6394f5566c3920037d1b3a3a44191b4c979f43a398f05fec59953f4691ef03c31ba26e718982d229ee32101bb940242ed7df0d5a6cc0a38dabde82a143358d4a6044e678583b62509b28a7aabb864b550c2f0a332a808 -generate_ring_signature 2ff3bc41c8184d849397465ce855f0331b2fb8089acd03896ecc40f13c26c6cb 3c0d534bad069aea7a7a99f476537d5fc7d744827fb3c5b1747bd5e628c0c060 1 6a2dd8917bb9f1afe10a52fdc06a7f1a8be194adfd27720f52dc6b68e41dac13 9a8ae3cce36c6a7ce062ca5008b7fbcec509d750a7af1755506ca42987e71f03 0 f67c2e6a42e440b6fe30d961f3c61802ea30df966308074be432bf06e81d530cd8d83fba45f50c2450918df418bb142da8b29d200aa637c7bf7491a9d8611109 -generate_ring_signature 4de455ffd336973df436d8cc5400f445edaadc720ff6edeff859b49238aa2fce 0d974c6f5c5852046fbb400ecb528e463a9ac8ddb7e4f87290675000e4c29634 6 e119b88581dfc38a94fe46a82590cd9b062d321097017947ab2a039d77723a41 7ed1ae0e3e982d596cc6b1c33913cab5e0cac7b70a22d957ce5b51fb86ce1535 d74735989a7d20983a2adc2f7913caebf4fc12e1d33946c96d893ed9fcc41b12 af83956b543c7ab0878eda74010bcce3c086b748e6ab788628c78eef075c90d6 357399bcc7afcb24242b9a1eb62432c35ae6cedaefd732cc858d7eae7cb92e79 dae830a72a324ab3113ae4913a820523184bbdabacfe07bcbd687ade7d8659aa b5558d1400cf33fa98203b0af326975ef9038e19f64b41299a32a0f135bc2804 3 af9c35857b1b065cad69e683c4816456db4398c1c673035a008bbf7c8c029a01336a4b17d5c4a57ef76bf98255d20969d6843dfd2bad7f42aa8660a0e6f239089828de12fcc34680d55d5980c1a934437b48d0ab4875e8a76550cfff8eebb30093d65b7c311961b754df5e33ab418ef81920fe162ed0d23f3a610acf4d5e810a96c9fd97d8a936eb7412fb34580939efa836d249450ae728843632141c2ba103573c225945b429ae750996a64bbba856dcaf8d4ef290846220130f8e8349a5037b93dddde7abc478c2f5a425aceebcd80183da27e68a9602218bb9dd34b0c40f196a0a26f32647313e966dc60d3c20bf8f64d4dd5f7a3c9205d89b4e689c7a0986b71a13ad639b7b3c7b6de3e8900b44b25187f7f614b27e14a99bcea2070c0b0505b4f1f922e00962683ab13e083bdd3a38f7ba35b0b3674b2b98db23ec9908c2372420594da0550d0066901936b886315c95a867b60a77966ba9cb2c876d0d5fce3bb2c38c39099655bf1673658a3f805e60c377a74df65d8731b88138cd01 -generate_ring_signature c5a69d4c24d9ccccb2b7f24569071ae98acf6e03b925e5a9cc09752d801c62bb 3eabbfe3695bc2dbd5901d017eb2e54b9caba0945720164f342fbe3e6ce66b78 26 f43a0cea4cdc1617fdf4dc9aabd74562d8a295c3f85ed4acfe4042119367ea4c f4b250e120df0108ef321a0ada6f8d56a290ddc4164803d62d92e06524f4487a 60c9eaf854e68882287d9f28241a6ee63496342162b018d85c7e547bd65ff258 d3bbab657cf5184747c0ea16043192f6b16743a2aec28a35fb3e03c78114d01c 8b00e6cde3c562f5d9318949c9eac03c685090b8a3d57ba4ae5704ff3b5d1f02 4e16fef6f635620955f7ca6ff8f3077e146acc5591573501874e0f7ec8a6d84d 1ab363c7267a5f871fa39b58b3f77f132c832a148255fa43d488e145b12f24e6 93d47d397bd986ae573e04cfd6502baa9f86572d8fbe2fcfc29d35a6c55b5453 a61daf279f18faf9f001831bc06539fabea3cf733b10abef58a1523414ba2496 063029c65fe66102a1c47575d374692a459a416b9fac9450b3c102494b85b5bf 095fc13758f256b4550452a379a65f8d1c23e670cb5904394d153e4f9ef6f0e9 8be1d43efa5494cd054ba8f7a2ab134fa778dde275d453564e2794af637c26e8 146719dffba2869567d19999455814cedc3384b8a104dfb6512dd434041e8f04 8c21f868f215881a4d8f8ecef15a45ea9c5577c96edc5f2db93aaa97627267d3 c6cd4788daba63903038377a7748208b58351ec9384c96fb1c85558063ca8128 3e5881dcdd2d29e42ce5229d59c8427d266e9c0bfc48bd849a22f9c563ff572b f2ac153edf0d83e0b04bf20f7fb6c70881a8079af523710983e8aa89373700f6 0bd89db8a50f485379de7737d43b3f7899c254190c41f8ed38c1b82eeada7554 50313db4b4816e421de0dbb01a534131546b64539e2ff471e63e8b745b825c5f bed722400190efb4c21cdb4d76679ac6ddd56ef850ea89f5ab43f89d4f2c02e1 c81d8bb33ba874db043e3d8bf303b5790192fea6459adb800a76d48614937fcb 01563d30080870956b47ac0514635364e1c5f8d45e62af0895c405e96be1516e 909d70e1e8813e0ac85788146a836b2cf2d3ade2d2c5b18c9b08cc41b688990a 2da5ed39c9928eaf2ba35e5195ba789f8a01e99bd9bcc55c81c5b1c7bf6caa48 4668235408de2079f6d3111e96e502117b10d42a5c0e7790e9eebb7105a792bc e6574c97ebfd1ffb756f4b27c71b787e0c332b830086081ba57cfa1a699ea613 66dfd1881a176aaaf91af0a512636d9c0049460df4ccce64a4f7527e2d0e0702 16 d92476d6e246736d9149686fe8bbbc0f551561742412ffcd02e24aba4ed1f006cff469eb95d3187a5b29dc863a936f16db138855d94d6c5db0ff7e88b8ef93038d3768aa6a3d964722c39b15f03c92888d547cdb9608eed212547a5fee785808df6dfe582e0cffc872fb55b29d512af69c88b90d381d28b4df087804cae76e04b927234355f252861eaed8cd00c07042e67614948492193ebc2d298e0a956902b3d6c9f965fcd053392481d2c3922a52bc779e321cd8c811e3157ea73c4908003b691a43646a250e06840a88121069912d81df4b8ecc2aa04231cea7390c580fb445db6236ba09baceb89f34686f1d900e1a4fc6a514a87b596963a6efa42304aa6e46a4e138bf34fdff9909d392113d4a117e6a6df512c3069a837f4d41550b6bb4ffae037948d1e4d5642b68528d8f5685e284067195b5de323cf1a9b1c706c6ef640917cee6c33df237fc981b1d82bc05922dd83708a71fd63c9b410bf500f2e4c1d76f26bcc19f92a910ae50e9078f24a10b3f029db1d59977baaa370f0128014b8f78ebc2bdc6c4509f94d959d041f6e8dafb06796be0ca8efca1030b0a76abc3c2f5be6f1311b9f2524ac6f452e57b374fe5ad4199b70482811035e00958c6779c4390b4c7c662243b24c2d79645c7c5b9d52e9a197dd2f4ab36ebc005dd5bffade647d1e77d127edff0e1f651589d483a8db87c7e5f002cf25db63b0b6ecd5140350d792ec8e509e4f6f301c8b7b238d8d21601e2c49c5ff854b3d4025902c35c1fb4fb9d0f1f246923f69e8b3eb2f86b7796714537357b3ebb92b504ac0dbbfb776cf9166c08abc1712329504be6b823add45ba92bb6f0deb289a0038dd6fbcb094ecc7d699f654cb6ec051474942756277f9ffd6bd2e47d0b5abb013e86940468337f70e113c1410c12019c6af7699710fc267956cc8278f8e256011d2a3a2ea94fd34d9a3c2dd7208e2026222d83f7c1a8393ecc66423cccf7b1013f07b8e289fb12097301d2f2e68a18b9301c1aa90103e4f5a32c982aa7d0970db8703bbacaffc6d4a0d9204d362d1982cb42eb5b6659faa2abb2933a7295d50888ecfdffd1be43cbde1006bc5bef47b4ac17e5a0c4ff69d9965520820dcb1b0465f9c21fd07faea80669fbca108ef83f1abe51240fdf0f9685087930acb6e104d6d59d0d1df2a6c00b91fcc7448a8327b621d5556d5efee934b52559821eba086f085fd1adebf5514a126b402d28522edeb5fc4d76c5989c63859c58cf32370e6f320f35fdee15f7cd069776e4c0d82f5f91947e62e523dfb690c6596f0dca0171889ab5c7f4f44195c86c7e9421d20b455fa8019aa389014939e67d0cbe5606d9570d9e3c2c1c99827993738348e8b87bd47c23aac6b864a448d279b675870177c3d3e0e121c3aa2752a0c8c9db30cd31eb01ba9e64636f87360263120ee707c04bd17d9c7114161a185df71c166a51b4182b29faa681c0cde0e0c43e2f8e0a1b8aeea02e72f8dd2cb75c6395738b4a2e183dacce4f58e6e55840ee2f2332041eb213247b66a959c98c4cf4d6a1d42dd66e5f2a7e80dee0d1c716f9650a6e0628e3a3ff87288ffe89bb952a6db212ba96a1620cf14b056961d452381217f50244648ee4f8b501f0e23f76a57e27d2847b0bb0e9be8d4e86431c5d9602a56c0a373b3c97de97157fc2d0ee29e29deae82ee4c93c97a1fe990c1e9c0a963cac0df5e09a4d1ddb3414ca331c5335630dbfcfb07af8ca2e13889af0930232837302625041547613385102a211993380184b3c586bdb3ff43986a744325fcaff5a0f0a5812d074e1900d41ce24324b4f30cb31999f43f7df60d5231342f7a0744f0882f304fafdd5ba3ffdb52323a7418a4c1b246dcbfcc7e71d1f5f37682796c90bd65c2430e1dcc2ec73324b1a88321aaff72dda1e8bd78449984cbcedb1b5ba0fcf3c54662a1b4ea9d1a62a3cb612609ada804f9a9d7d70055c24860701b97f07ceb68e721193c8eaa9632b5b3f7b594be8a9930a9538c8f9ccf2b553aeccbc0cdda71a58b16d594d2df16fbc8829c7632b9b8687c518f2de428fe87e7935e709ad0d2583994cd6f7c9354cb38b4b6b511ab3ee8a3e544fecfa12886f91ec2f0ec772c9bf641bf57bd640ba5f36e57a685b4b548ded06f3d008f81210e02d420296ee50c102341a0ad38e23c312618fcbf11f960c75c9ec53c5ae5c113f0e8602a93b3ad40f211e1852311f85984e3ce48f112b3f469a8ddf5a6fc194b1dc310cfd5e567dd500b3b6800001668fb8cbf88e7abf0fbc38a432a2a3138f29e5440c5fcf5d543d455abe76e536d777331056b00517980f8e3a68b192f7a30f1b5304 -generate_ring_signature 1a25025edeed2967079043c06388cd736a6305609ead156e76233de39443e6db cdd7e9ef74c4f826659baa13cc7027e9d3c0b4379472adae05f36e99ff600541 32 18cbd5ae5ba735e8ff1df944cca9ae3bc07187947d3a0377811c7e0769cc46b5 2eee82ab6674d77e15df8e3fef6d52f2159d96f510aef9f03a7080cc1df8a551 8c891c48ea8e5578faad92012e8519be5415a6397f92493cf368598927562aaf bbeacd239001a036995137abcd6f6df6af0d42517532c177cee3d774a14bd50d 6a7439d1ffd71e17552bf2d14763bad542aef8690dec9a35e7033d941df846cf 99d0c3c86698a62548085e50acff48c7142218ab6c51308429e5d516d27c1e2f b14165aeef86209407ffbfdb583485fd28f6edfc09bfb30000a69af629660478 a1b08ad9ac3f2fab9ae1c44b64c1f8c0d89c7ccfe524220a63c8fd4b80355937 c6f39774cabc63d8a858d76d2b67968c57754f6cf539a0516ebdc2681bfba6c8 e1420e8805e8267cf5cf14ea411f178feae61416ea6097c2936cf255d6da75af 68f36553bc4e176554dcdb4d40911c9d2fc1ad535ed5de68e61214740973721f 36995a5cc2d48acf783e851bc82a7d33b39e8d5fa98a28d053496431f62f4e8e 6e5a2e1e833e72907908da061752783d2bae0fc8ab5a5269693ad104fa23a541 e4c81b9504412585a70f804cda57e30835428f9e7b33db9e303cd8280e1eb133 b21e9d751bc67faa423ebbec6bdeaae824d66f1fd287229d15202ecebf972ada d85dfd2d4c2d681e4da972cb7ac70b9472b5a9cf847e51c7257beaf9a71b6c7d cc68be54b9a80b51446d0588e46f314f0ccc495c7d51e3d271737e76a465c33c 34305ec1efbf3dfad30fcd4e67ec2b03687d889bc2cdc77ab48e0b5ff9cb56b8 c1e4997cb9f2baa62de3da1f39b14b0f81dbd2b5b1458d4017e9c3d78a24d406 bec351ba97f26bcb0b2e4c2dc0c42db166d281a7907971bf5087eda6fd4c7092 a61009cd579acb5a183f65cb11309fbfc2c83f15a8e9a3733dbcce4bcc9b68d0 4652edce62b97c125f033318f97c9d0b6af10e054d424e0054da0892856f8a5d 089d6c08e5cda9afc0e25c942156cba8e1154aa6e108f7157b21beb0b1dd9c71 7e67864cce0de6e0b36e85a0ffa8839316dd5257f1d43a4bdacb63723937940e b7924cc3f1eb11c19f0f92c4328e485ff5c087f7cd65d56266882437cf36b3f9 b90b30b4dfe9bb2e74a319d3fefdfe16dd466c5f304cbc7002c0b406c75f6cf0 f0e309314c00e1052b94b8b61b8215385eb018d80f7d416c7ffd3e303c8355f1 532eb3f1f94d0c51c3c2084e1459abfb07ef8735edfd8f0549904a66bea4a6ed 00c8322013b025dabc91953fc9d2c7558e2d482f7d3befba5ade16bcaf12e2ab e073df0ab60437b296be99f91cb20f4e2739ed54d3f387f1bef16935a75c1712 9e3706f7488756a2813420361f139e2e8478d77a52a07e0e3e0f2f85c873eab3 021fe8333e571ffc9e67b99ba619a42450b5c1fffd3139127f63412b9464a57a 1bbbc450a6b3450d412637420a225f94f6a76e0de606ccff43a749e255e7a803 28 5dd96369e04a442e917f63b0b22d8b21965977601b4f2d933633fabeaa01be066ce1dee3f1fdf05983257f5527964668720c122bf18f832e458efb1f3d4b4b08a1e190f557bc1efdb6cd4e3d347b97e55d491a7691a1199520c8e69054543800d8f1768ee12d514233b1547d56c4031a5d37ae7e54cf101470f525cd268e5f0d36b4d5019b24a559679119dad490e9404c2728a054ec33b39185d2c7b1cb090e8a15ac74761f3c9b5e7a194ac4234513f33eddaa09a747fa2da116852a2dc8089f4fbb21fe317dcc242f6928e38eacf8cc0c802c3469959719304c7d0d27000517f4fc7cef3868427ba8724c6ad934bfa2dac6ebb445afa1cd832dcfafd8cf009907ffe2c8f32a6e6e68f6f8ee24f8f8eed6aecf2b4826d9ca7b0146ab5c3e0468cd93465a7b4102c3fc8b1c00b54561b078b422c06de9acc86c968d9cbe5206890d45c4aa0e1c352e2a219d6b0002c82eeb2706f63a37587feba6a0ab34e40477000502380c2deda391802db2836f9a2ba46239be2daab6892440004b63700d98e22a6803e6123d6e131a463cf0a141b552626045e35d37a2e5bc4f2950b803eb8113514749979854f1895705aa90f8ab222b010d2ef466dfce6de455409606851b25e1100dea08363eaf37c155f5af2fafbec2fa52b0dcd9d26e04d8ade30f6442f7249620dcc6215dcf10a6d9ac491ee410a9dca05dc7a9e9fe4a47318f0e5423df12b719807196abab3e37ee861751f7392f3840ce7fd85353f3a8543708e60012672b91402e4c0204b73628e1771a4a8ede032d6a621fa039c5e4988a0c6d4844bf775efacfb70085feeb8eab5645aa5f5cd7dfe5a5bbd57ad7494ffb036a08defc8af797c9400fbebc84bf619269aaee66a134830f0938c4f40a6fbd0774faccc3fdc72a295f5f06a1c441f4b4db0e3f997e9fde22a80bb7744a8eb90c3bedae519f7412ac666c7c4d5f8951b55525e7327b806b6e8d3e88cb380b4d03341fc62654d6d60f3697aaa49b5fe3e3df7f086d54f6e79d0fccd7404ac41006e83cc4d9a01e84c9db0df2ef1c593f20e64cf5f9545f5006ea0bfc8f0b51020d633cbfdee4a65f1a1cf8d5e3cad8dcefc75ea7cf8c546bb833efc3341898430e7835cfaf33428952622bfb8b6a02139d76ec4b11c75bf2a9d9cb3bfadbfeaf0d18beca3fad9111e8a53157d920d05f3996c0b5cf5d4b41e9cc11f4edc5143b0690451a6bfaa983bfec2e604cdf8ee1b3916889e348eb7ded95a5d4a969d48303c7fa4643c9b88527555b7653b203058415622b0d585a45e00984cd948f9dc40c01024675e29120a7cda2adfff6771244d6140083d76b266b8d9da4a78526880bd8b2e02dccbe6cd5f769c1c0e3f3e4db53ebccbeb881ac5a15afa6e492b1c20d39cca6e04f09150f2cffb7e632879b3860083ef6fdbb678837a5dd47388fd20eb250904c95a0e52ea7c7253e2ed2bc27a61533743c72343f978d1c348f42790e2faddf6964acf1e1e6e8b8f4274b8e877636483d49ad801ad7eed6a9a9891405e0cc5418493cddf8d07919fc110448dd61b7842ba9bb9b60305d3d142aa8240b9e8132722e926f6d002e79eb63fbbd68ee624d9c5fc516400499eb419ecd200ae6f8f7179433d3444a6c5656bc5ac978d92093d92bcf7d23263414f0294a6507760db07e4e1a7a0f5741c5a3fc75815e5a9d3b28b540cacef7515b8c512ef102ec8361a89b4e53014ef0dcd5f4ca7c51cd334f8856cc3a9d734f521753dd2a0557ac07e080678e2537400d67c61d1f0fc056b37ed8fd40fe64fb4d24d08a8808df316f5d45d6c45b1b7c0e897af619acfab1eb1e2f24fa04c96cca43680b100c5470793570392bd07220e0c79fcf83a0b69c17e6f4314261c76dccabcf7ab1014d96a776b6d93411eeffa82b4a44c49717fb7271b0a12748f8bf634f5be8ae0d9b0dd99ce695dbc4366af0986d12a0ad8efd629c0ca4851f5e054bdd673e210e31efe35636506a55ea2476395a88b8a44d4b4ee2cff71a76d3e295a8fb8ecb0c0d51d7b12b9036cfece89ec5e1adaf5da32e3c5a9f176c9e0e7d2295d905af095bbd4f0745be8e113f9e889f3e7f6dd83dbcfc2c9802817a9081ae23480f420384d98489b3752c9c754b87aebaa4f90d74dbc8470506d36f4dbcdf8b1686c6096af43a7099f47d58585c711527c41472b71b617ab69616da0b51802b0260410129a09819c7adba2caea93c856641569916654bff27d7cea29900f6276cb84b00bc985625879d686a4e74b612b2711ee37903e40739dd2c818ee56f9f85234d08da790491bbb94895008484824eb28d6d98db9afeca9a711298c49e72e1adc50485d23b61f2c886001ee4fb1ed079cc014e64950d7255318aa1fc85d4a78959055a7e80747b9c2ac60e1cf6cd77639463a949b109cda36379149b6777074ce10fe7ab50838f4d0bba7f76d021b16a1f897752490e5945e41bd748a2ff34b67f0285e33faa5120ffeabb69e584b30c857cf024ad6a6214b361c3132c94e1ce870720b3942f4b30a0014b9dc1f3d966d32084aff1287cdb770635c5b070e5b15f000694f46219ca844629f732ba861cbbb982e18512a1a5fef494ef31d4c913ad03b44baab077de377a0ba7a0fd25f5a44809f534d9086c7ae6b8175df74764a300db173c82115cca3f68e1eeca4ee4721fda53583b963a49ce082de78cda39020e33f448b8b5bfae1e8dffc235335e3dbf4c5f6fd6d51065235a86e7f654c7700f06281e2f87bcf94218dbceddbe704537825663f7dbd8cbc2215f05117be12807dc2afd452ba147fae7d265fea4b3d39954b5f3d2627d6a96470e47e3268b2f04a0c7eb05909dd3ef41e863643306682c10ad5c04f7af6d097bda99afd9ca4f0a -generate_ring_signature 06849cd0519c6f1009ff2038da647ab6c1db4158bfee7644db31219a32de2265 5ab33b23374071466d658f4931aa7ce87e2800bee54a77b3228c07a8d1f9e4f8 50 f4dca6918c240e30306a9f94dba59fc51a8ce538d71996d1b1ec029c9b32acc1 3cecaf5af6facb8438a4feef5999cb9fdc28fd4e4ea8ecd67ee057c70679a00c aac24c3bf580a2047cb608e7414c28ba41923980929864f3a59c5ddabe1813b1 178bc14f54597a5d3216a28b763597cd9593deea8e59a5e4ffab0d3af17dad67 cb648c43bb1ea79463c31058908db6360ae89bafede111ff9119f619ad40be49 645417d726d5f09e7c40ba1b1b1e17de4b445cc6b443f106ef8cdf20709de226 42fe478f50153993cb0de879050356c81055b30b04c773d07215ce8a05e86b9b 853818c89f9822f8b5bbd1116cb8fb192b49db52881a63fe91be8828843bf49f 43996d323e85feda01a303ec77bcad68cfbd45fa93ec6f52994fe002f3f63320 e80f906975529b458402d90e871d4fe391325a3506880ce3590640c1721663e3 249d745a3bed28cf3ab726767b78266a4f0df17ee72e4c228dd4ad9363198416 127e4eb44765ebb96929285776f2f28b8b506fd2f802709b960ba5122386e4da 47925a49af8a140f389594c6b0f58c0cc7d1e9b2ddf8b4b19caddcc3c191e66e f2c5333dd0c1fa1b3bbeb8f76e0c3ad4d90ae352e5491733577f53653a512a47 41ba603e6990ab4a6b38194ee651f33b1bd811ce9b415f738a999791e9ecc08c f0436f4175cc6fd250f1df326cacd940d9554ad61ea96fc21f7338b5314c0f0e 165eee723e8a32ed375e2454dd569b0a94ded444d743180b81883e7faa4a4f13 a85e2a7516551b743a2485984fb579351503bbf3ffe4a74a04877f9dcbb53690 e94ccff70bc813f73e14eae7093ce6610bd111710c284aec75a04b0f4e931fcc 03671c6ea4b79883673021463f66222b4aec7c91f5bc03ad7efc562fb6fe2db5 26a39e79ccb667024f0b7c90c1dd724da2e3754d810cd5491eac2b3cde14a1be a250f4bf3ac3e0b8aec3983660251dc7d6540d59ef7d05ee4b2c7412c166c98f 914bdb7c9c9b0735dd1be3f60171458b8e312e53ddbbb23e541660bb31fd1a24 a67f611b7bf550f4b54065c0c77352d3c49a3dbb71dde20777788eafcea84513 a9d5fd6f07e027beea34762f024615ff38a74cde6b009cb1795346607e5c1ec8 7c894a201bb20226d380c8b58342ab7b946782bed4532f9f25c40f639f1b1312 c360d3b1274db4fba04b8c6db76de6d52fd4326f7aa8ec955be3c62aed7188db 2be5959d53e19c49a6960aab64e2488996addfffb2419e3c8cef3db1f3c33a35 ba81236a84fbd39181eea3b60b1a85d6947007cf42c93ac15ef7a2cef6a4d3fb 8de16d964a3df51e199b8df767470f4508ccfccd27b7f6d78b62cb9398bc55ea ef9b3fbcbc282afb025ca8db586de74a30264588f5f1060d243c7865e4c18c6f 4dc1a34353b429f5e1811290d12d6e69f3485e6af9b389843aa1b5a067ced872 c8295f4fcc4620e37171d648e229e07c0ad3cf81fbdd49e895c08ca2dbb1a73e 39ed7eb8e5da66c5b688e7447508a283c96bba5c55ed8ec000e42ed4872ff145 4f7f18ec1e2eeee07658a986008ba1086b3a1f030a0dffb339099f94d4c8f3d1 c05959888131b964bb63476d63904d04bf1e62538e8c227fa6d6a84b1b2c5755 9af1683e1561c8c82aed8dc257a5f301eeeb76d538cb62c80d85825c3b58840d 58b9d74270c39051b00080c63d5d306b6c7e8ce773b912ae34cb528723b31409 75c8f3e9399c3e6a233b1f511138af008476a4fef6749b0d039ad92edfa6cfa3 8f2d018ba38454006905612074115d7f52f021de849afb63834f621b0cf86813 edb4523261f4218904cd2316470a97269c10b7dd6278345fad3c78508947624c 89ec4715a6d64497ee9825ec916c66ea04f4f6005f2c09737d094667e0e2c134 60d872a3dd8bc3dcd1e620a448fb2ab021b5dbd0e42bc54fd1a22173b7af796d 7aa0e6c13aa26d3cf23d32b3aac2f4b9f07dd8975532d326fbdce20cd978b271 f20616d23430a3a6df1fec7eb6ed20ac2f5f4d17cc4af342a92928939bc220c4 30ee3a8103f3b6869b385f54aa458acb4fbb8225b8cb1ba1ce0b313b9ab32830 d2c9241543810e19e2d25fb2b82f1bba7a7da6d72093f8aa35ccb1a7eb9d1271 e716caf713eb8e1c3f8c0c02dfcd682faec217cd7fb0a872f9a6e498be2d8f1c 8040cbcc375bb11d6c4da2de3035a95273695f28b3f766a966966a217af215df 118137a60cac4033aadd331dd3c1d1511d4c6b3ae41b929c05a31252f43d097c f28183b869e0e416647dfbdef14a6e7b1276ae55c760120cfb92d5333cbb870a 39 e322e88cb5fcf73e3b2fc0aafb3d20b0d479dc0700138b1d93587c07ce8a000b60fe0465a999d792750b4c6f2eb782e173b8ad94b45cfdc8f0d9f09ab62e9e0a4b01893156ba67bb00089153289a9b015b2b6bca2cc4e2a047475b8ab59d88032d6acbff2a28f0c1e79f82429462c9404503bafe9478118a11c6dffe11d62b0ba4d7846dc3aa9b8ab6c96a8a10bf56ab68fb28502a6fa14597076265361f41094528d8b06288153cf8a0ad7a480f7142fed424a7a1c720948980ee4e10553904eb151e09515b3287ad6d61decad8198b66e85bb47d08a5da3977c36717e89e08e0fdb015aeb9ec358de6cad1cc9559bc0f399d7a42a1529f6a7affb18d568e0d26b9fbadaa2e3324b973b02e7735e6e19903d1cf5be12bac70c36af58a02e40125116de322656259e1d747103704391333f7440c96c5707fb2500732674a200fc80ae86019e26ccd6ac8e3969f5d87a005077f54a06f78fa5b87d78e9bc1a10dc1af47d2f98fd5fe5cfa1117654fa6eceb69ebf68cd243cc31c5642428244a084d49d48c54fcd80a79082c49f7c18f3b0f55bfb75d306e1c08b4b0c8a9940606a6f2063c5d084e6ee6870ea2a4b20d950f69dce8327507dff63cd770fb0490008228b6243865ede83c609e3f5e378b6f3945464c887f7e13f2e534df963dd90971a3c5c5c12c74dfca1b55c5c971c15a13e94c55d8dbabe9ac34fdd259122806a959de5db3b43abb79039c00e63cd8fd068b90597253be2709937b8c23eeb00d3121b82999c6ba02ada2aa745ce5a330af3a22a4ffaa238feef63a9b5ce0d90148899e3268a123cf79df77561ec94220f0c27a770a80fb436a5480fb02095a0398ae5e5b841dda9e643553358243e4b02cd93f8bae7a8520ae5e52f8e3c90a0b9468f6e9f57452c324bd9e1b4e602abe8bc682fff54d6a1aaa0d069f156e4203058f3977463aec20b1e7fe1bd4d58eb0fa9ecf1c7989acec89b65e13242854084d252fb445737c4cfaf0214ea2dcc224ffd12e0631d7ed2cc08386092597bf0a65cfbc691249732fe95548ed68107bf2cfe6296294cb92451b01c016dfa8b10482ba6f72e18476ab8631b52a8d5cb5864e4d2fe43b47e0aa1950c60cc573e308dd0580487c2a09ef5e9d5c6ddeee1264cdf6a128f1b347a338185bded919ce09752b4323c15c9f582222c022907fcf4ab19c1a6b60feb67350ee4ab1ba8cb70bc39105be1a56a14db876bd8b0fab2079a4de9f3a8da13cbf47e79456b97549080d573aec171cf6a35789063f3c5a80b4b3180d2cfff2a1586f617a639284660484722e2eb293a49684f98243e7f25b6241805dda23d5b65e28dc74eee3a7e4079e8dbe531db67724046af715f5fb95e89e835da3b3e84f95a5a7f68dbf1ccf048d0169e73915b440cf6d82db32ae5570fc830611a645d8c754686e4c8c2895077bf0fb0825537a787763f5d026f692fe6d2573d90010295042890d68f76b500864d1bd8ae10180168d64d8cfad5214418693ca10a40df601d7e952b1d46ceb083a09586ffe05b46449160e28a624b2dc797bb47a842d3565e5ad0ece0ce2690ede7ab2137bc02b59a84724e65fba52b58df548d9692c94655ce8b7aaa25a690a81aaf24bc11b3c68797e6531b8904e8cfb7a44f8487e4341c468f5322e43840673c507869135a04b033909dcd70d1aac810931b1ee217e6193f1cc1f37896b03f27f1b6c1b40d2850ba70dd0e076ddc9d432d0d97241142b58575bcf5b55bd026a8d6ece53181a1507db92b858ffc1c04f90206e6cdeda67cca76c56b87c3f0ebad09b5994aec7550dad847dfe7424ee56be526a416b9d9584c0f5c5aff0f205f00a4bc23d5953c56373ddcb1b3ea1e2ac823486855bf51be4d8cd749014f40b4c9de33012ea589c6b0ef91a467abadda3d730286506c5d3561933652a61c804f211455aa4a7513f5a23d6f8a5df1833ce4257536711e2a7d5468269d2608c034b06cb5204f87340b6d7aff69d6eb005a09b596d3603e56e8756c736d084dc0e64dff02b8ff16329362c903f418f9f9314641a59ae97e81f9182f03abc41ce0b5db99eaa901a5a04cc216efbdca56844c7ad930966ff80e57962018f358ee8026c307a61725f67f0204ffdab2acb34d7c136d5f53cda20219b9b1b3ef838630f6ad77d15c509c8895a8f4a409ccc21874d998920cb6e48b57d3a3ef208c3500fc5a915da32251801483995f7d8a8ad39afee832afbf660feec4e5dde80540e05b707beaf5d649de8519df9d8194373236e7207785abcfba18cd8483686768202dd5d1f18f514d4ec8d5da347463fca3e712b6c166cb2cfe93f865deafb1ea405848cf98f22f14335529cb1ae5fc43e85137f92b9d151a8954a3f504133dd01097e9c8f2437c501a9a155926225cde9ee3b5943275ad8e3ab97401d967271de0a7c5881de2c8fe8fac5a89d1188291ccc98c24a68abe93ad6ae8a06b2d29c1005028a340bf2bf53798163010d20a84954ca8ae2d740cab432fb3d17a536e17801cdb744545814b97acd0842dcfa517a8cb73f0eff2b2b4ca6cc6951e810c8f5068dc6dd8dfd6b361fec24d99b8113ee8aaebd39ab36e201c933e45a1a83f6570896f30e71a0e6cc433a422c6734fbf090e178dffe67ff028c09e786a5f82b8b08b2a3ecf1065b8aa6b621b0b1285b716cdd8205728fabc26f389f37323aa397079b073b79d39707bbcb2d350d551b27d64b331770e6af8b91c8178168bd1bc10db48c661458f4b274eb7a275bc21d327eb7669c8df7901249b088133fc6c6200f5c4960708ecccaffebe4483259bf669da079d9fc2d82bec9db4c518a4113b70d6a2d7211f2d264064421d54a402023f70485e5f0ee2ce0d41190e0a041f86008096b0d4d212cb1dbdd66b04751ce6bf8e6b43656523197784abc39c4503d600dcbf44aa810617405e214d1190f77334f2a3e3adeecb59409dd2d588f7e5d320668e55a7f595e71678d0fbf0d3b2535a4aaac3af2553f866b572116003c8a7a0a2bd0e5f1e0f3e36e749e2ac1d5c0127c5355a7d61e34aa76a07370358ea997066f31106fe2c73d2c966896d819330f9fcd2ba14641a1b3d679782224ace51f0d7fea6bef41edaf29fc5af8035f427c00a64cc2a705acd5f9d9b64771c7805b0d8f9fc456ea5c91ccf3c20fb901939a53badd780d4261eec5de7bf8a8cfabac0de00085ae134d46f176afa458a4b42cda58435fde587a675d59e499d58368a8072f5488bae58a357b193b1112b6841bec5d9e9d17aea4afab799a820670aa930d29c69c83c332a403622e6cdb855ff57ad3c0189d76ee017fef6a45ab884c510e14abf06a1dafa299f293a05f66d06ede7b7c71bd4845edf55f0316aa2ce6e909df19ac96e071c85e029b8c9dc64822d141fe3d7a63f22448c6d9f97e21d70203106bde1fcc26a5403d7a1c42e3589e28b503f13fe4c828f4bdea405b37ce7c0293dcc9f934edc67b69ade5757b26c5a660bcfba263d53983a8c229a3a4bc19018238db3bbd7b8af80575cdb6cc399d5c59a9f2073b5de1579ace69ae52a09206369f8f2062a7d3c65b13d55ce5d36a4e029dfcac43a0673937478e445344a50dab8ac4c222eb55381fd2eb44d38241aa29c42698911eb227b1f7bc8d061e55001651375eba227580f24cd8cae5984bb4bb09ee57f4e8c3f3c98d9b57f68e800ad07e3fcbf7d30c27f1cf3c4c47f87145b70a634f513b4aa3dbe7b75d80770e03f263abc6449a1e4ece70ffd79bad231dc7a0979f8b5654c4952bced59024d6008744bbb31113115c8ea87551371cff633f6a8ed4050318af956c11a7d9596b0fa34da56533dfe6d91719131e6a098d4c854e2be30d637891f3eefcce020a7908b4778a70de196233e5b49030258ddc7b128cb843ed6bae6f2e0b6430d169100e9c5180102471b3f5e6804d8ccc14b8d4dcbc72832ea6ecfd7194a427a1707b03339ae7bb7a52805f721a512db6e257c48626262ac9ab7434d36d1e0de6d8ef0a13c87ce39b299e73bda10dc388cb10feb0e79516db6e3640a1d82917639d6b001fa4cb430b74602b0167812108cabbb9036b9160d2979f1d18caa2aa4ccd750b4286783f67d33100f0dca786181410b66fc8db3b9dc1356be6f8fd00adde80068ce364351e316e154a6d87cbfd0c9fc781cf0f6c8f98b7f7284577512abbdd0898ce4d23351ac5f1e812ff7b9c092bfaf5f099c88088873e1542f5c556dd8e0adb066f1340b301547349c04c95e320d9802e27597ad1fd449d7bb32159453d0c12f75e3e42803fbe4f2985444511a292b78e95df63de4c68a1c6fce18c8278056a701bf228be9669fb31e22fdd9011472d23b23b7563a0c09ab45b4d396cd8093b7af9c52d5d254ad563c49b18dca0ccc9481f39ded5b726c7d32837a9fb3c0900853277728d2936e4d56b6b105e76b03a14b24b2a0eb73329b8b9dd306ee604de09549b6ed481df03345d8eb2ceba043bb262d42231cb82950edcaf47067608 -generate_ring_signature c3ed92bde9e8446efb5b9367d42ec2d1422a2cfa450a71141a7097a49688df52 f0dab29e41e047f2c8183acee8e0708501ef4ef0ddfa6e7f17a9024b6ccfe877 63 da39f87cd0110e4eeb4c3569349e603a31a6fb69dba927f28d18ccf5cd877d42 cd374e7929e2a64d6b9be6dbd9cd599d84d20f7612ac652f64372b73f1877408 fe80449785af9cf3ee7a75a83a43659c6f5ba4c18db3270b87fa75164c859f0b 1be6eb1f5707cc1869a2e6ebdaff53cf48ae08eae0a8b1e531b888542cf293d1 8ee5d44e7badf8d5c406edcdd8c530b16e4e0b3b9b9bb9355befaf2efc077aea 3d438a0fd481a0eed145afda32e3476b76ac92a006fb4fd7810ad329a29b858e 6b76c127a388232f2df579062c1bf1a28528be805489d4f2705d66123812b2c7 680039121a8a1928e28f3153cb1176401d5caeb5dba958c24fcfb0474cd4dea5 a19c49f7d41672de74e063361060426d2a8b882349b92bfc808ce1e61ef12f11 8303590b8103b58ae2c77bad446c90df388ab2ecf06baac717f0afc80695caf6 562b47c8f013f3b19c61ebacd5526acfeb1cb804935d358f7c91ae04c5837419 ef3a80c7141778f0a022a868bc60312f647d43431992d300194ef4ba3c35d438 79b1823612b9bf0aadaffb6084fd2227e72cd3d7e4e9c01ed1b49a6676ebaa48 0dc8aa6f08a8927375135075e0bb400446e6444e0e8417e6124520eddf59716c cf05ad9b936775c640987b5c24e97747a556d79438e8c971026419d7d570ed80 c2a77c27771f2b48d872ca607557e68b5209646fcd51d33bc2e7354ad20c64c6 bfb6f453161cf18160d66e15b35b0cec92e8ff6f280c7f8a3f7f6c8bd7c43ac6 f51fa0445e7aea779340cf8be0bbf08ebd182f58075bac9d6444c6ac43fc2f5f d007b1eda8d4fcf518760ac888c98c55e95d31a80f60dd2b4ac977b16ec218a6 621bad8defeb944bb8d45d8e639188f7126c575c99181c490020483bade02400 4be49d6eca74a476c53ea0b10339efd3f1c7b3b7ec94ed1231ed9d98d0c06535 e290e3eb2f3610c491129c37300cd2e06bf327604430c38e4ae74c2378521c01 404bac8f26b8258897596efeb6a2038769e5fdb5bd9f025879e62de6099b79c2 d831751f5e3f66c566623b38c3f42772de731327660ad06a3b074007ba95a0a1 1a82cd19f29451407682902139f2c23830fc162b921ae2ae5aa91829559610c2 15d0830fc658ae55e4dd3911034f674a1a401f09b7cc11c3cc6f4d2245dcaab9 f48765e2972e935d57885af53bca175a9f7900569120d1fcb7986c2f42b3a305 e3e2b896e6bc92b4079ddd3a3490f9c9fd0e759fd4fc2709e1d742a6196e49fc 02c733dd69cdf8e3890d006ea71c1555a8b6407fa2f3ac6d967f6e43db4df100 42d84b667f691ba1f585b49d1d5fa029da5520b0686d8798c592ea844137b3f6 5e6605e0f7abe6131b382e6a8759c4ca5fae77ec8291fa878935962ee02e7023 43db8314dbb6db17309b12392187087f92934bf63d7e052ff7df1dab66251e46 c1de18964d5b564728cda7674a983d85b9e61af2a5012489473cb9bd048de0a7 80972ee2f028d2f4b2a15800a16152d42bcc81ca3c2437145bfca495514cb69d 83ef50ea7e02045bbf4f158d32f4b942284e63e5f2b780280a87703e4f7036f6 87604dfb8212ad16d491f0d56d7b311b4b24888b360c36b5c1a1129db3f3a8aa a3a8d82b787407f866a125572c62efbc1da5db0ef23fc74562d4390c68aaff56 01fa56294a12caea1c202ced527940cc24c4a89dc8270f49ae2d18e842400b28 9f931197ff4f05f68b25ae4a86de55987756793579d84b5d62de550150164c44 b61458c7d49003834597f78d4a2592d1fb486482e8e7bc3c3a57f49ef2b8ac42 d554e6418a72f0331d05757d200c3692558f334802719b53927648acddcc3351 cbed989db9983b608bd23cf0f5dbb80015add6f0b67b1b6774dfa96e70d506d1 795ad4295025bd980139455246590abadab9203a035c50846e4e6bf5faefc729 75b50ce254809aae0d537d54c0156197e20dd20c84bbd9a62e2e301590ee0e3f dd8006d8f8db4216f3a0fdc27a872b9f2d16c511d450ef8ef9204f10860d8453 9903457d3aab9decd7c2e07202cbeeae6191259e348d0e05fc8439f06404ac53 40ef0206e8abb47158988a82b39fda91d6f52d592e49ddf90181bf959be81da7 baf85bdc56b8033c1e262e08e123e5353cb7f7ddb2b7ffd74ccfa529227853c1 a4d2ee759a828c54e976a8bbc55294e0f971cae0f30c4ff2fdb04f07de39c7c1 a0d47358f5ffe1d742a0eec679ec72cd1481f7190cb0aff2baaa141b68899de4 9cf118c576775697f38f65e1605978c2af376fc5e87e18c7438b07b48cb4ee82 9f022677e170ee00cb689b13de994c7ae9f5bac789ee8c8ae1e4c5e7e179e880 9064ec6c92d15bbed8c3ffa9c54dd4a71c3e940373033de467234d6ba7e863ce ed04f38c3d6180703052c3cb1150e685ce390ab1491c85cb317533f10fa252fb 5b71fdcbff0fd2e0d68d25f03b750e7ec3adf0c4455b0e06bfeae8437cf746af 7bd75fd7e511a36f6462dd1242f4c53db2b6fee823cb5bedc26bcc9c3bb52372 3b403b21997c01407a6af4215fd3c8e21b4badfba425c032623b182bb2e22ce7 2d15770f93f004a76c5e4ccc25dfabedf39e57420ec152fdfeecd75eea79d139 f1d12a64020bd216a36776fa960a50453b3a3cf398ac5cd64ede354e8b882868 f1ee519a49f43b4d6eeab6922191742c70adc22d3eb88f68f285114600740f06 8b48ebb921c0dcea1e01d7600fcb33fe4c50a1646de0f5feb775cb9bd87b8988 3485e0a10bfed2eba8dd4dd81e2ea42a7daba5c4ec4a035521004ef90274565c b6a73a9b1b67ebc907bfd0429107f58b7867a029b9e48bde23b821102f2b0ffc d5daaf0ec5ee5a4ae2a10fead09449b44b165bc5e657dbdb9aa0ae2a16824e02 58 a583e89fb43afcdd5e5987dfccb123c297329a19aff3335a67089e7d2de322086f9e14e74198106ca353e31fa3426369f415a2bacf3160ea4e40aa3605e3660bdd62726dbd0706112964a0a28ceb7c11c26a0d0fe05c7090e600f9f801455d0d694fad13006c038eb6b63beafb831e1016c0a0791ad13ed4d17f0a3914bcba0df45cd71fd6eeb60349298f944f6d4016cc72a25c5c071ebb8965946733dea30b870a4804a9ec89c052e8c42d168bf6d74ca8ed846240a904e4260db89d12a500a56cee04ab6c5b5c467220325189b29bd36d544a1d400d41d3b989fff7be38072f479c12f3da5992a926b36f30cea493d9dbd80b653a0915a721c5be1b7db605b7181d4ff939b629488b582cbfa8b55701b955fe7650ce9bf2907c9d87f62300811ee6dbe80a1883e316de9cc92d932d8a4f640aedf587f842d21d6105f7e50052f1b17b79af70064bde9a5657483c8ed1e175de4cd9d54759ce648e7b88d80250986e9dac1372b1571a4c18b0eab28f7f73246daf72468d4e8e34af03934f06eff2618127417c7254efdaf71c2e92ef962fe47e9bde2fb8bab49679681daf0c8eef29b1b1b08181631ee9357281cd5e58a771671e2006fa5389c1190d58c600f98b78cd75d697f132f4240009ccdb0fb39df1239cad5d84fe43272220d0eb01c8c8e989e12b766e784d3fb263b6be2e984e98ad1e4595f08c1652a38763b30e8e23d3092ff96cf7c40476684dd2193139600d0c8731528a0e9c536a8d26a10be91dc5671f96518896354360da84916eb057c9897347d40aa555c6921116e009016af319005cdaa2029196e31d59e782b62ac252fdaee47cbf0b2db408d673051f8db6fd7d6f2198d5c970b2cb39cbfe3717c55eee111f636d39dc1dd6691b0be2a6c90bc560a43196f2399fe935c1ae69e0c90b9d72d6338d5db864ed2ef406f77030daa83dd3f906a9d8cb39d74874d14b022b8d96213b6fc29c06e8996409be201c650d2d65cad9a1e0a70ec11c480f15dc4ebdc69301184154867221c1081f41b2f5e34b7db14463af3c3b635e11eaea1cedca5bf0b2a689a8b0f127ad0c0b6bad404f396161b1510045a6767fa939f33752bdc619bdde7fecc4b76b6607166c34f75ed8d3e9b329ecb231ebb036bc4877e92c8a9a62d1b931768d7db703c4d92e4fdbae790fd5166841925d7e4c06f799698fda93f013a755f7c4c0990d55b4c37d89efe352da93cb83fbd039abc3b6ccc79db99fc5294b5f496df6b40eb83a720f00a0abc43ec32d9ba4c6d12d1f3686b454fa1fdb45bffb332f0c790e32cfb2ec8cec7f124a3b882b086dc571af66d0e766cd1c900d0b9b8dab5c000bd71650bbe3eeac4fb2706d3585aef87eb210b5a888145dedea45cc6ab71ed607443a6a21e1798450b6aadb733dd23bfea8ccf953acc30e16c5a5601cefbec008c6d2f2212879e706274902464fcd25ba7558f3eae26b94864855e53a031c540021391dafbd46b469485d397f4f6bdf7f8f9f217ed09f79245fd57af741cee90f6141935381ce7d6b92c50aab7ebfe848bbd275f17a16876998575487129eb807f51882700b56f162cb94ca3ab246dad56be04d6ff05c4d492922976be28bf30fc4b6eb7371e707c622fbe5820bfa4855cd1901a1847720a6cebbc8a0da338b08db493f6173432cc1adff4d55a7ca09f9be4db6f10b8397887d408e9e6eaa2d02435d33e0d33041e87988f06eb11523afa6222d8c559defdfcdd1cf9a3658340b3261abc4d08d803e254ac31e1cc52dac9570b2f78156bcd8a2229b8881ae5607921d704baf33e124e9da1e82b3debfbc92ffcd91b68a433aa9782a0f5a2c55033fdf8376d957fd308e066ff49461bbe78818b0ca22a89a1c7634206f80a47b05dc0c8f97374a31d3716a76ac6f0ec0a433acf4c1768421338c0f9b86977eb80d7a1fa3c8e5d4588b30d020c78f357b14050adf30eca1b62fc684e50ab0fef906bd3c4aea4caf4bdf8a0aa6ac8ab8637da6fd58bc58def2213f223ebbef60ed00cbb61af502d373c96313cd71dff0c25f046025e2322bb246b07298d640946d031c4c3fded92ca9e97b63ed24a61fc4485d41f99503ccc9a404a9168e4046800aca24ed5c6b2dc4ed2b29e826e66b6f209d26f78d1c9d19a6053df5c4da314b017e084041132bc96b582eb10f4a8c8f51153e74fa254e8ecea59e57d354e85009c10a4c0ee75b67d256e6ed681a5419f0887f2819ddd6dcd1cbc6416a0149dd0bff4db9808c28451662e7f24f76f87ea514e90879e6ed1037bbaf87b285542c037e42b5212d964876db1b9856d1e594e0c081d01934a37bc7b5ab5f999bd4a901079811146918eb45c5420dec19b201fcee8af4686d6a5a67ef0539117632ed07b4e9444fbe3700f5223932afef7f40771003c23976a1766c86a5e9531f249505e41e033cfe2369b04f86a4b63218ea396ed574393f76c0a6bd2a27876fe38e054f78d3fabef5fd3f1dd07b47d332c3521b891eb6f11895bdc89d10908a19ff0bf59166d2a9ef7157d002ddece97d2763a2894e27a5976f4b6c7db82fcdabca0fa2418ff53207671ef2b578a1db6db2ce3d6052ab898d858b96f2211086ca7e085a0e36d46a71831213482f8fc37d06cd6a28093f17f30502c9733c510b56670af649be55ba2dd11a8f411cd19c26814952c864ead414f349d5b65595f8c2e603f1bd02c9623a13b1ed294f8c91bc97df2649ae0931da9544b0948245e1d96508d9abc0dc043514a001f1b924300c19455b047d060864cc490d6e93e1ceb75e0d8ebcceb43d10d801561f8ea90f2392b2033cbd75a1fbd22336013f0465ebb906e59b7a98b8b61f14b82aea2cf6f91d6018f13cc2155fb8ccbc90ffe3cea927063f5e461fccd62400c5614874166bba9d3fdef284a7d4f2bad526723fa8c05c0d512a00105e27d32d61012a8b7ee4111a3b74d9a16573711e0f2ccc646dff380aef427722cea046e514b40d74436c05f191a121ed300bf29c6672e873bd4ef90b21d7585f1db20d2bf7e999d42dbf25e4e2200c7a1d1205543ee8bd3983446d07ae943a4ca1b663c9deefb77507ebd705730d32db113808e9cbaf9aa414fd700af4e54d6ac84981f816b6255e8292884d2095d0fe283fbac5283c211f107ce70fbd12a1b63f3b249ca2c9b0573f2e750865fce07f14f65b8e6bd33df9aa0a6b0577526d63b91fb6b1061c7ab8016e2f77b214583f06d2f5de1404f4d798945801cf2e7e35de62e5d658d48334750f53714695b61ce176c7f7a67b9b3fa86d750591c0421998c69ce9237ccf726488f9f1734da635493b472d2268363b44eb3304f91fd50cdb687a9f31a5f57418c84e40a9748d6f0234fc74f4faec80339cde037ed2bc4953fbd29a1ecfc9a60e25f1d218dafcee9b7753f5dd6fe0f231d0930ea384b470b0473139dec1ab627305d7bed373f94ec58946eabc9135fc12f8c70feb6df221ddfc743e4db05b60eb484da13cb74f0e8e8b1499a40861c16391830a52c7918a777c8362d2fc046ea88ab07a39e34bc8d3045f5594e541f64b52a301450896e7358311c635039cbaae02a6ec528ffb93c41ef228641d70c38337c409090beafbedde8e79bc04b67b91818125ca7b5e0065695d2b247b781aafd15e07f3b227baed57c9452e1cd9dddab46d8a0bf9811a172c4fee936307b3b340f009827297bfb4607ca47515e00d876c7e7bfe3da156011ded770bdd718ed53cf009b3f1461eafb79063088481fdd25db46ebf1689b3015f4b5bf2b4d62d27ef9b0ea993abbcb9c5abbc29f3c682862c7a86970756a058d56110c2cff31342739407cb03dd8cecfabbf23122487b6cff7baff24de7e6603992033877645364cf82034a03e86a9fad14c214fc747212449bec983bb55f7fd28dabb7fb7cbd380ea402104080b3442800a173f762f5bdcd092ad7f121ef1cf5e6c67d9bb5d214f4b808230e9c141c9303ad4ee1ca832472b0780ab425eb6eccb723d6e331e031926c0138e922c74b4f9f0cdd2ef7dd2bb997c2c0e6636350eea7aa021675694a4e3a0f5c6115fab39077cfb2fa06520886a05ce151fa9220fd9ef6562dcd8e5f9db908f41a350172ac6c8f0f52873a67f983e5e5f52d8c07d3e5f329681e36b1190701b217db4e14d0cffae5b8b3967f80dc13707f7665167b93e58f9aaa2c6e485a09a29bf525ffa72fb05b847792a95b03f704897e45ae76849292657641af827205cd8a6bb49a064b14a592efbabe073fe8da513396ef58497fde0a491446f4740331781a6df64bd145486ef305093324202516a0eb08ce7b895b7ec7162b25ab0e24215d6c6c7d2445ba8052280953b86a288ca16c95531e4f6e6e5a569ad80901b61de428146c311e16c566de1202536ffb30b4ac36f58065406d3db3a59e9a03d6ee9835109ef0fe7987845dd3e5ac50d1f673d203a4f69a3f15419d78a4380917c7c3a8478a40ae6d98b0312b185d16b948504fa463bd312a5fb29a4c5fa406d4aad66171b71c116efda93c43e2c345a34463f581f8e85877b3168c7a17470cf7b5ebbc960eff67875b322b9e3f0046134478d0fd76308a60e4423875db440e01539c5a71db4ab4dbc1f1219b92cffe5adf5678dd4598c4574fd791275c110d26e993f75c8bef05e71e33314cad4c037b788b45c3da12574ecd66386a341d08714265ac4cd9ab644d884d76cc0bef7d904f5a58c46792dafd5cc22a9c8a9e00d0cd2a3066995a912a6738e4d1ce09653d6672194ebfa50a93cf7a1d5891d504d31734d114b6463a61147d6e780d60b05ad17231dc475130c7929e5dd4366d0f5217add55bcc70210a8b816dd890a824ffe0ca5f4284a76b9ea5642a4e39e30a8f1602e638402c6929f9dfb4c5d5586a911246b7312452d074b3c59a02634a063a3c7eed78c6c349dfbc0417473be8cb95a11976f358015eef5a1e036b05430ec38972696115944e3d5c5b31329ece434d6d443be88a9fac015291e84692260a9ebd33c9e183100dadca7b76451c31d4286d827aa0be4abbd5dfc72f812fe80f6b886d9d1ed3e1d231f5ad743a10c5d5c2ba48b142ea885d1629e4edf2c94f0878a55b28d7268727a7598db6d3184f4584480018715aaf39cc8c19c7f393f90a5a6487efff93589b4b36019aced42bda34b0a5f109ad8c9a6fb17201c257090bede0ba9fca628369f712eb3e80d1132c39b3e854e5783f80699224a7c2dec009eaa489fd1b692dddf7ac417eb9cdd7138b764cc0b7bd075b65fea073b2ebd1006cd6e3f6091b983ff3f0f57023311b411b843a644926f3f2c3519e2aeb70d2094fd5d05eef05ae6938dbf5b6b722ba07ade6f39c915e38a4e012f43654c19d08e5211fc6d65030dfb21ff0f9e8c95bb689a7a601d2a63306588d31b5e0ad7a01f0a05bacd19fb77dfe57a9241cccb784cb42f1861ca6e7fecf6b9767a812fd08750dc52b9c5f822067860dcb756702ce86e0ac1758e1cf2e5e5117544d8d1308efa70a858bbe8308f42f8a585e333fa25a70971de1752b235b52231667763b0dd9229e538abe0bf30d7cf05cf0d991454ef8461321209f1c3e5c462f352f2e0712e3e609dd7359a7a91b0aee20db249e851a0f475cda61daef225c3a56e1c50e317c82843320359fb85fe525dc936efc92b3af1d02a0298a42f5d2da20219b03 -generate_ring_signature 33bcbd4c5fa68af0c24eec449ea51bb72ef7190c0ece9dffef244eb90d6765da 732fdd3197aa6855d284d6bc4749adbb4c265336b62300984ebcf74d03d31ca1 1 878686a68ba5dd5aa696fd1078dd94d627486bd9c11d6dd328ff0a9b6c091f0e 658be715fa02ba1b7f4eafc02f985fe14c9f7d25f6bb4663ff87ebdc2d63eb00 0 9e33007e5336346e5106d4050e58a43ee43779c369ccaf8885f853d83fe7cb026e18cda48b640f5cf73067b65a3274b33afe0886693a952186f6a104158bb404 -generate_ring_signature 61c98e5693c58afb5c7311d89c4589e4669b52d8ff4571f293ff1f98af9b6224 68535c66978cc85a04be5b88c000167008d36429547ee67230abc78d01b3a07e 2 244b5e8cfbc8ef701d79624bb3499515be5273e45b73fbcfbde5b238121567b6 04cf46394b267c0bc9a5c9e2e5f88b07d59cd5a9bb056f94b46e816db4789be3 f0c934fded787d254b29eac8eea8e249d6217a82e8e9d5bd7565611394277404 0 967aa76d9317162aa629bc41b43b151ce71d2da0cbe8297f422e4cfca5402604dfb8018a2a5d1067d3c508f7f3efe77d249687918f1e6eb4e6c8902e89862f0b24586a542218dfd3218ec750d7e5d233bd231271ca805db28da94b55752662008accf21f16dd7a29fb4c93d510cf33d424b4da8852761f4df5be34b54f6a6802 -generate_ring_signature ccc5dbfe3a1cdf9f9c21948ae48b7cdf305a2054183d05654f6a5b8f1d93b6d0 406a3a1d1b23710ed1555c857e26bb6185a783eef109fbd102728811279bf26f 111 2921b78ba30bd3557e4b772b3d61ea6a16138631c4ba2d8613419171e99e66e3 ad1f075026848ef6bc1680d01e676f8fc292a83df780b49224e9b62c215f6eae f0ce3cecd97138d3819ee595d9c3edebaca5e340afe2f07183373d0dffa0f4be 26eb1a7d2b2c5bb31b7fb377b2523ca36648014dfd16c7f695bed93b718e8733 92523fa28a9a5267ed1801b4d606e0fa5c1b70d54c4634ad0365c6373de04a81 19c3b3475cdfe8c9e801d0be4def7e2d002cd570fb9d9234fca3a0011a8bc5ee 0e9593813368b47bb51b706641310e983b927386a90a00398108e8bb790ce5e1 5d46bdc035314dd0de17318cd46d886dea88c67150375407f34c0039989ecbfb 0e8d745fe8777c695390abcbdc771c9a7038cc327c417f3b754118c65b6d6f99 8b05713d11a953c083ede9778e7e7bbbf4410e35fea2af5b4320b0c7cc4ab789 13761d8cf0742d4b60bbfa4d205c49d4231eabf718ec4234f4036ca168d9d1ec cd2db44254c778fc88a7737e400abcce5d893219d8460c6ab3511b42512657fe b4534bc0527d545be7a0192467837a675c47e94db7ab43ea0773bb968a5740f8 ae5ce2355ada6f7780d89d1f33a249d4dfe7e079b5e102a82314bac3c04c3f6a 3838cd930a369c5458933289ba73002c71134a5e9dbe16c9dca9471987882c26 ff437f8c5906e641d47e53514ff94977417cab286d5f9998c0a7b8177173616d 9abfca55d6be1bc9d37e412d7c35202301060b89e1e700d5514d02d9011aab29 a3232deeb8e763d369ae5c94553aa0e264705dfe24f1fada06a1be1ebe93dfb5 8f51c13bfcf2486557450ea30970171fb0d428c02a823c7f9c704da2402b6594 1791024939f618fe68b0d73e853103b1fcbded7abdb65fa15aef63f55d8b7f44 ebebcd04a35a3eb5c9af95cd67d75289e616092523b8674c659d55209b9b2d61 4702673f7fa85237ae5f20e68b966f4fa9b68c8b6c900316e9f3864a2720b509 bba906384ec35445dd4fdfcd246f38654e8b9d1e3b24911e8c892687d1bff04f 1242ea27621579afd6aae5311988fda8be14600d5fc64352af2ebc4dd383f7d9 7dbe2bf95b8051ea0adaa52744aada889d89e6ad189ea26d8e8c355eb469571a 4cdf70da3f89ee7210375564f8d46aa5fc3a3c47e13866abac7c0d618346a042 dcd45fefa6e3de7ddcd3e105f8888bb6749cb565b2d1fe67bb1b56fef790fc5d 9507267fc1696e5c35cd3718490dc2a853cd2f6a249827f0235d6cb95ecea192 fdd370f6de86d821dd2ea27158eb2ba1a9f6bbe1626485fadd01a80a92a3ded1 575e8265225649995b947201fd76719e51e56f15eee0d5e6462331f69650bc7e c9c8a863860d12415cb601e9d8362990ee855a1e5d1d70cd75e15cc53c07e7e8 dcfe0f0f4119063c29577224bd9a7a1a3800d645e0db7547ea05389f45e73c95 76b4cabbccb35f51dd5f61dc72c717ea336795fc71d7510feba7a84e5beb5fab 0f12bd1eeaa102f5531d9fcb6b79423393fc47bf0e7f753c814f5c273a97ff75 86292224747d0e179c14b7a3e65e4561281b6a827aef6afa2dcb8f8b16571b92 1f9378d5cd626274da52a2b71027b5ee6335871550ffde522ff0a6f49986eaf2 6d5daac0ba917f50cbc0c8502489320d6130cc4a2b332b34556086c5084a5324 9ceb51482de662fe631eb9009212b401fe7138b667b7bd8cf94d9181f955f3ac 958663234c70ff625e10a10779504e267f643aede28861c4a0759eb01fadb1e3 d906f333761bfd3b113903255c1589cafdd20378d85665af168d0aad0367f83a 0635c64549ffedc46dab199ebf89fcc8ac599c8d89970f7133ab5e235e19f832 decccd21d763536ae6d62e9c56019358437f7176b0c6620b51bf59c5f2b0a518 62bfeccab34d00e92ccf718f671b735d07fc475bc5e4fd783e487666b0fff721 adaa55bfbbc3f50b640ccaec02646f4b152fef46d323065efda9bdadaef91ba8 82bfa52412799a07d83541bf6a3de59bc0af127e4310f09fea4d1971af8c6aa5 4c796345e19c94182721175a198a8ad535ec0f547558c7f07cbc3127a1ba0d87 ac9bc2d8ef7f43f80ac9d87142545ec4d14e54f64d4af3aae305bb5407a819fd 934000e2895878f33474fb25b205d5064c181277719336e36e688133a93bfda2 1b3ca7399c0b5508f80a645e083627435056ace47a15f8fe9f9fda75a0b17baa 9e360d75e54b81e3434caf08a8341bfd70abec216f1760388e7d68aebd87e6db ba19f181e552de8ee972884cf82d87abf397949851f9bf867a7bd57656fb8d80 a3d028b2702f532fb6dd99154d310afe882a709f8d0f194a3352f800b855c91d 6c477cc3e4587c389469d20bd69c196613bd50208f91324404ad58201f7549b2 a296d83f65b17869870485296b1df3bb2245aa4245abfad85e826dbd93ca4e21 23bea6d1f3a996575696f69c7b4f4e4b276707eed13cd00cbcc97bcd807b9bf9 5273d520380cd20c951e725147ee7aa942b743b8873b0ad756bdf30851dc2d98 85aca67f1e96a7e3fcf7ea9a64c5eb63dfddf35b692f631f89d179d5d3ecfcbe 84240ec649ba87138abdd7d1524c2b580c95d601395ecfa75ddcefb52fba547f d11fb311986843cef697a42c1db914979eccde0dae94d1fe7ebee7d4974be857 0af06bab640a620fbf4cc5c3a777e209c5421641b8ab610b3c5a2a1a47ae2a0e ba30f319070ffb436f5a5853d00f8013241fb6a6bc472d142f303623d33ad465 34132768b3b2dfb6d97c8eccffa9e4009230eedb6e84ddfed5dafcac3763adc3 c5903c815b8bd030162bbdae429032faca5d73777ce3a8248dd717578f0b8541 adc10a53868cc31d0d81395ff25be93e04212b1f45c00ab5f6eebc4c9b28aaad 1b841fd24b0e7929dabc30e700c6d312a8e3d976c95155a3bb3102fd9e0227b0 56f8165751e6767f607821a630ab9d2132661b4ac81e2f693e5c4f60114ffec2 6865e341bb94717a4de51578360b59cbb07a1660f70b0048d9475d28d7adbe3c 3dca83f1651d518dc458d331c9b9e7c2791ee1019cdf392cd722214e169ff2d3 72099a12ac2a7852c982c2345a5b13d7ee8fd6cfcecdf989430e365dbcd758cc 400f30e5179063981ae05f55129898e12a61dfd6379670fba47f4af1f1abd042 771d8631769dd24075741231cfda6e1bf41d075c4c60af3521546b2f6f2f7da9 1a4ac92b9c6b0ceca0a0914c21934774314b7610eb65d81639971606e2109a13 c6555b566f15c912b0fe560cfa4b5df5dea4e44624b49aa8a6209f9131109e25 944e66c093a3b22b7b64434839dffdfda5b8e0ddb6e93b3fb4e6c0d64ec80ccf 5682de8256dc5f421323d2e18e4fe8e86810eaa87c6d58535dd2c8d29d27d6f2 ac52d43a2c0fe2b23e73c67f6b0db159498140621b13b4bf2fa6311de6cfee8c 24db498c9238003c869f46647b4ec96fab351438cee5fe815ce700f5a83aba83 75ba2f7f38f6bbd6f58b59357fb99a74b46cb4252758fdd4e669d327a28fc693 74d45357edbaedf1f26950c22d83506ab3477bc671e685583418c81aa4c11f4f 61c814f9c7d4066bf95ecfc56a6b60d95eb63b0cdd4c0a45ff4d4f83367aff38 b58e16527d8d0435434e83e64c6ef570cf3717f79f8bb142a3510dce185286cc fb771fda4468b3ea8ee77c23ffa586486cbccd347fcac9fb97960262fc4ea76a a5147a14b7ef157b8288f781275b06f0b785c0888fab930c6a78d94ac818ff89 34557754636e143800091dd6e2a233b47f140010f36eb4ce27b48855b74076ba f95443b3d18f130e37fd03856ec8c6e38ac04dc9d528220481cbb49ed27a9f03 3a6d4cd695f507a0a8a404c02d1e0bd2ac93f4ef2e2056da9ef7a73e70d82f7e 5420f0d5dc5f296057a98a879fbc0d64605806aaad6b574da9a6e2ce9cab60b7 71b23bafb900f95b9d8d0deb139f0cb966ccc1078542b32dceef6849de962e8c 2255481001bf79311d76a4989dd98ff8c7f2660ab70f273b52024560d7d9fd66 2d291106b2157d69bc98c89e4034cfb9988d54b69a413a543074613cb1cf7923 3e38943714f3d3db34f5c12f375e73e99e6947fa661e86065c4041d15408eff8 7c79bb5943468383d769a23b260a0179587e9fbf3224349369bce1e5a49e4869 fe4fbdee077a24b3ac3fabed5c8708f4a5d9f844a8741cd6b2f539932d1a34ff b3fbe8f600c1f5a192bea732df2068edf5ffd6d766b2eba55ab7f6e8a8e4de8e 242b451f824ac319d890214a53a0c84ac7b2555ae80a02cb758343a607bfae93 2dcee51f5cf0cdcae0fca85c195a0f1ff1b3d4e468c9bf8d5dd6979b46bfac09 e35f7bf7fbeb114a5d73bc5450a2e24d171d947268a41c4da4ef322f387a20e2 5247a3383b66dbecec8e74af6fb621f5ae3fd77554c3c3f34f0de68a5802706f d727e6a804a5321ceca5df85777121c501e00cfc1beea4455cf94c68ca3beb8b 64a875b077447051c23ede119427c11392bc495a401d0631da8eb3ddc6af5c79 a1f1595cedc5db42062066166a58c45cf7065af7e52d54c26e16fd98c6defa16 91410d274f804c5ad21393f0f1758a43d0003d604e34fcc9ffd545a3d39b35b7 61ae9820c5041ff102e5232cd43fba22d68bdb5bfee2d997ed97f59edfefee53 d32a713c0ae6079b57526da8b355edd35cedd2ea55b9192e6e2bb97f2fe10119 9057bacde18dd4271192956ae16433cffdb67580478f52fb9e4145658f1fca55 8bae0275e1a2f5b71e2c2beb809e5a98d02b22abb8ade1c5356aeaf8587926bb cbb581f34ad405175e6b591d7f0d68272140a303a4044ad386bcd12489cead56 477283eb5796ec76bbdff973d760fb3a25f5a776d2cbb9f9d3a6e2391064dfb2 2096412af720af30473b8db41ee7c88ae13c2954d7078d28d284aa5bc76ae1f5 2086b5fff76bbc94f0df920c81d101e50708d68f0b18f3b2214c84b137126a8d 68b883a806d347d1ab2efb8d975c12725a68dbd162756d50454408fa12390cbc 427a77fa841f3dea30b971fdd3e26d79a6b1378674651569ce263b68e3654d05 27 c9792a474d8ed94f315117adb8db3de00b852f158492edaa1bf1a9345ce64d06954d455fe19f5736b7fcadfc1b8f44060356e97f3c043cd9053a650db3600e02702e6e2c54decc8c7ff405955cb15fda9628751b81a3e47109b3af13a7126e098dd905b97657689eea887a041a51815abeb2d8a95a655c80d358d10c3efa83011b39c7d8dd6188d040b5b1c507f76f6f4297cbcecb291282a13a72890ec0d60518a9149904268ae6d5b9377405b9d65bec14db2827422d939cacaf30e7015600931d98dfe59a4b676b0a783c1a71e64c5ca7d9f1efc3e4ef3e67f5ba046feb09b017327d692d3519a24464b2faf8854909324b129bf46c2726a12f686e3d2107a6c45522347d38f960a1260147d6bc3c2ce6a7d43b2b81584d091943358e2802a5e2dbac5abb1a7729783873c528d76442c102d32946f86f28bcb538f8cef80d663286613741470885912d1502946fbf9f44fef9fe2f9a983f36cfd16f7b360d28754ba2debba5ef534a566a34373e7830c5c23ec7f63bef8172b0e9d6ac8b0a359a66120df7ef14005b6338f6a7eb9c33104019b592ca048372c324ca3ceb023ae4324c1e52bd475e2a6411c3d117bb21277bdaa719ba24ed8a9a88306a430e26d7c1aec0c3f5e0812f6774265ed99c3ca0cec7976bcfe2ed7998e52dbf320b4536bf38c4b3118a08e5bc312f4df0881e73947c5794835de5708b1e149dd30ce5731cc878081724f896144c4f17a20213f30fe49e20c8d2440e3bb0e8db35063b4f5a3491011032165704f56becfc4c7c01b053ffe8e984d3d6a22eed7c820183b16410989e896f9482997b29b7909cd5d43213175084d9bd40bba761cda303ab5caccd7fac7167b1b2f36ff1d67ebe0949c52e48f851c3e0c1a9fd20706902a5368771f4a3324204c2c1d379b45526bff6e0a21a8a7ddca4f9d4f59bc09a0e3cced0ac95786c93f3fef089a641017292797344347956557642f548ed720d0f768b0d50fb9b6bf723e87dff55e702e6678d07b98f4217dd47cd1e8754da5402ddd7dbef15375f0143030a9f48568fcca9ecb507463db9159b65ffc73937860a586a7918ae4c07958e5f39a4a60f5ab5facc2acb9796775555f22e87a9947e028742ebe38181035551a6ef9cc822a562aade0c24ec78a4502c66720bea45ec0ea4485a61ee9da2a2d151a446e454b4219e84b4e16adfe962adb0c6ded6652e05e8bcdade1c95ce8ede4c77175fa576440a5ab051c75de6a75bcdb5c05bfa560daddd7c2fc2bd8aa8aa65b9bddd6d42bf679754d8b7d27925e7902ec7b1db76059c0da54e82be1c3a2ad50789c84113925717734098e3c2c9faa701392f76c107bd46b9bf99c40cabc36d03612ebec1537d240e0b6932ed021ee97575e98ea506cb439ffd5198266dc0438308bfa88328da606712bdd9e4fc10b91e0ad9a9f40c0974cc094cac423c8c9d974753e707a97cf5ae1e3112ccf4b83ea10cd94a2b076085ae1904701bfee5bc105135d3c5628c9e7692cf3c18312b4b7fee1db10a0dff74f42ea71820bd6e7e9217adc301556b9f4b5d385246bac3f273116b782e0f207b983842766e5fc9ac41720e4fbf2f5c61a6e48a36b0c6dcc5078c88e6ff0b4b0f69a644b6c0b0069d5973a171ede818c3c01a174476de8107772c55d8d80df0b86a14ac2dbe733cf6330a0c7d7548e78ca194b363bb64e2fa1dce1c9321064777cc3b0c65bc8def0c3a11a0fafa4c1ca36379bd35869e85da25d4a7b70707b5b09ab0e27e6bd14be600797eb2d43bf6dcd8d212b8f34f8bae2c949166ae046b36cfe12b3562e55f73cc5d890b5825a46bfe0b9f0ffa5df2e59fe57ac9f10863028b477c9168a75516affebcc52e08356af5157e836ad28f24c3cb38baef0cb87356190a59fe5e973b581febb29ee36644b34ee6c5e660abcf96f15bae58066b2c5021551c52aef8ba74764f78826c77feac6b3999c5d7247d26f01926c70a63211c894eabd7e6eef35773f528639b121864ab30be1e681fcadf1eeb3b330f2951a1e01cdb3a595fd2af1ccf09ca1c3518dcf5171bae0c9a8333db5a086005bae6646960a2f1d1ac25435f2d95dc2bcb5ae9b79c418a23acaa0649dbe4680628d92df7831b5b28ce03b984d429e9486b3c9ceffb045360b2fd8ca3387e300c712263a3c6daeaeb1548a52e581a5078082b9129cd63c23899659ba4bd205400a68c9583f4673bbfa613949b6e7464a4bfb801f546acbe4bd3325f944a316e0e9b6aae590b8f39595b07751f16e21fb4c93d5f3b6f501484e15fbc2134f5a902c082177ea10d152b969837a1d773c83b42a8861142b48cfb889970bbfcd6ec09b01a0d633f3d2426314fc45c3ce964c1ec08792b54bea439a5e91d68b1fd800f5bfd03c3248329d548a51269bd9c68b410926980066e396059ec22501411090d3f988795d400b511d8d1b5f6048b9d3c32c2c4f7cc909414e8acaa281ec15d03fc83f78c89100c35d604bd6a9bc55d542f57596ab9b21646945c24cf6a3e830fc4e61e6a2aa0a944eb65f6f208a35ea6ca146dc0092a2ac90ea9dd47af4b0b079799ce05938c7aeeb8bfffcebea7ad23d2c37a072eed6b5cbcfb55f77ec31803535960213ba8d2fe9a9dfb9c7963f92010789a5d4c45de2487f65d85f28c6d0c38fe761f3b6add1d0799cb918044aa041e545267d5a190c75fdb613fc67f3e0dab57e9f7e7e923f955364dbc9ec0df23a83e362d4bb7f2b687544fa5c4c14901e55441e0777b6515e4604ce3e21490c48a2642cdf94e4c2f1aa5bde5f4f9e903ddfcf2aad0bfcf67cb8f851d30af74ed495f1e6515f2fa89ae363e1ba7b1810c56c1495364922aba32f85deed3d107f083e2773bca35b9b158b78538a75082009349112467d4dff104df5cbe15382b84b82c9b698e94cdaab05603f45f139309b833fa81c9026a4898ede2169b2b962370371d16a4fca576811c4d1eab34a9029b9e2f23a418cee7208e9dc85b6cba50ca3c373c813f0dbb1612d67bda7ed00f511fad92b30ac627de73a83ac15a7389502898af551915c3ec0d0f90c4580c07086085ef82ee35b21656b6f79bc5e41dfbf4d9b12295fe3cf10ee27f7154f004b2204b698347180b69315ca862242b3cfd668ce7a566e65e01e90ed3d18d290d6101d5911a697a6630c1298ecefceda2daec744d9d489cbedc12711a0f6850095b289dfbc65540cbabe34f564bec71a3930d031500af0c08db812ccf2aa55102d3ed80206bcd317205bd52eb8e178bdafa2366f9127f0b5e8250208a20a5520b4ba3d45e68fe65f1569fe8a7802a226db0cc2cea9c39a74e665409a9a21cd90f6696b4a2848e7efc440928f9659c9e214eb428868180401fee2098ee17aabc08785d75db60cbf57cf664fed4dc2483dfa862e9b88fd36fabd9f3ca412d703307f0f12daa2918a798d46f8e3cb37df15d1214ff409340d07992a3ba9b18694a01199650f58e4217c012cdb3a03733d0c6f0c7ff2a90d2d55606f17e2a1e521201e7ce83b87c08746f1097ad7468a8e7b9607c41b0fc9d42204f7139976576b10f1cb5889eb5d358351b98a30db38f38480b0b36b3650c6e0c2249b746ea01eb0fd82ad8ee894f4d14e29c08bfcb115fb314ce63b0319a14c0b3ac58140e30ec0fce3e717c2e2a22676effebb4b2dda1140c9a40bceea3750563d764b9ea470e04bdb8b6772b2ac29ac929d4b6b92d8d16d5477bd6d90b196a1c48314a72f95f0fddb9ca36af3d04cb96ca7c22d0156055724c0dc49f9517d2e65dd1b3c68125024c63791771d94c05cef483c6eac799fa1dd412b347ef47392a20dcb991415003d3260a4e561b2203ad94baf2d654138e162e0d7ade81a93ba7748bc548e4270293ab8fc15ec63d6d9d7b1d80681d1b58fbb36b0ea7f810e8f46f4d7b7b47040aa682fa8c17dc21c4b77425a6c6511d01effbebd4a94bcbba42e7ecfd0ddea50c850eb64e9828100cc57eff447173b770426af2ffdb222e4e8e2c3aaa1029c2066cdea26cc2d7ae3f3f95a407b95385ba9207190d36948814d2d58050f6aebc0f6025774dfbfb328dfe402b3523d67766fec93a061d7e0d9fd7c24d16f62c100bafee7bafbf6d8e9a0557e254eb56fd53fc10691a800b9267bf50ad88280c37049d9c2798b7ed9bca0fb999ea43c307a5f5dc499a1b0a4737572b1c00541c1b0c4c3ae48bfa48a79f54a56bf97fc69bf1ead3296e790ce0d6368a4337dbe757083dd376ee334adf5307e775d4d14872e9acfbb5887ea23d602c175677ad029f07b01b7a5c9cdae1e2efaeae791a6a0d59ae80abfd8270c594eae360ada371bc005f351c69a4f3f41bf0241e61f382e0ed5e08500e36136eed08e9723d7786f308f8d2053ef695e391095a5c2113d8c4b2955797c13d3b49ca93d9392de31e34079aff4edf22fba02e49bd82b667c6e53c6c32d666acb817bbe5ff941065dbca06eef17ff089bbd3e88245b0fe6db5ed4f0f36c20a156687f135b75e05b5403b0c628cecd89f0e682219e900cc157a0b2cd21d9814aa40667c17f23c1439ceba031517d78a9c5acc4a5f41bab12c31d4cef6ac61fb4f4da7347ef67c3da2c2f10722baaace312373fe3e6f0b393de9380478818ff63244dbe32460672c82e928064b536cfbe657f162c7250c47cf15d8a4a4ebb7532c24254b4d06f7b30196180aae8e4c1fc9de4cfef7e764be27be97e80984ef05ba3c71218a0babd22d835305fc7f432eae40a45ee9a426fccd42f5fd816afe46b6e89a2af7eb5f2c21fdcf0af8fb6e9faa6f8b45e249ae77e70b4c1f4a114cc80fad5ee6ce1606787ce1bc0c70d2b4cf9afb1ab48c58a38a3bfdf886b95ed1f0a9fac214398eb5b863d6f401f58ea3c5b267a5087904b03c87c511f7c477c226d3670f6b877e632b3306280564c7457f15d32124193c6f91836e38f1e51e09c670ff4169abf0f962eca96a0a809ef331f2813cc51cf5d5f601acc4a491fa910a788c778d69425db9a6797c0a4590241f68bdc0e2dd9a677e89a2cfd65b094ecf9952474ce9c83ce58bd0290f60ff3d728c1513869de646dec36b863be4d1b6a0608c9b46e304818fa2a44d0d9dd156209a299b840933229b15374ae08c74105694c78e515ad6adbd1b459206b538613fd322752d9de3fadd52e39a87e6a8e48803a1e858c6217841b37197005ec2b50b1ee8a78294d6a938a8a3fd35696e086840b8e2f85b388951068a6501e00d845f383bc3650533041ef0242dc73ceb8bb6c22df4d0af63ab4746f4cb0f582e8fc3a3acb2fe86b18b26efda5ef34a7bb4364195fdcc2673112884f11a094c8ea5970cd1f9032b1d8dc7e1291c4dbcabf3237f8e4aa126f84f7b1d9ad500fb96369348a58f365688a763bde285aa67c4955367f024c841473461da445409c6cf4f167a2122528b68a02ead545186307e435c0b06db0c6a88da8a1a940b0696eeb1a2127c4aa1edfc86af82fc3fcaf9922ecd7e62b9a1524a732022c7d00cd5f53a678f1b8470981137145014568dbf4c141e5ff8e5e6671c2591f681730a394ee2aabc2f7248071870aabb4b8206d46311f0d0eb2bc81fda4998441b64013366ca32536a7df7d5d74dbf0f65116fb133fb29d5a5ac2db6ed501f1ffc5c0ad32cf244233a1ece6de45020cd38b0f8927dfc7fd909ee440c7dc1476f4732015ffe4201bfb80a505df9443164ee829833bb94acc64610f3d441d8d000626004379b94ba7124bbd1bf88171116263feaa514d1bd31446413212e2bb40b2731036106f4a6d14472304a134a022ffff9dc6c5153793ee7ef7adb46e35f99f1a3015ec639e975fb52acf24846e0b4b8852b2976ef046cb139f1fdcd337530c6250173163a19303d101a9198a5e86161fa34ad747a519984620eaf11d24edc6cc8089b1565affdc9ed903823c9692c1bb4cf60eeba36b39a49d00924f8c670e4190e398383539ca06358d0de2a2158f4c5745d09b4308bc89caac1448c512b2064090efcd0c8c7afca41d5c8fe5442154229c53753ea3e333b660c94457da36330081f41b0bece83a0f684c969cc905642e1628ff7e0ec1847328a1c3efdff3efe05f11b6a12c0fd6c1990816d9621f2c533b16ac2474e1eeaa87b8477c4a56c9b040feeaab08331e5be5e6c1f7ddde6baf7a6a50f9e37fceb04bf2bd588e79f3e01a9bb1016e88a66d44b0e38247ebf5fb1a23377c5b4927a8853fecf4fc3e3fa09177949bdf418f69fb761ef79f7a919f294ae06c0dd6895abfe7e6943972645015c06402483a5aeeceb05d7a36eb53e1bb9e818a39c49996c3e0e3af16d477e006cadfb03e5f25eee3ef1ae1da9175c09866b35832283067d98783f222478f30825f59b188d0f69f916946f8614ea06de4a2861a0eebf6b29b5046eb8a0751807077f9d1e896df8d0bf9445172113feb82295136046d9750a464bb808fe13470693b4137b5cdaca5bcfb07f9f0b77f05bfc9643ccd597c08ef4d462baec2d8f02859db7248167550fe484dbc955a4695080996a4901802f49714c956b6a68950e09fefba153447b8119f473570430c9ce4f3e527f3a830b602dbb00d75cfaba019b88177f871bae33931ee3b26c1d94c73eddce9fd9dc9f90436aef8b1eee2e06d126ba313a3e75103013972b2e1e30e6ed3ddcbe0d37479b2000e6126b70a402abf09b5745233f3966c8ce0bfa01551e1b3c2d4c6b82040e9a058202b678a20bc1d96941ffb83b725fcc0b0d1f2dde1f5011007d47ab72376c300a872cc7280fc0e187bb5d9362e2481c03ad1da3e92f7edfc43f17301a7ba9105c42d2154904c91bfb95cca5d801dd9dd626c6163a936250f8704d36d7c94b84b46e2ad2b30ecb58e100d75b274d322f0057e9a48934e581f2e3702c6bc1e619b783d6e81d036cd4b2c4612c6d02927220af8014c185dc4250b1a3805e6ec7a9d3200ced7206478682d3cb52ee69193aa3d5fa750220dbd33d354899a848d562f6926b28910e9f790ca308a6b4d4c1a9d4eb0284318fca65eab48c13bfb8367a19719b7b9d0ed19f3de017fd75d0a8a73fba37cde8a46d7d1d4339aa4300d88f03129dc9c109e3d6696a7236925be8753c126aba9a65c03ae9da6ca19b8f35f1d95f4db28f0cccc61a33c4622e28e7a052a62847d9ea5b5d18c7fc2c9164e7ecc25f589f690bca6b103184be4a0bde9e0ac32bd57096ed602875a17e6a22cdcb910674f04008cad41d6980c53e5858c1fd4796ca7ad8d84aac462aaadab2408695b2a8b539085b20de2ca4968a85b8fc46f3e1a026f7c97b4c0c0e0d7a9d4af11a69d1cb260af5e292201b60955c328a7ddc74e2a3e31f5577864756636b85906e723042c2007ee2033612b209af788a359f96a0c6f88f8e391f6457caca778105fbd5c37c07f90fba02f89ff93c29aaca3740a8a97ba9f43ca764e9fb3a409215b5a708ec00449080bae2cb785e63dc3036178478fdaabf22599d65c6a3fb390aa22e285c09f219bc2c37c058373f37c9b8cd9ce7434759878b1ac4ba5defd4d185453c27002950769793484dd1726257176e110f3f6e86850e267015776a64c008668c52030de7ae99aa19826f71717fde57bb3b3e0b41872db27d215af9690093f945180a97340a943f4b60f358033438242d34a5f36fb82dca1bb9d73538f16123a3390eb524c35ccd3bcefea87838b9a983270b895a03f4f9371533df638e30d361ce07e6d1ee021f9976729f371ff08531b0787b89802fff05854e48761537f6db060c6f6e3e80783a3a5a8e3070319c7804eff9b99a47442dfec29f0185019831890abdb8962e60fa00ded0bc44bd838f595120d29dbb886083db7152938caa91da08fee5d2cfb40dd9a44b35e91fdbe204057d5e44e7cfb5ab62e8eac5483826ad0dd396f62b55de1a0c7585aeb79b95d9369d1db4aa71bc662a50736e1d5963720568bda234b54e68d25004f7fbbf7b55193e7f1ad3f2039c0dc194a977d0cd810a69515f1449c27a48b4406d624d63056ff514e759a55bfdd11041aee06cc5fc007262d75f700059177824fac664911899017c2eaa33e7349cd4b2e6d5b3d2ff06fa9c3b4d70288cb78ae3ce6f949fdb4aa4e55d08673e93f1c01ae69ceed3a20209050e37a9d62239c0cb772736084b6848ab0b151fbe15944345755fd8ee33005b7361ce325f1102640a3c2febaeb854741517126cb93574b61d0bb23939090e016b8da7878857e1c3e0fdfcc2eeec5f5b4ec67ee5e34c4c809acdbc9f6fea047ff1688c45416e3e57e9ffd984c15eda5d935bbca1b3fa79aa84debe2b60290122997dcd973bbba4ec74ef5f4d1bc96993bd23776a5da08e9bb8082361a464023a8a4263b83ca52a960c833fda184b3dacd111c44316ef4a8aec095919e7ea041e68081fc7606cbf2a91e0463b94356ae15202892c48bac0e0fa03e5e5437b0dd7d9a116fc9e4016996f4badca5af1b5e22712dd2d9af083c8f72fe746905d0a4dd0d54f26d73da6d941bf9874ab21e6ee408ce8afdf8e309ab0e711a1279c02ee67b0f76326ad7c61dce46e4e665852b8512c77f6c4549edf6e3fbfcf670c0495f72de17833715b80d8f94f999c5d828298373524620ae4fb7c005e992ff602665f38b113729a5d35b91f7eba475c4e8edc01a526d4ad2b6e55c45a8daf240fa53dc91697f479f49d8725bb16d25979247ea9e249ef22d814172264eedf8a01b775a40c27a551f95ee229f153449214f193b4c46fd2cbae881fda2733fa2805c48a2e2aff9dafb8a32fc33171ddcd876d155832b32fc5bc009415503d4d930f0cc0001c7c93eda209c95d2d3460f02b200cb5a7e31778f9750f3bc6eb24930e19769b93c25152cb2e572e294f514c44eb67b42233fbbc1ecc0cc3709faa0b0861ab09f3e8b9f8d7faf9d42d80d5651bf74871f5edf4d5e48a85cb384ebba400d6de67f0926079f56ccd18d87487065cb4b7261b56d8012e1350b8ba4870fc0a1b61fcce38e9b10571b176b381176128a73e20206203d191cd15723008f00005cd318b58658615d6f34aa6999ff88de209944ec1d0a3466fcdd6f804d5ab0800003f4a6280aae95d97cbe9114a4c47d2615e611344be4052ee933bdfb4d2c50bb06f17858bb352e8f01d23b955532135e62a98876195551a44d42a92fd18030f108d1620139d0bf80cbb174fa5662dcb17131b88c230ed7d269c69a7e45e55096f0c88d4e5c83c4490402e00724c74fdd9edcf799190147e6711b8e9aaaec10b46e247353ba07e6d042b42acb6a46e0ec0846a87eadc9d53e4a72ec24c7fe00ac48e12afbfc4d3b96684025674e85253d88ec4ba7dc66a08d5f263fb290e2800de617a3f0d059608cd803c6097e272e726a348be174bac91d8c777a47c6a8e0f45715e79cf92e407f433a47df0bfcc17cfd1a9f4ceefe94ee4d09940ce7f5e0f2d05a5ed85876d3c62b21685e955c5a69643450725deb39462f63c6c64646708c61aa914fa2e95ca21c9364965a11f19f7fa44ce230bf591fd6b84ea91aa230b45c249fa3d6e7fa4ed826b54ba82dcb8e1b4006871d0bebcb626abde26bcaf04ac9af0a4167299c0a5b49f5f273aa947a06bb6aa492f910c6d807f07940889042322f819555f4d177835bfe6453d464b321501833e5b81169569a6ecbfc4630477d071de15c128b7334680234e608976847249eb38eb5d4530347d0f10abac0ea677e2125bcfc92258a8c8cbab325124d23a38a4bfd8431d595fe546e09c0202a14d7cb39b3b84af9cedf731ffa42f321805bacf31abfcc5235133a0d199c50e7d8905937c6146f8d5b9ea80d5e82e4aa3065fa33945fca1d496d9a95003010dfcf59bf5da37320935a71655427b8b175e1145b0771e6c8ee78c13b07ecc8906406c9f13c18a6fae156e901dcc5f160a5ca480a64ee4920a224f455dd5f5c50ae38c644e51909c5f101ab5b3c4916e52b527f82545e7fb27ce98822cfade59055a76f2642c986674292d35b911208374a76e5f4509735c372e2fb28a758ac708 -generate_ring_signature 15e1e8785c6672c8c9bd42e8b0b9dfa73ed16b7312e067bb23380a5662884e13 df79782b5900dfe6d529fffee15fbbc1768ed0a58b535232124ffcc89073fb56 1 5f5eedb18339d1ea19675e00cf95acdcfbfb71c56a86c51c473752b1a6eddf22 d2494b222ddf6a368339062b29abe06a0fffd651ca408844a13e8e9c1483c501 0 f486ea9525cbe473ccb7d36b4f39c98da0d5a11435a4db701277e89205637a08c548a2a5a40f8e878c48c1fb84fc975aee4f3550eec44c75795ac4c9f1bed308 -generate_ring_signature ca505427f45e3f3327ca3206a0b5da1292e0cd7361f6a625dd9345ea0d03da47 9fd40e7e4bc7f5c892c8000666b514a73ee6603def5babca6b51285c40f27309 2 839e8769b9dd788743f455e74f7253e687cca012d0ddad7cca0e4767e4bc79a5 72e824806950403597e8dd402e2913d458aa49d39982318165e32e5de46044ae 76e8413823935c97bcb8c388d61482247026874a53b8d31daa616b6f244d3c0b 1 47f5bb2b5512a29d55cce31fdd206818b0b81530754b6c8d38c5a14b10a41108254bcaedbfdcba04fd66805b030c12d6adef005219aeeb251c4b0d422821ef03bdaa824b0c8269586c156aac66fc1503a72594d88c366239bcdac96dad3cf900aac2f1a5027224bddc6cb26095841485a9ea8ded51f57f89d337ad328fdc500c -generate_ring_signature 640933f68d149a459fd5d65fa800ed1bc733ccbecf94b17a8a6678dc6e90e3d0 7b3e6f1907ad536d7bb54b41827c3d9483da8e87b5041faf6cc7fd235237f3a7 199 e1fd6f2f9381f01f62f9027760c178dd9f5716898395fa150bd04f9c1bcd7257 0c32219292a9a10f7902af43cb0b0ac820d2618dd2efd266e36d6f7bf375b546 44bb2452da68ccbad071ceddc6bfaa5a7a0471e67235b5db25ae0c401c848ba7 ef310ce28bfbb3868d079d856042448a1890589fd919796efcf0958a6fcdd49a 6138d4ccf0a22b094bf5f6f4bb25431c73194d4cd455225e9f90e890ecc258f8 6cd95891a2d29e19eb1f2368ca8c5bb0e17765269ebe249c2c9d6e4cfec2e701 518bad14481f59ca818908ca5290b892474cb9da9ae78dcb4684df6758a12fe6 486ef59a6090636d737f22e6f3c6786d600d7dd50084fd5a6802f4d1c14aa8fd 7b7ba8bfca6105c550f82244e8dc88a3d14f2573721cbca36bd2abeb5dda3361 6a8ab23a0f9a41e4f83b815e83295d23f704b0a46bd7787e017fb003111952c6 6e629c6afebae95df966e02ff8ca6589152dc2f1a8d79ea4ec806578a861bfe7 bc0df98eab5b4834f520506a48092bccb07099a8a57ab0d05d73a1b644ce5a9c 1bf49181176e9be00603b8697bd817908ffcaa7f5b6d3483e4a20f86a14ab144 2ee400bd275960a00316ecc4f4d62b0c07c77b5b39c9ba35aa21183e01ce7576 643c7057cf4f13239a05fb4daa429764b6c4812e6b31ff31990182c486537fa8 72c592d097ea1d533270ab38045068d9f8d3de716633a16cedbfa5de6ef1d94e 397c51ac125fa63b5872e6ab21da9a04edb4769975f0eb50fec6022b4163ad79 0ef1c332ec45f12caf7434918b5df896d7ff57dd0c5bfd517a99d1e45279dbd7 b85a252d88a0f3c910836ebbc1917a5fff542a8b6e193fb17de53aa7806a9df2 faa62a1b7452db23c98f0e36f6a9978640636d2a9a0f16713e5f10c09fe3e508 328f24953c88403511a3544cda71c6011fe7dfb9d56d3f24f0ff21368eac61b6 df1d055e26e6a5ef462e906fc0deb64d8b29598bc9bd85b5458082089bc96ddd 6c212c22396b7d5581bd5fb81bbb666ce3a184aec90d58d5e44ba1de5cde5bdb 4ce80f8e5c3097fd18e3bdaf8ba2c9319d2c038fe2133cb567699bf8ba797e32 da98eb0d9f2c7b7f966f5160a318169c9ac34176486af194cfbcb3d72860fde7 4660b2e8c795df61adb43ae7c80fd13d4f3291a55af278dbd315450a0c729656 b2847cd4e5196c29d705c1117de6dd6e517140346ec2331f88fff66555b453f8 74ae53ec473006db85d690d8241a46b390c62b66038ab2cc19fbb9557ac410f7 60b875aa3122e4bf0b8404ea36c488f0dda20ff1b4a4f3a23d13b03e1224456c 781f2e0c5693d7ffe37ea904f72274a969f3ca5362dff6587bd7731e3c8af2a1 2eedc4786cced370cc96010b5be504e587357a9fec120022c6f417874e885aab 57f3046490762d405a2cf33b0e42cc077f962b4762cad12d73acfc7812e53752 95d804b52fdee15815250d2de834ef304b6097fc5492370c2e2377290094ec84 91e241d7a90145bf0320818a46cee8638b8000afcf8a79c4573b9d63f1aa75be e5c1a8968de7e4e022a29419db34f969f0a32cad3262f609633f6fb7078f3836 da909ec5404bc643cdf16d774275fecf796a3f114c333dfe55b5b5f3cb605571 3977d5e358dffea1fb052a1cc7aea970ca6f1d5caba77633c8a019c099fd5c5a f4fc33716b9d5a9aaec8707fdc0ce658cd2f45b389c8d0e5cfe68bd986999389 816a38588fb04069185b53c8e7a152992387822555e6a42678a3aa09ed256b2f 73c235791b37af8bc5d20251695df714e2001301c2c42e6f4f0f6933b68b0b3c 37a1f5ffb8877b39e7f07c497b079918e528943284a86ce6ae4bbf92111c63ab 81127e3f9e51799349ca316fbbfc66b9615b81e34c1da957a2523cbede998e5f d022b7db7aab2fa830ca163e9db126143615a14d00784d029c1ee583b95d4ffa 518e4d4eb6c823e6ab52675ec57090510eb1cc5171e21ad531e97c1ebd9c84f4 bf18ff3b5f363af34722d8703b4ab8f6c20a5a5c00e70b29b4a0e2011248d830 09dd17995fba7f2bfcaa29dfefc5670acb38139f95c015604150699ede968e11 a10518e114803f176d8cac931c689a5b9aed0719fed4f3cf724121f2396e2bf2 840cb0975d20cf39161e599dffafd50389930787e3c9f9d5422818074490d30c e079333d9d7a6e99f86881d2383aa810fd16b12bea9762f98a3420f14fdddcc2 2d966bd97f8f3942e1943ece7b23d8125c4ba8899ce0f9f46784a2d1b38e4d7c d65bafd2b7fa8030414db8d167121da88d4e623e43aaf7aafed24ee837069785 672b6a10e067b982811c24a5e83cc2d70e92d45c2de5b499f906a8a9d695bb6d 508d519efbc059adc7eefe047c8eda930330c27d83fad61c2a41b502f07d4e64 239b57469cf421c31e765b9891a5d1a42251bc9e62c5dd55be426c500f5d7e41 bdf54bdc32858ebd44760b9afb27ec803fc6ccce43f5cb72290456c31a120312 4b42e3bf898e45da9dc4c59408e1f5aaf40bf11b8a4d09ccc66b4d626784fa04 0ac47f6b42bda3688fb69a48aa126d607e26ac91a443b2d6fc7669bc52a8dc2f 940f30149014968e9cc01fec132785bb6990f01ac0b7bc1ac97b3b5eb6256183 f81895b0ba67d9850828ccba479bec869c188f2c2d254b5612d627ef719a88a7 854708c1da30f9f98cb05ca5b8b8573321d4f729a7344921a9f376bef75c9e51 8e34b500038eae8d855ed7b80b3a81c05d6664958cda88e2518bc9e7eddce863 48fb26a2d6987b3b5dab2991b90e8a149dac0dc5021b198d2dac0a5900adef51 ff8ffee9e4ce4056d5bcefd56d6b06b481b72f96430ae41fe3320e165d122d7a 0f35e5b2d3736b6a9be73a6403c6ba0f98a938cb6e06be3f700bacf83e2540b3 07334dca089b23c1d1cd601e69b5d64c1af0347861f3754274d9b556ac9aacd0 e02f32c3a031698d5b6eb871798306b9f1f083947ef081e37e7f58226b6d09b8 6a0ce596efab1e09e24f83c816a2910c0f18d054a914fa059c41b1ea4c78f6b2 57f619f188c0a869d043f4c41cf43236c8e1ce80f12b6168233a6f452b667392 417484f00663dcaffd323823225e1cd0cf76ad7df724db16cce584492173e15e ea96e9c65d7759c4a0a9be30e0ad102f4dd0f47ab4dc75af9a8fcac816528d5c c01db326db562a48369f862a6057bf152e12154b9b71233f0b21b80462f56ef1 32050cf1fe635c0df1b584a947d370f1274e290fffc192dcd6126203518e47ce e6f2f9c2565ed7a334c0ca91efe58820010aa1ec1241e1b8827b23935f6895cb bc851af7e8ee6501beb8b4d03a7f0062442d6033ba37d5ac2f25144f7d01aa45 59cf88f92e93c57c35d98a382be18f17c24df3d41d8c8db2a91e6d5ebbb42e12 31f592ae1cae0de2e4f399339798f72f287afe968e9bc56aabc323a9ca0dd278 8ee9c8c5b1d3f378199fc47099e415fcd802651e208afece1284d94b5f45ce3d 508b5b43b6344dcd99d4c13df8d80f02055f094ff3e9d7f6db3447e01bc441a4 74872c9591414526444e50e95e0006a77b98c41b70c56a647772160c77603d7e 21302e5c387885ce1359e32b0988d0c3c0b645002d361994ee2031a1c9c06834 9bdf64b862161a2556140305b68339c517f6f54a247f96f238d45e1834596414 1693c3cd7e03df5737e6f206435972fa8c100d68e5d55b1efc6f26ae85e16942 1aa6e0e8cc7840effa32f20a21c92b48cf8a676f69e3465cd1594dbe800e798d 97598a6b0042768ffcd605725132c323250013d9ffdd4cbc46c71995803fd6a9 be9c2ff2e3b3e788f89547a687a2d8990d51c1cc70be9715840030715f14bb6c ad23094b33c609916ca52ccb48bfc68cfceb423ed2c230b4230d34409b1701ee 98a4bed71cc89baf62675cf7a8617177d6ce4f7c62014274ca9a574e974e7a26 c71c798ea3ec9ebf1f59b949e539a67aee11b8def522f6ed695f433b71b159f1 b298b7f06fe863b3ae360a12e6cca2d5ad1d105ae139fc01325be21f78d1aa70 57932261b773012ce60c5e26bd7a2a87fd66d47f0cc3b94437fea1cbe0b4145f ff35cb6db2c5ebdd155010503ff566ed6d1f5b1c9a36626ade48d76254250d3e dce0046a37851c5026c7a4ed303d870e9766d84a9e6d4e5976dcdcd60f34d4bc 6d37a87c1f685b27af20795e89487f790697b5c99b97dd0a19ef0711a1ac3733 f7266a5cf5b3f7ef28fb4e2428c5547c670a056b110bcb9188ac0a4452e39c25 a2b19116391e6ec0526b4af1f0fb04508fcd4306c91c7124196162424f6191cf cb1cb1c1dca53fa0e7b104127ab69699cc55aa750a9474b9517fb375faee3862 797b0ca02fed4c418405d88223eb001882e2665c0e631dea72205db3249a9903 104956bad09c091477f9906ed41f63490a62fe6e81898b8bc7d2044c02e7a620 74773d104bc903adb07c4e8bad78bbcdb44b5eea9bb052aff7ff96daa8f97365 8787c10d273fc7c43d5b055cbb631cd6fa24068ae2ba576049e029a174527222 6b13581a144e59149e402649568811cfe67d363c2466a272c2503861219156d2 61eb9b1780fc73fab757095aa7731b0a5da2c813cc36d1e607363a37fef27d0d 7672f3451e80b4fdbb01dc2efc655ac562defd71fe7e9c785f8e2d43b7ca09a8 2402e629ec86218046a59177c682f07d298a2327e203b9ba29aa3a7cda2a905f 2862572827a76baea9b113cd3057dae5021169ffaed7353a8e8a150d99914941 95eeb5f30313df74b524624cb8ca9397c97814698fd503eb80a915325d4bfd65 02d6feb3e2e024540b00f37b5b2198d2ff05d1398e1d1c1f3b73399befa20a15 5b52a566cbf14cd15d44df91d26109ffd242010a5bba7692d8b4e180e79aacf3 a713f0c2e91fb5e99e2974efa91de6fc0609c64a0e0cd2bf849cc0ee7fa3fd36 73ba4abac7c1325dd63f832e34dee41d4189d90e64f775f904bcce4bb3db793c 0a7857cd3c77a4c8449abea91b3d424fc8f7b1a39417efdf5f1b85827e65621c 0bf93c473af049f8496ccef2672503d3c75092f1dafcb7da8a60b7c6bbb1386a 5487792ffa3566c4c3c551abda71b6d5b461add6fd81c2db459017af4d3686c1 38bda5d44463d0841416199cd4c7b5a924b1965a77ece07a069763893a9cb75d cdd3fdaa97260218c247273eb293d4e90e4b0a0a2bfa1f72302fb98e1249fbf4 cddd8cb104fed1e429b08285ae0b471d5d0bf74fd1606887171f7176bc9e1253 eb84cafe4857855499e373ef983a2143e1b1d6155e94a3407e2e85f164ba421c 46f8579c8618a783fa34d0d6768d7dce4c4460b1ed21a24d4b48117ab148ec3c f8443fb9597919df3d9caba2a9836b1a3076b78675facdb890a574090c94cced d297d85af7014563f80c4f1a0d1886f17af1a43de53b34c449d660e35d08eaf6 1855741e4cb18127641e4d80db0e585c6f3d357eaa5ab9cf134e52f3023bc2cd b3eb8bb92cbbb2248a347b7d439d6e7deba3e11c0f491dc8dda1234d33ff7e59 48eac61ceea14de3a054bd98e687cdb860ac9dad6f3aa5732c1e2b8c2deb8c43 05a7638c5fe710f66a02e55b4cebb837de550a5ce2ebaf2f036b371f366baf47 6781eff113890f0dbe3421870aaf39fff6f64a9773208450e3c6cc5180fc0446 c52ef31914ef680e9940a5d04d6faa9d5a3bde6f30e4392a9614b4586ea11fca de390cf19cc66beb0772ceb5713fc9d06233071045499e7baa08f0aa398ce9ca 50a4b637e93b15704cb72105fc9e0a8c08e02d4bd386421aa42df597cf32cbb0 5e5cf1bede2ca83f83b04c7a3ceb54283e769734431060946b4092a6e3f1043a 90107a3e5bd79cf0c9d14f7c41afad86e1564a2bc87b96b78f64448278dc83d9 5c12fd730cfd26bc35831b953ef6c88ba99c02f2ed682fcdc5a7b45eb2995e4b 6a5534816c314480e918bdc6ace3924ec8b3ab9f7aabac1e46931df705d0d6b3 d33821f1f4480e39146c5d22c5f514d12de2acac4ffa1add24e94d0aef01e3b5 0ccfdf97d8f4d1c3bbc405a6c0a05cb10c84e68a9e828e91bc95613184285887 d8a28eda02b6054603560444fb09c586c851f6d7dc9cdbd62b627f04ffb1d125 91d7a87a8f597ccdb99c8a1fe05cc9c025aa267c63a8512f4ad9ede0f598817f 095efc60133065f2367438149bb8fe64be7a8e2ee6f0b6d66e7c1d44546863d3 096b3016663a9ba25eae4b5420d5dfd2752753526b5e300e6632a52f581246ff ce0f9ef751a001b0ea6c95c8f93f6065bf242b4ae69d8f0300243e223023235d ce21a3b1d7cc54cbee8c3b2042e2251d2476cd0e2f73119ecbee806492eab3dd 93976f4fe773f35761b0a3d56b5f260358c7b04960d6b01342c13319e11c1ffa 09c8b32547300288d6e9c3ecaeaba6dd15c7fa037a565b201c961f7aee9ef1c1 decb1e86aa6a956e687aeccc633c688d76fa9d76ca8d7b99961b1591b4c3acec 530080918050c0f671d21b63e4cce47b639790caf570a32c88700998b61f77d0 1cfe24c75253c93e025d78117ce0c2a1571e2e89e1687a28220c222b4582718c c4ff26336a238471bef959ffa39222ca67bb4eceaff89a104dbf99671b92d7d2 5a306e5353c2f33d596fe151c616ed716d9bfd68237038714b53dbeee2185f0d 7c0699c7e93eef0f2cbdec06332b23fd9804512d7b9a709790cad1291ee62329 07b843fbe8bb4882fd4bab8c042dc86a597985fe6c031bbaaf14a1ea7b1d2a8f ddcf47a01055394119fbfc49ba1dbe50eaa73f3cf19cf8b60a96326333bd13b9 6884f9ea3a3c4684547f6f8613d1087ce35d5b14dac078dcb27d63a5c3a7c626 c965f6b81f78472b1730b1444d9ec15c9fb6b54918b7b3f4993ea21c9610bd34 bc587636da4ec349e715ef7cedf3ede92d7a3cb0905b2dd35046f01dd12ffa6e 901f65b107e0217ce7569b32cf50ad1cfb72834ab06803f5b53db3464c6f05dc 51d7b3ee2af84871f009a8caddb325823200ae4462e88f3bc9c94b9bff00459d d85bf76e475ef81747d3eda905cce4fa6e876605e102b9b2e8f72cda9153c8b1 9d9a63453c0525302a0d2e7737449abd52163c08f24c1e37f15a527d6be68c95 b6e86edd5fb169911f22137f1111a253fe2bf493cfc989dda1f9a880f3d5ef9f 7d072839af8950bbaf6313a4cadc4a04f152f16ba3e84ca932d1445f9a34afc2 177f7508e693dd881969727b67446fa7eb9a47c26e826d43bd3a6e0ab5834bf2 901823191b933476f034f77d166cc5bda91b0c41daa76c781bf098e13983885b 922f40a9eab5b333199265429c4fcf25f459e09ebdc63d5e077bf733dc7412f2 319fa49be35d561499b802e63d8e2c61849b7639c623785266bf3d6dad7e3b18 07cc2c6e39549e7f76fdd89aa4a9becd09d31822781a94839007720107462159 dee6471f5a489e8ebe6ccc9b1e2b16a2f6d7df7919372b2115498781ff90efb6 29ec1cedd8d6ef03d011b35c17debfb9d4b202d964164928daafc80c66c0de08 9fa044d016d3ae76f4479d8831f4005efcc6daafcc78b0bb8cc8b65f63c8e9a5 768c5cc4a18fea67f416195fe7e1af269ad1829cb8861e19afa6384239e6894e 914752c736372d835b803db11dcd48156a4123895095f124b39279da0dd5236f cbeee34f7cef744beee1fda22bff75f4423bcf170e5abb20fc7bea38cea001e2 9023bf6f93a11c44043ce93f694351453c492f86feb6b44928d253473652f5a4 124a47bc0b26b26c43f6f23a65fc74d995bbd282e1044f56298b54b599c2cbb5 5c2774eaadbdb04a732dbcf9c23c77c335bdbcf686369e6e8223cb0274253508 f46bdd8fb828d1177c62dba969af55e292901774759d2c79cf8a5f1a57acbb9d f2af226a6a889ddc46eace4b559a7ce081395056ea030e1c0f4547b539c4b0a3 faf7b038e862ac015e8190049ff5cbde4f6b437adff070df511866e804ba4959 827f334cb6e5fbb142890c745e63905e0f0778d2a170369adb64658014ecb0ed 7b43a29455e7bf9bb18c406d8220c9dd42e737967e159697f38fd77174949c27 cb633ae5fd91d1769d88557b5a428183ef703293f5065b578e9fe3ff3b1bdf15 fc811147b7c40d424c287edbebaf6d8e7242d285103d1b6f60487287afb4d848 32ef999686ffbb7655c4aed56d167d2d7292f711448e8847a1a05e55e6424735 86389e37f7bc902081321af80c748af26665076e553bad8bdffae84b5cac4466 39033a1d13f762335650c32db88aa2c19a128014946330e09a0a03ebfb06f604 f47a687b06ac083c8511527bb3dcc57b8483e295ef2f24b3e84280e739f7baac f8451f5f9935a8713f1eccb30d1800915f83e0736b8c71c62cd34720c75dc7b5 227ac01feefc3da4c2e7b452e1cc37b20e7b5f4effe6061ecde47332385355aa ced1f5d61e7b24c1f65297ed6a611d92f233473862ad54d1a7134007ffc35e03 cda1925c58a914d8b11ebc4d2668340bd55565aff5c118f8a707141a4313af09 29932f04e23bf8c4e235571f2ec07cb384da86c855d2e3b45fec4051a6bda5b0 3fe044639d70fc0e5e6757db4e45df0af07385c3a25aa4dc8294a477bf39be08 bd398f48990e8183d93117a6162841d3df3eb78811f8a84e101e5931cbca754a 52b8ec2637c8327591ce0f41a81f77603ca5d508353486a5b380f3c495ac2b2b 2b6fac9a5788ac550314d5ef4a85d855ca12f866dcc8e55f63b7898ee77c1c17 880a74bd63ec12ffbadc16c57915d3098476cdf5b25c4e8cff1de4b35009b7f8 96bb3115b7d40842c7ea3631bfe35184e2d16af4261bd3fba60c2913e4911c9e b3d442f2d897e782bcab66f0a1de170fa5171f588761a3ed7f80a04f59644abf 4da03bce5db4b41ef54d3a5dfb5140fb1794332c20c2cc80e4184549ec38ff68 cd6abefacad45eaa7c9e295c08857910943d9b0e6945ba77199ad93b5668eda3 6eb4e11f2e62cfa6164dc0ae1ada61ebaa6949a07cd88303c633835fa98c1e53 e4705bda82e65f57781a596d1e54871dc587e1a614b77eab59911c1721d0090d 34 eab35b0eb7faac20a8c03d21a2d7eeb758c3161c14552c74fc1e4f516a31cc0569defbdc2be4ea96654398883db97bf8d389970c8140c9c708e416216cd1710f66e804907319770fa0cef00cae6aae36fee7b2c08d7737d2df20a76d5627920d0a52c47e10047e6161be0f072e8d62008aefe7c2b2be8605fdb974b04bcf000582aa1d13b07305313319a2c5d85c61d3a75cce95ef64e5b389805ed9d05b5806f23e326a855b7aa0afde99b7ce3ac3ac8ceafd320570930f0bee91596eeb0c01d6b107e5ac724491ef9985797930594d9000e9b0e7dc7221083558474a7bed064b18513aed7d3d0a276e196c7cadc6bde6c71e8513a5e49e7406d0e05744fe0abe1618a0acc19b5c9489be7d2ba5a6269791b743d93ce9098060eac4eec41c0c98191ef618e472988e2f76410caa48128a31f14b6256f650b08ab24faebdb80a91bea2bab9c13baa04d5b779e67e055258b231ef14b71c717b0ae8041060f601597c9ef0124e61d978abebbdd4ace0acacfd7059ba1a606beda4d4d6eeefdc0fd6b18ca2e9390ef07869fad1d161ba24f522352820d2f1c24ea97c3f9e6746008f6b38984d68ded0aa1eb332b4e1b0fa76734ca7925cb329c6c95de76855e60bb6577c3ed4cab0aa65a2a6da4122bcc676ac5fefa9b86f06c822bcbe17ed1f080bcffb11c71504542ca054c0c6162da4da2d2b7c1484b2f3652acff2ca94a60051404d365ef03f79b628ba3bfb710b193e63aad5d7f0f4bc69249c6d8e13ce08467cd348b5e89ada62b9e38ffaacd76736d13d3c063879667f19fc24f552260757df2f1f0b4849b0f31ec64e85804221a994276bd803f9390a53e87a04e8770f0534e0d0a44ab77ca558257fd22b4ef26b74efec0a43062aafafd1c7b0f78d0b1e043ac6a1275329cec962257ffd71ba6519aa7cb2ad4da9507dd8ea1f0cbf0bb7b5eb7f56017acd43533f07ebd90d736f0da9bba8e273c954e171e2bdf96b050255b4c28e773caea463d2061142fbef5dce37d0b8976e5d990a93cffae8d009dd6e3779ed5462d258649bc0da56f1ada0750bb31caaccbb50c0df4d063ede00b4c3a77421ec734358755befc2938b4199e2c683aa8fc924407fa151c32e190b62a1c6542c6fc39ee08c3e7fadf6847788d22632d917a372649a605ba662540b396197a097c6e5414a2d44742fccbcc9e991ba0d6b57c3494a60e65eaa6ef406c19aa0fe9f584587ad09dcd0c2e3c22b12313e54d3db36ca8e60a7b836f5470cc22791fb15394228bee5cbccc65472dc62eb4e6963733d04651b713ea8239c02a0ba61e5f1d61020180bc5633bfc536d9ca0d630c6ad3f5084573d7bc9766a0f2963b0f1adbcdcf9b53f5e1354b273e8c0d142a1c1c1b6429fcf7a8ba6322b009d2e2af428e841a5ac67a05dfe304d97476d37a968c5993cfa5cb62d09f3bd0d8dc5c94bdd0b81a02e53b728a5eaa24b96591f70abef1ae98b7ab07d0e48910a7f56f40ddf7919a6824a2f492f95a2458de211fa488cee1bd34c5698294e850ab454c7dd6e82d547d4f8f283c57ecee87584eebae6b177d9d3bd8d9c68d93d02046bd7d99d0f726fbccb4e24b762a01bad30aa9b525d537d878ce29ce38741045079e2a813f843832576efe11659baacc2510cb21e88759bbc772294ce4b41058a9b5acf73f73164228f76c9fc84f74fdb9fc0605306ada5991b090760c16205bc9b587093298d7f780e45780a0f969fb7abd3eea7f3a56335c6d9bdcb798b089cad88617d7578834ef1381dc38eb1bb98eda40c6d2fcdf1236acfad70dc510640fac254465a4d353b0619662471b6667e2398ce7a4a652cdcb9008d84cadb01dd57e070f179a8d0ab14f92b16f9599dee5647d7b67d46044d9120b46de2a00e6e52228e540c8753d8aac6068672abf64a7d499fb5ab4db53fe596b3dfc7eb0c4e03be965cd11ff438e36a67fff418ad7219053f5a017eb30a635d8119a0f601a9fa844b4b908a267f185690b875abfa621e9c124dd98d2755e8c0570522d80fa5a0fc1cd2395adeee91f2bb008afde5759b97ae23e7a45359d5a01881eaa108f371c4eb774a63f63f2d835dcb67a02eb55b153f467ca47aefafddbe49a8f4018c82adc0a7aa5caf94f5f86cce3bca731cc5d8b3168a92d007a55221c92b690dd99605bc6454b4a2a57529d2aed8fd7ac8402fa3c34f2219820f2f7818d17500b663cd13990fc3d19bd6e933d83abc531366bceccf6dc3f6e678271f8d5ae809fea97b731887dfab5e168bb0c95378445893260b85ba775c3f5f5e2f293ad20514c669cbf62624087651b323f2848076cf88393bc63c707b6357b12eecb94e0904644c9de8742f331756ac61accf7c37784dce1de81d399156e8d51d8c35c70a80c654a623cfb1e8c113f33ff274192dfc75be91365f6d7c1e32a327bc9bbf02d73268f24fd6d59d3e9cb29b46999b330ae8e47de2f9af526f7016979bcd27077b15dcc01fed4af99996a6a169d565306a573495e3602085d4064549bfc61501ec9a11cbc159efa2ab3f708f693684d657e8db33c645896cb644da4f661f3908f8d0228d5dbda20f6c6eab73b7b259571090bcb5cc4af91e180bbe44ac99550a15f6af4d16f80400e14ae4e007942257dc5ee8b444862392e6372815b2989a0e810881afb76f12265a0c72b3535a8e9ed7ab86c4b838ff7230a68905e54bc10c38bc5673e1458269614026fb9d635701af26def6241aae2efa00793e4a76850e2ad6b2035c90131792142d410f673147650a95738355189575cfa523a530ef0cc95c98920ea45f12ccfa512041d3142e30a7978c4c818f563f6dc21e9886ea046922aa220bf17ceebc84e6b65ac969aad536b43201e2ba5627e6a6b458eceb085f4472333da95697cb94da31688fad2de9bb1b0a3026d20609a91f6b1e220f0532c3192aa07b64daf0bc21716792564232fc295c36e99cc26767ed25d9c2eb04f2a1eaab5f9e1f50c061b6eed766f7023649fba0e05a4dcecb356cb3a0a4d503dca2414b253014bade51656835f41b64337624625605f488fe986c8c75a48404b43d38f334e194e4b9e0c70ee0ff4571dfdf1be1699825b18076c23477bf790eff233055e4b65cdb628783b15d2e3fbd2c680eb3ca297faf7cfa0e16a4293209938cee000e291be6b19ac6dea46c532762140c237ef55fbc22ea143601ceb1000434a6268f1fdcc484e2495aa0a2bcb2f46ae85f00e75d122852a9746b3c410c81d10645a1e1cd4d2fdb783418448e4fe6ac22dff3569a498584620fdacdab04c964b70e80d45c6d04036f9d6f50cf0e11d60c3dfa2abf1725f7863cb389bf0e6347a96bfbb67e81f379da165b020f5b58745d4a87035f7ca8b4a9a9bd4d6c0a58015f58779b921bfdbcd2ee1e7592d48512663c138913f4c04580a16778930e4a51ac2271a3942f79ca265a8df10af008501e129048b8b6575184d5544e5f0b0791c5a6fd02990a9193c2cda4743a48649807c679f349b20167842ee39e41004cadf3fa7c17771b008d396673f7de1f502fcae72ba1f73ad88614410108240bcb74f5731b254a9d69aa1074eca75a9af09979d2daae1d76c9718b6ab9aaf609394dd906f1d778af8e310916fa8c09ccf4891773a36e6b0b8c0d45cca9f4d20ae20cf93f41c81b51122c123ac74b67ed461a9a9dbd486d3a90ff62b48ff4b30fd49dc8343363ec35aeacd61f8541bed134246f08d09b295bcc9fbc7668e1090b151fa9c0aa8e4700db71aef6aed6a21fee34463edae033ed97a38124c13db80bfe522b83c56d38ab982e4fab8f8df10aebd284f4b14214b7d758613f5f37c80ee53831bde2d5a94c4063f5a329f0902ecb5b0bb38e599dd0d890da04516042022c2557b93ad33d5f5e80a16692d70d0b8d0bacf61b10a1ac12b668f16db3c70977554cc398d34422cdaa93d19b85fdeac17f337feb2cec7051d69b6d7267740928902ee3e253c307359d2ef17a8031ad472aa4aa4cc57bf5bf8d1b61826bd401b15588a414a35aa6349c69ab5c8866394a0f64e8ee36bdc83b4970b46ff63f02293d8f64ea8c0d05d5f9e859e48038cdf33944e037ff0a082e18b226fd4d7404a87cddbdebd154ca2b429c7e43217872ee687e29c42e2b6ade8ce2a6e98ec2022414bb10ed9b278d59af11a1b5df2849179c50f2ab410f3b17ec75ddc52c2f0e2f90b38642eb70118de75092cd5680117646733ded0a43a281066a27b5712f0da08efd9798f0c2c77e04525fdbf458260263bfe830550178d329f368ceebed0ce18c2c49211a5093d86e403db13452a7ec4ac04cd274a668e089bd80f1f61503501f0ff65cf5f963d81d55000b4235e9ade97214d06410e8949ae6de698f5308fbe56e7644dac995b943927cf9b62c44f8cca03b1ca8b0a9b9591c4daea5800f2b88612fb294b178b95a4ad96d1efeb6ab13dd42d75971239de80f2ee533750e17d92f3b15d7c922d72db517a0eaa91185ed4019f91e41fd39ee41ab58dc9f02561713db73c1e3afbf17bfff5bba516d4c9468e48f3eb67b4b8f4d562055ae0b223a016022b2b6378457f0f3e8dde196bc10d2e4c040d1983ead7c57039f1c0b755f8f63d86d084fc9601223e89bda043adc5839779d7fa408d625fcc450a3003ff5f4f8da4303c82ba03e8b5db1e5e1bb95fbaf18f6ea4b16856a862aaf14089da16d7c35f229c48ba351a449827889d84ef124e1bd811f87243ddeafe482080711354139a90591aca01bded11500981a4da6a6b81c894caec956e1a47aba0948f5745e7e15b88a7b80080443e342737ec997125713c9ad2411e5ea7d34c902d31a412291f52ad92793e3c4afa8f5d90a04366045ab5f975efb433e9f3a57002f5daf31730ab1b73257fb8389f7f260f94e318013a9398fc2506acf5a282806972c721ea1cec5bb5eab247e178119b6a8ff3e4fb5cb5a67a850a74220bb0c098592100f75b2103b3fac1a1629c7c26e5140059b7636b34f3048316a5f4e790aff6e2ee6b59b124cf7aa21a34d9697718495db4bdb65d7d25ea2712c26cf710d6fda52407236a749d455fc172e38d3448afb12de70c9cd18a319cd54d950430471af0367d944920028d0449952ea565e2d53f09fedcc7dc4c2940fe59a494a032b7833587757b7c5158f8ae87bd9d690f779a2dfd0139eda6de8036bb2509700391ee788e5088296effbd14e4953ef3eecd6c0a1ace19d7cfb1a0af28385950b9060b6dd2b875407d4a1a1e1fa3d07fe9b45a8cf841adb323baeff578f0c2c0e4d6a249a512d1236da0135d3f9408b5800d52ded63bb119e51f8fcca4118930ba8d90aec1ee1be2dfa5fb795814c4f7e333925b50747d6b0c686311d9bd0c00d9606b30b28f742426667daecb39197bc003191f92b7f0df945d3324eb2d7330b20729f32f7f182e782e13e570f0f0737e8cc810986986e490ebea392ac391f05f823c0056aac8314dedd570dc9a623d8254f0e782973c0f9685f5e6af5a2400e20e0effb97e2abd96c10c040f1ae0a99666ffb51550be723c2d30767c8fcba08867e75a900c35ef3ecc3c3a28c64526500a6736d250bd5433062e3a8f3443f0374eea01fa289d85adee1a9e2b0d76705a4bff6efc11d97412d28bf8baef14f090755146a46bfaeba4ec6a10b27cca291f4016353a0fdaf9e5dc29afca2d85f01c6ecd40b5acd71f32b9e30e329b9e0dc055088c6de789518875f2b5c4219f30b0bcf43bf91fd20cb0150f7654a123e2f1a12a3d03be327e9610eae6c7fe7d90ea6f866f8cb4bf2772318dec86e4e70fa548321833e4c773da257d28160997802456ac823100705c0cf5a7c6a4aa8b7647a95ca59eadd1a02848f5ddddc8d96068e7a015756bd066721f758a438f041d915865dacb86ab3dfd07a5fa2b0060a0ddfd57bef8bdcff7a37153a69155b19c0b07d7ac2c9b54efec05f5d3cb21fa40905c03e21b8d203dc00044e562f571ca1ff6727ee585699977ff6d1b7d7e45c0f52766ca41327d51ebcbda56d92ba3f5e716aae70bf77c13210d82249b46099015f90aea7dac7bc56f83cc23ded6ee71b342310003f11690ee180cc9f4a6ba701cf52141890f067e5d5bb57aa2f4b07c04afc3e7c29ef6a4a157cea168ce09300f628df435ca397927dfa5df9bca36ebfe8615d43cbc90ba91d0b679f0f696d0905b76efc5b932f13ecffed9fe1a01155247459b02cc2ce60510d5cef99888b03be252493123e0403a42e73eb93b3c60dac8fac42eaab7ccafc0fe2d2f4c7b60a754663a499d5a3423ab74588658d5d35c8692f4e4165e2545a5878daeeccbf029d1d7bb94dc3f91535f262ee9a11de7326031510dce9f5624f6b03a5e30bd808cd35565ec0f1899014e66301469385ece1f93890301c4d1e33e31c37bd9ef20e3011b5cf5bc24a578ecbe6d4f7f5de29fd06e04cfe3e790172bdc63aa2bee301c2a7efb5173417553d2f59389d73201b1d6536fbc963dff96e2b995be723d903e00619e3c920cfe455a4942a0a26fb4d43704a8d61fdfd8738b8ce7bb1b3840f669cedd06ce21de81c02039503e2edefd1c0ca55fe4c5a526ff489d720a6e10130d7539107110285fb6fa54532a00eb7eee2d3986652c348c188e821ecdaf00ac25d0bec27b0d9a4ddf5478676675afcacea9c8b9cc7f4c059b6c85a3909be0b39a740381d9008fabc6f7e04b50b6c925565f0a00cfc71af58881061d3e517056a4873a477f9562da01cd499c504d7f202c3535fb804b1765f7c7e2f6e00390ac86894a1e34a4b0913f315a9a9f18eb10c6f4a3051f7928ce78127413860cb06a183342f910339b8e1ad9805a14c1054f5b4fb2c9b25284363c56cbe32eeb80f736154daf9525492fc776484cb0c104def46f9456d1f1951e3dac1bb52d351088a97d5bd580e1ece6fcc3a8d3b79d591add4df080de958dd1b5c52fb7100c20725e748052672e3e0ae2241ac8c75f70654f0914d8338b03959fc317f95b7e801c21fa172cbc875a2a3b6d1e248344ab56eac7a0bfed84eb013ce4835ed9d12035075702878cabf3286c3838cd05283fbffe21d12b38f14ef6c331b9e7a4f6a06fdd451981d9b50e4757a68097b26b8db036f33aa889b865b0043aae77060cf0784979b396c263e528004d0dc5b665315e994605f21814c89d8428e1ea8b87e05125856a8d6ec3fa6f38ba862b65831463b5b8fac5888039500497043a930430df9a07b96f0026b59a2dd495a5dd13a8fa21bac340c0d78d79fa6c5f57db5f40264c5ff156f58d213b6c65ffc3040db37922d9d0bb9fe6c8ac64e2896cfdf620ec1b232cd5d23a5cfa7e9445cd8876828d3d840229dd7f1d9241aa9f60cc32d0fe7ae7ab4fbae1f572ab13e27f17346bb43280c5f59948e33fc66ad39fe80de02ca16f65bca4b55514c460528345482c4ca2f82937aaddb8a6fb32f09b17a5000fae2f9da3eaf2d3b79aad176178d220292fa6e5ea3effd69ba872c7b3268490bd9e5668d6f18f142b5a58614b132b1e323f32849547cf1c5efc29ff6c447210b748657658bcbfe7b306e750ccc2bb6a82aa41912e369bbe1602f22b65d3e7f07bd90fcffb2ae1fb2f73687585fdd4d947eebb0795596feab9e74473f04e37f0854b62134aeb671bbfcfdb696534c2c51315de51295041cbd42daa08dc9619d0aa39c897e3922c5fe8e45d59933c9c60e6f2bcc00c2b3c5e5c7e8f2411edbe1063624f26fa6763e09e9b5c35cecbb96df569e8b08628ff789813d198833b52a01b79cfb20b5253437b66bef30fe184144847d0a6e4a4aeb4a141a9d6a7c63930febfd7829abe1277cbc8adf2d7711df55834d9511b863d95aa49d6ac164ae4908d1be4a68793711ff9a69a31b49e72f54925403084aa6746ca35eb64cfb9b960fe2ca1c4dd9194f9542b9f321a7941330e6a2ddb4dbc03d4710adfc7d9d6c1d016edc722a77771a4487ceed1d8dc08535088d3f6e3d6cb0a176a29752f1ddff0a1718e2aa5bdd6c2370e0f4f5c73bc4d2b4a64382da48b968973bafa31f2ed00bf456612516b33b043aef2596c33bcfb77136923c7ca0b7820bd76fa3f520d30763d6f76bacf654b1cdcd7eef49dc82ecda4488ef4e3101514380994935ba70043e8f15bcd425915cb0d045d617f86f03b7a48725b1c074f0c6c8fb8739aeaa00b50702bad512597cf5d2010070b1b07595bdd1f251cf2ca0048ef5c3f0c326029f31d92a9be48bd82fa45373d51f78d330ee34b48ca41566f5d0d55a9a117e0c2d12b176b0db888da562ea3290c8144b8b7fb2b39c8ee8a2d7786e9eadfa8e09eae0957e2e385f64ebedf24f2b086528c74f4bf2d3907d73fa38d3e829db470bcb3e7f5e3b9650ec9e2879595872adb8245bc57f323923ae088d5ba0554d540395a8a23097b145115fc1d7364509bafeddfc9ce4b7521e5c19f9c0d21b6f510a8f0c747b82a36fb921599e88d0d276a2d65468259572f8478f7794eab3314a074e5b43009b55d5c61369c35246e7fdb548d3dd6f2e55787babc64ef4f9c2de0864906a765a50b406ea7e157929bfa9a0c38d3d40776070942405ff5e52cc9900606e3c1c55702827f7d57bd2cd4f0a0f65b92297ccdc3f2b76cd93b918e540078279a2ff80f0b35023f06e61322ff75237cb0ac8d60e475341b17d3c92dbb80773ec441583f4d400c98ac6845e8542c81ec4b8fc8c89fbeaa1f860ad476e9b099e03e0114f58ceca9cbb1fc3ea5df9e002f6c32c9db1cb3d7939a066e06ac800ba4f9b587482ceaa7d3e498a756fc8aedb8fa89f8a34799daaf2c3bcf09e1702b713ac06e2ef92db96dcb37bcf2893e88d48d2838c28e4bb4e86b6aa66d0ee0a326075128cfbbf7625066751ab00fb4352a9d0492b454463dae298b9632b660722fd38245e8cc023ec6c134bdd40b1d029b3c6b724e7d9a5171b618ea69c7b0ec4bdbeb6930fb9dadbf4d65d9aba1e9a30253e4bc85903f4d3ce2dc85077290fb45b9f586848587f5c60694fbe34f9107fdd21edc71faf8403f563a4d3e4750c06eb4c82e30604b9645606cc9f3cee535ff147e5be9bedfbbb4a9cd64fa5fe0f4d980faae30d889907e1f67b8b400bcf3b0f2d55b9da858afbca8da48b57310e019c3dd275865c319105ce95d59db7284d205d242dd66028f94a4140fc1c500056b45bc6eb4a6962a567c2a3abc7777193b5a86376170d4f17c2401e2f91c300be2a042d78a7145dea718005dc73fff75132bfe013d9d8fbe39839d8cf6bd3086e0cae4af81591facd1dd20b304513b57986d533e1af38f4a2f23aba50be530d33becb5e996ba173fa189f45fb4df11657faad34f838ff2e2c07df9f569f3a0497300606284757373def299631f71706b8a8013a6cfccb1249a797817c098507963dd16286e02fe1feb3c4534642bcca05c6a3d35764cd166d603ff18d33be0d9deca603b0020bf9775d811547a3d5169c36d419f30036945954391762d1480123ef24cc93b9bd52458d55a274ff91b359457fe9188b77c2d5395eea53e42306bf8aa8a2ee36aa89e04029693f8d24dc31398e86210233cb8447c7da5214230ff416ac2cfd08fb31cb7bcc7407acef6b6d1ced36bff4a0a6e437aefb008e04043429c489392c40ac316bb950143b2f1b3b8ee1725fdc9fcbf91cce00a0fbb8084a28897842dc2a809d2b06a17756a622affd8abd40d2cff0bfa96841828eeb06169b780508e9d8c386fb8da4c2d63e03f53c060132c20aabd9a60dfd5c0d840dccd5e395f9395b42f15f698d5c4eebe8dbb517cbd089051bbab054917d9a60044bdf5b333dee103500f6af67208d5039d5e8b63ac6e67849af2b2c1b3665c403f6656f2be5c08a580f7f8e34af051e156ac0258daeb411759c39becd4211570d15f31d238ffbfa6dfc6157de0e7100d58ba5a4bccbb75a01367a9af9ce6f99034d92a5b879c73e25d81e3b736791f987029fc698fc2f40399f922c68caeb8f088f54dc16fdcb680238273f7b9ce618c6e3c1ad609d7781a0f80fa3116c83590c3df53f8e01df16c3b30f12df42633707f54f8b6c523ad1c3d3be548163905e0c4b4a75c783e2f0bc1e401d54c3057174e28d9c925891ae36ffbeee0184ca110a9eb6da3198a02db5e88e9f5fbd2c73810ce09d5ec7723fd6ec34f52100e03d0fe75c8a9f1cdad646942832fe70055688889edb86e8e0c18aecc5894e05472a04d155a070f9f05a87076a9457f8ab605c8363321df1f525bd19e561ece67e4105f58453971474653d49b70acb9c9b4d53d6ed6b2664a51c2d2e50d9b947bb8d063818286da859891dac3dcd492e1a86ef18ac0153b272feb3bb32c7d61b56be00e42856593ed9eabbdb70c3172d7d70026151a62e4115670935ad1605c211f80fad9f20a958135e787b36b92b9e057f999106de228d7543bd0a0e9506d0938e0e77b86cf4dd2f9faa3578f4377df649a47b7a19532e0fb64e10ae7aab51506a040b5094f995ef556bf9433c7f945504d72084a8ad64e73f40db40ca1e1a487a07ea49d395c64642eb8c35f35e55a497675b9a683f33a11e585ffea59b0fc880095dfbc9ff9ff00a671494d9833ae8b0062c0dcf2135cee3b6a24234b7a7cb170a2acaa5f5378fc4e2030c8ced0496049120ed285cb57df2f6609a3583da40a50e08b9ad3f2535275e62362bce099f575d10c6fc066240ce70a91152afed87280079293a02f83f5b4d592329d29807a7596d86fc52aa6c8997023ea515dea81909afe4316d1e189fe9e6c0f49e165a6f77c7681534ee26ebee26ce12e437ff4c09b694b119794afc5d103b63f32b26ea40996ea076c4652370703101c005c0010f2a5844e6d261736acb580f210ab1da9e37f3497cbbfad97b2567b80430bf960db480076ce40396aa7d2a88104322af9ffa868065664c36b5ee277e068cbba30fe579925de2da9aae4c74efbb9e37638e8e5e5b6246a75623bf12fdbfc1c30d0c567b59303386beb0035690e34da91c76bc30866947cc1c327821456d731431063cb7f993f96c2a47ed70bc6e89d9e59f5209e767b7be3fe32c5b2bd15dba5b05765a2a50f860436f23bea831633f3f5e589a0e2dbe0f15f27f752dd7364356038f50f56a62cb35af38d1662d972278c7fa5998a430b5d6a15ee95a24974d120b4e6a03fd13c2b3bcc0229dc3d50385845bbb16d0945bc10557719ffe42b8510159e5eb0e14c591d83b31c955a3945282a69cb6d31dea5fd1e483a6da4226650e8e21569cd75a37d9b75687afc7d636d17bd0ce2241fb21a0a069388e331dcc04f3cc266394525534f55f6d7a4e508b0080520c31d5aaf03494877afdcdb05003f1a6d8d31ef8e07c66286cb260699f7f018c017b11c173f513fa1dcab063bd043dbd213a41db96f8fcc402b5ef4c5f4df947f481f3960b96e5b7c2045b56d20a7dbb9cdbe115bb40d27369287063941d551e891f752044b599130f94103a3f04e5c9a4d9e7e829fa35db4a7afe66e98d584ef7d73d3daa0e743b6b312d46110ad3bd699bf2935043ab2d7a41ab7c3d95a45db76a75c7e0d949c4bba5836cb5042cd4ecd74cd6be5f64b8aca6f0e36c90b9b946e9642971a5a18414c8d3063e01d8a906d49756da16f69f456d7b5e84c22802132572ad06efefc250c3a0fac50b2cb5d17c198773437047ec7452a8ad89dccae35c8c0ab4fc6ae43618072356099ce84afc5b1527e6fccde920f73b242e2e22e187f0c9134efded66c3c2030d08182af5b5d1637f214fa808f8354fe39a2f1c98a2595c78ebd758829d6558de02ba5abc8475f4860fefe1450571d9c5c8ce04b72a79b2b139f5a1d6484b6a9f0f04b8add7a7d8bd8b35593f63b0e4128ec3b1623d5a602067fe78176ebfb8fd0e530d7c7e298d7dcae7fb3a1e24bd2345ee515dd30484a1b738b4bf11a07e27060b3385e73d29fccaa464e42bc0835e781f1ddc79d53e2a5cfba5e2f2be117903819ef7a93e9e37085d2fad2305b3d1f315a80db604fc467c00dc4fc8b462d30bf4145965ca6a511fc378e587daedfba4f9984f07b4b1293c16d91355d2c2070de485003e58bfc9b0ee39035731633c5745575bc4d3c66e6bb8986a4c7e143f0c7ff7b4efb46c95e36f10ca9443ad485766e9687350732626f1d38f4241f6a209757955ac6f81a4f8cc40b61ebcb88c97dca2774ca40132743a5196d23cdf6509d454e11bd66116aaeb70fe63ba577bdc6bf7f8d619a4990046e834eefc55320fd61da98686829f22b2e70e597b48de276904566ae221a8ce6352d93b35657a01a8a700fd041308c38ed8b35e940a16b7b481b51b14fa7d9cdc8123c8d78b8d0d3154fd72e954575f9add4ab23b5ef6d63fcfa923065a0e164f008eb4dabe320a51339013fb3fd8cf9fb1acb930a3018eb66c7038ec8e9f391342abbec60e830d0500479c6e825b59eb5965b6214d2a76e774ffc1a12dd0c78a141438bacd930da2f82809cccfa517f2e6a97e79f83c27067febb7460384a6094d38fcac97ed028d25bcd904234a9ab70683e0ce71a675846705994c8fa6caa9a2b23725f2c205825fd00c0b71da03e28eafefa2ef65bbb794f603b46ac425e1dcd060a86b210dad690318a5b4b6dc22a1b02dcf3e08cb6bb005288a267acb880253cd91a85204ff6db55410b720c2075773eaf6f415b3cba32647a3ad70eeec2386e355c39803c705d22106ac35c06ee8e6a05fd1d5f3913424325c9b0c869ee685ee83355b0b39e02f640aea1aeff172e4a12f8f6d996b6967dfa10ce1f70944aa6eceafb605f6350240249269b83ba4ba4695f710ed6ec9b3b5b7b7e322883f24d712cd2403da325188651210c0a88b8b443257a8f760627b3633be35314cd936a3f09ea4073aeaa7d8baa8aa301e435981e035dc2d212b764fdcc9fb65a8c04c0b39086d09d42abd7a8d438dbf16bc1e4795091a00751d2e5b554bb0e9bfee1ac62f014f09593122988773fe35936b57d59db5476dccef7651fdaa0d273fcb0a5b106c3c08d9ed733e2fcee4c97f649380b5665f111047a6fa4736ca70bea8f3d1c3a4250bc8a3454f9a88323bc670d0b1ac52e8e08b66c92505adaa95ada0b80929d4d30475be64b13829d5a746d2b3f3ac654388bb8f63e722da0740fe77996751cefc06558d95bae44b05b1351c6852f8176e3475410c4adfa7923da407735a44b71106c5cd8fd617cc727530c0982073b9c94b2b1d7ff80a7c2e93b80182514f2da10a122fb6efa275d9aa48a14803913174b2c5f947f88891adc4e0bf3878c9cdf90c18f1a17f51e8ae766efface1df8fa0483e35a72e95883d9efc4a443ffbcd350886c158ed55f7631af84dcf9974319a87bf6f8478f4bf23752271b2df831af700d9ed970afd8d9f0cf599b4e5ea3f7236a104ba3a82b54f5122441bf8158b550b86367ffbc6d71137dd9eb048ec554ce0c6a88fe2cb31157a94644f1550ae6603e12f853b47924103dc9b347126d47595afe689be4f36c3340aa07447987e4a06aff100f13c793b149c03abb26390e7a26a89a4a3321ff1164621fc7b87a999000208bf895c9193f87ad6d9649e9d6a37a642ea3e1b287729be0ee6bba6f9c90ca625305d4e2db3c2252a5b6a62e8ef322ccd2b2886e78a6ca3f6b5b3822b1804cdb228d98043d0e90a89406e0e591b2f90449a33860a2a7bd985b30497d1bd0545e402218e840ddb7b3f4fffb00a90295e611ff5ea05e4c0ccd8c7760f110705c88f997b8a3a43922e5df0b61be09b236feecb23c40dcaff412a81b5d1e1730291d0378e9fa5f737c4b8adb94ddf9acde32dc6954b2b3b8890254ba4123e18059082c254010e93de39be364e7f31f67cd0c7afd22b9cead93d7cfd7eb647a40dff518c859693cb36300d8f3f425fdb3895a407fac43228cdca6b431e551df50f874bfce2337677232892b364b8d846a6fb7417e85919680b2b7644a0eec22b00f7f2edb10a7075a67ce59acc52cb3c0296005df044afa5c49a538715cbd9ea037a14b1ef399072d8867f70441c1c12f4487b7795413f5c4b9390dd59eb58d706f6ea3212cfa6c883885bf17de4ce3b38788ab699becbfb6096111f74ba624c04fb34419b03daa19acdbe83d190b6772ef62a19a85a59c43422d87e9e92d59902fafe568ca0e9f65995d75dbb75afe39b7a04199be7a1d3eda5569be6da107c06f163728d3e70758c9824f8ab7c6dce1af9f7efb973d1bc92b6833a3b16e01e0f57199751c9c678221e4723436fdbc32622b44f9e70a77b1c461bf7a3709a900bf39d71a686e5aa8422a20341bdf318490377000e467e390d2d3fde090eeeb806abc8eb321a1f3473f93222da9f7cc423b8259a69ce1a7b897e8e000fda4a5f0d2f9f046bc6c32f4460c063a0ebf42052d50a3ff445f9fd1a7bd546da18100d05f2edcd3d4d8bbdb990d4ed11d66184515eb595e2a683e348d28a65cc8634de0b4df2a7229bfe47ff76f889330f05c8aa7d7bfb628b425f2e0ca9cc2c1171ab071a8cb373b96533d892896f7e19156bfd20197d0ea8419009b1cf22458dceea0dde173822faf0a3ac17da322c885782b3593e39f440742f72397e8e3f8c15a30494dd94997e13198abf3e37e7e401be4255646a942adbd493fa44f40c376c0d070b67eb0cbc008b598eee224a9698d99fc11e689ec51fcd35b9bd2a38a3628f0f8e5c0180ae8219774da53ac6c2e71ae9d84a083c3371bfd491497d80e6a682055b7840e0f61df614dd1e22e3a87432162888e7d15b9f64c5a3820584f9de310cd14a6dc3002c6fc5e2c80a19d360ca95b384ae33ee8f8dcaf29bf0e2e7a78d03a137f4632eab694b217cc3bfc5a1a0ec1baf4ce03f573b0b4d153936ab82730990c0aebf8e429444c26c7dd8038eb16e465d7d51545a9e6e7330cc4e9e9c720529e3da56bb8b077c013bfad5b86dbd52401fde7d9d9e1c3798652c6a1ee0c00ccc74087e3a9fed0cb78b2b6532c645658459239e2d410c4383f672f2977d3f09f63c608b3d76ef20f97c4b57edcef1b1ad6e982625a67907c214dd4d6151ad02d414b1c4abb3f442c1d91d42b83dbc5d64f55199f675d613e6c6cdd7644c80050551eae8b0d36d8809c1f4357ba3a4486c4f881b7cd8506bb0a8e3a86b57ca0a1c85fbf97e652972503ddbc33a8bade7e0859d9ae7fe1d54fc6d211db533050ef9f94c06737eeaf8399ae4d5f7a90ec6b1c5d87c6938a982d0951c90df7b2300c4222e8af0b157f89e5889fadfacb299f5dc5fa8ceedb5f392090633c8059a0a9c9e55da44295482fcd02412755951bc77f979c768344f436abae112227394067066199773c7ba88fb6fd73b7740358bb3efcd93c279edf9972f6067c8c1940074f4e5195b3deaab16528994bd9965148c39196ce2753cebba6bd464c4c8fd06b394b48323b1e68635e0faa4280cccf9f15571d96552c29cc5a6ab34516c030006a90c34de9ef01deb2a692da67e3c52bcc2463e9f5636bb38eb32812ca7ff038b211269e6eee27c1f64056defccfb589186580a0e02dab10c0a68fb86edf00e6207072eedbfeff52c58e90c62cc38bf33189703960d60d6fecc9e8891ca85028d464a4efdcb52f5ec9898b77c2adb62c0fb434505084ca0410e2c804cae3c00e69afc48bbae84f62969737ff395ca03b3b31bc2026ceddcf7bd92a3e67faa07ba8c65b2bb2258137f223e21ec362f95d39ee0c6acafec66362f0bc672fb280a6b883a662361413609978b11be0c3064c71f325988143042d9b807b47f268d076d5d4e807a5d0a6984df81737c479fcbac6f6dff715b2c5d6a343e495ff2b80f1719a721a9b8826939f8c4aa7b4b83f8fd6378f07407aa082aca25a64431f500e9852079d1380ea05fc47ca6b665339cb9256e3348ab0b78b7a74f0ca2c2250826497d92cb02405fd9dc99e4e1fa604aa57e11fbfe1f2aee3c58d2c0f141ab00b141c9cc659d693b4a764a298da0e80f797b88a8c6d0922a10ac650abd6ead08a3beb5df09ea0a2ffcfc03e02638ecc1014a31a1f26e763abe94a153d2f20507e5b3674585dab8a95a85351f6fa5466127c37ac57707f9d0587fd2ea7e6b8100d019d24274a0140619acd9c0ba0a20ef09702c4d873197d4db29288a586a9705948a71d9a4dc22d209f6481aa913f1a519ec0d881ac3c1ea07f5ae2b88691a0bd43618e093ca31c99ee842a2218a1effc76d826c42c11cc04d301983c4e3a10e21b101867a044da01ab1654670ef513f55ae830124058d814ecd359aa175ba06854920cf7e3b430f064f9920ac09f5c6167002aa65eae2e0af13985fb3329c0809719fdd73947bdf84ff5e935cbeaed2b6b931e7d477b314756e3d18b6facd0425a6a7a1fc21261b51854cf6d159cf767d9e233f4a1e2018fdac49470cd18d0f36448ffee53314787c44607ba4b71128b9279f43eef41d614b2615fad9b8f70538d67496496365b1bd714da324212dd9c4c2e60ea34ba1579ea54f9620d8160a725c27bf2fe60bacb3130284ec9e3df41243be21240bcfc82d3e8cac43db8606d85b8c7309c7fd24e6fa047d1f5c40070c1928adcf55171a9fe5a95d46cebc0b9a05af9bd49c2d28ac5da32765b3e2e64f222f680fda5fbce47e3eac66cc510444375cf3823302b3cd5c97406896ca931d78b9696fa88a926ffab60ec9aeb80a42fbd6f741568cd1e2cfcecced70d8d2c93d1e4009003dfa49af4e844216f104f1335b65757bb822548525fa68fceab34ab40bbd5f925c1f94b53c32c17ea6097fb89cf9e7bd36fa3977797ba380843b08d479fa47b5857c152bd22e7977b80e65906fd18a5268546e081e85d6befdaaf3c4bdab8d03429c81f4bfaef06f110123804f7710fef85cb19800a5b5c381cb85fe81ce4fde5bf71747de61943f1a00b9befdacc4ede14e0f7836813830cbf9ed38a90cc7fbf21864991b85bfd12e0bb241875594de4aba4e9d6d0a1b36d5b139746d34e885e7f8e3bbf6678fb411074634b7b7557b66ae7571ac9cbc56951df39140b3ea7d64f9f9a89d4e0a4bcb0562f9eef689e1bf86c10868e952e06ebf619ae25dd39f65555aaf244c1481ab0dd995640e281ef327cb9532b2099c61856ced7d73904e0972efd9bae3c37b8f0c3a6747c3c8968622bbf2b2aba8b3ba85ba62c526a28e736143d61eaee37c95038cd1b43fff3ad42aaba089896678c1e29844cfd7a164418b7d34d7e540f1930630d68e1b62a2eed14924c1860dbfb0320848abaaa5badeb2ad70782428dc0f0362370be553d27ec964c927e75bd309e6870c7815b08ab4d3511b592eabf561080c2249ffbf238bf7ebdf73e301e9b3142ab71c42e374d9b51ac24fdc4bde9804a2b87a298e5384b8c73db89349f3b34ec0df8f2ac5b18bd83f10809eecf067063deb995376b3b92b51e9a4fbff1bf671afe97016895ca72bebd874688bc19009d8a14e268f80dfba9edfcf4f2e17a1dbd2233b79ddfc3d5c9388e10a830e1a0984c8c9e6487ec31c17c2403648e50cfef67b1d47825540d72f37da28f709cc012937fef6e2d5ce5905fdddff04bc275f8ec83494e51393d78144e1628512000a6dea0714254e3d68488a25143010ba0e1f5c42828e6c014158af4d3498a34d03bb5f7ff5326ddecfc3fdb8403e0462339d679a1904802626724b9be3a747c306a2c4057c30dc64937f75f3991d22688c919f4f6b993b4c40adffc49827de500b8564f3f020f9add5627657e9cda655a725c1a81c1b065750ed35983ab73f9e0f543ddfc88c0c9587e47a8352d50daf3bf177d7b8258fb02c17097efde166a00978b627b8442ffff6478ad6fda3820dcdf8066edeb1223d7d76ad8bd32c48f40be9344499ef950180ebb5b19ff218c0b322f7ba009179625076f64fe087067f090a5b33c004add071f32e7f253086387632d822faebaff2d353b05e6310a5f508d14c5634d649c161938cdb4b55395e790217918fa145171ae53de2e225433709 -generate_ring_signature 7864676e28d3c4970b0debb0e6f97ea408580a98d226dafee3dd81f5a3487cc4 40d7c9c8b56934e5a5d9a07621a15fb22374327fec4fe966bb846f06dfb62cc6 1 494838f14fcf86139012741ad7732de1d344dec1773830005b3602c49e363c25 39dff26442e1ba3eda6724c73174a46d8fed8eca7523ced7781fe134b2f4400d 0 b07021b3ad94950c2b00abb941b78f962476e6060c5c517fd6d459ee96b376092bb36bfcb036f60c82a9edf627bd65efd735d65826b568966a6224d98754c509 -generate_ring_signature 2e56246c092a45724cacd88af27591f7b36558138dc9f84551e343f3e5f9795d 79b775c12d319addb422da0e67ba0569d1d04cfd608980caecf219b65feb465d 1 fddbe3aec2ab6a7c85a14e5a631db26aeb656f75311c48450ee02dfa54a7a16f 2de3c5a26614cbfa5cebdcf016c9a87afb79822485174be1ae85544aa2a35003 0 16386f62533726a98fa5f36df670b8dceee04f824c35f6e15a0dbb6e3e4bdf0218412c5407c4fdfd442a16f03b4d85641d0d448cab0f9b1da3e27b121d4b0902 -generate_ring_signature 7815f1d4b85b2fa3d55770abd44e7d7111f47c5571935d9e5abaee6bee223095 bf1e67b2b20d957c19b829881f3654396a78adbcb44e985f7aafc4f5efe39231 61 d3399fe1944fc161ed48c41e5199c0d1543e1983de4cfd5d2c410f45311b9f00 e2166c3a7f15b793bd2403656e289d1689feb65f8e6fa9b7d46a34005b261107 b800cca2346900c2e4a7fffce98677cfc8847b83a5c69915a3ec51862f302555 8f8b9048a0d2f4d0e0de1d8aaf9760766ab3b9e7cc5fa3254ce88f951029b04f dd638dac03e070da9c635e93ae6250be11a35cfe9bcfdbe7df3fc5041b11e63e dd85beb9d51168206681cb9e2d07315dc15c19594df7e2119f073566d80d8d97 31e92e147b4549910056a05d60cb44d95c258ec13b82e57d1348265626c938d1 f6d071a1f002aa6b543a8f3c5749255d8c9e659e1ed46e4800976e953b82bb1f a6b081eb3489da635b97f6cb6878848c085a60d8b567f08b001ae48ee1591649 372ce8f0c084f59732aa7312dd360760dd3019a073c8cae656dfe2fe499004d3 01c7206287219eb32f90879dee2d05f3ea36557f828e4b91ba14d30c6c36273f e8220e44b09d67dd1ff189de878989324d964281b678e238dd5ef329332c1b19 226dc13531650b0de4c419171f4265fb88bf9b645396c39835a627424d3162ec 1eb7fdedfa46a4eb222797815aebb70e1f3c0a1bea9bfa3a5bf999d2c2588684 53f0fe809deee1f45adade3acf4b4514a1d437639c98cc9562951b7e95d28e3a aea6a6fc2cb0b865ebeb9047309270eaa1442c10796f8b2fced7458cfcd0e57e 214b0b9af85917ceac889de8f197bb26c5226a60aae4dcb812395e9830b7b185 59ab7c5277761232bb784b937b97290407dc2e22e0712270c18561322dd25297 5da1f62493bde6c3f398172047c7de1217bd463249a3279193df9b6068d2af55 dad11f986df301dfac98557bdcf96e36efb105e458cc3157494319b9eeb90cbc 6ed23b5f3108a39439aed73fc45b313eff7b198585a0de020ebc72543d4c735c 90936fc627704467602d21b46ac283168dc6a8081d0ba0330e0e08f7d8e9a255 0fd25a20ea3a833592279b5342ba758ed433a3997677e84f36a96bb0ed48c985 48b4d1123003cd14d0a9e7c323d1220824f536deec12a4b887a31a35fef9707d ea8c6a93e31262c5ba1be8c81129da5c5b38f4b60290a43bea72ba8a64bc498b 17b8f47c4b2ad10e21427ce62990cba355a82827add46abd01b0a9c6c2bfdea0 de19153bf9d58038d4f0c6cb613e037b2572c641f4bd71b1447aa4c93ac75438 26b47b7e2b2996a659afd62b05add0068672d724a4dc18a33ccb083bfe30d760 fc8adaf826a43673e332af17c4dcc381d69c5f05f82241202f799ab0c75bb58a c25fb0b991261f8b531bc5ad19e62b1b8055db902c2b1a435823c3e9856ed4e0 c46d960e1541d03db8b945297fb8cfb6febf632a151515ab0579595ab9977695 0411911de3280f44aaee23820e05effb2b3947eaba456a246a29d3c41814f5c7 1531a1532463934f0bc7ef7b30eb947a65f7b6770c55689506176dbf387553f4 f620c8e1ca6b327fd3646bf64dd2c94e9acfa3b4d52a008ccc2d0ad6db5ef896 82a462271505cb720f9f9234ac367fa6608edb83d33c1de3d92bbb3afba19b16 d443003d8fca22d127eb6acf6b26c0e8c4feaee60bbd276e19cdebfa2fe20acf 2b3faa1881c5ddd2d4f4b2d8a15872e4c74c1c6d3bbd54c5d1c2e334857369b6 8fec354ba1f19ded18abd2a28812c09019bad7f4ad07a12fe4c3a0f7e5be1521 ccd228e8336c7edbf92a2faf42c221b890a6c2f5d48ce59cb6858551f93429b5 c36dd157fad2ee13582891fb642397b4ab159de4b55fdc5fdaa6a01dd6763249 6d750ef9905133a6073dd0043fdcd7ef1f0d0e7b68aab2e79321b5f904a9da19 800055a80889361483f078c8be0f37c455919ee300b6fab6e637d31e00433b12 0ad3cb33206d1f80995b7ba6518a7626739c1b4057d5169db2f39e78de3e23a5 8e077ff44226cbee60be2f4d75befbcc46e691cfb60c664c1209e1bbb031f868 1d4fbec878de15c747915bc2942331ae6353e2ea2b1a562fc93b264730dd6c24 5681010b12e8f47019e0308f2952ffbe4daec078a63c6e8452bb95cd2ef6ef09 53f5417119d15c1df61673eb903a9509011c0ed83fb8a6863f8d972bd0f1c6c0 a5479f031a8eb4eae48c0881a6fee4fb3a3cc4e2a2d372594d5ff3277044fb02 c07652126a9845578a02a1512c77ac191d20a8318f1f1756d59d14e9f32f2830 8c8bafe3ce09e7721da3d52ee6d63013650d18c8482e57d501c3fd7ee5b0e9e4 f865858cdbb9fb50898b084136dae15caf9574aac8b712679d4318e9edf7b04d e318fb363e54aef5e7ddc0aa2340c2afdeab63e262688c95dd6efbc7f5a2aa1f 4b01b80161b7bcab306ccff59258d11e994258e9163bf55cc8e652416d817be8 5975d6d8d944547346f31768e953db73941c6bc1a189836012f77b200ed8bdfb f9e4bf1d84793e3702091f8ae0d833c7480e474666b169a0884cb84d6e5f55a1 3b161766200c121ce33a1ace049b0b65e29fdd307e1dcde2afa95a4dcac3750b 9e7861e59e8d3dc063aea6f094eefa2914851e0a96f12332a4dfed98f81e1f7b 363cc8d62506cd8dde52bdd490a3d3de6c3314303166ca2a8baf8e753fb3db0d a1e2e309a4dbecf825cc4dc6cb4a6675c1c4c66bc77cf63c5e19e9554de3e70f 282113e165a5ef3f6327066b407b464d2f23abdcc0a6366bfdbd10b1f65ecd07 7522f8708006f4930053063d182a25bfbeac061d4a499d1aa7687f910a2b6274 879fcaecfc2dd21a62fb8478768194e0efe3a920592237ecfad527bdd042880b 3 3f631726928147ed30c75af4bf2c5864eb04b4b4772738073367c36f6ffaa60111cbc61cd34915a4fb8a406e0fe4611ee28c99951ac18fb722e81602d3f74904326d17759dbb8dae65c3647044ccbf5f79477220b76b2cc219932fda9cd5340ca980505cf009be3c9a496d68f93ca3f52c99d49b3dfaaf71bdbf71d093efc20018ba9daf425c152a6cf945b30751ec9a964e179d67b01db5d40a1ec477de6001c19a0a336fc28a1cc77a433694bb1c543ff015bcc6d180c0ddc5d8b2723c1d034d6ef3d4a0473f869484280883e2e0a8aa210186cc4b687b28b4970150023f05206e35ffb427891d5284f4614312b36071f0d1e805a8b54ff6c500ef99f73d0e2d87d138dec9ca8f1307b40253a7ca159828782e07a06a8cf9e15c09c5365e0502c104a4acef1df809f439d3d9ec7f4119132963b2e66e7dac6529102b84e60ea05e061f51e3e358b723810a962ad21e7e3c68b826321c18a676e3c8776d4e0ab854c34a34b2dba312a0b8a662126021825672fd6a8ec3b6ce1b2bdda2aacd0054ef2a648c52aa2c8c0e97284e8d43f6e51f5aef1c402ee14f7b34f5db7eb50b1fd9bec7beafcf5a6f236b62617ed41df044a59094961c4673a5026a6822bd0d6af74dd471e2d4a858ab15b8c6cee50e7edf2c36f8a5af990747c01807f8860c64d48093d3a8d6af04a92b881b6f2dcc017507a44b9986d27d9e0739c4478c045e3980693515dc3397a90628e1c1455ff74ec892121e650ba2ce6f64e2a461047abafcbfbacfe6ce332a684e9ab44ea75b117a109b1adcf202591793f2907408273ae83e5a3634715e13bbd0271ec1259827b7d3b8052e989a422ca7eda91c06f2b67d7d1893ac1180198a00b94265ce7ec5aaf3ffa3a9c4dcc013d256ed5606dee7686092feafb1a2628804b1fd5a840eb5a6f078c9d301862cbd1f5bdc3b02e5e6cba8797f50b49f573747bad9390d5e547c7f3670b05148461dffb513ec0b9d1f6e77320b11c883c4d2624f253f99c2793497659c5020c9c498e6a653e60b38aa00820f9b7bae02a3ff08ab17f89b48a3b59f2ced6ee22dfa478a3dea160c79836ea350fafd9dc40747d2769568aa93560e2f7e681e1ef0758640756d770405de9f99a838fcba6afe49b4b4a2d651f968318112c42bbfb26fd227a6a22e0fc5285ba21d30bdeb3d4da89888de0a0d648b249b54e8898341f6775e74ac3706690e44210447497794b2a69f58c6ad199829b4419d96ee56312c9e5ed3972f0e83d70c7e4a6bdba630c154cfd8b10a9800896c278735172c20c86e9d8f48a0070a7f29259a84268fa2ba607d8aa0de19d767599db6fb03ab4c0d7dfd2df97b0c98870dfedc4b69aba8d88cc436f84788fb2dc300783508cae34c999846553d0bff9c1a02ecc087cf45c2fd5d4c99045858cae3aae821216298da845265fb66061fe1b852627cd0d16463b320c6abcf36577fabbd0da0695edd51926ec7a21b0910cb5ac673662aa3a31d10f2f1582037d28332b30e0ae9c0bc39ab57a0bfdd0d8379de0a0edf65a9fbfa4cb6a4e707447603cc1087f6e7313a24f498cd61a6089bbf6cadfad44c1062405c52bb8139280b51582b5660940f6ce9e70cce5d21027b0493e6f2645bd327a40b367243765c72fb1e9ee190628e14f7022c5d878e0a52442d0c380e43b550d713d68da1fb9d598f7a537ff8cbb9813bd2a41ad0cc0b1361a9f29a3a7589436e71983b8a3d23ae2f85f0476cd0248a946e0bef9f870a16c0c0620e30882281d8fc97551c8083657f7a979f21654fb73ffcfc62fa9a04b39206b8da73342d892360798344e321a60652adb7194690b9d7b3093f538d014a7767c5baeb5959e5fd81acec9973749547309c674086d1de9405d34c4f56049497667487ccbd19834293563b66d934db21d8ae5203139aca821207844f660ba8ce39b383c2ed9e7f62d98472268feab6427bc9bfa3543437b9fe14cd73680e6eb165d92672fd238a7cf1d64567d148e6c6fd100984cb4af69e05e5d9aa8e028d72ecd27ffc1fcbf35ef5675ae890c0788665c554e607307e0ee7b1c27ead00bb782fc919cf21e09d6ed17107384a602a26bf817bb4c9541cfac1b907173e09bcebbf86af32a79d2908224ddef1f43b3d4e2427942a9184bebd2904ecbfb00ab020d696bb077d174eccde7df10a6bd3784b78f1061e0af5f557a76858160b051f409fe1317ab73ee9febf68fe787b1227ed5ee50edb259397a1cf2188e4330981db66828fd7ebe5b42713ed7ce4780d488ebe7151e2e0061b46f94e532f4307a59e5470885cca0e8895d54a7182daf327e9cb3eba38896ba1503dccdb44c7094df1651e06370a2ba30c99a2fb6578b84fd36345e0d52188a3f1d88cc030be0792f17a6f68da8bb2bd0e7c86285dc359299e8f01dd0cef6926d847555a06db08c27e9e16ebeca374cbcd8dfc871a09f62bbaf292fca50c957004df6a04ccdc0bf661311325ab198825bb380840bd2e60ef5fb38ae030a077204aff3c7f52b80377fa4c8210e3a4a2f8b8a5d4e1472106733a6a48f0fb72f6e942ef30626fe90e0c15b3c9dd2ddad58b745c6b45e8bfeb479293df5a5a810f4545b80e118665064fb6d574db8c99f9c599c38629d38c45aae348d3d59a423935e7f105846759024af878e313ba20b23eb3115ef2dd9cea547bce638db4f1aa3772e5823221920700e76b84986685272ebb81fb7914365cae882dd0c99a9b872d718f76fec24f0f6bc85ee6b9c8377f94feffc047aa07741f748f09c2939d732b3dae046e0a68060d51e2f82ae09893cb904dd61610aca06b5e5f4abbaf2e626fc54bace3a9e4059113e6bb992dd30d58af07a8ef042b500f4fb6cc1cd8e55a833e761d083a3b0b07cc23c17ff527ed768cac05c498a1bf34d3ef9a6cb781127b326a9465f2cd04e2e6091f29b3dac0c422dd23ca54d1b992e844204d5394452bca2dd2f47c1e09592cd6c516b7f927a1ff09e873556ee8ae2de87efd8c5a2684ca42f8c980a9006e26d71717c42c2392ef59b60d912a766041415df373c535104dd402d290bb021fb9504471832ed06aedd6674638017bb5d714e88bfb6b5b473efd87c24dc50a93ec6626e695286de966932c299f20af54504dc1b3d7bf93ff0bd258a03038058c926928760a30db939cf2dd7cba2d8e3ea165b4ab9bc3de22e4f1bcc48d5205efc78394d64c654f345be89c9cf4dde2a0185833058d2136d0a5738fc380cf0fa623cc9ac6a3308ee2748b6503c26bf4176b08a3793673c78b7d09b86c100d06ee5ba85af63e8dfdda1ab9deea0e6b98a63dac2efa4baf37f61dfa5a12bd8e029c24505f8f7dc577842024f8acd427fc12ae0f4f091826ffc0dfdb0e3942b40fb15fa642ca4cd11669a5a39c90b3ae93524019e380f7df2cd89b62b5bbc61f0d11ef3299ded766472e37f8346ad29945ef635566dd663742279d950effc81d023fd458c5dbce160b8ce2f9c6e3ea270322938b1414a179a65caa8fc94d58bd060fea849a2819331d73bc4592142c17999e5353c2897b402340a7dc653491240693ac39ead4012645fa7c46ef91d53ebb7c17ffaed6c325f266a95e541737660df88f8838eb6f055c838d2990c3dd55eba13fe08f1d0f6c3dbe28f4ed74e67f08e4d79bd76def62b94cfdc06788c8ccdb796b3bf02706724e81b6f24f528f030c31a927a5b35477c67eb5eadc06bb822b018efbad736616246c4b395a9bb89a00d57f42bddc9f8ed6d258a99d3a8ffcf6b71e6e00db6c357734a51d0e2adeb30a317a039d03c1f31086f1eefbfa811261638c5388f86bf5ef7911006287b92d0208f6d4ca4c678e5ade8907b7f0ee13615d306bf43c16a04b38ed6bd5d4bfc40916f42dedf5d9005d5fee45f9208b4b0596154561347f909598723ad91930750b0274ace6998a031bbb1c124ebb481dbf6afc93b8871f8b76a15ce4a876a33d0fe5d182c78c599211af0ffe283074a8011a5531ffb4710628afcbf0b79da9090d27b817f12b1afd9d84400bce134e06ef872554e29c0fd4174fe6ddcf0dd0520e7da6e491846303b78cfca2ee55ebc7994b1960d8c82293b7efd053af4930800870c5cc62d7e2228f6a6bf10df0aa2b87eb842296ff9854d48040a9e7046c350fc9b60f435c30635941e9140913fd2c1b71cededf2fd42fac3c152ccf87d8010a4e3836c427b16e2efddb78efb203ef3074a5c0d55640bcb6c1d925f225204207af9d8725bede99d3f7d8b2b17665718c50bdb49922e56132d7f20ee3b878230a8427acc57e2fe7d52f87d9e82391625bab2bef706cd62b95cfad1d9320f15905a207ff240a7b8098016fe8cdd1f88bbd8ce2f26ffa73754678e89ac17322270050fcfb359fa88971c7777b8190486908fb0973bd521aa6491e110eb9f173c90d23f2c7fe33daaf3e2c561fddc68dcffed8a1d6dff66c2d5f27243ffbf2aaeb0a6838bd775348c53a2ea251fa4c69d3c998aa1f18853bf30eab667cbe91d94200f5822ac7c1c00966763b45c9f5939cf1f9796417c299f76d67e14a399542240e058dd45e96e8aa5c8504fb567e3e30f7b88183bd42198df8528670e338a1b70ace2485524cdf704a80c73026f8c1a205c90fdcce66c073dc6d7ed0487f27b70ea3c3154d127ab3ebdd84623cecafef0b63d27692bcebdae98abfaf342c8a3005c51ee09d0246502096d2a57994071ae266bcd091e766fec6b84193316e3e7e040ef4b2628f8cfbb7a3f96ee76c2adb53b0a0d024649e6c0493bb0d3b2ca9110902bf99ecd39cb6b0301975e8e66b6f704d1c0b2cb179614d98d2a10425853b04837ffac3267bc9555099566b7ea1553c9da7ee1d20a8d055b490d9521813440c6e089bd8bc4a7494ab74d9cd435f4691deeb7f653e18036cee654bca38df160e61d6f37252c317ad6ec1c3056afa60f7c98709df765224b271342916fd5f2f0dd020e56c68e20a0ef3e16597481b692faa22c8a0954698d89c5b6b624853fa054dfaf7564bbebd9eb56f7487314786febcd47ca77f6aba31fac285be00c1cb0949ee6b5965ef7b020ef8ab2f4c8c632b64fef41d3505e92e8c58609db0d88e092ac172befa54262d9696defd21e761da873f7208d656748c8418324db0fa8000764cb1bfe49d1e225ebbfbdcba65fe6f2dfaba654a8d36b0b0c30280b97fdc0e412ebcddf566bb785573d44e2aa58c5e6a9628b65ebf2424f8027ef62794fc07b6d11ac0c261dfe6163084448412eefa21a0192f933919618abc9b1b0c14ac0538fc99939060d17646ba8943c78253140adb7231eef26346b182eb6ca395e20fbfb68b2d262752a6b065b312e76b7db6c0b9b5e13eecbd0aa5fa3ad51c57f808c11e4847a74a4d058f69881c8919c3c916a39219b7d032139f5a4140693d22091cc2eefc1b7733ab74352d45cbbc891b2e85fbcedd2a13db08badbe20e762207b0165d6d61f222c1ca7bcbebe010f9a1070ffca89bf61f77a916563044cd1d02 -generate_ring_signature 4c4e0ad8f2598b7d77a053302d5a6795c381364241b30287731d6c7d063e5253 765d90a45d3bedd3c6ee22b5783e15ae9d418c64dabe2683135027a4e0f0d47f 1 f0aa7e8a8283be703ec37480d9a1e445ce42c58dad7d275752bd8ffaae075f9b ba659efc83361288e75dace789db89084f3970e73518e0e8d03f939eabb5fc0c 0 7059e63d3f212eafab3b404bf15149aa27b59868331ca891d2e6bcdb53d92a07a0900eebde58eb56dc6d314a4a30001391d789a25d5f2cedffc2ba082dbb2505 -generate_ring_signature fa75d79801a1ec122a36862796c333cf133a930d25ba2faa3cfd8401b1ce65ec 64c40ebcf87adc0ce335ff113ed46236769df40a1bfa9dad5ef83d8babae3ffe 1 fa560cabefb92c708a2018c978743b79a348ec2c3908c74c44f619d4a437c2e5 c6f86b60576c5b4f0f03bc9fa8a52482cbdb490b0eb9d99b79e319609fd10c02 0 bf3d4cea305878a216195cf4e757a054a60076aeba7766e2d28964f12390540e6ac9af1e64d31f80a26ddf856af4a8b0a390624c82dc46e27b4098df7cb1950e -generate_ring_signature 7c3fb9bb3ee4c42954cafd7b2b7e8cdc0bc46262e1c01911002435bdbbeaa392 bda43de0bab94f0f16ba11829801217e25b467af70657b746544a48667d928a7 196 3d7deb9d2aeb577cf0188c2f8e3226415e5c4f641e83da62745d8f20120a2c46 4f74fe1cb3af7a94a70f3c562eb98142765e1dfef4baf9f38bd368b922515c10 ba66623e0a2b563d871badd3c5dc6a1492d92839cd3aa5d2c0eb5f70c5f79581 71b8b0d917a73fe39ee5f2f3113a90b9b26abd07f56239ea5b326544359b19d3 eefaa73d07640c1019bd2f642cd443e98832f82d7890c49a2ea7d01abeb71455 f9d84b3c3389860cfd7499393b13ddb2d1d47ec3c782fccaebdf892d7341fa19 1b0bdd06f4dab389ea44e9d7d1005d501af618687d00940c2443b84e40e72136 3e1f0672ef333d52cab1cccdc601f87d010c82611598eea47c8b445823f5d489 a8aaf0ef9003a56517acab915650d7dbbdd51e702c2ee3d84f3e62fe0d8c86a8 eedd4498a0d2c6810091b0dcba02ab3e34e8dd4a4efcf2dff9ab5d91056181a9 d020f2842103fb4d38bc130cd14439b4a4957fcc666dfb3f8e9cea602d0648ba b2dd26957db1ee390466b7ff7b84cb95d8989a0aeaa0ddce683b254390d6a6cc 4b72466a6f2eb480af8715b9a37cde092b5beaa597f4e6e00746ad6d2d05b398 f921877891f56881d08de5ac9c2981c54e6c1d0ae2b16c7cd1a677b198864ccc 41f35918409892706539e055bb30aa7f2fa282f432e13fe769af5b0f636cd69b a2b4d259f5bcc195075eca1ff07997b0377cf25d771716bd4560238839867e8e bb4fc78175626e852e68fef83df8968ca5f5c4f81e1e6112ed6451b9d5f5bd7c 4edfcc81529f6e8888764bc5e41a1fede7049dd960f5a5d197f229a5bd1e707d 58e5461abca133964190a634685bd0e149628bb202ca0d5445c7a852765ae82d 0fed57463cca6186faf243735eb3ee19296afe91474c492f5489f8ca8a9028c3 7274df448dc3ec321473fd02de58ae70c0e27cb95f0720826d7853fdbdee48a9 add935fdef42a91396a34e19659a13fff9ee76b437d4084594e7575a3de21b4e 993ebeda5d18e86f53235876c9af7e6d10f3fb65068da9bf3afbb1abb464f52f 1099ba8fd7f7cc772abe480fa5f216bfe48f46e6340736f452f5e59b10182349 1c5a734cab5a13536221c7f83bebccdcf2660425b358a30a13d49b8a2c832cf3 c0d64b092dc9db3810f59e3fb8feec10188f38d31e227adf80496f775becd04f 755a97fd034508b8bc2702ba1250f5d71ce48e86c7e351e86790d2ef1ff825d9 e47db52ba46c257338824e3adf22706fa2445fe44805d4bb94b5e0ad8c47df7d 6b2ac3928ca6dc8ef22afaa034f66fff380bafa2674a4cf490960fc8b560dd9f 9c1aeea7d25156d1a58b0252704b71b3db0228f17c4cf95ea71b2b076a8b210d 74215b03d16e45d3b251a4c6367b54f8ae438f6965167fe5ec3bb645a5885bc2 013aea76e7a4f7c15338d048a54626c8fed0bd291661963e1f3567923b1eb93f 97c048ef8421b828ac7c75253c51ccd77e427a6ca6390d554abe773a947e24f1 a28841ac91711236b0e4e6f12fd88bbfdc09e269a6e26d7aaed06c3702efcfa0 e0b8ac3c9851b8aeba1edf45b2fcacc18d7834757c4df91b1e14b102b215982f cfa5948f6bb9b6e5678f5fe5c45d266c7c9fee864289ca3dfa79ce248f0c0b79 db95bdfd0f2429c78c806dd772fb934c3acad4fb5f7393e25b521afeb6a35c38 6200b0a613b936303102722aabeb1212b78f6af51735a3f0d96bd76058ce0267 79e29d799a6afaf916f0b5ce30feeb0eae2c9952c1ae4d7708a24067169b4ad5 20ff221440a6bb518535f42abdb4d5df26b3297a92b74eabe8d660510d103919 5fd147c22101ad4fbe7fbcd32931d55b13c55cbad3db68a1ab3f6996ea25d03e 01f4dac1ecd9e01bf1320587ec8674b88d34205ca51ba8483ecdd27b07f7ce02 73227647ce4ebde477e0cd99631d977fa049e3f0d016df930d38794d45ce7c32 829d500cb72ccce0680b7445877d1b1ad89f9d643f7429aa103a655670501f43 3f3f0ada3115f1dcf6079c0867c0c9e3c9ecd63c5d02920b12581cd67bf4251c 9c0a5f030055125abf6ef7631709f06c386af32ba9bc659647f6f6b349588245 56ef91cc69961d6b417ac27d82ab9a7c1b56fe8ed7935e6802487153eb8bba15 6943def5c2ada8d0d78fd8da01a138c16737992bae209444f4b02d5b96f3ac2c 3517f0a7f5203714e1b2da2723af527b99acddc6b48733b6cf23d0cfb6a4afdf fbec53b91419e5f4c1e9ea47c499808c27055492101ce15c85592dfc9f87fbbb ab7a6bc753aad0d5485f332d260f351b75115bcdeb32d1b0a1fd0d8421ee9ebb 6d24d7851f0cf26a3ee3d3c29f8e69f4546c90d9cbd3402fae623e07d69b022d 1ec91aa4a3898b66a1ca297e32940ef75bf5695d62408b11e46b831b25617f09 78b9628ae4e16b74d36ededb48245ffc70fb823ea0e2b7effffc34d4dfb8d308 e9980856b66d6e29bacc3272d8d94ebd638117ccbddce2f8357dd45ca32934c4 3263b10bce76a36c53c3ff5cb9d439c549c7de8d9e3e28cc29ed094ea304ba73 7d15f57f8ba68ad9c179b94a752888ca27480d439b13bf7b22e0f09c30890c29 76806ce6f9f66d86d585658d049c90b7a55d55035e7b9f426f2afa2c295fb6d3 da9630706b7b980a5e17e988ae2ff5dcdd0928d3baa3b736ff8fbcbf5e6acb4b f8da823972eefbcc84a68d34ec0cb69538491d96d8b9a1ad25ccd89bca2eb227 2649b2831326133828b22a7ae2dd1c2d794bc80fc92fb219bd038e20b4087aa1 41dbeab376c0cb3badd9ef47886d8e91a16bd176babd5c93d4222eee59583951 507d4bf45b583eecd177a2d7de1d303e908a9e7b326ee66c384074a19d0e8986 c4327912595750e1b4c774dab82ff6251392fd3f2901ed495552ab943896afb5 de7c4677a46a08361d3748d31c1df86d6a677a46b2fc52fb18cc8c17e631f9d8 bd154b97db57d73e1489e4aece2e891cc90689461a32ece0adc0252f2ea8cd0d f85947ac2d27b169e3f8668cb5d309c93474e2b4e39d303ef00cd22bfb516488 ce68cca1c16786b5f84d2d1b6be185c50bb7e06b6587fd12e88aa0ad55aef1c8 fbc677f0efe1e33b870182a6c970805dbd587f7341577ffaa2ee0c20e73e2b19 062ffbb81d55a0599d07c2e7cbafe69b85f1562731b7b6ff29aef4910c83f8e2 516bbc709109e873a712e6ee502612fd247531d24de032f46d104c6968887c99 147992743e4b8c1e638e6c84d6b426544cc49051f098366837217ec6839b2832 283508f305a819032db1b7d8e5ce5f6e9c7591fe555558d5e18c1d8308acc36f cf7ef848184c876862e4414cd556f787f880025486a4932ed1428ea22ea83e5b 688407f0f2c3c3e1d46c2481b4507245be9e897b6e6bf2f71ec42ff60cac5233 eb82880ae90623b8601b37b8f7f1cec0cf463aaa4c7041de35da6bb1e8dc3383 be18599f4111c5d903acb9dfb4c435768a3003f1ad1428472263292dfede4e14 036c74f81ef0d9812c60b77d4d996fa358d1059b806a17686115cb91fcb891a7 56c13bdcb883d9ba092af5ffab17ace1bfbb6a020c562e12cb02c8ac4aa56d78 c0e519110a5cff1bd58e27124f7c2ada7c4e337bb8c6df93c71ae1e01c862bf9 58596e856040f9da1b9996da7ecc4eb82201b92d45c7fd70f7a365b95bb58b1f 58c0e7620d52079f74559b40e84bd5206ff697e8a96a236017d646daff386596 7d9971daa6d9b033d5fb18153c941f468874eed0db6c31597e7339d0a6abb824 1266519036a3cb221de554081a56e9b6ab0da26dca30dd1cda0a08b8f3ae2e53 7ba8112ca27bf3efe3fe5d6f839dd7c60c904013e0c299fca13447cdf4046a17 23ccdadf7fb569338fe0880f84c81c843d32fc8e51d53d0e6cc06288441c12f9 89ca3b7d4bcbc5d983a9210c8e25a5e9ba55ccb51399dc4f87bf766e87a803db 8e1df71b815b60d01596821f77f20e8ba714e13680e4bb57c3650110994106f5 56b73066872d8a4b86f780e8d9833dfa56419e278da45ba5e2db20bffeb66577 2a47099d3dcf25018cfce34ceafe9d87438ee4186c41490fd403e6e42b5c2d3f c7a3399f0fa1dbbd9976ecc6b4f939c860b4af7115a14bbda763632b1427ffd4 9e95ec90e3f86a6ba34930bbba2f93439766b2c1aa20d6b372f53aa785ac6503 77790eee24121080bd6cd771633b58fea9554710b771021f74d7438a99bd783a 53a887bb398735352c8b991478de995167951f2a985275f2c38102937bfbae4c 1bca9a852dc22ba46db7b0bb5793346a905a6e45bf2a7373dbf8960b5b42594e f03ce64633d857f3d0f4b267c6ed14e3a82664338b26159ff25dee6ca784ebc6 7d8524ed9d52118efce4fadef93e0a0bc66011bbc9877e66c9649ecb16aedcb3 cf65cab677b16ce2e76b2e675de6f2b324c6cc4ea82fd3d9ef646876ffc59185 d84478e2ff8128c73b3afcef77cc2f1d9f08a49ff3f0587a3a6d473f55e0eb53 f59c7d8fa9eb320ed90a86c92a02ebdc016390dca8c9722170dd5198cd1e9579 f0b0ede5391b6c9c584a61db76a0cec84cb1640472365fd278f6cd5da4946921 07cd121ae416d38443e3f9ec281774098c4779d712b0b7a85d31721c41a7044b 6f33a40ba6f6c8fe17c1f387b2a15a440afc0b262628c8c189ec936c7ccce868 93d3c1f4187815f7afb9bfb316594bbb7bd194dabec5fb906b83fc2153b4e02a c0514cde62fbd830f585c13491d6567b0e287b3b4a7ee7b7816b1e91a34637de 175954ea8c7a717813d62813e3af15ccd10935e95aebcc4ac60473f3d24de202 7f3f6c6efbc30d15995a2e1ad3d5baf1685f65463d19b98d14d7c22edcd33cee 8da94cd37f45d0993b6f37761dfdbe699fb00446e37766f1a8d2fbed8919aa26 ca869ef84d9196b289c84b0a0f90281d787a4505157eaa91f4f1f6b9e7443a5e 2eda08be6e1d26b9d6bad8360c5f30c2f47af50e07b647d69e0cb6991fa37898 d3ddc6aaa0883e6c155f2118c5e2501ef8d182593518889792e50b1403a04246 944b3af2047b28c5bf51427b1c29242cf2a2a3f6882c6fc7060086bb72ce26e3 44579a1b2fb42179b9e10e232c9d11e1cba5e6268e3e27e22fb292c75b550732 6713824a19a140834e3181023eeea4d9090d4c0ef7938ca5ac760798807149e3 d99e86bba4142a398a2dc7852aeaea64d710e086b241fba4fb70ffbbfe4ebab0 241c2ea4ecd5936b02fadb15c2d763aabad2e7531892a1448c5cb1b2e540a928 6cf74d18fb775f01ceb9222574d0d704f7efe797b096dae146c2d7f860d6ae60 2df994259a9e9279a8c08f7f37d1333cfeff7d4c9b00e273ba0bffe67ee91d58 e1f86f218491f4e1297187b600e17dcae2d71362b0aa051bd241981b4b694902 a85a6b762a221ae263dc0f8568b23388879e94454b9b588752e1a16105e4efeb 213b0ee105d7df0ca3e893dde9f50a57d0ff2e91031cacf2cdfc6547c07d189e 9c5879307b9d6957f504d1b2cf3160fc787f747122abdc423526640327ac59a1 ec4fd6c81d070ee743061c36568f2e02cd1e1b75caef5aff94a6143005a49994 2002f3a945a9d21bb9949e8747df9e40c1bca2d793eaf979ddae2c712ee6f85c 3f0eb01b2613ed363e129a4dc8d820fe325c25911d8a480a62159c7c53ec845a a8164cd59ffdbe57cb56c7c049b1e95f3693b0536831c840febbce5a723fc5da 154861f7eb6cc3253cffbfc3bf8e5dbd79171aff9244a205454df5a827bed731 224f573206dbc13fa4621c6b73b036a241ea25619c14628b0d9767743b7c967f 6cdf85e92acd2dfd4399aa1bd45d803ea3d0794c76945e2d80274f53cdca5f88 0d3b885c422d389a29a0928d6b09883f4a309bde6573b495c6f6a268eec2d519 428e5249c0abb96946314d6ae67a91339e8920d2d6df6bd2ab01618a81d353fa d699f8d209ef4bbfbde089705716e162ef404983be581dfe016e0c49a9302029 9eda3826a1477e2c37e40e687959331664ededc5fc4937d03e81da5c0b34ed68 f8fe870c71cb553166802db6027fca173c85ebf0f9537430371b2ed7c3a3764a 622bbdaf0a8dbc4430d89147f9092de7a2637d0c5ca77d1a2269081d85c3dba0 5c372dc15cf0c42e3f359fd4c1a5c2e1a019414a400e0ebd18394b96a40c98dd 91bd292ce4c3c68a5f2579f90b4a8b09b8030e31f7e773ee844c720b079d1e2d b2c171f58346747d6ed7b02fc65873f33b7e08ac8183144fa59ef23f2bfc959e 5cf6a61116fe8d0b9f4804e6fbc07af6ae15207b392c8783e404d5fd293c543e c6646612e88da493c7944943e2e7bc2ec432410e0f43bf7dbe63545a306975b5 ac6f8b9b72dad35d5cc636b93a3b4c3dc77b0e2ddbfe90978be8a66e98e3957d 83171e32bb5e628424811c615deecd0f89377cb0279186374c36d874b5ce2a2d 474871f34e82e8aae1f236fd7ece6b9bb8d9627d12878e64fba94ee0ff917e90 697ac8f1dcbf582bef5162d945b2dc2d1a1969bf59161c5aa4e6ecdddbcc6b75 d0ac304d9ab860d7ad0ca2ba9b3a2c2b47d937051992b547426502dd8cb74fb7 775252729d52b7fbcb724b63ef65d2c14607fcd3f57cd9277a10c95aefcf682b 8e3523b50d6ced51c5a82b2aa13f2d498b504ecbaf220d23665f5c55645faaa9 40460ae2f74bde032b31812d53a373111a7f3551e0360aee6a0a5468324b29bb 2a971e6b6aea6dd849df590900fc1f2f527ef624b7f578ce23a43b7da1766ad8 64228053b65371ae1d0a5b3823c3bdde6ba4e9ab15cf84525efc24ab7810d7f7 673629e04c5f248c138f987e346d6f62aa8b70142768ed8faf516280f1ea6b56 aceea696d75ecf12f55924214699453432418a6ed52b2954dfdf1d6eb66028d4 124b855dc5d1164885ea22ebea5849b513932aa42feea0df88bc146b26062102 2043c7629e30d8554739ea06709d746206c08cd7998b6fe7278022855ec96f8a 114a9e312df49f4650807d8d568da9c868508d970437d843c14f23a5b5c745e0 c6150dab7d30c4a57bbf9f74bddc9775d86d26bb9c51496b5fb0887faf32ad8a 24335733fea5102fb726536a5f8ba5cdf20ff37b4f7640b116dc72952bd617c1 bbe2bb771c7bd5fd1c79eb68e58bf4d49e0c45c00e274bd5876df1049242a729 a3ecdcdf9b4af0bef4676d65a25188742351af5648c9233a76e1c75a24eb7a8d fa75c3f4785cb295c8e4b7cf4f95e9cdd80cbc14a9dd67a1ca7d544afd7ffc17 b02c22ee4e0d7d797a6d7212759fc99de5594b4075454495f786aca12e919678 c81e4d5e4af72bb134385df0131616470a16e312f2e660610045f5d3031884ca de87536fde596ff29d65922de1d67d596238e5a03ac0d4e5251dafda619a838c ad6c7c271779001b676bc498d945e90fbf6ba0db589c5b2d5a2e4a74bd6e8d01 4aec1dbdb3e2c9c272606ee77ecb170e6e64b0c857ef9790d612aec230a8475b 82ff743e813f4ef077ebfd66ec61c32a27afb8978bcdbfa69c8b8988998acec3 5a0af108c17d6deead0149accb66158f8246d4939930b8683bab88c17d30d30b 0f46615ccbf367984b3a89a7648d557ac69848376fc56e77ee796dd124ee47a2 5bf94829a2e3afb01140433a9d57e8a59899db28f19e64aa46ff28f5ef64cec1 3e01bf0f93e546cad6eb526f1249c1899a784808ae940f4d15e0a896191d4e42 86e649034e59402ab71e9e7e577d427d917a4257d65a283f1d7ac023ae559fef 29a914d0f4951aa24e2f0aa63b1f537c2081b11da7799a70258d7651a35c5747 3f0107399325655f8b6b33023796e8e55d75525a31a9e5c256f24cb23fdcadb1 6b052938fcf90cea2e5caea0d9cd4e183990f1efba477314b8ed59faa89bd34a 1c6a32ac2c6d3cc6541da9afedd51357bd81172dea1eb2d03a1264a988f761dc 889927d51a0256466f031595d94b95fdf732708efd504b9d22c6ff54aa3d4c59 c612ac8c54634bb1d7cc614a177c03d4b0bcd024ba4a74a43827af518ee607fb 6bd3a9348b3e2cf91c5e9431dce292fc2c2322d07ca626767479639c654365cd 9deebf112490cc58fe510d7aa8c804657bec78642f236df79317165cf2f206f0 dced935b8c9df181c26a925613e96193d52dd051f2001e74f9b7e6348d9148f0 3f6277b2f63bfbe985ece514161452767ade8331f20c40f3f0d0a1035419d533 4d95e5dcefe000349998e1a3130b7a7357453129503423a0f02683aa941cc0c0 84bf7e3dfac85642c1004cbf84ca5f9efead8b8fb4ca98b779e9e5f5445fbcd3 c3aad5fc72c27162dd18f9fa38b371cfd98b70b885ce7e0c428527ca7d8b7569 c716e52b55b748463b4aa1af2f5e178536b0ffb6bb62807d0a51960ad5cff40d f1bcbedc26b50cc7de6f7ef24a1f98d58564336922df6e6f4a70337e6670c6bd 65323b25016172bd154dd7336dd6beba5ef6f45a8713797a6ee39d0979c746f3 4204c9aae42fb89fedb2270e6e29eea1df504c91a9a50f33bb3cabb506412d56 6113d4806a2e2f16880724d125ec7fffe7c1292ff38cb6c6eb8a8f5af171d781 0f022e7bae4d0615d72527758f20be97b6ad2a574830b1d6f6c754ec4b478a1b 25178ef51a568a7d23ce35b29ab02a618185fc258aabf3ddd01fde845938aa64 f06519e655fa5a6ed6cc80efaad8db30ea29324c7dc983cbfe0f3e931bd5b558 46b4b06ccdb3670d7027499daddb0bf9a1269378856cec1700cee91ecda64497 2399b6d1babe50a8c854a3bec66c0e7cdcc7959b03d8ab9f7963063e3ee7cd25 a7a4f6c54713d2f6305c2800a582092aaca32c34b20aa07d0a968cc1ba45481d ed82f9e92b53a19571b5366ae203f7dcf90f19fa2edc87335726fc22dc09d81e d9787436fda6cd8e5791574b3aaa0283ca7c4a5ede9b2433376ff45160b58a0b 82 c3046b44e97c901b3466cdc59c3166a15f398c66264ca3faa98a5ad51fabb100e57620f66965bbacb87c972f387b8b0b39c3baca36184e7852e871c65f5c6509bc7944b68fbb6cad83db7cc1ba72d5b2ee986db7623e03e85869b1dfb259ee0482a8d8a015c2515fe9679b40fb802a373a5fe4211f73dd62a4711101493fc904ed91e4003c52a474f8ae17d46852cb5031d8893342d0c1b1cae31fb6e81d490bfc53b218aa0f57b2295e497298e2a148bcf219a114193a0267904fe39d8b410529ed7398186ae46ffb616e886706107c48de85cb0d0064b5eac81270a07aa403ce8028665fc1207d43f80af777c2cfcb74793a81a3a3225ecbfcb42a44490602fcd34898f7dcb96f0ad809ef44bd860411ea1840454957ea3e00dd8647894f016b6fee01616103e7e5beb0e1054cc759b16cea10a27e1d6a6b652de032425e07f1eb718ffd53c0cc1cfcce1131a0f72f9b0f51fc8ea5c0aa40ccc8780fed3b0262dd65e03960648f0a0f94f7ce368f1fe1a43a696382e75b8d30b864e5c88f047430a1323b2f333c864aa37ae4957237bbcb6350def725e7b377ea5d2e10d6028fe66d7c08edd6ccc2d37ac70da1cbfc66eb916d434ebbf7bd064d864c8193002f1c8b911915c3969ff4c0456063c55ad6b47583ed9a7f3240f6effe383eb6071c139d9b84c3ea59a5748b4de21aad17e739a02c2f502fd2c6d1256d6fa9b302f05475b46f3f57a36150e7992ee3b77ff09643c203fcf5352628ee107f7cf008628a1cae518684eeb4921eac8aa687fe28d408fcd9639cbae20b3cb97b52230b6ab7b5648e58ebf225c28db3859a2eb5212067d83a9e6f9fcb47ea9974c0d20afcf09f3da6dde29e54a33d2377e661215402ef3239924edabf2b6fe3379b36095a20a4ea32e2484445cc3fc9c0cca14adbd810809c0a8ce8314f6d34e287d50feee6f2015e42f3d2b016079fd462715aea6cbf1e668a66858e2526edc5ef6906104ec309e2e0cb2bb445df9e36241d5933ac651c7e752641e1cd212902538502e06ce87f119514b1f2da2cf79bef1c2fe78a34497aa7332e11f13f06d8020c0a802677625b98d235204f156d26bb96da067530cded07865da982f2da44391d0434d47afff7e6ffb6b0b514769508798e7fec4140faa426d2ddfe5ea8e8c1f3061d84cc1bbe6537fee8a6698780139727476cde09a4d9f760dabca66a84acd2088f962bdd0b3d60114dafcfdd211682fc5adb32b2d103aba139abbfef76162a001159fef3826648dc2f71ad50084c13667d9fe58df188471753273b188238120aed066487e983acf19e1f2989a21d80fcbf0f3a635750e013b5b5d102649125067d1fc40420bfcc4cfed689a98ac15faf97da41457320df6d0243a9cc7da4fe0411bd9eb65c600d80754e24dae239df11d1e1df8db4ae58a317538c39879bba0abcfc859636eb0752e46b463944be1610fc0b7b4d660b378fe963d1053592ab0d56d1b0726123f126fcdfa71bb8580c53b97e1dd1318690a3db66b335e7cece0031f06f64ba57c176c3623a3a126426bf3597cb8f153058a6a7d0e463e5c06b0e8d8a5d750dd8546136753e60d982ec1b8d85fad1dad1a90824776a525a09e10de8c3bc2ac53ba8e3c4955031d757e1a45d0ad85ef522d2d55ac77ce8183c950600bb6dae62a86841b01edb43ad2316c95a6146e710435ea0d9fc97eb44fd590f19d92b06e39f5cb524853fe5968a908704df1c1feabdad9be6a3124beddffd025f7ddf27722c14632e84c37828756d7e8070ba6cabdac7fdbc72b75a0af3cf0bc11b1dddda783e360edf4446387f8e2956d96f34e021cacc21dc19a366ac550f87503dabdb62323980bfa31d7d50aee4531a8a803c1fb226c7b5475ffb9f4e0dad6dc42021a1a38f200c46d5ab2d72f9746335816b53cd1107b780c11c41420acd57a582c94fdb4427f08610f2611dca98d640f3edb5df29ddda610c0527800ecacec251609f968891e8518fda3baa395a0f0c07ba31a44127e990f4c5809409010c7a0b30df7952e63195c2ac3f223202100af6e9178b25c1604b69e6707404aeb82a2080a7ec26ed640c7e60e7d016e02aff112ad0cc40000f4c8395143b0e863586522b75d2d17b1ffbd0b5187615acf1081bace08deecdb8f876eee2db0d7d88764f7121f85ebf449da2203f3d81ca0c421bf27d4aa0c513f487c363310df6f9f72946b98f03c293889f05807dfc9c9ef8b1ed63a4552b0a1aff4c9b46087a1c0200eeb7f8efa1dcea86270d2e4af7b9a0846d4c130b88efc55ab00e0d0a49dc57723b95676210a7917817b8d455310eb36fda6faa5feef4eacf73b162067fc9a42947cf34f8310ccdd4bf5a2ade82ede0856c1e17298cf894ba88edad0eaa28aa6949de6c74f0392f1c4d6a57faec8dcadf32e26f5ff72603b6cc943a0994262d59a82cf194fb93d3a0cce6a8f4b0cd984ed3c4d7d5ec4d295097baa10e5a3abba0a426d1c6fc251b31f87ba14fab8acc23ebc0bd31a0711a5b5ac9ca07cfe0b01819ebb04a3ed1221f8f7ccf1fd1b7323334e69319e740338cbda9db0c7116540bb42fe3acb1395da3701d97ba64701f7f5b01e9266ace35c9ea95470218367055639e99b33f2f552ac1754e38d407906980b94034ae796d95dd6c030f0cea9ada0c6bf305638ca222cab96add245eabe309c845c595f8f025d23e600023792304fe86010e89ca50b7472517a3ea33376a7a7fd3c0cec8cc7035d8090a0e71635c33f5b14aba950107551087f95e921b46da4195cc48da0ae3c0e5ce0311a0b9d7e12a54d12cc703bdd700532c3248f2724ca23c01041e2c63b9523e028b1cbd189664330c746b46ba81c7a469beb6a9372a3484b3b1a2c5c86bb50207bd12f7d66b346ded14e6db68deb4529d573f00e29d9c737343f48f9100a32802f83546bb43f2888dfc1ddb0694cff1b8e24a7e4f5fc36460564f96a7dfa2d9058d6a085ca04696a9d5e278c10c94e2df302995c785aec22061fdb66d87d14f02c9852578e3c75b2ec58e7909c25722b629bbe39c11189fc4dd7d0fcb9e737309985cbc207c57bb198e5a09e2b2e7a31a7346907b9d9835740c34b284e315d908b475c3c4eca4508e8a169a6f057fc28d6a5922990697963b3f896e571d2f310a58c386682ba374d597bbb80335d0c5fccf1c77ffa15f4b72c1684fe8f1cfaa02ebdef82fab044a6f8ca690f207f455ffab777cddc22e4a8ab29eb2af9ecf600579161f91e2e0cd5b769937066fbd66c762e45ec01985e0eb00267b82db081203166d6a41b9e1c03bdcca8d077a21384eda20ad684b4a5f553b644a6b8707b40fa97b4bd4bf48eb4a7707911b41420dd8741563c705723c972f50dd6561920f038beca2d633c31c7788717f2972ab347e7ac2d7d8d7eaac5d206ac3069eb8f508def2568a9487775d61f3f3a085967cc4c086f36def4b4ae9fc486dcb9d145a088b135d8c59f6e5c07db2d994d69c8e033ce1bc46f14093fafa6dcfe7e31bee0d7bbd68a2f560105f5299c355b9f57ea6fe3b41f086bfbecf7072b90ad9a53e01b8bb2e6d51fb575cf0091a5953c74d6b1544b712bd3b5d6b6f629b993f71be0461cb0450b27e8025e736554c94822a0e246a7441700cdded75307e81508c7400fa13655c949ba22bcf757f5f6760dcab8a3afe55b4d36cdef505486f6ce38604f24944e063602d02adc4db3474edeaa7f108871275ee3b3142aed3896b61620aa16b9c3b9141da7a6e2f01244968a99c97f84c60a36c2ea1885d01ccaecbdf0b6835aabb7c099d2d0cb83e3212b39484a440b0b8a8b0b0e6b81fadbc2c155106807662b09e1d9271dfd335133ebf1a2ab1bbe74a6dc9e42214c45e0983251804f1a85b79b4a9427e8220f43f7f531548f0cbeb074a0a469856ee9ea3f10def03429bfa6ea5a638505796a86c37d292cf2229f7199583cba4a37cd30037499d05526344a79ed005dc1d1928e86a021f6913df7448aad9bb681f47c07f11ba1b0ca492e5a9452532f45ed466a52f2486f5f63d879f82c4880d5d40e03ec2f2440551839f4acb75bf239388e2925176230efb301e53efb13e500fe7acd4d2bdb2031faf0974eadd9ddb36f8f5132ffc9b43f90c3b3ffa5fcbc4d32ba32e1e31bc02948f3ab608d7dca6158e555a92ba95b1708358c0486b3b9bf68c166dcb65380678655371b5c2eda2c7b479ed9470a76c8e9b3c2bbf5c22f34270371d48e40e0ba19fc418674a4a9a5a5118956ef0fe35d98760b1861737ecc43f941205077205205cc6cf354daf3eae1173ec197296ed018227013ffdaf9db645a42da368470d6c53e736441fac1a7dda029e94f68d853eed9dc7c0548fb81024d45fb4657a055dbea743485ef4749780b01ea59987e335aa363491a0740d75705c8317c84504dfb6368cc8901e5ec7f69908a910fd5ee6636f96d2f25739f0c5b226cca5b407631290a67e79313176b469df0f41cfaecfd6032740a283da7d0d9d4db20f090ea2d7417fac4065f797372d99b4dc046e53de7d1f18e51638ceb0a98ed0a81b07181ca8124edd86bdf213640b57a907fa3d2d0432ba8f8494ca363227c1fc98068f8b96b7e46bd7548b68295a2a15c3b3b046371e3b5e14504b5d90616fb695015d41d821f1be56b5ab42e9d54cf085c24a2ba33154ebdb8d2517722538616d0daa4fed30e8303c3e404fcc995bd7446464f180ea7ec9f975ce74e3968641e506c9474f56c0d5dacaaf52e9a29a88e5105992605b4abe44c428dacd75cc77360dc39705c50def1f5f3161a62c0c80e75dc3c0cd0b6b7e0df64e7305b844bbea0f275b74b9946b4acb5992b035d38b58d7a9f4e16941e6be1b8c2e29dc801eab029e0141b5abc0484e7fe0199bb727bb34aed76ff51eb7f794c550d3f89d55e70cb54cbe4b9b39c1b4853beb22fad7b8c13b5eacee435b8c0af7b2aa10d21fca09d8e2133173eb652e2ea2ee7c386398024c76b33d68c79946e774afaec4b45a0fd7af0526fce288de2b375946e65e7e7c29dedf403c27adddfddd2fc84747e90a96fefa397169bac7d0717ce49a450ba86232faae76e7c1121f36de845ad76a0eda51ab547f17c264c2a0748bef659d71d4dde4fe090947e54f864b97108bf10a6176571105cbccd03fe904acd9abfddd737b4ed4c778a8e02af6cc415c49690f505c73ef3ea3e3e31bf4444600667772af7f23731890774aadfe4c39a36a6507a082a646239be51d8a0490d53b631823f488b4c74ed26295d66e4622d43a9e015f6a671bdd28c768bef1ca14b24e02c35f9a8e4237a677c1857444f6ef0a8c0bde6cf83fb5ccbf0d264d939ec88d434f60d78c682bdb1fe66ab02f0ee0e50f06c3a6cb85bd9858677900bda38fd541866f727bf04e04f14e22168b8b9500e8078d5b540dbb2e91bf1ed34d917954a74fbec2fbd78491673a4ec31bef383b82031ff314f852761de725d892380de08b842a49309edb4864edc26d8a6417603006373f3fd3682d9be4f8d69d310f1176d692b704640407cb43aecde4251c432d045e66da5bd8db763132c2943c8d419ec82a913778dbee2ec9b3e8ae52161bc20a27bbf6c8aff0a82475ed5071f8b5c7e3ccc549fee25825abc749bfd771d9ef0a2f35b5647b25b83371555ac8221d814573386b5a6b73019cf6a8c21176afe40f5ee24d2e7efee5906e966b8757dcf98bbf5e2936450a207c289ef47226d933017e15384c7d3d8f1d400787ce8f4c3da1471f05f18a2089d0757d856ab1e15d0f41453f431cfdff7b6783fae40673acbb8930002aa115d1b173557c8c4087b40a01c63a382123fc6f26b28ad75e53dde45f27e1425728108859a297815a4baf01b220b05e789fc09b9792090fe91986576cf0280a916c72bb8583ccf2faee5903972aef86002ecd629eff90548ac10c1a1284b7abcc438bbca0cd0f096857bb0f1067a764476c4f7c97011a8f1aa4eddcce8a396c0beadcde37fc15da2f108502206a9605ad7a54249fd1765b446442578f2ffaf7b4001c2071b03fe5be49e40583a9eab074267283475d9f4f494138e6b159a241bbdd4b7bf3f16bad4075800d13fd7ce92c25542ce9dfdca846946921590975e57da0e5d48cb49966d57b550543f1b3a0285d9c7230e62097d418fa79a4b7245378fdee40c3454d6eb213f00e5ab1169927e696da6f9b0d459026143a8a0713a31b55049e571e19c5ad427a0d660f450aa89032d433e3516a968a8d990a38b5db01af52898144edad8f39c304b4af83df4e2dfba14febc75d829f13349984d71bfa7bca7f0ceefb6315e7900c645268f5439c0800530d10f8ad07011e50aaa32f17a7f4b40881da9f31337f03562bb186bec0f06d1f94a90948806f3b0251a407b5aa2faa4704eeb0478342099254937360a83a3201fa4a2c6d8fb1f1601563c783d52966d4a988da36e73d0daffa9d7306adc6cde0aa51352a3bbbc594f61b5fa750441b293810d87bc52503337159fade850c8e86e1438f5ca51378e785faa1de0960f67940adb9fba8fe0cf563b3686163f759b8e95e5d09f93e6b62071360f77d6bad08a9f2db8d5a1d01fd406c2a9918e3319a9a2074950f7d40a5560f57e30dc1a8165ca70ff01ca404681e67524cc8827acf723df2b1c05445e0ae822b879f4f1689ed1dcf8748e909e37ae8013ea05607658d73506192601c905d88051a82f5a7c93cf2405013cb02913a16c9433500c21d87e4c619c4cd0779a133f86d9b6979ce41d2e74cebc7076261b041335337a3d1e5172819fc2ad48d54f82115737cc798789d5e510fae018cbc96708f3cdfdd5df3bf18409a075632f05929d6108760fa5a81bd46c78a015d94dbf62dcc944890d573e4b8e551ed61dcff4f6a2474b71cc6b10d0f96fa0750462bcf57bfefab0dfadb15b5a2bb860dd3a00a3681c35a646b1f81001f820bc6bac2edf351d525ff409d03cec61db64d81e670740a2974195e156208b27d0e4de7540b8793618e2b94c8708bdcd5c274aeaf2c3ec1a37d00ce263fc6f91e0b272e75af30574ec0f7c1e23cbf98986c04b0813545ff7cf461972607d485f70ce7b7aadd0a64f7e6bf60f28cd1b3a1ba96c6dc55b16dfb1cdab3b13533bf250e5997a861c32a4f46fe3c463dabe4b4c574cbb618ae9f1e8ff78baebb6f4e570762f69be45b9c31eb090f0800f1a3b345ff03aa936973dc055f2fadc0e5dd25004274fcb701327c5c13d16fa15919f7939ee45f5d415e5f3b671cf9e7e7c8d90f1e0f703414c22cf144bc9b673a400f5af0a294a1b2081a28b5b4fc6cea86d10bfd485356bca17c9357ce3d7872736e8fc56df7bcbde4624bee3005e30be81808e07a6d18996f09c9a1166b271e94637dd3f916fd22bd79e2aadcb120d8be4700a104f5c4df66d65ba7d88d5d9e385314ad5c260d5ad947c1e6142e202a7b9700b448c29eaa259a0ae9cef0d8a4ba51374a6be1c01a4b45f1e91e2a566567dd0a366853b358e57e6588c34492ca19d6dccd778c0035a992556397b281c44f48002fcfa2da45f58443108fcd1affb1bc5fbb305269c783096bc115de2f375f4408c1a9537fb2edb86265cf2da37cb7e53c4b1106733fd54a2c3bd9d1b1d1ebc206b2253289fd600e70c81e99f8df555a29775c670c23d805c892fc6c8463f1230ad5d14de955990559bff18c4a0434b031c655e38d8026ffb6dc0db2cc0c870e06fc10eaf9d43615a753860fc453022a8a8d784cee0eb52a2a71180efabef2380c3a6950c0522fad2da8fad28029c0a38a8108934929b70b870575228bb185f30cad8e6b4d67e59b48305d6a8764cc98a097f51bcbf8c7a6c80a207cc80058fd0cbe6b20b4cef59d8f5d54131fc238bf1d97a64412d817f86a21b22abbc17e890ec147beff79438a5f73c5446d110bc26275d769d06f464633262cbb12ee62cf01bd2fd4c9ded992f30438cd41d9468d59c7121f7a5c581c41e1bcbfcfda9e1602f42554a5ada6275e69b8215b4bec1e55ab7aed6e2ff89d5ae7aafa0e6ea91404b3c7ed0066d088a8c0efd269de18ee8e48bb4d776f8f6932db0f939dcfb9fe0780c61e39d1c867a22c97df2d5eb4abf8129d5979c1347f33cc30921bad8e7f0f62d44641550da0e36c65158498b6cec865ccba214315c76c301e1a3135f33b0c062e1b38864fc2fb578c58a69a34271dccfb3f9f2c6c9d090c5290b87a7ecb073d2596b07b3bbddd67fffe2f287bb529ddfec683c42aa914adda638116bd5e0cfabd6459fb4bd7cc5c6e7c1764d838a1012b187e9cf8548886b1c7d593444801314db5d4550521b39bed0fc19eb1141f10ef694d164a2f21b5110b6294a3ad060cf5ffd035e81000f4a52574a7fc0265ab1f95bb73d996c0e6857ca53b073e0e405207a4dc5dfe5338c8ac19bfbd18b9cc8777cba715daa8639941d559dbb20727611e9b270b1d13e221b24984f36b8b4773ace4628a84a0a077884214d4c806c0b1e29e56afae63743f7747f1e6301d6292df851ec0d0ef40ef438c0b4214083fb941088bff92d1ff2c18347101b7101ca97d0fa91aae26e257a22daf40ed0f20e6fdf1c223b932850898d3e55f8378b97f040b833e51a8be4ee6be54a7400331f0a931793912ec77b55b7bb18c0354fc77bde55465933ae036ef6b83cd1208f99fab41724bb5dab9c53224c939a1d87896dd01d1c7ce92becec09f8df11a0bbfc92ef6658335cddc8f60d2bdf559d11847f86603ef1ebfa9db447d7e63000214d828a0014dfbaa1a89359a43d0f7c262d8fc6f263141779f9d72dda7793d0a795c26f876562d6f666320956119feee80af68e85278dd25ffe320f6894a800fa1449fbdde07184be07ec769163ec11a52162bd69b3675c32c3dba94b1c8a009f2327b4afedc18a722673117402ba9876c6ccc81e16b62ef06d91664b36d4601746f18ebf4f4b6a380c1c0717abb6d89c0a13ac5e2dd9c44319bc7dcb8698a008d86f97a4b4f28ebc8ad83d0f8d0a396d5e1811f5df2c43e041b782b73595d04c76fdb737ae9b247041f51b8d37f4f06211bebf470d93d8aa560c7a989f65d000c43dbe85fa194a36dc00246a3f4968501ba5745309870388b603aa865615102c8d5abc6c8da5fe814451d0b4cfc2e9bad59b198ccd7bd4ed80c2b36c509440dd8d9e593f86673302b2cc54111814dee6c3796693627ca43093631b138844203ceba574dffd835da3a5be309168750b242ffd44266a2b4667b9967dce3581a019a7ba4184e89a37386b715ba9c801368d243daa408e8fced9114dbc31ea4c40926fb1a2985277dcda4169bb0ce5bd9cef3c4301fd3de21c0d37638912d194e02b1402be4317accb61c411ccc0446964e0e3a9795605bfb129a34562dc4969a0425868ba0728c582192f02bfb3dd37196f256c6b32c96cd0a1509ed6dd965eb0b90dc350a736806acfade7c23055afb38e50b76afc0cdb1f324e79f852db4e00e0a89f1a0318739d50b8a1cd6ade01e3d6b4b63bcc244819ab9729ad0cdad4e04a865f04a59c69f7d82275ea317bbe574e5a42aa31a733e67d235be708eaacd0269fb932855f30524f44f034ddd95df4c19ead1fe50beb5a709d822a259b1590cc32216512d49d4edd7c0ed12a2506e79185bbd9e0dc0b2564379452f723ea503b4d30e235f124d92a6b49d5a56fd018e90e8dd3d169f3867da7e2e365b93840c76bd3914b3318fe15769e7484a0712168583492ef40e5cdba5bbb8069620760edfbe37a8f42100eeb4e930569f3471b3492d29a1faaa696545c50c5a1bd62502e4b7c2c9c25efc4f10449a791d6bc71073986b8443c526c4f0551247bf5cbe090bc72feec42635343a63139963dfcce212f0d0563d2a3d4488515708721f02080be78c58ee2e40a014885eede95ad1cb825de8683392a9c7d0e0656028def30f6c89ce1c27c0342739c2a8dd9392f0a4306dd77547564c44f68987a0e6ac20008d23a013da1d12ee937bbdcee0b4ec4cf0bfaa13a4657fc5f3f694cda123a60dbb44b5b432fe2fec21aedc83fdd66e2a74023da8430ed92c347f247830cf3603631ea97446237ebcd26d508b62cf6d9e276b1e92360ba014e5467052b15030065df45fc5cd67a5baa144aa60e68d36855ee4998889604998336cfe85bede160a19fa485ebedbf33ab73fe3a373235e40baf7bcd1ba480b9aaf3f33904abdec003e1f1a9a13befeefc8d4c3c0c72e7c246f6597e2b22be2e5313e1d4265d99e0c7babb43c8fd6ad5edb2e959598d934dc1b0516d02b3e5aafa75817456bb67c01c4dd6d38a37bb46c327c8514e14b0feb3c65c50f9c43f9562804f10e5f5ad70eaee1c9d3dc8562b2e09b6919c8251cbee6af2f122147a763f7e0e0fc7077b50d45a93e491c37b8cca7f49f1dfad2cc52add97631691eb1c80650219de43ad80569636adc4760b89545e0a0a5f4fc75adb5b251b3a1b97501a6c4fe55e82e0307785d62b193e4ce8410c5b39d4861058a221b77f64a8477062c4a8a49bff7b50088039bcdb453ac577ab0952b07bf05572dbfeb1920110d172e11e266659f7305276e467f940101ad5c6ef06cffd3d9e8599aee30be02845eb1731ca2fc916c03f15c04a6ae5488540964d71123d6fb1b10405dabff16081e94394b1fdaba860e9bab2fd1f4b34aad547175b68d461c209019dd2c6ebd29d565ee0a1d1f312202cc961eaed416a4495985140d947180deb28e739c7a86e3ce80c6010add9ce20610865f9518f63f66456c587d138293d60e382c2532198b1e1b8e8c16dd9ab2077f76649dc6127bacdc33e1265759d48f93c39bbf798f1bf116cb5e82022c880e1d0f8968981cce1db021e00b78a4516eb360631466892d80c13141805f806b063a1f141ba661e8cd96a66a783d9d2bb762eb626eff7cb2ac20bb826b2aa1300f6203c331934eb93f64675f7d80fa540982a6db494cf240b40df950ea1d06ee0beb03d1b7304113671eca73e5ff0c128bfd75a10d840701dbd631feb64bcc7e0189c74eefc3d069b55d656ad81af5fdf846bf9c169ef81d790b98d9e886f2020386e2227bb587ce4f28f54b94c492d88f047a498d51e941b5e6223a047b1d9601c76eb05a8b14faf52011bf63e59dd950eee58e6ab9d14af92f23a13cfa06e40dc4338f6183f5e0281c341d051ba3e77e2c336e35db65efefd5bc829352de5008766801bb0cc50f410d1d3542ab471a40fdc78e1665cc04b70e0819dfd6817e0607a026e7bf6f215aa37e7a242d74a13ef46233212a85bb95a13296585c154201230de56079cb85b9d3915166929548feade266b69df96c9d1734f6a115396c0319cef2f5c36a6bfa34b2c0d4762dcecd618a27344eb8efb9e4960a92eb724d0339e06ec463ace0ed8d9f83c5fa5048321908ad619098a8b4fed5c823c7523d0b7df8411ae9b141dabed269568f289cd26c9181c6141916eaebab2af15fbb190869d2e1a68697d0d82d5f5bf72a7993995ec925da9181dcc7e70f4fc55f16fe013e07c6a74c39b454cac5dba654df4adb31849a7b981585183230329a97ceb30baaed133843bb26454b15b5930883a5d46b0955ed313b090e6de8ba2790b76e003d2404bf066ab82bb7581d869ca53168a46aef1709ff96b682d0128187bf400ac2afefd4938645991c2222e453159bcf7f9df786d4da14b6699efdcb97df0701e16442d73100467afcc6cf64832a8651bc527c0f08c4476920977db779b5c60c8bec26cc1adec998a601a4e003beba0f3762bee2b70437130340d56cd7bd7c0948b394ca7f7aac147b77831819cde8c6db61efdf4df5cac7d6481656db3e2604afe2a85243666e26a6b52127ebaa9c4c8ce62e732ec86a9cebaa27d2ba1e5105bb511c1b56cc7aa42ad24e2c631dbbf8f2d3bf42422411494539ea9abb16aa0f899001604bda965bf3629be7eb7998e36cc9c7570a016290e29afb3d8c4d5503e90e0232dac5803237ce1a738bd18a14ce1686307f29576ebc0acb2d5e9e2701c24aabe397db8d3401bf0e91ec8b55e55e115f3a993697f170a54f9a5cbd6a0abd3696d56f9eed21eb86bf6419d59ff35652552d4f90a0dca304b760fc5fd101235231cce4802982dc649f38b51a4ac5dcff07d99ec7610981a519e69826240d72aece8bb8879b86974c9d17d8d468bc7f40962b385a02c578297c56d0fd1a0646cbe64f6bf8ca304603ca241b938b06d6412e3f2aec081b999e9a13221bfb007a0ae3a4a1b4fe26ced70ae972ae08e8684a6c02881420cf1886081a22d92808f7eb73be68ca0d1c5eef5edee6d264d335bad8d38675e6a071b5775f3f32700038b35e7b505937fa31a0e479a6e9fd0324dec74af6d13bdfe4f8e05565882609b7fafea7c3c45d7073e1bbdab18214627aa98292d93aa7b82adbb1cca6c0700c96f218588018051ed0afddb6f3b39a96336ff6d9e2da7044b46df13e7d815f0e36ae5c857bd873e6193b12eacb2eaa7381d7082429b932e7cb58a0a4325c0809037df603be32385b2ebab08ce07fd4c51c66c88aa1b497d4b3bd2ae8a2270f01459a8811576fce6a8f477e9ce16222038cfde19dce9d64dbf019618efdca100857680d301b7f67079f39536e7857d750d2f5c6782246eee663f8a544d342620ddc1f1a88c9da38a67eb939cca8cc9bfbbec1f653d0964ebfa8b6373d6f988c016f2b673cbe3900f0094d3c160995450d54eebe0ba9850d48be2cae3d4984db03b3423116443ea6e82f04dab1fb425a1d077f927d75461eba92520b93ab74aa0bffb148c2ac06acc04f90b9cf4e282b4b5492c0232b74d381f99f457c6613df01ecb2f4e32427bde1ef6e1244aa61009990fc247e3f2e95231a3f8d709fd9250368c4316fba9074e6531594c9527f2395b78d77a07d29cd0cf607d3ae0ea983001a48c146e8a10d2464e4f9aa8f5d51b4bc369b85032df5fabb6c1283e476d70ce4a9c5b196577df55dd1d610fc3acc5b64b5dbaffe30b3790611922c304fdd0017165bb5b163e57a9e0f05f96966fd602371c6f471df0e32d26ceb410c44e6067deb9de591fd90a2b433610b255b22d5d2598dd5896c35f2f3cd90d5061253045b4ac689f33a7f42009ebf2f59cc74b0103058bea53704342b57e8bba210a200c131d5365395a83b91222e5440e6a696f57b39a1adea63677a452685e88dd203c799a4a792d1f1c16ca9239c7ec00107049d45b124b3f8888940c480bb968800d839779bac97e86c4e438dbaf48cd62471a227339c2d2c4d95de56f9327d080127e0a7adfd10fe06342a08f5182597376f114ba748c7490b49690fd9047a620f5baa78f3494b392e645c5976af1d036e70ef7cb21e4d6ab3d702ee17881e72097fa5e0c1695bfec4f1a64eaaf3e9186b79a441282b7ec4d1917921aa087013049adc324fe14cc4634f56e6e6619a59c37a1ce260b3f089ff7ac6225b92c7100b1dd697c05ceccf65ec1acfb57ed849d8a852cedcfe00ddb20e02f928ea1a90015eb5cef88cc8a88dfdc94707bc2f07d79519fa00cc9e387973116d56346673040d062b5460d2a20ea2e6fbe07372b981736f8ceba7807276b93932ef6b47a20a6ae9da770c578c56cef6741ab2cc938ab6ef4b2b43f67f432710bc0a04cce60b5358714793a5a1c8ffd54993e6cd4a1a1630d697c82bde9275c0a8acb4e8210a45813e8e3e3984e259ad6f224d8a40e8c476b2f2595adda2a0bae542b11b9309c2a3fd7d38970674d0c38de2614dc651362df4103698aed29ccdcef88338340f62eea7b6ada86f78e7bdd34334230e9ba1e10852a965ea50c9a500aabd575c0cbc3e855dfed20de9c9ea1dedefefbe3790fd88ac21078cb61c919721ec050f094be144e6401b58936c1303cc43a4e3308f1ccf39b44d4a413dc4151afdbf050a0ea5e5aa4e4c3eb6ac9ba32221fb0d945a4e555128d03e591a029b6738d57a0bcf7b8482032bf741b46dc0ca5fd8019cd721450bf5b5981378a39e6fa4a39b031cd4233aa74834bdfa15fdd65d798fe8f31fd13d428cf162c97100181a3d4d048dd9d4477e80d6ed85dce7496a23f1d4ab3fa28ccc9ca29e57552b4d1e49200e243de57989bd4f52d3bd59a00c7f71c090f743d84a16bdb6f673f34c065a3b0433f863405d24ac07a162bd6f7679049bdea8ccdee7930aa0911debec26de4a097b2604683cde6475217c3477615bb2a8d0dd136dad3142b65f5a79e923becd03ed30c2a9fc83b62d3eb7e24fcdeae4a11803a9a295dd4cb17e3b7d5f61781a0175c02031a60fa336e3896d497cedf922c5b93eb9b69f1bbfb7c8b8310773ab02e8f0dd96bfaca269e3e2e494a28a16cd2576b6a94e2d3392cc4e3bc1dc30400fcb46046f54332962e59f82b8dc3064f935626b06fe34b6101be66ca92b846b00dab39822424ca36445e17116067a60bd9bd65d1c1d06c59450e9e7d6028390007e11a696a8b3ed26e85ea873ee849feb11d3c7a794dc348609169ef852f20100402e537262d78915788d6ba8bf39bfac0cb7e8290c055469346eae64cd6a310523f10bdd4b32d6855784156028d1918696ff188b5f1f04be078ef3b64db17a0fee064c737323c1c3bb8eaa6a77e577c5a6d7ec353af451a29fde6f0555d679024e542d0e2e0c6256ef74006a9fdfb36591e357ca051294d38957677c1827030a7085d7c1f272bb302e6ee55b79012289afe9ba505896d234f31b3da41ee7480999c585c425953cb57973af592189e7d38c7112b3a81962294673957bde3c2006b52b9c2030646d43c276a03592e501fa7b590448c3d7fe44ef835c73162eb200795625997643762ae42dc7cec3729e4c32820a1880202c1a9ec439af5f1f880685bf74beeeddcdfc279a1526ccb0b82fa2d12f62e2c5b1338284e93b47be590abf0d73d4725c4933d265f397661ab8249200ce7d01675c6767a0e411ff1b460231242465e5295bd9fcfd5814b2766bacb1bdf8bb5fe5fbf6dda3a7943d925806c1737ce82e4400f4c7412d819a344488756a292cc5a27208197e8ed95e4beb089e627ffc5ae59671affe6f12d0cd62fc4f7888de36f4c22d9cdfbff3620a270357aa906800d87e3a3495deaa701999a652b82aa581651b0f3ad643e3d31a090f30486bf44c7703b78993482e8e0bb99faca2a99d108848711f79b32e37b10307e6c8b2041ec8e07aca9e6084edb35b0e641768fa8acbbf0bf3e20b047fa7ce03842632f0dee74e53bd04f4d2bb6259b97079b5ce04935021c0d79f06fae8c0004d11387b1b2d75cdc301e4c280c77d237219acc0719cd9dae4045d0e8f828306b91af39536d6f850273615b51aca9465e8b65eaa7b4eb05ef11ec9990161a60ac6439bc24d1c0fb445acf4b4cba99f4ddb40d5dd82657c518fa95a0433f4410c52492f96ffb7aa814ecdf0ec685a66170816217f125a4a1fa696cec1592fb701f8de55cb334e9f78915a1e3dd30bde5c66c9f6fe1435d7aa908e0245e3ba930bfb0f02960cb3cbd3d331c2be7e2dc1314a8bf67898cce0bfa63813522c4b900eac9f8fe14d31f2f71cfc42d5b0bd48ce3c6e8d5662ffc9db50e7ea7ed0b50200525c20ff6e6302585cc56b729891c98cd3dfafbd729f7e6dbd6338ed4a8a810230b8b373d84ee0b7a4d3c28614ac3f934c366a0487ba62c4ac23dd4224707a09ee2e2c66ed53f84b026c17fd2396a3be1be6aa6150c9dcebc8e13c02a4ef700e34051aa473ae5df96a0a1cf114c094365893059039713a22640e872ed944da06b7afdf02b93c04aa84ea90c695774eef32f50b55e6c5ac2c6cefd0a42025d0073724cd5cb89ae42b26ee3ee9c0c3e2a8e7cec2457bcb77aa09d7e3c9593e7c0fd05492f53b24c297d0314a93d9ee73dd7393ff197f455e73f633edafd8d62b0b2324b4295d1b14d288f78d42cd87ade5aa2beaebf9a489c061956e851ee28001abd5bef6f8d865c620d3e29533fc149697c14a5d5d16e7142bf3dc413429680892c5be7ae973c0db15461c0a7eb4c7c6fa93e9eaa9bf635b3dbfa3bad5251a0ee943a16be6e9ca58ae2758c0e73ff6038e515a5a926e7617059e0867c85e89078d2e2ad5bcde287e8c860edbd671ab942778bdbcc1c7921ffc26d337d9af1a0e115f43fbd394b3cbb5915aa47eb3246af5ac1bb52a139b02388feee54eb47004e554bb49b97774c8097fa018a7d56a68f670b35161d2ff5bab6f53bbb009350ce62227e052748a445c4a4fd56d8e69c9a05b8a36bf049eb788ccfeb4e3385901912ec481893a01db0ec5a8a5b4e40a1d6120231e218018f8414a84f1befd8d0bd8de86c55c0ec8bd529dd4d3e7714c9a98c5ca227a337549a04268f00576860c1f75cc3f4e0ff770e84b6840459a884a3dd11a5c4a9f2bbd477dff1fdfb2e6053ec432a735095e59215e32cb897e9f12cca62bf65daf38660ab17dd3985cb900efbc7323d1ccea72299084ec1ce0b0d58a9419be4d65d09bc24a8a2dbb7a4606846b000c73ed19afc1fee71aa3c864cb51434158c696c9c76023b5961e2016041e7f621d17a76e6481cb8bf28ebf04c213c8647dab68667b9d596267215e2e0cc2c40f8101abf8e4b919755f51c8acc58da76fcf3ba38eea4003bac28f366e0360bf5e632a3538ab92e07fcc4f154660e3bdb270dac301f92e519d46c3461d045ba6befc421ab03f907849cc21563e05ece092e26d725c4974157cd55c1abd0f8e4946b723824364b5e2898dee78031483954d094688bc0925e486c4b9102203dbbeeb14d648db7e79de18582de6c5c7bcc7a1fd11daa8586f685755a4d1b50acb47e43bf0f7b0a919c7bd4a9b6ac8b1df838dbd556eb327516a04a7276a5d006fc4e5e57eb933a93f7ac57f2143f3a4ecbb01bf894e50917e8cf04523c1470a141fe37ad231f9a074fbdc2adf2699ddb43afbaed1894c27a0e53db3ace41e0fe58676b2ad6198c31c31d4c2c9aee45f3a68d3085eef2e7748ee4dda795a390d4e17ce308d2059433eade2147578cbc92bf877179e62d11feb03448a00daf80e13323c0796bc7ca639c95034ed47310b5bf98fadf5aa628fad189294434fde0e1aa0f413ba0b9408aea01da087f516314d5b65ac164f6242fa44b664c0918405c5134d7e5a1880a358e4912d3d9402f55f2528e1007a2875f74359223b6e490b7cfb31f3b348fd689fc57ef24560f0b20f4aaea47f04994bf5c8cdaba93e9d0f4654a40603a34892e68b0bde87570a04f5d4252701738e1161abaa507b4bd40a7ca706b235a061dfe9caccc6ab7a77f3959d28e70d311a41ffa12c8e0553e208d4a9ec6d841063fef1b6a36d98bab2f3953b4cae4400c32a1dfe79ab97f51209517b630ba3c6e86bf110fd27fe5576fdb17ccd7742c48c2e5652cde4f4242206702e4e864f210442545db89086ed156c9e12e7312b6e6d55124ad65d7ad2910be9cbcf85655bae5c348a3059539ff1e13d69644cd6b2107fa1783ff16fbaf5042da2cd33c52c9737c80187d23b8ff82703becfa82a8436d113e7408e475c430d5226648bd8ff368129e0721315cde38c6df25c8bf264faaa7170f9d36e2f8b0c6f2b09d6dc03d1a5ed21b9661d9dcd4070d79217af70769c03c29743929bb809ebdb5c0334231f372e0f241cbb60cab80b763a019cc65f40f466a4cb35b53d016badc7705a8751404ab345f139eccc757e4e226156a07340cfd03b6aacbfb10b -generate_ring_signature 6a7c21315ea9a0794f13bcb92ebfe303e1b0713cbd6bfacb529134a6ed01585d c86de54a568c92e9d6a2be843389eea6397c740fb17949b70fb10a9a58842e2f 53 a4eab03193f38a2e0e982a87120a234f90b0bc7944f51cac35a25176fd58b777 d23b91b0325fe014f6e53b9fe832d97042b4aaa25cc5f1247658419c48a8bd49 1bbb20d6fae0893cf5485c19db5e675d999a0e9dba0e0718801dd3f2707793f3 2b515426826b80e919c7b7acf9616b6dd5572e0d5dba19bf9e4da51c00335487 7c9eefaa09435f31121d5e355e4fa554668f4837a61973d30dab74d464cde65b 37a99f9bd561f0192816187d019987c0ce5f147d4c418bc66f1a5cdfa0e883bb 8638bfc48383464f756c3664e864d326bca7855cd4f8741e29c74dba9cf4847a d67f42eaf5b97140183b520d329b27d245e46cd7bd00c2a171ffcf3cd8a0c9e0 4e7fb336b76b0304d312f2d75b8bf75834b7398db6526008a74874e4e56e6aac da1afcb4fc99dbd35c26712046956d72c6ae8500c3f916b34d670e6c9daf89c3 3d982fabf70524a3fbad979afbbcfb2d0bbf8c2aff2305bdec06e5c79d98b47a a5f8ac98cba7822b50a7073a987e71de73ab843465b744a3435b4bd005522a94 08ac7bba764eecbd335e48c24dd1c04c69e0f2b24165b12a408901dc5da87043 6a9232cec3fa118d16cd669e6dab9a8ec07a0141b3d3b5c97619289400168432 cdec045aa9b95db4758e28ef5d3375c539019188ed4994d59d932c5147e7d84c 76b7e24b615b9c211c78a8b212655d2abd2ba6da10ced987e827163c9f8d80c3 48da2559b00cab37fbb05f10ebcacf51650976a020f045d7dc83024afe1b2f6d 4f16a0f0e1da96f7b885a88f5d203502d5bd717ec8b5836707b2da85accb05c1 80d6ff504ab0531ce476105fc6c6ab4cd39e75f9ba0bd781b7f6e9ff483f71dd a063b2575fc0ed77466d817dadeb051e1264af664b3baf2fab0b3bf3c7b5cbec 69d8a67beb3f99a7844a980df676962f97b9971a1b084a5220bd830cf279e181 33acd6c839c0c7f438189e1f67a8313be209413fbc7b0b39d1265a6d757f879f 97d4d0006c8c7deb27813cb1235e7c914a20da278801c2f3697b462071114276 f006a40b43795409e5c5254e5486c9522ee2fd1a338ed26e9b40ec4e1c29cd52 eb6c0ccb68a8bcf2c2f322652f6e0635d46e214f0bc0961e6ee431d9a6e70e6d 10a6835fabd12b737505f67c3194489ad1f67e2f75982d50c5eccfac7661c050 2743f8484a17f4b8ab423d9a06e648638f50037a20b453f91da821bb8dd98737 ef6cbc0d2dfe502227ce198c737f0bf0f7a4931444bb8ddbbd82cc317449dade 574b33bf68724f9217faccbc97a60e2e6a7497582224aabd262dadf54a73453b 1996d428c975b3ebc9504f329e76d724f2716fd2d6b09436f0241d55525dfcf4 4aa00e19bbb3aa17adead7dc76b7c018a9afc20b424fd11b53514193ebb48568 346d12690e9ec83837d4f402b0fccf731d999b38cc66fa1bb8be1e46398b04d5 a819b6df989fdff76ab04fdd6cdcadfa2751c54e14c359b6dc63f285bb545ae6 8cae8ebd0995b16248b6f1e3c7c61d9f0de44b582ba27f155e1f315b81c0af60 0e6ab1fadc1ce2f6473481649a3a500a86e4aa00a042d0257506022a7abd0965 e2adb81732a12b14a36d92d5ac877c7eb23b4d365a31f6340ee0e85e3044cd83 557afb592dc585c70ad082f601b97ea5d53acc1e8c1cf2acbf73cb2e4ec8ed20 6e2edee22b8a26501186cf35808472bd9c5343c3763d921322398abd5b524e4b 321503c0c52728139ef0c745f510897978d1805ec1366245f14c12472c8f7926 1e94842bf9529a263ac929ac90835961315297f2d01d83fe9212cd0c5d86f662 f278b17bbe1236d3066be0bd4befb0e914a524f85bc146c117e05db1abc54126 d62acf5d9572433e91cfff5d9d319723e0d49dab4a3ff4a7a2c27597ef4171f9 1cb00476f95508a5c4b27c7de7ae82386bfed926cb335dc6bc934b21460abd7f 32855938be63eaf809c44abd425f69aa8699cbf7f8ddb2a94817692574f85b31 6d16cd460eef86fdd3a4ca2642866ce01e7f09d9c7e3158ab61fb4fe7b1f1866 1382892cc72eaad23a9d62e3dcddc3c8e093177fd99076db600ecfed64b60977 d7757e0cabd39e25dbe09943b20145c8ebe5710004c53ef8355b9e72027f6cca dbcccfcb3708dc00901fda1044bba7d6528a966dbbd4c7fdaad104817a37428d 42296a58204e10349dc6b9e58625ed27b7a0fc30d56f275e5c492c78faf3005c f40a1bd0bf96be276a9a65ce584aa7be335b762ac9adef807c31630587ec85f6 4e4e6efaa2112f4a9f3e2baadd787b09546ae6090f39bb2c2c701ea2bdd8a36c f74d02271c39444a3d2742e7e4015fe3f3a7f3abd96e4c04d719ab0324352638 1f89028e20b6bbd28eb46ce5a94886c0fd79ed9142147991750b7ea512c03be5 fdfa920e8a966735aa26527da416a60a777c4e9977d85417cadbf32400d27204 12 362f1e874fa8da5609e479cf975600afcaf36fb8fd6b420d1a9e1da0afd5760b12d7e4a82e8b590e594a0c40b32994c2b2572904126df150a76d0393c2264f09fe8d7e57b1515326e70d09496f7411113b3f8084d224e4b2be5a7b18874e0507feb653c395a5353f1ee55ea1f134aa4c915632de158e6699af6e9b0c366b580e4e4e29f290eae1246dad892c9222b90c414bf12d7596354e55ed2e8f1f5a1502b655eea199db586efb1a415ebe0ae929a552fce35c23072a04a1c2e0c08c8e006e13c97a272ea2c2b1eb91d7974a448e75ddcaf3147723249776abac25814d0a93d772e28c853f001c864f4cb3a1c75c1ae34b180bbc3c638ecee1230d8be30777800b59cb4242b9c9fc859e506edd2f26ac3ed2d30c64c73be355e07810280bc7d4a8e3dcb26281dc6e95cfe861c5b138292809a77d0ca1dbffdd2e2066a00f8c7b79688e1d24aae7e18f65740b899b5e3767e27b36926faa7f1321791489077439c6132c8451f169ce7e96d0e05dbc9bd748ec339749478ef8756767fad10a87a271d42874b85c729f12d514e49c9cb26d6ce7c5abb96b3df4c99a1db81c026039b0ae079dec47b1b861c0caaa53ba18f050cc86214af7ebeffbfef8908b047498ceb0cfae3c52f7c5454d337f11322d0a9d261eb65aefff524a165e3cab0885091ae69aee81e0a85cfef61a0b596fbcc5b864c07dc2d7227a6cd95db426021d51e7a8f1c56c9f786a59f2ee768c1285e526c23d30f9f6f087b8115fde8a009cfbf59104be29e9dfdc982ff880f840bd4865aaa5147df8ba3d2739ceeed900a1069774454116bc7f689381a9fcf5aa2c6daca1b743c08ac40f2ec877b9e80ed491321eca693a74d6c5e19fc63f41bd9124891337dac863266b5d2cc629c80883757195377f736388e51c8e2581321112f3792a6d2b4f64af3502127c6e060e88a22be0e27210da967c91a0954bcd9bf5e09488402254c144ab2031eefffb0a6d09a7c24f8409876937284b23279e91a3d67e775ba79c887ae150372f00dc073dabdc3d371b60eac924ea4802335b2814ef81fd3f740ecc243da8416cd6320ef99f21c94ea31b0a3fc44c5677ebbdfc3d0844cba376f931316780eed6cf590de5addf1704eedf96be395710ea0274a6e52b648ad77f85303cbc408b67c7d50a48ee4f3883629fdebb7347295b7823115a24e70cbaae2879c3eabfbbaecaf50c38f9de0b60bfade3951de997742c4b997759a25951d08ed2b721eb1f4e8a7e091b871cb07485b3861957a21201f9372c5e21f06d0e12b6a0652c3745f5dbec0bda07cf43d0e9c70f40452d340738bbc883c5687bcfdf918840fc3553cc8ecb05624365a429a6e79aacb5055c298cfe4db2c23a0be3be9ac39010d71eb2cb3d0ce3db316df6852cfcffabe94172f31e513e25092d55b944f5535040080e6e920f77fe99a7bdf20fc71ad333cc8a5c59e99274e5a972143bd3633432853cec0b076b31e9ad695b778bf14f5ae3043da1d9d3901b798025b5e62c592decebdb6f044adf0117bbb960dd7ddcf9a5d4c0bbe338139c17bcc5c13974485487e6ebef0cd32c9f153acf7be0668b03ade1e3020b7cbacfb2738893731ce73f9dec630600143c099f919b16be1758eb553ad9c780c8290e2fe1ec44d2fa6a2d7758d8fc037ebd2dad517cac1f698052697e10abdf35948b0d23332f7c264f9e55f2903a0385f3b8a38b40be2f0e7a4bda96f81f60bcc82ae6884b28f01218dfa6e450b2062fbc622d4bd472aab4ff6c8da0c254370aaad03a0852fa5a2dfe58c31a0fd400aca0e93c7dc9150fe5ea164b773b5e5c1df27fb9d72b1beb82f1d11f0fea580bd6273c34033b08a16e927542941576198f359d8f0e5fde177bd1a6ccf4ec9e0492b56a484be513bf4f73390537dbce0dbd6d7e07c68c128376406b636e61ae08843bee3021f19fada8791ec911e9c879fec2ee6eb8903db50c2b9a71ae18b80fd5cc566d9493ab01078495f8163fedc996a4a13c7f1170436e14b1d914a76c04e0082e8b1ee2f2b3cdd86e8e3e0f68c123cc8c04bd517a25e80a681d9a75bb05b74eaa1b946d1b5af93d42bd4a1ab49f08d33a1bdf0516bf110a1f8a064fa507122c188f2500651d5f94b9d44b449d12303442153b042a4769ee3dd90b01580e6f41de0c51e66430a23bfdb67378503c6a7b16e5b491efc4296254070b099d0039114200b61fcd7d070aa2f756fcd1d6674ebbeca19b7f04627afe036012a80949e6c9387941d518081094b9fd1cabea95e53289b62025e801c5a2cd1148160ca04c483d4d8a61ebf93dd9aae43ff8ad33c344a983f80babbbd2dab1a6644a0d54610f7a546840185ec5493490da7142788a19d6c4286fd32d3566e12166600fead97175768f8b81fb354f20e923fb92ab563d3b67e238b8c04cacaca8323b0e73b68b7f5b71e13ad41b5e9e8463da272b5363679616231b7c3200b21c09c4098a3e241e35c65a15fd6bd2cceb3e82e69fe4780b3c963af318c600e020cb9801b9277df3df1cb89ff13a6e51698ec34b6b968bce214fb26f26f9a1a05ed04801e822587da6d43312701ca6e950ec74a4a47404afd14b89834834a752afa50206128fd543095165f46e2fc25e94bf5ff6b7b8355e9e4788f26eef4dad0569e70e0099fa6f66143faad21af9abd709a65cfd00893296d54081c055078e8b6bb70dd791e00d92dca8073a4e6ebac2f3a663aff43ef9c1823cf2844b0173079fae0cde03ca32be734cf8c5f908517ee0473a548d7a7fa2e3f464d41910480dea390232942a44c00590373277eb80b03a6773331770e824e1fdd26d307003f9d3f008ca4bbd93084017ddf51053611ea8cfd4bec3c809e34481bfc835ad9ac1daeb0a1174640168b4dcfefdc6408f46a94add4275a18e3ba410fd5777b81d8bc1a808ffdc6b6a82680a0b684aee0d7b2814381d9e0f281f6f6d19ba5f22cda814930ffa0f447be2f7ff2cbee3c71a41726484b8816376c192e6d8818803c6633f580a458e4489b6278c9bf4e6dc37f5b17ba5afa092b3fcff6f39794b8a5aeac3a0000687f690a5662ac5ce6cf563ac7602ad558c35e8618e2d0eb2ff8f2f5ad508083cc274de7ac5c1661f5865bc14316700d1bcda79622a6c521dcfdba2152f8f0f79c73e27aa5ba0a352b1899ce188868cfd959ba6cde3f1db5a82c2c61bec7e0e46b3bbc7ae294395187a3f6ab65fb646be3595609ae8190cd82af93602848307db1cfac6900d65e82ca93f66e0222bd254e017d1f23022f76b22dbc696fc0f0c699aebf95bfb2876072221a838242efa4c41e47f8cdb231b7b6a4aaf62b3fc0ceec422bcc71e68b4085de03bdd36f73bad8a715b975cd6ed87394a667552750f4a7c45065ff1da6e221006fb6176879e2e6cccf4da34abc5741f0e9c9bf7530b1a3ca21a5c8c7420712cdb0ed3336fd4cb70620e2037bcdfb3193d6feb4e070fc72c6314917a1c3a051781fd5c138706d0de066f959e03c3fdb32e84ba42cb00d1f4d50efbd76bfb78eb50017674e3fdb2536f7fe1d86cf79fabdcd9ea1c700b4438eec37af8005d7f22cebd13b496a0d90eadfbd4943b0d120b4fdf9e890d0aaf9dc3ca85c63c7fdf9a8463984f0a6411324214b7c889cad2f618f537a685095cfbd0666b116c22798bfe2b2ceb0f247de8756c3bd5f7ab17c158658b10cb09131f92300b295fab075796927244d23f1f04db1da1ed711d4e745d5bfbcb9a02ce1a22bf3002a1a4cab1dbcd49b606e40c53a91aeaf6bedf01fd53f34b31680fe11f46a5cfbb0996ea26efb4aeff5a8c4befc90a3e76edcfe4c5eb3cf7949e0b9a1ed381c8e6d0b844a7cd3d0566c43d3c87d1f0284833466d9d49c6d8cd9a064dae2bd409836c3620755efcad2ecdae3b87de6be8014352c9e8d989c66b3906165fecba7b494f11e40686c2d46a28602b3909990f2cb38534e37da6499db901a6e2489705eafc7aabe77a263b0126e36a288437d6b744777c9efb7c1814140944de7893ce7b02a50bbd9c3dacbd4d3a832a1849f4f690ef437ca32751b5280880e85f355e0e3a7e6fee12d74f3aaabbe3d800f76c7a99aee977da97c8168b0761b094b1501cc2d7c873153b1b689f091eb471f6c7053d1ef0c14c61c50957085ab26191f2e43b6a3bd81b94778fe73a457ef7a092da38923cb7bc87f1ffe405fc1d3d74ec288436d39a11b7a937079d8802d53ee484de06071a3bf755ec22040fb335cbd138f7973b8eb5124f4f4408f7bf7061e728bded1a9dfff4c36c18036d3d7a2b8d3dd560aeb72c65eb5a180a04c3218fc3a9b25cacdd0bafb2e3d00bf7e9b7136c517c6da294ca2dc0fdd27ea0bb8c44a79cc72ee009cdfa9c80c307c3fdaf30c70efd881aa74f3ecb22edc67c63ac557491f5d4d037a14a17390f0df51b9cbd46cf4ba88d64edde5b0d31e781e270458dcdeb2586594c1a441c1b0f3d6e9fabb7d8098e2e576a4095d3d233512dc5a33bae8ced3c4b602dded84b012e5cd5a7d801c5a2248173380cb6d2044330f1b833397fe85a65ba0815d44f0bc5dcf3740089f0c2fe6c52ace47c649021404f123ca9db6a31c3eea5e1145607161e8eb5c7324c58061de7593e9cfc9cd82647147c9350cc9336e811df37760790d8ec6616021d40955aa6526a9159d1004f33ea9e480e3c1f70766a174fee08d71c7231079b69bfb86cd32eaf18d1e166e70e9ffe92f299cfd29625fb3c20077c0bb0a04e0164c0c442a95429964d062dda87f103805d71f273fbd98093a905 -generate_ring_signature a4f99b4aebecdbfa9f6c5fd9d62aaf72bf17ba6b85b2b86f6857d4eb5aa4e2a4 903b964eaedb5d9df0b0b34f0b20d58cabf1279e7254300089735c55779f6d06 2 6312750888bfa7ded17884f70275bf7e07062a1df46e580cac091363ce7030b2 155806e2d34207010d5b4149cff7eb191ccd3d38dd5a1cfd9dcaf19891878dfa 04ffca61416f5b7b5d918e456a81e4f50a9d4bbae583602f8544be5a74c35006 1 f3bfd665c411530479d358d573ef0a60367ea9a39f3b14c478c6a6a3fa36760d50626f2f9535e6e341e26d1f5ccc0a69c7acffbd1d902c958b2bfe234002ca0f54d6461138cc02ca1684a2acc7191f7a584c35b3b77f68c92a5e0719cc8dfd097918dd169214dd829ff00faa5d1e1a8a7e82351a74b5b740a65089603cb0310e -generate_ring_signature bdc62a6efca6c735edea0f7c692ebf61244271d37dcfbd89d538eec558460cef 615390da874162142d31fe5efe83e353bb9a35a06e861b6fa96012afb6606e53 3 f0927d23a105b3550d3aecfa2c3115c5730636fb068080dab5f9e2a91455fad5 c7a262ec1e963a0c885a967fea2e3da4374e2400ba9645db84ea1c785d13d07c 38a3d5ff005353ffd24da4db56e22636e1bd2c0182cf4e08a84cb50af7752351 a31a2f30ef28f312d39d35032878250a53ebf5c77325eba642299bf98b567d01 2 b4dfada2756e35f729f0cdd6464e2a3b55eaf2f617bd1f2d22cf7b4c37588a02da8c071cd2d2def07efd3dff48f3ff417257899a74d6c4cdc9c77c1e0eca350fc5804070564dacde4cfa88fa549520d6357738130732ce6e36e40c036079e00138d7e752a8f849a9130a10f4995ddd5d6b56ecfb598964fc8b933f68a3d65004739d5c0817c5e0d6532cbfdba5e2277b2f495a7b88b8678f852e40fbd94c1102fb432a3955212605264172d37eb9ccc3892ffdc22751e30c19e7516414d69b0d -generate_ring_signature eab1439501745d1a9b34fcaddb7a42e8d09aac0a4070e49c193b7eabe02f3e72 6ce8208563bcd24b2582f5c8686df7670c4046c6639d9948bd844d83c79e6813 1 df7698d71575f97f8c3699da593b61ed18f032140799e2e62c7a14e191ac49f3 004c41b8110c26fb97c3ceee44a7423e7ff0fdb3e7911af60bc4a03f2efd5f04 0 60ad30f6cc0a8e1b3f1eeb95aea3f9a24e582f37db8aa73a93241a491ca4460024ee2186348587ecdc00744b6ac04e4898d2feb937477377519e19f55bd1da09 -generate_ring_signature 50d6c84602d35a33a30fd22db0d5cafff513d3947624c0185dbea80caee90c5b f686926e40d3a434315e5f4ec24c8282275b89773f52a4ed817025943ff7f022 25 9a30a185b0624525d23c91ea4f28bb3721a797a790c5cec3a7028bbb8e191027 8f4f792489a3796f4c9ae40b0e7fc91a7de29072db0dc09d3c5890a294d01a8c e12506e001bc9c5bafe5301f3df40bd27a974ae162d1446fcdb268a2406193e9 e250ded73cc3dbf89e920217cfca4c614d4eafb5a40c6e36bddc349a4c686597 b8b0831d43d7e2af8aa0d607b3ac194c33dfdf7d3efe78edf3cf6546011810a0 76423bd48cf42c31fc156e3091f20982c6bdc3db8e792893528279ecf06384c1 b7cc082b2637338f2530bb5340ae7c4fee3a2143bd2453970ebaaef83c997592 f85494d2c98b7f25681f18bc32565d0039015aa5266f65dd232dd731b09b4cbf 3ee9148bb2f4dbceb9c0869f3c4e7a5245e6e549f214bcfe4d91f78fcb15d6ea 1b250b0f1e2114b6cf2d6c7fdd4c7b9da1f7bf721172be560e2fcefdfd4813db 9d1b3233a32073ce52df7d1a307de6b836582afbf0474351e7f0a2b2a7a9213c 83c98a063202a587794fa6d5b0fa0d3c18a21b81a43cbb366d26a91735117f86 537697e77585c2097b51341c2811cda8fa3550cfbc44e529f0a63d63ed9290e7 5da85646a0b264efb575a635de1ef2c955a765dd336351e1b2ec3994d2c04e5e 832efcb83d53c171206dc4cfac510358bba39225f385a551897c4139e5eab6cf c6c37d8fa87c45ddd9c6d9f1b770c6faf56f903b59afaa8803ee7fc6ba5a3e14 6389ab8261b9771d991039e4aae4bcf58fa807749905593d1479a23dcf6d2e3d b6fc1558d3db2bd362d2aca176659835a3d7f34d5ee2c6da1209bb2355b4e954 91c3a0980db59fccc7a90a69af24680af4bdc0d17e0a72fa7fa5da59bfa997c0 e6f8b0e3e397895d57639d5aadc9881aaa3d8ee04d31fc68d2f5b9e411683075 0a4503f9c48b731d1dd8b2280a575c15e5fef2ecaca934969cffc5cd115dbf26 1327c1f73ffb2ac17233d79624a17b1aac6b645f16f2407de8a92077c19a3c7b 6dccf4059e35ab49f66e199315e763efe2815a503eab8bcf44f4d25534f9d200 f947e8966541a52c0835c2a064c2cb71bbc652dbcdb1dbd3314fcc8e75a01f3b ae46f670527d4c0d9f04e0a4ab67d23a4e4089107c3250ef62c9a43a27c1c4db ab8a1a9091fa8089477cb325d13df16b35fceccaea164250309204415733760c 21 d2bf48116abba1d2948aec018e1178679133c4279776f7f23f980a2916a3bf0c06339e395be2bf4d55ce3dee813d12836183ccb9c4c15d3581187ac8d7a60d06d3365526e825344e7a6bcd490306d9c2c9bccdce0c64f65fb6ae948acd3b0e05fac2290d8a9ac6cf8efc42a45fb308815386c28afb146bbf4bbc95c1786bc30a26b70c634f23c8d67bda12b0a169653a89050928f9a9388264db675375cb2a0c5c047b9d0ee8f1d270d153276b591212daf6744ca9492d4ab4680ea4ffa94208ab89c2192d4d093374e5589759e21fa7155a88ebc1a45a49f780287fb31c3c0da1467c0aaf63817b7d9c8c3e9f8c4e913821cdf616b4b467c11cdaa86ad9a70fbb1e59c16bcabdd8cfb26e842c576dded2cd86dfe983e4ecfc5a09838227430c42faf2da6aff8095579656ddd5c073ffb6645ae2df3e20d93de1fb7ca21d5002082f4b0085237d42d51c484a704d3fbadc1c8b413440ae771685c97102f9bd0f548b5a270a5822ab2d23aafe270831d3e2717a1a6ed4d73b7559ec497532c700ff1f48e27ea86b838e5b73268f91e9d8321361f85adab7e907082f806f704503b2620155cdee7f98951233db488799372fad0fcdc3e14506c9b9ff085961f70c2db280b6fdfca72f4700df1a92f301d98fb9ccda81dd1cfce1c8950a790c8b0fae6ecf403b5f9d3499038c8277a11d05f58fa3a071345ad978ab75069ab6ae092d0e65398f8eb45299d33d282a91e7e5c34c849883552762352fe3a0017c340bc5b8ca7cd9b6773e35e38c6dc65efa4ced0ec4153b9e12985f8df1d6ec76f10f6a40b42669386ddaa15e6fabb47a5ef982f78a0cf243f0b26172cc5675cc7a05a9ac88d74ed7f3dbc34992b20ded541ab339b9fefd97f368003af8845316090f0ffa5e4656d7e3c789fce2138b683de1e7a10fc885b438d8d5911b70e2126a0793a3b950996b551e835a5f097bc5553c0fdf6ae6fa138257c490173b4004120fc534d58bfbb22293767d56e8bc866dcbaccda0fe473882f8cbff6ac34d2d9507de095f0e422dee20c57b104d3b08459377d37a2df822e21e64503f5b0b037f038f6ea6095e8f0ec3e33fd424c852ccd5775c822bb3992f16ab58a14674c50608a0d65154ff4edfd430fdac3c695adff068a0e4bad77ae75690e5636cc678cc074a3514acc4f135e7681c47cde9057e883c8d8f874703fa0033aeced1e9d7cf0dd9d844dfb47526eb72177eefa470d3b9547a1ab3afe41dd8a346bf3c28bbc20d0c317e0c0ddf9701a099cedbc245867ce2fd113726535a0552a5b88d5020650fc3bb6b7c835267e8225eb651b7fc81489b6da3dfa5286ef2727e7dee0ba4f6088200b248731ff36ef6478a91595246769f628b96a919b82c6b7c394056d87701f62bf204e948a8bd693d22aae3645a02727d950ddb752bb86f2acfe48ffbc407eb3315311243c8e54835c4a8019318748c61d64b3c6ddd62c6a1a0fcd9ff5f0ede06443e60856efefdabf99a6a1ac5638d69fb8395aa9e5457815b8191ef050017b050fe1288526e735b94d1934c18b3d9f7156a45d073d7cfcd58aff8e69c0afef5da22bbd78edc19cfd9e423386fde0eb62bad363cf2e27247654abe58040dc7a5d4faf95bc31ff5b54ae47ac079ac916f90bc47ad6c542edcaca72d86960cef4522713924447330672851f0e135c571b52eddd4fc327ab4599037dd7f0a05c6c58ec3e72f53556311265d817c769e655130155c6d583190333e0587929d07aeaaea316b3398679227068022b1720b327d4d0aea82985039ed20389d5b2901f2ae0c48d2832a9f516cbf49e53709d28e7237e148f788489b91daf4df267708c34d148683e551aa5af15bc23646f83a84d145ddf210d10373d0abce5d2b9208444ffef792299861ed26b37a4d0db0b4776c3d2d5d6bb24761d25a5bf2a61b0860aca7d99a08f892c474111b9dd79dbf10f0e3f69d5beb498e5aa4454754620b5532c6f8461db6b3ec444ded07fd430d20c0bd1aed791ca02c9a251289fdf60e0b67254803ee39204629265014fc6253c2db7a3d0a6c4acfb143dd8338f94507276760e484a3eff1bfda5572f7fd1c75da51f7504888853eccb1035a31e1a502f4e3faed1810628b9296f127bac4994c0f7bc106a3a12779e40a8fd8ff31df0e072af4413d10941c8126d8c3fa0e927f60dd4377463fd434ef3896b23695de00a7011ec98f709db4e46e9502279f2474e548af10481a6411b730255d81909e08 -generate_ring_signature 24b6afb3f6d03575e6b84afb6fd3787b6554e649223fcc94f0c3f8aefabf9457 c34607c491db77c2a81d12dbf15e28e3fc50190e43560765d84b1d88a04d763a 5 37604db2c71da54aee4ffa062a3ce264f6f968bb22e195de69667a1f6d8346d7 92ff0f511601d6610f31f3a53c956265053e53a94a9b08e841da63cef7480fff bef1ec8aa444f5d1702357ccf31de57d9d08297471c8071ca27d3e9f30302f6b a0dc011ae5cdcdc8ea827b893a02feaa74556f6a50801ab1d5994f13ffffd133 77ce2aea1d830beb85788d5b9b9ea39a1aa0383807299c479547e16e7c633acd 1c5e52449305df865f8156ae662da8e69d334ee7d0c9ac835a359ce5ecb0eb05 4 d17137beb1f1f93628afe1ad77ea7ee3184aed0078771629797403d6e9b51e0fd8102628c57d5b2474ff412e65cf0b6ce2d2f10177e1da21fae8c3123b4fc900dfe40327694e5b170720fd08ab091013b4645bee213f42e07fa7e95214631a08c186096778d2c6df8173915ef1bbe39437d6073e4409524fcbf5045ee260ec0d603a44976af15955995f75a773229bdd7889a5aa0184f292bd6b2ffe2bb86407a066477364b553440ac6cf9f7fe4636b48ca50e89d0d8891ef754134d7624c0db30d2a500c99277d90089542cc5058edc224f06b87af48853766926c03ef2206bf654cf9c3e0f6c74c42fd047c1c025a2709524087259ee25306bb861316cd08d0ca9a8c80ceadae6fb8d257b146f909d9f0691612ac6f0020b6c30cfa8b04073acb18a42c3f2ee148d7b2c5cb36f6908cb393f92e28fa5ed7a188190e33a107 -generate_ring_signature c5629b2c40a6c6c737f5dce8411acc9c276e6f0a56e707f8e57d60a7071557d2 743c872c39ccccc663ca95a73a624559e470c89275f9451e99b943a12c917508 4 7675eb1b2c42c881247435df509b540e8af4b715b863f696cf8f1d7def9492bc 2225eb2d6559955c01988be31a3dcedf4cfd6eab26c1b894f0c89b6625bc207e 287edf6cc3280b1a0e57115d79b5b762b3dd404ed1749aee4cdd0f3850bec996 601df0bfe882a553240b1bec04f63aa6592171d4f1da9f9bfd6509f1f76b463e fa9e98f42c3d58380216f5c6aa0ddeadf5a8f7f7e94b0f5e8d68215838d3bf02 1 83aacd68aa70217780e0cdfb64463cb38de519836613b8f6d6996402c45930041cdebe5e9af616c368e9f10a036c8ddaf3b6fc9d3fed325b52a59fdd5b83f80b4f3db3eea2d13dad10f8b35ba0ec1d299ec849c5247ba5a56778caeda7bfbb07efdd9310d839aa2d42f372ebbb9295023e16e8e347374f7d254938095d3e260e04fa15b33e5b64536294982e0e20b8d36a06605bd040de744171af0f020e2f0815f9e6c52c2345c8966b93324d503e40466335b79beb83d862b30e4e3e15370f29709581eb06f19d8def04d6b3c123a84a5cccd9246d683f157bea5f25f7e00e9b4465540565c021401ca6346c7452c106f4cb5101a0c8d92889bcf6ea18fa00 -generate_ring_signature 1a4197dee423f190acd42720cc120eacd6fdb3bf10b79234630b8858b6ca9767 b4267203b4ae75d442d1ff8149369c96273da7aa9eb82e40b905e1dd1637e96c 2 8dceed51a14035531d0438a6e2c16815792a3e4d76f0f7b34b5491e4da661fdd ae627eb1310b295996cba5c7958b1d0f0fe5bda5ebe6bfb1b4b75e8f82a46b10 0db7b3861e845b76870c76b143d4f559cf6449fdba4bc46075817caed034420e 1 d5a9eaa390fe15432dad58e0257a97c766446b1dcad9e224f70ef82b42dea309fc8c558fc5ee33829a3e671d023f144ce98220c7df65d490cfdb9152fb85af018292e9a01a1f5de0a47dc01346cb7eeefe372ff34a2cf4fd02db30e926f57b00257cdd363c629805034600e5c2e377c159230855b1b4a17d1991f80771d6f707 -generate_ring_signature aac5d207c0aa7557360adc8f06738e1881fe94b73f57368d845f5682f8096f4e 552caa3ef09555e0a216cf8a78b2e18271373231c4758eda7a270b2ddd71b92b 53 6fb3972559f40e71e36a3f1106a7866ee3ac12c0782692e78c10bca229640457 e883af1eeabbbb707cfe9f543956f5bacf9bbc169183279e901b91a1d2481e45 f1ffd5bf8f58e9e1474d1305a55939efef176dd58763423eb3dffa481e103c71 18e614da426c877dc72f4229ac2b4811fa69f56feeb194b73b1df699b14e79f7 a1ec96815246af7cd69ea904d218f724d15dbc0eb271235a4ff1be126925d4fa 344278387d740c1965901597ba56b536d71aa9354b209819bb4a0feeab3deca4 9ae49f5ae55a66e5b3a4b78e1c05756c13c7f7955805e984e8955bc79a7c8640 1c0fbea44d7ffe1a9f1145a760f6f42f7470e8e4037ba9cf4da94228b91d5380 57eb35ad73b6a99178453a88a91be2ce87e886f38b50167b7d121906883bb4d7 2a7b54e7aaad50e8c817096733116f69a22a72aeee7d23b9ea99a8a381015bf3 bedf676e37a4e4dd53b92a8a469184ddac922854327d98a02e5fc648232bac01 e46ca855f80c8e707cffbda4f0cb6ddc8875548aa8d30e1699facb2b1912ef43 89d6e8228d7a16faa1b37309835249ee56870557877394a039fac2d2dfaa27ef 2315f8280152ce6b1e5634e2419b22dd94aea973193b61d9296dd8bfd93b9ab2 12cc102744cfb58b2c388e52fa9c581c2f4ac84e34073a2a96376c6030880a62 f6974ceea92b921fd60f6cb02e275bfa7f500eaa682c915aec114068d6db88f5 138b0b7687520bc45d8bc3e6d9bfa314dcd1d8ad51c48c449afaaf7e7f056d71 e3cf7715e05664a5cd498f79055b41a5bc60b4b8827fc1fca083ee55822eebd5 4bfb5cd9dbfc3a1c41e59f9e1c00237a46819643fb967b5b92a80e7e386430c5 04e91cdeebb6eee9643337c58c719e44d401eec9b044969798f92fc2208d6ea4 f4be010794473e1db3049ecd4d84d05627dd33be6858ada87513d89bebd93778 b422e821b07ec1531698e2b89d50997475f78f8c59ddcf7452fa7094f8994412 8ff811aaa240794bd5e8cf5d21ead05fd755678656e8f0e7ae030a896ad0e3a1 b2b31ee946f51c58dc3d1e831acdacb308da4c894ada26d92cf885b466da12b5 2e333a1e3ee3b906b058bdb67db9884f2286d53bdc14c5143054b1e6348ecf63 cdbdc45b81cfcaa2bdde6d4319b0234ca2b8c464e6aac3ada947a181463a27c4 846eff34251f5c0076e4e2c854983c4044b6fdb836b1d6958084404c842541d0 31b2b6d776b38f559c1e8f6fbd7701a1f9cf067bedc98b91d5992579a6fb20a6 753c3a97d7a7ac59c3e32b3245b4c1e6a8c65fd79e2645dfec9e08196bf5c5c1 facda9cbfff0b7f8bdf25dd6af2534f64f3edf18109def802733de31abe06579 288da7b095382a572bf2b269f3d2f0dd91468d458a2c50be1139dbc014572af1 7edee65275e7cb061af3b8538a02dd1cb54c3a0049d722b3fc295af17c95814a 90f1b088ff7cef4436e5cad92502d21075b84748c2b4758dd0c1fdf0396c45a9 e1e9df368aacda8282da3cb81ea1758599413bff17aa9b3ed4d4c58a26c27857 7d59b675fcd945c0cafe8c2ba2623064e066fcca4127b04e1750baea465528f0 74e8a9e84b57bb4b07e46a3ed620a85ff609dfaee364bcb6c1dbb28de7f1c812 14fd789d3530800344d64a8b0173693bc41a2a909b18cfa88a5ca700acdc726a a6b766d16ee81a8570f6e7e3fefa39954260442b42c4f51a3b83ab6100292baf 6c8a23d96bd60ceb6b63e8353c2fc37efdd85b4af8ef9d6bbb6cbc56b78f3ce6 2fa3b181f1d202dd58d0b064348bdf31c1dad990dbbc8e059a1b414cd126e918 d2621e0e30d4c067701617544e8c86a0d4e2bcee498a419103b500868d9606ae e654d8b768ecbf0b688d3e513858f9c9515de599c70e4403236436768d1a1660 6e05f7f1c282324b171d197a03ab799a0bfdc371ec291a5dc8ab1407bc0d7e71 793bfc7db631e1edbd61fbec38831f9b5e324d2342ba6fb39e1f066e2d8a812a d869a67a0a327f783d72c395cc8b3319fc55edf427f2233b40200a7a76b3e4f1 823c7157e173f079713580b594edb97a0cc24feaa2356b5c493d927b25e576f9 1f52f97a0f224dae75244213223daead4262a21324f336affcb1186301dd851b dc4d8714ba6fb00db603e63b71095e0c0f48375647d8328bd1f1a98ddbd758b1 52b458e8782e3afb49cf0b4142fdb82de0b9a9b02bf66e396291581a96ac660e cc7a1833b75ca30eb566ec98a16e444022cd0537e9eeca574e5279c72cd402ba 492dc7df7860ada5e7fd7c076a7ac5515934d345ce74fc7f4461b19ee0c95dd1 a393560e00ef2187f5baf6338066076d72d170d8f3f76d53058804ff7ff76be0 77a6d6591d159cc018704b75d4ed14a0040fb8ab7924a6504e31263404ad7c20 d68bc46912d5f41a65b74c8cf7b0f387363e2d02b1cac744cd4bbf48c072e006 13 1668a872c614ab34cf519a3a44e3945f5e693f83a0308417e3c35522a2f5290711c748c3d9236a119f322b8f70bab552d3725ee62ac7763ad19b1d111dd8610cb18a28ad3aa5086e98fd9c8417ae8000f5c30cf6ac2d1c2578cdc8f9363a760d63dec8b0e97e5a8e65405d1bbf17c11cf8dd86ffafef84511d61468c7d1d340527ed234c4f98f170d045aa30463d9425cf76b602d8480d27c394a5a3fc6ef902eabfef77815e10843d3e5fcdb5b4c68c9f5ffdc113cfd0fc47e7a80fbf91d90550d696cc326233f97a8e460f75dc229c0e962ea75b4183c75527d8d46ae6fb004cc12bb4cfcc6752c7ca98a006be5d5a440fa4451f3adae49de7e32cf495f9001ff1c785b3823f3689116cfeb584c3ac1ec8395dfe95aa695040411244e58801af3e7b94e372a2cd01edc5646267f7721a41834c7e67440819b5e9413f43010a5b07229c103aa6e71b18dcad9c92cd1793c72a9cf2f3217e53374cf48b7d820d511d417e577caac31677c3160a4f8001d30a28ff0c8fb9a92adfe3290409c70787bb1fd985dc5596801a864f2b6da927d4bc47bc6fe74852825b2fb3f274e60c65d59eb1981502682ed9e3f6b66578a32ab8900e560aebb1bf9e5d2957a22a0f8913f24f65fb90264f400302731b2eb959ec0e5530fc5a2eba157bc268516e0af351cca919bd51fb5327dffd52acf8e9e46711eb6fd0852b9bc6c5cb3350c50de61d0c0d3e0507cca71e0c9adf0fd456b0646254e42c8143affcd4d630cf3b0f9611dce910d92189d4e0535bfeae31f2c2c41d376552eb6b1867cc701df9d10afb27eb66905421fffa2bdf2fea125ac0f132128a6856dacd2b450140b2f4a10b619ac214a953b719dc182035e2f2763b6caa4d0c85f924325c25258ceb936a09e58b7f8401cfc6b1b4359f4a01ebf03f683609cfef9e93a547ef3c76a56a240bb5b41b235b44d863695179091aad432fbab349e758e1456db4b195fa95deb20c3c6ba094317e9828c5d229b1f878899bb37238a35034902677efa451280f7709f8e08099470dbb55db6a56db92d0cd6a110465017d3d27c3d79f2617b0b5b60731682ad7801a6c3bca9c4942abff0242eb88df56e904bb820c6825158154900d4a6d2161c999870d541e59b5f21016b3c451efeb418c152aa3eb0edbd8205e0dcff0e8d59b7e3ed9ecc06211849e0cbf78130bb54a0fc274542137719d738605b674ff39e13f35c4bd855fc02585fe64834644136fd7627c9a5674afdcdb6b056c4ddd69be693b2fa5a70363325953799feb1a9cb94e03e2a0a506f4c0ce5a059aa16b454ab7bf602bf46d34b69ca3fcb1fc0ac9486a3914374120189b183407b99274011778613c4140d08096f03d8b8e161562f98e2ecbe36a1acca78f240703e7390ffbd248fb7cecdfa77cf4328e17412f6351342a3dce3b4814affe7307bdf318d457f330e83f3e7c4b3170cee1a14d9568405d71aa491fa763efa9570946bfbcebf5f5cf641d35124e05f2e61ef020cf59bc5786476561b409bb6dca0d97e051c0fe964e2734b6b4ba9cb92a5b78b186d4e17fe15c07b3e3ddfe4c5b026dd745862425cc1eecaa313a5bb29cf3e3733fde098dda9d18adde0eecd4b30373c3b908c685d7a56420fdd6fda2801be0b92d1a66139002ccd5ce7e63c7b80b745787494d576c732196e4a1473423a75465c8f85a1519711f87b796700be805e962167b4684336656e266d39c115ca2a7a0b768eaad2f1ed4598622a53f230d8b4e5ea984d85493b71223b52d01c9b0525fe69f92f38fbc1f3d6414b3066c079995ea42670a44c2ba4ec7a8ef8dd8a86053aad07fc94614b8656d347a49490bcfccc471878c894f758dbe4620a523ebdeb45d5a0d5ee4a6bd9d1c197197cb0a48d85bea6093cb5c7bc0c42b39342fce57e676638c52f64fd37016bf0e6e590f871d04072d18d8cec1f4e05e8018e7be7f4da767cd1bab7120d002ea6ac98c0fbf0fac99b40fc525d81e943f06faaf1fec84d13da278c18bd43397490c076d050153778e2cb166009ec9cc1ebf954dd930c00815e87f4cee7f969dfcb1d94a0f7b378b94e35ca7c7a31ef10d4b5aa83192ab6ad240edefcb18e13a5c94bc7e006d8a66bfc1129d90b0378ff62b564ea62d26d92c1f14775e44e4f453c4d398065af33ce4b4c0a00b4b64665f91a7d7d84e361c284bb9cd274e85a306b9cde304c0c0393d8da71d7abbf2fde949934468a1425f19b99adabfebe1287d6ff9dc011b6824fce6974b2fe60cc84499328134d386508c92644e63b51405aced3ae20871f7aff4a88951f947517b69e1f0f465f78e8bce9379d90b90a3e2cad4bcbe0eaf67b513a582dacb284ef738384f41246d5938d75d4ee9a39719121a1e56720a0df68a0be66ac9c36e9837f0675ad1030727ca886fb510409ab1ce2e6e0ac208ea0de4d44eea670280248aafd93224a89926170760211f38c13edbf1e41b3a044b7f59d32468dd82865819245f9682df76bc82c44ebb8f451d23183f23e281033bd7f336311f658b9f27fa898249640cca89ad18aaa2eca5584dad9f4ba25005e1a995bb84d74ead317570faa7959b89cf0f130d96b34564d74bd3814f33c50061c30aa0a4d723189b726e89b7eb76aae0f069e4f0bdc9d6d0220a614f6fa100677f62769d2d2f5d9049d333559637a920e92f22e1e64c2b0491c7c3257fca05955a8ff46f4266bc634e2eb74a5f56078e85065fed455eb9a0a6624456a3d70dbb37d3238fef783782c547a2b5b8b91b2039cf6dc21b2d89a1a66417482d3a0f64d32411c2d58c9556a5aeb54af513b88bf26f0b857f17c5c21443a8641cd401d9622ecfd21180593228c9305219d6ce91bed1844b1c6775ca8114f4b960f500a4b54b2902ca36407ffea886a99f8940ea3dc9cfe5e24f451cb19585f6e68f02df59cc218cbea3e0ea45cc72e574d4f9cd113a429f44264f794fafb88da9560e2c9f439ca1fd76da39be85f2f6b953c9c92821ca5619084565cb920d23265903539b5e8abf713a316e0e01ee758a19bb4f8882c9488f8f088bb7cd6f3b6a320b8cc38ba2ddd50598245b7cde53815e9e31809513273b1436b47c2115d5e7260a5e072e5b5d35f3587cc3a763333e712ca50b5189a9714473e061037ea8746e0b94047c5f9d7c99b849a09a1ac46aa80cc56848f1767f3af49d13ae66af9b5100a46e93d15cd4afe575a7489891a49a182b2cdfdac82780ca3a8ca17d52c6f40731cb42e8b48328dd749e2ce5e4ffaa70db997b2ad141ef5b5dae346996a75c0730611859c709c494f09e397bf5ad42380f5f1507278920abca2e5e71357cc2086704e7e93cfff3c27eb4e33ce02efab7ba1c02b7ca2ea6132c032429b937b309b0b0f7bd409dd7f7170c3509cb5d2c3dd42481652c071e44a177b64965ae980c8273f599d619cbee3e91e8deafc7aedd2707783b44ecf39ef3acdcca0c1b00049d88e22ac3d56a07072052e3de82415d004fafafcc2328d69635847e9e35e400f86267bc4553352c6a21e2fae5e4ac47a1a19cea9992f072961321983d63330038abafab2f704fed4a09c8585c6eda454ef38b0ebbc1adfb6dd6c026200b7c04951c45ab5c63e8e355f1eb52d14d7281c211e5afbaa5a1c42a70ce602c8aeb0568f599d03b038f5679fc3ef0871faf4d5ea9bc33a3774cda9c025c0ae300b30319b4b046d467fc820bd77f9a6dd31ac7398c2f7fe769d7808671a997dbaf650c961b152c4f5b0f65dabc534bfd7901b36b5aa1d086fbd374b8ddd4e8ed8fec0ac5e637d0f302f972e8116fdfbe4efc3d71f2cdc23d65c21b73661f83845c2901f0395f0cfd7c7bb0d056f246431470914081f2b7f53be8bb39d4f366ab2f040541c8f1108135f5e2109331ef71924debf1507e41d6ddf137bf2447217f5e1c064b575cc4a93766c87f87a21fef76840f3b2c150e82643d066314be98df9c330a42ffcc9a483da1a136e2dc906cc081692703da848de6736cc27b8270052e390f7c06c837d56eb78ac18c4c5ac0cc20e1e4562da82a161755f79bd6035d720407d54c467f8bb1a70e23b75c06215828cd1a5888db8e6bd5bd43b9f368015a4d098cd41a2c9d60dbbaae059df4a0044636de663c65fa06a0661d6449f5275d200fab38e6c65f7e1af3a15afa1205b453daf1ffa2f621cfceded82dc359be74c30b5fba3e1a0edc73a7a134682b2f73d3fe6a0392e239f66803bd167600abb5650763d782f12f16b3deacc5f31b37e7a60aafc4afbe258b8860591a2c889c42ea0e786c6373a4faca9dcf6b0299db5531ea668f1c1dd81c482d605d34ce7c3bd3048f6ba7847127b72171e258cbe3483171d5c0b511fb054e2d9f5bea46bcc7590f3e9c216e8c96ce3c6bf86b478259593e6b6129b1d95547a97c67d615e8b7920b7c6ba4b2c7a093787ed6ada578221ba058bfc244251449693b240244328c97034b0b07423844159bb77ed30cb5f76c9e7d36f1f8ec864ff03a8e541c81cd540588e4622ae14f99258cbbe0c788984be3f04f066fc5799ab49cae51774fd37a0b5c8eddd8585ddd5a30017c91fcd9b217321def9551533e602861b3b9433d9c0f9181a8023ba5af0cfc964162dad655ea443010473e1cb524854e46f150bbc30b79933768d9a8a49f26058cab67b5ff540338605a193a70ad523b800e7a27d908c52e7fa60d5c9e746354373173862a9de283a764db7d0e4c16d1a88f570fbf0dbd6940100f3c96868bd852be5db570ca36d5391bb32bac33ffb20bd54928230e -generate_ring_signature 1b9c52310cd90de6486e3c8b73ec646b0da895b54b118acff6ecfb69afa6e346 fee5ae2310a6b91390b1f30f2499faff560fb74ebe4b32f965af0edbb140a740 1 8084c2112b5d153f5086f416d6d1c059843bdee8f391f547ba9460225a69cadf 56320a68733e538cca2d2bc41b01634fc3b9e2ae3f9f83635b2574a4245ae00e 0 493ad5e819821f0dac10a9c5de44a5579dcc7c5a6a416da10b7279df37a11b0f1dc2a41e8e986240a76abfde51a8c94d965de621dd9df16e224256665883e904 -generate_ring_signature 65e7321376ed6c6696528042a65a9a4f6516d65fcef80214808c0c3230a52087 fcd664a50e9adb47d9ae24dc83f707e5178d3235b84c17e9a6f586c0bbc52a47 1 42fb2300246f28cb82112974815f4c14cdca8750a20b25ef861621effd08c45c 8e82a603216e1835a583482e580e635a34b431012284d709815768785245f800 0 ab228495a2f462c42dacf3691305079b6141fce9530df961368e680de31f53022dc2fb8d8952c2467c890275bc487d1d7a8f78237f6808d817b7f3b126e8c101 -generate_ring_signature 5fc776eaeb6aa0303db0d4397d093d225c8cc0e00caa55d5e3110e9d7aba1aa7 5745637caf7435d578fb680de1416357dc6c6ef0ef7f00c0d98952cc3eca7d74 13 31b7451326d0a7a224f17225a19e946750d81bda5a2f56ef09fb60bb2172a44e 9665dbe2e581c02838c7406b1c2632ea5898f527c27aee64001f13fb69d4e46b 43522177f2705f00ce314e061859663485afe95dc1103d184dd8445b51f8d943 d087ba1e5c49e3d7f627e402554bf365e115eb049d1f7101bfcd02bbffc09d5a a76ea4f37eacc9214defe54f2d59017a3d410499c3a6c7784c538d480764e2ec 881632bf12f572675667d5b546c761b3448453c771872793058d7e74975d616e af5bd86056c8494bc987c9c38ca25b9479c98749dc1db4a352ddfa119c436afb bc6d378f748e912b350e8716c0965c91fd00798534a25148a9cc8308b0ef1922 bb0e87d6c20206a4237b34b1deeab57891c6750e4d152e28a6477400e4d5b3a8 3556aee9033cd19cac0d3aba95b99694deb7dec82a18509529836cb013f7e656 1b0e39b149d8425fb452857732ef05daab09881647d5e5e648f57650a5fcc5e6 c2a218592130b95abb79673da2204d97970894818e0cd4ed17569c973403aabb 3a3a3c9771727a8adb3029e1022d766357396ac444aa17f75ecd13b7dfc4f25a 20fd014c0ce804e8bc23ced4b22b168bc3c94b8f76b7b0f2366c91e4196e070e 7 f13f64d4aa8e207d2e4e36e0bc8b47c619d3cc1214ec53f4854ce26fef3c680ffb3434a75358b5c9920475283acc64a141cd7a3cdada076c3c753c9fa307d901a118c34238801886893a205fb2175b7845cedc638b8f80a4f7a4a619fa6ce20d94ca17cdc5ef8402a585937083ba55f1c971933f293eeec4be5e1f5d2e7303086da6dbe3834bc8750bb1472438133d40b68fe2cbbc7fb83a7d4d65ac4fc476029c78beda3ff8482417349390807c669ad878c79ceb45d71726aef09649516700bb19a45f8503b7fc501643ca8889a9679694a288bea16febae581f2b2353d30c25cbad97b0e3b33f679604e3a50b43cd60b367605464cf53d79e3c2b24f17206d298e214c8bfd42b86b2f4a772c517d9363851c45c8e091e325e9c1d61f53a0dc64842ed4c9ee025d1caab83c3868946ea3449193fab6a766e0086b8920f880782a3bdd46a7087d95ca1d1856c9d4f437d3638ab6ca6de7d2b1c7e0bf631700b24f40f78624cee8559166b65ebdd8a69c0da92c82b0fffcbb776acc052fc900258f8330d168224a7a96770faf0e2a987a90c251d4e76d5bd11e11833e908f308d4d4f595af5b9a4f678c72e2b9deff2180f96e36abcc63a57a35e446c5623007fd1256aade7c6edba27693774e1bdb601ee4f97b94069c09454bd63868bca10f7639d4c1ef711541a0b5330e11c1b37e8997af2aff9405b30138dca26d9f6f02064b55305d6a0d85cbe95d8921bfd208a1b6580a34a6286566f292f2d2f88e050349dda72250da36bb35fe0d2514b347cb522d817c7d76e43581bb3942165300dee52e6fd22237605beac81126ff4cc4ac1cc3023cffb5dfbd88a46e65130b0b93284a5bb0ea6883c336f28b0e2595a7a8f97a74404df21e2d9a6ad41689a8054570ee404e403cf8952f3e5c78d2b311743fc28c690db778d4c77742045d1108b33c3460b6eafd30389b360ea934a5e47396747c583bb962a730158441fa650176273d2678872f9d628f2bcf2fa4e55348c347f6d5cd5add5d16da2dcfbbad0a9969da01f59edcc8d997e9baef87fac85cb845d627a446494316f698c5156b0bc526d485ede63f84581f04554a7d4d49cf27ffc42eafa570130178eb0cd40d0324129af54a9663840a790dd79b4dbdf8ab468dfe88a09522c504b88d01193a03 -generate_ring_signature 1b670fa7fab988e6f8fdc8fb107b3d075faac101675f315f48f069d363482811 311bd02641a786377befcf7f879163d21693f0eb1bcb162e016f16961adf8cc1 6 81b31e3da8c61e445c7f342caa50aa1f14e957cbbca3d541c909dc5040436732 bd9772f8dcb21506b557824bb497ef50079ea93d74b936ae6ee40fa1ebc5e261 7a31c4a1f85d63b66d38c7656d27611f99b933c8b97c1181376acb149dbc2446 763dab71cdc26c00204f5d24ca3dc0bbf122401d0bab86246774d04adea8d2ef 19d20452c993dc154c00d764ea28ca9c18f92df93067a40b90cd98cf6055f2a2 0765b3b2cb35ad43f4b64d7da4ea43c89d080c201bdb45d5b546f1ede6eafe4b 8ac480f5d3827bccb2bcf68e45cb0ca7cf3e9c876d80405a7c455b22bf68b70a 0 627c61808f2e8c64258b96241bd418678f29ad5e5bb0b54c998bfe0b6b6e3c0f853a06b285c9d6920c822865727d853f19f814d3364d16b37ee09f551cd2b60aa74dc88ad52de891fd4cfcec22815e175e9bf5718225e8d4a4e14d3effceb40dc40bf784b80e7ce3acdecff718860d31c099bb2d73cb5b10360558e32ae05a0cc98f34e4401846088db15ff27c4d615463bce242ab4cf24b42676b53d00141028a1f65e7ffeee54af647b8826ba60954d85dbab97e59d6087663a14c66fb7f0069cda230bcef707cca774c9bd6df0a0346b9d1eef1900c93118aabee9d2f740924339358b4d6e6f861c969b2ab455536d1b70b65f1ec9f16d960d106c1af4f0551e1e45a607472113b6b88e381156fdce641fc66d66539561c0ee6bcb539d40ebec532499c6a5c28966f69c43d6c25e0a208feffad242ddc800b8b9c58e1f80482b48ba52f661e0c28383b5daf6999fd1c6c1bab96d42b4da848b37d2f4bcc00bc788fa7863407b8b5aff00c1c50ce435e058496e0c353b264dc39ebe9a15b00 -generate_ring_signature 89102300bdccd553ce352ef36bd8cfbdf13f099c02bd18596e3d42e6239bd3d2 66b67ac092566c2a368b9a8d9ca4c4cb6a98f299e5f410c662017950512d6031 116 aacf971f4cb8083e4592930c84c2f7e1e814359c56cf8595064261e3a57062d0 4286968d242a26dfb7144780c2399aa1b000e5c64a7fa136663d9e9129974657 914d0875d0b0ebb1a309ba776dfe0a0e0c3ccb37d57da02a0adff77911fa6cb1 25960a259e5be8f63b901767d00eaff9e3b5b920f6080b957913c065036357b9 f42f1612df591adbbd3075dd4d7e13f632262a2aa4692fb66a9b23f929520ecb 2cc95b8fccad32778dc53e534511749bb98138621eba4b49df2ee579c12970f8 b613d3379b8bc47e960b43003a77dee82913090ef169ec2c24bc1e2e849c6ac8 a2fdff8411483e8012060880b6b2ec460ab8c4092dc88b48bd2111593221a425 3991843e89714483490b27ae31f275df2dbe7e29b0adefd7cd2a985edc5e69e1 b04e1160aef718f8095f6d74b592429a04998db7e3235af0805e2393ab257f47 f56c8839ad45f551557e2f0207ef083f0c5ab8afd19a093106f079304bf1fd8c babf3b67c8a305bb3fb26c0a0cbdbf11bb96df24e36903e5d7931d8acd8a4def e08078fa1b5592ea810f70aa9ec2b5af155d158cfb72a4339b06953d203a98f6 24de47d9b5fb0f83502c076360a5f84ff10fae7c178dcb6899f0e54d04c6f744 bf656a168108aac05e7489c23b7d3aba492ddad0a7305b7a235cda9b5f28d62c 20df1335f52c54cd9a273021327eb3cde3927a2a1c589c0b8fd2bf5305542255 6932a7468388e9361a00b61444b2fb0eaf68d975c554ffe92d301fa54277a9e3 c6878450d4032a0a632133777ba8904cbb2e6034d05d5ccfe183d9189403d913 27780f528549913bcb7d6bcb96e14c6cfacdd4a229135dc06d7c5102219f0110 92a1e11e5d0a1e83ef1aa41bd739c136fe4d3b2585c0d8ad15061d93de77d704 7ca5bca6af948f20929a81e95d75faedc991ba2faccdc3f2d942265d0e60beec 7d0299200ec4b03843d3c9c78d33d9cb871902c2da6e871f5328e1330038991c 95250393ccfb12b976d783e295fe5a0986370b05c48e564c2aa5d5c3e3d49a05 81ca61171b3f4f312a2460fe2f3a9a3d70a4c648a1549ff47ac4f621ec00e8d8 8eb43535fe2ed47605beb83118cde781c3699ec00473a56ed1ebb72bf177b356 03e96f6ec4eea800c6f3ef8b2c43f31160570d383285ecb1738a481cd3d5c335 209433cb2ab66891b1f9dd9fb74a75dcdac2639611f72890bc4c2a90ee0ce990 1c64633169c011513bc0a3c23dbab9ebde0d84ec021815b5efd749122a316d39 aeb62e7eeca2e3d46381c5411a47372bd9ed18db465d99a055a3b47c8be3aa1b 8253bd9c2ed9610658e5e339f2531f19fd147d0782ef9f60917e9d06babb7e68 2728a4782111a52f676bee5c3baa8bfb5c346b560510f38921cad69f9de907ba 12d57f3b4d36edf9656e67cff6dbe2d6bae85ba9a4365d04c066cb9b85eb4c11 e458bfe87a0561429dab19d989c37b09726656c8a399d609559db03680c946d8 e273d0effd007e930b1e9e130b4f87497188c4ed48fedd3bc34d169f83735576 31b09e291aa05bcfd743b3da58eaa02c772b817aff414d469a1f668f41ca908a 2309b29e52ccaec650074476470410a53fe1091621881ed61e30240b7d8e5ad6 f26e0a3ae0c0b5d5c53b4fde3a017c0dfb1cc1e67c7e9201c484256c02fbf584 b2369e479b65aa0e85c6d61e312733724eb93cb2c5b34b088adfca7f61c939c2 bb0e268150f215a3fd664363b2ffda9c7f8cea4c47c1efc43a9118f09bb66cbb 71b08cb319616d98b8ecb176a8d109ca5adfc90e7d88838cbf6a92de3e8c7ecf b2e5781e43a4b2c32d0acd5c373cab979b290928728e9ba476791c4dbdd9be32 fa305e51d4f7c53dda4689c34856a691ae3d6a9d01ee043f2106b4bc3787dda4 fe970cb89108b4e704e492c8db64cacaf564956bb1c47610ee25245a842fb210 336aec71dbefc4e4e44fb1e19239080446d9299b0149e1fa171c48d601a41c8e 554b235718cac2e9355720d4acc8838de199b59ace20cd1ffd575f0f4631841d d3ff0d68b3ff9683e5bfecdb8e8377de4ec37ecb155cf39c4e63dcf94b1ee979 f2521d0a0e9836e48760f0dd9910f229175740e2c81ecdd62e3859a0f4e0c7ff 66b07816d226538b578bb1df23e408d754a8a07f3ca5b6374ec386c5134d2697 ca59cba4793221d8430c41eb4ef32de270d0c89eca0b858b420a57696eb30be5 c3c213d1c7effc9e43a51d247f0fda635055491dc26a23201ea60758a37feac7 cb0f2314b2ad60b4230957199a9de58698da7811f47847ca973102a66f0d9498 c928cf24971c0890606fdb0b56f17b9409595764e7e398a2e729ee7838b0de64 b189e86e14c4ca5ae8b4cb715feaac84b921f3bed879deac20c9b27799176d88 65e86d5133b1d43edb8213bd3bfa7babc6e23628e52e36cdec478d39759cd6a7 3407636c7c04d71490e9edb5839531aa4724402b3c663ba22857af6daf6c9353 3445879109faedda39c091848b3b49cdbf61ca6e95ffdde56bcfa28da6d9d27d de4c9c94c1a01d5d177b47355118f70a68e7cea90d162a4ab67d7f8b8be582c4 cd847f96764801152575a86b30e6ed3a75acedbfdb16a5576d3a094342f599bf 6890ecec3024edd3be7e67817ce51b8de27b7a4feb288d8c4aaf6c91e5e909ad 66e74b36d7939f347f0acd6699214d4a78a016d9c2ca512a6f6112fc4be6bf91 a582a1c2948b238fc1de90feb779b9d11e57b06410ef58e74f565b6e3dec4fd2 1d58c0007cbd13072dc8aca24abb0b6cccf238b47c897a1010a300cae267c021 a309f20016a70430700d55c29521f51dcbb9491ec7a7be3666a0183f7b5cc032 23c15ac582b1d2443eb5b4e1aab30a44f108491057a87064a1784eb64023e96b 49796b6bfbbcc45aee369a4cd875e73b43fc6e108ee97d813dbb82f4227cd821 008de8724f40b50fb90cc68e804d395de075bf3f40888741c98fcf0df2cff0a5 c974385a5536e2e7018885cf4efe028760084ba063279d848293ebf7cfb5cd90 827792ebb3a8a1283d94fb063877561a4e92c709e9541b7c87817b28ed185696 2fe3aa80686718b9739256c1a433a37109c903f0be3abb74819cabf35e0c1bb7 e93816be20d1dcdf6ee39748a1f08e06f8f39490991d3058abbda941329c3be8 ee1b391beb2319d8f67e7376e68c069c0011ccf712f5351a82c13552cc890047 eda56aa82c4e114c8aca9636db3b356e7ad9c76c63acfd1ee135d3a2ec3393ac 0bf5483e4bdcf85336f82b77f70b1623d201ff601877bbec4b7b4963268ab62e cd4567b648634eb4ac39958e55ef352570122929639894f31abc61adc2609fdd 0ad0e927718cf2b4eca2e50e0d27d99c75cb7cfd33fd63b7fa7ae38387d92e12 6735f7d46c51519a4a2d475899fcae2f47e08c91a08d28faf81ae21611548f64 210e26da394508be17607c6d23d08e6d93ad5009f0677228c754d212a8e084ec 70bf02ec4ffebbce2020b5db776c6eb463b24989f1f3f8aa2e1bca91f2a4e315 498b3093b6563f383502e489fde1cc1201acdfd6fe776bfd68f674c4e4a2e8a6 8e3a7e23a5cb28de1bd8e28ba5d87a1f1f234fa405dfb5f9206dcc1df31378e7 9dc0a522c312cc2a6c95d954ded0023fa95e049848cbd06cfa85798b91d9b96a e84f3f5612a23c4399389dfd2ed6972e6744b860a8f110ea83ebd77a3a7f632a 670b5b7c96794bf0300575edadeb40dc40f30c52ab560f55a8f7219c2c7be945 b97fdaf538c771ef870edac92c52b266eddf2f41a662c3b812483423f1172f32 34fcb11256ef3dc85e4100bdcecd84e89b64d9c39da22b7f7383ff1b172f0327 0d735c44c9c7c5502d4b4b280fba770b284e2eae7f9446d0964bb6ff7b4e2f92 08f03cdfdeb880a685504b775045779c86135aa6dcfc8e06899bda0391141946 865c08b9ca9748b72018189051fb1282dcd1662aef708c62593dce09981a45fe 647f241c0da6d5e897f96f709e4c5e0ee7db1a90026e297b2b98739662599656 b424e2d17bad69bee7e51c8c8c017a3689b4cdf52cd016af5e65e7084b3c380c 671455db63d8773c5e95e71d37c3bf7d3e6316a39cb2fe7d234899011458c83e 28119b556f4048b9b31e7946073be2b62f74b74a56cbd31fee1cfbc2f5f512a5 a8e89c237d06199bcd94c030f5c58ad1a3caa2ff5bda6d45de213262d038cd03 4d6ae40c4e28276d908f10fac7db8fb0954d0b09f3d516cb61bd9bf9b5df9fe1 7fccc1bfba50e840563c220d2520c9f77afef38d9dfab6e01892e6345ea100e2 28e363ec69911e6cd79ef7ec1c6899a531ca6aa1b00d00f68d71cfc038043847 21dc113dbc94fad84468f32b6b654976e9e2b7ba9caa011fc46394cc0efffab4 513c7e81377e13bd283918a5a44a5ea8bb253f54d554fa760e04523c27978471 f121a815f969fc0597b1b5c518cd49ba4589394fc511633cfeaf0554a33e5bf6 19b4883add93f293a640f138d0599d8abd50027f605f68e78e398568ea444647 ff453b1975ed16f8c0e1411dfde72046542032a9e753b4cf9bdce4cff141b734 4d39889a38efe6d22a0d3569d79b2d5d27a2caa9d40f8d4232db0ceae78c4980 471dd89be76b7673c0948e9dee567ba70acf98d02ef82b8ebcb73dba23a25aed 21a96e9e7fed5e8301c71774469297fa1d0e095ba317b916501070d18be35eff 1529c4c48b69e33c78314005df30b4e24f25341538b4e4784187f8492a95ca4c dd5756c71342bc91146a6d89dd9a1755b2e67297dd08ee2ad47da6f88712cfde e223d3cf9f77cb85b9443da601d925305edea5d1f86b69db533edc032dec4132 9df21b3f335c553a66f4c6b1dd7ac870dc885de1b3323e86dffb116d3012a430 c545e90cde0ea37de654dc7f6cab3042b9c53ebb923580740bad667891f34556 cf75bf6c505a45d0bb8b966e4fd8fcdb60caf6998310f13ef23d48e9f8da5f2c daa6ca75877e1e7eb9c9a1aa990f850d3748ed84dc65be4ef4509ac2dc15a50a 93d1f3b4a03ece48c32a6e8f2ca589953ea4eed5c53798a388e51f9a6a5b9e57 0e41584b69979e002262d1cca78e9ee773e22a4458ebaa53de795a9885051fae 4aba7f5eb551ee6c25d9290c10ec73cc2d1fbb0fb3646f2c3d2959e620d6543f 6e0fea29e401d70f40f8be4d865f7db6add2fab1ab82090f3b85e53bdf9a6cb9 743899b36c46807eae625a8fcb717ae77e7119dd436a6cfc11a7876a1201309e f8fc487e376e13bba04de3825648ddfe435e78b4bfebb43e5b0d40a33859a500 6 0b8026574ccbba296193f1ca37ad91ab5ed182d556aa674ba2449f2627bcda0c6dc6f1dabc8796ad1690235c2d3784414be879838aa68c7f3deb69d6c00f000891d847f551e4b81c697b6fbec00953fcef9062cfe894b070064a5d7deff78d08445b922062643e71ad988f4b34dadf5972345bc8b36697021b9b8868de765a06b6c8b5dd51ffeebae285546da26165e8c096cc90882c34f770552854e143d402c5d7f5c26285cecb7b3166b4dc5aca3462ac707a5229636339c26bdbdccbf40de5ef3fde8afe304d7a2aaa835b767f7cf0d669bcdd476bf3224355b622af3e0cc8759050ded35ed5076d552e4adf9348b56d2b027b5f2b27f127e99fcb77ec0b0a2c9f8621d8326d6b629c8480c748fa989dcb0ac5f448b7b69f8dc32628ca0ebb967d66aca42fd9662f9b35b541fa6e795a4459e8037c839f08f4acab9cae038c2b9c9cc878d358f95f10b179e1bbfb26d164ff665f4bd7f8de47f19ec45f03bd669aaa546df1756350eae70de45e4f66cdf3363bd4bb07e50be2b5223f92014f7e82cb599377a56a2dc6622be8e940df1458d4cb5cd08c839d34a86b86a90e4bab45b770e699968e44c32ca24ab4719e77221c1d5b186d816b4f8ce34dbd029e472426cca9e9a72f773dc248a9ac58433cfa7752a431cf1d795a1e661d4a04ad9404068c21d6cbfa11058fa46ed4682ab4700e0afb893d1973c4a13624cf02e128a4730d146a4f894d1441f3b9fcb0721695bda019ace0a24d53bc19d82e0ba579adb76bd7837ce7243a0b46160862a729e73806fcddb4543e8c06ba88150a7cdfae57aa221fd68313cd9209947318324f7b3e55a11cb9a26602168ffd0100256de511cdb926b31868e1c9f9221f2abb4c799b8c1e1bf9cf67338b9e8c690763eed483e67dc7b9921d1c89de3af49e2dde297c06cd3d5464b58ec9db90600ccb892367604a44f4bb8872f116df58ae643771b357866874937de0d7bc26810efad047ec17247fa1f94bd5d7c8538e126ce3b60a5e89ea434fe879fb07447a026a4ea6a569c0dee9f677473c89950ebd2324839deaf287be71f3fcb450912b0a5cf752193bc2e19ff9044732eb4c46a6f5c1a1d25a2a1c281bb8868732fa800e36443f3ec420b06d04ae628dffc8bd50d0887c5d79f4f84da5a5fe4385353f09e72a36d717ee34a23e5025c20f7ecae38b0092ec721e65838ba575164298ab041846a38162ba033526ad1f90e9a3c05d07c3d8dba8565122b3a99eca239fa30d9e9c618bba7bd6fd0098fcdbcd2e9f215eeca594b2d670b3fbde8081f146eb0a8a28f1750a980b595810f85c5f3f9654d167d71a703c20e8b2ef93c92ca9980a2316e37ddcecf447431b594f6dbce33c4b580f100b3450e08fc8e81a0bc6b403163584d050ac517fc2baffaa5c48d5b673f1b8574c745861f2774b04c5665d0cea4a3c6729236227d5ea8ecdf624579ff8abb604404ddc0f9a81c5aa3e0c3607025106ca3abc098c34a83945d020a0237fad8c73201f3dd751b282b4c3f62302ece2d7da870c5d88643a7eb4d9c9b8cc93d86c4774ce0c583ed98c71c8937903945294478a131f7b2fb66b5f6b3cf4a2c46fdf89e39219c493b4506987694400355d54afd091e0f6eece93deb42e5e513d569fc1f2a97722d9051e0374f9c80490096611769068f4e97b2416b7e1cabc9ec26e34f134c900539266afd1915d0408532b389b8eabc63af405bbf5971a3193b759aa2ec253d4a82de84ad487320271afe8dd2c60d07221f412f2be29a0779f7009a0bc6f62eb7a87bea43bdb3e0a1ebdae7ed155a0d36fe41374c8923d9fdf6b70dd823063b08dc1012d803ea10a49305de83002b6027b0870647bb15c084c944e403e8a1ea638b29ebdb0fdf50509eb7b4aa6fea61e0300085682add4f1e63b10047e0e66ebaa4e9d73a47b380c180c8c318dc111b57893078c35663532693591bbebfa1064ec9614051c6b62091dba74033baf6534c26201aa3ee53f008122de11dec0c7961957c775137b6801ae45151697be0942c015c17b0026c14be13b9284b57baa749f1b4ce250c3680e2027823eaa1bef2ecd308c43d6afe849bdf020ef0279956189a52a880871bd03a311585e4e9373a4d7d9d5b0bb056e24e2b18c473cfddc6dc8f3bf1147295f0302a999e2c615dc1aaa24e254f6bc36f04d58ef686ebd201b5dbd03df0655b20dcecdd14451a116deff2edf2c11f32e94068372c8cd1630c486089cdb2e18050e3cff40c25a3f70d9c53237a20c4507c65dfffda88e4c422b5235d25a0b2a050ad1dc55126173b506c8e7fc92a6a6c9ebb4d1b8d41ff825827d311d4715163a083e01a141aabe248cbec1ff118c93ff930e2b1fccd590d6134ad4b5f3020ab406ec8dc82f6f0763b40c04705f322639f6ae44dd3c44c3bf83f6fb777110880e00336bcfa9675938990fb060cb7d668f9c3ee5bba02ffa6a672beb6e42c441f3080e361b068a1aa4a9292ebd37aad580e181cdd511355d039190491a7ffb70870d0d128f09f91e837f4b712fc4844a5ec90935b550645b4fc17cc8a03ea2c39f0b956b81a7260317cf7e39b3bf61fbcb68e497fa045831e143b0aa80aceada8b0ea7f3c20f7489305598e24403ff1a1ddc5481bb6bd77e2c6fad8a0c59846afa04943b4e22d05bc79cd58c81816011f6945b34c1b1d56f22751e6fe9b22ab3570bbaa850caf74561fa5b7715fbbfd9ae7adede713cc5b2a864cd2b397430c52c0d0c6b4a9191aa9791e25f56cbf26c48e3aea68352e9950a6343ca396b1ebe8704f5892cf44957dc513c7004e819620869cd40bd1f3c1e544a87f91d71e06f2f05716b742fd086ed3e7f58d9b2c09001762a96e3b7e7daa9bfd7b7bcf4ee722f0302cd9d25af1aea9cf4247c7c749280d6ab934a9d1247e978d3d3269e22e16c069ebed3661f043a257242969700885965f99b34444aa31accaa22ca51b19f010446012d08b61841b1940a2ecf0f9ddf1605109e6fee9a77bf81c16184722c3e059c49020686d6d63537fbdeb4ccdcd52ee5c74ce635fe6e8314bedeac4899cc0b46696f07422e14ec73b0e9517bbcd9ab4d5c300bdfd5243bc51ac4b98148020fb77b95c55470d9eb6d98ffe9a785f34ccb0c0e669027fa3578ad3643e9e0590d2c4a0631ef7beabcce3bea977686302702d629422d0f2efa8901acc221ea0709660e50274992c65cec4b9e9e8083a135262741845fbf8879b7ecc59659d5c90a096fe4c7f6bc15c715501f970a309a6ae9b302bd4303457e5d3db366e6910200cf685719c94311c9bd9010c2fe29d4bc7dac6610f41dc65570feafbd1e602a0df8820262a6ab3bdb886b1270abd83ea27540538a791dbab3618f49f2248ce60966e6643b251b214cdb2c8769556dc9e87ffc74cb9ee70911692249b72b863a0fa8d80c39e6fe9fb98c526ab6dc71f6b076aa58758f78a3f1a8d34229ed99630325aa4e1fe57586132cf310fd250501a16a93d5fa4e96927989d65c42ac92b40849f5a5a5496806d3deb5c1764dc1a8e79006e5f96daba8756de10757c5fede006a5aca2408dd58f40a4347d0cec2e0c7cc073038d54eeb6566e77f0d969f3c0a58526f0fe78355f8e21fd37dbc9005c91a6040a9f231251da4ad375ef3467307b93863bdbf06a4e6536024492654206804132eec96fab2468a2674d8df5918005776c7ed12a9c2b9d3ba0da860fb35376a5b6c55e8b59bb26e26ed1f94edcd0486a8561e2fc910c4cb9a7c348a028b2d167b2acc54eb4d243db78c686bae720cbaf7990c189b4125039450f14403b318de0416e85b78e0f4aa2003efaf1bbe0818fe1cf1ef04059288e527be172f4f154e60fec10084f577775d03d8d0911a0dcf08cf595b04d52d3f82925f8e6808eb60781a3ebc1c877a8108798c6e4be40b76b3b743494bdbe1a28e5a42d256a91f7859b6ed43a3c4ff7722f191fc1c7b0ecfd0adee13dc3ea2fd79780159fb1c096154ef9ea3bb02aad18851d8f870a10d50530d5c1b50c1fcfc784350137eacc142220fa028419230e00ba4354d916204173fda0603a66f55c672c0155d049828ea04dfc387dfab5d5f9d331e1c4513091986d1a8a74fa3310b733c01ed012db2315a6dc68614d2135f1eeae13ff872027a6ba1a177de6d619f32bbfa41ac2e0f9c66fc5a565d717b40b4b0eae5649500a067a4d901b99011f862274de2c0fb6f8d3b450340920750a6b9f1eb5a29a70fc6d7512ab7c02147da9dd5512d4f4adddb5620ed8e356f34b5750aef2d309a02241ff73998ec9cdfa9709573b6f7b00f6252664770a90644aace5bc2e19472054a78e9f9e18d4a29d972db99875ad3630f8b8e9a947bf40da4ec1350a352d401f4d53782615dca11a635391692bffd0f4309411ad9b206a3c5c9adce5f57cc0698201351fb4ffc8230abccc674d3cd8dbbd959ccd8b77fb546634c028713b80af4d033fe66a787037fcf38e23b84c8f48b0d5f8a48c24b1992bb82f3c5cb1c0f0f1446f3ac899ad343c187ec29eef6328d6bd4a07c6636b5349faac50facd906f7ca340c935e677e08682f39fdc48da4d8cdbdab86ce696e3bb9458fd40d310b7e06f49e51e729ae2e705ce1b5cd7d0fdeebb8da7dae9ec721c77abf0fee2f05b051f9feb49496fdded0f87f2de1186773cb5fbf3f32f9de67aded3f2deab60469584cb1d1f696c5e1a994f19aaf5596d9cc7193f908a2d34391bee6f4711d02b093ec04e1a3b796798f1a65a656f38c43f851236eea699e610a87df289b42026e9eb4c5263d3693df9458ae32c85e0e778bf7dcad72cf194101dc2aac61540b8815ae39f5dce41cebfcf4f2ab4feaa55406c6db38d3ed6c2538c55f417c2f0d1fe2a0df06dd3351936e7ec94bbcfebe0476a4ebe090c7f34c3712f13eee0906b3918da84b9520b5c889c0924239afdafe9f49a39e8f40af461c8fdb6623ed0aee010f345fa58bd1442fcbb177cc23aeaa9a9c80aa311f92cd6754ceb3598409c071c7557df871a5bd8efd55a77a7fed0a2c2f0b4c4ead01769eac1825b8d40556f8609669c8d04cab252a288048beca6dbe72df33945f0b436d20740c3abb0548bbd93ba41cc3e5baf1fd825aed918eca542b21af05e284fa5d1940f5d95e01cb226242af359ed089f607ed380d46e947058228c818122851f880ab8e7171088bfe7206f84c6dc247981abeaa724ab4c34a21e9557ecf8ff6baeabe6991470b06365d278c4ac03fc5e9bc4a06f26acdc12294fc2bb7447d2d2bfc4ca058c707a26332713bf61117edfca06aa7110b9d036ff090c32556d671d0b4011d139801affcd2b3552ebb196f01210bc97c59b5783242a8b0bbbb046a05310e7bb2850e7f59eda6bb5216d9ed9187dc9536e51b8cc7a1b41c805e652eda91964631060622cb5b2e464bd5ada60d57952e787e2d535df78c812088d088b7f14c6df7df0ac69469c699541ae3863e80bbaa2ff686cd5d2ebafed1aa85c3fd1f5de51ae30d637a4c0f64840388b4b4df37b38f77bc22e9e37a8c03e027b748f0527e30af07a00b09c1cb6b59259f247db4e4c00524831d6d90f433cdbd3a37e7d6025ab200256c9411d1c1e1d688563a84f4fce67b5e11123f116dd78687baa72fff53100693d284374489d97bc23a32f52de697a219f945ef9d27d48c4c75275758e37e0aa8067054df6a037fb51329942667df79958c66512bfdce8ddf6be7b68c88be0ab509da2b26304cf0b9d3b50d02c2102266dbb90e1be618c9c61e9efc151099050b20d3818c5897615a9c99fe42de4c3002c91b3cdc456a825a0cc7df3ae6d503edefccaee3f2953ee2a4823c97dc1184f16f6780059dec788b502458795b4c04ad511550d60312a882177660adbe84ec7827c8313bfd67de62df338f391a13032ceb01b49d9a107c23e5a789eac36b77f900f66cf096093595ffabd43a6b9f0d68c2219740b0549fa2f1662b33f4999a542fee6aa7a3426c8bfdc862a61435013c298cab85f68773df3ca2d58c872c7d376db95faba7a910f1f7757f24618e046c299c43ce8c2977b96757063844cb76d2ad209badca2d2b701439704979ef078c02ffce66f8e49f6123b56cd83a9e645c882f5002fd268aa30ca99260258102efedc6e7529c0f3119bc75b1c4190b9cad55d4dbd4c2cbba314215d8762e6d005b1b5104e008331497c958512cd5a11a0e4209eca49b13862b25eeac38e403038acc74c8d9cd65ac2a5615ce141e156d32bb14620cc151a0aa2d798be6668901bfd8ea74df2a427e3d04560d3f5a82ed25773bd080f340cb7e34daa3ef631b0e24c1cdee1be4a9cec177f3b2d059d620c48729d53bcc7c26f7afdf64a3a0ca0c29949e2ed5c20585182ea370e5f2ba552c503b75211ae01aa44b3bc29fdf7c06213ab3844afdc91f09e598a5f08a2961758570c06f4e447d27307908016e51005c58bc9dc0affcceac613129029eca50059b527395aba3dbc678ace92de6b409c9f4cb5fe59d3db5aa8975a6bf44bd52a90f31bc8a6dd03e53e42c6957cee101551a54ac6e216bbf1a7b0e26186257975b7c727201eb1eca65a8e024f6aaa301f773b438c69b1bbf8b280ae10597a4c7657521d699c70d63019a0a708777fc0e55166dfe0bfb1261e96a433b6da50c7e31e2d698599ddff6da02c6576f4bfa06fa2d834d299057616c4a98871313607f46fc0a1f1e419250582a885e75aa110c70a69066771cd2374b5f5ee40f2cec562d603f77f0d7aba9324ea584cf40fd04292e5db9aebc3e124174a57ea393c2f5a3f152a6fd83531b267216bd225a1706480b6320a639aca669faea87a5b95a8349f47a362620db4da044b2bac38d530d45605992eeee058fa956a79a9a22423ccb959aa4e0542c5e27814b3b9072a500f88e4579aa80e453528f22157cfa4fc90d2399169a00db3c054096813e024a04a358cd176ae873af48447eba47c679e01c292d17d6a743c4c65dd58537bbe40c584a8841d1334cf4a011d713114904ecf79d29690fd474e02e02a04886a08f051ca5a5a1423d16d952c6896187c66f809ae4eef226c0096d352724d69f76ab01e694e178bb95c20fe9f4d32a0166c2d12c7036e4b0f418354b0484e41ede20075347c11f7f2e88f9a017beef6bbe803bc9b1ec967e4f29b13323532fab2e8b032318c6d362e1926ceb1d1bd102e02e9022e44f4e09bbe64f6c84f454a7bca00563236ddc08ca12c1185cddd8900aeb1615dda54ca2b361cc15e2f91ffdce1f0715f16ff14eeac60fef63ffeb0f7859963ed8a1f58f18414e932316cad38229060746a62be7047187e78841e9b534d58077d972d6253e8a4c95cffd63932ea30a391100bb7599e3a5763544db299b6d84a6201dbf19c67d8b3a1ce167f9f69b0229e1568749e08ffdeb71ec520675d24a8d935118a4ceae340b0a7ac8cc0fd90b07bd9420bf2f79baf2c835300e4ca929f3b1221e210b1b03aaded917edfba4073f5c55d23f560e23815f3c190de64b1fee1027da74d36e1a166f043f8f492f07ef3c93544a02cf1e6ac713a1a33002ed2a7d847cf61e8cf990a72d31a66fb20244bd91dbf2d8d0b4ed5daa02a68c166235eaf29ef8da8403a63483137afad90682cb208b05f6a3ea93dbf61887b770daf247b1b13622299193b20fd313985f0e7f15f3f9c8000b257589217a445df19e2fdcd71cd01fec01ad71d79cc34eb70dc955c996f1d1a1ef973a009d28c4ce69d7b00d4b39cf17e9820286c8ad992206f9b268a512a5b909ee087fbc25516a14196ee12e88d7b3119fc4cd3c713dd20289247912b66dead861ad7cd73bb24c29b6b841ce7f81d8d1d87f4fa42e4ac0087073290c46b78366fb297c4a6fc0c3122368e67a94614dd7ee079afe9a2f620961ce78f19c11003f734bf48df0eec2cba8190c98bb7f40a9eeade6d2037ebc0dd21b41ba2fe453862bef3be436a0fab704144d85ce0a9204e36363339baa4507230b6c76b4401ab7871b63f4ef73d568f874ed6c89e21cc62822098141e16f0fd8f136d4464f016ec7abfa58cbc4e604e3d425e3adf2a94ed6cd1392d56f2704b14c86023284c029c04f3d2cf0fa2c4b57980e4a0f56cc5ce2191dd3068cfc0e8d97eecedaf9497470064cc0ce125b9b1e1bacde5a9587fdd97a6bf54fd3230b5523a3b5d85b3393b584b0c7ba2dbd6bc39f799de6d4130a4c830ac98c0c15083db6baf4e2a7f2df5440003b4e42a4e254492387b3de04890bdb7e3ef428c401322bd14ff8d538377d1800fb39623441aa01b9eb22a8c649b20614d04b591c0b2bce9770ea16458865649dc9e0fb34c1ec8c2db7cfbde9de58d3257c8953d00d66ddee0faed1397a7365d3c5d8c26edf42da2e7a64000e4d2f6e17d38d4b3d0b2fa196680e30856f7ba26055cb8db94f1f959f0b0c0e6c03fa6768b1f630e404768b1a88ee8bcd1863a044710449321166c9b5655c217306ad619e873b153b0ccf61eefff7482121646c59ef2973dcc57fa17560588500609e6da786e3e2350e923c7945ae5e9fa99315bbb6c99d294b42ffe48dc3bfcbf5a0b82cf4c2ee2607534bddca825e05f452b1b6412bb05a98363240aece15a731815d6f0f58dbb50b13cd03e2bbc9d2a6a9163c897e5dfa0a9c2e5f9052a64947891598dfd76c050a04cc7e2b6a2433344c4d2f0fa0bb38e7bcccb0ddee095a79371a3482c6622900816fe80f7ceeb7eab85876196c4925f04a192fe59175281f70c2a98afebf230049e6058938c78fafce6fa11e77b5e095f4740a99ad4d61e270bcea34b2a3c60d5bf79ef4c99a97fd6cc9a6db88d23a0b0c6e075b983babb8e33a5cd1295314086042bebeaeeffafe09343825867243fff629fbfa5e43dd8c814d83b041394501f76517f7829ba6b27ade1da765539299cc3ec55aae8cadb9f388d11f5e46540b50c1253f2a74ec837ba6f0c889130a5fadee2c24aaac92b7dd7c96cf3d4764076757092486c32d401921756faf0ae54f671806f57baf20c7504ec27fc840090a345c46de1f0a213093e4feed0c2474e8d00751533eb38f21740f90a532cbab0938aeb2eab72983201e67fb8cfba1522a380c2f7e52c5ebf84d480312a305fb0267a32d20824dbce4d04c5bc81c962417ec834df5b5a2a20b9a64f312398ebe084c1fa73c8c4748a7bece777ba89e5289a266edb0f190c0eb204a2fc00638150eeb167782f024f5bd2a675be480742265b5ecb2f0c7cb89ccb5e5302b6110b801e998f336f53fb681e6024940431dfc8f0760be8c0dac0f4573e2d4aa80a0b50012b36b36a95edfdb7172b4c12586f2e90f0ef029ad46d351879758dac532200d011093124331d057ae84a3054399cdd872c39170944434b270730c09d6b2360680d668677be702c0c4b14117d7a19051a950f20b8c742adc3eb29c2fb4883e0544291dc87e1397ad049d446638b55af62efad0585257be515bfc9f1a290f5f0cc6f20ecc2908782197af37edf432effc87bbde671438723f7da2e1133a7b95015b645c4a02a4aba14c370b23cc006a2ab5132f83edd6c59c7a633631b0279e0464741eb9e7d97234e4d859ca4fa9e828c502af81365d5895a45955ad814ec8036121bb5395aec20006b840b4b45bc2037e9a5c7d319923cd64059cd21139d80dedeafdab448b13bbf0ce43a0c51be7072e5d62a91354f5995644b88492723505cf077984d1994785d6acc1854941849b926995617de6aa21ffe87b4c0e897802e1600678cf650c009cf9279077202b4aa01f3534194af2f2299b426205a1a0030390f0eccbed460d9ff6961c475206db0339323d6af2665c97c56f4574a8a905bf80a7b8c169457211ab0ea0fc31b71fecca1ebbc2db659a3549e84f519d2a005d33fbe158caf318e557f39228c8ab0efedd6a6dce9e347fcb90b0d213b1c807a990953495688d41396f238720d2f942873e42bb2ff280298481f0e4f3f8c80f97a6669d384ce3f333f3f71e0d591f107266cf46388eba3f4d8b8bbe9e6ca804dbf782bff51a998792191cf6048add724e3c620083401b09c59104e482f759012e81e47bbeb8d6b4001cc272ec43248f3a03f77ca61a9a813d4b446be5ac750cd9662c7e398b7862de1dc0e9571394bf5ee5a3cd905f18a58afdbe5555cdf401ae6ca5da84581e9bc99393b68db21a6dde189a8fde88d89cbdb8a78be85f290bbb652b01b3fd963eea02d3c6fc92e9778d585a927da38fcee52db599b74e86014ed68a16b58be7b05b4827d65edfa0d52926b3074a3bd033ecd4bb11a5a2640122470a79aba24bd5ac5ad7dd1363403aa6d08ca05e3049e791f633015b6e6907299eee090468dce011cc5831e50b854ac27dee76168c481a6d5f5f343257ec0823517da298103681ee0b76eb36fa9546e6fdbe53c1f30470e8dc8d782c10f20e1f98c739d022bcaa1f3e9d39447368747b058b18c1ec82dfef49fa46f5a3e804 -generate_ring_signature 39fef726944368533d166d84ca3f2ed35aca6b33e5a3ddcbde30f1a60465c61b ba1907948b591f4d5e7faf586b3f95d9d259ec089ba3ab71ef4b57beb3e5830e 4 cfc47ad6292db3248c65c78fd2db49eea2c2a6ff4c6f50771decac7631c4f866 4454dc103cf1ca4cfba718e2d34dd2489b08e0b350523dc9477dea5f16743e73 74d30aed08a71ab71277adfc83d8e0de28b2eba61edb0e94acce6309973b6d45 2aefe7ed1319282d5e1e01220850c933406384c6a931b0acdcf4957de3891eac fca4d6c4cc291b9db974d09df386a7742740068d0db8e96b1b4faede19f06e01 3 0601bb0d7875d6d59436c781c80b0f563f77445936ea7bfa99c9b202b6fc7e0b18594363d1e66674a09147cd3c0602923d38c6e59ae3015ce767ea7ff30f4c0adb30d9a00c10c1fcdacd8bdde252e42bb633e8cf1e802f37908ee2c6ae05f50a8bf771ea62e4ab6c691f65d66cbfc23cf18e7664f40e9a81b9cbb856cb33cf0f51926a1e0446b105f8387e8a80eee286b643c3ad48b2702164055d529ddb9504d4a44c6f357a21edf9e0b6c6d1c9a2f50aa700c0e9f448b1cb37d6be73263f09eb288235e120d907ffe49f0737c0f2b7dde85f9799374bc02ce177d3f824f00009af09dd5398e4ded6351f9b051cf675f3b51918009824188a58d112474a2a05 -generate_ring_signature 7f0c29493bb36b01a82a2f7077d547890e5bc7831ae6a35a2f31a0f902d4854a da08db64452bb864c36174d98a4e14781c78b7be3ff474071c0afc444fec84d6 1 bcf34b4ed58ed15b02861434750fb724d3101346d5e8303437f56bcd5eaa5c8c bfe6a1b8cb2a570d84f6df232db97b7a8e4fa3dd8e6af54d09fef6aa6f67d305 0 38a871342fdc49ee6df8bb03917f67018139515d6bcdeac2846b174f4e8eb10f4dcc59224258c944cd85720d61c024af48d2b85e1be302f9b00a706250c93801 -generate_ring_signature dbde6983e1560c26fba2a47c5e5d55dc182a12985b43766992a1e1f119947126 bd9bd3dba5bf6a2d3e986daf25c2cad584ae7c3afa7c27f5a98bc220ed0378ad 14 0f89f5a886f94ae576b8e5d8b947f0e1c7430d6187b9cf04c718ef3e99d945e4 d3e5b4d8755f61d6ef6943f8ba572fca1041346eeabaaaf4d53b6820cda40b3b ef305918a04cf633ab888ed026dafce004b79e96ec7bdbed5ed73e7daa14f5d7 bca88a261ca9d4ac8b51c8880ec327b1893d829605be97a299e9f29998a90d42 aa06e88145690e0e77549fac710a5c2279c1cb330203a88efc44dcc81465ed19 a2b43e260b1ad8a55ee794ed03fad1cd4a7a80371fa5799451593dbd4d4c7685 2fcedda6848e5af9ddbb3c94e181c8153a6229dbc896098e1dd4892f4d4db92a 117ea92dd03c8e8d8b54d680f30ae97884be678c4a868e672c5f78de1012f66d 20b0511d897bcf5c00b6d601dadd3bc7a879fda5fd41644dc07015fb95de9a13 38ea2cf665769f2661fa7e08165a9bf94cb807ef946d2cae10fb0cf314919620 d7d6c773b3294e5aa5436ed9c61ed5f03213fab5b30b83ddd0e7c12a412533d1 de39e3972890dd3e175e30880c96f497e180070bb64d726b968970d2e3be7ff4 fec305745ffcfb15d1e52cb29377b9a029b555b6a4470f0b8165e32d7bc8afcd 623eac57d7111b44d17da4b98c585b59eace5b904538060f2e4527b2f08d7d96 7817e9be56a20810243bf96eed3585470b75dfb717ccd52bed820321c9999e0e 13 6d39802bd6e4368217b7c660085b2a73fc81025606f0b7fbae61d078bbbb9a01996de5f69ab332095c3f69fa953133419e4e27c321ed8172f66a2aa28e9fa0029b8d89ceda19207d321a6babb00b14ba41c0f90556e6d528b40e87bcce10a803d208267c873dbdd050c6236dca754d516630b964903df0a9bdb1c16b74ebba03abd556a0ce6c12d0cc7a0aca849b9c2bf51a54c721257e1cae3b6c5091e9e00a2e0fcc498465126d4be33eb978c8bba17ead82de93212aa597eb70de5fcc920f6947781427e35107a86b4140807a11da8f8972af5ab00c0143a898d2e83a640d68b9c7267b29efefbd5aa6dba5d69552aaba10af6b00e28a448f86bf1b95bc080a1bcb6dc37b990723e056422e2897ca1b47005160b0c4f9896642526dba8a038bce61eabb2945ae1165ec98a7456dd91a89fc2647ad3d83c78a0db98fdeef02d8dfe1a2a69ead13134faeea677a5dc60056b979538758736e4c22be4d1c0b027dbc2f9780a49ec94860aa0fc0fd06a88df8c79c1e81b802e793b38da9ae8b066da8cd15937fcfedcc111a355cef7fcac20859b4e020660cc1d568290ab8880e1ebb71904a36f1fef6f19873a989b7c73ec96dee503c2ba3c5af2b81d41f5f08ee2c001ff5d1e278ac5584fdf4568fc29932e66e4b3fd36b441a8ff3a265e108d6cf11dff6571af308637cd7dd4143489760cd5e988c5de2dca986601368a50a6728bb4b4ec22ce0107d733923f74cfc6a3ad8b02946365f9945018f95460e01bc4c4d47cb1c21526b21ef7d855eb4aa5916cd514a73e7db3e02ef9c260b46001dbfac6929af65ab9dc15ef98777936d5fbe345977dcb7f14a65a2c130914b042d6f28c4cad41cec7a58cd817525c22236e1ac903f745c28a034eede566e5200197f53bd9d85170e47e09dbd33d44e9142c15d02b975271b08d7ea4f701d940e65b9181698cb3a9de7a119ad84468d2f496487cd5dd94bf0dbaf6260569f0a0735270f8632614d89a67666784cafb467c664ae0b31e27d4dca9ee596e05e05034988369abe99431eb9151b98edd9b52d7aeaaf58cc0f0a88483dc06b769985051532c1f167b0012b6520c997886c1941c54cdf7bad5c411345eca8d0dd7c9103999e154cc35456b21fa753d270edde105609432c546de1f38790ea4ab6b49c09d6d7105b5c6a473f20924f4fdb6442643a2d2d4fa474959064a35cc64e90210cb62f27656cb2bf8a82c1be2852467a8640e23c8a3399d98b157132a3b104bb0c -generate_ring_signature 4a049f0f8bf7379759bafc11f3e9326258df0ac45b612ad5088bef00d28ddf03 d4eced528b619b2c7e3478ca4325d630c3e79822e59327310e1e58f2a5bf46a1 1 8e1cd22c64de56e319bddfd26af3e8a6213dabdd844ced186eba1fead7172564 ec5b99eb1d24eaf612b507786695acdf1d15372e3acf311457d7197159059d0d 0 2677efcac75a0c9d3e07a23712994352751fd133769e8c7589bcbc00c7495b0b19242104115260fe9cd7eded79a9c7d95414a83317822fc1a12741cb5304df0a -generate_ring_signature cc597b17e1ff8657ef92c92504a0a1638229a7960b286503597687714d90c0be 55ca58a01832cfe103ee846f2a11e237bd11e22a4baebed2548e75ceca9b2eec 11 02c74957d08764bb2dce5202466669f53b66570d75afaf9d6394bdf325be7c93 7aef7a7f9f34bd0716ea1483a0a4372b437ecdf14874b98455ebf4f6ea4a2314 affa26c8824fc326e2024d05c1286ad0797e4921c3c75009f80f965ad0b6061e e9946e75782aa240166ec2d39b2232303b0f79774d2a9a08310b9336eeec17d3 a7c3963b8e1784fd9004e58fc205b2de95f71d24ccb474cab1cdb15080931520 80a6a8dfde031883f53bf598dc1c47061487b20f393d0a630f0b15fbc71449d3 d9583c14e71f5d28c474e25fbd43336c5542ee1a4ce603f5299e0273f889f9d3 2ecca88312088b7e4e346b72d37ac2c9f312d4d82a842eb9393ebec65a0d7fe9 b59e25c663d8617339865199c0500feadbcc5e2b9d00819a3b91304266cc98ed 9acd42dc028bf3b39fe1fbd98d8eb7c7c3ad85acea86efecce7e41831e5a0e03 3304c25e953f30bdbfb6ed159e4a344c804dd52aea4d104bcab5a281d6a4a594 53cc0ff1070cb40bce44ecc8de8f6b189239790afb0545d951992845cdca0b05 6 79f96449ad1cc312d124f83e2435238456297d5637eb1a2bbe8a68c6d1fe490e06b05430d4eeb2c11b3d93afd95eee82e7591872f544d176b44267611c1bed0596f1e9f4b20603e00bff0f1701f672c987b1df0f673b994bd655d2a3ea9b3b042b249fcae65340f381137e34639cba49de5be81eb329153617f0ea0782f4d6048653e96c9b27491a074fe02749a33f0ee013488c9168b18c20582bd6e5e0320abf521fb4df547c4f7dbaf94c6178e2d0d8907ac33e77031e9bae1a80d017a3099e9ba3c16a18b9aedcbfc8d1924618f7ff58135ab0cb3f85295b8766ed0a1d08f680c539cd0ed7b1b24630bc9f5c0cba555f65c4e09f4712da4941a2c733ab0a08f79fa6b2681ac05035c24e300ab3ff54dad61eec6865cde08e69ec735209061379c693f85c3688f4a6e04601fda6cbd0c028a4a80839f743e79eabdcb9ba0c8c333ca605f3a16524d18e3a25dfaf2d06b4cf109e66e5d92f0af1822139460797383edb729bb35ea05156de7ef609ed5ab3890b5b80c46a278c392c3b75ff0996a05ee80ba1a4e50b85eac2978ef8a99f6c7a04d80bd13592ec6f3538eb7007c32822355461ab48fd917fecb647ecdf5c8551e9722ed0af5f5026d98004880666ab29734d77238e63859bfefc960953f83454bd809375ef259dca1dd030130194b4f11dca8767af16c5762fc0b8d300b9e603eed9b68dd52ec723029430840177c555e64fd7024244562b21f7aaf4bed96ca623b58b4e9cea3434401227a20445176bfe361f413d4194693a275502f6ccca6c2f8f36f9db94a6e7e6924e950d802e1e22428971f82e5d68275bd84096ce901ac53dc44ad6dcaa3836d9a8ed078be51c9de93333316eb59a5fcb86eaf42164df35a9a5d4221286210078d5cf0779f249d7bbbab6c7a77dae733acf47082617d8f76b899378d8200477d178a80fc69e37a4463af1e35b45ed62d09a2a53cbaf5e26bd752f0321f091f1e6d9ce00 -generate_ring_signature a1a10532175cdd68eeb82f0f46b27f97cc2bd57ecbdf6e339a92c61d67056fe7 a7cf65fccb2a26a3470e9f90ef57f9c406df48f0dcf5e9819553605479d54cb8 1 516241f236a13881ee4aeb786cf686b340ea9f3dc8f142ab7939b63ea948f9d8 0666045383e7f9829c827c19f36ab1b57e58988af20ce494064ec1783c85fc09 0 213cd32c2a1503edba39aec9b731e2e9a95eeb95253129320cbe05fe175d600982bc615801e9683302a3049e8d5a3e1126b02c14061662a44286ae75913d6e0c -generate_ring_signature 33b853afc4a8fff7ac0b290b524bc23068dc3bd098dad3cf44bb96470ceaea6a 13b719bda608fee66c92ed1f005cd7993c144ce764fbfaf5349de4ccf5b6c319 1 29b8fb819c8be48673c0b35b8d3dc52b81fa528cfc91ac486b7751b1ba88ea73 bb666988157a61e08efec906b79f3e1321fd06d1f401712c0b4c47a98de66907 0 7d0b0a661f8268d9cfd64917f795e5fda2baa98b67fa3215d620cc601d478703049f726148eab6cb3edb8d77bff23686579ab086f79f3bc01767d12bc1fa9c00 -generate_ring_signature 7267598c7cab03345e1d5e770ea5cb4fb41d934079557f538b0fc4115962e89c 72a4cb672b3233588ce82c8aa41613f0e1f087a370871ed79b72983d414d2dc6 20 1fbc0e3d207a90cfb27c1619a4db82fa106454b554910381521071121f7cb756 3abb94f2520ef80147aed005c178e6ee800ab93d91c284f924871ad3baa3d607 180edd37508ccb4ae708ea73f0e56b0bf4d4a0367a7fabb67803e1e2937aaf70 947f5548e9c8937ecb3b13d7f8c17889369ab8302ffb140a742659c2d1744043 54c8e1ffb3f50f9e364aef8d7164980cec2ceaf36edce662252f53ead9a784db 613208344207cd0665eb79c8e0ce0fab7f8b864bd49014c7d3fd20552194b947 338aca305d87c2f8792b82136cbb7396bdb218213d5e282bb4d29cd713389a33 ebb825b0cb8392e3dbd324e009fa3cf5f22662c70b35ed38ad32155942d2e7fc 2a6a57bc6115aecea112235dfcb6908a5305b54c3e1be6ad47f4286b4d94fcd1 1e9131251f0cbe92c17dbf1cf67836afd9dadefeedd0011f3d53292e889e750c f1d339e8dabea718797095a461fb2eb70e536fa2690a639d486c027cf5af6cf5 4f4f6582bb2e5eea2f1b799635680b34e5c7aea6069dd434a5b1df7ec53eed40 00ef708cc6a3843468e01fb87abc5a78fb3e44d1adde671ef9f977652d93f0ad 1b441c5ffb9d966ebe924088aa42718a58e5f21129fbb5ab4710b30a5eab0bc1 28ea41a63a7c05801ffa3f0775114b52a07540e024e4f437d15c6f596999a54c 5d1635b9996f202342826c0462a030f4a3926923201d97e2e97782dde4232e8b d63ef61485f58a8a8421c1030c63b13e7f9285b3d17a97c0ec617156f3d87e12 22e861e8e46894f227e0c5aef38e7144d61ca338a95c8ac00c222afc157a012a dd99fb211e2e4fcfef75cb569e9a5f751bed5f29c5f69e4afebd558e1a915b1b a79ebc1f781ad0bc716d9d20ba4a4be3a41babd8b940b57419d4090ebab97ba0 77458fd9ec7a1208f2ebed73ce83b8910072cd2e4658cffdded55675eacaa305 8 0480c96fc5f281c09bde6b836fcdf9cebebe890a9c7d32b2fcf51dd184245d02b5520ab2ea5dc52943ce647a24d0f460ca71d5becc99e6008f4e4b5504a3a4018548fe0df0b71550f15f6c780c7a46f2e58354080d83748a3833bea7295a4707e6135516e2eb4f825d0aee624639c765f57aab35bec7fe6ccb544152edcecc042bf6919f45cedc9c638e15919d511fccda85ebe6c4b8f3ce48f98dc6114eef0951036f38723bc901ac2a27ae2f399e625e082a7da1e8fff3e53ce08ae798050b9cb7e886bfb14650b98cb2135f836f9991c714f88e647fcdf4737a8ab074f60d5eebb0d22f1a6a156f41d47817f8e71a213a2cda9fc9138b2141b6dd1bd1b40a789adb540f827cd2c481f27904ae6a3c2ecfcbf8871e4cc4886f2eee673d280954e12ab5491dd2505156a77d0b9ba4bc5da27fac8117d2df4417d082152a0603fd80070a826088f496277e838be997851aeb56d6d0684aeba687a62932b4e20621a646f3f799526760c39a0950ed7a43ba336212abfba34540c77a28d9f4bb06ff979e2a48aa1f7e3cf50353355c19fd124f0254c1efcb7fe6e96dcc99d36907fa24037bbb55bbdab52a3df1ee60a950ed23863f12388873f3a96294f21fcc0a7e0c619e8b8eaa2c92eda8c4ecbaf2e0e459d4f956f73b66b126cfb123a9c20b6671bb24889ae896edddac4dc7ecaf6ebe6384501ab97b6cff92b6aba5651b095bdde9bb00f13203219bf50f52e21a12a4251958238f86d8832f29eaff16bb0ab098c7d48c0653e177a106b7709becb2a0b1c0fb1fc46326c9a5c134954a2b00e2c3a8452222627a30dfe73f709fa4697ff5f024796fd5073ffd3fbf0d952102d770dcd629b37a883b0feff338c0ff306c6e8752c2a821ef4e19eaefac504e08695977fc2405e2db07415ea9a157f5f27488a735c95066bcb050a1c583f58607b0796c0732709efa610c18f84eb8a90b754b8d2fac4e77ecd50c7211ffac870390405d9e281624d87cd12bcc435dfa080177aec9e6b5859887d1afe26898330e1fa4ec1473a73d78a4ed539a39972c61d87ffe78d915cc95cd3e1278d7177d030ad3e6a8d3cf1cf28b4d38a529356c58b78da55e5c48103a801505a040307c0207c05942b29ccaff175185691046060ae4ba48a4b7b804bd0506e361732a7b0bf71d2f6d35bc418b1fe686ca6d3915f0c5b270872611e3dea817f6c49b4d0502ff3ac42ee57dd553bb74b0463c1a04920c549c74b2acc966a262f55cbce7090eebf981b139f527c39b6aceb80905f186629919ea8444a89c8a3d8192b5bca702995636ab36940ef308beddeddfaedca013a37beb2fd41224b6fbbcfcf4453b05d946790e7fe83f4ac68ba7fbfb6db4f535eff2cf48dfb8ab991813a6b4d87f0eb5578faa8daf01b197582c51bfe2d6ce1050882fa96e56fa8fc968af560c7c081f02d4d3d0440581f59e940e9379ddbf4d41045cf5759539ce8f4288933c0b020f481749ec39ae928a674cc65f61f9aca32cbcec456b9a5ed457e900e772f40e1be35221de2c1351f192521c4d730620b37ed34d9ee4a3ac7c6e8bb783e87d01fad72001c6b344eb08fc5e1c2cd0be939ebbc1367c884e4e2d40267958d094068ec11eb28fdbb43b57cc5f70c05dfad08114acc8b8adaed02661b5cdb471b009b86de0e47d3e690fdaf72cdbf0c078a20ab46c68a68fca8c6b7db0198203030d8e24064caacd01a80b20aba98e3d3f3a51cc53c998fd9e13efc7f1764507eb0861ee72eaf6daec8b1f639d7314a972a0d2d28af36790b00f851f51b3c10a2501 -generate_ring_signature 43790ade135a2bf9ffbec0b7dbf243f6dcdd40eb7b420d849868ff7aaa0f67d5 f454c7087f82361c3912a9120b4226db15f0d752d96a5f445e19ab88d0bb32cd 2 5513355588936c635e602614de59f0dadd566c4e7a77fa151830e454838fb72c c00a25f291c66d07365ad72d80b0562e7a91e990305a0bf0e5b01a0db499c8e0 30c8fecaa0b7f217aacb273eeae2ae495f65dec9dd62c17965c5f46beeaaa705 1 9af906242d45b508dd511fdacb50df785908d4dadd67cd06246c1759a6f8870ed73acd6dedfab49a0132df0c22235bf78050c5c44f37067a317afcf493d1e80b99fc9ff29b0ed56128a93950e36052ef6c931ffa59299f584cca699b96c0ee0cf7ded1d35c8ea93f35eb760f0aaeb89eb1009ddaf6fb0448b39a43a9acfbd509 -generate_ring_signature f745e1b2dc48174a463a7b510ac8e6bffdc6303c2816ca05195d9ae739db3ff5 eb4669ddcb40d449366daba63b22670bf36b64ea51970a796f07fbe78b6e1af2 6 fcfa341e9f83038e4f10b48ea65db8dcc728b2324140891a0566c0cf16017af2 3abe9c454ab3179b0fdd96e644d37285582e54423cf27904fff0cd060e3522ec 202812d70556c9afedbfbcb2b863e47bbfa43a0f0e366d50fb369cfa9ba40496 f3280be164b445d7605ed53195350d332b6c4a0425993782d6f5974520f433e0 8b368764599684ce8308969573d800ea8e4e9dca46c25429005d23b8c2ef0f67 dac4c7e0b261d9ce63a7afd3a1e7f1d3c04682287567525b1696ba305a26b42c 40e0ef7967fa1af5d40c8e74b5aa2ce841b04634e8eef869a3e25b4920c6f405 0 209983d1d175ae6fe2db2e42545b32411d1a598d1a2e3d684b06887ddffb170b8e390725e399029826bc3b81a049f7d82841e554f34780e3c650d405d89aee04e5066c618c555963e38b930d50be91312d8453dd719481714d3333148c86d507c081fee225310379d1b58a5542511a5d6be472cef944e9697ddf22e143b3100bfeaee842eeec4f27e344b381c00cecd86401f5c0b8c9d2a378963c0b7bc54d03e1ccc05965a4a084e0e90aaad1fb9a1813ec90452c85b86900674adbd1d9f50b7eb522e8a3386a259f12ce42ef2b5c7f3ee21a0602e7a8ad330a3a4f20bf5802e74bfc22706f6fc1d4e5e90b3fc0fac2fbc687f7d1a89e4aec13255b6c930309c9956d81b40cb57db49f7029e029b49de5b2eac7d0fef966cb01461636682801e55f60c2d380fe1826725718c28315f3f7d35aa542de5323337e47b6c7923505611676679c592eddde060f26b4f374410a4522eb35f064d071081e0e9e64b50dd800e9121b7db458900ba7c7fe160cbcce78eb3904fd27a05378b06b7d204502 -generate_ring_signature 0c1ca4f91f49d1955400c6f4f0ad43a05b4b8e5bdf8c10da751c98dd85c47d95 ed2b4cce5bd48fa761dc4b884062ebfcb4d51dfb6add0bcda77488c533ec29a2 1 c31c24cc6088cf25e09cab4318376a3202945099c5b2117ec04a0d03da2afea0 7297a530706b0a9826fee21337f341f3a7df6d4b53e78d21c0ce596ad2c4fb06 0 b79c42e9d09657c39cf189bb6e1c94b4aa3259c6c82350e8a50a910a7f749606248b9179bd07fb8238a0561f3da893e822e813b071a04da5fabc92e668451509 -generate_ring_signature 31e7df067e668a7056c57de9230390b3b21832b0aaf26c1d136442f138615387 5a53279d3b67d60495984b9cb94036d0504971c6f5d582b8a9c868bfe5856de8 28 d8e11f5cb385732a6b28074afb6337a101560a0015e9772d3f30d3948adfa268 4da2764bb6febfd8c8e04b2cfa881095a1311336854fd54fc4b6b1d3b50b3087 03601a88b19d5bc27bab15b33d1ff472d91e7a928a3ac537c709dab71bd56e0b d18d584e85ebc1788a95a43f24242a33cc9fd281a25029934850752ba44d1cc0 a2696d71168201625a49011911d328a514d6ffc61600e807450349198bad3d8b b1c2f0574ff45ceeb330de965a3ccead9738da629a941436b22f709939a536bf 7d024af0ad9a8bc11b1870d4e4bb34a3aa7f615b47728c80e366899088627861 5e16ab4a356ca7682ef9b89c2ff32ab2233393c1f6f8ec39945fd8f68d29df5d a4b8a7093c7b2f11f4ef98f3e17f398c05daa7f6778c4ef6bfe8da1b6ad8638b 0f3c7ebdd53bfd02e2f96ef56487d96efcd6c6d791486816317d624ee90f31e4 744845074f17c4d32bf7b9c0d4580e94a1e86f2c5521c5f3a2c08a815a0978b9 31298b4531ac19393a103da8df5afdca6312fdc9bd467bd488e4aafe0336563c 9127fd630d5000a395971aa0d908cf98a5c7711e0f01d460a2a7684f52d059da ecae915500777293d1a23bdb2d70c17c964b9a63ff8dd4ce6dbcf45772c3ad3f b48d34c124988a550b37c4a1d823017ba38b39b790880379ab0d9cc0031f934c 2de61fe61cbcaf6ea1f10cb8ba8f4fb8df780cc00c0e517bcaf9284cef02bc46 040f04ae028b915b6d1c7d906be11eeb401f7e352def5f7613e211fb0fb558ce 551d509feb45aec8e434baea8603a2ff77b5e3a07cbb0d0b527c8558c4c64708 d073b898ab4ee3836c67d0e5d1dda2085f4c12aa416c81bc340b85c3b8b6ed52 435503b90a2d14f405096ebca6b42282534834fe9ea39a6bba5a4caa4f079766 2acd80251b3515fb625a9a18d2154b9ad1beb8d8b010d8be83ef0b749c5dd6e3 e5215f531238d2c273de542c6f4fcd444e82134080f087d0afc64f6fc8bd44af 22424ee51118bf80a8cef77b8e113cc0330e24a3844dfd84917fbead9b8c254e 2fd2a01313fc8b08b276862efe9a959c3b1a19c26615d90530bb81a9f7bb86d3 ed488f41eab4fe62d9ca4b7b84264cc8320704afcbaa174d0cce1799d577e741 4294f3ccfe624c32b9b2274e0c12e55daa840db023085c7e25ec32e00e889bc2 0f8c0b190eb31fd4afed7e449e6110176f33ccc4d986e948104607a326c879d6 3bdeb0e9895a3814004480cc6f992bb3d35b747f697bb88a04147e419c5c2c72 3e8890b916eea212d4e1e8c72b2775339eae8c42e4ae8b43ed09e24c694e7e0c 6 ccadf6b1749d19fbeeb11a13276a7d6351bef5696f107dbe5459a9116522e3090c204a95ee2e62723425c5355dfbda1e6c0b3d56a8742d52a1ec6ad471e05f0a7d9e33d19a221ff68085df2ee5c562c6e0e204e1236a5b0ebf43584bc232690802c3bda6bd812ba50e521334c5f69c3bd36a5d10afa89493032b3756f2bf8300bba5a1266115337e3c30839b58a1babf35f687605b5ff5892a8ca5124f25fe09d7e05d56341323b9cf6862c9fe76b5cb9e23094591f32d5b9d82a6ffd139cd0e10a05627435f7ba82099355f1833b43184b15970748f4df35bab0cd0b3a927052f2674dbe1f68c5778e04eaeb07b0b8a5d032c4d143064b4f2ba6b02c0b34a03a6bd5fda8766a42ce12917dd4a8cebb0dc120148ce92d6fbc66a98b00728b60e773e83767cdea8576017744683dcf211d6687e174827445418536ea8f8277c0ea10606d2e2e78afc78d00253666ab905de8fffa97860c9ebb9ab72adc7e89d009725cc85ad44f0346f6fc67561a6854c13873516722d964e93d5f5e6b80b4203980f2a574fa5f7545ad67a397e1b6b78144569cca612f895a2a7f6ec3f74210e7d6dbd6e25a5fcb2fcf3ea4c4ba8d358c7bb1524f3e7169f4a7124eaedacd0012e7808c64bff2de2edc045e520eb6270dfe865e6a83de0a967d07e42d710a90e6846466cf9605d9199e4b18253ed635c453285f3a98aba257c01d98e845a2609d056cf8a13c17966e06cff17109e3089cbb2fe04e87308c64cb85e330b9922070a64733849d9a9816296966121e894724ae138d629051de2ade2b0ed3cdfad09d1cdcbc0acf0adbbf36caa14033944640b4d4e1da76f7e0cff7bff0940bef80f370109976f394cdf02f63bc042181edd629474f9ca4bd6e5f777108545ed690b11d5f4332e5b8a04a7984e526123a166a012d1cf02cd63b3d386ebefe90f120c774dd8d60dfb36da55f6f372a20466c103fa6c35f004deb76505f1177980a508d58f83d31c891160ab486496a1e58215274ddb3c9d147fa882ca76c3b50d690a8a06d03195369d0c99bc096fad0672333a0f56ac38b058edb707d7a9836cec00f3a2d1810d4b9f5d88f1f5e4cb9e6c0d6cf7ddcf68efdd0f5c922d301d951703b40171346860d16a37fe8b13ac2d17ee4f3e8596bf095d97f48dba9b453c1c079c2eb2a126b57eb6e2ce33a5cef25cd2f55662a5cdda73aaf60c635b0ac3560cc28f84dd01010300e847a91562fe654a337797e40287f4f7e8c5ef44d730be0d4bd7be57c3229d49e44fc13bddcffb4c74ebd0171cd51e2b49582c9801450204ec07084defb841cd1dd52cfce5599a76d3a5aae0a7030300bb338002757afd0689341be22f73572c5e430a2fe8972cbade9bae152cfc1ad9da8a8fe82f28f401dccc75a32d68861f8fa4a07f653369d0f3621fc0bbe9d65997930aab8b25ac07cd079d43a0b9cdd4a1cf1cce46839d9ab0a26f9a02cb0307066521f4496f110cd74db73458078ccf6391be33cef79182859f04a93d9a92ea48d384c99e48b90282d775145370ad05c3b17dd9357f4149332efc4498bb4065b5b51b00de6314051ea6bc8f61492773ccef7df9b0310c210b65ff7d4dc41d79388b5c4cc6af7c01cfa3e0a5144414c00fe006fa1248891a86beed1b7ad5a055a8b85a33842aa80f8f8f91fc2b9c987ee245cc00799aab1984131d143527a0e1c1a123906c896c0d7807727c60af304bc2034c129cfe002e0a72ac225a2e13b050391d24c1629c0de86afaa0762d65404530585ffb1090fbe04e314ba18ad1001641e82babbabc01f5cfcc92ed3dea9c042b8bd12638d41b909fbec2cf471a6c275da8ff2c991a08ff2f8d0ef14a5f7005dce8a070ac41f9ca74d9f85e5cc7d54dc13277e43c28094a674e4ba96026785f00a1309a1f24291cbd0e1c6aec09b96b43aa18c0b25104208d63cc2cb2d7487aa4045e75e61b999ad56d7412f174ed2676b142523be20c67672c1c55632e379171744ae0ba9ed5127ec93457e9b240231ab97a6bb40e00be85e3ac91470e13ecebc8f2f711592e9f0a5c51fe87315ed53e61e182c3b7062cb071b7fd42976670a7c0e939cff16f3efeb9749550b9b4c3ee4628afb752042da7e1e318df6075336f018f6306365ecdd6e6da00ed1407663a123a81c9c30a7b9154344ebb0056cc69acce01391cdc68b3b7369333b56babac7ba8f12d3c0ea18c88c7ba103ea701691eae77b3ff399c1319c939135233c991371c48b3e9039503c2b3303655740b8ca7823021002d877ea64356e23ec30a3ddbed8f311c084a00102e40e3f03d16f56be99c746c4cec5d855c7ef77587bc9ae58ce52a1e0152305ad3871dd35f73f20cf0ed7af7786d5d9366cd55e03964bbbffc2f0adb0e8d47952b21c1585666487cef82d40d6a879f86c4e1bb39beba3f680122a00d0ad0453b5f68c46469ae6e8a555b0ac2fd1b5dc78f505080479f9100d1c936ca0ae56f610bbae7b68842bd33789faffd7c2ee4b83ee5af164ed694a44fe92e040a -generate_ring_signature 74cf9d48387f68da96ca0b0be54b436b877a40b8d7ce35afbae4930e435245d4 21d51622f92eecdf0071d205840bb1e1e1b8b26d69942dac91980a694df9641a 2 b06cabb47b0111da68931631552e977c5d0f7391abd7e835d4865ca6b6ddc4c1 c59a24c4128d29bfc1d676496b3b275e1623dd226ddb23f8b4852eaad13038b7 880eddb85bcd967112fc751b1512b490b11abe5d054e43126990afc8226dba0e 1 04bd30cdd64126a47d8ff7c8788afd5e1704091c20b9fbd5be399f0dea62850bdc0104759f7475654766b09b7788d3e1a090c59628ae2a3860647907a12527020952fa76b7211af7088e2e3ac5b8f5fcfd15c4eea22420cfe25841184122db093f362e41ad9ebf70074e590d212dc202c1eaeebbe6d4b27095f571078990b70a -generate_ring_signature 9207d102e70ef77349166326193c037511f13940a761e9caa6276c186b3eb2dc b935299ab3141f7bcea9047224771b9eda89b7e65d5bbc85ca163f1d7defb31c 1 764d6791a583a488cdce815e5fa424f70de370e2669d6767ddd3d553c6199343 f6a1a2a2a3dbd61d40508ba1f192c0dc37fe3d297f3df14c9730a6f084779706 0 fb190dadd6f34af307dbe0bec1df71e8c4be3833d096925232453461dd91c9050caa89d49eabc8558e14320f29867bd3543c653757ddb4df5494e416bb294e0e -generate_ring_signature 8f1205e1c7bb2c98ace5d21dfc38b0e52715a4dd21f9b7de40d9dc516c0483fb d27c1b3252173f413b070231ffaa38185f412f2fc8af2dfa34c6923146cb8f8a 229 52c5784d3cda705f4866716a833c47355b5fa4898cdf0f719014b1e06da6e6a3 913c3f015930f8ef9ef6e7113a6d9dc22bd50d047517e2551fa3eaebaf108502 6492b0bc2eb958caa42949a7a154c2900bc56ed651135dbf4b1b170fe9cd7045 15511be2cebf723622ccd3683485b7643fc64514f97a882d9254f4dcba06aa96 30b0cebff8941b4295fceb60692aab5cc46f9080e27da45272545311f81f211d da45fd73c50d7fd41205025c634b92098ac9d86dc163fbc5cefb2bc8c50ffc5c a6bf60e5242b2fed9b365e5e30a7a400c1ed7a182291be8661340f03a63ee265 5bdeb86000a7c98f5c7c3570e807dc75355909ddf07ced6b1b8a49b8ab5b4b3b 7626e7ddfac740421e4ec2f375da22498175b569cb9ecb7cd0ff729f17c77cb9 33f89703bcc1f9888f44ac7af120c14ac800adf93302e7fc80b6953318683540 15ad941b050df08d5fbed5646703b809a4b2bf59fc806f68be975a1659a3d67c be0d234f31dee1eafdb19d6219a12ecfb0cba4b276dbcb9c7926588efe936bae d2c6f00ce060342eda234645e3302365ec1b1634b24a3b48bb83f7c2e38a4c58 68e9268bf9af8e28e84ca36852a5cdabf74996854218b84e62fe1821a6fd3be4 de95a3015e45e1e1a20ebe69066248bb6d9091c33fb5f0fd99c99e2c98b3d9f0 175f159b521035a0d4244455f49c292cb6a84c4820ddfe691d34c960ca04f7d7 8c2334a87ffbdda21fb11cb805d7a0ed8ce0bfe34974660956a8ea56395aa4d8 c7edbee25c17019b2202d4d0536bed6c36c0cfe9368be0a937587792be18a73c 42b6ab41fecf4dca2b1150f4d8952ff6d3e26c124d1abe310be551f2d5f5275a 3622119839daf53fd79c3d53a87e92b7174a4ca560cbad31f906b8def47149d9 1ae04ed9d6599aaa3208bb092eda99dfc9e9b48f08b73b45211d907038f38aeb 01cc92d5068bf3d9ccdcbd5622d574a02bfad10f4efd4b38d0f443da3ae00e5b e862f2cd0bcbd35d523302201f9bc7d15ba68b2c03076e475005de87bc5bac25 0a9d2fd156f8c3e893f28bab84b7b9384e31a15d1131386bd66fc345e5599653 ee3144f7734cb223aca913d15b02900aa7122f079f9a6247d37341be18c7493e 49630627a6644da9ee51fadd02c54dba4abd237db31d8e7f911f9b3669c71ac3 cc1323b8356b0134cee1836eb0e42282f78e46a54ec1406a7d28ea639fbdaa92 3cc0a3b7da1acc1ad6d518029595b1221e9b632ac78a707ed136b597d18ea8e5 1437804f33e10dcf092b2e2de5ff4b0e541b103b05b160e6416fe5d915b3d867 a28c48c79a7694db14669c83277b53961a86332fe3e488074b3b4b637e7b13a0 0f352d25647efb575677787de2e358d579be0aa9bea73dfbe3dc6217b12706c0 ad3a5789bf9a2500ca930d64d72f5166516c71f42534055b3a945447bb0a4fa2 0e338d303c59926ff532b127bfe7f5275b6ba6110631ad6932059d028fa49b7d b68a76cc12b0825d96739793cc5365d02bfe50ceff68afd0b9865f65cb60a3cd 018de5869e7859cb475b48aff57f07f0aa8c1e1ffba1e8e96e87fb32c6d684da 06888fe284c0789eb6e33303797f365dda3cc8f2a2f9ae7754ea1192ce14d435 7f41f8ccdc6f2b5194de7e0477302d1fdae0a74239d94d481d3147ebff4f635f 1ff844011bc0f9a1044b23ab46fc2acbe00d939a9fa90b32dafb8d52e25c14c3 1559cd22ca6b489236f6854add12fc7c2946c2f1f02d378539ecc9305700f87f a597e24bc6f4dba4354d97eec4ae6eaa44428e3f35ca2d060b85bdc2785b2dd2 861635da1e9955e43980a21e4885bb8998c8d86a047f382f94f93da569985c35 66f0dd261e45dedbe26d5e060b60cda4da5aee59cc0ae63387dbed7baff10649 447477689524d8c7a55799d1133c47352dbc5d1e71f1355822fc984ad6cdc2a3 1011c08840a7436f9366091864d940e93e6ccdf7b04189907ae27e4d7e00d96a 954b68b72e15fbb72d805b79c8137d01f8a83546848f8e84d99d7e049dfda8c5 160761e382b3dddeb20b285a60335140f03f3d75acf9005a8274769d3d2b3b60 3fb8f5f3539927e5c4d8d254d696ad4a2eee6d8850d9ceae857851a608dc11b8 5597e4539febf5cf5572df1ae65e58ceed3d7de6c7d8f48d4fb0f3b895951b5f 5c84d316987cb2949689b99adcff5ddb82e0c1996f9ff5e7ef510ad3b679ea1f 2721a20b915b3e8b3263055b1e819947c8b6acdea2fad1d5f2799ec3f52f5423 abbc7b0ba883501c0d07f898df3d11080eb4780ad610e1e8155b4b31458b93cc bd7254abfae24aa591fcc630b3fe13b2f6ecaffa09d1f220ec3d2cc166709ced fc3646f77bd6635c64a53e50517ce45fc7a60e84dd81e4ca06235693d8cfb44d 9fcfeb091e1bf9cefbf395dba14848ffba2714efeb80f49e9b00b00c9f05be86 8c6ef973374deb3c15fed4721bd7aab0e6cb36eb543146d69ba5b99cceeb2ee4 3313b1b042d283088915c9416960722098d20dc06e0805f9d20dc2eb7b31b46f 9e44b4c47f110e2940b199cf3ffceb69c711876cf5f44b3bcddc9424ddcc6218 52387c696e8b95cf5ab7f9fc26fe4a66bf8e1d84ab56b787591619fa2c3e44fd 47ecdc3e664495b46990625452266fc65083351cee005e2a769986e161788ad4 93b8097c3c625640736d2558ff7678691cde0fc00fc2a4e0c4e7bb1b54463447 d32b0abad912cbed3ea7bbeab6db254e521596bd6fd944df06144a2cd685a68b 6b2a2312bdf27d04cb2aacf4a26994dd4b307efe7dc2b1393e815fdea8ad6e9c ebced6a281ec97f6f7ce32d1e62da1ead1173bb873770ccb11f79f9d196b4307 16fdba74bd5741106023583564de63f5b77fd0ae433253ed67d554bd7bcb2826 f1ed0bf4e6f4ee1fd98a9a9b69645fdfbe81ee7908dd0c21cb1860b62e356ed7 681c3a1347ad98aaec4d7031be4969b3f26bc09b03e30497d58d30bbf95f036c 0b9211db6b2a938346aa0ff7df2800f81b4c45a58e5d7689503d584d0a0a5b0e 7dddd689afeea27ecb36fb61df6a0f088152a5694f4cf4155cce68fa2397f6a0 accaf8a5f922e97e1e740b5e8f60674563ef8efbd6daae9cecefa048705ca80a a79aec40aa552d5d2c8564d40860785bcd12aaa001bb3c1beb6846908eec519e 6a8c92275c25fbc29c8b9e9ea0a7eb2d50dfa48836a11890adb27053114e730d 604d081c0de894e8a44412d641baa0e067fc038347ac1302aa2a9b0baced9311 0ada2bc88e8648a5e0c01a90a72ef1ef334849a5cec553309769ab2ff98618b1 3e89073127cc5f0fb823d9d0c8b7ff60974413a12754775b9fba0efc19efbb3c 01e8a98e41bc850b040d84719c66b985e798a624749dcbf8b358ff7d64c233fc 6feb1c7182cf86bd80f8eab7f4681e6f4af6f2701a024d8dc6e581b4a4168ec7 f8e67fea54bffd71c8629a90d50c7f6134a0c2b0c4526795ca2a5e07f146f392 069158fb4cc625c32daf2608bf603d73b7cf3cd344670e218f3e8e54ee691ff8 4cd66ad442a4cfc55b4d0e913daaf33cdfe7dfd1da22b6c2e3a766d2e60d772d 1d0bf5a9a0c93b83efe4143b4cd759079984ee4b0b56512a3a0a5e2c0c9d287f 4df2310fb9561413b277873f38428cb814f221dcd694af87c2a9dfe676a64b2f 370a267d62385479b270e46f8578fd2f68325de6b7c71f7bd6ad678b061b71a5 7695614d59d1ee67af6684e4e9ba5e82cef5880b53b3070a9ed5520757fb2f2b 5c95cabe47f6be580ba29dfc59a01fe24985b9cca5ad1c8f11d94a3c231efed8 520519e1a10836f288b25c7c32c15469bbbe2618d5193df95381d1cc32860847 0d1f46f19b2ddf805247e8023194a97e1f25a23d7c9fbcd9ee75408b369f89ca 6691f76d727a9fcd6729798328728e9b4991ab4ea23a0e8fe35566985dddc1cd 1e9f2fafd07dbe67ce07bdc4b81cbe6bef69b5f69e90db19f37bc88680d67513 3a44c7187849ae084e96d6e6fc5607550a96d597a298c34804edef0c611718b1 f6d7535c498c428a792217943664569f4c301481b400c11a03c03fc156fdcd51 2dda0f1b716a5a96014d1ad7c0b0d6c3049be66082acc5760b70db40591b7059 97b342dff13f2ec104afa7ef42af22d053c0d4724d5c150a600309f679783c10 397b9cd9cf85af509978ee6324ea25ce2ad46f4b6fffd70fd31376c411c98b8f a38a93655b55c9ade39d4d1e6a81b5e3014066fde7e81e91ebf5b82f6dd139f8 1cf789d950a4748478226d2cdb521f75a63c6dc3edb4cb561c2e57b38750cba6 4644dbd47839e1e94946ace12b1dcf5c64920d0c0188649ef4a5fd11b5075599 765b04257c56f566bf8748ce698d77f0961dce48440c50673e838a9f24233a88 6b61314fef1282d0eae6088f5180abde895a022e6cca980cc193597a2854ac6f c2baadb820f257ca6f3d48de4c9768c4b07c7b8d4f7342acecfb12becc6879ff 0cb01561b6391e1493e1910575fed3fc3c314a417313256912de21c61610a077 1a1c943bfd4be26fc17ab352e30988407bc7de6de0899e3c8aac2a575b84705e 0b2dad0d3b05d15de7f035d82acac91d21c7772aab52cf2f35ee17cd1f7496b0 7e3b55ad8e3a235dac80156c46e290880d9568752fc2843851e6de584d7fce99 2cca8f02b11d269de7a1790ba4ab530b9f0d893d6a6cc8369d183170d940e860 3a7191d183ca61fab0c82a531ba5cf5b1da51ddeb1bccc8a3a5de1b3a08ed590 3ffaca59a42c9a06585132bc401078b1e69659c151876b562918cad9c66b080c 482a252d0b29f7fb876666d565f5f67aab6d39f29317d31236129632585b2ef4 4163654838c2ba6d17590d6710cfcd1bce67f76b7298bfcf92139d2502b899ea 94a1dc49c5222983b4d843765d51526f0f1cdb54bfc9a68f62bee58da9cd0270 4887f9ef5441a1f87896339506af632b7d8a9c2df05b002b42c5b6c32165fb66 c53bf4a93bdaf03f2e3c4561357ff9a247cf019dc38b621b916f2c4d3395f9b9 f94b686e0d068cae20b55014454f50fd950ac9f84ca705b629dfde4baecf1ffc 2a3f77e3c18ebe3ec45879fab23e3e3f1db348d06eb30666e3a185484a91b7a5 5a40ba01f1427edd310b9408c5ab2488e5d05ce48b8bc85f8c0081adf11cd9dc 75abf56aa4921954d4423e957f680abbf1e3f458a1717f21b69d26bc7132d484 08a037168f337c2f30ea5db11153eccf6f2cc847e052ef0f2dcca49e446f9c2e 9a88ed5ea6035728e6cfa1407aa9467df401bf31e5b9661160bdb48ff7e1fc36 5c86516712f28f11b0a96055acd38d7819d497ca2e4283fec8300da62612ece2 b8a0708e9b6d8586fc9bc3279a5f0a1bc99505f627bbba52d9cb4e313ebf4d4d ecc9011f2f931508fd5b199f76df7bb96ed8c1345a1787567d80b249d2b0eb55 18275f7f1472730153d052fe574b8e890a4a32b012934ea236b3663dfa28f14d eb3014649405efbf8bfc962ee7706e9bee6a4ef5625eedeafaae0051aa721917 59fee3ebc15513a0c63a4040bf31bb02b6c20c9246d006b4f026c1db2e7a49e1 8bbaf1b46137d97273c26d93918ac0baabba90084bcd209a0a172eb8e7ef9b65 8b2d7272c1ae09827cf434578ad48fe3ebba74ce2d3fa00a35c55523e3a9de89 e129b195950d493e3c9e498f8dbea5b3e1eb4dea65fc03ac2bdb26df885e4dff 3671edffe7f5fa8fe14ccd74930c7ef620eaec25534f1e0db04046db3a09d3ca b086b636c71efd2445cf6281fb3fe8c858c5a345a6ab38314e3d4cdbe962c34d 7ce5992f4a5b9ab21f3b00bd9d03eb3b508c4e8d472f6ce75a624bf69c489cdc f709e736c33fad590fc82f9a7147597d3ef86a3421c0cb90d4f7824f19ee0643 0a758da68465fe3fae79ad29012b6035395373d0959fb27bb440dc9468683f19 5de2ab6d01977528e26cb98e22ce5205b76ec3fe33dfc38beb8ed1ca8d65f41c 0718b9494418118f2da64066b22439acef7fdf1e0f8b14f0522d42d4ecff4722 52ef5deaf9620304b0dc480da5db8e3cf017484061de018008e2ca1c2a6f0675 cad10726ba8716d69051940c377ac5f6a82e2e9a23096597cebfcf06bf515e86 9fbbd93d71ad8ce532ab9b2024aa3cfc17b89137e91f4c3f93097e8a34a10e17 d7d5f11eacdc7cbb053d15d3f63bd0e33554b9dd2eb8c83800f8fb9d0b2dde42 07027433acea249fa21af4cc3df4123babd856022b1a6e7e972a80602a5292e4 4b1cdfb44d28cbe272563682d11e1489f4308bdb836b6ff4a61d0d38be1a959c 9f35f5c9b5b382dc4b6476d912351a322cf349d8b5861df181163a46cd393fab 210cec3467f2c3cc24ef57caf3f7fbf6b7a8b46edf272adbedd8cf67ee954aec 6d5fafbbdb69bd02b98a2b4bdf24065092c0fae33cf6c6279647675cf20f5fe8 6814c20e384dd2298476d630badd43d8834560a06e4a5d328268f03b9f65f714 d8bdec2059ee9a599affa6e3548a00524dc582cd194a66b5740332d8404e43a1 8e446db99e8e579e5059ac28440d2d2c6a6f1838bdfe074f2da61805b213c11e 50a06a07245c8319c6f64966086e439e8445382b79a31513ae10998537568235 5efecc1a91a9a9df0fffb1050cb1ac2905100ca92c0ef87074d50e17a54c4696 ddf9201bb6ae23f18cf6ef069d183d0ecd22b08e481d2f1c4760f3a029a17ba0 6c1f2b0a8ccce1c65d4f411584c4a4811894b96a7c74dfeb4ed9680e4edf0259 300e358000c2b357e48e532f4e02dd6901dea80a371cf4b4856cb5adf2f97c5d 49ca50fd86f5ee0445bf9292fd492e4140e550fc6a520024619501179732d503 026d202c9bcda09cef16ca1c5dcaaef6da40fe42e533562c530e1b4a69c17277 8e4d82f0a0384babe7fd0a4326952955832a37d1152d0fd189094fd0922cf106 c3ccae4f7e60f4fa82bdb101fbff68cd2071e2c7c5729b3e9d7a0a6a51809807 e2c970b2577d34c1a4849fd4ddcbf48bc88627d51c8640b3cb2ff73a0ca852c9 054bdbb5411a58a04ab389997a4c85e38f2c714137252db2e130b80947c505d4 491f4b4d406f6e89833f4255c2f53103a26e3fc9f2d3f04ab6f5e034f9d16a3e d7f7a5fe433888c71ba0567bb87dd28d719e92c71254a1f84238c7a78937ea2e bc03db54203b141f413912cb5a0cf4aca06609dedd432042f8775aa2524b0a58 5e59b2c9319d9e6b450020f4b19b4c30bc5b2be4d32f4f635005f3efdb40ddc6 4d3553533863be129705f3008ffb8cfc0477860675c0ab53a642a13445185e4f 10837c90037eee815d50df2304f1c5f35ccfe3bef086aac31ea953fdd5b1da1b 5783cfc3d851b2043684d08af46bcc28c218c4800aab3e4a25192990c3a3c143 a529b861e4f2a800c334f542c958072804073d33ef707a324ffb950a0d9a3bc7 533de95bee68271d28cf19a0cc1eb17310c12b00516d8cbdf11a0af3d90f6ae1 ec2a1aac02d4a55ff2436405b7e821d9612406a4e1aca17b3e05f54039d47fa1 cfbb9f0fe10486fb902b329603cef2d1ed5be4e50557e366dd2d9c75cf535129 b0fa5d3efcee11d9e75ae5e77cb0363f64278fc6958114c6896c77f776ea456b 92562a6e185be15eb3dba54eba90080b2b556ea4e3244195e97c289f2936c09c 1130fefded4d6afe6bd3c775c6f3d92e7c49dc0b5f4a64ab09dd94efe5bb27cd 03df5ab7e0e605c91b33709c625af020147fd3d14594ef3928524b3e41956276 fd4730ba5fb0ba5e26f9bbcb8e24be8e92768b874ba84bd850d3d6c6bf14fa36 ff340888ba7d0ec25503b411fba67bd3eab35e778299f4c7b8c4685ca0e4073c 7cc168482cc27ace90bc3f551975052082c33d3c74244cbf423910d00122e760 b67e965b6227c63f7b1f7c1cac3f4ffa044b499ef2126be0e1874db9fa24a6e8 af6ba3f29ce5b209c40565ca02b58dd4380715f6f10d872006488359e5a468b6 4267ae8273f14e15165df0be29aeb50a9a3bd312816a9be63bb554bd6b9f82df 4ea2aca4800d87b6df9995e3d83240df97e309fa4de089f8b12582cda536ca05 bbd135a87a41a425b196297e060306fc2ea93a1aa2b9f3e6ed2b66b52f4c1f89 d025ed814116ab93c9bac3f9a4272502bb77bf9f71562de1445129e041bd2831 12ab2d4d0972a1c1cb4edb0c36bb60f3c347a8a651b814325f85b326e48707e4 99f3623de0fedae77f920301cb2380861f9844fdbf0d71991b0942331449f9f0 a0f626fbf3ec494ab01485e7e9e49f97a28784231070d4ae3c6b7a9df94c37ed 580d0cb132d0204f173abefcf7caf3abb8bf62bf65bb4954b29f4451f642bbac 8c97a982ed265af9a10f3f8093be8fbf23bf583fbc5b85e8bceb0aabdef3217e 66c73b6297879ab3b614c47308a3e64501904c7bb61e2896121b3c97b12d3ba8 33c536581435b1ab7a93b47ad2e8ee25d3358873c7f13e07e38ea9d1fde9581d 358af96d40f33c96c703a54970c329d9cb71777c66a41b3706b161730e178e6c 973bd3b32a458e0b238a95feecc044bcc7640de370863919a517629d26a0c100 9d3ba5fac2f6aa8fc46a7558bc756ffed5a1a2ae57aebf71360681fed878424c 95898052706ffa6d889c76a090e8244d2e6e7d339610a429da38c3e454465e8f 6604e03547ecea591a6d36ed604582cd8abd72bdb2b49e0a917771da20bcbaaa 38d80837cb55b1ce698fdd5b8d44ce9bfccad9cdc19e0e3b7bb7de9f5eea7833 16bb6df962e6127a9b053dee33aa890210c2afb63058011a95d5d6217aad5d41 09d9cd42fbb4bcafa7fa122ee44a13b420e77c58add73a305eb3c2b89f81348c c5aa1333b34398e500bb2cf60376e5dd6126f4d3db3034259fdf55bdbd3ba7fb 3fae5690d4a5bc412b86d7618d36dc4ec01009aad3edb77ff776c673109c7548 b28456140a3e985c226ab99a6c80f87afa3519e955faf49227c7de36f93d6d5d fa133b36fbfadd578d68199bd44c7e2b902c2ace06dae2ec52034875ab963d0f 3a5c007a828fd572ff8e0e713c46fc41f5aee958e186c1b88198135b116e5ed8 de33d23fc56054e68f333fecfca5f4d576fec6c500a494b008591f99c2a6c126 8db348260e9bb621ed1ac68622e551e852db4e8bfefb048e31e606e71cd9ab0c d909650ed9a50ffcc7f26fafdcfe91064dd187eaea4dff027bfb66d734a94bc3 2275d3df45c2e67a1831735a9852351d1e40d7903380cf3b33ca7ad4700ad8e5 9bf506cd884abfccf74b7ac9899e5430ab9be9ce1dcf4339453cac9308ab4867 044e10b3a3f390f0e44eae198a8fc246162762c0303b9326cdf01ae02285cf27 3423e004c3572f016a2711b9b7d5cfa4be8327185f4782a83e719fbd880ec73f fd57d3173d91f4f5b7991b70a4a7c17993e783c9a250f909d8a452fa1d4a7d89 4fc2721e8e5cb0f0e49791437299a6969485895295be74f63d8253c3e0897622 c370fea6b41b19482dbffa79495759699404f5b8aec95c42d022e710feceb4ee d76fa502cf3ca64f27d37460208b45d8bdb4343aa09f60bc86b43b45b3bca456 63fa51cc0c431db9458fc137148bc7072aff9e34af67204b0646139b5efb43b9 09ea32768ee291622d18b4ab9b182a0158604757150dae3692016c830f19b508 f2b2230fb64c40711b943000fc9faee75bac64677635f21b141fd76aebb38dd2 5e39938c9c977fbf84df5ee0f5cddded6d55f17eee0a38dd5bf01798a9df1c01 855f49af12792ec85075cd22ce20f3bcdae31749371e906bd96504b1662c1466 4fd587a7358b0de45ad268c237bb9b299d6a9fb06414aa30300e237ba1a3f72c 3edf61a65c3ce5226dd877d6aa70d639d52ebea7fb4f3aa7259e0efc8a5ea1ac 5846a56eb003d2b04f8d8a5cd02391ce10bdc43ea6114b740f590070d28a7003 c842f7022d26e8f0c9b832102efa259ce5e77ac2453fce14a364c590d1ec5d50 f90822ac98bcb91651e1f71f9c0849f821e2810743ff1e8e7aeae5909908f451 45091874969d3c9792356d245536a8da824e9adff04698cebcb99ff8e9e20f3b 9542ecf82586fdcd124636a4ee4bf2c4bebfa0f98dd76b45adac28227b0f455e 38c69a23cfeb562bf698b66058d99e63b5ecd7b8ca0b1354a57e9d60140c35a1 f7f75d344ba6ecd4ee5072363a6eff47161aa6334c86e4f3ff832074fb064b16 f7815c6dd6946ccabff6b93effcd8cdb8dbc9630ec5274dd476b27c3344438f2 b21ed1f01a74f7cc86f2ebb376b203a82bdbcc17a6acc4700d314012d3ca7e6b 54655a6c6b8e909278c760828a75b2daf5bf809aa10d84fc68bf4e1d3636d5f6 6b69083974fab0a280295796253901ac813b657efea7348aae3e2eda762ff923 fbfdf4bf87b4bb696d14bc2b350acd77eae89f267666a092789e0af07a32740d 38 226ec6fc0c32130bc13519edc176fccbe844aa9aa9a3f31e2de4ab27d05a9701c30982ca75fe915fbe58bd1450ee11090e3fdbb6da76e2fef320bc0cef7cd807ba545ccae4b8bccdb79ddf4c0b30aa01e845250f16d2723358db03aaba996005e00ee290691f63ad61fb224198e56f410c348ff76841f3bc2b93c4454aaf080c4e4916fe9d734c952848135e1c63dcdfb26da0f8c4ad92ad2056df19184ba005d612e9ded7b8a67c6f857bca5e0aaf4947966b8f2591f40295cb429dbab62e07ff96cb9af45acc89b3b2f2f9c3a87de522b337c066f51897bebf4b9c2df5a60861ea24083d3997560705d03df070d9cabb381ff9828f94c3fc65af8a19e51104b51dd2df8f341354ea419ea1fac81251a704bd29d347b79e12e33c8a4012040f74c28da721d51c73d200b7af8331e91d183710203d07d3326106895c85abb60cfb0f7a760044d58e2f7c4492894a9db17e659b303b15b57acd5c852b1e636a0e2665a972d2878f3d1999a8e64eb9236b9e08b39a5436bf69a86304e56ee0030cad6b4a9c82e8621fff95554c6ea8d6afb9b691a644d570c34c20d69b49511309f4a62245fc6204c41b8fb2f27f3227472ae1b5096bccbf981516719159ba810254cb039305ed4b83b8e97265203a049707a76f5d69b2f836e298f3f117f0290da44bc9a371bdea377d9274d50a5638fe2f77b0709b7bc9e22a02ada43f38bf06438828e6d4e0aedc22aff795df50934bdfb3235750fe8eadd9d4a542a0ead800a8b529269e00ab39d3b208884bdd3c1bb2d491a1eefda07e6886ff21f031b10d6a1cb099b670aacefc5bf51222b7b1643ecbdce466309653ddb712bc8a65fd0bdf09c79c0e125a2ee8cc038e9b185e0c9906fb76ac4188aeb760cc87ee1f500e1213d1af889a245231aa0adaa16865d2b372c8e90e39d6691859b9bf2e57c407c73c43f7b84856d6e26266916dc7c640ffc9fec6434b300b43871497f680600603bfead9c4d1959291851a4e8adf6d7ef6309b37e54a67a129cc14de00b39308b0bcc499ab843d969442cd1db6443bd0c5945c6d36c965af3125be4c4b93f704e2d7e8767dd7551249775e00b348af8badad1e67c95434ca871da77910e95f0c6cfe063b4a339e8bf0fda3b3a1a6a05391acd34f29e94589398d351c11ef6405f9403954b7a1dcd357b9114476ecaeba72b6f902856df1dbb07168161d64b70d68fda987397d4c11e3e4acb52e6b34d701da68eb7af0bc5dca60900c12354704ab2ce39f67e6a98338a6cd7ecce590e6d40f081403ec9a9889271bb4372a5e01f700028c1237040867b6b60051a32e8729c0c4430478aa67ff8b6a93c627c40ea9d027fa2b30ee0e93b6f937e252955525c8091956bc31eb539b813cae5fbc04b93e4b8b045fc09ecf3fe79d1765c4d0160a1fffb36cb12e386d826e73807d004b3de97c96bd29829f5244bbe74f76118027ad699e2f66da9d318961e0a2490327f1d757fc9005ebc3008a4bec7946ef692ebbab986f7854fc2eb02773399106e21c6cd0af51a6da094df8b017fd943cc0c191df3b8dedbbafd0a7c3f74dbe0e4a538abaa4def3909ca7c6a5c93d37230237ab903e45eee6471c1e505fef8b0cf173108a6127e5017f75341f15d08947ea6b32ba5d91bed3861a83e6a7ed890c2ca1c4b1b48193b9b579e8ed409abd2b702d78d2ab03f5fb0c72758a28644e09f32a8099da4b6b05feb1bd7bf20720fbd5bb9a6dedeb822785dfca363f78ae0e53441b46d77d364118e5c3408f6a6675e1aef56bdb490f4dd95e91b7eccde5084bd5799f7904eebd47ea9f7500ef803a0ed0edce33921c8d64239c71115c61045b1507ab6b4c7efd8135ff7290f647a6fb6770dd44801386e542d6659ecfec0d301677a504c29389bea096f699ce3989174c4d576b1200737bf35187e6f0db0a0c16c7a6bc6b5ea500721d437e398b16bbc0818f28c47e90e2dd3d14a879ba0d14bf09dde41526f71019824eb410b74e43eb3a0e76677bc4fec5d20eedff200b91d506e90ed00adf535df746f22885715642bc425ad03894224160203d2bbb0ef70b23c6289161ad59419742f227294032a78ac7166ed7bd3fcf7faf7b2ed502074e4d17bad33bbfd31d8692238f43079d7d4fb5e92a2f74583ac0cf9be3df0e4c1c5ea6b5fb2fb41b6d0b2cfcb23fb0ccb316529ef6fb1feaa90025aa86b80069c1cc7a7a47dbd32d268f2afe7dc7135c9123a9a28ec8cb9db5b3fdfb2a820b7df382cc5b962c845ca92132d6e3effb5b7a78f12433a85e62693b2e81baa8078bf6df3ee9584ce4306668330bb7625b9f55e995640c839cff378855dc3e6605c376ba4201fe0c18777d2ff98c5f59f012d7471fdc94cb1f317e9b081e4b250eccced3c3e24f940d3c0e51f6fad44d9fbce3a3f41a8d44cea9c06a63a2c2ac03f24faf7af58de7d54f52c2db72d73a9f045aa940f8cf3e96718db99ead9ad40fc5ff99e00cc19fc20b0f4caae7f9f6b03c2ddd7c105d92157f094933c2d1b704a8a6cc52113a1b23b25f458097a0da568536995ef8e794a88ae3c88e49d92d08ad5c65ef8ec62c758a1044a8ef5d086ce9b4d7af97d69de2425ceea3c79939076ac2ae8cd9d2e178688fb1461bdfec2c4ded9b4d18509cd8d15a8eecfb8a730db1e6507ddd993c72f0e54a731fd6afa225e51c5c1483b4b0c6e9e51845cc1908b8ac8b8e4fa4f1bc62402c759b3c7b59cbd6d71baccbb1e883248f0db119640633994ace444814ab140804e9bde53c5a7d1279cf711f9c7eb3d47da09151e10d2addb78e055be6d7a1b303544a10a64ba02e2545eca5b6ff741d8bcc4db98b0de347f9a56997817eb627013a27c185ada17b4c027289263cc36af840f9adfe0d43b76ad46d668de9ec0ce7d4a1e33113786f935bc5c95e0d3d05c9f0e363b2055c416728b8e5439154becd4e8b3b4df2f418999fdefcab7ba80c3325a5c71003ddf1f3730eea84565b18cdce7fdaead6a99fc98bdfb182f90eb627b87ec28801f6c24b90d0d89ad5f90cf00da0ebe4bfd4840afc081c3aca0a661d93624e9102bdec1265399977d48cf0d3d47dbfe5ec96b0cd7c8b2fdca922390c653e49e70e73b23f64cdaeb13e7ead5e9b15d8122decea957f2aed9f71f7ae03d70c55640590ea267c661e816c465115e1a81d115d8bcbb950f7a375c530d7fb4a8c7b620cbcab1c3663e07803cea73f86ea461deab1c75b76248aea6152ee730a7d56fc0ded1735c98048cc316fb16a78f1a51a39468f4c1ec850d8c1c30fdf1eff11a207271485b81d8959e3211efdc037220bd1de4000daf8c4982a6f1c53f7e4ce230ce35d08b8492ae14f2b3cbea4e34ef8daaeec3498c6d6a5f7de06ae79e6681f079d3a1767d5c7bb49724d349729669a91e3e8fabbe565c2d2f5808a658cb0a906dd961a2806eac3e015802c52c6e7022cd2cd188bbc6640d4ea54eb08283df603d7219564eeb0e9de3aece5455c1f90474aeb37a5f325b9a4102ceed1b57dcf0e9f770a283f1545bbb5de7374ce4a751c131cafb631e371245b7bf3003f6bae06fe0d685e00bb81ed7d66ad9d73afd5b7a05d7a0782b8164e211ca69af3d89e01fb52ac96b1f71372ae54db73244c24b8f68b33f03c150a032969e11fb5fda906eaef3dae2226bcd99a085d1cd509b51d08622edb5474ace3fbbc8faa88ca3e0c5e9263a188698f82635b82eb665a354329a3fdcddc591a8a6eb737ff944cdf0ecffed76cc280bf01847bab2579d92d57627a835e1dc2c52280fbca07f849500cc3f056a6fc89df39055578335737c013350f3650811ef998617d713bbc1c1107f5b4ab46fc11a4764d111762c17f18941f8b706fee54537f82c34efed627690f4e83ab5a6b17dc0471576b2e85894793e635b2ecd2c008beb6ce0e1b1a750d08a36b81e710a24ada5990d56900937db3e471adecb06f9c78b20d8c0848f18009ad7e0000d383b3214aded17407b2920e906fb0a2a762d423a8d961b1405f790b5c549cae9be9294d3456642c225f646f35848b9ab332422248b1512eedf4060a40bc57df6fbabe3a57dde3382296f5e5c45a62da753cf4a42d623fb67283d5087cec9a68bae7a9ffcd6a2af4cac2957a4d7d895a1f3e51a0ce24c6c035a75b01e1e51436943b6171811e43d91329718041b64b81bb0f4bcf49076a4b8f8cfd007d6594bd937b6edfd0bd190baf6ab2a96679340c038ccd2f5194293a78e14d02aecbea3589f7a70296cece754f58d20d9fdd317d3b8b7455ae27e8c08df0e80afd423d75e311cb8364ab4404702b9f19d3be8c32cd61322309d929062871af0af6453c2a45dc99b3b723667358d64f205f23a4b9f60212f1464fafdf3a994e0f26efc55732992623186135bfb5ad53eb7b19c1c20ff80f1be94c0a68a2248108f16a1d9476e69b21d7b2e8e45237b4feea110347e266b5c12f904fcddd13810bc5799ee53c47cc9469fcc71d7c670c281dfdb37da2f3b590732fc8c1919697045d1a8f76003d5a7f1a0f519ed8a862cc4bf267a731151166089d74d1e033f00afece9ad7dccc774198a8dbafde6464f77498cd25f073dce5c6e302cb4cf23101590ff03ce9d837c1d853619f3c272e3f50868c7e4c7a756c251cd9c2a5d116071ca2012660b7498487d17fa2c79b98edf53b7fa77797271d76e057f050199909f343d5e9ffd52d98df35b722ae7a13c8b4f6c9c5e5371d0a988cfe7fa77a250cd7065407e6e7041668483bfc910af18c948543abeb6958928ab32ea024ab050fe0ac4f8e00b26e065dbd9bfad0f6bcaa43308f59b8e9ac87096073c5ddbdd90d14713af4b470054ee3bdd95cad78e22adb63f0bf7a4775ba69693ec23bbb7c05eb3dcce7e3ebdff42d0e828500bc6276a7ef75e61c992e7f573bc13004873907e7c620856a6d4d44aaf0e61520fbc2c59573cc01b7c5eb138d92b40da701980c1561351508a9a6f1a0289c2c2d547d63f294d01a4b4578dfea8b9649aa87b804998462bc5ab2d5313079f42f91ddb31f6eda7bcbbfffb024c04b25841b88780275fa3b145e089c079f41d6344fb73af2818316427e864438cf2b899b9a0c60062df1583e756a669d0dfa5f54f530ec2d6bb1777e4e90fe3c845794ff8c463b02cdf42992f50f6304df2bd9036fcb61b32abfd768033867ac46bfc08a90bd3f08c85b6dc30b63687948fcd4fe63391245ae8a83ff33d01a23c21d654f55d18a0256f2b28cc791159ed99f06869bd556621505805be8f151d00e6f0d89d970f50eb0b0196e9636d186eb89c989f5f2e3195d284a9961a5c35c194f87734bd9820d4a55d011d013948e7923b11d22f762459970cd62fd289ab3edc1f631a546da0675c7f877d8fde2341b3374c9947aac2bbf72a2b6dd59668ee1995b5190973d0583a51f60b09bd2f2668b47161aace20555905fb5f178d23881c688945686cc0056ebea714cfd75acf7d27038a622f8b8f319ec60bb44cdbc0a4e8e0e3b47560948a8d906f379380f1d4399c306bb0abf6473e368250307243c3fb62d6fbba50bf316c2981e3936b5518d4956ee8a460e33dcb4c40578a054ce0cf2c32a708c07edf12e999a005030e675a4a0d40760bea4f0dcc7e2cd65eaf582df22f521c50fda5e9236cd8f7d671ebb5edba063b5c6332e2284123c4ecf67760357be1af1079fb440483d44351b98c6ea0b3b72f44ad7618b252051e18ec27453e2994c4a05c9bcbc498113f6356c434f9f16a4f53c19993cfaa0a66bc2f2289abbe015500d27224389f9418db7a6dd306ebdb3fe1074ed221be9360104d2a3b5d56072440893830f08ae9942cba1f36cea473ca8265e87e3bd34de605e8344b6f92bcf970746ee8b5dd837f1ee0eacfc99f9811fe8ec8a2d7fb77852051148bf711dc6020c101d7ac16d28afa399868679d227eda9c93e5227f12309b17fd37e399ea743021b7ab1b6d2ee4f7fd4ad3af7dd2725fa6f4320c1464f428ee30abfbd8ec75c00ae16760df49b4d71f966be497734cde62bb7fe5bbba8507986b10bbc05a74304fdfc3e522287f38806308a06d86203aa211db6c1fd5696ff87ed7c3b759e86059eec15dbf66326e00a5aba1d140d17dd3a1f97e2dcaa5036d26c977d68aecb08d35b6aa339bc09d9e46625d1e7047649c3170a557b7751ce32b77ee74ea0d4050f1189a1de30dcbc65530960ba70d46c16e9ff73277786d8d2945dd193808b0fff56c591cb9f6462a6419318037aaa0bc356890f1f4042f7a1743bed497db100755dd5a649430e5799f055baf7eaff72019ebb3eb10d955c56fc6324a8278105b6a0ced3c827ff6bdac8693bb5d51926075053e957f5167850b7af7105f0a80fa69e67bb13f411d66f3f0ad07ddde933db701a1990f75b1fb5fbf1f93e08e606d369c896b30d39166544ae7e19c5b0a958de00cc2f403d7d4a722d2813f60a083dbed9cf6433c5338d10bde8d56699f89e4b75e255872e0b852de4a0d758ab0846301f7f3ef92152c9dfecaaab1e5b253ba9ce3beea6a333cedf9d6afbce19030ae3377565ea9293ad5885a62fcc86bd9ad24130f7cc2a21627f701b64d4fb0dbbc9a1917a2bdd7e386df85d054ea4b9fe82a71e52b7e9526b9c75a4f51e80070ebd5b8e999d6f1b11221f60971d1e8793d15fe9ab02823393a413018e36350fd4664808044c50c0c0bdfc87137bdd6b6afd6fe5d6527bd6308d31aec39a1409b7327171cf05654b9d80ece30e546d605e8a5092f1bcf7a6875ff29ed7f71a0126a767b8996965c873d09043b4fd2a26023981b8fc05a91ee91ca9bb790d6907415e9abffaa10eece461b2e4bc806ef718e6584f81053d4633cb53acfa1512068e4c07207ed936ed87679fee574a64492e938dfd738813ef4ce02c01b0ea77087587bd2fe291dd0adc371abb2adeacd97de12856fdf3e4033a12bcae71388c0341b82dd9544ba729bea1c0f3e9908536c00ca6e08babbe1a82330eeeafa8d106f8519dc2d530f15e2c8b8c7d20c705c428423c560e036040fbf15ac7636ecf0039b4ff7bc87a3a459e1ec7367f31ade3b6e7cc9f3dfe8405a8758d2e631e9202a33e79ae93762cdbe2458636ffe68c17633d3b49192d062f26daa713e179d90a4eae783c5ad5268d734d65278b26653d564eeeb580ea2123c1789b0752e57d07a3a71d2ef9b0ca3a29c962537b086ae41936be90768a1398aa4c7732cd15e208536fc831c214d9863f224f4c4e46badae6766ec704bf54e4aef06a720900ab045c0628a1d3dfef4d6a60e442a1db1dbaadaf0440b7833d670a515df088949309ca6e9b7f92b8f7bd0af0e2ddcd682ea421c5cf7f93df7fcb750a8747a3ee0c09f46ec265095cb46305364d9357a2d3b1bb10993520b9c54b78649f6e65c8d90c5e700cb96ec53b09cd057cd4265be224025d4a5bde024144e0f47ee09e2af7079d6445e4a156ef9819ec938dde87990854fb2d66c7bbbe7c32f8ec316d0a6d0b945b43608a0bed2b8f792801f40b24b9126df545aab60b1c0b7cf63ed885ec0743995ff7bdb55a930d8896352084cef8b3b94313db1bbe966de158464ffe9905bc08f9b7bd261f437bd476ea4d4672847de617d7c1910f525562b1b17f13360496144ee3e8c93bce388cb9e823b98840994692ed5d249e5533a53a581888f20813f98c7bc7ebd3d35e9b481eea89106ed53e1c0957f6a6598ba7f1efc6917c092647d11360121667ea91f0839749ab84f346a7f35c3cfc06abaf7186ddf5fd0a3b75cd676d0dcd6f2f56a1ca7a495b625b72307443dd26c065eb41468e703a07aad60f535e2e7f060ad8a101788fa3a9d0c1fd19d3472cae3a7e50013354d407ec00b9168e6dd72a87ec7c241e8d8b4a87b3c5d5630a684eb5e2c6fcd928bc01f0c195550db9795091c85bed3c8d12aaad12d3477a9b157afab9be4fae8d40033f55dd084cc234609d3cf469aeeece5d1eec7cced0c4f27944b2d58a8b9cde0135925319d6ebcb54325a34def61354e8c17b03e1c28f7ad2f3fb4a83c0f7dc034fd27c1125cfa56c1c9e334750c2162221e2db0840512dcb4e089b768ae2fe060993029aede6a16eac47326a5c1daa83f3578b58e52fc36ffe0d6034c6124b0bb59fdad3bf63b3f731d0a17344e9a3a9301b983639e8626971dfb2700522e404454ef5e0a40a579fed42c423bcbdf43c08ecb4ddf0bb647986640eb7f6e57e0dd2a02b03521983621cce0be340bcdeb03db94adc99e9985534276f4379fd04026260bed58930f997a461f24c131d5e689c4ed4213e28af4c28afab4e0f672905470b7e5d4201ff7c393fb3df17d16a6a744abb39e334522f283d401869fd8504dc00937235c5ced65fc1722a3ee8e6518ea38ed597ca8507eefe6a420a5fd408657fef85d221e008b156af68d2070e40c8a447afa34c90edd9daf5f9b032490e1aa549cb38764022680fde63bb08f49c7ccf42513349ad93141543eb8723c4057492079215faa1e457e41cc85d004fdb4b749dbfba20aa639277ec5ef44c360f98793539d94f2efff4ff9379d0d53fc891fda3df5a15aeb1265c77c916e60705d5f2fe58ab789cc981036da296b0dc311cc30ecf81c63479a68ca5eff5c6f201bc7e5b7e533f53512c6269a99f0a01cf95eb0276eb6f2b962fc8bcae02b38f04b23b890dc9e0cfaf7e47d39dd6ada779f5fe59230957b6020b755fbe3efbad0ee1a9cb4f583bf144619ba1de7b8f6f02b83ec26f00847454a5e73660cdfbf2048b5dea88a03869d90bd2596cffb17a074871e553e0e67078fb21636e0e13e9019e7a3c3239ac2e3e2137193d002c3fc4a593449e6f8a6ea25f05aa169bac5d0ed0babf744ab79d3dbf1475934fa02ded36b7b615f924d90388bedc13a8ebb201076da73121f10a3f12e13b41284a95469335592463f6712ec909f1a568a1fd045b2a46664fd42a8686cc65b674395e3c6104f8f072d6f08fbdec560cc0ccad0c27a6826bc5546059c982abd75c4764d1c5fa7d90a8ece40521564dd07f257e02554a8ec68376fd1646056b2887359c1001b621f0235fdcebcd58932f069a12012bacd07c0aa0b78da0fa952b9551e5e5223e542780dda3885a527d82a46399075ef0697fb6087b8b0530de6e85b87c430080ee788d965932028620aa95a7100392978c3880ae3412c57fd6bfc7f21821becfc968b4274398d4c08b95b1f9c909d3e63647833eaac1bdb43ab9598716aed4622477718aea434e56589038f7f20e4e65db948a69e60eb24ca706a932ab39aedec10ce00d7652c23cc7578f41d200c9082fec6d13f3d74b88cad2866cdcb8ceaf29d124516923bdd7ca930c2b110799a8601a0c066760d721bff206f60d317a9c4aba466021ab2a213c4e70a5f80bf2f77b6cc0bca573ca1d8b52f40e72df439339cc346008dd26934ac10ca05602386a1e2c5905a97f5f76671cc23bb6e6045f757998c424b6a1ce77ba0f04ec03cde885e541be8aa2f0bc40d1c067d9857e15ccb3a7f4c8352b33e52fd7edc907a84568508239b5dad1d95d23b8927605345946bb7a295a6cd84152cfec6ece056aa39f2e95dafc34cc7b550277db171d5131635b2285e24720478477189d030a16f939a1fb74c7597865734a88b0b749365506ab1d7a078f8ce2dc946ddd310fb5767372faebac4d4be7118bdb91fa58378a63eb703285118d2675aaae777c0e236ececdf98d69d79a414f99a98853f94a4ab5e13223cb1cfb519b3c127ee307c435745533cb3d016f9908f48bd6340c994a3626da9fa2bfcda0968d526ab60887446cc871a01451bbf7dcdc4c91f3d378a0a29d5e8f42bee345f83e5e6643046fe23634b2ff359783a20d94df69ab3a7c7d9b89719c59de941e9fb229e6e80cd71cc4c593792ce04fb9266ceacb39d758b06daffbbc42e4a247d75a0db17b01da1e94a2a1db829d58caab5d25c9c0f458c93df54314c7d7401a25e708d21c07aae4c196f17ce2ed2c9ed8fee96fb6c9b1240afcf52ff1666813dc06ca35b000715845bb324b326dd5163d08c23a028a790f444a79e51a4062df5b395ba339093e1449fc3afc61a5cafe3eba4bb86502cd0cc9232920319bd6b1a24de670a807f6d2969409ccd8adde436d72d92462849eaaaa04fc0e24880060d63bfb96c90a672ddc3af84ac3fdb64a21f908ab54dfb7ff5d0148ab8c8617d331130274840b5bb9ca4ddda77074f85060cccadedb0e8e424ab044bd34c9043d1c29cc904e0a40a07c7caff75383ad205f0c47a1b900b665f22cebdb653f506fac082fc606080db48a99756ec03acee8a9ba52f06fc4598a94e4cdda110562cd614d1a53fb0c9aa5a1939d3734fffb2b04dd91ff7212ae07473d4a8024f52f7f9d6c4de03b0e5239012fe1a1ae1c8fb53718065db6de23a8f0e3673897c5ccba578575528a0ad26be05b95b4b5a703841df12a1156a39e637fdb2204f4a6f0b8d940476f660f02b621bd71520e66c582b6c93a37c24fbf1e4076cbcc682fe2f122a12ac9ba0fd7560ea6b1c8d83a032e889a6a4a900435c1b9c6f7979ddbcb594da8b928b20767731943e701dcdc050c02fa46526165b82e33b37482355a3fe934996afc2d03830a73f490cbbe876a1db7f2b19216293f240f60654c50c94d3cd57e5b5668026919c7d8b3730af368b999e27b58a8cf2eaec6cb80116eed284952a288aee50d760f6f3b4ecfc82784961852fa301f8e71a668b2c5a9198cc302ca6599b0640cb07a49c71d3fa0ddb6997ec31ac9cefe4082433acc71c928d7f461123c4dd30d73a6feae954222c711c269af99ae40f048e6f6b1cb92db3ef82152028bec1b0e9618b5e0b0e107865e0012e3dab4676177e1f1c9a5f5e67238e6b77c9be2b60c5fd06ff0a2d07d388de31772ad047fe42ebeaa4a6d9e2814462a8627c4cc7e0458d4db2d36f47ae440dcebeb6b5dedeffb1eee50b97602e06f14c2cecc56570c3ebbe1256a85b1fa9682cafb31745cdab5278a1bf0c41cea863ee158e166bc004f39c387c0fd9a4716db7780979259d2db8458000df4db26c84d0784b970fa0cf5f7532bef0bb545665ee021172362e7c5a68e4abdc9e0376b323953b31daa0d0b0fc9ec34a2d31fc267fd3eda7fa743f15567ff331a22baf37acac1a1095604ea5a898cab0cf8dba8c20bfd8561827e8e4589e746b53dca0795e2c7c172a1005e4e552d34afbe881e9e0769735fdafe0d237b499b1b417313eb9df1fa13950e369238dec465e8a261ee192f7fecf80351b1567f5d8e5b5b9409127b9ffc18033e1551f94bd2c3d6c2b58943b0a335e78302dd72023ad77a4dd924ad5c55bf03b4036c03ffc45a5c76c4b6db45f2455a7f862e34638613fb85d024013225ea0df500f16cfe58e7948968079b5fcb588e4d9fe8a09afec7bb70294421d0b16206cd4f32eefd342a3d1742451fb286c629b4123c400b36add8914f3a3b0b17cb04307a6927d6731fe23432697368b166a9500697f50fe408ef56cc5fccd94a740a42b252edc5f4a8bea37eca9624bb286129aad3b3ba8ddfbc7f20dc1dcd0a430319f7ca59e8d4059d1d1d70284bb3c53a7dec8e2f3dc6f58a1f1e95ceb21ff90bdc35f9603b44baa41f6d137152bde5d994512882bdc71a80590ed2e3742a2c058022c0300523497f0941efb90d29a7d131d9bf4e75eb1cb7ca1960ee565768075172fa1ac29f3dc07a322752b8b5ea95e6ace26d18ffbfe4dc819018144c8c0dc49323427ffb782769c40a757f1f6253e40b15a4828b242032c7c877227bf0087e753e620da8dc3db98f83a1c76691ee92ec7785110bd86ea27f0df26da06f0f2c862d403ee510de00d36cf6c402b55474fa4e692a061dcd552f74e7c1277d05174e3243ecc50a10ebbaa57704f28effd9f80ff94a4119f2ac8ff5b1e0f9df0381a4598ad2d3e3d0a017e01c7c6b45eff04546ed910027836e316c92541ed104d4f47faf3d3599dc33527e144e0f5c123b1d3fc565c488166f4d0de870f9530b54c4836a0ebe17db565526d226e44d4bb53d77df98bbba7cf8e672fb35ab6d0c1b797983dbead52feae83476ac04b62d1414939bfa03061550d6843b6d0a4d04ad2e73d359891b09a6a7ccaf99198b572808a7ef52df9601839a1fa6f1a70d04681311c2441e0fa321d5b4aa34548a9e1012254c434818cf076fb2ee5e03f50d086ae081b87f1deb29fcaa1c08c791fb24f7bd8223d211abf914aa04a325da00911ebec8f4d5ce3d127e733c6143817d814810689d68ed1cdd24eaa0eb3ab407d1b7e80f7af2a88489a65e435e08cfef4d6058fcc75f939a834fe3260c8b3d0594e7a76381e08be446ca51a6ede565c4ad05a2699d01cc6c7f393d8a846d850c20f44e5d6549f89df33e19ad41a1afa9dc7d59f776707e5f2b9364ea15d4ae098c57448f7d38a5e063778c2c7ee96c22a1fe0f4d6c9d56b62deffccc3dc5360ef84c8e04edf660cc59621d029c355e3b0aef571dff402eee7ed4cecfb5ab2308c5ac8c492ba2a355283a9d6661a657c496d97835c8d14da3286d04b2bc874f01ee2e9137f43fe3439f34bf811e0953783cb371be6a40fca756c18413afa6a70af73758dbc3f2bcbd93ee32fcd504fb13b2dbbb2f10519438a7fb7284edd4fd0daa36e280d6a3c9e9d3e5042e99d73d921b902f2a6c863b065f40d4552c47ee0cbc9ca97b741bfc8e2fac7a21707cc801e68e41609754879e776aa72bf6831f0ad2b8adb9d7c1d6887a34f38ec0617155001d1e911b943324d309bcf562e36309ca2a29605219369a382eeaf2a14baf763bf9d0e46ed1da7624787659fcb1d50e8c14a9e67dd40bc9ec9e23f0bc4847e8573317a3bb8fd1a052d6b2e2d3598d0ac2c6b0732524d496d6d093f36493c6a82d728dff3b164deb5de2577c11f07e053e323b7e6cd815c13cd07469bca408f02318ac8d5e540a6cd96be9a2e4498e0447980bd9f9dd5aa803dd03ac334028b0eb4396d750c5ce461dbc15f9fa2a2b06e9f5710384dec1ff5854f2abfa8181fb5a676b70526d72a666bcc2db617fec0f695ea529fc0663362c471ccfca81a9e829546fea5c035f7e8dc412e8344ec90484e175d0986347f0c02e8b9e3cad695a985fa31ed708682a8b834bbbd427ef04450fe37337fa55084487d0cc9c459b04fd14508991410ada48c546e0518c0801dbfc8ebf6396eeb8d66f7b55251c009d7474cba53d2a72a1fb9981a6e5ad5a09620ae7c1d71b4b26a95989359a2bdb7a59b1c97d9bd4309d374acedd522f090cd356d695b800728b331cd32c37d9d6a709f34ae55a8c6fc7b97b7c506618b0062a4c349504beafb6cd3359ae2b27f8256c6597524e9cf287d9344ef9b790c804af530d75bca79d1965127ddcd1bb79f13077c0f37790fbe18122924817ad860ce1dff09feb06d942dac26d020a775f95fdd4726c762bcbb0d8c399216ce9190469540f82f88ea7cca298b721ccc3f0f5578aef36e9b4c6473fea33ca06e875012f2b7d40f2c48feb2e42009e8841f451db2a5f23ad6285ed2bac2792d77e540b58c337ded280fa8d728401a0d84c4d3186676c8f328a89fcb18c2086885b8705473dfabc0ac481a4bceb4c144187e1f3f2a3fcfd6840aaa08b389696fa4f5b0e0bf26019b574c5032994992e097c204fe2c1378b9f3b4c52e65a076b90dab6027f2f2ba47f96ddf5dea8f10b831a9f4ff092b020ba469178a7852caafa341d0a67004b91e4a92e5a18b9d0c962ed6893211ee012be6ce3a3c704ad4a70cb950d71c3481ebabb4125e224c612e4d6550c8ab47a7f34e1f10e5e27d8d6705bf30f41289c66ee07f12fb35c22161cb8d216e52c87bcbef8686038f31886e4e5d50627f78267978183f3aa5e315bd5e0642666cd56a1e759d1ca884d205c0083ff07beed3d67b4ee1c17ba52ca73d0ea56b967754f223b9ede1f3c57f439e41d930e04de6e29216be06691aef455607b2c17dd7537be9baec2529dedf1586f5e90039c8788fd3fc9649a081ec8dc583aaf7b1ae5146935eaa0b4c897be88ea5ded017a51fe4f4c3f7c2f8421108e0dd2a610a9a85ded2c4a0ac2894a6c7aafb4bd042baeb387495fb151484f6ed0200a2a5941dd7b2beb0140beca2592b75cfc7a0a69922de9e6f267bc6a69e05a4b00ac20bcbb6e6c986bd32dab570eb2a3051009c708b6dbff220c6e0e6e42c1abd42084ec51c4670ecb8e501d9f1e8e73a7380f973586555cf862845778794cb465481472141ca3fb45770a97d079e0d27fe10fd20500fe4c2386cc425bca4fd5a51202c38943b3be428753ba5daefbcd6a7e0580c20f4913eb9fad486cee11637ec662c254cf7d3f4e0ab008bb8bab1f59e306d2b417d3548975f449eeeb0e73038da0c7a051e24ccf268a3a646db8e734d80e6dc63ef3da73f8504976e10de048f599be95026ac79b1508b2c85b8a57875a0d8085190d2c0bd903dc7d3d8000ed22d33fdff4cc0b50741ab1078cf6a15e4a094a006cac29f11e33d799601103a19eb1517427793e90e5fe1a6c21a3758c120530ab91beb030ec86aae1438a1444d1353ce07c6d2af53609b186973c5cf05902acab15c573ae94611b0c4970f1ba03567a8bdee75e8ee200096dcf3bce228503c7b826a5685d4c50e06b6693683d9d3ba36ab89989accdb020793f9404598909167e6f5b83e0cfb4547a3dcc7dc81c0a76716530a2ab6ec2cf6802cd09425303a03dade9f4810517b471d4f086132200b5445c590b241bba071afec7f86e0f006b29329e7e64905ab8bb32497d8d929e45ac441079d65a76971d5593dedb8004eb42eed62d4fcaff967dadeb4a53bc07d518d487aa04a367396c51861561090e4bdec5bafe793d4aa39ffe2fbc853552589f3f80acecccaa175cdd82940e450596cbdc37c5b1c3598af49da2e509f88657aae137b86153f5d296383917f39800bbd46d03c138269f3f45d3559ce8cce7671a0a4104fbc7c1b1ca1c1501a7ce06e37a89865aaac6ecba6211b2fc80841f0ec430cd9df75df232f65d59d853200473f878957243105f545b1bb91afec1bea9dcf0c84fb7e117582ea2271222520940600d19da80f5d36ed73970cbbef20fa99c2c8fd9552dc6db8b864df118840903d310a43c54c946776d6b822deacb72c3836ff77c14a198c091aa6c2e6fbe09a8e2286691a9128ef32786793f4ceb75cb5378aaf74c92faf7d1452ed95b9b0b4e9c19c1e2196426f4ef36add5586ed3d65fb7a7708ca8fd49465a769bb7e609ed86d9020b4d4246cb53c84b63f93f77d5eca34ead1666dc19e621c5543e88004842bc12327618386000a00967376ddd74ae0e5a6dce99da58221204e8e81108df55619be27c6a64f9c82f97f4b4004df09ec82c3fa4ba43a91f1770d2a9ac0c89e5a50295355ee8f53edb968f8729d4267c7c0fa0a1c7bfc929acde8f861c0d3d3d1265f66d0594738f7e1828bcb560bb232b539d3740e7dae5e32f024443095c0d1749704aff2324c39c4b09c7f3ed41b333ef027e60a69cf23e82c82a6d0ec4045d7c0a4da39e3e1fa88b1365677be76f3dfa2efaf137c4c541d5f00a8d004281b3b8b3ec3b41112165032fa59de3c026e67b0a8bf5ff2c9f44356c54620323da07f40a5020981133c933ffc6cb61bf3700e2e8b59edcb79ef28545ed8703fac42e6ea66625aa8e0b82eb39c974816818e7b0ad12b2647da24aa98ddd240a7f6b7322379951113a9341fbfaff02716fe2f08e50304aae89388aeff7d44106448e0820013de42853b9553577347bf570af530e26795971b1aee9a75de92c0a310af83a427ef41a55ef224a49d600dba2ccbf30095dd7f56149a3dc142de20c9d91dcb36b467b6ae0b1b12c5b47831307a7ddcc2967f5573b589c082497e709ba99cda53215192fdd626a09c1390e83e7215c0d3b467aec4d4e2b30e5874809cf27af46cb2708e9c81e0e5c18d41a5afe263985aa658ce7d285cbe7845ecf02d110edaa9a26bada55c9c10a5ef7bc00a66d1fef26df48961faef442566faa0f29929d3c2a2feb9d75b1853f63c8aafcd12148a674b0066d6f26c6f167770d0f6916d0480770ed37fa4d6ec3ef29ce67bed101124bab55b824686f7a5a963f06ef285dc6831330f62f45eb895896f15c3009f85efd45e06babc216e52962390b80eaa9f8b9d0005716305beea0852185c507b09d391090fb75a502a877981e00811f18d1ea1c75262a4f538345adf2b98b2617dcfc96eeb09d0c8c6d627c220140247df13d122376dfe1b764d15d6faf70dfc7bd2a124aae7629308e576bb00817c69ac56cc8c835435efd1d83df31d2d71e6c1884cb1e8b1de6459b3c83a306a649ebf25fcca2f0df87c69eca7ac637d1c4747b13c8c4824a8b32129917f30a7f41cc4c91a43902ef40f8c6d1d7d9d6f175e5a70991c2968d1b62f31493a8001b697112f68956049c45fa5a56b01360ad1ab8ff8b446c77fe30fa7b3b643b08dc0790f8f8b87f79c5c1a3d9752c1ac373c93d24edc2523455629f22c8d6c20a52746944d3806f1f817d75e9f78f113c682426155b8a5efac535d4702ba35a09bec613ceb8b2cfa2f838701e22254d7a26cb144b5b697b3e2a740f238fdf450dccdaaebf4568d74349ff1e5e8c9d3a902d54f6937feb0b6ef8a13360a43fd9083abc2cfeccb41f575fe2a921dfa6f9a4110e7c37f1a1e78aca2f70602bbf9e0f4c5d82f67040c22f736cb0715559821b5f1587e664ffb12a1a8fe8b4a4c1c50b5aba150696176d6db6005c6287a1873d16d0d3db7b9d272d6da1adda52da3e0b49e01203b84fc55375730cfa97e3d24ea648442482a3da4d6629dda8b9819e02ebb4a54385958db14a9c5de6636d06b13af64026912dc6bfd9b339c2b0c6e900ebadad69a2e0e312bfd422c36277e065ff78c4b55b1ee67ec903926c8df117002cbe83c440ab86a67c6ae8f1b15ecda6562daf53bc2bf22bae1308da10ddb4018c67f590471f05a10159410b47657618fc3e70917a9379c84b1aa1f96494e708e00fdd82fb759a83b4e741171ecb6a698b69779a17926a34ebb25a04dc7f48082b8cb38b75418689edc8c2de92630ff6227186edecd1f9f363407ecbfa84f40752224f589689e896ddde22cc8efbd9b5a5fde3387f7eb9f569d5e3234181e4062e57845ff75b0d095abf284e5038d14ddc0bc8ebba5637ea7a6068c99dd5e105e781c7cad2ff62c2a06c866509f773865328d8cc85a86221693c4a3df3698d0828411f79573139717be4a80f2cb7e4ded5a68e3a95eca8963552fc8425f696068106db04216602e3f197a14998db49266fd0087d0761b1efe35279d39a9ce0002e6f2807dc15ffd8e5bae2e38ab7fe08cac64a7698f849ec44d39b7829cbcc0abaf33881e0417f41fee7faecab25ff830fbf4355c2c125f3c2c0654dece8fe0a9fdbdc49bc8df5c8086fd7f6033e4f45a2ee6ddcf1417a6493229d666f324d03eef5dd9de38acee97a42a32000dc89586f5c8acd42519d27da5d6d41f355500cbdc78451ee62c158b09dc2b901c92785ed550ea7dee29b04fde0d5ec993bf00f4b1deecbe41987ff73b0320efc8488e8627ad075872eed9625ed128a3810520e5f90bad449f005dc829ccb99e00517620295bef693658ad2c792398ffb54360832564d65ad58b252dc06461e27ab42f3b94a6a60c63246ccddea4774b16313013314413406c79ae195ab6f421694b95f9dce505d18d2a1f8049e9c50212b2d058f09877ee1dc51f439d68e6aba3a9f53bb450c0c13a3dba5dcedfa7abb04ae00eb81a33070e893f6a3f66a9b01d4dfcc9384b5a58afc607e2f355a32b318e40b78f5c44671c1d834ebb7010a3716fd99eb74c612f34ca5049e9e43328af9060c6fc468e1d0393b55f0ece74e85a57a9ac59a36ea58a9d24de69a6b0fc28c9e0dca02c44ce19e886cd19b33c3efad603b7a7bc527e0c7be1c2cd823d6e3c815069144b0854bd80f27fac1d308688b5340da080016139de9d0b43f263ba559cf08ab63ea84a85cc3fe52f91b04fcfb728c848888bf3878e5ed730226e370ea1a0c6cbda91b0c6fab36c4d95148c335f0d303a8b7ac42b0a20f80aceca2481ff50b68e1abecc9db05f21fb9fba04a47ebe94f78c51049fd9619db5998047525190a8e989f7b4ab4d003f0c6f6dc9107a1b03882b287c49259b0ec38998aef62830176d6524ae19c8e1a19d19c787a1305d2145831ba455a813b7e29692ff293170b918c8503d216b7f88f05cfbd7ef20bd78a90a1e353cd3bf78fa0eb66869fa8076e14e5084dc6bf07808f7eebf07ec1ba84bb965db016624411f415b71137f80192f28764d765f748746652f139a328deb75a7fb08b39512137f888eee5c70009a6129f5689b787054d399df0238a18429d60483304ecc85984f09b124de1e10d6cc0cb0e551109c6356d89914cfc84785a6d951fb094212973d76614b85fab0216f7ad1cf97673b032d92d9a5362326b790f5c45a0f9b5df9808385e1dd08502da953710f6c7e31ff5170333cf40d30022e04d68e917c459a9329c2c8a53c1071308733466e8ff9cf631d973c14838dd364a1e0fe77d6277351823d2e5b0ce047c6a1ce56ec2d126d47454ec6533ad0ea2b121793234ddf99595c80777144c07ade44f3d81b2e26634e69da5b29e52fd7863089d949ba5321b5faec4ab3a33097e440fdec037f97a6000acc5372b09011829a16dadf9eb7dbe5047a5ab28610c9a04267e2e622f742dcf884867316f4135335198e67a4ec034437b8e98e6c107cf0a537162d7a2f0249076be0c326f6a4b9c7c0bc050974287efcd3213509f0d2743d2399bb3e987ca46593e90513faae5c032bdfb5219ca96919bcd57f3270524c74afadb045f3a36e0cd1cf68e3bd68d0efdafec8b0d56f11afdfb04cac704c7365a596c169fb44ed7d1fe690c7150c82aea164557d9bb05ee53ad3cc14107e18afcd2f153733f296f977ba883111db4bbe58b6724346cad4b7f720e191f06cc98cbf3a023206972f9f821579d997a16ce8dd7a77e04324aa8fa8fa65f6e0c8cdbd1c34f64ab225f2c1ce17615cb049c452882694934bb23a30dc722bb0903715370dcf2cef4cde7db004276474ae36bd6d244597c0adc6c794b3e1ed707000fa82bbc98558714f01c9ca28c855e1a3ac2ccbdcc090287455383a74022020d1be04a2b5f7abe2850295f49e7c180ac8e99ac4d7f8626b997bbeaf2db4b7c089f445b634f4e51d96b9cfc37fc38fe84dbc2fb24c8372cfe04fdd54f03d45c0cb39d79222eef1e5706d32eae767b0a68d5915049a3c583e16243e0a5272a7002fa9759cb6bba23e2c2c041a87bebc1221dc3474d609803c213aec7866676ac0cd3b0bb9f4e360c5d0e9670e5e3ef6ebbe73fc5b9e82b28c0b1b53fc194d0940c08868b1150303566229a9192e32bb8bca9d3ff8e0d240d0745895f7e9a2d2401e2d70008ade16084f13278a6b22ad92af563fd9c709af36fb9cd8e7ebcb3110f7b2762d32a2c1e1d662486351ac820b32adcc80523db3405fe448843dfd59a0afeea65c2ef6271e374827ada480f037062b7a0316a1dc8952f6fc133199c280544a125457f9a001a45fa4760c763756fb9ba0acbbe777b429348d834f5866d0b367f5de43deabf8aca9682a161d204ee115daa3e22d1dc19c8a981b4eee804010b79937bef1f78f3cc581ffd9991f87b3349dcdc69c1d68bc673a6464e39710935b3eac50aa3b85fe3cb6ec793189cc617cd30eeb5cb57429281e69961121d09fcd189c24fdac0e7b9437a43a68c76a4f7529d86a872fc8a74b1b666044bba0deedbfacbbdc6811a305a8e985ffbcc4f75ef1aca4642b624aaddab2bca1be107a2c0717a976c1408a4a5967d14f369af318ef0e1e14e2056eb12324ef207310c863bd9421654e802e4a5f90f8899776a984de4dc88c43cd69cc4163fac367c0a3b3a1eda93a52457409e7c9898c3d63cdc7fc5684dfc68ae8b75f11c654cd60bd595e06bc45f6975304f88264cb6ea76fb05b4529c246feaaa28777dcbac6601f27af7b803bc7d2f66888772f4eda421d26979fe2c69304916c26e226a01cf080275ea176e0bd2df44e1bdcec64bc63141066b87d055ea85b5344c08c314d50b11359d2c67d80aceef4b984d08234a4b881895109df15412f1ebf5d4d4355d058352f701c11756a476fe8559f6b6b30307fa96ca39f8418bd8268550a1321108897aed8ab31fae2c6e1aee769577323e33bfddb05e4a066fc704c6fab6f3680b2ee0891f61e1d827659df21ac609340e17ebb73a2f7f270e54cc65a84fb8ef0de481f11a136fa80c18b7373add3037a737767c8cb30f314d9eded61b35813f098ac2c7ce53216a76c6ad0ac9c20c5c2f9a9aae534986f6efb26df8153f4ff102ba0ed11b06bef078241b195412f44bcee5633432ebfd0dfc8791c51dc16cc002553b32be3f0879e82607c58b38517c4dfb8acc6dbed3f63bb0805f7854f6200a63c90bfb0e86d61ea69130358a6a3d24e0cd991d448dab0a8e24f2cde55ac801765b7433b15b5cdc2e351861db5d4a01a31a8c76bc9177e01871e7fe832d540f82b1617ccdec3a44f6b2d610655b10c04063cc243af1ce1993e3545d82d02b0a9ee0795ba84d22eea67d6113cfc3e756fa80fb4dbbafebe7ad261b0c7d8c3104 -generate_ring_signature ff48702510ab57e5c8d1b6e81acafb78f7012e10e03ab15b0f1827ef34042dd0 82eddeb24599f7945a021098f99c7a1cb6edfeaa937e824e2f529708dc25ea77 1 c2e3e864568b78db05944261bb131881cd05c85c69033962d3c4f7e2a25a98f9 bcde8c2f9402b56df766a132e18cea4bd2d2c70cb537b599c2e829b7e3af4700 0 c571742a37be6de025f5ef62548fd4eab4bacf2c20aed554fdd33d105a5f4909084bd42a13e701c9187e2981482f72d75acae930d237f7f56afc63826748a30d -generate_ring_signature 417b4e63adf44a5a461ff2ff030a1757fd342e7f93ebd920c25b4c8e6d740187 bf738513972b08c9078a1b21cd261df99f52670326ec59dc94279e626c0ce9b2 2 f204e5533b350d6232e62308092afee62c4ec0f4fce45938a2bc17ec3bcea3a6 50ccf363fd401389de4f584b3597c3893faa78316cb8799ec6c20a37596677c4 a1bffbc16adc7bbed80ece0ae2b4978a0b3325257a96a7e3c3c097584d096e00 1 0059dcce443421cbb13458781836a8ab1d64451c83e987d7393abc34c198fd0a79af78da553af13701594af9f7d49d9908487cd2ab7326f2d267951293be9f04d0b0649f4c357a17c6b74eeac81b0c2925f513fece6769b735d5e1fc91115c06bbfaf5032d0055dedf834e13f9107658a05e273237320f3236e0b0237943ea09 -generate_ring_signature 030be7e561c24a2c9a75cf63dfe5bbb49addd7023362f7688d24ad9369967bea 158ff2e128941383275c97ac9c0206450dd2f16dbad1a0f30b045cbdbb76c2c9 5 205a0dc801db4e3d217a9a9e91bad16ab78ef983f799b8364ff9ab44add8ad6c 0a6f06fed33891ad9f778c3689968dfb1283af71b48c1690dc941ab115ef4d69 a19641d3c2804dd2450d313d1ab0ea95b16c4cc1cbdfebec643ba05604625dbe 93bbc7d65e865f094d1f7e7cb5b07f734016648b7d3e104db00b0d8899d19e8f 68e6e3257e7e974b4ceb1f7c4461950e60c1e5d1d8e935e02f4116bf89f5d842 0e0e85834add085696b849ea3ac806740cbbf7e2dba4002934fe022efe25f60b 1 7245e840918957f7a1d4ba91b88f77b7396af9d183a5f77add127919d78048033fac954ac51d5eafa75871446e071b1ed2c4cec22a87f3b764b1169fa52f8c0123b1bac004fa75a6960e34171fe44525ff7a091f47de2844eada697cf0697f0cde7307fb9985576001673431b4512d11977bf10185a75eac5c7814739a77680d7cc2d004c200dbe824bce46d848de436be9f4d776e628fe627741d1278292b03f8d325e471b62ebe4de12ee5adeec74333af0ce3ead8dca6678c41fd9c07240624a0b7cb1a7f0d12e76721976b45bafd3e73994edcad29cdaa468fc0b538a407fe640170b06423d575f761b003ec60fa058a896441456b112abb9f253abcf103f5519579906e0e0d11b7c4f2d93f8a5a7e50beb53424f04110c47caba39da10cf3bf5d06cdafe550fc5e9bfaf9f8b82257197b8bcac41f3186e36ae6f743e10f -generate_ring_signature 676d9d3f03cde540717f27be188a1f3f089b9de4264a66906be09441f3910378 1b768edfb4e27ae223a513c913ca9122e2da6bd2f88efa1718149068e6a000b3 1 fdb9b839c1c33c111ee96c1fba14a6ba9aa851737e89a629ab9be2c215c1bc5a f8eec233f256d39bf9d6b86bc1858e47748c5686abed539c8c44457cada7b202 0 f8c2b4185fa150b774a465cb1abd8d82f738ea939bf12cde5873f158674f2c0c9e68745b4093c9c4adae7f008da842cc62d5112a9714a6016efed540e8e11200 -generate_ring_signature 6b1284d1a3858c8b7932de78cb05afbd1d97616929e31905ba975dba70d7507a 4ace77c3426f132a65348c8f2abc450307cfbb5aab6b83748cdd9da470b37162 32 8e02737d48fdf2acb36863a26c00930d9d7022156fea101760d6f178ce30e0a1 7dd3e2d772fb4626db9ceea8dd6e455d147d86a4aacfe0f8dccba90937dbc2d0 413747d1db30c5a9e8723aca5d8e2b105c8be221c1bb4337222689f184c4a6de 297bb55ca843b5b0b291ec07dc6af5746d7348920fb57138bc2a6ae208239223 eebe4b70a7669dfd49a6996775053955a4f03e98b74f1ac029c1d3ce1579fceb 62d36715fafc49f61c615704f85ef67bf6c82c876abeb029e875c3847e9e8d21 c003d25e8b139b9a40b1e169a8006e335b7cae4a3736026a4ce0ae55f1d1154c f89a5190779476851312b1297ff0d8bdb0d6032edcbae23b48f9a8241fb7b54a 22a64918ea6e8d63399c1837210716fea97d6022c3657c869d7c9255cae853eb beb2dbcc8a4ebb25afade190a4b396df94791d873e34bf4fdd04f0a5a5f86753 51779058b46699ed76f017f551b53beb6259dce7238fcb23f62553638c0a0721 077f6bc7e6eeaf2cb3beb60ac00eca6412980fa9eddd932b9a408edca4981ec5 82da8fbbdd764bd252885dc704945be6465fc45cc30dbe3eb6fff9692ed05210 1df2acf66b87bdcec1b2d8e454e73fce0e6edf521d9c2ce5d8a0a5d8e7c4bfc4 c4107473cd90199469995334065883df47143ef21704bad6fef7db88a11e4799 616adf3cdbe84f04cf90b894eaf7a3e420d8606b3f5638feb3dc57684b63f606 180972d031b5a05c43c1822aa2f391de533069c98bcda58962e8f124a5816f79 e7fadf78edcf92bba764a30e00c626eecda4fe7b732e588f1fa668dfffae6425 369a2989333a13a52af60cc2400536292333a78735b5e2cf12ae1405d8e29c70 0036cac6d8ce1a2a5e623db6f9dd8eaa231184c85c1b7661e4a391288d82e7c5 dfdb8d0684014a38ddc314d51c948bb1fa93d2f491a0cb71c0119e7c3c677023 dae655dc8a1f360aae2d2f97cccfc95244703e91841372ad4e19ff62bf7ef77e 79d75438920510587b7e8935b56e1182a6b1736ec651a624385215d8d461820f bc7705ff99d0becd021efeb88f032a9f1a8afb6e4215da04aae62d4ccadf4b2a aa92d90286a2e97e8deb50bd1f88b0c17af828c037f5d6ca756461ce5aa50947 8a93227c8c929fe5668877d141cbd701b9221505a0af068d7de66651c3633b1d d8c07205cd999930a681e3df4c93d0f0306d2f7af98f54b7b0f9cc6c856164f6 71027190c84d4ecabdf9c6e5e4e441532b31da01076940d9ec6f8212674954c5 16fa8ffdb9437d1ea18c12820a0bdedc301adfbd3c525408784a5af4fc6334d2 dcf6a3df67483bc91e2cfcfdffbd967f1c50724d15754c08f46cb3afdd16775b 6982f0182fb32a36fe007faff4f28c411a686f97a40b44c4c825e865f9487400 2b4cc6cd754512d8987ebd79a820b681787aed6cb7bbd7cb5ef792ccf181b228 0b9d7dfac5f2c2203dccee3bf001cda08ef2b12f8cb201e2883df36f61970405 14 1e166cb3b92e27e5a7d5c1739e5bfc00970b2e6bc90c460f760b210185dd2d077ebefc4eb216ba10debe0feb86e5281506ef231fb49a4787a946eee0cf268c04bc000cbfecb4d2a9923d270ab34b9c8222f81e63aa73574937f59a8ad84194026ff39ccd97650182451124dc48a5f30a7f67187014e976438a01eb0881435307ce236da50436c9116e13d8bf8096abfa94cc7774fd8dfeac3e741e750a5f0d0fd6dc9d52d702eead69b11c32f46d3a739138f27b0533e9222a2238408c31c5063b3e64285824714097b78f9c9bfae30250add81c11677bb9f26be3a2833e5b075cc3f0559de4b3a415b0a971c36da19a7978e85d905d21a001bb19796130b100e5f3003f382a9b7a56ae251a95bc8dd31ddd20e4b8d1784573a089bf32f50e0142f258948cb600b75d719cd3ab341ba0529bf2ebe56658d3c787eff6619acf04e9df5ac6e5376a11f22d20246099d1a55e6d74af05c861a5292671d30a25d7088abf432cdcada442d32cb37852c6b5e885b460da78d2a19ea030f1ee4a018008bf9a5589a284c7c7055eff2757f905e6eda950a5dc337f2bca9fe04f28d7260e4f8574d3b62c2cd5fb3f6f720ec8101c18e1de5be99047836780751fafd41b01aa109292605e1913d02b300d263a7b1b7cb994d70e744feafd1b288ce8b94e05e69059e098b42900529473eb831354436c56a5431530b172c60647491ffa110a7476bd5a42e8cb412c0006df2ab7221cbfa371fa66c6b71f595675887d809c0291014a92c329c42e2f71ea18f45acfe18bf398c96be94e1a147e79f64c0030075e445a671121810b393481a7606b1fd2eb2d224db7d29b01bb63a2c9c865c70d98f598bcfc5853357362fe888b4a959d36494787e73327e5ab8d8b13db59d707d78c62d721f36d6ec561a17b651f52c24c0038533fe190ecd07cd3957aae5f0e81b559588532c205fdc48fde6134cda60fe1db5630015d3eeab0eab1e17ded01b3cc066608af7444e4c54c189682703b0a59ed8a89f4ba48059e5a0cf6e2d60bbc2706c04cb5ad2ee6f2e1a01606f45fbfdf7942490440e0afa00bb01cf5a500e28635216f752e78cf0f51c7958f8c8aed819379a3e839d4dadfb55171329401334a54ef085265bad5a5c17d283b6043dbcfd4c720859b167e704c90d6f7d30de187b76df69c5fb76c2f5722d119bf1fc9117ce46f3cac75c71704e9a41fac07b8264b498a1541d761c7ce5ae88f69fefe807e7afc836aa0a90e04e8a6005d073181a8ab532c2887c656497af3ee9be4565c47ea71fbdd0c10b89f083f24d90f46ec587325352f8beec540f36239132d9a6bb2ddd6f5ca2d74f1ac5cd9a4660a47a96286e94f1b99649bd611dbb061b585c214ec05c6f03bcacd5f1f402b5e091ca3e292394394845af85526efa20c8ff54f96510c2eb1c8fad2fd2071e3e208e80d5d6040a7c04c3747d8be2d744ba39f40a90aaff13290fce0023553398b0e36ca418ff92002973f3b5d520bf0bed2ca00ce79d8d89c0ba8394b10ae44290a397f3e50a86a64e47f29db45d3e3a642c4bc8b5ce2f8ba6ecf8dbef6f301140a1203fc5d9d76e9a82ab32dda8b4159c6b06b314f96fadc33ff58844f55f30e0f46ee7d6a0444ece436af6b74efcb447e50b48fa80c1805332dc67510b01a8e076a44fecab6831026cafda074bea61ee36ab18a6b2885faab940ff25dfbd5880a4fda7aa4c607d65ae4fcc91f98c8ef7fd31127059734c580faeae0c9a445f10df39229869914bece44d18bf3fc8b504a06c4076aa7054cea1449853c2f77eb0304800ab486a51aa7e789616ce7b1f2f4576d822e7f0a496d81c4e989dc169e04697a53388baaf75b8b505dfebdf2f348438355c026a6cef96574ae956da06f028f5717ec26c7f9c8794e808fc03ace6921865fa532074de6e2b86d531db04105a1f85b24cc8159b59043c558523f69c5773efdb35e4b165030c5494d345f5d0efbb419664861b37ac45d86936fb1417e25427f57fe63a34668c3ea856621bb038b79b1becf4dda51c1a7b9bbf561fe2fd47b49298afe0591d7b7fb4db026e30e1b5c76e3f9d62a3f0816f63177249bc85f6f53cc4316fe1aef1c987834c10c02ce8fac4b9cabe0cf5ccf69132f42a09414455b3241f34bc85aa4a3f06fa93c0f6589f5f2594172cc802fd03e04a8981c7282b6a5b9ad2cd932de76101582d406be03c9c20466bb6b3eb78560bfca6457e52520235dbc114268771431e8d499090522a2b60c769de3baab55c1f7ab1ba0f2e237f8b0780d47969b92b7f42d500e98aa2e11cc0ff955fabda4769b52627c178c9681bc8ccdcdf5983ac1cb851b05ea2d1619f8385e0a23e4ba3c993614017d74a7a01e16e68cadbd29c9c9d3fd0defb22b68bf6ab829aa1bf78ebc1f8d30e6067f005a8f75b0fc6e1e28bc0e29080fe70d937af655e3189dacba1528775183febcbae8b3fcd78523eb6f10537d0603c4ee2c39f1bf1bd379092d3cb42b4580c5ca3b278b018f8b3c9fa868055505363f9bf5d94e5b55575f35daac172617c9672ce781030246549e10f9a8449e09a8259e5d76d90f681564a98baf2316925936cc73191059b478d80972d19bd60b6be7ea56a240e808513811ab998b13bd170282fc439b421f7c1da5f497c0230d29be81e9b091c1bcc8ac92beb571851fba0f23abb783b4b95b1e57e943f58e09c2745e303ed17c24d99e319996288e69c52e1683c98150dbedc3867f74333503ba6f2dd8e5b8999772fedbb111c5a6c4db6d4db757a6db807599e049f78dc20e2322b5859278d3347c663795a6e2f2042c6d1a3af3e2d7462de2d17d5310530ddde5a7a0304b4c0adb2d80b9200d143d90c3f5b93d7028b0ea9e2779fb0acd03 -generate_ring_signature 2877c2572723b6c1de6b392c1fd7e6b9b06be04a33b2c87ee27559a4f440d301 6be1605f102b685abebe480e495a6ee11b401fc4f8ed2c7a9d59372677c51133 1 43f61d5fa46d25cff1552dbd032d2072537865b23f7631b16355d6e04f57406c 5768afeb110865a5c863b330dde198fee80d775dbd33ce56e639cc750825e60c 0 9cf705b616975aff3b05be50dd3d0bcc5150195f3f9d9aadb47ba3fa50234d01fc53b9c7b464cac22c534b2158f4478ad873ed37359e45cce80fe5fa0e04c80e -generate_ring_signature e85672e6b328687d087e5e27a222d908708082526eab8d9d1ed9c741309ae642 1f47514331ac0da99d0bb8bd185aa97b127a5c428ead41a49a1df9795df80a21 9 5d81cfee1bb4c5d9f12691a0a7f099897a6d2b5db92a5ad6e4f16ddf67ed1546 b352738407c3d1b642ec14ce4e87783c3461995d4a759f213a302d2f6644be10 2561702e1179fe38a61701da52b2c6470b7ae222b7be59aac2a4850a00a0517a b8e838d471c530f3c0eb2b6ef7a5e91cba4fe4ae976f5b9dd34d388678ac2c7d 00e859925f2b79171a96df93368feca24d15d9160aa005d86343f69b2147319f 59a3b6c9ca5cbca2b1b27ee13a158565ecff5267bfe407da2bf94c863afd94ed 51eb2c685edfba3a962e435aae95b54f866eb1429ddc3ffc79573c076cf4a638 bccd0d7379c0efd79aa6f27515826d350b8cbbb6713802a834a1f34f49a09fb9 5b7b1cc1529d4eebc5fec0b0d478591c0bb0bdae91eee28219841262036a8a60 4442e0c6b2c4e6cf3f5a1a33cfd304e8fd6c0c1cd8047061a19d83525b50b30a 2 bb40985067d244cbc7a03a5624fdc0a225c41eacf3276cb53ed5e6b108a0fa0c55bca1ce5b58ca218e994057375ee04eb95b589a3af45033316631483ffd620532f80ddfad405303f9dd68dd88ce5462fcedff7522346a63eb1fbb1906d7840540e55a08348992783fdb36c530cffc272c113d96146cb5d73ba2c5d4f25b290bf9c4bb91440988ab2250a4e5ed791198f73684ff30e650aea40c46235e08870359c27fc6277824c679a91013d99bc2ffa5aae07bcb2bb7ae6921ee8bde25cf0c87b9a43d8cde69813cc46378e464c2ce1fcb3c63df8a26fc42b1fb79449356051e019daeb4533064bb7f62539e2f6e9631acf12a0049e19a5ac1dc49b5a4fc06e0e5b56710c89b6905912b5d93190d46fd14c77416acd56177225901d85f160b6f772504adda9dfab49ea1aa2549be7f7357e8c57fd4b950a051f1a448bcc40db7bbf6f8668441411c756ae84cbf1932c95891859846cc181e28a746310b1807139982afc11cff2962a9410528a4c73144e56109b56fbc55f07075ad7dc91500982f633d6a0a1ac393ab8566266e05780f949dce7e3f438c29b63d6a05b69d0c6c52564680830cd0ab643cd730839bf5b4a3ee623e56dc927abb9a322146ef0670fb48c4adf0a26aedfe3a1441808421022c9974e3136097a07fbf2b37fc700a557b7a68d8fd39418b74499ddc7ffed68dd834da6af967e17672685a06f255015b42eab4b8669072a7bf00946d8890f2e1512645fd1885d845fd64060ca9e30c6179f5a48ae2377ad79765a25d458076862b56f06aebcf10bb15f634dbb86e0b -generate_ring_signature c960ac5d7f59051cc139e56674bcc5a3f0fd10f6d4525685133ad71da9505d03 d110909f0a37135c260f7198ab302d84f9980cb0f9fcc863b9865e0fd76e88ec 1 5cf0e409f6ce507bb1d619490f4501603aa0b5b11c2040681f5691c5e7af95b2 1f795ee966c8a672d15337e590b1d327632928970274de649f6d9a6d71cf8906 0 13f7c75611ca96fc467fd475a9c79e68105f7844bc97725f334c1b33c6099e0d281461587ea3a35f50da6c84d73dcc60ca22877aeee26a23bd0f575f8df25f07 -generate_ring_signature 00480a8cafb58dd4fac3d4e0b78615ed33fcea74c26ad9c23d6f610dd131879f 2b7fbd562eacf805c3bf9aad99e90ecbd22a521dddc5030c2777dc9f139219d8 2 66f670b720ad778de82b255292fce0291b5729b4dca211c9f0def3ecd0f8c143 58a740373134543502818f2326766e0188b935de010814e3e61fa44a2d1944bd 118bae54eddaa218b8e7b8c9079fa5e42666d38b08677a64606708e0d6574206 1 f5e758369ddf3a20458883dca10e6fd1ef5fa3e19012869752c5c30a4d022b0247e585ecfe5458932c060abb6165803952efdce7c0333bcef3823947f0041202c1adb6ba852ea57105a66a7030acdb6e3ea854d3bbbc8305b6a2c0ae1fd5d20436df8f27009e3cddb943c75c3abf35560c92beb367eb7ca344e80b804aa62407 -generate_ring_signature f92442a7a535e39ea68305835767d33b4a1527539ad2a184188fa473673e583b 9f256d40277f781e035f26613b45660acd3f41f24a8179b60a56999115a83d77 172 fd881da6976a55847f9590a313352a1a24a7c5b3c8c568bc37b920abf088ebb1 ce48a50c2e6ce8edf3a295368278eec1c9b73b56435783886ebada20591770af c1533314426eb66f59ad0f7469d65e8019f902b053502e03b0dac849b7262414 284bae0be6d2bd1ecdfb9ad7c6857ee9a9ff6ed1cf50233e87a997ee2bfdf909 060002eb3f3b22f173e4ba9a50b9140c3cd5c7f7c3c307369d3c87466ba9ed8d d7d32b301bf7bb28ead0c666282fd23a0cf445219423997f8dd30afdebaae9b1 56367289441de9f8938588385f9a3a9f4f9a63f871cd3b72c471702b8712cc2f ea5c570305cbb52ba6d889d8b7a340e9335972d520ae71c9c13832e491567464 071eac248b47a2c4653eaee65e55030239c5a4477254f12b2edf3b0be8367ac6 3f3b3221a7fe3ed062a4d5af91c3246cc7d2bc30e9d3f85947970944058d6be4 bf078413d79661eda1d8774f7003a5816a93632a8cfba1f3730d8a127e28a9c4 e889d95ae3eeee41f3debf69be540254c8e68347e8b2d19d96b7759dfc14e377 f5dc25d2ce32defa29030708ae1d6d36673f8b41146cf3d89c7aa2f0f2b6e313 5205a7793f0a4b0d6e1e9257dcad29614c9d0f886fdb16ef4dfb4fc36af632f1 cc33629b3226d7404851fef79927fbb90c1df81cd95b7703e38ffa526ddb206c a37b372b2c312ab90f771dff4b2053d95ef3099c76a6fba984bf916b29b56341 f4044c8f9a9801a5a04a157b7c9aafe40c019207ee66d29fbd3a356bf710fe84 dee92a17e7bf79f7ba3d6b6d01b213bdada853621087e1ae1247b115a98768ef 0d696f6a9682a9f2d4c0e582925281368f16efb8c3cdb700154db78114377dd8 57728b15184b062d286f942fd3a163ba68cfca54ae3304e739ad3076e1cffce3 82ab1f9afa7f7f77289c00080b1f98a487a14a2f073cf36bf96a30440f20ca52 139c5e0efbbf51c5af2b9117b7fa58d6412d46d67eab6997857701230a94825e 4e17a9d3cbfff868b70ba95e4243a2da2df968ae5b0b67fcde527eec0c084244 923577965437137b6a933bd61505ccfffd228aae996d25fc96ae9db5b98d07fb d841ba1679e8ace379aada4547333b839b808c514f6d19e38895ab48b1a9d16a 8175b06c4a1b58b90b367aec2e81dd9c41db930a96b3e08cf06ef9162a21415e 818abf49a345f93c1275d55321fa70cb50f458e9e67fe911aca8e9a4a253a34a 2f521138d0edd239f6e54d5e4d94efdd9749f6b520fea327e642a0fbee8a5c04 9f46910d6268a0dce884a538bec4a81c3bd550b739bf5d02035174d1b6707a17 64656d4ab3a6f1c92cd71ddf45659176f2f37789d0338dcf124b1e7ad1030f71 f8c3b190e7a9091781da8ace4b6019b2d68f05dc92e54960a1a8571702b9c77d 9ae039b7b615745cb4e51634a5b8a10484d73b81a9baf555e11efeebdb5fa24a 75157319ba0ed1b0208d3764bcfe60cddfac56aa2330c76439923d245bd7d81d f997a99abab99f25b18d72b7d5b73d4dbc1902dc3e1e01d1fd0d12b633772533 aad3267d5679ef6eae0d094ae5df02b5228d3257d9a1edc0af7aaeabdb9051b6 1eb4d7c23a4c40827eefad193fa0c778f1f84a07210edc51b42d3150048f90bf 70e8bc3d0136207ee441333ab2f463ce6a456198aa7d7acf7d1c966f89371bdd a6041cc33222e72a94710efa35235937f843d4372ac73668217849e4f908f4d0 265d61d8b2272325b2b69dae4f728d3fbb3073da4c4006d49867abd4c1575806 502d8c2e6f00025493227c87f12a1319199c3283503748b32b23af0bd20eedc6 41d762110cf7279095cd2116f10ec88f99520c860d3ced6ef72ae99c53468ec3 1270155b3fa3602160171da175a36e4ac52adf90a7f52ae84d8be8471863f681 f4bfee7e8374801d097ba1199f24c2750bee92f29f5f84174200dc8f25234023 ab8ece6cf4ff2b2bf545f8c57791685361182df280ff1bbd925e8fd3c16dc329 04f1c90fc0b45e41ed9cc34a012d623d0a71e726eb61a157f7e5fdd331cfea20 ee65cd19e5b17a0dca4706ebfaae7474929503051fb26bc70c7f78f986311e2e af5af1a0079b7b62f0b2eb03964ca314a21e0be6685c1c6e6dde44bd4346b943 96b9d0ba83bcd6f976a964068dafb5329d349380910d3eb67e550fbdc46ab884 1956cd083ace90b869f0fc7041362b47a5317164ff30d5d4597f205d53a71474 402f7334d4db7dba7b1ca8572cc893223cdd7fa520459080f70cefe98a093635 ba1053f093a6d06659433238b107558e26a28d2db942a84d9747fd05839f5056 89b8acb7bba7b8cfdb045e158837a4beb36c65fd064fdfb2715ac78a95dd76c7 7d16961a37a25cfd9020b44566facccb9ee31c8663c3917ad7ba0cfdee07ceef a731d84951d200dc2dd94d18c77712c558bc3704acda6085d6bb46d0021dc7b6 a14c510bab57377909416af4573bd3b8a551d2d35421a706758408880bc4871f 59f8144bd5690d28f29907c8a958a1a70f8bd305a36162e310f04f2413ac55c8 0d56e71a5e55aa4fb86756dad3e4edf87f3a01a81987d1e13f86099dfc3b9494 5510c0c357755864b4485fa43bf7dba01d33052918604ec41533610130dbdc35 9fb86f44b481cd504258ac3975fb5a8534673fd77765f5ed90cd310cdcb4006c 3298a93187801ec62be93c5aa5900916e6ef57a4e19331597b82dfb9c00b2d9c 55b2800d41d2641fd75a214efe80a565fd5f27410783232f2a44f7a774ef9f2d d6e2629ebc2413e4f294af37b2fd948a7d1d71728fb59794fce78ab173f32a5a 23617f3efb68af4f70ba8173f61b95356389c4cf788e3b8f72cadc0d681975ff b06347741f5fdb84b017a177fd904913a409c46e97cc00440ed449900e9ec2f7 e88ad1d059d2d9aed7150005189836ce56dec709b8a22f63ed2304ad6c42c87a 2fcb144f29caa8d4e19a07f977ae6917e8fa0c830c52b0d4748ebba4801edca9 a432e7e9cfa465440d9a0b1df528d974cc32d4c7f25ceb53440e5995e9b8feae 0b0428e6f8ed8c90dc54832b15a20fcbfc82cb5f908f36045b1dcf6b69cfbfca f4064a72fdc46314d3652c0bdfb6f08f1b248d5c747998fe412cb86e97c6d83f 45cba132b9b9a0ea8525b70a158d531e0f4bab123078906e1257558b9904a24e 9b41948b3d7e5d4636bb670ce3b66d16a939f34320f0317ce20ede8a9651b700 bbccf33c2d44e1e59f62fa8144edb353961bd522a1e380f95ed006172c88af0b c04093b6c7bcd3446060f9c18cb62503acd1b1d4d5c4e7818292065bb29bdb88 5cb1f7658f73d542bfe7b10a988f45db4bb9d777ed6b0f780049ae54e82b6ca5 3a8cdcff1cd09bf1ba1952514ffdb00b204322613221f6c6efb969a36c164adb 03f8c02d0dc951aac9f5b70c1c044c06c9c98b0f61c5b30d6045f9f1a12c1fe0 0e7c767d8a26d57dd35d5aea58aa9d3a6098dd8ef2732c66bdf0e183ba23f6b0 1d6d4190d0b0f4b8ce1c53f1ab48c601ac7f4c487834f2ed355255a62813e11f f609212468d6b96a6ed41dc61708c2521aa924711029801e8e994095bb5361da 87f496fc9296d7e4a2b3757e555083f89192935073915fc41bc8f4bf447bdecd 1741f6e096f8cf208f002cde14274303ddcb25c2533b9dd10f0728e41f28e501 b091eafa29e0509f605d0671e4c207a74acd926ca791824d0e8751f58124bfa3 8fef9d73d54f5984806448be3a3b469b1b9a50ddb6c7a69a53e404ef3940e32a 5da7b39dfc6181a2cf1ee4f9f2e695b5bed73909dfc32f575eb815f53c8c0484 5e95b7c9f65a53d07781d57093ab9cadc813bb153e669de752f5c97e05571507 505ed9f5b5ae645ef41900a40d7157b332290bdeae3d19f866af304989d5d8b1 1f8959af3cf6788fa599a3a00d84c323bcf29dee02bc65171681fe42c76d4b5c 443b4dbe3217e35f436a76531ee08d19024edc0453c2d341991a8390fddb1568 7f3f7aaa9da801b08f6cf47eb23b3cc7d098c5d21bef44ab449ac00fe6a19299 6ab9c1bcc391acb14e701e26b32b7a6f7fb09da69d51b289469f2a977bde80d4 8efffda82d82d52bb1cefad9ed90fd82956db431019d040f6100ac161eb7779d 59cf1ebb7bebd9e07338a515fa9882239bcc77f6e8709f4765b463388a7f99a8 efd4bb0ff013d411e7a7d220f792ec5ca72933777cf416c5d7f2a2945071beed d1daec9942d6cfe1c2a082609eefc2c9e831a0c07dd21570390e2cca7f2dff50 bd3adce1a245373d0073f2430729aa57954748d90e3718399028fdbdf68b05c3 b93a50fe5a835ce86b56209a1057babf323e6dd32fee9433db6ed3695de7d9ab 3a1f69a2825eb6d2c90b438e9d7fcb3fe8c1e38983aadb0126aefa31bcf6c645 ad8be22685e2be87180baf881ab3dc90cc636da658175b732adfdd968e6e0246 9d57a848b3079857b0bd7c7f961e61f3d6e3d52c2194e3c3bff28dd1bd5080db 1c1d0bcc04c7ce4cc76effd19c8469638abc1e044dc2a79c7eaa0613528c7c67 f562f27b6b50c3cad5d14e7c4f12ecae046dc008d5dc888a89d796aee7d92272 e292217b111114bcfb21cc886b628e57eafb81a6f15eb72478b3a58c9fae5ed7 0398e72c9373ab5a0e21048f4fa031532ba8fa7072d08fc12fdb9cadaf0f160a 77c364f1d84650d7cb383dbc06e3c4570dcc2a343ed4f0cac0bfd76e1a0d250a 067c1fd7d8f49457bfe82088af2622f1d164681e70865f2b317e8a39b5b1d5fb 32a06673ae1fafda5af9e2a4400b0b29397a71e148ab0a10588d97cd408ce759 5a9d9c4d860c661e86742c4b8a2f9f641a50abd42b85a702f0f9078e06189fa2 939d92a6c0bab1d47d8eca4c7a2637498e41d517bfe0af1578ca6ac2d43fac67 b95cee77da3467db2e20ef20a9b88a31f1160cd4c96b6f08cdd41f719471086f 36ec08a5ba086104f1e20aa1bee9d911e499d0a83ee3273a9afad03c64d86885 d322470a709b5aa95a584918ef8e80351984e58799fe061c8112dbb8ed166e00 3bf94b5d1bc3af26948c9e95f0efe70707b7567f6c868a26fe0b3736f4eb84c1 0dacec7f9473b709d9d08eb0ebc09f8d14153596afc5f2151e21ad5f4ffc552d 91f9062ae066dc0cdb72a9caa0dfa82230fa2db6df73e69d4ce042a8c060d813 689f47516ae100226f511b2491ce607d33565d036c270dd879f725fac4f85ae1 38a3a226fb70015ede495dcd52d5317c8f837ccf80ea444e0872742b959617d8 2698e10a18971e5533259238128acaae4db48bddde16b3671e0ca608ead5705d 41e5a86e6e2986ee7803d5302b70e50086b379232a81b8985de0c6d8072ba128 9904888e211357fc304f14a141953565774a8681ce718cd669ff3d0cf1b796d3 6f7470a432f921806f7704af9e2ae3db09e79a98691f5fbb355ee869c824a9a2 71ed2c4844a82c9bb02a0ed2ceaa1bfe5011364c90ee2bb86bf2eb9ea4656198 2872fb459f19143c897500e78f4e03ed59836d14c8a99abfe1c45c25fd9dc225 afc7929206da56bfecb5fcbd92f504b8840ba109f2bed578179316f2840b7493 740e6ac8f581a0d48d1c890ae1efa021348711b7668c2bf44ce4df9de3900d8e ab637889c7cf30038e81325a13de81d28096719222b2eab649ab4dc46e306abb dcbf3053b800c54b354f4ab29aa1470d2cb41f516deddfe7dcf37a32c6baa4b5 43f4f3389d1301a51d22acee3a2bc19d8ca3b4051279ffd1cdc43a81ef0f3120 d53a2897da965ed3ec8fe3a64c84e94148f5a44e26aa618f2d7d6ef6e1fd5f45 eb36446a8f29a00e560e3539910c595e84159b0097ca45e1251e211efd4457a6 fcfc38062f786c990627e08f21824cb2d7aaec22f7b375e5f9dd32d82fb9ce7e 8b639553c2a999201727a1b7402b65f75e048993ba308690ad9ba2b65361f507 e71aaa0bbc4e864ae50dc86b9ebb8644320d91352025fa0eb0f60d0a3d054334 3e0aaf77018f0588e9bbf0adb974a83cc2fa77f42cb4209c24766282cff72286 52d0a11678b725c2199ffbda6814f92e9033c2eb5c5ec249d4fd4fe94e23a726 8f8c15d5ed07695a7d4e815cdcf4dd3dda0926d0d752468948ed919e4729ccf0 aaedeb70ef549d4196dca9e3fbb7ae4bfb81e2908969840c384d2afd34af9f1d c4033ba752ae96463c8c6d0d2b84ff52be33f3215de8f78e89d817ea24f3dc76 f1207b72213b423c405c200a7a5fd7f8023e1f239c8e606ddf71031525f23b37 baf147ae7bdea07b53a5f5e75ba469179543dd0ca592095ff616ed04ef9beee6 2cce4a9d993261d22aacc8b5846160c0d1c4fbadca7a70479fcdeb550c959c83 c43edda5a8413902774b1f8b09b27182bec45f69e5889e202060dfceae6e9ce5 22832c1ec22d2ab3b19093ac102a7aa2b8b0bd38952b9e35e44c223de1269a0c ccaeb8254c1836cfe80e63c41f1b0b12cba744f6252a115ce428368eaa19f561 aa56531344d04ac78cde18fe6182151d31569d6989ee9d5dea5292b21da8a3d9 543c8af32bfbd127e6719470804887617c42fad95fcfcb653d49009ec615b5c2 9c54714b1fd93b07226cb356e7e29e1fe9c093a22f3832f3498b6fbac03f50af 0a1d9f709bac257082747850c6adca588a7497f5853cdf90843a4deefd0ebb61 1accb6cb2ad322986802e1cf695a77856dea76a0aca440e6f7ddf7c6995bf1d9 5a077b219652fe5072cd730e904db6069475fa9808c9cba94668189922e3fe14 90a84ec912c8cf108a484d9305d0435f6f8aeaf48bcc4e11f86f5bcfa27f1f94 0600ebf5b2f516607f12411699f6dd8c8817c88cb9f3382d854d4f943ad23f29 2559aba16f4afe15749840263fda8974a76f6ae4e5643e3f6b797a3c62cf58ca 7ab8110bfecb7a962ae0c9c503a44ca616d3fe93adbebb1daf376ea312adbf6d f43d50e52ee7398b0fa244e144ee76d30d39a41e7199424950d4f00e9796f9ec 78cf72929a258d65087e8568e2088a6ceb6cb807a9ed07f5af1af426a59c5eb7 1d840f3efef11524a202b6b4c55d15f152ebec1fbf543292464bb3de84a3c0ac 244cef52f6ecc47defa48791392fa2300201d8b10310aff5450038c14991948b 74779637e05d6c6634b4639a77837b33a5931db6fd4669514df6fa3a95db181e e2f711df4622b4ede67c2a90f1b54e90e8cd0a9e9233c30ca82ebab46c68d97f 935c0b5866b20fd6094efea23ec5a44d9f38dfc5f9e13aa13681f6c944903946 d7c11734281c2918cd59b872819af1fe6808b67aea22aebcbf9dae2289eeab50 b8496e518ba54a9047c61e1c88255305f43ddbb46ee1952e5261728f6f233950 a12f64dd6adcefacf9a68dda0307f97699f45069750fd2842dcf49d30d9ed03a 8f98e2e04a873d27b24032446f3802d96921a3d364c825e6b918f4e8f3e8ab85 03b646a54e208cd8e396a18b43b96fc1e742843437aa917e6cac0d706b0782d6 30322a0e721a026ef6ff39158e4315aa2a492cbf3763723e7bc78657d9573a3c 4060d5f0af5ce15d7a8d1479313e0fee2b20f8e968cebe186761d6c01317bd05 825b5e2c98d748a4749705d0ebd93e0baca50c01b072dba309b71e7c52be9e1b 57deecc6a18a1eb81dff5424b8da3f6a6e34ec7af818a361d583b905ff7296db d576304b302f68dc38dd385a2241268c204f6d0219615dc123b0753ba0cf35ef 13f693db38785ee165adf0cd566a7402f0d4181d2bd633c081e86c5509013fd9 258de71f92a436777203c25e57a22fc51750bfb959022cdbff5fc1d3eab8b41b ef87aead744d41649ade14650cf65f719a7a1083495fa3908acb756f84468a0b 99 19bf3e88892fe67a104217c1ecbd02648d861a44d6c128d55c56acadfa037b011dc6201b4a13909db017475218ac303130174040563a855978e883582c1ad8095aa23b1265d9e7eca8434455649d4e6770b445992fe368b15abbf5240f318c0adda4d6a8f06ff6f89328d45fd772e6804c4658567489b5818a1c16c241a4470dd500e3a9883982b9da0522853d835d7b411785c9eff31494bb89af48c279c505a2e2dfc13aeba8ee39aac52038bf1571c79c9033b269c8264b39a616a85a50076faae678254409888f5b1124866f01f3413dba6ef86e7b77d9336c0fe01794032b4f1e048288dc1dabbd94b0ee7729eab754a0d35eae60345b1ea197aa1e2608a352ea941ba65864c883e406e512f2befcf8faaaff3c29a8cb39277fc1bde70f59d45a6e7efdcca8f35395dadc7db8c91e869dfede900888518e62e652e9be061a5401571aec991859219bfdff864e6d10d0e74c81530c5c856a0cce0eeb00000818ae303c1e2124e11b949f6b0fdea7449776394447c7b807f46f89974dcc005291af72b726a8a2eca3e26b34dfbed3bfdc372de904ea64b88129a2fdbaf300055fbe3230ef2b290ac14c9ff173741b008a6fc17c8961a4a431bb583627010717403319af8a383ad64d0c68a2c28ed80a503ea473c199b49e06d1f5cc056005124ef390367e389a6ba862d827bfa0e64120322949f27d5d3522a4b039943b04f0bfd20b793442f74bd2781afd6bce8708e41ca6aa9b0894d4b4480e5c5929090874ac770c68b5ec20acc49077d1e512732b591ec7e7668d8acbdb5f4a3bce056720f06026fa04ed2a8d928a6a44417a983dcfbc28cfd8323861d2abb6a268018b3755d48c49df8e7fa8bc81c49618639aa6d9c0eabbbda56b5546e68bf0bb0a43153fb732723913d66f34f0fbf9f2197fa21c0b5736b845c3761f3ab6d71c0174b5949ee5b0e8e4c5139ba340ac0a874b3408b6ed930a097bb4c528706dbd0f2bdf376087d3ea5e565537fb91d89fb5c82e34edec4de79bdfb6295e1194630d3e4b16ffa9e030335fa329d3de09e3d61a151b7bb4f7865fea02847af6b58c017dd5d09ea2a92ae2c1d146793ec17d82990ed31270998ddd8f59b6220527d709b640e8102d3a1b3817d3d33e3de6d12a11f66ba893b266f68744463fdc21c209c49410774bb59de4fcb2b496cc5ac85bbb99a68844618b9b5068f2e1e2452208acf255c33d8a9be21eda174c1adcaf61a08a4cd19c9bc148a85f78e9ff24030d492017bc46d829aca317eee3f82f1a5d4f48e99aa17efe065c7215a656e1570b56088257b444966a3f257d692aca91be53b2871e6638440de6bb8f31e469b8084d9403a11f219d861c2cacdfc33b35938181d6efec16620b2f56662a4506540ebdb6638648361d0c46d03ca92969a087dad38f95c6155b3f0ba08f7f972f520fdfe68848f59bf320bac3f6fe8f0d4ba0ce1e9382694106a5ea6606794891ce052031e7cabef2b11d748f53b635db2f2ecc4e73f8563c55399daaa6bd2ea7570beffc472b5f4cb53231f2fb4e3f2676ff6c05eda6d80c76efafaa4d1c770b04072d8442b5dc23f3fefb0810861b1abddedb4a604f0381ac0ac3874401f1ae9f04a5480976abbdd70182ba817cef39fe7f0046fbc7c70f37570588affe7ffacd080c0741c25bcef17183d7cf83cbde7d8d0c9b0fededef7a924e07b75ddab0df08ab25994dcbc003c70d8b7c2d56613f8bc6f89bd2cc24f5302c87ad9acef6e0080eaa548b00d284a587a5d21cce894c750cb2487212b97a839c985eb0d71c720879227ef868aee3c57207a5cbc5b5b2cc7a9434bf665d11177c237f4b0f7bc2077b9d7f51e2edc55bf66480afd0777644c287e7c562dbbaa3682c868d2681ff00fef3abd2da8266689d3b005b1d812f55041a65345a783621b5e399b20a33c00719ea615e443fd40e431565115a0fda5aeafae37f2bf622e3f4e74c456cb3140b63dcb1523d841413687be06b0bdd2f783ca208672193e77d93245225286dd207820989c3783c5c8dcd6accd3731df33fc3da5a9ea4cb1888fd9691ad0818c00bf9313c27f4ba9af58209d6254bc7db105b3110963991be8d9fc2ef396028100c592ac03d67a52113ea59e9bee05d2cd55a3caf55aada1405582063357e82a7083b679d947f0308a9aa22fa78a348a0c84e1c27afaa0f49259ea86a72aefb4206fd3439199437e5219b9e3f626389fd19dd779e8f260646ebb4079fbf3f9dfe0e47c23d32e51eb553e411ed708d09844e9be693c97b1f8e04cfbcf8864502fe02778c725e20a52b1213b49b1908e63c5a01e04735a6aa633f149b53049785dd0fa341f0a72003e112a5a25622cbe636dd81bf5189616ef90197a1f5cee5ac0f0c8c09dbf72d2cf6942fde5e7395be69e97c9a9a831c3a90fb3020c39e2042170cb472ef176d7f94ba117c5f81fe49adc7fac348ba27fcb00d324197c7eca4a504ad10899c8e68949ffd867990984c1f333aa965feeba8ef4295a844968117e50c801ee46dabb9844ea170fcd7d9d2e200cdfc337fc01b3fc8d45d95f39c11d203bd747c153b48a51d995ccc7c545c3c2eebe79e54b6a99c7c81b41809d748d2096f01bb503680db4822d764611dd19777244eb6f0e65326a514cb5a4594b45b07afb9dda3f4949842e244af88db19cbceac5236b29dae48853c19d2c5f7b7f601578f66701d4792af936a8f9d5af36ae32f66c04e19d2053c3c618144ca9c9d030468fe5be2d4bfd8946bda43ba42ad3297068854d532a5ae30d9069305ad7209c80b0ec1c3c555ecf8168c2d07c108ced64554e1dfba9c847e6637b36a3cdc05c6437a8aa793887cb3593cf64e58a32ccd3afe2a56b423bbe1316788084f6b0d5f592cb4f04dec5fcec736ed25c1e494452165d299deacfb053135d23940fc086f43906197d023f6af703835583127e316c4ded2dd4f2905da84f64273e9b5032db5cc85e3239b363305a401dd5ae7b45da846adcd7e9b242ef050e76639610e0dbbe40247ca29feb097d5da8cb83e3c7d5ca44a87daefe25467866282b0270ddb175d4d8b2d58a00e6d3a1be655ec920a47ad2a1b6838c20ae5fba3b85d800961b591fb9f656da834f2ed5cfc4513d3577d2a3e6dfeb06d9ea306642f99b405ad8d0ecc1d7b6feb92ef5a0990c6e2ac6cfa49b5f525bb65cad4fe7093d8b7072c3fedef9cd270e833289c67eec91e8cd36532306c84745b3bcba4e26f26a207e01c97da39f5c284271b83db54b7f6e0268b9700f83ee8b8923287499b31870621e7384e37b698a5a6e0e6340e8c46cdb0e7da7cd6b04042aee93e282bb63a0d86864900277b779f949f679806b8e84c62e5096206bad213c86480f7110d1d0da30bab6e4101306ae2b1aee6c6827e60aa2424f6ee7dec2ac75c419e0454690b1ce88c87510d00e01dcb69eac3808a3df2cd3c4fc166fd174cb3f505f1382408c3f644ac5ae85829b62a7743b7b927fc7e3ba77a8d3a9544da65055b07f85506ab72b78e733fc115733554fca7e1f72e6a2b6187513d8c2f8101dc5325488e08de8c01266473fb088de76fd9533412c321d5ea7fca27d3d7a86940e3f861950eea427e79a750cb7a62c5cea77077db02628a55700f3256d04c74c89a4eb8350798ad31fe813cc138760418bb7bb070d31a12e6f554ef0ff1001801074b6d510b49e6c4b7d5e5f148138e58ead90cf74a85d847e0028fe2acb386a1cd0e74f504647cce52c056f691445f8879e38ba016a394296a76c64696effe043d7574d00cb64887703991a0ad3e05c00fa9881aedf2a7dd42bb8fb0028c1d8bc80bd5100c07fabca514b38ad34372d732dcbefb185ce06086c0dbef0a29fcf19eedacd900a1432cbc35f0e70db1286d60b334b9c706156c43a79acbf6b60c686a4f32760c4fed0e56a784368df788c466ac3f42bd1183fc505e151754cd3dc0fef66be40804254e961905ce11326d87085d8a2b27e4fe2deb60ba6dd0a70f25641b52ae0cb27b2e81beba5a1059c51c232e84478b8d1fad044a1c2fd5913cc9d2f435590884eed1456a21f7a32a122ca17f77037e385e9bcfd26ab9f266b9f0e8ef25f502a8b078fc067a70996d3ec5979c9e866694940480324303e0ea9afe5fdbbb8700f0fd271e18f63b313c8926a825d8a7dc4e9264da9000d6f7c05470237b6cde0bcc33f51f5812444ba3a3effe65fb5bdc75d1a3025cf0a7d902af749000db4704f1fc3f994d991e9d7c898a19a9d03f9e265f34a8d7d503066d6bdce43922b90b753377ca54b7ff031f5f177f4aae7805dacdbd351998a27d4213078c568b8a0040ec2400665e35b4bfb9b713beac4592662535180d4275ed7659af611f876c0b3ddc86653724953cef780dbbb150d76d8efd3f6bde2d26d3861b351f13b9e00efefd79f2424b143bfe7f0d3fdd346e27de4de2fbc6f4a12173ffa68449d97c0cbb859850e7303e597bccfc4b372c5ebb2d4b591088b98e6c9db0348712261b0cbc87167912ae868e85ff1008adf3ab59b4a54089294585cdee5117f486c83709faab527c50c415d26967101e613c25bf0c9238ce685f99c6f83611b72d073a054034dc2066fe5216a887e509784c9c6a794f86bba684e345d77b595ac37e320b482fd755886c6ce4f76c22e73c1c9cbb8e4633f6a97882d5764da0319905c20f5e110622a0157c689be8b35ec4484d903679981ed0ce293015a2ab6926a84d0b7d91695756124810049fd53fb6759c4c15302f49e75a73625ed1e43e4813060802d1aa9f4e02ad255a200ddfeb7aeebd1cbba209b4fb31ee77c25808df013507994a641b3b1397cbfb66c77e1a8b8308e35baf1bb57c4c66e687a2aa878b6707c2ff0024c004402bb0680fe16e27e020a33c4b8b63187db36260f379445d940afd90d0b209412b98d1ff3dd82504a85c1731e1ca912b23ea491062e441bdd70de74ad8b574cad5b38c740718938b54072c8cf1e6e2b0aa840acf4ef1e0beb104610b337feed6d95ec83ba94d557a09f808494eb73664518f47edddcf1ae90b0b3d07a15529b7f8f38489b57826d7393219a234365917755ef5bd58c5fce71504c584409e6b661441d8b1cfcd274214f448e92e3dc60cbb1c536f0463770852077e8605756a28056ed72ff446952a3634ede88d13f6cc3a0667757862b5d81b09d148d15844eb504df6a682e4e6cd76b8246c7edfc94c7b33e1d24c558b29510d5fbfb9eb946b4f9eda707226f3da34b365116cb953e1333d44219a94ef4d170e10ade3e9211d80eb971ca6b91b214ed168a8e29335228e6a91bab45ddf08790f6f4b428043d21eb53371544d2d7bcd6ff1a27ba7f384db5810003e7e73cfc107d40167f4b7992df9bc168d9abf68b495460769b84767869a36cab441c0255b0d48f2b51f729392c7eef43304cfe541605d34525d32ab013a3a7817f451bd4a056f7c4d21c56a1618da1ad2fc7e379372213ce4bea71c3f18f0f579273ca9640405d499b0d35d7d410b57e01182b59911ec9e2ca7fb87e6bd4d9bd079c631ed02484bd18ad90c09aaf8670506373e54544c2fac82e891b3324a1bd1ef996ed209be20a5a53da64d8b1c3962f268f96d08f4b81e3d3f3eb756560d4e468a50430736895be5ce333264aca116707b5d200182cf3325808b078b3f6dd1ee20429d09610efcff54684579bf487675dfcc11fec86f6559d1da7e8e12125fd5315b910700ca2573dfdc5beb5862db5f88ae4dd72016ca722218e9a0f13226448fea5a0c0bc7ca27e3ffdb2f2f7ff80a8952e0871b9070e2d3d0b4c466ed3b7e3e146c0ee97b85607a2bc7de7253fa5bf1d5518d7ca6bd92a246502710a0b3a13bcf7602c2df9791ed0744c75fc227bf74c38613e1177d9617904a244eca2726f824040ee1d2a7c3d8e5d430a43ac409ef65fdb4dfe4327d41f213601e8348384221220368593d426b0a33d4933458b1c207217f82cbcf8650cd0161482d69e66a0f810daa72f1efd3c03241dcd1e75c03da07b79cbda10e06d68798706c9145d82dce0f261d3f1ce448f4f342038806ce3fc6428df94bd4325234a2f45299b4f168450ae38f81af1c5e128173891e021d7a87906811d2c688a8c188f10cff72e3324e0d22095d9a89a30ae570c3540621ce1f28e3b452fd31d410b7bb8a462e2839cb06fccf49086a4d22cda1e5f023d38e79cef825a4d7d9258e071bf0bdd8087dea034185ba7e86b85b5c902257d1616b7c94960b64ae8538880bb59edde568ef9208050f0a648bfebb15cf919e4bc29ad0ede506d8121d974c56b07b1f63759fb7073b7800e9e5bf895e7a825e61d4d1aedd0c9460acd391f2949ddefae69f451d0b3e986f5f8ae455df05a629f134e9f813c888765cf95046c6b16a6d505cc9170eee008feb0acf2498583a9be0d00d613a1fddc81b8e534185a79d7157bd50ab042dab11a214f7cb3e9b2373233a7c7c1f9a1f1ee4f7158ef559ebd4965aaa3e0d5e47aa407383b97a8cd5f13e786038e92d900dc84c86321e19133c261af5df0e09a47015c1e5aceefcfbd9d757de9d873c2ae1be3c36c5db5cf3b797d8d760081ea48e1ee12f8b67dea697feb474fa182e2060c8b538e16eed5de732d251aa0a4aeb90e2eccca92b8778a0e1f504dd4d75ad6e518cf6906d60200879bff98907a2325b509ebd5e5cd3b53c6e2397b22b7021231ad881dbdbc03365058a572504b589295e9b33eee2f2b0dfbd2482b00a5fb6dfe9dc8d54ef775880dc11674400bde795a8e574808ca5ee84a936e01d4acbfb9cc0bbd86cf5bdad7f6e090b020085897d3f628c2534362f770a5d20350589be62f77efbc7da311ed79d9d2f490fefd460271a8addee32b9fd4e6692234beab893bc3a3613f350b091a84502e908ed83fc164ee45870e27675cd8df3707ca09a49c26b208fb5ee72b3891a9593082c2933aba8e0868cbd1af14e6fb72b36af8ba1ec6c10551272b036fc6fcbf302845b3440c8d8cf3c079f368a6e653b07045b026c54ef7fe987daceb4725f9c00f2bc1bd1233574f93914bb3c9042d7c4b0b0c272ddffa95e096eb7b64441320ce36904b5b07df38d1ef9a22ec5b183fbc3eaffcf999112a16c23b8fdce5c0704eac81e503110e59156fbf64561b857cf39e156476e29ef87f4a6c08640fec30b7faf06bf4a9eb1e19afa39057bf5d2d00ea352fa0681d64fb7b8325eba168d0dbdc5d283f631b0c55f575f76328ee49c99a65e3e7a0d329d3c16559d1de4a602cc02e44f1852631e7e190c10a70ce79fbbda7bd8915dcbdd7ac1e23f6e34a900ea22a7cab6b2d19a6802803fd9d1765b8067273eee4b80f603bd701c5957040f81e74c0eca1b183d7e564bdafc9d460cbeaa740241f72d0eada097aeb61fb9082be81ba42d22f3741b5c4d28cc59b99be2b9b0485acd3bff88dcaa5cbb15cd0e91f601ba0eec61f606d8c70b87a0fd02b769619da91d88d9509dde0cee67d900cdff92781a293fbf52d10fcd52ddf7089c3a9ef8be56837e52018a7d7b0d3c06c7fdb183a424ee4e38d59cc7ba522e8e2fb13dbd5a27d9e7b9df116e97bd860aa04f8045d8cdd10ff8a4a13176f5bea2ac1f4e699f12c2c6f6072d793fe99302836771cf1f28ae03393b150c12273cd6bea973cc4d7d8599a1aa84adf3bf4f0bd4f37564cf4aab35de09f4305a3ccd12ca7c647278e5442a8ee61b1eaf9c5c0758d015bc699791c37508ff52835e1da95f55d55060c6dacb4350c32942e0cb0d2d8f0e1ddd6a393f8308f649c294f3c505d429582f66b676ee50873f174c630c221502d922650df39c8454ce394ccfb9df4e1b5563ad16f3ae2615fc6e33e508818e79b782b533d1eb5d79e929f1af9d38bc2452bd285e268e19bbfb2a99250d760a50920aed383fd1636e6ec4babb5c1e7f0e4beaedf75281180f1344934c056337040d33b411f4459b68020a9e8cc838af1e4f027b9f5cc17074418d082a0f525cb684a6a54c6d61fb3fd404e8b8c20a3c97802da110b58087253065cb150b93e3a27fdd2c89b7e269d708565354ba73b325d112bd1ebdaf5219e000742a03731a79df35c40b007ea43a6494c804614f12b5c0a313ad9f575e6e1a13ed3a0f692ad2ab1b2b1805c074c4512049d58f8abd80dd76afba02fafd927ad593d60001bbe5e795fedb3d5687c879953046a9636b8da6e5679553b05871ab1394c005de132a9e652a0cc1073146ad9be58c573d9a777b84329e1ad3ce61a256e05c0f8abc4803b2012bf2caa0e00048d9e3db981241d4802aa39c75103e8a91f3df032f12d55d2bddce8533317df105b4d8dae3b14371d13ff3c86669188ff2af39005fc3bf577463f492cb6a016d79312365111f9f3cc1cbcc14192891a2d6ed860064acd4d129e3f334c96074efd67c16863e93bda32fcd79d242a12d666a3da80b2937f1b966baa2a853a49e15a427f0ee0adc14913fcf7eb73743282c0a726402964b97d68c45baa50aa961508c3e430f44061260619c51ba9d7d0d67a434a4039ad6b26773669810af7b97fae7da6cec672a644dee16c308a692f4dc31906b058b1ef2d137e317a87761c18cfe7788af8de1038933f3f38232e18aa5165fa50aae0545aa4d5df4310bc004155527ff40dfbfa06a7ff79ca0c4978e058bc57f0f06ea87b9a75c95f34399a9300dd27b3bc379e1178caa6bd445a5b08f7e8cb106c6e81e9d06fd2057df5551e8235922f7a7cfe9095198d40b686a7971be7c7d058e65bce59cbd2e5ee05a8d45e7aec14cab8b5849ea0b6693094274a5303522089e2a4f6e79ec1868e5389206db372859777be80a10577a5d60a472b79874530a5c4bf979daa7c0ef9eed0a296681fc67d0a02419e6c9ae2053866b6ed7e92f054414e3a54c8df51ebc2ceeb10b26cb10683145af60f395bc19bf40436f1280012c4aec3b9fe42a51755c4f463f2ae37aefa7a671c38e891d5163d7efb0bc0200f5872abed6312f1c4fc160cfac84d5104f9cfb94fdbd2246a4ef08a2ebeefa0c1464a1a08b018c9763ad03ddeb6d6b0174844142ee62d803a7a3f07a68f58805c1c9404f12a06947e22fca1d0ad78e8b4480cb7b3b517a8900eaa66e525105051e4434976348d91fda947e0887d888968bcb4296776e8b5ed5885889da06e90b5dccc745e24ecd6de28a08ba6fef685ab2bee8aff6cb2538fc6f00a2fc08330fa6b357325eba9797023711e612c1e56f1387fae09db90a1b4a4054794e9f4d0ae0a9ec6e46587de68b6203eec353976246860faf9a60fc88b3f7c4191b6a3a056bfe51500bfb297c3e2f4c371aa9196de46c2684d1388a792b6e605034253c0c1bc7d0925ba6417c141c5ccfb5a424438649cd70d8a35ffb40290365de01270551b7dfba790a506e528a8282165809648ad15ab29270d5297ff13497575b170e214f2fdd82d0d6c69cb32a457f2057cfab1d8f159aaa1a99c59ca17caf9da8070d5683120e5e9618cf9e7f03e198ecbae43127d67c7a31549b5c5c978f7704031f101fd1ab5bbbc68f5af2a782308fea09bfb51ce4d60a68714c920bf337340e3bca9745d417541b02c6042ab9049359a497bc5f48bb923e05748e1f8adbcc02875bd792eb643ffaa485ad848a32168c87a4d1d4f95414b07a7fb07c74bd51060a048d6932c2a38bc827d87d1c6d9cb479c2d1049665a51f39799f5ca0d15d0458ac85a2ec8235cf5077b049565a678eab6c523531a15d233d50c9c094d3ad079e3d7bece0a9ad9673a77d95210a40117c8918ef62be61afc746626863bfdc0481c5c4b531d362a625da44120c0ad73bf452ffadbc1391d3c66d12a5aa0d430112ac8a6e2ab872bb81fbf3061167ed45979c76c391d9f7a7197b8c03825b660c8886c9888a17a622272997746905ade13e92774e5b1768e3875012a9d1f63d04e659c0bdeafe671f6ec4aaa80d810fa1d574fb7cdeb86e929e42f0f5f92b36018397e5a0ae76721d994a32da4a555a8e0464296f511a8f9e050e7d1804ee810afa5fccf2ec13bcff5cf7154fc7b5dddccdcb3cff4aa08e0fdeedf6d53cd24c05e3fecb18dc5526727c4202d669e7d6fbcd921a5cb6dba90887227f381fcb5f090ff84c43b7778e47bb5b8b1265321817f505997531471290766535624c2acc099fc28e97363d3766bbbda47638b958471c2075d48d84a863f930d457c5e76705fb2a6b243bc6929f2777a13c6994332a122f003eee154c24fd60f971e0fdd20e34805f76b1cf51809b496a79fb7069a542c05d3fcb107e1f2632795503a6a30c24b52b6b2abb96d3cf61d4aae158bc62c00e0a87d2c2dc9a797b8edc1a3035024d4fb500efd5fe823a379a15593c8d67993cb7ba5be34656cbcca8035f7327003dc1ad2942463e474eb6b9389ad1e6803fdde73925e7f8fcf683d47d8157c00c50239a1c4d207d9621dff960aab87dd18bc365b36a13b80d937a809c3ecda4051a5e5df9329d89b03e771a98ccf4833615f5dac627c7e89aacffc0ba065eb7005d542d8d48ae30766bbe9043ccc0256f7552d474569bdb735778d81dae3e32046e3a710f970373195c12c728f437a76d075ffbf6779a0fe7271645f08e37e7094a13376737fbd66fcad8fb7e1cc2a9a02ae25c66e0f03d6b29207f5b9c51a5067ff044552a82caa4260a34df846f6927dbe34749af17cb57e7d3c1b26a683c01136d66869da3419345f3fa323d7cab08cc1ae43296cb217684cd0242acc41b04246ed22fa78c7b83200590e9d4ee706ac36d5b764cae469022ec200340df9202985a9775b2c6e449e7baa996f1c69015a7a4381061ca019807335ed8c017e206029731585d6976022f7108dff3caed5718bff56f53ba8f109f7ca24964c2df01f10a0061a61b58da384953ca0465f4f0c0a4b48ca78f8b2ba1649bbba84d540a7e9d0f19b1250de23973101c0e4257cf5b91f1d8433791b4a6450ce77de5d001a1cf52e0a728bbd2df289a353ae8aa2f4fcbe78877251bcddcf8c189d14a1400bd4a65d1546ba357d1c46199ff7e4429cb8b29ecd446cfb1ea59d7c693d1090eb01c67e6d7a2384835e71454bdd4f6b151b27388a21a536f9133bedbf805110e814081341022f0e2a38fb646f1d9307978cd395a3d69052a427f40dbd41af40e045a4475d035c0b03c1a0955a91d8f691979afa99dbb9c0cc0d5b632c62f1d0b3923d31a37e8dd56ee3b4e3a6fb8ba89ef135ab5b347eaaaa72834e61cac320f6e72013948678e2858f39d29a79a9f0d89abf766e8f73bc03d0dc48aaa5495048566650dea62bc8a382b921807b5e602ce1b81f60d7170c43141ff49b848b504b17c5ac85f789fd9abd0925622023b5f03ffd409b57f5f468d5411493294a001d2da9e4dd77a2f730bacbe9a3dfb624a5ac8faa39377a7a1eb8d3a2eb5742004886dc84967f90ab000bcc5132e7487ae0b13ba7c2b226d622505600be9800c0b32b4de820e742c3358e75ff4330a3498fecc808b31a255a1cd1413a478cd0e0e985dbf21b92fb2ae1cdc19a7240e3a646a53102ce10c5e4c71a24b637a47bb037ddacb3e84c98f2c9d6d9b26d02b3a270be18bbac13d58972fd8e1923aacea0526c8c2a6af34ba6867940e58f7753e6d7181b1b6ec9d9bc5315108d43e0065041b5bca8b38b5d4c55cefd44a9dff77d440e76832fc951f376afc47e318452b0d1a0d71f26b57af2b7d2cc77c7f410b48f8bce9e265c6acf07d188d99554a4301a07aeea9d979ecf35398ac4fa3eedc02534c50f8e6841770818dff3225958602abdc21ad474ebdd429a6332d803aa9bd3fdcaf19bd57c58b1e7bab9fb9fa8f0f3806b837c259acc0d58c6012a75314054c84167a56e057515d1fa8b2fe5ed500cac8aa19ef1878d4dc5cd9f1b489a00754f60e95bfbb4d4aed701f70c9bc5202f19357d3ca4e51c2a58a163e2d715fff10b0d7288bc557d45bc82cafc2bbf10fd7f464d72a2a80634f3655eaf675755fc0e81f96a55f994bc96d6e7100c9970fbbbd7e875fc3588162194519485476b1aba3329cceca66c7697a15a30c48b40eb85769620eec4ed22db9ab7a4beeb196a94e4358464c39d7df59e8fc4852f9012a68ac10414a132bbf5ed54c585a9ae8e5d69414b4e4d8c044170f369efc0402ef1067f385fa6a6522dc79f7e1272dc2d8817e326a5dbe8183e4abcf6b33a4083b7f531f641e90c9c418644e749c9c564078c0cae8150313f0056da5bade9a0bac34c6aacd391e5c7eba8f8b9c9f5f562ad8a16e3a92c0f1974575d0cd39a20d90f7efbfb164798ddc03c0312cd3f7fd69fcb880ad1b5e73b78f8e61442cca094322c42c27943df2f81ec138abd29ceb7cc59e703ee881328e50f26818f5870e7e9118cdfd85cc34e79965750d74f7e4de803690b346395fa634f865acce780c8aa5289c8bef404a33d345ec0df8fdd8668775ab09d7d057d05a1d8bc103ca096e53ed546bd808915900746e38ba9f118fdb43e768c0c02d9d21e1cffde0c00953dca684886c45b3d34ae06b11434ccec98b85b33195b9ea23a7d6fef26351073eb7ad717d4d81574ce32e83e775b67430ee26f5838ba1964b810315106d7f05c1bd4cb51f5c893fc78a92cf2e711e39ae74683138a0dcc0173ecb930e11c8005002a196a236963073c8e1026066e738883588bc04e5178a04a6d2dbd256960735d218d4cbc5c42e68a5f7bb2ba529dd8aca08bd3d3393f33a3940baae3e850495dfd762cc5feacd8c146567f2ec17f86ea12f79c342dc5f70bc5b123b6b2c0b28a339dd26fd6c5343537f788295a16f23e43063424f7353d2524714d5415b0f32a2f87c9bf591ba1dbfaefe2f0e06b60a7e8c73848216ab32a335ab09eab90ea86e35405a07ee026fc43d4c299b7d158665ef55b5e31fa9a31aa149144aea0324cf58148ff4122583868123edb10517799f9a31a3ac6e6191b17927c9037601da5059c37d2e37cddb48643f25af43b9ac5e78372343a50138477ab361c4e90f1d83c10bc23a31bb32e5a2859a32a323673c4d839bc457a941c52f5869b2a401f22b108839c2d02f51cc6779e577473969fdc0a9e1505dcdd45a57dcf9239700c2f7c0931953f2d6e3d958af895d71cc83bd2ada24a287574ab9ab7b030c84066077576bc8a9ca5be6f43e8566068b7f3620234f7a119bddb6b714262321eb0c39fed73029b828ae4a0fe92f6d0dddb49bf7afdbe251107ccc0f6e42b320aa0c3db8cfd704111ccf7fb57e33ed71fae0f866b90ecf090043a27c0630f2943f0d39cda3158180f1f8fbf77da142db4291fbf8657fbb0a2153b1b09d5d9a778307325c6eac179a1bb6a54db77f33f0a055ac57a91956b9f758d35a8ed6d5756e051eefdc28cfa90541c8894a25c6bac132f50880275097c9b402b9630006b33b0dc3904d2f1f0b5ca838725911b227674e9816012386093f8b0ecd771bb615f4027c5e21838b6817cbb3335f5815a44b349baae068d4e38ba52f57f9831c90860e1c449665183f7a22a0c54551831c02ca83876f9f57c860f4b681cf63793fb8098a518875d846dc4fc9e2a2304213893c9783dd8c743bdd80764743eba8b2350f2e59c48cdd26e6d8cf8e4d9adcbbe034eab37a1dc9ba9040a1a2c0102074010d36552b1cbc7717179728abd519987c011b1318509dfeb60fd42c706a77023b05106fee3a72395c528f72f02fb3dcb0fd493f87c8a4b356989147ebe416784007a55457089945f608435aff0d0a2d18893fd810a4616d6030270545436adde809349ac3a9cf2c927ec40428614af36868d14d627cfdd93bbc5f6cf8a21cdcda0fe9874ac773be6eb5022ca057a7f1002b6b9e4dd67ae4029bd16d6bfa620e7e0ba70524683c7ea28c1128ccdc8ad7ca4e558027fdc195607aa1e2fa3cca509c02dce1864f338b8ae1a0e6c4d20b9261755c0649eed775ab774a8dbb56f82ea70b4f1d4ad58ab8aef1c222736d42b8a39be6353ca29981119a1a7404bb21d4050d0f698e272311dc1ba5eff85d07688f190e8709d008b047cd44ca90f716adfc00f345f2d648ef2acceed6499bc335082b1b7bed72b9989426f01f2112897a1d007af110ead6941cd742ef1a0dc4c90963407fdc5f10d8898acb21be43d275ee0d31737d92b33fdc5cac1ed8f5838055fb13f467c8eddaa2294900fc1cc808e40b94d6ed317a76f3788f0c857ba75a8fc6ce752ec3ada66dc4302f776e6cf8ed0aa7b383becdfedecbf608e3df224304f93444e6cdb936fb148ada29635087b70802eda172f60ec61a883b9fe424274396c919f50fd07ab0754c8170a7ccb62c081ed8bb96c8381cb68d3267bd6754b6995f69f896151f1633768ccdb30ce8ae082b337d82313bd5172b7cf3cdaae73a08fd4f2d26f1e96f140aa062362a02e2034246a8fbe2d5ee0b6b82b15b6caed6f8f54f539bc3b593b9d8ef43a7c1574302fb9872aee45ae0fe267a22aee24cdce5deab4e408919d91a8b53e75d95473b08c82ac4a5175aef72e5ce6d834c401c4f9413588702438e95775aebc970c95308912b3f2179764d1a6db3785f03df237b745f5356c5fb018801b42e74ef6b830258d46c290ce7f3d619d75e5110ce7602c32dc1541bb74e94aafea42f003110067513d74aecacae98cd1363871626668d3575bc70a8c05bafee08b5df24ccf30cc20cf10a3b9d9d01d88a2ec9dafb733c077fb90cfaa9848db658981188088b0208b3faf042e2b35918b6e8ab3f557b9eaa11f0726f6c4d672bc43c1f61be440f6989955bf71b92d45c9842666e9fa39f6bb7450355755ad2d05b6208b4ea540bf516d02a72db654b8ae882488d34c3772a63b121ad9881db19de51a6b11c0901874af81c08cd8de93d47cbcb3fc4faef512885293f23db9c1a78270b0f800f07a37f38297534629fb1e36eb31bb6457bfcee70aaae60d1f6c394e5848b12190c7598279433edd0e90eab560c442da49b8fa7c557a33db151b045ec941521f10fab4ad5a179924b52dae1fe703cd06eb83f1b4755f2f5436c8aa19117cd4419001b35c0b04653ad2308831326ade6b82bc05edd2b4ddf57001a3341fbec0f9307ed56a77740adc32cb20b7ff73a1ed20b0e11c860d857146de643ca1664a2b602edf49af1993946126b0523703f3d979f7ecb30a5f677b9a672118e07f1abdc08730940b4b8b2f7dd8851b3aa9a6c02894e90d3ddc1e4f20fe3be395144bdd00504ffc8dc8fcc6c3eed60d43eaea4dbf3f3614759b86457fad2ae4c3b0e031c0b54c44234dfd529514bbd76f952bf1512a6d84b5bab97a7f5390883de21aeda0792eb6cdb747cbbce8a71725c79a283a99a93dd5d10fef0afe2f9093ca39f310976fee51b6bc5e7b8793c74d75e6bf10e86e2df13ea32ac61526f25e3ad85b80fe260f0e874edf0b7f62522209676512cb3f88bc31d17d1e9d981162da3651a047a8c006d50763acd5ff9ec0f83f34176055e198fa75442e9366999c5932c280f8ac50bef654479571ebe95c808f91410a61000508d1833b98eedcd29a96cda04 -generate_ring_signature e46bda5f8d177a85b3d4f3f9b52ec30d3675e7239eb271e9756c1b9dc52d0c1a fb375e609a51a1a54d30f6554e5481a94158e49705233340357ad15f25c832b5 1 d9515348ed96ba26f155412e0b4b7fb190f48c1adff6d6f7bb0d68c4ebe432fe 70df55444de1551ddad38c3ba80c388032316cba280052447947c02151dbef0e 0 454e4c6db4545872d762426ade93dbb89c1340a249540451b887bd081d90950e883b17bd17696372f1662b4242149a2d14024f3c1a6667bfb0609cf42c475202 -generate_ring_signature dd3a63be8c1d0e7c20341ff51de1ae69be6ad9a4af2494d969de4b5c5a3d1213 bed9efb67d0318e6e2fa22a32ab381332b38f0894f8a8ada7f8b4372ebfc967e 4 066b617b0fb79775aa1b548de8757a121e7d0e38459a6bc5dd0a587a88fa26b3 193a48039163ffb32e1ffa931abbee6e1aded29f388aa635a3ab148c8d5e2568 4732c8e3a686c813b657069e304e06df196259ac5f1634bfb7713438345f053f 4f1a2284c22c27aacd12d68d25ab10b1fcdef99a708fe2903c30e185fbc99c28 79be700bc846a57a8404540767e0c3f22a32f812668276c2d6b9a2938d286a06 1 c20441c768a58a8297250b384d6bcaf2572d9a9b91c8b5cf3158c39b0fee800de9a77b7643fc79279a5dd6f25ca4490fe3706b8ea32fbfb4f98f0896a3e52f0112ec54955efceca566e3344e522e09f9a85f312dab24cc897595349f89e5e00082aab587427b2a4458fbd81531009b086b427d2ed28937d5cccc4f01382bc90605b0e826e4f171a61690cf92779b948b54f41a3943fc278ee0ab8479494f770086006ad414290d877ba9650d8782679246e0c53092c8b4120e1fe545206b0c0a73bcb1430e95a6ff86302047d5176196a24890d7d7c8e5da204ccd3554547b0abe99de271f9ce6b4256f733d744b282ab35ea86c6034c18ef395f7b9efeb2907 -generate_ring_signature 2a3fecc5533445d1ff407029a75e714626b2eaee3f6479c67a27201ed06b2b9d 01c8dbe8167151ed13b296b133178b80e39a38b0c0c38051040ade484b69e4d2 221 8b859d51a272d7d7f42eecf840f7fa9149a4dbd6a7724f6afa17c4a1bf26d8ae 8d6f021c956ea9a626077dd81b5fb6e459a370b56deb4f4fface816bfaf00668 815a27ec056a040e436e299d9632876500d90f3dde3eaf1107d9503788cc0c95 a24932b33273a1ceda8f5b32f270fc6e0df415fff64ad6b39017af5359242b6f 9a0adcc60772f3f654b3b417943433b00b6bfc27e8b8afe5fbbf844147e8c5ab 90f1e5a5891e354d4fd02205a33f49657a5de15d7ff4ddc31f39d8643d62aac5 450f08d11598d355afdb687cce5632cbbf31e3c1e0766765ac352dcaf036a67f 3866d2f6934814b1095f0e0a1f147b93c50f15716e254c9e7d74645a4df78e0e e3491b5ebfe4fd7c5bd3f1dd3a40ab2825bec7c4d827e0599f1145fe51629f3e 62c9bd5660490a1d2e9ff39215eb040f736051a242963bf2f272eb9d73fe132f 71e01607b9b65d973be08bf5983d862bd42ef2c3f0fd6be7ba33a54a5cb909e3 d561622d76d33431f0a7881258e4906e5774696441e93194eace2bede8d5d095 9e1c44bf1c3513bcf7ad2c087c0eb6f0d19ac9288a21838cbe629312543a7d32 506331bba887f11ea4ad8c9044e332c082302838c750f0b0ba8936b8dfc70715 a1f5054ef80b2ec1f151f60451f4c982280f128b8ed831095ff4479f2adc8b19 19dd0493e1890f8e0ac05b9fcdaaa0bd9688e2ec9f47e2432f02ca60992e4bb7 8d2df708b2ce601d1bf7d762da0d31681643d74b8ef61e061c1f67b8e88f3975 b765132b1552f0c34491edcb6d601849aee7557ca805edc5296334860376838c e4e824505152dc5a1800451cfa73437c266b6a0ddc9a6b13f8a82f2a308195e3 33be8cd89800df491acc53ec6eff8132fc3875a454d2fccd019fc6a3d4aca291 f7289f047047bfe7fb28bd1466daba43a6b73318aaf082fe49a9703f2650c54f 85aab4738840c444824cadc97dac6f1b738102ab8d495c5760ed553ec8cdb8c9 eb87a343835083e45d815729559c3e1de67d69ce50f0f1bee874a3e90b8701d8 c58861edf4520042f37e873b69016220706fed7fbb5f4ebc1e21b9fb5018e20b 9febb8ed1c5a2cae82c73149c0fd7accdac0451b8fdc81121b954dcc500e5dd0 c5825602f9ec7f01f1d7905c3b3e7a4671178863672f3ef2c83e1abee6788522 fb3fa6e53af880f0cf31f95a65b5181b4be788265f9a1c0cdd5c3f1718b5bf83 f6b63d638100268978d89ed0f6005d24a1b143c112c73a918ad27b6eed6f0f1d b4589104a456ee51feadfc532a6f52e5bca5eb9070d0a77a02624d774d4d2eca 1fc0934d38877661c56143af7277eb837868e8465f0a3351efe115d1f61a6b20 bc4f9dbd0695c462a8b57fd6b0af3974104bde49c6062b5c4bcd09615d028b7c bbefa2f48cf69f7b1df407805e23764ac7266494449ab9fdef0641b4f13fefc5 1c9ce4f9a6a3931a3ad753ba874fae5acd3e85351b3456dad3c0a8ef85028633 b378c247b6855244af5246a0760ddd1a703629716b16b50f2f7afa5ebfd57e01 88adc9c2bec405b609d7190671cd84ca990e3f2794ab3550fcf5ceb569009fa9 d063eb0d4f7ab5f0b7bff340644c61590014570207189c73846322e0b77f8392 7ef5e21552383ce730b75abb6de94d8623ef8987e2d382d85dca46d2f5b94324 7aeaacdda090144ac43de8e04075421917f57f1044871738ad85c3933a7b92ce 73efd0833c7b48c215c0f92d2e72c9584bf1a5d6f15c9d99e19a6f6808a9ed8b 65b8c07bc87e20fb9ca0fb72787720d7a6653b04e11d4d31f6c699fed3ceb5fd 250511f67f3ec1d43778d1c712a6b72090c1812349262f5aadbd37e6f3cb69ef dd168f71e4b227d7417b3a6d0c6dba72b1fe04e47b3816569f149ff7e736c6d4 e1837515ea0184def7085f6455cbb2ea7d957942dc3a67d8c6c2ac5c3f588528 be818f8f702a06b5757bf5620b6ed5c110924a73252d5818b4903036b38e9ac2 9348070e09c4ea8e76401842a74161a94a84a46143a1242e60bcd7769f8c10a4 775b7d0938679d7a173f56742e08d0eb911378e65e137548d9ccf8ac6f61e00a b44cbf01cc2e599fdce193fc44b58c7e9f67532e6aa0cc18a771823b7709f379 2452d9e33927a56350678ca3975ed7b2c8e6d4d567ad7ac0e4126b1a55dde552 75b837f6b344b941183721fb45bed9ea0f5ad890e05f465b4f0078b8c860ea30 626ef8f4b4cd5a655548792ac7acb47f3bd0f22411a91d39a6460773b8b962d8 173a57cf7b632d55ba237914c471a75ebd5023b471406501db025318dd7c5afb 6e50ed5141d31c5c71a32b01dff6c0f9b4d1fafcdb59e7363d0b0de0f6f22049 353c625beb6b2e3ad123fbb9a5b2596f38021bbeef7b5e0c10ecc9234f6d553f cd24fa2bd9e36f5ff131b44852c0bcb99d82f055792ed8dff48e837d1b4212ca 2388231a621404db213c4060ff612cb04291828799919be7462d9b0ce8db9642 f05660f72b5d1b9c8713a957604cb32b1713a8cbe32a3ed4c30f9f581d1b10e3 a9604a2437780030a1ea1fc481a7d2d538570c08f355696156a8313c4dd6e00c b759e38e1dc01c64386765f177c8aa429cee8ead275d6ceb7eb13ba22780e430 aca51ddfbfb7e7d73b15a6a620bd5be30c5ea0fff58d2952f2764ea5378f8e15 7bebea82546589b5992f3990f088c948ffc03551d65275de4cf379fe08a231f5 637176cb1b76867a4a07c3f4a7e972ae621c128cef42937a4f367b5b52688ae1 444b6b8d2ad3f031dc9884f1c8d33bf92b0f8e51a9decd2d1853a613a09ef956 d2cabe5ea3d6b8e8539f6ecea33ec239ece6b1d362ec8ace8900c7f5d32b18d0 12ce5eb61291c983d787b75b4bd4b4fcec42870f7f1cfe8d7864d955705863e3 ac72fb9e0b6a14fe14a7e4313c3df10a5f6a4e424c8467547d02ee590df993b1 8e7757946777d73b44177c05b9beae59bc440eac16f548c95931ef4d608401cd 649919d443bfae5542ed3d35dda9d4a8f5027f8529eb735ed8cb27ee408783c6 59510fe2efccbc9e071932f0a1d6295e9f0c23375af49e4e1ac630b6b2ef7ef9 bf061ea258631a7bf55c1bb2e782d745f8fef6433688f4a254b5871f1a59cc8c 37542533284da65b04bb83ee315c0aa265552d9583d7805f02a4d683ebe87846 b32389352f301af4a588d53580b2af6d76947705d45414e18c4ba8865dff0f33 a48963364cf079b4fe0128013c3d937ec06ac6d3cc4adb28165c39a37a0319fb cd8c533905d1ff627b1e69130e3758472c86174adb5002f0220369d51133aaeb 61e6c4d613863a1bfa1f9124380cce995ac5dd90732f5979bcb29d42de22eea4 2d0723b5254153eb2a17896b7fc15b8059d29e5005020ef172aa50a9ab7ea7a8 8a743f0297f0efe2ddca293984ee8d3db4f5cc461c2aa9a487f13494b59fa25b e6a3d6ec91a5aa85079c7580779b393a04c54782b61e0bceb0d0d0275cacea69 0df4d37fb5c42f35624003a5cfca5c3d6eb240758569b5d26f16616551574ab3 c9a427a5d45f34e865751f516eb16c1645fc0d34f9d3f29d15defd41c90d7c11 d611c94f2cfee7f21c74272603f669eed93b9be74f5e0aab045bdeaf02218e11 4a414aa192df1dc95b7bccd5352c3dacee9da798a587be8d0dcfc2d932e53c23 d432cc97206bf2028e875b0c39e098029670e2c499b88ef451b95c526bba2f09 bc4594e40b1c06c2dce163483efb045e8378d73d819d4364f8fa4519c8704a16 37e6a276d50c83cb2ab5a9f7ced57f2b229edd17e2c91fdacc32d93925f10145 290c5152fffc9d95e8dc1d815fe633cd79b1427d50c8db67e8b68aa2c4b98470 8fc57c77048100572648ff75b9c5d82dc1c0d0fa5e06f05afbf9f201712adc4c 0bded12b4809fc9ac013e84373728305e8464ef4c098932625294a4011450e25 b8e535e32f58d625101ff5318e30492fb54507ed21adce526c366d5d3e6830e0 f8377198a04f2faaeddb95b3184eda59ab45d52583bc8e6277e326817f5e288a 8ebb388549bac9d0bc58a50efa290860bafb5c558ac5ff97014e5e91e2b5d6f9 80d45483e6d7e55efe1cf485514b7c9b15ad69550f8228adab97dc7dedb77f2b 860df3068a952468d7de7b480ee3c114e2af6a1bfd57718ea70a532156d316ae 1e7db7133690a920da094aaf299bce31255ebbd1ff89019334069563d97a428f 4f729843f70c02f0aae4848573fa65fc44fea293545643effc5a0414cbd02b72 f6ea093551a609547278602ff331bffcd788474b51a4ccf1576e9c8f4c351d0f 0d1425e162b53dad767159eefcc68e3481e7aa15cf5dde15c560e86e9cb0735a 0e8af77622167bf235723615c1c3d7a819ff60db6c5ae32e80f5a2856a68daaa 1e59be38167c56a186e49d712150083c5c1dd7588433b428e23062de4221fff7 b43c12e5bf504f04fdc66bda7621af9e8660bdfccb2816075159ac2713ca3f2a 9f7666358a33abab5fd147f4adcdf57bb32e12150c079be07d8fdeaa9ea8beed 521a52a0b3e192d19c0d35c561f27f6eeca58ff13e58d529beee488b93d2f3d7 7e7effff3b399f59166c50e33f5cfc0bb5260ced230184bf8992be8dcf887b10 ace89f0a5fde0334b8c4cd6372814c0e424e477a71838d4ee4be6b063ef83011 c6f19f9441c7443c9aad2a73076f466f5e4f905ea61c3f294bc20b588959ee2a 2a635eef90451e80ada03b004c75fab54e15e69f569f9c3e9129f58c713f2b49 4e822815ba216e4e657c7a4ef7937215b6d62196d294345f321589d5dce6e209 a68901cbeaa21bee99f17aeda62c6fe986a2938494df1fac1741511c6c11cf88 43d3eb9c030f4d9964d5e9c6ecf2b639525d633187e11f0da531bab6e5ee8a01 c0f196df45d950b38ec8d2629d12aab07856874494c29f71c6881c1d9854d2f8 43c9afda75cb063deb114f4b37dbfb0078f8cbee6b8cb740b97227cddffa6a18 d75e8c0dd232a4a241372836d8f12afa216dc4aba3cca2f7238d37cdaa54e1a1 edf772170c15f645d820e11095642e27a7fcb2a1850d1fd08f3e8f17655cb480 9c47f9140a0615c1532835e0f0bd405ce7ccc8b385febd11a1bdf68f3e921259 9d73a698ad37b84a11b02b49d6bfc96929194baba505645ef1761bf23fedcf61 2643526f0e6e1cf9f2af821278710b7065f0cae0ab880e9058c329ffdfdf3ec0 bb76790fa787e08a246e71857c921d4748b40ac6e8451baad291e7424edb40c8 35e56823de9d39318ad185de2a1d4568835b54a6abcf49eecba5f97ec49006c1 9c705590ea073318a4982ce47e67d422e751ad1043f7510e6a104fa8a7a81496 1bdfd29ec07987e54e8c928f680cc028dd1672ee6415727a8d66639cef804fb6 6b389fe787a31b450f1818ffaa0db20cdfa9b6880fa0ce0a7c541a90dca40242 dde10545b8e2fd54ffdfd483c18afccd262e204605538588848ea1c0c99efb03 4a10e9ff89c15561cb1157fc992e6133281504420f132623b9de3174658d28c2 c05d11b8468a9c285d195c40436785b680eff853135ad3202d85fd6b3b71efbc 709d67e136f6fbb15c6b209d56c894a0012d3a3010bf785ec6cf46565c7ecaa1 a551208cb6283ff8ddab393d47d2f930957a931a70212bd55fb83eb03497ffb8 d65abbf9e83cd429a72a2c0b11e878e5a4de06c256eb6ae8b7ece0ee7ec4e899 a03de6ac90e23e9470213a21b251e70e74ecb35077f2485ebb2f7d150c1f79a1 83ce4ba9a0d68fe3ce9421f42b8a010c550fb6100c2f8ab008be42902f3c036c eb4edd84bbf5d3299f3dae898586c55b4483e0afe6f4c253a779b59a928d21a6 10b0465dbbc0d6ccdd8fefadffcdc6cf636c7d6eda6ba735718e6e0bd4ea0ee7 f77556104aa4371f176d65aa01c0c3dc4eda40e10df76beb443b450ba666c16b fceac9a002728d8175618729f289d0e9a1dfe429ef2b9758aeaa63990daf74ec 96ac9c4c4680607dd545ce646e48ba793e146988aada0c9c0581a41c7d9de1d3 0f749c6dfa9b9d40996764cca834443751a654c1396161ff146f145158946816 873a8cfa29fadc9e3fa66fcdba54a99c0d5a645880fe162ca31dab20003988f1 a9138ec342b3cfd9fb544a5e5c148d2ca59bc62f54d27fb22c39e6f6915ccae3 e43bae09f5a5fa2596ea6f61dce8d81f0b9d51ae509cdaae1a24b963c274ef40 7a1b36d60806fbc951852e66ef531c403925e9bfe7ac324fefbb2fd81a43baf8 fa159a7bfc0fd40d2bc5a70a1bc9852bf10bcdef8d8e2e1ca9c62161b719e1e6 ca533537e8ea96c9b417a07b70a3ec07d0ec256f1bd14e8b34e4d1c89f72097c ae8e7c402fa13e037cc53e9fcabf06811b17afa21020b647b1dd686834a2d67a 6ae329a6be8103e2e4976e0950fc024639b41b8bd921ce630667216be4359db5 1a5b42a72f462555ea91f9e43c52f9154feac0f2b4ecdedb450143d090b93d06 f6e54cd2ebb518244dc737487da1d95e303b6ab78196a6c9c59212f18824b0a3 51ad7925ae3bec9cb057ca255ae54aa59698c225e5a0293e09d0e83fc4e5b7df 4984ed3a617023b33947a5644cd4bbe8ca79b562a091f7f61080c96de880a9fb d9fae11e8d2eca9d88188fa1b5dd6088ce1875eedb85335003b8aae6abef11d4 e20fba3947dc0003f5b6ebc49a40df8c029408546659375d5b22974c7d3ed1fb ed2616df75233d9c496a1f0d130ec9bb0a318c0b05047fd8bdcf1ebc2edf62f8 482f06cb80351780d5d49898014ed4f4582348c4ad33f283311027382516c54d a59efdaecb58328250fe5e506a5afe36662a5265cb4782eac0b3839761e87b5c 8870807b28a03b28321d06f6296ecace564cdb01d7f37592168b2d2ca075c7c5 62a59c15f0a3dfb0c1949dbe156c2294db9f840dc3bdd4b342b8405aa28391fb db2b5cf69db1da72690f3d0bcdb621e1ab6bf2e8e40e1d0202dcf35d49904067 31aa4a6adbc872d7d62189c83880b5ff945bed0da282b75dad30a60790c0f33a c93ac37aea14d028789d9db7fa08d8ca9856c4b1c101e5f212a2bbd71e1784d3 c8bcacc9a538112417d16664b694a837e6d397b1a4de3aab80db4d326750cee7 a784aa9d92f6e9379e576afd1175a0e5b0540f3145173fb30784a830e85487dd 0a564ec2c2d56e504bbc96330a884de705a47a25142e44e039b915264d74fd3a eb71a630f352135a48b03da1d0cf9d96832fa4ce940e6bc1ff73c47371b47754 36431d4d8a33fc41e52add24baf42d705860d5cfc83aadfccc6e4fbe7c6c972c d16de71a298b57cb77398f2f0226415bf28602c439bffe0334b0d68905d219b5 4ffdcfe47d26d0d30ef567366c6eb46275989a8f847b39a8f30d89a74ebde012 1c1832371c681f58df93c6c4fe33292285a801c2e21ded6e8191f80800b981ea d5fe4823f4b5c221a275060de1d1bdf72672dce31bd3f2e0a474fa8c38c41077 bab9b85dda37d0559958c8cb542609ac95a5963fd4631ccf14a6535d320cf9e9 15f589eed4f67eb0593ac0cba466f4b1be1bed4fca49aca54536a4a24a77f29b ed67d0fca43e7dc33c83efb68375c3a19fa8eb4536c49acc27621ff542e86ab6 ca9dbdcd0b47bf2adb0e773a0cede86e7dd2aabc5e6b95c2fc3c1b8c5210ae59 5e915792e97503b657a9338082f5ba9b24e2fee4d1a2938a3acc902e3dbf4997 d633420dafefbf863766da7c63606d22239d6548894e26f06d891bd406b21524 cf4f849796892dd5adccde35a74999c25c6ad3c803718becb4243ba6d8c7e1d5 13167c9c0793e87af248369823f245d99592a43c60a15349d44fe233c5bb9f2a e183538bc5ee8ed570eb66d393fd056793e269b109043eae5c01a0a090d18b3e 276b50ea1b15f2a45809d0b22cc7834e406c1c1054c0c7f7d8525c32e10719b3 191e9285d6d24e95fd7934a09d44920af2042291e4c9a8586e0515225c8413e6 de9d26522bf6f4ed113d33a1443c5f160de08691daf09272e7ea03232f4e6e84 d333341edd7b38a52be376f8287d13f89bf6b01dea8a50aceb421d9f602b05a5 b8a0364136c444f623e4dda641be4088ffb270a4c455c6e941d341681c6d6d6e a62fee4d42bc6db241ff2513f2540f6c7db4fee24b129717e3004f95960397af c259025eb09f04eb7431f508b3c6999a3418bf6bab8af9b55cb7d3fa4eaedb87 c27c59ea6664edb562515b3f4c71715483aac96657e26017b054f01777db8887 f91c66dd8483e994c9ebaac3688076e8797d4d67668909cb2192d279d42379c9 9f58c7886468a9c83ba1642052eef85ed2a45ce928fcf10d173f4ff4c89dbb44 4653a8407b6d1cc000eb05b1b840dd14bb6188ef1d37a8ac72e12217fe166472 93b14e264350b8c30798d2a39b9072feee77dda2b52e375196b3106022b4bedb 5273509157346436df1b7f67faeed0c0a43e999f398466c246bc2e9286b87459 10017a84966ba1304aa896dc9fc5708330f19054d064687b39376a9fa3241fb4 9d9063ccd0d2d540300637243750c6bc652c1f119651f81140e5322879d82f8a 940eb9dccd7636d1f891ade6e4306521419fe57030ad7175cb3c8da0fc72304d a820c82bb599fdf8d086d39acd194e39f132a85f18d8300f4cc56a8220d225c2 233233f3420506c6227ac4a72e37a4bc907d63b291a4f32d4123a7da47159514 7fdbf1d6f41f271391410a05f7a8d30e55e1777905673b8d4b3d5219a47d656c 2661848fb57f9b929c0982fa6fb2ed2e504d2d44448cf087952dde5ef2ccd758 07621d43208d862972ab719f654d757ceccec4f52dd70f013e2cddbb6119219d 53f0af85e186307dcff8b2ae1b87f9dbfc5250f5bfdb77f36ef3aee934853150 34c6dc33ff9b31f5cb61c6cd9cac5a57494ac89ff81f6eb768373507e2331f2c 9dd70bd2b9228331231be2a27d40d3d9a1bcef5c5065ea456f091d554b47e5ce c3f51b37f9ca58c36acc1832c7a0ae39d1a4cff8fd2f754d3d05d546d2c0c561 362b58b15e123a74435aea20c0c96ddb5ffc7413018c4ff6540b6c3b941d1b88 445a8726a0fe3b24c15b4d1df672059bace0614e07f61b3984a624b9eff63aaf a49862a6574460fc5e9b3432da844458d407ab51632f28b02aec0d5af356937f c9d3ce57149377557ebb03ffd48b85bfe30f5fe44819e2d589ebeefd05f4da1c 9184c6dcbadcc0425ca7f69ed9a5f120cb9fbd9126c761cfb10307c90f75af22 e5b3ae461948bb71e5d5c1c408cb68a6fc1773b89f2a16fb06bddea5bebfe84d 78717fce1d774e4857b31faee17551a3c70a161f9733b9e82cae3839de372e16 5259c3ef1249d01c1b4270759a51df4e9c04dda8a96eebf5031b9b49ad47a5fc 2c0a3e8f2ac581b434d56652e75893f86395d8e34e0852ddec0496e35e286b91 3b2af796e8f040399653cc212a709de714d5259e74869c8ca1879c4c35b16acd db2975a318a9c2e4e8fa5be0c62e49d88c4b6606dc1d9cf71538c4508d68d92f d5c78555d2a2a033d104c868c3d908855247a0a9b31047b29d169b1be2eb20f1 d1a7e0ab08e9236ee740f2c42c57212be40213c9a5507d1f383d1c8371b47669 f7b7d65be98a75555b03e382aa01c790f1952dc8f8b019a34f2d6418ff64466d 773bc5294e59c1a624f89f25b359df72dc603234815e17abc0afe586dd33b264 25806ec523cb87bd4c3f5425a78fd7f879978b9d0a5bc2efc4db3a80340b91c5 1a0d6042f55fc72643c05ef6bd3a0c3a05589780b9c37779dedfabfa12be6926 4474180e2cb3f2d3ee664c63cda703a82d49c0da75dfdca8aa10c173a85d04f7 d2f254cb36b039214a42b95fdefdb45ccff86bcab3f38bbf3f06f7bd6bd6c324 fff1eb7b3a6e85f22fe1cf95d3d7e28b2c750a3e711b75ecda1f21279301cd7b d82cdfe7dbb0d0d15a39d392e5529b61256cf6dac2ca0c04f10c81feddcb5502 1f7426796d532dbe452a65916e56583c418ddab1d655dbfe9e4047d5fefa95c6 acd10a2211b93dbb4ab82079d09b712f7060980023a09ce67440af525afadf04 190 91dae06180a32c3b02c5218eae4ac14ce9c629a65fc44ff15afb2f50f30f6804649b4dbd8f7c746e09977f7ffb6b29b3a7e8b4aeec0cbc1f9db85a9124fd08099dfa126d9f9335773b043a888f7438836e105cf31b5b35294403ebdab3f768046da009bdf6a9950e0735f88ac3d33bf1a8b38b109afa3830991e3e5a708ecc0b5dbe69c6be585527e96c50362a69404b81c18900aabd1512201207906036740129a050819c2932489c68976ebd621614b63797fec6dae88d1e80b5181fe66706ff0ec97149908b97947f5ccbd5298c2ed346176ab7adfd3788d277bb403b4d00caa8f3fbe5cffdb903d9ecceaf81e5db0b0151d6472b5e1c2e976ae5c89a040fffda036ed7228a7c40ccbb6918f270b227b1c821a73fca4edc92dc486d63ee004f1ef59f87f491ed3fb801d96b499bebd8a794f8c643e14ff0c0061486b58a0b100c33f4b94e26912b06a009bef9a6541b23311b865aaf1a719844e9f9761e010f77bf3f76c6c983f88d2e8d31d5af52899fc1c1d37cd879109781937b0a240ff7c791420a9efd7cdc75f2bd4bd78cdb73d81d3b08b0aee6228653bfc12cc908d72e70745e29e0f1c8e13067d1d02c2a680c83dbb8baf6a290fecb1e70bbea0bdaee2bcacf997408db98949ec0b36e29eaa190fce14a510ea2dbc6935daf0c01fdf17211ff4e74e7d0594f2d9ba5b99c29ca61a0a4b29c1fcb5035cebd171d0e43eb63200bfb73b7a2e01049a5f0935829c03e5333e158cfe40068f68ba4f80da446438ab8fc425f9a43844c085bb7fec6e5cd47f56b15d63ff26b3b79542206f24d3445cbc746207a9456d3626bef29bfcf8e67316fd2fdf65cc6864de8e000add13b62bbc801a87ff46a2a2773fdd883e463e1e34a73c6d7595f0a09b4ae063942ff1fb61d3479f0a1c0add58ca93edc7bda90e1198b5672802d9093c6a00905089c50c440f7dd9286bbdf24ef57a4714ac09cbabd7e6a19209b9311d6650ea87eafb06ae4a8125bb3c18c81a7519de252d0edb0651364a4499c19a2ce5602e6f101d0e1c5d4029e2cc94816fd3cc3c7cc19de8fb6795082d55e4b592d480f126b5ea3d12e0ca7b4856aff1707a19402580a79d5c241f59c0956c15c96a70fd3c54366537a68e5c689b934c1ba22955e65359ecd9f5812f9827f0507e7ae04fe6d660a566dca1d40b6e8c91adb94f3443320bd5394ecf9c41d4df136896d06f3068bd9ff11899e62cefbe32968127e19cb4bfe19e01d100c95f253315258084fcc6c02d5a9295b123712de898aac3db16be9ec5f4447ff6ba26558856cf80e7101a8909d9933d8099b42a4a80ea1f1fd2dd65d1d78bdf67ea247a64f6cec05669d75f76c57afc346ddb6776ba53f41f65fe9a1f4dff9c8238710738121e006529e87db539acf9df114a9220e1e5f0e2ce25dc5ae4dff504ae3dd5aa7a81901a73e1e7b9d32c9c70d5b81efa57b6c259633b1ddc9ef98b9a00c7d341f5dab00fa30796922db48d929d731a713447927059093ca4f3bd9e2fc07f5fe4f873f0bbace7386c733fae904e0e2e528efa66c9e06ca5e3330fd980c41fd72bca38e06520d6f997f6f6bcaee71602b7a5ae2f35bb6078b6bf6d815179d32f723b8e40f4cbff32f1a32681aae630fcb454e9e0921921bcdac9b19dc814232040bf7ba0be80152bda1b084f32312ec0b33f0628101e5f2fde33ed1a47a170a233f988f0c5c4e7c069c66894d8ba3ed3cb9ec47d5d7010ff1c162484376d1595a09dc7e00d85454b69212351e18ba29afd9bd672867316b78b34192514ad87b858b2f5b03379979a57c3deb37fc8e437354956609ff384a5f9177f9f29899dc5cc3647403b4f3f92942633888f2ddfcdc636463a3dbe0a4bdf8b37682d4cfa2bc03a1af02b243b3ed11c7e56bcb8518d2af6dd97f52143b64d3e003ebd5da95c14bf5040d464ae3d976e7bbc143f87fd63928b1cdafcac2e65d5ab5a4e7c063dc576fab03920bf2310814694920ad659f87290b245340124e5a179ff7e8e1979383e5da069f7458dc3b9c47917d710b431d26c3884d37c188a9cb3f9638ba323fe8cbd70df3fff5bbeabb10ed8dea39176b3af732d56c2acffbe52226557b9d304b87c50d108cd063f135568fc32672dbd1986062ca90724e54adf7483e5206240df20f0588bb84c60859b8dbed44dacff238cda8b9ef478b6396e096485b8d52601395062578d736ba6ad91747d52e3f228f19b6eca84cd4c984190f5efcb3b3924ce60478df2e20845626432db7066dd9ebb07836ff742b8b349760e7392104231a8c010bb6e5db488566176e337aaabc15b4f9d963ec59f41f91567f7f5a2c5c625003a8ef2e0d4c0b471384d4ad6bb561e881992e74d317f8962cdfddd3afd1beb90d16264e0249ae0c139ad538be083aac8ccd8e6671f3972fc8942311692bf7ff06721a7e0c4ae333e78d366eedbd3378487a4f4f137ea6eb4f221f5f6720fbfe0f38f7bee76cbb6a997330bb4791e244fa6fb9a75731f90eb812c77dbbc15ffa04241cf3de420b6e8b2545998109ad3f35c5b5e50541116c609e6f1ec90a957001ffb794427dc5e4dc913a7043240c27a3350623bcae1f431f6f8c03ea41fd240aed5c0d77ef9b6785e866267d8b62599933da672ce47fcf2e9ef796b8a87fe50b1b8c4f1d30e4f6c103367e0a20a53e9ec0a1c1d90001f23fde8bac1363dd500e8d0cde78240711c2154baabc630c5dfbedae5d1532d5fdfb78d2b7331791e601eadd7a2f191e6061dce3f95c8490495d51b06f13cfb8a2086b0e3f89b8c8150d4bf14c576c1cc8cff43835f6154fe91b2df67686daad2201cb59669fede1ca0aa0d4f554cd58d7fc1ef49669dd20e24968ed73a92920482ae11df6c00eb6950437b49ca3c12db5d12bc2fce95900b99dfe45be731f9eb58c04b928d3b4a38809b709a3f34552904b14dae710ebc4f85274694ee77d7f721457904caf6a3c9308b4bd79276abeaf4ccc26c98173b96fd3fcbc905f787d2efbf9228ccb179c3306090e008d0d1b1e93a9414bf24c25d3311a7cae586d1f30c6bc5f4d2effca6a09941df962a5cb2a765663232e6720171174c0caba8772e8ee4b619e9025f106017e4fb3a6c32f7c902c41ddba24630f64b48ad42f57c778918b17eba9d2b853081f18f2c8d4e6b0fbe1d2ee08c1b6ceba4761a0e172ee2c940fdd6d0a7ea576060febc836130cd04f3e54dcbbfa430556e9fe547f59f394e565c96d5936dd760c02e61a15c1fed0d247bd33b57353977afd85f6322fac67292ba1a6b4f768e802a6f7b248d236f8abdf7ac55ee0a107eef738c31bdcd8d17e68520e151582bd0789baf0f9b6c37ac95c0dc75824b9b1d091fcf9e42b80c5fe8ec1c35d901ad506119e56966b63eee2e7ef053452bd66f5059ebf6aae5ce0eb0ecad8e1758989006f86ca3d8d1c85897a09eaf95f863c9200a6236305ec79ba2fe9434fbfeafd09fcb7d0fdfecd767a968099e1f755d085dbe36b8a247a009e654488438eb4f90ce71795b6e5dfc2e095ee0adf68338e8eafe6a7842bc8a9df00c945caf85676057d9c4cdab14a9776f1c4e765d30f637eb521710bc8462d568e6410e4eceb3608751877fbcb2b2bae5247f0094bfc1f675e160255919e21275ecbec348d21bf03dcb3d184870ea5b214abf0a59e8a81fe0971895b9fc8a9a4c1abfe7af26113083423db4470aa9c5f2a17744c1ae408eb84fc56e9988af5a3816c36446f041f00fc3d732dfb776c5ac88c82fd914641e608533461a6adeb90d22d6d20a3c9c90c98eda024ee8e7516b0bfaa4987662eb804672895cac25483960f010db61e5402cebd00a1c2a212d1077b33cf684d70804523349de60c69627d8d208b8ce0d20276d58c8ad7600b9d0ebc05a291fd9a7b697845e9a4db4123996414dd58ff130079941f0b3f6ea62ec2f7e6bd2bcf6d171a13965df1b78a63ffb9f7b4fb07780534bcbbda694e23948855a64a6dc033fbf9836b3d2c8c9e341dfd5b098621bb0d9eb1915a7c15553f9f6f7322cd57334ac147ea26a32d3f8fe8b3eeb59df78600921d7f37df0a335bca22f6d6033036b3015df9b85c704a713959bf7b123ebb0b26ba2149f292eded1d35f269f1cc97f5ed39ad726d2ffcf39f01635ad365050e2532822ccf263df7a37f57d4a92d398e3c69aeb2db4333a4ad8a31289e602c072f88c7deeb21faee4e2e5edc8d44e6726298971ed614f22a7d6e194ddf94380279678a5737bc6c66757c35ab471fdac89dbec0038a8ae1ffac103c922ac9d903ae97d68692aa51fa3b0a124b737949fe6b837446e14726fdb37aeb8d32d6700932a8e3487de282779e4acdca23c5fc6d2815b04680a88ad77c7f107a60096e0d900094cc338ee81c6c9a31d3ebbf45e925ff3701297d0b2e6bba4a8a7b392306e588b702ecb907784bce3f0d3925499fec8ecabf6ab3a1835bb9c0e4665c850c399cec505ccee4f8d3e93a8885c481c4e49ae83dca2e8cbf4eb9c731717f740a0fd06f1923493c076647bf7e5f67aab18ecbd6e1c5aa7bfd11638f3e3f58c40da3e2503f4f2d6e42c6e59854f0908ffb1abb35f118ff05cd38efeb020236c90f06b4e18c247d2a4ee1aa5f56055957cf8150ab2c0dce289cb8a3e4e8574c14059dc9a121d7875d69c2cb42dbd7e39b514b699d8864310cabaccf365e3eb993048f84f60bcf2467035c7e093161e39db898470ae91c85da85db40ee85cad4d702ade9f6e8eb2afee1f69bafa935fc89fd79593da0203764b2e91846593d1aa6053fd0f087874fc1c3b810f28b23c2d16be52d9e84ea33fc49bb730731e283400a9fa73b07dd605bc5e3e630ead6c8367742050db8b73022953d4c36ea2f21aa00a2bfe7ae0f5beeda4dd96132a9a84aef3b6b37bebf67da239e9dcb420b014b078a692195f4fac817c5506ed9c57dca7c1299876a7fe6d6ef1a1e54df9a987e0ce083e5370a0e920a72138ae8d67ce08732389bbfcacf359264d6aa07345a47009c32ce14458e89d7a3dff9000ab78bdec0166e18537ecba2e6a452b4de451d062066fd747e158cc7e9250164e810c4d1ec397f63b68afe3a5877a81acae32603b0ab12da9e0242c2d641bcb3108bf6c99702d701cd371f6ec7361fe9d9cdeb0854967c62b2702f8d0012a9b3f4fd8b1ccd49112213d85f7160f59e17c5df080e8329dea18ef49c6f513e4c24b94e62fdd82f91373bad888326cc0f818a18e009c4fdf30e59278a2c2b0e8ffa1539aa8aa97305b52728d3f329f60b796c7c5f0fc8b49f9464658433767c31c544515d8a321a3eed8bbb16007f4c019fca010003b1e0219c70d54d3b38b2ee4778bb6b677dfa61bdc7148964d39eeb7fe42a3809d3b4ba22d276169ebcfaa3634592f6aa7affb18fdb31407ddfe25b7cd910c109c125f9a8be911fa2652fbb0160b1573bb50dc86700509984c57e3fa5b07bce08c8a5050a89325a27c77e746693ac5326d2d7e52a9483115aeb1097f9d3c15f04bbc1c22d855059f3ad26c336dddab464b54a6d551f07b6acc9f8d56b103f630a6bbe13fc8d0753efb2b0ae40beaa06b009df2a7f6ff59b3cfea5c7718989770cb0caa371d9bb42961e3cdb9df499f1b415e659c5c81da41cd115afea47474204044c863ad26602504db19ccb016a43a7e222626a16eb5a0ea55576dea2c2790fa6b2ca68b9383c8d1fd2162d3f15f1cfbd16fbb8171d2234d2ef54b7c81f5307bf8dd8c21e4e8f2cb0544dab8b8c38e01ea90e133a7b8bf3ecfedfd976517906c3b9a213ae7a1ff8f0727bdaae386f9f855b457ee7ab219904f644804d21100293cf4e30e650d8d4358afb5008f6b76294caf87d5f6f21b087fcab93bd4fc109ea50572841fec74ce6bb93d540aa9977f48b74b52d33cea53513033c3176e60866a8aa56d33a3ef01cdca4ec142667b7cf9f9bb91aeeca2db5d0942a80160e059ee319dab36e41269c2af1d95ee90c75a1905e274b9a46c78277fdb6d7fba30f13abb9f6a00204c22f1c478de8d537fbb7d7a419e992c9247654f13e64a11009bb2f2f58b705f7d3fcafd5f273d235ad22cd5a5f149e637624810f2a7d15c9065b65ebfcc0108bfb281377eaf0465a9d5f348283e06139e9c31692a88ebb6704867750e20b49f577fdf565ec146a8627deb36137ee3cd19af656c2fb6a8963080118048382a852fcf6d7b63883cf7324dde6e80cdeda1073582cd7f589498104521c71b8f12c6c9391b632a0288077ce2a17c039e517880f9ebf1a54fd58de0ce25c0baf8bdfc83b272864712bc50052317968ff8d0fd777eaeaa36d51cb1805690d394eb19b872274e73d95aa9e1f57d5af90afc8de74d10b4aa27b7e7520051bdfdb548d7b881831f49b9bba55b0f79030c99c53386d9303bba4323b5fda07fc5f61420c049abd3a4d8539276ef14c5b46022b531d4109ca4a2c972912e707925cf05655af9fa2efd347708d4fea96e5330a70a5add156e9908c657fb56909616570ff6d756e41c9c6470f19e7f6c1948f159442604ba5dffdedf32866850db1dedbf17f4ef852ff232c126c566de1e8e10fc0a4d544733135652e4b7be601d9eaf2a2b25146b92506074ecd91d3826606bf63cd80451ac851d95dd0c996076e8d9e8dc544e3ec75151926099169f9fef5fa3c962e534607fb810310c89f029c1aecf615c3315fcd0b8f5498f7f102bb207d19433ecaaece0c6531372edd0801885f9822ac577988db7674e4de1f2ba7966527f24b62c777f41e9be516210f10ad775cf62753d62ac12033d4a415f65d3fd56115ded54544deb37a9839ae00afa1f722391aca00dc92439b14a814d801de52c95262f51ebb82d07f6b6f1b075fcb52ee33f6cd9443ad27ec75cf685002e06c8cd1afbf0be2f7b35330fe5f0ba2cbee426af9a537498ff7f6bc8f28233e8fc3db1ffeb329a907eb650184a705dcefd32f6ff6dfead03dc1c8c7da9bb4eafa4cab334a22a11be3a47676f4280d83ca57ea87fb46f5882af55b56bcc5ee6025fa4760ed2e74e94e9e5ca56ed007828910f35ae0c35b4da2dc805f064501872c4e5a2906524bd33e79817b28f30e29d29f097340f2121e2f27c48fe55f3ed4d6e11411b744ec4aa8cf6ff0078809a4e92071957baa59ca1b7a8f80284ded272c12f2238921b61f591d6b5389e802c68ac968b598bedad618d5f47d692227607dff4d1a47ba61ff6ecfe74ddd200644e681f4c35a164d7f56070ae61ad807186ae9874f058c9fc5a2d8f53e0dc207b9fd3a106414a8a2daebecf36b5de9f057d20ed61143f52b1adde856d909350c1332ab7a5b5ebe7300d793ca298212347a538caa2aa174b11bd66844bdcfc90ad42c371483d832d49d2c17f2265628ff483e88bb416f2c0996638aeb365ff6051b56deae4a8ae8662d20b721cb81fd96b999d0fc594ef0a9bc05c1c98da3db0343966d2630a8a96480fa6d650061b636a576cda32602fb9d57b54ee9deaf4c036678e082851e7c88f14097a1bc2a87e0d624f4fc9cf7aaee648553fc1d94580ef565fb436a2348da9e153e052d510c464e9adc72aa5beae76b65668c2f043807fe658432492c64c4eec2d55ccda78ea16a687ed971ef841a1dc6869bea84e603b3ab9cd290f41c3df348c0856b0b52feb35a9d2688cc7a3d3dc2f7f401275101d73828ac2a674b879e250a5248eb50ef970f8b76801113f2bff003ff5bd90904ba35c9c0f2928c3ec58adddc5e1c0ba50819ad468b0fc8bdcd76a53910568302c8eb13fd88367618391431bd63301441c55646ab6cc2eedc05e233de3a7ef40fc9f873b4d36d6a6839702f56af687f20d0139aa616052edf007edfbfbec0270febf061fd4cfca4e4cc5cedfdfa5ae3b0f60cd90219ba23b9963a5ae4bfba2d0a11e697d37f2ca997dc723c21551083690b0dadf3a8eb6cdfe80b675f57fa610f52994497ae1e7213332ec3a05049db58b825f9ac0df696e7567249dbe733e40e13b0bf7a574bc7f344a3bd75fb92acde599ef715373d7ea56ac16f74c00fe50c3bd54a9850ad2281a0de9629a8042feb256a0fb737ccf9e5e7223ad53c4e7f0f5e8ab2dc6720378ce8f8dcaee9d430462a813a6d73601d65425cf3c72ce83f087cb1100bc71a5e4863e44877b0db2eb83683468a5821fcf5623077eacacd2d000bbb5669ec44c80c47d44691f03ff5492430edd26ee9ed9c2610a235d36cd804e6aed960e4abd542c2393d149b4521ca2a11470dd8a660a8782f167e87d3d90846c330e39507ea7ad281acd0e0842c0615f953e476b6aba89ee157b904fa6105dd713307414d80018002cec2aaa20f70848e25c50cc1cbff7f890811b5397405d657b8f71ceac9da056102c67b1d506da30e8e703e367e4fd3f3b9866ae7a40aaa953272b2ab61d93e6573f2dbfa34a2c894a925ea42048a5f29d4c36531a20c3846e8200f1e7908e143fb738ba457a39530bf3264969b56f21bcdc093863b01cd9ba4b97fae73c626bd1bebba775d9bd3410da5e7ff35c161d0433be4403600a9a0e1abdcf6d4d9fc2a54b7b7c2fbbd987efa816f3fa503b1783bec61acaa0d2f44a73bdb0ff675c6f9ebff8a541595e4dd1c3c8f9f77f6a46bb2e575e0b80941c88bea17b67aa047171ec0723f2a6177f72e90442309100cd2daf3a8e91b066bf83e119430d3925bcdbb033651a31def9e0ef1b278b2134143d8d43257940cc70992704c00231bafa60a9ecdc893698c62653c6c5b147cdcdbcd23f7023407914c502e5111df0b196aa9c20ddca9512c3a66103597d1bb36b5c1abda9c9008f994493efc87d1efe733f521fe415765696691cc26f9a6d1ea4100cfc1c9b007f545d66894af9afe5339200927cc93abbb5ae09e4dee03850d141a8291d88c07527d5788bb4670a3016dcaaa1e31ea5cc8708d3ccc1bbd6620febfa220e8d509f9e134dc6a91ec51d62507dfe8e5dfa291c5234709e4177d4d1c13107035e50bb70cf190f4e15491b56196d6db28c2c86e7cd1aa908e6da422ba49ca68b3330fdfc2fc547a7d853068e2b43ee434b96097b42dbea15bcc3bfb85c25bc5160f0d53a226bd44f3c2f0aee264798307e579f1d8c9c16f51d353e7da0722066fd90dda88dff6a09b5bf860c998bef0063ae4c26112d434d72913a1ee89df7eb97606886116d9a213de523004a7e817cc52e61d978caa6b2cffcc43443ae190fac1010b6d73517196230af2c9bae8efaa0b440343edb7e02adbbb26a8065df63dd60e52d9f64fa4a107bfa05179fb551eb245f399dabb80816aca08266d0874f87b0a331275a71adb02c515eab7cdc96db6d83d5fff17151b1b7c87c210814ddd2002525d4eedba5640f0a3447ad10bbeaa22c75af875a6c9ed5b08f5a891138cdf070b33d2aac362a6a078e8ff0ee628810d5b1be449d06e0e0054c39a59aef01107ed271794920905eb30a376997a1cfa6671dc172e972e0e1d4ccbabc2d7994e0aa3aa7e65563f5546749671fc0d91789d75298312c45298cae158a30d5da4790da191ac1335ba4ceb5b4f649c093cd0c1929029bba3ea62613ac605578a400a04d9d88738e20a44c8518def60d06fbe6bc6d8820d724734dc7535de7bc95501045cfa791d55fcfafb5fb6796af6221f1ffeba3f0bfa2f867c8d773a15bbac6b059440d62401ab2bb315ee3fa2419e6ee57f586d60849e5f3f9d4c72ebf2902108f59233ff89bc30e2a8752163464db4817080711d54f58fcaf848fe2d0a5b380bb74bfc580a047bd6a46232a855907b41edaf556df8ce6de61102fb4db7813308e164104f51ccb9b8bb92a52c735e820ed703a709d19e77b04c5e3bba66d2a2030b305aea6ffe10438f6307efd7ff43ec44998bfb91a4f6c9dee1a826ba053707fdf442cbd7b24265544b42c3b242eb6580c3ce47ff8897648dbed8a187777b0b978a31f16975ccd0d0a6a44a6f6b63070da2dc155960dc5a906107101d3f8800794862402d395a0ca2de95d7e4d7a21ee69706e6ebf312e713d9b395080ea905b79c3845745d4c382826db160faf5d3d4bf87f8621a2f2983cd6f72961cdef0a26e216a99b499e351daf4b803db95c6bc72b57a54b17db5c4a28fdadb3d40d0d40780753d1f9e7fe7933ba267dc9399020e5c2e3c623d2a49a7a50513538180402d6f21e57eb71f8739efd4269d80b6396901ad8aa12878f7302a3600d3dae0930bbebbce8948af3aba9e2066e70b79afbcf5f3e036c5329ca4447c696e4af0c8cac596607a20a382beb88598e1c5544392b7eeb14734d1baff9c00e5d546a034afdd9ce9b2cf891a521ca6030b377d52f1790a5b30f3bc06af012ec26df9108e67a76dc1e6c748a35fd06f8ba5947a4c4ee894896345c0bbd7dbf1b632bdf019bdc4d3741a904daceab5df2f650fb419c46483ef9b6fa02640c5c80aef11f0c1b36ff945cd67dc78da67e90e7003d95e1dd2f343a1a302ce7d91d1da7c26600d8e0bd5f66eb9fdf11ae5871908809afa33a4231a34a3ca603247cd623ce7d0ef8b62e82d48c5d258ee253f58dfc01b999e6de56666f6f9ec2356da0c9abbf0356a404246b99adff9e66f32e2e95bfef63a46e4e6caaa9fa7f1827beaa639209ee3c6b5ccd0f8df3d584f0519430ec449f7b669d34844b2a1746a688b040e60af90238674d8d2ec47900141a6bf470c823cdb36b717530b52df807b7fa01540279022b502bc50534603d38f8dad001d7378a960152454d9f0336e8df9cf38e087662ec9b90f4a43cb141ed49be79fbdbeae47791067673b01ab1cdf587886c0ac9d70a206f65754dea18586d384a9bca6f30db22b04f31d63bd919b6980fb006e106718f2f8b7d8f9f2c431b5d985cb36047000f8e99da44ce6ea50cceb46305097c447bd959ce3280c3f6bb4e455c172936d8b8bfca3c7baca17c63f8dcc20ff4f5f64268a13847ab2aab05c587bb0a065ed3b2c2c98944a7736aeebf4ec60c9de4c7ef0aa74044abbd78800b848de18a5f33f48f74890895d985ba470d2c0a95921d22e5e88d7a746c84f0096c0543b2f400eddfe4b06a04b634b25f2c43060e4b00151e0862dfbd0c882a5baf3875e3dc574d849853992fca4e8edba64a0bf0c0913a5c2caefa9f1f372b543e2fad581659bf2b86d04c32b115b57042e601209fc0dd5ef64c69ba67d72ba389bf4dd478102e99957a1f8a518d27951343068473675f372ba861b895a3d102ed8f1c0c1daf15951b78d154228391f9427900aedf7311a79fa594acd29311df3327a4bd120f13cf5ffeff1633f98558f5090be19d0aed620e35626443a1d0fa9a652016852742d2ba5c8b9844b1a766fecc078e2af3a65c49bce92f6fbf377fb44d824ab944699d9d26929b76b8d42648e8039d42b6d87c1a57beb98ca6dbee45ea89876e6231774f9ea1e4e9820b4cfd5c0b68486b6d0818df67145d0568b5d8c87117fad3b7f94a3a3db2a6802a574ad804c8dde57905880fdc9938901acaac91fd867d2337fa278896e962a0e74bcac60746cbf9ad449a07ace8ba6df78305ee8e1e887733849b09d2df7c4feaba75920a7d82db7d14e3452c0ab08ed08a4d42d80aeaa56f41d656592966b6d6b542890efbd63209bb69a53561e6e28176c405a699d3dd358dd6e00228e824d5167ea406a9db3738fc77cfb68c8a57392186cf3ab6bba4de90493c4186f3f4cd06552d098393de955a26a0b1e600d2357c1bfdaa7e4d4002172f6f6695bfcd0aa752860579cb787b102c6531a07aae7bc8e379f3171be8076452f6948a47142216267405c14339ddbec39d2263c423a5c562e2d89daf434d3a8159300c14bbc3941ab00e4c21e550e23e9c5e6925e48e83eb1a9aca0026ed9f45ab4c03bad98cb110d40d11cc7e57610316979b40c94a91cbf83f6200ba942a8806ba71e5b82726d3ce04d68229f83db82468dc6ef41f40c50e4609d06dc817b3e26a751e6362994e6b0cc599c5b863f4d7ce46af7dd8168335207e08e6aaa0f364fa8140851bb2227e0e5cc3f3f2a3655040d32ca9e318f93b86955f67ca2a0acdba5a7ffb4580a66b08896cb3776b658aff6a7b2f1ebb25ab20d39d87a5f1d2a1ee7ac8b7dfb66848076ce1807db53c6b6e58740603094bcaf45a4f551baf0a2762069ea1aff3186c0b18dcef53704f18d4a278335f80b0b4a34c07a936456f4771d1c5a095a6f72b0fba9c665f52b552fbb94b064d161b4f1e173c9b99ad9beaac3017b73ef1d3590d0130db21fa48cd48cc974b963a2f1a0f143072747412921591ad23f0c3e672046f00914f388d1c0ace9a08982c0a85d7c2c855e846825632f329f627bf031b093db8f97e2cf66318fd1029c7b6f110697a2def0135084edee2e755bb8a38cf0115f7ed905d5e878d20e2bebd237cc6e1d8700675f6a745a9e031fa4826e2f7052d41aa8697b224afd4efc0afa3289f74f86cee9319cfe8a5b068c16bc96f740579d4a87ea6e20cc4894b491d85f3f6bd5f53adb07773fce2f6ce54392b5a4408bb6b3d653e40d81997058aa9c62317c42e788bbeb61b523fc774fe8bf675010778fa38987d06b237d0674b9f5d0ac8ca47fd9ad7c9f7f9a66b96a6e55ae3bc0ed08a3b43186112e735d00801b77e3a8f5c330e29db8dddcea26cb28409aca509faf1f4550c5d8ebf707cfcb40b4c8873e50e5b69c9bb214c100336474589d80d27a8b503f6c916f1e795b7193d2118c7a4157f8d198be9cf967eebea6a57a205ee133b0ccf95531313a693c2bd64995913a6625f6b83a91bdd7e83788d6b010dadaba59ed93c4902a23babd4f0246e87010618ffee1aa720d5587d9648c8150a7563e51f340de57f6218ac5e719dba15be03df5a144d52a6fae34b6d7f9c7d0c9b3c67f28b7fce791b2364827e41caca673afd3951b83a5eeced6e013d1e47094253c574029339e7461941ea2683c325e42f8a6a63b7998da597fb81532771056ac413f98c97ad74f263605a3228e081f0e93075ef8f09dd8fe863c964c92f0512face777d8d42478d812f33befb43aaffa3b03e801ebb7234afce6664bd230b96a7809bf6ad1dfd5462d5931ea61fb8e55daf4cd999e1231c2b4e068012c50ad1ff32c4b54efd4c281ee54a950b2bcc1cafa46bce884bdaabf277c8ef589606ae1c919a4185400c197f71a67c1c3b6a26a8baaff87a3c4329d5da13a6be2908e892daaaa07a9d785fde0992d089a2cbeede5e10fb1afabeaceb8c94ae3a3a08a3dfae81709bed09b3598086a4a0e1e586df8bf03e23a0a376a8c6db5246a30f520d8541f5e0002ff082c94b081358e8c065c61e0d251ec97efe6e8dae4bce0ec14dd5ec3d784dd5bbb65489a926d794401af4464a81fdd41c10f5f01ccd7b0d45417765c89cafbfe6723745444159dbbca31e6ebb0fc637b34485a207f5f90bfbfca520d4bad2b4ff3b91bc29f0458c2c3b8612fe29ed6d3c0244c2d6c22f0fdb13e5088ccbc1603a9b1e2480a5a8b19b01898f8695ef57bb7205d8a9287a0783c121f221bb615036e9a333aed788d4ef208df46b1cac1fbf3273787e055c0cfcb259073ba9bb09310520808821f9280948ca4e2072662fabee3f062eae940ca0b0fe6d4e2db78fc1e29e18d9fbeb12d6d7dc4adfb72e90488d0e2c77478901af88cba160a94b41cfde1ccc7f22ab3332801628e6882830a6e42641ea02d90d0310238561fba2423b43ef75f003606fad9afdbf2a040831269f925715a0c3034027cc831aaa5cf28686c36b3b89389ebea5e0ee36457211756aa3dc9bb51c0603aac2a84f1ebc9e676c94e17dd0750ec5ec22fe87a5a30737d04899a627f00c74c7837892028f8091b4b7be653f9cc6ffaed035f7a253e1f21258c3e2698607541c66f1a6c42778e9d6b2b45e53329d4bea3cf04bc8b83ca250f148fe0b10034723e0e38513938a9f115a576d385a6dcc3251aba17237e57b5d214a5b19de04ce4af3634d5824bd124a48a727f318404a87b9dc9cdef7f6eba710e46e636d0763a5a5b5e482a3f46efe1c2cf410f5a77e0e7f3f8bf0fd361f3e7f956da3300800d47e4fcccb3e7d60cd4c9c224acd7942e693e7d7b807025e8d2f8dbe402c0db64e5713ce1aba30c0eeb1eb99cf680b4d6139c26abddcdeb94f796298038b0d0ba52832204a46bfa1f1721bcad8101b914e712bbc1ed58087024e514fe0e307a4416935c00a4b811ad4f78a77f915e25145108c1d683ec8ea85624a1fd94e07005a282bd0e9deefca82dee1c1bdafe99f3030a15860a5a33e2c043e3504c10da2cf11a1307a92754b5b807907913a35a9a3b2c3ff565c5183b38cedd4e5900acce4a01df53611bbfa8c9676e11ba13b1b5b4f44121916f87265fed991350503b9f090c3afa665baaa3b7669eb18403bd23a43d4bf247c3d9a3533eae3f3160dfa97bdf61160000b2f35291aa6c6847fa26d3071ebec8793c66dfe90999ba209b68b502eed1db8f075aba8ea7a02040253a5303709f41edaa33bde016882600c2791e4a42f8ae4a55ceba608ef1d0a9e75557ae8a66a6722d668fe29ba229800b5726c5dc041a76b2771a3d4781df098635c8271d5d0c5574a66ce24e56bd9040e321abb4fea1269df0333724ce8efd47b15e9cb8d80d2083c6768a96f4dd50a4f958c0dee540104d3b61ea658c9fb05d371a03ba802dea9dde14b2dfb771b0cae45da2764f7f6ded818ee6d0a1032500f327f48335c3928f7fff6af469206011450dcf4f203ee43a6cc8b41d331383eadb09946cbf5956f79c8861ca610610599e858febd45996caad51720ac8d66e075ea0bd4821de154053337fdc4c3940e2e6acfaed305400f196820eeabbf17876ff2e1b9070a4f5c011f138bb0e797065ea529739b3ebcc2fb1a5563f62844562850ca9f994c235fc088c74ea9fe7d04200cddd1d260614e60de29323a0984bbf44522f14f9b032d8c8ebd1f9b06ed05f3d5958ef7fc1da6e2d01fc0f402e4be55b48d3e2448e5841ae2789f719ca004bc072814cafae46928669642c7b75add8d184f88c5ec2465a6c587a556bc110598033b7b6a9454754abda131ac45dcf195d300bd805244790035c644a77cfa039b26a7b87be7eaa3193b660cad41695bc6f7039aa2395dce1ad76434d25f6e010136a8b0d1190d59a2299bdf3955480344716df405d804affbd32b88db283b006187ec38fcb5a16f4aad00293a833e68eaf73a4ecf5afa60ffc507f709b0e309fa9c51aa73e4cc70f927ecc5675e839176ae7befcf86fe179378b4d1898ae400d20ca7c6c2c3e8967369e52e2ae41397572775ec2583386f3a1c2a3d30896e0d07ef5f31b4a04bfd61f08f76e02a9b04bc75a849155e8bdc9a3249308ddfc6007007ce7120d228bab4190ae42a121c69ffba72f122cea31eaf9068a1d355b1054a6295dec77ffbd824afe5590c8172fa12fc6ae6950785a101b6ea40418a2506b76b737479e09af0f99186d14de0f4513fc4b80457b7d80f3f7b95ed9d3b1e07870ee50c593513b6296ac361fab232d53381d251ce8ec4090266fbe5adb8d7034302647da066e492641819592424f619a38abc7d12b2493823334cd3ef612a0bd8625da2d21a37dcecebf1d7a57c05a6e8bfb385708533b8084505257d888d02fe0f7fe52ffd1877cc357433a603d29ebe9c6b559b4ead2a3fa7bd7985d21a025bc4adac4aac357cd8b97546de4b24bc4a21c01e0467f61115ac3a948b73260ff8ece22080def2552d2f95aa2deff214ccfa02baa34dd42169260827215c320499ff5d6fe90b58c61cf0cb52c36e182f842976b1a361c12e61b859609b0a2b03c55a425106f31e4e344b1ca3e2464ad705964e89dfac1533b0c3f48e829d7e00724cdb27b3ab18217911f2d347fdc35785e32c640425a8a41b30224dde40650fcab569576fad67a98a70bdc5a9911191bf731d855ada7d2ad19ea0b9588c800ba18e098bd0631f13e54a03d4b1c28210db97b607b74ed02c6f312e736169af0f3fa72678de72d720f86a198d378b6873581c186993cff37292bd66b2a2db75011b0dfdfa67ebd77e4c4e1387742e1157c5f9d0293066ebc5327fd010f9e2cf0859c111085eab993e42c8adbc819e19f54a315534d6c682900db08ba33a09b402bd0c0a3697346b315521c1cb49e8c8c551c57fad7f54fa61195708d6ed1ddb04a967d8e2c35a9addb5b0616650bf3256d11dc75a5c8d38559cbb8cdb37e6810b046b997049a2964da6fa2cdb506e79afff50230443f601257c90fd826dd1b4035b0b1652d980dd8d066b247dfe379d5c47c2b6779b5a8e9f9753f863287f7f0fe3892d67f4cc4aee6835b9d818b118d09fdfe827f5998ac704c1982a76fe9a0bc9369c4839f9fa92a10e26345cf3bdb893693f60cfe9e303f926b22e3726960043f71c42a900bd067598ecc4067f520f8c877186efb67b43dbf03690d14ba5072c618b198635473135e3964fe55638e5306eb8b89447a2bf33b7b5ded2dbe701ac43de1037c40455cd2bd0f4b92fced20560b4544e4623de1471b9b129323a077cefd2bda2156870c4d3d22a2b82952af40593d364a49e48beed8ffdcad2330d6ae95f9bf156b0931ff1bcef9d536ca619f31131ffbec74636d1158cc3f6d7059bf30901a2c96cd87e1a2c77267afebc5b75e4ed22255deb1b005a3cc1d2630ec6bedbe4467bb2ca4b73457f504dba5ca4bbd928b80798e770d77cd74831ba051f3e147741f0174c68029e0d59e03bdb3fd108a2acf8a96e4f422d537f03f2039d374c851216c433dc0a6091e68aef707eb76951e4772012fb6776e96366330c1399d6470c69d1b04dd51c2320fad7e804587e794a0fe56042bf729553e287088f226e05ce230b1214b3e605cdbc8c1060ffc130168d1775e7972a645b20ac039ba823b5de8eff9af4399ece8112f06a8b5c871918d5977f2879ade0d225d408bf66042a6b1e6cc847c9f7865228d3737a19238a20bac1dfff6e0ca9752d960c25a8301a0ed70ac6abdb61e1f987081d5e9b834626da0c176fa66681e2164f079f0a5e5a0f4a205b9603efbfaecbdb16ad34ca64df2bab9c754e087585cea304d159bf4ec959d6b56984fc59217fc42e97315ce059cab3623bf45e16a8d9920c751718d330337787a9ffc9556c5e2792383d915ed6fa92603fa49c4fcedb1606c5ebe129cc5f351f94ae386fc54d251826d1d17983d92719dbc48ad1ba7de0035087449c2b5bcd9f8121d4774de48371fcad032e4477cc16168a38790487e40f87c62abd33b2501c81e0b263e1398a0ca031f10f91db4416987bc552470eaa0a69ffe32f38f7469c44b4e6cf669a25d9deae27a32d8af292d724b026508377012a24f8fd21ebe2183cb662b1aaaba8d79c1f35e4f016764dcd2a61e9a3e7c80bb9c337b526ec23aea6fc68fe9e80c6b055f331191fd317adb3d83cbbddb07002ee1bedb5829d89ac4651ac3ce3318cb794d5205fa1acb3ddc6033c60dd5c020c67cd78d6f67b8e28212db0adfd4ac29d544effed0bb6288cd009b257d6f76e0e5f10c57ba00f9148bdcd1616adc7204020124890bdf01652617d19f9676ed70c630094ebe0aec7c9ae2210eb6a03c169d04b693313758ece011070c08ec6fa08c50ff04f6929174d8f6bd76d52fdd9a19956347530318e5aadbfbecd8f6e430fe9bdf03019c9bda49b8b45dd6a593a137a6bb42fa12d00491e4653300a59370362dea01ec38a685b58406cce0500540595d79351adecad060bed02b404ad840638239903d414792102828c8903232b4c2cbfec9d1d53c0fe33d8882be347a4095b7ae9a982082797c98b030be27bff6b4623a37d6b3396a4f56ac545e74a5501edbacd9cf5c98846a47c6af9e81fe9f622b260d3aac0b4342293df67a068750712712966dcad17f47bcad7360c90c06eb81cc61d1b16d840556c24fcdfbfed0c54274a05458a995d58bb0fa421964a54b3031fe9887f13c7f80a8418993caf0b06a3779dbb07846d617c645732809d3a286a0320a643b56a65ccce0e7788240793119a50d2d47d4113b72256a90d5feebd424dbcc58783b7ae029b533df9500ae60de13ec48d30d6681c94596223a3e6f31f67bfa1ee86e054006ebcdc813b0148f4548ac1c448348f26878acf8f49e896a0aaa75e44c021eda842d35918d50b7e98049b4c636cf5c6c2f14361e071fd5cf082e0eb6f957cd02496390a212d0670aa22b16e29eb828361cdb104973a1942c0fa525cc955712c39dd56c3dcf10ce647ca40722adb7c18e1dc458d87724144b89f56a61036a610e54d7ad7eab506b2d0de75d48ee90a5af4d566b784b3d4fce7314e95564553ed6c4bb4b579a8050398b909d7330b33d28aac3ea097cc4ca4789f7401515afbc0d65896f4761601bc7037b40e746cd17aeee78fda1edc72011788403b33bdf5c1fdc7f01358c40a0656a64ae6f9e7e123f3feed0eb4dd9d972d258404a1dc8bbc05cef2090c3304db27144e75153f789feefa8f1115b020233906c8160bc0458e7d347ec404440f9f541aacbef1b9f640e60e1ed4e473242e47988fb941d3bcd863d160bbfea800f59cf1fe64d6e5d959c7aee993129887e520a0dd4b4f9b1598b97afd8e7b8c0dcf475f46b8c826f9c2aa6a643fd44d488f13d10208c16d7d881d5297f758870f033e0316414853e507699f407073af47fc524af1d2ecee69f20e3e2da789e80fd5cd632247aeb256c22d8b8a2e4d73503063d0012ce4eb967e1e4d08e9e4be0c886d77a351a4c3f82c22ed761eafeb87dbb09da667f6b01ce23d29892615c604fb25e9360bb86b7719638abba883b449ef20809bbd01d6ded1581c3fb855740a17ed02d464bef0aa12df75897f5d1cdac3f1535440435bf0b5a8824bfe6f0208976bca6f22edfebdd7cbcd1d94faecd549da31dee042de099bb57028b2b3e1039d0e072c7da8b7cf3463ea9caef7b0bce770d3f6a85cbfe153f58dc1fdaf8a09e5f2df380e2d27f5278a0d5a2b00410a563b1e6368d88b85ac38ee3411997d0134e538d976bb4b8aed41a527ce1b2926f101891b102800ca34aba4a3f623df0e92d6f0214b3f7bd4667e766e3e83a54efecb2e9b77c99db254b054f904b19d0ada49713d1e24ff4a6f200681f0c9c11c4463e37d2f366b15a54ce815341ea5073a12f34cdc89cfcca90f727d478b0d67d4dd755199b9493f16fdc9a50c373d07e08df1bd2d52a65524561b817828940eeec49aeaf86ee22f81271aa6640ff1032c342935c51b37f7f2bffd6686a050fe16241ee8fc836b174f08ab15131a2909cac1988f337211067071fbd0eab76de06eca02b7d7e77b65aeb641b0bf1a8f03523681161d5777cf307b6a3170fbc548f9cfdcd668b17d02fac72e4f5fca3f066a442d561e9439bc4f96af69467b27ca6de1e9d2c365548e99d7eb2f4087ca0c2272b75753907c43d9c08d5d8d25b00778e2c0fdd4893c2d85770d09593cac05d50b61abc9c1e73bbc2abc8892975f70b2f7aa25d80e7e1962623021ce594408a0e02f3fd8e0c5dcf3b3deb43fa79062bb026aef3756bbdc2782eec9fdd97b05790b691d20c2c30d695709bec05239afd15d5fb220279365714ba75c5f874b035135cf1ae832d4b62587ace504ff21b039a7ce70941633a7f5140674dcca3b0ae9c071d6960e92259fdd7a90cf28758b9305e6f1e4fb5c464ffbc81acd32b50603cf348028ec4961f8a0730478963f1145889fa28e9ba87c4cdc7dbf2310eb0a9d94ecb72a228a87706da1e4c9b3564f69172a39663219c68e4c7daa8ad4200beae6d421635f5f24274f3460968c091c6fd05efcf2130fe3e775bb14b40c6d0bdc77f81728b5982cf7b46c5951d2688168532e377ee2466e6295a96c35158206c3dd86e7d55e3c3760a9a9eb42a0aba66435463705f9fb747a4c944f7950d007e5347501b03293147a73bc7cc312427359d8edfca34557b70b4dc1895d80a40f -generate_ring_signature 67011525aec41e62812368de7e56ad8ed15cd4845e00871483703bf9dcba31ab 819d1090586ddd1ec978a2f24412bab7d583208042f35c68d6ad5ec98752bba7 76 dd964f5695c3a008543c185f0a1b5fa461e9c22fea98d1af2a1e5d60cdaf6e01 d1b04957e8b634589c062eb1b743fa1cffb725a8e272703bc10f50d1f5a0642a 51dbe51747f44800638559a63971289e43845c9286aded8b96d55d982fa22637 81e0b148f3ce2bfb07971eb4acf845ea0b1cf1c08b27ace8b0714a78daab6097 9ba5b03511558e8edd7b3c0336d9086011c5adc81aaa03664841d8c62f1fd2f1 3ba3b659ae309970f3494eb0ec612a5cf70da1357bb5beecb2fe946a9913f6f1 882ea42f44c98b4e0d85af542d9de44ed889c3d65f9ed6d24c9eb751b640c12e ce38c8d666e28094548fdd3dd3a9e9706e0ab2c863d5e1c43fdbc0682bbc00e0 b0998d216a9ea0224668c114c8db2efa0a565838075f96126bfcaa22085b4745 c83836b02f86df9d9c8f753f52670cb80ec5b6b2720cb2b7fd7fbbfa2d838e5c a441967d23071f5a95a1f82f5e2ccecc2dd3d31bd1849d137c37e9415c01595f 0322b7bd2b2430e428c8f1273fcc36f45f97892b5572bc53163675abcd987753 b9e1f6ea22472fa3db4957c448172b1d58aa61f6048aaefb75d3c647743c87fb 348fea709d69b0752a6f382577e2149d83b39c5aeca6f0474d13b1d4627da825 50360c7ac3a214e93473db297a3e1211f08704061bc868bdf06976a95db2e6fd 8a5ed26f5ceb633b0e25b2a4410178c89ab38634fc36175aac9847fe666d6876 9b2690089def921d1d5cbf63ddd3f58b5d7fecb4ebb54b9b900032ef0d687084 4a22af02b3ee18ca29add712fb0890f5fe0bcd52848f1f8e38df6f38dd5c99b9 46b943bcc3d9183b473a4d522e4a1febbd713e23b7ec8959e5a4fccbaa9a4e58 ce8f7b05f9e53ca34b01d6a5bd63ee14991d7ba4e42a236a7248855832023dcd 851d02e432b19150a6f451c82eb384d730b0c3ce3c35a4505765785fc307ff36 7ede31e63912f8434bb525222bdc771cc1539e42cccf8953ed50b7bbd152f87a 989a4e49e2169c52b2e8ed72378944c7f4ca80cdfeede413096d6bc6bb481987 8d197160b9241e31906172e6e59aca990939999d13f247f5a5d63feb35218761 cf685e95fa014fbd3a7d23c9345b54c8918a82cf04519dcce9aba2064e703bf8 7b7bf2a667d37550e4e55a37e728ccc78cdb856082abaf80f30bf1b9c75805b7 b63b938e1ae69254a31620ed6db8a682a73755ed347b020e245209f4e5aa344c 8e1bc9db8e3ad41682859991867e2096c5e39067bc4157bdc5564c3391902df7 998290f1542e57fb84928d36aa67ceff21910f22bc8c3558a0ef10398fdfd3a0 f4aeaba0a6d239ea8a01d9cc7daf6ce0109d26aa92cb30f4456bc5eb2f3d6738 17833eee37eb03a9ae32973d56754808205ef421688f18fdce0caf0bc66e4f27 30b5341b038b23ae69a365a896790cd64aa19eb31864bb1638c08285909d764f de2d29581951dfc59b9c1d2a2a4ddf67919dbabf8a58651b2fa527c414a5cddd 0457828b3514870bd16433cba46f8738c173d41eb59ded65acc6c7dbaff5dff8 5c9fbb3ee625a4c846821074213e505f9c51d5358abaf3148a8d154cacc6d6f1 6c4485b140aaad6b9e994c7d2e5023d0940d85e19af437fd21f236ec3a4733af 88e354a64180b6869ca2192aff2b69fa306c43be47a4f110b85dcc5495f1c977 6a6a1de9b1c8cf8b9226fc675ddaf1a032205f897d0727829da84b8b89b22d51 78d1502e1cd1fe7c525ad2bb4f7c9f742d679f7908e1a2d4f7bde67ce95b8ecd b6ec7b175273d7aa77355401a3c36d43d003f6efbdc0a961564bad698e8264b0 b4cd90e8ea0018b56c069551b6c43f45d5e330633ef17161b85acd7418294d58 25281c2d7629d25ec3b0bfe45d621b5429c1588f2831611c642cc7dabcded2c6 6dfc0172238b46bc6b48fad9ffa9ca9e8dffd0667ef95611bdeaf212ecd6457f fd8836213387691d192f743f779da56e093a435d355426422afed7cd71d18cd3 d32a9bfe7024fd29b185a1308ac3fe06e21b181ac51ab2de211270a503ee93b5 d65eb25830cb331b5bf837c591ea4e4a350fe3cc01e795e0bed07d38b4f84991 c521b61b43eb63632c484c6955c669f84095d769f226524f2b324d4243398cef 3c282a717091456d676299112eee95a854a7a6a74e890c295071033c4086760e fdfa169265150e45aa61bb1450d7a1ff82a7f9f076bfd1ea5fcb3fc35b527299 139659524a57f89d2425bc842cb106d8c84c9dba73fcc03d61ef2b7e6ce2e002 dd28d9609d1d3e4f53c48cb86fb6af584275dc00ece5322836b89209bbbef2bb 139e90fd22032ea389767357866c7b2ee9a19d9637d5911e74556e89687e79ca f09a6690d27cd15743f95203885b89545c0d31d6f745a0c1830e9c2c613b94f4 b39a46aee128baa794634dfff8157c6d3971de45ea87b210a568b21d4cc2cd39 8f63b5d7703ce9dda77b5fe3a6569482d1a42a2a7e7aaa46e3f50a1bdd217e12 14f4e2881ee2111945d653a6c5ca978361671932c50890bb355f277be25d2a77 e29737b0d67fd4b843c907975e594978ece72d400eedeb0133e875cd65710c3b ea3cb93a2202ce93bce08902a70149ed46a56d01d646ba50c39f8fc122e19926 e60ded286f6ce5f73348f53cd99e4a3de0c5e60297be0d7f066fe19c08c13c16 77754e38b821d49702150ebf7f43fafb0889c05cdab297341578cfa18128133c 434012a532762ae1ebd6706d4740128e4f1c4b97488de8844115de50d7b9149f ce7d22e2a914b82c673b65b28172af3760540a84a45b62bde70bfd5833c33509 7af0361c2aed7982fef7782873dabd2d0ae6adc240dbaacbff15409d916a6a01 d3bebf533d2922ea2539d196acc3e160a8c776bd0305992eab11cee72b51576e 68bc2a53fe9f28b0fcac97ff57c0dd6469b3387741aab8bbe8779b72264f10bc 97741abb965b119d339269b289ad2b630e8152a2e8ab33bc9da9fd155a2453f2 a549ea88e7610bf3c7d92fb93bb175146bca920a8a566a6b8bbaca0c73fd31b3 fae4b40e6dfda8cd353c561aec3c9c8da0954d888b9c6adf883621b50c3c99b7 55e367e48d3ee954646ac39548bd79e9e56d216b1ffd07d7cefd5b99bf08ffa3 b5611452300c2159de3e38795fd01a3fc57dfaa516ade34e288e984ef3a0d604 3ac22c7a0b7ffc3611cbbb883cbb1fb6b4fecfbddf4d43c2c4fb484d4b103868 94d7a77a15bf45726606d1a5f4ebdb46609b7cf029cba1e51a629e1083f3d76d e7c85510fac98d7cdf17ff2c1103f65411fd196c37571a4d2002bedb00258cc3 023a807dfef8c1e036c0a55e6b1b09ba9aa0637caafee1fd1b283f48dcc7d88d 72638bdbc1acec76e018aa9671b04f82e1e0711f708f6424bd77f9c048060ab7 f19bab5af9575092387a5070f63e2c8bb72c14cc9f1ffd5944c2c24d82e880c5 b5a3a51d296fd23efced3457f883efcbdce7b2e7ac1514e5c51211be8c328604 24 753bd8c42b0d38cc3515c05f50ef12bc5d34cab0cf6820669abf85fe66871c07e344df3f74ac05bbb7270e51cdc2768725c5d50f458e7421c37de6bb9f2cbe00e66e46139a1f40742ad48310f09e98601ab636000bb2ba047df9f232e29ff709e8667295b7ab8a1ca7f21ac429c6742490492c53f4440920855cfbd132df500a2d2825b622ecd08a3be6a421db918bbc8a394e5b3fa21b1e9d6fa4ef6b4d5c0105ad1278836f10ee948fbd4cc7f33c76fe457a187b11fad96f07a5c3b4c61601c062a9484c258d37abd2da09bfa1f74aadd31c850138b69ca03ee2ac73362205eeae22f7de0fb04782cb2a27aea68a31f31b9639af77ed8cc7c6e7ff1fcfb307a9800c1c10dc42efbb2098df81096ff82b4ddd6fbc1c4f4972a252bb920a930965df63a2f6c3a554b571ff23ed60dd5d430f59c60761ee92883b27ba5cd3e60074227bcb9b44997e043addfab96cb438f4feacab64aa12e06684e6546bd8e608032ab771fc1b7433fa0fc42ccf837081151ba0346322c587c7df4aee726e620667d1b509d5b093a3c0f70b130d4be2ff196a16df768446c97bf9f7d6e0db4306921052ee334b04c29e790dabc94674bbf9b8192eb5586ff4aa0c94ee66121d078daa862be6e228085e30ff12e4d17b50b57448c0540d74b0da051a241c7b3005f6e54fcc2ab4e1cd20e0cffe22f12152ecff46aacd1482ea10f56eadc6363909e256d2beff3aa78337008ec9723abb40ce6a8dbe17d43d0ce8d5f062c999600176edc662c93a3ead2501295b827039bc5aa621ad1ecdbcbe0d132602cb9c2505482336c253cde5639ce3fe67a1d660a4aa080a74ac876d5497c448841434cd08d2fba2c6831f923b1634a09e599da97a7606d10baf902346a5c3b92ddca0d3078606e3986d24d5cd5c1bd1c7a3f9d44325f081c388ef8d2f76dfcc8339fbda00779486cc3f8f7becbdecffbb5a918d218c30ba32c2a822f63a8536bbb9fda2085dedb86ef1f3567b6d0b2555f9504fabbf5f889fb1a517109a71dc961f75de06d8519d69375d802b9cacd2dece92e6b837668b52ec32d41e093e184345b8f70f3f556d19653b10b681a67ec93c54af13f6e7608a17e688e65cb1300510baf805f64f49b9571a855318ae1ca8fb05824ca7f1492db8f6d835033184ecb185e804b17f4e55db4439eb2fa94095b7ae4228f7402452b3efd473afbe2460ea269a035df5ed266089f216b9d7e16acd0bc1155d92d3b174deaec3b3dd1f3e2b968b0a06db920045ac4fcd7bb6ef27f7f45ec8c1366aefa7170c3d404b293d6339c0054ca8a6ac94c9d75eb68ac095f9c7688cc3efd08573d0f72317f3e32f0e3a13028ae25edbfd3103c13f0d1b03e326566cf25266276a1b64a379aa775354d0190cdfd8f2c203ec0b1298f0fa835405589d55d4b4f08294e6324a5ebe1dc1ff6808a93822859fd379872b174f8eb2c20c2bd7c307c81aa37e1dcd5cd2a0d4de7b03e0c033161cd653ff9e52b7c13c9fd951af4642eb4ead0587e2ae20e37c6b640d2255b7abbb9ed77314dfa8dfd97792537c0e1e7e3ee70a0329666e49b88d8104baa00dc0e4b257d6183f5b063a25e9d305cd46d4440583d6e2bb3ca35c30c00faa5a78f62acc5c0d6386b32bcfcc1161321052403669bbc16d3bdc414385b60f394a2301b76e5c3f3f389ebfdb2e0af058a7090be2b7c93620dbe8106284900eecddceb90e821771977e29dbc75bdf1c9a4b16334ad85ba19b8c0ec932cf79007c43dbf91e4eb769e51361066b79f94de6c83ecb3f7bec8ccbabfbc2d266a30380f1eb10559aa693631a4233239f7b08ce11e3009e5b7caef714638755b5450374644432183abf91c2b05599e16d4ab248ea9e19115b810ad54c602ffc69e50b644caadb02d241a7f50e8073a0eeb8e784e12273a8d90d5d4f421c13a3d5f3017ee68883f64a6742444116f1c49cc5adb8cf8a3e294d81731d9278e3f881b406a266bf1cf9c14e5e48a6abe135cbba1174051be1d95bf6dbcc417ee654b8a50bc76968e04211bbca98e7289d418f09667afce3064622bb5733f6801d9e93d20a0e75d6dd6df5a612231bb868ea9ca70dff09bcd8327b81eef9077dfeb07fcd0b661cc09d8c28c94566888fa4e91a38ef9d809d8cbf7c2a96d42b81c8f32a58049a04b71d721cb7a4012a4e54856b0ab788384d52924973cfc319732acbab550d63d9a934493ce8d2a0af58c85602b974855b31a8540c108848bc780f68253f0114c1372017135d52450c930ec01b4c0ed2075e24792f16f93c6a76139b9342023804aeeafa75268c4fa9ed9f5839b156cf54c79fec2f0d31fd9a117c780e1f059f968b62d6da1561c19154e3f0c37f157ca7c7e454248cf3aaa6ff74fa465108c27b0d60c09ba38e9373b014e91b39f1ac35276c7f136adeb73b43300371ee0d0f6a86726f2bd80e55766a4e2f9e1f9f2c25a81412d489b77708fccbfa7bfe030530f72653645f666d82c9674cf61aed175801a191fc1601a82ea0009044ba0dd14580081885e3ff96775735c7df0ed9b96cd3d8eb2daddd8d3f528143070605962084b919317a1dcfe053cfffa5293e76b4fdb8b08bfc2c0d9da67312a3530b6ed45d5445fcfe67ebae6da3e1c2a58de06e6255205a27fdd130e476c1aaf6026007952e4d2646c8521f761ad029083f2cadc38af0b4a9b1dac5c3fd36f7bd0a85067ae4b23b9ff85741ef3b53a729f492c0c8bec7f9049b4be7bf1949649f0464343951c0184d3aa11a2b7845a47da4ffeaf75514464466cb32eb921cd2680a0585f660a28d21da67eaad8bab25fa084f8a2d9f362a057bc4426077a261040b8cc31147dc38d10fa1e242b1d66aef3a370223944a615732861012ab156d53048f40d37fc4611904476af631b7a2b77a356b4c45986a4e4ab9bb82c676115a008492833044d89a4630ef78b87b74233b1274c76ad59a9871e7e335ca1a0df90bf55ed0c80b84f6a8a43e645e1bca9ec5e22bbe0d8f065a3110ecc1fda7534f0cb0b3a408477e93d04402a9f19f64701114664ae871f6483d734bfb3f7074540d168de1e3aeb0f0d660592cdb24dac3731280b60372459cabcf3bfb1fed2bf2047173d1fede108ec244eb1216c75e8b0d82f856f3a05fae239533c70c657177014be0201fdef4c4376d35f7cea673d61c643430085b24c667d5d1e8142dc57802e16b847045db744b472f0d409f9710b571111d8d6062464f867e02a50271090bb7a80dbddaee992d3b09c9ef54facfc24680c9fcb3c32e3fe30f7fc8e4aa8b0f12fda6b1faade1deb60924fea0055d24a3a689698e794ab8e4cf32a42d5ccf04b84d4867e5a9555365fae23e70ec38a183cb74550c78cd7996f209c04f10bd0acb6eb3a27fbd90bb38e53a10b9eb2cd0c68a2b2a5ddb3df6c86696f52c9f0d0af63671d453db964ffba0f8239c02131e2910bb4c6a6874a45a32e3dbc558ed01b741228be039c14eca86427205fc5003c9a75bd8c908634f9dc5eacf3c98c60dd79a5dae7ec16b432cfe720158cdce0aace0b874aac03a75fcbc9d4f91cfae0ee84888b230ebf0dcede39fd808e8ff736059094da5ebea2dad746cf199b3550644b9d1daff0da7a1255ee669c44ebebd115788cab8d9baf09454323a507e0200dc75eb17af2659cb89f17faeaebfdf155363f5a0a4feb7400047715c9cd68f09cd659db80d8f77f40408efa50dc621eeb53c38e39fa7ed54d0033ead2101a4023b510d8c2b0ea7867cc566b2df81d226f690b179cd526439284a8261a8902f04b91dd0303410fe78cf091d87db65454ec11d9a4ecd78cbf51643838e3afaf405b620010e2a0c03711af3a53e463a1b4ceec7fea2ec8dce0c9f3a09ec2e9d1d02a5f42f16f729be1a25a2353917ea1c599d8b64b99827ce87cee56a7d364f0c08a65d7ce5ab9984cd84c401ae3cdadbca83f6624e6a4db2bb730a42a21075cc03205dcc9708260173b322c19eb7d53dd446314b0c5c333e990327d7293495e20003326be5a6cbba34555404a114883d26741d4318cc6859ffd88e1abdeb27200a470858b413ee882dbdb29fe9a6d974f3375e2ca484c32509f5c017d3c4058c0fb8fed6c5e209bb0e55935874dcaf290eebfa465347c1bdfd656898f67e8c240ff5484de93d094a7b10b1987845befebded340f90480f677c2d7ec1dc2bac3c0f2f8d1cedd8483edd8dc20039fb02261d375b788da6e4f88bd6bf95e1d4b25d08937515e629c155c74ae6242c02daaa1815dc4911ef0e160a13384897aab2360dd53cd21fed9dfe414cc82e279a47198bc0798e003260ee451bf0623c6975160af198bc474af3b7f97c606d96708e262f3bd9b6d124981893914d7a6ce59d0d0b4c252f5e5578762d67d90417560ffe5d3d43173a78394c4147b2afa5f803170b2d9ebf03b2fa4c9e1e62352648f5c2c5e88150f5d8e7a22c7fb10cdaa0e804048909cd988eaf170faa9cc9c81eea6779163ef4507027673c3c87f876392f270d1876fe7cf44709165611c7814a7d97aac477af52d92760be03fb9bb5a016b00d8a124238fcac4f782696a92bed8d97a35ee341930f5eb96bb83b441dcd968007a49231469ca502e0e39eb68792bab8200f5eefb2e9bc0e6540703ffac6459d02f7ec9e749e1ddcc134ea7afbd346e3109d7b746bac3c63ed47efdb9e74f61f0ef10ba3bafba5b9a53fbdd84c25ca5f1539a1baa68cd44529693d474c4a451101250725a5940f56b6b66767f0118baa1a54642d610e9e4f58bb18a07e7ca5da08571a351763d9fa4065f9a36021fdff0d1042c405ef847c7303cdf092269a680cce3cc2e688a60b9d83caf08661445b07256d790d6982817f051b97f4a593f3093d2d135cf780f7d0ec4d58ecf201b9843d7281cfd0c6e203eaa0120b473fec0ec85328b811e67170eba7ec33388c1ecaf5885165b4b181690587f695e1001e0da014d2622285a91ac52181365aa1b4f4307dd6f1fe4f46cfa1b88bd883b79d0298f7c3555e9192cafd175e351caebd8c96bf66a6164c97b6e2cbf2a8ceeb89068924b3907220711c688f94c001b59169a060634c4cb77e7dab09f7b1a768ac0cc4f194c0dbf6f4018e087b6875b8a66215c52499ff22d10c71520ae9f4f9fb0f3223fc16d58d04d653b3ec085af7277f28b7f08e1472613788a1d43bffc2370909d3a1f88dce132ee2df2a839339cfc502a7201d89635ba243832722e5150f07749204cb85bc5cca30f4e177b578c9621660d17966fdd6386f4dea45e825a20f9b59b8b4de70bd3b7860b09e8167bf88377c79fadcdb40563b91ae3f7da6a709bf4922a7ac03682d7552e9d7396be0a5c728e57757acc5ed9923036facc6ed0645eeb7f2c6a07b602907a2ee4da70f292a219404a0997b7729a52b3f2f546604e2a3dc4b12f6ad6e2e9915120847c1c91d46a0e13b1715a92c7bfa48c7d8480a73f8c3698228167fd686aea41c27e0ace3b81cbe69aa74bff26a324d6604d800c3ee9433b0979ead3696319102e3024c83bdbd35a5f34264becab480b4aac50414e2ef4368df08a5d1d3f7e895cf2830c1c09e8ff5ea527b966c75bb07a39a0b85dfee234520e39d237446f28ae1c7b2110aa098050fa3cb073b8ef9a215a609234129d7e9ce505b79b10db50ac955c6e8f757adf170f99a660a0f5b6317770c584da3a871196a929f2585bab2462508e40fbb87e0a7147c8b9b2f9a5c36b40e22adc78a4f782e75f160fecfaf866f34a92627965e0854ae75e1ed5e243fd1054f74cd38cb66bf0149ed7f98542bf8dd569e0daeeb9c46bdcef6d6fad12dc00fabb4cdf0515fead723efb704b3a4794aec05fab2cf19a4e80a0c93aba79854013de5a1bce843641c5b30184d2ca391f0a2230c62bd004f53ba2e4011566df1029400057a21803d83301aa02e9ac6381c5255bc0e05c0b44ab2dd94923aaf50046b06f0ab3471b0f8b235c5b51b90f4e84cb3ac101bd33fc3f21590a8fb70d40df846bef3b97de9960c9b32a9fb021c271652f2d0ffe5d0ac271ff1130123910adcca86dd60c54f2ea150842a7ad876e28ebeb7854785ac25ac83d1612d95200fa58ddadc4403459bf5c8de88bda35de29b8eccf8b6a2011317c70cd546a2b90ee6bfd5e96ea87c7845032ca252afa6629ce46b5782ad901c1f8fd7499fde80093c98a5098dcf97686e5ea7000ccd3894f4ff67ef913713c6333faa28e172a00aa7488aab58a6e00bb629cf5218308404f95d3a3a63d439e143eb5b255c57b30261b34d39ac6c7049c6aec81131a410d641244b6dc897ab5e40668a574315170ac818616056412516a73b94cf9f5a845c48b38be6775c0b76f27aeab53f45a10e2c546a8aa21d9641c6de187a60a987f39d5705a409eba6b5cef24a70a47322004b4a2555987f48a485255fb2f236b6f2ac959f057b032c8769473d0437d4c00bfa14c7037b331295954a883098122fc61a206d8c7641c15676175e6518e2c6000ebdb435c702cd60a4eaebabd9c28c600111bfe89aebb50a94eff36de842c60216b8b01fa94b5e50072f5cfe6d89956f7bbee1965c375edf9bee628c9f8d1702df04215204ef6894d814bfa0bd88b7157c26522b3788aff2dd58181bcf98440a6fb883ed81261dea166316e41193940f5930cb4b003d473a66b5e4c52102ef06438e5f7dd895c693a7c69b3acf0d4bd0690819ec7938a82df134e0b95da1210649e136ac162f85682c715ecc1bb947118d73aa13f217cffb58b80ad12dd8ee0760196ae2479c60932f404f2ed1579688c723d7bbd89055a8c6f6d75b370f7201adbbce7de6077976939268a9f64357e6f4718e1a09525401ae5602a8be9f2d07 -generate_ring_signature a204b66b297db8196c5e43fa172a9cf72d610c1a3e5c14a7e64b6e77a902a7cc 360b1eeeadccee686eabb2475524e968331807e166ea52bcbf4b806e056ee332 6 3a819e2a86cbb7c93d82eefb25ffc9d557aaba2e76ea0cd35ef017a0f9db4a74 fe4bd986465cd8d4684788e3abfeed9a49365cf9a40225a9b5f7a8f0d27d4992 ddb1f912f0733db94098ad017feee9b550c2afdae5e0bc4bdaab634dde7485e3 ea08a323f76486e70dcdc071e43b7458b070d5e15148e57268b4801fc0e9ecdf 16e7e2e0736b76d75013cf19835f4b3130b7761fa2f1243e513b1940deac38ed 9330ae8956224cc4732f9c94d92a3470737d4943400c6b837d8a5e4769e4c2bb 5f961793fa7fab2364e40a420192a778e214079b163c235d48364ed07808b50b 5 9f9c488877ea024fde8cb4fa37fa85dbb51003d7120c6cba58a17371f2d9200ae2667a2d3f8f5cbd84f45c42132606fb1746bcac8c0cc87ca7e94d8dca7eea040b984e9b6f135e316fc91a92042025183eda4acbebb37344f1f88e7ac60cde0e505e1ffc6e946b639855222642218d7eed129ac7a3b97bc18bbeb8824339330b01147768e63e31834ef9e0e892a5dac8fc67fbfbb8c9588c78675deccbca0300a5e0cdb626032e763179942404b9ef462fa24db12d6fbec69e30b71913ccb905a416304aee4e78ba5220f6a75f9a25fead1d2ba414822775de23e81d590dda0ea48e81668c4a2a937eb3919ec320ddad7e0745908515bad872b1967507a29400646f55505de0fb9d6b25e5f940166c858d88ccb324470683ea7e86bf28247805826fa9322eedd64e24dae1539267e425eb720cf3c28b82253bf73cd26bcf820c76df3fed0266389f61b37e700868a29a9cea712e6f7ac0b48175d079166a620d1e0d597124bef8c9ef7170132057840025df0762210db37ae05c10f10fa25a0a -generate_ring_signature ef79e077a9e0e9424ccd7c150414f789a14759ca964a0e13fc01fa5466c81e78 f946890532edc31375a4fc9e0201f16121acea77989bc1f44f7cc9e27d618cb5 7 7833f5dbe94cb5307fa63720d352767c4b1eeae31307e89dc2bab1b483eb07f7 a7c0d7cedf45355d0d2981b5f47390c3e452becb05e015647e39fc4221dc242f 883664c5618118cc6d2e9982d3e3b6d28916edb1db5db6db7bd5120dc2ed1f7c 1227bf14d8642d1ec64199c7b955557194a4bfd8962aac9236e38d25a8fb47f9 eb41c810fb20bed74105bc9cff98bff7526462572cf709a8b85ae65462769d60 55e0ae0f1a539622d44ef3ec8fa1565017e9f763c45f27eb5cbf6b926a414bfd 7af96fcfd866484934851fda064375a00816e21466ffa8fff2425997adb7c190 0b0c659145f52a67e664d6c06aa96452c552c1884cdd0f9e5b7819adcf173003 2 b2c193d0310a28bfadb3c726c54a0c196fe466c5e2c8ced323a322c488745e0ded55711281a776ac22a3bc7c5cef72fdb8bd81f6b51695a2cf53832fcd1e4600909691417e737b8f8994853277ef4b5035845c3a236293daf42608213992090c110cf0352e38fbd28bde85b126e3229beec14be1418531a4a17ae7e6eb0c110d4989c520e60c2a47bac25a5164103e540ff0eabae6202e023dd252a8a0c94b029ca74148a5b0aa1e01e517a9b81cc0e0e6059809be94d6f9c144f0c7eadfda053ede2ae1e97872ab4efb93aa448cf67d6bbc8dfa918465ddd93174369e82910da68d261379b8c536247121899a3db0c4399be8282d0c2114b72aa8e3eeaa4208a75a6d45d091b7a0f73471080c10599dc9f0948f1d485168cd5bf862650f3f06d3af954e97692ce6ef56031e87e3afab01677769865b1543756554e1b5c88e0eb5a6d40f4e5b1a0dd3093cc20f4d9e4259238d3de00cf9f13fd5c32a702b590fe3e0d624540afe8aab9c71cddfa39c40217fad437432654c75d409f0243352032f6747b5eb02ff0871895f86048955c2a895e3226397003b17acdf4e6fcee10b6ba7a94de7600c5451b8b964911d82de6175b90ae72ce80d043fcfdcdeb6bb04 -generate_ring_signature 78e0172eb16bc072a3b80ca90d93b44df26ffbc7dce563174f5865f7c16e5f43 7479b29e23de8cff8858d8ce192a594e7c4c3eddd8b898300b3994efab06c5a6 4 ca91beaf2146e06879051b0b1605935a0df5b5eb1ec9ea4f7f8d0c698e7c5bf3 567e5e858d217b840f50e66af8547d3bfd23c76290ee017b1c5ea07abe4ca354 c24d4eea3e2e636a9a24934ab8174a05043ad5612cef38bda772063f291d090e 7c51495c749ae14fd8ba542a7fc76aa77d4160b73f84e67811c1087eeca84d05 ae5a08468ae07c2ae86e46255bad3bec88fc27a5697b88a0a426c8ee41372102 3 e94e9ecf96317298990c34db47c7cd0e72fd480fdfaa6bb25bc2d1c2866fcc035937e40270c9c8730c7c053ffe96e02567b64b496198c6b1bec8f36dd8800e0cba0e8a8001f274105017c73fa0c634b556431f24e3e72b6c82df468aa14c7903bf9c0a7568cc59b6f5196af8059fac305516b7d8ca5a636e5de7a04d30dfbf0fabf8b0b9baca85c3672f674e94c3b1d1cf2de1ff1b5ad03d5105aed3e3940e0ba2855887982bb0012ffef9bcc1b788143b9300d36e3155548d4d5483141ba40cf1784181339d6658fdb41e9f0a5e7b0b1db4f2d29d52ed7b4d438a3238764706e5bbd9e440aa828913aaff250cf4179ddcd3d4800362fdb8ed3bca70845a9509 -generate_ring_signature b2b17f8eddfd010da161593db87e352a00d0f915b3095657ce31bebcf0531d77 6d9765acd0f77a17564da4a5f7f07a0b918bc309f136baf6b452eff47b5278d4 7 0dec43ab1cb7836dd07b41edf9013b8f8565502509bd853b73a3fd7c2d8332d7 d007bdb3584697e80ca791a489452dfaaf96690715738e9d0a9772761622910b 3bb2e27057e5cb52140c29f86ec9072947931c4496da0bf88eadea327b45e13c 85fb98fe49d5489a55a67860a4dccda34a81b00bf5796565a5bca4258eae531f 3d1c25052eaeb43c950506c73a61cdc464c3718a502d77dab4bd23eb34093bbb 386800a322ab462444d1bdb3cd943642b4532cb4e6304270d56606daec593bec 898e99644703e2ab485bf42197618479f68c7767f1a81a754254194df7bb5541 8ccf33c9539ce3697c1ec001f6374d950dc0f5888fb2459f0bf5f1c12dd3fa09 5 5d55b880fe032c4b5f0a7066573260b4b2db33ff8ae15b325d6ad85a82629d0f1ebf913a3bd8ef76332ef71a5ea7e60e4a7e1d2434e243ef70ff00c27f4a610f3aafe8a597d791d503bcae33120755248d622a5fcc9c815646ea105e0342e10e2d0f4b54539a67203ad6a65963083f6daa7b3f9d80edf5dd910ab2fda07e7b05435154cb94c1ab236bb3c9f898a51046a9bb2f4a8542b4dc30115ece5a7327072b79e76d8604a424ee065a9fddb2ee17e85091339bd5aedcaee25e606ce07908876d81f643ce0cc276d1d6a24b9b162cce63c39a9f868aa9c631e4247a2d6804a449286340b2a0cab47f915c301765496bad6eb1059cb6d7fea2c8dd461277085a539877cdd601cb6bb4e15aacd0cf83c3991c29a5aaa63ae98cdf12be23a408f22753d6d5e809e0fc39ee3d7f384b5ae57a03901df297d019c74ebb4642160009a87da730278191f8a7b29b8399374257a4947e0451aa05e2913716c595e50716f5161844c3f98fe8e6dd6711859a1cff84b4d0db0f673740a1818b5120200cb5fdc3a18713428e7b3134d5dce455c6418b0aca3f16d8a1b8f099de21515a028508ed1f398e780f0b53cda46a45561ad37d3bef7e2b8f0d56e643b318523f0b -generate_ring_signature dccd54de1c3418a71890e09bdaea34de43197a723146a148dfce50806f6351d6 beb57de477af6fff12b965fcaf9ff7229f670af5466c040902abbaf20ad26281 227 de6f898395f9d3acd113f747c1ec42b3c669642e954e078a84625e04f1203a86 50e0ec8c3ba80da72d39132072ab6db97355bb6d689df8d49323d6519f7afe76 33214ddb5c37f8ee1f71d77ef8f8389cc93ebe3e0750f0ca750067116ba6dfef 624036187cd190236a3af52cbd8ff1551af9ea618b7ad46c4039956372f2b37e 4d8a76e47fa3de3b4230220d19f147eb2ac1ea9cb0e815d5210310474bd722a2 9dbcb6dccb566b9b4ee3d9f4dd096ad64b86de505861a4b27007ed26bd7fa057 8afabd34bb7fd38de6ac26b47d135d6a0c05b890061de8e26e719e87d1140637 7d8f3290f75e81a26454b06a408ad4a5a025586eec86b8f1d4a20c006b0cfd5a a81cb1aa8dd7b2845b6f62cb21e37327eafab75c305977a487c7dd9cd9b72285 586bd7a57d35523981bb88c3a05c38f6ee6f7a4596a5c70d9bcbe72ff94d4230 75c17101e9fd6868e7881f5dede9b009aaf2e6945858c286ed121c3b912b9466 bcb29dbd41f103217282fa56c1c3e49a30bdc22c29f490a0c87f15979e90db94 10865f15bbda6df7774693537a26ffecf4f8ed4a9be5ea8256fc5128a5f5ab24 79c038c008b87d3425473433d22a6ee12f6a94912b2b473be3525df20304632a d2ea981b421db4622dac964447a5fa0f0b91253cd985fa651a0a94bb06a2e531 40360e8d38645b50466c06c3d2f366fd3b41ce9dfd854b4b6a6bbd91b9f2bbbb 85386e78ee0cfdb9c053759b698aee59487b080a3f9bb73636b6e9a36e80ff91 938980150ff4af1e402456d64d15e1a932f5b9ae0d03b7122c952a35456b6540 aa274c87ccf47e58a227424fbbee715aefb91a6a624217bd3ff62f4295200849 17ba30bae32dc6e3aff58c7b865f28ccfe8ad56d1779c3a40c9091dce280cd21 40182f7b319e2332eec3a96ae080935a8d06376a85d50e1dc1e54459b00538a4 18772a0589e44334bfdb0154f4ab5168e7cb33c2aa77a7603425da7c12d6479b efdce92d903112472849ff28ca2f7e312873d9325d28a378ed723d5fc2d0dde9 c874df6ef1ad049bc46597e1de0533c878070fda32bad8dd6139e98b04a44af6 09d67f7cc7632824c92065fea6024d80f1a5c9c2fc97d66150a5e77e9b069fb3 7bd68164f521e0c47994aa974693f8bd236564ad73add045a1f06d5d9a42da0a 7aab16af4335f06f3f24f38806b10c20ecd7f75e16905a97caae144393c880e2 096bfb98ae3213965acb6b92a60066b8f8ee495df93e5a2944de1646c369ac30 460ff31e4a5363b5aaca21aeedf944a713196ca387f438268f5817de68c22293 2ada78c71e899bf785980d8cd94f027e365684eae7c4292cc7da633e00edcb90 b84693047173cbc9166b0ad16a918d2dd5cd5b4dcb3175343e2a061f83623e23 7fcbf67da417193a649c5ca188c3c330d1615cf12e6854cb45a7899c24e08aca 1324e3c54e30e3276fad872fdcd7ba4f9ddc97cebe3f886658ac3767d60843d9 e555257d3f2fd95dc9555f8d89ef1dae813d0f6a9ab1e181f7d5ada73c8efd3a e52d868d66be401ee50f7eb5d74746beb94f677a4254eed91ab753f738e75da3 1d7355aa5837df46db3e8e8993e73c4a294d646d190a73ba40aa3ce841a83534 1aa2563077ff97e778155ceb8f8b4c98e45295e005fd9a5202e62ca462f995e2 f4e6929b34d3833940d5d30d2a7b0ccaa425360c42effb1940a10f49abb4b8d6 960da78fa1fdebf415e0baf03b63eff38b81ed99639186748188c348a3d5d8e5 ab52db15249b26d53920280b2b4686454ee211ef81bc330128e7c7365728d36d 72182c9dd9736c191efa97312318003e1550e18af5ae7b5f57b75a78d93462ae 8a822606f03874e68a1297636b7ddd645966b342ed11e826390a85d6fd13c3e8 77ccb0cb46f40123a379e014f46103cb21169b8f8dc376f34602a61ff3a164f6 c4a730fb9e281d183e142c9c6256183bba9f5871290071ead468d2b5479e2cf1 def7aa66dd688039565fa35a223d34c83aeefe5a6e702889eaee554028efd3e4 c42af9fb89579eb04d706df14cb7c47aeb844fa1c81cbec70512323ab608eecd 6f7331a1adfd3751d3edc5dfa02caed59d35813e646c474854241c7573beb1b6 91573e6964a2f69fba125d7897ee25fef6b0227a51a2deff1dc9205ed0778ee4 ad9bf2a571f586d8368024107021af31d5f5751999b25129f660f5b63cec9c97 0837392fd063e15910d2192b3c180228bfc7f12dd2428a81cfab8f91cdd44bb6 9c363f58e7440049d17164c4bb1f5a8a1ff444e1c26cc1ff97e43f4fd21f1b56 7e3e818d6a8d02896dcb8a7d53add542cf205c46108773495810bd8848d13e3f 4788b7a8e7b695a8ce58a3d61a7a3bd37d2c65cbcddf0f8402dfb8a5b1996394 fb352441f47b8f406cdb638ac64e7b6e8088eefdc9e757b9eacc7d3f72222a82 02ae8186d25a835ea25bdd979a85e2ed9681180b51fe5812ed67f431ae4c5f62 099abc67b8f2b1411f365db32e1973dcb2f6193e674f5ba9615cd3665a509a22 f140bb04214d43c84272acd28a16c49e2b6ac054ca2edb06542c2c2a764f6a80 cb2a56e6e72f1017eafb033c66e4899cc0da2b161c47265124ebaf0ce5c4fec2 838c1eb32105b74439cedb6bc89f68fd1e1359841994b58a4a7aaf5475c54323 e1c28c4e44817363335668ad1b2a38b2cf8ba1c0da151c1793d6cba07af2c5c7 3cf16340f818400832e2f4d3ac53242aa822b581835c701be359124fa74d51da bab07fc6e7065cfd2ef24b0d99bdd0a37b7c3a94890a0ba6e112ecefd9b59fcc 69ae4430e581881a5666177cfdfb2aa4d076e7c7fb1fc1df85f4a42631b652f8 5cb788dadfc2f0a8a71a53cdd95e973eb56ee8d8120caa38c9075b1e1e00620b d37ae42bacf5b181aff456091f7142680b056d866e1dc537b4c9c7c47d892068 5d8879fa016d9badd76b8e69f77bd6f02ad5b0ef79323306e8cdb3d3175fab59 b7e0d03bcc3356971ff4e5f2014a1ea9e2b8a3f87a170d25cd334ef440f1cca3 1cfcec5e2dfcb2243be40ae986f597f5e62efe2056fc0ae0f093a1ef8eac4c10 d45fa110c2c973d529ee68f8b00a7599c9e9821af0006cedc1ddd6ab3e37d9cb c003ff2afabb78406fdd999a1b48796082f4106fb616ba7afc27b475f2d78b79 6579d1ac0b18977a0b4a3184901abb13148a833b29445112fc0936e7710834e4 d2742bb8b5bd2fc348adb9121eb048b842ff428edb4cc0e628a51b235453c183 bf09a5bc58fa250176148cffd82244e614b0fadf94c23e53abf288facc92510e 6d37834e2372f26ad0ba8c510660ce2d74a495419065d78480332253bcb686e6 56d85f362ed1b9d5cf0cc9b22b58f704d7a1d18cd9799621c158e0cf6eac263f 15c8bd061f78d454c02a67973a18883014ea1a506740e3231a9b942b405099de 444188e9d62b697974066852422a091f9f9687895db8036c4baddf71bff17b63 652c85a355ae256e65bb47ff48c0f421633806c127bdbbc99b11131986a17476 d6d364039ad279968195fc81f2b2b1b8e315fdbf21618d05976eb434533ddbc5 082d940a66f319b4f2a26578dcb0277c9dd241d209f11059aeee396c767d6943 0f1ba3b82c1278d71c7ada842514e9e8a6b03d49925f279a55d84cecf4b8ea97 64369ba0557e73fdcb4fab986fdc58db1965fcb1b5fc2baaf7c86bea7e4cf0a8 c612977b21bde87630763327ba5fb9bda6312a03fcfed6aaf40b56e65c945789 8463e1860d65d4b64eac0d5367a5af5bcfa203c16dbfd083353917a61a74bc14 4ad00dd4cb6e7b62c74a36ce1ed7720b8c6453b570677012091f47ec7632759f d544467e93925c0fbe87a630d5a2471f3b67e79abfa1f8d3e89833e36d57c7cc 1127b1aa8e3d8bea0b4a9184720eae39e1879fa973d87966cd3fddc8901e0ed1 afae49672415a9cf1aa4f5d5a921e6ade299a517a5681c5888e1eafac35caefe 1bb1d53b9801aec3210277fb8af2e473a8d1026495c0900735d89f91adb54508 53c979d5d09084b0d729b5e740ef1ed51f99cc416b3096869eca4a287598cf60 42da4fc63c86c7a13bed979e30195d45e73d0b959865411465c2ccc30983a0e8 b0e4fa801af1c5c2834b31cf80831fb11d626020255f2b0bbc7c96465f523288 2af31e59dcb552b4eed7558885de0cffbb5cfa7217b423c590017588b488bac0 6acfb4632b22521dbe49fd353a239848f53e7265d43c89b59da8b0cc3f8303ff bd720e79385f6d2ca5f70fe141d02b50e21648cb3f959daa425de1e4392e5c75 0e3e941a4fb0c523195cc6a0dfdea6f52c566ab82c25483b9a10a9d11465589c 85fea41341b6d49d4823e309d4468d7cb655811177bb8a53e236c0747368b819 32593bb228b2f454aa091fe6b2e4716bfa29be3089306895310b1f2f57230c56 4ce8bbf39404f890dd296a2718624b8845eec23023437ad83dd3f90e3ebeb52d 434fc3946e64e1d07b97b77988cb48b8ae1133912dce2b9c1902bb9c83f63886 14354e897eba43297579a03878669d513e37ac42bee8e7c64e354ed39ba6ac3b 67c9bd298f98c083736bbd6511fed9fb238ba09634d630acf8c13fbf5d4139cc 3c77c3a7286acbf62237efbbae13eac56c4c0bd55f7fae2176550ae2f49b6b46 5149f6fe63a8042b6fe16c6e31b5b3da0245bb49ec249045152b1814e777efa0 e9c51ac176861a0c5e72275c34686f38e8fbcec99f81176a4f280e50c1d68de8 6d2de0ce0adf4eef46e9bc7a082ba9c45384c5e2766f7cd374f6e7ecf767afe4 7defec0b1eb6aad14ba9f886a3bf94df39f8f9beb4bf3dcfdd8e9f30c74b62fb f816bc04b50cb419e5342f8d9c1c45f61e8f7ee1021271cab7f60eb938619856 4e740f39bde4b3ca794f5218df1045ad330c992f198de22c7b1581e585f6e8bc 2a707dd3aa3ef5a0fb89987ef90884797e9b679941563b1b0f0fe482df2cb704 780363e8eaa858601ceb6eca2a95ff77caccf4a4ea15893dbfdf1d97f6196b5f 7954b47f519dd86d64fe572f5c83746dfc6cb7ffe388e257e5a27242705a615e cd730bc5c83ab9fd608d5e4d0ed2fb3a090e993da29c0341120f94940fb31a54 50eaa1323e56b6cb217c2728120f51cb7fa19c2dce41be26baef95c6f61cc276 811817719c3c0541dfeceff7756e80f7c868d56d6bd06feb1027a0c37b9957ef 1221701c18e4cb5e606260d2a85c99433c136549ffcbed18cf2e843ac4118695 972eada79c154e43a5ab8797202f266809d163f8a1496bf750667667d1f73659 812e63c9f4f8225eb94880915c2142e26163ef6d27d4a240b9bd3424ab0568ea 65e81550555313646f8ea5d2e1d998039c087825103a1cc9aec56489d6e7cb4e 4cadbcd7d0be79f6f32dfaa6a45a7479081bb824b5029c3efcfd51cd218791db 163486ea2d379505656ed6065a355a2b5a0bec2f1c56121047e2513708af0ba6 e312f142355698ac9e4705286e24ce259986cbf9c475be9908484ded0aba457d 5cf113e03b26cb54d5f672b6997a44b28af8421d258d1a51244abae07783dde4 7d19c56181925f1502281af675823ed9799978028ea3fde25e7cb7f2b2bf1af5 561035986edcd4fb791798407f9351b9d15ab7ddec1b1156211e4372f65c081f 9c2d63e65438f187250b110223fc1a41600f1516b75299d418698ebdb278972d 8db1c5443b19e83d124cfb93cb7659022e0ab39ca30fceb1cb7eebccc04c33e9 2a0beb68b0cc5fb35a2c8ad37619b7faec3a573380101bb1f3f8f930e22f17c5 95a8467c529e347700ead64b0f2b2520edba9317e1988a5e05b48d88de6b23c1 1f07b7c84d37af770b0d4dd3db8031fd8671db285db5fb292bb24b4cf03a66c6 03c26aa45c9344f2108ed8bceda99db51e2b3e476a9507305f4a264cfc22487a 7acc92bf21c416c9c2853cdbcb75912d17768c0558f45a4f9dd89f9950c04925 570dfcad88ccc890f989f6fa90445433718d1a33c2f6cb9d06f01e105641a0a0 0e703be79defbf776eacf28e3c02faafd451295528af4c3c5abb85af27a26c6c 8868637d4111edc6b9967b4817419116ff4e08342f94a1c919f88cfb66511db8 ad34c041687a0aac2d5b95645c3be9a092854f05ca306fc4df87b66fa20ac854 3c9c07cb12c72cdbd9c0a53a56dcf49286ccf1443bb46e389bc7f98e9c1e5a08 0a73a13db0b8a4cec8adb5f49b3ef1aff9116ea1b40907e7d7d53747914a6165 301e0e2771166d45a7db4739b33e67ded6f458140e03b77f7dc37dc10e5795c3 456ac73e71f674bd8436300971c616ba64522aad67f199c8600ddf5de5a5e6db cf529e39c63f83fdeaf309fe226248dd7c0d8ece4889249b1ee3f42802e84bb4 6c593de6e012579b5cc3f43dff7ac21e30433117f39e1dc5d17627dbcccfa8bb 2310887b528cdb93fbb62059afefb5dc8bb1ad99a6c26f470e8dafea9a21b75c c874e7cda400a4a7d347b9ccc3849b871083bbe16ba4a0961b5407d885d885e2 7d85f52aabe672cd6374d1f45ee2b8bb64bc9aa713c9d5b11164358dc0618043 ee63fc1d84e5ce7b6fea05733df25621d53e2f8b59d46cf6d3c206e0a1a4bbad 1945742ad66ed67a7e7be7619553eae5772137b123efc125cfa56771f73628c6 16578d8f6792c063ffefbb9fbda79cc2cf4a217a15d09fd6d9e8c6f5cb3edfb7 2fb93dbad3bdd8c52e66bdecb845ac12df250668987a46533e64ee1702586c11 0dc58bb319f98d536c5aba1b410dd591de2cfbbcb9626004e73f953989a09063 8146f9ce2ec99a5581481f5f9ccc32e31550925b16239c20adebe48c2a0dc8ed 6fbeeda5f57a6c3bec5266808f679ebe1786ad8556df24452d9465ba0163cbca 434b44876cfb72d61daf97f0bd8aa85d323af4320f52b880dc55a9c06c3c1463 c13ff3702adfcd8acc2a0b6e4e675b82f503549dcbf14a7c29f66393fad8093d fb76c1d8836c2a1f718106011e3dc5ad544b893726fa72b941d123ec6a20f785 2b7ecd72aea8643057327b542103b08e00b79ae6198592dde61cd62929089e83 e7cef581b5062606b00a2ae4310940b5f18d56d2742705a8bc3c7c54042c1694 d5e7cf1bfe62c0c6abb750e4b22fdc9b11355e4b34e884c94571163d21a81d6f ce69ce14cb9153cacea90c7fe3e8460653d27c61d239718a937f1fca35f99d17 b2aceb0c7bb9a7f865b3f01d06eac0cb1d3ef32a4e2145a49473135641276c0e e0dd5fac25d7e724aa18512adf237fc463676a5d1c9ce42c6a8b2c5cda013506 f7e58fe431e81b6fb8d5db68f69a7e4596c76227c0291f73f9754640085c7675 b63f41f757fe3f6eb32d2b7ecbcc86dd06d3ed3c68f22e41db42550913169a45 3a143a89e143e860c93e71c71f42a04ab75dac68baf92da4fefa6c6b173523c0 7417ca2eef7e735a3ab12e4a0e3b3c2439c71dfad03014200b8192206acc78f1 3e0136f18d38405b67567e2ea5165d8782a1ced39df60f06980d3d2ad9d24f3b 4a3e58971a4e4f94ce12c054249d1fdf9dc371bc7b5279f78197800c2a51bb46 269cfdf63c238721dba6bba1b839759bb0fe9e83d609a2901d141786090c3f94 95eb48427cb6c4f471c2ea568ed9df6633862be02cb2ca025c73b2d624b056af 421e453d565a46650ef8227bace09af7c068466da857357cd9b2873ad1ad09d6 822692d9465ea2005914901f30869c138f9a6351ee06b318ea9a26d443d97d39 fa23a03fc5b0b6e1150a54fe2bdfc78e925f4a66443f7e4a918a7c44cdcd05b4 c40394856093b0f40c439a94508d1fc3cdd5d6f1747d7a876c3250deb24261f8 0082526a179e1f85f2c456b87355d540144ae21c53cadf9783c5a00cc145fa73 91265fa8f7e3ccf55f695c17a0004ac429cfe485463c2dca00a116b84883ed3c 81dc3104800931b6a4c5cece8d3e2e8629722bdcc210bda4cbcbf9871a43edc8 aeeefded266eb59949423a42d3ebc1af07873e1e954696bf44daf3a75e7dd5cb 230cb94219fe81dec527b602ceb442d2fd047f5f69f94e5aa5229e18ce6eeb72 e495df1e8aa30144401c58dd35d99e206efef5800b42ae2c855ba2933ed1641f a3aea8193f840fd72d17b18a89b937a4892fd267a117d45db566c334763275f5 21df42a8e0ebc06d0be965488fa6bc6fd56e9a8071e7d7066e9c0be8a18715e9 199b10cff8216a7ee22ceb37cf3c03d219233e65a473f26fef00137d8c52be50 69375507f886578c829b830f5964a71243a21a88b9aea1555bb34b136776ae64 53d95e59a7cec2ea6ba975536d48a76fb560f61e988a7d5e27b2564c4e429450 9840ea72bdb5e374a4b515fdbaa737f50be2d4115e4192d0973a652c10d553d1 ad8d699290c6ea3864c6dbfe1fc2df282a7033a115ac050af16cadb47f1814fd b9b84b4655239182a7c635dfda8444a090d56ad9f36b39e49c9cc04c9b903d5b f5c7569fa43ac9d2639d582f90467c15ff8edac68da3368307be710019cc73af 52b6e9e81e004a4d350d87b19d86dcd759429a09954105b4b884508d0fd2b022 194d7708a9ae555cb73ddcd4b5e41ae54e297c19b03525eadf28030b16c47388 d158efb1f35f7d182a24ae62a543440c932d48b056d62a6bca8da8fa388fa251 6aecb71bb4a7ffcd6c4d15bccca66e1f2bc16d4a6c3d75990c3dbd30800d0282 5ecab698f65743d8bcd619885f36e574f28ec1f665847dd87ed66c7bf94bb8f9 5824367f4a299d2f99dba1bed610b421f6486ca776d3b1b3e8ac8e9c7567b4a1 9b1a0a3bd2e544a7cdec5b13861e77c8103386e57710ee6f31ee7ac777d3e089 eb852b565d9a9a4b1175a30bef0ed763c6d2d0369dee85bc28671c7d50dedc79 845b3fa7475922b76431644b6be2f0cd48c997ee497b0e3ad7ea8c3d1061e1da 1e9b85af0b4eaf78c85ff0089c6888b8cfcdd54f876d7111a3df6f96bcfcc678 d30f8e5b89b088b901c943e89f093b40838b706757139eff1b47c848edb286f9 aafba65a11d917cd3b38bc357cea2ea44cd018cffa6fcb9045e8b35501f93ed0 931de2cdda585f0ff0f7f81e747c1c5b20ae49a930a943871c8581dbfa5467e3 6f7ec2a05580bea3790eda02264a371e19ea10a05818b2d1f9df342945276a76 f5a08ffbb5b9317ba9281c7c77f3f6b91b02a17b8bcd51b7e0b2a84bfa0399de 4737d5fea3b9e3567f1c74a6527c2be489002195ec96c75fa7a412fa020c4b90 8693790f118dd039b89e51cfa8b7887c98bf8145dba4a981adabf3e354e45d77 b8a660ce9846d73f1ebb888faea6345ddc5c2124c9eecbab120d6ed427c59f2a 4b1ebf45036321b68ec8b0543203d21bf9a639027fe58261a98b44c0af19bfbe 24b6b654c8f53fbe508e669b3804cb9cd55056540a9b7df24ce403888b3999d3 fd9930b13d52c5d70440304d0e1e5b54a4b6b1ca2a435677c5f118f07e2b36ee 717eaf9e1090b2f1894e4678602a3cb5c0f374858af6b0d4fc723b396353ea1d de9c034a546b2c6cd88154fc9eb766f30b986dac38c3cfba22b16ddcdfe9dc7d 93c221d3be2d20f4ac343b9e67beb6dbe181acfa2e03e80b536b74bddd754f38 4e3424bb19b878f1845783d33117f315a972e4cb8a4f5f39218ad3eb081e07d8 4f254a776c0f3bd7779c82c22c33390aa41909c89ea9bdcad91dafc6e4003050 2050b427b2a2ec9dfba6c86014777901852742c5783c8e89d114938ab728ee18 9dbfb19eb52ca6e2ae0ee44e5df65bcc5e7439af40389244cb3b54fd9866aa26 d8b8df21ed6caea91e075382344d7e63de02addc86beb7d76be24ef2155e8353 22662c59ef7015896560440498100035ee0763c5a6de0b263dca397058523c34 0b8d591914e20c40bb5fa99de44ffbaa993b8fb08938e3f5033c07f9e4bfe881 55f9e2ad6e2699c81c525daa2008c323a0978a3b85dc99d591dda69f0aacba72 d228415156119c0157cccc74483b149d443a4ce32971461239627b7aa02a4b89 e8c7e96a2ffea407a803eadcf5ddc6254795c329a6f7332fe8220bd26cfc83f0 6e14ae550d01199ae9b978ace5b382fde0807d8671827a75f3951b18827527d3 259bd7e461198a3ca17d4336ed9f6214cfd10404d3a6f6a9a0bbd87c26bd9076 25e4b2650205fe5dd3c4b1ec5677389b00a4912b5810622b505d72125200a42c b38caff798124570938f7d2e92aa8b0a37229020355e0525069cb2c2ea16eebd f6d09aef0f9a2820f555475e44521817a2044a407da71731aac20fc4b6f2c26e 1fd4bd9f88327912a6c6ccf04009e9bd3cf0fe43fd654e1fe96382ff0ca4c509 35 7e308f9108d9f3921d5962875e9b937cddd86c67f606ea8492b5f38c1502a103121e3a84f0121bd0af0304d84533bb273d4d7c58550988ead7c9303ba7360d08eb80d12d809290ec94c35edff2b817b85473f87e4b58e26a356017bdad08a60ba11aa5148c5501c75abee978b9c04b5fcd775977f8455e76e52044c51d6ea503ccab1c00cfbadb06876ae1e0c9263e459188aee53da19294f5ddf5f72b94350f52d3c66d8394111a8e6924df6e039569394f84dfc973130a06155f5803024b043e69295f2637c10e5ec54538cd77f85077c1b0c097cac40f437270c289b5350dd3cddd37bea0ad347c914fd540de6e52fcb0bc585e045ed0dc1c92de785c570e9eea914820ad7346e3cf1b1ac5f6b4569797fa85602321442b6856f8325ae70751cfb870eabcdbf06feaea72edbf929ba302a5f658031b6234b5261adb534a06da6dca88ac50da346c000bc249f183a09d23c79cc6ae9dff2c100c8b234ce40f1b4ed62c34da2f877a8686282e905842ae30654d7f4e1ce7aacca0ba8c1f780f69e34c2de0a9839ae12627afff7280c23e0db49b5d101c8b342f3282edd917052e466dd7b71f2e1f35dd6f33952527c28bbe51138a21abb702b5a24f4425400bdce16ede18534548eead784e03ce7e331114f7ba36c5ae3d4a91f481861b0701ce3d999e29e2c14378a1fa7064abb54cbca5e6df0d3f290245edeedd8ff3910d6a7848483b0f8b623b1fc92abc4630e71a333558d846e86e53a73f14abba4409c23cbf48ce04822d7db21d501594aa59251a5e932cb75c968b5c752c3709c4064aeeb62813a9c66c3d67f9f55329bd2dad112b6fdcef7e58a9f18a9dde4ef30ccafa71f2e7132ac62217a4b837ece3ed2f858ba5f244a1c05fdbaea5b7cf6801e18c1902c1a4c4beeeea4ba074e786471c553252e479805dda2d97edfe7f16033d3ebdb9c86fa3eea9c9ba992d0af03e98643ecf495bfd6f7a7c15143510e70e833719e3713de590e6837552da1ea891034447e232818b7eb8dbe9732a4a4905996b121cd8fa375f761c31cf6e3371c98f71bb30c7765bcdc9a4aa6f959b0000f3cdaf5d4d2a12e9cea4bb5428429a1b0446f1b6749461b18d28260a494aee064f8a1f6f92d8be76dd9056ed37bf0dd0b8362c026c90ce49a85a52bda6f7340a900a44e7a673b10b42e398a64c8ad309026acd9866d0df03a46ba1866077490eba015528244082dd00cd98fe0811fbc9ea543ba296826632ba3d2b40ef79be0a1f5839d89034afca07073f656d3742322b0545c5f2c8aa300bc1868a7569190c4fe1e9ccfd5bac13fd99b797c9b0571a08bf73ab8adcddcac3654c24f08200024b5a82ef4b1b99539b7dc11e57a18dd2cc744e12bb19b3060355dd0540018f05b1894c3ba57c3df94d78367bf49e795d3d3918a3b71e1ddc31684939fe49380706ffa3267749183987d9dfa191a30c79468ca27b4e48ce7ea29ad6619a35b2046442e99e8772a5478c5e2668322825267cc60e71259e1ee21b0fd71990911a02b3c0eeb2e32f589d42a9d7e15bcd18aec78f11f6d3bc31f0f422cc2f0afcc501f2932391447ba4afe5da0bbe7d783936b8b70bf758f3b28641f07316c69af60782dd9f89a4d75596ecb66e27bafed76186a56156b2c98fdc54f96272233f4207fabe4a1f5e647add04ec9cb25de359774f844a86b69f8833be44beacefcb200c143534426aa64d28068e1a84ec617a0ad31995873e47fa91180460090e4c8206123d39777fb7d83ea96d4d13a78b6e45076e625a227c79a6fe0410d2e42d080ee386f376655611fb1e9ea539c991cc372140183fa45a9761bec5de4da7353c031a4a6463ced9af2c960b6bc31dc43750350032be1a509fe1a9f6b3a7b0522c0ce9340b12f8678452c36b065757c05c4a2690c4d47048d05cc49d92d667e8ff05df1fe2c5dc184b4793a8b2552b4123a35c93f661d7fe78441cc377fb50c3dd06e6021e4a1b84db5463e801ebac2cbda82904bc076e33a78746d94378b1fa330475b3f01b6523524816c3967e57af098b681e46f23c34fa9af4191b6fd5f74d08ce536a5d770924f875d886ae885695ff96cb6d1a4252a0d381fa4dc11b92c904553adb374fac14369cc66101aadf70317ef7d0946d9b5b6019aa85681d49bf02433b99b625f001c652bbf0c1256b4a83938410297f8467a6b035c8c24cba2d0afec80bb6dbc6caa0a4ca980298e03a2c047913f23ef07b26cdca76705ec3650d630fa66f40c088e4a82f517e9ff3c26cca3518953405d194e54726a3324a8a0cee9257d0c63f1f6f07119a5a3b400c1d7d9fcb0d3fc4470c84eb40b74d14710400ff55fdb4e27e4be497c28c96f20f962901fd8b1a9a25d2f93b6861a1afb403855923ca02f030e18d9b8409f7ed72a020fefc0e59941662bfcb5285382f420119f6bfe18d79b078c30c4d2639001f578805abd1f5b022df991525acde1abf08fc3435eb89634ec41b40baf9a4c6b547d2142cebb06ec2ad2f9e0af044655f0323aa305767a24c301ef4eac4b87f9724fe9d9d7c5427cb07b12b1270decfd9062976a2b8e5873082d95774cc0292d361d863d96915f61be5e02898255c050f04e6e7a89f7664ec47899e55497deb3fae8c9dcda6dd8d07587c65c78cbc93db0cd65dfb91859a94d9ce830a9c84ef7b52ede7e721a1c0c3dea72e26fb7582ff04c2fb7a7ed8445136ef37ba1b91945adf2bec1f3da834e3a3157037db7634800dc108d32bd426d4c1045275a2b6094aaa58f0b68b4fa258e8fcc4b01b02b8ac062a37c09be69c54830efa33c46b00f07816e7a845494896f96d8f6cec3faa8d0c222b00da1784ccf31019e409eec43e81f865d5767e35fdd9ac90725766321e0e02cc4335d67be30c859e2e66d09f651148e3250f3bb15bf444b87b503f20210b44e03a233322db8ce32829a58982b70439c56130214c7bda9fbe3d40eed7fb0e0c3a9e68c02d43a26683cf166521745c1935b039b3728ab51a9893e361057a020cd3e9e91a11b8c0df4bf8ab8f6c8b0dc15d62506868e1ea72d919de2b0f920ef3722c910032a1a4cf27870a7a0ed6decaadfdd529d75a4e742bd66ea4a5ba048e9d1d8cdee7f0dcf3299bfb01032aaaed959a6f7b7b2b2738ca3f4788eaac09202ed8db29b02d6a7e92c01475fbfe9253b897a908bee5ed1d0bec66a2e5d50865c151c70eb28629407c003c314df46afca3aa82f207b690ec8e4c28a3d5660e42c335d028a33ad9ddfe2fd4daa8a25cd2a5d8c213fc69eacbe64a97044dd00a5434a5d3e20e771530c72065c2a86f2353d0600e308a8855377da0c64f6bb90e9017294660d13ed05302631086e5c2faa87263ab8a85f620c6835898c6b86a0941843df16dffac01d9c926ba0f02ef85a58dfea5a99533c95b110c4e4c220b0d5cff8e6cf98bf37debaedf04cd25bd591368ce6ceb39a635f695ddca1a69ac00fd3b1668e9e9a851da6fb6975c5f01cc30b8a4ad91c13daeebab72f15bcdde0e2a2728a60369eb1dc7e96f3b5ded85ba47b89bc0b080cd7638f64b2c1992e205f8170aa457f84c5d831b2a6bed84085ad9899ed0a09b1a88aa0a24d069c98d07426dbafd82b30ff6baff6964d0f41fddd6719ff4f13387a89acaa62e3bd2b501dcb0681bd3c08d9b6682e044dd30bd25086191c2e184a5780279fa69a79f550d773bdfad65b31b7520749a0a2362c3347c0263a13313f7dcb9ed079786e8a503e678fb740aebd8a8f0995b8ef1f87ea9e83e3a459167a7ee260d52e6f0ab940ea8f018fa2c052bb5ae444fb5844dcb914426750fe05e99e71566c9e44f0cd906bb2c20c508e1bea70ea03310b53a87dfab6884530f76b64390954ac9512788013a876cf8fccedd160493c05ef77474050f19570b732fc23c14573f9ed628d00a4abec2fc43ca826b7a77e40e4bc38af18d04c1fbc695465923526cf047947c016901b45f6cae865346f580da8fba6d38731d95155e111f0f5ab4b18377056d00289a8d9a00fe70082e1e7dbeff8b8e5c8827b30a8dab4a2f93ce7526dac5950e9303a08e6c200cd95b25758e5cb4caa5dc3d3ea8814a06338e8e753d6847a10b41810df0afdfe1b4564b148867ae98dc136b0bf3d6e7ce78b59e38e885d3c6001de7186f6024b5d1df8a5798af652345e84d99540c7c03425aa59add7b10560b2466bdca353f3148eac51f0f020223d1241091426709afbe8681cc9a378c9c0f54648c49751971e97294f14d4b80075a2876911b80b373a1f181e9113f2fff038c893ada1cee7b7d1910f1701374aa255e5d991cccfd3b6c3936495fb37b7201935d6a83487b882e62198ee84a75fe9f6ad09086d998b0f2dd72067365db8c096030cfde05b6243df956207ba3f41dd20b518d16ebe94e17248df8d6ed3654069861e13c4da96cc3d96d67d609e01bfa42c7c2bdc6106b918ef7190f20cc730592bd1fcf0a338df807152712c4f88695d202de2c132c4d00696a6f6113bbf1090d3b9cdb98cce551dd3780e259c9be821b0d71defb7f5ca9747372f589257807a18fd5cda88586cf49ecc6a019293cfb04e7d542106c74c79791d3cc763a660539cb649c4cfc8593bf95e131609cdcb3b51dba3022d429949d3ef92112b9c709e815a19337ebad3156fb2fc0d93bb4f2042a012da19b7c6baef7b6fcfc6ef7050a0c56c816b314472a28c30739fe5f5c34b3199b316a34625ec2a916278122085b4a5901e753908c60fad34fd5309d2897d942063d748d73c2c34fbbe3cc5f0f562af9a32ff51222487ad1a63c6e1094f459e648ae2ded85c8cccbfe8f301d0a9c9c2bb1b3d99c2f48bb4b0c35848f4bc1835cd5df5343b17b65eb51dd47c2018fe1ec2f4dec7ce976bee8a5f10a0d41669c773ae5f01d503b8118fff4a0b90fcd4e610588fc781edae15c8339b8889e2df6ebf78ecd3a8d4677043a69a2fd017a083507c67396cd1fdd8630408d71c16db0254b5ce5714e141ab8b4652d34087e5a2a1fb9be9688e1bed67e2bfb38c9ae4fe14b394daeefb790625c7a5b7103845bdec58e32783ab54ae7d1890e1c01fc7d0ec9062441d7bd9249dd53dcd102e9f19db13d5019e20271d38b2b9ce8b57d321722a6c6a986233937ed4d82ef0a0589077a5ce9980c4c5f64e5f8886f6744ef0392cdf81c89e5e14d4ba81f950001200a976bdd964481ffdc47e0e5a28a931c95b5d8734df7f93c3875c57c44058974d666a4f3077e13103b52b3228670b8149c4a0e44d07809e35342d126960863c3afe8e2dd5fb7940c235e5bf535cbcf1cdc6facf0d37de514ca07c4f6b80ad57e57cf80499db6ac9d0abc5c3b282a0bcc65f642ab02358f12dcd0f89a11093e808f6470ae209d9bdf9f3e1c5246d9669383183cc94e8f7d339d48adc7ea08b428bc89d26cfec99921488bce8eed207d9856f1cefa9ba69ec9316d04fff50e4a297db97f966152fdf849724e979a529e2fcc98acb39434bdf16059095133003f05ff953c3128d2157134f539f4c68e61a09d60a0b188f28e05acb6b5b22c071f9c54958c3ef46c281ca99ed65c7ad6fd4304b8a2d927bc1e0cb4c82208a204fdea679cb68cbc95382598358b4e8036ad186ea9db67285f590d6acebf3c910fc3acfdf8dc27a6360b3c095f6bbb14e77c593f834d237f45725477ce97177f0c61aacffcb65509e3d5a2cf96c17df6c53938a51efbca665c4b0cc9383ead280f2384427a134de05aff0df35a3fdef397e84d4f9c46de86b1282c24523b6cdf0e0db46e5b33160606f2f1d06a20076ec5020701705110f9193dca35e480a91d0389b3da164d94668702a5db7fb9fb11960da05f77d112278747ec9dd7dc725c0deb8808ed2a1dc37c24ee6dda732fb9a57cded01dbdb174522cc8f48637ecda09fd23953c1ab7f7cbc47ce6dc66806f14dc8ad6db2e44a0cf7522f51a8b8771022e80cc3188012f3d388ae648b47756970d7e74c1aeb1350e1abe2c876fc915025368a506ba5dbbf56ab8a019d6b63fd03b4a526e475cb0cb0aabbfd2348fd30e2280bf99e868d2220bd936f954037adcb6d93ad2e6578d24872db2afbf25b40aff7e03d45003dea6bfd76767aa4cb287b5d8b8dc0571d7aea2c9be170aa7f8096338f26eecd554b123e6334887034dbd86523c6ae1db1458f13d152d6d066a0be1a6add88ad6a2d7e02fdcfde77392735e686ea8b198059b5e364d72204db70aac27b4f6239537699bc716c988a8e0efc0cdf883b967aa84592093c2e3c96a0373d1525cbd7f3aacc02908e0a5151aaf6629f0b639e4fdb44e9e6ff5932e0b003c3d2a13e09a13f77e4a8dd49e5d518f72ea69bbf7491bd7a25ce27d896df608ac898387dc5f4236173f4caeff65954f6bfbc90ca1224c1e7ea2b41e7f3eb20547fccb087c7295adc740881090273371979a2202250f8615bc4b843b629be90413cbeca3532b7e02db4baa9c8cb2ff62b7a8f17c96da0de8a96135b01313740758a0e52e1d12b4e077f3307b8be96239df0628b3c47e152bb986d2e228de4502f761e22a2b74f011c8040f55b56728e508a5c0d4fc8946492f8152d9d88ae6049d45559752987c257bb38c8443b460864b0d6addd11839b5c0bd84c1862c630f37ba19ce48482fb55387611ead9e83cc89555dd188c0357e48ffab30287204085f0a81d9fe7d661ecdfddf37f19c1d2f2f4343fb6e8bfb3739e96cb92c4ae40ab8896b390e8a3f5b936508206799d96483423d2bacdc2cc6af73e8baed1fae0d6769886aa370f610f38b028746887caae32598b41c800571f1994bf3b490ff018655235dd40585dedb9aea2611949f8680c75bc2f5a27ccb162a95a68e95ae0f788361ef0e67e927db71a2bc083eb94d6fa3064bb287b6197a725197cee0f502382c3a1e9ea372d0416185dcfdde027d512c796f25114e5d216aedaf0d41400b4e9ae7f7c97b68e53871cc90130749bc38646d9a031cead7bbed1706d1abd606b9389d13c1895910e520e86fa5bc8a37bc60b92181fb5e83324029eeda6aca0647e812c5e3688ac421cc919126a2324b345049418769507170d324cf131c5d05ee76cfd78cd9265eea08eb6883303ee6b87fcd92e6ea4fe197ab05f74d7f0e0f87ac1bc6c2f7856e493e3dfb28b57e60ba62a7fb3e9a779cc34e3ceeadbf9304ec7c441b6a5c3cf2a51b45c80b4b4d39c7f76d74f3c39dab5514cfb5eb562405747ea911ca5a0243b6b0df4deb8cd31d0c268267ddb82b25029fa52c9cd32905bb531375a95b2987f5ea4e6c82db0205fb74ec3801ee725a5869829fe5abaf0caa5412a2fba581aebd07ac193bce1be8a6ecdc06ce7fc1d53005ddb72c7ff0048a8214009150d6e364cf07243016bd5fd7236c179011af2c29f09b5cb2abbd0738c4d84430f1f330c16d09653d88c396bbdad126ffcad281eb210821baa4de063fb32f803cd07afcce7f83227b3556276d113d6b4c0aa41b06d766334524d805726132fa59e479aa3fca261fb1b0dbf7bac6d3040a8cae36a50628daa91e940a6a8730b5ebcbb8b384f5ca886e9ca9767c567be0bb3bb6049c0f8b4b95ef8c031c80add827b75e22373a80161ed441ebccefb66d1b023a7a6cbfec90f9c96b0a5a2d5b1dba2b308816f2906073cc5cb9c3244306c728afdf17f3a6269e8a540d69f8a60aa4c2f62368a5cd7cb9d9d44b6a8e1e9910f53f8cfc49df4a4c26920ea41b4f0f862a909d6bab09abb805c11444f56d4faa59d53bbc747e4c06ed6e075efc463e802fb9e6e74784086c0fd8796ba99f30ac047cf418f40056862b9b0ef7f31f409e03731f97a72b1c0fc7a438d8baf79f8d0e837ef6a47de55e2dc10ab691298735030640e91277a872bad7a760454ec7a8f8cb5b6b6dec410468a30d9cd3c5ebe00ddcec846681133a97950893bf4034145fb79b5cae017e643b5d046c24f40ec49c9d3271d9a9047b477954955065bdf3a4c0690cbdb5c79d6a6f087c8ac80e88876e8dd21af696a0a625e6c8367bcdfa66acfecfb352a2fc926403a5278e77c75781da2cd38525b339a255dbce80e4ff72215333e5f72969593501a2f0cea5a24458ffd04ae63c5e60331a5f49bac3bc404acfc065b26afe8d9a08b3bec0d08b594ba2bf8a984540cd1d073236fffef040711a7d8360e59e5e7e0b1a6216fbc82a015fca730ba100fc9fbaa9c19970378d8735769d644dcc19450d19601d5a90783afd8787e13c78d39499e1f2aba14b0b89935613049242956507a3b2146549e776d9f9ac61f0024d4e0dfa14618030d758c2edbbc618c9ca8b0ebb121a9e5bad7410f82a49f4cb8b7c6fb14edb276453318703f5253d595dbe0c181ec17dd0cb73381342ca4cb4d5f81e0721f7d2d1e44539b04b1ccabeffc90e91620d25d659b1addcdbef9a851b0057b0552fdda4bc0193e86bf409ce65a10a310a9d68ddbfe3fc33b95394823e74af06880920ffa47b3457669368089be10bc7db22c5f64025c24fbfacec410d6db94bf0e20f6cde7e593d33ca980ac2ad07c0098f7479cd461f3de966a6fb63907a705f3828030a1a37714001eb4b68420a3c032988b60b4967bbd86906397734af2a9f1acf28e6415fc855278904fc0e08e272f2f150e42082e9d9c64af3df5376aee6c4e9c65f01c6f67c1fdcf7515f035995db08f465bac830f57e8768d0d504f713f26488087e1b4f4d83bb4a959a036e5377118a3029df6a8aad18d79915da351166bce1626ad3b70fb103d7187b0040f36a7cd387c2cbf75ca42e1f3753cd914b9b17a2d7468bfe6cdc26556a5e08bb0169076e6bd98244d58a87472540a28c8e3624b71335c02c08381049140e07e7064668a6f7250cba79241beae7bf761b6fc6620353a6de8f827b75b2f92e0ccbe815f1c48d41fd29dd3e1f57275bbdb06275c7255fda1db2da004ac6afc70b43aba531b3d40e8172eee3c3af0cfed3d0b3a4d4e7da00d5fe4679d37ad38908ba924197b8d3dc5036178151ceca051283187965f381e7fe2ec8a14fdfa53300ee5d983eff36b87ffbe125b87e9c16df9012c147b6a58e2e395a182159c3da04bddcb5df1231ec7f3638ee1412e3d06859f55abb79af3b0e760fff6805d2b30f6901838ba2166f9ae285d296e5313a36b9739901d682345c2933ef7eacbf80069490d86f9f5a4f44f7e73a2c7d0a1e486f56bec7d1fd67475bba6c1f0a5813089cef1f2de4f3ab7924ddd0e730b48101ba69240ff0a99ed04bc1a999c8dc1d0b117883381cac06ab840ba890c65aa93103aa29045aee55e393d3084f42b14201353194b6e05a91a886c22292d11199b82e1bbf3e30b329b2e03e544df0e92b0ca3c203f3675ce8197900f960d0d1c23f547b88d3a8ecb9022355609239c56d04fe8ba00b10bd656a62b56509f26ec99769515f9c58864c483b33149890c27504fc7e041da197e7065a40e938bbacb8e98dc180daab05ea379904536bff5cf409145e2a06de08b3701ce310bd2a90af0befd4fbdcf9f9ed1218bab1d2f7971a0c2956d4e98415bd16f3ce7c2a92aba3098d8793e174db9603eac09cd22c2704061159aed9f3d9a2be8f00d73d8e73691fdec4fdb875b4be159b378494dbc10405c3421ada30693f88ab3ae0d34a9e8ddc4f6bbacb564aa0d8886bdce425c9560cf6be7d4028238ee8608efd4b5c3443b8bca5cc897f6ea173e1cee38de66b02020d2882379f321af12062f9b21c022cf0b32a94ed95236deba98f1946ad4b260ff13710590fde31f571e3863dd71dbe6adfddf81aecb8781ea482466ec30997010bf656cc40d44509840be524f976965f1f5a84a9e71ca305c4d33737c7702d0067362b7b1c25d23d50eb211c94a5745f941ad46ff21803261b8150236de0b60367f00942be190e9b6d5120b8498820b5c464947596a30d691586baca77adab0ac1c342e42fcb0dcc28bea9fb9235bfbcbc210da8d424e25b3022b8feb70dcb0223e6965a516bd68002b0efa7c81f3d06d83b9249c9db8e79122d7ea899a5a20a4bbae76c694bf2680e31ceee22f19bf82ee098d5a52f5870380e7373ad395501fb9a422857d1fa766ed2332be2a69c9d8aed47d6137193409e2c83308bd48d054ff0de9fd763701e6159ff7a315f3050ebde11692dd4d64e901569ef2c68680b0a02f78e5f65cb748d0b75d533837feebe3dedb8f4263871abbfa2bef3ba1105708c0e4757badde88f56f5ddca7db74d7738045b95a6795ee7a31cea52340b0aa8a62fb37cd0260fb5ed73a45ecf4fc6f10749cde7e52d50ecbdc69eb6005a003685180b2ec910ae26216e2c0a1e96a4fe69a19d6db41847fcfab992532d5c0dc233f5ee18756651209ef425e2acf995dd44390acbea1a23ba52e0a540650e0a041ccf345ef07c4fb5d78888cf248e758be46d3ec90d0a69ab3af5d85fe91e054370a75edc76c5b20bdaef3a4ed654356c9d01f5c9fd53e30f7404f5f9d5d706a699b87e59b6e524c88e62fb4d28753ca6c53b96813a1fab2890c10da873e30eca4fa370c22a8acf94d004d78add522c4c462aec16d5c8488f39cfed78b8bf0715d40f78cb86c849ce67c80e851b4d621d0241c0fc33b8b7b976f139ac4a6206d8ac43f84c33ec00bbec205a7742e8098bce09f542f116b9da3bd36347d6e60a8745cf842d82ad31b0cf60153777615ffc03708612186b0edefa9f1e4c877a0f18cfa7e9899cf5f70670a9474f6b1eb19cc5adf6b30297530408ac61ee3f48073cfd1f878da326a384b563ee5beeff0af89be348310f6e1b81f1e8b972eb6401969730d4acf9a806bfe10b040389a7cd994de800be734a27dd691d7194d1040de3f0260119c21e8a8f764944bf95987ca37c20fe7956d483a45f3a4dfeb1be00b2387d40f2f20032e805f8e52e8647bcb5127c012e7cc037c2c906641ce74709c30b0d00a68c6ea654e56f2a348ee3380cb709ccf20a299295fee486df40e5096569eaa86d7c7d0223deed5b9bc94763ba679f8a0d7329bb5b3fdf0aa660360de7901d2957944038147802fd36b1c5f0b24eb07dc4d208bf4ffde380953f5c07a7eccad3f39c4e1911b5ed640745e71f052c712c6ddb401fd8ebefc9a3aaf408759a209970780cf39c62312c8690bd77cbbc95b87f3fffbbdb3c1f95efcc150a9dcd37d73af6bf1ec4328e63f5ba6c52e3f2da253f96608f0531ed366ff5290d58e2c24bf594ca78f0e791f20172aaaa838f61b22dfaa332f36e18767b018f06f34b1ac8ce7ba882e996d6086c3a264e636ad16721e8f008b5b19f06a2de3e0abad7dc659d340d8e36c2fc68097e99e994255589db459cb17c361ffc303d420eac111e8d1601d6bed243a4d2db89fd5cf3883308181b3f0b3f07a5489544ce06a27647744548a2f25e27ec1651de0e962a00812039b5c6fedf998076f57a880e9519651dbfd803d4d723e17b7040c05101e3b69421dba0f7ee6589ae8a696d071aad4a8faeb258be7ec6c456ca96944c502b8ffd6a97e421599e8f94d5780904d8871304f8835e74c2480892b54e9f8e237efa1dcdbf4f1fb8ac81f3dcc25c0219efbd2fd1ef67b23c7da232b5bf2bd681686005bec01b283efbfd524198570d62e58e9f8e39d383e0caf88ea81b1566ea75ddcbbccd90adcfb8ed63a9b40c0c8bfcf34a3f194081585d90f35a79082bed4ea74f739650349ddb49595a980d01a74df4f85ca9bc47401bac53dca8548ebc97207663fb0c5fa62dfe948b98a10a56e78f138c5d07c13b6a7252058b3209b4f178e010dbc39e62caea46f49dcd0fb53eed92d2f554c26e7362a6b1d8ddbf0e121639b9eee14b202e485a2ac3e209e90581243dae633c655743ccdfb9c34ce1e901a30d9095097caf2bcb475ad301efdc4540e55f7bc810a02aec6d3948dae0b760237999476f2a272afc1fafd0046fddf000e67a2d3efca78ac096e9dbf05acd314e099c9382ed9d1592c2335708ee198a353e639a57ed639bc33dce4c0646ab8d3541eba898856738ef00411e09370a0423451a64bf09004a8b5cba32f7d94fff9eeeffe91df31a5728da88ab0b581c7dac573d08ff551501f7c975527e58bb7be29a9f459343dd05c29773ea08732a6da07be781d0cf8d6549cce95647f8fc977872f541415ad6d442a01c360eac8345d49b0278b83bc4fe3563632992e4538092c28ecb22d0606acbf07f20027362375eb2ddb9cd367b77fb6f909f4998fec5911fe39bc7b28f6c2a6e56a701dbc21dae903e89b9d12656f1dff6f1f67416223012ec32878b8c680d69017a048117a926c571cc9406ba3c9787891809437736ffbf1d29c6463d00e458e1c60f89e1b9498d1321c2dfa55c63822499e4cd4529a033f382da6580fa8818b79d08e49ae3eace2cde08fa76fe0a496750c89dc682c278062f597bc618ee6b079204551a3e33a5023076ab12fdaee5da6db11d3eac4df762d8f7c752f4b3d3439d03de70f5d58193b9e343d4413d45ed52fb06d22408411c4eb2b77134376e444e0c8e93087b2cb4788c3fb6ba616a82c910bef9dd3a1c953946b8a8bc07f876410e69ba45634dc5334ca1bd8ed1461254c134d03d2b3f79201810ebf0e2baaf730e3aa6ae820b6e2707b84d7bd150809b3b17d9848111facad44822750b39d0c9006cd6a570ed1243d09600cd85f745be9713e3dc6abc45a28461b3e66afd88c20a8b7a5740185cd455bb201f6f6f9335bb0ace02ddb89b409d5268ef929ce63702324c558ed020218018ea3d28ea64f69d5ad843f3edd19924066d271d6e44e10d67e20711496f92d51d9cba8837df6255170de993ae0b3278c70c520cd4246606f04de5444492e23ffba975cd4aaea44f6c1b2e3e6051e7e62485fdbc68515205a9645802b9bd82839085424b0ee46a8878b1f402849f56e6b9bedf2415fa3c0c0829d07b65cc44a6610a0da42d3e1920754ce696e8644af377ce57489c2cda081356c1b8629a9488a208bc0811b0bdf79d5ce0977995ba728e759ce8fe84830cf7b996258b07fd6de1403f3168baf815b3a189f6d83034f3866f6e7d3bc20503c4400620c75d9164efa7b721016f8cc101252b879e630eeef8554ab186ce550af6075198fe8fc899cafd03786ea7c490f57b44469598c1f5d137d767855a0607cc99afaf6e203542bfcf48b1fd7d8cea2f183f6ee47213067efe336c9017170c2b25b21554710c31a2bc76dc3780a036c1c1c6e05ef351e29133cb3d1428f808301b50b062bf0a34fc525fe7736dfe2711969650fe2910704d9ea74e9955700756ee0193549b09764a1d17ff01035094300590b48e2b461582fcb97f89e3b9088380d720e4b762a8f54184abe5558e2ed8f2291a0399147202ca852dbed31e0bffb652976cac42df3a41bb80a9205b8d7531ef91117661012aebc21422a4c007c14dc4a0a14043d3c9bc2ba41883ba53a5fc0a4f7cf95a9df9cd54752710f7095f2f4ac4b6e3f855a08603f1d75c412918d7f3dc155b3936dd137a6d266f20093a02241cabbbb78818a1af24075ee409c2dc7790ef7d0448c05ef964daa8f40780404c0b6f4fc1a46c3420ff2ba8970d365a3dc6986b5af4d33c57e2a78a970109ca32d1ed14f99c1cc87a15a323e6f2341f4720360681bf9da6d932f2d77f01a56f946d5256e4219baa0434f1a2a26824d3d21b105b6ecb1ae32a50eeca2708dc6f5064eec90df5a4e586a2ed0e56189aaab152bc823c881e7baf3a8dbd9105cad4538e70d403db8fd633067ff869d5439f9ce186fe5a6ae5d4161e22e5050f00f1eaee484f60428731b9df5f0585becea0fcd1101e50a0dfb20d64f47bc506a42c7e512784f414a8c93ee1bb4db9217d7bc60a263429935cd8d78615973603d8c90911c72f85b2b0db4212df4136e56e6929b75464e0485de93f5955b59509fbe6a66ef75d35f7f5a48205e743cb7df54ea681f6b3555323562a0b2be17d028e4d43bf6d5cd4107b9cf3368da9f7b9ef75d27a2bcaefacf45ffa53f4cf0208fa1e45ea0151fecb0ca5ae78123bbc374c120524ba487b08515016a49323130210ac4777678f6a757533e55644462cb9d2c371c032cdeb5df1b3ff03bf2c5f07a64843da23bae5931a77a306f816d7a0034e06ff77b1bf3b4bcccb40819e860e1d6866df65c00006257a80c8e366a827658f9cd4531c51f51b92845a5d41ee06bf0cc8a7b41a93ab19ba40f6a24af1642f297b222ff5c0ba7d53658a62322006e187298e0fb1107ca216ca491a0c8d9201b00384c08a9932711bf5b082b3c40defaf5eed1dc613b70ee379cb9db6efafe068e4691c950bb5bcc4bff4929aa70e8b51aef378bbdb8c91c6ddfd366c9c2dc1d002c2efe1b275b8032167dfd1a606fa30af25f40f655c5c5c256ee850acb325952ce59fbd71c8e63ab81dfd89b301649bb53e38f01bcd2c9d2cd2bb7b6f8e1c3f590ca020e0093d49da2abf4af70212047b62352183e196df1083a1c5b164bb7f0ba00ec4a6b7f1e7ded07c6dea09ec2b6172ab6c3f0f8f79ec8583ecadd38c54e0f9eed122f4daa1294698ca7d0a1669b616f2d2bcafdeb73117ca1cfb9c40e8b32cbbce61e7f1cb478ec2aa570a8387c3bf9ce73315dc907b9134b4c2a842799d0cc9e54405d7a42db32a64f00322129969e226463e13f1ff4a7b055d12c718e1b6c67d1afd8a3d2be623b7e403762f4c890ff6e40fe71a6bfdcdf9301fa4de66733429bf135e9c0697bf507106b1278afbd8f4576bc6ea5dfdf9789890501a0c392b578632983f6b1c7a67fa08b1e13a6000c576f8f4c549b5308ed1f3123c22eb1edc9d2ab13942e86e9b6f058899a673624eee13326330126b7cf121c35951dafaea8444af2f547c91a2b2076ea0a791ff0c7718aaad3e759266825d9efa222b9d5684baf9b51f1c015c4e0248f28d1b309097b09d0929c5580b108319274819b6db42953ebb07b9b7c1530509502f194b66f34a982bea46e37619ebced90ff09ddd23ce0511f20cef02120edba8bb7aa844199b034bf02475e022902e18029789ff4e15e880b55b9ced560a824bfa6e7ad37f5102ffa70022b2bb061fd6aea7f038f8d01c9384097109b50bdb3fd5a3a0e1ccfbc7429a3e1d9ee8b07db2af1b0aad79d8f1f8fe675bf14e079f0330f116655f14a2c2c3572a69f4ea3ac8e7750c91501e435d059aee3ebe07e2fe3661bf5186b7c4c5bc0dad0954f17514a8de8a4bd022511d89c645e2170906c347ae4e4fc77e40c73786bc1ca49f6c37185f4b18c98296712a248c23c909becb1a4251b343b5f5804ef4643bc442d96246244b3a5e39edaf929f9675df03456d8f0dd9124656fa8615ba5d679e6423a4a5adde1b2836434c65591b6bc20bc3c002559725125416492b2d937cdd895eb4eab2eba576e3a996de79dffbb10cf6c48562c604c78388d135c88f856721dfe5448a4c88d6727d973ba577418000a3a9c7a260276daa1ec7514d7cbe7d47aea92ecf4ac014e3828f86cc2080de089babded2773d64dbfb5043b5ac220e37d3aa6401324f107a29a1ab5e919b2b078a5f31b00e931d9f6bf5ee96a5df1064c5d96291da01dbbb135bdec9a9897f09ee1c2d98fcb2df112fe3cc53c7679215cc0b937cef825b5bf9ba2823f673030d7a7e86ab41c616d58ddcf22c58ba5f58948d745ed31b6f92d8eb2d31e95adc0a66b5df50fa836da39787433f70ff7de475c6cb36db478cebef0f2ef8873bfd0208e3db699097ae772ed80958d43c17428c2a09602dd260670a7e57a8d9774006f3cbd405764d7a9d33017dd7dc41503a90cc6ff984263b7aa5ad8a7ff7d8400e31cdec158c95ca6a389e4cdab231510a76160514c24ba73d7cb65a5ca1c57d0481471330e55c072406520c26c22c8f7aea87b8303e1a417181dfbaf1cb4ca10c8776e513a6e4412c3c21032e9d6e43e77b41f4a8835ec5b0093bc84f4df5140b0d7f02e6de0072d7ce8f8935279cec4a40e365d296f838ae92cabc6004234b0e2a5a38a8a2ebedf1d6f61161f0bcfb875ac3dc2a11a29c71a6af852b863f3a0e19e3e15f2182a31d68e8e194f42ed97b870eebc6ed86eb4a7520615a23fda302f4d7d756ca6c22494029dbf44312a860106cbda5c88a737aabaa359b51ff9f0d86616e89f1e292fe3a3dc27c47d717e68617e083c262fa3b697c07d04806730b4a966a6e57618e33f278364d919a5ce60a8f174e0321802e07938601ac3f070f948accde198526df578b916c2e1e02bc562128818c70f5d48e077b5171057c077f4b36854b01bbb63430635b5aaefbb06461449af9c4bc5bec48b708effb3a007a1c02d16b40dcb20b11e166381efe6dfcce5cda786354d66a6ec9bae8c58e0f7955b6fb065662ef797e961afa00538259a737d32671e5b34d85e9c3a748fc047cfb99874fd6e6c82a5b9272cf2cf29c7e05750da17819c0cb37e8ba7c00f50b14f1302cb747858b197026b77309c2bc88b0dad05693ee76551abee1e6d1c709578ff4a26e5689d8e9a7fb03d7dc0409b205196061b2edd08a6ce6e73774b40200098dc823f5c393d9183f751fc71b3aef4a6bb2bebe5f54345f7de75e39c8096c12bd7e7ac994a4cbd70903d54c817bf758cbc5a00861d60ab1432873ab7c0c957249d43dca6ee291143297e28db4ce7aae348458b9268d8208ecee87999d0df0eaee097736bc5aad5c7915afd956b439ddd4548b11cc2530955e5cd9af2505b36017c712c32b7e6d9cf74daf01bfdbcd85f06c949ac1979609c7a427c9160a35090f7a102bbc8057f85c8bd21acf0d688c45a95f886f066745944cc6f67b010de33898ffc94e879db9f2162c564acde3089fcef5d446f004d23ad0f116310481bd07fdc4f06bf0ef0636d6d64755825c35246c6719de4a4b0abcccb088410fb18af86edaa62f20856211b700ee1708f2d65dbfd2cfd6ca995ee5c108c5740c36b92d8e65b4959008b7a726e0d9aca1acd7a6f5e7c543061eda54c4beed3306a39b9cb892025d99ba58a8fad99dedc462ece235b74b8d1f90cad933e8f4260994b6b5146c97887dd30ecf0618d8cdf40f30a05b4043bf5412fc56336e34250f7346743d52ef21865344c531731bb9fa25993567171d56f453edac0a2af25003a08e35eebbd71d6bc371df17ad61918a0ad6ff7586909a4986a818d3adc0a30f478b0f261a7f0276d35a93106a7cabbe33680e71e92f3baa6f8ada72234c860dab3d4f698d02723ed8ddb0bb6dc43da792fdc70802652ac1137bb651879e560b51ea5156cc57a6e8390e1fe5f1ddebb858ac12d67518af739d17bbea1492c80246ebca7dbd471690e9d9eb4f0d7693899923aab1731184e127f819bfe65a6e022f1aff8e5f0f3a9ea9aab568e6bc0a0bc009e7d1a358f6d6c13e50b7a78532037f9958900545259239ed40383365dd0ec19b422a18009f1d6ffc260a129a7b09781f054f4701b19241340cff7033c00605b12e7c831443274dd25c4608e17501731c9001cdc97f378cf9e49c9f064735639e9e7cfea635e953b728f4ad77c20ab387ec5510beedca6fe2ddbd0f830b84ef360b683fc0423c8d660b477977a808ed31c3b980bdea7897c7b53161db0efe895beb770bfa603a9470f8b90169f40e6dd4dd9bb2485e166dd18f5df7d73d938bdcea271321c32660db40053485ba0bd598192e3dd41dee39252cb89c5a3e09e2721d9be1d11b5a1cf63d3cea1eed0088e9664de8f95d2ecb59162473cf3e3a72331038a307f13a563ede0bc13d0e023a680e9111151d5327e902b2ae9349dd1f92aca2ea562a92ac857c6fb875f40624ec08548a7397df8ec1de57daf97037c37aba167f663b81528c91ffbab9ec0922452216c801cda812daac6f354527241d573122cd856fe597d46e8941b23702abf12c53f4bce240553016f1c782cbdf505fe8520b924f6d7574394b3bdc3b0734ca8ddd85183cdfeae42b60b4d8fe54303ee2d369c6d1faf539c194dc2bfe0652ca395f7b8b8d6493d5efa117e990d47368f417cbb219dcbf5e8ded6e252c0bbc4d25485705136d017dcd54da69832a2eeba5c9b95cdd24a2faae543d9b48097bfc26598dc19a44410c9fc550c81475d0aad3dd3b57046a7b8e4a1664493605854b091280acfdf0ea45dade294e843afc1eab373c45d44a2a7e8cf50273c008d270fb42a8c85e99cc7c04c631f5f784582b27b0e500bad48f6faf9173caea033ddf2269e6d08b9e228279bf77ce7ee597e838abf73fd5d4f30b67215f9fc406816d76174974ad7d9079cd22ade3b8f8999084d7e5cf088e4f2e699ffbd11704a8f610318e7ca6dcf4caa241a6650f9146d13a7440405682d2422a9c7c03de04f38692e460096e2770c20967b2075b4adba508cd872128acb869d12528b91b0752965cd9a8756c5c994bd2759695eade0745b9fe16bb3470ebe68687a8bd49062a78f0bf36e46c99205374a21cde0fe9c1d1613354546e4a9aa9c0fd9e03b30f8888fd33152a35693d5c8e1a9f87587885058b1c8b02934baba31d06cb62720263bee8d91f98e2cf5daeaa95cf572024ea9ee551083c88bd5dd7cb26b3b52403bd17043722db40515a966dd2bff59698ae17a92b35e12b8df651d6801bd28d0d242718a2915569874fa517abbd2ac08098fa3f17484c146a8b2fd5972ae9e50e7631612788326ebf00a7e523b72e02b570e7b2c1bd01878fd2705760c4b3e902614f0d004943ed7a36d9cf58224e8ac2c3783cd4db22674815af9d0eac2a860f398dbdb8037e3df5c43830998287e5393bac6cbdb852087934725dbabbc931034dde1d50549434ee6b3ef41770f67fba6313b970155a8a8f58c474136e896f005ccfb28127af4ccf76a42190e2f4a30c891bf29a42263f265728b7a6523d6b0f6c7bbdf1a9a3bdf7a3c252c9b591060399aec1598fed9dfdfb6581e37b72990f589162219d1a5d8acf4ea8ff42b168e3919cee23ca365a6f5060c2fabf75240b7dae95b17b4b3dd58e91aa05ebf1da0d99ad5b9813278d3b9e3caf40288daa0d34302f040ac7db9f659e13593661ff7568218f60c26cf00c36b979743ecd2803cbb9bcc007cb4042dba333f23db423c0f31e1f3e5ad34a6041fc4a0b6bb2110c9e76530befb7bce295cd79d3226314fc148aec202da8d7992d6c058f6fc4d90ba411f5ef862e9127ddf48c42c27464d5aac0aaabd127f774f218111a8c308902ca0c0f4f7e2006097bc189fa3b6fcb4b7c75cdb7910c9d72af30cb034a7ed2076b223716865f71d2a54c362ed2086ec2ddbdfe8953467daccbcc9337d9e42c00d63252c8be531070b638b5d2ff2ae2fd307d481d7b679c14bc1f862f26ecb302c56620df8ed8b24c031f8806918b2e5dc83f82f2bc8604d62039219e527b4f0bafea9ab8f880bc36aaff06649fdbe1a84baa029362bf6112d69022c3bb4a40045f2cc48aeb932ea562742eef2ff63a5a8213c365acde7e59db54f48c6dc0c50cbd04c187e68661400719187095e8ebf509c8caf823a9d0cc932fc267025bf4071488645280c04ff840361366fe3110f0a765b03306ca84a51a30cfa0f722fe0b661002a6e210783b9cb4929466ec6f72749137f4b88b6952943228e4ba7e75007e6d472952dc010460c52fd0ef1c5909cd625733f6495fc3c2a99441aad4e90fb78c88850708079e1b8467efe3f38791e3e6e494e7b7d52fb6b0c6f89859e70bec7621d076e3849a527b5faf963f1e19cd3a53e6a5b0f1d03e8ddba6f08cce056f14b474ebef3e7473ebea0b078a4481679669b54da1c15ad1245df986857404a73c2e8ac84408272110efdeca8aa91c394ee911535228eb9d2ebae9cf2baf0ce19baa2b708c009bb8beacc220cd91e2848da73cf6debc8714572e76063b05020f72e4eb4e9a991b8d0a1ecb30955e4342e026910ac49c4885ba75039e01400f5b9e012af76691e0dfd584e14e2f534e209877bebffda30f66948713f2516a0f5cbb65c96db3481cfa7eb35f9170d068d81129a24b82cda3c4c04ce76a3195067bb653df0c40741cdb45b76e33d842061b64c4141416f5af7e78f391fe90e402a864419bb8a128afd13c2eb82b4d303cfe7931e7acbfcb60cd88141c08c2bc047481cd80a1209a2aff8cecc9ce26e1f51509b2af8c54b9f6322553d36317ff0f270c0f4675aed8064f88b5b40636ec95090c32605adb0f1a0d67b951f16f0f06db419d6dcdadfd0284d080623ed5cb70038086dfafe87278683f3b92ffbfc1094567ef31d92ee9ad621052bab4cb36b3e7abc242b844d391aa06832973d5d10b3be7e386257c2d98d5b838af5d8a9decfc07c2b46bdc8beb4d4972f69b8140013a589f32386732af2917d8e367b18f3ddf73722727b72e927ba2fb74c4bd3d0bdb36a7d302f6f2cc1b849d36bc1291c1deb3a68c51fce69f8bc1a87e6192ba01af34971c4c031c662a2c6d4552d1ff849b6abd49d0272dd1367844ad73994203d1946e548e369f6c6f5258a117c8a6ace7cc5c2474ab80b33f6508e16d42b00d -generate_ring_signature 511e40c694c62adccd1cd78dc759ad6f7e6dfc6f65c233300edd092548e6837b 1f100b5863c7a8cecbca53896f81bfb37129724d1ac0482da5e3c041ff57c7dc 1 25fe770727b3555d648a78a3e962b1bf25f9733c0fffed8837ced7e2b3214a07 805b31538ebb4de57afbd5abba894511ef846fa6c94906865803092d7302fe0a 0 959d747113240dad99f5ba2b9b2734587e1af86df7006b417f6a719fafec2c0a3b20635db2190709f935f5fd6f6e5b7d7031d81cad4af84a16b2fd8e13d4a000 -generate_ring_signature fd1acd2eea26d5ea5f10a0b1e26b68e4e89fb9760cb610bcee9a0e6903a25904 984b195e9d1b1019e51a1a00ef3fead39de4a03464838690084b5b1f5b49eb4a 26 bed2706f07b60e6e4ffa986002009646f5ea5fabd1b164bab9644b690893d9e6 a4fb36914b96a15fd407598ec221d6d6a06bad7c21bfd0079e91db6b64048f91 ac5d1a9778bcb740b0a04211516231df150d714a929520183c6dd54153b07eb0 c82a344033f5709ae3398a87d909ae637b24c0b355d25b76a04fd436c0c01488 56bfdeae80cd043158fd30b06ebc4605b4dcafcdf90db2982f1cfeb7e5494ddb f6d0da924cabf77083bc07058088dd8c4074e33c1839d7137b59cd665ed18637 d4897cf986fc87998d75784803bf73a1e9854612b9cabb0d5a91754a9587c83a d0261ce00fb5edefe2cfc4b2f1152a5802e64bd8bed7ca4d5ce7ae8e6be671ad d5d7d51abe48bb01095b73590a322c95d0c2d8aac5a30cd9c071d42fd222bca9 f6fdb08161059d27e267b29730e633e405365951a79a9af34e64b2831510bc5a 5dc9b05fb96aff4ba4d6589ad93d086044a0e6483528706bd65550ed154657e6 a7766d3acd6e9abc9c2925c3d1060214894f6b084d42907bcd8ce486a100348c d681d22b74d9caab9d5f8a39c2072a899fe687e74c04beef4dc50c856eb18407 45151bebf7146e8115b238efdd4a62e9902d8ec3b2d17bee96e177e6d7aa19ed 9f0f1064920ea54f315688deb2138113e19a1ca6ce6401fe778a01749a2a8736 e862feb485334845db565de4af0b91d08cb2e4488553054918a4fcc5cdb99ea7 c07283ca458cd202e47d486a82345801fd8351b6d511a7bb5f4ada80d3c6109a 7ba6f60b39d016bf3ab7752a09d9a9bd72b34af8dfa098fdb1f75e565e5323d4 75a784cfc3245741caf9e5d074b516bdcecc8e27784230f92084850460c6986a 1b852eb3b1840382e80d8beb354567e7d6ac15e5abf7e450358b70f067388d68 9b06b82abcd972ffd5bb38d7c6bda7a4e50e79350d0d22e9ba34231db2c69d6c 0a65a8633f5152b3b3514e838be2c0a6cb63c686f3be5163044812ba73372779 e535860453422af9b12fad4a50fcb1c233b303c4c1cd254923b7594ec0e1e95f 5c70df9727b368bcdf48d910dd9bbe2d113d468e22eddd03bf268c6194f5e46e 934174a3b129c761d997d0df693377e44c5303aeb2036e6b26fb0b6f7c688146 a3a8c856c73b2c20025a9db3d15ed505a5a3cb453c7dd31f318a76fe5098f59f e7def0f0562dfcdf304d8ee8b7483c1292e92a39a2b6616e0763719aeeb4c10f 9 c6822c67eb2249f3a442dbdc2633297b11f2fa073bb076086c0ae5344b40d6093277f11ac09b6775117872f9bd66ea450b148effe47d8a3d4f28f6a252d8860db528078987e3a16da014a935a111c73cfeb23bd53b6740501f862359fd43090bcaa76038c8e479d9e4cb303c4fbcfa06ba26b53a035dae3ae36fa6efa1b8a9005ec1b16f9d3f17dcec0a089ebaf66c41e335bd4469aa3369d95a7277f5388c0d2b28ba53c01d7deb416d950646221f976bb29c3992d0ba9bd4f0267dad66db016e79123c8982509f46e1d72694f45cc0678ea1fe396db43a715e0f7883cbaa0450af1a7f190fa8844a7ba235dfe4d01b5571c07111cf491d5f2801b83b4e370bc3aab84513bf9cdc84bfa6cdc7af852054ae9fa8b2ef1776729246059e18b902341b373e955ea3127d0d5461895e6f4c7c35cbc86f4921066fa62a59d3f00c0d6129a8b39b45bcd3fa0e4ec29a5f0a2440ae7592518e5464068744e3ef547c0ad2b9ebe218f5f8cebe2ffe16a98c335bf7e09367ce4f7e38f606223d9179280a124af3437f031d41bdb44e70f5a1c8dd14467aa0742ae0a12c55dae83a39a80bb3bb951bbd367bbbfeebf304349dd228844ff9dae04a4e8a359cb9eb89084e0885b1164ba7f5393ae319ef93caee9891ce3f3aec1d5edf2f57315d0f06c8790357ae1b362c443729ea1f990a1549bce040de2c8e94dbb369853a412ef37794032a1538cb8ee4f637786af56d3e1f2998f15f1076b7dee2b55ebce5bd1f026801d4c12c5515a2600b11778af74641174dfddf99c3a0acf1809fd63078dad8d60fa6598b0cb1f74765ddf46a9f29fc2d99e6dc2f1c9d8e5b73d3c5f6a3970699093be2c69f94ae2d73ab58fe8a136bb7d3800465e525486bb85b34f43ebb9897084f4289c4bdc663c62f00349a22eb9e80586ceda2fd20378082f12d54a92d2301023833fb85903e1e376d45a1df47f94cb33865e23bf120b88faafffa5b76b30332c0b1fcc7a76d735d33104d4ceb00b3ff5390b1283e9f9bfee5300200a4d706bd8e03f46373fb9fff891decfb39d58905f82fc53124275ad2719eb121814402cce6dc9d62af0cd1e78483e4a6dbf72f6aee3da68329210713500853900f0a0660bf007998ceac9cbfaf6cc3c93acbef21ac3e84522b4177262be97f4b7fbe0a4fb4ab9f79f84c214b6e0f306e51abf05763323635ba6c3ad407641d4cc0180dbb6340d0e7c7ffe42f64ddbf87fab6880b044a38a7f0f49ede342fa6622c5e039c127a2a115a35aca8bac60fb060dadfc7f68000582baa638a861e5f7dbac50a5db8503d00cd91662bfb55714701d38d812d88e091c6b63ecbffb866b7e798001f4f3aec6b3713781b99527b36871e5520e87a6c0109e3adf92a7189d301a40a7894cde0b740db61d37e53fab2adb066c00a62500231d2a3a47a6c053da69e0c234847784ddbfc80603b16d1463b7226d3b61f457baf9ea0521b09f92f350f088ad7ba2d43507c70ce1126af4883e7d43876cb701968818c448b4f65f8cc150cdbaaeeb5b3ef7164c6c5954ef8dcd9a553b86aa4c4676685304f2fc45707010a50b2b431c3ca8a390e54aa03c6a593c5def5cc821f1e66a569957f5a68ae390f7bcae0e4037afe17e17a02e19fd80a199b167594c1aa50d0a8447b0318c74806e8f9315b78fdaaf486a03a7edd1efe9c309c63de886afab3accf5e3b5ed03d0d7d8fe554623e2a4df5f22f7ec9bc22f62a0b2a716568749a7ad3e2b7a7c01e05831ab5a8811a11de433b39fefea883eeb995eba8e00ce4ae308c6fff7251f20fbeec3d1a72219b74bfa609fbca57b6af8d553b8e823141e3bccaf76f553e9904402879f25c086fbbde800f4477b8501312b3c7c8b9581fd805508dd6ebe4ac00dea99795b05efc8886a02dc69a5f44bf4ee87a9ac851dd4b572b6aaa5a996c0784b33e066abc1d5fb6f1f07c5424b782764b3507735cc9d4af89a534a57cda0573fc73b32d1b2d3d1d2f3c072db3b43fae0573b4513f11912411c1d41bdd4b0af0987aeba25237b47c5cc352747906fcfe8ad1a563d6a4026006c5101d1e4c0786f1dfb9bba6356b8dd01b05bb40a61b29b4579fc92d92143727548f980d05004690d4c4f3542503bf483b122fe98b98a105bb9e09a49756b62dc3ebe029ee0cb83626a67cbe182476f78411e8b20fcdbf4f5756e0e608cc7590e0dac0e17d066237f3845f78fea87a312b6f6b6f518bdbaa014586fab04d0f400241884d880ee215ba9e24b20d6cdec807d21d72ba39308aa2313bce08b0550894de2589330d1f6b31d8dd215cf7682605026da9589b10913996da5ce613de86228dc20f5a03 -generate_ring_signature 5a353b51a4b8e73c0ea6abc2c657c04a77fdff66fc6725ef72f3ad627f1d475c c9900fb41f580b8dbfe112df57f0c06e1ce7fb0130751cd61c16c51120cf2805 31 2082c30f4fb72d624bb617a6a03dd887a65bc0f54d266caf486fbac1aae5442a 0eda2f4ef08a2c05146633a297314ad90dd695da99f4f765c18c22c0c808812c 749d789d269f4a8d46b4af5ddb19cf5ee7f86c54e0c08c6d93691d96a1fb348d edd996b1ac97ae752bb02bdd19976097ddcba82f6039f8115498fbe93cfc09fc b7123f37c63a6ba41ec9b4868113d6f66cbbbaa8d80427ee6964172265fc2e8b bf64bcfb1fd3669ac6664c3e9352e5f30ed3060fd80c97bf43105bb062b9beee 991ec7c190a8f7b9accadd7c2b7ed031fe9c579f343499814c4c4d898855a3f5 420ef41f473736a88f14d32ff6416ee906a4bd91c3a573c9299a4f1c054471f3 236a9c9deb53c00f8668443a9515510ab1e9b968f4be278a94c3bd17c1bf06e8 0d96fc77c34ffa4ef13b0de637055983224a12c1dcd206b283c797aab5e7127b f11026dc54d653154b6f4a9c29d188e9c8d4633605e689426cc3fea64d70b114 04b312d50cda555c47641f109b9f4c6778d9a7c52e2ebd57bbbbd32c459b5c96 b1ba5c22e1a25e62c099f43f3e62f3bd082fe17b2e0334d30b45bddb8290fda6 b69eb8187d101ca4ebb8d84c72592d77f57d04943f3ed6ce93f56bc370b915d8 a0c257d7c690866b100211a0555956726db6192ef9ddb6569b0a452e7764b0ee 99cd8de3617f2f157fcf318c43e96e37df9ed7303c27b039bad46a8ee337b684 e929eebe671159239cb71bd63468e94a2cb90b756400a389b49376f84aa269ce 8f56d7e009725f04ea1ac3521329a1572dbce6fa2098cbe4ed7132fa5ccea342 47e13fc70a64213fe9d3278cd08ca6aeb844bbaf556df1c57d927c30f6d2c75e e4632e8650a1bd477c11dfb50e3c48c77c0bb5ffbcc2de1c41ea85ef50214b7f c8d0e4cac23ffa3b13127de2c01f885d110620b899d6d1ed4fa014c809642284 33873c867e6a07e795638df98011dae680049a28824194c4c7d5924d0f7bc18a 7930cbe3c49a2067ca5a88383454ada7c1529ac75665be86acc0906a63d0b84a 803714d531449220c83f1582d3a0b96462e6a1c4fac0f73bf486fbecfd99a216 6ab2e19ea796cd40a1973def711a3c370edd3afbc452afec3a27375c468232a5 5f58473e62a5a53727b3556b0d537a5210c77effa6ef4c00a00e6ab328f29133 228455d4ae9f1cb40781b45e6bbb26562bc01fa91b81f16f46e018f299454b57 5ebd456bc28a81eb4399fbce59a8c8ce0d765543e7d1dc876ccf2401da38e483 edb57f628c6675f649fb2947c2b7abb9504e00aac31d3be494b258daffff3935 44d94d6c395ebbd88bd008d0ff9802d38e06bac61a71f3afd0c1d6b75f5517cc db1c12682ce582aecb3ae22f6040d3c804d0d000de0b051c8739587850534ecc fa0835dfecc3c5213938d2abc5b71467e1412c22cb0cd2c42011a03f15af9f0f 3 c37c7fb6e87a004b2f619e89b682dd2b0fcddaf4e2b1ddc7374e49ad2236d00300806a887ccbb198f7a5d483fb2fab1e76d5367e4139c0830bcf343c808dd3043560c44abde6517a4d19f2ad0c34a21e4b442a002e3e3de01b1ef2ac5921030d44e36711cdcd8696af838815455e49a852a8e48ce6012abdc89214f555a974013a9e625cd686887a071428caa54f7e41dec52190ab3e76372064ed35982b5a06c562db689e42e295ddad75ef892aa9589ff69f01a537d0cd33c06726e7272f090c71d0c55b9246994fb82cf541de4c0d7da069d9f9c8f70c33d61c175e2ba301624c56203d1f65ead50c8c8ab962eb750df0dfbe16121bebaa3b5b5c633b8807478d594e8639e56e4fe1da783bb733a74f5a27027c85193c0ee2aa5248a5590c96ae810ba38cc3997649dc90be361bdb84e711af41091a9dc8a3536657b71500679c30461f74b4246b0e18d00c0e0526bcef750a3b4fe50c87e6414484c7280c12e3530b236684545f3596c0b32bf83efed4ae47c209f6f83c257c7d787d080a474dbae2c47d543fbb0ceca72dc7cb1eb0271a6b4ab1f38304df705d76f2330e199dab48d4c985de0b3f85de47e09e0dbe95b4e2d1beb1bde359f59253bec50fa4e389b5345611f537aa154140c33f86c306b7250406f57261e194eedc5f2f0c8e3735a618ce013f0158ea52d2aa0415427f83f1e1251882fe6a6bad068cd10c4905eef24a059aff58b51b87f3280417aabcf15c3df498c1587e7d20da0e3e0003528982d52fb5585c5c2ff24c974d5b4c358a3f472c366132aa10c9b342fd0d089bb3ab6c161ad99081d05a84da9654b43bf20f012e4df7a8fe7b352abbbf0834910b6736160ab726a10216d06988610bfe43a7eb48051f348f819730730f0687f9b960b4b956411416c0e97a950fd0b556296520d480c8dd5454fdae9f9804ee643c30d81a88f34a48c1704f4a993e371edcdc194e0b69022d014b87849e06400056cf375c4e9c4c62400653cd27b2f21dd1d2e41ed7f4bbf7ba1455a9c200acdeb86611cea04de14cb3004e53148bc5c9f195e027b2b0e6e5fbeac886ba05d823e57d600e6cefff70d38aaa02e0231326386f910904551535319bd249b5081b4592d5576ff1735ee7af8c7388aa5bd96709350ffba4f25195297a706601067cbfb228af229e363b0883f4cf87da258af323a14e007cd050f82ec0abe8030be3c5ba50c52f7e729aee539a73ae989137caa58fbc900495c0aa5a8a72b3c4044c153c7d659c440d8986bea7c03a62b83006d55ace4ea136dda030cbb94f7308c02aa29d52a558f3e798fd45c6c1a9ccf731382afd37ff62dec5066c01535b06f34ca8f726b18295a1c077d1831e51ac0b20ef7cffbc5b84f3d5a3f6c58ae7033924258dd46d6c86e469006076c5c100407c80efa4ad693bc76fc17b44ad620df51054cb47037e7cb01838eb585cdf4edfc79504de2a7dd98ee7dae95071300be73430d5b23cf0bd463aba726e2c05919e8fb8b736063164fde649fe5a5e1c0d2faa33c957418c9e6cd229bbdc581f149c5a48e53b904abebfdabfbe35d4e9017f2af353a51b6b9694ead1dce4e0050c871f22183281e9508a1633b873ba4802e6cb728d118264d848fedf0b6e0fd32cef9f4c9dbcff7e46f7cc1477419d8a0ec097a9e2aff6586a7eb9704d931de04b4f19fb2ee125071357cdd18b97ac3c0badac0b1f35dc882ac42cb94ce34725d27af65876e042d9e25a1cfcff0479540fa9fd42b736a94371fdf4058cf5425108f5e3e4c3fc14f28a0fecff1608367000907aba24099bb53285d235bd7dd24ee976904dd301733fcbc0a0f9dc4db79607dbaf2a06f9a48248cd59ef6a29bf829ce8eb5e58fe78da2cdb8f00ab96def10d95e38e3b5a105ef1d4092329d7d56cf6c16a25fc3644aa72e52fab26ba6ccb0daff69b73eeb0a3b1f315b52961e865b9be70ff95c38a18d73dc86b6771dfca029132a46cda910a4826a3142e72a1aecae7646d241139c2ae99c63a6f094b72003dc42510ef14d0c3c0c1dfa901b9e6871d97bafaebfaf529be2308f3e36cb105575f85c40eec91f18823b92e5079d3ec5c15a8fc7179ef282c6cec79fb9c8c0eae6a5ff61aec22889b283ce3372e73509dbf156db41987cba704e4ea30de8f08063d4d774cc494c204e570eccac5706a05ea33960a8f6fdcb98f4fac9cd16e0cff82ce221fa5f2cdb6ed8b1b368cdffd6632b612d4e6361cd3109d84be576f08d5fe4f350fde798530a61dd297d75422694f0045f6eb4c6807cce283de4c8a04c5092e22ab8d0586c5e2482917370bb1106094dc3a21c2df7357f45c4a06a305cc9ca5641760cbf7b7320d3d353362c71b05f171f510cc3235862be20f19110196e97a157077da3c35d25ac91ff452d9855874b4c7694189e6765e70017dd40f9d86592dd045301c51fabcad41d3c0b43ce137092ae87eb7edb32c9e8542be01a2df9b2d0a3bd8610d75eb90adddcdcba1b6f4450fc149dc01ce57cdcd00e8026e8f019fbb00badac170329fe83306ac7d244963ff31bd2b7169436c384a960b2475e50f2678ffe9e0143374f8e29b2d9475e25c638301fc2daa72a5e506210660eb7e094078aec0b907a4e8be2b84b4a51c1357593bf7cc94c24de5b21b020aee576c484d1d340d0c7dc94bf02ee222397b9e933be7bcbfbd9227b3fea6820244e5f6918868486a070eaad080ff566c18fd7c40de6e15cfabacaf2f32977d06cd807d306adae9f1005e441b80bd2b5afb8a5536397e2ec269ffc9646889df00 -generate_ring_signature 6b0442ce1572d31322392813b8f2796600e1bd3a7f311cfcd5d18db158df3f83 005e98bbb03be89de4e329438452ac2466eb114dea37227d0583067af043e361 26 d753796ecd8caefcdb6d6eaa0b9f198541cad7e68ac70b436a7c5fa4db496797 6ae845a62d710002eb816996c34cfc5534d1323ec9b664c20151c4571617185d faae0348d8ea4771b6855852bb5fcc60d992a0fd9ccbb4418f9f205fb3eae956 c51b9891e997455b4b220b2f1b57dd8cac0e35489e9f8156cbac6b7792a35f42 eacb4149226b18cf68ef4cf0bf21d09d3e094002482accc00b213d0c32010d25 da150b24184ad0285d59eade87dcb51e73222301f46a0b8cff4007576858e11b 731a7cfd4b0bfc6824e2b5cb6e3fd66a77981d707259a9d2dd332168310e0128 b8ed9d7e6d9db63cd5dd9f5effb80843648c18a5c63c32b67ef6232240707fcc e611578ee243322c9d2e3210f57abd215388bb1e79319fccea9944dc8640e294 410acc54a3f9762e069471c4686a7e9e3e92c61811900962d6ca2400188a6ddb 87d32d08f2338c3da64bfbdba28f6b75d46dc4ad7fa2f018f033d09b608871b1 bd0219ef9562064deaed5e8d494ab9a22c32f468c5573258d6f8963c5402c62d a56e1100ea7ada74f25f46b738a3101732b7fb2a6a24e860fc42a122cb295603 b5c1a4655e455a01e68e3f6002e6aeaf2ce8e84d610c5e4542fe2d3100a01df6 6d324750ad63ef0f6be7ba47418601b0a5b5c1317d151a9449c53d27425131fa 46deeb14d5108ae9456f2b8375dee122dd93f8c03fb326866e6409586b44c7a0 ff9057e3940c9016f2dc47f986425e3d4f7f751ef2f54ee3aa1aae85a2f32460 9598db5a457095e3d02ea5c1ea0c56f8d43a2febcc64a089907219992cc8e4e5 afba70859ebbf598a74ae65fcd63fce51abdd43b5b6485bc8dcf9a2eeff66d7f f0d872a622b64de9d6f5db16745b7b7dcbce78595217317b73637e9c253cced1 c244cc03d464699ce9f3c9fcebc80a8131104d03f2fff938dfa1f76dcaeb6ec2 ca824fa57901f10a1ad1fa6c51a444064870adb920046153246b60176229569c 2ca019b674ed3157c84475298abad0f6b62dc1cda2a11a92fab49f9743567a24 68903516c9127c4e405d1583738f2329755d88724995901269931006aed07600 0f8e7fb6d91889ad5a0aa80048a6a1d941f666e2f5c9ef5b322bd3729de419a9 6f87fe92f681328fca521963539878521e1549077f5851e04b200e3e5d9859fb e4887420585b1f8449d75da7de40507abcae71e73652b880ecfab2d43a9fad0f 20 f759dd4dfc3335ba9f866f118c4c60af808bb6ecc6fd03ee05efbfd5a867b90573ea38606265a5c902b961ebe0cdbe99d8c22c014d8a641a4b8b807eb7cede0bd7bcd41af4ac0e3fc4925ef0aa7a34181ec477d55ceb294d91e647cd35f0e0038419102bb6b448c89e66512e700a1a979876f65b5c409a97878f4f54d6f8490fdf211c368cc4d27d905f80926e52afd618beeffd666e8b82ba957a0745c95b02939ef192eaf2e1462a8f785d7978945f0b6b66792fd1c7104339a044ae94ef055cf84f84b4f2d2ac397550122800ebd533b904b861587fdd7a7ed21ba1ce950185031d63371483c4a3b725f685a004c6c50d248a70c84aad172adeb42312da01b9f19df0fff7071223422e86494cf0d3c6b32dfbdbe9b5e44342d1b1a05af70ddf792526495e999f6830d95f5fb1c042e6c3ab8f3281e46e94635846f5fd1c03714448126c5096a9b0a16b35c2999d0e35bf1aad48428967669160654038fe0b50972a6e4f9327950ed21c6daaa3163695c909f83faa4c72766f10d5e89c0d0933ddb7079d20a3ef2f69c19478352a34c07c5271aaf22dd646491b6e7339420c6ad94ea0f676ad968077e30950d4d67b88ce7232236b4a5817191623cff2080f85d72b67cd24a5b1f1dcf7b201ea7e7737587f67266a2f224e50e40d169aa10b055f7bb7b0c742b07fe62b1d72da02e667fa5ae60bc27a5c93ff4a7fac1ee00137c17561e4c1741c7403b5352999d560737003c3c6d7529957bd669126ea950e0021bf7b8396f7bc845ea2c88d41503bb8e5a73550ce30359c6c1208fcfca40e9e53b8bcec5912304979ddc9a4483a0393941c3324b01bcb175bf9567fc59c0ddc66d9b9c3eaf9615d0160428a6151320675e104b047be7e4d20739758704d0a7541543d0f86a5da0e42bb18a7248e3413b0e51a184291b2226de651ecfd420db854df5273bfebbece2e31741311008c3540af4c1e157d0a09d65ae3ee6e5c06436b2d82e8c8a348bec14601db213fa843c43887576b1655b8f522c326f9a60c1feeea5cbd128c8397cdf3c63f97b843a02dd368de1f919a6c7534d0d21bbe075099dff3aa75ec9474646a6883da266a550fa9b439cf4d1b9313ed3242875407e7c954fcc807151d6d16ccd83fb5ac8eeab8ae43af5768c73442700616e04900e04b85325eaa695071cad0b0c8b685e053a06edd4ed8d82e921b6a6e6ae92909404f36a771f95ea10e3910e5da87a79bdd09f68c42f2ab581a79114023d64908d3e2f95c81ecff1bec33dbc54adb8ab66c1bf1ad9b4def708d077623462c5d0f56298adaeb0066c19cdd2ab8a3c12a01791091690e50d0a39087ee09856bfb066726258fcfe26d43046fcaddac4880ed85d2e4e125586474c43553620b37d10a3e81f6137a17356ca613263a387c1060a855f175678ced2e1b2f0487e9d4a00300aade217e03de51a135f0f5678f32e0307027a02fc8ad219a29e86c495f0a0a282a92d4cd6358ae229073e6164481451b48fd5820ad04637d48f23d8cb346069af074eb9a672d4fe5177270bb64646dc24c3ec03aca505f8a9cc4bb21e8590cfe66f8f59d313cf86bed554bd8c8b63f06b8e92bea191cc37a8339fccb2e51051632f84c0f9870d2968b9ec55bbf06c566186ab36bc43122340c99d74a07700b512718a6f701f1b172eb6cc44435a2d4120c66282733fa7a22e116391e51ab06ed314b106cac92ac73b7bef6962d156e7f9ec23cd2b241536fd8dcc8138baa0b11e3044a60fc69f10523ffb84ae1a435a583ac3e028c588edbdb75e138f03504139c5f9cfe2c9973f1300b4353a1480e26e2f9728b45a0487a441e0f8168d30eb4380473998f635109eadbf6812325f1e897f5cad7364ccb5088790a54343b0a6271ffb7e88d9ec23873c16fcc1d92798235496f182b2745bd4df1028074840e06a1d443907f515d834f79fab8082273ffca1c8703706ec07302d4a1dc5b6901c3579ef56cb563c8329bcc739005bd7d057a2e6ffef889e543d6d20c0c69ba05a907c05bd2ef258f61649daec2202b531104fb1193431d8f12b6464ac5cf520b809f0b496e0e34308a65a25585cd8d4eeb6dcb7d73b3389464862fc9164f48092f74b81a2c99a57f306055f8bb8338b82627b19c35877cd578ffa6447564c704912b88dc9be5fd8703cf96ff3643c7c8334d61f89077f62eae126d8a69c0b406298cef11bd378804830e958ceca623ad97172d5f2ca7b5353eeb6c2d9cff0f067d1c7c29b5fbc0fba774220384a7009e7f8ca0e8db8b7bf73992afedb534080ea6df6a7b0d1e71145a7117a5e16f607d132f2c2512c3436580e809c45f797b0f -generate_ring_signature fa878e98be7bf61dc3b35153e4ab01e1c444b109729d4428288fa17dd1277318 c711a0a27fef0f9531030c710cc93fcd675120c2b44fda635fc3fe58ce68d5ac 2 8705fbfb8783ab5987596b73b4d1ff0156795c951e0c58b8091724678d9d4174 aeccdc9ec7f198a2f4824e33ed96d40215f9b22fd69cd2f0f84546093fa44c67 128378ed23f8edc0dd5305fa3e39996706a4c77d63b5ffda8b294b057c3c580e 0 111247f22213a60f396a26e60768d4772c2c674fc227efca69f0a9ea88586a044e59bcc34a4e844dd232d9bca065653294b347e78156207e54a8531efbc73c07b65d3a9e6ec44fbde5ff8bd520b9b29cc572e413a428f9005cad9df8183f0601f23537d7c3054c51e4a95cab5acc4f1aec7db14b6febb75e3266367d5d596e0d -generate_ring_signature 4dc38ce91c25bd6cb03ed5c0900c0b3a3d171ecd3f441d8bf38218214082d784 4279f878215bf5455ef8c99444b6a8cf0484d54010b0d1e8fe7adfe97af85f10 114 bd939bb5f29b32bd0b9b884328cb04da64b7a77b9d0f1975a42d74c06222906b bd64c1eef3f01b60b4c60765795c12d9d1e67df40fee313bc7b0cd7d769bb669 85917e8366e4bb6557e7e3d6d0851f0bb72cdb2f5605cf80287dc503333cb4ff ae20b8d284cc742818c38e284160f244b157b868fbb088f6125b8d039623d282 67676a9bcf5d35194deed9e14a41c23c81f5e96a82ec4aa28d9c54574c27cae1 c57610fd10ed400b939d00134aede8e719c8e4a8abcd18ff1b32f7fc96b9c937 494be2c5d57bab3e0e2df1715d4ab09912124a8eb65d44745b6ed4bd50718f10 d89243a7661e6cf3d7ef223ad3eac26916c71f9337e02d56db8bb710a41dca38 bedd21b55f596d4fc3ca8577ab48af6d0e4caf878bdbc81c61368799da91b655 c18ae2c77b4f87e07ed8564e9eec44a7fa841b9deaf425ea1be3ea7c800cfb94 789dbe3cb82cb86630f62da491b353336731b43ecacd9d76841917db6e265b50 d983f5d7e4980efdc335a6eef84da9d194aea20eadaa2b1cb2a2dcf6e510cb24 3fe08f0aa6a0bd5ffacc337d8cfb3ffa5ed8b1ad2717d0d51b929d9a33806790 686623a9f75270dacfeb22784afb28c0fea864434b32fc76a7c7908c378f1e8a eb2af211b6ec6d3a7583c0a264a4de602ebef841008dca26e06a659e933994f5 1e02ac91f995e252099050a2f9bf0a107500f689fc785f1f9d221deff9354e50 526b8e6185f40078ccdf886172921d276549dfbdd3a0cd27fc65f172d3bdc2a0 8e3d39b85ed3a05da76c47c8f70b76020002823548f8d45fdc27df8e6852af9d dc0915a34b7411206b4694438d629c17f84c2c07aa745284b1e84133765b88b2 6f1070b084301889189f7db4aefba51bbf037bee8dbdb086ddba9e9fa316502d 8cc4b03df9b06722f19ee747f5e4adb7b6a5ba3f9473bb33e98f06afca0155ff 7913b5b2a3371c554ee75295492f120e4fcc1761a2e90c163800e0bc8566530f 62a6ae54a6ad56bf2cc867132bdc8ed65858367d7ad38ffba12b25bc2f44a923 afd37d8701510ff65f36a4089d28a116e923640d83cd013c9ce2bd232f689cf6 d2b980b075ad35c7080194272558a004747fa3d4f54d52e54d7eb15a55fe47b5 09dde581825bb3e27bf96127461b67b50bb5258077ab5773544f29fdaa4cc48a d5e555016be782538646c00925362d280850ecf85d9c1975254025187739a0b4 099ec3a3c0b2448c583d9279b8df8d6f9d95a524d7ce35e5ad796619559a3c6a b1785018039ed1f0e47624cb17cba05a29daa6af97847e985c77b5de9e2f90b6 4d1d4f2af470f9e5c21fdf9985312b217dc866cd3c99798322d4332a75ed3f83 61bac09466cc764cd2549229e63b21ec0e00125211c18d2e784c027edd279198 e401492fd7498a1281617bbb9750fa4dea2f7ac1c05d4601d7b4d6f93f05e05b 4b50fa467dd7bf98cfdfa98b87a924aa5122b6b09fa19e2c6b1aa82e4f109d71 e4c8c681e9f7f7f0607ba801fa44816a802e81e8fc42faa343d0c0ebfe8e3e78 8a0e62086feaa8a6259ce3a21c4063fd4cc807c1beb371372f45e7aef1493123 fa7a5f9e71d90eb5ba18bdb7a9337243ba0d8735c4721bb9b65be880ac4ec6e7 8c89e1ad8f42ee19016d782eb7489ccb70b72be6ed9bc3861647bd742fba528f 339678b140b4c32ab322905eec017d40d039ed7e02c9ae57c68d2fa7e8584626 6c2ceb1dfd2d66f045bd54bfd7e5908a57bdd5216b7b17ea808e479c0e4d7d22 f36e853ea751ae307fdbe0837663f823106aded803139620a9cbf8d65d85c1ca 1514c9820ad846074be5e94a1a460efdd832703bab36dad44b04f6723e6b983f 4734b3ad5971011990b5ef237b152c24a493f304b337f556afba97607746fd81 8cb350acbb7d6e8c4da9dd936645a8750b052a29414c450a9bc886f1ee58bc9b 90f095ac9e66ecd8c321797c8cac0b6ead2328db02968466cb2a813a14b97b63 b6ca5b532fb55b28dd5788905f16a4c017617e45bd9b59ddb916a910c004c906 2acfe7532da865b1eb9f8ac6d344f535c2dc9e6f38be192986a02ff8968af635 e656d87021f86642a2f147b58869913e1721e8c8320ab77acdf32775ae4b816d 45847b41ac23724e860ede8d7fabed5982702ce646484b7c008a603b48b08a4d 6d0c71b58f122a7c9e6f4a71c0a8ef6ab1d598d67118486fb704c4d1fa8adc99 abc2b523b9f0111245bfa413450546125e29293df013aaf0783cfda5db038302 8649564fc912d27de342dec94c8dee22da9d5953045463bcecd0cf111a2e19e4 7ebc13266c2d167736b1fe30b6447f51d915a09cedccaf68726bc2dfde668816 dfe2f28066a7b2489f85153ad3fe8c42301efc3792e55764241f0377b1df59ae 53337434326613e0a7e86c87effea7123084637fd9ec488d6a5cf79678418d71 2fd4edb314b9ed004f702e97673312cd247ca6cec9dfdcae83ad266cf70d70ef 63627d0e850e46d81bcc136ad2aa095ad1a451f2d40d0954b5b9a99009c9c723 22d3231a1d7e59481188324c8a300004065010feb4408ae9bb8c5a6028099005 00452956c834dc93e022257d4ccf84a981262c21e5b0e364d606e5b8b35ef10b 8e4624bafddf2d0659dd9568425153ce7249d66dd796ae9d9a3958c207ff621e 18e20d7be6b02026da91d6a20212fb83271ca5c0e41d31f7742f9e5d7c9f75c8 0321996b983d708e35a7062ec8de17bdb8eed2aa44a33da0d2d1fdad633641ce bd8512058818d365f2a894bbae3fb48a8d8f683cb5b7ea86c20876fbcfacfd4a aa8206c4c30cae28a9539f34a06071b321f3bfbb1192890beb6cfcea066224b0 208e753a3e2ad56bc88aaeda6673781d74c4adea302c24bb430bc9d2ad99ffeb bd60707aab510cfe9aea55674eab81065c4481d823653bfdf4ceed5aa4cbd2fd d73cf31ffb213b78260d22a47f44376c188231f066635944f43b5ae6c487fdfc 04acf87b977a025d7aed687524a1612b4ec58f042f570dd537e2b7bf1f374819 b67f9de08052c5fb3a0b62ccb6ba87ea75cd0ceaa251708b40844267f6b014e2 1ba734db12fcc7ec682fd0ba5e50f8e201f88bacb180be02ca298bc501a04334 36d7d9519faf0b07448f93704963f2d5be500feaa60567408b62c2feee1abf63 fb64b38df7b1c5c931251663722e1bbcf64aeb53da9d97989e62eef5b3d33185 9934ed813d8e4ff4b96ea8691f2a73701443643065025a46b8d0ffed57deedcf ab16da45b8ff0732acd013c1a3574d7a76d4f8c510dc7dddf54723f8bc9235d0 cb6174b0170ef65b191639424a1d18c67ecb6366d5e789d006718ff192b74e31 5e832d1026ceafa167e47f8e846d6f9fe37d337fcd63cfcb0327ae049c79c253 7495dff8ec7290d6672d5ee2f5bef600fe0b573dd51d4d356dc3093801b1db78 218cd5ae20837d084034d5de568343e729c8c38c4c1aa9a7129eadc0b155b2b7 9466ad947fce451cf7fadbe9aaa5c7b6084f72b3421abe042121d6947579543f d221ba32ba6279137c88c55d22a192535e263d14033e775ef45eea9c076d0dc1 c428cfb99f6446666b862996418db4a552bb045ed8d8fcfd2b08deae775398af 8769dc3e2d1ad107d4f0d96cb5823602daf842cb159238809a9088752d340ca7 4083c2735f5c674f4896893952c90d275c6d28ec96961b36e75164b42d63469f c1f161d41107d3e258a1f77985876fcf02f05d98183ad77c5c943944024c4ce4 7e5fc3484d81d4f393f6fafe0dd4357ce73d08b6db85aa6d4a5dfdf61586f9ca 5c39e84b62a9dbcbe60d5625491f3cd44621d990ee50b74b7b3a7862057c7c48 34383e8918f547536c4a41cc91b2f02f642905325140b52f53589bba81f16383 1cddf5fc7808b6466f75be06c1b19b90025a85e241a44512e65a94b275058179 141df5ff0158ea408546d801ba6f0c6af9bcdefdf23ac134cf932835091c2f22 d476b262891e7be025046acc191b5950f598d26b940d883be486e5032cb31445 522d85cc71685afa492a62c6f4508207849af1987a7116cfc90e4c19ebe400df 1d1f78f69b6744335233e84495b0511e32d3c720e2373bf669c27a4990668e74 905d0a24578ba9bd1bc7b3686d1b08848b470ab12f4956824cf3b0fcf056c0fb 8a3768805b5a09ebc505e5c0d4242b617adb9e0f3865199bbd2a7be7579024c2 e7c80d659dbdd822a62c5a2b5580932a55c9baa6dc0818e8ae5467869f87375b 1b32d833d664cf3338c60fa3205c119e1ddc8c9cbeb44702459a97512575c832 12abc274c96f4ad4062309fa3060d05df560ec075cb78a80251cecacc9000a8e a01aff1dc079be3335a3efec1cb3be3eaffb22080688a4fea7ef634f8b1e5bac 1f4f6d983fe92cbac643d9a027741439190bd7d911d90c50a86bde27d8f4dabd 5d82c7c2e907bc4f46744c8bf1d8e441c21e28d3e194ad9acabad465022496bc 8177edd83f79988face73a00ead13d6c0ecb1db4f365b2e3f9568ad58cd8c641 2ef4116bf37982032ec32ceb4e1415331f4fb988957d113425ae1268975157b7 58a2d5b81c539077063bb9d470cc5aaa3f5014295ea7790b6bb002ba368ec551 452b24765b3f19045dd8c1b37e16823a6ea3c91d9500709ea0aa83880ba159f1 2e967b6d4aff868718cb1a7b26f50384b1012eb02313e8947d8e9a7c52d28a7e f160277b45b9b94f4004260a2dd9b2682f13081a1490cb873207ff96874d296a 6b9995916945798f3a838a968e36a030e64a240737da517d6c29fcb56e2e033a 3d3a67122086e15daa676f97a1f704008dbc47084ddd75bff2d52de83ef44377 e2c2c8614448e6b57b2bff177ce01d466211ec6cc80e26e9c4a9238657b13932 240762e3135c801ffc2df0714bc22bac52f23089d3698fa14c4f9dfd1eb09377 1b120c957aea684c4babc04fd213fcf10b20f56f8873a808dd707982c73b349b 468c72e026931e245e55e916ac2d0235c52e4255826f113b35c9857e171b2901 4dbd62c32aa0b9fa0cbb9c7f8174387957f23d2b7cf1386f39400b48f40802c8 a3d0a864f3226f810e69cfa3c6fe0e2967af9d69f12d39f85ce0c2c43e6310d3 3e7bf7715c43237de8eee1de54dc56b73f8e7982b30c1f93bfecedd49be9adbe 00ee10408bd89c7576d8e154cac0c7f743aad43ec26fe575f3a005ffadf84606 44 ea036c798a978bf880423093d4929c6d4b244a9874b5cd3500095b319b8e0107b33b4d9c60dccd53ff651565a687a88dd5f960efdcf29467b5d04e321c2773083602313ddff9a642f4ffe8f147d99a9eee00aa5ebd66764d172f2ba22c038c0811bdecdd5788bbee3e4363bada8ad8830d75d2465b4070f4312716c5ace376096929f6ca8867557eb0ce0f9012e6aa397be54579234001dc96fc2c7cd03250098ff6e080b7228981376b93b6af674bfe0d39a6c9df262a2a80f73b9531430301d262e638a96aa55fff4a00f5ceaac44159ed85ed37e475c524406dd096643d0735797f98e52db02565ba93388fd3e75c38b0c4d3276327dbbb12a51c1569c601723682178103a17295b81a060c099371a837569f362984a722e7a4914fe046050f9a015a2f91a2fbd6a0a76ae4c1b072ad3fb9a6122d25375033ada429b4fc0f0d38870229bcbdf4f94adad372b332ce787a3ceae44e84514bf26c6eaad4ca0437ad225442c2974481568fbd539f9059be80fbe69fad56263f0f427689f6910828e4679dd1ca75430b69897fa58065811e1e6b1b2a89ed7226b17f31a7a59a091aab5c83e2fdeb2c8b7bc52d84af68d4e3d57e0e540d38a3751ecc3cf5111e0c24e6744b8b6e2b61da27d8d2c40d90e01740a900df55f5f5dd2d21f1e2d4210d097c362d0d66f38894b4997df63b06d41c8094231167439afed0c23349b8b0095573ba5c72bc1238ff91d11a7fbd1bf5f03d64b72f7ec8e8d0330cdee9ecd5026f23829ff8175b81f03066bb2b7589c37b88230e7e18840504bfee024148d10d0d3e246b90670c04aa1981bac67ccf1c0e81debb920c53e3e4bc31d56da46c015c4039eea9c3bd4e9653ae03c2e634490f2693dde90aa6a38525eade34478508e4d8a6062c07b2020eaf40b43c8216f4d0730388879518c31f72bfed2ab8e105fb78a06f9ad875e380f32ac2ee353cd5a293047d14272c9c8d046bb297be680286075eab2fe1a5ef43ef61e338bb7b487a788c609e8b74cedf4fe3eee9c2650444887aebff0c33649a23f25281f7393eeb6e4ffd211edb57a0a6a0d2ccc2eb00509427ad297934ead29d912b86d7e47f52b975957dec8a3aec22018f93248e0771094b471b590fc011cfc6681d8d5bb21ce58f87e355cf0fdc27443b05ad60084c7fce3e3d401865e252df9725c49875cf206b9c15f91269bc68ba2b9095e80beadf571b5e016cd8ebd2aaddd3bf3cd512787a6fde7e3d89033cc1f30e5bf20749985686c20c612c7348e2f37fb9356d292337d90f0c9a495ad8b447e031fc040dfcb46edf034cdcd7f7317b2625396dcf70f384ab683c8480a6254308fdd307c8c962a133d2b685fcb688d7e0d6764f4efe37b1e3dd6f6aed7bc247e1a0060c061811214a3d0dcc33e7a9519ac4d7f1ddb1334c1bd28307eafea3e3131b6f07caad0dfd03da229cabf9a0c504edda6d3bce3ef3e754d5d4cf078c9361a5fc03d8a1b49ef905630712609ecde497c1b54e008b3b38527177df60d7e0ce88ae0287b34dfffb0daa0f9ff632c779dbabd8edda87d779ca6c11296c168f6cd49105ab86b375369ce70a82a0c1e65338584db8d2c2f007dd9e28ff816c95d9c4c10bc439acad9a05fc90a4190a10b1a3400f97b1c34f2bf6630bf279183567ab24018d461817de728b1b6727fd62228fe3702e67310bf6f820483b24a43dcaf226005761495e717fe30e5292f051f82281a9e85a8cfa0d9a52680a056ffb53c53f041a7da1db4830a5b14899fe12c8337f1a00f88796541e37a85c7a8b6ae8cd2c0db4064eab0f390d15608123eecf7cb49292021d53a28016238073073f743de50e6e01f71dc1c36244724857c176c7340a8907a195b2b19f76a0287d42a9b5b407b570bf698b40386c641bae6f0c2cc72afcf7706fe65d9b78192fef1da8ee690f93ec8ecf413c06bead493b824e90dc8c5c958f888c11a6873764751d17f9e301998d47b7e4d1e00ad610eb772150bb77fb498ef0f3a844c7d45187e9d04db3075e6b9ac21daef6e3df7314c6627cf646c71c85b05dc0a0ec2ff4a0ef58331001d32d3124beeb1212538450443bc5ae823506d4077eabaafa414509e302e03b08335ea3964782b982c078dac2c271edca8cb798a68b974962753935a822c72307774fbca91cd19be4bd8b5ab1a81eb007c2498db6ca94e74ed61b1bb5f556cb0419c28bc88e8be8b8877745e4d050794b2b1a5c549585afb5e4022872b614c8088f05ebfd7cace6e82f9d069d74a04b67e083e58b1514cbe89bf5cac23593590ab744712f1c80ed6499e25ae85dc636c965872c7441b96af6b9e1766a4502d60436adcae780f3ee4d097c6b26591c62c10eecf62dcfe8b9faed1cc3436181f9096fd3e6546b8a683d04ae9d35a5246e26c0c3d67a85523552ac135e8fd74c4e08916a7051715b4a6d8bab0c88cafb55ccfd4d77684292993ef1a62ddf3ef00f0ff1f3ca2be5631066766d923ea5d45c04513b645471d2c698fee5c11449cdad0420191d2f6f7130db95889daeefff4b2307f441ce2e1d2c7b9dffe373a6db4e058796df6a4a485647a8f9f660adb6f35a9298c0f427f3cf212757ab50a2d470008bc2dd5249fec9d0f2f401b8ec7d172436705d79dec78ed38d3c2f9284413a07db64c092b429a9921c904aee753ad3fcc1c5779c2117fda0ed10a6ebf77d310414ef8c089866f7125f66b759d1059ca1c98ce2ae4d90e68d7af18d7931a5ee0ab40c025e00fd8c2bd450aaed9d6d16ed08c4e499ebcae6a45cebfba66656260c8d5dbb7a0466e3ec9f214327c2746c946af769bff38da55dd5ed308424691d0c1ffdca53753ddb7be6ea081da0b9596fa8ea4d72ff582b86c3778012f5005207f7f8dd669e9108306d477530008c43cc8cf08c6497210532f729e3f084fae80a8bba574ef14b654f503d66585eb2acf19e2bf1a67fcaa554786452e0bfd75f0d0bf6b10c066f6de7081bb5a8b9c4e613a3391abad46bd9cec3317f15c8d12100d4549ae6bf63dbbf3937a6278b31bf80a987a10f7000de1d6181a7a6bc633d01fbae3e7a41b8346027170806b2920c6cd8e36e62eba3103947fd45988ac07d05fcda94ab8708da35c84fa5e4cfeb59be89cb51afb39a3a6ac28af8172a547008076d47811ec74c8627c4d0306ecf1f51ca03229d63f31de267e7ffd299557f027cb8b4b8fced8d08561aafb32970bc3dca5e617a91861d1243ee53e639712b07ac23e107742b7316f184ca6ff68efed2ca5bf76edb065a0080df2443e488350278f065b68920db1efd041dc7663befe068b35da3c3e94e04dbd13d929dafa10fd164072166633844f21423095e878fe5902418c2a2152e8b78a009482492ee0fb521d632ffe50ed732d0005f9d47b57181f7312b1a41b1c877ca02162d66d601aecf6ca866dc9c8f2a4430a9b9bdb740f24014593c53eb244651b0b09c605501e3228f67b83ab6ff8fe70eb5a14b66a44e2ac7180a4976fc37dc8227d20a2007fb88b9ca14c8d298fbe9d7eb42ec2f53f10c8a1c54cbac585d169a11ae73c508b097333ca2830915f8b90673ca90ce52d2c3fa9a8a4d756a2919d3c22a67ee0d0478f2776bfb69796417ece78a52c998492d7832080f5f52ca5691e16b0eb305f0bf5994284bf5a83cdf3f14cbcd4a5ada94b0b2760f3a865ce2e736a527b108e1757d33ed4c7f13fea7e327207bbd437f2f9372f941b53874ee6249c8dd46066659d4b020e1edd486de54d73fe49a1e030d9374f0139a0a544239f5716d7a089b2f72002b6bf05886408c2064f7c9e82bee35e0d2946c91805c26276f01830e000ae9b9532053074c0fa5949c2fce2603b1ad334387f0bc64959c167da5860f1d8fe87a047d577be053459554790e247b46a2e0c537bac03440b9a0b49dd50168654f834fc64604a3fa582198f8cb184a1619c5ce144ce86033b14f520ef30f882e24bd959bc5f3ba43f809d3705fa574bc4e7b8527d85e1a6ac58f735e01074e8dd639aed41ca1d533d8a74b7e691de1dcaf11815940db6767cfbdc842c80fe4502989de3aef26a3b77340ac584cff691d3628ca727bed46be34d186fa19064aef1892b3eb4e5265ad2c14815dabfca977c57412c2ef14cc22dffb4e975a0654b43d8c4b288d4ab7b7a8766a6d37f5f534dc3c61063bc3d2e01ecb534de806e6bc1e003ae518dca85db46d1f3f5b1a76ac554cadbe80d83ad96a1ef524880baf80746fb9253e0f56c7eac147fa9ebb98c66cf6292806b83d75ea8bba8efc0f3859c2632502cba122db858f09e24d8b2332e0166848be6c09007dbeeea91e08c61cc0482496f4faabb08ee57b1826843f13bc204cd1d5d30fcfee699b0eb50603658426fb52f84b934e900fece01c168a5f0870a1cea2c7387f9ae232ddc40b611915a52f77d95e2eb5892bc2d1646387a1428f36981b44e38987040d0ab10ebb9887b6f0fb63cea6debc60a9c569bd56f38f5f68a57d51adb6fc0aa3a0e700b9051a49969343ae55625fd1be7d46f9c1c399aa82b6c57e8fe808222dff0e014e15879a6fc3c0e3d49c6ca77da12568f78ec40a3dd05e466035dbf987046a03bd1c7973f04d98c8bc232fc8cc5b65583f3944bfbe212dd961caaa0fe48c9d00f0857609e752c014e83a79631e866f86e7796b8b2501f82c81b513a4b59bd10c6f506c4bd45457f45a332132c9faf89ed50bf74faca6f79ce2ccc63d7e528e077874de714a5862df11a193a8a2397928ad3399a6d812511bcbd579b40871c60af3e87e9fcde3f04031f8ef4e1581b3792c20df1480730f57c9e0b56ab8bea30b6fe472c524ee3096a5ac53830d39659254108d2d31ee7700ce45f8566b394b03269a3fb390646237f7de1d9c6bb9f916a2353608d354d0ca77478f29557bda02fa89154b3184b63fd62d953d52f4e1866b72e38fb1129c5a7ec57532f0be18051861c0b9ca8bbe81d60a3f931b731603a2f2faa76b447ba2502f000c1e11460e8925203532a0b182b2287696a430ab2102e919f6c38142c685207c4d7119d00b6ce2da2cf249fff1298c815fd41768873677207c28e25bc4373f1cc32463c00540812b690dc1fbc38cae1573176b9e08c59c0ff6c4717d459f234ab209b426058b25e7789188f29ef01def5ad20237a3d0d2197da121ed2920b2852288d6bf0ce025da3764337443243d16c5d2dd1a6557df48c4ef8b6ab1a2c215fbd904b308be4ca810aa8a0f9acdd70fb3ffe66d2430d1ee242c4e1fe2c3dd06a7567f930d3119aa0e6843460f72e60c67844a2f5d1e501dea1c9d3892dba51f6bd7b55803560212c751244f0b3f97c2100b93b0f096d0194aa51d2f865179dc00e6a2ae058f9563a46c8ab11dedf879f079f6469056a0f9e193f60f4dc6e803dcc7e97f03d292472a20b336971cc84c0df1ad14384433ec148b0c78e1d349e78cf00e440c9a7afc466cc762d9656973ae25e19886182b5320bc468d71c955ed6013d38c04cca336b21e593e0b5574a6a5037ce4c8a9d7faa3141e5e57f6399acd04a6cc00e6a28ecdf54f8fe5be58832ef1e2a0e9705974253550c1a05e69c3c72e3d6506d4431b8b57769412492b1a9c9fcb7190d551d7199d023ff5d858ef92cda2c70551e3b7a0f4a32cb83b5ca111e4cd1005616d8464446c9e70d32cc39dac3d3c06753f849ae0d60d8655418e94c88ebfbedf0051727936cbf825928a16b0b33d07e08ab155ac6b7d07daa2a83d61548c3a27ea09fe450de550f0ee29cec2f03a08388a63328c23b1a0b66eeb266f837abf657b9a649eb35462b461bb533e3c2d0b69af1ee57a6b1df990a4574a6bfccca5da1c23eed9fef2a9225663b63034190008f42234965875731dcc76803da1a58290fe2e5e8f88f44d9bcc035809627e0bf6632a71eda38b9e4abf69fc3cdde99a897920136517cc5be2f3db7043925304ac27ac718da62b7c550e3e8a908831cbd0a5811b211d9f0f25b612811b7c7a08c51e7fd191b966d012f22b75d950e2ee11eae12de1dddb061e504c2bde0cf50499a643b46797e190635206a51da4a9e124a6c0fa78827db20d6e21df67441a0223e7cfa5ea7a34a76823550084d3b8a6a41ded0b321b6f795a792d4098d9960580d89db4dfca3eba564e4c0743d4e117e8abb7366fd0bd6a175dcd020770930bd8e6dc9856b3ebca486f38190f5a3d8e9bdaef525a4275b2cc6411cb06f2c30700c365101ce07900cc0b580556c0afcd0ee7ad0e3c42273ea776662081b9030c94a8e15630532444e843927db3b78cb90771d3b411e19bf7ab09dcbd3ee3ef0a6075746f5afce41aa48e77b6680310ae06fd532ca3b1121e8a1392a55bb9cd04c8ea8bfa4153b24acf1be0d25a9c1371f43d3fa02d6ee4546524a9e3a1c8610694519c16fabcc3940f665816ebad79c5891f68a357b8cc36b8fb3950ef42780bf0954598c888d722527f0bd89c856e2e9a99868082ce00d22136172aa2201f05a3d812e20cace6d618d8f27af5727117fe13159d7b66ece3eab1926e5a22f50bbfa6f0026ff592ae7f2860f78579057db8f7d95ec685b07e47e1505cf7674c0f33117901aae02d8cfe31dc75f74bab3acf5d708e725333a586810e5cf70647030998795eb6bc85216ceb58f1f3e966c52e1fd1e641dfd6a389f2f3baeeebe50eb464d2e5b3b0586aab42d33449638378d83c5e33b68a72c581a3f73f851e20094e0fa8196166d1a392f6318ce7571c3052398b82cc427ed01a1084074b85f40a592d22f3afa34d5b87c09804f4d261b491b8eccb3ad0b6ddf6bb30b83e611c02d018f85e808bfcb5e85388e1a80dd63252bd7e995ecaf60b800235386ee7660a4cd6c4c48adb98cb487994c4bae683b0c4d21e0e6b297d4404a13c7ae74c030f54825445da3ccdea4916d52c9da05c0e209838597688fbe1fb71c0f17d1cf00a07c909ddf3515bbd8a971999f0927f1748b535031249d1e5c61a97475c09b60d13b2c49ac131d2fe8c5b20681921adcfcfe0bead3db0cbbe9600966bcab0e309e0da71d8b3f00a0dfdb0a74f0337101c7b7666acaee601ae248daa8c6555060ead14fc3a792d05e35b99321429b1b81a392faf52e7edb4ffb0375b7f6c39e606df5df228ee7cc06b285a2556de8e5b7fac02fa1dbad6a1d49f89f23087fb2902b46ad07e8b68857543002ef7a69a65fbcd04886a944f8fc358fc5cd1bd8aa5087dc0d8e5a44fcf955d989504e837c846173cc1966cec776108c991f097c9970db3d8cefe26db33fc78cd1556b6966f420c6405f8ae4082c62151af10e7ea730fb1e7e63373d0e9a8e0ff77bd4a2bf63f85a2536ff3402997b7dffb20af408409c391bc20afc1f86f1aceb81b04ef5c22106a24900cbae576340c191dcde898018989906d357aa9c9bdad2b288bee23d9c77ecff2bbf35d7f2a6f097bbadaf50a6f1ed67abef43550ac80267233ff930e9d7b313d1c21745854e16813fcae820e8f4cc8725769aac0e6f00b1c862ffdb37dd3f8fbc62532bcf667e1ec86845207077d85868156d541ccb0e1ebc9b96d63660b0b1a966e994e61b572302f88e908f85092fce00b56e943c54d861705ce9e0e5531f1a66bda27078eacc36ef3590eaf00c63b5c1675ae6ada64cf378e777e7956074b04a813b34fd929d0acab10030b8f4d6a68cd8d7b835a83a6b0ba7a6afde6862bf328b62d67a8218dc20f190cf57e0b5e0f18ddea2cfc96293d235e5943ed9f8afe5c33746df67e6ec905050a6024e1d446198252bbf4014b5794b8a7d9fb74873c1dee6c60330ec1d31bc60dee15c391b205f71a62da15f7dbbdf52463932a191884388609d9bfdbcad0d0055f334ae6822bced23d07d303cd35841aeffc65388ab80fcedc66461261a81b0dd8cd34270be2542eb2d4eabcc42a9e083a07846efa79b351db493c5174d84900bbf4e442660c051ebe059550e2c67a7a8434faab10c6bfb2802b1e2f04cced0519d047ce3c502abe2ff94dc8be59f6e415016d2c77f1b54bfbffe179c9ead70aec1fa21d4a814abd41f7d5d19bc6b77f4ab14298a1bb14f7483197fff2b6390e2c3230700ff95ef79681078d49f0ff3a8f51138771989c3c1a8e18e13e49a90a3fcbc0a7b8b2458c0b6beca04c5dbdfe86b538e57850222a24eca0476c73b70654f3b8e29e227998fd54ffe06ad51f831fb4dd0b07258a17a9d27595738c060b4a087c00389c596fb33c838f4c7581663317da9a3a941056d6aa000734e380005b7c550677862c23689eef181e8107d1ff986c9491de02d8f6c001789ab222032674a1feb232ae673757ef59122249400cc1ba29a953815aa8da9e8275b3de0f3361574f998cb95a4087c880c87c8593c24d82772867ed9f2437f8b2465a0b0e13e36a5a15f56e04f4e861c1dcec4913c789a96e556e1b8155fa9e472c8007024f2f0d7978a7aeac7fa54d59acc6bea8758dd0b215a240e8fda5b05440fa1c0c933d982cbcb6e543ae08fb82f33f97a0509da0f42ae235f42698b1244e6c9902b5cf3fbf95688c9ed3ac06b5073a03faf591624f4f4e76cec2a590da26d60306e34eeff5b3f27e6d8cf3ad0dabf417397883c7505b911519b5bd8aa9f9d9930c720d534e362a1582b9e3e008c339d43e1e1c3a9f26cd7800cf4752491fb2c70a3e49b2bc960a44168bd04284b7abf6506672a29e5a5b42f27ffb1596c544af00709b832bcb891e9fff8511d0c75481db9e7a0392f16db45873fa1d45d7a85f075d05b31ff42bc26cfa9c87a6400939e9f32a7388a867877de470cdcc39e213029cd6eabcd67af7bc6af0a981d403f2cd2a863fcb3d31cab9e34f60115f5be00a5fa74fcdb120cfe179703ba26691838145a2c0b1043d0296d27e88f173f3160cfd1fb21cad26e39ad6dede6aa15b40cce45443a1d9b1de22b9e9c63ac9dbf4084e1204fc9cd654f68572705fa66eafb934e924f64682ccd4c65cc38cfdb956079dc39002ae8995c740352ddd5b84795b53a7262d231d2c309ad1888301920408173699be4eb061febb4351ca82398893cfeacbe55e41d7c2a7046846ec0b940bc6d1df129c92618fc7da7d8c7a4f5b100faaa52ab538d592e7d38f446fb005032356d8a445faa7d655efe6d6459d05480d88472df5ed85d3b34ff34ba6a59906ef7b7849802186ba3c50abe2f2995456da2803cd96d0d97478e640942a63e603e22f2e89274c79e8fb3f5bbdcf3c91426510988730ac9637ffffb660ea1cb70ebd66f0563595214a563452163252b3db9be60d5e129f90f55bdcbad2300c780ba70b30678e11e349bcd4d5b5a80ba85e80162dd08470eb7faba473c3f4605d0c92cedeea55f423c1cccb7c0a9a2479671b96c9ea1a3329c1df5a71b9011a3a0941c3b646395255e0e65ad84ab2de4a8e04c54995dba0a8c36bcc4d56971e350b71d7baed141a9ee90672ab3eccd024095a354915bd6a3e8e6aaba2194ecb8202c3b328b8fbc2b8587b75d0ddae8edc5b9129f883e1ed4210358a99b74fd72205065f05f72ec6f988ca2a5d713761c56b85f808d36638bab082c7e670f578b50f60cc3cba90bfbd2868ff15909e92da705f38a6e4ba0b0cc904a4815930232600592483bd5d4b550eeefd8a1567c9e349159adcd3c41adbac9c55ba8ce494c10569410b9aea3b33dd25b887d26a618e5f3bd323672a56f4cbcff3ae8889e7ce0aa2b86431718210ef6a49cc5083fbfa5ee538ff6b95fe4dd7cc6d565228f8bc0f9e3ab33a4bcdc3c49f8f15a8084b9526e874b71989ec8be22245e65944588c016cc701f511e4c5445eb7e40dae1011769be29ab8cc5a3a67cbbdc60e35f48c06ee90b79a7d05059137d32fc78ea7e7d302c616a5bd1d88fda2a6ae963f7a5f02cd71f007a49718f0afc04f7b0edde7c517cefd623b89bd6b5644d4afe353ff0be7ef516ff029ad53713ff564b808388cbad04d200f396d69ddc9f152856d930fb36ffcd1919822df876c3a43c9e867f69efd77b5698cd7af8d63d1ea7a5b0d030f6fd54945de51a6a99aacf4c1be292bb858fb44c2e018f62f66d78fbb5a5a0f5f8bf74e1cec27f4fc3236560949fc57577978c2f06284e4dc5bf61b501e650f09a314026731c54b61d84adf4d9be32e88ffbeffd4f094df5c5f0068d13fd40c35ba9e69a21063aed2846db36ba7b0c6653c1771f53710927bf5b58faf7fa103ab86d54d4d8b58fd7271845a874ac1cbfeee7bfcf0b3e69c466d80dedc808c0d8d704b4a52025b34668b8bfd8d50f00eb2b4229f7c4a4c6a03d36771b093170f -generate_ring_signature 52ab38afe83396f4a7abbbe478732d39260c8086f1b221f37018ad83a56295e8 52144c557bee42c63d3943a1da22bf53c53cf47e18e39ec7618060fdfa2a056f 113 2667878a43543a286946b627dba44ad682f51a0ec0dd5885c0c17706e1f27962 56070ef37ef631a894808bf2998c18079451cab0c36076b94ba7046928c7a1b7 09d61f61e982a1e500603b81bc56fc727b7ab3822a8af511a213619776bc559e 3d16d0811f8d8b1ff564124ac0735d77c2b62ed3339a2542deb20167ac8d78dc 8d1e73a58271f020e21201b77b3e1a0d5802960cef0da9c30f88331d1e53b7b8 b15c3a90c6d12c50c12ad1f1cd4f5cbca77abfbe26dd1003c5f92d256b7d9a2a fce4121de27006176bafef1742169e769f3a25a075b413ef0c3f7affd5150561 23e7a79af125e2cc0907abc7b61ebb2b6d712691a6c556474ca79c1cd2873c0e 1806559d6d2e9812dfa4d97efabbd8ecafb8331b2a836e8b94212ae21d9e935d 3d825ca551aeb017319626965977dac767f90994d4574ea52b0600086f745c96 9e5d692b5e82670f6284fef4efb6a3dce320ca9644126d52782f922e2f1cb62d b04d172573b99e1b8074d362c5f6b997b05ca74a5aa4d35c957853f9078ea90a 451d26bdd2e49368fca9c893cbf9a2551aa0bdb1df3d919a75f16da4615ac00f 39123ff66a0a8cf47643625b997f3febe9b843028a733213f920fcb0fb224321 2e344a31a1f4abb279b66741e22b00d72342c93ddd66332b9480f38ad010dbf4 174dad431a88a820abab2a8ddf30bacd6c0720da30f98ccab7c821f2ce13570a 8fd6651dd86f87c6e9baa019e3222459a3495c481b5983bc1f3bdd43600538d4 70bd22972b4e8c895d93c5313a2c4de3f096b2832401b34492d8b63e4c828b93 724ac189a333456efd5ea95bbd6c3174180204a0541f56c9d3c4e82c1b9a9430 ee0295b969e97cfbe6d47f879da1a789cb27f9bb2af514fd549b4c8d8db67ea8 6516c5de7a016a83efaeb52dc3810e147831cc6a7bf6d556aa711e3f26ae74f1 3f8aa4e1f31046011579a2efb2ff2e98c2e94868bf61f529b28e0c9dc922e65a 40f502a1fc081d3e0870baf688962eaeb053998be9e61627a99ea713bedb7d33 f5de2cbe86740e20007d273d240495720423986ad67d13022a69f67eb65c9db9 a72c9067245c4f1f7d3c6411578b2e02e18c373f78957b0c011d1ba817d5fcfa 2a6f3ed6fe0238355cf8a1bbab5f2c1f5674c2432cd8c964f4bde62d1f84089f a1be89b4e0cd03a7080617e61c08203f935e63429a34f8ae637c6290a5f855a9 dc25b39ea362c07b69225919ec631e1de3e539a0c99076421a03888c136040de c42663cb57da0d67ce5e40583deafdab17af7f37f4e9cacac7be29510b77ae60 57e85e3d5bb0bfb51da145a2345412b3d4f1bef0a9ff125c2533e3a76c2fb261 51d82c0f6c42340c6f37f6a4d24eeddde756700a2a674f0e5745b35b0493cf47 d6239694cf291b89f96ca1f448b250193f738547b70c7627a72d6d8c3edef2a8 3e3ef92d08a0f37954c6ada45ef29204a7dacc626c7181d7613f2fa613a7d515 479b439e8cc29f89d9dbbc3acd98fac89603d262b014a2f876ae4646ada1d401 ac9c823e44caa76f6d0d2ae5da6684a6fe0fc4c623cb28bb0ffedab0de052047 bd47406403e535790864051db0c1c2d09b0e7a0fa9df52d23036106cc5eb915e 19abfae288790ac7d77c0581167f78415897eacc19ae8d537d118c47fa2b1553 b5a5323c096b566ec9e91eb9f4c870869872499205d05cf3d7b58811d60b1f58 36d46886bca44dcd834fa408bc22275efd1264644143dc3fde9814b06d1ca44b 758aaa67d8781b59b605c687e993e1d43913e3693a351d9addaff6a21cf196f0 32c1e4af3a5597eef97f47511fd377a961dcf5e3ed4c1b8ffe981abe8ce31a84 ec3619a0a1928ce8907e344b0c7a8e87e15fd53ba8693341138a5714442e2c34 c6bd33f733cbaff02918e91d14855be7966fbe29a04b6149833010293b04920a 6b8a52bf35bf9bcdb80f5c22fa241b7342b4f6bbe085f78e5096f0647f0298ba 3222525c78358332d2571622030a2c91873a8912f815486ae7f1b38418cccb2b 5ffc8527b801db0fd1f9fa568e6fd8915afd4d2a12c9e760f8a0e3f65c13fee6 65cd0954290ad98ee8fc0ade4ca8931b1f6832199e69496a57d71b25e0c4da6d 519dd0ce81bfb0e2e2aed5c4404fd08cc5dfc32cdebd2c4eac8e8341a99593dd 028506245b4782ff02e531921ad41f33458316d2a04701949c9a1130170f667a 65479d0e3b8c5e054a42165784f71979e44c5ec86edbd9360d364bec827c38ad b056a8e8159cb51dd0ff6854f0b5cb7d73eb6af8a5056f7a157000fe950956a9 121bab1f2128a355510aff20a2348ca726015f44b14247ce79d17147a4c4060c 67b7dd5f52f743bf4421b83e735123e1c17173c562bebbc92f241f748c45c682 1e8a956e74016f5431b773efa5ecb58a388e94f91b9a5a4d928c90b987298361 928bca6f3ef639fb399620438c215df701e992d50c32a7d519c9c4029777d8a9 4b928f62407d82ea63fe4ff44757b0e2c99b3d809f473a2d9856a4e7915a4048 2638494a4220023d7abb69e0663e321321a39f10ed88170cad8c098adc2b5762 b4e4fb545e5daad738d95438f9caafa048eb5b7b6cda4984f0d98b218f8ecab9 4e1da4093412883d96f6080929c73604c9b918e4b4eb3263edd50d07cd370ac2 1825bd87bd4c8621c5d585e3a150b810734249c5f8b98826d4fca4fe17a479c0 afba4add454e41364dfb8f3f10e613f4379125837d809f9617c0c59557d8ba06 be6c78f9549f725e77166b209a3a62be24858c6fa6730b751b454d8db46513f8 d72dae253fef5793e2c4b21266aa5fd4bd4bb298ac12024c3136bacc698bb5b7 3cccdd128fb4279cdb8782fe4e891c92b9212ca7df38c1281a7c23bf0488c7bd 38d08fe57e0103171b5000d5f7d6f741eb51c405dbcc7ba351ced61d610b5e0d 7877f90fcf24f4cf3fca2f456e942af7cbb7c713aa9a26a437870bb0dff5adec ec4175d3e5369062603878430224568d1d9f6b01b48a0377dc82f66f9ca309c7 eb039d354117c3df90c53e9eb0492b4cf2e4f6b4b57bfb6cc809c22621edf016 6ceb1f244447e6c4fb2f4b7abebdd227271ae511383515241e146e3401b47afc 65cb32f44ecb9ce88d08bac89c7b36eeac2e52fbafae9c104b65851d0d3fb689 7ae2db115d82335fe2d49f12ef8248994b958fbedfde2f99dcae864daadadbfd e547d52a6eeb118a7cd1147895f5a75dd0dfca914d50706f6a7033235e3ba07f 6ab9a84a88f767a1cbc69b2740c05acaa9fc9d84ae58cdc77e01b0900cb19ed7 601efbbfc5cb40884d47fba0a5e1e5750685788e4225ad69319f0dedc8053cd8 151f98617ce7dca0ac7bdc7910fcf5afceea4b8acb144110377b458ee877eab7 7dc10dc41ad38ef8c879ac0c434ba7dfe0c4ee458285bfc0b07be3127c970bca 171ce0ef0830d4ed99f42e0c20d063ccc3c6ca50b747b36f24572535d28c77ae 3f55caf66c98c9d773a90472b2432e6bcdd84a286b518a3f3f95e2ff104847f0 98ac27c0ec172728c1284698b62bf64afcc2cd1535ab245b6ef9e39e1a1ee486 38a2e914fce5327a0510a04ebfc2843e5ca25b995ec616bc1e214df14cdbb2d8 6ede2050ccc3ce325d911fc26311bc74f9f09f51096acb61ffff4b751705e68f 527e46d547a1337da68feb3065d017f1fc3d37fea430714287ac3bf13de5e43f 8208fe6fa4af1af795df8b07f36dcb08d87f9b5fdbb06059b6ccebb6cea006ce 41cc08d2fa9ca82df528502af00d1d8ab83840d3961cce3a000909322c393b15 c04393bc4ae049524110432433f0290f23a88dc4b0bed266bd3c139180f4571b e41fde50f6a402f874e366619f17cf3af987c3641720207c0e48b30f3321d462 d680c870d7b43c6ae308b818dd6d14b29758aec61195bbd3e354221c897f5458 352582605e62e595ee051a22e47c7f10c86a0ea59896c907afd853c418893bcf 39b1b721c361d5cc7d3455cfeb782aec7f122348a62caa0d67f4fdbc98665503 66e0b54e8d0d0b0b61a6641685c1f3acbe72bc1e55254d88a2cbcf50399fad68 c3afda12547982d6afa86121d0eae5a549d22192469079100f272ab6d8831338 3d8021bf75cd1a3b64192e532e21744cca23a32a7a50b459b635d8cfdd6e28be 176079f943ba5100d89a6f665864407996e7ea1d554cfa79322d38300fbf3cb6 735b236716beb3d302ad5518901b9a523d51fac099752fa0c1714fa342ecc944 d6d69f6f715109ba6b81cc303efda0abd38a312f526b49bc058ccc44d076be32 1e2dd2d69008482d8e7a02b3d026e549d61455b1add013bc88e131dbae129b16 e02a717aae13cc6ec9a9ae8bfeb952c42d8fc709233cfd1ef7ccbc1bbf912bbf 009b16fd9effa67a4c4c8eda2b15fcc67adfb5aec379d592c6b80c63d3750a9f 40cba48b6fe177037c2d2f652e35278d5aa779ec0e37a01a3338154b0109c7d5 fa94d28721ee024c3920937cc597b6e440056d873da9183a4121740079e91c52 b87e5b2635dd6e4bbe8d22f83e55a9b088fc79bfc79b3866ce37aa3be95a4783 705a31ef4484a1d621a26ff0b0250ab8f4b4feed12227f709c41b03aef4739a3 5c424ca54db641680633f09638dccf23657a0fc34f09c2ed97b3ff0193c330c4 f00e3bff74143e2eb81b5aa10d4f8e110d6f82c12a6ecd870f786d120a863ce5 2b57a48a8c801c44fb5a193e27b51a3b63ba879a68a603f282ee29bb06dc7b20 b02e81daa731f503076e99d7e975ccd900b8a4f4a20768e03225a74ee7769c6b 2dbc9cba9c5b1c99149fff8f97be8faa42fc16d0be7bc5ac77dcf8886a290e32 0027178fea8c180bdedbfcb2bb7e394185b37a42977afbb70ef8cc3f5b2b1997 c417798c3869d3bef770f05c7eb4e89948bd4c76031dc429d6a52fb199e16b02 829c84deef8ab603af8fd2a06bdd0daeb12820c32345488d074fdf0c8f004879 4be25ba569f1b4aa9c55a3e6dcf232d3b3ce4cf9990a6f8698b24db41ca20eb8 37165ce3e5c4b593456f947b9813754b44e40e8407b81178db50716df2352374 b899ab2a46ba764730d7a822b6e24afd6d6d276c4a73ee66fc39eaaf2ed57b84 fae3ccc4f506532923a8f03d2d227f60d7870ca2c855098aedabd89abfebfb04 108 1a5ef4371a62115c4738ed0475f022b26564a53f4fe400828c73b632922d9409e44ce61e1f42eb35de0279c8f2cce7576937a66ebf13c317ab8d1e16497bb50e8cf4a3ac4f69616aaf24bc2a788032fc98a81e31eac6a15e7d51a1c356e9fc06953254e68fd218334d1425d4428a417f5a787d848f95df4fab09b3a46abca60db13ed3720b4ead6923126bd5d801fec0ce795ce4f2e7d65cfe67045f1aadf20e713db4ace52a22c88d526dd37bbdb2debeebee5cf8a526bcb6307812d6da5105f8f5271fb36bb1aa9ecad5639d5d1890125a34025bec5fd3d3d347defad9050ba5d4cd28c1b83afafc7383601a631efc3d3e7b8d9324d9ef2e482af55b4d00005e2f48dfad0757d0ea6868f66fee9c06a75f8097c417bd52b5f3fb8688d55b0142128c7814c5770e39e0808fc5e683953a2c4de55d481802e53cb005c16374036821eb2b0ad3cccfe05880b051e6ef461ed4c99a155152dd5e4d2976837575024572406d50d62bf88713cd45406e59b96fcbb227f41b9e1d738300a9ab504b02745dc8be0d830b453eb453dfc1351396ae66e50f65468cc40e93d58b5be92805a11c74feff56deba891431fe7e9e07f585a266c506fd79c8f7f6011375a5220991a3967e449e92a90b1d8c823170401d49e721e433af0a58d7e46d3cc534880fb8757cc001a8870309ae882f765d248f7df51d9ee0d0f0e3338d01c20fdaf4007c83cbe4188f767a8118e855a805b386ab766529b86f7abc3bb216412b94d60bca2d0be6bedb4a38627cab5c3b23576be308c2d6c261588e4f2f97907a472c028345c9fa3e9994cb617cbf788faf4c60efe7b4d97f9a88635d99b1e9874ae4017eaaf6bb0e0a508a7012a4aaff74f55fb306af3c06ba731f53f5e3496c40810f93afd0a700d9635c74afdfcf71d3256ecedcfb42752d2409a43d8c2fb1462c0f920e94edc3e3fe99994a5f81cdcba5cd20216d6898e76de5d92d708a8756bf0e93737aa75140672b92cb03cd32b276101f3f11fbf4a99f643ffd111f7269e409d9d3410d720b7781d23815d4cff5567b6d4e46228465888386e462f0a00b4308f55cc7c7ce54342b6cbd055d91d1a8f4e9439d34365feb193873ac8dc89154083081c38859913fb9061b781a877c7edf186ea6b0f2d2e52d8580e908b39c8b0621fe0ddd6977d109f9e7358485f9f9a52c3809611c646e518ad1bb8ac253db029fef063d2da49d4c2fdefc611fd41c286e3adebc3c10a6638e2d1417015dae0257dedc7b75644fef8954191eed5fcb84b2609cdd906d0e819a3fc1ce5041d20e360435c0f0f4030b2928eb9cb1bc466e9b180c2c5c496b6c738df0d3060bb10ed00cf5a74fd092bf8eaf5405f8b6dab8e769247a172293b4c031c062506bba0e3aa9ba72e1711c53ffb12e91ee280e357ee4d8f3cf7cbe521b804c7024903b0dd84f7a2c7b35c4d40ccbf07265b043fcbe60c5575af5febe457d1b03e0317d004c6b19add44caadf00f38c32f4fafee7e79ce7e1d88ac7df1ca9222e0975d70d36b8e303755f8281563cd489395db91ff6e79ad496088aed0f69e3a75a24350e2880261e04996a0ae38048ab94f55e7cfd2b8b626f0e974064603f9de1cfa10bb16e4d30c7ebed0467cc763f9a11bc5c365b95e32afe92ee602f1bd087ec8f0779cdd310ea136433fdaaef52c8b1790aab02901cfdb877f23aa9d550c031bf0ccefa6ae93f5a7f5fa29874fa7db6dd9cf7491021fe0d0d44f7d2ef908af2fa0b017f313b514f949751a675513883c675c3906750901ae6b6c8b606519b33b603425999bb393e414d361f2eca1f78ccaeb595a90ad0f54736dd52f33428eba701cde108345e261414b0894a2dde8e608749dad05b53ac95a9971e9b1558d365054ec6b2c2bc3c0f19e626d7b28a1827972565c4a27528ffa288a5ea2475115e0b42cfce09fce1c3f9c3af277a5178e1ec17056ef7503d61d3eb6eb8a7ab30430d51569d165736fcdb0e2e132ea336e01e4cf4c601ea6e8e87dc3fe2317c4611052208c9db676af426791d8a7cde51314ee458551b02f44e54960d55e4def9f406eb755aac9bbde7fdd13d8c697149247150f8f6601c27b4f44653662a102b9201edeae8fdc3f7db4ac6e486b7647a496f1f3733163af928202e87fcc2bb6352036b47ad21fe16846877e873f082dedeb92698a418db3ba6f66468d9f7a9d9420266661dae496379488b67bff119c0bf8bf76c3e1c11b3e5ac4e28b77ed9f99c0f79232081f2e49cf483d098e55b4c4c0063e44f16ff7ee79ca87e0791f9966e057dc60dac78e8033b4c5112f7d1fc487663394d60725f485885961a5979a3ac0122204b36d47c0721e1e0f02cfa75c9dccb1d336fa120eeb10b4d4f4f68e5730e3f8bed25f378742697bc7b88a50469414d42973f02f49d16a2d83a7b9c998c0768ae277e57ec5cb2f9f8be5e9247bfc66be5e8187902d0d96571e2980ccf3c0768e52ad84d08fdbb6c8f48df91fb5d7a3cd7434f260a2a3c8d9b43c9a77ff909ce44c4edc26b5cc82ae22bca3e4231044a22b31e396b803fb2a03e9e3de05d0c75384c67725a0d962540169f348309d00a501d6d05f9f1e44acfebe40e21240087813f2649e03707797db2871da837d1d5f187179e8fcdb7bb1d7618dffb2605bfade539bfcc9c06c8167cddaca619fc400f0412b4db4ccf34cc51ccdb3d1505e0b96631a802f937e3aa2507afb006e5dd996880279e6c9b32a6d27454394b06ba8a4050e39371697b019a2dba3c494c579be7879071552ebd6f19a947663b05cd40ce1eeafb7c8d0a374735c4aaa6611c3abe4cd648219416eb2df625b4950adaf0b3891a8286dc9e732fd88da59f3a4510777da9bb8021c2e947520a716c05dc033297b8b210cbfa750e12489a3ec71bcf3a77aec537825a591d1c40a6e30bc471ccd02ce021a7b03fb5394d4dcc437ad55e6c88c9b7a441cb085da3583c058beb975d8b5544ac8f3c24a73010b3918cf3359425773f99e787c1060a0f3e099750919f5c779fa46882b9a2fc60bda1713ef87be883986e44e6e3f7efd8e60aa97970164451054f3a8c7b09100cd62d0c28de11d28a012866dc81beddc2e30a1a98c6eacfb7a6629e2027649268de17236194551e249b6a5864be33fde6ad068a832b22ce00ca7659a6e4497fead24f915eecdd73358dc87b2d10049afe46082289a6d84121a1e9f91048dd0c54949d9762e38775e71faaa3c1b433859266062b633f727cf2578d255f1e593650db51b64d4fa94aa63744978a6330290fd0025f2929ed346288aa5f405b3160ab1381ec6b16d1c7137187e9c603e14c89140bfb6402e8e72e90aeaa3f04a13d9109d81b19bc171a08b95658d2e4f83e9bab0c3cf7871d77ff40b8b5062b1b7b3742489fab3f4f8b14ef0f8372232e5a559c0d393293d9d70518b6b2cd4c9d969876c239ad55c349ec8976e9c03fd21c42c90f7663a834846650d7d7b143706bf8a03c247800806b5ebecbe81927f6459bdd0a50effd74f5d581692b6aff20a94e7046dab342a266a5c9259d8100cf9b4446046c6b4e747a1e2fdacd9e454f6059a35b4bc8ded4912f0001afc3e0be9882b702099343a596c45317c8944fee535abba364fd13910bda3a07781ee2f671ee0a01b531e3cd32413787e48785c887bc7ccc8aa85c18af5d4cbc8629dd3eb97806098789c054a723e5a0b7106d0a7ecc0755608c74f2423a701984009bbd30f625076beb2dc8b99e3d60701191992e125e635c0153403ef6437d6cafdd84070a610bc1ad231726f7aa0e608914509da1cd68f20f71d2cbb3d13bcb502dfeaa65fd081a837d233a2fb9809e8971baaa1466f189be405df4f402e26d0f28974547290857a6cc7879193e54f8ac2dbc42f3acb16e24f3b6fb8eae215a439b1bdf6e240723a1dcd6a8a1f088979fe7076481c6a3a54c1841c67abb4873613858a09f1a0e8129523d6cb0a1d2aef5a7f3b090390a12b4796ed1ceda834f9c4997750a3d00eba2f76a66ba699d20560ff27f855edb77152c8551c5bb90bac6461105801703687107edee576299ab5e468f230cd84309b5db5ca0818911d91c7fe988272a08c52ac5a291e45e6890a52849fdc5ef90dbc3d93b3c0ef67305712a56af8c2203e337eb974bba80feb7706799e77cb5e3738c9c424fc820277055274e24f5c4016f165ccdd3e46eca7e328164369bdc95c68600adaefe90cba45ef24465740508a2f8a712541d6fd3631d1ef1c96223d5d74210836256ad28fb247d110b4270034c404bb4248c5b0279a8d0ef775bdda7118925f25bf1622bd952bbce96522b047091e52481d2857532c2d30e0224c27b15c9c8a9532695a54680bd387c7f650d4f7d0af3912fc3ad0abfc81e4a505d728b8d2d9b1013002cc9f99bf5a969ac07c92c62cda3271262c731461cdf2d9d5da07081c6ddb6f4fc4b19c43ad0127a032389eeade1076c02c9d10cb2cbfac86b81a005fc89441a58613c2016b25cb30694c775d142c6923094462751cbf5a74367d11eead92bd18b3fe39e0ea2d63c0f9b7108c4641d977daaf015558a577bc700a6260a62d1fb6e13909d829ad54d0b7904ab823fb89816d93dd8c5985da32a7d91154a1222259ec29f8882fb1e850c5f1ab0e571da4661ea79ccd08cf91a43c3cf6b4841298760e89c4e8bbcb12a00cb9eab296e40c90404c8180efd65d1fa65ada931f3d9670977d4a4533d0875032d9744af2e148a05737bca54ef678dcecc8777a42c0fb5e9a519717f05bacf0761595651ffa03809c719163add0365451bf4e12dc9466ea51f80e8029f61af0b5c57abf94b1366fa3d686abeaf57f7d8d97f817e0986a4c97a59d5150bca3108271177fc026a66d9bd5961a2ad61bce9d1800c41e6ec76e5080d9d2472e7210d828a23a7a784bec681829377af5fcf6d232bacc453b50b13eae91b7d8283c40197ec181c777c907e3dc5aaa61e581e037a66e6996266f2b14d48c108587ea007d3a118bd8e4fa7658f86d6a73468907d98c6c5c6b4148ad6aa1c082867df0b041b4ed7eb08ca6ba4b92f11b54c3c2a1d176c4d135d020338d125f659555ad706d50ca12df34eee61b990997a26fdf2df2f003226694097c431dd0f1e12f2110c1bcfa523c55dcf3ccc9b6d93bc6e1a99ab46d1bc57e239a11ed3f20f3ee72407beaee8aa6e515dc08268e0a8354ab4606269ff6435f6720ddbbcadee5720ee01fe0e6299167fd1b6da222b59ff7f375efa176f3de30e736b703e0975c191e604b8bca01e671dad21b36271e63e8c7203fcb83b61069c82190728537df4f8570bf49c88ea1e4608925a207fc998700851a1ad3b50909c5cb1c5ccd2988ef6f7044e9e9c8713df6823ab7607ede709000305930dab1f297793f54ac2ab4b8397003b48e6ee50adf19e27d928d63c0792fa2362e3e278115bdc0a528676af00820a6d39e813ed3898c4b0c52fcd5bd91a0ad9b3606cdacf9635080348fa074b6d0dd9d1cc3fe3b0c4d606739d490986fa3b20e6e17ebc208f3a2136de78b9bec308b74148b7ddaf59d650ff0906fcea41d7c04ccf60834612867a24bc4b7c3013036d3d501b933c9aa8bfc4fd92db6ea8982d10011c7b48cf8d463466264ff2c904cd04cf8a2a684eb6358636883cb47b7a17e5202bfdae039f29fc5157cbebcc0d24d47c1d64213fa64a17d69b25dfeb926a7a30a5ba4a69c3dc0d86226cd4e400cf06fb56af9342d892d9c60c395b7e2359fe40a16006af791fc8d8f1d4ae7205d63f6e5f2589c30bf87a12d86ce777428eb0be137ef96b46df6a545726983904a78a62aa9a53e10f685fbd8a72c77dcb99b5db596adfeafb86a66d2ab48cb908ac2419dd4bdb9743a56effda54f9d202763cd4bccbf974600ba9774b410c0c01e60f890b8d5cd85fbd72deb9dce592dd0f629ee6d47e22ebfd65188a59147e0a5138ae8abf6962dc5a617e9a8ff173f51098ba5052d2416accf7625d5d94df029c38119eeb6f19efa18debcfc986ee9b8d4e01d5a6d68d953594f3bfc4cdf30bfdb5964d7265a52b3937fa49d6b6d971b6fa93389c0ca677180211a0301c190272b833b16d18bd9ea3bfcc675a65170ae6fb487bc1be44f2547a0422867bb20e295d27df2e8658b30de1ce16d8949ddd3b27d04251411fca62e2b52230d3e408444729a1ba2e421c4145865d8b99f9b873694453d629233cea095c4c2e1f100d17ed670f8a87a66480ed3ec9f32b50b95b38cc24bc3b297882831a0a70996f0160b7b0750e6ce880ddf12d50738651c02d08b5fae1e78ea4618d39ec4ec97f06be1d7eeffcb6d87e9a219dde2e3a9f5ea4811ef5e02baf4cc69f43dddfc2240a4a51ff4671d4826d2a3f592d3795e0d49ccdd1e19b30e44343f635544d70e6095ab184356778cc98b32816756e0dcc4a3e9b0ad18cbef30aa93d27c242c601084a22d0c9d061c25350ef592e209b03a5f4edad466d45166d54a7fb02294d6a0fbf70279b0149927673d629cff01f95669d7c66a3e52b39b62433f2f81fcad00045fd498037b5fc8da56ded0216a66d8cbfcddf2adf0baa6ad45913fb8c6b0b009ec2ebdb6bbdbc704e634288ed6f644e9eedd23c9afc74fe20037a27016fdb05047777eb66e0c0950ddf98e26ae8e51051934e00070eb3bed3622781dd2023050d00051ac182fc638afadc3cd95edb75c80c38680d43307b7288461ab76f3909f9d8fe414fb7fb68fa84612fa4c266962469dbf8745f76bc0d2e0ba83b60b00ff78c9ef8be32f69036bfb0849ef9f32d742b3693d102905b43df77bbe5ab070e52df078746535674b4ee2589f79e819f85dda9dafa3b4101beeda425c283870a95767577553260ee68cdbfe364e63c0b3372847e00fb5bf3c817dc3ea7182009bbcfbbf9930323993a38df5030a9f258c7f41ab5b803eca4f1245c3ae5aa99038cfc0cb289f1b73b4ea0edc6b52a4acb24fa2e1bfb5c401d27d8e0b70ee1b80dc9698285867cbf7b1d1ad5bd23b3a1d135070e2fe8198b9c3eef7c3e1badc50c1ce39ea8251ef0dc91e53724b4e84e0183ef753df684c4b460754dacfc8b160b8f34c1c4bb1de364353e8efcccdfb26d4340a1a5bc5a238e75571eb96e43030b8358de0d88327d6f112cd6ce0f640a95b564ea7999888466638b0bda438b580e950c9b8fa38899f091783f5c0e686a1d306b0c764a78cc7c0a679e744d813e0238b4c0562c66affcd5fe659c27c8ca29f0c5759ae6115069575e924ce7843d02df8412079582e12e2be58019fc6f22456b6367c9c9216eca68d7bc392f08170fd0f67f9a142e98ef570dfbf4a7abf9d01ec40dcb7fe1594b4edcaabf04e27b08b239643e5d28923166119665407586cd44926bca5671710be5cf7bfc6173c30ae8a8d5ff90f8e78fe98fb2003a04a43a7d3ea311e808546edb2bd978ee349f0bf1cae6bdd5989a93a55878ff144836a56dc7325834b1f06f0d74a85ff138670770e0b67a92942ac86936dd20b1dfac9ad4dc1b2c5dc459805f6afd2b973d160ab0ecf481faf1bf274a6978f9dcb1acf32061005f8d38329ff1ccd828c107c50674c77fd7f4c784a81c6a6b4b31e22e7be4148bbfded3cfd478f8706acfbf8f0428b6b0c3c6645380a8e6044bba8371c18d895572e17b204d8e54a6e687f9380236eac290d84acfd089ae8fa82c995b292950aea1c188a0fa35223e38d73085091a8c8862a6936b34a3723744e1da6f2fa41dcd912b14061b8de4b19e5b032309d0e99c5462575b3c7343b6a4aebac0ac2072ef31b9ea8bd47fc089e862b04e007fabb3f0cb4e6e1217fec843ab8f4507666aff47e882d4d367f14c17d0d2e90c7ed7048186db17dab048e1d9bbb9efc950382828ad6a5417f19f615aa500b101baee484c5c2ae6db821dd8954a31a9374093a8d61f93b5de70dd8a78d747080f9e3f9c55e5c094bbfeb3bb49ebeacfd00c9961801fee73ded65e132a60e8fd033a74f19de4ba291127b50303982034bda3ad174c95c72a019e6b4c6ad439bd071b4bf2b16c4e24cfa7b2f696815338b733c6b441390c0fa621f742d90e6cb90457ad1bdb020bb07a019992a750750dd35c9c14342ea53139eaffbcbe83dd840f01135546a59793bbf054327e3ef6849fb60386542f306be1d92ce0374387cc0155a0ecab065a16b7566ef9809009c4e02eab1bb11e65d56efc370d5707ebd301719bc91212305a3c1e15262fcab95565b2851a42a8efb02491fc0ae62f933a0890878f126acfbdc21181a05538446a8512bc94272ac18c21aa152ff0e1105f0ea96806de8ba2bc3bfd2e8e398c0d4b559f34805fda6e6d64cd9f35c5064c5e0872edb30bda7f405d4ce2c823e70656089e011783d77f1e95231185eeaeff210b1df82843f2b4a2b0535c38f415ec0e93cf9785c4e1ab9cb25ba793a2811d460ee6de6289ad56de3f8bb9cbe628ef301e1acbf394d1373461cc8318049ce86607f6ba953dadd15fb6dea6aabbfb119687ce8f5cd36f905d6d9059535efe8d7502c9384a0f5e4ef7645b36a5e516187b20192cbd1c6d3278142c2e829a9980a105e31324a47998c1d0c6885f2e7edbe71913ba6dd8b79e651566f402a2ecb6070b12b2c7e93b62384efd51a792edf02b63f0096994754e846c07a6dd804023680285f9654c0fe2f3cda3a9e52b8e9474a00b8e15f959cd151da93d1f11c40c540b918b68a189e5a4a102fce3731e12ec0dce5184d3544ea659ea5211caed66430616a965962cfeb1c38e31c3948809b1fd8c77082165afc8cc6da51893a3d4b901aac0afa2471ab5576f183514902f39d6779a9a54e3ba5816bef557ca0c35dd0273ba3797375490799ecab1f196edec4f6165e998f83d8e97362559fc8cb5bc0b230ce0876b73f8b82a2d07e09a3ee8987f66516739c78b5335c163c55d257f0c5cf569d28acd154de447d970b9e3320b7022ffb2c8fe88460d9f81a03f62260e27c916bf72b86d8f07185e3f72216557c616d5251c7a8f4cfe45c349fceff305438c8e334ead6e2c5794529edbb9087b4a3ae57f68fd01d979da3d065e704c0e6a2780bbcf62f286bea2d8f78c7a63b967b629d00a16a5731cfd5cf1339f6702c61561248f1e4651d6914eb5db9228f1cff0f04c9a173e910ddf0607b3a48603fca6e770f42a008d5a4d239957332f887ca4db45e082861aecf991bfc9bf060b11e036d9caa2ae07af619eb1f5ba082f0e20ec6f24279ce752ec7a6d75e6b301d21affd3b23ce9082fb68ae24ce9a04614c072371025c820b4014d530267dd062baa78a8e6e8987357d9197fea662b9ea2e6b9f4bf986287d987d92e7315c00a827066c843697d7646186cd6e446efb1a1c36a259cad3f94a279ab044c12e50dd418b145fa43296d01baf33c3ed9ae9a402cea0ee2a4175937c8800496375c09bbe92756b2f40c0dfee7ea8cd0a318c209a76b00c0ae42b0787be71fb87e5800efa4ab8f1dd9850e7873de963a5ac14ef40348909255dcd3c90b18053f617a0b50f90298a404163a9c3bc1c041de2e3caecde9bcf4f75faa854a543e0dab060bfd1127c40f03b73526dc16f68522ebcb9fcac9bc1ee66d80cf95e5cc43b4730db44fefce108ca64be56ba53cff6077cb222703d9f28e4a7cab64a8097eb4ab08776b22eeb9e4b724cf731096c1961dacd1b42a0c966343c9805df4c9248dfa036605945617b3933d10997f1756bae444bfb8abf4a29778ef446198455ad5360001a41e33056d7c984da009f066acfa67c1dac27e4c0d847397e853bb869d2c09baf820e0fd26335cd9ff6435dea48cd89bbda4eab984ccd8aeed2fc42ce9a9096b13f572d951c83a2988f97d6e702a81b789f566a4c8675ecc4fc9cd7906280d1f474dcd6b1a12a1ec7c5e09202e17453952518393443a60a3f500a29fad820237729e5a805314c114580684b4cf8b80fa2effbe48c43bbdb4d07d831a2412050acf1762ccf5e96d6a8db03dc05b21e3adcd498d0cd7bdbfb196e5ebf33ea6074890ae4330cfb01beec7751cec929ca36c53b46b92bdfff1a9c26907c9bde9089fd18dfd62c528b04ca7637e3c291a0e24ca9565c90ca6cdfce6a241ae68b709cfa503146b532d8b4c44c906d56df944624cd79f8880bdac10102d8d63b05d09dd363ae9fec9282cb42ad80e1fcb364f7582ae97654f232b17345b723880a904 -generate_ring_signature 869c7247a0b0a1fb90d96cfbb2e3d17682be83f64ea5718718768a7ff74bdd41 cd4c787f13645ac936e8e981b3c725d1bf042959eab770f7c28179f6f37f959a 50 64a0db89add71f4dacf4b369f61a58504533ede4d3740cecca23b82f3a75f4ef b37094f708fb5ffce04e866a09c3aa4ae4e9693abdde06a7b22dff21330d2865 e80522d9eaf7c40d7ebd82c81d893dae50ccc030c67eae697aa0f7df696b87d3 603bf0a35d784c9788ce83017240d87603463c6c41f61896f24ff3a54e5183bd 2879ca5cbcd35d10079dd6b0875cec28e8f177fd12a7e89a597d4041c60b28e6 8f16a24090b39a5295926e9f7e1e73b85fd8f12f96e58862d5a70b5b8067fa74 af4aed48e14d50dd553871225b4cb21dc488041ec203ae1f4140c3a46595ba69 91619b1d38238a1d1ce66c10b3c474893e0484a3af833c55a346d08df4520b2b 4fcd543fdd76e2a7d5a31e6d0d39ec96e4d70b14ecf3419d8f59f8a87e31a26d 84fb3a395fc0fe8ac6bb8fa697cb62d3d56cbfe568c24ed6f6c973cc674e63e6 2c9215c4af4e6ba4447a7ff5c92670eaca21bcc140aae3ad637a93ffa4e0c707 5384ef060ba220e21f947772eb03716fb79aee73e70298e74003d6150f4fe609 ef2500d30e8ece7ae0a2ca2026d4f176ace683edef6326a16f631e42029de6c2 4702a38b0795b6c71a0b8934c2b43b0420c29436fcdeb1ff04c5d44470e900a7 bcf1c1b26acbb158b8d4444fc9951fb62388c9e2e37cfaba70a676a0166bdb04 32d56ab2539721810ada48acaf38e0d28a2dd6e4eedc2dd9c82cac01786111e5 9c3321f4e62d07e104398e1e405823e9e1ed36032ffb78ead40900ec52779db9 8b732bf86cb9368873cbc81c0390eec33c88cefdc66d4063c54b09ba3aa2e78d 2dc91d83ec7a70f8fa663e49c70102671b43eff575c4ec9dd2ebf3abd7c03d61 f982af7048136c5075ba09d0d82da852eb1ff9879a49967cffdb181dbe08d576 a603ae7cd1acd05ddae21bb0803fd7d4af1a4fd56f995abc3343b3d86827093b 296b597866b55b7eea58f80d58ddaa00b7be7058e07b24563c4732a3de2c23d1 1a0a0ebf748500c4c58716300a78bc636d8616b3c6d4cd9d27224ffc6ffd21a6 2a2ccb830271f5438d1a91b5255ba79c629261eda2dc9237d63963c2650e7038 5644c2851b08f83e350bd96db37015bafa8100cdfaafe8d9576b7e7b5d52f76e a69c652a4d177a681277d5c1b4ad6b9ef22737b1d49789380dc890069aaa3046 3e7facbdea7a85a4b59ff60f20d441179fe72d3e07719597b11f544341fbc223 55358eef614502ef018661f3092b076e66612215a378f67e060fdd3a625bd41a 92db53a847ef3a1e0786d07ec6dff53daf37c2358d1b76174406a75bece6a192 6c248b764ac844f7f20317da6ee0ade57c3addf491a6309e19954df847fe0b57 c2b3c177d65920dc7e16352f4d4a1cfa82da74c45c502ffec6148240b048da0a eae88428fa3f81f6a565c6f71a34a1a282550b543d7af367ae568cde957a5adb 347737d568850ab93cdaba356e2f2c932df6a8b41fdec8b05b9104950766e803 40473c24f38722a5db64db65f713d670ca27db39726f32a728eb93774a89ad9d afb366a426ce9f1906a9d3673aba98e048aac4e4e668dbcb17054378cd42ab44 e9f3ab459f7194bc370c362fd7d8a6a75ca199b9ab4eecab528939d27dedc48a 0d4b4bca9ded630b3612d80d468b504d0c180d0cb434c46ca42c68ee98dc2cbc e1a6e0b00675b3b136853539a4e7f82877bee50b7ecc3fa26b8bef50ea81e5f9 7ffb6985097f8b43c0b1d8e645e7a7a92c44f72d6fea1ac90e429ad8cd6bc389 9cc6611070bee3ad7b9ee4cb7019a55e89981fb33689d4ff7a876d543d0e9112 e7bc5ed886bf0e3d7f6f5c226f8fcabf9d1935e7e2d609932ba263f451cd9d27 1c65db720c1282e65a0e49d0b06ef80fb5bdef56c74df1989eb020a3568bd4ab 7cc29b80758c5528e9534bf02225fe899ce2d91bcda453e046f275cbe0f1f9ae 51094251b02255d1ee35ef29afce78bcd0082a50dc86a164aababac34c46bf55 ff25ef58937eac01fffb1d4c73935ae9852a5612d26c13174f7199bf48a6c25f 69c882e768b9f5ab02710125377cd5f2e137d22b25ab1e8e3ea7421e262391b4 c4fda0318a3ddcfe2017ebf0bd023beac85fe29e49ea175b75846fe20a97d461 49eee66a75a60155e24d1337eac7f8110bcd122a9a25309383135d43b37a80ee df2a2fd55bdf1941f0a7d40293da98f050c253827d420f6e020d11e81613a0a3 d56f97969fd7002aa6a3b9448bcb83354ddc3cf148c4e9a5e36c050fbaa7df42 b61e797b24014d16d9cab92b84a7a057a1a05054a1f1de374cd61c040fcc7c00 2 4183e534383995cfdba1e890eecb79fb62785c085c966b0a95226f526cb10a046e693fb62cd3a2c16acd4692ce06ab668a178f0af8f4f126878fc69863a89a094214f094d6c89d48f7b743bc9766706c7457e64e53b1e1020bb79e9b0c691406f2f62e0671f61ba2e18f2aabae91e692170b953ae2e177e73c638bcd726ade019909d9f3e028b07f3a040f43647803c0a01f1cb3b2544edadb5180e8c98c9709eb21e4257463721a270d0cb34da4e4d99a441700c93bcbc70d84c505cc7c9e0c85a172bf87bb0f6b9a9b9cf3d861577fe87570e459710dd0ccec0bbb0adc040f9bdf17fca8217cee35bdad24e41e4619ac237010f54c60686b252c2e4afab30ce89281b0f28e1afadb7af51fc2b61d51adf7432a6acca555c3575558e6f413032488720c172e0865a0eaa3cf8a11b7bf714d76c9eb068f4edfa3270df2139500281e570a4ddbf51d5e487bbb9962c1f6a8d552c4df717ee1ae3b3e4ceb05f00afe1eec5bcee035b1ff64b5e5508c162ce396daa938a952a29cbbc2968dba390ca0f5f97c23a2c9fc2d22ad49d1cf470d3426c5bdc5531b503c11576a9ac52c0cbdba208e30e2d2727a7fe893aa6b1df6e327c64123dac1a08ceeeaf860f04a064769c973e446e0b50b55693c0128ce7d42e3963115070cccb077a2eda5cc5e035ecc8bb77be23e6e15bbc040d6d2275af2e1a419cf6b3175aa0d914e0fdb6201d8e5642a492887bfb713b5a8c75d182ef883020b3ba0936a445685b46cbb74089c605f786e8226fd38f3c92ff91a55322639584ea423df71bb84d7aa87181e02424f4fefcdb1a546cb6bc78c9979e546fcc43bf2468a85a60e69603ac7aea30265b5abcaa22f9cf79e01f6f15cea4ea9fdc9e3c450a5d4f16d8f907325ac680ef926a619d8c4cc94e847305c1b20ab3069fafe02c798e0a79319a84080ba390cbb4ab06c0bdfeb70f02beef2bd04be87eded76532aee885a4e24b23dba353601a5dcc790aee025bc3b4cb5f1072027c58f2f639cdfe2d1b8a6b58b7084d22c033320199435aed1e54ecd0f57f639e0216b93c8582a6754a00f7a89ce4f688f0e497b954a725b3a62b7561649e53e73671d61cb4e0318a905f08b4ffe002a5e02307015b2c3fa9e6da1625620a925d2ff3727296172466e9a345f8bd2122c82098be157bb4cd58e9edf0fde10e652ab93d05980762ccf6a3c7a4d6745a6dfe80f3f4d3f2a610ce844cea7887a7b14d9a105099b7e39140b90c17b3990c9401c094aa5c6e1e8c107dd1af7e2958e2715494265d81ca7e362cd9c6bd61ea538ad0c4ffa4d8d38245533454c9180d0eb9e34fd68f1c877540ba5b6c7d8fdc4cb2c02f5faef49567f8cfba896f7bcde64d7e90bdb27c1fb88b114f3ba0794ef40120686b79edceda4109f272c54b6f36bbdbd496ea8f32aea7c86f9a78113423e970853571082a4229478d23fab17558550efa02a0da8793d1d9f9a06c77ffdcf77091afd82034b8e46db301b248545cba23feb78ef3591853ed78b657c0e714c9c079d65ee2124bfe03f2230d2828d659a6d0424e1cff8d5780f8a3a3a7f59a41c03b493d0a6d22820f98b2c58d1ecee371b5d123dd3247ade42645162c9ba9ed109bf8db464ce6cfe11d9a8234ac3b34c97b16bc2325d0430f5cdab7e5a7d6a760385e186dd93e84e57b2ca645a2eef108d259e2f273f273632ac20e0152e04140b0f3ed6e69d6af352f1a06b49a83002256dcf99ea88a4a1ef175ccd96ce93820177fa68184d3e9cbda09d8b7a9027b0776460b61492951941715588c29bd01101fddc9a4e183b4fc33af3d2d43d33927987889f6bd545d3ddda6fda16262fa30a6c2649fa2cc30df112a0476fbfcc909c272989001b17fe1c184eabfa355a1e06e558656cbb731dabf8d483fb9c49ea74e49555d25a910c1fbddc301cf3c4ef09e1d7941fb5f2a5276040aea5e4ae54361101de06e3139e94e24eca95640cbd0dbfb8e289d335b3d1daad70b96710019d98aa7f74b61f7adc99993f20abd949093b03bc3ef2987b73425df926586b3e83a7230371653d60a9a5f7582bd6c0380aacf28742e3909997d16b7b528f25fa475c188aae67e51b152c2e245744578806c359ab4773595a8a2230b9979cc37267322892233db91a4b3b7c781a179c93004957ad257a75f44ee0988b6e787750abe90c3095be44aa35ece10cedf5472c0df33dabdbfe526a133d0b07798898babbcd3f09a3efed5c91f901cfb8adeb0b0274836bbaf074d7caa22163b722a1e65c8cd301b0e69a8eb232cc7107fa6da60e2f75f65b87979894bd9cf3a4461970a7afe77f105c120abdabdea1889fb8820d5b4cc2bb8011f12123f89ed074a19f89bd7e19e5730ca1d95ed5f4b1ff38b80eaffa55c2a2c05b76745a3cb58db2f0d6f0db013b4c457228786953e5a13bbe048d954b4728e6bdba9f8fab277e1a008b676cb36ccea12e45739c3e00ed031a02e8cff03b7ea8beb9035b98d2459a250b69fdc9785635b42d1db42b81231d820ea5eb39aa9c4767f6b43b7269597c6462c193760333d821da73e6935327fbac084528e307cda0bda9947fcd732ef3c54246e3ee3b394ab06608b87626bc97e30ed23632a6ced000af0c795a1c9b5722417f17ccfb58bd80b3c1a854a9326668099e433639b9b28552da5b1b832afa54c83859971db2887d94d33201e31b694509f7f4d23d772dec780b7148a28d958ac2b4afb248434b9ec5792ad0b04045130c473e8bf72eece12bfab252fb6187f88999472581c8d7ee5730faf7c161492005ac2345fbf684e1e755e88b23b8fe3d0dda4bed52da6837cdf637b2afb8e78105dfc2ce19c4021f908d5b5f42938f367dc6b7a8bc8781ef28dd9b80b0230e420fa925e61db3ab214b0358012d1ae09d7b8ecfd4c9c5b66f5533c4e657c7f5370ac6016a6c9ff46c9f1d29be4d14b77813f3764da1360f7a85ecbebdb6f2607f0524a000f731aaa124ab2bc9775582d91a8ec11b227fca7876bb2233e4fb8a1603154272974ea41da40244cdd3108e182bb1175acc9e245ecf0120c9e335fcbf06990b8655896a4d047f0f63ccdb30a9b99d76a62560fdf7a7c8730380f67823096e0b1d698367eb78832f5230e6688755a549498e971b8c3b335f57c9d3122a08124849cd8acf22e5b6193eb778f29e013ef6f20ce309bcdc4cde42450739020b7bea62f7e877d2d962341c7c04a9cb371c8920d8bcaf3b5b1577f357d4eeb30550d2a7b035b5bd3134026d84f6792524b66ad775da003e06c018b9e6e0622002eb6c77aced104b6a71c9fd2fd5e6dcff4997deb79436bdbcf5f243c9fa613d061f9f1c57de7ff728244ee73744722b3b1f8eff492814f3369b08e1b51c51590afbd8ea37cf8a23a8c4419fc39b64e049dd740523bd6b7690b32d8bdce0bf9f07c75050c4b2c509cb3e4e84643394c978d600c7ce1985805bf8d40839de3588070cd1d0ab303c185889ef8904d2affaa1f1aa42b071b6d48add35e27876939e0100f999941e5b8b32a22208f7a09d753c03bb4d7e5023ddd422ab3848728bca0d864bbca616d7b434f3bc10d86e069074bd618754a5d42b931abc861a45ff7f093360324ef7a6764d7e4d41993d457873f40280327c990536adde132605d60e025f0fc8038c2c577a16b9f7868269a998f238abc1b1dcd86d91d15f9c6b0b63011ee69dd5191c43ebc5ea6b414226d1fff0fc98b5859fe31063c0fc7f15dd5605875a262a79986bd5371db23fd2f6fa7b2e033a28d8665e46fff39c1895ea8608cd0aa32ebe39e8b0eb8e96cf594419901c73de9b168756a3a49722d83c2d470e916b2aade568434d123bb37aa30211a9c972164efb900a152891c20768839f0d2afd2fabaeac299405a92d8941731d86f5aeb7149d140f17a6e950d92361ab0a1244341273ea65ded016704cff76d539a5560258ac11e612e3c2fb8dc2b23b0b2caf309e545b679cefa2200cb5ca63956b7c58e7e7ed79827fbac2cdb188d7030388cd2ccd1dfc41349bb5aa2356ec4c44adbf68bd29f06210717f6b6a854d0182278ccaccfe43b2aeb66d58ad9e4d9575f89b1929635cc7824c1210a377850c605c943293f9c15a890d384bf42f03ac233f2d92028b02900f8cafbdfb9d0a06a7f2784c0c2a3df0ed61e9c4c48d570bec77599f3fb3c4cd60d27c0b41f8b10e087e8c4a9119c724a918ebc5638be8c94a0d88151434af46320031bae18862018b5c0a5cea422ecccfa854d0c9ae4fa41ddc2cf5d1ee646c7ff652de27acd703ca5b9afbcbe46a9f046a3b4711b8dbd272b46b5b2e9860604a8a4ec7175caa0b9e791b3e35c72de0ee3aae342eb420ccf1e67a925ac619ba5a91f9837ac82d06ea9f783db129eee6e93d51f679dbd6e90c39510b6e390c4b764c218df059330dec562368f8e82c244fa6c727ecaf42cbbbb26e3e677af63c80622ed55352710b538273db07c6fb56c99f429c7a1af2913a4ffdb2f52db11f8aa6878c6c5b2b0b -generate_ring_signature 1d0b119ca5e69bfccdec2771ff272dc2c8638c187733438939525ccb8005f4ff 8645d7285139bdfe550241936b2fc8a26757ffcaa7bac9084ff8a85cebbd1e89 3 8a075c4f74b5520b511ee1a487cb31c4cc93befa5af0887414efe0115fbac0cd 5407168cd81fe9cba6a34e7e30cbca17f448f2226131ea57acd74420675830fc 2ffe6b476ff37d8d6487cc1c7e5e89ba0295a5d0128e6ecf8ae64165d6d14d84 ffacc2cc992ccbdc7cb0cc1a695ca31a92f6d6a2563b03349688a63a86f8ed01 0 d56755bd0679b1be0919c5e0e278196520f2bce1726837f3f0827eb65670f501eb7af0ca3a5c41cb0a1e845518a63ba7dd071ee35c2b1e82cf8756a91218a4024603069ca1eaaec9792b0e1bdb87d12b8e5136b08143072c6eaf12a0120181085ea01c5864525b04f2face202dd1dc4f4cdeeeaae228a37e6e93dd62fcc8e507ff8361c115df826824707075c8ce3863a5ed56bca381b16a29d3ef839d4d8c0588a634fb9f19698bde67c2f85960b546196b2d503f941561af764750f2ccbd0f -generate_ring_signature dc0159dbf72ca06954ef706baaf14f7c84f6d6e96aa47cb0fc100a73f21506ca b0dce2128797d8cd8ea9c4dc13be5ffa76e3c68278d8721835f7bea75d42621e 155 55bdfd958e609cf23a67c353b313cbbfef67c4b9f888aa9ff96473fc9c841e61 5cc2a7c274ee46db7d80a45e09bcb4701ca0b6c651a3f71698df8681f565da1b e1ec3ba3b9a5c1f93867401ad6f4b8f45a81fc04b057bf48198f93507db0c45e d26059d3c9f334e298bc08d99e64060f1c68e8cb0db08904f3f2e989c8eb0da2 06ff2aa52649f6205f044d65d691168f3bf22da79ae46a294a362c23fd674cad 376f687a817012087ac04320874b9e169806b3a384ecbab35aa7caabe11af3af e6f0454df292cffbefc002e20637b78ae2c52993e2f1d7801fefe9894babaf97 965c5c80ee12cdc2b0ef724fea7b86aba5ffa1ef7a8d371f634177fe0c77ed69 5cf4164fd1d89da37159323130a12b0dc4d22b6743f7a14f37d85675cb7711df f43d9857a3c0ced069e7e66e99416b0f4969010ae1ec4f90568fd9bf1ab42d27 15a59c1dd5958f6b8b48471d7fd113b4a761808409dd5606b5eedbb3fce5749d 4e8c6e51b88c5df9d2f41a66e80a5b443be79333309de74e36d26867c5260f29 84d85995ab7fba0a34a50d10c6c9ba52922b7f5f1541e7740dfa7fceba592b3b 04409b6c2ee649e8836796a2d0413dae06f8f41cc352fb00bfb108a6f608ca32 9c207be7f2a862125bc38aba0e04e98d16d0d2ff2d36461c0480716a95ec0a36 39fce2d41d67bf1f182d1ccf23e140ceaba4322266b10ca3c950055b6be5b023 fef4c2cf18221ce0ff9810a1928d9168e1b88db9f42f668d74c2876286c848e3 d1ebeccee551e9c25aaf9c6f1f6334fb5471e5e94f46bbb1d80729919c5691e6 9e7ab6f141bd4ecaa6d7885514127168338ff935f1ffc56eaad972e19b807aff 4aa10541e1a9124fcac6896b065066ed0d73150c9e9455f914e4d96ec07adf5e 32ca3c20ab39e82821420d6e2e37cb9a72f19d1df5908fa1fedb306b16c3273e 8172aa6cda51efb16683412242fc3b90a3a37c9381e4109c1f00521546fced9d 2f9f8b8f71b8e1d5cb244c0f0a14caea1c5d77b13ceb6a2ebf2b600ca2d236e6 719b3d1256ab1d9f286f9cb4bac235da7131be9dd47388b91c6eac952c53312a 14a64d08f79f8b03c321fdc291fc633fbeac766125cd5bb1293028bb7e86e4cc cdb1c8bbcea2d12159ca80158b1d8944d839d82f94e1c0c3ec84c71d00a67659 aface084d21571606d8b913198308fc78bbfe4fef087b2cfdceb8c335d756d43 66502a8fcec2e95a45c10fd5288ecd64e1f880a6b7757a3921e14f432ece527a 63b5a9153f88dc28a9dd325a81edb0bb2fd73fa2ad2aca31839f9350412b357d 7c377465d285f2f6d31834ff61cb8a9cd5ab2fe99b4ff9c330e0d59d305b21a1 ced17c63ce3dba87598c1adc062f3a8af81d4937447ff8991f7c780bfd9d9631 d33c03c444dad20c86164d634bcc2689be5724091a95c006723756544a5f88b3 42c6f935724c8f7f3f5c53645123165daf862cb05366a895eca0a7656cebe76c 4950dc9ec99c46c3d605d97f96407e9de344b0bfb7b19f976c9c84a18b3d26ab c813aa66c11bb66586ad3af0cadcfd7f4678f9ce71478135b8cfaf3f7fccff8a 91f5b936445454387f607698a4b2ca38191ae36dc6fd0ab0580ca4b80b058d8f 9b8741d58259a1f279a397da968d1df565d8e133ee7c69e1ab72448660625adb 4a7c1752977c764cd5ac091751bff8dcd41500f38b7c3baf458963f2133defc3 2d2b4a25e1f4a864c3f45e0bb5808484bb51d2e35b9180e3565dd2945c13a9ed aaa64e83a28293a0f8759ed4cac37082552d3935c827293da30bbb5d3403613d 66452a289e79a5361719e68d911741f20163ef4896f0257585bb9c832069c5c3 a14e0b54b0e02a7e81fa314190c273653926c342c819d74e9aa461300f238855 1c1322db318ccf855d7a5ce5a6aed6bface24d4086cc7b26ac67733be55570ca e10ddca61c7790d94984c7ed066543eb76623923557c610ec2f8de6f79f635b2 7588b14ea4f0e4a215d9a982eda345bdbc6aa4cfd04511867c40f9011556434d 409d5ba7c80a7e1c29df9bf923ce011ef47e284c0bc462533245be82213b4b7a d5e6a2f9f50e6e03b514ed898ac28f24fbec78eefbb3dbe0a6a00627f72aaf4a bf34dbc0ff7eb6c8a74f111324fd8eeb2be93a93c8975635ee06b526ff1b3ad2 ebf00d242b0667a638b7c93c397e45f92d1e8acf73bb2abf73b03490b3b6c3ae f3688388ec40d6680cdee04c6f11d79bcf9eb4e5ac2ae253b4ba852826b76bf9 0ee543f8b280ba4381bca59e1fcfff6dd425851c4119e251a7732c99b8d2f168 d872db69074557c2102d81103935a90bdea94ed0b0200c3ab0847b526e29b4f7 d4db1b4947a3e86d998ff66601af2f2da8cc84e9d724441b464143b171d7c89e 746e4cd0a3813757876862505807b4b78270c0a170b888a3bb9e3e60c0101908 8d3606dc0218adf7c809f52dc2c19c9aea02db66e95b21a4dffe48680bad98c7 721174c2d937c62637e492c02253ee2a7defa7d4a3b6d5bd47bc6f0addf40ef6 97bc500b936ed73732b36010e062fbdf149dc2a5cce48c1a648828156c956c28 f3422baed25571091c63261b7f854a389392cfee89a8aafe67b0986c77f933f9 3224b4758162f6a3ad94d76f096029d96b8542e883a50f48d189fc9ddd927efa 8634ba86f40b66d5e0ae98089bec9c49bf7ed348c857e9a8ae6af9fc1a1f1f66 afdc97548124eefa649ccc49f8c4895e1503a0b86e4732dfe073b18a14c6e0bc 5290911f8661f9a415535158f2effbe89a9178c4194c922b660645825e234584 a79798f044fe2f369b259d2b59c949a0cff4c4eb54b5464a1c07862032180273 36f35784685306db02646934f6ee0734226dd836ee407bc83ca232539af2a10b 1a689224e864e3777accd246ff0ec5ed4f78b44c7af8f551bc9b411f8614693e 37d040f52915b13ecff79dd88fb88f109f091a5716ec289f72adbcd9d1877221 3f8d7c20a19fc64d9ca3b1eff52f6c4c062d6ad85e9b242b3d16618cc5c359b7 8fb07bf7455db11b402bf9548947b6af97803a02577e538e9ad452fe51960335 e457e7a04242381202e5ec2f466205ab1cc3fe0fa20a97eed9cb1afa6f04664c b8b4761d93cb707c2e0fc386991643d770ce3309203f1b0c8f182ef797fcbd3a 4a5c2e5aec7e342cb8e6cf16f17678553cfd06e5359be5994ee6e50bf572fb22 5c16c16457e9fee9a62c4ba6b6dd7e46aa1f3f85d68f08629ec7a96b85118869 b7299ed0fb01db3149fcf30dd1d4ba8c99b9384bed66d70c3580e042a6f7833c e6c61646a287ad0a53d582ffb300a86755164342b83f3a6e5fddd5471068658b 21e7442030bf8d818a79e5674f1b5798a576fbb1ef84472add4689990f62e8a4 7755f1fcb777b9182eebd528bf3f60f6a2da148514e90695acf897196bd897ac 8f50370b4a8db13017296ae820c4b728f46e8244824e590293dfd9db7888ba5c 2fa322e48e87ea8a9ce4f70ac45fec4bad47ed617817a39c6ebb38bf007f3802 add067ff6442a2d93b12b6de049b5fa78541e45dd0a0f74c2223ad7c61a7198e 46554f1886d0ba1aa9e264a5f29b08c957b5c2896974664b222e60b6e47e1b0d 4e0a19f0b65791c9b0b510e49c670cc06bbb324d67f657a4028ed9f03784d8d8 386291c7799ecd8cdcef7fe30f6021f42ea2918b06be3fe8df2f47a0fcf2d616 2f4a5d75e0868c2b8e523ae394049ed0ca390bc64f641ba203b9b4dbc8d41d2f 841f17f2584641774eb003c751d0ccae29152dbbadbba8eb066a2ded5dabfe98 d96e7157019eb21d9ca9ddad08a2c2cfdd752fa10cf6aaf11089c180f6dfb13e 7360d3476419e86cb99abd0a33264327b0b5171557d812bdcf6800ea0bab7131 463083e7e2a8fd2d956876dec974816bde097827365b94a1494d5f7169f69686 44e8016a6c0e2e21241c67bcc8b844793daea164b5e2a14baea66c3c7a3cc773 22764f41e82557790205bc987553010dfc5bda9d8b9cab62def4c881e4ffabd9 9a52e8f5b5cf1bcde87297728a79c4154c272fab3a31505e9de06cc22db12b20 45ecf071a3f952a3886e388374de59aaca3109b8a9424b7cc4e9844de93f3c38 04bfda9f253526a91d0a4eaae8e8449bdfa9d200346509ad9fdcc90c9bf72046 baec1c08bd22e1d1803758f86de1dab9d472cefa662c4db5da8bdc3efbc19b34 efc658768831e5dd37bc425c2d958f14c088f72d86651f63099b6a59fc956aad 8bb4c7e070bdbdcf0bc3ccb85a7f636c40f6855886fb9e5afe3663c78ad39122 a4a4c96cd0361853a0f6e464a2ef681a05d30501c71191f74883a7071b38ca74 1f0eaf33404e3d3acd817f9f8a49200f6610b730b03dcad2c75829a92b67d8f2 693c7c1e884e24acb6ea9f79df9a4d82343d2f00a36617e80b2341f4a7061e9c 57e1c0ebdb580b1ef2eefe50d96d81d9182b45cec86b8c2bd8bc70d8094c3a64 10b2ab4153737474de7bc454ad5f247fd398761bb29f665cba97dd2a446f7397 e80e6ca216d809401268bea920b105ae5bdd440577b7a9ae2981b3d75b39bb55 967fcc98c8830d8374f52e19229f50d39ae130caf369227941c97f432d6a381f 6276cd137870acf4b11d90c2aef851894fd6aa8d8ef3a2e6a7464e0daed09c87 43a43751bf077cba57e404a62eff1082d66777f1e304f0251dc884a472d65730 199e70fda56e43e548af5bff218590ec49467db20d932ba7b93490df9bb79ed2 75621e025d68155e2501289bf8caba1ee9b89e6389fd2ee595e72baf5ea3b34d 6b7e8ef6c4575bac539bc5fb12d6428cec7286e03ffe1f00d4996ac4214051df 3a28bc22d5954f34ab59bca16162feecad41b3a25ed1008b21729917e9e4dc4a 8996cb1d13337dcffb5f57547eb7c6be1cc2af29d9bce46c4dac048159a15920 7b0eb9a962b2673a4c3385f17fdf9059f202421a36ec76a2190eec8ac1680d1e 6da2909d4ba18f512cbc36a2221a2e16d99a78c6e526e802fd9fbd38b8608ddd d989d9c710f84bd67771a252197af590b63b424ad1c89d623181ee4dbcc2acb2 5f03667eafa7c0eee3c741d4aaea93246d9085248002cf92b4fbf664da891e5a 4e885b308279d51ff6ba3294f150cfa79de993e4b4fe240e0383926eb1b72a7e 48310fea7a0b977e646e440ccfd050663c1567bbcf716c18738631be861bd928 2d8e36d9c5d5bf1a121d9b86dfd22dd40df765a8640383aa3a98e86815f6b202 c2ba1b76ef0a6ffad1f816d5a195b4290ea5bc5a195c21b99a2205a0fb0fe19f 9264af1aff612cf6c5423fba55d78357d35f1507961a1e5777cf9324496ce5e2 ce48bc8a5d073ebbb81bf4e4a31d30b43869d47aead425642fd590c2c6b71ad9 415ba1f571226cc741585b624b408f244b226a3ef68112a787b7f4ab117b7070 02690c0871b65ed57af53dfe9ad9af13fffa80e17d559e3ad8bcebec4e3244ae 28a00ccffd9aa89903398ac9b36e8bf24e77b25000ec0cc05435f70caec00f5f d71cf74bd0d2adb4721b4c2a2601109e25b41290716c2dbd20cd71416560042d e497022d82a79c271eda123b3f2cb12d7e050eec55c7ba3ca5c18f90456df49e 5593d828a1c1ad5fffaff2fc0e4b82c488a4a4fcdee2bee513fa7f2b8ca21402 ba7deb31a63aa2c63a9b6de0d018061bfd5bd1305de6cf9be496f2d0b38f0f1d 2fdf34d6c3f7b14cbf3d6dc057f68f9238a01843bd79f65c343f8888c57e032f 0ec1bebdae697a17fd38bd3c2b1d466c6a2cd62b221663dc14450fa9645f8f0d 64b8735f9e0d05b013bd5649e8df55455cf90d0a32e01a5bd47ce4bae2e2663e d3210f6fb94b6157defd835fbf6e24f335a53470ccc876c8f24b9cabc4bdc689 854d5cc84664a763d4ba94fab9f6826e4b6795b2c4c4644d1272fafcfb38dfe2 ef8341e4a2cffca78f4f85382c1bb11231f98e313e8b4b158f1f3858e0f1bd89 721bcfd1800fb89d20114f080b739a7f577466853064735708dca02bce6c08bc 2b21a17310ff3da504aba575ec91cbeabfe7cc7ddba637140f2b7ea4a087e5d2 c9002d13dbd6d60da440acd4e2fa2a96a51cb18380b2304c45f8d55d9e3a23c1 9c5743359406a6ff0228502eea24354ea96edfeb39d4149612a9f84320c3752b 4fc972f7883ce8ea63a0579fc59ba3626876688dc96b3b2774202f8c2d514671 8262e5c2fdc9e2d7add1a28b1ab3acdd49dcbbd4ad6b733de427fdca8bbdd9bd bcb2d7f1ab48ae12ac447d9006b14953c7b75a45eba9d7c28f3b596ae67d90d9 26cc343804e2dca0d14ab0d2a2d7d03b794576bf270c1e79b737191a78dc02b8 9acf167693db32fe00a5d4ec090129992b39c269833c6666c1946d8523bb054a 507659e6454ec03bc6228a469717eb91adc0c14f2dafa266c56522e037bd543f 6dc86ba6eb6846cf225842fdfcdbce3b702041a03dede7e5003cc402df63335b 1677fad719b74408ed9e1b6e2f9e5e6f0d5d54f850f8e4a4307c3fd2a5db6d0c b27e2f7563d41739dcc27a208e3c1cc6d7925820e953b36906bd63456c23a4c7 46a4d38ba7ef139dd455ed55953279c6229eb792833d5360a449e84d31ec9d8e 97d72d2c3deeb90f2b7bbea277bb5409dc5e185443550599dee57628b152cbe1 06cbf2f8915bad92aa93e100fca048910bac864de2e67b786924a5dfa47ed2dd 5f01c55600492999cd80dca1fb95bdaccc1ccc4807e274f5e2d76780a62ab9d3 bf3525ee75abe62a109fb35e297a6ae6ab51d430756ca8a44c2aa0dc558623a3 3a78768168d7f695ea5c96485f80efadd5d0434c256732af421ca95921cbee87 1748b5a61482181b63b42252c7663b9c19d3386000b73e440d49a2602801a192 47fd23ed6490a2ca505a01a2a0216e518b5459c621df2fdf9f4090575ecc0819 22cfab5bcf95785b94f17529b1292b25b8ef368d6d3bad17438c9fc4c41709ee 3309c171ccd892d173085fce4bda373b15bbd84719baa5c86b00bcf2c04191f5 6e8a6e2009014f498970673b8c94765896e485f7f5fdc8d36c97e1daf93c6003 77 964f1aba91908bc5383a86e42b1d12a626767ae2266a7d51abebd85e71adc90a5eacb3cb318b4cf9841c622a66267e4f849c1da7c1918f34b30b981051925c0c303cbd855169d8e3929bf41ceba6ac9083a0e4497eca9f90d858324dcbe1cc0197e01e96953944ec5eae98109276c148dbd8454b843b3ccea46930324053a80f53fa7ce8847905357dced42de31f37569666981abd8ad79fd134817609cad30838cae4119e243621403f3ad0e648f8c554e70c50a573a9b12de6d063a0ea710c6b7295caecc2467b14e6c23d119cdd6a683988e27a427d641097d9b3289b60082c07a17d3d2ce85e2d81a51e6fb6e72564c2d83b3fdd8e13858303f211f82202a25825d8f5df3bf90b4c44476cb27b5afbc2e1332fa5d5407280d268e6d745018b48606119d478b0a6c17211004a141a9d260d762340eda14d37db218fd5e00e9379b467e3d48fc6362f66b7f96d30f0c9f54a56c7bdc925fc19a0305b30420f1abb7c6cd5b70b2f6aa4f7c93e3db7475e7eaa85fd89d35ac303089d4076b5068e60b1df9495bfa5189ce85e9e488cd50dfd8396563710225c182f167d882d08479cb30929b8f8483976a25c39308e4aad44202c71891f0293b6e6cce8b7810fd44c048f6783dd77aa26a71050ee3d0c42b29cf387634081d5170503919ba102f5d88eb9a6a07da23ca431e20c5735a6a125e056e645c23aa7d9f98fc64e9a02392dee0d10ea6add93eaf2a61730f0c23697156b41b172197c811186efa0c60cf2792c23c8669dfc57b631f4c255312c01c5581333abb0050509503ad762e00690c6f7b793994e837934fa5a570073fd26fe4461e57387ccec4828ecae56500671adc03ed8ccc6965ca95d5fadeaf27ac9b16c877eeca9e4cd0151c3d279420c70b55f6dd6717129d8cad62d1accbb33b5008676d153a755db1ac8a13ec3d7029351c1a17c4eb10d2f675677233af56bd5330b76b4ab3da25ef737fe3f79e1011d8dbb369786c10854a06dff14982cacbb665c6cc959f073d4794ede912e1d0537dea0239cf59cf01c02a85686812dc24af2a1c526bf2e82918e92b3b6f6a00c024775c6fec3893dba077e51269e15ec47b961819f925726e0d18f8d528b7800b0093e7418641f60c58213f6005f7656afbf0070c794fa8cbebbc411a8b9700f060e12667176ed4dbd6646412034c7751d42ca838db3c567a75303c5d275df05166f1f1c8ed6124529297535a7c469eb27dbd934465f02b563205c553c442600f7046e75ff841607086eee7cc70d93ba74ab011909e678bb6b45ae91ddb0670ebf3289cccbeb98df119488e228cd0f9d7c1a0be9010075faf4d9e2ea0b72e90d007d466c688664c9fa2061ed008f4a3614b9f651ef631b429d660488b0b30e033002a699da2408dbb877ad5b1d8e0a7a651df2996d9d41b10e0234c78169e009f3ede121b2c80b7832496679fc1219a7cdb048ab06be00839eb740cf7164110c11e1ef1b2aa204e8064272ce4c142744a20e93595bdb9d0964577244ce79bd0addfddd902f85eb5ee839809647cb34e13a0f01c3cc1a2dfbd7ec8ea477e02409e44617e6fe7981c882919114241212aab2013754b7b66656e892d63cb3be82096c421f809ce17560595af57e4578345602d0c448b40d32c6192a05a8dc377309f6c03c86334397306f231c3b63e3ef152b06f6bd2553ef10fd02e89d9c0e0a014489afdc53cd7445d3ff3ae1babefaeb5c580b9cefd1fe27322848854756d5070f831a406ee809cca27bb1ce73027879a639abe6433489845c8d8060c8af0a01f2b9f04025daf6cdbc4639cc9a20031148d73ca3640c2b96d7cfff9044320b07446fe1af874ff741fb7a626c9a87bd99b4964c1f52e2876c6756f78ab8172704d0afdfc4d93531c9ff839b120346cd31352c31e4d1ed6b4e41f4d59a1bc3450cb0e6ca3c711e3efc8bf73065f8ad6566b9d4d7ec6e8dc1a74733ef5d5a7eb20b73a11159b4552d6149a5cef62161f389893d9bee70792c1dc4328166aec37c0f24bf63a1a1cf456576aebb89f405fa1d5e96e3d3fe44c07dfbd583ec4fd6c40ed080485d844f35be2b856bfc9d9c444beb68c3243180da045afadf292d41250f01a0ee65f73131fd931184dd272b957f6d01c7f1fab57539cdbac06bef0a1d0afead4e2f8b46d2e3183fb001ea2467889e20c5f666e2f5d47589eb6518dece031b0db48e33e87a21d6d258bdcd24d9dd353226563948c40208656f889852910a07002b8bbb7bde2093466d5700f124fd6d9ca7f8d00acad20356b10439fd410e9e050614364268d392d975da9d837fe281e4b78d81a0a56cff2c30dc844ed40254d3c73aa2d51437e276c56d6497583bf42c6ffc7a8596428a49f5743976450b2e3b4823f670d038e2ae12db8c650ba4ec7962192f479b859956bd952168a808159691b912f197fb98217426a8b6b5385d93d6627ddd6be0c3df6aa944bff10fa32f7c60444f6bcc460417acbbff9adef5280360e32f61c35efaaca7f36a0401b50ae6673e0646ce64f527876024381a2a096d3b3d2d3d739dfea7afd6940604c27db89c4af12437451ef23cf034ac05944617a19234b9107eb65bdf54d7c702e2b88a4ab3fc44c7b0d797e70bbcd73205c20a0d982c3e04c8b2d65ef2e8f2045192b64f637d296e789ba72d4bdd13ef6621a97eb692030daf6fe37b4191340883761b28ac501f2196173af058be041bf42ed2dccbe507005edefdef1db7000ee6a70f3751b08a66a30f8fa6e1676636a33e2776e7d3281760013d1fd4e1980df6ab95dd154908254b248efaea1e63d279b465319e5f9312133da9f157496500ff5c4f1c88461d1a03392dc1c7103ea33e25976ed50fc2d1d0df87337bc95d0d4b8372735aa002bb94838436b278979bd3e37d46e7e98b31e8b2eb00dfaa080f47061c6e5275960c9a1b27b54e6fc391ada47d3b86c5a1d03eccd8084a136b0ec0c2a17e22738baca1cf014df191de8eab17680d8971b7c3f8ef79245dd66f072ae39c4d1f2688267a053c604a5b761a30a904fc4526af5274b25cce9b206d06cc840f5ff52531a81bcd786762117cc0bf3f8d32b79d602747f02b8834a6e809f5bdc841e92e7ea9106852a785d0e8b4b06a953d44117854efa30a18b3600000f51a8b106bba84b3da14393c9016b8fb1d2c2b14f8e9056a183de02b4963130948e5228ae038d24ee2804995fa2269a447e56de83b42e24589d11a4b191f0205174e7610a308d8d7935912ab83c63e6047055a590b374767f6dd59bb210dca0e33dd7f8738946f59c2a33436c51f71558354b51fe9ff0e4ba465fc2b71e9790172478ce72ddb2779aa3fdc7b6a650b0fb0b515342b4a553c2ac8a717a526c40873a2c912ff23ef5f4c3a3318f51a369ce989c167688fa2ad999744bbf28b730780af0836b2e88138165511bd17f1e77465e9785d7f4cb814e683396e20da37040ce5e77b5ff607fa38e769d448450bd30adcb397d6771ad0c20b0e9cc4ac29063499d2bd323094aa3ee406184c6fddeac2469ba61095483f61be306003a6dc0a41e0a1b14d6b65ad9c2477a884062dafb551e42464928898606d702858fee8027cc101e683e444645f62c4509d6cffe43c9cf259850b2bc02b6b9be3b92de409295338805b407327e8e2b0ab7d40869257b2675f1d8937cd486746aa431de20c7185be7e083eeb8a6283929cbb52a7b0b53c21f5f706d1c36f93cbe4d3975908425b7869a85374e0895d226099e3907405cd1858ffff3b5e0857d488b2a7b40a4fd5f14a480fad18d1efbdf2aa0ccd269083577debf4b1eb73a76c93f517440abdd1e3935edc2fc5143e73a908c8ee75e5c78b1c6b4a38db93a81e4a0f9778050be6f9e19682af9b9da65ec9fa09807549bdf0d12b66b4e55fc82bfe0bc7320c3d5c4a82fb9384c7565cfb542712f6190ec3bbd89b5f0abdbee8c6d1bb065b09f5135f9f0246b5f42d664da17164b9cefa3ed421a45170ebd28b2856f6ac4b0c5dccbc052b3c4a406046f5dcabe0b0c444ecc48e61a2cc0a93ef022dc25ee5041f439cd52bf536e8d05e469e2ab59772a44f3b5597e23d7dbd36db4d616f6701887da077d80fb9c8c7eea8f21eb699dd4b7206fcdcc696c5cf947fa41794ed0fb88a914c9cd7ccc54a03faaae73dafc3ef44cd0cbe9334135a0c919cf7103c00ef004e7611dcd5444005e9770abfd4b9dd8b779b2152216f9351d7e7ae10ca0935f03a04d7f5a6433892200c2967f7cf95714b1d3ed7a855550d0891a5920c052607a40df1ceb2306f3c7afda563f481155738cc7eb0fd4a2e8e297d02b5f8095e72d4f7673ca79d84cef4c54d8232a948f01d2fa232ee25ca68cca823d5340c641acf44703e17db8f7d3c91ede3316e2374681f4a8ce817733c10e575415609761f1dbb03ad6d761f7e10201b8f067aee6d84c3b84de6d64d401c0a94348f05551b0d811205aee855c2d675fe4bc2f1991a80f8e39baa7ec1ca9e1b8a48c10c189004b1f52541c38f654436f971199cbf0fbc5548a39ae3d0058caf64eac501166bd366cc08fd9f12622683ff7de0d4c3acc33685b4a18b398bbc13f32aad0eb513b4944dd4b006adab78178f71ffa9e8d9d3217afe19283ca5fbb1d4383609078010b21954e09edb71a5ecbbd72d0603e6395ce25d2c066a97b94d6732280f9c5c807e912751bf5b36ba1dae4a3f725feccedb740e7d4a273da96934b3a7030b40d0a18fd3932b14fe482906af27924395f28763b4e068cf86ce8ecd20eb0207147da79d85c77281ba79ffc0876441ab14b5d23e13db04ae459e752a1a3b0b2c41fc23499f98a3aeb0d31c2e56300301363d932a8c48e6582ed07cac65e1061a7a76a8b7cea34f5b2ecd278a86acf3e7658343fb93c354a5c7f0e141fa050c0f516dee7bea5c35b398524f3e49c8b0f078b35a79831d5c548e4a56f6f0dc0830ea88cdb22d257608c149574e7e39404bf0e75fbc2dd2dc72cab53d9c099c04621f903d7d7bb08531ab702f05fc8d984f122dbb6cb5237288252d84c3d56b01186481ea688728b45b91224e10fd2a3e68c798689916e27d270777b1926dd90d32cf47b1b7589575edea7c1bd9e6a055c087a9109b358526480f6470a24be406c145337c0f2205b861920dda31f6bbd57f17bb7dc5091cd4473b5adb6aac590f7cb7e8e2a005f4b8a54252ef4fe3768568ce894b56174d685abf80fce209c20820b1c9a4776d04d9781fd3b49a4717ea8426f4d5ab8675790fa1d3537c41410e41f2b1e573691311a1e1ceceebca95155566a3d154865a03b429a2e2a579b70e95eead357d6178b5c2ed300feafe558f40de06079780f7028e7923b0279e0d0b2c2f2aa06c1bf9f2838b7d4b6e5da99daa9068029595d572248a9ccb7b58970751f3d506c6b8e8fe436b562a28656cff90b56df696b178eb56f102a63145720eebe88e2f471d7fbcb6b9f367d05b653ca0da921dc52654593b53d3b44fe2e50cb98a3154befedebe973f33f9ab36c8b79cf8d2645f6ff7aed1c739406549700ceea093c34a5a040e39740546cd9b36d43c0b4883154e74f5a2ace94ceee2610160d133137b6e00b8d075b7156033ed718c4d7375ac4cf35280726acd13d91503ffa7d46c887c2fc764b39a184496eba03113b49dcd57b5ad99032a0749736b0d2219fd70594e2e4c371bbc77510f10de9c517ed66b313758afca036487ff18023696161642bf57f5a2aac821db1d5949810a0a1b722e0436deb2dc94a67c6001da71a2bee39a5441a9b90cf30f7f30e675375e422542bf6d217d7987432bcc03ccb5c143e3140dd0c1636e93801b1e7d7d361734c884145973f019760099df095c8b19af1c46e8cba8428492c46ff802b720a11b97f6d55f3157718ac1b47b0f7742ab6886c5ee0b5de548ea69b2a451b31d39d641bf451fddf5e98685d6a40258cff4c156a85e292b6f452df7cf4cc0946edf0e9268839e4175f2481665e2083cd23003e3b8f1d8da11730cc83eb8357f4d1312cfea06dc47240171e469e805cd472b8269b22ec99c1792594436fafd734b265b4338567d6054888727e9d708f297035ca0e4aa2a3f2bf5960d5012d01d0f7e934da0c25de43487aa42605d0cb9f5504205005030429ef943c5e4880189aa6d96b9e3641faf7d19a7dc6fcb067fd1b6182e38316e2d8351ca1ce92945b63541e51405b224fdb9f1e0b6c1670e6018706f263c7e8ae43a221e41f664d1641bd89b2697dc4ee8b2d6b9974c400c354b7b5d556faf76d5b926da008aab440545514256d1867de6ebb672e7cef10ef07666c0c575228094bfb5016fb28553042eb1bd880228a48401d0bd6793560b0186bb00e0c8ba9f9960d068633025609e6709289c6c6ffbbec50cc20adf7409b6ee102bed2e085cfd1d9160d1d3ea7581f1023ead418c24d89d4a933a4f110585a54513357e8ac7cbd234a835bcd53a9d1c5f4832f07aa5ec213c9a6736d70419bb412431cd4dd4c5ca857f939677188560c4c2fafc6053bab6e4361d7350064b2473e267d14f4b2bfd87aa2ace397ca1ca62ae417b35e497795573a175370ef3ee8626412dcbce1593f6e1f7f310b550bd8b54c4f12296c87b1fbc6ec3ff0d2948789a4ca19105d67235fa749467ac14682d5a5680b6267bf38bd4c589e9082759940fdb611a47eab4a2b92e5c51d63ae2f17f1aad8df975125a4d43e79c0c00421cc83193dc826cf90572e57da088a0262e9b0851c5e974643263e445c900d60f3d55608f081b106facb4d20b1bd93f80fd95a29e5fbdd0886487a2dfdf0f1355cd98bfaedf9e0d65ceaf59fb575b346b70d74f4a099966f8bb77b86ad60991767c375bab84e221f5b11bb693114a2f03439f2b52939fa7f50bbb4f804302ab40e17a7f04a23ca0890b6e77cda648c3dade5ff6debd9bd6ba2edee9fb660d8af65278d73621f0122d2f547929bf826004f8037893b5458ea6b82c4b4b9b03241d71e04928f505f940f1ed7c196f246198054a24e41a0b99f790dbad76d3026828665e0f5c0ea785f39f6c18a29aaf7b58a0124483c9c33a474b597e317f0bce0b6562387280e261d94eb5070f2a05c8794612f1ff1dfc3b7b9b39963aab07367f70d908e4bcdffb3c9f0a2dbe3fb3d4209c7e046bc780163e628edd68650104052ffd574e9bbb478f73e558e70206c04ff0fb625b4a537ab0062bab7ffe084948c3db15498f5d4a5421d7a7ca5f4ed6d6d8c13969ba65e50ddafa1e3c4f073ad0be8e94a7156b642fd05393d502ea31c7fc6de80c540e4410793e5496bc06b2d74fbb6acd6877085df8174566d60bce9c74a055a1b4260e65379f2ceab908076f5d551c5f5b7d8c272f573a0e0e77163fca0d908e48b6394da44811c1e20731635492dffdbb3f625f0d73cc968a1d31aac3e4d7b0d62148d1240d0cf691041ff63f9bc0117374591a7cbf75e940756ca26f9ec2cadff72800b50af95b1b0625215639d06ebf0b502e6fcd9cd3cd9ea58b899c5ab9cc11fefbf2d82914e10acb7a5d88d2976df2fcd6e76b5777a3035a7a0ef8d862363bc1c352e32a3b25082a6046fde3ef65e4057d0d5b49f5a99cb7c9372469cdc8c52514e57acb4ff20efae06293f2650cd3cd15bf74edcfef458f16b9f258955674d5cf336606400b0fc363c21ce6e1665bb8b3394ae3ea1a9b5e36678da68b8956ac0ad9f904f2780bf03b6db98470ef4561777798009e858b53d83d5111a90f58550e73dea455480d6476d06b41182c229fb44296b8b3e06040ca154f31a41c8350532c6118eab30585c145aa3252bae17c5600132412e6bea08d343815e172d7f10386c9270fae0deb06ba0e995671c98fa279141aa7329970d53e762d1308303726e1f067a39d0509f30be03a052e9ea26e93843cbf5c5fb4b925ea78a5c8ec7cf00b925d079e02dc525662e01e6facb323ddbef6f6a47e30d4f2839b4d5813683a35bee0035907320f0affe129cfa6640645a12ea630445351d62ddc626d7ee9b9ba57a4005f0a890595e1f2c4a61c22e3a8cba39f4e8e7dda7d59f5ae9a1b440129898d6f3208b5502afdff42029b20a98ba62723c16fa2f07291a6d769bb062fd08e054390094cb4b87e0fb32100ea4dfbab06f8564e4bb4fa5d9454bcc6ac4e1cfe615d8e0446d904249e7ff62315742268d35e23bea759fc0f0122e3fd9d820d429a505a008d833bdff859f59493e5e47e7fbf0d1b4012fbfa778314a7fc88b00fd23bc1004f7957cd14d2f28852305c2c7db50e7fb90446a72e49f886251e20dfa48c850b4ce6594a35d33578adb837431ef0ca16303bf35431dadd8e0481aceb151df700821d546f0902b173475c562d65e85312266370b97aa05e5ef6c9b5b5d043ff0249d051fe80450c1cd6289db78ea29638611fac124253fab2b453d099fcd973082bf12b9e810cf5587bd43b2cd50c53a1bb544df0a674792fee29c925ba04d40bb9caf043f967ba9ef9c03a668fcfeb9774c5914d231985a794d10aae7837b702adc438a2cebb9afd2dc7aa9ee4d8fb448b16a8e963015674eadf289338215c07d66e5ed23f72d02bc316e861960c414a45eb69309fedf7685506a07add025b0cd64e3d9605d9ec7106ba103b34a498c03b10cb0e2ef5565c45a72b7db6b1d5067f711f044b2aba03b6a78bd42b07ef71431c462e8034a5672682a0619c5a6301f55f096a3cdd405e538e92b10387369412497586769fe931cd64939cc5760c0c7bd12b399546a1f7140795b6ac8ce0652d5b2f8ed6c44baae2d61e4a216239073661df3a8121dced23831728e2cc697963aea388fb2bb21dc86a8a34a09d300591c9336f48ec25cadfa0a74e66d190b7cf9f4b825f67ee9a5db593481aca2a0672481feff11eefc7b1db169173b591efc318c1348fccb31f21e71faa9e575e02f862ffbc8578bcda117226a5acca369bbfbc50be304ef0e774e9488b1279b305541012ffab6a015b55f22748158a72ec38c6292135e52620a9b8c19b30b1e907dd6862505652b018ec29a4f268a538c26ac2b07c76fdd58e6f02e83356b1d100b5327f65a24e2d4c19603f4506f2262893e6b29bf2e5ea6b17bd816388693805be4756ab75f2538e89a4bc196395069a0354112284730ca74f83c4fa2859820d2999c33aeaed013c54c1c6b53404a4ada1416060a6625fc23a2f31482dea97028839136beb71935c1441e7736e0cd282ddc65ac21a4364c5a15573f4eb33290c5e3cdbb84c0f4e79009a41c7a10de61dd6a65076c4e239ee947226be924f6f0a5cf8caafd27772b248a4eec556c7e7f490ac9d614dfc8128a6d1de5078137e0e824d7061e7303327224970670c613b843a5b0d48c9692c18d6554baaf6c6cb00c82c0d3882fcadd5dd73859c8203d0465d2f1cfc0d33801beac9ac4f3645c700690bd497f538d820299dc08b509dbf9914547286f558b18ad6ad38b0c90b4c0e10014d5a975b1ad6096425157ea0a970c5096366c5e03284e07a4d2dcb1d3605f141e7f0d3c0f823844cb20de86266da8d5471ea51541f84fe73fa7c02bd5b042d56ff58815b8951f723f63b635ea4d2db7d1284a613c71cbeef9c0c13675b0079a22f520eb7ecd63b819dafd026ba49b442646067e1705ae967f46612b029045d5f2b3542afe57d3455afb5656329df7ecd80632205fb3b6de3bf8433c3800bae113de16afe42173241cff67f4ff1b634c8fac81d9a14dc736b99669b27d80072f987a19626b820dcd22bc88f7914f1a9fb10a456b106aeee1e9263cb1c6c079a8180ddcba1ac6a1b411967b9fd716defb6f456e1508bbf7d2808d4ba559000c2b57f62ae16283ff7e2e144ef2847b5dec2803323210d78b80b5cd798e3910d6813363c7c3b3476d0105f21591cdba1eb5df9cc1c051e34c7c6ae7c186f2908f12abbbfaf07b6fa0184ec60f18ab4f5ff5cd331029c7c632bd2bd9aefaa480c6a59bd4acf9300ecd5f2b352ad905c3fb0b2b1ae1e9aca717caf9f5dbbb3750393de2d421f373bbaaa6d2772839d8e5dc45fbe3d5bda2f544ab58d578351b10e14416add30cf23ad95370d404e703c4f64b042c04d355671666b3a90e631ce0f11e7007027a514823f7354976272f14191acc00c6a937a518057d79b4ed26d0aa7880bb71fe6938cf3c3911e83a066a658fc653c97b8fa00795c4a95d4c5ea0452f424303c656066fa52190f738679389910f163221a6287956216f4dac8560af631478bf56ffa954e772987ca8c2336f8855b8dac6a547090bcca325c5b020f29bee4240c111025ea6e87e97301fbe0f23b81095902eb6ff7528c89abb37d037796c1def752c3c6e48e5addc2f8294deca3a27e5b02c016facad87eeee52c034678fa092605ab1bd8b1bc246f2012acb4b10b8be70a6cf0210adf5542d377041af11e95833b3d069bb9f56584b64ea09f7d8e0c81a9843b18c902ee5d544b0c1a3cab85cc41071a96f3a532f9c1ee0f4739e2c6644e8db17211aa94e658e5084b3d7d096b543340307467d13cbb2f19f4c29f9907decc7a1506e707af264d0528a7b66bbee451c535ab394691f9a960e85cbdbaa98515f9322ca3dfb11d8f0f954e8179164072f90cd9e3607001ed790fdfe7da2f0be821142bfaa5246fcf0f2bfc7950dffba24847f0f6dcf83f15f6bb03436e5e4f7c90aae0205255e6c30642d1c5dc71ca6895df222a16ad4ba71aea8d3e08e50003c96e3fff9566a6670a6debdd28130b43a6c4ba97aebdaee39703ae4901742d254808026affb5fecf0d182d9a0accddf7becd0561d3b09ac1935845037d618690788b54c032e9583a00380bbbfe6c327309c65a62e1d52d9b310e217f66b795e39830bce54dde81f800d981a58c89f0fd73c5360e984779d4912137f1ac3db98351bf31815ee69f51034a0f34050d57b1713b95ff0e04f80b5c90c98e62c284d5d163f0834611209f09a8f439e5fef0b8e1700922c27ed3f735e04c4b44a7e112b9a93e0d7a35eb3d0c9271818541b912251e336327a90351b94234f1e68b16f2d5e8a449fbbcb50d0179cc4c1262f883c1d8ec610de1f78a51964278aa5cc682501e6cc26d069d070d372946e3e647e44448160273a0a0cc576e3ec9f094eca6c2803a025eab8cf50573d48e9714c4c13ebd8603dd4c1c5b790bf24afb8a477cea592fd278e9d07d05b75ed86d75bb89e340f620be4d7eee61402703916a3dfd88285af2a5c3ec370a20941c79f0ffceef712d922c9501d61a774cec163e54a54cb804c5f9982f210d00489a33637c59daf1b428e3c4a42d25c54a917d206e5ba5fed7fe572748b50c8549df20fa19c5bb041e303ec58f4fa2489b4ca4426b6dc340ff5a6636d53806e05d03998b5bb41eccde4794040a564a76590068578f2315f9eb5013b417b909d62856e9ec7226cded9ee1b9e3a0b138aa06eedfe4ba0ef50676d6a4dc4aec0d1d14e4c0ff95d02372a3d86e00e720e5da906e54b8d1171ea45a7f457229ae0da1c298f4bb2dcb65ca2b6ce6314f329b1bceb8d537d193441d2177ae5f6a760830b77a027fc52de393d317696b1e5f5539e8c03f827c0bea22c3ae55b5707c0914b6b46e29e8ff49b1a1d587f862cd923e02a21930c056ab1981dea1e9220f089f66de862a1b847433f09c8660d1fc0410e96d1d8b56ba5955213f64a0fb120e9d0f1931cf023f7e30a83d035a19fad0eeb7a094e0631025046b25da73508e0ff9a6a84a4e9b43dab3a1a81c412e554e99f5c5907161f0ae6abea1ef20068e060bf9f999e47a021db0c1160ea8c51710c10f934b1b923c4c8f80a4adda58280e161cc8901dee6ba80f8a88c96921f3896ef991d935a2ce8cad2a7c9b410ef1086d1efe57b8477a8b9a9419dde319bf226d0a2c2716fb414bc0feb40e940aa50d274b052d390123c3daa4f7559bce7be2b14ed0915a5fad3a6a6cb8fe4e76220c4e0612201d877a5c1533ae62bd2a0f6573220285d7ad4d04eebf9c35d91cf607c0c28010248a208cda7a3bb44774f6129c7edcbc73339c1410bbde758ea21b0a5ca8d90a720f2f1a8f3935f353abfed8331b50fa5c6bd296c9b4a43a5d451c0fe35da26963bd5ed54cf9ae77c7393e7f734465ae293cfb945a061184bd5548003d4bddf991e00bb3ac577796d32f28c2e2c874e7dfb732bb51fb5fd4764ad103a244874b963d33fec20d1d9baaf5ebe99c7ca445e0b86747e16544e1486b260bb43e048046520161c2da0408fddd4c5f164040fc5cf3e51f8f1d687f00f260005e22593815324593c150e274c2fcf2d53cdc96c81bff8729b06a82ff76e2800756a33a7ace3e03275473dff91df6e5822abca60a960a2faf4ac5d60a1fb7750cc2e6a542eb7e25790007cd2c472fb73ff102b0a8037416420408bac0535ef807dacb574c20d9ed95cbbf7854e2038e160df701886ba0622b21dba4f1cc901a0b74c8be25e7a0dcb23b729f669e0f2edb78d90c9660b05e11efec9199bde9960414dd33c318df89222adf62e0220a31ac169c7234685e72f47e45ce1f82c3d30bdd25e810eae298e73ffd99eac44f9869f1947c39b1ea43ecde0397a9e3b49b0f1a3b8766a34c777701debf292c2087c0478e1ae7b9d21fa69f76fbac53aa590185056b7b86993601c2870615d23364e1cbd851f47f67eb72881c31319f97ac06636bc1fae90fdf67e44c614438e446a3f1d404d722cea1a3a4549499c0d4c80505e5913484cd245b170c4d7875b3cc7adc40d1f639f92075709abcd0afd07b0d9354f108b09191ce0765383accf5eeb0a3e28a8496de4801f3fd2e458280fa02d53d4b41a36f85eee29805b18d0906ac7e23af7c713dfd7c72810aaa8942a706e946bb57686c22465993bbd160af52445e1d35fcefe4bb50bcc84d7f0c5f5404fa189ca866ce2cd5f131340e507106c25a6954c8f5696b00d4d6f5e094a3fa073e41b50296530a0300fac26f8e4c0a8f36fcfa95487d0b9a06804aadfdffa20fb6a78dcd773f5c7f091e655384b570b948d13c9db744d2ad2be61762fd528304a55c93cf9683dc11f35d683165ddd1e708f5373ebaa137e40731d331688f4a03272586e31cb38f45bc4a51b5b48e2ad29c6650bfaec726412cd045e73f78880b37deb590d996bea622d8c6456a92f0b1cee5cb9f24906fbab482eb69782fe0062584bcddb549a91c20d1271e7b38fb40f59bc2840ef42670d7454f048822d207631934280442fae0b4a69ecf5cbf087d9d00de490fa703413c2476abecc5a10d975e8fae0a1870300fffcb9e8ad44afca4b85ba3e42cb54a998683991025ad0da2a01a3135ab8321e8276caed898db03008b0d2a1994b2c7cc8078244b58fa0b8e5a9cd24184e2fcc23e8549c68a0351a47da14028b5ececfb82f366e76e2e03c75bb8bf36e3983fe07b2f10f73bf6746c11b19798a1cad183d7c3cc36ae52013c9074b9755a6e95f619abbac953d6626071883ec5aa91af02c41c93adf6bb017acbbcf94505d6271f02f445f78fc3f081e707ccdb4c6f271953df358b6f1008ae795c6401cd319271cbcc0b1e773d7d89f5cc4c20a270c1cd687a72cee8f702863e40bcd13e274e4c00019da0aa6e42b25b7b52935765100f63f04694dae6010c129969c7b8cbece68d081f1712b23e4dd7f4eea2cbbc4e7ecb6d851f084a03f88007f4301ab7f6d14eb3707e2fd65bc1ac9d61bb264c96d38c066016eefd02ece5d026f6a23c78aeed4c515d18c85dc3c98a208ff9c31a87338355a1ddd4032d233fb3aa34d66634b910e7b0daffc06e582d91bdf0bf43581eeb34f60943091cd79aa5979bf310cbef72a315ad6cc311ee8d570501da0c3d01d1a09e72eb01d175620df6e35279c642ae384f090c2cccd0d2e7427c7c3f72d8d6c531f3720b1348d9e3bce76471479a6dcf62b52be88deec325685f484985e04848b8d8f8087eecaa711fc0c71e1f359a12e0ece74e7892ad33a53cadedaf896d914f917909 -generate_ring_signature 62d9fdf998799ad5f0044a6a7c5bcbb9deaaf78ac678f0ca3750aee518456f70 e85e6d34b7a44c497b42634e4e8be3a56e714cf5c44792c29204903769a21091 16 21b726d56ecad082666ffe11fa61408df99af9e47500483421b47a34bcc410c0 314d10d957af2e4da98a98de73d201ce595460aa9f842237ccb0347e9493d3cf 9cbf055445a0e7121e267b3a73e7449e9eb5915b70922f47437dad8f4ec9417b fefea43cf649abf557a369c3f7a11d4812394d1def349ab23e7c2e44d019288a 48360109d5b6da985b6701f47397ecbdc59d97383be7e9b067b318acdd109ecc a97375453701cf393e2a8e95e5b6c2ce365c461eaa62cf1449633e850b5a889d 7ca32230254a075dd5d166b06603ed21cfc4f5215c94bf84ce9ccf3721c44df8 14beb62093b4712b058f10f8232884896e4e85d2ed8ffc1fc6e03b6e1080e2b1 a453729d18b0d90e519e241710b05547b2569dc07ed744dbe3a5c97942e3ca75 5c9896d9305a062aa12eee2bb9b6c8e3be3641528c6d19847081172694d3594c 574a15a29cb4e3c1b244fbb9e2bcaf0cc6c964d19047d3dd44efe0d5bb5ea1ce 0980b5584b6a796bcd0d1e87ecf3be9f1615413e3f1ea237bcaa17108c11a5c8 653a3daca423c001f6f69ecc804ed50a82d0d95cdbdb35c7483fdaeca547d807 18f5a832f606874954b4316e40f69c9df460e505c0a7506f0d42af45c58b483c cee4f248d50d0302575d03de3e792cc5ca9a2cdf58abe5b47be7e1e4a801771a d63afdc5a0cfc9a531b4f099fe8b74b2f9c758c39c1cfa3fda7def01abb4e422 7c23e8fc27aeb5d238494829871baa490fabe516081fa922f3a4161ed0e7c502 10 05881846ec67d764935d6c040dba760a8e40161753de1639dcc9cb740a2db107fa10da97ed599be265dce75afc232372e3a8df3c822682f146be03e780f1300fd24e1e33d1ef5967386c9d20b4a360bfeb1b4767c2dc13a35338aef71c312b0d5c176d26abb5b92aa80122339200c4b7cc03963c34bff697f72ba071385c1903ef2b9010affcc4c76356e6228c3c76047c70905d987fff388239eb48c25cc4012af1d7c05f3b33dee915065392d0ed1c5265935350cdcaf638a86db2d14cd00360fd0e6e2ae2fc172c73c1ec090beb344b3f54db1d0824f52d7488a9fc214b00dcce1443dbaef00ecb07bcffd9ecf8ca45cf4e3569e703c94b2540655e13110dc04bedadf1c305c8b27e7392bcde501d294f75cd47bc58855b1318739c7e290cc87beed32932ea4a48293e47f367cded0a1c3a4db4e9c99daecfd1d1097cba05af0ed127ad8f4a3ebf7784ac7477994bc3ae303b79d1875947ddc6c0da61fa070a8e59831c3cffb03488ae53cfce79bf4e6b7bc98f71e274c44520140bd3130c45e28fe5cf6bb4289649fa3538c476cd294c53bb40d715448e43d0bed5fad50754aa52ec4d686e75400e7286dfb39d6150a7272719d89ea1f922657bc5dfac0f365c468633f0679343b8e625e36b18bf9f2c5d2d6feb156945e862948f6d2603719f830650ec2c2bb194059821c9b6c74a1f064abae3c72ca801439b03d16605506e7524c75c84b97b6e7112c48a1aff4bd563fa3163b6fa4bd1e415cd9d480d98be4d519ab047b3259c1cb99c1e199142942b2ec1fac20e457419d27310b20ef5822441014a18cbb9aae5b75f5c07e73e17f90cf1ead39bda032a8424ee0807375e9f69fc74723b1b11737fb37e06e1419faa9c7b55dce9a3593d215d6a2904fd41afaf6ef2e2229f0c27f094bf6bbe29f57332811f031dff28a71c59e3f903009289db494728d72d5b10fd7bcacea433bf2804b53299b76574916368a8be0ecbe5bc089fa687dde3091ad9bb81a9a52e0de14eb6fd680966d3e5c55e29c5011607feb7514a3f436b31bb480e7a2681c708833dff97a8bff685a1b15b2fa405b14c398582cc7d730493235e38a1c3bfa5705ec909a36d66309dcb87347d3d0ca8c784a70d4608ffa0f35ea3bb2d134cd55caf098c6dc2c44d4379a3b78e4c0877464d1f3ef97e1359f005e5c095fc9649a17ef962e3f3d6c9aa0caaa6fee5072fd4d47675fc1b2377f599dfdc0d6cdc5e5e54919f1d0c9fbe24c896b8984101abac9e1fb9e2cb88c502e5d60f46771195903411a48fb4545a451453871e4c0ccf001f74c8c3054b604a9fd097da2adcfebc84980f9aa493a8d57acf959310016ac9c84254f0af0c75cff4b9708bc1081ab6e9928f6108f736b1b49812ab7d005af0de23d2e687ed153e43b176f0f2c7a95f14ccc2ee1082ee73f6b97c86ff0a -generate_ring_signature 10f3730c2f6a2514d89bc556346e2a37fc87d7e83757248623edeb9fab8ac049 0add4f035c3579eea25efb66d55d73cc4df230ee3a749cb5ec8ed434d913e41a 1 8c906227edaf3c2236ca3f0e9b6aaf208bcf39ff871919427a7719ff092d26f5 1fd2d19d0945cd70b8a3104d3f0a7548a9acc311648967d48ba83203f213a50f 0 bd6a966ff889ef342dffc2e96befc46b687bdfbb776d823fc5e58acfc6691704f89e6e4e90ce5373ad30a99d00a92d2ced7b6f755e5a8a7f9b0ee9969d9fbc06 -generate_ring_signature f4555c7a94cab7fa9604d4c106969a84ad66a469599db08ba49bc24b1e1488bb d97745abc00bb8228a40b47a0344c9556d8dd15964fcf20f0fd82341d6f18670 171 cfc4bef5eaf34348f327005dc7f809d94e495153532aa7bd337e1230de4974da 79b0a445dd281c6c167dbc468a4946bc46d7ea55b1393895ff1e8008f2f53a3e 411bad6789b69ae4a955d7d5bee956a5b7c73ccd3481b6e331fffa049a45d625 c5e8959c5e9f915e5af54c1f77a81fe3cff041c001bf163243bf59c206b9b78f 401660dc495dcb63633517cdfb4c83f7c1bbc39b510caa85d77861bc3f221618 6ca7e36b209d1e1c5b20b78e26ca678325502c504c43e51fe2c9e12d2ef289e4 b295c552bd1495b7b21d99ae5bb7b8025e507a3042b6fbd81cc78f2ab2878927 1a10dd6423205ce8dee6302ca9a40f2257aacc9e954bb6fce5cf4a14889b00fe 4def6357385d6989e58e06f38a50fa51503aaf3b13c2bffa146d2824f93f2fe0 8efd4d3019835bec1143624705a46b9f54dd4f410ad23a75e39f868728585a6a 448e81181967b7c2f211960907184ccc9dc01effeaf2bf0ff3246cf715fa7841 e12006e490cd7037403ccb0cd61a54d6016103d8228ff5bc5b178a4be5b3d5a2 24c6dd871e6f6d1e466e1c2be9779ccf2567abe7533a6d0868b3497346d6f08c 4dc82719c9af722b68c9c9b7a6eff94600c7e6a08240307ec343762f9d24b142 f72f1ebd2e930a6f94e2b3487e3bdc9f8f82c78e8a890635c76455bd12d2620c 508410277ea62390fb737108acb07efd9b4afa8cc3f0492f1735381a6bdd85a8 f98a6c409991d99882a77806afee0f5a4f479f4840279447945b2873c992d257 32e736d6c58b4a36c91cf1b8d9719430db9182e15184a30797eee75dcd966b22 f6fdd93cdc90c61980ea7069933b6dbbd53075b5a0dfea2079a461b4b4ea6658 38cdf0a99c31eda7fc48ffd68989add1a6224503e269a5536701b11e4028708b b1aa00ffa31d1d3d7e645dc9ab2c9d724b3a699702c877e7ea610808dd2ea9f5 1a8f990377f923a024effcf088cc532ea6049d533d59563e398140dbfef2790f 635710a81651e374f11c728151a6b81f8904f4036f70cb3be54c4a1f394780f1 d4c8b7a93f5aa7b5029651f44bfb87ed4e762e9a166e37db35eed7ceded15017 5abde930e31af431a396c120cfb04ae6377f2f653214c76278b5e93ee91c7989 596acbd0cee6be1584cd61634edd8ed33f0fadd3918e8b3398ddee785be0d2e7 197c6902281fba43aa82e272c5cbeec79ba8b28dc0bbb1f1ddecff2c91cf0444 88176dadd11bb0920f9dcb0b53cd9bc720919e663588317d6d48c38fb4c6a795 c623bab71256ec174614b343d79a6b1c7c29f89a94ae9758f60cd5f2c01fc40f bbc6e9dd8b262f08d09935723bd9ceca95667d6000b64d6566985d8ceb02f5f0 e8d10be27173f52da0711d82d8a2ae34925fdec44dc232eacfd24932b2e459c0 05d9f54e15501e036c89fc60c8fdf9ce39a7520d0585e02e852f944a76cc47b4 bb548d6df5b6e342173a857f8378450dfd1c1526399648a05f81b7e72cc5676c 037311c8983b23d7ed1450a24706026c1930d7ead062b4c5806127061c96fa18 41d01eb664f28f27bd51f1959a06120d7eddfeeed185fc4b5b9c67593ca3f750 ee1fa901b60359598a0985f6642fac8604aa654e78f1f3d18a1fc4ecc87536cd 7d69624959350420a65aec671b481fa6ca9f3406e9080acafc5b6dc251e50a56 5315e45e258217f50b9bc1d79bc411aa350d3427080b3cdf5c97ac703861d519 a4ab5d6d62a398b29a4bb0ff983060158e2ed7a81488fb1271e380839d5ab8b5 05985546d407861f5c113c25061eb90876cb7b1d043a74af25c62b406b821337 bad614857399ac6ec7ed7887bd1e9e0fc0320b595233fa0c6797f8dce599ebda eebe0e178a0e1fe78e6233eb6d86d3bd701173831d7f40da0d64cbc572826cea b329aeb55ae0de7a468892cdb57aecde5268829aeb84bb88245111fb438dffa6 fdac8651768a15a0f8e502319d3cf2dc41fd737e975c2b4a428b42db1dcede27 88d3032b6384a94593f5c782e3e7bdb027414c3fd99d8730b2252a7ca744a3a7 1771480e847547152d3aa315218a1c2cfd01cd45ba95182a1b6447103ccceb38 37b27bdf4740b2a100f54f9a289cf58c2b66a4e4f1b13e577095403c46ecdf86 427e01a2c9473a771c6fa5e2dbeccb62d351e429e2947b2cf8c228bb10da4649 15762146795864be7e50a35b2f3155b05eaef4d1b01c61347db5f11d5baff073 69e02c54680cc7205966f38e4a27a37a4a7357026fc38b1b40bce7e7edd5d1ee ef15e86c3ef859f2c85cdf828cd425d4f4ab7aefc11f5a0f4a16daa2b5fd22b0 618cdf2644069de2e8275619d923ead50f93789a4ae2ee8b68b625cfb206b39c 50d292bb61966a8d4beb864d9c120170f1570bd63cf07b41332797b6c29f5c9e 0a34b827392ba1883b610d1422c11696cc281c8b6ae75e961c42be3a3671acca 14730187723cc634969ee839ecf45452304a07bca280f7dae82ab0edc0877c29 699a24951c6ad1649350086f99a1854c89bda4228cb4a472179987daf854cc10 09aeb8ef6645a359661d04a03b7b7ca72c17a0a31b88997264cb49a38b8d7c13 85b0ab6229bbfa7a3b5b7b23811785805f63909500c94fb51d89e8f0554e70bb 3b665ca09ac6eb886900c99aec8e95270ff3ea73c1d8654cafe3acfd40019003 cdadbf8b0087a497967578999992fdb5f6dfbca21531dc5430e41151e051ae56 0ac2710ec9c037dfc4c3f93c5191a14737c0349a2c0ad7f6a44796b7bab64ea0 ceb2bda229231c4d5dc7c031cf687e6bee4d94c75313fc3d662dc8a6925dde77 a530dd5485fb70af577f782c9bb1b3694f832fea5555309dc992c65950137c14 2f55b2ee169c1115ff9eb53e24e1a240b7759af68bf305667fedce45e3f0d619 69aeafa707c68a9aa05a273a1b3fc158a5fdc20e143523cb6362f6ca37f99c25 2e03f9603c7abff4fe2766d73c4a39fdef14d144b0019896ec3685684443f1cb ca18d53a70086097a653b294e2eb531efee7c58909c0a35c80202224e4dee356 aa7b68adc147c53ae015e29d898a72b94ef6b6661f3a54c88a03075c73fbcc81 70cd2e3c6c589814e7a3191ec0f20839bbb2849436b9108110d689abb9e0027a 7dc0f441b3f1c7b35cb5ea301dffdb55e8bfdbf0acad34bd01786107d43a847a 3f08b78c2866d0779ef8a6751b7814b6a509a091c99e96fd3734886a6d001ac5 11db0478b0e9a19dc38723770b1798e3addbf704cf8f5d2e2764d139f0d22a51 f961c491a8525f841bac81919a905dfbd249a7a60ee6257584dfe276ae7950f5 28565b59bedbe41949595332aeb2711fc67733117120b1822c2e9a327e977125 022098f9fa98ecdfcba9ed3a8bf49c72ccd8117cc14d21dfbd22db54deda7ba0 68f94489f7a92f0a9222e201d2b4bba8ad6daa41b4de2c57c7ce9b393dc9365f 34b9147b28a3ac76dbb13ecaeb3f6d6e722a4a8c7d0bfd8efcbeeb187b096a79 b9a3ddbedc533698050e8c4dd60e05919b70fc5d487df6d01b62858b05f48aa4 c214edc1e0d6f77f18a3beb648b37a547ad6f929f3bab96586ec3034d6f9fd8d d04804e17f6bbd4fc3248c049895d3911d3953ac98790ed97f7d038928be2946 08ff0bf8daf6b3b57164169c2b48ca64ada70baa106e164513ff2a5e00a29ce0 bfc8cefb5c9e90ac9e5a1d92e9b7529d813f8041e519fa527b224151af806e26 a07f1068e09111fb6b58ad945f1c7705afe8ffd16cbe5488bc8fb94b8d53caf0 a451ae9ea7500d137403e431646e4ffdf6292489608606042f1a0e373e062f7d 6fe4867afa167c2f14ef976eb6403af05c632057e0d0c5884a3b83052a9cf32d 2e2e29ff51678630871baf5f4b1c97d6474647749de46d887ff31916194cd43f 662a6698e43f9c15cbeb38c3a8f31fb131e1d9b476f0f3a0bf40ee0e8e6a11a2 8421394abfa917e685bec5736e2492f825e7b259b587d6e568929d4a05ae2a0c 442f5c4e472fe9a9ae50496e3ee4281a7945d55a585aa296873e28e2cae5fea9 d09852ea077348503bd7995157301f844afc568e86d3cd18f0b6d415643e3e20 268d7e0eb3a46a11012dabeaba1f7e3574d1e32074bf4a2feded65c12b97453b c122fc5e2fc268e3b10f328e4ec77edc375399c1100dd10acc894903da97b9cd 9f39d95d583cbd4cb2779e0820d40954218f009a7cc5df92e030ecd9329564c3 98e17aee11922bdb6a06e8d5b639097fe9127dbf79d12aa9a8adcab208b36a2e 43250a86c378ab45ea8f34e71a451cdcc8e0709574d40f77357ac3693db3d4b2 f33bf249022052081d7b5da52abccd5fec3330fa176306958c7e3d6291f52984 020c044368cad6dd0e1d4b563ff0d334233c6a875a652e551d0bf8855c9d772b d32198328b301c208a8ffc272e512f909012a07cc99488ca9bf08c8fd8940f83 0832c436f450191a0e0ae66be14f07ed5081fc53f66a0df1315d7358cb299d52 fd2d84f1afa4fbe177b4da82bf8f6a5b46406e4dcd6f308fc54c6eccd018d707 c650a776d5e5f98ca43507f46d2d28048a3e21a5196dbaba699ba1904ff2571a c87c053930f772f7cb317a3191c3c114fc323220d74216c28b9d1354c35a866e 7dc1e344d66e726db6bd8d296dee9d3f04ef75862bf5380e445ecd43b0932618 af34f348b06c894e95c02c6a16fd7e52da6b45663df93c6a2533141959729f7b f99155d1317e0a8014da9f95ef688226097cf59080edfb3cb1a7d8c40c236517 bcffc6582fb43aa29d9df01cfd043166191ae64ea184af279d3c4cec05e46572 dd56ac7d1111f96f932fc79f3b9a33bbe5ab7c2dfac8d3c082c1d07c31147ba1 af799d2346c63aa6e1aff8bcd560b70bf99b3a84780a2186b018f87cdc7becb8 a613368b100cc5a85c4955ad5bc04e5f8d95fafbcd62908e699b984210e548a7 f6db5e3e8cf9f271b129038c706e1a335baed4cb85a23934722e22ed7aad4814 f94f6840a410db8d7809f6f9b6e4898bebe6ee6c792f046cf08a0e192f0af4f6 cb6060273be798eb8e209509a44301993613f4fd5b56b4535c515fa55b4d746a ed1c8d689f250b24e66c8153558ba88317c26cc02ddd3fcc6c9c59cca038dcf8 68d13f2e581dcaa275f2523c351febf927fb6c93e65ca9a293ad6e812b413663 46f723ca4398207c1531aab36297a3f437f1a26458eaa3b7cae6dede9fe8bf91 d74bd9c293e3022a7f7a2a5cb8c22f6da99c4dfac585bc91d4a54428af645a8f 30eb33b7a3cfcb4ce2bb552ff92711152b2b114b9a3dd027a7367b8e8426d5b5 f61968957b10bd9c877b50c5f7c8beb6791800f1f3bbe9b78648d3fa0faeccb8 04e2acbd42014dcb32cc1e7690cf83bc017378fcd3b391ebebc56efb6b515ac7 bbd85c1e26423b3c6c68739a82bb5bb1bb045b8e154ea69faec0c4e55400b79d 87e234d1e02dc9a3cd8167b7fc36b72b2cc9a510dfc160b87e4c3f08046e504c ef996edd8c19019436b04acd173b66a4a881ddffefad2180c07abb7534021af3 2b75cedb11ccebc4875dfbf2f4b18ef82ed352924567cf9b8bedba2e79ac9b3c d012005892ad3bceeddb59a34f98d1717cb85daf2e9fdff671d38d29919c3306 5934b1dac37b15070667de83bfcbfb87386f93dadd3d90abe02115ee1be25511 8c8367ac396509cd1bdc3baf341cb8659e85e597c321cd8b07d8e349cffb27fd db8e1c01cbe556892ea60baabf545c1944bcaca8b03c22d4a1f5e9167b5749c2 26929b9a191e52549d227b3798974397b97d8127911f6945dcd52c3a915df871 bdf06c632061e00b667dff7405eb578912508ce8b1cda679ba90637a6ec9d755 adec4d15f5b6858c8c7fba49da88d68d4bf31cd5b92b34ff29ac5d7cde88cc98 d70026fa9b5753d42069c8def719a909d34d6cab3b1949b5398564bf6f408d70 ace300fd54f1eb3b6428c46feee6824f1ad1b7519c099800f8c90c92f4c52833 0d6a0b164b9b02a3877f8326ba35cce82e4eced1d21af4d2e80f86ca1d8b72ad 3e65edc9aa0612700e957251c766be20acdad8ecbcbac2a645e286c3c42889c1 c797cc975661a163376b9d0ac24abd415490f5c0e5f70f87c40cdbf7f0c76c29 40f0a14168aa61ba89b9e5c40a8548858efaae2990b1a102a6810cd4e14a4200 422dc367b19a024000e1f102653a2db986d13c1be3b0fd9a6d9882f6456cac0b e69f2c3a2328b8546bc48b72f489d782e4f669f0a95e759e2c58101b10fbbbb0 d0b9df63e05f270697be34988384816f750d2cc5f1b058637cc4e494bcb247d1 cf39c2a55ff7c176830e14298088e6482b864bdc9935a880e54000ba2eb0ce9c 47b5d892a0a98abe0646e21bf3acc9414e08e74d9d7ebc46b8c5127e5aecb478 df6c351cef6ffc4738adf60d0f7f995a651e93dfa38d18b5e8be83d6cf7ef6e7 9f765118726950e8cf8f2f6f6db2cae8e49556b0432fe6960fb31f4262acac57 9cf2fdb6049dfecd5cca8e4a5fd17364a89ad0ef7524a28f48aaf7b32309b4cf 13cfdc82e184d2626825ccd9f10915fd95ec8adf1f11dfca92f5fb5771f48a0e a3aa71ccdf007f88880835328b070265dcbec5b8b537af52774d99cad5aeee68 3cc2fa6550177b8354d2f5e241f8b721d2a5366c34494df2cab5ba99864cc23d f2ce0c858dc7639de0154418fdc0f5f36ad7237830b43a200eb1e5b8ed713345 08ed90cab1be91c643d1d9c620c3bf85f3cfe1173c7cadc37ad2dead9b5ad176 00ad99b49db1adf38784bd79bf313794e45de8dfbeadb26dd8a2d475b49a6b71 37f121e481a9282144254a27b07b031e44bf34a47e2ef1bcf7b9b8524db52050 e00d06925df9f5236e69fa2a78b78de859780ca4e8345d50efa819179759e483 a4f6188c99012e9f26fa24abbb7dc87a3057d1bb4b99f4f384e5decf9c17c36c b5a5e73fb99c679b4357da96990a6d19a881e12922f1466958a4daf9af573e88 4a52f4bd038ea6c046ac554f842f88a654a055e5e9bc18bd6172f78dd2c97cb8 8efa9ea083dc3fa22da94cd582a3fee99d6a51db50444b1aea61c4bccc2b6140 ce192be6d8d50cc467a4b520368ab399e880b3eb4d93b8a96bbec74070e7c155 f22f7b08626b947b8d6017b846b258c75d55e1098d381bcfa7440d5ae51ff91d f11cea7db46c8bce9a69f5eef55f9a4131bcb465ea1153c9144fb698b1d936e5 b134a75ebcc9fa5b09567511151c8cc6cadb20af14e11c040f19519a6f613102 59b74ee6ed5cd8ac35f7dcd3b5b3497d391a3cfcbd21afa40a72713cd45b23f1 7f31beff2c2c80200ba74222781dc3b00d1cb9c2a92d0a0deae2032b8b6ebe43 acf94b13dfb0480f64d8f24874daba01d93f09d2d29be66a48e076dcfda39980 d31da219eb8bd9b7ebb4d6723adad876c59e1cb458f66a11b8b1e494940ec782 0f493b671148ad3cc994506460ee02bf973068429f9f1073d2cb09096918a5c4 e7464582dac622f032f7964927c94b2d801f92464c59ee34d533b474e0c4c568 faf9274a260a3f80554a0e9b6015ead2b3c7e39d9d5041cd63f834c5af85f398 424919660a91ecbdf5dc035759894703844ee28939b9eb004ced281901dce148 08df61a2481c760147c0a65a188ebbb4c0a3394bbc7850117317032ba5f7a31a cb51316d6b4d9797ef4ae30b6ea1314aff7d91e1e8b0cdc3d56649b9037cb193 fb517591cd9ed330972170eb93c3563848becb59e905f421afe8fd8f37e5a1e2 9cd6bf970dd2da5899dc28da8446cad1bc6881cea822a9a20debf919b23ab20a 103 c4005b7f84099af86d99f4c4d4d88c86b1d309cfb457d2836b09d6507427e205584ceb61fb1c4c6a9f09042fc06342c94f48ccb65f3b33af21a5ff4f00a0bf03cbdd1e1bd5097866968e0e30ea8f5178ce5240c22c8a974e08adf8d0fe3ae40af32492a7a679b89978cb637ce74e7cf2f71f206d504b0f531ee50bdab1960209c90d925d11af2ca2e502fe88c91e8765d05ff658fb23e51acd408e3ed5542b0a38ae390169c8e8926503662f2a7255ef2741d0d4fc4da24b22e24d4e4409a20533cee9a8b287eb4e7c1d868f8efe97cdc470401b0991df22ec7e46644b3efb0dab6b5db335ad574f218251cdf9f2416f7150781ae7b5697b4064290a284606005d93dcac56034235ff268ea7848befebfcff1084b1016505f65dbc9da14a180b92a0025050d4a89db2dabaeab5ec1751e3dc2508068e22f4d213afd6d590b80959a971ff2425fad3bcd13992dbbdf9785305cea18f04ce131770b4d2e28dba02a00e3b05de5d0fde61e63bdb786ade3ca58947073bb488764606b3ebd0600609e9d9c0adaf2373024a69ea44acdbbd9a84ae74f25488df0be2738eec3409b70045ac54ff862a8c4ddf5d13e95ad3898925280c2485bbf589dcf12a02e1b20a08f8699b92354e4a384cb2ca5fa840c04accaaf7542b9c049fba901a262c96b60beec5d4c2c6022cfa86c49f9e35532a66c94aee232245fc805bd3001cdf05f107994eaf7c4d48018ddcddf742f73dc706880354e36761736e78592a62b72916009e2f80ce8ade0dacfe8655dab6e1d8d4b239e6779620c613778c93c066c6cc0fa61c8d21e5285eccadfa5726dcd0f2c56fb7188ff06b0245ce0579ca01d5e004a9ccfbe6c1e1950cffa962a60c61910dcf778ee4ca227011cc7d7d9c0cc8380ef863d563834a3ebf8cd61a2a399d83ec0f5eaa5c2ec8f10fe068e72892b74a0d88a34a33380f16bdea2437889accfda618f3838ccfa393df5af6d97c7939c20c2224da8f7eeac5107361b7083caf977c138dcc8bade5f68d2aa2caa075b486091d7969480ad8b535041b2c93c29dd893bbb39ec6eca8242120795e6a8aedc10245c83d9f15b0916326980003eb60cecbc47751ce56bc9df1dfb63959170726008cfff9ea58554992292c866075f5778ef572dfabc69a82325949eeb8177a5f09e9aeef78e9fe58d6658d18275548fd0e147b8d60d6e6a577265994b741a3cc06f3c03da8f869a69778d9327d094a5a41c06e25e49901aa8b194aa08660a19603767b339e28050f4bf2d2dae2010e8ab75fa99a1c3b29253a8601009e17168c092ebcf4151f2d51070fb2fef8943cfe456c78cdc4bb7dda09fa768984a88fa30593198e31fea0a546d46f22c7de0c0f6dfe11226f27691deb01b169adf587530f3bc9270b9e1d78a8a67e4b9d70d9e12d9b5f692bd108a2644b1be761729ca40cabcab2cb7bfdea3362563452db9ef7c884a82d0dede94538f5145f313c7f1a0c73cc2eba8c27fcc0b8955d920de6bc8c92ff3e4e7ecc0d1a1221d9407e5aa1034ec66fc12a939a0f2767f2af343a46852fd64c850d5fe82af921eb60840f320319de593ba7c3ec9508c70172aa3b9e0bf2927b778b42b413920fc22d4439d505b6e6469fd6448fd92284c69f912ecb7f4ef0ca274ea68983cf4859d7bd847803fbe21297cb423a6dae7a947384944fcd0c510e149ee52a751ebd4ce214b82908aac302a458417da82e3af5234c925df0551312615016a197ca727adf6e83740282039557233a0e92788b195d13bd59a6b348960dcfddf971274d913d7166a1083dc6ee8c25f1510d056ac0106932d9fb49b48cb1a059e70ab14feb18a15455084252a94d7520172a28ff09631273278741808316fbee95fa1a975e5070281705867fe68506de1bd459805414cf2ad43ced52da167396d1a5104297eb19cce901dff29dfe5a9de9e56f1276d842727b6a1fc2a3b003865b4be8b6fcc44b31990bd9f4c703a5c1081168c57ccb92e969272294d354050d3533b51ceb1c9444a009c09932b58c6c798abd336c413de060aa96c22f32baa3dabb0187d5b45d69270359f61a9832c53ad31dbd9aa5010c9d6954a95128fcb64ee5c4d7d2397188eb0d685d5e4b123494f6094f3fbe103c6ff75e07ff6899b1cf82e17420840e049e03ccd1e9e3849d1e02c9dd3d17b6db737f56b669bc67038befc638b1699bf7240fd7f62de49cf873da500655c3380865c72905f4e58036802850d5d2ae883d220c7c222f15cc7437d37d44dd891c20f361b7d0e1653b3b359d504affab6c25940089be406d304b3cfcfbece51cb505bda6b4488fcc9c9fc7da6babc9bdaf0d2d09447adce0101b60bbd76e1c0bff8b9ebb25932907c9e5e21e88ede4a884e01e0354013f067ec762031c18d4ecacce884da16b7ec49d753e636c9bee70e6b83700892d437b7b6970de0cb3f632a92dba085ba5bbd8b2c02b09a94787daa3e0c90ee4015aae33f414223c3f5823b4500b517bc050dce4b6d8f8f17ed44d8322300b30abdfc14942f17cb13e5da605266c40ef3b386faa9533b8d042999f36f68e0b7002048f4bc81912fd84ceaa12fcae1957d91fc9195b995ebea3487a88997903eb932a8bbaa1df1c7940ccb6369eb47737e95d1ffd34ce9c51488db480471c08fbe050b02dbda9253163237f14ae7533e1b29a39fca035fc1f102a80a7d4160d3feae8f5739ee867d319648fea77094c707846e4541b607e4dbd4f0bcfecd801a76606bd1cc2edd04bc51217f693e873ac4be75595853a402e1686bb5726790a0c7da0075291bcf33214bf86c9dc3fda63861373713abb9490d6c3c7b2a1970a38edc410272942f4758aed302f2184945bfeb26e538788116bca0133e5a79300be3170da7e3544577de06f0ae3746a9e5fabecfe62e80d7c830ab081dba8c1078ce784d26e7850149dcfa5c4be93a6c8621ee9fe02029de2813c5263ec4ba70bd04b6a9f852ec02e101de57b8a7ddb6e7b4e812722c9e1ae1845ef8ab78b800351b4acc41e2160825036c58af2cd05166fa597281eef026c647c3acc69b9170a408783f88f183cff88549c049f3c54f2a29e3b7891aac7d1839346378139c505781b02293baab8a2eaf7c40d11e684e7c3e8e7bd04b5b376c663d506a42faa0f2352dc209c724c6b45bc1c7491065864df2c7948b7cacd0abbfec7597f930a08046a347b7e18089e75f50b65878e59a3ec8158e8d2623828215dcb45a97b410d519421f7367efad7d0b6590c23b495b9d5f751ae444e98153e7929cb75c6ba0b86c63e16abdc3eb2b0f802d8834dd66c36a2b899448edab4df2d42bee0ed7001c952706f90052599beae04b67833a556254b6c505a92052d4bc653f1b7ed2c0e2268b852cdfb990a561d98d1d621245b3ba56f2317dffc97b2a548ac66df3305e51c094fa1ae62ba9cf528bc831439e17c2c707dd900982a1e873217b1ad9d04684ed87c7a14bed1b3e314cc1ce27098d38a9f985c2d575e1d73e5128467ce081fd1841d5dc5d495f2e559032f7136d1f9c2c31c17f9f54ddd0419eeeb9f6e04656f902111736211a21d464a249cff3c7f60bedda472df2525783e2711571a05315cf172b4c1fed6dd6551a068d17bf71ca0e65a945de61530619134b3b0740d335c10e604d5b69dfe3b4cfae2f75f0e915221a7a944243dfdbb7c160f6e350d1a9982b0c172a914480550e778bf345729014189a2e2a7fee38e8db067cec807222476bc4ebc7b409915b9fcaa2dfd3e3011dc50443bc110053c7e434fa47b0649f66b5780e8c9e07f8cf1eecb416d6a078dc6b5e7b6649195552612b91fb603738a109038de305169b62869f27422102d29743d725e72ac6c38db98d5b543040ef47039dfa2b7301efa06ca348c69f3d0a1343cb2b81a9bce0e5e7812631302545adcd437356948ed0440efb14476623608bd17fca782b8df715a18a80a8502203555efb76dcaace047db7b58e14a340a4c40df976cdf1a611a800204eb3d06dde5af61a81c2bdedf93a0982cec2d7e7a2e06f05b0b29df58d22ac0e3f96b0c5312fe5e33fc0a2d8889612765d7a461c26ddc95b6344d6af2f1f6f47b895100ef828d42b6947fd3584b41ceb237c7e9d58b81d95c2e8fda86829e7caf89390d8b7bb98c8064b32e244461952823a7b486d4c77c84f6f97cc871bb397369b40cee4ad48760a76d265c236fa2033fdf937d7cade969de7a63c93363834e1f9f00a5f37a535dd2c1ec403f2475d91464f7bc5caa3f4d7474a30c2cd67c22515007173f2aa863ca6e44adc2edf8b70f6b0112a4134a4c23eb2a06baea34befb4d0e4c6f879a3fc297ff740310327926312228c24e3bda34b1f6d96c97cb415192092338896c126659933003f85bcdff65572fd081c4507cb56b138c488b9a41540835a8368cfd81e73988b1a68c7b1c3f02d3f6f2cf3f72fa4c2a5cb312deb6a10555075870dcf71bd3445f6f234ec13c07fda4ab1b5601c7de4710e9d9de7ed10d0c4ef6661650815e44ad4ac7cad3fa30906caaa9eca732c7fb834fc06f768204039be141561016e8811a36244dafd4477637fac2d8739c4b65527cb540a2980dcde5a701d76c311809cb780271fa03abe32d6a29194432e19d1ccc5c3b821e0617ad6a028ac4897c698d730a9dc9e6b1f5214fca28b2962be458c5f282809a030b0055344efe8483fbe7357e9e77fd2451a524e2f5013c86bde4c748acc6d60525c22e8581a116629e190c6f216d42e47b2deae5bbf9e21aa58066c11865a30df9951ca6d8a4b94745b8042ff09d3cccd4fd5048dcbae803334f81849e07510980a959409402ec713d84edf4cdbafe8dfac332615004ab6e63bb82273101b2027785f7d4014a0b380deca671056d4fb9fff4f637e900ed312a2896fb0efda004b6abac0a75694b3cca9cdd6240edd6b90d338bd752880f4d66e6a29f0c47940053100625e39ae536797a4fe909f5b779a4ea7fcd23e6ce9b345f2d86a4d69f01829b711cd78ff96036fbc6082b74a41de3953080fa7fe34976b0e3318a6ae3075063081e3f7d69721b08b18fcd9bec5374cc049a12018f726d150087b36cd60d513af6a58e3466c8545e650e4bbb7a6e95a7596a8651cf3742291ccfbe21a909321081dc89d0f26b1815c04c437d304e03629370974f109a536237ab3764db0491c8251627f14250e62c371c5037eeff2b264ad4b720ace967dcd3fd7a0bf70ce9f0910bbd16387cbdf2927bab2f77859d94c5988b6d740d2315f9823d987d00b4dda02907ca773852999cdddaa3e74069aba75eabf06602ed315c341993d3090dc2b077196cecc070d99f374f271535cddbcc4de93addcedb3ad21d370359084bdd3df0b5ec967e2684c24dba4e50fc38a6d14aa8fa4490341b4c993824b402ca3313022f243268d53a5628b894cea7e8021ce4312717d649241319f04fe90a5e91f8ad38e9795bed6536655af386e299b45e7afc3198b090d4d04ef203cf09ff64995ebacf67b4f40b6cd16f023c2836b72e30700fc9bd276163227fd1aa0062fe4f494a855aff9fee649872bd75d4a254c1a1849a0f6792ecbee041ddb60fb8f42600e9bc83a81a88b36f55fc966fbd86dfc2b8b9876811c36d830c29a606e6f79f67842ec1eda59a530180eff96872eed57d50d5c223d7b10b07d70ed702a9e7612b81bc298554a16b86ea9fbf491f0d03ec4c63e9d88570d10ce78e6600adcf7ee7d949cb8a51277f7aee1f9925c1327870161ee54de401a89b0e54e30bfddffe9f5a45e8e5ce2c406d8251f8ee8519c0cd949f189e2a805c8681e05808ccde4e1f20d48efacb9f407bcc2f30130e0d94add8c89aa02badb1463560ff00aa5faa03df299ae067bf972a1910c7ac2273281b3cdaa76263eea27f432d710b206c19c819848bc0293a4f1b57efb5c5d14cd075772c3e2c0f3bc86551137c062c9588a7e2f98bb2f6328cda55577be501450a737ecae4155d031b5b4c616a09e4b596583962a7ec631e28c49e4da6c7c6d45260d74f128ed7364a54fe82b205ae56b8c6fd079cac3886abd2260aa96ea1850320c3eb90c90e52b79d4bfd4506417b8cb3335540665a6c35131f5fa5695a6ba89e821ee622419f9c3448172906ab19c61f2f190166419a79a00020691da7eba2414531c5d94f6c2b9eec972d044b85f586e75ef500d84accfba411397d141b5c0898dd0b5f4e240106e4b01901ec315d143fee6cb7ef1129cd814d4baacd49e6ad380c58bce567209ab449af03e7a1d392ea99c810ebcf757915f601383fdcda4ea584a05e0b6085fec3305e0ff11e11e298e7bd2db47d8c40558bb3568fba5503703222b8947ca69b8c63300c72e257655b8a905cbbbac6fe9646c61fa59193358037201064e84ed8ba6af408aa9bf4eefe93893d7190153524640d8ed37adb397f0b14067dd1b1f98cd65b085e53f66f5d597d4c467651826b72d5e391c7066a6559375271d7fa6f12ceca0be2af57575eb9d729185ee66d07072507f37e84f20954d722402f3d6a88418704d78ed32097d3a1868f3dd38b1690c6dccfe7c18085626dffd8899e860f19ee07d8650453643ba6728997c9228077e63225ff99019d6645fbcab469039e5a1a07c63e611ab552b6ddd6d6bcacf5bbdcfa08a2a0a02d11ac2ee35dbccfedb46c0c1022ff7873a3a3ce1cbb5c7633005f85c352ebe3fa1e6aeca55564334b776f0e75bac8f1366d8debb23d36d306a47a6c4c1a5e6caba7d07d0c07fb7c90729401a28a7001e1be3ef09b597fad5bbeffa10cca5871ab50797bf58bd31425d40e05cc7035ebcc23cd214f9a0882016a798cf99473f1a63bc1d650f5da3bd2211107779497a9ddc7bf0801413e600fe02c520cc9647dc48917bd2e0d4c6514d678071415954a00064f863c6ef5981bad9a0361f77d0920616150c67c9db21b5f7601af40b4432d6ffa8df4a1a1a421e0b90dc29d10ecd50821235fcf8d0077da0f06313ba80169ea4fac296376a43ce092d73d597292548e3c9f0cdba6daa27c230453b4c83109c9a38b468a99185261adef5f60c4521e168bc092108abd38531308548187595217a1b1bf20d39b0add80fe3513a1ca2d4ae118f69dc8c2433b230583783c168825bd87feb84a40cdb826a66d85ce7ff06ae07b828e315da385a903ab156ad4c68ccddf1cee86e01c9b7c0144b311dc09737d57089cdebaaf7905056e809f18ee6130f241ef59ebd6252fbbcc1048efba218c877c1a55ac7945640671e0ebd27ecab1ceba6501b8878c9a7c77ab06704d665cad597f0a4ad6bc4e046bd3a59fbace06d3f1067b18307d42b278c6ddb961ff168c205c0f4f872dd10fa077b7daa4fc25e2bf234c1d94848689cf4febeb7dd0817d56bfbd034524590d3cd69e780fca7f49ba6ceb76e8c1889a3c2cbbb0762bc8b434854c0ffdfe04085adc5d7fd8341e1d3f5ecfbbdab41cd4c80c72b3c6dcd8ea9630c2221c0be80795e46530e21a828f26cb0fa55880c127b059b968d910dcfb59b044176d82ca0f2c67ff28e56218d44896a861228e769cf2616d0b1ef07a598cd8a940ac4f4f05d62461c9c14241b9f5072490b9bd09a4e95b9f3e26afee603ea6a4ec95dded0f1a2538b0efcff1ec808e73669c36df0bb9de2a7b25470b28580807fd7b685d0e1cedc076ac99dcbb166c2349a6046c4d3e8aa7ccad710a15d6f7ddc461b7710182402da2d909cf2eee7427ab38b0cdcc9505928a76a2ece24261b9e47ffdd60c824e4ec14caa27c5f185878a5b5832bee3cb90b8966f08e1df25d3913c72c505d5936b43051cba251785724f3f21a114e0f184d3ecf62807260b2ac86fa8840f4f0861554966445394c4082905e5d8da75a3f1e068366e98312088a93e111602ae3bf228c29390ee8aa0706245750336bf77ae40935c24d92e5c4815cc36560d7926e77238bb7aa2605ccfcf4d2399d36d9c0e9b8c1b9e973efba8e1fbf0c502c6964a26ba707ba9e743c5f05dcffd4f2f13b2bf187cb12f92a2a96c68be9506b79903e78dbc97b451f113f9827377a33f96a89e05cac3d5d7b9e2f3a68e610dba78a42da14b4ae6d4de224f535933875e98cac72a322d83897a46de2601a70a0935b938a07b2f1b3c3229b8c213d7a8454645de3b4c0abea05b177cb346520b4b57ab4dbd112c902c295d5e9c70caece6e848c26250e1bde26147370089a1028a385f4cbcf446f2e4eb50a640a6f754cdde3154066d657939d89560173120045229b5ad986b8da057649afadc8e7d32a01974e40ac0aae49b81f823dc3fbb0fcaad924dfd5d020df02dea72c5d9d6d4e1301f7c9031ea2115e88003b210b60f0e1557463125960487477583bf42678c1e36b5cc21a57f562a42e8759d2f06098bd1a87edd22860919dabd94a782a2edd71dd92b90e672243c8ee039d6498b071efdde3575f9fdf02edbbaf1b7e4543814aa416e4005d3367dba7777f0549408fdb65bbf538c332c39f64ccbe47526d3d525a4e5e8418660be5a68c29308660cbfc3728d762977266701f873128e8c0a1be969c1bf3a6d0146b76d79d6bfd70940917542a0807e6ae41122e41568e9defb378aa97e81563357a811ade702d60adf978f3cbaaa5281b50dc36f6cbaf422dd3782fd2fb6ceea22dfc1daa58df00be4590cf1ae0fbdb601913511ba4001340c859bdea4c27b2019534f3bed911c0ba285b4c2e86cb7bb6d7a63d42225082ab086da5330ffdc31c7110cd803fffa05a67f387eed0e2c8ad597bc70dbc6256581a71fc783c6a46482aa337e19a18007bf9254a3cea617f52c0914ab8c55b3ca424797fbef9dec1b1968f8d3be700d044c01602a7fa630cb1333d93bbb46a06bacf33b41fd9536f75c9e2cab52a99e077983cca9680c838d16ace80671ff7a8187996ab3ba728967f0be634ae4452905ea248df97cbecae786d8de14787c6d9bb50cfbf0a0941e181d2f8b2988538d080196b32319c11afa12a1fd670dbe1da4da1d512f16163c1cc24c81a2a683e109c0855489e7339e0c02501454958273b551db94e2416e30585059f36f7abe75060b55f4195ead79c0b47ad74b3358a05f4b8f48dae88d363aaaafdc639ee36c000b634b766f638a92137dc1bd35e515f4faa738285f6e62aee8e1f0b479172b099dd621fbe820165aca0c4cab402cde02666486f51a137b8c9b5bddf4c1a70c06798bb0b105c5e4ca6669cd74886cf41542419b4012567fdd220d488c4bf6d30d8c8682347026a1aac889c74c31a6c23287ab862f7174ca0b95982fbf465d8107045b4741c6cabc2a6c804d49ef00f82ae33860249d23e9f35ef8a9d09c92e90f07b569259ed27da7636b0b515ba6be18bc9c11066e26808a3142e0cb8b5a5b09780d3f92cac1621d3a78edd3027a191759792ed3e2c3346132892040a1f48b01cae02f2fc732fc280cfd11f7307020bdc5bf3fad212919d49cdfa886eb104c0c914f91ae618347b43ea84a7dabdb4673f9a779e61137640c8581552e5bc14f0dc71b08f4ae16ae354b00939ff9b9a934a96872c4ac5752f0a4558322364efb08a8d6e8d473a28efcc482b5ecb8e82fae20ff6dba6be658e31a1ae789de6e6702f5bcdd837241599f6b674bdd17e07c1b5bd3a9f49b8ee4e8a071a1f3049fd5095f799898915b64bdf7b95bf6107af49108e37dfc27f5b97f9dbb97d36cf39605a870cf8ab5b2d6355c39ec8d707fc4e0be499c743d7ccc657a3b6abe096b7a0f11cabea39c3a61cb1a42c88d3bc36d26206b13d7c53e497726e65f454f18ae06acd7ebf0d8bb2f63ae1537373ce69ed9c65b4c46b4d582cd5471dcc9d285d504fb0a8063614fc87335ef44f77020a158b53097d72ee85b19239fb866aa86150ae870cd6c1f8bb86d443111d4248b945eebfe6246e3cf17fd5b13fee1ff35b50eb5f58f2c8a36c13e8447075929ce82e509ed19e63d347c144a2dbce87d33e40bb53e7cc2a31154de4ec5ae76146db2c3ae5bc8b53a472625a047b986ec305007ace4e9309794e215a708dd43932692dcc6364c5f94961221fa978ceab4725c004925f96dc6405ee85d0f7722b3075360f2aa08994947add14ce08ce2cf69d4043db4c8dac58fa3e3e13a80e9e1087cea9adb228b87b40922e8bf626b50a531056b7c29a9dbc7f2c3c34cafda827cfb8d1a29608f96b629bdc612ba08d3c1f407b769ab8f820adca00226bf94f10572c09c16dabef485574b27d4a592302ba40ecefdf9e16472596adddd35539fc41e042574071fd579ab487ab58d4fd8d8b80673e3809fb09e00ab1cdff8d628df800723db33095e9644ea0b078848051a6c0815a597990c66ed58a49c1a882f6fb98beb92c5a4f95263f99acbaafb310ea10eb572d3e7fa254af28cba87fc73d12696d52a9666e1d74b2618c61f61427e4e0ab06a53fc1aa297e1c1cc97b85b3bf0a76e1ea2d84d46a7929cd9c33f4ee5220a689c0b99f1b77bb677a89d4919f85e152302050ca441234d6668294e8554bf0bf05c12a024dad03956c3e71b77679dfe44e049f105dc37be6f07f7ce034d8a038cea4756c5574ab2b08af331da602b123e4c48ec5fbc79a1e1619de988bece0ebc8d4699a8342d74aa51de0297ae4c0bc372ac8d5ddf682cb6e8c575d9ed7407071e6c4844fb93ab55b8216d67c329ecba25361f54ce5f129ca7d95af68f5907c7dd785f2d44b735078d9d85c23d24fefc3c2fbfb73428b37065ed2a37e4140745810f5d09c84029572ed5808d5328bf647a9267493fe6bb986d5dbdab587e08c82f7d0541f61927688af3640983368df5fc4dd7f12406f526622688477c5a0a7a999bd74539b9d8394039574adc34481b8baa55194ae8ba963c7aae52f92809cf7c4e08bf94fcf0519aae4b0d9018de1c5d54b74093fad40a1e379c6d8bad01524c0a1c6140b8d0980c6cf202bb9600dfa914e025fe1e60c7a4e81af8bd3b05c3892b87bb58aeaaf3664d01e6cad4c1e699f50842b2235c94877be821f6af08ec653bdfaa75288bd30eb8951ea1d3f1c07e6d95e153185a0183b9519d0e690f5226a0abebd8426f3c8b81a2ef59adabb9acd956fbfdf1687c2b8858d4624707c642a5b942c628a46be04015703a0ecc6160b94a68ac59eb428c7e730c04410240a1dfc9c2d4f86ff0b515fa433e607ea565f3316e356867dd6f284dba6ef700b7bf16825d6e87ae1da1d260421ca3a2402da69511cd4b55dc0e276b4ca61504c483e022b236f9ccfa169e20c7b799631a1a8144245453b8dfd0c415cf5c0301d7c954434150048d2db19e665c4eea2620bd8c92eb4a6f0de4be567b2621670ecf253972dc86805691f520559edeaa18a3158c145f73a4174b9c5e14b9139e07fc680cf861aab7e581ddeadc5bfc25f3abdfef060341138449aeaa4bf8844c010c8aa2db9345a4673488ada9b03c0732d796f74fe391ee337b9d391d126c45035a9c6285292c9dbc262c43d6ea067ad9b78af6ea05d7e372a0c3395199fa300669de109c9b3a4f73d6feead31dfd04aff779d51afc58815c3eaea53fc6312202e8244fe07792aeb38a23d267cb90f0b62f871d63010ff351804cee6a4245c009d5559882150c1d490fd72c5ceafadb96518bb31dcd23ec7b3e67110e815ba905f8ba7354b08e9a9442552637d6196ea82d89d85c55f8a2aba141883e6dbf22043fce50360c6841f821550820e178d7aa65044cf8df8d2e3ed0165ec0f17c280d55ea15df2f7591c9b9b5430bc48154966caa556b124e9c82a259b54417afca04024a2d4a8404b72b42ed3aa8a0d58681ded9b4c79f9e2f7b0f65fc0f067c290ed7a813cc3ccacbc6ad3b3beff2e5db5923245ab9ce5980e04fec4afcebc3e5086db8917d93c4c36ea6dd8fb832b42ce017d242979f9622f4dfb56f19b710c50c86fee367f08ae398fa12350cf6ea9e3f02304ea51a4480f0b6e5db879912d70a5083d7fbfa72d9c2312282dcd14bf6d7df02d76217a57057c6c018f00b720406d586aea6b712aed2153b71495f6788566efd13ef83af4b97703852722696450aa5c95eeaf7d233e09a7494a622e976a36b2024152e3d2550e3c16481cfa51f0a0251dce06d84a8356c4f44ec2aac2ec3a6e318f91154262b9a66cc83d4524e039bf7661be91a8a74ee96e6667db9ba9b5a5b77fb3fe01c942441027e6cdd010ca2f460d1a7b80b60fe866bc4de84d14891360afc0ebac9b712f851a420b2510c8f6932c05d2664e86ef37604ce4095a2c24e4920298e31188f0b22621b7b010eb751a484c683ae034c334c912cbfc31f06cd1492b03210ada53fc03c871cb6020548c5e502ac55873bc1234ba8424057407f418de57b5e1e65e65e84befa2b071ebf7b5b205791a716c24d60fd7165e25ebe34e523eefbd6a7dd55e6334d0209644f2a77e4326dc4d650e42e2734ec12f943c5554d480e206d4c02b326ca3401cc34f1812ec0c138a8a1adc4ff3f0900d0a6e3ac781e514739816fd9b3ebaa01a043d3722064168745ed1e7abd00d13db2f817f341699e1d95a057020c9c9a0c8471f8be4d78c21e0b8fcc4d6988683e399cbc46a77460f899d698e2769ada0ed6304f05cca2cd8d492107ce32328f6454e150e1c568b9cb9ae76e9fcd74da0f7bcd4fa301d47e6ceeb64b513d203cfec1a14b1b0ce766ca2b7b76344d01e00328dc94f66262f4d4e9f05d7ed3f631b71980242a3fc3390f5b2a17931cf0e6020dd405ab2f6dba054f20c15ae5b2530e20fc9d3b5cff6ae03bb2099ad8b6650d47e551e29840c7a3af5592b12bee0ec826c88743cf17319b9237933544fc30040f467150422d493469a8bc7b290419a3b5ac0e12dd82b185a3d689b51308d20660471b6e27392468e6bdfbe1c8e97e71d28f217f4766b392e7966ff2e734ed05e9434ed3865228e9bb974410a30a4db297c1bf6acd48116b9ba6c463a673ed046610918f4fb74eecc1befd3f2e69d3f5e198097bd0c9842a541779f92eb27506494ae483fa7afdc1191f394ed70cddcede4819039dd3d6ef388858050cadb40e5d7354ff9d1ee52674e8660b815551415dc266568213832ff3244ab70292b108d448ee52eb8b47fb5b71aa5eec54f09d595cbeb021e56baae6609348ed70d40d234d65a1bf4f409c859a5f2365083398fd5463ee536ecc9755b4754d69692505551ab8ce1f18cf3c1c176ccd3ed94c53964801cc9f45857303fbc1ee56d8ad00ba6aa5a54245715de37762ea80e11561fdab977b48f489526c7eacb11de664077c831ff5716a56dfb371a87926be80c339ec86f37bce3f4b319b339b7271f70a928ebef14e8bd021f30b9a2627ecce281a0d2c21c240231a77f0a78d8642630d5bb20dae55979d6b6551e3d8892008e2af2f4da750d9ff2bf0e097f6d0f80109fe016be02b7279117d12ac833bcf63c46bb274d71dc3582540d0264924a3ed0b88e1b27c02dc0c2c6b94a01ec02ba6ceee7c0d74cfaa0315d607f4dd38112d00ae7c1091daaadf9581a1d95e8fa16a51690ca9a32cd1067bd4bdee63cbc8f304e3cb7e2e70ea30f9cc30dba0d50c26318bbc3c4353501636a4fd092dcb52030dfb10033569457345cea511310b8ac9c3f7638dd36484040f9fd358568679af08d8c7355b9855d515f47999eab3b135b39e611f94887e1bcc278a8084b57e8e0fb2892c956ccc0e008e84e167a228508b03f49bad890e1c7ed0791cce3a7d5d00c9b20a71b62843ca34c3445aec9c6e76c4adfca122e998a82323ea609a462600cff9a28597e67d3d19a1d9ba47395286ff836bf343a042a6e3012fbf0622bb079cb5ea29833e6282fff347a12b32ccecb2a7330dbe6512be4d4203ae9ce9110de41d3681cf43d0a80fd83709028441ac63bcb940d33fb7bb0c01bcab116f2f0428eecbf87993a73bc55b93912ac8ebc23631c44a4a9006653d035d196a0a2d09dd0dfbcd4f07c56cf47da88e48c2f67d5396364920b8ea9b3ae86a7df54238077a4458cc51589ef2078b3ebe4f8b078b00c8156d637672a719edf12e5fe9ec067b2972b80ec2f9747270748f042dd2a9b2a35e96c64407b4a345b6301f590407d45d9828fd360043d9d0757b8d32a5a5fae234bb43645e5ce4d95146c910e4072b9bdf9d3f555abd7438c20821630e72a62e640a374033a971d52c8612053705262560181519e2822f9bc350514442c58b0761f7f67c5726025e23550c9da80c97ecd16e9c56a8e8e2b33d4a076973d7cab7b9c119052a20cba15f3305007e068da9c16fa464531a47021c6ed27ac7a6c28caa472a306214fd2d6bcfa9d8c50f80edda049a9b927781d040a13ea5446a334056b00f7581f58bd0b9fd6c552a0a2a6c3913903791b2c841fea4321776b647d3c367a710b68ff661de9518646b0834021bf0119e4b2e55bcf4d5e7b04626a92a3e124c8296382883ecd9a9cdc70a058760d77b227eb5cbff83c631346572a04cbf4ea5f101ec578ad598f2cc0b01396f8f7ef41ad3e6a0610436f71ce32a80d2272426a91be8b6899a4fcc6af107da520e92f43a0c0b2617918f2da88e50724a69fb8f08ec39e43ebc86355c0c071ee9deecf828f27f22c72b9dfa50a330cc16637722dfc94869c8a03395131201f61ff990e94e936579d0965a7ed235b093eb1239d9303f3216726153e4b4e90f4a864aabc64cedb7cde7309bb29e8f1679e1d35dddd89914632f28b789747f07c23604cf99a7aea96bdca25a7c0eb1048f0d0ed7c538b3ddd7b17b9d663cc806a822b1b6c20c748743511e29bd6bbb63a92905be2fcbb9cd59141cff7c001800bb621adc38dde844a40136d2e792c775833bc280c2b830b68ea2de1b8b833a07d7a7ed08645bda54ba4301f26e0f29e0576b66c854bb2b61e11f4332fcf7a90f03346f16fc29d2190bd5c3c1e5c3eacb0b1acf38a5d805901173199e6e4fc608da64284c5a840423aa43a32e39615cb717c924176b7954da847eb619fa6a6609f39281f51130ec5175209361935ad03f32f59038234b0555d87eead6fb5a2c0db639121d4e4003caf2e27058e5709f78a53f6cc4b5b0fecd7266e528f0d70e0515845c905b136b752975689bc8604a188405fed19ce6d003b829c601bb6b17020c4ed76cf1c5e2b2c13b36011f308a7cce19b2ffd8bdefd0297fdd2ed96de705e8b5e0fbdadcd83fdb76cf89c23c73b325585a17772a5bfdf8ac93b94480660c2919ea069fa4b0288669633a3d54b930f5fa395f321cccd058a2d7981253000940eb471834db32fe7700dba57426c23dabc2499ada11aa8e5bcfe568c4f5cb0b0c2a9baff4957d45964a7ec37e97450681308f270dfa347943e3691e8faf8e0ca196a02732a75d0400fee8681d2a49cf83e04b162f25bdd825fe058d4493f102a609181b56261bf5d4a195c1f14c07dadd9a9d3ad47e20fbedcca3d66a6a3005 -generate_ring_signature c4f2c0a39e10a7d2881c8753890aaac6ac136088a60bfdb67d9f4b17f5670464 8330fbc47f5ef2d5bcf3109e30396640363dab70a4760847e1ede29a99a660e2 112 e47318b68aa07faa35ef3ae5b8ac38acbb0fbaf3def0a4bcfff10395650c1eb3 0059e481fdff16f9b76cd2203d707be8ac31d48614585fccdc232a1e89841d2a b16f9868b930ad0f327f095f2f58eee17344ef219e5119c2a4d23078f3288af2 d375e7d98e7f286e38459c0a90a742c0e9db87f173609b3e088d6b0d1eb3a71b b8aeaad7d8293c44eba8932b8d7ebdc654d48ee3bb99a2ce9320b5356c363aca 016437d4ce1c2ec84d278ad1151e86005ba0757cdb110145110fa26b74038590 70bbd94b724d740a11d7d4a816c4c87f3eb7bcb2b17004c0ca11afd3671d6bf0 8346fdf809bce48d576e43e8005cbd6290633094eb508f7b1b9c2a8225a169b7 d66885f9ef8d956b5f7f65641651e31302075ce1b5865c5a241fe9eea9b29d22 8314224a7d53944a56d8ca1db88ce4f86a63b4663eefb779cf8153e2561fe761 bbaaa6e1e54ca7dbf72e37893f2154e027f4fa16175be97626efbbdc69586e6c 113bd03d75850ac055e90308da8b18f336ce2f7a33a88403dd26f5252506311a 652f8202dd69d0d86855a85f39f01eb961046f598588d8082ff4b4bea0501af0 24342da5fe22d17ca26d88f21357e5d375dea5e293ea81bd8ddcd5727213f196 392997ed25a6b43ff9f800a04131a81fdd28b839bbcf017337d407b145856907 abcae499ea45e168aa579ca1d7f5cde47450cf61bdb768b74f38684227be9a20 41793fa54c828bd0eb3a127ccbe27c4400055b2e7199ea5c918b88ee0d983314 c57bcceec6f61fb7de098dd8ee46f9d5cfc42cf864306601ab6dac9229efe5d4 2f9c53e941b12af7d6d1f49617aa8984be45080837d56c015ef28041d70bbb6e 16beac4e9d17d70a7eb517f110d8e7ab5cf60b4234f0064a884330e7af8f8264 fbdd6593adcbedb594273cdb4f71d628e6922f572ae7b94d560ad1ee543e17e8 3cc322f308c404283bc3a5476b262744a2d23402b4c8edd729b963a1417f08a6 1cd533cdf11e6c7078cce85de6290555fd75411a556c128a9962b7dd6f4d5c09 51ecac75cd208d0dd87edbafff96006fdcc82eaafc0a6a4084444802ad396758 1409b737766520c2d4789b6d59c26341c7aa1ed815f5674e794d9d0af5d83647 ff676950fa8d97c9c227cec21314b2970fd0e7fd688c64737a246eee1ce7167f ee4cef48d1ecb46fbceb2db3768f26d5d41424c5c7263e5df8dc206642445681 635b8c1a27a5ad357b46ed43f5911da74f20df7538ccab7afe574a4ec152b4c7 8f1ed5f84e8d913a43bf95b9f1566cfc3a067d30a28194f3fca347d2b937851e 1b97e52ae79c274e456980c2930f47174197392c8576111136cb6354d3f844a5 114069c991bde006821a4bf4d7981168046477d02fd97826d812d9f16f77907a b655863086ef74aa89ec9dbeb65bd766bc59e600f2fb91c06de972d813eb2ce0 a0f739a4e1b36c8cc807d771c84e081ea83a49ba98e194b0604d2d516665b778 58fb8b5f2a78e34edf2caec39b3f382d5c5af7e6efc6260e55d139a7371d25d3 821efd6c97ca6faa08c9b14624e4e143e52cde411d27c05cd1ad1c4b126f6e67 b20135c3919f7efc856e39bab403fb72d11970c31660a418b8aa67a427a0b303 fefdcd2c9f62d2788aed73c44a3632486974a7c146d5814229132b136e21e413 db6b3594fc8d6e4086aaac78f29e786d988d88818f175d2ffda41d5a472711c7 07b7567fb88ce0f9f467d8c42f1432224fff4629e4e46ab69026340c6b2a7e43 a1644980560aa39caf5deec4a899557be279f3d9503b973450f08c4dd6e82fae 74eb226428afdbcc7558ada5d79a5b6bfdcc9bb8338e75b750a27ccc083d919c b9239985dec6a42c08999efa4e7817fdab6b49301f04559daa1b80adf42b355e 10113e293205f5847c7c8d8f41083e82f3a525b5f56de04359706e5b473babe7 62156ff12c819c07a5b399c6a5694cf81b3cad3182d9c89fe9493399df4d7fcb 0d88e5842e2a1507642926ee6f947772799e27c4276e84a0a377f28e8787766d da17155ac68b93a53b3450cff5c3627b633b2b7464d3f0a74d9f47bc7a9b63fd 027b33143e2bc160670358bd4f206b7650ab3ca6120f163eaf7d52b1f6419ad0 38dcf4d9c7f711c8c3f333ecd93ec97e22abc07670a8c8658e6277d579923d7b e88323c9eaddcd13f3348bf85f5251f593f034ade1ac3b5309b0d542443a5e37 fa14c4f0c750ce4b52d4811caa95d3c9a7ad209966683cbf083e24d00e1765f8 838365eac90f707d698b76078f9ec1d896590f9adfeb5c0dc219d80b42929d63 e599e66bf44e7fccb2722f3a97df6fe782e80811e957a6d79108dd700d46deaf 63e1ac5f9583e1463db1c0dbea5f5780eea86c3863fb7f2f7144b094d52713c0 f30040af05b4f9d55c2cbe1de1c2be3d0a464a3c2a07590ca5248eaa76947ed8 f293f6c22c31534998d09fcc9f83c6711345ef9acb4799297af1a30ba50889e7 6adf66f4a7655d9e80dd691cbb6ba6b0c34ddf01e00bef4020f5fdd993bfa62e 7413a65c5acb2f77d01af852e1d17d05544d767f62761ec4bba98ebeab91db0a a604ccb842e25ad2739ada5513fa55c922e98a1cb47db75cd945fd1821a8a84b 760744f0d42cb0fbb23e3be8e04860eeff2c489c93e39cb7fd3e644313376de4 d3319b1bfc438b6c652aec300eaba43a8d1ecb0b10ce7b1456732042b0d6c219 f8a118056a6be318825229a5bbc9800b6002522e577ddef8382d272513672bad bc8b2c33bb713ed0d4cbd68d7c118e312fcad230965cb8086dcc60e0f725ce87 1d7bf114a3d4e60c584046097d308779be8ebfd81bc4cc2ed7434f700d0f877c ad197648d3c14b3a127c04a02b1bea5b8dc8e369096a3dd74c6eb1ffd9686449 6d70e6bd2eb0a115f51c5f4a1a5fcfb052340110b9db067916687ec8e5f581d0 5708259e096e2c0f23724fc835626eafbc11e98a8672e36360ab580e8abc23f8 64959a011b73de580cf315a0799bd7f4e24538dc149ffe9fa582fe16a1389a4b 987abdaa231434b344aaf7dbe32040701e1c7a5bd7cde69e92aa17800574d6b7 71e094387ec015e8bdd1684f778d544e0868a27a2cce16e3245863e279d36858 297bca83ea72ace5734a5b734743de740fe5d17f2d9a61afc28b5d3174a4d899 4b676cd079de1a9222bb783ea75c17ae3e16bc08b3618e4ff201a9fe849c042e e927115998105d74e0f76b3ce1c3a46b0fef5c68f6061949c3b3fe7f21a321c6 95438c8204ca32bd089293645bc0eafe8552fe14ec29a232fb1ad4fc619932af 5b8d7ffb49e11b950d8cafae7bc3319c9b399dae92de13a01ec7226a7821fa65 a1a64ad18b13235f8ac0c33eef61c152050f8ec646f4f92d7fc9848ad59ecdc0 d728a9547eb0391c9009cfc4ac05409c42fdf5609034354004f0fa4d5441878a 784d8afaad3bf0437067961f1ee47c71e609cada0b97c636aa87a4da8cd640da 9e562362de224ee6178006c3f3eaa0e211fa9c0b9e4a909659e7e0d2a28cdd48 b31b9f4a7e801c99f98d1b4523457a434d623afd8631163f7ee99e14a7b6870f 9164ca548303e3f8e0ff9614e064af82f8cedcec6fd76541210bdef127eb450c 82d00ea6aa39897b10534f681a739925d179e3c25f87d582982988ff8813d4c2 c3cc009f53709178261b9fd064f31bc3397e4652f37db77717cac41430f68b0b 3c6a52119f73f153c9b740b10e160e88a878a15a685c6e426494c1a190bf2ba8 787fd20038a29141633d628f1d9be6c78486db3256641d4c5bff7bc6ddf3787f 5f8f4faa52b8c26f56831f67bed9ceb8a3e98243b5d89944a0e21e78c523be86 ff57fef6e81f2c1d5ea0f39579e30a2330b7b30058d65cb5100f6fb91db481e4 6faad18ac496e6517c09c2ffb99ef74ee010f1a70016477aa92f04f1272cd725 8bf8561b844beb409a9603af71af4ffca292776452278995a2768f924069132f 0573f9fc57a663c0ff3b2cc35f4301465e2c5737ce086d2159adb28100a9d8b1 44273327e8d0447d0205ca23ea4991f0167f82a7dc7dc9a30040eada716d2855 223250e4ee92ab39a66d8c5d10cc1d859f8e129522763c03afd9c1ff982c8d3d efc9951e85bd27fddc0dad8179ad34a125b21a24f0f27dee656e5be965f54dad 2b31f9237409aa3ddd3789f095404bb3bf9557c7d1919227a4d812f2eb7afb9d b4d5426a38af058bed01586fd89efc34fc60cfbc95d4a3a34c722e05c5457c1b fa9cdd9ee59c34fa855609a835d3bde169d545ea653702f0a9b7645c8a8d472f 377077cbe71528c3b0bcf76ab93ba7451da7adea27d31234099289b05b22ab1f 8e5ea1ca5ff58b0d5e73e959b45a650332202e6e2c182672bdfc365b4b19f550 260285a632a4ead67966de806b34a32cbdc69352ccc25299509a3415bd6ac2f5 16c8b44afca503068a5117a0fa39b1cb5866672ced428ae720393e8140e4958d 6ec0f1ba70f1bfd60018d9780c58c09ef50ce619155a91fed21516d72fa65549 112cbf0a773da739a875b800bca212c1dfcaa8a7b006bb0b1cdd72e197dd5fb4 909c49c403a2533b78a8dc96119852c226b8a93e302d9a34ae910a8c61ecbc7a e16ca70091bf8859d39a34dc2fbec79f00888832d287e0bd0a3442a6067b7206 b41959aaaccedd4c7b4ad47f694421a9ab5f18365cf45a88d85dc4076e87c649 aa268761491f71d9cc3b911ea0db0efdc35676bcdd5194952d9d0f1dd82d18c1 cb1fd93f7c9844cfd85a4c0f89f5a41793bbc43cee813fe3d5ca10fca6538b04 9aeabddccfe892522302b7bf3e04f4b94773b0bb89b28f6f19e24220495c0caa 81cdf2134d20d8536596154521f3cc259e5b917c9cc4373c6f7adfa0b19e8009 78154a42cc5ebc11375cc35cab1a274f024301edee8fff0c08b5cdb0dae37c22 c29ad72588fc320a019c6c102e50ed32ff4123df1f8417e0e3ae315b8a6a31bb 5e053eb278d157296654a846a072b83224dfd088d8db57abdcfd8de00b2a8bee 5804ac28bb2465a4a879f07c063dfa4cfb2762fb9015da611c9b36fa62b10c5c 314e8a0ff8ce6e952150be70fa590a975e6629b6d6905e3f6233672af926dc0b 46 28ea3d8c5f1bbf699fce60869ef4ba24c3a92952ef89b25de660884ff5145404d6e87dae6a06b41a16cc020fa0840653bc7a40cbb248c58383940856809c9e0c09add695143f7ad570b8c5190355e5ebe8b2a576b98d7968b67ea0e5df6a5803a263ad7b3a2a9d9f0e51bc97de6d7ba61410fe17652da30e76ba09048c90b20369e091ea6c9627e01d0c8eb87be56123cb8c8643ffcbeffc5bd0c10078cb950e13699713db4efca2b055c2ebf3bb08d7b1f2e6911b58668ff34e81b1e44dd2023e494438fa17cc3d7e2573149a648f81fa190ffc06b9c38a4694d49723181104520c5496eed090e0cba75fda6813b95ce5a07803e1cb7666246783ab3702e30a10bffe445304ee6250edfa9c96193f35763b9ab21eebfd78d75a146ef7b27c09e6394e928331aea229cc0957ed93bbb3828370e7276674876bcbe9a40a4a0c0f9678a22ff7a4d289555b0b3a46d0a2923b1d99d06228f0da93c15813de6cdd0a99da82ba4172a6fe8896b605e0eb8f5b156be2af8afe083258ce2a38cc263305b521b2dca996c041fe1e999884f467aaaf2e5678941074c05a7844a88f619507f49e0a88ea12128d9ff573280d65470d385a4a14c3b461257d1e6611fff34f0b5a61d745cd34f6566089203452498690faaf2392bc11c376e0078eb16d09d3003f2b9d4937fa80a9f2b41f09f0ab08d46d84dc51080639f4d8e08195b03de20b0a9db2cb9a8b33ea4bc495f90ce781563298ff78ce77bef39ea96e37d66abc0e2985c5bdfc1782d4b6a351da491ae3303ea79278d07deb9053c3ca5bcb05a00a7fda7e61e1f56bc195926b9fd767a7813b3eb0e96d3e4d8c7b44945ee58a8b0f6c421ddc255d106541ff9505fcc73ce198c5db718426d207e9965c2f665a2e0faefdcca951c06887238fe0f63c67f38d3caab59cf140942336522b7476f7670977d1d2aaf6ad40b177ecbbc3e52d4686401c4125c5fc8afb2e7fd21ebbe746050dbde8816924913ad82e86ee96e655ce994bf9303785712248812282670d0e06e4a93bef51eddb447f7a65791d64616658a5ed0db0322e0f2b24a1e1b8dcce0583e6e0f87b7f93a5c2011b65f9924f59bbcb2060a92e36923c6a9d13b2e665089eb0dc6114a685fe05c1023ae256353f7c1ee96b04a578704dcab7c5e17acb087fe1ae38602bc3ce37d402421589baff5dd56d0a0a66f3df855697f4c888c20cbc3172f2cfc795560c3e5c3823c7ef1ed9e1515ba368ebff408bf6c3371a1406255d67bc70ec69b86e9738c3c26c4967fb1efc493c8cc04bb45558a6ee8d470f4fb720eff24573dcbafb75c533b54a4729912f067a35823a56c790f457f6da08deceea2354bf5a99afa8960afcfd733d9e24dd15d4df748a24bfd11bd7461808c8f9ef61efebef8ba60a37e484ff0ef885381970d0747b10ab3e5f21f6b3f10d658ce849b4ec0008dbc5e1a2a0791a19ca0aeec6896b9e8c152ac4452d72d903ac9894a9a3049daceb988d6ca4a6808f9079b58ede63dfbc262f94531c4d2705397b08ca15958b64f52b19bf1e98ccc2326c688c10831e269303e6b22b47ca0dd0934de1902e302230a452904d545bcca1e181ba797f977ef43d8a1f9a627708e3354eab711c3da5bdeb95d32db8802d93d221e6571feac35d71c331c4aa2902fb90e8749944eba5ea59f39414c20befedaf6c08852c54dbc22e033c98e137087d1a853b3f61a59bbcfe03f5fa54828d13208d84458ad9b0f46180179a7bcc0aaa75f1305409d50bfcbdfdec8fdf1dbf618a5db620a276c55e8b222240373703400f79bdf32a7f392503007743c75f513b645e9e0b1e59427a22690faa284608bfd12a949e1c3f5bb01b8d2ae604e84f2f4c5f75ae996f49bff9778622c9940c33d27fcd39d754a1c961b4dee0375cbfd42d89ce9a57efb356bbce3d5e1b2c0978894b43385366888bece77f0160fc3efe1e9b5a7570a74add6cd94cc2899501a9bc57514ac9dfa1f0f72eed1334476e7559a6c7709a2e9199df8b4e4978060e14f535bae6776868a9b2d207cbc16c1c8fcc0a72963dc4b1dfe1a3e23df8d9025fa3558683789af8d126282de4d6ca9b3f1a61644a10332fb068b34bcd9e210fe0e202e03fcd5efc4b1e77db443f75f7ab7e09cd4f111df691d71a11aa67040e993d6c61413c6a8980f15077322ae80f6a2b715b8ac75017ce5c2afddf9fab0bc535d9e90a43770669be198029c656c412c2a923483e6e6daad77344a2819a059cf8f651c1519ef1fe38b55dbd718f99195a3e36c5d1527061ac851378a3aa0dd6af9658355a1ac6c15a1e45fef3a511de69aabbd6bc083f554dc8786d5a190469d7b057fb58727fa537aeb0b5ca9efe4f5d89f210a8198e6a9081963ccc480b701c8caa3885521503c80512f575cba6494017b740b55deeb3be7c49002c3e0dc25b51b2cb9b2f89bc37baf2d71339d430b0f9f0c5c7bd4f52cf031ca74b7706af7d4dfd2ecf2bf07aa4765266c1e7db0d7cf946425d77d918161affd5f22d02d18fba12a1f8cdc5b7b1a57515c4edbe26d3c11e386f9313458ffa8dfe11210edc973608a9b164a2fcff94fece921e7e52b69b08b16a5d79584129924e47e709399b868d00f6fd334e63c19aed2ba7a7067d958d79cd347389211bced8b12c042281692d047d66754f0b51c4be4c173edeca1f7cadf6f4e2e4c93a5291149503cd0b12a9e5804a9ad7f3614151744a12126bdf6f720dc16c5e60bcdadca7f00ef615b9c50a0a6fb224acc72cc04d3dd91372d6622023cf81a7b0d815122a680ab92390263a254424a9d30d0a58475a5e48b73538394128a66bfd944a7379b70ed5f8a69eb4f9f22f076a845e9113d8c46689235a337fb4cdcf33a2be85c3ec04621a7f2c60072e4d79e2fab3246dd26d7b4d00ec1dee1f149d3365a64cc0510caf4e6449a3c7fe5ef8e485eb5e7abd30c60965d149819ed4d172bf1b53c6ee06c10294716b69ab466964b50a18eccfc4f21a03618f305194dbd168b999a8390937b7a506aa191904fc8b55ecee44bc54fbe4598b0a47f96fbce77bb858ef600b9753cd7f97fe1cfa747a7b4e0a35d7d154f88cbb58d0f6e219cb9849ea43d102035d6ea4cfd79e8c4df0c9b0251f07882dd0bf56d845d4e77d3cb5e06cac41074eca8ca8be72041a753c682776286c0f1a5cb1e462f61c4fe34b8e1b3a5d520f6cf7db15cc7fa7147d9a4aeb9bc9a12d32967d6d731eedd9284dc356cb0f2d01a59c9d3f3fb1738dd939549acb35cdab7ec2687028b46e90384009797eeeb305ac0eaf530329635c0b3127fb9f19d8e7499618276306e2b3a529b2af617d9c0219cbce0fec136ea8f70471fbef448a1bfcc99258c7d11523094fbbc7d4bce90af19e38700a546e80b1a9c2f59c0be7947201f26f50bf8f2dcec61e9b331e1803dc0cfd5e7900b9048680f3929880bb250152e15d269f387de0a8609efed38f0cf80faa4738d2ad80e41dade9f4a10a86e2cb5c53b075c4414a5c646d64e7e40e01cbdfa9e743f7a020ee7138dc8fc3179b9953cb1e6e889632f0006bbe10bb00b7dfa2c47840936f11021dbba0b20909dab77852c7f91149e348c2cbf36a880aeb52d41fa689d20e9e693d9f3300f0e46547c63f06533f41cc84c8243ce7dc099fcb2715177e2bd057fae0f563d17daab53569be0c0835110b41ad804840d20971fa941f4eb15039725d160e085da2ed5f1e392e2464d0a02e1479cc21e3d508ad3fce67fed18525be8fe5bc1be202ecb79e7635484b35fafcbf19fe806e410a5bb070d0dc93d28bcc6c754f0a6ac66d0dee99f64bdb77abd4dfc413873a2c016aafe7abe0dd2c8b3d5314d39258d61cd6a82a3dc810462da092eca95737530780d4597c9b255564eca32c4c1296a6aff4f5a7da83b7fdcc65364845e25c4e06ed6435808edb9344e6d231d354835301f342d32446984f76a73b36c01984c8028c7002f0ed1f1c19b5972e41cac78625cbc18e6d207ee7769d955a4167ceac023dc0b85f4ea3b0d7df0925d5ab7dc79d9f862a68b49bf7c3926454da6751fe0ae558adf2c6e0f685a5f248413b31269d552b887ef939f4305cd1a0b0d72f9302b257215ba01b4ce5c4a138475d95d6ba7e16aa70ff64f680526b4f5289afd00755542316edf852a3514a76fb53232ea96d54a066d9f4ed948f6dbca8732d77021f78763bc87684010a7db33ade6f3ca5474fd6c47ec7577ee20aafaacdfacd0dcd366946e23af146249884017d934c78aad10f4af1c782980a5067bdbfef8702092be91187b89aa2fedcceb1518f9b71210aaa487c810ee62c1f4696348596030f4895cd2d8fbc904d43dc3493a913d2fe17b897db84c180874a8a0fa4962f03d39f2b8dbde2b3c699594d83eaa986933f13ac6c6fa10b3f42b47a516892450a2f6cfedfaad75ad0f24094fec0d41f6aa7c6e5b7458ede51f0961d58a160ed0db6a7935df9d522f23268e4fe8fb500e4aece2a3d240a9cd83239d1f11f368803e2aa58163bd9fdbe880c470f633225cb64d61617cf97b017bcedfcbc6a64170e2100039fefdc23f7af3544d651daad7dc1c3baae68519a014dc737a5fc0fc30e251515605904d9129e97040c503fe92a73b3d9768571aff0c8ec8a322179e603263652ccff21c655d5a205df7dae200975ae9646ff95e1a1d913a6c74842ef0dc7d472f63c0a177e028f1716c9c6d3a22373d5a8eedf83dc185bc23b90426c0635116f61518ad605d53c2ce996244ed2c6a57f522040ed31aef386a1a3b3ef0e6d45be7c1be2082fd7e498825a0a8260f16f4ba6c70c9482a1b061e6cc310c0962f48d9fbda1577b892da605bccc93808771ea1d51192b309714f4f2341e1d0764b406047e1337ec83af00448df774ea0634e5dd556f20af18d69b163db9c60cba79ee212d8c54a3696646f9bf15bea4100b18170aee86bd35da56777c51e10d1ea56c440e99142cacae9bdf8e83478cf4f7d1b340932d2f816e26ea20151f014163e355e1c237a905357f5b66347ed3e27f063f2b0b0b9ed924cb0075c6f5090d1be47f095557390873e0bd46b07d7ae94c9e8667eddb2252a57df76b3f9804b8ec8dfaa02396ed96f177bb0a41a02917428b8d601ec2d6b95e4d27e754150f2cbf42b99ca47ea9c322d10526314d565096248f202554270fa93e842628850506abb962b3101b35c8791cc806f0f075279793d207c528a6c3d6f0d3cfbe4d084e3902aed389cd0c55930341fd213d3ecc937c0a22690a8579e1724e5354e90951c5d8800df8be11c8673c1b8746ef18f33f87d284007ecea582aba0d85be30581e4187e29c2888d457b4ec0854ecdef24401115db8c16f106e07cdf427fcf092d567284f44083a7bcbd6c35eb03ab7fe90e791290d4d5c055d466aeeb2dac0d9c0e917857d695d444e202988e0e198f15f8e15ffeb7eecaac3f950405249503752d9d1b1f86077d9827edb660dde77d0d893eb025e2dffea829a510d12eb409cc44ac404f310b36af86a7f7611815231491b64bc8d2f2c3aaebf9cd736ab50147b0a8d2ff62bb9ae013b5995695d19b80397b6b4fb23446a2b34f9da2a495013a7203f86af6ee795e68ffc16ac60bbfa684ba1a5f73eb67be117788a41b0d00d9c12ee62845d4f3cf4992ea253e0ec0749cdb421646aa7f0b532d97d8bfd5023ad501a901d6acb77fa267b675b323c1e0e0086d9b38b909ef402ca7f94f5e0286f6cde162bbb220496f01711d1f5692b8d5f50cbcd8035706f812eacf3ea50aeb739c413817378ea22fef8d031ec12157b88e973d13412c08b95c3711df570f77b99391ada37d4596bbadb80396d2e715782c014ea7cce672b6bcab8482a005d3726cc8cb2139d498a5ab05f44d6d61cb4e84570dc73c6c55658a34d77c63091feb693618eae5467d91da37e5fe68c044336c31ee89e5224e0a7a8477fa31068a6526189705ac7ae14bf99caa56262b564568e3e396715ad90e36ac1777b1037ff41ee261e4a1ed11c0b3819587523dcfd36611ae9872ad51b8506212172d049ee4a1f0a13035968eb60e4bfe87c46e1d7083a2b564962e11bf8cd790349a0e0c370320723de812873dc4ad195491310d1a877d6855414b994f7fdb6f56de0fa27677ce0980485cc189c477915b5b8c1bfebb850bba88434031bfdb29cbd10568bb1c70f25b127cf2dad52068976d99bdb46e2b349578b7e533a7d2a2fd53028ef41438439928dfcc1da355ab9c21b908c45b3e1678cdb403da9e5797d1bd090c5ca2e5a5b5a332951eb2feab1039cef63876fa208f9bc49badb1792f79c8064eb3b02ba1c662a5563e44d63c954f44d0e1f1eb86842a6fdd9b8015b67387021af5ca34f2170c85fd3ce4f26b2bd79721c13ff069ff53e6c6694c6973f22d023661f063749e120ce23800e47eebac0054d8b262248f17bb9f3437792d725d091f4f319a2f631788bf75d16f33889c502c5c51a469868ab591cae2c73834000d9f2ccc60973c99a4aaedffc0df9025eedc50e8fd3000bc51051f4b04e4eb5b0eb6560f9ac97fec4a83e36e98bd49da09afc2a464972df66320ffa5138d237c0434029e6b51d2fcae707ebff362d7ade57290c2dd591acdea5e71c1a05475b70ea7bcfad566e8b55af8687aa76b5da905b0970048b92aee41b5981ded4dc8d50070182b30c13e3b4a18b99e0ea92452a16bae195de5f91859298292dbad2144070a800456a64222251b4e5efd4e9be2f715bdecb37b64d9c194bcabac6b01a70ed88fac5880bd593f2ad2f0de9132687ccdb7aaf6b69cae0ce88ae817cf542400dee0dba2c2dc53651eb79c894951893c3e76a05764020383b906fabc799691069f94103d9074f2f7a1ae8b369bbf532d6eef8361bcee1f482b01452ec064e40c05f39e295a074eda84b5eb646e84f09765ddf8a4770e091bda48dcfd26a85a0ab075ae6bf2231fce46d25a87e520d379da873b3bfc23620f611140b8022fc30ce73ef3378e3dfc5aef08510c39637442f9dd24c7044d44a00ff4120cd0266e0e31cc7a09e5b2a4d5087f0287e7f53a0cf2b590fe8a96e31d7941dc41d105f20b92214b21a916c6dd7889d634d5c0f8fee2d3a307dc82eeea1c1f6606472a2e08d8d0092d118676582d44639a7dec783126eeb889bb74fc4218642808cb016a05769d0117ff78e8ceced59e8a65570f26d589efce998c4256491b86b77b2391037bcc66d903766c6e894615180370b419af30f5798921faf9707662a995b6b801e4e1e044fa5eb81ee59d70619ec428bf36ae5416b678e61f62016b9fc0c04e0417325862c9eb59b3bcc338cf9a8d639b77977e3a75b81d31f6c7ec8f47b9320d97b01f87571705eb3f3e544af04e300f2cd02e60efcece137e0aed7d19d2e00604eb7419d6d7a59cd6449c3b8cdde052cda100382e5e9014ce71763b74bf8106a0f659a8b0f03c18c2a2a51b516e8ce7fa028c30c0980c02cf2e6f0a4abba208f4d99858bda95cd632236fef30a7a94223771a91f7c79b842cb4c6917db14f0b4dc01258f1eee375c1de7f203e87d148ba893dbaf2415e7bd7412345a02c630f04778e72b1c93f5a3ab2a0355bada13ce60bf92bac252bd9f7e2208aaf3d8e092c77d4a1e7a9ce39b0434cefbf36a7efb6ab9d79fdc8abb0e43810cb75f7930c20d5ca6b6b5f83921a33d91d4836c1802a2b5973df88285aa21074158d24c500bcae16a86ef6c7aca08e6685d8a06c5db9bb30e893796a366428c81151b01a0e018d0f6ec7686819abc26ee15d646fa441981db9b0a0b97151a629590dca5000a612a24a2617927bb95c0b579eb0e383355d6b913625f90116bf1e216649040d59ee6c9f806151878117aea663053041f60618830ed344845a9abea0e57cd90c4737572fa1773f2e71746beaa3787a9efc487756f2fa3d336fdd3506af1c0a02c0bc8eba12f315926a0bb9f81927f23544c1529e58800b954f4d02426917a10af2bbf3e675c41baeb8ee6016a6885c6cc869446669a5eb0e9a0b252ada0562035379ececaa47f0f81e61fd74bd1fb378e12091fe1c8bf5c13d2d100d9a59620c35e7478f178ac8eb770488a2db4152188e05dacf8c544e4cd48d7b24b2275008986e38451610aa74f9f9e5aa366392a1789d7366de07204abb5aa274ebb8b1001e1ab30b156b3be2c74e77e47e3a1d8fd48da9ea4b4fb2acc2db2bc10e519602c850b2ef5ae991febfa7a60f83805c4aaa91f5fbac4071b3f9d62bb43847810051a04e88f96e8e259d775895d0ce6c4b0491c9856bcb1dd95cf599a895694b09f348f64c643bed85c714550aa6b134956b22f785f990dbd227e4be2d32646e0a994326eee8b82509d9bcd6db7320aa61f62cb4f2d98a48c9085c6deb96f6d508cb91ae1ca2586879def704ec86066b2cf446bc4490332a4746028788a10eff084d44ffcf25af752d22d010d3c293bf5e7961bd8fcd1872484c2bd4206793230643c13fc7aec0cb2f2b544188c505b4b35f7a111c3efc977b26e7f79284fe20093b41591fb2cd741acca1a73372b22291f1549308d02b652a4501d9043545320661d35e132677ff12b0248703307a545cb8e6475e324635609c824d1cf74bc50e33f1e855370b4cf7be8f92e9f5efd7f235670098e351b31f4bf66a6237dd3601d3cf305d2067d6056812c7d71c7809febfe24e9ef206ec37533f77dae26eb00b92b41f1bd57e194fcf21a85c6adf084ff0300e7387230975cc932aa5ed1e9f03c3bc7f5d643b93b7f4aefa2c768e4b1f9e8c45eecae224cf79efef73f533420a07305fed8c760bd5bbbd929301d43aec516f0f47483312469b24772027c11a0e021efb35fca3c8338c8bd1834df5cd9163dc6356e1a0fbd6e209140284657901a842edd438d192266db750f52de081c8afe3d2eb15ed02863fe2fef41fa035002c92322e3dc56d3be24fa75d7a43ec4cec48d75ca3a5e822ea9625a42feaf900996d37d4d41f488c263651414c5584168adcab739b52b7688a2c351088105903556e60b3fd66e879755df3f1dad0ddddc46a9da8699240db2819b5ed5aed1908e848c84cf5276d8b5df2e564ab36d5f1a9e80f847ffe9dceaa852577b53d110ab5cefa3e9ee90e72ab73775b1b7428269d171b3ad8ba6a1696a77c895b8fc90049dd1b5dd899c125486a8545d957d1b20f97e3be534f066c4661bd4da4a1bb0dc1d7a31b2a2733402919105bcd1f2310b7c1ed4bc9f2ea3ca5b05da71da82e0d749b2bf513ae3c6983691001ac60ba7a99b42cc7d5d4665a15456cde340a600c3951559e615638adbad7f9eefd6e5b97462a8f805016bd6cc28b1942b569630a5c71325e319533c92b343eaa009823f8503b2d73cb24038fee9462c55c7d920ea11b0c1fe35e0d8cf0d1c54494a50511470c991a295b8f1409fd7bc43c3c050df37179f8d27a8e8056be89f5dc6d575769a2665a11e1e5bd93f0bacdef9ed70b96c97f833342aa5c9e6464d2a559be3f480093d690004dcb2de4060999c79a086e30663e4bcae4a68ce731f408e890af7ff4a9e7f0abded0d9f1541ce7e7f80920c03e125cfc30b2558fa7ba6f6248f7c3746eb33329c772fa7ae63ef791350cfa930941e51ee7171d234b39242dab32b7a95f28eff35b652234fbd0629080091cb3816dda3d746ce0046410fce064614ca6066273bb234772e639e7f6ff4d0f34130af8da8958233076001e84c540683d1845b82e99a98cea14136e611ee609f62b7247d849f89f9d8f99dac928a5a8744f843fe07fa4bd5e263615dff5a90e0ecfdd8feeb33180e0f72e5a687228b82e0fbab979226a0f01b53672db4a740daf6e233407840063542bbbb6fbe176fbd48da75c12a86f0f87c7915857ab6b04ce70351953dd52cddd9325b9a045f9ee0a4f8dcae5e902cc25165838df9dfe0bd79400496b81bba078a2ed8e2e4eaf612831e75b7003a0638d25ec52fefe0a0400660bbb895ffa8cfeef54bd26607e006a6539769eb7fedbecc3a44ba23aab0671b26e7f8a12e08fe0cee83fdc6f629810be178764cb1a6971fd297b9e9a5e01f91133d0c5686ec65379052c1bf04d61b997a217ceded857fe4756ca27c9c204 -generate_ring_signature 2f70a3f91cd8002c712cc239ee2488b0046d4b010eab9d35554f4e1bd9d61b0b ad0464c09da58d6bdb00c070a4e094c0883cfb6eec67fb6532093193b4b1f6dc 55 e19f645f9ee2bd327eb51f336a58e2c9db7b1a64a97d6803d6b56ed4fa9cd560 2c9c1ca72314e021d1cebff7509cd33dec503d78b8249bf712cdfd55895a3726 7bc59484c4005b65ef76ca020046038e3a524db3c456d48bd6e6dd45f38a252e b849fae09d21667f19fab5fd6c7d0544b59bfbed39a524a942d48828106cb12e e16fbdc60de52e405d04eeb52b3b00c0bd1fbed1d5af08f4f35be6428bf4fd8d 9ab4b2beb1c9a8ae1c4c33c53fe19581488a836bb933b45bce4884604a5ffc96 0fc8e4a7ac769f9a692ec80395494b43e581f82aa65b4247ffd7a67291fa3b58 af9c421abc18053d52ef23a6846ddefcd717a96fd90f2b04ec33eab670dbd39a fe83d20f114e98d35389b23ec392dce2f3a110c45710f0c61905bc5c77bd6389 ca5eca751a73bb5c81f1f85ee75c0b6933f364579189a9e010b470495d1d4166 678ddee968928b2be7d171f934fe13a681556c03c4471d2b3a0c106aeb16e0af 58a41d7ce0ed959b012e587542acf3031f7a878d0668573f296e95e79c0c56e3 1f98f698a97f4bf968d8c4a073d62bc50ab6768dc8f0253a6ee7d0a9b8e400e9 203f2fdce050523df6932b625fcd99c5d592853d69594c6ced0d8d1a27e2df4e e682c2bb504201724f9d6831aeda7347efc2aafc78397f237ee36a2d609adafc ded39b9bc8849e513f81e5c22bb93f4d7009522eb63f580e9e5ef369a009f63a 9b4566467f59a6f545fd438293c87f895979da6151e0f713f0535a6a78edf605 b16fd389f7553736eab1855cb33822999b4c4a28ad1aff92776724fb2935e91c 1ce0853c4f87e754e05213c1804225ee1a2120494b20fe23bcf133b33166504f 0ba8b536b491f31696ab1d4dedba8164f7a1774d648b6aaf571e7a1dc00962d5 df770c4d34b57b2cf0dfd5e59b8778e4f6821796acf3e5a8a1ef2b6c6caea12b 000cd6a7b4564634f50f4cb3bb34040bbbea725ba56a0226603e12f16c75c838 68d4b4453419af5172aa54d1ff68004e0e8bc785605c87dbff1522a69fcf5eb6 6ea42b2fdfabfdac3d4e4dd520fd923c25ce1d66c5c536f21ac14af60a3a69b0 e6c455a08d17e0f82fdb4b1d2952d1f03bb66fd20b40d80f693e6f1621261b8d aa4da257da007f817e0ef63694a46500b56c649b6430cd8ad2cd98cdc92fd5b9 ae71c3343d5a2b6124deb034ac1c381121b80e9cdd3c1a3f8ca645be245c802f 55c97d73d6cc3e432460456234d554ebc88f4153ed753ae69a42ed8827906384 7d2d00d52c811603b99a492a7a2459d1c88cb5113a22ebec3ca09ffc126c8757 b487a8889eb4a2e809205aba036adb11473ec68efe7bacb6df6fb0ab34b5f563 636fd45289cc28718d29ec8dc3a53ab20f2dbdb81aa8a7e73ab256f16b075484 d4c8554683898da5f9da8a64c30fb3e343cfb19eb88f7fbf567901a9a98d2d71 160b282251304e7cccc5682a64e5f4a4c7356e199b023ff9818c25defd1e47f6 1a5b8c9c7a12ac3f2470048f0642602e07796a4bc7bc095aa88a30976fd3b873 d39fa1a932a00e90d0c2339bf81666c08f299234846b54124942a9db33365b48 d023e5c5466fbb9f9f4210e53965f90b51efaf8181b4eb11f28081781f618fac 441afbbf59c3ce187d0ea4b7f0b8c886509b32f762f84b64d64cb1ae7e4661b4 7d9521c9c0476cb8deb152527709412eab60f79e6dcae7d6a8bc764b521552fb 7753e5dd3407847543c066c3be5b57568a00ce2156029dced77a7d7f84b51c49 643c25c296ff6b10e044502b84bbbb8066dd60c13642ed568cd3a127269cc683 af193ec7757ba760a786e1bd6dea91abf67e0d09fe1dde9636ee740cb64b3881 97c86f4eb82cf9b008f34d77be77474a9dccbc7a28f8af3135804c4be4d7f4c1 42a123aee5df04b5d770c8d135ce837ca7b61f889afbfe459affc364683bbaf4 82443654c82e18c320f5c5a91eddaf6a009a9ab264e19fd377094165553a5798 1c281ae660b2a48d4ce02e48fc43d19d9506fe50ce98be6138ce2a12f104171b e697e05d9ca04429039d3b472766d362bdd5bc09edc5749244a4e1631d24fb19 c64794f14532943a569709acc96c45ad352cdfe950a925f2d6d5d15461e24dd7 215eaa77ce36cb9da74e8b4cbe60fa4effe632bc03b8ac2972219d7197b1755d e45863fc78b8e87aa3e1527121dc382a16697e8febcebf7371975d02a8c019d6 64c05b4302440eebf39e77dfee67a5c556c28240d204684197c36c61add87089 c56a0a14c23839ebb8fdcbbd53da469670546a8a4d9b988e4283fecba308ad63 ecce137e698c68abfc86d1e30b88654aca22c4a81c5badfbe97db39fd069f4cf 0261b71c4342e73833ef38913e92cf7acd43191b63872739d4c419daaf35d193 978a3653c3a18d1f58e3a222176e34d37ffbc816b80d11625e0ea049554b1778 bd8028231d3f30ef112db35443850f73b573f8a9dc3345ca5744bb7b97ff4009 8eedeeb643d1d8dbc79f2f62d47dad575e1965b8cf1c25dede6f010cb2e50300 24 eaae9417376a2727ae456952b6c77c5f38b9c92e4fd3efb869a6cdc502010b0396267d2697d38dc2c0d3f9885fb0d4379aeeac7984dcb723528c058fe7fccf0acdd9ffdd8405dd4d9dc00ffa6ec3672a19d8f6ad2d0458eca37b2e6c7c6f89083e9aa5422f51edd7809b07cfe04e6efacc67fe42fc77787bcf1b2d59ba0d7c06859a2e4232a0171db5d55785d4b9a48fe62455761947763acdb568b2b099f007aa22f02dff0da9dd7b90862fe231b57a967ed78c686ec94e2797767b1d36db01222ebd062911c5dba991ee6faf24229925290dce2d25b3eb8b878009b5332a066ba4354a86a64ca714063bb14589b6b12c891c3532375334fe553feb4b32b6056340bb3305d8b1fbd423656b6bf75af44f3d386a3f141166bb65c566c8bf80007ee029310b82e1f2efd028caaed863b6b4c649992c5462e82ade7ce699191f06f152c4014d8f79d15e18e0f6bebb9701c14d261f3b799329066b5253cd64370af0cb6924072f3fb7dc1cd392eb78e71e33c7772ef6393563d12e73509c9c040617306dc1a88f66e3e7f988647a810efa4e4a264781504020fb8b7c4072ce8b0b89c17f947b2b17c92f71e9476244be865262ee2407fa3339ba5975ea97f98d0c883e2e7e9539a06cf25880341e885e84d572c14acfa266319b0d37ca83c5e00a1ae825930d8c9f0f6f52e475222e0190541602df549615130b9cef3867117b02a6a2195c5b439764938e418a0e08ff17ba4aecf71a15a48a3d34028c897b000fdf8d73d8977464ddda4eb7eb4768d8ac75193e56d05b6b66d16537985bfe3402cc900fccaa26b56a1edb0193f1db92dd70daff618243bd88ee1b859fc7a8fa018bfedc642ac92a75f45897d164442d937801482f835012377acdb6013e6c9607036d14fab4bd810ec7c52f3076e2c3312eae3a6c9d9455bbb5e03272f7abc805fe0c7930ff94027f0045cf34444969e84289270c63000977de2d1eccbc4c660bbea06d523eeb97cae1bcc36ad1258c23dfa3f98a15593db287f89905e587aa040d16849607f0c55658d96f82b6216a62911594347fe259b81b1707cc963bbc06a8c0a3a2667e0b011d448f931fb5351aad6dd3579578328aadb9b6e711531208de59fed8be1677896b15a46e9685fe60529f7c19c1209175c87cacf4d5ba1a0dc47ee237063d4a8275d60ca98e9e2e873094df5be087464536ceadc366e9f80a3257ef387248eb702b85ab4cff32c55c25bf52ec106c744e6f482d5431e9b709468be2303ab951539c1007988523cf47f32263347de210296975c7183848a202aa110f4d57801a1cee8b8f80809ef5a4c620e1f66b148b8445301409157ad203809df456ed951adf7e693d046b372b3a106f5d162348e290f650762d793b850109951f7d11cf72284e937ea6bb27510bac5eb19a722956917553e369e3ba21037c52cc32506c4e4e54d2f68ce4a36639cb5b8161eda46329e0f6ff9337b8a20b4c82529001e10e9faf5520aa8a489b93f5b6b70d96e63df35c85acfa5ab48d07e161ae389dc35429a9cde17e258e7d83acf149190505d13db631216ab9e67b095e818687fe94cd4df7c6e0b0ff177d71aa27f8874f320ab0d599f635ddc0c70227fb81b00f38f23633ca1a5c43d672ae793be916ddb2a671cce2a57fbde01b0921611c08e2f0559e197b3a6a98fb2172b81e3f50b2dd9119c13a3ecd0df960010857730c8997a3839de95ce0e0681c4f0458ebb22ad2b9ee6bbbd2f6849ef206a716bffd9de5e6fb898393c3806a80c000b20069bd363d940fd3538a58bda70db5aa711c0f919b7118ea3346c2a796f41425d126a8189dad387d72bd7612150c350c51ae9446846bd499a6a1f53db916f633c273275cfb7260732a949a4e5a0141e7ebd4ed46c0db37a87a66c8ebe624ecaea0f2c3c954ef090322504544840e52857fee8bee484f3f633dfaf1aa06b2bd654f42899d551c317534b8c13597021e736bbb6329e9fb48aeea0ae1c8fb5a1e7f79f2b1e68d80412ff757c848b80483b19b8e3d350b37a140e8ac974fc6414223993d77ee9868456e09db2f9b880833519221072db682a5c6ee98b6efc523abaaf3290654a399674729d6cb2ad80fed946c2ef29c0cff0e30198fab09d6683487d1cdb7c0a26ed6685eb96ba8d500a3bf3a9a0710e9b41d8a3c7a69c0dcb51d7ff935d0a53da7799b2bff122dc109f9298f1038fb77648e15422b230d848edb699b66c3dc11135f02b64752d1250593ac5dc0c5c36aecf65b197de594b686e33cf9d3882b5586e31ff54dacd9ad00e3d57d7e9a7671f761fe15bef823b48b3de7d07e4e51a0b2a5d30bdd2fac5c01315fec3dc7ce5a002168920c597bb91a4da2024b507a05d29a75fd82def5470531c558cd909cd07ed0cbec68bd3a41d745b663f35b962bf92d1912218482da01dae9d9e7d38b5d5a6d76a8b2bbb242466d91a9b3593f4683b83f2671ab2f1302957e815c7ed1562e22fcfb19b7f59853691ee93b9fcdffa9ae42780a01f3430c0f58ba37d5ad4286c5c755048350d01d3f5f8f02ec83205d1effadad700d6b0eb93ca6c851e711f1201c4a5c60f166cd81133093409a6072437c0a9a778e910cf7c392bf13dc9475b203d02225d98220435904a145f7645532a24663efaddf05dc2bd08ca29b6cbd79308f9e79fa50938b16b91db53ccec2acca982c7960200af4b2740914d9f8cb018a451e4abe62d7834e450a8b99d16c8017a5127d2b4708bb062672f28ed0a90250c4cd754e04ef17e7956bebc857600835621a854ad506165904f04af967c5cdd86b276d908eb510c29e4b35726e40ba2660994debf70385c1995a4fe36601451926d0a76c7beabbeac83fb9e56bff487dd07840774e0e7ad674b8a7fc89cf6d26f14546f7373fae88cdd4e6faf8015f9ac31996fe2908a3dc9dcd66a34a025fdf4eee018de32f3bc674eda88923da8afd6744d7e0230674d3e99b93d4affb1c9a9bfdcae352556e44b0a4b478a2c8c2a809b27c9202056a40cddfacffd4c4d31804aa715771c022ceb6b1b55ecaa78a8d84d6c0600805e2eb0a8177d9080ad7be1cfe3b1f6cfee69ade4341eebdf3dbeb5976295deb07ccd24ab4c7a4809ef48cfeb8c39db8f931a9fdda4ae52e9ae6b4e91a075a19090b84d65381051e02d0dca60ecc80a315698608207a8963fcdb341af8242ece0e3b75341340e2feed3f74de77d21f0b2befa50f8f7e3d5059ce39b5aac6958d06c4cce49425dd6b3a9df40e9c1fabc82529d5733306332ed0d111670fed29ea07ad6251d7f6e3d5937c865fd319e230f236b29c8882c8d68b310e45d79ca5e209bdce9813668c97d0689b58433a73ba8f3bb563025350cdd2c64c0632d5d86a0fef746c43766309dccd9ccf9e5cd5a793055dca574597bda93935f62b96d1630a7bdf953d3594587085e7a77acbc10e83c10b40b78928c98cda3c172b455a01085d198bb2560d587910055135a549b0b73b488d30389b055238fed433b6f3e303135d34e9796498ed2891a9ef78d9dffe0c68ee911eacf947d2e1c216d2e0740739543419d67c80e479b1904d751438578b73d9a50b63b8563553eee59f45570c95e10187bbdea4f19814e1859119077e23147ae8cdcc0e2ebad55222b3c1d7054214a3e7a34f6e161521cffa00e93d09a1e339f9b2f22844ee1124f5334bc5003360185c32550c06eb51ad2a01db6fcb59bb9b39cf4f46f52e146dfd6b6655038f241b7397d5240f9c2942c95e6499cfeff0a5eb3e602a9d56b305689d7cdd03a8bc9e601a41f080c7e1010e2c7301ceb2c8bcf2bc5eb0daf9726bc815aecb068009ffbd354ce575f0372b1dde38c125559f61bc7dc8903b991fd67165d75c0fa2c7443145836fe814858b5fdb77b7f096bd461e2a1687045ad1fc9036baa10631afd54699063ef52f9de8c2dc11e15223e0f01af2258cb6b404f665e04ec60b1d6e2acbd2193d702d63358604e6ad9d9c9f1bcd0a3601232cb970258e56490a810aa07de8c58f212fd098db0818d13ca4bfed5d0b44a78a34c5dc625d045a0137789e1cc12c5d2ff583f3e2c7f5b845ea29231a23fcc79e8b80450c6c86840257606a73f3cefd3027d88c23ccbf6a2303d490ef5ed6e1af0a849f74364256099e7774784153f26129a683fe15a87970a9698faf4bac120754fee7218248d30d6e7c39562d4fb59bf693dd22d89c248d18b90938358f4eb49a2e3633422add0385f735d14008fba4fa218c2a834ae780f360030b0a1ff5952ecb8207b304de07a896c255f098da3fc9701e89dca066ea3c72692a8fd0e8027b34bb0b191ebe0da61a9c1f4fa43a993a4d37b6d33fc80b5e841f9aa39ab459c4fba269c9cb0601b55df58b2a5b3b22844ecef8d8d1ca84d73c325955264197f2b142983f503c0b16f97c1bc644280cf6c86263f0ad2589ce731e5265c22bb29b7930d84bec8306e213ea4ccb67ddfb51311796f5db70fb7b8eef92de905828c349075e91eb3b0a84b2b8f91d23913ef090620b0d9e5bf504d9cffbee67c48189f6d38e92e82c05ae13a4e54d0ed852411ae332dcadb4ee45409187e19fd812eaa4b614edefcc03cbe27612876f3a106173f1c4d948da216876826b4096be5ae2b8320bc915ee0fa80240fc1843348ff92025f48d6259fcaf2984b2c46c9b631cafd366de874a0370fd5e519256dff86302bece079e9b1e9bc1f3f063d47b41b24bbfad6a44790007e7afbcd892175bbf1a106895490070ba5dd74a4ba6e97bd9c5f1dc5e6d9d03344384259cf3984160cbb7ee78765bba146647e994fe29569c8ee9e551bd3302f4a7945d157b128ad73c8658d060b750c404f89a868e4a7113b4e8026fe9f7006918ca80ff6544497771ceaab420caab0ec60d9cb59a44fec7a75914a88fd7028180a20fb2d9c91e20abf0bc4b1d9b1c1caafdf9aaf0580631d64ede07422507 -generate_ring_signature 0ba30de6e6d2dbc9fd491a2874728fd0280ced45df74f8c8d32cf2e77768e7ae 0b3de9afe1359f3f83c005c7631c44a73ffba60a836ae3839d8d5927c4471ed0 152 3a358906b6ff770b1f077ae12d8f7f3cde8cc6d3c19a8c9f5bb6ee11b7388e7e 472a126f08b58e6cbcd37f5ac22cfc6c662546bac3da95da2ba09452f2437a91 fb4235440693b05fc30539541b237b7f9b5c7ad68df2955361c3de5dfad8e9b3 591196da4d50c814756f5ba064cbd38d1af3671a407d8a05cd8d0e056a4e012f ae702c49cb7fb2dc5df1a5e1c39f2b2ce402f2945ddf59241dc047b4ef81cefc a585b5a0091db1a7ab1bedf09903aab8d0b0a844d74e67de526bc99cfc23534e e092843c820545862a9e6bb15ded38458d654c953971ecb97fd1bf7603c1dc6e 322a688cc9f928b3499215ac5bcf36b55b781ea58280315c156841adff146995 ed842c7281842528fa2b17d4d910377ba970d1443a686d3742a18816b10b4ad9 daef8362af755e7e0d52afabe3a44575242405bc654d2c5c59517b98090bf334 1c3845699b373abc21d24b1107ce31e3d3eef3e7ea96c491f7c6652ce57465fb 14261e794ec119d49af09f570dabf6729560be83464419a93d02f0da7ddbbad4 33b42eae69927195bc2de2fb5206054ecf6511312a2528d4929a4a9867002813 c796fcbba62668d7a0d2348a1d9b5f06ab4fe9b157b0d846443b41edb9a1b6fa c95fc5d08879a12aa68952ae167d17993a7e2623297f75fd2272c82e32bfc37a 6cb2f098c37f9b3c863566c29d56939ebdbad47aa24cceb566cb410223a846b5 b77692430504c280106fdb7f639c495d8ef0d7d558dcbd75b23c03f51f8a3e11 4159b10f826b40b00b32991efab391e8f6c0222bcd8ebc0ca35f01c56023e0bf 3fd351cd999eea1dae072737a2352de6e0d35cc5c03b7b66784aae6b5e8a1466 9a184ac51ae37b7fd07b91e062c085b6cfbe8d9fdb539da59cae447ae7a7b78e f3542561f7f3543004b64d6f2d45dddca1fcc7ce148f8fcc240e5dd1edd2c294 f84af966409541a111985fa9c0ce4d203fb6d449f337eac3527765a7026ebe87 c85ae572e78401bbc3594bc748bca1f6996461cbaf8c28064aa3ec6814bb41c2 4aa24501b140eee2efa6fb6980eb6bb4b703eff58c9069b54f1b30dee82f46a2 c61f9c3d781903381bbc07c6ccd2631e6592130c7ef184d2936fbb156ec1560d 146811dcf8fc8172c1504d032ddec6798525e1d8a9429517ad73641cf2ee7499 556394b1a728ad1d4cd280e5e56837702e029da3d8718f50e5bbaf6f0b05ae17 0d694f1df6ef6156bc6f8c5cc2a3668801e9a9f29f8436d22d25feb331afe929 7ba9d54920fa1923eb772fc59f73ec3578fa08866b226d11e983cc8d2f8ca631 9e4f1d09796df5a2f21b9732dd9a217ff85b1acfa8ad071c0f8cacd16c875025 77c0433220a41feb333fe7a4c76ebee4dc10a08644bf530426b99b21dd0ce3c1 1a34d9fe7d8b4503fae56512bfb90821147cbd0d276ced49d456da3aa59f50a7 70f6147b9a07429cda27dbac9f7b69ff87293a49a6bb32e48e5bd7c6cece8bc2 52a798ffabffe412acd4e9afe2e21ca0f5c3b7b83481d18e98c03f916fad4f3a 6fafe4e0b6a1bc4e19439958d5b5eb6300e5685637a976595748955ac294450b c9081e39f92a9d9c0b0d120d3bd1bb757133873ee5e02dd6e428083df7c89cac dfe7f7dd98096fc79fab45669c8173226c19f953bd7d7eb2bb2739d79dfa2e23 3c3856df0f874c2d766f14ec708a366d23128ad13df93d73db9156b7d9f074e6 866dc59ada75d08e8c8ef670218581db6a3fcff78d62d8f058c4d7f767ce6e21 53ec7e68ff4f0c96dedaee098825b83a4bf56c3f6e590f787e4fb02a0491a035 66d5a0aa788d312053b71aa88fdb961ef22eb238afa1eb8a50f739d821a27e1f f5cfeeb51f1238168ad45c7daa7caf2632caeccfe64a2d97e6f93bea5fe902ea 575fcfea8d4bc586a780acaaf079f4a75d4bcaae1ff008cd5e961fe7f7a7bbfc feccc7e6f4619532c2b5cfb43a0e7240b35e7824b94086a93c2f8ff76bd01392 7fefcab77bd3284fa4867c63503d1ff728ebdac0574632be0dd8afbe601f3b81 6bc526e9c885d131970279cfc139e14d213ca40384f021541e669b8b64cf6c5c 864abdb33355465fd8d918c99bb840169d53e1532c8d82aaff27ccd1197f8ba2 2d37d9199ec4b6660639f4419cf184293ecddf90f8d40420e61bea0971ea583e 45890e5e880c0607c04b9e703270355c33cf305485b9c15b9927ff2728bfa5f3 e5778f46b5adb329727cc6f39685138b0ed0932b3542873dd4448909f7d3acdb 7fbc3ad923ce86f8ff5c34ea3b657fff3eeaafe9be2e00ad74e02ab4a579e558 a247dd3e76847f4c67f98e8c62ea0552c69410b57f59bdfcb820dec44fe377cc 31f23aeac4ecdd85e4833c8adf88b7c481a6f687b45920ae746796c878ef16df 7a812f1702f24563d4af961789b40be3d5b7836277f5c96096385d5d373c02a8 6ed55998c547fde1f832dbd3c496c4b1de1d17cb2e2cace2cf188d38ecab1df4 f24160e9814de8c26b075a6f11f085788ee84abdca189158a0420aacdd9b6eee 8255924674ecbcd958d0ecbd07c8962bef86f2d2a5aef852ec8f1fb7f9d69c35 129592cd3a9d7e1463862b37909bfe1d74927582b6c45a6afd259ab07ebccbbc 5d44bbe0a39fb5f35dab4e900a447a42ec4153eb53f69eaa47bdb9bac8137d8c 18eceddf52dd350616f472d7d1b8fed16d25297913d7f2f8ed04883b999ea48f 3af3a5785978cc66e200dba17afaa3b40ce4a5783fa9333a6424c4ba06fb7618 901492fdad5dfded52b21c9959a178334f8e7168b6609bfb077e2a7b93ede507 f7d79b9ec77df91be73f405bd30216aaacd3a055c63efc4f86f0b109798655f5 dbd4023695ec11a04d54740936f407fb2c2b6cbe979e6ef5bf0767a801d0a178 93ab27f15725d4630ba876f4a58ba78e4e560a410aad53a8a735911b7196c6b6 545578c450ac54f055d46e661d12d4d0adbe0849a61e2ea03d6e3d4638da7cd9 3391411ea286cfb663d15115d113f7b2f0826a840395939e8d5b611433f2d113 57ef1e875e3855b4ab4670fed3d630e6cda0e1b9341891e59b7e2f9914c947db 658ef5e1bcf430e63a0b9122ee3a84ecc9f47388f7b31c6fcf366eb8fa9d93bb 2658013beab0b98888d1eb2f795f64f16c8855dfc503d3a66239a0047c5593f5 69277ea51de11f6fba8a43c41fd968d901c4e31e822f4b5b3553318f847b1995 77257767504d0df2a8e5500dede46246b257f7a9f304d5e034268bb02c23e209 06dffc165810f727b325edf311d3839cda6b71ef24fefbc3f455121092d7a938 a50590f3d9193887a33303080421388a59ad10c546a1311e16c8a7313dacebe9 4a0796e932306dda67589cb37f697c2810df1c1747e2b2fcfa293b4f4c40c4b9 c5adb0180758e9a960558496d341d36e639d8355e36e076ad31859371c8b1014 9ee7528e99713c1bd54457781063dea844349199756561b4be6c384b779ed8ef ec8f58b2e690c33d2d30384142e787c7b380d422bc7845a99b9d36ea5e1a3c55 151a797a15a5814ba694cf2bb077185e5b1977d9d18eac0ad772e1282ba5ce80 c08da9572b6395a5cc018f6cbd1da4883d6a2f7d3d76502fdfd72b655e1bb5f7 30ab619fe844790c294a0434cf663d887898c694b1bd374b2558216eda20e683 196b383d573af3795f23d86ed51dd55d9c3ae875464825141be817a0be662345 153ef73d1f5b17c75c970bc76c29e4f2ff6bb212d76e0ae7ac38445c7c76ce97 4c8e7f367d39ea4210f0154dfb333766531983d43313240753483e00d1b72116 dd237005fb83081cc37a3d4a781426d7c72fbf170ef7973256d3b9cf212f2f8e 8baa3f9913024928a3c62e82d8d89ef7438fe7110b9dea1dc138c7618837403f ee427f72f1736d9a3b416b363db0e19250a04cdeab9969f6209bfa556cf79e5f c7662161c5e8c2390fb938a10669beb2713a9eb58fdf61d4476bfef7284db7c9 f9bac6ab6e3346e88b5e48eca67640c104dbf8520f08e240416c3ef27a29a332 cbc2ee1e4553e90b60ff83126c636bb047e95d7d17e941aba994bc5e122280ec 601b1aee63a11d7e9f930d9a64f672280b17787131d12e46ab0140ff01a3372e 90fa3f00483356004def6de99c8dddf30d340b96a065d0e14e7e2ab5929771a0 5f762e1c5d76870eb65f31f7751070f2664a90dfa7ae1df568f64f8478368bb4 8c03cfc38212d86cd7002a0947128016a0131983552f6826d20a84bbb052aea6 b188375c340056fb061f1ae3bb28ad17beefca3e7b5473fc9087e257cae927c5 dffe5382445976ae1ec4261b3370718468ba4ecab5cbfb50a22ab6d38285d3c1 7283670d3cb766afff7f34486489d5a1a5b0bb823fab655657166de815abec24 f7713361d1b7b267f55265c03a458233b8d077007687308da0ae02a3075c0d4f 202b3150f80754ff14b48f57a8cb648ac372fabdd91874e45fd0b6b5b26b2de8 cc9ad47925cae8fadc55c3005147ea9f93b4b8d7b1517104c24bf0b893ab46e8 be42bf5d3f94f09be5042260f359c8292dfc6f7c27ab8da88e9d4d80ee553e78 3bd3222539be23ca0edc229d3eeeedc1b41b8ce296978d73c86e762af79aa887 4080704d2b09ab7ed4eb0b8b0e439ec8a2ead3a06f817ce3f9363563950fdb0b ad35286dbd79ecb282fc7cb18c5dc7e7abd53bbcb26c824a3141fc054b8d15db 4aad9cc0beaeef5482e2950883d7253a309ef56e7fcff5df54f5f8e654868cad f1d06103cbc99b6de6494047a63fd690a1feb3082c52eed0b2ecffd5872629d9 3b55b2070aa5fbbc6f5a160de4e9f3c2f4655278f38d02bc6f5c5987f6a5d46b 8b6e16fef782152e2e03abe8a72a0c961bbcd899b27e62fc1c59a9b703aabc87 a027b3419222bce3f34445a08da62ff76712b33bbb62ff25436046e8c97ab78e 07fc0c70593b4023360ba9026368f270ee095f65cc7ea57f459b739f73328ae1 a2bcde7f605fd6d05046e0eb333081e8491057e369713b9f9adec7af1b55665d 687186ddddfd074aeffc932f3d56fa3edcf50479c2c537dc81c712c80f0d60a4 868475fcfd1604aa98ef79866cd4a7ce314850928880af9bc2e31eda14f07f79 c46158842eded9c26dedcc934ca9d51ce3eebe5a6173710225bdded6ffba7643 1ad3ae4a9d113f8991939e7396f74fb0d96280837f67caad692d18722a93a200 0ef7b4ff25837eedf897a910f445eaefe4520042bce6d666cac0b206db3dd1e5 7734da981ddc91893bc8a527007f824a22b40844d0b4537209e5d3d37bb27091 ebe6fbdbe09907e6fdf2c89841e1c57cf69c6e324f8934559cef075f7ac0e2cb a5ffed386db8174633ba84fb978f88f8217a6afda3ca2e5acf6e70249b0b4937 c130b6a8e631f76d972d0f155949fb7fa8d093e576abdafa584cfd192cabdef6 7edde741298c76767208089c421fc96b728a108eb96e60618ed458a25e62a0af 3453fa314a63d4eb7ddd4ed46dccefbc3c939afb8eb2d00a3ccb4592e5e1c39b 001057c3d37ee9247b99984c5e5270911227156b442a879a9ffa598b9c0521ee 337b79ce5ca206ad07c09efd4b90abf7d907be87cc842cf4c33a4a75f40d03b0 13f81b423b6fd6096ae3e0877ceb6fe79453a2714d72f43b8779d3f9ba7bdc56 a6f2f646deb6f9e205ddaee63ef8a76b3a5b54a928ad4f3e1dd88d16fcff3992 65cd6f6ebc27c988cf885cf88705f1868f66350f1aa9eef50e3e9d032f8f110f bfe7674163556b3b7f7d14d706cb97df910eaeac8e523d564aee31a02d63ced8 5fd0212e3214b85eea338d564a336905fa46275d7207da69f5c94cd76444b66c 0745a8db9d2d5d2cd987cf39a9719da6ccc397dc8a979bfe1b98755b83ced8c4 8d47529f198578fea2df336e62bb2509a978e570d20a03d0cc5ddee398b90489 3c7ab76d75cfe7c749c818939a4d00b22cd55d17811f1e81a2943368acbc9930 9032f04a5cfc16c2560a30ddde438fd67b34f03d067266cc1ed0d6b1f21a8da1 82a319462f7be63add5b1de1c57d4f96b7d01a37d37c1402b8ecfc7c23172e45 5fff19c41880b0ab48f57fc5453d4a14d5c22d78f10ae7bc7a5ec7c6d397be7c 7b4bf36034148946aa80874237e075fb735b3a5ba7a25a085fbf70fc19f63f16 5e367870d1be56519048148b998a8da59d93b302f8136ca1ce8265d92653398e b1ae44dcdc1345606bc107fc2ff729fab2c215540b088e6117fb82f8469bcc49 09a26ba5b7ec87989a79d47fdec7febf79647abfd0efe6ba1078a15b345116e7 a53e112ca9565d939ac0f80c9218438e05ee1cbb40e094c4c6b9778cd1ee9341 4480d3899ff9742956f8ea9686d3d52082cef3e150fd8d647768701d99805550 0cc2d147b225cdeb658984df806fb6121de31e3c43d73cbe979c8fb8251b0bfb 42ed973a0b53fd57c7676e9facffdba1fa56437683ea6839537af906ed04733a 00ff260d90022060b2c237a1a68251d150fc53b94af0b47adc9d661dea155785 8d7bd44609717a19a777658dc0aad8ff10c8fac87e643378a683f0097e916057 47f05593d2ee2b00a2ddaf85ba6a7bb9c56e09cf8ade444503dc4d426e2af9b2 caa9a7998ed8f932e5d50c969b38da96ba85fa5501bb63af160fdeb987f6bee8 8629cfd12d7e4d98962a96d5359d6df658740b02e3178842da6536006b11b20a c181bd65f77ad32482f0e347091f9e6469d6867b55ee420a6201fc7eaa5f9c4d cf322dd9ef25987283f3e35f9f457c5a8b04e8ff506851d068ae1b0ff35ad2cd 7a1257577ef572707447108a254387944435ae9e37eee8b92ac3b21164599e0f 57bb7764c06e796b8594ef58c605ea682790abf86cad7c3fbb6842f18c70cdd7 1358110fd9c8fca453bfe9f048ce071eaf67dd7f1cce4f4d52e9cad916554c03 107 848c0fdacf662cc9fd1cc58adc663b801b1819348c70d7050c3ffa19f2818a0f7733bbb9dbb547894d181c6d11baace57991c8de120fbe53ec12033b6e773807a84d6c6bf1f117ddd8d1f610501e24da2fe67de79ec69e485b383239b43b1804df1450cb1f2176aba74e58ac5b30a123318aec9cb1b8e0108d246bc489577a005ce98fbd69220bf9e31c989be15d0a3f4bf9574c4e3dd7d6f61f7e69ad7d5d061af789ff84cfe334e2dc01e9be3b6fe460160fe76c7fabc88a76a5c0f357cd0c85e6f175494476ea8a54b4fc342510e6a0f90a699c53c732477a91c97f908e0b7d48672e301bedcb5c8b0130e158894c1e14ab2df94268ee9567539247f4f30465cd47c5688b42e321e8692c9d6a6646b83db2ddc67de0f75e2aefe06e49b10d29b9af0f392611e6ffab054f62ecb84317f2a907dcf3232dea6c3430f67f77000beecf89388987705dc8c9328c0e2d00100073cc0d299cd22d824e5fe1e7250db49a56fe3fc9279b7467e1201f75fe684de2ae1113ee0800a385356853f36303ba7b9d43f8887aa372e86828778d8ab0b7be04b31b8c028907d9e808c3cffd094fcd5149150f914109e69b0104d3b4ad23aa2085625d721028a11c460da9370b517fd19f66b72626c9df5f8ad35a4492826f9cd57f35f0ff65912dca47bb8104db074ff6df7701c2ffade238672332bb92a46c2c6799fb1a63904818cb654b09a62e96e9a9c362d0bba455474bf7e9d6e8f20891b85aa6171d389b0f4425a10a670f82788cef79b731d35383387ed525698b923960871ccee2eaf214fb4c510caddd1edf31c1c08e2d6364f718258e928cf1ce118aa8d7b722502fa20fb97801f227fe677f35841dc50ad6eaac30fa74fe3da2bfd5bbc2fc85e40d26f54bbd092ef1830d9db570d1672e2de8a6c6e10be99e3038c00b0db4fb77c6be170a8801abfe3c6747b04920be58a8a0dae9ca15193c5a551e6506d541d4209ca859bb0abe6acf7ad5e7af8df47f4d77e59dd550a95a1c0cc0b751a1935fa9a8deb45b09ae093ff9057c2b34cec119e6c343c6735a9f8faee189fd4941eee4900c782200c2685a5091dd2278cc27f89fddfec1ce6ab2081f5f38f3fe855c8dfd2916560cb7e91aeadd28bfe333ac9eb06bbf7753240df35940b8326524a929745164f605d6d04196efdb0b93867b4ff6a91e533d11214e31d0262bb0099e373451c8f403cb3885c4556b71b1b0143c1ab3bee5d18efe396bb9c2087ffe6f1092c7fd620119a5b3f2db9ac9b5ac608f46c427b6bacde43e05707e0e46ecfa3bd72f26dd0dcd0487db71c83a7275348cae3ecbd2255263860cb6063b7f80ae1189f966030ca1da4e230e18156838fc7e674144b09660f775233502277d8586f2d81582a1074287bd247e03420160c2b3e9a7542e0ffa7be9c199df46c3e8c04e2cbb49990e735cf17afa86dfecdc9d4ffffccfa5e2808656eb5bde2c9b613b86133d21640748258e09e0695e14adb92c9c48bf81f3dc5b6cc638f240242ebd66752a6c9c09726bd5b92093ceed83c4e2c0462caa3a9f9437ad942c33126f76731ff9398c0049275f1d186e86594b8cdca8b7248ab82094869daf35db534c980de8df27fe04d72955c77389f8a12d887a578b312d024a154a1b92b87e854d50134b9e29e50eb5bb752789d1993dbdbda5160c02bcf3a49489f959c9d101ba657aff043d7b0801683ca20213b780edfe4b5edb32e5c1433375092cd808f3aff7d8db94e81309b1a300a7abb258e417124a2e902d2790ad17d31b534de0475f74d998628b6f05504da3910e262cb27c35f06a724802a321262f2be26e6d2dac4f959b2d928008a22631cc8d75341e48393789a9527ce77452da8519fa394726b17d83fdeaa0008f7125d0e787c9ea999f0c9a9622bb6de26b7ad69466a0ca88075741d3296b015da065b467b731096ff052b2d22b332a811f5a35a13de51e363afc12355bca0fe065881920f117eace034e78c7345bd8fe56397816630fa43efd7227d67f4707df8293b1cfd588f0db13eeb16edd25e264e292121b25ec031c95cd6f8cec120cb79b0caee5b2fc39ab83bd6dc69d2deb40babd36b5ad647889252eb0f911af080a6608f0d76e5f4c5984e6dd2869f5ada91cfa0faa23182350f423879ecef8057486c664ae11b6f7a578b48e2bd4f68cb857716f3dee5470d08c9068d2c6c7095bd09bf5c48b5fb8bae4b14ab1eb28527935cc4f9684b0b3bcb443344d00f3008a08659135815cb29cc1c975c9af8c5c3631ab47700a5606a237835bac9cf2058f87e6478a060e1e30215538d9a174d0c9247104ddd4a1953639d693b49eb90e84ba9175388fd9ffa986d0b9eea4829bab68f3d347be37a9bd762d2a57afa9065e45e91e44114f5485dfa154b2dfd11328fe88da51883c65c3be1b248a32610f8050ad7f30c41b0e73db7fd3b1b7b89ddd25cf804e33f6bc23b774284ff6e60e219b8df25a1869713d23439b9d5661fd30ae9176a3bd4f7afa04933dd5feca0102834c162776b07649845a0bc8f03e2ec923097fa1e1c0f64831e2a19357370256e423d20fd5dd117f20e8082c8859ce148653c2694604e93a8821d309c6c903bf82b5becc8a905dcd923ac964882a119a2de0ae2a31f31707059bb8f11c530944228c218ad16fbd11285833887d04a627bf8eaf44c4f55d9671e72378bd55015b03192e5ca22a6c048d9b888def6a63653ba6a5a286e2981217b333e3bee403538d475bc8c9a03ca32a229433ce877093a3099886bff0bcff17a7bb3f4ba205e6bb3579533fa92154aed047cf14579ced6ae4a550a065419264e7f793595e0ffdbd40119ba7bcd8f144fc8fafdb1a57919fb207950bb842a8d0781d08cbf70a2430dc76d9213eba9da4d6c927afdd2b65cea338f2a50deaf1592374b76dea07e827f1f6d41cda7b176be2987c09ae7ae6bbcd95132d075cae27dee168d6060f6a8876b9ea0a7c5c241c8b5bdea491ed694f7c2eade495819740fca07ae590048da949a90964e43ad5be2adf0cbe2e865fad6f48c2b8e5cebc81d21b974a060f2bdfb5ca38bcaf8a40beba5c36a898721a74549e570ea3bf7e3516a7062c9406aab469e0448096d52a0b1a84066db8780746c01c30659132f8ff264122b1b008b029e49dfe3569bbbb92998c409326d98bd3acf5f11c4f2d647845ce2e54b0012d619f4428abca24f5255cbec003c91c70b72767b467728fed9daaa229fef60c7e182a0acb350cc1a6cbb3e9ddfa4854ffe7473a7d0f9e8cd1881871ff69990c0b20f40090db92a22c768d50dc8c5fcccdb7dfc18f96d2acf6c3e1374533dd0d1d65302779242fbf2406d92812818405caa3ce9ac3df979fc078a40e2ae9700c5549087db7dd29aea603784ee2e5105a689ab84857be90ac2e02caba82df080a3b91183bad553d7461409be7535a4392af205380fbd9c933c60e3b3870a89403387b5d6f33131b3c5fc251495045f7fc4cca8d61d386f10811ff97249e5ea70a1c0b5962332c27ce1d6f378cda113b9dff1bc08283b8493d13757f308889eb0968347fcd23b9fec4cd28394eab2ece663392bbc7b8df9f6f7c12462b1986640f044b820929807bf0d107807580bc6db0d52b4dd89b9395457079ff982961630d25a1e8ac911ab8bbeb1b61f7537ea0c48bfc6e20d6207e3add7374a29dda490c92a429ff6d174d086f7ba00ea22d9d14f3159d48948a696d5a86bacea90e2800d32dd0f193935273f09c498e25ef22512bfde8d8be17a0d87cf85086c76a010e0b5a4135cca42f2b6d053f16480a25653f9ff921513087028b40bb759e2de90197e55599327a5eeba01dc4cf5ef8c88be88bec1364d011e4ad9b860fa4490a078371a5b1017d7c3c0ed07ac256025084b63c1bf8478c8dfdb7bea8bba6abb30d180d07b23f6c055668146dd5524819ad3e3919fb7932c401fa54e76724ae2800c297191d86b1a9740d872eba9b27259b870c9432545d9bc1994ee6b7bb84d60eba61b3080600ab778e08564b76d5a2788cb874e1d2a176b907e205564422be0a3c1f9e07648bfac95a698763c42d34d345b389dbc629a34a61b62776b7eac80ad18840dc7424e930a4de4697c0b26a3a2cba81feb6e3784b88131dedad5fad0e1f5922daf2506c4cb6bfb0d2c60afce34f546cafd14522edb79dfd2077501f0612645d312235698c37f1e4ffaf36eb4c9bec18f89283bbf022b943f644c19d0652a413ad6ab38947a8e2bbb1a9b8ada2fc2fcda51ee8d163fc7cca74ab99e3073f84024893edb8dc5280720a729cc8773f93d93ccbe0a2506f68da2b213578070b693c9aa896bfb690550dcd5ab9494be35e14a7d814b7b4d399bda90c438008e4416081d79c33826ac671167939594560b3e56b23cf319942e68ac86163c9053e5a9a5a38537eccdd797f2ce5650e204d447ac152d6cefe448c95d54efaef07ee67b976ba89009d9c7da32150fbbf7e2b57c60cc2b77edcf68964f0dff1e404eeb5463f7e0a6e612b13407922e2b69c30f3b59358d52f31ce60f37e40798701f251d2376c87a530bd497e2b4a4bfe80c839280888ff1bda10541c7dd182bb025177deb3b9bf6c4597c8551cce3a5cff2b8b6332bc4677c48e0a589d0f46f5074ec287bacc81357cc1982b06c7c1975debd9ef4ba815c93dd1cd25a7ec985908e59d7b7d353f0c19b16131011275cc5d139de46510f3c64f6e9514f51368830ced8e08b9c33d0e56e0cd2dbf6eda68eb0b67126df0e0224b20e03c8ed5a5980f4436207c314a9af8ad76868c6dd0be717e8010162eb491b16bff18b3454e7f0c2a54c20609b403c3d52b09795c38286d8f08d8ca6665c1c9f1eb2d7a6871750d6a0faf7e45e3cca6b7e58a81124ea6378ce39b3e350780abeaa01e5b190393045a7558fce19385867f17b50429321ff5bf229a2889ec96bdadf7db29b2c3940e6d6b10e0b4a58890ffcbef0cc87fc466d36105f6614619f254b6fe895bd15f0048864b3502d902ca02d03002a2f2e91cd5c5258268185a43e51ba911419a7f05c9bb405342822338f13a0a4b6597dd779ba7aa1c293c858ca896badf74a6b50da4c0795ebe9cddcc95acdce55b9a36faa9870bcb4fad7dd694216ce07973040aac8d509dc86fd616cf50b96e0cc30bc9bd0a48a400fe3a16abf875ec30173f07af3b795a4e6ba9f70b36c78bffbe9f1332305d2db3b659dff4cbd6fd65abd207eaa9985c37648cdefc6abf1ccd6ac210118555593561c1a7e2ac49512239170bc76cd1ea7bbea3601035d9e173884f722d2657f3026552646a259498b4dfe60c1b8a9823a3b92c1d6c169cdd654bb5255066ab180effc1893383211fab1a2e0a2e65904c3797293925a3d4c32ee26194e6429c778313c518f9bb64ec4394340c2caab05339016465f9476c7eaaa201ac8ade7c480a059d6f291f32521d389d0402da00b01d55f131ceda07ff92c2fe2229943f40e31ae1c9a95a6e5a4bd3180d393115f29d77e5a11fb448c180fa7f6ef89666e114bac616f2001a2322fd5f022b389a6c55d1dd49efeeb32eeb338ba3f3f8358dcc0fccc17579ee9cc4b70a0ada47fe156c120395cc19e9a4bed46938519a4b274d413e96a4d631ed291ef70ce61d08a712b10bd11f78d9faec82e69609251ace440636fb17377ec6e2dfe2061fac9d0fe80c04d9e3b4d4681baea3c5288a06b007d933ec2216ed81c73add01c106acc2067d07b54306ac7e4d024ccf257e5647b62583fc6adf52ee766ebc041af8897f7ed6e09b4c9cbaacc99ee3d3a1f34d034a3934e9105d3bf623cba40a07b17514d664a009067740b9fa2e0e4e7a8014ede8a6e71477e2a5c77ed8840374bdc3ba5d844abffe8989f450dbc7256ecffc2a85b6217179c74628ffddb40c052b3193929fccb11941d18cd50ff1e47876dc7d10e4d48bd4261d696a8e3a007f245f9c48a8365bd64b6975f0a8abb994559df4b3213df56ae7ef13bbcf0104ba6408a7f3047b718a83ddfea0a76d954dbb2dd747ce3e07eb1bef9aef5cb0007fe30d47cbbbf0dd5aaea9df5feff1112f4d56c817169c6ca8bf8faed26f210cb0251f9cb82413f510c32d06068b942021f12cd116e61275b97505e752af7008b1b55dff950dba575586e08c3817b8c98496b3c8d6e04ada9e2c25b4b75b810ff7741130fa6455307291ef8ac8f13ed9b3c93d6478cc42370288855beac3fe04235fa66f970906acdfdd7756594a388feed42505390eb0ebba94e80daf126a0b78b226c5fb7da592058f9e624b5131167a4f45b30041028643ceda71f75fd20689077661b4f48801fb6dbc9a17437565d3250a85266bd0f3b92130677970ec0d8dacc889e16dac31063d2f8c0a64b3bc258485ec7acfef24d21325dd6a8be409daf37555212f985769de8aabd4f4987208524a08b310fb82bd2d77a49e32ee0d08e4289345dcc750558297dbb5ce64508b70493735f96c9edc10ee45b0fc6c0a117ca42176f288e75c599bc66b1b2f7c678d17fb9f649e49c1cd6efba829dc024246e2ea3db76fe309420f69e7c62ab339f205f3993f9e75713422e25806bb057b53eedb05630e1213d0fee48cdf09f9d6a561dfe3c856eb2ad5e19a7d5fc70064cce0d3a57732c6c6bdaf95605080f190d13592f22cfe82da94d0a634a8080090fe251b1147b8f3583c3af98d09b8c8f427fbf92e0baeb37872628bf5ff8f06663e2696b3130a46d05d6d850be0a781d16596d87c5f3324398b83cba840a102a12597bee995a49c7809b9a0e8912764b0963352a63b95fcf630dd2400b1bd0d206fadf62077f953d5dc3fa2415e49cfaa29f07ab2cada25a5bd82ea0afa8b0039896b299b694da5dfe5c9e0888eb7913bb4a19e361bc634da386a41b5eab5057fe9aa84b4a4888c82f737d5bdfaea35e25438ff1f5a7228491d93e2f684d809875bde27cae3870448a70abd01ad15c15cc253496e4d225b18d30387e7b9d9032ace4fb89513c8a3bbbd8c95b071fffd7527364330a4c4c73312a6b0b48ef90b0166747924511a378511cfdb9c1db2878e1b822aaefd2551a0652a85a2e18f041d23afff2c809d6ff422e455e1f40227d753c86e1878c98430e62bf9ed28850ec9f8b5760276bf4e4bba1b416b55dad0de5309713b067a723f8b0b741c68f00d2f3ae8a07a555d77b90bbb70e6fdd03f1460d2805a5167cc53668ab705fc9d057c5485138a89fbb6d88c52c89cb324a727134b10fef2bff959dbe3a29326360b90891be9325c73a69cbf8d918b634198de770c793728edd27cacadb5c0642e04f203107e109616e1602eb9f91b6f0cee7716387615f9eaf2c4a2cdac13a35009fa2603c2e7df7749f64d901b6a6b356c341d44a8c8489436cd1f0150afc00b0708ebeeb6c1272e3f840b2c3bd0a97dc54fc5e58fae98241c43f53f0a5a934a093d77f09cd0f2c31d5c993868e31062ad2698921b2f6f53d4cc7601246a04b3086f65ce2e21ae1775007a18e117184cf079477dacd79d8c12fdc4512947f343026b8fd5f85a5e2678ed3ec8c574841c9a5cfd582b8d7f1794f097ff3e04a8e00c1b05c9ea3a145c80ff849ccb8ecff88aacf3dfff6f37bfddfec05457167cb108b137eaac5e17922ceb0f564e06e19eabda5e99ecac8c5f1e0681026ecd3021027102d0fdf04c0593b69854b0468adc2b0f230fa0eec90a59ad74a95cb71210080d1c2155eb51154dc6b372523c7fd8d7a95a98724ce60ffc3ab5bd7511a86702475bb2267c4f632521692ca34d2c2972376708da2805fdc72b8f5cf6baf3490e2fe6a70a09d4ff4bec406bd1ca11e6d48313819dc488196d0796b7901c3ab8040048f6212b847707491c04445d6a5b6a25b6f6a6fc85b7800a5ed1d413b75c0a9a1e0664c9a8b2660b238d30c20b872d1c65b724ce6c82775611571fb67e850de732d8ab1751ac2f9b308f6e758263997cb12bfa83ff18d2a54f51335ce71108394233b6b5cf0924cebd82fd5e1ab5bc8f45a090fab15c09bb0f375ae127480d61e0223d001a07086c7a28a2daaf95255293285a56e414b594ad4bae49a21a0038be0ca7732e64364015ce9a271c570d8ee9f5893a50b77ab04e0b9fdb34b3069831eec9619b63d1525d16f2a70914ba5011bd92c586c9129790006ee91b6f0094b8f0c2d75aa3ea399dba73e54c73ac7afd02de9a6ce6a81d5d13bb1ca5f0078bb9ec2b63ba79b96df33aa64514184aca3a2816569103ffd38274fb9fc47f04289bab6adea974e2aa6877950c3df0103b302da4ec181892e78fbbf4483aca0f782da5a872afef5468d09635c24aacdf676d840554c22109e781eb2d09097e057a21b25ab8bc39c281ebc21480e6d9bc972e2b1ffadfa450051dcb1e5d637c01d0391506787a9cf0bed6273a3efda0a0321dbf48c5fe4a1e5a470ce108d5480ee24c3eed1330051c46874a674ffa202cd545f5b22354a9f91576dfc7024dba0642080a5e080c5b9454d3a0025fc80fd315e32d83f9677cfbd8e0ee5039011307d1d3a9e90184a12be9b390fac3f9d8242d4e8fdcdd50caedbfe6b73c9401dd0e95d112b28a604b94bec5dd802eb0db53d8ed849f81a85190de6e71d9894d3c04782e2923c57977b30aa55a58f7d73334537c90d263838279b939777a657b570a7e1d02c2debd71258676e57c804ced408187a2453f9732b811e862eac282690f6061e39d80b0ee493d603780a60e97398fc7ba7b97b853b74dc58e38ba53a104bbf6143269c99075bf7bb68be828857ab394b0427925bba7b7c881003ec7e50cf3706763308aec4c363ae11d6ebd93955a06105611d3fa76cdce4184e81e45067ca70f26da138c87643fbaa0cee071b69e01d589d18d2326392853d2a867d6056c3948721d1b1b489047a2895972917e14f50ba4e787d12a42b4cc27c43e830a88a6d787a62f27d363fa91c911215bdd9980c08974b720d66b05da3ea0a45d076e6914b5237006a05d3fa7319f690d22f9e08cbc81088a171159db515962730463d08020499a59cbb41d88ddb1d301cdedb7491340fe0cf9656daa03f2e24f0e36dbf1874d8f54ababf888410598518797d4b1c96358b9be3b9a4bb39b4787086605bf5b4e91879818f499f7648688738cc417269be27ae828c1d9edfac8040fd409057fcd2b97d8f024a6b9573cf9e5cd69346ca6fa60f9b9574d23b8d0de073e1c60b0a8db7dcbd964c058ed804b019061f9298b9e9e80d28d551b02e9630e2447e309497fecd794f5b430c0226c429ce6b5fcd586954569366b0bef476b07e4c1d6049dbe4838a212421c97496b9d2920d96f6ff94dff6fcc965551d91706733325b3c48a360fac99bc2436f612447a7e74655acaf68d6c0327829067770da573351126a1db507326ba31404357c53208386916f9ef8d7662e8f6b3471b01da0e2886169c9215ed1cb9fafd1da3a2cf00917aa7007f8779ec4455277ecc059d933e2afce960bd9f7222e7d1f4dde040fb4558f69048bf3a1b46cb78237801f91a5a0676436ec0b7b0f10b1bd89b790214bb54f64f5867ef8deafc51004d0f3cd89555d9312a768c49031940ee3e108ba6448eb24fe02bdd04d0916ba0b203636ae7e564274559f211d61f15528b646b5e0354ee792528d224351d4f5ef30c94e3fb756fd7334448cfde5c4ea82da49c587a914fdf69bcb04dbe6fbffdbf07f31dff4d0740db30e78b70f731bc361aa4c8fe84e28b3b0dc62fbb9a7defc20e14b9ac25d1e90d4188aa783f6bf5d11e2bd288136f8567e30a8662de1fdd7d020aa61bd50a63777c9099965b1825951321f901c8f513ff03b5cd9f2132a63b0ff8573b857a57798978fbfc1e4935316e11bf2dcf6d0a531b56ad312604dbd00aa8cbe091dd4b4a632052488e0b843bd302d8ecb77a39684b49564364205bcb09d4b2d55b6f2610c309f4f4153defa51a2c71f7dd40408faec0ff3397295a7508f75d9085940f7cc626c1b342f73f056885db0060ec6816467cb60b885486160d7e2e775b6254b3e13310a4229ce0d52ae7af95792a7bf11d956f6b77cf58eb0fe937453c16ae218429f759b617fd1c9a1b656b4dfb6e37d0590af9e76d5ddc04caed59fbc5cada04ceead6c84e3ee30cd46b01a71e25fe56f5d713735d80a00bf8fa9bfde7093f88aeeedab8968fd0b5a1d0bf9ce57d042853b3c79767c4c90e898c551fc62dcdd4ffcad2f53970c17881aefdefc7b31672e0ae7edd48b1c6000f13a3f63e0658ef31f2d9b6831062ccbd95c1077fb366ee5cd482d6f199b10be0da73b421074bb95b7d4d4fc77b27741a21891f4070ca8b6c47bad24410c40f51cef80f07ac0b736b81c72f489bf1c98d5452c9b1a376acc02f316c3d6ca2054d9ffd7b9a43309e90b0252719090073389dc92fb283bae482e10b00bdf9740b623f154f2e73c1012463c5d1bc1fc0821d4b73a70cf147c3044462b0ee8fac02ce9082e7552eace098a227cfa2bb3e770abf744b8b7c5a92358c853bb434b906d0636040b6a5ebae45bc63876faac43885febabf59c8d3c3f1ed817a158e7606e522b17a5f61b2a5828561f52ba7eb9c15917f07ef58dc330fcc27e9097e390a171854443c37d603f1f3d1e263accc5b219d9a79b7b415c8d860b9c3624b210a89dffcc7aab06f1d13cae86c3476f037f5209968e471e888bffb41f016d1c50ccd68610e402564580a4bd54d55dd850ee19ddd482b5d0994460691a62de36c0dc175138b7ae6a5ec21d0f2aa78393081ef7d638517e9a11cfed9cebb1dffd60386eb62ba5a7622d5bdc7414ef4ee279492488e8a06996c85a7cb27c06cc88e0318ea764c56bbcdff92b07747de1d96f12d29d3b0802182d7ace3c08f7fc9890bb84b992cecee38f8d251aa7ffea6071b1d2d5310ef322ba96f577997ec15260e11c20204aced8235b879d4bcfe9304a4032768324549c77726474ef6574a530aad630f393522c8e2e1a0e93940ddf368a7c62bd0ad0703eb24cf66db597a9d0d2390e9424e0f119b0940f3bcda29686f25fbb9b929545fdd075346eb88941c00105726fbb36b4fa9115c0359bd227aec612f9253188377f8db9751ba768076071881159d2f5d1bba54825afbe244665e4dfe7ea562b62f28b746ce0f32623601682ce2c3229a5ff14dcba206cf7d8ddca1e6cb93a29a414b2cc65826faa7e706fd37c4063cc19776c4996c87bccc37538d45a0c80b907b3720ce606c42c5850f0f8c3d34016dd6ec1762663ef3e83013b2c1655e4e4c20e72b1be7f069b2bf0ee1d4858c37ea52c3a2980ed79e78cfb6e86aa8f85686299f23bc1fc62c55570108992b33d13df169abd62a25595453e57b5c6e1c2724965c06b7aa506fb4ec095e0c86a73db10b2b16a3667e045fbd8c4ae66b636156be75418be3f71904c1089056026d2c527458eb04744b316018d3bb17b8acec3a0f8e919bb259fb88c70303c51da13dcfc9a1fa8e5c13ad5332b30ab297f8c71020d17d97d4bde7fef30c3478d97a496667c876cb4575e00868ed4eadcf01138450aa42287afd5f188000d15fd50f43e01508a008c4f306831995dcd88cd80a3bb9d133f7eb7112b10b0bc5ff61a955864b72309d25dc0e45053bdb884ed93e6bb9f0779a225680648b0039bf608b39c3da583f5ad7670077afbe3f41279c9df7760126e74ff5055cf20e0de870fb41126b9da1e1e789fa09dfb2cae73a5f3ec2c9c0ebf563e7502f560e0b24fbda4ce29f8805c24d20303e9a3a94772a57b6668c12340391b0a466f60ad6970ea7a5813f77a20b3620b9e1e433f003ac04988c2454b776da39ff89920d9d5a20fa2b3d4bfedb40d4c384a91b719483af62ddfcb141230cf957de6b5e06cdf17130a8c3233aaab69a4c47b3b67ce20d47a39df64f424e160e6cc52e210f9409c8ec5a6711b97f20096ec1c3f102d4a9daaba9c3f867dae846cf11583e028fe0738057a8a0dcef9a6ccf88510b7dca83260001e3253092f3ff25791d6400880359ecdd45c79f48a2acb125552dac5e5926faf0e7262f795704a61d3ae2088570a4dbedc6ac3b6f58639144faa2eb8fb09a6f1f5a8ceb42e1173bba76ce07bbe535d782d42d4ef315ccc95b92cf8f8dbb9e8322b17730cf7e055898b9f0096e5dc2ee04ae051dce7e9a85547f7a85f7fd17d2285d3b49ee0695b95ee6f401440f8529ca8f2503f2169e95de3fa059a82b7eb175555d4c057e18487c97f6022b2ea08c73223f41b5179cf0a5ad89314f12463041e13d3f1812bbff34e923008e684d70a5d6887fe9648ca59172d1ecdd396f278476b9913e029037dd9d9806e3c6e1031cf6e76251c7dd239b9110ea6fed10572bfd402d8e4505c8c689ef06decd16ca06e9ddd74422d0105720b7e89fd94037b3ad11118690d0c7cb66310f2b6b355304dd4f37f41e78c02385bc2acbcefd4639f73cb867af108cd9d5e400127f2c204dc5aad3e7e71f8d7eaaa4ce6a82fa6ee58d2300dcd3c5b2d09a43099be2e7eaa2f85e53afeb9a2c104b1058bf862d99c0c0fcc7861fdc35ef5a710e45c496802905c34e71a170f60c0d5ff5afd149ae285bdbc1c61f1777c71fb001bc4f0d378204307ef691a36e5b3bca6ca2e1c45b9059a7d2a54b7245a6ed540839976d0cd7c33dab7d617c22dfebc09372cc3afd54e6e4b9ea78ef9d5a797e07fe5689dae6a53c2a790612d53ef918df706e4a120906f56f7bdf446d84733c06319a7cc3712dfcf83eb43ed60cc79ce7c8a6f1e1949d7ae10ba40cb6ecfb290bc7f1766e342f4dc52b59ca2430293e94ee1fd8e6a49467b7d05f13e7d7940709a8198613d885e9cb81535d1bb823f37a751871ff44b2635dc251736eeb868606feaa52ae24e14c231b641ae1c7e224f3c415a4acb46a1d358bd1c17307ebea0aa7dbde0f80df0414b68c1797b5cbf208a2c1cb900005e79ad08632247e501509ff883b41224ef381d7fb414e58e6e4796e5da5e449baaec1af97b14a1e44880d658d571ae26ca9b0b9f9df5ef7cc5ee161a4c19768619ebd95c5c0451895a90912b02449d9f1242f7d57c56a07dd6cf7f261954ebc33837fdb3ec53b443c990128e79f778b674e83ba210e8b2f0146d6529b348a2a884fba193a00746894de092e7c6a084202f8c9ee82eeb40de38d1c92ceac085b032345b00dee21f4f3c10066f6462ef5ba113918dcc1d785c6cb095590df263ae60660f9704862554ec80e2bfd353b7ce3ee7fee8c27e46fb3307c4ca19ccb3a76da4c242fc2d2850fac0961e358bcec2d97118c1b5337eb35746c0f13156682d5b20eedcc23f421da6001ea5cf0aeb54ca01f457e9e5f8007a24be9a5e6c6f644030c55134d25c704af0b2575a5d4df990c460edeecd8eaf7e18ecda4c710824cebd9492a0d4398a0790d4660854973ad4311eb71a9cc41c97f6c3cea1ebebaafc7adfa53bf9736444c06ad9d63355882eb4079d88c79422a1b363b555a413803dafb9844cd7716ba3c0136bdd402eef6669328cab8e858fc24d831d44f6f35b6ac15abe4925615fa570fa60203ae74cd04e55d3940dc223bcede1984ef9b9c9bccdc3a6d020201381200fd7545ece2194e831dce2ffed5221372ee9fce6e74063e7256b6681e3ca2f00b9a4622b907ce1f05c280fa192d943511354e29146854331554707539f4066d0c09899617d3bbe68d3d881ad6826a592e972ced5c50aac80818df150180e31b04 -generate_ring_signature 70b22a0dad712049354729ee250c77812c8d958133d282a7ccb5c7ce404a7b18 fe481951dcfd22fe788830a0710c2d3aed379ba59ce250ae71ea46a62487f0cf 1 00677c75a2b2cb1c5b946207d8f6a4ad98d9adacea1e5481fb84af52da4c48e5 e6bd4c1635814c70cd87d7b1e256e002a954c151ac5e0e6cbbecb0ab7cf74801 0 bd3eb811cf89f0b1f6e6af53c69bbe51f2c3330395ab3df88ce47f7e3563af0de58ef47505a0845bd45366c1a8dee5712614087c96146edb5288635431f49c04 -generate_ring_signature 70c5e47ad8fea9638668fa564ba969be479001f55eadc7869b102d77b5cc5214 af2e9cbb09401113f23399722b7118d38070d67810cbae3c18e82e7b7da6f472 206 a18422fb54e5bc1a14964fcf02ea976ad907a99c9de543aaeaf998f049f92d4b b51182e7531087236c2fcd70ba1c99604a790e6543540582a638652844f962a1 6f8b2edda8e71567c9961ca07b818c8dae7288aec02c148da0bcf1fc96bdf146 7839c78aaf168c645786b1e646261a865ad44b0a83024f719271bd08e9db5cc6 664a1b716e8f6d679237984ca759520ab88db8dad87bf34d581c61137f93044e 3c3120134830ece01517323ab484002429a65eeb0bb17481bffa97774d5aee7f 933409cfefb692004ee42f1c281c0451050964c115bcd81f79dea07885f44948 ad6921f89907b538f3f08e34c1d253cb0d5b8ff668f335a9cc6e718e9964d170 1c2aa68c5a31e9fe7bbb8623570e67bab36522659cd88321c3f1f1dc468cd8a5 66078deab22c8b165e30dbcdf5b9ffd5734f7df003ca3fd515e535107e0deb0c 4330428b7fd83c847e0949054d66632dbb03bf17f9255126175d6d551b8acfae c6a01a0bf78fa2b335f0d5eba32fb0fed7a5453ecc58042f97a57abb4ab93768 36637941f031cf30f9abad0afa6ac9df869c4dc7239035f00b2536c83eb07f6e e582018b9874cb88b09f9e30ec9b471cd154ffe4b79685342f4959c653c7e30e 9d988d6cbacba45ce8492043930ada21ee880e0f9f7c2bcfe34a978787b7317b be59db2de9e9c18d852a319b8021db050c8684e9b4fd27cdcc70d7972f262235 701f1b7057adb0d1a917d09f9703ca267c6523a15a42d4b2903d1c68bc9dbdf3 ccd77941930d74002e7be55e8cf6b51b2efbb534250352f9841cab4b09d6101a 9bb62944367b74b680de5a491449c5f4c89922e21999e4749c63bddb96757b45 d4f1497d5e1602dc78b67cc2410369ca0b65ca3f43269d48a505f35794abb7a8 545c4f9c95f6387f51da3938bf05d6e1dfe24ce7f47d00673047c6d15b775b85 9e16b849e343e81d0a8e4856e5b61f24e5839b3aae6e3bed70218a831b7ae4b9 6b85c3a6f57abef1ee42b1929198b80bcfd590d2927465bf86a708a8d8935016 45702a3b1ea9f88fa318ca774673c9f5305b70f81eabb243ebc51a4d456a39ff 14e17ab717131d76747f7f89529456ed4b7e0b4bfdbefa66b479a1cdfc2cf1c8 b28bbaebe6e5a2082179a5d40f82b858120207ca642c4bd208f86d1981e968ac fde5f21d0002ee5fb68b31f336de025dca70152f8fefc8c96d9369c8657bb45f 6b6250e0a9e114274c470d03b3a09adb267eddd060fd7180a3d59f2b4c84a255 3f912637b519de978a550c9ce554c4cd8aea77b7c67bbb4b61b7d35dfcd6cfe4 2030f7603dea048af9075f8d5f94503afc5e9de977d18606915200f186c7cc91 b243f8f735967e6d2fef727ce4ddbb07260033eb06e22b2c2a6e7c573ea8b957 a4d61eeda78d420b95dff8eafe85b94c4876872f1da29b344d213ceefc4913d0 c6f13c6b465dfac7794fdc9b025461ee81a20a5e12aa1bec8169cfe89c66ef29 a4653ef4b4897b15a9842bff5c3dc1511ee1fd1a4709eb9bc11d479628b5a49b c5b6f5f523e94d64365318fca8eec9f9b69d7517b9d0516273478024c07a552e f9e16f2e35b355a188119e38acf7bc16afc4e0e239fdaa97dc487b9789ad2093 8e32ed09461857c41eee4eb6f4697107373ac5bfd404b2aac521aba53c1e4606 da10a8ca7ec34b14f75c82fda8a295339db1a95dc0ce4d51c92dade911a7118e 00ba18bc2201748eb0ac8a35142ef36a1f054f45cf328ce6d4c3a7399434b51c 77e93d9c6e4d0fa69e03244504cf715ccb6e1771a68c5a4bd01e7a7ce1e89ba3 cdfdff3ba97751f3181e617d7303bf4d8dcd5163bcc40af5390ee071a729370f 36e2b4cfaa03c516f3833c40d9d8ed3e5f123f81fa878aa7f56ee21c687a1c2d b978726e14c14fd17ed98d7124feeae05714a8109e1dbc14f503a7f04178ac0c 29dcd31fd684e980ae3fc46e5da92f7f5e78babdb806087ca36ad8703734af60 c1c96cbb9e90a08dafab66240ec2a427c9427dd6cbe2c649aadddfe2f2cac4d5 ddf16af1d9f17774b2d18a01f21633c88e676729fb92ad1ba2f5a6e4515faf3e 7f3bfe385a2aa865c30d151d1d70f7780b9404c3ce0b80cd8d76ae0bfa2d48c2 33cd6755c2a765f34711898c5cdcaa2ab13ccb4035809cc714b8ff1b49e312db 6a9c43c587cbc9040a1bbbb5ee5b31b5fb15c8e8bcad62df9ee4234c0137b330 ed1e2acb487769fcdabedc3a39a4a33f00689ba64d2853c247f1a82ab5d9c900 a7d0aed414d50b92555e68b1627c84600850b2f67023eb90124900fb54dda7e1 9c6072d044134b540033a836fd2cc23887a8a82559355d7e05934c46257ddfca ff51af4f58762907aa34f99131a60a7d303391b059d05fae1d4d4e52e9a7ee12 ef073664eff8f23d2db789333d15a35901822b75146bc40e6a9a60bc348b0f43 b20fc9ed263e55e0d3b17ee113d43547e373cdd165339861d1a5f00824954bf9 da9614943a2b671472b15a1da5689b2a22503e468857e9fcd5a80c8fa0616927 b1d8c70e8927f0a0949c7ccabe0f8420c7ed3db8d0fdef72cfae6c34ce3c236b d2229f0f33a9fa68062a177416c13ec529f36dc95429c6b3e2030e7998137076 1cd7d9d9e748868bc060399946dc24d156a1b392d6894bc1ecdc54874eb26d64 870f6592e775e7787cc3141ec39a4bf8fc40216d768b215ed2c37c020663f568 c7ccdd2c40f607a04ea79b14cc3f0e1087c1c1aec9cba9be3e9a040153878cd1 4efb40425203e4db182ce267e1ce8f9fddcc7dea9c231875dd2b477f6160f93c c77b8ff4f3990a4a716d9ce40d9dea47d675d4e2e8032eb4e158e71e22b593fa fafea62add24d9bfe2c5678c3dc32c3460686350cac842c68ee8c9dce4befd5a 0d9d2879be4d5c54549a652a0332937b19a171d08b87355a057c155a49dd3511 7d37429fbd0fe2b2188a93c537c7e55283ef4fccf2ef28dbf393039edae68d1c 9647f768f127751f8d2e8df5bdfcfe0b50ab08d002b859a36be77319d2f626b2 25a2befe5ecd5c5afcbee35e708c513e9980d217b9982a894decf8e723f4267c 49fb16a530ab7e69538cd98e63e69dc602ecf3422f854d0bd9dc0c56a6fe435e 9a4cc03169cccbe20d82c8d1c88cdad2c0e16bb32c22fed4a5325ba24c5da531 92ad7fd060ff5e009df4146670aa6f3c48add5eb9201ae12c3545334efc68d8c 5508d45bb35097749c0bddd3041a15f3f30a73f8d8e6bc26edca97d2b3ed8eb3 085d6e6167b1711a5f0246198a0ce033445c56c308caf2ffb67ed4bf492a760e 814453420ac7935b45302b60a76d60ceb3d875e27d84181cd995ab0cf7c194a4 66a3b5485bdc1fe37020e728315e4952d501260adcfa287640a15e4ff29934bc 7d3202c71e8352547fef9f2effa942969472ba6b2b711685f1e7ddf767bde373 c603687740f6353258d1563ed82e5e72b7ef7738425b829089e044312668092f 78a2b79ae83a3be22e894c61f9dd9944816749201ebede34760f0d97bea2d29d 77915a974635dc324949da90d5a6414a9abfff9c6a1fd2de2397ad515ed1ec4d 394e0b6cb9bca29f0889e679730af807cc382f846291fecc23ef891bf4303352 03bf7c7d9e5f15da8d8f4d8c8242eb7d0f8173f66c9a709273e1803a073e7c0f 885a745d8efe981be6a9aa5eba6b24b23032229968d62ba2f680a437051957e4 bbbbcf28ff988f39a47cb062cebac6a1ca52cca0b7553f1e64503c9508ee27e6 e4253508f5c9313bb1519bae17f58c685d49e4194ea7b369ad0e079878d253be 33e5fd5640355e45d35e4dd7f1e8e7cfa2998a9ef48c9c887fc31046881663f7 8aab3224dd2af87ddcb5831c1282df4fd90b353f4269d4da50252aba203d19d4 be6533d22fa31ffe42c80e1a1eb71d65bb27a8e63c7f382d1a00c254dcd986f8 9c0652aa08322b9db87e6b8bea6868994d9ac10fb89a5c1fd79e6cf05e4f451d 99c615eab0941b915fcdd01beba0f79d841455986f64b211a74631c04adc45f0 eb7436280e32dd1c1fd11ec57d44e4b960630debe8fd3fe9b16f7e25455153b3 dab838aa3a6646ae8523bc8e612c5f76bb5cd21bae09af8ae035434a9545e1bc 6b0f31df949cbd288c5d24063851ff1c107938cba425be209728e09dbaad55bf 83eb14b50510e48cb3f336fc4aa0003c1fd2dff27e26484c9e3cdaae21e0f73a 37be5905a9f43cd4e56d974dcfd016461c3d066d3fb227d6411e942705892208 53963e49426946c393d7051247a746783821d70b04889a094a5c99f0107a48fa 3797c08b0780ab73b9f4897a12174a42871968f024f767ad713f8a7c35995b5e 35f08b38741b662a557627dbb793e4ddab03a144afe29f15d2582f528e3f54a9 34087c19447afa9ebfba8b6312969741fa38dce9a3c52294c08d949180cc79e4 7352d684d1137c23c8d55ff9c01d6dac19ab3d6b8f8a30ebf5f9789920e5c3b1 d20ac3c612b2b275c0c708040418562f80ec07fa66d5b8bb166d115e059421d1 b34a94287b0b92f980fdca1985f12feffbc33e22194cf83f7c64f9db3959d810 b00a64ca8cd8d6dd32d2e23e22fcbbda2c979e3a25e095d9bc984b75e29263ff 88905bf24369828cb2d7789ede9efa19100e1de11fb23fff84c5f919caf1b200 f550c0946b5bd38adf6cb83ee5f66a33f6df9a352920a0608cd6973294b88591 b84f4771e6e6bbfde0ba6380d7b0adfd745782a79c665ef158b35f30c3f2aeb1 6125547278feb8959d7b44022834dcefacaee1821a2b9ad98072409fdd1fc5a4 2bca5c5a2f52ddf22fb94c1ed7f094beedec8423c2d908530d56bdc6dd8b33f7 d122a98f60cbfc9afb08c4a3665a4297bea2e28e1aa14248e534792ac9be9754 0cda988e49b35ca39b860348c499ace34a1cedef1fe980bd791e85cc9a3eeaae 50405db106877d4f79bba49df0d00186a34ba02918f38d10a6772a08516f358c db86f45ea5f440499c1fcbddb9e094ec839219d90ff65ec5db7f00e401f294aa f2b186741767357374da23c9c787b00f7715f6ddd2bc13f4ce0c7fd8af871af9 45dcbdacb01ebee6cdb99b6bf299a327d7600f911eb178b6b040e427045893a5 7c665eb4e236b8fc0df26b4e7006ea202158ffcde5bcb01bdc76955332dc4612 e5c13f2bf51221881634a0b3be87f9bd3b77ca6fc5190ba73496de2025d9e9d3 0f5d6fed8deb031948aa27118f24575d129130cf4d54e8c03bdd5b403077b9bc f5f83a10c8257b8571056cf96b205d6e29ae49a045165f9e81661ea60d210b46 04f5cb095be125daa3ad6f020c25bc4eb60fc210c3c55ea6975579c57704e006 310a935599ac84e860c339e951c795d560a8ec6d0a9915e36f54bf7476bcf7a5 02e7263c5f19528ab4807e5cb0de10f754189d00768dfbd2ef200aa1ae8bb2f3 9e7512f100cd122c07927b9797b694e4829ecea344c5aab64c31e2dd4fcd1f4c d5882dbd1118a46af3c624b569edb0f66d6c7eebbbc822a09e74210605d05858 02fa26513c2e35299ec5634188849a3c7876f283d8e6d95875184dcfe90f928c 7c1af6f4bfe0fd44c10c6e17382585eb1f6f6e1c0c0774fe66517839b4e74a69 ee9ccd0b683adee6b6c99eb80bfc58d50ee650f2089b23aad6a53d1514204d3c 7a61e0013420f41c550184125d3810897caee0c1cdb035921461d30c070f5c44 5a3b4acb99a292959c09c3bc164aa35b8cfcd80e8dd1e5a0ac18b4b20c1f7beb bfccdcc76e71a16d7cb5cd68daf3c83ea71ff3ded30cefc9a574d75cd7ed3cd4 0d37450354f70f3421920262eedbb2388b4b3025fa7b7872045e108cfe506a69 7769a6ff5204841123e2f786b9c438157a68763baa0ef3b911b1918dfc908fdb 0281057269fd5c1792dafeb5dc50f5fffc205ef14b1a1b495335d41fe9833641 eb74bddbde03604204f8d59400fe0977d2fadbc4591d25092dd8507ff1ca0441 4984c0958c38d0bf7db3e714963b7ae2be3f14e4247aaf8625a1206bfcff624e 416cc5e0618e97a86a868b745b730cf5082736b28f158a15fe97d46dd18943d7 c0334b9b1bf615d4e50d93c5cd68c004f616c96448640f96abf15a05f259b6f0 72228197fbf42e0bc7fb85daef82dbe1f5e2dd7b173e80b590bc6cf985d5a065 74d54c40ba88a6e7e407696c81045f77b7ca443b5f676f9e7ed2133004c220d1 da36cc9ea4368c90ccbb962bb33c447d7f1c57c6b5f0073f1bc1f453a58a51a3 29346ae924c2c641fddc37b5db1a1cd7d8e8dc6c10f397ac1e4296fc50f957e4 8ad915dcc38e22bbe3808ddd979703b55641e5e082d922ddf95eb55bc1dd1c99 f9602f4dc07dbcae954cb895a266f64f0ae8067aa0de93c828b0b63ef77b1286 127806dd2c84355c8f15d5542dbca5d2f545bf7aeb97da34d09ee353c18df7b4 4808e46928e4e630867cb664a2a594e847858220ca93bfb33e06ebb991816f60 f45ea82edbdbb2b01bf809edd7ed8c7b5d5bcd610eea3e3e65fd3d2d0813e738 b9cfcc23cc02517f75dd3ba4f05fc727681786f67e6cf81edb3bd39e945bce60 e1f5bdd3eb6c2b9315ebc2fc8a2265b6103a68a966992ffc100e00a6bfff91a9 b0fe946f3fd0a6f8005f857f84d96a929971c37caa1b7ec7f8f76781c10f7659 a0f943eaa5354a75121d68f221d7f4fd05820d142c52ba0e613ce40a94ad410a fd4885348d62e21aa70db54056909d38d6a0434958a88bba1b00bde9b5d9a68a 81f0f73e215de76d5d9395ece7e348290fc38c254660d07e5bc1ee3af399c349 6299a39b5110643b1ca175cb95efa2384e6ef5b097e104d538f791b61c934039 7107d2209213b68af9ddf368bc4cb14a7eb4a97c2d12cb016fc4829df353b976 26e8f097cb2958051fab454439aa1dedb6929a218d6ebc0ad71ed240288d5848 03c22c8c6e0d2b2566d02486f8d281d47757cfb55aaddf6e9ce709d0b434bdd3 8f0851c2b5c3ca4878ad6c9b7bc5d0961d2c10181b346bd04024a1c3c01ca783 49ea1b8ca3b5ff382ae05817952efe5b1e492dfad8864520909211db36d9a3a7 4b4077f01a37c8c41d0a841b197f90bd81b0f60e8e85ca241ebcdc75ae7ca7b0 c5094f0a05bfe6bf19b8aa4294ad8ad350c9da12fb2349e19f20fa468a8d767f 28620428aa5d407387a24846a62cfe882bc32222b1e0a11e0878e69142f927c1 469a5d58cda2b621561089a5a84923527f3a7c34d73429b32f12165453fe919c deb95037d7f978e00a400165cdcd21698a9abc5543a86a39c2a3a2a38df0147a ac3a1f62cb0e149eab665764aaed0d534c57bdcdd61badfef5e8fbbff284da4f bb95b6728b9d49af7954d46440c0a38d95f97dc319a6bc801fbbab115a9d227d 51e67336b6a0277b50c6b8c9461b570341de5c545d6ec069133fa52fe0fbe96b bf9ecee1e808820f1733fef3d8b26831fadce90ef25c2c9e69f4ae1583c2ff8d c2ccafa1afd4a0fca65c04cf04372a9949fc82e1cd44d3fb62372c4eef025d49 e6df379d0ae015a6e363eaddabc993ac719fbcbf0c426923cef3ce181bdf91b5 715a8e056a708fcc73e370b8c8189b95be07c48f029aad9d78318bb4211fafc9 33086563a891bd5405a0c4e6c823aa6caa40baae56af2987d0fd5926b7bcf92d f135dfaf3da2b5b44d02fa04f5808eb9d2f98908d5be6084694a0d0f0bef6b6e 86646a742b57067e655ae93ebb181f34b2bf68226725b7fd49b7891c5e8d3c0e 76f0c9c066cdaea4caad46ca803c9aefc3a11dc75aed472479652f6d75f9f593 4d1772db532f9da6aa39d0644867e5ef9c429cd7986f97eea7c253a0e43e8698 57bba026eab4e72dc1a9636f0c63988275e9eb38f66c56b0f6d998fc281f2f0c 628eb7273a6845f9636813f810760b69248603686f21ab695f41304a5259d7ca a83d219f94eaddaf2bbc68d387db7d477f41a6fffd90b307c45342703c987a8e 149807be6e62c586c635336a9cc8e1e12491ff04528da3ccbf4c62dd49014d72 5fced27002f066f6e03292c55c36bc9f4e5be911738f25f889f12d0ab576d690 619142a6d9c825b6b874b1619f723382fb91d1cd94d59814adb195b2df8e2afc 46a9f5f54f2c432884e00bdcf31a1f2832aa3fc08ec5d613e39be20a8e82ace7 1da5ab4a03bb087697f2149715033ecc9fa93f3503c0323f2a4763ee8c8bd51f 481a87a30c3af37b339dc69250c71ca8a922e816667443710671a80dbe52ce92 6f72c0e69adfdaf0dec11ab94da9e9607fe1af9b19d2942499f2f3b06c70ec10 3f27220ae74e591ed12f7a5e53d9899dc3016346747d8ec9fb0d8c6bbb7c2a62 7be4d47e1841078f34a8bceb4a63e3dd7d84a7a15d2180fac6c8cf9409ce02d9 4d781a55176f8de667ae70e9c1bc7cd4fd263930b82f4a4f32ee12957d19b4e1 b5df86e2b91c3dc2f216c0c9ab065ffa1ede0d6ba02fc98df834c77d65b2ee60 448250ef38aa56bbd00f29317b2a48212acd247ea64550dc411ad9b176f129de 90899eabd9f089088d271399c46d2550c63e6b3eee2ca47eb1a1b01220abdbba c3e9bce3229262c0e60a477d16d898464d78d94b5ca4ecb64f769ddf20c5c440 67ca124eedbfd419a80a46588fcda09e2f5fe336b8e69d989c210e613a82e724 f36f0c8aa0d5711221f96dc637e34e8d4cb79166136b77637401449596507b8e 5a7b4baba7c4e9e7b0bf849d2f3734a5b822f30f132d3dd1f262ed9551a2bc58 a528422be9a71e011bb84759bae4421c53e306cd112a78ea9f79f1a2b19b6c17 8a80facacc40636b9445e719bef3a4f732e26fecf9fe9754919ac27b9c53fdee f9cd67c569544c62a0c73392289fb7682d727ffd10e7a79697a4433e06470f8c de9b69ec46282341a42fbbf8de6b54a232ef50cae2ad1d774f3630e60c8eea92 929033db79ef727eb67d6dc4aeea650c01271b3d2a6873afe6e6b0bce5650cba 301ce60b3754afae20c3deb7ca76dc542dcf5e3c37650258e11f666bd9b978e1 b07597015e477302bd1f044c547f7246b74de2e4b069de91314e7023383e891c f6be00b7a0bff65e3d29bee8a690717c412bedad30eeb1b9623dbb7744fb72f6 afefd6e6e0544512a57fd39de6adedbf6d980abc65de3ec99f89ed06315ee378 43dd0a609beb44b6df8459e8dcd769d48e892897872efcdf1783a5a913f5dadb f765aea469de90af8389652bc1cd0aa52fc42e57bb8e546e1618d818128264cb 51e47a387db4adeab17ef6abacc440cea6fc47e00dd448619843ee6aca670536 b2027fd7a8e36de5a752b54332d2449ead5213aebf6c678c54c91e35e6d87fd9 fbc0102c91c3c12182445681f5f123ceebc65bed2d9932afc8a2f6fa78a04b0f 48 c752903af2e755bc1e8858338e2b765c44f9404e4a18fd0f91b3596c9271f406bb75e09fdfd2f4904455c4ea70b054b751fff7136a773d93839d4f02edfbce0e56cadeb1b6f6eb529d8242cfc8994a58337c28d01228a29d31099263f05e8c09b807a97e73e015d71e133b986f5df9282833690c6536db7e7379a747f0b48b0a84e235c633b3331840483b7a8702a6fc3c0fedc43d4ff22e0da1d018d389700ef635d82e8b5f530984a6af95acd2d0d0808d698fe1538a9355b141a9da3b760c8535800cfb9711700786653cec731f1774a04c4a950a6a109db39e2d6510930210e6345da5412f62cf67a775b3d62822e78c32c9cac5cab36f3f30d3edc1d30f00324828b0ef0be92bdaadc599097bfcefc43e4e4c3624ddd7fda7b52a22d70241e3153bf2b6acfa043eb9eaeb98054bf9fee0c0f634c18a3ba9eb34f1279a0bf6bda8447a37ffb5964d43d7dc3746e680f9971147fc988db3a90e80f0a5c10d1ab067fba00d24c912db2a7d9efde5b169130f124c609b2c2994334d9ae6130632dc2b46a184502a09c2968d07ef8dfd6097ef014091ff2ebddea5e3c09efd087a2ddc5cebe7f41f8f54bbd5d26b651291aa5f53a3a825bb8ae21e9a6f78c501fdfc728e3591fabfe66f1f3a00295abec0179d9cdd9e6d875621ee870c14dc041ea89f7056e2344698cf7dc4617f694284d8b6a2d206bf96febbb49438df6c0dac8e19f37e64d0e792713f28e771dc631a01ad06289af2de182282f6a1e89305beba4711b86a82a4ec54ea0fc3226f07c2966cf908c8351ad685228913863900cd07e8f7ca27e1e5c2117bda6be169dc92a392031af88c52811d169ae2137f0d1639c41b4739d4691f8f57d467945b0b1dc7d82459fa678f75debb643b2be20fe216298b5d526c1f74b503514ddb32b4c243c10813339db16eb91c578ed1670db4a9d2e7fa13450b67e317ced5ed3eb4edb3b848985dccd452ab6be85d29c70bdcb1d40b3646753c393d0a93c2dcbe9b05772f3a2b2701c30828c541ebe0a50b54df2180afa9bd2ba0d8925c8dd9f4fc6cf66bc6698cab1d5a522d57f90afc0e250ce977176561b3e909d7a2a2383edc06df64490e39b503d5f6ac44a3778104ba7674715304b05df024969725c024c55f01ef131fb9a0048af416d68cf8130dec17a7afb80bc03912e4b31d2eadc915de1bba343c007b5b5373cc32267ce806dbe00adf2c2b714332b3eb9e9102f20f2aad2f232a9b46d251fac0cedd64bc0764fc6a982a589d68e0a8f787e41335ae22e6a1a5930870ce413ca7cf86d13f05c90b6d8fdbcc74c35a34c24c73b936f918d5ed83b4b7f61794b033a5f5e81a0fe189252508a23582fbb86b071d0de463923eb699fef4e9d7140b4a68787f0f054a4d81f7498be4010ea8514782d16b8a486d0ed80a7948bda0e0273bc14b2403496513885c5417bf007a5f93fbdfba9fa3ecd5a3a871a77670a5ca794d7c950a50d316b3350a4f1f0ca2ffb150fb729c88905dcdc89fdd6a5d13d0f84a8e7e0b94d15f66d5270f4dba5b7e809bbfdb8cdf50e0d61311a1d6e5b5c94f5901a60e9ff691632f0aebd28c989ec35f7e2f4e234f7cb9f2961b6211c5563ea95ed5063e8ef823f742950b2b93107ed3fdca7e259225c1a5d6d8915f2af9da37feae0df0f4a7f3efd4cd358529cb0aca99ae40b8220cd0b14491914a5ec266556bce0d571605481662abed71571f011d6e7c9f31f94bb2a2d48126d8478e0d49ae2004e5559a482a01ae8c1ad0c736969891b07d17a878535c1bdb572bd08b23acd20a88128123843c4db57b52f18c880f3e3983f93df6e1b60548cd65246cffb118095bba492204d33367da8cdea1439d5f5b70376d689f42b1ad7aae4ae71e658a09d2db14fb0473d848dda3980149322d3d0581ef979b723ac8cbeee5ef6e6ef30c99ba14abff111fd533e31dac4efeb7e95a52883e9b2e17dab4765ae77b6eef01e1ff2abbc2bec91e033c5957b53255182492a6e95e4c3705c0c95b4e37eb3b0aa88e306e3e2e25dae952b8302f0ad9a635655884e2edf73735864b0814299f0743a6db7d478219fbf168fe10905c6f868300b7d976c04cde92da5f82318f440bc3fc2328e9c4eb7f4c27994cd45916939c0b4eaf610f1670fad5ed0fde56520f8ba2093199fa7050e6dc397c68a1628ad0526ea89313c4c83a52fc6165934302d82568e965ba51758994554e5ae32169189aa0295d3452487ed949b2eed4c10bf63222b64e8a7662643c115a0ed6abad31df5b8f59ce6d1da8ecf4a7cadc1e0b1a799e0f7c3290e2338c17674a51e150f609de86a99ef91b1006297b4c37f80ca43711dcf7b6180204e14ce0b147753d55047729df62bec151d2cdd24dfc540f14bf6e1bde71d4eeb25ba6d6b652a8f3f9618787cc665be918f1759601720c0ef386e71627c954605269024bcc08dc713edc59ecc568edb6af317cbd9448c30b5329b0c0d950b0e1a59a994aeae062f6385d638ef3af45b9ed1b121cba975105a042b692c82b722cf674ebe787980a4776b150337ece086d26d13a74b04b4205b2003c5819029659d532ab6328924429cfd9432965e9caff62d5daadd2d5ad00b95f6f1284a1a276dfb75791d92cd4dfb75a497a84979a18380d17ac4a4e290691032287351059ebc30a157a7828bc987a271aa2a094be0d6d27e3b5248e9a035e1365092ffdecc6c35b5d6180c32b3f9ee5f98a3b87e0744d598534b5c4980d2320c9b07c0294d8fa323585f7d61f1eef8fe92f027af2687277949222566606305c8ddbcf05bca04a157a9513642789db3dd674f56225569870ee3cbe18e707a4f9a5507aa45f53af37f707bd03bf1ecd90eaf80d59d7d6d7452db69578e20f0caf1c15368b7796c18b5d911a317563b4ba02e0b877e1a94e403301b27c8b01570e149da07f3b5e5e1b3b8af933cfab70d971b15dd5ea2fd804ef0b0762280011765913e60ee2972b05e81fb1a17ecf00ac29c4842ba264ef3703395eb62909f32b5d852a39234cb8a77ef60db93cf564f9a9dd2aa2c736b63f79e8e5508609febb550a2dc63e6901f599a02a43a5256ba9b1e57e56117fbbf3d67a27bc5c0de2e83a44fe167cbffb1903c3ac24649221375a7be3730959c96d66928f907509c00e242ef536f72adb1244230cd0c9111f0464e98a1d8db78005ec45aff6df01ce2e4ed27770c7b1393c05dad6a7196d2adcf18e7f89d819a4e077973fd3030306faddec05a6b0aeae8a196d5407de08c7a65af9b6646b5930168646465516000a81c7cd41620892da603cfb9c5b69a0a5519c0e88d33da4db2fe4f7c8e19d00be28025e2be62a58997d7071cbdd29169b0040f1714ead974dfbb4944abcd40b03ca39e49153973d4b5db8c9086523897bda887fa239c6f0276aaee5a594280215cb987d1a9fe3531256be856c094393222f2ae31239e7c6a57fd751f4fe22045849b5eada89f216fbbd0e70126029a265bf0b1331ff5c9739f5f89d31a07a08d9eb922701ffd0a098ef09ccc4ef2c8672d29432c21bdd9bd1b418ebbcf55509d65d16ea319219082ec9d7313f71c78502da080e78465ad72cf983a8da8cc10b2aadc39e74d5db35b65c5fcf169fc2ec82799f5dafdeeb9edbb234095b3a5b0cacc31fc48e0add8b664bf64a462e21d68e1a7121036af4160c09034676bbe50b1067847250f781adb2cc354ed0e1b16d1a8eb0609f3a5d824d547cc5ba0891008e57232028a283ac84d511918728b20f8b06e0f7f000526ebc2bc92878ede8002f0a3b2c179609a23548130bd942991b2fa4b63ecd135ac04cdb685ca41d50084167a81b3bc3a772eb1e8f55deea9cc055e7acfedaaf7dd5fd31ff7a0fd9bd0425029fe6942d785963d0b7b37045de8598cd19d12be5133162a004f2afcb5e050ffe67939f08ce4bbc9249eff06d402cc814c36ca12a0e7dc8ef95af6b5f4b0ce3ba69f5abea7cc5e74dccbf9cf7bc431ec562dc8d0fb6c36bf6d64fba64c004d0889af8395674f043c732256d1993ab6f861aac75330ef56921449260ab95097a92c1b75cee135ea8d0e63d1a0d5b5121f082f8fc4ffa2308521a584ccb2309541cb395ae243bb1fcd8be306d1e2ec6042ebad97b12126098e52be84fca7509f003888a248256796f038f30c59dfb2133e9f42f6febf4af86dd0e815e73cd067548ce93303cb226edfe90d637d13f06d73f70f5d2f407fd60a45a6e01bf32085a83e9b88fbae058442a96c6843bad1529156b5144cf36f40fba36d5c5e8cb0af59028e1d629b55166c7bfa0fbb65354970ca7eb18ef7053d0e6629a7a75d30a5eb83db2a8852456e8932ca68285f0fbb3297cea2964890d7326cf41dc44500daac69b7d4935c15e3da87eec66585181fb697dad9a510aa07fe9c01ab68d350aa3f7ff59d3188f25f92c0376f26d0d322e7d65038b96b9436aa1b95cc4677503be84e6cd5f01359e5eb862c11ebd8b45cc18872518326b1f9141515b8747f60665015cfca5c04715d9168663a2b190cfcf198b9f43fe0e39b48d9e458502d80b9209bbd3a50c3cbf58d9620b725a249a9c849d0cb8388dcc7f2a90502e5efa0dac0f9eaea95b72a31afef787d38b3d1b12753cd5427a3549f97545918acbc10a81ab5eb0bb841eab9100a7c81028a32c8d3826b836136942234e829ed2212a059e9ebd5f7b37417b4fcbe5c29ad97256d4c8839b18f930e88492ca2c24b59b070460826fcd5185c05edee9740e6c10733a047276de769b55d352d080a7227d05ffdef14076d65e5f51ca1aeca5611f7628714a2be8e482cf9533ef9040fd0e03ce97908629bb2ff05b40da50d3e52729793df7b1af7b80ade2da610e1cd3af0c171b287af79e054a9586ee6dd208c1236c301c7fba9edff173f423187c49f500b0c405ec84e1d116cebe34083e7875a80a3cc273111239dd088a137a3e4166058ef6682eba4ddd344d3a2ef203fa59213ee8931e73faa6d87ce98d19737c76009445ae9f4d31bb8a708127ac42daff428b8479416f7770e26297890b292a9d072e087239be25a2377479481aaf3554cf74850e77afebe01f64edfbe5b9147101aa8afadbf7a7bd80d25b2dde042a67dd45b2b39e99897473e858a41e5ada7b08431fccf2e2545bff71f76b763bbc44014718498a0bb4af8c55d2f63233192e05bae827de253f07ef551c81a3e75db3986e281619696da63b623e29edf998170f069f1c4702977d87d5914e6491d5876af99b0b70c778b53123fbcf92bf10030df768f6b40eaa62f06ac2450e8cfe45d57cacffba3f938c3152c3980fd178650d80532104b9e0f031d0e9fa15d679df8264762bacfd18c6839e77b8349b462f09ccfc92c01f5520694ff846cee53e587870710c32d99e25b2b11fcdcfa096520b1a244add0e6ecf2d69ac0c9f661efcc88b72ff8148e5c4669f8b9c7e6321580bdf1c857c0af522d1c14b86274fdccac009a83ccb0171e449af8451505f80d000eeac91ab84eb89f5827f0081a3ad92f5eeac3176e65d29ab4bc2e061a5305a0422441a8a146fa6da58f08557df4fbcc7d227d5bde237ee5d4fba7baf132cac0e9f5d3db2ec2f5e42776b8d455ec93046ffe391fec70f3c327f09eaefda8799026dbccd6c442d31efb4e47488acdcf8b7cd15c35de959f181a083c0c02b759e07667805be536e47ed617a228dc9a57cc50c1b732ffd44b0d912845ff3835a0608ae492f7981a6ea57c20c310813f675056fde9bb1b96dde014acef3fdd137e20a961766d4410711df70bd5ac52f24138425d77358a3b43aaa5edcad2518dffd0c6bf1394b8432be78275acb5593582872617baffc7aea38dbbba3c9beb4dad7061b2cbc664ac0ec7dadb6b1ba3e234672c8b5ff79f15e2804036a88f2545b70098946bf46e0bbc30c7bf95fc42d4fbc6b0acbf3139086cfb21dbaf85875d78502feed91b22662f5c8740e393e8bbe0bf3d3bbd44bfcb1fa0eb6de4e2780c33706346cded5a4368d68824ca575f98ef74369846de062c0fb855fa1758685758203f3e3604e55eab54d33d3e238d54238a7a3871e6309f0278b62ace6b8b9990408c977b6eeea0310dfd37bd1f3ef165340ec8bc0c962682ec53b66b615f72b16048537d80633ed368d483199d79100c10e1185a79c30afdb47e1d202a25655d004ada330ace94a5640419af934888f83e6a60bc88249d44a791589e41d9cf1170d2066d8dddb16be86c17b64de3276bfed708bd8824ec15408eb4fdb87d5f8a107305ff5d4c21ca34c26dee48f22d06998b03829d6fcea08a1fcdf0750bb2a510fdad8ff1429b48cc4f233422badf7eed7db6f04f32d711e77a4a1a21ff122430dffbe9577805a689770fad814643d398aa5c8f82799a1b45e2d001b8ffd0981004ed12065d46d0c4613844cbff8bee75c592e89f1b3da4383f8ba00ae6d28f60f423488b01fd96996f66590941d325d4fa202b04c3f073f74c441533d16be1606afc3ee9824dada8d7f5b0d27b66d2f300d0396a1834f8f4d5f0f56ce61c4c50a6b12f9a2a4930f9cab4dc40d1976c727f8d785963711a5a7545149fbb7ce5b050ed4f6792acaa88f182a5f6dfbd3fb2c0d565e7ffb3827bf31a03d1ef7f6f900c7a83cb2be7d1c3c3d3bd3d5a4b68fc2d8727796572758fb1c53e082e3b60b0e8e829bc6916e2e31ef802e1228e5b095f9cde3d9cecede8d5c1e846a40e0650811f0d6b1668b97b9fa401a70efd3313e8a86cc47f0a4a6f090d99ed659b6800d7e657486f4aed9e00d05e643df3545855361b5c556f8cc13477f2925c1c8dc0af4c73a0432f416f04c0907b89f5fac84c1ec8cba4f3dfc58617dbcafb512d601d0edcc5898e1124364fd41b1d513dbf5131ea81b7d27fb89e2a69b4b8ba35f0789d53d4a69a43885473a7d194ad09489592b194df1c93dc8419ca0313fbce20ba9d129288ece220a546a28e524a9c19331bee27c73e98873786044d9aa60460bd04e1adc411385b7a0894ef821068143d8cad40ec0cd901b514aee6d9b2fc401b83675f28c36a4b181958e46254059e0df2838f2a2975a18dce87a34ecdd100db72c4dcc5c9e09f7b57b707b91886ebfefb8c938928f8927268d50d61270720b476b046ba1023cad1a2e3b6643e1204a229d82077b5db9299722aed9496a970ca3bbcc18da52f0f56008df59948ffe24f9cb95a132e60a1ed30c4c952134a90fa130f15be236c08f7c612590ebe317bd911d71ab56e27f573eb22b66f3e3500431f87fde1d4b85a9e63dbbae60b8c4979608f669d367f382e523b8dcd1787b0235f9eaed9a352c3f1a95b8423696eea1115865794f0e68c869072c07518c9301187d9143dd7c9abe19ce1ce324fb321ce260e1365603f0a36ab0138d9c40b7035869608a42c31e3fbf9a53a17f3ba787a63dfe964b25fe1a7c242af20d65440d044da61d7b167467676cbc69174fb78c9ef1cb0fe813771ace6ef039fbf7b40cce1cef74723c9db28219cb0f609860e8fd6c0bc4dba65b9208969f6c7e665e0450ed8ea343568a74d063bf7d8d02efc81a840a65595436952ef934a65443fb0a273454e67654237a99c75db85819442ebcb0e01ccf6bb4e7135882c796aff80b1b137e7f2e4e1e17c73fd95e40d8ba75484b5c9293f70e44b0f22c531af1f7036445cda03cf6e253a0179d4392669ff380ca9a632349e04613f5cc1f171e5008bacd84dc144ba4b3951ac8975498dc129f8c76155da3982e8bc1001a07ace3085c7320402035732865dea7630a66ffc43ee7a8ce372fe00a04c3ac557e86950bfc40e4a28a9aa2c83fc323cdfa3100570fe1c811e9cef28229b8c571e7fdb2033c0b580468a97e52a6450c469299870d80fcb8c22051bf15f225fbc254141608f4c0b673da5402d2619cd1e0114fbabf6997a9f111f7dc56482d398cdab907024fced55a0b847be69eff5d491eafcd34f1e29fec721375da9153dd3267ea9d0cafc991254c1f0a3923d5fb8d63e1dfd41ea1fa27c0b3c400335758880c55ae0ae4cd55795145706c3ec04a3bc87eb8e46858fc600cc6415539ae986a60adfd024fd93d63e1f3fc5d32e5bccd21630aa700aee62f7b1863b468e33243a7fe2c0be096261e629dd6a788fbc4b3c2474d444c0e2a3353a3193d8a66c73806abc60f224ae8f031adfbb93fc59d36bff07adc81a53a0bfcaca429584080d8627b4f0cd66dd0556186af14de6c18456c7ed31c4e3cdddec608b3c37cf182bf885e910237f2281ef98c41e0b54120c5cd0a71a6aa89c3a007b02b3165b23ec22d22c5032d0a64fa68b4d7f79d927e10c056a5762ce492817547594a8b12c81ffdcb3408a0ce9459ae1f59f6ceeaf05d5907accffcb926b8bd89fa082bb2a0636ab6f20dfc7b22627300cd52fab7f48bf5ec2ec66a97ddce816bacccc21cca27fb26fe03bd234330960b687fefe0fec7d80cd0f3a2ed84c61825ef3f7816768797aa7a021c76b6c42ea236fd4c50d80b4254f472079bf1009cfb106b10b69b79480beb03572ce46761b729efef9374690df2c6d274d74b122bb8aaf2c8653cb1cdc3b4045369edb043d9a4b9f21dd2625de372c74d21395df7753e97f910459e6064d20021216ac20a1dfb58a0e3abb7db16dd001609ba833ff20f63ca6aa0fe221db305cde31f51fe24c0d049045dfe7669216576a9a1fa9e5a266093264c39dcacaa0a5bff93c4fe782c44149171f03b3265f9011bff9888081b8537baa41b436c180f21532ef05670c2ab267367369443630c67a61ebceda6534ad52e06e2a5dd560215db5849fe97ebc71214e896d017ffc327593fa538cfd85a80fef032ee8e7d09009f066ce7993dac042d11fe630da9b36a570bd13c7a9069ea3f8da33fa4a50fc1e5c215d8ef5a08c1c3f7bcb3604a86062f52792f71e17b6df3f95b116bc60fe793674c39e9613e6fd530678decc35f6bd0c534ea90eb024826086e8be69005e26970fe98f04dda93d17ffd17af637a780d44a0d414aeee146b7cc03ff14f06235146d4d9fe85cff4442743bb3bcbde3e313caf7c6fe38f496411e1ec9b2009b28c043af665bb91f4d67c0a23a55ed28cacc344b57c7b93f1f3220592b07e08282790a2f4d4da49d5f393dc6374f3de747d6764d066a401be349994bf99c90a18a739574b1ab0727fd79a09e11e33e5b1c53eaa17c97965dcd5078b9ddb2a0bb380cd9faf8e2e5fbfaa036dab63b132d5618efce5bd8d8738b313dd91086006a809d52e85800e9f098afce1955ddb561ee71e4e966789b8de8ca46921b41a0e80095d88ca7b7957825e7d0a5313f383f9b0168e675f6767dd9cde055576190202db994c851ea2a5e7f5b05dff3828b994a6fda52928ed1e1709506a4762280d983941fee08ccfee9da56404c73cef174a122c468aa7277f31cbcf20170bf70e278d9a40eb8866d7a554bb65465bd77a75d61bd5b038068dbe36283096ba4304a99342bd100c5100c958ab9b986c6a5eb926dfc30dfc7e4afa8ea4d1a5b3850e6e0cb85aaa97374ef0ac6b863ca699040520edb93fd26f3e1e2d5e9153ef4605210a626d5a6d87e27e76de71b1b6795439e020dfe0e1318dffa1f912f6e9490fbcc0a3c3715a06e43a70da3a46511212fc94f32e9224697df4bfd023f334110388d86bbd40fa09a1c0ea819a617a294f6d7234ff959fe6e4b6f34b85d02da709375a67fe558ffe4340d5a44606fd206a287e2812abf1f30aee96d3940d0f9c02dc044eb15670fbad317a2801a38ae9b572c31f5409ef67f20955dd747fd021059403b3417ca0b6fe1d6656848dd23be31e945a4fc864d3064151bcfcd4df5f02e8b7519886fc6d990d08f923e712d3e971f590ea0cda3d4194fab45012c4cf06fb090b6b6bbebd887782d56cdf7e92f6a42bc8defaef6a7879594e1b4b9d1f06deb368ed5576ab75ed61eb9ba4927195c683184c9bf52cd4704ef11c31fd7b073cb1148f263d70d0c20c79b624de1696b13376badc92eaa859e8b59aca7fd6067d6a310064c6369df31ef634bb0832d1655a5cc7d8b4def43d7670148bf05f030248b0c189466b497d6474f421317b520d5bab86af02733210a0293d5dad20089e4fe71dcb644146747adf422d8f279d2508dd1781909ae042799798d3c7db004667384b154f3891ca8a155e41837ad53088b0ff8e9e8e63b7a00a5ec26c910dd7e213093cb5f9d65578a11e909f26d9c21108da3b07fba09ed7b57d69f34a0b5a56ebcc650f624477c4994ac53b9e328394265e72b612184be8bdd57fbb7c092c15c3622ee553b32696b78fd789ae40f50bfdaed583c129b7cd5d098a3f6f01e1a6e1272ad7e47a2f9253a313655b409bd9182992010f5454f20b07014ede016d4bfd954dc5e98462bc560e4233b71a35cda8bb502ef582e09971389375720c3c730af280c9c3d1ca4f960240dd1424b1ff29b82363a6d81d93c4561e69d00cb32b005ae3800f2e90b1495dbb31b609d784928d1ca9a1817ad515d640651e020404da4123c876e291a61012a3d7fcc4b3c257ed1c3c36e368a7316b6fff840ba7526f19dee288d1fabd20a86e426c1b94812f1501dae2e3143e5a723b7a59068f42717f3c53bb509822a200c026caddda75b5f45611ae0427c68f0883063c021a084c394fe33e5fbf73c3eb4d7ede5137fd1a3dceacde6f049ea2826b7b2f09567db7f518aaf8a1190cfe2207175fd6b475bacb7e7e27c851c9e7f9d702b20fc934bb7992540f75d7e5f43d9a48a0ed0f554ccf4e86f5f9cc3f92b8d725e405dd47a0129226965b6c127007718e78366d1c19d3d7fa4e9afdeed5ba822ec90cae5faa72a5f69a6d360970d76ac37fc458cad791278ef874208ed91ff4c2c50c8897b25d9ccfc208245cd5b4e0f428f5e49d8286c2f862ecc2674cbae2a29903152a389262076882bb2a227ed5a3a14a7e09d9a291da498cd7e8295c77b66c022d2319a3354c453ec3ed86413fb267e2b8cd3ea7b9c69a898423544537e20800e48e8f72b7e7ce02aac099db89fd629e0bfd312d1b06eefe3a15648654ffc20c74513478a8ab14e76eae374162da10679c907f482fa4a9bb1714921a457039020a651493e796719ce61bdc19eb2ee5968655dd6698919e169f595f76296d4001d8307bce3b2abe36c4b630eb7e21a4c3c47e3dfa8dbc82d2c10288aa750be10ce9e247e5037c4c21893db408c5daf1026cba8012c8a717f4ba6346bc58dfe102fd2dc28e50207139418c6171f130aca3aaad5069b2de5ee91cae621bdbe1a60dab4c22fa1ba8353c9bdbd2987b021b55a97e45a52f7c391849d8387459dfcc01424fe127902932560127aa7b853a31bcc3148aa9686dd54a6781be7e92744209d337f929a0a5e66083bc5739f56537663a0311163eb1a6be7b81f1681dad45006ce86e013b66909e5be7f487f0d249e70a8e272dd4ff2b25e473ee8cb7596402b4b2cc077fef5bec3c816552f8651ad1f29196b6ba7fe202cb4c43d5055d4209482c2b19d03b179f9a40fbab0f364ade937c47375151805bc2bcead236c8cd0681d6a8285e4e88864975b358c4164c2ef6da9d4441444ee25e2d23da9847820ccd4dcb064d69c5bcbcf23b5823c423f0f8a4f97ce2405705e848dbd67dfd1d0f9d79542127e6cafa454b807db865c810fb6734248ef1d12d7fe79495b5be7602d901b23f20ebb0b997fd22d581c28c92207b56966f84f8560b8a2f2188b7db063c903fc578c2e36f6ea58399153575961df232839b30ec1ec2d9327b5a91a80f255bc0e671d85a3edc916009e94a362ad8f57fb9d9e8039a53ef7e6033ba9407685dee8de695a409352bb98e09958c0a78728732884f4503c891a7ba224c6d0a488425e05265d745f55c30dd2a67ffd410a9ff3b4ecf38f422f8faf9fbc6ab0413d489af4a20a553f0fd9ad69cac2d09f21eb74256a90d4061d6f4d33468ee007491c9201545b58dbf7c6e630790946c1b5fbe127f36982e081052a1e0f54c0c52facab270b821cdae76c49715bddf5a1bc27f9ba3f3370c838f0cd280807f003496f81b9171ac3672158e9cb9cc23a03a260f2482538e7c243063a4bacb3f00f364faf3ff9410c8f88a1ba981a37d17595fdbd2a965907aa91269b58f933d01ec2726f38973aa54247d11781a0f34b4cd893fb278c2a98c37515b8fcb74990dfa86a9ccd268422c4acadd62909f11f49f9dc60ae24f97d511a80e7040aa7502f1eff2615252a09a5310cec8afe79c35074e8d8c425cb509041bb165edaa9a0bb48adbd37cdb77846747a84e3566fa5cf06354a9cf189b20ed289bc3edff2f041e8e0ac5d81f24bfebd536b90432c4ad2e4e275fa9f8167289796208be628204dbbf38ec58cd78baae7943acb57b843ed0af82ddf40ed88edcd569074256d00f4b1103b503d8e33a13754eaf9e133282c737fdf59b0584b6ae7741424a3626029b705618d345d6caa6c85f3905d8e0b786cb40fd5df8c7fac652487fd88bd40053647419e772f38176af89a43482a0f7ea57300b047581b22600e1c7d960bd0b530bfc4bb4fc0c999e6c01b60bb9db93d813fe69472e06e6d4d30229f761650d37b1a08ff1d6b06cc3e30ec9b712b15a85b0d403c2f67f2d185159c87abb0d0577071d668fc7458d0b9c87b893eb000b5e36b4a8897878f59afd3c718db6b60838abe11728c29fe9ca7438b5ccf8db1cf472a7437bf3bf7156f033cd238b7206e428b653399946d64fe8253298e0bb825ab9420b91bd6fa03a2e05f3fcc4bd09621d40ab275f971b3d559ba4b7f6d9a41ee00652e63d0e1a55aac6fc5f454d0de9fa69b91333924270d2403b42b3cd6c4f2ea20a5e895b46152b2d6c463bd60d903d692db29fa7ef438a8921d05b1ca38a650e3bd91a78ed66c96de3176cb60daa8b9ccc2953e59aec1925d9f51e1671fb6c40454d0e3d1c4e122849be16920ee7b9e5b541643b577a83788b74161bf9909ed6e72f767925aef9e07826e7b7003a100c97416d39ff3465a92b4582c3050f3988756c80160b7efc697f1da042021334bba7df3a859af711978d365c0b03cd8e5eb8a92bfc52f0c5cc931306370038d5ac79d9b0357de65b1789113d65b1f53a30241fd4397fd32e16f3031c590a3a3c94c75758f19b9dfc25851d148413316d822eac18fd698dd2887e5cfc6e064ea07a82c35b7d5b30bff932fa089105e8e4b1cfc41f4653bdb5d992404c70050922af0d0f735a179e92d39d3422c6f8b4ce3c8aa1f99bf320c1960a38cf840901f26a631433301d1f2c8aff8907fb860a3326b8ffc816d3a71af8f7ba93dd024d573c49e9b0fffe2468e5f410e84582dd360d4ec50e29955121db4844389c075198aa1fb3b8dc7a43fbb1eb9811dfaa344f1eaf21d2e037b3769675562ae00899064076cdebf34fef46ceceadef79acfe34b1b170282d8f26208d84f125f70c722bb047814ed3f2d07d748f112a8e085290e21d1e56e809f330717b0e7bee09827991a35d04dcc9bab009da86c1c3a3b98d237771ade3a79d7bebca3678f80bbba4ce3e2a349bb6c9735235fe88658426c46b464ab5db2a70783287b2fc7307390d9ef9cfeaf1732aa297de775f22ed56c4e8547e66f55617654716a652fe0d066306458d6aaacdad6c9d0c9e91986e4022bb310dce8d3e3d649915556f63042f0bdcdb49f62fb0be06df83aafd3cce1288caac6d471ab3b2fd14e40b947207cba62596b423d7839292f383b1c6b32cfeedd33e83095213c466e48836f12c036d26e1f407494b9a28c887e351fde02141bd93355ecc9a35e8485b3358c8c50757b56d582157cac6bbe507956b8a249519adafcc9249153489e9664094122d08554e98cd6b0a0c236126c8b30430522e94268d57b92d19e0f1626eaeb88f180c47381f988477ee7ebf4fe78b56c6b44053cd10ae8c0fff2cb462396a5832a403a701da48f0b1c8ae3120e35f13973e9ba93ef1be1fc2138ba0fa60d8b3db6f0ce006234c894491cda1992b85219f7c44ff7f9f8170b49effa4dc8f3d2f200308b06d8c6e9517ebae3318113e8ea894b19b73c1ea3c5a73db5af999a012651f008fd4cae064b076b0bbbd04f501e8e2afd6ac0b7308aadd18b37cb86d04e1b606c8cb1d27040522b195d3718cfc9fc81acdb4f0390db61f2ae62a852b84b6db0bdf29c7cf92449afe6854fa0f2a9bfcd27daa41f061d881ec0dcda6bca5136c01a2407deb420b56f4a5e299c116ad6b28abfcf7b1b93a6dfc7146a29665a89b0268993a701d4bfe97ac264fd4c8c1fbf5b08520e801bd433ee3291868d40bad07fb00f5fc513485c6fb7867dfb34d5bce47cffa3c890223a8589ab8a104d90b06adba2d7e86265e0b9ab00a26ccf55616c92d0fac50a241fb8f09c3707955be08ca9c589e532b2bf928bd54268149f09c210431b1c719fcf2785517d86348da0103ec98a9944b92546f4ee0d4982c8356b4c58d72086f60438d8615db634dd80bff4209c07add031c5ef00e238c17e36717cc636c787c6ce609946ce21f62530f9ca43317fb531c1c050654cf901aab3bab440b05a50acdb96013038bd2cb5b032c75b8cefb1ed5a28c989efcf0c8fd2d27900c17bb3bc87770d1132a1f74b80c4b691bad4d3e2e165d35e9e53b8ceb891ad903f030777b484ea7cfaf0a18ed0a510e1f7b2c3dd46bd292d29127ad191466cd0f3595ff9a0979bd4af445cc7a0d4d9411617c2bc0efcf025c13386eb7c0167bd90f5c6e1dfcef9c3a028888970786be01ad670910470c4537a05b25d5fae80f1e8e5fd544fc151f79babdf43f0f6f20db2885a2eb017bebc02a2080e25655ce8d63caaca184a6cde01c9273d00e34c7783cad2a21f57cd423393a587df3f7ae9a191b7fd3998c2859723ca428073439f8b6ef77f7f3e6bc894712e595595c6a9362b9fb159151310237e8c2a80a771bea5352efcb34d37f9cc378d71061d605239be13d53aefdf15eec2101950d60a78109c64c8ad13096d074d9e8c571e374d456e638fb31c700ab64d7fba305c85d95cfbb18f2e364027a26b24d013209a0ed549a74083f0ac2128b4be294051675448af081286cc57f185def44fa5cc92518bcf26240b6623de279d1575f0f7d2ad23dc8bf69b7f3e13fc28b8a497f51eec09f311dd0521e4f33b722e1bc0025800a3fc6ab930d32aa4b4dd7c514425143f3690781eef513557d1058c2f0055693aaa2ffe77332bde0a50c175324047770da0243d87015667a58d48fbfa403c5004f7e538fe639bb0cca21f3ac21b63194bdd7a991b8697d02ae3de88acc0bdf021483c58dbc328c607c474eb638b234768e9c6092cc5b44c4b6b41a99fa0bea35e53be5f1f925dc09b520037a14b4d85fb163f59a8e3a9217c16b8edd0509887df1fcf3c6d2d2569702be90958c8a5f2cb2e8d5e177a48ae46a1026088709aa3aa5aa0e8f8b9bd41aec8ea33bf0de416b91a6833c9e6794840aa2d59fbe071ae86a3e884002f7ca2480f2ccd0c8d1a50343a61eeb649f30f79c2a5039fb0f4ea7bd1f1b633cdb06df788387ee870b2747bb74405fce0e7e43bc89a432b800f3ff885a43f2898ff2e9dac151ecc8e1fef69fc3357ed8af8f5594064e3dd20cf888a2239fe4b31c5d835d6729716171924a171ebab8d6edf94afeddd700c403626e5d6150848529423071b15abd0b642746d5946de05a0db3142ce6683dea037e454e9814b67280ced1cfac9c2ba145a600bafff7fb96cee795ad5e910f3a0aafb5b426bf0faeba4baf5d625d0095e3f5844694129c43fae7724afdd84ac00f10c9bf35aa1feeca09ca43787593efc6f3e9ecce378e084a7359c564b1a66b0c23f83f0d4567d5d6feb806bc689f9e105a4a501b5f2db7fba02eb37a435c76042397c92ea3c0a60b596766eff99eb82a83fb0543ee2ac766c6680aed4808c90bda954de7e4b897cf7d937b2226ce78f5fe6486ea9dd0ff7c66cb6060cf638d0bf3157b43ecbe6a28cb8397f62bb861a605b168bd4722da0490d4f0bc31aafe02d67bfd2cea74e01500943382551189d50f0c15039545e24b7d8a5305e5fe530efd5f7a275dd7a474642724cd319a5aa33ffe0e5924900d66edba8b86cb0a1803a96c79efa689232d28c83364226cd8fd14db16792c9968f8632b8530b87f030b2e7185fae3a4219f0e552585c5a74542b8c41ac2c5a34e4fa3d19dd5c8288d0ee06f56d6f72ec343ef5de521d8e75f2aaee739e5b56ba3e6d9a89b37fb9e800a27335dcd593839163840cd451c94383eb1b7779dca10cda136387e5768570c0ea0c6242630b25dae727ced70f35e9385f6f78aaf65743d4c0aea6045bd59b004bc76261c573629f23e889f4be4c50c2dd6bd42e8e5b34f5ef5938203ad28a10b80706883cff45a206d00a9ab21a3b784fcc4517753ae2f1e2fb1a364ed33d10d6b99dbd07000bb490d08039c7d3a0dbb9763a4158cea2cd7c5eb24bb57570f0163a7f01a9534bff3d6c9fa1e4c82c4440277a9ba25adf7f6c9260be16247790cb65d629c89757a353935c999c51fd8461e44ceab8495d75504a54c71d09d1f00097fd82a0d9b3b115759d1f0fd76ec9d452779316ca09c158418be280154710968597ac3fa1f7d8dbeb521691d9b993f7d70aef2b1d06a48cd20fb8c57d60904d853824dce3011bfbc07878aff4dddd8d6c0c6462287aa2cd128821a547c4e0ee3cc7b6f4c629f06d532df3cbf76ef4612158f3e19d1c9db7a1ca6a32aef3209f1d3cdd52aca595d2b9e54b5eaf58ea97cdb1ecaa2b22270a7127ffd96163805801ad6ddc2346f146ff99d4d160f0cf8f933c715263c69387c695b28aa6ee2043a0b4239df708840080ad08e5ae177340fcf91420a1f0f6a8195f3b2fcc79f064de6b2503105c98a69b64b512b3e2e4179af1ace089f135d7cf06c5424e34f0fc8c67d10648589fb37c31e151b18bb121dc40cea2abc88e21cf512a411f46105083599f08f8ade88564cea215ac27f4592a556cde38d407972baa5d8e21f5a0df73e2d0943a79640b004d6eb1b29072106613d4ba8b5af8c10af96ad2059f4027bb5be10aa600b16b77c8628db747cd898a11f017f9badbf8db345323a67f20a6bc8d24ce2480a8469ae192b12da5efcf79eb97ebb627ba0e69c35371d0be40b03d2a10d9d91829b145797b42a9b4fabdb6623ac2e2d1faed5b48ffc8964a6021b2ed8a0bf6d39a217bc47e2ec052639b96529ca89891a0b0977417d0d0bfb02b0372195543e6be33359528cee86f5738ca51db216599280a8d81cb54a5be80031343edc6af0c80fe21e32907c8350e166cf0ec7611c58beb253e231d88d7c0930b87e9bf63dc74c60fbfb75566b9a56cdcaf12fa2bd2fd2c03ab3925b31b50e633377272ac262eb63ca1d9d5bd3f5e455d4752db11ccca6ce28e153b75c2b0fbb8be1083ed1d220c92ddc2be37f8706f8231cd194df98033fcfd64ad59565082c286bd5ac7fcd1712fc5357e05cc0508e4f9f24a810931bd6e7e4ca8b7225044b21a47649e3db8c415c7dc82c3e601f1faa3af3789b3e9a71c7a72a01425f0eaa520a6b751a71d5f0ff7f0287a9522f6471faa5abf93570d09e65b7d1782806d8160db43c7fbb5af25b04ed2fe7746fecca5eedecd66b51ecfed54f62852b0a9b84960fe643835c6918c0744a248f8cd9551f712021d6af55ce62135e314a003127543a4bf2fb4a74afc81a30744a9f4b72eabe45652970c11379c995023203bda96f2936c21fcb7ebeacd50a4a0427f2bbdd8f0724260f59e2460ac9f31c0e879cc29ec9da960488c964a8e28ab4a0484d8110137ccd30832a9644f8a3a8080bdad28be182a714fb0f8a13fbe7e200826e44899d10e9c4193d3192d605be03edbb18fde21d8f7ee69dae1ce5aae5949451c0f5efafa900a28959cb7bf2c00df4decbc27fcbc9fc884a7e33c33d2e999fd6c25c111fe0fa1ad6464315276a0488e1e906792f06cf78dbfab354541314abab22aa4af14d49320f196bf1dcca0255fd42b86bd8faa279e0519ac64ac3408c7cec0edabd83683e56c86b27a5d40f190e001ffe97fe14bf9a5bc97c41e3017e755fc12db568733717b3c85fe2ec06793e60045a0e7c7336eba35db6e1597ec5809ade6e1a043bad9713c20f549b04e38197c186524f08eee4faf1d1e8968c4a6c5ed4b2c87a178e64e496d77f440855b2967846296961ff4d19da5b4d269a2fbd52060ca13cfaf5618ee600b1ea08c6718b761eca00d1bc84320e14d81371112ef60045ed6eeee7e0515dea378e0db75ccf8176aa75c7ec237d3ae4004ca8defdc7641bc924dcd33bd128755165067a1d6023910b36a406af67ebf2d25a3dc821d23e6ef63c6a012a6cb83408b409fb851cd56a21494805c54cf6b839eb7b4be17334385ee614a90876d4dbd84e03f3e23ffe0d26aef43be2d0b475f864df3c2cd9e291b279728d3bd2a6970a6c00c9089ae1c90f5d9b8f66281e981c67c69f915e3c24d45dc0b05106042e07130690bff522ba91492aa07256ccbcd8b880d86424dacba5b69fa8dc403c1c527b0b417bfae5d56cace665919661ea0211a4cdcb8b823442c7cc207f09642dcf4b08 -generate_ring_signature c9ab4560e364fa2cbf7ec6e3aa25251bcaf2beb043ccacb0a4624058fd88d86a 5d6b8e078641aea54474ec65784fccb1e95d3a0f6c1b97005d6fb65077c145ac 3 56d63e1b1a487fd4d7975e66dc212e3ba4180fcbc6ba777bda12c4a957f359d1 0ba8218820fc5a47b7449974d27f4cf1fd7ba6698f087a6b007a15637c8c56ca eec4a9fdb41c38be9bbb62e86f0d497b8adef1c297306cc3a209a700f1c76981 461bd2cc07b9c8310b74820b6b7fafb962605dc168cdb11be6995b344bf95305 1 7056d61edf517715249d71f2d06b2695a3bea07d84401b27fc22e5ea35afd0035c73b2a96346cd8e12ea502d2de1010afe37a84921aac4c95ea197437e7f8d03e83eb0b5d2e7e2cc5f971b125893b998efad29de246d1afb0fbe4b698d6c7f0e56480a3f8de3d84082b9cd157965afe3c3a0ca6a3c8c2de283102e19ad31910c82985bbf27f70f84b65eaf1102477ed4b93db467f23e91e982b7dbb80fb3470ebeed00c63713327f01cf4118e067f6e8da3812b2426f37a8aec32f9e059d8b0d -generate_ring_signature f075672344407c2c73e656aab50a5308cde472718afb873c3813cd31eb083a22 725e94903757033d3ebc8b23440f0c208e60f8932872536ed80050f0ce714156 1 ac769e6e63bf28b0e214931c70c958bdfcb8b7e662f280fe1699e9570b3e4df9 34a4a033910e6aee4adaf7aa902b9bffaf1ec93c9949bd358485f59c45538306 0 d497a27dd0187186d3b5985b14eae557f19b1981f50cdd9410b803dd226a75084be605f6783cb961a6a8f1292452406a862142e5367671bf176c9b136a9a200e -generate_ring_signature b5c9ef14b9a08e78925da00b25dbfc501c26ecafbfd1710539c0ebf3f0c4fbd6 bfc8153ee1fa82bc2a51d1e74adb672f8354f3e11591ffa0253c4a3a7843d759 42 3cd53e438e8c719ef4087516c7124def7dd74122134893d56fc52917f9ee9b38 f2e4139786fbd913a4f13e19d484bf62929447b8afc84612094b0f5bd043df10 5fdc376b219fe822837a4ad8c483f1f392a1cd70141368a20b0d47ad9fe1e009 727d639f4fd6588673837ba332ad5c0ccfd832155dc7e194dfa9a8aac128869d c98ec078ac512c8be32d11374bed3fd019d46dbfab909f65b47052a0b36a20db 272da4cf42e06b9645cba73ecbef4c57b64b99e481cf3a1867ee7c971364904f dfe696e5068344bf3f7994528217694b8b3d359eb52a362423ab2dd23aa0ca5b a2b507f5f68b776722b35012a49fa542f58eb1f6f5a4f2b03ea507e306dcda46 4235b88c24272d62ebfb9b75e6af06479fdac9f26ee03560b53e33d48a820c78 74f869ecf9de6d2b0835ed98600e6c24794e549725eb338f0243025d9945c008 daac00d7a944c053a2e423047c1ae410cf73d0b3e3a0c57072016552cf940313 a6fdb201cf3f7b8aaee0409bc5098d0fbb791e4da2e87846e69c0387ee917048 c556403a2899b4a1288c81e6f4e7f1d2b8adc7e1baacb2272f87407a5987ce4c f9f08e37a0c25ecf700e25fc7107c9bd008931cf9fdc39c454bdc4a8f66b716e f2c59ddd77f72881f42cea3a1a1053f9b4e4723e20e65a1874fbaceb9fced0be e7ea591828e31b78bc7634275bc73436b23dc1eaeafb86775428e5c0a10cfd39 7c15e3d04367d0638758a8c9ab73eabbcd356909c04377d9c3008e70e1ed0eee 3bde3e1aeb47353edb3a007ac3fb658471f6b3c33a67b8224534301d41d55769 8b778667d673944e41147d049effd5e9197f6943b65d8bc47e251c7d66e614a2 a566e5cb64d80f5eb09d5d8fb0c7bd67fa50b2847b7594a6817c94a2d2cfac40 44d95857ad4b5254b378db5d6f5de3aa0c866e0eba2757695e5b955a71ad425b f95a8c8f71f794894ead92d7a8343b7f92c2902376c1ae65891b425d7beda62a 29ec148b76bad44d003a3e53c1cde766fa9918b011696402b0b5546f6cc98c82 2321dee77fd3f088ff04ef45e65fe6baf7cc57a2e8d5887efde37d4e5dd5940d b094fa11e71f396fd2c5efa723ae3b86784d3b4a3ca28c454807c379fd36d8e2 62b4e2eb263e0af951102eb0db0ac934087876431fb5169f04e3033ed66473c2 3043bd14d14c669e87fa0c47de6b5253e1c9b660a200b528d5d008dc6372ec28 81837f200ac02a8ff2949baf7e2046dd41475237d01dbf8a7ba05435d4f56542 b374ce8d68abd8d30d806eeb3133692abff1cc03ce765f4d2189f420792d0fa2 8aa45f186737fc070eae52127397db1c1d921b3716233a76538ef4cf8d98b006 094a03faca408ec2ef2422d1e8e93ea9ebd15ed6793f909327515725fd245d8b ddb31f1ca2d6a32e1d6ce1e3c7935d2afdf32bc00b185ed92832441705af8ca5 cf9923a125eb3d3c6a27bc8abb15c9a1f5ecd97d6bfd4101395c547c92f53b62 70b0954b770448de581288b0c28ef89c95ba5bc78d70302f1b3f8befda378e63 f32f02453664f8af919094f4d8ddfa34781c83f4e8b8e76bbbdda82120444532 a1c063c2be3b23be7ce11920ad588cff49f0be61f4cf1d86961ad990e0d74af4 c9ccbb04e610a9d99373863ff6334908a4218f3a27fbd9e97b76d5a1db666609 7352167d50a292ad64b7c1911ff0d3245ea58be061baae00519af17ec81f1cea 7340ce3795cbaeeef9586e1be8bb45d0e11835db89cb991b1b9042dccca58de0 8486d053b5274d48b7174efe4246d6e0ce405a90d0101558f9ff98fb0f1f684c bdbba1f4e3c95f849d2cada4a88daba5965c9b1707e3b963cb130bf9ecbad8bc d077d77756520959c488b842f761257f35fcd5190e86c4676a4a44d6ce2c6bec 553cc6b8ef0b6b67e23e2a5474a2c74b954bbea6e8e8e8c6e1fabbf5ae4e3e0f 10 4df8d42fa575ef8d2f8791c00868d126a13611e2e723f2de9e0a65c52938ff04a54f81690e76e29f41c629d02cea978cd1bb318813524db6cfff08f25592da08cba6f9bc070fc52f371cb4a7cefe0cc2eabc0f59a26faf80c2592adeaa367b0648693b7d5f23623a820c98d527a2d6e911251d0f23f8ca8eab944be874211b0eda6b16811b36552a25c4d3ce5d12b537959c985fcc0ef435d3aa66994bd2890d0b24d1956a2c2997acb633018f38a362c53418701d2ce92bee50666636b0f30607dc1a48d7396d8ca51b6b07ddc35ef2627c8c5231f3faf6e7db34dcba78ff095ac35abefc2b33edf1608cca98631634a04914d296b8b74aafa442a1a0e38f0168a90b49c74f9b03b4b08bac28e985c0f121ad175932f202ee027c63e842180be407571b4db2ab7ef165e33a4b6afb1a77dc042482d734009d47d629ea4705058c4f2ba79c3bb3f7c2c4ee3c22ee979ac8ff1c66787f0e58ae14cdb11b3bd00abce3d258e999ada5e2bf72b551299749ccc8540172a38456c8793d59f1b85e0bca5cdfb40573b257d12ba020402ec3af7ffa5a0152af83b45142ce727c3d590929dd1d4ca76f258364c46150c8f8301512afb6fec95af1336f74a7537b3ce00078f5f36ee6d02c65ee966c0e8d06b263c044a59ee0bc5bcd3e46cfbbb4fd2004fb934520cffb00d5bfd389fefd5a6af9d0e4695f30ed4a0f77911f2e2d7ec10bd085647604450989480445bbe222d8bcd0fb84d01a20b328dfe8c1363ac6e40dc3165b4057e621d42108cd35d1ef1bda1b5c82e925d4e61ed8bf5bca2b096102a7ceff744a1bfcaa750927065654f105433516f6b533592fe90ebe34b78ecd014a665f54e3189b24de6c2c8d2231840d0606e4e75ec0e961255c7ec554c9fa0dff4ea2a6b6604f63591aee139617b86136038edbb3df02aa79d9f2a8d0a43303212281cda7610d9a348de7d4263f9f2768f1551cbd77fa720a7273bf57a94b0a19ea5b978602cd52803ce2b66f8d2e530746b57a35da4bcd96c2fe88be7b33041208a6445854ff23897751f4fda6172098d872b46f62e0df23f1ff933b832f036481068286e50a28ebf24f5e47da0f9b1bbb51f8ad7975111170cc24c89ef806aba96b08d4a274ab16fbfa4a1528d72b6a9b9e20c58ab2783d8103247295030ac0a4ca63103c146df9615277392c6379012f692bc957a015200f6ab669cd630ac7c0500b67dcdc9a8f62bf2b64197f394eab6cc01d8d68d9de76d82defc3a80c5655dac9e556f3a009212cf0204f244bb35d8d61eb56fc33896ab75d1d2d7e0b7c02a8d08b6716fc5e5e19feaa2c9c2d9d5fdce6041c583236d5cbe8e4a40e05911219b6e21efc65e1c950c350c98867e7c329342996d7398c9036b4a0f56502bead90b8dc0bf3e88e8071f10f4112f319905256b9b0d9c2c68acb731493fb04fc4101d6af21735c3f6c9de0c653e362e48dcbd6e5e27438bd4d3ebf4e44bd05ab7e5dc585a1878c5d0882e759848c97be87da85be3efec25c9a7f304d010c07b21bb74d5216f6351a72c666d4feec708fdaa4c77360fd160502b115ef06d20e17513476aea0368a9e6eb863d2ded816a01894a511d33f22ba5c2addead5300f184c4414172e0ad247f7ff57aad66ca351daff60e2c4e13f5e4c8403c4b3b3085f0ff40145530ac4343b5b13e3ccd47b1ae9f645f90ce0909ed7e37ce5d1180bcc41fc4a0740962f5b45b6761c1d2fa05d5be6b8c0816c1c3383f26f02c5e309fe9b3e311ffcbffaa381c08e3f8bcd6d130c58c0730f56e9dc7293f9e2a859057c3ceb3e812822f8aee6f9acd2c34809c5fec7b9e6ebb0331f012ac29dffb00492741e3aa236116a98e25be43effa716ac850021cc5be6339903591dd2ff670d00bf17525fdd4967a0db619773e0370aebaac15d1651cfa3a3c2d76139fffa073b68318850b8169be86170f9e59c37627cae33bb6595f510e5bd0fe525ae1204c15b89fd37b1f7fc89a190623386712363f3e96b39d108bda90da8458d32cb09415f6d0d4c3279947ac5e45d105ad712b45301a100fbc1e8287a07fd782b720440971b8897de518bd40765e5540bb8a82a6232ff7e9c63624748756e491f7e024b4100a5c9754df4d1f52992b7529db545b03444332b5b3b4afe384919c64608e04f6defc8b34bbdf283b3b7b9b1e8642b9de2c4d9498a068094ba6563d89007863de6d863feaf14d71405610fda0d21a05f5e1ec6edeac4d4a742e73794fb0a585fb55e3f8e2ccd0438b86b4843b7ad6a9d39591e219087541448fe15a1f10e3efcac14b790cb60628a1be3b9a63ea4ea98673f2b5145a0390e0a73f1cd6e081034fd0e787ff0d5f2e0b55f19c0bbf333886509ba577a5d13101f70bda15a0ee60d1589ecc0818fc9c00e67b35e306fdf237637461c91f69e05f694052d5e04ecac599c8a07ace93cef69d604849bd621259e1ab16ebaa2d26a7c8a9441900e46c36e14a31de227253abf35f826a1b0772ce60d98a9758d000a7f8a94026e03949af06d2528a82d7ce9f9153ee0d03dde08c8f4d532f9cd3804c5eca63eda0a149ce7afc28ab4ca5c7b0ec53597dd311f1e507de2c86c7f4cc47ae22270b401ceb4e7b4a7dc92120bbd5f18864578c3179c607212bfeb7b258836d81b342d04ba37ac88879c8354674aa021e8109f372e06fe9d948974f5e526d85767966d0a7b6b572c1f9548f2c024c29dc5d7536eea97b0bfdc938d8cccc2769db32eeb00921d03c41c62fc6c0a222ef6e6b4684ab505f18e7f08ec6733b2dc5115ad3703f2a1e817e53114919e606b1c71b0ef595673c52e8ed0f4f6b17d09e08e72d40cf69a68a179d1fe04af217ec526afb028906d1b5dfa73c847d95b9bcb4683cd0914a20c8b15684d4f8f91dc4287122942a5d0cad863e6a9c100649d57878cbc0e914fd43bda744193ba84437d30afc9e3941125c71a448476d63211389939c50fab39878d8962743382673c015c0adc18d9aace62eb3eeb6964831e322f7ea8037f67eb8eee9131e950dc4f259adc15f4c300979668b7bf6aa69eb4fbefbb8d00e1edb3fe5c07d6bcdea9597b6623468ab0f816110ad72ea5bf2f167ffb96b909e9e7a704496600992ebf26928f200867e4b74b2c93b8a4ee0a2a8216ba5c210ac13953d4bab22f7c00cab61809563cbc7363530c63cdbb922e0836c2a179580ded4a7c9f91809fedbd1e4d12ac684defc9a8f58580cd6a532a03960185568203bc0e2c75755f9796e13d21364c86c7591bc63018dc2ce7122a2231eb667b4d0189a1e9ebb297b91ad182c654b475905bb456f251f92b67ed7663e3be2e89a701263413be601e1b24cbb683676c977d7a998f64eb05aaae5504065ccc2bb421055a93468ee30986ea0f71c933cf1d0de159534c1bc113f664c83c6460285aaf062610f9bc21467827b64c0eece7684c1bbf1fffe9889da6b2c7e21a03bd3d7306ec1f71db25ca599c89c8663da4b882ae01bfdd05831feb158e7f2e4cfea47c01ad9322f3de86b09f7747aa3f44d7b5d1b0b4d26c77bda4381e26c6c5bfb3160f1e75ac8a363a209b5c37d5f93466c48cd84d120ff94e112fd763fbdccfb0b10d1b2a95f43f2f92ca47d4e08aca57da5e2adc13c103071ac95daa4491c0866e030acb0756abcfadd58c09dd00983ba0d6871b9d3264753d12e426f688858e640b46c70f5b81e2291c49be1ffa2964df355781f5466e1eab2f388382c31c98ba04c788690f3bf5356fceec3009f56dfce2a137dd7ec8ffe93007953dc048ff580e -generate_ring_signature 9b329f5487db8fa896767fe45c6f92096dfe0be8251e4cd36d07c0919a9c7dfd cc275cc9d60c681f4d00425e16466fa9f2c36f5bb333ec2c95aec837a40d0fd9 4 67e340c96d30549d1dcea389f686423bf0eadc42fda684a21ffde3fe2a0a1d3d 118888e22f09ffecb3a079f729e993bbe3a2f8ad9b3ab98943d7b6d039c93e3d 1c03bb98ac40e56b9101b0a628aff1f3ae682a026cba93ede7304f942261f04b 9f8aab00b42766e651e5d5c5a71ea8399f52bab563afa059823ec0ebef99ae32 52b84d2cd9edce72b79d4fe908f59290c7231b8fd6479b11b81e990097c65707 2 c1581d9540631ce2966868d0fec7e4c676906887b94a4d16679852b625fa9d01a07990ba0a3c457e78dc493427e406afb97b002669959fb1c768c55a7f7b96016c8da559c0500fdfff680212db4b9c30243aaf27271dfc5046e9a313aa40560eeb8849c6a58f0617dc59b1bfba8429979784cf63bc1e7bdec89bcc44eb3e0905e1c306e49e593f9d349b75b5d4f6891b863c4de88219ec5bad1399dc50a3030b976fb8e5501612a3ecc517b0f2c9ff9a07120586398d169d3d812aa3cbf81b08c8fe286d93a6b1053b5e6f5e478cbf2dd10c258e1c34fd4b431e56581afbd1084e71e97da3c2a4511a2dbdcd8cf7d8ccb89c264714f941f49da7941fb1c11a0b -generate_ring_signature 3e8b6dc355913127e29a053eeaa791f7b9b25c96292970b20617a77f2941ce66 864ec9b981e85f596e34ef440cdab5ac85878584c8bf0990753d53c281430f5b 4 f04f4e042649c5340e6decd37d44afc47a81e00907733866c866d853e10616d4 d7ac266b6fd14bb55b3a4c3fff28017b1f2d51591a8a9a38a921b55e0ecb2b36 c579e81fea2b7202b881513f371e0b5cc4ba5e941e7378cedbf2355e5df74ec2 16cd14d1087769260824246f32fbe6c6e8068e7efed639574c837904fa186e57 1d46be9f88c8a3546d8107e6460b04cde2821f0c815fdeea2a5ee8556b36f006 2 83a241054339ca83784a712e34d3a686d829e50de74576380be5ae1c1cc99e077fe486fd923a435a19d9b6555ad855734add72fbe7e719b9578f63e0f1ff16032abfb77cee40451dc6e1d9d5611b7f54daf589966824cb3227d55bc4f2b9fe0960acbbf64e522ef2f738b7fbc8f3cfb4ec092e7608e6f56c0a94afb881f57003a88e35516894ed42ea1da2ee62b836d33ab649e8c11adef7149efeeb40536f0f108f4740761f9186f96df95e6718cb69538c367051dca6e656a348b10977ac0138bec3b830e9da4dfef7d9d0316d4803ada80812518d6db64438dc4204b6f20f5fd2f368d3def5df71cb8f882b283393b0965637d8ac400dbf97147197503407 -generate_ring_signature 4eea1e52284c31388c572c77b4dd6bc18080d356f22b220fb2cf4a1706bc0f86 0317dcfb34494772c5bdabcc64b2661b8f061614472914a82ed7860376853ec3 4 35ac95d061c9f478a387f5b33ee56b5c962c622cb8335e3f5b05a50dcccb9567 eff1403b48ec6986a6f3a436fa75390d47df6b75578cf7c00c9545fadbf9f9f8 bafee79e294e0d60c0cc2c4ce4fae48df86d0ba91e46e4a2e6cd033b34c74414 1161986f00835114de03ed5ac2f9b94de944c1a2b9f3a237c8e3bf9f0b048349 324b8b23740f0a95fb37e26b28ade940114335d0c395200e3df2dbccf3fe0b02 3 2c5102599b8dfb098bc41dadad8553f3d8de80b97f7f825be031e4993720ca0111a5cae362cc831a2fe2886cf766382700b8cb3b63e667ef57c99c1f7e964e02acf16e1b4858d5aa24afd02c8117f8841013476bac8bda6a87731fda498efd02b77b439f4258f3d88a9cacd23fca62eea7cf6bebc9e74448f2979b92662fa9039f751f3d49138cf3c9f996627b3654828bc118c761e2e674d6acf2b4e892820b9eb34e9c5f3755f0d84ea3a75e57947cfaa2c1d2aaf9e391906a92f5aa25c00395ccc07ccaf8abea39686715146bcc1311dff525684bc6538a97a7738c427a0905082f90b7cc5ffba7da93940854ed5e3572069360df887d52e3b093b3bf3909 -generate_ring_signature 3897f3826263809665c0f79b257b70f91ae560f59533df45c79aa481f14ba6aa ed20816021e0870adcae45b087cb64978c27a36fb94967dcddeba7878c43065a 6 1f644846ce53a77e39b3e5ccc0c578bba7b854b801815d27e4a279b929752d66 9370f055164552e621e0ea348794778e844013451447dac7420ba92789bf23a1 58d1f500efc8f928bae7a56d15ffc8b07b65139f4578ec2ee706ccc992d46cf7 07c2dfc3e82dd1625eaf9edff3a2fbc75e6e641a41a2ba56ed0c939d2b81768e c2156a0f6cb0f9d9c49abab8124b36784d2f0c676c9af313d1215357e5203e4d 016c41e09ae240dccf9ec65d33ee94ccc74845a9c8c233c2a2bfa220be6dd093 2753960b51aa5cef3e1fe2f7766429bf0bf3cd91268e609c44e5e1779005d20c 2 f738c0489fb544b24d02a8d28e231378f0dc1cf12814571c0aac80f14eb04a0ac7f5632475083d272560ac01537389afd92a8e8890de713a0d2bcf6566c72d00229672b135459b0b00e180db7feb3f48084c6b03eeeac5e2de4c97102a366c0d645c9f2df8df0d6bd74eb96020d532c00be3ea652572d0f7be8eada19a1a81061f3ad675397f54751a62802c8a9f1f6dacadf96aef817144e16dc7e7359fe50057de3b35380699d25fd5939a5884101652186bdf46cf6fc3e712ff0a6e056005e52135d38bd7d7622e928f7fd375aac38e5fe379d04efadfe315feecb25f05065591cc787da2607eba658a5b596b3854a805ed8aca657cf1ee00a9fc9c0fca05485eea448330e740647790c3a658040d486c79cfe4d7d59365099e680b0d160399c8b4ab33083b1f9b2d30edbc4eaa7cbc9ddec02dff44055920da09cf69a90893fc900c2703aaaaba3cf9dfe505cb8173272660dac59cd86aa15e1ab8816d05e842d89aa868173666c2e077b942f733052c7f2c971ab720599be50fdfba3b08 -generate_ring_signature deecd93de3b6635a3900d9205d9a0445035451960faea63acfb11ab858265584 1157cad423a531df089ff8735908f4cd8d8804ca6f796839239c18df3adb224d 1 888be7fe0293f3f66e8d0bf3606153505f274fb692431e258bea9ca2d140d85b f8dcafb41c048b60f3119e9537c0e2d44cb10b1e6734aae324e473769a63870a 0 0f20e6c16be22265ce6241f9e0f5be348dec032def584279cc0cce918567c707cea6a5a7ab04df2caf8ba67802e3dc4d6fdf0d8102310ded9495a3bcfa0bfc0c -generate_ring_signature 81b47dad14107e991eabca238e4b65e7367928f92b795b2f3a2508c79608dc19 c05b11bf0e1c3e0f47038d6aa49ab4daddab874de20e0886bd6f6c578ff6db01 2 b7f3a03806831c048c28fa2ae2f5fcac0e6d4a76cf9fbccdf2ba1d0e3229b35e 6638087a63c6d537b87a22004cf2364162a52246a68162872931a6c0c35aa5ba 75c26eb3a2b4a277a7cd508b08879524621a628ed9ba713b276161ceccd2ba07 1 f386cc4ba9b309500795c7a56dd86fc359a7a099d5af9076c0944c08422d4503815597721bfac1b774e9b0ceace12ca6f8bddc8dbf57c5cdb37047b924cd2504a0f7e6d53b7ed4cd092d685d6d1cdbee60a06cc9e317995ac505d3f7b346eb02f960ea6d977a8caf6e4239670952366ea226d3b22f5915726ab5ff1e12774008 -generate_ring_signature 27f39c66f6a61282ebe04d3c6116a57e4133798f01a738294eb6a52c813585a6 a9750add17565f877b2b22823ddcc5ee4b89f41c728972523d61a69b78e9088d 1 b02c8a057b5cea1652d1a4db956781e6ce07e6f86e747ce176a7eefa3d4d652f 8ea9d363e3c1ed113f8b6ae7672511441cad4877336596e940db05efd1e9ec0a 0 98d385d75e74f0d67b4e56814f0812e6f201a04fbe17d6b189b1250e5a057f0f49fef4b0551b7e19e6aa8b9874263cb821c10f3a73168a4b52f2ee5ab3a66f01 -generate_ring_signature 5c37b80efb792c48e4c99395fb19626df810aae0e617e587415938611e35b37f 952470262e4fc8ea399640c866cef6d408edeb219511cd4eca7006622386f661 14 84cbe808524c622505b5e67783989b593fee2b939b5932b8c3fd77bad3b4647d 60f3e7f2287a85996d5aac23f440ea64c6354fcb1f7013a5b25b081f2dbd991b 3f4a81047e7b9b1b8d642f8586c6f98bc20baad33f75a7504afa7c109b0fe612 40d1ab12988d9c1766f01559399c0e0c3451da872781825364a1c42b46760ff6 549564baaec6c44ad533e9f01a4a133f2ba260da2127a78ce876c30e97c6cd58 82961348f57fc20143b0d6b30e6bafc63b8575bd0a55a28df76af8629cdccd00 119798a0eb51777954ca108539337f40554d4b2df47a4d21de97e135b66b9dd7 ed90cf28e5407fab6b8d8fb70a98d9fd064cc0beb47c61ac94845dcdeca4eceb d4b35cec0f367a4e133cb2c6d4e63c07ee92247ea1033cce6bfdc7a67474e224 d37a52f026a589b51064eeeb64a14aea05420c2bc70d5a04ab1d5128819ad3b0 968604beed7f12f1058ac5312bca68c811064117b189e0e4333db93e603c8be6 b3793cc7a8a5daa5f02ca4496390157df25213562e7d4fcecca72e9a23119e71 9ecb2e012c207c1d09124479bdc8ba9fc10cba28ee51301b5c7eaf9ef68fa355 011a63f6c9050800a210f1015674fa555ae80133dbea7e709dffcefce488f691 ee5d09e9d9167824d3ae704ba8c5b4d2236f69da9002c28cc0faa08954caf708 8 a77f66c1bf3aee949169c2fe8d9acb131e32f9c2ffd23ec56a2829908d562601f3eea6208bccecd66f31f596fa9f00d18a0a15691560866ef26d3d430f618b028916cfdc1fbfd1afae37da8f99a13edf81a0ff3760af4be77e4240afd58ee80bc7127b404467ff65bbd3a8f9e4b642d471461279091675c66ff651d1c42efb094148b87d094133ba314676a5caae8dae51aa4733ff8974b913d8b0c4186e3d0ab3291402abc9f06317057cb2c430f6b2a4908d8f0337a4e562219ccc1d086f0343fb1a2d4f512e98973760206403f6315a59cf5f57272449d04507f4c7330106d3704033300f50e6224fbe3b62dcd74bf951b8a7fa0957ecf4a226b331ce7f087bf4b8d4e15b2f4d5d0b1b82b967405b9aba037efc362198157f61c4646c1b0e2c398117c269d0777bf546cdbd438a9d820bbd538d2028cdbd8d9cd481184a0e65edc53e29ef19d014298a3ca602259eb53099265c4bf08368466ea5ac9f8708df1c7796544e42665a130828257889c42f0f87a7e703cf9a4ba6a73f0c75f00e79e6a2077f7d711cc50a9c70ae1a111764445ef92e677f1008ea236dfe232d03e4b26105b27f1ac86c2a31ac87cb176e415b529438607dbe899c8d0e1c2dcf07369f9e4c1914b03389c910d8ab43b81ef611b35b518a8854e7be3daa14451605378aefad4ccff7dc639326ac778ca35538671bc8825a110d5339a6054690920af37530856183484de3260a2fb5497ae21e27856766e3e678cf7454dfb2e35f0ecc758c412d8d0be58f3b9c71705dcd20e81abd4a668b51c4f7f165d045ff490326d7aa625bb405717826284e791bb9cf4deb47fbd0ccb9ed636e296a28882002961bf7c850682e5a5bce94f66aa244cdbaf5b69305aca483fac58546d0d4e10d3396a42f0704bbc70dd830a500ce3d1484c41c475af49ae31c0e8e8f4248a5087a77d595078a1035042868f98373f7966456cd8109711ec1cf4f6a9f44dd010a58ed9578348fcd9d1c8cb569d81b95146d6b42909d46fc52fb06528344f3160c0b2388c2ed0ceaf32da74a5547feeda44f08bbaa7d04628109e73649b080120192c9ea78a19e3c1cde8ce487d07f25e2c4df78ad19f41fefcfd245eb03af380c097add1152d58c51e97d830ef654b15a93afa0fcc0f319e7304f7e8fd331aa047a23a03e544c33471cc97d6ef893b61cc74295d03d1dbfa105e5a02207ac47035663503fda553319ab0d830737ecaf8ec2b27e23cf5034bb003176e98319f40a -generate_ring_signature c5541e41e2a344f29ecadb669ec32474ec245ef6b2b5f06717612477a8bda42d 62feedb1dd4c876f4e95c2733a958adadf85d278f946e4c82f222a7711ca10ec 125 2804aafd5a6c29ddff9968bc1d6cdb3ab4d346e83d219fc96abcc5729f6b703a 77521a9631c275477f4163fea03d7c3fd704fb7b5efd379320e005840539af0c ff24636208c5422a9c83e3e8de964ed134553e54fb7e8205d2e77b325c66ecd0 f21c08aebe88ad781e69ab0026121fd5f134720075db02bc436db5b6ce9b459e 0535f689f85a203f3612be098e8fa8f06ef477af3395c6a116bf9e3280f57975 ee82c0276beaf45e6efc7ce81696bfff42f557029ecd81e0df7887b7dca4b0d9 f760789ca02a9fbad11532b7cda06619a32e2e6e66973039f4f843a1cfcfb906 f41125c6fec4783f9578aa8fe9fbaad0dfa5612a829c9d5b055c778f404a120a 0e9f1968af9a915ce9c88c0ee9a1c42bc4d6f606262509404362a80feba773a8 43d5caeaae639a65004bcf71222e8ca2d3b2851b152dbf7bb89aca28c456e63f 16a37a71f407d8ed2bd161cb9d3f45a9f2801ecbe67ccfddcaa31cede4cf986d ef3ad750bcb7779904bd2bcb5561d505c1c1891d8c78e46e94cf1d63a0fadcb6 746178b33c58f06a6685b550b789d398862762f14ba9a3f8331b2ba82e971322 ef470ff38a5ef2fe7edfc030a77d086100965fae7a341afd095867a411eb2745 e8d43a2b8c03e0eb1d64109b1bae138ee4578dd584480fbf9becd4e63ddc3ef2 f466151692eaca15a47af224b8b220c1f71c51a78b581b1f12695947c790d09c 0b064774a419a807e737a7ef8ff52dac16c372448243428c321c024aac33078b c4763dbe8d39b3f2eadfd70260acef19c336a1fd80a89d68bf8d5564c467ccfd 141ba183ad8dbde5e67f98828c4adc018d53db2cae83c34e3be314bacf438591 41927644356a7633faefd0bea5fdbd25bae1e720819d2fe79500a950e3fe6d98 90d8b56157bc869813104b12784c4e88e908186e10435d50add8746552f89c08 9f3eef380682bb8b6e0998bf7e3391992492183d624b829ed3340c34a6affa7a 87397030797108c58eb9502a52a18973db5700f8bdd610dadbc80aa3b6c66e59 2c5d5a0d6bbeffb62f288ee87e5762d6fc9074bf787d5df4dcde7a49e6efd1bf 8b2c1a8dd258009d5751dfabecc24fa5935f0d252871dd66d293ad0185915a5b b1ed2a53a023134c2023a77c7725817a9205f831864acbca58f9c79d417bea85 7f55eb07859de3dfc0a8e206d1d1cf4a0342488987a6d2c18f41e97df0df014e 5188fac915e9e03a83302e4ae128f1dbe63b89767b91a4ff3b9295c30dd3bdd7 10ff7af1f258091927149854228a5c7d5ff271bf4bda55a9ff34d1ba7675c509 38e38959c1ebde70dff0a5bf2257a13281b11d432bf7f51d3737c500c36f7f2c a19df45899c18cc81122cbad000567f8fcda8e789293f9b77b5845c03892fc4a 4c33aed9b6b8ac36afa9892e7183675ae5490d21449940b207aa6466cc1e97c7 4292a31b6bed65a201ee83b71915c238b72072ee439b25a2cd496d2cbba85250 77891645ef71973768d5086c5e666eee6cd22c18c9c027277154c294e58c1107 761de841439e26204b01290f022bb014db8df120501179be8f3764d7c19fd8f5 9e711d6b3abaf3a78048a9e1276e6d70aa4ba0df9673d7b7cd653494125e585f f9ea96c8410b15246095f15b1a080578a3d2e4a42c9ca7ac41d713d69c674237 13b6fcf0056f59eede98eadae5e9308012083fe4986c744e1fd93db114c389c2 1ab06de0e3067113d4ecc48c5321fd6928e8f30c0b4c073e21a629f794c930e7 f2ab29c1b2669413a71b096379c3fc8b21889ba95518e3fc576215fce0033592 9463f8f4a96d456025108c444132060d710a6895da60ba9ed29cb0e7fcd222e8 f17341125a334c6f5ba759ad278014e62bab511f9c7fa45890f99a07463d5299 0cc4709fefdfb59de0bd4bce0f3833a2e3e9bcfe56ea4469f9c1bd9e219ad662 cf4a202bf367be4e41350c1b3a49a90f1faaf925a73af48224b02d8679577d84 844e462cb86c7906ba82a2cc5eb86828fb9bfc790abd59c2cf54ca6c0524b6f7 265cb58a1b994444fd2a9ec13e22f1e219ee2910b87bcc809e592d4597cda731 eab37e95ed3dcd62f3ef9d98ded850d36c437ae0f7c4d360eb9bc0006567dbf2 a9bc3a316ee0f0dd1245d33aa0f2b0a65dab787db3b093b583c1d183cdd87388 c593bcdf8162435ede45858a3f82d18b6e08ec9917574bb630b019885eadc15b 519bd964446b95b440fd2832a2bdafa6fe9dd41f91bf9c190827ecd014817149 3c97c72e64b47cf79222f987d41a9f95959b05f60aaa714ecdb375f6bea2f24c d0799a853482f9870120c87d82efe93f6ba672e361244a1308f5a918f8026204 3fbcbe6e8afab9f595dfc5d42092b46ced57cf4a77a7732010e5435df18bcb35 e7058fd902caf725e1937654bcf210f8a08bbcf4c174127a19bd013a4ed13c5a 3538cc278efd09cfcd347eec14091864878040351f128a36f17f8eb1bc1bca93 d023d792c2ecf5e174d78de4f4eb1c972f05fdc31510ddf285ddac03edb6e9a8 e3bbc9156f2d1efe4b0e5bf24370772956146201f29458902f299e7b178e2926 5ce05d70587d6f961dadb852cbf573da00d3575902e5a111204c29c1c1995524 13d6a79c71d331cc44369af63eebe06208038fc18a35d65a9bcddfeac86799d3 f0c18a55b75b0e8b8e34b5efe0d3227be9898fbaf8b270b82a347c477442331e 6d941ae5057bd14443053028bcc66e3df3ef8002ed4889722a619d27af42c4c0 65d401e25158b5d536010e71ddd6face36fa59159c7147f57f98dbabd6c03e3b 236e3b8f14794886df4b2e6cfbe93af86a369ed36ac7a163855fc84a917d132b 2e731fad62c827847155d6b543e91656f33a37f29802b99c74b5ac3113bcd3d1 8bb40fa5f58d155cb5875f14fd8f540b6c5dd7fb230707cfa3914d8bb76a9985 b741f627de1025788557446cd8571f965165f3b87ba70bf9593d2543060b1dce 40c2cddadde1a33d787f42ff20b897470f6c49a2d1cd8fd9c9aabd4ed20d8098 b9b5944a94b1024f7f03d858245bc7085f2bf8c9b559040404b2a8f1f5668353 229f8995a931a23752d3617ba4c06a74e48a6f3c8bfd40aaeacfa2fcbc6ac031 c97156ee1235c56564ba3bcfb12c645e5eef9bcfa4173c3f7efa755646a3999c 207cdf552b7744e8e68e4721ee56795e2ea0d00db61156784b351b07d91d9b16 cde0f0dc90d52b59a17d9f220a8993787153aa1b2dfb30074633219be62ed6ca 2f8add5d450bd257117c2c40f33b50dd4a85ca2946b10217344e842ad29a3f57 198859b069a1c48e96f6420b89dc69cbfff32867574717ff02965e9ca9aaa9f6 da1c7cfc3af582887f4bf517548956f949e1a83a8b82a5c8a396df15e1ad1fc8 a0e5719a9ffc23af748a8e062ce1ffb8c82da607c2ee26993b0e76c01c1951a3 05776203a11284fcd79016b18d7b4544d10b9ec88a861baaa3b980ded424da0f fcf8075b1a91c94ec4b6f8412da739dd74d749a3cc55e9574e0b9d982d21ef43 d567383f5e2709fd6b640dad0915a229e62d8e44880cbc20b71637ef6c883cc2 8c1c065394f4585c0244671370ec3aa9f31c73c109f50ef0290e82b41730f3d4 a6def36e17f8f1bf3225f801454d57b2f8792adc94b1933fa01af88fe8e967ea f61371c2ab70bc8012c87fcd14f12d7ab1a2eb51875c764acfdfe3a2b3f69487 aa0303635376c96892e2e2f609d626b6dcca8b19879f5add956927ecfb6112ec 327a716cbd42649a2f59d3fcaa59cdd2049e94a96bcf21d77249246ffeacabe8 50123f75a9558eb33656757408e2ab0250269a03f9ec1dfa8386b38ffda39f6c e38b6d66bb8d6be42b76fd58aa01f118da2cd9249adf097f1b3b4f46a54d7ac4 108e7f9b934c25bc12d2fbb18031bb211dc7cdf996f111d0a2e56d6cb9c6a9dd 5074acee3dc35437abbeb588f5d942f968d449823b29942c21c79a16f05e65b0 6038f6d5324fa1e378010bf8ce3bbe897d5165b764396e25c243db6906951f3f 969d74fcf9d04f95b465ca2b88e50a79c678cbb3d1e1cfda6002379972eb676f deebec572142847258635858b17708930be57b82404f14d028005099d670675a cc8970b85874d414e741607ab7a9692512cd3108c0622c89128101fde33eaf83 ddc7f19c8d9a83c0c32191ca81a3430383c6de882741218a4150c9779559cae4 2270ff3129579cbaa7f986cf738785ce9fbfe70ad863cb39de9418905775758a 6e2a1ad2fa32e93d2dca5ba62643116e6b0788fcda52a9dd74c656e358370580 0d7b0a579493f836a031ba1a45411f36e4174ce06998bd231bb22e4a61aa4340 eb7759d06fe9444869c5fbfb6276a97ca4c8fa577030618ee50c7684900237da 799b5c7306c3f2882eade612689f64b84e03fd984f229b2bad363e9d22b33895 271ece66610fdafde9ca4766cf6e9cbec05386e840d0b161e5508b1a21d025fc 74528f7ec8243c31361f0c20b8fbdc3001c7af4a03e156d907048fa5b02a939a 5cc57310e3f8c9b79dba293353aebb162d7bac8535ac93366bea3d4ba7421dac d0440a843f298088834e32c073f27400c239423b5964cd4cedfccfccb0dbdf7e 61b3bd3533f547cf1c95755751fed8295be21372be495dbd6adefc160bd8e3a8 0a62af61f1c5b60e5d8e0a73ce851c3118b3a33b3e98248508ffc21c12e1aa30 a2bd0986f7ba0a3e2acd06c9e5bdefd96e901ba630b261ab1dce6ba18628513b 87a2209b6183ebbf569c618925fa782208943c0c4ba3be4ccd1dbbfe4fbefa80 c929225b641df9a42614b29645ce066050299b51fa4f76e4d5badfa50f62faf6 02b21e01e28dd2f197fbd265b82c6febf31d13c357e2e524fe770938786c0898 e224e1d91b7f496640c10c658c983faab5626f2ef388c8573262a5c2b803d737 f7648874f6126260ba9b85d3dd99419ebd95a187a00f113efa1cd8e26e24e66f 70d018da92f36ced31cc9298b8be6e9b7d1873b3443c604e0911be4cd6bdb190 0f7966f0a07e18ff4715fb0d0cd23d99c8c6aefb0295670e86eba3100458c466 327b0f4c5a5d34c9e69b5f3c2d9e32191ea616f31afe0cbad2db717b29cc4e15 e6c620872b328204fc60016bfd6ffcd5f475868e9eafdad2f90fbe8fb604653e 367bc5e3d53ecfb280d5bcdd33d37c3995a9ea2f4488f20b0bcb8bfd84b9e655 b826533c6aeee95b7f8aa6b9bafd6604065aa3f048e55acddee13898e7f9d41f e7a4ad5121e7e60dca0ebf2f49de2f19f622ac3bfccaf7c59d548e08f5176156 7b9802431d797c61656841f32129f8a99e23f625013df856eead6a0eb63709d3 6a7337412e7935d128dc296c0e35be814127f25ffeb42b64ec0dbd294985ef11 2ad88ddc9f00c78f253edf8a26757c38f2ad59cbfe69ce6cc0cb6577dc863782 d8e3961134ba49851ed743543d66a85dae08fa786e859ced4d4f1e9eae6c148b 157eab6090d78b4383f756450430cb3a4a993ba3f19e73d04fde2425aeea0703 614ac9e9b8f848877e3ee8e24d1b4c597f6afc2e518175b02b209a69c0a565c0 0a4d2290321b8aeace3965cf602c32739a0beeaa91567df3ca40efa915973447 8ef0ef41d7e977f0c0f2b955e8868d331a2cc5e1aea3cc014a64d96f1653b80f 6f8dbbfadd4f875bd3fb7860e6b522be87b40a36a9aeffb7d8de0115f2047b0b 66 4dc0004a909b0ea093f3f5a7bf9395f1836f675f63225958ca66db4244c0610824c5ac795e078a3ff4d70c021ccdc506e522f9b57d6ccd5c61a14e84bf7bec07c458a7ffe6df15fbdeee0f44e89a762e47229748764fd8c2f653927dc65bd7008e6a6807b9236c1f9c8b4a1fadc0cca4f821d3f8442743f1df5cea766f4d030278a5fba36f3953aa802e48cbb5b420f34bc3d29445f7099462637dd769c1dd0a3a01e6d2cfce3b2bf86dab33d4167d307d1d25339d10854dd345ab54cef52600d6e377bf9c92ac9528a4ff2bd4931a5860e7387523cfc7cb8f70e95ef5752106299d63a321d9bbebdadc554982029f0663e8392a53829475308fa7ce53b431082023ee77764f52e79ba7cdb268deb5d8a13cae9921bad88597cac23a33d931025a12788a0254eeafc6f242646e7723ba124c3d30476ee70097114a7147599605eb282bc86b5c012e08176e40cf3930fa956b0f340af172933bc824c21c177903c70f70185bc2fe378e6279e1588a25f178ef000ad8a6008647d53742cca5ae0871fb150c700cc649c70d19262811dea8912ec0900429e554e56a6412cd492606e2bdb0b2ca12269727ca3e3b2e8cdfa738f8730914c63725af4c7a8f7b8c100b414794dda4fd2477d63a74f167131088cc070bb9aaf9f14173fc02db48a2ff0a8d6a78a7d3ed7ce29b4869fbb4fc1404fb4a9d2530d4e0cfba4afb242758f5004b7b1efa019ea7e30ab61f25a8ab5bf92c0721e99700eae5ebeb9a9fdd3e66081ff4ba01ac9bafe46db58d196c11cb9304b14ae3d7a3385f6cdb7faee3dc1905722eacd1e4d770923bcad99a45aebcc75b602151d36a2a83e7c625cd8fca480e2b969e32a19ca91c13b003e1d038f1b1b61dcf5c03a44d46932157d48e77d50430d0294cc416ac98a306fb9adc248d16cd6674baa2b24998860f366e3f2b4f076d037dc636ee28c2590cc6544ed6e520a71c55d6d458bd6013cbc7156c8ae405e1b1b68b33b8abf7dee5dc42cf1fa130b9c9e5108330d374b37f154599ba290f9b983c7942f66d50bea032c6ee85b9472c186e50c53689d09a97cc657697e9018a3207bf4d9859058074682b23d7603fab003e18b19c0975174be4267f275e01284d7ffb807527bde515b9161f7708a30ef256ab7dceac24044a918d8ec01701282e8d37142e45b9d6ba348e23e2aa37cdc6c0a4f882f48fbd93ef0d843f6405af3f86e986e4fff771a532d0f1def54ccc8c7fd0a7ecc6196069ed5235d35505c24d5e3e1a1c9b01d130f1eade76aa4643ac0434ded63599bae730532253d605fecb9834d901326f3928733a002d9110d737a79f397630af8be30a5e4fa027046414c36e1bf9188419d80ae52f9d309e1fb1f45ab402aa2b4544d805a5c19207fe45708f8f01111502742e23a63b61763e3e81f48f88344771d8b50740fe940edfafa34d2da5d0312d68a5de4fe27f95b40382eb048b5d17edc58c5117b21c0478b40196daeb4e191b9438401d51b96a43664e8425b1ed3f3a834b7866a5d00dc584f7e68c4a54a1d02819f4855ee91a8639513fdb94ce05d936461013a4420c8b14ffd7189c6e88124bdb69855e23790cbaff2daec526ff7daea1cfda670c086c269540d92290dba760b24ee696ff5e061e6d18b25da69a6cef3af82e08f708c027bea729340395a89a239d4636e7079f95c768fba29b7d2c97c7b57d54590dffb96fe728d290829f9382e50bc3fdb14b832fab00ce44c5cf2bcc9382c3c3038fb4e05aa99d90b3e82c8d097279eedd21317307779aa1217d4b9a65349cf209394a10b7fbbe87dcd98f9defad1c39f2e59d2b5b511b0a3cef72846f339cab0a79e2b8fc82666e6d6164ee050ff1a74a586e9bd7796acdb337e154cc35feff013ee0337cd1b6291902f904a3a0c0463723ea2efa0b530b2748d30367dc51b7081cdff2cdec7083a3df621271930200412fdfae3a1cb69ab25074ac6a2b260209f185c74313eb8986e4d99154cf0011ef57778013d80205d8bcd4ec3f3d602f00ec4d597d9c207b6ea53062a36e0f7688de8641cfd09c418ce217e08b7f31a10ca52afc702255a518e24f2d9d78fea290ae9eb780ae51f5f75073948960fce00d906fc4e84a7670bc547708d2a52b3ab3381e7a540a77c1ebfed53de87dfc81046e8c74e582d864379050c61296d720be792823eabee0fc7a2f783a902ea020099c1e090e13bc4b92db2cc059b32a9bc73cd598bcc023509f6191728f353c93069d637c734d5f860f801b4855c9328bab9b9d59eb5902fdfd2a67e1d26ce7a30d5cc693fc0bb0100f246b24d59c784e029eb490518402fda1cea9d3cb5bc62f02a179ec62f872374a1061d9a0c05eae1bab485edbe8e53ef85ce34b89de471d0888133bd506de75de0b29d3c5c40ae4c78f15ed4168edec1a0d931fb30b457e01bbc51160e27c79bd01a440bc79d0b6f49e58bfcf3c1e2da8e11b7b4354ea9f067d3de16fc82e9066d181744203447c84bad3bcaeb81a737ddca73e29405f7404a30b2cdcf2eccb50365d45036f902abcbedf6e3b9781993f3d64880ffb65b5066fe8c78c26c1f4090059db8feb5aeea02ccc86cec3a6f18379465f18fb80b4073c6fcd99601c397911d4a053407c4fcc742b6043289d036bfab167ba1d85840d9cc14e881e52f68e7ef84f895986f5a5c4c82c4d1974acfcf348bd382e6cd1034300598fb6b438164d7997c93f3be5a3c94c4856523209a9768a5ebac7866406e2a3fa1b21d7684afa80afa7ae616143631f6344264be67968e4ace35cd8850b11b94c9711f89b43172d0fe7c4119e1480b50900399417976abf1096ac278e08af40882eb26f137446c107b5af3de323287915b727741afeb8685ce8a0c5160761b2397955cfea1e719fde1eb180bfe4375eb36d4d358e4ccb3f05e1e955ec01b5e663b12629cc8d5afc25735a97c1a8c53d53deb8c49014423f6f953fa86f0ba4dd5194abe5f6a1ade9ec84a152e4bcd95c909a84e709cc015ee37999a4ea0891151e185cf33c68854011540159a89ccf582ae4b605e168ff3d7c447242dd07cd19610631cb4e817e879ba59c637d5e0eedb8d37f75f90274fbca5d8da2d6055693069546f92530d1225a73e61c37197d224fb495e6a8b2dea86d9ba472a30f6b207101bb41f5bfbbef12d043281d6763881c7f58dd3a0ce83f102cb1e24f07afe7e3132a83eb35d7506b842192b407041a219b8ff76757a5acbcdee2847700696796152b4e794fcd481520fa47fa9ffa14da0eb305fcb5c8c71de1446f370679bcffde16f2c7a30979e1047855e8116a4738a82ae4fb2dfc3fffe893b8830a63b1587bf7fd448a3cfca6ee640552adfa52bb32620a8b01fc0544f6473d3602bdb97235dcfb7d12dda8a85dcb4d346b3933873948f3929ac8f54fdefb486d00e471508918c1f7426d654c32d1ca8d2517dfa246060670e7ee56b2e9d7a532073f356fec3a2c9d94824f3f702c036b58e71a76ba9f309736076357cae37be606751e120e05206bd1133d022734a2ca465639b1981a2ad786fa791ad4f6fb3900a5de9268dfddd7cf39a8105c375d4e5ab6003602a66d33e63d99f966ea569e0a1f221471be8cba8575f049ead182886c339e7af1c4ad797906faad46997fb508f5d288d87511e5963fd23c89575990e7f8eb9cc237b14740a16987b99cb4220caca046d3644e742f8d099657cf68945c4e1e502195c382daf2429bed25dd1b0761d9141faf6256ead78c7aee9dcc42a505796bdb35d94ee565e468bc7ea00006ca58e6f4c6dd591dbfd6f3306d2d765522f68bef4ede7405190da56d2f3f4907eb98883dbeb5f022bd4190e8a34b2d77f7c626e75675ee08b51f1693af8cfe03f9ea10294467d8c136243972b0fdbb2196005c6a1f3a1d6b303fbc3e4ab33c0c977bdae51d5731bdad097ef740c6b12ebc634fdecb82090eee099b72966356006c89681f1fd2776c29950605daa95cb1a0fea3ec6be1a7dc91f8dd626c570506fdea4eb5cb013ca970c104e0a39096d5e4a7388740ce44ca0d64c2c6c7448e0aa867712abc79beb2d5366f368a75edf4f6870094cc06c091b0f188cbdab84d0e2838297f675506a5914845b282bdf3c6e1120a64a64fe0ad2ded2f5f4e86970d09db1b11d7420b2aa592ea3ba101390beef50d42596a44042abba6b7d8f2f40d7c7468f1048c90df151aab5192309ad06a3674ca1514d92236d7b22e1181ce0f4eefb20b710fc0dcccdd141b012f9142ab7a35051242fb329a56e499d1dbb80e1ea14af799a5e00d5245115081686a6e16d867a37c7a0ac864b4fadd125e0c02b80dafda7e91ffb641ff964384b9201c0697e3fd500babda58839f453735eb0c872bf6dab726fb303ff13cf7b2730c0bb8b13d96333bb01e5e27caaf4b6f760fbecfc17f0359b7e33745774dbf05fecd45519acaf6d0204d582dd60df48ca30946e6f2ad7e28ec2e62d3ef75a32b7434c723c28bc15ff71d0f7f8a6e2f6151021b4502ba6ee6042d56cf7d8ddf9d7a45728ad1be62aa7078e9baaa6cf2cbe80d336d7422f29c6354f73292f3ef0d19dff321bdcfafab53ac9afb5ee924e31f07dfdb9c832f2eefd29d1e44435e8ad9fa64b41b612382b1362a3509d78632e104167cb17bb645a4e261db047ea86e6261373e1d67844fcd7e87d8d6b24b0b99083569d0497527fa36c53bc9fe0bc4ab94347fd9879a79501cd19565d81718970d9b863026e088463a9181254bba9bf233fcdc22c5a5e3379ddfc33e950b11c8040ab1557a7753244175a3d434862bb07844dbd2da6087f9c1524e83c7e8c9d60ee56b8f55cf0b61cf122aae9592d0af9a9abcaa9dc366862018892676cb9645027c17e9493bdbc53e5ae8bc29ab6751f25c0e041a4f8acef0a2b6534b5036420e2bb54030f05959225d4c9d0ddf2f9fe0ce1841d4380e52ba5fadb5e586582a06e68acfa26cc07bd8b918d4d59bc9900cbf525586b2da060fcfc9dcae2fef270e25a28ff4f1fb449aab653b865061d4a3789c3201d6bcf00c13f8678c934d0009fea4ddaa82e5cb4b270b6142572eba727903033a45267567a39c86a3199a1c0eb2a97f5c5e1dac1fd99a88eff6f1930f3b5d32261ef6ce8bb3f721ec58d2d10dbc8b669044368af81efde77025e31ee9c5e226acf4856341a47bff97e97d34093db3b6d11d4c3a892fded7f9ae333749e1003df3878707f371444dec9f756804e3414a70d52120cfedd38aea649fe4d36ef2dbb4ad8b7e9c58a2dc586a416500c8f96d8716eafc2310c17f6760b6b3451dea0a31194dc4fd84a877b6b9c41700d2ed8eb936139d08bd0548dce4a7437e6aa6a17b528f5a9d8f7f01882dce8402e7b19d53c2f8ff1e2738dc2bb6680c1be82abd48ba09f9452ece81d35d1ff9058c38d2dfc00b6b4dde5df1b0e59f48302332e35b5227398497aa80ce4dd891019879a820f92e3ef301842993ec1d810016d21148543991549c110598d2c7860d2b4a459e75f8a5a3bf8aed975bc4335c4f6aa2da40b9b4e9875125fa7146c60d535f56953630fdee6df568aa32c406e0fefe6fceee7129353103cd37d977790fb18da1650495640fd49772dfcd2f8397a3d01b9a76ca4139ee8e9f6fb4399e0d3d14412fe02a78c0cd3873ad2f3a32c31ae05a98427bfa42916223fdac912b0190111e7ad6fd7c3a438594e9a2b2264abea9639773bd22be11039634a35d3b00e9daa8823e4fa8b077df4379f1ee1f32f31c384db9da7590b3e30d1cf7225b02272a19e373cae8c7a1d9e7310183af3dbd3ae19a6060d3b23071dc8008487905a0ef9011dcd39badf5e1e4092ef2bbd51a247d84d77820686d38c26e7630970fcea629f12bb7983c28be7d73a92fcc401435095ac66bd40350056445867d7b0f37aef3134b3d01444c9e670a6615557c283a7592ee5f446480c40fb6ae961106bae3137c8145e7514374e55cfde7001fd1276aa41a36b68dd62aa438faa5070cc5d8e3f02b870c254ba2328bd9d29dc8fc1059d5dbaf950731fa620cb0ffeb016e0ff1dd7a9cd8f278b76170b8092ecbd63236ccea97539c4708fb212a4ee5001f67a175b927bc5951c9c0d708340248e59103b86b7d32c591251b55f753e30d404bf8dbf40f0800348b301ec6b6b9b508667c8548cecac573ff2b9a2247630c51f58d56e558e39fe65d104cc73749d686bf8071da26a2abce09f5e91cb39c0c4f28da63b74a1f27a4eb9fbaf27732a3341daa872f87e74ab38a694f54da55095bb5c9b4ff005615c7cfbac47a55a79000f3765b20b8e409a664214ec86e5c021412f6505b59d347d98c644f289dc752b97a20767744864d6c85e46fdf543b07290aecd9cf9afd8dfd2cde0fef08fc85c3b5fb1c59f3725869b1e883162a2406e3aef1e43e983f1fa91d03d6b24cb8100717138a64561bb2582884d7c0cd3b017f135a7ba72ff7fd095cea52906040ae914499567342d59908544a8d1e7c830af8892a55f6408f8c45cad16a23a1ed76262a3a5dfeb8b174996263a5a39f2b0aa458079ac018f048658716bad78a2f263fb041d322a8a437468b5292ed835a0ac46664fdb56173d4922102414e37cf65473b0754ee0112ab49cfe997323a61001f581875efd538f8c6ce3bd16d191a3515c8248f4f5c4b6e7961dcda9286b50350b600ca80e76d21db282c2706e5dad59a1d8067b20ac564bf5bd6fcece0fa02e00ea91e70f1ef97f0109987761778ab1ee5dba88db2cf88c652941b5ea0ea03c0d41a55845fdac42fdbbb91b4c78ca2fac40f2786d3445a116f50cc22519606ec742626a24257239c18640c7d548b08cde9ba01c2890eeb975bc1d7e90f57088ca8e24a5261cefd62eb6cca15415a23c050d27da45cc0066a80db5bbef4d90928178802434ace8553ff4f54a12b8f11981f757be7776010e6436e0c72820509673ebf236897067cb144ab2a14e7c1a38815c08d7ad3809d86f4e4ba3f12060faa3cc3d56eeeb259feb81c1e19dc6ff6dbdc19b59c8005dc530915453362880aec9cdeaa0f720c2e1f6d9dcf8b2c805a42779ff93f4f0281e9191573cb29ae005b0b3f61fb7a1a8672ab2386a2a258cd3d579cceb7b81cdb78c82030a497f80876b4293ab137f0459119092701cbb0491306e89753a8fecd8356d068f843a500b3924e55199d1de3be74c9d722864018f47ace0b74dd4f9d639ce80d04abad00347ae4583990c44454d7331cf8cccea96427a4de05d34a3a955c4f1e746a430c834de19404a77fd33796ba12600690bb4441f7620a7b21e5252021d6f460cb0c59b0b022c97236c98550f26499beb6a80c8c5c6c2ab487d15d0d285b366c1d039378e2710597941242a64a2a9d3a3b9eb72118ed58b18a2c5bb1572e91806d0cebb74327e2e0760e1e81a2e61792e39f4f6e8e374fb015d57219078f8e8dcf00ded933de3cea84f7ce9f47210d43cea3ef0971b5e428f141ad0dc58ade09ec0eb36602bddb295784497b2ff23d589a72900b1c5bd596f7f3eb9805c9ab6a7e0dbe75f936497cbb41a029ee027086da196ab971cceb28662a1f0a7ef8b5fa1d0b1824e3a45f9619b5c6beddaf9d6de9fe6247094e73667d6fb0f86340e9bd4b080ac02f73abc702cdd9ff4cdebcc512621fe0e6e533c77e96f15dab1766a4b00a15e5d2219fd4339ac2ce51b33d8c93994f80b6940812a97d6ef5d75f079e3406397254b1aa03d06464fcf4b1175e2986f76f87eca47bf9a12526d750084f75026ce571abe2aef2dcaac4d34fb704fac8a375b71cb24696e51d783cfce68b6b072775589a34609c5644e1282b6df5b59365fd7b6e67e2a1c38dd3746eb2d56800ef7fec80fba750ac12e0e6253b0f47011d422b73796ba53ab7f47b3ffb5cd300b0b8ad0aa2f416c22257e6214159935a352efe87bf1407856784f23fd1014f02d44bfd5e56094eaddb138e33d79fad843507acb4df64dccb9a3e08cc7f352700fadd7c8fdee2868d5f6ecb32da1d12d4d782e788ebe071b78fed25bdb41589017fbb07f0dfdf9b45512c972adae139476da1af30eb19c34dc1b09f846e4b9e0d435cd56833b2d7a053e5e3475dd788e6f184b75ed53c9223012fc7385856a6038239e38e3b15169a049ecd44a04c3dd7c4493ef64bbe1a4c248eaa47917be80833b2ee25df9ee4f2748fd67439e41309304a8a8c797d14849d939bdbaef2c706065600ea940ad7952238c7fc512d9cea31e927a2b6799aed1c2a89a5d13e8607b49aac43bda321e980538c88bc5698c7141fe6feff5bac98fea8633aa96d3808606d545f289dd6741ef12fab862b4ae4e50400e140e930540dd81cf78b2f110123dbb0dd77cd6481a245e16d242f2d9aee4d1c132beb8ea45ff2e33e6ad8a407e20028074f1a89b6eaf6c9e2c76b8fffa8096603a1f41843de0130d968cf2c0b9ce0b54af3c39ae5dfbef615e8a437aefd3b4e8f276edb6a79b802238d995602ad64f4c7dfbbe2803be40cb3ac3af6a67ac86e1bd115500ffc95af0c68885102223c21be4e38ba59c440d3ad778ea28a312d93b8da981b615ec14eb638ede802f6f8b7a9659a178a5d0e428710b407ea1f0f981806bba9dc7850b15c3371c3092b299dd69bcb72f2167a50ebfe66d75b4f256fe16254792f5518e1389585d80c141d1cc2116189e70f5d790e58fdbe1055e59d4670810169d19ad0f5eb40af0dddc7f10e86786ae05cbfd4a5897d00e3f175203ecf39d6e33e252972d10ebf07559e89ce2e7b2a997d2dc922d5ea14dae614c0fb362029ba1c439fe104d0cd0adb0d2dd9515c7577b2ada453627af0762ea281cfec691f15daff0f52394fca0e15e77e76f95291c4fe218a781fc5e59c686395abaf78919f65a89c907a29ad067c30a33e5ae5c6e7d1b11e2f2b18d89f5a765467044a6ee5c924f580529413016a8be05349fd52b13382abe407f08fcd76e82f874a380be55e02c92827783405c5a4c201e4136d37527fdc5450fa536dfc5c029b85fbe2df2a451c65fcd1520a73d6d78fff06142f260eff5f68f6c6d6a473985d4259a50ff54a15a7ce0d9a053621fbe346a8fd4535137cfd5198a1ecc5cb2ec7e8bf4f7e48b4d4fe8abf9f05ed467dab5a373d91ed646b7183fdf5263dfc4ad173714ae7b236d1fe6ea45e08e422649589ace8c836c991b959155a8a61f658a60f4c7b1771a0b56bb37833065e3712f8a4d0f41adf484a03a2db86cf3ba761759581e9f339c8723133f2e707f5415c1e6d32c65f6917497a739dcb633a51be56c46baa4196e0057feaaa2f09efa4138cce6f362fa26d4664700fa5e7dba5a9068dd05e75279d7862b628e503d6999aeb7c7455fc1b6ef2bbe1605e0cd615f80c17ad4f50f568c75b8b34d40e73b271c611f249a76150db0903d82350b73d46fe2da93c618fe16a8c0991240295bb38dfe42b9095c27d51a8d4ab6504f2b3a4e88912dc7d44636ed6dd1d7c081ae6b0f0c7ae51fbea62feb5c5598265532b4a6c361fc45346f02fb9fcdaee0bd094a11ba49e0a635affecc691e01515bdc139a5761e263e87cd26bbb4480a04535d7a04daa59b88e7b7772c450059531b7aad08f1e313792eb5f106ce52000a078ff032112aaba4b6b461b650be2607f562e1f00578e0043952cd49db32100e1401f313f1f56ee68795aeb76b51a09d8effb36343b73bdbaec36ee10aa6a909631477ba215bedb1a9aedaf0f0ea6a8d187ccaa3394394599da419e914822903399a12a1ef3fd6669961ccff82ae74bdb2d35e6dcff068c2646c78847e69e604145e0ca5bf43956d33a228e877ed4f5fdeb3a618bed80c5e67c12f59c3c9c0008de90e6b9e3444ed6b027d8bf42798002622eff383220f1bb884fe3552040c0c6687e2bf0a5da43ece1eed36784a3e31a7c6e8e57643b4e84f7896e7104468048cbfa14f2758539eb3c62041cb9c511eaee8feb4581e0c31b1f56791986c1e09cae2c1ab6a4158e83016d29542da36fc7fc15fcb13285badeb45b462c231f10513667d398826b6910dfe0d65e57da0eb687a31893228f85a81b61a08e77af30aa24302fe34a3cf2b4c200209c63737209619bcee377a31f436036767d0cafc08f7e95b09820071030e49d7e74cbf0e6ba0673ea8d713ba881381231fb19c470cbf069190607b448d0e948a18cd75bc5028b8f8fd3d8500fa70c5aed87ecae003e10772fc6cc5da07abb8ade5c72d25307a7edafcada5745637398666e0538c0243ccab54690242751b84a34f0f7cbf6793eb7c1978d57f2c4648eda51929040ca1dc2e63351b213ba5b9242d1bb82fe5ff347629f73dd7e846533790de4a0c0fa51576c8b5939c98a57896052f84e4158ca39d8456a3d6ef78ec751a910ae70a1ee20227067149ed052e4add5edb294875b5b8a27206ecc2036df19cd42160028b23d984d1900112711083a1465576eff6b0bdb8184479079ddadf3ba6da74058118583787c7994d247562a67ecd8e54e316890cddc8698562a909d74e48390d4bdc3489613e9b6a5e48006163f1b0d8f93c4baabb54d3b19e557f93580a1f00d1d9999d7f6c510a267758ea5f4e5155d364c47ad0405589272c5ce3b0af8908b129947c63c6de0658084111b8e82daa500f2c0d487f4e46f7780699d9be4806e77798a83d366511797b48294a314ec53345db6e10ba721cb3070c2d3b17e90b31ff22e89ce20bee3e7f0b665b3cc60a8ed58a413b13b7368da5ff89b32ab104612f092203d286f9e8339a998035946b6a165f9182a6eb66d2f7478abe8b660eba8a3cb19164ce0f43cb350b3547bea194fd120bd5110a100fe6d9738207ee0a2d8447a7a9de8187e2b303003a246b0a7697e4bc3e3ab082601b9edf190bf40dfd084c664397d05a644a5445e4619ab71b75c8878be8b638f6a0f4d09e81f70887323fd93acb4b0584e3ab1aba68655e90427c9a1a2694ecd77a80d6071a8f0e811fdef1faf5a2cd2809eeaea033e3f918fd51157d0538d61a22571313ed560a33971875c62813364e8aa6be1fcbfdb3cf8e261994ff2f3916ee0ec7ac9ac70dcd70a95bddb71fd57da3c4e3d22d657b8ba8b97017d531c64817b6c659f51309b00fb5794c7086b8b9fd719af69074d01f3329ccebecef1479ffbf02abb6860b1c6b4af6bdbb7dee15c2e5e824f1a3d8a19fc8e8fdbf17cb541ee6c8edc6fc0972034bfcdcd8e0cf6568c5dd8815f3821d254a8fdac4c4c9f59075fff2b3fe02f371efc09679bde59822a4d17f37383bb528fb0722018ed742823aff2944830b -generate_ring_signature 6050b724afab4e33fc1adf423689add9c50984ef8df4b93034fe824ccbff6d6a d1588a8bc29b2df0d555b8b0632841b68cbbb4623ee615c9499862aa5b732cff 120 ef87037b6f29edae32f566f14ea179ecf470fbbcabf36b62d252b85af30f35e0 0adbf81b03429adb494d54bad3a726c919e81df09046e8f237eb9b5f82882a4c 3539a4bd1b04de484d125456d2135230caea0bcd47d76beea4d4521918f7e769 e01e642c44600e167c640013562d0d83d62e9eb696b70e9ca217725dd0b46ad4 9e748c90a8fc9e8839f770f94ed282e08b2d0319dc1287bb2fb3b240d84dd055 43001d2b2c696470582c98b0410879d5f5afd93d7bb90cccca625d289bc6a3a0 dbe579be20a891db9f42ecaa18e45ccbc4abd200ab7258131365a4d5c93e776c 69f3b6889f8d6d446374ae878b38da35741eaa4e4a88ef220d16163703c244d9 f8b561dded476626a7c0ba1adea2c1dfd69d96f0dfcace37406cb1bb25b19d14 881e289bc813db26f4a718a6d790d553c8edd952fdc6e70f1434e0cc81918098 0a56f9f412b6080c9bbd334a6a0ef92ae6a61b038d6a09b0b4f1fb38611bcd21 2b8c0b64bab89e760d5a74376f331ff45e5a5756619836c00ce5882b08e3c164 fb0b6c65d3823cffc4fd3fbdf0f7d867017a8c2d2070af7f69753836a10b3346 d58bf0a33db172ad6cd6460498f3fce85fb3a138694c3beb46d48bb5fec7fe26 0ab01cf3ce2a8d87dfbadb6477bcba61ef64981fea057acc295aec2dcc9ad983 3936b64dd7d013462f90d1969d8c601bf6a4f0bf45b443534eb2ccfb03998ede 412213951f3a59b88d161c057933de94085d7fff3fd1e370b22b16855b6df2bd 5d6a58959691c9c8a62c09bd015b84d4fd7a4c8ab3826100512dda43cbbb4ff9 7eb29652b5ed2b1080aca08c6eb2bf7a41e30df6c229fd56b5d5096905b2acba 732bddd78f3cfcfd342547d80cd2010ae931a76500c9fc073cc193a843839d02 e48eb1544264647008711c351e81c32f81e41f5a7c85a7141056c253e8e856e3 7288c441a034b859a5056dfe0fa9911c24775637c5f707c2eb28c90961747514 f06413f8ed307215eea8842d1f6aca79eb1846c21e1c4c243b665ba195a1781b 01b8892d2d57f8bf7cca182387a6d0872a92fb1a72df366d873307ea3927fa12 d729b986311d8c0da3ca87ac439c5fccad8128a5be990850a3f5820846147146 4b4d2bc6efb964a9581dd77f183a55567cfebf196353ded9b03bab6649ecd10f 4f12843900a11cb9802ad2474cfd41edd21405a2bdd740e9739c66a5bbe50223 d93acfa9256172f808b269ae6faf49ef9cc3c86026efba2002d2eb6a1da504bc b869d5d99868014123044ba4808bb55ff416a7590cc23bec4d46f7a517ba5b41 35b15cfed88fbc7ad9034d47394fae12fa8287dc371b78a7970c51c0697d483e 24c214c701ad51ac08e0a57a8da5c0459c2499910cf99a6a851cd435b47627ac a92fb963867312988139b9e3c29d2076d1a7f051513b6f2c3c24d74f377f2e37 7e4054200f5643f3437795f83bdcf506d97221196ea711b1d69afa5e4b345978 a9c74fd8309fffb5f589dd48f55e29653b8d0638473139eea572bcf4356bfa13 c8ffc26337fe41548090425edcfbb21989da5914326fa7ea776b9214252ec87e 3e25940afec823a365f77fb1f13aed2180167df85773ac52edc44f2346ff7c59 ddd96cfccaf4b991b9fd6f819ca1ecf8e0996e42862b9d0ee71f0a446620822a 50090e56c723895660648958c033bde07fddbbe89149b1a8c8656a6a35a4bbd5 74912093994ca326fb15659020de86bbb291c425b8937324a0070ca4c60a9165 68fd8c81aabe602c09f4b37046db3fd2c15267d974c3697c5f6f35f25efc8183 44f490d63003625443747a7243287d28b3f5fe4ec2a273131d8bc7e09c461d05 6359841de569f54123834720941eaaaaa59b8f9c2671fc7c83ded6f831e9fcc6 ea75a676b28568f3330e7d9421ea92f3ad3cb9ea67ca6a1662c45eadfb67182e a6c073f05c29b0ce08c57cf36d71490d5d40187d51d382e09fbbb2a54114a376 f4b02dbfd2253dbe13ada78a09b53ee799fd347705c07a9538cca79fe719845f 4535ea3b1f6aa90a6b98e0b940c164b31f4787b6a847758e88ffc7fee05d5cd6 8772138c613d9fc8f3f62a0373d7040616a372212328d0acdc333d62fabf9a40 a8f52f5a71eb7d703f5478f4f382b2cf3b0efd6538b24ecd632178dd432dae5a 97215a35ff24137d83c793bd9057ebe8ee7e310964ebc5d41eab6d15342479a7 e7ee87976fac8c0a016d83d26fcbaea4c18103ce971a1d695333632432cfa1ca 00d81de15264f2c13b567041ed3a8cd5331cec6305e4ce7772138be437d62437 d452fc10e867349bcd7f3a783012d1b4e26befbc821b29f8fda8cf5e5b8c9b03 96eee1a1c980b51b51a3e47cd893a4930acc2a61ecda8beda97ba416fdbd6f15 a828686eaf20007dd299f869ef52fae1785b0f25810a8b8ef5b47d2294b77349 bcd0fce555fc44ba05a71cde39e36de093d44149f803781cec70a1c040d4e114 e5d10dd7877e7feb14ff7ff3074abbce9b62b7845de46880a1a3e400269e23fb cf4cdb04cb0158c1397ebf413b9940424f4eefc3aeb315b134bf1c012de95886 e99a22d2d2d0bec068aec00b14213757b498140f6a637b3d14244f4a83391640 e1d337d2a691a786e85f0f2b6be24fbbc6e3b0916986de5551f2e04eab58bbcd 1dc8e63527bf9ab5699fe1b2e6d6aac976da2fe8c0f3ba390239067f19168d03 f32db1edd95b03ec7a6cc707383072b2f1d9bd7553ca3213a76246ed050e5ab6 9b6a260abe2e997d96e528bee60949c7c79d22e88e3f97ff9740a40c030e05d2 ba6364da3293a9a53a9068e15387444500d6d5a91c45760b30b900cc5a44cdb9 5739ad6c057d2c16e74312a7123fd6dbc46a1f34067f1a6d3f8751f801fad433 e6bab56a1a5f21bfb687e77f65d0ec0cc0063576708f02b204a6fe716f8db773 97407b2907cb431220e5553ee94eee4b92fcbd7d3d26f11e48399f5c9ee85be3 861f72244c53d41969ca914dd57e15b82158270e5f133876664d689d541ed165 0de2abf3741bc18b0f5937818f3a1e33523630ad8e1cda086b955c2b13c4817d cfc22f7d43b1effacd87521b5463772e8453a2798f2d48c2918d264f15c563b2 26c67ae82b3c310202c1908af303e69ca94c0ba83a8176d54d509781da183e86 75b7727257ace3fdaf28bd08606f4e8d471a805858a4de3af7ff1b295a8877b5 8cb68849c5752cc92d8c718605eb5390ba07013bab0659429981cb8249148107 10e3bc9b4705f0a5545deffd9d83f16268f4963d4d12225086432dce3f317d82 994e0e93851f6565314a797059f6a68746533f6d8afd7164538c279e3983bce0 0026807556960aa20611418df4ad89b46722bb4273305ab5beaee0518bf90b4a 5df227da750dc157f18d54abfe7ea27bb64eee746b41315c843b42ebb60a93af 6c3d71b333bd43ecfd9bed9e9c6a3438ee386283c9de2bf1d9cc6fe63eb3c7a9 5862c6323eeaa240cbc96df54754b7f9b38a982646dd58b29b7674fe280afa47 e59d1cbd91f6a1da83f811068d2c32d3a4dce1cc87e12dc670b3c8f4cd837668 e01b48407c6cc98e591279d215168d45f8a9b0bdce74294c863520a96c1f3578 d123f51fc47d4a4a23d2589b3ea6afacac1523ae68c9c3e987efde55960da989 b24cbf3af9e8598a861c21eb667e305b275091ff54d619de94427c4e8107b4b1 ce5ece118e978a798e3bec113fcb05480ca08761b12f4d82de6aa20c351dfd4a 881e216b3ed4aef9321ea28d6f31d565356bfc4b1df72b877881273b55de257c f086d77f57298e4001ff99f30c1ce019cd81a74fb77dc8d3b5e286a972b52b78 22359fd9b4985eb46e587cf19bb5094ff334ea115c12eedc31b14a0c1a883306 f4ca0ca1c5e64f8143edccbe63ce32279457871600f83f726706a37274f0dd82 2aab22b4fd2e8d361accdb45a9035695c109d53d69ca0bc4b6cbec1c5a5f73e0 d4b27fc292dfe7d49fa7cf49901503f5c6fa53812247a99d09fe2b540c1393f4 136c4bcec68a9a9d675f590e35ed6a9e51a85be74c269c66345265620f5f196e 2903ea5a2ff85ea2f92a411467005858b3a315b6b6b9c7a7b406fcf2906a69cb e86aae3208c02700d40ea0c63ec911ad32aa67fb4d5c7b055ea2161a877cced9 c2523fc728db90b1111de2a58e424cabb7dc53810094cbfed40e0f1899b31cf0 239b2dd969fdffe6ae68c2a227fd066b0d08fa305c8daa807db24925d2a7ba90 2d64e595338b931b929125659133566e25fc56874ef3eae77760e289a4e12227 64ccdc4872ce46da3421e9404faf86eb8abd0046239c71b8fcd9f2b7e1fa88bd 85c0e8646ac761449a58f53106cf8406af576c36b70c76410a038d36762d4abc ea4dbf46f8653be48bd964ccc8171a87d06c3ee1874eea739df7de9c8f06553f 31ef879b28137a2252476dc796f988465ef7640224a5d9b8b75bb890e8a8544a ab061319d1d6fb3a9cc5c2cde8201a208b82e5eea782b88ee93aad24785c2d6a 43d69deec91854813f55eff328db76ca3f1973eb498eb0f1951a15c806b8d9e9 f9f07b9a4f5969d9ced711bc842836faf8049d5feb3f4cbcf094089d0213a079 efb00a7103ff7a73f36a3b7daad7efbd296feae5fbcfc8aea798a5921fd4982c 9ea8ac862144b79a9715c672a206686f4ba6790c08159746b2707a8f20845b44 22f9d130216831692a2fb6be1a5956179794cf0d3ab5240aba781add81c8eb7a 2e43959ec556d13a5e30403182b5d786a6c90b1271333bfd306b15525c3838cd 7dd14d4250642888be66c827013a345b63ef223c79e5410d86fedbe880f49511 075559e15ccdaa2be0d98e6a4e9248189168612117f1161da8523fcdbf62e725 c071bc9b096c8e911e9f6a4b05726b4bd8cd54ee358d611c0bf0caf467764aac 82126c2b00980c6bbca68944706644332100586eae865a99391c3a99fe206209 955eea558bb0799db9ee5994a88e8d323e27a63075def3cd6d16a2ed82359240 23a79218069842b0364c4ca540ca80374492d6d3bdb578515eb5c62935e5cdec 8c107f0b24dcb8d4d5bd749b90782be058a6665c71e09052e6521a5a23148ecf e55ae85f46ff1d248b12fb35c35df934f4da4865c9969504dfe03eac92112b11 9d4c8f0d6c14ccc7a9c9438cd11224344b31f50c9231fab574d3923bd2ab6276 6475135f9644ca979ce611a47ce21f55f16da6edc548a88b7f1f2d5cb828abab 3f78644f896131d3080551c3b5dc669884f66a90069fc02d0980c8cba93dab5d 032cb098c9caae12e929023e907322382e07864e0e03891710413bc9baa6f628 03f519eb0e73ebfdfc8791829aacaa3c10fbf4a69505e658abf61ee87b6d101f 8dccaddabddeba280e5df36ba751d672ed25f786c12a8c725f972b6f11e3c638 e567bc025376197432a4459ab346d82730c42b604ed31e27b6f16fdc61351b01 16 818312cd8553bac764c2aca009f760d68a45c0e9b6e8ad23cbda753edadf030ed290d87a9d7d91c864655460fe6b91f412f51263baad7a3fb9cc564556cfd403d41395a65b03e13a2a5a0d318f728c494548e83f0d603ef6eba9f0b30965f8021d9c1559dd557050df1aa1a2b7e2c2bacf2aafd842645871d058e273d4802e01e5af08974742816515cf26a531e17834ec7e774c7dd42b1b7e327c0f1617f70a9e5aad969b628dd5549c859d76f097e0b047a025beefd8f12ca947df02c6070ea06f65a7253a736ce1056ccb5e3ff713e451a85f97ce54185b54019708b8930ac2ac265b7559df6d5b13354b015c967c0227816e7a881cfe073f2d30d72b29014953ce2e87f4f7deebdb9d415a050e8f891e8059bd9c923d861b4c479386b4012c0f25b5c00c54989d377d4560ee99d973e57f90009766834f0765768e0f480f414f29416dd53d1da19c27cb4b18fa8e6c0af16d34e787a463e7fee3118ca90377b1a51daae573b5073d0ef6af05640f78317823f11be982016e042905da000d598ed64481bd862d689b25815e27a97674cb25f4cabe85803be0239bc1b2b909828417a1cbb97af967a3245657318f5c73cdc436738734bb9c0954a63879330f26551a552f0d9bd2fc9ef55778df4f610fa08297103a2163dfbe15486e908a05de50591c9e5c000e3c89e45d37dca7fb7d81e42d213b0f8ca6f1b57329f7390cb92efe1bda555d83f484ec9ba003df8e94e16a58b88de6b475362d28e6c2e305e9cbd35fbde879713d5f3185ba07f460f0ba71977fae4e1e8a78033da53bda062288073960b02eda2a5188b919342da3947017523a52ab1a4da5b421ea726e036c75a5801a209bfc18bc4e010076e51f68f557c14e4f41cfaa25a163bb4916034a0904e7d2f01f9203fe6e89c0a90158fc1cc11d9eec28f931916cd4e906ac09caf1c454d72a44f52e141d3a7448da808061b59c2b7f7fae9cb96f762377ad085994f63970df0559ad8f8a84ef17ff34d3646a87641935fe667459b8744a3f081238a79b3e399de8560f4f7f86e29ccb2285b5e66119ce55df50b8d86c926a01f8d2fcaee416919827b2fce6b6193d912d282b35d4176224da640ec70f61c406af8dc514634f852cd5364cc625b9b3bc6158a1ab8281030b5c8555f85cef4f0bf32ad788cc4e7bb0d506a8e612e439854ff7e8725779d89041806cd73596ed0a29fcc805e9a15aad6b8595f2c74b48191fd71996460563df11a8b16a6d047b096d6eb0dcf97c901246b2405d6e081aef854ee7513886e9ad523c8e9876f03c0da84e4da9a01b4a577168ea293f6cdc8da22637d5dcb9f33e3bbfce6fb42cab0b6fc84ada32d366fbde8a5c3a2275ad295a5dee6b9e69195f04f197c817c1470a4544d9183502d01ba36abd8e90208131c4957cb08bb7994aa66a61caa798940ed89579f116f86a4a8b3cc948265ae688cb6fa73774bea2d46a23b944c508770961b84c17e5b4e691558c902408a7dfba96df06987836467f71d33e219beea20aeb3404002393c1530f63991f175afc675a20cd4402ec1a1bada9e6e4853d5f068300314303312a498fc5a2eed1f5257b5d9425da7a40ba93283fed77766b20069453839299fec4eda12df847453a20f26d2c614e39c8c0d2f36dc08af23c470d0805c49a1a04a71fd0eecb1c1a39f95003892f1101daa46738247362efb94a06bfa2a610e52f7e798b3a98d0953f76cd8b27a58e492b1e78aa64abf30a316307292a39812a6a3206e8bbf7787d4a5cd42e60e9d0bf59e949c058f954efcb57040ccdabf5ff5244083e4074156bfed2640b75fc694b3e1d17f52ee37512d0e20802cdaad46c3d7fa436d6d8b6323566b6cba14a504983eaa6d0fcf0dddb53ab00ea2f5c7269b6a8b5796b55566c51de992166ecfbda52e138e7acf1dda84dff050cf4c6e9ec192d9d774d7d6f51491b676e8afa592e9a9dc52586d0bd7686f302695188350e3620e559ecae000c698292d7e81ec8bad50239c0c0c8863a85c00d286115c7de5139ccb1c889e2a5e6235bea499c04e5ec369e0e761e2683d5b8060036916866dea40d1860c5f6ce5980e8dab61aaa406b1fac146300847a089806d91be7394c54312dcb6bf0e218d88bab339298d8c69f6ee1ac1b24614784bd01c387dbfdfbb056e35a5fbd387a6a7f9ab5b2c24aab2732e4f25dec1d3f31fd03aa358c1a72587296086743bcef616d05fbb25292c2d3cd3a9da32b2db6a1700986338e5c280c660724497eb0f0751b42ff55f2a2fce5e6a93ef68d348e20f40386aaa3dde23a7936a74a47b632f8ac89bb7f32a3279d00022932f9c0ff32d707cc91c527a5c507cae8b4c904eac893879e9a09854f1688c7143fe688a35ef809bfc914f8a2dd6a54da70eaba6ee9440639458ab12234aab3e44ef953419b6c0460474681609cca8a841ba607c2ea91fd20976e421a2d340085680bbaac63350e02f48fd6a8c6799218416f698f13ba3e14ca3115aa96abb4b7e89f000115180d9584c1480b2616b9e7ec0d37c2eaf7eb0a2ba7e838de84281aa980bf67e60804f4955648d75dd6511642fd1ff772230bdb65f8e755f719789d1701c30360bf02f1a23132dc981fb0b897f2c93ed635311de94829f024a7e8060cc74714ca010ff8ae0413cf0f4a378bfd07323e318ad186f7bc25a833c5ed36d3209032d9170c1cc3a5f7953fc3e8edefbfa835258e322967ccb0f8241034fa6a36b93d3e5e0a7270c01c6dd4a3d576d464dc368c41e96ef686d31d846365e18b0822ee7afa084d4c276bf832f306d69fdefdc419dc4239b94019e8d108543f4668078050820ba13f469fdf41b088325fe90e1eedc2c03158fd8cc324feceb27aa745b7bca70eabb4cffe24e0b5fa2814e7f0b625eb0f5d4a005d7cd7528b9cb007af74917e0f20d1d9d2a1003962d3a6c9e33d1e36d15e81a26b8b540b35c944774a5109f7037e28452ade490c56e08c14e7d9f481ffb49f7146dff13b2e48533e54deb6040a8e710cce12434b5d11e4f7abdc7963528f42741b6b7a52bc1eaf81d0d6b833084eb864c30a01c60fbe36c4bb90410e0915c121386c735a7b59d5eabb350e0403b7489d204d5bfe8be85e75436566607c8ecd0bc8bc53cc41890d7b20b1db950982aee4933865a304aec8c81a83e49bf6a1330d0b0beffb133add63fcd9ecc400a2719348f1000cb9b296ed33ea306dc9fe1b5e639c689b9959640b70b47d9906198c4e3eba23cfb7f2fa45c9e5cd4d7b163aac12b139658795274d33a7f8e90281f78b40762225e68cc880f4434890df6c44020027325a8266ec379c984d8f09cf5319b419fc2bdbc518abe7740236853e691540a85717f061a218821f235e09936e427dcb532fcc9a9708c569587b7701652622ede9bb16efc9820e82cc2804d976a866ac237d4955f39e27c3f0cff435173e9fbd778237b64460e8d502dd013c97b8b863b888b40ec9dc946d2e58ffc8e554b0f4459c772962387d416c6405ecd6a9b167198aa5bf4e92075f00a93fc33905846d50182a5500253c9d93750d8d72ea9d2eef4b12a570ce1ae838dc902693efedb9c8deba1a24e4ff43f79906983b3b062563a6b359eb8ccca0eba1767eee2fb3a66642d8fd058d47c9b42301ce5d9ca6db48b8929e222b81b2faab5a428cc8b8f477e1e464ad62998173240a03795ae90f21c6dfd19bbc9676ff9bf07d97dedd957fb71b96c4eef3c2b3a50bed78ad13967b339f1565f682da373ed3496d82be68be00e59c81e495cb089501621e2e2675a2a2d2f335808ea4cdc236823cd6a3868de639d5869d18a34fb307d9ac341f8360e85fc130bc6b8755fe475c9ac6c88854d7f2a33298c2d9892b043d1d66008622f34065e4d837c2444356fadd2e26ece01a6259f9b6e0c4e1010033ffb401f4056724a07769565531a0a6cbd73f66bff3ebad1cd6431d33ddc90cd904696c52c71178dde83a27601fd186916d781a44f552c957ef234b11378005e293310e3194c0ae6e0dfb764085f9a2372da945e01b72bce7033238e15cf20f62c4c9134b9187de1c5a263f542f238328842b4e126972e6a3886385582d980306e07ea52c75618229ca83279865fe5e5a1d611f2efd285deb8480033ba8170fed74e9ead22c04d1412bfd610bd320369105bca72a00b4bedbadd16a50d58c07c84018e0da506ec11ef232079fd2f9ac8d62bf4d875f2dc8bfe62dad52c7a70bc7d6b6c7eb6160a6d069c3c596a33d5647a14b5d1461b41c550d74a9744da90b783030dd3c2d2f904261caa44b26064b223e071c99ea2b5439edc42521f1ed0d52c7beb8027334a223af2d5e2055c1c6b9eb43c75389ec246b82835677d6970e121646e85f7401e30bc65266ea2164eb6d8534ab3827a9360a8848344ea27c048aec4cdd1a1719ff4cf8075ba4f4c3cc522385e319157f444a00ea63d16a470ab0fa44153fa0d211371acfd5c28d85470ede784da43ab32e79e335176ecff101968e9e0d77e45f9efd4d54368c33773adf9f189a0d4b80a2dbff98b1f67b5404aaeb17d533d9e0957adaec0e8a3c8a34b168d437485c9478e7c4b19c51e6810c86497f36d454de4d95413c6d02efe3fe638c65b4c5204660f7366f2358ef7202b49feacf535dffd2090db55a1f3351825d94b528db11b4f681bfa7b3df42f80d4502f7e864021ba6707cadbee6746e0b2641ee0692098ab45e509b37d795550e0c3effffc44daa7227b6b708a3d628498cbfcfe13eb0549e098de5ac9ed9d10f01a3877be157ba860ed9001ad4a68b2cc035d2c2234810225c57ab774bb1f006fd438ba034cf055e278b86cf584109f85854ffba9de710b68c3f835de3ca1a0b9aed77ae64f4d752fcaf489036d5cedff31036a40f3b4f16304c6a31b4b0d80c77b7b5ba7f8656556a21a856538cfe251baf3a5dd820dfb2c1fb453f0caaec020e0dc0fadd1683b92eccaff087dc9fc6977b6f639ed2eed120e6ecdcf2880c050296865c9cd088ee84bd52917fdba4bddee173346df948cdc89c64a4b861d5084559666c6ff130422d0caf43db44c3427a4d5657d4226ec51158b690ec6cd50b6ff6a016dc880a687a10f20fcb2057317faac6506dee3f906b5fe32b8b416c0fde397c8750a61388c798b2641d09f0bfacf8a071bd0e32db64458464967fe101a3cb5bae64b48558e1bcb6d01517915de66c140f287ad79c39a957b20ba6f30fc36303c1cffe0f37606eea932732a7cce7d0c8a3e7f56cd254c429f8634f730d2652c9a6d4088ce17470bf650649691b980533e671301cf7a5ddf4dacd2c3c0bb972445be569528ac53f5bb3e0b426af8ae8fbc2c1b0ff626d7670085fc75a098a5c7d5cfead3ab28a57ef6ecd3aea2b66c79b6bee959288a9f6e3967a06010070e3433961e33ad162ea260dc5235cb51233e52ffb770dc922b361b47d80e6073c1c5cccb26c0a4e5d7af61ba1d6ea820cf3859595c3d994f16fecf1826eb90b23a191ab80ed8f6225282ca112f6518649916fcfef9254d542e30ef2d76b1800361d6fb6a9c559096314875aec90b1baec12d4bd8e8a5eafe2902ae146396404bb7523b81d55d59ea7cd196065b89ca9256f34c0878048bc7baa53763fb07b066f59bd9397a9ddafb4986fb5bdb5c6a68b52ee9d88412f506917a69d7a098303de15e1349801e828be2f3d46cfc51f4acc60d3a56ebf7690f6ec6e62b97be202922c4ee870906dec7a7d81a7575f62309d191979eaee2dd8868e338a17b18908ac26cef563b488c775efb792bcfe501898e4b1081f5d8168f43851ad7571800cbcb790963072d28accef73fd99da11a180a5e73c3b136e088dd3109a87e9170cfa181cb228d01588467846faf834fa8caecb758f39910d8e96c21432f2d61901560d6084e30073bb63008b25323457828048a351e39d23577ba982c29dc2c9084dd3de94dd6fd57d3713969b059398bf7ed6f3088688424e03bf0f5ce056110dbf84cb9eef5996e1a2a934a158c23a8bf009fa8ec1e6463ffd67db8628bd8b0e997f21300fc9aed4008581b1d67e2a5afe9742dc2e4179cdcb6df9701af3fb06a28007220cd9f8b83c811b86f8ee31b9f8ec9decfee25ec0cec47465978c8f0035a90e7e02cf8ad1ddcc3e41af3f90a78b0f5867a3ffb620aa412217dc56360642d86ccc9a0d98b0d9495f150086f5fc5f20dc09b734aa640faaf2f6b6247a0ef18ab7835892733f1716de94ebfda388a9390eef1f9338238a131aef374ae00df939552ef1075de5a600f917b0f13e69186a075629cee5a3ebd4da6081166908330a6288f1a53ce312275226f5aa382168f5ec6444ac8444048ce859df7e820b4f50d9ce8ef300012b227075e6e2a2cb818a3eec6c6d6a5dae8038ca3f9bf504267d9ce0c37e69498039124891027c11278fe22774524a0932ed77f99d8bac0afa523094a8d0ecbf6b3930ad084f7cbf5dfacaefab0e56c27a1becff63260208bc624befb99b5b5f3e63960941f370d70afd8d513552640978100cfc150b0601e584d598e632cd2fdc39ab91a0d5cd9cba480d6682eff3389a2d3e168eb76b0bcb2eadd8b48e43df853309d2ad2783c76e50e6e1710d48ff8446a7640073b700a4eeda435047a1fb5917137db4c21d7d2a46d4e6249dff862f0f8cce3a5e1d099cc25a374eb88386ed47152f1a6d67fd1be74d91a23693eb7aa6d5bbfcd8fb0ea587266278f698a6500c4c23fe8668d0827c05de246d2f0f59bb005a3933680d214d1bb3cb624b226c21e803ef2f69cd15bdea593ecd27a2ce550b1046eeb50d7f4e7fd5948dd78a109eac27a0ad76be9d25aa229dbc0469eeb57a170c9c6e0700d7414dac696c2e043877cafe52d3f3e396c64134b1dda19c85e8541a73540b45b068cb3644afebce94a24ab65888834476fae8d6830eb7416e09787a9b1000fa17e7d99b2a3ba5322bf100cba7285accb4076dbac9585908b044a925101c0dffe83e945403fdee3a8aa97f5acf6939e6f9893244e4459df32dab4ce705150e0fe137b81018cf05add94ff99d166b3dff07e9481bc7d36045985f5ea6a71d01e5dc8a06d65801c31352095ef736c453456700b51e5334f7697398ba1f9d450ae40892eefff78d676cc3b291aeba484d7c6f101747326401931a1fffd9adc00aa637ae784ad424e1b1a912f3a7267706d68370761f3fec379a2c4f1f2bcd3704db2d17db46ffb2bdfb82c0e6d6e742cb368b39a4e76f663d801004c31ecdec0da4eb79ceb526fe005ff8cbcb33a7cf3c8fbb6792fb5fa7d3878357221997d8034e126bfcd4884f8a08557637bfd2546b7cc55a3f76cc4b1f7ddeec632fef7c0a16c92bb4c42dd3cc93dd211f1e44e42ee309ab5f1be2b33872a3e46df8671a091cc70bd9db3be7248a4acc2c39193d448cc29d63be907a10041a25dc4a7dc508fcd71212c351039fb80200b7d031b0e098a3dfcb19627ef047ca56cc5ba21303a0279587c03a87cd1de30e44fb3d3baad883e7d5381d469669b19d38800f7e033e1e78dca43f7ef5b2e58a13cd9df531b79d6d8855eb711bdc52258a9ef81009c07df9bb9fc3a582bdf0609cf76853581dfbc7c068ac8e47b9be82e7cfaa050f44438fb534c08e84bc3052e130e10f555b85ad1e191f180042920f9e4a55cf0e2a6403c5eb62502835dd66bdbefea6892bc4758d6c505dfe60756d276493ce0c1a4304b4bf614ddb558a841ab7c08db5b4a6d721b0009b03adcec52e79b90f03c14caa0ce55af33efa8cbd9cea826a4df383b0d5fdcf0702a640e99b41a077015b84d7415d461e0c3f1be93b544f5195f775968221df61b9d686f14c35552b0e8a1beaf68827c429e578b5b73a3c5e2c5f0882cd3502e93b51d960eabcf73107f030c1e9dda3ab056dce89f86a5b246edc40392bbc1384368fb7da7a988ae50d3a63dc437e03e96727f43337775dccba1e38c70af957b94290fa2985231f4d065582a14a05614ad207b9defcabc16628cc04afd522a1d7d3d8321ae9c6311a0541bc7af99c98196fddfe1eaee74c3b1c9cb033b77fbfbda3342059439fe9e9029801c15743af9341d3e49e55c4bbbdd818b1b126763bb899cd1c78c62d7e220ddd1231220465d7ab33e66168338a9939ce17d415877437531b3424b201c0d4065828734aab0415dbcc08f019b55f5b82215bfb81077e38831dadf4441ae0c504394b7e89836939ff2d594880612f3dbb076be9970bfc037c88eeacfd25a8c003873383523633818340e4783327cb55ee182e056535816c4fb1dff9a42997e308d09bd6d61cf01e6523c92b59400c0adbe6d45b0f9fb7a13871e5779981e94b046d7e80484f5f1611479fc592033512ddf3d0469d104ac149b0968c3ca4849f04b2ee55599d73b29b911175b69e2acf20bdffaccd1ac62336a67755f107a4cf00b117924e05e5ad2ca073e9fa719003f6c0c325575d4b6b99c469284d1dbe54091d16dd8e654f02be709b8e6f58e9f90a58c5c53710ec4dc8dfc136abf38ef3033c1cbe049f2361fbc192a8a3467159b9a3403bc608592ffc1fbac9eea8148d043cce444bfa2716cdab74bbdf2e43918e20731ed1b6f2eea45676227552a69e0d5e32ae384626bea99ed6c775943850d9883730248c7fe65cc6e862e7093db9082168a910480bb246aa6c08e47ef9376eb9b6ea0b471a8da411eda068c79af5097d8928fd852770e8afc67936024f1eb489e610da2a816f5c4230082290104b0f023a2c810981c26d9576146d44ab5cffdc414a92e309a31a4cb78e2da6720a0e4eb3318e6f58b44716885449175d8fdb343ea1d96bc884505a4636d49214a00f3dab8c48730000c4037d77e15ecdf1153fddb97e3e14938b17858aff4b892b056d28fb3284f370b94fe9af7a319d333eb13196aa4055d529a855d9976048130c24203da087b5e91aa9df7290fc93892512cab93309e76020391ed56c0641df015c008a9dc2b95fc44f8cf0ac69be7c4603948f1cc4b5072d19cfaa966f8cf507bf9ba5604d6247d7b897d0f32a8fb035b7dfb5cf276e42fe0b7442d1f092a1049a541fdb1761bb9f54662e80b786c027da502c39146bfc5287b5abae1721b204b2b9af8a8c178937d6155fc88faf7f1404e91cb7e4d295d8a8287c21383366058f0306529dde88ab8a8c9b6ca3647e0a4539c9f479287bbea67c29fc352f5b0097fd382d4e0d68d10d85eab181c7a1f43dfb5709f5bae0adf30b245fcf25f407086822d2ec8cea0e72ed4fc1dd1615e5dd2b79b28d0e9a97914f24ddf85d930c3fd0335954ed4c83bcc9662297b6c32dbec08fc303ca208eea1790252c838d0bd3fe76c6a91165051a39d775c01d65c2d926bf6f250f6abaceff71ed884c0304fe05a755cc465b3bfb04afd6eecf0966db8cacd64953969ba2f688f5858a32045692d0b393cc68de8f9e014c9f8cfc82d18cdce0e2184345a4b3eb9f0992d80966b9551d5a8aa0866beab77120d7b18c3b8eb943f9a5bf79a5441983bcc3250d9a095ce348b263c67488719795c6a0261f0296d85b5bf9374040274da4ae320a5d50ad8f96ca0a5f644f837d55fc1f11ed451576ed2feb697814c5e72f48340d813e48912c75000b35cd14a0459e90b63ba21e2a7fc4f3cf69078931ecad0a0ae5fb72e7f4c4453ef29ae2133ac7c0aad70afad5707b28e657a76bd8daacad08f58c4382a374887182e8e167ba2c09a945ed23c3938a4e806026d53b01186508ebb44636a3a81c6d88974154bcb981544893275401958de595867d81b13f730ddc9446e1f18ece26e0ea789caa8e9725a4aaa277dee3be0d6d3cbd65bbef7c06c973dfaca004dadb831abca4aa30e7d318fd1dc05690242f880aa9949bceeb0d5bf0620ccefb0e50f709f99874abd55deb8432ecfbb91426d4eebb959ced4609ad0681d81c230df81f5719e8086acb122f1cacc1a2c679a2d27aac5acb26a909c986a83890a49b1bbbeb67f1aeb77208b00a201d70ecd60f3d5e51f87173410ab3442e056fb2845748e308daf5dd7b60aa6ea973784c08913d5e970f32e3160f65947585d6abc7034ebe1baa675487c236e718a0e4f92f586a7d415b46c52e05f46be003058d4fa734836c07b660024ddb827e0d81b7f836bb3deec6015eaa004d4808475ee9b1835c172801a0190cfe4b8ef3279e4ac3dca3a95f5b13884006c52169cc390a884c45c7fe6666ed9a068c90856c94ffc8cbac0530ef5e672e062682d76d6d6335a0abecfba8a82ba69b7b5a26a2816b8673967d8d56fa5b110c5a0d59a5981273aec80b7d020e55a448a7b7cee91dee0e78933cc6ee1f41090f8caa25915905e576aeaa3e8f2ea92cd989ec2e18787996f772e119703d80b40943abf8d7135ccde0324292c3b576014ed5289c6e3c7b5a77e8711c4433a3aa06e9f5719f2a7e09631a05a4ff817db2d0546c4ae6217810dda47e5f6309928405ea9ee251f0a32f4510db2329585ff35810babf02f3c7dfb6fc22d68f5540b00817c00512526b92515e0600797a57c38998142709815c46e36315a77e6e689d0e3b8ac6d2bbb06f1a0a4a99c45dd4033b7ed8d04fa3b1e84f66ba63c73ba6a40e549b5384204930e89dcb0bd0f41a3ae7f937076fca2050a65b4e4b4319625c0cadb73a9f83389bebd8ebd89134c027cc197a55c29224de9e07a284f539fa1705db8da16b637f7264f3acfc0bf4005bdbf492b970d619ec7155492f8f904d2f05c0848a739fec2ca92543777cdc1dddd7d5b7d870f0ee8c2e1cdcfec75abdcd01664ee8f4b84679550e782481c4a897e9ef91ce092cc93318fa74e2c0a3104806 -generate_ring_signature 9dd907994196494b8125e30882384a88166cc89ab3d0c91f6fde9e8ecefb5e01 90dbda83e0a10b0070bde90aec62e4dc65910a922c21ce75f37c425cba693876 1 b8780402a1279c031fd5dd4cb89f48bfd15b5a8dfc140d9fe0eae67a51d18df5 5631b1eed32e0c03cc92739379fefaffc2389bc6059c623a2df77b13f41e3209 0 e3e17420d786d08aafb0db583d180794310b6ab26952ccd3442358fb72ad9f097a93adc1ae1e707e100277e5d049f0907a1210cc37a692c0da852c7b684b3309 -generate_ring_signature dc57ae672f6691bb5adeef2f47e8eb0cf0c5af0d06d479a1b1294e5b3d41c06d 3025fa55a862d8127dd4c6c3d757a2e555e7d50356c3028f6a0027aa786c751b 2 e6ca090d9d3cad0b144faed63a19b9f263b793259f0a84d3465d9567893893f1 ae20f4f7f9038da72a39b4618b1a9032d77bf1787ae00632e19b50051db8de04 0c51d9cdc712d60c0fa724e226ba82e337451ff47b69da5acf95fd41db1d8c09 0 3d16afdf2addec448787b2371e0c46471b063ecf805ad36f78b8ccf0dc2d3a086f3cf9bbc1f2377d030fcd11504a40d992e266ec843e07fe6ab201670128c80243ece5700864c385d093520a063053219629bcfffee6c2d16f1aca8f5cc35c01edbf3e94a71b4a4315653b12d9afbeef726beabf0f29b6b76d13217438323500 -generate_ring_signature 2e3eccf3241ad759efd0759054ad22f235e33e882f8b3a0b8dcc2bad44cc13b0 46083a5c582071ccf8cd1c9f33bddd7b02328a1d68cef46e82f41baa171a2fd2 2 ea16dfeebbb925edc360cc2034ed4a7c45dbd9a2ac5c2699cea5d822a31b6187 64c01e0efec188fdb60bbf359b073f613efa84fb51d764cc716938a6e3cbbac7 1742543972b8075a2df32275289d6be641db11e78bd88f72215a5d2376203901 1 36c7583ed471c8612970da5033e94d7e40b8ea94504f48b0d552f4e9548efe08b76eaeab49c551f6e4d318e1888bc33cdbe394d0214c41b6f2a9373544f39e0f7b04e0b55e33ea864b12bb0a7897f04a2d224f19edb2c9a743305a418918680a3156c3b8028a0fb3aae2accec272932413e75b5c6e19a42629e3f44b76b61407 -generate_ring_signature 5324c8a8ad37bb76e86edb6127499fcbf161e173ec4cba0d426e25a26aa7c2e5 a3d91b89186b32fb14d79601878d9b5cf0289b0ac68d19b474c86f4288c8422f 1 ab633b5c1c80ad6bf183d24f4f37eaba1c4776e8383047290503e920ccf3ef59 a7afdd093c3a4e7f64896c7fee5b6db5f6a57a6f14c04f48df5c4a4a1219cb06 0 765463248c1f9976535b6160effc3d8ac895d41cf27d38e8da4718085b103d04be968d56d80159572c67703c87eb3282569f3c52a533523694a03e2239f71605 -generate_ring_signature 9ac64eb93443ad9fbc9abc23cd255253d3f61fbebe818fb9436f2f12397ab717 0d24970317c011442316da2d75ce0bb19dbe3c33ce6efe6495dd185ff0b77a26 3 29316431df8bca23ff0440601e07bac7ca40edc4fb0f948d1cb5a4e62153a1b1 3af36e933fd1d37481499f583155fedbec8bd3e131d278a28b209d5d6938ed7f 5ade6caeaaf734a3f6435719f88871b4094ece978b37ddf6b0554aba023ad626 94c2c27e71b84624c2f55761fd6b36a2f0f835a67fd12bf7b892dfae86c03d0f 2 c03cc94609c87875401da849432e482449ae53ebb44940966d4f65793069dc027fa23a5ebb603a1729a86e964e5febf65677d38e7de8ef3947c156608101dd0b867f4a9fd07e535a152f6db6ee3488bdf6245444c52d7682b146b3da79aef2049591a5d7eb40194f84d019e18dd626d367d7890f59b8aa7e2d4d8ff4fe284d004e6c3a86e85b41ceb4393e2eb45242ed83b0ba6a08b2650bd4f851b1d3cb5a0900b00ecada1ca3cd2c0b8882e7c8469823b9c2aa327c0fbb485fd657ff4c3508 -generate_ring_signature 733c77641afbcb27266517b8f24262be24609a4729609ac2bec71b4aa86f67cd c2474848d390a19e55e10d80834f6426d2421d3c0d9348e81312b9c644072e79 2 5eadf01c62bb7ce2e1cdf66e49982fccd9965769d41846e1526cb9eaf2d15395 ba67c3a77e88593f8ecf2c137cb0fac4ce7d2259010854396991fcbefde294f5 c3c9808a7c62b5542b5c054bc98c5f140820efb26aa6adc2f48f4d0550536b08 0 bc9a215c32f1cb318427a4fca6e12d2e24726293b5a98a608fd9609fdccbad06e8f130069932a32fa2fb4e0fcde31677a77e617c14a5bb983ca2af358f5dff061199dee6b9c040c9de8e48bbdc5d9b5fe703d401d75ab92702f83fd3b7c54c0c4a7f5388c1dcef3e9605c9cc0166fa830695a6304383e3e2a17b233186e5680a -generate_ring_signature 1792c680135fb955b884861240d9c55b6ceae3a130059fe1b3ed2e9ad5a9de97 ba66d0c9bddf46eca50a3205269fd2c427e40a9ca780d09d68b953511561b396 5 bbbc21787e57aaf4928a2de53ad1d1c7527586f1f8337b1f3f8d4d37fecb35ff b00f959de68120641ae043cc9640ea2a5fa040ee950858c1e9f16b427128a212 c5d5354bfad3251768658323c092fceb2918d8a700557c79ea5fa638c18fe516 e731fbb5657553ddf378c3d60e0b12b1a5e375ba1154c6b79ad6d276e68f75ea 1936e101b0e7612be29fadb4d8a17e3dc20c44a7f065fcccb1f372bd8e3b0c19 747205001f75da90ded4f907a518903090940432f8959d8ddf25413fa3381304 0 be388bdf42211c52634000c68ffc522040c889339f3f9fc713fff18849a6e50183e72bdeac7dc201ce9240d31e046cbd3f211253723e2f8ac2d5436f8b700d05ab9371f126709020928a85fe94102f8508b1641922f5a5b8657bd2322fb7eb04b98cff5d4e0129f5b3e66213a42f42f50e45e414018ed5e2005722e7222f180fa2d4e4eceb08b7516322209a8fa61a533e7c327a542ca7ddd0eb0cc51b65dd07b468e2ec7be89f8d61d3216b4d533b69ab8bc7308d224708f7ec713ed89de90a5cbc132c5dfa27d4d253ef77afe3d2935284840d019ff78b6172eea4a8ca5909435e89e3fc34b6a35f9f017e2c91d0405fbe77b99df628be43cebf79361d9909469ddcf9e6729df07da7024731f0d6d1fc35ba29b0fc6e265cf8119801d6c90d64f938eec1fffb3b11a7146f979944170da4223149936e20b2e89eacfeb71303 -generate_ring_signature d432ceeb293d5ea12e583f0e6a858000ee675b292ace24d2ad53d641988ff416 03776cc64fcfaf6b9a23a85f9577bbdd429b653f732b43a0e8f43d67efa63c87 4 200d574e962228bc5b74f2785ca3aed1662541f7300c818a4907279fb763f5f9 4c89d8fa1e9ce61a0f8ccb300b598c795baa7dc1aed979f22fd19958412c6fc8 287c5c314c26c80e50266bfeba4676980391addedde9789756dfaf37f5d5c120 0c294071658273a2f36d3bf44863fc65c8732d46e5f907c4b68ec8aa0ede4643 4ccc770ed00b9eed0888d3d6346bf28324e98418aff1d7903daf2ed68548090c 3 29dc937dcba837e605950f9e441cf7dacecd515f8a3df4920d57559910dffd059f47828358ebb5cf25a78ea3af7248fc6f615641a23252ddeffef9f3eb96ea031f94ec7883d39ea6edcb6d63afd8efed2d39e17ac655b81ff63209cc456b3603fa4727205e613fe4f2e09761bd0e2e7fec4acca582a17ef208f250556ea930081adf925e36f15f031ed1a91ff880b33077d7dfb69d0a0dde81ff3bf8b265df087d8d8d3f76a993480a00dfa24d3baf594df68a136cb341c4cfb5fe057b413f0940b57072f697aafe698ed6651806a452f58a4283fa3d264ee9cf049533bbbf099312c28fc2034fc6d4a162346fa3e00c33391667c46e50a6229928d68433210d -generate_ring_signature 5de707be4d1ceba4a9991eda597450d72c752ffbf85f714725b7a53086c2d611 ad59d7abf4332dbb03984884318194af02d41844ade4e9f91dccc65be8467abb 1 a2103cde970a000902d7bcd98045d5a688cea83d1a0cdd1bdbca4c087249f11f 6eee07f5e11d2601d7175b90135c8328c797d5f4952a125a96f934aa82aeb006 0 4181bd761eaded0ebbc3b8e7ce7fc2f6fcdf842afe478bcfdf96bdcbe464b303b9d5cf86fa9e6f75c99501fc3e327d94bc56d94dd1d16081859146c94696960e -generate_ring_signature 1516afdad27c8277ff77ebe9cc6b9889061ab85d504c7678b51d1b453e656f4a 77eeb7c8666282fa03e473416d2b495c62e9b8423bd30aa054cdac22f0173b75 4 294897bcd480edc6eb3f302bec49fa75aa38de4ea0a5b3ce458e284477a4df2f d7b3729fc615104085544ea277352df10f43e24e8b7f47469893f34df7197e95 9e4ab024bd6a82f3544a941c0dd88b2985601df873cfb6c82c669562d0ccb2c1 768ca9255bad7ce9db858bf51271f6321620424e7e24e5422395b10e3fe48a04 7328152575f971140847e181482617d1220f0cd933535cbd8a5492e8c857030d 2 1e21afbe9950b0bc98ee57693e5c62ecc2ad3e8154491a6f1c567ed277461201a1dc25da476c5e6952221848af24318e94b6297c80a82a657824539de6814b0efab54c65e1111b735cfee5a90b76e429dc84206547a3a73d42ae322f39bf3d0529a8aae101f990028b54615d20b957556feec904aac2aa2bd2cdcc7064be2a09ed5a2b89e4b5743dd24d6ed4c5624b3dda88db6922e625473fe751ea9087580c046a3c258371e23f7e5a53f5dbcfb9ffe6db119ab3b0377b1e21c78fcf737904c54aefb383d4036d11f800c03404a0f0196929bdcc009b3ed3b05297a99c970ebf9322f5371c9f6009688ba1600d1789fea18c18a197e1a850a4c9f3df7a7a04 -generate_ring_signature fba004537aa4d6db41185d8c4b12b3256048480c65d99eac669d156968585162 ede0caa2b77adaa6a0ff9cb917a79b644d2587b7d3821e5632955403ba4c9d68 8 62c27334f32b1587534ea7810f3356eec492bbacd7c6bfd2cc91b084dcc38643 c6dcdc2bfcfd81b385864f46dad8d1a1f608eb4d5615debaa651bad8eeab6588 806806bbbe254061c70ae2ab54ccb2c10886f792d9b3d0569fa9753e4c44562c 9e6598f7e3b174857ae16fea6948156db8093c3f991bff0da5a2d3c8f302c9cf b4df03f1889ac5a3b21134d6be2deb378a4c228af70a3317218fb34acb3ec86b 00262c572aceb403da34678e64368766aa091be815bd42bef5db81946488b366 c77fd924daaab02e4f95d653c8689ef3d3b5c71fc70825483bf36eab26280ffb 9af7b0c4033b7f3a8de1ce74f80b1ec03fcc3b92f2212ab8ee5a9c68869b5995 404d2882583e961947d1903d8bf28d3ee2fd467f01ccefac2d2ac3431ae30506 7 bd7910a0bc2f158cebdafb9ae577daadab7160d5a3a4bed0f63064308cb8e802f59be263479ec1b4a7cc3514dcda06954513737b7d6afd30544cfcc548ec7d08a32249e0411f75234533459be0534b730f82ef24cf49b54b8d0e67358d1c2c0a050a87e88e745b0aef72da495d72afb76397b15bd6608002802fad039657c70baca8dfeb3ae93709762eedad733ac13521d5da1aac34833b2d4ff42a10be6b0e514f401001f1c4319bf29f40f117c66b0c5788fa2de6a9830ed970c8719f23062ec54f1ab3d47ebfa50cfc9895669390d1c09cb553e2babf43c3db252c929a0fcfc2a1c406c2a8574b9a49c728e4701934a91e59d3ea050d0c6a34c785d6e30c695bf977007100a2013474c7e46366171697b7bbd3e049917f86a2fa59888e01148d356627024a4ceb657bd5562f87492845f234f09db51f19c5e67d4ba61f0179a23e12fdb34b15a16d39b9f9de4e4a03353a9e9480a782cb984cfb3d815e031d8b648a8d2dd103f9db0b321d2d43a8d1fe84f98a1cd7fd36e74381c6e38e0717331f4379c732c010d0deb02cc63893f973ab5cca9a2f01c97a3dd76764200ff3a5f78a3910710c4e34c41230fcfa77b0683f164122baf65a43ce3a5cc58d0af6ba33a62ffbdc5b9a11293d46cb43b4fea07d0dd19414f6eb1cf1ba6dcebb0d51c939753e8f67b08f84275340ad941c54150b6751e3705e4c85dd774af56f07 -generate_ring_signature 3ae3d9ef2c81e08c3b85166fd60d74ae81f1be0abcac3690480a1ad0186e68f5 27e97d10d75e9108d8c4e89e43ba75a843f4b250b3873aabf158a0379f55986f 7 1ef624898a6fb35a3396c517f90afe615d97e1beb426a8bd63de31e3f4725ff9 db1b81edd507d1773035e62c458b4597707bd5f7abe52f6503c7e94372699daf 2d0b80fa6db1598fa34207dfdbdded71c01c7a6e0c48a9895d103ea21f88a765 b75766e4545583a57ba86801b55b63f7f7c875f6ccf2e567048d191230901a02 6c633936bec4bc1d110cd8c1ef9ad728d43871ed5c25496493cd5f853e871b42 37426776747c40a3e60b35730a93d3aa3753431e7d8dbb2b61a5aad33ad8f6e1 79ecff41ce5665dcbadad024b05d9e26f9e6c7b9a7d10d6d608ff0fd4364895d dff0e02f69750454db98ea1c0486d8a27a105362ba9b8679b0bf2725967dae07 2 deccb28ff9032a67a1aac0c4c0e3e0b4bc56a86fd342d36024ad8c72398c580acc594cfd86f3828b70dbe6a20269617537b43115d0681488847674610d2a23007ee786cc4a1d833d446047fcd6aa100030158d60f1e35eb6e3cb64acd7756e0411a2e376a1d1c6d055885bea1717aad45dbd3c25340833187d6710f04261a502c4d9d4757bb719bd0b9ffbd39cc2c8136126333fe1388b35e60f5d328c3b8a0441d4324b7d98cfe53a3ff9c34cebab953915a0f086cfaaad1c69367c60a02a08a200f94ec13a6a4c5fe059d682cc61f8606cbc370ad52060b3297e664adec70160f308b42d4ab41c82c26dad8f57686251cbcd5fb4b4b64c631c857e9ff9710599dee2fa471b50ba8981dfcc5c270a67df5acc2dedf010318127ae7bd358550e0570b3ea79b85615c44edb393d3191216f6ae6bc6de1a03fdd00a097cf24950bd88ae2ca1bba92ee207186040eb76ec6c6da2f877e7081b0e48cc661096bc003a3f4778e2f20e34ee38093f9ddf03f7c1589549c606606f01e912fd2705e2d0882583a8c640a3daf385ac7995b7d0f6e790af5e16f7aec2564a2516d8dc2700fa69930edc68cc4bfe8b15a94016fabc986e5535d4846faa0f6b6fd6f89f5f700 -generate_ring_signature 5ee5ba303fba3f86f72178eaf964147c0f4728181baf66d0d69886ea57304f1d b252f1d78bbe4179682604610e30821f9a161cd81ce886689a1aa9199ce14c19 1 cf0e634f021ae9a7741780f42dccdb7ffb0c5dd00e99b208872e604210ad5926 ed4ecd59c016635ae665994d6a1698ba6b39989fc31bee19aa099bca24bca605 0 001a778568dd97e3f6e3d1f5d073a5f174fdd6ded27b267dc0b1630816dc4d043164193e36db8e80e5406841afe1b9ed379f13779c6faa8ed71a8d18e7d3800c -generate_ring_signature a168acafc3f3634fb3afb2fa4c85302807788e0b1d6db633457c343b83d4ba02 2ed829909d69d8bff8cb268783d3e844ad3539ff90fc6bed846c15406c237801 3 8eb8412c40ec4e21cd9a4fbd2d7298232370a4ba83ac5b0d1e316888b817b511 badaf9725b5d536b6f3a66ec3ef108a4b3115025df7f43e7ab249f3f58059f6a e30cb9b423f01c24bdc64c739a31419cada83692fe0c4d64fcef6bcb1776d592 7e76841378d75e2606cf68cbf75f3f3db2cde74b2faa01a701a3c432ea191c0b 0 7a99869b5c979655b5263ccdb4c63a26e332fcf5822c5905a261c7509556d30e99ec48c2e5244fbfb3c8aea94886aaaa964105559b4e02d60bba7f8eca137f0b2e82da4609f47eb803f442a3a6375c9e0b6797f0b9b858e4c1f46f3ab491620d115b42ab21664127e12dce3ce6da36f7bcd00b137500a9c36aee81dc4449570da5918134b6462c76ba245711478f74b3c5d2b5419b4c7bd795b4cb86861a8b09be7ae7af1b12d704d53055587eb26a20d9fd0f10e69144a746e4e44086ab0704 -generate_ring_signature 76c197a029a4979d0388b7ec7e68ee11ccbc66a8c504502adb011f718f46ea51 b1490f09967c786694043061f7b498ddb9b064091bc8437ce133d71fabac2f6c 31 72b83a2fcfa3b21c53d07c617a198a000d5c4446bc05f142f8d42e94938d3c89 bda3e253729f9b6b189e923f6a5cb3b36163b06e8e2e5c1c6d685cd272ca0ed4 a706710f83c922e3aab795c56883186dfa8dda3408ee314f04816e9b8fb92f90 5c0813cb343b1cb1825ea4378014a6953f5884a8250d5766b23a9af5b43d2dfe 506171faaf0ee551b7c2dad4b1a4edac2239be4e7fe76479cfaac59551deb880 9e58cd307a14f6482f0c00d9342fc0b08776deb879c567b53c9a5ecd58d96364 aaeb56ebb9049870bbf2c68ed50c74c74f738c282da33a5897213c7e305826b1 d0e9a71c4f7b38d6e32f455107a814d6ccab122a3d027f320ca36f072f58caf0 a7672d1d2178777608f058280cbe24887cf1c80d54e4d3ce8c6572600887238b e550d5bef941cea97a3ca5587654794b2cc95e4ace85043435632d6fc9e6c239 08eb2a4f3d70a4e70bfb340724fe58e71cf75de3952c474abd8270a1a4145c67 4c69a16fa040d1904535fc5addfa4ea00c6478c97fcf349094fa4cf540fba173 844f1c9064fd2337d653c08109662a533ca1ba3adf29f71ad52fec1d581df0d6 1f38c8da9e1841686caccb994796b0d462db73db8bd5b023f47438da226212d5 b0a333c00453586b2585617916edfb5d7c1e0e41a06638e8131960b9058e0486 3e1ef31dbed8e4ea54aa290b70cbeb6674f2edd2f1e187634e7489fa52bc1d68 cd5dacb09ceae7dbfd47d22450197370322d2e34c5061ff0f886147a4cb3b444 90b87ee3103b7ca76cb968e6781417438fa9603507b72d5bb1abf1157576bcfb a8977f55e6aff38511520a9f07959dfed92a336e0aefcc6d10d21bc9937ce18f 5efc3ee01e44a3a68febc8ab9dbde69bc47f943de706c9e1309718b18b66d7fc cf1fa8638d4113d43b9a9795c37891dc10d1f6bd71919b014529f59cf2bc0d6b f03eb4af7517879ea5d377e49ddaaf2533e4a1e61935ea0d857fdd1387ebc899 763c9a6765b4b5ac7f6e53789392a1ffb43a0bc850707018f6419ee7fe8c7d0b 8a524e3d21eaa69a18ec74a26dc2d2c6f93689abd3fa4ec469a9effa1cd4bc89 8b6581e491580aead5297d1415c29bd12e15c79ed2d0bc2a25246b97a8337604 7540c5547acdd0df7dea03b49e2cc77d255385817bf3cf6ffce2caebff519074 45dd05c9ed02f168c67efadfbffd2a95f0f1cc84f4292826083bd10dcab56b14 bbe9ed0564e875b45735b0fcbb7e52ea810e54fc1f8fc7e1c704a16183f48d12 0d8c787d3134f90078bd47ec104b03ad4fac9bc6d61673c780fb445bed6c6da3 83cac99ef2be476a29ed5a3af28a348574576a086eb5ce2afb477f5ce5aac752 d5d7bcd8f0c14dcf5f621aa4f9dc1670efbe7b82dae76b43698fc21a2c05b2cf 019a7f813771d3f579ed6e3bf4722ae6ec129e1efc8854fcdff5c992a8e9710a 14 a6e35db50defd44043da303dce83cbd5a0f4ff3c05a17bbf1bd5c9bdfc191104adf136de1b8662cfd4e8570c738e86632f26ff93d63863283b89722439f86f0376d5f5c9d9bf4a97e7acdad3ee41cbc69dd76c7e75cdd166e181c1ab58ab9e096fe849972d98bf267a00c7e6eb86750323e935fb28d99e1b7a36650ea89f3100f51636a4de174fc899480cc8615637d34845e99ddeffcd03262383fdf35c6302c07eac1361a586e306a911a0bdc8ca70eb0fbb599c462d6f6a4de41751c98d0afa3acf3a707acde0c669fc91d4465af29c41eb3ea365f6bfc653019d91797b044e186d097cce7ebd06c4721c06d8d5a20828eeb11ba707417de1d328ddf36a031fb1de95f29dbce1d377dd7e5c8f1e2e3ca3136209e624b588effa2997856904f4e1937397b743050215c000b227d110bfe5263e96830aee34dc321b58b49107400a45ef4344c27aa292170c52cd93a11b9ca7325094d17a414fe00080676e06097625b0d262a2142d29e9da764eb52c7d5b78825815e02e070872ca62b5020048b1221dd9c23d7bee7af6083a267cc0c200b220c8d959ff32e4100421a1ee0b787c29f0422d7c1bf657c777d4240c811982cd1ee38d3fb3cdf6cae4fd6225073d45caaad9ff3975a5e561c728a2987f3763ec609a224079114b61661044670c1c9cda2f3a9320e833db5beba7d82ea79a3ab41fc14596280244c5bb75b63d038f2bd7d605f0be1e8a7823d17b2a4451c2073d617026848f6efcfd8643ee7d0c427f8d1877767f2013d87a4dcb9d8ce9a8ed1fa0a39d400abd2f25c876cff10432781675d3e1854509e4f02f05f54c5aa0004726802b4b6203a5a45002c299033b1ed32c6ffc69c87192d4b15c02a7ed7900f697a6c0d9afc0cd4fda8cf1e5018e01fcb365827eee1c9bcfdba067587131e395338be94ff70a5e1af23c41300da5cbe9ef39047fa4f15caa7b8a48937790faa1d9ecc003c592335e11b753e00c85799bb114b2d77586f32f085a202b31d1820794470c7086745cc047b028d90e14a0a74df45f4d325443841b1418e58e98edec29512a6b365dbf26f4b790260bcd51db03ae50601b12221043f02a374015cd69d7255976e4fa164b83f980740f368be694f43183dc2ff469e6cccb08f7abfac8b02b3addccf6a7383151fc750af1cb3591e95b12e58db370f245d60038df752bbd70f65139ae11ba9d4a6fc802242d15c70d96c5b307cf673c67a53aa3b885b36356fc55d5301f6a9a66deb20e2bb0d0d66da832717b8ef4d30fd36984ea881739ccf243d1e0bf84ef8835790dbc92a2e736ac6c687caffa57787d7e21842f5100e1ed9aad7588a83cff0788082982239837eff586ca787a9716b35112f0e8a1085c0a9c8f39c998472c69040f915174193bf367ddc9c5ba00df82dd92d23076df3889c6c1505083bf8fcb700b4f24baf11a07a194a1ac2b0d6557c075ba82fa4298e19d07972910fcd6f595066e5b499b5c032ebd316150b8feac64837d47d6cb48f1e62ca369de4878fe850cf46cd3ae66a658c9c4ca7286cd1db79e854679e9c4959154bb642886a8cc23062a62d11b0458974feb9ad40df7e9147f2d4cb984082d64017c0d826d7d57d2058bad8bcae5b0ade7f4d2cee051a97e04f5e9f8272a3cdd068141ade0c2816400865707f4bcb1db7dd7cd89e856b6a10005a020e514024b55805da63c833c1d0a32d3ecbc38cb9851db07f183046a8784fa9b6700798fa293d942879748d3a004035a93080dcb8b93c9e656434ce3b759615d9ef6375c9ef65da4e469a3e13d0be93ce82a99940245640b8dd1343adc3c902d13550d0009076610f9fd5ae2a20ff6cb10576ec43074cca73e39a108eb8be2b771df9478c1bef13e018bed8a350e53a3eb816116f57123414f791a170b83298f1f60dca8fa84d8c1083d200a910bfc8131cb692b924a41ead51d512bd64dc7f925a7cdc5d789b4ca860e17a618087018bb410997e4cecec255d1fb709b9fab7598b02f56ddcdb603e170e054f10e43d5455e673cd080a167344cf5896bec713f814b2de7839b69acb53e5e35c10b77200e508b9fdaacab4ee81b0ac42491d3b48179b17f4034a94ec80505a2ff00c3249e6bb42c067949a4ed48b06842415449512775e53c07f156793d4dc0ab004fd86e64fa97c8353b696c6a81b294ae66e0336a8aee21d301a1c2cb19ee920cc58a234e65fc8ba21605d397278a5960e3f86693d6283127e3ffed187bfbbc073b9913ab6a4aacfef80ff3bca9d6de3299f6783db8146047338d113159b81f06bd62fa90a77f4dee7bca61ebb3ba6e963cd9c5c64c938b2a0ff56bcfadbca90215a310ac4ea3f2d37ce487acdbf5a70c0341d257bf30d5b75b30cc033c07570debe16ec26eb5539dacf6a06e71b609cac5bb41bee606a7dcfe26ec973c412701b90abf86a434ce93f80f14c1fb739b645413c4146252a1a6c965416ca6a4b7054e1c3ed057106e6f41901cbbf8759fa02495797692e744c2256b77322ef12d0345c9b32693250b5fe75a4d25b82a04e3c7349356c998e822fe30e92b2367d408f3643e2617c6f022acdc349fda1003d1d904a1d611cf47578a02fe55db4b09039497d45d503eab3f736b8de10c744e469bf8a205e281f82168531563542aa9047a5cafe4b5ff237877488e9bfbb29ad53764eb80264d92966f305cf515842101343236e743efda7022cfada2ae9ce027b9d07c7edb6e0f4fe09b4338a111db0366e2a32b0f7c3e240eadd98b09c85d706388094a8cf1434fee740843e257cb03 -generate_ring_signature 98a0d34ecad7f93a524bdd5bbf05df6aabf1edc86e6dfd555409eb9f12b970b6 9472ff1d85dc16f590c6b034169850cd9a7c61aa49991a2abdaf9924eefc483a 17 808f7fe95ba368b13e3b5f5bf8375263e293056dd4c0b946b15b6811047a07fb 8b7a69805ccfcea3c45182def8cc422c1f23959e156bfb4b94c5fa3392589454 d56fa8d5afe511e42e28e98f7e24aaed8fd49280766b40781ac01b14e402a94f f9e92df33c3a7deaef73480de48f287a96692bb05f964f331e86a7314ac3cefa 44bd6fe3e84c4b5e931d1751bdb85138dbc2497dd25ee0acb2340adabcc3d2ac 5e0e3b4e8610b3ad968c0776fe185d5821b440b1044c3cad601377b92792dfc8 701052782deb012f529a3fe3636fc4e6d4f3c5319c5727db36b7a76a634b983d f37e7aeda09d6da3b5f9d06dab4c809a9a70c58c9cddbfc81178cdb90be5d511 ed952f75fc7fbe0c454228ba22ee45bc4d54438d88e5544cd74d33c5e851e80d 60efc3617bdbc7957d8511526338e57e34f9a8502a8911684d24de2f76a87ce6 17323e276a428b2b238a5c03460a881ecae3ea9622f35add96322ef1b42c1ee7 9e51a49147a1029412502883ee90d0b683925d611e354913af570c8be1549f3a 0ea8252e6e1faf7fbbc70ed8040f9c57c87bb42876ffd8564032776d81dd5dea a7924de7fe171159aa57a7d22a5647f2e968396e6a4e424afbb070b98d0b12f4 f985bff093c1fd67d92b225d00bc4ae37ca856075940461b790c17c1a73debe4 247c72d2e0916bdfdaab6abd05ef5a877b7f175bcfecb8a499b59c6577b93e43 12ec03a07f4f01fcece9465d8967580241577df2d6da53db9a23f5257a62ea6f 4b9071d06ca415811ebf1038c1bad7d7a2338f82b500a3a61c0312d48b09040c 13 859c1e1c5cbda894530f44e8ded45304fa80f98800fdd4d428af310f674c510b466d49d63c20a0e17cf5b0f9064b01e366fe8200a7dc9ccb8d0b8f78a168b409699898a81b8754dc6e21d0b8d3ac6480a75e36928468f66332e1e4f816e89c02e177b57ec9a0a8e5162d25c28579c79cfd0bf52cc100d75d5d2513344cb2af0dd10a614ffd7682bfd04e879696dcd667764045a30b2f0be6b4ea82dca29f5e0c1a7f27c3ceaf4d095f7c52ad678002f3cd1064f2571255166115e0bf92cce90139e446e1467a363e81f8246e019eb0e0d8bd4f7eb08e8fa06e14bff30fb5f20b2cffc01b01cabe03605404835509413100dd34d4190ac0482879091aedc89e08d1e80e76ba33679093aa6dcf1520da84592ce7555ccf219ab3e169f58945d60d0f9503d5d048419bb9d45e0ceaf5a7580e6c5375cd938210be5b509e5522d207b620bfc3729eeffaa1568695feb283fcb0cd822eaa8b22fb1a0b59178d2fc306571263f570a357ed0aa7d2e2cc2f1983ecaaff08323ea18daf7e850f2a26ac08f5768a6249e31ebb16c745dd6a2ec86f3a54aef8dc4acc63fc9b01f7a6af6b05d0b25cd80c41d4e7c012e335c93f5de6683d86eecebc8cb662c1b79f724b380cb55dd140afc90f4b6e06679defd00098ed175ad20bc15b8295c076479fe09c0a3ec14584145f2ce63210f0447890e01642e738626a19beeb6dacd55ca322d20e4c9fdfd9595b4683e4e3e3a602911d629f7a119b201f131916475532f7839a01ba69e15f4ff7a681152175ec1ebfbbd40e2d8ce5f27aed2274608ba0e63b8b05530c9c1b048587436bb8c9bdecfb34abcf8b20b977ef06de844bc7234abcd401086653aaa4bba433347c4693e062565efbdc280b313b4f29370bf495b887b50d3b4bce34bb4ea94088ef2e073d358765e4daf994689c6107fcf7e5dba13b2f08db464a06ed3ce6bfabd11cb5cc0b2897446b38c774f1fdb59cbb8c97dadc100e296a999880693ba6a27bf84a0ac07d6485fc803cd52887f293e2e7e5ead4df011f36a05078ed3baf55eeff5d1a3197ad465741c36c51157d8f4674d5abdaa10cd04675451479f3bd2ee43ab3e9f7a574cea3558babf4602e34210b0ca9cf680ea08ca3f5fe73a030066f67c8904e5ace16a590da9f0557ceccc2012f4946a10b025aa5da1cf41d42a7a630649211c9c6a9afd7166c64d0fb5a82d91dad52b60bf49c78ff9e52752a72c427a594fa5226dc98e45d82d7cd4fe1993a42fbf00f09b3421d70c2b86ed644632535ae1102da43661347756f0a95bb29967e5db59e0ac20ce20f5370fe18456c59bbd29159733d89645a0e2e2be82985891dbff9fb07e31f82dc4d660cc440733bc6ada51b4e2073a18820b3cecd3b1a9e8024a77509acbfa539afdf4da2a4fcd6b15135038f33046cbd005032adf44842a9ea12680cc9b88c1e3af379575e40899d2adec5cb83e5a3a5f640486422aaa7cbf07a94008fae45d390690f1f8c63805df6a21cfcdcfbb23382a28eb8fad0cedfa1255704 -generate_ring_signature ffaebe5a64fa21b3cae1f3c067113c4cf958a4287801c6a10ba0d63a82a16c0c c44d1d1d668711d4ccc3cfa257b24e2ee233322f078e4e6f82a17753e4f5c8b5 1 47d76caa6562600ac2e06caa3b861cccc17d73eb25df6c34308e21876aaa54b7 005c86d012510a55a17ba3300ea863c7179c91e876ee0138f8e987fb4d7e0d0c 0 28142d4e0903609bbf490cd50c1317501f90f26397aa3b85dc72789ce2c3830499930cc6eea1294daf6b25c7a27c1ffa0856da7e9bd49d8b37b8b7aec1d10206 -generate_ring_signature 73733ec5b86946952811b69e7bf7ba5c37587c91f2d34cb2370d2b9be05a22f7 d8e042940c4c896d6b06bdc0fa35e077a07e6a39cb15c2cbf9ff5c6df99b1cce 15 9161d68233642bfe6035afaba1645dae605eb345093bc46f03d8f142d5fb9fb1 128cc56981de785308fc47e1edbaeee881f818971d65a8a2c0100ff1921288cb e3ddb25dea20e2fae36efcf1c8cfe7d3514b371157a39108f4b0e7609928c716 d08ed18856d466f1ef3f50e49d0986e0cc3718be4a5dfc99311070f7b135891c 56cd77bf457f0ace98ecf454913a8b6940424c0e12e183b5bd084c34122084a8 232fb54db3f3758c5329d8d37726dc8bbdbf44403192b6dccfa8d3783f657969 554b67d108192723af618ec6024f9167100dd252cfff52cc9288da122350b548 049a7ded353d5a0ab8661f1342bcfb123ae5c8369c8921b5589a0ee96ae49512 ea95222a7f00d7c6aff189b8fc0c3844e24375a511ea4d62386dd6d5599f165f 558cad957191b01fae7f274202d8faa3b5b71348c1ef4600302a84f112bd2f37 c046f7d11f1a0eb7dd6f25dc1e83c2ee571e43241fea595625b06b18180e64a5 2f203ef33ccbcdf41813ddd96364179f00d04ab0c475744f66eac76524dcccaa 1f427b4add5faad3d81832802e23ae646a2ae862c51575d6e753b35fc87c51fe 9fa5579abfc3a715e844651c5985800b8f77f4b2d2c1ec4168e6817fd97cec7a 56144586fedbe763b3b0f3676cae4e49507c79fb23b7ea08a8b755e70c46e634 5e508d8a5e99e8ce441898c87d40de7b4a0cfb2bffda4b57c89d20065c9c3604 6 b3c351e57cea5c5759ca0b57884fabe028dc9c6185cc8b4d287dcd69c6eef20d0d3f000bf5b9f494261e1baccf24c395c3847ec397343c46958cc67efca1bb0e0cf2d6dcd53918d59651a6de5b0998d1bd6b7b36a2139d37536e20a10618ab0e18a2c1c53670c77f096c3a6076fadd9dca4c463c546d682bb39161fd41b2d101fdb829e55148ccd65804db07eed4e90bd86f7bb8710cec2526c0abbf9d3c620227574f5d1be708450be128368789ac3ac393c052d9975c22e81eca28fd02eb0faee0231339208ed1ead0b1e6c9af1a5d13078045cf2a31d3f9229fae9ad9c806d9c80784748bc18cf6773fbf3ac595b926d2242897016cb2dce8532c0ad2610008998882fc468b2eaded12d9c4f7b488a434d9a9ce7a609a7031348a904eac05170cf699f45ae5352eaa2ca804fe6b8f68f83f2df8a08f7298bfbbf630b4b10ca42aa71bdb7ae231490fcb5a65733afe50acebfdf526a2a5139cb63e21c2b9018684d7137bfc9d3da812b8321a6840f957f4a71a629f52881bcbb6c495133c06860d2180609d495d3650920f5b5a4a979890f54190d0a1ad45119b39aefea60e8b3053febe287cbf8b391f1c63054e1cd6c0feb3ac98ac33b39bcbdc04daf00de50fdbef8d14398e33df891ea4cf25bbaf32612a0c8a5bd8c03bd428fd5abe0bbace413f9217636270a3b6b83036b7d98ecbb0d0ccdf64978feb7f3afac426085788f852b8f4cae321dfc104c6a1daab5cece5f65360de4fe5fcb82c89d45906e4059ace4b54f91825912db55afe71f2d4734db085b01aca8f2c0e6a3af02805ca764ca6ac38bbc3aaf92addb8d918d269c0d6da32931836a4cd41c755dc4903b1355049469fdc2ac6251c16392b21962614c446650d1472ce5404b6bdb0a100ddb8b582bd55b883dda3521d61ee48718d2fb924f74ec600308c3130b4d1d807aa92e305c02b74466647d3f7c39ee8368a3fe2a8a73b6743b5c1d5239f4db60e349b10ae9902208c0bca72576fed11d77d2cd51e120febabcfbbb2093e7e0c053e9ed7b820acb48f2b95fe94cf61e95ca729e0a7d03019c65d6e6ab01e6fc10d5191425ef7421c768ec83a4afa8be811da71a2ef50aef054e8b4999012fb9b04d148881fdd57b3294b09d115da884326eb0839e96fda767053b1eefc5716e9018a61796bb8436d12c1a7e629f0ced6006e5b722c31d914431f61d6552f11210af88519be0c5db6ccb80d7f064b998d29dbdda9bf32e77d5b1e677a055744f20cfaec6be4bd9dc4fe43336217cf393024e656d98b1a9dea814174b0bad1a3090bdba8c7a7a284dd56bfd115516bbffbfbecde1401cf62692c4c0110cf1f05ec06 -generate_ring_signature 778bceb8b14ed5f0f51e4483bca6ed959b851aa5ff880a59320d30d0e9c9ad06 d8508c6187929646cc7231cb18a959d0c181e5f40e550c32ebf11dab277cb36e 2 dd0e07b025b266a88482d72d7d3122d2513b11966b5f86b0b3190402e30343db 903bff8f1f2a393c6f31dc6672be383ae112737329059fc46090bb1a9d684c1e 4a41c53827294ab03c79424b60a5faec6f44fbade5e01d59228680eeb4a00203 1 860ddad8565df50b6cd6d246331c76a3f9ab5153910cf7f91c4e5852789af006e504ae33ebe172677529875fc95bc74d874578b9d37472016895a31a5f9508019e7d06c6e26ef936fd78e92823224fe7d77bdedc83021dec123405b75edbc20f1bfad95c32d0858d8059e31ccf4a45986643f07c730fee1a87016ee0b30f3605 -generate_ring_signature d0af946a7168a2b284854db904594d1ad9055cf337f25b80c56f218d3c0d8dc8 ce5be5577913123659cbafc8e7fe1b31227e976ec379307282605e229aba392e 28 b5bdd837cc0aac94b3fbcfc27fb023126a3ca0308d6f9ba22d24322d5eb01d57 e1b478d03240bee41ee60b3ce5c2875637836588696ea197fa4cc240d9f6ed44 4edf95184182c3034efaed72684168f95ad8ec6250c25b075f0912e2d4f63459 1e9cadb7f1407262d64ef55add50c2f6875160c2fb645c8c8ac96d2605915e77 4d888e5b483d209c20b60c5e5601c42deba7f05592ec656cd665576a0bd3f742 bda224dc161b87b51264856b6478fd355106105b80380ceb36d2e18e5981e6a9 37f0548f3545620b3ef1515fc5b522bccfd8b8a068598495c4d2cebabff9cc02 e386b54fa02234238ca51c9939d2e3fdee81abcb94853f033c615422babc8f63 4247bd9140878709938dcb0432c0ad95159a00c66902c004d2ea09e2335cdee3 93ce5626ab90afc7f16c8fdd870e9d3640407fbc4c29cc12c11108a852208774 a68380092c8ba661fb24f30b21d7df4b840dbe8fce869394986c7ae4e2edc0de 25be966db483ab07c610bdd83a5e26019a21c9cf65d582d3aab40025284dd4c1 ecaf62457619b1c1362b35dece2209aa5eb9ee8cdaf59ae1d5be775fdfa987ab 5ba393fc4c396411dd2e3e93455b31b17037e14f9564d9896de7455a1994ba29 16b37fbc30dce9dffe460ded732c588b2a863563c0d724cd909cca18df6ab50d 4e97f0370be8608c175717e554f34aa4610daba6cb16fb96c4136a57ba230b9f 86244bdecbd028e5be7c98b2d347e79647333e71784a584eacc308c094cafd2b 25839bc668849bfe64fc9be62997fb93d1188108f7565498c33f3f4ea4e1bb23 429f58dbe7f3eec5dc1bf30ecef4293381c828c5bfe7b7d7bdb6acf942cf858b 2e852cde3f41675c3a1aa901653dd6f91229fb5349b59b95a86669b806ad6d49 b0a6aa5f72e0b404b831b691b29c810c533abad713128efc640b78b46b8bbd6d 8bc504d0ccfc3d825a1de31f005b02e5d7e8396b213ae78dee2745ba94af12c1 4653b7942cb6e119836df837d39f7b43339ae6faba28856d987a50ad2794b292 454a9c491f09eba303fd689918d9ae6ad662f8adf029fb687dee072d8809d26b 861cd74d161b68c89564fe7621ed75778aa4fa86bcfd60b981b8fb5dfdcddd16 da9d169079abbd9219fc9d1ce674378a218433cd3058d7f48e71891724f8e3cf 90e52c87f417b04bdb42a50cd4344c89d2ef87d722ac451d8ce89cd148b9a69c 6226f09a0649ce2c264d056d3dfdc74cc8edca34091423845c78bb691bb6d89c d06d01f7eaea9f5aa3836471b07f66cb15f9abf5191f03245633a73abac12609 25 7bd2c4792bc05abc21bcaebf0923eab275c9144c80ae806a781653c40abaa003f8b3b085c8c653338f002969b223f61317162fe0cfb7c02df508e539adf1bb090afba55f7be6fbe3d73164429c946a29acfaba89321368fbf1ec88fa0f7cfe05ccaa3169e9e9249298b47730a1ee026f0a1ce38e84f94b8d79152f6fc505ac098a89f2f816b1510e983a61e6fff890275a5d4b3f7e6cca6856ae85d21c0dcc08acfa7a0323ce302ebe7c597773fb3876c37143e175572990de6b0e66038d8607a52cc9e23ca724149ca49689b65b9f877f0910ba87a3468fbd1f089fa9a66104f8fb2087a7ddace7d2817e91dba58878fbab281f4a69d273fed6cc4f556c480ae527a2b69c2887844217c6381065f1da64d5ca2fcf42dd4193b2f156adf5810a601b5184473ed3b918353f29c1fc70b2f2ad706f1367d17cc2a8fee13199d70d986a1583b2033055a81581688a8f4ae84d676e160e3cb0d77481446bc41f5907f39d9cadd88a421412342994a8226ddee48256c08ba37b7849e824f885c5ac08ae60dc153b19c11a605f7f4f00dc48749dc447e507aa593065b2d4da1299670b89c882589707c218a5def3ed377575fb159160fbe2059bf32c0ce988cc43500db3dcfae3c7388990b1aa7535382c60e82885b86bf0bbb8a1b47390911cde5303e9e16a145e17a7e4b2470d6c95a063198579bdf344800676b67e02e40318f20b9beb98709c039a2cc7642f921e367bed48c3c5b03e6be8b056a8e7726752900e5b0a139ec47ff32a493d12adb3ae7c184a2e88dbb7212818c2c580dc465aba03eb465a4c9e17853e6a6e617f87cf294094135ec48b4717c0abce8a61eda5140d506eee7d820553c62aae4dd01b404e85feb69b61ed525e0e8a5b288211ae0b0b89b3e4f9a3c042f5dbf09ea88cee77e359207ef17fc2767b6a7cec02d3fcbd0a88c6fd3fac1f8617686fd61caac6ac90bfcb4362fded2da360701b319f1f7605e3669e59a1d191a63c991bdf24c50d3f970d648c763cf50769192cf72489ee0079946d777a82adfcfbe5954b7ee6c2cb334c8bb2b03e2cbc7f23f73fbd8adf01752c5faa7c0a3fcdd6e591a5fbd3c516edb919f4229e413bc3c50fe9baf25b0535098eb0e315fd63671c5b248d203a71a1057f5688fc8213817f3fcc98b0db0fe15983768c57a5d4c28aff5f7240c484fc1f2763d9c2e36664ca3f0b4d2e3d0cfdc0c42f84deb8597b9c223d4ce75587447e8a7b3f08827704874c65e0db6e06742caa0c741e16dbe4c60e9554ea42c8ec97f899a4b79a934fdab4db1cefc40be3fb1e63b85abf67b1b6fa6293bb93ca95a6e4b13ded72255426d2721cd2960a72d62c0bb5431dc77d79d2da0a47bcb922b638ea10574426a83d9056f7ea5d0e322e2548caf7286f2d7badac6d42ac61b2b1d0524bbe11a81edf6c98dbc2060174a3b5330a88c0b046bb042e6ec11b746f03c35305889ce2152439a01afdb60696bbf66b6699c03686d161d9eadd1605f7ea34302a4a798fc6ed5f71e09d8e0f69628629566261f40f41f753dce47533d4dab4d3359af56719e4eb8c108beb0849fdc0e99041c2a64b8444809c7737152c749742d3745e3733493c9c1c768508c94103969397af990202b3d5e45354a7766fabd502e8ac65cb9d95e7766221055b497766a15c0fdd8ced4664a0f178631315600fbeb8bf88d4fe5676c372970ad15387638228f0fb751ae7a675e206f9efc31b3783b5809ddf508c840d4d11035e44f6c3cb140162c3e606b222fb22ea62f15be1b4d3d228778c71993b0b9c016ed70b6bdb0885febea0eef3589c83863d45e5143c243f33921a1db96a11d00214682dfe8b8d097ff779e4d05279182433fc84d884afe6d59bf1fb3f904f3c02fc35df786e57a2f2bb97d979b60026b49d7765378b394d854c70ab016e8b170e3450a20dbc46af7995de979e4c776a2abda7b657f2a7a606c76cf534258da806ca1ec84d596b13b1cd199a120e5ee866e240dd51a23b2dd184cf96a09c181d0ff215f5148823f9d86431d7e02735ad4d553da0778fddf8faeb8cacf52f765b0a3d9a873a4f490afe2167ea8298824647ec7b50b945af20b36ef9dce700ef740ff132ff39df353020c8f547580f4b7e10275a1f8a29733c7eb60e9bfb5ae84002eeb384abe845a2d71d3efcd97f83f6c51bb4b5b66f25b9f78aaa2e76897e130900f77f4487d3730f5671e2badb83a3b91dcd33c949ade6537a86814fd226f0056c59312566d7a4dd098ad3b3b31f643ec34057cdc2aa9e90f3cd30ddd9c53b029d1988b0335072623a7419fade2ee80eb2398fd17556796e4db6de3481a0a309d133db7c07cc91c9d6f7caef4bf7716f2ec6281438dd86e751bd943b145c1409672aec2f673359ab6e61fa2a2a61dd16f2951d6b8e0a900016e1828e2a79b50b8104e4aab9cebdb578e8bbba5a6e9ed3236b655173667faac09dcdae12fc6c08b3a69129ea3b203634a00a5aaaed6fa6f14e73795bf0f5e00f1df33020e90a08 -generate_ring_signature 32fda91fee7ffd86261cfba41936bb2a57a1babc1e41c93bcce51132d3e9b507 faf0d72af0aa2f1935f9dec6852902445190d777581a778a7e1a92c1bda327bf 7 6e89346180becc891a370752d14a032274b762a037103e634b45bfac60809226 97d5764cdab85f5c11a86546a36a96bae26bd080c451ef596daaaf5ea684086c b60d1e57e2d34be3512e8a2be4b3d00ae2fae3632b5f9b0ee1c71705600b1c0d 3f10de099eee553e1b45f8f68a760d6516e2690ab993b9bb75d57a09a0556f70 070eb1a8fcd9732847154aea827954d8eac4034de82aa78cd391ae8c8f395e19 49ffd7d2431e8db5626d37d6220b630a431cf592bd72faecd522feebba1f2291 cc1127fab637befc072b81cfc583d2d93180133cd0ead88efecddd89bc46e4d6 84eb3ef42330604ceff1a7e02b17de15c717f1a904f34db6c724f1702876480a 2 489d9b6007165452979e4ecea64fb5764b1c0488a6b9489c5691e4575caef50fa42e51e1adeb9763c5a84edccd78da62e5ccea264d4f84bfb38d70981b713a0969d670a07bdfd488eeeb02f722e281dcf1d83c29d5fb5cb1b47b54fc37bff00b340ebb0aa0d0e7b2b067e9030dc66646caef70b451c68fa40ff7c7f3f3ebbd0e56f144734e10dde12c0f45e70841cb7be099fd3fe3957e43e66d15ec338e890410727d7eca4da979913a9a3f22b23a5760585d09a4a9438cf99f518375dbdc079f220b487d36e27564de0a7795f89f842e8cca4d8667d9a2fb2703ef54c78700cafdfae9e01d8fcb90555f5dd7f0e7a05230b871d2935dbe51dfe4dab2e0fb0d81c551b476df8be09230549767ad79b1136d64a6eca6edfdfe9148a3e649e50131bb54ae13620964cb242989baae1902e2b74c1b353d51d084610194963d83042bb8af66a24a2e43864dc4a7730585acd16f2a43bb50d8532446937b77cd2d013ddd668f53c94a12956543ce125b4237cac099d8bc8bd50414cebefec3c0ad01f7dba7104bdc71bcdfd275aa9e55980dcc3bae1b33ab776fa84df2bdf0886208a112a3f59ae23ad19d1590e5df17a93d145c8372c6875a3dfaf134d86c721d0b -generate_ring_signature f95f58b92f28fe5c8cca37b620c77466d564444b3c4b27bda95be071949ee7f5 0c7a668470179291b39470d30af192a98277cd4c831bf6fe9f3501489ddfd8fd 57 9e703ea6f7136edcb82cedcbf43a68c6782e8f1e57c5c2303b4131d1d5215b78 2ca97ab38e7199a22fa6cc16ceb84711e9f2a41a8f997386ce5b60332e752d32 15cf730ebedadf9fff98d1d7c42b42328259a37645d31ac52a1ef24d67208fb5 bd41a6107e68625847b3eecad7c295f58cf612069e47eb4a713f707452687a1b d95b91d6438f3fb2cbafc7977aa1c84e9869cd78915800f9560d3f0274b2accb 698db750d8b5ca89f0a4b0d0ced5f429626aed733dfa772cfa6833c2b97fdae1 4cadc08cdee26ac4f3f3cb932ceffa9ed5e936df7bf97492fd07bea007d5aaf7 5ff610158afae988f8cc3731b3f0613d1300df97a6822626f845d8a73f14d839 46aa6f92903c682a2897c8d73559f1db32dab440f857d9d3bee4e098fff99656 20bdf6ed73381e3da67d3a8dd62e82bd51afe2f750b7ae124b08583c450365b2 640e7073de6dbb3a8d8497c4a3f9c60332b485645519b2283a238742da08fe46 c9572e5cab158cc073919303f7c3288c2245c49de1129aae637b38c5bb62303e cfbb23c7d6ddab8a249ef1e1dcc823e9bece5a2eada6ab13fbc1242131daa612 8afa786d231a0c09a13d63170fd8226330f81f708147a1f47fee7557ba27d3ed b365ca81fdd650d274f1ea94c492a4a65e64adb7b0fbb6de9528782a3650118c 10984b7aa7bc1ac1e54125f0cf87f802a9d64ef28ebdf3dc91913a4eaf8aafb3 cc880b625163e20cbfc65210c127325e4b3a17af070d1b74126c7227bfb6d065 0344b564c3e1b91487e607626636a5027dd2a9590951f55647853ab8a886bfbf 5c568bf19007ceeac73bbb66d53c2cb062eea710fa82590f76da6845517aa8f8 cf31e75da46ee36623789933c452326df8b33609ff549b6709bd747f3a973ea7 c3af861bc2c38f2d94889e5738e4a756b231fd38b39d9fdfa307a6af6a26fdf9 3dec71fe173c27b02df24e8989cf7075342710a13976e63bb740be0ed3cf8881 71221e35d8ff84de6fbe8a8a23a6c94d4a2e5c9dd5e0806c337b78b40972d968 7433536546f072ddf45b1cb55fbe68a3c3b6154b4f43540974df4c96c16df3ab 62b2725a6f4ddd4e5bbb0728efa86630b41d8ab848d746f73af95767fd57fcec b6f19566fde140878f4f1fdd0f64ec397ffc1ecd66d780af774b35ec329d2139 b1e53d524b31832419ca5ef8960245fcaab7cf1ee7211f3de92737fcd32a2256 156c9189c4541514c557e3767e3ee07429b397cf1cefdb7eee9c978d1b11f6c4 4babe5081a6e5a1dd8ea579522c8f6a44db64bd48229ab6ba7f9758990c333e4 3f6ee7d39a89bb34bc68f02557cde48c0f1e4ec9654d65bd704637d16fd26721 4512838f751891c81732898eb640c8512b6a77cc7d63a3e61ae0827b7f710627 a69bb4cd67c4d72585a8d3db4000429a3ca1691f2da44e01ec0113ff72dc895e b737c73f3572c71efe7cb285879ade2b174b65cea150f180eaa17014d7320cd0 7d472b19d3b3a828dd67749dab91cc686c0aefeac6f10b021914362e9e3db34b f6158b35f8a7d3bbc700d39c43483aa57ce38c8e6ca1195eeb87c673e5c2eb48 5dff3f8b3f1d276f142d69dab6f425f4f78b1a18182d1ad207c027114a694b13 e54fb93a3f15286ce5f2284f284927eab88e48b8213c1a41eeb586ed999404a5 7dfe099cad93d510b49cd166c192e813c3e512a62dc4ed11d9b9f781f0194c80 773cab6f26db9c2c36da474052966fcafa308ad649ceda337f764428948abaf6 aa7946ff4d12c48703c04f6bfeec86d18c4a854109739b3863e4b5007999e2c2 b386b4f889db963dc4daeb14893a3b0b6c3b09a3920a1bcfd04dedd217e573b1 0726fc793b0c7493cc0439189bd82d5d0c3dd117b9aa33d6a0d9553de873e88a 93f9a1f0eda3a75467c99b01005ff16a4c8b006649f77533cef185c4f7a30b08 377b1b8895d0b601d45a5dd36b93eb460ffd9e30a0cf1d96b91f7f189f4d8732 5730b7cb7e779695bd04de02fbc180f8a7b1a7e6d0fcc066bb28d4c94b3aa021 548678ab5e2fb6d870d6c05e39b3267101011c0a842f373b0c9735313fe7c207 788e4bca36e99ac9bd39e7e4188f88b78dce485fd8ce7408ab5d5588a82eea61 c7fa217234c15a4b2af0aca4ea58af4d3762dcd3b17a7be13ad882ea91539416 12c3585925770b39fe686a8d04ee10251d504c94a6c16853f7ef1a6f0a525556 f8748feb866849ac48f120940c6731791a593e5973c9228693397d8e3ad65268 8bb30ab41ee5221c65b21919b8a784de26c55983fdaa5bf635a1156b51213f77 70a7fe521146c4e2c6d0673e9e31f9931c0fc79d516439422dfcb86cd52d6497 a85e0367501bb37a0c8d92a311d3b6ced453790b116246c9c5b7a3f6022d7dc3 062fc5d81991c3e216ddb0caed6fdfff321d73c2c5fe54b9d956d18cbf7b7c53 fca490659c54bb57d385e33e8b67773bc912ed88506ad07f33e4acd1444ff692 1cfa1c7683fd787875092bb812b4064d0beecac871e1af17e72d359f27e2d87a f2a11397ecaf7753c18f0a6970da0573a2804bfc4f48c099b29e71ec6397c2d7 25a78e09d6d2bbf9431db8891b048d8429eb7768ad2fe5f2482a76e03683e908 5 27f7d788a2035ccc721b7c41d23a974ca4d742e1125e99a1d4a4d36f449f1b0846485922e0663680e42c890bd46625c70fe5fd55e1c7cb02e59c9951a53a94005ef3caf7a7ce2c650b2113c33e25b30957c94cf0538b7bd53436ad2041156c0d8a60259468ea85ac380d57b0770569210f00d6b9129d875e80fdcfc27cbaeb0e74ec0d7fb08c28f14b03d2f3a5316ac1de3b87c0daa4d1447e911de5d284fc0d7b0f0f77824313a58d624c2f261349ebcd23ce34351685260126f2720fbf89064629c7b7b28e84c4d3d9f0aaeecb9b44c7443c569d88f860506ed8f09cba35055f9ba5151b934d4c0243448fa1d72ee4a1460043da70349a534d7f6f3825390a1348788daabe964f014cca277e72f27145875e19b13f9bc94d2be573ea1ad208587204c10528a5a43198bb0a94b990ee680c3bd6016e14ef2b789d6ef61c1d030404c14e6e79867d75e0d566d77041da9e01700b9adef76f73241455aa384d0e723bc0c0478109406b4d47241eaa7c8674102770b31a03b5c021e3eee419e20402253888463cc64f1902c8790a0acfc653f5abbb1becead628556c770affac04a6987fc9cb4eb55179b5f5f36b13b1b4dea9003db2202ee5a7e6c6bbe6fd4e010034f1a7ad53bac65dc590436e12ee080ad65d819b143e005de20c58c746730f04ffcb50c4af2dd78352ec4639da2e152988e9b03318b33f39c736e62b2afb0cbd3ae7759629f2d11304551ba72801ebd8a2adc7c071174feb134ccdd46c720b554e0c00d6421274ea7f45613cf1753fe5385181bb4584fc96fbcd5ba16f79000f7a49f2bf7529d577f8118a3ad60aa200c4e54d9b5fcfdf0144db9639bfc80c39c99d618d969a8df3321ce8da00692e7bf7adf30bc28936e3abc5d89deb11037c38e1534b617e9eafb9020cc1febe2cc619db3573ee3239f3d571999b198802ca6bfa30637a1d3794050f9dd9176121c3d373a45cb54c08b706617dbc4f4b0a5abf5cfa37149a54b30475d95f1481ac287375f46c9e186bdf0307ac3d2a5f07e7dee417e5a48834b45f26b5745bc09bccd92ed1c37c765347e648b401321600869411d9629f5c141edfdf1a9e1187cf1fcf505c22a12e5e1925b5828d2e0f03f849fcdbd78579deba7ea616e5eba425697f5904b660027ec4731a481dbd1e0443591eaa4bc33f189d3483cc3ae12ce0b1dbee50c0c5508398f6ccdb21e3190e4c64d2d920654ac28695e84fd6f7124d0faaa1d772bdc09b88d9f115f642c707ee2118d042fd17dd46eb049fcceafd63421216b301d099222407d642dc64330dbf96b9dfbc4616c8ea6654b0bc4f51c8e08fedf0a0ad25a08bb9a544ceca520540c2d4af6eb450c69e0b720ece8f6a8dfce12103e58461f7a34df2aba942a50996f0526524d39c46c2372f88e19bdd0c56ce41e6d4ec3913fcb72649131df8001768bd61adef1d3259d2edceabe0e53ba004da1c518b61119d29d4db0f16d2024631bd556963760c923aa51579921e746fd669aca97eb77bd3f478e82adaa30f7ae3a2f0a55f83061b6eddf5339c72c79bf8d5b00942db42b70fecc6b947630461bfaf14649d0dfb627231678c10c9a85fd661d078640bc88e03ac4b1c71cc0cf90306ef97b4817c368f1fa9c4dcd66fec7c272fe89a2446a8fc93e28d81a60c86a730b89e24f970987c83d4b7c364f0c905516858c5f750b3fcf894f55cfa030281eecee1b921e2d0cb62d63d58f5797cb42be3b65adab953508824438dd104642f8df0fe521048882440b71f168518b27e87da854b3b056d6b45b2e04dbd06ac7d4f733aa0994993e0e598695835ef31d45197e699b35060ca6e4cf807a602c835666bcb80b84ffe021e5425a3b20aed0f73a46697a0e0244e88a06cf4550107e2ec78af5c240b856de50e260a3a4732539f9f70187a64b6841aa12dc5630ec694ff2f617cb7c6b4b7cb858230afffad0dae587d0185aff1dfd43077cc640ec912bd629e5455a905f11fee1f7054a2dc1852bc6ada4e933197d75e5837240dff6c2c100507a72fe847a8ab6318358d307409c36e0ac8b0600e0f8c555c8b07b0b329ede640adadb5ddb7aa2389bba1dcb42ea0d4c62221b604bdd10a20950cf9c65f05236dd3f3176bc06b0a54b1e6475d3d8da7e3f6791a8811ee49c30b05368c7f6a8a1b99251357a8421878936e06723cac41eb4af36f4b2aaddf233c02a7359f323817f3a46266f4fd0eb6ad1dc6091569182dae3566a22672e360af0c02df92f3aeb714b2bfd08407b307cc14b12562492c6e891baddabd8d6b20de0aec5e6028f3a84c7da60d69a928bc9c89c15840c3000c076f484dee413caac605501a2f3a307d1dc44c53672290c4d2973c1bbe63503bbf617baf643021434a06add90c9c16ddbb49bab63ba8890a546d3e6d8f86528951f9a0d00bd20335f004a6ff52b2a95cfa75960cf61edf80b71d38b2c866efcad95b13a2ef78cefcd00b6a236aeec96e01295664a8e8bd04285918790206ecce3259bc89e5d766e3930fd351e8d68955a6a8190651687356170b93257292a99627e4b520e9c85d43c00462ff0a0b6cdd481a0d8268ab5602b663f9804b18ef5fe3b1b9f4fdf361f3fc0b0800ab519b986c77d595ea12c4dc4a78d71adf643cfca4cefc68bd038e2dfd0c50874db65c84b38f98a4116639922bf29272c36f32363b850a19145fc9faff01cc0bfa12ac950d2b2240a83110a080c58bfe27c57f4939b7bdce9a4badfb28097e1b30ca6701fe17171369e1a318ac031bead9140d80bfa4f8e52434418e7c0fe81f9d0d5bbe329bf34e25d08ebe114aab7b9fc1fe131636d977a083ca1e8700b4d52cbfd16e0edf3e90a6363e88229d9ae295322a2e22804b3bbd8da25aa80ede85d8b0199a6dbb3f3cb0abfc92248605831fbcc1be9592baf51b528ec65e0245b8ea254a8fdcd84d13ba4707f48ed4c4439091bef66d82ea19feeea757b90f29cc9d07e235245d0f78fbe7496ded41621cdffbd675cce3518f0ac63c1479015d5a7eb7439a6cc20313a7bec7171a9a5163cc34682d84feec5a1400c590ac0c68bfdc88ead31c34bb1001cb945ef21b36fedcefcf9a522ba8231fb9ac7f4807d17c3abc706da669722eee6cf82fa9e534fb54c87c0808fb158186b3442be8064b3c32b257885c4f20eac683f0f0adddb1398866464a6f9655814164857b7c02008184866c5972acd64bb760da5a351fec2f04f16f50a041da0e68032f2987067b1a101732a847430a698cd39bdbdbd59e6f173956be1fb7852e0519238e1f0d113de9b1c3e6d0a4992100006a02ad18f9ff6188930f58f98ce8a88712ba48026f0d2321b20c9c84bddab2a649fdab94bd4c0eefe7a9b4cf97ea80ac7868b10ea48287edee1171db95e66fdfae79435846d93156508d2b1cd34ddcfc788bbb0894112564fb6567caab167d4f99bcc7c58dfb0f744a966760212f22c73df873042165f9c59d69212120d250ecf5ab45dfd634debfec9270800a009921cebcc900ae88fe11dbb0f072adbc34e02b408c41624e2b05ffbe91b1cd7b784a9e12a00d34350602c97d6f12a5078709d34c0092516400371d56d54938ff8208921b9a0f805a2d106a901f11880cee0fb0904242cfe8a281b0ecae01b7a0f564e77c0f0bcd7d27f21c15ca2f6a54737e9f5711d34ed2bd2ca9e5c9fcbad896f5ea6c6f0e8c0bc8c74bcceb6d19ec1259a5bd3e931c06fbf835afdbb865f79120fe38ad0a7687500f22e5066ebc51982e5468f80d9afdcc9c8d15110933ba465859bbcb00203f9f06ea6377eb73471f746fd58befa74dfcc0c86a361aa56f3d5808942b062d624eff791432b4a68a453d7dcd1d76c76e4616e3fd7144bf50f764d0cf990b9ca9d60ab5e3ba2476af33af73e5eda3b05c69df5628f4d06e0fffccaaff4c050e511841e5e4ba66890f31b7b4d650b15461e96d3a054cd8800e569fdd695503719e17b9e5c1405fa9478c0e594bf656fa5517a2e1315b499dd57ced95ee8d0a9f41ec2c66e7462613a93a0aa29cd136d89ebfa4e7b2fbb4bdb81c0b6b4ee30bd8bea453f78199758a8dae88be26a4d6056169c19f0b8a669c4c01a20ac5aa0809c03f9b77f4cbaba79b0b3bb267226ab457a98f3db49b5ddd76938e173045036ab73092f038ba4b8137ce824bb678eb566522f17a5b5906e56591cec091990267877d5d53d959c777548d2a324260e1b02a6544214bc0079088937967720405760e32111d911d6d74675bd5da8cfcf23971dc2f569bff43d9118f9229921d0b01f9371cf50e56699e72d4ffdf8bc0fde7b4cae29afe7e628894a2d1a83c160c4ef81f235b8055c2cd10171c86f14ab13d85a075586af8cf950554eaf102c403ca8e8b480087aa11efc9c07042c50b29a66069e574a38ccbe4196233ae7ee807c875e24b8f056e7b25bc7a16bb539ca72c8c9cbe9454e1ad0417417b0d40e109542e18e3cfc116ab87f05eba020e1218554d63e841feaa7cb2063beb9664dc0b366bef65a49456e91f554f627d51315df7fb8bcbb97000443e071ea82959140bd7b9d11d8cb9535a5afc47a08a87de27e18291a803326693a4f576dde707ca02b5ee92a30fd8cd837ff094060b75490f8848136453ac603a5508f9de19044101404a5f45fb167be250b9dbe50bb51217dfeabfb2f36fd402a9e9373fbac8d30c50eb415cc80e5b3ddda0861bb015afeee835a346a755d06fb0f83a043462650f549bcb0b353d421de2d171d9bff3dbfe67bad88fca379752a76d7687c987920e008aa8258703d05597dc0b0aee74d0e7f7e24552e62650383f794d422a92da0163f1b9586ee00f40d8ad8ca406d892b06cf4325fb2f8e1c319b4e1ac3ff43b0765c29d68efb289478a52694144a02fe0607bfc467af3d67dcfc7f3f3421be10bec530ae754f26939473c33f1cafba3964e6ab44be00212d0f2340f7fe3912b0bd8c348471ef8d6c046e4f372910f1c6f86f667901c9b7f6145852f392f2243074b74e1ea3922197654bfbb8f3e7ecd737c2a3c54966942874062f165a226a70ae64bc92d4079e5d2badfc83089ffc9768ff5f8e7d17fff1394edb4aadc9e9207d6521380e7a6503d3277c97ad1f287aeaf2a26fbef9a792f77adf052bc297e09 -generate_ring_signature 3f9d1e8c4afb644f791e59e8cd50f02ffc79029629d27d18462bbf999fa28537 6b176e3de6c8e0d8fabe2e2552415c02af6c8d2352d99c208af199dff42d0a89 1 0870ddc2441fb0194765bef22a548260bca7fe9f8480a961f108f601798dc115 8c1cf72b82661277cadbbedec6b11e35f7bf100ecee3cf1fa9dc46de1d9d1201 0 c1a128dad68dcfced3423cba8dac8cafb6c890e6bfee4595a5db341af268410257754821b4f4707e1eec8e99e072a5d4924aa408bd0b357c96d886448ec07404 -generate_ring_signature 21021e77c02b18cfd15c18a1a6a46fec6a5473f49fe7f17f408c9c5ad3bf9f77 b34901b76b34408675b429898c4c3adb74859e3577bc512353ce51e338bc1b80 7 bf6aeb0c9fdc617e09d5fb43f98f77c0e4db61b442411f17612d8f7d68030d8c e3134f86f35ff93536f816ee7c71a22658f0922dd6d977141fd3251117adad6d 0351df4a97e005521dfdae09511278b8789a7f095ef151c134fda3d71db05438 31ca8ba0c25b68cc7b0cfb6d37ceed81333f87469880e8a4dc431daf9b3213cb 12887b59f4b5af889620abf19a52a7bd1973e04d7b949ff683dd3da922457017 2aaba178d00eb926ecc67d750d6ce2f10402e59cacf46e1d60cd2bd2dacc7c06 ab66bb5959bfea90f0ab7f1d6c78b6e380a8c91ae5b77ee24357abfe128fc625 9e682a0ce957782de7ecaef9010f9bf77483a51ad18b513a8acf4ef2c7562600 1 b84e4b2a4b3c7620863d63acf8f2b62e6dc236b590bc8912b651a840d628d808a0983263e06be3a710fd7c6c2072657daf66861adb5c766c7f58169fb93649051b8712e084d52fec30a99117d5e8e0810548b58fdd947162b9493913b8856d0de65920ed19777857382ee3e463349f139c45a2b2b53510e379077e7a371c1b0566a9aadc5e070cdab52d60b41132087a2bc1892d8f5294515c595ec5306c68035378b35c912f0dddade9dfd15c93ce31aacfe54c61f8ca69c8441897ac46370b9dbe7e31917c7235b2b81fd805bb907677a52de7a1a10db66bd5b0fa822fb1073c5894288e20a392c5e3d0db38f295917f71b0d98af0786df5392169889ad104ac1bfdb0a87c41268fbb66995d7f6f0adc60f945e70283c2ea49b8eeef38b4051faa9c714b412dd76c2f7ea358d7637f1c295ec920e7630f705ba7f7373fe50b82ebfa730640a9f28b5136d14420304a62f19187cafaf131aecd7fd3bdf1eb0eb667b357b2e0f97a7bce57bb99975b44921c3aa43a23332a0babcd73e4365308cb3d66bab782c87ddab879ba13665afca42cdfc474956db57724faa7371cf90cabaf45e8f873564b4b606031bdc55980811dc78a2094bff14c28199403d57f06 -generate_ring_signature 953630fc2044cd653f7a0ba4d3413eb62f6e17867d2a24283d65c3ce6318f887 e901f99a3e172a3f7de853302c9ca5a1ef79f5762c13ae654c4259e8cee66e33 4 de453f88739ae0d8339d5176fee305db6c4558ba79cf29f7cd9d578ed6f93f73 2662a16a5721e8273db4eba161eed7f6c55372ce1b57ffab8347f94ea937ba77 9b838a770120cd96e91ea3753b6728aa50c8428a6bda2dd55ebb2ace9abefb72 7555929a6e983390a6d99b9fb21340bdea436104456f7345e6319e772f17fa82 47baf5064573771c80e48605222461043b10259e4b1d5ab00ee4c5109eaf0509 0 9e8b1456efb777fa6e495d19e01d157961c573f860c58bf690f59a28ac19b607be3169f6a38372d28f9855a9d92c5805908e18ed15b2510745c348159f262905148e003d9aa5839d2d4e17da5ea6a026eee750de02a7047b10154f30ed812407993dd3ae451da38187863c025e0d3a8f0ed98b20a1200c355174e76b46e2d908b7d480d1368262f147f71cbfd8f5e723a739677a316b6d9322cce582026b1c05d2a335ae99c77389ad718df8601f70ddde0e5d323aebfc709d27e6574193a00ebab62c02fee131511399a7c06ca2c630616aa1f626feb21a0eb98a9de5d471076fe3b331438fa57f4e0b84fbccc55b598874ef3e85bd11bdfdf6b15353442a09 -generate_ring_signature 389429172b85700ef011454e82461e30d9df22fd1db8366c615775683e19d8e0 999b6e454561a04399883e2349d36225d208c3426018c8a5140b5ed688601c1a 1 ae6e602587bb3d69854b8ddc46a38071e6987cd8dbd8e5317bc22ba20e568653 1202a2169995970dbfd88fd2d6bf35111e1a13e6b0f32b8bc93d3b0afd206804 0 3cf5eee0e7fef22f4ce8b9a84f366f10df2367d3f1d154aefe306b5e3706360854b704291e0010f786d30af6bd9c4832a008e9146448cee2300d91362d875103 -generate_ring_signature c37605f12deb3cc9723bfbba6a865ebf42b6f55ce8f3d6f097771ab2b354f3b0 fae39afd0699fbd2a2ab9403bcde544420b66224cba89e6ef4bada7ec9f7ddf2 3 7f973eb742664756b20e8dfe86e1e12a62ea6cce44e987474d3f0d5fd115da7e af79056ddd39d65eba37874cb91566c6ce0a60305380f8007535d2e7dfd7d8fe 720f9e325b8d682a17ec1e8c9d118535f2102e9e03b570f5cc74b50e8ee1d12c b57bfcf6db2519fcc43ca7650cf3248d8385e5cfa280d6d90dad4b2154e90b09 2 9b0756729ca85252b80699d68190879b0dcc3bedd62628032b5df0437b04ba0ce941f1d40b98d3c51508b6007946b6c74686241369caf65df71fc64c970cc503e9e09d2069a8cb439db5c3397e4dbbcd0ef7fe8093a2a8ab28fd8ad40412d3050ea154ae7995347014e8e2b7d44f5243092155ae20cc1b7079ef14b970d6ab0625cdf3a8d97f49ef6710bbdc01b5b198644501883e1f273854627193a5d1690eabb98183177abc826cd9b01cd7a58c47e1a33e40330359158635b2258132af04 -generate_ring_signature 37671a1d249e1788e7c6193b699c5e54f6be1ca35714a3a3e4bb5f45572c01d2 e0e86972cdf25612d13ee325998e27afe1f5ca20cc558021bfeee6b8437062d7 14 f41482621e6d7291ee1837f511206f285589e82270c54f3528e9188dc39cf6f2 ba41a5e2f314fc05a8f86861c2e3a05318556814c9d209e4363e363476591f6c da784f4125cab4638fa28b78a7e1040b68b0f4b782bc53403d9b311d1c8418ee 1c765f10d5c8315d648a1ffe3d3c81bfdfa6ffd0e32935b3f4e63f3f563afbc6 107c411025027e2d443aef21a7587dee87fcd8d0201a679dbfdaf4f2ab19a2a0 67d5eda8542bd0951035449c08bae062f28a7eae03acbd4a85c70e98321df6f0 90ea7de0f1638302ba6017957756f60b85de1f18d415b613c0c7c9d1fee2b020 714f410e3f73569ba9dbb4b8f973b1432cd573d33d24ef35ae7cd2f7ad385cee f2c0ee9553a23167d0e49f274abc2dd3976c1cfb91ec2254c8c88477f46ab46a fd5de7201cc934f74b307d5f5f63758e633e9d60fb9d3eaee47f2fd2856fe9d8 086925bfc05dcc018b7b0494d8743328f5dc9b7d6078c3db4f03e2d8be5e2aca 8fd012389212df1806ac761c9a70f1e358870177b639ba7431cf708279e1b77c ae9c72de597032207f452e71b0f4885a4ec933c9908068b41e9a1a5d08eddef6 668fd60e30f1bdeb678c538fb5d94a1836b1e038f20409c6608f857dd3c47bcf 1a128edd23b4090c4eb20ad7ed850a3bbfdbb4bf0ec91066d34d3b8d90433b00 4 23e5f4060305fe03b4d492d0373a2fedb9484be4184b84471b5ce2aba441570082d6a4c0113e3a5361666e2ec206b3ac148d7b6482bbc5e74fbae3841169eb06496f4b5f529d78fac4f1a59f575b5ba3fb14279f87d5a37f78d9278ef89a5a05792932728e7b18c071827b9559f5d235486ca241b493c0e565fac373dce9af00b70b72afca797e9eb1300ad9c8728f48045bfe249a1ee8d9ec772dc5e99a8000041605e39d17ea3b20b2844e0efaf113f5574092b35da1e338aacc48c5dd6105691990852e49b5052c83821156ee2f8cfbcdb30c7d95d2f2af56c47f67a96a028955e7051907435e74216e0a14770ebbef577155afa6c30d881df0ed04625204c61527a870f853582ddef3d3b0cafe64c83e9bc18687fdf21090402459b95004fd2924630e75e2f476df7bf10c9d7586543ff728c41c523a4d97641b7a9240052069adbed7a8ff2d8531f5a2139422794fb07ffd9c6bab272b322925a4148e08f3dc866d6c34296225cdc71cf328f04119c468e73a9be25d6fe611635ad62e0719b9ab36102bd1f17d3e70f80ba7098e146d80a510b576f5a0c1c7e21c6f38046543f6d0aa261413de0199f12ea05bf03f0412395e91c63a48485845e362360fa5d41f56e746084c8ef2c6e6631c2f938760d42c18bfe8ce2b830701e1a3ca09a8493e9a7dc9ac1db6e2c0bb8ad6bb5ea0c95faa2dd81e563a28bab999fad70735c14ae16d5e117e7e31e0eda7139dc3f3a5b75f78cfe2a898ff148b67a99c00740982d7425b45b2e572fa458dc5c965c5f3551b3a89ecb2b281faaaea6d320c0e9333342bae47309030877b42c6ebd3f798289ad26560dc2348637122630e0e39797c36c61d362444e3001ea8c214d6e343b15b0b071e2445dd8374adc6790b7c6a36fc24eab5b7e25fe33899af72649328d30e302e7c79969fa4bedaf0c404c680e37dbc3b2060459ba126c845ba1b0a14d3185a06875a596b737de3f0ac08f20677c99968b8630258e19c531aec38818cdc490e1790abd76eed78194fdb078d4e3327576cef04c1e2ebd2e8ccff0669e305da2d76387de39f0886590cfe02aeb9004ca8702de77a68b87327cb5baccbb773350617b87c853baef120a41e0bc666e3c3b50e914195085ccda3214dad2b79e2a855191c6c2eb8e50713a108092ce90c7fac40636e542c1957e97ecd5d83a5db1c56d4c6b09dd1d0e880c97e0fcfa64a73c3394fffb771ffac7b429ee67b97d81d041975f9ae0d925800a5370d -generate_ring_signature abd653f7ad7fd63df48ac6a7e0192cd459c65a8240f9d2cea3676a8bf574d3a3 4ec5408a2203919766e99425df38cf93d465ee4e7179d4140f743b780950f7ff 127 f7cc7ad1d5529686cb49d9a39db137ad1c4c480bad36c87e9874db399df6e2cc e5603615a39caf26768f8f006d8e7fbf75559d8f20f1d668603021cbf5b06ede 35c398f97a395727bb667e2d1b2e4ee561ade6cdce28decb955ea40e3dc81b19 39f7d4ce324bfa1d831a3ac2a26784f4d9858a1a7ee913f0d753560f0fa205c7 3a70187619d98252083118eeb6c43d9f23a441d081c06da5cf1538ae2f514b46 324c0c07fbbec5cf493db7a55f4f2944a88d66fa29495c17d2ddd7beb799a981 8246ceac0bfbc5c3bf76bf1e188c6edfcbe7e8a8b92c0930a0e9f6d7d9bc4efd 46510f6fe33f0246f667ecfac5e9d01e62f9a675b3c9b43267f7ac6e9e055eaa f0531b6c747fa76dba4a033571b5adc2affec1d8ee7c3172aa25a35643118ac6 c3080d681c17a1a9294552e508fbc3a0183a17a1e2708fe32552580a44ea4cd8 dc56dfdce49cdb9221d288b78779a6bd84c4cf8e3c5d7dffb0c5ad507715f174 24b46cc382e88800f74d1eb5cd8f81cf60002b5ee67fdb2f7fe69aa3f921bfe5 28672e60cb393cd812809e8092b639c73e81cc2e0f8867bb2f136cde06c4876f e1ade5706d9f09a98f177a310cd7b8cda1bb72141283205abd27a1db228d8778 be543df678f6169184ce2ad48e7830679ccccfc52a63f8feab3d5ee79f0c1054 b464788b8d9c73bfc942547d9a2726e2c63106f18e322f9b690efc813c68afb5 4fa40c9e5d07a7143203d40e401198a589eb8751b4dda6bc8cd1681586150590 ae63e7c95e21ee618a4bf5f51a9bb1349a56e13045c1ffa54d51fa732dc88a98 788277e0c0c724a631417c4caa078aadd6dd7ccce6a2dd3b6126490f9cb29b03 0e7f64e648f936b92ba48d50f642d4c59bb972837a8d0c698ebd3f6e8d834756 8c9b5957c1c93c492cf3ec80493c9a2ca5c8a296b47c45a6ece5a9c1829249a0 8fba8d91bec11803d4c5762227b2a87248ba4f468c2ab1b4b99d37f605b6c942 25d297ff24cce2c8763580a2cac0775cd77a4625f877b6ac39bf8b8ca06eb121 983429fa4e9308edf662f138a32bb5b5d667fbad795482bba974751c1cddb922 a4bf3f834a9f55d2667a98958618e667207557636d212af92a5f6334c812f8a7 f35b326077681c3290f31fe27fc154716e58b7c9913a77cced12a56d1c492a9f 323c052da3cc1228ee8c14a16ad1c955df440e58cb9811673f49acadcd111954 f01661bdeab726471018f51d247c872624fae8e5cbf34071c49a269957756e0c b67dcde3c5613b2b3b599264f06050fc144b0beae6e234830548b6af5a4ccdf8 38af053d20c292fa28d084721700d138b911430c73f397ad67cb878e115b2beb 27c40d8f771f20559e775713e71ae041abe5e1814e6631ef3eee841539e2d262 7a3a321751c2b1e32dd96af7d33d60184d8d42aedcede75d4e22c9572771d6c0 166a8a31964185aab43c20927b122f4457005786e3d8594cc5512ff88f6778fc 37d33c370f64d5c21fcd80739846a39fad9eba9803afd1e3c3db6c933f600845 68ec83d3d23e6054492ea161ac9fffe1a42ca54f28038bb1c42d3b7e29fd333d 5384f0857de1ed5fa5db5755828eb4e117465dde04a15a90215612782e29f4c6 f93dfef70ec9bced9b7830d6dbce44c1aa4eb671d5ebb3b815d654224db90f1c e386cfd691fd2c855bf8a5c86ccf228af6d9481e38acf5cfbaa9d8accdb6f740 9380536decd8199c51bb9cfeccae5b75d423f18e1de0651bf9419cb9b484084b 4689cb44017f37ef8ef63fe68d4ad26018e7beaf3486bdab9c6c3c459c3e7835 2baa6a00de237bf2bb2fcd3d106601e57f33c27a1214ebb317f53f20052bcd73 c874b88ba9c5e2ce74996d132be4879f2a589b21efc30314e80d0cfade1958bd f1485b76e02c7e9b402c577182a4a941fd4c60618c6f92f7ece4f1f03caf723c fbd10d5ffeacac15e16cefc049ae124ee6dec10c66b6f5b62bf21d8aa41acad2 f48ca5d7ac83ea3e8d9adde2745fd6f50fa7639824db2b311bab61adbcce559d 0d676c1b31a9de877928419723a5eba5d37b2378d2b3d9e846b6cdc865cf6f6e b45daf0605d323651751912084602a122b3a39611bff1cdc36fd74d882e17201 0ef240390d83a22f5e7b9685545e94434d7f667141e55e9344d50753986d4a2d 138d36e66f4cb547e3d2e2e32856a10f04877cc45a4d94d2853c7ccb9c29a05d 3c616b6f7303de221b0eab85a33ce48ee0fb91b125b69c2bc13bde24316fb146 c808d1403d310e1128b18554da2a8dff773e7711104495ae2d4c4cef80c4adef f00a9429229a6c135aeee20efa63cfadc5cb264f965d5bb99c2622283688953c 9f763318111c6e949abe452fc29319e2c0cd855ef13973355a458a3b7abfa5cd addc8266481e686f0120ac9537d03348a12823ba9ad2064c8fd3c056af87d9c2 9e3163d748d6fea21146280df9c2b01c6b46300a40d5d313749982b94caf43b6 09daab1f1bcb2f17d13c0ce3024631c834b845ffc29656cac32decbdceb36dbf 966e9351376dd899b4b8dbcae80f03764a7f67ee0d1c883ef1ecdf62af6a4c70 526b72a160bda748d06fcba2acc635f2370c642defd1c19280ce29111912adad aa37714f944dc1ebb4a5bff29adde7ba2b3bcf1298930cce423ec8bb71b46301 7cb9588e9e2a967a8a5a1486864106a667a277e28f65db460b3086772f06a97e 94fb2fa586d2e0850db9c6d30b4cdabc2f2f12f59bd1c9536fab74d9766f134c 1c466c9515e20c18a56bfdd03bb7478c965a7d12d702d7d4957a63a560d10266 609ef0ebd972a504c818929e4b680aa2d3af312353eb0f8c886fce2c2ca18434 102793b591bdf4a26d4277b57abb796e5066edfc167aea07ffa014cb58960e75 4a94b3f8577cbcaec6b0dbee10ff8f66320707497543846b19aec8f922b4293b 6697ad22d8ce84fdb5fc90cc5af87d5d2d962de46cb53ca843e9938681484d68 18457de093c4a00394f250ae8db6cf086e33f6d5d14dcb3040efb86b3a3f0b04 aa9742d9efbda738d62ab7625bbabcf258ce112757d0278d160b15936abf3cf1 76bc78c14142bd24d386b391e510a448084640fee6d5c89e78912563a30c6082 5a31d2c3cee04912b6bdee1af63d791bbbb9895c97d40f64268d429c29142985 575e2c99943ee27d8962991068c135d934f8d7189ec84114dec86da9f8c86d7b 653841686d1dd0025aa32fc36e2ec002f602d6063433722d32b438d5e2d75319 522bc0507407007529b25d2eec729a59c0f60e98373a0f539aef20df7f53ea69 67feb74336641ee284e032ecba89e02428d2829af28d12b0e5bd9376a60be00f 3c865f1ca2bab0db4eff5eb9e4108ac90e1b33362d43910ed423cc670035f039 d6e4c9d3d9d3d99471e5973327d308fe8faf93727fabfbb0f748c4fc9fba82d6 d70a8e2810c33e4f5ce14666e6282b71db8ba4b4f25984761a61bf21a80098e2 20202ef0bd6bf3faa3dd42b314b620e15fa03cf525b7fafbce8b1f620c86bfba 8576732069b9c355cf922f86b90041baf4d4d44f79055afdb35a958f8ad9fcc8 5844694e707777f2f9499d4bdf209fafaf286fde9040b51657217add3e345bd9 ebbe61e0c6be3cee2b8f2825806423b8368a7f649a0c842fe537873674061d8a eb676ad1281e502de98d3e9c4732a095ad28db45c164ce7893547fe6d776cbb3 ee6ae2f3a4e2c55c347644afd43a8e3ba646259a4939ca5d0acba778d05249bb 377de8f232e2702372e38e93858ae04ee8729ff65a76fefd8b961e64c4eba497 a0ed9e2d5ff4c1c414edb066792f9026692e49855bd6f0c3d69a1ac2413feb9e 1f6c215399aec9b4d8bf289d372c2467f560896aac9b941d3e3c0646c4611f79 a98c0268b55e338c26e4494a4c8a8022d9653647103a0f1bcf91dcd8b3ccffe2 7ee898c856b5fdcbf8003dee310084f8e5d7553febd3d4d9a4dae9728ce7d8f6 e549734c11a2460d6a99322b248dc590074d36a74635666c0167f4d6455a9b10 801df1a8e2aa0edf9d00861bd977b0e4f5d369c182765852539e4eb98d58d9d1 6b17009bc4da1114f1c40a128a5f9238a5ff65e43b0e3ea6be474245c63be927 86a0be9a8e802b0a83eb58fb288e8eb0169085599fabe73df43d98dd538e4fe3 b52cc90b3082ea8bb1c16f4398fa9852f1d7bb3984701dcc59403ed0ea11756c 2e093e60b05a8dffaab61ee017987832247f2980afac47bdf83cf4d4c9b09fdb 23ccba870003d977788fb87907888460551f208dec112af68b493e339324fba9 4336845a60783d068c0693181b155ff8a927e2ade96175842294c5269bba5fc0 885cd6d8605166246c5ab4add221064ac3307ad12cf0d76961527722baff5b45 3640a825842e15ab7fdbd183861ccde121bd494d55dec192307f6e26d7257d42 51e8532b10c76386fa77df1f0972770a67b83d877946387075f159f58814e449 775cba5f1da6c8d6ec21a32821189f46c4acbf8248b236b1e14ae4550607ae54 6a4853aff074835c48ac5fc3288f185e2ec3888ac41ce5fdc6d7b50abfad9f66 73789c6ec8839b4003a2045a47c9602f75a55fd2632f4c1e9361f939178ec98b a548db9423100cba74cacb67611f617ba18b0b65d29fd55ccab9f81a0613f653 e89c5116940301a8cbab6c88056e479ef6ab6605b0ca9cbdffda08dfafeb697e 77ca3397a46092795d90efa06d1bd62da05986b7fb733ef666fd387e39dccb91 b16e1b9bce92e7e72834af0964871ff655d94223f297e2a916bc054b0c4f8a73 b53dc02837033e165910df5ba952c0ba9c3afeef594666dc0994bc8cef844cef 16e983fa02cf9303daa709d001566d3683db349cbca4ecc9677f7da6a6a873f9 dd6a59c284336c7248af37f73cd62638b4a1126028f3088f7809093bb9f40c43 ccebd0ec548dfe03c8576949bff066db53c08d2ea96fb7bc3eaa2e35bc4e549b bad4168d208766a192af7fbeb089e80fcf3ba50783063be866b2afe7f2bb392e d45a233a18f241b0ebc2e27342eb7d059257a766409c5471a725cb13c4331ae4 99dfd92c18d6d113ade3042702cbbd6bb9a79c0c7aa934fcba3382c31dbd7e7e 62ff7d2b14a161f835ba981bf2d97470a2df1438e2c1252441555a898e1e0aa7 ae772f8ce1d252f53aebb7307c17c4e0e7d62f419acc3a5ef596ac80f5f95d49 95abfd3722194601a8532044be8d20e29d027d0e2f4055bfcb51c000439dbfe8 3ea674df981be77af3101ee05efbada58aa84c552b85528c9e96137b0b317f9a fce584e406a2166a6e4bc7576e45ef838e4ce27d2065a45a19320a7baf163f01 0def1fecee4b5330a6488df6f248df22ba92af84bea002746a0b647e50941c07 d692409668548677cd700cda6f35836b205eec4de848518b6a883dd1270839ae 7e1d912ebaaa566002057b1a6a174539ea9029cbd86342a8aa3ffc748a36da7b c281754f3176f07b395486b21e69fe80cbd853438f37a25af70b8becfab39fc5 d0accbde0cfb2474ea79917c09a5c6948393d625f29affecf51bdc3578e93e67 0a299a649e18631ec310b45ee09d737eda2cd32e6ba100ed3bf0984ff88b18f5 e27bee21a8a3745f69a8bb71b60907892f43bdb270af1d4e682a28112c80e4c1 d8f5963afb20f917aaad9e0d0f329df6daa524c0c4d80627c537eaeb7c6eb783 0828b7115e8631dcaf475cebb907e6aac977d9938b7739617e480846e8b0833f 4c50e16ebc84e90f0d414526b053d3db85e9c0f1273217537805d9d7fc03d001 82 d0cabb9447631c59067c5656d09ee3badc392c06963f817317a84132048d1100f833db1780685eb559d8b88e804e597d9d3f178eb46f7ea3da4980798291560fdcda32f5070f1f3462d1fba3b8662955ffc6b1249912a84519ed6993d1d5920a459c587bb6be73a73dabf95e3cb87f608ce8ff0d26f62aa02f8469c284f7af0bf15dab84d8eed10d1152f500cf24a358a7c52f703f078cd5fe9fba6a328a3b0988ab8d821c5c0538d14224a6829c88d43194254f8447ec922ade8aaedac07e03939440b9d880f5b78bd216df10dffdfb4562378fa48ae2a9309bd887b0cb1d03f995828e5eba9fe7e2db66da3322b19f035b2f4c79f995523d5c6dadda9ba20ba1eabce9b12cd26c80df1e7724c96371655dd0c5772a0a652e762ba79407290dab34b4331aba23d95dc8b61eebc132eddca71e16f9241b6435906b97e4cf54084977bd6e420fcd253edf6cb11ec2e7aa189b3d02163fd94c3ee64552f6c9230dd16639ef54a3f205ef719abd460f6d4d6667eaae7edb6e87d717977eeb950e04a3eae2c2fe832d539ec3ae4de06cc8bfaf2054597f56623e466190d0fb930b042bf2dff9d73d31b3b8b2d6a713495248597fd4362245d645c3248dee19a5970bc0dba8a070cab0a0b478fe2053c4faa28bf295baa80688954250a2907f8db20d218ef14fb0035fa4f663cbac04d8b78d314bb0d6ab1b3e7a53a7f760048f0c069069188e313020720bbd60614a5d68a2d0805c64d73d3762e44ae6a7b83f79036e1025915823feaaff5696db8cab673ca6ecd4707386202f2d1cb68016b0650517f7cb4fcab6f58bea3c53ee72d245bc6e27075aa2027f020f976f73f76688081ea64d9ff6b730503800af08ceb57529b0ea04e07e994a81d5a4b9e51480a10e08326a66df552b572401e2b2f441a67f71e1fd0771d204981d619351ca0e1e0c0d41636e99f7e3f3007c8fe8b75c0b84e2756b2b86f7785ce81edd3a7c75c507f46b3a6fb8b9c993225254bf4f848f71121baff7ee788e808de4e9222282000cd2dbce4ec700c4b572ede4794dc4ac19dbb0181c698134cb06acc69c0f6abd073b9a139e444cb973a7d0b1954fa10286c28c9b7847d831573c2c247be3ebc9064ac329185935cbf456a567bc6752c8a86e5d89ecc2e82e4913ea4c73d4fe9005b65db02ce67ae8e2080362c4e41bed6228e9fc0ce4095c3290650a053ecc9c0404ff3d1799b999470aa61fd44d06a60c34c08ea4705afcd7d5b86bda1cfa57070ab4c723ff193653c5bee763d016b952bac17ab62062bd60bfcf024f5ff92806eab845e34c83b374a37d962442784bb061defca3f86bb92d3f89fae544ea6f076f15fa92be0903d1dbef149574c9976297e5f0db8c67a2b380c4b25573f7b30bc472f90b8deb89846be7e4458356c5c65a97008f34bbbbb7101ac47aa75b9f089755a98602a5bc148cbc882783f4a9c72c5ca4a9e6209585898497b1f7488200bfea01fa829fb56834b0e0944e4d3491c56948447e038efb74b9530f73205a0464ff8ce80092e9a4edd49f578e697b14f38b675e829ad1ed5312887c5d644707a8d5f8784c1b59a6239c6d155f12b82d08dc79c14b1cbb83476ca859365de00e9553c678d595507f2aaefb206e8950eac162d40e342c07c20a2b3a3e272a720fb82d333c3e66aba6411df3a35f3d1f7e2c2181901aaf53872aec11b4d2d678083859e17b45758983b2d3f6d2c143c3f5c40250428a3d5610d73471884a309607a5ce1ba1db3ae9a61ee61b992e594b66277f7172dff0a517c96e245c2156ef04f75b51697dc2d3d55c017906ba365db248774833538edb58a3a9031de8b2150b2cb1f8f9c8aec9e7514e0bb38fd7e7dc5e429f4d10d3a8591b8d4200a813e107f08aea7cb9539c59d03ece09abf6997de541c4e81d0ccf68e3058d5849fdd6038a6e0af5d7f8e5487997b62b5c4298ef4c1e7a99c8acc37ae898074d0a6137049cf07a1aa9004bc2600b5a239d79048b835f86cd51906a95a4e0a336ae5a330fe026d96b15011a4b03a514c66687aeaa0c13fe27e3b21ea3d04bf98bbd088502f47326e436baac4a794f1ac63d8657ed66de24c852d6e7db6f548ad4e1b8bf0f2e29604974b48be27fe24034f8609edc3a481d3b298b4bc5dd67e5493258a80a667e230413426e0d82f6a29d240977fd49b506603bb766643f5a23791a57c3093b5aad541b63860cae683927e6c642afa861403d106e55fc1d97f5ca8f80590d6da2cd340900d6ea679aded9df38c442a19501f24a4ffc4ebcb8cad7cbf4760bdb4b6a1ec37f60ead4963aa29cf94a8a817df929d39b161454025db9ddddd70362a33d3733aa874f0daeb710796b67d898064da0a20e8ba0f69e21fa376f220a6462b340c0e40ddc53357245ec302f85822f65d839ab7e3737876f2a488d5b0ca65fd2be689044f32ec0376f14b1a8e991ba8691534f6ef03708670033beb00e1c8cb1df6caba8886e7c616352bfd4dec0f7736dd60a7c9572e1d9a75a2b210029bbd260ceb701b099acfde721285fb12c0264873f43d6d22bab3e3acfb86706d51db3b945b88cc2bdbe7f79322abf30242e551c588d53090fca816f2cc84a05149ead4160ddbc28ff63ba1db4e1379b534653528045fa03c329bf0497f1210715a37e457b737a053bb4bbf79b8467c4f08d1a4b710f26c450db42d2ea5cff03647c8e59d58e92ee4a069ac47b2a2b417a345dffd439e317f258219eab3f4b08ba431e34c9d7a500d188d827eff15effb5adb21d393539dbe558b3917bb30b082722fdc84249d1450bee8feed23b350448c9c81c3a55b096c165468f3edfca00d52c67cf526ecf33935770cb960cef064b9fa5daadfeecd2071a3bb944af540b776b93777f1511db5bae6777180f2c950ab7156cc5dc1801b4384ab57781090997fdc8da59c33248fb118f6f0ce73b9f0d704a037ad7f461a0f41a55174f0f02d61bb1a125c6aef7960495b75016937711df3f3cc0988638c1244f256b307104283ef6e1fb0ae4f410a2c008cbd11f7c83bc605f1a944b7d55732fcc175e5f07f61e47a48f7ba75f56af869ec4c35ee8c6221388a6fe8cf903a7f82226730108faf674db9c9933fb7f472401e2b0710516c42cf225b4b92dc9179b5ccde34f0ba8eb0100076d1f0e4985eb3899cdec838d2b77b211077754a829ba5b00bab306b2533aa2cd9161453ca0ebd2c3b01c8e84699d3202c5e366c6e00af61f9b11089a14ef51b95e8f69191b66ede5cf9761928041a325e5b005165947c4c03bae068343da0b8d6787cbb76a210c6993270be23f9bda32420df5ce92ed71e1ca5907ba11d83d6f78a4cf82ba4bba67f680fbfa8f21d3d21542c1a64d096133b50a0263c13e3c9a0089de524433171382181a2382bab9b843c4b6bfd90fecf2558e00051658a22508c135be89e332ff4e9501f859e83cd96332e9244fa4a03a0f8e03d798975f109c75a588b5d17bc9c95e19dc09f94d922a931af2ccdec06cd21c0b2739d739bbe1db39e2da9d6ad72042eb236ad1b9d6c9cb7331e15cd81b728600a0511670c8f1d0f9498e36146a8bfad5bd565ded10c2e4350fca85e19807750ec7433f0862b35e7136183e5cadd1bb3789fa9c45c62f4841c7cf6cf8ac1b5a0cb3216cea185191b2697e15c38c11816ecc530b2cbb067d70588c2a1a469b460865fa32d45b876588e90d397557a83a30ab657b6e7e97478fca81e3175414e20d3f223d3df672806509b676d369bf8095221d2e83cf05852887b8562f27e85600a52534ece6ffec518585369e603468a0bf0e5267291dd2d2f8e1e568aebe2a0c9dcc608708066c80e39112a5f2a8898f8adc590d9063a851d1be1f1771d5ae01aa61fb93ef39d9deb337c570a3626a2f3f4931365376a56743a22ddd35f47d016e12bed89505a3db2396c45e23cd1dfb7adaccfa1a25d9d6afec6a6d1c10df09ea56357ee470be6a4f5126c638db97c4f2a389ddaf883ec020c619562f003b0efeef365236c9ff90c259d2cc29570bf31afc3d39d680a30dc2551f6ceec9d607a973ed9b8c888a43e77edd806ae982cefa1cdea0a0308946627767595ced46001791e317ef3f5f7c2de8f8233bad1bf1532abc1b27d75d27a8023f8b85305203c6ffc6c0beb7c107c45e032ecd135fb9304d7ba9fc145225cbd26bfcd33c5602e86d8a55948bdba71338d5e2891504376c4993f5c428666b77546b0ee6804b08d2de92c2f5cfea0a0be135979305bfd753b840f201b3d4c657571c787b61680910e7e79063b81d6e23261b62694492ba077eff11b21e24d36b12e979d907880b668547f23450358144c02310a16c7ba2cc3d5ae40f21ed1afe6ec48412bf8d00f8d047ab9e959cb708fa5732e59d826c2769c8d39115acb794499bd720094703ddcdf0b0085a0715c8678df6e17ae5d335df411640de5cd830d7fb83fd8b44092121275dc2aed3e52576953e672bc6e8008408c881b61205d29ccc377431900a863ce783e08854cb296570dbcd915c83278a5c06614f447d56df8e934b5e5a09b1fbafe326ac97e45fe2cfecffab74f64d7ae75e31f750f4470b80dfbcedc703af0ed97a656689ad2253af666e385c04e2254184e294e93fc55459e0c8cfde0faa7bef377453960b8bd144e4a67143aafeb93f3895314bc6eec354665d74c30b536717010ed0e006d614d7ea4f66a72872cd91cf5cbe4f96f4005890ce513c0d342935d01316c7c203e3917cf7a0ad1bf1750ff37f146a94c5015712dc08470b8266473b5ff202a9d7b4f317381686d2d58af6f7c8693cd5b517eda879603105c307c62e00a6047378319c5cc013cfde28950f8b7804e126ae71801fee0a5c00004e7ff8f81b803bfd6f47578e1125ad2db84493095f34ed602297991e3ff207bd54419cd577cb09ae5b6316e25ac1c2cfd4f89a3af6e7ccd2a6f91a187d2d0cd6ccf6e0e98928855bc6cf1e0c78abe76a64d9f300a78b06748a9a79d2832808f8826881c1f4de1c981acacce079bce2425207961420e88787108ceb2254a10db33f7ed9abd936ec22b5fa09103c20864c9645c48f459499e2b8de99fec29407c858c429b2495de220fe24113ad3f1979fb6f15cba254c6bbb452a6b6638f90f8f388018205042d7c26a1385115b6d97305e51649f88415ffefda5e9801b7c0b280127828fc62f771da09670078bd53b7a1c0f7ab483c72dc881c43c59c20b0bf443f077861ed6cd8169ee62b95b0ab5d8fcba335a2e738de0202d7bcfcb8f0f665a25bf643d59c84c16b6de2ab3158a64a56e607a9419936b8bdb316937030576c90b147ba80251ff45acd9362deef2347a46e30d16740b7d6f44263c1c1c0b6540e2983ac304aa152a28690dcf573107989b3c7e72bb0dce9d9ca747ff1c07b98c8caba334ac334c77ac11a35ac3dd042f4a682697b7e21a461fef0f584004b8b77c4f84fe8901f7ef7b1b469faa05e1850c3de75c389561b70e03ae8b25087d60095c59766172690ab5984edc8d09aa26858b9a7515eb67f12c75d6071b061182c4a3db65334ea499f5c0314f794fab84a4c9ba692745fcb93726666702070975c3fbd68abf7d829e8f011821090233e298fbfddc3771c4a32e7789d1870cae55bb6725c3fe23ac65a3021590e3c873db6eb499b13a4a5b9e1ec6c986e70e48008b04e7fe7604aca5ad73680b55515f32935b2a9af9dd3e4929587f65df0de6223ceab75eaa447f1a5a710b6acdfdd84f85ed4555035471600b9e4ec5e404861b299295881bbc77cc931fe0433f5b7f3bf59c247e63968820e1e9f601360a6b032bc837e53a6f362f0de6fb58a2631e3a5747ec8dad4e263b5e8349f2c50019158309cd5f64239982f6b70167bc5091919879289bd552afffaaa14f43030fb924ee73fa988566e6c47dc603e1a6e88ccf2a0a80ed55302b6bdf94a605fe0f32f7ed12028f5de76c9ca6dcbde595222e594c6b93c8c8be341d6c49f513480ffba7e0ac8ed96ff53aa6276702b9709dedcf24f4c2540a5efa8f5125012a1d0361c0f92b7e14f49f7fd3011a5ca3d1be0e9e03be1ff94da43268ed12af4cf906a836a2bc495bb653ac4dbc8c11e79ad34a9ef66126536f38b7ff40b6d725140ae85396b4b26fb72f19b30e805c89f0094898878fc48c926e71c13e204321600759fc9546bf3eb84ccc62e20c1949aa5ee092c1897ec237ad1027ec2e576a9700693301c0b8d4e9e831bc050d1ee8f415c0ce32a24fff5ef50b79c6060f4a2e07785956c6189a19763bcbecacb60026d3776af94fb88d76186d569f6011bea60d932c0b09186301d34c3a39e1ed256bd7ae5c05b3c13a42773c3f37eea372a40e8f189c5aded55276bf1006cc0d0a37257056619f92995f24ac70f6e1d7c4a304c9cca712ed6ec96bae5a17b3a3dbf089dfdca2dac6e23b0b5da1230374c5a10ede5032e7de45ace504e48811673f485007470633b160ffcc0de92a5268ce4904446ba2fd351bf5ecded525b8de01e002382ca32200224e47f2997cc9de7e9b0721fab6ab692e58fe49bac57b8951420774dc85baa0f214fe681d5c6e34d8b6063a64d70dc6bf4245bcfee926c5cf78d3defd7f8cf6e6e3941bdd4cf220f27202cf18f1bbf87f6f21abb7daff15222df52b62856e7f7b2baa284687a2dbf62f04fa376b5d93a0663854dc3390b505001368a54755ed4a3cc91f2564bcc1d63207651def03eb6a2b6fb686a1ac11c6ea08e8f02383b21b0bea3c57051f2246c50de206142f69ad7a051b23aff871904a74f971bb016d482a99c30ac8889d0768010d6d9e94a1ff0eacb229ddcf9ef67b5f54c9c04b3af634e1ea46831afec0e001fee3fd46cc10d02225d04d26b34d9599d74298b272aaa1abbd8a1e338935ea0f1cffb6518a9e7549762f5c5b4addc6576a77302c7ca826d49b517b1947d2cc09e2a82a758d7acc912d9de4795c2bd51b988648d7b11b6a1a221a2b70b412120de8ed32cb44db2c43c6016b3767acf4dc57cc27d10aeeda01a2669bb69c9671078be05f0081a399727a500508717896c24b7d92416c673d24f30336a4841ca60adc8e12c888064c120c1f5f8edee0932374ae62a8e0634188bea1267580746106c715d88b86401ba01b5818c63e52107e24a1239effd48a3afae452b050322e0a30dd158b7d1617e54b9c4f239eaa722f670f1233ecec04d5c223af3417966f03e107ead4bc0dfd6a931a6eb99c2d5d6cb7d9f3797902b06e50049da9e31b3f02963cde5e1d06885c6da542ba65f332e09708a8e3bc2ebd5571e9cc45f3ff4c055a41ecd74a6fb856049637c6ea6b50b7272cb023d805f179296b642c9b22450a285218c637538eda7c62bce016474b6ddde8f3f5a2cbab94dc99ce982d47240d34ae96df2bb80a4501514df26fc711f87bd43136896087f8f70153fa75478308dcd77d7b5fd65fdd1980e4fdb1b162af9e5319ab3a7359c436136d89274d68022406137fbef3aa02a430201edf4315dfd91ee7f768bbd0ea66e8f35c04d816019555159ad25039f0eab12b2a244b9a496f689426d224c33ea1ffb57b3564a20739920a5d7cf66ac54d47c45877c86896dd96d8b530a9edbd7035c1722069010cff98fedfbe615ab12dfdc89b954d3b9bf0bf8d3fd7bc9df1f7c1dd36887715081f1a5d6e105ecb8804395cd65b4134b28b2b7d8116118fc8c05b95581a0a4b0ecf90224a639824bddac80460d55ebf8e62917feec850d9c5fed88371708c090ec874c63a31d958df041b9ca37f6bd128dd7480bd26bb33e9d97ab028ba736d03cf471e66634bae963a8c34fe471e8259fb17e6965ff2ebbb279c40a55cf0720b78ea31ec64cb4e9a3242652b016eb308a34ab9b779fd9a3862221698de03380f6cf16e297fb217dea0cb6ac8eb8f22ef55951bbab237407f84c748c1ec6b750ec708a2f5505b8f48f1de0625fd58d4498620345bca8952d3e24067eda38cef0fbf70315d79da519acd58cfcdd0b29ac016bf744bc86b9967c6ffbdf7cf14b206516130088b246c0caf2f4592dddff59800e121e32338839f50d0ab708dd01600366adbdc79a39969f231bae6e76d9a6dde4bb01517d1ee41e0c01efb4b3ad0019354130b9cac0b34dcfd2078af5b1ee29e0f7a04162835cc88ee3631fb170c0c77eaf9213eccda45c0ed9f486369d40a989052ad711708d1935388d99212af01c452c1dbe2b3043e8c32a82f868cb4a2169847ef3cdf231c9e5029776e2cb00f98dd11063242e7c3383454acdeabe2f22b824c908cf8d5f3e62070d696390a0c417e7964cbffa03657bb37e42ffcc64d5a0b42ecaf103af00d3df1a33fab10070d9bf58a728c05e274264966234c25a33a876a87b02075a1c7ab00620e6110030c7231c34312960938d9526b3c949ee0534082d332cd459ee4649a1fbdaffa07e2719e544af834b1eec3eb1c64fd29d4e1c49c9e80910344c9f5f342075b2308efa5a3d2e7da8644a1637bc872d2f5b8abc5deda5f52cfbcdd13d1a5b2f87d05e3926b6344069ab238da7a62638abed9cbcbe7751e15099459ca9c874468120d7acde5ff0a32ab0bc631a11a11820f8c23009b6c3d123493cc37d2a111a1620d3197fc09d0bfaf39b50937eee037703d9de092c0724eb6ea761566893317100a6900ec0eec169462e681798c160f3097d94216b0bb8ba238b112e2593499d70de840aa37c673b2e1fdf7b9e654dff07a556ab53b26201ff2eefcb46dd20f040a395fbf2e10c26be9721b08e67b7757827a0a67b889dbd0960decd7227458120847953fdf2bcc35215d3af046bb92142ec4dea4d008d824926180608f8e281000d02722f6a884f947267d2c896c437fae2f92ac73f2af64d900c5b63d9102f50f7aa5cb7974f26f3ebdfeb28fb7792a2ef9f1ea313c5f3f81222a49bd1da0840a0236391a96c281d360e866a5c72e477bebe911c2a06ac338e1c57d4b2aec8e02b8e0b2e8610ba747e7495c3540d2ea35d673bcbe707fa87df23b016d58b0eb0042ea961ed2d75c79d35083b9567e358ef5c069942456282b1476cc4a4cab660b4eed05dcd63f6e6149f290e830d1197e621ac604830d5ee81c281f443d6b7f0db8b64e870f915ef180522381195de0ed5a26f259592dc693f5a835e6f5899505b73af986f032b559932dda202a583b388fbd4e140485ba385e43b755d7a8350508adf1317b6f16ac0779e095bb4fe4397abb1f0e68ade8e37954272a57910e036488be0f17434b1aeb76473d0fa69f4c7b524db6e1943290d57b935ce3eae405bece6e6f469e8d09e843054a94ed848fb34d5956bbf721baa011f91fb4c66207e2c76d7ffc59104022d43069035679855419a7a7984e397edd38289ed536f50c3ff95bc7305bca5e56967136af04d92f11dd9eae0b3b27f76f719f71309b3f00762d9b3ff2bf30db3e455044cd4d7d570ee35872411a40a7939556f965bc030704cb9b6e07e00246febe622536f6a5a5f0794b292a8b80ebdcf95ebf52e00a07a09ebc9db5847e97ee4a993d5f505f90b659a9d0203470d240771bbf2ef9530d27d57830d62e55cfc7d31e9884e915c5b7cfde2b78c0bbbb50ca4401ac6e790878d3296e91825409f2aef37bfc3dd4b74ce5f2784ab829ff2bd8170e110cb10a93c206549033f45f6a06c7df431d4c4c7e92bed0886ef8a9bee5134ea9a68804317f612e0da0f23075b53d3310000648d33dda6aa770153b0a0c04179e501f02de7b76c59b663785e74eaacf61762a7a1cb6b74d7728016c74742cca5e78de0162fa65a69e56504181391c6545e00ff37a622bcc8f013882dcd9010bab7e9f098085d0ae0d80f43301ed3be3ecb7b6e1a1083faddf87fabab3c78851c2697408e3c60fff2148f9bab332925e6949cac9ba74ab260813e69749ad24d18d378105021b7d1aed602be328141dfc8cf8ff982dda82a5a96c40b4f3ce751a3cc8790e5cbf929b4e43cad2e1af6245cb700a265b3bec4b61d1a8776020a5560a070d0969f33f8629c5f66489e3f8f90dac2f692864b752bdeca029221592d88e6b7409c3f15f25c5768b0edc343dcba5939f3c94565589e8077713b9a0de02d79d0b093cc4b4ce1db3eebe85eb1a44efe2d31ca2ffd9fd780d6182d0f830393522620bdb771278798511bd8f8eed10209b0fb8234e59f1e68888eb2ada93d10113bc04b1b723a36c961469377e4ad65aeb950c46f7dcb9d74f83f3540859e64728f40f283a331bc661e6ba172d75d2e0f1aefa8a7ec5a394b77fe75691e40486cb46057cdc2ea549c85fd72c81886698799115b19d689109a9d338d33f817016577b08c13865ce1f4fc2497200f9bb495500c3bc2b9b9cc1f86fd9a9c0af1c8e4a630031c3b9fdef6a1da4790ea9f05b99df5bb2b065590926d263a530aca8c2b0480ab50647b857f0bc80ee5e0fffe473f59a6c6d4b685fadae2a1b7611f719660f0a1f4413a52bd14663414bc0257002d2fa7e2e86526e3ad5790ee3690f14d75b0abae817c13196e5ec62fed760709a3e579b66863b8a39cbb0ebfa063f0a7cbd06eae1df4ed46c98b756353b18af6b7eef296863a3d31d619d34ee80e3953232011a3fd3fd645aad0e9f2d38af95d27f5c976a5816f76ef6e20dc70c80d31733092402858b465c1cd7fe50b744af8a58e11388e3a5708ab3834ff9d3506d0ea304851928b1e2d5d05677015fb3ec4e9beda7b97b4d2586a34840629c26f637e4052a9bf782c974650c2be26fb96282180550a6d90ddab197e9fe4d91952c934c0d87280b5ca14e21550837643977b73ad24d9cb03b3ee618794cd2e5a3155b6a02b93d5c2053f2a17df7092788bcab93a731c93a831984125ccecaa14dffd0c807df6ba0a49cd5d4c0caec4d670bfe168e4d923741367b3f50a03c1ea1ef863b08b25e4d118fcab730177457e73b5cf4faf3f4443c8521bd07a7df18329a71a001b56ea45a1663e3f1f11d8511aa49e15e3cb137254e954b7ca7f0fc610d26b20ac9b5c43c58fce8e4e28687a1805af6334a9a11b736a2402cad89712dac6e440572a993e0f4d4455a6863e6c6b10a5bd58d5d9172fa603acdd3c488bba9a2640ec71d62f8665458e564cb4523c1a895e096b320c5d5f34aa19a048ccab96fe20f50aae4942be9343cb68633d88f0bdd5ecfdebcdf347a55553a4b97816ee1ef0ae78786d7dc7502f778542b163fefbcb15cdac5cf9c6accfa0daee47d9f6b1b0d233da8e62abbf61c666044dd77eb68f3c5a79eb3ea99755fff33e5085a5aab0ef462fcd4d67f9c7b40ea18434c01390e6d3cda376622a166e0d7b7072e3f2503d78d02fc2c60a3f64a287de1d5653bb05d2da6f32f1b86b14772693d4e12060ea80457812ca2554ed9e44c8332b80a7383337f81e2a94ef97afa9a83451e38049e9d3c04b41bdebe0e1516a2ab8ca0674c707d01c82ced0a7c3102d0254e7707 -generate_ring_signature 1bd71e0dbcfead5409660f7e8c3127a3d0c42fabf9ad6c0d82d88016ea624ff1 df36b0898025fc214088fd247b1b2e2c49d8b7112158410e9c2bfe9922c43dd3 6 c2c9a12dbbd3c694aa2dedff6015a22fd8a849edf52bcc7bbf8a05cd53f6ff23 437bbaa4c47db3859620b779dd5d2a04962d006d16f9bd04a7a6593ba645794a 4a32f65c25000f76a5af3a41ba8bd88d0acecdf6aaa2c55688deeb75625e2de5 f3a5c02e272bf7d1028f201e33c3549631c89ba801b5ad1cc7981424cd1c7c25 ae2910331e8e8b26f7ab2075d3bb9608f666fbf0c4c71063c58c2bfaefd7c055 889845375f869b5bb75e58c169cb19db753ca9f558f806b47c160f1dfff52084 4cd9b90686b4bca0ae584a8c6aa7aedc6d22993c380e03c55abfa047978b4a0e 0 0d39061d4c0467ebe36e13a0b972081e52828e8f0378b1a567091f9a8376f001d04e9629b22965fde5dc22df7180b4fffc614310486dad7f4bdbf66e622f3b07433c34e8ed59ee83e2d6abf144beb911ae28c47143405b67bb2d8d9084c5ad01b5e212f418fe441b5a353876d6278c135e7d9aa33fac3a93733b93c61194e40688bf935c1ab6162866348fb2740f8e67bc33e26abb12b825d24798319303b400ffed5daa25e306074f5a09f88b20fa6bc9ea86615d9e98c2c0a82078eed95003498a2fc1933fc2996c73d82e1ac955948f3e8460947779bcb5257b0fc41c6f08b03c2d4e9f9a437d2437325ba78782bb0de3442c907a27b7f2a7ffc761fda50407d99b7bbceaaea57875e80f26126ad88c8d09789941228a3ec34800d7791906e34f21727ecc3ff11534ef1c7843946469e33d0c385644a082cdf94077d76c00977d380552c2e6629a96cb8793ae9c58a3f88e04312b2760f91ac5d692bd1e0b766a667dbb9771d955572648b7dcca0a75305d3bb370df1e577b291698cfd107 -generate_ring_signature e424f4b58872a89f8d5cba2367a5c518d6f33932e829f1b82ea361005fd789a7 3881cd8adb14d6d3486a135de75961ed9ed7cb92294019d81adb8eb07344173a 4 08af7a24d14e395c22d134f5db91bce9bbbd0e05625a0817e7925c7f5d3a288f a0833c919f066178070650518818c09a464418c0579ad6b6f834b377035dad02 72d51c7e3fd7f62b2c2e108749a71a52e59072f9fe9d9eb78a9bb7c7d04b5358 33f26e4db6b10c1ec6205159c9292d852a39d8d4eff9b34147f9021e15cd4021 b0d7f260e8c049f4773e7a7957656bdb3426b3ed2b77a92963e25351afbab80e 2 3cc2bbfc7ed47c0b84402f29b0634632eefe188e7debfca0cbe7cb48b3cfaf0bc768e20c4014cac3e3ca15da53537c05c5429e04a43060c988663e4fe1aacf085f53f0a55bef34192913942db876affbb3fae1ed5f17e1ebc9f9d353ab1c08014a0c3646e77b5f25ead7ccad33c4d40c75c09fb2208886d077c2bd625eb8430e0ccd2f67acd092b07bc4e90b240b9f1485af4efe3a164d5f91d7dc83e8017d0f9447ba608bb38a1b282ce925bc0f5af88bf62aab2a08983492b92217bbe78b0f5f35a65d3ab8ef7ffdede43a840919ff9cdeb17de0e60ed393712ab339d7e9089d2ddfef4864cc21d7ed3f96880e214c0f8ac8c7319ed7dd5d8152075e95da0f -generate_ring_signature 5bbe504919c3ec458ead546da6a26736d2502e6a05308cb5625c39d40c3b0c12 af979abd7a21ec14aec19f65b49717be0e48846576d34c27404b0df29997b81f 13 d151a6ab8f224c3b9b2bdb438d5fee09275d134d320af24552c67af777d396bf 5627dd6d295bc9bd10039aa49cd520ce164dfdb98b5586dcf38ede1cab9e41dd 1e7968c3440d4a9994dfd89fda5d7f399bd609d7d428562aad4956efddbe85ba 49058138f3cfa317adc8439d479aa62adc11ba92670252048020952d91a949e7 206246ed0a40f7d750ec28040df4d659ae116b1dd5863f4372eda67025952d13 d3c2e54b9ae6962ea49eca392655fbf8027346ac63dcc309a0899e62420dd273 2b13248ac56f9f3bc37b3d49b2898fd783668af84f8a9738e610931e59e66842 b76331e8fac5e727716cd2fa1b24a6c5703bcee81afcd923b5efa452b0d6a869 87f3a2689803f1d825b4b7d9591c4631e2319b9b9582666d23b15e738939a03c 83179f1ced3540b0293518d30fad1b29d8227da77f1a32a19132b638d72d6d8a 7d1ff46774fae090d9433060c2c38b3e0543d2f9291f469f4ac0d75d6b8e4f90 e293f3c438ee82c0bf1d5b7d0cf27f9daede67da84f44436e395aac9021c1d3d 49541a49b7d1df796b7def54c7b0f8fccfb1a6674680d18f67f5e7124bf0a8dd 579e68d5f338d7c7e0e07ac07e0e592c9dcd18b87291a19316e66e57513d690a 8 af368c7d42a787fd8127cdc6a412c802524fa4329af935876cf1599831c42c05e8ff5e0b65c6e46d3826cb2d5534b419ee2c6b2a2672ee1d92b42ce70f2e7207fc91498fa72cc44ae7913f8a6d42e1a2db89deef51c1b41fee656718b82c71081526fe4675e2fcd87be90a1287e71258e618bcbb7db48f0ab80498801aff4a02e2c2a16a5a177ff3aaf50096023b686c547d084d0056b10e49d4fa85864d650a7ea0e3e0a7861c49d673ac53266e9043a6eef45357cd268695f8216e26e97106f79c7cdb585246396d27f3f65a0be7542470769028255c0dd621b189e83508031aaa83afdbef5eb9e86714ed8d8465eacd04ae11992f3aa8ecb1ac9efa8b4206153255d219812b70490ef8de637d6dec98f19d87b330b614fbf011ee6c0f3a02ad49d1178157061716615182ba12c949d379991bd6eed839e105fb88233d660bd20f42b5a1555298475c0270f2b7b47015bb29585442ecc71e7a929153ce7e004380838f0c02a7d3e06b6639fba7d250e1c975d89c1cc3bb38d0b19845d6e504e6ba41fe5436090affbddca7707fc95f60ca3955109bdc77601f06367bad4c04f4eeed9fdeffb79cd8e36fdbb3038c4c624715fd07a48dcae04356b577bdb60dd5fc6d0816a9cb4c9c7195d88569f4a6ba4b1f62dd2375f7add1b85dea22530937b9dc7ab6169a0c897454476bf10e120fb5840219344c4de65d0aca7e55e808e77d8a3eaee0d406039ded391570a3c7b8007344b7ad342f5b20d862fe93a001d0eb127452a0b85cacb931ffe51255bfe6fe80f0ba32c51b5faef13444a67602300b125c8efcf418b312d23e4f15293ac3194af866a7b4709baee85de56c6408a2fdd94d0c7797818c2d2309209a6e32724c9f1e3c8828bcb52155982ae6a0000ee4211f48be5f0b2b869729a575068549063d97f0728e197831c3525df51c0d2d87ea585677e743812498b33595786860050bf07602795102fe20f05a42bb0301c2a59d3d6df160c3c7fcd44ac27b6a4acca59a3163f30295efaecbb3ad3603e09cbac03b271e2fec9b5598f612c1d093233cd790ed9c5228ec5e6edfa61607dfd29302f33b84786c3fb17b6febad25767f153aa2755aa3fb0c3e06d11dee0dd9a22a3bf73afdc14a126872384c64f2f636aac5d8a87db1f9837662f6154f00 -generate_ring_signature a0859f82b14dfa14725b605a1f66c4e7e3c5703096a3cfa833f996b5e105ea0d cc280d0af6534604494020baf8cb120bffdec0339aadcf45b3d97a2b7965d393 1 13f43d83ff833e7b6ed996c43f01724dde26aa6d0ff8bee55b7f2a7ae080c893 1693e87cf56c39b63aad39216be18df69feef1484ef89a9d20eccf59584e360f 0 f2140da73e59aca72c93618d0384e734c49998b2891ff21f4b7cdb6f9cb543084f103fa57b8d61f852da3dfd5afc81aaab78d8a6d82ee5476ad78590b1f50101 -generate_ring_signature 0b93af27e122fda8495915b5038a4135290d292040914c8322751c075859176c d874a4e8dbce217f1f0d503daa4d2833dd8457d2d29022c39b63c2ff18295462 1 fb104b44d767fe74de8cb1c133c2e1d253857eb003c6c63528d7cc67b3f7e49b f39fa6fd80c7a487e67ce834393545ccc91891b663b57ae879ce6ba4079d600a 0 938ec36160d9a37319b125ccd54668b71e2532ae16d932d284c72af1f7fc000453e3058faedb6c5b6f0aa88383a6f0d64c29c370a7b1a59f20c09b3712e75d0d -generate_ring_signature 88ec571618126ea8a58e3d9d6d3415253a7a9e2a4833ab4c68869ccf369a1aa1 0fa962ae711149af59f3923efb7e275ecd525f065faddc47b94d5b77a1d058bd 3 147eef3259895073beefedcdbc2d0373150bb6dfdc255b9c58326fb443cf76cf 48b26ceede8691804ed3476374d36b2e820ee44c0792361a511080de5fab88f0 2798e56eff7a2f665c67a1b615e19834f2095580047490ed3998cfa1a5ea645b 55597215ee22059246d3b0ca241f9fbeea9ab39876dc981ff1fe7f70ea10cd0b 1 37494fa889ad5c6686b0a69f0a573538f5a7b86543dd67d8b960d04eaab1920341adea81b6b7d4e0cb2eee4d56db0317556f98aa9c266c0f4d6ab6d09ab18e00bbc1cdaf5bd37f2958034781f9070e507705e30ae51da563b71145a6d554b40a2b94899419f4553e984c59e918535bb99cc75201467084d8c12b6b97a334d90fd34ec919165432c50f2dac7e1ad1cc7f2dc387df81457153ab759b27740a04043f958618e8fbe419a0161f0ccabecb820943243fec18856b0979f1691e40d404 -generate_ring_signature 7d0e728c17d84fa5a6380b5d42c2874053f090ca9619c72e8f856aa878300a78 406841c5266b911d87602974d79515ee3cdefdc52ee5e319c934adbcbc964735 26 e134815b7a0d32a792a347b2f87e63aab51b90b3e63b281f4832e2e18470e452 7b5604ae9a247eff5c40efa5965808a9294586dfbd6d96ac962167a4134acf4e e7040750c32328c80ac5608f9a0bf591ebef09d0630f5022e3628558c91ab2e9 3c358a038783a448cf3286470996f23f42d97e3ca2cc4bf4fe62ae3a4f974466 5ce0c0f74280351838242547aa953e6ef42f3830c9763f1f201c95e116a9cbf6 6db16ea86470b1e4bc1aba22ffd2f6a309b8c442cbc82c9ae1d7503ff44ba235 996b564c3f75320433dcb6e93ae0c45f1d1bd63268b2dcf97feccdc2ce8fcb02 2a7ea0d2ab7ecd8275ff6c47dca7ec0fa796fa4abad68d20384a1314ff83db12 31ecb4133c92846d600a7004a619e5867595ff17fd4b4c4b6685a34b0a64a212 e065a64af314013132daf153c9d7079292340724999e9b9e0e2ac22c4be269cd 44ae0fd0320230f57bbe081415831d4da5ff3a4c6fe4ae24a2f9721df86e8de8 8ea50a4f60f0c9d389940d28fe7bda03dc202a8187b2287c5609d0a86d80b970 b0fdab7d002af49b410025b061cd946fa32b4a4fbaa400d8b05ad89ec6c102cf f39415c4eff393fecd622a777af99d13d6ada020e6b5f154b0721f91bd36e005 99df2ae81c858e669d81270858e66861a9bebc89abd36b232d2fc70415f32a66 a3bf1ab959108e6eb6044b8d3cc8ef0fac7c56d326b225948974c66003a7a49b 3296005eac9a12ea9a9160bd2d224e549a050f37f7b8a6643007f953cda3964c ad1056f0da4946f740394f3c044438c016bc31ef30bd1ebeb4da58fedf91096b c69e1a9512027cbd747a968593c936fab41dfc0de4189316f49d731dd5032cd5 cfa3c7a19dc9fe7654556910f7e6332cff284d94787d3f1c142213b9ab388aa1 a8a526d7c0cbf45988a265d3f3874bfc16fd3e972b5c6a02151a47aa44f07394 1b4b025ca5776cb79a04b73e1cd207f7bf18f388bb9732279f870a94c20eb53d 9223e36a7f6fac4560bd6a82a48d6af7bc91bfcebee656f6f014673a0289b485 9a8601702f972d76ff9959082fd1ab159e5607070cc24c09633ece1f65d65aba 73980dab5271d0312d3736daa5ccffe20edc58040be9a59d833ab288f2623b38 9838bf0467b2e4c5b42c2558fe202360778154a2df347fb3cbe950d677b7caed 9da3143e8f9e479e66ebb78947eccfd708b8dc2af91e13ddbccda8beab2b560a 20 325e456c11776379052eec1f5e5bc3c6f7e44ec5d292e651f5dce3111b1d4008e6f9ba7a184ae6a60adc9d8393b43ad77385ba8117555d316e2d7dc3fceaa409c9147b5727d66b95eea2ce3ea847e60ad0be4a1a455072fda76748fbc424170ef92aa6ba23b9a63f6ff892f5c536b1e9b09291e7cb1b47cac2657ce7cb1bfd0fc900c4a89f8a6e676fa39538ddf0c8c572181dc12ca66862bf13b0c8db29e10792dd4c1de50e0b3ff1d7cef0a4446c52bea00d794e999ea5b244c87d459ba906b944fba8dd559b2df25967379be7e631f382f8d05659ddf1aa61c06231077a090261bb6cda9b85227b3803db6ef276da6a412cbd524ac3403bde9396e401870b7b851474faa7b4ecf51087fc5a6b56f39812914a47961c8fdfa0cdedfa59e3075b1687f01292c8344c7ac61d2c4cdac3c02ff7269f9f6c1ca5eedb58c1260b0101d6b9814538b5018f5e5ccf0b30292d73560d63c380fb73fcee38788ec378047a6c994ceceea7ef000241d7d9f2cc2cd74b87dbad5d3d66f32fc1a37749fe0148690210f553511464e003e689ac33b8e1c8690d330f66df4a48fcbc52b92f0b3fedd7376e970be7b1f4288ee94fb9c0711008b032fbddd8bd8086ec5d088c0383740ac83379df53bfefaf7803224b8951e1849c31ffacaa16465cded123090108a76ff73d8fbb9d567abbb89cf8166e6ecbb8ae98f282193fe587eb2ab0cc033de4716df0c6c245c5c31dd4be2c89a2d9bde699c0d7c95516dcc9e409c7ad0c37614ca66964cb196d4fea602bac76a60c75937de567a26796a53be834a017013a4600971dcd8df3c4758f6bd21f8ead8ee17ac0f7890b19a0bcc377b172080815c16f420f0b4d55884210f6f153b5ef5ea6f1f663a3991fcf0f25966d044502d06727812ff7f40ddabe2d2d6fcb83d2ce79a65f4883f21990683a037272140911a5462221a79dab36eaf72c1b6cdb249990b52a0fe7e4bfabbbb12fdd1c22076a88f39ce2ff234cdd70e97048dc40fe21154e09df562b78e0768e3c2ee2fa02d774b997d2b49245b13983d2494bf7705a1ecca7dbf7aacea87daf47bd813408b3db0c6a004c47075ede405cf729874015299950c5bf825c7908336ef0d5e6071de715da2e8a476f73bc84f89e39cabf496b41794002d5f32b4dbf5a9289f40938b32016eb8a665e10c59f989cf089e9d05d3d286b2c83c5092d613e56abff006419bfc0d0009cd5c3ba8477a02abb4c9cc6ea0cf7482daa6f3935b896139b01f5cd778d413aa5b83ae4af0566e02135c2e7293b75d7866a273c6aa8f1ee8606058c6992e269c9b51116da6d6d3250d79c18675c2b5697dc3eee68f617420d0be76ec01a40aac669cc29f290745181ed264b9446e08c0e99969d46b1556861091df36faf365387a864db8ba7154a5453de2137a8d2cfbede31418522f709e60fac6b782e3075fba83a26c6c001610e043e7fb2f4d979597bc50f0c87a291b901946aef3ac851e81d0d06bd324f1843e3a3b9993d94e24714e49b24f48ae5960d6eec300c43e9ed42a5dfab3d0df7664552657ea1bc52dfa00874572480f7a904f58162df0792be94dea4ff03a5586e0041156b7fa54a6a52a25f6eef830511062365eceecc8929d9dcb3517da5603b2b01b501c090a871c2fbc55c76e7f380011b86838d1f2e96b18c35634188154f310917caf7c243ae1f6b437e9141c8330e8d60b08f5a9536796602137d18834176aa48fbdc616a27081a61fee25b317d08b6a0d9ad0f238e0af6294b066623a782d26cd6de9d1de327e8d6188090439d0a8a146e88a64132f46bf21699316ee271042f90016145e23e423996f64e43de0b401ffa59dc03f7a2726f8ec61b201e36dd12dd7984b18c9271f284505ab4bc01469891c447c680aebecd3f92ca45b838cf8fa7b2dae97749fa0aa33d5a6df00e645dfb81149422dcd4018550464042f2ff4b6d948cf6bbd15548d39b3af061059f3a4ed82d641749cbb54decffec80798916b3fac25cdfb33d772bff165fd70fd2b11d7b465c4ceadf498f7869acd2253d694e4c88aca2f5f1ad426d920b7b0efac57d3e87c7f39d442459f7563d70f5191fe57e582c635fb90ae1bb580ead0c9ca4bb61b06221858253526ae3683b9ca03f69f91a85c806324f56a56d4dce0a4ebc72bda5955302fda39f081180030a79acce778fd0a881642bd2beca36ac0fbb83309b5f5113800d51783a244730d6b642ce3957a9ac1c8ccef5fbdf156c0291d178d45b21ee8c2ae7030bced30324b3304534924284468ff909e35c08e303241b1140a84f7312a9aea26de5fe87cd7eb189822191f8635e7514cf69fa0803 -generate_ring_signature 65915976dad0b79ec2f06123198fc3a123c37fc4a73773487e857da9a5c54c71 7073df50257577f8b723f2b7268b6d026d172b9fa7bafe8e0d1712112b026e09 31 a2b0a4460179b04820d33421d1ed3c5f984c770738e6e734176c1b69ba5be705 d172bfb94a40f6d5e3a512f19094f112ee1ab673f54ee9968556b127169952cc 39c3b2c50c49fbb9ea7f49ebd3ff1b21c6120fecedd83b6fbc88013dbbebdbf9 36fc7e7fe71707ca4777c30c05d7020fc7da04b333676201efe55e93a1468797 7f1971181921ffd10a03172ec2726b7c95b714214b94d040e914a4a549d24623 2013ffd455d969d46ef413e6cc8114d2b6a25de9e5fff6aabd4f1c84fe28bf58 61e67258e2b7ffab772eb1e68d832f940bfed8d3ea7e56f9fcfe7ea26a8d1999 64e5efb93d450926f1e6115688897055b968f93a6972172719d69cdc21e93e9a 1db41b3664617a8e5dd42df836433ccda0abc7ff1d94590706d506cd83da9c79 722a3ca714a18f10ad273c30a5ed6104a00bed41e5c6bf5f955ab7dd41a49f1f 32367aced52479bf495d60e499e1671537ac2d8711fcd83ef8874c667fb94fd6 d4052c8067abf0112c03f4ef277f7ee5e0c351b245c1f922d2c82bb855d6c341 537ff1cd54e1e52430585be5197b3da8954b631e423beba3e39dd3dc6be19004 66b18195c83e626b6a9c315854420167a09bdb29c02175eeca18bb1996893a0f 6c8982d18575be7948224abf0157ef3f788de7294ab6ff5c1cc6d9bdd5647527 6251ef481c86959a70d700a5ec9892ba415d370dd1fb140eac186f74090b59ae 25642851c0c2540c4a43e28ef53f2923af198546242bbec704db549933ad6498 002c5ef9e09a9065372ec5c408cdf6975b9673d416d78204ca1ff40b3a2307bf abc5cb8512bb1db9b640c4890e68dc3a7e0b492202e48c68c26ab68501150352 0b8a2f4c3e989eedaa91cf4c308738a050b33d28cf23940ed9070a576b07aaba 97d865b7b22cd95e121679e94c5cfb4b1870e4779058d308d565151de1ffc754 b3ed05b092a76c0031c064d505430a15b1bb4071bb70991dfd111e04ec77ad44 99096c10ba7981946e06381fb36672c611c0aa8ea97a3bd8d171a4a188d70e91 fcef5abfcf89053360ceba60f1a0742f6a209b4e9bd3ba23a0491b25b18d12f8 61c1720dc08e8fd3241ed1c0f59562dc5a39337f2a33443ab4f041ec9842e216 cd5d30ee14c6d6a6ac28024b55fbe2c306a0dda2790957ec2ea3806615e9965b 65c60d4eff3add02a38c4876bd36586378abd726502755756b1ce232b7fe06eb 3e7c1ec3ef42e896cc5564c1881ccaa0ba7a5b5e616f069a185cbd6c6643aea9 521bea98888e7645384b810063c034332ea7fd15cbf091ecc24a9b2d629af997 5293f3c7583d6e5f28b5a08282ee05a2aa2e8afc2b35db0ed6c4aab167de4273 a18fc87524c2eee2b4cf3c001ae2969837e11bfdc9e135cdc09a3c5854b3a04e ffbadfc27c1d36aa85dd83ce4143d666a9fef3b90820373fb96f7976117db103 1 e1e031054aba103d309ff23c6e1ef6ebfea2ecaa4d134b3c5a26e750bb5e750bd1ec3efba130c1c0e764ae0541877432a9a134890daf637c6b7aaef90bc5c70e6df8ba664ccd004f2af8ee634ce569f6861b8911ae25c13b12c3225b2f069b002164371203234771933053189f76d06474a90961b500a796a35d176efa9bb90019d3e595b90e8a646c8e1e5005ab83ef9284d499d6420e069cd8b78138137b03762e1d0582f50946687193b607f292c96c38ed1903914cd771f45b0da5514a0a1ce1c47fa9f5745168d44cad0b642c7f2d922bfab2dd1b502cbc85d4584b1d078d9890022f7b1962400bee36f4624944f0b7f995ccc87a6dd96dc6a430e65a035cce61b1991b4de039865a7b8fa678ea585da815b26baf5d60ee4649c8e89506ecf7af186c82e68333db8b420769bf255bee1e53b5abc0784724672225658707449a66e0d7eb33bc9cd9f6b913077bbe76c3c1ef2f649fc6846900a9e4fae30a333186d3af0819e34bec9f01f278bdc83debb2251c456df0b84cde6d16a2ab032811f6d0c95fab9b7ffbec0f53147971bb28d5e70927dc1b595c86baaa15c80cfcd3c79b16e0095e76466d482300294cace148270a790a337a7dcbaa430ed105ca79b271a80af7dd38e28bc97adfa8155bed333c671461d9666e2db21d64d003a7126f26c022d3c1b36804fa0eddc311dd84a7bfc4a0848c701b1bcc9076160646c69abac06425953fa682947113f33720dab0c7e3622e7dcf5a520cc7f56301be0cfb1ee90854f8bddbcb6d63bc83e6db96b0296c2ac97905b1c0ac9188f80e6d6acf6a20a80a24dd41c8c1cad0303200999abdf2b6efd9816ae29b812ede013d5a17e3e2653e9fa4b9f5ad693fe06152b9314ecc9e8b8e32d8331cb09ad90c4b1ee92bc59d66741bcd904e6b204d87ef3cbf135e19a7438970b571109a8702e399026238b71f5a5a458e1cd26b32b1daf994a48a327afa5aad003918e3740dd9dd391ace6d134f1003c570c059241f8c0683a303411c7644d86209fb99ef05878e6643f3f474276b5ce4c1d76037fe50bf7321e995cdcd8f07994e02389e0e5fb41ced19511837ee37e7502fba3fb5e4ab33d2caecc2dd8372cd346e0de50458105d8e32bc180992a6231a3192a686878e4ee35037a2f36d583d7dc910bf0cb09a6072a5987797255cb632ce8de054bd9c2abe3a772c0eb2198bfbada57604e62f177c630b9cf78dd72f85ae17b5584946e8d929e418fa9cddef5366ecb00926457109c1d6a920a7c053472b5d54e0c410af44ce0c562dcdb194c02fefea01513244b2838132196da731943a1bce14fece3ec9bf22e704a2cdf259c918d40115fbfae1b09bbcca0f753519b5f7e017a26572d9d53ffa376bd3508595c41f08a10612f500efd9e10ce26dd9545d696bf411b98e4afb80e84505f09b8cee0c021f03aad100e80bc15ee1fbf3d849e1d092be486415da42f0a25ab82f7df576076cc138d9ca6ad45ad33239f334c242aa5b750d5b5595ed6d6d9c94bd7ab91602c6512e7216bd8c8a990a7cc0e5f9a2866f07e3b6e4df0a001e5dd7ace49c91058af2771e18f7672d8b48615989e2c7bd47574983d57aa46f9fd562d8d7442100779eb8d30ad91f5e9543ce5915b47e0b9f8c4a4eb294af64da76348d29a6ca074a7d1d89d95f82866a40a85bb5039a597269d3ce9ebd8f3d6c71e4430382bc0f4eda4ea3b3616a1b94636c7d492a82e9ff868e7f261881fdd241faa5b38f6102e22a5c69f6b69be687e52bd487bbe64a75abb66a58368aa0b4652c133f9a3b00c92c2306c3cb5b8f5f6c60f26c7ed101738c5328ee0cd1c46c10462d2b4dd0078f2ab1d86be6fd2710be0fbd1bf5c148b574802a9aa0038b38f2d82b264a87050b770885637958546d679eed705b972dc9ca0395ee8fdf43c3b1d76d76f3b10785a6f6a9611f43d2f09a82c544f462c982dfcbc32429080e2d4f05a3984bf9075b8516307ed325cf84371a50350c86b1e155c480578a1130d5df634f55cdd20c79df9b61f6c2cfa3e038db159e8b36afd4a5ec5b012c52340edfc63255e0e30f564f6e12c478b0989d45029a975f5c3e5a7397ec3b41408b4bd212735ea697082650d2f76929631250221697812d9f29dfb2f221f868b84b23477f35b8c9dd086113c3ef243b321be5b7a07b1f1256075229db03f5b4fc15aa00b08effa3c40290dfa937e90acde15289865763c9ef197367bf716a79b47c598105b08708700099743822bd5a049bb8be2afa285d8bfeff7992c95a5f28f2749751570cb3320ce4e62649f9389b222370dfb832cef4664f19e1c5dec59bd0549ecc7900aa430b625be6b684221e26509d038d58f25c6d3f32db09efa6afaf9f0313a12cc659063e89654c1d590cff19daccdc5f94675f1d1375999fa39f3dedbdaf2d65fec105903ea624e0d9009e1f14af218f669cf9a97a12672ed5ecc52b746f1fab78b005ed4dd717042c4a7300baffed39eb2c2fb5584d7d1f442ab3d741e61b63b8c90d87f896723315285a01cdc8c237ab2b558caf27883b2250978cec131c8eb4bf0fef06125b4bd986b095a07e4d756b9dc2b8a9e8b7ec749f75e7b030026a6d0b075ec4aab8c3808112cdee7c16fb29154a1ea143a57f45d468fea51171cba8d504075849f5d72b9c8e395ce119889c0b5293e493b59d7ba85cf95963d03989890586d31e41ae2affb2e6a2b96a372866ce646fcee6c2740bb0e4726d601d25af0e56ec3e33fc94286c0c2102cf35a98e8a2153a31cfa5e9f7bdf52225579009006 -generate_ring_signature ac3e3b092c1e38aa072cc4210d9bb2e4ce013216d06cba6049ca7b679bf4822c 317219905c41dfc83057f3a6a0d538f47add4d4931b087b6d488aee4b93ff7f4 1 a957ab83e1decda794a51d72c6b411a526b193dfcdcb97941651ca61fb40a066 cafd4da25098d3a9667da2474b43613aa07f58c8cec919c02067c70b02f18902 0 dd277ae6f3162599b15d772ea0539729ed4b475fe6613262b8e7dc6955e71a0e7fe1ec37e52d3555d84977e85d6584743d60c41121e813a6d1bd171b7be19209 -generate_ring_signature 6107adc2ed0507e69710223b8f25ad15872db003a33231b30b13e693977a9a04 28c0cb6ee37eee1a2282c28676b5b9b3ab652ecfd46c4cc29b8b6f4ba8cbf514 1 ddfb74774075531723882e838680b6087bc40a394ddfb6ad1235e233491f4a7a c4aae45c82526a21a7eedc6caab8558a2bd4f54cbbd11e95e72bfe372bd1bb09 0 a01ff14755aae9594bc222e3c0a1e0f2f57c8a0aeb01e963e1a8a6a594db0e0b83d4158edb1a54b75515dae4f3b33849905d03308bdc2ce0020df8aad9587c04 -generate_ring_signature 2100a5f4e410e5dc62f19a0c5e87184e1d148a8dd98b2466964959ff2381da66 d6d869463615fbf48380f9d11e7461f8cd5bc1fe91fb99f685743aba5ae70101 28 793ef8c181dd024839f3212f25ae757cb80bec1c219db4246c6ee2fa052b6f17 2aba2b63e6491a35ef32789b0c7a6274377cc205254e9bf2f69cb0286dae5523 3fa876cce9035a3e6a4d5d1b7a8c09e2df305701c39878bab4da23bc717f2eed c9e31cf9d3551e3fb2af4fd1608af9627f0a417d3cdaae50424f7ae0ff69783b d0c8613048181c9a3694afd2a02589c944bb3eef2b82b77c250775536449aee1 b9ebf2faf7aa48e64ad3dd91d6c719ac4f765c31b03bcb8fafc869c8c7636f91 e9f8b1b1cac9b84936264a4752dc97d3028a209be61bbe6bde32f8faf5463a72 2e66c163b5b33bc4c675b99736bd883533d8cf58ff92a6c6632cd47898a8060e a993576fd3d80b0925a900c3072aff58cd46dff9d10f166ab52fc57182b7afa5 da828df878c59586d46a4c49696661c3bdbdfa9f36a053d5806692c42e3f36f4 d2f4e92d5e5d70fce216e8b6d243fb32014d8abae37bebbee14ea9b8a3d84b8a 2f1f24c37d5eee2ae72a2dcd3b1b6ad30f5d34734a762fc4ab7b8956ff49dd02 cc7d90c3c1c794b6406cb1fa52f61a0045a2fdfe1bd83636c848f18a100bd98d 481a170059326d8eaf5a6885213b915fac4cb27a8eb5318489a75fed10cf50e2 dd2cd3093ca1a6169b55964de9003e308736bfb3903f3c8f8d6b02f252df474f 7dc1c9c1fb20dbf1c50b213b43df2fc31dba76b9afbee67b8b0faff9a7d269ed 50e9f8e8964df954a2c522a8d373e52d2187bbc76919287a59d9b506249ef137 8902dad485e7e3a7b9cbb784074a11b2f75686b7bd6d613027a0bd91f0a96c2e 33f2908d1fd2d85c821734bfee6f1f08a1b70b82b95a7b592d02a3d09e858cea c70aa472bbea4d8d55b345cc2948ffcbff1f91294eb23062088332a5d78b22dc cf57313df41a81100e9abfe9d50146d4bd97dee3a4633db1d47cda8874de978e f661b18e8576915d55a6a23e8d201ed5286a576f2c81c2fbf4ec7945e9b54f7a bcbfc29481405ef6941a8865ff80219df8f16f972e6db14ce5ae1f05aa3e04ff 1c5b932bed93ed0c1b0cdd46325126b6049b4def7a3bad6b7edbb8c6adb628cb 089949b4a4c24c2131989b09abdd0aefdc12c1c1f62ae87e04fbe0e9da567544 0da2fd4af5735a1b90aa73c411039d41dc2f61aa1d1ff7bbb76ad39e8e2c5082 81073bb6dd2b22897882b3c9d865bec7f568b80ff23cdfcc22421fe9771c3395 5b87191663fc83c7ac5c0a1936e414fa357bd8c83323c08c5aec0c65be085458 6a668a19b1bc83605e4aa62bc2a17c45bcd68210cf2b05980ff205babdeb8508 27 648d6924a11369fc5d2bade59f09b707b28e90f1dcf89e52276d069679ab940dccd995fc380e89ad64efa795a244ef66441b633d286b3855a4a70ea63dcb8e0372cc9ab9bb112dd6b596eee8d52ab50cbd5dd7fe62c03fcb14554ab4482cb60466c9a0565eca33f75423ee4ee506df9de4d2ae801070b8bc3bbd0298bddfc300ff7fe6ec8a3ddacea1ee7c658f08bb97e264a944cc17bfb2e5212be4ee9ce10e329f88c610d9205a43f5b690fc17ba426971197ba0b7ab6717503c9b50af880407d3702cd16495adf74d067f3c67b51d29f3a130cddf8ef785af58dc7598830a0a7fda5bba20a94a7dea5262be385b66d999070b3e542ae9b4cecb64793c8c0d06cc61b0aed2017c34529ed19fc056500db5030dcf684c5582aaa353be6e3c01fe0424fac328567920ce05662c2b8e7ab7ef3e4acdccebee49f3e00e8bc9f70e30b829d77645f9f76db0d2da4d1d6343a3b31cb1338a7655f0161127b74c4b066de546b7a96b09f516c2b71e0cdb3b955ca4795d385eb223f3f8a0650491020683edacc93b3ff82c8b14e468615d09f702a6a82de37d0e09300c2c8228513b0d10225a10d16b92d46b1116dc764eced1ebe164eed912b2dcf835866038f6be075b5fbd663b44e16b44c864585b74c199f8c960dda5a456a7c471233d806fa8096e556b365384956823c73ee290c0c9fa4f41cece32cd60b72c26e9e9c7b6b00cb9c01f645e586a2112cbac077143f9f10fd1323fe5612ad0fd868ad4fbfa0a00b5db0edd482c8f70ac15dc3ccaabab86f23f389101524a48b93270901e0a59052f727a159f763909ff10073ebe1b612eb5f5d4c128a13285c30fc4551626d706e514e3fe8c0c410a003ec217ae1188e3c8b317030c21cce978ac9193caf00a0501a22913a76d47f5c6e6e53a88a792336053e7e0337d3d405845de0ce32d5b06f7ab9fdb839cdd10956f59e9a4b595de1558aa57dc305e80a13a781b209987088f2606e5bd4caad396fa2852a5479a5b7068fedac6e79d8c68c97512315ccf0faca367b8616b7e954cb434afbc335e7e01ea7d552e77178b1fc800c771b79903ac9711e1bd0772efd34c41c90f9bbf384064fc049e431c6413b23bdba75d3a0fcb79ff0bb0901fe0321fc41c70325a33b702c56375d9bd85945bc7b833c32200b249c959d814f048be4c7c5414e5fe801324fdb2a660240da411172197bf4b0880627bd74f967b4c15b2d289740fe4362777e7beba012ba7e3c4ac088ea35802a5e42e695d86be71d3c48f85598e2d547c6adc27925b16a6e6b6c51dd29f960ca5574519107556c3a36722dfa78fe6f217c9d15b5494455ca7b7813b3f49e60b19dd6f01184120ee68f4bb80cb7b3c043b32ddf0c8e67d70e1afbf48c0252a033b410a7913402b87054b54b759ca6bed3acda99335218077ce1d5549b81491089343c05de444ab18a470761a6a19e918fc8538d7b5b23c2d6c76568e65edbb09abe66447a7261b689a8c5165faa9dbc6fe384980148adfe99a4e7222ed929407b71dbaa0a5c448a79d80a085ff5035a9ece54ea89a353f5ca61a0bf57703720e6e4ac852485bf9a029e6c24fb973f3f3840a6b532a597a91595f89441cf4b60979b40cc1d175558e2da2995769b12ca6bb22444730601acf9f2d575baaa91008912e2592f41b4916a9f9627c1421864e3f19ca0eaca32870e47e402c4f114503e2d0f6dfc6d1733d090cc82aaf8ae82b892fe1da599acb3e8db2d3eecc14d207ed7cb97aed6d6aa0fea3d7b6f314639e092a91199c9b77eaa9d1c363c0857d06f572aaaaa4991f7a55a9f036c373fe299e3b8a85cad50c4d55e01738acfb1703ef4f1bcaca154e2767f56f40b6b01f60e76072fe91b1e8a0405beae04e103c0f5afd1f9667e1ff33bb40fcf6bcf3c760201e39912dd8149cd73abde8723d2406952d166c303c7f822195f59d48e42e1926b6a35085ec3317c1e9d024498ee90d3d45f5c3aeb18a6275cf207caa116136dba92954a85adcdc5d35bb2a4877e609ab43fb2f51792862dd6e42d2ff5215f8599774d346dabe90f1b1e6ec30f9180cdcfd1d2c93e3a88a48ceaee0bc5f231be2976529be0fea473c6c9b0e7910a70308c2cce6d49d0441b6d0869724f81c7cd4e565a55db9738cf4d52aedda5d6502ebb03e4d191fa13c70901e22daa333c2eb7c259b44798303ae974375d0b46f0e11b516dbdc8fef6b5eefc4923aff4483becdd5d2b8bf34ce8cfd8d0cec5e15063a5d0109e704ef7dba81eb3d27798cd9ca77d607cf18251302eeb0096795b205ca8e9ed46f8ef0d81eab9316bbdb265d7d25610239e52e6bfcafb598a01d950ad2116b4fa5c436676734d9a46b3a483f6ed2163237bdcfc30f343e74bab739015938ea48af543ec234debe7061a50fae07698d0592606b768d1368b9d9ee970df52a28cc4ee6ed16ea9510e55394df485f0fd539a2ae607795c4ebc3f46c3307f6937b8f648d034c662f2343763d8e77c44c3caa390383d3d57c4de5169eca09 -generate_ring_signature af71df96a0ce2242af718f9f36bf7b1e2e54bf52afe541127dc2b87f6ae259aa ca8423fd0e91f8872e0a32bd20940a577b0fe5939ff8c684a67587c699407cec 22 1258734c3315b929610f4c8215a30412459f294317eaa246b5d8867d12c69363 aab540da690563ec5971895052762a8e8998c754f895201694a17c476dd598b1 74990fc817461aa56686cfd5f453b41a69f8aa901fd4e8d4d1f1a0b5f6ff8c91 be833b7186433e5d760182cd8ab18751036d1b0e968396cf61ef0d903633991a c174deb550d5ce869ebe3ec05bb8fb582cf4e27c35d5c190b7da5de77f28dcdf 8dec97e5c5778667e0ddd106fa037ed7c45eca6ae55c3bcf25503d41bd807fcf ebb1afb03b050a92b8e559eb8e067b545f63d8099821e50b1c99799b7d1991eb 7e9eca4eac87463a8a0706af0dff91dd9000aaea65a691255bf3d4891b55244e 51b1223f80ed22dd385f378a33a14111d712ca3018ba967a587bed35d8b798cd a1c58243c6446bfc860b55045ec7607dbb23081b72265365fa90cb90eba8ee23 41910bf9644f3f9fe19c5a219d3b7f96ea6168133c19629a2889a73de302b5fd ac0940d8dce80710286d7b2122907d0c2a8cbebea6493e44d3ebc88b131e98e8 e10b2dceb0a93a22d8c62e6e4f8c7d766c0733316e6d9af29f6a70293b2ee109 f2553f4c0fd73109c497c05a0524430184d0995adaf87df4b35b48dd589db98e ac12b75019ecd593017d62134be2c9145b530b80d0c604f3beedde286fbca385 366ffcc3d9f2704507e10f7945ca35af510d4917ca6a0f320b22bb9bf2d126e4 6e8396f83467caf6c90a774f7a35dcba54461a71e2ee2990df127a5271b8093c 3d1e476c5c17a2a9d875e8e23243deaa16b8ce4bcdc2dda4f11d60a521fd83f8 c52b53a7882356adf4167237b853e0605029776fae814d3fc7fb9f5bb8722f2d 524c073fa8195ef0ca8eeba82d2182b8cb026a4f0759296cfc02e5a240e6b65a 0214ccd35e3432dba23b879df17a8efcc9e2e56826be4d0ed4cad87bafd20c9e 9e572b2ccc41e5595b3c74f6b1a571dad53ce4efdd29e04fb953b7e8e5abd8c4 c379fc436343668d69d752ee38c2e4f989cc013b9926f3c54568eafdaaef8603 7 9992f500931ff7832bbb50126894780e600da117a548d25e7e98850715e9b1073ff3d31215f1d22f9ed6d8ed3c501585a35a2a15abac89cccf016100842b53044852569b4ef3ebe7f616721151bb96f8b7c0605e2f6db08da5fd9028ffb77b0fa7933c55e7ec5aab3f476f89dd578895365a15434b54ea22923185ea4195ba0d9c1ab9b4b168dc8e619b811129c12d6fa3bbf34684fb8b3a2e26e42ea6ace309368fe6a2f687df4ce7e55fcc992d54891bb9b158a9bde23924206fbc198e090649da00f34ae324111749b7a87b1d932bcef1bc86d5262f79abd7dccf6e2600025dc1f187309f39d5d22617803a0c332b11ddced9bc6a0e6f13ab3b6cd40a970c2211ce4663ac96be5a19065020e41d5c9ade02ef4092f178d507e8fc5e05740587a23d310036c02d3fb3f6ebb3b0f89e338d521edff6cb43ca48d9fef7fe7003e1cd86995864359357325a63826f23bcee9261e32429e638ca44c7a26832420f6e9a25520c0658a24f727383e0fe4ce6ef8f664364ceb69b67982119764f0e03d51936fcfa210351d569193956f06fe0945a6c206d56b5f88f466364efbe6c0e32b7ac71c8c912c7fd291d4a30ab857d9fdc38471d0a43d97ea4c98da064f60f4520dfcfa7ee94e29f2a71521489a09f68ea92f7c5626a9f1fa370d18b1de807bfa99afb301ee05041853e33c21747656992d5bd779239249060bf42c1bc170c4ed19720d9ea9ed4b56e41ecf233ffe45b2b5fa0c560fdb493c8ce21a4327d033a0b44c105f1f453cca7526c80f726a77eb3ce460d4ac74a10053d0385517a0836b69d48e9c3622e883d1805c3ec2eb867d34cf15e27cf5a06e203907bdbb50c252ea6185a1c5210188e55c5a5f269390d46de4257dedf6bfdfbfe3542db170319be1b50ddadbec2fc0fa5d51572b5ae48758f5d0c0ca9b70900822e8bbbda0382c27cadb9e52e2e85e62ede48e10055b29204a882690b2c0867d865f210db02a62f5f2934f86c9f102d7dcf8b8542fb1b0e1007e4ed5f2ca7114beedbed8307df73093abd8d1fdc654d4d054f0f97a669312f086ec8f921f88fc80870d6c20309a5ff593f5ff3295f4ead0aded9ae766692912b8781c31d4839d407be330b0eba7413611ca47f2f2f5850eb1bd405418f32e0afdfa938a3161868312b13640b8c2d85e64db452f7f8abee33c16e41d3ff5f5ee6fc92dcfdef484ec26db23d0ef99aac0ea09e2510cf67ba9026c35d25afb3df4622f0e9fd90c83820a710b3059246c6e621e68ee3f54dd0be02cd3ef6b8f7123c339c99cae1415bde70dcf80f8615f3b0d1edfa80c36b4ee4146ab9c5ebbb8a98b4b06b8b9cfb651c01f72f0bb08cf0e2280dc1df8c959689b318c85bf26f36d4bbbc4af33ea8a1ffaaa7970d21807f71e356534536607e1552c248c5a2059837c4ef95f0a68b93e98896d8042c4021f37da1bd996516b681d2e318c812d535e44e0bcf03a3182e5f3f9b130d0e3563b5e520c269ba709823784272b111a0aecdd7fe8c716a94acca97f41e0e8fc81ee5ca1e91977ddbbf4c74e1ba5a5f4fa6e88c7eb572633ae3b626c19c09a55f2a44da0fedff7dc0d24c27bffaeb448e90079e22d9827526a05e6d119d086ca98786b81bab9a975ecb97186697af5d18261bd74334e6c153512a3c9fbc07eb9463ea338eef67fda11fcdcf32693066e3b40dac22b12da3bd874aea89ee0676090323d26a5dbfde226b4c7958d9055e8151bae38d0cc23f443d169f49bd0ab79ccff97b47b3660b41db58351cec4bb1bd93589d1520788344bcd0a0c81f0f270679613d96a024e27530e45e96456833fdcfbc4045c2a93f8c43798f82e000ccb6f485d88d592765ed40c5775a9f6c8e59636d2181ab5bd07657c856bb9a05fa70638081a029acd938887391d4140cf35218382de51b58dfd6549244ead60a33382bcf3d1a98d7d644216b59005880927f4f4b592199ed9365b0feec5cff0f -generate_ring_signature 4512063bb19daa1ba31eb0145d48f7dc9d06fd806ca89540becd2b5e6826c1e0 89a8e66b8da6a4002c7cbd2dd887bdad6a08e3412d1972c1ddba31be29ad779d 4 104de0915736fd728e8c86d2458441d876f459f995c7256a276534f438a614f8 05fd6561503fcb29ce98b70157dc619b5c4aba732aabb0b0d10b8298d1f5e155 2c1a30eb5f25ca5ef00b7806c934794f03dcc5ac58606aec2081f9522a216749 133392cef31dc52c7de272824c7d487327b3320b2eaf1caa827083872002b16b efcc49cb457ad9394617b802a3be8b9292ed7e88c782508899ba39a152e73200 3 c3b6e40232ba8c6aff262f04bf4d4668dd28ff8356bb8615fae335445cdc4e08fa93846c258f76146d969c380a591c88dfabf9e201969a94f250e4035c66db046a373ead5283dfd066616f1295961a55d24af8b7a75384ce05ee3c67103da309ec4c2a1c47d5f92aa278b1ee3bc55ec919e394b69687e756299aeae435c20b0869c137c6c933f2bd088d5180e580f497e25ede00d2c4785efe9c6a5eada7900087147e6b6cce9666513bf97536a2ef3014a63b5a18ecaab4f7f28d98f561850250d2e477dc42f5b6150c4bfa4681bb9e90bef930ffd760e00ce7182e97479e00990e014373710ece4bf82f3c76b344910591eb61fb80ea09aa754ccbc4c4160a -generate_ring_signature d4a171b6e8c5a7881d47e5e059129c134a12972e6cf446760d5ea3f5d9d8a526 4995bf794e131c0a54e6b94218aadb1062967bc29978ef1e04a5ec2a622bed38 2 8a1e660522cfbc1da70e1f269efb738b9efe941435fe7ced85bcb8b2b445015a 52a0a2d5f69efa6666a07a177725d76f60a1fa078e7328132ea81e2a1aead5f3 7799976d0f2f488ab7dfce43781bbf6d8f64f4c17c6dc5e357a98ad83f23a20b 0 58a9a6e5c44b00e1619155aa12e3d145ae3c03fd0eff58c8422bebc7d7cd99021039d15e9e448d4ce5aa0bede8167d4bac58c847c403fe9f0411fcedb6b1cb0ea8715857d597305120950eddcacbebd54a2bb7f0287dade22a9be012eb84f70dfc1a0b459b65d6c14ae09ed0e7b1ab4466f5a7623ba746335357ff157d670f0e -generate_ring_signature af87b1fedee0e438f10aae5befa088392ff4dfae1546b8c8f779fc50ad51da97 90e690a1501ff3a3fb14070bd46a4b4a7175bb31f57956486ca61f2e49cd4ab0 9 35f64d12ad8dd1c71084709e6e868e68b934eb407aae5fcda2505773503025a7 c80dc8d3d3abb474b56a5c054df286f87f5c58881451feb22cdbdae8f3f900a7 3461ab681e2e79261f83d37d82d4982892320fa386cc6e6f5bed308bc1c13d12 46d70d6342274b6fa1e9e3d5b5de51c4627000ba00432606cb4aeb362e25da6a 2b561ad67dd4aa1e38a5fe1c8454218127a73881a206b24862e136cf2b255780 31053ebff5a815b078f8e94d9f0f044f1688b0133cd883d479a94ed066a1d1c2 968233788adaae5fc7466d8390d94d6198074b114e2ec9b52c4d851ba6832166 f668b4ef8431e75554c02db408f359ef81436a0891490210bd509923a7e0a749 fa4407f6eb50927d9c17ca60b21e8129a19684ddb746e4c186b88ad5113dcc86 020bec4c5ca87f397f5c0919116c54fc4fa83c1a650b045ee4385a3d7bb40d03 5 4bce93bbecfbabc33366568fc36693b46840df702626579e62e9516f0e4b9e0202ab6b9d8a6f2823b05023fac29ace4b15b5ed8b8c6bcac06da835c106aeed0c1638e5b29b5572b72acc82611047287fc2b3a59093cfd318331e6504950437094dbeb8961078eab9c99d8fa5bbe5bfbffdd8527c621daa6e7dd5a1a0442e240cfcd5b5868bfa2da07b12bca77492675dc42cfcb566b34a359091d12a1056b70a7d6e449a11ea39fa27d7d7a696411c95f10b6551896611b1d4c4869ca2ece20364266d3b028c0435a1f136ff012de7c1360d18111aa87e7f12aaa71f78d2d8010fc6b0c6e87def7a42d42dbed8834da0e67aa29d84b721396fae096582c822068ff9378df71cafa852910d5011168379fcafa138bf745931c08de73a89a81806c8b08f388321ec17a80a34c88fcb33d38760d46cd3facd1d8f22d511be64af04563fc7c8b44012016059834897aab1bf30b7c779974813b003adc3104cb9950ec03719ff04f556a8a1dfde07d48a6f1b10147f9c035dba6c2a673c3d9ac1d701b121222acfbfd61222a230256ec665ae0f9d83f85694ae5b48bf2d0c2f801d020865529a730c1385a82dcbb77e7fe21421f5dd0b15340bf446945f101b3cc50fc17e4620dcda2c8f46db467c3e3ebbacbdd9758a4f6f81d1343449e7535de20dcb984a9958e1ca69466298ad207e287fc363c19a60779bc9e6b1cdffec47dd0c8e4255bfd134463693bfdd636398d148923dc78a1d53248df34db30bd8524500f91f907930cbd92a38fffa0452d7bc42ad1a025aa8e8b6372617ae071f3e8204 -generate_ring_signature 2d2c11cf68486227b17b80fe6353ae59abf53ba0b8bc75f32a61007b557c53ad 35e426514c73e7c66880bc26f90365d770c31fb753926f24d23848697bfc5a88 57 a9919f6a2b7acaa39c078c3b24e3487a89c1e98f72c6deb29190efe461915b1a 97078cc1079d661dd75108310685f568c813d7486064fc35b2f69b38fe6e94b4 d6e58715307fdae6fcf242a4413b3264d0550ada54a02a233e3488d63dac0307 a6eb853278a50ed8333786b3b15dcddd3d8d784cc647adda671f710a3cd46bce 204fc5f49b9e9247b2245d0b29b32a697e6cd5b1c4347430cc2002ee6682551a 19f3496ab38450705b89e6ed8fd2c725a72ab9e04daf81b3e84f762c6f368858 cdaab9c4d1337195fa27a23ae9beb85e1b421162b0175b01e5022a8a6693a2b5 da64b3606b987f43092b844e787c73e147dd3f1401e5d4de45e6defeebc4c542 8636da56ced937d7942364cf6791b38e8819902811b071d88a7e9f31c9158318 24d943b065ad70668edf4dd47bfc174333547e92fe95a4840aa1cbe343ad8c7f 4f633908fe98dfeaf22d5f82a7bc5c591f68f0a5c087df556804a218ce5b539b 550f1304058b94162f04b4435bfc4190006262a55c326750c93aadc37c491239 2a8a480ff6b6e352d3eaf025a8a2d5f7170e8c72063216af052d14050d68573b a7a57ab7e2dbb84b1b687ce4e37c966aad92e8d63a80a67b399c3bc1775bc570 b1b394508b9e74e44ed21f6f38aa8844ff16856e1179b51b73968582babe8570 fd472fe1eb884e3f57567ba1ec8d6a3839e944cab78e639146224f141aecdcfb 5ca43dd0779bc74b551aa2279219b77dd51b6d84698949e23a5fd73663f5e5f5 4e4bbaa324ff9e710ddd5f5e837df67df9ba854afba57819b919b3481fe374ff f9f50fbf4109310755f80a3920a2bb47e297e4420b5859045819b8f2ab68bad6 4bc0b971d4bab80d4013dd6cf6363ed852b6b95a94b83380eceee179611f0126 9f5fb2b0052f5a19f77eaf98b94282e1f62d09b3dfd090074ba6a99d7d3cf0c7 570157fbaf6de931c767a74e01be9e00dd875477c18a556c93187cc9aa9f51b3 5b581778bb48ba15fa9bb4e03524b5206268bd2ad52aaed0ce60ac577cd3ef94 00c51c2ea99904e5d933635fb1715c3abb4ff07642aea7dbd46624fd9f1d825c d50322d0ead2433b3977ba3dce5964d17979cddda84a13acf5f5c824f110cbf1 bf25117e9f951431febfa8370999db5159ca8511fde188cb0166624773c5f0f9 4c64494a15cda58cc9def65c4746cf88207d32d24b90a0c134dd0ae01b09c144 01032bfc7e3f6e6b0a30a3d265e01e385771c8886aeaa6948965c05728b056a8 060f286518d97854b81a3ab11a55141d4edc97bbbc93fb0bfde999234b05400c abc25998dea92a2cc721cb7bca4ec8890b18d31fe9b130e706e9f9c231933aee 0d462aee190385626534a8642fd579da27e8cd596f90b3d5f5e7fe55407bb405 04042ded8ccaebe4ba0dc9d67fb8bfd9f51c6a43f4dc154f3858b2f34624573e a8c3ee54ed71f11805178141dc71af46d0218cafd72ea5adb3b54ebfbd2ba1eb c4d103d2800689c4b1f2b984ee4b0565f5e214b8209fe622db3f0b8b8fbd3dfc baa5fb8c4beb0204f6be08ef6aa3ea2351a81ed5f169315206a089e7abe8e691 9f69cd4518c0732b7e0d34fdf8fca4f449b391d66986f4032568375532a596bb 2703488d85817e84c47dbfab7d96a741c5603fd38674f9a14dbf9c0785f90a3e 18271655568f950df4aeeef27efb9c59680db900232da356f3bc940e77a661b1 a260915c171adc5c17beb5b39d073adb213ec6206ca8cd6656ad0207f0675c0a f3304b1d21a211a6a64be267512752e8fe7e4682fdcfd42676d4fd7fc49605f3 7910d249a3c64181a1737103cb8a0cc85dec99873b99169cc3995662ad1c2397 b19fac0f51b23d973d0b7daf502321f1abcebd28f6f8abfd75b377db40a0b99b cf3cde5e0b30b42c5b610d5087e32d21bbc819a6ee816bcaf928ba20c45670d0 64f3ce114419a4bc0eec99a1f65fcb2096c94c65ef8a5ca44209c48b6f364045 7f757bdfd7cef93d1ad0b987041bc741ec64dc3cd78293506a5bad36e0926d2f b0155d119bc08df378af49e9eaaa856742bf7783f3ee16d9d545a6064f12acb6 5b29fa21c990c8b43186c1d6d842152a2fa26eb6c0866c10014baac7c82367f4 6fa38c3bea221425d2fb979f5666b6b0214f9fe9ce0abd6d39427dd22bc20c6c a6f86b5127deee81e39532d897d37407dd7348beee9685f0cbece5decfa5d3da 1827e21b68bf6d7348b325fc74d8f65289f30a38ec4f84bfb126d3d94a6e8cef ba62987bca2eb991d123ef903a7377415eb9ac77f244042a87b0538e233fdac1 be54b474591ad0d58a89c6a696abdfa17005717e6b9360c34cd95634210eb8da 78ddfa3c43d923ca2037e3774c9c4c8260cdad274487ff71dc1f5b739e0ece84 6a2184d5c8013feb86b8fdcb6885ce3331320d53f4c02245bcc90c34f4f29bc5 db01a4dfb62b753a5ce1109a566604b9eaeca13064b13ac2fa24b4bbdb859236 de3e15f15f67e61b3f05022c387ba7029432f417c1ed96377d0fbaa9b9474f4e da88bf9678f4d1594a8899ebbe347e7039f5e23287dfa64d5809f0e70a359f2e 098a6833175b819831237a5b135e325dc1e10b0d348a07ca831c60ca31862806 1 4199f8d6909ef38d2e8b6cc6802dfd1ec0d06517d3cd0293c18281e2b81a0b0513f67bc2b37fa38522d657843b27a6cf762ad6ccdde704a1fcb18e18047d370a2d3b2959819f0f1a86234badadcb19ba33c7c7a5be90ae3c834e360dd86bd50c0a6a454360674710395393d161464f7407bb47918de45b965614e1e783b0ce0cad263b58586f566f7fb002c90ae537386e7df7ad41d8398fb7ad0b7ce6b64b0d52832acad8c5e6f25599d4e90079c0f0be88548cd09ffb976b3c4e87c7d9ae0ee1d14675476b15cf87290a5d1a0bc7e2376c7c594b727d1d0d156996bbcb280d69c3353a6eaa79815ebfd2c49c52df4bf46fc256005023845e4bba0750ca80070c32ce3d6549cb135f05bdaa3de1730cb3d1793a3907b5ce1bda53a317ed3c0b05f780848676d2df00a812b2065e02910bab2660ea9525aae9fbce20eff9a306e80a54b06297c79ee6e29d574d8d5d5a6a8e6e7f32a74e13bd007d9cf247f40a116a086c86fbe1e7bc2e0afd9c3e0bbc3ae7b04379ea77cc55c93c279903d10d3ff3ed6aaddbacc75779fa9146892a2d1ea3901f19fbe83c191e634e62e8660dab541971156a0d7e483471a40e5040a3b75f1ba6df46abfef2ff2ce075db8d09065452a13ac563ca9a828f945308a74efb39a0505090f01e02d396eb82af320b14eb31120fcab6efe256c00896cf4b84ef1b6ba19b5691430b6cede209d6a90c63f9810f550e346999233ad550f5f7fee6a55364b26e51fda1cc5804b41c0c0ea52909a62b7f00677cfb7cba9c18f14336c61436a458478b7ec4e06c41f828013f4f7559115967432a4878bce9f861c377d4243162c601177255b30ed8f2720915581c12ce5f7a3f63c4ae2eba416abd39523e85279ade2532a00437f6130c03e4ebf29b8aafcaeff4908aa9b587459670a70623b9d56ba6c1ffe800e17bc90cf5a926310d71f4cff9c117bf5361c6229f960b46245554437b31a8bd26de2802f47f15cdcadeeae51516fc0cbf7d8de2b3bbde11b45c3c7c5cb6a58cc564a70d377cb8c1dfe198a2f3bd9569c6a01ff94d71f3944a779cff6ef278dbe363800073cfbb463b0fdae43f7005111fd85183028ee8644250c9670be031939da7840d08e63e81378429db095cab27595802554754996bdd2fe580350800781d64b80c59b87a01fad1383a5467c719a1c0ac0c0217401b10153b476c3ac6a818e80c0228b215a75ef433a597ae3292dae49d532d1b6812ee9291f87f248ddf47e99a01dff46bc464540adbc59cf39fb12e4b2dba9c64e0cc207a78d50d676e37d9630a575d1c5a8bd171d7211f76f00121bffc602ec6cb132a431c1281ab99e9cca00f8b653d76ef6c38b81a2f3e8092d1de12e02ef2d866aaabfb59811921651df206daa281d1a854b77958b955c68fd4d536f3090a8dca403ece38154f812940d101cbb9e4d85b2d796e84c2124b4bf364b2eb88bd80daf50300e011ee05fb132808493ed12c5752d9834f3281da388bcc75ba5f9b8cfd709ceabf63d50e700d8107828c6f5304fb6fdbffcf874cf05dfe16a7b2a606d739abe3f991dc68a60fb7074f32a9cb2affa4c1dc92a95b19bb4868f3ae4bbf4a0629e3cc5a46dc259c0d00ae4fd36e28036f1e947391326644498e1ca4e7a8f043057d455e53dbf31d0f0c741407b5adb73509e838bb156f801809be25478a7c7433283bae5a5a3864dd0bd49a0a8e9d0cf8d2d0005d6354758e91a66f45ec95e74861195a156dd0b36f07b8076a14281fe3f5c42a18928bcaf61cd064b36465aea87b7aa0ec75ab38f10a4e6fbf370031a9428baa85d5553e3ac0a1b1e4f56ade90d7709cd4f12a4c9b05c02511ac95010885b8a6001ad6c46497ef1c1810d80839662242fbc65c2b700a82b2b06afdcd6c4d253f3a06850ff1c1c04a4879711d9cb7ac593f53c04f5303f03c625938d81cb575e74921534fc7023792bbaca28c85f456d6c85bfccdba08080c7787f2e66a5dd660f21356a281863eaa5f1424312739a65560895fc0bf057df124c8962b5ec2dde027f46c986ffc1a427dd428c73f2575a3dd8288cefc08a062a3c67240e41978f3ff93436f89777b58fc58805e60f683f9bd6faa864e0126ee980fd563b7c0442a0cae99d33565a28a7372469b371befca5466a3846000d87056007539b2f0d79b5f413a182af5794ac9b950f1981b36bb9ba50c376604f2b7bb892a1317ec666afe4b2eeec32cbb7a4044e944d718296e74c1426d940d7997512871325ed1fe29718800fcbbc009a5d93da5c910e60dfe1b2430eb0a04e558e4f769f93616b079c1b5efd25db61c5f71d44f0346db37380a7f7846c60d29362665b7474cc37f2657dc2b7d8e495fc0e8c75158c44a365dd7deebe16b02e36a6dc11b4fbaf9e2d74497ab1978052e26360f8a07c3ddb70f7d73b11f0407fc1d285bb960a853f3d7db8fa5a9b2dd07a664fb62de2ef4c4a5ca9ad79f30046fecf542355b6dbcd761e55eb3ae9ec32b969f64eccfc5ba41c1415d0763b90703eb78735c7ff5372a65236e1043ff08e77170487acd3476b82e5f0f21dc1f040c8460813abf7ace96d536e4061b64d08208dd3855d3d77ff296a0193cfd010dfafc42748e8f44bb89c2c385ead56cb0a6500fbfa83aa2d33c184ab37f2ea307ee97f0ad6899e1080396c7f5244d85a972b7b5dd7b101a8c601ea71e9a56ec08efc784bd9e755bfc7081763b2bfc3241b2382cc2dcc746c1c2adf2e0cddc4e00748b299641fb1749e4444e1df71397a96219d4f371edf754ae1c3bb859130d031b73e213d4d533cdbc6dc0702476273ce93127c95e87f27303436d3ec424870d58ddb13cff028723a2b211d5ab87acb3031f0ea5a03b3ce14199283dc2fafb0a8b8944d0bb6a8ba068b6848bae939569b554099a8f69b8e8aed526a4227dd90f2526c3bf44a34b679a9eb033df96a0815bbbe911c1171b4777f6ff6bf516c707dd2c8e59bdf6110df9f8ba3349e23deb479199b5d9998e61b3e78a57032f6b0ce3750f544215a14a72b434246083314684946b2dad612fcf550ae0e7a60343028c3384754a692098c30d38ea2100a4319067f73349a8156b94dee3a8a6baa50c8a02a684cfc3882cff7548cb608fe0f7652e7c1502370656656552a0ca7ef708d3ede8f5e472606a2b92de0c19d40f5fa4bdd6e24cd15bb0319ee66b13c8560f8f915d065f3542d6fc7fa4b28aec3ee3a92113b75c7bbee2ce7b85caf9e6fb0cf78c919c2c372535678f426be28a1b6aa4c878589e985b62494f52a20be773058c5a4319b5c107d135151e0567345139a3592e071fb96a035d8364416f8353085a4da7d68093a2a6adee33f8951f8697095ea093b5a28d6a2a6a1c09115c920ed3b40825ab8755e2b1a3bf2a57662aa3dc78404731ea989d385b674ac4ae8f0cf3ef4b51b8c82cb3bfec29c12934f0922e45b5ae2641788c82f9378abdd21506f5196b1f1c4e15f36c8268c2865681f266e98a616b69a19882d816dc5ece43027afb68d919b9514e18ed47fa5f9906686ac07b6e15642d7acb17f1ceb03bb309d70be29ffc8f714169e214148b628e014e9ba5a840ebcd48cb45361332f57109f69a1ee2cbd31ae2b1dab0a86269758f5ee68828b9a506539e83157be2d078001a88662286d5ddb163f5fcff2a305132f1c643d644bf829fe5fb2d1d87fe5b0df774f29b7ddfbacbfa290d638eec8e4087ab74f0d0acfc9ca6e19cee44ca9703c39867bde6b7ac6a654acd8f799e81f551b7df6353f844708ad15026a330410202cde7fb5eaafd7141150e89af6e23c31cddf13f430cb7f5e174d121cd94c10a2bcca9f833521405ec35f9bca031710c4405542d936a4588295ad30536aa8608c63f55adb8bf1b5478bf3c8990d9e367786925a2ade306ff8a4f44310bcc7501594cd0dfe9bcee0d004127f13c125ac774fdff5ac9d975e1b773a236dd02fc0ebe3e81b7c3fa5e104dedb761831388b49a08559700eb53be744cfee4ae2fca056e78c14495b1a1be73b257bfcafb3fcef8ec6410bcce57457355ba470b23f30add59d49217b65f06b77dd23bb70a3bf4cace891a1c8ab20dce3eb5889c56db0a912b27a53c3e04191fa516cd32f3d48f64d61e316dc4d751d4e042c07f48ce0de119e10d7ee53a6468d03ee9acaf0bd36219c1c83f693090c039cc53befce1065901717de9718811ba5ca6ebfa807ac0936a5d552670fdb141c12f19911bcf0afd846f5e476747374a516af468711dcd39fbfa923f061489352b4763fc554702d737d75c6b70b925cf3ce8100069972d25124039a5db574b4f76929ad3b4050a06712d01f2d14ce08ab83389ac5dc8798277622fcc698bf97a36e13cd4cb950649193b7ed63a830159a33585539f1d22d1516659fa3891f67c281deaaa888f08583bab5e9d2f4eca6cc65b1eae7e7935f6e4e85f709207d4cac1d5394964930e37874c30b18591a9b420c5e0b460e50f8cf27e929800b8006f2be503763b8b092825230a2e884d2d9a26c140605fb7953096f59968af356b661acb65cae151071996777d3160cf40204cf833cb24aba69d73127cd5a6f53e101b293c3f07df0127c4d55cccd4d1749cc5c9612e128b8e108a0c34011687ec96b5e2cde281e60d776aa652d7f08e73b93512eeb14e14a60a93995fb4518592f1eb197a879dfd02afb1de3926e2c3141742236ad35c5e920d4549a2a8d6a970b1e1ae00db9bcf04f5e0f08df98c8f7432b531492c926590ac6136fd56306f8efe7043614ebd17044deb383d2e219fbee78f9cdf63825ae6f757561654ecadd5b8e28bc4e7dc3f0589b26005d4b159a6a5d8d27caf9a5507eb7aa3f2374c0e2656a3d1c088341106d1c38c1217e72b155babd4a67d301b3a109cf932ea59fdc27811d7c0c4762a0956eb4940c88d113ccc65681de6c854102d77a82c6075f53b7966d5421c424b0a8a85f1e5fc72a59338b59cddb3daa816bf6445f0ef0c02ce87c273d2e5de770751328d4b5869440e0fb58292223886ae2de3dcd35a0350eca38ec536df24330d83204fb31746c6283c8c61efbfa7d99e4cb17c27f3c9572014384610236dbc0b90ebb3c4c6be726dec00443f7e7424abb4edda50598e658b52235eeeed929302 -generate_ring_signature 5f538e02b1461f07c98077400e3cf540b0626000edcc0ee4f184bd1f72604f9a 6be7e0a471ad7fee54ade0d6615b22f36f5ef44992917c3981ef7a0a4d561da8 7 4648fa9cfdae1cc58f504ea9031acb69b269d148e581e01294730540f5ff6930 9dfca258921efd4ea725792ba16046d64831fc572f3dc72ee4fca1100b966ddb d7f734b73581e4fcd011a57ccf613b25ab32c3e61dcc3aee5b65ee0d118f3858 e11aadc5cd441dd0c48f584c8f92cd17d1aff66ddbb7f86e4ee6deae1870f0c2 9893530b57c30c46ffd006059cc5ccf20a35632060107d8ee0272da1cf219b7c 0f5a132da48e2f8dd651651c00026b9ae41d909503fc5e7b64c808201a06d2fc 69fcfadb6d9b4b296d86583324f22d124fd6764ce0dc6331efe72adef2ba1a26 02043a6d949d79e1a8c63c231e3db3bf406bf741d9e4a35b14c41e9813e90a00 4 2ff1b37eb77c41161ad4554270d6ec2d11c25dbd4b36d6d943429fc4e4b52902b081e532196f8597b497d578828e3f579a97962d7ebe328da5b636628bfc5c0be8dc2d0db4e88cccc1e0cef2c384e43c835f58cf2219dd3de0870129082847090804eca45c7059e07b9e4febd2c77c3bf02f5126e8921ec357a36d5fd46ec30e245865416799024c61adba5501d1e6a1810e27ab3baf2013da31949566b397035ddb58031ffdb585eea0fb301b0b67d739bc80c86ad4ec3c809bd49dec27100381761103e82118cb185f2c07a2a64f9676de0e0534205fd79b0c9a968ad9af08ecc95a4d782cbf56b15b7213082c25fba5a16f3999574dfff4cc9703792d6a007943ecea1497d8114b1dcccd008e61c2cbb315444aea5e9c09d9a9f4aacc370d3df96a8dc4987c11f20476ff2f9f58c0f50ff3076e3a4e17d1ad4efc8ac1080edab3016868bb2e68f0c0d2aee37174665d2783a95f94cafcfb448d095c89d9098ec327a99e893a1ddd6b52e7861ac018fe68a2dbb8e7e1a03fea94af644e1201601450698ed41e83ee306bfbe5859c66d028082c4554eb6b4394c5fb9ee06102a8f4e4497abb3af7b99264021ca8d2de203b37464284f672299b3442c7a2ad03 -generate_ring_signature 39bd24a7043973bd7a7f4c8e448e7787d1e5aab98f333b25391f624a492c1d35 e7551719351d2f367292d49a58da045bc9af52dd31cb565a2020f5fd3333728d 253 87211d95088dcae2b1d8db1e408b1eea3050193114a62975b8228d69364c2e16 d8080eb5ff65b1e88262670190e68166ea45b3b603b37b6d7373cfaa636f165e 241d5a6bf98df975d09c3fd82f28daf686e24e8d577632498cf47a80742fa4a9 28044c0d9ec190be78c95859877fc3c71a5eafb944d87af6657986098d5df61c b5380a0808e51b9bb85a54c703ebec3c1dd5d00ca4c776d3a4d88a3b15fe13a9 9b02e613f1bd267ab8ba9f17e1f44dd254e539ac7c4ae51db640be7d43aee526 b4dbc4c9bfc1aaad51e0a4605f40f3e4d86bc7483e9034c60412b099eb36dacc 94af0b33beeef150aac1ed32fab925099b688b72a6d854115507e893d15663c2 7e8e137d9e882f0fb9e8eeb29e607cdb113578b086780a0728e926492017232b c025e69848c70343a238a934746b0dc0edcd2d545af7003bc00e647cee2f635a 80c47dbf387d8fc014051cdb257585f7b85b08e41364e3a6267652db57967cf8 2f16c481aaaedc8ba701a58363f4574d21fbe7d9d3b225c200b7fa9725f15948 8ea6e2ff9ce7991d7764a92cba2c865f5e2a5e258588a43f76e17e41de039808 75ba819f4fbfdff82330cc7afac927e72fdd861cd9243693ba5745891311fc15 23a6a044fc33f8f2e7f8aff58e94283ea45fc8202f1e84c71914073fefea600b 3662f25a290356e28770c62bd711ad6ad929ecab25da3f515a3c053e6212311a 192b423ccbb0d6d329e42a8d0317c8a00db0e5a2decb455b79f6b7d9c0737c06 054535dfacb051e8f8cca57c43ea456cbf563fc80371b8ab750b4d9e660270a4 892ebd8b4d5abca1c059e3aac1cb2543194108cd999debe33e7a65d112760d2c 6627c6b5e09c06f9329edb030089e2bd60212ec499bf9e00ead218f3b4c4a94d 0323b5f1c8df8fc71595693abe6a5423cafcc7379ea59a1fbae58b1c820f5f66 8cc337574d514c3b74794eeb2cfd25a2b0c10768e631bee1c08499ba34b08c50 42ac8825861673461fc8e350040863a663fc03a8c7822d4d97ed3d80369be618 c4e5dc0e598b2d75087c6fe50b411588803f1924ac9cf53882d952b6bf175e20 f93279c53d909208453b55837953825d8fce2dd9d88d98917e7946016653d867 094f2ff19126af7b3c0f71d8f0d569edb7d4ab103a7b541a85defdfd3f516473 00da2bfcf3f2f224fc3536837ca93891dba7254213f5314015eb6be4f365c6aa 99fd38e293ec436c242c51b8d7688a1e0da8b8d9498f568c8c67b7fc7b03ff35 e8b3c064790b8c6004889e828c28e4a13c94de102ff868c0cb30fa7a1b310455 e009ac341d6cc6f400c9aa812eae38b983ff1c3950ec0ad32f54a637714207c8 41d6e1013a167657aca3c785b428458a53751a3ce4f55e7f69d1c2a732dfceae cb6646dda6cc5d0f46c3eb31b6956d944b63687ffd3ad12f0d58fe4a1412021e 989c30d40c19570e0fce6aba0e6789ec2351436a0deac9f4bf373a5621583610 ddc4aaea5c7d9b2619c2cc955076f63ad67beff0f57cd678a43b6aaa935629c5 7137f11a9d15db1ecab14ea167381fa81bd092040a9bce49661788380f5deeeb 92670f852c2cd07a97830d3f4db9577d9e933d72b46524dd05c65325d9a2f875 d053e29032574a0eb93bd7f30dba833b1da8181e2093e3b50d28a5f39dca6b6f f4e4496e938470ad634e61275427d3fb275fcdef514164975d93a320f5882e88 80e0024f178225cb0b40aedf698b8f4b85e413a34e29df3e3adf9bab15296e0d caa36897b70299c47f3a0cc3aa7433b9c5273e803dabd5986f84763492a41a90 7cd4fe492d5fa570d769270c0cc8ebba8fb7253dedb141801482ecc5fea15a98 a2a76ff27b18546a18b6bbbeafb1ece1272a03e2f147e9bce94da684f018e322 90a46155d50366bdf2a2d7e398aea33224a295aa3455fad40dfb4515d365d60d d08d9934354be29e663f1c8e50b6e3610d8fa15c10e12feb4cbfb1d64a07a059 8555cde97863f54e6b9ed852e3c2a26c2ea56d815d710939d89eff70153d579e 265617d3c9973965a217a9cefc0200f5300f3ecacb1487add5e1bb141400147c 6a45afcb5a02430e57bf0af7572dfff1841b9740f5e5052540db3dbd64fe3cc0 1744e17c9cd258c8a7396e7d704bbc4c6c13b06cb92bfd176ba1567772cd4ae5 9236692660d3647d50a61c688725baefcaa8675ee933596c42886d7e57d81b46 a8a82c4536579ebd4e35bf3030b1d18b00f3b56befdcaa94e6e6dddb00b3aef1 eccdd01e8deee3c4ea8fffc8b41bcfe089da7fc2d0d250c8d81c790a0a340127 a1b33761a1691e68c0ddadae7965b912a0a2578b27eb6e5234cfd1f6bc175dd5 65df31e331e3a1f31f01892821485c796e18ae9be5046c567c2f9f31edea5eb4 f51b804b2b4c7047e874db85fc1f827c78facacef789bba5ae0bac362a8719c3 cefbc7087a409c7bfeaf01713590ab8ba8cf200f0e253ee24513acadd14eace3 5e24afee28b5670695148232ff4ac7aeb6d028430f7e52ec699bb8d2fa423543 75ca63027ccfa35301adda5929b6d34db711287e8c20049f04682940a2574cbf 6d028deeb9f33d1e2dc9a7815aed9d46c8bc5ef5a24ee180c51b992d02447feb 0b4862a56199782c3db8d96e126b52966d8857c030bcd12bf78dcff477de2dee 6f5a8b4bee8f6d5f58db280c52b72b24011168a95f856460018c6e942cb93018 a8866f4e5582371713d07a92b9db45fb32f27fabdb45fe78b71175af9b9abb05 f9abffce30898c135700ac2872cce9820f6771733cfa615a271529c04e619c2f eee59d2fd563cd83bf665f28f327f28f2236e0d7c72e034da73634668014a050 22a58e501959e7d96664eea0a947f95643cadab389bd257649bbcb75e52b101b df4b5654604c4fa3b69a9303047f39149a9ff62e5294ce1cb9f03a6599128759 892b52449e8ade9f51e72afa4d16cfd61025a0b852b4aaf0b62771ca4e4d1c03 e922bf917ec5c7181a864a2b0fab689c90593a47591b3ad0ad442ce8b632aabf 09622f5fb64ce4b5d67a424a280af79dbaee60a557cada15a72045f27c839617 791107d5f62b4de6c11a38bcd84a836ac5799cdb4fc736f1f5e14f8d4bb56d9d 3279edd7b2fcacab9810ac647eac12ce8b16994829f283d3eb83f8e13a4d1429 739d415d0f7d8d65675ab5dee02fba52b22baf769fa331477768e8fa21341d4f b6bfcd65dbdb070b48930d06a83706aebcd7be61fd7595c8402da87f09e8303d 9007464c9c734c561094b29f09be140baa1565ed3c09196f399e82b489ca5aa5 be6092d1c575e39349a043b24d3df2a8e9b4938e8ba67796428ad0a7309f808f 2ab34408c3bacd9bfea53991e4a6e69ef5c6bb25978bc25f62244b143f9bf52a 76a04b6675637ac67513c8e6f9d89243f059e3407a7d04d534597bd0c7e46897 06325655016660438374f04b5190d361b605d30a2df103fc4f1acb7e28b7e6f0 5f3db63b41e7c2789a9839ad5fa73abf78d9ee2a6ed7fffa7ab485ae0b1c21c0 481f3b51347b46eabc5136721c1edf697febbaefadbd1d0d72f8f792de0fabf0 a8fb1a7241ea84c5e50739aaea6761d538a042bb33341adcf37e088aa1d51477 10c28dfb14d43cb7914d21f8a5875d6825d44258b8cd578706befdb2bda02092 5fb5866fb47158c2a5bf8abcb52a9c53a2d4f9c0c549d352394aa96b79e406ce d3c12eeb91a1d62781ebb072b272ab1bff02d2fc5c0c8f2af0db54696121c282 d7cf291e972479633e7b3b3c6fb8019fbcc26888e6048d9e78eb63058a5ea47d bf0a952706bbd8adf29a83b681560fb826be849ffbc69d7fada22e90fe83f9de 83b805751bcde4a3174a5f6531efa627a47b849f702d6e7ff871ab792f0cc818 c3e23cbc18a7aacac51625ba45f180e4fac85c76df506553f5c1864fe17c086c 3abf67694d6026a2cdc3ac07aa3281e527594c551319a2e6d9b257b7d46b58a1 382f03e3d26afee7c3f7a8aff90539d0b05521bb3458161f05e472717e050924 1a2dcee09581ba083f476068b6e59c97b3179c2a9759fd5062f6ed03854e6738 a1837059296356f67330d65f3ec669a77140310381bd40b8833038da9ac9467e b786b45a36f1fb2ab17fa149b179db91ac9214a6331990f899b9c9d607a96948 b3d9d31002353f99de917df0fe2a29bbf9468cb39f3ac6f15cd3693b9bec9500 afd4d04039fc38e10cc42211f091880c106b4ee88cf223d674b72691ef04f0e2 779fe4986cc325cf9d43a81527667f5477bc6b0dab67b5deaecc1c78c3b41228 6967bc33b9751da2b33cb217691bbd5fdbc87db54e360c236725df760271a6d2 20b279076b9092772984b180cfa0984e2ed6588a2c970d6a406b2773170a25a0 26109422f9bc97fb8374c815a93ed9634c8140a8d0e14975d7f1e52b66580946 7eeac26b1ba8efe87bb115537a60ee5a2bf6b16a269a518d7c60c3a17b3f89bc 98e996ba603332be1162e011edfec5b73a3a6184918c34d81a6d8b43a4badbe2 f92c62570ca18eccc7778273b29c5c817e19aa5559a5104cef66e4e89dc9ff9a 96ac32b1c4d83ef670005b00e79131cc3bea1253d5c082475e6da0b399b8ec46 13bae2d12ee9264bb9291453cd7019a57958f502960c34e42017c13a0d428ca8 a344ba1158f690728f90eff634b62ef5f2ce2b8485e7ec9eb3d523df9ce9e20f 540926e4afd31183a2d64de8c688960ee63aad78f8265810d24750989af3703a 827ca48a9bb00510c9c89c629ab3e7fa5870fe2493bc6e07b86390c7f893e91f 7724d7adaba57802ed1509ec9030323f08e6408afb4cdfdc05655161b75e1525 a21c61d032a71dc127b1677cdf43876169493bea45add0649cc9d059bfd20f9e 62ed1053385cf71c7f25369a405d4b30b726588341ed822fab9949216c55269b 0012dfb8eebda069b6b178448c062b01df2580dfa68356ea9b18c466d7c21a1a 2b87f48472bb3c7e4d2cce4ff0cb1ae568db0c8731e6c368252a791bf83836bd fb4c4da5dc1f72661f0af5db7637f1b7940d849103c430d63968c320a02eb9b0 9c52d72249c8cfb3821117962383eda8c12b6e3f8d23986ab4afd3a488437fa3 d2aac9ca8f90feecac1c737690c26d3b3ca4cd90841001749b22b16bdc1e43e9 0392f0abb11ce9258379706f9da4703e71454fc7d8d67536b1f607f207751b32 78a67470664d2bbc9b352cb4b14ef9009d9e90bd4cbb0026803d1968a3cd1078 d3c46ae28f78b2aed09cbc451d9923667908a5d43a8e092b630ee4be84394500 89e4bd7046c2f12dd51effb3d2c800f3ab40ea4da49977c1d552a12d7f8aa959 1989bff2c64645d0364924db8586d990ae186ae9f313e91dfb4b3b70d05c8f93 42a1b41f6cca4410e04819ed22f20c9182e7a9b9bd7e8408c41a2eaf48f1d192 35b4663612712abbe565843fc2c8761a1b3b0fff08fbaaffdeb0e3a7f6853638 3daf4ec635bb2e54e527afe6df275c297f7fe217724781c4f8739ccc9c9b2fb6 5afe40899e4e7b817bad34de512ee2077227facc7bf4d3af21ae52fd13526623 b0ff07a6f55a5b48ac6112e029541eadeae416e99a88a2805f230346eed89629 7d6a9122f5df8c327f111e1b3bb934067ef9d0070c3e34681560145cd3544e61 bba9cf327cbd4ab53e16379ff673f14ff209e9f69fa78507504290352b22f1e0 09f78a7968c74f519ec07af117b5937a93445fd1292b3f4c6c048ed3f2ad473e 4cceabfe35704957d8d765ebfbb4b25e7aef813bbb69918e328a82ccc9cd0ef5 4d072bdb1e147c44696d3ac42708497cd14bd5b2053c4231e0f269ab68801d38 fe2581a5df60a4be668cf4eeff3b81b1535b62a8a073663d25cc40ae7e727bd7 201d6fc7a1d66b80f66b2a7e7461ff48c2f7f494ce75cf6a8fd07994315c7d3d 4aacc4df48cb39506847e47fd1de8aecd36644ea9a0a3715aa6410f90bdd17cf 391c4953fe0d607a5fe0757d3b6d89f377eef9472e2df092d84330dab9032c3b 7c0b6f25bcbdfddef802981b87e2d2602e796ddfbf38c612a1ee279575b473a8 7d918f300409fb5498d22dab33d5fabb006e03884a8120342e8c7de43a0ddb41 b472faed5d81a2ad3b5abad7bc4254a17e227e6cf61dd85f808343ca66d04dcd 56046d829e429c14ca5bdf58c1735f9ed29b23d82dc82b865f4404bf2164f78a a777c375406fa5771e7014fd9c7f1195047cd7afafbfbc4e90895f07b25bed88 2c8a6d21d61e1f11e8c4384310f41a6d170302ed1693767879280e6d26a2745a a629e4931c6b0932c982fa5204e98907abe2f36060e8571eac9faf4214983ec6 26b14959b10a5fc133763c1042da576408b7ef0722e74c7c990771ecb67194b9 33c948c923205f23965294543804368f8d60f355d0b812d7ae49100ac3dec0dc 5e334c7ded8a7fc203e7b4b7e03842582d3f87bc6d2e975091c5b1749dc3afbc 9ede74c0b6637781bd4d617a1ce397c5c6d985f56ae0a3a55292139e636e343e 397a7f6cc7cdd493461ed52f39dad6f3250a8463472c95ed9d549d6d64c934dc 0faba779da6568d7f50b60ac6c02ad0abbc93f4da87aa61940a159b4ae7f96bc ff1543693433d98347ca081f5450abdaa0cf029ccd8654b31920dc8630feddde 333f205783f49fa3f0c93d9b97791d7d477a9731131559f998bdfe978885604b 1d3b152f9ab2ede0ca97f01ae350441b4aab27bc99419b2b65a499785c4fb523 67d42536c5b0cae6b6613aa4f2a9655fb108a1cb9c741ec0e8acc47b0f50bb5b 0ac2a1b9379b4eb1c63d742bf7789f3f9ebac237ca1890cfd527762b7f24324e 8ab3bbc165e4d338e6a06221aa9d7bfe583a02ea4e411c5712f7890e87206362 2b570b3e4505e0c909b0b5c8516bf506c47f4a46857255536e9ed48cb668c8f6 c88352c9f9f561fd50106608d456a26849fc9b94b9b6fe630685500c8c0a9374 2909dfaaeafaa66a84f68336277f17295af6f389bad3ef74fa3f998fe1d7aabe b59fe7f21465882cb99b1005442917cccd40b9991f9ddd1c0a5caaec633e2a7b 0af13e35bb870c074cfd20e6488817842223336da2ac422534a4e47b5096e14d 31c21003ebf459dcf7d60d87619e953d60cbac7f3e56a3006f783d7409231169 58bbdc210a0a3c9e6d7a6c1a739e71385d260acb26caf1971161f1ff129cc850 a0c1fea9d30b676be2bacab78a0a803cb91d0d5b7dca34e7414b623d31d760cd cfd7370b09766f1129c6f7154fa9173b72b15492c96ff5423112d81aaab345a3 1c4adf684aa1c063c88f48b6d755b6ff3e234b4abfaf11e669b4b049f3990ed3 10287329dc43f6f23651cb0b6ad8cf44a733a6d62f5e3bf0bb564f9411b8fc53 eae584bd1ed75c877553e40e71f0fd3368fcf5ab466f60fd51fdeef2f3163ad9 20723ccd0d19029a89eb5a705cbf37c67fa7482b2b5cf32b269713f9e82df0a3 4b435f890fbec0afa63df7ff10216141b4cc91f2ef43e45960fa369643490fae 3946de1a98c9dbb03306cb44d1345352df983c0ee81c599642037ec826a95a73 81f7954e59f94dab306d170894f26a64a3ed794e58da478fa4b1c97d3e7f702a 7b17975da7e5f925b7c00c9e49ab67c1c05fdc84ecf7c7c2bd9052fc1792a993 c2a95abe1d8563d55b71d31539718f81588180dbc1e7613ced3cc8883b7a4ddb 4151bc7f598d8b5f51c06994350ce4992cbd5cf5f0af19131f2eeb2930e0c2a6 e6d57d2471095e9557746dc61e51d13d23a13a39c21cb2f5a025e6e57d955319 f6948af76dfc38f9f369132e61275d3931f73cab4be55e0c74c26f3ac06f25ce cac3b7a21c358d6bfa6b75afe0ac3ccb00c8e1e42c1cad83652d21f687953df0 7f80969a5e9ae3b12dae228ec1a9705e9e5cf8822df26f4b2e01d33d01960ffe 7f88d5c21dd827ae7133e3685fef7cd74348ede6ce206f77c48bfbc3ca8d9d16 0137e2fc4336f7f6e5c58ac7de684ed6fbb80b94f9a566e462397185a83aa3bc 4e09fed75cc9ac94c945f26099179285d323109b9e5e6495a5fe70352b47b23d 014decd861cb19767ad2aabb1df2a1a9c39a90ebfb0f9bba99336101a3caeb04 6a8e6bba480e9236ff6d502a670c9c3214af2c2c54d68ae26373be3ea9f6ba54 ee16d722d807012e9b33dc391fa877d6ff8b4c28d8a60bef98407d595fd84bea 01c76b8e1b6a8bc8da70dce6e764ae7c3a5e84299e5ee08cd549452e8a7ad5f7 7f9dddc19df35383423444f76b977bf5f9f8aeca8ee4d12b1c2d47050c4865aa e31923c564f3331aca4266e02a02fbb38082782bf920c73266dafcf5c584a938 e9e1a4257cf560e8c93178a567c31cc5b0da317989e91fbba69e19fdc144a850 d99b31b583a68991c6a729ab3e014e8efa878f4d73428a3e7837b4ccfb7ec34d c43dd8c6692eba9517699c6ecdcb4addf074078005e66901131e3a951c1b0edc 0c4adff4116912e3cddbd8af1e0a54252745b18c8069f00848c86fcaaf1b7aee 71435bb799f392c3fac1d37fbf25cc104123c4200deb7027a25c83f14e1376a6 106deb263504c267e112d2a5a0119a2c56801262370e5005798474cef408ba50 39287346a77fee5f44ad898f17384b4f8d6fd9f579ae9b1a247c0092ea61a459 2227d6bb59ff0f8b917decbf5da7fed3e6b1da14d1acff753c24e8900dc37e74 2bb4d37ed8a566931a8b423ec83989cbf87d6c95be7348060bece8b781706a01 08092eda20bdacec2c77841cd6cc4c5520f526f95d6f0826633bdf037d9d4113 1c2c619b184d8283b6fae53673fb2b157236ac33610eb5b83071d2ed211e0ff0 8e2cfee0c3e50d555312177c397f1f7e28c137f8c66adf4480320f809feae542 91e29a009e5a842cc42d63fb6df9c01d2d166b97128e9e30747cdd6bcf40b27b 015e3a83975191cee58d69290ca0bb424a728c4016bf7d7a8446045f3b445038 0e1644bbae9ce4dcd9310271cdef3f5a1e50dded3fc252ea67d4622f6cdb3f59 15fabd6e07c43e4fd09387cab79bd79d2d1167254e03ea4b2bc14a79d86d3d73 334c7d74257b32240e6cd3715e5ccad9c9854e499e2a0a9a965b05e66a158c11 931728bb4e71c9ea18ca56741a4ce91611399a12d55d24c5e926d860c9671f67 e8f5006539db80c08d514de53e33c196fedfd6cc69d25cd854ec7e620689f605 184a126faeaf6f5a815c95c47e9c04a7944eb0bf9a333ad1e170cc214e0c89de 30243847c6842b53d49252ec2cb97d6ed6380c6a1b51f38aa5c22734eb444af4 4fbbf2cee95f7dcec26c8dbc0c6cd3933761707f72014b23754cff935cb17bc8 9bf3ae0a3eac604de96bcd6601a8c7cf6e4b50a0cdb19564202c56ca566f7e76 1db713ff96be67e88510ada404d59b61cb72233bc848a67a49218fa7eb03c580 11e055e9d596101236c23c1ec2547d92d43609e34f9df12b5921a1eb86d94c6d d2577aa223e766db511f51c5b2e682bcf7bbeac3f1d62688676eae35d0676a18 94249cd701e10680522711d48a1c700f65ee7a588eabd3d14db6b00d3b0a883a d3565a2fe13cac9f6fdb94345fadbc56e9925d6f4e23a724aad18f2ac389d0c0 e76aefa00ff29a4f6b79828490b0cf6a5f1d80ba4b6a261c1e92db2ca2394f53 ccafb3c0c1bf893669cca0d35e6cca664e3506dfeedbe2e9ad03118c97101ccb 2f93eca42748aca9b75b35d4e93605dbeae6899aff2243302b90dc708b619b91 9c5f644fffc89210281ed0be8025d6f26bc199f6acef6c7d540db9074d22d480 73d571d06399b629e06ddb6570e0f8c2bbd1f77e533ae6299f52d41a5f7338c4 15ce90fd29a054ba8b0b6d055618880b09bbd224a023ea05ab2351fea9d803fa a989382b2acb0beba1b03b963333f871eeb5d33d3fe7458d5070ac2792197585 42f972b27b415208048a2b9a889b68da93265253bab8e0734d669999e1aa6d0d f26d0f678d98edbf10d7cc58d02907283cfb4af65ee711da72d049ca2d45db46 bbe344aad8977ce28c67cb5a68877a4d7c17f386a04a5c17616d1180b46e02bf e0ab79f061bf88fdd6779df98d9dda293f3d2795aa708a2de6490ba655834006 88c2506e0a3f6e896df79e698020e240452b32c6fac52bc977b25747f19f64af b4f594a10eede8ad967bdfdc073119224909381b7dccd689adab2fcec0144fde 397a775a0664b932a0d72a7c98af6d08319dcad3c32db270120b0e277d79a3c3 7d63131afe8aea760a530344ee8deb6b7da613e3ddab7f85c3e1f7035769f782 8a71c81729b06a8c8627850015e8d7561040187685d648d0e4099ac2dc090836 5d17966c6bd9faa7cda178016d03b4aa310d78bdf42eee6de5dbf5466a9d6c58 9791a2b9abca7e54d48afe35fcceac3910298b64474e867a3a3a8593201ec83f 65829bef7805b4703ad88fc1a7cf848b38c3e40c0b16a7b7104bcd0741403e56 60512fca2ed6efb77f8299b3b33688bb3e81f71265a1c4fbe1abdb266ead5057 2021516ef3799cc02c7a956d40f0efa1d4f95ff405ce8dfead6989b80b32bdb4 8fd4b02b418427901456dad0cd1ca52671894ad62abfa6f227ee2fb62538aa27 1be3f560260be66bac669acbe18472ee86b338e045fe6821d0de255ea839cb09 d5ae308119a926b3a4a359e0114ee2f938158c61f484dd750f4489cf0e535e10 e218771ec2e03708e7f885f14d9b233e1b7a7d262c56d4f009311a2aeda0ea4c c01c9457d1ad329799a61fb10620f4c0c0b500ba26ff7cc5c3351f1ce90f5b3b fa27dd75891242297128724a5e0f2cb0050f3952b21c3028e29be67af64d7747 8342bfdd59eb7d54a07830ae4d09a0d15064fc19fd4f174427cc33e46d8e535a 0ced66b48f6efd8b0230dd1bbd8c5550e0019d8def29913096e02d39292961df e98da021b8ec628abb0ecc8a6897f3324d7680db16ffb46dbe762c30779e038c 258d59f6081f46450745f0f7c8a5fdb41fbb4ddc0a0149ddc267630c2e677d9f 0f86b6e98a65ab1d035e0fd02262daf83b21c8ff9cab3cdf7afec0c43af3d1a2 25442f835deb1d4ea6333eff39668c84a94e30c57298169935b5afcfc36d7adb 303b1075bc6b497650521361175962ec0385dd87bf864def6f575c2adc3cd0a2 8ad76afc1d698b50abbdb1d94a5c86ccb49b17d49af4d36f39dfbc66ea953fe3 b5218d6cee39e1d1a74e500958b718e406a89c7f468754a744ffa8a39b54e8e1 fdb05ef89c3a19d21e8bb34783a60888a9be53e1e7672d1a3e6f5c6cda4e7029 1aa8d8d92f535ac3bcc0af296a3ffb2c977953ac1e75a25cb65c4f4456bf5ca9 890d1506854a507ae800a7edefe094979769b1e9ef9e376296e7b328830de625 7017bf0e6491806767601a30572fc2dca74d1de7cd3e0ddcf42d15373a04bc8d 71c0cd41b5e501771a72c57a6868c082d4076256afba7569814caec598602f27 376b3198ab6e5849451279c39453c528081337f80ef80e882e954f60b1410600 22 0c9e8f9068544fee2c1de301bca8fdb4e7a996ad3958c2335078618d8ffa470ba59652c9cdadcb367d706b0010e0a38d88d1ba52ba4ebc93322c2a8c54bb010f2d2499194362cf761d0d594464aa63d8d3590b5c4c3f8a0228ec02e9a0012f01b7233fa6f1bc29dd211463fd4224ebe57dc2c557e7b3fc50a8ea38721513f90906485d1ab6cdcfabdd4d599016aa9a0fa8eec1bcf49943292320ca7bc4a1eb0b34f786e8a4dc7b81ca378ccd121c09f2dbba0ec20f7145aefd4868211a3c52040649c49d07147be02435df395ed18daae787448d07671bcfc8697e624b12f1023c5710b65b7de9f62c9e253427b4819e17dee5d7aa2a509854a7d399ef1d5a0d08e01fc2fd942804c21a5ed4271d98ce3686ff2f7c1278dc15cbdccc80168b052ed1a0cba1e14c8f7ba7b065953d6ba340cd56dd8d886a9f8b1e1ef2ac3a3d0bd5009b9e2bb20feab1e0440c989a2e94829ea0f01ffc5dae5b45b2eaa25bc5054467aeaccf6170db78aefafab5aebe9bb3cb240141365a933c2194c40ef38c0eb6707ca694719713d74468eb24887851174a44a53cb8a7a4bfd61e8e051daa0ddeb397c87d204400958cf72841ddfc9cd71268ad962a8b815f030d057348b40d14a599aabd3dcd85755f4fa178b80a97d3275c1cdae97d26f45d57810e75f70cc0ac9ee4eefbd522f56890b3332216c642a7eac26345d1c4572d3146b2b4f50aff57f73e97d7ccfa54e3c276affb495ff39244d1eea42efacd11c3970ba90508281c67476d48e73048674f6fbda6c80c208df1d01c460ed8728947260dc7a80e25e9fd2c2c8155f0fa5dab86d9c2b91c417f18e8e24845646ba5fbc96293d4016dcaf2621d40fd3c3d38e5cbee5ef24ad15c26175152031622b4a7f81bd015081f425e3716c2f940f7d1b73490274fc656243526180f8be43be13c2579caad0c98472be6173becc70707554feb37925c96ff08b9b97de1ee95eb976f915ccb0bcc0ae009b6e8d0f116394e7af83a1ed6070eccda664f038cb4f6779dc20a690ff9296e1f0694ea293627acba003dc4dd884d2f4189997be8ba66988e51057b07b6c9471cf71d25ef0d756f3dc76c4baf1c9de13958174af259d92c47e186cc07e18ade94d882809dd2c577a14f043fffe5fcd7b6944e56cbc675b88f1c77420c92c625567a08ede95f185735389f4ddfc9853e7543bdc483d878eec058860d0c537d8134777b23cec6bb11b7cccdc9092d446cca977dba95c830a4c484a70f0e98e6ea670901800b150877188330eba41c382b14c62b9ca58a65a8a11486d5009d2a01a67f54328c3b009a156b44f27f7ffed30e0b04d38cfbcf091b91e0770e53201f3d5e841bc8677146e61ce3bc647a0acba5d3a940568e0c0e74027a800a1b83c25be06ba0269d9d52cfc16e511303071116c4841965c0de3105e5405e09e7b2dac14b9fdf7fbba45eb948b280d73c83bb8d4266062f4951034e1bd14301e510fb1c7db15e79dc064757d4f4d2a4747f8bbd5fc9d60404bab83c7b34420c5909c6463632342ed87cb3b00d0f18707e37bf1139d1c6e854089e09421522036ddf534c2e5080a60883538b31aef144660e92daafa3daad44503ae5d231a003b56e45558694782cea04c8949dea9ae1866514a84efdf850b1500926feca2e08d4a7c7a7aa1c3a354ad7ac1926087185c19d41df381836df5b743e646c24190f7fa5e3a1c404d8f27655c65a989f97764cb61ffcd0624387af29ed0374b6df064de9a91efda7e504435d7ed70cc65a47b3c5c2e5532453211846d7e607844c0f42ed7301493ddaaf2cae5ed67b5dd1e05bdaf6af277a4001641c19787d6e780d4742ce77456da93ffefbf7feec6a2102063797715ad167cf0d9e5e90f5d4f503ccaa7bb17bd10015444b0a31395fc23d5f62028240593fe2ab9c0c3492dc4f087dc0f63e66a6abd11070ba69045ef80a1f2c4f2cd44e8662330f56ef58010903ea719bc357ecc139f62cc71bc722f585895d0c019709787d4c3d3f86a3938503754d3c9818edd7b0328d8392435f42734a84ef3c2728ff32d7fc84949302670a8179923c4137a24202c0b4ff9e682a5aa158e8172d1efdc523d021ec9f37ef02f16c5dd35ed1b7484920b33ae4ff69655b89f6f30eb1f6864090736761fe4e0aaf8d5cc7dfcac9802da71934f8a9b50520badf21e07dc4571dde08cdfad57a0c9d9dfc0e74ef75b7333fa7349a07485ddd0580ac240e3ac2c78a86d47377700ed83b138fbb77ccbbc17ceba465280bf9f3836f91f8c7eebed4d419a6a2fca40282da21586766aca928221900268c2a6436a1c0d64e18fef0024688402d86ab0abca985171f1a977f8270cc60b8dd5ce454a3b3b3e9231aac844a984a4f151e01d601870e91a3faa786aad7a028f5b3e5e12409838e2b2168e46e17e57f583603404e9327ae88b00b94b914dfec1e54088af2df9d8596a814ba44a0875aebba0290602e11a52f55913c0d20926c23715b97eb54acfdb4032e3b36531567d3cd0d8b18909ddd7000586c003b4ea027095d12d3bd9abb19561f1295bce26cd2e609c2c36d424ab894da43c47cc2deb4f76dc570d67dae88ad482d8d0f93b31a1d0efb1b94e0700d54deb6c840d2db4de8ae397195e29d819a5d4ececd13a5f23f0a5bfb181ffa6fcee5d86333abfd95b691d0d951f8bbe36297ec8607eb00e6110153cd7ad846c15003e8c9e2171a979b956196c175dbee74fec593f106a0219302786f7fd0b4d9e5a9dfd944a1513899a0414ee184ef86af17c5ef7b5dac02ec0d820906640c1acd6464103255ec96f7a76dc90f1bfa65dbcdb5893b979444e609ccbb165a73dc70f88abffae3e1a3786e9cc75840d5243afa0de2d835683ada048524bceef407639edbab890c6fd2695bb8faf801e960c21bb1b5e23aa2e94f05e915c1d88f296a34c4fb88eaa3fee002b9247234a65d2b3d485ef784d7bce806a7db21f14adbf56dcc3615d95a0671ce0e973754924c5ac891e4029523e9e106f00f39ad39afcf02ecc843d9e93c229249ad547f1f6680e2ca27581e9d621a0df918ae6366e80b367edf6e97cc59773d7bb9e3691e167f3bc34cd95b1a8e7d0d800012c97cd4e67942d5cf249ae36192acb01d8b48d04e0cf4475636c7f8dd0dfb09890bb32b263c0cb964d703edd21b4e3a509697d7d2589074b930f4c5de00a9a347be56e0f4c4f59d62e091ba7057ac9520437bcb0b26aa9c66c668273c0ac75cdd7f3fe72d8d0792a87077a018744c02292c603a6475201886ce83d8a300e89304190ead434e518057f5d8dcbdb277c65d247b2d2c668bdaff700e783703ed92ba2a2e276265a5c58e70fe1b418c1219d2411a15c79d936263e26164520df441948bef0404d3d1c8797c84811978021d296b6926d648ca8b28463a840801e7888dfc2c5c21a6cf6e28aa0a74101703469b0af8086caaa0f3bddff0581d03acedba8da5e59f57dd354d413cf35f65479031aa5bd508f845de206d7d20c209755c12bf15a924e6a3a40f4f7846c5d02750bc219a5ae2130b8385ea8449850b3055ee15e2f3d62eb4c98d180b0a7aeefdf485c06623c17768007620bdc698044508f5c444bff75e8e4ac71094f0d380b616b74ff5e813b033cc18c7f2d91006c64b36366f0ff561df09cdf0713d8792c98f6dd17395ac14447381c5b90c4b04d555124609db930c7dfe231909a766ab3ecd0eb32c4d4cfc073a60ba5ab07c0eb52c10613d3ac397920830c13e7e8f6d09293ec1f86b5ed1772115352ac98d0896a47a17992c10ce9ef5e496e3003733353feec37de5105539242e4efb4519021ddb78396bbeec0eac62ec54cddc4865a468c1ad02c07f5d0c23c1b9a85a5200efb9c51d6e3ea194c5c8bf9f4c8d770b92035582679893cff995898821129b02b9630e7419b4166d3969654d8fbdba6f0572849d30d8bedcef91e0b472b21c0d4a896f9e0a080434df790f9284411d11ed1ff5da21552a6f979dd7d738d9cc0865fb58d781eef2cba1b0fba6cbc06932de1b19d1d0e4904118453dc746c1d1079828f0d4ffb5ff1e1c6c3449c230777dd0cc5519dc702ec8720852c63280380871985c651fafef2a7ba123b4a864affd6cce48fc2810e667d30722ff9f19b10115151b154f7c7983deee1e9666976308ff77ed799a9acb7588c2cce94db8b50c61f5a839202c67803ec7370dfc5f3d0619d578fa9aaefe2c6ce58a3eb1729a0eee287dc746f0db3f6131f5aa42a98df719604721ae0ef13a0f0c20775c53d00540d049c1e70e203b672331e66c1e25ec54cf53f46e324671af11422ac599820a9f858b8fcb4e4644cfff99a776ce4a06938a12d1fd04d76bcad793335509080e34534fcc2839197ddf8512b1bc7c14aa01e137fbf0db058762250271e7bed10d183517e6972bab43084f640d0895d03d06675997063cc373a0e055508cafbe0661ff6fc761ddfb10063b2c61b37ff53de1e8cd04f6ac8b4fac4f70a5e9f3fe0da33d92fb6c714e3ca71bf5244f8ff0ee9d51256a0656e1869f28e9f36cf2b700cbd0a10cc20f92baddaca5689dd096fa4168e0b59945cdd4219a5854dc2fde009fc31a0a742be28dcdb8de52ef5cc20e6026bbbc01a5f742f251f189ad853806aad1adb69c2cbd12cc0328d76c696e88eac8e252e873f738b5031efd1002d40817e9282d946dfcebf2af541d66e7ce645cfdc8b693b4653206ca88f2bfb81e0a74a916617923709274e8e787707f81295603f196d1a1c11ae23d10ddec60920f1c86607fb381d156f909d9aa607a6589fb4f6d810e51694f826e56ddbc49280228090e40fb7e170fec7092ccb40c23267ffd1045b21b58aed25734b6a62d47057941a0aadd627c4507bbe86b1eab8f4787bfa62a2dc480a6dc255b94094c210a26b69430aacbd7d4ca446aa2dc8320719fd765c8a616dcff7456c925c7cea70cdf6eff6cc7480f53ac9a183d7653be427ea4addde8cea992f41a90f01d1ae209f3116b823a70cf5d25967c7dad95c637c1b81fbc0ae77ab23684af73fd70740e7b92490dd2d02e5ecc03f0d2c31a3514795668ff3cb4c785665f063ac8e3f506a6a1de911d46e32fc713c5fca9782c9041b4a771dfa4a7e000fc4ee27e89e10b3fe9ec821cd7631f108a1e7a1980ba068b73810829c5768de2441131567ff70b4b5e6138a341055bba7fb16599f8704024761931c694f6974ffce9af0f8f5a061aaa06ffa631b457f3d67b17d946195ed83019826b435cf65aaaf4cf3164e405fe9cc4b25ae704d682823f77b9a6a3e242e26341c51bff6db15ad61945a085030b93baf4397ef103e48e97001b3fbbab794154ff7151f369c24b7d737241ef0d3f88797a365a787a916151cd9392e76f06c0fdd2da2e85ff8e3013168db9e20cace5780c92a6e85bbba2655af55341010fd0f43b76c513b630257a1eb2c20c09bc1cd68c5015a5f73b1254bad08bc84c7100350c7cafd43b4e10c402835fea0f6edef05971f166899baf1ebfb4e0096f3db17dd8f9387e45ed58ed642b3b5007aae7a88dc8491a07f33505c6c850662b292a3f2c3a65c1c9ecfb8cbcaa8be100db4ba3c506df12a9ac8c19595b0c86add4c3fbac7d45df6e91a2046bfc5fd20a52ab6073f99023c58c25bb97aaa51f21b8b94012893b3038b25c93d050c135036d57cd81557832dbd01d2b230b220d0dc7a84e682edca4a48690a017b3fcc504a41c40fd023e565aa6d15e99d504232a1c0f349555b8370d3421acea2e66af0eb82d84175c4f98da1fcb80fb7f56b4f32836275bf0bf790f1c4ad3b17423d704a5062fc8c654285e6917bfc9bffd80e68e665dbd74b5727e1fce02c6cf060e06dd479fed34c5a6e6c085729ba45a34d09c94ac9d7bb648a6b42d679134e8bc08f32ffff623557c9b53960cfcf2cd78fb00f0b4e9262814b24799d9a44b56b002834c91db8d6fc45e36df359360d452aafaff806d588223bcbe0fcddfca51790beb54068dd340bb4dab0f345e3d2ea30c20151d37966e546c23f6bf8d73738a09dc9c1d8f43c6831d30349221018ebb901b44bff7b43d2a174c4adc08d28e9b0240aecc1374723aae047fe34fb5763cf0aad158b50b6525a27d18f6c06d6d7804e2e9d39f7aab825de64278ec9ff183f08b7d20333944401c6b5b7a6ca2a5fd0e862a0cefa42047a48203d4ae4e427e9a6ce04c23c5dfe00fac0fce5eddcf76024f610cad126018f8bc319bb82459216a36928d964d6916170191ca9a8323dd0b141a872419db99500dc6cff91528d582ceddcc245290868a69b7f6d9d812a509a28323917bf9e0786dd77dc22af6bcffa6d6fa908dfb9789eceb96426739aa04e1971c48c9ce5418df5a0fdeb2ae84da5d5d053ce5eec9324ec49930892637064b60a44e917c25a61958de20d994d123bb71c9729d48a8704e1ed199d842500fc8325252a751c9b426433fedf63344ad62e7517e567a9edca5ba06ac1c3e4005c28a08894f1103ecebac79a7308d69023a995c2ff73bf9648235b78e22b2c1064def363aad8282e74f15cbec4c82e705d64bad9188b0dad43e3b4a7a495b1c09a1201eaa5c3aa0e23628051a8b2cd91f170c69a56a4c12862d60351018462f0abcb0513fbdde9caeca851a6973f96e7aaa31f86efe9ff92d6cff98b1bfe2800308fe607f53430000f104c31035f9dd9f21a6baeb63dae98fa0d957accec70102313f304bc6cd2248b7f7dd9b497b8741c0fd746fb10811781591082fad2b570ac869ef721bc8909a06a9d08a665579164c374cb839594c0c1a0fcc4697be6f0e038a34aa3ce5356f99c75403de0f4d18e5524c406aef8b6ca85aad16a6ecf30f9e74b05d12286f3b7000877eba9e9987dc920d7588bdd0fe9cacee871bc3290979947d782eb432f4fbf2d6b0bdd2184ef72a04cd2316ec824e6500d788ba7e079e5cc224a7201e4083cc231b00fb6549627cab00b6d493ebba1cce0d463c99042792d05bbac96cdbb416604809e1fe1b27f7998685d5e49c27d04f04efac3b06061697e839712f098f9596d0cf32f6bd1ff76b7659d1b627fe7b3209078ffd0bf1aa7c7d48bcf4a0f98409e8b01dbf329855783838b78906feacc8ec6d0758091aaa46d79f13766e433b0dfbe42ca183797aabc3c738353cb9181a09cadd2805d9c46e32de01c6725b550e3cad4ab4d5e047716cdab08cae95b953ebf3da130b06cecadc0db4601a60b44f9847379a5d961926095e6c16f9789eae958ece700cf6acae2143dce6ce2ded99e546386630ed94ce2879cbf2082dee3a949d38040f0902a37ffd8627cc9445d11b05e473b11921f958a83f2694d85f6aa6d5bbc60811c26449569217e887bedb2c21672b5bffe6e2bd4842a4787f96dfcccd06f3007aa8ffebbdbd67c54aa5394ef8a3b05c37c0acb19542c87bed99be92a7845004dca73a6be6de8f03d86f78f887610a45c22b375be60c89e3bce66025a7070d00cef35cc273425624bf81552d0c8cdebf21853e1f27d7ec30ce58f0baa63372098fee116ae8e719b0fe6ec51fbf254ce382e47cfbc768d12c6d9bca35809e8308e46579c1fb9b931f1326cf8cf58bc4ccb06ac4ca00727aaea1ec496b6a94ff0caf2a051331bf31151433ea38536c9a64b84e856efa7651ded40817e78bbb6009660cc8e1ccc97167702577ce3c3efbcaf5fff94745cf737379b42e9fc2ddd504080c3abf9c6ec85867adcf51656531833343d33f341d2eb725e3c5e80a3d6b00b90c38c93951fa8d635e24b0b0a48b2777e13e28e58ceba05c7f9bc8f3322305b530f6a457319701669c0b135583c05a2c44c029988bfbd50827e57dd002130517f4b8c06b1b64d89f44708f9f9be94d0e74905a8103dfd8f82f5dcaa168d40a7da2839690c9beda2cc82f8b81467f92c3c478aac981ceb429b3a6a3e5d842016361fcef9522e3fb1f8511a9ce446a37ad86972948629d783ec7df5767abd20625fcaa37690501207d502eb1729f30394f4e1688e7e7e266b85c317ad2ff340ca56d7a23ee1df0c73fb27bb22965c03c5cf5cb04cdce8fd3b1e7e5e05578410a9579eb3ec10a76b94236f2920efdcc72d3af010f6fa23612808f660bf2ce7c0a87af607bea164a8765703af3d16f4df4d20e69f987efc9edb5a555124db54a096572308654574d0612f64676c3b223c8e0eb2007363d134609c8d6a742968d0522b2252f8cc03a25aab5774a64c5df7a7f6711546092487af84c4607483a2d0b5bde96f702df14927b9907ccf6eba88977ec7b24834253dfb6657c351321660848d68c7fd33113431c12089375bd914a449bc95526aa4ae83e3d165217dc020cd6e3f60c57897ba86e29c056396c0d27b491c6aba1fcbc2f402a0f2a1033a8057867ecf746a1157ea58891e314ef9a4652d59e415ad82b9b887c19d138f9650753286821bbf782f934a0064178ffe6bda710f4031456b48cecfe4aca1bc42602e918aa46e512d94adf4f218b68f955c158794a54a13e69375c0e48d0c43b710ac30118ee440d7a501e724c79bc9d8f08dfaafa4b658aa47cb624990fcf6dbe0e26611ff81f1804487257c6094b228c555d5330f9eb617294b9614574e2df9c081905a187b7333629bf71f1bc89aee43494b1b44746716d301f1b0fb4bc9d15025b2686b4a6fc04d026196a8ed9f4444864fe4d0aea2a8b38a3d2dc39019c060f27cd572411b5979e3b4519aea6540c21ba95d55e11b9b3ceb26d522458bc7e022d6b0359b12ec355dea821c82ddf888473554083d0f36dbba8e9cca999effa0c8b0f4e13e9559ee50fe42d7bd071ca97f3455a348985c25872593b0071e196059bb82db11518a38ff6b91fbb263f46728ddda2f357c992b2d803d5faecbc0e0891ef4f92ab23d624dfd30a9efa25fd88456c4e84abf1bb8c11f268b5e0ba4209844e72fc68a6c3a26564d0fbbfc88431da1d765c292a81391ec5daba34d31507ceb8fb3044d9d1d1f99b4941a126e0580a255fc98fa2bb7ab58259d23d0a5d0a0df0bea82ecaab07f30d97d769d5b40c7605b11735ec813875e61a551a192304f8fb030c02c6f182bdda1d6ae85b8271260bedc2cedc301947bcd8a19470eb02969cb572cb4290989b0a9cc0938bd92218c65bdbdf97101cf7da93be851d3d03debda376dfddbb869e2f0c669c287e71de604a4682b30931f8178c70b8ecb8032401da4c9474ee1693df584e3bc074c6b3284b0962871a784d94012f0ca2890923f0f4be09049085029f38dfc47bfb9f289202b5d00a3d19de77ab0d07d88f0ff220751f75ab02690e02afc8bc3472c502ebabc9a09a20e636ac86ffc96529013c74764728f136711f653a8c9c3c2b08e6c9822691973a41a7bce053b5002a0a84e5e6a91e15ac847330943855a0aaf01b9a20e4da42cda63404e9d1a15b1005daee460c950776a19cdc223b1fc6fba907a787790f598ca5d0034c8bdd9c5a0eed4b0070fbf1e81b572499d71fa5595907ca348b232a56b19e5f14031f08ce0707dab2b3e7c7056ccd9b259f4401c6533a4a18b9f6bedbdac04445db0e4b4a091548d90dcce9ab43e248bfc01034d28a19ec4355d927849f7553b4b289830303043ef8b7fd5e3d1dce67cec39463a3859de87010a75e964cf2c09ea2d983710b055fb8000c5f8ee2f7c10d973d010548ceefb1699c5c80a24f9fd264fded960f0a5b9fabafca8659199e076a78283d6f291d79890dd0568cd654fed2d0eeb600bf96b8306a3df449b2bca6d176073a106e53e3a02eb1d5b12ccbfe00341b3b0034d3a83e9aff008d2f029b1252e62d55b5a7c0b6b30aea3b78ab92131fca1b032535f849044c6567bbe70ebc388d898fa231bc2e61fe387ba4df0070fee797005c443acf774e192170bbf7df813650dff1c4f38374e4b5a6cd4c1636103b220c93405333c6622beae311836860a889aab363eac2610166c6912619b6b4b69e061a720f5f99dc9556b8031b385f732db873767b09d7f550d8ba348a686393d208589bf347f450bd4a3e5e02936cecfbf85f3d23828f3faff9d94f3092c13d640e33b4ff8e7cce8e22f86ef223c3d20685137817bb092f3e9253b3fbab2431a20c33d7999bef831c3a149bf9378113389e162d3a8229fe5194e8c5f72aec836309cbe02c4bf37b6804d6f261b6d0d982a7fc3b6652b6834ff24e01925dab1a100474ef064fc1efbedc116ba9164398db2b55f59289575a9a30184895c0caa13c09b271afa9455ba5ad23295ce604c2623600266922eb11d82b0a3fc7ff5700ce08fa19ce5e0869a99279011ff7e58dd46f0728d2c481d4e25d7298b2a57755d40b9800794d6eadc7cd744fb28d72c6fc830e84b71e5552af17b083120c6d688c037be9909484db11efb31fe69490e694c903f1bf93671c8b92995347ce56d5a70400779af62ded79b10fadfd9ac1764a8077d7c8949c477847701459f10baeab0da8367608f69e61e6c14ae2ab3280042697e03717e6b734d70280bbc9e60dd309b4167d9e058328db60916d48bc61c35511f642fc84bce5c485dfcbe6b130f60beca65c2b424da75a24a4d3866368561520f8c315f67a14d38a47b60147de8a0000957e317d015fbee9c1721829939c95b1387b72023e209bf4ad3dc55d7cd202fc77ed7f91c81d1b55e74c6d56f5584b68161cfc978f406898e5ad417eafad0813aa416e5b34cc21838ddcebfb8d276bd77fb0d6a6abacdc774c676be02510001aa2ff2387d1b6abd1baa58c6a14668797a57d5487381dcc4abba1cfe90574000ae7ef1a808cdd6efa461b36b54c30881bd975f619772d5fc9d0b3c503637209ffe76828bb602a12106f1d39944b45b8fb516ba7ffd6769c5a56900a4e9f130f5a64a5173f468db7f56fc52d189616825dc996e3b4b2ccc097b3b858c1251106e0dc8d665150ce694a3277abf1183d62a7a0730e16286e0476bfcb32e287e60b61ddf6724578e6f6ed5b221c565fae8df2efc90bf5b90ebdbc1a3fadc6f0540f9f01b0865da5c8b83bce5e7d2b1c1c3361cebc685d97445af9eb36596867a0084b483c0011f0f414443909d368fa8e1d3578a88e69b07dab67c7f2ccc9eb0e0df783767bdb2ba1cf25d60c2bc544d40fa98389e22fa65879321dd289405ffe07237bbb2b33aab42aca679795161727fe472232597323df6ec7e7d424ea4df604a596fc8fa2ec797d79e6d59f84095be5c94187717dd7ec6ab419cac59415ee0ce437583baa28679f2eee32d4f6b492f7645c9586bcd19c2745e32e7dc7320b0337512313842faaba7e55fdd51b419c2ae5c805d8288e66852ab2c331fff8af0c48dddb147aadf4943e045e0448b5d2bab786a85a11c710c51828d6ed5ee9b504a53a08e5f472dccb019ab8875e76e73572efa1d6c88c849a8b975750a334b301c7d6414ae413ff6dea7778142dd808998cf3ae2495668a74326dae1136052a0101f1da16df5fd0bbd321d7f5f693801757d6f12a20c251791d6391e3e833a5099960b5329c02e88c48608a68af41d360ea63c73c95ebe52fe624ad1cfd3a1d0216a1de5fe4fd39d0b9521fbbfd78eed2d3703f9cee0208f78250880c9b0346090992b95bc551edd606545654e3f4859b7b1a1e023c4fd7f86d251c282504870e56b3ae705d3b3537d4b1cd114c215ceb56731451aba5db7fd8edc0a2f9caf50f17af24fcc8cb6af0f0c06559efae18fd8e38fd51ae7a6b03db906783a9e8c10e1da5d4e0e37d3548c9bd14134761a8688dcdedd7d9ca6cd03e9ce2ede7d0ef0865f6d77b4e472ace4126cce423f878a2581bc6d799433f67e7ae39862f59a103d0c5fc5a9a86ca2cca982dd0212bda765a48a0a4551252ea2630388b235ca30498b517fa80fee0f458d9b1640b6441fc6078100d268b7e473054834c52f3040591b845f08f5473419c1d234a4a83c57aeb9db06e65ed3b5a42dad007bbda600146a923187dd64de324a1cfe85df417742db730ab15f6ce4d48c28b59872e8b0ceb4e906ca27dc1badf99679376535e315499d9abe3f1ae766ad155ab40d76103efdbb3b375db760f2f114fea19520e9c30edd14ed8ba79af1909838af3300a0afb231f18b59f2a416840b92cc8480657ef2df2226a170bb5f25dd9e4ceae7a0856ffe10f5ef5dc1fd449decf21b5fb558e556197d53827a2ed88c8976e713a024cfc5643398b158365216dbfc9c1f657c4a81d999d63df9dc2259126f4ef3e0503432b9ea78865b14b8413c6721ae7290535869ceda71d97a5665459ed9e1806a9968e6361c1164968dd4cf4bcc9ba28c482ea38c8ddbee268d3d9d50163b4013dd5cbc611b7f6879b068672ce19abd9bdd572753bc5b5a61a291ac6f4afb202016d2c80b2bf39952739796afe4fa699b762c85587d11f18163dd3f0f308870514f4306968e96aaa4212bbd29ff39ae075f02b2a0ade1031b30bdaec186e9401b615ef26c4badce802cc714ad5b808913e41ecfb72163702b97bb18a14a93101bc9dae3936df14e170670545e460acbe1e51ec756fd5542bcf1ecd9e50088a085f1923bee4dd73d1a82a3abb492d4ab7287b9f33c548cb0be80e6382a4782f083e9a5be2709986a52a4212e235438bc28ba4e8d74d5e3cb0ac122869a42f460e3bffb1f0022f7e8c8947b2fd677d3c148876bc11bc0d1ff48ab02744736f50020df4e2b738984dab9ece08d4cb6b2244466a8005cd381f766f888d6edd123204a4bbf94a5a92add61655834a959e9516afeb5ba4f949464713c9bb721c64ee06c607705803724ec1aaf927352d90145dad07f1dade956c0d4f934a0df14b0005c5e46891291084d940792cb48fa2f0b985308a941e9e83375a1fa8330157530652a878cdb1a0747f1517321424181a5243c0786474c331b85a2c599b1a1c250698223770a4a461af7897491005c71be734d55572bd22fd8fb4fc4e2fc3f6c7024144b0a950d58e2b0452333a903b694c24e5a668e0627f24435f66c3aceb2d03fa326f7d5f96939c333003c14b2e1b076162cf9d1beb1136a0245bd225ca910f0627d8392c1b13a2d8ca1bdae05ae4c4668965133b15c88f9b1bf76897d5900290996237522e41abc39bd1c71dd8aa8377989d5ac6215f23a274b7c1bedee40cea49f60cd0fcec773b3dd99827f3460b12f759e592b817a4211bb6cd3282bb0c47388cfee71250a08ac6191c7ca93e67220a25cc7b787f8e48093e3dedcf030eaae63a1e03cace1f807e7b6a3bc4cb4d102ae93eb8309e5e4aeeb08a18af730a045a4b83a00a258300f506a99963773439c9c0bff4bdedfcb4718298645455072ce38c10cd912f31e78d6d0508ac19bc5daf3c00273dce16293b5bffcd2b8c0c936a4941d7f411a0420039da80c8d0677730d4e2d4b8435ed7fbfe4ec042be08d70ebf121fcd9581437ad540c0483fe1b7d012a9d76e9e0f7b202ee521027d07181d57b7ddb57cb608c41653b3c79b2359d4c7783bc2f8624e72691a26d35f0df01c422a9c744e8267110efacf09ed678fbb539743ad19251a82eae5a2cd840e15652a22e6d60f9636df5c168c34841c5aa475f8e2007fcee564b5a445387c07303fd415b2ea74aab647febcf5c73c974c6f321e52df8bb827357beb42e60e0f43dd97c23b8e73a45f9f3046b08290008066d4bfe5e8c770ba4af256fcd0f003288074bd65529500ad54ddfb45a6e2ec5cfaffd7716f9ba14550602f3de7d801dae6f1a480f7836b51381be68a178f41997a8bd98cc54afda137c96003bc320c0bd4df74e3929b66a2a3603737a6274e1b03dbf7abe7a814a0c1a91ac6933701328b142ae5247f5b91d5f1d6d5e676bbb0b9a790da87a4571b2d7f69074ff60c57665303e316dbfa008c8e9e7686fc2c4b7e76813def0a2d007e7a4c0bd2e104a2edf7b87ce28011b78debc7a7770f0f493674f93dbe8b6cdde89aff353e07095a6a14090f9c4215bfe23b3867843b6370319c9beb1b67af02fe44f3806e500b1c2dcbc93a3e741c8414e073b2290fa3bc21aa90ea80357d73a8ea5bff5be5012ea41b72dd7572afa81d7b09845b9d5318f7c4197359f0c4f40925b5fdab8e076b81407b1006d0de544fc16908fe6b59ea2e11c621bcee70d9f9cfaf21e44800e2d57e48c6daccdb6001bd23693e36bab674cca1eaa27e3abd617ce2cca9040de7a7fc5fd0549484847b142bd217ec43959e092d950bd4956582886d84689f0c8d8b75a4abec6ec3f6beb0d82084d018c33a57704107457961a2bf8f079ea209f90f391cb50dae3c2f1611263576448d70449fe30645af946c86851ddbdf18019727f506a36b00ed5e35abff78ffeb2d106a8da732d64917614ac4d5556cb6025b971b11a5308eb18bd74aabb8270b7ed94d68858020ea416c2075997475830a3ecaa554b812c104f67472a94b02ce9b5c766a90f40ff0d35950e862ee3cf50cb1556e62bc04f564a13045255c7a80fbbcbf8c8ebdf82af3fb8233ec80c4c705539d5e6ae645766c50e0905266b734484e032c529e1747242d5b76bf03ca9209cfd5d35ebd5a4b311a6d3bb7e7afcf340c18afb53145556a8cf78933360d380963aaa2a945c47a134d5183d31bcaa204c83af7458b9a357e0adf1f2f63a9010c7903f3a4fc2189b3374a7c27a9d95c5405fb787af01864db6986713a25ea770db16de51d9bdc11eff18ff26f871fd4e9920c57eb7ab537f56898a368e615b603d13b5cb665164fc6696b5667a2ebf828b37993fc9d3865f4ac7cdf8d97e52507afe89e453cdc359402aed1f7f4b45000def9c1167ab4723288849645af72fd0a146ae27c0699864e20224c6f5e9914425d2599032aff78ed9f27c240ef218304d9992cab0170546dc6b6b0ab40aa5ee824e14169a5bde5a42dad7107a3d08e0f8c2048d9581cd470d10049f3769683634f9e6b387070b54f2985e3a87fbe920f9f89de81ae8b54a62021089c9e2518bbbfce05be6214d3cfeb59b74b8acea001814b7d09d8b0cf8bf103ce787daf009ac204582622b7959384d7973d6da30f028d64255fe55e2563943421848e7db99beddc76ac1415089c639e21f56f7d8707cf9dc0187da082d52347469bf04fd685b69960f2736d6198a710c8ac92c3fb07f73dd4aeb85751f6a4c52d8498de49087d717a994e2005b34e9360f1471e700b523258b3667f2a9b43caf46eca4e48d78ad8e46750b175fb4e034581c7937c0159f135606df3e174563b8c4e7d6c90fb6025308d68651363e0adb803c42f0e03aef76901f55ec1512cbfc47dee2c871339bd6136eb99d95d7198bd790b3cd9036e8a7bf90586fa8cf36180f9badbae530cb946375ea286472093964dc539c007c05345a441903a7c55c92b92d932afee86e8b7d6f923a7cff3559dc2da358c0fbe2dfaedfa165adfc03598f176fd1e420c281001727eef40452725b7888cdc00b8abc3791ad17c7f29ad6f1e360d87ea0ab2349f33f049e26b7154a5eaeaef017c06ee0f4fc43d0bf8fcaea7628b42a44d95b2c0ae979c37cc57733c45ef1b0ba9dadc8c65a1061b423ed1e53d5828d6e63125105723cc2388bdb794d590da07a50778792bb4005601deebe971214179db3df008fe5d97a49b6365d916950406e02159a59b1104f72a08cece141b7df1391a81e5e62e92102ec74c93083f7c02bb126758ce4b5072468a8c9e78633252a49f94b9ef0045696ecdc31cc9306c036317b48dda42e4445f307ff910d29bfebc640800c6709ca062645489fbfdad046d4c364ec980070944cd1eafbd222c8357e2256f4606718377b72fc42e80df07f6314dc9a9fbdf81956e69969e4c4a8155bc1618f21f5745b6e95dc232462806028b302d7dbb6163fa3788c14ae1b69ab43853f463364a93360cbe7b8422410c861f4d13a3c445665d33a87da86405287fbf82a45e26e5c10b5550469e9f3507cc1d15fc4f5276f22e03ad4155e8ba56f56bf802e3927efe024a0258227232049cf306e84ed23c7419ba12fa48d05fc4cd7d0f9fc5e0e5919dde94aea775aa0d5a698236d3f3653499ddf3e6e32246e7e4a0d4bdebe50dd99ac8cc47d6e3910c5b724397812b387b0151d9c7fe1db04555b7bccbb6cea9fa037d70673105b500b65f726d2b3928dab55afbc5870e25cd176aadbbc845e1883ec1d8b14dd780080a5756b7a820455393cdbf75aa6da11648dff063dc1182915db97f0cda33cb00ec955b8109ff41e7e2fd519859f72ee2199d73d831a66f4d0919c637c630d30e0a8e967514c71d2736fc49418283d979f969c39a503c84b607f737ac1aba8e0b48aafb11ad41e963a0c7f45211bc524503ed2017b97b553448d69f343ad248050ca9669c8be7ca1615c1d4836d8e2a4d424cc2c2be302b236c8a46d8bd30960949fe54726ad3c3871624cd94ede0b6aa69804ba9f55544171db4de0d007319019abccc7dbf158a8e628708bc25b80ffdeb4fa1932436f50ae7cdde5bdcfda602db79108872caf07874914b459b246417f8aac5d7a563351731d29c21c4d6d30605008961747a04d20db8fd7c6189811d672a8a948ba843e6db59d439c0809e0e69e4cb7ea493121893fcbc58ea3afa7e9d4909e6a364f536d1fa1255f0f5580636dcdad4d6ba5e15f2dfaaad2f8f05345a02ac39d715a5c22cc5817ff9a72a0d0bcadc40c6ef13ce30bddd72f146e5ddf77e8f6d3b5ef001d9f87bdd160fca0618ae77ec6cca2f7ff437cc78934157f495184a7952a69d0581749dbb4a4f82045f2f1f55776cda7fd275ac14d1e62abfa868038106ca8151173df33f33ee9c014792395c1d3fce9a58a6da428f660fe6758999fdd52475bfd5e1dff9b387200b753006c904c3de0bba37650a66004660f51444cf0ff8addf1987abf051d4df0eb3cf2c718f12decb2d3eccd95a53e087ae0b85e47f1da52966f9e0f34a7812028b0a7ca592c7df6ba343f2321c2217fdaa7a659a9bc6a701123176be3f2177086025e5bc3111ff6fc3141c9355b1cb1cc8be1df7afe29256203a98385110aa0cf5610c1a996c4db92024a57a63707b81574e40f31f4a7bf92b3954f217f69c0dd997ce5d1e55600501058b578566330d00301001ae2b74aafde3a6798c40110438d5c2a30d41d6a1e2206bfbc3610990e92aa9e986bead84d686f9a9e475720b2fbf9cd04f95fa2af4331419aad79afe7407f653619a85e3619e624aa6565404876651dde1474db090ecc6e7977d8bb622c286c9dcaaef4c240c0fae20f34904e4da7cc4015e260406c87f9745a2cb6eee401630d8287954a1c91d0843a1f702ee57a0900a7f948bb21396f406e350496f5afe83d9abcf8eb2483d0af453c30a5226324449b92f753aef636ec185edfd3264f7d2e0bf08d31caad1dc418de50579661eccaca9d2d300a1752ea1b3001e2be58a6aaad0249334629882ac5d390db863a3863a6045e98426924dde4ca7eb9aacf94af1808c4cef5152372cb0590585a3b668edd6dde937426552c854899115ba031f3e411cc3147e4b4593a5bc0ef9d0d24e4d20916927c6a0e494934fcbbafa48ee568dd31f920f48b45deca200a08c9ba8f441c2056c25e8ecf0019e39a8a0580ffcc21f3f73e5bf10d620150c54d0b9adbaa036096e2df0431d983a8c059f2920195ee805b85a4e8d24885c053b0c16025bfc6ca3d0ca125530b1d945a3b03bf149d2cf3fbb625ebd29795d0e098bb366a8dec65ace29acf8aadcb959e02b77796cf0db16877adf112383ca0964420dbb01ac01aadce2502e597e147c5373eb38191f76cb547182ea56bc870451409b30f88225e808ad47a6bf20dd902ba982ee34d87103387638d11e3e0b0a9c5f61b28897074c4f551b3e1dc62f30b020b39b6805c270ea68ed9cc4127b0eefb2fe1cbfaa9ad1086bcf8abd803a02059c02481fbb8bedc26bac402449d9080b5e7cd3a15789e2c5149cae4cbe88d3e0608697c22fd0428073bb2bd015250dac9aa8f6d149ba336e027d1b8a4d6819c70b3b2a04e38731d95f583fe4cd360bca59351eaa03712316ee6645a0bcee7ceebef343758744eb14c51499600ca600a6edc358e4a6b166fe2daedcf8988d4666083da05522287d98f555dbd0945d05ddd34e4dbbf0014d122a14892b0c9bc0f35d79e2770bc0ccc6203b60b11a32029e42a4fd5fa07efea52d7b50aae093d08fe2bfecb9fae99ab33c8ea08f9097016253e5d9f991a21b01ae845133556d1cfb3585d0855979d40c3e7de4c97d5e09e20cd0481706d2307b7626c5a593008198f758efeac817c985495ad96eb0ba05ba6a8a1a1a9e8dede26043d6c3f549d0f6164c11f8953030f24621eabad6880a96a6fc846a2a662fb0eaf75d89609d7b5362ca39f7898f07dbba0ccdb82b7109349e150a88afc4131efcd2a4153af304dad2dda0937197194b2ee7544af2e4070d91f697c71e237d0966b7785570c1e548ab63d374cb26743d4d540e299abc0250fbadfeb4982ce690d2283e56481d809f6f0413b79f5b0a6f98bd6c7b237e0da579e1ae7fb621ffcb814a3fc1f99689b78a8f992f47bde4d355944a47e5760f9c17ab5596f5a2a51082b08c5ddec7d55256ad5071379654e937f141fe5f810177628c21daa2af136e195d0ad690faadb41debd67ab93eb1e514293fc94bc407a234183739693564be9b873f7a7f788969c1da1883336569a00fea857dd9810e7604f45c6cb96865ad1503dd4b512d703bf16f652bbc0a653bdd62b4b1187300294c876f11c30210d95ce56d61f362aeced7ecefd73a9ffa2ed6396e8d98030917aaffc8b00c94135dd010a80fe8e8f8164c86fa28b18bd9caa5e5fb608e7d08749c8def35aefd86a151db658ad13008dd7eef3ed3d78260aa090a680a7d000220a5b95fc0af46442d1071a87be783d477cc43dd93f80d0a8e577e0c51a4180c5f633b3ecf5124a5ba1ee16f98eae99544a37e17e3397617ee364b54ea7faa0a0e21be35940d43ba8cff07abc1eb338b9dd1804259686c9fc344310b93956a07b67c6f9c393d99884b6bd0578e394637f8f4bd330f67826d57e095869ab0ca035235b55d90b1f0811c2c941f03ccfa51f3d0546e1c3ccd955d4ed8521a40cd0e97e331f03ca75fa8019486cf625cc2c8c5751b896ffffa4b932b5a8ae619c805add99024dda69d3d8839c7347e899f2a70658ecc9ac06c8fff77a7a4355fb005edbd0802061ccbfbaba8490565952350eabcd9573fba632b0f6edda7430f920c972d48ce4ffbef02840029d55ed21dcab4a0c090a438cd30ca1405d7b878060ce36b2fe99c9544d27e2cce11e9e3d55470cad45df05840f29861f189869b2c0c0a665ba6807d5b10028d49ed0ddd2c7ac0d411375164217251f9f2853d46740121fdf5642e94d76a7b46515293e98b9ccf1f6f79c4b1e338b616d1ed8d72890e9adfb4bc23678e19917268a07b698ed65946946458ad598ba604000978e0dd05872599ed4a8f8ad2d0a190eec904161d21b69095f9070f12cfcac3755441a906d247128a6f3246f7f72b119e8abf9ea022c946181dd86f04dfc85e871299fe083d31c7866ab001f247a6a56b1fd5341dde2dd660c463fba4a72dd3b06f99d2096918904767a9d31d0296d8d043d87b0ee73a3c5be6dc2abf871adafb6393230ecddd27402000636724d249809ed419f4e7dbbea5c4d2cca76150b016309c2b0734f866b46fe186b18e0616facb1e4db47cb070366839fcae651a172145e3790ae96113f75419fbe836769161e9eb59e768f6b449fe84a68742d88ef103fb690cf37fc41843cdf1c3aae75bb779742d178c426eb1c41b0b89fd35b01621e8f003f5b71fb9d881c5bae0e414f4b869052d53af1e1188cb6b3fd40cdf5c953181061e4f3299f4ce6aa95bef8bc523af17c64e16504bedd089d736ab771f7e7cbe0c1b9eebff64bf0337010609833cef60ddee4abc46d34d4f2a2d76086006f509029e7a04822798a49af80dfc53fe3cb120ab5e7db0384ade1178e04a8100631a0cf4252d454735765dd6ed2909af333f4f51bba560aa7fe3a078c8c6aa8c2900024cbcdc41fb28934b1134364df1d8f5b49cc964db7bf6d2cdcb61514f8b540a0bceb7f71fde4b917b7fb625df5eca84d9418b7639b3a6505d98bb3b047b2aeb06bd6ea0f6cc677a48c79d4626658e5a4c9f2caf520b60b2d99788b79bf6886808c7bf34bc98ceb9915857a7d8870b15bb6f2ca47ba60d40c63ec12e7816bd7d0d9af43c6e3850bc454fd3c9cb492086466fa603f39f877cc28ad41686bdfa4c0165948e78b6cfe916913c45cb1908b918b15a9ad22d811da44084fe94a2284d0fa53cc2267b53e5d3329ef53d4531d60e51688a45e1556cc38d6dd787305d180779323e6d837cec5fb2c3dd20089c2537a95523bd12bc1d46e4a985f64fd19b0aa7ee84e9e2a0cfd4438b4949e44e637e432e3fda35b6d3610948adb37ed84d0deb4012fd79bf4b34c0d3b5eecd20a3a9beefedb224afa0ea1d61f5fe288f8f0540f4515f2fd4731ce06be5a1e3fe319b97bdce5c9162a4269efaa55f40be760eb711b1f0770f7a8f3851f5eed2403193c57859ef3a9c0dde5c7ccfcea87607079bafeacc171cd555b4683cac10174e7691b6050447811315245ffbdec8b10707a61551307b1731e08501c4c77d8705f69a0fb5f51d44bea7a1757ab49f04ce0ce5934ce66033bb3ee52ed145c02852f0c817579ce9bbfd0dde35dfdeed34720c73713c4d18a4620608747f8ba3d7350e5e607ca0d53efebd3521373a49cc02063164c9bca26f0837f32c1aa1fc5c60bb118d1e760bfc7cad26aa58a106a30e0ef26a4376f7c81394c686869e80dec659aeb631521e643f8a561fea7b2274750982c647d92cbd9ff751b37249af2d628290ede9b6c9bcddb4ee2b64d977d2680e765ebd18e7aa240fa0e7033a84c644ef686ec0c92bd4b5aee22cdc307b2b2608ce0a6937eb4caa3624251e940bff10e433e85dc72752f4fbc020ac9ca0ae160ed6e345bd91b7f27fbd398d1a271b2a910025ef90186d48e134ffca401f6a6a0beb675c4c8f54d2b1008c103147f1a034486a05e7150ed3fda45987430573fc0ba4bac3352a84342f17d1da8eaa5b81014fac3e5cd165e4659beb9ab6c2b4910b3d906e77f7a8b34c20de1348bc9cfbf1ab4c6f824f3fe4dada7169cff734600733abd9bbf0137aef6901d11163ef1a0e130f918fac0c90e8e1c280031c070f0bb38d38fe55b844581e6677d313fc84f0bec9feb764b9f3dd3f6e63b8ceb84f0e2f8501f8bec43dac4416bf2af1246b4acbd734abbc7404905feb8bb936420d01c24f0058a5019696d548db36ca2a8e8c30d66a6887f37972f90305aaddbe5d06ea9bad064434673aa92466a2bc13b729f1a5acfe1e33bea1552b283b2eadae095aed91a34452ffd064e1033868b7869829061046022bc7ee97882c1233536105f25125c17a81fcb43bb1d3ef920cc4abcac82328f6f01c8fa1fa763e2d1349074a244833a3b184f08fc04d8d4bda3d5c157bcac3f1f6138b5cb8eb989a9f3c029f2cb8c010fbe3743cb906c5ff6bf93a881914c930b06f0322f1f98bd94c08050fe98befb6c4776b52f7a58a114181e511108fbc262c1af6d6a922d82e4f9505e59fb9b74428c3e06570930482f82b2e2fbf1ea57e149d828f251ed2c470110f89a0593b75e411f597b5d8cf22a24f207dc4147e2cfbbc520e75bfaa6f1b0d0d68eda97cfdd52858f3859c7bab7069776194d714bf7de7416d50749754de3f087703207495a373c29f096a00ae5bd03daf4510392578bd580d77b355d0a9b40cc9a2a25c03770192bb645d4cc61499b58f46b8c0ed3eef8e855a2fc7deefaf091af3501da6dac9a885a481e4a4e03fb7a1dc3f6cb919d01f564e7a6270d88300af4baa2a140231fdcab55106e91db93933164d60d76e67f5b100a4404dda420e56f5bbd0d49c92ca07515e74edd629030f8d2bd2ee0a2deba9146dc5a7dac409d089823c8685ce1bdd7672ddaad2330541e7c69c224b4bc560f50c2e6fc0c70a8ebe3d2117c03e88a9edb8b4e322c1684c0890797e8b0cc8feab549f1b9b3e0bb83c49bc82addb1a69f533e69c40e3ad71cbefb61fcc4e49ec1c0cac07a943052c640b76fdb3d2bd7e921e932bf28432beb3763614530a9d641122150a19270e6ccf518acb0175eef69879627637d8a762ccb87404d391d4dd217eaab0189f079ff8a990ce72431af49d4d5badd7462b78a606fca18f52a23a56d5ecc7c7c80999bbd1564c9b43b04efc80a665141ae0824d3e3e071153bb7af1e7bfc2b8b30996b9aede9c29d8f2f1c7694c9c465f62a441051f581fd0e8b9dd2efba7543e0920958cfa74b569da0fd27e9837637589d66e272f4ec4b8c251998dc10f8c90094e817a1a4f64047bd4e89abdc3856a30bca6465a0107ebebe62156803c6751040f4da71043cefb5d0e2f8c72f8f9dcfa7fd25f7338a8806edd293fbcf25b630d1a3297eb00c3bfde2a32a45f3c8ec85c83799d8651d5673a5990564e6b46590c90283944d53fac2c44e4f5d8355b1d3a09bd39b4e9c648a97afab387dca29d0a31aaef5a786c2890ad36af71099c8531f57cbbc75e15c505b262d05216b77903fcacd0689630d18a4422bde8c9d929a0efbfa2478c6e7ea6d825c12fcd815c09f6527c09a43545b6eca924d94369d33df092f97760ba1ecfbe962a5f224c1a03be6324db6faea93ac57b2c7de581f74f8b729ff4a6e1d8de33ef0f24471e6408b3ce4b12361cfbaebb894a6687be08a04544b9037690c6648c9d29d58030e102d40df79ae96091c3370832a4ba2ee7166c65c5f74731cb4fa53f795c6c6ba10e -generate_ring_signature bdd604377d0adea441787f06cbd71142cf15d55ee20ec1bea85f573661c71201 2487ddcc1b463edd2a754b037e4ebce25e5fef7d87a227d6eafa588404345543 35 b089255060a9bfb64276f30e0f156291d61ed74376751cef0c3c519bf97005cb 71344fa8a1d99b228c90f79d26b10a0936b43185ae7e456376f6bb527bff449e 2798b734c642a9ec401cf1a33c14c239c2a59c5f48eab81450f06b8824589ae3 3aed394a9a3077b2b7b6254d4ff647bb96b7438be120fac9204096b5f169673f fc7b91dad8e497665fad7726ccff5cbb5c611400743fa25dc395bc95f09c7704 d4a4dcb19764fe5a25a5963903ff0c0b9134c4b8be2cf7f33e7bbf42b59618d1 38b63cbc455b1340fbaf53d4284ed6a0db201b4e4aacfcdafeb6273b1a307e3f 0b8d7c46fc803560f12ef832de6079adcbc1ef9f787b45de01a737ff5e95836d c50649bf69d8dcaf869c7e42948ab1784cfdf39af5a7e4f710726f439b25fe51 cb559abd56c267e40422864b8e58cd27ee9f9076f08da0fdca1939d20e6500e0 83c0c2a194cb48bd356a96e50ba828121c00be8e57a8ffe7460fcdbd543ec13f 1cf20a067afc5e04c12b6ec9ed5dcd70d647fb13e390b35b24503db9590faa9e 77ccbfb6fdc8e4fdc4b9f1d5b642a0be86ecb52d0760e9d37949c2a08be3b17f 95061c0154e8feeefdc01a2d1fed47012266721d0fc3b81f1e39ecce4f8b2850 2009e95362d812eb87acd566bc521ad12249dc3b1919d8af30ae0aabb389b6ea 7a8431ca2ce7199d1db1a3c786fc9405dde6d0628952cf95174f0d35267a41fb 8fe2a2d24ca5a08caca966a0a5175b9807f3030631c5b93b7ac35eccf25724e6 67a3edbba5207baf306674a7c24b2093a4bc41c3d43bbfbd545175c8c6028bab eaa0962f91596cee665815b64415daf81bfca68eb9cf5eaedb9ac0a0c4ed0900 2f87c482a8ebfa50f9776869b0899613d31302f61bb9a8066182782b738db442 1fb8bfaed14ae9aa8f13807f7a07d705d47cd642349fb1787734233b7c85a3ed 35be0bfdf4b725f01e4f05af0bb9f02ff0dd4f612ded87a2340a1574b3aae315 4a0fda512f352146f7859748681ba33d2760bcc72a20db5922691856f7e603ca 33f200d19c8fad76478d2eec8699beee2061ea1f31a6f28e764cb7025691266f c968d9bc39daba4299986612b3467ac3d45ef0b830dd62b497e52219b175fccb 22460e30d871caf28c49e4cb59cf296682dc386f5eec6279ffcc150faca7cfde 1f92d5efa075ca1f939b27e1b0aad182cbca7f20d2da676ba1992d5696dd17d8 73cf74bf162bae040c2523789a0bb3a96cdf781f1a766754a2e2ee1bb200791a e669e339a639b731135147dabc872053f458a767ca38c35d3e9a3049f7e8908e f8183272074d1f826677ac9d576cb3f558fec821f5e32cb337107ad6cc85e63b caf86118b2e212f253e171c428e935c8eb6cf6ad085f25af4a0a93f9ec59ace5 9dd75314c1d8ba4bc81914778dd77308015880272b65bc37c402b1cb832a69d0 bf83ed74a2f7948e17828735a98afdb798a3f8793d1df6d4d1d8069ae7403dc2 b553310ecd79a8254d329a3d6e2002c89a501c06b6ae3b7feb152293dd26397e 7d483ab7dcec571e016a577f74301a6614a34734be679ecbc324170dddf06aa6 57993693eb82f28e7ec9a7bb128da07bd30e23fe4522dbc460d96cbc87482706 9 eb06eef8d06cc359802f960c4475585f95a05a1ae87a181d896c034d996a450732640f58830f6b2c4ad3ce132b4ab0b6c8737546eb45a08585bebd3ef20c0d01da3a2798cdf9d1a734394f3900953f43a1c62eaa2d26949e2f9651774f61a8094ffa30a399ef4204687a3464f8e64ea56aea2f06e17e2ce9d24403c8f1c23b0a6cf0fcd37c5836d9d37a50eeee6058790f745d7333e0196a6f12788deed3f5078fb201ff59faf7a567f09a9f03548b5725982268c6398ed0c67580fe7df5ce034f7de93e3bbd7001dc6298ff56b885b21a1ac6cfd4fd3f750775bdad9f913d085e004843bef5d9bd0ac9d62cbc77265f7cf053ff15e81ed0d481edb801103a0762e12f0e6867cdfff1a3f03e8f99dae3db4fbc5b90ed791d109bcb296876dc0f1344309c66fa2fc37c2d5aec0e831c44cc4acf3937fcafbf0266103f007dbf0c2de154e44e94d8cfc797b53e05dc2d3d61115dd154ab15610d74c3424fc78202008398463eaa06bf687780829df04b59120def1b22a915d0790e664f5d8531030243b54f4824c77418aedb58eacca8b850d5006a8943193349c3d74811c6570dc7a3b596d308d44fd2e3e64f804160fc2f797c5c15ff4fe1083a4861cdc50e0f07b331b4f32e15a5aabc617c74eea170c6214b2786876d670a5e989e4c006f027c8bf25459e7cd40d2f9834a2eec52c3dae4b933fe39703e8b69ab46c871a2029b96c2e758cda159248b93543dd85e3efa10a003f5bed993532f43dc0179cb041e5ef9cb37a0a5f10dcdc255523228cde8d3d3636d93f906e302db718c415e076856b278838e7f08e6f624a0d5ff180948638a44eb4e587bb9ce5dc2c68d2d06954815a2caef8445fee06bb3e502959eeb61d36fcd7c0224abe0ef51d9b9b809a4c9db1137fe5cc1b444e04d3a82a3f1d5b7fade44c00dde807f54b2c1298b0b0da9dc829b9c7798e10688bc8554c1bc148c67f53d10eb956d9e9f7ef1fea50ed0e6c3831d3edabb06228742c3ad6d314926f2eb73a5efc9cb396b98a2b3bb03e848bd4e98e46920b99512ddaf48d6476d59d199180f389c57a08eaad39bb009568daa0b4a6a7998f0ff6675f207309db1d30a565bf50c03b4063c3ae0319601faeb5b69d5b7cb0f5cb7cd7b7de440538651286be6825d087270759649b2e50260c794e1f45bf0837934fb0c565e51d659af70a8133c0e9cc734e856758bbd0b3cffd96234a40c5fa95595d5f421c947db1054066909e409a24c13ffecbfb50e70337af56c5282ee673c0dea3af3599667482563d53f174a32a2528ea4c90c0b04c6d9d06aa373e0efc6d4eade376aa52da5119410b62505da31be7e37954805ca39989ecaae27e8f36fcadd566acdfb8fb28e0bf8b728a8b16bb7c0fd5186079b6c7ea2d57dd12cf0e7d2377ca1bd3188a96f163b05e1a4c7f2a9a648f5f204e733187860ac9ff9ba9f5a41fc8599f090a11f34ddeb90d3ce9bf69dcda4600de7fa9c30c0d623f858d4c009c9454929cd853c62ee265186513c3524457b1b035b3a6d1ca267be5a651b7024306c525c27d298985280d8137af5cc583d59e50980846774b9977597328e2e565d65a206be18ed5b4fabcd32f830986ea5b806079969bc84d4ae99a7a5821ac2f0fa11f045de8295765ba588cb38eecd98b35e046b51a9c9a7865574cbe1911d04ddccf73c410265f21efb25883bf2ff99860e0805f26a7c36026ed5fbdfa85faed307b08e05c85bd1db3811b4838ed24882ea001a647b6c993b623181b2cd84414433932091252ffac639edafe643e05ffd2a0f2fb4632a5dc478e705b1b0d6248067e9face7cee3eae57c0952ae5d895fc19048d989393e3fd9c83440127e5fac6bed1e629289fa4f290f1abc711dc9f74e203508cb5427d5f283618ef311364245897092a8369be7550d4064ed8bd283d630690f25e786f726a96bfee1a7d062c7086a5ff2d38e01a863c44c8a2b3d88bca019c3e5c6e8399f5f58eac9890ff36dc343cfd89d59aa0e0bed2faa718a988bb040e5bb8c301f30b9b26ce46974ce6c6fdb0679eed96abf6c46d60fddb4cd37807376c5ec9e6d541d11d3d91eb341ac86256fac22f59ec73ac87306b5d6b1f9c0c0b44f4a886f0c929d79186e9c38ef0350bf15987a98584521b17fc7d89f0770c97e42dbca4eac4c90596fea1b1201a1053611d088f3a2e524d53705365911e016cc3303b6aee6ade52cc6f88f54a8d103945a2e17250cf49d252c34a7c00a9003842fbfe5a664d518aabf0c8147c870d8fc0b70b4ab432cf968398d52494be022fb016dace2e2520fb832491e793a19ba8c7da4b4bfed3c1f19f86e2dba44b01d2586e6e1d60d869dd40c2b08ad1b743ea73a6701fe5b1fc375393e7a3788c072f9c5bf84fbfdca94340a9731223e44e03c7936d7e71314a6ecb00599d3c4e0ee15c6a4efe7f11f08220da2d758b4d444db3892674632a28934c29952a143505e8d6ac31ea886d59e6cbbc16ed12c4240b95b0a381d363bd1c73dbbed79edd069821f31a189d5cfc742e89318eb6134431f3c746f17c4f04a3837647f11bbc00cc92d981b05200c9eb0057484a8550be48d8be660fdd90b827c38a551b6ecc089c2d4ab9a37ebd9fed1c9656880accdcae9db7b4a183c8618a5b7b3f07a6740eb0ac7ed2276bb1980e9957da5813af0fcf3bf453338192050720ded52a56a3034155bb47c3592b977a46062d4ba1e5468d30b7223c8953bf1a3af50ce29d4d08f0654388f8735b2ae0f12cc96a7f71e1acaa12e0f2fa29a99dfb48076e549d0384e55f60d9c18e407b2cb1acf2bc34f06c7fc49fa3f6e79911bf885764a34f01a568e48ea4b09382d815a20a50574c760b99efb97a0a43665b2d81944e878d0699717339a18cf15d5059abbdeac15b86f2534048c0de4f079ab6b0a6bfad0e024f9be3b8b986da1f4b05f85604b38514bf69360f9632cc373ec1128942338d0ef64ff19458af3e94b8eef46ce2559c1250f0b0b12e3561d86106c284fac78d006e91430a08c5112f5067ba27fb996410cf6b3766f2c7408831f3023e96150904f4770b73eac0f83bb16f4b6b77aeaefd0dd2ed2f1511a1bd1233780dcad5490f4e3989a1f646f1555fae4561333e6cd098429523d84ecf3bf20aa27ff41a9800 -generate_ring_signature aca251d46d3b5ba026de943e11da65c82565e3661f1aca050799c330dfad3d41 b26123f9a3df78771873063ddd286b3b07e8c622f56903f2efce7499de4478dc 1 332885ac700a35ecfcfd9d4b87366e052b2b64a9b71cede41d1498ebe448e3e6 e884832fa0894e874fc141dd3685f50e5db4e63743002c9005997948552f4b0b 0 f1e70c597eae68ed7ecfb6dbc2e55ef21405edf3e1008c7039cc130172e0cd0acd8313afbd9f598980f8cfe0a86ce6c7f010a875fcc662293ea968350f7fab05 -generate_ring_signature b775c2fa902004d9f8b68d5e8d02f5a8c1a5368339cd1e9a5509f9cb5bde73d5 7d0c3bbc111cee95905b30f237c3a948d90feaa912301831d3b3d0d765056b96 1 8594f65a950e1a254db53911145528dc04b86702259d209172a832b7886d2d2e 007a01d31abf4ef99af89f0054b67b885b1964b5ecbbcc2f1c9e5dd1157c2a04 0 8e65e615a34134d21f6fc41e56952e9b28f7d6fefd633ecece9c819e00645500b048ce13c1e513cfb87584879d920da56a094bdcce7b1716bd0feef968fef106 -generate_ring_signature 677e5736293b69b1f168f92d1f194d05ced68b431ea47d89d1805e285a75aa96 c7fe04a57b9bc912b8b51cb394ed14d95cf3175482764e5a9e311b79669acd05 3 bd2dd96a9f97843f6f9f67291f4ac742f7dd142e4bc174d83242322ea2ed6578 519650d18da99601cfe0ddff1cb8a6c3c5a3166ed0f4b4d5df08e731f1794af2 cb6f9d2a06625c1ca76b07ed61ec15de053473ddd9b648ce6c912a3d176ed6e3 7fdad023cd867a5981be27fac5ded58a4fad51750510df61abceb2cb6cefbe0a 0 9c841cf647c280baf63bcb627a5fbe62dd601950eb8517602fa1e2f4cb7f060a81157febf210786651b9f7d772a1cea0c3f8619523f780498b20dd4614a9f3011d1831136846d7ed5b5a03dadcf02b22060f2c1a07cb51eb1012dd711edfdd0f02158ac98b5e16ae4655164293bdad41a73e49fa919cb18b3540dabfaeea6006d04f61cc1c6263a3ed18c9be162dddc587604d13246356243ae3cfc11bc7f00fa8370bfce21c305439b37c109e59eca60f93ab9638d47ac0c2d1f72fe1914105 -generate_ring_signature 2c56d0869d611a98a8583af24571d794a9f7d657bc9bb2668f54c91339377b9c fc4553cdaedadf367b81758a5b277e20625549411a88c7325bd8a7129bcc476a 2 e82c7b44deef558ac8ca40818f843d27480d89f5851c2e0ead9e2fe58eebbf9d 66b8b0b3f84eac9fc67ef4d8f5324dc53526d1906f0f830d21bcea089e0c42b7 7e23cc4cdb791d7b4ec1ceb2ef16f65d29edc81cfe5786a62f4abc457c4a600c 1 3d3efbed657c2f625b44d21d3390d2faf56052b71e2431583191725e902eae0a12756cc894a7341dd1ed147d7e57b9ad6daf653d921558bdb14afd0ef601330e759689b79e77bde4d641f1853df9c0fdc7fe827bab030f0687256ee7428829068bf7d985164bb91247e92426479ac788dea2e16755a89b611ed6b3a0745fc40b -generate_ring_signature 8446c895fa03164711b6289f8dca06a575ccd8558fb070d1f07a053b6ac62a88 8f78a27ab3ca15e3a040e4ac2fe32902d418b7317666becf389f520169099aa5 1 05291f379474a1eb448d27e66553fbe9df2a5133b15392f6a966ace067a870fc 7bb9bf9cf9611b1609b19513734454f28f49f896fcf29e689a937abcc07b4803 0 76befc22f46bcde58f10aa79595b3552dae008d60dd5d90058fd59777506cf0948cbaf4528f5680f585a3b0f59f97c8cbb0b49cc593e86eef7e9eef2b0cb5c00 -generate_ring_signature 89919f2cddcd14dbbd6510687053b794e5b8f01565250bc8968b781f24739668 0279f476b72eebe10b6db1264b63b2b074144dcdd4c0c2764cd4d1815acaf713 2 f82d16dd5f4d75904b7b9195713ee68a1595aa8d9de4fed48c72c0529734f52e 04569b72e8939aec2b6db3b83ee34c21326a951c83915e1f318435f609445b41 824dcfe5b0051072ef13f8c9e183c0d1ff5f0dc9a2c6f397bcf1bc3d626a1803 0 c8852dfb86649336b7e56f5e20b7e87f7ca1d6d39348992b52bb108ce183a809f1c5c1e3acf7a49ecc4bc8d655e877d92f9e366a191e1522d5e1ee2d9a5e530aeec566ff54ad190212f115478e7584c4ee7bb51c0165287f484ffd846f335307bb675c3e0bdcb3b0feae1a2b66ce58aea59fedbc7637a0e1cb8ae06314c55d0c -generate_ring_signature 0d45a262ba21084d5b11dc6f7df59cbed5aa38f517ca4a814ff490923916a652 9b86f1081957871b7575cd304b3cbaaa38d3f00703de9cf9e8e184128f864375 197 d0f935d39c2c505fd5a8121bd2d4a741896f55ee2470792d924dc0101a6a0366 460c54ce55f47189b9ef38efcd9c2677e4f3b7705893761ca701d0fcbb17530f 497b4f9949d0021f02b66a82223c4cee3471218d072dd5bdfd3cd75f22e7c0a2 86234ee6f836e7a59fa06e91798301543347f89beb69c47a5610cd6a48b80f81 eb8da56b6a7011e63dabec4649def5c6b1e90ed607e3526ed329dad2d201681a 2d35789d85de0049e0b401689d2cb627e88d8fffa91cc98cb6a0cf41d596c936 c3789543dfba6c37c771f175366171d91d5ee954e9a0626df83d371e1c03600e 19096bc68e91305027ce6f497869c5187fe39a606064f01dc45f696486fa24ac 59731aa199ccc0a87aa746c6e6cbb76295bedcb6269906637ebf0ec791706b0d 608f849ac3d56aa72ea3d80df7d5a784dc4210ef2196ac1fd972e9bc7828b378 e98d5ee1f8de14bccf0abab68e749a9c3288d3d0fe6406d668f912ce03e5830f 3ecbf97e70c7bb254d6afe53e6c15a9e240f26fb732e9c8ad1f13e6f5bdbd766 bb32c560feb78ac2da03f973c620b99dcc06c726b2a570b732c862c95a1a8f79 7475630c541b4b636a91e93ee3610ab5ababc266db827320a8814c3a347b9b8e d0a372bb94a4850540f4796fea6bb38d394a47a935d2dd4a5326d86d501c767c 74c6fec0ee4b8931974d59e8dfdc4ee0e28e3d1418d23428234b48ba8ad5393b b688d964bdd826f6748bf989babd2c55febea15e51bc92d3ae961509c0e336c1 90d569472bc45d3201db602f71869cbf528b2b6b3fe19105278ab39bbe1073b4 d9a36d7afe645436cd02b3e61a86cae1999ab5242d039b4097508861a5e247a8 22c1541a04cbc85028279c5acf1b54b6151b82d09c16513b646a14c6944c3f5c 958bd65d4e627939b83672a58ca806770be18562c061c2a225dad1efe0d95b6a bb3f7a2da142d46d520a1741c9c24d85804ea3da66c691d836cc3b8c5f7421bf b5194a6a410afccb0a4963cb71afe4c177cf90f9a7a3a3d4e9660f1ff064ea93 4f7fd2fe01c9dae2050735a578bbfe329a5f8e6153816ac53dbd34762f87a8a2 6596a10ef0c3eaca356f8873042150216ea7df61d25e36136df4746fa77ec0b4 860402d1f5982aafdee30a7f8830a0f4fa64877255abf4a5e2abde02f43e5c2c b86ef36d3b6873de1efe9e02e2083d3bfbde0ab81aaa37af162f1a6fa0eba0b4 5e7000837abddf0711071b6d205f999327522033d068d3d029187b083b5d88dc e7c7f0e549f921bfc164a4b724f261759c46b147b8bbf0e6e68c39503c198b64 fa55f966b88976d859d6e4776ed2dff074761de70d589a1c89c86279f0005a3b 75900a1d92813d506556b6484ca988d165f54008f1a8b50e0ba8c7b23bdf871c e7bf33d171b351a061ed80d3c52029b6627c7b73167d04f11e339da701cd0d6e 655314b8659808e3993409e198dbfe6555053ed5e0c195d39808ea0f45972b49 89f9d50a6e5f312d92da3763101453a9ecbaf69e84f47c21d855a05bb54a219f a64975ef5c421dad5eda121b3c3e58f818443428a05263053be3da99fbe77df2 5fc852cc8337bd39173274d4f3cf102e0c2fab30ed3d8ad70c753e3c344ed4f0 61298f604f8dd7e109b8600eb9a84001c3d7dca3efae6229dd12adaa4e3d2c6a 07f4d5b629d9c2efe6705f2adb2b9342822e615a9fe6d98897d74fdd89fe2878 5e0f62fd8243023c0b9e7dde96d4ef14e3079f4b0d7e76630c670c76847aad5a 345e572794d11d758bc761d9f22f977c827ed332108e810b21b85cd6378518a0 8afce8fc456c8724baa05516fd9af2ef8ddd29e538aaf1214756f683188a1bef 08897543e204208ef1c1118b4153c450245dcfb2b7746e48e8e389275e816861 d10372082654fb3dec772174e0967ea577c5d93d4ecdef99c70867d84829a10a 4e038f0e07dfc7e752952b19ec3ab3355b2b92e7a39182d3eca79b6a3f87d14d ad67fe5388f5e92e911157fb2b034c1a615a1eeccd3858f255bed067540dc711 c40a5eff26f7221382959ee22dacab3668894870fad1934eb8ad8a7e40ed36c6 ca5f7f63c498e39e135e8c18f0262702de1348dc79f8204c216651a9c7f9ac71 e578f8694a5e92e48f06d5709ccfb681b9c8a738abf20861aa51d61872cd3348 b238cc4ba4613e26d7d41996e6a15b7a1b4314aa7157a984eea7d2bc0706d00f 52a762e09b64943a304ac9c2e110ec56493d00ca752ab2c715ba72f7d69bec89 b5b444ec26de88fc6ff295056545fd65ae83c012a45683b9a22a379efbf186dc b74cde735535b0acd9ac6da6a18c10c4d3e889f1b0ee33aabbfe3e942e9f6321 ae98eaed6da71726406457e4fb6b8fd6577e545ccd7aab51e0c5d51a44265e4c eb366a542d43efe8e33f1f3733dfaacfcd97e215a44ab0cd2aea54a485bc1ee2 710ad4431c43814d664c3a3e0507f59cb8c65c3fd6f6b9382e84bb308ce2dc52 957765427ab11d99da32c054c7c68f888f02f1f2fc10c5883fb866661b3f0e1a a453b57b38dbd7b2af86ba28379d8832e3bd57f3b54897875b458ddff98e7949 a9b5ddbc6bce04caac06aec9761a507f0e09a8bc3f2e7fde93304b5fe5e08673 e8854e7fb42255389b91010d08f90ac2d86da53d338f914fa5edecd400d29a7d 15dd3f808f9f9a4e1f0f68a6157d3541dd24f5e3e51b0eb51543c1ba1dc7aba0 4f187a0886930e1129c97e3373b873c4be9875f745ee91a2e20c2e713a133d8e 64f4cc62ffefdd1b73eba2cd09c5f7ee3f2433faf82129ab79ba6884040fc3ef 735c79657390255c9072a9852bb1d92425811a7703b9809eb3793f4119e00463 5b88ede31e1f160f65b6063921a2bf8b5a28788ec8c3f54089aed3d5aabb983f 7c1252e028be184bdf13a60a46bd476217cceb393d19db69ef94bfe6f3380ac5 d2ca845fc232693381d777903751160a1fb43e818d548f0a0151dbd23815b260 d8ac75db6b5eb39e3f5e23d0b88f82a51552150419ad35e2ce1eeca110df4552 71686dbbe145ed2962b857fe2b732bb0006638ec2c91889f6ff79e1729554bba 2ded0ecdba64251aa08c39c52d0ddc5eed4c85df82f9856cda1e0309315ed47b 765d23651313db76c45f44ae14865aae2c57f8c67beaf102cf299f8f4f5d856a 998456c7aec76489456b3700990c3bf373bc85eb5643a15225819c91c8642b85 340176f1b4bb47be1b0108d75f4f06adc449a28a3ee4b3b7cd58d186cd6c7c19 7d3293cc9c72bbb56250a56c44225e67c63cbaaaf65f2e3671e3a8553889ce75 ac9752288d33835a09b7110f63c38c74a3f24b97fa26471a9d5adef3c4d27373 e152f9eef552515995ef4e9ce1257287e5c7848da1a19697c0ab30f14f7d1d97 08ffc32c3134d2e1ab2f57d3b287a8f6ed83231e756905136b42c1b3aa69928f a5180c65796b1a1ab3bb051ba05483f31e84f49c1eb893392fe987187ef85c63 8e5e0df1415bfe86c31d128a94174622e9323cba4e1adb06805e92e7b0620fcb 8bd78cb19bfc01c452f2ebf461670e00a3c3aff5f7ac6a1a789aa8e697ac324e 4b65071088cac227ca7b21538cfbc0cb09d0be5736b852e44f1b02508900cea1 6256b8a6eb474cb662edf8e72d45598a24d9c9a5d0c2d4ce90e6e4eb4ab72f8d af391f1ce7788799623687e8f64fb61e742273a8a7344a6098dce9f6e1b1d78e e74249c6cc363e2017d459fe26ff53745f0ebb45716b03f735b00889811935ca 5010e69034d8eb2d46d1a8b4f0982c2ff82f6a13e81c61ed262939eeac5cf3b3 88f249e548a21b58d4e63560be38b14054257f5b88adb0c1b2db7248035dac78 925e9971e38bab4865df5368cfe172581a48e8d8a25ffcbbca2dc00a1c765488 e3087dd5dd33f774691f876a3755f311cf77bb6972eb2c6f56928346973d8e99 56c686807919352f157d48805535d6824158026d99dadb72a104764d7983c2e4 46800e442d18322d36f6978aaa3790dd145716459f3ad4a04be9597725af3767 b32dd7aa461a9faeef0e495886d5d8c7fce4f8f5b7fb3fa42ac513bae5903793 b58508c057d5cfe3a4c4524c96c74f5af636b5a9a56cf1bc4cd816e6d4d465bc 5cfc9b6f9b677441ae34f285fe46e36c922c15ae955a9169d490984bc8b626a6 d58b254b005b382262704dac32494e11e867b30a92df690ad0883a5bf7bebedf b582fd6d2430c8651f15e80ce36cec80b79d7283bdcd5168420fcbd779d1e9f5 3e684f24aaba4b871045cc521acb81cc4a9068e06ae0a7c0c4a7d5ec7e2947db 809eac13d43c2fff1e919d0d5a93a17f97775858fd822b787cfd9d040cb0d341 6a6b279a65c84c83083de47e5ddf51965103b6cfdc39be8f0920cabc138d1b32 11753c1fd004eb63e3296009423f7a455019ea6122a22e06d300edd724dc054d 2d32f6d1bb3a0761755bea3b77ad838c0e0b3fa3fb52186d2ff037fdc3c0f198 3f8fc50bbfa21a30257686beda5a777728a60a3d187fcdeb5e361ea75b4d66bb fa0d4059819fe819544297431c1f676d1b486f9daf8611012e8ffaba1030d767 1902609eecfabcb88c566f1f737acc62b41c4131178eb8a8ff68506e2972875e e536199a16fbc159054a32e48cc24c7f151500e82c2757353cca78df3b72d22e 659e8fa4ee5592b00551f6f3c6e8746e6c05a31a46332717964ffbcf24643b30 594bf8cb04d93a3811fe7bd3d3f1a413775aeaeb28d3b06f7f29617e58e3c3ef 7c9d7a620d47d9512b5dad55a6f4fe98940264b316372b74c0d39a1f7b355663 ce45006b86dd046a5a18e70801360901b0d6174a695418bfef4dd036c55753a1 f199d0a10dcf37bf413f9f8617863577ee4a3b86454e3e4c34833dc51ce8a9cc f65ea29258bd880c7924c54f538b08a9795212830240e606e5d751b3ec8e3b6c 4a4093fcf50674032c280905fdcbd285a626d87b9d077973eaa690ca95c4c71f 2f660dc6c1a14877e7898aa47ec02bdfd278385536fd9fff368f5303f1b82f70 05821ee0f3ba4a2451eb951afd27a624348f9bba4561b1fb9089e974aafd1316 af33925039e6797a7d7663d6c693ecdee23099b60ff22c559635b5aad147814e c3662d59040b9dd071b53edf6e41943332e09c6ea7e4e2ac12062992376e7b9e 67c71e230ff2274b8fa392df01d43ee6958d4e6f07da64410754ec5c5ba52881 e2d574143ce458f5886f24d031c49180b3f78c55309365715ebcc8a3620a7575 63160938651dd3ff9cd282fc5aee479afa13705c7a2c43cf8fbaa286cb216070 e51f74ea5fc1d517a12b69e5451f3f6780c5640e5d590c380f18a3300b935c3f ea8345cf437c679dbdc05fe2bf30dba47b35fe45c5ab2e5b68592c4adb6167ba 893d54c1b4fdca988943c4d51d87f37185139c9cb4f8e3626501e36d6a6c5042 92722b7d3ecd3d5f6a50ee26efb4de32b26545b58d83886da5d09518880a6ac1 59255ac1b983a2a2e1551a8f19b4ce70575d7ecf4970a250e6ce5634e7220a39 e76d98db55a8444e9d82f28903072fa1b9a940298b2a2b892ec198bbf576cd39 0c624da5122c9be9c1f0f3d6cc3caec5eb3c5666d13241be0e7f2e0f8ec303d8 0b5b10255ceecca806ddb8fd3f09448367cc961d2cbb6e544811e5a6adbb7b82 264ab5191f54099261d36b2fa67fbf503042ffad98ded6ac5caeee9e638b5a6f 1ea24d52a43ed3fddf2a4fde7d13fc73c8757e7446cf7e95bcfeb16008895c22 a369d000754b106a32c7105623859a2b44d167ba2662474d64ec90103cae1782 87e6981a1eb1f422b6c482628204998236f01cd4f563d9b883decea4781b65c4 26fd4292f36e22a31a5f17f918364d0fa1af7038b64eaf2c77abc071ff324911 1f7fba3490dede66a8ca0b0f67f069f48943844c22261c69d586cafe9d3f86f3 ff7c7a106db23bf12f87313679605e6b9e0c5364c20da190d5af82b5b6b22fab e33cfd1d5133ba44214fb24911a44deb554830bec522fd27f0d9c3084613f413 6dc71dc6f84a8bcbdef2d72e2fe12f21b29fe1253a015fd95dfbfe755486313d 6ba2e3f0a288699640458bb12023f8b1c6cf01e292f386730a7e04ebb17462ae a1ffb0a73d396083ce3a51fae7a47c10bce4e53f736331ea791393d9149ad791 fdb87a472b97c99a0c6bfa8c8ce93c6327dd796f3d71a3a34c4c81926d6da322 91990deb0c917e2d68ab5177ea86fe68552736ac7b702fb81dd994581f60bea2 093beb91bd66615026efeafe94795e5749797c8339f61f9ee3ae96e8a1a5e0fa d1bbd9eb353fbe9bc9c78fcdb9f49d56d310e287dc698ba37f5943660f2294b4 8342b638e5299018ecacc42e496e7b476d7f35ffd6568600573da43331f36226 0de99f05c276e608427855984b17f6a513383f9f3fc5914d59b85a214dfb85e2 c9013f923e6e641de8a15f21c821c00ce771fa5f36a35d6eb1cf71fb4e633296 a3ad1f8872b82cbf7e2607b5058ae202ed1c4f6b5a963db93c46722295f31479 f82e25aecb0428d36f2cd0ddd00a066b4d1dde1150f0a098c2df2c51003a180e 0b12cb3bcac1c79d798fc51b32de043cba54ead89ca92ebacba60d25c1eeb057 d5a7bf94666cca12b65df7241020dadb44f4321f8a1784a3467c2a2950723465 c439609c1bf47a2dd78f7bc5fec76ea959e61a531ecce3c5132f0470a438ca75 88fc504b3792b714cf1a6f09ea06a61fe625aeb30656061e42d839f0edb32db6 e2564ee229515f37c70214195c39dc123f988a4ac285f53676330739b5622da2 ffea0d4088d7364d36827ffd49a02c5e67d2d1fffda60e2268a361f9e665dc41 b90a124da487e998d333f782e11a2811d686dbb2387fdcdda8a5d03197bcb4d1 de4c52684e022e46d24b2085c15ee9750192427e7a9802e1a36cc1ed2dffbdd7 656f299420103185383c44c5962ec031388ed71a73bb7044d789f2ef6cbaf1c3 970fe375583d4dbcc1c7ee1ab99dbb0c96090524ba6eb8824b1675c15dd88d60 aab8f210d3a0fba5dfacb2d7173f21afa3ee0d6a987478f4feb3ad810c5f6f03 3396e08c2650fe809a12b5f44bd599b2cd4fb31c4f46ef409a49fd84a77a01c7 834731fb9db2e5f2d6e27bd7301e26be7bdb804bf83c1937c3c4161aedc86cb7 f242fc60275cc30369ead9e735952f6d7dd15057595ca6f609dc5d58a4791703 14323f5c93b07305aac7426b3799b4887a475c67dba4765ec8a70fd80606a399 dbab57d98c775867d49d6c52423c0b126804542d411ce9ce25cf3318c4550e13 d3311c559c2b7a814beb3beadaf4222bfb4cac71bcd7983d7217cdaa543228f3 de0667f53f27ec36fc2ae62706e8f1f31ad40b7c41c75ed114bf0e330fe87e2d b69135ff45f3dc2aa4801bc87c3fef26d331bc43ab564b85c13b068af18108fc 661d565d6920d157cde619ef12b6a1c5423c76626316733b2f292d9cfda997e7 a0c95af16260540b15491b134d8edba37295aea89c0100a1d48ed2c2b6d48503 92526a2a4f3a617b69c8f512790a038a7108df70693170aad803110083c50aa3 721bdf17a1d57f5d868618a0ecc1b30e5c7c532d4313586febd088aaf1e6e0a5 b15a677ed4b10725e31febc960832c10fe1aa4fdef17c7689dfe10b4ed11981e c556abb91a48f5bf50334d76d1a57a158b724738b1958de18091dd10c248388b e15542597c42cd9489f86844ee28eff51fedc25230ba60b8cc0e4364bcf91b98 d393f580e3514fb5b11a65053286acb28f27681933179ea9a876b5f8f93b438d 89e823eb75765537b62451caf9716647134188fd01e20fcf5d64c91de0fba39f 3c2aa2372f3c532107f71b749d27c2e6ff868b6284ba697cdd6248a2282f7abb 47cfaaa08546aa6c24db8b82a782231827772af391cece7b743e458a4d2f27b8 022d88759e90a3a7fe32cf5d4a589e2b6945a534e72ab513416410d5e062d0fa b1fd2452b06dd3cf267af2838907ad6e951be731fbcc7948b41d4ab9e2f3e6ec 1e669738dd5d5b4c60d68ea7b83543be705962589858f38abf7c94154778340c 6704174c51e37e606f2f59bb4b0d81e7911a7106f067275bccc9cc728167969f 27c3e5582d3ae50115cc2ed27ec69dee741d220be586a8e4a15bf11061f5199a b3e3cff7095f52fd5d429ae13feb9bb07d950421ce8d6eb5545c9c9f37ad7e98 c4e86321804d5a694a9cb01c250da8cd8ad9ed0018a57f753a9727939ef43636 8747be44c733b2774d99dc0ebbadd1d5a265990f3a89ec700cf2c2bda2432055 f3fb7830410b46dbbba5df560109114c9b93cc53944cf66657bbf67a4a3dab16 211000e8e40923d62ce5d876540ef386e9bf3d3198644fcd5aa5e3e82066424f 2013502249fd648ff99a93f5c1084e6b241d048348cacf5c07ca96323798e31d 3785d7050ec2fab2bdd440022329e791610e489f9a295b71e241730578e270bb b58f968cded07722e0ba9b26a0be633d011797d1a98328b938aeda8a43815466 81b119e54b8a5c218ea177dcbe332564e8f58c22c08965e6a697595b708dd9f2 569f521c520a7bf7c26733a9cafa9f68da5c35b0c66f737e632a1e8789e68dcf 20f86cb06e37a7a714ac5dfec96d1b59babed0d5635e700fe647de211074cb96 7878ef11b7770e557684f57ca6bf19292f8249ecf579320baf1cb189643f0b9e 80b6f868d06af612f5b7607126bce9df1dd538b90bd227074a493bd0f5a3f67e 33cd0f98b0d746b94675d42147c90b1bcafe16bf4234388af6cb8cf5672e372e 96bfdaa51f13ab4b987db32c5f6c2091c930e2141eddea4e71060d78da517726 f04903094be80d8fadbc7adfa9dfa821aec0e7d7c412c43752b1b18fc02b2f59 1e1a145654e2c3a77663dd13c2e83bf42b183438281cc5ee4f9496120dea8405 50c1b066abade654288d38684a982d38a346295559d77e14eb87ab9c951b7300 69 c400dcd66c9ce4ce86685cc8acde97f62a69f516225283c4aff3db88a91cf305197f9b94edcfe8a28a4e78b14e4399564c04cffcd13d253eb700317fe6e0c8063261649161e04ae8179cb4413e0078462c2cf275683e24fd045e28a0fa505f092eac2d0c056a2366ff5c8112351b25e24d34deaf2b6a949f0d7acba177b5bc083634802751410c043f6243854921c7497d229ee0969c589c2fee4f7b3bf61203688d748e066e7caf88d71369c6a683e34a8da494e17ce743d8b159a10d7ea80ab05f4d852046c5cb70efb4aa0426d602e5dce0432656eda9863becca0f523c02fa44d25787c83770581fe7e4368a3e3a4b30160847b701631a10593634888c038b142816d58f2a7e43adab6759e7551c085a6bb3111abda63cdb21f4bbabde03c79fbeaf3ef2ca3626b21d96f7ced93fff24ea7bb0d6da1c5133e480baa44c0afc2b61f593ecddd2a22ecd7405f87798a70aa3e7f2ef617c1170f850f7d0180cab1414558b2c17c4b9e0716f39ab6722e0d331024ac2f2a56029c9efa062a00d4bb1ff9801bf4066c3233428a9f7f968cef7ef5ed9c3bee97758651005b4250385ec154a1aa38deba0def3d5088cd98b49ed9d7b689fadad356fa00eadf59a0218c9d90b4adf0ef371b4b0e46ed9ece4d7a6e2c7de2070476f871aef20bb1a08b983bf4cf20e174971ac7bd35312ee8104d7ecdd2f95d429dfc51520d90fb0059218483beb000c8506c10c7f89b0f818dd47181a52b2d09dfc3c001c9159780d0f257285050863192edc696178fbfd8aab58b01e0a93e28d472a7a64a33b8000ee37d2d8cf1697180a1829335b603d06adcf68f746074853c9644c55dd9d0c039108ff7a9bc98a6e8d4035a05f0f9011157d9172ed1353b418d34eb29bbd860abbb7cb38ef8c2d28d103ea47ec924b3a90321ccd44f948bc6d547aa4a4d68a05deb5694be4844d0776aad0ea3f05eda75ce3bc4a9673c18caf57cd761f95b40255de7869b3e4d33a87290ff6b647d57b9dff39ea65e8339f773d7e57295bb90f96f4f4701156eaecf778ad2a9d2813699f6f16488c073efb5b637e4e725c2d00f9f5c2040868a7705fe6b395356cdadb21ee9ebb8504f6a4730050a4672dca0cd4e3aa473ffed04bd6e13b36f6602e7f5da33b7683eb5b20de30ecd754eecf061bc1752eb0179724c1dcc45e84bd62c92d430ef2eef0f3afdf6832a4c8946304f8252eae0dc9bed1b7f971b13975459da031b81a7f68834da247660b7390ff0afe5a4b2f319201771e5d97b9c4eb01505511ef60860019ddc7168bcd3054b6014c3eb6364ecdcfbf4fe2a2e928105a4d9e0596f029f708356ebc8f7170cf2203f7994c32101ac0f20a49796c3522ee0d6c87946b0aa54eebcf66a87b411f4c0e92fbcc534837ea3755beb2338cf05651e06827206c8531524621c96eeba0fb06eb99f61d215d8e873043cc0a39dfcf4a917c94fa00515c4a60d79f8504e5140b29081e52b82cd2d9da48321c45aea6667dcaf982583dc1f46cfa052fff911003f2be27cf931a1890f9484d8044bc65e4ec9386c24ee17e95c00512aa9b1e40048302e62066d4f64364f8c03f783a3c21f37fe8e6838d3ed31c90df360fee930710453502ff90f05fbfbb3d09815b086c082b385ac0affda9a2b10b670fde6f0bda34038f56622c38ef7cb0ddf88c1a62960cb344df5ddbc4e9e7c8a4a7669d07eee0492dbb5b9b3fd1fa48047e24974c6991bd2a98791a340a0effcd42cb8a0dca0cf4a41f2a8b7fd62b8015ca06f2eb68d2c9671b0a59cc9c6a78814397c0022fb2f61948dc917375ef30ebf8f8c8d65dcc9b744c68e20c0504d294ee1093060fa8adde244a30a558a8f48fcbb0d928ff8cf446315ccb460159fd1b53dad90a59bab26b208f99019054952c65d4c70e80d58129034b01697e7dbb72345a310840143dc46d5f19b4bb14692e852edfe2b0aec265ea67dc08a7eda3c01d05fd0d3b05f28eb2dad0194ead51efc141a77be97135f38406e932ab1e3257b731000adaca02e1faf3bb7e5501fc7b327df9af47925e33de27a5179b60e4338ac8d505ee41ac311b80df97716990e121b9f8e1433f341cc70d086bdd781a527b1e870bf27d43c38485aae5757903b479de59124cd255323f0a549f64a78a5f23969809deb5daa333afec4042da25df55f5d132dc2a7f941738c7fd196dfcfa76db1a0bb9216ab4d6f366f9c68e17153e36076f9ca8c5084343b5925e19af128ccb210e4292fe29190c5ad23d35352704e0c1de097a60914e1958253dc885aac2e4b108906b103f38ea55ba036a60595e09213237211181bfa4b3e002fef08749b1740f516f1226477565830de455436ef4ba2b15af376ccb0a8d090d2204780b30da01f728ca300c5c07af81422a25ec86946630cd61a2ed574e9b42f11720e937b3037e6154a3d38f08c400d519756360142750accc313f0ca989c747a8488c17fc0cf2603c61a31311e83843ef53f9cad5034b35e19328db0b2c9338dc61afb340031fca9bd320a3d5cce21e300aa4510198d84ff85a4d211799b16d021a8f4e1f02f345ad7fc08566bfe20edf13f4b113107b20a78cca1bb99c70f06b8304f6bd088e2b380418007535e18173c1c7e85ddf5d5816f23c36480f4607cf4e0881a409b81d11f310ae7aefa24ffd06ba45f812043b76fde0887d256452bb8d6822740540918ecb1c669e373ebd518a40e8ccc6e2772657a03dff6ac7d6b9dbc42aa00b6c294cdb557cf06ca1962f365d5d94706cac4e9ae3a5dbd0c653f356a753330f4f75e995e211fe14583db569569ad5ed133d1f2df69e34b83e5b25be881da507a0c65f5fdfe4db0b964038cebc1fe9aaaec0e9df0225743a1e1354152cd5590e04f1014158d4048db661a701241793f54debd8693d671cb9d09b883762e4d20e5f0e9f72136447d2205bd1e465b29dfd37664a5b4b3bf3803f6076487352a30e69c9371c8bc8611f446145ea9163a9810bc63abbf8d6b3548fd2ebc3ba19650b3528eec70b1c92e39124272b41a3b023e87fe10826154668f6566950341c4c0ae5c00cf4a94441321a7c3acf5a6058ec455f299acf966942bfe74cbe75e5d2079b3c87404cebf90870b59e4552c447d8cd50d3dcf913603934d06ef0b668c80f3a65e62c34ddd7dcfead42094e0f904347036cef98e8f87a5e0acfa7c105da056ee1dd462a18344cd39f60637ce06499cdeb71e63eda7eba803ecf26ff83b80ba905229f448bcbd6b4df58e365ef53b3116e842f5d51de1367a74e64d9d1320c2598b8ec8a28210d5ba475d17f7abbcfde3d04b3e81dae851e32ec9a7cec2c0620ecb02a2f1c3067199071a533cb967809e4fbedf147c2a38c82f5c40193250af758eb6cc4b732d92ef6cae9c7e4d3f733ab49f89fe923be0c3a8cc8cbaacc08a4c1ed0f185f6d66a8e6e7438536e9fec766a89d8ca89e16e14c58ef9f25220e43436f539a30ac553a50a81cb2d87e832dbef46467eb62049e7f80e87ec0a208ecbecc910f6ba99e929096293accfb020b843cf006737d0c69e6b4bf10b17e07f68bad5fe751a7e6c015d46c042eb0f100e6df524d05b2f123a3cad2ff2030096ffd9cf62314fd6a88382e2e0466ce91d929614fe0ca6b64aee977618e65ff09fa70d7deca54c729c009ea73105b9e6475017f680cb34bb5f2a255f868400c0193c376f7ba24e556641cdcd64afdfaa6f3f0d378903f2f841b320b85fce9960abf3c360a659951a5afbd16fa9d4a0fee00534831f5ecddef5788bbf26093660267966454f49f775500f05b3a5321bfc2e7c6f06474b50cc565940becf78796058e20ed7ff0b0d721dbc3bd3e4bd71ac6b7db831e4bee48762f9081de1603280b7027e9364c446689540f1dd3e7d0ea034e7e76357468dfae80b4cc2b353bae0d2ddf35ebf0252f281cfd23e61d6b289508ee40ce1ce453c2e1e2cc9e3a580d08978a2c48997703991a3922f68d36a147c817fd9d6eab228aa1509b4b850de2078c2415df86a1af7d953a31f97f7ef99bb9bf43a8a2c1a2d553f4b016a694410c4867a0744c3ed5e2a7ca4aa77f727ba23ad4c8430bc6d0eb7e674ee493271e0f29d882710b6bf73c07c1fec97bc84b7816b3189e9a57cb7518178079514b780105578f6a783ad337ef71e2b90134d504b6bca5446b57d357f4b1a6ced2813309aae612c5bcb48f71e538a22ba88b2793955c71b3bbb75de05f10941e83ffec03303d7a221e4ab1c09bc767f66fce1b0b165c8d6fc4590bc047252c53a7eadf08a64c357d5e442298cbb39d7e744d6365ae4869efe258d3a775af25282e175203db96e2c8901365cf0f37521f166f6aa35d71810bd4a5bc3baacb9eb3fec75701839bbf432e8bd02da0616216dd1b3b1bc1f4a87acce1ee084e00c4388d487a0b906ff188b5aff18b9282a16385bd5d8b27f929e9f2bf4eda70b5b40a3a067901b336a0f76eff2e4aa73dfbed34fd46dc7e8c025a631d7274a5c7f82c1eca1f02dd32bc8a5acfdf2c59ac7c0ba116e362f2d8a8291c11fe7ab43c14d1c995eb00b89ada2f48000c4137b330688739f5bfa8fee35d2264c4bc512e078fdfb28809be3938b9e91a0576ae7fdba0f03b04a73250bcebf651e98aaeb19657101a7e0f523f96b01f89a52055c5173ae44af145a36b779ad1acb70ee397a2834a240401f8448e04061d0017e6b6d34d4b96305f238db7ac6dedca3d5643a648f672b506430da4ce89c8a33e8be5b60d2dcf6ef0a204f6a6e0867d0c3344effed8505706bab25c7a54a57891c97429ec649b7978d4c415d29662dd2147f37ea97513b20edef5d683963c3145fa73a33c6ebd93b6c9dace9ddd69191321cb5c2ed406fd07fdf31309530bdb101fd46ce639ebd158f2e8ba786fb1fd62983d22276f167301ebcb33991d030eff9acf56497021a14620978773e3ce6f281aa56ac154af590829745ff1d02317709745b2e50474050d2807ce953dbfefce566673a7249b17034621026a6df859880f9c4871745ce520b89b7cc2ff558f17f93f73cd2f21870d609a4d8bb34ab213dad81c15bd3c84eca4f6a70f548fe6f4387585a04a6e7f0b5207b947be5d6bc4c223c614422331cf9ed419c2759cd0bc7bc24b2ee5f38009f8c22893be48b1f8b84159303d7f8fb70a4d155f9c9155fdd3383b0d933e6108dcc17735c3a90f667f29cb7db6789e9f0862b89b51e9503dfa76e300bf4cb402b5c147e306994904b828f39e11679e41ea3abfd3afef0f813ba98c9654d62c0501edb686e7c22bc923c250e312569e102b721a55bc72f61255fbdc19b23c640813d9b35005aa8536d0cf7ada2342a6c034d44d180e2a4b78ab986ccb64a79007e75cfae974cc46e90c3ebd3e492ab761c437b914e53f6f9b399a30b42c03640f48d7f779f49d6d2f2315f7ce6a40ea1db9a59e4d69a058abe94e7708ab8d9308da8de9c07cc5b0b79086d5f9d2611fa4c383b80b62dae2b7012148a694d138035e22d55503a71a5a8c51ef6cb730b84b694b9d640f302a767513f3647716090140dc7e9ab86b73d4d72ea069275a168667bebf74bf634b7fcf38c29a7645fc0e11ce0e5c7bf32e418228bdf5114efe80538fbea9c54dcf9d0b38aeb0de60ae0a201dd20af7297d3701c3369ee9ab69fd437ee170e3e03328942403bd67ca6d0ff833986e2839904c00888a2a61e74dfb3fe7b9dda80aa5b8e31f1fd2ec154e00fa93819f02e63bbc267a621df251f1c69a3404d497921a3b0cad359562a1d801e2dffedf404be7c36caab6526ccf425bcf939406e815f85802e7e5f9a3830d002834feebcc0cb68c56615b3d5c69733b63756a5238193297a1c15efe969c6405f0b82683b2201a9bfe3c452b67788bfecea92a4511a45f812e639b7ca78aa40d77ce773666518034887b921756a5aed92b79d8032fec550e90c5002a5db1dc023d39359979ae9dc880e715d2f25f592be9510aad4c52cf33f18d9cc800a51d04c20b8bd80b4b1ecce94c453fd73083812f05ba69c5258ff5b192c6639c717503166d197a5c02174eb0422e58ac1d2461b5e8bd0f722178565f879d723888530b543ac81a6c07e4a62422f128252636525b7a78f3a60745e5cdb1783338be5f0eb70c53c769c047fe8e479326b8a121d4e4e3b4d42fc833ec65b6e6bd7109f303ded7aa4e749c68a8a8b05a7765c172ae4f0b541402817ebf08cac386a228d3076e0246c6aa2893a7f2a11e37b8b3e02c6905e9e18992affe4c36120e94e1050089cee0252279797d24c076ed9e67d9a803e978db88593a47eb0b542af259da05e5673cf2b206faeea1aedd05fca70453210515cd09c0dfebdb0d0b532e8cbb002578e18b6620adcb39cecbc79d67a7ddfbbd9eff51bcecc8ae5693cc632425037e2e097ed14702da2dd08f154d2c6df01c8de2f496fb4a1050db0df38f4d8a00a9c8e79cb3bda8ba286177d77fdacce0011d48bbb7f9ed536789b5402624f106fde6caab2d466884f4389275af6bb4ed4a5e845b37ccffa5c2ce8930c1169409ae87c54edb44d322c07bf7cd485804f843a6f2aa93074c077762f45572e02501dbc53906d0d056785637d272572d9bdaddc5218f3a42a39a2ddd7f092352e2057628cf83613674832e56c552aae03e85074bb6191100a0c110c627ddc76b2b06ce9258be5b2efc22be6867f2ec28083c210a886c9d3d02874b9dd986029fe90ca7e2ad951dbeb8933785d70ed6ad7f2deaa3da8f0266a196714f7e7ec72cfc02ee14a6c48780d75db575610591b23a5039cc5a88f3116b2c9d619976c399f30092c2a906fc2d60624614123496df4916dabaf7bc7a108c4cdf4ee1fd5acf590589a394546d5d930d6921ad89059e928c84c1d831b9dd84837a0b1c0e218da6094a5f9e784c0d288d3fb08a26dcaf7b4fa01a04cb96019f9c7d67dac56eeadd0471058cfe766cb95a438036679e2389081963f536312115991b956e92631853019a85eef2ea4a792e0bf9940f254dd411ac7856960a8c46a5d4ce16746e443a08ca4e288772180219ac48cb649f284d875a6d26b09876d54b23d3eca0fc04c5080af9741a9408fc857c9dabd101fabf6765cc4dcfff839386f9347ddab7d85b0d7b12b438ec95d130c169cebc81f0460961d124447c06257f7b016d3537799a0f9317ad97415da98570f615923fda90f5a12ad6999d0bb1b08903c366f0ff1405bfbd5dffca22012908ac68f964ea9ce9bbc8af6da6c00a35fd7970c6c70c40003e4e6ebdc99fb03928b98e49bd25a2f5b727809ace603f46c76b6f75f15f2700f418d88eb5a195267a536db9ec99a6855aee5c120cc198c67113b1f9619c1e0af4f63a9575290b71dc0efbdad543dbc6d8334e4c85b47d8c82009bc477243000b0a5a27b25f6ea31a3ff0303e53ce4b46ecf3030ff3e47849478882e8d4c560983ee5001be5c72112ec58a0fc19087ccb075f83244d38fbe7082ec952b2d4a0a19b1cca4d5844638c28e1b6c6c57fa4203fb6677184c750d04242b8e216a1b067bc6ea154d72c86215cfb6eaa611d3d7afbed45308cf1aaea4bf4fb463ac1b0064d4a9ece22700d79c0ef69f28cfadb95110b187b8e8f7337c50d5f51ec6fc0d85e69751c968ebcab44dcd37971e732c889802b1d3e1796e66c23da159f5f8015ff85875b6e43318d59042601e668f5c1fe995dc6ebddcd46e5d65b2efc26501842244f5fe28e998ec051274013966785f76a39dc7be21121c1a27c1a1988f0f6bc3a157319c2a129b1e5eb220e01873b5b3eedc88739a34cb157434a4655b0adfa7fd337dd235e44e062fc75ec7dee81fe39169777fc246cf29bceddd2f5603488472441d6329d7a7a94af8fa7d01804d66fae0b1c9c987928c025ca7b7b203522ff96496fb70086aa61f3f12a9d94fbdc20ff88a3dd524bb0c369804c3120ba47d6d0d22e2c28a65b7c376e51f4bca00e307f4d2a5be7692fdfab601b24a00690eb26cf2a3f305fc565edb277c019340f5cb4ae72062cee928f40e3905f30ed58bf864a824bf8d9bb68b46b1e1286883b3a974e54a8b77f0dd5a4476949403a1b0da02e687e6d1a21d39a0f67cc8c5c85c0f299e8db42a5b247825787f180a6ff2feb3b8ed46743af099d36aed6f9a34fefd9be2c788b765ae6b2e07523b0518047035f9411699c63e8595a4b9320a481207e487332a87d736c91cf4eb2d091eb33911b92fe4678e1d8f13c19ca251bb8f7b20441d47e6c799dcf4096e6109a05327c481e6f79df04c2ccc993ca297b824baa8470e4498cf43b826aabbb302c43fdef413815ff25fadf84e9e3fa3086705b62cb710c74da79895f723a7330324816407de1271b60e731977d1af4d86e3d034a14a3e352f05f88885766cc3068ddb16ae7985db7b4edcbdb70de4cd4eb5f94654908c4039c3e317049be20c0f448022c0e3e9f04ad699e15a8df6da8ee0d9caa317cb489dc5ec276e77a05a089b0a0861d69e58788266f7d1bdcff298ab878ea92172354f08314b2a3fa10b0bc46225b16593630a998e044ec5a9bb1643056e3dee4c6f2f5ccf9daecf6a5e0894d7030025f9fcd40e05c9e73f6a54d730362e1b01cc9f2d5db45c336b18b0014fb89a21a8eac0e6dc0403b9d032022d44af3671489b8b6bfa7fafd3df8e6b081116778f7f3ef02a386730b643bde59acc2db7ac753c7270cc46d141b7ce900ca1b2b6ea29934ec3b0cf15f8f5cdf964f373156581e78eb6848092953b24de03cc082ae4cdc71501b994c65c48b9df73f2c44c7092bd53532b287dbe7faef701adb22b822c36c19af77916590bc395d298d4e6ddb1e7ccd7bb7933bf8ffd7b0f682527db4141308c3af779b5e2558b66ce7d5916ea7af096418fe3d65ce4300a2a1328d5ebaf7647c6ab32399151e1b8adc25e0b12d4ff960a440d11f5b0d005eef67c33ed3f4b4744d7d98f1d1f50d368dab30c16b1f7b112d9c212fb2c6a0c69cb437b2b248f68eff447ba39e4a7ac8d97273f2c507378b168ae88779e6b053455e7b29e1294a4c8a93124532701c84541d428a84de5acc2b2e9d7eae8dc0b87289445352cd29aceb27b5a6f0a9623e127f84b28160642ecc003aff0035b0ecb224e50bf2a10a84e9268b6417b7bfd12c33bd27d7c5a48d6960c01d8eeb40ee0431f73805bc6b3516780c77b8a70cf5b003354c529f39f45c1211647a2d30c8a810c54c0909d6482a5aa2e4a9f0218ae551a20a93980eb11c80d584342b30e0ffb450e790246bb91bf0b7ead7161666c2cc64f79b745c646f514b45c0b1b0f39facb1925899eb80c2a50467f301e7f1b7789b6206d9658222b85400b19990e819c1ca5106625324e25a890e46ae8b5817b0d81a47f775f06160844ae8d0d087779a213a0d6e111a2fc71f860b9f80df3c38e08ac7b71fb3af53172f20d2004cea1ac76af87c6117749bfa054a3f69521b34b31d58ae8456c4ae33e36f31d0d4a5f3429a5c926b4fa2e356fffa44d9ad1a562d6d9be6a1896fff390d5194e0b94c2375aab43f8a147c5825f054932bd9b88decb2a01a65a4618d26a4862440d3e3a8cd082c654ee9e011c3531f2f4ff33b1a9eeeb2025075e3b9fa6ff3d2901a2cce1d29cf64329d601f836731b2574ddea2d89738016949a36539a4969b4032b29b12c8e1029a8875f675ef74ddcbc88773b3fac28b6cd53fee4cb47821c03d4968eb2ac0e2e91b41e38dab10cb030389e28a7f73cafcd567429a8418e2105ef8ac5c2ad71f3f7e2f7682a73c66d087f67409f736d04d4b60f68754e1dc90c2412d86bad431dfcc8a869c5ee1bf96ea7b4d2a35ae1d3e0d3bb6bf76cc8e605241a67f2379d7aefd2bf3abb9a987c565d88847ee6f8c2e64eb15d1e3b2d0205b922d042c20bc376cf61a1386cd9b079d0e504169794682fddfaf877807cfe02eea07662ca5bb79def9b0edbf6b15af6455c3ff18f81896ef039f28c195cb50565e96c47072171879bea8eac4e0766a59d1d19d404366d897bcfc55c06fa100a72bd1b764d04cb5d94ddd553eab51caecb49380fd56c3bf23c40dd8ff37f7e0e852a6f78760a395324b1deaa1ca0c4a52033bce9d37665cbccfb0d628a0e4c0ad05e7c5d37e387d90cea4890d7e9c8f976fa4ddb60b3de212469569db616a607901fd285abb313c11a8959080b3d756450b1448a494642d5bfd29c1d92175506014ce8419cd49ceb69b9e0cc11e78001d4387c16536dd0fe697e4f49f3d7d0009722e254ab780d37fecf8bf58a2b5674a152b4ca68e3fe7e5baf6a959395f60ce3eaa6ecee3bb34c47c84f825433cba087b8c9e2f0de0f62eb2c755d0861f30a05c065a53439be2e794c3d5cc197b5e25b5124d743d9468db8484c65bad12503699c33d0306b5e71df09cc4cf50cb9bfec7f8ada291d7ba77d079a0291e09e034e8da6a27347d48f5b9975ad92a4d84c7939fab99e89f319719e3487ec8fe409629eec569c9928663cd4f4efe35ae8b6876122ea4b1e8fc4869fb16ae58ba2052f4ce344eb030d2f5b958b8a0a230639b6025ff6091db523d74654bf6c22830a77663dc6e3c17992edcf882fec55407772a403a66d74aaf7c4c8cdeaff486f0056cd005772903c3e8873c2d98b7abbcd35b7d154795c2f73dcad880f390eb3035fb9fceb50a8e82dbb11e9e27b7d08d5ccba4b7b825be799c14204c9c3cd990f0182abd0675108e7641219e2e287aee0e453026618b384f7ec0475b6c2761d06539dda33e894dabefd0595654ae0fc1fb42c70077309fcc58a221630bbb86d0dac4048b707e179797fc99600c758edf10ff549089f7d66bc096bccc7859115013be21833ffb1169cc1df865999c6e18428da149ba4cec11e46beb5cd8fbaf40412b4b42362bcd36b56b78b04c882f99ddafc0e41e0675fd463919fb10cacf80ffb45859b8726ec0ee70fb2ab873caf5b333ea273ac9d6bcc59e4f15d63891e08c27fd61a9f583b90d4cd19d8c06b91a78c6bc6eef4f81920d4b001be90a9520eccd8b2018d1c62a38d27388bf91c620739055d174c16f36f0abef8828a58ae021b174de9664d41dfeb6206c394f5a0ac2bad288d4951ef45d09028c07aae8d016444bf52187752e9686e8d07a51a906ffb72f0a653870e29c38148fdd60da50771b65d9c65eb306efd0e6037d1f4356baa6f0af7858e1827d6cc7e0fb7a6970217f6f1ab34254a47a80c9d615c5b1de576350345eadc68cb05eff8fdb7140d014dfd4977d85ddbbcbabcd33844ccfe1465a180c22d844ac250c6a36cd33d5505411ce0f59e32b073e75fb11426cfdca258f37fe8ac4f86b237910ac6b7bd6b0790f2ae95924abb00c3adb71eda0f96828f0a548c9b54f4b521067ec61d643607f235075a90e1d6605c3342c26173f941234cbce6a6bc94f8110b35b5d58b7f008d232250f6a4fd39831a5ef6f11245f3a36cacc3d8f21acd7e113a5363ee91095c4000176df4c981dfb3f976b7d3f90fcbb7f9180578278ed148bc10eed10d0b663b50375760ab577f84172d0c7aba9c8f85c0e805f123fe1bbd8b4b3438640bb3b1de5d94203dba6a929b33c4a7e8694c7394522a48337af5cbe1e0c203cd017ab565f66f3ee9a2892b2da2f4b905a5d715f0cae5b66576a592830a5c8c6301c445e5bc769310893c33340a4ef72aec9ede613f6ee25c58068427c7727ea104d163ac5a8441b156593059b6670ded5bdbf51a1a9a8490fc680eff9bf6630504a09e0497de94419c2862d9a70441634557ab3706f3b3a57377c8bf9327d2ba0a8ff2959855984b7f85a425ca73f83c1504a76c9aabfde872c1de60089a873b009327195aac6b916980434bcde81fdb1a2d635e29bf77d0430d27b2a47ab6250c422fa9fbca49e7f9c3ef8cee46522ea6f1b1dee38e91b7261c28e48576c9ad0302ea8fb85c0389060582e699a416dc503562826c63fd18b96aad2f7150356f01e962db92adae0cfd872f3e14216606ade6df351dbd477751dea063d05438390d9ba2b48519031a0ef8bab9560f27fa18add5aa559e5b7f3b4660c121a990b30f1605ffcd2907796dc5a83a2967474e33ba236f4460b519bfc5eb1ef9dcaa22056460a35cc59469e3d11b5562a3311f8dee918dadb629186b7fa80354ad09920bf1192144a9d3b55c4f617623cd705b8f87df12701c740e59d608620d051cdb0a681240f5c3d0738eda7b6992e6b17d314a46b99467c56e7dc3cbce4421d7a40f6f22eb6f5530c938b11387aaeb7e86295dcff2bf89049611a2df51d26077020ab668a47ba24e2746018dd3e0a95376045c187064a5c09fbe38796fa5beeca80335dc4c3b71385101bbd8366eff8240bf7043b7452a515807d7976d754e1dcf0dc3f86be7e2b5f7767c2f5454cda40b2514ab9d7fd1b2c2ed4ed832021481c8028c3525173166789b5b6e85a9900bec2bb826f6c469ae68033dee628716cf0b05213960bf87f65fa170cf3981bc53d9f0e4e7060190bfcdebf7047f881b1bfa0df4e4868b44120186524cbc65f081ba132c094d990c36c53e78a386b89d89920ae39525506af0312d9a8d53e3288d69fa44f5b7efb80fca91f71354da3fcd0001d1cc5efff003db4208994c93b1c8ba8752611ced0b6be64385dff3e3a1d99603c3cd630aec5182a7628a9bd583d3e0307e130c3c056ce53df7823781b2be6f0e68366929e3db1d15163699cb52edcff18c7754746628ee8b83c94e32fcbb540433a3e1ce3ab88fef6f402090efccc0704f767fbc8c37e697445ac53c3c7c500d01c921f64145178fe1482a7811ca416a917f8c708317df8f6933c586740b5301ef611168662eb451e3c87cd9cdf97ae0ed16c7e8833f617af3fb288eea9b3009df80cc7c9f3e0d87d11ef867474a9f5e2344a777db658d4befb424c855ec0c081461edbcae88127fd292f7b1cf535a0fda7690d37b6945161e8ecc35f638f40bd0832f4aad78ebb0e584cc30bfe8ccc2e75c99c0777443b8959fa21385b75d0958a141b7fb96b9f2685848d287ca4304bb4390b3758b856ae6995d7e67a0340db71239a5993911ef80895ccf5b36338fce1f4fe234b7c722d912ee0e94daa80abfe2ab020437f57271af71cdb218d2fbc924008b5e667a062fd08c6db388430c30863da329717b25acc19f33581fcab0e3bac58c208fde5ab9498dbf22ea1e0d3f5247b9e1549e55bf786de6e1a61ba4f12f19ccfc53e01d79fe76d180b657092297fcbddd5e079cd763b3fc25c9a65fb0a7e03061e14340e60de0751285d705dea83c50aac7de7821758e4b754e5fa8449c7a7630addd177721a8a51634bd0a08e4497e610d8ea8a63d317e9ed4534bd7773e6596ec0ea2b4c2927a17e50f0241f0bbb40456d859a1278340f9e48f7bf9bb7b588a290acb19c9ba56a63ba20ab053242b08f86eb28b911f313913979f06f912ca40681ac2b01066410108ac06390582609857a672acb93cc2c50ba103cce1b4558430c8fe3741909bf5b011010847f0b8083577cedcd5282bdf132d8c3f556b3d3e31e0e2220b7e87742ea2017a5667f2c7754777123e60f783f2c3ff712b88a46462bf36db6265469cd85a004473e6ac6729bf13285a046d8149f2ca793b39e90531f02e56f7989c2671df024c7084bc037d70b28959d8a6a9b8263ba30325d42348a4a066c9b2d56fa60c0e522c097187ba5909b5025d3c578746b97e411ead24a457108e905d2835bc2f0298717ca1e9a337529fa274d92c8b5812806f9da9885ac354200f9f289f33d603643b05e0eeaa0fca529ab7f8234a9ba3c67bfd146f29922422da65310b8fdb0bbafc5901aae1573ea8b37eb05e4c0d09be63d4b62dc13f3077d58dd3ac43cc0a9de82e3c83f8a234c1f2b72621b09c190f828219c364653ced8621e3172c57062f32e42e8134da67e1191e8b995d06cd6dbf8a7e8188edbd7157e8f1043fee06629fe0c7e045a3c28cdc99caf78f6e27bdd8273ba5ad7eda480b1da10a87c9057020e229e972f294612b0e4ece4035f6db503d6b5822b12e82359d82e2bac301d8d04cf2ae0b891e2cd4a98136d211184bfb5bf5ba1b9de0f93ccbe270fc1a073d3be3d8b76c7faa81e6f585bd87535fc65420920d81eadc6b79401f65b7bf017759ff27515ecc89d960ea73be9e55ad57bcd4cdd032e08359a5046eb8d13d0042daed43382c0c4724a6aee3eec70fbaec9f28f3f35d8130e2cc738a04bd0e0bb49ebd470ecb7fbf8fa434f848e8aed33a1fd7cb65fc2415e3ad3bc57bb50a09747bdade1e58fd31e5fdb498b8f110bdfa390fa7651779521d1fdc9c3279ee0a68921330e26177d3e50ec20cc2efdcd3bc0a3fbf42e1f85eb184559d6674280ee849f04313627801561868e3228b1d3e5a020190131c914c9a02f9c60155fe0cfdadc634aa3f052555b2d9b0352d5710cdfea7d838104daa0d1b9467f06b070dcb39dfeff739f04f5224e9d4bcb820fe5c2f1771731bfe4b759140b7956fae0e7978415117745d1d57c5a944119c62b02321f549cb8d1a487078d3bfcb278907491c1808e65df0fa1e365f7d8a571fc6b43c8756093126af5454d4468c66f70dbff9a48615d7a41e4f32b4320b30df1c23d7f03c5632c40167a5ad8f293a150b56f91b38928d56132d78f0a28e1f01829dd27cf6cb3f75f00770c68df9fde10b3872e42581fa87ed4407c088feaf408d9933cd7e1ed859894df3c1de211c1408d151cfefff4295e50c46b4f7f7d3747bd5983a25a616ec095134663747079504bfe13d03791da920f5c23091338a07ef5970e76fd98e76f0f241d4aec484960523ce18f4a28f19c68699aa26d312e1a8407b7282fd5dd7ee4641a391eee7f20b5e693f4ae9cef7219688d70adb14bf582ad3ac36c9cd678e257c52aa27f3ba034c06408ec109986dc525c3fd0569f4c87af71e2e6998fd52a369cb7ca52eb10732dd4a18f1a76bf1a0216db6d3e89b5f29aa661570328708c84ede69aac65b0249544addcc3fb1898d33b9f87272f45a9b797f97880f77c03d16e84195041400c071c2d900cbbfb08a5ffd7183846726884e77a506321dd0c395271943a9dc08f4b5c8cf5872eb64d25c34d3830c4c45f7b1565647b985834be21a00fdd2dd0bb6116d0621d3eef312029dcd6e67941a0d13a3132c2db6f307eaaec88b5d6b0f8b9c1489ad9792006052c0305d03e1ca72d6e0bfd00254a7bdb0b5616c3b5f0bc70b8c47f6abf58511cb7d7474435f839812d0db83bb5152fc7c1bfdca2cc40d7db234280d0d07672e262533d9be4e7cb4fa38d266991f892c723d579404aa05306cbad97e179acb8ded8be33e87c3c1b7f0d13c63515170a5888135280c360b6554a5e57920a494728709709780766406988305edc2d3e70e36a335a2290908f749e424585f34db52bb23f266cfc21ed7fbc3d8c361c5c841ad52c05203e40d987e8c9f277efed398f9c02ba060a8b368794d9441f003b5485709680b5f1506758dece3a5456739e3a169f54f2a297d1f4b7179b996277f306db2fdbbe76e03041956fd992ea5a6282b81bd84b7fa17275bae847cbf6b7b0ce38b3b91548e02abd2b9c4d3ef42762a6fd8df382124e0bf149e3e9d4323d0142e898fba78830ca0344c27f1616ffb7f8353d0dac1cd7d8b172f8daa7128ed7f79770fa476ff06f23b93f506f4908ac698d7bda1351c54f97249be14b744a943de8a03999e630bb059302079a6c3f1a6d8e56e8a48b7f76e05dded7e538be30271c4d5b3bc880fbbca179510f742078390c7ec3a99a1e982775a035c071b653075f4e2a378f0016fa0dd3a0c9bed8ebde17c9d1d117b8a3aa9a4ede663fd4cd91314905df06b0a83ab5aff06ccb5e4569053161cb76e74be5749cc50c3fc26238b6245e580350cb966b1d375f2060409cb0b25620c4564b5736a12443d83c7b7720cc6e2cf600827f9a6fc1b221e59fa1e14c827dd1513b512dcdc743cafc375cdbda5bd788d0fa0b5faf78407eb59b77c34eef638e28e155b21cd6a744c0089792c54e0647a0459540d8c6c880aa75840e85a791de8a0cd107d6aa802584b6ff25025020b490b3a178c1ac3adbbd4d024efcac5e6f7507ac9c4955317492d53a6c1a5bb070f05aaeb989b5dfafbcd0b676b973057e7d683d1c891cbf5be02dcf1177caddebf0225bd57aaefaf5a1723887aedca0d8e55696222a81822995fc4ca91001c7dda0604603fd3275542b104240752c8cc50bd45453f606c0afa49cb627e302088c70a6f403e7ee6837a9b0c3d8ca404ca829b777f7d5eb3efc96481f05ececed3370fad98b4da97e7b8e5381e82ee4f3d07a1682a0405b68d7d8b46ccb2d106c1550ab4f31226e835e7ad9d5d63e17a57a6bb14358fbba10e6fba89fcb419e82112084f217121de144660f41447151067229610227ced84f8829cbcd7059c074cfc0f9f604b5b8ddc02f03a371d55167953557700fba084a7e7a6fa5046b905642e031366d52706175e0b09027adc84d6b799b305ab984e7b86c3def7d873d8798603655ec65a5ca477d64c9e5cdc589091d702a047b28d48f4bf97d748717af65f0eb7bb81fcbb1f6e56f3df0fb12f89f21df6b0127479f84b75f9f360bc76f4de0ccfefcace88864fedf39ca25ab28bdbdeffc63c9d8bc84a846f91ac9cf4ca7f0f5d4b48cdc30af64ca7ce116a5d7db2d02bec3897583d786a9956af7482cca70858604b9f6defc7c609670acdbd2923cf0baa48fc9c4e3512ef0de03597a095054069beb01b72bfba5803c427da8cf7a650fbc45be786c999e9982c35bb1b020f988496b7966daadb50c9182f0a96251b2139bce6d2157d257c113c0bd96893071757a8ff890aff9dc94cc152691b8487705855b61e21ee22a30fa1ac3b43ce08949226151c2b8d82de0073d0187c2580a53f0eb32147385829bcf4442901500378cfc3f49c16c4d7f226a0d3b7fc6098a5c7a5b510babf68795360b4402a1b09647bad1da714a07b8bfc08627543480b4cb96ec61a3de329c17d5f055159550839db697d633308a8aeb50f5099ea78bd484457ec9e2e81224365ac78adb1e605b76436fb16950e4e13e9d9b9308f0cdbddab1e8e68efc62084849cab91ca820eb787605021ce1322da05638501cbe914ed3ced9ba73115e4746f06f055c65102313765aea37ae8349f2b22715484ebb6d05461ea394a79f02398eb668aa1ae0bb7a3dda94881db130b704cd288641321a90681a54034165a43ddfbeb2cfa9f01669eef11b225bef91b379b88968bde6bc8a638a574a3e3300ac8143b13f5f902d5dcf331c168304a7668a783e21cda7ddf3286bdb88ab40d3630b1bf9527e708e05c02ba08fec5b4ae0771d173c97b81773c3ed55e900579d1f4abc01ca7d405cfd9d5b877f8b29a2c3eec59d652f5f2b16ca729fef248812e65a7d45a3a4c0f5b0c6233e9c2287956411be9075be3b05bd6610979eeb54683fd473e44efd509e52e64df862b1a7d5512b26d4fcae2f3ae4dccdca15603ff2c46a71be6a3e806aac3227c5479e067e410931975f5cab25bdd9e52ff3be6a99b94b6263f6ef60a8fd8ea935c62f6b11386ad8da37f288fb137d985c199d4f9a296573da418ca0ecd01b2418499e64c5244cd9c254decc386f8b6ae4e03d0ab17a78cbb2e89c702ce1e1c9b637e12079f655ce79dbbdeb45714ca40275606a80b9402c83ae71809600040018f6a0bf6fbc6788463acf5b25f37711abdcfe77cc2059d7d06af2b082dfd7409e505447cbdaebedaba426b7562485034a2a7472f934a41c2ca902d0c -generate_ring_signature 4b99442b09d30a94e40a661547b075704ff7076e432907efa34f28fbf8f98c3a 8c817e1ac218112b22b9f47fd1d7de82f36e48900926febdb32adcfc4e4503e1 2 3596cb2eedbe31599dd34e5577a038571b60800da674802f977182ddebf3cefb b290773d661bfaa5cc2d1db49b3633963e714e9c1f3cc8d843fb7f9e57e199a8 1452ad276c1cff34d8ed225e848e5f61080b131f2500d6bd06b7e85f85d08106 1 e2b501cd7d0686a838e640da652b738ad74ec10381cc0bbf43130ecbf202be05d0e2a4e1987d0b31cfc1e6736d6825b974545a03d23f58655ffef5304c0cda003f8b8126ae215bfcf0e6c3fd67e14684f4c77085f54d8807debcc7cdc1257909ea2b9e2d16949ce92f881f0cc0b373a28826c9d97d89d3fe7f7817f250943e07 -generate_ring_signature 308bdb322aa460f8c564d2134e23833f4e567150599cc3cb027083c5172a9ea4 6025c2ce5f391b371ceab7d0e0a0718eca1a660603056c887e0117f0c838737e 72 2c78fa1ff09188a0c4c26871aa125e9078025ac1e49d77593ca0dfa1989421a6 4dfd23fb69675f8836f93cda1dca1f2c55b68a16435d8ed3902c45709f11ce2f 9562994d83657b04fc8a26ec25ec00dd6c2650781d81e866a1e4ebf78e0ee80c f5d9c7e8ad13a830598f6f587c48910b3cd4b8d338c90a3194f3cc6b8c0a1a89 515aef296c04dc838810cd2dcfbf8f4f42ebfe4942679929cd3247f333a7734b 0f0f309eacd4b8ac55489aafba5cacd746a1643399130d56ddfc77e826feebaa 464b240b5fa690508441a556a6e7043451d269ba3fd38658a46dcd78d449b781 662cf10b9f6900077f61ef37bf3b21a4b42e0d65ecabfcd5c593ec23da6ef016 48095d922127ad39050e52130b408147dced83e557b81f237e67864e68e2103f 55916c66cb8086f42769ccf831cd4356d31eb6c3411db78d8b8a8e5d7e26849c b72e843b6a252e3d6cb4f98bccc29bc494779c107d385cb52fc9d90fdbbdd43d a9264eb06d803e5d7c9f5054678d649d87dbfc7a2c826a2346e6ac929b55fc48 df7e5cb855d1dd60f6efd88d00d9439c92fde3b71567cb46aef17c76fe53e51b 5c3b976629247f7f10f4c6d6c52846b9b4de1d7a258d84ee0811d0a417939e98 55a366725e671d0136fd0b711fdce650b77559adf56753f07c4130f18a36f024 c205931d4633f04b17c931fb00f2b47b8b7fe2c9de6def25496ebe5f61640bca c3baf879f8a858219e26c7983a5cc8618af19acaf1871fdecdaba355d6ed48d3 5fb47938e220e2eca446595c8396c75c28d0e180c2b3b6c3b4d9c9c1593d3ee5 ba26eded826bab30fba456ea53f5c34c97a1b5a985dccfaf6718d1231db6bf50 d5c01cedcbd2bdde6d37011766d8a864ca0f53943501cc0ab3933a86ac0a530f 434dd5d7e49617695b786c2ed3e851b1b76a5140369e2a390168d21cb99864e2 f87c29400d724f5c0c8e4e48049538035a4eec610a74d2730ed76176efbd84b1 ff55b2cd5d13d4d8da692ca9a0d1af104e1df3414e4b0b1821a56ccf676d3562 0cd6a4a67367d58f553ed01253582a17d8c85d8434b790fe0d79157e8b7a3fd4 27f75211c127aa1f68a3d22dcd83200fc3916cd1c7951e538600a31d19202599 3a23e03dc653bdc805cad9a038cdec71a0bb2bcb6de17e2db4467df3639ca7ee a1b76ca66834623b4a2445c7f369cedb1b2c0e884f938598bdadd245822ae52d 57e14ac6cf4de2ba8f4a4fa39131a40ff02398b2a2217a0747b4645c5eeb5703 0bd34d6cc73e4824f3b96cdc68b939fcbb3f3d64f85db0e2f404189d39e1e3e1 abc73c606cffe36f175a81afd69e3bdd7a6d534aa8da4541aebae0c5d78ff2a6 23eec063528ed18f12792077cda4ddcd7623b8ad7a8d9f194c0b25495d6d774f de751896b52bc0803437ec63efe0f68e6c25b17211373a6c083e9233cecd4c2f 88be6f30459ff0a926a4d7f57b9a71b55250e9387208b19b235f4e69511ce887 d64854d2a0eedab738b9155b41b30d425512d2165fdf68b60963e6586f0a75f8 29a1235869a8d737511ef31916570692eaadc9fc5a836419d91157959bc7408d 0cfe56ba540437788376011d248c5b0addffd76c8f183e1798a81a05995eca77 1d14bbdc17e017020d8c6696a1780ed8a92c1d25192da8ca83a0835ae6ceeecc 603114e5f9220594cd088b81a0cfe4b54fd73e0ef821e478fa1b3ce7dceb32ac a0fc34ac08c99f31ed89e5e310ff55208bc3fa2b53a750383992d460c2a12dde 83ed317fa3bcfcd2d5119593bd6e24db04b15669af5384d08d1bf32ca220a60a edb90d89c6618a866613546e755fb50ae469b95fc7148baddae72f531090e1c9 d29ec006b1a758c0cc9c6d3d9f2493295c574f90d6c6ee53840ad28c629fba2a 1e8eaaca2c4a8ff4f4dc13490237a0a97f061741c0b06dc5ce2a6acff153bf94 68df50cb1ef38e0ae678b4d449ead853d4845db7c1d41fad198cf2aecc594d13 e01e97370bb7b5364dff8611ae6da78f1a38102bd5e03c5e24eebf24f4ec00cb 5553e29cbf778f6b48e8c5e2a68c9bf3d81442e1ed81f25ec700a9e23a662466 23024f3db8eaf17fb8e0e05330a1c9760245afcadf2efcc400df7c7d17a2f767 a827106be8428f79cea92551f543d37393685ea2a286c66cae92f8182cd39605 0b08a56085462887c422032a20128ae61ed97dbf5e74fd8d93cdb1b6e19461e3 3b2c211dbd384da555d95b648a128b56ab6643b216cd0ef0b3efd2383428be80 ef5b4344e2685e2cd651042f3f03dec4e83d3fae8e19f7390756aac1252e8a2c 6874856045a450c60b61ff651b69e34e2c834ccc28f7f483485e43f2b7e619df 397019b0b5f8892c9cd5578270342cc060f29908a62afc7833f2132ddd890492 56cab4e804d55cfb63ce4827aad3984945bf52a980afc5fe65fe9724217bc007 516eeb63ea2cbd880702aef419a1a7d6b300523168bb60c1c2f2176cf1d3f0d9 0e9ae60794a835ce5d1988d7c461eb18f25ec62fdabce76be9ba7937a9f69217 0cb857ba94a45956dbe3c9634d5c0cfd5bf97ad640af92d0b99fb0544d7693bb 2095075d719d82294627cabd25b7dfaf7158c62ad211c771d3644c29a5e8bc7f d45ef2f378c76e52ff85f3586e3fab64411eb387e3a68d54834160e9d4f75195 28e2f30d2847b093194a3effa41f01428cdad1f2d20cfba6eb5139f9e0163a5f 65bbcc93001475bf68096f7cae42be2412e3ab74a60ee2f4926fe5c6aef83f0d a61e3661ee0c48cd01ada4fd2be409d2b461acddb708ec548cc1bb0f7eae6f97 d26de17c60cdb8043f11c087f8cbdf014dd27c7ca80a08fe8aeef96d0a1745d5 1a493350e3b85b91b47d8f1f52effbe30f2927f6f86b73d13a1bba57eeb6c67d abd5c231d76667750f9d4a234631bf3f72d067f1b88a4b0926dca81004b3d0cc 1a3e09ab6047738e738872c6cb46d5157a0978ba84af4e4f4436fcec61ab6e6b 29231906cfdd684e0f4f21ff0b0ab42e9969bf6d6064b38b735f90428296105a b4f5a4ed8d4169c040d9a4c387eed3e2a2282668f95e5d59cda02b9282432bb3 321e8195768e71c1859bc220da29d8b7315671615da6f7a1c70a65c08a1c435d b8b37d590b0147ab67db2bd9cade249369b44bca21e7027d56b61f375e643a7c 4f8253bd0d973bd1079b792ce8e714edfafc5b30625babd7c6c2a9f04a25f074 466cd2e93630e51c245a31c4d6cd4c6918374d45324eb23022b87214a23d4fd4 990b405d17c5c8583ba5b4967781da5456316385111c52d4c1761d44062eff05 19 47b66bb3d477a5b04351efc2172d60e25d7de574c6a9092d9dad8c760bbcb60816898fca364efc2d7b09d4021b2bd01d5b2cddde228aecb8ba95b0f42e31d50618fc5ec26512bf8286d0b6df805b2cecac7d721822138e6cd628e7823b221b079569d5acb33d57c44c3c95b473c81f9e6c508ae6d47ca4549df79ee1a4ae4005493383663459c326666e639f292946a242c6652ed0d804a0bdd9496a6b4f29050202ca0bd475463aa1894cb91ffb176e466df39c0e11d34ce231bd247484cb08559c28ee8fd0bdb4e94db9d995e3b6dee8ebdf263fc9515d99a555cbbf0bc806fa115a233832d759195a91fcb37d2aee13ba510e5c10dde8a4d33296d97b730a0fd97ea4073ae4cf8e0bb8ebda36bb58baf695d888cd3076d7eb5ee42ca28a0448c3663455792061b2b95556d3d6b087f20902aea04a2327704a8aaf07abce0269343896743263ee03f888c2c538de426e5d96e33de2d478f0949e1324fcee0df6ede249618b5a567d430d9b6a2a2f51c0d887b55ef4f9364c69b7f29284d7081ec2290ebda8dfcfb61c9dc988db38035afbf437ab63b4b3abba168a58bfc702cbcff10e2d992f1f3caeaba8376de5b8e0a73b20b2fae09f396a9960a95fa00248a774092660bd99afeb6b0907d372be6973a97646a4f7866eadda42bf5a40097ed147f36a3c8238f2ca734a153e2e52def8dd344dfafebdfd35bc78569cc706134cb21608532df9083c4e2df48c74f6e731558e6a244cd50b221ce298d3d1066f46091248718fcd9c45a6534b37a37cae75ea2a4591323263020d076f6efa00643b4a4463fca29efcddd070ee4816713eec42b57f059b7f4c556ae65991b709a1e7566b7b493d70d40c6b7813bfe2c127bb75165e31ddbd108f4dd9af0a5e06ef4b1fe7a9dabbd69e38b5816090dc63eaee84362a759a171c6ba361d17fc907cb5fc186931c35085b4a3879d54b4046b20e943dcc03dfdf764ed5ddf31db40eb912568d855607502149716b3209638e4827fe6ffe17322217df4b915d9adf03e2b87a48bbba16e3f430dcd02c83b453a9c18d98a00097a8b76ad7eace043c09d3148435b866df326835049461c52a0a027b7c1986a425608f98325e9b3f27067f96b197442a48120993cd96f8df852b343b1961a72397728e4bd398d623c30b5e9cd054d1bd6bb93f9208529e7ecd4474d250b811132a3f0f0d67fd40fc07013feea269de72c83f7bac8c7578807457e199c56b6352d3cbe1ace5ba28e35704b94137bee9c728c07265bdcb8db835f35ddf935b6d6bc03a1535f6df38a2f60fb5a703e07f4c013c9c2cda116effd81e06f2d39bb698653c716d1108c6e47c0c1eda383a446e6811a28c07af7b42b8f5a43f91874ea2f5358f0c12f245bbbb003eb9d288b53632b31114a332b26abd81593258fdc4eb6c31f51e36eb8cf98c00850e45e356eb37afa936140ad2f4a7ba0bed11433c8d798ef9d4b06b3aa038010eafcaeef2b942d5a5ef611d6b8e8739105035f4c3ef069b3692209e66c06e00fa07bb8b0e2b5578a396202d2e3117add3c9aeca2c95c742a1f161c3abac3f07a5d6cf09323a2ab782873af2efe5276a25c08d401c5ce1d9a2c7590f1b848f0bef3c40837da48d04ba3005efb74f7a6de2c689a210d46124f32691829443a3066c10190929c43912e0f042ecebb33f0a2b384a07d8757f62371845e5eac8d6090fe785f4bbd390a293de6a2ac8b57a14de60b014afa8f17de6e20059879aae0a956fbac23f2deac2c0cda6614d52837f71210f5b0448415071f69cbd751dec00a002f17a6c4adb748657dfb832d43a0c412376cb44bb363bf0cd0ef205c66d05c722d2ea1780617b156e531ee0fca7845a6a8b66ed0af7ba056a6d230e5f23012d3df0a011fb91f74f1d14487eaf3e77b0c2eceb7533c6ebe2f2a3dc6d655e0118b11fb316f432a72b5c3a28faaea2a14bfbcd3e5e391c3b625b7ecbda2cf802744996d081263741d9821dc1533ddf2ebe767dd8bf697ff023ae7f63c5b3630ea71e254a5eac99d0c172324b8f06824890222833c4a3a6d3f7127aed56480007702d4644b67c18d92906dbc980efcf693ec31dfea9ce1f9061ed3808578d7b07889f27633c4bebf62154fef766bb523effd4aeabad0d950b86095e91ebbcce0b99fbbd5ffae06c4a2afaa187cb9bf488b95a7bd32d5f1f9d08e04eb80852510df4c6da68c332a727f927a31fefc1b1f0c63344218c2a4f416cfa2fd7acf90d0c3a0289e0631060516e08910abb896325cb39e2a9293339b7fd450da494f14c0cc6282ddea0cc43ff2955f1437cce7c72617d85a3853f88b9814daa33039c940e2dc9de37dd680039e18754161b906f0cda88bd8a4f4753a802a90663cf10e80ad1229306fac3408bfc346a6f53a9a32487119980e8db237b5f9cf206d32016054c6278eb767f894f546ffd94c6d391c85c8d9e00dbec79ada19fc151a2e6610a39f60c64b7a73e24595856caaa1d0d5a2dc693038289a4369ee0b8bd6514910598e10cf6f68e4bd551466d0aa4640981b05739e4ec2d52bd545e3082775bdd0d2eadcc3db115a0fe7a2de0c583a4c769a3631f55d0ca147a17d3c4ef2d866c0f31bab53e282a113a55b7548db5ec963e4dc7ce58fe0ed0aae72902d8ca358c0f62b1202e22c1155ba86a7683a2ebedaebf5547cc574265c4452a3bf83664f5022c61662fa38267b1a36df9fac97cac0b8d39737aa86c9ec3703d4469851794066784f7243d37261b24952f5bb5a8ff0add82b0e017e247db0073e2482e00ef0e0b1127618077fd0bbfb20ef0eea0699ee9f9c9b84bb100120b76fe27fd89a6088e9ee3cef1a8efca20c6928c0cb498d387515c65c1b77de63a93381a1f642b07902d2533502d99b112422ae5147bc3cb014b77077a25f56586e215756dcf540e726f0c16f688faa65092d3c319767ac5c15f932d6af960e4a288de367731210a42fdd27b6e17dd7989b7fc208c597a8464eaabca174de591024a83d6313f250e9f30cab3a53e963e32cb7feb40dc1fbd5cfac3cbc03e6ffe816025798c63ca0d388747a2308c5a4506e27da110a1994df51f9dff4c3078ec266df02358e96506e32587a317ae37dafc381b18dee2440aa58ebed74ed9982cb003fb679cd7f60a60b87d161a706128cc8c3bd934749659170a9d682a500de195abda568e96350da68c2a3af5b120807775a44837406f4f2548a8f05897f196ad156611ce2d2a0ea7fd03b5e19df312eb8688c7d86730bc9cbcdb307936633eb4b2d000047e660e19733502e2e9de1b4474ab78de43caa7069b5e8a87b9fe942c14fb0d495d55045799df8f285a28770e44e27a20e7ca80c06c764136c4d6f7e21c7fb11303fc0f508703113e8e3bda762379065e243807d8f04a1ee82a5bfdd10ee3cbe7ae3f0c0377f69c949717afd959f7a7dd38f964d9b18759645f2efcdcb32a22c808ba0d13c679743b13d056b0b405cdad60b222d2cbf6f8c926e5055c1af6110b0e860a90a83ff0a852923ce25e3d41511c5c0c36aeffb7b26cd05f24804e82efc4f605434c53a239d12fb53df1a997d68d8cfc7604f86aaed1f6d7a6031db005a552094f390c4cf98475007b2c319681fa9f1b0564cdbd3be881a596167cdc8d76f70a11680bd2a47ea2daeb85d4dac3ebaafe5c190ca369501cbe21623e207e3ede0a6f0adc0d89d967c6a7fbffc4f257649d8d1d6e1b6623a18549147207040fe30bbc6c05f5a8c8df8d59e9de86a2228562378243d79aba40d79d7ca1e50f78670662f447e6561d2ff8493b8e66b9b24c4685ed5669b721c744534dd04e3916a208a02ef829dbf6a1ff4b4c538f39984b34828c0f1b38445e7faa071c16fe8ea50256904880545091d19695c58a9302de787eed93dd68689276222745e0d6b66f0855f58f712298de9c45593df3356842d9a5a15e9da10a2c6d59d759d64e1c0a01c401a226dd32222bfec5e6804f2f2bfda6e5cfdfe1341c27729ed480fac36505d0aa2725dae3346b63f56fea6b929faf34bb144bcdf66daa426cb3ebe2a8d905372f364be7424754755d9d2e4d384c8af4f046a082a3eeafa0ba68bb9aa6d705827f7eff085c961805eac36882cf54fa46f65138115fd99fd0424caefbc599078cd6ff873dac15902655cd0890953ac2d0147b6c65a2663a589df32123a8b4091c1baa35d69d6f99cf70512e62b1b27c872122d0d5444342dd57b63ae0992d0621095bb7dcc56899ebf6d47d536b8341eb28db0806cb5c4b480e97c56a6195033de18ec030acb08b6453b562e8ddad0bbcab5b4bf5e3a2a91f367dfbab0951031d219a2423dafea825e61e118259f5bcc1f46e51133b217b102ec8b3ce15920232fddc9717026b8d78c18c6f565bce766356f91a1dc7f89420f379b8abba3203c205b3a610dbf6cfbc4e379bc2269f4d7389cd8c6cf2e0bf1c8fecb4f1551a0b56c6b87307a788205800d9c371bfed642968eac96d323c530e49f92a7a43bb0ad23bed8e642670ea2ac1b70e74fac28f5f4e8a9c8356a259b1992a44f7e6860ca2022c7731c6d34640857ccb54ec53c85e051c67d49e87fc5ba6a35bb268e10f9e917958c72c091a170f222bd8eace45113b78e12edee412883f6d59c8b021033e9f00e6d569311d549ae95edbe49768651f16c36791faa6dcf346f223a31b0496d6d39a82b8495960aa56958f423cecb69a3dc5229ef2da50d002a57567bd0e411ef01549190a9dea6bc2849e143784a8469e928dda2db82a5dcce15bf02a0800a6c55186a68f6e94329dd05b8a4621f1a8ef0f87ac79a4d8f3e3462833ac05eaba87aba0ae563789d17823ca6d3395e42fd8d704110f8f0014b0119645500f0956463f5f19ff420bfaf94574297304a86e943958567f6f2398911e4ea3530fa0de3bad6c83de2c3a9838e3852ec17941c1a907905ffe3dc9ae6cf05116d409211d397bda1831ae225402f07e8ac3ac910493f7fc5f4c13adc64e17ba6f5b0cceaacb9344dc593c57bb5ed14123e75c8930a2470c240f079d6c002eb973a60ab868bd8ba803f66c889b64a2935f3044500a5aa39d65a6521289d3327a10bd01235316b8f29897b372f7911fc4ea88edc38ec2aa3678a3890f2bb38da4e253016af8b5c9b1764d4c7d40dec931326696b353c706ffabccc8051795e332efdb0f85d50fff295938fbc91fde7a2c2f8d8e13ed9bb05eddfc83aa8ef48c17366609150686186cf718416602f3ab5714a3217be8c101488689bbd42e57825905fd05d4f02e53a21b7aea582c2349e750370406e97b3ce971d561691876c0c992950db16cd05c786618cffaa8e9f3a63b9ced6782cc69f8425274a5c236513eaf830fd370b4460e5b0ccdd066e50ddce13779391d210cf4bf524152e92569d8ce830c1f0f29a1c5c9ea885301fd0abe33ac10858cd6849181f9982fe2c8f169da90047d61c3cef15c70784541d5275ac99402dea98a8471955f974d09761f55e4bc0150bc778c4889bd89842d8b563313d597a1c9f8f89ce41205be2257a45217f7079007efe31adeec3e1cdc479780cb46a8a61cbf88de3394edf91c0c368f424904f8e7748274b801e514ef3a9df2bd74b60c2d4553ede7acc29a6e18734e182906722e39106b6b406c5928286a94340b70661d1055d0ad9205a2e71839981f330ea0d62f0f80c155b9e20606e180119bcc506c98cd5e06867b3a8acdbf8c3ea0091cb0aa362ca0f716d473c18239a38bba97624b04d537b95710b260b12dcbb1010030b4537d1f7e4996b14ec7991fb0d9e5a9263863c2c1d72fcc4e38777ebf0f86bec748b36497b57459eb23bbeca2fbcea0ab111ceb0994462c7e74e54fd106eb725875c68ac9647d543d6c9421bfd12ff9d5538bfc26f4fd234bedbb1a0701916b9385013a0dbb26087b32a74df8ba2fcbb706844d1c308675f742bdee1c040affdf6bf4b2ca84d0ffc8cc8753f4f3142557161a02c43d38124c04a9c2c50325cc9bf144cd479c764b44781e441702cefea42c6977aca1410a003ba9685e008240546f3fc9b3956ae459856803a27193179e8e108bcabccd2c38bc25a66d00f0ac9f5191b7b215d695f3b0c43f8af577b26e4f9c1426a43051d22e5a4cbe0912b27395b6d9785c822060d710b2e2cb87b41ebd70cf1bcb8ac66928452f030dab293cbf2c1ac966d311a79711a9f1c9df8e6848dcf5c60424cf4f7aad0265002555686be44257961baeb71087560aee3d842b84970bfd5125010d5891f85a0065471bedc4db39ba93ea8b729e62a72c02fa78d4fcb23c106ac4431e6e9adf08122717cdbd02c1be09b34a45f0314756109e0849ea60102e39599376e7f57c0b5bbf2c0e71fccc029139ab6bea7ceceb47935c3ef3f844c48a204f476d99ee0b19589c40beab8fa1bc474b5a85fb8177e42665ffcc21cf614f320f2212fc370451e9cc7cbfed55774cc19ba8e4eeba40b4fcdfff8027721e25ff1ab11ea6fc06 -generate_ring_signature 19b59e689992b33510cb3a4641a0487214eb16b6c4ec84f17a725a64d241eb02 35404cf6de872e69cc675a0c374d23085e607a63b198b243575c3aaccba5110f 55 96bfedb655e4ad5ae088e1170a9f8b58daafeddb84a3d8922c7a695e82e66963 b57b0dd3ab098d2e5a1cb9df3b9ecdc5e05a5a79a40c818eaddeb80ef3502be5 679c0ec82de8ea3d0fbbd4f41f61cfe30d486e8d2807a7b2da091c4e79cd7efe 1859dc973eb9798fbf6c7cd07db81acce29d707577dd72eee64a3d5373103ff6 4749c0e2a2595df0cc7608c1893942e2bf72f1ceb3e4609d0a12737f3268378f 34980ffb911d8f163de0a1f2da648b989d2b38f41e9525b4fe2e1f5647a15263 8bb5ae4cda78148b7b0333f2ea45fb88eaf413880cce4254f6e84dcea809ce23 e02027de37ca5fa4a7490a35a52f26d3e1bc1a462f8357c3ed9db7f7ec1bf6e2 dc30251df7d13fb90afb8a6360bab069a15a7f18b2db02a80da3a3906b96b479 e72e6290ad812eb649b4a722ffa13919d2e4fd49ff4a44d5e1f8d80976553fb3 70caa5ef3d0766d48c6d9a6728d0d539290b4a68452876c9b8554590429da46c f57560f08f8f42d053aad27a4387fb09c0c914d921b518f1d158dfdf16a4e17e 4655b554d751125b469451635239474a94238a5e59aa3ed0766083e11ebfb9a7 259012fdbf5f5453f7aa98d6b021c4da9214f34f297b11e32f1effed4bb13909 81b66e8895b7411a2c7b8390c0b20673b1ae12dffcbda94d5561646a6d461dee c62b504e655ebf52bf1d72cf50cfe4b4e25a67cf6e968c939e8baa09fe05ada9 139ed705b0a5f440be69de7d7d3ad3a2996d36f8f809f02bfd42398b02e91dc5 392f1fe7ff4620ae2a3757acdae3b4ab011418e843153628c3193db731eca520 33c7d48405a1112a28fe51de2e6a9a9fc35669d246f23b66b88fd65480c23a80 2ecd2cff507a023c57776b03ceb8e75536c3ba9d734bb08672b7aca0a81dff95 4608c674e9421be71e557739fc5b2b868c8e46717d893c499a575d6d1f6af1a4 5e89a1023aca7015745d6e134222ae6d36574605626c816396755f0be2d68bd8 004f0204e19cfaad23af654dc4ac284fa89229c2ef95b9bbd5aec1e0e106fe02 20087f0163ca1244c5d52b7d9c343f4859f0fb8151f0ca44fd58e9fc28622cd3 d061d7f431bfcafe091420eb0bf49476ee690e680f63d2cd8e57ee04ec315d43 17107bccfcef930b408cbaefb05256f430fea8dc5fd4250ac9dd5f4ed3fc2547 ca339d35f0fe605eb0587ec378bf0f3bdb44e11438f999c1bb1c3c5637b7e2f5 2f89eddb111d0b6d8ef5a6a5c265c2ffc491d0e9d09d0017f494df2dbc360f0f 88719f6e415b781c843652d420fd554d291f2c0e8cbebd6d7e0fad80c04c809a 6e0b292ee1b4bf0767a7163b61c7d9cb7d4cd45276a78913b07b73f1c3c1d64a 4eabea46bd0266491d0228719fc8073a404fd25a4e837accd5251a61cc87c02b 2017496e7854f8fc95f17df21bfae2c0afeb43aa28c245ffa1b5047dc149e89d 24589b406b4a7698016ffb8aeaf5185993b8502e46d46e3bf37bb078623496c9 e8e32089aa49dfe331db6fc798abbd5c3f2daf7e1c98263cc7869e66dc7adacb 05b2f33d72ae54e95169937adc6420774768db8a9e3d7236edea05e4455e18b0 6a4b66dae9632c12f4daab911b0d8b9945fb75c25360549c23291cd63744c3ac 8f423495dbf74ee63563293a66074bf15713e1d3f3a16ee4d5f33d414bff6fa8 3f53e929272cc0ec8e023cc81acdfd50852273ee9274732acc069ff56e8644f0 f0a84ced9df533d2a34935af3d0bd07d544b2e84ada7c3143df14a529302f09c 39100e3dee3d1985e04694de6a49a082df90f3f14e07837dfd96298ee8019252 895b06215ade6268bddf5c5accbada81af003ff3a8326701c7c4b2e4af1f3f66 a99ddc831aed70624f0e17f8e1ccfcf5add0d30ff448ce7bdc08d6464fce9e1a 60ce654405b62dfea39278dfa49bf1cd1cb640f60d3bf18fe3dab964832bb7b3 0f755692573303969da6af7969a990f4fb4d0d5a22c1c446338c7aa394b8ea55 10da39906513a827a213081f345f6253bf93cbe5717b8add690d76499580ddf7 b363a3561c0abb151066a5a39b623c9c1b7745333dc16e3ff858b227588b525c 6436c0ca822aa4068aa89054638665f1936cd2a00ef7c68c18a200d5731748f6 310c66d3a506da4d1cab6649b14f875c07df63139e6c4424791fdd7ededca9eb 5137254f8aacf7b9b331927b27c932f68a248df87954633c08bcd84cf7bdffb7 1616d9caa4875622e3802ec550aea5d449b648ebf710a77d3c22eeecbbee6f76 56441b786f910a220f80a7312b1f58175bea544c2831d29af67671af474cc5f3 dbb337b8152363bdca9c7c7b15992fbf2797f113c6e035310becf222ab12b970 36fd79a1708fe543dd785cb28caa54f1d2224b6959821294d8bad2ba982ad4ab 745e169e91122070e4320302d73305504072395f02a6eff85884be79abce0c07 870a32a647e2db50d03544860d834c1c4666eba0e351ff13c0198bbfcfc89c46 f708b34270bb6c3817c74e5227e43d13c13ce3dce8162b8ac558da1c2e81be01 54 96aeab993b2ba87dffa35c2620687f1081c79fc15b8964fe58636102c6225c04538ba9df4b089bde96357f1b7529167f606f1d22a191fdb698b6688cffe0aa0761174141368451014097f5488c7e03181d0853f54d02e24e93267f54ca9bcd0d2298af2f543c5ef6e9850549e739f5e0ab0ad11392db95443f0dda8d3a94850df8f0198d55ee345c55a2db1c85320390e2154ecc7df786efd7f483b96b3a170de973d0ad93a6cce8c6642261b08a1f99da721d8d0b1aeeaaec4f26ce2a54db00cca418c80877ff5c5d391b38bc71f70755d197322c10c72536cb69c5d1d21b00e3df4614b4443d28db24d6e8a03e95cdf2467cd6741f017d76ce34f46585c30fc0ba9a74fcc1f3a4330a8945e848465f74a52beec2a4445773f4e651bd1f140ad655ffe8ed4115ee277e974881aa42076731b4198c9c32a5673b86d4a3574103ea525dc4e406d75869d30a3803c5d2b0c86c5be4236ff534a84e5aad8162240d35b62e36979566e75d6793b21aa4602a8e8b2173624e62989f409a914b97b50ac872b72eebbe0aacd4d044fdfc0961c9d79644cd13d6b87ba4b8cb3452e9a90d0f779527631294f7a6f630f9c6065090f59eef2f5d6f65ed1545c78c7107e601f8538cff77718952c0b4d14d222604c649b238fa9dc3201487fabc4dc768130d22ba9103b06c5584c3bfde2ebc8b9c71f339e99c33ca0f45d4b0ee69a3797603d9a8009c7e4d29c7ea7ff3b21d46e8d64cb40c59dabd2e72e48d282f5b6acd08f307760cad0f368e9ee84404acc11ef5384ecabf20dc1b244f99754a63b2fc06b18fe28e7c26b2cba2ca8adf264598c2ee67857ffde4d1ed34080bbb36a54801bd3cc4c04016950a8768a4649e05c941b17cc790b9615d04bd69a8a05540420a16561d7010e9f1baf7cb230b30c07bfc93d7fcc7a6c0be20cf62c4ff3ac12d01537a9ba21209f62ef0d5f26373f3ee755a4a7d7ed51f4cbbc0433c0950ed930bcf65fc192a962cf9c5dfcf8d62969adc89045750a6a1010f0ec41f9027ffc40a7019a9ec3cacc52bfcdc3f0ffa16c27074295a6464c4bd2c49c075e15b0052099499a34575d4b7445b023d7802f010d081662ad83ca601599f15ed6c8140fd02ca088b91b9aa0135dd250a7e412b7a59cee80d9c1c9adb96c8c6177d17a64407d718317c0c411199df2fb6716d8e870c582e299072021ed25769a60e3774f40a4f240fe027b405d6958241118d69224e408c29c6c538b4268125ee56e818f70f20dfec82fdc6879fa3e699ed77537ddefe769101dc6e9228cac80c7607bcf50ed1aa7c216f2adddadc28def5243441deed5f5a18bd64fad42d52d000d9a5cd07c462be3389c4f8ae83c0f6cc1f614437547811a29abcc49f9ce5a6132b781e04d2c2fd70e4d109d76e235bd755759ec32d2b858bbad926f7d389dd64ed971b0d478f0da009f31c34be549e50c12304ee6a7e9cdd49cb80aa0a191fc2c76dc501fcfec231b79083ae656e0eed52934f0e16f078e32b222e745df0c29cf5dfd205146c72d81ef244508d263053f8e9d5d78d9fabc095c970ec8901764f4b44590ce37a3d763ac1dbad2adc2b03f7cf2e71366648e9f33a83bc83145fb0ce145c0d5deff855c81d8d6db6fafa8d8d0dfd41a4cc90eccc66c0a78be5f2f7ced8fe0f1bc84892f4a08a764e2b240fcadec69dcded216d15ac6e006436d7474b0b1a007ff1f544c52886bf6592c3457753a60c7767a983876579ab60e02460a6c217062efe9cfa3cb22e648c370c7182b779241316033b7421bb25377af4e81465d80a7b4a5d151428bd4a6c4284df63d3f5faad79c310e26f31ddc8ac02c998eb7a086dd6e13ccda11d5d90961ac81859be8143ffd28224ce332460d134f1d702cf0c4d64014eecdf7a881522ec826decc97ac32eddb4edc8ce0f57b3e0c1d6a14d0f76eac2f17711261f9a820b200cadd522b11e4bc19a31e443a884a4edece40e0c658c9be300378b1108fa6ca8c178e65eae8c4e8881486d802705cb10f81bac01d60e58499a2e62435c653a41a1892addc2638756977196050ca196c64fe7980d36408819b9c71fbc83b1e3b753b155e2c4376738567da7f31fb75f26fdccb503edc4bd88f3701b6cf4e0503bffc578c5d112c6151bcc51da22e186380470900b95685260a428d08978cadf34b8c0c6499bae140b5a9bc5ab29dfd59ded9eae0cd3f1e02ae5a54143af1e23e12d8786febc69ae01730b1771947b0f4f280c5b0025363a6f88bbe38a2a13dab3ac92ff1b95002a81fe1c60a4272fd4ab22bbcb033dfd63cda389f41f75d968502efe105fd20d80676061835331ac556ab47bd6071188ac78b4cbd545c11f4d6a9ddb4df28382677e5da30301bca9fb95ee68a70b4059bdfd8a0e2739c22032b92d6912f1617387027d3b677df2ad8ae660ae0c0dfacbe6bfdef0ee9fc15b73f3b462652b9a28a46c9ebd1df5c5e8d386a43b59003c808fa828c76f556d5fca6a30e06f518194f87edeeb7cd6a8b91d437121da04a7147e686741cfe5dc9f49711d3227b12395bafce9def7b98319888ca1b85d04ccf772ac7af47434d132f15d201b95508a57cf531a69643d03edcc115444c3031ec3d5a5482d1b2943e433a5d3213287ddc363f64203c920049e6b98c433bd0b0f818535d7f72d565c5e474f4450087f490db02366339963859d937f85782502bc24604022f7a3380e707644219bf7216d42f85f9d10db65d44ad53d37bc430a336f5546c949e67aaf8c55d74d165f7bb3096123702872f96dd5935d8e147709f3b9934a9f54a2562d151eb58f603f0cc86afbc69358175a38ea8ca3a38f8706317bf73b80204c0e010eeaac2f076259ef551b1bbe8a6dce11aff53072aa2e08a25348b750163413ee37eb5653b53b255c8ab6f9c024d8b07dbcbf31e835740fd5ee986edc0638378198aab5eb3096571ffd9bb5c38422fad73eb96767ef980a47f0b27e1caab297ba2df2e4901f6e509f8cc583c74394b6e15fde83816e2e013baa1cca3e88572af1e1a2d627bc0046ba83614ed490bd3133ec82458445fa0d366928a1fe6246745361f2090e329ac938e171108ed3816e9eeb3d2a247fa80e539911235a92d83c2cf52409dde29bf433e6471439470db6a1dbe2513ad9db0b4d185865a3db9b23b42ac3b85dbc26b70260f6eb677571fcc7cc0e7def9c3107d223a558aad17d12b6a38b8b2d2fafa1751606a0524b0e5e4b78324298c2d100316c352d472a7d692a0bb3c47aa02ea6a1981d150adb3926cb4fddce5ae030019ca77e496fe4ae604295d158a2ef4d1acbf51c991e1fefa33502c0434aac6d0a4610f3791e03249cdcc28f52f23473dfe7bf651c53de381a64ba8c17592de408794478970be2bb5fa5e77f2aa3e2080e6bec490e5d2ba96d4e24c207adc4b30cbc7d9c6956c132dcf6123fffff763b9c7487ed53732b028b5b771650ba857e0f1a739d7343ab7ef4fb55a530450fd11d04eaa9ebd533815fa4a8e8210ad4800641337172b7f34c356ce0c7ef0fea248d2f5b92ecbad795faf3f6e30e4eba270cf0bf21e571523fa346935f0966ac8c1cf8b870ae7dffd6f8cbde8cf4fd126a07c91c38d7de3aea2f5246b6c6e2d45baeb3dfbaf6caaab1271c57b5c0097eeb0e6523d34601abf5bad92957419365dfa53dd33c1694f91a255ee5a6451fd3470b3498d34eacc0132518f74ade75deadb89c2c0e92004ce7349bdf0ef4077ea90a70630cdfae50efb715a95739c01735c1ef461fa66f41f337450db30abcd75105d3cc27692f04d44d9b02b387e55e61ed7a936221c0ca532310dbf9dac51b2f006cf2249aa834c5e2d59b264e077dadb62367851b8e9cf8f67e1905f01ad98501f03220a4fbc719d29e963b2f4bb0c08441c68b30f6aba6eb8a946bbfedbf3c05471adb66caac242c0bc6763e09cc61458d50af2a71edf7a86d055f72f5b870029aad9f7320ff3124119ebfd9cc8f5c1cb3d9d7a77b8903dc03b4e68c5dd9e20ffef22824cac4e54d3cd025d472686bb3314373266f54ce21ba4ad4ffcf3fc50c86434358faf8671fe1039260497fb9d2b83b5519d6bcd235b9e44305c472f1028b6fcfc369349d2bef66664e6f66d5ddb5786cd1f436c5d2307300815481c603c63a95c24ea4ac6909ee1276459466758e52a74a0d6dbe374047e2ef0ec88c025e18e97152dfa259dc82b43525584a37f0f9984d31c287c9c4194ef1adbadb07f8e9e5525f40dc1fc2eb66c982b851c5c18f1673d9f50b4fa6b3178802ca62030aeb6a71a17dfa87d2ca5d0fd3994a404ad861d0e7f7c275c4d24fb555da4901820b849c9ba5eb3ea9d3cc7cbe945e22739bff621b23fbeec57cccc1486760043d92b3c66b3f97988de4477128b596af6115533d319bde580786202a0d5a2b0151cb97530bc5a5482818f88938825065e19d5c17a3d644f8f97d035c6618410b7a4ff378477a10c53a9a7b1268a5f8387a038bd4a7e9f51fc14daaf7ef8c830cec7e033717b9f8fe567754813ab4d253db95dd3b756d63491c5d6ecb4d203a0b24e629b047f0ecd9085457ddafba19230f8957005c2c35c8aec41145cd812b01887e37ff98d3191246d9918ffd8b6e1912e285d5650d0b2a38a3bda948502a033ea9a70098548621c098d7e055bc4199066bb0ff476358612388c9406d964200a9c1879892bb6c4196d9c8f51c66bdb0f465cb4c4dfbe3db874694104fe0c0089c568dde8721f75516688093312523400955ebc2d3f51d1485035555b131890f831edcf7fceaa7c628ce50bec8d3d83b9109b64398b633f6bdf1a9f20b552003b9c0adcd5860bab47e8961d5c4ae05d02819c8a761bdbe761e57bfadfe61a509d4fadecb7bd14580284ae6f4e99cc8ef3cf9012483111b2203f3ea9b4f7f080d0f085cfff344e0b28b4d842ddf55fd8cf560d2f83e7892a4d111facbcd50db06 -generate_ring_signature 4672f905fb42dc0475983eb5a48f658a06268290809009c1c1b1d2c76fa8b2e7 1e95cfc5d2d71497ba502d461fcb7ea9f9768e229b9c268e3f8341a4f254990c 1 3d62ad8a5671f7bb33e660429e1a8d65f454ca409bded90f89d659e10284641f 303c8f50c931bd0703582650568fd4d3382117c521de689e1630abaae8a4440e 0 b63eeaac17ff2b3250f2551988df8db96ac6344c28047fc752de0a86d6953d0dfe32fa395601e090350d595c98a61693417075355e72fa94aaaf95a068802108 -generate_ring_signature 3c562fe4a9bf99c509f2e8d4032d42128a7e92b168392d9538b06fe8f57ffe7b bbf7fab81426cd9d7f448815014c590fdfdf9438021002f067664326bf4c972d 21 f766397c6872286d33fd553796dbfaa31e7b3d1fca071ec0a4460dbf140a9f1a a6a61c5ffe6b77455c458b3cb3e48ec99c70963f3d0b7476f2f3fd49d798bdbe 23ef9c123a46aba32944da02867fe6dbb83456fd81e57ac37c04fb398d748e2e fb3870eee10bc2a23e5cf82e0023c95d7de15ac76adc77a78e4a4c15a743b52d b433b1ea0f29c61a863315d234cfe7abf86106226da82d4de2a59efee82d4a97 90c7cc26068024a6a5ea19303358a9768440254c5fd395e60770dd114003b12f ebdfdeffcad6e468659e5e55c0702cebf169e0b6505bb802101acfa7936b5971 b558862930e7fded4b64474777d7e762f252d7e5ef32cc0862f259ffa0cc074a d10554549af45f28017be503d7f9d838d8c20afa543b0da9cd28f45089401038 939c678793f7619c5985f478b78f90ffc9b3de93a2aaa1674ea9a3b3f5b4f369 e639f8e4a4196ea5094fe047663e959e329ed2a9c5b205d4192213c5f3c45201 1b4d75055248504ac3c2821e2cab34035c4c28941960bbd177208e10499f0bc6 1b6e7a5ea11b4e4a042e2e197f06dbeba08163e681566fd83737e209ecb69678 209c34fe577f2dd7cc74706175211a65b87489553fb104c9da0ff1cf5e5c402d b1ce728ee6de1e258471179dd350967dcba276f7faf60a9659756e1d545811fe 8b8d736c76157dcc516cef83ac9318921e9d6adfc0e4a40cf686fe71504d79a5 96331d76ac46063e2d60b4bd809c91e77b893c8d9e2c53d27a1c378c20ab40be be0d16a05eaa11ec4ef8283d5f1b3ad1cae73883c059d855c7d0355c1249dd23 ae7000fefca7f670daeed94a5f3ad56697fef12313821842c0981271f2142d77 8c5fcddd3f4b3855f1d17487883f33fc05eaec1c7949aa9effcf1e17eccf8895 8900e46d54a0a2ead552e74ba2753b5c8d2b15e381daaeb48569029433d6e8f1 edbafd6cb274f37b1783450c83485489e72afb99e07afebd2853f9997418980d 19 998c597fadafa011815319d24942132c3bdcc700d4ab3d6af8d249a567f6bd0062e5a8af71825f21b31cc2e343c8fbd927f212b9769cbdd202fe8de4e6eeb705c8fded12288c91aedc16249ff6737a32cc97b3190659649601f12e6044d56f02a01687e4a9df3afbbc3ea3f6c154a4d847a14aad1c856f8d119b38ae408c0a0028a4103a17afd564556db21fe908591b7dd6af25760089fc249da1e4e2cefd00989137f09498c2ee3a5b56638b7796511367a6f114f3893b843bcff886e4ad030975073c6a76e3e38f0753ed2960b5f7f85ece867f584df5d164cd86150b8805e3667802880c08f55681c311fcad9fd2fea62d2193590354e0aa451312fe4708acfad1a9a8e492cf3a03418f7613220f662fd56d4889936eaf6e0e2e3c401f0d88812640f02576d42f00235c72bf7a5fa6fc051e58b75d5bd07e98ed501d210598567534918f09ee5a554df4958b7a0979054905c0b378f61709977f5b2bbc089b503abf4e563414238704dc7027c02e116c6880f42513268ea30673efbadb07021964f0f109e9d3d50b4c9ec2033e0b3bfec3bb6e7d4c5bd943105087755507556460633cc8f4b4876f2d1b7a37ce5da9787e09b842f2f2f461846840439a0fbd7491c068b496fd622d9bb3e4d64161d944c60322f3db0ddecb6b459707260000155b55012d89eb61c830a798e591bdfd7ff132302023bd89d77896a4ccf30017d244663479f9bcf7b38261fd8bd2888560997efe5bf6a5ae665b9dc803590b35c3e36d2b24f398ff7c75607088095d86fe956d26ce9aee10749c734c83b40abf88a1ab1ece77643c87851229645cad07b04a029c01b977a203ea9841bb1c077ba9a319937d126de3828e1fd3a43d33f7f925a4ee2487f81dfe4bb6d7e2a5092fb00260d1b6d95a26596edff3da72011a923132b3b8e7cb743947750e1a29061dd223b2432bb5dc6a91a3efb5a887907c201d2402f5479267a56bb356bbf50b8906c1550f06534c2ded19c9991b12dde68594d8787085b37c51e70728ac300754c61a0e658d279a102a6b9ae398d8804be338c518e9da6a9a641b998aefcb074213a1e45a946c4a9cb136d27e02c72be54be5468da5f522e73f52b43266f20e6845b6b2a2594f5239abf145b596b68455d8430a90785c940ee91b06dcee0a071c2870d3a2df188daf811a19ae31342efa8f1d5b7ffb8f72e056d5dfbe52430ea818cef5a80c33b21d34d1c4e353f930320dd1beb465e141e7d45f122cd8d1033212a928fa682499556f8b39497f31244ee070f128bcd0016cd8eb35d97bc10d9d117d43edf0748ca7c1f7d7c6cbfb43fa47b216aa166a5b2e8c6ab4da27df0190e0faff082ec92633eca71f1f53b61d4dec4828502841588eb1bd3d31c5560b563297de39119549e7d71a5656e24c80ebdd2380a7d435fe4e55b136345065001de98a6d10ca53244f09be66917bd3c9d89f682faef90652981274fb4912c309474f72d315ac5ac95591ed34d4c78c7ffb9c74de7e299d3c9515bb5bf2ce7a0832168d20fc064ce000f715560de40a22c3ecf058be09fd7d56d5a0dfe7df43076b9f5161d34119f4d3300b8e9a670d810681eae268b8c88f2f70b2d4d428b2074b60718054e8e943ee4db73faf8b5794175140242b890298ddc98e5ba9032405e1a2b6be0449f24468121c5c152a44bc3ab199bacf1eac52487db43ee73bed0ada3878ae39b6d179ecbb70d55039fc3a643496893b9114067ede6f5cc17caf0c4932e6f2265f815a1ee52721a3709b32cf6cf3d1ce37be9b094a5c813d4491054d719fa5e4b8971b942d584033b5d67af1357be6a835ae3f06bc26455ba1b60e6b891d71de1f5336c9b92747585de5c9dd005113cd54687d19eb71c1b5eb360b -generate_ring_signature f429996a2c98e465ed627943859394523fd3edaf7ab2a919b0d190789e34546a cb0dcebde38589ac7c0859ec7885c7e6952debb5cd69e6b0922e73eb31ba5068 14 7d8cf927a4b89584ee99103b0203a51636d454aeac07e163065565f37a22449f e5390b19dc3e87c8f2e8adf3fae09348f3abd92f936d3a4c1ea8700b29e31dd0 af63ef0b26af519197bc1c456474274d00301c68111a6552a781de6b5989d86e ad8a74a8276ce918dcfe1f633b4212d61782b38396082709eec6547be24cbba4 dddfd48e4e8599d65a87c7ffd853402dd1dd945df61402d6f5d1ee5997bc6f04 f5ed6a7ca50fa4352ef8b230f8f043d2109bdc4d914492233a24bd51571c7bb3 e9c6b1dbb79c841d2f39407336f0536b30466d76dd96c30634acfb4132718d99 06d9d6ab1381c4b6e3f914ca3273965aacb4479a575468aa84dcc088f675009c 4bca1da62da88b5c0194f893878425959abba8f1b59f70f8fc35e90fcf04607c 537de67dcb5b0515251c02ceefe5edebf29f96c3dfdc4cbdd80f677aa7a86feb 81979c19b915ed61382c40953dc698d9d2ab5487d8cf9de2958dae69d165f8ec 939b33105fbc1114c67916681405b0dffd88c6b9d265023f1889a0ded6b6f715 1da95472cf9ea935e2225531660b0340f21d8db50b8d7f9ef889ea69386884b5 bc01a282651fb0e13e062be2ae48dab4533bac2bfa7a069d281db33ece3bbef8 9f70dd260c97b39abfe0fd3a4773ea3e31f4d4a440c3f998f68482a6a580910e 6 49f32c1a4ea7f629cbd25ce611e62f3b1f15afb097b741be253699e7af38b208f4ceecdcaf0859bc947bfd19bca13eb0c4a79edbe179dadfe60ce6925365ac041554d97ca72204756d8094425d7fcc47ecb56159b9ba6ac3013f56c9ad7ff50e28abb30e9fb96eef331d2c30cf01a2e01228743fd427c161e4c406c952979d03683d5a04f98be9270e2d72a7e7508d47393d59cc245a4e4375836f5ebb50220fde69ddc39b6620e6fb367220226a779f9d48c43c2341aea8f494335ea6fdee0228b59bac066663f519221be8243748e672d8869ed6c4854bb55c285d984889028b4f3922d68ea29a4a78d70c7cf6fc5e0870595d6a1b637a0a0282574146bf0e5936ebd37c845bd38b24de7e811148c4056b75a073afa81a5b300ec67430940cc3d689e46669af53d9005e5ded7d4540e98d52ac6f8b94d8ca8b748de3b8bd06132f3b781124bdfbf03f3a15723c07b834c5e8e2e9781b9b130f4a284e850b073ed20dd04344d534a3f034cbb5071e827412c0dcf88af33319352fc128f0ee03ca8e85afee01e5c427e0232f46827da409dd01ac03c9c90ebefde041ebf8fd02147bb163966a12a64c353c52667967a986813bed287eeda8e0ff40a43f57f30c717d735093ed42396a08f82d55681f35968bd891c3a02460a46e6a090260500bdc01337b050806ee9565f9cfcb1321da58c19fded8de7dbfac35c15f7287b90ee07e538d31607c23bd31a9c53972dcbc824deab45342d41b5c3fc28dfe731f0dd161b6440fd69ab03d6a7dcf8dc47ffea48cf0624f8160a1c817d0b4d2054a087275210884126315d5b537490a67f851da27834a40d0289593c5cccfff3fdb0510721ae833298b06b1be4b23d77dc510255d7cd6284d5d67e585d0071ee3090ebcad8c7deb1ff30e3a04c4f0455f559351277b977c2d6d926a0c7b9c55bcbc067d4664557df0bb5f48e30873f29005b53a1ba5e36ce7541aad33712e92642505b5454547505d08a28b3f944721f4db925328997e45d25757e6b1afc18454270e71aebdbc5497ea2ca6e11da434c39954828fbcb0cfebc32662af2b37faa74a02c4e313a0ea1b35a94e77ed6fe0123a39516d7d7317937c1b1e6f2cc3895d6c0f93a983f7c0ba910d408aeaf7d4e9c0b775d57cc2a81af7cc1aec102fc786580b7a75238b2bd01a3f164ac617e58b9673280131b43240e850ace213c2c08ed6094bc7fd379452ba684f1e2ed6184aef38751c53d70f3b11180e1452a91ac24b05 -generate_ring_signature 8d14132e5e17124e6b09f1e79ae09c053856be240e8c7382f8d6c420f7904300 96eff4358f28c028507c8e7f0972dedb4330b822653b2b313f4730d46839464d 6 c616538cd58a741d5b8a384cdbb2d17de994f61c90f280f7977f1a485c2cd43f bcce7c9de27adf25424520a824e71ed3e00652f7a08dbab59ef38b690bc64d3a d2ac5e67b93192d3714c302e2c933c9a303d484ce2c69c242fba97913dddb0dc ea7b1655ef60438b22f1e7d37324d92b4b548aeb12d7b870f2cfceb28d0977c0 2cb5bfe3c0d79f7fb25ef00316e250bec871a4ad7f103b6a9d0c0ac7cea10375 0d5bbb4a6990c3e1c33f173354732dceb862bf580770829ee361569a8d77b44c 1196427b5966709ba0a1ca8b6cfbf60f91fd6a2c7c7e7a6609a63ee0f801300b 0 9f13881215597742d89133c1b5ac0eec371bcce401d3f8d4e5df9511db9e4b0a6d4240f0f7c5f3f51172f2f2712bcf11ffc49b7b18afe178235279042c432e08537b092b97f25e9617f54b31357f009265eae4bfd2a8dd2d8586b0517470d301456358a1b1ef9ac19879b6c781ab2ed5931760b1da7c6045cbfa8ac216a4130fef6f678681b13a8b38a5c34aafc4bd70fcfe996d29d00b7754c4b4a014abab0e037536370b390b09838efea5d673f1ae4dd5dfc832fdcf51303259ecfe7a6a0dbbebdac8e4e06ff5cfaebd35934c4ea095c6a7d9301c99a4db0f335daecfba0b42fc4b4274879e19aa1a612d84867fde040706d398d80b07e096a32f6c77ba0b281b3440a6552f990db9c07409b5813d1b15169b771d50a6e68077f3eddd6f08454a80f3321a3e77a56d091ec57547e95509cfbf41fd3ae364387073549162056ac4bfb296d50dc52ab4a73e32cba3f99d1bfa92fd0dba27fd3f7fa25089fc0b9f4233b85c338e10e96a0c755ad6d8f5073e19882753ddc2eff46d1eb2950606 -generate_ring_signature 05b70ec90350d0aacf2b9be53ea0a7e0912c456b4e0fe7f3efa8c7fabb1de215 db3f8c06eef1a728af728ce5e028068dbca392543d43b30e3408e70a5301e4bc 19 fd5ead415e17536a9a92d5d8063001eeeaf376a4408d3e4d3f3351200f2fcb0e 05fcda741a631937b631b745ef0451150d9442798aa28288c6a2f7c02d12b08b 04bca31da70f07d8e34aa70087d78dc097c478267db53798b1a4003ca02d9e1b 8001d9b613fc98a7a3fbeaa7382d71a02f566f02e1281abfb83888e3c83c6825 36b1a72a97fe92fff3d983c734cdbd2187f34763c98e85e9bd42f90541aae212 11d585e09e6cf199be4e13c2bac0b996a4addaad8b1451e5b0afe18b53cd941a 766650cb51e01a611c1724099e9999c60634e1a3cb36295c58ed35d4d8ce6860 8151bbc0a9b80790b44e6ce4542749de5e5b91171f0240b2a029d27e51c56836 a84a16dfad85aae7dc4f86f3576d396cf2867961b129eefba1c40a9b87895f0e eeb46b381844257d051435756aeb6e235b92545095136c1db72d84edb64fef7f 78ca044b9a1ef85d91d558d71046768bb5ca5e4cf1a97a693a51e25c3590d514 953c11498b63f8cbcd143d0515aba347c20c61fe47168e7c862466ebe875908d f11936b0f1dc77561fda254ce5ea7998bb1c00f4e3e69e6c63b0795d99961d93 5de09f7a41ebe987ea155d42edd7283ce1548191db18aede9bf0ade990936baf 26d83642ee3546f8334921be1fe4c766739b3e92dd8a29894e1e348bb6fb428b 48a98894200a4b25f10741c42195b8700bcb390b790ba0e01000d3477b36549a 4bf26521935253ad92ba75a2cc88b931d82b3c79fef8e5971f228e34168ada07 6a5cd2c7a32cecd50514eb46046ad996bcb2d1eda668a7f82ea105756cac2b08 63b28fc379bba0a51da8d41d1d89ab5cd2d5e514fd7ce0830963bbadbbbb236a 15af32d28b4350f74faba181075479bb3c5527f1ed7172c00ac28b703127b307 8 61339564afe2b84312162545e634784144063d993112f8ed45f4084d24affa083c5b72117d290735121aec439f4626046066e9dc30106c8b682aedce0e2c410d552e53a83e5aead11edfc421e2778e09500bae95687fac02b68facc7c5dcde02d996fcfb0c95c49b627d1bd3493c5648135ba09ae031a8303b87ed82ae746f01eb396ad97b5c6e971e63f425581d4d41ddf58f2d5d834e7c7c6229dd7f01fa0df7cec1c568d6b1efec96bd5267a061291b1bd4b85196f77232a235bc94fefb0cc4b53a739609476371765654b03bc91086ce943cb6e41ada1200237034cbbe08982830f70395059a92f1fccc3152c3fa18573c0936f7bf927907046f71a1260ff9fe34d659ebc980e5680ee03ef8228c76beacf36013427e6e21a6eafca14101d7fe079ff665a57ee84780411543981440343c4a9860a34a30d057eb98d44a0de3f58f1ff763ceac4f192de936719ea5015e604680db535f8299939aa1a03c0866fdb1d6b276babc2589bd7c009bf0f46c96dba0e24d0e2113046fa39c55aa003f61275c78362fafc8f1f880622f1f638f03bc176e4c20892b9a6829b43d9b0d791c5b1f356a31e2a7b727d38fd61fbe7a2ec653c3ce835fa8ced27381bff604663d86e9c855285d9b35213cda849efab1fba58f162a3db7ef7f7b7e95a90803afbb23f999bb012b0b9ac0728032fd6e35c55eb23856075eeb520ad9f71d710c9acd5c2ffa4e90a66e6cd02cb1e02de8e47431934802a042895f5dbcaed83e0608d6f44145caf24db0ea09648beae153d53aaa356643b0b972bd64d530692f029295984afdd6ed2dae90a055443106586a2c97736c60de180b1030ef84d90f0522d47943d6c8673425e1acba41b062c97277d69efc842e4e46690a69e1a4020f5acc288c518416192370aac4da4e984ca9fb8ebb1cf23fac7412daed53a2060272b2124f671fd583527c2c52de057718264fe3aed450e3050a62a488dc7c6301630c13e084d3f15362a4618f3f6393d888664d4865f32bb63834c71d74c9fa07bec0314d8b6f1d925094c4a7cf98ac84464bad2793009c723128e07fab983b0e5d2b3bad4a8e28b23de778e32d5e3fff8c813097ecfe8d1ee777c10753481f0d2053e080463c670ea38112dd3494f8a6d9c01d6bcc10a20a6665a99ebcc3100559a0fd1e43e29b7b4a922dcf8ed35ceaa7e04f3cf144e90db0d758cc5107600c86b289b70b54f87dca3cd81437f5e9f45d06a332cbb107d8ec01f3d1b3b74801eaffa35f18bb3fcd209f55d5f255ca4275c39deec9dc29dfd7a9831884acb000506b821849582959ab0279ae00513476088d532960b778e627a8a79c7d0dd60ba676bafea5c6e6260b2f38953d847f560b4661c0cb91f8b5bd113c297d35800e0a6ffcf2ceb318a25b93d7acc2057d5edfc955e5856fd5555683b5c181f9290b4da2ac34e6fca822dcf8e406b769cb85615f02c82baacebfb7c24bf868e5dc0fc8f8f9c5f371b2060b7a1707aba634581626fe4566874e6a5dbb5b34f85ac300f3ea63612aab3df71c36cabcecde86dc36d241d84e102871a4060018bb825e0bcd5ab727c7adb2c2e5042a41a7b5e7fc32033405534fcce627f67d9a61853000a09dcc2a6f7ca3b885ccde29fd51160ae7e778f42581a62d806c71ffea308c03d475b6e100379fa04a22f1887c94c71856a9eb2f1f0cb0529d10bf3a25afdf0b -generate_ring_signature 8e7b0209eaf2cb145700a9519b958e08189855775468f752b72dd90602caebf8 e128395e02c5766dfe8e16fa00f544a0f7e6cb5e698dc00de3683278a33a9d11 1 702d51626defaab76f436ecbbefb7a1bcd953735c1b585149a4e6ae7c87ddfec 9caeec6bceb4ad72ca57dbf1562d53ea0a93feb6a69236f8166f061d93f2c901 0 b0136b3f767f4575c4a02bc641328b2fc1843fd29e11636827fb5a7b04866b088fb2301818e9bc4a100ed08af0931a7738368b8761a48322267b6f24c0c1ac04 -generate_ring_signature 8bd72f709b787215cd41c9f7953b0287d08f4e6a73780b558ccd03c3934b5918 8d3904d2c864c2c47ded0b25d5e6b125a902b075738deceafb17fe51df3357bf 2 ad75d42030a6426aeab0303392ce21c936df265c5557d800604aa7c3c0e390e7 7d31f2eea57234b7d6d6f09d4ff58cc4bb7d4be04d9c40fa925706466bb82f0f 807012275c28d219e1b973c1ffc62aaf43bda1b49fe3ff094879f9676253b102 1 1e58a96cfdb229ff1067364ab778527299238252c2f5b6b54ce52b404a58b00d3f116e0a92e439730e43afb362be35141f8ebe7e836104938d345ac9bdeea2047932553bb0ee58017aa60a69a3ffdc6c52d5e2d918bb1553abcc0792423c51010f9a7409b61649aecdd855f500a37683e43772e09451e1627829219f49da7306 -generate_ring_signature 21a6e77355023a1ca3e620126ee0d7f247f9a814e40125e2586bc9c6773928cb e2814a98af57ee26de7edb7da847473008e128902c90ae796a9980863d8e1df6 11 c81a625349ab970763589667eb533b4fcc76f764e525ed10673e5bae74bf508d b2143c5206e143dd966e38b3d6e785a87b631bc5dab23df88c2e357ce6753e35 44f17cfc3e461746a121975377a05cf87c6bd41ec84a480fffbf045a4b17c0d1 737dd0a57c5bbb2c5038fc3d084871aa281d087040d47b5cc36c381fb25e0620 8bd71c4407f1a7e9048cecb474fdbb527f15964bcd2f9a06b540050b372bc542 f31ddccd182e3b9530ac13eec95786b47013c9566499c20fcb8b31d6b3dd91cb 074096dcf159f4a52337d58bca2b695a95f087125676381832a4547ae6161d4b 8536caa0bb2488682c0c5eff2a2cc7723dbe1741e3ee28194228235a363e7f6a 3ad9404f37be6a07cc9de38bdc1893c172c9674cb186070af90ca0cba027035c 9cbf183bc430c397a8eea5cf733dbf92f7ce3a0365319b979dd32cfcc3285cfb 817989a15ed0e35bbaf2d62d94a2a6bb3025c795f830753679c3773a8dcf6cdb f84b370bd4c5aee8c383a1cde66c5ccdb497c2266a6b15e53d4bb6cdc0535305 0 28d4938434009cf81d06ce9e86550a97cab92ba094d1c16c61f3285081061605a969fb42eea4b09bf670b1fbdd6a5ed130e6781a5b328e99dbce4acb1b77fe092b1550a9d385743ba10ce6c1c01e222334a61bd6a6eb03df16bd3941e61fe601632191d08465fd08baaf22f7b0f9741c2043c805f58a1481db63931d5b12ae0838c8911d1a3fad7d6721b7bc02ffb0af8f5a163bafc414f7acc54d145e4f430a58abdb5b50a7d944a0f154e50869438526d10c987577134689ac8d2a98b90c01a9d705db5056137206bf5d2854631769970e979efd3d23154f7be752ec3cec009d4a6284e4852830837f908fcd21fe7b8f2d7b9675841d14e91e35e98320bd0339c36f4423cdfc798d01950e5ccb547dc5b45ee27f578e4d22f808ffb37039092b188f0fd24eea22ef91cb20a57d8ef85db92591929af96e47641ee8c478140b148f56e466b5ad3ace2e200a8d900c77bca53936944de83f1e99e4eab716440ff391d234ce1f0505750548df78274166b79a7430d0d3d79a589e9f9f71bcd507c75a0b61bcae847371a9d38a21e129eef8ce0ca16bd069e142e88cbfe829ab080cc2a7d2e8fdc80d3fe0a9026183c2e1c87c4a47dbdd82a92be831b4117fda028701ef5c1103fdba5ef685de1c36750bb7324b12e1816457b329027bdfb1ca05ae46072de09885fd53a7c56f03b596988014d0797724e3404216daa4bdc8970715a79457ff653aeb5f8eada9a45bdb12ce7077d1b8bc4f8b00a83e08198c290022b242d7b1f2325acb8cd457774ac9f54fd12233a8006171175e588af6e75d090c8f4c9d44ee19d95e418d6801841e5a74d16ceb29313e8d6413caa28ec23905c05f3022e84c1ff7c14603540f56bec6f2c21c90f5af510dfbc8c6a55045850671536c95a00fa68817b05f2828342a862b5cdf318869bd45ee4146324ba4c50850fcdf100b7459fb95e7047090e824922b2ad57a8a0539a7a2e2ce9d87f88506 -generate_ring_signature 267687c04961afdc4dd6108ce46e82c9c5a60a6db9b613cb071a86dea4069053 1f8b194a5dcd594d315df03b43f6e6c6d8ae58b51fcc06678c93ef532a7c2ace 1 6bddec7e07d75ea37fd6fcb93b7094d1e73a56715a904647d5b0d572a6d2413a 83e12ef8c17ad0741746e1edde68f34fc3a241e9d612df464f282e449ecc600e 0 e6ab686ee1f55c5c814478789c9af8cc419dc6aad4a6f8efebb0355d14c2b80b9788f7a429b0dc6ee13d5f0744cec9ec9c69e691e9ac94665052bfe58d8f2b03 -generate_ring_signature 9310255e1d6492094731550312eec4fed0f54ea5d706cb2a611434e94de2f67b a6b30c2ab8c81f1e2b826258e3800503430825f7f111a5643034ddaefb4a9fe6 40 41d5a10bee397e496d882d7dd820e3854bb222240d4fde670ec2340931bd16d4 dad6b13bc8910f762c3badfbef8a686fb787b6511eb20e7f6fbe390036b2d3a6 100588d38cca1dc9c852d2f89a1f11a246fdb955ec2f73b8d5f8ff3e915beac1 b8b3ed919d7d75574bad2a81c5057b596f62796d96acea022784cb653bd4ad0e a0e37438540bd74fca28cddf345ef304b579ca4fb60457b02a9438dab0cf09f5 e5971444bb60d3b5cf42a088f0e318d2b3c22e356f97457dbfb7362d91f866e5 a159413d63e3466dc7cf257d0e5c094d0d5f87003c9bca4a00e0898fb137a364 38af861b033f1aef2c996952cd44a0120bc4d04d179e74b2ad9d21596a9b8730 bd0a348d3280f6b986c74e6d3703729374158bf1a069701f4aba16f73254c0aa c857108270e21b98d602fef841b56f0411c12305f38ff38d14372c8718f7d2eb aecae0afc964ab34c2f5564c220cda5182896dbca21635ac81026d3c29d0feb0 7bbdfc571e773e399b569f4ff2830e8d9b518d0b5d113c66c78b7f4286a97848 d4e44123919ce55ef7753229180e82335c43c064d515bbfdd16af5459e6fce9a e9454bb7137d5562ce7fd1a5d387441792a1d252af2e7f8249da3c143e7ca5f9 f8ba4561c33a80e40c7ca29743aaa5f9ff45831ea41af4e1835af4843311b5e7 562e1b85aca51bfe7fc455fdbc0060a3107836ccb8e72f197ebbd4cae6c38240 314d5ca7078b9cf66cc9a127a84346dc7a07934357ebff1f03ebb46a71c3b29e 15899bb4e5e5f5ac515e9202d3be847d7bc4a5d2f8b10606a5c25d8deea117fd b088006581f476a6f974389367a8d751e3e77db254b44c37007512fceaaabea2 ce728b492bc3de4934263add7ec0e8b8e8a9befcbf6d303804e8d543bd00935a b18e46b791bf0f12877386efa7dbbadf980d2f090fa2e59826a8eca0417cbb8b b1367e0a7711b395a74cbce696bb16102f8bfcb550ada075fdd28ae6f91ee820 f9d2d946be5236f38240e7750defb8a2e6f9c938dabc5773e8fdd8debc50d6fd 4423c9426972d73a83f73448e6bca19ed2edf3230ea018ea9cad3b1f1d76c4bf 97522c269b46cf817c95aa9fd186b9c09f9ab2da7af3ab55bd562d3cf3b51ed4 9f9380bdfa737fa00f31bfaa185c89ddb4a431e18f4a17c12afc3233e236483f e9544769948638dd359c9fee61317f0c93e4d476c457238c7f8741d4fdd20ffe 033aede3e0d40659cef397ad6250db441c97dea5c26ae4771a9f4dbb1941cc87 a436a016cfcddaf1b1f1fd9dbbfacd6979269f0772526309cbbbf7f40fe45920 d40b3ec269a31e412505088853b395405ab22a54d2fc0b7cf8f36d3746ba3e22 5127aeb4f206ecb11b191437e41ae3ce2e8734066ac559921a470bd656d56c24 89b0e22e57e9182a1a7d02ed51a5e6811f3ac915de5164664b296033124ec6ee 5937d8236f189d12fd6cd9a2ba68df4d5ba2bf77e72ed9449bce95cc0105c974 bccdc7108b06aae759d5b4d0e7e03ae74d5dbdacb6c5ae6935289e231a1bcb7b 15b5ddbcf9014f7f31170a82731321e9cbaa1d3b1d374ac8e9baba8e301fa1fc ece21182404939af7ec56ffbc46d8a72ae114945aa53baf864c7dfb925506b47 fec8930653c39e756c9ead78a921a02bbf3cd46e48053766a3ea05efce314417 bc04ea71c8a2d6774c477819f1e2be43fb4e8990b064e6c752756cd8fecd2ded 373a4b62cacd09fd6ed9e3b8354445b8316d15c11dcf334b28c2bb7e3458e848 c81605bf680bc260a7090ccb84ffc13e1f1e78fd94c2320642a3786f3fb2bcbc 299563329c5dc60a5689618c81e1e4edbfbfe96dd877c27c30e96258ed287405 10 35dcf7c756aee357a62bd3f7118f36e1ad541635cd4c3746c7f11fc4ee9a9b01ba4fe13dc2997be0114fc7c69aa617bb39c6ef84a1f1839b3210e3f128de1e0f8d4a4520ce53fc5eceb402d1de6230ccb68b2de43071137aa36c592a6bfe62056556ba6d14b5cc4f73d844cbf9f8ef77536334ca7984a7bd0947bde09361870fa25a6ce41f7ab117188545b5cf311b1d88415f2f053443b6c6285a3def1df603ce3d0bda6f4c05f9daf2214858b8b39d2f28df1949941b651b77e1128c0e89099440b8b0e843f0a29bacbe0118749993f1fb801f72c22280b4dcfce350c93b012f9867af2a83abe72d9e6ab2ad0e597c7b9e45d2b46f46588eda644ccab2a8020f6ac108ffd076f6c0516bcd0d550fff5da3b14aabd29f4c27335b0ab4932d00478058792e7e8da0cd843c3798a3521f8c270f0ec3bad76b20c7918622c18b0ef7f7c65665b2fc39192bdfdd372d7377019215546fd7d5499d67095c2f094909c77238e7301ea963097ee3f11fe8f4615c72db8f0fd8a550bd406a4500383b06eb1bf39d35d136bcc60c8e6b836234b79a86c72fac01b1b4013b3c6d81358c01c95fcb809430c91c9bfffa3c61e2bb89c06a80a9055303e59316191a6751d00f99465e18f23680454247d470366084811d7e1f464ca01912bc94f2cc624e0909346e8948f995d9e59f7d30dc5b6e40f3ae2c60668d5a79c91b1cd66b97d9800b438ca0e5ce3ba16da904fe02cfce462ceb9e8aab7a90e7bdc045204e6e84d60c6c17b4a3b647b6e446f19c8fb0c6e24a74e03ea8deb9e57999a532fddc9b8a044f0097570277084dd23fe2ab782a19dd0934a4b0f7378af215e345c7da9cd90a6d17b682725c1f50ebe09f2674368f725d6bdb7612f5a154f4c1fc2c97545a032290d1dadb3b21be2b9fef3aaaebef163db4f9f116ddfe602f5a39fdfb89e10d357bc61236d775748e49e6bfd51efe16f98b26ea130b48b5eb346d5591b2110650bb26f85eae2548b791cee8e606a99827ba4cba107de05c84afdd24b522fc02771afc8c206fc57833b8bbc5888d8cbc484525575afb66e70ab5021323743309ef0b032c1e16b039ead8d87b411f24a4e0be3fa47c21f610840736a7c7c32f071e062cb729d351b92311c2cd074ecc7179c374a0015b5ee84b493e897cff9d0a53b69db8049c710282db431a3bb00ff4fc04e30d4d745248812cdd4de9baaf07af2384d96b8c48e3254c65e646a2b9ae57476ba0c7eb75730a471ca6e997eb0d289e832fc38f939fe53162f7f39f22ae71c6b26a13baa1baf00f1519220ba004bfe9c21488408f71b1e9b05c9d69ecda5152a6400815b12d8b4db63b90375a0ba7bce7dd7ee54ae6f80d7e501ab6d6ba32b61e4062d0f3cd73b22b8fe9734e02403e509f00431f8cad1a39e140abc67236fa1ee226b62c54c8b729e0ac434b03e209d78244595bb90950056f0ed002ed9b7910f5ee350de05443ba6beab04e087706dfeb36744085f5202772d91dc13704390e887f7cd416048ff1151342090d6b665088d1c17286cdb3fc21430f00c06a1852b201c9e8f892f76a5c2a68740a57cd673d402e34bff1f2b6ba4332230175a4ebd0a497b022a14736d5d6d73203c9bcdcaf79cd226fb84c88295176715e7f717ae8fb623f9921eea1a30620070ba4db3b822878b6105d31818f8188993d31716893327e1ae9159b3efad6b0f70242b3525825e62f31faeaf23f455fea0478e64bd1e94de2a7e9344aee5e9e490e3ab9d2e49bda51a70174cc2460099856c820b9772b92f80ec7278be4ceaf670084f233618bd9f0105c19f44f67f8ae9e0f2284745935266a0a13f0be535efd09b2ba718e4fb68e05db1b9f1080411f3cbaf0e70cd0e3ec29242fba231c91f804fb9e3b21b18825fe552b55c8ae3e5f0f6f532724dd3df9606470327875f3250f5291d72160354ac92566794736330d61a2fb53dc2836ef05ccffa11fbfa11a0c29cf06602914637d6703a422bf2cc012267eaf10f9c0f1e5a2f29200c5ffc1031d2ea4acd4e94d6085a370a6291b2d6c03e85ec7b53b37f33dddf5bdee99fe008442fb0bf43c8510c46135a14e7692c986875187c18970822168c4636d4f4b0f7b27ad184bfc24d0a439c3914d4c4f1654b0d785fead82fe14dd65faf3e7550de49dbfb75ab8f61e7deaaee7aecfd8987e3331036b64d846f6c181547a68ff09498e8f3072b3dcc9cdc75e0dab3d53e0ec4ff9b9b8cbcc8f13b955dac8cceb082f235a784fa6f15912094941b823f6420667c83d663518558957908f617dee0e785b718f95cccb7a4e5a57cb9f6f93e1790b122a39cefd67d5e35455f62bb5031a44232614a697ee369bf5a2b17a287d7b2c112399b98f536b59aa0c1aa2ec0ed6f3e6cf419d072485fe69bebcd5987cc8240b40ef0d4b0c289ac5c27aa291018553cb7d3b29b866e1210fe18888fd30f9a750532f7c5fa040ad69d3f2327f09497b6670dd35e3ce93001795a469e97fed68e7382791c9f38be295aca11c5b06b6169e068b723faab33e667d09aed5a11ddd397b5ff36a7630bf7a3c4e6d4509773876dd25089c008c2f7050c063541bda43a85f9a3c0f6dbe057f28917cfc07b8727f8e56dde493df3d34a701f3d85bd480a57bd0f764bd7d3e9351e20e900b12b66263897e006da183828805d9a32ef7458651bdad8e30f0896398d5d36d0a88257c70b4921e21a9d87611c2a4bdad9980ca7c07f44d7cfb605e85d4d8540944a8890690ba252fb02466ad3d78aa12d69ab0c0da23b04f5bd1caa3d91e5c0529de3830893598202484452cfde5416fef5741780b43fbd1a0dce7abe3540a0a8ae162cc27d3dadc7d24b4a2eddd9946b360cf9b50de985789479206d5129308f8dbe1c001fd74d6489feb42f632aa4bf10c84c1b403c32f1f7595839bdca209a611945f3813b3a46f951f6fceb9026118a47677e8fd6d4b7979cc014ea3e40abefb3822d551cb89570772fa1e508191c0a7e43018b61d5c2e0fe30ab028d40671e982212222c3df945172c35b3986608e78fd187a774fb661dcfb18923c67091872163646b8fc9f7020f981b840781946d0b1c4f900e5fbf965ce0f1c5df800f308c5d94340fa52139cfbb6dfb0c459e050bd6869a7b51efd0fe2ba27f9e801464d0eab476d705c01819d0e61cc2af785bf5529c2275f6e163fb261c650250d5119e7418f44032be271a5ca6174454040427b6562bac5518d0004bc9a493c0c286f5445e0612188606243acb2d8220bc77dab3e8475813c9490d7e7c98b3208775b850b39580dfd45981a761b12408afff711907df44c2286bd18fa0a64d6081393638431da4888aadb3547285c544bd54b27a9d9b5f5136e28476fc789a30bffefcbd9d67e9963e47f8f711a9af038e992699dc63fa1b3a895b6eaa84478036b6908e55abc08f1bc2afe6bcf6f4b11e68d0ee5eac4c8017897f9226e27a60ead22365f569e8bd15fb85985ee8e51e0e8bb6dd70a4c5f0b87484ac37e4e6b0bb80b579ce4df91ffc56c3479b9151159e92f56316918499e1a950ce596539c0e3ecd955894e288a9c23e14ba741dad99ccf57d5bd03e5b6411bc64a1c4475603 -generate_ring_signature 657d817c2d4d9a393b1d9eda25141349f6daf11cc4d6fd7b8a1f279c12187e46 e8c62926823b84157dcb6145174f85084425a5c705ed0d37842430352451a394 1 6ca123601f7636c3372154cbba220818162efea295240761066b059d12148b96 eeb5e6852d87a410c402eae49f12242b35702470b648824c817adb253d119704 0 cee9b14166a77a6373b3d4077f1550d8a72f54a823a0aece5382269481e8a00b6d5032386581077ac954bbe3e4958dd777885fffb5588cdbf94f124b469f8d04 -generate_ring_signature d2ee8055b5e9fd86cd9e9cdeb95450590ea7a48e976337e8af699593d15d6232 cd23327ec509965ac07ac7f31509833e47fc56b96dda646223d917c02c292ba6 1 ae47e38a341217de4e0562f9b146299c0f7cdb971d314ace7522fd4fa3e20fb0 8c4730239e8f96e53ec2e30b856645506887527e7b6ea24fbff166a727a74007 0 6b65eacd2f7b2b882b7583dd6bb6345388951c77c1e00058c0bd01bbecc2ff0e33a4e0e0498ac03a17e70b0edc107710ff8a9d83d93fc05a3a833970c2ab0903 -generate_ring_signature 5f6aaa96065ebdadb91cfc017ad7e81c1052623a75dc979d052c43d025572d46 e96c5739f208695639dd5120c89672abd6148f185164bbf7e17c643f2441ed18 1 71b0a7ac6902754f376699e4526f3c9882787ef2ec7477dc2cca2b5d6791af28 0dacdc8c2bab9aa153b91ff96e7dcdd6736e8829632e92506efa068500ab4b04 0 bf9418ae6d50d252d0b743b10663324f0a0fad3ade6fd6e07b54e3f3e360af073f1110dfe23d7b3d6cd85f42d2f70bd577428ff3085ddbb3527a5c7a77c05307 -generate_ring_signature 210c782e19ba6264cb91745cb5cda5ce13b234ed030561310e88f6dc2722b483 b439238aacc9b192a9d7d1b73f845d24f574997d88c949d54d372549419baa7f 225 385d632938755662d282c477ad5bfb19bb1d153e5815077216a4c4e2b394e211 5e180c966833b87b3003a824abf2c6966441760258c201f7002e823306a9c2c3 5d040395bd315a7bde66937473a7d96ea72829d2f2f868258edb4cb265aec30d b5f068ea2e517abcd21e927c7ea996c5974cb5c681805ceeb348244594a342b3 327d212984e2e84026317ccd150142a955be2dfe34d19e194a4357bdd221a9bc 752baf4d17686fa71a2534a6864477b608ded4d869f847586fc6ff4e4d266255 05c39810cc10183513ab20ae2caab4448a0429f50673b239286c2843b43a9aa8 f60a2de08e5a77b7e56777d6ef84a5b6b546e6934cfc3a635378c9af0b7e2f1b 9986783276b0dd845c3b0c56ecda1b29b28bd7a3ea155ae6fab4376012a40180 0b3b7b391bb34851c1720cea7925614177f278deb37b16d52197fe8aa45118be 9d41a41006737c046947fc176183ee7baf4c37114479616e89d7517b9d039a56 d057fc6060c31d7629edc250791ea60c9f49bc5ca3872c6146030bc08ceec217 64bfe3083a136ae58ba33130ffd58a60b338245e368db66335d4844bbb0e25a4 4b7b5ae9dc755559da17de7325ad60d80b4f442bf508e304d2dfdfd9a3853a5e 2a5d589b910884a9267458678333e8a3818a71a45005a7aa3a9e088ebfcb88b3 eebb3f88b3f7951e243d7d8db9003edca9f0d9001244476efd46074fbd904fd7 a9ae02114f76adcf94ad23a9079337f1d1edfd74fff2438ddb47d0cabc1f5af3 db9edc21464cb1d6a8001bbb2933214b5ed3a2824935d63c05a55bc5b681953b 5afb033005752c35a5e1fcc95d2341640f532d11107b3a54c212b610845db203 8ec392866d432fa11d21b4293ad1ebd421fa859ef7c5311eec1acf73da95f366 2d372298a9b62e508013d83cbf0d95ffd72fc8fc6fb0d623db98a47e30640eb9 7d13621c703d7bbe44a196819e192422a9211e53a8a6ee138d99f541c7c45bbb 00a26e1fbae064a1c2c800ee32ff1bec58ea68e6bc3d9319d0e6f7d9d4858943 b3e674609b98360bbb85e1f9b80b779453ae635c894adda35bd100e7c6b1879c b9fd8cbae04c271e2e59702508d371c15f180310b6b5b16bf78f92c30cdf3451 c7d7b20e3bac8ac1a104ce0015b29d6ca9f66e4b921f3b7760d14b0d0ef806bd 50771023cdca6100850cdd2f60cabab98e9e42e6de099a1f399b898efc79321a 736e41ab6937e217c5ecaaf37eb7bb7136e8f9e29089c8be9567e8ec9bc76002 52cddd12cdf1c506e78e29591392fc24e7be5b9c5b6136ac2ecff15a94fe0768 132e70b68a7ef9c5f401b812458745e73c3b1143fbd6d548266d446e8ed21800 a5c2587a5b911408527f894750bc2fd3ad05d88fea96eb3fc521ce217cea614b c36d3589279a9754ed703a49e284243064bb8201823bb1e6c65ce1f1cefeb3a1 f352384e3ee128d4d9f5e53677e193699a4a0b32b87b494abbe9affe461c8224 623cb978cbe7068f3f5573abdbf77acb50f1fa21456d6c426ee7d14d925cee2c fe4eaf7646a7d7edc86ffc7bb3e02ba1bddac47517eb676a73c8cba574ac7583 74564c30fe7b0bed8908ed7550c7a1c0e81dcf9972c5588223a5c31f7c5f24f4 3957b9c95219d16df5af553548404c6ed013feaaaf3311ccc19767979f81afac 52e16912389caae211a4ca91048df9d62541505cae921b1adecd1c92a5e3106f 9aeb3d3ba84f8209795c9fe000a920d7b58e361c2ad09856e4b385cf1d3fabcf 52e159e9ed060899121461c71906a83f47c1337db4d487590c1d7b742e23e29d f4042896920a3546282ce109658cf0f1535d98aec685a54bb653bbb52f71f560 81581d762fda656949b3c072d157a16cbc96e27f73410fed70cc2d816ab76632 01d2d48e6e5599d24534f3482427eb4501508b8c1068583f7354074462aacbfb 323f4706c986053428d87e580cb45426eb38eee25fb956345607f71f76e2af64 c48ae1b3e86ab129abbf82123f987b773cda8a621313d5e3e12a82504aa4b4a2 764a1d46d895c15e2de0d8953d4a349c11ce203bd8fd5853c7acb497040e818e e59cb3843b69071cc6a876a73433694f55ad77999c1f2d9840cad6f4d46cddf0 f0c7fa7f51616a2b8b3d3c66fcd1b999ce236223d899a24d21d7cf51c7f8320b cf103bbd9665692f9ebb884207be5d48260d16cc118184ddeebaf8db303372d5 718247883127bebcf88b3c0aa856d2c82f205f0ad882cb40fc308f011d4c6ed9 12d01937773a71a29ddc4fcbe01005e7f3736b25414dbeb69f1f15504d65cd2b 8570f352e0cce7b04f9a415cbf78ea49b22c6dd1e199d2bf2a36eb7863b52633 72f0a2aaa9927f98bb985d97aec6cc91caa36f06ae37fd49e717f3c465943bf6 955bf1291296b84cc7f1a01a9d38145a747cac1f901739405cc358c1a791543c fdc3c3ca79c46bbd3226776dc9ed47e1ff3f3a7748860b9894812132f0290cce 5277b50bcf94ad33066eaa0d94885009bb6a2ccecc8748ab5d2b053d1c4bc8de c82775ef48623297b0ff928b04c03b1502645d58ed9c111478bb9c158a6245d7 88cd50b04d60e049714273798db1af00d5106280849efed1a9c1e37ffd97e253 d77f732b38cb637343ec20a66da97c5b39c9c3e8ff4b84a444e3d32164612791 cab9c3f461b91e213008d896bba641ad24993f98d1c7c872626c00a8b7c001ca 4c62c3d7c18c0b5f240c56b6f20e1ca4eca30b7d8806f66aa43f5df8a8d382ac a70644c6f3c2cabee8ad982a2994c09e81962abdc94f0fe48a5de7b155941de9 3ca3119e94ef5a78db0e52495b37ee42d3d87917cdee4cbf8ff53989939b626e 0df77c493d22bd419c3db7ee8f464acaeb6d83d607a7bd5a6083a62c1b318f94 011fdb5a7173b0924e03210b8ce3d0bf52a5982574faf3b110739d0288e5da3b 3361b6da469b5eacd5a5699ec7474c764d1426ae5caab18133252b5d186c1f41 eb68f27174f1dd2d342ea6be42eb3635fdd597031142086cef689f143e149faf 1fd91c95a7eb4552eec9f60fa61d3f904ae3c8799fa1a80926dea02cb8b69fcc 2fdce58215cfcd09250e3830dd355ef53090b5f8ea6c65ea7db805d720ead1a2 b1678ccc6288b290116e3d8341eb32e9bdc0e7c4bf1872afee58eb9430f82c45 48eb663ff455d22f43f0b6cb27f7d5eb0943d4b60b683717198002d7b76bf4c3 2423895ba50880058a75cbbdf5a535ce176ec31a14ab32d9de4dc3855156b8b9 06043986a58cfa6a7fa0668668b39f297b00dc2aa7470bc9608021165442b15a b881c686c1b423b1c36eca6246e5bd5d0dbf2f1bcba8462a008ca7dad7b8ce9d 1222668bc17ed0be0cd5f58172d8c058cf3869d26b201b850e46e2d1ba6528d1 1bfa0e56cb48d57372b35238c12746ee52345d52526ebabc79bdc28ac559f1ac 0dbd0538a75a12d385837b24a7948bfb3e7b9ec2e10b05516396041628e18a30 99910ae1888e67a0de161a454574c19c1f008f1c8559204e575db88dc80f1a94 1f000d2ec665610f784536730adf1b3e5b9b9db13a42165d9544acb881b0b92c d4970792197ccc02b043555225c505be8495eaf84b6a70d55139dda4c63b20fb e4601ad66a30cd9bf6e8a7291282a91731c303b459843c73d6b3538bfc3656ef 256a7723b4f9b7d7f652579beb53a1de9e7bee8e75833cf73b259452783f3251 613669fc70b3044796ae69b20a3fb3ad32f2e0e64d789a00dd880ec974e6afe3 0a9baa39c17da06593fefecc921b5a56b08e41dfae48234f0fc23d8f6a376ac3 8fed0f0e6b4d42105fff2fa2f5d17c1a29959a58edb4fa15f137f0676c6ea7be 630f0d0f9a93c58f56d9cd2f6ffd88e32588b5a2ceb0e1888429d3a38db25ce0 7e12a83617a864086ecf6b8c440f108ecbffc96bcbc8df5f3eb3c72cbd5b4e12 d267956f1075d0755c7f76b498b63e7f51c6e1c4902067d3be637346db102f1d d2e828db06faf7dd49e7e5223c21231a3b4cc4c3342cd71a3a92f06d727214de ce057552eb966328262a82f0106561632761a1872a5348c00e2fea537a946a4a e44b42268cb4127b29e47f5cc6499e67b618afd48462eaccc13477423abebca8 f9f0712fed976ab4091ac0dc3c15b3c2dee4bd54eda3e08c6dd2f9a4e4acdaa1 0e65a84589f21ec3b9ab6aee1d24ac1be5cbf7734450bef6f523b1052601341a 12fee1a3b1c49e1bea073a7bfb93c8879582febb9c28354ed5ce0268077fd176 4bc6cd65e4451fae3817ae3210d8a59303520d0eb1fe4c5d5e43d8466dd784d5 b96717f2b1ff0ae2dde66343dc8e00268366d0e8688337f6ab7d18508968ac8e e095f6be7cfbd4143c065b3f74abd9efac0552e91bd66c50fafb075534539ecc 750c8f66ef049a2f66dc488f51a125873b97569c692b9c31040bd4da3759d5ad 7612ac603bee6381390e5a20fff937b2532f880a0e51671f2641b67d58135f60 ebf737d8044309797fb792a059b02311943c12876d3a5c1384166ee2b717820f 80849e5e6d4f4415d77a52dcd6fa289881920aee19735d03fcf5979c2b001993 c97589e7bce4464b1f1921265e8ec6af29040970f09f2c3475487e7ecf1d489d 9c407322aac4ed8983ca8b8dad19b211f0c0770195119157fe44f1bfda932ed9 31fbe13706f2716dc25b149e77da52c1ecc55b70053e41e8bd92221b1b385783 b6ff14454cad1917030df735d2c9220b40880d7fb0ed08841e9e705eedf9036a 06afd0020bd36ca861f8202223febfb21eb5c7e338c907a4ce654e457cb2a315 be6f0907e14047eb8fbfdd1f878550770c6fc2630832b81948927b6f80617372 163f776a0f464f59a6fa6bbbd7e93aca17ab04b04b7ce06d34226bb7e900d7e7 f1550dd1d473f38ec080a6dc9872442350179aa80ebca3afe3286c61b1ab732a 38610d484a664c9cced181b42bb7a96a076921437de67f6be1c922e07ca7ca25 5990aa4aa00146e517e50f3eb04336597f2f8deab18ca1439ee5a90863d4a72a 50d7699edcd2730a75ba37516553f0548e2abb5044ea89cac8851026aa73221f aac4a77bad6ea4d5dab8b739c0a01c9fe78dac1fec94fdfb1168bd5cd59798a9 95022a31b8a904b2ad50d8f60e7779fbed16e47c07b1ea65c19a13ad8ada2291 439ad6b57a6dc6b7dbe15edaf44d7582f0d6b316ff823d41cf85ab381d35b860 38bfbeae4653dd4124de9a1a3e53bfa3066d4e5961412d6c1de12cf77d27fbbe 55992a2b6cb34982966bd89eae451b39c701e79de02d7f3440a8c493a51d9d9c 4b44ea04e75b073a4d597f4d1fdd414179bb7bc5b8ee9001a3c3313eb7a81028 3bd990d568b7f23824d36b441004334bc7d88d6552e1b1b9a6f772ccd02af8cc c6c13ff416fe823ac2ebdd4d8c96c9dcdeb678ce832218eaecaac26d227aeb93 384e2915e3003d1e5a32fe42c165eb31ce1cf2f7972ab7080ff9dc95146cb44c fa79bb9d556b1063924ff37f150aecc8590ebf234550f4c90135fd301010d020 a06676590cf910a41cbe07a80e3711ecea47d43343eeefb106027aeb81f11fc1 359028b96cf085cdd4156f29c48aacfcab8974c51e31d1920648d844c48503b9 f4fe5c34eef748c3c9a3dde8eb3a7cf88f894f7f29275ea11ad9d21c2da7487a 7af8f1af63e71d95ea3c26f57a9a3818945cde9f1f70c77678e501a6ed2c5b53 df5347afdd221d101381ca39489ae4a40c79e60dfe914640b7c9a15695bde31d 9d68f3e4e218ed9d94181094ec24d78d8e5e74462edf23a04e0f5c309a488ea4 f69e67c58bf7d1f54daff66bcb9f967f4a800bedde5c1e8e3388594d2b6162e1 4e522383f361282994b5df8bec583c9076915963c387cd8fb79c5a143b77b20f 649473a9ea78b524cd53b328a181eb40c0cc67f93545baed9fb9d013a218829e d3dc41dd315b7390789ae65cef880d5b87f4b6f1806877f4828313e8842fcd02 2f14539f942ee6e9b0f10fcedffc6c2928737cdefb8ec12d1100296ceb74d56b 9dcb4fea73d041a83daf21a9cf9cecc054749ce61b55161cea8533d0ffcfd66a 8683d13dab4da5823053c4623a860b0f30990ee197a528780a276f81c70b639b 700509bd43a4d2b1cbe027b952587f67bf07617ef194f1d182718bb1761ea6d2 41a1e9fda04748ddd5fec36d1178167776ad5fad58ca7ae08c83ca4fba14897f add8a8ea5b584b8eab15afe856925109b90a73f21700ebe6be92064968ba8766 e6db06fece8a3c69c8345ebcd3a5448348e3ba7b3fd15a05f2eea0ee45783d5d d4c104b6d17052fc549dcc764684c848cd7aa470cd478752b814010cfe8c31d4 e36fc9e9c235d35b997678b41b2702b931498e32d22911d3c47aea55503b0033 c46fd9dc260f6d25ceed78280b2d5bbc08657efa5f7b962e30e22ed3893f768f eeb7a4cde0a142ea63cb9580b0938366b3b95324d18b17da2be4d2249106d3ff e4987600c30314a65d4ba41c132d4aaa6df9bfdf43c9f6edb4aee71afb3b1ca9 26c450378bd5de84dace9354dc11164c0df30a66c2623ffc9821e9ba96573474 3768619c48bbe89a1929c7d18f71dc321ae9147c29e1e9823e15389af035f1fb 65c1b6c65fab69cf2026b344b5b0cf7e312d8554c8ca9fae97b87edcdea5f945 79be69b0f629b18930c38f588b76f86a2c91dd5f8ff77265c58004639539767c f5c4443cae1a272c3ea900331bc349b72f7537e4ebc4ec9995a5388ef922731c b71e544eaa0ba427d75dfa2bbbe03694da48ef2be247833d143f81812c7b5a47 b7b2457939c77d5ea8ffd71ea933e4efe986ca8b455e53e0ae148b4ebc4d48e0 10fca1960f5ef371ad93ba33f223b7d2851ec0c9c76f70b2d629d6581368f90d 988f89d0727350eb720066e198c14229bd9c6b30a4313419df9ed31503ddb02c 2f81e060a1c1d035ff2cd062ff432329b6b16dd5e5ccd3ba1e3c64907ca41351 335def56d9aadb5e550a9a87df2c4171ddedc3257cebd96a88ba2ed0b13f7301 1bfe59272dc577a9821aa956551cb1f045c67d4b9228a04e0b4449a8b462ff0f 444cb383eb3f041882c5ece5a3ba472f6cc4586f101c63050d8ca8e4ccd0106f 39c3b97d1ffcca4f7d0560f49f5d913f67a3903789743d29b49b902b897774c2 fae6d7e20a850723d9764e97e3856dd3863329e66705d8d0ee2b9889aa70c327 1a095ec877ccfd6ad7c098273feb65d098e1f573626e57de6ae4dc61784c9042 d562adedb07334daa8ef9cbbefaf98d64b24c9741dd72445a9e120e183a63c6d e80223440a373cda0d6adad064bc2148b320113d7406e1eada98f1de93472b0e d15f5a5ad17f8a3ba30847d4e85424da0114eb96dd2eff269cccb4b3cc364591 48707fd6560c4cf9cc8222491d45810fe75673ebe2a7de749e9dac85242c1104 8963b85abad1a6a24eed9b63dd46902766eb8b0dc13d02b9e80e3ed5dbfe6511 49d0fe1c91a4037348cd6f6b8c2bddb8da46214c33e8c39c0630483b83305ab6 f803ac0ae722d368b352c47dfae3852904bdfe9bc7d4642e1126a482d5e9eb72 1084f0fbc396d6ac455df3ca4fdc22a24b8d1e00b3f904ffcb6d2fab8729590e 4314465a59abb470b1e05dd90925da4035ba6aa20ea102c56b6365865cd05a9e bdb6292729ed47f044cdc357e7081b249a275ba904149ce9719b57dcc144269b 033d157a3b91aead40b8a4f029b61f2a40d39b86ff38e8e57b52c03c426dd10f 138d03ed71356e08e6ea8d29c57dd8b2802054587a058c80773a75bf74bfe371 397cfd01c6fe89a34b41873338fbb70b4dfbe8a954d895e88cc87ab2cbcd7686 292e2bc17fee6d9bc8f09c710411605ba57f8534063ee3608ef39bdf73ec4db7 8150e00b1e5b68586aff8612515be21fc803344d3d0329badb0cdc99b80a1362 c92a75c221dde7e996ae5f8ea43a5760563a0532dcc6360a60dcb0c7abc13f75 49bebc69b650aeb8ad9b8382ecdd65a74d640153ee047060db71536e5166e58d c03564454188c4a7c29c94b4d128246140bad2a621e400137c7c8566c3ed98a3 75ccedb4415bd43430e80668831b2f667bcb086778ca43805d9b67ebceb0138e 47a95d5a7fa6e64dfd42fc92f103795e8bb26d8548cda156075d528f4ea79c37 ddb756c6e856bf99b3cda839a95509f50a9b18b87c8d9e07395eb1f37f351004 d813a9adfed2a92f4d2a386acba181fd12d26e8cd139e67e39bb1a45775b3f8f 36c6a368a17becb5b42b43855f1a1ec9b958077077a9ae8b2b6186854f2d7b96 5698732e696ef2306c582231ff9d48f919f4f5d59bf11df3e2bc7a9511a8555f e0f7dd725ddf4ca25c9bc32f1d6b33a562325573cb3bd9f9bdd03eb15a568bc7 6ecd766abcb6ddf79fbc0b7b510d7be17bf5497fe57e54fbab5f44b59522eff9 29ccff9bd63867d4bdd3d99c79bc54b9503d3312ce4792f280da7435e22c773f cee276d9b36560b5078d93780431258456ad73e47b98741c4d885b7e917a620d c465fbc35b063492301a77e868a24728a238335f1eaee5e7c94173fd1d5c2bbd b8a805da943c09244669e79bb62d6a58e80e0cdf069445905b332e0ff2e0a4b9 081c277c8956e574ce8315e55a4d1bc6a1f7084e3ef79c565c5c920e09ccf7d7 62a0c62da5b16a818926f5568bdb97370612c34391831bb8fe60ddef00333e80 e98bb0d8e342ff5ec1041a49101a848ca973b3143373404be9a6c2045244abc6 4667b53e81243320173ad6bc9564fc5249fc89410c70b915602a8c164529342c 26c435b82bd68d0b7ce15e81bc391b2b60b554be5867e72a9566a101e27ea9e1 9587ffe6e571e2e36fe80649da50c303ce81f852ccaf2b2e9b7b4664260c00c9 3b28089761856fa94678ff62ef7f5ff7bbdeba5ab033f2bd71ba5850bccdea9a 5d92b8261d4196ba81ffef7859087b51a05ae5121554181cc687a4a9490699d6 297f21664140a48c0cb3fd6e6581ff9acafceb152c76fc4bc9d31d946e2aa54d 87d4a74090844bd351a393e7c9fcd7fdde317947281a8680ef950e5b71cbf8f7 1435d4678846561678bf9d5600b2a787b6339d4ea3b8187a47ab5c6541817741 a8ddb8e7b2ad56a9d46dfda69e17472e610b68af71a3f7ea908c9bd69d68ac62 d8fb6e4733f9fb707f77994667f77e4e3ca818bf8a6af8120e50ddb02ee65f83 8c34552da56de382f71218a665199132e665a1aacf11cdfbc77e5ffaee59c61e 098d1aceb9cc5ef48ba98dd731a3440ee771b9ba272a2c3f07cccdd192f76661 eec48d281e1ced0a49fe3259dd5b4834e22da58794495cb12b14c50f42f352ad 01bf24b8be84788a89206619db1cce831a71cdc4fe0b51c61d0d93144557c19f 53559b4a639f13b09851a396796fc6ca68211f3ecc2a00a687dc3a526bc1efcc efd8b29f481a043c230077c3eb0afa01d99835eb6c5432bfb855b4edfe57b43d 69cc325592eee89f8c1219ae28e35e515f167491b1a1a99987fc1091e3d7ec8f ee3e949a0957a440e8dcf6401c7483a97e78c90248ebb05bf3fa2259fa3b767d bda559c3325659ebeb39078896a9076f66ebdb69b95d21477d422bf892c81c0c 435a8f4867263036f7af465acc3c052161c75a6e983e8ada56e5a88fe04b4a6d 2fdfe818559614cbdc8428e814aef218181d888820c66e8e92b3d0e038b7d971 9f7a9fb7d041cb442104b1042a85085541b4e19332f837a6bf8200ecce1e4e70 97b37dd1b11cbd70c90f0c80fc8c4ae8ee7dffb1ddb1a9b89fbbf94a53152516 238255be5a20745de3541e9e269b10bdc886707eb44e6b7677ad29f57c2e5380 18203e567a0bc5b74c253fe7f3f55632d245f17e1acdd0efbd806129e2c57ce1 183149a1e04a061ccd380488268820b73083007d21f9f09ed559d49b2ed9cbe5 2dc198fb09f54ff3988d9c90d94238ddc96197722d71cb1793164eb352ff4a5d 45cbacaea04505e21430785d1b66aa47eddb172a078a578fb976b018b3902743 98938e4ccb446cfe999b091234c844e2a6648de95ea4b7408320b1b37a0157a9 d6b18d00da6c1f1585aaecfb15f8913fa65cf12466dd5ebc55fa84b28cf39e2a 56fda2b69037627ee3958547c0eafc7f376c0941ee1dbb2dd5885b63727392c0 b3538a6ac0908d7f225b58f2185a1735e2f0013d66a5fc5c7371158fe97b1005 4f4ea02eb4ab62fdfd94367557069356661e2d2032e9ad94b04e9ff3a7c44a01 204 16e419538ca50ed94680f3a13ecea37c21e8cdaa4fec621163935c2218035a0abb8be68930c603159fd635f62592c22c842742eb2d845a2a0f00a2da754f2d05babc0534b9b2c908de5138142cfddb036796d4a7c057ef56de4200294f886f09cbeff39b1a0f2b98c59d33b9709095aa7b26245c8d7b28fce123677db92f0c04db68a76cd0477edffff397b7e8ad1b7a91008ed41d8c1ad2a5f32d32ead9800ad8327c39a72f33cbe342a0b610e6b5f66a0f083ecee31b2d40b9951a9333910f0a7f5a91a5ace137adacdfe969fd95fa101acb192ed6f1873b2764c39c85570679075806bcf626ddf4c9966e103379ac6d5ce8d8b1b00d97b6d4494fe917c706a8aa2265fd1c60e9302a903a1e7b198e1e879d7e828da04ca9b914cc8751980e2e60ecd022a942ae3b0db4832c3530259c3e4c9aece72992070e5c925d6f73020b0f42a08162e91ae14fc0d66217c9178b008925ad08cb4aa956ce8de60ad50e954c1e7fdac604e1783c138a6ad51f295b8d85ae91c1f5c4b35028e1a372da00f84137eea8de263dcbca6935810e7d69e714f778db75701bc03f99246f24d009dc56f481cf8ae2c2ef03c8143acb6fdc8b3e70348b5efc205ab8e407b76cd30251b53ad2cc7b2a18aaa5e40647b4c1dea3cd9634747e006f8d3c7def6645e100e34347b44b1a5383f014faa710d4f7a361e8868b76939858df4d51b2ce1623045fd3065dec39648af3973f551c40638a61268f4ad4fae0303a26ebe12d554406afa92575ac82e732965c1352e3ba0ddd7e5512f8fffe614a3014cd095f2c5405b9689ba74d1811762645ddb3fe09b3d8bcc5ce45cc63b945adc45c2e6a6e8e0a2dfb265ab77590c4636f2975b5c9eedef807c7dd50915caa2896931ff9e43d000136cf77bb49e4214490a19ba0b883e93ca056f108f3b0c7b3f83c9b0291dd05aed430c3fbcfeac1fb2a0356759d1fd18e08f2eba1f9527d5d8ba2235f648b0ebb636b067b469fb9474bd9a180fbe1d132fee3563cb10771faaa4ae8eaa76f0ba555d2f723903bd0390fb518e724060b6877840a523932fc3349e739dfba7805e26d5aaacac5b0bcf57ab48971bcaedbd3553c474e809bde1adf9b2e24d254000f87d3bbf4c15c31b886a5e94694e3f3b737670e7dacdad2a257cf3ce7a1a609ff0a1316ab8e5942b2acfbf93bfa7853c5396e301d126927a16e283eaf35ab04fef2a1a9fee695a3d503d9c27e677b2282768a7a9717ff1fdada9fd2399a41060d93e02b05c28a19f8223a2bc4e9c24732252b79154656191b2baf8abc61980920c7cc5e425339f24d3ee8440208b0d9018289cf7816996ddf40dbd17b15d3093832f025b9e2a828a5f8e68ab0090e896d8b8d132da4972fa06bb77d6f146202e41d09f2dfb81bceeb916a5adee209f2e7486d7b53c9f07bba4273166cd1af061d8ed64260353e65ddf8c04e47968d2deb6ac37113eba1066d5ba933c3b5e50c253e5cdcbfa765c33b079fb5a21abb809c14d4f8ec3154e1066e2ecc6a56f10c18f2c71af5f566239552628c37ebc1b472e1350fa9609ef7ae1f57de662251024913a9de56b950c37909c31b58595634cf69a377243620a8b3e7f566ad6e500a9c8bf63b1b1a935bc7762b2e56826bd8e14c2f4376fff3ca49a9542dfd6e6b0e6e15ec91fa4d1b2ed4c282e65e333aac5446408ceacceb14bfded640f760720c37851b04d6618da04172b0c001e2f21f16d9c94d56494ffbdce8881223e5c302a14febd128995b8dd1d3c367d82bd4c348bd0817ada2d50e92b3107d688bca08ec1c9edd4e6a64506ea264b7378b3a87251bf39aa53342fba1d680dd5bff270d5d04535e058a3378598f2f6c23c571da0ca0686821ef9d3627a08d561cc82b078612bd5a0abebb9213f319f2cd0584bd1780a14643e90b22f2cc2e3e41b0a30040ac76fad246d6a21db47d97f5dbacd06610bb088f2db94256c129a38f6b960145185dd690b8493eeb55f859d2232ca1fbaf02e939b78151cfe75b59f99af701d8090c4f96743f581de28b9bb821cea6708573663111f34365203ba7bb08b2094c08d93f664d2c735778f384d51a87787f17ed27ea8bf6fa4d26408d03050705c7444ab7f1ecd2b5358aa70770c53f1dd90089b0aa442e0e6cc01045b12c2b07397211ec466f29a556dcb75623a2982c57d5925ebd9a69f4dde7b4842f26d30db278f6c4bf53699a75aaae3663e6ba25ab2c5bdb3179018311d128818ffac3078a394e13e5328a3c6e517adbfbbfff80bc4b9455dd86f6ff59cc5713f0f3bc042c6d4b02a0263e296b2877c1808a7ee2635f762c07019c490618dbdeef741105ae62e6fb6ece1b60518eb1d66ed80bbc085ac0f354a74705b3fa325dec07b907d6d4caded00e9aae8aca23f722fc6070120711f9e20b97ea5aa8d2d2f119b9054a710b6432a940f208ea1cdb44690246cef0516d811ad544afbbc4e0b067160d2f814b5e6ee49492142c6fce17e855f256982f919cc492b50fe57349c156db0baac808c51f0c9b54be9978eae208506fdf04f01233e8af1074f7becae18a620c7a8065d9b9648c28186247c0371df92c8c5a5e5f6b19d80016864bfd61efb608af98f7a7eae861aa6d7212f2586dffc8443f4103a9f0d8ad2f8dcda496a5690275b6759e25f8b41d5f5c5112007860cbe40f5608a507aa86ed8a1078224e34041c974ca360398fadb5d4b0581e1af384e6fd86c1a68815044a86ea731c2564078c17e1a257270d1c84157d1025bfc807a022e6b54ce9bead496ddced6debf00177708c1e6fcb221442c417c27bf8e7cb3ffdbd48e0ae023695498bed036808091df16463fdf882bf8377ad04b4141de04dcdd242c932b6a0932116385a9275062fb5835a8c1e0d85d5da4772b7c73a43c6b540f099c0cfecfaa08d12c521b0043c51f707e8873c6701eb49b613601dd8dbc5b3ce3a9c5423747d840b2fcd190d4aaad085d3e99eaa28d37e1597b8e3e0414dddcc5da32a98839e68cc572745047655b5938b6993adf0f0b1d5f7c870e56b375a2be5185e7ed119e9e0c1e19703da6d7a4b36633220c311546e8952c71834ee7def771346f2f09bad8141cd4c02e40da9d005566d44a514dc8cebc4f70d9b410b6cc13830d2b2c3558f1dacec0256c1e492aa3a72026a08012658f29ee26e0c4605b4b768283b373336066f3f01062ab4cd91a941f84abf7f20680261b22893b0ffd524afaa9abf35cdc66a880a83c4b60c404a7e398ac61899b9210df8a4606d0dbdd3619cda46af803a03500428cdff39b4af0435cfeef4c21246b7e017810255b36d19bdaf09a500165dd702cf05d9a51e916a88f148206cccfc4a57337fc7ef3f3542381fdc6299a56d4a02a21dc849cbfa65c7dd2f79ae66f85bed57ea1baee35f5e3821faa5c6b6837a0afc686b2e3345dbe76a055c8adc1a40612fdb090759f0666cf9dd707405e08005fe933768e0eeec889f8d74596463cadee4f4be1ea919cad166953f9ccb8ca90ae4ae642f224e7b93a7221b44324cd31268c5e48aba977aad1149f543edfb490edeef8d06d1629d30fc4608019d29d71508422d0ca83e49aaff40428707e1670e4a4fac31834ebbd978f4f243ee7097b064ec400a486e5c897a0855980764e806923857cc350a97feec97b9108821d4b12e9f60f6e16e433b89c4bc59f33479039ae9390e27d395c014fb68d603acd915a0ddff2dc9a2d3e7021ce08d363efc032e9a83eea905b02b5cdc10e76645c8ce41cc99893351d707eda9f782d50d12087886d5ca78408ac81785a60f2bdc2e6079ce07ca4c1d921b6bee6fa1913b430511672278a08ee394d6f39eb13281a2b8fe6ecc6118b4fd3617827c911363130990fef13c790f6f82f3f0607e9abffa36918c7ac64dc4982788aff25ac85fea029e4c8f6c7600ccc74fd4da2b2840774327604582f5f80c0767a0caf6cd02660efd6a8927774bb9e423c3e6fc1994f921bc77d48b4cdef75c4cfd2c5bb2be2d0615c8917b0df429844f796b2c56b05e4c19be253cea6ed8e30495dcb65c78410f94b1e102e05945643e3c20a729e040f35388aa0c18dade36068436a9268e980def3dee9143b1616c035b591f762cb208239fcaae1165feb808bd9ae739458409e882a944f826ee5f18469a21357ccaebd0a935d25c954ae969890edce7dad40eb3a716a957a339944d8f5e99ebc3ad4eafd992e1759071f3c0307fb33a595400c08099b22cfc8f4133cb18d3f4743ea56bb989cf1b1d603970895ffd54817f0b04cb00b6589a6475a35d42316c9bceba6d64f76d242ec8951e900cf86141d70bca9d1558b29144724f97117571a7528a291322a2ac29ab4a4927631510b0c20473280fc992cc3b0593e8316118e3ba44975a082840fb7aa5d5528c372ea5430e7a391f6ca74fecda3dfd6f7d1755f66c1a5b91cb39b5f18f7d842cc02aabe206cc75ce799e3aa5cf603b5c226c4e139c84512221c35609e6b97a0e0a54792806f4b37740f15b3e185dcfc89a4a1849c272a3507f0044440dfbeaa4a46921d50822f69a3a6feb27c6f9f1dadefec8f967d92fe0031152b220199822320072ad0ce836b6d24ccef0af6db6a7a6b1a1f4fa2d1350207a50d84db55688a4e4f0b50ae35035298490fe503f3ca00b04feed7f3bf008f4e49eea7078cb81fd9c4e6201dfb2713f2f57913d36fa6f2a95fa2ac072432383135c62ae31d97e3ff0352407504cab906bb799179b5af1809f82904b5531a02c5b5f7a02cfcc1a07ad9509015d29949c67d4588999ce67c403aeb48b289157486e83632571a737bcd9abe80298d8e140de8ffd0268d8cd2725cdf2ee78d854869b67758609a59e544e35790f036a3b1ad729a0372bdf1d6d001073f9cc702bc9d009e4fe66f9b61389ce920b6d3ca0bcf2569b98f0171bcaa81f6114e9600a5c59e808c5b8ace5c750fa610a56fd72c8304607a2a9fc664cc1a63a49f26196222286258661edc07af5ec5c0461497fa3216e66589607eff192818d6fb27616ffc69f91b4b57b46d37564e305d6d39875648d9537064dc19af6ff1fab0df15a898efed71fddf35dd853621d03b198a832f91eaf8967af31de0e3b04c5057ad3e33ab68f7bc80358971602290718825ce1dd00a6d71f6557bab44e983ae84728f2c817cb269e486c061043de08f31a676e5a20d53dd661568f75442cf4c9ad103467a3004f2938155efb883b03e9e5d96539468dfd90bd0364179f101f338f49d2455eb7c10830fa65d28f5007404f56e864763a6217e54b5b8e915a84026f83c596be8c6d03cc4f9790c54d02e98f44e7e069679157101c0cd7f4898e7497ed566f95b9d9373a5ce3e0535d031e4d733c5cac601da4b6ce79d092eacddc7814dd10e8cccd2f18f2c0f3ec2b066ed3f2b39659ea8b3a5d948b01b506b618befb251e6f2b664892629b235aa60d6dc9bb820018ec47a97b5766ccc4276bba11aa66cb1b77d014916557d43d1507cd61e671d7034943b5b8dba7543645cf8dc6df3268625c312b70d42303d137019be8d84be1bc63af870ce559417eddcfe146854bf2d771508d2399534629100a648f9879e698ae4ae238b24e30b749384b2510b96d3bcd5abc00dcd39d885001e010f8d9ab5cc12c1a1e90dfb6c93c76e799e10f340cc907a053bfc30465020905ad33ca6b9680d5ea7592808b8a47f7d0554347cd0cfb4a2dd10d9916853202ca75b6d3a8d6eeda543bbf14ba9b71c7c0193f3d7b615aff09fba7fc4c21e30a1bdb20ff5348185c7d153af260a7e9ab1fa61f44078c0a0d02a28e58e6b91309779a1eaa221a031182c59af732ec9409a760b525ff4677829a80fb761eae8d0ef70e0aa96c6329814b8ed3c42ae6c027406bd0bf4ef1a3ab5ab52fc1d98695000292597d4f4d4dc054a0ca200c03f38fc4163d1ca9b442e707411c12907d9f0effb4ce25fbfb2253fe45a575d9a2ee41e3427a84dce1c32a50cde3d2a853ff0071f0314b2916526c034e23452b64123f11199b771ee2b1af0e486c083a801f0096a0dc342c13f29c1a53af8b4d732f18e1c4adfe04c83c3694023b0a0949ef0b35ca14f33d67090c0c01d516110f26151ee2fd405335ccfd8dfb8561507dc3000717094149c49aa7e28be60c99b5f7d9a66a09a91d0098c081ff825a28c270048db1c81ace94678cb22e908bc69451b77aeedeb2f9890571049fdd39d9ad280eb63751f0b4963666afb016c990707252900715688790c642026fca2f086b6e0573e4c42cd654a9c8f606cfd80d9199301b8440644db32a411f9c9ace3b55e1084b65af44e1ae299f808d0c21453e99491b439bf5759b10723ff74d22ec9680063ce4e984a7b2f630ca95303dfff9729ae09113af350c36ad2aa53e3ad5641908972949bddbf204e3138c42dff2a4fc32d16b54a0831fc5241c89be25d8efda0c069884d2f1fe5f5690e65e111a713e4ae6340f4d7387c3975bf7f09318f6b10cb1b77ab274697410c3b4ea5ced839a0c642cd89e0d0a9da6bb1a958a93d5d70951363f4555cc34e2645279ba3e20352a0d87ef386279649ea44dd2cd9d758c0a8d8de625cd4b227c4bc29fb6b0b36b186f375c4ca65af35ff85c3039501a050e85c72fdbe25dd3bdc67ffbddfcb3b83c4231d6f1781dae5fe365b2062ef4330850063729202e507f2680f2a0019d06125d24bd0c728ef8b73f36858892c53101926f6c1c068a356be4d67a73131d6e4ad7c34db092a873f6adc20bec57e308012a22b6734f091ab85850990e75148eb913cb2a2d14cf843bb3b5705cc431de0ed9fbe3e1cd15a57a22a63fbd69e3e380b8c00bfe3ba89a4838123b2bff9b7701f2e8a65ab158a7d37ef52fdafe2cf69afc13ff79694fe320b6f81642f20d8108b7e54ea1da597e65539f39b505f67b053e701ae6f978e839030df1e0e4da4108163ac5425ef2ca7d15f8d65aaca655f35465561c3078b27e6b401a9841e79c05700d65fe2d4af9ac60b44940cd193c79e115a583dbd2cb48bed93d9ec859f10f742c06317eb859e5f3f0ea5ddada506232216d1857f94c0e88b952ed47a6910430ab3d73a770c5331fbf93950d202fac53ee7be8eecd6ec3eb1ce7ca60321c0e21dca91a3f95e7626bbe8cc99bb6f32e00a5c4cb021108f0665dcddf6e51e70de5d6773c5653196e53065c0a55db5150db641795eba6f4dc6a75d9e262646803f3b42dfc878ab46ca75c5c972240a55e09a5213bd818b002125b2187379620002625592b59e844c46cbe065caea8435306cdec8fd75a06297555df76bd22bd09bf86cf07f53e7d65b63dfdde8f850e704a96e19e6eb8bbd883070f00a5f1af03e2cba2b7d4ec4b79b00c26fd1ade75cae58db490a969873fe04fd8495aa6820b34d48a59d16d0b62c6542109b5d0f028febeaaff7be514b2a11bc9295eefa200fc1eb14982cf794bc8356f140925c3ccd6d56a3df7aed7abd5990a2b448fd40f35c8f88073099f8a4bacd22a4b6842ea6c1ce5009a16b66e0ca62532b5ca0f09f8250cc4ec1c0d17cfab374af2641252df977b6266aebe6a1f8e4873ef20bb00a2115674c94d3ad83e39a7ecdfacc69b6f41f982926b83e45fcc6cc84713050a67a28576ee08599431bd7bed74a451ff793aff50ff17338405f3d8d114521806a28c8b27c64871b1baa08cea4a7386d36d3a8d27e21e9ae541a1becb55504203bbbf53a14c550d5842a7d83c304493e9d2a194b4bfd25996761b634f669a120e0155fe83c0f9c5abcd68c235cbe6d7a1142c9aac98c87fd6a0beceb5e4e39c095ea2784e03cea3ab9d0349f33f07aec785838cd41fe6d9979a3b36b02b1b1406892939af622a34a2ef570ebb7a4b2bd8289e9560592ed2fe324e844a5be1190c12b6cddafe21b50f2fbe21c31cfaac26675c5d1a1cf76baf9feec4f1f1ce0708b98c321d6e881024ff6afec0f6a3251167e91817d904fad589039dd8db14be0817986f8191143abca5dffdd49f09a4cd9e9d5455c23a47d35f84d0569b379e09580f0346aa8d8837e7aed4f0fec7cf67b80fd3f5f2e2df48125ca6b98c518101b5d8d187ab91bbbd1accea50ba1bb92de1665325dde6d7ff89165d882ccc78025dbcfbb5795d83b797899206ff8ee04821ce86cbbf53077fc1441f9184ab440925ba058387019eb286594c2a38152548e027e8c2ee9109da30c60d8b2c42a60d961e09657811c6df334d66aef12fc5cf88e273569cf44cb9406258496044e808af22dd00a1561b4ef75343dd2052735ca8d4a8c81c27447cb0be59447da28108ce08d22221e90162c875dec610c5710b40375928af94d7d59296754f52050107d0ba13af9e404b0b055a76149e9cba9d2826c24a5ea34886b015abbfed3fe603fdc0002c6a2df1f274f0766ff9dc5f5579aa59290948163146ee04855285f90d24e07459daa71a6b1ecf7b1be2147696655f18a23e7c70bab4b8c63368aef10d37459811086cfbd940f11fa2f140847148851eb77c08c295118c490d8f94c30a08880489a007c1ddf1c37aa56f23d0f80bf2b1d012f4d6fa0eded13178240503753627914817389eb02480e1bea1997ad0e0684f1a319b0e3760e91b392ea5041679da09728a98ecd59742fef00d6cdb70ea08a2a2535d35c092937445551f09ea87b4410d08ef6a2c9441c8b32e410edd3a9e2317ab32e8d3b6a2374e00420f64c01ec37ec2ecdd5aa92b48628c11dd30209092d9f9a26c4d42a4e414b34f0f0005a349f8c7b6946313ec69ba63bae3c2013442c64d27b31c4763eed7f24709a6103a39fa57d94446263735995cadfb4275d3ba4f069b414dae108a4ac8860ce01251b6569e3a005c2fbd2973bba835869a4677624e5df55da1d991c0edc50a1594d733958ffe22a8a35a5c9230ac051b7267873f62e2ff056103c2730bf50821a36d8cb15978ec745a936a357326e66b324db4815cf3e775837ea458860109b0f07beb8a52512b6c3d2c2983956f808a1f3eb161b1674f48e27f97ebdef60f2aaeba48671e01b83808096d3d3cf5c8ad96dab79090b2a55a219d868fa45c05d8ed0b962a61af84132aa99cb9fd028149d458c0426fdc8da30147c9e39c1002a02730a489224bf62e20d431dd92350c1fa9df17b21588cd3e1eb7b238e07c0d9b9c834008a434112d33db8b1bf23c0920dc450c10b9f219dd42ca3541025406f62b3fe1e5a7bbb24d97febf1241311300631ff4a31c33871c0063d37339780e8669563ebfeb03027c736ef3e4140b3c3c86bf3f7228586e71f43612200f090875abcbba5cee99ee79d3ac7a68c91393e1e63eba4bd2f33846b21263a84bfc0f8f7da3a5adb861e4b0e4642bc14c269eed41312cfab11a8bb449d84e81cae90199e589e375e8732dae771246923a64e92baffe199abed788577f4fd525c7e40aab1fb215d64fbc7e4c3c4f01ea4376de6e31f6a8a010cc658420d009d36e55089e7f0d30a81d737cdca49a0a1008ff69fde6ffd1cf2e611859ca1ef81819ae0ebc557327f33e38f2750b6d66ffcde96ae11e625dd3b3380a8dc199f68a063c0380e8cf746b154b0bb32e13746498492cfea4f64e08225f1b48fcd49bb570be02ddc692fbc8525e38ffdf80ee1cd3e206349542e04597273f7263816959b7970e31eb189c37c67dbf4b840b984497102c88d0400de78ed3a39b52aaada390d20bed22fed65744eafaf541661470a0be697eda136be7ddec44bde772810e147f0791b2096138a56c0db00acf93054f91ac6bc0e3657e203410ccaf656cec06480820791ba583c3c89fe6ed44d39cab0fcb871ac47007b942bd974ab5b80e8f9304350f5cdc608bcd4e9f65c6f8ca48bdd3d17eb196971729627183f4a485b872032adb03ef61807b494560353a65b3091d41baa37955cc7cd4756505c38f4671085a84845566bc7b1d19ea1c23a08d9ff0f2db5cc6d6858e9e1e969075dc941106f3027c7e26cc38c8b8df447d6bd209ec9cbf963b2b60e2030440d0801c4e110358f7c55801369b23f8e4559af84ccc9d87aa14e9f00a1fe65ab1c85d0c070e05b2f2d7f553e032af8ad700937d5830f650880c51033c2c1a8b89e0659f2f3c0a7b937bda0acd91d2c1cfa3ec862bc2bd49666464a4b71b86d0321daa0139be093bd15251aad8f6af5e026abe6a3063f7fdf76453429265d136fa0eb62acff00a08fa64f9e63377f34644e8ff27db06357cd0e5fa31b3d1da7f02091abefeee075e0850908296d9daf74f360c9af16474572c38d928aeb7e7e3b1d299a0ec570fc63989ca6ce05c42df06e6409e37c3fa263ce92d361ea315940dee71267d9b0a09bb21390b2e37d7fc0e2ff5b93f3dc93997cf0dbafd27bbe0a999a56bd71906e618f93df4f53e309147b58b3978a1b7af931d884cc2df5fe18a2f5f6256640e2498eeed0874cd59217c7a5a2e2572006a2c3eafb08da01f31291ab69cd4b80a0d46f6cbb5b05f15bbeb931567e3c1d47f57902cbbdd9708cd8f9311e6fec00f266989a39d73ed9450205aeb878c05af1314c8d062060355d241af56145c590fa24335ee26b5b010b3494b93a37bee088c0185bc1751c6e01f4ca5d233fc2c056a08ce6cc681323982281d32804b50f510191c6147517775135c118415e4d40463f5bfb4f36152d050f908fabf5d714441d08474f5facb7432972fefa599ca0496f314d1737d48dbbba0ea092930261298e51f98dd2bf2eb0c3c2e9f84f0c308197a7ea2738129dd2773d1309e3871b01f9bec883508fb69ce6fe5a162fcb80ce851e11aca3f4cc918367e40a10bc1bab765c4f8872eb60f34ff5d282fe00f0bfd5d3e5168ae90fb4200851850d5a88aaf650bb3c0f356490c7c8cb5dcdc18026645d891455c98be8b0abe0067d0f1e9aaa6930fc8e3c3155fd0d8748c79170b5cf8e73c8ef4bd03851a485ee0e8c5e4ddaf24555673a06debc8c1a47818520b088becbd7099212c1c4ff64382c63d9ed1f2cf25f3ffeb7f31b9bd589e7010024e3f99eb151c294198dc98f04d08596da3460659f82ba21369a62c0304371102e903fd4bd2d78d06f97564307566642b50147fe28934cf197ecc8400bc4eac0065f1d2e53672e229ec0bbdd45e26e3598c523f4c1e7255329fa501e64d70580ef7efac180f95770585486b8c620cf724edd86d367519f7273deda6efb33ddb071df3cee79d69811fd4f8075bc03f8619b21c276fce3bfc45a92e0baef02e240b8be54dddd9d8ca16a49d7894823b6b22e61a0194210c5bf5f643e946421c40067c2c3614a2e7d6abaf14de09f720a8ed5e038eafffb178910f66f2a275588e0a1df2abc2014d2db73259eaf18ac722d94ddde567805370d1f860baf274fc9d0e2b0763d44270c11f5873e9f8109a4f83eb83b2e4e7681923e8f30467c6ca9803fdc5905d54b66383e3cfc1b7c5e7de5db9985eb335c997fe2e920da250b7af00fc82f3ec771a90a6cb9762e7421e39632c8beeb223a46a9391b34f1214c1050bb377874ed8e6a08b0634da87ec1fa1afc76460111bb7b607dcca77b3e7d9fe0d791be4d72409292ff9bad34e67cb21cf5d6ba6b220d77d768546b977f4c02800c502fff761a4384d1fda556dbcf16ed0fce9213eb1ae4ecc11cb50a16f60db09f0705eebe70056716413da666920d7ab0fdde72f90fa49774449d4c2701c9e054573968cc5719a63bc4b7ad50b7ca9efd6b1d3b19a1f135c6128aa42c6a0230f1f398b45b88f69c9c148c8bfd072dade1a7789fe25f64a4525b4e6d75761c50be2e8f0ad01d966ac7599b409a101c0959f22870db5f8d330cf2fdec26b34be0ea54801cc0d685f89904924cba6af5cbd7bf2c5865caa6c893886f3f1d6d8200619fb7b86e762f94d35081e6512252f3055216bba4460b96fba0e75ece44bba0705f5b413a6b88a2fde10630675aa49cb926b48ad1ac79452937f49cece871c050b39d3a54fe0a8504984e68f751524120b3aded08ea867d8faac8c688e6f880a5accad604206897b8a8b067e15a41aa053aae606ca5963ffa6e538093ad8280913e56105e7c11e9a3335033fd03472d76f50082cdabe05fae23b1c8a5196a10b8ec387b1dc87902010f25caf6e0af83fe5299396c85c866f436b5fd9cf20390bfc10c7a0056bb78d6537b918a826d2f8b80520bb8f61d3186fa6b57685e2a2061f1e2dd90687c2317a5fdbc1c5d88c99eeeb4d03ff66096803ca14669e2bcf03ccb4722719db4928c9fbe97298999a21abb195cbc6fa331c851faab9b6f84c029dc9702d89dfeb143bc11c80a89929f10d4dab8c7fe04bce0defa51c3f815306c75497a6ac01116e1110d500a855243a8c932625969aa74f504571619e8f7f00e5269170c817c605aadd7ea60dcf5bd2bda783e7bc763832d0b158bfa4ad9c057cdcd027d39817ea1d9451f7e35a469b5808c909423818656e6e49ab7df8590cbf6a39883e365e33cee6f69f9d7389459a1a27e9a959b534ee5d9734d03bb30d9300842d31a83f480f481927f9aac0b45addc03eaec44043bc3ec45d19f5e3043cac7f300058406bc9acbace495c8682c7bdb74c7bdf07359f84c378bd21b905a08d7507cb76385a0c8d15926e3cb29cfac7d02cb52e2ecb0681c960f6de3c0ae985f5e5447f204d3d8a1b53e607029dace2bc74c42deba777a34239b99c080a61648582e6e068b153542c3cd5af2f5adbcf29dfea5b16e28a1d6be47cc82b0c616acbb4c79b149df5c052d80e4a7ac4add12a48a22edcccebe2657cca5a2f000ac7300f55ca56bdede30cb3283756a0c11c01a607d9c762f5826862beb83b039366c5504e2c70ae0f5b18c1b27e49033b0f30dcbeaedf2afd6e9425f90b46065dfcc0f351fc6064406514ffc2b3a93174d80ac67161531a4b39538e6e2fbb0e0d1e2049d8d11d58f0893a8a913857baa7afe9dfa0c4c615439e654283b37d01aa0cc42f90b06903e4fc4e18ad8fd003b19709e5fbd8f643a86b8d083d4e07045002fb6a8aa4f414ac973ef3741fcc28437a6ad79605beef16bcec0f9807580b77566ee36360e7e3ddbf7163435bb1e98d2ada225777f05ca84226f770fffd042b12e0ae3594fc3e8ed3a290322c223f553d334211c0f381d43836752042480f8926171845044a4abd09e895bfe3ad2c9d01574ea3d008a228ff827c5cf25e017e8b969f07b04d0eee2edd6f2e80d5a7395021156fcfc7227d4f4ea224ef05089dcb07f8e0ef02136cfacafad31cdb783dc31502809b9486963a1bb24eb7e60c2d43b048080affa018b7913a847432318fe68e6247942975f7ced72039e860043bcfc9a2bf30b3214b1240ea03959071729984df735129eb9b1d16c956e30e0a34098c4fdc8c22817843e2c08af864a261319877e35f06b54542c4d80ada710fee11d3030ba1df9d61c572b58154ae658a052ff4cfb7ac3bc5939d4f27deeb053417eb3c93927f8fd7dc5e20961a09a5d544c10efc076e5a25507406bd29ed0f5963fba069d4dadd406b143e8b361f535ea3697aeed4b8973c63834b50293e0340e2bc94f77eb38647ec0ca02122dab1a3205a538b12bc5911448e9e4da9950fb3457dd06d06b3c284e3ea6dba3f183d2be52d9263f1103fe009613637930307dff5b15208a7cb76aabd1434210cba0e734ef02a3f8ce36764f593acf23ff50cf237540a827b14744f3482cae9ff2928a5de660920655fe42c87e9e22631d10f5e16190481dce7cb7599481c27d9b1ce20046b99e3697992f12e599695d9bb0c8149a988e7c93eaa91fb3228b151cd26cf1dc7667817364c53d8460d307a930e028cd29407453b8ae839f0989171dcf70ff519e5e9e4fa15e6ea3b6b0b41dc07d45cc09a08a09da72561f891e79492130f00b2d3faf1d2e5f220f1dec531800100d1d82016385933fe98190f32c81422ed36a26391f966f10fcaf91f762cc8047f9ce379c2f2962c9d1a38308d6e10c95d540699b1310bc041d1f888b4229e02c19c760b77b37d9985459eeecb12273a423ae0d5605c39a7abb0ce71841eca08a006b9579c1c08d2a29bf8f2bd14f51abbe0e8ac9e8755951377171b13164c091998712b360b8742d0102e67372fa53f9da9220e09c8881f9926fbf7e6cba608235130abb062e209a5891733e8202e8058f78370bca5ced0e4aa0185b63edb03b54c372a90f21f75613585a4fcc20f08e2c00aa5ff0da55dc4955c5e7361de0aa561488997704865724a8581a010a9ffe74560c24880b2b4a0c8996920c29d0b4460cbe6da64df6c538eb828f16bb3f82438ee3b594a9cf4bbfe13e5bd297d0c7cc4920319ccb0efbe3afceaed02787515d82d99ef73093aff2079e8db8ed20f75fa33dc24a823c6665a249d4dc661516a4128fdad663f0ee72d092bd41a1b0ba5ee01abe290f1d86ede37ceb70933d790ff53669f9b4e5117ae03172cca9b06afcca3a72786e5d5b19851935ae54e5659540adbdf7c9c0a9d38952cd9f5f10da48a4b0930a5dc83887af02f56438334a77c8db3a683358a558e715c0e56c402c78a7d09a78e765033a9d42e5f20ef551d980fc7770ec0643cbb7762d9504505fa41eeae028b235fc636d46041d772d2c180df0ced81559a8bcfac842999850f203aacd834622c2260ecd19d825951ef1ee1aa34a2a31f4ec23287de0eb74104efbc3ed8ca4c5033f0d95f427ef3a483417edff1fcbb29271d0edcf154765f0fec9bfe606453d3c77b23905cfab13cb8044b2776c4c5d13bc73c60b025b48b047f35fca842ae3d3316ae2a0aa61eca434fc79507124081505404b8b32ad4070f635717d289cef521b4d6e1a0e3801c3ad12c5204776cd4f9ede04f45265bc5063c7bb74da601392c99199097c21dd43a1c39fdf9966f65ccca7f3e866981060468f423d4896043bdf4dbe69e656dec113e86a0af6dd8acf8030482c527d3d501f430b0e1cce73c91a626a5209b74e79a508d8836870fc85c28e4e4dae58a5900f3fb4b28223aef935f783b2aa1be5670cfed32dfcfbec9fe4956ee9a5742710164340b658a2d51760a3f6b992ac0d611566ff537fff9c85568432298abe6900001adf3372e0bc5c8adf10877c652ddf6c0c7b3b7e1a55330cc61990101868b0819b60ae89ce1ca35d0f91c88737b29cff8cfff5fefd7fbf6760aa66c0373a704d9ee152dd3ac8a45b1feef865f60269d71fdcdb5e64312bad7ed57f09cb9fa029319eb67a1860dcc6dc9293f649030bc0b72723b6719e1d8ee1a16ba8bbcae013e6b209056ec2c0d71e72a29679f2e09b0e9d96c5a73c113304fb2041c15af0a719c570209fc35b1cd2e4045395cf71126068f850b2ff54bfed7d7df10537c0beea4a69b798139b9d7091da9735b8a026bb0ca2d75cc2a2417ffd14ac3ba430e628666c91d88d920cf5e1d672cc732c8e0180fc0653bd48d344e67abbf56e8044f1ebc12e05cc48dfb0a0614eec0fb4a4369fe1f764a28979e43c6c0bcb1a30b654861cd62197b0035a40da110f4239b07339d06d8b9cf3d918ec7fd905a7708173d5fa3addcfad525ea1301e08e8a2e4e3ab5c84b33a8a9bc861443eab6ba00596719ff66e957915f0fdde36c96ca0127ae10468de11ed30e0d9b3245626404aa958e3214f8c2a577ae9a66a4156d0180e1c955b36f9d32e046cb9d33553803215e93ceac4afe88d91caef2efb0768bf3cefc109c1e9a12073d22d46e2e520336ded892066f76566383550f04089f2a3fc23594bcb903b580aff57b8fa1d104241b3e18b2441eccbf09710c15f59f41c1e606622ebd803560cc2f0b22a5e80d8322bda71d6d5562dec57f57961e7ba2186f39812f391e08fd21fe6115836f07722a88e2d2f06d16ccaa65f1d9406711d6e8f9cf1f9cf28e9b65e3eda094a50c96a9dfef4dbd0ef94cb5327694d071b17a17fdd86f81c55a25e2268f3af4670a32e8873e35c7320aaa8b793f060011fc8e71dd3594f106f340d86f3990d2b00b3d016f8778025b2f2c241507179ed165b8bce6001157368a7e5ea50f7475e60e91f4cb2b41d23fecf2835993295f2c0e871be5d8dddf7cb2552c61afade985055d95a8e6dc6f5e69ed49c9b05f4a0cf54e969c9b10cca60da19158f5812c6c04cead56dfee889193ab86e803dac1c5ef2e187c6edb3dc88ab775c1e422ddd3090fb7933dbe284baeb1de3f10e999a9a745cce17da2d7c0a360bc69564f92860a6fce947c3d284b6d4139fe0c7bfaa26f75492e25d7a132154719e5319e6a0107bc81424c0c2d0590ec5e2332c7168a1b260ef2a95f2820148541c343d52cf809638581ce07c9f12efaceec80548043fd7d47f4d25e57dbf80ba55054b6890201fbb4ec8d061ba553d9b099999875a6fdce15af3335db0651c98c30e68295de03c31d8dfc059e94a24ee022951981a11ab491d99f01d2fbbfc21e5ea2babd290ebd0107cc4d770dac328077e71f7aab62001184301dd86ba403e0dd66a9fdbf07509b6600fc7a32cb6f36013b77987599b0adbdd507786c55729b284a83bf4d027bbcf3ca4315634ea40863ba60439a0933440178f052288610b22a73220ce9012ef08b538b46fb24f06c7895ca84901e14bf0797494b3ca0c3363b078ae9960b0ec81b0bc89762e50acd775cbc1f27f5f1199792b937287d5ee8d2e33bd1e6003969b29a36333b16931c5c409258833440e662301533c678b4f2bdb63345070b0512dff61ab32e0957d69a87a5d2eac76d2d045040a73db8bd1515122fe4d601611014aaf1235d5611371d9e8a4e5200c7806f591c48168fc4a86d37adac2809ce0bbcb537a5b469e131e79a08f8ef9cf8348b11ee2ce2e938d76f1bbc59220d459d4bf756ed9867fa30fbcd369c9aabe2e99482d39b340823fa7ea24a63470379a61e196366c5cac51d8b1bbab1a93b0804edca1879a7a3631d6e110597e70756b7e2ea006e4a17542bf1593fda7dd0cd84eebcc497425f355c217cc222ce015f29bd08cc1d5cfa95481bf2029320ac9fb99c2e5334eba5f1699115c28a89066f5307f2735c48604281d0df91a43144baba41ffe1d6660cb24f6373ed1afa0b928892a95b235b78d4eebdba762b96c688436216fb48e5e34eba10281254c20dd37cf56aa24f97fe7c55bed85714e5a0307018262885191f8481d5a0bf8abc0d92978c85a8587e855e86bd5a92b8b96ee44add6754f181fe1bf129109cb283018c34846fc01c2b681befeec173e0ebbbbd9262ab19a9c1395a8a363018b47a0799edbc9472040266ffe8af19c1e0402c290eb718a86ef0387e397c945f44e800935b4137144d742899d3111bbcb06b548a8b41425474148da36d9ce21feaac0abf7260624331a4b6d97cc26cf652b9c51f94f23d933ad8acf2854b579bb6ef00dd709624c761ea2d706fd817faf74c88058ba08e568741b599937d14c2183107bbb012884340ab18c6a17ecacea91826ec7a32f282912126eb0e78c468723f0c4525a6749d3618908fe941203ed085122563bd69b49e10f4c390469802a3240a14485da825b22e44d685ee6e3fe170c554b8cf2960101b6be98b3534fa00c4038839667928405113ea086fff8818f0bf9a45ab0ef3b7dab8f8bab618af7df704d19f569168ef56e22a0e203d9e693a65c28e0e5445dcc90f4691e397ffceb30ef2e3c57bcc069902f708f2e9980c2a06c7bec2c0153785864288010f539bff0cd801ca46e1d153b2474b4a92815d32eaa47c3d07d359b1d71bd2e1b5459dea08fd3c78385cf7abbad28030e9b2673636a108ba2ac1e98ab85d1632292399d80fdb0b60208bded3a97ca63fff65cf13d6d482f0d8cef1cfb588d677664cafee064ab4a739c5cf99cb51bf7fe4e0d4fc36670605b2c59dacf9f5164a66ac119c0f4038ba38ea06b8843c3040a3a2d9e836b4eac9929d60ca82ff81f339f80b7a0aa81dc77eca85b503203956106c545c062f3634d017f3860e870352aa0ca03f046e1f9d609a155633bc25f9515212a3f4349cc9da21b8b2fc3a4c57537c30800b4bb5c597ed3d7530dc29b6381627ccb0e8145b8391d277800b5ee5386fd8ab092b6d5098bed8341a7f062d58e5381e610792828ebb3973b00c7b941361ab2b0759a21dcb35c31aa15833bdbb3abdb6e1a24a28c0b78a42cc2fe113665130f3028210f60c294910a3711d3bf5f060ce1ef07b9947f9ed243ba94f4f97414c060f5a805c1ed5fff948823615638384054bd322fb128967e8e77ac1e8e0b589e908b086434b474c628656cdaa2fff803d50f688eb4f2de41da0679401d81253a1028e1b826083b0cfaf4bb527d38051e4214dd492d3fcd93c0296aea777c0d3690efebe7ee1104a6ca67e109b35d21ddd615a4e4f4db02ba694d254158413be0605b57dc9d2157741fb603ae5839c1f4f67fb4bac8575dbee59287310d625462f049c5b5cc5e9c9f762cd20972bc6c8991fbfe5a21ef183801f53f1c2802e752e022716d7a4bfe64eb808f582276c1cce06377b5e7b61688b896bc66882bada5d0824727ea47c3a45f1666bbb7913b15d8a92e49303d12c9e811b8d1f895bddbf04ec2d3b87fb2e70cb87a0431d5d7a887116c45968fb79a870dfe3e297a00439063dac09f303f07bcb73665552a4342490cb60c30aff178319406cb9d97de7aa0c3e5e5254171a11e813bdf5494e13e65d2c08d81371815b9abf1f31031c185f0717874be10ed6e8735c298f0f1696608168247fd2c070bdc670019880ecfc7803e45303ec93afc4941e2a6a90cdbc9b463114eb5f4eb9ef3b4c24909eb96b510dba51f59eca3351844cb30be921d1ee3e2520418322e68751c7e6aa7c9cb8ea0e3e551da1008be9ff608b80a3e7ca60512a03dbc46946f29fc83be4c681f7200a9b80e6721aaa118a2810fc9459114ee073eaf6601d3d88b40806b9ba4edfca02f63c8e69182b0feaab2f55dfec2847e0dceb5e8c52802c43edc34824190a6c0417f52008748cbf0c252a7436d62eb974bd2b0a33a15456373d7c743b952a680e23f3897f22904cef840efcbe6abe093b900ebaac721194b20ba3666eeaeeb8084cdb8b2c180d7d0a6a9191a2a3eae9fc1eb8d386caea56277c1eefc8cdee7605efe28cd8d32d53c4a98f6459979683fac109a73a52c878a029775bca072fff0e2840b88533ad7b08ce0ccf3676673d794d76f16cfab5346634f0b6548e32c5051bae29a08c2a0bc46dd7232dd60b69bfa66ddb1afa271371ba83ce725ee5700de1f66da0234dd99b8ca21b7760734910879051f46bbe2ac46d4afad0150c360470938abf0eecb5cd0a0619c8bd65b47594d6de315671a26df314fc7f10a7cb04939c89117a4815f2fa4373793462a8c71607044e567bfee8b619816cd204d80d72e9155da7a82671400d1a2cbe26bf87756951dc57a893aff7a1569951c7c90f4971a8e5231e2ff5a28b9368ec4f0bab8d270c6f00f8896deca5347b91fe4a075a7af8387414cd330967b59238e872b218f6de2a0329d8fcb38e5005554fd40b211a91870557d6d647cf244344f4878ea1fd4f5d56b21f9bd2616e83bf587b08d3c868014c78c5be6c4070b28a864966311976b4f6705787861f53e5379f840d1d96ed4b7b2aea312b1f34214ac5663a8f243f288152023c85ddcda052660f0b3bdd3e48a69e7703d53d579fc5225e7ea0ab9c716ff8a693494ee85e46ba9b0a2383b2dcb87aebd42f300971e57c03c963b20f8b59c0ce68dca2892da8d8780272253bb9f3960a1d18e10a5cc272deeb2458e7fa3293cb4356e8559e2cf64d023441b0a116a4b3822b086bc560e1f4670ab2993ba57aa4b2db1a55bcd25fd40e34f4661cba161df71ac414fb46e3f9ec4660bf11d207afea16eedf9cf9ab4702da879313767d399577c103c1559452e8087690df929694b1b417d4a5b367e70852d731399b7765897567418f9f52cc41ab6af07487c0538a5a080a81d9bbe80b089f98c52bfc59ffc3977c0550a832d670b695c5a7eaf880b6f951568365e508889cae5e25da80836ba5da46112b7bc90f23ae0be21ad84c303e19c450d54c081fa3b220460418281559d0eb7c6b6ca0129bdd16b2299cac74c27ad4f02f7904a3d39e398903e19ccccbff8f07db4d0eaaca8568baa49c056bb6139b594b8c02f9e4972c86e5ac463e0ade613585c2e546c6c3ae9e293ef9124143c19c97aa030f93af932fccca44286143691d9d9f6e1b0c7f9ee73822104dd0e4251b7b400a0ab3bdae3a10605db30b88244fb252405767da5035ccf292cffcf09fdde12809e94b96f541aa6324260333c6914afc72ca1bff2a3dd5a057ffb20b94d008850e -generate_ring_signature c94de04cde5cb97d00fc58347c9d43c5e2ff19eea4318f3ce8eeede86e590181 dd0cd265cb990195247bcff884ae711d6d6e27a552da53c3871f9f1ef313119a 41 fa1a0c591987eca8d52794fdfcb34be618b911c96bf95dac8383b875200f160b 5df51ed1944ca217cb3aabdf05f9e84481cbfba603863402a3b0bc3032345285 aab3f16311418e85c428006e09f6ab4cb938193554381b480c2ef44782ab092d fa2d0b52bf1b930a1f0f482813498bd527ce090daa3f4285477aab43cd1c45c0 954e9aeee405d40869ae3c3ac2ffddae7c00e08574f8e28528d9efc994885f51 1ff131463c64c2c3a1b7af41435e737718ceb11fc26df0e48f192cc78b49606a 05defdd1653a375ee7b758c3d7bc997beff91c486ef9acd1f7407599ef9eb509 4db7cf256f884cbde45e0e580207029b4f5fbaa85ad7464b20e36100b70083a1 581797147df7936051e989bb4881f330344d5733220ab185292371438a9a7660 606177bdf0e2889440bc7c26fcbd0f17c5a204d1c20205dce16be9eb561361b1 94a10e3d908cac01a162fa1087d08145fb3db70cacf955bb70d51bd0c0cc2915 a40e979b15e9b750a010c4f924a6da214bd0a0356aec01f392e676c9f9d42a4b e4e6ba7de1cb51d81bf38ad8e9bc3ba7e3059b170566e6188e5dcdc197f424cc 0bb2355397a31022e06f6edbea574aa43c63a063f8287fe3de58a438193cddbc 1994a036f18f48016570cd7ce9c56458df51f532738e2fd45fc8e09dd53ef228 0ab9a2f03402f2b2d2d7e850d682cbdf1a82b34566059897b754188b09f84477 338c19bd0bcbabee027bddd1b819ad49d5c37fc77c7cb6d6ad64862e23ef632c e91daf7d75e20f04693b719c473fc61a15d3076e1e372068316e0ef056be00a3 f547d83a8f49db95529bfb04880da8d1856c39a35ae73070dc84b3694e49c82d a3f131eff367e0c26660772e1598e71a430daa4d7ff274e3c8da018a40b7f765 205875d30d48dbfd44277116bb0d80b478d1f8a0a83ab789ac0404fdbc03617a 92c1fe822b784d0dbfbb2ec60c8c8e9e9a797b807648554bb5105b951a3d9d6d ff72f514b8adfc2861faf09820604be178b7daf92202088a85d2d0e66bd57edb 223c5ca852fabf656ceb333b5bf01d7f1f37f2566b54b7c4c29a86f18d1b8ae8 14a1430cd78fd2039ac5d7df2e3069b24cb36b12f2576771da0c1911f49a273b 69df315a3694a8a96963810c498a765f95eb4f84478bcb38a8775797de768e86 e94d3267a6fbec3acddc3ef82a82bab6ee8b0fd4a7defb1332b936a5f1013fb8 ccf5a0bbf7e6addeed9cdfc3599a5a94e47c5faa02a3ba4671a4c008bd403f49 45f5cd60d7af60fcade4173bc0ed1a36091f206dc28e13844a16c675422ee1af b1907d4d139c71715303888acb530cf952f70e777b3801a0f402f2f0585d6930 ca8744c0d9e716417589570bf615e2f97e01a83992b36558af37d7ff28714523 fc201c54527f971e930f3d35bdc20ced6a666ac12d851398a7fa9f26ca509f53 6efe0cfea913636b65c218d9eb260c3b9ac83018e18623135af56184a418b565 e35ed29a37ee3eaf9d9c8133a0ffe4d0b7b4b0358d5889ac0b3dce4bf4bf12b7 4f336bedd6f2044ffb6866bf87bd50c3bc3f0d814b18be816f51beec2f29f1b0 eb40611822d44136ae6779a5586246a2ded4d005c83334cbeda1aed834b7f888 64b8c042003d59c3e9e1c4ae0d2ef6c1d151e02c4c5e7c36c7aa5b59b7a74357 e7ebbdc1ca40f25c085c1d573b4951e9d0e15cb0c0ad0026492cb6b815ec2595 2148ddd29c481bb590a19dc5091847a0a86d1a1f6cde6a8df6f594be8dea66c8 96c16cd72fb2150c2371c2313d1d24520bd660b248c5cf3ee368f95d7257cc0d 9cf1735d67ccbd6c29457094d09bbe4b18c3824e97168d9fad6c3b97a177f9c4 25cd26b4ae877a3fc7251903d65736fd36329f066ef5043d715032b1244cc803 0 c9ec6588ac6cc707a200c7d8d3706c74be5aced3efd7d2c124c9061fef31540681728c1c84e7ab3ccbd43e21aaacd4471b4cf605ed42e05919b8202323481d036d7343303dd58f09d36e2985707e0f41768613efc107e1ce3f911372b6dfe603921aebba2bb8c0cf6febd785b6ebfb1ed5a1452f2067ddff8bfabb38c9427b0db0b64ef0702e53c995fe7084407a681e692b689b43b900c6c7980ac934a5bc017f0fcea68b71c2f398911ad990faf998746ecb3a7139074a4edb72f0da158b06ac869e7dfbce2c0bbb59392dec43df6ca1005fe55070641cb4e2f9a098449c0d18db46278dd1dd0687d8c8df5e9b4c8f2b28cd304b32b60fbe144b9655ad1508391655bae6fbbc044aca2768605dd2fd29950eadb9d2595b0c85348eebf80001a975eb9cd8c1d7280d8eb4fff5a8583e85ec03b864211d518e038c28b04df70e08e3e5847c10a6c389ae0fac0bb738948c702df6643509541cbc6d72b0512705c026cbf1958a90f5a5c2afa868f4977aa0654af18efd20f6c23eba86a8cd3207bf8f599c70dcfa6c62822bc97a84f3e2c555027c444e63448f7e390bf9d9400023df81a5f7286047cf7ef6f599331360559011e6d223ebd7494e3f685bda7e03d527abda260db3e74c8d3dda5dec5f6fc86d0e06b689df5d5f33fa47b49ad40ab62897bd66b9dff75cdb66477a23b99e6e6fce13329a25e4f8963c5482efeb06f3f211a5ca7e3197c6959e56256444ca318b52b25547161a750b754663a0df073922158d2201a3c238fd558cad934d7dfb8b5841d2b08ceaf24f6d3f3f8d1d0235053c2dbb961661cd49ab3ea072c7d5323b73b9742d0a413296fafbc54f860fd6041859f72d9ac9335529aa0f120a55f56c41df4573ecc017c3f293a4219f09ad36ca72d7c9565730dbd4ec15c3493166bb8bd24ecd05ba50e19baae305c405688eb9c2b5ae213a998658aef5ecf98344d9ce29d1a4ba79a58aa118929c830b4a0331b6dd837dbb8820b33e3417e3479225dccdb72898e80b2a0b0f02a241097db0a9848553024adfd5a6ae0dded46db0bf8664e3119da60523b707481a830e60bbccdaf4fec18e87e5594c4e725d9c86b30f42d33a6871da9592c49284a10d39c97e208850b25043dcf5fb57c85e024e55361c163b0a0d31374ac92e40db08d8a149f7f7ecfde9b39afbbac78ef9a2f62015ce7e0f7c8d1dde4549fa896f0dadad0f8b2868fd06e7c5dc20fa1e8877eeab6f65a4c73edcce23921c989e0a029ba93869de4f2574823f1e1de909c5e1f773a2dbe5102223e61fa84ff70d120ce4a46a450a62eb338f2fad947ee40b66d3586c0fc9b760677cb0a64a6c128a074f5e5138f2cb639a12269f9326ac484334879a31d1f11fb7f7a6b6ee46c6a7053d2d30f871231942d5660c3d3f114406c683126b64918c19d5f90f951710f6024708e2f569ceaf166845ca952c093ce5b138ae6c2f33d4f307b22c156cdea00063404304e0bfb586a5d4b88f70a3a271e47de6c0455f330e0c7b94ac93d35c0309e9cda85387821c6ba956bd39b1c2721aee2ca0fc1251339f2f0a45d0e38c02faee3b54e3ccf5e6770560b80308395d10355dfc3caa120abe0004ae628c1e09c88f6e10d0431b1a3e90762d8f138ff7e54e97561a0f31ee9420a13f17cda1044efd7bfb956c812bc6ef656077557b7fea2d5d0d47bf18e2faa5fe3f393458096271979951f4307cc8a69d1f2eca3e0e386f159c9b43cd28729900c0646b5204f9959387c4d54bf4ae40b3bccfe312673530d2aac16ebbd4455f675bbd660403a6a8cb841afc7c01f28536762bc1c3bc57f0fde5ea248822a88034acf68c3f0ea42d352e5bcf51c5ef62c17bf0ade7321dee5de65a95c0161751c08b2444f00e9039b031eb277fbc08e45b8c232e87bc668b0493bdcf0d7b1498552c82fa6f050772eb6e20a111d6bf6caba0eac1958e084dd819396f08056e5141ea74cc2b08ffcbb6f7b2f19d8aba02fe0b09f6befacbd2308fb3fa91115975b6923c006e02dcbaf76b7a4c2efada4eb81d37c6a2be4b3f271eed710fd13e4170dcb9fab80af5f2bfe6cab56d5ed2528edea9256b34620c363f4ca9f064e4f937e26a801d08866b616762d65445b4d11be160928afae8559bff299222dc532486e8bc20a7008928b10428fa49b2b6d03a9914f9bf0021f649bfd62b32b4bbb8a85acf68390997440d34c1bc8b7a3bad0c145433ddfad62bb5dc5a79ec7990ba1ff36024a60988c05ac4cdc7830ec062934b4e4c60b1664006f1a82e75da8c87a8f92eebd10dceeca0df6af81a48656e888b98b5e18108e5d5d9424f448089dd4feb9a3b91025687f6584d810484620302c7cd27e1b17cfb3675de2f5977887307a0e8ff73021e663c816ce008cf979eedc9eefc8a252d577bd187c96883dcd50da771e09f02a4e9d6a7df61958926d317afdccf83f32d92155320d718f6b2f3230249ed73018308ca28a0a5d0c517ca50682310cca727252f82bb852c1fb79c883f4ceab20a2b3b8c3421b94125c16ba95a9e551e9e688a263023435b2c66db2446046a5404bad0e48ab943e93d754013ee4de57a38dee3a9777367dada4158ecbea6b4200431a81c33fee4bfef863a9335b086af8872e06dfc691c04e10cc15b1727344709e2b77db6f6ef04dd4aefaae96cf568b56dad2ef0ee91ba79a8800d8caacadd07f8ddb4c72519a34b5688eae4d6c99517489a0acd3094ff34466664664ab0060f92e76bcb678b52ba78309b89b5b27e082a02745f60adc650fa104b66fc2f5205b2b87f5cb966a73ac301dffa8c50723b433cf222bcdddf4c62bafee78c3cd30866216d56570464d76f2c45ad4d262363489887589cdf787dc66f405bc6a66c0b85c9dd5d3418d79ac8ba6e6ba49cc2a45807a4fbd78183cc3538b2a93ca9e50d964e451f9ff097c9ba6ecde12ba25d18ee0917fb5a337278d085fbfd17466f01aa5e0a018f804e6cd08e22835b48a11ab8d08a10dbae6a511f4e1c5ee7c87e015755356f9fac2f75cfea0012ff04fdfeb4853ff200d34ccdc7ee62ef3b39f50471ecbdcc0cbf1fcbf7233de10b141a0b4fa167932a22e7c94712ad0ca9b00f08f5cb26e11765c1075a0608afd6e10671dd944cad6eacf44834ed32bd1dc5e9039cdf55334debbf5af0b5d7716afe8885c4e447538a051e8f355c3768af32a50821cdb3dd16c6cf865e278883281ab0813c8184f7bb373b09a8a416bfa9dfe8052f1c2391a0152c43c0b16fde0e74a0c8f574457128a9a311421fe485621fd80969e4d2b8886de5954dbb5ee85c8d212c74e8da355dca69405d8c3e006d509c030fda69ca35bbdc55f8466aa5d91ec91602afc111c2896e9758240df684cad008a7aa75bad2414cbbde2a0b1203fa27eeb7e121e726db0d5116d67a87ba12a90c8405a3fcac5e66e154fe1e4df99f2cfb5ab1356f005310739049f47181d4fd06e1f7987587327d506f10de7931e5c08954d80848b53c4f5986e501d3ab59760ffecd7189f0063699e6dba205d9a90b7a91be2badf2e693b2f77f4314bca2160b1633d4f09375d36925856556cebf3353a477d6085e2f3aecd4381773bbbba70735480e0dbd1ef69760c627e2eb9dd0a772111c4d2c9cab14e53a41d832443d03f3f6c3a5a6ec67c3286b230e406820d245dc4490a9007ae7a92455ea4c80b900 -generate_ring_signature d6ebf139a45ef1fa4b4be6a9def628430e9a0ece08b67e60646b44d7581f62fd 009fd2354de45de4f50f4171609d01f3af1da8c4a966e6613656ab7ba547bb4d 2 6f791430dc6089fe5726dcba4999c2f277ed2515275152c3615756c85ca7fce3 fb5ed1804e5b50fd5e0faea33284e7b91d9d881a69067cc49560ca97e1828d7b 689799e5ac8fae88a1fa82a03c0dec56a2ffa69f983d929bfcda6ea30e735f00 0 1f3a9646c1e9c1a54114bfe70605b849d0001331d297da070a524f20782777096d5cbe0511d7d855884e5ff5b1facbd0158ceba7deee8ebd5dda35cece103b0c416ecd95a60c405dfbc05331d385ae1b53cc06fff212db6b55f57a7e3ea5ca04fd0be79230ba3b22bda44012df65f57183a9718aff784cabacd38184884c3009 -generate_ring_signature 0ec44a65dc63613b9be298c6039f1c13f58071e1b8f642259fad92b82e70ea6b 9c1b7841db55bf2d432d77363bf8f7871946d1028ac185176bd270b9b1c8245a 22 0ac06d71a291bc9cb8a65166f6e267aa94f67345780fcc3a88990a1fa5ddbbae f4dc2655b78a75a5c02d1da6fadc0e7df8d10024cd2acdfa75d6b926d9df26f2 b898a4bc2437e9c7aca7ae42b40b9f55801251be6a22e06b35cfdb9b519fbb07 5fad8c5d05bbf6e210b426f1c85cdf65c610189659bc1dee66cb48e155b4848e 06c86b3de6e5b17a6b18bcc3bea96bba1f0e53011abdfc8d983e7128686aa565 1981523626d0ebc509c4975cfe7855f5935518d53bfbd8020103875bb04c54cf 71c3b087b4ac47bbf525fbe96f827dbb8ff8cf477ec15e188df1f7468f12319d 76ab284bb2b33394e49a7b9b6ab4eb0fa9175f8cc0549099afef7a425cfdee73 035ae37614df557e2879632c43dcb2a6e731f45ed71d4c24813a2fd0b33e27fe 4619e99967c91eddc5bbb3326d8bafb2d91a69e99120dd426dfdbf0fece87b2f 6c25581aef5948e25e70cacf2143b8aa5d09c4f0f71d6aa72b8f97acf504c9a1 035708993aa26e4a03188068a9053b2c4daaf5e7fb6fb5b63e4c5b3d5fced851 7046c37e9f70f71033fd835f432553e867df9ce1f42bf67e883fd1eaaf6fcd91 fc9c1fa387d94e42b000d5196cd36b4d9ae84e1a4cf2de91dd15a8e9c655995c 80c9ac968a6a22f994705609c7f829f80e9c56786ea24c1048814c9bd8ae39a8 4d7eee539bdc72685a3e4239f78c67756fe3972e1b88ec61f5ce7de6e90cbca2 9f080a14a10352a412dc2067d03db1e23a55fc00e1c90ebe2e3edf4c9067f8ea f124e82150067aef668390263f418cf8bd5ce9a01fb2907e6847231178f4cedc d28e3033f536023ea168cc178fd5c9a9e3ed795f8598f7cfbb973122a860e43c b501e956550a6e563a89978557633f9d61ede3fdcb4f5f73b10fd98961369c19 a7c9d688441935ef112dd091d6f934bd055fdc508e39f78035da02849b5e374e 5585b13645eb85ee005065fdebdd45914a3afbefcfa4d5aac0b2807c21bfe0d5 ef411cbe80bc6bdf3cf2c9ac140669cccc0c9355fbd42d32c545a67b3bc96a02 0 aca697bb06144d55b3906d30d0d450341c71864b99d9f1452798777cc484b8025fb67b8d7d930239fdcdabc762d1994b89a91c541ba2b0ff77c3d19e7fe71b0cd4e45a89681a1b412eb5d4f7a4ed374ce365282cc3856898961fa6427029040e451a45d6508293158dda5d7aef9be79f430e126d35efda48a96c2d5187e677097527728328fce97d5699090ac1deee665a9f0bdc73d5fbb2f68db89c35e0120beb46178a1098248a484f2a8bec5d839953069258ea50db97bbcd347f206e1d04c92421b273f6a14cb45804b6cc406cfb16460c96d29d070d1e77a30cff01020b4845641c2cd5a4289f86dba16dacddfc05fb087454199a68d9c4ad448aad9f00ad13aac6955b148ca394237ca8d607a168ab1e9788357f6b8c71abcb5afab009ea2573a4fffdd9c77bdc93847645bf39fc08f02936efdd737c6ef9f9fa697505f42530421a12759843125ab0ce55f491780690a697bef1078afe63a7ae782d023a310c941fe87d9df0a4da465403b88d10e228cc540578247c7dee57fb598e0f5482a1b00f1f071ed43e5a9b5bcd165a8af1ce8fdbde6dbc2b90d2c8c97ce00da2cb537811b79827ecee21ebeb477c1f0fd0301817f28774ca21c812e6f3140c0b651f08439eb7e5d68fc6aa52fe5c3466103d65f65f2e60a303b004ed8a6f0b3e2bbc4e9c43ce1873a0c6f15898f9b1bd465c06ce483763f862c45a7122c100d37196d463d4a511d3323490961b9aa6a98379b5c4fd2de367229e800c45e201a08778d829f529d38bc23e1af382f8cb8b5b4b2f8f9e2b1b954ce99c4ec2ee07536f04960af4ca938700b84e8bf3663dd80f4e6eb4e5543535e417c0b690330ab17413468dfb6258f2d6b8f6c5ae26ab902655e92ca3c795745b5799a0436d0a0a67e9f8a786f608669b7f2f3ada944e9db979512b3f89b64842533545f611094f319e0f8c434de546649b8213b241630335201e350cc9c49374c4127b96dc07a1a86c5fa76dde1863292eb7bf7fa33d9f254c63865afcbb0060c6189553980b247168b2cab577006578ee58b1cc93c53f31a8197de6b908734a84be32a17c09dc585f7a441016186ddc8b4026b89ed255a48c5df17a5257d83c75799b69660e64873f3576357d10656e0f399d334a5ce77dd7633498535ddb91c399050f63082bef1f63d923bf9fe6fe2ec7767aaa8dc1d01c9d396228e2bd318db4c1b4490e91d767ab0f89af08a85ec0b1a5e5f5b664ecc53f7a67bbc9861f4cacbab7b40ab93ce0780b42ade40849e8f51560becb47aaa2c5c97c30f9defea8d4e86d110e62603bc1ae24d41171c1a63af6f18edfa7949af088d12971059156975be9c40e00933b9cf66f8c691d29045070532d0a75d3c155cc6c5c89c811158fe439250038ada81184e0f15ec57bdd814b10915ac3dae65f57a47ddd875e8d9ea35c80094b89a38907ebd6b5c28a2aa87a64e4994a4799b1ad48206c64c9ed62393d510fbb102a4060b0e25f64956b9b3883b21df88500577b2632f3b8cf53aec2f6ce0f576aebc66d943b71deaac22d455136e024d318f6c6aff081a091ff6dea200406098006c1359b4d8613cb8ccdd87a6da93d7b5ef7031d54ddc8afab77d134260cd7f8292836dd49b8f0d44acbc7ccf829a229577b928adafe8331010e0b90e70017dc056496d6b1caa56929300911f9ca8ed42544fd7a51f48f777573e54e060370f005a3801734c8a3e4cd783f55a6204573a282ddd0c3957d49bc30d71342098899eae59702de18275d2a6ca2e9d6e2e0c9102b87ba2bf8c09cc57ed18c43092940725f044a0d73c7dfd04ae5c5c12efa99c47ed0942df7dfee0e811e4a8906015a70b6d9b4f94b6fa3f35468433d1117ee04937575a6cdd1e9be0a11303c0e95dc7ff3f792cef5922a19d35b90228d2c020830ca174a38772648d4ee11f800a8464ce9505e48de3c5653bfbac11fc405c20354d34e745f90738bb5bb200b0c -generate_ring_signature 93493d23fb44416ee09be43865923d0e1dc1066d56f5a3d0de81813af3ba0dbd 7748c0a5f3f87b8261d37a2fcf576f3641db82845d8c9baab1255a025e947fa2 27 2d160aedc903d73ca9290d7a6ab88c0e9f34d8d1eb85ff0c2123e1e619aab827 7bb969822d0b461e0f71f8582559be4532c9f9ba4b98a3bd8037f3ae2cc99086 3973974ed9fab1a8bfa2bd46370a22e6aa9ee366333379802af5647a360dd8c1 d6b7ed18d47a17ddb488bbf95b3af8435f2beecd767e1cef3bc7fc0a4ef7c4a2 0b30df77534bf83ade55d67c5525d900a8a7a4e45d22af5d3fa8036ab3ec3a28 7fbc57d8de03940bc6ee8cf3f5598cf04672d58cc53793c1f62e0f193a2cf264 300807e7fa48d0b41448f7307d2e53d080ca6da2dbe0b49856acbfb5ed7e126b b8caad285713bf9beda3f580194fd57152f67aec0e70a93c28928f5f486f59c6 a07af8e32900154e837d3b7b74d5eed2eea6b5fa431e09f4927256459a381021 73aa4e3f354b1059b14d1cd48f52502231c181cd06d3e377e93ff7d7e4493348 ce6d6cd79f36aa44b40bd05e6a087cde2fda0d82d4cdaa6e2b0cd36b0b3803a2 038030ecee860ada3ba07323cfef9534ea0a90d2b5d30f2af5cbadc1bef72e60 dea728c4b55cd4db70c5c69438fd75ea5180675a5b9d66c02fe1a7199e9bdb69 f27326d480de4e3b79274bd526dd79d24f11ebd046b9a8c5b376c44061d23a9f 136ba04808b1ddb0227d549f18e8322002c8f9e75600a3abd5c73559ce0260ea 601eed6733db13d4cb81bc73faf4f9f5af74ce56405f4bca0a048333bbc439e9 3c0c6f776ae4ee29c1c691d0b57309ed56b96a31a945079f41d3ea89e80f32d0 7249c2ae5af899b9283262f07f522602c6d1bf3d88ed92e0c1b9996d76f0447c 9518aee525652a3dcfa5a37d3844e7b2bc051db5335ea438673b94b01a04f8c9 2843e804e929b6da93b04026f44ee744eb364f20610f686d5a73fbc43b92663d 6b5281b6cd170d9cc7ba7bb56af507aa3dc21e816f0acd1659a908ea9a416366 ffe9b0f145fbc6ea4dce6273b27e9287654cfaf82accf33885fae7b152fca9ce d1bb3f05ab3be0fdee933d8492e1c5cc24e7488e44c4258dec75b4b650a9892d 8203602357f52070b4bcfc3c5240704ed87ecb93a0b4812512e3db7d9d6ed061 1568a18b7fc569e1cef7a211eabd5da6fd118cff94cd726d1b4d988598a51117 0080b6bfcc6e68ab3bd176987ec4f0ebfa08e2d5bd6901cbf24586bed9ecb4b6 6b608f086d9d4c67f3f1daf684659a389c5c9140c7b6e5ca71ab5b107cefdd79 dd1d64ade0adf36ab84cb537861c99b79a6d012ae1f994be411baa76db298b03 0 bea6d698f5433c70952cc7caeaf17ddcb69f63d0d7a4f67265ddc34142723e0965c0df9366b2c4e68dbdb9ea20baeb077e7817f05c7177f1be1f6ddf8452be0bde569a5578ea72513528aba714f00676622847818800c503e370e41b8150be056269f26db3dd87047b8a482963712f15089f2ba6c1aad59b44947fe4e3f25604a9e448fc52f5a50f47c0b00991addfe9c2b1e41ae2eb813065c181a54148ba02695efa2cb55dc8d84d1f574d03d9e0295229e6dcb3b9eed50f130e91065daf047b4c8350a02077a31d59c5cf73cb70b8d65a5efd6b66beea277032a4482ed60f946d7986e1e1793a5cfe16723af882b0e467d2d8d8c68bacae688dc5b5ff2a031c40f15a610b84b55b443ae6f7bdc463e839688724f9ca5764b5822f2b4ded0ec9ae74df3ae9b855d8da7c0af915023f81155bd602c55ccd76643b79ee6ee804f51c0dff6a13b4396a551ddddf56f87a908a356aa2084c241dab30ad1f5cfa0a5932eb1e3f268d29e8b70c2d67d3a100800e602818ed1582378b7494e5226b0d439ef4bf56d18abb171730090fe6a8e2077baca9588eb8b4568c4acdeb09cc0b9ba9da84092772b73a02c10d68904e1df5211e2314787cef870eaa08590c010c28cbf16fdd74e52d987b67b580a3b756c9bfe9f972874814ff00d9123c774c0a1499ad079044c423a4063a746c221b7196e46d0ee3cd727dbbb2b54a98def806ad3b71731873ff59f9322d2aa05f8d3f4bcab6b4274253f3892375941c72c00de58e2c2b80002ba3c8bba8bc240d9b9f2c28a9467406011604037c2609cd830cd4edd516946affbbb55050c4e263654d1d766d4f391f2ca76eafb48cdc3e5f0666f058e007d9c96558e3837991d42d69528900f804780d8a7ccdae4772cfc90bfc13ffe902b0312568990758a5e4526f4a623449b1c51aca4f98dbd21fbd740a665ca4c724bfac62d510bf0fee0daebb042cbe407b7c9d4bb45f82b17a849803090209a422ae6b579dd14e015ad5b4730fad267b0490165398ca0538d638d70988527e1fc8967c07bfb39ea958836c5df6854cad6f478e468ebdccd9c7abdd0cdb41fb600c43750a50d369c502ed069954e1f3eac8379079d2f73846b6464e0f7711c2df43adfa9a4b5e72d39bf1c965963748e489bf0ec0827ea2a43c74530492c34d31c156eda9fe249cf663d391d977f93d07577b5ee9102c9b6718ab0e0c91fb16c6e2be9986fe301f09e163eb13e583bfb7c660f31017d2e5b67337910b18955c54d4368a441cb3832bdcc064804129a587d2e1f5f1aa3fc48c1877e305793fc5a7b6e1b3c46a5b6dd2e1a3cef701e08d06d6620009ff17d9f5f8bd310a3915fc9620a214b44ca4330ee16bb3547d21c9071afb83007181ff63ba16cf00451edb71ed22be3347ebdc53a1f01880c7d3fb4a57df73bcdf213cb557b41a007e1a65e5aa0f627124158d05d41afaa1c6045519b6bdae349a41d06709827507ef59db9cffd08bd51e635879e6ae1bb66cd53995bd84181e52b3041afb4a170d8882369e2aae3edaf892e6e12cafde26862447a91e518d4b1ae26dd68d5c6a0060af9e33e4e890dea8a4a791ccb27bc575b6661b57f70434e070c9c410757102d62a4222d814429914e376099387c35a613b2b84f5b88bc68a10d00b88cb3805af4eec30920b5361d68fe562109d816f08a3ae2f48292f0c37f72eae0a9c610c91182ce834cb8640e4ad8658fdb0ab0c5607e93eabcfbf6c44997ed09d004f07afe14f05f5b8defabe47244bcc50a0db18ca66db64deb8f6672a5047bb76060ab1d0ac9aa708743f36936433f98c18dbac3545d36f4cfddb0455951ccd0db1090fc8adb82b12308243fadb52961b2068669e12b73d931a34d7f9b1b95d22c00e6243c01d061dd6bb1f9b49b59decabed3fc2fe9c643d61e8b90f839a4949e90f35032aab34dca4c06e4e3832186a8dfe05551a7c85eaecdf4a0388a69efd2204787609978f997649e6938c1572ba589c551d2f63f65e9132053fa5039216280c59210de7fe150f42777ba6453fe65ee80c9082e8079a202d90d2090278dab6032be9732402408d8498f471ede447e4a08bf543500e0850b8946f949450a2230d882ab915e7b45730af26f843949f22f2f42ffb28ee075358c3bac90ea2f9710d99e913986f3bd7302a8c843dbfadd16352df4aea22da55e79379457fce72fb04b2898ea995c9b73d03a152f5c4c41940ac13fb049600ef29445cd812d8196d023f24143e72586d4cfdd1273cc8d73d9f829df19938a81bf5c3b5cb5d1266910b1d0c65d258e7f23e0742a53d470cd859d82ed831c32c946ba7df9e8a956707031e3a5480623301c3f92bb429e5aa8b25b24125c2526b17afab1b74493353c90d3616d12f19a38cb37db8e0bc5b55b89617b85b3343c8d805f3e102b5366bcc04 -generate_ring_signature 47a17eef9aa4f45e349474251fa7db40f4dc3b2d9cb74a0f63628730e4f087fa 67206377b4229f14b901ee725025ad9067500f80708603d343cde543f6220070 16 b9d6ae2e4275913b39ded0e04f23f415e21d0755e6f5f15398ce24db187b80be 7443760d12012330c27c0d958be3f5bf3c543ea087b2e710f1df3aea40a3597d d58c7950dfa2cd1e5d5958b03665844c4ec07d3266238af73c026b2df9c9d749 22c2ac91231c9618673ee8d8cd01a3fbfc915f6da971019e5ed1c04cb848eaf6 bf376c083d6e0298d8e0bee38fc8a296ff9db39661ff0acac51a7cae47a528ba 4d84063c54fc35ef611c69679d6bf8252aff307262372e127ceb6ce28a4eb57a 191d335866139d9a9d70172dcb623d9d0d589bcfaf29d639db9408105350a6e7 16d1388ac89e6e7be13d79c597bab902ae51c727f4003e0e32d6a9944155f5eb 7161b56af7340827dceb9215c1ee38f21479d7deb8ca9aad4cadad12dd190762 eadf42743e1b0f76badbde7f1b5600c599eff2855e4af3ba1e832b56c745121f 0113294d12228749802c3502457a95df6875abd7dd63631232e319cda4ea7176 517b3628d5b1f6a781dc2a65084e515d45f745a55acf671b478d2553006ae2fe d1a16b1897c1379411ea2bad7ff86ac19c519141174182de83c372da21e04676 9c6e206bf2d21ec5f36fdc489e51f9748d748a8064e5ec0ed21e7210b6075d71 fa2fe7158dfba5f1083ff8db88ca7510fa17a08da7da486f3194297ed4ed0afd d467bdfb269e9f5e8c72cf6c27b5c7eb4c2beccacd7c0fa37d22cdbe2d15807b 02584ea85f70c3ef4912ee658341e6b6dba3f2b9e3cef23d99ced95aa50d680b 8 a40c1041eaefc3bb058d049d1d27265f5010428ff77c469fb1540e8c616a380993741a55f853fffe8f63159741fe6472bdefcbffdff49467008c3b45f45fda024a4cdd813b7f9a83328746863f0acb9dfad4f0a79e493166ba0e81f95ea98f040ab85093b2a1f18d58ba5d3388a50a7be32ce5e13b9087b9c1c1cab2be98f6056ac7bc41b7795ab46858ce7250ce69cf567d17acf4e0d885e898a26bc0d8600ed21c79a9642e20db569f02a5e5762ad5fa7dbc1de01cab8c5dad06e0c327e4065ed4063b87d629759d18e5bff5eb23b184e118e06326f0ebc015aa8c082e30032da8a9f908689b28b4d68a2faeca724b8a3fa4a19400064e88120aaa001c780ac0290d023b71be7a6164e50bf3b40b048514cf780ceeb1b959d0c5419e017008be397a37e7125e3e0fe28dceef3d0530ecda6853ff8e8c9ae8be5aba50a48f01cf4050224dcf77ce8c641bbd98b61ce2034753619ca96b99ab206474932ff2091ca4b0ee5efb1e722e22efab6392bccc03436434ee6f554ffbef847d841fe701bbb7b4fd8b3f669c2c463f290f492cb406d05651d0d7ad5d5d0c59f21d07510a0ac2f7d8aa9f17868a69aa9c27f0aec811de5126ef073737d1b3d9e202842b009ec25bea5b571ddbcf5ae407ba4b5fbae1b25323b17bc58fc17ea4bb439e6800a661f99fbbc3a4b8f0b5c7df581e59ae1a48fc5bf973548af75da1891d05a800a4d54d33e57944d29795c26d25e36e7f64fe959d23f1a01c794bb7e7eb3a210fb4b280905833d866ba86ff5ed90248ae3920e338bfe6ee173fd59b3160b84a09de48bef6ed248ef54510ed8063158cabcb1cd1d831e24371e1d8dae3ee25380d068e61dab85ad6e96c412941806ba9f3cac029f3f4877c904636443063c716077073c657eef097f972a81cd7e663dcc05538b6a3dffb5f17c10478603e06b60a2dd44dc881914bd8ee321e3dbef5005724abcbde7bbc013244f32463b1edce02eaf0d30a408b981ed8f58abc6e3e353737e7e9d4ce242e6c3b9caeeea9bbac0efaca348789ac733b1cf0009a18518f7bbd9cdb14a29cf7400387b395e0512f0be046d4e16b3f796f938016a263535c43d973e6c687405b52370627af9a11a304990e02474b54a2d999aeb53a10ae7f0b167ba9aab3064d8f5c89384f71296803cd71aaaa0d408ac449ad47f424fc15b6c63eab1211a1e3949e1a1c575047e604590299ce3e4ccd17484998e3dd92570d9487abd52213eba890b810ce1f16a60763df8d0229fe69d9f44a4e789ea00f84dc23256de7075f989a9dbeac670334072e1ecf44994057baed72f5c5920de737ec3b23b37397a1df52dd22e2c0ddbd04bbb10a48b14fc757eb4b95f72fd4a6f6191a950a3d2bf83aabeca10f7b8fb80a461d1d663d78e579e24123448beaf5dbe636fbc5de1876234e84eada0fb2290a -generate_ring_signature 9a7086a8ef73356a7a113ae91f791ea57a32bf63cb15766556218bcb2f7582fe 9eb46385239b056e240bc6a1180c51a025b0837da355c5d60055da138d05cf09 75 d716b1fb66fc9eb0d801d13e48a4795600b8afd004cb31bd7bb69ac7bf26a5b8 facaa9a563716b9d22e3e8204e8c38ab90e4329812d9bf33dcf49322105ef8bb 092504da28d4089cf7fe33cbd6cdcfa5ebf9ece75d42805975564bdcccf34497 893aac484591284d041d6cab92ad3a0e187834520d90b3a6686276070ac380a7 4e8670484c0779ba9975ac8bf55da8ae29d278a0334b23e670fac6eff5bc133a 7fe32c5fc50564dd44faae596d56dcb817232c1e50385f248e6dabcf382d0d20 5560a7525b10a96fb989ffffaf9c2a20291d0d28be117be81cf7292344c26a89 7abc90f8cf53e7b31349994334ab3388d209b38b0a1747d656b064255933b80d 4b5931de92f69f1272ace927b49149cc942276296ae99a42e52d7d83de3fd414 a2e67069563571d1eb1f16694869da1a9582511ea81b005eecaf1f63adcd779d 23c1f904a58e6ca0d91c4caa3dbd7cd5baae653299b339f9859ce870200db57c 19d779d89ba045aa643e717f548b247156a41d35e7be773d5775eb452587d44d 68e999d5a013b3d945434a46adacd5a2ef18ced42ee0259d949aaea9f06479d4 f8c85c1538d967eb627ec666563cfa8203b978a8f88a236f4fbe179fa791c596 19909e7839625dbff33ff26ed186110acd7b34179b0e55fafc84a71b7a3f7e31 53312455ea259a3056ef247f4b25e63a807fd2fb463b0ffe1417cff46ff4dfdc 3380930deba9c016b036d71ca525f349ddbf582ecc80ed127da3272f6aeea4ac dbde3d341c05dd02ad333c64a9bf35866b1f44da659a07135875cc65b4d65439 06577af36ac3f0ac371d8a2167f637c741b9d18a79afedafed8e943a081733d7 944ef7b3bab2fd90c5a46437b068c23d4a5074ccf0d0a6fcb960ed9763c0b880 01cd86208d37c5512d16d459a4581904d13eb862fbf9e34c24e8a1c3233da0eb 8a10901b4799674e91e6c496deca1f904b720dca6c3a81364bc2ff03a7e57897 339b3dac7330ec98d76e59a6e414629a1cd465d14402c6404c9655036cb5a010 c0f2a7cacf16277a4c84b115d21db048e8180a15b013af3f295739cb0e5e8c2b 9bb9566b6ebb7e992a2e6138c810873127f3406860cec5d3e867f676f23cbb73 3a31153daf08deaee78252f49b658c875d195343bae2a187c16465b4615b64a8 5047c33140837bc18466fc3d1e178179768860faeb7ff166f65450d53c7dd290 bc66bc18c1d6601746fdbf34d4f9c4e7213079d15eb054cf570edbb66ad70591 fdfdd237e667d70a530fc4f387af0473f99a1f2988dc480ac1606df7798798d3 d982e4a92446e08a2e9dd91b155e580f3d181bde1d5f5e69a6cf5e82d35607c5 f8b566a67779c1ece46c432d20b280c5cb8da1184f7eb242c33759434d7fcbc1 6fcc2b37559dd4cfc22abb8b5fa07eedca9d56ade5372f2e4a038ad1d0b92c0b 15ba3fe0679958f07c6deb5369d356b48b668ec67d4832ad33ff37b0abcc629c bc70e3eae472a511ab3e547f91aefd53e40dccb0b030fe7f0f5c382f41337be6 e74bbca25c9180dbf84ee1feacbb9e6d0514cb6acadfc7fe9269d8f1441c4004 0a681694b9181b8b0eee8388c9714f2920c63b46ddc955643d9ec4781c2a820b 377e5e05a7d1fda80259beb3d2d4067cf955e08089a74a45b460799745a52532 198981c0b8d166af3bff21e762bd85cfaa43cd7241d7fa611905b4fcc67d6236 1c533cc6c0bb0f4eeb97e36be210351f39b1a4ab10b7a339e92aa187a6e08679 955803e9b32dbf08ea6a31dcb5bfa460976d058cd5d35fa2cdbd446dd112b3b6 b6eff72cacb508187b555d67f22abb6e73ef2528404ddbf17411ac4510c44fa6 f55361c4f5dda43876eca6af215d10fab43d1fa4f029a370a08996e08fe5610c 38d3a3e8c7d263cf018d96a9c81737c34aea0b2d3092b63d79ca96a2289046e7 5a6424e37427e45b539c65f46272da6b578868ba83a76e6a0ac240c3004ccba0 80d9e5a24fa55306544acb007c88c87a5c65b6f3f814d3138b56d914a7c1f046 7635087c2fbf829094a693322f3f3ade9c719ffb418e5265c0186f4604a294f9 00ce84cfb403560546340864755a5e399e5b2c061645bb7c12a7c99b6098ae82 dcf0053ad01d6cb871a35dd4f255956e50f487ed81b0135862982eb4843df3e1 ae49f8be1790b697b4e8dadcfdcb5786ae07e2623798d494c18f22181ee1d4f2 36cf774f577b9ed47efc0b0b8d38dffc78e6372ff1c3326e336b71600789f487 e30e26abc6a8adc3d0e8a226fee82efdb0462b698b98a6a1878c640cb1cbed61 11ecb444c49b4a7571625fd56f8e30c9008cdb5ca45acbb8d8b716480ca9bd6a b89f7406af985457210d4e406755e995cc07515a414c0c6f751c4269ecf03eaf 7456e8c3d729f835db509c26a5b20a9349d73cd5a59c2f09978df89650f7db88 378ad7b8655c6acb0309dee66ac1cbf99454869528c5cd45b17cae0386db60c8 86cd4f6a7bdd988a848508a368343b0fadc1193111fa561687db3cac67e2696e b62cc61b3a0e5cc7b99bf1107caf5d810d95ddd4102ed701d862426639bc3735 01b43550d9efc0413fededc10d91ae556a36c29151bf36e94c391f162ca325ca 75c92f49af4ba741ad911d40d2c4e021927009b71602601d9432468069caaed0 4952e76de4f8e470060e655a18c697523d7ae0563ed61dc70a54cc3830e3c988 562ef593d5dd96f709bb82c1b59ae43ea34b365a05026a7344010abd6c419fbd 4699941b91092f0cf560e7f9f35db0295f952f11c5821635676538495f663201 ea0d5276b2de554255c56fc0589e3795fcc9f39234b354ad8cecc554b7b8f6bd 685df7e6f427618f22fd206f70ae5b44d71f408de837502005777fdd92bbb4bf f364ed496716cd88da9cd2b9b404f620868e8195de8d2f367f2c4c80e708a16a c7c368adbe6409674f1a2fc603ae4fdc1a7cb31ccead9b6e1443a6bd90fb35be 248ec8d63f6c5cf526819521d866ab1bbdb6cfa84b0e87dd8a7ad7d1a47a841a 4dc9ca992f062b7a011c372b3e99f87d54de6883627d42cc97bc7a576a551d1b 3dcfa728ad76ab77e634add3524207937374f3eeee11a566b5babddedb647fd7 77fb0e227ad84997ef3a5f33c800b7ad6033aeb0f3eca8d688abc8008dba62c8 b8990b5dfe159a6db927724d9572270071593aadbed7d4e9b9acc4a1458afb70 72886ce644da16d21a4eab8b7d00dd65f639a40a5dea3579ad7923cede155007 6ce176ac239a4afd1d9f61f7cea9286ee6b5a6c3f5d8c76c02a3e6c59600deaf bb67aec3e0b94a73aea72380edf585f9c47232f471b81ba1725beb05d6352cdd bd4034fd4c3d280c619ab29786e48bcf7bcc8e839941cac09d57eee9a67f0cf1 2b9967f5aca1eb4e0601d393b1989438c1934a0b0dbdf515637c2fc7c9709a02 17 f87b7b46f6e5064ac532e94bfa9383a8081623314eb3a47cc7bba298674a740fd8060cdb214b0ae414845662fc04687cd879a6d38d42b47ec048898145e68002a54a79ac4362ce06f7d2277648302a21e34382b7cc2c0e023bc0df5bf8e1dd07f4dde27a71085f9168c403c8f939a304c5f38e527cdcdcf7012eb4d64a7d11078277dfa8c57763271caff630e4bb2879c50f4e6bcd09619624b1372ae8f074044f2504c4d7d74449e37497cd23aa1961685d41e8ae35e8d4768c95749f1f9308fd35da60b895712f72e4fcfb4a0e5d53864513183afcd5c43d4ac9807d56d80da444c730e68ddcf048a78a8f162a268d872e84b053771ea6257a94549efdc000d1dc52f005443989cc609443e4fee4a2afbf420b8c5b0b44bc0da731cdc1d80358a4c1b47c9b4351752d760b45025aa4721b934a407f1ea096f88a6693932304f4514001a93582899773a68e6c63cb844ec4dbbcf2f5492d31ce3daccbc42b0aaa4ad238e08cb446c88839ab5889bd1ad120142393e8c55f04532f3f38060f0c40356f9e0d2769564eba415012d1aa74391dd2c54a45ea3bc995968608a0960568ccac49e52825d585a07c288c628ff1d943f30cb7aa5b652bedd37c4499040f49d83f8b3aa4d4f6c65356212d0b26ed2c6a16a2d786e4be3afadf70bdebd407d615b41c41a80c9d339580a17daae33501fb42b5e3b695f579c2bb3527818305592976625bcdb79d2965fb5cb240c46ba8a40506151fd9bbff4c472ff421c60408df1984e029617398296eb1e9678e7416d0209084d3301e1d45487d51f74b0b316d6bf5afc988d7402bcf14549c740f477799cd6a0dbfc67de22fdf8e9a02077e81bdf026f0c71a366b6c903030a72d60dfdc7b442b53e57cd60ab912ba6305becd9dc1e5207b68db934f1c0bb6ef7be553e94c517423214d9811048c97db0f7a58392b53522c938ec81016d4ae7735b6d9de1cdc049b57edb67855ce8e7c0f475f2bd16fe3da64f040e3037be77c1243f13b340b98b7791ac8a763136ca40cba66f9735c20627728c2a9129efca42bab42a2bf9edb62f43d3bcda433fe47026731c310d0196990d47fd2391e387f0fafd71385bcc098fafe8c01a415b8150e981a0bec2238bca76abe80f07d4752f50d3d7f5b9c7c9dae58281445f8aeb30dc84de88c4f138eae11bdf4feb9b4c3296319e774034c9ebadf14e25175a6a709b00b10fed2d75a40293b2777dcabbbcec7d713d4ce2db9a64b929dd65189010544cfe03c8f3f3979b30a3d5ce17815e36f03f6e7b9552f96cf98dab4ed0c8306d840e78dc0ffbc9467cacc058a87e3948b371cc93def309d57899e26d1191a022a3495a39b7a15a425675260595af6deef4bfa8695cda4f42ec444d4d4868b09749f06d7d2acf0f537ded7d32bccc4f17f6c34aede942b8fb9be350abab5ab0a6c328515db6a0cf897f59839d85be6506e0a4197ceb3ceac9c6043e6e9593708b2d2257072c46d0846e46848d28f7c99b0361a76e0fd22ef7642ba95f8dd1804c6e62ab836d4e06df27c2182f6b7fe5fb8d83432d37a656dffe62d8630b2180a89bf89ee905016b54b01c03f40985646a3a5338bf9e7675df2ef9c5249987d0358044a274a9edafcc314d902c680fa885e308d17f254d07cb95a41961df7be0bd7d10c1eab703e50c3fada009bff2d054524315132b27d660a97aa600ab4710dbc7c1a7f94420ddeca4cc070b45402fa5f267016749fa471f457f87e647058009ef22567f7be3d81bd72f6db6aa065eda0cb7a2fdc46d2d82830c16f13fa8b0a2e213790d8f0e403e93d1e8ae047dcbf51486f647e73da8ff397c72e53c2060c3eb05c88b60997835f4143f82f750881ac768230af688d267bc200338f4ad903faa91a93d60f5206a6cfbfcd8597419d0a87923fcbb66bbbdc139bc6495a710297514767c4ff3e2fe52dfd0b0570873bcba18c2cc36990253817d388056e79096b1691ce2473d4ac32445449a8e686b62b9a373aea9cc44d5a46c2ff5adb960cc218a24e1a85526a751d7dbf273f28ac238998e253d35c537f665482658d460b6faf6bc51c0012e301af13c403429077009257765df26178c4b1ad69698a7101a77df2fa2682ac01269a0fc4eef569cc277b1d13b4c1b04efb86823b2d8d1e0d58ecca65966c492929667efb801256d8a26996c8193aeaa54e8c4c026b7b990af04889d455f84a4fe96ea86e2a96ea38e44871414b53d126391183ebf9f06509e0709044435b885b1b866047f6cbad74e0fc269064c974a98bc591e4d7272f04a48ad884e29c877d5a478914e7eb5fa1afc14315e2794e9ddd9001d29156ec0dced39d640528f2898daf4c71ee72f96a424cb060688b1a1809d06d41dc76af07f7be406d259f320e56643780865cbee72021d9627d6cd0d034af82a52233eb0ed1a0d0c8fd052a443bc924639d729baf64357455012142f5ef279b72122ca30be5697b1115d24eb30fe7190484ecbf1eb8e313f491947c82a337af83a15a910df11d9bfe4d9c454630a9d834f5f2c96b01e905217a305e2ce48b2531b75a7f0bd8747543eeee305ff059fa87d151b8570ca7cb5f2e4aa8c13bfc77567d9c190cbb4aa17b661ae327db5c069b93c156876fdf2cb3deddce4b1f5788cf5c8c6d0cb93a5ffccb8cea902cf2df27d1802bf8ee44efb0a57eb167f433228c84d9bc008a1540fc4a2aa84b6f62cb958ef83d2258cc091f19228ec36ca7795b0b5ca40efacea614ae0bbb12c8b97da05cc4993372828e745ee902ff8deb05a2c7652a0e851c75fb96f8f70c67e2d165a22c96e50f3d57900833d372f5fa0db94a0d82075b9e9f2be1a03a45409bcb580c138eb322b1e5e2bdb87a908b363fc9f3debc0d5ef894eaf3b5415eb418c627a85a4a04dbaf209aa73218213e6eaffecb144e096d3cbe84cd6c48777a0872ff4f77ec3576037c8a7ba87cf795e263afbee65d06a58726459942930171d204d554e3673f9711763e13b0e05d586e5e144663f10900e52b6de41be11d57a840c602df5b3eac5cbc2dcb63328ef6d58768a6ba370b971265d07ba7969e3ded0dedd059400459b61dc14bdd60968741453eb74dca0decdf36a2037496588c818296d4b3733d5230cb5db82cf5c3c52d32f194696c0888a30efae07630542add79fe1761f41a72e7bf4044d930cf8d94b4650f8cae0e6c80aba538396988092503a7b53e1baa96e3b520ae1295acb358f5bcd855c501f67365790f7b568c85b5fa8b360f9dcef14871a659b5fad199f3f4a265d30004b278e109980eaa8f6caaf471348b3815517722064e8e31db372717c9dd76110fd13883bb23ee54c145ad851177d7eda3aa79bb5d72e85124618044a1945475038805f65c66cbe58d5db81870d62382580345a4e2c0c4c72d9aae34779f29340e5324b085ab8f20c022a1878c568bbee8e36ef0407759ea4471e1927e7eb80e0f68d15657ecf4cdde557117d4274b5e027f6164afe349637a52a437adc8bf630a9f0019817b317c275a55d4095793bd27b6b08eae54357eeecfd28887c8857c0ea717f35f69df80d3db21b68aaf15a4133e76b8d898c12d84464efbc2b3525903dbd971b570c4f9a45aa21a1dbc37ef54411ad261a377f2c450d590c4dd630b0e96e581eacafb7dbf115038ed36015aa1829b8460042b781b4114d84e88b7940dde26decb1d75b6ee4a1db215b4a75503947c7cc98bd04a367b0342b7877d960b2be7ef1facd457e6e1a93d58dd4b96e3c2faf684498284bb2f2cd7d499e1cf080bf975859169e7b4dbb1c20b26b807cb65547facc7dbf3d1f15b50f143639604a615b5460e4c4705a6a222657d83080b07e331a5cacd71e1fa96afee87ace3081788db28b2f3f35e75ce4ff4e87fdbb3b3a457abd4fb9497c29663164d6218069e65d4032de080a624053e9ebf7279f5fade0af4fad8750a44d825be50fe6e06dfc73597178491e4fce8e7a70114eab887cfecf620586d519bd383e3975b2107466bbb16301686e958f38a71a3ce774b4fe1498afd0816e4c23c2a638e308500463ce694f3ba203669a149282b09f2e5f1289eff160e598953f6f8ab9f7dc30e147a1e18ba1418f379f59705610ad814a507878cbd31ef0ad99cbbafe3c83800ac952d05194e52410678e3b5a5fba1edabc351afedf1e3a1eaad92ad6f4eef0eaf7cad976cf571b9a176c27cdc0e461c3a2afdcad5f7140761037bada6fe1208a53c485241f9f3118e0f8f6d93128e4965a1fddb2a08fde668b321dcb889dc0a955c88cbf796ad42a8273faafe8d89f9fb4f8c12c900802d303b9376b82513078a63de112d845f7eb3d832de837bf9be5ff110d8eb80fb4b01a03b2d3d82b20c83f128bc61116b00274a8cf1eca764a54e73d7ea64459ffabf94b810c9eef80da761dd781ab8bd551cadc6de9b855fa4897dc790e15d04defb4609397d5e3401424b60672ad99f626b66abf6db7116f79d979099f4160ed85fb53e6b8d659d099455e0cd6a79a31b95861c7c3d99d226297870d08d8cc3dd06988fb3086dd3052b91bfd3691f1adbf3901d7dec727d1cf4e1542440695bdecb589c8b2c75ce047280c0a085ba396c34b30d16d4b3af5c413b333a1842fa0a0678984168c0d40f28c4fb8361b59e9b616871e82c280b7c17addd59487987ec023303e2a962e1061059a97043e3914ad1fe31423d9d0a30b052eb9672332128c8ee5e74ee2b990b8ba0de941f522131225e11739a26ba0a494831e19fbf2e6289d21c3815202c029c99b2fc9a7a492066d722b43e2e3fffa9b8c711d0b9368d2ba19b87226385042f8869a00538995b5d028981c0faee06cdca8b4c6308a1d56efa7fd772ed4807f28ed6bf6fe2d61056055b7587ddfdf37bd31ede1d31e78b3a1dae0b415b6a0aa3d4c996e95cd9e3af4ae4f527cf5df69d654580bd7a54f4afa946a262db1a06718e075a0fecb603a3da413d9da00020e8db194408447d173503a67655dddf03f8f87cef2d55d4518cf4be3d6fbb224d08c74750f5c6ceafe7eb44e4e70c34012a7d1ffb9f929562c234c39f5300a41e9fc5abc95455cb8c14e1238ccb107b0a720e9be6307b844e9e8226b9a5a6de44c87faf7f1bb1279e97c8a63e4124f903e1b811655f719835dab14596612590344f854fff143f27e57bbc588f945fe30f6890abfd567cb38ebbdc01da0d393ada5cbb98f753374f33792843758298d001268973b9c4d71679d7969d4453e7e2f35b824ae86a0f94c7f6663f7052b8e40ba36495e9a3b5d5ac05ce1eaf11b766052b13b03bfa7faadfb3b0714e652ca005da1aaff1d9ab4ab18e213980e015ba6fb176e4fb281ba0645e229b4b30897003e47d5da289311db7677a754a1b6672087b54adc902b537c6366ef7b06fbcab02f50d9ef2cc95db03f5a46375d92cfb01fa364f6364a1c2305b2d4197ae5175074379c17d0e2b0c624487044896ac762afd7293d4b6dc02ac78d41e23dfd192056288522512eca4c1b7390e15592159b1781ec042b136a5f62b674222f52e2f02b0d151e275b3e4560a7eef14bfbdac4728e4e66f85ffe9f88dc765212413910e262d430180bfced320cd67d7a3458eb53f6d289bec1b6b2e19c70de043a8f70253d3594d4ae3cf974f16f40563d27bc35b31f343dd2dc5437357197b4e4456015d309d774d032f219f205ddb140949432420a4936cd0956fe9b94aac518b180e6019acfa875a441fa41ee165a6dcaa0189c314ea519ad916d5579387a9e22a07e62fe791688f540c2b41646ee634529803da6e1879fd4832c2f8d6d02ead0c007dd46f925a8dca5f3326f100cd72a41d1bc250d008a9a443b8ba968e59ce440be6217b354b3f00dc97848bbe5d60a03c42127056f2a7993e58185bc75d755d05b9e9301d0a8e7dc7fcf030e5784a06da6ad16afd03eab8286ccd73e299a61f0fa37bb6584934cb6fe79202892743083dfe59bc1a739a33ff9f3703cecc690e05f0841f210613d5c62393d39fc76f57a581202f5b57aa5e48fc20c5b85061f3091f4e75699944dd669e8a465766afe1a8c3dd40509ca18bb9149c4f9d48572a021a85053b9004a114e270bc49c7c8f95ce9f5488dbc0b038860a857013617270e58950c202879c830b131c3c7b74e3a5dbde2989cd9c980150c7bfc4da920660f3695f1c8852ca4e8b1f8be6e1fca07ad9e06a88683a1d65f23fad09ea52f6c00b1696494519fdedaffbc464ccecede3f32eb1d4aa3d2be87766b678b46c1430dd0a178d47bdbdfdbbc9cb5b84864f4294b1a8ed13366dde262c771cd222c6c05916c1524299d1585e8747f1fcac2e87f52743291c3cdc4fe1204c59eaef1090887d3882bc8b7c49fbb388e505e03dc48527da85ebd8da0f293cc28f32ab2cd0419baa20598b2bf4d4381ddd69b65f24fd73a1ac075c9be73995e69a08b35fb0808fba65c0e09c1c678eb8dac6aeba3008dd83e2031a3a22102b85c56b0c98a0cbea48333548a44cbdacb81af646c4692d3a2fafaecf1d557ae38d44c1e5f4106afe4715b5f6e5ad018cf2cfac81b996c0641a94101cc2bce4b2cee501bb3fd0bf908ad106a6550cc254f4a62691202555a3835f2f0708db355d5229a9b2033098756a5114a3c9770306fd51b710b14e1c0b695502673417dc87ca34c7f74d8057e39b2e738f74812729a4a5f0fc6b1e17a40bb20cd1034647eba953139267e0c0a9ac35f04fe82dc4b770dfb1e20b594688ab9e837856249bbc094b67ac2220b -generate_ring_signature 9d3b5964da0a0dafb5a05244d09c44cc052535bf41794549aec9b85b7a238998 b7d7b25d39766c953ee51d4057e3746b82c88731470657ffce7f90bba173c870 1 a0dd3438cf05d1a81fcb179ce77f0a61b8a47525d2faf17808662ae3d2127d4a 9046bd3b0ee4f3b9f6874301485110cc7a5af1806eb93acef62718598a837d08 0 21fa54f297c87388cdb9f180d3ebf5da753b708afe3247661116982a6b348202455a29020e8de76f7419a3255688ace36be49037ee17457c5bc8019762df1108 -generate_ring_signature 36c2cbcbb47f9040cb04a7e8e1bd128dd73240ae49d6a91e793c624f9a1b5680 faec603891f4e9da1cdd3e6d205a4173aa202867a1eb5959cbc9e93f353f36ed 2 2d266206059c398811fc3ec5e99c37dc51af758c47f094bcc5354884fcf0e83b b76f2f51b0e270cebb200499466d003705c19d8589e62d6f2abce941455aad68 5b96fa1f454618fba2f17fffe6a26238269fbc0cc08b9361aa03c451d1fed50f 0 8fc197b0d5b14d3456f532345c260f455a0b2d39ad78d0aee7dc840b04eddf04f038549bd94d79fe582b6293830455e977abf32abe7a99deffe14edce2fd8a07c905f794e8d5182505868ddd36061fdb019451c2bff2a3160c095efeeb5d5903fa4217e5a11f414b678737b3844ebc995a6e58715b9f44db071ac3e041766f0d -generate_ring_signature 8ec53a5456f968a3c524f9096eaefd8df6bac7b84fa3a94d0bea97696520c66c e55faa7e53c815159484d92d413bcda25408c57907fb97debcc43b82bb72454c 81 4e6ec9a062da749b4c7ce55c1771c5be74038853f1ec913878dc89b65a98ff82 76f3b513e21d14585ad5489f7e7614a99d0f565ba1d9c74d7d3ac6f4de6cd0be ba18df4320a46e06f5092c242c34b1e5780ed295992b8988d8b58fb4f4af8fb6 038270478eba4e0041656da105b78146c1934c9e8c43e54e37e4103dd9b2d84a 1d88989753b94a019df5b0d526a04355b5caca57eb89dafc2ddfd166cc2d9b16 a18d580f24cbc8814533279e50c1b76c62a3f84c8149a5f28985330342a5510c 8c97df0e0ed3cd10d4546368038ac04a493fdb4f776b71f2883da82cfca39ba0 d51124bf2d485048464f1292f68ac4f2f2d381ee4d776f442df04470341e5dc4 76e1c7489de49f7c029256219e12049f8868c0326dcd9fe7030d4cac30567dfa 0481ffdc653eb171f9f868759e310680c494d060876e40ff8259129ea672e213 c086abc24ec1e5d6c8f1a88fc25aa1b8ded0665a092d57678eeefc7a8fed692e 63068e1ba561aa0b5b7e3338583da9dfae07af9198024cc19636f2ab864ca457 2523398a630cd53e849a151ace8438fddefc758d65a0983556ebe4849cec0e69 05715bfef2fb4e3d04fcd6caf880db87df20232d9e6c22f3e536a051833eb97f 79afae0b5d5f0340259f26c0ae49f2d7b2efcf451f721386bcbd3db0cc516cc2 32dc102cb33a1dffc0551aa87f896bfa4ca364d7e473855053ddcedad08f6192 28772c16ef4767cc67a4802d334e62b3cc366320ddcac5db6ed6da4a3a518e48 ae62ab17972d879f26be0dc8a4e0e72cfabbeb48a1f6c862a566744c73f0d5b3 95757dc182b24d6e76f770585632e8e2293ecb0b2e068b1415c5aa6b8844bbf4 a9a01f9794d39e2135c734007c792c0170211b2f31d22ec855de6c2c9bb099ce 809e8daa0bdbf2845adfbff43ed329bfad793cb1d50964b76b0d2dde834cafba ded1d37ef497ee99ab7f47ba850d3d1592469939b25fa0dcccfeffeb6e487256 5f0c974156a91fda39cf74c75e8418f5dd735a30c3e1be7fccc6e66ebaf51bb3 df40904f087cdb5c2d375fd9e9cc1b8fccbaddd8f8b366bfd6c4c73d548c89ca 86786f17d9de29de6a6f3a96c1f15efd1b795d97f316b2945ea60497416c4d22 571c315699e3f94b0b49c31c9603c952c1cb7b4f501ebc975e7cb9aa76d22486 6b37e86d97644021c4aa8a7570dc5c75697d8a5f48c3d1dc40c5d3bc534ab466 37bbbb806e9bb6515f1b506b554a53590b078f3fcdcce8accb1503d83b4fef11 ad7c90bfb7c44aa341d1e52e1b2ca429e29ba4db54dfa33b061cf6ea1eb00f73 a6562d8af16e8877bc51ff84af564dc25a03f7d0d7535bd2c5bbd130b3e762fc 15baabaae493637cc08130ebdcc165d6250f863613d137e986c3318eb1e1d53d 30bdc4dc44932cda6b13dd13848dbde684a136dc36ddf053c021a789875fa5e7 486d213c4c340c96fab9ceeeb238077f728c3ace8b01862fceda8d0552b285d0 31b5688c7137a1f2caa7356b494db41e82e22dd6a8fbbc1d6f7f2c95bede6e04 df368afc6547d8757f35c2f1e925b2401a976e3dd656790c29df95da30aa7d41 5b457edbef079804a73b9b2c07ddf6795cba1dc7b2b378efd4e090206556c0e5 1de5856c9fbcc5b9320f75715d93718fc5ef2e131c202c109ec452576ad8c0af 57efee62fcef10bf49fa000f0859bbb6bd87601ddb2fb92c8d5b7155ac088d37 a66b2987ed02312dd641783d5e0667e1962271ff175d92a9cabd9f8ee5d7efe6 1d295ca90c2ca4e776946f589090f8b29ed75cfd4912b24335d1d3af6904a165 5836d1b2feb67fed61162fc0547a2989cff2b8223a54e304731ddb1777a53ce1 cf6c69da62ae9770b7cb9258bb6e8b14ecfc4d48157742c2795dbbc757bd9730 15d960a1be78b06fef10a1d748f4b7102e16e7b9b515b85e4ed56366bbf4d347 6f4084468f6082c7a3a09ba66ece708020d294c17718c8a15ecd4c84cea2e269 db08f8b2fd5a814a77a829c3d81da8aba108bb0a30d0ec79095f6272fabb29e9 bc4658cb9532f7dd50cbbe9cc3b69c42c684f1baed27c68f7bc61a3d0ac6fbfc 70118d671fc682d4ba0975f6db97a1e946ae1523a1602e980be873b3bdf7e262 100e6a645828abdf759c25a993f3176bfd861ec8b14fee0bf2257c6942f3cfe8 dd4a958e1f2f175763bc424c37138f7f6ace5505b4730c1474f13e29e9fee09e 981f550230c2ecc818356c5978e09c7bdaba2bfa50a18cb65861c757fd2a92b9 c4591c778f2af35031f0b8c10a9ff2076ebf4743dfcc683b135af85c68692734 ae21b69401e1dd790b5d0ab2a9f302f9596d399233c527fb03a3c04c174e9deb 1a479edea2a50f19902e1a6f7222d5dca50220170d3031d932aabbb2a2c60a50 ae222e075a61554b2931b48ffcced2deeb724b0931e57a7fa42c83dffea81be4 e09cffe50c23b6b501416c062abb82c4350142d512fa7718a1a7b4bb0c9c89b2 140813e40064d016f31c79e98732ff2488d8f5203755206ae3ff8b43ae29c2b8 755adafd8cbfe400bc7f0d6c7e9a6745f805094fa56411511cf71a842dcf5e95 d2f4bd013ff2a5614a0f46d8f8291a727974291ef07d6304cf43a3cdfc8020cb 77b077c9ab0974d0f7feda41526b5f3c49aa93128c71c20a32210320e1f64b76 5658127bad4fe2d7f6dd4dbc60a73717d42208a526b6d0cc42a0cfc72dc5de47 d990e1f4737f9389eb33c7ffa8b5ace778993c3e7843fd8eff9e5716d7dc3823 258ea018c125c4f407fff137b02e0b3f5746d2ea37e5b3f0ca6adcafd4d9fc36 15df78d82effc9eacf8420cc9e11aacac8d5e909cc54acc9c5bd7c4c871451d4 dcae2deb75447b6ea9fe455cb32c80b6d9e756547da0645f13d1089069238913 fe5566a38dbd13b5a0a18c0e6b39c5774a98c588d2fb2fbf062a6a313dca8e15 852091726bb4ee8baa253c406c0faf71cfc6214aaaede4a378465c6b8bac7d21 927934f87ed1e0f415b63e60145baa00c5974030a1c5eb8f24b7188f10fea32c c7db3aecfd44d679199341764a02c3be4a87466677263b8b7d05acdb694c124e 3afb101244955d7befd723e91c81a286ac7f651be08f9895d2273e2d0c49a300 2500f40884d6d748b93f852b6ee47039fec6db5d3377d28569d0fe76455ea246 e1b1e24c5a4eb749ae2e2cab6fcf3b86634b426c3743aa9ccb25f50d99ead1b0 c344cab976b25c1785abeca1946186a1b4d5c1ff5bbab59d8dfb6ad5db01a8af fe2baccb1e96d61f5be322ff3e39d5b72d5cc799a758de1313d4793b5a723fc6 83779c08a1567d1ead921064d6637784b8b85a2d18bb3facbb48e530cd5830fe 5560502b0c56672bcea621eb22343c543696ff0f25b230409984d89b083e399e f78636ef78c66c68d74165c4635fae714db6ddd9ad3b7ad51c7c45f125189b37 f344bdedb278b1a78067d1effad38e71921c10c7ee69b0f597e4a481b4a9b014 164d7bf3bfec8c94798fe21c02efb54b58665b26d7796d0ffa3679b5cfa02b31 a7e4fc8d4ec066b75bbe98d9cbcc648ea13bf6b32646dcb58e5590edec327232 03220e9496c7b992044f1d2f3dd65b6d0e8dbd4bf2f5fa7036508d9fcb28a147 6610c3995d2a266a69d4205027ac22196f9817d66da97a547a2d9a41ae582d22 e95249c7c9018c9c5e46e59b620e8e412eab445e832cc46cc99b4c9178100504 68 dc051e01a95bf5090b0c6a81a5c30ee2230bd6c946ae9cc01cc5b4d4e494be0ca5be00c329853f08d4e520acfd6cb627b307dc20600eca8a0d916d5cab538b0c851b7de41f13a230d6b174cbe94f6f45481d2f9a40171d6eb51a1c0603a6fe02d7a3d24f008b91c428bdbe4398a2aeb93997ac4cb0d8ecd3d6608f194894990892fc48cee0729b6c31813e360b7bdbba134ea93ffb24fe41b075ae8687ce400ed2524d8623d36e8312998eb41dba8ca73cf605f3df6be3bc0ceccd673dd57b0c4fb9efcc44e7d099aeafa41c03905fe212c26a90d0877d64ab9cc0790871f602cca960f5852539df513f152de3ffd5827978dc351288c5e0138b54e697ad0d03a5cfebb4d71cfa6d49dc358f4309a3d47d19a8d0d38908795a470350604eb20c57ab4d0b9896945f4a88dd69bf135aee3ccd44c777dac24379adc149f3915a0a12bb4c02b908c5e932397d6030aca3df38937a37d8f4883081662b762707e000693c2709362f1134d960efd0c121be47b599a3117244b207ca673bf6f777be0b8cd811a6b50498ca92a92a19d141a8ed0e5343fb87c41e99b3444d103c679d0aade2b9501ce663decacd5ae8478999631bb00803da5a40e81c8ec7ad896b4d0b90924d4b1987a19ca15bb9c5f5b10b79f3260d6d64cc7c928ad759098d69550c3ac2df95fc5659a6a61e1ee20cb54f9fb72ec19f85bf8a056e2b0732b42db702ef76cdf48529074860baf484958e088636eed5c2b6dd0abcc0e506c778dd710a4026f766ab1c8081b98ace78f5e53a147869c761c5bf759fbf820f40b7f1d40663219feec371b348319f4d674a50be827987373d8563f4c9e36d35cfef442c05caf61e094ee2c07729ebbec7a2b95e38a13018e1be9b22fde45acdabbbda55026e7fc9ee1cf27b424364e5411aff1f6ce1b0bcd404145498fc7acaabd15ad30e2e4fb61d4acb3a6ee0ffaf1939a0be06677978fa7aba04d973e4687d7ac2fa02c0930e5e874b48c6f7d8714898ebaf642597d5249851b5bf85b9cf5ebc247d0d82d1143abb5c3706c629c1b9739f7814366ec1fd406bbabfa25e52a30ca9fe06c3358826e931d82e30e12d2eaba19bc5d82c53cce0ca3548793ab16128a8650863df1ed605e009122eb2ca75c962bb5c4108961ce12ee957ecc212bba620ab046f96502dfc1693325ed41f38331c83ffe959cad53734f5c20bb9a9953bc7c6092c6ec30294c4caa14aa1a41e0b4d7d68c41f0cddfb2350c07a78908af8edab050b6f2c46859002f874ba8f8aad578ff72b472129b4bbedad565ec4294961a60fda096986f5863aec6fd0ecb0174058f52d0aa1574cec66547db47ba81d5302028cb9767c904744b20cf80a8af5fd60de771c4df2dea19d648289300e2d87d907fadcc3a4f482720b1e0b7b21e4e392dc8032719e12bfaf19aea01bdbc1f7d006e1cc33ce14cde0d3823504d6326fee43b0fc44ae7e7fd38fa6a38b60fceec301d2e9b824c501556fb498abcd38cc1c9afd68b0bf1c01e11d380c985f45ac9408a5e9466e9ef02cb335052f2b1073215b1a16f8ccbc46aa01ec42b1defad4d800a22582ba59e41451bc28f3a8632fe3761926fd2d82dd56374616dae1a8cc120e8efde44aa4f379e92dd694586e52004daf0f35c10fb41ae10751adca30c61d0a8ab0382ce938ee6e457925abf489d4291bd43c4314c6cf30ddbc5a16a2e75b0713d49666c219e12e0c52d1bee6e74f0723eeb16e8d17f95d91cdace8ee6cc00199d0c661f39021ca96be4d3053f566ccd11451749bd77ef5654d53c96177180a5b62159b0b111e8bdc29bb5cf3a866f70636d341de3a2b15562bf8139cb9c301c937cd6e0a5b29c471c9c22ee2395170eb4946f45f6c7bcf03f0e69ccbc5280b4d632f1b7e8aeb92e6dcc6f4c59adc99c7711531daa387e6a5197b11b35b2f0d9a1abbe7a2be58f15d3648de884a855e8be284da30078167e4f41ecf561943044083642de348abb049f2e0c7ae8ae5edeac583574aee572c9692e2e089fd9501622cf6346acb8bc59aed648ebcc19248f0399a286ba21cff0232808d39ded00bccc01d8cfea2777629ab002462bb54712cf0dbd7f7d5679676104a77c7b2890af00796c798a78a3a4e9e1ff9e3433231c02efe3056304f8b02ef93b85873110c66ffab4ff083839e7f5b7d2daf7db0a9c35c7f0aefa3b6b230a5f5aab4a6a0036005746dd22e1a4134075d1d9ee24c72aa7c9843c1c9562611644a9aea236303b1191478faf4e4f7a99c3741cd294c1d9e61d18fc9ffb16853640f402d3884016668b76f1d0ea844212f43b649c016a4e30a33b471da161cfeffab4ab2a59b0f9e66692763f3797b64037adb5a57396ed94a3f5373a0c5b782f1eea94006d10ceaf552c3c68b7068b2bd223abca4977ec6a6ee180ed881c9c09c0114b9ad820b66042feeb500eee8b7f5b57205b5e4be05d2e2ac9973b74e733df1cf3aace509f3c752e828f3af4d9d94e054540c5bb96887ac025a4802285e72733b64d4120e1c23aa5f9cd78a3d6165ec6b463c2f9fc67f3887f1394d7a8ff7b0a779483d0f602b51c512f29d16726f4c0dbda42b69bb909eb85c8d3680cad54d6d322d4304a127370f548f0096187c90a867f7fada233464a571419a4a370ec7476f78f80b04f45468810eb03f0305054b9c771748595686d9ca26af4562ba93490f993608eded0bcb2d17354bf8b08a62bd8313b3dc1d6befe8ba9931bdc337520a36160cc1d45749ef5d55e30df5e551c9dd84af1ecfbf1bca8bd7f05a70440f76f55203fcdb87dd42aee80293b1e89e3182ce4e1d5f1b7c5cf5cbfdbb4f4bc7af8a900ca562c974e870a3c2a05e8d15316c3f83edb7b9043e2503373c12765363bedf01c01f138f6700c9021da1d362d0dd000cc7514e78a0146bdfed847c8f64edbd01280a10add0f573bc2278154db5078ef688cd91df0eb1bc82bc6616c7207574012fd09b489ac09ad2544e7aa922328f67e1e2b0bfade3e03cf09656d7658a0402f14c10de89893b007b15c52e8bea8ea89c8e15c47067eee237079a08c0adba05391a806b5e329dfacba975e6c6f0c639845c72ec2a8f11872a5ac3007f09980cc730aa193cd66ef63bf52f9bad55d68366cb07421f2403d71db514556e2fe900af988b561771ad0c71af192b18969de454111ce873f62145370aa9bb7dfd7709f6591f4843a2539a91b0cece37f5185c8b3718fc49b076f05bccdcb3d475d807e602ab60a086453f204622a9ac975c263e048b3f3210dff5908aa3dfd46d770f3a2780ddf4ef203225bddd898024b05123aae2779887fcf4289c53b35fcf3701a625ee97863203f076147f221e7184273a30e99929aaf28d2ca6ba90b6f3330dfaba4fcae3072b388cf57b32cca39b06d634dcbf24f14971d954f96472081908f7be2c7122e71c77c39c89af70b7f93ee6fd833be132d8621fe4d92f79a6bd000aa9262c492cea68922ceccbcaa0829e62a61ecf1a83d95cac3e08f4dbc7a209f295530b04cdbb0eb8448c3679b0e0a2a8c8a1d99de043919c1f7430aa85670aa0dee47db68e89349d8b3d3cc889e5852c55e17209a71c1ae598e7167fe2bf02493ac42f91afc58588343a20c1482421488686ff456f1aa74cda2a103f38220d3a6448890cc050abad4dafbb17c0e1fb0db9443fee995b1d574287046ec3570d2208e6cc6ebd0c864fe47ac692a06eec096f4e0f9fd469355001cb864262510a46e15ef5f45f3370a9521f402369ba5692e081678ca073c7e89c0f5f840b32039a6a13ada04107cc722c36b1f66e66e3d9443f228e186c407a67a958fc19110b576585e343613674b3f63c1082e9f928f7eeb4aabab3a09d115936f7dc2fd80a70e8d45db877ae0a62ae2067bd2b9bf2c94a3e8eb32831e22c591054c804f50dbe2f59a7d8c62420c2eb8f3b73df5d328d9a87cae2dfee1eb88299769ab6700907cbe9b7274b904fa727b886487a6cc8006e419fe53c20cc858f9b59f5b67d00fe80d668e875704c86f1c59b2c228d057b627ca54e346bf79f5a56f1d623310dd187731be8b0803022d94898a7cad048dca68256976969650c9633f4aa09330b7cd80871c0f15ccf3311f83ae7b00af38cecab64a04319fb5a4aaa9377e5c502f2d64e1db85603b1241666998caa97026f71d57b891afbb4474331477d17540519d23ae42ec8181efb0a1441e48bc0aea6037c8b77d0b0933e06b20d9d36d70dc13e95f1cbaa6518e59c1a91c42f81ce38b518d526b02dd8dc7daea6db0e9003e8efaaf5c8f7fc780e5010069670d7e5702748b4b7816a76dce6a3cdb4899e0ed29708444f7d200da63740fb7c6537f6f80feedc6aaa8d4d754c75e0fb30e50f6ed9e46cc0085ce15097d5bbe5573c157b067a0a9ac489e8dd0ccaf947ce7701eb39660c0ca3dd107f1771c5663edd23636590677f5e9be06152acbaf383690a640b14986093df332005f0f3f60a69905f19d1a9cbc5540542108a2c199f830f3a2d1c5e28c80e720185cd62d43ccd697f0ba0c95a770751b6091590709585032b0cc3a0a913db766c5ff09e036722a61f15b8648dcaa864fe361f69ae6a5d002fe49cdbdbaa26ee7982755f756f4faea78040447df2832f49e1f0957bb4ef02a1b6b560bb2d2b474b71e16c9e4cd2d5a1df41d2df68fcaa78ebdb70badf340ad9de775504910be3cae4fa2e2ba919617667e591fc6ca7c6d3de32aaec3cca07b5b9637b95adc97dc6499641a1a31780b4dff64ac5aa8f9a7d02db722c577707a4ad72d6e5e4adb18325cceb4fd6cc492510e0323def59e62d968a870c6575090666f02b6df7baae501833f8822f785190d4a4231abb04a83ba8f39bfb7b7205d9a981bb8fb491f8d37f8ff4314d5c1bcf6245c296c9fd4a9d754573bd5d5e0d2bbca164ad824025f644588b431985d18a35f0cec6bf7ca6631ce825e670b3068943b553c4891fa50a9af200122bc97a262a1e6d7366c2329284cacd8387ac0dd196d9d8f996630d2ad1ef99bf5d171317caa0a0fb94c86115162c5b9e76750e4f5a081df272eedabec854c4dc9efc2aa3acc03e5cbd52980ea8be434830730098b71bf670b5ca1c50e7228f09ee5760e9fcaca30e80568e5a2d560c5a49b704353cd3982be53a945d9bd28db2e2628e47c3eeb3e2b07781fb98ac01958ed90a77de31823c9cc5b7aa1f0481edb215cdee65bf4f5c9e0f1310870b4204706001b5b9bcceaf34d56abc9a111125ec04a542938af9f39b20c8a2a7d9c78dfbbe0c4a41e595be489c4dbe92d040817144e9d49b4e32e125f7609ed031763150e80c29244ebcf8833f2c9afc31385504c302cde0101519e823c8000725ed290091094f9ea1152c164a25e6785958e304a6b72a986672ceef6996261ca7595cdb4d005d5fdc609d88b949f4d628b53c8d3c5a3ca33dd8b7f742e4f5f32e82a63f130485e9924b86256a14474d87a1a670b672daf38f5d7c7ef1f7b9c45d67354f1604528528ddd60c139ca0833ec2853c3b847cdcfb1195b0929a8be690e7d627f701980cd6fe9250a84a92790222193217deb7c423256b9dc795e1a61cdbeccd780d3be9d2c0117f47cd278f87e9683673f6dbcb6c412e5921060c72f691c61540049b96068ffb5129c7038d7498d14ee6be5ae2db581399a3e5d5b97fdabdfb770ad5623fb28b4e5dd1012af0edf9f3bdf8ee2ac859db2cc56bad939c2b237e4a05d08a44534277230f4e144a462738e6bba05fa08ffc42335e3cba52431d62450cfd734241def81f5301a1a360d3bd8fb361267e76b7921d554a0a18be8ea13d0b2f37f7167b7047cba35e810975e574e63fa109ddbc304aaf543a7f250c4cf10b4ef39fbd2125e53aed3bebc387d98b82b31b786cfd8a489254aa6a4c29ac5f05063f77bb3d8f5130d2750129eb1fd1beaf7c9700a8814662d79cf0ce6440bf08c1b5312711bf66bdfa6f7e31b6f3146302a5bc13f876fd4dac1ddb50a462eb05a292b799f071a599c8f509f14357ab9e2d64f0bb4ff963a3f0bea411c24e5b07880a720d52e1a9fbba609a86e57149dc1f4cb9a9e98c7e42936f1eac1c63930a9c9602e214e422408c6620069839fa1f2490df1eb01d57085baf334cba8d790597d487cc1e46a8eda4d5c250e0e6a23f0a4c2c0a0467b689a7afe4850126cf099c9488d1c2f62015161d5a9197fd48d057af2ff3c99b918189d8ad56ea56200afe2ac392b3fcffbbb69a3cf91a5c7e611e5dcc0822b6bf453fb9303bf96bd5011cce1be35dce1f2837c80df1374800811bcc9f0170588b3f8cf012bc7151eb0a0e22dddc7d5f0508afa8a4352fb218295d78f021bd54c704d9de4874f258ec0a451e83ed9ccd023c0d35ddca5acb2a91de6586c617d942e97a34cdd2f9533f0bf9d319a8965e7ba75cdee818b4c0c1f5bbf2f46e97808ed3b498f79a6857fc016d35d1b126fd1f1fdc6e9afcda7a184eebac4d82aeb9ca3106777d5e98d3460a23ac4da841430f2936337645611bba2d65ba1481be6959ab29d0901ea471780f8d15a5e151d55015c22576856bf054bc3d69755e253a4a34051dffd6dd45650c3e2154f5bae965173ca2f360c44eda8dcc07771266aa132db5bd6ee67ad27e099b2dda62d907ea9d35d3eb24da2e11373093d69c261d3e72d70484e085c0900ce4e35cfcbe7e60026b4590f2fc098f80fe3b410bd050e957f27ceb56ce187a0bc0ebcff5d60750ac1daef3458a9ba47a52738e87d585073975078b0144d06d06546f15f137b3919b5d5ecec0e0b9dd5b892a25b3dfb429462c9cf4d1ca005c0eb21a2d9a298940ed8a9f46d13bcd36908946e563034e21ce01eddaa8ed112f09e293e5e7cf56f2853849f16502e76a124e2ff78573dfa8a999468c1b67b8e501970df04b863aae3f558331f4f953bb357d8392ab66fa82b528fbf897da00f2094879e82a71ed2baf5f8ba0b8f616cb50b435ed56a7c9aeb6fe9d3d06e01cee0ba16650b6b53f852cc229d46a7dcab1f6a9bf0475ec8d98acaed8a916d061340c8fce4968583717b7673046ad6c2b402687e5f0cf86832d05db989da49431b00663f599718e68040631d86af65ebc2455ecb13db4678bc4db94e8c07ad07f0703096298328c559f8ad15896177b9ae22ac5300df758c5f5c6e0470071ce7e2403e7b9acddfa7a8b26dfe474b09367d55432de66b45203f75bda06c58f5eafac07ede66027b54bd81ae0b376523bebad5b392bfee557512abfe94dfd9a916ea4005b76627163172cdc7874b118f219cef35f8fb9e24f7280e5d72d4c0fd1adfe01 -generate_ring_signature 713c4c8803fc00e35bf91007f00baba57486e0d70d332c9608d09b6682d5a554 794244933962c44feef2118a18c784f069ef776f495f075dcc22870eef06fe25 4 d6ed7494656d90bc14042ae12e0dbbd7b9f890d2347417b21830785a32fb3b25 dacf20780d08fb684de5ac429259951b81deaf781a6e31dbcda6ad07f10ff0d2 d0e455ae02f0be142f67090ae09f49ef67d65c5ca67a2edd0e612bff1b04245f 61b716ef95d86ea4d50645d4ecd717cce494c2d4d42aa30fd13a45e3370a7f34 da2cc4f0ebc2d7f6020c9dfe8ede0c1b216075c6c2eda1a9e10969a69a35d10a 1 d6a43c90b85f2acd859bb242fb1f9ab325d50092f755df8a37092da21bd8d701776267c1a9f824b3bb52edb31a55346c1b036fd9fbfc441e1cf1896d9a52330b18cc5127a5d74b4955c36ef99e8d8535701a8d0dc4c449beabddd6e6d9bb4b07f05eee58a06413ae45e2fea73d83413112fcf3a05c2375f89cd3309f590ceb03dc52ac61f6c8cdca14e30c49570bfc7b983f6a86636b451ec9317d5630174e055e72e58852998b0022d72bfd9bb7bb924cc4189f33f8178873735e4e6190160c7d43d52e958605e89fbd223c62a75c8b9190a2e07775511b2983e65423cc4000e458bca4cf0713aeeb81a73ba918dbab9631e1cbf5914ce74af2c62975885904 -generate_ring_signature c24d45d5956e2ff05c5900e0e3cc833784a44af630d7aad0beaa57fd879825eb 359095816f878d15ab2b0a2186ffbf5d95c777c21ca2cb72d2266d083a4a5809 6 bb3e5f6ae5df3c4a43310d86dad1560abc1f6626a09d5a76eddfb78d652654d5 7a4ac8d3528abde1baf73df38ad03a857739fa446862d1e28c4ac3c83edfd15a ecc674b53bb166ac2be28a7d51e66edfc9f95a324277a2d9d1b908e0f65c5e9c 5841a26c6b246992664b8d8b58769db51a4f7a194fadf2c7a15046a0e2770023 75ee9e843ab7975fbbdd99bb16392452a10f7e7b38144f29b9d706bfa22cfd65 3de3c211b808c4235fba01b016862f8305f0deaab1fb58823f1be27f151acbc8 9b8031370c48fb1cbb36f400453a00108841cfc20f4ef9d9d206f33159cef60c 4 6f1b8ebe057c8ccdab02361c0b26ce0e5d625d19741e8b5300423aa0eea6e20ec67f938ed8c01a4ac90c61578ec6519e85f87e7419124fa2284c84be6ccd860b7f519abf1b744b8571038bc38589f17fb3770e224ff19617c4f710a5a5f6280b5e8cbf78a2e7fc08027582b163891e642a82a38672f5b7ce688a36fc20e0d50ee4e38c85afb5bdd0e9ac8def5c39a8849aa7f66753f1112616f768e1026ec40a490c71beb31686b6df5c3e51ccb38cf41ef403fc0725cf625ea6094ea0a74b00b874d65bddfc11d9034f5d4a273c870bd75cd07bd421f4f915095b6aea434b064088ae3e2265d345d4a7564c35a19e5c9e3b5a3fe6932687695197b419c4140bbc7d73d569b62f20155c97278c440c3b871290195e40b58be6c7b08767acaa0692e48b4a8ef22a9d78dcc5db4ea50d1e601df7c59e000d6042a4b310692cc405e40e12215380a43ee0e23e586666eec332bab42e5baf42c3c300b1547df5f902fb47e77e7a0b0675d58fa7cdf28d7efd405075587dde50f1ee1a4e4d08b8c001 -generate_ring_signature 9b9e3fcd3f946f6741e6186234eccbf58f97379d2138b6ff985ede15f22f113d c3b4076a7f669ba7d594c52e660da73a565bde7416c9bb99e06e9259d325724c 31 c468ab3f7c3268f7a1839d256c30bed690689a39994e4afe3512c765f2b21ae9 9e8f235c70243e95b84ed1e454c1c86b10446b699f059f66c46e5a1b37dd396e 5742fde4cbfc7422341b8a5449fdd125d30e41357237e469bf0fe77246577442 5402efe6137d07e5b71f0a1192ff212ea8959e080d32b012f937fefd0edbf337 2331347eb9271235c789b6d2be8c6dc18713e878968d77f72b9d644b16f26dc6 0bd583c1d0d8b4b2f8b19609c8d928eb4f4196a491ca45fb1f7d27e9b1a92c5f e1841b87e3d529490cd95098d08b589f51f0c84321b656ba6e0820c41bff4574 aa142732d8b972888a704821a22d62e92eb09b620f0de227981a7d9612333591 d80b7da6a8b938599b5dbba5941781b1217e4ae5a90efd8fae4a65c49c30ca3d b6d8d385a96ab10a4cb6a82df537be9ed042c8f6c42ae261baa487f7e927a384 131a2aeaa5db3afb87093ce9ece283ff1c3c8f7ae83f016612a4d3c866035a54 23cd7cbfd909e99e696f371875e9d7d6fe1f99a0a091dec26dc79fbcec6c29fc e496229d63f8c8b61f17f330dfc30417adc1306275b55adebd8b2a2863f72c8d da2db6040913049257b6ced576f35e4bfa431f25ae137c6cdfb562118bde066f b658b88b06cf34f1897ed99a26a20b0eef67ab280913d42a688b3d862cba3d09 da1f11e2eccd81c0de8498f22659197dbb66bb0512188ec900d44e8036bed70b 9fbf6c6e3f494eede2ca88646a1f3c3e3c40cbc0216227e0c474f5ed7355275d 5246031ef62f9bb1399d8c444a9e3ef99b0da76ce5cd7ecc882dbe9847d1d62e 8e4c0645b710436a74749e8d5531ed8719df52a68293713e61fbc45d5fe8a68f 18a5567a6e61cf2d3bdd2fb0a58a39783afabe754ef59dbd81e370e35954f1f3 a4c53ef53fd1c7dc628b6cac4bf35a5b84ce3703c07040924d2db4ca523cdf73 7ade9695fadb65c56bdbeda04307b304a04b9d5876a1ebdc9dfe35f7484a3ea8 82c7f5919c40ac93fe9c30b9b50b6353dac39748634b5afb52eda0aca5c00c68 12ba3162a1d7ea4b0c110e4b2f7b6f83a3874ebc983698258e9bdb187efd2ec6 62f6e20381447fe7c19968f5eeaa00c04df07ad01f96cdbfed367b6d34fe7b33 f27a9baac0ee08596f753298a41c704066556ceec1afe5a3c300e339a709225e 6b15357d01194d299f5dac3ac8dd4ad6cd02588038c3d9a8fc4cf322cca7be66 bcda402e1596fcea31ed893a65251f5fd60cc2b3571c5fcb1c8418bb6ff390cb f04d671aa35a499ff64ac633e18ced492f00946d4e3bda70d6274350ad1c313e 6b11299411b8c35cf07ee188537faaec524cb4ab00b28055554673450183d288 cc0b067ef56c580d768f01f0efc8bf7293e408d0369d5c3f0666a2ee4c70c553 28c2450bf0e73521266c017a04fff88bd10933d316572e91a497ffe3e9a48f0f 15 f52078f936f4fc464275c8d7efdaaf204fae9f54859d771b611bb4f40726660d6ae2c5c5c817c1dba6aecb9c68ca7920f9419f01778a45d4a780016faf22040852e1bf7374585a6c2daf275bcf53bae45862f7fe0e7e06425f0c1580f3bc09042af1873c896a9e38d3b3b9a0bec1b5c2834b5a34d1768d1c72cf0f7407c99f03dec7fc38b807e0e71fe9130516a44319a94138ebe4c5454dbe2ae97ff84487099c7e4dde05266349d93a277490350f5344662695ee32e25d2bf81ba9810ec8065f6bf1042e41fcbf0d39243528fdf6dc2c49a75440f1d4f2d5ca5c63eeff400b2a5fb4a6d99e264ce6a3377ddb452fe77b6d4de1e311c35b776f1af20afbac0c005cfb8f3e85e7a4087627faf6f5d6e2dc23954395da31f6db131208587403096f83912d456a82c29cd8217a5104bd5b9f3c447c21cbc325a3069e93fdee3209e31576a78f0f255e6f22bf9d344f4deb823ac8ad341383d82a07b8bffe1dbc08628facdc6992579262679cf2248740f43714e830be162832a93d90cff1eaaa009f3c15f0d7bd2ce540f18b8715d85111b86cc79c857079d33e97f4bf1b502507bc2eedb85db6f4b28f3eb957a8d21fbff8234773e43e697b01dfb8f8c075d60cc7bf48cf9fcc106d5ccfd308e777130b151e23c2eeb5c1408e9783fb0e82aa0cab6755bdbc5a231defecec0c9f19ae0b552a941be878feb41abb94e0e3beac024e4b606268058a85049ff0096ea006bb62e912a1512dbabf8f7ccca41d8d960ceb3a7188b2ace696ae4827156dcc91f064e95eb254941805b77ae2650f00f70a78b4c200c690bc0a0dd392169dd3fd3453d91700e87a104b9dd051018850f7042e30f42cd278f1efb1d57ca40bb0c9be1fb959fa6205527cc325885862272c098357c3012fd27494789a50b4aafb9d490b7b8da00480add7c400c820477f0d03dc121832e5e9b2f4699cb8885556645f839d639547438199ca87f14b23b423041a8fc77436154d6633695aa4916bb0eeb77927d31fb7389ad042b5cf7da6f40b16da701a7c5228786c9aa5fe0c3b2b2abbc973404cf4bf0cf77c2ce992f88901ca7910708b537aad408351b23ee31e8a71f2b154f39ee7ec071e7d8617843e050c173fdaf5104de4ec725f98088fa8aaf6b2ad1b5e1cf535f5e45b303bac3a0e49f324fcfa06ca00b195f994e0d5187d5b07482d9bcaea296b272c506f99ea01dc6cad19632c034a01a546ecbe8d1be78a733653e8dbc61a721deb5eeab57f0115ccbf2e2a70e6cadefe5eb104b6809d78ecf8727519d1716588a792819d72085603969d35d2230ca826a8cc760414c7ca768b384dcffa708bb14abc3db107036b15a95b9ab54d3d3656258be0c84d8eb0427b9eb0aa7af6d74578ad8ada2503d8194b22b8ed704a88f181204eca01d10616b29dd4d7047c08d787e3a0016f00fcae305a8afe1e0b6e2c4d568b43ffe828d0c40927cd5353db9a4f13b8d14901be99ffba31fbf182cc90b9e3f1a9f1b501cdd26e47b28ab2154b27247339460759ef84a8b47fd2d856f190c384f0265a0058937e2220c3a9a10fc81547b77d0da8887f50b80d5a92185ef165a9eb170f477b13b95922debee1b43516ef599a07f54c880d5fed6a106e018792ef76be1abaab1467bd9f2d313b1189e63fb7a30a2fd0ea02746858d87111eb70680406c86f4027b03174c08e7cfa20b9e266aa02b258ada57a843ff0036cf1a881c4fba860dbff1d244eca76d114b6ab636d720574d0feaa8dc4fda1eabfc723de785b97d2c616508927f17b28e571d98a83ec0dcf4d22101ab265aca302b87dacbaed23387bf69ba86d5e5b5bd4ee97671da907db6240529de4708fe305d067720456dbc945a219f0c40a953d5a23be5cb1de0decf6e7947312214bc60666791e71fd801112c2352c9bcf3031ee5f821bd35008a58d8eef0d6221083fe92ab0481d7d0deec9800c923dfd04c1a8a0c152ee140ae56e7eea817a7d4a63e721833d72c9ffd3bc6babb949a5bdff4eec8c612e44038e3d59d95ff73bfec83024964f4456af52bea09c35a07774290ade9c77d7600c24e3638ba1896157bc0effea656ffb444ab75f36777ba94f158335f10ec9ea07576148d0d880a3f568ec361689e86aa9eb4b0ca1942f11e28fca9178c352ae09e0332d2cca0c9177f907a38ce644bcd499d3d0a6bf45b8fcf4a6ea90c98f01019df4cdfd3986023dedaf1f12a2d6c83e3eb223afb9b7577db81f12b0ed094901eb84118895d379330ba82914aa3bbf884f8ebf703c99a7bdddc9d65604b43f0fd1d54026db98106a6e2b5f05dc7213ac689ff0561f1940622f2b50fc5460e705cd15d45703bc316772cef60e91a7463f7ea85a68b77de5e387c2b592d708d800cf16d0150f33e8b535a2a66d37077a6fff7d4fe21a70e1a64589d22a3f7e680f5a0d323f53f3831d71127d98946e3ba4882913c8039c7999aa505e7285ea7c076a6dc4ee6639d14b2038d1332a7632283ac9116ea7fb823bc37ff901de5a020494f9b96618b9da1b7794407b91d97464690be79eec33480aa378f31bd2ccf002156493a41e1f852c89a2e57eb878b95c87cafe8a0401e2897856ea853acc9e0bb855e2a398128226aa239206fa5d638de4656f7507b4d226d20866bb889a040cb88e6805d0673d552e46fd9e436ff53334d3fb5423774b0a3f799fd83114e80dd392363e5095333117c49a962825fd195062e800bf70c56113bc43552e51860d238d88360ab32c01657adae7ef564af13f9fd4204866dd7da5f17853bf1a2300 -generate_ring_signature f31b094e55ac7802f86f73c3525a6cd8e769ee880a8c63aa2f5992c255149a75 b17df6621687c3f37b1a5ce5ac09d95546679313dff994083f079b5cb462c930 2 9085d0eae6ab0e2b4c9289ddd4b4405dd818dc5218188920df043336d491f918 5048e0efec6bc401a73f920934508f4d9b99ef5ecbb439f178b7e65c7d08f410 39467bd15083c5504b8e2a161aa69a6e54d336270f30814bae129f1a53972306 1 0415bbdcd6d894bc056d377cc4ab1f08d694bdf62c572f6c359a914c1351a50bd378f1467bcea70b154150670ff65547891b4857a5db01ad7b57ce416bef1603e4ac86a3a0b160f999338a977380ff22148995358a87227cee8de27c9b22750e8818ce2639b448b0abc1c4e6860443e426f5bf045bbb723db9e076bf8c72b30d -generate_ring_signature 2b1ed38fd7d880a817ba1a9e09166f4ebf6db200b718496e4b0e1611b699a71e 71dddaf7adc360a91390f506b386c69a1cfdd89e948d803863f742d9fb9c5453 11 7670293c88d3439719814fa939089f77b31911384f46863e903d78704c004a4d b0bf008c1c329ea891d807a1d7ef55316b480c19dd90a00233ed6027d566aad1 726dd2e15afbd42415d0bfa6886d84e1f3eb9442f71b4088b04c79747aeab11a df4a86c0db52362d3beb62ee1083fbb3c400553a99b793ffd20d4afd8cea6a14 ff9ca05329874655d5be3d882099ef375017081b3b16a0b7da8cac1ed3820988 88baad2c438cb5208973869e561254d3a38f4848039b445b9a4e8edd2522c325 7285ad0124a73272138c91e701daa44aa52cc647a73351f1f842bd7454efe5ca 0cd91d92f61536a7fe4f7c9a6dc04e2dd74dacc2f2f6a93af216dce3f69ebcec 0062e10dc722a08dbaa346d3c2070973ccfbd511dad2db35f77e8c31eb95b913 a9290ab629ce61f962650140314ba4e6e23ad47e1196460bc33f6ee92b18eeea 6cd25a8510ff4112e5f2c4d15801b7a006db3092e24e2db9cc216c7834fafcdc a5d6b5f4dcfc705c6f42f3ce3854458503a5b82742a2857903bf9a57f297e703 4 4e922754f84435d2a6bba08b1d08cb54b84cc3d64c36bd893039466aebb48b06cadf8468100b5e921eb05ba1ca821fa8e6754988db9033e3af252e66def1d308a5c106a7964734bab8c5678acba8f5b07a39bcd04126d2d05a1936e7e1ad570fa8b326e66fbcb73b86636b12e7cc728139e4d62197f428fece963074cff7b30de8ececaca971b44fc0a19944eb7b48348f8da3b0c9b4e7e9ce4f0abc618f4601a815be934cff18e9662771b0039a39168c29e2ab2b05baa3fd8659657f5f4c00c32894a8cc1754f7ab3c13d06dcc53276ef617c6382fd1b4bb4b601f688aee0c23890314d6f4509ec1b00bd8a3df2775a5032c54ebe6d1aa6c9f129f4214bb0f21e6fdce50834183a9347b3c894eca2c79a2be2738c282ee62f40409a849750b092838c541959024ee799f8f2ea07ad425d1c9fb1c1deb59105c854a613600099c1476b2027ef8f475e15da2a8df91929ca0f4ce687590d95ac9e6e2d0878a0ad8c38092dbc484a278b1a0ae2da6e9b1fd105f3454dbdabc11c39bccf3302000ec9ad809de0b247f86d4e38e644ff7b29d52cdc5dfb23567232955dc7171690219f164a52b7c37b2d59973e1e58cf76cfb38d02b59a206d212093492442f4705e8969b8450a74c0dc4d9681d43ecf433c4e72ae8041f2fa757c562715ee5470aaf2ba2c951a8c7d6bbf6fae29b2c6ffc193c0af2fd419c2e87d6703f47465008353fd035ba7d3e29b40642d905a47235045fac3bd0d65c186fc83543e82fd5059f02cf54a9998ba3ef2e3ce397fa72260c64ea56674e8e9ef96b34d3d05e1e01373c5ad927623a312281fad2b6d8d0c4292917304c147df8e1aa37e6517cca09fda6af031fa6ee63e0a6692c9cef71143458ad073e3bc956d27c3fac68358606b1efcaaf2118bf88255ffe8318c1472d7ab5f4175c1266514a06e0b8233387025c3f5e3c9d46429925800d464a5dbb306cf680b5a8c6fa047fd6cf299fca380f -generate_ring_signature c5093dd27848ac8566eaedc9052fcd6197c28bf93c33afebaa7ce2dda5876a00 323871a9a595066bce864c151cafd777f14afb4943761ad5a574eeadf5cccb1c 251 39937708a3b6828e2561d337b4bb62a05329a677891317ef1fbf021efde4a32a 7d853d909949ca86efe934596d599e2d77997f771aa4877b6f66c9ef477cf18e e983c352edee9ff1590f1b148b377e4a2d5acf31be2fe34df8f6a8d4c4e4ba05 7e1871074a0892900d96e11c48249bf88d429d7bbfc5f0a1029dd27ae601cce6 053b105d261dafab41652fd16d5f6fd87e2c3802d396097745891a1f41af5c99 3499b5ae6a1a148a140469d676a0f42c4422cb71202196215c5e35b35dda93b0 cb14c49d87d8a24cfb716a35bfc392ed5ae3695ce41a9c65c34834f3c820ab4e d4d25b34a483a582179cb1c171532f16f1672c5350950936984484e8f2256c1b e657b8c50f8c92b530cbb8d9e77f3db440326b397a54ba56e3cc6a0b123a092d 4dd6a6ef7f8d5bc9f80693c0a886b0c4432eeab776c17346ac19504f46d622b5 130e7e54142cad6b55cf6143df37f9d206ecab657e1fce433ae278806ca1d26e dc7113def3d74145205db0179dd574c8b00b0e708ae5eb7510c2624500274532 7335c7e6cbd4e8153b9c1ee028e3412f1681058440bf04e6613c49fe1f1bc75e ae3948dd1c2d07972a05cb741943e766fa304e2fea461cf909eea69de08d4e79 28408929a927aee09552e8a162937eed73757ad37ba996365672f1204ad92717 2fdfbeda21d8293c0594ba9671d0110421fc35888908603226cd7eb0995e1ac8 3cfad5a488402caf59a69746fb5cd739782d61d6e2cf71c57bc8c1127055fa19 cea1d4b9951267cdba6ebe4c6bcfb7ff7f465582a73f3b8d60726ee1ee4564ef 36049feba81aabdb2b44241538d15f60fb851dfbc19d13a6e4de240be745fac3 d4225c2a253f2cbd16bb65b500ff4369240284ef1a4cb1f77e6e8143300d0fae e8ce1f23cf3ec0f98eecdd9c744f9894a5c8b3dcb0b29431c4bda4658b4ae24f c1456aae2024890d5c914e9e0a2926e7f004c2e2532572ce815a9ab91f8e282c 959ff70881dbc4521285d80eb7941cd4ba94418da70f041ffcc7479c7c513ccc 7aeb49c0c8b4256f7a718665b575b13cc0688964a8c947edb78eddee1b32656c bc18deebf265b86a577800c425c3c194a390b295063a87aebdf816315e04a0d1 e3e9862b6b0ef2c15cd2058dc35e03c2aafed007e25ac3aa59cbe2654afc8d42 00d1abb0f3f487207b0d764a621ec24265e35ef7d5256647b7404976a8bee167 9db522d9789398ae5954197c166cbd9f876c342836c100364716a3d23a3cf885 30a63e8040c68e413514de31646a18847214d70363850e40bcf5e9f5c3d92ca3 2a78fde45151e821a1a924b5241a2403ccfc6ed62d2463b09e7070b7279c5a9d a26c48fc6e7e82af42fa3cfbad13812bb6395aded22dd250b79f47ee7dfb6581 a801330fb5930a20ac3e1d928ad94a70faa44e7d8319cd6c781d3d5e0b7ce0fc 7ced5508691face4c0630aeee6dd57f510911092109720982102ade5361833b9 2232855cb3aac2d84031685bbe847619d358070216d20f681104f55bd100c2e9 6e49a809ca9d63a6a21496ece8bc4bcf3768b8588456ec1d909c2925f60e995e d3a035827bad58e5a65284003b112160f3d2f45c103bbbc13f00a92f101b2e7b 3abf72f7ac3ffb7fc6113fc42e26031badc02e4d8fdb3f7f08b436514c3f5a31 2d3b155aa6fb6ea05e5a8367039d257fa0b334039d5ea0ef11fc56b8117c306d c7fb3b153d7b88597b92ae7d79f0e3185716dba81744ddd9ac1fcad2e0543fe8 1325b0d92f95fa8ff2cd42384cdef4d2976e61e76ff73072bbcac1369013789f d8cb35a8558bec532c929325f135119af32d6e46a2aa9931a7464c6d469cdaac 7a7c8d38b604d98886d467cd766c40abc920d751c2c94574fad91bbd6a8aef5d be6b00d3cb61d3032253e1a7347e346dca1bb51a92a3eb8b071af0c891665b37 0717cb474be340eaaf4a144b64dac510b6e8e63e3bf9e8bcbb3c46fed88b0f52 3542fe85a3882427abfe0b026c12ae8d195a3db1534254a8d1af81d25992489f ac694745614759040e5dd4608aa75f9b570f77d2e166364d6912cbb21fea0823 5cd8f7e533b3c94444c897c8c91212f0a228fc719ceb8bd55a5c033700dbeac2 872355c0b5f2347b4d2d7fca96f8df10e41b45b9ffb72043a531274409494385 ff1d9017025185587a0a4cdd7c884cc70cece019b26ebc15b09f716560dedeef 186ba15a08137c92659ef620170b35f6b1bc9ecf4c029732451394adfc999590 9c97f115d584768d386ce5204bd2d3629aa63ae97628146498ca37b61918a442 79f55796b89a671a06bfebdca61971130b23fb61eae4704d2fac27538ac499e7 b90a0e602d78353e01b476c3a2c35a5f0c7e5f415bf78d46ede20024a1d3c4d3 a670570bf89098e8eab1fd7afe3e00b01c07049c3722d66dff9b359fa895d70d fd465b0756c76e548d9ca89b6523c153bbfefb1ed9f32774f9e114b60a551d1f 936420d78379ac16945964a1dee95d71940e87c2e88c0a309f70ea710ef1a1f1 7821936f936122f4adfe274bbd32089d4cec99401014b67f0cffbdfd3253bc51 30d8216ea0f746b13f5e4a43f6c4d297d7e6db7e19445749d595eb028ab09ccf 7681954cc4cbb792670aa9a21e64b4723d86495e4d6d27b3cd606b00114c4397 e9663cfa339901c3282b9d2b4560015f5ebd7fbbd4827023b224e54109933369 dbe9eaee8efc256b605483f862a3dc3d5f70a4053ccf29fa4a52d008441decdc 633da88c3db244e95ef373d027a09cbb954ad208fe938f44c3dee2a5c9bd7a23 a1aebb8588a8f423fd40bf80763d0a0e5c4b1bfd3fbe76f14f9b307561ed03a6 9863117a21bc64aa4a8a301aa9798ff1fe6febaffb1e2958b259e1783fb5737f 2eec0edee3b2793b4c35d7759054e7b0c15d4d450b06a5025fb65d8a60f15372 8ca8ed9269c7c5c7ffa431228e9f688716fcc4133c8f4394513251ec26fe3159 f345a4005a7c36b6b78d97a2a030e84cc8157daf4a5a02d63675ede07529dde0 f7cfca247ffb2ea7cef102761986bb68b2e5032245960d800d5fc65d3947f9b4 59afcb1a6088b9530d8bb2435c23a885ee82c3aa0c2e685631a21a228cf07e16 1f4b5692aebadd8d08e8f4468b568a94b2eb59d5d4bf26d5343cabeb20f80f01 897ecba2d98f671188525193fe5dceed743d68886ab7fbaf5be3d09564b619e7 bad4d546d08f62c1e14500f7e340a2eeb8d39e5aa99b9f66d329dd0bce311a37 a6fedfca7f611f99b505df971c935955e2a5179efba1f0323340d67962c4d84a a30f18f05878d4815c755fbe7569d5c042331ef9d94571b0e506892355bf79b4 fd7bbe962d8a76822895dc0b08c9fd60cf1e66e7d91cbb4d88a32d876941463b 5cfd62b1a9c70f8805539e08134011fda0bd8512815c04a96ab1b79f84c6ca91 07477415ae11c9974543d373acceaa7ffac870868220a69e06c3b733939b383f 947545a4a8315cfe81d61a3caf96f5f1a41d7cf354d7095891525ba18d5edc7a ae3e36b290fa5663f46cb37b4d8785778b6e7a5b5da34f28f7a1771ccefdc084 54d701879193377dc59c6df056652fd546b4f3accb0fabc6b6019320cb5ea088 18e49c30704466549121a72ef2756c34a208791ffee54ba4838225c88bb8a8e6 e569ad0ca542a034679e69d502cb792d6a6f8c864c6abdee43efbd188008e9d2 54d46ad00303564a2ee8ff3360eef10952abe041485f2876016994dec2f7ac1b 612af9076950f88f166138e7bd7eba7ce342273816ce9f701b6a3ce6a385159c 527ad33d10c16c2164c4493cb5ac7e3322cb31282c6abc8fc60d5c19395c291f 85b25c37f30e9b1e6afac878fb0fdef3b5145443bd9ba551bca138ba379817d8 f1ecc0173843823f14104228e526537ba7d80aafa2a3f048cdacb2c0640001ae 1cde7b25a4c9b20d6915df9262e220cf42af1620dbe43fe677f97a1c5e021194 40ccb1739d05ddd2e883bfe67a4b4b00807aeaf758a68251b109049674eb627e 541beec1429c13d96d5daea9a75dda434c11c07f445326b1132582caae01d282 646f5b9cc6746bcdc22265a54b7c8043cbcbeebb1ae15b9dee7f6d7c7ec0ff2d 71471b752190bd2ced82c80b406ae39ccc88db4ccc597a24cc1cebfe24e42e63 8cc5a53f3eea773c29cd1a51706f768177f0f388b88d74b2b705fdca00d41cb2 dfe6ec108b198bf4ab586bf12f3f337d341c1a727348582b02e9649a2efd9ae7 02a64a9f14c464086daac1deae485eec3b15b57ba73a3cb6829a45942df6c885 7993899437d2e12076f3311006ec58cbdc36498810766a5825434b3cea5a9fd4 8a99015c83d9788fd6890af7711c4a3701a18cb6691d01c2911daf81a7036e52 6bc9edf373af0048417561db069c88110da2929002ea335ec61b7869501066ba 212d2fa1f059a592c9698bebfa9fde4e1a42a7e5cd3ebcc5dfe4cff5e61150f4 eb4d38583d7578738306c3d8d49bdf9536403765691d7397dfb870b056806878 5086416d7d2681eaef90d4767bc362717d1f75738fe63fdbf399fe987db43485 164a5a51776f41979c044ae85dbfe48a718dc637e7f77602ac4745da472cff14 93cd3e88854c1f515ecdb84622489175df9af084ad7f7072cda98f3b4ea76031 83a6a90b6cba9599afdded09ca949ff11c59f21d715dbfe1b7bb69e8cd30e39e 1411f05a4deebdcb245c7fc6e1260963e848d2d5093bf81567abcf9f84823b36 0d7a2530fb5a816088760d2ff8268e77dae532a31d162fe4538f75faf017560d 0fb071cf8e1fe1698f021a4817531138967476a396b75b3cc904856f2d973caf 030725321cc53ccb7f6131762f53c5e56e9267c4b43acf557be855e62ac1555e e552bf40c1ffaf28e1c467817ef78ef8364d939f5005f981e3c15af2a8e1f68f 7e11b3ad88eb6d844a993b9de6b85439e897ecec629a27e001482461dd40d0ea 16f0aa77b2720fc1c010682081d6cf1a4dc995ba28641cf5bb3ca92be1396083 0d74a5621aa39cd36575996f46f70cb2e17a65a48544ef8153fa3ebd092cd2ac b07a03f471b407eae66bbd77e5f32d7df9ba2bd53600644a6c43ccf2da37380e 2453ee3f5ebc0f2c92ec0b9e520fdc85a5bfd1094774e89dbcf7c47f6a3c8e44 d251b156ff019aae5893d61e0a97d790a6f906970232452c420c2accc10150c0 c5a56fd86a0fd7b6a17cc704b241840b377d47f47eeec7a46b966354655f8b11 9cc2e36eafb7a43d447577fd8ebd8daaed083338bce3c7d150a562e5c77c56c7 1f496612b8a0a887f9fe7ba917df15a26c2a0e5367528b7dc207bfc731bb0ccc 9e53a519f3f0743b9b02d1869a9acde5ebc122f764facec61fbb1b344d71c26f 090a467d9f5b6e63f1d891861ed4b07ca59c39957c94a58b61bc31b0a5fd7ae0 0ef42450c94af1bc08b782b5fd13d4def2d845f1340e911cb3cc1a99deef0987 f56cf062d1975b7d2325078fccf313b0ca0f9bf47fb81a1f9496c59a56c38c9e 72a867219b50935dfe77b3b1df2962f2693f35d1786e586c1106f275e2fd43d1 0ce8053f27a719156673574afa97f4d4472cc0e61508e5e46f34d60349d70a24 7ae67af34879c1a48f48338f3c6a43e28b7adea79209cfe307929d2c213d18bd e8bc556cf00960590987c6b8e92c034421699462da965550e042b0394ce5f3c4 006ee6f0266bc3d1ee4de3c4dbabfd237dad65f3d8d1883be6e8261800a3f504 8bef60f2f5d2a4b6f92113fc6e6644e25786cde40c5b5756f0f0c00660905ee4 d5ddc9afb5043d875d63729e1ff1454e33b625c4b8809d6cc78a722fbad332eb eb9e35797e0754a91ce08ea61798563703fe8209ff6689c88b36d6a30440cc23 32e5d527199ef20bcd81d4a66bdc2ec4e06cc46ef4fce8f047267313b26b7739 bcd9bd9ca2c136832d0469c6e38b8df493072badc35ed90bb6063f10f565ef95 587cf5785217edbd9406ee2210fee0b0963001048943eb4360da7a922e09a6ca 66faac7543d5e35abc41ff40e93d26dc3dbbc0225b283e6803a8586a25d8f83e 481a8dd416ea4cb95da47d4df364da485d7733bf9544956082673aa41655fcd8 87cfab1ca3d4e95aa3419c6c42fd3eba0ec55dbbb4c1dcb2f344a10e0a4c1fe5 66925ceed101bb8ba62b1023f59f4caf1f30ce11d98971e5d26ea31419849e5c d5b3eebf8aa62351c4b731531ef851d9fe093327fb7a4598a5e3b0fa11d1aefa 144b857e9e1fd993dc9bc2677345d5cb721171e42eb90749675e782664e6c002 b93b6b29b90149848c2452df74b309a91ba6b67db97f03d85f0337ebc8cc624d b7b8343623c8331428a87549b7b93cf932dc3008a94920a95987226883bcecb2 7b4538e82a894a23770c06c18aadd0806ba8a9d2a001c07cfaf4be39913c7d2f 925df872ca181459906b39330b8238642f0c2ee8455e79378077064b41615316 c474eda94a395af8db75357c336d7093c996d9d73572fb646bafd395c8ee14e7 0d73fbfc77b3fe3a5750280e8d5a5427417a5474180efd55342fdf464a286cd9 64be1caece30b05367337ba9e0cae59a8b5fca0f872a256a2ca529db87bb56f8 8be33680a41f61ac87e8834991bf5bb066d6761d6b8dc1ee3261ab31d9489e2d 181df403060aaa9e45775e7711244a3eee977179a1a8b265ca469ca37ea8b918 c75c38b856bcd1aba8f0b39da20e99454a829a64aeda962211501db1f44fea65 ade8b070d01fa4825714e9cff03d3888b8e4494aa106ece1b5f19ac93ad662a2 be8cb23501c41cc8da43ff11695b06f03a7bfcb556eebefb3ef756a4d3adf39e 635c8c8532405004c47ec4f598eaf557d0f190101f2dc9092cbfb5d2c194a632 9f0303816b3161b9a54ed048c58f2aebd4b50dd1fd74759b77668d55aeca6966 6913a5aa387f5fc1df608509e94efeabbe1e645a7a0b2ea1731f5c2b76c4487b 3439a5b52138d8489f8e4ea2b6eed403591ffe406c92517fd92a0b94699f4338 e37f7d0be2eda682c76b916dde8e1f59e49a3f728d0e6a384a70617d20d67b1d b608f6462485000a57441392ba0a6f3e080a5702a2e1c2f0ee076c89396e626e f45b075f8bacc04dc537a68e3152714f9ec771cca01e8dedbc8ca0556bae3e50 ab88abef0ba0c0f80019a69d3edf35bb3acaec3b4cabbb999c2811fe6c0e5201 4131146f23703cd3a999104ad4de0e6cbe70617a18db2f12fe205ac0145c9939 7533bddc26066cbd331ea83cd47bed0803dcddf53e44efc8d08bb25622008642 bd4128d7a66046ea22c24c4113bb19550e8190873148ae4f8f7c2ce5088813db 97b798c7b5bee39cfbdcdd05ee03cc41531902fbf2510e2173fdf65f77d33e4b dcf940ab3e938ebb84705381e9bd8fbbf28d38147333027c931969294a73c5fb 8847b8216ce4370e2d6af86d9078e9076dd0d1254d39fdf268fe77fd555ac582 1164bc0ceb2209a98e74b2c8b0208d87e7b22faddfb85264d193b9e635bbfa0c 6389eededbc5d132c379c19f329b97a17504c1d15a0d1394f0c5424d71afed2e 23a1015cccd6b3e32b86be91c5cc6e284728e7361365492b643695ca569bec6f 994c0fa0662667820fe339e742f682eadb7363c2f32bbedb3c0581eac6103130 a07f149f06097c6867f376efdae00a1eadd77df6dd962fef3ff384aa62dbd994 132ee638838203d2f73abf3d2d6565a2b66a49182fd1efcf4e74f337dcef8abf 6e88dc3ef36edcc0a0855b50c9b74918c2a97c143158015391435bcd51cd997c 2f667583cbb5396449332bbc7eadd753dbfddbd858aef3427c1a612d5816233c cea8feb61dce52b4289a8d5340b4309b1c5eb6faf13f1119cd4b2bede2a197d9 784b19bb39c04a0c64d8e03cfa02cccf2bc421b68641a909367d0328917b707c 75beda4e48f1475b63c4e878d44172bb4c4c8223af792ea94ff990bca6b3069b 7faf00a416bd08e6e4ab4ddbfdda1a081a00a64fa0392b95e9230eee21b652d0 2fb7d868c25ff5d388eac019245e59490a83650409c4e6e577df9b3c42f0bed2 b69baad2f76263308d1f073fbeb2f1e8c00bc4bd11191eb5def5a9fdcac60ff2 666f450028ac20329193551b9c2610d8b25dcb9fa8f5940f43e7a60e9c47b7f0 84a1f6033685833b55eac7e04c741af9f760a50d56f209d222b0d2b46d42c532 f227596d9f75206ce74f2f6078986571acf0eba96100e76e01333836cca5828f 787811688624da50922ef60b9fed8899a3734ed64a553ea174255c02b775059e 0c38b0514b4afa77993790fd35a2313f70e2a5c7f2e57504e86b15b5be965b92 33e697073eedc087320c51d1ecf61b54d5578e355c636418b217f98ad8fbdc53 4b64e1c35f9eb38ad17344a4165489e69ea3407101b409465ad17f8b47dec206 7d6d53cbf0c498461fe18a8e68a19ab04374d171951c61bebd95dc4564ce1c98 17066d4063e136e4ca567b7a2dd79aa7aca40634f87793656fb38fde733dd759 fb9ac5740f31fff598eee443097156f3790a54ddb14cfe02aa6cf2e5b3263f46 b7f18404b45acafc9bb8cb10a186a696ae7ffb84126e5458f50a2f1794e15469 929ec779dabe57da88b1281ce1792624c729187e4fdc0d50585ab8528702db2d 8cb2b46ffcad9dcf356bb089b8beb2a461e4ad8cbd5d2532780350e37e41d0b8 25125b917658538e1d422595b7c4a5917d81e47d397b74baa5d713d1babbd730 6ab9febd5a2f5836ad625968e702dacc6babc7fe52d428d7bbae17ea7c3ad61f 4874db513848b00dfa108c53669ebc17506166896af48e3c68148d4bf8b99939 89872f5084d9875e216519bf5a6c0b9211d3ae603683f411ecb84b381895e863 6cd5ae3853e0abe7ab6854b6d0b0926d92c144293ef4dd4f9972fef1ce5d6e37 ab3475fb2007c87278a0b7a48147d165640842d5f67169dc0f3ae2fd305db10b 1ff198d5440e28b78e48d730cb6c210adbe74d42862b41c5ed42515b967b3c68 9cb44a35a2a15d1aa9a94b71d06fcba5758f1f691b48d1817a063b4be7f2ac5e 3b1552d31a70d241c3c33b5ef0358cc846b2565427d7c66094f08fdf0dc553de 5ab0a9edd5f873c69035024f5ce6dcea1fcbae7c75a35ddd3212783d0c692957 ad1d6326f5f0f122e8702a8494a3cefda9c5ecacc61daa3b3fc1dd94fd58e5e1 f8545840aa70b10af0918892800f095aaa228d8cc94527e93b1e5040d1413c88 9209e8b69e44f10f57fd5b60ffd7ea319ee94679bda2321cce9251f1260486ae ef5b023e360229edfcb38c0357ccb791b337630d5296f505763d48ca6d332114 641bf6bd2b1b1356498ea723e0018eba1c4126bfaaf51cedcb144ab2d0362398 6f3e871c296ece9eddc5461072ef8566bb4ffb9071eb591eea8eedfd0fa8a97f 2487fa37a0778bcd6560c8a445d09d5c7fa8ea4f5682c04cc446cdaf1af9f579 7126fd6c1918ff3feb8cf821b586142a07680460d7dfe528aced2980dc403076 d4d6a5d8655a8119d0686d5a82f74606037da1a7a2996ed25e9f3fdf77ca391f 8cc8830b2213ec306c201584340f4b4f5cbd3b3fa3eb36f75786c822e22e594c 32d173fabfc93d005f3ac3ad2366703b38907a2672b5bc724241ed87289d48d3 231ea19cb8dfd1538ad9358c94f381884e5eb671ebee6de0032dfbcdb53740c8 81346e00b86ca5b96febb07161273ebe427f374522df2ebac148d83fb1c84b65 6622ad031e4a255114ffcc1b993d8d3e31c6d65e40a59574905b216a352a37dc d74f5f46d0a64f9dfa77600f3f30b38d2a0143a770e664119f9f77ab9d2f09c6 8e653adfaf5064ea5eeb09d51dd65dd8655fa7fcba239f4ec6ff41379d44768d dd71ac0050e36750b6e33c90efa389b856cc6d06b4a88a2ec732bc505886f114 005dbef9166eb9d661b8954120bc5d3a26f0019ce3f3ed9323c45319e1820551 f5b548cc9af5856e732b3d2d40d73ed801d809611be1b95d3a0a4578974b2d20 defc412b437cad2fdc7299390a68aacb97e78252f38a80d9edabbcd3a4abf3ce e0af56e16a967fb94821b853f6197c6d9994ee0aab2b081ec16ee21f228ec0fb 2853b9be2f74e4731ad0d77b05fae3297fa7087f6e9a6a61dc8295035ed081fd 4d6a31f13950296e764b25be58d3f379d79b3bbd6b38f01fb6d3e473a4f51712 623c7cf4765775246300ad80136a7362cf5c9d862708aa7a19f57f56cc06dcad 548e4d75e578610781844f271035461009b327954bb099a2c1e45ac9b08c6df5 191e63823ab830693cf02c68e19d49e9307c7a4f044b7698dd94d476df250862 e8fd2c2f0a999138fcb936569f3f470c4d683580d72cbc1bd1e4b36faea2d972 925689b1d36695f45765184f979dff2f2bc70efe57e37d9226319b50b90dd469 8fd4bb24b442796650c1f0d825f468b955a34c5b61189a1c44b6df47feb40d8d 0361ed2dcb2a570f577b35cc6d7eeac9b617d70b7967fd4d30f94da25ffffc39 d732a6674821514311651afe2142d14be9526596e9f45e9c8cb658cca6fe53bd fa76c7ea0f87084e9543939eba23cad3d3ea2a0df03733044e73fa25859b8cd5 c8ddeb6e648cfc07f8ebf7a677ff6a038e747e37923849c15c45342afbef8493 5c431e3a46089c0b41ba2136374f0e42ba6f9555b0019995b690e02d1800d814 93dbc3d9dd0820e634aeebdc808ccabfea052b77199ae04fda47859928a371c8 df9e4ec31e852616503784e26457faad8ecd94428884bda9ee6d81c575394867 f9707e1b484adfcde45bd506627735685e0b3663ef00a41c48bb1c11cbc266bb b123a4cb6366790bac198d2d3d400b201c75cc4af7a3430c8a546b9891ae05dc ef38093824a8b47c138e20844f923934f435dc18e84cce31a679a61fe68917c0 e81b5c08382f256377a7fde70b56421e7962d4b9ee90378b201666a0bf88c6ab 256e4f321a15a634355690e49bd7ad6b92cd51c8b1629f85c49260c0c3431f63 ca7b3fdca514a286c7e8f440e8353af4a030c31e5f27ecdbde302a1f8269c482 e6a199df5a488561924613397989d00c595ab63019c2bd1d8b5df37fb1ac7ada 4610c481631c285a6acc307c9439f8f8acfc306f47194e2343cd74efb7007e4f bb2d60b1aeeaba077329246a5a406c310a98f94f3c51ee6dbd102f9e6677198a 834ef843a1b0508f4862ed8013d6555cc21a23c52fb5609c2698c20db9912922 f624c48256355e29be4357a424d2d5d6d9d0d4d8ed3045fd28957d1b747d1867 6168d8666d802eab8552a1908420575c4cc9b5dcda2bbad9c10df93d7b665931 206b2c718e2f34a009b1f1ee7df74b9e813831f175ad5d06e520af8d0012d178 61981a77843ffebd3625d850e0419fbeaaa7a08688d92266f33100d7b6c40d0a 141 4e67a7ac6cd1300b79a1790f1fbc535ec33969dfd79f9b6311e93f8dd35da50ad98a60c96327e1d573de75d5197ac694ac66774fb4a5f011b3442462a9c658022d687fb6ea3dae9c33505085ba037046155851720940686e88085f18311f5b0a046782e297b0ec579aa52b0002c62cf368259710878f3b5661af152457f28b001e1e243964635c80b1721b4bf11e5515c972743b9b33906c36f9c89cfd7c1b056871b6ad76d71cedfb11fa2d29a5ba3d309c160f90c4f48f1718ffb2310ba7067d769e772a0f82734091062885b0f379af0dde6090751de1f179853e48752603b03671cded7081c873b4de5a61082e9bd1235f7abff43f052b5457cbfcb8fa074555384a9cc8722d3ce79599b56777238aa78c09009ce198a57a9160206bfd08bf4fd8a1d4f2488174c67c49b39fbeae0ee42f2323a232b0bf380514b120960212e1483a0db6dda991f2c8736b9df9e7d31c981d7c928daf12bce0b1fdd49a0728f9e00861dcdf5fd9b15455132a5240d5389ba594f15438bdac5e4136181806c422e629d74126f876a0a5d14b0f7544980a085ec1d119cb9fc8d6379577d40ca62b66182b2e1790f55dc0e10fdfb3a8cd7b28da07e78512d640a1668eca950c5fb61dc96ba0d777ef2287b042a10c8eb9c526a31927200dd1097bef7c25ca01eb78c3f71630b880ac4cd2625ad980c0d2169671c8efc42e016ee7e5508a9000ac015e392716b3b9e7151013725e06745076684abe6441cd18e554799d12f70d9f52ea2355df3546b3835c7f9705c6ff7c9ffb41ff3b3263a9ae32eb7039f70b9b4bb332647fb99d7d61d05d38132aa68261f94bb6ed18bf100ecf9646dba1017ccf1e9aabdb9ead1974eb1d1c1fc9a059ab9788c0b201d8e5de85d76642e30ea6f7353b99dc6dd80ab0a740c50e0ea1e7151e318007dbb6d51fe42409f5b40a7f6e01bfabc19fd3149b4248e25b016219b99d340acfb3d9bb716afd8731570dac6bdf299bdb7e4515d8e0eb1fd251506074e08db975a975e620a5a31f9d7b0aa6296ebcd0d3799784a3a151143349e977dc8bc09ed6d89d0d62b93d143af50f2b6800dd90aa984bf33da5e6881b8e2e541f3bc8d8fc2f789319314f8ce8850ed369009d20ffb10daf1634e68c3c011dc8d8d9d2817f759b6e9603d13f4b740f71280430425ede8c579f344964dd22cb449aa31f64537414a80633c1cb02010328a7b38b703bcc632979024c62e92715e8f2adada6dabc007b8c78675991d703b2b935754000274bbeeeece5afac04415974fa15434575878f3006ad4cd3890341574661d1968038702745bd86e3ab8e88ad387ac2983aa2b7955370a6e25705cf9571db8d53f7ec1b29a9a9bd79f5df1139b42e2a2584776d23d4b43ca23209a5ff9d6a7ed14b42885adb3c17f3da044059a23fabc7e7208de27365612cdd0bd18c042cdb282a3f7f3f16bbb79113df7b4d2182f1bcad7d695882cf0607410cbb3791961c3ca45b5ee8a18d8ab6d14f7aeff98294769cfc0e75b6c03ebe9102234c1eb380868c0f247f5abfedca6a071fab84bc88dbb249bad56fa54e3b5408453873905b0137da3d5e29d778f37a989d6480d13e4386fedbdfed3578426a0619393d81047fe2b099ff81b61f41ced2e97ff14477fa6f506e1aeb8fc9fbfc001d77fe4252427d74a8e231a95546861d0c1490923e6aa0458b24e2559d95e60c9ba5d9c8533713c8fc975f18c534283b95974571a78352d467ca2775f64e2308a62df53bef2da6a945bceec7b63b279edd97f22eacfacdfb68a6835ee183f6043f0232c819e33ef8d48265c98faf68826d89a1784641618ea56ed1a18ac98700f40fc9778cfba5f0520b2b6c19e88c67f63f36a1d2d3455b40051d095ecd360a0516cbb8a7c86ecf4bd9987c6bd981c3abed6db965815b0ec20571c90016380500bae8ee2cc3dfa744dcde36255aac1e5fb795617e1e67d0fc9e8d766ce26905dd1b6c455f095435ec412e7a93637c734e810eef1c862a51ab12370662fba80762117a0a65481b98d7f92528be2469bc9b7b67779ffdd06b7b953f29fa040807840913ee988b4974920bfa08e71a8a09d43c38c532fd9db09344390a610e3e01d8d27573f8d6f0618b79ba6cef66470c646b6bba1b8501b57127c7837b24c40ad3002e6740418aebf28bcb3d236c8fa312a0dced5fb5e30aa451a5179da783006c7801089b53a6539188bda423be7af7c42a56216cd8f74d9a2878246d7867026086e912efd959ef41b6974a413e6d5ec54fb39d0caf03e76d6e52f2ddc1b401737b847da8c1ea3a26ea79437875b582fd22c2a8c8a1982f9925c70a088fd00f5a60373e26344f28860ccf8e6ab361676e918cb73d73c3e1ff18f29574459b076522d6b6a7d7292fb7bbf143a8c651c14cf179ac582a532803749a465f8cce096064409c944aaac8933c344b2fb714645dd9dda31306ee2b17960929beeb13032e058aad5888297a1fca21041e51cdabb38157f157458d3a546480d1ebea0c0c218bae518c72ad1f096c1ae339a02933c110121f1d28f53c7d89729bdbf2e103d117eac5f5f7a0408bd9d1a702e25142fcd9ec521883c11f818ac58e54f00001093d6e0daa39a484336c4aca8c444a093794d9abc3c9bd3c4f89d46d64af040c8cbf27dec713ae9d8342a9c5979735e2726fe7668377ee37ac80cc7a605afa0704983e5ce71c0ebf5069575eda2f54396cd2d1100adfce24796c7ddb5632ae01f3cdffb60309e4748f4b5c8ec7eca298757c9bc9f1e73a843bf65477fedd0e0e5a61765bdcc15bf9cae2df7be445b91dd80855d7570ddadeb318c1786d9e4404ebc558369b09a0cda3939cd9e7ee6eaf4e22e4dc3336e4b7650f347c8642df06bf192fe5f4aa21abd106ac2e093d107b243d2ad48a2aab1b3b5832d8e472530845e573874cab57742cc31fb0b1194f7e6d77d491dd377b55fd2a780bf8e3cc0791b6529f5897038e98e2d33d3f4465800c67671c5cdedcb21c2e792ddfaa250aa4eea5e7f81b56e4ffb717bf0228679cae32ff073e0f0a7fc6a7799de52e49026738d6cd7d1598c840360cb5c168d98b86365817c50427f30d5e12d60280dd00c25bf5199c86a8f58c7681754e6dc737707a6f55347ffe409a04bed4b577bd06af96d8545c8c0cd7968f9be5f7c0bd9775aaeab7161604d7e36d0b0c848de30002807e8ee3a5045d591489e0b33169c5882ee700cbf2570a17ee7cf142ca13036d816b9aadd06fd77f43a9e0b40b7d229375a7eb5f6186453d6668fc18683609a28007d19f1d56a08630da9a7e4e3ad2e70fe9247ffce23eaaa6b74a33346503acec3558784ebfccf56114aa3ae7f69311fbbcb8d6d6b0bc5fbaa281e2abff078f6c12c4a289d0211eb036c8b036f306b9b6c32c88d3731f27c7e45ef27f2b0b1d975a5a614ab986d65586339115121dac6fef2dfe50431b6d1b023b50808002eb36beab4532eafdfb967675647e4b6d7310e902210d22d125173a817146e20145bdfad526ad1e57b57dd6bcc86fbc9e8b44051f5d0b69128aa3a965200d81036b26ce7f4dfa4994acb50003f8ed28913cff52a9bca774535ce8f78045688400169e42475e1174d5da6412e0879aad9fb77add817afcf783d9ab4ee83aadc50103f670cf0f7792d56112de68aad7c1fef98fa01ed39375d0e9855ce7c032010a902b51cafd56d37364eab9c3ab21f648b159e3cc082d652cc8bd21754e2cac040f838be62e832e995c50b0610e5e4b3e767f8521c1745a3e63791a36f8475d0181507f31220558f352c2acd8be5beb2bf71c0c20ecb2439b94d3db429797eb0058e4e7894d0aa8313688b5ec6df0823783bf606bcb14de2f040805c9231d7e020c66b902affc191fc9fc25bce65c42facf62f6a76892c054a5531b48b0d932057430e5f81cebcd9bf6c33161f21b5fdade5647792c9271bc592fd173a363a00a0460f0c19dbbf29ba107026cf0cf172b4c7ed9cee9e9890863c65d666f205302bb6af64a9698ec2b1dadb2eac59438d6d3c6a4e6fcf79ff765cc9b28efbd8d0bd099635bb30467bea5a53e6918f3d9a9616e26ae2553cb08c44c4332bae35a0cc151842be36c98515c3c08719740651784ec93d2e2a47c7be9cbd8c71473d90f21c803384233e07bbcf10964985b38d7d935f74749cad59251153f4a7d27ed0c4ec1276018522f6f2ce46a97ca1b25989ad5fe9b92bc6b1396112df79ffb220833d75be1a6b9d0e6d17314396d0320188ded49127b721e113d51d2eb3ca6fc02ca7cc525de7bfd0ae0ba54aae895fbbc260cd2fead7b5055e0664c2f0ded3501c78b6a530857967ba3d942fd0ed3d0796a11c03c1f86778b8195fcfd84d952057a533d04d748c77c0d365b77f1c0dc0dfc69cf461580562322567f8b0f46050498a29529b624df50c49a3ec4102e2db13848631a78777ed6df003afa0206d70a9e5d31e059dddd0206dac32bf083c8e51f26cd53006ff2aa45edddc588a8c103c611025b883f9597fd32e1a6c9d2b99db3ff6c43bee87c0b55194b0b927cd909da8475b2a19a24843a492df9d46dce549db892c5aad79653469b732b794d1a07b52f572b6f6abf3a1a9fc4489bcc30ef9f3444261b944a92d5fb482d50ce4d088a79c14cc07953072d778b0b9dc7f6d91b4aec1c1a1218d3700a8be986d4f20171e51855cbe709567090f2ac9f50b98b990a66b25ae90bf30c8260898c3ae10fa033c17f463ad520bf60d18d159c1017fd1ecbfc4159fd97f7dbe94ef5e63e009fb47b0844893954c5edfd40f4c11840117a275b76a19f484a0943422b6a8e09742bd7745bf312b40324ecf9cdde61c7b2b7da2dd461e5f585853eab3556870f81ed26b26954c4e70c4ada951c3a81913cb5e01816f554c9c3ddd9c50480e40382a826235cb02887af2c37c9f8f983788713b04f3f3b8bc8c1b3af3ae98afb07e07c19c47559130fd03356d8ff2e766a0af558ec090b3fd13c6e4cecf1be6a0e37d02e193613c3b4df12a4d7229bb6bba87caa16d21e0bb6a447cde94a5b210fe1bf41d1237318d7cf841c2c1e88afca135b46ac4d3e48df0972841434165106264494106387b6d693bb7579e71daf6e4d220d22961e7acd111255401300c4039a0ccaca5a4eaa7d2483f41df06cabb1d6e35d4ac321bd13f45a0360a3415506811ab32cc6c32430c426ac484d12e6125ae53160747d76a2620582c14410d30d4eabc1ca13e0966898282f9493457b1472fbbb57a7120ba8af7acf811426340f658a0ca5911e76974125cac2006093b71626d6883d8dc82c23ab38531f17d802000375368f07a5994a9b4c8c651cce873d4cb192328f6d7ffc3dc32c292d47048e6739a3faeec4a0d99c4ddabfd70442a47756ee6897ba86b0ee4bab30dcfc0422af7400a5bb9ed4a57062bae7b3e9f94194ffc76087f6e986252a68c2eb520d8b4d8fea463992312272ae6dc503053bd8bd58cafbfc6cf0e778a05636b93d04de19bbb8a764f2663d63247bb7cba7392170f097795ad3e20205479b9d6c3d0c1e3d1aadaabc580112dae35ecb5d57addc00dd52d547741ea58fd017ba4e5b09f8da838d473aa5aed7fe26b054b217982a7bc79b6f1177b930c36eb5a0c4360c58cffb85abfd55a9ac6f3a9fc521022f18a377a5f874c6fa01ebd6ac2202150fcfbd787aec86c540fc64a636ca92636fcd290cbb109e206deaefc4e65b0f2e00b0190fe0dda4353d4e2a929ed9e4efac45a9bc93dcca748970460355b9632307cca776d7c41d8a77dc84396c4bbf5a9772c40b007a0df203531d2884e83bb50343a39bea1e436b3717c29c5dd29a36c208c22293fe75ac1e0ced941cf2d96103739401ba57d1c7d908d7388dd8d4daf08c1c9b678e8393614496ce46a1bd870c64912cba2d64c528955ee84e35dd9f85476de412c22056c1546561cb1f113e0f511e0216f12e7751b661832a52586fd908fd42e2584a658edb5158514f13040a77010defb6bdb5db11067f12430c30a28d2518c01ffb670e439f730aeade4c073c6537abb4fad0d09c8cb41546cf8a03e1fbd0595e71f75d034de629c6a0600b3cf372cbfeb570f0d196bc51a938f92252e661ccc023ec062117b3d28d163e02d41a651b463a5dcece0669b9278e3132ea18402986aeeca50008f5dfe9eeee09a377ffbb4e897e0af1c7d5a48c2cf87c4a30b1e56dedb1d25687520152c2b108dc3d4a7f7105c2cd2816830f0b27c7795ef4d58a947bc6476b10e6e1d883cc007dbc3cd7dd0cdee2f4ea6b023d54fa01a5201268e80372d7279dae38d1b0060a5d364891627ae4972ef69051d8b80289dceeed2554f0eaeb7efe0fc75173dc0cdaad9c881b5cc5da881594eb3aa35439e80ebe3cab22c99a5e927ecafc0b7d050981d651ad100f90c81ad9fa1d8a3c9e55162253d80626712b5076c34cd82e02ff2cfa0a9b141bd1e60c83f390415aa89c6f45e543e1141d60ff7292a240b00cb2042dac5e2f90f800855b1f46ad67789bb2c15a413376202a7481a31bea9b064966cf5b5c8b88ef8149963cc3d486b8f2b67d568b3eae8dee0cfb88ada5470d0f7a843eb7aa0f241f6ec12cafc3605ec246c3f53e4e9eacb3fabc1e2669e20a756d5b85a68e09988d3ba58fb2891208fec425c32e143f0eacd1ab18c45c4b04ad6836757009e32b1e2aabc93ccbf920141645ecb84d8529b1e80ae4738ceb0c88e5edd988e61de07166ef5fa497f62246508e2390271f14603b2a5682c60b09fcb7053857cb24b29bcca1e9a1bbb372dc55436871199caf0c06ef087b08f405038395d459aa07594c3b18151ee930f4e608faa998739da5502ba8d10ab66a052f72ab36b4ebf52ce3aaf1cfecdd99001448c2b2705a53babcd9a4a303ffc8057cf9e6482be3c3bbb1225e1eec07412028f9d7e00cc59f8fd800c4623023f2051c2ffe5b0bc18048ed78196bd0b152269f379b23eff10e6cff2a367ec69bcc0e6df5880402e32cfef89622781316ab6a7d918ac84ba7c2849ee0a02fe1f9c40dd2a5af52b04426b3b7588469d11c2b9ea8d113025e4b2846dd998b9629ce4808c8dc582dd2af193f027e4b1207f71fc34ee81586813d950275dc33610b38aa03524cbd0e5fee5b3ad6f6ed4ff907233c7ae14b3849782e3ac2b5bc87dce5680ca5146536f323c0d7e213f15cda539b7ffaf6eb1707077edbb9e21112a615160d52df5b4866199da8303824879cf62bd300ee15362078d7996c14ba490e90ec0f42cc321dcd24b226a1312113bbd2b7e9044d20be8c3a505989f10ac9ed30190e8596691a8638d247700928d36db4d5d3b3fe2e5b39ace8c9263891bee7e43e0d172ed241411c3b52b4867601a27bae38d141c6f34dbfc4630fd6f523b7ff430c4567702560b222efdb6a4b091587937619248f016dd348d7bd364fd81cc9d80a83ed1ea01096f30dc3ed33b88a7ae6a88cad49e9885fc74501ff1325dbb02f05ce5070dd2854c66ec0a03b256d4598b26bc073f9161c62668f16fe25a641880d5b14de234b81eaf22a7a339e9cbc1525f160555014f1ad0ed92aa4f2ea70660f91e5d586c0e2b8055396813a707f4e336fc1f29ebf23bfd43e87af0930ae000080d19fda872b57d018fad4d217fe1b2f30104b9db0f7643c649ede742bb33e082cc736c78f5c52f8158c149e06496e58065aca611b9233398c03a4fd4de2ec041981a48729a575eefbcd9180bd2530cb4f554880031cbec9c250f4b736bac10888c97e0c0c673dea61e28b45cf86909937351d8791a49f389e05e612dee52f0b61b053206a9c88ff9e9bdec0c69c14b408268edaaf6d04a21917bf05848d2d0f0c3dd76a5067219510a382ef3414512994004bbc36c28098bbca81f7e798a903b04dba2e3c4a03a63d72d1220c6da3073303afe4f792b4416907b31d8697230672887657cd684132bacc87314a2ea693ff6f55f006175965793f10dff6e3960b60764dfdc141284bbe78d2ae1c2b1431a16470a1cd563992918b565980c6450c40d957ca80dd7a275c5069392a5f1de2094ff2e0b5154798afa64e199cae9107d34183134c6675041a3364fed3b7cceaa5253b9bc99f8d7c3be09bfdd130ea0c59582971248b038956be5aa44e9437c54f2342c6127d312e39281af5dcf20206e7c677353669c3a36a06316765ca18984062907b6a6bd2d9e183a0d9f16a260402736e71e54f4fbd27e02289817995f7ad15b50fc8a2a27be822acf7ecfb78003e829d6bf32e4aa8b64cbe3a66de7e76ec40f0666776e5e863c48d4115fbbd0d5ddb3a0adb8558054102c34a9e9b5c0a6b4721064c7d11aa00080bb9ec3d11040dd6d8ed85c0fa1633ee2c1a7688b8fab9a16ec6bfc42243c0a80c662d20b40e7ca9322bf94591cb392d2f1affb4ecb2b3f0512d94571088a775af791e4603051a4707901a550c3104de4741078ca43b456fc9acbcb67aebf46856f2a062440846450e6af6e635d6e91cdccd8b7d97b95ec5fe0a6fe0616d2192c27f43786f04df12ce29b07e57d97f354a2377a29fed4c63bbd9dc2cc8ece9b07d8c0501070b670df267a924d21173a389bfb1d0c37708cdbfa2951d907a2b878cd53ccb360f1ef154b28e8452c201db3f644282edb7d04330a2633c42917bc07bb1980b550d3398bbb2ad49070286db8f9a46f17f6ed2fc9fc1518156dc6c1395685a0609023a9f21b809008e97832399710ea9e0d1c12f4456a878b2c5086e915166c11c05eba04041b199c295583b3d5c47f5f3a4f37a5e6ddda05be78a1c0a7e3e3bd5006c59410330fbbeeaa2024d495e77d3dd82d7c629eeff41d06ecfb2f6f0bbbd0b538366e6a2c971abee38a12580f1c28a313aa08b80347edf8bc9ba97cc3dec09c9307b37fe6bd16b31b5aec3c432ddea0083c6250758b0ab710d550e797fbf02f563e3296231ac35a26a85bdc40d50f8a71d7b0a04fcac8d58e721eedb1c850e5014485ac3eba8a1f838aee68eda74474a3835424994098f369992aa8e31520beaf70a8ae3a29f6cfd38f3c3d692df3d03274efb0f2522e0234927bd327d470513c21e34f7d0797211f35b17a276796322201fec51c251b160ed49a833922b0e14f251616a6930236f3075d222c5c1fe7c5fe3c904eb4f2cda39cdbe4bf3b80f3d99e00b12fc167fdec761dad45d7878ce6191eb440fdf8d3b590e5a791a3d0902734b97c6acf63d4a03a3f4fa923f634cd31f6eb5043aa302466cdeb56179034aedd4195541e6aa0ce4b14ed48f494f9cac4d5900de8faea15958302f8aad0a159ed3316425aa5a8da34c30f798ecd5e0b8deae2dd89e62a50f2a093a33d80d246ad0e707fb290a05aae2299232860027aa27dcecea6b8cef8fbb46ec56f405fa85d97b631e3944bc29d606f4a897f53144c66bc6236a4ca0df3a996d2c900d9e7d05e2e4f6744b072c228a963642907e44dac5960c41b7da56354b9ae5490945796143ab74cdf9227dffddb856ce63dd1705d57802d7bf5cb9b85c6e2eea0c837730139446d602414c94f0798911d8ccbd3d1ea4a878f799d8aff09a49e00d160841e884251827f78dace87c09fd5e69754bd50e16a4a7246d808f0e6b640f097aed72e68d63408dbe6fbe687bae732d1223fabc1804fba9c1ddfe40d65d07328496fca25a94c4d255330f20b685600525c111147dd5064c0df65a0eb3dd0a2b1614251710381d1ce49d2f9e4c02d2dda4d9445c6bbe420552a7140ad16f07eb8b90901bd2f43fb72d575539bbd0f1079645d9dd7a410097eeba6868396708e131f344e3139bbb83b3acf692389d5ccf9933f5a4f07d972dabedb5142aea0924baab9baab4a16d6bac38589b43a9a8a631b7e84d0490ecd6550575062406065a3120d5586a65206e9d54c529532262556a6f0f4c41821d69532094ba2a2c0f2c1150e4d9c829cee1f48279d208a1aa18cce4fb0757e50cb7721b1b57f77406e8d96c180fe8d245d67246a51e0e3ce476644fac65857c6ac29e26af06b760006b90f1e5a0ad8e3d069aaf50b7cac0b71a8e336f989cf0633bc42bc1d2c9a9009ae9bfd5d540873a99af3a8bc06f35b31b69ba58d759fd6129bd3df27c85ae069e71be14e7e223b04809d097a3bb04a16612891b5dce672bf026480ffc23be03ec7cecaeda733e8d94709de1452711bb89bcf2064c5fbf54f8dbc42a09a72904904dc6f61cab975f5e6285872067a4b2dc81db55622cb349a952d0b8423c9604b2dd54d6d7170bb0debd886a6a50fb28ff77634c4f8e8b0c949a989b4f0a1d00b1df6169e54bb450ece8282b6fab5931e825d26cab9c75afc68cf58f03d2ae05de6df4f31a0df8a31b8b68261f2c5a28c10ab713040b99954917a75ad31e400bce87e455c3e39d6c5ca11bcdef5df0b0d066531561ca27558d346ec3ee57b7097e2811824cf7d441c42538fec40f6783c695f6cfb698361d21ccf30cac708602bb18a5e2a627d2609e9c5533efc346a2a6bae08b1ff1d340cb67264e0adc8401ee9c24454dbca98653c19ec92e7def47d9dd398fe2da283ab466f2ca5162b1027db2d7aa3a85ac5786d1869caaf84a3c715d108121abb7ebd91f1e127c0c880364aae15de3901be5e0b6fa1f6181f0586f9df59dab88db9af0aa289ada08ce0ee773cfb2917358248594de7b0fa9be0d0699f54c16ab3ec581c2c9fc7154d703fde9316c838244f1a9dd3c6009f4f6f7bdc4e2826a0d400ebe322758e218980cef3044b754a86e113023cf973b55649e482e2ab18182bd34b38ca33e544e72023fbe2f23ebca510c1d257dcbf2a68d38a1fe1f9bfd0af64f8c8a5ae6afb3a60ecb3f8a43f0a6f589f0e178110bc6f2fb9e46ef810ffaebf9e1956a1a8f82c601a73e6f4d6b05740a1a8941ad4a53465041a8cb0082e1104d26e992842178940bff69d3bd914133a7afd4be25d20b0d8585ca5852b4f5caa14c1099a4430e4901668c040437235625422b6a3ce0ccddb961f3002bff5a7e95e69ca9f208ad950f2d96d5de67fe4a3efa801431a12a274eebb021816ed9a32f40245471e34c5d0cf127148d3867c8f98a223d8c30589a0a55d3ce32a0b07d5bbde6453d77d62c04e7c881a4ab2f2f8eec40df0fbab2e7f223f21da20ca329fc78bd1a8b082b5e0aeaaa110225d0bb065e40b269beb295b16126c04c095b58be9d4621f6995e7103b3fddf74f9e26ad5a5a1bf7884be7573d29a04baa7e52452717502314725050017d4e6f91e8822704460820f700bb33f1f51464f4cdbe9081612e7e5c907790c481acb9c159636920132508dee063e943d3df139dd4b5db4fb07dc82394cef00ba923a769ebfd0b8752c3c7b8e0265e0506b410dbb886f3c99071a15cd192a030a41b11ac3ac39a8eb39c0e7a5d326c590d33a3038f97ba28a0c61c787047e04c0815a502e89fa1d7a3cbb0b5b233c1fada19c6799991a4f922309f9201d7106ddeb0bbddd8310085f7c7d5e948621e2b3283379b3a9cfadb94834f9fb73760edce404bc17cd91c29e7f0ad88af434fdea071660c59e5c46c028f232844bac03964aee4678eaffacc944b06db61b66d716c3749077164af13c539ee41be4450d974522ea59219c73064da294b70f3f6bcd08d00c49840f28c31aea56afd25b0d772cef073acf5bf95d23e678203446583093621840d854cb02c8cd1a52ced50e2390465b5e521d937f6bd58d43ac6731241bd84c085c3e29d7335765d28e3106648be285aeb932d5b069ffe21341c1845cf964a74044a6bde2842a63e7a5ae0f8c36f434f1e7c525fb3ea5b3f3033dd54e25d179c9d524cd5e7c3ccffcc694050a719728aa8f54e1a3a889663569c0e65d603d7331a82ec3fa97814ed8a08e056a5b3867f45759823ba8dbe86d4b60102d026605d1ab8ff9eb8cf81ba561cc0aebd01b5fa5b046adf96ba75949fda75da1a3ff3d091307f721ad4b4fdfb62b06a69b6f6bb6fb32311484835290e384c17f58f1c36e235d41aecd8aab78503c0750746e3fe4dc9a9ce5e7bb6ce59df759554a9b057dcb3f9af95be4178c34640e7ee8c1b32bd50ce661528a209c3b4967dc0abecde33701c9b7f806b31dd91d0f6f4e76dabbfef290721bf93e0c3e9a2250edfe5fcbead26e0cc7804900945707eb7dabdba53b56fd428e52c01612a04f48c8077a0fff421aee3baf2c23cc400c129f98f17900c53560520570a59b5a3ae121cabd2edb7e19cf482daeb30e7d08f57afefe104efd55ab162d2ed7e9c171f78f25a54272cebfe57cb2a20e2d4306b27c0e2690ac0000e8da87a7ee66d8cf7ab7e324837f9c8cba33c6e404edda010735f5d925fa66d849a4cd2d7cd56f5ac1228951244a27e542ffc6b0161e9b044fee3e4c4b22bd328a4e6e74add87f77b1c9d69531e5d43380f7dad20ff3eb073ecb0a8227ea7fbcb85c314497700277105e705f8daa79b3d4fe7323c3dcda09753b9f99208f3622fdbb826165bdcc4508df12e5cab71ce52b1fcdcb218f1c0c6123ce1c73032a6d63b0847cf75ae949d8f9ebb14c2ca1b9a9d832a8cc1e770950a726e16a2bd5778d27ec46ecf4274757649301194cf8c486328b705e1d6e01f195a1d4660e78f5c9facdfd09606835fd764f7e21e6d48ace420eed20dc9e0787b6a8bff2cc9aff530e5b63396db5c0c479330577f3780529a2e7890366670cc2ff7f3466955b86b47a72300df87bf43f2c9cd2be23163151d041765f1b2103563f82bb2d964365e6faa7dd7705247d418ed6f553c67b121423d76f292cf20a483331bcd42eae8b63376e303b2890cbc4a7df739a4c0c81d7640f94d0b97c0262107620b2bf856b5e76c8792d86e362eeb7c033082c24c7ea4e745452c4c209bf5a053e576c4f2fc07417352903c345be0d167022ab65ced737904e2e2c010a9bfe31f13120de87534497a80e8a822f422dc69a38e246e329ef1f935d15840c065f0d9e6d1426b40a0d04936f1f484427486b6488d9c649d9c91d6919bc550699d213ed84011f2b749885ce2be1b4c6999cf3dd11ce329fb6672e614a82910906c0e65ce0a49194badf352d05d505fac38cc9ae4eb8f246d245328467459f0e405a98b2cde688114de7e73f2cd6b26359b30b185af35b9fe33ddbaeb355870a5ae0a86d3deb581df03c0a26f8d95327c9e10f35aad9b811a05a3829b81fbc02bd36781af9873dc983a8618e27790665619d9d0dd2efb6b838588ace940852005f615367bdcb7e3a6025c49470395a674bbc113728a0ef35583ebc5bdc8191008a6adfd195a2741ede9a6a9a0e114f66a695124c5b1e28125df3a98d4407c40d2f0439d43ea5110ad5a0e9ce0dcbe747906f83e6b020b63f65be447c30081c0a29a66b074825584c67f3eab551fb82d2cd16e1977fe60e7ba4554ef1d986530774d005fe259ab622fdec78fffb379e8ca7b16c538b1185cd81390fc297125006208af0e06e8bb93d70f2aaf6b3102453ed4c73cf0842a598825f7a3d4d3d040d2ccb60ce93c393392d11f60da7b06d786db98ba632726f2cc73654073fbbf10aace74a3ae6ff693b3325b7efe95b5f057b6b05629eb4e230faa1a776a01abd09adea1a20e7e1e2ca29b497cab9c752406619a1d4e0f67e1166be08a1b57a7f0dbba02cee84e977cafd3005a8360a4f9f3807dfcd973bcb0f60c6f6aafbd6e802772fb78e769a009c627b665059ad3c7734504e391f7e091a64ac8abbeeba840a871f7510529a982f8ed0ef0bf5e2211f19284d900b894c39379d72c0e54bc8018d7dcb9216681bfd8ed84842125041efca0add66d7dfe5c720c0d7a4b01c1c0c9087309b98c3213897d0159864d53c70b326d5d786f17fc62e2431c8060db901018315b20162ca127d03f5fdf689a57c7a542f05add01f500a25a0450ab922096c71e4c631d27d2ca09049dc81bcbf61009ab17ffe167fb8f10023352997850f3ee3a87f8fa039e9a1b22449f08d531cd0e248e41774653d56d99156b41b5609ff9f481d2e3b7e968f4107068b36ff4a5da44ed60a88f77b7b70f55a690b590c749fb6a4a3180db6a127f548b96171bdd8fdd124766d5fc22a5ddfd48dc07c086eaa9034a7a74f62a648b7a4f8d09ab2fd59fb428540f0ff1ddad1313f415506114e23f574ca17ac664e0c09fae3091489f8426be2b983044a5c7b922b47750a64a4ccb21000e31c85d92b335a419086ba5e256acb7335901e467c52f6e7a70db25ad7cb48d7ff1981a3b22264b3d67090d656599a46d80e05a886fdcea140069df7eed27c380cad9464b071f61c51e54eb35d977743bb49188745b8c8628c0174ef53502575389133f4d28828ada9b76cbbc82f419217f6395f88063763ec09f9e2d04ff0162e45b264b263e591f07580305f8f2bda16eaba552ed6212e9406ed4f6e57aee271e9599d98176f5c6b3fcc2e3fe6ceeebe48a38e3b8a6104540109af1233a481e61c1d8f7190c69b49c7d18f39bc3811398323bc664c57573309f5bac76a5b51b63cd2c284287884c2857dd9f2ab87d306e67c8a637adc085b06812f76f41dc1527101783a2b942e88d694dbbf5df525b22d5793ae7f7d7e8807113350e14bf7b58b7a4e11a052d8c2a9bd01d320ebbc50c94fce8d859af908081857d11c50ea4f97f7b357fefbf64a9365004ff3abf7ca7bdfcc4bbc2aaabf097d068434d843dbfaaddcffa3c183731f5484060467a732b61a0f15192800020f15e9807d6ea828ef8595b182aab943f04d65f267cd61a50244ca27a03c4c4f0bc4d69be239988132591adbdd8dd76dcd85647d768cfdcd5842ebe8cca88d5b04f20a465d4bdad27813d1c00ca527b2cd3fcdafa14e21d9423da6cc7c04c87f07a1454eb92c178d7ace7c1ba90156d2c550a49843ec9d13132a817065f8c5a3030067d24e1299a0fced20b8e62fa4811c2e2dd2dbc1d7a87f91939a057a570405ac9df5afe55691f94c79afece38c030f6f355ce4ed4784bead56a3d21c6f76074e3299a8cf37ed66c9f76e055fea6dc08d02d8a4051df482907f6425cb478c06433553a8d1da6b3e35f395403dfc1ff6302109e1b6395030934f32dfae4ce20536892f029cdfab6227b5a3e527cd0be1e7339ba449a900f1529fd654f8ae3d04f209afbf4b1b1c519852a6296ead7d150525389761baedf44ac6071f878d71050beaed1e520f631a0bde169a230038011f07f2f990ad52f07625021a254b4e018a4ef75b6014042aef20a9225d3617838ff1b37b18afe43aa449e3b49f9e2f05bd89598a4eac23c70b3145b1cd1577d8dc2bec5551165956f7eccfa5a507da03a65f6ace76a6057cb4064998eb3f960a5f91f4bfcb40a9a1e0806d22781d2d05da58e2aa1b183b5782e65442511b5ce6dd776e3f4a2ce95e8a3cf900df1783041477cc1dd735ead1425381e8a80d123c979b1a835e0928cb2b84984adb60f40861b5ff393a7558baa72dffd3c6ad39f7dc023509004a12722353db205e431606c9d85a7265c08c38744ed948c8d526aa252a7bb8971498faf318fc9652955802aac1a9b15cb8da39c54e367a3f3ea782c2b52f532f04fe2bc4c6e81bdcae0108d3e3393b7a7179da8e6fa02d219050d13ed3968a392200abf8df9b2139f5b50640d7f253f8ceca1c7296cd353559f850c5e5d5403eaf13192d3715f9c6db0d076a2bf0fa3228a45a3fa3bc4bee114dfda6565d38e9a70d975a0bf649dd4bdd0261bac65cca7b569ada19ddfefa126517ac5e2ac3441ea014b3f84ec7ce69a104bae63da0ec377e02bc209fe08262aeb2a3182aadaf87337937d93cf0265f880ec4fa6937027da17ba90de29893fdf65d0705e4c1c3c3ae497a6b8f702fb3df0dc2cd00e48ceddbd668f4e4bc5eec6d332500515bea352e8d897ef7d49e76390a5e298ec66a838f2216d3f1f0547199f40c4c4a453c8cf014c09a0a1b25e96c064f6367eab9c1173194917c15fa15b3b7a7be00dcaceff71c265f2ece50e67e0550689f939b8792e202a490c0a6060a0a452185097974c96c4e990ea59d0a140b23ed8bb2422b96cb27a662bef936f5e2f7ff3ab4b019a4d6f6051e334f4fe30f5c932fa98971075c6483fe6a2ce29810318ce787c101d4b1ba15a457dca7cd02bb2f4f7678d41bd32114202f7492548957f6c711754aa348d02143681a5f4905b82ef496b1535f848bcd4ecdccc4c8427bf2403d3dc0a681767d0f7ed7491b002d11c85ba1b8352887f981f5247d6fb62e23d034c22b202618512408638b1b03339c7867ec8ea70d7694b5ead1372b657595fb3530a9738a9908fb0e24fcd306370324f7993150b96215ff3a8fec8f1158f91712ce37086dc7a59d4bddb588054f22284152d2b3b1e591c6b27b1b6af1f92ec615cf5ef9076fb90089541da5026f651189cdc770cfb0cf6abbcdc9af8e36128173ccbd3a35afe1829f9cacdb0b6a20ec5035a4a4cffc2e85aa284e4dc6829e553906f8d39b3a3142289e1c080b5da4e5c489185ca64ade170750f0c3c872b899a6e89b62b644713c56e035b804f90d95a071ec6e1f8805edd90f8c57e8d886b90ca362d6416fb34063cf928609b5fb77b6d87135e2a5eb160fa79f24761aaac4e7bb740bbbf03e5a3f42a6ea0a432d348c279af085217c0bf2fc05bce508dbf1408a211d025ea73adae34cfb0968c223974583cd36b178aa748751209e29a0aa9602f20a2d7cc2cc9411fce3032a742deab670b9550cb7be44d47b8c5cde9362a3642baa92d48bb3be29defb0000d4ab583104e1ace4703894a88c9283d6e1340682377f3d7414a6a002a3e705a8aacf50be94c1c56b699aa95f7e6fd92d8cbd4397490e3751605a62f97c1909fb71ff9c5115abadad7e79cc844c4891df22a869e47febdab14da164c7715c077ce0d312b79887f8dd7a6606557409c654bba0929a98815bacdf90df9c42a202d10bd228f4634f8a5ada3e9c147cdcb65c509594db62959b5c891aa4f363b40f58d6b8c547a85b527bff20d067a12eb2571f7dd98e857e0861f62fdfee5540020d590a06d9397c973a289e3d9a7cb95bb3f807db306158c931f2c30872471d0c33c49e15b70bfcd3c238bf2594e222a33676c0259ac6637668704546e142ae0961cde5a4ee3a56c584bf8c86f232aacf5b6758d2f15c36b7ac7c9f05e8f7bd04e4913b31ab651e05efeb7052dd8277765ff5c23bde4ca362f603a2463a6417053bb56338e1ee29bba920fcb86526a3fb849f57b5622ba1bfd8223f21f947d80198c0dc70e966a36d60c97c3081e84a495fa9c184515162d7fb0379293b192c0a2e9ac7ab23089ade0e4daebf4eca54c658ac16e79f0562f206e1bc8f927b190c79f87d86dbca24d116c086fd3eb0a2247aaba0ba1d3982bf92ec30841fb12a0706c1c22266bc4a9ec7aa5bdaa65d3c78d0ef04d4e7d31bf4f0df889a57bb18002b3e7004e9f7f67d39a89b72f44141bfb7beb00018536c5c06b6e2ebac45d50a3ef547cac7806d02ef06a328fe818ee70a906d4c0a462267406eb280c8b1be0bc734ced8874e46c5eaedcb4eda3f5065fe668e58bfdec19dc44099739303f708bb311e72e172c8500c093e336afcca4228e12d14e7e669b578fb9e03898abf0599a079a0cf3c8bf5bcfde3feed2744edf02918c1712c6b39961a27162311350cff9289e670d576c142498b8f9b3bade0c250d6511fdcf2ac65398845bcd308043315ffc67ae233a28178f1de692281cb749c8867de7ba9115c04ac1e67709e0e137eb48d3b09ae04b0e8692c344ba6e8b6ae3306a1918d778845d3264d6e660c10442576b87edd5e1ed80115a39d5c66510b4287af5bfc2b329239e8a0ffeb0a518977958b11b0376329e59ce00fe2689bc4d2b9b67b98e0ead436ebcb94fb065db636235c8b94a11a249c14c4f26c4d137af658cbc19ab0ca250961fa3d1d05b87bf1047bee2a882a3c8b14c8ba50f32742081a1c135b3c19ebdb5a445b730ac123613196b99b058962108e5ed86356c103bfc4de82f16c18580b7d9a27bb00ac153402cd742a1259a8db7e88bdc367119c81b204187204944c2e42601637019c9c50fd7ec020d1451809b687f3f068db50b4e8a39475f8662c6c76c86ba607ca94b40b3e1079fd3f321f4cac7ae196d0301327c7dbe6dae5dad63d4d16390b5a66ede93167fb71b1bff91d17d19baed6a5df2694375856c99eb1e7a7b0d1022cc27072ef7179bc10ab3ec2db193de33447f3ad92263db9bf0a5582ee2bc50aa947768c343d11eeadd55a5b258dd1b8209d2a40441e61a82dc80be68958af008059a3aee9c2313983975c472bf015831f0d3a9a6c0b8e75e6b9002421bf9c0d7d4a3ad73c95fc6ef174066adf6da2dc78edb5646e5fa4f4b54ff330014e7401947ec253ac9c2965ea0114ec9970a8678e137a31ecc79d230820f7d66a926c06bcde6d63da5fbb76ea477d86c5f9442b6fad3bc6c04be7552845618b709a350a1005be0514567e4b48d8cc1937f32f962fa8450541b1a6b97cf7a8197bb604077a0fc5e75da43f626d866fc72bc3c045b0e728eae2b5cd7c25c6171504e070081b591420d8251683d91b69ef95eeb24efcd2ea4888eca0dcd1e1606c35575504776e54e00e3682c416a25bb0e650889e75c395b5d3745fd76b003cceb78b100574f900ba6b907313b8e1a3e3911ee034323efe369cb42fb4f10dc9ddefd3e70dc2d7675edec4a31783422069eda787f42735733bd5e885bf5cc91598385b2f0cda66e63e0ba6b0b079e0f9eef7b281df74514de287853e3183b8926b8ab0050a4d1eda80b80bf7a8663eef022cdef9b49b5359cbbbba4bec5a8e755fb7a8e304d2ea4b9285fb762e8de825ef8989b6c79d80f9ccf627992d3bebe30911abed07562c3ed0df19d8078196705dc2e530d6168872697fe9ec82318f494d81b7dd00e89510f37fb753e6e919836f12619ac5f42922292bf68d04d0f669fc74570605ef1952e3c7d7cb4b5f230af4e4098e42c3fd1d0cbbff9c3d66aed4d385601f04912a00071e446191f8a576dc54b4a1843634de988cb5518c64e2c484eac5b409214f3aec60478be5655297390fe4ce4c569822c0d349cfb818148a5d3ad0930808f40d8faddb86bbee303eeecd980d70a6d326bfdaca3234f24cd1d5e94ea80ad49888b14ec6768dc5f1f2666dc1d0da9da22099bc33b2b64c5d757292399d057ef6cab0e919bcc72806b6be6c2de83f4a83f52f5bf390e69bc7c279c53ca20ba002ae8b978751d01388b2454a1027730b62e0f50b1052edecb9d4bfef2ea6075a93d40b3b241d26d26221e4c6ac078d3faa5e20267c5b90735fa2bc6a036200561bd27e254bc28a15e05ab65686e2ba2c87141f90606ed2085e8794e59a730eab983538ddec3eca8182d44d93212aa0385b7212a48d34199b9657a39cb6f9030e476432d2acd77834b896fa2667a0517e2cbb90804d3da16647255738e06c000c44f606d9cde9c614f02c8b39bd3de77239fbf71fd26abbf65aa459a20c340ac807fa8efbc36c879611fc9448c7b288be230156478b6a5fe9612297932dfb006d2258b39e6347e7a560d29c9aed2a9cab6ed1c4c02730f411be183e8746cc08badde9636618d17541656c2d3b29adb73be7a1d946372a385605581f7089930dd44d04a4b4630320d67b8300ad2abf82a09c49ce1dde83f5021a5bef2ef069079d019caf190f32e9b9ba45abd4819bfc0a2a088fa11f77bb34a051a041bb4004d082cd3a4a1ae2669eed564c0a5e1d1421617ee62ba61e97cea0f24f19572e021bd3283d07627d59673b929bf5a706bcdb54901d238c8a8871fb5deb842de60218d891f5250e89d63c78932d72c9996f017b528cb0a0659d95df403e12b88a0d11f2b408054408c6089f2618cfbec6358e8b50e321d41651993841cf11994407f09608a97ebeb79a1a02c4e92b8313c24e70a0e9ba5ccbedf26bd18d9d8152091e905ce9baba0dfd43c13d28bcac56cb659dcd5f853d465b9e065bd6d9f2420bbe12fc595918933a8cc6f0f02a13777c777ecb8732f8977abd928f4688764b0f4490153fda77c4802e00bc720b85ab986936bedac95e3ae1bc5c72fb83d8ee02b18b774c56d1b5e8a0137d153bdf16e39f239c31141a79962c079a664a47650e2a5a48e23e2a20a82f958714ba4b6ebefa43edf8284a66b7e9d950f9a38d5d0bed183ba5f6b3f328bc50c8a995ce513cf922a8ea65b9d62109cc35955f82de03bc498deaa2f0f013b64841c317dae3f2797eb0b5033f7c591de9c001fde03a055946124caab7773263d9d499b71d924e3cccfb713865fc12f88d7bbcc1d1a50bd01b25055b53a67fe44d11ab7809ca6c9841026b05e282c9ffb28c02335a6c0b33267fdb96528a4313a7a19a54ab6af0de42950b908236367b30180cbccb830f8445a270ba8696f91c51b3f99ab2b37a48c36bacc8b60e168ef7a348ede5ba0c6a7b0c86d53de5d3af4919d40e7fdc9a7214bbdd97abbe4eb5eccad9d758fa0c5fec0f076dcd067a1d699e7d5f71581ef1cfc9b810ec1ecee98a3542e8c949088419f3c95b2c73252d7ed2fbd13aaa3adbb10a6ed9f9e9fecee741f3ebb3890d8cbf83eb83b5351bbfa4787793e75c11d51b80ef8afb608d4857b1d6faebe4080fb1b8d69b094203f78cc2312aacee53986cdf23c96d3181ca6b108c10dfde062ae92258e0929d0ee3038ab0fbb70b0df02f78fe203249b86a4e483a54929f07a1088a5d4a400efd984742efa00cda5d0a5e396076e1d0a4c7a906fdfbaf820623f29772932b9f26c63e3e78aae4fa79cf4b569f4ece90658c82eb9aa0659b0f839c86032aaf72ee5e834277308162f19985729af0fc21f96a3ecfc91a1dd10dfa511155eca952b071550c0e067d15d75a19775ac744ebb4ce7e913532ffde020d37bd305c5f0a63cc7ad2f5bb714a3f73fb6c18946e49272abdd3513babfe03c9fad33965b53dcb506dfc7dbf325c308cd83e360b3361cb156998dc79900a02fa852db74398d27038e6a805a7942dea87c529bf7c97857b61c81d02b638480b897d8b8ee5d6b06e1e0aaa3375f28b9b11998f9644f973345d6f0931d26c410e8b2d06ccb2d7be1f80ff41a1aeef00255c9511b731a86e845eb05164d3046802636d2d7f59c2b909328d574e8f84238db71010d421ea03d79b353f0c5ad32a069b271d4ae78beb72e3afdf4403f376c197fb3814a18c135e22e4cb7032166d0c6034d6aa3b26049375eac910719e377d9c73cb91fa0dc72fb3c2936daa74260e1d81b82ab1bf9261be6ee42f1039fa785071cb474b540771953048feabfc700782f355e06a5e57fa4cf64679b53cf3f917c58c0d3e7c9b7dfd23624baf9784027b53b77f3183510393ab91b8820eea9523dba15c9e6ced65e586c878ee379a0d7f1b58ea05e54a386f40f3621430d0d39454e120f7fd426e32a69a94c5e77f0e2dc1a019eaead12bd794e4eba898d203bb264c3e8af1b5ceee4872eab16e7a0c7d4f1ae1c1a1e97ab4d2b2e2b9f9862810fffc6c406baa895372c7bf252c1e09bac4f20651131dc487fd60489dab1aecb3a1a1fc628e5777aebc4d33ae6f70068c27f5e80c3c0cdac9f9a3d7d5dd423a23dae655222b37e00aecc00d39e40f06db09f83590612bc8a0c23ace281018fcb84125229d05849ce22fa24266852108109ebde425b24807c09a4be7889f9f6bfd151a82ccad7fcc71a73fa6f7b22b0fb2ae4d7930ab842ce89c6286f72ca3edb2e5517f8a2b10740df2aa4ff500510afc4e7b75c1f6211896b68aaf84f83f371b04b440bc0030c4df498b2ea56193035800bb9d69c677ac42400fac66b716b40672337786cd61ffef2f854a1b2e6a030688ff39c18ea36e684034fcd31037eb9d7ce15f23e9b750a6dcf7bdcf6158061a5ae95770ee24b4631f5856b019db3ced63ecbd912ac4f4418c3275631b9a0fada3885ffbc3e77d411831ed026fb4acda588f776ea5425930c5a347e8906804ed18dc5967f9c02ec6211df275518215909b3500327c298a34e3278b94ea5d0c92d47f8a911ff48af2bc8840803bf86f8723f496f59595adbdea5517fca80308581e5283f0fbd1bbe2b781e7921fc8fb528ad5907ba7d4c47cdbd4c67dddb90c29cc743d57a5f6ccf5386026b46670ee547e8a5a572706050aaee31cd7307f0426af789bc4583bb52a30be1983bbcaf0477a9ff96d4bc4bd6574a2ed4dd17c0da471b0ad1a2fba6c4ed923ddae0e548aafa53228e298b6186008c0ea61dc850e29894f98dc0c244d7535873b4303d9cbda241380f2079b056f914447a946e405d0bb72d1286dccbfebc5231cfe4c60f86cf20aeed368d1b589d4758c5743990e100f0f00b23da52a24917fecaae9780ebf8968df5d2394e74763da1a4892ee033c9c73be5e52a9d77f12ec675216c33b58f29289978ba8d8c0074c26f11a1e0844f2eda5a7ee8d3913d3a22dfafe5d150791d3cfc8f5f5b8592a1c644bbfce012382d59f1f5cebd915c9e04e1304e2f083e45d42c5b67f00fb40d99bcdb41109e698966696873e672b60425d5cac9d8a8e5d77ae5476950afe5c635dc08c2905049761c0596aa2c5f320555e77bb411c835373aed3a8d64f988ce5d216e8c50e02111a005a1a7776bf2a76a11c9e47c1969cc670646745e7bad5cfed1d42430c -generate_ring_signature 590a993f96a147077c4f5cc32f91a7c802e654a5c8586e9598d0b6e4fde6f48c cb9194bc59756cdca58afcda4960aefc51304bc4f6ed04c6c2440488f42b6a40 2 87fde03c5506336f088a68e7bdbaca0f4f0e8a9bc143808305a7047194242664 8b7ef8a586c5feec0dbb2e72d8036764ff5da197557bf179192e31aad1d5beff ec722447735f098024e362a928af39663703309bdb68b3a5e7e42ef7601c720d 0 6cdb051db188493325b1e132abdd978ddee23a79fcf20b0464c21664888e31035fde14ea9c26dd22745afaf7cdd50fea33056e5f68bf7e16167bdfa2f3635009306bbedb2716fb5503048ec1f3182b65f1919a42dad2a46d7de705998b0d8c00b4dcc465764a0782f41c636643bf767bf325039517be584d7a65f12553844705 -generate_ring_signature 0f36247a48d15d7ef13a065c7b1a1ee40149510d7297677108020d7b2a36375f b0226919b26683f35354c80532460ae47ac0c70b2f18a7155f9582904058976a 1 24c4f1e4a4d51bab40ff04be8bed03b4337518300c1a0073bd59011b3a0fdbc2 3dba1bb1ca997825b955163be13e92cb7f823c13db9de96570a1b539c4c1f607 0 fbe547a84c9ee1b2f58e589ca65a0a454ee43bdc8c886a377daa9d2aa19f7c0a569df96c7da5b83c53bcf8c7d839700fc3fad6f162d59267a4a6d7415d911909 -generate_ring_signature a1831c2903f8c324b1693adecbe806b81454c15fef50af931c62204b3e135bc1 261a8904b68f5185ce1657f266f83cbbb7cda81229e313d568a15cc55cc86521 40 9f6fcf297cc2dee2ae973a51eeaa6e940388bbb75065504f449cca9b25267d00 98e264b0c531599a8a579074b2d927f85e0c8b62c437f6372267a275c4e10169 42549d197b01ea3544e172e32b102414187e707f3bcabb6b175a48e280ffbdad 5cbc67dad405316a18ff8863ff2bc32fbe25e08f8c291e790733e39e83c42947 dfab77a0540c2ae33cc85efc014987cdc19cc435463a61152c70336fbaae0715 3cfd622fd739f3eb972eaac07aebf78208c6558bfad030afe4b6b7af38ac5581 2625cf12b9544cbbb8cfb6c43d176cc0722487328d7ea20a7ea435c7beeaa4d7 aaf3c52ed69792553ce48eb77242d350a8cd10ca9cfef151c4634a284338c15c abfb16ed19fe8aba99218c2734a87c62966e7450f66592a47199615d8f08073f bddb2d703ab7e9b711ae268e900ce8ffc7ea314ba16f69a839c8784a22dc1cde a4a71e5b7225ca67a6ca194f5f650cee3ab4aad608f27e05c2a72d5ab1417399 397f57af3d7105156e93c47c7e75205ce4b199d3d668e701414f62bed9f30a35 aa89fc94e7ab1e9c47e2be820e4b852e2841333375c7181534c1d9f6338b2b22 12574a1031709e503b7b55dca440095b5ae32e7e49960df3f13af0e3545856da 2cd8ad3c4c1479a755671fc233c1ca15da6d1319d58ee7fb46634cf5e6d2c2b3 f72d700961cde8dd195b2bd34b8b33c27cd38ead4ff52cd65f32597d9f845c25 dc50f2aeb860353b9c32c9163d2f371cc9b1966ea4099b783db95615d1b347db 02f9a85d776b326a14e3c116f3e34706f831e81ccfdc4323500d28e525c22fde e46577f6631c36676b6cc24d154902c03d8cdc427b8eaa9a16bdf1600dbacc5c f61fb173a89280c2c853240f345f1f4acba37c73fab295c6153d5b0c84ff5f29 78d202b46b95461b1f0850005668ddc15e38757853e48bbe6f531deeffb3c5b7 b4fbd260b5c4d963f1f1467eaeebdf072c22141d53d5b87d4b8b98a162977021 496e1bc0694a985482d5e4deb35a8f5b048d3f6af8d0d12a8c7e8d1425c16cec 5ac968233f0006c4849db8c0134ff928fc34212a6955d2fbe6c4741f29ddd1a1 4d29eb966788a97031479b226bbc1fa8b8124ecda89c039add1f48095bbbc2ef 3c721246302983cfc7fc5505fe05ba883e54bb4b50e87eebe01a44322e356cba 634e670cd777a9df99da4be3ab467801b4d87a42d93e057fa798e08fb239c91e 7f972510a0eefdc9ceb8ad6bc4051d8743642c8899ad90f81882a972042aa120 431c662db985b69fdb1492a243237c0b6575a137065ffd665be0df48773453cd f0c20daf7e7d96d1c1282bfc919af7cee54795c544bac82adc854040ce5bb142 b7429f8a8bda10eb7e6993550f7e967b69a4ae04bcf1be65bdb252f0bde3f097 ed293f21c6a1269a56ca8335e5c492d520fbde3f70b877f22a6a780eb1109bea 0a6b31f4ca18c8cd4e1b6860664e445c32a314b3cfab312f7485b35701b8d033 ede2afc010140fb9b7e89924c1a3696d1883d3255da5aecb64f64ba3d471a90e 1dba5ccec546590f8a9ea6e91170f0d0c505ddfc6793b150feaf64637ab6dc2e 9398df9e62ad755ce37bf7d03b555316e7a3a54714031fc3630e997e8ca226c5 39cd3807d39ae3de4b43789511593e57e3ca4f44d3ab87de4dc50fe8c79fbf79 678358781b39ff78d276740e2c8c2cc482c5bad694edaa12b194bbe9dba7f78d f965175ebd6af2efde584f6bec3180fe5da01682603e7b9a54a610da393fda68 793abfdb3fffc1c2669b18d68e3239c0662766c5745a0f715fe9af5530fa6d2e 07a99a07a14dcffe0a3dbd5e14332410dbb5a035cce4a0171ed6540eb09b1505 2 5b8f2db32b8f2739071b6c4839e41001423ddf62c2cdec572de0e94865058c06c8b7a4e79c37c20e21a880642c9164aa532b95ece108f018a39ded89e48ab500b832b4ad82163649b2bda47002ac8054e36831a8da997ea155860697ed2c2f02e91d69f842ffeed056a28be2156a542d458d59edb1346b95ed1d78e7c04d7a017a1715710122ad02921df682089c2b7e9b61b3cebf68d5312585ea7cc758dd0a38c80238489d00dd2d200a7d789014d9424cc53c671560f89d499dcf37aa0d08ea9ae5b3dabceb342afd551006a735a2dd1ca5e4cbb34918c52f20a5629dae05b3af34d91d73878dc794e19927e7ad88c70e3512d6e6874f4620acbd150ca70c3f8581df9f682aa7b4ae93db7a6b2a194a7ebde275e04c13702c26df94ee7308fc006408eebf1c39968a0cd7dc6df99933b0ca7724e9dfc7130cfb26f758120e9cd51382c2a509927845f7807fd06b5d5b0f6c2baefcd032971ecf225a4be00a55d4cda55ee6ef81e77cbb78c4246b30b794351980f591e71fe98f8355b08902a9c93fece9febe0488b9d1d0ad3b46c32e1b11d02bb83a45f56f1fb8b1089a0f8558c1e58ab09760751a63a9f1a34eb1265edeca6516bd35983f8deaa3c14309300a1b6d671a73261fc260963e438cd174b3b10883097c371a6c5b534a6c890f0107111e98069aed13e5dcd8ff3e8033a22b20a58356eaa173e3b4c5629b54048faa8c4564ebdec1a86a22e8efec9a7aaccbdf30b5ceb73dc19a913e4157aa07be61fb36087ca3d5b3c4338254ae693b9be72125579e4be6887a675deb034e0fa0f93342171f10a6b301d12591347138a4452f08310d511d77b2c86db8d3b50ba8bc1022f59b3f0debb920dcfa6ad32829f1874e9440aa3eab0f49bdb7a1260b645e56fc93792ce94a830a2f2455161fffc7434bf6415a30311e1aeb2f908108f3886d6dd8fee7f359b241cefab4276258ef836503d7077e7de9595b474c500b1703ec7dd1bac6b0aebb57a5b7fa75270706d21b955685b4c50e36a2da0f290263b76de4df0c17114a3e909b8e4fbf2a37cb0560ff3a76ca8df82972582e790f1d67a5f7399d4cbe094d2dc252de3163fee75bd9ab17a838d6992bc3ca0e9405f81050902f13feb35d50de7d1e3ea9ff282b78df49a32c70410849465a91d00c2b86fde9714474081f9a37327faf111240ff7ff81dc5bdcd3d800348325e0d0d281385d2a07936cc43f3ee625e977005f82ab07cb404156902dc8de21f5871052210f5a15bdb2b8f6224d7cc88980631bec59f756427a180242becabe1dff400b838df84724e49938facd892481f18384aff124d065f15a4a16ef3eac27b630e3a76cf606855bbd0e2eb097ac4360bd004ec2feb7ef9e12cb7047ceaee19a70106fad75757b02894f017dfb2328fdc72fc2c64a1feee065cb781f4aa5a549208c1081f6a903abb309db7dde9a1fb4be5db81b80e93885499cfcf20e263813800ea2c9efdda98b3323a6eee42676b4b7577f4eef37cc8b06fbd7c855472f2e305b5fb29e247ceca85b4198e563310093713f6101bb1b2f03b49181f8d857a350fd197d6f216250b3775ba694794d122a6277f0e1b91cb28d853e9af4edb7f6e0950c6d97a4d8646baf4667c78827caf90e9f948a131e051b95dc31a1479eba70b3e9664e415344fdf746e8fc115261777209f8208a0892167e6e47383776c110aa66e892ba130e61b3744e719cf4b503f81920537169b8a9cb9797516d80bec0ab00c7813e985a970815ced3cf3d154426870a2e1f9f1a1c5151f25f54474080c81ce850ebb25accc0a9d456f5cc5577469b8653a1ab5f2625d906f1ff88a410332c99e06696f5037068f8db6c96efd4d8d54df5b1096b06ec2f85ba1b1101500391ef6956d235c8b5c37aba56f7446f67bce0a370492ecf0883c9949cac27c021230ec9bb86491716fb65fa7aea9c6e2deecdc85d9074b7c875839f359288f037a9e339186e2e690298ad57c95662e2e2899e7f33ec32f06b74ea2c3fda22801f773f2ce3070338ace22c3feffa8cdb198c844fdf4e2bdc7ccb546f0405e6f0308f7ccc5facc037727078d9645a6c8193cde45dfadc2ebfe661b030d76bbf905a2c1ace08199c5dbc5ca671f9b7026b0f6804f4aa77c87efa62fe61eafb49a0ae78e136cd1b24d73c7e94d872134165f6cea6582fe278d425bd2df9050b8c802c2e713cc06358da730fdbba92dcbdfaa0f72154cfe48979f5d5e1afd3b64d7042ef74e7f63fe2b2b25a039e1351caaa91512d827c763f7445a8610b900a5890e70bfb237d7b5341090da9a954cf9010e26031bb8248327173b15b82cf87bb708e446461c1e7d1198f02dc08ee0408c7dbe648eded6846960745d619c0b2264091ba71ca5760deffa13cf5b07cd93960a07ffad6f0dac9c6595c92115f2740b0a6d177f8747b61e33ddcf107edb858be6e143c2a72d987a3d75a2e37ed750b2046a054dd740c021aa622816b2546e565f05f78fdd7b295db143a81a038403ac08158cb03c7f741e32235316141a659e06a0f7da5ce18f6055e9f2fcd109735b09b3fdfbfffc6c634c7d76bd0be666466cba7b35113e561c0cc445ebc016c37901062ae0e1a5db644250e32b5817e4cbfb9cce8e5995af01905a95b23808b9da088f22ed2488cf7f64779ed7dfc1bc2f4fcca4bba8934bd9f17be1d26898f54803be0317bda7e600adeb9b4a2971c828b379243676a23947fca75580c3c8667400e922a8ff1356832ab1563287495bfe1242a4b2f5de56f02b9e2af1173e59570bcf4a2677469a88b8de816253633f344ba7239a8a628754821998322fb01ae30e2957a883295145ad4b7e3651cc008e6473d00f0af5ecbea249db9e7b10622505dad2eeaedd3481852521cfb0d61dad9ef797697f918e8744d2ecf37948a2a003e18b4fb6d0dd1e5c6c45b058178ef75d4a6467ea2013bdf7d5a903366f382906482bef4bc476b834ed11a854307d3a09d0d06937d07f47a11fb38a5120f6c00ea507eb0593162071fc570e1210769acdf2d19e4e7864c188286de498336c4503600beecbb9669fc81176c471900c0508c63980690f623035b380b942db27bf0da5e1c34d5a2386b9f585191ff59d95d5f2ab94ab453e71a94d79074eb9bfa00c448c4fd19738c9b4eaea1e1cca372b10fe7de4bb7ab6d9c14bf58f1ac47a3509f7968fdc46d86ee9d49bc132e9c7c6d09330209cb2751b9e9838e0451d581a0b4bcb4dd8d264e5cb021f604155df24f375f693e406e88f4e9e3fa935eebcac0cd5c2a37cc33c741bb494676c710484f00d5513828da123360e1d4b6427294900f746e74e783a85650b27957a0f1fa6ec828e13b5b702eea4372655ed569b0d0f0282f2d11eafb5783b01a0be4b591a1ad7c24b62274502ab446d896fb59ac60ba5c2101e9d0cf5854cf942a41cce01e2863a492b750c773d6a71e589201eb80d2e0141c0e5eda8f65c5a56b2c3c44fe2eeee59cdd8a2440c69a1f9340f98fb09c3b380fd7acb101c204a652d001d7329d154eb37ec91cc481b94db779f21eb047a74c1e49016f06b0d3bd5a622c8e097dda9ddab02f6da4c650c499f8d1c820f -generate_ring_signature b9ab0b10afa5860d279a36ca738754958805e5bd3290604096442b8a4dcf9730 425b3eda70237941990ea68b9889230fb9badbbccf08a74b7c4a59ce552adb78 1 a15898bb31142d00cea651b265aa4ee7e73189b383c616eb0f6e37ed23ef7eff 84c6db89df73d478f2725b0ce36218d81fa68d1cd5ceaa8a1f8f2f10892c3005 0 fd75f1cfbca2b0c17988fb391db4fcace441e58ec3610c04fbbf4e3ad7c2370d43398ba08055cfe30bb7210ae3d1e26d580013ce15e9a7446b2c7c1815e25700 -generate_ring_signature 77f35661d7757d7d03c765f11350f4df7bd28708a37163e7520bd8c8fc622503 2b129b323db1ce4fdb915ebf2ddd4be3ac0798b4f9fc3e7188846d9993764fd8 10 ab241334d6e35fd6340511d9c72d5a18159c125336c76cc06eeda30ab23ca126 80832676389cb95756b34c8df992e88936b79d89114dfcc8da1e6eccf6320239 c5316c4465366ab16e1922a835d9a8b2f2ac89aa43e2f6c254c703b7cdc88519 74ea52737c3db895c2b38faaa7d1b47496998d4defde5cc72d070a15d622908d b1d7742def18ea0edf1a0bb3931b3777d85902d969b9a2a4ac30d997773de9b5 8f6ed97932d63ac5c74dcd60385536f4d3905e5697e6c27ee1fbe15edb0bf7e8 be4a83371f1d524c26abdfa898e92049d4f3471acbd5fe9b03cdce08d7fb3f4d 3d1d9750e65c8d279fde02c4c08a86c781880d3747b0d1a9ee063bd978c0921a e9d2250439b623b02e4915ba6f3eceb0a74bb7af6bd8ca70ba49e477f69f5cbe 09aef8291d5f369067a350126fb37112cd0550cf6534ce110100066ba0a8a7e6 7d6228970998328079db9ffb11b5340bd972a39cb5fd090f400fc2f4d9261008 4 2c3d6a3451c7ce0426a5704f312990c040758d0ff1309ae349208d4e412cba047145b28c3fc4a1219031df5b4f265215c2bea50861760319b34c0f3b73c78b0c89826b18249320d04cdad4fff35841220e9c5c26ec03ce569e9cc796bec87d01dc2abb4de17cb29d7f1c09a6796949e8a752a660b3c723bf709afabc9df91e04babf5af074d528775d583e0b247943be9c582251c902e973fa7297b4de0ce002a0f7561f9de2ac6941281dbb0be67b4dde21383b79588c6994f0912e1ada5c0571bef6138c8db1fa6741de3dacff01d93093e3acb8f2fd218104c5fd461b750d80bfa0fc47d230bb2e0dc16de4a585d64e8210dde3bfbf4c57748f9bac2e2609e97a20deacf6cc3b96add1478622cf5b57bbee9f718f856eb645a2909437f7022e8f2f09f3b3245e574decd65e55ea716dbfd69c10baff663ef9d1d8b9dbd70aef65990acc1a94470a719b3db9f37eb8bbfb87a0cec86bc827c16c606abad10a813caf397627ffa3d70ec8729e7b8f194c8e79cb63e72a628204a7dd96db0b0fbe815ca9dfd827e343c845b6aadbc2e99a7567bb22f3c408b8fe33722dba3209b04a80d481492ca510e76afa5b83f5d826abb5b16ed1e286e5d3d9dacb6b250d7ec4ab7b65ff6d7a84635b325c7e2b5bd5d579186395746b289abe3e5d933d0bcc87ef949cdacfda5be3b111ecaf02725c1c901f807bbba49257b4b8d1e35800f34241a9f56106971af83837b87c6f95dfcf7cd2e55ba0d644d41d614a0d5f0647246a1617529e4af6adc449c7d3fd0b599d23fd0a84ff680090a51eb821ad0c61b2cddef7e79ec969b4c4802e709b4bde35d392d3557cbf6e6de2502156b90f627082ece6744258443f92e5a055577754bea0b6a0c0b44bf2c4d7464882f80a -generate_ring_signature fe0e906842bbf5445baa4ecabe98dd6ef27226ecc2b5ad9834e08c046d0f578a 0e4320a4732e89ca8a53cea98b44492a77168316f9e8ce95fbdb5197e9d14d62 30 b7258c82c9b3e0adfadc33a81ca09cd307e70ba065c16144f46f552414a9a629 54d94e93bfa71f1ea7c1d64902bd8df7602d7687e43b983ec3ff6ab88b4765f4 637d164f669b1111c41a5533ec52a4b05a515ee5f46f74ab8e50cc481157edc7 66fe4748dc0ea965eee04b152c0dcbe2a5fea11333951d568491103296730f02 acb9c2c966da9415c9b09bdce3492e7962d10ac1c2a5e46938a6651e09fb5516 c2d7dfd2f498249427aa0eea3b192f4802a3d212f7fda58c6961e231ec0ddad8 c830fcb8aa75343dd3722955964dcdb9864c7922b872c1a209f477e923944379 bb23e3cba803bb4750739171050a55f31d479ec0ba27f4c0fd5e8a207257fd29 a6afa3958567c006ac5a61fe4d40b5e34aa0f796aea13c2ed3866a1f12fb3e0a ad6765229bf2c6c88971c254e49acbe6cfe0310049673e1cdf346cf09da3f56d 0edae6331033f401c42e320be461975a86552f196f495b3a4e3b0f547617e963 a920e55b3c7f3a4a8653d75ed1cc731e31ac880e175959f6e267fcfcecd22955 b4d509383bdcfd434c407c5070f125c46a46733da20a3f0fe9979df94c31d5bc 25daaf9f93a6284f702e02395babcc7598031c6940e7914a93a8e9ec722e7fc1 2f1c7e264b1262b445f4178156119b3fecc1f458f7044cc4de63304e14c97587 a487d33950e0d251e92691a34a583e13aee472b4c841843ba5fec5b3c7656ccd 48971038b01b0fbb7ed269349420385f1231bca51ce21913572ddb33162c9619 f222a85417740af8ea34ac66322a4f494ca309d7722ffca6713400e4be4fef81 696f40d88004d1a539495a61f35483afbde4fb225483f1bbf7c2f82c7e59dfde 9a3b1cf51901567f6e504c0c8b08a503b8cd633d6f542c9020cc4d238e6c00f5 3fc2d5cd18e5788a96f016cbff76554765afc0428cb260219b81dcead3edc978 ab62d587fb8948401a9a3cf874a024457791d3f2532803e39e00b7e522cac759 3dedef9bd6efc320fa1bc5dbf0b0313244efaec9a7fedc18667bed47a1e97af7 b0342dc39ce8e3f1b5053747f6fd3a450319d7568779dbad042e76b31dc816f3 8b3365279c15fbb8c7d2758fd0de17503c48d87aa9802593c22ad59a27d845d4 4566ca51354a7da4bcaf7f457bf803c6e32ee109a939a69c342ad61534831c44 da8e0ff478e7c6b7fe83467d5a5cf90fc769db0d8230eeab2e79424c262229a3 2cea0bf3ddc9e0ad18757bd6efc37a6e5923dbbb76d22a06463f25177223f3cd ebdecc636abbbd1fa2b166bbfd742ade21ad6a22dfc49fd667cc807b8f51db2e 5293d8afca91f70430a90bb0d05bcc4e6062b20578ff2cae721c767b6f929fd8 33c6805f3997d25bc420affd33636816459bc9b8cbc2f2c65fe2ebca22879b0d 8 9eb3443b52a8d541fc0dd9b4f1d0807b9bc5e9cf6c79672f3a53960fd84ca10445788f3acaa4df522b14b7bbab50e7b0581e1c297bcd0f7f06d43712be225c0fa86af386e1117928a5df4e73746cebc724db20ba3a1a835fd96419ecb851b100645980ab312a193b5c480a684edc9febf18000bc7306b02f0a2671db4bfdb400aefa3d9e221e000cc0c121daf7977005286baedf84fe482faa6276f9816e1300ed0c574792c6539bbb812e0e9dd9414ec9fe7e752b1ed20f4e8e886e29514406ef65cb982a9e2bd4227779549121d5c1863bea2eb2877e656199315cefbe6305c2689dec309efa27d6bbdb5b9bde168e1b747b7606215bdcfba9950f31a6850ad45d4b623b30b09a350cb710adb7b7df91fd7ef369c0f5ff8103d1d645e9c60c2920bf74cfc36d58fafe73077cbfa74c2fa20361a8b24b44835f0f6d2426e90beee9356d310392f802c1a34ab52ccfb3995504546eb3a9d8b6c5b8f977f3180800b001e292a25cf9de46b3462dab637e9a296d16d034d5ed8d6b5d039ea2670c071982eafd2ae5e692b0b1a66ecf016193e2a7b5b7ef114cf2524a4623251c06acf4780972215c5c375a2a2e4bbe637f9ce7858a6fe084451389be7e4c6f58081ba550c3287f36974dccb9433379067e7626b7ffe231f2469f299dc645185404dd04adb1228d303c459ab917d1237d0838d2171b7b26161b8d7188ff18d8bb0bd82441ee7ccb2cd324320c7d72e0e5aeb3c32aeb807600154300868bf3afda0300b49e37e244040351c6f6d2be8212c1717b05a2606f4aed304f18155fbe7e0faf684f2ef03ec401f9f0029a52dbcfe37bc846eec343eed97ae8862a3d385c0937594af033128137aef41f56d15ce6f35fd0749dec9d8d7fea8693911234e30121b83759262d5e3a12489d405b2775e072d59a47fa5c7d63fdb9731a77438a07298e3093753353ac9223827fca0599a725cad6c8a1f90630fbf50dc480211100240c4706354ccaa03d4d750caa9785276ef60115331dd1818bad57b45e7461015d3e97ea37e852dfd8202f17b5d9b4ebe72c5d3bf75080536407786a042a1c026a4032e5d1b95f849bef992006147750295329c7892cde5c8938992f0835c40164722b07b4f22823d2fca62826430024f05a251e38cd26dd201e9aaecffe2508440ca1d438be15b7d3187d4dc7e8cb8c6798a0086a81d8129d13b8be9087ef0e8ad5db0979ba37249f8bbe11b22a7ab8320550cd7713c94d36c8520dd8758305797ae9cb593219b6fc8ebbaeb3a1f3860d041e79b9f733756f463cd8c8adb10e8d7a1b9ca71fd87c0294d7f69bf2167356e10c5b5c2f490b4ec1d68449a0b80438b1e5d00f74c31d342aead66ac2a17578493674b9507f76a234ba886666ad029355355fb95489b89682e35e9ad288de2beaf33701e7bd078ec8e9e0061fd20b2e730218958e2479f256030c68c1b97b8deb2a3e2d77bccac3cdd07d8fbcef09eb980a87aca6032ebb34dec70846acf258dbc147c0071def9da0aeb3920ce90ea268ecd38514f199b34574f1af45ab62279d70e15a9b2007fec23c4ce336440c965fe7e2728bb8657ecfa8a13751c8bb611c01d11e9023695e87a199e862270b58b536ee8d2f801a9dca33d7f48854fb432cad6923bdf95af59d4d3fb35b24018a181b272c6206044168b0719da3f473d05c2a7fe2c0254cbb3a0ac51990700fb2d2633f7bcd569ae7146c0f1ecc9db593c4c37cd2954357a469967e393d8b0059d0f147a4b628a606d96323f4784e9b1e923478741d06d3cd2a13a709755501e6eeb698a242e14693bf8a7450f7a8774d7aa957f7cbf01660c636141c657d06c19dbe686b547ba6d62dc3c59ae3f5f1d967218aec23fe6b494def21115d5a05bd1301a86442a380152c30bae6d623eb85f0dd33634e231de178738a5eab10024f03f7700efb88122be88b7e23e5bae2d7d9ac36cac0bf308612892c2a09fc066c396ddee1752737b7a820bcd35a681ec7759a3ccc9c0b70f47249fb9bf3640870abfd5345feb1f034cc276f3d3c8b250905f1931bcc0703a66bf6018787520d6894b58beeff41777a509076b68216c09cd6f4a5a8fbe9045500ecf3487f1a003779919555001e5c1749736bb73095a1277ac1acb9859ad4031ead3c7c16b30bfe9e82574e5736a0baacf56cbd6dfd3fcdc2aa3a0d4010baf1d22fe4bfcb4b04dfae9b5e7e49ef88ddd959c23327ded194035f07406a21830f34049db6fcdf0047236fbf76defeca1573450e8bb6f519937d105520b854825a04d150301033009a17f81175d24703c3e5da295be2ef589a46c1adcf3dd0e493af7900241ed805b9f4f8ddb3250abd1c698b769f00624e85c48f95dd5fe0726f19e2c1f0515f08aa59068ffe6eec5f3862536f41e69bd7bd53a5cbf6fd67f5dbbfbeb7e790e3040dc97c7cbc0e3f2d574ddb27628de755d6f7af504f0fb9ce7b2dbb7b6b45cb04ee948cd0faabcea3e2d23a119c4625abaa4231814c25ed15e16d893076e2530a5fc5b2daf9a492dffdc587555068c8efa9c36d64476872e70be513b06638600fef12a4a8682b371ee60ca22b60669e462371d04ef987b4d2092cf44f15126c03775a837f4028bad9749b4ac9eacdd99bd4b7996d953b5dc21ac15e6566665d0e7e90b7de500076c68ec74ca34305f6156e7e34017145320cca59c686eb52cf05 -generate_ring_signature d44366265cc5e6e8a13f3d2f55c79baae89befbc5ac99d063e6e0dec1d5f8665 345925032111e3150664a24dc32937232ef1bb457d164c57c24ac1160fb7d6bf 1 0875f733705d14f8dc398a529ca0bb633914572d8849d084dde057b82a946fa3 f51168e99b11a987b49c956969326d5ab4bdcaa1313fa7ad146b24932208d607 0 c5f770668602662d20226301fca255f0df8c7b89e26ba282ebc79b94364fd0035638e021b0ff2f2f6e92eba40cd775aa6f7958d5d9187180d37c090ca9cc8c0d -generate_ring_signature 9b43013f26543ae86b8194bef3e6999d7a787ac7d9e69375e117de5f6a963a83 ff20e8a898dfc4e8c3ee2864418a757fc9c52a5a6941bab0c745d23846a4a0f6 5 551ababef74f99377fd5d68b2ad3a2bfe14ec6b4afee4c39686508184f87cc8e 25d84441eef268e987eb34f24749b4a13044e341e6399a5cd6b155a87e6ff0b6 c3850ee99faa03c06b6574ec52d2916e32b399aa82286fabf4936b39a916e431 42dd11fe00b24c64342341eeb6643d229ad1673a51f09192b3f9ab4b93256cbc af4d559997026bb67abd8ee6e469dd35577dd529ced3a657726d0c02edc3d5d6 b34b5b99dbb26140e778ba6fb61449721e4c7c8c1bda6e70eddbb6c0672e9e0a 3 4865be89e5c547bb98da5822bcdb92a85c98a2c9aa2eff5bf21f212f8cfeed09c1633b725947aa069c4d0842ed007f9aa8f3fcd3df6a232fd20dbad713f47604fa2b387df7262aa30456394ddd3d4972d7901ba8c54d830f005a87daf3988b00733bedaa0a03868b7cff21b9f7a7b2c5eff79fe08c249f7a119868236874510ea0f2e7e0383c97a7e78f43555d4ed5f1a81191fda0533c0d0215bb225886af097d07312ee870127d57dba00a4bd7e5ec165a53f7c916430e6e4ea1f715a2e3011a46c2d425cafe22688f639e55ae94c591c94056d102a771a57cb855b306fb0af181599841542b2548ab2b14a3ceefdfc123c0d23ff51debfe131e79713cd70c650c7acb0249389c70087564d0340eb8cd8341920ac71ef7101c5d05b76a0d04d6c9e3b7c4a609a6066c408127693181288fe3740758bf4c12c0d7802188a40d -generate_ring_signature 3c53431eba5c16dbdd1fb2f98d6388541b7b85cd5dceac9238d6aa7dd5e8ea8d e9c7b96e13b6225b03c9c774e90d2e3f71b7be553dfbd22cf1767888c4f83b45 16 70b95fdf50d68749f55586737433d11e0506886dfcfe08a82b5b01c173dea87f 9a8bf41dbb914dc402d80b6f1510e0318fb908181d765b578776b034d6359ceb 87a438d3d769aef03c070d3853f17c4e470a4a7ec5e4a118a8f00bb0966490e3 0ff0242f7714946d5b872f9fe6873d237f1f4fe501b88119795f64f744e8428b be4c9bd9231f25e1743419a2858c014ced12708662761fb36083aa29710d1120 94b62bad7ce972fc7ee236c909cf19203dcd46fa48552d86f85a2dd6379e4e6f af00070c55a10d7ea2ddd2953e593fd5cfb29eab6c6b676472d029152120fd95 e839d97bfcee72acce077bbf20856232fc8e31d27fd71da70a6f0600f85dc9a6 f35bd0d64ca12db2c9548255626727e57b4eaf37b42caeb5c4160e5053b54903 7b23cd36d3ef9cb17d8afa4346fa949be91492241c2eec7d02329f4ef37be3cc 7f5580e1ca9c5ad57941951ed0de16dce9a031761dc476b0a3f4733bfa76eb75 6bc5897d154e23c56cb1216534610d1d75241d7462aa11b8a80d6191dfed1354 99884db56a229765f038e573fb018af4e2c4e75e9750908a6dfcab2d4ec7a821 656458506acc81d90dfe82decfbfbb6b5cc2462b6e18ec798b486add559ae372 0d165d983a91a7228b44dd25f84ef8246fca9530a6f7e15924c102d4f4b9c038 83169f90ec014494f2e8dda969dc1dd5fb60f47e3a4386945b787928e56817d4 580db78b04c538d490ba0e0cabd646e357f6bbbf3752f0ea350165b3fae41a0f 15 8c8a00287044c0b083c3137365ab72cd2611abec4b7a7b800cb473250ab92e0da194616bf7f76bf5848b0f64b800bc320cd05a8273cb58c0f06dc1a117f39c032114dfb4ba47c7fae3bc8fe012a9fe0876322330aaf5f60068ad44c4beac2b0d34da67ae15b691339c51bf8fc0ab06eb480de096ba989ec346b98ca5b7cdd101d0371834480b2ab2aa759fbcaba7c21c44983d51998fd76782e4c3bacab6a409a9ad50b32f69987e9cb1e273117d2f1c64f540f93477c346135a7cc8256446073126e28ff988849a5127405768b21128399f0d4bf018e3db08508393a1ed8705378e795153c9fc6e99cdc69f0cad6efa1b932fa7a317e6737e9d63e17b87c1063577dfeef974e82a74cafbfa84f1c67b0b1055ae2fa613659ff34a088990ae035345fe0285439137c03c72e234872875bb31baaa249df56f14ca0bf0b9066a0b1af02147f735bfe562d207ff3b2a88e91f8f11dc5ee6c0fd769f2b736159bb0fe36805a6780ec62a4dfd121fad7a6ef5f4303302f61cd421bc54b58dc986010c550ad6ff49a1a4b818547f5550e1b132ad887f856a60b913aaeb866e22cbc60f31649c227a5597dcb65a7e391fd2996e87c72affe6d5693a3de90ec5f8d64c0167ea55430816f1f85ad67274c235bd428b0f1b3b76185167c4b7b314f39b3c0160b63afaf1d130495e677b1de3865bdcdc06d22dd14612a764ce8dc71cfe8f0ba4026efd5f13da7368d45a8879a4c0f06c2a290ce3eff4fb79465d3a0bce0d0591abeec4615e0005edf47bd6f73ed4935478d8a52974665429f0d464c610270bcd1485a8b67f7141723e9d4605fe047925e8374d6306fc977c41c1473250230b25a480cb1a318be8cec94783d0d9e8c5c1ddebc1ce78b84728fb36488ff2020d1d4d08554d757b7595fa336d0cde8191f50e471d219e08df5c33293cccdd680eb34f81b5da93e1a450f0a3059f238e4643ec59ea19513d733800acd83dcd0302259cda4a13932e4123550795d63770af8a6533568c78d288ac95626d77d4060e0bdee47ae8db7a3d2336b495f9a3611d69659d5ca7e83c3e40dd1286e6cd040388a27da7674891c4ba96d02186c6ff01564c927c691e37e0056d45523ea1db06765f8b6900b11aa51fc24ee8580496a5718ff21ae9f5169575808d917bb0b10a2076f2f5ea019cf7602051e9bba0c0c4fd18a5ac79b1741fd5f823f6de57ab0e5d8356634c1202c3c1f8ca50fa8a7bb64a286a46f8e322c92fa64c93c739080942f261516a1c7d6c97037d1dcb5f7744a6fd68776309e23fcc4a8d354a658d0d67c88778ad32280f0681db5101493cfe2b73b9e12160b73ed918012cd076ab0d16ca85c95fb3cc9bc8a06ed2aecf0740fb17793fb62682dc8d05591a47ff460746ce19bdf90049732e63575b18cea1efb698ceafbdd73d5758973bd271cb0c08 -generate_ring_signature a2848f3b36302284378d0f599c7fc0b7911a94281e33d4eb4d47f7554971f7c4 dbfbd2c763cc046137ae025d4fb22914e8e7182f3cc727d2177e5670ae95aaae 2 184816f5034af3d627d6d835e5c2913953f985f597b11370c779ca34048fbce2 85172db3a5e5418276b0b57bab2962b26cb6bb159f3608bd31d5eb6fd507b799 d598ef43cbb2381ebc6a1585786dc1afd6f3b2fab6ec7c7c020b934bd44f8405 1 e5e814fd7e2aa476364a67c34b32928e97fb3184e1bffa18327a6f3f087de000ba044964f187570aaaae6ecab02dd2155a4b35d9b45afe2d228fa6b69d72e50e83c8578ce076eee06b29cd26dbf14527aa4ab28224e1affc226fb73e1b5a550a4ac4261c5c1a4ef49a071912e67b2aa0566b417073dc3d09fe09bff37d109302 -generate_ring_signature 3bfa708865ea752237a4797383b6ae2d4d3c41482ab53d42ac8feba9f80b62a2 2e4d774207848de566e97eea6262bb6ea87dddf04f5dcf911ce9914e9c97f528 91 38f7acdbe90c284805550b51f1e9929022e7d533bfe75bea0dc33f717a523e4b 817262805accdb4febe4c20a8037f50aa1fa7a00592836fcd3d213fcaf022f45 13c55f83cf89d5272dd1d638e2b3048653167468c11a8bebd335cdd72e7158fc 71d23b3dd7bcc81b2fe24b32e9d3e57d638c21ebd4039a73c15bb2d6455f3b8a 2d30c73750bf6f92c3bb59771cdddc7d0d6e0dee4d4ef60b443224b418b5689a 5c0eea3463693e350aea35b9b75c918ab6782971cd4aa830180fff60f6084ea4 72d4ba8604da472325d32ddee00e21d844275c3896911c26f94038f30a59b305 2d09540ad3704fb6791fe07161f12cf7c634b173b4348dc2fa2b2d91b5716d6e 6cdd2f19ce8037aa1d0a1b933e2c619c65947fc732acd11f115c62d40e77ea41 db94bbbe5548ba971a53006889f253361d986258b9a641737b88d6d1c1a83aba c23eff960fa6ce574cfe1f74248c29b10843be110f8321641c2147baeccdda1a 47b9f3ad5306af76c7045c93b914dd0a90370ff9e3888129421ed8b78d5b6725 b749de5034ccf7c0c1bcc7a76fc3b71a90b395f8ce74189101c8b78dd08f176a 9c5c2afa18b46a710f5c2bc387d61eec6eba8c59a00781486a5504fb35b8e46d ea7a0f8cc1e7896b4de7ad84a8f2223c1f4cc320e466ddf80112b01e9f7383e4 8408d1626f6123a3c60271334ab9ce1568f4361c9e8961a9813b2f82947dd0bd 5ffb6207a836af8db9df4bde8a1fe896f864adb6d4a1699cebdd134250d3627b c719c4908860d4a4204a100951cd6f6a5f523fb1c25af8f4e1a7d91566042583 1588e45a7cd74dbe403112737070ea504804a951b592d86308aadca05e19bf97 2bc329ac65a06e56aa65e146f5ca37b15c707a1a856681f1b6438b876a257a62 6cb6add63061cb03876eee0de9733db3cfd194b529b92638d74ad1e3197ca55e 869f1663036ae025ed0696a551fd6153fd0eab16437e4f5ebb740975530cb4ea 565c6df71b17757170cfd147fc7ef7ef5442d60f420779de08537e4854242034 ee1361f2ed36794b34210f0084ed1e853d79403287ac7e422a9e2acef5d43171 396a2402d29083eb8514421bfb8b841f699d607565131c44aa72680c47ae6cd4 bf3e71778ff37c494d0d588e4c240a7a1fa28dec561e5fc95ce52d0795d30b0f 0b1c1afd2a06b982d99df49358e06aba690af29ddc2f1c6d5003e6b44b670eb9 0967624c84307d50ff5823e51dde55c2a0f4dd3e54c478bebfc74567bd7a1b27 12a0cf3cca9791f9d9188e21f8d5c4c5632ea737e4a548a29c6116009b1f583a c26300d73a72480a4553d325bdacc91f0c3b10b7dd53d490cb3d9a69ceab15da f91ce4b28de23f339c6ffdd175ece69c2718e2a3d9b22a80961f6aebd990f09b a5b04ed97ddd4a071ad49063c159c6e1e5bd53be621c2103efa9944a504c430f dd1ce2e7ad25135322058928f7e0176d77097063eb384130b19e30357b4d1a31 2987d815b4fa2b7214a0eca3d95b3dc8bb79ba433ac66aad97f3e5ecf8a67575 dec31d9c26307ed50d5ad50c5698b88d561b3732303d0ab09f2ceb106b2f0af5 7ca0b73fd6dc919d8380b22294516103ac26831cacfb46e0907223290d5ecab8 aa97e38b8e804aecb8e2c1da77776e3d0582341b2d39be6a45f8c513c99cd5f7 cb32604020edae3f1ac43f49a50364a09e9277ad9481f1632c7e446ff24d376c dc66cd2e4cbdd497703f1bd0953033cfb6550f46412250c4b62a8e44f20ff7e5 d713e361ad8a2b8715bc3a8bd0a64cdf4fe19d6f4bf2c20970572a5aed81c14a 1952d47e81a3e2a02d59f47090da2972b89d8952d498bd95d24256efbcf56fa8 33ffff80dbb6a235d0d6c0cc52dc0dcacb4a692cf09cce398423eb8742080853 1e328b3b594f3748288881bf6df6c2400fbad42e1dc53099f98945d0776357e6 e45396f2fc37f54c9ca3af36970ca0ddf908dbec065b232678d5fdf9cdc115cc 369cf4a82d27c83b295dce181970028fe53d6265380cf87c01819e36d1563ce4 7a68d3887599907fc20337d5f7b7fc4cb4f88dfc6759a0a35bf7a2a077659f20 0e579c35139219430eb86bc0da2d37f269893ffb6d10834a6d04f0a7f283dab4 52101d8a151e0a535bd2f5fe4db6d1826c47e6ccbd8a06d1ea8e05537fbf421d 3cc96ec853bf5d99eb69530adecd6aafbe9a95ba14ad506d33772c9de1cfe1f4 0ebb479ce8e81559493318897f9829cbf14499fb639f99c5a6432900b955befb da8e0e7f63a5f460d64b71a38263100afca62d6ddfeea1ac0db0a657f1296af3 119a595ecfa1514529f07f7a90cd78d4b7a98544fc4ed0141ce1c7fe2a9acee5 d9faf2641c4726c711f0d4136ac280e2972425b5ae7a3c27bf5b1171b378909a e807cdc919a38d3c286abd67ae7f0dd3376ac8e9ac55716b52b5c44fca5cb5c1 59c7d6c794047bcc905097d7fd8569a5e4888aa751065b66de32d8d00890bc79 39a5852394a61ea8ef293b244f4a2e3251939dd6dc383940e4b0e5f49b963c10 7fec3deb4d91e02f59d75bd1e7ac2e92b5f8030d696bf88463288e7a12bd4ede 9b1364077d41d4c6fc13b5e4a77e52c27b2fd1dc7765c1696ebde46a07c4abb0 2f6956d8fa81990810a2ed1f01e04b4484c0fd3a76cd84ddd2a9619e332e1d88 5e135779ff608a35cf5da0e30656090fe76c2cac427604b732fdc826b7265198 8c27f69dc560a8e8a68310264d9e65e7ac88beb237a9abbb7708266844057ce0 efcd93dca818910bceecf477ea4334af40922e56c9f4db357cdfc3321abb0f68 fdba4d25f7845c2858ca4e6c1b077a2b7f0f54bfba930670c255f254c277ac2e 04a7e77ee772a997a8954b709cfe1f660576adccc0bc828042a6bf9978594618 917d17c135e20aea7caea1dd22cc6752e4fd5ce05098d2836a146c793eac61a8 b45cb5ba80a17e6c0646adaf9cbea1f7dc5f3799a826c9f088722a5cd527b82d 29a200178549a18673e0eb92e8bd384dfaa695e130c54dab6cc44e826e7c3112 c8303040ae302f47eb64d676166d16b6e38b8996a88e49a0cf1a679da3dc40de d0dd2eb2093b1bb607c5b53a9df148a7af9ab8eaf50e56a9a19c4366a4b873a2 54107acc6285e280bebd6c5314d9ada8311dce901bc812d700a3e938fa628ee9 5b6748e854d70e02a91b3642e600fd32898279ece0f10729127de0bafc7db0ed ecd46f5a0d0719d60a71739ea93af27400770994db68ebe7fa98f9cbb97f5e86 9a5cdd5c941a30e5840598daf4e0e4dc646775ed5080ddc03bc88e74e57dd7b3 b76f4e14bc66012de09bd3fb98724759e0fb3cfe68b17ee2f236ca35fcbc058a fb0f82776ca7899d5cd705d784cb0a30d9a705fb5817497d66c048709392fd8c 6ced641a3d4c402a7bdf2de0d000f9512d6245cd946971429ce8abbf13ff56a8 fef493c6555d43b0f2303815f086b7de4c13eca9fad0bc7cdb75a118bd433392 3ab468a92ec76d5acd3837aa83b7ca933984be9c167dda2a43e86f5b5a70cd01 155bd8eb9c7efba4b2e45083e6e70539f68b0cc02a23aa1ef40d94424b0cf257 e51320a48a75b74d223cbda29a41403195300d6da467c8d636bc909bba0d36b8 3fffc66702b2144fdf6fcc3be9545f7f5ee034e399e4db1c44f7d7960cf0580b cee707102ff886386a1afc90ac11eb95ff796df190068216737f85da4a99a85d 27a33317c49c01e292d23a085ebc2af814f406665c43f9f8e064234bb9022a08 de53a7f01a8b11731298523138bc022a5def631ada76f4c513a71e5398674225 585c96a449f6712c701e231b526202e28a7e7878d8c09c79f103f2c734b106ac 55dc8746379b0c79871bb5c3fdcd4d07f16567e4ae20fb7ec2e794d27785facb e9a7d69695afde442c58da9339bb8d00fe3a90a74f813f00880f28784797a309 6ba12954a1b735fd842fd5534d28304d9819625ac0425b128850b5369e2c88f4 d41537e1b86925fd180c1dc27f7c6491813f3344d4b9e7bf26062f3c93a4ca24 d04d80299b1f40f97eef90c85799b317154baea13dee98f721fba3d6736e99ff 9629084c2f4e36d15a963af5ae25a8ae70a20d6d4029b19f313cecae8c810163 5eb7b30d7c80f24c1cd46f488db56a4b930cf1c595878682025f0315d1595401 43 f336d6453c3a30ec8367a796c44102f82869fb1d8cd15a83878925b976db46082ce45feceb7e5ff50cc41f78318bfcdfde684c1e5529ecd390b15bb3b2e6b402a14552344ed57b0d80d60b82a61b6a32de5683e84ece310ec4ae54c3576d5b089e80d45da5d6378508cc8dc70a6a332abba95313f3b19d245e5087f51bc4af08542317f9339a58e606aa2333f20faeb15ed86e20afc3044889b1a09904939c099525771d94d84068ed1527f387fa7171d84a83d4ef28aa6a035ea5062e942c0805a161f960a680cbe7fae0411b82699c4787ab597daf6b280cab430921d1970dd17f87fc1626c904d558f2cfbc74e8d9686ff3a0d05d8fbe693934f26b9aa000fb5ef204151bea5a8b39cbdc9150f3551d3d2cd9de389d4fd4db7e7aed3e8d063f461d8162d15bbbe55909cb9da4e4702413471cbc1d957357e6b29748a10608d021f14dcb7ac9761740e169b9aadfcd4727b4c99ccf66c00b41f6c189ac4a06eb96d0f2f3f97825811f42ce789c07c9bc02b24e554aa471559f15f87dbfd601753fa7cce2dc4403e22e365c9bfabb11ad394d041d11c4fda96031199c83160bdef56df1066ccf8bd41cfe5eea2affbd596ff975dc1eb55d9524f0417efebe007a15ef47e71e9a8abbace6b33cb89c40e532219d8f76f51092e9005ff5332f0ada57076e7d0900234eaa853c5fff469e14cad4c404a721900f8d9095c2cb2b00c6e0574787237836ebd0ce53d898d55a967015cc3625d5ff8e76662593264a0bd5b3b0889e1f949569adac819f53044c912827e9eabbd2ccba473532aab815065fce040587740f7f56f79aaf4cd31bd12d692aebcd2a6a9ee9ad5407e65eb50d722d9091d301b49f0eefbdfa3ae7ba7e6e516e940970e125e8a963e3bfd44e0b0b2ef05799af592610f66866f375da52e0fbf9f9bd75d979d6ab7e95e9a71706469fa2e5a12ab5d788fba235a2ecf8f6cd7d3ca4d4b99aaecc73ddedd60afc0932a62d81433e4f91f9fe6c197749334f37fba39fef3bcbc4ba72c036639dc309fd48db5a8a41b4fa128929ff9685a9a0a6036b816590ae7358eb10af8ecb9e05e0a311397c03b0bc5594a6f1a94fc2ab3cec20ea4c7cbf2dc462aeb6372e9903c7718317e03a76cee16b341f769d3666c438184bbc22387f6273e2d7329b460de2a40c00b52d11dd30058a9d49aa70b84eabc97cfe8a6c4c7424b52a4cec8309d8e11866f197c0b36cf097a5dd1cba984074194b2859fde7afd8bcfb8e757c04a203ea3dc101a6aad375bb151eac1b36461b7d9ed359e47e462d1083b4eed709fe77aa12c6e98be0368fab0fd09b0c7e8c4690ce708a9dbe60f2fe6ec10532025f48755e1c8696373602b7918f54c954e1dc8ba0ab1aa3cf78e7f87906d47705d8c4e378a3bcdd3216c944c0d4fc7631a31bc54103481955d59f20bfffd882014bf07b8a5600ffa46baf94023413edde9ae24b2e2b92fcc67714795230405f001ac0c9cf6b52d63b0e4dc2322ff9dd4c17f300737279bdf178f4a9bea330c30dc7f6b3470d81b338fbf73d53585612128adb9d86df73703dc8b57b6def5fdc0395b4a8861604f7b927fd6f19c7f54b3801c62ea0e282c25901cdd447fc2b790612a1ad62947946ce9aa32cdc4906557a1d88610a078635b3d7cd88df2589880aecebd228623fbcaa4a5b8dd86c1b4b54cb6107e1408b2493c9eeda4b89ddde0e96f832972cbb1a69998799514dfe2d21ae7a00de1cf19c6f19b30652857d4102937914e5536175e3430c9cde0e742439313a6ff6acfc8a3e399899261291a80537c1a8296128ff523fbef6f67f0a0388d43839b17bc711fd19cfee42d8d2fb02890f8f617fff8c0c74c7edd7c9f1757588038f0d7f2320fa65cc02c5eb184400495a978df82c24ab7374b0cb95fc2cdc22efe70744472340dc650d7ba81fa90ea0fe27c6d86aac4ba162f80c81dd51a5b957db08b0ccb2147077e5fc39f5c805db08788241aeec6ba497a8b09416395b327343ad86a4e186a811adae66dd970ac3e9323f2f639b5d9fa9ac20beeb3c2e4596ec5855c5fa0ec13db230ff51a900f4bd76b44541c835a95d52a1d97732773a735b343450a013333e068fe8853b073bae8c01bd3e89782df7d5da58774f07c919c27ac21dc7727eac824d2491a00451f48f2d62ab8a3d383cdc7eff66a83eb88d3865a037f5b6416a63f6cba554061e5f076f31e448933e066821069ffeac74a8b1dcd20dcc4e095f4ec29ffaf20d3ee9ede95ff2ae4bd9dc8a615334ca5f27655c455655776147baa73f58ac15099dcb17d6c3d178450f4f8369cec8d2e41584cb9396a95e2cacedca6cdf45da0fb37d8ac92775c798407d588661cb3e1848da4196d29d6a1e39c7bdbb1fcfd20f20e648a526f184c339e5ba2fcb97ccce3746d45bdde60f98ec978c5dbb81fe03a91e1e7ce570c555f270c390767b8680eef6171c1d247728936d1d407699ea0296eb0b6d2f1d11e0004fd9b918efcbe13a16bc5c0ccb9a1b4468eccba6a7760e8f3b87c88dc4adca7f8b85eff3e3d64bbd2278c92b513e89f269598ac170440730ab0f83a0975a57bbf932d596e72233156255bb8f75aac45c173168ba29e40230c5003896cf9b2a1a1b1e594ba2742435c9cedfe576714d248e995cbcdb13069391bacef5055fb0562796f076c46ca59124ef5cfc5f68a720233296b3991b038232555fd81cbd09423c05f7cc34e2a802e5767cfa62d4d134391aac04629c053ea0a240c5fa0e08bb31f222d841cffaf0dd98ea58ff9b9f98924c84e2664d07120ab9995ed6972b6199343cb7bcd6ed511d5f051e4d9ac07885ff57d9ce6602fc2de5447578204e2802c4b08ee2d70a756be0e1500a2aa0b0d25d72eceb780383d9840d4332ca8f56aa43e08e31ed5fcbf982f6fadc4b75e2d7bb8fd3c8ea0bd261d27c8edc81bfe94cb431e3a56646d7c73158312b058f1928b165c75d2a055e56621219f274c79e48fdab342c9a4efd2e50414d2deaeb62cc7b57facb9906d7df14f39d7f0c9e5cbb966be6907fb04826875fbb5e12d18fb6bee5cf37ba02f259769ee50bc6597d95bd5b7d79f20d31196717698d920778f83c3dec8195033b7099d88cea6f0478164ae6c9001511989ae3acd759b34082de19c0dd28390d68ca78138739dd60cb5284c095f50504a470a6239689b3882864d6cc042331099a2a1669e55046b106df947a28091601618525b34f3f383c9549f9e74b0a5407cbb875f7a1fae649c93cf48528f25bb5713f79372e636d827037f343496202033e5a4aabadf8f5bdb2f1bac693b51b558db8eb6cd933515c0675f90676b6ad073e05b8b4ee373a098547391b31ad1dea62b001a9432df65ee2328a3ba8637b07b22a4086b14ebdb70937f51ec7ee20f85e9b2935d8e4791c8aac31dcb5d4a1077a995c779baae86691a9b89517c14044d9e84ef9b2770363569ee6c0520ae30136f6c6940e6a089d74d2a91a7c5bb7016e986f538109540256da1aa436002006e3e5ed41a940863253c4eacb25faa05a0170d987913b2a51ca8f29a4fdd99e023479c0cb0478b11c5ee4b9fd63963117715d9efde2de988812542f301a56880c5e40ab8a9175a7e91f53ece9b991cc6913642217332afed0217a57b40fe62d0eb511378d1cfe76a316f8c36339a647aa0bc71fc916e5b9d334bf0cc1bf7adf0e7bc27c7f9ef44603eae38eae83d420e9ddf9fb5bb5dda168fc4af47cbab1370d0900a1ee0ba632f8889d6cdcdf44df62c3162c9de25340d2b406330a472c7e00c598783110bcc6cb69bb606005bbeef6b043cb7ba652fed4c012e987ef26120bbc025592cf475bf37e8fe615282cace19588a8f396f1dc88a02b29db0d74fe0b1ed4dccc404594d9d2e54b62ef9e04b1e6836c2bf151d4f8a9b94c16a190b10ca3d109acd57bf9732b4586cec825e2db4acbd6f5a35c4b47df229ee9a1f68b08e096e63a2b5115eb72985e9c798571272952bd9276a4b242fa5d23c83e0ed20afe4d88cc69c7de6145d4963d87711ada259b3cde77df8db5c0a3679c0be1e608e68e09bfb25f17a82864d44a5b01394bb2bd47e9bf0c4d5bb06ba6854937490d51eeb4952a307e1484a285a24a9d83426395bd991c9c2d1704f41ff355b298060454a052881c0f6a133cc9d38146512f6b1a8218a3bc7b32b062e41451f8c70d8d6dea558bf1c8dbfaa1842758a5f05f0377f35b8ed567b7bf48da58e9dc540180efd88fab346c66b87f14955c8c12dfdc63c9069353a3f731ab91daa0831103813f6ac0c1c8f74f86366afd925913c08b017306499d507c72472d3d10ecbf0e72cee2a2425d35170221e056aecedd3081a155377fbb51cd901f0d2f02b8df0c898207071f47ece88b1dd2c10a3f5f0ac904fed7fc48563474eeda726b84b20e79428b1204d475d74eb519bb6598d976455bcc90634afbaf0d965cbbd42fca0650d2abb6e6a4443e052bbd787efcbea78a1e3ad85f0fd841e2152f23f45cc5047fc8488359b43b4aa998e41d44ca2ca1125d1f4d63d7766cf73104d4915d8f0db8befe72f1f64871081577787f8f1db19ff0067459513742d1c6e4c5d08e3d0bb938ebbae33ede5946d1e40f985a7f452fb76a614c8c1bd5556cf6f8d712ae005ac78ce150c16538e5914c85a852da119cc0388f6168f894b9530b6440fcc905fd9419e0c5bf1ed2673b41dc533a80b6462eefd42aebda44226bc58325539c08f9306b5bd00952bd77075afbfafd124999cd637bab85f3c63976618c7b356800310e888a66535dcb16bd5c790ae1178d17bbc16790d1e685574419aa3626bf0e29ddc5b573a48ca3f85d10e920eb24b944c0e15ae88add3e1e81ed7c6361290464f8dac9ccedc60746000107a47699a5473dfdf53700381751957e02a07b0308405223a6afcf95e949ce29612aa7ddb67b5ca47edf272728420100c2ac5bc2059fafd5d5dabdfcb1d31bb71b56de855c1d8402dcf38ba04cf6a8841849622806be820a42e871d70b840ae945945df131eeeee530f290b8f89e5fb518d107ea016265ef77bb910c3cbda66bd7381bd60801c70549386cc06498411081cc891409a7e99ce434e2481d5824e9ec0f7c4e93732695710bb852de917a62be9ffb040b0ceef880075d3318cb028b47f59363ecd9925b27fd987c256eca83f868426b0e8a5d3b408940d94195201b9e3676ebbdedeaf30b4fe3a35abf36d4e0f2a1dd07d4cf8cd7df4a68b5c2de1f65db90d8ced5039ed98c6d5b54cab8e26e739e7608a2c0061a8ac18a8c06da340a6cbd2868fddabdfa3e0c709ce304e651e8b08e08d38f570f572a681e0452cfce934cc4be342cd030ac2db872581945d5d0b446029610934d35e9ebb44629d42b14e1d227b3cc717cebf39b1c382b63d11e930603734922d22d03e0d72c2060259e1b71d2e35712feb498a2b4919314d5aa467103144494cfdffaf66bcc705937fab5a477bae868d0671017cbabb4e7fdd861990c29afa675c3fbfafed07c5e6df79ba67b6932f82bd5d266833acd4505166dbc03e325fa2c51b420a6281c0c17ac57970b5a3b2407b4287f8490fc47bc50dd430b544b4e78a670bdde495896ea2a5ac55f5b16d28bd00bc847e618c015719df90c22e0347e83b937bae5cab1411f54ee6a88b81749a84659c338a6d3dbfc51bc0613390a5c44f3155f20c4c8b7d7ee8723fbad528b0374d00274592d9d1cb4f0042356010188bbd30e40f5b63068871de6aee6ca4ef164443257e0539e9322b00b182cce663aaa350ab818b7dfbf23ce4b373b004cf28011818bc1592dd9047505719b94a330fe25192d4e566df7ac855108fd15695eb0625895d679a370ef390d718a7da5ecf43449d3284c5fa53af73efb2caeccbfea0268339c03645dc22305f4dce933d41184afe2a2d8fd8cfa18483c7a90e188d8274f4d89cf796d70b108c57411d249f1607847595566a20b430b36011bf74f0801863ca1028dd0489702569a85e98c6e12ddc382f3d097519d0551116d94757666c638f478038ac0f5002158da5d14b8bd9349e6aa9f24e6f9f68166bce65d61dbede0fccc153011cd0f583e3f0af65e0aa84b1426fd7c20cc95a72acdfab8a09a5ab1ec1275981ce7045170fe75a50a7b3c1de6ce10a017ed9d11d675c4d9bd86615131beb646b944076ce8557fdbb9614b40ed8b63dfcae03fc2f3ac6247c6a5f967be9f4b23f59f0b68849d1434be889efae22768e7f3c3b572a9afa58d1f824079c4689212b26f0af5dbe233618c5a46f7b575dd7fcb22b51c2c668fe35d4d9b124a64a0929c05053faa00c2ad98e97e27805aff9d3c23c66b74e342ccf48d5a44a2c25f2b791403dff4c04d40b30be1cb10b607a399ceac6a1d567c7201b5cb1d68fcffcca31c0519a9487e723dbb104c165e2ef621b1dab018564fbcac873c81b5997543d63206505e1fc04c4ec67942039f399c5dd9ecdd99c1cad6d85a978813d1b2c824180b752f4e9ba6951a89a5ada46bd08fa901ad06beb5fdd841d9012eaea30a00d20be0ac0cdf675a023c94f0361f11464dae390be8ec77da865fd4fead09e29da70bb41a4cb873c4ca9a1226c6bd825dac965f705a9f2bfdf91791d6b49d5f9e4401ae5f56f1b39ebec11e0bc52bd19adab9f33d4350ef32eda32697ee371a5f8905a17370a57b9ddb10c3a59d0f33105dcab393b615549aaf791d1cbe92e920a80b020970969a06b3afce3de607e4118db0169e988f542e43d76a03c5ed9ecd2a0a20c66da2407dcbbd069b179b800f29c482126ebe32e7174cdccf063beb6d190efde1df5884020e4c30c4d8fa83807bffa5199314f05b2b1fb8d3842fd15c4e047f2dac875263b2de232dff225f24573f7ec0994f7cbfbe3e50cfbebbc61a5f01ba5a8056d4721bed705564935fd080114c8b37873742e416c04c6d897b6aaa0f638e0d96c809f8e46b3ab671e37e8cbc73ada9f4ceaabfebf7c32c50a415e60f309c0605b88875e377e3d6af881e703823b36133c2a1d173e64bc998102df70005f648583b0024d9c56a45689a711f89590f7d7e3e1f7cc906c776ba3a278304402c66967ff338497897cef8f4756b533acfd2614afde3d8dc7677411484590cae3e747189445add323b37794eab1b61ddf952ae72c0d7e47f81560da4a9c40221f4e5848cabbfcfd67fa623954481857436131ae689b1c61831bbb9bf17770f7627a53926097f618ae0e6e7106209abdf0164e51264dcf198b5ef6a08f4c10faa9d8ac222f6fda070612a9e8dd051c20d1258142c67d3ae50d4101bf58a4a0a9d1ee2a14c48ee45369f2a10688d7da8cd331d5765a7f5567cde91188875b500ce6c9bbe42be21af3c550215b24d08cac0e09a259faf427d3b8cf2a990b18d04aaba48404a896bc92c5aeafd067fc325a2d5460b50dc92d26069af2e57cac40b4a8d2dfff81716189ef2a8febb6f06ac428edf6d1a0cc342b7d3389d40544505d96c0942a02804e8c7300e8d094bcfde46a64c12d87c62552ca5df1730c3b0066c98067fc7c50a810f819b16ace8e841ed6aee6091b1977028a992df92ee5200ec9ff4919e8106fd9815e7f9ceb91b1cef4f37dca1962ce297f43f2fd5ebc90cdfe99c8de010085ff020fd2f53e5ff9c5a693aa856c9913b2d6266f0f74d4500e5139b5e5076c94c66d7ed42260fb5d4f93e0910b6ce736d28ae1baef6c5ef098cc3fe587d87a211ed80067354a31aa33eac4e6eecc58e7aecb385fa4d03090873a9b28baa5fd69810e0e7dbdf1880c1e9faba696bc17d355babca58b0635a0d2eb6bbc0b544dddb849f42b92ac6f02b5d94df207f4d68e584918ac1f85d800152f7a8a21af8382749d23a78375d30bdf760ecde8e77bce87a0f640f41778b07f8cac4ae1d0d1247ea8cd675ab94ec057666dd5325b6c8f898553e8ab5a88f0ca3ed47ed793c289e7a198c5b115f6075c1cd170a0717f31d4a14150532c601070caee6aae8f7f756ccee18b28afb327f0902800c5648a23551358bf3e661630a5ed926ca2fac1a2b872cae900e19eec41e565a52a9243e6bae3852e263ae2703689c2aa49f520ae01616e2adc70aee9bd62a78ad63545e1a268661aa9485ea0179e99ade674e0e698da1c8015b284cedf8bcc6cab49e964c34c84713537bb50e495cf0e0476664ce5542a660133495c993ab363f39bd9eb288825b764e309e02 -generate_ring_signature d9e4680311d1cb9dfb01254b08fe8cd0dcb7b3c503d6859c59dc47e25615024c b8f8617d742f1a96ab3b79e141b52c76545b39f00fd00729ed4325c2e8e839ee 35 c67863dc9547745b0a1835bd2bdd3c7f866df86486e79b5b23c60dbf330dafbd e837d13ecbb2a5a0bd620f59334475bdb332d44f44ae4220e5b30f4134416a87 c00aa3422f0a2f3a5a89edb8eb7c99d642bb33d2b5d4ae42a228ef3dcf990ade a132684aae1af1909b7d32035c7853359deec9fd5ad14e5548cc2e241223988d 39b05e702beb2ef5e6f02b67d46fe13923ba2629cf6dd4d813f92b88ce94e049 d3f8732f7598b1e7d51388a77e409698b1490ba56ff02df6c9091fc3723ace03 54929c78aa0ac34a796a230b66ae375a443a067a07954cdfdf4f34dee0a08a23 81ef7d3eb1c810cc7fdec70dae0a75ca8084651cd9a446005f7af0a37ff68c8c 06081276051edd0d6f829948a77a1ac5c8eae9e492880cc52c3a3b7e9442ea86 6b8762b54c942dfc5a701842fa7cb5ecb20ead13d5e72ed2475e00ad78f292a6 031c76372a7bb536cac58af77c11daa08cfb59f990cbc8c2eeaefc4ac1a598ee 660ca8b174d65ee995bceaa95e922dbb701ddb6c4df76e7cb46a75fc19b13eeb 81822888504f072acfca4da1c30575bf5efd17a769aac9cd0ba165003de67927 ffb833d7a1d148e158172ee880a850d83304eef3c6746427a1ef1370fe147474 23234646c19c1022929d56a62e494ec2d45e7188863f375cc2ffe681701112d0 227bed9c4db50f0e54a70edcdd4be63ea2f6e7b3563af10e01c9a9c5997fdba1 d5aff7375658c886005af953d831d6e4e2898b1490cad7d44a1b428e87e8c2fe 546e5da5f5599dfd4cf7139f92c80d70e6361249ddfcc36a64a4a6a4579ed6f3 4617768b70f157ad344866c8f0d9575c7a8029b2f693ebd75202fe238c9f334d c505334dbf2103cb24205e0ae4a660a592921c5132906cd7f634b78ebe0ced01 688761e17fbe6024f8e51c6faf00112256440cc4a2c7d37888ed4f5692e26b71 fc48bb2d96d7ade8b51a189f4ea1a1a427669fff066da86108899e2e069c37f4 e80d7e7298e64f4f273548bf0e2bdfe3cf8ff76f86f1291d28249052605dbf46 23345ed9e65ee1d2f9f0df21ec20f4fc506f837f54dd024ef770a81b12588302 b572cec572366f8fbaf5ad8ca07cd1cce301e56ada7e15fe2ceb03d6f7c615b0 ad65e69ee23a2d216d437521cbc41a946f1a0e2e350eb1c242e53d845e664a19 9d652c7154706b781272ea4ff1a5b3b84d83b2ab86389e927b6b0bbe611a207e 05bd82e4dd30ef4ae5041ba77652e173ed932b90ae8f26f0c7a1c924dbc16bbf 95f6523d233a5180cad52fa70fea8ba013a1f565f9fa5d56e6099b99018a5948 e376bffabf575bcc111d39638e0559a8d7e6055e594f5f43fefbc5add7904697 022b90003abcdffe3444bf899962aa0173489163c45d6f3a1c023fd8f089cd6f fbacd6c6ba0fe19d9d48ecb207c66a7578648a77e9c7e4475721510afbaab99e 88f5947ac68fa3b16c1c768a9bc70ebf76ccd2800e6acba428ef6d8be78b8b34 c4a86247b999e7c8460f3784603080ad902ffe2e71c986278c7a26db99c32447 1b83e2998db2167cb4f9133ec411f62fcb2246a84ec1ea4acaed25ba5fd60d52 a3480165d43b66938e0169faeb99f7d09b4c918620775b48e699b9e3e78dfe02 29 4f3672b263968374fa854ed0e6fdeb25a11a81943cff7d96308b68a8834dbe088f5e3bfe4a6b1477d9248d89eedfff7d71805bd1cdf81c18475e3a6255532806c14bfed5be4f67fcbb24fda0298dbcb1d12a3ac8e64c582dfd2a359d8c64fc0d5193a40ca88f0f760a28205950655c2cb6dd3e3445926c274b7bfb92f6923203d49b53ba5e591169998293ac19f23c1bb579ba937f5c843ba7f5124cfe12cf005d1ee3005f897c0d03091144207e3fb353c37c6855f12c96f60dc4b895480f06e84876bf871e1b0a08e6075bf0c2387e8f9210abef5e51b76e1c236cad84da0d5e63e03d36b55771ab22c0537003128bdd9ce9ff6ad2605aebc9f8952509bf0caa108acce225571004155a51f8f3ea552af7a10647d4a8b3563e4f6b95329d08fc091404508d87aba2246088504539c113fdc815e78f41b5edbe18523a944d087213bbca7ffb46514164e849bf0837b04838809d5e4bf96b06487c560f074b0ef9222f8f8e2a1889bf8b49053d23581376ac4abe4c45934b6aa93fee1d6e2e01e1db0f08cfb5cccbfa4face2b012daa3cd84903f7cb107f44938385554dfbe024e9ce2e3d9d000f53affae715e90279a78435e33127377bd7fbaa9054be6d00c7097737056e7565fca7792edbc2984740099575ea3c1f663d3ce237ac6e18e017aa614fbe5bce8c90ef9a5d58d4d5bd3084c7d4c290a8f4ddbd9add898732e02ed16945294cfbd77500ec361e148f3124213d8f8476a43b803bc377919880d0f16cc6cdee8f4512136b030c0335acb862fafacce525b977b3484d591b2c93f0396a45f559f0bcdd53a3d98bcdab020baf7917363e5ae4ece87d159e5d49aca015bb7df31a82a8ff485e3f41ed1a4dd45fd0c023b3ebe67ef5886dd73168089066f253aa431556dff8d113cbf16d8fed89d6db3baf83099b77083901bee90dc037e49e74d2a66f3e2d93db8607ccb946423f4c6b49833e814ad384bdd2ec6a9020369cd7c1717ed59c7a526e60d01cc166ad8f3b000095b79ee8f90cc4c272600d3aaafca34afcf7131975e0517ffa74f1e0ef8e51db38d0fc0aa90a1662d880ab31a000deade65f92768c6a7419f59ff25ab952f375f42ea249184075aecf50ea6ca7a1cb9e374d1d7acc7d7be78344876bbd8cb87fca86b2709145098764f0a0e823e57d69ace750ea58bf6f0db549531a655f23a85d2a05334dbbb55d6a00a1c3a1dd6472017f97436898075557af1dbe64e01e5ad22bf81be33ff0e2ec007342f3d6f586a14bd0cac0ed841098bd9104d99519b290dab5a8d90d3174ace0fd2e870cf2b903b73d614d4195e7f8dccf4308d3f4268349c13b6d02093429802665e2111af809831d8acdfd81aae3fe4ff196f33a4d0cbc93eb32335979cb40efa5f14a8120c102c979e98fd02d12d9a064a93d0c9bde6bc09d4ef2a22258c0b93c772e3fcbca3545d533c88d58f83b1e015b00526ef92b76f24d3061c4c7c0a106f248383955392e8f45fbee1503ea8e6a7c0e40dd1f451fe700ca88501a007280f337d5eab54185287ad30b921c454dd20b351d606ce7688cece3b3016a30db7c2a3b7e28aadca9cb50864fdabb82a7b4c14f072cf0ebbc90ae94b9299db0d490e612214bddd78c57459d55be8f40dc815c6a23f12f9e3172e9482d2f07209eeebd59d5d8c2aa1ebd5455541f26246b5a85212bcf309c51d8cc571811e290ac2def5cca70ce7be0259f2d1e3cfe5657df05e776c24910ccf04b589cc6f1105f06f200ce863e672703e6040e1aa61143ebf30b4f8d06bb951b8037241c21309aa6e5f7e5a505b817c965fb5230a8cc8db94bae06c282225eae54b8fa3bf6402a4ed950351406a7b1fd6ff2ea14de9bdb5530deb1bbf88bf0a72ec0e31ab3d09c937c367f3e97d7f20ef150c6be10f03acb0c89e63d46d64f73c31508eff5e059e29380453d02c27c28c51949ee208a8433ab61bd1e776996835511f0937e4014fbf2354935e1af783c20c2789d01e480b3255dc9342bd76065a28e904e0780caff08eff84bc92e0cfdcd324870a227c9008fd7396274b33679aaced513a670e5b6cbfb0b480eda0d3a1001e0936534ee564e63160c413524280a9345b66d90a9b542d786457984d97bcfb82f0e7ace032598b9ceb2eed153ba1a599c7b452014c509d49f481ec1774a896890723100352c78275c4b4a053a50ee0440e93770156065bbc1c2d9e14ef6a021816db11bf6b60cb95dcb0d11891815cccdf034e012a8c0e4425aa83c2206ec7d7792522bd394d176ddd859316f5f5e9ba51f6cb052be14312239919f1abf04fd8d993330f59b6bc202379695f0950aece7cb3110b1f6e540fc240b9011d9ffefc208018993d5df994986c3374e2bfbeecca834d0ff3f7f2013c9a70b5a609c9c0960ca43c42e8c4327748d33aae982850da4f690fe788cc121d73eb71ea878d2f5f746174c46b49a486ed1f0e02ec5c7c17f9bb0f51c31a90e16362e4327211e8f33804fa36803f298d8196c0e708d699ceab7304bf62b94dd15a657949fe1f67d10ef6d2fd710aee911ef0570aa599317d45f40660bb1a8cfa5b25f51a93d746660d8095070f1310ce72ac7ca0c0d282991b080acc94adfbb8c7658cf13a75d086d7de4c27e5427baf82f92c864317857e9b5802310dd0eb170a744c10397e10dc1dd9e105575b78b5e4b729db87cea1b221410d42d06ae16bc94209d0d3e317b4f06330bf7a5050dd79b631c3ef5404b9608d09a95ba6e87b631150a661b63a82bb514f201c0b0fcd670ced919023c7c15fb2062d2deaf0ff3a6c5c003bdd29c0322497322c1e126f3693dd9b5348f032d4200b68d984be379698bdbac416c8c3c91cb7cdf5d816320888ac4f6668b4faaee30ff5689195a227306035e6291af75514012a3b21667128821f6a28e26a7528800c1d83be7e41d78340bb4fe140b5df70f37d62b551185965fb8afde3d986a1dd0374f942d95b77eb9b56e3af94e93996951ccc64ec67c27388ef6c035d055c1202741f59f8b8e0b8703992e086a3bba8adaa3f916ce0ad5e6750bdcff2518dc807373c468728183e05f46bcdea1470d8d798ae7cbc2955671bb8cede79fd764209736717295f7f10ce1e7db42e1928d8f0f4711537b19702078d2579f9ff316907 -generate_ring_signature baf768d9e42fae2c59729a1d2b8c1c90345ba669b954316a5674d1de6220a76e 4d7d7d439f8fea0f37accc6bb4b1d9b3d2c6a8f1de4c4080d058aa9aaddbdbb0 1 782b450055215a1e6bc07b6003187d9560cee16e6f5262521df26ece593c89b4 388fafcce2f0aa9c54a2cdeabc47075bc4c6dcfafcf8bac5a99cda75c3e61b01 0 e7d04a6d4629a8a42dc237f45a0a0cba213ae340fefe70e4730812ae012fd40c50690523910dbddc97aca9daf6f2408f799d68c27e46c13bb8b126f1b82be70b -generate_ring_signature 01916e70c1a168a97075a7d873849f7ac03e65094ee16f44ae66ad4a3e0a9a61 19388d755023e1604e7a357953c2692ebf537afcd3c5b175b18b4480c1770ed4 53 242cfc91401e49fbe717545536ff1288d9929ecb3fc5fcf431ed7e457bbc4b39 5720bfc3064c22d0bcb46686feb470b9483cdec909c4b70c63a8144c603de1c5 3144d1064b96500b9fa8ee6ac4f95292f6d92e7c6ca34b5974511c380807739b 90aa403c95a6a5ea6866ce56913201a0aa37d5c09e3e0c0150b8f23e6a8f7074 29a6167a49da7587f4a4a05e534e194f7fb0858c8b187e681104939611678220 47a0530a95b6e548ed923ddaa08d8cec94bb9afd43a716602c73f7a563485426 d7792a71e94ddef9dfc4300d460fa547d0318c04a0f43513e98fec2389fd03a1 84ef4f5e3c509f8110ea7239b531431da9420ef98bef880020ef1565915a9a10 1a32deba9900d23de6dca4cfab511391e4bd2ecc9d153f2cec3a4ce4fa4c54df 371d5595b2a49bf72d7824711067e3248f2429e086383d77de2035a5da111c25 68bf85ebcae2c713975dcafc9200acca99d4d740f05bca766d7eb82391767f66 837dad3d55f3fafc1717b116c0f7e7121ce70b4cfb542b5452a08f92dc59ad55 d66ab88fe75167e16bc30dc727e2862128b938292e5bc60a5eb03390edf0b133 32f67f886be12e0bd1c98eeeb1690acae74e7c6e321ad14bf6dfe7bd843176a6 572c46495fc92467f1bf1142893e0edf08ae501f806402ed1b8ba58cc767f8ec b845884ca93520147dbfcc37a28b5d899faed2f821235f2b055ff34d2ce0ca2e 00617cc79d54d01e4bf16be365e673c3cc6bec51a5c337fb736a885ba0acd573 6a8278978430c6e99cb857f4e4512e8278aef7fe70e4b2cbdb0aea6d5baaf14f b0177887294e8717c7c4300e3daf4e5d35721a54fb85aefb99954ad1cf15228e 5d0a7d23e13f32762fe5e66ab9be9aa73336f9c385772269046132a11795caad b229f7653c5630d1b2ac5605a5b2419d7c8ad9879d6d296eddd14a1ed788eda4 97e01654bef78ba3a81c4bcb36b07c6dfd723a867bb2d1e1009574ca5a4a4444 05a16ea1786cec3520ded847a0addf9ac3dfe96c3315e785927d75834f73b5a5 995498a9ea1ba686429c39efe8fc92cc2bfe7a4a3da23891b302d56b18c61075 e4f2da569effe699c788939b58b7271eb5b63347382d7b9fa650e0c16caf7dbd 62b2acfa240fdd2888dcd3ae4b3b60d9aacf48d627ad4909f0ee3614d2a1d8bd 6d52a488709aa858e528c36acdd35cac6cc7a1e0d612ea4dc68a4393ef095a56 da6aceaf9e86d64910f2f90e7e7d30a3459260c9dfbcf427b0704f5d848ddac3 84c11c1ddf0fbe484e80c375f0bbe985133c72d3be646e4a62691b3ddf02c93b 132529a4a7796849c67315835700cacd444e85a11b9e71afb5ca41fa81dc8373 69d1d9c94d25a965f96c89bdfe92d5bd5a10a145312a46d990d8747d9b54ce72 a77f3f1c05b8b70a0203e373031adf0596eed28b5a434cdf0abaa7c2221c5a93 a611e3a402a42a33cd8f832dd46c794c6adc9df2bc32747686ac7614a72d0c2a e8f60d367002f5fda4a024992dba1b161fe1802e680977b2e2f55a9c3deb27d4 e887fde0d2c22351ec22b8aa8889a80c0917613ab397c978b2871af576c76fbf 9a90e74a7e602b11e1085681ef5e08a59827b7976ecd8e14f5c7a81312a9b84f e35b60b7564725d9a7dd34a6ff0dfb5d488e3cebd79f8260a7057b2b2089c233 71a3cdd1e3f0840ce0cbbc9049efc87f376938c4a6fefda0e4364684176e6bac 6dabcb53034fa276be2e73851d9a39aadd74b3ac7ecb0eec92b43608cbf4b02d 13477a1e0cfb62bdeb1a30889489446cdb3e37bed0e868906ee91da6ee4de0aa 1bdb6348c889278979c6064c256adb5e3bc76b61e332b2981a49fbd79a14dfe0 e3c6ad547fcb3afd9dbce9593931897d8f736b5044f543475757c7775a58168d 379dfebd4d07db29982a708e4a03ef03a583e869e704f36dd62da8fc41867cb2 4249977ebd5483286439256595142ce68bf2a88d40fa2a0e204bb8918b2ab1f3 08710fec6ed8004733e622281bf186975b7c7ec6e2a85d9cd7fd146f9386908c 0ea6d13d9634d24f6aa872f341b2bfaba220045e6dfd752f0746cc1b5e9732b5 201ac295b1b5a10a4317748a29f94ea0e5b6b069a8759eccf5bff9067bc1c829 623ea94a4d6de8a3db5e0c19026fa2623559fa878030c98495111ee9b2951247 f1382fca2d626d971af139e3873405119843d0b0237b48d08287d893e7f003b9 5e536ecd5570c8ae9165916d9f14688dbc8c82130e1c589e23ac5ecfa8a39435 f18095254b9f272c5e5f10322cbee3cb62cb40e75a900bfb69b1557c254060e5 d1c0c862d42a95b7008215dcd1cf6c4516df9830ea11c217042d0f3df720814e 4eed5da8eda2ca0a8436e337346fc54f3dd38b90748bd4023580e7fbfe271dba 8b58a9e402a6a320edb50825a07279ffdb434d5bba8c2b93bdf568144e098a01 0 609aa6ed537a983497297b9dae67a3d740f9fe31b632506e2e4a4c051dc5500a8d5100f9c8de1b796dca38fea0d48ee5d7c24996969d2875d0757f558240b70b98d8cea11b261dea4996a426bf66eb63820706bae1ad65e864dd117156e71202c4a51bccaa7c50d4651b2a6a18ce1f73aa5d443f531066f494e950f8771e90071c6c2552edb05d797ec2e275cb3653d0089eadfff5a1822c94c39b331bba7f0bf5b6b92904c9fc6ba8029bd61b18c540aa2f6fda19d9dba901a11fa43033730aa8f9976f1b307299007eca72e21a0b9f1cdc559081321bd18acfac996ce0150795611f1ea27d57db1eb548b9b83e9875dd38f1481d6c14cc19ac880d7d2508059d2889b0c4a4932be1a6aadf7999b300e8fb5aac17354b57ba74fc5b39f5860ab5ea394af859c4008674311a478ad64ccdd6b9f240ac896ba5e1431c45c2e905de4e9f4fc6b6b22804a817ae2f65c71f2739236b0f452ce622bb1db320b2690e6513f1c3cf8382d264b01a9fe8175b9f22f4752fd7934d37c8d203ef3af7fa0415759656ec966e46e8661f6d80a05205ea095fba0a5e1183ff625e116d9f4c0a3e3112bd160f7fb0a42df58c96664a0fde979e1c1a6cba1643f1f48895d4a607a92d715b31b68bd5ce1c2a8bee3f34b6dbcebc56bac2e480f6caa66b816348096602e3c9f49f2a43a526c7c252513c6b6289731c6fe2e9f29f3f428d608db0040d182278959804dab293cb5d201d49fd032557a54188c555b70dae8a6b36ea08700155ec01b8407a6ec7f40ee1add38ba72dba2f971c95a06c257df268545d0ee7420822d8f62bafc20d3c41852a22784408caf29d87b1e8743a43d146fd450143435f388d53d027bec2f3ff634aea41b98d3fd0a91fdc5843f5aec3ea4fc607986bf868c4839d767efdcb4cd47fcb9854a0c8a464aae9a569c54efd413e8c08de1136a11a22e37c9638f8bc144b5e477cf7aa521c4bd2c3c4200cea51796e03c54c9f30baa7b1530a5d0f19b96f9f731cef39469ca82e8fb943f7b72289db057bd851012bd066f97037ec08c16a5e5bdd3ed6d58e06d6cf62d14e304253f0067df2bcbfe93d5768a80b5647341a7e377be710eb154a5d7cf1f836d3e2948401c38df5776f04bac6bf7ef95c4ea4afaa066602fc2bfd2ec7966f215fa576590f2b12ed60a54017e42d4df0874c7ca833e4c74c6b104439ec14f6c0889f713f0676fed40e35319ff57b391d5cb1c707307b614eaeff8141e44232bccd4ea7140853185f2384ad78fc0ecd4262137d4a4520639e3d8475facbb0e8540f7aff7705fea17f5dc23a132d96d949dec90b9094296826ec34b4e915baaf3b6610df5a0d8fd3334b810f00e1e06e63618adb3bfd8a9e7e1478d1c3b1b2e4d5388248bc0ff2bc6b13a057effc9ac818f3e0b4bcc46f9bd36f3a913e28b76a31aeb33fc50839420d269f799394d86efa1006a61581f464b099e1cb3810993cd789adffbd09087504bca594d90ebaf0d18648de5f80cda5d8a64018cd8919b5e021a3d5e005c00da6b225b8315e1b6961f0b2fab2aced687df2a3c0dd14463579703fefa90cd45313ae0ec87915ee9a2fd71e47c155c0efd00efb49c88e1b5a193946bd8c0d086046114c15739c423919beb362923e4386139aeb1f889146a79fee23de0f01d4176198988ced521653793347cf193de33b42a904aef79e6bbd02bb485ab30eb4da829d4139bc32636d2e39a865f058ad516777a96171d567d07cc245041501f4f82bff8674c47f5b21c9fbb9a4974ff1516c005c02b94a4a27a50536926609bc0ae6633d3a7ff01ddb28b0a2b687617801b9d3ff42d709f7bc009d9b4f9e06f0fa7f66ed13a8f49e4d97dc6fcc8b95c7d7a88f6af9741d7c6c3542ecb84a090e4bd9f5496c11b669bb3be377223909d374af355cc579b9a129b5108477bd02c8369ac5f22a9fc44899890e55f8b59bb42a98c3ab61ab260d5da7f3eb98ef0f8cf10688274b7d6f81a89679ff0e6556d8aeda589ecee73b3e5a62e494a92f0af36e805eed96c63b69c6c1e139a11b98c330711075bc90d55ad592fa8fb6eb0c96c2277fc1cb2390cc3b2cf48b9251af71a9c81465517cc650b1b9c69fc2e60d6c20c17da0cff1ae874af430a43ec8f697af597ff731221dcaf7fceb974dc702900f58393d6101ece747af3a341d0c3ca4c9b75193f037623b86d231acfa43083eb7f24ee11db68345ad5c9ed7f5365038a1d5df9c304ffe9f5163a296492601c75ae6284c268dc1ca4f858ad7617fda4d8d509df0671fd2ede7faee5f68510767af721bf06ab3ae1c4bcc512bb8b3cdbb721a86295620c8ee21d096a5734e04862c1a054a708241aea5ed4bdf4f7a45094692397b5971db4566a26dbe42a10bdedf116f64ff38cf29e5d773955c87374bcec4e45b3fa12ee8dca9a201415b00b562e112cffb04c20e10da981c2ed18c33b1fb111b64f077d1d8db8b865e5e06c391f60a44c16186fd1473d2e7d684e0138859e927076802777107fa5a345b02bfd7cc4c97bc236a7db2931c3ad4581ac7d7e17f5cdcefd78956002354696a008c17c6a4f316dbf6b9a42ee397b434458097ab9043507e1941359c9c59d96306c53449864e6d6e58caed20f3f86cbbe254952b2bd1c697b1a117851e5efea80535bcc44db680809aee50f100b75fee39c0d6806c5c2562c605f125163618b70f4068859c266336476aa69d13bbf13e352f6ec58751f59226550c3e229eec9200df314c83e93d70ab8675ce0210f7d05b85da4574d55d293c47ce0e4b8c07a60020d00fd6ed703803d28ba3d86392d615449dd5db7a6ef8ba5fd39ff24cc453036306583174a75bf83a08fb6c1a3637e4c26551a9cdd28ed61226c6c8555de103373e3ce46c71a4a3fc6fb0aa806970844c7616b03c88f6306a4abd48d7f3d9062d8bb2228e968c3ef155f78ae43ba48350b957efd15e117ca1fa022b4481890eb66afaa914ed9da87b14ea4e4188decf45e1af8f78dc082d72f2b3fb3ba6410105cb789f8fd317b65396ba8b34d742d2581917b6de1bfba41c33d35a947ba008acfc83bde74e9a37cbda481a8c3930b0c6d369540bfbdc72c244e09b9996d00cb6886e6c07266c24cdea522b68fdde31f458e7d2990b848c448b69dec0ce450c339752b261c678415850f0f5e19b95aa2c126cc65db8feaa78cdbe80c31ced0418f436fd805bbc202f28e11ed0538df15698dbd98d2d44ec3e8001819c398a0d6c239b9c3b46497659fe5ecf96f5b33ca09f709c5f61b4b8800d3ee1e1c7980cdebb148b0b3808362e8599ba1fdd2666735ab8a9fcd5be987cbdbb5b6f863e0f82fecb7435a67c29a6e5a20310fdc85fec8989f6220575ef6e2834d58989da07b144bf7199498823325701ef1dcb166b1875b0dbf1f92f8d4b108696f71a660d84a1b6315269f8d6bd0eb2c9a161305a3f1f4269cfb5e85d4a332e6b99e7c4081bd128376494bc1cf308d5835f8251f72acd55228761997fa2ab38fc0e02e305d20a8d2181f121d4af43547f5fd324c147bbce81a371d643e93c66dd98196406ed9b7f9711d057f9f2d967e2d96c04abaf0ffeb56769a66763955b9933ff7e002191a2ad9851a6cd5cb7ebf52c166f271552f283344f2c70a5ff7403f72d1504fe6d8a6d41d16027c15d2661654ce416e5ac0936a4a95a011b1221a5b38bb6044733c983ea0d7c11c488dfb577ef1379a625f594461b9ba24783f062d96f7e0b084af26ad7f8d28b87c85bdb7ca6c1eb35dae7510f6f5d0ab9680eaf2c1f0804e63abbd55b87acdc4aaa1cc70a08c214a37b95098414298672853b8859cc24017fd21045fc2412fd78f1b69af0f08bb1e4be003dbd785ceeb843f651ddd0a906b17d52f06a635cf6d692f4b331fa850687d0e541baa7ee2fbc7669becfd3d3027a218a18b6c0814f04143a64d9a4d37391a006c79eb148b3f4d12e70876b010827fb7d1dcdc006dd3d55876f3fce3a90f62b7bc5c9ccd84aa3d28a94dce3350b76f0cb5a5d4048198a506dcdc1ed301609c04a011b4b7b89535a72ba207eed01594380d224173317d071e9fd4d3d6f72cd2e5918624bb4a9b10c60f6c30b9d0d7d5944eb974216c48bbdaf4a7f69ef92b20e03ad824ea78f41bd7ceeae73c00373139435c7841cb737304ec5add479f140fc06e28f67cf92de2044f4c23c0400c39ad413285f51e76c087ba5d927a300d44a7e0317e35be94d41cb89f66af40c6994d0df763b00428f7e94af71aa00c71227853f1a1f5878d02c85108bcf8803ff9e8c036495bb118eb35979fded8c3f8dc8c331278d0f3942d1752a2b79ac0aeb3d994f8c4204fa96787571924379697db8ebe0fb1688b15c6853f85c20110dd972052874cafd60b866bd163e83a975fa19f1eaf5daaa1c84de7acb867a880cc64aac0160eca5641070631d5f85e0845430f1fe3349fdb95e27dfd1e095330fd8e531d764605587b36e7481708978bec8d6a0f5efc188e729f6475ef9170c05b2510dde7fc1dca90eea757593daa442cc156a7bc09ffc40837e9395ffcc640350057acce214e5c3ecfc7d5834a9ef1029b32d84ac1f93784c279cc72bbd8204fd9b5af30c739d5d0ef8b5121394ea1a9fac2d1972366291a47213173e26d2010ed400128c775e733af9ab3fcf090707eed20b3b477fa3753a3455444333c805ac46e2c235c79fa20c71beb420c3ed022561076d8fa8c5a96e480d09562951021009389888f42b29f8dced9208ea91f9c5444ae02a261efe1c907e55ad90a209 -generate_ring_signature 0fdd09cc2513c1d346346db21cfda3bf3da4d65bf66a91dd87c83fda9b9d407b f96cf77c4abc31236ec66ab0e3c56d25860cb2027897a5fae40622a7908ab147 16 a5f687daffa9505005c73221669b1a728930db51d4d40b78ae6a821e9b319440 07a6ddc48dfad0383024bd700f46f56c88129345439bda5e7bb7f356ce11c8f5 585bb3d7f53e474d75cead5d1ebd12c68757bfe231091adacb877b09e34cf3d3 bd06689f501f10bb2f4d5e3cdda3954a6d55ad18c3ad485fa98a4e83b163fa15 0908f88df8ad262a40203ba72994f9bc919d79acf8f3847c5ae72205f8ec29e7 6ada309079d68bab1123ec762dd8ac04166d8ea824acd9408f502731dda08a8d 80d9f89d04bdf2c205d6955cd4f285790a4282a6d75bb555b1342138b42c9364 77e56ccbd4d1ad228e32d2be7837e3871495df21e94dd1328428251d7bc3729e 6387f7309b7005b5073e718b24b2b7fef3fd84749fa98e91dd1f83912487cf56 6b7e693dd187ad5c38f73079c040366abbf2990dd30eee6f685f0360ba22eeaa 819f739bedd0589653cba095292e436678a1fd38767d4a6e9449f3d4246f12c8 5b0d6f09b5ad89d7cd8ae24e8ba3c2c4440cb8858c2483ff1363037491953fd5 e3a579a3dcaf3ba92fb5f57cc4469d1ac00cf048f0f3950819875b1805e43a46 0b650b9de62dd063d88549fb717d3ebb8fc15b3bf7338457c53b7cb4c2b1350e e8ce03b5b89b392e9d2de32cd39416b7c189f5ba81954c37bf64586dbe707ea6 feb0d23239826ed5813f0d76ebc0934a4ad72186f9e43a7895c54e5e03c55b32 e01f9713a2feb7d4f9a06fc9b89f1f438d990269f8650286146ccb2df251e309 13 ecb57980bdbb5ef293359718719bba53ece5c16e9e91037d5500c599c5836c08473940755b3f465558847f606c162022f061e9daeb0742876661b5bd730285040676f5bcff5da1c3c13049dc3faec02267424e7bbac0fa645b5c5dc6b06d1f0034a89cae995d08ac91aa59b7e81e476f6b250b1c14e6c42f4603e50c8dcb5e08d6d054b4b5c93ffa94c1889a20bdfa7893c4550c1547ca7ad21067a06d1ed9081d2a97e21c46e453719e4f4ab4c55d3844f4c50d1a63bfa4783b9bd1f6a20c0ded2d41ee2218e45e74daaeaa11838e518cdf4c7f95e94727a15a6e5ec21a3108ae5a098b3988da0fd6bd4601fb84434d5d110eaffbf5fdb3fff485f8936a6805ef5b397667e8877c878ffe2991390de1b23e075b39d85eefa1d6948390b033064c6f966d30df6e2270794a671b3185b23180e01b48288c12c1cb56aec222a7032c1840c0b0a8a93702996416103907888902b9c41f470b70cd309ac8802e5a0357968ccf1f821e109543af1d90e9675d07feb78a5c39d7f1007f5c8c1d9fa9090ed07cf5eacb033f2375fc6364c3bc30744ca66e20386109b28842ad0994170e0423fb67e47ec48e0407f3627ffecea725494de2dfd8e2e061240f4578310a042c39d7b3a61b969a3645f2fadb91f06c2da7b717e74ae8d48e8355360aed24009413e4917e37f291c842ae6158b62b06c6582fb37bbdf6537bf40a58b3ea5d0fa81f0be7c04e0d8d7a9813caa3f64e08d72c3e8093fbd4edc536297b5388c10729346d4ca87bcc2eef0710ce23a884ddde40efd7ecee8efa34ad191184eb6c01d95e852d866e4c531db1a7a63c8291353fec37f838037a9bf4c4b21e97b87e088698f4352edde777b66f41c7bb1cb0711704e7f6a85e173fac67bf4c19c73b09e8f2369999f12b625e3c5f85d62c9e2336216b693606879b1cda7e015abf470c8d754c8f129ed8919bfa9ce0e9c4f7baa02666a352be858a0a789021ea1aef0f04d78e33db565b093ab0bd5ec9e73ed57d9274f851af5d90605a2727986be006821a1c54b0918fc1256fec86bb33bb9ee767cbe01bccf04868625908bd71ae0cb18711fac846b4c9e3740513373e910025facbe7c9633b09ec51d5e12c9aa30da1189c040c5b3d0a0b91befd7e1fae61e9157cb9487e2d99251922f65443a80a290ffeea5e13c10609301c7525d9f2cbc4cbee4a17d8d98ce68863411ae0ce0b2ace143a3ed6af756e6dff9ec2a365b63cd61b6f04bc471d128507befa12f903703a1f34594a0de03e2b18b6d61c449d742b4ec98228ec23638da3788e2be401ce7501b18a656fc5192a6dd2eb05345a89d2fa0872e470539840f2f10d9c5d02ee60b0fcfcbb8b4459d73a094ecf2407e19deb71f58325b13d037dd3dc74430141b8f2ecc3cdeedcacb087c659d186f36de2e9c643d8f8283daf4cd95631170b -generate_ring_signature e3495fc2ad438c8128a655249d4d6b69b6c17ee1dbf96ed1acea6380d07fb724 2adc1d2a97ca897fe0342c2165b8ac198eceb0374a7320da794d1bd38a45c962 5 dada0d56d195390308e9eb9304b877ed930a1c15de8c0a28ab04066cb0cb379b 85e9284587832bd7e59fbd7d3fb9b37b4b63e801522f187fd5bf45cc4f5454b9 ca11ed3ebfa24d358807b3ccdcf4c623af574b8c07c825b4b4b6f68cfbe9bef9 f77887b1191a51859ab5bfba228a360ce889059a60aaa740a5de8e9d0a7a1e57 c445962d9a4260693d6307b3305fcfd65807ffaeaab251349e02ec4dcb4f2d02 5d0db6d9854ffe9d26d8df64f9a0f5ac01aaa30ff2819e6377724f76d5c8d802 2 7325ae6c41730b79e34d127212f2834a6c62b1dfc56fdc676fca7f6b1b42630d92dd1e5eeaec7c20840ff55d6de5bb7cd1cf0b6f1b941011aec0fe842902d504149136b3398da5144fe1cc8c71e9cb0d6794bac16e3abcea9792915fc21a060267a8c0b46b7c60e5d9ffe12ca4fc69625488c723e96ea2faf0af2b430fc828055bb77a895c15e14f6cdab67db820c58ff5c4f34ac9891a1c4b98c37f343580047c5e2157ec077bf2ecf987f775e0853a68d803902b664aa6e98efc3421e7710e08eb5fef74e1aa83c93d60c289dfa174cac28778dc0f5e50ca8193c18f33f5049fd2d5982a2c5d3007625159d873a71ca0f1012d3e4200a6ae396bb12c41f00d4b95d8cbc1e4b0d887c14084b5d795d528211efd24d8b0909669a32083d6a7004f572503d0dafe8190c4f5960e151fa549f5363f6fdccc6939dbd597cf5db60e -generate_ring_signature 923a11626de7b0b613c07f95a600a1ae1b62ef2b0bff338120f4aca08a518f0f f12c207e70b2dd9bbfc6988a0ebe5f07f915b5bf2b1f1a8ba23c5db2475e8d26 4 eab9a7d80ad2d7e9060076bda332b1e2b31860426710e7071e5f34afeccd51e8 8d48bb5e57d8c7b0950384093d6187ccd03b0c535a0edd6da35a6f015f928cc6 079e64c24eee1da696543bfb274ead55ee33e3633b9601d9e3512371194dd4f9 6348488a0884315336961ace563bf106bef9f2c5e745e5204531a3e00695d5cf 2d4e461db0a3b63a7c05d4699b1c790f86351dc1fc96d1f8365ebace89d9db0e 3 c50d0ebe8a92436ef20456bfbd2b91f21df5f061757e6297cbc1cbeaced3cb0753dda12de97ee3bcda38122ac08ef4465e52313835f4e5ac60a2d5c84a21140d48bd38427129f7319fd2d37d8fb0d0ad65d319fb11e36d13b8c3b1fe79156f0cfea6d38a94ec9ed6d301584220ab9fb1210ee635af52b726618c3f1b0ff42b08045bd637569c4e3d8a32c67cce796175805d472778cd43a278993c94f7af7f0435bc0a9ca41bb6cb123e7d652d2a70d3e8dca0db564247ea617d29c25810d20c395bcc885554b26c751a77311310f487f2e5030989d02042985285a93a18550dd203770e98cd3a0e5874b27129e6f880aada3a1359ff8c95b62287e8e0ee0f0c -generate_ring_signature f7eeba3fcbdc35c01d69774f6d1e4ca270680e87e1af40b2773dac9e9b0a56a0 6f1f04eabe8e9213c7c5d4c4a4df1b5564e63b054d3e09ad81eb6c4d930ef44f 7 ecbc3d0e415e2c5360b40747cf604fcd6e4751e125ce2ed8f7922a317bebe282 60887705484f05a205b5e6c98ec1be1df8cdd4115f0f3edf9b545370d81b2283 4310521f1828d60b124567720d381d203d81d07b8c66434011e29bda436bf7d9 4280fb5b19e595916a02527cb77814868af83620174dcb21bc8da271ef680004 f2f8b898e39ad301c969cc191c11b162995a5e1f813dd63aae200a718c7cdb86 867556a39a4dbde3c7fabd5180eb0e7ce275ea211db2fe90e13c4c040c0cb28d f6c1111d0bdc89c508faad4ef2015ea98e1f5416324def724136e030ae647603 f01ce7ed8d9dca5629b5666899c8aff6ce0b58ad2fe04b77ae75c2ed6b9de30f 4 7a49dc7b8bf73358eb0bcb5024db650e740f79bb3b62de674715c29ba2887a0a1e341701d54bdb791d96252bbf7f2125ae29d52549cbd7800e72ff25b0014e0f1bec3dac65f1d1324aa604ad53260f2ee3a8d6ede607394e5df1a3a80b8cdc075f39840ef73502adb13e607f61945dab75a0274cd07d22d41e3b534294d073027b9e3829affd4b8e0a7814a64ac8ed6957dd377aeded35987c412046e6b22601344648c9f776501cca0f7055af58c9b553862731e05d2d6951b1e10acafde109be17aeac17d7b7be8fa4620b93a633df9b0b087fc89a927d280e39bfeed79f0ba6c6b08a540fd5926cccff9184cb0e39258bc531c06011cead0479d19a9bf107785030699ce1b31915d50d27716eae11c90f47a03260d371678daf8e53a6080a624d76522da2495401b211afce50b17ad336c2b89b610c5f000da1d328957502da737613ee8e1dbccc0d977a1512b9177fb04553c1891223fc352c91951b140e9bfb3b1847aa182ef05adbebb105a769160e2bd63cb2335d4db6947876d8b50f0e68fde6d3c687e114bf72cebbb8ce98c9def1c85bcc579294a119410c3c58018a55ceb9f0e00dd9d5a9106057529fdacf61750413e3f538e82fa367f19e5b04 -generate_ring_signature c4dee30ab0373ada5dee59e1362d805d6a2eb83f1a878dc9e82e1e9dda566d60 66250b52e8ea438a69f00cec532367c889ac73727ec2b41f696bfcec68b5788c 169 f2f2b60d7675c181f68eabb0946ecb76d12c2ae176c8d7f2b2f5cd7e5390b732 743abfcb7c102fcde3281f0989bdf8aa23a38aa28370e9caca172f5befcd9fb1 6925c7c3b98df3427d346866a2063fe956404bf6dd718ad32176af5f55fa4932 e13d9ea26cfc623476efdc90ae5e746d5c01ece1c662c1b93e9cf19a70830b7d 05d454706821b18b611d100393ec3307138bc84b0c0958cea0bc4eb1e9341236 cce2645b7ce500aa4fb89088e6ba8b90d488e7adc3403850b6fd762500c3317d df18cc2a78fbe16f092a779a7f0503cd26e45a8258379e4535d97a01e4f3af7e a9d9437498986268c6e2594b4932f8ac8798254bbbb9f17e9fc5be12aa35beda 9a8f7b61754085f10a5ddb5a7bc293ad28e8365f8b51e94a18e974b7b536a883 3295ada3db3830f1a2887c4f1403eee920a836108a42a748414da663e7fe9108 80545b9db676fd424f717135f3978b39415e045225c2aac5f340af7169e68b06 3d9d86d009b0be89558db01f5ab33c2bfa32242167d6a7afe06ac195f6c500a0 37662037db5136dbe094d1eac43c18c9239969f9d3e0039df9679cfdb4f3d18a 3bea446ef619e281d5fc24c358629581d78385b0556d72fb244c66d97e2c6483 a28b168bb36453c5fc8ac19c55ed117077e0f450eab8972815682e1fbad7327f 6e28882488bb1a06b52d716767a61584235e7351b839b84fb2d340230dbb75c7 52a7690a81457f57c9e79fcea48a019f3bd405bb6b66e61a6f63d9151d719a7f 9a80b4b0f25383a2c2f70d94ae5a4da7b15857d3242d05669e84f02d66e92edc a801c63fcd5ae02c607cc766f3ed531cf1e94316ef2d2989ebc611b200a300a8 34e4278c824bf5d404204de86aaa1a806ce70fd062eac373faf51353e9fa6202 4b6ff12fb5ee85425a5ef473502e22bb78aaadcf63ad4d93ed327bfa691d5a40 27dfd189f1ba9b2fc2b0d48bc6086b1a4f242130ceeead85acefa3a92ef86ce1 37b68e0abc377dc3c967591e5615c78e49ebb08f1b77952b5bbc8d9696f2aa7f 6bdc04cd1004485d5c703f63811fda02ed60d3e90e0dcbbc4e870027807f7db5 e106081b39c6bb35c5f5607e57b1eeedfba6a6060f21ed360faa2a8ca5af8d1d fbfb46345f0bd2e1711359b292ebf8bd6a7e39e531f986591954979fb09fbb2c 37b5b8821be52009c9e93c3ff1010474644f5b2872a8736650134e21b387ab31 c83fe1124f489b72f050473d52932fd5d68f2dfaa2dcc21136599cb918b135b1 cecc1ee7fdfb34c04581d11c61b300decf57a42e280edbe70320993be72af60a f2b51106e9a9d3d144df1c152a80a090331df2efc91e310403f0a05b9eee87be e17858155d4549918dea501437c1148710a310d0f90620fea070e83e02e53d12 46b090083bd9288b6acc4812e363601ddc83c03ea67b482eb55d2a790b77e4f8 bbfbcc1daff1f526118950dd3e2709c845523e19026123c5369a13c4d59939cf e075c3c1ea09cc5b80799103ec90cb60576c33c3b93a73c24b0d1ceb45d295f6 af65af5d55b0d0d15fcba45eaaf58ab174f985bd4d41c2d20b7a4526247c9714 80bb8136d6e99bd8016b594c39e7b137326ddb543eac6fedd100dff6d6b4b5b1 5339bc37bfce89a3dde58c7fa4db847a4158508bb50bafcacf80255382ac7671 c81b42947cc5f69eaa5c203eae4df3b3d020dd3a0c5018f8a9f5e34348624d0b 6d510f05dbe39d83d6640cac35d0a60068331cad220b17c520f23fa4552fcc87 d25684244293b811b3551f6dab2a5050fe9dc2bce52c15740a2467009222ad5b 9d87b136332a86b9c5bedc40467ccfb345ca8baeea24b84ca338928ec5eda14c f2e3f7adad9febf75773a3c857d62d3263120100e2022ae9b77c58b3c7b894c4 d7d5c94f7e248cbf878428a2b144af620e4681da88e766ae43b1d6dea2169967 30efeb1e0e068b2c359373c7add7676425c35d7c7fbf3bdb90b82dd824008ddf a761d5d202b96868e878551709c2b5ab877d7fe56995504bc9052ae0f0200bcf 55aa7d97269864c26740e4be038efc3b0c5befd21ee78be97639826f5f0f28ba beaa56cb576bc41b36f5751c3c7251a70398e4db0a3c09ca35791e8981ea1f91 83d7a2343fbe5165a375540f07a124513fcdc269f32c397a138f8af02a44ded7 26efe640c840ea1a9322378e8e90f84a17627e792190d3753a4d87bd730b18b4 f1a97f521feecc1049496d25dd3648443c601de11949d575b0c550d8baba51c0 d3a56987efaf33ad73e78557598c79892562eccd7a36207e1b4a8f2580b77bcb 5d74020c3d7c93bbb99d658b8fcf1cb18497208ad1c44bcfbd8a8b956646051c 0a0c3a31f1d7cdacaebb20388dab4a8ee07765177f8cbb039719985a5a942e74 e8fa5aa4fc7d0821c6c013cbafeea5d28eb6a24c9db8779e0be56f87383a3acf 78c803ef1f3df340b6cdd5855289dfde75746ae4fb6e6f79b902da3e6edcb510 5bde60d09e8518e581b09e441d9e9ee10fe68d206984d8da451be2969dc6351b 9f0d4380fe0bfb2639c08219c7c83b8d0dd4f8a37b9e7f956315cbcc91df1fb3 ee57237455930f2d6a13257fdbc4010bd95502b156592117befc744e68b6a4bc 05845a51848c70ac4ca85654d54962644005fab916c14b572137bfd21c90e893 cefc22e0ae4f7bdb5981e9af5226769bbfb4117a75bbfe9d0c0aaead403ad02f 79df1350f974a43e500894a2ef4d069347a199579a198bfbfa7309818f11cd3d 0043576d4b1652fe8a3006e223fe2907221a22c73ae9dfffb4af218b970c422b 178c74199c65363956e4c567def65f8ae5fc0ddb7aa7cf04873db552a18631bd ec64d4014cdce524f52ebaec746e4cb7985db07efee7f230f7a45ba0ebaf2667 61b2796c0984c0d366679762172eceaf6cacea13c448f10c01d9b95a3c0bd932 78b5e5e15304a5d7deaa7fb92d1dca0db3e8caf4a621596fb5efc9e45b56763a 8307fa27a58136ddaab152cb540dd912a5f9cc467f87529fccca7be31e3360b1 bce231185b0032910b1983e47b427164c87735004579b80ff136b48dca7dcaa8 14b20e79d48470cadb4c806df5af9b034d8df8097a3be1f2d7928fe34d2b3cef 4247fdc58e6f242735df1b4fe9ea9fa87c0f93ec02b7a1f57314325ffb849cad 45c59346b2e561a5ce513d69d53d60b0513d0c34fca33d1a82147187c05da5f9 5f7f797554373b48cc0b9fc19fe98fdf53fd7dac6895a3f7a7e773f616501c35 aa2bbb46678024ccfc9a9087a282316f6af2bb04c3757ef7228831d9833dbb83 dc399f899363da744d9d4153065b6b684bd658c393efd3590ecdff3d9c2ed52b ef6d0d6e6176b560256198b8e349dee4afaba86decd2bcce727dbe95e2b70636 d32ebfc10103684af4d1d40e94d595541aa541f4580b1f772655c653a02051f6 7eba6d64022bd3abc8a5c86a8895bc2997d77dc9a1945ce761b65b15da53c6f4 cff49af65ffe5745dca4cb015ff2c06015337e90d3eee87ed64de0490989c684 4c63ffd66a6dadb52cdf67ddb33d710dbccb0207c1e5566ac61f22a21bdb129a ce65e5281d0168a505605fdb278f1898e30d0a941f8b0f9764f13179b3401aae dd903cde97be0cbe8286e4fcb959f165ade330f86c365bc5373cc5d6921082f4 38346157f200df62a9caa5b51c0b39266e67e8c8b22f31876a0737ecb3924c64 7a59f714f0e320e8decd66d486b6aed8285ae48f77cdbf8db8496e43cf327dc6 43549791da8e97a5b368cde89d57dde61b4c7b1826d2bdca03c98547d6c1f210 5a8087729bcba594809cf4a31b6d2a66713d11f44282fe19fee4555fa38f33a7 80de3bf86da79e5ae3c839ab0a723291d3495dd3903c8f64a1aec3c388e774d9 2953ca5866e7d6eda4551ca518fdd1d8b88f5621483cbb9ecaf29097ef6876d3 bb9814f0e3957bd5dc7ce3fadea884545594cc240806159fe497ba5888164654 335a5909bb1f4401db26d7e55f726b209d154f632e713e1bda691e1346fb1fcf 34865ced6ca72c9e1ccd2635f6ff2a3689d3b968bdca016b9775e4df7e58377e cdf0adceffeb97350dd41a3b6ace99484a4f4f7980ba08c3c22bad35b2d25622 1095dd8c0c3555876d83821ef96927bcdeb3c33f5785b7eff6b23012c84e6bc7 e04fa71c25a0e3484b479825afbaed78bcca81d1ec16d0e02b0ed26732ab70db 383dd6af2e2638681fb025379fe1a58438a5b71ccfb44f62082fb711937dd982 3dbe16c9dacc2a7c3d4f2a7aadd7323208de7e81cc92dd4f8958768574ba8d0e 1b724b508e6f688287fc9adb44f097748eebc537b8a9ef2e5ffcd5eb0db256e6 a8ed0d0d34c15f7b9bd8539eb4f0db1a73703f7b1a684590737870417889d75c a1ab8437038769c0677d621cf9bcf25c02fd4ea19386e18e7a1cc4e27ac591e3 d8263c35b3be8a8054c7bae2c394b6c6dbbab44c0a3a8ecf0d705dd1fc8cba16 b903646b44e144d83b2a5338054fb318a0cbbaf2d4ae28f4e683241c72a45645 f66868f006d85e3cbea999cc1de9aab9dab8ed420e887eb6d8b8bd5cab1094e7 f062cc8d8b539657ee47edd97f11ff9b863157b951af13a736b8d16c82a84363 8c9fcc3758b9ab2b89d1ee8457b0d666087169ac25bbac716414ba5587047695 bfd1f74391c25ee492570d813899533797a11e321ea9e3461bec229061206ab0 455a4eba5a915e05782377566b72dab647d9c633dac408aaea6f8ba97581f044 e0c54ce9fe9341fafc56791db8d5ea68e8cbbaf222ff855120afd8dec9f62695 377c0338298c3f0f80e509182a3fd5a40c81f40d15b46b762c0e5598eed8ca41 1c107e944813fe33970f7d5cf7e1b12539e36364181450a0f60631c3b10f9813 8997bf02ac05b9491cd822642d487c72084752b5e4150b0c703e032418d754ca df6b6f5942e2fd0d674c709dc04297c935b33fb597edc3a5734af6196318a617 ab7f3b2f0558840dc839c5f281a190d8277534848c9f64534d9b47f887a54809 78ea46342cb94abffecc038e4e00ea9a5699dc34f89dcb625b35c09c31c20090 209130802e9d6511db53dd050c8c20963375343d5e47823fa970c40ffc553c3a a7b4251d7524597f481c5a5308d1bd3b3c0254d352a9a5b78f18336eb123acbc 7dc00f08f1299dbf52bb029f19685213291c8cc9508a1b2143d5e7b7b18b1882 ea3bc724e789117a5c484b5b84441b515b758399062f2bd98209706bc9a8c3fb cb0f6539b7b8dc5dc22b2301428b9e9a2f6ab08787853b664f6845ea9e85d9fa 315c2d8496df14859b7901592b800da7ae4db9f8c92653dc6d0c108e8b4e0eb2 980a0e7e3ee524d557a0bd194d2b81c5c305aba1c8c195691e4d4ddb4d257f52 41763dbab5729980d1bc0f26643e657852421493e1bdde3b0ecc756780fb6c57 3ba8348fe5bfb2577e997df67623e132d5a290c2eb381144bd42470baaeed8c4 6d9b9089ee7f98aae119f6c6b622bdba6955abe4e874a085245635b8f2b94393 4c82127d23c46e3053c6490ddb8aca8eb567ce3bb1c3972e26a4d47dde728567 5a9a20efb7bf87a0e7c91eeffd12efbbf72d7ae4c0a8c25b9d9c3a4ff8411c67 1d186b6ce7892fa7a1c3f4f00a8b1fdafb82d97e9e7aeebe18750f45d114069b f367f4b4179fa6d22d6d22a828c33de8ed0298cde5fb5d17863509f9417af0a7 2811d5b3ed14736137126bfbf65204cfe201c5298f70aba9d4d3d0470d729ae5 cf4b99cc377fcff0b7ddc95b4f4b523c2310394ca5bf1a17e802afdeb906cf32 e6a2fe52632d2367d577c8092a66c377ad37ec2cb209c7786886e5704bdbbb25 4ced786fa5fe2666af4caf36d267efc92906c327c06d449b601005fe4ecf2ba3 c742a00349add70c374c25e31f1e192e97705e210bcbe81294380e8df3802b51 6bca8c87b78e364890984fddbccc8c407e512a5e691f8c9e4e04f526eb27db32 33f41b7270fcceab849b60835b0c5b8f3d0a3362db18f6428ac8d6cc629a52e9 f6ccb30dba421f16c87224c1fc6c910c28d928947aa80a4aadebe14b5472e3a5 b75d3c6321f144f78bd014df235649645bf6eb8d15a0b412c8791f97dba6ce96 1ee09cd0a0c0ffe069acb5feba91b0d1eb78b810977acc83131b03415a3fa2cc aa4181c9559f8e935047ce91591939a372dac2b5daee47209472f919c6035a02 147b4551c883e364fe17ec3d1e9a40592cc27f8052e1fc7d17a6c5ec24e2494e c9e70b872854e07077e80d0f66a062e15c46c3e108d7cf656a5acbb5097d38cf 32e3e959f6dfb3e9e3bf1b1fb3c822bd8bb584966fa11dc1e444d2ce4cade8c8 842e0eee7a3fe30185d75956878c418aaf33dbadf2d95223031edcd9334a14fb ce6acedb380e0506c71df56f08e37c9cf6a6a7419a0a84d67421f8c56524ce82 c4dffae7b32ae71007f42fefa57835500094a53a7e59b4003da57be6d752a1df 7c3a885c38d04251b942ae97223b302ea5f38383fd01eab497709c42d5798a6c cb5531c9cae36b968f165726c3918cb6f0904779851d8ed46fd9504a90a39776 7229ff35e6048fb93a2ddf96abfd5642442d91ed4ee2928e2dd2d9819604b79b b79d0f869bab272133ec14603e03fe4cbbe5fafcd859b8751d5cffa2f13067b1 49759392147b1f835d36bb592ab1b387a433067c4ff3ef27c65046c868028b51 466ad6d9a84e0662e61b8a8abb0bf5df7beda276d68909d944a28ffdeaa8dbd1 a3b15d7dc0194fb2f1aab6a358d2b113f8e82a5effc3640a89671c76e6a70dce 43b84023745566f7628a0c30be507cb86dfd35b80dc8eba994cd1d2e0af685f7 b8fdd27e4e758747e0d303623d0eb13a255037f5154e0d869fcd2912436d0036 1070a72d4d5efdbef3183f5a0ac7699ca4f91f3d17883f44bf7fbc51b1fae1cb d4506ec0ae0bb3ebcb7d481bf5ca8a68e19125b15df4c15d955dbee943294e55 858799a67150b2fedf3544b0f1e6e3c3d26f7f886926f57f53dbca535c8f6cd5 3c2938a328956c51e42ba52e7bbbbdd2d85cd9ab1807ca2451822ae8002a9f47 2a1e89c0299dee6608a8652416d21ee18b71282dd0772c65d6d2af8174de8890 c710afe34c83d62d6fa2713f8ecd695ba6f7c3556f7a84f9f9e817abde3fcd14 9195d5d5b1a96ddb0f8366a2ff9e0ba783767d0bccc52449136ed07c05eb1729 8324d8cfbceba7901fb55976c5fa6acb13005fbd838dbb42e77495c867adbffd 5dc1c7243b65a5a6de9bfe9493ee49c369548a1b0f7a707c50b49fd0f9273e5b 8cd9443a7faa14d017876ac6116a4de3633059124c9f55e71687317ec4a4d4c9 0749cce6e8c6eb0b30cc9599b9d1e2e8f536af0a52e3883c9b1a0eaf60bc61ec 1900841d34f0df254a39a2d586c69ea435e108c903e9dada712075752da3c470 72fba31c4645db0e3fdfd6c4bd4bec66dccda0e3b1f39ca0963dd6ca237eed10 00de416b0503948f1eedb67da56b1b6b529f648c69f43bcf1a91bfe88a8c0e15 40b401518efa872876a64431ac7463a297acce71697edbf95bd5a4584385a91f 6300f0d82da691b8d88cfe2e2766f7547cf1f60ffbe70ab984cf1b8946334fd5 fa3eafab921b0a825cbf4841a68094cdae5734aee61725ae8c598ed4f66d43ad 45f89106066fb315ab9004ae5031b1f914599c3b0d9f59cd27ae15c9289dee0d 51 550f2cfe247143d73b8ca8c94230aea263cbdea6941240298a96522a699ef30295e4ac9fa151405a5e545c475d6f6d864d4722d248b5e9fad5500c0c46e8b8085305395183db1f246fae4c0ea40e76be4491e0e5a888415a0b15b2dcbf17b80fb3a3248300cb1d61c8418929ee52227e8dc819d4f5a332db61956e17ad428b0cff00324b1ac30ca7993b73942f9e9dc1b3775414071f066a531ae765e49b250a6c21fa9ca1f051603e0eb0c49d2b1b637a022db29f19cfa983474bd62a0fe901aee7329c23f522f01473f5d764a78589b97f24f06e82acfd38c07d368ba02607e0d0653463b71d8d9d228946999b6487bc271b0f285876705cd02b2032b501086a45fce6019dfd7e8c43db56ef03f298ed1843d8af0b8da285231c65a8e1900dc8a3a2bc427c23b03e1efaba87938fbc06d549b12ed7072cbf9f8c10edcc9c04748044f3a359c9842357ad9150b225764d1296060b68cbe961fbf7e8768ed106efe61d4d2e7703bf1b26ee9d01aef6e0889d5a0a587c82f736e49ec248e8c505abcade97aa5a018b78d3fea96c17f79f6db7e0b9a729646fec2752eb5e9e460f1d540c660f483f26ccf2afb61cca612f85533a0834b523931802fba1bb5bd80635a85a5988bc00ee6b59368bf520703cb69112d61d957e0c044b48228ed06a028b3ffc9e4aad4ec9a02295581c5b6859b6e1c6398cbcdb00b48608be1ce546035d2b98386520fb3fb03bdf36f58ae11423821cb80e18f9073ec7f1ae14f98b0e016d2fb7d6fc2be583fc4271eb65456630b5665d913f5334456d65ffa5425709aa68bcda0225092eae513213c35390aaff684cbd0c2646c3a20415800ebb3f060ef700a8b17e146adfeaae163489f3b738166518c5aa0555c3a2cfbc2a1a020553836ae870433f1c3c0e507d12ee7d80a2d9ff7b2dd0efd78a0a1ae7f788170ccb8b65cccb581c3a0a9391b7a52a2faf7536c3ef816e40ba7c4ea75b688b240a14cc3ab6dbb2209bc81182df55b68623c28293e8888ff25a790ba8daad713a0ad47e978ad935d2be4b07bd281c0ab2a252038d227cf9bcc2d64f4193cfd3b601b0ead5123b91e69b2afc0c85539f7083ab4cbe0a99fe7a414723bcbb7063430687a18661b7fa620de67e978454f87f634cf14a28c684756cef67135d60982706082007a751f92b55a693a77c0e6199cdbbb85e0827348951f9da840d07cc6001c95cf68230c8c6115668e682cc483e76a3af70bc770eb464d3627bc041daa9016ed9ddaa9205295e272bb3b3ef3172b52ce39338929f7f944e5258798249a30b57a3397b680d70ba5ef5d6f30d1a5c829a82d7119a7f80a578a64e1bfb5f85081b82124e8ea116d5bccb8ab41379a52ab317e51ce76506db98f224c138a84508ac7ac7056cc9820db1f5991de300159dc2975ed101345e8e715230b27ee8ae085af51523e604926cb124bb70529238da91a8094ce8ab8d12480e75290b5f4d01c959b8bb60bdacc774764deb71d000e5fcd2bf47f888519e10b5524d15df38090655c1ec3a231268f8ef87929fa92e2362d33e566f7c5046b78518232304bc04909b52c267d5e41e36f998254074c97a56ea2008631156dae267581e93da140d17c03b20f2f53919d896a0b52454bb8e19adf1314f5a9d9ae5aeaa8349d7580fd4c08c1da9209cb9f3a17583af0cffb89c75df70080f6653ddcb20b4b326d308c337636d587f90fd2c0eb13060617a4e16d9ed033bceab9f22bf2697dea10a0ff1a186837eff11209cbc4de5b035274f907ef87d5b8e6f1b3adc9eb8fdf8200aa04a2c0d28000e0feadff43a9ad985f0b8e16a124e4993254ee22869ded70f0044e26562145d155ef60f77aced604aad361b8eb573f7c504398b83ac25b25c0d6ec98c238860462d488e8369ab2a737835d476dc3e7b7f811d04858a9f346c0ded28c9ab941d91f81abf983fccc22841db7c0171e40b8aa59d41b3cc4f618108d7c91b213f6eb2d5c8aebbc41d5c3c2571b3b155cd1f2d85d0c961e7e6d51d0a10a393ad2198fc4407b86de23ded44f86b607f094cba653aed28f6ea4137eb04ab06a5b215940fb4b0547b4e1e416d6925a1d94b58d76b46c31ea3ee082f400c312b0b62b731f6b0ea7880e3f157da73b8f642e34380f064ef776fa49e9fd90972b948a54818660920bcd731cb00880dd6daf963b51b708bb02eede2336f7f07ba366256992311d522ec0c9e5e86c8ec1bc48278e33490670c90daad6970db0177e66a4d09af016837044adfdd519f85393731a9a2e9a570dcee585ebd1b3f002ee2dd1fe11afca75e34f980ef12a9b69c39a5046dc15febb1e53cda653fbc0c0660affe8cc0e6dbce8a1c5f08b1a9ad15b0c25e635c4ad1a59a37120300b60522527f5b4907cbbef7a739cac0edd54cfba16b42ac201fc22b94b9e2848e790ff15b0613a0382ada2cfe671f6929b7bfb032ffec6a4e6f389ebdf8c1167dab0baa5397e4725165e21644189c43e61f95768a1a4cd72cd4a299b6036f5325ba043fb0be698ea3a76126e222f5f656f858bd1c5c3a4fcef55d55a81839072af5044529efb2b8fe57875d426615768435b89da774045cfa7c43ab48256282547b0afbca3cd889d897b42daf38680b5e505bbea6975fd83a5f92c6ceca2c2ad48d04b5be5f14882c82f255d8265238237899a22c4e8d2fbd94ff7e8ec7f7ca12af03c13c28a3a5e94979e158482cf922259c27c96c7d0e3113af8b699a74960ecc09a62cd9c86c313000cbdee1411d69c3d28e12e067ccfbc78514277294a80cc7084680a24893e6ca23c9c43e31c7d3d3817933a029bb236230de0e0b918a44a603069c7cf48ae8432f23a44c75c38161168723e302e9b22c9d7157b7f00ac7970be3eb599d09df2313c0c0bdbcb6bc77e8de48246d7a4598ace9df80e055e96e09b4b6a4a1c826b5876c5965873647b7daa63665058c45dd5ba651a4b518b0270f018c5d10476e7ced2b9f6eebd132b37bf3d2a13a55d338d7c5dcacc72f4dd2087d39621969d2183ba266f22b145758c4d82df8b54c7a2c82135021a8dbfc4c036d4b51f51011b1a51a5a0cebd6a511fce1838d330288d02d0f5149adec4e060ad664500ea6eca23f74fd4063a41ce356c287345a04de842bebe17658de4c33049fbe98bd5bd68ad9d744dba870066d96658384e21c5a27284055c74b40463b0faf29c0dda1106b762c2d4633ac7fe6d55783f563c51807fc1b725d8d5d92450ef05c97a28f49dadd28d260696fc8e3bb4cac4217a5665de8041c0efcda79420f9f58b372437efc4a96afe6a2dcce3e642648a270cae90fa4117e75c605189e027fc84bffbcf3cb6c0304fbdab524f50afde3d0e760a15f82e35eabfff4dcef0595384c3dd73815be1902860070a92f9582c372440e45c4061fae081f1738dc0679214a61bae33a47a1cf4ab43049d271c142b02c4db231d6407d7f047d5c120a099c81deadabf1bbb59ddf3a7b30bca9be16b98c92e28390c5212c188d7196074e00a084bf47f983e4d01cc390e3f0f33d464310e57cbb813a4ce0716b07510b7a319df55fcac89d55f28bef3f33da75314ef9d782c617502694b7d517d7530361aed5ef08203e4ac01aba6fcb8c1404d41f52f8e746a0c91fd8d89f00df810b9ee016de75a61ef80111752a39b413ec940266a9fb120be4512f30a3a622a80d0d8a266c9be3fe8b742ed8d8fe2c54e8eaef06677a754798d6ed807516f9940306264a77c824b064f0ab1a47bbe197bbebfc5e0277dcb54c4415e35338d21e0c933080097a69ba5329e52f9c927c1c143c68e0eac2a3f139b37ce8cfc761be0aafa2a799b8bef98c2aff2de4d30606d031e490851894d9d74b984127734b19024d0058c98d86a530e49c8beeb714ed3197eb09eae8bd8b9fcfc0d6cf74b11300a1d043ba357927ff94392bf01e60e021a540f962afb1141902858efb36877c0c7eb33b1e0851b354f5cfbcc0d561ebc9cc53a443ba6240cb15fd7d56ade3130032f5038d8529d014d10eebf3e3cd57e23a0da2d672b3556b10fd89c1cc37ef0c6b6181e3dd4fea0d276084744e53bba3e68b81f851d1d9e5bd7130d3579faa0d977c914c6aeaff3354a6a197057b6737c757533ecd9b7f0142e097304c014a04ffdce71633d8f8bc0547a3ead1cfd5e16e23767079cf80b12fde1348b586430d6b207f71b66bf200a9dd7f4c9d16293500c8a967242beb8952a2932f2baef20772b02152f6baf2cfb847e1d311bfdde2da511d9e27f84ce338fe73e70f16fe030893af010bc2b1449b316f28e0f7918f5946d561188fe264a131b06faed5750f90aa4ff1d6bcf0ce5ff9347ef0b4fb53d8df66bd4cbbc0072fce0b9193b2560908077e7b9ee0a18011947ee0a1143b87ec52c87d418b909a7ce5f11e0d3e410e8104337d687c3b53d3eb821d6c7065cca45f358739a7adb4f8b99fb4d40b6c0c833581c60fdf04bd10a03dfeecd68511da41456941672a447ffacd7c75651d020553f976558cb338977e0aa2a1b26a722357dc86fe7381b77cdda3cb164cce0aaff5d0d9e21c46fd188b378b2a9f460cb3db1d934c18fb75302effe56c8b570eaaa445869dcf7a8c87a38ebceab762648cc3c933ef80ac10d3b1d6317dcad4014858c3a9ff75f2f7528fe81829605845998750e91b9afa5e3476766742eae7093428ad317749322b4fac899e4fac6e1e36ddc42083579bbd7db80b750a94e0054fb39cfef6b40b1ad03fae31f385170143c684c3925d4c25c6e8d0cf2ad8a9012733018daa75a0dfe6dba31d2d5af36833dd33521219c0e5fd921ce6b728af096284cdaff9e192b9ad120192f0a628f8f399438ef6275542a30681622eddbd0f19d08b98ee131d1303ec5637996f5b83f0e3748b84fdf5bbaf7d3f911a60fd06f64db90d5228769ecec72c4301a7b1f68ef14e0f6533d8e2f4e460d2cbb79a0a8512b7a6ce9991355b53fedc05b1c696a10bb0c69fa99a287de4243e0ec8490322c214baccd20bc146fbf5f8e5ee85db2afc2d8b834bd2b086e28632988356058790993c85d636c00f1512a80eab31eaf1bf0fd481ed8a9b8f5945b04289860a42f561b24ce53793d69934a0fbe93a837e18f4041ec6e38b620db9f7dbe4ea0a408d4187eb198a3eb31cfcf7d20f1446f78a412538ebdc74c9174ffe99f2180eb179a255caa1fcd072bcc938a17024e799be4276fb9964e60aa9d4e465a0e20b58eee935f84c3e2abf731bd6968a39bba4af52fb30f8b4129f187bfcbe9a4107986c5acf2327597eedcab62924bea6087aaa162807b77f73f1271f338571f703baece5d2c84b9ce9effa23f40c6562933a9e63d4aefa71bac4b201f1229ce80905ea987f725f3818cf3112cd7ccd835059932337fb688feec3e24fe9160cee0360122164528078155d3473196d63da43da105a3edb8dd56126f5c00407290e0600d511250ee64f9308ff23d92bbf720e16cb8099cc1b414293625ec06edc6309c4a519ad35ac88bd3dbc3e704614d8582d0fb0bef4533cfc15127d8cda67590155cf69ed41aaf9a71dbf83545991766cd7d68e47368f7e20af227106f1bf2b0216a8e199f9f0fa3067d9387e0c5399f0bb6e6bec51749d489a6489d8de4e360df1cc51722fcd8fa18775e05b9a5793961fe0db7b5826278aa91ddfbe15ecfc0864cb0b50dd8991b554bbfb029c72b0fabce898943c603d50eda6270bbdab7d0bbc2cadea95f67911aab0e151cef5de98ef9f0e3696b52926f26b24e2fa9be40cc1cb5e8b2114b38421e53d083fa62d7bc9bdb8be7b17bd8323685628caa53005c93d4f4a0daff10d166df97bcb632b9ba2a234df630792002aace248971eba0144275a3e15b7fb41ef51365a635231291e4b6ff2ade0b4123c99555f644351003ba557cd4d0b47cf8a1bb91378e0fe2c90c680d812816b46aaf6f8ca7456bb0599f4a76cfefc5cc954534fb0eb1a2bfb6ccc719099c669c49bf02ce660e0b90ffef7308ee778a7a4acd9f561e983417123ab7eb62f97f4b89d48f6150420850eebe38a49dbace14c90e531d837d994697023678c5d6ebcc49e1715cf03dfbd0bedb26f477e970356e58d4b5ac533ea479b0668d19c4e6a39b9fdcc709063e60e1b16a9604a70fc71afe4b33177c372085663a941a6c6f6077e5e521be105fb09d5fe92b1650cb1d8cad7ebd2df6a5993fb236a080d38b6398f82e36ab01c28005392a00ff0423fceca664a23b529de58994426b98eb259e49aa85435b392f50c2ca96a3142fe083696ba54979a168cac9a9e89a254c8ac610c938bb897050e0a5c7808e94dd1867a34d2222e6797f053b1ba32c4157c0f040ee2b46b19c9d80f5bdc8788bb88c3ddd5975ace0881d39fb23ded2300c62b0bf2793a36fd92e300adbe3b7958dc71bb07a18efd4a939ee3b65d16129777bab2db1f9575d126a707b398971b3afe8fb5d8e4aa830bf7ebd7348155fdd7ea62d0c4e1d21ad810950eac247cd29ee894e2061cbd3113465d2ae91052b61499cbfbc75622157b9d200487aee91a452d767553fd1eedb11027c612e2494b23a1a52d52e91fc4b8fd8d0492c0dac6c0b1d67dcb28385a8cd72e85b5919d1728293ee29e711d60bfc7c400ce7c2a0cb0ae9e4093d11955007dafd6ce1eadeb1a24377c830bce37036636069d93925aa38f2a6d8b6f1f48f999842010f5e01a395726c9e5734866e71ae004d444a58acabca849265f18f749a967b7fc17e56a49e46dd3253f5bb16cd3bd0ca6fe23661851068f0f4fe15f998e2ba86857bbb451caac8387f77effffb22a0caed422b23792a5bdd681bd97283c2b59df097b7fa4ceb89df1ff0ea7a1de080d1ac6122ea8130cf9d5b4ee15cf3ac689fd019ae9a0500cd6d7b17ef8d8215d00b0a40d2d85288f0aa3c94caba8deb695c4dbd6066daf8eeeff9081e262e3640eaa5aab602329b4c7a42aabf380eb804fd56dc475d58cf9f6eb6106582569c80719ae734362b450fbd0d51740fe2c44f871cb7221b9a9b6a7a4f281a2a28fc60345e9850557bdac3a93fab7f302106ad2ed2cd0e4717c79456b69865959f98b094331860bbf05393e18d43038446c185b728480035e1ad29652eb35dda43b330b361b63f34847448c5db957bede36c009115bbe7151b8ce5c7b7a72bea3b9a2042e0a907d9137581f3341b77a92b4089b01031097f40b1e23db8818686e1d6a0c827e44ed159fffdc44b65cf56509cb539bef77ffd8bedbbb0fa8f2cc846385001ef1adc1bc5fe6cd7f31b7409b3b07b40ee67b02f2c90d8de7c4dba372065104df9a1666c09d7bfd08b14a21f7cfb758137e296386ea1ed73eee68fd359f1e03cf94507002645e17c60182ae3462d44a9d9aa522156d7c2173d6731bcdcd3e0a17ef4c8ceabb347fd59001815fd3cec24005cb9aeca0a24bcf16b5b799c14d0747aa7485aab69c7914d40e765b7296556b470feea7e497b32e26387a6134fb01f170aa9899aa178219359b0d182e14cff5f7fdd3810b8f17fdc4c88a15364a0db47dba15577acf0e1d01e9f45029364d224bb671a616398f9c101855991a4604547649a901b4006a34f5b46321a2f6ee5f2df205c3f957414e39604b9272380760f39f1a44f9beafc65a88c853c0c9ec755dd9dd0eadb572d00e994a48e95a04d95caf2b6416bb39dbeb4ca5165d6b7a6578d96f13d922c1a3801c03cfc5e30cea4c8371ce829a4ca30966653469bd488f890e297a3c50087f07e9532a8eda0cd2957b1f99f00cd63dc7eeed770a51912350d65c58013d159125bc2f350413047bd081ef106e72c2f19538c9b7bb0202800bf3302d9cc095da9021d5836eb20ae09678c6286e175d47fafa72f5d04fd5833415510d8994a41037084e99f7eb01942be52177cbe5938cca162d353d5531c612be695f341b69458f04e6f277360cda48b874dd0f216161c87af81f450c42d3118f9734a61c30c0f73fa572ddfd099feb99360e6b20c8ff24609393b6b825132b67df31cc042e0f7290ee727f4802ef838bbeac63fad050ae612dc8d7f5ee20a0dae75dc43cba61d88f19c6e1fa0eda384f429d11996ef2a7e669ebe126593d4efd86e83d1591a3fddaa42544f2025d0f33e31240ccd925cf1985abc614ba50ec49430e89daff56640ac587f3420686af1ced9944741c869ba7ea50cd6bf22ac3a1647f015d471aee150fdfc05604d726cf0acd5e84a59b168b20ba2a7994b778fe5affca0322ae2a6111bca20201dec905b7d3317b33319cbe00d4718c64db3a11d6f365ef311816936ca3052d0716b57c354fee3c06d90eed59577bee10758538e4ce2a323a09446811dbe02f0c9aaa76595555977fb03073f1d30df66429472749ba11366497ff6a658715f504abe5f5ff5845117efe1057a6c6321c8f851ceae6af9f4641c0e965cdd5970005d32a920722b2da3b8ae5d178f5d3fdc5697543934d7be637d52aee1e06ddbc0a6aa682c560baae8de3ed965a5ab9d8dd337f60c9e577db9bba0f1e6f7a87a204cdb74687b04c7dddbdf079d29b92cb3d21182bff1d83fbb72b54ae7a598d44023e25e1abbedac7a2dc20c303b29d931ac18d80bed543803d65dd469febd9900a12ca20491c6c1c6925f70accfc25481f1ab619ca358a2ff8aeb0ddd7c465890244ab0eeb0b4b6ff35c0a198d25b679dc8000e15a098d02ad71dfa42b39839607213b35cd7d28f47b0d15eec12c1d1d6e0cffadad7ea636834f244e954079860985b1cb9aaf8465729623250c669c481737411bf4ae4c9eadb78355c6f976ba0d4d5cc6d696186780bc7f53941d7fc6c50715c4c975ba2d414ed065db028fbd0e136dc631d7a2f9419be922277cfa8a99444ec946f071899dd973340954612b08ba99d140aa2b3b0ebffe0e0858157b33fa8aa635d1120cd5b4f091b2f7d4d70d752d34ea69b42f9c24f8e20db8f8b48d6018fa3c1f68e82945c3d2d7c75c4001ac6070e9f37649995d18f823f2a387910959c7e4b45b52f20960f42ff335f40f6b29eca81894b8327dc340d2e349f3b89ac3d81b899f4b3c871f8dedf0d32103eb819e999fb0d90a75d71b9dc4fbc7fd9c8091dfd0dd9ac9e0f26e39dc9b280ff60fd6702c6dd246e21c7c0bf8edc4c2875cc3d0fbe5cb880ed1f4a95b8c3401a16b811bda412dab1d3a0ebac89c0c63b2e686ff274e3ed11fb81e5a8c817e0536e5088246a51c1888ab3396623933240e1e51b332d8162cd39c3414fddc3509ae1d46107d16e66db727d4e6833c9bc37b41518131ce274a20b2919c36ba0007dad9f262c3915c174d286808d9d69df6db283fbd916b4984d986ecef6cc24708893ae279bfb5346570e0903df8893b08d81e6c08072d6fcd1b5e1201c652fe027302b5121880483d2dc87365af6ebcd76096419116c79ef3323b43176913450fbb1260896e75a0be1d17801a8bdd6d8bcbbe0d2bbae720e384b728aac4f2970cfd590820118787936bbdcceaed78df2e8736628545804baf900780de46c09b0e66b035d6f5b5e6d185ddaf2919963447c18ac502837d5b4f51c6ed68bbd3bd0799589499c41e62779817ea25f19561e02082754e88c931c50c24f61869e5e101ea4b9ff34272e508cab3c9c07cd7b800883c33a065f2ce490bdf12ff3342400efd68d22c3e83a43303daa633b9b6500ebf8e42d3d58d1723bf72bd98294310077514f10278cca3f2caa7a8d4d2451502e598f37332da1c9bf86805f422d5bd08d97c2a12c7a72a5516962d966ff44a5b45c1b12bbf6da474813504d1edc693062fd1551b84bf4ad7e7b2ce18892905b5fdec551d38b0837f55caa56910c5cb0327188e15872b48970d75661c5b76f7d0f07dfce3fae5a7d28417d0648d383d097bdf15b78995995f581cfbe9fabd1fd7097a27c2d15e980d1e2bf6d70ccc5b089ad000145a4c0f78a1667258e695cc3b46f82c596f9807f81d1343d787001f0c3343dfed759eb42e66164dc0bb494d99b55a8748e1886cef1e47b15af0a6ed0b69aee2ad1511f8b1ef1d688fea65238939dcbb397c8f2fef42c896ffcef95907b5e101af3cca741d52a6f2807266ebef644b9b7396652c2cd6ae773795c4ec0a852ec1b9be565a37bba45219f3b06e8a0b00a8cf0503a25297068e9840c4f509d21c4ef0b03c08f3f8117f4fbf703a60b8be2a75736cf387f33dc4655bb571094007359e8ba6d1e3c0d8053086587e01a735339b7d2dfcf466177faa64c19e0410eea74d493684b06c376e695ecbf7e04ea14f5f0c046307d874228259254a047bb1263e30ea1fa1f8d89b1178e83941e192350f8284aa75b38c3541ba0097094ef1d1e002adffe4e4fe29cd2f56845e6cd3c11e4ecdeaa96effb41852de400f1bd2e9a712e7cfc601cf62051ecac58d86dada2acfe7e789b511e840883e55064e2bb20c115e6a5166f9e879e83ff1f16161ecdc82c233f9f9e93c1d3463010b2154a51d4cbfbbeeef4c0eedca5c73379adb1d743c5ba66b28dfd7d6f8691405581650bea1b09f5e9eb95484eb2358392d43e0afeb1b8cab2422e8212f09700a84fafdc7bb6c33557620356d4890c925470e30f31e7cc431fa72e5f39e03f604cb21362b3a19e9e4b85700323fbdbdbe2111aed6cdab45d805ceb8c715c35507b141bb3e093c69f9de6212822dbb5318e02eb40a171cbbf949e31407b5c9ee04d1a483e85fbda27a92287d85a52490c3eb86718f139837c060f802a3c4b807064c25bf40a9e047f826d1f4af5fff76d04bfa99a54ced5d80cf8d28c73a181c0ba3f4aa59a28a38b387ebb46e2b7b94e8c960446891445b54aa52857c29c47905f41d6c00b711ea92d667e4ee6abf0295f4104527440e4df9b9e238196988c00eae5517d7f41723ac9eac1647d02b500db7e7eb60d5612e2e89173562133cd80959314f95ade28704cb9cc63c8967354789581142611b8a63421a56bece799705b929bdf292b065015b4f6b6e582a29a4f175a13ad69ef897ea2012fe2b7c3e02009be466bb14c8a39af33edfd6ca5907a2888c0b8d8e5e1b99857060fd4e74053375370318927df8608de41b6f37416ad920e8813f4dcb47f01339557f986402451207edb5b442248aa34ca5c4946bbbd1ff93bf51b9001f0d735a0c4857880deec9b59ff810cc193b8ed503f8b8d5697f2d736030e61cd40cd1cba00aee4102eaffecaf7f49e224a3425ca9cd850c3fb71a1dafcd52a948eb0e3dc57bd0510c1ed101d7d6dc0ee5116ce9ae3ec0734826cfa6f9ff8271248c72acb807072906f90ce457871f922b8d74c95ae7cc6ac98ed610f65fa986b5d49523e4f31e1b019cef1ca0f8219ebaea071b116fbf8c1d38c239de5341fe9f899420d777183309020d86a19d9dfd2fb0caddb266c8e7d9f3207267405e554df1b33dfd519ae400d05c70332278841d8d62d554ab9e43db5bf634c0aba75047fdf8f11bb40443026107eb3c7e401ebb07d3b298e8d335e5fa84f8d835495521f044fb2927a625068216ba33efe82b36f6bdc29b1acef4d7b999887cd5d944d639cbbc3b38eacc01508e8bccf0be4687ff8b58098a87ae2b1978960378ba23e6a0052fd105f0f403ce969dc2be880f589bcaef738cc90722883c2b0c48556f14b85b9a14542f97081cd63c3545928a261ebb19757b0a57cf4b3667c2702b96649eb2d9d18e8c8209e96a4c23263c3b51033f733f540d4da59c9ea30e1f9724c745b7ab421d63a10dac08488ae51975071cb8c4ae6df0553fa349d62e5a7eba57912979f4efc3050f33ba087decab2a48d22a1f26bb48467fdf54eb986fab3e74270c0d89bcae0502c32cf0a88992ab7bd11184b638de5b1dec393d0fe0121f31216fc26ffadd17050d76fcdb239d02b2e70e5954cb19ecbb84f422e583a81868c63a2b13b782d7064c506f463adc2809de72e51cd718fe686e17e30fedb13481318d739d19fd260173a5cd8a3d00742e3653150bcf677800bed17ee6b2e1a63903ec7959b5a1f30b9b9ce010dce7908da3ebbc3c1ec8c4a1003bf4e21eb779a42f5d03e04b934704d1e9eb5ee8dcf795cc8a13376c96fc4294d8647af67f590abc4a18955e5c71078d918556d56b9b07a00e435b9647021a9264bfa93092fd76857529772f87a307fb93efa2190e897f97880d259697c22e8cb8a5880f1408a299ccf3368854b709e9118c03384911690a5a0bfb49364b2401fd306eab29e0804e6b28e03852f408c9247325ef760ecbb6e2cf29f4cdd1112c7188ce37803cd9cde6e1ba3c26850a7c11ff91063972535830d78907bc5d8ee2f1ccd53179cab41870cf1959861d03c1a76b3b7106e8232f842327f7836e52bd59c45f260a81576f67cb875e5b1601822a2927fe05f67c48d029d01fec72ff9ea3709c7c117659d8b168d22abf0600133bcf37195ceff135d7503da655409949cff3f3b6c80e3c73fb533d618dd30c15cec98d5abade4d78b4761efc4b608f1db13d243d94431abc8988269d3a28047a4b33e8f7fb7cf3b038208d986743ba37eaaa41e3ad9c22c59998f2b23abe0f5f741dce25dfde2e8fb69a3f11d51efe4f3217586b42eff8e1a8969e473a6f09ed6090ebc709ad61783d512c80d51d08e1e701b26aa2e152a55020518ba7330653d5893d0b43c18bff7ad05fe3655c8895c5c9d3184d5ab221699b81fa875209b3cacc6685ac2aab99df5fa3f53fb439fd294a2599b2a12a8c4a6548bbba8801835671a3a21d39dfb6323d8af9cbb3c44bbc7559f9946e7f4103d7b0a9605a051e76976d328ab3dc2ce4a5a1350e80db20826b285f2dfae02f969c020b59a60771a85eeae68b12e65a7c1bb9647c34587145143fc3a5b505d140261f48de2f07910f8fb905b22379217907253ddb8632299b57aba1197c910b47cc4551b13c063df05e049efde3f7516f100f441003159cc23d0deb5b79b456d07a4a80652d08f05db319131f5ba0f54f9c083e445ade70fd3785ebf31b3e651af7aebf9f1e020e88d404416c567e1345dbe50ce213ae900719dfb0a4737999432a01fe8c9f0e12227668445d56215fbe2521780a07c2e33a16adaa6a77c13c74c5cfcc4a42005697d8aacec53ffb0b85ecac45fce1330bd8bc4899fa91cc88e1a1caa223b2031fac5120d7bc8aed9c1e59d52ae28239aca69d6cd52c3950715e27695db8980ab38afe5ab51a4252b157c3ffe7c6bd2b75b8c93aa80c2c733920b2ca6d52320248483f109d327f79d4e78d5b1d6952efe147979c5e73a15af1bc6789fbf4b80c9cc7c364013dbe522cc37f8e86df62dec8e4a12d80b5ea89cf8f45569a54c50e385651561acd3eddafa2db494d257b66bce2be2feeb5ef0cbd74aa0c550ca70f1d51e324c4987c8895ec75046756eb8cf7d59f2d8ed32a247edaf432ac7d5e03baeb9ddd615057e6b863d453b00c1a617bcd4d9340c196b496bf39506ff7b602586b6466a92ea148e4910f7a106c002277da66f3c2e2e88cd816bbecc6aab20274f248fc73f02d3dd2efcafdf2309c24132f231949ef3555049be4f08dbafb0eaed210c99cdd6648ebe093a93ad20cab93dadb8246b096f32eb2516f6a89ab091595cfdcb3f252108e1271d8f6ebbe0ea5277047a9c4f666599fa31a1e8f3104ebe636221d96653821f54b1d745a1e448cf61f6acf62bf22592f6523eb0c900e46b0547622d76d8481585cf909c4e04c2e2850f3915ca7946984a21b180cae0c1402d001350e4c08d67e239b8b3515dcb1bdda1e1df691f38e6132cb9e80fc0bf81dcc709c7e29b01b4a1ee43ad9f24c11cc804f26c133bfda04f1eafb16c60ce7f9ea345fbea54f7397466cdea5814fa843dd372d30ac49393b9cc74d3f3b0ecef4bd90217b8c231ad0462c29387b039529033130ba34279986de7e5489640354ba38d1bea2f146684424bce21e4006be1c1cbad51e889a94ff5c37992f7b03c0a898f1f2c0976b16359339b27e0ad286d3da23337c49d79d8305bea06ff40b56c250391317c0ad3dea1f3be23be5bac9ed6ade9e8c75df7659a3a00b1c1d0f7b013fb839d66ef102174096fec84c50af0362ad372e4423915d36f3d812e808a2467598e952e516a29e16e92f1cd6ec18e57523fc2d4b70a0552d1f46cfe70e403517d598eb3d1a20b87c03a909bbe9ff5f233c88c0124e7ad7a4d2ff7e4005590cb064f53e5f892504049716f98d846fdb1bcbef0c61f83732f7820f7f21048f6ae1a3a4450b897397569222ffc2893d4fa280d45d23e2027c8f6314b0080d733dd234e58e67b4a31b5324d7033672a19620eee270e85d6a0eae3b921f0d01582151e29a844d0cdf6c1da9023c4941b189ca2c049a69ceb8a868837cbf5c0cc90361e66c6c1b0ef7df5fdef097d5a447c0e471f145d29b43bfeaf66f0509049ce9619ec2ff8b7b457f6af9ee79a9cb07033bb6ca1da962c2d6b678f7065b051e0147e5ef60e9aaf51b8cee66580daf2c69c67a9744741fe6e96c19195b0e0c99d0f070a45dbd0af6bfa3bbd210e50d2382d858f9144104942272321bdc5a0ee42e5d9315ebe848c16ffd85dc464194bdfc0f09278aed72beac0e8ec1940505cfd3d874594f4ac636fbe6729014f239e43b471a3ae3012debfc944a8fc0780142daeac8f8cbab98058f94d97a5f000634c7d77d797c4fbb23eec8747b1d8e04cec159026526333304c9a869c5360bfa1532f4b2b658a269cb56da17da943204c43e3583fc9c6785b4fdce469c32ff433da659f91ecff57c9c207151bf36fe0a06de682d18630614b99c15c3ea1347c293b8f183f7ae3e009e88d2fda0109f0f54b80b9a2df089c1d0c6a5494e6044c5003fee21ef217c8d802e1b6310cf6601611d8ffed3ec3a29c786b5bce3bc8e4d3d975dc674fa1f17c15180f5148b6a0121082e9d9b30aeb18a4058c2ecefce3f3e9631d5e93099c9d47f87f374630d0b29526cc2a15c76fbbe774d26f0ed70b86e7ff67463e3204ec8a482ae4dbe2309cdd5efc4fd6284c76481b8e7365a4438b0d9463b8163411962a12ee301d9020d5b31d8d17a3252d70fd56159cbbe3cf5145c1e7e4659098ec58ad38fbfc1770173db35636560e3f7fb12b6785f62289c3f2aeeb81937823cdff2abd377c9540ed38c1e0983cafe1c81314f3ed8445aea70d354127b17fd6ca0598ea50808b907c0ee41e6bc76831017fcea66103f153666aaabffc496084a43417b0c3a84630f3b97ed8847d94f5b8053dc3c00acffa1544aad18b4fd56c78b3c9949990bf201 -generate_ring_signature 23427a37b63e16df40a94a569475e086585f88042e3c6933cf1c7c089b041a45 a680bcc8da17f610deaae851e49a1153a41cf2a0e7b4df452b0cb0e06fed4fc5 27 76ef12c44e822d190d8591a0606a6246e3e339c3c0d09a3e4ef9b9f3e537c783 dfd8e238c9d58b0b26de9d6d577cb9ee7fb353d5e624577d8a7089dc7ba75c2c 75d01aa0ad629f58acb073ef222e20cf3ed9cc497ca0c0faed5328da617201eb 039651d4977f68975edd0044b8c69aef742b79b553550bbb89d03996940f6a65 2e20014f619c3253a8ef76ada8eb6b6a90b48d80a0442afb5c49bc677ca30633 b6172170bbe84ae154fc5815d4736578dd9d30e1e0436501dd36b09da27bfa7e 8cb4fd174df4dc7db427d121a19bf938b4e8aaad7830e9e638f653ef0011ab54 049bb382150f20b7205ee71165393d59fd4cc0d1a690a088387f8039867f5b08 a3ea8ea364079b4a02debc3fdf1b6d7a3791981efb1688a876b97008d3aa27a9 ffa5fa37dceb7570f33e6c757291119270ac62a9caf79c61a1f73347996b42cd f3d0898f92b979728369d0d9abe73aa690292800f3e4efb66de9544e95fd11b1 29291a457166cc60ec27368846b57c40876d1f573ec9af3f0adf44e478c1d561 195ea8899ba4e879cbbdcb3946d8158b0db04d9f147a07342e73089a7aaf5c53 0cfc96a760e8bba3e0a54bd8f64868fb7230f025603bc1d7517d5238f309223e 0beb14a39881918f54137e99f016277f66d022faf43dd0a4312de3611ef62167 87e660091dfe3e75636c7dd731a7aceef1aa6509a4ed0a5d9dd70b5ff02fbba5 4e1dac7838a601b8bf319f75d333a2488feb652d3f2c1610fb24bb66b5dbd727 6e2959ddd5b086f020527fb71362b3d902b030a27a873654c22794471312ee44 2c75319035311b2f58593503dc6f6f0f5c9d6a5b414586818f48452f5e7846e5 f204e336a2710b43975568558f6845fc099637b05cc8921e0557ef5121672e06 83210f8e7869415f49bb722f02ecca7b1a39aa5cb90ee5f62015c26b5aa7e23a 3ccbee824b4d6ba42ed29e238af0d36fb4213986ce70582e2b52e8e519b23c1c e42edb639429562afb90c78af73c0966e4a38f892a13e29c778af7febd30267f 1bb904406811cbe96212e0b34bea451f8fc119a7559e7bfe57eca21b43eb55c1 8414918482c2104b258f9095e099492c5da1aab97173d21dac8c083206ab739d 65bc67958d05c81c80d48855041e321e1e74aec3006c2cbdf0d9c6adc0549271 12fd3cd5de5c0cea07d92c01871687c5dabee74bd383fe58a0721e5c0658127b e3bdd2c25f7b73bd7570bb5c6d3dc6469dac206a4483a6d8dc173bd2b23a6f05 2 3f529b5044beb9d23a55096ed9d7865435c1024abd2ca87dc213e1dc7807af01193f09b542b30aa3f4edf5bcca516f05c8ae00943a413bf8c2c5845a9dd5a70d16576f2c229c8e8d8a7a38e317b72adc83c1d53bb9c39af06addcf33b297ff02756b9e69cdebaf6a035d79a9f06370aa8c86d549109c642b418245f097e20b04a8b61b81fe20f7449bf4b10832219df14ec26a958c0171e67ca6613ed9bfa70eeb807c0910459e5d971dcb852004fc62609b47833922fcc411bc46bedea61804ee4ae28ac9c73f16e24e95d3cc2ad92e79fe02be99a7b66ac7c19fa8f4873000e2591eda2565967f65f23cfc082d5c26a1ae09927aea39467ed67e53200bef0318792d9432d39360f2b267422a9dd6f2bb38a971d905ecd0c548647a532ffe0c147a0cbeb3b7109b3df7fb487636e58826dfea0b4f100cea7b8a7b797eb6e204800445d108e4b2cb3d750294989de215a9f801db9e13141bdb7066178de30b00f54c66e912f66fe472a06c106f1d9d581edb74b02d51a780fcf4ffed6daae0055d3944393edca64e8ea3afe95b640957398153348bf55c94c03ab1c6105f950a6028cf6d69ebd747f4ad241ad908d54eb83544276a0a8a3143803b89bd2cc80a00959bda8845088916105ba8dd1b7627601d43533bb3890bf85e41463055230829a5b5a1245a0b1e944adedc436e254be2366ec5e76d2d4b9318a86b5f7f490da0bc882d1d13477d11d17c91f7b63cebb1fb10bc92967014bd16c8a5965e5f08dc5f2369ce95b34d6c8d2d2d25b2f7f75b03c41fb002307a906d29610931ac03c4b800978d38de16cc23ab92d4caa800b2add89cb119d0a7194d50d1ef5287003c4fccbdcdeb8176dbbc1e964e8d6bf9a9be4401c1cf0072c2de2e9515d6f700a78d470677986c418e43dfc6f0f08245d3b8c301a28044c418625fb06ca4bd0472bd0fd4b01137217866b2f4d5273444ffa94b1c43e156add2dc3bc22546f903cd80d6a9e05548c4672e70a93a1a797c6015358efeebb6807d283ff856204705f428a3a06a011e07c8daeccd0fd63373b437611e457094f7b2d13172374ac70a8161f389fbb6421bea26b092a4bf8a3b9b888eb47ba82ef780358efac8503307a7834cc6e376a78c35ab7133f1e482b4c4d4effae5facf4a9838d89c072d7e00f4b7effda8e257ac2eeb46ea82dc6396d52ed9607504ff6b852432f318a83e0bcde26e122971c7dd9d92a1690ce70b5aa7b947645a49dd3262bd2c1d988c3f092f61bf555795d4dbb539ef593b3c2f5ccae19087a9f0cad6a47d70fbed6d5a0fec7f88d6652c529835167095c69be53ad2224e3b28369bbe3ab42045398fa70738b9f0756d9b0beede437616e33d65b9cc09f306d6983737d5e62491e0a1090ac852e6c83f13dca5d4a9e08c76d82f774760352ada589ee0a9bbcb756ee71701a02dc3df690218e664ebfeec6b782fd06376edc57d10513676b4054cfbd08801135356067624bb2030cd2f644616e5526bef25df44b8e3b573b0c2603b514d063e7d5fb0170fae65aa37be832ed397206f333e76094a44e7be4ae4f14a175a02163fbb4363f672b2e47628d86355363660a02c02a0d1f7ffcd496126451c0d017cafd06bdda34dc028d834d77c6e7ea508f1720b360c86fa296f37330548920b48482c0594a8cc8f0db2d250d1d1a95c11f27ab5a61099b7a949490db45fd90f677bc646723f405f29076ddc98c3a8f40e1c82f85d3ca5565de539baff9cd50f0c9c0cc6c764dc1657defcfb6ff11b86e483ab4a46507f08af763dd40fb4bf0aea5ca36c9750a32814f5d3df4a27e6b14e8155675e593785f25efb2d4db44b0e71a2f888b1c0d2808db436ed38b9d8d564e8bcfa2c7274dba60a02f495c9c101294d74260d8b51569d7ec2c49903e8c6904078b324dded75463a1e285a95510c56d30bfafad9b6a184ef93147cece263b21542f048415f8867a580d8a02b1300b9c1fe225cf0ca30b89d0c03d118e46f91f513356976a89df306a988aa96cc055d1a221eaf3a00fe25989d14dc40ebdf6cfa48bc50fe8c676a9380147d7ea70387287c180bddb6ced712597189b093966ed73589fd9de75c8872069deeedf000e7e68164c5d5dc4ef5c8e052e86617e198c9d90eb775d7a91978a035c2873c0c1a5f94708028ff566de96fe461dc7ed5e537eda47e8365ae8245a6a2bc4fcc08492f2dc757db6b2dd42bb80550371202d9a293d9ea1d966efadc35d2d4f7370e33c9d6685c207a5e11cba02bfd5b45970d76fdaed73ef87e7e52575e17693f09d0fa58d03cb64798a267b6ca4fe130c967674224a2ef5af6db8e2fbb8cb0470c2e7e8d73ecdbbcb32f187272690e238b48c5607639fd05f0f44e2a7f59adab0e9ed38ad638b8cd5161a7acae3e9c4876d8b00750664a663d1df480538e1d160f -generate_ring_signature 4a79e4858cf84189b1a787a39042ea6be11532c2bc4c1e87937546cf467d05d1 e6e7e9b18970c931eda06ce590197f03131062d3d1b5a6ad71ca1e5abcd18e3d 12 2fb5a4364780ab0fac68569071652025fd8b48e74aa242c27adef75f375d94e4 3c46616f02f3b6d9fcc70f74f9319547b6114a4b2af80da69a665b9edaf6a4d9 1c4d1f6b0f21a6b2a975e2a76e7c4c735bcad9430ae693d69b99db3623944c1c 2be94122483ecf69df0dd4920519ea1ce71af7036f03e27466ba7272421deaac 8eb99f028055ca92189f78726acd9b93ab452227084fe718ac4dab9e8f4389dc 226f4f356c64efa694b8311ad07d4ed444d940d98a54920d2d1f9fa687cf20a8 4bbfe2a4a7b779fa5336295fff9be27b165d9a01920c3fc3ff28d4861997c3a9 3c50a93bcc8b0ac7cb7904cb370d850c81750e2de67ac9d4a769f551bd28727c fa5880974ca82b96b3b64d419674cc7efba182815d23f8424e7e354cc3e63dc4 710410134c629f3565f3706878f34c8b4b049625d520c4efe0b8d0ff9ee02fe7 b0d02c0f6de3ec3774101beb260500d636a2a48c5be06472d17723377f82e0c9 7fc89baf0a1f51aec3e249259b8f22194c406956d27410ce5ffebca081fdca89 1d8156cb422b95597ac3b4ae844934b8e729b09dc95d288c4826fb2b3b8cc90f 4 613856b2ca411b309d246c66c23a061fdd5a61694a4d7e3151c5289c77d51b0a49dd2b84dca274f08d870e857b375837b6c00e269d73c73e20393bc45fb5fa058edeeaf8585e261c854675d89852599914862f451867ea48852c5bf87757b40b955eb8a953b2a9180795f69485e0eedc9ef69d534d7aee0d38878f69be585404defa08da1eb84e80ceb58623ac4ca7a6de61a786080162ae2a8e134c942b5b0f3a79729276cd16a02aa859369b5cf79911d123067b456247ae1c1cbe06bb990424a406104bf2557d86f6238dae70a5b6096fd81581bb7727df228adbfe885605b2f03ed1ff9b3847c77ba6b73eb273751c0e01975d52b04d3b5f05d965cd410df83232ccbc1db1b5b318d533ce38084c8ddf4de67cd594a9e3ea0ddf997979063839c830af8632ad08e652b180e15cdcaa5e115f12337a3e00802ac8bb12720f4eff8ee200f61047ca8575dfa779f6facc4f74ad75d1efaf171f9c004afb460740ebb29de09dceacbce81b590061e213e62d2dfe4761bf97ed9d7ccc2391d803ccc58e5aa54cb8641209ed899b1913d9b692142d7f45632915000ce507874d0b3bf38e7e7034c8e60975fb6bcfa2e0882c8681e62859acdd5c339dd27f664003b33d730635b7a262e5c97dabdaf00753925ee57920f83582e93fefd1d5073205e610d05cf7cb3c32af73feaece4a84596feafe08c714d8c24bd7bc1e436d710492790bb7320a56df42f165e47891fbd10a804a9278266c260e1c348cfa5747098c0f37d780402e08638c7fd2a0e0cced7ab579cf7f935d91db49dcd20499ef0a61e9962b7c454e9e8308e9a4ebc0187eb60b00a2fd007ff4ae11c53c29804c013148a67e294e754b2765bc8611df29d95c3fb468e6844f724136dc47bb082d0a453e6a8ee62bcfee6d9602766ffa50497cc4c278e7207d3ed115a132a4999d00139b6725e139131f4bb276f823bb823dfe6be7902caa8f2811fd136362589b00ae178b3160c8256cc7c74100a5c9bd14cd7081862c85cf68f4ad664b6183200516a6f1a8df7d004710a22e2f28816d0ec76a7f8e76639f702690a3bd87653408 -generate_ring_signature b3a73b35af9a583cec3e5ae026c0974460a27f514a1e57863ab5b18303b49bfd e40c3300a1834002a79553eedb269f35f9d7041cb646e3e6db9fca5f153dda0d 10 ebcb749e504392105e194230671d48c40a2122d199dc6ae4e0ba73efba82bdad 7859f6fd20abfa37a3c77079adacf378ca5e510c878c37c588a9646e93fe8388 427f5fbb4eab74be396e86079a6f7efa6cf50d058e9f050686421abf936cb4c1 0d6be5c57e41a58ef7f994a0face6c73c93aede764b54cb3666453d57c2ff4ca 7d0a29ac592eccd5310a9f6ef5cc6ebcfd854b437325c38254981fa83a35e333 67d601df6e64415b9113817e05b525ecde13d8f59020680a700768f9df9ce0ab ca677493bf0e87103de142670672bab6afe534f83fbf59bb7efbead953f2ae79 0146d12aa7dbdf94c4c6c9fba9ed250f5edb2042dc0a6b6d143155f2f5352452 2dbac320da8dc26a2e4483bcd01eae0ad7748c28e4bb6793f182f976f80108ed 87db7f074e179a7998b44b864409980beee78a7ea3befcc7fd1fa697735562bf 35b98eef6f934ddf49deebc1786ae2a7c69d7c061a108ea63be86644aa65510c 1 c134abdd131a057ffeb9bd9138f65ef2aac6f1df3245841c3e253c7744d7ec05e81d092d0aad6d215c4495729db9db88cb41dc8a2ebe480ae5d102a97b90a10ddc7d0e029c4cb4b48960afff2aece493752a03307cda81cd79ae059bd3b2e409b92d68a4142de43b55605df424f59f29c8698e0b8a72f90535a904a163085a038cd6bdcc824ca94bf647b0a37d801bd9bdd35cca242f5a6dcbf4d7df3024d30756cb694ec36c8bdc928e634a6a8ce4121debeb7c97db6dd7641b5d404e5c9e0a0300d423011fcf8367eca32333eca36931efe6f15cb8cb6ce9e2c352189cd50c6b2a1474c267f5f7abf4f49e2284d03c019006a9615bbe11949743eb64bf710f0ac80c7219ed024a9297c882be1087ff02ffbac14b4b2da87ec9ce583ada0e0018a1db64a022e9669b537a4b30ccdcbab69705dc7ae85cbe81009279796fa901cc4b3fc14b24ce61c8c8e7e0921f7ae468611a0dbcaa5c68cbd30a2df1e39b0ce8594d2a8fc7ba0ed48c09550682c648cbe6ca8302a2d16617a6a9bb30bcc201b123a72aef2c024cb24a8ed16a0d839b801b0432c21d6ae0db155f045ad812099355d3a3afe5002a6098010220f31343a446361aadb2788e1b7b49aff354fa0ccede8d1e5d53e011df1242eec4d74c03c5f5eb4685822cbe6a497ba52da04000e9f88ed91565f4fc65b3fbfd8351f82fe4d960e22f71942755cf2d3641271407fa5921ffd803e00d3068bc1fc0941eaaa6685f08552bcd83b8482ba63379ac07087893e4888f32d8f1f618aee2e3c35ea84b5940e5ca3e580d12793981955b0f9975ee6006450b5681c94afbf08be38f518c296f4df53b70e338fb358c1a7302590162dac7eeb32c4eacc6d6c4f4f7749d9c9687c020f8a9ae13a84b77805003 -generate_ring_signature ba2cf253cfce5ac728cc5bdfa9e02621cac271d7d640ef00c7bad3612f7ea07f ebfa9411cd1911793cd8c3c3751fefb1a4f26ca477020409303e36d624ba31f3 5 a8dd3253a8e5d1aed79cd6b19d6f8f006a6f755c8da0b20e2c9187fe203f6a18 f7cadf8be983339ac7aa073402ff1d5152c7db7a2b1ab927aff355d4ccb97538 beb5217ff6e8217cfa07a89e132171eaae685ffc7155e1349bc2ccb6289970da 6f7165dcfd5f3310abed2c531905a5c69b118b2d708ade5721f0a452248e458d 04201b3245cbf0b7225718ecf5aa71db813eb5ea54b21423f93fc9ba202399f0 d5d5570a52159caf96724aafa56bb402e9340bc605d665b4fb283c87f3404306 4 89af7f6a3e191273e7722963de426fc974226463a5e34af4d73a64a258d5490f929ff430f05f9e01197cdb143fb85ed5461fcb8be21eec1872f5bde0fd192c0cddd2c4c12711f5b3968e72e5cd309a22f492eeb13dd8db744bd764a9cf6d10027691aba258214eea546dc949e9c372c30b17ad10a9a56b755915036d09d8e2021f4cba99574d24cd898c297362ed91389cc5b148965934330720809b50cb010c022f36cb9eff3868f43acd5b3af37945c5bc51c61a95c0532fb2cbd59bbe310da48d59c57f620c43eb9f7e2d9e278903978813c3f5b6582eeb7d7790d0a81602b8e30b363626d50390b9afcec243a348535a3515ee78a9d3b81720c93fb75c0a0c26f6d88baf87b10899cb147691d159f731ff3aa72d2d5e7f648231b8caa90668e5a5dfadbf6ca81168d2d5e81fc3f632da23988fa3463feaff17f588c4db0e -generate_ring_signature 07d546720ad955c6ac191f0ea16e5f7d843651501ec655bb7352f0cbfc540cb7 9c58ecdc8162a18d21f31152b55b98c21529b1b918752e05d6440062b320e36b 34 c5de097b79f066a3bae592e76e4f681f9f9cbddf2d1bb9819d8988f12e657b28 3f2e00f51eaf8c766ea0a750a72aa798c3323c630bc6bbf66796d9eb1dcd7814 0108036469ee5180b39ab609a7cb4a4ba3f4c6ee1399f5a5475cd7abf56f6562 c607fb7f081e02725de17473c3358cc3863eebc8306403fc097d8a8cdf56bc5a 358cc0d47937f554bdfd5cad829d6d4c04bd7b4bdeb8138387409f51f5bbd233 c585912932e94cedab2246ef0f35ba86de9ac8816c72f39fac1b74ec849513fa b967097a873c451309dcc10c8a7716802451bcb666e7aef43c23c4886e958f59 edf0437f0789c2f1280f946e027b9e9d3cd7a7450b77c0c29cc2d1a3a4048e59 6e96fcc4fc42ec8113e21380f6e34dbe8a1fc39c8ec605413a6e4ebcef95a5ee 3540744c779e95429aedc594ca3e7f144fb36f2354c82a215ee3921eee58a687 eb13aa3f8418b863153d0ffa0a185060ea881d0bf26ec385511efd7d5af9a9f2 7f6f7a45c10655b51e31b6d8a8d718eb55be8263be321b959bd31d8175067833 403cf1c69bd4293df454439957b0b82b4fbc10de841225dff9bfe9f09d0b1e00 8e79d62b1b537f5eb4f56e876c25c5419aaffe859b9a281792009937d39e3a18 2c69ecd10e42299b2775570761c7f256084b0ae90d49e77a84f1f728e1ed9eff a15aa70042d5321cb041d4bd2204a7b3cda423ecbadc33aa57c4bbdf22e9464c 8a01554c542f2df7d9ca32dbad3ee49473c064baa299d3b659f30fc0cbf19b9d f2a1a19157f813c81ba6633b903d7c63ef3aafdbd1001206e1b6b1334260eeef 577dc9dae2487db1bb743f56d1a016e8352d2eef75b8439f7a0b06d2484e6329 c405f1ded4cad4af0084231859177e971c5525f1bb1854113ad7c5bc62e21dda db561e3f680279ff441e82c2a7251ac1e763ca0624ea03eb64fa2a6ac72b7b93 a38531b78756f9ba162cff58ca174efc1d776e9c3375d43a366c5da19e854a6a b12e648ca8bec1098b935a509295024ca47bb4f2f0f458cc371afd286ded5bfb e0e9d1e673bbfb6785f45e855cacbfc081725ee4f9572b152976c70166ff6f92 be23ab7ffbe883d989c97c708ce49e6b7847a4b42a78d7a2a122de8e7ed05aa0 d5a6a40407c2aff52cb6d80fe6fcee2cb265517744e655dfcaa45e9b5b159e3f 90e4110de219aa004caa3aed8b67108ff8888aa4857c54ce6d7191e8b11365cb 9dff22c48301e57a059f72497b5b04695bc6f69ed27d12650b8b5e48c9f8f8ad d056b92a46fb72170ff6d95012156b3c75abc6b19a70969ec132f93e628ccc4f c6bfa573278be6a28702532d85b56cf3ecac307a53474f1599bf35ce0c39f692 cbd889739f84e045de92495e182e47d1b87f2979de5eda0e24eb15078756ef4a b56c32d9e333345df49bcf546e4b7555e5820429035314341146e2eb555b736e 1fabeea644179badca2d5a7660fe89f61ef1e1975046490dcc8ab54a35b2ea12 8576859fe085697bb50b74c16b8f8d75e00ec1f6bb6207ce506df6b1bf8dd8ef 85c20f8768a15b7819a3885ecf1c285cfb1b5609a93007fde3e1964d014f5405 13 4c2af572af2615bccfe88571dcd9aa4df64b6218f2c083889407513625761300e8bcbef06be6bc034510979835818ba827e9336dd2670a5be31c6031a05c1005a45de60e7811890278f6c7c744f8ba59cc98b24b3b4ab69b0d8c9801780a9003623259e3fcb8a0df87be2d5035081cf934a97982927a2489b6283969f24ce8080f3b07076f61cf859b2dc96d76fd39e85b16f891059100ae9072be37d7a9c404d1eead8761e72e927a85728606da45c876ae03fa2d0ee79eecbe70d8450a41089b735448461c9be0f6b5a1b7b156e718f7520a06720b4ae337d6f6d4bf4d18097c9517da14d2a782374d94626fb388a2a8aa13969d0a59e067704617b010b503e6a008855d9e5c54700ca8852cf2f424ebb0f795466afe212f9c7e11fed252010e4c983c216964c2e08ca015b4d0f61c338f6663450576cb583ee542a1b1830d938a8febab8d207d6d680caa72226cc0a6d23f29fe67b61db2602da3fdca4b096af3a7693aa5bf1b7064ffa0fd762a670d79f577cc9eb551625df85f647434039afcd243d85920e39f59197fae25ae38f1655e8111e4b3204ee96c9af96db80cf2e7f470dbc808bf6c3b7138a2d902ab02331cb8696f5cdf42df15f001a33c09068f93d56df4a57f5a35ca0aaeacf4e5044f07799a47aba5741c81982142b60d33d6afe1e8cc4ab0500b98a4abc3d26f70fda407df8d606918dafdb089dc80085e37e658ba320d15e9692f022aaf7b6e2e282dc6d192cb409c5d1085099b130cfe71f476300be43345f81005dc3d7b651f6080253835837c428a9e702d63d805e64c67d5ace65cbfb6255f8ea6f7f19fbb3644a3dd92a3b7e6fb6ab3c78156027b471ad6a218ca5fce83c3ccc671f7b2518a9dfa230cee43489b35fac8ba7108a2363460caaa18bf63c7a1a8acc6e2773598a308ec4a349546580ac1ee363205c5473eb275878ec49f2cd30064ab14e7aaf69e7bb690fb11c2e17327c04edf0236090edbf9506aaadc3c793c97f36b8d1125ff24b872371e4586d75b1276cc02abb2cdc21e1dc603f9506f501d369875eb982ac684769b90a42eea5797230d0818de88160ba2415c5bdc5da9b15fe698dcd0358fac44a62fa3a6bed7c3dc9001cf122a1eb07c9842d4edce098ab99c8c1511070dcce0c3f0aabc854876d7100a42bdf0a278523c784a26f5e800c4425ced7fe7d04e16409271bd42ea8819200540735e9eee26e081aca217be30f893c46ab7063c8687de439b713551327297096cc51c2d26938e32ed3e7fe2f6dec46e76401f76548a541612cab694c6dc510d655e36951521f74488f73f8c748b97225642a6eee956e6217fb561e9f20bf606778a2ea44f9365ceac5d1a2df14ddb71f455fd52233817a942db0c9aaab9aa0e563490341af8381e7c74a6d7c5824b3d2d1975fea8231aafcba1a2ef5265eb0636e6cb6fd842042e496355b13dc4fcf1ff6706b18c63b30c374e2c5bb3110c059c5325f9cc53074351b3805ee1135d015d8f1e9e272c7b9cd663815b27ccf200c66f3db1b7f037ef149082e1157df89338b987456e8c31459e6a62967c58600c886400b24e5ed151eb1d02da908381b569963c1c30b3e24f99a19bc8482d300481d17ac2310bb527bfaa80f502b317d63da6b0b5d12cbc28d690f1a239af20049cbaf8276a36ddf2dc5713b86cb89fd80c24797a3442b495f6238389f466c30250179e19a7a30a5557c6c34e3d4be18eb7be5774cf0dcf528970676caf8f3c0b8dc2e8b2b459d978366af8da0206126142271ca3065e591b7953808ba039360c981dfeea37cc01a88326c80cb579ea64de423b3bd9f37fe60e5be036f76b2a0c63207787a8585ac866756d347e52fb7dc329cc96ed47c5756815d0ee698571048890df269e9eecb7923d93f62e8ab3d019542ce074587ad5f8f5055aeee5780407fd50320de0c3f43f3c4efcb2ce606c14d68e95854d241a5b275181a2ce760bf904803119422dd9d1a39a4fc8770498ebb652338e23cb93ce7889d9809a0f0d0f78b08f8dc593bd107a1d7e185932f9640f66814fd0948b8719444c9a317f090778b29287f2b1a9787191f90d46590e28ebd40d83db74de4c08ff6a1f437006d1514db193ff0124393df6191b56463a083a7afdc3726c0cb3f5382ca4bf2000367500d770f5e6e9805ddbdcf58745905463230fb8d6020a6c169a34f5609a0cebf78f364216dbe1a85144a5bc0e08ab21e22dfc88c78eada90c27b97e8d1e0847fa7c2be13be1e41caf3e2ac357f3a5abe6747c724a79411356226f22c88e058dcad1523dcac5399446fb24387cb5d1480a8652c5ce87ccc10cc4dd0c412c05da55f3ff8b591188eb5c3c6364b75ac7752ba1c4df5359e7a7695eedd50e80052d65574b6ce59b0e07d30255a1119cfc5e43d5f0e97eb92a9a2253e391d9a105e42c41debca573a6e0421037d451bf13473b80a06d2be6212650d0c244db59071542e9477a14cd35ab47744ea265f45d9d103e82c2828baa471ed9376a4bf10d5745a1caa0f634f3326552f56edfb4b44c6a4317642b6c1ab39cc19f7012f705ebd6f5afe9fa18c64d7a5b5748a5c39429fa9c53c310d74643cbc516f237b203fa66ac08c73c2b8c8a0c4ae8792c73e2ed2850af287268abe8080da8da91b0028c598da48d0e8544eb3449d1de52b7b83dd6a6f86acfd42bbc99d680a2569d06412e0de04d11509efe404aee94d466df845258599c70e6cd2c5a621c2404c00efac5594132ac56b4fd04f35e2b0c0178c571de1059dd4bf5642c7bf0416c820b9f5a2eba303de9e8c2c2c6e894155640713c80be86310441812cfe262b389009fdb8bd46e9fefdc1dbe2f6560b56f29cd706879ed5ae794bdc79ecaf57a7450a9c15235e55cc262c02b2edcc2ebf795ec9a37f039741ec3435ec5e9ca49fe00a8facb37d6d69565ff7bb35aaa7a1933b988f6e5fcb3e44f73df4d6a31e3d650c1e999bf28cd34556770d0086f9897c9f07e755ee7eb73f5a4d18a6114f651b0ed07afd371cea2d8d831cfc62228a38bd1762aec43bc018fff038449126e81f07 -generate_ring_signature 0b1546a77f70112073985f8a806f191e83e9d3cb9f19e41f15a07671a7d7d173 0ac40cb07f49b58cc8d7c8f9eda97937c5cfb83fdaa0e897e4aa8507cf55f2dc 56 fb504b3a12b0e8237788b91816e395f566762e9d85e276592b9f42eb46b932b2 2de49b9fed2a1379e27ff9df1387c5704728bd81a61381ce8da4d0190e310cba 4b42cb7ed8b175b0d82c6f6577b3c2ab65bf0e0cbec21bf00a6d0a532d508383 6996b0dc98d6d30c76d3424d16591495301a6981e8a4afe7b0b7b0f1682c0c8e 8c3d881ee3a14b52541c96ea7ba2200a17a9ae2123c15774efff022603808f16 c7bc7b4e978d13bc12a50ce744db1c964ea624d53d57ed21aedd761fa9e5dc56 84230301ac02a11ef46e5e7dd0e2e73faf19b28e3bb579374a805a3a07feb800 0f5062ed757ea9f3a1d9680003733cd69ac3077de75e715da4c72774fddbcb78 da0d99811f920053e451849dcb82c6f9c5f6f2e1e0435a52265dfa695289bacd aaaf445a2d1bcf716480c3f552efb0335d76633b4ab6b71ee6bd9460fc24a1ec 1f7884f7dbce7ede89ebec68fbd6765b2cc92ffa7f8c819b1a98c86c0166f142 5e1592fd36141e29de682b90ffd13d68aea02e67c8c75e872ba66690187fa6a4 78f92af4fc0e7fe8c117f1dec9d225cc1a690abe427f626466ad5768a1578932 5f34d7ff989f08ff0839d1df276a0905c9ddee265d652e2be032f59b86686d95 7525ee1aba8272b610df2377c0c275202fe06cc0589b9213e70a127a849e198b 43170ab7baf0ffdd0fe6bd391dbdb7e2dcd1b89707bb00dca9bf12e5025b0fda 8b84df55edbb4cef851c9674e435639a0b147456333b55f2ef083e572313e347 fe394491438a5a7860e525035b70555caced54a2ee0d0d7b23a85abb6b8c6a49 682a71ed5b369424431725db66925de5175d081d65f6a4fe049a5748836737fe 45ad3881f548cedcef87954b2c02363e0a4571bba5c5462d16bf5ae4f2dae423 8c3947dd8a8959059543c20250f6e83bbe841ea641759cf6f6cf0da204dc3fc4 11f235ed2bf9246af8ba9fc067374693fd3150529e05b138dd6b2942b7b8ef0c 57a1abfacc42c7ec4f8933bd93b59fe01f0e49690621379993bbb03ac100f036 0ed848133ef3457e15f0977f10a76d7e535b26eebf9dbdf97264a964214a05d2 fe282180e425a1bd0a8b7479be259067de45fc6e89243f0d22c7565148acd310 81857e68f244e6d5bbb6cde0c7ca8e5b8662870472f78cda46ee11f21ed85b48 545ec00ff569c1ed27563608e09719ec282f47e8517ed95bd1398ccc0f7f0404 015730048da5e50a112a705cd3110fa035634991efda22bcedc9ca6eb6940979 0e3c5354e7e30d619cf5f89a31817892507e64ef94dd9ddc36296da893c60389 9f16a094d0358ef39bbfae78c967677fcb3b701245f66de2faac17fbd9a50b3e 3ea3265959f6857f1b3de569fe573268e3ccd4f4fbb3fafe0b63524c13df0375 1b510080c98faffca1796b5937611e55d2d91ce491789a65df068ba7a06e2fdf 2d1f63f2b1f54755b4a3d328552f79708a3fa6db59dd970eb068845d8536c432 d9f5b0a6f2f92e8be14dd2ce300333d20579d3fb6f8719ef8a8d5ba5a3e72cfa e4d7b759782849314e443316bf297f0ea63370eacb54839ad9a377a54f72be32 be3341838a0f2bc12009e688ca22178361db99df8060bb520740138ddf5645f8 11d8b6d32bc7a35768648d631e4d320ea8b56e932f1a2cbff0d40095fc29f80a af23e51d53106147d060673d7fb4f2a47bb2ab72b2cc255797fcd818f5135220 3ae4c97b960f65673fd5e01d2c92b3220f6b285b748a546027a8b1bf59e8ac6e 76d0434adcad2173c4259116139ad0fde9b2ae309c1c6e332571794cb588d152 08d4b2c32fca4c8879102396427058c720babe1e39b90279bf202931a0f621ae e8e3cc79d0e05cfe951707e1c903524084e4aac4c30f9179c0be50b7beefd7ee bc9c3ed0a2c25b1e59d70d738dd9da4ae3fbf7d535fe58846d523faf47bc42a5 127d126506b2c410e2c8ac9ce472b1d261932e3fe361dd90880864d003812be3 c894d10d2ee5c17280e3e53c026084229c4e9e875cff20d608a1ef71e4573320 02b412846cfa7350e024294beb8fdc1e2587557e8a7b4452d4e9e9eed14c9702 c5fea97e5de8cdfe09a77f6f78a302e9db64df2137117a848c46c79079b6cdcf d7d0505214530ea4cd905270f664d9ffa08585a7ad28123156f52bed892f5055 fc78f270e04a04f38ecc4b754ed926fab86d7fd5cdb959e91b9ad15ab5677b6c 6fa027b87aca6842606c8f8bc4159221eb056c00d56553ff60884ade17445fae bf5e94eef26a03762c215cee6dd95140ef2ec454c2faa05d2964095992a47705 29440b94f3701df4472ac2647af0de415c2fd191c23dbb8b8f096d3f7ff490ff 6d6ef06df5e113380e27e8ea590b8548c81a715de4b54dc9a5d35d1dc45dfee5 c8ead1f8291072758ec6bf2c68a6d31e5f18a9906b3f22b9de6541f4d09f4068 179c75dd86d37ae7ad1ba856d31f36d6a0089ee1a363c540f0676e8dc727be9d ff186cd81fc7dffae43c919c60cc0da74e722d269741c3694c8ea925ead329e5 901ab283171d866625e3b45fd7fe13b6b829a44224a37795a61683e6addd1704 25 ea7f6a21a379e80b5d22a00bff43605a5c641ec986b955d75cd6983a03e5a40a15ce6134535179a72be5ba5c83502a052abf50cd6da4aacfa25ee7ba1361930821c2a9224299c1c3268131866e4f9f304bd406276e04a369818dd4924445ac085b5c6fa5174fc4b659b57102548835432cc67cc9c182b853b0c235c4ff93cb07bbde23d68de1117a7983807ab4362bee70f01eb91d90ca5f788e196df69c32041d2e0a8e37006bea18932b84ca68a744ebdb6aa6c077ef32d5f38b8aa91b5203280d0dc71dea4cd0ce59dc3df4239706a24ec314f08c64dc3a9ad70d4102a90b0a0445306210dc1a7e2e13b8acfc87a5783810e8e1114c3653e57a8c6fd92a0ff00861a19b6c95e8488e5b941c734c04b3ee61a6c8d8bd96b256989eb9aab506c0cc8f425c9b4b6b50c28497d7e451974643148f79eea014ed832e359729820649a6b0ea41d60015b39185d4e73839963cf7c928787f045a393ef4520d423a0268d6ee70e252b2dbf7621662a0ff8a4b50f65972f3401145103f3ef39020c109445ffe882b116927ec96214d4eaed46118840473f03e657fac317417168da50ab497f018501f319826c069349a509da85e91a14af7ceb39bbb03e9076bea4104a25c119e34b58e1f06bfbe89137e74337dd379be370fbd71502a44e28abf9704b174c466b962ea73d91faaf09a520ace560918d3db0ae4f596817195b552f405cf375ab3cdb82edce5cdabfc4f718a0e33fab7d735616c6f83ffa4271cad66019d33be509eba4363766bf685a64938b21666d786f36ae8303b8cfe82c3296a044e9a33293d814e7cfe7f324d10bbd55e4b3a4f8e7ac5f3b42e019e485f3eb9073694a88531baafe2aa47621519a2396a48b5d38b6695f5a99eacc3a627e66205fac696ddfee0f963f1435f29f0c59d8099db7b25e61c44d5aeb3f6751b675c0ad4a0e77ed524a5e8d30c5131aedaae113bbfc2d9e10c777f46708af2ebc9eb0cfa26efb6834499ea1ace959b09d00a20d99b928b607e9b38c748e1a1e3bbed0f78beb707e00602e7e2a78fdff44d2785f665864c752e9baa744b0b717d4f3908cc2a1182faf69702d5d0eb2a3ac119ec6fd00ad6bcaefd2c1a975b00fb5004068afc023901f8a968248deb99cec8a1d00d457eb5232f7cc58d4432da1c6c930a4def75a5b6850c1eb02b133a6c74dc07d81995c45120ef6cb09cc4842fdbaf0d4043e912a7e9c6d8d8aaa44358efdb8f5ef0d440599b02271cf8259d518e490a178aa3fea33f6487f8bf19b8754d28d9188c104a0b537d546ecd2970a9a70805ebf353a68c761acaa7a7382abd45675d8ee1e3ea2ef18410cb690a94067ba804a2f752adef8c7887bb10128755eda3ee220fbeb54f46dd17c0b0a4d22067d7024393fc9af0ae196f660d9bb91b2235b88606a8d2663d5c2393f785de1dec5204d6dfd45c9bf67a3bb8f768caaa66755103e7a14ea32ca2ad47449e01ba98c6030834a5ea66ac038aa6f97f1af2978c9c6e167d99ceecf6d03960eb16040b910eb83e84062eefbf3983d775eddad5fc7cd18d60cc146c7439c86f186d950b060e83fa8f838cc0f37cdc964e364bfc78b73492fbc6e599033a745558a27ffd2b061bb9dca3fd448bc00e37df84b03548bbb774c0b4fbf877a3c3b7cec2c001380401a14d4bb61696da5d5e4e6f5557cf6f0049ef4af152477d630226da11dd0101f736e1a7507fe045e5cf71b4ab749da4b9a88982716441f33f2a1b2ad286640a2acfa1e05244be97251e9e01da118edd4258a1d57e35b06ec83a02b7293e4a0c6d3a8e7b1191a5786ad83c068a3996c937d5ebfa236b9bb75b0a5408a61e160edab56a2ea40069d07fcf009fb8f38e88159ed2565e0e5d71d43faf359b0cec08b25d6cd86fe8556607f55e4f63292b5e63de758094ddbd4e119cb1baff0776034b0e8ca5ee48b4dabd9c06d89ca726382868180b0960a96b974c4acdfec55e0e3a895d58eb158543b5f70c30a07f4cf1933e498edd6f1594bcc7f269cd2b670526f5cad7cda88db8dce8629d8b03059f44946aca76a2b8aad3ff50547f97aa0301ebb366b542e75cac85550a01edc5d9f124b87b65a26928b7237529c270b809b93d85eeea3393abef724784b8307d8f71e5d11d5d57c1fe67f65f507eccaa063bd1c7509f618d6dbeaf3b697188402db41b353736b0761d08d88d883a2f0b090bf2d6f121f9d28b4d616d6ac91e28c4edb6877f5fc5557294056784a798230fefb467137c63d1147a7108f53c3d829d04a54b351ae5ebf6dbba15c52887aa06073a9c95f68e7745a2bd3edb31de58e11ad25018b545039853ba836203944e074c390ab3aa66299a3714fa0b8a91901ed65c701580398186d7ce24ae1354290c8f397c93a409beab93e6091dd842f454ee3e62cbdfcc29492bb503eccb2a1c0c885bf070d23238ec149c2daf3c5be9a9991a9ba255ee891799743f394f93520b2d20498495f8c3b5069d904914429b35c416057b71ffa2bade0b6f81e3beb40bb54a716ccf419c65d20fdf51eee71415e68ef134d1b7315b2ee62dc770229408d3db59c0e6c2c9efb19da96bd7f84c7fcc703388835911e2083e29accb9c8305ba311334ee6761e3b92a399dbdc882af86497e5e9e9d80bf00f6bcf53ea21208f7dc2ddfe35d3fdd46517cf64dbf149f5ef2d02cac8bbc5f43b8fb3cde77c20553732322ed3db3e4686b1c57a1b900a7e7a3e3af6c4c0e907f2274df6343b80a7f6988670bc7a0a8f0675eb99a89d861d8834c6bdf28abf44ef694d549e239041ea31c10ba19b0369a11f61fb839f328a39b9fd833f64d740e74241f4db4850f22382cdc8654fa088d55ee6b62ed8023dc363aeac53e95653d6fb9434e27ef0f275db1298d0d11fd767ca64b9919273b075dd4e15a109465ed413ea59a6cdc0948c46562055cfd7e6acd121b63fea957186f778c8ec1eb0bc12ca80ec318330ee996963b34a4646e82a38437af659a18d0c19cfaaaf5e119cb1dc50f21f3b700822986d743b03cbb34a36ce09178976ab9cfe8c12b26e2f0336f07edf471de00d25d772c234c55be41166c12d83a4b51aaab4b3ab77b54ddeeff4b68b003fc08337395a34260b92f7656e6208524b1217bff180f25e8eabb136f0b1e51d4e605d298558b39c34ea22f04654a158527ef85889d7a9d41551d8639ec5eafae5e08796345c40c31b7c28da1b765be18d5599137915fecef65eaca9c7c4c78c50b077836cecb6c522209d310a0c07f170b09c642f951325adb402d595e53d73f5e0748ba180db3b070039fa090302f73271b2dfe937180327ed3b1405ac9df198104dda7f8c8ea6f31b3e92eee292451a9a5dfe3af2703580707221a9ff8291a220854b3fe4deddc77b9fbe331d4e74e2e89b3fdec28ab411de71f87bd41af8adf008a6a7dbf27512441a5999d362b628e634fd3febc7fc5eb862122aeb1ac6bfa080ea30c00eb18d5c047656bc3a796ced004759f1ad04f1973901b10cf4ef4490f58001d1592f13fa33037e4bc22ecf72a2970db98d1e8d82722f1d443c2501f0e4f423eb7767c41cf4e1bd34bf17a1440d6ac28053b8b0df157aba27547b94d02e0b288abf2efa8b4348025fb47e1fcff1fda0cab0d6eee78607b7fc25ee93d0fa96a93fe64890827b8c31d267027aedcb2a9747285aa83eef4d557ddc1ba93011ad0823ce50a6ab1906b1c2797fc7cf576736b3ee7b918544535c0679c656c0d5aab8ae696617ec546e90227d95cfb956fcd15b46c0742e75f9da9f31ae30807b132af9651833f08264a742dda198646c69fce8c133a70c1846bb1a3f8e10803a07b25e8ef629b1216aa3e2e188daaf8a7a00e7375b4c12aa8607d73222272025a1facc8bc5e1112e42f836c8c9306e2d90f98ade556f4f321a7774dbf68620b6d0c72b20732f83ec7a355a4510508ff5ac223a87c193ae2598f53eceb0eef077ee2ea781164ca42da4c9995fa956f566b93db3fdedcc368164f49b5523f66035b20c6787939d349627a821fb78aa4e51f4858434c15d9d2e82fdaba90bf820eea738ceaf81093afd3ad7d1ca9a9d7e940741c8497b5f174c8c28e490987970580842bcb73c62e0b98695d43d6c877ba243cc8e13be27224f46b457d187705085ce1e4c48ec8c425fd377331ee7c495585ccfa993d598da0639d597194aba207891ca46b7f5994f5c4a6a067c76bad2f3ace342a3de56c99a58218699e41580ce9bcb060b69561c29bdb39ac0a32c2ac38547b36c1605380cad8e584c28d0b054c1e110d0c9ed87410151da57a5865806828386ea8401f84f1e864ca80d2d60767f6fd35d9965b2e5498a282606b90e0f07305a94753a919fabc1e12376ff204b155f53c6b4aa36fdf67ad2c306b1e1e7c109f9c521f25545ac6af4e1336ee091e7ce65b3f281c57294a76caee5280283c98429ba6191e6dcc3cc7b0870b9f0ad76748877be793830ae2a96c8ea1d4a2ae74556e0d692498b296533d4cd27404fd67a698fc96c43eb7d40eaa3787f3897466945ce1ab3a825a9c45e40a783003a5cdd368a6879e842982403b9988881c3b1b0201def49e6699f98d9be55e4105c2c879c99f93da90caf1f004d30f20fff6af22273ccf4f03f9aabec9042db802e0774ce4695d25c33e1b4ba73dc91bae60fa77dbf524c25904bdfafff210a20e08a1ec6194fbb8a8943bc1c3dc626689a7df4cc7f404e29273a1c617903911095fda7276bffe02f353d71d6362085e3d537b8bc068d8d6857d2b3cdbe0feb9036c97fd04a9047927e652a7759ba47e518c527ad8660ba9a5a3deab787e1a6a0022765a4a0645d610b6d7b7ffbc165c39189f92d160345b2250b657ebd5d7810dba07b24e98aa686c455d96b35d7df3883bb4befbe54e8d512600052f7062fd014e0f925af398c80d8ab546c8c144f40d8f6e4225ff13609d0d95f1ab7db8580f6785f5562ac2c50d8fa5153c3e151c46952adf2027fdee5bbc378642efd0790f403292110b08702f9495037099dfacf8378301df774ae05b16e29c37a606d20d -generate_ring_signature 246b0d03ba218cdcb8142ceb5233708fdc1f453f1a492cd962e0dd9b191ea00b a58a14933f07ddd1da220d588cd863ac95d4745b46b0bc581c8b608b8aa48f94 198 0db161f672914d04b3da1ef8fffcdb431771826fc0c197e8825f2b16f0e1ff2b 6a77d52d3688f88f6b8bdaafba20b78065cd9a9fbd05213a96a125ca224b8eb9 e2ea7c4d07361af255042d42a83fa1ed8c49a9f454c7a8f6953ac4a25efd7803 fd944b028ccf14871fa10383afe9e30660a86635d20503c3001960c37de2e69a 61410433de0ad6345b5991355caf4432ae0f6d68de7b8b92fbee59a8ef3461e6 b2a13b81e18cce2587150264dcc9a4b7d5db29199601ce267381f912f3950b7a 54e61f2d4c10373f8ea74c8c262df8130e8d9b92529d9f4010822561ddf431f4 243e9f19ea8dfe283cb4cd1532744223a9530328854c771da9815e411c3ca262 f7c880c639b2cdb9f5bedc069e18dd5891428036391b3872de804d2347e06bfc 7899ec95851d38036fa9305b0d06221227ed571c0f488f99357e74d0e97f2f41 b55d7ec0e21c1b1c397775e2877af9d50328d9bc1d1d9b41075b2c82e59c60d1 86da65cf84ffa0efc5d851f16927ae1ce5cfe37f22ca1ba6bcb0b0d0eb64e5f3 a0baec146642142849fc2bbe21b3fb8dd36c5bbf4c4c8400a9a718732be93895 18e7f44ad2e9dbae18937a04deaf986794c4d1de98423a0ffe9e838505218ea2 085fed1c67c7a5446f05ca2258b1dfaf302d2c357c5626db2f6ff1472be6b789 9a7a89bb811e02200372ebe05f263dfea069011f51616bfeaeeef4d06b471123 c7da7fabfc31f636d3357b0153cfb6dffd2ea29dbcaf79a51b0c8d2b9ee141cc b49528744efb738fbd350f830e7c94d14fcf929490b1a7a7ebef9cd3c0506bec d392408898105d4fa4ef7a113c5e51fc9ec12e73d3a3b681895c5d1f8d64f9ec 14c14d0a7083d434ee67caee6b865733aad7e1c6b53260adc4a67ae429001630 d0a66f5a0b9f256542b2f47d20d9ef0c9f0ce902762e794cb6bfd0223bb03309 53640b7ae4b07158cad551f8b87080c9665cad08ffae960cd538eeb202566880 333c1d4edb0dfa89b137577862e6280720ba32d5a8985cba281e9708a350cdc1 9c85633679a683c2c00a653dd983fd6e6939e9a5b3fb1a91857226ec720de3e1 bb1f5067b77b9f97c17f4a94e9f23c83ce86290fa675f0af3a88bdde6a41c8c6 0237b12838ac6dbae1e8129a75907939d6995c2823fad75c981dcd983ada76d9 5222c496e1219b242efb961b9061080da46d7184ea84ba3f443e5f56e6f8e301 1a73f7cfd54d0c215775175106a40c23a418861b0ecb10d9aac208b5cb917dfc b2ff34e86f46a9e541444950f04822c87a9f3fed09eda2e354ee00a25adaf5cc a37896dbb89f13cbab665ebe009de96110741380b6ba0fa3303d025eb2328c60 2e123842381b4b15f6c08d5dce5b7cd375414fd0309fef0f0234da74f928545a e594b714f1b8cb58d6c1784233d1889c036ac446f4a109db65ad3e504759d3b8 44e1e6f6481996fdccbc53330ec84315b23f2e6177a04a838557bdb2bd967ede 21c095ad1a318b4cb437bc85018015dd88f7be33d7a8dd9866c1748e68586c5d 91c5ccad9252630c2ea99586a87420e8af58c3348ee379c2d1ddf0a221b8a6bd 406ec1214dd65890ee515b98612c06de1fb192b5a9c79a62a30119622a63fc92 b97aebdab39ded19b5151cde77e0dba3bf884b20d76e989f998555379e279d1b 2ce46bb4e29bf4020c8f89041a0127191c91609c94d10167a8bfd0a05436c7af 38dcc4af14c5ef185e7eb728ebd9856666ff74e289176bde4e13f2e89c916b64 22858147faef84673a869220da42dd7ffa011b3b344c2e78d5f060207d030e34 efada635606131016da8e1cae06032667d020a4647fb543730168e424a5b8e3b 267cc134a2557c011b156d1b9d5f9d12d8cc1ceebf5e3071fa96878aefb28980 ec9eaa5c03b8773659309ddabdaa3cdcd7007935175ea3a6f5b3b929b4b45994 1832d72a8c8092c0d1edff25076be448986ffb145a7eac5f4bc99665bc4e636d 76ec16c44937efe375a1923cb4cea0d42a394233d00ed4e77461c0bb19591f46 387cce667b9796139aeffe1f79997a0d019299a8129b946a849f5f537cdbdf6b 79106c954375fcd054ee0e558d8959a6e8b100c1b2475c1f2a30e12e936125e6 7bd06529c0c944410e0027d4b418105022bbd479d2791066aea07763a2beca9d dba510ea42aa855ccdebbbb71fcadeffece08803f3c2760c1822a1e5f4fa9663 c98f55e44c5213fd51b52e869c7096ea5fe9620f8b183d484d447ff8a7779778 1dad1ca1319f93621fba40e4b7ffa7c939cb43525421df2b096361be1b8b1ddd 4ba49cac2da0d71749bd8a99f60bc231bfdc4304ba7d33323a362ba045003af8 823f604a64a454fae850acd9267ab3a7eb96deec9476d2ac69c2f013023ff2b3 afcc56fb9d925c8c7172178f518f795dd100013a35a22469aa01850d5a2b8933 3b02bee1a2346707050462002b2e0624a7f3beb0f61199e8082503ef7bbeea13 a5bf9d17c3fcdd0678cd6e02a3a44cb04127c3cbe0905dee1ec3e2f207e8247b 167cf06f2b5cb320d5d8e82a25312c768d176c1a8d7c2a978b0a6b355d9291a5 121f682795848f0cf6881bfaf24cd161e1d48ec64861a2d3d6f5bd5bdd8d1c19 1c9bc3a726a992f1e7afff27ee6cccfcea8f103dc018161d0bc3cd3367bb8424 4a5293fdea6a697bc9a561326b2ecb6a364a38d28d5b51ac517f8ac36a598633 fdb2f1a88848466354fb68e56ce89e17026ca60d049e063a67d85f6a29848aa2 8056d4516ab1042b2f40fe62a3e1df9eebc350f4cd39d7c60744a25f127f9f24 43039a60e66e80cd341f0d915608485413cf54abd00d6f74ae7d6b400740d82f efaccf178d84c5bffbe97a3f0af3f982049f3b4f7ae981e80b5caa19d887b606 532b117cf74e4766c38d3bc22de22b831a81496e04eb9f30cad2cf1a08c2e371 517fa25d585f74a45202d4583f084d656ea1854b0d03219792f4f3a28f23d58c f472a57780e1b0043e1c06079f64664ae911603ea663becd80d6ee23009000b0 eb6d7f2c9d42f5e9c5341ae6df2213ca5aff31308b8e56b6d9600fa2b3283a29 224239609d5215fe464286cedd2a04cf5be2b4865f3867df83543b1b9405ff32 54ce5094e3d07710882a35a255de37cdf2cd31d9b9c121b3bf91ab7bdf65c887 a0665b64ee617e93e6b2656ec248f99b568dce3cdb93d0cde77a59a63153f467 7a87b59a3b81eed644cce872635415ac56b14e8ce1d57758e3b17d208f802ae9 cd266d34ce426739a6817e41b47da687da15d0fccb44bcb63afe3e6d21808304 91d6a6f62da7e9086bb77ef0fa1652678f4112bf8c58966141812a41bde21014 7f11b0dce98b3b5b753547cad841a49bc70c50979cb7e26931188b2805562c11 6ebddd1fa58696e991018d0bd21507c9fac9670dfc09b83460831d0f99d6dbc9 d2a836ad7b06d482f0473cfcca188e2667241e2fac3c61446616d85e2873209a 0787949bbb01720189c8c681c73df597e5604d268f8ce00990f2e3d5f21e2cbd f7597c8aa7d943292de1f422b9ab12ae9fa26e6b029a8001fd6af739b8c5d16e 3938d0588802af284691bacc09e8924d5339abcc01664cfbec99510906fb8f06 0655a083cfc8ced5a2428b8ac6d90fac5492cb59d492b50c82ec706a9ad621f6 e67d8a5f62c1d7284daaf885e438f79fdd3f473cbbbcd7a12955ef107ee85c17 fe075fc6115e419d5e51a05bea69b864323bb3223ffd2cecef6e0c34e5b4e1fa 231b075c7044e047993781d57fa4d637f5df0cee973f033702ba468fd11a1e6e 63be8069804734a71417e6c6492aac78377a94411dc38f6ca94c1687fc0fa574 a71d86fb97b927e7a2c37baa95b6be30bff078fcdea7cee9ffb2ae3032631867 2868f924fa5a7633a1465a19064f6fcf49236cc893570256b5ff83def889dfee 9327dcd74a80d8e531c1355dab619058fd5cdc4fe01a06f037818a975a7fe74e 2499435cfc2c9432b3888b7a2807f192ba19b62b45d7d273d7f5b0a204d3202b ed5ddcc23a3f887ce3fdb9bb25d758312e7909f9535f9a3ff1624cd86f903a3a c32b0e534cbe8a00ebb0576d80b80dfb4b75f5b17f8f38c9c84e3fe49d13bb2a 9fca90b55ba9b6c5f2c050d2b2f1dbb3bd9e5e51e7b8476cf1355421b0f59b7c e7f9c9aef7db8e8dd1078201a3abe2293b43236ab521c8b0792d56bdd3008246 c09f4b85470610997c9946ed24c314d56689990756c11f8544420cc87826e683 38323e53c2f779eb1622324be8a5fb006af48ea5ef5e3ec00148a147b00f6542 1a06eb4466f0ceb6a73be5b1d799835e86f6ff309a8397a7738351b9f5cd1a00 f1ce554ee1a5e1bb952ae702018ad3ca23eb11ddcd1bfa11b0c1c55256b1547d ddacdb96a51e0a4627d47459904ac22d64a220a1d1bdbffe16f5aed08820fec8 0022e83f981f666993ce52fef3d82566be91bfc1954673b07b7ca3ff5fc58e49 4fb2031fc2197a88d496854b3935daf08373093ccce1f3e69486e4b35c35961a 12f5aad6c8f040e99b9426b95229f2498481a69f4555fc2a593768b68d8df433 a356628599009e89718a1d1d6966f28da025984e3b7dbb310de1e39945606db8 35a5213725ccf4d076a71e87981b63097228bc1043506e1c2ec429f13355ad88 1ec779087cfb19cc36ade2d26f64f9bda01057e81ff21fba482aeeed4ac12335 a913b76c8eac995496954feb8bcc402d6d6f4e800789ba28bdeff1025d818bff a75d75ee55b992b952ca5cd226383b3964322796819dba518628f2b4ffb2fd84 e2ea18fbd119c70d15f4223d594d40202614979a08ca9177ed2c8c76862b2e22 a89ec97b2fe0a79fe66416bc90f396a54b020381e2c7942fede9d56c8b2a36e1 1d27f8fda1fb4ebb4ac24e91716e636398c702214188591e68243123e126186c 02cb80704c2f7e0b1776e82a7e16258f0a8a4c3ebdfac82423e3f72b7ee56d4d 9a524da42a15229a1c21aa734d09e4a71c0ee202f5334ba972c59e00b0871fd3 04cb489a417d31f07b8aef25651e7ecd6ca857605c720860839562f66bdf19d0 d543251d5e015dddb344028dc9325456e3a65d33c5de7d3ffa0bc4f77bfac4fd 70f3c9efd0122620789d9b67d84eba1218f40df0ee75fc6e82566e83e888b990 643ac4025e417233bdbc3b1de190bbb1a0cd3c2dc8de7b9ced271bf3a067e391 1f86b62e7e9a8373f99508c94eae94e160610de9a2885dc75a4704f05d569b37 a329f36a793abf7b70440a1b88da55f88de436e4b65e75cee79957eccc454d94 20493dd3fc860598e2953e9fd29ef927ecfc661443285e7f44b55aa2853b8b40 dec1cc91cbbead300e627e6aff37467273a6deccfd077b4f016bb2ac7f54e591 49bf801c8c676cfe1313e692b56aebedd91546d3e3037d72cbb957253777313b de0168b980e3e80133c7dfa74f76a8eaf7a6e39c4c6f5e2bb9cdf9bc8ad94055 26385c685bb1bd0e809fc3732de977a3fdaf31e8547a78e18225b83120bc6e69 90dae46f81b1994f6952fe1639f741006af0c02c44c72aada46d6fe9aab0b879 cab19752deb880f776f0fe03f32025fd7cf1258638a487698a90302727eb80ce 90a85fe21ccee828f07c00b4c85f6d54516cd4bafd16a8b6a6ae81b2b5466785 430fc038dd9548be476dba2c31c6748c7a354e3c67966d3250900dd39c809e28 49a2d2e4c02a5b94b5ce54609f7dac32aca0a4b2051b784ade638db8df4eecac 4d6ae1194d575bfea52a4e09266ba41676b7a552346100db98908e927ebf18f4 1b0bb0578845f9c1f7c568ba36e7936729fa907f6c1a8c1899229cedaa1aa306 10d3aa986969f9c45562adacff4f74cf399294ae3d6a56c6ae72135f51ea90ed ac69f664f096b6a8684c5f014a8b984f1eb9ebc2cd7edd2b28b37ef25e3147e7 d348cffc84741e63d73f26e953e1a0c6dd8349008edaa22da7612600561a5ff6 d8513404ebf2c16f6f7775d3586391168e0846a973f2229d569a12a06429eb93 fdb70b83761ac9e5f0efaa7af09e44edb8ffa0183b75ce52ecb5f6dbd0abbede 595b8d61b840a5659888c9bc06ab291df02f4cf5199157e0a5b509c382198067 54cf1293b535ff5aacc99099974dd99a1261249472edd6e6b4086fc1cba8c90d 97c875ce3d7224207c85371c7b1def7eeeb5b4690762b719f9f04bcfb866c479 c348eb0c65094a6127d7fc807507c8302a1c69895a97364a2f01ca5482a20cd7 b1308b60a84a9941dd55462ede7f9a54be15fbbb3cc28d7d3479252d0aff9563 c9517163ac2088e0387a0cc36e85345d134fa4104cce020658fd8f542e836edc f64f3d2a5ee687e1f8dfdafc7b06b3b62f1829d4510ae5c41d1e637141b45f80 44a63864b9473c34d0eaf8ae941eb127d8413c6629b8c36fb08b0ca4dc214df9 93a1bdf9e791ee990bf5508b6bf513409cbfb4ebcb16852a38fcb493810ae898 fc94f570800fb6581c4eb3d277be0a34891423b22e1f3391fdae809f9e75729b 12122063caa42018d7beb28e347bf7c0831da5a492b9faa318f822ba6b543008 0a6544c33ea85db30ab5ef3944aa87b5243c6e44a3001f64ef98b86edceb9520 64b6729a7871fc0f35ec31ec51dc6e444b2a5afd02c508e336305f46d5eaee60 bfb50061c92ceda81088d5698f56c4ec4c554354060a38711460332d38e21a33 d77091a9d6d90d9e8d68d1070ae328ce59f7a6a6599068e7520af35fee82fc94 d09449e1b37600ad3a249b93f2decb928c3ab1916c38cca9b56c38e93ef4d987 bd1feb8de1340e0ea9a15ba6ea5bc4f897f0b3d86ab4b882743620cf7133754f 00ced965f3ad93b796fc644f608b94f5851bb8be1559a5ef9a072f07437cfadd 610ac68246075026e34fe339cfd31c413a4fdb201bd7cfe8773875ec5f08bb79 10ef02726da9fa5618dbabbe19e3670ee4167b7c9228f0c9367a53cd8c5cdd95 0137deb5bc0cc9a05e0f12f261da6584942c556c0598db0bbaba1704362a8fc0 f69de7e6f5116310708c3395a3e4e95e4e58aee0cf39670a69d167cb308daa8a 17a8dc951c11526dc54a5b877c78de0267a21841a3fb137f0037666f996795ed 28d84bbb485761c0177ff4b35cf8982f98f7092339e8d2fc448aefc8845c0876 540ffb7709f0e719fb5125e443b79c3bfcdac655671d33187b750bb3a27cdd59 b7e545642adf2ca59cbb67c5161f4fa5c82d42307201b55b55dced00107de1d1 bbabd53bb8454036ad63cddf866f7e6942a5e65d740efdbaf15393a46cc2a5b2 6a19d37e31a1d58fb394814334fd5a85f9fcd1bfc3b816990292f8d81eb2519d 98393707ff0ee3143d5c0e397dad545f7edce40c334f791df327ea542d31cd75 1f71b20fe2cd0064eb2688696006fcb45d5ad0b722891bd7c8077d9717914e01 3751f297c85b2064882e0afab06492cf1b103824cce5c111e2d841d8e8f459b6 ca24b137032418a3d5805e53f04ed21bf57524caaa5cabfcfa19d48061f5f612 b89270edc915387df517efe1ef3d13561001ac485733775779affb438e71d8cd 051a33c231cdddc05ee22d707ee5e8eff9d1ea12dcee617f7dad29210e08f6c4 9119b076330d06caee1dada7957dbea09e03144a122ab049bc0564818823ccaf 04e925699f33291b1ec77269f0f3a02ac1013939697ef6e1ed1c040ab59d213e 9ffcdfcbc96482ce62bcfff69719e9a6ced6e3cf172d0cd234ed9c7e8e5586da 9c35c55dd07ce906697dd1b1951fe1149ebd04cd7f31a0261804db2990cb6274 359f282831d45f2d2f915dffe9daeb8acfb4d99c5e2f1be17ff3671b378a80ec 1c10d7e23136bbdc3b829338ec8a11bca411d5faed84fce332ce88f7426c43d4 6a60603aeef94a7bacc061cb070fda7db41fbdcbb654a4999637af158acdf1c1 97ba1f621d285ca0222a2e31ad7685dc7aa40921f8e9dc0925bd84854d05dce8 6ac558b2d25d64f6b3ec05a6f1515f50474071883e3212cca0f1a84deb99ecd0 e490ef89f3ae5442e0e7afe3bab29cc80801fd82f32b65237208a5644ba942f2 7a904de44a30db4455676a6cea297a0bf420f5e9cfb9fdfae8aa833995fd7c65 58f12241a8a1ba839dad5b602c6ba45cde6113125e59f9052da4c832d14a66ca adef9f1a7a83deb20af284ab72e4fff3c573bd3dbb991106d40f4f725f289c8c bc3930af2f43c34e6d904ee625bd2beebd315d583eb7523c18f6958526bb131d 86e0d0697f039e5271ef13abaa28ff801f90e6bbb79ea905df55801bd0462286 c239f19f3a2be47fcd0a23cf95ec09547157010d8e6efc3315651f23e2655176 99e7300e40160c9b8dea5c066c1578aedbb8c9e35eebcc8ca77f2b2ea2b02dff a1a55f538026ddafba163ba90b5f348df85a214e35420cb11477d8391f62031d a298dec7818c28ffb74b359efcc38eec4b32c1e73e0e8881febd3bd04da66040 b2bf08059fff6b7ac09b835bcfebf106c4386ffab05295dddf769653be295a54 6a3938a46207a8cc52ff35a881a7ff5fee19b918c8d354ec074a2943636508c6 4e96f1e895e106ca0ee4fb9ccee77b63ebbb14c1d514269affa917a0249413b7 4f1e9be08fcee2d1ad61a1fd15c8f0c9a1aae378a763e1a953c96254f38b99de 8321c7ce4d12a3ea5003bb741646c771079875712d53d9ad50068e88b7de9fb1 d0a5e457c374b7d188834afff3ab9aae45c86f7db697b26b21b7a8220563c46f 4565759b70e9741178085228485c81e1bcfd8a8ed97b9e80850b7052c3bc7ee8 133d0f3f9a55c3e714eecc0d582a6efef92f78eb607e03bd505970d631714a63 83a5bcbd0ffae9cb2f11def4f599cbec5bfb02705415ab68dde796c121523a06 c9028b0ade18d0b941882b9ad366b079ff9b1074c0dc2b9b1286f2e3b8e6d15d 3fdeb6bfffd1afb9ebfd745e369eb82c8a328985803ae385f265e7c7c5417370 e24eb8851842daeacb0f9710304506f90d32cf3c49ea8a8463779a8ebb7add0d 25 91699a92fe43e1ea98614ba322db6376e183cd772112f41bfc616da7b5a8ae0345487ba93cbd8cd70e4991486634eb4033e06769be384223ce423f2dfabcb8046b6526a18d3fad7866bd596a389ffaa41859f65f92f73f882c77b3037aaa16070aa6a4532d034356090206306fe901645c5d779ca039645f7ab61908be7d9d082bac632faf9d769705c528d02af6b67ee1a36b15f12c5778a49c37735614b00039d8e5e29b4c411dff1ae7d0a92a60fe069e84ae4583a5099103768b82c80f02e264ed40e4d965cdaa9af657a8b5be12975c453cd9db34f0aaf434fdc170ae03c73df3fa30ce5847ca5c44b5d67997e3deaf0fb1ba9fc5acc0b1acb685600d0b1dd56bf8bff45af73fee3540a57a55830e3e7aa63f450b11f9b5421ffbf0af0d62e5f7904e585485f939f8fd99fbc93ba3ea0555ee2880b5379741f166cd800f7d4cb49847f030c49b0876f04003ce065442df33f687cc6fbdf82310e6d08a0fea04dac85fa056c299547df83280d996309ee2420fe199510c346a3850e79b01f6ee83abd38802bcdd6a7e6ae198946fc6d706cab83598f3f84299becfa1e00daafc7f4d96701b59a97645858c802b54256abca1ca596d22f18c9f440fd5d10e542ec3066c2412b7aebd229a9693c2751070d55ff1e248f11966c03ef3c6ee043456f3593f6eb82d1b99c21a73c826ca0570e8a93790c5250cb3935b6b62e00075c09978b2a287b93f30211ff1dc8a06e4d44b240d3676ebe738fb7c498b2a06e61bce59d9c6aa2e90be4cf1e62de6a3d4e329b978eae0284a7bf36228aee903884cb456c866b6ba662d621f153b30fc1fab7527bc8d3f12336f9d4afb6c3e0eae495ed06f2ac43ab52eb144e148ffedaabd544e16bd99d10951172f1b573c0b08d5fa8afca8e3c5a4ee46ca1a9b8f3107a1326e09cca06e83590e63e4b9e70d94d629b1203c54bae9f329105e9eeb447aed1f9ee2466b918bb36039e69d52075a0fe42273b217acfcd403af135c49b585e88bf3a8a984ae22ef4567878aab0e9fbf012e019f54ab863da4430b62ef2c924f2c1fe6be41d86303462e24e2bf092b3638c9d65968d158122b9d6a964a94d4d93e1a4b066f24341c95c5a8a9540b73ccf7b95826840f3dbce8cdbfed75e3ecb3857fbdd3ee13f69a110a96ac280bb52e6fd2500f35e6d619ba24f47a50346efa87a3ee50e97fda50c6003252e10101bea9ed9723b3d5faf71d1a573c5f1f588ea06ee149519d68ab52d8b70124055d056221d9c5c72e8c08375ab3c960ae6820e47ec0cab360b9b98049b8c7cc07a599802a7658fe6ed6527619040db407226db299ee03733be5d92037690cc202f0a828e072a47936ee3ea94b5fdd515e7ad58980b85c79c0338a44cbd52ace018984eda632b3e182c2baa576243ec05f772d07b3623dc54611ed9062f352cd0357df021827ceb55bdd7c11321f6663264acd85856ed7dda036241e6db096a30ac7d7b0ace5df2e568f9fd56d2d2071ddde4805d2cfc005ecf74d99c5e5ef5b0175a54799f9368c2f4ac6d22352dd6b0ef765f19dbddac7e1864173f70a19680891fe7d839c70444320d0004c0de49f69eb0e19095355d1add6768e0a6ab8bb07d8f9e8c83bb088a182906fd0f0a5fb211f0ff5e578181f0d2a5241a8aab4e30141226e5afe62f7c524df3b447ebd2cd0512eee099da450382c9d46266755cc06ebe0e10980f777c7204b50628b09dbb44d04d2a5066cef4c03830178b2b3f40923fe5a13c683dca11086152475e9e3c78320ca0baef3b20742a15225522fdb004d8e0d330d35e128ef26897f39f49f8b33cfe292209ad6409e6f0bad0a30bf06b5ebf734a0774fd388611125b9e74c2943b5bc33409356c9af1965bbb4ed5008a0232979193615dd2ad14065515f34b77890c28de49cdb2e8642fbf7ac251605438ec69cd43f0161f913de67729f2e5390d84d6606164dd30917ca54b9a84c0efc9bb6254cd6aea48fec1efc9a2335bf6cb232b406e925df5853630fe8d7ef06a75bfc6b9417f76e4d22052655da4b0f177df410310efa14ddd089f904aa8c0c459c0b20d106a92902828c2fa62dd8f44a03de236870f6b2c7c649713607b104d9d83fc4624c793c933a806a5fbdcc49d26094025e09fa63970f436d56bad60f4af3a66c5729237f613fa7947521e66425d4ade98222514c6a373bfef59a0b098a0fb50c7f72116ef28d4d488e4ddc92a66ce2e508954364f2f1107a6ccc2b03abab11440ce824f3aaea307294baa0fb59376246c40f3fe42a251c39f7fa6a0e200d7717a9b5585dab5e45ade7a1b9a5f27569b9f78988daa69bf81f993c4706af089ed739c7482f430981a29ba377b7734465f767c8773bdf5719856c241c00d229d4e42b4f5f780b74412e712de26c63a5c1b88bf09a631fb47aa6e802470d7d3f81375c0e0c8f8635d2a8bed3c93c0828b6b59a0c426a22e1889744e96f0a1a799dfcb662c9bd87e7b51eed8fc0fa28719328843e443ec2f5187ed5e58102dc22a0e0b41e98ce363fda693cd1c0ba1a2aa00b513260ad8943efc6f566cc085ad495aa0dc142edda93a60a7f0eed7e62c46dd0d0f8598f8c14e6f7d3e1a005832b30d50a8dc2cd075aaf50af96a494c077462fdd283e2a8ae7462582ff1f0eccd12217f9d4bff5e99be831d4d21e0a5629ab5b12238d9cb8600f4b101ad80dc4d0d62047fb5986ce9f714a831f39a32b9b90d9aa74276658b5eca31b894905af0c026d4ff041bd351cda99703ac9bcf057a3ed5c4a7c6de834c8f72e60ca0291f8e60efc5db2bd0bc02c47cdb5dca7a0a14d6f5d24650e78dd885dcd4b5c0fa478327ad6e358d54b4e5f6eaa8e7f0ce2d9922e7a1a15b221f6bb9f3174ec0b91e81ecf00d141212b3e51e3b2e8fde71c1e77c3208f2b3681841bb6b87b8a0fb903333460153249e52af97a82270ced5e2f3dea8718d1665ce9e611130faa0c0cc166cf79ce59616237806eff24a9bda63bf2ac5e6d48979623cc736d227608ac09742106f5bc93a9cce7d166260b313da04e19b31bde9c3887a3180206660e6ce6d1c3fc94117196c4c890ac73c6694f9b414a337cfd264aa864d6571aad04ba86c688d497372732be3b6b6e80a1600e9bc70fef1dfb1ad72bc66c077ed60ea9a03b83160cb86e6d4cdb41c3c3e82f163d2507b182aa8191777eb9c79eac038350babc394bbd84de52f0ab1cb5f0fbaa30680e304fd470fb7c6a2144a8310433f9f7972fe04b84acf7bd7bdb112115a9abb0a357692c7731d8490faed54a09ef095859ec566a698dd88ea4412bf3d62059acbc2a694f639436dd60aaba4f0fd6a180c5ef697a299af6e6a18461bbae187fae4762307ff28c29df48ed647b0f7b486e6966565f4cb03b0f988d520e2bc9465daa7f97b914e0678cd064751b00aca3dba380883c0353195bd7f261d67331708c4f602e2edfc43ca987b47b60056ce116ffb54ce23c2c767b261fa90d1821bb3efc63af74e9ee21ef793fcaf506303d3afd833f825ffbb8117047e75370441703085d86a4a64e654d9d261d0a063645166d6ad995240f0c1830b3fc3a485410da57403b9cdc591d9db2283d000bfd47c4d17cc2e024a77d45a897c779473c7e225cae0436527b70bc782db5000609fcab48484c8ac9a513e86aba1295d7dd7b2bd97cac26b192211386c5d97a040f2bc0b48ef85c5021c348b98b35b69cbd6a2eb8feb54949b7c70a7158e16e078ff54dbbb6abc552f0559746754e4d5feabffc5e6ba3affef36cc01c78def10ea4ce6de40fa498f21c22d434494eed600df26622d06a54bcb5c8cecb425edb069b4111dc66939082ff71822086fd4e5fc6bc4d1fa6ec15575385be72e084490ddc1be5fb2d581d5d909ca46a0796461b6effe82963d0d571a62e9086278e8307d94f0e9d952413a08b4a0733f704e4ef56486e8971ca01967305e9f9b6f32b0f7cff615d1f584cf5a72d99aba4c401f609a6e495891200e6163b9fe38ecfdd06e69258f73492a51f5ead29c642de50a4853839c78e5bcd9987f02d43ea860501c5932f115f12738783db8ec19ae959a8825698def6fc56b1424dddfb781e4201176973e8c028ccff37f00c8466f7443bf24f0443f39b02b8310d55d7d3f22e0615a097e8968450698eaf33978b6abaf7309a8b3ef120db57b25db0d60a32d40c98224cdaefc5fd58c28fe63810303b3bd856d511da92cebb5de3f5967463280d4d8b57539813f692e3566d1981e35e85d891c41430f4b73c0bc58ce2290a480c26fba04bf8b1a34ac21a0976b9d7741e5b6de64c40949a3f3cf27cc10807ef01063f22490855680a800a0642e982ba524ab62d972960d90fcc14a798268500041bba9fdc494310f11411b5c6114ba48f8d796395075b7faee63712ff463f010dc5ed204f68692373dae4d5da1399aa47d4dd5b5395defbfbdde24786bbb28b066b46e351b6155761543790ce065804e5264f0ccbd6fb952a032df317b0d9620cc78530ed46ac12c9162a4c840b8dcee4958c8a334820f6070db308e811174d01915d4bdb08ce81dc320ff528d0ba126f3ec28cf95c8d83dcca655cb225edfd000a939089c26eb8b8968d3064d3af109b4a2ad71a05cd167720f280a2a8777b09a909c1d571a79e045ef7db071134d26aa241483c205e667e77a4c406a5d3f1038b0895da9052b2c2fa00b26772529e7487069a48c277e294bf0ec4db923ef000bda2f96f9df6bbf3eb15fe17b077a8c96db63db56af40745a6902520ee797f0fab36b30a38754e47a88e379299af6ef2510bed802b110ddc9872d52513c2ac0486ce5c202dcfeaa326a67ae6c1195531eb828f7f605fb5be826ecd4ebe1b4c067e0e8ec0d4a8c2429a4314d58dbe983b78e0bc88bec77bd585dfeecd6753b807f280f75aba2c23201e555173e9d19e081b23fc18f561567d1fab358c9be7d508f96b353c5fd1bd9aa31283b4a2157ee947f095eafac073aceb2239ea96fd590d2bedecac821958188dd1ed47c7a5aa9ff74ae83d7e00e60b4f618f0647e6980d20c42b9e8765c19f739c505ca33158596e4445efe28298c9ddea8bfe174bc30a18432db20369124bf7f24c78110e7ff04b35a2c8fb76c992f7d820d526d04400ae9ec601545269d6ea40c6ffe90be99a4605b91f1f2f2c6da4b2eb1856bd030944a278e887c80d63446c74aeb34c3209ae9bd165ce39e2b5097b4f2d0b175b067512b7373c4431ff39e448675481311888ea483e4f4363f28776ebb8fae743035bcd5d91a985d0c4372b14af50f9c26b92cee26887c30d20a822a8404c99db0728170d61d523f20bdd125f3c4903301f4ba2f957f2b11e487cc73b81ac28d609589975c0c87cda5c8bfa9b0ef1ea60a8f5dcf2b8c892018a419f5596a80438053884ec38be277792183667eaddcf424645b12684ff816bd1d4482abfc49d480f2f038784dffdb22b7d60d6b15449b44d4b2ab4443bee8de5a5c22694f695ce0abbffa1d34e3aa8427b91d21fb4bbb43deee1d6fef21f0136575dd7c7484b670d24726ff39b10dcb41798923b2fc1489d22a2e5a95e1a394b8c89be2beb1985073056ceb10c9900ee4a23b3dba2658db70cea0f2a14576a17a3d4c46dcf63c902ce1b74ebf3fee12c55ba9e61c88b58303d89e918d12b96842f9cd686a70bb20ceef9cbbfb0d7f20c0ce6e95e93d2ca69b382132252b5c76c5c588ac07b98f7014324a11c1de768084f4c11c09ecaafb84fe934055fe0c455d81e0429fa74510d31f9fefd65f25cf573c588baa13a36ade0c005931802243b8e45895fb5f733022f1c3039bf0e353d63c790787b32e963a5b64a6a055abb7fd65a02dbd862eb07a3c25bf473bd7b0c6a319da7b36d7a24b280610bf26439f860c6915c1d72d5033930162f0a344bebae233bc3440159a5517a8f3eea84b5911d2099d20c099b092fd75579b2cd71c0221e31d55cae5afaeb221cf80bf24029e10496f1bea42307cfcd880562756bc12138edef7f8f256ef7906068832e4db67c1c71684d0dea05d6e8441102a9fae0e1e1e01854354a00b2e510c677e37f7928657b28f900ed080fc8120d61fb0ab548d74ad1ceb030b271ac6a6fbc4957b7c74b326ffed88306625f47d9307327492a2f89e05ed78422d300eece87787bc09fbb159462bc250b25b472c34dec48a8a5e6fc563e535295843cd6940c28f8fa58c5b4a0874e0f0268f81aa54f62969d9fef3f50608ed0c1d9266516b2d459e7730590d9fca7b70e2cd630d0b43e216264eac09d2e53eb7bb27b9b708b8e4f20d9b5f2b92917c90e1c13d02ff1c6af4fb468848844e1479997816a71c57f617b7a699170409a580f54d0b139b858daecf9bc75dd77baf10cb699e29e982b8c8deab2075388cde601739751a4e4e44084cd919b3bc0a45dc32c9d5734c688e0d9a6e693b7d12fbf02756a38aed80dc085ed934ca0755785751f4d3859f06375dda170b6a088e5ec08de6a7c4683d356c58a385b20efe7d3f2bbde5c7c9c7ed795db106cecd680070fed9afb5162564594c40d2f398b2734b41d24274023d11efe08fa540166e4a303af233f140a410f77f53beed9e8bbb971cdf2fa15bd1fc1029664f7592b25b20f20f08ce5750fd8ff3efb2016ec90a2461faaefc8ca4ca38bcc5f47f39d11340beb19222c43d0aafb2ade825e7125a967c2e9907432816db7c3bcfc418f577e042eb8d7a8d449a23a821efa8c5421b20895e97b34985c13f18d185ea359061b03e3ac695997ec614f82fe8d59a99dec3ed2984df4286f0e5b39e7998c29a8cf0b8a863ef5c6607c57d2d1996a7311a6aa6102342d3951243b8fd5262da46fb80241b55647a2e01dd6aa1de77b929d9fb0d51ed6c862d39c282d1832c0f8c11b06fca7cc3822478816988c6cc5c9dfdb009a642cdd1de78c243fa39c6df308b7085da84a1a17996bcf1a47586e76b9d149c32bbebf618fcf5be646ec708a64b406c57c90a490a0e5c58a41c48312db76fcd1a16e3528293770749cc40c2bb0b90fa9522183881a324a971c112b3dad96c3cb6052ae2adaa03d7496a1caacea7a0aab8031919839edb89e7e8c749a654cba13f8cb8344659859a379aa6a832f700667e12099ea769a1e8ea8e7108cdb07bed50ad60601513791216b4c2382135b06cb44ce9f5d4a6f36e668145d9788495c310217423d859ece5c014e9de01c430e89e3689272ea2d7badb629cb77dae0eac2fd6b695aa4d7ed7a0e3c7659096b0df7717c27cbbd2a7bb777440d3f1b29a3b2eb2aca6f6acc1991af0cbb1458d806b1753696c05755befb92d3f23c5d42aac1975242dc2049c4d4504b462e65410707623ce04282c159cd1dc0eb2776d797e40691526052f717ea0ffec3353fa405e95fb65467eaab4fb248497508c41d0ea71554fb026634fc76960e78ae0f0b0432e799657f175738a62f8f08afe00c43e442c93fbf643d4c2633831a4f5fbf099f3149fe42194f5aa19168b4b5f1640d0a4e9a484464f365914a6251d1720b018579ae58b287f58f8961922c015417790ccc5f3196b81a0140f2a9f2b3a12a037f6730eef1b164d9331ac13ad44ff1db00dab5564d2b57729184312d0808910c38c6247da6dd22c1926d957ee1607527ec835042b47b078628e2c0e154fbc3092a8bd2b26ee18f3be850b06f74754ec40a1a4f0a9683c626eb541d2edbab130521b1c980bf71acc5e3360b90bf62507b9cfbc2e668b2e0b95ba229fd6f7dd9095e8899b6bb49866d68a7d6475c6c305997fd823e265106b3622bda831b24630e5fb4d95d66cdb8e5624f09df6e95ede68934779e663da92d646691108df27b04ad9ce0e62f411613fd0f25602db2337ada3be3194dfed48168db6ff5aadf0608b878e66008ba56da671c1d58515fbd5b48d2fe120dd0745f6c64115848e0ab061c9f9f8ee13d13614331f628c3f5730bba0af989d86912e31f80c2eb8ade5e08043c58345d18f20cc71393414f8e052c987d3421519b665e328146bfe115ce0cc1daec25fec9bf801417ddd038c9f01bd37f38ddc35189f61d8b97aecc5356002394aa1175b5b234208ec7f639c5891c2dcad8c773cb4e65cd9c75ba9599290158c7bca37c78ccaf3e4fb04955d7afefd7a8b17d13b1fde83dbfd7e8d747e402f2bb6f5c271e44787e787d5be836a83f699341c07e1d515c4d22cccd9bce2f0781d35ffbb0e35ca9aaa5d8ab6d27c566b42f74ceff822a200a96f17a216b240ba0da2a917a34d256ed6cb2af3e8c4172eee2263cd85220e9d677af879d31da0991965eee5e81fb7bc547c4735201d798a3bc3e8dd2851102a7138ffec5892d0c2aca6d8610104621f0f54c78e68750f2e873f20831ff4e982d5efff258decf0b298e4538d1c55a6bb163985b207156d492617add7381c7b387a6f01adf576e09d36d62e80bc62d77f8ab56b6fca813b24e9a0ebad9a44723eb8657bff211c50c0b7e6ac8d63ea9cbf971160e857dfff9835e49c47bdb930a4920958e6abfa70c12d5290f2e7307942b22db66b6673a5cb3b96109b43ea5ce59acdab85ba6e30525800e98d5cfa6c5f5070bdb0109b37fe14c68c21310659beec8ee27f62aa50c31d0a0aa2d21ee33f4723870633ff89f776f40ae7ff9f1425ee32516dec4f200613837fbe1f00179b58cd6a678b53560362c5e07b770211f1bd297033b22d40698e78bcd093dbaed71f67fe0b1f8057ec3a0daea31fe76be6387f3f66d4f7506bf30d809b9fc3c234587f6b31c8d2c07b3d88b7f8fc232259de33be47463510cfb87f3afa13b67e44e650c26610672c5f067740cd54201984b07bc8cee2f0e02277b0a72c46b8042da256e57d1c3eb66b124335bf97dd06ee20f91cb83e48f02d163b34b853c800b507da8505be1a7e558ae5e8f8c7e7858d4403ab8311c3208de79c79f235612f6137730ea4df4c4e0e518578e3bb6b24c84d5f56ff05ba3055ee38f93d578422ca60e6ee9d893a95b378096ee8a164b6c7e403cd5e754df03075fc826b87553a67f33e93e6dfe51e4d2f242f4222cb8bb456119ab5ecef600a2745642e57ae63e62c2544720d3658b9534f6ffa010cf4032f5b3f16a7c4108bb7ff357b070c8b83554fc06d1ba2881278d28be137471c72a4e6af08c4afd0b91fbf9395ebc06572c7875b43d06ab3e4d9da771c1fa3e5ab78962d27d93b50713fae3be2a4a59675eda0104dd1b84cb42aba8c501b05c489f10a744acf02f0250bc3d744c76e474d5f2ca2d49cc87589e8ebfb3611a9d370227d41e65df200f729d4e28f0f6d07612ba9de438fee323e61e1ba275b4fbe2cb24940feed4240ce05e7a5c6a00b8ee8bee51fedbac4ddecff70c4c9eb061d724bf4353c7ac68099ac8dc498e8bc9cad3c3baf1bc36cf10dae1bd63f91e705df6a28b945969ab06831e4e6a4e7ef4a486c2253810870b1b6281a7e5191c4efb5fbb3e0d4c3f16016a06c9cc206c116496e4ddd85c7302599c1345dd7a01c5f5aea3adee1cc88005e343b5c5f0856b2908f6b7176cbef56123e07d666cb61b407ac310cb41cca8041a11515f6b66ec23110ba4126d96ecf2822fae8bfa98ba130e7d467ed93f280bbc20802a528bce488e9e48893597f20377076f0d134effc68e343584c404f703a846c5adcb5db29e56f4b6d58e74296f6c38ca4e113bc6f175994666b3f57a01a99f216f4465a29c195fd991165fa0a50e3dc5840999d214792d4d368c15150f5142626b85461ce3f0e6b4829b2e121f64c733a60226530244fad41014774e020f6939a396182bc6f638cbb64814d4bdf6742a2798f4da39bc9472cfc6755c0a911504078a3544e44d602087654928e84d85aa7e4087f9e831c05737bf29a108012c93376641f9e78a3059bb38d9e12c11a69e4a87ed0255869c94b02bacc70e7622d1c84df9ea82c4ac6d31de599b2af9f7ca9fd5b3c345b350b9b01c21dd0c8c101bc11725cac963e593d3bec607cfb393e09695300453574b23e01fdc490838ad57e08dc6b852d02abb7e4588dc708ec9d5fb21db2d70a64b4d19437a5e0439d95da018acff669c5fe760591541eb0dce5d7104920202718501cd69bcba0fefd7e9ad7857bfa1b004f41ae97e1352fd9c8f5833660dc677a78bd15243a90225d48df8c28bd5faf7a8cd221f95b6d38103ea4c3520cc4ebb8156f5450b680c1e4ab0c38e9de2d871ec17bd7916eac380f4900f965ed4e6e4a76c2ff7f3ee013eb5bcff371183857c03f62ab73a6cebafd705cf2d476a9ec82689d898181f0e52896642ec8b96ff482b9d1dad4f311feb5fd9755dff1f26ec9f755e910737008d00817779f5ad405700f00d2337e38dd5793d0578f7fb26ef62f8363c86a604c9258905bbe52992be611ef36d7814296aaa2fb124411dffd2084e88a46632046554604dc57863e7e6c02ad8ebfa9b7b58f24ed0e7495eaee3eaa23f60decc03a5d9870aaaf3168e2c4c5b28169e8d34fa8ccbac6932a277db6dc628051de20c54289e5b922debd3029cfa453232b592e182b8429ad33504ec30021a48c5da04779395912260137868a57d6359f63be0c4f7c80c742ad73e2a7518d337f4b60c2c6a5371852d8d3db84093354c7d82f6e7192da0bd27c383ec20be13fa90140d132215ad5160a3c245ae9d9272aac87454de860e2fdb08bdf9a6961021c90a01b8b0a7c2b27674d231e5766f9f206284a2ebc4c72e792d8fee29caa5eca92e04bfcdd858480311131ba4ad3305e5b4e2f8370eb3f1dfd3d14a49f8eb783492028343860414a5ab3cf645da149b623a9c25a5ac2eb16f6aa761e2436426b003024818656bf12dac5a2dccf67be874458e3f28764ab48861c13c03efd1f79ff202fc362b2911f386d0f7ab062599b881399a7405eb0ffcc3ae90d611bd92e8bf04f5062c399cd6008b46c7f5a72e608acf21cbe708ed72d7eb82889ce8edce1203add0f76ae8c2920cca192afdcf8dc2cfa027b3954a6b135be14c7916da25e70e8502306fd3c50a9e0477ba7d8b91730e77c643182ad3aa4a48f9725f28ec330b6b8f2d0cc4a571729dca34099d4cf199a0661244c17a02ae4d9e552d13faad09710a3b6b42ccbea9f615b001f09b02dbd2b9ddff9a923dbff04aa61954a9be0ff1b8500c9e0796a17b36f447191f5a5159a03e2670cd0e8cee6f4f13d6591a080f84dc2b10c5d663d90133f86caf52f7f751efd7c46806bf006acdc21a1b07073aacc92f5db917564312fc8d068e5dc4225cb1230454bf989d3c3c9b87ace00c11d019878d3cf1c267965e4ac2e381f8d3bc33bf6a31b684b9e4d3c5491bbe0e5d368965739cba92380d58f7eed8703eaed23cd0a2fe7f6656e05449604ef505923f50e2dd5050c1b9691344a6bd2b63312cdae32385a4153c72890baacee102da41085079ea544bf09e228f186d8b94d6fa7615980459c9ceaf0a933e4ff700f5156103452b7466d8d3c9d0d686ea0fb5e39feee4511abe3c73fbefb0612506140e9cde797fc0cbcee9fe01396a294064a11188fba3d8c749e4909623840607eccf527978073b6206db80253333e427b65c03075fda4c9901bf9df87387510ce7f4abcdac44d4d2b240a859ed839bda0dc6abaf175b30de9fedb3c99097910ecc96b4bbd92023af202f886a350b6d128599bdbba366af266582c92cd661630b939fa1604c47882585ade45814f94d717e6d67a52f5fe13aa9d69a78fe41a00669bade2d2ec8ed0197606ca09ea291881c061b3ce8b4f2b1f5088d839787730f4f232402962f89d359776f81e82fdb8d90d25c0f396a70a572760e69165d2201671b0b19f69a641bbfa7e420348347301397ee1206e6da5bf67642c7c830a50676813e6251feffab2e587956de1cdf619efc0b0dfe85bc2653e335ce1e7d010b15adc24eb4ba2a064ec2b78724bb586524788386a1b0ada4f8dcf24303993f0a4b0049d7385396d764d62d87de60b2f20e7bfeb771b4f42fadbb975770f4630ea1cc86ed9825950a78e9a5c27e5e7983c61182fcda36e75423d87ac9041d320abeda411ab96dc4bedded92752b0ca4ba8860bfb8279fd4d17374c606d4e09d0bc85ba45eed1dd4f869af265f032cf89058adc0a8538ce8d3243f96123a430c0309f8a5ccc588dc9d7cf08824d789aeaa0a405e687ba7b97b711da0912e35fc0f9c946ab6cebb64b0133e441d8d02bbf061fb77cb36ca452be312e0ae699eaa0425ed7d62876d0c945545ae1a3c9a1a4f7cd5b3764bbeeece90afc6a629c8f90f5097b9e767a4486d4f8607ddf40dd25c2df16c961b0ad1f75764df8a72aa6907f97e1fc0c11c5627b95f68378ea65d726f56708780cbf0f076009783f6031a06f3711c43044c89e9076f1d9c57c5aaee2d921a6b32e2e88ed91b7d800229b60d26abdab5ada93edefb924150504c95ca0162c49d45e234c1f4e26a2a96d7ac01e0e529d97f78e0aa1985b31c3750e4c7810e99416d7a09660732f5671848e909bc42fb8784dce3728579d04a09615c6a09fd49e1a4f985009672037e34722b0c77c53229832750befd88f80aeffa6f1475d873613695181a7c9fe64e9e8f3c002aa73e0eb6a21a85a512ccabb93ac0e1b089b2ad900f717bd60841008e97400968ee123a39eadf024077247a56cba05f8ea1e4a8b0d616498709041d3971960d068487d9a6d3386c56574c6ae9b1fee0aa09c33b24b206c3ffc8e6739ceb910dd7c12d235ccc5007e1c91b91e9100040c75eaf3bcd41e5f5e8c62e84809a050effcd505448b3adcc70db588b9782c09dab732db476aa483366927f76515f9502e3012971da123c8ea5e5901382da58cd269bba30a9682737bbdef4bf901a0903224e938adf0ea5b6927456fc08132f6d52411f53f5d41df9eac9f109f8d39207439b510a791516de6986a5d008364f2e006313af6ef60438ed42415d791bb70b090d06eb3dc7f597f9b582426277de4b7eabb260e647366adbefa72f45d50f047f0be10fc5e9064885c66ed598e460311140db05615192e5e059c55403777a062878628b75db81fff138611fda011a062ada194cb80e2bb635e657d4c5773f03b973fed6428fd0932f21a7ac026b8b2c94dde1cd3182d525211982a75867360b36f819f2359665c774e72bd24091fd7c4d9160c62fd92367eefd9115ccf57c07c5a61ad23406fbc369ae3e1f23f635a9126fcf89a525d7f28e1df60a83d0f9063d0c7b57befa8b2ab425b43301d639f7579af638eff5ac1cebfb0f1dc053240dd018221c868ecf390722d013b346f21a755592049eb55cc066bdf9a613ac18013c95771c8e97d38cc2591a8e6d053145d3a4c15b71effb726bdac189af1b7f0f0e4eefe9f006c78ceb33f4f48fdbd3567dcd9a28ac763beb1a3e2e74edf43e02b6a0e08599d58ea64f8732a8fd2cb39e76ec80ced1212ed5e35cc7d18c2d770eb4d7e24db9e651bfcfc9e5e22c329c846dbc42712a3009ac257cb6cef04d760bd9c23a51f09ed2080f72b3e34f71bab5a601458f2106d3e6e6d6d7e6c03e0b0997daf163144ed852c2200e2450be39258ececd5c117becc500ac5b79e2d52707f43b12090c31e2bf9abcc692263047243c61dac20ba4212079d5a2bc364f1001966a85595fb413102a7aa056cfa886363d55cbd9ab0f58a365e36e7a219cf10b45ced70c0b5f81793fc5639d7dba3bbb06a53a81d54e9a33a26b8b005a82fc083a84478e289b3fd24d3dbbb5e5730bf9cba3dac4ca5dbc362935b971af50920c9eb46475734f7d42f176e78c8a226baf097f74fab4a82ba0dd721c50b8e01809718cab67b368ecc007ea05783cf80c464d7acce98a44a6eb2053393d3acaea04c7c88c0ddc657b807ca68ea0953823186097c0c8b304ca516a1a39cb35d4c20fb2072fbd0acce7b174f4f81726a45e4b032b50c5fc4d50340766c941c5d8460aea6f068a4dc113e8c6e412b14e347c073643f347daf88cacfb668a309462600d257fe62504693dd813d55bd5e5b6d75c6f24dec3d10fa1ca8b062deef38a910611399ef2ba65ce299a088ce2f6760861000703c9a8b63819f8cebdd87e0a56062956224d5f08319ec945f50f57fd42fc98af19a02075e0ec217a747dfb3fd70e80a57b31812e9995f4780870d81457ad3723a0ff1b065f3606482f2b64d8090e3231f373245376f49e25a2a925f058b632c699c32e4d85f28db31bdef4786f0e1432c8af25e8a66fd924feb1bc49ee1c418b0dfae82991edbf9ed677c82bef09456942f258efcd9b203a140a0352cc84fbf276c94323d37410a474130d4ecb0f76814c9830408ab5764f1bcbb6a7048a4bbf515826bfe8282697a4cfbe7eaa0c65895648d1378164a9bc787d3e6ccfd3dabd7d87d9053b53f8cc6fe88279f80c2df6eff62c7bdfe626507a67ee295100fca8b1df2e6887516177e727d08d5a0332dc8be98862c587d2c44cffd94cefc7aaea5cf195643be9b0f855747e44c50b45fa6057d9e3dec3a7af9e63b8650f598504243d1a7439b5af646692f1de92008e23015b9f5057f78ff5aee33d946cb38bef508caccf03965d1e16042223950209de0d44c16488482a4bca2c4e882952d57f22f0d58ad488e5fa25395a4d6309ffc01afdd5d134a9423f102254304d5339a2d0db63711bf27e00622373e11c0d35161da5f4915e520aeff3e0d644437335e18d9145c38078714f964fe9774702ea31907cb1e0443338640bdd07bfba58edbb8b3f3d4a0c2d87a503360c78b20890dd8457408b712fe95b93c8eeb81224ce7373ff394857d4c0b220ab8b10ca086a3e33782e7b6b1fa84ea82b97061f430980be5595d0493e80f3c20f2cd10b0539f97352b592d42e00091fc312860d6506609f68e682eea30c972b50a53ae70ee812265cdeb9e136f953e95930d367989c2fdf7a1a8c01aa07fea12ce29339062c1d01eb0997b7e606b9112c48556e7254cc986cace4980c2f285d492383d30eb452e83cc6c4a1f04d469d86d8618c180bc92b722ff0fc66aa4db222c0bfa00c36d9e980a6558d3aa912c3c198e30ba06610a2cf53421565974678b4035d4805973c939dfcdb7a35d325b4f22449d1e83308b98c4be1351c4647dad678563d0e471f2fa769a615ee51be5bd56810f54e964eda3a4a02593e1dfe729a0925a00c3ae32a9513eb8577d59c9ca6ec8dc574cb5e6ced89e376453480dcad563f350cc5079a8f55c252c8f5982ffb66fac1bee2988a0ef6f14fc22a0c7a5f2e2a2107f7f5d0209f0bbbf09da9e844b1a3f59c4c12655664b146051d557ecfb3f12905a7bf8d0bdd033edb4ea70b35d1df5bf723f970a8717d83df9cd4db3760832c0218a302de4a350540914ff78ad63cfd5e311a6edd172084d15fe7cc30a3b59005cfa82e2a744966b85244b494b51d913d3e3a461d72da466d2e44092d451eac0614e3c3f981e56a488dd7c2655048e283197a3cb4223d6b38df3262e20add570aeed51819e04b645a538e476442782310782df1e971dd61d7b77014a464198f04711e3a7c9bd6f62b37048446db74080b6637ce264bfb901a583ecdb3f01ef404c2ecb491e10a299eb20be84fbbd929d833674177915b88338a80aa4654114d08a8390ccc731fc443454b005c2fb964a51b220cca7e6442df825b812369e6960d434f9debfeb29a574595e8126795bb75babb700f79d0813e91a144b2fe33d90a6b80d03374c62edf0a6b3b56d7b577b6a8e515e1fb0c079012cde87a8b6bae0e493b7649d9c76f48a7cb30a477c77eac6689e5d7db9512e3275378fa9a6bc2079aa5d456da9a504906428de84f9b34e0df23c264b789d79aaea6c16db4f81c041bc90fb45facb255dfbb0e5d2521ae74fe4dbcc7b056ff6a2e19085455cc9c0dd18a86e5d1ab695905dc95f39f653d6db128a281d3d08af9ba20691aadc4170a6e4a3ea298fc04c45fa7a2f5b8007ae277847128180a2e7375b9498fd517130baa931b6826a0a20faae159a1087c4e2ba26034652c0b38a53b0aeb96e9ca0b0f700ce71e41249cb4182997dd04393d81131d579902335abb5a177c138865c20d0663ad8395afdb154c78578c58e4428907bd3569b9d7cf58c0e1c53f3e57e305d2d79d0f023944cd466d16212f4501e2ba289883b151dd553908141c28f3cf00cf4894d8e3bd4f0bd4ad4403a72fce4822ca9eadd4acb82cc086c164735131035b46c652f905f48bf2509b2a78150860f4ab8a8d65dc610dab2d453f12bb69036119f0746eadcf8a4a03b1de0f8c22f0801884334a4b027a0a47d3c4bbe0460938a3f002061ffa01dabda2f96a786a4a19fcd0d0099d1a498c8b76004732ac0f5f518d07a775fed793d45508a063c3fe77135cf68e512d2093bea41bf7d9ad0e67466088f4f5bb5614b7f3822993b66e88fd118b3c48f9e3452314db4f884208e7622c37caf11e219f09cbb503a00f7f2ea0d7d1b0147ea225411ac039b88a0b4989287f23603a1a32a19823f0e238c7418e3002d7c8a5ce212b25108e738101db82fe2d88d5ef70ed231804e1716333e3cd21f8976c556e2af79643ae21100755ac97b7a5cf7e660ec162a4dc7e6661d31a804a51abe6178f7ff2b4a5cb0f0716401d87bca54f1d10b3ca6a44457469fb4052cf008cbf4ea6a0292de65b7b085e630d2f9f57e0917ba530095a5f512c236e4888077c64eb3fa43b70974eb6041e71305259839f7cf236d1e66e488204c108c9f60da7369562bd9439f9d1a10bb3dfaea30e7b1eacdaabba3696a4ab5df990fd7332c58776b4a87eef1f98ce0efd45bad2d47965c955aa7a2e4a93a6cde28e67ef7d6be89ca917b77c4d7ac30d42fb9bd5f1e5e42bbb6ea6efa84ee8a0e119a751f6be839882eaabda76b2ce0c8bb85b16b5a77cd0849040b48e63a96551a1416e712e09713acaf1f6bddd1a063870aab5ac79b04243ff3b1a23d265c8bc6c151d9ba5ce38175a736a38b63001aa96f91071849fb26e1f4293419874c887b0541ba0a84706f56f6793d1119f067a410d679e909e93fdb99b04a42fc7d1bbe873f0a6ddd23f511992c81de5d50a43d105d6db074c03cafbc6905323a0ec9109501c41231e913a9cb5ecb01efc0357c6a24a6286d8833857e19195cb37f5e18148852757b19b3ea136d2b544560513e8094a108ad8b50136d7ea1a5689f748830d234e7d6b4e4b9fd505af622a024ea25c55dcfe2503b095e085957a30b9ee55e79023c85f7a82fb1be5260f9908d63305e4267448fea8efab8c2c6c124b3a1e763b28685280c37d1adb002f680fc17a7e3632dbe18c430f4b799c3a4660faf039ad7e67d724bbb2fb9b10e5dc0ef671094a78aa561b3b55a7f48d64975d9e9affbe91004b50d9d94e2244434702613f71f6a4d2ff96c5ec14b35f04e7d6634aa8df18f7cb354e3410b9273eee0a215bdfca3db61b3961e6efc29e6036a8dcee279d82a32008081cfa4c8b7cab076f34223f8563f8f4406f0cb88c8b5f9e30ff3f37c48eb80814682828dfb77c0129c1ceafcc2da0bf24133b80bade09fb6651fbd68f2872a44d4fb47be30db0006670be7bc4f0f6d3b0cdb31276fe0deb50cd17bdab908d3f931cfb0870dadd0ef87fc22eb156412208e4296f221bab9bd2b9f628207ac5b5e2daa40257892d05d7a32e8b8cfd84db9a2c048b417b474f859ad2110ec0d7cc99a1431224acdf0c102423cd4cae34298f6d5bbe999359bf1641d9b184fc4c65ad363cb3ef8f410c5a696eae469985d0bfbbc0aab3ff609c8e88e6defc0c1a2f73d2b98e93a5ea081890eee8cb87780032722203f865fc149f197f69a597409535b11986a9fb9a06116e557210f7b19b3bd48428b6b5a0bf560e27c196c5c3caa0b2017bd6278807 -generate_ring_signature adcdb7399ebe573a2e88f555775d8df55ceef28b0f51d1256cae8f109668a24c 447ef2e9196b56579e07bf5411b980ed2bff6414024f79852d9d4af70a449870 10 9152fedaec98aba200129eab484df0a6366db49094419265a78ddc2b57380e30 b79be97e80cfdd3ab77c6855acab29c655e3d1a07a6e2b53462aa7b9ef83bcbd 69864e7c079c36ee8698ad1b54f66bfd101bf1c835670beca641f9ed37736f99 ca0520d1c7e07f43082c5a46ad0dbb4aacb97e88d7246a60a8ba3667f2458c9e 053d4ad64725e121493158de54d28826417808669ce746b807d65b1f11839a6f c299d75d2531a842aad42ff488b2b76112caf12bbd500d503f43dfd9708746bc 04dc77ff1925242237f287d9ccee87c27ebd75ac6e3a45c357d9bceecd937f63 ca3895a0d1560e67451efdfd8cafdc838c7f1fbc22a4504323ee47e7436ee49b 3a8185cf5f418483607610c29acc87d2b5b0eb5705a25252dc151d28168f65a5 7ccbafce5134beffb22c2906ab4008a62e784b46bd74ffe5bcb2386a990adcb9 f00cac90c0731f2c2eda3e61a2bbfa99255c22990d697a1008ce4a53d42a8600 3 c34e5cc292e6a45929650b358c9e4e06cdf8720eefcc1652e6e05f7d10fbdd06ab7fe0cf50b4de1cee7995ae250da3af0256ecde371d60098ed174437a2776064fe895c89b8e1cef0964745eb829dde215303abf16bd38d6152b195c89764f06a9443387b5a5a993d8a92afa46f8ad2dd6ecc9c71b0379ac7fe21e6a20163e0ee949ce04e30101f2a4776df1dc04af4a6d4665ad9469a54f2b9fcb948b696a024b6b6e0f1b60e7424b74b0b735e9232678c87274fd931ac18f7fc0064ad82a0c19a469a91a4cca00a4412dd423687ff6bd23410f4c9c2da14101cd249ce28c0467fdf5d519d4e5467e10346430d1d56bf7ff798b26e0810145428ae7621e0604994bea862bae4298b8fcf1bc25cf5f5501d6dd6f1d9aff1a9a642dbe001e45029f0248687977fc591ed17a30e572a019c5c939a892a76cc54be41d9bbf3781061ec3ffa5a58109a1d28896c4f5b2dfcfcebb48ac26452deee2102248ba46e1088ec88ba7a5a015c08d2f9f67b89b43e7f19fb1a6608d86e3094c48196d479d06653e53cfd9e2b415c0e2c39fb7b60ab1f72b6d682aa85981ff6bec05e36e8a0334c707b7c92e0b42aba055030938cb1e60c9c61e24a3ee2568b394da6ef1af0ac20735443c6033777ae285d8e239ec9009c0c1c18412889ea5a064c30359a5032701a66d6cdca2756438765e401205d833e397aab5b68da09ec63d3958994407116e2f18371d2493ee497c8add0e58e3c2a08389b0ff709eb6790a01c16ec40e4f93c285b621db15f45be3acdaa81eb61afa47b4b95017c303f7b1122f38630eb0c5d5694630f5533c8bd88d33c0aaa299f67e7c30ee766565208c428f51560fe55c533ea708f10a98fce6d7924e0c95ad8ab7f32975f2e36aa2bc69cd0ee200 -generate_ring_signature 8603bb45eb1799e1bc1fe6038b19a52bfb9ad7cc9cf44446f164acc3ca40da1d eea6a1e1451c63be7dc890f76883f56b1fe5b41921b4e9a5f7757b92df2b6a49 10 278124100668fd040c4da5aa9dcc1961b3e51c0c1c427757e00938d4584b9a72 1e7124d6beceb0fc37efdfb8e2098b24518f431bf8c0b1d5ebe553402c025b99 73f76c9a7b6cb8d8bc3996ce6fdaa00ef47e3c4c0af2fa6cbc794153d4ee0fc5 59bcb04b3649b9d1c6a697ef8465128d7ffa20ad00d4bc2f3651ea8893e75e17 8a996eeddd61f604a74434deba30fdc66efe9a92ec938471b11f88ded7365510 124691caca477ab72bd7b69ab0e991ed6f6d30e910f34997a8c826e5f9c3e502 e80acfb48cd74ae789a6591ec70de50049fdb9319c8b4cbd814e463113e97c23 4be725c440060881b1dfc58d506b5c16bdfdd539bfcf02ad5dea50748ca0350b 57f42b791c1ae5f5dbf20e303be722ea94fd993241ef302e94da5cb017802ba9 dcb72d6d16b55946296733c9638c60dff04002c51c55234878846bc1b6dd1864 f0dacee794abc5fbf38c017120a19c7e1c65637c65b4103fcb8c148af9aad201 4 f8b64affdb7ece73942627162170aded7a030ce093d1c90f986786156bda4b0a698140b00b2c50b8aa0b7fd5a8aaa2e3aaccb227093cc68d2ac59eceb0ce4d080744629f0b40bc96ddff73b312512b3e3886462fdc2c4efcfde9e74e0eff8f05b0a3ed6de5ec750cb68bef1a99c4dffd2bc3fa90a76496c3e890ec1fb54a1d043481b7d5961827c355e4e27dd79b67f03ce7d92075a368a0716dff52a35bec0bb54f00fcf2f317a7cf26243ec4764a90277d1396a9bf175e4503bad41d34900a954bd362cf87d97282c5662ec5c2c34db7ef9a2707cee69477956ea7ac99c408772cd1f86a4546d3716b7c0019a12398c06422da7f743c51d45bbde7f500af078f56333249798082fd5ba7178a6eb8f42f2a92b3ff781a4821425b96622e21033bcbb343d70594bdf46f722614b615fcd62ae9112ed56078a07d7f4719f1f306c049144c88327388bbe0088fb8af619213eee94c43b79c0a6cc6a330eba89a090a17a2a79a01313e701fc5d89bc5820462baf7233403117644bb167567ca930dce25f0a4dd3fd82f31bb60942cd73e9e49e17fb8e200acf57fec304b7509080f74bfea3a21626125b4b784610900713739222f7e73a2a547b6e26c991dbdfd0622f96f5e516a97a909d983ae811ad66a9a95134295d4765f83860ade5866b409098d5ceebfbf682dc288417b7aa06018f87fcf84bc9657af0289a1f4c99e240822b07d9ece9dd6134e026de189194270547847d85a323e48106aaba573230d0e6305e5674707af1ecd706d61fb3ec9d00adb297c70a7e49c1df9f36702c38b04956a41b2403a02c455691495ac183640746df4b3034182ddbf92c874fcc063011213dc8ad9a4bfd250103e98c73053de4d014ba146e8b92dfdcb0d2c7b49a500 -generate_ring_signature 393bd6d7e3d18366b43c7f64f94c7f3e803c05a357fd4c9ccab41f235545ee23 ad175b4b3efde3db1a37d5860d51d8c1e71bbdef25a0d88f29fdd6ed07309665 4 beb4f6cb5a63cfd76a7e66a78ed35d788947613b90e7bdc25ada761b87ea430a 0e37fe8e05c17b8ff67e4fb79a6849eae9631a41fccecca28618418746d0a9ea 087f54a5745a7fd38e45534fa0a878b582fd7d16e6705e0bd195d9c11ffe9638 3c91a5cb9c704c6f70c36cf483ff5dfb14b45958ee50b244de2f8c60e3931a82 c022e13c7fad4dc5e547e92919763f8276ba20a839ff4790f7423bfdbf60eb03 2 3a72a16440938e6dfb3fd9eb25859abc57b5dad2128a7d835bdfc78b131d840d968bc131d314a50a92cd05748666dce92f899bda29d8d80dd4590d792b42b00277cf912bd58034b9ee25d633da6958e3fbb312d129fccac46602aac8e7a1c202aedfb4a68eccc527813534ac26e1cc4df49281949e7dd8887cde8b4474ce340917cdfe0c21e51218202206c77a30b3a05583767605894b6cae1f21210800700d43fd3160d8140da1812f7a6b1e68c294d915ee30039c4f8c0cd4838812be760923bb6f5db6d4d89a2d8f78395b6961f972a47daf5af9bbfebe75f233e64ae106dd0199b0e92ef32e9b2a8d34e932000f06045674bd3c9a5f48b85ccf894e050d -generate_ring_signature e565abb91e365168b01e67f4a3c568d32789fdc1e6dab2f448e9f38d091a3d4e 9408b7dd8b3cad102645c2011cbfb0edf8b012cfde69948fa41745d9b2e0d375 1 353fd42821e9933571099b5e6cf214b0f20f3b6d012e753818641c618d20defa cbbbb2095f92ef10834a02629b43f7cdb9c44d638c6972b9030d793472a63207 0 090ccce3fb90269f460bf7fd200d55dbdd287c81fbb2e40c8403564e54736c0627389f1840c1ed4e9c063f2c9edadb6fab94ad7180df670f4d0ca30b9dc18402 -generate_ring_signature 7ca2998d7e7f0adc4ce35e5b474e47699d5460663aa16ab449609fbb00d500f8 7fc9c544c3e934782785e9f73fe032d96973111f922034ca48bc825cc27736c7 64 483168d096ddf7c014a148e53be2d680079bdf94ddccd86b087f8b33d357b7fd 86bdeea8a6d0fb1d4c7d5a173d5468a55f6787f612cc997039307ad56f2ec6f3 c60a76b900e4670551e578ad687fba402b25416433d72af5291ed69e630337ea caaacc734c97093c58dd64102a4246b2a5840c1c813c4e338394bbac7dbebc75 1ef3e4e217cce535fc694fd8c6d3e113914f0a519038690ce7324d06e4d1f8be 916111041980474203cd2afa9043cf5d9c3d636fec3498e1f6b06115b668bd1f a09a5afac52945be31fc7a2e7046862c8d4806649359fbf8b5f7c69628b4f167 6b5d1fdc1a962a295746d49938647583ea088de7f8e241497fc6b41bc9121e95 0400eb6d12f71290e0bf2e6af6ea14c37198a7e686b63e0569f6741844f0db28 235285f1e1e1a1bb6daf5820e3f9db2f5ebcf8a3c1dff2a988953d60d77c2c90 847ebd598b288b0052a82a35c58fee0e477556cad2bbf15dc60208ed14712b08 a8a54162f2a6e4fd177b3c727dcd2034643d6a43970f2bb9804cbb5f24366b5c 37fcdd2a3b035e5f5f4951d3ea120dabbdc219d9a6c385d03643a7037eb26af4 c3c68afaa4e7cc9c7cda7569cd3b0e880fc2b39e418383c4f7d6aede362acaee a14729c01c6f8c78c68f4863e384162a863d304e780cf1d87835369d6c0f4c42 ba8de594a2ebd411901147db78dce4c6b5dd35dd2c85ae6ce2e2f48f3e47c122 f9d0351c1c41aedcc6899d3c963c410b3e33510f747c1a3cce8ab1823a3414ac d8f4ac38ce7be2c45d3b74880338bba84e256042ddcdf30ff25089726edbcee9 4b33b840fe9c767bc2fc9b8f989aed3d8012edc993776b1d2476f6542ae15cdf a7b39b9014bde6702c0c7baf60a3245a70f8db5abac0fad30bf98c36d8b201a6 3905a5aa52ca2d61f49e770c53c6663687c2b6565736b51527b8332730d283b5 e9932651c0ae63cf3738fe067908dd46644f1d2235972e027beec99724d013f0 804f17dc20b27060756c20a2e3b1bcbc8fa01db1672c7aed51c20a868b0360bc 138c0ac27cb68eac5dd51b8f75d1c31a215f26b14445bcb3642fd00a176a6639 0f283696b934fbcf7ce30f78f8664d8f28c986a202a0c340b2d7d5782cc7bcee 36415f082045b4c3b1b0f805d2e6ade990723d39db0a53cdd723d10a255d41d6 16a9cec53d35cc2861126070e57d228c20f3350b93ea4b46d8b62d01f3209f20 a5c9112fefba9ad954476e87f670af6dd626898b3953a31cf3ffb57886f10d11 ca10bbb819ce71f840e69d53750dd43adf4cdc2c785e517c7edde54034a3baba b1f8df73868c6f39af5d6a71b16fae7c882cfa335115f62f0b093873c308d06d 557f9033e27f5ffa3268c4a3f3fc94dc73c2e3bc70908888c3644143503796b3 f2cad5e736f9839d99cf515859fb8464fece1f85450d5bd5558ce750e60e2942 9becaea439d210fd173a374e51586d125508c458ffb0eea0257416ae62813a81 a56164a43e06f4da3d2cfec1db2c1fbc2641b9f86dc4869e06e55f0a9ffcf751 c8a1abd87b2837247515c9736804424e235d61d6c41f90e748e72859446633e6 210074f11031e5ce0d2ac8cf51e9fc7981155fd1011745ef1e74b342672b453b 8fae668e0c5e30c77823534bb06c660867896f016907fa8b05f5a18452c7714f 0e1a32d6619800d7c2fd5873d124c917752f058318d43b66b2512aa1667c5151 6803d84d7b5a3574328f3403b2f4a79b5262aa31e6f1c971c179c4ec2c8560ab 44c61ae79c631193c330a66d64dab906514cbfec06c8bdf57d5cdb1844b2f789 4000fa60a283326fdf215ceffc849f6f58cd74b60bf19798cd6e54b6e3d8d06a a78e6293da0c64e26b788e55a0afbd8e4273a226a514cab6e3b4beb8d214c9ea 12980cd87170fc759380afa60290915389ff1929ab5de05f1e8549f014fb2b44 a1b83d3f280f162cc37feafd51e90cf6e1da6c82d25ca9ae12b4acbee46a949f 6cded174a9447758824a50352936a539d97c0977ecde4eb9df83c0244a44b89c e6a9d7f60b9d6f367befcfb0578605aefffe810cd55081232176f23cd4901ba1 13fa490eadd0b74699af3be95e1f5b2e488826a104779877768d5e10a506bdd5 5ee53f2482db49cd3373a9195fe2067e018a081189e9e0ba2500357fee9f11d7 0cec68b56dbdd3f61c5b5f242928af02ac0f1bdffc5461b5855fe58b582f54cc 6c17365304dfcf711494cfeeed75cf5e121ee6b59cd67219edaae7ea07db4250 6e801ef00a31b59ad896ab91c68c67ec24aac24b03436c7013c18df945666875 8326bacb4818132db5ca61d73897c1ec0769d9833b9ab677c42bfb9b177e0f09 2b460dbd272c99ec3ee39938db0555df0f23e8090da8e115a912e15d51aa913e c3cb48550117623033617d274569087b44d1da2dbc0257bbf45f35e3581b536d 110d6abeaf7b20668c3891fc61240bb2c3d67736f5e80361217156a55e142f5b 79e8696c0f50252f81b5f218eac91894ea15a95a48ca68594de8aafcae37d7e1 7308404a054e1005bdf9eddda7a5d0ac0b395efdeb81a655f4b8e8819bdc583a 38239bcf14fe4fdcb14d6943c464ca8cf401cdc46d3d212b4f1ee52161e3b4be 3a8bf4e796f2cd92a78240df064c3520f4966257b89e49ffa2ac6b4f70322a97 b4310494a59ac8bc4ccf06b17f70ddb789b387215fe2b73d180b3dc1779350ed 51275e0ac22a92d506d12e7969e28f060ee7fcdcaf100134af046d622ef7c8f9 d509aa1c71eaf0259e74c41d404c25ed03fbf75f249214b7525570eee1eefda7 388f6ce354823892c1cbe49d7fd79d8c62627308a48291af34e16bca292a6ac9 7831cb8fc935ac1eea198f48f6632475f8feebf686406eb00d43f4054299f8f3 d62eb32ea87d2f0efc686cf9d79d111ee668a65a48c3ae2606bee28d8dc54202 15 a333632662b109c834144757de67974f272b3aba9d1859bc2ef8c1134c63a502760c7379af1bafb7040420eabebbbd57d62386df763ed154f8083607473aac03dc69a24901d3a18d451fee65fe0f7a8164824e50405ee161280a6df87e817b054fabc2dbefed3afe6bed3115e43a7e5df306505b5ada2f1ab5b3187117ef990c83ff703ecb34cdbcb4699e39b286789762ed6d9999715df080a46ee815d9210997a83ef9369fecbef4daa6edc93fee2312b0282f3e31f4d91631dd74341f410a00b4b9900f54f9d7c232a56f2c5f15882b7cc9825d1804b104b34f1bf93810046d3f5e5500220d0b01824b4f849b3a7322ccf25596bd35e245d2d77f0595310f064bc5ad7e380fb7a22f43d2fe0c5361e5bd1ab523c488ac85b293cacbedcf0e21c988ffff0cd27c4c752473d51513364d741f43f3b2d4a6127be86099346f01c37cb274e95f79ab87c4e352e74aeccf91aed2b9eb2d2299fd70fe909f793104f60d22470d0705e2b698ee2185e1109606a0e5ed99c31d25ce85b7024179b50dd6a9d328f3dada191e642697d342337cfbea7d75d36a2bcd2d33aac7d7c35d0c6e82bd855cd1aca16e28a2512d14bc88f70386a215c3864be3949052fb93eb0e9ea6ddab0b83fb4233dde93d5829481e8f5d46fc3c16632eea27b14b5fe5bc0785e6d14be9490af7d2f4aca4de8364995c7c409c10d0a01659773d1b5221bf06386f77f50c1d2c76356c2b726dbba329099f0ae838a96cd5d464fe4a5b4ca901e7e0da04584bf2d484afd1599d4f9b0b568fac7c1a75210dbfc7e060d1c16e0c337d1b66b22a3a6c3f57a437b3cea7e8e5eaf9baf1812b0d771383796ca85f0ba136d301e4607f016eba758272d386c2f5276cb4268763210d1a4c31783fe30f624c783c8d22ad77ffe57ab95cbabc6dc3a3adffbcecc7fd847b37f4ea855b0c8c7da3c84f95e5ddcc6d0ae9443aa6427cf4fdd0d14e4b5c40b44b94145e9a0fa5e4b38b3532d2e1d85d9132ac9be44589f202d879455af8ef5b13e3f1ecb700f619bb90554201c6c11c1526304384a2120f8d4d54e8eb76c20a729ad261930fadad049fdd619f5f17521da59c45516cebddc632d3ac694fe9ced9af2266f20e55711593671b8dc1b26431dfc24ee1fc90fa4cb5b60d35c8ae06f7005af2fc037a6d458b86622353525fdbe333f05c7b760773d28eeee8abe96aeecf51b0e906b4989a676bc0b969da9a84ac6375c28d352a651ffa93dc068591bac94635e50862181ef497cb0df2140ca34294d19f91f3d2718c7869997ee00463d6a6a2f4031543d42df3eda9e21691b16ae19ac1c74a61da42eb8e59d5d642a7b471c5be029a0df5034099acc6da6ed818f28bf6aca8c75cd5fb755f54d557bd2d5757f20e934de129941549b7ba8b2a862d12d47f760b8009dae3eb23ed360194f540fc0be64f74cce7fbec163a29b34f0f08d4919b2f44ef9ae9aacf6c5d302a94fc440983ef2f059d0522caa3687373db330eab29cc72b82d72a4de2f2c593adce83502558b38226979c21e02b089b811f6622b72e379b3f7dd4546649fe8389b830b0736a2f9622422d62a5ae128162e05f62db8f38a33012d4c74481c02a0bb15610a3b7fb827bec033d8876dbb9d7ff72de78cad1c748008aeb1337e595eae13c20d26435bba69cfd5db7c25c18434dd251d2a27116d992022069385aa22584d47059b3bb38580429fc06ad2149ba9cbfb7d863b0d6657a1256c4c87e157443eec0d3ceb35d3e10666b4a18547fbdba0dc9365f584c364678c0207d32895f8903a0636a195be0d094a41d5d3507f11f1c815ca1cef7ce1a36100a8a8a9471d02f605e51c46fd906e4e76b207d71c3719660122f71d9ec1cfeb4960f139cd9a08f1011081b8cfeebcd41b353b9c08cf41065bc237a1f1232197926c09eef344a45c0d38910b056b455c149fad535e7c59e1389626c34174debd7f2db12ac45a93ce01eb8ded0a128780323f3054e2f1f2192a8ce55b447e5b9e1617c4b15148a05203ffefec27fb7cbe277e5632bff7a4f0437ff13c458fabd92e9cfdc01bddddc909a5d15510fda8a9224663746e1c4c366a7a270afaa3c54c090fa7e60e988ec70665fd9d8a09547c16ae57c688924add0840e6ac44128c08923fd5d57c3769f80923114ee0dff44b4b388402d581cb11af854053c667784465cbfb9f56133c4109824daf9338127f0152d659e61aeec034eb2c0247c486acaddecac0136979b30f7188637d847995cae9a41398c2c8986e8552b02841136d043b40d6828503440645a89b54af132ebb3c35e77289a8efc81c45bb54cef7366ba08e20f6db1fcd0871008bd048a0c311f104f350a1be8cf926164550b54de6cd9297eddae6172e018dac19ffb240e415a98d106544f2f1fe39ad079df179f79b4f93fbe644062c062593b29506cba09e5499fde8fe7de847c2b07f218086674f157d9fb52e7313046f9d6c8991150a8d1ccf7a77021a84c877566096261fad8f616a411684be9002b38070b0d557dfc107b728294b4d30b8e83bb907b50628c8b4282cbde0314f0f15ac98e382257c5eaf2086e588725d27f0ccc6956d46710ecd425274276c360281a6ed410a83ad45584ca08285a6ce01196d8e8a745d0ffa084a2c3a64490308fb8761db21acf32596291fc4c88c68604542d3b0b3863a53bc5327631c5af10887d68802ec663ef019538437c3a460ccbb17ddcabc9ab16bef28079e39c94b0b00295b9ebbea216810fc2b81c0a508294ced8e679270645e01c7acea8c528f0373fe48957e5e1c1ee6c29b255d36d8a70a9947c4bf5856889287f93af6b6bb0b70f65a31e00f547f218dc194690fee18c6487badc8adc9b29bb87d951a194a09e7b281b0f644b20b1ce8603ab8e7b2a9a08ddbeb9d7029c0922d3984875e3a03b4a654a21cb4670ad5417fdfabe083a6c514d2543604fae8cf0805f3025f73088225315c5a55202c1538a420509134caa7ca8b8c1efca3f9c7120a7ca675210a3e7aa7dde18781f1f749a1ec811aa4e9161faca2a0841f63b3eb3f1ee653000916f287ee81c0398b62ae7adef993e8c5041ef803b1ca8549bfbcc1246c6b000b9e6b4ce81c128f04a95f7e13069b576a62cef7056b0c493e8bed5a6ae9491304c7bbb98886a9043564f07ca460f7928a4105223e89d45ba5818246c752803e044b9802c16b6998b582d56c34f783673958d8cc918a5aa9c5c5915aa30c647801dd523b0fbe07e1b5c7d53a2f341e942c6a368eee64f6e2e0d4d3f7c75893bf04c4093d346155491f6e8c8b89eb55caf64a076cc6ea8085f9c7e7a5ed6c419609d22b80e81a3a2a943319cc58e32e27906c2dcaff6040730338d558d4aedcd509ff25243e4b54527a130553b959acf977c6eb9b389d4233203d67a0a12d1ca10fb54823621ebba093cff9d029916d9c4ba6fa1eded597725708428d7b12586e0f1fa030222224dca5380356cb7ca4c290c13f3f1c779734310164f393e50121036cb61b53e2d32a5bd21a2574c19a1cda83db8c940ba7e1753035afd7e1f7900667948b6abfbffe8a33d3a542aac78c651a1e59665bdbaf32a53f39e136de3b0107dd52481b55eca80a102c57e8a7df29e2f07dfd16eb079e9c2970e1df447204110efa43bccfce4b95dff75e00df256c112ff419a99355774e3efc7b48eea400fba35a8555c0da7486bed9069b0aea8d9e1aaf9130af2588255d5f8c88480d08052f4577645d83f1e845055d2a9cf7c84ce40fe2fe6ac1dc34ed323b3d185403f84de40cb52a01813be3b3783662ee51c07c7e49829e8d15f553c2d56a960f06478cfd28f06379f02111dcf2167073b20f88a4b80c4fbe24844f4e4748e70b0816639950a6c55e50e17b8ee0f507f15bb4ec5c7a7eb81cf40bee7e248fd8d30b5f7480e9ad4b5010d129995706e427b62030dd41dfcbdb256e7043aefa04f5052335b5c2cd550c4ab1dcd9b263768052f1f2a72fc2f5286f1299861278744e0afc41fb83d88fc713b1837ad301da8a0b8f812e0ee2320d278fc42273ab8b7906909f79d7b3cbadd9bfd7537c154a5db6ee8c50f95b6fe85eca0a9dbeaf50850fd86c21abc867919520deb226bb4f3f07ba445cbcb1e0796fe674ecae3c54c5032c8b5c34154bfd064aed8e986c9a94f8aabb5ae6d9ce2fff397a61dbccc52107e7690c850c50bd04017afb9c3abb073ed9a6dc557b3bc132a0ff03f7161fef06939a11e827c067e5a75fe793b3706ce75bb08c94d116ad8a74777ff4200a7f019b1439dad0fb9cb761393e919084dc1feeab33fc3567366f295c1ac295710f0b435b78a13b79b0b2cbb7c76803a445393671f1d5611fe5deba74afb262bcd80e63c779f2a35685e8d3e716761a27b53730664ae360bacc0243826315fd6ef807826bde8620f6529f8c603f981f8bde830f5865ad7cfe1b437124607a1d2eda018b6edabcb9ca579d6c47cb69837bbb7c84e57118434fe4ab78147b683686fd08fd9607303565e8b3b9354999917ef1ff0863f73212e8fb93ab70514aa521ae0dc659c43aa1bcb919680a149b5644067e403a699831474be553837228348f5f0ea65c06f4a305701962fa34167218a1b615045997b4572c6428a3eb86a1a3580629e100f493883ba229718447a3ee62b13948c0963458acfe95daa9f7ae78580fc496151c936d9549074bf049d6caa62e34130dae14af4799c844d3eb58a97007854ce2825cadfb50c5b46117fb305747af7a2bff971aeca767aee869558f55012b46a8c332aad6410320e09202e3f77a7548a3a896f3a8f9b08af406015b7b0fb7a4d2bd5cf904326c03650e9d4b6658fb8f9eb048cd6b64e462c4c51fa4ae003ab6c7a3a9c2f1bf8b4682f589890ace121c6d245eedad0e52330924e4b73404567949fb220dac572da95359022b0c0f4462a3b979d5e95ea8359a45cd40dd04d5d83155c1891333e6fdaa65da29ff050c4c3321d2ba039300e2ed5e77cd230aeb7eb38d4c6b8448ee303601a85f6179c5cb166fb668057073982c33cebb0d0b9f8fcd338abaec4bc0969727b4707a92b105fef3ce1135616bbf1b02b70eda06fad46d17522dff516de9ab3aec2341ffec1cb1920d75e168e13db8b8c12e3109561f6c4d3daa129bb3f63d0a0b14fb29d4354ceb039e5f81175161572d3a5b099d744a8808bab5ef03bfc77cf7ccc28b0a6082794d43b2f7166ab55fe060a6013b5b4c3fd50e374c96344245141520861e8925f782691565ad55b4a12546d20dcf026a39a9550d41d8293103068bd890c9c379ff780591b18d48c90091f05e07eb783b7216f08dc6e3069fc5396b3e4dede2b2c8e6f5e2293033ab011f672e0f11bf67f011d7ab70ba2bc2e404d69d924d7ec4a2efd01040c46fb62484ce04000316cb029af783d17f4fba05c762562d6eaab4f239ccd2971c9fc14d19fdf307ff92183dcb74caf6a7a8332dd851e602a2aa0d32bf9ba0048a265da63c1e7d0331fc0d5a30fd339ed82fe677706d886641935399922fd7fe721c3f29c955e10b3a3cbd728b15e5ebb6e61c69c79e228db75b84fbfadc91c73eba6f81a2b734031774979b2d72e7c0f41d22340e370d7ae24e2e8cc893688122d5f6305b485b0161adca3722e75560941c848b03eb96d14c4c5a3782c8cf9a361cdf02b73d070fc5e3465ce8067c827b4738e8c2ec7bd328a5117c5a917db0e8eff06c3d5af905048b9551ce371d26d48af1d8f7577377984948822e6fbb212165cef59568c607 -generate_ring_signature 4e6823185a8771ea63ca39e1aa4dbb7578a6fba3da566cea485c82b3c0efc115 0f0ffd85c0de4993b1c69e5b0c21a3811b49f6c0f4097a81e33448c1149afaef 2 cad1c5a19a24b36c12ba2812652309ba4234f04ca20812ef2d76405d7740afe2 4ff3063f234d5d7b4717b2c2b9e4c09966f69f1c1083099420e37baf84d8c9ba 071ae9ca27b1072d58abfc39b4bf143d61845202748c25189525172e1d081b0e 0 a99e4e3910315f33c42dd531f1951d5a36776284f55bec8714a6c6535bb28a07093aaf0ad3fc8d9c9d090e00e51edbafddead4f56f9b6ccc19b477b91daea306846c639bb01eb2bd1355339693445a147ebb57dfa9a8f3bb17e00201c1a8f70a80762b98f6e108ffff98800aec6d9f3cc1ca98d9af0e4615d37387b3bd2b6708 -generate_ring_signature 91cbc9e360956a6ea91cb542dc70d6cec885b8e2a1b763a3e352389041be1aa4 077849a2880ed750d786a1f1f0a17cc01c256f896373c465779e5154b3f7d955 113 1f4bdae2817d67f27dc0ceaf976717df975fb8353daf7fa01fff17ae37770146 fdd656b891d9e758069f81b2b2daf433fc84b3dc8eeefd2d295b7f5ab9d75c92 0859b4fd8c367923f1061c416b7e8e9ebb99e3829e50d8d21fa659ca4078330f 7e2da8ad81daf87ae03a1f42ccad8d8f3c8e1d4f75dd89416119b1c71e8a2416 c32fdedfa2464148a62c7630da8f598ff39f13628b221142f7f2d5b61fd5efaf 76737534abb4dfdc6ba72c40f3b406f9cec3a51fba44b56284fc62db05394e79 e4e6d4b71a8e963a256a300e4ecd265dadfc6ffb1fb7c46a68b9badf18e3e4d0 b4ce84dd04dc6ccc4b85eee0925825b4436237ec68b324f66f5f9684de4f66ba b1c379e91b9b72abdf75c4d25174bf029926cfb3498beb075586c9ae3cc105e7 2267492b2a3131012bdf68b84d681f03824aafbba96b2b9735343abbd74b8cb6 00ae5b1f0c470c254facb1b12ba8ac6a31191cdd01709d2ee6b37c1caee74cd5 bd859849cad2bb97e2da3908dd8b90578455599705674fc0016ff46c3549fea7 bb21060aae8d8503dd930512d7a080a6828223b5fcabda0c161ec3ecaae3fefc 66bb5f6b1c081e0393d2224ea522cf385115dc03b1970c2e7e3a5c72d8e7bc50 33cc10d158229e8603dc7895a81a8b6c55edecf6f43a506625074261d402fdc9 43a36814c2c72f6a273fac7094f9b00124e0bbd332b9ee61ca41ea231b018816 1d7f55694bfd332d08164d331fd276e56d365f2a7c5fcd3824c77a6809b65385 c2eefbf1779a3dc88c493b6512ac8d2393b2a65f195681baa41bb05e2e58f689 981ed644db662419628670953465ebe2ac3997ebb4d8292b24d2ddff64fdcd86 123dd138e0f62fad60aa9656d484aec34ad87fa623b69ca4f77f36b5b903d71d 29976e6ae7245518b0565907725a15e1445bd1c0730b2c98433c47e13f34e4ad 541da01c43ea8445433cf70817e7fccefa13245c1d6ff34ada5324ed8dad3d04 82a982aae68c079dedcd3455d266bcef67e4d39028afa0df883dfdb4b36ce979 7561dd51d46d617281a314a4e112228a6abc1ec8ae26f59f5d691cccbd96663e afa6f7640f981e3d4ed2b85b74151061aed19ff5390c0ab3791cccc1a21ede59 54c84b57a8749841027cdb4555f8a8c03dd9763957d801efe96096ce6a58a1ee d4186b3f8ab4c4fb9256161f632c9fbae63912909c22636357b001ff34486de3 e845c35b7b319a99099f122f0acea3e39e82bf536c9dc0a7fe5875d6b0739c74 faf9769154330257db19465d7ae0f2f211f730e4c83220c48d7648596e91aba5 3bd9d7b85fc7ae7d7bece942d0ead33b882d0c35d96d491eaebcd6fce5f345da 1cdbd85712849004e3e4069802d7387ef46a4816ffb84fc626d5c1b9b7a60a23 d284ec26e2df785de3542990946152a736f729a787913dafe58f8745b0d263db d23bd5efd82b47c8d982ed9e1b4dedd39a3ee3badfee703dcc33d3c32b2075d0 f1eb248b21f1a5abe42327d1f203121a0a113fb1cfd61281e639aca1a15798a7 dc124febbf2b8b75ad19408ba905ec2660f8641608048d4053b137c18118285f ff0a4193b301b36562d8c1ffab7bbb9c62834b0116a48b992a85c1ebea6b0a81 8ebd75cea0d1f657d506b3cbdb855a9db21f87d8e0cbef42849383f093b7eaa0 9e254d83820a33fd0971a3c7efe2ca64c35a3d5d50ac3884bbdf7d6f77d7dd5f d2a69bb8e79306446c6b2cda1ad9c3d1bb571720b43e55491abb505b6aed4f6d b60e0fb3e1013aa0c1d196cb9d2fce8c1f201c0a013e6634fde756f6023c36a7 262e4efc7730fa981014d1567de9d429eda860bfee22ede1c9941ef94aaf2159 8a40d305e04999c66638cfb169b2a991c0995c814ad978eb9f1e951bb3465c40 088739da61d37ad97d467ec8bd7ca4139b311f7f8b6cea6469aa4e8a4972ba51 6874ee85e75171ed81a59ee5030a8f5af72373719a8faec2680c00af75fbe0ee 0ec37865399810603eeb33048982fd83b25e9e1fcbeaa91c0ed06fccc47c3f80 5ea898f527a48bf7a4fddf87f26d13637557b6214da4eb1b0e4e0495111f9f36 b1dae8a393bf959ccf33a86ce48214f4250458661892fd8bcbcbed768f792548 25a26575e7b663bc898396ed9ccb961e9bcb00d107f0662edba72d2697a78d4d 927ac8a2052c2635eabe2602f67d1e024ff0f04dda5a09a1abe3475cff9b4f78 ef6c5437357e0b31c6a3ddc3474ce246f49a669ce06acc00232a4cb170e0b7ac fa6ec2d86e6f12a008a2415f6bb6d62d8f4530b7ee264e6335421b464033b6f1 77027c9a7b41d51ec9851dd80e52221d541330c4aa65ae9604bb924874dce56b 6229ab07ca58513e9a5fc1db57e4c1bef34e4007206e440b26707594b3cf88c7 137f3bea2550d2307d8a733cd7ccc1c6f80fd9b4f307b75583193c826805588d 48f0e380c36fa89f755054572914efcc6ccb415d77348416a33d5512f8376380 4f5e4429027959682771f088b7101e1cb07d0183052627e44191ab65a4d11e98 d40ec8d941cc48b7edf706b778d736183e05856d03fd929adac4eebf3268cb68 8bfda414414ad854211292ba745ee96f200c80e3623506fb8525f20fb2271fc3 1a615b1e5534445656037b118b8b7bd13ae02ae23436b4ee338d92d37c3d4896 9bc163d094d4f87154cf3593c1edb359a903dfe7509524d9335623a29c656663 eac712841f6694776756f6a89d043bb062861a4378cfb13af76d301c71cbc6ed 7ef33bfc75e86390bc080acbe35bbbad5ddc51da165009bd0daa10db962ba996 054e6574ef55c9f9e94207ec107352a0dccc240ef20c033dd6d1182f7f62909b c32880fa3ce928700ac24530ead3571072e12b03a49b26ef6b3d35d0f4c59d53 b98d0748298b80029c901eb4ec4cd8a436e83c7e01f440c786fd16e15107ac49 ebb0e6eacbc9c5f35484faf27ecacac6cc694ef4b09d807029ae6f510efdcda0 b490c1cb481c3ae08a73f63a1102b316d286d93852adf5648cb0dcb6818126d0 d4f4da3f84eec9c39a4c7cfe27a3bcd39cb9f291005614f1487e0f45a4f1ec00 aebf45b322432696c7b67d3cfc0aee50ff8e40c51ce8cae8a626812449d3a54d f606c7fa4e43f558fdcd80fe7a73dcbb249056b368f5a44f3dbcb9324b503c34 106f85af18b3197ad3351fa8fd8425d260e7aa0c05918af757bbd3361bfd69d8 32256ba58423e1ea10dd4f501a5d238f31499624872406fe500f498e66d008b4 d292d6bd8bf7432aaf9c61d7dc96c73f0dae8132673e85fd3aac5fac1a93431e 52b24f1118795f20e46b90c1b047ee5ee2d3652ab2bce842a9cec609fa62aefa 449fe393def04380cea7cc4c3db08cebf0482f2ff57127ffcd987d92c3fa6163 7a8d3c4d6eb1516f2fe284e496574b3f189b5015a489fc50e54a9f414dcc1b0b b39077b6c733c1de5db7ff8fb3873f024b40fca72f9cac1fc08af28b18e1b932 0b203cae9dada2034024effca44f99b52a36ed00a2f4b67f03a4e0ef5b7c5dcb bb56bf108fb574114fc98c31e713ddc445cbbeab6b01d4e568dff3bd169fbe2a 059819ee8457141574c6dda4edeecda5e62993b800bb2148b16529bf6c0a7d13 79688125c0e6b72e56ea7872416735714947f586635bea64120945fa37cc59e4 5adb1c6cc2ad2431222dd58e8a6f3571063b3ef20bb123e3a1071fcc60ecc9b1 cc3dc8f1ffec0e5f45293b94a5a7bf3ae58a4d4f572a9f5ba8ec3b4f34138369 3999f2af3d71f38b14e98dc84e2530f037e83e7394bced0b6d681ac73029e563 67652807e4ed16e014757a70974b4f8db9e6f6bfae39fd0614ad1f06e525c081 d3813e43348dd6866a69fe1755162f250e8e3de00b7ff0060cf6475d2445836d 438dc90ded371c003c1038b170b925cecb796c3074ccbebcb98e3168af4d39c9 740cdd1999f72c2a29922d6ea744085a4d9f104636ea931643943ffe673fb15e 585fbe2386bebe0fa46eca5ac524a3cf4665498c01929b98854634b0a0d113c3 de3706dcad8c44c755bd56ec422c99168fb5f8683866a13d7cf8c2145a49ba38 da4157d8f82d2a54744daed564c987c996120211b30d482fc0bed011e8f94fd9 721a665b9b6194d077108c0797031347aa6b2d6183812e890ead8f7ede04fa99 67cd0f8158601c13c2f85d32fca57f324985a20c4766cca265693c77d87d5143 9e8803213f74d6e5869fb505e8309245889a807a48327769b8476f16992a8198 eb535a0a39ee12899ad81b8327bb17194757e760e134a0bd34a38ca32b7fc9cd 1a94815e92a49195b30d5c6d08c6011f615a876d9f84562d13e20c8796bbf944 ac695022107503164727535604598ba50cfe2c8d2555345948521d94851caf8c 4819c71ab8e12d613df31c3e4302178dafdc21ae33baf2ee3a9f2b161aadd640 c5b8a211af4dc95ca5ddb7554270215cbdec87c34dde54c484e1bf8ed7a5500e 375f63727c1dedae8a51f8424156f97f9ee3b54301423c8be049492638476587 cbe6d761149db8e9231283d7d3e27b6bb107068127e49ab0ea318ae47a52d941 d78379ac13a4e4e05a8ff9cf451d22fcc16d17bf4b06f66c55f8da8584b08fab 6edfaf19c5dc75df69facf72eb82bc2c016b2650f32c4afb731f7f3fdcdadaff 44d3fe29429f69fec91ae3e2e33b227fdc00a8ab78e3510b2bf03322f20683a1 a859389fd668d9b8a8a5fcbd3ad6c49c751032078462fdf6aac4e5600b8bd37e 6808fb004f96d638abd7d164167fff230265214723a7b65344011667814ef5c1 6c3654047c65a6312b5f785a9246e064f1d223913b7e11db00bba27b8d6e728f f1383ffe364151b77625632904f34bda76a33df6561c30d591c30cc492b0fc41 6cabd4505bd1a98ff5f7c1c75d7d4e328d691510f4a23ab74098c3b54a08ac03 c4818a93d8e531cd4534694bf915b7bd5d65baf66976fea183e3df1ba69b65ed 4ed680ad71299f0ee843625af25736e020ed7bcf82ee266c0e34537b1cbbecdb c8a92d1bf5112f1781f2a7a528b196a3bf4ad426a48c30174be6ded892be8be5 6ad5557af5108ef9b99735168c733031ca356c49e9a4cd26bc6f3a332d9ec219 5c0ecde6ffe8646985d4552fc134f6d013b984474f29e62d6626dc941c23cb0a 31 6385a2b5033b9b43d35d5efb16e3b6840fc969452b509aae79a4a3e943bfbc0b7f1b4a1568a8f259400fc897ad6e4a2784d709a394d44e0920a0c44956330f03aad95900d0e6a4a847b2fe2f0bcfd1691ea0dd1e9c07f951e0327789e0ebaf076c4d206e1a46cf10afc929d4a69e7869ee1520b5e5eec5ac1eb23393615bff0ddca0780b25ca9562a6bf8bfebe04210a365afb51189c397fe83d63ccb4d2860ba6b43534eff3cb34daa96981c0ac86644bc9290ea47032c7b560f5f390acdc0dfc7d81dcc4658febe025e5cf95f5f2dbb8d7399279189346a75ba5bf4d6334010883701d18c54fe5e01338e2d6711ba9c29b4e146f69012f5200f88ebbf7840dca4f1b7bfd71f7e666ad17152b46e5cde06f929c5abe28db8cd2204d648e8800dd4a0c2a67cbca4ba6a61e25f97bee017460fb7f47c738bece161b9eae3a960ca05638b0ac6b4e746c2ac043c3499d6d523a1aebe5177b0018f54140cb8cda0d6d83b9220e2e809b1d8f9cbf5d5553a84de9ae86078614a0f574cbbc009b100a9794309b25dd619c98874f1ff133d8e6ca66bf09608c827b10fd6e42b94e4d022ed1bcf20be54f06f90e9906c1a2e0f1c22a4155d40a1adfb6caad724a9a24013ffb86711c3a195ad78f1127c7681b74b77ce99e66cf275536f4dc844a46590209f51d62433521f949cf143cac1b8148be44eca20e52b7c92a26d664af842c04e201cb7cb30c07b219853f75ecb47b579bfa7ae3f94c7550eac063e928db070f8370f06de67b5fabb73096ddf3da41d0c6f9b961797f3c791214c3fa234b5905c36488531b0ca89912a16f1f283f431789ec12691f409e06d862a5b8c47e2e03cc8dbd70b23379531a87cee403a6181789062912c6c302333c477644d987b20221768c39beb0e6453dff36875f26baa630ccac287bbe4a1fe86491b43d5a7b093e42003ecd73751c39e1a0aa4eb34a40cb635c4a6596783abf109ebc0680f10f83126ad88122f44223ffc737238f5040d6eb7d739919be413d7e2f82fc6e7e0abe29291ba715a2fd0c258275b77e050adb14f4e0585b8ed0c7e0359ce85c9805d604d03521dca95faed1b123fadbd90fb2c8d9007b8de02e1f519758aedc9c08ff5cf64251d6c7f6e7264288294ba4313d081152979a54fe5d1493295222430bd20133342177957d7626014b57ebeab7300faf53a10731e9de7a4e0372b1860446a26d53ce5a0a04bf18870dabb872d4df5ad06149a0f50917e2113f4adb520f6adc81be64c0e06dc615dd28e2afaf50a8f99bd4ad23025d065998ee4dfbe20f428c3109d77a5dbbac52f4c609c8c9a6da00ab052bbd8a4b901acc990426160ecbba9cd03a35da8d39649722acc5e9049c06ae93e81a6cfee7410dca76ffbf0ecac5fb11654925292d7d339618ee4e6783d3cdc16566f0f8c1d15f9ae00ec20d9b97e252f785c71929c5c9258a0ffcad21bfcd6cbddb5157dce90acbc50b2d07c0ea7700280055e65d1fb56edc5e6615d31cb0ef56f103a417d4025d225a8f056defc8a5ab783a47266607de5e78604ac3baaa88d89cc8ff05d0763b85bd8b0f177917e985c14b51f6e33aeb97cce5828250b4834d5df42fab0b3ad5fa3b7706140c130e40f26e8f0b07448ccdfa2c7d012d3c0dd267f0da542ab9413f614c011bacd85de612ed8d475fd0c45d40dbbb6ba123f20402933e5c61d83c07fd5104bf08de016c5239eddcb1cc728e2d685ff28ddcdcd0ebd7eb1c2e69ecf6736a0c653a044a8505cbbb42fab5ae6911bd42af399abbb9b77e3554bd2dc2df08930b0a3d835eba3770038e5f2931b003429646a14b97648a2a951e430a7ee4a0fa032663abc7746927e9a14a5605cf7f883f409c7dcefcea97d45204a1c5e8bb010e1817e4faca2d6519b9316836379747267d840a750eed44ce1e377440500c4505b5e08756ebcb79c22b3617a05cf278f8bee3c06b10741ceb29689c079844c0038565c6a96e5a9572afca53fa0ae82af872d901ece8e51c394a39fa7eb9806e0607c670426bb1474ac60bd1ffc6c841a00b2530dcb7aefe58ac4bd84953772f0adaf7a65f0bd15bd6ce9a94085174fd75c6a7c58787fe33132b52ae46174bd4007a65e14fa380b8ef26f5afbce7b3464625515fc72d7084d44046388bbe91a2036ec51078daabbbd7eb8c34ad4ffe772e1560f1ecf498b5198a594d7924d313089f3735fa05ffbd72e1113cb5ff1fb5e7d534677eaf624b1de444ddf8d969f60dd98af763bcf7f001dbae6d81a01895d7a51d097982bf4b4ea70ea5d60bccae0ebb7b1e9aa423dbe0387cae5fc23d56975e1a095e956004ac195257b0ac7b6c0c72ed294963552aed3d8ee825cc1ee1b14fbb367ad5d74c14f170bd59dcfcd107f1f97cd7f9830f8ff29ef0f7c473af62a650997a18ae31570756d7a3f1f02b09505e23944772c0c211807a2f0aea7d7b1e6bbc48e124a4de74b7dfe52d41680af7ddd077ecb1211d28385c9f439cd0eedb3c1d22b4ad2e9aea3fa0a6e46fa80978068aebf2544a24f8a8d7d42b60d40963af6c711984811b9ea15121c0c0e10e81b67134c7892b2b9ff906578f4d9b15e548751591d2900b6972d691aa027402a4ecbfcef7d92d97c25eebbf613bd7d488afa4fb86ad1a52df12408651aaf8088a5dd7fa8dffdc830378fa77a5f0b2494ff14ff715b1662d2c2d2b3e41ff75021e4534a8ee6eed9ce7bd4316264aee34586883227a3e49f8615efdce701b3a0c04358c5f7ff5edf26fb2aa906ad1785ab2e3acf3be54e23313995dc74a70350a76c4bc19df287dafe2d7f257c56ac3836e5ec3b27a1e9bf1520fc9cd634d2b08b1c2bf5a4511b6ee79d7f66ed7623627eb57929ddc507275bc6411a12dbc1308dfb48b8699ba0ed77313a30101bd66f732d8da39b6b7bd276ab6bcea9fe04306fe06d14152b8979775699990eed5bca3e5c95ce916dc22e279318568b9fdfc03e9abb7cb1a65b6ffa1c8fcdf03a264487df8e63efb32742c5e26a3eb66005c0834bd512c14f3e4898888070a065814595f19af5e5811c784dc78280c28d96a0a88aa65445d7675559d5ea59913f4f8f622bc8a15c2b4a1f74454b8df39f7540b4200397ec2d18a52bc22f78e80481044b037bd3c7d58f066f63e9144283a2905a65c57cdd8a3e3fe2581c7ec4a013e3c9bf44c2adfacd661a6fc2ce4b0c0940ffed569d437e4baee3e228484c28109bdd878a402964b226a446fe3d5fbf7af047ab52cd941a8230d73ec0d718117d6a5b7ee9ccf75e37f7e91f6ec218e66350e1d979a297ca386fde3edb6339e58c5ca546312012542857ddc2fd88c8c506906ea906f293f7c2491fe1f418b6f51d6b868e13e85f6d603cd48a79f1a27c4b402b337eb2a5820c54e7437f06facf1c4300d2ad086c4f84befc05e9d69a653710535078205a48ed49bd8bb063b5da10393fd501a6a1fe3d07e8b86ddf1fa11d00a17cca8c0d1775bfc56229e45fedc1723b9547cb2b296980b2dd42b58e1b39c09520064634c52ceec4e7e1ba80eb2ae8e3c4d51fc47785d9f382982347ede500ea2ea308c834bfab1068a7798810c29b5f2e5221e68160a6905424ebf4fb8b7037130eddf2d07014921b3d6d8db50f0868fba03fb4dbd724484994885e67c3a02e7145b0e55f57afde954094db28c9c6760009d629aa234e3ae0a7ff98579e30182513d104f668545bbab88c95832c2ae20f6b6aa7ccaa3cf99764ac3065afc0e588f4fd18582ea7252fce172cbc15b8153ddc538a4bd9692cbcba1f2f3eacc0e4103e4b16b7ab718b2f6e98368db669e9d9f36cdaa0c77fc78ba4885074b830318828d27c0d297023d4b4584b52055278d11cf4d4e948ef04bd4256ec7eacd09676d04ecf25a0d090a3b0bf930ab97b510013327b8b2612626648181ec2d5b0eeba57a690de924fd8c3a7a399a2c1c5fd6a8dd693e754e0e2e581deb2b92a708cec9a2afd01a110b2b22766d21a8fb3e7f7b751cd8e5e40a149895a89cf6920fe5d2c620a8eec7be1b57db4ff09c5ce1951dde409421ab713673d28439ba3e07bd8cfb78d21198edc9721b78d2adc7f566da02ed9595584c58dea46dc0f006066e30ac7ff056c7e2df7ac94929fcc05db096043d1ecafa6a45b5d8ded06d1605a8d16c8c27028d5ed28d0e0352291145eec9965da61da9acee89720962d5260ab1c08f8dce882b3168ba3f0928204899338d7228fa61b6faf2211243a186d90819edd992e132e347a81b396cfd302fed80c2d24ae7a06cdefc243d7435790a0ab972a25926cdf6a72f3e60631565aa9d347a64c6a0200b2550aa4e59f3b52d01f464aae7c1f2d3e93105cfb6d8beeeb384992a16894dadd5f003787a1ce11f0adc3ca244e4303d6b95fbd0ce0ae7f397b7c4b0110b3fecc50b687d08ce2d4c046383fb09144e9c9f171e2a17333cd6960ded59aa9325f199f953e5e8dd1c1e06f16ee645c56bc312ae0a348ab802eff03547a0292ec73aa45dc2583bca96ed0dc6f493fc33378d886c3dfafd314ec2000f8cfb657b706a0356f8957b6acf11055b9be40b2ddcc8ac81fd8a3fb440c2cbf67b61296a2428741c140736cc770704e96c3fabffa9aafd1d5d8540431c5312379859a839c23f429ef1122e283793033de9b75fee2e685590e4e4149f50040b736b049d07b3a8801545a41fd1b0140a12cf6c833ea3f6ca3065e9ef492a0960e54fa5ee4ab1cac89d26b406f2b2ba0ff2a34ca1dd3b9c16a7faacb534bfd06079ed992d8bf11cd9150eb5872ef5c40087f6de64cf9c491a9d7d96cb43f0fe96edee841cc30c163e2e1ac225faa9cf08c72f1769a780ef7a314055d2d93ac671c7281470d8517c9179e8ab4577844a05db273f000e91c8cd2df555159d6d1922caf25954a673c05262408fd4612f410a7d7e1e9a5c66b57869f612b28193ea1c95cff6b6dbd438581adda3f3f8b097015a6fd6642b0f1903dbf3bde8e901d432ea546ff95a2977441a221670a2f1e30466399271f64417efe20e1100a91f5982cdb91a2f4c43128ea12ebd541d9d1d051923905fc96c3e42aaa4b0b27779f9919a7966ec9122fe7dd4c5107b8b5e230491530628d82940be870f4267438d02417fade252023ceef3a605635316c239079ce256d52a662f0f581fdca98521bb99dbe83082b7f60cd73877eb13538ef80bad30de72c4c58f7105b9c19947e4db119fa0481bc82e5bf068f152a74270830f5ca7afd1534990f6a3bd920b1ac84c4b24ae08ac57000ce59a7d4d3dedd1310e77bf6afb2338563039be41bfc237e645fb6d22d62db7b37334aa1c291e876b0cd5b8288e339552c5591554c0aaf45301d99fbbf8bbb1c5cb97e2ab361468390d9eafd01110e51a1e22bf72c64513c985a59e36e614b3a1bd18672e4307b6260b4d79538e20dac5d50c40617608ff0f5e205e1035707af5f55236d8afff0cdd0b0061023637570926a2e58b4fd08bbe0fe32b6c403f837d5affe5d995644b1209c71939fff7e2f89f6cb8443403d7a3cf46b683498f6cc7c216609caf627f7307127c816036cb239c856f5e33c9ea8ebd4a40fd5b1c2d4bc6ef8c1c334ae54702002e5cf28a5c64819bdf516eed479adcba165abd00ee032df3be280aa19bfc0c515c9e6e17709d2955fffffdbb1c0a17dd5f952517222f2f6cf6fa5f804e2603137f674e2e6261d6d9a9d57f2d1270dc49967a3718774fe8d65c564aa0ba8c05b4b579bff9c9181ae9d03f7604d31e87914cdc4bc9029acd943300fb4330bc027b25491669aa99250578874fc4159bf839a2e1d5bbe19047032a8e40902b110f3de1f863fe026b7c38f8442eb29f72f151ea6e1d4e885d3640c2333c731764089c17838fd51a9a8c6124ece27e55983937a3ed94d9c4446b6b2fdc5d17621a03ae2d322b3509b7df40bab4afe9103ef4a8a73345b2b959f0d54bfeb1fef66f06878cce546ede1938cc65d43d697694b05c6bc299fc247374cb202e2f75157e0b635ba2e003d48faeb4f8a981c21b93180a05bac8362089b9c3baab1c021b4e0029c2250b79edc82255cdec523dd63d18789da4d1287298b7d33c84f5f81c0d0f1f0a24462d1b254f20e6e3586ff0f7278e0cda790e6fe5208753f0f10b1ce50666b7e28cf0e6e99924f366737ea7e3d0bddb5d6bfdf8cb85d2ab78d8eb72fb078b8d7518f20d345b45d8f61143e3c15694a9abb02f213a80fc9c2e1628c06b061ffcfc52678d707ffbaf3aa91b9f06687ae14fabb9ac62ce89a9cf470b982607dde67839485e77b57ed5b62ffed5da32f66498eb1310a43954f0b36629e7f1064b159d1c274f68169f93260f19ce102861534f2a9d3495d8df69f6847db4d70795da715367cbfd6ae7d1656e0bc8ade046ae4930d18b6d7e6ce39c8877838400156c1b2856adc94882520e4c58e7187966a3c55fcdbeba01fd38775f64a82e097223b0e0637b690748f2ce412687815e6ffc7909c1ad146a52bb793186897206274e4f84666bae653a0bfa2e22c3463e51fd116a040325372af6a57a638a670f55e0f581303beafa5f0a3dc4fc020e416ed7498c7d48abb9d1e0c3dfe078100a6c2d76285631a5b3b3b6769a3066b9a8310c5775c84456d7e88ddbf55ce91902150703f951d27ab3eb1d07d1640430e773ddc6352b34ff28998f8b688614cd079a78af0edb42eee1d8fc734f02d09297c347aecdde4ad7aa68ccd144856ede0d23290f15a817359a1bd5425a7f140796379f026b5b8d737282eb9c6330ee69043d2d88c240495720c2c1bc7bb181b13b0ac1d4b18ad75fc7ede8ee6da741830b639fca1809e51cbd5c6bafacbe10e3802d71f09467f9e6b255213fa67f02bc0be4ca2491929fc90dd1119463703a1fbc234ccb92f79f442d02ee5b409ebe450db8ebd1f2fe8b46e94aec94ef0932a6203a61a220419cedfa64a5f34148382b0eaf4bae04f66078c35b925e615c9a90b5ae2c39fc27ac00686e6c1df84caf0600c8bcd83a73f162c17f4b89b50ed5fcf9d5c90e3ecdbc54fb1eb97964b3189e068265e3934c6ae35455e2153d0ddd3414a2faa734c42e706c9a27f4dc66067a0bdb6945f8abcd81d88759f63041326c4881d70c3cee69ce087b3d03342b5e0d09dad6680d60894edd2c541bbed393b756d601c1b583636acd20875edae631f903782b7499515db9b1169dc73b771855f45857afea2ad034c458521bc9d6c4b00f00d6d3026a6a9ad19b75429c03197f05caaeba344def20bc79d63b587cdec50fbbceacd128cf4c97479f2a4b2459296beb6fd06e6f86aad288389483925ee60e8dfebd5d83ea6bff1a70fb230da92adc9866721bbbb2260b06fc83c72553870fcd63ff51281888782dd82b5b539835b1788c36f33ab82ec33b8848c8dde6800e66bf2005e3f195bbb300969c1512ba70611a15a99c58b5f7f59e38e8294f7e0a7ffad0c97de4c7ac8e2cea73ee7872971ea49ffd40c578f8dc3c3478d1699b0d8f39643b1941c47d0c116c80b51b9b02b4f738ed5b9e8251b2348f628c373708bcb529c2f3740f1e402be0d4bf634437054ffbad80eb59a273040495751b13046617bd3dd0cb9a7fb0df5a02c42bba95e6013b7b48cf5c646e9058a6c053ec05042affc6f1ccccde0ef89547a18bd0b0053e2424d9440e972bfc7e5d42956102f14e9a78fe4a018f88cbd007dd03e29739a1cdf6b5063f070befec0245987406ce9a0f6bd005c8e28bff749df87ebe1bd35fdfd5b2ddc843d97a212252b28200f3afa238422cf35ccdccc8dc477d0458ca5121ab3331ca43cc37f108e80b9900c3b11396d2b7e4fb7ab684f26168176fa326a25a632ddcf7a350b611b8d8c400e6e27f40896b5d45ad192a1fb9cb71ca858d3db543902d4beb72395c592bcd0be8c9492ad3b48bea50a91242710afb5bacc5a3cfe4c835e719d0d443b0be140b4f5af5fd4f9c34ff6fb49b75469c28b2bc4cf05998c9f76bb66ad283d4431205d730d816cd10dde0c30e706eebe1a0c174bab51924895b98e4bb2b4f5297870067d3f21cbca98b0001037ba4e897d288813bf873c05c9df06b18f864555d8003bff35d8f92a69e5428b63f978395c1c466aa43051325a4bf14c5d7b335e39d01ca1a872d67b7dcf6c73b0c566539c146b331f75d0056045721b81bcae7d1ec061d9bd2f57c64e09260e0f61c31e439f65ff73b2a92174e19c26c8dab42d77403b2f98e19417e62c2c65edd2563ad20d7576a358a89dab0220c054c48334f940c455a411137a66659d18d5a5ecc6954b59278a6ced59eb0d69f8360754e29b50104ef6f08f40d0d973762a7445c3298f30ee1733e17da37e9e062e1c247cdcc0da9ab3e8e8fdaccded2c633d348b2e38f9ca96b31f79a503d3b435730f36b3c06e683dadc4d671152fe94256897031427f02e45f149b6048261ae6b45a39f23087b921cb5438514344e101908abc2daae2e1d56410d5fdc938379aa41a162860d2239a6b7ad6a397bc3b7e95d0009fa676233532e5d9ebeed2baf10a1991e560eb2a7ccecf6ef1a5cdee3266283670afd1313e50e3bb66e7dd8f6d23e7a4bfd002da637ed1d1c6e0902289813fbec0874c6a71ab9e594ed2d8da4edb0b514180cd02bd629191da55700014c621bc174f6e4ab5d09ee4e2179aa6fc481d3bb98029d15f74776784cf3a67cb1b243133332aa17fd040a02ddb0255f8fbc693995026e106cbb6b2e92894a63c9da19d53807c464a8822814be812b56de6b678efa024369be06e561fbfcfc1b67b3953f25025e5dfc2a70d2a2cc265244724ebd8b0ea6f3d8c83cda7db16d50d265f11e7c5d65f179c9264c307ba9fcc0ac53bb6d0a4f2dd1e2190a934f866d6502252fd4449e7f48b4d7875e771e0d91c266867908dc6e3dc4ce9770054a9d32370e3dcb1dd770b8e0c9786a06463f722fcb8aa40ab34940f621830709cf3d5c2429d14772fbc79dfc637bf73ca7fcd7641b10730c35ae044f5dfad5407f71c017d17c311a2d37c0d982fc05e464439f724f3f050e00267ab187e7966bfdfd16cb385938e32aa0399a68af799cfae4bf4cb00f4c0e0ff0d8725ccf6e8336bdb9e773efd4881aa2d6bec997de5c7bf006a1b5066307082746846460b321b2d2bbcefb439ab20ae1ebdc5149a85b0e8c476fdb74360c2ff768d80276c04bc70dbe73345de2330bfa8d1b6d6f3abba7b7037e71ee1400cc9ca23f8634aa50056e33b262ebabd83ed5680bf650acedea1c96bbef0f460e311870b56dd5090ef60aa400aa0e51ad52df6b2ae69de4652dfd73726187390c0fc169c93e355cd9c449c53ed46da672b88cbae1bbe34cbc464a175bcd20710721df6bcd3968a4c7f0f2df2837a7f56c029d72d5d1d3f23b447922283bb8a705427100acfa2eb8f96c0d5b5880dfa0f8b0d02a2d2212e441b44fd088b956b30babf1c7252d1df7775d4fed2768aca06b664ee4daae142bd7ce874472ed64e40bcc04fc20a0e0cb585fc1cefb04aba3daf59977db2ec3893fb9ede441d577c50dc7189100475976179a0de1fca535a102b2a8b7a5484be7bc024793fe240ed70b77549c3bc22b439b5bc32ade784233529800b8300d06ffb24556c3f7669b7b0d8372ead3214b4ded23eb67300ce836cb76893018d98739f6552870acc3e8f5067f4d1f4c1dad5ce6da2c660b7463c7a4318d7aaf9acc358e6ebca5ce2579b80fc2c9988ac09bb5833c13bfcc1179a31fb496e1f86bc9f968d82b06aad0aaec081ea25afb44d6432084706727949b731df04df9b64adf236f8e84e8123bf17e0b6f90bee496e84079cef86c4a76e01e550e17ca1e32df56d1b42cf2df53b55f0e41e2a538daa9c499a2f8435105c86ac0da28c288bf145ae53c1d4695d0ce8e053be37f770734f8dcda81b66fd3ea98b87beb65fcaaa9be8bd41847631c82d00b6cedc0e13f6f6859fe63c6eaf97a5ee538ecbb1edeb737f1ae4640e60ad68d0292a549fea041ca35f037cffb46919da818e8ad732a6e4ed405e351ad35495c0b9e78b752e484634224a1d5e348c7dffe9e81d66c166442f8a5a1f5b4852fcc01663429c9cf8aea5abfba61e4139dd50e79e108fa29dfb367f5cfe6a6620a4100aa234d568f2746461dbabd0b9e02b9405513af4d5da32476a66babe276778705b3584ea525dd25046fc9374c27244fe107eae13b7233eaf10ac0fa84b3fccf04 -generate_ring_signature 5354b346c632fb825e3d4facd91c90176cef0f333295379b68ae2f3d646796ab b232e87202790b0f139b5abf06b5ed9dea9fa10b45137abb748bcedec49957d4 2 1d18a97357d5c6f3660f9cbaf1d05bec77fc60225b96c643af06888b41d560f3 e4943e8f3d243545a50e1fece9b992cbee891844f6920144321f5026d51c010f f0967d0fca4c4f72d2cbf40eeffac2483d32aec3c862f83c0e938e8788e95602 0 3bf521e80f707e0a2212329b98afcc721af4e80c0af3b3b4b52d3844b8d84d0276d32c21a4e81f57c428b76e25cf3e635e19d6715af3fa547855487f12f2cc098216c97a7071295606498ba068dc4d0be56eabfbb6764c50b12eb95b5be6540fded08135a06b5a444c4dee477d683597f5a9e95035df813b6b025ba22347a903 -generate_ring_signature a3e9f19a6821d12b0cae5d619f939c5d9beaeb9a361f9d7bf374b3814ff23ac3 5be7e561234f7b6bdefeebaf9a512ac4d97b77dff058f832100634dae4b222f3 4 1385acd49f2edcd1d00c3e69d899ff286d76ba1ee5e7684e480d914d31f57a58 5c43220a60eec00974abc48b6dd95e001d4b1e362aaeda5b712d8b6aca644304 02365a93fcab00824d25ce4e4bb58a49b9f68ff7b1748d1f03f8e5edd6fff416 a1abd0f71d7c05bc675f911d3c4e54c1b8618c603951a1de691eb38f030199ea dd3b77701253a786191b9d59b556f2b96336027fe8b0de80bd2b059acf610d0a 2 0615431114ffb77968c2a151e88ac4f7e9c76d0111d51532902385643bb19b0dca9538f3b1dce56e87719c5c9381ee912a3da53d70a24b1767ee83d7a6f0140f411c77ba4d43f724dc9a0734e14d151d760e660a7f6a563586978fd9af1b7d065251d60ad97b5f5459dc57c939a57161c2b8fe8c953c96a3ee9123ae2087880d89de70aebe162bd22db65536f5daa17b252581acba7c708fe0ca99f115b38d06e8f470bd37c8253a791e98b576b1c61fbaa33d127652dfbfa04d216638fbdb05a35daa5bcec656bacf32cf740402c6d611734427075266b7d163cea31c1e050f705aa16ef4aba7d720232540c56033922c07d10d3d2a61e0b337f2e9be95780c -generate_ring_signature 095549371963a6086a8533f8182dac9a9288863a9816d457484aae549c10c454 034fecfec4129e575a8f79e4a2f329ed0d6e804db3c6b30178a298acce98562a 2 80e4e87a2b4f800d02c125ad32c11b8d667705547775533c48d73f12f39e1c41 c404cb7233f19eac34d072f1f24f9edef448ab74024a8ddd8d72639079be844c 47b6e374cfb1b6ec4adcd3183f7b9f54812d7bb6d87adab41e1713b89a918c0a 1 9ebc27fbeb7d11d32db4957e4dd7377662b418712c824b453e76336bf64a53002365ad9e783df0164ab73d780cda0a05149847ba135a7f3f905c7aeba9e3e4048a993bcbbd6fc5b99b28ce2f11f420842402d3d33d19a26bd0e56419ec694301286953bf27efcecc2ce3a6f99a1e8effb8063046fd3183f3b7862a5849aea302 -generate_ring_signature 765d32e597159be85cd75d6f4a26b6afaf0eb7618a10bdbd64c3629d5f37829c e5729996355a7f45566941b16bbbdc3e9645df09d11c7a4fe0297d9046d80876 4 ab4b00cd5d57edf83bb7e34a17d61fa41fd2bb00eeb8b182e03e05fed0d63047 1f121a1695b39b438807592a0364e537459d9ecaedd7be6ecdb71b9534ef74a9 02849420f9ae2c064385bf53eb6a49ef1ced6fa4b2a386ccfbbc279633f3a4d7 4ae5357926a9a9e9204bc6f2c8d3c05bceffaded63d44c2e52792fbe87964b89 fbb4fa26dd9caef9daa40f9f451d01747fb79eb9bef92b680df1b0f52588fa04 0 523b25238b4edc3b55f35b6f3e58175c3f63b41268444c73d646405564b982095d30a67853047027f2713b68c2145ac132e004877cb1d4ec6018c98e9c3feb0a98d9e880919772e856a38194afba119a698a176578dfb545a67b311e8a54c10088a7de0b11d2fb5518222cd683488bb8cd9e3930d8d66d0dd976af3076f4b10bc62837fc63311ac9f613b24976917e833d3ef1039743aff5d36b142bbcbf9504b5dd7bce1365a93b0e9a245aeff2e8782a880bc5ed6c35bab42c377e0ff1700d361a48fa64b7e529edd291f83fe02e01464a509ce62b6472e02baeed9cf2160dbd545244dcbc322bf3629f756cdd2a80459d89988012cc21931350fbfab17004 -generate_ring_signature 5607d2ce8ec511c95bb7a1ea452f4574df04bd5bdbaeea20ac0e508f13feea37 66293e624f791235be8fcd3944938a213b1449de9b64b840f46ab25c244e2eb8 15 252083243400c45f44300a90a5a72cf124586df2fdd358c3f2d8a10a9d3b9f84 dbfc0f9a60359bdb13b1eeec597ce25a39019303f53e214106c1b6efa039f41b 1799c271c54721cb9b9aff31e770a27db2016d3462e8f7cdf97e58f5d957d1ea 0f3e0b58254ed1f16875206a5fa71d8b2bd3051cadd875a85c064fd43fe972a6 db61f4aaef31bec7a76142570228880bc1ba95aa3e130efb815c392daf1f648d 69a59d101b46108998f7147556e1a489d50a8de2822cc4b616fb316ba6308890 3216e6c0b89b0e9dc558f22b0646340901d4bff8dd6d0d37b428de10e1fb3d8f efad5c615373f47a5391c88bd7fd426915d61f772f8813fa1998007ee605b032 aad7a20871ffcf814a70a4964aadea64a2ca043ea3ed90c04bc0c581ace03197 ea57e5ceb849204391f7896c7cc93ac01645bb955a35e7295a6201d3888072b7 ef11e7753f6973b1f3c06b2b7dbc596db6f16120715339b17824086c12a18686 8a8442aa38bc171b5fede9ed5892c4c6f8b7834f6d84d6818134a2f61125f86a 12fded8c7ee0e7511d3f37d7fecb900ee662c3f7dc36756d64fd7bd5221ff607 97e073bf305e6e79f257fdeb5d5b126f12f818edbf3502a129a71948afe94933 71827fa61bc9bdf166378ae6e479ab50eff55f8498804bf26e92fce047f1a76e e1c93e67a747dff61c24a89817f62f6f84ebe585721cbb46d0139ff7d410250a 10 812b2d04456b45b6818b807fbc30a5638aadde2466818ff15281a09be39a5a00a61ea4ea3604a53dec3deea1c7df7ae2e023554ca5f2a3ff4c53cc8b3d83940e9fe5673b3138ebb57e77c7cc9c3d2e1a263d308266761abb58f6175b6a5b8d0193554bcf59025d8c967af773552b72fae6b8243606dfab55d081b4b640a27a0542f79afdf02186c46f053285b7a1d636494e2a10d8ae11cb833d46f24fa49f0ca10cf87572538f21baef377f6a4df585d6cf4fdfac6bea8fadff9eada00fa8009d35812b2bc13dcf81f82edff22e1399fbdcbe2c92f93aa769fa457da766d90c930aebf85cb20d9bea893cf4c4f04514a904836fb9a3545e9f11c6e9cc97110a086e89386835eb5e25774a05358d85604540fa68aa9424bc3d801f53d2394c075b9df7fbf58dc1340f2daa5f004ec67b4e4aa5b8b426026ada481762851f4c03632e5e62771546c253a94b507f7dceeee5cabe8f09eef8f944f16f2296a93d0be350e229edb889ccd3ddb22c984d33a83e94e9d7840932946d164fe8e1bd6c099c5c27a237c01d8042d49d089b129bc2cc142f12ddf77a856f817ec2758574023ba29e804de155a7f3dbfc7fa77a5f366eae53f7c4e962e01168c3355ffd3d08d33a709fc72f167758ec133fe90f2513c5f912ca82a56e5f17ca5cd6865faf07d3d5a1ecc34f48979e6f1e67604a44e749c33ba48b971b2d65920aa29699fa087a0dd99766049560d4b0942f7e3085d26ef1b44e88be567bf042c9979a3ea10c5105f85c6852b1e67beef8a3e0739b9668ee46a2b0dbf1e3cca85935744f10077dc31186c7225362c3ff5f5aee4fa7f27977b6a81b10d22c09505dc8e957ab0513e52d25b6d22a5af1a4ce02048749ddaa74f671f9dbbfc44cfce38c533cd1011460c5e5d18b26afc0687a55b313b790a3f6eb458d7bed7b076afadc63284301900ce9669e3f430879f6375f44e218af5607bbab9c9e7ce0ce12c1daa55a510895e3eabd3d91ea0be0511f2ecd6a313bfe74171ce6141f49fdbb06442334350c555b069e9f809ec0ff6fbcb19f873a7577d752c5a133e69490b28b7958d4c80473a41311b95b90f122b9a2e52c21e18c43b0f15f18cd76b308334db95bb06c06aadcb55c89c22e9793a99d3749568888be47e6c8abfaf5279aff0819bc8fb2045134c54d3cf4c44681b501fd8f32c57b1ab9a771c1dfe1bd122204b9c91e81046ed69f04959841cf300b8a766871107b1913198776f854217dd3e1de212b270d87f01dcc238f7dd4bf6938fc0871809279e14c7e2f5655c4147ef3908f22490350d973b2557ed2fd6aa6e253c8a2fcd3c84f2adc1f1d65e9715a47cc29384c08 -generate_ring_signature 781f7aae6916cb86442605ca1c1329f08692a28c5cdfe0cfa95d964ecbe6f9e7 dabd3b459a7ca4562fe5ca42191a402e51cdfe567079cffaf7ebe599459490c0 49 6d5bbeae1447773bb341d4f6253c84a563d776c81124bab9c82b8b55966ef9ee 5f3582036521d737a102ab0878f3482825882d869168795c8d29501d25741e71 52f9596059344eaf95f52e49d2ec46868c01a0612413866c50b351c5628fc8e6 57d139af17d71882f6a385f6a87caa657970517595baf226175248877f5ddff9 a9f4ebc8be21b9348b62361a712c90841c4ff4c595b36049efe2d101c4efd321 e8415eca3390ef846f46259c0e0fba6dd7427a7b5f1af4cbdae1cdd34abf7569 4f3e26a193a4cd0e338fe5ac6b4451217ff963c1ffc7ed2afb8c86d534b0bdcf 438597f124d1177200a93dfa9d8d0a9cbcceb2cbae2d93640147ff1eef7a2233 f5339ce166c0ceeb926acfe4a017911f9e1e3650e4eec6457e20cf52355ac4f4 4c59880049b15c24b6f54586a69b8935b5d8893a7dafa1550c5123cf0a253cdb 18a2d68bcf6db85d092a4362767cffbc973fdeb9eaff23d260c78777f8f57681 0d45035f8548a968acc0b0815518ea3024360446580b0e5878d75b0610911340 724763763a18220ca705b3221d8ee2231cce67235d0a75ddf076e8ad5523cf60 65236dfaaf133b1dce26fb478a81305bab5dd30e426ada4a399e29a7c02ba4ca eb7717bf4521a54e02db70fcb96c20d9d4d6673378f6b2c196bfc22a3d5dffe0 6752e1853091c6b4aa5f88df39696cdf2b7ab14d3e4b140d1c3905a6f86766a9 ffaf2190b741ec45ad0bb7070e66235764c44449ab408c6769eff87ee92df421 9a3fa68c3398397d68f7eac4a19e7235bd4256243bf8667082c4bf5bbc06b386 c0cbfc6b9c6b2e6c7c696cd7a89e4c79c7dcbb394199494981a6342fcffdea0e 661f99232ae0a6143a994c679146f2756cb4dcc6c465145b05d7bcf57aebaace bcd4b4ba71a309874300bbc35f9a9a541a7ee8055f798a4ca4dc546ab021f25a 8937c53d0262f927ef14ae7dda2cbd277363612e98669e58604547676a862af7 bf01ff591c0a495d7938ee4e3aefb0e20b121823451b1d902dfb8f2b460aabd4 6e0d51f94745295a30af485bbd46ef078fc52172f142f1f73e68d5d0d9ab1222 36fd64b91f05287e299200deb9fb4cb0e3de6f0240e2dbf274912579a8a75eac e72d9f05f370aac2cc5e0777bad931d6e4e193179e822583f02983f8c6bb54b7 d589025c70a128d8fd4b6364ada77612879a039ff49a61b710ea5ba856eb4cde 78c4e48f85675999752f7e6114460354ef4615e3ec05d2f6f96b85a0feb2093e 50f02e55a8df0e9bf0c44c66403ac989c630d21c2389ae73f3413f1d07f8fd2f 9d4879da832b2027ebd9dfe0d5d361a4dbf32158d039d6951d20d353d0129c6d 9e5f72821c4ac472b040e19d85234f46aca39613013ac66788c3143eff365d85 9d1d9d4be6eb21f591cef27b387545a22dfa1882a7dcb30fd5f2141b398fd2e9 35147ca542ae0c529dc9818dd8e4bcdc300a867254b9dd0317bf74a860a66817 17c55d7febc20cff8ad649ba7ae32318cac1750da6b4ec47c31c0f49ee1643f1 f24f5e7d6a9a0e9c457a0ebec586b4bb0a3a5564559cbf377138f64562df2484 952e0f4633631f3eb0135819fdb7aae7742ac5b2024c5f15ca1cc65e1cd08f24 7b9adc5c33bcd0feca677012599cd9a7fad17de30a30efc0981029e15c4fafbf 11e437c3869f6f8d822ee753c68b860560480a37eb57706082d076e0f601e54d 7b89c9df6a8a9f261d298a996c3a1947a6f676c2c7be4ae7643c2ac5d8e89c62 ff3e6f71a711fb28a24a2ea10170ec29d4fc3f3e2f2de6a8698783b0664d941a 919436ecb0dd620ea94686ac3fa07bc17a777d48f9c0224dde1703d7a2ebac63 7088fc87666f3a284b325d1a50ef179e47ce44f546bee688bbee3377b5462e3b c4bf7d3009908f391b0a36d2768394e429a4afb69d789d64bbf1377402f39b01 5626037572ef6d5c06636c8d2c7a56e19e4eaf2bfd6229204d4a60157b7c3d9e 94c3d100bdf06065c3d6c21e4d743d925065888271afb52777926c1bb49698d1 45591bae02bab2a3b21a83305a149c0f1ad63d16f23501ac471fc5195eb4c934 fe5634f879e4007ac0ffe322a23d96d428ad09df6eafd123e67009c77d3826a7 e131ff9519e778753cbb08ea67fad0bf1349f8bcdd3e2a9e30556d11ead0dd5b eaccdcec9531361e1b4559e4a9ee176075cc22a6770864c21abab1a28fa062e9 b6b0a5cb6c1acf7b032fe3401997b9be29ae854fa7d6c1dff8228a85426e8e05 35 d8fe93012fec5d202fea478b51dc5af3c87e5b412c3fb08bf2c8bed541fdf20d7a3ec008c2f0d60942b91e669108575e40bb33ba976fe62fefb9a79de3c0890d273bf195b698a43821a8161bc9f80920edade208cb80b29a56196793554c8d0804e8bae8036d3c9a4fb4af31dd43184f8337a6338950d32af747bbc2adeac705c9077b246ec19549a57c5bf1aa94037ce32ba7a9099351cc1316d9328c6155076b6e82c6d098597445b96e319023e8b46ae190567616d2336c91595135b7710dd58723d73fb870f178a5f224482d2c2d9f55c1ab612c2606139312f5164c5e0bc8ffd8a991d926e3a266347e2c004aec31f4bd4f98db32d39818e1aa7dab87008517faa1424239a44079b4c7161943d6b8cdf779374f0bbf2012fc73666fdb09fb18858d96b4aa594102f414fb2c0aad7e49b520513ca6c62d64fb843fec4a08bd2285dd7f572e7199d149a83da6464fa93643a88851a018ad6fa6ef201bd2044b272d5387d6ef576117e1707a2752be17dbb21f5822bc6938cf388900796f044c43f557f4c4b2a24ccab892f6cebb774ca186568e1a80f0ae7ba5073d3b3b01e1151b4f538859bbea8c7c682bd99c424d6426553663ed1201f077ff9808db0c76dc6e351020a0dd0f122df4f5ff545381313992c3470a6d1905ba87b000870ac9513dfff24f1a1bf3c5c26e0fc35f488d67467bb21fde9ff88621a91e32de052303150b9c06bf289539bb254db0f03b7a8a2c0376076d355c9047368bbe010032c0eabbef36d528ce939f5c81f67eb265d980e42d5ae529cb3093210397600038441cf34b914e2b8d315a05a3ff2e0215b4d9efa8a000b96bec4064d7654101c6c880205947bdcd7303d1ad34c848538d0b24662b9185ef3da41c7223dace03581374907a5c9785b9135f0199c774207c7d7b0ecd7b8ba464bc3df4830b780ce885ad3fb2387ebfc34b0e3c5df093ddab9d036d970c399ec4bf28a71cd7ef0baa5d353cc78326c42b6ccd49e762cf4c8642cc1c59b536356d3c6fbf44ff0d0e094c977a10cbe6bf26f367b6e9f9c02f7f469789d6b562d1cbf1a36f07f7f70a3a8fda9c53f03e721ffa7887e2c6b8965410932d888115ac62ebfa92ecd78d033724546da824872791287c8d6a534268e2abdbeafa488d8128c6d26ebe63f20667f461104a0c8b1d061da0f3b28b77379d3258cf58847774c2f888c68db8420e19bd67ef3ea2a47deeed384de335996079bf2c703586d7d66d95c6527f33af07af69dd5be66b65404f70f3e9821939b51aa5de51765a94e5d1307252b05a4c01e77adc9905cfecaa29fc8122b13f7aa999dac6cfb50fa2abc16460429827cc0f8f24d22784e5d7bdfdc6e55f31be66ee1d7c9a3a5a7e2d92b7bd1501414feb070b1dc12e110ce7d80f7e1dd67849b3855672008fbb3f34c42f5b7c0cce9a920f9a601d1bfa583a304017f1f600bab311d41f855c669c0f8c4284825f7b0b030c1358b710a4405c2cc3281714ed036eafdffcffc65625f42ed2386c01af4d7601bb7c2a89ad69b05bbf41e3d1deef6d63c3928925beff4291f729610b505c1d063752f43914559fde2632839a4418c505f5ed91558ff3b21ec145d5578001360dd4c711b46a1bb705d2c64a0c7df1480395cd65aa38117ee204f427e55a7260042c29b971490cbf1d542b737d5227917c7080cbb29c4b599c211efcf8de5287013688244d1566963693798ae8a0268365dcb049480c2ce85f31a0b13b9aee02030145a674a3e700150ee60af5520213c46c7c3480027ddac5df0a90c4bf1ef406fca63614e7bdbe19ecab77bbff6b6daf355729573ca9b3a409aa9e9b6ac57a093ccb1be1c819badf96c0270a7e033aceb54157fcf16a36373d0746080fa0e405e3c882a36fb846b82666eb815af683265c32da54e42ee0942ed1c215a48f7504a96f59f79760b0c8269eb875189629f9170cf3d50cf6903380e9e251245ee10c0e1a594c041a6155f1137b3ed40766842d19b8d48990d74319328caa3b380a01df9d09f76b7dcd156ca8d6e76010e42cfd93e5b779835f39ed88feea44ea310b689d5a19e7da79ab595135c35889edfe44f47a4e698a859cecc471bb54543307e198b1efee4c03c8eb53a4a404e31eafa05dc5c9a70219769fbd197eb3a91d0dc9b5fe08bf44c47ba431582490efe1a870370c71acc30be548a683024202e50ff14f8cfef3e3716f60ba95d1a1cf6ab1550dbc204ed86246a2c5a681329600066d8c3d3109fe58dc2f53c682fdfa0756e15f752e12cad949f37c8a38e2e9590d0c55c25c69b692d1857a1c42f31cba94b1fd96db9c0558999d34aaef5633c10ac69f56d70784fdc58505c187c354c07bbebd39188e5ede3e121b1e96001c450ff488108ac4415edf332b9fad54da22e67a092502b3816b291ef4dbbaff0dd100c3f5134be3dce80dec29f7b521431c85d3f036ef92bded0308657446548cc9088d8364b984cda1bb925225ebed08b8f5e02a8d38a81ff9c6a2fd629a94680306312a0f1f3e01794b44a905eacdec9799baa2986d258dd63bd701c30364bbc40029861ad1ec428d9ede1f7dde3196e8506178f87f944dd3ebd0d656e4a275600b29d3e5c1a6210e3db235d996c04073db321871ca6d9afe9c493cfcd987514508befbaa7276f8eb67e500285f9122d62eff6982a44461e035eea4d92730fc4f0df353c5b0c2a0af6156dd88f6bed1d7e54fc3dcb4dda2425d6be769f9b8cb020a50b36ec318ecc6dba966eaf88bbfe06aec868609e64b8ee7293f8d240c7ea4039722442ac539c0d22942c7869919d18d8d10ccf1280edec595eea82fb3b7ba0e81e54540c8767c168392204d78d4e6df6c5e48228a817032806c65ac0bc1d505b92e208fd7d27f9e0bc2700b110879d2ab802ee2eb10b35e0521540aa0b0c808eff9b720d0cefd4e8739a4848e0b8def2b2c88c0996c2c6613407b435ebe7403e806b2351cc60ff776c6b3de87c741f48b07fe45de41102d2b55f667178c9c0797c7d50a08cda2b20073fb3b381ae40a625c8f74ca1ffd5124e1c342e51d900cd386ccda7a5433cdd88a2aa31d1484bf8c90cb8791090f6b0096ef1d84d4750145d7393919cbb29ec50fd8bf47f85c38990cbf76ecc4fbd6ff98b77c8b206d0c0af0f5661b33a8933dcc535c916eb49d6e4c7e335bc36f04174c67903339fa00f5925cf4e975f7e0102c12a82778293140520217c18d56e37fa00e424940c70d7785a4b043f5d0324ce3785ffda5835f36506620ba1740aa368c7f1aa6b2cd097b8c606b8e03efc987e716ce0c2a6c8bff784690d15c1260aed6551ad2645d049853aceede4a02c36ca06b4accc3f66c2c80ae41415b6a0ea0e56ceb51c45c0483fd17c124575fd0c08e86cae2b471dfabbc0ad8a3fda70906f78b42d6093e0d5f0893134b5c4c28f1227779a8459f5f6b1d9c6eb52c60f08123245ba695570ce89942bd9e679a8554eabf42450a71458995f66bb276e256c3ada9abe0aecf0d96aa0bf1650080feba619ab005612f60151ca6e16818f5b910c350c6d0735407da32644a33f5e367d35cabcfa862f2d826d5f67f3ebea6441d124260eb0cd20f131e09dbb16a2854dc974552e0a299dfe9c5eb43ad91cf427b3181bf856f870b740ebe7c935bb0cbd3128383aff964d5d57c16f9249ae8173515bed3af0bc00c59464b1113188e5029dbe8e0cc3d8fa8eb2d272164215f60799637cd183d9b02d56e985d9f15a3b50c519d47b6a7b6c1369deffcbb59b18b60109a8e0b23140beedf4b17c862c238adcbff74d2871dadbc48b810936af86067a68d4b95c1c200a0ef7f8eff402fba8454a59712758db0cde2be748ef886e94919a9ee0bf3170af3a699c40f2143cd8afd078b4b2a1b7b10f6e4d398a32b77b1576a16dc71db03a44f027c22fc8b3fbb2b54aa4c309a8dfa39fc1bc12adf5058da648e44d44804c1366319c7c50f0ddef4a719c3e660be546c223f0403a7f418a28ffcf2951402e2443742b0581e13545eb945072c5eab773a0dc19f5527cdac61176249ee2307e45a41d9a0662dc14ece168ac4da94dd652e743b1365180a9390bec3d246c50b622c0eed9cced72b762a4244e26e89048ab6c8cb7dcafb23dca9d4f6d00c850894c53bd8d3c4db9f1cc1944130c2813a84fb6e013d3a73cabfd4473801cbe3096ba631e8bfe65fba0f04ae32c6fc7ea44e2e8ee17c4c04f4cbf140248f66f3016952e867339f1b3d7853b25c8180a452dc30e126f0942789997c0c5b6a812a021f9cc3369fb058d46302b5862968df852d9387aba6e0f72ba131958ee0e35d0a6f8015225713d6e457be74fb6d63de9a01d7d6a6d4cb103713064cc297a7980712e62d7406b48015f8110c3723dd528ddb9a308e7e7ac6e61db847a27efc7907 -generate_ring_signature 0ca6be8442f73c39adb0992700397888777437a7de0da8c8f80ac7397c51f46b c2483ecf2cb22c97aed88f73d621ddeb6f26c3417ed263dc17a486ff77274806 1 03b86aade5f2eb2b8868d951161eda03d4a47efe945a9dff7d630de9089a94f2 ef2190e473cce3732bb33ea3a62a4d8172a78336453c32f4419d1437ad3e950e 0 e70de0228fdafc3555d07ac61e61a4368fabcdab228cafbf0ec4aa2c8a59260229d579203c9f5ceff024ba0fc2eb41aaeace5ab5ecef65be0c2be53844a85f01 -generate_ring_signature 79c5aa9e030b432d9269f7e35bb8c1ed8eca493372526a02ea1d6ebcfa52b385 9b9a27939cd35b70d56eefed6bf3473df1bf5e1cf3ebaf7de8ea58ef212170fc 16 1e6c15fded661246e31217f773daa1c73c6b5a535dd39cdeece6347aa89981ed a2dac02c4e2ecf3f06cf95a267f7e1db2bc014bfde9b8d5e4698279429848a43 ca579ff489a24164edf6a84c9bdc87374b47efd80c3f994184b770fcce575296 2e247431d695436c7107a280e966eaaaa4d90440d824f93d1c96ae49bc16d4d9 f2609d17a8633257d1cdfbae1690892339e49f9a46eefa9e7b97d5b0570f9cf1 bdca7e43816c3c6fd0013557b1e0f2dce14ead44b6ceaa381986cf6c3055adbe de1b17fe16b510a67e0fc049a5cf4f801a9d9550e7ab8a5e4f74ada85a4057b4 2e9281c688bb6d020dd8a4079acab780a40329c6c54e1947f0e0e7d90b614aea 51dc71ffbdba2913ec8e578384e4d25fd2bed760dda9649155d4ef3f49898c63 88d6f98dd9e6c2a990aa0120152a372da00c455c97b22767803121f55b9d3433 6ce4fc262a6b4837e5f7baea0a512112a2d72dc6d36570cae857511197eee9d0 ddf3cf1ccbed6da657be10b878abde58598a07eb6be65cb870978429bd6550f3 5469427cb812861380add098f93b02d766d7b9de7b5c34d17bf8b2105bb99cc8 ae7c7772243d1b1a0939390bf562946634fb8f3a3df045c15f622aec4a19b05c 62f43f2a86d3cc9a59a82ce2c087c9442c8f0de3d648e319793e8c7ae4158735 1fa26c1a7685ce10b3734969ee68b9d8f441b0ff1beeda2a6a5ce41d7857727a 7f846dc0a1378202cd26c66f6d80322192979c9191c9bad913accbe8f3b4030f 7 0bbe1868d32efb1f473ee1f659d41e42734649005026e1ac279d5a4f517c6c0e5e346ef16de3810d7d88d57a2d9f2f6fb447ecacb08c84e9bd4e4a72aca50808e03d2c29c27a831b25786821a8cac11d96d11e5bf72116719b0816d642135701a1273adee1d7d1d6ea3141c1df8d4e24abc0f48a3f3223f1b230f8294f5e1209bf5493093162ac098f74abb5ecde6772c57378e3987fec98084ae4ef2311ff01d2055405ab8ca3803feae7beb18f3b30c06c38fb3f7e31aa2ddafdb5f2e5860f8b7a8c95779f997002a36fc230048a3ce226bf2a2dfb29ece8e835189301960ffc7745eb3ea67a64982eb099d59974868b8c86721706600b3e5675658c8944046664f52af1d85774107cc40b326496c07710797c3c475addf9c4932b0fb03b0c1ef1d853253c0c89a6805c99e7c610bc81ea1f39559e5fc3f7893da4d27b0b029ee580fe3ae9b8abd48810746be3b7e5374dd57751e3593024f69194b498b804e4ef37bd44f2d0d59ee4cbb6f6a114103e1cefc8b58077b6c152221ce75d0b0091bfa7db1dfdaf80a122d3d92b60279802970a5d5f03ca33c51812582d724b0b01abf07180a7cac8118aa5ecac6a516bbe9a2a62c72b59379bda7d93d0a37107fd3f78067cc47207911727df5529a4d4615f96f047094e51d2f316cc3d280603c922f432be163c96c277b3899f3b5bec9787398c91e3b0b5a8f25d8e7ebb0f01423e4b9cdf28651fb7dee1ead55d02bbc5b02722a1c5d14588a9f27b8cae640d9b7ef746083f33f0873455d0e3ffe469fd3383e510bb9184f52209fc5fe3a20f7b01928698bfbd1f33201c3b2a6147a6bfb78cb2aec79312a2271d41c03ffb064014c7ad2e736cec5bdd313fe08d8e44953276e3b9f9150432cb0de79183290750a91785fe2a5f7052b56dd4a96af3f41760984a032171615c65a5eec24966049ae0fca22086de48ca7222ebe52d03e5bcefdb174b45b8c96801f8cafe19880b60e07801447e325a06aab7ef883c275f49298b7795063b015eae1ff9d6e88909fa967f53e74e7a50a5e2399d8ecba2b7714bcbcce137acaa3e778d767f6fa106c43bb83ce741c0e7a9f5b30e1b52106aa63a4a03d0ed39bbeff96116e3c9900f44c6b560835c311721ec3cf5d22d2a023dbe4cfb904cce5921ebe6ca88b7ce07922806026209e364cc8a5e29aa60b546bd56fc37fceb6322d7a6e92d7dfada02e2e72c22e3fde3c1d7cd93e93621b544e4a72fe82f0f259a19bf7fa5294adc0ca42df2ceed1a1256142e86ec8cbcac099213b2352be87c941468d9ec1c149f022469523a31842723324589f45f4567028bca50e6d238812521b717b0cd8cd40050e17ff8812ae27f515a2ca37b261dfbc50be24b973ab2d843f0cda2e7917703ce7dc6d30ea5a15d51caa3e2cdf08f3459f0768f9df8eff5d8b2dfc0380ae30d -generate_ring_signature 80e43999bc762b25fa9d83c6fd111032ce5582d573d6f0f3e82e0f989fb6b8cb 1437aa8974c08719cc58a5334921c3201e9f45a5290f2581b26345a659b86475 17 40584e3d53899817ece3a763d73fbd5d5a09cd75ff713d3e06c3eba2fc853319 e4b87de4b1b936bf74e0bf1aef738e47297e65f2df50c566a9d5177c75917534 98449fead3b69ec5ab2d9f524ce8aa5e6d84f14917b3b03575aad4d4c291a634 23619e368d268b186bef7a5fa0165c31ad8a3bf4b0220bc262f484067d9ad4c7 06268863803442caa2e603b4791a097a8f33c45683ef55befb3c0d7e3055c36a 61ae5b158be8ad2e489dd7b0b78da17166a97f09629f96342e8712788c1dfc0b 4852fd68ec5cd1231f48b79a8bca21277e347d39af3349bce848312452874d59 5446a777840c6f3f75aaf437d1f84addbd22b5d5c848ffc3b7fe16e1157e4819 29984210fb9b7462a3cc598bfcfaed8a0d704d02851f1ea7d3e7e3cb8d73d3fe 93d4243ca3db959b7f3d7af72a0bc85e27226d1c716dcbe1c5b3743ef5c289ff 7efab8e221de5b67335eb804564b60b5be37ea20497329bceae89822d9e530fa fa084a1bf2c317822a31681302722b4a8001fa2aa9a0190e45b68346298b9aa7 bc15f7855be9e63f35567ed80b629c270a1cb1de56ed670714645261edd0acb9 17749387d62c8c3f725f1acd5b44c955bd4b35ece33bb5b3fb121ae52dd07750 7b83783748d179d74bf5f8a177a8e400ff4783ba1a24b7966d99b587f6e4210f 235b414cf437b43c611267566496a834045ba01b3f16c7b83a838aedb35e5863 0e326a30399705ca5c7fc10ba5f072fe06656388cbbf8f2417032c6d3e1f1519 0be7d9b1884397738bd4495a62ef77233f1b262363539f6bc3834b3430c84408 2 eb94166938408577a45808552cd51352f6ffcc40f03f596ffacfde3e9ac7b50024ddcc93c7be70deb202a923a924d41a66cbb1a4ef9ab6ab660c3b8f224fe1040d2e79825aedd60df00ee292be12da0cdafc1f893f51b37356e5d68551fba30db8f8ee0e2a033fda20d1005c49464527589bf9eff8bf5e14e1dffc5e81adf407a93c8ab8a007fa20e963df974238bbaece93f95470d9cc8415ca7b8b3d32400681f82b8cece5e152fd54312a9c481c124ebd94fea24ef74c4fde837e97e31e0ffea03a6ed5b7e864b1db520897487d6758f91872f5f2f2e922068ff3ec1ed4000302457a48b33868ae02e1ecef336183708f43935e26f77261a8a7130e9e0507ca91997751576260ed3566ce29b424705a14072c3a8753bd0350e26daeac1007535d6a441ddbc8c68a74d770ae1cd23105322015967d2366e103769dec98a80859f995202d2194affae7bae42965ca2dd820f0073ac34f32c9bb4d9e6ee3070f4053bd90e8dbc64aa724766cfb0f00e0e06ee07241e748f216e9749630a4290dd5c610fd6603022398be9d0db9bd6dbe83cfeb3ccc7d5c5b86acc226415e7f0957b52baff307d52c144de8c34ef36480046a04cda7b3221c3d9535b74375fd03da2491e036c7de424c9f2aeaae40aea5b546c57e12b08d170ab5fad3ee773a0b1e1bc4d7086d4794bcfcd605d39eb33494826c67cf5b3e989082eda1d61e950a6e7878783bd3a087f61e041c25926e207aa2adb686b124ee7d7e1d1641d8c20d380e986cec276bd823bf8ac174341074f568e85b865f466d2834bf66bdc8b80dd7e8a531ae71353f78ceff67154bfec3c5a5474a20ebf517ad2d68a8433a2e04de3e501cdd60e9d03ac21712a3c24de4421facb07e164ca68025ec71c47ffa00a68766dc2efb0a9b0c85ced09a48fc7d7dd169b9b8a64d916afea303540de4017feb4f5be92aa6159d0801f3bb8ee8aefdbeb309f6d6c639f5c25eae0fe92a01b5cc58a4c21300afd5d165c0900fd156374dd03482fa376333d1b168d7ee120308d8809a35a78c0434057efc2b51ebf6f7d3f2fc771277950197d3e13c5b6a0396385539bd059ffa3c12eb42ebc995ab020a5d2d026ae3bed525397026ee000e8c700fb7e2704a9dd41ec8a895a610619e87591e19fcf7c5957365e6306e580420f0c09f2a6a4e9c6853a44de2773d302c9d9fbb24472c2cad4303edae9c1c01bcd95d9e2ea2050245fae50d6e36347647dbbcbd6306f67ae9383c63799bbc093a0351597e0d56cb8fb43c2927ebdc832ce401a98a16082b56bb8ec10a986209423583e1cc2002a3ed6f307cb7abc97b270c61da2ae01d9d4ed927a97f30e106a8e1a42f2238bc8c54fea101d53a1752885b0f4404fcaf285e555a18c9dfdb0e9c0a1d9cc57c296f91c7346adf51945b0c31456fb3758ffd4a395a40250d020763b726a95b2168ca644ba999d40d68697e8d9d2f5970c8641b9a53a61c2bac05be5684c7cb5397315acee2e1e63f08cb7922469f532a97d2aebd5195b2fe0602 -generate_ring_signature a1cae1149c356e23100ecd1987c21504dfd7eb93e828bd3e67010b2618b67d12 41ef904648e97ded7bb6cdb675c0eb7c3e265920e0ed3a43f6d9d52b9cac4950 4 8af0cd069e8ed1cd5b5210d4f3b1234fba3701a51f71223a642afc1ab7c2ccf8 68a106230168fb6b767c70b9bc50adae625609a4deaa23607eb431a125d62acd 7f77b78b984a927a28d64f19feb63bab35f545c419003dc6804fcbbd0a6a7d89 02e2ec9fbcd3da1d36c4426320a0ae5dded7b03e360e801c842d6da1479119fe 9bc45f2111dce6e47ce84bce74bdb15374994ccfdcc33c497c8c6d02621cc402 2 60ded68241c357732f79290b35f199840589922d852fb66f6d5534199617fe05c15610a6a3821bc2d263be5dfe32b5b59bd5cfcec4ae1216fc61204047d92f00c900344a42ef57b8a104e93cf7b945d5e715dd39d86a5aec83d20d6674a1210665f31cebcb661ba213245498a30c716dfb459494aa7f7fd12cb5e2e95ad82901dbebe82723d550d6a8628447ca27997aa720a58e1bc4745b2c75e1263567c108d5bcc19ef6f64fdb392b2a52505a7255d5544d9026037e6586a81b238ef8ad083d9a46873035d309debf6bd4ddca8a292a3d03eb94800c11007af0c25444db03445ee7df8dabf763c5fc83151f3d09da5781c734d966e4a2a31925e36aaddd04 -generate_ring_signature a4a40107ca42f136d1a311b9dba01b70ab6e9b488c9d4bb1f82137a8de045b0a afaa82207be08f51be6d9e58d2029c812fca1215e9a4c9ce7614fa9b1ead0e33 1 21eb68d3bc8a11f481c4dd1aa33a7eb137bc0266faa99ad02035de1940e96ba9 4fbd33282caac0fb0207af80c006ae9da1993618bf7f2eff764426fd0fe7f204 0 976d64ee5b223688bcf5fd91721d245cad10601776ee516d040b0ad824cff1001c4b6005796b989a09dec70073942f48b38934d412a2521d1b57addfa751eb0a -generate_ring_signature 856142e92819b975d12e0fe26c75ae88da078d345246b985f3d2ee7b2c2f7c5f a7869efbf3517f7b3217cc10c8d34aa79dffcbcc332863aeb9dab30c14f2c216 4 c2fe2e312d4d1b483105304f0790bd832bc2bb194157b215d265ff8f1fe5688b b6db213bdac6431e7a58bcd7bcad322ac7dc04a2ac609b2e2c1942aaa2acbe7b a9a365b5196b89e4ead8efe752dec4900446c49a93fcaf75c6e01d6155adaab7 ecbc8dbe05d49b8c9ab8538a959747d3c965abe9bcdb090829e109aa9af410bc 4ab503c0deb81e5867cb8acfe683c713eecdeb27bb51b5cabe78fc3d287ad507 3 c4c26506f6d9797347707dab7b7faa9def8e26e05ecdd90c95cfd0704de6e406e64cceebeba4114144d568cbc334aacf1637f198d872b3b9ef24ce091f64bb08994ce6c06b12670dd7790e1f233da881b966679d21d8803d8563004431c45e08afa14f7c60f0580fa2406542194a468a9b634ac519dd099780b7f7930edfc004ee20ec07d92a8e74f130ff63699824d78716ceb89c745dc745f6669c17e855038655b1f968c43a4037a4b2cc590b0243157bf8fb185d98d798ed0ee8be82b608c5d6965dd7b46fe833fef0e99167ab4ecf154f540055567d87778bf1820c5303b57cb7ff52f507c3f6dafc0dbefb37f1f57bf8074fb1f38e3c2e5b85db989a03 -generate_ring_signature d43a0443d5c3325225fa5986febb44adbda0422c3198fefc5c6f004c12eac890 48a03abbc676e7c1e6595e7871d3e47c65756783745b6c83beb3966c83b24426 7 54c73df736d858d956c6ecc78f71bfa621f1668529798aae794a2ebcc0cfe8a3 48f1b704c8549362e4bd701890d49bbc96f029f5b51740cd9af23be3c8e330f8 34d8123aa5765ff6fab0fc962b525c8ae0bce152a59c8336155f62b5f8261ca3 82f6e242df725fa43241d94c88c371eff160c9bca40e27c1ccdfd5465f8d1195 75ea08cb3c88c0dff75d744fe587524a5b3cb012c2f4e7299673dd24a07cd85d 8a3935e33e50f5f9ff79a529f18ed5c88340893bb688622625bf7007e15d5fe5 3261bc8eac8e3f468997a2bcded49c910fdf5b97056bdb5e81535665a23cd13f 55cd53ed388daa9179037a611a241494ad182883ba0fa337a9d6608a6f554309 2 f539a11cb38fa78190c72dd5f4dfa3250b89e2b3af919f8fe91ffa94fd5e7c0cbf0b2e9af4474c4e952d0235c131923050a04bab8414789a4c167ee3446d340404dd270ff04df4da5a7e301e9764ef56b816563559cb4cd2aff94e4566defc05de40d8a2e4ce90b661bf5a96b85ec8c7366b562966d7d3c4cc50963656074503eba2b2fb49139643dde2e53641cd91d53a95d373a4e5c6283a9d050b6379010c7ff82ee48198c40728c4a9293251a1c586c179196159533fe1d5b95341ef97014d0fd482ab810f60aab332adddced38b17f257fdb81788482a3cf02a064b2b0d5551f8a94daf972e7cdcfe747c8b7700f10c4294ef4cebf4696a939870d87e01ac8d9f55d19b9e1618a2ac7894c21672284758b3c285c20ee0254ffee04f550c5c083ee98a440821eb3776f15f7f96c337e3291c25f8c1527007a78ba03fe70e94c6d30c8fa0c7a331c793ae2921a53aed25b369f71e3e1c2964f5be379dcc0f49743115b9202da8862a013496964782283bd78a22d500767dc3a84feca7e10f80746423dc53a08f99db9f9eeb840c5c4379883a42df2a4543e670d55c23ad0119a2c04849ba4ebd15152c5236a3a61714106ec8f0d9ba6c8b908850c5c3b60b -generate_ring_signature b2a6d43314f32e184b6224f1d237368213d205e110a06eab248d8ce14dc66b35 589f05748c0e2fe74f2d93e8bf91c6dd062456acad1a8c440151142a36e37366 5 d1015e1ee08e69977d25d7e23692136b840a702afaa2ca04c7a1ff3d844ebcd8 bbde63dda3a37b486f0f12757b2e5a560d47a041f4bbba732ecf55846ef97288 839a000be768e6908d46ee701b19eebc912e346f98cc523c2d8ae63caf9c6c57 10191593db747ecf070bf88ee12a5f8c16f8ef506c6f5caac4fc0e0d0dd2b6d3 446c82636100dabcd3fd93bd36eecd42dc10ded9be9b37fd1c868ded993a8bd0 c188a0b57f2c52f5ab7ad0e98f85d05d317a631d20a45f2ff8d65e4dd9d00f09 4 020aaad06adf2a007b3aafcbf35d2cbcb49ff9be7f0e969e4deb02278406a80fded3157393258f5c7ee083ff744b34f887e8e729bbcf3c13336b6a1fcaf29009e8cbcf24af6ad6659ed9f5a142349d343ffc8b3573f055206823cd80f627430038591e3616bac855c3007806a6573083f609d32f3a3e84f5633a7465d0cb2d0195f562dfc750a95a5e0066bd112820959a64c139f6dc821d8f5533a6541b7e0d41d0105dfba7c3579da79d20052c022f3873199f49f046d350d90ff8b3659f03d8e2307a338ba175fef90ae978498bf74a6c6e0bcdd47e6b172825f04801300f09bd758eb4f229fc412951a87acb062d0e0c085362cbd7ff90ff8077867397095d7e9a10f2b8950ed4404dc98fe3547c14ea46ef33c69763f7c8a33cd09f7f083d2d14d277b5ed0918052d527ca9c484a16016f8d8885b57d4d14488bd8ace08 -generate_ring_signature 2cc6d7e8e09924db18a5cb8454d9d4651e68b7c40c10f2124c4178819c166731 8a63ba236ee52e329eb0cec80e8281fec17a4553aacee39d386e7023e8c49f1f 211 402a41ca99cd815d081c2481ea92da40524a3c0d1115380d080643fa3d9b0261 c643929caa547433cd00d1e0cd02b77e37f5de0bd28fd21018040431e47ceac9 989a1efbfa052314e3f222b0d6a1870ad23a7759208790c4fe0dfe84f9a682dd 28478f7385c01c31b55f667e04f71eaafc7615d65f818155e4da35a160cc4d85 94a4beeecbef6b573e9fd9b3e959fe53b47de4d0da7b9030066e8ffbb31357da 090eb96dfb16bdeed9a02046eff14c0b3da54c8d93d4708d336ad86355ba116f 7b77baa8eac66b27d8c3a7b0156fcd94d958be2551351438d075b91b63c33a53 a58ed775d98bc67e07945599536d3d2b4cc06cc37e4f230396218bfae0fb1c44 29320ad589c514098a8ec72b9349f0940737f2bfa36e9330f2d42c00a0120386 3a9a27201c7bb4bccef5dc6806d040c30a8230d34eec0d685a6c4e40751f49a0 13f2730c4bf1c2b5a9d35cbefc51d4f74de8ca3271033c7c4a9d0944dde08c1f 73872a978fb3ec59c4f7f86f5c008cd9ee9f54736b180ec968930983176bb464 a657bf78310f970b68ee552e2bda5ebe5da601b5245d2454a30c0c276ec18efc 5ec07e85ab34bcac5d5172a700868c29b9ccbfaad9858276df0f2eb75e142996 9af36317b0c92e94bf9f88b3cb32eac5e2022d67c5843fd761328eb8d2f85783 65631374959a3b4b0fa5538d510a13edd1f616c1a7b304f1916004695dea5eb2 3ec33d71054ad6db9e4c10680d2dd4dccaa408e8796ad3f04f63e6fb6c9436c5 eb7fcde5107a6e168a6bc7bfd51604c60aacf0ffbc41c4ee9f004eec92a441d5 4d6264610c118362726519f09cc02b1dadc926ad5d3a1d334d3203c42a7eaa9f 0053001c4a77bbf3aebd3956aac9b8420bc67d84947128c32d651d78634f2890 98c403100bc3d1135388a8899718c67ae72d86fbe32bf4ad6430eb0e5a871f59 1f0f066060620f72fc27072fb04d111d7890db94da780753c565114b28fc61d6 c7bc71f7658a142c8c2f32112d5f2fa2bda5140632b577c4ded16dc0e0324bc0 e1d43f558301785c73f060139a114b59ba8260645d3a42256fa1554b50d7d1e2 92b26634220d7b331cf050d947fc8610d91f129412b01c29969001e7eaa9b770 a6db9435005617130ddcfbacd5f432cd688054c7bbd5d6c74e35a6b87b36fcbb 8fab60e3f2b22ee77a896e2f244f683e0215baa6c22124227548473e8226ea42 231600af4603f92dceee9d17187e0218993f6f60a91205a361a63a1edd23f31d 41065d0f4a7c7bc1e0e1921ae8db77c6e8bc58ed6eea0cfcbcd8ed75b7a657e9 83db2a59e355af551f2385866b1479993bbf3297877032f14a53893db3c0eacc 1f286383aa01569fb3cee63a35dd32f41c575261cb68afbbb832b3c4eb9135d8 14157b52262d16b5b2b03e0bfb051211b111776d2a777872dfae2a1f3dfbf780 8b499e0ded8c18e93b012b857352ca03f7c53d19a7b662b45bd6f0ce0fea230f be7c42646fbf9d17dc2c09924595162813a1cd92b41ca029465240f105ff498d 5bcc54cfc168b31f99d15c2e23cbbb33889107430b86dbedae47393121c7e575 9115043833cbe33d775d09472a193354f00cca070b86e2f2c55a3c587ecdefaf 62dae9a21077417d38636f9766d2b23e8f31c11d371b941600a68123a0e5852b 2f880dd8a7785fb4f6584ca858b7a9df171393eb1dbb997e049c3c74bd5c28ad 36f51e55611ed2b0ad671bc3b5a67dc32e9424baa52b7dcfa886fd16e32a4a92 cb88c24731f1c01341bb16711cccf0262711c5d538b5ee3d91e618a0aa94ae57 774ee3b25c731b1563ab1a4023808d1083f4d019438eae312a071e0963320b73 80f340dcd9f0edfa672adf1028fbe5e7933a5f412609062951c9c13984477c1f 846e5bb742c7d2c5e540a41b112dc6743c145a76dac105de39dfec0c03804934 6c3731202f8f8da0d540616f32fb1261187b0d5dbb8f4f86e36324adb50379c6 304c36bc24065978e078b24b16bf8811bece463f53926d8bf4cf14141a8accae 6e39e3ac724c929ed1fe8d2a1bba08b81b757f32ee119a07f8feb66c990cb484 2fe3718912375419fde8d55acc1e9f7ae8f3e8e4f7e8c253f180967ce9f6e277 1422514f9fd55ec628162935e2736205f7b19562e10f09a24b671fd3d363e807 ba7c20056d4c14ffd0f93dda7c39233f2b9f005dcff265a9ec774d54a16f21c6 4e024cfd9598522249b0940e0a532f8a2e460a06db24702c8503a7b88d8ba9a4 8bb41c4698f0c4e1afe52d5110012d704e063471ae568e4ec407fd6a7f97f179 1e5665d9af4551c32f5b41cb376f6ec70dea9a3b7c8568a8ce24c525ab1cc65b bd2af664fa7374d46ed3a2d6de4295b2b6d6d241af3df086abe5b9ee7765c8bf b598e6304c34c0a3158998db4877c8025e27de6ea53305f445f774a7235c60b2 7817004add781de4c2bb6afdcbcc88165a8620994a27e96e822c8b599cf9181d 402afa1c572a3e19f68ec8dd5c3f2ad4af9ec3dd0685019da41b208fe624dfd4 e1ff43e5787e2832904d4f55ccc3f24a896a673b5841cfb82590ca8889074818 2b8afb146c7f80094e3201010ff0f6c0503d4c916219e7f08523b6eaabac0627 671fac59f003840250f4070a05f89d73abbfefa4f105bfd8f85f377db6409f70 bd10a4554ebcf405fad8a7371ea2aff0589d0c554e83dda524a04663a7d3d694 81c03045a55f1c812b2280e0cb4fb6e122466d47ec60e10975eca58ab9a13d1b 1b3dae6b495af9875c3705bf1ea6695e7bdaf39c20947e061eaeb820026e9920 d89c734cb3226910d0ce056da4cae31648f5f7689f4879cb440afe2b783cc92d dfe58bd956769ab6129bc2966895f3eecf98d596a15b90dce4d41fda89f51908 90b7690e81a72de5b64b94be37faf4cf2e053c0560786cd3832ac0a887b6c2a0 97f5440f4fd3fe8928b1da92089fa2f2a2cfa22ee836e84bfe6f0f0ac2c0b639 78733374ee6577eb4aa1fe1dbe30fc49a26ca6709515f9fb9ca30ecec256e525 0cc4bceca6c04f76c8cb0579cf41869b523ed6dcbd0a7cca939040b113c5ecb1 a77eb08d2f61991f1c5d2d5c17ecff62b6f355f2c184586458aaf6f8fe1b0c47 e904d9ccc3b5d0727786b623997e85477572f374a157dea7a2ec15ac0b8cbd5b 529a15c0030b5ef91a2b172d050ee093b6a008726a5f30b4ada8e51272c89e61 e484b6e14d164bde5bdf5e11ea0360f4b3751add6dcb86e0609060903db9508c 678782c7d1fec628538b8bb22e04867e1cd37b82fc3bd27af6376049edd52027 7b75224203be14b0d9648feb66944b90a538a38977dc9def8515fae3d3b65446 471cfb7f41e6716e40f1e43fd3bf60619bb61cfe9647bae7bdcf159c6c011b6f 9a9abab7e9ba931b3e07d8b5f2a6b367e83b7fd27b876efdc15ab64c56bb3e99 3907d8e20f2cbdcb064d0f0b5a9cc39869aca703fea645e487ae7569fca87229 46a2823791014ddc54c9d56e45f469871e4f14f33443f7dc337d5910beb1aa19 b30317411d74a37484df3768877d0e92b5522e5622cdeb19db037688633a764c d63f7433d699967d4dea7f0353aa6d83a1db6688bcf05eac535d806f2861136b 05e06df4e9ab60de679307e3b12231ef37c0a7e8bdcdbeb792a140e0236486ad 543583fa163484a44a43267e2ba34db90e9ed2cc570b7a25c0e45b22b9ca1eac ca42a5c54f83e796076e644a436af8565132ddc1d075b95ed355c7f2b0b556b3 f3f5efe8d35449192c8795d2cb1059b720d0e1044a3ca69b1f57962fc819d56a 89bfa2c9258aa739d4fdbc65fd3b6f0a544d9cf4b22de25be25b036e9d9ab2a2 092f55c0c3bc3a275c4ac457c0b15d676c8d5b2a072472b624f1874fbef6c372 11595707e8ea5783c592db350724d7463f8cc141fcbc60a9863ff890d783131e a381570de73bc10fb7f4b4ea3876d21bde840c0cd5aaed2c2521cebbff77d258 c629d6bfd1ea0dcdd46444c5a560a4f386735c7e1dfba644e119da62637e6edf 4605ed8bc6ad9c8734a4f9fa61964edb5b73f1746b568a3525b088b7e4e28738 d2bd09313210ff4eb285b2c1171af27b1f7d3a14cdd78da5d36d5df33821097e ddecb9ee20cc01e3e00884943e5b284088589501ac73c033648430b6403bb0bd f983fa409d58a694b709658f79f488051a5a3627a1f5d3d8ab4f29b88ec85591 11b78bd153835d415546c093859342a069c2f9179fd77487ddd724441f8a1d00 a1be919083bb6e1f0e9ec941588f3ff0cc80bef966f32c1e57fe51f9d740ece1 c5c5a8d4f9a3c212c8ab2cb9bea0fe4a2d1b28ef78d0d92948ae2bc58d879924 2ba7ee31adfff772224a6915cc1026733d9750ed78b0a6003090d01b5e4800c7 f31856d475a6d9e542a8c52940e65ae76aaf239c58c7af445011118479ba2e97 d8ee080399b781b97e9e320be1efed8826ab3332ccdac22c412b96b587e49f3e 046b156f6016b3e8c4e28ec46e6a894a14bd085fb98d272f954646aa6a68cd8f 67da4100ca141d0b335ce9aa673c8ccb1c241d54e8e2d33cefd70fceb5b1d25f 93bf5b1c7a6ea142589637ede192df057328a7ff99325e8d143f5933e0e8d094 2013b7002841ce5b4c162f543ce204e55ca37c290241703cd444638b7e1956e6 e1fb9f7f35c2ce2f064db2652a494fc4132d67f1435d2c422651282e2d5936be 6b84444a3fc1f4ed71f07fe9807aeedc3d765e86a308cbddb549e41a07637540 6922d129dffb6f2e7e05e25d67a675deacf4a3eb7591cb8f411b4bb02fb352fd 807fa83b273eca0d0cdc181b9839f806164eac0da439354f27bd4c999fa3e112 ddea38959723583da1265d5bbbc23fd21d95912ab44ab7bdd388b8f816d7c950 d31e177c298fe21d24cda414ce09ab970fe07a16247afc1931831858f682913f bf212d78a9d4b8141c0e1e03b553c0be1bdfeb5b17cf2b9b109a1dd2f08fdc19 07bbe8caa6552571cd4fd46f165a89c5eca829e04ababadc29fc862625ef3415 43339e682fea6b57b40f7c199386f392488077429cb491f0380d649a87324411 46c1cd36c1efec4e065c8e64700fa8e225fdee7e7b5d0455184acb459785e924 09ea83b1d7d5a7b580b54e8e95f3204374bae8ed92e1271a8573d9d72baab4a1 8a7700e99533fcbbf456c9b22d519a25f1f5bc3099c71aabefee801277d0c19d 909b328ce25f2e5f270ed63fe45b43d242c03c3f74f3ff6001978ebeb418cc61 f8e3cf614e7bbee6985e1d5604dba2374630bbdb9651e91dcdad5ab53409630d d6052da08cf10157fb2a2e3b44c85cf76df325fc919c588086972c6bbfe193af 9a3b931fd12fd1f0d68fd76d68e44ac2de9f0d82fa476f50f0dacafcbc38dbf6 f07f3e41a4f7f79500cebf1b351ac5cf8346b068ab1cbef602fd60136b20cb6b 15f00a7af5e20b918db78299f63ab9ff993ffd9b9c3e50d32b89d8d68f1cb6ea 0402a24ffea45621cb1916265651c80c570a55e8ef7aa8577afbe2b15f3560ab 0ca97cc9867b2edec0d46d9d0fd14071c4c904025fd0c5ceaa5b13391a7303c9 755f312086e70719cf72de5564ccdb28288ac1fea0f41611f5437754cbbb360c 4f865ab94b9747b5219e5b62f06c8acd434b8ba71f9a49656bafef74e0fbe000 eacabe372936f28985b08db8fb4c2f8c9b4a48c261d698e77ecae3c3232c69ba 66e7c6a7231b1d3fa2771babe3dbbd42f1d32cf5f80e8112dc65ac08ea630c05 826d230e93e779a6e5d9ba481cead54668b91f7934e5a47f6d2067356d88a432 38d8c90a333e211e35d18433fc8e97a2912a4481a31007dcc3cfd7d02d58e445 b89ce70d879d1748dc572e179124da2922b52a9561c4e5d4ef787e65c3092bc3 dcd03083e2edc956b86afac0b6b72eccf61a96c0b9b1d8c49ed5fead44c22164 0b3b6bc0b8dd2aa42ab1909e31585da82da55ace9c06a9075120bb1584c4e65a bd7ded926e2626afadb1ba4c6a6484b02fbb328965bee31607f24c1f11cf35bb 1b822414e321327b717a8b73a68759528b22454ae4f1efbbea4acf27553bc7b7 6fd47667514ba98fb485a526bfd3eabb680eec1e6f6ee9b0ea242f051dfcb62f 10eaafcf82fb0ed3f7ac45f994eebacf1794bc7b484c3bcf1d4385534a7ac8cd 2f874b03e03e634e4afd81c541ec6061d956fdffa59940360b6be44ba08baa39 415a29f704999c6a1d57de28f50b6c8a28aa3a45e0f090971f0350169cf10442 65cc454756fe9f0afcacd7ebf5ecef668966b8d0a689ee9f8a80a0d672662d93 ae853a35374a5f088e4811ce400ca24b7292209f5591fb286a840f811a1a3a4c 13fce6e2bbc79ebe247e21edb3221333aea417be828cbf7dec641711cd009c0e d0d1c7e0df37e6dff7fca30ed034b174b6395667162b7ec2f81922433700006b 11700c2375553b574770775e7ecf74d356024c6cdb73a12040f899b072febab7 9f2045dfcf371ec181d645514a7200019f6917be67e5b29b27a690fdf434720e 9211009b28ae0d38739fda0cbc46242b9c091dc864e3849463f7d5cb6eb4224e acf85b5927f99c616e7f0119c2635f9e56689f1cf771e94c29d2bc6af30e3b73 fd8889f59b8fdd47277bea541ef26a7861a890898a15fa55f19df6eaac438054 dc0db4e6550ec7cd5ce876416f54c3bc59447b83c02415fae918adea6df7a4f1 29f5752cd58eb91887c95c38cd3691a9b404c99c5022e3e644947c58a62405a5 90d99d090249b1fb30482224f3c6d3dbc285c8a2f35a417a1a4559479a5af592 81c3b1b54dce4e4bea68f2cf57d5d10c6eaa396eb66880590a9d68409ee96e3e 8e78d814062170b9da0f2df53876e50d658e8abf5175be44f1a847b25456adc8 5c8e9a46ff66124cb418455a16ae3b78eded90d8d0e6b87f69e0d2dae684553b bd3bd4c32d490375d0652524597c89eb2a8dcda40278e9e17eaa0895fcf3cd63 37d269d95abc4010b6dbb4a1f13b0081701a625fb496a554ef50fa790503a0ae 069716673161003f4f4e03e91e61e4c35307be3285e9b9f4f96fc87d9256a112 3bf47bfecfcb4f13b54c8a5388623355fff92f4e991b1439ef4bd2c04c25abd6 8322ec655d08bd2297a67c7d218f22caa679139679f03a0bab4c0c07e74f5a59 4c7ffce48eeb64c719286644bd4dc84a6ca8a09976cec4365ed8a9f1e52020c3 1e66c12636713e73ad0661b537ec450f53bef1f34c814f53c780068c3cee944b 3606237da7504cdb79140ae14dac5e9970763a3c9f4a7d74a3721c93c7e1431f 1fa3ee9449761613dd39dd33e274e6d86709e83d747edc926b115659fab77121 14c7b97c2462aa3bec7a691242367004906e2b2daeed42dd2ea8c0aac75dbed4 70c011309fac84d7b2e71fa0702b49b21fbfd75204605c5bacc0c74dc5e8dc33 189ee51670246ce6697a111207191553afd5580f11cdf6859746993754e7ff80 1131c9a3307f39ca82c6232e5852e4461d0ef37afdecfa26b5022a93a7e5abff 9b130da9fae53bc05605bd8b9b7a015713699c5be1f02227a9c74da3db31a018 2ae654a588871677c065d03dd1d1d4232e1fb67b191a32573926c62d70ac7b34 a1a6f173a6aebf9df3f322eeb425a596e71bfbd8b75148232328b593059397b9 deb8c6156bb9b1cdaddcdcd83b0286e746c59d2888dbfefcf77e5fe1cfcd72e3 d007cf856dad279f734fb20b0e5c97839ac2ed18a607f8581b43fc5b0dd076c8 990073943718cc401ddb885dd082049c0168da46cb6568a56a4b287c9d959fa1 dd5c9a93ea17ec7174a091e41d91f3a03666ebd3411e5ea74938ca33b05dc162 c182c5d4f1d8be0d7a5f1b6ee8d126b397fc5d7fb52dd58b0f42f9b1d65e5d55 7adaeb0744f933f647464c92a39bf738067f6e1b4b996b4f2919289f2fa5ce9a f9adbfd726b517b55912e28c83f19d182b8df969ad4b12347131fbd7e0a8a2ee 0073fe5086e6319f79cb9243f359519f00da4d3be8855fa79f4233f8a50c5874 a6c4da072b6da74e25de82ee19976195b8483fa6a054856792d89b1e1f68ee44 d5f638f1b8eaea5e2da06bb90bdd5466830f036e6093df3bf23d03145d315529 1483358755a29f66d238dde5e62a125d50f6d22ce820553e207172859000a96c 72e77707ee4d52fd0ccfa34c57ed5d2339a69f39e6aa6f371080a3d414e25505 b7e9e15b52f4402ca9fe210563a213e1dba8bd02d0da57440a03a98980550a80 4b1480c24c531e5bee169e7ce570d89ecb0f0c7b3d041fd93f04abd1ca8bdae5 682b6bfc350ad26c92b229abbf92aa82a3d1c789f124c63c166555f4f960f592 94e2a267bcc92476200aa4d5fd0b3d6fca8f2c6a2c69623a22931b8e9242ea40 8d09501afab7b3142a44a531971cdefe348be311412347c0ed1ff2be5bae723f c6a8695fdc9043bf1a698ee3e2df46bc211ece66e0a5215bc16c8db3c676ae26 fece9504781b2b510ce438143395d3ce8f6ed69dd1179b9615680746b4260b56 7e43c14f5b5b2dbe7e3b37f9726c32a04244507d09cc1056084afbe29b97ea99 feff4768795d67539c95ebd9a89f8482775f595d8ef3852a988ab14fe95f5227 e88d342f5edbee919220c56ce616a548f801da5186ecf00a3fae3ce4eb163fe8 bf8e39152682f122fdf93ec892eda4246911194534a15293badb5e09e3c110a3 6654a6a6b4a0f3111b9c1bc051403c3d0a519a5721718e370190d833f63a8b88 a05d4624f0b50a2d8cbd071ad862012b3b01e98b69969f9e5d17b7660396eb4c 4bc3d8c6921685728332e49f6f4ceecb659504966c1d3bc49e57a79422c1e35e 3c497afa0fefe3026683a39fb701024d7ba204a2077ec0daf03d6bb1ba9ec005 3034c04416c57bedd19c75e57f79e9330bca3456c43418e5a6bf002d969b425c 5aab8831da8f0c192081f901a62c8768ea530c96a3b249aa9cd0cc83d404eaf6 ec54beb7e480aa22d6fd6f0c785e45c7f2a191bafdfab0bb07d5b48f092d9c5f 9839537dc7da3a8141b41c159b91c769d0cf2ba6e68b94217c602ebdbfc6a599 ed86db43e4a4868efa115d887acf04af9da75527a4fcd3c6244b6c4d61be22cb 8c507a0484046c536423e8d9af4e35f74ab7d30e0f3d41378b95da880febd57e ffd1a7b87836064b4247e77e6d4e88e944ab3aeea5c6e069161227e0d540482a 038230489f2a54958eba36e8609ead2529e3932f8b89c4204fc21ad19920adc1 ef2b4e6713f76a01478aa2d01d3caa45467de753c810df2f9b61caf0a526b699 abbdf138313206132f30d3c3376318e3c2a1754d95ea64e14b22e60d8dd8af54 5d3dae9e4dd24dff168fcbe2b21ff0313df82a1180b7d7aa0cd4aa1d9584bb5f 1df861a9b7b185f0eaff1c005d7c2bb89fed2ebe0f32f478d2f345bd678b49b5 829a61bcd2a3ad8a8d419c5c8b7fc26f2d13428fd97b7c54d6f888255640762e e6fe97cc23d26246af4db30b1860072a4841915bea8e575ddc5d7739a6b96954 7e5dde760460e9b910e216540728b4ccfd67182c070c6ec2afff9d1bcd0674c9 cce6c582a6b4d913727ed464544472bf199cabdd81769de5009814887650660d 170 ea82e4ba658f34410739c4febecc7c08078e0b62a6fc4597509894fa651a54089f3044db749f92a8ccff2aebd6063c91ec6a1f83de8e0808b177b70bd7035a08023fb3d69dc9940498d6cf2949daffd3171934aab529b7866f9628cc9b0eae04918e5dace8731a07508f66e4bcf9775bdef966ce4cd393c8fb71a25437d53209cd3b7521aeb7ad211a8c2daab389f2c263cf57999278d9b86e67eafb3c2623001c62aa6ba5e6d685bc8c579580fd3c6326ca0b267a5c53fb11eee3b7dd9cf5009106dfbb0e9388a1474258baa3344b41bf28d0deeeec9b643e974d92f6291b0bf6688b42199aaf9aa0897dd9e6a9d683e9d2601512cccd6fab39c4b93b275a0ce319c00e1a6ec063db3059312d7ffc149c24adaa59c42e590fcd332371fd4200da0011ac335c02ad7531056a58ace93ccc6479b5d6cdc838148c03bb01047e08da80a00977a41e2e139f6b8b899f8ac26fde88d7a84b6e5fd1e61833e4edf605d76b9c21006d29ace962274303672379e9a089bbede499f65b3e2d909273e40dbf3787444cc0eb17554d0fb392d57f437fea6a79042705eff3de784fbf60740e9b435b73a1d249eefd988647f3a165e859209183c36a58d60f4c1540329ad7078ae62561a9877795dde84995587a087653dfd767d2f176053bc4b373b62d7e0a054e93fb84d8066f0aa86c9ff4e31f4cce6835e3f95b3830a2b447610d36bd0354c98ee84bc7c352617822d9aff35fea5627c2231dd169672697981118cb3804afd33269e443c2ae2a8f1776c606028e4c6a04926d03b9661484f491f9a3b708908c658abeddb582b959c7eb022941f8e62e6cb7dcbd036bbc3f5ba8b7a2220054ecd2798166942946b837e1a7ca4f362a5b8aff3f183b155b571eca80880a0518b6340d2a77dced510845165cff01440f68397c53f61b409cb715b146714204c95c85a9c955a15df3565ab322eabb01632a4422b3fd83faef6ffdab3a2eb602098b926a0e0f70b838bb57d40f3b84012b1c0a5f8116b652da3d66c335d9cc0ebdb250bb55b877ad4e56a7b40b5907761f3485c0b56c6ae15892032165b14606fba3426836f8f3e7329379514584a6da97841f77efc48d86f9cd96c6e37beb0b1b22df1225abae4c98529c6e87a43a99bd5326c9aede7b1e664e0796e6ddad00e20c0a23a6d2fd0b257676bf7a56b7ed86b1b7b7bd36186742e538be5b809c0baf17056ead2c67b8da3a7cab6b508ff3ecd2b3b69ef7cae476e66369c76136065007b911a3e0993a156113ae5947962a5729d455e555f70546bd61821910a80f7081ddaf56841863c970ee7bd52429133eee999db65017867f5e5f2a3b7be3059f9835ee8ba1edf7578cc00cfed61278e8938809f685868acb94d6f919f1230ff5c34e89a25c04cdd64b892ae9a58bf75f5f9c6bb701b7d533a53207be0b930ef088241b033a967c4943d7338c71bafaf7bee5a0e58acb7d772b310ece706f0102bf10278c0171ea744e663b04accbafbc2328bf401aa1d5836408bddff5850dc3cab068a3059c4a68934df5aa446e3371829718357095570cac8d82e4132509850d421cbae0f0be02d919888c5e3cd32dcc1f4e883885c12d2ced8d740539071653045621f6f5fd88b7f41677ad932e4341899e6d5c0d390c769dff982b940278b2635d69f3f8bc4dea693058de53686bb6f7771d2f993cd0fd4eaf8520410231b66569fc70bc8a3b28de7e793e5dbae35a12d9c8b01fa484c4e5c2fbef4e0659eff7c948fa96fd9a3eaa8c89162916ae13c32654b6cd13c4d6cc1fb79cb70b5933434543f90e05cacd051abb6035344347334c254a1a940cf769b079a68901fa07b639ca3110f56c9f1ed5d6ab34bce27d9eb0fa5d5adb9d2b3d54424ba70a6f64b710ce76f4f515d23eddd937fdbdb4fdb35069bb2fc065df2f5a488f2f0f595ac58ba79ae6926bbd037dfc213c57a4693cfce1a22182ef5a703b07bcb80a93dfccd673acdf5deb9c266f775c9f726127bcacee35e0067f90749d994527093f89199b67b7aebd8c76cf68c769b64696d51fba4a8efdc7440df33de2214a05aaa1038d5608d57fe65af625528612fb46d52e3b64f47cd0e3d5211c8291d6057570ed14e632d34e0c67948e5fd9c97c7b582c70186e5bd1103b93357fbc2b08633f5581ae94ddea01f51b46b5ecb450aeae04e48e1c8bda8944143bec41260fa5bf3b24c9582632a60fc6d9921d64a69114ca1c5135cb55f94cf3c74a0fce0ccfa960df7e7f6a393fbd4b8ff87886b9f91d13385fa20a9df466d82b11ed54027004d239b763be04fd871018695af7701fc91562f89c485227638309b0d5750f0fce584bbb68d47dd659ab095e168bd524516ed76c99704d9b34a84962358a092f72f623fda9b89a414991030ffeabad1525ee40c5b651ef10f564405372840f5548955932df0305be158029800af45b36421743dff718a385b620efaa911f0697930d84096ebb3e0dd2fc60350e210532b7bde44d83746eb1be631c555d8e0ee4c37684906af04102cf63ac460938bfa90302f734f5b60c283a2f885ebb0e08ab5aeaafb2d33cd9ab3363094329674ccbccf7c36cec4e158a059d7c338f9703caf25c88f2bde6105fc530609f123955934a98b11faca11335b3bbe0705e8902175a8d746200450bc84f4d05b0308c9331d29d9be14caa5a2edc0878be424906e4194a94d7f8e14b692285c73da0fc5697782edcf85fe648d691ee6132cda8053464008153251c2efc5ad3c295930a1b6a33cd62def4da8b2aadfc88e69e4709b7afbc4ed1495cf3adcaf0333f22f11e6a59906605cb7bd5951461f7915c6d0d7d1710786973745ad7920568de3f1f266bd502ec31c9ca177d3159f921168306243b5363814c6b068dc7c96206aad242c6dd3dec185964be40d8ce7faf267d0566b3ea1f3017e5b12769483541b35d349d7908d16db98d39ac22a3b6b72ed1069cc1844ffbf2dc5fe2fc75e7f43a8447ffe1d08835d8a261303c246dd55b8102daa70651c81d4d31b2e2f9575aba18aea66b277d394a8d4c78c22863ea2c2a03d379ee502535345a68805668c7b99d3df69c74e5ba7959836646572c7705610f1ac3e2468e373deb7c134d1e979d5d2c05ce4be03987d264af8829068639490494cd984d7cbb6d24ccb5d900aca12928df14633acdec01bc4332a70ca195ae025f88a63240253cb37ba8864fb5194f898a32331714af54ff44cef61a500ffb0ea0aeac16c521cf92b344a13407e6dc3b266b5ee1610321b7de87ba4dcbded309eff15f61146ec007a1da5b07d28b0e32a81a76e800bf8c9771478c2a614a080b03d3daf34488df7510485a63d47e5d03c852817a924bbfa02582846fae6ac908e506581317266b3404885faa619b6e2907438b7e1cc388c56b30cbc44e93af031425c55f84316d1a4033eccc1f514ad544ac9e84b80e0fecb96f56af70a17a0d3d2c03f640d4856ee4410ba5a689c9ef97cac5ea9e91af40a786861fe61b81013b8b6b3fbe4906fcef61d38e6163238d141be7e80ae1d438c5b9f19fbd4543056b8aa7ff5e4f256a1cf1705ea41a100ca4ed369017ec71f3766c75d4bab01201806c87789ec0f1a8f9339da9699ad530cc3cd558d66f4fd3397fad7d91fc8c0c0fc8069473ecfc66ea6713698a9d9f21d55e09439eea1ede9d0b7b503c7b8703a242e0b0d14acf2e616272af6286de322d8aa06e49fbadbb16c1e245413fa40b19a25937b6768d5f6022fed900e125d27415454a6f0d3297af1ae58f41ead50a4309eab598976b5b4f31c4170dde86396f7519dad2841e059d0deabb311c1d07764988a77e1d51b54f79222fc0c6762b8066393faa7ed9af08de137dbeeb3d0c8cac5151a57655dc21e603eb32dbf32e586d7556d8795830e3cbc0712a693a01db7932a4ba68960814e94f11d0e66e6ec480a951e6f71eb728817d1ef9aed90cc1fe35ce64a578316ca373a229b783f88e7fe52605fbf02009f34935bca7410a7955037fabd3de7023342b430bc36b50a8ae68fbe346898bd685958aa8dfd50f160346c7d7ece3a09685051e8e59293933b64ea7f5c4656e17dd39df19b24303a3f8a001956f1c6bf2ebc9bfc6dcd14ba1b3cd78a3236bd317b5002d1189860902409a36b36c818b5e98cbfc324eb85d71bfebe59eb2cdf4defb40f197c2fc09085313f3d580a2b0b31fa62c8aead58bc2490ef88a1cbc6b8b344e3d2cf29006acdeec7ed75053b2a713b3ed4bde58e12290fd3bc49b44a9d196e89958e0d80836476e3de556445a6eba672f1ed2d41517f6e920b1797cd5b1e9075278db180bf8adbb24027fca68a5b9e536a22023ad09b1b3881e31cda17ae419ebc3d5a7019fd7211250fecf4af524771abbafaf813f8f8c479a763d1556bf3f1ec140a806c3e93c1194f8194ef338dc73c71288377d6fef28a6a2e02a01daac2a4c541e04eec3befe0b95e0078dc38c5605793dae820cd99446c19f5074e9d19222eaef069550de74671969287a8effd874089acf1f2184b01f0d08322e957b188090de01b26c09c842b0f2beed7c491a8e621ce897b13612ac2c6360d19758c79292b207e2d3556d75fd53719078ad3a112b49e86d80171e3cc97ce7fad27c16c65ff105c9515d4a4f17a1a1fc439b053cfb8cb2117f2847387cd26c719a912818c67e070bb80992dff1f4dd64e902508b7ff33fbf841d2427022fbf51dd4aaeaf3d6c0292a7c59e6a7bacefa10d5da2df89f79a443f840c7b661e142e996be43f5eed04ebd89587df6e2b917d45ac6d9f4d275ade6d0824e199b4e4cdfd76463648380c4638de95def2bcaf1cea53fd876e3698716ac20029adbed1f5905b400b31f40eccb6505e6000e12887f8ec10950e7d44178036da57d0a298527dda5257ba1402ac2d6676bd8ae155e4beafefff3fc7955edacd2f31d688d5e23c170dc08d300be162f3337fbdee3266b72b3dd9d0db781996176baa16524bf1cd90421bd6dd01ddc9ce76f6d0c9bd2918cdfa202ba49b18a815473263e1e2f6e23c54390c4601f4cc49762c2c3733abeecb4b0bf00f9e540e2aee6b45320a755e7ba68183480bba619c4bf6750650668678294da95c5a170a00827d62199a73884d2fff3ba6027586973b62f6c4a2bac364ddcf57e6c3c61968d6efd6933b1b81d3a1d93963093c4fc335fc0f0353713d4b1c8b25134c6f800f1b5628ea1361edbb7077819607619b2156b5e161426f7a3fc97531a655632071d843f573ce9aa2efd14e5d7102577a07c306685b0e2a3214f01c7d125270c167a3caba9f7dc0c6bd37512c67061318180f4b5e470c42ad4428f8460ef8d1399cd9e3a90a24c8b366465a8b7c0fa3d5dad8b7ee3a4b177d4400b3d84772c535d0b694762b6b47475e81dc91910e188f4c5cadd7fc51c217eb99c176aa78852f3c45c24c1efcb46ebf38fa53ab018dca8c99bcef24c46009c1694756c70e88750ab8813297ff55f1914f51b7690351d86402a2117ec62963ad602938c6f05db866f9667c9a4445cd86b1bd518c07f54fa73ac39967a88066092d369f2102584cc09683860a6713f3612b87e65f0238684a953f79167b78ebcbda155b8d6ae0e61b01a03a15ff2c966936e34efb079831ca0b7b9c92bfc8cbdb583245a8f6a6770acb465f6c35353d11d43de9ba0b0a45b1016cf76d0e6035b121a864e803939c85ea3ff7007c4b8c3c204da17b07d82b2c6b85d2cb097649b777d48d8bc32e67c88bbfb6998dc222e90a6d8f0500eb8ecc4de7adc6ffad76b2c864b714d5b30242fb8680c49ecbd97abf20e08d05d5c80d607e847c8b8f08119bb58d0aa1558a4c9f40256b9fc6a41f3e1f394e082fb8c740b095a5809348562218f8bd8409014d7f5ebfaf53840efb0138d4650bda7e9f0d768d70e4f133c9a9ddb1bea36e67df24d9de249bf058e53a151860091e3f98160840ec50174f45cc3d7ff2de1f38c22e5a9afad25db629a7066fb8035fa6938a8d0b07f9653f07517d9b9add7aef85de5bc7378c42d80cb517546c08fb77c47567ea0d6921a16307f1fcc67b2a022a04638d9de5c4b23f338a67680c372794dd0d2625802d623a53a228828139f126d1cc2db6fd1e13bd8d414c5109e99a096d4f91f2d84151f8b9d18f9213445fcb21a5016a530a8f61074c67d904a12b923aecff801afbacbc6f40d70df9fe568e182fd12e1122b9c87164509b0e86ed0c2fc1bf3865d44ecdb861e4564e34f95ae61117031d7054ea9d7cd1a90c949302dc61928379c496c3edabb7096aaf68996451c4c022ef143843156d6e0929f0fd47ae8e20e072f35e4c28b6e208686d7b45c0f45345b01b4f3421d0ee07037f56bc0446ace25fcc393aebbd984ab9b1a07a699a2ed18ab01aec144b930068383e648893ee195136515563b427a94d402ea6cb0b3a5c184e2c19945fe109927a7fe2b2e73fda2084d77b34e6972000eb161ba6ffd63f84af801b81f799091d9cc65d4307e2b1d307c70e4c72c38f6306505fcc66b8dbc6d176f9da92db0cf82b8f13050a1c60964bd38bd63391c7bfc58980c41438e75b17515dd338250018f039d0a1f317dbb3cffb1cc60f35986fcfb7e815b8ea93def314457b58f3087c0cfef3a6793527bcb11af4979557df291307cba7b423773e6484ffec83d908690fa62df2b0e24312004abfc2994eea1a65a4ead06018da44cb5faf5597ed0abfbf0ea5fe176070399c41fd7d72d4dfd8060d0027db4743a4f9cdd5e445320d60679d56bfcd0a2bbcf4bbdbb25a97f1ba3f858476dae8ca56e89a7f3dabff0151fa98c7731e3f7124251ee86b61fa24c883bbe593ebc1dedb906a612bbd810ae90b978ff0083f1ac026f7c0dd9bcce74637bf3ab2a34367964aa0ec2e9cb603f5dcd16b3b4031af45fd01be83037ee6f213c8cdb9ebffa986b190f571886f03bcc5f533ed810015d84603e0f33a13d5f759d34875429539c75548a6e2c2740eeb790e35a90f4d4192c7a3ed18dfbbad5112b54817ce3deb05f622f683c70a08386b384674f84588abe318d7031bff03e8c6f7908397d06c15f863b42de3270d38486faa9549bf55ab14d6b9c1249f1ded1b0a02eeec5046c45fcaead486ea07387ed579309ee7baa2611d2a659a42de78164b008ca2652d86073080dd4ce7021c11c666fe1649d4234952e7d30a9eeb280c4e878ae2cfaf5d226bc9bce0b9098e26aaec993bad328f8db4b24a0a77447604d623a67927e186236b0cd2c1f10f7f28d1ed128dca96f6575846bf1435fa0f1d6cbca9ecf0eac2288b540ff26c01d3cc88fcd1ba73cc5f43d9de3abe308cffd736c1935acc62ff7da34610c2f9002c509d32eff88e593cc663d94b1b0504a00a9578573ce1617794994c32213b0601e782d5da1a630c3f79c54d1e9360fda61b0af5db28ee79b2170639d67d2a0ba3bd4fbcd14875353faab2a1b8c251563220c066f386e6c56477378044f58e0275e4cfe864d6eef19f34b7da898806430d461fe6df89448ec9dbd7c8b8837f09b72f4fe32f0afb9eeae48f411752e140f0f27f37856a27d2791642afa96d0a064a18017d1c2f751e92515431bc0972eafeaf4a785a728c557ca711d3958cf50aa4bc5c088f738d05bf2d3d874f8fec8f0b08709386792c6df3ba6c90deae5a076205f194ed9c89757694fb62abfcbf49199169d29dee298053c066e3b04c6a05e5cfee89cd749cdf860bdcdbca95d2cb9560aa0a7f877ad40ecad7a098944a006989be2f14582077764c54991119a2c8fc026de98da44a04af8630aafe28f3041730337a2f9b2854f58493ea965a713453ab56a5d6cec461fa3e5673a9ed6903fe6c77c2449257b2c2a4e6fa5bbdf0cfa7f2e3cec0626471aa2fa00c842bc60d0365a1b1515fe36a53026a9ac6da01c508c50196bf6869eca5f3d2fd4328f308aa21b3d4e736dac9827ecc5eafc34df0d5d56ce1774916c44b5ef5e6eefa7b012479b8762877f381b556b9d22dff3fb16013e573d957b6bee4347e11f8cd340d7384c733ac852a6c41eb5d6bb314d0d5cb0a9b03903a734008e31f73d6532e008bfcd392595df1c73e49642e11be863227a941788b115ca7155d1783f2d44606a6d78fe1a7380b4f0307e392726a5ae2f34a57066e8a21a63d4ac0fddaee53031c6f98afe310e0b79afd64b01dfe669bf8c2a932b3c4db36f760a459b101a805ab6ffc9a717bd8613ce14d0b17ae78ab119403a154c9c79c26618f60f73e730d99305da08c4038adc745f7f4d2fbeeba4736a7c7c9f170f1cf9d31e8cb16db0acadb13ff9c9a373572a45b05551a3a18cfeeb365f77f0709fd95a39e144b4a055d5b0a207bb93994acb3deb6b1b8132508c3dec36e04d30a029291a7a9a47b0872b5108073c140cb4f3d69ef34096558671e9d312b6f769c9c022e76bba119069fa4fb636bad85f73b1988091c2444ad31e69a15d1779a9b13d661513537de02a10c1529992ece48dd9ee96a20d80006397a61fe6753af5b904c39cd5b3a850fdfafe46902859eebf2719e0498605590752c66f08b575ceeac2d3cd3baa35100b5ecb868b30adf6188049e0acf553779599804427e74cfa6451b782d420db50696e441326d39d3b3b52ddaeba5bd499eec4e7ed35174e87a87b66316ac06750416a43dd86fa575200b1ce704926ab53da40ae77c63dc87200bb8ab2a90ac8709f9aa861f8bac52bd77f8795753dac43e5030cb4d9575f694e87b9ee0179ebb002c2f4172e893c267fc11645ee3cca1d138494a7b87be31509782f2f9e1e05f056e47b72b06ad3d33eba0b7e37e8ae875d5babad59825de9d478673cadce8f704e1724fe0c47ec64a6f1c255babff74d212a95f261ef4a86febe1e22cd8ed6b071742ae32c3b2c15d1a4f4be8f452977c2c7290c64e4e9e59feda172071c30e06927b87a8f077181a78e088ff18a1b1564e65deb3042c88aab6b4752eaffd9b0298da07fbe75c5b3f64d6c8b0850064f7e7634cd0c3b74be6ca4c58d2cb5d8e006d317d4ea6d908229d00b5c2287bd9425ff34d73ba37fc3fd5907e559886770ddd93a9bdf3406fdfa139df1a5e8615db82ccbc53718d5b5f95dd8e906386b50bc09c03eaaed033b2fa78455282c83bc7e351c1d79a83ea148c1a3a43ab9dc30c53e3c83d8d877b677967b7e66f05b1d52bd31da93b789645d8d575461ab22f087d0aaa449fa2feda216185ddfe77bd3e4c9bf497527872830ac737ad0ba9bc08d3076440f4bf138b9484ad88368272005dc697228a9d1ebe5e4327dd2d5d2000d73c52abd3ec4989357ef79b1ee995ac39f6a3cd5437cb31983d39ee4328a00eafd708a321fadab321472844b13e8182a55faeb4f628c47bd6c90c959d43f8003e8f28ca6e18cdcf7fb0ab397071c3cedcc607cb8b56066210fa9fc96702110c565eb058e4311604640f15fcdeae2231dfe90dc8ae089895f2943b902625c7051a59db64358d791a3ecb47b4a7077398d315266e9c77688222df9c6c97d9b003a168a0f5221ba3fa362dd07e015c108ca61de0fae55a7b1d197e336f0d6e740fe3ab219d13d478cfb9eb8a21c2ffde8851f1f9f49fe63bb47dab567ce7e30f0ca82acce07a50099f904e4c2d5dbd3efa5d8242a010d84d8e85f1b758f186820f3632d051654478bf5f107a90eac5122cc0c77b01eccbf54cb4868b7ef78dfa0c2661f6372c71cdc8f878035268f8d1cfb4831cdc2b24fc6a3f3fbd2a0d30230328f434088d51533f3bee58b1a777100555ad68b42cb64e4b901f99c020f96601de78bc69c2e6304bec0794cbf8578fc6bbcb2fe899355943b251a27296907208008497cb97f2886021609adc12442689fd770dff2034ce32d992abd5319c090b8fe62771b4f0f40f338e8b9c911bab369c7a7cf853ffa242438b9467011eee09d568706749cfd61211500ae8ca593809aa02336db24bb1fe3fdec111608cb90c9ad0c802934b83de3c628674121199674464a90578eab26005ec51cafbf3990bcdf1e6f9840161fffb8cbe2c2fa34801ce7740e6c2666071103bb82b58ebb805f2d9e7b782f7382a7f9b976737220f8990e6076a1109d08d0bef610709918803b795c4b159f2d74d67219f03e61d148e16d8fce8972ce588b6f22dcc57a85d007d07a76b7f6ba929570ab067b89d58c285fc5e9e9233305178a2412f6fb1bb0d9d95ba369fcc75e9a4b70aacd44de01e87518f5cb960ed55375d192ad27f2f0faec8b8dfa0b15de459ea61357a22a4fb13b3167d06db99e0bba66621cf84390a27cac81c8f93ce9a2684ef8fe6b170c93fef9ac11a4af074132406df027e060de58dbcd39f18473ebec4a3393e34f297eb606b587e37bdd7463ec4d173bb5907c03dc919ee453c71772fb7420e1d392091cde9a37f445ebe482ce9fe8da89008a8dd9300f2c041e8e05c9d7de844ce06542936d3625d47444a4eb9b0f0b61706cb539eed9c93e90caf7ca70bd9ef30f8b46b342a286c358ddc4e35069b473c0b5be0be97ac44d7f96af292d0c46eb76bdae7c8f171078f7d724e5da56b0a0b01bddc6b6af7e1a314a5129593f916e4eb5a17d61131cf3f4b42a4870e2c856c07145d3c065bca131e4c2655f415b9a5567851145fff7f66c010c77a0417513f05ed3373e6a09e735999ca2e7ebdcc2b18a1ba9cca0fa9b3dfa4bf9f234e50240bcc5969fe08085cacdda15a1285283f800323889a3413f9278348041228aa5a022449c23cc347b2014330f46b983bbc4794f7090ecb28f31a7a44a017d3e4c803d4dde349b0c38cad74627dde575ddd03dc7c99c5cd05b2ef0be90c10dde1180a8e86b63556d5e835db8159fef524cb185313cada56cf45aec57623fef76316051858968767f813b7ffb7b947ffe6f50f897bfb792bcd9312c1ae447012b9490e6b751e1ad0aa8b3489ca2f70f606acb0cc1472a466c6adba7ae5a60a9a8fc0049eb53a6169bb998a13278f4a2e7ec1d8440f17574cfee884ad6d92635f4834082ba6ea8980de0868ee97317e3c6219f76e88ad2cdee30c59150d41830cbb8d0cd2fc3014c744bc8167be03cf94fb007d8e4571a3c4c0373a080348d6c03cd105c7e56b1565d46fac84292708e3d8df455226d0932c508bb0052e356057e48d05e01ac1a8f0e8ca56972807e88f50df601c043e77521299426500d2c62addd5012e23b3a32485e6748e61124b01897b1ef8e02496fb7b0a27b62e8885b4906e0fd8510c8f9811825dbdab47c9934b49dadcc52d87f0e485af5222c6b1a8ba5904a1bdc8d6d3b0d68f1047c290c3fcf4e6bde3fdf238284d66940b86b9f6842009963a0bb126a22a1fb050292aa8382279f7c6fe381933596839324284bb9ba50b19d13535fcd4380ad7dfd5850f876f56bf2147fff15b7d70e06aecefd8fddd0ef1a5e985c4ba9f41749209e705e1f2a31dc392ed4ec7d058165aafa5ac33d70aa36bab7ef7c388024aec4d6d8c5b3e08e6200a59e13b835b6667f379986f230740aac74ae49e3a4d0b9c8f84af043a1edbc5717b907098c870d5863760d2200938a5bf7df814a745ba5f712d9a48d3ee092b6c26602356a889c3e781e6385604973772884df951b47a0d5f0ce1bc427dd13abdee9d1689b07c0f7c90117e510ea3b3ff29e08a93b22ce332f59007db999d35b30da16b71a4ec08a87a80d63f075a47d380a8a135abfd11dd86dcabf94885c4d48bd8ba2d8209bfa1ed9283c501de35214a1a7e498d003fddd25010e1521521f8a9f85333d6b2964d1522026304308d3d59b0ea32194930a325b0b95a621c75b4c7aad6e849472290decaf47a0f1a1563f8fd732b771eb8fea64a0bbf06eae14000d1f9604824046a5366d2bb08b8f517d5b54352eee63a7c5be168b7b0e331a497469b15219dcbc098e35b2000069f258c8668c2636bae42435d2a6d30a53b771e1a71a555329524ec0922ec0a461e36906d8ac66a9d0845b29e86e97ce369d1d46d657d20d0ba253117a9700ba8b8e48a606aea466cc63c0cc5ef934e5af0632a37a1893c05abb787b19e3300d078350d0c68dd41ab34c07af29473647db4ef20c27026a86be8553c62dae809eaff1ad84c7cbdf2c6203cc90685a8507adabb27f64b368d10fe7069f962af04977547d385fe8ca54dd0d2c2969464bfa45d7e859c57b8f195978f430933c50d7cda0935feb7dbe8992e9871479af819492112c6cabf0831db8cd7ff9f54720e7f5da5036e07c2019558817b8603b4c4b8f75c08d2a6d011f43d6ac27ad83605a7c8206d23811191c283690498172dad0b21a8b45ef12c06e29318013aa0d40c2a16ade5ba3f04deca705a58d79e87b9bde8ee1b3b8c1aba716f23c8b5d9b80547e6bcfb763df7ea03286aabcfba25edca236acf954c73d92cf3e93af5f537063d39224cbe7675a0ac7b3b705d1a340226ac43abd1435a1045fbdb40330bc80c7cc83801510157fb53cc9ff5013cf1f408b5f815041274d6165a538a59a03908244002b713c10bb308e47bd14ede806c8cbc82bd668d024de0ef85ad247c4d0fde988bc4d59a9254ecd0a8d6cde887f7f3e832aa7bf911183ab8c82f70c21500f5f59b7a6f5900d3753f849b6289501236e2e8a73765cade626ed7b91c6d210a73640f612123a01f4e8dbdfe8a013376e3096c3382bb6767887b35d515d8ff0c3d1719ce14cb924af6b4ecccb076c679045f7e8cad08287d7e15aeeb68dfbe096a14dfbc1e4e9b8937773c88264ed04803a4b2374c6cb688b17bb367a3b22900ae8039d0fd667ce2f87e722a76d42b33e3af454ec79a8502f83ec5d628f7c80a2c0d197c739b192bad58f6d51cee3d231172462fbaf2bec8380568d04b46ed098b0f64ae0c65db3a6eb669d975b5af2205932e9c90ffa572e41087d2712c430b7b511ad2f3f65feced24fa0058e8741ea2739c9f6bec0ec60c87d58dca0b510a6feedd0ecdcf9e5e9965b467e4444ee744875e989c5d0898370939b9095391084248a2dd3a1702e8ada9bfbd460fab92822ba94e7537a1fd3b6503f051476a0db0e4cb7119d6b16059df4c8407510840fa07f320461881f831bbc28c52fbbc097f33cf11a214857dfd574745e3d4d38ffe77bb0e5ba063c2edc40ba8c5721b003d9a5f67ad09adc4352f3ba6e8d88ad97584035f632db9c49584801f5dd85b0180fbc7bc477d1d60e86676f6b01752305b233bd9ad7b0e76f58353826a481906d909b232652897c683d390f64bb124a59d3048d817b72ca11480770ff79553081f427bf781dbde2f276b280035e67f9abd0a8a68badd4bc7863052c4c115b201d331b21c91795c3490803e61618c67dcf8a7e7bd3c4a49b71ed480c3eceba1030bdb168ca1d26ab967cd029006e64a799bd9921beb00bc8a44f5f9e7baa2d40d1082ede87f5ab758107dea2fcfad9c0741ea5558d9ef1135ecce8fcfb01b240cc6bb0810ed22c097de84354df1645876a73a7653d4360424defa369ff6b2570050b3ae1f16f4d92974e8f6164bead83891df791826a7edf605ee91290cc2e8080fc3923e16541612485405a0f04e16c360e114059fe0b1a9a2ee37fb6dfeb3087746679dde11e49a663e4f2672dc2d6e0b71b588ea1702a94476f0b3a497cf086851c738ff397d00712f126844cf1f96bcf6258d76383f19b4118d7175769e0706b810a573f7f324e04d6d900a9e61a8988900699459c09053b07cc0753d39045c1e03d8ffdeecbd9ab3f20a25bc0e0e26385f8ce9a245859b35a3deeb055a0bf44a5dec70c627beadcec4671c3db85b5068131884c5ad81d98d5a560cdcf503a6433f6f6f1cdd4b8afc95209d08b2cedaa0178fa02b93cc1c9517ff00e9970d7809a95abbda9d065e9af67822b94de4be4e89cb3449fa068cc4e03b9e5ba10372e2a01bdf54cc87aa108343b6c333c7d11bb682c977454febb4bf7ec57cd90a68c0041fd3b271ca5cbb474b71767fd603816570c6520e2f9e714595a22e730b56c3a55158cac51fe8865f9b7a70723124a20f7517ca236f1e3f68c6abc8ab02bd681ec97c68663f62c68733c44654c98fbab22d1e45334035954b0cdf05b505004a4162899fcc06f3070235e8edf4192c581046e19c7087047b1829c3425c0fd3a16d8760d15a4fea7ecaea1f6eba43ec054af18ba848f76c9fd52be591f30b322627d555f7a4987ed128c318943d16abf2fa47cc6de262397e189570318d0aa3ac54afc4c09b4ce0db6c87284d16f15b18347abf8160d7b5d383dfbc182e08e8d6cf08eddc7fab9554ba0357326db4095bced4732282cda21407ed6eb39e0cbcc9deae090f632b47b81bdf4e947dd16e6a826da60e7c8976566da79bcda00b0b1805148c5e44422a6ae5e04746ff500b72f1210b2f379765704195dd6b8d06facd1964f05afa6d92bd65e0ac7f55b0a23ea64bf900f48b18b6d7b5d062a00a2910eb7dae2f8fc88596a3f585f1f3238b030278a77391de9c55ba858182e2064f493aad8baf78a6c1797c0425a2a9e7b31fd055e1e36e50ee19b1cc86b7e1014a87120e074b5d4b556aec3cc1e2372edb2dd0f93b94b941924c7bad46af780b24329b1dfaa5773f5a512b855e6d4882c4bb4954a0a99f8c5258445202a729067e5c88daf1367ad23e6a5d621d77571ef37054eb29a1fc763530da23750aba0ef98c4b91de987d756f47f4c58b532966a001b9e2544b8889b82dedb5b2a8070ab31ffbf3be38d6b387b378771d79832c7a9919b5c7222ee9c54e56c4a9e91f0e17f6b161676f19c0f2d4ead33b9de2c02d19d032f22d27b614addd30e10ccb07301ba09e07a8b9ec318557791ba3fb99a326345c44dc8eef0181c157c2365a07286fb992fd85e103a76a83d4004c611b21a8369967f106b156530b4f0e0e680992243ea896649a8db6d843bfc615eb7f22d8d1e391f9dd6372b5c234a1710302dc7be655c72ec5baaf1ef7f9aed62f90c264c7edd740e379ae2f8a8cc27b3708165de70dfb304e59b48078ac23453e0950c853230fad4c21332adf6188226a0ea635e5d190d2a8f6f2a35ac3b6a94ee3c418b8df2458e8a305750c439c187a03962d02698708fdbd5335b94ba1fba7e676f5bf77fbc563b0b49bc880dec1490fd4eefbcdd476316728e71ab2f7da533adabfdbd073d8c8766c23147c3a107403e52d144ae5ed4ee6048a8171be14d1d13af34ca1f3c90583f468d8ec6540bf0b022be81957614cf3ece7dbb69a5c435836379e4a480d73a491fee7ee0297450c313237999166df052b995f9f0fa7efd1d803b6c05225fc1ae894c4b46605fa0cc3c22f925c2a7977d2b6ea1d89c34aabf2a4f1c20503c974421e6f182e362e04d8f5f85fedeff501deeb8f99d863e640811a99f3c80724561f58950cb432b9069e271082b1f33910b4f148882a83176da4fc862b03c91b9d9ee885c2495a17085ebfeba5959dad04fa9c8975fcd80338e4b387bb3dbf78f8e2d3bab98229d40fecd8049fa13b8d946c71b308d2401d95cc7ff23e94b1a82bd152692d64c014096bc8f3f157a01ed7ffc5f9e6e8e701a7f60f7fd19f4b92f7474dea18b474140cf8844b51d3a0f572b82088e41cc7d47e2668dc23db7b85ca8d8364ce7b65f20214ff226387ac618a345ecc95b0a88b14b1c9b1ae1759c2633128bf0a3cb3fe0dad463f4664dd4dc9c03c0c389427fb598a1b440ebccbcdd2b7e89c0ddf0338040f16159de1924ab8877a6d95c8173a278beb7cdec33c26e084785b4215afbc0624fbe9bc92f7d716a4b98c1c7a3c9e28f2c5385490f3959cd23f63b4375eb7078435e064d9ff5f27b09e1ce17d02741bb5098def2d2d3db4311317f9cbc99403e0ea0f5d395de36baf1b1ddeb56100812e4354dfefb8a09f7f48bdca5bf22a04bb4926dc4c3caad3bfc4da5bf62907cd3e0004e3cc8cb6e8d9846af8a0985b0f2bcbe26a35445426c79bc35c796b3c6fb4ca76b9d3f455d4e6816ec13a344006d5b7e952a0c9c940596280609205f77ed9c15bab5dc5d8d0b88e3408cfb96f05b372415201d78d85a4b3501c742f22f712af44f2c89fdd1c81356a3532567506ee4b2c5752cbbb0c9935f872f4fcfc17d313efed0844902200e50a5a14a3d403c27eb43dec67b5818fd28ef0eeaa5fc40f33fdaf0a444dd612402d79ae52070cdb296c1b75cac20fd1ce1e73d0f99801c5824f3e0bdb48e4064878eea42dc20ae481f821910acbba3f17f212a611ed765295810c69b56bad736b11f7a1de7c0a4025f3088ec49ee57bdafb549b9724ddcfff01716fe155424fda1c76a18d180170cb99ef30338b10170e1bcc757885df008769aee7285e567b7de24788d85c04ff49ce862e929205c2bba38dfe97c1fc3ae3653e55973a048a01150a4c94fe0777883db93969f9224488e100966e3c407dad2a5254245319e830c7c2eb3e9f085acec121b2dd5ec4e157e0b79504eea5d9f9d2d6c92640c08e4100c2338f650e051776113af50a15928571f7e41ea7fd648947947d51b0634686316272af69029dec60afda07ce978ee1dfc65eded7979065a3672e1782ef28f183ca3102730f868b749d37f86de5e46c321ca20c7a203aa482741ef19bdce61df3c6cf6c89021b1d9369b2d4268bdbf0571a13d5225ea2dcf7936fe22e2e00fd00f005b2c20522cf0013790df6781f2f22cceac0559134f8fcdc4dd58ec25158416eba21750c913190ad6a90cbe6be3918cd13c919f9cf98ad89bd9a19dc5883bc23be838e088963da6ca14012fa74e3ee7dd406ab9fc09cf0efeba819b0b8f98355b35209064a21a1549a11cbc2e6f37caf69fef5fd42cf5195e7f9c9b0a2463096a356370b67fc61e307d6414ae2b20e5fe3aefc0ff65d6f4664916899278dc628e0380b034b45321613e620db6a75a811adc81ef79dc230f6c4242cb163f497d560d799039a92e52ee101884d6babb8cdfd033a46056174c4ff3b2faf4adc1bf07406db0193b2959776e1c3a7608f62ad9d4dae764390a9bb703ca661faa7742621db33054aee8a2039edd648ac74fb71454f6adc79ed4f69531c56d078c76c90836a9b08569377cdde7c7dbe1471fe1a4629031e53e6bce924b4985823dc89e962ae9a013a101e37e9f36b2bb267ed6bd88c7dc5336b8681e21075fb50f0357c8e063f0eedd46706205aa375571c00f39879570db3615eed51fa45809262206e02b0f9023280f450ae383c904825b3a556d973a0a267604b0e72e5a67db849d5a4fcfc0d8bceaa04927476003bf5a05df280d926bdf3abdbe652b2fb9d2a876041df6e018c8d96b038eba0feaf802ebf99c19cd12a90ca479b2ffd40a4b7b0e573a35e069ad3da0020f171003dab365c268182eec954301206bb67eb87260f2d28872703498ead8f0bf43d75ba473d296402c6d916df49082fdcbc99a3890336a01c41000f519521b0d75036523ebeb79dc7b279737f9dae384e3f106c757d68f0629d0a9a5b3cc60e419cc4104b17ebeae2df82a4dddf58643c1ff9bf38fefce8d3e80fbe1376955cf928fd954b03071f93ae1c22fdc2f7dcd99efa191aef2d17885c0c1f3f682ec81eb15fe1911439f5bbc29c4d76fc48c4dd841f121154adf2e0e1089ebc07ad453cbf13b67af52e098bf67e9906fd61e4209e6171fd6c32dc20eb0e29ae16d0a12f5ce48c9cdde55a78ce1e101a7be97bee2c05167c03f8f79f46073b9d7381fbdcbe3c3187bf4febb2bae7de420ecc193aab1ce77f303a08a5bc07cc18ba74606c05adce43fb4564238758569651de4820cf5a9d61022ccc3f260786ff9debf7b52f3817f76aea519bdcf8d1d2171f4bdfddcbbc87563ce42ba606d490eafbd0eb73af9e2e46dd1ab768d687220cfe70b0a5fd2dd397b3acb73f0153dbe436142adc8b20f0a7fef52571b6e2a724000621d550a2325b87c4e4d703f12c2ea561798d102bd77a720305956a59fd19c7a01ffd1b46c0ec314e674c0156b9f5125a838f4dbd55e29b46ee421bef326155b061209feb1409b44776f40182ddfd1a1bb8ce600741c871a5015298ce23978702f07b5064a1b324a917f304f0f03f051bca246b6d3465368cb19caffcba95646a82e169cd25adeff8493c0f57794ca31d17c6bf2116b9999f1a205c2ac5cc818e74f228852e5c0ffca6d407d665837997a50e8bf39ad9d1aa9a122ae3e8b3df3a96f8cc4f2d5aee62e1ed098deff6123fe0234b755fb9ea3d6f7501972a80ecd5f5c9c59b84bbcd5b078e034763e53e6c2455be9145e5f5e7ae6a1779bc07d988936dd6ddf549ccaa15b80eadc33e1afd1582d8d13e301e55e77a04bac08cc3b6f1489b57e76165d99e7c006e54902507b846db97e4e1a374e80a016e3c0f2eb31f6d831c52591cc6ccb202fcf043f325e61ee50d656a47d2447921ab1069edcda80d3e82549975099b0e0200a8f0e7f4afb4087ef95cecc2deded038b8aff3c4147b9a1c04bdf39ebc8f00d34dc9072bf5f2d77cdfa3347b00b13d56edf25d5cf62e956a04ecf1e65f8a089eab496c191ea906bc608d351b22bcf28c9a2133595e76828765c8d7961b6f0b7b61d770f58c57e8f7d36a00f3306e986f3fc2bd3fba35dc798c111dbc2e6b007dce9e9ec63e2835096580e1f91297a7e626c49d4cc3d642eb08b1e230866905d51bcde350a91efc4ca6d54bbe0ba7f55177cf9798a537f24f0e80e0d51bd80d53b5215eeb7be7587847c0ba7c9bc73f06c029c0cb660bdac0b153ee5862940e2edbfada8fcc4ef04b3bc3153a81d5f8568b291d17ed0463985eb0889279cf0db29777ef278929ea327b5aa1728719876b0732e25b735b09fb78d76326e8690ea316bbd5dae90f6e69fd549e66f05434334b682e0cc8d147fbacd25b2a7f480adf76b97d34e5947b88726afc5c40a8ff0ce0559a9be52a23d2a607094f86b80676f21c05f7f9b3889ac4bccf8c780b51874ccc39fbbce7bc4b2083cc1ac1480c2fef8fc480f423be32e217c2061343396a95b63ab4d6a8b947eedb094bb7120c6118018eaa626fec20c8525da789fd50f427dfc3dcc246b77f1fc944dc518100 -generate_ring_signature 68d6b1b9d874d51227c9f0a28cda04d8172e7cae79e06b58aca4cb5fdabf36c0 3438eed5f743a6715d57581bf005efe4fc4cce9447e6d296bd602250d8c16fa2 32 97f5294c86120cfa379c931f3616ae5853e5650dccf93877dd3d22a949deae47 20456187ac5551528a6c1e1e6e6ae511a8835a1e17c2d8376fb0d3d68f8ff749 0b8117871c4b8a996719c93ec132408c440b9f0a73d36ce619e4ea5099f46f3d b258d44bd5ecceec9ea3b4fc8e95496d997234a63c7b6e5128b39bbefbbc4bed 7c68933b4898deb06963efe87110b3a446466a13b18660dd8f550622629d0c0c c2a30c8b5167c28eb95b91920dc363bb6f933bcd64986c3434ed89fc077536ee 3c98ea89ace2a89cee7bc6e06f63cf5ba9297273b9044d4c6ae81b9e411bb440 cfbad8a65a06a22fe90f2bc11ffc003601392504fb1b3f85177f769e22481b8d 8085897e5683d6b33672d6e2e7532337eaf1a6c47d6eab0832460f5460f9f495 a4545f4596f607250e5de364cc2e0e070e37d1c330a6ac6eabb3d03af415209a 9febfeb7e7bbcfc9ed9d663b81671638f03555fdbad469150cb649f765d60d6b b7240cef5233c3eaf7ea031d7ed769d65a7362c90448afe2fb5fba997ceb6d45 0343b7459f99c7ac11c3d9f829f5615c5bc60e35569dfd97b78e6ae2e00f5d8b da9d89d8f350d85ce47516472c0e73dbe1114aa92de1e847d7c6a1903651671e 3bc5140c5ca0e3df7a69f91bdb268dcfa28550c35d64da809ba9940c03dc842c 85eb184236053a9e30b23e189e446a46c11be28359c0b4f70fa696e88a425b39 d08857473602cf81bbc7b1b17766fc09a7fd97c3994f8bc4de94c6aee03f3e99 7edfc9671443ccc734800a1479d6e7840689872b8652be4e97c9ea7aa9971e3f fe172c59587584facc28059d30713ecbdb2f38d75e967899cce7043592ad3e02 d073e626d083698553eb8c7d60e5a526e06f9e288f2c0216cc71535b443a3528 6621abc1d1d77e0e65d363b1dbea5a4651a810fead6d57fb116791f83824d668 fdffaf67600740168caec34bfd37b0fbb16275b155de1eb1bd7b39f1150d0c88 dfddcde4c8ac2861c78bc7df7cf627f7bf8d115c825a10d470ee665ab72bbb22 4d93013a13fb22587ebfdb63e9d8ccb1f7c04bd51c199346461fcf3314094887 f008c557a5edfa69389b32f0da30d88b2e6b91a4e37600c14772ffd578a67930 d1ee1579b8fe43e9faf76280b8c012985465491c20bfbc29d9b2f2e69083e16c 5056cb0d29f7e3fff91d6f9ddacb545f2266163f049ae76407df41c25101658f 80b56590de9d2826db4bc73ca7f18407fd0e5c5c03dd9841c9ded9b8dafbbea6 62571c909782c70567e9968ded1c05a4226a3e04a07ae9db48e0153a56b2a468 fa3243902d44e63e78a23d70a6706efb6e453d3ed42d087cabc7655fb83ca3e4 976c32ea460a47aa3596d836d70bb40a84e6f3d9ff1e2e01a516cfeec938a2f1 04d573623956db0dd22344c139dc7170d8ddf6296ccf558cc2bacf230485aa05 041c83987a208dcb9b7658b567e4baa29c0fd278a85a7ed885d26e4356250908 11 192c8007d03ce9c87ca63deabedc7e06dce9dfeb418fdc73e07662528829a40102cc1c120e9468234ec81ffa53d8c68330be6332a9805cdcd0429390cb303d0ac85cc6abbbdd73d3e1d0913a29c205e769b0da64f0a3d0f3e65c9b31d741090f99c23a484d3452207fe3309a6384db4454cccc9e9820dc03204b4b7e09f28f09ae7a76427627d23d4c308c243284b8277116cf656a6d69f79270238ce318d204caeaf4842ab1b2983a117763fa56cad0156678256a8890686da86d8a94360707648a9468b1c5c32675ba598f6e00f5af06fba34cc65434f884dc935acb3c100a3812ec0dfec3816b2f489d8815c59f37636130e4dc68c8ca4399d479dffa1f06ac3b16dac1b2ffceed29c58763697aed9fa9efda4176f18a7d3d571e3d2eaf0e4647e6c8d29daa1de4c1ed633401e4445e5ade6e293ff678049da2b4213e5807e4d337d7f86659197efe7d7d7c7142d102a186fe7821e4f409e839136c20cb0fe4490c8597959f324cb18c4ff3a0ba84dd5040f5097a218eeaa452410962c90a58a20e7eb44dd3859961dc35fbec539891907bd7d399ad145dcc5997a2d0cd0eedefe61b426468a6c0f6157b7aaa2a1f6d3ca1d065a8fe9e8fa784fa723eaf075fa3a5382f4022643c755b2394e3906336997e7889384ab97efb6a4eeb17320457797b825c187076a1f2f0ab0d26b92ec99041efe94de8284d57da2b03afb70d1277c95989150936f48f4574bdb97733d816a1b9f93be80f9a22749c0551eb0806e336b2f70f1a7ee42980d3f1f18779734fade9545ed72c5604f79596719507ab555fcd213f6e7b340a0af18ece2040f757e452293f5f3060ff513139e52a050eaf85a5a8e4b062a0bd62ad0cdf3aa797e9498cbb3d99b3763aacd85caddf0b7823f65051f03e7f08fe69eb79a1c6138a5ff0deab2f30fc4db152fd2064e0048203e7cd3701664d112c2550174e0d55cbf7e63be9501f86356e0c55dd3a0201a1df11a40d0f94e9cb82e2ee5272da83d55423d755be9330fb903be6de1dff01938b1a852c033978e704cd2e64271a9e96e0756a6655699ab71fe66a2ae5d507083a1abdaf2f092628c27cc8788c5768058d019f8e3a92ef526d06966c7e720f490aefac705994e51c7165dcb78bc68172856869603e4807241c446967f05b09e1870731faf6dfe3473e490581ed18df25dabb4e0c56a95f9ca75582ebbb670604dceaaca2f5ece824061f567648b9771abafc155745a2e18eae96324f5d390135da99bccc159140fcfa7456717bb40411a0ba1692c8b1fd77d0f4833e83a5043327474ee9fcab8e2d1db3236930a802e6f776b511e712c164d23767281b4108b750c3caa8f8da5058cb55e2ecfe348bb3664d24eca47b5eda3d656630f66f0ade294f9e140e2d0141648033f37a354322c5db452149a9b0f2210c77158b72020f28b12c43ba796ea82d55a52743e2486a649a39bd3bee12620c4fa04ac6900e4094aeee014e110646ec5e2d8bc1d3a661f3a5803368e9983bfabffcffc56500a84480160fbb0f651992bc03d74e295bc2677616f43c1378468c6a4339dd780b4bdf691e127f71b1cdd6e6eddc7e16c8e215bbe12aa25ee78f0e09eab4645a03917d016dd7d2f3893f185b78ea0c979acdc57fa7863a44dd896d89da6d8a650a806b34ca3a00b55d776fb234e8996f57e9658b36a453794bae74e8e862f0ea02e31cd0cab539dce0440c00633f656cbb164d17d96f9fbd4723e0de5a60b4e10b69a2e9b4f9a42cfe39c1d6832622f1bfc3ce1c2c0e7112bbac6c28b9e31c7b0c7ada715c5433be35eaf0c8f0d80cc9c4e865092dc98fb94da7a16b80be9e840ec67a1636590d40883ffbd31211546c32fdf518035e5fd0bbaf889c9485f7be08e3ca350e15e22c02bda292f7c8802856339319139d2185c55e68a057541746038c4a60f02e965cbc3a36147c3fadf2ff60de9190bd7c3de92b817e98a89dc902c3ab90db51aad66ed26f02d5ba86154f420891129e1a789ef1f9a51c72d98c05e847d8396e3fbf7934c5082928a78cee65e080232c28f3cf53a360a3a333250391dd7bab5a67b9020bd9bc7cefb84b6f7cfc2eb36a51055a96f09b98e6372d0fbbcfb4f9c42fdbc544180b572c2d38c3e40c23b11e0e5d58edb8b9ff55a3cd0a73224f90088c08b11a9b6c5fbbc0190e1780e8c1b832c561ae51b30b2de050026204540792cb734d8ca309d9963ef3659d9585195752396df0a2c0c46ae5950fdd809e10446768cbc25898d186ca5c6e3bc24bb752d7f1e22fcb6f46a99a6008f5417af0e2dc04ac032be3a136c0941d4c9f88d27f6a58c78cf4e17673cbc9006b1856eb776fe0860e53b03dfb691b084e2632267fcb2b8011e780f96ff4eb0997d73ed67c58219add3b97fe8550a8cd4f7ab013b85d5505109b2a752d5dd40b7bb39a9e7fa605587942c9a27d8eceaecaea5c18f98ac3698e3f2c7209168c0321a4c233a0010873cff7862fcbb8f8f75ccd1eb180ec77ebc4b97aa224bbe60bad2b389d190f50d4d7b483cd18fa5fc39ecea58aab034d6b9ace25899fa7920d36389001ac4a50b6a7ab12a94793a3e4dff3c814b33c44d6a8c749fea3a2e200ec58f4afd85b7eb9d07fefc9386d5129b89cb84d874f053f2b7ffdee1670d60bdec3d96010313576c0dc8d8cdb252f95b8dde6699b25e2f2a40e000ea8a0560f3d476f94f7a9034c33dceea828ed48d5bf6588f72e349218cd9c56e502de560c96e2bdf6f4f9859ff9c13af523794e630d68c3a5f62eb8dfedb14108cc0e300c7d0587ff5ce77b478061f126609224e47e8cb591816c038f90b2f1c2854ec407db4cb3e76229c3d3201610f8f21b85f0a70876247ccbd47e1533f85a76cb2f00 +generate_ring_signature f23065c28a04de5d38606f37b7cf29c680c06c2a9bc00b2bb3bac696f9df5c61 7046e48f17ddaaebb928ae39dbe62c23441f01ed40d23fbf5f07e5a352d06197 16 9cf7b3138ddeb90d60b31bbad6458bd58bcad71192d37e69444b28f9450ab37b fe25432b3e417e7123b3b55661f9d8e01b9238c801feec00d01b0a144439126d 1af5776b1bddd8ea5e775e035ae7a3fbfa2e08401f7bb01162ca7d2c9ce21aa6 8138759a1d698a79ba0ee523980c7899f5833ccd15f9c224a02c44accc46ed71 00cc8407088c92ac28aaeebfa3de0f699de189923fb7fc18daf1361a7356c203 6493d68aec79197563b65b4d202665da993a27318538b46678aba6df7475e6ef 2193c3b3e8c038d3ee84d30a3e6b8ccbdf29b25f9b576953907b28a3abe41689 3f4692db3e0e194005497b99f5097938659fb00906b308e4413ab07d20d21ca2 5adf105a86dd1d4579bfb3bbd362119122bbf9517c089273570189f368919f60 8e2b0684c678a5e9500332e375fe28f9ce127e1d847a56aa198f81d02afecc3d 75cd3c47a8d0616d4f7374f3b652e2b4dcbedc826b8b0f22c8f2b12d8449171b b26567ad1bc3e39a4d59795b347cf852c35944498d5ab3537ed76f63111bc196 a78edb131426ca91e0a25be0197578a4d4d2876d18313a940814d8c8e65f493e 943aa48aa6dec62a8f30eb16e796196e3a35569203e58067228c8b496a739d4e f9d1ef180af3b08d9ae7ee9dbb687591bdd3f8fd2b1912de622cce6a9e0d25ba dc6c4e0b458a8f3b47d5841dda4b34bd01c845031421c8fc34d90f2356564fd7 f7738841783117a5206b00b4054df1949312437643b353459e02552d2c69f10c 6 964603b118505c20b3987666972a5a5e7e891c3e4e51580f284688e2481bd70b498796f0c813fd29c10e0df30beeed0b1163926f327918b35be185dfd44d6b00fccbd4c205948abff2759be109f879ee37462f837f0d9eb08eb51f4e186af20e282fd4377a6b31e684956c989a3cebd51676201d75cb48c11b16816bc08a3d04ecdd368735193e485218aa317d492dbd3b68e47e8aa96f98ecd566a44dfa780d9a53dff72424d0ba262698e1dc485b838cde36bfbac9754a7aec4cb66256a9094e151e045713d497d795f0298d385b791893205ec8a29dc2f0723b4544ec4a051c22203aaf8a1fb9ff0b81902dad6d0ee2da1a5f3c9be1d3a448bc53e8abec00c4e8b14eef82b27c6dc7106529041fa7bd34dee37a0f506a4445babea0299d06afde9b02d14754da838239bcb4b51ec24d7afb08c9e14b9f2c52651bd035ea05a09fd7a7203b7069b4fa663a9c06d8072e0335123ea3a3bcd5ef351e4a3c310a272ff7ffd79773ae1cdcd664a20e149c98b5d13775ff9f6279938ad546e4520429fac293fc0ca6fbf225a2c8626e9edd7adbeb8a7a606f2de9ae94ee4aad400152113f70672d860f0c26fe2b482786f1f38e1643a938a39a04488de0a3f5c30798729b1464dc926130c41c8703eafb4ab2ebe202f618547b1bf17804ea31710d8ed7fbada1c2c44657de76f80d701071249b17e87a44533c499892e7a296340c5c1a0e3fe4ea65de541d3ec769a4fc3eac5ed91bb9da498b89a79a124a9af30135cfa0ce7e2c0d4c526d34085c186442a308c68a2b71d8bd81bad2b2382b7105f78b870b18c32c38104388ed277e1b2ccc15720460a87b13c6a8d6ab0cf7ae0ce94d4dd6f64dcf6b3b0d4853e28eecdf09c29cd1f11f21f4d690a1d4ece87d0b3f6b0f87ba59fa78cfe9105ab748f10f6575978e41962c423ae58b0f6f1b2001cfc6de6a49cbe2819d37b2eba07e7b55dbf8f6516f63de02f10e9c7a63354c0427763f12232941b95bb89ba559a38043f833bb54cde19f6084b9f1a2a301c706d1661ebe1bef22d6f37c78fe559e1d729252798852d2992717616bf67548ff09e268d36867a8c31bbe5928d9660bba90c67306366f972d6ebb43b89cbf40e305ec56094d951be06ddef44fc954208791d80ce7f7efac7b59082bab0fa55f39084ce14940f646bed4c8ca9ec0ff6bb147c5788e3482f3df0409107d9ac1c35a0db29b65a861b51ac08191bbaddda91285a0d7b489d123c22365874cfab8d3e8087d1082abe722b290e95b63660ec41e677937d8d5b76bff9c328fb08b6b7f270838b0011700cf2c2c6568ec91d6608dbb9439bfa67f0117aeb2c5e4418097d20d9b61cd4db115422d07e81c5721384fc32ab7d365ce8491c36faef484a1a8b5031a9f9075c346560b5da4dbb19f56078ad0794e54584065489f319436425b3304 +generate_ring_signature 89226689e486049662075f55d46361d821c5ede1fc172581458207aeb3d7374b 4048d63774cf0e3d73059b76c1160f5b36fae2add758c0b5d0a76eccf459081b 2 68943d3665e40eaa5d8ce9a3279e70e9d00afa0cea15d6671e024efcdad2900c fb89cf7108eb3b68243e732e820d716e11a0baa0def8d2d837ab998a9bd642c0 f75b48b628a7f3fd1dce1055f7c0b81c36454e012dc7ead8d5528c11cd52990d 1 eba04712d647d7d1b535d767e859f23538caa40788b38aa3fde25bf875966e0bafe9b2f7ed81cc2dcd087eaea08b9551c8d7de011b25d73c1f0eaa178b613701900446fab1a384897600e0c3f67b1652cc7ae208157dfd9981156cc3c7d2f807846c432fe678a286c39e5d69f70d6d636659c46f3c20ad50a05edb833355240f +generate_ring_signature b5d8229ce74db9826924b3c6e5caef7e7e5bf671ed19fc11be2989dd3c47931b cce45b0c2c85b4210b5b11644afc9395fcb69ba98603adddb5553445e9ec7b6c 144 0be075ebeaf99a172e8e39e394767c3a3f987767dd4980c63801034626594ae6 73fccd68f4dddcedf7206f4928e50477501c1efd04ac95c240bcdb1311abe7d7 82d86f2cee19fa0019fdd5680e9f5bc9a0a19fd20fe801693646eb80029cd721 5028c84c1470faabaa794544bdc8cd2c711465def027442c68cbb51d8b26a173 cd8f47f244cc2c434906ff8a3b05cb0cc6237dfca4df80f54f737ed73a8de6c9 b5820b71fcb114db2922d51ff6ce2243fee94e0b2b325539c7ca31701a291b9b f8935af82ec3e9e25665a07e742a0db3ab87cac8f9aa8765bf50edde6b039370 3ccbd63146f9d7b10b80d92ee369e723579b31d62d93c6792de1a4eb498cfb3f cd2d042ef2fe9c3cabe3092cae589b3ac93bc006c44191ec547645ccf67afdff e2d93bf17b1a2fea61e957bfc3e8a9f354ec7716fca36d9d3147608eb3af97c2 8a48888c11261fb5a99f7d446d679b545f9053b2daf6c82afafe43f8ddc2b6e0 1d5a580055cadbb839eee43d38dddb20d970ab5c1a9e2f05c553d299cf495774 f502b134474771d28c63829de5e2cbb68f561ac4424979ad81d9561c77c9a8e5 1d0c147249493a9cc4c6a08a5e1b787bcafe06363736cfa165b1a01347160495 5ac2b45e81b6098c0039a2af48d87b98e39923f3140768b797ca3d33929ac7ab 3859ceeb597d189dc18be59daa68d39bfc2361b820524631bc05e22b78ff775e 96dcad77dc296cfb3929634e642229bb0f748cc674266991ed53d64956d6677d 3035e9feb91d2bdc3917a8c58b76600141a4333dc94499e36b9a75509ec9278a 78b57f73d0d54237460f950433f02b23a8b73fd686db4872dbbaccfd93e4962d bbc589f174313a7862b5cdbe0bdce6ddac58d6167fdd906bf255e3e98ec79160 cf34f7674a32ea2273517d25472e5bcc686f3f461c734e4e93a302b4c9439d0b f880e06bdefa123e7b6a09ba0e0de33fde7cf7ec3b792abb07ad06107e192f73 988521245df44f9840aab96fd90af3c22455058e24eda4f2e33e1269dff4430b ebf20602e0afa497d66b8e34e5269ed831e970f912310e178c1414d25ca71c35 5efd0c9703fc2e020379534b469c526171091147c59d2552a871823c11821e6c 943dc0fc80c35556a653903f09cee980d4f66d9e7179dc26ace15aed32cfb9c0 274eec520fb3250395785dc104e5b914ff88a4d7f9da7e07da6c0830b2f3a1c2 560f145a25c13e0a1f6d9d79edd399d5afc6b09e3103c09f1d77b11a975e3b2c 3b13f3fe0e4428737929f2e13aa57f675e7e3688d8b7b0475d0a950a730d354f c0c4ddf2f2fbf1c0c8ec3873285ffd498b594cb5714c851c27e1397d386e12bb 81ae0f6596c54518ccad5d592123c5960e17b589686cadf3b530b185d93048f7 4ca1879a6b680cbc2024fb37a2a17853767e884cd8e2ad20c2499fbdb53d57bf 56d56a1d537d1f9bdc2505bec8cd238d765e1bed5c245c1054422520d7204ab3 b3c4e1763c0bdb20cd468a13560fd0ec0576d167a3d3d62523067e8e23a2ece4 90805b8b9ad99246003275c1dab6d1bc2dd6bb12454ac381c662048c5bc54738 dfea8fcc3267c854025ec6c917b696c1905e23282ccc042d81ab3e37782380c7 d86baafc5adb032b78d5a7e2047b619544d0d97236d79002d3a091897fa0c48d d1f6ee6693c03674a865ff5f24316e48f844784161afffa57f0bec4d098f01de 9ac006713f84fa6e3bcef13946203f85dfdddac7a471ccc417a65fb929c52d3b 9cbfc2677c60a2cf155dbdcb8065778c7428f6ce8524f483d67eb45e7e9ce463 ab7bd7860210e59ad3231d0309b591d1032b6af933d59506641e55b659efcda3 7d5e773ac67fb198cd86d94f52d8949d3a44bf213980e2e9355451e65d5d3888 3f34184c4cc8f2d7fff24871d02347f522a690866c695f2c7592cd37ce48f9bc 6674fa097442f932e1e25123d663672e2de17b2385b8c41a6a509c46f89e324a 234a35e2f0da5e2182c2450e90101cf1690235894fe8ff5cf7036e03d4423865 f2c8967a786fe891000838ae56ee84891df8dad799971bd87ad9e3aa0dc1d03a 0484249715649583e496f21fec59eb4c35553761ab82b3bf85ce18e67c184ade f6104748641de70509aaaf7330d390f45ed534ef38bb11ebf52ce8e6b1f9cc42 beb938142360b3b1f0933990a5c0e65180d77c2923b2aa2a3f6250c153c8dd13 518d918bf968bdcd664b6bf24e865348f7093ed723e0293ee86a2402b87e5df4 e86e665a415da43c81bb03d895151814ec4c045147a4bcfe37a014a846f26436 1a11a329f7530ab7b31198f03d8d29754ffe53af384fe5d4db3fe90ffa3360a1 cbf7a677e205f9ad968df137584d4c90438505a629dd6b5f3c4f822564b41c8f 903ea1173296e05bc70d6ecaab59f1a6ae55ba8b428d5ea9a3a5e4217ab5dd49 aba326ca541d77ebc99dda5c1ecc21a07010c2945ce9d5d18a2bc753fcc4156c cc007e712cac3f9d64f16ed07dadddf934b1b9373247e0e8d350e5a2551ee0b7 14200d798b42df0eccfa9f36ad0e18f1aef0021e9d3ae7912e71bf4efa947f29 658b34f8f8f575805b075dd65b5493b737b1d8b6ba122a55a25f7053f23da8da 146f311fe86024f1a81034d6c9bda14c3d4728fdbc030901a1ad577bef3ca5a0 9eb53c235a0298a92643833c1705b6bbbbf99e254a74e93a63b1443934ee7aa2 ca1831e48ac62ded5bba90fb71d61fcc7704151495bd72e05c62f780cf9b519c 4d1d68714278a5333173e703409b4303912cf3b44133102fe9eee8842306fe08 4ec22758002566d15055dc51f1386907f7104dd011c8337f1b36fb29e881bdd6 0c90d65ca0d89c7835d5cc8f185c6abefcc68c0fde058a516ddc19aae133f6af 548f850b0f17d7b21e8c1a0d77785253b05737045b944364c157b942d094e5b2 d0607ab0ba606a0765283abdc2db799ab04c5c63edde5554396e28a87c5bcdd8 51d421c5fb161cb1c883e2e81930d9f848c5eb587aa2092431afe368fef3e0ae 5ece9e7ca0757f3342408b957d8a0848fdee5938251626670255ebb0a75ae101 5579c81801b58b99d1238f2253651b143d8e3ec4cc69f0ef5fd5483d216e1319 7bcaa05b83bb272070bb8987bd618c24e45311b57085b5b6a33f3e1ab804c4bb 89d7c2d2338e0b5fe50d17efd1a567460b484d1dccf9d528efa6757d5233c85e cef2cf9153cb0ba4f39713613ba40ff9cad9cbb7e518fda13e721c329e6e38b0 8a831f7a9a03d40371d569427e1c00b4c6b59a804135c90849fb0abeeb203bbc a71b0481ffb4425af168570f2b0b415ed1fc1c181204e21a27fa5862d8a63c6b 99fedf8d43745d034e111b8cc7d99e54d18b53c40a428d2628365b2b720a67e7 d2575e2b349a45027aea08f5b423ae42950e39fd365891533196026f6cd2d496 e081393f25372bf4f1aee37b8bb04921fb8f6aa0fedc1143ad9fce6de55243e1 ac4168afb6887345c8491a395b777fc2ce312372c6655295faed65742ac69bfe 5472335979b474db10d62e368bd14c7fa3681e2aa3310ab5175d47b9b23d4861 3e70485ea10a5d0763c84c5dd9e09a25adf926965c59c0d7d1345a60d0ce6024 ea6173b067f377d97a79537f532b8d2343567e92cb9dc977e772cdc6129447e6 da151c45da028df365edf5ffb819db00f38ceb10fa687d629f958d653c7f7753 4d94eb70a30b0c63513a4f09907f972fa82a2f941be6bd9ca914641ebe8553bc 3907706663fca37513a9a30facd133017aa772f69731be6d4deb4f40047ccc48 32d52817b46b90f7cd04c2aad2ba6f8d44c8082ba397c60b0d982c5c7aa9a8f7 8abe3186bbb742c573ac355421962942ab2c75facc6c898ee4a19a03b2526ddc 9bcbd8770aeeeeda57a9a2dda3b526e5abd65acbfe8b68ab4fb346da066c476d 010c68c46034de748d583b050e2715d98ba852735272e8d11d6e527bf1a40cf9 3407b8a4d8c5b985a20d33d3896cde2cb823320fa4f7a8f2385dc320d83d5ddb 53a7e5fb8541fa6abcbe75a39cd9b0352119fcc84e724a515f3442d4a558c55d 73becebdf4b4ddea87969a7d672b4778586a5711226e7ea72b6d615bd6eaca29 96cc838b65be8f2cc82682aae4948d766751bdcdb162b399f73b2d1b28a47492 2a0780dc42a9aa0ff3cda976a46510ea79ade528d57c66131da66f29046669ba c0e71216cc5e4dbd872b783181fc19b8c838881b8c7feeb7b679bfa700c5f00f f7b1094d3f05868b1d8f82468e3e63d6ee98a2556190e8ebdeeddbe739662e70 7cd1ae917e9fe9b2250d118b320a611c42907668a2a916430086e79fdc31624a 6c02f8d8d410727f698344007fde07f7bb260eff705a031fcca93387c0538136 d0f96ccb71432fa05978ec91f83d522bc6237dbc29a28ef02c9019f7674df4fd 0754988d535e9b8e840d17088c97eb0484b9086fde51eb499f9079c8694b9092 b45a7849a1b66581d71acd062609a406e78566c94863ae128f4dd89db838b09b f2c392a9b334780a36990057be799cd2d96d9544b3388563fac448e2a8e61ba5 ba1ac60d28e8fe4266f7e99ba5dcfdf2c3f03688836b6e39295b4f08356e5e39 3cb51ec951027e73f76394226b502c12549883591c82f40998d70a24433c584b 6349964aa8486223d4b70c8b8fe69145525bd91ef6628e1c6cdd2ce0ba04c266 290f25e23204297c88d4e709a0ca24e3cbc54b657393ed8569e1d9f5110cc2ef 0ff7d6198640d9e511867fc6f6eb733728d4087cbf803cd6fda69743415dfa0a b11f6e8f2fb83fd784b1281372023354d58d84ff26c24f6fd7701537406c00be 0b5a3a445240b4151eaf074d6be3c50bc54fbb69db6f1eae09b6c146e81f87d2 a70b418a5ea1f707725dd25fdb646fc10411acf4ee3495c160e56057d469be7f ba5d677d820274a39f795af23e660a8fa619f6213d0c99051f93006a472105a1 da947bc68bb177db418974a50388357ba6c0c7f7d1c269c6c7e7ac12013aa388 b8fface27affd9eabd46e85658c00b2d1a187938e70aaa0401ce2645e1faadc9 01950f516b23727d50e930d6a7f982701200cc9b4f91e5fdc24fae0621df0648 d1525f7d9ef2244122bc256f431b58a53f348af292547b970214c78677d96748 928e5176379bd48f34ef5acbf25898ddde6fc2de80783d71d01dda12f38a85e5 c4e9fb2607e4e77d6be6651e8f3252ee3b0cb4612adbf38432d8cc40a25b6423 e8c78da2f6c26bec3eb9d0c8e54d7169a780b4eb3a67f60a7be45b3b347950c5 5f198b0d848e36526f7159ede1b985ef4ac6981ec31d337efe6fe896236b48b5 d49ad6a6b2bb67adb3503179d1c79163385eee4ee6169fc060058b8ddb9fd401 80bef6ec30689b27bfee132087ec9308d11746263f7dd4313c400cf98a45724a ccc998e5dc245cedcc864285e40a6453fd2e443a687e0695e1f36887168dc5a2 c6b95bf4bf9d0514ef8f69abba93cf993c4731598e9bef7ac7d1df9b5cd868b0 571028b516c0d6f51d1b7809fd5066494fde172fb962f2a95d9091cc231bb462 f039561da33396d6cf7f3d5234c3b624981a193128904f296a2d49539c5a5354 c254db3225ffbe528992738a1c2a2d659a2b69b7823d5dca1f074768b2d0fa1d 26e8fb8d19c19f48c8a4a6fc8c7ae07d81a20e338b26ebf71eb6fe9cbedf82e6 20c5dc8182e869ee3b7824eb8f3aa8bbe41cbe85fef2416a116a781cc761c459 627f6fa349be0f4fcc820ebab0c373d346081727c41b3e41f6908401c55ca8d9 dd81b44f36eacc86416c791de3b6bab04d52f8a001cb805f71a09572a8dee99a 621a8ccbf534ee9b37d39f83a6f02768bc0bbdd56a9ffad301c905f43f95df1f c0662a10f78456cc0b271e278563c6b269dbf1cf6ebe5cdda87c07b735aa2e64 49f3a3193e87521d12becc9ef14c623e844f1f1a6f55fd6c2704390268f45d90 6623968079cf82cc14b56fc0eb73faf93b4cb5a4f6e1c56f12e2978aca03f6f4 c9f349184647ab482890e8f118a92abb469f62c2756b599706898a7ba2709a8e ab17adae0cb94f56924e7aa5e4dbb18b640fecbeb23f3728694a071af7efdeb1 d3b700aecd64ee52833e70c957c2d6d3f3325321786e4ec6fcd95a4645e016a8 a6e161b23862fcf9f036fa3627f2887089f79bb4e9df6587a23cf40079e07a02 44354eb4d4a96bd9dee8a8e74f2596f5cf117eb2137057758b012ef761ebb94b c66e82e556e827481441c89dbb03bc57e7fbeed3b684ded48c276056bec9fac7 1376ca9c2e462f8d22aac18d284d5ea20b8614a86b30fbe073baeb41074cc51e e098ba48f7f5f85336e47ff10a3edca5eeda1bf9717de3f4262a80e77ab93674 2779e3d23b90fb744d69d5812b0c06bd17ef83d509fd6d5a86cdfd534dceaab8 d66a3585928fcb67eb352804e9905ac7bca6d6011fe5f7e3c15df19a6f9d55c0 9892556bf022ceda7b1f04aaf0328ec0220e468010a235b760069df477789167 d089b93676963402c9ca2305200908ef13f6e5e5539cbd865b44cf6b32499b02 106 c3599fd9f3ac17a7abf7d088363a558cc65594f9846ca105209797650fe8cc02595167fe0b2d7ad1baf90680597cc298a4e8220e64238b9ee818ac0d1c3cb901197e458ed8797030650623bce97ba8c042a816937cacdee1dc80de61b30c790b5269f9d96eb2a1c4550ec7f99060852a52d4509d30e30c6ad480651166ff6a0687b9cec9d9edad0a015e25e0848433ba87eca019da1c3f619632c739add00a0788d60b7e484c26b9457de38ec2209694630f40a64d61abfd0219c3749902a309e2873db2d19f76309a05fe7380966802888c45a87fea1327660c3a131a4f7d0f84c75ddc7fabb0be6d96103d8c7bd354b70c2c7cab6085cfd4be689442fede00de86af3406c041122955e5db1fe4999245d0963d5bab00b9a57c39b7cc298a0e8d215f7bc83a35943a4206449cd0cffb1bd4b4e38674e0249de866f1c92b1d0eeaeb66cacceca6c08b212de942d9e75622fe6a74c12cd989b5deeedc25fa8c0853f622018db4668d4cacfd8e31703bc920861ccbd91eb17aab22787f512d9e0e9c0eb85c7d55fcf8d6f36dae60864d8e6b1ebaa83e050fdb19b0b58601735a0b75832687dfa9287646b10e1317cab57fc0e839f111c4108587779144f8a5fc0aad888425362d7075f35c0f465f3dfceddaa15f3d5ba98663ebc79571e1feb10b209509e263633be46fb90b145319143311c4d68f609204dc78d1da58b767e60068df23dedf83274e3c745f779501410292aaaf3a3e1ca869c26553b2a742a3036362dae711519613b2cca7de675489f7eeb70ce561235cd5a025a6ef3541d60e8ea4f8a708fe58e7dc4b62706ae6b36b5edc4db2c79e5504808c646373f1480a35543c375bef62446decba5b701b9d6ab6fa9ef7496a34fa69dd7b356154e70b48d8f5edac9e6747108e4988d460dfbf8e01b5a5bb1092128602117ae1ea63019ccd049cf57ad4ab59814ff218c68373b596effcd7ac9724c80ef24e9cee6609314223945883af4b688a3332e184a9af97fe5e32d9b1935c20e4f01640833b04fdbcd33f12b644e8214c0e614feb23560912cd9331ccf18ad2192937faeb280c6226e186f3eaabbfd7a91d17e7d601fee1ae1507427378cdf6606b03b49ef1030bc1f997c876d799ded665411db272572baf71147d98c72ce9d74586242ed70cc304bca4eec61392564be36699228037ae4e0f30a3b6dbc3ec04b749a8c7f00a1039e06e5448a63ac0f19b7210ca123b8c6391d9d480fe77ee3a3d12f03a0c0d659f299507c415e168f12f7cff9f3a7340616f59edd1814208fb226dd17af0088f35efd0468bc02d1bd4bca546c5767fb776e4988775cfecfb54e5d2a2322a00d6f600c11298a426ce745fd1c8cf83125ed1d0999e62fe8d6b97b1ace6d19905a093655682b905cfec6dcb43bbdabff8c176d8bfbd028a878c0a5cd20f3af203c3e08eba1d970a3d975d0a0731411f6fa073c2fd9cfe587dd76187643bd3280b96fd38e180420bfa66b7c84ebd30bc9a0258dbead563ba6eb9563058b5d5340ee1d00b24d4edd26b0884e171cbaeeef242cdda9a9b0d6264f55edc671d0c5e01197bfa84ffe3d19b41a8efa617bb340ed0deaba427a803a980665738de666e08432f9e4702bcb37a7161288bf9a4a15f1c7a876aaac365c6d17589a1b63a7a0f80b9f6c1596d9eff3bd4bb4dbac571711314b9dfcd37f1e7a4968248aec47e0c4ea897fec99aa22d8a24064cc1e4d5c53ca2c4b2c2f4d21af89187edb294100e00568f5c1a9423b58a98e734a084d097dd288b63ade91a39844a9d3ca828d5086153b0ea8dea0f853b12579dae0cebad5e5cb47fb1ee2382351c61c689be6d04a82c71c8c6908cda5bfd613378d2adae734ce11093a4420a32a1347e82ef4e034311fd57012c4378908fe1c71568647703d5c16451bc7422ff395e1bf37c3806f4dc672590fe3dfd459796f2661535cba870df5452843db1dd6e9853359608019fe7d435d2c3bb19d80eb9b9375c58539bdde5da3d36eefe1733dc916b7ab70448f3a3d390249fe7d5e40797722496f97bbb68544b38e9e20aff7e99c6e1aa0a9bbbbff6a2cecf105f1abad5f41323cf60a2ea069609e3f480ae1f2bb9dff201c071a7892bd5e212d17e8af5d050058daa2b2a2d380ff0612bb00bc30332b10e67c5e5e5e97be66492e1b081243c53b094ae85d13d0a6994004a9609745b740829ee72857f6de48c90b06ddb3284050c7ca1fa73349295ed9c255186ec64c40b9d5126c2103472f5834d52c4d2b9456fdbcfaefeb6566dc3dcbffce8dd4a5b0714c13ce99a70f75257d5a3a608429506a6d2dc93c3fa08ea455cc4b7921bae00095d3a0d3188d2d30e9e662efc69e56060644722f1b37e1d24c831844b322507546a80f5655838f461937500ce799358fe2e589e12175a6614897e8f52ab2606bdb8ac75c5fbcd192e0bb0a5dd0cfca1c5d0a3048cfe6c2825b70f4967bfc308a2abc16bacc2b47df24383a83f3e530fc29b5f5a87cfe21904c72c64b50a100712ca358808284501952f9d157c7ae6252b38ab014d01f7781042dcdfda02e708b909ccc8c6ae1162c01cd0616b02665ec2b146c8776e4503297b488531b2bb041e946ffae962ad1ba018cad7faf9d9e40fafa26088ace24e47dc61fecccc5901d0a6aa2c60b46f5d85c7c184df48f93a13976e4937c4b4aba35ace357207290b533951d9f6c6ac7c9639fe0a9a6e3a636d5a2018417b1611ef71e4b90b6a6e04f0228e8ba1d9feab59d8c2c4ccd50cec13c9220cf741f33efd941a17b2af5f02b4c010e33221163023d0b53f3d9caea1e8f42b1c0fa6439ff27e281b03ffe90429d4a22401ac332ab6a4663d66cbc568ab77ef541767796e28213fec2fad380976fd9e62881a69c8dda41c0684cc1bf23471bfc67f5c3dfb3b1e18e9181f310c7fa0c8365f54eb77eb5e642f4836173c987ecddaf709f99a59808f2f091a950e8bcdd07c454e97b82a0e4d14a4414436fcee3574e38234778e7eeec57770b401746958056d6d066a78b66ddd3ab65f31a02f5084bb71ccee24b789e5e13c7305c75ec1ec0f5397383f79bbffc16b3149f7e9a9c5c67478edd0a099bf5a17bf0d018167e32fa63da653646fdf400314364c030a132255eee57c0879683871770cae9d5feb91e8e948d1e973bff68f4cdd78e17134b778ce5ebdd658664533850369bd04189dcd5d94f903604ff517699922246ce4ae265604fbb845347c9d330724d673d721dc97b486fa47625a896efefdf5fe3c41e2b792d23cc8448aac8704f88353b139d1f4e749171a854755a600fa206a1dcfad73af9dce6d9398f2320b48e7a63c58e960fe5b63abd9c8602b2cd36ead9964320e96f746985cfeecc70d4fe1bea9512f98590e946ef76396b2f39149f8506ef93f1be530b92aef5bfc05abc726f85a930f0dbc87ce4123a9ff3b7cfecab3ebdbec6362e0d09efcc8200c159cdab45451c59a35d02c0f7e0d7f862031504a06c5b822139d0daa73397900a33710350165506a0354d7bf52eb935ba2092289b4f0bbffaf1754fdbbda3a004120813d4fc1e280ef9348c521aa2c986702c1e27a6454acf0feca067147a60ac68bbc269541a50be4c3c5d4c58ee5045ea260982cf8860f4f12d317a42cac0ada69f1b81fc961f6e053caf7c9ea205548d6a7a2a19b531ce9c02573af35ac07fbdc7030937897b8280d70b23f50be0e974179da72a4cc901a88829052d00c0edff5f34b1132999a30d339c079b682efe2270a6a8bc80952ea40117cf0418705b495a0aaa1de3b3a00d04c24232e71449406aba31debd36e5704bbcbce16300826f9623ad2442a239e608ba8eff2a76fbc8b20ff0c60055d1c6fc63f8b72a90c54ff3ee9addffe43e2764bc2d1dca5a7a717ad3e7f395324f88ae7213131ba0dca4aafe2f3c2a5c295294fe689913ccd24947e839dddceb7b7ee2ace87d94d0bd45994ccb16cde1e6de3042d7f3a81244b5e16b03c39fd48e8227c57a294db0f1f1200823cd481fa10cbf07a80b9eb4d5033865e678fe641b90cdf25860a4b07650be4a63a78fbdc1928f147c77e3e1d254dd82bd21e773808525b51b2aa4a0ac2d9d5f330514b1d5bbc059b2598237ab3e419789690b9fd98a2a3311fa67401986d1559144238410aa30acfedfea75b45e65fb3a33add72a5f838bb4f0b04063db28fbd61d4b6c63b69c24c2dd7e6f5f6ce16b914166094e1bd6043c5885208cc5d6ff63f22416e3b7741de9deaf690fea9e4e8642861a2a6a601699bddb800070a41dc4b951351279bed44eede61bdae90f85879376dc7303a849ee0360101ccbe7d4b6dd26c95c5805c3a5ff9eadaa415f751b77cac21c34102e03899920a569fdee21083a63dd9616286747fb47f7faaa08346a77d2f5bec34062f8d9905cb99da501ef3a2530090e7023bfd58f7a8ce6a9b5950926fd5b1dd194f982702975bfd3bf35e757dc3752d788c3c112f5765db63967fcfc9f2f4ea5ca2009d00a8a2339796ecee04e4028e9b4e23ad338a6629d4a64816d80f7e55e6e280040f0d2f5e6ed0a59be64c16c193902a1336c05a5999f490e9f3476c9f897058e50039ae25ab0087921748d1f5a38a55c86c3b2f792d057e2959ad2d48fe7fef5103b92a7cd703b264836b89295fca913526bc2922e1c499ab4a85deb5e1a94643067ce40d6b4cdf9d45ea104e2305879bb0c0d9f15c2e4e93c12c569e5299d0bf0559a45b658444dc1e7f2c606cfbb2c544cf63f3cec1586f9449a5bbbe8fff6e0fa9e595b3fb97337b69c58a096e4196d0e9dcdceb68d1c32bd91b0eb5b8744d0aa8c1f78298f047871a3027e432d394cba5c5f42a8ea2c5b2083541b011dd8a0b2b142f169253f3025f6627bf22ac3e01e7c6ead6f585af692999a4ff8e9b6d0473c8786a72f0f9a11513d163b1944040ab80bbc56852dd8dd47b880e57eedb06bd0094cfff52ea997c6142034406d89216cbb18a6663d3912e67803db1cf730ab8914aa760106f7b7cd3bcf1b33d1a1cb4ec7c3ee6dea62fbb0c5f44f610f30b3647e3db2883b0534e992dac3909d23b51aa02ac96663414a3b09f53b0cee5043307e95d656cb9ea8a0e000112bb160e39313e9fcefb7d764f4168a19e97030167bc345f3985ecdc0ae589687f34018e622c9385e775bb81efca3e96bc5bf0032c331b3a4ffc143edf7a4f2bd55e6a3ce4751635b8bd30f7cc212aced57db80df13f6f5d273cebd940fe7d4ef8e1d5b4d79b2520408a6d61e8113fc1d9b3c40084ede09f602e7de1397382c6263deeb994b3f956207a53031b506559ee08c200f49977be6e025edd360167303c736d118b1e1796146c169d56ce0792a8290c00943e4cba899c458b051a2d0437b2a7da18a300b5343ce85a19675584b982650b4b291526b70ce2a68304dd5bd9cedcfd4f41357f267ec839bc24d3c6f5906f03d197a921815e124cca619cfee719c432823cb9bc0a95abe35b1c8b4a563d3b06126f8b9673c78ffaab50b9bd4bdaa3926c0561d32b33cb6ea34908a0ad53a705e57f73c18b3ad711972eb968516d32491d98e554c5fc5d531295a549e50a850d09d7a1783ddbb9d4ac2c463a9a85d444cac5b283fd860b6bbb6ee4e74121dc06538721d7a375142cd0b619aa84d1b4f66bb97769847c379df060b4df904da108c045e484cd96e3b3bc7c92d313d7e8133174005806a4b1eb12eb61cc9b26e5026ded5e5a65d20c2a6361de60e93a991814ddfa2ac987d6dbbd238658a620840ff3cde5277c9f0d3c4e06ad1ae6da8a0d45033a6163a3655754d9c5124e80670f30cb163d3e175f199e1db6d54de4ca15910002f2d4cd807592e886acd088310d55b7960c3677d0bf7364db5d9faae209122188961c0e19d47ea116eeb3389d04fd5e53f8fa3ad2b72f302152df460c07950094367a6bb1c76e6c6bc57a463405816f4a3ea003d322e04206b1d79fc07cfee9c26899b71c41c572cc9846a2490f3cb90d79d2d9b13addbb1744aadfe6473f585ae9cd37d56f50eac555b5edf9007826b85fe5cd787ea3744ba57ba705cce3c8f1c172fdd8d10aef72f88cc6900bd7cc665ceaca2f742e129d6d457c77ea8630a56670950cc5df597e3035e2bf02925e7b8555dac8940caa133da12cdd0e18d348f1c54a8b20816c5e17631bc107834513fa33b347ee7d8b86f7ea6859e3dafbb468ce0b9cf6ddb88d8b48caf70470fc4c2e12b7dd1ed1c0f94d71f4ade92304c4e37c54914a3e71449d18729109327a04e107d2181f7a9b86e36e8c1dcd902029a662532303174ea41871a0e4036fe809e71e57ce6b82b3f0a5d6af93e5fdd82452a9c1ff96a58efbf5039a5604c27493b8927a4f318a4dd2c10d5d317a491d63d8d522886b750affb5335b0f0ae7b240067c9303fb06de5358767a11c296152ce37a0c3b9b9b922593bad57d01f956aa02414dc94a755ee5dbb21326ea6524e0fe5397f85041e405846ac13b02719a18005ad8cf9a92de839f2951b739206ffb75ab4d4f98516422ce3970dc037241c1a85f18a2c774f0905356743b6f994cf09ccc5db2b89b79689858c5ac09394a265f1bf60f0e4a426e019baf72812e6c3ab377d17b8483630979a2d9ab07139a4f4ac5b764e174a7f4f1388d42bbb7f4f658dbfe2178503384630f018e02130c924bca3bd982ada71e0a7d24a7024c7ac3b61ddfae959ec41b5a44626a003c0e19524e8058007d1315f3278804dae559360574eb4e162784f99a7062d9098a23f04bbbe96d806eff78a217573a2bb6da2cfda5c0f7f5ab9337f22322eb0c58e7cdc2a0f23f82103f9f64030b1f25626abd1664f958ba0f2c6359253977005373a8a035698f6c9f2e592654470687b77e4b9535365250020a82348d3cf7052066b3881500f5c46ca4db97dbc0ab3783cef970a1f4d4f1b3ba87e6e90c1c0961d6638104a1821fa03b30022e66031ec15d668e3ea0e3ff72484dd337f2e30bf606a62b4e320187c95edb7cc225b3c428b8098765fb5b028856eb4f7cff670d04d102ef4a28d1c3cb141db212e1ade287f8975b036eabc2538bad8baddeca049fbaab5b6da8ffa8a0e5eaa011bcdec8a21cc6e180e96570893bd54684dec90bef5705055d00e5caad11d51478a6e53a34f5b8956a9000bdd51358d5690f5f01dd15e0b0884fa6fc2f7ff5052d5af34dcc4eb596f2a62a068245dd95301f6c026886eacc4dd7c770c94d626ec59b4cc49846ba34aae25a25fd3f4705bcbe47093bb01765dbecbb0096fdad3e35fa76cab6a2965185515ba474ae7eab967f2f0180ab999118d5fbae3adb202003d3e72923f3bb4e8d33ab32bd2da0e5baa5b004bb9bd7a4335f2841ddba012b5dd9741ee884425f66a477fe46d71e1e6c002a0d7099c010c316806f99ffa8e73388f0218d6b9da1c37c370cfd699a5ac460fb06e81ff7e4a1f835b0894e8cf3646c8cb2b5963b3c9059142277d70b1f978784056666709772b91aebcafc0f2b468b90b7a71a2a56cf1043d308ced8249990490392bc459edad192c5220388a41852bdd62c8831b8a93907eefdc3eb376aa9d00309d5c81c1241fbfae37b68002a0d5c436cb8048c677d691517edc681dd956a0046476866472751d616964ebb2296389d16cd346d67d20a11da12bb80dcfc3d09b6de8a494dc39788dd9780fafde080a7148998517381aae05454c249555a910bd91b65f157041086ac9d0506bd4da32de55a64d06327bf8d225a41994c279c04fd051ce9bef0810d0ddc1b4e9dd1618ea9657adb8259f7878437cf583e09ad02b86fceeeab290cc6b812d591f7d4f9e9143d55610fd20932c17bb39dc950cb09ffb1e40b7b681605de2a915f84dccff50541d34f34f568ec629df5c4b185df04b95ec5f33f182eb4e25af99f91af440df26c6a397e990b93f7c441ac11ee8b0ec5a5832e7b4aa073d0de29f59afbdff435aa08384ccaa65c8f70b36faa0172020e4c23df23f5d489bde5f319ed31f55a85974fc5330035939bf3094a9b3c4f01dd55ed4edca8a2987cb66e0c6b04fca8a99cba4d7e882dc403baff915949050d6ce1dc1b99076516849282a50790aecc381f06128fb588e78da1ba33ea9ca60dc246eb01857d17db0a6d669b08c3b3e2967851e43bb886cd33cf8828f5d6a8067147f9a9ac544c315cad56622bc9ead8b69afadc81fe20b632b4296d45d4580aae69e644e6c23069ffcc93d8cf45c7205b775ded3032bfbc2209e84740bc9d077630f79c3ade66ec0c9c4d7c3bb848fc25225bdea462b00e1b8bbefba0b50302c96c69ac2c9c9e57974a733dd2125e6ccc395ca7c7a87bdc7861a12206098900aac2bb5e974bea2f90cfc592f964b122f5525bec0453ae8af8cb7896ddd62f00ca5fa63d050e757a738c34012e18f327bbe622dd30f6e4b54108b9b8f9f47c0109baf7f34fdfd95a61d4b2c7f3c59fc5ecd52961791f297f73d7623d525cf90b5bf0cd7a784f1e7d8eca92e509d4feae8f556b1626cbe8c047d5d290ed01a90469c140a3445aaf633fb2bed3c2b2a30312b98ec18fa00881857373c6a7b5510db5b319c4afe634b7c56395c5447a37b32091ff79f244290569847d1b5d1d920efe05b3e8ada5e3cb3add037dbcb32f2e3bb144472721adc042cc8906ecbbbc0c0e65ad1678b619a6148e6f264379d1dd27545fb43ff133694b0104722bda9d09ace850b2ae4913505c37f222db5898835228c0f42cbf9b24b33f22c7fe80f40a54c0d5cb4d4ad62b1acedc844574016f914cb7261ad693a398c68664760a3d07acc185fe4bf033f50338f410fdf64199231521c2cc907c11ee0b72591f30970c7f6a05e89b205c71091cb66718438b5d7aca900e0a43d183e81bd2c8916f85060fdf685718e72f06950f08009fa7fde9a4edb0905288b49c366eb2a74b74f9059b8790114ff22c88688fd88098790cbc5d9f7855c9f9c4cefcb3b2800e83210d8e10864f1e5b8adc1427b7769d0fb80050e5faf4e75aa2871f97f59eb7e3ba0bd5eea6e4ae1ec85148e1c6535c1c97902251a05ba805f9716990785e400eab0ebe6a542869fae6089701e147c3a0f1057fe3a8740e04371b47f658daf896190c1743591cce483e4a95e9687647e5d8f24e58ae184717b3db9dee01449bb2e70fe5ed585a5b1e82dc52a25ef942ed8610255f29a5ec564a74b524952548e19606656f08578dae8a9b702ffa20959ed2d8cc72a904bde19ad490720ecc8a5a2f0079245cea98e69cd0b5fe83de7223f87075dc27e0240efc7a8c4054c152e3f30e4e83430bad0b9df601f1173dec4f4a41fd86c9da322b278d780cffa9e255c805e2d627f9a33d864c658e0449cd18815058adb6b6707bdbc10fedcd152ccda80e3c43d5f6c29271dfeab06d7c104d727e80ab3487d5cbd7489d347a547954cb06439e54d365a7f0a8866ed10b2c24872a5dc31a92f15c5ba43b643080a4d33c0684c9c6632c70768b85ff9e8e7afebb6971c04939d50a272d6824a176b98321008292850bde080906ccf687b3098fd7f1a674c3b6527d409718f0c2715285e80e6a32c94a6fd96a51806c258c4eef427f21a5a22ce0c0f5b40a6a30a83c53e5079b7cd2ffd96c1b88537cd776e4c8e4f8ba929e4ec777c09f878cc3df81d663041a8e36185b216b720de9a791940ce5cb12bbcd0ff46f870153425ab6454ab90baabf1450feea5338a34a6bd522c6930b9c6b3449ef6dc8c03722df572aa67c0f9c8efb9c8b7198ea5330e2affccdb140a9f826c581b0b027d07883578634670a7e061d4bbdd58d5857ab0c9d986cf306c4fcdcb272d265e075bbcde4c181a408b42476e2cf978b3600353f31ff6e662b3944fd847df1a8a3473fcee22f7f0c040e7920dd689cd49db14cb0728c95fb167ce35a559dab70cc09a5f452c6ef1f0f80051029bcd3f06a275b01adecbd1a559feb46b1a271c07ff534d1482edf4004bacc213d5427aa83d2c63c9bc684131b4907c996c4268a13a7bb0c8d5f568c04ca695b2f7a27c7200a42159d75b7ffa6b467df73cb622315db2be7a6e256050b34c872682b1ba76a37e771449b836ef0a3dcc735a4f7b1f6474ac0bb1f83880f907ce30c4d53814b3ed8301e4f80e0dfe0f93b02b414d3ad092e0448e984700e97edc1d530054568013e5b75a35e53e31b4e1859a45bd06a8bfe2b0529e3ae0c247755958b4017459d25c7db42eee699e3f5b3662f745643f951bb4212687006ab9547d3d295f869b368fc2d79da4823985e3c102a08f3c90fc2279cf7bccc07a10fbb2ac32008011503d73f8a1350928dc17d99f9ea2a60e10c1849b1d9db011b46ad84459f09ac9b181591d7c812979c60559c71f7fa297457e23fbb85e7038380cc22aa0bfbc334d25edfdbc557aa132f3d6eb5c81b86cb4166d89336900682ea279155f88bafbc9e9b420116131f46aa7a4c9aa7d101685dfd6a1a757301b3631002d920ef7d77440dbfc90c73b2e924e546d7352c00047309f68a2c960fc834a9aa81e81cba608d4f67351a6ecd4bfea5975c0718b63321fed600d96204559d4283a2dccbb1c69c9820767bdad4fa1f0ceb7c2344789ba31bcf3803840d77ccba76ab24e507d792be01684713569d0bd89d18d889775ac28fb5afc52c096e39421d23eb728fd897ab9361592d32623ecf5a9e50e30bcf38740c0c9c8c0a0159d691266f9d373392883203fee2ad141568774463270aec890720233d050568398d1495f04ffc7f8ab8c5062e54baededa2d6bef603948bb45bd42fc9e906e21f374dd4c8e3f9f6b6ef6a25f2fddfc28cc0a26650a427cc1d2484b48d4b057e673d61e211a92a1476f8a49409d1888401bf3ed7bad2bfac236afcc2f7dc07e2d6a1ee882e4e1ff2ecd346b62cd7fa96cad3b8219661deb2cce2c96d60f201a7ebae5d5013b888020978f8139308c90e79ecdfcb659104fa9266a6ec9b2c02e4ff5ba9618a02c636e01c29661d6cc1de76c9d635c450c2ed9b9f41d391910d0717729c780f064ee7a1ae8b26cc9c3e0d0bd7e0d25419d5826aca18a4731e0238cd2afffa7baa3c10701073f6d9d474e8d3671b7a8b4f36f75ee984412c1e02cdfa21bbb5061a692c7d7f4b571aad1247901cc7567668228fc26de45a3981022474182a3eb16e922a00f54c30a44344a1a9b96cc839dc849f1b0723a3a04c05fd65770c644910c94651b72bd8332266aa3506f62461b9a15b39bdbfd368110bb124f08dc469084f7e9e132ac61c33f2ac7174e51d3a37f7b685e2a57536240302b5e58ffdeceec86aa75608f9b7705e55040a165a021d83ec058e6005a6fa0a780350f3dd779389b2a7e8926a8c6e2b7394addcae0266bc76706954489c0c003dc292098e5c4a49c12f000b823da13f5e15cbbe2c1553bb53d84ec4996cb00f8db5042d1c2c592be597839dce5b1989f93f4a7c30bd0104ab99150519b41e018cada1b7bd77724db7551d20ffcb9bd4be1618dc95960ad2b2b5ddfe405b520736104c1245e15b3792afd4f70bf24f20c5084978edea150818d98b96afe03a0f0019c4baf17a250276d745507085ba3ccb0ba4a72f5f9e413d1c82b8b980880959be53f7bb88d06987a6e48f14cf88444c4f082a1639a4ea77cb3cec5f593405dcd8840bbc906f2afef9c452b733311c31fc86f71c39f222ca7f8a2733fe3d05d47905e7f9089f9e279c89a041a3d62ddc751fa179800932bb53f26632232706f1d3457801391443dc5ad2df07fe3c9d191b02ca459e0c30a73fa3bb1899280c0078c67117226c2ee9992a13daee82cddc136fc5fd6c5b1ab2e76eac7003c304521da52df2c5b1b613ceda50549e589d08870d26cddc46fd91df60aa73149409252ffb3419305e0ff6fc2947e3c88bb50b7f2cd58cf8fd15a925f5aab812310c5416779cb7927bc3e82f02f01f14cfa2b5f838cb46be26b497d799bd5b945d032085b5a36d26e797266f12a94ac496a526747589a5a0bf2aee4693892715940a994a4af08ba3e8efd0c63a67eb6e40fec16dcb15fab6278aee94a8ceb541de00bd7ea0167596a6bd5b17eabf3e0d7bb0947700c0e1f93aaefd7b4ba09ae38c08e7253f7e5fef906a1aa77b8dfbc359110028decca1db222dbdbb98bffa4faf0e4698287fb73a159242b186d7333af5ba773014e4590a0b2df739f34925778a0e2eb3ea471969630637a872abb5c7cb6f6e43a4f230ccd55f29377a1ee945fd01fc97aff901da84bf65a2ffc68dccc8c6ae80d7e4eb97650fc9d793276cea1b07dd4d6b8361aff22758e78fa21ad5ba314fc71a514fdba96117c7975cfe0d8a0cec4f89f12f5224d480c79bd55a7210a9c7801c026ccb885ab769051a3fa94a0633ace23b654a26e77c8313ddaa82dc2155f3e5417a1485c30d78a3bfc25ad10a93a0277d24b07aee0407d4283d1c8666fe83ba22262ca39655be9d3378f0af044ba52a9a72b01b20efc515ce65314d6728e50775ae83c16e7a05e58bbbfceb0d2990630f425232da59c19c6b020ef3d51e855d756bae6c4d11205de62efd730268be7cb5c64fc50cc0f8717219f2eec52a7cd06d4b3212fea635ba138548d20099d9d806ab7ea5309e5d76d35e4a27ffce2355488abcf8efae2b94a8715b610868fb67a9b2c8a3e6ff32149c87bcce3bc5b888a7762681961c911920f7dd6e08c9a4c24178b694379be9ab9aa317fbefc2e3f67a99a3cf33def91cec49ffb501605fdf79694e12ca5a51b3398935e5bc195ffa77c09ab164126cf19d193d97062d610aff995c3dcc6410dd7258298c71434529215fcce74cc8d70d9018e6e00d707fdfcedca40050908a5c977b1b49c46d45a79fcae9d6134400d9b294e8320cb97b2b52496cf80a1f06ea9c7178d289d54d957ef8198152a155682da469b607b7ca67c62f84ee060000d17492356ef0cdb57147615f8b8a4b2ea124b54a17011a338324b2a38d55ad44eb4026ca5adcc45f6e01aad25858f17f16e7f3e1880e +generate_ring_signature e8020add6aebab8ca5f8b49f2072f631745887fa205d8db1a3aa1b5a4e232d81 dd963b8d2145bd369feed2501aeac1de2fa16ecb1b7cb93564535a6dbccbb3c0 2 9f1c652d42539ae6c7a43a5118d5890a4e1b386b3a400ebd8f2dd5687626dd55 90a86ceb7951f7b5668205c22e8d2c9953d0e44773f7d0159618a8a0238a53b6 5e6dd5608134fa4c64007aecaa340a0f379d1a5c6d4adbf017a239eba303c808 0 a6b4bbc1a960f29d8bf5e64c86f24d7ca19106f22cce2c78322fd64349a39e03d022aa167f277e6cee337361ceef52fd5a71e41d5603077ef10bc8145465d60f37429ece34bad65101bfeaddf6288eadb3303e4c4ee313b7267daf20c0e9a301207e9f572e9e37ef376f0b1019d493e5f3d7bbd50467b8cfca2406902d75ec05 +generate_ring_signature 3e592f32788ec54e3f10560b1380761329df534096ec12251382a96f8cab7eba 0b72892038d4248c430d1ac93f4985a8bb9b43fdf457a83618b7045980b8e6a2 1 526c98024c9a4fa8c6ccad5101f4afc972fdeb228620d774669c13ec4d029cb7 0741f944319e0c4678f4a414a12c6956cf9d4b3ad04a40cd6030e47ab7e9700e 0 80ff0faa32c308136c11720c51480f1b8c90ef2a1e3bbf72586fb6b5974a6403f71f857f3b7d54fab53648f37f6c162b996c7e59c2b8d85bfc193d4553734b0e +generate_ring_signature 701268c079222197470218f73587bdeb19c3620f25d1511042edabd0efcae448 c2b7340137942802b68be0a9cd0deb826a43f7645807c8f4179c64b11021c36a 1 515cc1cbddabcae11062f52ba676265114a44372719b9b5dcff7865cfbbf1568 20966d94502e95dffb45bf07173991a5c0ebca48c0941c8c6705f7370bb2340b 0 0d994e0088554b40c9b2b1283bee325ae62d8acf6f12c40fd63305db818eb10587801376ae209e164aea4f23986b8b2df279dc71d0df51961a42e8e04c3c7e00 +generate_ring_signature 847a7cdd3eda4d087626d16b975bd8dea19bd914d35051759ccd76080649a606 a05d0004f793a217255613e5b533efd58bf1d00e9ffe7d1062aa6eaff00bf614 29 60fa9da64e6873d5585d7c6b445aa994181e460fcf9c4edf9c2562432034c418 319cab68723c9c65b13df37ec1080812e182838e83f12a49d72aa8b82f8a906d e0d78f852a658ba8e2812978927a42caaad783594e463b73d25bad7ebf602a5d e5d6e07c783c40cf86479b179ae2c3064df13826f6ef66d1b5bb458788f628ad 97d175ad6b1daeb14df659240d2e567b269604bcbe62615efc1acbb3ebdad4de 5915b9e450d09664efa12f6477a526084e9a1c16c814f366e4175cf03f0bdeaf b08b9168207c344ec1f1addf104b06f4d396fe0a703c6fa22676549e221a9819 e28dd982bb083b405c5888a05b7ff932026a2d163febf55f7f8425df7a2381e4 b6cc0bc087d836d4e29e5ead0bfe51998943e147c259a851e138e931d6ee2cea 6bc6641ed933fd309190317c1b43bf34a7fa205b2cfb041c9f8d51da1775c09b 2438d50597d45379e848462033a037b7281eb6b3acd259a5190d9279e79a3d15 eec728d14ce0721d82e552a13d446866f3e43c5fd45d8459f6517aca1f703e38 6fbf0ca4da28ff0d2457d63f48864662748274eb304d6c22e3bfc83296ae0deb 51aed9ec8aaf554276b3397a30f18f76eef129585a5ac056ad9db42d6b062ab0 6d3b31ca3c9fcfc03be971f1107ec82cc5f5be67a0cf280c899ab566ee3c3cf9 acbf10cf496ccbba0ce691cfcfb240d1392c583288e0dca2b562710f0acabf5c b227447474e2fdbd382e6dc62061f4313c040bd951dd46d380b1fc4b8dfdb341 93ae8143cbcd9604e8862ee5d5942e90114e5133fd55052cd2d9c266a858dc85 2d90f8a4ed2e98285e9ab6938ef20da123f365b84f3b269b3ed03dc885e2c86d f7a9bc8f7901886e7f5b6a62c0f09022281d213e043df961c9bc61554ef4c8b7 58cdbcbb72356615330903011bf7267c8f2d7d61abfa88789d43567e51c7cfeb 742e0b7bfc9382859b7531e43e11e99c1ec1089ee901d502f116742194f78534 bed2b49b3170073561c62fbbcc1397c1e82ec0a252299234709a02b5badbe17f 6c7802b9d92c53b2b8ec8f761a260e680f92b4577485b5f516fc594984381047 3f32e6f5e41eb10431e1113916f94976f4fcc9db76edfdcde37cbd20a22756e3 9031e2a54db5f2d4358cc9486e5b25626c40afc5c43b20e260b0bc301d85bc41 02dca47cae77e6ec54842ae1a80f341adda1e0f5f78d016a06d1bc5595b7574b 65399dff20e45ceeb08f30f42a1e4f45c7c086e2a5f5c30f0645acea610cf4d8 894d72f759785abdc31f519d816040dedbb4df5af332187e9265eb1d4051da06 6f6da025d6473c5c0f30402add3b401e177f144bae5f907af5febe3ce32aac0d 7 57a507ed3a677ec6dbf95dbf7a5ed94c0f933124e073ba5b959f3652d27e6b073cfb78982410780c2300f564c0b4e689530a6464508f1d52c361225f3403b909674b46560d717ecf83896f2d7f9288cfdd34cea3df36bf12747f59c8d176930f1fbf4a13694628c4d238308c5577b0d42c1a7ca9aca6c623e460c6829de02c097ac48ecfdab55f4f7a43b0755749b792c36f2083c35b51e2af567038cb5ce90ae29c99d8b0bcc8d1d72c31f162832c8b8289ddf4ff393e790f7c49504be78e06cd638dded60e3fd27815e03ad7e1cb9a4cc2c46df00fe0719ab0a4f4c9b418065176e8126924f3dd323edf30c99a39e60e89d350604cc47554233e02e562590696dd7fe1cb307ce6d94d5e63f7872f751a8bb956b111c5d02efc949165f4b700fe766276c37bbb7d2075bbc2559e71cae5e42729f1419cc7f34292b8bcfb750835395b7271f667603008f358a423b3effd543525b7cd45a9e2d1342619f0580520051fd65bd303470e17e6b57a1de37ba1b4b53e403ef242252d60a7b626d2094b0a6751bdc36640511ca8aada38d1c80e97b68b9daa85cc04cc66aa48282004ddb1e09a179c6a011e39d42bb593a604edead19b7283cf93625676e27883590efba0fc488666d9535ac94c4f7d7e99063259d975957777aeff435195196d8401126ecdab0977404aec36f58aa1c87cd8b08835c15a88a7029381a00c45eb9708a113ed83382e08f716771910f88f3cf3e9ae50c7591527008482cd91bd0a4808d30e2258961fa2c08caca1288a766f88352bf1ba5bc383a28065ec63feddc1007e259ec20eadcc56a9256aac2a24f4294fb64ef8ea0d070ffeee714f67a3f20cb41582b5d72012cff3443f3aaed1a9bd2b83ae4005f7d1c7d6b48fa747546906d5186c7d26a5fa4a8f98b2bc74a541bfa0ea13073fc3549fc559046efe257e0ca2d4d75805e9a179ae82ace920c95f817954db949020974c914b5414423dfc0f440f240595f3d3d8e2b596a02beabb0a98a41e33b1c1de7f93f1275cb8395f03c0b02c94097d4b64d805029338fd15018e6104aff703450e82ca501023e29209b10eccce95abb990080a662dbcef3eda5ba29e37953583fe398c345fc5399d02be48a37bf3bcee1e54f13951099deeb0a95176225487f5e0d6fec0b28045a105fb739ce47c1a7029e70f78d1e9558d29f91a974890dcecbfcc38bfd9a2446c0e87b0f2767b6ed56c8e57cdc6bcb2cac59ae9e1996b11b50f96cc0f083bad6e007116c993820c30c29c6c63d63f25d2ecc488378f15598cac622d8897aa0e970485270b9f0d882926588be9b46b2e2fe2528fac404301488c1bbee3fe2fe85b015406c34ac576e2efabe850c4f364dd4f3219c353196251ac4fe4fa998148b00a36d304107c7c64b4b4e9b0fe6c140638be41527302c0acb9fb51ccd5746dd20c1b7538618d428e2cc35d6e74cfd8a8198d8f193e91c98a9d56c3f2f89cf19002c8f96a047328e1f6f68e6e510e50b09f9a5a847fbda2f922aba35edf111f2a0983e741ee2e0cc2476bb912c2df27fee86c8c0a2640894b578a8b67fb3064a0090233a8bd6310a39a6075cd752844cb5ee6f924b410a84b41542f17d88af5010a3b912e5e37bd4ec0433c6429e944b0e1232b4ecde6bcf1b96a6d5104d770c2044fa4d1c3885bc26d780fc66a322353888158d18f6e089af0b02165d6f72d0006ea36ffa5f86627182ca1faddaf9e86d85521e3baae571bc0524987513f0b8406d353ede948f9920c4172a12143902caa700e7ea9e2d91c8dfb681da16ac0240ace547c18836051f38a34f8c406ed36064ec88bde6712d7e6cee851fe4ca83b0fd6536d7dc540a442fb92a96aa0c98f3db85ed731608cf86d7329b8766bea31053204e0635f65d7d55b65c76a1100ccfed34ede7a456872636d6ef547040b5e040aeea6beed27a6acf5e4a0f91c56ac29b819648959d56a06e822046802687e0aa5c4170953888b62db3b528ce3e2b4ce9d86b3a6bf4c190d589cd93865eafc001170fdacc5fb7dec5df5254f7c5278beb2bea0875b7043c4a5d04bfd7bc4400ce0fa5a3f133e33b4f66728191fdcf2e9994773a6c8846a1f8f21fda4993b2c0378686f2cc5ed21e59afe37f98ce0743b92143c0e83457da706eb0efa82fef60e6d0e4e72da366d9eb614207e1a509789f414d1b0a05a7c8e91aaf1fd4550b40cc0d59139e181bdae41f9e510a650014bdb24df5d9b61b111e408b28c9ec5b808c242393af934775d6b7cb48f29783e07fecf21b3f7ece63b712869d5c6dd9b0ed47ae62af3517698f33abfea850b1f34ede4ea89bad89919e73ba5488e120903db1ab87a677a101a03fd2cf2031bd5f27c943966f4c38bdb2f8ac3b85282260c1fa7be5014d236465411f906db6826391ecd77703442c294af2c6c19ea347a0443944798199b945a432025b3d8b1b6e07843e0fb424d8677ab849c2287dc3d0259d60a342d8607a23ce03776aae6d5a19db6ff8868071b9b76d90f29dc077304628215a00615e934966d1f7b32de99b6a8e6b6f82ca85350c25d770367655d0eb1a82125d513992687f26d0f80aaab57c924035843514153bc3476b19ac77000 +generate_ring_signature 21b7918f07df71bb61eea02d6eaf44427254d6929fed711b69702a07f2581ee1 2170c653c773adf0ca992a320751335723a37f418473b51e05f39f4c56ca0158 198 a7310ff48dae857eff6a14d2feaa21e9d2002f36130b16460b6c39a4a7f9fcfa 638c6ab8292f8350eba3e282099ff5bf2157e249d6d8f4817c1710f650107663 15a1047de62574f925b50199dab771affb8f588651f52d19fd6412c40510ec84 fb40ef2ea3d9c88142c8014b364e0e0c7a3c588e5f45c8588e54450d51b426aa ca504e824c28187e327b5d7ae7199a246f73858407bcade0f3ec9b4d51678d6b acfc1fa1a602a4e8d7b40f5db21b12cd4fee3db4ad9dc873f6b2f835573ff911 a0c976e070ae6c6ac4950b098f25fd6152cce78b02f9c781500fc12714ca63a0 4bcd175516e2d4f9b189dc916c29ea08625a10439ea0a81ba3ff909ecf188edf 8c68075275c103c3581e9e0c3b70687278dc986cdf603376d8257e4d5d95808a a27f6a62d4aa751c9240553e0a3997eb518033004ffad5ef037ee51358bc6d2c 738354933226891098ecc542f68555f2d16326e5dbb8f8c2fc91db0d93db6c11 37b94158c61cbbd44dca406bf67c8d4c13e7d0c8c7e9d6794d5d29f576c477c7 dc71ccc63377eaa777e6f591ac890132d59e63dfd9fc26d1ac5d90e995fe2bd8 a9c3655c5e63cfaff27b9b7553d34b8dcb632d8d7eb60685904c589665e02996 35b199d68a146841cc6b62ef32f7fcd470c6ba3ac20bf4bde67ab988875ca553 7e00d706b974eb2cdec2dc4de1e71773dc7c7dea234749b3dcd9cb6ceb3d68f8 515e89a78026305838e4e059b0ee9573c61017b25e92bba60f61ecfd06118880 9fdbcc0a4a7b68abb0cc94571b407ebb3300c1a37cd1d629dcfcfa8ec982afce fe328fd284ef8f8ef08babe0357c39c1afc76657b3fb3e76948c546dadb5ae55 473046fbfc71a93af79fe516e88dd2cd2e4a129346fdafeb8458a887434020be 76025b240fd55cd3f0d7618cb987353c22ee6ff017f68aadf246af80d8f53a1a a3e4ef02949475560168d74e757d636ce95390013a9f7598e5751c785a0a3558 ca46eeb8fbe1b6f71eb46039987aa3a0333b2423000e28c8ef91bbf96574b5a3 756fc67e7addf14dd110af278b6025f47b721604970da8af89988004a74f30c8 430ee30d84f2bf7dd3d73f6cc7d25970b0da0e44b346203eaaba6b87c8d1bc49 f0bf365b8ef1c4af3c1489f969def37f165f60bf90c4b1e7d1e64caac02e0d00 90d8d60b866aff84be78562d69efb7c75ef8ad43a6dbf8180c7f3bfa55385f42 81fae7a46b3206690ba6592ec7ea31908b6b7426eafcdf4b72a7d867db80c290 47dd69f8405178eaaeeb253b81d9854ca3a5cf4dee853c9f09e5c018a888a990 3dbd9c96886f5ef5ea553af02f558c12699a62aef89f0959d36c11b9613edb5a b6e92ea527b2d00198bf9d08c2349346bb9d2e52f9a58f6f21886762a8bee77c 5137c2a7ef939c6dd71c516956c0bad82ecce452fbd92d80ad2f893d5db044bb 83b98b57a098b4606091163dd68af52900d995955054bfbf8dc5be2e285e67da a34e7a7bd0709f83d3e8edf3f4703e8e78f5a8328b8b537001ccd78a1fea0099 04bb7b526f22df2a7fdd7dd6d96a996dfc840d3c52e51407e6e02fb48653c17b f85f3534c07f3ede1fe71fa8ae9c41a7a6a8ca0114807f27c3a648e67d010c0d 30772180f96ce761ddb6bba60e078ad2697edb3b6368fd6b5532cb556a14a927 246288f7cfa451ceed0911a552bb87eec77673a9ea63868c95fa1a5cd2595d28 5ed823adf2b16c339daf9a63307143086bbd5d9bd48ad7884e12342177b93873 98d730c7b3ecf9a20d36270912edfb78e51f7d57783caa5f0fb73aca4a98faac c9b1c8b87c927d1ff20e8e11be50ac120ea712d56c79bbd2b0b4a7cdc380f0e6 e016f3e3bca138e242edf9b041cc9fe41ebbd76758fd4648b617c8566227d19d b4785c29d4cf5ec8136a91d82b37f00d32cd9f5c0cc4ed9f98d89e9e12321501 d7530c1336052f7fbad4f88f42f7b93a70d824ffedfc0c677b021ba884f54a2b 8a2b6f62da42c1c2345040a426a328224b6e1dde8046031bc38aa198fc946495 8ab5343f36337e7292f19f4f0cf0ed20f7129cb685d46960181ef8ddca615f6c eb77146a3a92895571947e4624b52f76349eea5415a1f0b64cafe44a1d86d427 144403c29b2301fd621b2192d294770c43271c4b1a65aa8bed9820928939f9e4 6fb15a7b933b936a2b00a1c574f114c8f1fb55109c0db8fbb1f6aa0cedd24411 5c098c6ddcc9775715a8712cc941dc760043b1be592cc1e794ae2df2674bd12e 3d3aef339088b60d7de300b385eb5740bd7c45dab071724717e85d10dfac35d0 1f965c8bf7cf38446d5cbbca496b9f4e1316598c9714ba751abd6279ba119fbf b50c8380cee5ab2db21d19d3790fb04dab6abc77ff660d9249ba511823270917 50f3f18353606ecf073b404fa9fd25dd89081fb2558fa739fac549332d81f426 b317387602d238b8f8e60dd59cc63418f3c911bf08e27e743802a6056d7dbe6b a67b3f52133c365193b3d0b07a770ac1a9ae2f968357f405ec0c5dc764d9e89d 51fb034fc77c16548c523577fb83026394dffcda641352e07f261046aedc29f4 cda39cdbcdee442b798ac1c3eca2c9fd9029387c5b9d6e4931ea007c69c1438b 5eabf6be3369f04af85cc3d9ea07eb7d36d5e8c917bb4ac82f65f783087fbef3 b93813588e0e1c30066efbaeaa1305afd7f3bd335fce47e11eba8613c2332277 2ab4bef429a6b5516c179036065c2f051e75cd0d39f5be376db50fbe7d7b524c 4ba8c45569fb7f9633d85db9c3e614fee637bc57f7d8366cdf43384b1c07d5ce 1c6be33f9df30233ee408d93647939aec0a74010acdcb1aadcc828378bc2ba7a 3a5440df19aa23f49469bb5a49f03e94dc8e1518f9acfc64d2992a424c3ecaae 9e251605352bc394ae6cbc7075e8d83fd2c7b8de90c327a3c3682e1b146fe87a 806ad4707c67355f8cef4711357215018aaa16178497d0b7870c27d8319772d8 f6ef4a8771330a3b101dcda998edd72efb655dc5a061dffa72f20fccce62a05f 458caee8a3eb73594db714221608f3ec2e8307b7bfe4ae6076a695ecb329c105 430bf3feb7d8c15d59db56c928803fcc586b1388a9f55864c9509af0263b1583 3c481cab8ee77c6c9182c23a0813c673b5a79f9e39ba968911926127b90fecde 354c79b857a63799189c3fd2ed192c9c5ad45649389191442c4d5d3d653430dc 06f2fd30509dcdbeb9f1b1dadf07a2c1a0f07f0c09ed89eed7aea5d177ec4293 185158f86c6ae379c94c02a972d6a2b7b509611c01fd464e42d1f4b6108312cf dc9c395819a1a1a4d441c34f826100fa164d746dec8e4ec67e2957cdb66bf496 3b2180d54f65060b21d0e3908eb9e61d51d401c3dc6ba7f9a6b6601ae9fc25da 1dfd4f86dab80474c115ced9f14e9654b8c0bfe960d4783ea749a04af99b329d 2836b7ec30ceff00da114f97fb42827adae4f851c960a82f3afc7649b15f9af0 e2f4901c3f23a57de9bb273e7c475a6e95cd151b0f124913ff8793a54e86b00d 3dd28896b87d391d35d51a898a534d20f08d7551e7b6e94bf1620e35016a8d56 29dc089a27b31456ac0015c122b2f01fd3c2df6a7198068ade70e56790b5bfe2 5f9f159b1955da1e199020a276d8775f5ddd405986545bfaa6d760be0b4f43d2 ddf00a1730b611dcf862d320af05aa81bb4f514d36c7debb5ba42e098a1afcc9 68e9c66c54501f39a8a15ae6ae4264acbab0b5d80de355e451d5290baae5c5a3 7b408eb753d2fcaff19e4660d42d3bdd8ef59e2064b85432b324090d59131996 6b0a02f9766c59032201c2c5b04453741921cd65d5150740d99155d2dca6e647 5c06dd72b563394a34e43ac353e54551486d2be717327ec3907e4eecf84f389d 416ac45ccdbcd8b039df9243151e7b150d9c8d5ceb663049bddf4fdc5b13d35c eea9d96242a44976de1526661b40a94932999919479b04d5c542b354f7fca5b5 2d3473d34a84358e2088f6aa6d9fc1035e3bc513ea613fd6604589f0befc56cf 33f7f9c42a7a1f400f64885a3b8f754f7a37cd240568ed89eb4b3bcfcf627adf b10bf05f99f3580191561caf04194fcdeb7b2354aba272159f16dde7688a458d a191c822cd757e136bf17d7b3255d2fabd55b92fa07c3fd2e7769290ccf759d1 6dccd76d0adc94bdc5a3ef4530edb326e205dacf527efb8f46c7be4e21ed9a0d 6f6c9c24f0a9dfc75ba05a829af930df9c90641e35647ac8d9dfe3bf162e345f 4bf557d5904b29c5ebfd6e8bd11eaa8c1ab125a5617c0e26d999afd1da4c69bf c5e1cb8996e6e9c445f5272b25f89ef9f89be61bdf71688f066a8156701b3c14 70e3172770643e04ec34ac004259f8d2219259abd222f89650f41861d47b1fe9 e6be521972ea378c4cf5c41d0776217078f891f04f630497c98e9e4cdcf0eee9 5bf7784a3925c89933199fea56841277e029bdb8e4dfe7ac78b8467d8f84c97f 70f5ad88720513a888301c9bd51a0d5dbe12de43df5d52293153547de0d4f8fc a62e3849fe1b727cf71319308e67d346bb3fc735e27152893b63ee238d0af39a 241c0ba2326a2cb22561110bfb366b7e6a6eadafea230a61dcfd4a9f6b4dcba6 568c41fd4e61caac83dd975631219405341201cc7afa1abc9853ae67a0a80713 b50eadeb0d534b9d1d089862655f4fb15c60763edc542dbe8b55bcded4e16027 f96b13a63ba656428ec73c7d5f6b22a5cbaaf54426b49252428af975333aa980 087e4e0d721080d22ae9b7163c846daa8f5b589a6691e8963c5da8025f9624a2 e24e5da5e60393b9553fc0a0b7a519fce15c3909ed4d79b1204a67dcde2e4569 8892499bdfe206daa5cd2355d77651010f3d4bd3dba9d9f031bff0754c270479 decfbffe3e059ea424c13a18e0825f19128bf74d3bb8bf0ea9f16c77e2ad2e83 cdd209bf4caeeb585551e50944ec07a319f3dffd5b09a012d18f5f96468b52d4 a85025abaeb2656c57b586cc1b592d49b01b6041f84b7c76d74de7ff226361f3 4698f35cd4064410373adcf01d1a5cc9975401fdd593451d29c8fa8685284791 776ad642d6cd0f9c3272ab6cc24064c5ce287d0c4c0c970bf796249515244965 815a7d461b39d605d0cf09624a01741b100d7d8fe7f5a43be593ac631e5f1ad6 3e06f180ec6b34f02d9fb05ad6b1e18f61c86b30ff481ddc5998f454d1e66557 053342a00d7f7e7d63094f10f2db6aeea8bc2a4604bcf0780b06f670780f5fc9 0e0b9d2d83b917845a3f5e73a04137a499d9e6fa8b867ab98bfa82b5fd76ddd7 8a7478a0b93dcc275f706f458a0f3f7022ac8812b1a0b3fb59a17ff33887a926 2aa41062284cb512431c3da7a24fd4dfca3b3b9d4746e9c281f0a6530c77bdb6 d2aa71095261507fdf7ff02a66ec2f810fb4cf25a1cc061f2fd9e6cd991d29d8 749d7d4fb454e0441786b0b83405adc7521b9133be1e9069e98b0b4a0a019742 9402fb817cb1bdf0ec3b3ea7f0e6de5af7ba40e5dc449a4604ffbddeca3d4bc6 7fb5ad8c1c39dc05b6b9f5683b0bfe3453a36ccffab3d7dfe8b0b24c9affd6eb 1d5beb87c516b2f164cf9b133359af4170f80919ec18b0c32130ac1b72384813 d7a29f1eb4fbf3d5e59c92fc82de7b21ae3dd5592fe5bf14ca947cb07f91f294 7c4414a285d08785d7ea218d851629f3ea64cde0db5f122a7d1234f2846679c1 da461281fb75f952c2d820e634628c9b7ad8bc85b2652066514dbd5081a8f001 24ed659f872fe2ab6ee3ad8e503aebee8871399ef6e8173a9a93f3c927c9a006 302b8bb71116213bb79816efe7111d60102a43e2553085ac726b3e9de9ebca63 ebf8a047c74fce459c1cfb3a267c973f22be621e82ddbdbf5c0fb8e94d8dedd0 82ff33c38beeae7ebc65ea166ca06e0838209719d9f68574bb0403e7a07951c9 856688e811d72ab66cf00280841d83d21d9a5982f971ca1b1406e5c205ccbeff 9314feb63caa7c71cc0c2e1957cd334732875c8da47356dae4982c32eabc902c ec90e690723155d6a5ba149f7070c142f367020035f3c9f7fe394f4c67ff5bcc 222caed12c17c95bacec54ca61a7eb3e37710521dd268815f025c082fa8249df 532fe8d1a928b1715dfc99a1e2fbc51fe9dc599badb35c31bbcbaeb53377253d d41e747309374c7b1d87c86affee4d0747b7a1d9fd1d127b54891d896008c6c1 89170b10570cdb10d9e191a8a73cd46f8b9698db908daf7fb1dc9c7ea34e2c92 4c7c8409f431e936708106858f52c7c54b59bbf7485f66533ca079bc93128903 e2e9f74f6d1ab74bcb1c276143e6bacc3656fa372ae0c55d86365d4bf87f387a 71370d72ac3428b928fb2eb392b7f9b08b1e332c5571b720b1062e60600d4566 3fd75f265802ca0b4e7dc1b45f2248cda782bcc3b60571b72ef62b3980fe4801 094c60456ae08e383c95c2dcf3bc2e3c067762548d57b89bb7bfff28ea5de068 af19c103bb8c17788e90adeeab90d5744cf8f7272b83c51dd1c5076e9da6568f c51e9883759ff945e2072a319879dd1940f8298b2752fdc99c3eab5162a9b9be bea441eae3c9b9554bbdd4f797920a478705209d2c837dfe6a43f76df9102375 68ca55b4f18a7ce36e32f68f31d6e55e0f6056eafe2066d1f4f10a1d36e4aa61 746d492d44cdee213b7b1ba63f380d3582cc84b187c115f13489cda5fa7e56ef 89407326a649e5a0904d2f02dd4e488f88a020c40a9f91671fd3f7c2212f00c8 a28169cb023c0f991bb0035546a78d954d0cee7235bd52bcf88a5df99b557f56 19c17f8474d5daf47659a9864cf1af09a594663270eca53da879650400469a92 10ffea22bad2190a153341c2b0d21cb3a4f907b8a7e926ab8d0c41382e4b8058 5e0f853d144bd9e6f460d06a4a3a39f150448b88835b4532c41b2587fd4c0af7 31754c5684b404654bca97ea38f2c00ad3e5f4ffdb97fbc8668ec58694724d82 b32e6d9773921282689cc369c0312f5a0451e66ea941e6448c98f8e981d48acf b147c1c3510eeb037c72cb71dc37425e963685f84f32a50cc01fd408d0bf4d20 57d2c9657c3e9a7296bb505297e55796b77f5d3db2f4fb1f09d23771ac62f398 b25cf9566236c3997d4d997f3d5670f676c13965d4a4a66fdf6900fc4883618f b7b93b8daffc9d5a4e47f4757a70e21a66df2f452bef667140299482f3173478 7098f7acbb510ee3f9c0499b2395d96f852d21376186f275f02cd7b2d87faff3 8c6ece212cade6da775e5f059b0efec5bb6136903d3e5ce07edb1ae45854b6bc 94887bf7a0fd4b7fd0d2da3bd78c13923ba3416a1e4e84c90aec94b860541a56 176b865ea64c0020c7e8371ffee45df70ee0f2bea422735c30201ee2aa31771b 45b58bb64bac42231f7f98469abbb0ef075568d99de4d3ebe2a480fb52cc6c95 10fdf36454f77b8909acf5478166555bcb2474be93a5cfe6d4c882c05e08d3de 4b0d03f74f8a5dadc9ac19dd2b0811f5b73b4dc60972dc052a656803510b8e86 c275c94455f1a680592271bbc61593c4dfbb38fbcad68743c1500cacfb542d03 bbde1fe13a989e8ae0ccb8260d4c1f3330a337dec7cd5c20dee2ad781610329f 50c2ae0be35cad3b9f25102f68b7e69310e1829d36ff52d23a7a000b31caef02 35bb8d2683e7e25d64547774b2c9e8553c295c367129a53cd2ed7447393358da f8e1f760cc5b69685e8d68d6d023fd5760790bed603f69b3148fb4d245d07e29 ea4174e4e5a6844c93f511af95d507c45c939ceaee14b0a033f2c93fe8f5a040 4f117a7382d9d5c50861b62a8ec5e5905ffa6633ec41b00bd61d0ffee78dd05a a88c98a8ef1d64f1395a7029525d0de4b131db3cda25b1a401c723c64cb5e357 617280cb8f8e0e0f42c62c53c732e87ca4fa192b578c1120e40905df9e8d8194 c409b94d1cab6ccadb8460b3d131cc18becb84159897e15edd646ec4dd4fdb9b 2e42617d8e1bea79f0f399443fbd5f15947ae5e52abe17726ddb03ed0d256d86 6a73186410df4cd8670032cbfb4b62b0b7f95ba4d2c3bad16d5a053f71515852 7205bdadd2305aea4b0082ec7bc8a2a8856edee2560e02741a775f7a0ed2e1b2 cc7ba0caffb42807788c1eb7944ab97f8fe62b73c41300131853c968347864f2 78d4acabd2f716af0d52789f27bf35ac8bfe3b95ebdf90437010ef89324fe1e2 98198945989839786c18edf339f538c065e83985d97dd7eabec1baddef389457 603d891e289f2b8ca96b43ad5c54d284beea789a4ae319517833723feb4ea9d5 8eec45e1c95eb6a99c6223b40f6b9e740709941c848df5ee5c4a1b23f100e68c 948afeeaf126f4fe582998b6cf014b9ce21b3a7e0cd439f40be5384f5c7ec905 2702a8ef3481001ff530a56006930329e095a1f73543b515159a0412d53303cd 1d0c05dcbc95d9a736871d7c12f9bf6b0455de0c6d19a17f90680a39e974b96c c92cbe487bb69a8bfd16a8fd9b4f2c272f564208f1f6a39694ef3a72b7f1c236 5d8db733373e9343d771cc78b6f7fa5b5fac0e5b7b55ef6115c7611fca121150 ff9701d74d4540e1b6494044cb26d0d1edc2c6df60c5f646753b256ef187fcf8 c414793da4b592458d92c8116978ae7a5d3bfaf0adf1a0799427907987098949 83184b7d1d49adaccd9662c4004306d458a42d88d16088ee50ec8d82c9d23256 35905e97de54db871c52e900b7b28c9524050c8508f547ca355122781dfb8dda a177e03fee74823cd5498a30bb30defbf7fcb04a77c7a03ea9a53f166196138a c589143a5a14b61399ac8303294231661f6871f01fb323b645415f9a6f854e54 223d256da69a41c4391235895d0afc14513ad9b8bbfa6c19475a07287bd591dc 6da1397c2980f41a9802a535ec35e3c605cc0af558a2c08a44435c086491c85d 2570acf82514e472c79a88e3baaf0f070386b8e68f783292237d920b3155de1c 59d4fd0553f2577e6817728152a7c6dc652fe69f78bdb2a95feaaeb37e8dda0d 65 93c48adbbcf83357c4d8bff882b466e9b49ec773621bc22e7d6bb9155ac0ca003e4afd8419fec08143d5924585375929c10c9f6614613c18cb86e9c32257f007c6d3d556bb6b80a269af77e665c01a76e260934b35f179d98a2c03b973222b0a7a48eb439c17d011e66708e35f8302d8612af85d4cb941ca4feff430fddef001155c30767941cedda2027618f381cf77a89801f8d8ea38454b9f98a5c330550f3a79bfb010d0e451f7ae598c143c69d8bb400192d0c5dbdadbb183a08ec727019f521d7aa990524faea91fc83950380d37becb055809c177ab0b28cee792f20e6744493028bbf4acc8f0934aef8a31e9c647a5948742e694d088faef8f5f10025ccaf3eb9e6f00f652d92f376786066b34a56dd2a96b7a990cc03bd5e3d2670bc182ab95bc9428782bdf3d24f8efacf8014a5da84cd0d43d6c55b799223d970be2610fe5c0a06b48fed19eb8791315f88221416c193fcda5857dcdbac38526091da71286ff9f828d7dabdf409014b904a9ffa677e0f5d5c0ce6ef97f88860a0bd0fec565ad9bdfc070eb1aadfd81995549dabcf1ad2261501808b6aa6a2b820fdc5c89118dfac5b9b2d8be5b8c5e0e649ef0e3b514e6400aa81a131f985b180cc239cc506f5fdb39e31f953d45b3856536ed5eb90904e91b43ea15aecede950853d506cd5165102b11f920a9f25058836404ae1747fc8d1fb20c6837b7fb810791a0c08285d6f0a7e36dd001103a0a8146da6b44cb731706f10e08deac433100598d8edf42611df4cc7ce39a582129be8304f562187e8aafbeaf885f9680c80911c10414428f2bfdf99191225d6767088b905a4b596dd124289af61b099d6f08d47e7b9a89e2812dbc0f2a49680edd181e2bebb5e15fa87f01e9758ebee6350d7c53abeec62f03854c06d38c339558e92d9ed9b0df4d895bade5541947147c078a5d984a00b76a6c82fdd828a0631b4c271befaddea4ec77982da720e02d5e082767fbf8ff0ffc90572ee67f276758591416170972b6501bc83a009286d1cd000c6f7e3b509c26589d2782cf5e556c4096b68c61d72043246245e57277e240032143c68e626a892e073bef554aa840977d9e637098dbd3c149fc92db141d3e0ec4ae1c4300b47617e692f63799ccf08faa33cf444dc33889a068c8112f11220a489a634cdbc16ade92da3bdc970926336ff3c0589a495115eba06d023fe1c80edb81dfcee82bec113d7e478c54f89a25c4d87b33b0677a08ce1647da9fd5a70d85f5b6789e95e8a9c5c54d1ca3d56ddaa0cc56571e98dac6ab82455d1ffdae07c232de878e49181acc0b2cc33eb51d02d3540cae91135333d96b15e47a1ade0285267963070e9303e693d1f1cdb799c045a80ce380cde6a08a194e69a7db16055c92773704fb7fbf4929cb25623be299b398a6dabd6d028014541fc54613000422bf12e32d5fcd899aa4600b0c13e03aa95b26ba1f976b6b33a735af0a94e2013a53fbd3de17175445efa6ae467974a2a92ce559b80cf4e1566c06d4c204670aa41f160276f940fdcb42be1df0f5567e6d50f0cbb510f75655c770808825260d32376ac191dcdd0f9fc25abfe6ac8e5720f0ba12c13b473da46160be19e34f0b0d09e59545bed2e5b5c2523ce95c2e8ade3ee566256ad9a2dfe68e044c28d80721dcab0a0410570204bb849d12f5796e5bfe4b826e3c0bbb8210fb8dcfe1ad09a77969ca81e43525c5e9de8126cce2d34dd44dbcaf9807bd48464250ca18660161e0c2e111d0682be317670b272d2d698e6c4df1af8eb89daf6975a1710fa80a43bf38befdbb32382c28495af05e15623b6a9c404835da42f6d908d7b14a7b08a136dbdedb979f2b1b29cb9efa5aa58a7ccb839481c505ed76acbe83ca444f09cf15e2ee6139a4f56482f974ee9bdc1b72b315b31a8f8f40cc799902c93f220f30efa8cd4c550e6954e98cc93edf724a803e9b1b7c59c9f3dcd2476a5689590cb0a9e07dd0b4671d8ea129ed9f6a8ed7bc182f549b1dc87669da307c062088050dbc1feb24ef1ca535a8e0d16aabae5aaa6a92edc7151365f61b8139e3ce2e013cb588a239717d7fbef9d6aa0a46411dc3d26ea264d9e579509e45d6f7ac430e891401287e65713cd8939e85b4bb6eb292382d72e20333ef1e04feab76232b01e2b5e39c6d76cf8e678781e13cec166ee0405105174738b535d75f49b133f50aaf5ea2e08ac22474622cd7ab47d87d9ef026f3b4875f9206cdd0b4fb67e7b503ab99d29c2abd8a57d19c3b7225fa02eda9f53479188a5abc4ef7c47b17b0e20cc7b9e6ceafbf811c9b7cded83d6ec2ce6265e33362f54dc3516406c4cba8bb067b8ea2ba759ed56b60a3bd77d0cabd871a0d90f5dc4687e1a91a56ba5c8aa30f9455d249122b3e9b266b251ab7d3b3560bde4ac77729eef6fdb70ab6f0f3420d4c66941021d6b0f888459af5d8a85dbd623910f8d0ec9c8d8996e4197903140a18818b582c110b1e17a1ceb342e4a042344b5ba7e3562136ea695d671578020c8677fb7b87d8fd1750429ddca808393f73fe8d01df03215de4eb0f594f92a605212e90f5ba99ceff394d935c4343014f0d25d855f53510e3043ca5a9003bca0902b7459401fdb868ad4e20baeef6a6b6dde5550037b9446102ac54d88c3bbc0cdccd86de85e691d62a48402c6c6120f5a5cf64fce30149e569e01a68b42940053829fcb64a97a4f5b72930c8aa53c589b77a7f1a049e8ae41db16e50098e5006a3d97942750f7131ec74910bee4355e9532bac1a8f0bde476a70a2b7e6105f0656bcb519cebab51b2b34f3e48790f04c981c3424e626a9cee484acfedd42230935e1ab4d9f09860856fe1a3938f348008aa004a92a9ecace3ab54e2dae9b2702c1927effc3e78377518eefa74846adc0aae32652be80b36344d4e5911a0df2036df7dbed07e7cb94a78a9c1c32eee7b54c81a80b8c3b5026d55bbf0fb561480a9c63401e53b9ef30484799209db38ca62fa8e6056c2bfb03b3f6805a1161ef031de994b35ad106b178075e375cd701082883d6d27d5759fa388307562e8596059913b1c893e7f3e156b98aa3e7c5f5fd2a86465e069c36bf90db125b1198860ca3d4947fe14081d916ecb615a593ac25024aeb307eca1532536434fa1d139900e9050ed7af73b9890a34b9e7acd17cab1737085a9fde11f66b54154d62c4c709f71d041f19618482eb9baea9b500cf4d82c1bfdef1808e692d634c85c592670a8d78702b6a6fed879fbb6a6d95ec70dc4e1d3db9e47db31371b54ce682cbb90f8b364e970d343b3bb1c324a5af0a29c7ce439fd8b75bfc95c465623b5ad6c907a64734e690bb24d448353588fd9390a3af6f793aa4d9c1a2892534442cf8aa059d11f4bac838da49957a15a224626d4ed8d6a4a5d45ecb10e6ddeb9a969adf0e33be898686ad6043ae392e01a8b5bef2076064b91d998a8c20bba36e25bacb013b8dae6750a0f85bea108f5ad2ac20775cec6e45a6f5063dfc228295f2f72106efcd080aeec05dd8b026a1d9fcd673238444975d4a59331e991a85032c45e106b02dc8eddebfe9330263b407207da6a304c02a27b9e8d0f4c33f59160dc8b20b93a58e8e4d0b3b4fd661d4f97a0b10038c863a4f3377db58d575d1b0ed523a008619ccdc28e2c6ad1d78acc92278d57a8f67b2f17243c989d806ffe59d470e0154bef575da6bc9213fc861f00b0dbc60cc124632454f326ebb0edbf5b652770532867e557d4f446881ea43af76f1fb8e63c7ee2b25ade32752f2147015a34b05e9e8fa3faf0ea5fdd4643b19b8a4191645b2b36b254157e273c9f2d34112740e751449ad399729c427232f19bbad4b21080ee37f7812bd2bbb174aefa587aa049a397458ace132f31682b42b50678a800f038266f590468358708702607c8c0b9dc74668e4adceb9365329eb3124df574a7301f380d1465f20129aff946dc40ff8f798a70db172f131d99059aaf02f41665e4f254c9118fc038cd5b8092c6300a821b6e253d4eee95aa27c4253e930280c4bf9bbf75bd99837ee057acc859708a9d71940c311eac800ea335c5d310e2e8a19596ecfe59a7d3531cdece333d000462c667537566ce1ded1c0dd80c6a70cbebb9f02927fec35f316d703f72e8c0fd74b3d4a98e56edfca97de5297c078d66cb9668fca12fbf03423a81cdb3a300d7b61e9559f2e94c329160fd948a5b7204b45355aa6569a3e233fa11a82d0dc0b559b57d4855cdadd13898e09753bb96f57404868dccaa0633f4b3e301c7a2b04147407cad47b749acddbc47cf5d3f307baf60b61212ddefe25e0edcff45996035726b23470e2034dfd16d66d94afad189c770462be9c376310e5eb0225248b0c24ff29dcec252b9843c1cf114a648a9231aa00d5aef14a030ce316d49bf03c05387d203e7e5d9494624da459fee468acb9b7934ae0085370637fe52b7ab9460b14cd0d520dafd6bc2deac6b6f1c13cf413ab5db88f89c2a8b4ea9e1a93aab70affc11fdee8abc3089ee6e1884ceef07750e84e8db2248cf102310de1eb1fb90529ef9d91a7d49a0b6f0f302f37ce9c90ba0b3262616eeeb07ee2e139363d560346f3cefb3fef6c230d941e02b0bd2946ef33739d306eb474698204084a9df50d02b433b8718bc02f6fa829cc5611bbd44edc6e8d6116b95cfe94ce40f570230115e15605c3ae43960c8855a435b50bab454eb029141dae3f0eda3948c0a17d064a12b1f40476ac9010c208006f2a8d795d4a595575fef8a7257163312956bd0a7adfc45a48f4146771713cf7c02385bb4d46398a269b6818be8e391e2b4bd20134cb5f46d5e77a9405a6cd8d9f9b5c0a118ea14284e54e45f4874755de3b62045e2eb67c18934e466ebb7e9fc3fd7eae3e12777e4d7cc88f0daf5fa4bed48b0a80d6fde30f428409f0ac45f6da42eea8a92704cf023f81180442d199d7112c0c1631d4ea6dff7a25fc2bb7e20fcb489655987c6a11f17843e971057f40f7c106fb406ebc6cbaa4b0c89ec9aadd5464d75b61b7b9747fbba7783cab8c352dbc04c11cebcc22b9cd0b8c78b48fdc1acbbcfde6fa95844d20c376c9951936b7b1057c4414feb1b11c8e6c202a73bd927fda047873872a0c8da681d88c71021101026cf7e33c1ff022ec9b564780327eea91519e662a3340c5ad3162a372ab528a04c8638338996fc1a3362c7f05c4cf1a6f74a5fa61a4f2a3dc0a3306160387cb0851cf3a288fb0f719da6b0bd39d73bd6f5aea2988108d7f47067c9712ea19000eccc82274c00a0b42f99b9b1d111a5f8561b217ba8dbff6abcc1f1cd33015c607c32c5abf3f9d1c3ebb6f31dd68ba054fd550511e909124a2207c601168fd2809db97499c12bd13a71460b334ea392d563d1d80226a003e6e945ba6cce2a5370da0026e4e14a612b7285fa13b8a5852022a9faebf32f41acfecd049e19d0e7709671bcb9b962392b13c2e3ec8a2828cb0dbb1abe6b4ccf15c1aa97dd85fe86600626e03b74ba14ddf3045c3d94535784e48f7e20711b6b3cb5af8616bfb65f202f1bb7fc50dd4f26a16444647726e888fc7171405e08b2fdcb54878ddaaf1d800408064d928a3750185c1fedfd6b10a1975bf367cfbebe3029328c3201e3c6001ac793dfebbd53e9633d213f3f5ba00ec363bde58c60579047ce155233c147503648a46c96c253b0c250830b48374b9116fdb2375d6eec013f6649f3c22f33a0ad452c0a066fb8129ebe3e2299907fea24be3aba9f9d6bc743c6a08d92aa53800b54774478c747793eb01de09e64d97cce9f5a4614e2e27c7be4a57e478f1010f0b22061f85a6e65424d788bd560f0545de3a3fcb531ed19973fb401b8411d0089a6d5ede41fce337bc5ff0a7a720c47d09e0c814ebf7ee7fc4c265ea19222e0df3ca1956c32df9642a8d6427e64b32049b78bdc7cbeeb28d4b98766a7817f10b7a4c32e548d8a412dbd7f5a7b9e4f53cd645dbdaa5671652075211672a6ecb0d12ef177b2bf9013d34de12d92b8e1bda88905b83c8a45bebfb4d3e257135530349153fcdf84bbda1cbbdd403a0bdd9b3a33bec2ee9218c929cf691a89ecf5c0837ab939d7fcd31166cf83c90b2a677deb9c95e32814f74862fed3f0da8d77c0a0073ecce0431b0bb1158474ebb47f9fd237b3c45c1c63427f65cd3d6aee0f6075965df8f4ff7d2261b767e848a92bff7a0b5477a8cafd81bf91f941b9790560c6762a4db9a3805662864cd9c434780f239532f963dcf037e8c7fc5dd90a8c40872a9d160cc02d3aa8cc5ee51e55cc7251bb7c16d26efcbde48250ac7a6025708ebae57af842db5e3f30490bcf3054b5bf29765275d36ebfa6ec14e6692ca7b08e79658911350f679a4ff16653c3a7653a6f6b996d75a31d39c9e3d8fee15ac05881b0d067849c1381ae8a90024690ffcf8d8d36159c89caa2075b28e6cec550f75f0d56f322fc053f167b7d5de29867ae55b39f500e3127dd5eabc414b788800d7a4869f8548a77c68403609874d7ea599f16a04c9af7d1bce9e9884a27c8e08d45600d414723507fab9735e06633d50352d102e1821ff4b981eb762048b710ede49b964af7acbcf4b6a64ed4d6732d706c773d49ba6d15d15dbbea0a1e1f107e4ad91686cfde00e1406a5727d392e39b0528a3d9cc8afe25c55019b648f1504675f5c655f3b0d5bd7fc0de79daae393941f7e3d6621936b38d75802665153095b9e2dcd8c5e495311516b6e9a29c68af47687f1e2fcfb0e7dcc3118c0ffc20b4f0030e725b3c797ea9ff31dc2312bdc841bfddae3a358081df509e35e32b7038a41c1d2a015a7479de99e7575eb1ac25d09495f3b2962679d897c6faa113d01f8bc4c637577d93105e09d07843577d77400b049caf01ab348b70df2534aa50032fe7fdc815ececc6055c8d665b89acaed8186f8c728000a6fc4a068e9d2d2018bc2edf6bcec75f602c7b1867dc4a44d86843da1e88ee5ac82fe8e646bd5fe03cb14e2075ae8c1ff0667aa25ed66d586538c9a2cc0c05e4a5cada5949fac0405f9770e5bd48b9df949c2dcb334fca76358b899b27aad42902d16368b2775f405ccd6a893b9219967feb9e6f78b65cdbeba2ef33eeb1850fb1e8c874331b5060394d7bd816e57bfe6d425c78009ad38d5959eba0907f4f623414f48a64ed29a0b3150dab4744e50b68deeddadbcf0d5d6a3f19357b71713795b9db801f9063409a5b9bd2889051ac8082c8406c1f050a3f7a876c32dfb3d8edee7496eeb470c038c544b91224a3e2278092d54eba976eecd43668a24424e6309c9d5766910f80a3a714c000349003201a98290cb27478a1cc3b0317ac491a77608e0d7d3aa9f0b3cd418e7723de85fbbf3047595abb95edda645fc9f8d5f524756a25ae92f65054b0c77e21df51b08ea79521bcb9125ca1d4e509e04a0bdf44ac57c9438b834069d6b058e49fd85809a264f917fa25bf18c42bd6e95f7b33f0e83667178d7c0035a31b535e410a4a8fc1c46ef3b9a8ef06cc8e0e4aeb18aad6fe199e9dea04c0b482d778577827c300e7f03ce6a94ea91e6b41f3170a6925d5b67912a483e4b0797b7224679b8eb9046a594b0b19eff6fb0ecc68ee65d4f1ddbeb99fc0fe9430bb8ad16cf8b5044a0c27f41dd400b4a04acea2a2ffcadc5d99fbdae288ae3470c75c8da1a399872cbd1cdc12d464f7665d99fbd1be64c35d16d029ae0a15ea0007966aef16ed991c5d4a42b3b18932d43fc3ccb35f6a1ba3ef1d41c0603ac350cd33241cbb9ee8d02517b23fcf0cddab42676e7a321107287133afaab9a5d820cc6da5fe00f2eaa6888df02005d1534855c27d061b098b233fb46ea3e08e9530df53acc8397c577edfa2d270052fed476c5d822a112b6c18c2da94b11fb74e40b0fe0f9e2cf2209606d85299d00961e68688ae637d73a5323774282abef3bae021655638e7e794ce2791257b7621426e23eda15900a51cf4a2b2ff06d1b03ab016887196f2924918fc7ac7d85d355ccdee64ccd37efc65f61fe08b95afa6ea707cc12cf4b2007a589d0a9cb0098956f6e773c534e5cdf10fc0bf595e315e0a10023cbed13710de59ab19d0709682e0a28b204ecd3f0e993491b42ace027dca90b03a61c06b3683280e8e3a6a59d45aaf3743fa0fc480ce505a0c1f8f750a51a0bb4fe3845c35c2c79e158125123f4eb6d062763aea26b5da6797b29147d82c90cc7a8384a2beb58f3909b191ca5cda1f90f23b9452a6c59ca88f28b9512e6db0833ad81ba4c035d1944373aa7e845b94ce5950f688060422422812a8584c15b02f6469a4314f8c65fb35748832a4607ff723cec81cf00483bbf6255d706dc8d0b1c4d2e41b5cc7b5f11dc642ba4b1b089726d61b5e2fd2d20fe6e19b9aeed7d03f0d5c389041985e7a55f5279d0db38950831517df9d963d1423b84b7ef2edc0865c008f1ea007294666a132ba012ccbec1bacb30aaf7167d9894cdde49541d06bd257308c8ee2ecf9b40f66892cca437886328e33ea0501d2ae4bd9fa8255a0ea68b13d1548020eb4a96a265fe2b0ada77f2c45c8e31f4d8d02c73e168ba510f8e9a7664f9b51a53a3f4719c702fb114118a77a886a18755cf650b74f510780dc7106e4c7b7796b6965b1b6b070f7570fe673fe5dd550c6054d42326154aa9051a6d458e3fd0bf430de5661e8759aee5f40398d3b2d04fbd767d36ef544e950979562bfab1663605125b24cbc31847b5f1ca6ce2dc1b841d170bb331da3e41018d341439f63deea85e184f2074dce5c7ac98ea6429a6088ea88a423cfb731405955b752f27f57a68beaf0e49f7845cf5be6802b2ad8d736652f8dd5240a8950223f25bb109f8cc9f0571ddd95afd80b693c08ea4967583430fbf49409df5ab00b6092f8d11774439830a1592c34fc1219bd3f146af29ed45838f4e9ce60b7508fdf12ea11f8759ae7d496e9294189ea5454407834a14765be3b879d5cfab880e51b97a28f8c03ac304e1c047b6cceb4b043f39204d85c16b62d9de496806ff0f3e64ca2a09768da9c8d87c1a48f6734929de357ac5443882b45f9e8a0c6b2805e8583bffbde9e414ec5c8828942f8a250348abc75b7486c0799f6f7cae46e10cedb4db291dc472948c5fc4dda302071395bfaeb0d9b835a8c93057b518ae240be119af0d5b12b0fb832e155a04292c3edd4cda39c3378d6a6de9d1f18506ba00951a0f872c11f979255978ca843314548a40c265df2da63a110b2b9453886807ee1ce3b5587cefd18b73ae783002cd32ce04f6190b61ce0a246fc45b3c875602faceb3e0eb3606be31501400d26346a6c927c81161aa43ec147343c607602e01258f3f709de654cfeba37d15464368959020480aa4801d5d4a954c7916ce890060393b1549c5dcbb22506a2f1543138d18358f56f89aa45c083c4ad2594c4b054825506b4a7600ace9b95e53fc6062b2ca26272f8186dec23d33b2ad49144a0763a155a15cb6b30b5db2baeb241ff372a3680eed3e18a74bd7037e588292450f96b1a71a88973a763f069a4e4b5862517fe63ce78a08c9a845478dd6a5f5060ac7581de41966fe04ac299fd6e165338cc84e99ef5eb2d3a922aa4a15fe5a0d0c8c2f6a9c9c66e8b56eabf5e59273751a4dcd3994c1f6a9d8c2b4cfa00fd70002b8c631a4b1067e3aa48a3be7386652d6c93b0b9c853e74622d0a85f4aeefbc013d43c6d2c986c6346c2d0630a3ecc57c3e6605bd405dd20971ea15bae56e3c00ea3660f570d1752cc93cdd6c363233eab0a08b39d866ac6915160e955dfe570d8c6c1570bc35f55e28f62f65be59697b21fa3ebee111d7ef89230a4e71de7b0d67faadbdca926d27592818e775f6b22a5e70a8dcf8773f3fb6b07b77c468a3056e603b933cc04dbb66ff167c73ba11c4e325796ca86b6963e46ee5f44d2af40c72ab07623694e5c89ba23f1b35c3c4ac3c75548e1937f0f8849cf387fef0b409082cebd4edd726121be4a0c143e6c15a67f5e12ed65a807074f89aef087df00972692dc609a25c25ec1dff2205d1ea29ffcc023c7f48d26c0fea90c343a69f09f60e62f272d0f250b7b54f437fc958a1a1dc5a17b4fda42389a8de1aaa8e3f093713d8d876169a96de91d5bcce65245dbab31bb28d1dafdd3e23aa0288a55608e03791dbded1afd0a6aa4da0c2325f0a9aa2c2596ac27ea93119be3e7969140c03613754b08717fd3396815370e51f7391c5c7d080ebb910c12b6042a54f5909879d5ec494e4bc4a5b05398036b4b5f18502b27a14f4284b4cb61d380e2ae5075171d9394087c2eb4dc8b661a9307213acc391d81d624c154bd318fc910c6f0fb3307a50ff853123da75c9b4a1b4dec32cbd0de838fa160a9710ae3410cdb909e22182738123b078cfdfd1e1bd8eaf644658aee061ab568dfb5976449d87e10dff356bf6603976870a325e19781ef9f50730bfb51f2a75b7e9f4fc6d32560602cdb294f9b3b75f59aefbcf291050c11984c3d771ebde6a2e43b963408dbf720b4b0e91b623f0e5313babc2afbe23bdf8859d10adc00cf9f603d09998fcfa61080dbb860e66ac12b00e5310d28dae46b0ce7ac9ccda376c846870038b0f6f6201d7247ca3a707f2454ce652d7cb063a2c7e90acefa22ba4ace0c65acb89942f0d50f27e1e816eefff571c553d884bd1253e4bdd7f2e37c3d13bef47498264f0040408146405617b176719968e1170d301f28506b1978a1504b46d456a2407cd0dd6bdc96730b8ec017a7d4f6f82d55843d53821064a2819d29d2e92390f56120f987d2469caeb61bbebba56ca01efc2f6793e5da5fecebf3efaa2ea11575e2a0dc6bcd5c56a89c7e5d27776c03ecd85b941d93b0a7305b075f245a0080e70950c38c2cc6c45880dc5248fc782337bc42050d574d1a06a7a7fccce5116067da00feb64ddb8b2feee90a8e86837f074f3002c9ce46961fb8f612ee9cbc1d174300f6e3ac8469a53dd1fa5415796b77fab1560322eb4ae4e3a8106d2a850a8d33606937b62904d2b9062dd6eb0c33849de483afdf44231d33fd3ccf99d5980c1320704a5f76c98af11cf0e511969ab427a46862ae0f11f81161b3e2f907c3d617807efbc8e302fabbbaa4a0ea144b9d1a6fd82fab540d50273031bafd0a91424e008725ce7614bebea99bca36df951f2b0aac4bba241a455a4ab67ab1ac34c43df0ff6f959fb16e85e96aa007c1cae47ada270e4e2f75c0ce67ade4711b0fb8e0801ef88aa18f3e93e2db9bb83f37ab0bcc501a4198bf621e0552d322fdde50be3044b738bf708f222ccd15ebcfa958a7c37e0c42ac868ebb63f02f17f73ac0eca0e3f53d58ebc2f9a53b525648ee5b530e85822c46f45d42c8691ce74e28ed742011c2b388184297c6c8c6541252485898393da4e72021aa8c5f1d200572fe1f401e42ac54558906c736f171d29ae2e8daf214d99aaebbfb07c2cc989fa6743100bcb5694ce121d8ec922db8bf98ed386854239e9c9c1d47bf3f57361363701b80bc1e2ef1b6ac58376bae767bde780898b42b12e92941ff9d15e30d28653af42086267f504bc795caaa946744f357061fadd0bcd6309562e26716560c7af2ab30816b8fb2c166aa2b5e62fa63c3b86966bc8c5668a681183621e5420b962589d062b448e3c1af43e20d2801a043417980a333734d0724bc34732f55be216373b0d20914859f22d99f7649ae5d4f74033d1918feb9b4f195789a3976803f1450e08c3439952413fdae92345a1245c598d29c098d1e73ca1432c775d966b5f82e50c300b503f9e85f354659034a2c2084f8bfd2df1467363d92de86507f5b03ed20637b8d97ed228fa49540c73319e577a3a4dbcb7308e5a6bce3de199ea088d160e467df57311278e27b0365fad5d715f975eb4a8d726cd28dbfed324a97e90ef0bb182ab8f03b6208a475f039ecb161218272c9c0842cfacd93a247c9a7c02fa0490a09fcc70e019be229aca0605af8d1ef594c3885b224dba3dd8813df2e07c0894ca783dbc2d65c8197910cf6ba8d51389dc6f5216eb96682eb935f7a26c5f08db181ebf7d3ed0a480f82be852f48278134cec2c2fa6b86e9b961908174c940c4647dce628d3e98854e1f469760f0789749d1cd880f922f368ff28617a79e10fda7e049d2ede21f6c2d65bfa67a1b959df7e8bdbb3020889f9a041704e230106c36d7a491ea04dc03603a16156eaa80ef870ddc6c56e55e25b781042c087b507d32a7ddcd293c361b502b03a219f36630f2d63633bab05efdaecddc9d11c690d97cae2eda7a09f76515645d297d0870a527348d40f2a0526c3f5144a86e0f00d419172cb9ecab6db9f443351c5e2fe58cd1a881e3297fe8f8add622f85b3680a00a5de45c2e80c8c20da3826ce6f26cc05d4bd43642d78fd2fdac2d88ff20c0603466a40858264b68fccc45825230d3fb92407fa31255b563e2aae5da95e250a395402f0a0b5cdae20ab9fb0182fca2068cb169469ecae7ddd8e9f35cb52e10e997858c84baf694dd0e64a3e85845764cf118b3e47d757d46098867ab3c3d905fbaf67754e7be88022cde8be52fc45fd2b7e57fdd95ed51a27edd6ec9a35f10cd274a37aaf93d67754fbf71d2ebef5c686ce03f50486a403ca9e0633863742041709122eca8dd74305fdeec2b42c7e1b811796eb55bb0419a0a973e6a58ecd0907b2895750bf9523fcfb11da42f486caf875c30f1438f5a178d7805245f77a027792dfd6bf2eef484ad287133b86804b0388e6bc12747eec04e75c4ec6c36a09eab182431371e47138ef925319a53f1c00f8005ce451b110c109da51ef4503060c3c64b7082a29a9dce8c76b836100a20ef38ad60b67bf1a899e55e5627fcd09d84c37bdb751339b3951235a1501eb2c16dd4c9b9b6ed55fe12e631e90a98d03517197d9e750a34a33f8a6b7fc98b06364fca1af3330a9162dff90543e70f500bd71d245452a27a750c371344b305f1c17f464c30a33b49de76d50cad41bd300f02c3c570cd00cdd196f82a8544651eb05c7b24291a01c39c7d27cdaeee73104fc1d59cb7944c5b2bfd853ff20d2bc5c1751f082c8673eb1712a67bf0b9846021fdbb9853ab503eecb91965e6fd7346ba4d0432476c457b5f96c780b6d451108aaf86f745d1b235759d9fc38408c3875d8fbc8742f8131ff700db8f2846f1d0a89d95fdc6a36eb97d27fe0c4041cd9042b0506ff8896c325f42c58f4a39ea007903b8454bce3f4e634cc39ae01f5ecf7d3ae0330e9e3c91ad6280e80601f1c0fae0527dd18a0888bf05fb6635054a68147d93de570106f96bb2610e1ccfecc0da6748c9ad8083dc79bf2201aece849503015f6c426b0c3b349acb2a469424d0f905731152f2a2d171917405e87ed37d48e823ff53d03e4ab48cb3e5289afc306d34db3792a13cea3fe62f50d59da6029266eb8b63aeaedf9ebde9572a5a4da04d84d28417aa4128f8485efc4cb77943bb99dd408b11e0cb5b0c13b5b7a537b0d2a690ca45ab1816054bb199ca020e5cec2f696f1ece29d540ccfec2c52db5301f6e654723d31dc9865331d759c3b5a8ad8b0ea3175c3f4db121fa8e30e4803044bd283e711f19a75b5239ff019a4bc8204ece6c3578fefd9dcc54014f2a65e04634f64999fcf57352d2356d96805c50da5ff3962a9460e3a932b7c3a0a783808b6821e020bd1ee37272c45fd8f4678ac1fbfb0c928dfe564b29fe2f8240c66082e6f6a4d60eb691a86017edde3e1b2d827da7c097d36c5c5debbb52002eec604306cfc09e9bd2ea65e5007d445778762137bededafd865248016044f13369b045e8e78aca11d79bb9179f593bba08505517fc8c0c413d995ca170ada7241ae0fcb056ec90c62805059555b5d61d9701df410c7399050e04b3e04d5e04c6b3303709c963901a4ec97bcc8332f3ee7f1bd57d63f7527c138e7b6a91c4cecd5f101d272b3fe1b8e7a67f2aa07e618e260386a6e391107c9df1bbd2989f8e4941804571c477e01e4701a1fa24a4eb30015d6702819d8614933bb9dd4700f6375f40e1b925839ee72af586aa73d6e32fbec1fe09d448a14411cd5dc292b9572151509821d36edc1f2534da4d3bcb9ed3adc1e9f706c1727474d3f214a07f01b22550db5e9e90b7dc50069ed2bb578f43d3d9421588361fd9f0516cba3787360cbea0eb8f968333db3c32a9e5f3cb3a76c8ca2fe4f29a0463712620de1dcae7c10880966996e8abcc12e74b213f4dcce7cfe464ad04b2d13c2741a22bc644fc730e20d5ee18d903f99ad6e5a3b63be8aa8577fee5217882c9e37288e00e51c61740d0e4c8a4a7987da408caaa41fffc403013cdfc1dc8c20886d10decd3453e521c60a07af3ec48551a4eb3f2e205ce62130fbf2c2a33d9c70fc191410abbde079c70fa78b4c393723bf0821d161c93552c3efd44ced20819ed504afb6f1e062f6020ccb9e3ef29f2d31deb64c18df2adb3c11fd3c85580db856c8c969efb5eae98c0f192bc444c795856e7c505aece56c907540d27eb974b051139dd977eb95abec05bedf85e1bd761618ef9540caa75308cf1abd02b72109383dc886f357ce86090b883dd7d2d63941ea51fe96269bbd5d5b513eae06f05dfd16c87443d85166800a41156691ae0624f17753d009f617f393788c45a61269f075873c6f8397298001c0446b0e65ac06b2f1638ebe323eae67c2cceae871a7d43513f40106c1cc600991b2b540f9ba0791a62f653345b84e60d9af3035b5547339e5de94faf1e1c7048656e3c02058d27227a8bae162d58a94a1b0826105c8ce4e7fa47a63373314041bff965ed9b4865377974b56296095b8dff9d370844c83828b18f3fc3db7490c92e529529e6d1dd8dce73b6dbeaf4f3dc1a0ed214041967b263397d0025d1b0065dce22184ed29d330daaf1e2c4aeb92f26d4cd2547e49e8ea046491ffd8290994ad32ab152b6bdf786a490a5a787d8a2b7914aa4872f0dc8431fe510dfb770a6c7b96153f0734dec6ba7b33d0a96e4f4b84292790682ae8be0bcb7a3975500c4fe6225ac229ffdbabfafda099d8d74863d2193a40fde9fb085031a5c2a0560f85cbc2bb6f2965447abc910d5b2ae7bd3302c824b8aa6c60e8278b87287a23080cd8ffb18796b4ed7232f5d61b06cacd65916e802dca4e629b58e642bea251071d4cbf2a64d4e17bd50ecaf689579cec3728ac6af1c9b8c1af0af27297eff30dfe1dd9cb3a649ff36c6f435b06c75969379ba03a44c8be04d1fa34f5f719b0044437b3b01533d0047171e60b40deea816521e87dd71713fdbea62656b5d28a07793089a9f2aa5d246ec6a67bcda429333f980dca81acf675cfbb802cc2965606bc0e9ac2634848137e0b6852761d845a65e1c080ae8c902cbb3d52f769ae9a0f246f62674e15f0a4f39536213d2b9a1332cfb79a9f279fee42972630200c3d03d12343c11c1ed4e9a99bce2cb4fdc7f5c43e453f968b35450238ee85009ecf0cce1fe8bfef4e21922da07be3c1bf11e59c74ce7ad2a327c29c34494b6a212b020e977a9bf5de685324b30d8d2b837e9dd76cbe000fe7f30c8ee0eff30f7bb00ab8b15e885e48c15778fc14508ac006714ee9f068b0e4ca94d9c67d1f7cbd570876c9892d293668d96413fe0e532f289d6212f53fb5479c54e28a7d930be29c0c30ae890d52a52bc42689c909c2de568e454ceda568d69e829a62ba831cec280e02c7f32a223d221a7504ceedf7baf8afd54d33e5aab241cc088a6f6ba068c20d4a689877654187594e1abef27249507093d9039d0bf93be0df0fb5e6a9825c07825824334318c894e5f76bbcba1ed965de24efef30ee2820fef0e875b6c78601916fc12f38e0e7b61ea0cd8e616a0bdb478781f94a7f19eb0d8ff14836eb1a0693e8dbb22f9e8a9d1ed5589d58459d37c8d4a144ba6afc5c4f6d381db86ac806e3d1e6974f9b22f564dae18a830f7fd3460ca6ef64c12e25d9a4b2c427a24c0903302905106e03ff340492459d9a110d60f1edaee07a761cb225a24243eacc050ac408cf9897d0cc98b0e1b91c2ee1f352d4b510035eed972847439144ad3a0967238e3362e4c1351658c2d03829d852d92e27011c657e7a8d6762be6f19af0157a037ddd48f20ffbd4bdb98bb35c3d82f903a9b4e428a1484fe191115f2890c7f0ce4a27dd1a31ed687d789399e1205c371315a2c9fc32a42a51099065b480435b7115dfc38115e861e6cd42b0a11e1a12965f598a6d332d5720743bd455105bc886ddb9ab24a2c2423804022f8697cfefe0c4d49bc9cc6f9c254cc657ad200015984098a667dcf167c9928a1317b568535683734fcfc26e0f497bcd1358000f22df5a306948d6dc8db7e460d8d3f4c58a6c7fa4c993b389167113a95da820cf648670dc3e8ac1db2706a22f13c5c8337e3b548f57b27fadb16a1252696870485c769cdd1dcff083b494972661b3f69ad3c093d40b9efaf40c0f420e02ac20e141ad97c2990473e015ded0c0325f364b023df9974521ddda33ac23adaf9c2044a0ca8a7c4f85e25726f239225925d8cfa19ff4b080639e171368bcd78e39d008a4e23d98b94af3d8d7d86c3dc5f2d2580a3c4d65d5b75d0f080a6f21c8a390f7c3649a4eaddb6097fed596aef580ecc5b746cb48ff059fa4b972d30dc6c18039fe01210ed4449f8b2799c7a84484f6c3ab72aaa331fb77ef6d20aebd19a6f051c19317c09f28e311b3480f5af428beeb9a5f8274fe4829166c36d1b30586008a13711cb0879a5730a750ac2357ad688625fc0ac6eb25e5388bc9e206215a5067eef2c8822160eaf6ea86ee04b44936fdbcc51a15a264e98f21578695a8ccc025bca762c35c2bba953f73efcd4b59306e004b64f570f74043d8889a6b950aa04aa7acbb7020c56def0fe9991767d6010247391023ddf9d19b3d9149412147c00d9c3defadff5936e0289b5615fb0f2e5575d11875b00395e911a2325d3a8b50150700099f6f6fce6655bbeece1988be8786a3157b48b488f8a7d213ec3267d09dc087e8f02393db3977eaaf0a8cb41417832d485a46cf1418dd99eba4f2e7f06a32c2da22fd18c58d7efde55476e207f53ab708e7ba0818902b145395fc5e90d1292fa7fdd0c43864590deffa413e1fcca4f420853d98ea83ba6a15d40d34d0a1ce303b2ad97692b34bf025b850c4bf7695c95f3917e39183318033816d1ec0faa8e6d1ee814bba5c2f106ac18d7a5ac720f6bbc57745ea502fd6ddcbe901904c6f4d492d55422b1d939aa37f4481f178c4251622e60382d34fbc42b28892701a5fa2b3446a8cc9268e22ffa08ffe8b28bed706cbbe8d18848ed733374c3e00ae00a730ad101ba3e26ff62006157d2389fb51bad93e6ca8df9ad860f8cd35b04875a7942e67f030a94003b2b1f89a6a186d89dad03cbb69ad9c4a213c9e942032786d1cc3e27d4587da9e989818f2265be650c2c9c0493d75bd843650cd05604e32d87404781df143b71545fa4785a3a3870f4e3b26947d7acb852564885d50aa9564465153d9d9eba5a9ffc7fd777528d2c83be6fc9d4353b5dce25ad83080f3ab228b14401f8e14de34ea7ea22c67a22a66874950e966f593cc96996678009a6371cd3ca47dc5c8dc9a293bb94864e2190ea72cac53aefe69c49b30923f20e957eb8a89c25039bcff8e3c88b3bc1506f4b463f5e2618d02afc814aa679a60a77958a78bb1b8749898d1e6ada33a359ade49990094f80f117145e0ad7e05a028b2005e9bdb3b4af2046b9c55c5e9d50d1ce418152b83aecade4453c6555fb0dfdc9095edd62d6f5cd6798bef9a0daaaa7bc5d482b101eac0d7432bdd501bf098909a5f0d08ce4213b4cdd6e94b984a8d99d9920d07c624343aa5eb5565acb0a +generate_ring_signature 25dd893cae76d6ac1932f11696af4d23ced5c7f8c9b26c443513e7460ec16ecd 5d9938750d6d01d3cae39ec888e440f33fec671feccd0a5bcb83a0bdfda37022 6 c29716ea74a2eee8270fcfaab52d6eb58c02084e6c0ee1efece22d8ff5ac9ea1 85179c988425643a848188ae78fbb0c39eb912d731fd789ba04016020e904dd7 5dbf0ab5804b5052e98871ef45eb1d79fc94177d6cfde3574f118c0418a84aca 3053056e01b44a45d9d4137e3fc8cf10b86865dfce0f9773fdbb459b0b305c41 e35ae435c1147ab31281c1a79c2d3a31678be7e87050d041c61aab1dca9b74e4 e451cf5197c665cf0ceb5a9d7b93d139051f56e11bc31ef258f56c9023b94d80 c53355e6c89359655240817ebebc88e2a7c039a53e718bd076dadbe8b166fa0b 4 8a6e1992229d45ed28e01d3a174997ab83b036678475f20664f26b3e74ec1e0165301cd5959fb5e47a65f77c7e07e1070be6620fda4fd62c631a75761c24200ae87d177250d67405733e9d3985d51319b3c5c388bbea41d399caa208b7d2b20b62c9cc9681f7a6fc957f07727b873ab8902ae07be2f8a8434c4fb6e3a58d6006d3949f9ebb6b787a3b7364327bf9ef36975cb13e54ef01468f9d6026b25c3508f634d81840a616cb80d9dc4760b0f1bfd679e355941c18652f1db8412d0d4a0192a10622979b03330152746d9e1e1f0e2947433decf380d7893b99263de67309e33ddcec71f5d3b60cd371feafed4bf4c4977436946cb40ae8de1c415ead3d02610c17cdd859f834f431d714eca3b2527e3cee8c5585e7bb9a445a393d418d025cc0603e9e4e181fb70e3f51b551acf84efb0d84dd86ef34f09d5734d0b4ed073ab0b118d8e91c5251c48ce461ea48845e059e37ec3d74da5df0742eabb4cb07eede7482fea99b8f7115ba538e132462f67baabb32c045c6df60acc33f144a04 +generate_ring_signature 2f1a0d247c8827dba4d4ce33f142f157e2f1767529fc7c19c789f00cf6ffd688 3374f89c3f99dad856ba5ce07e7c38dfeec5b312427bb33c8e1b8c372c6f61e8 15 41a94a5d8abcebc4c87b58bd560596b715bd33edb75aa248955b5e4602960ffe d30add0397722f8cd6238bbc36ef02a1351b0bfd5a462151a57cb156e477a909 8ab0a8764b7ce7c3c10a7e6d201732c6ff4fa5ccc9e2c6e25256db8f88c19467 c12136781dc3aa8a1dfe8fa588c768f3f5b73acda82626cb380ebc0e42a3edce 571d28f9270ca75dabb42b076a8f7febfdecdc966b0c106c4541cb6820380f2c c9e639cb8b24ec739970c8f7d87bea123690fd4f1edd394cac1fe570109db396 84321e4fe650871a21b17061c6581701f5acddb389d49e4cfb8a65bf37fadf7c cbbc7e4105af837cc47494fc5b5e78735a33190f1dce55e2657d2d538ae6fe95 d8d75ba6364a1ef06d0dcda3ab45bb2c245d7abd7dca3574a5f48c3f5c10f3cd 74effe798cf28847c01bf6276a0c24f5be7e6c52a3968b7df9b8545a692bd9d8 72740510584e7b51328029f4bc32a40c715d892cb00f70fe60f7912cd7b7ccfb 518813c1abe65ebdf8bfa96b139e171b30da00b3619fc258770bb316410d8488 bfe01ebd9d90edab131dffccbdb58cacd599d5f0a3fab24690c7e932f2f06835 9d8fa00ff4874b2f6cd130a224a2d2df214f27977224132d1d84a5ea13a85493 d780603fca86efa77fe4d7a9d35617b56e6b1f1cbae974bc5ca9ab4b37f94388 783590cb03f14936ac520b8b90b9a59ee656aa1a35a60774c23c0b120e0ad40a 12 f1774122b913ecafe6ecb941f7645a0f9c8c2490cf5e0243b45424074bd44c0870e2406a8693fe26a3f4239d4cb96a03eecd070184f419df7a325f1920efd50848e21b0a9eb6423046538d2af0069be8383a4a7868bb88fe41ad1001d81a0a07aba556c51ce361d4ce9ef2805486f12083d3bed46a2a1697c8d079b93294ce0aa32a9ddd9fed90b13993b3467eb32a355b302ce65ddb27a2c7fc1a43828d0c0995ba9f35c26baa2a1382ddef196c88b0f5da61347fa76f726dc0bd41bfb31108dfb4b0cef03dd95605d0db16ef2659a9a75f875e82ecd12ebd37beb400fa1201c9b40660f31603dd2452965816ff34d5a688ad3345e5e599c2d5f8d2638ce10b4615d4c53f9c722c878448847825af375e6dffbb41dd6b034c784ef6303a340ad741d62841d9743a7c7ca5a9369a99e8d2af76598057ce0b86f52c200d4b6e07fc352aef26ff5df78b20b5c4d8c88c328f9a837e24438d778c2f9aca54c52b0bd02a99e4db1b1c69d052f8e866b58387b06656522d26c66450bc9616ada61e03e33ebf0ae51bba5351bab2a0216927470e07044330500597ca62254a3164490abbd69eac97dbc210646b8c9427f356a370662164523464b4df8377b069fccd0526542a947a61059c6e06aeeae3f67e86974d115e010c36033bce5077fbae5509d760976cf825131ac8977393498c26bf1f6d1494f967d3a200f1e7b24c774e0301742a0521b549345c70106df78eec3542d301a4d8b85aba0d799ea3487cc70ab2630e249286faa9a370e2e22dc06e9f591421e0b9ed9b8d2f31f1e39f1e05058487aa6ae732ca7396505d0e413840b37dd5662882f569539cbf589c2c22b008ed6ae4711606c183dfb8c2da4554eecad31e79dcd0f159443d476ff68283e605ef15df0e1cfbdb7ce7e7e448620192f9723c3e935cf618e432c843c0112aa0003518e7c7fe49c5e6f23666a3ad14db368305a7438b8f19fe8f76c19c993aa20e8adda3139e2884e426479f48fccaf4b30798223157a707db2185c402bafe960de39b3e8641f0958bf7522e2f7c5880b13bdfd957208c58937210c9821ecdbf073059dee2431dd4fac81fe982861eaeef874b6a00466c889745aa80710e35710331a40885561985e139126fd398a8a3355161e9597d04a7ce2ecf5220de128f0bc04821d5546ac9019350ef9ccda1194d0b2c404e0a5110ca58db45367ce42a0a6783f1bc7248d916872b3c8cbbc7cafdbee470ca3902341ac3f3ef715b40f206a264e816aa64cd0d2ae620f4453c6d2cc9bfa7f8dcfcbcf85a519016801612071ec0cf46f0f96168c3cf05affa63fe0c35e7b8334ae9bc0a8fb979a3f8bd6603 +generate_ring_signature da547499dc76464e031e5ff7ee251b23e86a65e7ef4a702f49430dbc1a3224cb 33d203426218d7f5ba88cfe70ee0255b22f15cd23d1e7fe94e02fb4d7a835de4 1 86b01d9ccfb40a5020a4d522c02855924147e974f4909a1f15afed38ffdea8c5 55adae1b399bf6a36b775e369894601a26a5395e5092e93f1717e75dbf74f60c 0 419dfbcbbf863744a4ee96a357a627b688cb2a1ec3ab1225b311a9e68b764e05df980fc93795abad8bb49003a90e6a13edc1063a712bb8669e5ee3baa819e40f +generate_ring_signature e7e69c7adb279f38f2e2f05051fd992a11149a8998d1369be08f3dc277fae761 85bbeb775e94cc97da84eb667dbc70a26e60a5276454ef41a97e0aabfb8c2e2f 56 18d09a4f9592883fcd32ff6593cec77b9f973837f03d16996ca2cc33651992c6 974af2b4ef03f64b3051a9a18ee09ebe5ee860ade199631490bbdf6d8de269af 0f9b58c9eb9bb3211deb53ef5b997c8aa68ebb9357ae4b827e6042248e07525d 582bcbfbd1c46085fc27008c081b8c3190d8295ba3ee29a28a811c8dc7ddf87b 46e691e35acd711297c564b251cb5b279d11936e67afe44f321a83e7b2362157 254a0add41690908429a4349aa13813cb4b18b08659017515816181971d80324 97f30a5f6836526a6cff058d570b292595e8b056f740b325334712e9c197b8e0 5848a77ebae6530b5cbb1d1f479109604dd9491182c4f4537f3d857b160f63fe fecb6d36c025378dd87880402a8ea775376954bad2bdd78ba5614c793c0f9c8c 172a5304befb1ceefbcc22bf34479c924f29afd264a3ac3b426cbef3df1e1903 7bdbe1fa6447623cc54d957d4870e2be682aabc434db57e31db09b1472774c85 394ef3d1104938454158def95ef99ce4614a373235912fad5dc6bea68e9d8b41 23e1141711a551670210262fa8a59271dce5a05939d906a5d3cd7ec5277c1da5 969dde51d1fac502a370b8bf4f40d13824fc919670d4671b402a294b6a89bb08 0509b587aa1566227473c0867249948630965f4f94a6b024dcc64faab4cd0e66 7e0462bb2cb462c7af329b6bcc6b9664a2643cd6e360cfd14bf7eb53544c999e 738ec5605320e83f6fd439853de054cf99d9b320916ca3c26c53b914e6aa490d c1613e126399c42bae1c4750d814dd533c406db959abdd275b3d9c3e72984c24 d588bbe6c2c2744068758a5d6e259d1cf02473af17a1368e62932688eb7764c1 26d840d38fa305151e8873b14a441f42c864d873ffd7aa2c7c278109a446bdb8 66ff84c63ae19639ccacc7b493892f8f26ceeb3dd6d8f063859449da9d5b13ff 828787793865161872024f6ba77dba847f0873be2562afd85a64bfa0f453adb7 1874b21b0a18b6b43318736c3b53d871bc491695f5d86c8811ad8b2aa8464648 8f1df6bc7f2a2ca7a7d00f475fa487409a0f4155d2bcb2db1e9b007cd9368b83 40b39d643696c1517209c946e7e797b4c1cee0b339464c9e8b13ae28d9434afe b3621ef2364d2a8a9f38aabb9b624b932300046569e9fb026d36c7e73a3e8fc4 3115f7a4b63d229c5182da0a3f624de6c7e2b50e13a7da14a322f0de69595418 7146996c40e7e9570671539d471235c7baef7387ba12f1fc06602fc973a3ffa8 ddae2cda3fa2d25bb4a412f4aedcdd206274bcdbae18a3d6b4c25d978f8f5dfa 124c68d03ba3fd815102f4ec1e16016e6335ed47d9637771c426c49dfd87b1b7 19a1d656e101999c3b1457e995d8a0977c18bed779deb21ef832e7795d4d9044 b69f73ce720530c3fa94f7f6f0b1c6c8e5466a89b97be80739187695970f6871 ffebe2f897378da204d5e8338caf629744fe910569166768481b76d0934e5e0d cfcdf78c7fe82f7fd14a6766d4cf608d6eb92af30bf11ce79348bb2422c1ae8e 7af0a5c4137717bee0db0faf10813515b700be3b04d639490226b047a32b660c 8e824733a807d4fdb63c7621b6838f70054b9a069c3e8b8e36c7b7a2fde41de4 b51e86c2ca33303c307c9d1080f5066ffd47b67dd1a1a368d4bfe5def1fdcad4 f271285616306d959f3ee158276b7c35364191836ceabae3d5f532d1c2f6cb0b 0634672a39f8f196a86e8afd3028b1ee852026e53b57ab5dbfb36024bb3801bb 84b77938a69db65b4f705507f9a052aea980fb5827062570470bf1674772cbf4 b3f1ae595027df180e6d1ec987e7d4faaa5832d72c759f6c4b33fbec5c197248 b3aa197ab9bc1411a0088271908462c745ad08ba0b6bc52b82300760d1edf3e2 764478333c006629e5be2ede6050b6a9e19f84bfcc9af0cb606bca2a7fd6ff57 42ede624cf6b0648b2219d84e2800f86295b45b2d62c400911936b00d23e8eec c6d188b2593f276c9d8af38786e8dc83fc3f4888357576e0ce1f817c6f4ed0e7 e54f8c15e52301951fae217b400db2f8a42aa824f182bd97e979d38cc6beac71 815eb621be2111a52233f936689d47fa18695b52431435cf969ea1521abfca97 c39db1d00d3dfb57a9e61d8921569686b0cbe20e69915cd65c9530c8bc7840c2 88841ef6d698114e8a73b56a437acaf9dff3fae7edbf85394ceea8d0a0abac7d a10006d29887038ae2678d8ccf83cc66f6e30cea14f3776dbf3b1064b572680f 867185b15807549d9248eec40382c0c2efdddd0b6c18a884ab811bf0ba074dcb e2408a5abedc5ca9c397b10df9eb1d4f327fd875932544769b9b6ba124131669 390f5c7be19c6f50c0645efd3d416b1c740d38d7f95fc6983f5297921026518c 5368d661c76b57e15f8e4cf676aa0c8179bad2cf815856a97ad48db1deca7db0 87494de9d4062f589bd263b6fc826dd85c6b81b66583d6abb6fb6cd5954dd296 a353830ac2b086e36537b57320da789652df3df9b6bbe6f963e9cd6941758aef a0d9ff166385807b7eb58ccbd283e08e6b2194e0dc82ef190b3dcb15bcb3160d 15 6672ccc3ea040017f47f053e6ff4eaa141e249c6b3823c109393d01ff695d0018898bc980e07fa21c4d13d1f7423496253378234d207b8df126453ecda45510ee8a9c72f3bf391ef02a1d5d22fcc2679ea15c556b2e65e353ae5ffde93c4860e3e707baf5dbcc7b7a7b90d62866ca9a5f32c57446bc6ddffa8a853dac13c9e075d6bed5611a6306a4aab3c6794eed8ebf211e626726571b4418f8d3a20841c04a7868e746afcfd209c9202493f43c9b4a1bd64ddef9ee4a32fb7a5a728d5d9058067060228680bcfc8ed2b61ddb0bb91cdd3b8f5cd983555784c70dd72fb7f0e2cc8930ab6e613a9ad39ad96a78fe487a591f17e44861e372e4aa4cfbabbb60acf6a57090e4d7920ae8b3eac3bd851b5e2eed9280711ee2dbfcdd505ff628105e215e95fa96f56479865cdf855b2c88dd519804fe1d17b6d50c6aeaaaebe050a9564a565b8c651e1fbc257519323d3ea81db8df0906f4d75d540a93a881a580cefe685b776710f5d0892fe810d05690e4602d96bfcee5f1630077ebd8d3c0b039bfa6b3e0bcbab5320b9a02f3469e4c2e85e1d8248ff47d0a45453ad0842450b1609e08313d868206aadcdd8bf1552177b1c06568a66017790f08b1beabe720fb76227a4cd005089f9dc5de3446799bf6f6b595098e864284fceeae5e736ec04341ee35f04371f9ac88d6745e3a39fac3be447a4528a95a7203e7503a8d80a042849fa8be0c0b70fb18f8605d6e266a67b13571c3fcd3cf97be922e97c62250afda7d81dbdad5426de95f5a504f825ca7efbc941513224ec52075ffb35e47002b413313c358797bc3be7d1f52a28d7f5afedc885dcf8eb61cd257433be9eec08197106371052b755febe36f540f35555af99e4942e300677f8071c733ba15607f5fe58d2a0769637f0c9aab23c3b972669de8b1b87c1462c896c6d6301d50f0cddc0329ac8738dde283ea9951e989c6a7535b1aad713dab64d8f5e9d20195108fcecfa9c89b1a201ffe5218878c8540203903ed4dca085c868b79b088b1192032141fab809fa08e920a0767cad8478a3cc96f259b81397e91158f1a7f05b0d0a4274c9bf90076906d37b95ad7aa150d71197ce5c4cd2b6a9af6046f1b4808e03a3847dec955badfbb23a4a97d18d5cebcb56af68af0ea428508bb0ed1093e207a81bae5776271bc27d88ad08139c0f2d560e0808c450ae986470c9137f80330f1857d6c3331facd095111c9fe3c44314b59b9653d231b7b74bf699b343fe3b04cfe233fd697c63b84eeb2df4dee760237e1d10cdc3fe488d8833c04b3bb6570ab92ef5298bc82bf8d01b24205a15e27d487ee1501c2805f9dd9fd2d86a04d10dfcce069cf6f5c98df81c76875d2543f0ca8401af359c185ed145b6030e8f850975e7726e2f6a2c45dad9a0b96b2e3aff465813e693275032edb1546484ecc8050159fd0ba00c339148ef6cd3cac552c3015b9e48c89ffa3e02837115b0dfbd0eb169b1c14bf56a53a2ca2a051bf9dafdaabe677c6105230bf0ad96041b67140754b2eacc0c9886b3ca369a0700bf4f3f2db789016baf7be8922129e579f3ae03077531acfb6254f9162f111301f060cab2699dba7a05ef95acf896a1af71fa069ab594a8bede80d3738e1c3aa48f682a1a4cc955672767a62f60b35e6172a501e31a066cfc40673580eb891e3a81983b2427ddfef901ae0049d7bff333e494092bfb22b821f4936460338f50402f68e475df8dbc9592fe44f1a3da49e683fe0800a678548b9a4de7d4dd785d9a78f30088a7a9a5cfdb8346b07bf3ac41ac040d7f28033ec7c8913ffda7f4291e5e949defbf9ec734883af192124cae8573130c6d3c87c28c62b7e6fe5b0b54808e4e8a16ee60a749abb43a4baa3f2693e7c60492d1f0cd10fb27e19af3252c7d4e82c38e26a345a57befe541b771477b839204a6b73ab27ae97af8014d1cbf7cae900f63f8613883e584402191f9a7baf84a07631be32641b6a7416a2f0011b7a51ad89f0bb0409fc5f94517084fb01b8d2c05fb5d210f2f240c2bbdf1d3ad98e518302dbeb981a724275fa084872d96de6c024e2b9c22e9db344bccfb5e3ad5825a1307738265471d98275130afb08ec6fa0cf43e224b17447304534f24af08ff0de68ab29d268bb47b81d1a543e7a1f37f022b417701a2d39fdd05446ce4761fd20e1fbf550ccdddf6d2cdfea409200dbd09e6b1058fb68bc9d2a73856256a80cb5583dded609adbad45bacc9f89be5678006341b862439fffd1b222278e884e6679e8ec99c22972173bd90576629db9eb03def1c4e41f0d8199094214bdde0b37e3a010295eaacae2c4649ddbaa6b7b4107c5f1169b96f135fe7d3dff750f8926ba02150e86bf34014ceb9a60c06fbf620fef05a11601f9c686a9eb4a4d13d87ddbfc17c21098932eb793b1e76017febd07627337536611c5402b7be621a79392d8ae62e3d842cc93cc621ad76d256f4101bdd6d5171a01d087467b4996e49db2ffba41b6912eb9500a05fa287e98440b06a622277c8008a7167d8fe8bf233f8898c3fe0bb082a27112b688caf956f7ab0afa7ab58a0ec46de5085a82907ed4948ae740421598ab2a48731d15a40cac9e0dfed20ffcc8198e9535b91c42aa78bbdb1ac95174ea4ef6efd00e7a2358c5ce0f1f9c9a9954eeedad3a6c0432e421de87493896d2936e72cddf9905ec2392a508d69e11a75e0dca5ca047215504de09373cfec95216a2c12498f02be10f500605bc1893cabf0034e4402487c30857fbaebec2a4b975fba5ba1a5774d519f65803b6b0e207092c6c6beab86a2b38c7d77280f0d4b2f9c1e4c29c7b25222f0d3c088f9c77980918b82c3c6cc72225b8ccba0f56af2a22213c1a1e098c4558c92a078be8d6426b66fc603ca58848192c8626e87b9ac6af978d87ec84ce603c0f9a04e6864df7cf775796650d164be2f3ef3e5874f841916f81b82cde610d5f06dc032060d0e6ccec47e89e52e94c32be9cb0d5dde9bed80ffe3e6814ea1628bd470b1424ace2d760d639dceacaf5d84787030e66d19033bc2585744aca9c3219f40da5ca77015f25078d93376dff7e79f99851845e08144d1bd75e67b86472d7db0b13a2d10d70e9e95eea44e1ef8801ad6b8a1fd5ea8e0d7d41acbca35fd5172d0426aca11f22227d93ed45177d729ec3f20cce42043a1e6268a8f4bd686179290ec06ee8214c0b85f5fe0353423e5f6a68f96395e57455fe900f736da8bedf7300d9f5266b90401909e533b6bb9a2dbcd9517f34c6d8bcf830fbc95698c2c0710a786cfc9a950d1ab2cb4885b3c948eba9fe36f1fe42091fb6f34abbc41c6ad5071a09761444050112cb6ccb9fcfef7c9dc7fbd4475e46a0a63005f166240d8c09c5b83cbd9e453fc71911f51ed37bb4896532cc3d53a6ac00c1bba7897330f005001d2117bc7a36c4f41a4b8c90f7cc5b32b425bfc1e4ce222df4eb71d73ed200465fd075f642b6fb1fbe431ed72d11007711038fa568281d82f90b4970f4900131f1bcfbea19ee8e20b0d6f827900775ea58af01191ebe7db53e48716561540263b7c513a5ae81f26ac31a337b86d383e272ebceef0764e89b6164299f4fe20db2ba70227da2c0d2c4b248ac1f802752d8e17334c177dee33727f8756ef4310470cc220f71982e10178bf0dea9bb1a80e8e363d8481bcd1b9d237a769ccd6807beef50c53be11df97b967e32f7954e08887adea0ed8c32cef99fefdbb5bf10074795468c5f610d05cade4a06010821bfca0b8e9dcf16bf9c69c51d6d89c1100c184f6b85e4a83b59275e963b26aba2ebe3b47ae682a18043eaf71d34cef8c10383c91ff64f199a422f471c9d82c8a0b15946d047c2b09fdb061da7d17ddec40ca7d70cc4ac563d3d9c1bb82b78081f49e574408d79efa00c89c589d7d09d1003e17e7144d1a7d0a47b51953698a34aee5c7e82cd9a2fb4824329f13fc52401010856cb7d009b399683444b19c01b5c2822880175a286471b7b3073c30c98f60d54b16afd9098d3c81bd703733ed3f660b11fdecf6e04adc7a4c61054373acb098a50d8fa28e392a45acf5886e9fd1ca5a55718bf375dae3744b3f0c1af778e0efd174dda8c174ae65c54bf11f5478b5d2b487251f03a97f960e33deac289670df962c2c7b34fd8c9b734a94f2024200f1386de23c23cca5fc416e2393d19550a3bd81744e8d58c08ec03d6bb8e016918b40d92d54011072e8e53bc69e4d2c602cbe593bc35f06cc7256d87aea75e48eecee9d5277a3f38e7154cbb530ba6360f88c225473ff147b3f5fdad3edf8647367b9ec35f577687fb3290cc171b70560cfc171eeb216fa4af87417ab49e842aa8f5ae11041142dc239aefafc7b2fbfc0867c5ea0f842eebd1339dbe9e0731805ffff8c3119a895b35efbe760a503cd5044d1efe829cf952b8bdeecb18496e0ab500e011d7a33fbc90d907b8699abd0005ca6ad6a9eadf74d402e34ae6daf7dc96556d3ef46ac11b9ea94b88204f80ad074e4c5374da9d10f1dfb5e12fb9bd559810c2a96b00484d0b69aaa098d6f2020334fa86d03b316c3ee47c92679bcf4dee94228ae4b52502792ec47f4af77c650a83421becd7269fb177ad26b8596d5ccb37a825d270c9b4838360d94dcd31f00567eed2d33df5614eaa0c6bc94e76cf9d608fd90523ab9164c85dcaf731965801dddd7ddf01b4d5f411e6c8ac484c464d06c28f06d0572695337935daab3ffc0e3dbdd30abb3b182b610768847ebc4b118a4f3d71e8edf474afec079409b7ee0cacc2dfb73400dfc39a9790a1b4d1ff6ff3eb961bafc8c8ce189ef8558f71fc06430e515241e5f3f734ec1cb9ad56459f781f9aa11086f19b79ce23901c428b0ab4dd9cd47b97ed67628b4c2beef1d1fc6799eb4618bacdbfb6c1069c49749e0e337c761992e99221e83f1397ad42df28b35c9fd4c62278a01c44ad00bfe6b50834fe93efaab7fcaa3b8014e4d9b82f66c7a5013755790096889b6e90130d0d02b7c762ab0ed2ffb23cd75259aa98f370a8fad5f1178c1c7a2071193581252c08 +generate_ring_signature 8d502bf01a32e567707adbea7c5b07946c8a91ed1231dabbb363bb6c475debe8 797d78be1bd8f1fa9f586e9710621bd3d480427b45588fdfe8b845b12414974e 1 bf227dd9be0cb17b4cafdeae98527a2bd5f22d56f4a4449af561a5c7e9979411 c1d63edbfe8e5ccc53d5c54f571718b81448166bc241c68f09aa1fc0f337d60e 0 8474d191a4dc4edbaf7317ba5f22e2e3ecf48181f09bf6f6ca878aecd7f9eb0ef1a01512fbd30c659899e2a9c26b07ea9a399f4035d013075d53d8fba0042702 +generate_ring_signature a360d6c579fda6e77d9d8f7c5670c5a3e56dd67f9bbeb9a2a51ef4fc846c9e4c efe52ab1e05aa48518f70282135dbffc35e61066c0ff77f69dca8f4f77cf26a7 2 5f4e6fe57d228860581b1597387794778018d9508ae293cacef275f3f380f949 7f855f04ad22ae8e65f0dd48b9140295e23165c1bdc44c2e9caac8f7a4d47690 742392bd543557e97a5c79270150105e0e05099b7db61d2f07f2a4ae1b0bf301 1 c0f352b2d4e382513711017e089800d1803f2430c05e49f7920d2b97f1b9ec046d5be642649373a485d93b635e7b4b608e15ed664094ff04ffdbd9ef00277409f749552cba38a571ec823483395216df8cbebeb7a8647c152197f4ad1151ef0e0e1662eb65e6ea3f34b736c6f02de514d45911ec83223dd00c014617f80fc506 +generate_ring_signature f06ada276b4cb15bfe0baf1973b4159c4ae03306b3d1cb6624410d84ff75ed8c 33f1bb96ac7545b8d506cf2332fb5c1221d7833e8f1a58c7e72e7ea0c3a85f44 1 59ebef8302f5943bdd11879b6b4e3bcf098eb70a56e44871a3e6097b2a38f682 11e1c3f3d5d9187ead09f8679cb2172afc020766ce0de7ae29998b7af9895b01 0 67df283aac57110a96ad2c8a9451f244f0c04be6cf86fe7e8381ebbc30aa2a0688cdccc4a7010edaba7646a70bc03a81b064eb61b161ae438f2879eaf790410a +generate_ring_signature 4bf0339d9f8d053c5508af5620f121860191aefa336297ae61c07ab16e830e95 4b74cb953354a6d552dd2093fe6547018f2ee804b950c00ae2cd959d9edffa02 249 b273d48608383a643e8f4fc7a3218d79135807e1f01bafdfd131a6ebb066f53f 13a87abbe6ebc9c0a6a758e2bee754d629c0f0e3c9a8c922f2d6b84ed1d09563 41368a4bca9b547d015b4c88063bc4c61bcda812a31c5fa1380cb9917d91bfe2 7adc855900644fe40f6fcad939d2ef3d2ad64c78c67081eafd47aa014fbcf569 327c96fa149e38b3e54f28f3462c9e66df4c74a6ba7957eb9fc52a91fdaf7dad 421af8feeb282c03a8fb30a7837837641c153fbd43a8331acc28b1c4a9e86bf0 61281e80c633170d98119dfb0fdb35405f8ad76b0f0d867185ff43116abe96f4 2e25524e65bfc6c97f57a92766d15c394e46386ec49d2749df2d45bf52daf1b8 47ee6c2a1c29f513e09d89f74fa7b86a39fc4468cb648f74e0fbc1e48d8f6d98 09e04617608530d57ace72efad388ae1ae3947c0466c5b430b9dbf351f392867 ddbf7d3d8bf539aee1727a3eda3737f18ab63ffdf80651c5597e10fe6676ec56 135947fdaa00c8fef0bee2b1a8e843746094317d6feaca3c12b15d10154979e3 203b1c508ae96f42485d43de27fdb3075f3be201748e51ff0facd328399ff2e0 c336b25aa242b63ae73f67e1bf193f50fa8f40e59110b69e76db94ed57886d6f 8b285837b4f1690849e2b7766d9f530218aebb3e2ff9110a7b149378dba033d3 563db591fe4810c041d6fee4423947f244f35e819f0638b691b2b9fc77cad430 03e7898c213d50755f382dc62e36599c1d3dd87b6c9e0159472ed2f9f334c0c0 22e97507ef3b946b063e25d97f5212b6494d2696f9971ff5d54475ca9dcc1afa 229b32794f12ebb14c367f5f92290fd8190e14a65aeff3fc78aab3f8637b2f5c d6a8b2d32e3fd2fb5d1c71bf9fc51c0095033217feda93d973e49308f5694ee1 babc6af36f56c37f9d1cfe50d88c6e7a1403d9ca9cda788a01669a8ab6f050ca f07adec8757f7740eb2403d1a4b1c29bc591f5f90aa3c8cfa17035b07f0e6937 040390e90391a7eddab4f52925efa58dfaf935ae202267ec0f2aa535266dedff 84a82b340c5ba88f1359f113fbf717a945ccf2baa3b1561f347a70a83eb3727a ed06ddbbcfe612935bb53add5ef26d3e763e820f62d549af2713be22c6c6ee48 422ce5b6fb4e39f0846ce3a429a03fd2dc53df54f806b5ecf1dde1f2b004b074 0de9902ce29035edeec28692133417787524ed249b1cc1e2a1c000c2f35d563c 51c3352d40a920458a2e73a32198bfc93a72732d434b1138050ab8574cbab540 777b6aeae382f6d39fc2e613dd90a4228c2e8d69b3c56a84f250996a3ccc401a 2a324732d151575134c39e80275ea6aefaeb038346fe08314bcc90cda45b75fe 99a2da7d0817ebd800f5c2dc62649fc202068cae2692760a4b5bc17950249a05 3b8676f56b6358890bd11968a18e40f0fa56155aad8f89967a9aa37d8297b177 c0c464a4bd5d573e1bdffb58dad5697660e675a9e9e63858449b89b267271a7d e649468d35445f60819fe76f8780023b5a1ea23f116398ffeb4b4620c68e344a 05e7d38bebe36c388c980a9df464f018f48681ba297ba940cd46853b52300819 56f4fe13aead9eb250187d3f55bad323522841e0b5fed2257cf419692be899a4 acbfda9c0407409f6363b3718432409a2c56ead586ea6f8625aece0d48fbb29b 0bfa3d79778d063ad3675a485bbb8f8baca3296368409d81aa25ed3da324199a 800a29bcac3c088906ddba33ed1cd9e8ad0335d5075ddcfd28ded381179fd5a0 7dffeda14c5e22bd9cb1269ac3326a6a617b1bc277a77f5066aa2676dd6b9d40 8b786c7df9fb0e695678e9cfc79771bc84badd695e7285ac75bff9d6a07c7b8a 11bab52ae903cf6d7eea8a8f14da338ab52829ae7abbd6826e0c96cb1d8ce098 6e0219a5b11dfdc9ac7e6a8ebce4bac2b775a98a12697f8ce2afa792dce8553e a45f1f5479673fcea8ac0680f92089b115fc939bbf97094a430ab849ffea4dd9 e5aaf69d15c087793936a53d679544d2634ff9db1b81cd2266629c5b5d6048e7 bcfd31af3666aea09e3255e835fd931019b944af779af8e22428b713d942694a d320bc2b9ee9a777749dcb6c40e59a9eff375737cdc0c9e63539e89264e922b5 00910267ec94f2cef9ab012f1884518fac66acc140e82bf9684319d438792eb8 b13f3a4fe4429f8c34ca50fd9649193a1d9d42939280df3d40baf029c08fea85 79ddc3b230713949fac670ca6ee8442ab77d3987ad1855a856b20ff8c184fbd0 b9cf848cf9d1aae5f0d066e281b3eb0d447851c688123e4823dbf3bc5ff84929 3ff30f29ca0f5d56e3114205f032febe2c7ce3dcb778ed20d0fde85e42d44a69 49f1c860b9653e21a699f11dc10a11cde10d311512294622594c7fdce67fb8b8 8b18920f526da2a285481fd308428fc2a125c257155fe8b9c439e100c1f4299e c3b822f191fac8d362d2262efde806e5bb0a468290708fd31d6fa83890363a8e 114fc1213163e40d2f246906455a7edbd3070157b2089bbf0f23ebcd4576e7bb f39aaa33d3a77cfc664fab4560c47c230af7809cbff25f6806c59918296e95c4 c5a3eb0d203d502d830ffa7ac764c029b2890cd5c7c48aeffb793dda0e35f206 ecefa373bd1cba2ad4b04d5f2921218abf99f0825cf482c3540f94432cf01c45 3d4313281bc933e2bedbd7cad99fd60f1748256df79c08936d2162bde71fbeea 0ae2cc5b6d3b36b676cf08f4a9b4d754339dfa0d0ea5ce5abf5470b4726d09b5 6990d8de84993016435ca8f23aa18a7e72dae4d8d7e232994f7fa5657d34fcad 3cffa4c6b3aec0efe4e7e977e5f8a7294ee5c99dd5c0ddaaa3fe23351c941d85 a2d0b812fd1c7d191eeb61567298981e36b340c134c78da944f8a2203352e8cd f455055f5002146f5bbded6001d7ce6cd58e7e274caee50cdefba3613388a0da 477131a096bacef938be8fb54088a9004b29aba49f4579c33ca52deac5a8e5ab 67080c465a248f515e86b58bdbe91ff272cd23b08b2a7efe4d69f47e0ac85fdf bec5ac0c0b01a028ea0b29369e79e1c81eff46e9e69031ac3cac91aaf4db462d 2ccacdc26da82afaeeefb377043620a661bac86ff30ac720a847275c3b22ef41 6b20b96ecbbaaff46371c8c5094ee3af5250e9171c3207804bd0ce83c486b5c7 77d1c2e2a5b9048ad9c2200cd77495505c851fe1d0e4872f46de66b7af209ef1 fcd862e7cc429f954f422dd13ae8bb48dc029bbcf9b914244b7ef0a20102a155 3ede83a52d68d2fe4f8d6e721aeb809bfdcc0b38882d41e41dc2087c2b197f26 e38fa088d56b933da20b16848fe1310e4243513dd3c729f4032f74d47891ac8b ff44c21ca0af4dbc2e0dc012ee8e122de372f0d530db0d68cecac9f2a7c33b73 3b9903664c6ef51dc655f45f82de37b954dd70a37af1a45eccff40c492f797a3 1f70a93f7b6b459fa011b5e7bf421d5108430c443b1849f09e23aadbafdf2b22 b957c51631fe2c2dae71100ece8911fa410088a255dfc3521c0b1299d1ec89b2 b4c2e3669df39ada556b367b6cc9ad80b49d3ee765b54f288f31eaedf947aae9 bec54b546520ce1edf6def1e99bdd92fe35fc090f3d7ec249ea4ad7ddd998d5d c0105b38734b5a317dbeeca88fd34ea91633d4eaa90171724a420512a1769f48 34d20eccf3554bc5cfeab0839a5da3af1026be554b8006c91e495014f47a98a2 89b6ae04aa15388f5286393aec911d4ae16fa9e1c6cf991a8edc93ca27511c02 dd8ed17a2d4ed78da78446870808e79b46bd9302b686b72600575324c9a18e72 9127b0709d801ac54b8d550285a6a4e30a77f84a532eaab6c337a1bef97dd1cb aa0c38fd5fad2f1302e5983a9a09ae83edc730a32610a7dd102475624720588f 1b614f9407aa350b5cc5c52ccbc788e943a3f3d6e6a75e332103c7cb52503e2b 7bb824ad656dd32ad9c9ca1deddc41a3589f3fb9673ecb1621da283659139d26 8bb69321746fb816425ac5848e3d941decc629180993180572a2d673766d217f 17a6eb6175bd025118254836943f75898ff81a9cf26cd18202665bfd15c98e16 efa75e34a18284a2434c5b59d0c28891b998b2120a274cabc2d6757225c1b746 4866748e5ce204fef81c801a58339108a51e6d3fea7e5e2c879b22b358aee2e5 eadb7e4fa4a23a04f7eaff1faf8cd72b98215fe213ea9404398c3d942551249f bf44973880920ae02da88d1293672bddb4c5ca8d2c7d128cb244e480618cbef8 466f9c575f9eecb3f26664d593dff14960f4c68b3545a704b99594cec3f63060 b57feeda8456b15539b5d24c1aab860b97cdb498b629f81d57ec233e4111007e 4915b38ba83896e3f34bd08451300e26d5ef5d8d8af7518ac0592d19845b4464 d0524fd7c02630ab477ab113cbd21b5347063c933529fa01813d43a0d7d80d5b 27e89f490f81f8b21f9a08539970ea149b3a18196d54edae47105e2c21262498 a159d840849c5682a7fcc45335e329c3f4f65a0370bd835c70b2ebdc08d2eb83 b6876311d19355a2bcb0990f7b3fb98639eb5306af6624767cbde5013246cf8e c9351e40f566cd7e30de47c39154f598902d0d2a4f78eee4b37cc5412b2a6aab 1e30ceae50d00e8a0e87c28e46713011b4d911da0642468a47b95b98c33f4cdf 0c0f7add9e8f5c60117f50951765739424cf52757f48455162770e2642b44c90 e72c4aad3a76f21c7f40a8f7726b4f25c887fa11de547e5174e57d146462e764 49ae88514ddd003ef502e13b4ac56270888953a5802a5859961459a4c702cb31 acba3157ed52715ab3c0ce192c822fc4d317e84e360103c3cee3115c70a601d8 b05947d43cd215f923d48dc386c3f992351c5034c9112763bc2f89d9b4c323bc 0995423fc0a5997c95e07d3c4e16bade98d1885670ff48e59929c59c6c91fdfb 722c55efaea965818c6588b5b72f63a5b5036964ce66c662b0d01e85417e03fc bf2a2562576c9108ff535b04e023ade892ffe832c81deb4ab1cf69df767ac1fb bd6bfeb30c62acdf53af007c5fffe06ac6479fdc1582dfea2e5100dcda23950b 0c597284b35c159e09adee3c5f2b4383ea00488302714851b99f0fc6a774b7f1 86af1fe8506d70599b9f8f277f4a9467bff5f11c7838feeade171b6d62c109da 3ba725fc3c37b7c284b280ecbd3030d15b99008537d072da46609f1118322170 0185bccbc5d27113551e4eaf0dac7a724fc0c5bd8e03ab58891a5af79d0c4540 a03be24b919fc712ccef8e92f8402b32a5ac2e6ed435f13a01ac0adbe4cfff04 13a37f625c969172b64012f9c07ea8f87606f9a44bca086f77b72126dbae08b4 c370773fc793e240c04a6c6b44ce8c6bc06bbbf85cad228c299a0fe0a30ce63a d1c0b2fdcc1f83f9ff3808ed8246a6bcec7818eb8aa2f985a1cffb4bc71240bc 8df94b166ba97d7b5d3cbc0efac70565d5fd8f1bb7676765433122d3241476eb baed16c73411d8331650189ebe4b53fe9bf2237abe48579f14fd362fa1eca68d 968e2c6632c17127cae014ebf9c72942da77624a3c7e850b821a3b35cf3fc089 042d32521b49938a514044f1d65e69d2e74e3382f9044dc58d33d762f6a3483c 5f6ca5b45a1bac1ce6f04d42b6eef09ccdad558e1b3d5737fdd4c1947d57580c b8f960e7d188503d9c23b47eaac1ebb6ecf00558059a2062d3ff4916dabeb00e ac773dc9ce7620b6372078649fdb96ab0036c6524d2c24af9cb2054372306681 dcc1a2b1cdd61951167bcf580126f4d91854144f410ed394af5a29732c430935 399c3cff7cadc89baed9290842c4d689768b41dbd3402aee4751e4e6dc83cd83 cba3fddbbbde39fb6f01534b8049452ffe7e1837d28e466c0929c7726b5bb3d2 a525c1b382c198a32c710f6d1bbba6ed75ed85bad57ade17efe1deef3cbebfbe b10695a3567eb36d140a8c81b364477e724812c5d5cdd77631f756a678965fd6 100f2e875351cfa296de66052c4a83ae00c2f40bb97eadd1e7ea0068e524c568 65373bf6d75c43fd82031c030df1cbb1f2e54fe11dd9152d06f67784437a8c6b 10900f24d787db19021c7f6ffd05ccd2c1485bc9ad50bea77b5f7e2dd4d168b5 9206d8d7772a8042bd9b3ccae4d1e897dee041227269589a85225df73d51d8e9 e2196925ba83980352a4583ecfc2609194bea93e43702e1efab71c76eb99a77e 5555834ada3f35ac16555078158b1e129d347b2815d0cee6e17bb1db04fab190 9e411227937e25b05de329d88b29a3281e1471c26ee51636edd7b2bdb54532b5 cd812857f0c9592e899749df1d1ca06a4ec898e2d459fd463b87644ca1a80952 c336f88981b39cd2835bb54ff9d40dbaace66bb32005c266e4697d072fcc59fe 2f96e2125d594ad89999559a2d49f196ae3a075651d34351aa729147fbae4c21 d7f34bf026e0f3eb8f989d50f7fe2ca31e3e84f322bab7d956379b6ca67eb8c5 4ee15b8fecc0cd747a0813b82a98727e6557d35636210fa25046ba2ec63f6778 5c024d33681e72ce084e049ac978cdf05f2f690f9eb9c3c0a2f667e9feae4114 eca951b655f40be30b5139801f0eb195e6c1236dc1de5eb982a64ddc5f3e0ee0 b1ec1fe38059d22a2361a3698b04b3633f8c5e90f94e1b2e67c7b0a83d0ba135 249dc9cd75683ea99a1a6d78b941d25f54240f025218ca113c1d10e83e1e0844 395735c24e6403b5f9b3bf6cfec617ac4afaaa68e3861320c6ddc0c3dbba3e3b b88c05ad20d89d50304c08620f6b7f4ef80c50a95cc2877fecd2b929658de37c f4d13f28d1c3d0b5424b8ac845becb99c0c63fdf0d50c36a72a2b49bd64c4486 5eb59459759a26c15ede5971790bcf73fca4ef0bca2b2d2c712ce5d7551c7bbf f1eb0ea50f8c27d0914231446e3fadb7f0f4076b236bd76d15a2178043f15b1f 042c13be06da921788250ae0fe2169ccfd7b8f58258f6a03f0eeeb9ee4b056cb 3e8805215ac6b972a2007adbec893c526522a43ef8817e16dd09637946cdfe01 82f05de9344173995217794bc4d6a239f157038e41858fb49d73eefcc4ce979f 779060ea9dcf24e80010259572f453b743c818fe22d78f73c178f4f8e15f8340 8578dabb1c0d7d98f5e8cdcf2aead724a8fef51d24850eac7acc4ec67de107eb c8959add000fef8da12a32535810a4629c9f3005990500c472ca0c115a0f57aa bdbef5249d2f3fff40c7bbbf5293987ef976bdb15d410a62dbbc80f5066cfab3 82cf3f9a8c5131e29b1b1cbc9f3d48594fe30a5a0faf9f7b4d3518ff44905567 cb5a1a999801bf308a00933438df9adc4ec64b82a91cc819f46fdfa4dc63cd10 a2b5ff7c5043db55d1ba34b94dfbbda40c407393b2b5cdade2a01296d6a2d6cc cd9f89e414c961caf06f311ec8dd62f3941f116b42ee2220f6cf8730af87f225 94f778566f9ef6a3eb371752f76cf66523306c2ded5612d187210140dbe8ffca 1fee562d0e19adb7274d1bef2616122f37fcab620c31b259095758c361749193 2753541527a5f28886b6079e94031216be897533dc3aea2ecfad2d3b34c14a0d 74f9cf2e7284f89e175f7da2ef898edfb392ff850bd0469cec5b2999ea27e413 0822f78b4c9670073a76bbb206aeaa9f56d2d4c37115cbfef360375fc2bc498a e3bbbc6efaace48edb5dcce9a82bdf8b1a01ffef4e0ba272695ed17f31ee0ba6 9c249607b3ec14755909b1a4b96576864490c7c6cf077222f40e604089c2ab78 845830b099308bb31cf8d202681d2f42a709ef7a7ff29f25fcb340b8f6f1af21 f18514f95167651c539492ddcc5a154da18999f6fb5ca844c6661f113f36505d 1095e5095d519c92794caecc036b98052f8f8ab7dbac113cc144734cf6e732c0 4fc7a8f505c45e9cea40249551027ea08f7dbfc56f2cfc7dba28a31f8ed09695 faf4bd877cac477edefae6746b50518756026be3f58c3e283325f8b3c68546c9 ec3ad5ebc4dacec3ed641ec9aff310f11f6528b186175affc0dc3ac494280e90 6762ea15a154777659755f3e952190a37166ece974ab87c0f0ae41fd7e919646 6218aa86f87c50c1d29d74530fc73096cc5770e41c34bed1094ddc66835326cd 6c6e8e95cecfdbca5a6a3f81efcbbec3f6822c94abd6824b0b2ff04d8e005a28 42529960daf5e9fcf69f0378c7fab63dc04a440b590129d09190b43adb33877e 34da8e22d7ac3501057278a7976adcdfceb2f0946f9295163c42b9969f349de8 3567172889fa533c80d6345fc3bc669824b16091528a9ac6363a49555b3b1839 83d3c5a2dc852c1de0fdfddfe67bdabd232e7e786aeabc536e469cdc5a96100a fba85c323676f6f3d712a7fe174a74291ac8a7093279ca4770e2fb8b53292245 9f745cf4495ccdc23902bec531bfe44ee6608599bf528860fe615b5e64cf22cc ec2408378662a405bda9cacafda3bc482bf0ca4a5c3ecda11822ed66dd23ccf4 e6e2a769bb7bc694d5334699e807b312b31dcb84f12c098e9ebe730aa0aba197 86d5f8f8b1ceb931231e7955ac295f22b7dd5cbd5474c6f17ae9c67bde08b7a6 872a5aa1c00ab676ff697bc965082db4b84c9c5912b13cd73e238205b968f6c9 98e88fb15b4e7149d36a4d96369605702421a82536601f0d92a8a22a00196a74 b90582eb1cbf5d567bedb375902a66f452aedcc9fa4e610361b1994ce9756c9c 46f7eac37dadeb7d586f1f2154fb93224ffef25dbdcf5a50fbe2058fe4af4fa6 1f7515f2e3b6b0adc19d28b1733b596f408b3e01efd7a1c32d8a730687c83303 d9095d067e48593259474e88b1bc9d7c1b8f7c9fd6dad38541738577faf674a2 13b7e9dad168b21952ab494ae468f7eb3622eef3c93754dc85ea5076395b8d6f c53c69379620465b2ca2c0b55e292b41771066169b131d8ede8d958de335a124 f0f67b6cba0a5e26f0fb871f3102afe16c95dcfb3984d36f77158c55c2116055 83d6462bb79bd75ed33ac87b5a7792c49f6a7c6ad2fd9462846a7dab0bd5ccd4 e105fda7964432c084b06d5a4ec3ae8bfab30b85fad2ac5e12bc91f570f06c1f 7281cf80a74a1ec7881cb6173e8c82a9878a07ff0642d24408eeda7de48bf6c0 8841e7f99d72d4523a6434bf2f7654354f5d262a9f25d06dc5387cfb53201fa0 7221681239e07f9604d5e68a46965faf97af8c651600abf993177a340f6e88d3 113159560276fff26c42d020fea67f3d02536350cbd7b4ea36f76c70c300624f 14152448ea110c2a7f6efe4bf7173821cc7436646378634944164141e862c083 3f85f4b21ba09576235a74bf59ee99fc7690159934ac709639927a12598de4db 0ffb0791b151164266c3f61fee62371ad4b847681e39f11545fd7e79c8049a87 deab05a92357a34e87684d48570d216eb3a600a40ce746851bd80e33ec1c68e1 704537fe1c46b6175756a847e8a6c8a4eac68c3834e18f1aea4159e867b4afe8 9432b7a32bf0e82599f4c89b837400ad18bd09a29678d52f9ef0fe672e5db9e7 72915931e01acf984fb517b671b1c2a48bde0650bcc8dde11ecdc957deb2ee0b f0abb70c156aa44e30f7ecbe678f9ee9c0036c8912b737f31356714014a28026 93af6cfb7d315152248a3f5832795c53ccfef807bf889c9e08d7159ba5c7bbae 5cdcfbd85daddd4f1342a440b80663d03545d138fa31afadf45f8f97d6215145 bc67d0bbc9c1e729334eb1f625be3f76271f67075e080ff2101f608cfa6c9243 647f856b3e4a7f5b9f0edbc3c2086a14d97c4cfd940804e93e7fa38d4657fb8b b04035320466e030fe02365fc9835b0a13c75e171dfc1fcbcd058af05fe9a193 f804d2682dca7dcdf909155f817115f585dceb66b4cbcc513460e48dfe2e0ccb ca00d1eae1ad641fd240af58d71dd5d1b360773df738f76475f9ddce0743c053 99de32f96953e27f7fc7d6ace8082625adad8f875af5ccf98271211f6ffbf168 cb72c37155f98e712331a709f85b2b4cc137c3065c93b9a8750612e0bbc55797 ac942c8126db13a0a40d133df902ded357717d0cb8791d9c2b1b62586ec0e7c7 09e99ca05570543f80cbcf9c6381e19e8d5f21c00d96c9d04620219b842cb88b 6c754834e8f10b4f7c63b15b62bcd51232d514d1cb6542d44b84a84ce6d35c14 9cb2a9c1e1b3d50718d06faed604122745d6a0c4b7218428d2a40da6694b0b20 37fa13a595721d0ffeda06edcf2a9192aca945e8f845f39c850361060779bf8a f6a1fb231730587cff8331eafaffe84c036062f58c23313d0366d227f936dc0f c4352ee007fa39a2d837e554c96e3ea9c5f30bc131ee4bfee4691af41093e8f8 7888f2ce93dd67b62dbd401a649f2bb53030cdaf63958062a3afc269c65aa1ae d4beedaaab33b1ca7a62d8e3922a9066cc57cda6f5f53a1821c4b93663acf2a0 86c01b16025f966d766445addbe03d51be961d39f02611b1be6d52ce2e65ae03 61f2347d273c611883aeb9d63b502cfbb03935e4dc57815f89b2d960ca5f852d 88de1640f8120b16fe3cccfc6cbafdc3b2cad4aad54cbbddce71dca7e5a93d56 234e16921e47d84dca0ecde65723ffac02962de45664eaeb48f886f502f127f9 a7cc083d50070f1f751506a25c920ced9af70758dcbc609018ea29d2bbd92378 2114d7509873f58a86c60bfc37cfdcfd9a9b3d6bcd9adb7ea2f872ebf105362a cd8022df16cfa6aaa2e4ba5a2a387ea45695489724e472b48af3002557a76ab6 8deef1f124f6471ba33742a17098f6bb74c0d78a02ef47d303d616e393eb4519 48b56089969f9016e90b1a0aa3bab624a76ffd2d5bf7f8938269b114591141b2 9f18576b44e23d3c53213b7b7e4ac62a106282fa4561b3909c2e8576dedf414e 6839dda8b939921fce2234d2de861429ef0e896e8bf53734c49a7d9f9987f2b2 b52f6b08edcdfe3b6c7913e9da807d82e25a549e36202b8a8950f0a14fbc58d3 558d9906fe2fe216003200d96b368d4277f950cba6ec1949be6e42f0bbf522fa f369d7d155899f1fb4351c2a580c78ba591f7389ade0a8be48104a149dba7f13 06ff79895fbdc3db1d298456ae015ed3b7d61ebe3c69df56878fa9d6bd4522de 6e90d3ac10d5efe134def9d541f0d840c09ad7cdbc80e7ae326c132abdc919f5 b51705d06714d270bc2acfce33937dd15cb0329952c899d6f4304c7476adacca eea364ab4655adc1d2af1dac26b24fd8a6554abd57925dd4bbed807d6c40dc3a f815a1d1b99c386ede5a04765bfddcd83bdcf4d3c43cbe2eb768e9064bca8bfe 542eec4353c7aee91d9415ba2fd07311a3936640f91f1b061f1a1fb62d0fdd0c 127 8d31acf18cff3d7a2b763bd939b21bc332ba28c068b1760adc7e018a1c3ff70142d7e1178b7561605bef5a3b6a62f410cf385ea585da77d7e0cad50ecc867d0b032d81ae2bdf963829d776d6170ba2e38748a2fdd54af88fe026c0e71f3b400d556bb8959f4b6b87650c265bc69bd7ca9697b35193be51bef4a4ca254e642608961f2e99fcfecb08d694c4e5df1041a94516bb0472d37fe4c4bb33c934a03f02c80d96894faa8deb1a0a69dbed56586e82767f4f8a31490caa5da1ac2ab2ec07172aacefe8462da0db1b53aa3c8f16acee5b59ebaf2f2903d9bd119caf67a50ceb3b384daa28947e5e027a54a3cfb754da13b9ca1a774544f6bf8395b4ca2a0e969a54290577430ea00809519d78faed7555a4a92ffa7874390ee882a197f103fd4fb021a80d8cefdc9c1a790c99dbd68db603c68231298b55cc627514b0740099c4ca2b2cc40d33e34346dfa24fc0ce0a28c6c0deb63a3b6af5a591ae75b400d73c4c8ff622bd8b4337e809c4c9c90143d8a3d1fb69beba8cf049e7e55a28018ea4f895f41ce920aff00f6cad64091797d75ed9611bbd76f4c1edfc2fbb9109185901047ee6603e965c1afa0ec7d3fd32f76cd1955951a4587854aa579ad70744961bd01b5d6d626f621b798162fb9c07849e80f1bde063daba70edfd068c0759b1fc9504ead94a40d72f184812e48bfea4d48d07c045f27869a0e96a467a00729b9482b9a81006a19513a71ce69cfa5b85fb2b05e9f60050ac9963dd197c0ad71ab74b4d9fbbf1329ec64e12b3b9f3cb2af9fb341468267bdab35721c8ef02287721349eaf9dcfe74fe3b7461d396c69c69acfbd1e1f2beafb83b69d9b580c169197c709f622f3e76782fd0bd78d40b4c45e3041d7c6020c3414bc2d43210ce8a7180c7fa6613da4d8c5964199f721fce9ae1cf81bf624cc830039df3cab0e43fcaaa28079d84fd80de958ba331837d1be4f57f090a301ad6d96d5cf5cde0e82265b1f7439142f85b54a0dd829049adcea3dd59ee74a1c2d9be7a0b8eafb0ded2b6b3f7302193417b0f6f69c537cbdf35aa5782d2f7ea2120f353d7737a40ed3402150abcf3e3327929175482b7220bf98e7c75e62c91c29d6af978a803d0a60f37bc9e42b2295119a73b26a02ef305e19a95deb7b11cc9ff2816ba54afa04c1c02a86298dc2e635877ae4b89bafe609b4717a7055413316cd3b7d8e50e1093e5c399d6cef49fa008500881e08ca9ee88eed262e9f5bf8d23b1685e3017e027ea19ca4cf81dabcc6870da3dcea89314baf3097d841d264d70211358c519602d6d3dbed6fef64d0a54011a6a9a5a9ceb76f0d9342d12099c2ca3ce24c5a510f9b437400a55a0e64c66c8cca64674f96c7ffad87d228f1c25f111f8c8a6912006b192025c195651aa235b4dd768e647eb314efe335e682041e44b1667775c80cda7e1facadc791d9af2cced42f5156375e8cda1caf1f281fdf99d67a621b8908f8a6e7da7c33eb9cf085916e64264310211232975e7cbb648aa375a4a8c9930da2a322b2ad42a74fb98f0272ce042c917827fc6803593c8386c5fc14e0819d081fb29ab9bfb5fb6e4653d5889d8ca50fbaa8edc0cf9c6943403a5b755886b107af9beea17a8af1aa42cd45c0b573251727fe4c9028a74bf5b44e3c5e1322bf0b6388af808d35299a46a24f30c267bacc064731acfe5b84ee14d56064b9571c0ecbc6d2e047e40933cdc8f80cfcea96abea330cc502808795f54291a87ce1c10a7a626b83d533cdac92732035b66c614c73f488e349b221a9c2d9e947dc97af0b4a1207fc51203c1099ad7f45d28460bbc90d217fadd14ce8a62e794b6be28b02e57e34e51a30072523d9e8dfaf5df9b6e0db98096429a9dd9a865e9f0bbad4058ae95488e213cb0d9c3b01847514cf1fb3c8041baa1232c15d980fd59fb2cb0b55dd785d86ac352756241355b71307563dea63f95354ea6ada82d292582fba01fd9e3fa1157eea6d21f72fe6808dfd315137ceefa5348632dbdbe2a2c18ecf0d3411818f032acb787f3878e7973ec56a1f9d11eb3f80d12212b9c65df1090f0d0ce8e33979626891b94125d44bca4b4e1a819a393f3769cd35636a561972830e1bd067aac618529b3b740817f813310538b427934b1d8b5664f51bb81ef69006b4058b4dbe78ec9b38c775098891a222be44974e7f5d4283b2da4c88e9c1bb05b756ec86a0d1974c468b81bd261a82aa7cf6c3e5dbff7e47dd800699ec44250e5e7e745345230d76757cfe212205102005e1eecfbbd174f2ff2817eba8272b016c1581a7de86d0674bc977bd2126d3881f73bca9e5baab80bfb9297441a8f4095803e8e9f9b130b5a1d3321a0125409458516b9ddc776284906e2d11978b450583228d5312c26f06407fed2530b4486f5c0d4f7fe69621d0a517d112400a2e03e56ffaac6f2591b36f2d9b8a81d1324dfc4a5ee127071879eed655fe2d142702dbaaac7ab12f8f9925a59907cd8e215c753a2def62c0edda08f4c8f38c07e205e141e359721a07a29e38ad6656fe976fcb16f5ac48d4dc54a4aca18549f6780788f92d6f37fa7d740cc28563592e4be3beb36e7a19d425b513f680294dcdd600bc027bc8b38023ace1e70df496d6a97222d206703a961ae58af861946ba5310fb9b9d93d1849ea15dd3d67965fa8e37c2406226566f36f7204b5018c8d6920000c37e799d501c0da22952a51409377b74a6cbc6a556dce192f036dd570234806fb5c747c12bb32789602d68b972299d430de3f924c309583a6edfb933199380d4681e5df110e82ff578c03dc2942285c882f36dbdcb1522d1adc05b65f5eb50d77aeeae6961a64c94f93c980a693b939a5a672da14f66abf068742b72f898c015e984d533ec98d21a270d368d1589ce066d630fc7e0ed088a98c9cb496ef3703e191f76973085f5a72963a765a2be72e6722a9e6ab3ea9d51e26278e37bd63058bafb4aa684d718c77d7f14e27128e60d9336d59079ca1feeefd1df6ec46b808030de2041d368cfb418241b792982df1479d07bca84fd1d626fa6c6f23605603a1a857aa4b4c552ec42e71e38bbd254f85dd9c1e3d62d99a5c1ce74861e9dc0c30ae397eef0e27c776d30d3ebc9dfdae013819905d7d7f20395159ff0095be07ddff48205ec3bfe1b0b645bd63b5e7d9963f60592164fad0ffcaa152a1634c09d275d541a0abed1810a30bf6025a231f62621661e0692a6526cc6dc007c7db05af9b4f6a1b83d9dde96d1ec97eb7fe8147c7bd6fad8d5a113806dba66d330e02b30078367c0cc49cbee6d0a8077f1458bc3280fe6f596554622c5b50e43a7d0d8bb02bbc9d2384038874a58a3dbd8af35905369a76ca1a84b73e12d0dd62d20e7fd20a9177089eadd274ed09ef2be773e216722f0c76119022ad83f885009001e46091a17abde7b3af9a74ff5350783153bbc488e0e6c2260e918e1fbb121407e29323952c59ddec35b7a760c4c89bfbe620171287a4aa6898c9a187b2827b041efded978dbf705f18f424780e789f2c74bf010d9457cbf89673c275cf79f70ff0b0793da151462b629842e81d8290fb17b419bca9dd6b356ceb415fb1e40f0efba14eacc9702368b688b0df12bf0229a95193f3aeb68727b9555d368306c30b9f4de41c5630cc09be6a34770814535f8b8b5b0530a2184216c62e64576d2c01d4fb7c0f7765fb29e1ab5a4a5e626285e9e8af0fa6ced707c3c36fe2ae14fa00e5b467e54bf7bbe2da3f6b37c714ed21c7927beaca338b08ae9094cca8d6f80cab3bde49b255a8851a0bf55024c9370d65224680a06af15ae28645fc4be38706894be22ec8b0859f7ba6883bd06c8ecec7e5d29a1f5b3d71f36e544b1cd7f5008090c177134cd4b3ed12ea4465b4745d22c3825614a3fb71b35c0e047704ce01806e1dd4da697aeb779a8934ae6c83e59e81526a02321b790736c26b20002a082e60fac8edf157cb37ec8aa66a6658ce45459a1fb0c3299cff18c4120371340540b1216954dad34c5865277ea3c53e70d954acf265b57e8c2c0444f29a12ad0866cb496a4a114616bcf558d6f2165a2bde3fcb08e6f532761970ee9d99722c0dff77a3c3f10810c91c2f38069ea3aca2886a45af5a0ce80278c59bd46cb4260c410a215919f04b38d7112709e729e41fc1e139410b96017401135eab589e800d4e5d175b4ccb3f09144224390be942f3e8cf8f77c9a7bef263b90df2402fe60276d0dbe9f18c6c682869721e30e1fa326545983d216abdac8e5813ce81fecd02a889e6497833d270609dbb4318520a80a80f0b99a68d1526c3bc9f99371ce20ca85ef2c02a89c1eab25d6e5b60829d6344a031bf0fad62a670b7a53ac21fcc02ecee08fa66123a0be39535a89237570b3c8869f97fef1b2227443b13e586850a7f90e6453e2f7908fd432b8c2425c7818995c423c4ab7d92f88893b8388b5f06e89713115e636eb34c216813afd2027e1daa5821aced4c156f600a94d03d1b0ec0f7f3d44c59223e3d99ae164321dc475bbb9e27d2be9673c423f36e56504d0173f0e54eeeb4497cf84098028817e5c86b6f7b3b852358a65968a1d93ff468025b044eaa2648e1c5353cc3fa60de7aadf7b9e066bf65cfff7257209800241d0c0292974c4ab2f65c38d5ce61e976cebb1d20a894740be4d37a8b73dcd692130e7be0fc910f784bd2b823e55c3c3a0f577fcc0165cd54b632bcb0aa75cfbb4906771735ae1c81ca52aefcee14ad3926b2849ff7f3e1ecb7d31d117f3668a6f809bbce90d190ebeb9f5409b81482408cd107dc82ca96bf65d8f231721f2daa6006d66c66b2c1a0b35cc68a9de2b998595dc30595cb6a29366cbc5711b786c0fe08c47b44fb7dd3fc8799d9ffc7185e064c0e8f57a3e79b6cb0c1a76f6970feb807cccde40480637b909daf8982d5b1c0b661f0173948bfe8981a7837736f880004a4e9f5e70831fe78dedc73ad08e08497b7bbbd84496a821675f0718937f5fa0bf2eb93c5466fba6888abe3ef242149021a5ea5fcc18b8a4be8cf065d6dba42038e394581251e70f0f5813efca2aa65674511d0637c2ca3f4ee7b46626b56620dd9bd771b46c1767256c7782a3c582f9dda2db7b358caa4fb8f593479ad77c808e3edcc61f64433b090450e0bc34212bc28eadcad8d4b8b34c9d42b071be4af01c9d831e88bd88d13c9fd56d0f97ada04e3672a8d21d464cbe916929ce401fa09ba83ee90dfebaffea9537c47ce6b1a7a0c4166b35cc10fbb5642362458416501e69ad24380a4e646e310b5256adb19fb87a054d5d25a060ba0833b77bc4d320578aacede410e8f9d85721ffde4f07085507b6f54df9ae9a8861a043a1200e803f03b472e949701e039688103038a5a525aac1dae6540aa91ed4ce9c2024dcb0555871de7ab4e4719fcdee7fb18358e52088ac23c863b0030cd00c799ea1c9c05d356152c898d80550cc9775e46afdd959a3dc12414b5ba166765a2afa86b4a0bf6f5272c51d08e7f2454fbb8213aa3aad68414f224bdcd1e0fa238ca82565a0737db268e942b8221d43f6d5ad5f751e01d3864fe74c79fe973a6dae825862c07cc550f75dbea9f1044f346c20b727c1e2e31dca662203da8878d752edbf2d30d4fc4bd001ee13fdc6c36dbfa06db4816095a5a0af45932732766b231380fdb0d84a121f2d7cb38553a2b6d9ebaed085c06a89e2603eb0cf7e73073dfeaf9100f578b6615edef6ad73157a48c635c1ca974cc0ccdfef58df188ca036bc7064209af61c971ed8c191256bf0563412f83045919d7829a689bd515f113dd76f4ed0bc231f97abecdfa358f1b2c2aa38cdf661413f4127dcd6312b36840c4b4db16035002fc9e92a5bab000d78aeddbc23ea79b04044c457266f908770d3a1190ae0be9d330cc701054c5e829810763157646421e9600c96030ae9ba1b65c6cec7a00ae260fa5592851022883dd31d7bb527512e57b7978c10752c90dd5b9ca84910c4599655f20925c01dbe73d7824b8d96cf59b0813ec0f2d17535365a4f125cd00df621e6bc3bbf50c57c7ac08c48874c0c6d5b96ab3b24f22c025377260e64b0cb6b85c55995d1692049a9fb4b85a20befa6285ba0005b6f272f7ea52488c9002c2c99f17fa41261bf5eef9e0378abde20a562d9c9ed0dc3047e947337550ea0112949780af154b550bf663372363cd9611b61c0ea6138b4e6fce02216bcee503839b440d9e199636a516ecfdf0a3bb61ae40cac3b8f965a2708fd5cce9446b09a74d671edf4d9a0f41e81da63d853cca4e15e02d54085f67731a46a6e4f6c100293285edafdba94dcd7630e06bd7f15d65b01d9e9cf6a9202cd12a96db6c830317f950ab055d9eec8caf96533802508c07a4e89ab64b73bea2c83d8628906a085682584a09356cec579d85c62b891431532fc920aaa713474df0f992c9464f0b9355e2f41a7ee0e26fd7c836012d1c6cbbe5b4cd4da0cf33e4040fc2f438b20158f89df674f9f94dec33e41860fd40d6cb6c2d5b90c6626f39edb0d53386c0006912743580a0d2ab9f6b86e0558b356778aa2f08f9043f735ea37b826ddfe2029484ca684535826a460fcc3b3ee3b698cf08c8ebc7f8e5ea773414b0895f830bccc2633a7ff3f73350d99ecda55303ae712c9942a9c1c6153e84052077e7e40b9c8f247d4c2b84a6dfc34ecd70975354802f8cfcdbd528122b210f2c4e15830bfd42c45dc9a3db6446ee242ba0208eda031fa6fa028d3b56cc37b14e2110880f16fdbf0d85a4fd50e26a0ca5eedeae8df2e88b3c7699d57b9daf18b1946f1a00061a75b9bcd55c5d04fbee6353f0e002aa24321779cc9c05e9e2a305be81e00dac9f8dfa9b1300eab133603176e4b97acaba4958fa18a1661cdf97382cf46204e5b6f454f5bdfbbad171049b065dd9b8181b06301b1dcf9fe37badeb9b238b075a36e6dfbd8b7ac95d06ae765bf49af8f6aec289ea89f67e4d790dfaba6d350956052a6d5c160caeac8a0ecc84e0958e4d9569cbb2e7bf0189b4f99651939a06d30accbe9e34c87019d24e6621fdce5fa06196b6151b584054d370c0ccf5c107edba400f99f70873468f72a31056a8be38c4562825402bc674af096bc5670306137b0470e771b7a1b3e5e7c98dd10d99d93ae87f2379abc9a485568b4827b200e992660b0aba8ba239080c46c9f81c4abffe8e9851812c9397f4cb7baced450f2752189331d2926594927b159436b12d8aaa120673c1e4719ec533757251e90b07e0964caad10de6618cd27c815535d12d900402f00f766b6c7ec4c8df8bf60db4b5fbbcf8dc387a6828e1fd6bedb3f577fafaacca60ae124e8eb8d199027a0d2fd53964fe753c0b22c02aaf67f7050330480ec675e9e7d8704cbceca66e9d0d87e6582b7ac5b8f2a72d497eeced7e441b9db7a2bec6fbdd32a8154337bfda0482b0c935ad4fe720bacfa874af01f4375441eea1d2aadb2a666d90ca4dadf20b6108bfe7d794d5fad99bbc8c96fc58c44b7a597584fff96ef9ca2a31191cf102e432f92a20e47c898fb778dba7fd5eca605d431167d1a8ec67a8a07ef061cf0a192cd7cd352d7b3238d1fe153c7ae6e14961b75dcbe9fbda1d7df7c8767f840d0ba1adca9bfbce010d94fcc84e3380ba5e91b1389e0fd0577d178f2bef9fdb0efe5fa661963ec5f75d709d829c23029fcad65d229ac575d690263b7d708fc50a129a04a8ef845885cb390c1240b4b5a9f91bb5e7bb55071297c9a1fc9261b0080ead26f8188ac0c4ebe7813ab5cfe0579940a8fc5270d06bd090ac40ba663c09e43bb9bed41831d2642ef2478dd4140123418749b2553d990106417e5ad593051b2b21c2710fc3cb572ea10401c1b3b7cecd75aa859f4f3c81ab25e318f7f8086bcd6b76f3c532a83d67c72ab6fa27d5c583e6e90add31689a97ff7020f1f406961f23167a25460e7f59f67f039b2ff65fe687bfa4833211099d37ab8907fc0cc0d6a2317fea72da832ecea55897f8cae9fcf9f53381790ed7eb0703eaffc207507d1240cbcd8614317f6cf3ee5d8ac6365da5816685a6b2913a92bdd2b99b0036ca88f66f1977e7fdf35d0becca6e21c069273f38b269a510b65d06959e720865db712649429c3dcc0344b6cae3ec645e0592d211eb213ffdebb8a15c0f8f09278c8c2b6e0df86bf0d2adecd7cbbaef29a043d0d4273f499126c3657ac397041f492383154eb1018a44b6b91731a710dde36a94c31eed10d1f2271293e2ca05a58d0b258cf7663baa635001224517fe0b2181961d0d988c3c352db63d4e1a0f1f22dca686baebd32ad587a6626e366f198780f03bcb53a59e879268376e6d05d50468edf239b6052c62fcce17fc6fa7dfca201e09423b332d82db8dd199540e8bb6c8aa9f0be4358beffcf6cd87b0e7ef1a33afcd617e5d1b94cdff69834c0695be85136b5d49c063ac2b09b06abf03a45698e0125ab938cc2448f1e1118d028201d602f8294ea1a94682fcc8e86d9a20e908fd75226c7d3ca761c78f9c90068b16e334b0530ef5fc980c8ce52fd8126f1964f9fb40a3cc1f84aded8080740573cb4d3fec577be13253d7e790de0c57190774244348d28bce8bb5f395f10d0507a2189ed7c500d5b8fd26a16a5ddc5f06678df168a5549f5b3be5898f24a50ed94e8c841aca1fb02f2dbaa74d07518f170dfa67a1c364d3e99d193ce2ae120bbdc028442a3d83d92813fc8364ad96216ce029474aa35e1b4f47744b7af9af06eecd6547628b2737906c10de34cdd61de2b3f30dc1c6179bd4dd6dbc97c1660f156b932010ba9be9606ed98d63fbf97461799fd1771208645bc384b992b0ce0378e9ecd4d6fad69fdd36d1aa789b60917b46bfbe95fa388d25657ab912717c0d9caabf5a2010c0e0d31048e89fdb72c02556922a04bfe49d568d360985da360576e4f78bf949ad04f13df9fb3060437d7c39f12aa7e373960ac89511eb49470ef5d9dba36cac787ac18ad82d6ef17e2342661122d93887078f054fd0d1ec580a7efad90580186b319445d40695985d9ceba28f6d2cf24ca84caec98ef7a08a0d3f853f7f8409bb2b75f573266df603e76c3bce920245d1a48d7ef3d103136f0b3001e074374100ed373ddc5a32b52fb9cebe98cc173fb3c26b9bcaa9e1df880e529b1b337599d9243ec0f1ec8dce857cba0d8d4c9ae0b0a2be67d57a948114037fd6b02b7c1cd4a7f48bb58158e959efe95608f06ba39ac5c26b81dac2799108e907f0ad19176d2b92ae91b6bb765ee25edbca1ed61b722350fd394cc518040b8af75d139ce28cc739076e52f6045ca8b6d956e5d054fdcf443eb747bdec6d039f36063f87d29e3b29c593d5072b63d5677874ea22b5127c7c4495a85060550eeec8563ce78a8182a190e23a2d17f1147b29a87464a0ece325629b0de7c8b60db316c071da14a4f261391b6887974ce0395f9a5507cbcedc8145197b21053c0b70b006aec59af5ce8a7f67a8e6290987a345287fe1c095755c69172a899a0e08c10fcde691aeb320caec3dfeb291bc3d893a77a6a59b1df837f71dbad054630ac6d5a3b7f8da3200bed089078d78a29db62e66325d737f0076c0aa724bec250610b4eed9f6152be083d56fc480b5d10166ec6a769e692b0cd0bd1ced906368025fd4bd1c4f24c8cc6d2d7668bd5e33e858b71318c7d9d78596e753d536c9060619f2d34b3237a75eafca86b9de47d830063a981159cf8d9ddc927a7b7a21fe0a68d25467b6e3dbd08c7923e8b431e1149c09237ff983656a8dcf78926e214e00ddb47f6cde71490ddc58b36db5b0bc523d7bee0ae125bb614195ccf652359102eba584507a4321eba6fcfeb88da46a100cb6b39235e7ea4f1f4b6c4b7738cc0356eaaf013735b2fd615cf3c741790e9132617c4a5f01e7359705bc875489000a5e39248f8b8923f8799e90ca6cc942b94bbd83c43941d0b10ede9b6ce0c97700ce736a399acaba6e86bc2efb5bae695bab4f63d5bd55af52360bb02c4a10fc0564047a8cffb4e4b9b3c939d7331b4f17ca5071b24851c1bcd42ada4785b52e0a1ae3954fb75862cf31db7df00265c0bc85426c21e9f5996a789d45f56e35c304fe5063a297ac690bb1d529e6fd4ad9caca5df5ed74b1a82ccc7655c6c5cf1305ef906cf807693044a7fa18a2f432286693d40577757dafbe9665f8b5fa69200774c2492237e705316331f5a624d3400e4e7971dda2c5d4cf9f112f67753bc90cf86f09d26b1a9ece4fee6c6005e1b6d9be8efd92c43824f470db90e94763af0cc8aeaa0601a4f4b7f286940235bbb5eecb60796dfafe1f58a53f566ed4c1df04bff2e17e3dd053a89325943da3685cc01cd0671b81d7890ade28ee591e98240c3c97bc5ddcf320be785b8f3e8f5bbfba6bfaafb65b5f4973f7ac763b80f1c80d76752408a19982d742492daf4dfa1079323309a405685c25c8bf0db264e72a02dbbf683f785744fb9d49e3a0b0f3bc4abd79e8da34788c7c4c9a0d75cd09ad0b308c3f9e869924a1ea21b4e0404d322ec6a0eabaa4654da8d1d72375ba34010c0cf4b230625c002cd48db7258ae08898c00de27a6db101e08995e608a6b7830d5b1e0d60f8089cf0c6056a0ec6d53d56461b681b0af3b0073a6771380b92710a7defd12fbf2a821b13985988458af7e6848b21af018ee3003345afe072bf0a0c685b4bda91a0bfaca848b854ee91e22f107ab30e9af064f0326c92bdc8b1c1025cca3bcb692866578f69f498c130710274d64da47d0320fa8bb8088a15951f0ca0a46abece0a151ef2996c3f359f9e781151e60820c9215d45bd29bcfc188402ce1f960541d4967d04f3fefaf06a0fadd21d8622a36896daed78cde05ca9a10ed44dcc73301c8410bd83ee68add1407f268c44d501aba7039e03b12673245306ef7bfb910d3f7c53bbfee36fd8850964ff419db6b144d99b740638640468de0383a1e8b75d666f943b5f640a5ae0443442a76ae0daff5ab06dff374577edd00469382c476ad38c8248966f702284ff6357a320c17ab5147dd654ded11eb2020f51aaaa2afcb5be03a90fa799e53d94d2768b3dad2bfe3d3d020895dd08869903d78e554bea74e08ac15f095d189b72b2467b365c76ddfcc8ac84855902b5fb050837eb69cc78ba404b020425aabe290d683d1adaa1fbabadca63a44f69bea90e42f4f9f7809f1aa1ddd76906f9f1da1e9a21dd5caab197ff0c048cca1aec290db5b1f1fd3cb20ef4bff26b417de9a754352af14ab44ffcfa4b8541c4beac6e089ea0beedbec2fdd8115ef3b9adf9388e35cdf597196d86bc0679fab663b7c00728ab5373b5b822215c6a8ab23249c9e863b7c72ec29c1b1cf9fc964c5f2ce605b65062a1d546660eb74455a4584959cd66eac8ddd39af96d273f1f21b0a6c808cb9a5c0b9482b248fa98a04f546cf0f5e177125d137ae4b223ed40531fe13d0f92ca59019aba062f4ecb5fdd85afcf0231fa09ec5bad0db69c9630362f2f610ed62b4f5ab6680ad21dc22e9b6484f9235906059e4497f7d3c72d1541af407008e1c19c752b4a14f531574c851e4002fa20bbb57405ff19fbe48edcfb2eea6d08a6169e3ed737fc2739d15d99fd722bb76f6ccd49a6de5d0a2cb8833f5288820898a7358f4165f5fae0372f4c857e6cffe477e2bfd42f54848e9196f18dc9fe0c6dd1480014dd1cfd1edc84b2c7ab3df7d7b77e66d8346ed9f1d701ea8b66350ff919a35ec6bed8324124a21bb567369f979deee7984ad81a9d4abb931d1c590c44e058e154508a6f7e5d8bc2d47657c0863f8f00faba53fac0f328dbe6764904f7171500dc91630d7691408f36af7a36c521a39ae7db3e9ededbb9eccffa9f0201a6d22698036497a9bd9af50a2907dbb9fb5b74d9bbd3676d2f74f06bb6500bfbf9b3113b9a1a660813d7f4ab733d6270dd78ba376c4fb81281386c1616d3011ee894d15f41b0df104ab39f9e081e8a66428f9fcdab1b747db91b18353c6d0c7ad4c4be69155d31afea6b5ffa1d5c07544722602546ab26f357eb501f5f8e0293cd216f24a61e600d29a8447aaa426c3cbb8e23cff63b72c95cebe1601dfa055d81e57dfcf7ee3336565992e8c9007ee5adb57dfe6fa14791c68d8539144b06369dfeb7fefee359122e8640668cf3781f13c32f1e2818c9b88954f4a3e0df0f5cd9a1c909e2e15c52673808680a917bf9a8eb6c5ae4fec927661c1d2f63080b4fe29b8e1cd3c872edecc42229a8429b512844c3eb2a2293f1bebc87900a9b0c43cb43e52b1b94e1d2ad05770c89d56c7253b596bd6fa9fd678fe372c4b38a09a530040ed0cb575afec3ec1312eb467af7e7f12638f5355aa41f2f5490346d0db5615192b833523409103857a662cd4fb09549a927ace386e4b56829d937410b041ea1a43f2bb80a374233caf745b5bc4728bab3410d6ea705afcf04eb121d0249dfe90e1b335f3e94df0d279fd8e9ea05918e9e47c06e057ec5d2abaf6b1a0355b7718580bf466c2f1638f9f1ae6180d3de3158dca3f0a3d1db2a9238d9700bb961ddb1ca3c094279a872e0b1dbb54864b56a3bc644c6d1a73def1c966236023babba52a55dc7fe4e20a7bd2f02734ae38c6d63074327406eb0c2732b6ac900145d11743d7c53c466dca4fb94f539d917375f9faa8627a88cf9e77d8a51e90d33da02857e8da7f02394c3a12c6056fab7f1a1ed17b26b3f08f47cef6b58e60bf5c2942e27fdeeb2aad46837efc1042dcf14c39c93156395bdd9c4028f26ed05baa074e27ae32471222d38455de395c75af840f30085db30f330bdd4b8b1960ad257c1847a5a1a184a2f3afcd3e501945516c030a8b16d37d9391cfc550af80208c7d821db20b25a5deb2a430ddffb80a4ea65a63a738d01c363beb18769760949863e1271c39d812e1067384c50a2fd66eb6491694a81045746bffb1615cb01c77761e32963cf54330714d55524a498832f338065f8a6421b9722cf05e1270a33ccf7c41f9736599e776ac8e7e9a4d38ce96061f6746cfaf65b79c2003f250528e2a6c54c3aeeab40ce7177e1d398697c192c3774c9ec8e3593f6bee067130c4a366e51e325360fdf41709f5b6e75a26ecd4349409871af244f9f208b89680f7bf91af4becf97ec1c1a049e5e0bccc380007b4679986dc232b62b85ecd6f105c71450705fa92e032f1ac7b49f27e1be078dc039f5e678fe2731195a20f27307e4303b096fe9772d397c20fc3f19c1cd148609701ad90a6c567bf3bdc507a1099f7cc427cbe5f6f16c9bbbda10afa45c1a37dc668918f88928ff07ddede85007b6e45d36ab4c78f27b29a84274d0d52e2202427b5863fdd958c723c51057f20288b0b8a93cf95cf10841197cec5db2f2491535e72026325c23dfd14f6ed8ef0387a12ba95c642a3d198d8ebbbf0eb1de63d4b481d721de518769d0eb79d90809b4844ba44c3317e623018efdeae26e261d0c9e739a5c266a0e8f4eab15593100d577e005c6095f0ba18b2da8d5617d2853bf9f2afed1cf9d5a4481eab86e940de066f2ed877ca8938eb88804de011c14d48d740d47efd1907120d01179a362026f7bf35a3bdb64aed04d2ac4779a0faba8e9f705c5200135fc1ed93924db780295b3a2d9ba83ff76ede97eecef7c8df3e2d2b6808508628dd07b02e3d95cab0fa694555f36c424d754a16e0e4c6b9418e6a4a1bf37848b3ebbc2586397faee09a1b7aff4fe9567009a24209f21079c2b28d96c3a11cf47e45c29b7d98b01780a947ad2e2d43a2fd2b1b8d4e6672af2565864074a06c5580152da38cbf13ce50183239eafda1e75efc406b1830b3daca498e1ee2b9d4a0b298c2f1fadec1f08099a45a7f6637f40f413842f9c7e97d0ae25c59ae9e67e7330d1b4732e01072503f2ee1fef93160b5f3555f5c79c87e9407235198dcdbb378eae108c3e778728012b74cdbd81178ec8ca4dcc907729da68aa45bd89021760143eb74a2303afdb0d85228fda3f71d7317d801e3c36d381de8a5449c58e91c8e74b4a40f8dbc34f0932e36e529bfca9dc7d900b68fdddc8ebca8540ba98af4606a54dfd63442b900760bb60f37d4502e20b777195aa3b9ac6367fcbd24517d68c635067ee72c7a004222ee374cb9cce3dfae04908c9a831938587d62afc3fc3bedd7ebd4d1985900b2ee7742c9759db20e5103a408003251ba743b32a609b6e4d26c4c3539329b90837aac13d5882d3f1cddb23ff159da0324b5bba80584955e25cf74743cf0358029e5173c4abf7fcb45b3f3474ad5fae005277830bb350cc2ac3ff23022f9db500761a4d7c865dd3879e70f9b95c30d33dd3f5eae15c6438ffea0565c042b61403238839bbbad45acac67c7b2ff31639c8fd940ac5f82e2f924130671035412503ba250c182f0757b2f03ef3c563de668f216b3b47e5ad0b338f0734351ccf9e019326de888ddd9e40ae7a9cf16be264a44dbeb550611d638503dbfd367c6dce000835fa7b54ff314f6c7d5ea3c86dbb01f8e600bef4d212c915e39ff84bd46402ed8f11207a4dcaedac8302a3398fe5c49ecafb8f16d69aa87074694b7ffd7004d0a0b05e0fba91ba7eab1dca90b2e504d4c3716b92a3a5792344eeaf7c67800f88ef4bdc37ec0b8bd89f13f8a0d823f2a9eeea9857bf5a58e5314d7dbf1e3e08676c80988456341c0475358d4d0606ad1d65cb5ef340367d9ee055788873500eb5662cb7c47ac9fabfe1c28d71f1a8daf2390d71959db7fd31adbc6b1c6b2606b6d6114d7ff9f33dd8734f1860276d98d43bfac59171a1a4328efe5724f12106a104982e892c3b6859673a1aa0717a51f8932122f1623f2aa8cf3af9e8ad3d0bbfcf2169589266f138171dc5fd4006f8d26789b89e77b8311452c0d08a994804b0a956e2e97203ff29339ea53ce907e198add326438e8734f0dd5fc23ddb1c03d292e4cd9d0c82350091a198ec34ac08e6a290d1a5a01530b79ecb2095b99f05fab30c12837c0ef97938c7b9c9f6c83495a6fa452ad45eb308baf37c11558303607ddf4471169bd91b3687c71dab024ecb88d48176932c2e840928e2f2017b0771e36b16f1a90a6e647a89143d1305c5d38cdbb9698db8ebfc3424ae0c30310b508af8d56189eb156493e63c4384cdb6a8a1ec78043d517c43b8d06c32c5ff0220d5a2c6497864126247723eea92066d1ebc3b2e0a1ea9e4e2af09a0a82ae30d407f6117a8c102ef670b616d068dcf557c66b04c140377ec3ba5a9d1cd11230f3d8e6bf14eef37e3d2adc17e3e8ee8c3ebd374f6f3c64fe6d90dfb2c7eccba06a2177eeac7d16641ab8bee79eb9d506f203f643e348c2beb3ce4943d28bf4a0c4e9a67536e8ce38ecfe6a76a24d72f9ff5a7a7bb9dedc8d70caabbda5f16ef04e792b848696797201fa1cde6519d9eae1ad056911566c62b40bafc0e50c0020ec0c8d282593c702f2d09aaa782a341034194906ef0529e48a31c25a024c49e0c96ce4fadc96bc72e08202636ca3de7cc9eadcccb1e37c3f9f6b19b2df3cb8608e4c9ac778cbfc638983a79973f17168421450890221a725927812146afe57e0f346e84a38f3634549088048dcd645389fc3802e3386cfb5b3034cdf9904e1f0e567bd2df52d7ba5580dc6b99a738f3d64979055e4f13915ab582908c12a9e60a1a60f042bca9518c9c804bab036e5b45993a1bf1cf8ce5f03551892ab398460d437e72c8f301bcd9e9a61159b6a5e0bafa7d46c6c908c23a3902fc1eb05cc103ad80b7306fd55d753631589887742ee5611a147ba5b4e01a671102e12c895309097e045a6f80d7fc456d501e6d85d6e8b0efc4a31f03346d844467a6f042e30bab627e91cfca7aba0f2adefff8916f4608f16c28d9b8448d422041129832cd01c163bb381f696b0504e1d5a895443da2a606521b443934c44e64d07eb33eb00a1fe0d0fb1f79291639fe4bfe4101eceeaaf4f32e6a241256a8f843c97c14ba07ad64446868655f4fb78873f81e388c04286277f9ab1c620966b4ff2cdc7acd0ed8ed072e45b7fd48aef7f7569aa8311a19721b2793db09cd4799afaca643bd05da67356950a26836259c009420d81518a54f7debd7b1bf1570e14f11473c6a0bab9495700c5a4aa68eae805c57482a990e9657aa169d1973b9140b54632d2c0ef4d08934c09dd9a2604435a165ed47a27b9422951d0fac8cf9691ed3643f460b82838e8e13b3c04b631474c59fba205477755d74f2b8964cd98036375c835806e1fa096b6cf3439d46074891329cbe5ddd1a8748448873ea1e705b3ee720b50613011f3ff0d7bdb41ac162db156e8ae50f991dd10c9cab055d6aeb5eba58830730c767e0574887d79e58df086e2fed39b9538a8b8128bf57df57a78c6b971200f6a776b5be33ac2bc9242b4a65d4f5fa249e2b788ed808990cf010d42459ea06038df864091398619b2600d79aafd88aa3e99f40bbb1cce8ba2b305c50680e0d5ceede4cb5fea7c327ffcc7a9a6971bb6242831a2281b401b17933318cf5fc0ce4085772d797bd0d5c67b0db3d436aadbcfe4341908ba1b663a3b7b3c0a16c0665f49a03679da9909d84732a7b481af771fb1f3a172425b189e58ffd898a1f004c277bbeea7b0886f13bed84cf27a497367be6d4406e7939e3ab878d6cc96600d520ba28362821c7e61161ab8bbb90f770d0d4a08be8b8bab1dd68219201600c7315a3bee80212e24b16d8ca0ec6472de07726ee5796947dc0987186ff4b910751cdddfe4bf97da4767ba5cc098c606c7553c2928ae06d8e7fc714b3dc90b2009d1579e5253688b050fd10e0643f8e21b4390c0b7dc94a75ad95d727f417ae02030fabf2b30d59bd0f2c3bd1debf741d6287e19a989e6ccfb7d677c31d7d2e0c6d49703f63aac66123dd81ebba7bfa2558c46fe3cea4f97920f7079ff43ec30a3a8985904607379f864d700668e0855000d03e95324eebed56753d9d575e7006eb15fbbb4369263916869299b96a665684b99b43fd18d85b0e1642018c00e90be38a4b08893bc4edad8145701a23c922586ae398012fb4dde8d1176d1043050ad25f5784763cd210e58303641b9d42bb988ed9e738a228781da76105afb0ea0be9f31104bc65f28847d0fb25db9171a5f24c540e7b5aa0a737d5a9d7468a5400e87af021e9577004a8240a65287823cc13d327d603bf6658ebf66c8b6bcfb70f3cdcb4caab4d515bba51bd982670fd81a510a17a8c795ccd9c75890a785f83091b07cbf70d1a7c42f4d914fdeecb81004a41ac79f737aa7917277593f510eb077c477963bcb9ed7e345225ab6f08ff7d96b48543e48f6e0e5c6dd700fb173a0e5cb13bb26b35d0f01f02b1665eefb50d684e6957e4bbd9bc7c49d05452e8e9083270b4311bad39b944309d06a457d360f8bcea6a12e3793b56487e83679a8505be1a1e01baedf7229f1a387bef9fcef9ea88f3383047d8259430108d0df2f20737117f584c047ce37477d0c6427f18e353d06401e43df5ec45daf6b9e405d40d5f087ce513d30f284fbd47cb2bd24d853396155941c1ea0484a68d651b5039047ca0723348881f2c7ed69dc869cea6ae34b5c8e78176211676e1de6e2978e00248d8b06414b569ef0d2506f4c1cb672197a63c2852f51d20681516f512c9bb0c7bdaab6205815208f8cd654717c12d0f42c754f3354a64c0d27e2769e2532203de2153cbdf65a00c510e88817c8bd36c659958335c8275df2b64a0ed531d490e91ffc6b6c727b45455fe18d5816cd0b525e32acd4b74fe4f3d3437cd0e543b03ea214806e57569773b395f1de784b9760d721a1fb01b6621e59239bbf65e660cfc3bd18b943e13d8f3141508c1593d7c4154f4c03d139fe5e437a94ed715d50e54861407d588c70710ec243319f70844333810db88d39f846233a913c56a4f01e3165268c3c2381a7f4387eed231dbbd104dd88e6c7d12beb04fe9b2151dc807cde1efaf306047b51c1cba7d4e2aca517f63fb76947678e597512cfa963861024ac5290b035f8da2318e63716f883e253c8d69c6ae2fe9b42be538185dfeb90389925501b11044f779bd89a28fc078faff70cc5a2556730f57451d4f938dd10c761bf3f74b54d16a7986dde2cf74d8735a4e4d10d0fcbbc34b3b11f3221f2f0341842fccbc5317c243a7c7e71d04fb9fdbf77d62a4124c9edb387bcfda2e2207f7c1b80590ed0dc17f5c99213e62fe333046e53a5f199804bb113ce591116a0da14138759d1be9d78d966b7b7b76cd8e0bf846a90e929d63d98ed6251be5e60467e09023caf72f15b5907a87eb7a2c1767a9c5b6b4875654c913cfd9b414f60c61b042042705a0fb4864af34cb3de603246d193a23bcd28685ca36e7df7dfc0c879640e4196ba8090693e0799dd4e7e744bcac839b5c0f43a376039709016d03ec5d2e4a800606228b0d3334b7f2af41c383f2f2744461fed225332e76f7e80afeac8486c6ecfa8fec61fc9413c0b46ba83a8e757f3c7af9fffb980324f194013425cb1b0ab66ee3d4ea97acf13dc7e30c28e99b87aa0c1813e3f34a31e9790198702e32d1fef764baa5815a43f8ad47305d01fd5546ea965edf1fa2eb07940081e383b0d8f51d7c92c5b40fd9280049d802667c6b6ca54db5eb0788d06119016a5a0ff93c3606ff7c8ecbdd5ab2491895641283dd384375b535dcce6ae1670372e01c878f54519c394998e89c7dc05211c954cb1622d5a69ed2250fef7de0063da98aa80bd252c2eef2de3e69b0c7a491769b92dacdfaee6debb70425e71e0bd0e9247bd963f2f0da2c4e89b2db8271e6c7d887fa11b8ca1fab0dc7d0ef8508222e223daad8c6c994506c17d358880f5e659d2aea50ec0a2f6edfad3fc891043dbcd783595dd8c2f6bf4cdbb8785a9f23a02a57e398a8b476507082d36bfa0e4fd218026ef7fb57191f47e204212f0b7678fd7d2fc6262517d74dfa482ac802739d140871c445ab7ecd2e586b10ab534a1637deb06be35d2c4cc1037128b700e16bed7f18385f34762c706a05761698714d07a06ac144b6c33bd9a1b57ccd031a9d5979a9a0c6338636add6fd4938e1c9862f4efa99c57165986171e3c768076c52591db5adcb2116e3a7ec40704674dc55eb8bb425024f451165aca11ee3094cd39d0f46e81ce7cb78085bd0f7209acbbcf098877bb77a891bb82e93139207057a2c8280da90a19edc35aad99ffe53a8537d3fcbd688906b94f0aec0aac6020fbe00766aa389917604db0d2fab72d7a1dd226dc40e2c8ea028be4be9fbad056b1e5991814332c37b59e8f9803db4e5e112ae8eac808b144f8647b4aaf806046dcc70f6a063dd9b4c353364c3007ff4fe4ae201e8a09a44a71dc9be05d5440d56da880d131df7c07182c6d0f4771ef2185cc3c1117e6e27c8b8c028a7d2a200f67a54c09cbe831a11f10656eb29abe70865a58ff5b16547b66e43d9eba5530187dd8fa176cd5da88f48410e17cd29aa0369075e85cbf4e18b81becce75f02064c10cc6559c56b7535121bb90ed2165e721d9449bbfd9e998b1565eddbd78503bfac7e816e1086d6aa5d945edc47aa2dbc3a05389aa5ef71eb572a9bff765e0fa99eb8a787e56cd76990a887f0797230595f9b7722cf846f666540a7b6cf4e062fd4d13c92ceb2734bbb3f9e6a8f96f0d8310ad06af7cefaf1a6b8fa1d207c01265e5b2c50119661793b1cc203cd1fdd7d4257dc6535573460769e70da9d880e44ed4be3bdf9a8f31cd903d25b8ee91f603746c7b7a6f79d5b9ab39e392dc70ed5a462582399d4598704f2447d55f2e5678a181383b880f8917f81ea95e24b0a5b793d39fbc49da3eb1376184f89b5d48e3f4902310af5a17c3e997298febc0f172471a562aa4698e9a9e235f76c8fc625ee7bc32a6bb1bd3147057936acb00caec23707682363d8b9ea42b296a753e1c60a680e9f322fdd43119f289ee6fd0f442b239a2a8f5573315386f4e3a3091fc828db38ed8fb2fa7cdd9b52c2d7c40091304233de71dafa3008834f9280024d64e71f1caf8ab56959584f0a4ca86f062fcb56937b8c363dc0029dd5640bb7edc956e5713cb160f16c470de501af3101b06cc4bbba50ae95ea9fbfc2307b773dd17f1784cc9666b6e12d0d76e4866a09a5e711a12649993fa2acfec8c87ae7848ddc7c19e0202760232cea03b2a3660be2442c50595a3f6e640fd6baa44aeeab598e23890ce9aeff723045a439e7aa056eff3f136a7fb6c1d8f668cfbc8381aec6e502888cebd59e86be130f70ceaf0a58959ead321db8787c00976d8a3ac14b8645bef87236abeb9f310c0757996702e99bcc212cc504c1a822615356dd59b7eaa2f2006a67a0e2784bd57bf13ed90711f977c7d878d8ea2cffa7fcfa0802857873c9f06c3f549c33ebddbba0d75307da9fd4af0ad22c9affbd884d3d951fe7ea0231edc769d4a31a2ca2ecb4d83d00b660769c4416a6a442df1b6b4337a00b26161a08a159d38a988b6bbf409cbe0a276ab86eefe55531b030f88636a1da4a49b367c8625223a021b34234cae15a032088ede9e297b984dd15dd9cf867852d13455c92e7acb814421c1d58b9ac6f05b8483a37ad1f03bfb44c8edbee017793791dbe4e7a8eee99cd9037c71444e80b3ef718d6e1c8700b7e4febf9af0802e995b9193c90c482eebc5e648223b70707e3937b32605b460958b1606050f39fc8ba8d509e2ec1bdb44fb8abd9e086d3077e284e8401d8b841f59b750edcd097ed6813eef543762b4fe8d57c837e73c008a61f7b1b8d79d6ba12b1149d62b04ba74e26555809f2175b0239a547fd1cb00d803a1fc30dc63a5a081787ee466e21e5548aed50ed088db550f9807ecb51d508c91edbb5a03bb916fe4ded89a4494eac0c4827a3d0f9e6d83c701b7c024feb02eccc294ab17d746af62284a19bbcd5246c334dc42a47859463b1d81f5a4c5b09ddef8a085401deaf6a92bd0abfcd7d5917494a7393166153dde6402404d4b00dab3c9b2f8f49ab31d44e9ac2a30842843c40390d92d0d1867e0110803b0e490c7cf611e6c1a940fa9b751f52f421b6be69da012d0776fd6fa0389b764dd63b0f46925671ff31c16487617c103731ad8f4e9200f8ac3d2846d96838d07605ee0a61927185da7faeeaf41e94965e85b1b61826fe781035011014bdf4d57f6aac0e5db1d12c6eeefe5b8a1146d4f3f2722384637286c8397d8da307e60986add30899b97c94311a3011bcedcc8a4d9808b3b7e01e24e734976b6810f2bdeaae110539a9b3765f8711d25908266824982f2696008ba5eabb13db1962c0ebcb6a2d0128771967353c97a8f3d2f3b5eb83506a66bcba62e1aecc51d701e502cdfe62060cb7895e73d9538e4223bdfd5f9b84744751b49d22150175b434e649884a550b1a583b02280ae89a3debb6392499dbb7afa07e9426f93d729cb30546168ef00ff4300e49476fd32411f4a9ab225be8a0e8981e917ea0c66b29b219b68ec98504b4bfa74e6f4a079df903fc696deddab0554f84294ebf615e0e2896fa0410e6085def5bf4560d9f722ad68ede3d7d918af7f83b4e470b2400196cd907ce0a05021f44c4fa89cc57f9c879ad72f64c0a29294d89573278ebed4cdb8540e1b1930eb292c28a9351932f919d1822cfd5f9925a27601a805c62004a6d07c305cf2904581754da372bb1eb7a4e098fd72b164c94bc77df17dd129e037c195e8a45350bf548dfd637b2a441e3d13aa1bdd73931fc76063733498c12441389208a31320e0f03e1ab2bdd4c4264916a562d5567c2a7cca1896ef63685bdf2dc2cd493e80192f688999c983d4966eb2e4a79c12544aaeade2b68193ac1008e16207cd63907babdf19724c32dff882558a3d88a31e92746bde83051fa5ed97cd744ebcf4e0770fb70ed4f7f1876660e145cb04709636a36a47adf0724582c43dccc08f1cc0c25a5d6b3463c120eb9a26c0c1b38524f39c57efb00a41fa0e4cfdcf299996803d414b588ff20e9544a8bf6a3e192035ed080d8b6996a1036bc97516589816a09be4ce86af24e3fbad7b8e36092461a4769bedda2f052e24dab1a6fd21740b90f7442f46ea9f845705f1a6230c67cc476c386c4cc705b7df09f2e2852972396064f68bb7a89b7fb511c637d92bbb418809c548744b33e4a48eca2c436c0b4250c24432cdcb38a5bd8e9f93de511584b25d4e0089905fc7df7b2b8bc26a6dc830a6a086c3c008c24360947f56c95694002da7c19214a3343efd3bfc816a244c608ada515200e21642c0bde287ea3561fce1b550a5b07f8975bceb05d1eaf9335093bf549ce7d8db9133f415b4e57200b43fe72822fef269ccb514a27e86af55d0ce171418f0fbfe9a7cbd1c30e8f7a9a995314c0a3016b91cd541ecce7667ac20b403ed72ee1708826aee2a6fc5747b73d839a72af63e01c3e8beecdab49e37f0389d6fa5566c5ad7f2b7204ed06409c4fc7bd9891eb4a9b2762ccb6186f673806 +generate_ring_signature 1013e6d2970665fae054a3bd9fe5e1ed9e80e081cdb6ca240c0f517f1b415cab 0af5247217901d271584c54159546c10a1d682cd243e66a945af30b5eb427cd2 2 8eb838cd7d2596dde1caac7f8c29e081333098096355a3888f6cef9ad54b4c43 ecb9686dedf61fc294b3c96c56ea43d6e57500ca683d8ce93e4212bce07e71a3 f36383ca3516a2e053540ebabe435e3b57cebf3890478f221c4aeb0b8bd4e30d 1 5b7149a343029a5677998b993842c24f99086c80826de1636e895cb4ea529408af6de27393b35d724106ad6df6f9d55da7dc553931b2a8cd0c664676bd7cd80ec51041510e4095a24c2c9651738c6596a3c8bf252f9f58520ea1f7aae38a510bd1406d4600f246f92a17e5b2e1da53eb399163ff81e30f9dc9b10f4661ecc102 +generate_ring_signature 0b5ec78693ba8b68d4c52d569772840dda48ff5fb748ffa833e5392392c55dd4 be1f92e110606c4de9745e00fcc25187beeb7caef967abd9c355cc032245326c 2 3957312d5af6b690f318ccacc696d12ae70a51a5e59169a823de76c16418908f 4c4a89e48bcc7beb356d78e9d9455a67c53f4624c53254135d0f665562c388f3 6360f4e3a558da8015355552ef2b95fe491529953bb454449caf53a3169f6f0c 0 a14287ad1943b58ab4aa151d1784b4e5aa068821bcf8bbf3e60b26fc565fbf0af2031e84a70f31b6ec95e3e1c6bc29328ac67595c854671f0b23826cc2293002379580cf977d1e52d2ca1b61daf24a5ce80f656dfa089916a902a9da8c279b07acb5cd051626bcbee618968356d8d68730becaa709e193313be3d4b109633704 +generate_ring_signature a8ae168867259e89dfddb607d8121f78d9bd1afe3b56bdf7f8d44f328c407626 29c15d05cf7408ed0252e1d25c47b8fa0c34878017937a285dc037fe48c3d9dd 4 38aafb4066b703586c33d7c055353712cea2a8fc42bb1af683af4d52194ae229 e258caa68a2c25529b6d845e6477ddd241646d89135d3e860f9138582b0e2156 fe25ca5baae2ae89f703b0d17d0e9ab8c314eb69ee1b5ad3ccc2f178f7a13a89 ff91b9cb17606444470257f1b2520fd7c7eee2e9f62fa284d96c423fbb32c32e ff3f205bd350797a39e072c715c24902a909dab05fa8b7e3338d2ef69a85fa00 0 41dfe76c5ece99b90bc9d4ab80081cb9065a7e9d6b6cd9e49f9a0c804a64dc0feabffa5392a631638e178a175d87b95342c30023f05da8ccbbe407b686447208f2d62fa18b087e201f02a1ea21751767117fc383e8e77f449499e4b7e7645b0d25592977876e1d0da311a6b2a7912ead066f090a8aacfb1449ddcaaca3286502b951e1bdb5fd1035fd825cbf397b558b665a2f5ac91c03898845e70c91e9d202895f7bb57a6cd561752f8f5ebd03fd1ca406be3ee19fe6d0d09755b7ed69ae08fd1866ef43621706bd2003c795702bb5151772b7bd3543cac064d3b65acca10cfd19210f992ae64c6389eed1c3905af1de4eed95e257ee8cdb2eb19d6f76dc06 +generate_ring_signature 6f7c9d02e53d619372700dcfbde7105963e017372fbe2918ff0331191453ff60 11bbdfd15b4d972900e7d088fe7971daa6acc8e8d97e2414e8f44fa0acce27f7 217 a9d2c0e8a6674d829f4d758c0dfdc0adaa073d9ffa6456c2d06cb7ed9c7a7359 ef1c7c48c75f1ba091bff82de93d8ff68f7bc31da2ce87c8569e7443d359c5f4 044e3b84c6acf627a821ab990f7085c93abd290e5930767d6a177982d6ca67e9 781b4c9fb9e32d73d2d1b963ce415c90cb1844416f7dd13280e1146ba1fc4e5e 05d8c1d8841d0e5eff67f665ef58e5aedd799e1b9949443cc414932ef536fd46 7cf07260320c63fdaca80f7b8ff9eb61bb4f9a9d3a27cbf0c93834cf93fc259d cbb0202ac483c7c3b838c1fd4ca2f1bb47e91b0fbe6bd10b1e45da586d6ef64c 25ddec4e59d2ee1da3a0736e7aaba1969c8c4baeb25b45f7414ecc3a39f94e98 0dcc6715cb35ec3f1d7808ff671b2433657e4384ad77c6e24f3fb40ce407ff9b 207324c43b3cb524a6cf244595d44d9a9fb6bc5dee499308b95ae8a226feaae9 32e51b3211ffb05469bfaf5366e9818fad3265923f4fb734acfdebee7c183342 f3745f3cc4453c17488dec37617c06e24c7d05bcfb9449c21e93c310aefa4a44 55cca614e77dcc4ba78cec6c46f38d3d0172ad2da45c4693733b845449b7211a d01bdb20dda9148e2ae0b71cce5ea5914848f79e3072f0b248ec7950fb0cb32d a7b51154c60f197d723af16e4e0f324a901b4b26393a71669d0e5a621b6a4c26 038d389b297f53b1d35e64b92e579422c93528a82caa3742747cf55212a7d9f8 9255e412cd98623b34f764d2a55c443d3675ddc1d67e70af7d3903cfa80ea18b 0dfe3c5dcedd604a467aa13cc1ae316c1f077eabb02803dc06de657126484f3b 5ed0e9819d6e2d0d113f1edd978e543056ef6e4bc431f95f2076d0d2fb475d2b 18ea161052684b291829d5246f410d2a10844b60733a978571e2aac29b8498f2 7e2e83d2284a89f30052c7d3607e88bf658f9fbb1bfedebc419fe3aafcc484ac d7d0b95c8140094761ed4460afb84bac314b952bae09bd0031961209a56791e6 76492fbe42a3e2e00f6b98c207bd06dc8a2b9211bd27154f2938fa0e81d54589 dd2d108646f82c50e2e1a84de94cb2bf50d660d604182dd87ddf620ed3751c7e 43b77c3b8b7b4f57657194ea5c26858d5d60849b5c2fde7b9e2db9b2593959af 68d833ef2995aa4b3ecd512361d4f99c912d20e152976be8471b18e5f82d7a5a 80ea13958354db6fb72d24ca091ccc979e37e8f5e866097a199f726a15ed0df7 568bbc6de62162897808b97c17cdcc6bc1986534dd5f3e48a8c39a0c2a5a345a d052a818e54496d2db412bf4ee41ed0152510bc19a0863a59def191336be7393 e9202d3178b1ba5cd5de88ae45610a543418e844e9b99b443292218dc1abf21c cdb6149924a134413884a183d5d5e4f88d37a7c7a85897f5d7349ffc66571910 64066a9b8f720038d5094cea5c59a4d87f09a121bbded687e2913561b7462d3f fb6d221ac1fcf65a9d188165549d595bff987464ff5e99ad035deb282d42dc93 a4ee1970e64f9e52e882efe800594e98f29e8aecf4ea3b662f95fab5b9e94447 ff21f495bd4634f38c0e1e162f3946cc0a593f7c738833cc83737a3cbbe2b808 5160ac5ea648b08a8219878f0fe2a2dead686c3ffa490bdaf76f5aa70ddc8474 7d432689aabb6ad473dffe72c3fd10f332fc667806187a1d0523272d69671da9 17e4a72c95f54d277c7ba2bad16f634ee82bf403c3b2af475acda08042017fc0 7c8d25f7cb1a3c7c76eb0f1a0afcff5e0acd6bc497c99c2aef04284e58cda7b6 a2f0a4e90c503240cfed6db5ebc3730fbe73dcd04e083c5c74e4e992b4bfcd19 61731b0a82a84272a3484abb794d41f8aa35f7ad7c15eda62119994fa82e1be8 9d0cb6dcb296c7a1d9f315d9f3cd1ee319a32cdb26f6ff29eb60864d1653435b c57d7d5187cf78f06a2b4192f4b2af9e6e3b5323f1923d520d675ad716b67e7b 66865357df4a203d0365078d80e8393f91157836e16592ce129aff41de009be4 6fa3380a808f73acf4636741ddf415cf2968b5c66822a3d9db9231b981319118 4705319d29971da7992ed65e5edf5a5d4ab65312ee5a555f92230dff85a8f6a8 84e4c913f2f98cdf68913c688ab2660ac1f77034c2007fa33bce2832450129b5 a2d9ef7d02cea31f517947a914a9731b731ed66c50eeb27c152ab8f3cdbe7f78 a4ebe351b09a08e8c9f508938034395f032d7992a67671a6feca145caa354cf5 584b6866fa954938d5a134b840a801dd0eac1a17c24e45e13f4566bde3e9a140 5abd93a726c61acdc9505a30eebd91df1453e1d7cff7d2ec334d986b08f71672 a6931ec1d2b21862f1cb935fb0d1b52791d8f916c2afb9937b51fa2317f493c5 8209bdfb0f4967a4855efb9c48b019d21ef2d17d2e768ec86de7bc57f36c916b 301e708d9fc079acf118ce1623a4d2eefd5ae3765883eb7ae06f0df59f0a9225 7da0a633b9c97d588d0c4f011db498f7fe262f15de189c77d0052e522e624f3d 69680b2e40a4ec561e8a753bf932feed7e401ab505e55305226121dc14084cd8 1cc70e12f5b2cc86a4c5fece7524a4bb842a4ea57944518d035f3f2f68b44b47 69a0efbd545b2662c8a6b04aeeb37fa58011570dd1133d95b47d544cafa3c81a 91ebc540692be156388b17ec9936efeaeabfa760bf334286cfce9ee9832a299f ffd00880cf9aff6051b7a16388171b8a2fcbe54862015476c77f7b3fc46d7086 c95389fa96f525e20aa521de82876391681fc1e62c92c80253f609775e0ad584 a72805faa42fac4965162a569cfa86887b8e6df3f9155d6a87d9f3c8c03c8cc9 e4f035aa88e869257fb5938c550db6d3400f4a1ad9338d412d04c2f60ba7c11b 9284397d95cdba29d6ea6df1609a48b96117cdbee19e841be496b79337d63281 012c09af03e3d3d7f48221672c5bf4e05dff3716d744647807627d9d7ed75e52 b9c9d1f834c86d1113d8536412829692e6794731e2cb85934f3add8ca5296295 70f4428a1f36c543107dee9931b378e738af47b4c960e2360521281ed01db82b 2245991898701a04d0702da058f30eac9f2eb869566bf5b0832f41449834994d debb66dadd879e7875cdd1fcc2e0c73a7164e295829ccd0af5ca6a44897e4ddd 3a094f9d7b3d011c97897ca7cb55c1e4aee5d2833ef5cb56a9d7c1aaf043e359 20072e748ddbda7f5a4f6a9f30c4e7a640997e5ecf97f15bf0cdb068c14d823c e5dffd9502a42b8638da63500706cde697dc42cf941636a3775d4ecf5f11563b 2decf150e5e635c47b67ff2c4c2f1c3cb74d15724c050b985a0d37e01e067646 8ab05fc816919f8017dfad54062e9f93d2f8cee3c011cc077e442df75c3ba0f1 5929f00cbc961bc693eb17131b6f89de73cd2137a6112d482346fdce4da3072f cd245415fca9190b3f5fa2b229f8ebca3aab2e084f01d0638afa99edd2c817f4 a71c52bd92541494e4a389f667ca59f34923911e17ef4ba923a04d238f89401d 8ae0b7bba43ec4b225e4829ffa00d0fa6f995f4ff93ce9237c645a7d7708b078 3a55518cedb46f2b1edeecdf56914a8f2de3605df30995fb2c331100dd73063d b249212b901d73152d5d6575a1ef5f27079ee8a6660c6dba3f0d70ab18079d5d 09cece2cec55abe14f6c5d3681e6a3da9e3bd75442369ace34915c8a725ec880 1710aa52ba925feafc4477ca73dec7dc11805e393642e5a444442989be1def0d b993ca971ea66dad353f6f5c338b6a2c8aecef15bd79ba03838a82c845172440 c9d8a3bcf7523dcc38d1a5ab4ca71c999310589e9712f54d8bdc13075d9602ef 12e8d6c4b4ccbab7ad98baecd77ccc8a1666474a1d9717e227750f22d6f46016 04a3246f91e86c0cea76b123bc08903dfdce13e5bc1710c656cca5d859148cf2 92494c362575eb4a19462b1b14067534a465d331ac233bd770adc155a0e9f805 6baf277853495cf5482fe08582d79a957f70e0a878e86bceaa9af967a3a1afdb 2b5fa12f48497ae1fb670b936287f03f1c473281dd42b594dbdcde4079ddfbaa fd9f84887a617768d79b3492844be5b8da294e3ea016c1e51bce26a36e72577d e7da58d7aaa13fea9936eb28114f9b7f0ef4997414b569aa895500c0afab20b0 5e0faad0e8d55ecad29d0ac6316e17bcc9eade3bda7aa3006d03a2e9fdef7e08 50c555404f87b93e52de103c405c9fb1cb3c19586a0b90422061c4dd513cb58b e6e9e2aed640f9c58d0e2645f8ff308af33d8c8e8124c0a61c8ecc9ca28dbda5 959d3c613b4151b28c1fb35569fd3d89d1e6d276af4030b77cfe5ee22ea7c11a 404dc708e03dfe8f28ba1ba88f2e5db8757a3a67edf5c430ef6f889711b1971b 12256a5cc36afdb2cde8d58f6b6c996cb4dbb3eabc9ef530f9b93466d53d99d6 1e423eb530434bf15bae5f8a7c2bdbaf7b1c10501a6609dd2446636d90a332ea ad60a07f8e4093ee17b949b1deb91f62e1ab72595402d45062978df4c3266819 1379f3a747a040ef4e5073b3ad4e33e8c31902c87dd3d61e6c08c94c979f78f0 33efe37673f13b2ad5a982ba809af30d7480efb4892f14364b1275f8cf4fbed9 d4271609be30b70ce95cf10b2c25bfae6eafe50af6dea2d8306a760db35eac85 c7d1569541855b69bf0546034f9b48afa641bbd532d38388e96cf1768b9af4e8 2aad5b98da163fb561c7595a5949383a6b9a0805f8b0e2a8844e045e11cfbc22 1358ce01434faf7c8e9b2dade15bd514c7e92c6dec4855c2d10683f45bc6095e c3e37be5881f20a1ab5ce33605713ace69020f4d9969b735dd84e6aed56c86ed 846c51c4b6eeaf711c7aab321c05262e21d1327d367bd5fe08c0e92be077c490 ece46633e4e417898ed86f20cec69668d6e04f5215f80fd8d9b7fd1f310c337d f104dab4913ff4d456ef784b0ee10a7bd79f6693e37c670bde2fff363f2a090c da677636d4db6c721915564b13e6b53d12ef075590f76dae676e4c53d67410dc 04a4fb6c35c38360ce5fdc268739e2ef6a2beed8ff7bc95460d62b5adf68f8dc 5e7559290137fd3d83706e5e7c1121883c359fedbbb94c8ca4b2680733d8b0c6 479b7e2475c7de034efd81859b61288b803c456684be12537de7aa99b5d127be 402fd78886359830d6839113804b636a85d473ead1920c9932cef4d9cea5c6f5 5cb4b5011651d2c69e636f81ca0d841807209d841a739bf2961d1480c4edfc55 d07f7d8beae6750468330d553fe1978cb404f4a1e2488c753a5d0749ae524636 7295ff8a66d12b4818b5f35d91f2b0ad70ccc7443130792f4e484a782db7f8e5 fee7468ba7194735b76a6416aa03e803afb3bc66077f65a4fc666a8670813a73 b1b2854a6dbc4cd826dfe66b8c34253af6c3860502bb629ebd8d4fe071fcd1a6 7df1fe7319b51ad76d1d6e9115456c2100b8fa74e46c3059ae65b32c756464ed a07ae5f7e8c60a6ee0b6bc0cd2b4cac1e60a964e98b4da967722bd3d03409a54 2c89e51f3e4a9ca6c0d283ebfc97ed96edbf16fb0f327548617e86b89e5f8dfc 8e6b6ae609a6940736bfc9a50a7b299b0274d9ccf03351d2a8f7694e398abb2e 2ea8b51ffa4de90f3cb2bb07ff59893aa13de7c32b7726ce1006dc88317161fc 904a28f7389923ee6374cb5d32e08197e899cfc066c96682cf3b0fbc3b72ca1b 729ed8fb818480801cb35ce3253ee767255cac0031cb70b47ce4388e1c28a3ac aff0ba9017e8179fff3df916b714c215b85d094907124b4ff5899450665b8da8 27f59c289add2c9470af149c956ff3b04f5c6388926b2984c24e5b6756c847c3 fec3cb7c1fd7fa60da89c019ead2d966e06fc052096442d3142226ff0fdb82fa 42d091f65225d2e064d979404ab5754f7ca4bad7c51406376fba94c4fd0b88d0 2bfb9b80fdadd222bb08bb790e6d188fc54419aa279c9b21c0951548674341bf 2916e5d0c9a9138cc0166320366ff1a1f7c1f491a64159f903e7a2025441ce63 405628a15b6d835366899c6daa9030494dd33216415a88e6d9645aed8c89b0e7 3b2656ab204b8472eaefa1dff67a0f1302d9aa9a1ad8f23b5481a685c6a856de c11e154bd9f80cc376fa95f3fc8fa3af606256855b354b639b4df67b8e8640dd 8bd2ebe7318b454747d500f3833246e8a3edda5913577d9871e7501f4c4c65db a720d5a5a7242952dfe68637045142b76dff814195f426dcc20d317213720e33 ecadd044840a168f7e83a8f2b3f67f5d49131f75fe3322cfacaaff9ef68a0e86 a23c3b773dc8374a0b50173d6dd2a5b29ce66b0d1d62dfef1560462e5a41cdfc d0a8fe4d361bff92a2c8d77aee367a097c301b1a0dd518cf136f8dbe5af9fdc8 f604bcb4374ee29b3c8e4041d27a08ef094ebbcb4ed19559f7515401dca0744a fbbddb30feff43c8798c2c6ddfe3e8b19ec2d3ce405e1f0ea1d6c148e9491dff 54b2dbdc5399e72856119bf552be5cb3974ddf1a7de015d7e5da1ee02b0dfaa2 4eca7debb202e342051c049226f8cb4767442f13e712d3a1742857e3188fe879 829dd2aae457f9465995c79a10cc1c03488a95de1b8dc12ee74ca66325a7be88 ad6d9c33f993edb38182239144b58430aced85e701780364ae9faa243fa7a217 e78c8e16cc112e8b526ae3496bc19f9fade6fa6778173a88dd0bc18f7262e2c5 31ea3fb778c29313a09ce9665a52949dd6ef52d9fd514ace880300a6f2dd1f2f 8615a6a3d70967d960dc0bc48e8ea0ebf59d8b39a5cd8a99266288f4e8316284 65f76789b071a4e9354db6f980cd2c35f1eaea62e32f34fa1a7e4b341606ab3e d5f40047e69e7b5f819b276bc2d277a11c9937813d5924e467b8c9bc81d215f9 355b0bf3c48b6f3b738c8562887e0ddf6f7fc04d1456d202e6ba02014a4c90c2 d137ab92a2881eced4293511a819679cbbc89008d21075ee21c6bb5b046215d6 86332fbeb6b2f50aa906a49247b09f207c425f17f0d2e7a8a2deb585bbf0eaed 58bcdce587e6eed7609d388a55b05e4240a61b568e9e5141591ce8629c238fe0 d6097f96caa48e380a7ad94df021698e525aa113791a2b8be91a7974d29de2f0 a9cae6409dab5099d26ec34a41f9d646663cdc941ef0862ecd384d27cf2e9a34 2751d3a661a51328185df4ed66658f02393f90c3350eda059a4c71b9d1ed9f67 a989804de21383e46dd2155ec0dbe2f5c127f7cd97a127ad4b7c76f017493f87 7c337941ed522a8f61149434e903942c595e0bf68a19eee809e500395ecffe04 d531d3a090f7b9feeaf254438852eee405bf412d41c053023716198d98f8d0f5 625cecc397c1b67441730cd1701986484c2b24b5c32ca61321ece2c4283c6a05 9f0fa0d4e8999b7adf27f9b31824a7c309b23d2be2ee83e851df8c2b660360f2 407b0bfe39971b9e0037dd79db93d164d079f8e00dcb8d4085dc8b41f91772a9 5455a1f8e7e7cc1374f610eaa089086fa7446610e74aa8bb4afda37715091f27 cbcb2b6fdca0f6e72f741e8ca88271c52d913d93784d69e70f16d6da7477ad98 db1e3d9df06599d6485e2ff371d4a600b43ccc249bbc6309c3f9a36de1f3af1b 406725971985265d7a2888e91b955ed40f4e3d1cedeacb710f8051c53cbaf49f 8b28e249da7f5c9280c01249572cba2e6eecc970a93bac53bcb4b9c8e6e640bf ae00617c7b499f288834e52a64504210be9fa398d113ef39525d6a85ce757c40 0677a6fd22fc12cf3dcdca106e05ee8fd18759b78598eedb7e176ac44d65e2d4 8e60bf4afee39109eea9edac28875c31f30e6e280d898a00f796d85de041eb6e cc7249762d8dc1bc2cbfe83e5a3a28842a48e6bf29c4e78c9f115cfc27bf8bf7 a6810203173aa88357dfed1f35beee6d73e38da78a7583b329810a06c46dac5d 431f2e1fe54a13aa3aad164e339cf6463b8190db5f5632d4c096b08e100246f0 e03c6d93874e0ec2c8ee0d238382040d455a55dc0923fd0b2afc1bd1f7d399a6 73b62b31b6ebcc9937dbbe4ac6907609a68d6eb4feb51f7e70afcc912d22623f afde6010128e5d4fd46a0c2afc6d12b4216b51e092dc050097ad9cee3b6148c2 cf660b8abca78a389af858c41ca235fa127cb86098964a5dda309ace3ff34c32 f74fbd3f2d3da14032200763a61edfb019f6a34492184702cb800ea889bf37d6 e74dfa1a4004ddfac92d41d388572a5f255982d40e207189e2c1892dc5af1130 6bf7dc128af4e7c039f52093b80cabbf0342f923cb372712fb012edc469607e8 ea3f3eed317815434b64a8c02647bb49933a341363351fb463198d6bfdfe1ab0 bf607ade73d9fbdf67d6f66f4757bd85f8084a1de1a5411217720e2875b94722 91d0180661702425c83970e04fdf5bb86511516c400f6618c9f66e60fa79b70f a4175d3185abd7a03ad7d139907322418577644a7394c77cda9092e937a1b401 31f2b49a2f3df0b3966ea20984843e4d40df5d3a115cc71923142d2cc9a5a339 12cbd557508932dad07402d9fe599cdf290d8e13404a7f0bbc30cb0e8f6fb051 e87e1757f7257a30b7fa51fda581127a5ae9df6f3a63c79ea0592b63dd431d51 624357831afe4f7f4acac70c457280b1e5e3d3ceb7d6642a7c5062f71bb73df5 beb1b43f58b59c7926aba3b5a873c614d008ae6220a12623680f2e7d571f2931 61ee7bc796acbfa157a882721938f4c6a38ea7c5780bca69f09d11bdbf4c6bcb 6be6cce2d2daa1c1dc937f44c7b290880f72e849a178f0fde7c451bbb16cc960 c6701e6389ea37f45b9faa73b44dc412c43e15f63827f73253251048d0d1aaf1 3bd90e4ae4ec59c20955a8786436fe323545d7d76dd86e977fae235710c2770d 86e7e8fae2623b5072bee6585705ad8c6a35467053011a29a2902bddf28f2e97 f975164d0117adc42dba23154292e0d9907eb1300524f9f146430763f27fe1a4 b1f1177dcdb89c3330fe6137eecd4e3f9f613456e32db51fa3f334882640166f 507565d88391e24f45e3219a723a2201a02c40c5cd88b3e16e7ab8d36d3f0442 682acb51bb734a6c5a8184f716a0b2bc890dd14d80a268d9ca697cbad6d2aef5 d6b05b529283e658771e12cb8db03e805a6f377515d2ee11ce71bee3f22b3f58 a3b057a1933ed0381d0cd89166e7b2cc8c3613f9cdd92cd109d86b4ffb842490 bd337f0b6ac1634f12c067493bcc741b21581dbcd5eecfd1386b4b50803a5beb d46971f3d8b4f9fbb71a71cc887646ffdf1ac95e40c8374881aed95f4e60d6e6 8a3249e79c08af225720d75c7736a07fa6cf863eea4eaaad647788c43b8f4ba6 f25ff9ae361b090d43b63274a411a1b5d4536307bf4c2aa857c3d515ef26335c c306224eb6323a16ab68eac94a38649236d1124f55b7bdec67c8961e411f1fc5 fbdf0163bdbb52808c79b0670c091b39c906583b379eab71153db54af0fa64db 01834dbe726bb20cfd6e8304bd14ca1f2ad2a92c6e0676640ba2306661d886d8 163b7b5864dea3f7fa0a7205004588c2f58326f0a93ec6f4ed42db249b46552c d4c93ebeb66d6eafebd24ff97dd405b61dabb318122177de4b20916eed1ddf99 68800a101d30377b7cc7ec21e5e5ba8f31098a1426f09c5713c59838faa86a1e 697c8ff36a824ab70fdedf3b4890e0e4d767f4894c7a4fe02753715e4e5504b6 169089c3de0a304c16958b81bc597b22424e08e4b44effcbfdc53cfb7ca32592 f7f4aac8edd8081a5d88e1bf2a1d8af7fc495f279183c1cc8ae9c2a2559acd6e 102abb0de31c22bd64ca47ae288a2ec0945640c9d8736361c8e7e5c70193bd6a 44ad04132ef42640626b75cdb2e4aef4bd6f8cbf52b5097db6ed3d89cf980c5c d97cb6a5a0a76ded4893fe31663fb9e463d6734281adbff52fb386a34c14f60e 109 530bfd8a3a9d36fe1eb093d688bcc59d146c1d9c5de5eb6aeed0b43a5175fb033930f539b022addf12951d9819afcafd36c8a89fcdbf9c832119796f5b05230fbc63f975d8808dc3b6d3a9f69a876c5e4721dc88475262499f24588c9f1c600fb0cc5a0bd1c7a9b831f31a4d44a5ebeaac29e94bfa6099057d5ee05b7a54b40941a55703d40e45707f616c09ccf95a2785278d335f08b03df960ff97369d6800df3c1e27ee35295a2fa662b05e844d21f4dc319ca545d61be3732c01daf17b0503ddcb047282427c699c1fa5cb72b0d4c156dc2d5d31952e29b99de823516903714309ac840cc4a194abab1d4d370c0daaa26262a0c467398bf8c492f3fbba0a1e00adfa80b22310b65efcd6a8ca1f6070a12a74e9b3d1bb6cdc2e1e0cde5a0cfaba84a315ae1ad1aebc725205f10d925278abf3aaf053e88d95a924983cc10a20224df24ba4209ef7a2513eedd9a065e9ffebe3cae6d6c09fcf73c448c86a080b2936b8910e02b2c0ac9a0e19dcd35d8a2a8b72b1d0306f66aed67875f0b30e64bf180e8c9996622a50f41281a39b401b8c40cb00bc5ef2c8a13068a93da409b43f5f79a7d933efe6664837e1b7d92559b3b50847f71d87a127687b83f91b0619e3d2ad152cb0059277f9d221bbcc1e46d36757523b5b8256d7cf0c3f63ee0353b4f35e9c8b1b1ad97063370ff034e56623ff50ddafacd0d0a83140b88414087130eb92d138864af151615850ac692de53a0ccfa76d8b52bc5613a67d068e0d3c2a307ea6bdc7d3639b99971f94a0c7d7844ba75b796f1bb53f919d9dfb580f238817cdc2b4d5d6dde99114cced3fb5c780358d4463642ff0c656cc2fcf03025b95d9f07211d4c7618d7578b9626cf2d432bfa7e8a523a933ca0b5098e3dd00ba425c2d7ca098a63bbb29029a91a05c23d3e41dd136e586836c7e0f5c7b6008ae9d9843bd62ccbcdbe9ec51577b83de3355b8409f9df755c3d158dcb76d2f038a0e96db5c220cb20cba1064db7496301a0e876e563a385762b02afcff8e0f014268acad0c91b5df656be0af1054492995fdcb9d5030d4f3cec4b05e9cd3590d3b57aa520ed47149d5a39fdd0ae41168ff0db03eb46d4996fb41769691b24802fbcd8d03a02a3600ec20f151dc53acb43ce49cf35096d44340d18471216d4a0f339cb39677d5608f1788ba30190c000fda661d0df28b76966c1acd077109520cb236a7aafde0343af9693f4645c1b9b5b22f8dbb045af0c08a0e3661f8a3c1038cef8a1218be58327021838ddcfc032b6fbeaedf8476575acfeff95aed5d5f011154814b4ab400f7137eeddbb45f311b6e4dda472f609bba3633e69f99186305eeb293c0b19afd542f67efdd09e35efd3953bbc1999fc0444e94da0e232ac20572fe2abd5d3742135e85a7323f0d15540e890b26b1a9e3a426fc2aefeace4009ea9678e36c05c9ce9cdee9a1b31c39d6cb080f41e11b78d71f0e6365cec8c609b188a19dc5b6e3be592b0887d371da701886e5aa688438d98f0e38dc24f9ba052d1e422cc8093a23500de0945531edbf2026205a93d3c5a1be946dab7669710a8f183ec5df11d474411e952c138a26b0306ceebc71924efc8a1a1987c9af7e096db3d82e56fb4df40b862e455cd5276c7448bbe49f7d8f4c8a6df97168afa40b20e30e1ad005451fb88f7abcc5c80a115ec131376c868ad72302eb98641ea203610d3ca88d67e238833084249a04a5977285fa039ad1b2bc555aab1ac3ba2d077881438fb75f4322c2331bded7a94ced0620b0ecd0bc9333ed34a958555949017cac51cbc12842f17479432a460076cba44f79e7a2ac8214cb42c03ef4fda80f188c02823ad6e164e70340cf13bff49b17d81f8b324aa41835ea00add450f30e366f6906d09a32154cb4b4108c0adc78b29d0297636202a8093f4617a5be6b091d9c71004ff9a9d80ef062da4d2fc24dd3116b9d28a9b1493d92368f0cf5d60bf8237516b36d6cd93fd6f74cf93c1a8bfa5f07663bb494a53629e6958ffe1c0f692894052a574c6dd22ec996883c7aa4f6ba92f0fd16f970562d36994e3479014c3280402591a4778338e11b262d8092a03a95b834708a47d313297884993e0db4701d2b8d52c3b6801889bb3eb337683ed94c6d52430aa40359a743c7cb030dc26782a8f32e6c527b3a12ce6a3a3d95aec0d022e2d65408c45f022f1a16820c25cfb0aeaa122e45f7234360f8641ce35e3a9e556120cb8164f29edf8b249b0904e2342371e7acc03cb54891e23abb8ecf31934027720fd96879ec2f01fb3c0ef919b00a345ee590131c9c1c53a30afbcd37810679508af527342ade0821fd047130c26f8b4796f71794f829d007b33d821d6265a3c52256d89f838c160e900b534c8492855b9a3c396b732f6cebbeceea7bbd45d13f45e6583477a3ecd5f30fb5c537debb5e65849b51729c63c8b46308fbd2b0f9eb23968bc1e01408137e08c26717574be178e7b88491248b4bab741ac8648aeda84c788b6c7514cb74870ce6c73d249eadd3864c674d5ad07061757b71b8455386667ddf99f9cfd2012904a5ff2cf8e33895f81107b921a403bad6829eecead7759dd0848319cdf24d3c0f566f170146390e66944c7c30090f89772f26eccccffdf5a55329f4f0f6b99708dbc23cca128087e4614148dc6cb4d140881a447ab05b0a81eb990d478766be033e0e079f7e576c94938ac9a68dae164bfe02f2a9770437cfba8e577d0766a1087029e717883a2b8d086058c7982be9ac8a6b4285b9e129527d82a3e2cc2d510f03b5df875f98d64912902a2391f2130ccf51b38049dbf9c09dcb129e177c1409c535c25792b5a06d9c04bd3614a24678af538e62733eb8c84b96da4334cebe0b007e8920c587c90e23c016aeab216f4f2686a48420dd27535f6604f479062809c6bdf4c89ce740c5e4edb084c58606749fd8ae668c899b2baadcbfa04e872f0be5cb4fede713f963bfe26bb9306cb6eafd66cda1d59a9c01b03908e67fd6e6081e7e63b6c8c5365cd556412ceff9a960e0add9ff593d5c93ff7de119009d4d0be9f17982ae291f4a484bd008988845f684f2396e081026fc0e2e389864586605a220bd787a6d0af480f87ea13f9da4f80edc734556e98a18a0f5a00c0fee3f0daa4d10c2fc0086092f430f0685dc74fdf9a72eb9e7cbb9af2c00469d25d9c90aecd0531dca4da73c37ee32e7a29d8eec597971002fd9f1b848725f7df62c910edcb2ce33c0ce5fe29a870a8a3bc6cdb8cfecf69e6d2e6fdcb78995dc7b400a075d0cab2ddc617a2b5fb1fb4740602afa055bbde4e255cc6dd8c93264a185400c44392912856cb50c001e778577aae3cd5cc45ed4ba415d81b0ddb620de598f02511e40461b530d2d4528143d29c6539849104e1030b161f274d28f398bb9bf06f7e485f08dcbb24079d2891af11a4cee246cc00e39be0ecff091db9accc50406459d589a094d071a48777e0e67976f936f17d9d2c852af130fda59389c5556082efe0e1f82379993ba1b78ad9d74f3b5e3957864364ac1abfe375d53949f5e0d154ac58f75d82542c9a353506bbfb43222acd118919a50afed33e4479f0e3d0cb56aac4e16e3dfd1796ef25934311fed6c63a03aea63a15bdb90929819bf790e6a8392abdac98bbaf7190b5c23e0f9e6a1b17278f63c25bb3b4883eba7a72901337e45204e438fffa2f9432aa56358aacb1752b7762f107170f63e125743db0e71e347a6a372d42088437a82a3c8c822299cf53a2d232cb022abace3d9d10a0279cf36cb7f22992ad1c932332c4784b34b6dc6280fcc5d5450fb1ef83f06ba03b575cabca822f0f2619e6df17754abfb17bef65863ab7b9767559e030e7f2b09a495e432f207e86e35bf5511d275c24fcfa39e5c33a3bef45fa4850a5f754d0b05f8da75998716f11f2ab3e239d9b92414e68aa2514f4ce2c5432cbfa6b7ae0c88be1edcc887b83eb25a24fdb45444d7c2d80178657bc2965860314681bb6f0a47973946b7971f7c0fa30414ecb1ee0b831797029daf7ae7d2a9996f1c24150f01fe5c11c52156a489f24979cb6a9d81a602ab8d74f41049b2f910a2d7d7110472b0ecb0fff0977172881c3863a317430cf4b6f0587397ec0b551d485f448307fff4d0dd5a64b68a51246df2185d5e55a192c9beddf15f6e4c52c8af6cafc1082cf0822be81c3e6106f20347bbf89eef97977e3ff36b373ed5a5c240b0074a054739634ef47351f23b7f9b88e532de50daf2688afe8f3486d3f0436c12e6540ded35d9e359b031ab6fa5894587b310caa37c388f292898b59f5bdb188b2149042c102623e44458c0ee65da3eeecb8cc414fd2deba119a3d63d98cff3c5e7450e908805c2feecb5d4a38b30d064d634a826f30118c758d128f5ddb456412190013a113289a6f8288e8ffc52a57d76ee2773572f990fae8885f46236a501654c0c681ba1a96ebb0263413ccc676371bce12bea4aa571f75007e0c1bf2fbd5d070ff7365e06c22765b7180b4516c5943447ef4e995b56c47ec7cf2b8b6e4309480b10d6ee56da9e33b666f9aa1bcc65e77446778e36b90d73fac0ed234b99b7cb047e0823ef0810bc0df0d112fab6cb8adead50546c9ee51524303c5596c278ce09ca7bac9adb097a5107e7d12967b9282837c0b3a2fe23965995ed99e0afd03a020b8e4a2683799e9753bb75cd159e49cdd6a929c0392a993f862e9443fad8370ae48176d2520545458b1f97894cc12013e935c8d4c6b3753e722f89d27871c801fca3b2b28b74834ef660436aac8db385ddd527d56a0cd1281238ff12063c410f36d0e69d6c833e0c5506c3c6b74b7cc89ea809652ce34f8f0cc7f8716c1a650381d495392f65ceb0088a21db78c17b9a7071a4ab44f524a03f2a760b3c10a60c3cbeeb5917879f9e16576bb728c9ed1f81cadab42b7445a1c3717e814c413502f249cbfc3cce057f2b81ff8b8f2eb881b485e0b85117670150a6f27ae08140030b744d3360273cdd55a3b5b6e61f3a2558921f677c641226eccb0987311d4700fc18c5e054cdd2353278441734289f43eced9da67adda821906ab15e6d2a7a0331ae751bc9a24c0a7fcf50fd4a3b0869bf90f32ea74039028df67ca5f1a4af06c8e3b90654cc103164699e2557a0e70b08484d3710ec5eb464e09afb7acbdf06a2384ca8a5f7d20f8774f76f8953c9efa1499078cb5522dcbd388785c3dc6601e703316a8feb8248fcb4168ba07fbb84cc5f8c7a53fc216aa5fb8ff5326ec60ba8b52ec669604eecc21bb1d9196dcae9fa11be70ea815c810039c8dc7768750db9968b55a1cf80374cd1a040d3d905fe37795ff48540aa5cd692af0e5685cf042165352d19e2a18da963e2651176dd89338890a86e03142685a6e98c44a0a208e6b8ee605a78bb905de42ccb197b4e35a5aefec5971b7f30d31f782307d2820dfb1f8523fe42af6c77eb4c03d1d5750d808dfbe69eb66b2b3bde178f57200c04b4028fa57fb748566f32f86add2c36dc4fbf21a7466cd51c1e925d73f312d20d9054be0672bb3884618739ff3a1edae980b54984f3dcc5c242bb34b3a5db6c0bfeec3fec1eb158cbe99a5b1b20f3b074f209184bc6c1a9c37f510631132ba90410b7289be357be0d939988323fe8048efe4b5496f918acd999b993e9567b57005e6456035e81097aaf85ac6f79ca25de0eb12cc36a30153b53a085454386610c595638d714ea3b53e767055cb2baa80b2854307b68df1580d045d25ff54cc00cd21d8854289ea579e29ac0da7c0117958964e158ad936ae5489dcc44be9533074ed60b2b14d20e37a8d31c7006344dfe6025d2f4300315135d3c921a1230a9044f8e3d52a2db7ecd35541d49c94a1de24f669813dfe40fea5b54526c317c4701949ec3b4a38396bfa5f85c42040d1f5bb9c2bcb87db3072df7e2ed50111fc10b539eba3da5855afea320f3aeec539445a962570d9e234a7cf155bc207f97f60ff50f5fddbb337d8c24a3b8b9cced609eacafeb6b4ae7c981094437ed5c61e70b1b2f9186074046f43f58aeed909ff45d26ef4d5d8f8624ba8978ac93360f650d5cfb71737230c505816f1d1a819e7a7896a3fc0cf3c768ef6b3a1840dffd8d064e684c6e660369139da4ffcc213fbfdb0c400f80efc6a3d71a6da7d02c20200c624aa3e3a08dfc5bafdaff23c062ea5529b3c9d759224fd28bfc124bf7fe1b0a3b1db8a825b89888b305199a30ef93ada4d7328877d3214e2cf731a13f854200cad72002d8a072cacacb7c8c45d78f63d7781beef1f08f7d1a60962ee432ad02c8dd50bb503a47d1c7bcfb9c94fa17547add3fa2df94dd70b5e12b155443490c152e835ac2c957a667837dbd33229df6f66d94ea5737e538136ca0e34e8e130552eae92e412ca3a5a856140fdd874dc4a4d9f7ef2dc4654e6c5f4547001b5c0d2563ce91fafdfccb437ed12f537db1632c3c86e234e91baa7f90904ba3fb4b085484e5a1a5eebab7fe9c5ffebc40638130b616c1c0e871f738111a67c932250159a2df1eafcebde2368b6d7291b768c20a68f940daa05fcc367fb2a615f3bc09e016b624fb7e0efbe22821a599e850993b9bd5853cb3e8edcb72e4830dad1b086f509f733e9084ac1fd5a6504c4d6ccafd999423496e80859ba60f982bbf160d9af989c77712b05c7f140163bca32ee53f45cdc7e154f9e43d5bb42125f557035a5dd8a275f82824428f7cd221d5498c4eaa93d37ead3dccdf37fc0951b7a80b70dc09c027028983697b027804207ab17ae0d1e4e3f36bee0a114b0d3fd7f50be68928686d330670987b84b71a12c3245d2e1976309b5e669a9b05fb5601720f38ab2c3814697d6bd0b9aae8d91602cbd952274ce4fd09c96f6e7ce4496c6001a3a4e04163dd315434bace9ef858a959fc709e12256c62068a866eaeddbf8204da3e33586c417250b7bbdcec1a4e55f048af1262ff2cac949a8c2e060a55f60d137611ddadeb5812a3c965e39550d0e2ba2ba93b11c1127d99946bfb80b17c0e604987b7ee0533d46090cb0264fef70845ef779d667b7dbc4ea6b32340730d0c4b71db29fb59eff5b24e1d157fdd12b65e61e4874fcdf4a5246940c67be92a0c2ab539574397ba927cb3765db0725c77fcfa104ebc28f5cc7df9590017f50c0f048f860808c80c94df8580b5aac144831800c8756452c56bcab123ca6b7f2c06fb69b18235d8aac8dc6ae5633bdb798125e4563374ffe1101f3091e171c05b0696e527af64a6f26f5772c5e761662fd1be77b5a634cc90aac53560348d1ab406375a6c25a0637011115b19fbc97ff87915371a465a4e7b5c5cfc4ab93351d30d03a7f7eaf533d1a565b0466c6677447ddadf1917c7fd74d820680fc45ec44309b2eaa4afc831c86f5e0b6739f3ec3611406493bbd856bdee63bafbccd3d222079bdf9224f907b2932091c14b4966dca07037e2b940bad1f771349a8688019303e279500b5341d9bcde8b026ac5bf20adb4d863641b115f91cc05de3ff5b88c0137bd7fd2efb3bc9606480e18293b368199d97929b6319954169b4d1b4d6bb3067c17f1ebf944b3ffe9cbed76cb5e62c4024fd9edb4789dc5242a85024f10400bd5e08d49c0da204e8fa386f0684c76fa71a0e04e0e4c85d243c35bb862e92502430d93b77a7fa933d244a3d5e1454f5156eb33d0afee52d5cb6ecc0a789e8a0a1206cf0af1a2257460156ce57d259ff26d97de532a85cfae7a32d9ecf6146a0bd90b978e139942308728387b664956d3c0772cbfb0c21166227af1ed91d7be087c2d1db2d674c9b6c31228ce3bcdb7749eef5be76a58493f55e4e56f6fa86209fa93497763dd4d43bd51c9e297c1deb3c45bcd62816c07319ce6a570e741d805cf4330989568c73cb019078b783ed9cd28f9ff8eec3fa2fa593cc75367f0020b904cba6412c12559102dc94ee4aac8a6a213c7f6413f9999feb72beae3dcf40b3dc3e3b6629e25510225ce4d4be09b915a5061ea2914dc90156b99f7b66e76049c0abfdc7c1da5ad18b1b7b4a5342a0070861f9d5794cfedb180445b926404017d8538feb0d26d31f2e68642a05a9842a76676f24813c79de2e9aaaa7f77db01ea67345bc597f1eac0f31af9af264bb9a3de2776f40fb96c05ed451b86a41f0d4f93c16e63cb57ff22ecc58b68481bee10ec2941f07a46973d9953b1686b0400b99d8fc707d2bc99c664860edff5c4375a0a6ee51219d96d1aa5b55142992f0b8f50d63dd0c7e18009b0e00e4cc5ff0a7e56727f8881d67a26372b85a92cd808e986bb9f728d8a50c057eb28b76883e2a45d802e98f65881326b5f1f12a0ad0a2cea588a2e1fbf931f4511922d1bcc49bdcc334886a8cd2e4d42b30be533400df7ea0a629abe35b25d818f06e191de7576aa67604f087b3b593bc61ae30ab5023fd1d299aab64ac0005ba51e9adc25a0ccdfd61a9774aee4387ca5e08ccd940647db087089d6de9c507a5c370a9eca57014a955152166210061e6bef2fb5400a0d945ba0479d964e34a8321569d4ebbf86b5860f199a3c071a352097a3cc0003fe90986a13e3741408b5d2cc1d1e2dd4b3de0e6d943f7eea895af9731587b40df2d61cc1fea009fb5b4d71444a0062e54dd1a034820042a5a0c92329e4dd680508922657fcf444ab8cffa20ad32a2d9f9346c15e9113f51d93123eecf47f0802094660d26a37b1e572308238bcc0cd9d8fc6b76e85002912f36daf80ba94df0c41f1f63bacada9e91b96129f3bcc32ceb7fe39f8e3b35f038fbff14343617a05fdfcbdf0fd7c95321c2e30656d0dcadeaa0f123191959d4d3a940b75cb5e690c1da48b38f2663b210ab030841afae5faf3a051e7a384733805fba15aa474940e95f01b74b4e507fa357ea52cd17dd3909ad06738a5ed827ebda05bbb779b5d01a237b61232b70b62a386ee666a37e516da038d66796c5d1deb9925e7d38888076f7520ee2bfce81e1cff19db41e2e4b433a568ca2d020e63e9ec32da36b03b0670768237eb9f9f2a1e08823922726dba9e360876cbcf8d45392b3a069f3dfc061cae79024b95f0f0129f00ac7929a7d2af75c8934790c5cbcaf478ab9a1b280da048fd10f9b3bab48289c97c0b4338c0509e8f33f401519c19b2d6a91bb1a50c219d5d8696684568efd5d7832b7067280ce6de10de865cea3b9fa64fdcb5060a4d9eba424bd850bf3c3e3bdf86711b6717443fdb41a75a7be98b521ce4f3110e2f5e1923feafbb7c2f543b27465efe799991557b91aa02521e17903b3d9e890256d96357d42a8262e0753f78358d4e1d8f9ec870b721753c24c360ab7b96010435d4fe18f9033b4e01b90f2b474e0236e4d7e0f8fdeea3ec2ddf42c634b4f30eda2b4b57664a1feabeb6c5b830cd528d2faf4ffe6fbb5edc2df3083652f5300f00ce253bb745a9fa3e68f74c5c51bf76fed485f91e7ff87b189d5132853f7b0eb3731bedc94b8d44d5095a38cb5112615093af4a6c5c5a4055a1bea6c57dc40197fe3bd02cacc1fac9cc171b3d3c93d007c589d32c8ce39a6395bee54ab4c70c49ed8d98549c8ce7cd777195cb37734cb7c5e4906b93ee7dc030ca89cee72801b28ee0476a687aeb29892612ec89d4a49ad9113ae7d90e7f5104d1bbcb8db40cac1b7696e00f0ce928abf27843c3f510297d6e61771b54ff05df506a0b51250bc9f3452e6e306a124f847c351906d8c412cea8dfcf6dcf5842cc3055546128035cc7ec66a96eb6628c114b76772ce95720f8be86e70db1ad9043316189ea3a0427f34696bfd245a14fc0de21c86b45ade67b638f262e9db2f1a2c37e56e9e70ea56ef5ae5c9108410482782b110e83bac519dd0e634ce5f0fadc9c10b240d50f8f6a3142ea3789cb6761b140c15f28e64d674078854f5d38ed73d82100e2520da1dd4718a69db643e74434b2a95173adaa8b368a2c5be1eb9b8f9e30c55f5d00035c36f18ee46d4ac09e9c5eff16c4ada6ddcad77b4c8569ca691ff68555200a2b4dd099ceecee0b2b201f289009824e05ac1e4aea0ddb5326326300934c10039dc637d91ab8cf5a54e5913fa620681a3002434126622bf19e6a97b9e8a7b90f9e3f006b897d570cf860a0b5bd967e04e8e8495c9dbfbaa2a5ad3a02115a1f0459149d0f19bb5bf9a79923e6a5be882f96b4fd0bc7f82c560fdc003735cc5807a1625f508e67e150e7c941205d0028c7ebb1f2c092df8e4a68d68d3dba310e06e68c82cc25f595a4881994c1f80f38edfaa8c8375b2acbdf9c99808dab3cb30c000195641983bbf143df4d0fbdcaa368370be391a4dfb67608d9f708525a8d047607bfc17a6909a140fd052a2172ec5b4a09bf4753579af625c53ff427fc48000fac71c19397ac6f7b8d3b179bdd5b38930d6ed6b6041b6de57619aac418790162cb7b2b600d218fa80fb69c47f1cca0b24fe667a5fdb18549e342c9626c5209a33dc4bd4cf490d5cee8150294a62e6b47644fa1cf038e7d8bf410bed465b002628ac65dae09897921645d3babafc0b14e33cb1658c8b1d494eafe549b934d0f41d9d79effdd520a743978d95c1f45bf00b7937be5a5e11d8c150ecec6a5b2006cdb59a6f5d31fa6a9044b3481914678a4185ff2c8edeae59cc5f794ec14d200e0b02a5e054dd69d2e084ec1e3f19bd18045a3e7d23364dd701457684a1f5d0983aea621ce9b1d0d4c2bfd6f4a8aec14414a88e72b2b4e2e60586d15b31a8709ded344b9c349e4d81d78f8681899073a4e4b7af45a6627dadce0318119a5510ad5a543c2d40a68d425ac62eae33a1236fe2fa4db40100697c86e378afcb82706e4b0ccc115c947fff5b6a9d4509ab9d9100f06576e7b11e912be81dd6f3cf2096d2fb9a2a8f99b1471fdcf57e0b1b4579663504ce8f5defd276042bafcfff40e5085a85b84e62e90742369840db4b840b002ab0aaf9e3dfd66bfa2840292d70260a5ab3a2dd78cec36eae2a3fc75cfc7409a7f25b920c47e3636e51a2948430931737e2b54317ff7e7a39330b3de5d9ecd168a853604e4fad95b906cd20e4e066be7ea8dcbb55a7460234e2d25287bfc63a9e8d2b483d6c9f5b384fb1be43303b4e0f05965f251b27075d0092abf046a41f9293a546d055917046b6294dd8a0cfdea4e4849f947601b71cebd532d1122bf1168352aa3b47b804f4df5dcded80a9e4a7c5ec51ac379e5e6e44506a3b8d9a8ccd5edf4dfc29b8d45510287e1dd043bac541747509b337340c861b668a96b0caef40f839af9c3a2ec7d1a0b003d08e5a862203299a6b33c7e90245d6a97d826fc3ed8aa956f716102494f7da57c0c80e6e6444c7bfe81845b3d6585449ac12feb52be0540db7ed561969beeb86100899600da327d85edc873df996aabf3850d10837f2cd2cb1f52306d36828e4903ed07edb1335be9e2ca601c8a769df8c14544d570ef7b82c43e29c2c756b15907f748696e286230c1740a84b7b3109d71fa0c9a13beb7ee9d7a5cc7a22bb48a0af50e034e682e77eee558e3c4e0fc7d1997beaa8bb37e273e05d93137417ee407cc7d0f4e1eddff640966d0899cc9eb4a15cfaa5cf7ec4053b91a148fd9e2010185e55f18ccf8c6264735d7789995f424543e9cd6cf19a90a40e2e8b3b5d6970f60898d8ca9ee619e1ef72aa59801218e88706dd2f559128931868935f36bdf0f531bcc33d1415cd6b371987378bf6de11f38f21b517002990bd5c7a216ba660b281fe162661405551e7f22c522c03e4a84715f030189d04060b9562d7e02640bd7d46ccc62a1441086994d03de0f439908366f42063e9bcdc3923587853e010a8f4037807311f557e91492309dc1fd978029c129a93e6ab730ffefd4a7e36b09b6cc6e6cd55f5f66c103d73df7c0bd5529f5ced6db1b80ffa1e7e4a79809f405f0b941c1426aa3aa0b986eb9b2fe233d069374b6129bf43164a578f8bc97180abee95966f374a152519229421b10c4398fd75f81b7586e061028e453ce97e5048a6c30ff82cbb1bc5a3842d355b905ce071093ec72903008bf21bace5173740d0a91a24717dc2da92ba1566197170bf5ca68bcc983abf14c9f724ec11dd38d01e901fcc15e7a483eab8390166af3777b404a37702b30499b29b5b8face9d5505fa43654b5768e86c762f34dde105419eef3d278ac44b1ce94b8cfcccc9b870057a6cf3ff9bc832ac073eab16485d18339fd61c9e335848d7a67e00885538b70da4755c62c32bab34d733a42a378eae4065bc7468af477cadbc0a436883e3440a50ac5b87ca7d006ca26dc9d4f9f18fb69a4e9138746a619f7021f2a84182170874b35e32be8ffe2ce6ad40dbef331872c1e37cd8d5aafdbf52cc9ab03b4e9e08f7e01288c6fba50a7d796d421743e2f0f0aa69283995e497cd921e7ec4d03f0cd72315c5c6fab09ca88909d87fdfbcdcad94386fe69fd7bc597283961239c50f9bbf205898b551a48538f2c404573a41a472349ee0e0ccd6eba51b50834480001070c066202a9d067672b717e48c12b56084ec5f5a2604f1147ad7aecc08d3091d6c665fdcf6e6d753f8eda978b3a6ab1b0873946b221db0aa32eee159dccd019422f7dc42d7d8bda3536ceff5f5d309fe0e52072d175a409d2ceb5b01088c0ed8e0b6a5e1ae8108f7255dec01e61e9983cd8293bb90afeed229e3ecd5d412022535644b031ed2e8a600988b1eddc0aaff553c1a37665e34d48b1ae5d8855e067e54e07c65ac11abd632e0fb85ce84ab72582fa1706387d97e5c90b8402221000ccf28ca27d89062093cf40613e170aeb382d6fbc4e5f3c5766cadd962d40b0de10bb3e1f86f971f71d7221c2e327025f797ac2b172b08b45ab5979ae3e82408275ff1e57060049cb23434b8591505e4ff4f33b5ec7c52cac57188eb69511d0ce5bafe933ebe096290a54b2e6ff47b6793897f38bf3924043c20d1cbf0300e010a73bc31a7f986f6c24002e8f65c2a89bd124f799fea9eb2a5c960f14801800ea0d204a6734af867a177bc0e738a4763dab837f947a1b2607fc1aca9649d290fc4e9eb7e6250fbc914e68485cdfc5178cf307b2e7e7a1b92a7b99911bcf10d03ea77ba0ea2a89feefc228bfaf22e8beea2758c86bbd70c905f9108fe28c22006a86e06783f40bff0cf690c1d7f0dd04448c6eaee1046f80dbb1fe180e65971011cf4d8a00c1edd02b79420a85215896723d67f4040c9f64a90482cb2e727e20b20e741ba840f844881f0370fd093d978ee6b36106722d1e4bf3ce6b6ce804a005a79bb43bc9281d0c2905387fbab5759128c6c0729679b57daccba60655bcb06d706e0f3dc843ffed0493ba5808c9fd2ba910e8bbd10cacc89f98d6ea181be03f0a3285fc10160ed4c973b7fc8838252b89499e2053c748f6fcbb19bc8f8490e0c794a9ceea7f1234f7a1df4a04158099c2bd10366b75753a457f28bbdbf0b003ee45243bd69538c7808ae0fc2e6bc67ca08408e476beff3f31f96bfb12df504c5452fe546ea8c4fe2735e945da1a5ab9569cb0b458034155c70ad9721dc6a0a79b2806d32bed1dd14716b4420052bc4a31943e5781479ffa95d04d4569f380a0667b21486b9fe028ef0e38a3ccc336c148c6a8eb5abfcb0cf891cc202f98f0ac7bb2faf0ecb8c3fa04bdf3cf97a4840707816d55f176612969b4ae9ddadc9033cf2c771ccbb27caf62871ad28c362772702f0801e62a29c286480b15b0c0c05bfc9222afdc84b3a6b376643ccefd0cb20c0d3dceb4c71828f1d02eb1d52a20490ef35e86c034002a6c15ade69bd290697dff156c2d32757ef578ede89619b030622ee254a99c7e6b4c814db98ec2b840f9f855073728a46461cd20b5ebbcd0ba39a7e2f663702a896a2a8a9bbde904e3aa0109e771b589c233ca3298e2f780b5b7ae2690d9c83ef2bef308bfcc994b675e22f55ccb02d577e775af863c3d80c3aecb2f71a2d6d4150c6b2cc6230e735f8895d3758e8279f12b133e2f784a0027e884d42b6f29fd99a2e7a650a80c458c3492cfebf6882dc73c4241d2d3f270f6f86ad5580198c8747ba0350009d505a69f4219d0005175ad000cc8883f76a0c80563ee30dab3a1fba92df4ed28e23a43641b62224c741e4c854344a5608fd029eeff1ad9be6a3ead5536770b88c8d8e7d5b04773d24a249a3f3f086110aac00ad9ce3a2a45630d01c9563256de8941c17a980b8d8ee306d13f5ec2d4505ab0acfd5463d61ef55ddead0ac93e5127513115c5fabb393f292fc5af4711a6b2908c58dcbc1743285aca1b3213e368d7eb5270118a58e7a41cc3ffbb3a7266970060e1127ba0446330b28f5113760753c74783edaf4a7291ccded3627faf64f3100c3892e6e07ffdc4f2bd7836ecf1af568b56b20ca9fded07dde63bd1e98a0580f084d79ee2446356f43b5d6a39b13defa6baf4a444eb7b211d24913033e30900a73c1544e023ccaf14aecb16ff7933544d9f27f8ed0c1b3fc8014635d6db1660955957ab5687d79cda35d6b0c48f4ea3d504c07ad46ff79b29c6cf9d22238d60d3b3b3abece46a228f53b3b604c21a669cafd94db64bce6a6ade854a99f813c07bf0b4190910204a594416588e483bd382144c989be97dccee2fab64c29505d0a1637f003e553841345bc0738a4bfe6a0047fae501a2c4b765cb829bc415bd20f06669b32671e30562adb1804c9f06efd81a9791981f0e66669e481f06ab5e60ff1e3d5d04f77541a8b37189299e9732b2caad7ec05d6d539c6a973c72a061603ced3b45a9c30d479dc5e2abf04094e78444de011630bc14ef46ad9397afb010e2d631724971ed168c92395b2e4a4faa4eca1f1a4f4234e1d5ba1db3d38382a012bdc552d7a85abbb116e92c0904078179b9356574c0776ef995bca962de0f600d97b23a31c780efeeb90710faf591f55dbe4375719575b5ef47494a4236a1a0bbcb903928330b031ac9e26df4d1117391e58ee746bab3b9c001749f13a072904c861dbc8e98d6638e3f4c9bfdadd8dff8fbeb02319f139c662a0f64c238e53007b065b4e40476922dcf25d6b940fbd2d23d0960133bbe7f5e76c14d094ffcb038c8aa436a74ca1c794adc53a8f8d88b75f870dc58568c70b88803dd35944fb082015403989f8d613ff4c73cd3073472d2ecd5ffe05c62b17708b85d4cabc380debffb1dc47a2c5622ae60fde5d8b42a0b50ec65a96c3d0ff5c0566118936bb0a066218c4daae3a29ca18df18632675a1d41135f3674e06e4bba29700550af700ae35114614576580d38aeb360fd15f942f93a198fef462c9333a7dadf4a26a071af4a5f762c1761957889da5d2c46c4b765dce4878d0582cff3cbf785263e2031b81cc165de524226bb781c10e1fddd68ba07b7ba0b7afd34e43467f63bd1902e49f59e41848402a46e6612aa84209272305cad2cf163f507761438a356e2d08521fe168037e6e4f0551d5daa08e3fffa8e759dd7a15d05395344b4bddcbba0ff32c5a448d978b757b164e64bb13d06c1d191519282befc4e8c4e117d520dc050f8acf7d136c248a1e2737aa3e68a80a18c26a602b2bab791c66374723b81a0881ad60279ef5c9111ffd86b839ac13d65a6bd9fbe32eebc9c91b53947d4ce105e8a03f2f0c1f63b9a5f2a2879e44307e1b9349a03ee622e55d7d9b029dac070263c88ee4c3603bcaaad0744764488dcc5f546130fcbf9212edaea64ebcd28c037fbc310b1f84bdb801f6279b40827d384b818ba4bde847771bcbfb9749dece0f1fac2936633ec35da024fb8d5bf7870845fb5d5d981050e4b6267a4563af60050784cc9c1ca6e6666965aadfedd0850b0195f3730594294a72c6841b0fad7003b2ae869bf6f02baa394a5c4d5a254178c36c0f6c5e07275d78bd9e3bb8f35c0ef3ac447fd2bf1e93c8441a965a40210037156c0ad09c3e2cd5d6fb1db715e206d85147539c3a2a57f6e6cb24c172d4cb79d2bf69c4fbbb186619be3a3ee6d90685c668b6dbcee2cd48704aa5b983478fc00a273458e044b167706718b3bf3a0887a5aac2c299f84bfa50347a6f94298574404a89e17a6621177fdca18f3b950c81076e0d0ed7098f20bfcd9312bcbbf9194ee3b3893006a9d7f6e456ee8b880d9e4c0555f82b6871cc2001bc2013b6247b9a11bcc469d268660edcdc7310c4015a55d2c16f3e1e4456e02cfb15852ed8b08d69981bb5ddf2df9dbdb983cf8a07ddfd0d4304990050d185268b1b5a513cd30198a5d2119e719674f1f210b8e709db3b8852af23e1af2f80eee291136b3c8855741e85f1bfbb4feef6575f7afa08820ec92d1e25a0b3dcfad4a398952c1e308db2edd8c1f8b9ea5d431930231102f61d0561c6f156e78f2c8fdc8868ab80e27e9dc346b7a894a2290f5c0a25e701a468128b291447086e8c4cd8298fddbc5a6bfe724b30007cd6d5d96ef34a290271643027b820a2b5a421aa861c5ada4aef3d90f41fdeb9f90368635fed309b0c703aea81773b8d5bac2c149504c8e9e959da9f55635954eba89683aaced77b02f6ea5e532dd35717f9cf145ada78a03a0aa2fcf2f96339c3e566c3249350d704decb459da508308724aeb097fe49507db4c9a241546ebf0444a613055e91fb02f7d626a1349d84f547195cdcbf0e51ee6caac2b0c7addf3e6e9432e5502565035fed75f11eac2d11e38405d2bf322e097f82bba18b0242b7c0fa0300c0bd6705d8b2ef4602765ab42403c26e2f93fb9c1bcd5ca4eeb8a720181190062cfa8203314ac686cd33c7d17a0c2a4ee391f17a917b2550a918ddc3d48840f807e35604671d15f822bd84d6fdd478ec8e3883800189e5b9333120babb27c2d7f35549074d5533eb3e9effb39c34f1e48410144c8aad730667b327229d9bf7b34281a60fe692ced291ca32300721c703d2a5a05bd041dcb95ceec68fd38c5070933aba079902287954f15e3a267fcf74ca95d5ec5bd730da32970d3b54c398bfd8aba902e050ab0cb28e0cdf5a778a9555aee22bb282a19d947281e9e5ed4ebe51e62c09508fa400022b75eb2a053b3ea18793296a812ee39d545e524cef6ef5a9f9470fa8bd8b05e62bf92619c20e66b5c40646ca576add5f396a71ef2df6597a8569020ad23caca82e05abffb7202c57c9874eb11118efdd549bd99005db53d59f350a4c8098fc00aee7ac921a4910853a98ac739fc457a763cbc7fdbf30d6b84d9c03ef4c4e5264f6f4c40f2b4a96105f0a24bbf9f783efe180f321fa21ddfcc1f000aa92823ffc2b573735e1377e71c7e30681d7e4c5ad14df41d1d440167d4bae09fe1ead3fce7f59f5fa8204b7b4f4276a90eec6d9a84ff72a65d2bbfaf7429a066794987432996bf120959f9d11c73975d100261d4dbc79fb3a348512d4c0590724824e7524b124e893cb36ae31bfbad002bd992fc0872fcbd92fe4709291750e50da7cea4dacc882851dfe91d7c517bba5b37c444353f1fc375d81d8f885a0066086e8d7920a7ddd8ef8769ddd9494207569369b56db79b05158e8d83ccdc009f989019f354d7c430210a5ec0ef60cde654f923293ce5149f9d0653fb90bbb0199e30b2728c8d27d71fe48d75b8bb58e082930f13903d121a81032a3f36dcf0e0959c8854208af4723bf52cfcaf160ed079d2e3cee5ed394cce41fdc3e81c200efcf5ca866604c994c30fab3c2c1aaed963ef581c578fdd4f126602029d0db0ced3bffb66b0df1d42f2bcd206c12bc0963ec2a7b7998b7a77894f673970c9401d6843acbe4814d40e21c8e5b14d841b80c55db86830054c1a8136760b43ff90d34f21d25eb65c55c024a834b6775960ad36f65ff56d541e5a1eccd0744480d09bcee62840119d91648a2c284c72375064e43a18412d30e05847fa7bd4623cc0dd0a5aefd575e4bfa66c2a43a44c1d11688010ef167ad09f47d4ba99b5cf0c002e832384356159c23ed1c87a8d44164dbba2a6db51ed8f8e8c018aeb9daf2ad04aeaaa8a38bda081ac6bcf68b223e5607eea6c35675ac83dc1f63d3bc1b77da0ecc20c5d70c0455484921be7dbdcfaa1880d9b0cd42d61d044706de97b8540607f8dd6ce1b8d84a76d3be26feaccdb57f4975efe99b88aaa91c66d4e6cea9210270fcc25a96d56557195f108bcbaa312dd90b19d77139cce0d45884a22622920497ae02c4632a97f5297e3a348251c023cc7bc89d3920f23f9009b17782ce890bec77fa359f14cd967e85a9357157321e820713200555008b10929370506d22017850867feb8ba0f89989a2cc71810b612a72d7f7d4965911d9ca7828a5772f0a90dafcf4776117ca1a012c3a7445e2abf6620606414516d3e562a6925bf83a0e1baace214c0c762682513ad146d1e68386fe717135fbb4926c00120be1523500358c22d4f2672f1648818c3a35ae3009cbf3dbd34e7eecd69f5e9cc54d646a025faad585ff6dd20a83d2ef8433578277a4ff1ddd1b46f9f35b2e6909bb446d06987214fc9a1471ff80d0d37a4df04e285354263a2b9fc8a842ffe5e23c6ff207866c08cb7c9e7fafcbd881d4bce175e46a7f5341a2fa39b66f6bf3146cc7610cc0c031af56fc199028005e87628c897a0c6ad4254ed87643c9a5f4dcbf5dff09b432867bcd7ab1040cbdd17d72036313fc24f6fbffcfa6684896b92aef4dfb07c6c28b6b31315831fa6481c7d2b4d3ab3ddedcc0aaaa1bc79171eb8ef676590dda214657362641f440ad87e70854f6275a7b6da27918e4e8d16c8957c70d650d552424ccd52431060b64f996b319a91d4257531d8b96fec2abadda7c82f8ea0c0f2bc9c457cbbbccc2efe29f70adaaa233ec94f36a1cb08b9dca32e51ada68074d600f10b393db2ce0de4fcc6daaa2b9296488f8cf682e3a4d49f1faf8fba804acdf252174951031d14298d1254fc6c0afc7079582852cb27f2a9c763165b109351847f218c87dbe85687a363911441c9b558cc5ed454f9d9fcd263633f2870183e5ccce241e80ef14f1391cb0f8054797a5f4a69736844d034a950df205d8076f21ce184814856dab7936bb6e1501afa43657b5cdc69fe0fd51addfd812870bf81d159c3b19baf08a76aeea0fd6c0dc762e755309d1d6f3d2a1cff366a3e807cd549d514dec42bdc5e615d8ee5783983792c534dd9da4912a40ce57c6eda10ec29c4fdab90101123e07ebd65a35e91db03c107019c05811f919fa85e6cc6a0124f7eb2bf6e97e640d298ea69f1a651a98db3aaa6dab9cb3639508d7bec2f40a0da6f693315d4b3d3a1d0a17bc1be300a3ea90a8ce6350174fdfc9d74d4e970b8658e3f18877a0d52d234a809e62b04607c7183f44060110d65e3faaca400004427415c8d97ebc15320e4f79672e8f959a29376bb5546a8fe539bb5fe344df06498ecb20f169b2a6c7ffec9c48e23e95772f4e581d678351e51a37ae3c131d0cf3cb901d6f56040eeca76265dfd3a25d85d23cfcdc1ba042a27a2055f792d70dd939d9e23d0c47475314fab9b8e1745f383089c35ae4d3d8a47703a628a76e056b34bc57e918e55f2a5ecd35ade34eca1abaff86210254e51eaa6166506c490d85119b88d7726c17c38878a4c7bbb4b44375fa7ba85d47e345c97cd643e4dc0b +generate_ring_signature 7d40505d96cc9812cda2ecf10be26e35068ef21403fc13a3fe0374f1752bdc3b 58399ed2f6ab0ef8e44f8baabd4b7668e5d9e0ce163b55fde697dc1f57b65176 2 a0f1b1b883584dd18faeaee8affa2076a50d7783086353a9b7d4877f0c23bd55 9c840d84c4e8d918410d5efcfaad94d5be97b5a16738f9ba27c1301e30adc367 bc309edac23260a587d0ead081229e22a1a46029e24bfc99b8d264f0cb550e02 1 d3c0f07b5e4aba145fbb608b9f47c5511b83df8ae9730e92019b0d7d62672d053f904c8affb4366a819b1f057e1d0a165e065e7b23ed0832c0ce4e4379ed3e0a6defa5521d6a72acca6df52aa40e2880638a79b6a89909d86438cfadf2cd970fbdddc6378cc4d783be3cc4724cbb9a36c50d2a086c73253592bd5bac9860db04 +generate_ring_signature d2b1be9c36ccec50df11eb89ccada0a0d065fafc1a4b7296d85180598d0208fb 790464d130c590b15283bdb524cdc611c1dfe90ed958cfdd1c61f4a8c610e971 3 c760502af5bd01024b414aa8e6ec3291d24a119c069e5394023daa44cf502a35 304177d3c97d2ea31afd6600fab36a15763c2a7d6fd2b179aaf9adf4a6d93288 5c01ec55a849da5d9c141a1da2cadd189c7cc4302866056619bcf541c0ff4c0b 67567e52f4f0d0b41c1b633d3ff41eb5a3af5abbb4b71ea61b57dc39e433bd01 2 f6eff52b7d9b962013a6aca7dc9140c8ac8b2df68fb8b72fcab97803c280850ba3df73574602b238d826033bc1cd2072c572539b47f71bb221c2ba8da231fa0a76dc35001b0f3cd38cfc314fe79d78b2a1d18474c6bab85b426d08c1df8faf02a38f035ee4bffcc4babab8558fbb7733f273bd89f6bfb1498fca8ee78b9712000a82b4d043cd6d95314568a8c99cd273e08013e82e891e7fee58757cde825803d001f8a0fe95b789e91a1c8d3e1c935b2000b73b9215cfec31a611282190080e +generate_ring_signature 6a7157bd5b7abb0dbf254d14383ec158061c39beb909e371c736bc053821894e 319ca2b6bf52f500ee46fa4e19e07878690597cea71cfd1294d689377803b4bc 2 f579fbadb5fe3ef087c03567db8a70b8b40670bd8e77c9cc58a519e55fa91265 75e979d40c24323138df595858e567668aa8085c2adae4cd9a72ce08499f99f9 0e8eda5e20345e1e85b44af5a172c57f1b7ab0a80d4323bb560058b4bca9aa07 0 fd80ff060c2556e6d9fbc6cd4a2c201bf2cb045f4df0f0845d574928fd1a1200d65ade85ec207bd571317bd3b141cdc20f8db573d723f95ee87780e7eaa6a203b80ffc056e001e43bf73ed2587754c3fe62a1b0a597cb5c3f2788e41368d110082045b3ec5ff1cf549d2bc3a89b1ec602b1983966b618e74782a506c09c1a208 +generate_ring_signature 2ff3bc41c8184d849397465ce855f0331b2fb8089acd03896ecc40f13c26c6cb 3c0d534bad069aea7a7a99f476537d5fc7d744827fb3c5b1747bd5e628c0c060 1 6a2dd8917bb9f1afe10a52fdc06a7f1a8be194adfd27720f52dc6b68e41dac13 9a8ae3cce36c6a7ce062ca5008b7fbcec509d750a7af1755506ca42987e71f03 0 0078c0b416b2c63ee9bbe3df37387a4b4a62960555e17a188a7e56629e6d08078b8469eb6c8a14ddbb3f5e52b922dc34ab900c2d46c00b561dbb90398360b408 +generate_ring_signature 4de455ffd336973df436d8cc5400f445edaadc720ff6edeff859b49238aa2fce 0d974c6f5c5852046fbb400ecb528e463a9ac8ddb7e4f87290675000e4c29634 6 e119b88581dfc38a94fe46a82590cd9b062d321097017947ab2a039d77723a41 7ed1ae0e3e982d596cc6b1c33913cab5e0cac7b70a22d957ce5b51fb86ce1535 d74735989a7d20983a2adc2f7913caebf4fc12e1d33946c96d893ed9fcc41b12 af83956b543c7ab0878eda74010bcce3c086b748e6ab788628c78eef075c90d6 357399bcc7afcb24242b9a1eb62432c35ae6cedaefd732cc858d7eae7cb92e79 dae830a72a324ab3113ae4913a820523184bbdabacfe07bcbd687ade7d8659aa b5558d1400cf33fa98203b0af326975ef9038e19f64b41299a32a0f135bc2804 3 3e757e2e27abe42b28d20cc72da606aec4d895a6c6a2734f85b6e78444fa720cf30ab910d4fbf81a7ed6c858055f0655f4d0b4fb37041a37f97d5cea13dd0c007b8164d579b377bba70c9bbd4f98a9cef1fe3d7c5c9435daf70ecd1827b3fe06eb17f8d6c6ade0cd14f294b1fdf706208a5a70c0cd9f5990e87a052a4fae80037cfd63b611415417d20e85c1e89740592ccf4a59844d2ba40f2a21ea132205029b63b09ef8f5367272ccee350da5929b671dd56a30e4849eb54b369bb45d880dba19e4ed2e3255c72e8a23feb8df6687b6327d2845d7fc13921e6182f5f18f02e594efa77dc22c4fac2787a3d67877850ecb614f136af268b2b7eec86b04120f17a5ff725f3562cdb4f29a9f4bf5d0b51a3345ec6c7d4ded504a11076f379f051e539a6d9ab6d06cf26bdee71283cbf0e741ff8e10c9a1f5d53750a836e3c00ba31af2d74c3f2bf44a644aecf2510e21e0b4e0ab997ce26c82f2f699835521046edf1258b097204b62c1a070dfba6daf55c67c59c48b28d1a586cd493713e801 +generate_ring_signature c5a69d4c24d9ccccb2b7f24569071ae98acf6e03b925e5a9cc09752d801c62bb 3eabbfe3695bc2dbd5901d017eb2e54b9caba0945720164f342fbe3e6ce66b78 26 f43a0cea4cdc1617fdf4dc9aabd74562d8a295c3f85ed4acfe4042119367ea4c f4b250e120df0108ef321a0ada6f8d56a290ddc4164803d62d92e06524f4487a 60c9eaf854e68882287d9f28241a6ee63496342162b018d85c7e547bd65ff258 d3bbab657cf5184747c0ea16043192f6b16743a2aec28a35fb3e03c78114d01c 8b00e6cde3c562f5d9318949c9eac03c685090b8a3d57ba4ae5704ff3b5d1f02 4e16fef6f635620955f7ca6ff8f3077e146acc5591573501874e0f7ec8a6d84d 1ab363c7267a5f871fa39b58b3f77f132c832a148255fa43d488e145b12f24e6 93d47d397bd986ae573e04cfd6502baa9f86572d8fbe2fcfc29d35a6c55b5453 a61daf279f18faf9f001831bc06539fabea3cf733b10abef58a1523414ba2496 063029c65fe66102a1c47575d374692a459a416b9fac9450b3c102494b85b5bf 095fc13758f256b4550452a379a65f8d1c23e670cb5904394d153e4f9ef6f0e9 8be1d43efa5494cd054ba8f7a2ab134fa778dde275d453564e2794af637c26e8 146719dffba2869567d19999455814cedc3384b8a104dfb6512dd434041e8f04 8c21f868f215881a4d8f8ecef15a45ea9c5577c96edc5f2db93aaa97627267d3 c6cd4788daba63903038377a7748208b58351ec9384c96fb1c85558063ca8128 3e5881dcdd2d29e42ce5229d59c8427d266e9c0bfc48bd849a22f9c563ff572b f2ac153edf0d83e0b04bf20f7fb6c70881a8079af523710983e8aa89373700f6 0bd89db8a50f485379de7737d43b3f7899c254190c41f8ed38c1b82eeada7554 50313db4b4816e421de0dbb01a534131546b64539e2ff471e63e8b745b825c5f bed722400190efb4c21cdb4d76679ac6ddd56ef850ea89f5ab43f89d4f2c02e1 c81d8bb33ba874db043e3d8bf303b5790192fea6459adb800a76d48614937fcb 01563d30080870956b47ac0514635364e1c5f8d45e62af0895c405e96be1516e 909d70e1e8813e0ac85788146a836b2cf2d3ade2d2c5b18c9b08cc41b688990a 2da5ed39c9928eaf2ba35e5195ba789f8a01e99bd9bcc55c81c5b1c7bf6caa48 4668235408de2079f6d3111e96e502117b10d42a5c0e7790e9eebb7105a792bc e6574c97ebfd1ffb756f4b27c71b787e0c332b830086081ba57cfa1a699ea613 66dfd1881a176aaaf91af0a512636d9c0049460df4ccce64a4f7527e2d0e0702 16 901d6f1e717123b75b9ed1164ea44c07ca4131f1cd2799bee2cdf29735b0b80699ea5372d18635fe2bfa3c950e0482427df03d40c4adc50f1db42a3e94a7af0b0e479064193f147db1ab422c340c6e1a67389d89047f8c5dda887bc78600740094716c074059508d333eece20c516a628e3deb722df58009d96475639319ee03086d26db422c9b7fc7036d7406746a8f368b2e903609b930fceacaf151e9980f9c58de852374785c2d3a14194bd43f7c4833bda2260086c4c7e594be2326b60f05cd27166aa69154f1972251606ac671751623931dd32f433990ba44f4d1570c266e1c5464a21b0a3c5cf66a3a9c357b230ec6be5b1a6df533746482fc0344024ac8e69f61491a50861e7f17edd012377dab92f11283a46ba0540d21221e040fcea1ea30fc16bb84a302260211ad28067189996e5338433f3a181eecddff9c0ddf7f4ddf64149b69e73812adee8265368fed21b6c588d68067b4886c8fccdb04f304fea744c0fa2af7b23b111f839223ed247641b8c00262d506d7391bfa6a0c170c14f5602762f77f5251ae2367540d3f19b8b22eda0cc374fda732eb5330001fde81195a6d12e7e1e00c2148c308a11cbf26a65dd4666596933653b33adb0392f78f4ce83591266dfd94507280528be5d1554bcaf86ccd6ab62ca2004e39065a79b85ceb47600ba9cb33d71248bc42e3ce447db2b8090958704907b6871f0ed7a8e6c47d315c39389d75d7158bc79ec293c1d7725aed037f7940764d85740a8454e9f1de641e90033843d67a19938db831833a079a483dce50a34b89c4bd0f92061e9acaac00860aa556e3a6d77c1b4ea36477547b452dae3f4657f798af0cb14870e5a6af4a77aedcaacc8257299a3ef81682391dbefdc7282b4f052f550be7e0bd6dc73e9833c905f7db40c9773b4f658564bc277d683950f2ba6871270b34880168eb8805be7b5c90d0533c811bc406711dd529b77cae3ec93566adc407fa33cddc6703b16a4c1756ec5eaadfb52e8ece9af6faca60bc70a79ed295b601caeb1f563e667145f0dcf626425e721b1aef9321100d56d190f5451df30eef07ce08d22b213d1414c3682f8baf9cd4cd40a6aaec89e8a2e2e823c18eab98b90268308ce9b4e55a45fa6b9e67eafb71b9047a6730093f4d82ed71ac05d96e810dd79ca714eda18deeba0f7fa515725ff1c738c9095abd384044de3a27fc7b21006d15b40b55340a94c0e5724c85007ce4787d37e2e08a62456aed9b79ac8ec30224d011447b9ab3e45c36b2ea8c233cf4085c6d72b46f6dc461346d0f9e802104c99c0b44fff1f27e8b54c87b12bf8debca6c534c83e4bfc1229d25ea5b160208393f9210e4352ee401641b6836d47fab468c34b6d67ecf3cb35c92893a361b07d5ad4a9f3b8378a3f1326a7d0455073aafec91eea2343650614f5db977f5a50a4b4e5a64480b85c8fb125c99da530baf82b051877a0f0b4a935792590e2bd109b570aed7260c79852747d0a620312110fbc1d67d5a5add8dc393147375aa9c07532ed98fa2cd1ba0984b4ca47ec6c01376820985bfccbadc84feb67c5f10b50e801fe2c66f1a6d106dfa416b010fa353c656a18b3cc9e7b67ae64f32993d8806ff36c7d0fd9dde762f0832fd177ff6abdd023b79820470c4d06c4a216b4e1804d6e9ed4a9a30ffa11b933d89b92fdfbf8b1e7e103fc8899027046401d9e1f905652e03458b59fa8429d5c40feafe7c20cb5753efdc6aeccd55b0e32884188602f170783a4505fe8961a3fdb8698eaf5311b5d4cee97451db95ec6d835640eb07fae7a1d5b60721c2ebe336577fd0118b3f8cce7a6d279bff09a9259d66212408bbcce120a2ce1dd45d9c01605a6373e7a9ce7ac5e8f756b21b518eae1f128f05f95d22bfa3b4858e9dfe7adbba447ba09e90c7438b24c974c921b82b8cba310ba8f3b6a17c05aaf652604c15a2d17f47915b4548a577bfab8c5de6b9268e4d09cd6e5fc3b4d694d872392983d4c88647b53807c72129c03b429967bacab4620e38b7a6994d1451b0d1bcc3694ad5a98cbea059fcf9d26dfcd87c9b2611c5f30ed80f22363a671634f82ecee8a5e5735005c1fc9519b8d3cf79165654e21fe601339ada11894cf01e553a893e8cd3bcaabc870bfb20cf5bee731ca7d95f077e06be71d6c665af686b8940e4a5ce7d7460f70d35812b6dddd2ca1b92e3db3883094dbbbcb55a3bea997e9e60c4bd80499eba49067414f21156aed234b6c1a69b0f30cb8d708bf34a43fe2d1bf764e84a2e22d23995b89812fc6d1b2c47ba82720f7d97c279383135c3876c1173f021c312be46027a8228e931a71ba185f784590d +generate_ring_signature 1a25025edeed2967079043c06388cd736a6305609ead156e76233de39443e6db cdd7e9ef74c4f826659baa13cc7027e9d3c0b4379472adae05f36e99ff600541 32 18cbd5ae5ba735e8ff1df944cca9ae3bc07187947d3a0377811c7e0769cc46b5 2eee82ab6674d77e15df8e3fef6d52f2159d96f510aef9f03a7080cc1df8a551 8c891c48ea8e5578faad92012e8519be5415a6397f92493cf368598927562aaf bbeacd239001a036995137abcd6f6df6af0d42517532c177cee3d774a14bd50d 6a7439d1ffd71e17552bf2d14763bad542aef8690dec9a35e7033d941df846cf 99d0c3c86698a62548085e50acff48c7142218ab6c51308429e5d516d27c1e2f b14165aeef86209407ffbfdb583485fd28f6edfc09bfb30000a69af629660478 a1b08ad9ac3f2fab9ae1c44b64c1f8c0d89c7ccfe524220a63c8fd4b80355937 c6f39774cabc63d8a858d76d2b67968c57754f6cf539a0516ebdc2681bfba6c8 e1420e8805e8267cf5cf14ea411f178feae61416ea6097c2936cf255d6da75af 68f36553bc4e176554dcdb4d40911c9d2fc1ad535ed5de68e61214740973721f 36995a5cc2d48acf783e851bc82a7d33b39e8d5fa98a28d053496431f62f4e8e 6e5a2e1e833e72907908da061752783d2bae0fc8ab5a5269693ad104fa23a541 e4c81b9504412585a70f804cda57e30835428f9e7b33db9e303cd8280e1eb133 b21e9d751bc67faa423ebbec6bdeaae824d66f1fd287229d15202ecebf972ada d85dfd2d4c2d681e4da972cb7ac70b9472b5a9cf847e51c7257beaf9a71b6c7d cc68be54b9a80b51446d0588e46f314f0ccc495c7d51e3d271737e76a465c33c 34305ec1efbf3dfad30fcd4e67ec2b03687d889bc2cdc77ab48e0b5ff9cb56b8 c1e4997cb9f2baa62de3da1f39b14b0f81dbd2b5b1458d4017e9c3d78a24d406 bec351ba97f26bcb0b2e4c2dc0c42db166d281a7907971bf5087eda6fd4c7092 a61009cd579acb5a183f65cb11309fbfc2c83f15a8e9a3733dbcce4bcc9b68d0 4652edce62b97c125f033318f97c9d0b6af10e054d424e0054da0892856f8a5d 089d6c08e5cda9afc0e25c942156cba8e1154aa6e108f7157b21beb0b1dd9c71 7e67864cce0de6e0b36e85a0ffa8839316dd5257f1d43a4bdacb63723937940e b7924cc3f1eb11c19f0f92c4328e485ff5c087f7cd65d56266882437cf36b3f9 b90b30b4dfe9bb2e74a319d3fefdfe16dd466c5f304cbc7002c0b406c75f6cf0 f0e309314c00e1052b94b8b61b8215385eb018d80f7d416c7ffd3e303c8355f1 532eb3f1f94d0c51c3c2084e1459abfb07ef8735edfd8f0549904a66bea4a6ed 00c8322013b025dabc91953fc9d2c7558e2d482f7d3befba5ade16bcaf12e2ab e073df0ab60437b296be99f91cb20f4e2739ed54d3f387f1bef16935a75c1712 9e3706f7488756a2813420361f139e2e8478d77a52a07e0e3e0f2f85c873eab3 021fe8333e571ffc9e67b99ba619a42450b5c1fffd3139127f63412b9464a57a 1bbbc450a6b3450d412637420a225f94f6a76e0de606ccff43a749e255e7a803 28 9a09b789bafc6604a37b8a0b0b3090ed02a8c886f39f2bff159121b3ef0d4c07dde6fcda2c176638fd5d08c1678cc8becaf57c093fea4bfbf9f173918de49907f8d44fd477ef07fe43e5bd07c6cf2f8ba369c4656a5ff86389e928c62e346b02c7689696549f38ce7c9461a11405ff59b813b7fec52e8fb4e55fb6d3511ec5026378c74d73ea9a024af2c3b4fd885c017914ce7d0b0258d3fbab210541068a035cdccda0df52fe83ab758bc953e45096fe20cc575305acea52cf30aabe9d5d0fadedc5c16bc5be2e7a419f13a525ea2e482f20e14ea9236f59fc9bd5f8fa7a0dc7b7c8c45ccf354fa2467a91211dbdb2c73fbefb9a33fea234add273c2530009feaea50320102f4313301b882c080d2627bbe5556aa6b005044aac9f1008bc0abb7d0beac67928a451623eeb09db18332e60aefea1d07c6e719befd54da3a70f0e5d2b7ced91ae5c620e7e50dd109244bb2a49325972661b0084a3108969940197bc542f896909ff33c8eb4afa44019e9e28408ac3082bb41a53bad633f33109bc54c7dd2c34eb8f7d222d5ed688e313581673e26a294805b035e5eed2dc5d0cb3170db160fdfbca232a8f216c8e2c0adb9dc52d1411c42aa1b3de2746e4f90d6de5785c50f671b158f1c383829f4a9c7ff02b9db0deb49389e9a0d67d3f6608def932ae29df5d4e7ae793d3d37b31d59dae9817123f2263335fbd5d881f0e0029a5d982aa0f9f36bc8c43a7f73d745e198f90ab5522461b5135fba79249550ea9af2ec14a4412c0a36db71e72071e47ab14770c29cfac535b352920ee4e240c6674ca76be39e63846316afb101602e3f22d9776b7f965796cd310ebf1fcc7001092d4699182ad99b836b48704d663c493fb073643f30a50c3e982fd6342bb035f41c3d846aacfd45ea0584b656720fce0178cc9b55353fe89a0861b5e30280fce01d5ac0ed99428b2a20dc74d37f6036282eae971a2cec5dd4bab5f040aee0e4f4f2cf412baa3f94416c77c76e2e2d60287b5d4071dc88a185a83bfc60f010be5aacc7c4ecb42830f80d8e23e141c3c556335e0fe4ca52c9728a0d5554aa90fcbc533ebf11e39a5aa2e3c67180502f8b84972570e44e38a333ad9e25dce2302700eed4ca6d9536c579767a1d017ed28129d2c11d5d5d838dc73ea9406dbb50c18c2b2fdc8051a596fcae1b960a8a80b85ddf8b0b630a55dc9407d1cde281d076bc20384046a5dd2c0119c247a0f54bfa4aacff29218c46e6784e26962d0c50555775330e97640982447796a3c9c780e394111ce1257e50eaa8318b76598010e6458c00d070ea208ec2c6b84ab84c9b96056f2b6b806d13fa78e5fbef9fe9a057b77b3d089f06192eb0d97c1255642f2a101b7e2bea51e2c7243a257717f0203981213bb89ceba129d8b3da69b3bfa361e61d27d6b33b2ba5a9640365583fa056eb802e125c4d8b05207c11a6b63c1902ee8061d0acfafec338ec7ae405f500a0c948176248899ab96289407b2a0f9fdb7bde951c2f34c0959361d71e1dab30300ac4d93cd7c61bd2aa60cef26889a61de24f2cc526df392671d111f047ffb0a2e28074dfe315108c299dc32f2b528345cdcaa91553f580679ecb9338625800a862d1a96c86d14e25b920cb996b706875b5dcd58c2fe9079f3a229cd63506602c6ab0a980f23c860a21d720ab13bdb5dae34e4bbdd2b9c21855e113f8bdede0d63ba000e6c5f251525672b99176229dd7246d3238f89ed34d69d7cefd0198d03ea3658ac8fbad80f44b1602df08369705712cb7c5818f87d4063a27641eec90cadf9ca154871222da6e60815f2ec08ba3acc31c21ccd3357b348450ef0361c0925f849e754a914e6062c1d96176acda35fc6f639d967aab7a825023a036fa4004cd7d7cbfa9769491244409616bff61dbc200d250324eda3063a32c9502f8d06a26cc8eccd445d1a14abdafba0635cac7978fb18fa7fed7e2e31bb4ab9806606585d465766b44ea8fb5a516cee70fade1751baa5d4bc3066a8a90ee0b7cc7402ad642540990254b86f08ea45753ea104baff6b5fd57fbc2148f92226866f1a0ca782835dcb7599fb614f1c26030e7b2de088a2bf56a95adcfcb297f5ed63fe01aa5b95d13cc99579c7e6e8c4e502d6887bddb3b2c5f6fce7375e73070f91cc013085152f71b4763851aa83d6c829d7f72a2e778723d89ad3e77149047218ff077f3cd92091a1642c25b02c581a5cba5d047e7370add238abf3282ecd76946308dfee51a8914216eeb339d4978180dff40847869922f7f040344a77b76b5eb00333595a120c628c2ff92e4edc44b6e5efc359e0024b2d8459c1559149ce1de805e4f057399d93d47404178649356289c7d9fc29893bea6e90afb83ce184771b0b21764b1add18068b4e76fe8f73138c2a66fef7eed06d005b59adf5ddea68f60de53c378e744ea3bd6fdca265dbd761cc641698204937239991e1cddb49b89d0ad558fd3a776a9fec7b75c61fd39ef9c543749920a08dd8b89333ae168db1d6083af70866c03d031b7e574b477faa220492f0bceaa99a43d94f3b54ce79121d0bc1117ed2c1b3cfd2077fdc0ca0b3e60d9090d336e58c41090dad3e613889d40f98607e291246fdc9d0dfd5723e56f521f5c1ebf56ffc53e498869b74c40dd106018fac9787b0a836d25170986fb2a2830d6341ed45c99bbaf4b1a3893b30ca0f95b4962d0d5d966d4b06fb53a9cb0f99fe8f2f07f8175e9f16c6b74e3c5da700d650138abf1c55a43e69fbf2c9bf83eb24470ec1151baf6a1f829d51ae73030d9d5cfc6390d49932e4cb31974aaa2012d4a3a8c84588c01fe1147e463265990ff26720d70b4c6db955e2c1fd1915e47c7089820982c5bb81a844c8e012ebac08 +generate_ring_signature 06849cd0519c6f1009ff2038da647ab6c1db4158bfee7644db31219a32de2265 5ab33b23374071466d658f4931aa7ce87e2800bee54a77b3228c07a8d1f9e4f8 50 f4dca6918c240e30306a9f94dba59fc51a8ce538d71996d1b1ec029c9b32acc1 3cecaf5af6facb8438a4feef5999cb9fdc28fd4e4ea8ecd67ee057c70679a00c aac24c3bf580a2047cb608e7414c28ba41923980929864f3a59c5ddabe1813b1 178bc14f54597a5d3216a28b763597cd9593deea8e59a5e4ffab0d3af17dad67 cb648c43bb1ea79463c31058908db6360ae89bafede111ff9119f619ad40be49 645417d726d5f09e7c40ba1b1b1e17de4b445cc6b443f106ef8cdf20709de226 42fe478f50153993cb0de879050356c81055b30b04c773d07215ce8a05e86b9b 853818c89f9822f8b5bbd1116cb8fb192b49db52881a63fe91be8828843bf49f 43996d323e85feda01a303ec77bcad68cfbd45fa93ec6f52994fe002f3f63320 e80f906975529b458402d90e871d4fe391325a3506880ce3590640c1721663e3 249d745a3bed28cf3ab726767b78266a4f0df17ee72e4c228dd4ad9363198416 127e4eb44765ebb96929285776f2f28b8b506fd2f802709b960ba5122386e4da 47925a49af8a140f389594c6b0f58c0cc7d1e9b2ddf8b4b19caddcc3c191e66e f2c5333dd0c1fa1b3bbeb8f76e0c3ad4d90ae352e5491733577f53653a512a47 41ba603e6990ab4a6b38194ee651f33b1bd811ce9b415f738a999791e9ecc08c f0436f4175cc6fd250f1df326cacd940d9554ad61ea96fc21f7338b5314c0f0e 165eee723e8a32ed375e2454dd569b0a94ded444d743180b81883e7faa4a4f13 a85e2a7516551b743a2485984fb579351503bbf3ffe4a74a04877f9dcbb53690 e94ccff70bc813f73e14eae7093ce6610bd111710c284aec75a04b0f4e931fcc 03671c6ea4b79883673021463f66222b4aec7c91f5bc03ad7efc562fb6fe2db5 26a39e79ccb667024f0b7c90c1dd724da2e3754d810cd5491eac2b3cde14a1be a250f4bf3ac3e0b8aec3983660251dc7d6540d59ef7d05ee4b2c7412c166c98f 914bdb7c9c9b0735dd1be3f60171458b8e312e53ddbbb23e541660bb31fd1a24 a67f611b7bf550f4b54065c0c77352d3c49a3dbb71dde20777788eafcea84513 a9d5fd6f07e027beea34762f024615ff38a74cde6b009cb1795346607e5c1ec8 7c894a201bb20226d380c8b58342ab7b946782bed4532f9f25c40f639f1b1312 c360d3b1274db4fba04b8c6db76de6d52fd4326f7aa8ec955be3c62aed7188db 2be5959d53e19c49a6960aab64e2488996addfffb2419e3c8cef3db1f3c33a35 ba81236a84fbd39181eea3b60b1a85d6947007cf42c93ac15ef7a2cef6a4d3fb 8de16d964a3df51e199b8df767470f4508ccfccd27b7f6d78b62cb9398bc55ea ef9b3fbcbc282afb025ca8db586de74a30264588f5f1060d243c7865e4c18c6f 4dc1a34353b429f5e1811290d12d6e69f3485e6af9b389843aa1b5a067ced872 c8295f4fcc4620e37171d648e229e07c0ad3cf81fbdd49e895c08ca2dbb1a73e 39ed7eb8e5da66c5b688e7447508a283c96bba5c55ed8ec000e42ed4872ff145 4f7f18ec1e2eeee07658a986008ba1086b3a1f030a0dffb339099f94d4c8f3d1 c05959888131b964bb63476d63904d04bf1e62538e8c227fa6d6a84b1b2c5755 9af1683e1561c8c82aed8dc257a5f301eeeb76d538cb62c80d85825c3b58840d 58b9d74270c39051b00080c63d5d306b6c7e8ce773b912ae34cb528723b31409 75c8f3e9399c3e6a233b1f511138af008476a4fef6749b0d039ad92edfa6cfa3 8f2d018ba38454006905612074115d7f52f021de849afb63834f621b0cf86813 edb4523261f4218904cd2316470a97269c10b7dd6278345fad3c78508947624c 89ec4715a6d64497ee9825ec916c66ea04f4f6005f2c09737d094667e0e2c134 60d872a3dd8bc3dcd1e620a448fb2ab021b5dbd0e42bc54fd1a22173b7af796d 7aa0e6c13aa26d3cf23d32b3aac2f4b9f07dd8975532d326fbdce20cd978b271 f20616d23430a3a6df1fec7eb6ed20ac2f5f4d17cc4af342a92928939bc220c4 30ee3a8103f3b6869b385f54aa458acb4fbb8225b8cb1ba1ce0b313b9ab32830 d2c9241543810e19e2d25fb2b82f1bba7a7da6d72093f8aa35ccb1a7eb9d1271 e716caf713eb8e1c3f8c0c02dfcd682faec217cd7fb0a872f9a6e498be2d8f1c 8040cbcc375bb11d6c4da2de3035a95273695f28b3f766a966966a217af215df 118137a60cac4033aadd331dd3c1d1511d4c6b3ae41b929c05a31252f43d097c f28183b869e0e416647dfbdef14a6e7b1276ae55c760120cfb92d5333cbb870a 39 e1eb3a460f00a7a3435ca40f6a5c7ba8ad03411f4b2e3bfe94707e44f910cb010ba2b6c108d102c66f6a4783a06bba3797057881f17856a157b2e4a2393f3f0d1fa764523f363a7a8b59f10dd79275107acd1540775918677463e5a4a934c801ba7cf231688d9507794486dcab53bd886276e9ea13a2d7740ff0c387e2dcc104b532e24a39c6e3fabe529399597df3e85e23797eb505b17440c9f227625a6f0a8b73c9095082b50deb4c6c105a1e9b0bd4dbe0384eeddc8ca12f3091f1aa4203cdc7eff07ff6f27a0b825b192859be9fc6f381894fe98cfd1034325c04c59602e927d948965309ae621da6e167be1e3f2c9520067de4ff6cc2564691c6038507d3c8fb09b10e96e7a8847092765bb5d6d38aee5d39940608837be71cb24d8f0fb564e354e6accce164bd45273ce198c0d0c819e78e868f992170b0efce6bcd0ffdaf09c94b129113f8c6ecea34f30fcc76383ed9e7978e9806395ab15201590d40aed8a7bae628dbe33da05152d5be7d1d30b634bc98951bd7ff95ffdf018a004375f5eb45f5d940d98d8d1a22eb4485c7fd0857dbbe18805bd2a255f22dd60d83c26dc38179241aaaf3c92b23b61861c21d25ea5ad5ed07c471bf8b8f1bbc0118754e125914f3c2dc92e05af909dafc5436880f8f2f6e2a922a39cc54b241079a9a796de6fd96cfc3191c5429d8ded0136737462f822287c7730aa972155104a16f8ff9696a14cc8c83ba3dbe17fcc453910df037be3ed3829746ab68321c0743b9877196268c16f9f51d09f0f89f828f28ecb171aa13f15791399dcc8ee304fb20cc3b23e3330c442460b809468688b23133bb28a1b9c6d45ca8344ae7b70c40b7c480d4c1beed41d66326fc8b40356a285cf81876230fb2963cbf86da8b0e7f40fc5892b6103f2753b496fb65a4109fd004814ed6814fb8006922f6633c0e91bd34b4e2150f9ce1b5a264f3deaa5ee707126736cece2455eedccaff4a2406879de383ccaa21aa76bc38c9451746cd1de6152d3ffac10aa3d8d3880fdc3308b775283bacf20df252f0b77b1ce0dd87217f0c6045cf761e81733b3be4b55f08c14a19ffe72883161860d83ea44d0bde966e5bcd8cffa6b2d23cca316121ee0d544955a46cd3ddda4adaad6b3067c52e5cf27a47efc0ffd238f04d1725d00e0c6750a28bda45bd6a7230ff62057e561a0798aabb90297eb9e6ada53b5b91aa0aa24b49b81877ed9d0496fa6832b40d44872607d2f9f757c64e1b61e239f21502f7489c3fe2a5c4e0503a37b880f63348a81ffb1d9f47eafe2f281eccecbcb601e632dc45b91aa739939f67ed85218e974b0598c729a598770de520629d9ae80ed53c8be585b80456e19ba160fc9403f5444133b54ac109697bd25f524cdafb0d7cfc6579663cd67d01806becddd1e41f603cd71a852f443c66f5accd61c8c901d6574233f3729ce9dc23b251e345f3c9e26a9fde480c80a86196195d820c8d0edb3d643354db09efd245fec2b5fa87069bde57dea4385b6a30b8125e7576640629685fefe514a297bb3fc1705cf630540cda0be703efc10d14b3150deac7fa0dc2141ed9e2f0231bc073d74b7275991df189ba67a6a24136f11c0605bea51a0e88a87a4b0b732f296480abe26f8227febfc48469b0f25d5f89a23cf2c661fa0d363f0720339f76ef75d0ee7113b966b596c51326fc450d70e44450c6a623820f06991c7c896c7b0091ae83b4a4fc277e1daf6c26bf7b632fd97d8504f6536b0c4a0112c1ed00b9efcd4c088146a13b555c9c682a49a2aae35f0bff031ab070029a3d43f80ca442eec5a208dce3b9107ae2037c2ec22e8925f2308b0fbc69bb0c00ffe0135414b9608090d1bc165e7ef850d001a777bf7974b84e79170ee6630334a814a7eee3a48d127c1c4d0bb530eae9cb0bedeb64db6b7334b44c085fa601621177ba74c7f241f3a4bd8d6ed7e47bf25743b07dc9bff7702bb6b3a0714501d6afc4599903292281883fd892d8372b724bf3458c823300b6937bee4a4f370efafadcc48b857117b2a637573ac27b223f5d6771da6bf22d49ce4ad0253e230214ed4701fc50d479e6357cea6c893116486a7e892e184cb2f1a42b98b5cc3105b4a0ab8acdba36d8ad4fd610eed13b76770f511f8a1eeb988d6b69a25b647e0e4629d9ebd3e3aec6c364169cb13f4e4f10d4a98b81ccda56791a9d49041fe50528fea8203bdcb4e758fbca191e924dac1f617a5c0466496bc65109b36a921b051533fb23aada0dbd4510e2c8800cc147f99ff12bc5ee255e3412facb2987dd003244b4896f8dcfd352680d214f6e0dc60e85c0aaeaaf45c2dec9b9ce6a0fea0c1438990d3ce1b70560c2b97826ed1660a3430dcbdbcc57527cea62781072460bb1fd41765a53a113692f7c3f4b99535f799ad7cb830a09073b24f11964cf410cfec59953f4691ef03c31ba26e718982d229ee32101bb940242ed7df0d5a6cc0a38dabde82a143358d4a6044e678583b62509b28a7aabb864b550c2f0a332a808acea06519ae5cebd90099a96dd6b75d7885f4ae8b71c1f60d107b43d4a13910eaf9c35857b1b065cad69e683c4816456db4398c1c673035a008bbf7c8c029a01336a4b17d5c4a57ef76bf98255d20969d6843dfd2bad7f42aa8660a0e6f239089828de12fcc34680d55d5980c1a934437b48d0ab4875e8a76550cfff8eebb30093d65b7c311961b754df5e33ab418ef81920fe162ed0d23f3a610acf4d5e810a96c9fd97d8a936eb7412fb34580939efa836d249450ae728843632141c2ba103573c225945b429ae750996a64bbba856dcaf8d4ef290846220130f8e8349a5037168959bec73b4b5b5d82980b67af5ad9994ae31d0d37d79b015a788624fb60686b71a13ad639b7b3c7b6de3e8900b44b25187f7f614b27e14a99bcea2070c0b0505b4f1f922e00962683ab13e083bdd3a38f7ba35b0b3674b2b98db23ec9908c2372420594da0550d0066901936b886315c95a867b60a77966ba9cb2c876d0d5fce3bb2c38c39099655bf1673658a3f805e60c377a74df65d8731b88138cd01d92476d6e246736d9149686fe8bbbc0f551561742412ffcd02e24aba4ed1f006cff469eb95d3187a5b29dc863a936f16db138855d94d6c5db0ff7e88b8ef93038d3768aa6a3d964722c39b15f03c92888d547cdb9608eed212547a5fee785808df6dfe582e0cffc872fb55b29d512af69c88b90d381d28b4df087804cae76e04b927234355f252861eaed8cd00c07042e67614948492193ebc2d298e0a956902b3d6c9f965fcd053392481d2c3922a52bc779e321cd8c811e3157ea73c4908003b691a43646a250e06840a88121069912d81df4b8ecc2aa04231cea7390c580fb445db6236ba09baceb89f34686f1d900e1a4fc6a514a87b596963a6efa42304aa6e46a4e138bf34fdff9909d392113d4a117e6a6df512c3069a837f4d41550b6bb4ffae037948d1e4d5642b68528d8f5685e284067195b5de323cf1a9b1c706758c384d2234e66ccf7044f94e1f4f96a240600908a72f80115a7a715782cf00564d7737337b61120ed0fd22304921384d1736b512ed7ab0e287b25f4c48a307f2e4c1d76f26bcc19f92a910ae50e9078f24a10b3f029db1d59977baaa370f0128014b8f78ebc2bdc6c4509f94d959d041f6e8dafb06796be0ca8efca1030b0a76abc3c2f5be6f1311b9f2524ac6f452e57b374fe5ad4199b70482811035e009f2d4d6c97f53f26110c34a6a7a4ead4eaeb0aa8d6931cb3c9579f1b68b0e3b0dd7961eb5795a9e882739c2cd4220a5932af7e8522a6d58360ff91bb02823210d58c6779c4390b4c7c662243b24c2d79645c7c5b9d52e9a197dd2f4ab36ebc005dd5bffade647d1e77d127edff0e1f651589d483a8db87c7e5f002cf25db63b0b6ecd5140350d792ec8e509e4f6f301c8b7b238d8d21601e2c49c5ff854b3d4025902c35c1fb4fb9d0f1f246923f69e8b3eb2f86b7796714537357b3ebb92b504ac0dbbfb776cf9166c08abc1712329504be6b823add45ba92bb6f0deb289a003ba2f3d381a671e36fc1997532e07164238f8b99f4c8e765d3b5359ec9515be0c8dd6fbcb094ecc7d699f654cb6ec051474942756277f9ffd6bd2e47d0b5abb013e86940468337f70e113c1410c12019c6af7699710fc267956cc8278f8e256011d2a3a2ea94fd34d9a3c2dd7208e2026222d83f7c1a8393ecc66423cccf7b101d1f4db2822b707556bf76e3f91829f0fe28d25267b22228724b108bf95cb530f3f07b8e289fb12097301d2f2e68a18b9301c1aa90103e4f5a32c982aa7d0970db8703bbacaffc6d4a0d9204d362d1982cb42eb5b6659faa2abb2933a7295d50888ecfdffd1be43cbde1006bc5bef47b4ac17e5a0c4ff69d9965520820dcb1b0465f9c21fd07faea80669fbca108ef83f1abe51240fdf0f9685087930acb6e104d6d59d0d1df2a6c00b91fcc7448a8327b621d5556d5efee934b52559821eba08 +generate_ring_signature c3ed92bde9e8446efb5b9367d42ec2d1422a2cfa450a71141a7097a49688df52 f0dab29e41e047f2c8183acee8e0708501ef4ef0ddfa6e7f17a9024b6ccfe877 63 da39f87cd0110e4eeb4c3569349e603a31a6fb69dba927f28d18ccf5cd877d42 cd374e7929e2a64d6b9be6dbd9cd599d84d20f7612ac652f64372b73f1877408 fe80449785af9cf3ee7a75a83a43659c6f5ba4c18db3270b87fa75164c859f0b 1be6eb1f5707cc1869a2e6ebdaff53cf48ae08eae0a8b1e531b888542cf293d1 8ee5d44e7badf8d5c406edcdd8c530b16e4e0b3b9b9bb9355befaf2efc077aea 3d438a0fd481a0eed145afda32e3476b76ac92a006fb4fd7810ad329a29b858e 6b76c127a388232f2df579062c1bf1a28528be805489d4f2705d66123812b2c7 680039121a8a1928e28f3153cb1176401d5caeb5dba958c24fcfb0474cd4dea5 a19c49f7d41672de74e063361060426d2a8b882349b92bfc808ce1e61ef12f11 8303590b8103b58ae2c77bad446c90df388ab2ecf06baac717f0afc80695caf6 562b47c8f013f3b19c61ebacd5526acfeb1cb804935d358f7c91ae04c5837419 ef3a80c7141778f0a022a868bc60312f647d43431992d300194ef4ba3c35d438 79b1823612b9bf0aadaffb6084fd2227e72cd3d7e4e9c01ed1b49a6676ebaa48 0dc8aa6f08a8927375135075e0bb400446e6444e0e8417e6124520eddf59716c cf05ad9b936775c640987b5c24e97747a556d79438e8c971026419d7d570ed80 c2a77c27771f2b48d872ca607557e68b5209646fcd51d33bc2e7354ad20c64c6 bfb6f453161cf18160d66e15b35b0cec92e8ff6f280c7f8a3f7f6c8bd7c43ac6 f51fa0445e7aea779340cf8be0bbf08ebd182f58075bac9d6444c6ac43fc2f5f d007b1eda8d4fcf518760ac888c98c55e95d31a80f60dd2b4ac977b16ec218a6 621bad8defeb944bb8d45d8e639188f7126c575c99181c490020483bade02400 4be49d6eca74a476c53ea0b10339efd3f1c7b3b7ec94ed1231ed9d98d0c06535 e290e3eb2f3610c491129c37300cd2e06bf327604430c38e4ae74c2378521c01 404bac8f26b8258897596efeb6a2038769e5fdb5bd9f025879e62de6099b79c2 d831751f5e3f66c566623b38c3f42772de731327660ad06a3b074007ba95a0a1 1a82cd19f29451407682902139f2c23830fc162b921ae2ae5aa91829559610c2 15d0830fc658ae55e4dd3911034f674a1a401f09b7cc11c3cc6f4d2245dcaab9 f48765e2972e935d57885af53bca175a9f7900569120d1fcb7986c2f42b3a305 e3e2b896e6bc92b4079ddd3a3490f9c9fd0e759fd4fc2709e1d742a6196e49fc 02c733dd69cdf8e3890d006ea71c1555a8b6407fa2f3ac6d967f6e43db4df100 42d84b667f691ba1f585b49d1d5fa029da5520b0686d8798c592ea844137b3f6 5e6605e0f7abe6131b382e6a8759c4ca5fae77ec8291fa878935962ee02e7023 43db8314dbb6db17309b12392187087f92934bf63d7e052ff7df1dab66251e46 c1de18964d5b564728cda7674a983d85b9e61af2a5012489473cb9bd048de0a7 80972ee2f028d2f4b2a15800a16152d42bcc81ca3c2437145bfca495514cb69d 83ef50ea7e02045bbf4f158d32f4b942284e63e5f2b780280a87703e4f7036f6 87604dfb8212ad16d491f0d56d7b311b4b24888b360c36b5c1a1129db3f3a8aa a3a8d82b787407f866a125572c62efbc1da5db0ef23fc74562d4390c68aaff56 01fa56294a12caea1c202ced527940cc24c4a89dc8270f49ae2d18e842400b28 9f931197ff4f05f68b25ae4a86de55987756793579d84b5d62de550150164c44 b61458c7d49003834597f78d4a2592d1fb486482e8e7bc3c3a57f49ef2b8ac42 d554e6418a72f0331d05757d200c3692558f334802719b53927648acddcc3351 cbed989db9983b608bd23cf0f5dbb80015add6f0b67b1b6774dfa96e70d506d1 795ad4295025bd980139455246590abadab9203a035c50846e4e6bf5faefc729 75b50ce254809aae0d537d54c0156197e20dd20c84bbd9a62e2e301590ee0e3f dd8006d8f8db4216f3a0fdc27a872b9f2d16c511d450ef8ef9204f10860d8453 9903457d3aab9decd7c2e07202cbeeae6191259e348d0e05fc8439f06404ac53 40ef0206e8abb47158988a82b39fda91d6f52d592e49ddf90181bf959be81da7 baf85bdc56b8033c1e262e08e123e5353cb7f7ddb2b7ffd74ccfa529227853c1 a4d2ee759a828c54e976a8bbc55294e0f971cae0f30c4ff2fdb04f07de39c7c1 a0d47358f5ffe1d742a0eec679ec72cd1481f7190cb0aff2baaa141b68899de4 9cf118c576775697f38f65e1605978c2af376fc5e87e18c7438b07b48cb4ee82 9f022677e170ee00cb689b13de994c7ae9f5bac789ee8c8ae1e4c5e7e179e880 9064ec6c92d15bbed8c3ffa9c54dd4a71c3e940373033de467234d6ba7e863ce ed04f38c3d6180703052c3cb1150e685ce390ab1491c85cb317533f10fa252fb 5b71fdcbff0fd2e0d68d25f03b750e7ec3adf0c4455b0e06bfeae8437cf746af 7bd75fd7e511a36f6462dd1242f4c53db2b6fee823cb5bedc26bcc9c3bb52372 3b403b21997c01407a6af4215fd3c8e21b4badfba425c032623b182bb2e22ce7 2d15770f93f004a76c5e4ccc25dfabedf39e57420ec152fdfeecd75eea79d139 f1d12a64020bd216a36776fa960a50453b3a3cf398ac5cd64ede354e8b882868 f1ee519a49f43b4d6eeab6922191742c70adc22d3eb88f68f285114600740f06 8b48ebb921c0dcea1e01d7600fcb33fe4c50a1646de0f5feb775cb9bd87b8988 3485e0a10bfed2eba8dd4dd81e2ea42a7daba5c4ec4a035521004ef90274565c b6a73a9b1b67ebc907bfd0429107f58b7867a029b9e48bde23b821102f2b0ffc d5daaf0ec5ee5a4ae2a10fead09449b44b165bc5e657dbdb9aa0ae2a16824e02 58 6f085fd1adebf5514a126b402d28522edeb5fc4d76c5989c63859c58cf32370e6f320f35fdee15f7cd069776e4c0d82f5f91947e62e523dfb690c6596f0dca0171889ab5c7f4f44195c86c7e9421d20b455fa8019aa389014939e67d0cbe5606d9570d9e3c2c1c99827993738348e8b87bd47c23aac6b864a448d279b675870177c3d3e0e121c3aa2752a0c8c9db30cd31eb01ba9e64636f87360263120ee707c2a8b361c451213b2a980d54a2b621dcd25a40dc071066c8796796b11dd64f08a9e6698e7a747699321fdae86c979dd93e3bccc5f52bc5037d784de9d99a5f0c1eb213247b66a959c98c4cf4d6a1d42dd66e5f2a7e80dee0d1c716f9650a6e0628e3a3ff87288ffe89bb952a6db212ba96a1620cf14b056961d452381217f50244648ee4f8b501f0e23f76a57e27d2847b0bb0e9be8d4e86431c5d9602a56c0a373b3c97de97157fc2d0ee29e29deae82ee4c93c97a1fe990c1e9c0a963cac0df5e09a4d1ddb3414ca331c5335630dbfcfb07af8ca2e13889af0930232837302625041547613385102a211993380184b3c586bdb3ff43986a744325fcaff5a0f0a5812d074e1900d41ce24324b4f30cb31999f43f7df60d5231342f7a0744f0882f304fafdd5ba3ffdb52323a7418a4c1b246dcbfcc7e71d1f5f37682796c90bd65c2430e1dcc2ec73324b1a88321aaff72dda1e8bd78449984cbcedb1b5ba0fcf3c54662a1b4ea9d1a62a3cb612609ada804f9a9d7d70055c24860701b97f07ceb68e721193c8eaa9632b5b3f7b594be8a9930a9538c8f9ccf2b553aeccbc0cdda71a58b16d594d2df16fbc8829c7632b9b8687c518f2de428fe87e7935e709ad0d2583994cd6f7c9354cb38b4b6b511ab3ee8a3e544fecfa12886f91ec2f0ec772c9bf641bf57bd640ba5f36e57a685b4b548ded06f3d008f81210e02d420296ee50c102341a0ad38e23c312618fcbf11f960c75c9ec53c5ae5c113f0e8602a93b3ad40f211e1852311f85984e3ce48f112b3f469a8ddf5a6fc194b1dc310cfd5e567dd500b3b6800001668fb8cbf88e7abf0fbc38a432a2a3138f29e5440c5fcf5d543d455abe76e536d777331056b00517980f8e3a68b192f7a30f1b53045dd96369e04a442e917f63b0b22d8b21965977601b4f2d933633fabeaa01be066ce1dee3f1fdf05983257f5527964668720c122bf18f832e458efb1f3d4b4b08a1e190f557bc1efdb6cd4e3d347b97e55d491a7691a1199520c8e69054543800d8f1768ee12d514233b1547d56c4031a5d37ae7e54cf101470f525cd268e5f0d8212fcad8dff12e8d4bf23556e22dbbfdb9d41b0fc728ac40d78ca8ff0339f0836b4d5019b24a559679119dad490e9404c2728a054ec33b39185d2c7b1cb090e8a15ac74761f3c9b5e7a194ac4234513f33eddaa09a747fa2da116852a2dc8089f4fbb21fe317dcc242f6928e38eacf8cc0c802c3469959719304c7d0d27000517f4fc7cef3868427ba8724c6ad934bfa2dac6ebb445afa1cd832dcfafd8cf009907ffe2c8f32a6e6e68f6f8ee24f8f8eed6aecf2b4826d9ca7b0146ab5c3e0468cd93465a7b4102c3fc8b1c00b54561b078b422c06de9acc86c968d9cbe5206ac9ba0e08b899995f88306cc110937bc75af94cd24cdd252798348b7f28c8007890d45c4aa0e1c352e2a219d6b0002c82eeb2706f63a37587feba6a0ab34e40477000502380c2deda391802db2836f9a2ba46239be2daab6892440004b63700d98e22a6803e6123d6e131a463cf0a141b552626045e35d37a2e5bc4f2950b803eb8113514749979854f1895705aa90f8ab222b010d2ef466dfce6de455409606851b25e1100dea08363eaf37c155f5af2fafbec2fa52b0dcd9d26e04d8ade30f6442f7249620dcc6215dcf10a6d9ac491ee410a9dca05dc7a9e9fe4a47318f0e5423df12b719807196abab3e37ee861751f7392f3840ce7fd85353f3a8543708e60012672b91402e4c0204b73628e1771a4a8ede032d6a621fa039c5e4988a0c6d4844bf775efacfb70085feeb8eab5645aa5f5cd7dfe5a5bbd57ad7494ffb036a08defc8af797c9400fbebc84bf619269aaee66a134830f0938c4f40a6fbd0774faccc3fdc72a295f5f06a1c441f4b4db0e3f997e9fde22a80bb7744a8eb90c296414532d6df84824f801b60b40838630820fe6e1068bea5658514801875e0c3bedae519f7412ac666c7c4d5f8951b55525e7327b806b6e8d3e88cb380b4d03341fc62654d6d60f3697aaa49b5fe3e3df7f086d54f6e79d0fccd7404ac41006e83cc4d9a01e84c9db0df2ef1c593f20e64cf5f9545f5006ea0bfc8f0b51020d633cbfdee4a65f1a1cf8d5e3cad8dcefc75ea7cf8c546bb833efc3341898430e7835cfaf33428952622bfb8b6a02139d76ec4b11c75bf2a9d9cb3bfadbfeaf0d18beca3fad9111e8a53157d920d05f3996c0b5cf5d4b41e9cc11f4edc5143b0690451a6bfaa983bfec2e604cdf8ee1b3916889e348eb7ded95a5d4a969d48303c7fa4643c9b88527555b7653b203058415622b0d585a45e00984cd948f9dc40c01024675e29120a7cda2adfff6771244d6140083d76b266b8d9da4a78526880bd8b2e02dccbe6cd5f769c1c0e3f3e4db53ebccbeb881ac5a15afa6e492b1c20d39cca6e04f09150f2cffb7e632879b3860083ef6fdbb678837a5dd47388fd20eb250904c95a0e52ea7c7253e2ed2bc27a61533743c72343f978d1c348f42790e2faddf6964acf1e1e6e8b8f4274b8e877636483d49ad801ad7eed6a9a9891405e0cc5418493cddf8d07919fc110448dd61b7842ba9bb9b60305d3d142aa8240b9e8132722e926f6d002e79eb63fbbd68ee624d9c5fc516400499eb419ecd200ae6f8f7179433d3444a6c5656bc5ac978d92093d92bcf7d23263414f0294a6507760db07e4e1a7a0f5741c5a3fc75815e5a9d3b28b540cacef7515b8c512ef102ec8361a89b4e53014ef0dcd5f4ca7c51cd334f8856cc3a9d734f521753dd2a0557ac07e080678e2537400d67c61d1f0fc056b37ed8fd40fe64fb4d24d08a8808df316f5d45d6c45b1b7c0e897af619acfab1eb1e2f24fa04c96cca43680b100c5470793570392bd07220e0c79fcf83a0b69c17e6f4314261c76dccabcf7ab1014d96a776b6d93411eeffa82b4a44c49717fb7271b0a12748f8bf634f5be8ae0d9b0dd99ce695dbc4366af0986d12a0ad8efd629c0ca4851f5e054bdd673e210e31efe35636506a55ea2476395a88b8a44d4b4ee2cff71a76d3e295a8fb8ecb0c0d51d7b12b9036cfece89ec5e1adaf5da32e3c5a9f176c9e0e7d2295d905af095bbd4f0745be8e113f9e889f3e7f6dd83dbcfc2c9802817a9081ae23480f4203797e35117e38f789f6684bf24f0044fce1c357bd9a48a9f2189f1147761fd10184d98489b3752c9c754b87aebaa4f90d74dbc8470506d36f4dbcdf8b1686c6096af43a7099f47d58585c711527c41472b71b617ab69616da0b51802b0260410129a09819c7adba2caea93c856641569916654bff27d7cea29900f6276cb84b00bc985625879d686a4e74b612b2711ee37903e40739dd2c818ee56f9f85234d08da790491bbb94895008484824eb28d6d98db9afeca9a711298c49e72e1adc504673a91bdaaae29ae9dee0914de763c4bb98515d34e75e68441117d05535a3e0a85d23b61f2c886001ee4fb1ed079cc014e64950d7255318aa1fc85d4a78959055a7e80747b9c2ac60e1cf6cd77639463a949b109cda36379149b6777074ce10f4e7aa6dd3094477cffcc95e11df3f25fd9ec00af89a878a1d6f560d049fabf00e7ab50838f4d0bba7f76d021b16a1f897752490e5945e41bd748a2ff34b67f0285e33faa5120ffeabb69e584b30c857cf024ad6a6214b361c3132c94e1ce8707056c7eb13ce4ce9241c88f81738d38775a846b5c910e1ef3ccb0c1742a4f4e07b44baab077de377a0ba7a0fd25f5a44809f534d9086c7ae6b8175df74764a300db173c82115cca3f68e1eeca4ee4721fda53583b963a49ce082de78cda39020e33f448b8b5bfae1e8dffc235335e3dbf4c5f6fd6d51065235a86e7f654c7700f06281e2f87bcf94218dbceddbe704537825663f7dbd8cbc2215f05117be12807dc2afd452ba147fae7d265fea4b3d39954b5f3d2627d6a96470e47e3268b2f04a0c7eb05909dd3ef41e863643306682c10ad5c04f7af6d097bda99afd9ca4f0ae322e88cb5fcf73e3b2fc0aafb3d20b0d479dc0700138b1d93587c07ce8a000b60fe0465a999d792750b4c6f2eb782e173b8ad94b45cfdc8f0d9f09ab62e9e0a4b01893156ba67bb00089153289a9b015b2b6bca2cc4e2a047475b8ab59d88032d6acbff2a28f0c1e79f82429462c9404503bafe9478118a11c6dffe11d62b0ba4d7846dc3aa9b8ab6c96a8a10bf56ab68fb28502a6fa14597076265361f41094528d8b06288153cf8a0ad7a480f7142fed424a7a1c720948980ee4e10553904eb151e09515b3287ad6d61decad8198b66e85bb47d08a5da3977c36717e89e08e0fdb015aeb9ec358de6cad1cc9559bc0f399d7a42a1529f6a7affb18d568e0d26b9fbadaa2e3324b973b02e7735e6e19903d1cf5be12bac70c36af58a02e40125116de322656259e1d747103704391333f7440c96c5707fb2500732674a200fc80ae86019e26ccd6ac8e3969f5d87a005077f54a06f78fa5b87d78e9bc1a10dc1af47d2f98fd5fe5cfa1117654fa6eceb69ebf68cd243cc31c5642428244a084d49d48c54fcd80a79082c49f7c18f3b0f55bfb75d306e1c08b4b0c8a9940606a6f2063c5d084e6ee6870ea2a4b20d950f69dce8327507dff63cd770fb0490008228b6243865ede83c609e3f5e378b6f3945464c887f7e13f2e534df963dd90971a3c5c5c12c74dfca1b55c5c971c15a13e94c55d8dbabe9ac34fdd259122806a959de5db3b43abb79039c00e63cd8fd068b90597253be2709937b8c23eeb00d3121b82999c6ba02ada2aa745ce5a330af3a22a4ffaa238feef63a9b5ce0d901cb8e344252a95d4f67f6ca126def178655ac7addb2c49781b2d89b12bc626f0a48899e3268a123cf79df77561ec94220f0c27a770a80fb436a5480fb02095a0398ae5e5b841dda9e643553358243e4b02cd93f8bae7a8520ae5e52f8e3c90a0b9468f6e9f57452c324bd9e1b4e602abe8bc682fff54d6a1aaa0d069f156e42032fcf4753f95e137d0fee65fa4e7aa539a983fff8c199314b632cee81fd7bb50e3337feb8cd36d884ccfe66b140bb7d3481a9741fe633509cc05b8da5c97b350a4d252fb445737c4cfaf0214ea2dcc224ffd12e0631d7ed2cc08386092597bf0a65cfbc691249732fe95548ed68107bf2cfe6296294cb92451b01c016dfa8b10482ba6f72e18476ab8631b52a8d5cb5864e4d2fe43b47e0aa1950c60cc573e308dd0580487c2a09ef5e9d5c6ddeee1264cdf6a128f1b347a338185bded919ce09752b4323c15c9f582222c022907fcf4ab19c1a6b60feb67350ee4ab1ba8cb70b7032c0693c56e97b51d4746fbe0687eb6fea6d2df59f5251044f34fbe45b4d0dc39105be1a56a14db876bd8b0fab2079a4de9f3a8da13cbf47e79456b97549080d573aec171cf6a35789063f3c5a80b4b3180d2cfff2a1586f617a6392846604 +generate_ring_signature 33bcbd4c5fa68af0c24eec449ea51bb72ef7190c0ece9dffef244eb90d6765da 732fdd3197aa6855d284d6bc4749adbb4c265336b62300984ebcf74d03d31ca1 1 878686a68ba5dd5aa696fd1078dd94d627486bd9c11d6dd328ff0a9b6c091f0e 658be715fa02ba1b7f4eafc02f985fe14c9f7d25f6bb4663ff87ebdc2d63eb00 0 98418443782a594503816d6036765602b4d4f5731986c1a549e4514137fd4a06a1a96fd9549cfecab536f4b7be1c39413f627477c2b57d33e2d0909ad190b202 +generate_ring_signature 61c98e5693c58afb5c7311d89c4589e4669b52d8ff4571f293ff1f98af9b6224 68535c66978cc85a04be5b88c000167008d36429547ee67230abc78d01b3a07e 2 244b5e8cfbc8ef701d79624bb3499515be5273e45b73fbcfbde5b238121567b6 04cf46394b267c0bc9a5c9e2e5f88b07d59cd5a9bb056f94b46e816db4789be3 f0c934fded787d254b29eac8eea8e249d6217a82e8e9d5bd7565611394277404 0 4216818cfefd486e5cebf5a885e2593b3ca48db0d680be6e97303b7f711191010d60508349ab2027ed1455403b0e30e988596730e4d5d54800791300bcd96b0b8d0169e73915b440cf6d82db32ae5570fc830611a645d8c754686e4c8c2895077bf0fb0825537a787763f5d026f692fe6d2573d90010295042890d68f76b5008 +generate_ring_signature ccc5dbfe3a1cdf9f9c21948ae48b7cdf305a2054183d05654f6a5b8f1d93b6d0 406a3a1d1b23710ed1555c857e26bb6185a783eef109fbd102728811279bf26f 111 2921b78ba30bd3557e4b772b3d61ea6a16138631c4ba2d8613419171e99e66e3 ad1f075026848ef6bc1680d01e676f8fc292a83df780b49224e9b62c215f6eae f0ce3cecd97138d3819ee595d9c3edebaca5e340afe2f07183373d0dffa0f4be 26eb1a7d2b2c5bb31b7fb377b2523ca36648014dfd16c7f695bed93b718e8733 92523fa28a9a5267ed1801b4d606e0fa5c1b70d54c4634ad0365c6373de04a81 19c3b3475cdfe8c9e801d0be4def7e2d002cd570fb9d9234fca3a0011a8bc5ee 0e9593813368b47bb51b706641310e983b927386a90a00398108e8bb790ce5e1 5d46bdc035314dd0de17318cd46d886dea88c67150375407f34c0039989ecbfb 0e8d745fe8777c695390abcbdc771c9a7038cc327c417f3b754118c65b6d6f99 8b05713d11a953c083ede9778e7e7bbbf4410e35fea2af5b4320b0c7cc4ab789 13761d8cf0742d4b60bbfa4d205c49d4231eabf718ec4234f4036ca168d9d1ec cd2db44254c778fc88a7737e400abcce5d893219d8460c6ab3511b42512657fe b4534bc0527d545be7a0192467837a675c47e94db7ab43ea0773bb968a5740f8 ae5ce2355ada6f7780d89d1f33a249d4dfe7e079b5e102a82314bac3c04c3f6a 3838cd930a369c5458933289ba73002c71134a5e9dbe16c9dca9471987882c26 ff437f8c5906e641d47e53514ff94977417cab286d5f9998c0a7b8177173616d 9abfca55d6be1bc9d37e412d7c35202301060b89e1e700d5514d02d9011aab29 a3232deeb8e763d369ae5c94553aa0e264705dfe24f1fada06a1be1ebe93dfb5 8f51c13bfcf2486557450ea30970171fb0d428c02a823c7f9c704da2402b6594 1791024939f618fe68b0d73e853103b1fcbded7abdb65fa15aef63f55d8b7f44 ebebcd04a35a3eb5c9af95cd67d75289e616092523b8674c659d55209b9b2d61 4702673f7fa85237ae5f20e68b966f4fa9b68c8b6c900316e9f3864a2720b509 bba906384ec35445dd4fdfcd246f38654e8b9d1e3b24911e8c892687d1bff04f 1242ea27621579afd6aae5311988fda8be14600d5fc64352af2ebc4dd383f7d9 7dbe2bf95b8051ea0adaa52744aada889d89e6ad189ea26d8e8c355eb469571a 4cdf70da3f89ee7210375564f8d46aa5fc3a3c47e13866abac7c0d618346a042 dcd45fefa6e3de7ddcd3e105f8888bb6749cb565b2d1fe67bb1b56fef790fc5d 9507267fc1696e5c35cd3718490dc2a853cd2f6a249827f0235d6cb95ecea192 fdd370f6de86d821dd2ea27158eb2ba1a9f6bbe1626485fadd01a80a92a3ded1 575e8265225649995b947201fd76719e51e56f15eee0d5e6462331f69650bc7e c9c8a863860d12415cb601e9d8362990ee855a1e5d1d70cd75e15cc53c07e7e8 dcfe0f0f4119063c29577224bd9a7a1a3800d645e0db7547ea05389f45e73c95 76b4cabbccb35f51dd5f61dc72c717ea336795fc71d7510feba7a84e5beb5fab 0f12bd1eeaa102f5531d9fcb6b79423393fc47bf0e7f753c814f5c273a97ff75 86292224747d0e179c14b7a3e65e4561281b6a827aef6afa2dcb8f8b16571b92 1f9378d5cd626274da52a2b71027b5ee6335871550ffde522ff0a6f49986eaf2 6d5daac0ba917f50cbc0c8502489320d6130cc4a2b332b34556086c5084a5324 9ceb51482de662fe631eb9009212b401fe7138b667b7bd8cf94d9181f955f3ac 958663234c70ff625e10a10779504e267f643aede28861c4a0759eb01fadb1e3 d906f333761bfd3b113903255c1589cafdd20378d85665af168d0aad0367f83a 0635c64549ffedc46dab199ebf89fcc8ac599c8d89970f7133ab5e235e19f832 decccd21d763536ae6d62e9c56019358437f7176b0c6620b51bf59c5f2b0a518 62bfeccab34d00e92ccf718f671b735d07fc475bc5e4fd783e487666b0fff721 adaa55bfbbc3f50b640ccaec02646f4b152fef46d323065efda9bdadaef91ba8 82bfa52412799a07d83541bf6a3de59bc0af127e4310f09fea4d1971af8c6aa5 4c796345e19c94182721175a198a8ad535ec0f547558c7f07cbc3127a1ba0d87 ac9bc2d8ef7f43f80ac9d87142545ec4d14e54f64d4af3aae305bb5407a819fd 934000e2895878f33474fb25b205d5064c181277719336e36e688133a93bfda2 1b3ca7399c0b5508f80a645e083627435056ace47a15f8fe9f9fda75a0b17baa 9e360d75e54b81e3434caf08a8341bfd70abec216f1760388e7d68aebd87e6db ba19f181e552de8ee972884cf82d87abf397949851f9bf867a7bd57656fb8d80 a3d028b2702f532fb6dd99154d310afe882a709f8d0f194a3352f800b855c91d 6c477cc3e4587c389469d20bd69c196613bd50208f91324404ad58201f7549b2 a296d83f65b17869870485296b1df3bb2245aa4245abfad85e826dbd93ca4e21 23bea6d1f3a996575696f69c7b4f4e4b276707eed13cd00cbcc97bcd807b9bf9 5273d520380cd20c951e725147ee7aa942b743b8873b0ad756bdf30851dc2d98 85aca67f1e96a7e3fcf7ea9a64c5eb63dfddf35b692f631f89d179d5d3ecfcbe 84240ec649ba87138abdd7d1524c2b580c95d601395ecfa75ddcefb52fba547f d11fb311986843cef697a42c1db914979eccde0dae94d1fe7ebee7d4974be857 0af06bab640a620fbf4cc5c3a777e209c5421641b8ab610b3c5a2a1a47ae2a0e ba30f319070ffb436f5a5853d00f8013241fb6a6bc472d142f303623d33ad465 34132768b3b2dfb6d97c8eccffa9e4009230eedb6e84ddfed5dafcac3763adc3 c5903c815b8bd030162bbdae429032faca5d73777ce3a8248dd717578f0b8541 adc10a53868cc31d0d81395ff25be93e04212b1f45c00ab5f6eebc4c9b28aaad 1b841fd24b0e7929dabc30e700c6d312a8e3d976c95155a3bb3102fd9e0227b0 56f8165751e6767f607821a630ab9d2132661b4ac81e2f693e5c4f60114ffec2 6865e341bb94717a4de51578360b59cbb07a1660f70b0048d9475d28d7adbe3c 3dca83f1651d518dc458d331c9b9e7c2791ee1019cdf392cd722214e169ff2d3 72099a12ac2a7852c982c2345a5b13d7ee8fd6cfcecdf989430e365dbcd758cc 400f30e5179063981ae05f55129898e12a61dfd6379670fba47f4af1f1abd042 771d8631769dd24075741231cfda6e1bf41d075c4c60af3521546b2f6f2f7da9 1a4ac92b9c6b0ceca0a0914c21934774314b7610eb65d81639971606e2109a13 c6555b566f15c912b0fe560cfa4b5df5dea4e44624b49aa8a6209f9131109e25 944e66c093a3b22b7b64434839dffdfda5b8e0ddb6e93b3fb4e6c0d64ec80ccf 5682de8256dc5f421323d2e18e4fe8e86810eaa87c6d58535dd2c8d29d27d6f2 ac52d43a2c0fe2b23e73c67f6b0db159498140621b13b4bf2fa6311de6cfee8c 24db498c9238003c869f46647b4ec96fab351438cee5fe815ce700f5a83aba83 75ba2f7f38f6bbd6f58b59357fb99a74b46cb4252758fdd4e669d327a28fc693 74d45357edbaedf1f26950c22d83506ab3477bc671e685583418c81aa4c11f4f 61c814f9c7d4066bf95ecfc56a6b60d95eb63b0cdd4c0a45ff4d4f83367aff38 b58e16527d8d0435434e83e64c6ef570cf3717f79f8bb142a3510dce185286cc fb771fda4468b3ea8ee77c23ffa586486cbccd347fcac9fb97960262fc4ea76a a5147a14b7ef157b8288f781275b06f0b785c0888fab930c6a78d94ac818ff89 34557754636e143800091dd6e2a233b47f140010f36eb4ce27b48855b74076ba f95443b3d18f130e37fd03856ec8c6e38ac04dc9d528220481cbb49ed27a9f03 3a6d4cd695f507a0a8a404c02d1e0bd2ac93f4ef2e2056da9ef7a73e70d82f7e 5420f0d5dc5f296057a98a879fbc0d64605806aaad6b574da9a6e2ce9cab60b7 71b23bafb900f95b9d8d0deb139f0cb966ccc1078542b32dceef6849de962e8c 2255481001bf79311d76a4989dd98ff8c7f2660ab70f273b52024560d7d9fd66 2d291106b2157d69bc98c89e4034cfb9988d54b69a413a543074613cb1cf7923 3e38943714f3d3db34f5c12f375e73e99e6947fa661e86065c4041d15408eff8 7c79bb5943468383d769a23b260a0179587e9fbf3224349369bce1e5a49e4869 fe4fbdee077a24b3ac3fabed5c8708f4a5d9f844a8741cd6b2f539932d1a34ff b3fbe8f600c1f5a192bea732df2068edf5ffd6d766b2eba55ab7f6e8a8e4de8e 242b451f824ac319d890214a53a0c84ac7b2555ae80a02cb758343a607bfae93 2dcee51f5cf0cdcae0fca85c195a0f1ff1b3d4e468c9bf8d5dd6979b46bfac09 e35f7bf7fbeb114a5d73bc5450a2e24d171d947268a41c4da4ef322f387a20e2 5247a3383b66dbecec8e74af6fb621f5ae3fd77554c3c3f34f0de68a5802706f d727e6a804a5321ceca5df85777121c501e00cfc1beea4455cf94c68ca3beb8b 64a875b077447051c23ede119427c11392bc495a401d0631da8eb3ddc6af5c79 a1f1595cedc5db42062066166a58c45cf7065af7e52d54c26e16fd98c6defa16 91410d274f804c5ad21393f0f1758a43d0003d604e34fcc9ffd545a3d39b35b7 61ae9820c5041ff102e5232cd43fba22d68bdb5bfee2d997ed97f59edfefee53 d32a713c0ae6079b57526da8b355edd35cedd2ea55b9192e6e2bb97f2fe10119 9057bacde18dd4271192956ae16433cffdb67580478f52fb9e4145658f1fca55 8bae0275e1a2f5b71e2c2beb809e5a98d02b22abb8ade1c5356aeaf8587926bb cbb581f34ad405175e6b591d7f0d68272140a303a4044ad386bcd12489cead56 477283eb5796ec76bbdff973d760fb3a25f5a776d2cbb9f9d3a6e2391064dfb2 2096412af720af30473b8db41ee7c88ae13c2954d7078d28d284aa5bc76ae1f5 2086b5fff76bbc94f0df920c81d101e50708d68f0b18f3b2214c84b137126a8d 68b883a806d347d1ab2efb8d975c12725a68dbd162756d50454408fa12390cbc 427a77fa841f3dea30b971fdd3e26d79a6b1378674651569ce263b68e3654d05 27 64d1bd8ae10180168d64d8cfad5214418693ca10a40df601d7e952b1d46ceb083a09586ffe05b46449160e28a624b2dc797bb47a842d3565e5ad0ece0ce2690ede7ab2137bc02b59a84724e65fba52b58df548d9692c94655ce8b7aaa25a690a81aaf24bc11b3c68797e6531b8904e8cfb7a44f8487e4341c468f5322e438406e9b1eb76cd9f13c19b433342aea4b86129644e7710b4d3fcc19597979fba970f73c507869135a04b033909dcd70d1aac810931b1ee217e6193f1cc1f37896b03f27f1b6c1b40d2850ba70dd0e076ddc9d432d0d97241142b58575bcf5b55bd026a8d6ece53181a1507db92b858ffc1c04f90206e6cdeda67cca76c56b87c3f0ebad09b5994aec7550dad847dfe7424ee56be526a416b9d9584c0f5c5aff0f205f00a4bc23d5953c56373ddcb1b3ea1e2ac823486855bf51be4d8cd749014f40b4c9de33012ea589c6b0ef91a467abadda3d730286506c5d3561933652a61c804f211455aa4a7513f5a23d6f8a5df1833ce4257536711e2a7d5468269d2608c034b06cb5204f87340b6d7aff69d6eb005a09b596d3603e56e8756c736d084dc0e64dff02b8ff16329362c903f418f9f9314641a59ae97e81f9182f03abc41ce0b5db99eaa901a5a04cc216efbdca56844c7ad930966ff80e57962018f358ee8026c307a61725f67f0204ffdab2acb34d7c136d5f53cda20219b9b1b3ef838630f6ad77d15c509c8895a8f4a409ccc21874d998920cb6e48b57d3a3ef208c3500fc5a915da32251801483995f7d8a8ad39afee832afbf660feec4e5dde80540e05b707beaf5d649de8519df9d8194373236e7207785abcfba18cd8483686768202dd5d1f18f514d4ec8d5da347463fca3e712b6c166cb2cfe93f865deafb1ea405848cf98f22f14335529cb1ae5fc43e85137f92b9d151a8954a3f504133dd01097e9c8f2437c501a9a155926225cde9ee3b5943275ad8e3ab97401d967271de0a7c5881de2c8fe8fac5a89d1188291ccc98c24a68abe93ad6ae8a06b2d29c1005028a340bf2bf53798163010d20a84954ca8ae2d740cab432fb3d17a536e17801cdb744545814b97acd0842dcfa517a8cb73f0eff2b2b4ca6cc6951e810c8f5068dc6dd8dfd6b361fec24d99b8113ee8aaebd39ab36e201c933e45a1a83f6570896f30e71a0e6cc433a422c6734fbf090e178dffe67ff028c09e786a5f82b8b08b2a3ecf1065b8aa6b621b0b1285b716cdd8205728fabc26f389f37323aa39707073c7c1bb8b18a655c209ac8902f8e5e6154d57c0087f896bd11d2cecddf860fbcf0dfd485af263c0da6d8239af70d8e254d5f9d1c9760fd53939891c1f20e039b073b79d39707bbcb2d350d551b27d64b331770e6af8b91c8178168bd1bc10db48c661458f4b274eb7a275bc21d327eb7669c8df7901249b088133fc6c6200f5c4960708ecccaffebe4483259bf669da079d9fc2d82bec9db4c518a4113b70d6a2d7211f2d264064421d54a402023f70485e5f0ee2ce0d41190e0a041f86008096b0d4d212cb1dbdd66b04751ce6bf8e6b43656523197784abc39c4503d600dcbf44aa810617405e214d1190f77334f2a3e3adeecb59409dd2d588f7e5d320668e55a7f595e71678d0fbf0d3b2535a4aaac3af2553f866b572116003c8a7a0a2bd0e5f1e0f3e36e749e2ac1d5c0127c5355a7d61e34aa76a07370358ea997066f31106fe2c73d2c966896d819330f9fcd2ba14641a1b3d679782224ace51f0d7fea6bef41edaf29fc5af8035f427c00a64cc2a705acd5f9d9b64771c7805b0d8f9fc456ea5c91ccf3c20fb901939a53badd780d4261eec5de7bf8a8cfabac0de00085ae134d46f176afa458a4b42cda58435fde587a675d59e499d58368a8072f5488bae58a357b193b1112b6841bec5d9e9d17aea4afab799a820670aa930d29c69c83c332a403622e6cdb855ff57ad3c0189d76ee017fef6a45ab884c510e14abf06a1dafa299f293a05f66d06ede7b7c71bd4845edf55f0316aa2ce6e909df19ac96e071c85e029b8c9dc64822d141fe3d7a63f22448c6d9f97e21d70203106bde1fcc26a5403d7a1c42e3589e28b503f13fe4c828f4bdea405b37ce7c0293dcc9f934edc67b69ade5757b26c5a660bcfba263d53983a8c229a3a4bc1901cebfb65667a8cab32e86b079e750db5faf37f40d8506610866902d545b1bf4013f88936e69de6f1786a9e23455e6a4f9cc4d49b4310f876f22ba6714a61f7f06ab8ac4c222eb55381fd2eb44d38241aa29c42698911eb227b1f7bc8d061e55001651375eba227580f24cd8cae5984bb4bb09ee57f4e8c3f3c98d9b57f68e800ad07e3fcbf7d30c27f1cf3c4c47f87145b70a634f513b4aa3dbe7b75d80770e03f263abc6449a1e4ece70ffd79bad231dc7a0979f8b5654c4952bced59024d600a8b195b7e95052686a1bc3ffbf626035480252cc1924f71057610c1ab50495029a35f4380f27fe81378ff73e2d59f3ad0672b7d8e5091c78d85ace464aeccd01a34da56533dfe6d91719131e6a098d4c854e2be30d637891f3eefcce020a7908797bfa48d313842c20c4d51e8d7a35264b9ff7dcefcc1f87fcba5f7066437602b4778a70de196233e5b49030258ddc7b128cb843ed6bae6f2e0b6430d169100e9c5180102471b3f5e6804d8ccc14b8d4dcbc72832ea6ecfd7194a427a1707b03339ae7bb7a52805f721a512db6e257c48626262ac9ab7434d36d1e0de6d8ef0a13c87ce39b299e73bda10dc388cb10feb0e79516db6e3640a1d82917639d6b001fa4cb430b74602b0167812108cabbb9036b9160d2979f1d18caa2aa4ccd750b4286783f67d33100f0dca786181410b66fc8db3b9dc1356be6f8fd00adde80068ce364351e316e154a6d87cbfd0c9fc781cf0f6c8f98b7f7284577512abbdd0898ce4d23351ac5f1e812ff7b9c092bfaf5f099c88088873e1542f5c556dd8e0adb066f1340b301547349c04c95e320d9802e27597ad1fd449d7bb32159453d0c12f75e3e42803fbe4f2985444511a292b78e95df63de4c68a1c6fce18c827805614062805061cc1710d74569a66c31a9c76d4fe0908d206686b67caab0f469096a701bf228be9669fb31e22fdd9011472d23b23b7563a0c09ab45b4d396cd8093b7af9c52d5d254ad563c49b18dca0ccc9481f39ded5b726c7d32837a9fb3c0900853277728d2936e4d56b6b105e76b03a14b24b2a0eb73329b8b9dd306ee604de09549b6ed481df03345d8eb2ceba043bb262d42231cb82950edcaf47067608a583e89fb43afcdd5e5987dfccb123c297329a19aff3335a67089e7d2de322086f9e14e74198106ca353e31fa3426369f415a2bacf3160ea4e40aa3605e3660bdd62726dbd0706112964a0a28ceb7c11c26a0d0fe05c7090e600f9f801455d0d694fad13006c038eb6b63beafb831e1016c0a0791ad13ed4d17f0a3914bcba0da6320dc60715ecb36a910f0efdf446e01c96c0a9eba6569186263085b6777d09f45cd71fd6eeb60349298f944f6d4016cc72a25c5c071ebb8965946733dea30b870a4804a9ec89c052e8c42d168bf6d74ca8ed846240a904e4260db89d12a500a56cee04ab6c5b5c467220325189b29bd36d544a1d400d41d3b989fff7be38072f479c12f3da5992a926b36f30cea493d9dbd80b653a0915a721c5be1b7db605b7181d4ff939b629488b582cbfa8b55701b955fe7650ce9bf2907c9d87f62300811ee6dbe80a1883e316de9cc92d932d8a4f640aedf587f842d21d6105f7e50052f1b17b79af70064bde9a5657483c8ed1e175de4cd9d54759ce648e7b88d80250986e9dac1372b1571a4c18b0eab28f7f73246daf72468d4e8e34af03934f06eff2618127417c7254efdaf71c2e92ef962fe47e9bde2fb8bab49679681daf0c8eef29b1b1b08181631ee9357281cd5e58a771671e2006fa5389c1190d58c600f98b78cd75d697f132f4240009ccdb0fb39df1239cad5d84fe43272220d0eb01c8c8e989e12b766e784d3fb263b6be2e984e98ad1e4595f08c1652a38763b30e8e23d3092ff96cf7c40476684dd2193139600d0c8731528a0e9c536a8d26a10be91dc5671f96518896354360da84916eb057c9897347d40aa555c6921116e009016af319005cdaa2029196e31d59e782b62ac252fdaee47cbf0b2db408d673051f8db6fd7d6f2198d5c970b2cb39cbfe3717c55eee111f636d39dc1dd6691b0ba24d983c71f4bd1050b05b04509191c804a8729ad496f603532787dbf3672207526a28869130dd7b6d56accd6167c3563e8f1a02c81111ad152fe09db9d5960ce2a6c90bc560a43196f2399fe935c1ae69e0c90b9d72d6338d5db864ed2ef406f77030daa83dd3f906a9d8cb39d74874d14b022b8d96213b6fc29c06e8996409be201c650d2d65cad9a1e0a70ec11c480f15dc4ebdc69301184154867221c1081f41b2f5e34b7db14463af3c3b635e11eaea1cedca5bf0b2a689a8b0f127ad0c0b6bad404f396161b1510045a6767fa939f33752bdc619bdde7fecc4b76b6607166c34f75ed8d3e9b329ecb231ebb036bc4877e92c8a9a62d1b931768d7db703c4d92e4fdbae790fd5166841925d7e4c06f799698fda93f013a755f7c4c0990d55b4c37d89efe352da93cb83fbd039abc3b6ccc79db99fc5294b5f496df6b40eb83a720f00a0abc43ec32d9ba4c6d12d1f3686b454fa1fdb45bffb332f0c790e32cfb2ec8cec7f124a3b882b086dc571af66d0e766cd1c900d0b9b8dab5c000bd71650bbe3eeac4fb2706d3585aef87eb210b5a888145dedea45cc6ab71ed607443a6a21e1798450b6aadb733dd23bfea8ccf953acc30e16c5a5601cefbec008c6d2f2212879e706274902464fcd25ba7558f3eae26b94864855e53a031c540021391dafbd46b469485d397f4f6bdf7f8f9f217ed09f79245fd57af741cee90f6141935381ce7d6b92c50aab7ebfe848bbd275f17a16876998575487129eb807f51882700b56f162cb94ca3ab246dad56be04d6ff05c4d492922976be28bf30fc4b6eb7371e707c622fbe5820bfa4855cd1901a1847720a6cebbc8a0da338b08db493f6173432cc1adff4d55a7ca09f9be4db6f10b8397887d408e9e6eaa2d02435d33e0d33041e87988f06eb11523afa6222d8c559defdfcdd1cf9a3658340b3261abc4d08d803e254ac31e1cc52dac9570b2f78156bcd8a2229b8881ae5607921d704baf33e124e9da1e82b3debfbc92ffcd91b68a433aa9782a0f5a2c55033fdf8376d957fd308e066ff49461bbe78818b0ca22a89a1c7634206f80a47b05dc0c8f97374a31d3716a76ac6f0ec0a433acf4c1768421338c0f9b86977eb80d7a1fa3c8e5d4588b30d020c78f357b14050adf30eca1b62fc684e50ab0fef906bd3c4aea4caf4bdf8a0aa6ac8ab8637da6fd58bc58def2213f223ebbef60ed00cbb61af502d373c96313cd71dff0c25f046025e2322bb246b07298d640946d03477dad14ac010b83572a1ec3c9fda5b60e8badf4c60ed335edf0669f0ee4e20d1c4c3fded92ca9e97b63ed24a61fc4485d41f99503ccc9a404a9168e4046800aca24ed5c6b2dc4ed2b29e826e66b6f209d26f78d1c9d19a6053df5c4da314b017e084041132bc96b582eb10f4a8c8f51153e74fa254e8ecea59e57d354e85009c10a4c0ee75b67d256e6ed681a5419f0887f2819ddd6dcd1cbc6416a0149dd0bff4db9808c28451662e7f24f76f87ea514e90879e6ed1037bbaf87b285542c038d19079df94691856aae816d71a22c406176f66ed2e7a8a221571196ab0820047e42b5212d964876db1b9856d1e594e0c081d01934a37bc7b5ab5f999bd4a901079811146918eb45c5420dec19b201fcee8af4686d6a5a67ef0539117632ed07b4e9444fbe3700f5223932afef7f40771003c23976a1766c86a5e9531f249505e41e033cfe2369b04f86a4b63218ea396ed574393f76c0a6bd2a27876fe38e054f78d3fabef5fd3f1dd07b47d332c3521b891eb6f11895bdc89d10908a19ff0bf59166d2a9ef7157d002ddece97d2763a2894e27a5976f4b6c7db82fcdabca0fa2418ff53207671ef2b578a1db6db2ce3d6052ab898d858b96f2211086ca7e085a0e36d46a71831213482f8fc37d06cd6a28093f17f30502c9733c510b56670af649be55ba2dd11a8f411cd19c26814952c864ead414f349d5b65595f8c2e603f1bd02c9623a13b1ed294f8c91bc97df2649ae0931da9544b0948245e1d96508d9abc0dc043514a001f1b924300c19455b047d060864cc490d6e93e1ceb75e0d8ebcceb43d10d801561f8ea90f2392b2033cbd75a1fbd22336013f0465ebb906e59b7a98b8b61f14b82aea2cf6f91d6018f13cc2155fb8ccbc90ffe3cea927063f5e461fccd62400c5614874166bba9d3fdef284a7d4f2bad526723fa8c05c0d512a00105e27d32d61012a8b7ee4111a3b74d9a16573711e0f2ccc646dff380aef427722cea046e514b40d74436c05f191a121ed300bf29c6672e873bd4ef90b9c971385ba0d84600d9459a93d472cf9381ff8583c93d4625855cb4f112f0f0921d7585f1db20d2bf7e999d42dbf25e4e2200c7a1d1205543ee8bd3983446d07ae943a4ca1b663c9deefb77507ebd705730d32db113808e9cbaf9aa414fd700af4e54d6ac84981f816b6255e8292884d2095d0fe283fbac5283c211f107ce70fbd12a1b63f3b249ca2c9b0573f2e750865fce07f14f65b8e6bd33df9aa0a6b05304fe0a3d28ad6f14e5797ba91b9da7eb957f48dd4a51e3e163522bfb3cbab0c77526d63b91fb6b1061c7ab8016e2f77b214583f06d2f5de1404f4d798945801c55a13de477bbe1c15ae0e5eba7c36f2d8f78cedf96d48e2e9f7bb5ebcded30ccf2e7e35de62e5d658d48334750f53714695b61ce176c7f7a67b9b3fa86d750591c0421998c69ce9237ccf726488f9f1734da635493b472d2268363b44eb3304f91fd50cdb687a9f31a5f57418c84e40a9748d6f0234fc74f4faec80339cde037ed2bc4953fbd29a1ecfc9a60e25f1d218dafcee9b7753f5dd6fe0f231d0930ea384b470b0473139dec1ab627305d7bed373f94ec58946eabc9135fc12f8c70feb6df221ddfc743e4db05b60eb484da13cb74f0e8e8b1499a40861c16391830a52c7918a777c8362d2fc046ea88ab07a39e34bc8d3045f5594e541f64b52a301450896e7358311c635039cbaae02a6ec528ffb93c41ef228641d70c38337c409090beafbedde8e79bc04b67b91818125ca7b5e0065695d2b247b781aafd15e07f3b227baed57c9452e1cd9dddab46d8a0bf9811a172c4fee936307b3b340f009827297bfb4607ca47515e00d876c7e7bfe3da156011ded770bdd718ed53cf009b3f1461eafb79063088481fdd25db46ebf1689b3015f4b5bf2b4d62d27ef9b0ea993abbcb9c5abbc29f3c682862c7a86970756a058d56110c2cff31342739407cb03dd8cecfabbf23122487b6cff7baff24de7e6603992033877645364cf82034a03e86a9fad14c214fc747212449bec983bb55f7fd28dabb7fb7cbd380ea402104080b3442800a173f762f5bdcd092ad7f121ef1cf5e6c67d9bb5d214f4b808230e9c141c9303ad4ee1ca832472b0780ab425eb6eccb723d6e331e031926c0138e922c74b4f9f0cdd2ef7dd2bb997c2c0e6636350eea7aa021675694a4e3a0f5c6115fab39077cfb2fa06520886a05ce151fa9220fd9ef6562dcd8e5f9db908f41a350172ac6c8f0f52873a67f983e5e5f52d8c07d3e5f329681e36b1190701b217db4e14d0cffae5b8b3967f80dc13707f7665167b93e58f9aaa2c6e485a09a29bf525ffa72fb05b847792a95b03f704897e45ae76849292657641af827205cd8a6bb49a064b14a592efbabe073fe8da513396ef58497fde0a491446f4740331781a6df64bd145486ef305093324202516a0eb08ce7b895b7ec7162b25ab0e24215d6c6c7d2445ba8052280953b86a288ca16c95531e4f6e6e5a569ad80901b61de428146c311e16c566de1202536ffb30b4ac36f58065406d3db3a59e9a03d6ee9835109ef0fe7987845dd3e5ac50d1f673d203a4f69a3f15419d78a43809fc88feb21508e12b54df3fcf9f0dcd3ad180198ffc68e87896571bbf5cd2730917c7c3a8478a40ae6d98b0312b185d16b948504fa463bd312a5fb29a4c5fa406d4aad66171b71c116efda93c43e2c345a34463f581f8e85877b3168c7a17470cf7b5ebbc960eff67875b322b9e3f0046134478d0fd76308a60e4423875db440e01539c5a71db4ab4dbc1f1219b92cffe5adf5678dd4598c4574fd791275c110d26e993f75c8bef05e71e33314cad4c037b788b45c3da12574ecd66386a341d08714265ac4cd9ab644d884d76cc0bef7d904f5a58c46792dafd5cc22a9c8a9e000a501d4ca04ee0b82a59d750346c8f3bc34a7138d1f9603e30ecc830736d9b08d0cd2a3066995a912a6738e4d1ce09653d6672194ebfa50a93cf7a1d5891d504d31734d114b6463a61147d6e780d60b05ad17231dc475130c7929e5dd4366d0f5217add55bcc70210a8b816dd890a824ffe0ca5f4284a76b9ea5642a4e39e30a8f1602e638402c6929f9dfb4c5d5586a911246b7312452d074b3c59a02634a063a3c7eed78c6c349dfbc0417473be8cb95a11976f358015eef5a1e036b05430ec38972696115944e3d5c5b31329ece434d6d443be88a9fac015291e84692260a9ebd33c9e183100dadca7b76451c31d4286d827aa0be4abbd5dfc72f812fe80f6b886d9d1ed3e1d231f5ad743a10c5d5c2ba48b142ea885d1629e4edf2c94f0878a55b28d7268727a7598db6d3184f4584480018715aaf39cc8c19c7f393f90a5a6487efff93589b4b36019aced42bda34b0a5f109ad8c9a6fb17201c257090bede0ba9fca628369f712eb3e80d1132c39b3e854e5783f80699224a7c2dec009922df7ed1c9a332988e82b2d0dad551bd401d6905810da694e496ce90a41f6074fd5d05eef05ae6938dbf5b6b722ba07ade6f39c915e38a4e012f43654c19d08e5211fc6d65030dfb21ff0f9e8c95bb689a7a601d2a63306588d31b5e0ad7a01f0a05bacd19fb77dfe57a9241cccb784cb42f1861ca6e7fecf6b9767a812fd08750dc52b9c5f822067860dcb756702ce86e0ac1758e1cf2e5e5117544d8d1308efa70a858bbe8308f42f8a585e333fa25a70971de1752b235b52231667763b0dd9229e538abe0bf30d7cf05cf0d991454ef8461321209f1c3e5c462f352f2e0712e3e609dd7359a7a91b0aee20db249e851a0f475cda61daef225c3a56e1c50e317c82843320359fb85fe525dc936efc92b3af1d02a0298a42f5d2da20219b038ada0d7ea9808942b4e24d14290beb081283d3d46abc19fd6d455a623cc06b09c8c6ebff007c4dc05b363fbe8709e99b352c582fdf3cb4c9063cb95d3a8b830d24586a542218dfd3218ec750d7e5d233bd231271ca805db28da94b55752662008accf21f16dd7a29fb4c93d510cf33d424b4da8852761f4df5be34b54f6a6802c9792a474d8ed94f315117adb8db3de00b852f158492edaa1bf1a9345ce64d06954d455fe19f5736b7fcadfc1b8f44060356e97f3c043cd9053a650db3600e0274667f9b3b097c8a0070f4cdbff3b7a0cc413a6bf6083530674024289366ea08702e6e2c54decc8c7ff405955cb15fda9628751b81a3e47109b3af13a7126e098dd905b97657689eea887a041a51815abeb2d8a95a655c80d358d10c3efa83011b39c7d8dd6188d040b5b1c507f76f6f4297cbcecb291282a13a72890ec0d60518a9149904268ae6d5b9377405b9d65bec14db2827422d939cacaf30e7015600931d98dfe59a4b676b0a783c1a71e64c5ca7d9f1efc3e4ef3e67f5ba046feb09b017327d692d3519a24464b2faf8854909324b129bf46c2726a12f686e3d2107a6c45522347d38f960a1260147d6bc3c2ce6a7d43b2b81584d091943358e2802 +generate_ring_signature 15e1e8785c6672c8c9bd42e8b0b9dfa73ed16b7312e067bb23380a5662884e13 df79782b5900dfe6d529fffee15fbbc1768ed0a58b535232124ffcc89073fb56 1 5f5eedb18339d1ea19675e00cf95acdcfbfb71c56a86c51c473752b1a6eddf22 d2494b222ddf6a368339062b29abe06a0fffd651ca408844a13e8e9c1483c501 0 2a7dd1622d0bce1666b29a395cfe42507be6ab7f25847a913140413a1d3a1203ceec6f50ba962d4ba137eac5ddf398b393ead9efbbfcdaf6764cf0546c9e1308 +generate_ring_signature ca505427f45e3f3327ca3206a0b5da1292e0cd7361f6a625dd9345ea0d03da47 9fd40e7e4bc7f5c892c8000666b514a73ee6603def5babca6b51285c40f27309 2 839e8769b9dd788743f455e74f7253e687cca012d0ddad7cca0e4767e4bc79a5 72e824806950403597e8dd402e2913d458aa49d39982318165e32e5de46044ae 76e8413823935c97bcb8c388d61482247026874a53b8d31daa616b6f244d3c0b 1 663286613741470885912d1502946fbf9f44fef9fe2f9a983f36cfd16f7b360d28754ba2debba5ef534a566a34373e7830c5c23ec7f63bef8172b0e9d6ac8b0a07844b738e0f4d30ebd47768aa19e127f8691f939974b2de820797797658610fa1f5de8c3a8f59c4e9f84ad80ea86e9a6415f601edf6df22b0d73afe3f540709 +generate_ring_signature 640933f68d149a459fd5d65fa800ed1bc733ccbecf94b17a8a6678dc6e90e3d0 7b3e6f1907ad536d7bb54b41827c3d9483da8e87b5041faf6cc7fd235237f3a7 199 e1fd6f2f9381f01f62f9027760c178dd9f5716898395fa150bd04f9c1bcd7257 0c32219292a9a10f7902af43cb0b0ac820d2618dd2efd266e36d6f7bf375b546 44bb2452da68ccbad071ceddc6bfaa5a7a0471e67235b5db25ae0c401c848ba7 ef310ce28bfbb3868d079d856042448a1890589fd919796efcf0958a6fcdd49a 6138d4ccf0a22b094bf5f6f4bb25431c73194d4cd455225e9f90e890ecc258f8 6cd95891a2d29e19eb1f2368ca8c5bb0e17765269ebe249c2c9d6e4cfec2e701 518bad14481f59ca818908ca5290b892474cb9da9ae78dcb4684df6758a12fe6 486ef59a6090636d737f22e6f3c6786d600d7dd50084fd5a6802f4d1c14aa8fd 7b7ba8bfca6105c550f82244e8dc88a3d14f2573721cbca36bd2abeb5dda3361 6a8ab23a0f9a41e4f83b815e83295d23f704b0a46bd7787e017fb003111952c6 6e629c6afebae95df966e02ff8ca6589152dc2f1a8d79ea4ec806578a861bfe7 bc0df98eab5b4834f520506a48092bccb07099a8a57ab0d05d73a1b644ce5a9c 1bf49181176e9be00603b8697bd817908ffcaa7f5b6d3483e4a20f86a14ab144 2ee400bd275960a00316ecc4f4d62b0c07c77b5b39c9ba35aa21183e01ce7576 643c7057cf4f13239a05fb4daa429764b6c4812e6b31ff31990182c486537fa8 72c592d097ea1d533270ab38045068d9f8d3de716633a16cedbfa5de6ef1d94e 397c51ac125fa63b5872e6ab21da9a04edb4769975f0eb50fec6022b4163ad79 0ef1c332ec45f12caf7434918b5df896d7ff57dd0c5bfd517a99d1e45279dbd7 b85a252d88a0f3c910836ebbc1917a5fff542a8b6e193fb17de53aa7806a9df2 faa62a1b7452db23c98f0e36f6a9978640636d2a9a0f16713e5f10c09fe3e508 328f24953c88403511a3544cda71c6011fe7dfb9d56d3f24f0ff21368eac61b6 df1d055e26e6a5ef462e906fc0deb64d8b29598bc9bd85b5458082089bc96ddd 6c212c22396b7d5581bd5fb81bbb666ce3a184aec90d58d5e44ba1de5cde5bdb 4ce80f8e5c3097fd18e3bdaf8ba2c9319d2c038fe2133cb567699bf8ba797e32 da98eb0d9f2c7b7f966f5160a318169c9ac34176486af194cfbcb3d72860fde7 4660b2e8c795df61adb43ae7c80fd13d4f3291a55af278dbd315450a0c729656 b2847cd4e5196c29d705c1117de6dd6e517140346ec2331f88fff66555b453f8 74ae53ec473006db85d690d8241a46b390c62b66038ab2cc19fbb9557ac410f7 60b875aa3122e4bf0b8404ea36c488f0dda20ff1b4a4f3a23d13b03e1224456c 781f2e0c5693d7ffe37ea904f72274a969f3ca5362dff6587bd7731e3c8af2a1 2eedc4786cced370cc96010b5be504e587357a9fec120022c6f417874e885aab 57f3046490762d405a2cf33b0e42cc077f962b4762cad12d73acfc7812e53752 95d804b52fdee15815250d2de834ef304b6097fc5492370c2e2377290094ec84 91e241d7a90145bf0320818a46cee8638b8000afcf8a79c4573b9d63f1aa75be e5c1a8968de7e4e022a29419db34f969f0a32cad3262f609633f6fb7078f3836 da909ec5404bc643cdf16d774275fecf796a3f114c333dfe55b5b5f3cb605571 3977d5e358dffea1fb052a1cc7aea970ca6f1d5caba77633c8a019c099fd5c5a f4fc33716b9d5a9aaec8707fdc0ce658cd2f45b389c8d0e5cfe68bd986999389 816a38588fb04069185b53c8e7a152992387822555e6a42678a3aa09ed256b2f 73c235791b37af8bc5d20251695df714e2001301c2c42e6f4f0f6933b68b0b3c 37a1f5ffb8877b39e7f07c497b079918e528943284a86ce6ae4bbf92111c63ab 81127e3f9e51799349ca316fbbfc66b9615b81e34c1da957a2523cbede998e5f d022b7db7aab2fa830ca163e9db126143615a14d00784d029c1ee583b95d4ffa 518e4d4eb6c823e6ab52675ec57090510eb1cc5171e21ad531e97c1ebd9c84f4 bf18ff3b5f363af34722d8703b4ab8f6c20a5a5c00e70b29b4a0e2011248d830 09dd17995fba7f2bfcaa29dfefc5670acb38139f95c015604150699ede968e11 a10518e114803f176d8cac931c689a5b9aed0719fed4f3cf724121f2396e2bf2 840cb0975d20cf39161e599dffafd50389930787e3c9f9d5422818074490d30c e079333d9d7a6e99f86881d2383aa810fd16b12bea9762f98a3420f14fdddcc2 2d966bd97f8f3942e1943ece7b23d8125c4ba8899ce0f9f46784a2d1b38e4d7c d65bafd2b7fa8030414db8d167121da88d4e623e43aaf7aafed24ee837069785 672b6a10e067b982811c24a5e83cc2d70e92d45c2de5b499f906a8a9d695bb6d 508d519efbc059adc7eefe047c8eda930330c27d83fad61c2a41b502f07d4e64 239b57469cf421c31e765b9891a5d1a42251bc9e62c5dd55be426c500f5d7e41 bdf54bdc32858ebd44760b9afb27ec803fc6ccce43f5cb72290456c31a120312 4b42e3bf898e45da9dc4c59408e1f5aaf40bf11b8a4d09ccc66b4d626784fa04 0ac47f6b42bda3688fb69a48aa126d607e26ac91a443b2d6fc7669bc52a8dc2f 940f30149014968e9cc01fec132785bb6990f01ac0b7bc1ac97b3b5eb6256183 f81895b0ba67d9850828ccba479bec869c188f2c2d254b5612d627ef719a88a7 854708c1da30f9f98cb05ca5b8b8573321d4f729a7344921a9f376bef75c9e51 8e34b500038eae8d855ed7b80b3a81c05d6664958cda88e2518bc9e7eddce863 48fb26a2d6987b3b5dab2991b90e8a149dac0dc5021b198d2dac0a5900adef51 ff8ffee9e4ce4056d5bcefd56d6b06b481b72f96430ae41fe3320e165d122d7a 0f35e5b2d3736b6a9be73a6403c6ba0f98a938cb6e06be3f700bacf83e2540b3 07334dca089b23c1d1cd601e69b5d64c1af0347861f3754274d9b556ac9aacd0 e02f32c3a031698d5b6eb871798306b9f1f083947ef081e37e7f58226b6d09b8 6a0ce596efab1e09e24f83c816a2910c0f18d054a914fa059c41b1ea4c78f6b2 57f619f188c0a869d043f4c41cf43236c8e1ce80f12b6168233a6f452b667392 417484f00663dcaffd323823225e1cd0cf76ad7df724db16cce584492173e15e ea96e9c65d7759c4a0a9be30e0ad102f4dd0f47ab4dc75af9a8fcac816528d5c c01db326db562a48369f862a6057bf152e12154b9b71233f0b21b80462f56ef1 32050cf1fe635c0df1b584a947d370f1274e290fffc192dcd6126203518e47ce e6f2f9c2565ed7a334c0ca91efe58820010aa1ec1241e1b8827b23935f6895cb bc851af7e8ee6501beb8b4d03a7f0062442d6033ba37d5ac2f25144f7d01aa45 59cf88f92e93c57c35d98a382be18f17c24df3d41d8c8db2a91e6d5ebbb42e12 31f592ae1cae0de2e4f399339798f72f287afe968e9bc56aabc323a9ca0dd278 8ee9c8c5b1d3f378199fc47099e415fcd802651e208afece1284d94b5f45ce3d 508b5b43b6344dcd99d4c13df8d80f02055f094ff3e9d7f6db3447e01bc441a4 74872c9591414526444e50e95e0006a77b98c41b70c56a647772160c77603d7e 21302e5c387885ce1359e32b0988d0c3c0b645002d361994ee2031a1c9c06834 9bdf64b862161a2556140305b68339c517f6f54a247f96f238d45e1834596414 1693c3cd7e03df5737e6f206435972fa8c100d68e5d55b1efc6f26ae85e16942 1aa6e0e8cc7840effa32f20a21c92b48cf8a676f69e3465cd1594dbe800e798d 97598a6b0042768ffcd605725132c323250013d9ffdd4cbc46c71995803fd6a9 be9c2ff2e3b3e788f89547a687a2d8990d51c1cc70be9715840030715f14bb6c ad23094b33c609916ca52ccb48bfc68cfceb423ed2c230b4230d34409b1701ee 98a4bed71cc89baf62675cf7a8617177d6ce4f7c62014274ca9a574e974e7a26 c71c798ea3ec9ebf1f59b949e539a67aee11b8def522f6ed695f433b71b159f1 b298b7f06fe863b3ae360a12e6cca2d5ad1d105ae139fc01325be21f78d1aa70 57932261b773012ce60c5e26bd7a2a87fd66d47f0cc3b94437fea1cbe0b4145f ff35cb6db2c5ebdd155010503ff566ed6d1f5b1c9a36626ade48d76254250d3e dce0046a37851c5026c7a4ed303d870e9766d84a9e6d4e5976dcdcd60f34d4bc 6d37a87c1f685b27af20795e89487f790697b5c99b97dd0a19ef0711a1ac3733 f7266a5cf5b3f7ef28fb4e2428c5547c670a056b110bcb9188ac0a4452e39c25 a2b19116391e6ec0526b4af1f0fb04508fcd4306c91c7124196162424f6191cf cb1cb1c1dca53fa0e7b104127ab69699cc55aa750a9474b9517fb375faee3862 797b0ca02fed4c418405d88223eb001882e2665c0e631dea72205db3249a9903 104956bad09c091477f9906ed41f63490a62fe6e81898b8bc7d2044c02e7a620 74773d104bc903adb07c4e8bad78bbcdb44b5eea9bb052aff7ff96daa8f97365 8787c10d273fc7c43d5b055cbb631cd6fa24068ae2ba576049e029a174527222 6b13581a144e59149e402649568811cfe67d363c2466a272c2503861219156d2 61eb9b1780fc73fab757095aa7731b0a5da2c813cc36d1e607363a37fef27d0d 7672f3451e80b4fdbb01dc2efc655ac562defd71fe7e9c785f8e2d43b7ca09a8 2402e629ec86218046a59177c682f07d298a2327e203b9ba29aa3a7cda2a905f 2862572827a76baea9b113cd3057dae5021169ffaed7353a8e8a150d99914941 95eeb5f30313df74b524624cb8ca9397c97814698fd503eb80a915325d4bfd65 02d6feb3e2e024540b00f37b5b2198d2ff05d1398e1d1c1f3b73399befa20a15 5b52a566cbf14cd15d44df91d26109ffd242010a5bba7692d8b4e180e79aacf3 a713f0c2e91fb5e99e2974efa91de6fc0609c64a0e0cd2bf849cc0ee7fa3fd36 73ba4abac7c1325dd63f832e34dee41d4189d90e64f775f904bcce4bb3db793c 0a7857cd3c77a4c8449abea91b3d424fc8f7b1a39417efdf5f1b85827e65621c 0bf93c473af049f8496ccef2672503d3c75092f1dafcb7da8a60b7c6bbb1386a 5487792ffa3566c4c3c551abda71b6d5b461add6fd81c2db459017af4d3686c1 38bda5d44463d0841416199cd4c7b5a924b1965a77ece07a069763893a9cb75d cdd3fdaa97260218c247273eb293d4e90e4b0a0a2bfa1f72302fb98e1249fbf4 cddd8cb104fed1e429b08285ae0b471d5d0bf74fd1606887171f7176bc9e1253 eb84cafe4857855499e373ef983a2143e1b1d6155e94a3407e2e85f164ba421c 46f8579c8618a783fa34d0d6768d7dce4c4460b1ed21a24d4b48117ab148ec3c f8443fb9597919df3d9caba2a9836b1a3076b78675facdb890a574090c94cced d297d85af7014563f80c4f1a0d1886f17af1a43de53b34c449d660e35d08eaf6 1855741e4cb18127641e4d80db0e585c6f3d357eaa5ab9cf134e52f3023bc2cd b3eb8bb92cbbb2248a347b7d439d6e7deba3e11c0f491dc8dda1234d33ff7e59 48eac61ceea14de3a054bd98e687cdb860ac9dad6f3aa5732c1e2b8c2deb8c43 05a7638c5fe710f66a02e55b4cebb837de550a5ce2ebaf2f036b371f366baf47 6781eff113890f0dbe3421870aaf39fff6f64a9773208450e3c6cc5180fc0446 c52ef31914ef680e9940a5d04d6faa9d5a3bde6f30e4392a9614b4586ea11fca de390cf19cc66beb0772ceb5713fc9d06233071045499e7baa08f0aa398ce9ca 50a4b637e93b15704cb72105fc9e0a8c08e02d4bd386421aa42df597cf32cbb0 5e5cf1bede2ca83f83b04c7a3ceb54283e769734431060946b4092a6e3f1043a 90107a3e5bd79cf0c9d14f7c41afad86e1564a2bc87b96b78f64448278dc83d9 5c12fd730cfd26bc35831b953ef6c88ba99c02f2ed682fcdc5a7b45eb2995e4b 6a5534816c314480e918bdc6ace3924ec8b3ab9f7aabac1e46931df705d0d6b3 d33821f1f4480e39146c5d22c5f514d12de2acac4ffa1add24e94d0aef01e3b5 0ccfdf97d8f4d1c3bbc405a6c0a05cb10c84e68a9e828e91bc95613184285887 d8a28eda02b6054603560444fb09c586c851f6d7dc9cdbd62b627f04ffb1d125 91d7a87a8f597ccdb99c8a1fe05cc9c025aa267c63a8512f4ad9ede0f598817f 095efc60133065f2367438149bb8fe64be7a8e2ee6f0b6d66e7c1d44546863d3 096b3016663a9ba25eae4b5420d5dfd2752753526b5e300e6632a52f581246ff ce0f9ef751a001b0ea6c95c8f93f6065bf242b4ae69d8f0300243e223023235d ce21a3b1d7cc54cbee8c3b2042e2251d2476cd0e2f73119ecbee806492eab3dd 93976f4fe773f35761b0a3d56b5f260358c7b04960d6b01342c13319e11c1ffa 09c8b32547300288d6e9c3ecaeaba6dd15c7fa037a565b201c961f7aee9ef1c1 decb1e86aa6a956e687aeccc633c688d76fa9d76ca8d7b99961b1591b4c3acec 530080918050c0f671d21b63e4cce47b639790caf570a32c88700998b61f77d0 1cfe24c75253c93e025d78117ce0c2a1571e2e89e1687a28220c222b4582718c c4ff26336a238471bef959ffa39222ca67bb4eceaff89a104dbf99671b92d7d2 5a306e5353c2f33d596fe151c616ed716d9bfd68237038714b53dbeee2185f0d 7c0699c7e93eef0f2cbdec06332b23fd9804512d7b9a709790cad1291ee62329 07b843fbe8bb4882fd4bab8c042dc86a597985fe6c031bbaaf14a1ea7b1d2a8f ddcf47a01055394119fbfc49ba1dbe50eaa73f3cf19cf8b60a96326333bd13b9 6884f9ea3a3c4684547f6f8613d1087ce35d5b14dac078dcb27d63a5c3a7c626 c965f6b81f78472b1730b1444d9ec15c9fb6b54918b7b3f4993ea21c9610bd34 bc587636da4ec349e715ef7cedf3ede92d7a3cb0905b2dd35046f01dd12ffa6e 901f65b107e0217ce7569b32cf50ad1cfb72834ab06803f5b53db3464c6f05dc 51d7b3ee2af84871f009a8caddb325823200ae4462e88f3bc9c94b9bff00459d d85bf76e475ef81747d3eda905cce4fa6e876605e102b9b2e8f72cda9153c8b1 9d9a63453c0525302a0d2e7737449abd52163c08f24c1e37f15a527d6be68c95 b6e86edd5fb169911f22137f1111a253fe2bf493cfc989dda1f9a880f3d5ef9f 7d072839af8950bbaf6313a4cadc4a04f152f16ba3e84ca932d1445f9a34afc2 177f7508e693dd881969727b67446fa7eb9a47c26e826d43bd3a6e0ab5834bf2 901823191b933476f034f77d166cc5bda91b0c41daa76c781bf098e13983885b 922f40a9eab5b333199265429c4fcf25f459e09ebdc63d5e077bf733dc7412f2 319fa49be35d561499b802e63d8e2c61849b7639c623785266bf3d6dad7e3b18 07cc2c6e39549e7f76fdd89aa4a9becd09d31822781a94839007720107462159 dee6471f5a489e8ebe6ccc9b1e2b16a2f6d7df7919372b2115498781ff90efb6 29ec1cedd8d6ef03d011b35c17debfb9d4b202d964164928daafc80c66c0de08 9fa044d016d3ae76f4479d8831f4005efcc6daafcc78b0bb8cc8b65f63c8e9a5 768c5cc4a18fea67f416195fe7e1af269ad1829cb8861e19afa6384239e6894e 914752c736372d835b803db11dcd48156a4123895095f124b39279da0dd5236f cbeee34f7cef744beee1fda22bff75f4423bcf170e5abb20fc7bea38cea001e2 9023bf6f93a11c44043ce93f694351453c492f86feb6b44928d253473652f5a4 124a47bc0b26b26c43f6f23a65fc74d995bbd282e1044f56298b54b599c2cbb5 5c2774eaadbdb04a732dbcf9c23c77c335bdbcf686369e6e8223cb0274253508 f46bdd8fb828d1177c62dba969af55e292901774759d2c79cf8a5f1a57acbb9d f2af226a6a889ddc46eace4b559a7ce081395056ea030e1c0f4547b539c4b0a3 faf7b038e862ac015e8190049ff5cbde4f6b437adff070df511866e804ba4959 827f334cb6e5fbb142890c745e63905e0f0778d2a170369adb64658014ecb0ed 7b43a29455e7bf9bb18c406d8220c9dd42e737967e159697f38fd77174949c27 cb633ae5fd91d1769d88557b5a428183ef703293f5065b578e9fe3ff3b1bdf15 fc811147b7c40d424c287edbebaf6d8e7242d285103d1b6f60487287afb4d848 32ef999686ffbb7655c4aed56d167d2d7292f711448e8847a1a05e55e6424735 86389e37f7bc902081321af80c748af26665076e553bad8bdffae84b5cac4466 39033a1d13f762335650c32db88aa2c19a128014946330e09a0a03ebfb06f604 f47a687b06ac083c8511527bb3dcc57b8483e295ef2f24b3e84280e739f7baac f8451f5f9935a8713f1eccb30d1800915f83e0736b8c71c62cd34720c75dc7b5 227ac01feefc3da4c2e7b452e1cc37b20e7b5f4effe6061ecde47332385355aa ced1f5d61e7b24c1f65297ed6a611d92f233473862ad54d1a7134007ffc35e03 cda1925c58a914d8b11ebc4d2668340bd55565aff5c118f8a707141a4313af09 29932f04e23bf8c4e235571f2ec07cb384da86c855d2e3b45fec4051a6bda5b0 3fe044639d70fc0e5e6757db4e45df0af07385c3a25aa4dc8294a477bf39be08 bd398f48990e8183d93117a6162841d3df3eb78811f8a84e101e5931cbca754a 52b8ec2637c8327591ce0f41a81f77603ca5d508353486a5b380f3c495ac2b2b 2b6fac9a5788ac550314d5ef4a85d855ca12f866dcc8e55f63b7898ee77c1c17 880a74bd63ec12ffbadc16c57915d3098476cdf5b25c4e8cff1de4b35009b7f8 96bb3115b7d40842c7ea3631bfe35184e2d16af4261bd3fba60c2913e4911c9e b3d442f2d897e782bcab66f0a1de170fa5171f588761a3ed7f80a04f59644abf 4da03bce5db4b41ef54d3a5dfb5140fb1794332c20c2cc80e4184549ec38ff68 cd6abefacad45eaa7c9e295c08857910943d9b0e6945ba77199ad93b5668eda3 6eb4e11f2e62cfa6164dc0ae1ada61ebaa6949a07cd88303c633835fa98c1e53 e4705bda82e65f57781a596d1e54871dc587e1a614b77eab59911c1721d0090d 34 3ae4324c1e52bd475e2a6411c3d117bb21277bdaa719ba24ed8a9a88306a430e26d7c1aec0c3f5e0812f6774265ed99c3ca0cec7976bcfe2ed7998e52dbf320b54dc05806075cdf8121ef4fc9a98a2f8dadb05e209d9b3e361e6633a4453550700c3f30b909fc8604998ee6825bdf82bada7ff1b4ae822be338555cfd6c4960f4536bf38c4b3118a08e5bc312f4df0881e73947c5794835de5708b1e149dd30ce5731cc878081724f896144c4f17a20213f30fe49e20c8d2440e3bb0e8db35063b4f5a3491011032165704f56becfc4c7c01b053ffe8e984d3d6a22eed7c820183b16410989e896f9482997b29b7909cd5d43213175084d9bd40bba761cda303ab5caccd7fac7167b1b2f36ff1d67ebe0949c52e48f851c3e0c1a9fd20706902a5368771f4a3324204c2c1d379b45526bff6e0a21a8a7ddca4f9d4f59bc09a0e3cced0ac95786c93f3fef089a641017292797344347956557642f548ed720d0f768b0d50fb9b6bf723e87dff55e702e6678d07b98f4217dd47cd1e8754da5402ddd7dbef15375f0143030a9f48568fcca9ecb507463db9159b65ffc73937860a1252615fd5943ca9095c345ada8334fc8683ca3aec1ff0467d5f503eb56c6a0f586a7918ae4c07958e5f39a4a60f5ab5facc2acb9796775555f22e87a9947e028742ebe38181035551a6ef9cc822a562aade0c24ec78a4502c66720bea45ec0ea4485a61ee9da2a2d151a446e454b4219e84b4e16adfe962adb0c6ded6652e05e8bcdade1c95ce8ede4c77175fa576440a5ab051c75de6a75bcdb5c05bfa560daddd7c2fc2bd8aa8aa65b9bddd6d42bf679754d8b7d27925e7902ec7b1db76059c0da54e82be1c3a2ad50789c84113925717734098e3c2c9faa701392f76c107bd46b9bf99c40cabc36d03612ebec1537d240e0b6932ed021ee97575e98ea506cb439ffd5198266dc0438308bfa88328da606712bdd9e4fc10b91e0ad9a9f40c0974cc094cac423c8c9d974753e707a97cf5ae1e3112ccf4b83ea10cd94a2b076085ae1904701bfee5bc105135d3c5628c9e7692cf3c18312b4b7fee1db10a0dff74f42ea71820bd6e7e9217adc301556b9f4b5d385246bac3f273116b782e0f207b983842766e5fc9ac41720e4fbf2f5c61a6e48a36b0c6dcc5078c88e6ff0b4b0f69a644b6c0b0069d5973a171ede818c3c01a174476de8107772c55d8d80df0b86a14ac2dbe733cf6330a0c7d7548e78ca194b363bb64e2fa1dce1c9321064777cc3b0c65bc8def0c3a11a0fafa4c1ca36379bd35869e85da25d4a7b70707b5b09ab0e27e6bd14be600797eb2d43bf6dcd8d212b8f34f8bae2c949166ae046b36cfe12b3562e55f73cc5d890b5825a46bfe0b9f0ffa5df2e59fe57ac9f10863028b477c9168a75516affebcc52e08356af5157e836ad28f24c3cb38baef0c736dfcbbadcf46a3d722b8549a6edf470a4a4c838948f905188d7f727a1e850cb87356190a59fe5e973b581febb29ee36644b34ee6c5e660abcf96f15bae58066b2c5021551c52aef8ba74764f78826c77feac6b3999c5d7247d26f01926c70a4c738bab8706e625c4208f3216c19ebe672212c73fa946e9193875f7b24e360363211c894eabd7e6eef35773f528639b121864ab30be1e681fcadf1eeb3b330f2951a1e01cdb3a595fd2af1ccf09ca1c3518dcf5171bae0c9a8333db5a086005bae6646960a2f1d1ac25435f2d95dc2bcb5ae9b79c418a23acaa0649dbe4680628d92df7831b5b28ce03b984d429e9486b3c9ceffb045360b2fd8ca3387e300c712263a3c6daeaeb1548a52e581a5078082b9129cd63c23899659ba4bd205400a68c9583f4673bbfa613949b6e7464a4bfb801f546acbe4bd3325f944a316e0e9b6aae590b8f39595b07751f16e21fb4c93d5f3b6f501484e15fbc2134f5a902601e953d867b9cf1d9989192c772f7ef1f80fabc13cb17afa2e78d8e19b5b000c082177ea10d152b969837a1d773c83b42a8861142b48cfb889970bbfcd6ec09b01a0d633f3d2426314fc45c3ce964c1ec08792b54bea439a5e91d68b1fd800f5bfd03c3248329d548a51269bd9c68b410926980066e396059ec22501411090d4f0e93a9e35bd2ec88394c953868308bf5610bfb62b12a71c84b730c7b4c000ec4e61e6a2aa0a944eb65f6f208a35ea6ca146dc0092a2ac90ea9dd47af4b0b079799ce05938c7aeeb8bfffcebea7ad23d2c37a072eed6b5cbcfb55f77ec31803535960213ba8d2fe9a9dfb9c7963f92010789a5d4c45de2487f65d85f28c6d0c38fe761f3b6add1d0799cb918044aa041e545267d5a190c75fdb613fc67f3e0dab57e9f7e7e923f955364dbc9ec0df23a83e362d4bb7f2b687544fa5c4c14901e55441e0777b6515e4604ce3e21490c48a2642cdf94e4c2f1aa5bde5f4f9e903ddfcf2aad0bfcf67cb8f851d30af74ed495f1e6515f2fa89ae363e1ba7b1810c56c1495364922aba32f85deed3d107f083e2773bca35b9b158b78538a75082009349112467d4dff104df5cbe15382b84b82c9b698e94cdaab05603f45f139309b833fa81c9026a4898ede2169b2b962370371d16a4fca576811c4d1eab34a9029b9e2f23a418cee7208e9dc85b6cba50ca3c373c813f0dbb1612d67bda7ed00f511fad92b30ac627de73a83ac15a7389502898af551915c3ec0d0f90c4580c07086085ef82ee35b21656b6f79bc5e41dfbf4d9b12295fe3cf10ee27f7154f004b2204b698347180b69315ca862242b3cfd668ce7a566e65e01e90ed3d18d290d6101d5911a697a6630c1298ecefceda2daec744d9d489cbedc12711a0f6850095b289dfbc65540cbabe34f564bec71a3930d031500af0c08db812ccf2aa55102d3ed80206bcd317205bd52eb8e178bdafa2366f9127f0b5e8250208a20a5520b4ba3d45e68fe65f1569fe8a7802a226db0cc2cea9c39a74e665409a9a21cd90f6696b4a2848e7efc440928f9659c9e214eb428868180401fee2098ee17aabc08785d75db60cbf57cf664fed4dc2483dfa862e9b88fd36fabd9f3ca412d703307c2d1c11a677de31cd926cb9b276d644131c69ea6f7fbc155d9f71e40aa5dfa0c7fa84a3e66b139757fcc579fb32016b6db7cf35159a584cadaa2ba5e99af5101199650f58e4217c012cdb3a03733d0c6f0c7ff2a90d2d55606f17e2a1e521201e7ce83b87c08746f1097ad7468a8e7b9607c41b0fc9d42204f7139976576b10f1cb5889eb5d358351b98a30db38f38480b0b36b3650c6e0c2249b746ea01eb0fd82ad8ee894f4d14e29c08bfcb115fb314ce63b0319a14c0b3ac58140e30ec0fce3e717c2e2a22676effebb4b2dda1140c9a40bceea3750563d764b9ea470e041cde073ac25a270ee6850836552f128c5a4ffb8511c1910b36de9477aaf5e70bbdb8b6772b2ac29ac929d4b6b92d8d16d5477bd6d90b196a1c48314a72f95f0fddb9ca36af3d04cb96ca7c22d0156055724c0dc49f9517d2e65dd1b3c68125024c63791771d94c05cef483c6eac799fa1dd412b347ef47392a20dcb991415003d3260a4e561b2203ad94baf2d654138e162e0d7ade81a93ba7748bc548e4270293ab8fc15ec63d6d9d7b1d80681d1b58fbb36b0ea7f810e8f46f4d7b7b47040aa682fa8c17dc21c4b77425a6c6511d01effbebd4a94bcbba42e7ecfd0ddea50c850eb64e9828100cc57eff447173b770426af2ffdb222e4e8e2c3aaa1029c2066cdea26cc2d7ae3f3f95a407b95385ba9207190d36948814d2d58050f6aebc0f6025774dfbfb328dfe402b3523d67766fec93a061d7e0d9fd7c24d16f62c100bafee7bafbf6d8e9a0557e254eb56fd53fc10691a800b9267bf50ad88280c37049d9c2798b7ed9bca0fb999ea43c307a5f5dc499a1b0a4737572b1c00541c1b0c4c3ae48bfa48a79f54a56bf97fc69bf1ead3296e790ce0d6368a4337dbe757083dd376ee334adf5307e775d4d14872e9acfbb5887ea23d602c175677ad029f07b01b7a5c9cdae1e2efaeae791a6a0d59ae80abfd8270c594eae360ada371bc0074480cf49162aaf12e13318d46a2d9dfaf63024c5a1b6c29efee3f1302e6610d5f351c69a4f3f41bf0241e61f382e0ed5e08500e36136eed08e9723d7786f308f8d2053ef695e391095a5c2113d8c4b2955797c13d3b49ca93d9392de31e34079aff4edf22fba02e49bd82b667c6e53c6c32d666acb817bbe5ff941065dbca06eef17ff089bbd3e88245b0fe6db5ed4f0f36c20a156687f135b75e05b5403b0c628cecd89f0e682219e900cc157a0b2cd21d9814aa40667c17f23c1439ceba031517d78a9c5acc4a5f41bab12c31d4cef6ac61fb4f4da7347ef67c3da2c2f10722baaace312373fe3e6f0b393de9380478818ff63244dbe32460672c82e928064b536cfbe657f162c7250c47cf15d8a4a4ebb7532c24254b4d06f7b30196180a6f426311710a37a558c8475b725b49a69dd896df74fdcb55b9fa402b56b02d0dae8e4c1fc9de4cfef7e764be27be97e80984ef05ba3c71218a0babd22d835305fc7f432eae40a45ee9a426fccd42f5fd816afe46b6e89a2af7eb5f2c21fdcf0af8fb6e9faa6f8b45e249ae77e70b4c1f4a114cc80fad5ee6ce1606787ce1bc0c70d2b4cf9afb1ab48c58a38a3bfdf886b95ed1f0a9fac214398eb5b863d6f401f58ea3c5b267a5087904b03c87c511f7c477c226d3670f6b877e632b3306280564c7457f15d32124193c6f91836e38f1e51e09c670ff4169abf0f962eca96a0a809ef331f2813cc51cf5d5f601acc4a491fa910a788c778d69425db9a6797c0a4590241f68bdc0e2dd9a677e89a2cfd65b094ecf9952474ce9c83ce58bd0290f60ff3d728c1513869de646dec36b863be4d1b6a0608c9b46e304818fa2a44d0d9dd156209a299b840933229b15374ae08c74105694c78e515ad6adbd1b459206b538613fd322752d9de3fadd52e39a87e6a8e48803a1e858c6217841b37197005ec2b50b1ee8a78294d6a938a8a3fd35696e086840b8e2f85b388951068a6501e00d845f383bc3650533041ef0242dc73ceb8bb6c22df4d0af63ab4746f4cb0fa1e12b68b249ecd48047f5684b45c7e238a2f9a362fa8ab5ee8623f113a56c0e582e8fc3a3acb2fe86b18b26efda5ef34a7bb4364195fdcc2673112884f11a094c8ea5970cd1f9032b1d8dc7e1291c4dbcabf3237f8e4aa126f84f7b1d9ad500fb96369348a58f365688a763bde285aa67c4955367f024c841473461da445409c6cf4f167a2122528b68a02ead545186307e435c0b06db0c6a88da8a1a940b0696eeb1a2127c4aa1edfc86af82fc3fcaf9922ecd7e62b9a1524a732022c7d00cd5f53a678f1b8470981137145014568dbf4c141e5ff8e5e6671c2591f681730a394ee2aabc2f7248071870aabb4b8206d46311f0d0eb2bc81fda4998441b64013366ca32536a7df7d5d74dbf0f65116fb133fb29d5a5ac2db6ed501f1ffc5c0a7545a3d82b601d16a71cf81937565b0996d16a46ba53faea8289b419e815ea08d32cf244233a1ece6de45020cd38b0f8927dfc7fd909ee440c7dc1476f4732015ffe4201bfb80a505df9443164ee829833bb94acc64610f3d441d8d000626004379b94ba7124bbd1bf88171116263feaa514d1bd31446413212e2bb40b2731036106f4a6d14472304a134a022ffff9dc6c5153793ee7ef7adb46e35f99f1a3015ec639e975fb52acf24846e0b4b8852b2976ef046cb139f1fdcd337530c6250173163a19303d101a9198a5e86161fa34ad747a519984620eaf11d24edc6cc8089b1565affdc9ed903823c9692c1bb4cf60eeba36b39a49d00924f8c670e4190e398383539ca06358d0de2a2158f4c5745d09b4308bc89caac1448c512b2064090efcd0c8c7afca41d5c8fe5442154229c53753ea3e333b660c94457da36330081f41b0bece83a0f684c969cc905642e1628ff7e0ec1847328a1c3efdff3efe05f11b6a12c0fd6c1990816d9621f2c533b16ac2474e1eeaa87b8477c4a56c9b040feeaab08331e5be5e6c1f7ddde6baf7a6a50f9e37fceb04bf2bd588e79f3e01a9bb1016e88a66d44b0e38247ebf5fb1a23377c5b4927a8853fecf4fc3e3fa09177949bdf418f69fb761ef79f7a919f294ae06c0dd6895abfe7e6943972645015c06402483a5aeeceb05d7a36eb53e1bb9e818a39c49996c3e0e3af16d477e006cadfb03e5f25eee3ef1ae1da9175c09866b35832283067d98783f222478f30825f59b188d0f69f916946f8614ea06de4a2861a0eebf6b29b5046eb8a0751807077f9d1e896df8d0bf9445172113feb82295136046d9750a464bb808fe13470693b4137b5cdaca5bcfb07f9f0b77f05bfc9643ccd597c08ef4d462baec2d8f02859db7248167550fe484dbc955a4695080996a4901802f49714c956b6a68950e09fefba153447b8119f473570430c9ce4f3e527f3a830b602dbb00d75cfaba019b88177f871bae33931ee3b26c1d94c73eddce9fd9dc9f90436aef8b1eee2e06d126ba313a3e75103013972b2e1e30e6ed3ddcbe0d37479b2000e6126b70a402abf09b5745233f3966c8ce0bfa01551e1b3c2d4c6b82040e9a058202b678a20bf84faa5d510c8724938aa0b81612a02ad02dc6184ee3bfe3f051b1d3bac60506c1d96941ffb83b725fcc0b0d1f2dde1f5011007d47ab72376c300a872cc7280fc0e187bb5d9362e2481c03ad1da3e92f7edfc43f17301a7ba9105c42d2154904c91bfb95cca5d801dd9dd626c6163a936250f8704d36d7c94b84b46e2ad2b30ecb58e100d75b274d322f0057e9a48934e581f2e3702c6bc1e619b783d6e81d036cd4b2c4612c6d02927220af8014c185dc4250b1a3805e6ec7a9d3200ced7206478682d3cb52ee69193aa3d5fa750220dbd33d354899a848d562f6926b28910e9f790ca308a6b4d4c1a9d4eb0284318fca65eab48c13bfb8367a19719b7b9d0ed19f3de017fd75d0a8a73fba37cde8a46d7d1d4339aa4300d88f03129dc9c109e3d6696a7236925be8753c126aba9a65c03ae9da6ca19b8f35f1d95f4db28f0cccc61a33c4622e28e7a052a62847d9ea5b5d18c7fc2c9164e7ecc25f589f690bca6b103184be4a0bde9e0ac32bd57096ed602875a17e6a22cdcb910674f04008cad41d6980c53e5858c1fd4796ca7ad8d84aac462aaadab2408695b2a8b539085b20de2ca4968a85b8fc46f3e1a026f7c97b4c0c0e0d7a9d4af11a69d1cb260af5e292201b60955c328a7ddc74e2a3e31f5577864756636b85906e723042c2007ee2033612b209af788a359f96a0c6f88f8e391f6457caca778105fbd5c37c07f90fba02f89ff93c29aaca3740a8a97ba9f43ca764e9fb3a409215b5a708ec00449080bae2cb785e63dc3036178478fdaabf22599d65c6a3fb390aa22e285c09f219bc2c37c058373f37c9b8cd9ce7434759878b1ac4ba5defd4d185453c27002950769793484dd1726257176e110f3f6e86850e267015776a64c008668c52030de7ae99aa19826f71717fde57bb3b3e0b41872db27d215af9690093f945180a97340a943f4b60f358033438242d34a5f36fb82dca1bb9d73538f16123a3390eb524c35ccd3bcefea87838b9a983270b895a03f4f9371533df638e30d361ce07e6d1ee021f9976729f371ff08531b0787b89802fff05854e48761537f6db060c6f6e3e80783a3a5a8e3070319c7804eff9b99a47442dfec29f0185019831890abdb8962e60fa00ded0bc44bd838f595120d29dbb886083db7152938caa91da08fee5d2cfb40dd9a44b35e91fdbe204057d5e44e7cfb5ab62e8eac5483826ad0dd396f62b55de1a0c7585aeb79b95d9369d1db4aa71bc662a50736e1d5963720568bda234b54e68d25004f7fbbf7b55193e7f1ad3f2039c0dc194a977d0cd810a69515f1449c27a48b4406d624d63056ff514e759a55bfdd11041aee06cc5fc007262d75f700059177824fac664911899017c2eaa33e7349cd4b2e6d5b3d2ff06fa9c3b4d70288cb78ae3ce6f949fdb4aa4e55d08673e93f1c01ae69ceed3a20209050e37a9d62239c0cb772736084b6848ab0b151fbe15944345755fd8ee33005b7361ce325f1102640a3c2febaeb854741517126cb93574b61d0bb23939090e016b8da7878857e1c3e0fdfcc2eeec5f5b4ec67ee5e34c4c809acdbc9f6fea047ff1688c45416e3e57e9ffd984c15eda5d935bbca1b3fa79aa84debe2b60290122997dcd973bbba4ec74ef5f4d1bc96993bd23776a5da08e9bb8082361a464023a8a4263b83ca52a960c833fda184b3dacd111c44316ef4a8aec095919e7ea041e68081fc7606cbf2a91e0463b94356ae15202892c48bac0e0fa03e5e5437b0dd7d9a116fc9e4016996f4badca5af1b5e22712dd2d9af083c8f72fe746905d0a4dd0d54f26d73da6d941bf9874ab21e6ee408ce8afdf8e309ab0e711a1279c02ee67b0f76326ad7c61dce46e4e665852b8512c77f6c4549edf6e3fbfcf670c0495f72de17833715b80d8f94f999c5d828298373524620ae4fb7c005e992ff602665f38b113729a5d35b91f7eba475c4e8edc01a526d4ad2b6e55c45a8daf240fa53dc91697f479f49d8725bb16d25979247ea9e249ef22d814172264eedf8a01b775a40c27a551f95ee229f153449214f193b4c46fd2cbae881fda2733fa2805c48a2e2aff9dafb8a32fc33171ddcd876d155832b32fc5bc009415503d4d930f4c2da9e3150e66f2b82f7e217d15ff8e12376ac6b0fcdffb140930af1c9020000cc0001c7c93eda209c95d2d3460f02b200cb5a7e31778f9750f3bc6eb24930e19769b93c25152cb2e572e294f514c44eb67b42233fbbc1ecc0cc3709faa0b0861ab09f3e8b9f8d7faf9d42d80d5651bf74871f5edf4d5e48a85cb384ebba400d6de67f0926079f56ccd18d87487065cb4b7261b56d8012e1350b8ba4870fc0a1b61fcce38e9b10571b176b381176128a73e20206203d191cd15723008f00005cd318b58658615d6f34aa6999ff88de209944ec1d0a3466fcdd6f804d5ab0800003f4a6280aae95d97cbe9114a4c47d2615e611344be4052ee933bdfb4d2c50bb06f17858bb352e8f01d23b955532135e62a98876195551a44d42a92fd18030f108d1620139d0bf80cbb174fa5662dcb17131b88c230ed7d269c69a7e45e55096f0c88d4e5c83c4490402e00724c74fdd9edcf799190147e6711b8e9aaaec10b46e247353ba07e6d042b42acb6a46e0ec0846a87eadc9d53e4a72ec24c7fe00ac48e12afbfc4d3b96684025674e85253d88ec4ba7dc66a08d5f263fb290e2800188ea6488ac5701f4e8b491d03f7310a04839e6e00f8674d6c64dae8d5f39a0ede617a3f0d059608cd803c6097e272e726a348be174bac91d8c777a47c6a8e0f45715e79cf92e407f433a47df0bfcc17cfd1a9f4ceefe94ee4d09940ce7f5e0f2d05a5ed85876d3c62b21685e955c5a69643450725deb39462f63c6c64646708c61aa914fa2e95ca21c9364965a11f19f7fa44ce230bf591fd6b84ea91aa230b45c249fa3d6e7fa4ed826b54ba82dcb8e1b4006871d0bebcb626abde26bcaf04ac9af0a4167299c0a5b49f5f273aa947a06bb6aa492f910c6d807f07940889042322f819555f4d177835bfe6453d464b321501833e5b81169569a6ecbfc4630477d071de15c128b7334680234e608976847249eb38eb5d4530347d0f10abac0ea677e2125bcfc92258a8c8cbab325124d23a38a4bfd8431d595fe546e09c0202a14d7cb39b3b84af9cedf731ffa42f321805bacf31abfcc5235133a0d199c50e7d8905937c6146f8d5b9ea80d5e82e4aa3065fa33945fca1d496d9a95003010dfcf59bf5da37320935a71655427b8b175e1145b0771e6c8ee78c13b07ecc8906406c9f13c18a6fae156e901dcc5f160a5ca480a64ee4920a224f455dd5f5c50ae38c644e51909c5f101ab5b3c4916e52b527f82545e7fb27ce98822cfade59055a76f2642c986674292d35b911208374a76e5f4509735c372e2fb28a758ac708f3f2b851c1539bacdf93ecc6ec1677de99bad9720487b18a08a9c3072861270447f5bb2b5512a29d55cce31fdd206818b0b81530754b6c8d38c5a14b10a41108254bcaedbfdcba04fd66805b030c12d6adef005219aeeb251c4b0d422821ef03e492c9b8747cd195065e2fc6fef3f3381d040b7690e9f2c01739c68a86846303eab35b0eb7faac20a8c03d21a2d7eeb758c3161c14552c74fc1e4f516a31cc0569defbdc2be4ea96654398883db97bf8d389970c8140c9c708e416216cd1710f7ff4d65176f7566525498a285c6fc3522636958e1fbad9bce6fd3230253cb50266e804907319770fa0cef00cae6aae36fee7b2c08d7737d2df20a76d5627920d0a52c47e10047e6161be0f072e8d62008aefe7c2b2be8605fdb974b04bcf000582aa1d13b07305313319a2c5d85c61d3a75cce95ef64e5b389805ed9d05b5806f23e326a855b7aa0afde99b7ce3ac3ac8ceafd320570930f0bee91596eeb0c01d6b107e5ac724491ef9985797930594d9000e9b0e7dc7221083558474a7bed064b18513aed7d3d0a276e196c7cadc6bde6c71e8513a5e49e7406d0e05744fe0abe1618a0acc19b5c9489be7d2ba5a6269791b743d93ce9098060eac4eec41c0c98191ef618e472988e2f76410caa48128a31f14b6256f650b08ab24faebdb80a91bea2bab9c13baa04d5b779e67e055258b231ef14b71c717b0ae8041060f601597c9ef0124e61d978abebbdd4ace0acacfd7059ba1a606beda4d4d6eeefdc0fd6b18ca2e9390ef07869fad1d161ba24f522352820d2f1c24ea97c3f9e6746008f6b38984d68ded0aa1eb332b4e1b0fa76734ca7925cb329c6c95de76855e60bb6577c3ed4cab0aa65a2a6da4122bcc676ac5fefa9b86f06c822bcbe17ed1f080bcffb11c71504542ca054c0c6162da4da2d2b7c1484b2f3652acff2ca94a60001d303468f9163ee01abee90b964481321f1e3ae91940efac190b22daf8d3f0951404d365ef03f79b628ba3bfb710b193e63aad5d7f0f4bc69249c6d8e13ce08467cd348b5e89ada62b9e38ffaacd76736d13d3c063879667f19fc24f552260757df2f1f0b4849b0f31ec64e85804221a994276bd803f9390a53e87a04e8770f0534e0d0a44ab77ca558257fd22b4ef26b74efec0a43062aafafd1c7b0f78d0b1e043ac6a1275329cec962257ffd71ba6519aa7cb2ad4da9507dd8ea1f0cbf0bb7b5eb7f56017acd43533f07ebd90d736f0da9bba8e273c954e171e2bdf96b050255b4c28e773caea463d2061142fbef5dce37d0b8976e5d990a93cffae8d009dd6e3779ed5462d258649bc0da56f1ada0750bb31caaccbb50c0df4d063ede00b4c3a77421ec734358755befc2938b4199e2c683aa8fc924407fa151c32e190b62a1c6542c6fc39ee08c3e7fadf6847788d22632d917a372649a605ba662540b396197a097c6e5414a2d44742fccbcc9e991ba0d6b57c3494a60e65eaa6ef406c19aa0fe9f584587ad09dcd0c2e3c22b12313e54d3db36ca8e60a7b836f5470cc22791fb15394228bee5cbccc65472dc62eb4e6963733d04651b713ea8239c02a0ba61e5f1d61020180bc5633bfc536d9ca0d630c6ad3f5084573d7bc9766a0f2963b0f1adbcdcf9b53f5e1354b273e8c0d142a1c1c1b6429fcf7a8ba6322b009d2e2af428e841a5ac67a05dfe304d97476d37a968c5993cfa5cb62d09f3bd0d8dc5c94bdd0b81a02e53b728a5eaa24b96591f70abef1ae98b7ab07d0e48910a7f56f40ddf7919a6824a2f492f95a2458de211fa488cee1bd34c5698294e850ab454c7dd6e82d547d4f8f283c57ecee87584eebae6b177d9d3bd8d9c68d93d02046bd7d99d0f726fbccb4e24b762a01bad30aa9b525d537d878ce29ce38741045079e2a813f843832576efe11659baacc2510cb21e88759bbc772294ce4b41058a9b5acf73f73164228f76c9fc84f74fdb9fc0605306ada5991b090760c16205bc9b587093298d7f780e45780a0f969fb7abd3eea7f3a56335c6d9bdcb798b089cad88617d7578834ef1381dc38eb1bb98eda40c6d2fcdf1236acfad70dc510640fac254465a4d353b0619662471b6667e2398ce7a4a652cdcb9008d84cadb01dd57e070f179a8d0ab14f92b16f9599dee5647d7b67d46044d9120b46de2a00e6e52228e540c8753d8aac6068672abf64a7d499fb5ab4db53fe596b3dfc7eb0c4e03be965cd11ff438e36a67fff418ad7219053f5a017eb30a635d8119a0f601a9fa844b4b908a267f185690b875abfa621e9c124dd98d2755e8c0570522d80fa5a0fc1cd2395adeee91f2bb008afde5759b97ae23e7a45359d5a01881eaa108f371c4eb774a63f63f2d835dcb67a02eb55b153f467ca47aefafddbe49a8f4018c82adc0a7aa5caf94f5f86cce3bca731cc5d8b3168a92d007a55221c92b690dd99605bc6454b4a2a57529d2aed8fd7ac8402fa3c34f2219820f2f7818d17500b663cd13990fc3d19bd6e933d83abc531366bceccf6dc3f6e678271f8d5ae809fea97b731887dfab5e168bb0c95378445893260b85ba775c3f5f5e2f293ad20514c669cbf62624087651b323f2848076cf88393bc63c707b6357b12eecb94e0904644c9de8742f331756ac61accf7c37784dce1de81d399156e8d51d8c35c70a80c654a623cfb1e8c113f33ff274192dfc75be91365f6d7c1e32a327bc9bbf02d73268f24fd6d59d3e9cb29b46999b330ae8e47de2f9af526f7016979bcd27077b15dcc01fed4af99996a6a169d565306a573495e3602085d4064549bfc61501ec9a11cbc159efa2ab3f708f693684d657e8db33c645896cb644da4f661f3908f8d0228d5dbda20f6c6eab73b7b259571090bcb5cc4af91e180bbe44ac99550a15f6af4d16f80400e14ae4e007942257dc5ee8b444862392e6372815b2989a0e810881afb76f12265a0c72b3535a8e9ed7ab86c4b838ff7230a68905e54bc10c38bc5673e1458269614026fb9d635701af26def6241aae2efa00793e4a76850e2ad6b2035c90131792142d410f673147650a95738355189575cfa523a530ef0cc95c98920ea45f12ccfa512041d3142e30a7978c4c818f563f6dc21e9886ea046922aa220bf17ceebc84e6b65ac969aad536b43201e2ba5627e6a6b458eceb085f4472333da95697cb94da31688fad2de9bb1b0a3026d20609a91f6b1e220f0532c3192aa07b64daf0bc21716792564232fc295c36e99cc26767ed25d9c2eb04f2a1eaab5f9e1f50c061b6eed766f7023649fba0e05a4dcecb356cb3a0a4d503dca2414b253014bade51656835f41b64337624625605f488fe986c8c75a48404be3f9421d2b9ac1b9b2d63c9fbe377404d762a737c2b2b82c7905c96926d9c00938cee000e291be6b19ac6dea46c532762140c237ef55fbc22ea143601ceb1000434a6268f1fdcc484e2495aa0a2bcb2f46ae85f00e75d122852a9746b3c410c81d10645a1e1cd4d2fdb783418448e4fe6ac22dff3569a498584620fdacdab04c964b70e80d45c6d04036f9d6f50cf0e11d60c3dfa2abf1725f7863cb389bf0e6347a96bfbb67e81f379da165b020f5b58745d4a87035f7ca8b4a9a9bd4d6c0a58015f58779b921bfdbcd2ee1e7592d48512663c138913f4c04580a16778930e4a51ac2271a3942f79ca265a8df10af008501e129048b8b6575184d5544e5f0b0791c5a6fd02990a9193c2cda4743a48649807c679f349b20167842ee39e41004cadf3fa7c17771b008d396673f7de1f502fcae72ba1f73ad88614410108240bcb74f5731b254a9d69aa1074eca75a9af09979d2daae1d76c9718b6ab9aaf6091027d6c5ae4b91860d6a3d00580ce381058d23cec929fdc7b3e53ef25fa1b10b394dd906f1d778af8e310916fa8c09ccf4891773a36e6b0b8c0d45cca9f4d20ad9e4eb976ccfa1662e98558869cd6e2522321574649ca421843178c5808cde04e20cf93f41c81b51122c123ac74b67ed461a9a9dbd486d3a90ff62b48ff4b30fd49dc8343363ec35aeacd61f8541bed134246f08d09b295bcc9fbc7668e1090b151fa9c0aa8e4700db71aef6aed6a21fee34463edae033ed97a38124c13db80bfe522b83c56d38ab982e4fab8f8df10aebd284f4b14214b7d758613f5f37c80ee53831bde2d5a94c4063f5a329f0902ecb5b0bb38e599dd0d890da04516042022c2557b93ad33d5f5e80a16692d70d0b8d0bacf61b10a1ac12b668f16db3c70977554cc398d34422cdaa93d19b85fdeac17f337feb2cec7051d69b6d7267740928902ee3e253c307359d2ef17a8031ad472aa4aa4cc57bf5bf8d1b61826bd401b15588a414a35aa6349c69ab5c8866394a0f64e8ee36bdc83b4970b46ff63f02293d8f64ea8c0d05d5f9e859e48038cdf33944e037ff0a082e18b226fd4d7404a87cddbdebd154ca2b429c7e43217872ee687e29c42e2b6ade8ce2a6e98ec2022414bb10ed9b278d59af11a1b5df2849179c50f2ab410f3b17ec75ddc52c2f0e2f90b38642eb70118de75092cd5680117646733ded0a43a281066a27b5712f0da08efd9798f0c2c77e04525fdbf458260263bfe830550178d329f368ceebed0ce18c2c49211a5093d86e403db13452a7ec4ac04cd274a668e089bd80f1f61503501f0ff65cf5f963d81d55000b4235e9ade97214d06410e8949ae6de698f5308fbe56e7644dac995b943927cf9b62c44f8cca03b1ca8b0a9b9591c4daea5800f2b88612fb294b178b95a4ad96d1efeb6ab13dd42d75971239de80f2ee533750e17d92f3b15d7c922d72db517a0eaa91185ed4019f91e41fd39ee41ab58dc9f02561713db73c1e3afbf17bfff5bba516d4c9468e48f3eb67b4b8f4d562055ae0b223a016022b2b6378457f0f3e8dde196bc10d2e4c040d1983ead7c57039f1c0b755f8f63d86d084fc9601223e89bda043adc5839779d7fa408d625fcc450a3003ff5f4f8da4303c82ba03e8b5db1e5e1bb95fbaf18f6ea4b16856a862aaf14089da16d7c35f229c48ba351a449827889d84ef124e1bd811f87243ddeafe482080711354139a90591aca01bded11500981a4da6a6b81c894caec956e1a47aba0948f5745e7e15b88a7b80080443e342737ec997125713c9ad2411e5ea7d34c902d31a412291f52ad92793e3c4afa8f5d90a04366045ab5f975efb433e9f3a57002f5daf31730ab1b73257fb8389f7f260f94e318013a9398fc2506acf5a282806972c721ea1cec5bb5eab247e178119b6a8ff3e4fb5cb5a67a850a74220bb0c098592100f75b2103b3fac1a1629c7c26e5140059b7636b34f3048316a5f4e790aff6e2ee6b59b124cf7aa21a34d9697718495db4bdb65d7d25ea2712c26cf710d6fda52407236a749d455fc172e38d3448afb12de70c9cd18a319cd54d950430471af0367d944920028d0449952ea565e2d53f09fedcc7dc4c2940fe59a494a032b7833587757b7c5158f8ae87bd9d690f779a2dfd0139eda6de8036bb2509700391ee788e5088296effbd14e4953ef3eecd6c0a1ace19d7cfb1a0af28385950b9060b6dd2b875407d4a1a1e1fa3d07fe9b45a8cf841adb323baeff578f0c2c0e4d6a249a512d1236da0135d3f9408b5800d52ded63bb119e51f8fcca4118930ba8d90aec1ee1be2dfa5fb795814c4f7e333925b50747d6b0c686311d9bd0c00d9606b30b28f742426667daecb39197bc003191f92b7f0df945d3324eb2d7330b20729f32f7f182e782e13e570f0f0737e8cc810986986e490ebea392ac391f05f823c0056aac8314dedd570dc9a623d8254f0e782973c0f9685f5e6af5a2400e20e0effb97e2abd96c10c040f1ae0a99666ffb51550be723c2d30767c8fcba08867e75a900c35ef3ecc3c3a28c64526500a6736d250bd5433062e3a8f3443f03e996cab96aa0db6a50f6b33b9f221ae61f753321f85571956df108e1c368410074eea01fa289d85adee1a9e2b0d76705a4bff6efc11d97412d28bf8baef14f090755146a46bfaeba4ec6a10b27cca291f4016353a0fdaf9e5dc29afca2d85f01c6ecd40b5acd71f32b9e30e329b9e0dc055088c6de789518875f2b5c4219f30b0bcf43bf91fd20cb0150f7654a123e2f1a12a3d03be327e9610eae6c7fe7d90ea6f866f8cb4bf2772318dec86e4e70fa548321833e4c773da257d28160997802456ac823100705c0cf5a7c6a4aa8b7647a95ca59eadd1a02848f5ddddc8d96068e7a015756bd066721f758a438f041d915865dacb86ab3dfd07a5fa2b0060a0ddfd57bef8bdcff7a37153a69155b19c0b07d7ac2c9b54efec05f5d3cb21fa40905c03e21b8d203dc00044e562f571ca1ff6727ee585699977ff6d1b7d7e45c0f52766ca41327d51ebcbda56d92ba3f5e716aae70bf77c13210d82249b46099015f90aea7dac7bc56f83cc23ded6ee71b342310003f11690ee180cc9f4a6ba701cf52141890f067e5d5bb57aa2f4b07c04afc3e7c29ef6a4a157cea168ce09300f628df435ca397927dfa5df9bca36ebfe8615d43cbc90ba91d0b679f0f696d0905b76efc5b932f13ecffed9fe1a01155247459b02cc2ce60510d5cef99888b03be252493123e0403a42e73eb93b3c60dac8fac42eaab7ccafc0fe2d2f4c7b60a754663a499d5a3423ab74588658d5d35c8692f4e4165e2545a5878daeeccbf029d1d7bb94dc3f91535f262ee9a11de7326031510dce9f5624f6b03a5e30bd808cd35565ec0f1899014e66301469385ece1f93890301c4d1e33e31c37bd9ef20e3011b5cf5bc24a578ecbe6d4f7f5de29fd06e04cfe3e790172bdc63aa2bee30194e8434c378444997545d8bc01d0284f61ac7cc4bf5905bf452db14e2511ee0ec2a7efb5173417553d2f59389d73201b1d6536fbc963dff96e2b995be723d903e00619e3c920cfe455a4942a0a26fb4d43704a8d61fdfd8738b8ce7bb1b3840f669cedd06ce21de81c02039503e2edefd1c0ca55fe4c5a526ff489d720a6e10130d7539107110285fb6fa54532a00eb7eee2d3986652c348c188e821ecdaf00ac25d0bec27b0d9a4ddf5478676675afcacea9c8b9cc7f4c059b6c85a3909be0b39a740381d9008fabc6f7e04b50b6c925565f0a00cfc71af58881061d3e517056a4873a477f9562da01cd499c504d7f202c3535fb804b1765f7c7e2f6e00390ac86894a1e34a4b0913f315a9a9f18eb10c6f4a3051f7928ce78127413860cb06a183342f910339b8e1ad9805a14c1054f5b4fb2c9b25284363c56cbe32eeb80f736154daf9525492fc776484cb0c104def46f9456d1f1951e3dac1bb52d351088a97d5bd580e1ece6fcc3a8d3b79d591add4df080de958dd1b5c52fb7100c20725e748052672e3e0ae2241ac8c75f70654f0914d8338b03959fc317f95b7e801c21fa172cbc875a2a3b6d1e248344ab56eac7a0bfed84eb013ce4835ed9d12036e7c0b05d4c1afc1873bdbc588f489e961a4ecadd9455d5cd10b663679ce2d0d5075702878cabf3286c3838cd05283fbffe21d12b38f14ef6c331b9e7a4f6a06fdd451981d9b50e4757a68097b26b8db036f33aa889b865b0043aae77060cf0784979b396c263e528004d0dc5b665315e994605f21814c89d8428e1ea8b87e05125856a8d6ec3fa6f38ba862b65831463b5b8fac5888039500497043a930430d34b713457b3bccbd69f06f2ac936325441112a684ff67ffb6390927a8554a800f9a07b96f0026b59a2dd495a5dd13a8fa21bac340c0d78d79fa6c5f57db5f40264c5ff156f58d213b6c65ffc3040db37922d9d0bb9fe6c8ac64e2896cfdf620ec1b232cd5d23a5cfa7e9445cd8876828d3d840229dd7f1d9241aa9f60cc32d0fe7ae7ab4fbae1f572ab13e27f17346bb43280c5f59948e33fc66ad39fe80de02 +generate_ring_signature 7864676e28d3c4970b0debb0e6f97ea408580a98d226dafee3dd81f5a3487cc4 40d7c9c8b56934e5a5d9a07621a15fb22374327fec4fe966bb846f06dfb62cc6 1 494838f14fcf86139012741ad7732de1d344dec1773830005b3602c49e363c25 39dff26442e1ba3eda6724c73174a46d8fed8eca7523ced7781fe134b2f4400d 0 ee2886301f33d390b5ed86c7b474d9418c9eb1baee08bfbed5f082f75cd4690c1974c106b14bb58e8e8077d3f1479bca5c7c6f79620113391ecdf83af9d76a0d +generate_ring_signature 2e56246c092a45724cacd88af27591f7b36558138dc9f84551e343f3e5f9795d 79b775c12d319addb422da0e67ba0569d1d04cfd608980caecf219b65feb465d 1 fddbe3aec2ab6a7c85a14e5a631db26aeb656f75311c48450ee02dfa54a7a16f 2de3c5a26614cbfa5cebdcf016c9a87afb79822485174be1ae85544aa2a35003 0 c8b6cad60bae9ba2cf1ff82552c0ccfc777a07279b9d8c40a747f3bdab30bd01ee03fa1ceb5412e2c769506da01ef9a71c44abb551d7afd82376a9c101069c0f +generate_ring_signature 7815f1d4b85b2fa3d55770abd44e7d7111f47c5571935d9e5abaee6bee223095 bf1e67b2b20d957c19b829881f3654396a78adbcb44e985f7aafc4f5efe39231 61 d3399fe1944fc161ed48c41e5199c0d1543e1983de4cfd5d2c410f45311b9f00 e2166c3a7f15b793bd2403656e289d1689feb65f8e6fa9b7d46a34005b261107 b800cca2346900c2e4a7fffce98677cfc8847b83a5c69915a3ec51862f302555 8f8b9048a0d2f4d0e0de1d8aaf9760766ab3b9e7cc5fa3254ce88f951029b04f dd638dac03e070da9c635e93ae6250be11a35cfe9bcfdbe7df3fc5041b11e63e dd85beb9d51168206681cb9e2d07315dc15c19594df7e2119f073566d80d8d97 31e92e147b4549910056a05d60cb44d95c258ec13b82e57d1348265626c938d1 f6d071a1f002aa6b543a8f3c5749255d8c9e659e1ed46e4800976e953b82bb1f a6b081eb3489da635b97f6cb6878848c085a60d8b567f08b001ae48ee1591649 372ce8f0c084f59732aa7312dd360760dd3019a073c8cae656dfe2fe499004d3 01c7206287219eb32f90879dee2d05f3ea36557f828e4b91ba14d30c6c36273f e8220e44b09d67dd1ff189de878989324d964281b678e238dd5ef329332c1b19 226dc13531650b0de4c419171f4265fb88bf9b645396c39835a627424d3162ec 1eb7fdedfa46a4eb222797815aebb70e1f3c0a1bea9bfa3a5bf999d2c2588684 53f0fe809deee1f45adade3acf4b4514a1d437639c98cc9562951b7e95d28e3a aea6a6fc2cb0b865ebeb9047309270eaa1442c10796f8b2fced7458cfcd0e57e 214b0b9af85917ceac889de8f197bb26c5226a60aae4dcb812395e9830b7b185 59ab7c5277761232bb784b937b97290407dc2e22e0712270c18561322dd25297 5da1f62493bde6c3f398172047c7de1217bd463249a3279193df9b6068d2af55 dad11f986df301dfac98557bdcf96e36efb105e458cc3157494319b9eeb90cbc 6ed23b5f3108a39439aed73fc45b313eff7b198585a0de020ebc72543d4c735c 90936fc627704467602d21b46ac283168dc6a8081d0ba0330e0e08f7d8e9a255 0fd25a20ea3a833592279b5342ba758ed433a3997677e84f36a96bb0ed48c985 48b4d1123003cd14d0a9e7c323d1220824f536deec12a4b887a31a35fef9707d ea8c6a93e31262c5ba1be8c81129da5c5b38f4b60290a43bea72ba8a64bc498b 17b8f47c4b2ad10e21427ce62990cba355a82827add46abd01b0a9c6c2bfdea0 de19153bf9d58038d4f0c6cb613e037b2572c641f4bd71b1447aa4c93ac75438 26b47b7e2b2996a659afd62b05add0068672d724a4dc18a33ccb083bfe30d760 fc8adaf826a43673e332af17c4dcc381d69c5f05f82241202f799ab0c75bb58a c25fb0b991261f8b531bc5ad19e62b1b8055db902c2b1a435823c3e9856ed4e0 c46d960e1541d03db8b945297fb8cfb6febf632a151515ab0579595ab9977695 0411911de3280f44aaee23820e05effb2b3947eaba456a246a29d3c41814f5c7 1531a1532463934f0bc7ef7b30eb947a65f7b6770c55689506176dbf387553f4 f620c8e1ca6b327fd3646bf64dd2c94e9acfa3b4d52a008ccc2d0ad6db5ef896 82a462271505cb720f9f9234ac367fa6608edb83d33c1de3d92bbb3afba19b16 d443003d8fca22d127eb6acf6b26c0e8c4feaee60bbd276e19cdebfa2fe20acf 2b3faa1881c5ddd2d4f4b2d8a15872e4c74c1c6d3bbd54c5d1c2e334857369b6 8fec354ba1f19ded18abd2a28812c09019bad7f4ad07a12fe4c3a0f7e5be1521 ccd228e8336c7edbf92a2faf42c221b890a6c2f5d48ce59cb6858551f93429b5 c36dd157fad2ee13582891fb642397b4ab159de4b55fdc5fdaa6a01dd6763249 6d750ef9905133a6073dd0043fdcd7ef1f0d0e7b68aab2e79321b5f904a9da19 800055a80889361483f078c8be0f37c455919ee300b6fab6e637d31e00433b12 0ad3cb33206d1f80995b7ba6518a7626739c1b4057d5169db2f39e78de3e23a5 8e077ff44226cbee60be2f4d75befbcc46e691cfb60c664c1209e1bbb031f868 1d4fbec878de15c747915bc2942331ae6353e2ea2b1a562fc93b264730dd6c24 5681010b12e8f47019e0308f2952ffbe4daec078a63c6e8452bb95cd2ef6ef09 53f5417119d15c1df61673eb903a9509011c0ed83fb8a6863f8d972bd0f1c6c0 a5479f031a8eb4eae48c0881a6fee4fb3a3cc4e2a2d372594d5ff3277044fb02 c07652126a9845578a02a1512c77ac191d20a8318f1f1756d59d14e9f32f2830 8c8bafe3ce09e7721da3d52ee6d63013650d18c8482e57d501c3fd7ee5b0e9e4 f865858cdbb9fb50898b084136dae15caf9574aac8b712679d4318e9edf7b04d e318fb363e54aef5e7ddc0aa2340c2afdeab63e262688c95dd6efbc7f5a2aa1f 4b01b80161b7bcab306ccff59258d11e994258e9163bf55cc8e652416d817be8 5975d6d8d944547346f31768e953db73941c6bc1a189836012f77b200ed8bdfb f9e4bf1d84793e3702091f8ae0d833c7480e474666b169a0884cb84d6e5f55a1 3b161766200c121ce33a1ace049b0b65e29fdd307e1dcde2afa95a4dcac3750b 9e7861e59e8d3dc063aea6f094eefa2914851e0a96f12332a4dfed98f81e1f7b 363cc8d62506cd8dde52bdd490a3d3de6c3314303166ca2a8baf8e753fb3db0d a1e2e309a4dbecf825cc4dc6cb4a6675c1c4c66bc77cf63c5e19e9554de3e70f 282113e165a5ef3f6327066b407b464d2f23abdcc0a6366bfdbd10b1f65ecd07 7522f8708006f4930053063d182a25bfbeac061d4a499d1aa7687f910a2b6274 879fcaecfc2dd21a62fb8478768194e0efe3a920592237ecfad527bdd042880b 3 d9e5668d6f18f142b5a58614b132b1e323f32849547cf1c5efc29ff6c447210b748657658bcbfe7b306e750ccc2bb6a82aa41912e369bbe1602f22b65d3e7f07bd90fcffb2ae1fb2f73687585fdd4d947eebb0795596feab9e74473f04e37f0854b62134aeb671bbfcfdb696534c2c51315de51295041cbd42daa08dc9619d0aa39c897e3922c5fe8e45d59933c9c60e6f2bcc00c2b3c5e5c7e8f2411edbe1063624f26fa6763e09e9b5c35cecbb96df569e8b08628ff789813d198833b52a011c4e0497dfddc57d252e558edfab56edb2c908d5a4d222f975093dc10a4a36040995f5a8bbdad16703beb3881ee5a1928646ebeeeabf30ddcda9c236b213ee07ebfd7829abe1277cbc8adf2d7711df55834d9511b863d95aa49d6ac164ae4908d1be4a68793711ff9a69a31b49e72f54925403084aa6746ca35eb64cfb9b960fe2ca1c4dd9194f9542b9f321a7941330e6a2ddb4dbc03d4710adfc7d9d6c1d016edc722a77771a4487ceed1d8dc08535088d3f6e3d6cb0a176a29752f1ddff0a1718e2aa5bdd6c2370e0f4f5c73bc4d2b4a64382da48b968973bafa31f2ed00bf456612516b33b043aef2596c33bcfb77136923c7ca0b7820bd76fa3f520d30763d6f76bacf654b1cdcd7eef49dc82ecda4488ef4e3101514380994935ba70043e8f15bcd425915cb0d045d617f86f03b7a48725b1c074f0c6c8fb8739aeaa00b50702bad512597cf5d2010070b1b07595bdd1f251cf2ca0048ef5c3f0c326029f31d92a9be48bd82fa45373d51f78d330ee34b48ca41566f5d0d55a9a117e0c2d12b176b0db888da562ea3290c8144b8b7fb2b39c8ee8a2d7786e9eadfa8e09eae0957e2e385f64ebedf24f2b086528c74f4bf2d3907d73fa38d3e829db470be4f2dacf5cb0bf06c6f33f5016dce4a392419f5cbbed33cdae1893e1d0ec4f06cb3e7f5e3b9650ec9e2879595872adb8245bc57f323923ae088d5ba0554d540395a8a23097b145115fc1d7364509bafeddfc9ce4b7521e5c19f9c0d21b6f510a8f0c747b82a36fb921599e88d0d276a2d65468259572f8478f7794eab3314a074e5b43009b55d5c61369c35246e7fdb548d3dd6f2e55787babc64ef4f9c2de0864906a765a50b406ea7e157929bfa9a0c38d3d40776070942405ff5e52cc9900606e3c1c55702827f7d57bd2cd4f0a0f65b92297ccdc3f2b76cd93b918e540078279a2ff80f0b35023f06e61322ff75237cb0ac8d60e475341b17d3c92dbb80773ec441583f4d400c98ac6845e8542c81ec4b8fc8c89fbeaa1f860ad476e9b099e03e0114f58ceca9cbb1fc3ea5df9e002f6c32c9db1cb3d7939a066e06ac800ba4f9b587482ceaa7d3e498a756fc8aedb8fa89f8a34799daaf2c3bcf09e1702b713ac06e2ef92db96dcb37bcf2893e88d48d2838c28e4bb4e86b6aa66d0ee0a326075128cfbbf7625066751ab00fb4352a9d0492b454463dae298b9632b660722fd38245e8cc023ec6c134bdd40b1d029b3c6b724e7d9a5171b618ea69c7b0ec4bdbeb6930fb9dadbf4d65d9aba1e9a30253e4bc85903f4d3ce2dc85077290fb45b9f586848587f5c60694fbe34f9107fdd21edc71faf8403f563a4d3e4750c06eb4c82e30604b9645606cc9f3cee535ff147e5be9bedfbbb4a9cd64fa5fe0f4d980faae30d889907e1f67b8b400bcf3b0f2d55b9da858afbca8da48b57310e019c3dd275865c319105ce95d59db7284d205d242dd66028f94a4140fc1c500056b45bc6eb4a6962a567c2a3abc7777193b5a86376170d4f17c2401e2f91c300be2a042d78a7145dea718005dc73fff75132bfe013d9d8fbe39839d8cf6bd3086e0cae4af81591facd1dd20b304513b57986d533e1af38f4a2f23aba50be530d33becb5e996ba173fa189f45fb4df11657faad34f838ff2e2c07df9f569f3a0497300606284757373def299631f71706b8a8013a6cfccb1249a797817c098507963dd16286e02fe1feb3c4534642bcca05c6a3d35764cd166d603ff18d33be0d9deca603b0020bf9775d811547a3d5169c36d419f30036945954391762d1480123ef24cc93b9bd52458d55a274ff91b359457fe9188b77c2d5395eea53e42306bf8aa8a2ee36aa89e04029693f8d24dc31398e86210233cb8447c7da5214230ff416ac2cfd08fb31cb7bcc7407acef6b6d1ced36bff4a0a6e437aefb008e04043429c489392c40ac316bb950143b2f1b3b8ee1725fdc9fcbf91cce00a0fbb8084a28897842dc2a809d2b06a17756a622affd8abd40d2cff0bfa96841828eeb06169b780508e9d8c386fb8da4c2d63e03f53c060132c20aabd9a60dfd5c0d840dccd5e395f9395b42f15f698d5c4eebe8dbb517cbd089051bbab054917d9a60044bdf5b333dee103500f6af67208d5039d5e8b63ac6e67849af2b2c1b3665c403f6656f2be5c08a580f7f8e34af051e156ac0258daeb411759c39becd4211570d15f31d238ffbfa6dfc6157de0e7100d58ba5a4bccbb75a01367a9af9ce6f99034d92a5b879c73e25d81e3b736791f987029fc698fc2f40399f922c68caeb8f088f54dc16fdcb680238273f7b9ce618c6e3c1ad609d7781a0f80fa3116c83590c3df53f8e01df16c3b30f12df42633707f54f8b6c523ad1c3d3be548163905e0c8fbcdae5bcaa408c1f8d55156ebd664dc710ddce830685b4dfd4841fb34a7f004b4a75c783e2f0bc1e401d54c3057174e28d9c925891ae36ffbeee0184ca110a9eb6da3198a02db5e88e9f5fbd2c73810ce09d5ec7723fd6ec34f52100e03d0fe75c8a9f1cdad646942832fe70055688889edb86e8e0c18aecc5894e05472a04d155a070f9f05a87076a9457f8ab605c8363321df1f525bd19e561ece67e4105f58453971474653d49b70acb9c9b4d53d6ed6b2664a51c2d2e50d9b947bb8d063818286da859891dac3dcd492e1a86ef18ac0153b272feb3bb32c7d61b56be00e42856593ed9eabbdb70c3172d7d70026151a62e4115670935ad1605c211f80fad9f20a958135e787b36b92b9e057f999106de228d7543bd0a0e9506d0938e0e77b86cf4dd2f9faa3578f4377df649a47b7a19532e0fb64e10ae7aab51506a040b5094f995ef556bf9433c7f945504d72084a8ad64e73f40db40ca1e1a487a07efd843470138d56a1648c78f4092a79a3c52d46784f1f946fe14029b4a7ccb0dea49d395c64642eb8c35f35e55a497675b9a683f33a11e585ffea59b0fc8800980497cb8a4225b98fb25b9b928848f2a7438bb0fcfa0b1f71614fabd9fe7de0c5dfbc9ff9ff00a671494d9833ae8b0062c0dcf2135cee3b6a24234b7a7cb170a2acaa5f5378fc4e2030c8ced0496049120ed285cb57df2f6609a3583da40a50e08b9ad3f2535275e62362bce099f575d10c6fc066240ce70a91152afed87280079293a02f83f5b4d592329d29807a7596d86fc52aa6c8997023ea515dea81909afe4316d1e189fe9e6c0f49e165a6f77c7681534ee26ebee26ce12e437ff4c09b694b119794afc5d103b63f32b26ea40996ea076c4652370703101c005c0010f2a5844e6d261736acb580f210ab1da9e37f3497cbbfad97b2567b80430bf960db480076ce40396aa7d2a88104322af9ffa868065664c36b5ee277e068cbba30fe579925de2da9aae4c74efbb9e37638e8e5e5b6246a75623bf12fdbfc1c30d0c567b59303386beb0035690e34da91c76bc30866947cc1c327821456d731431063cb7f993f96c2a47ed70bc6e89d9e59f5209e767b7be3fe32c5b2bd15dba5b05765a2a50f860436f23bea831633f3f5e589a0e2dbe0f15f27f752dd7364356038f50f56a62cb35af38d1662d972278c7fa5998a430b5d6a15ee95a24974d120b4e6a03fd13c2b3bcc0229dc3d50385845bbb16d0945bc10557719ffe42b8510159e5eb0e14c591d83b31c955a3945282a69cb6d31dea5fd1e483a6da4226650e8e21569cd75a37d9b75687afc7d636d17bd0ce2241fb21a0a069388e331dcc04f3cc266394525534f55f6d7a4e508b0080520c31d5aaf03494877afdcdb05003f1a6d8d31ef8e07c66286cb260699f7f018c017b11c173f513fa1dcab063bd043dbd213a41db96f8fcc402b5ef4c5f4df947f481f3960b96e5b7c2045b56d20a7dbb9cdbe115bb40d27369287063941d551e891f752044b599130f94103a3f04e5c9a4d9e7e829fa35db4a7afe66e98d584ef7d73d3daa0e743b6b312d46110ad3bd699bf2935043ab2d7a41ab7c3d95a45db76a75c7e0d949c4bba5836cb5042cd4ecd74cd6be5f64b8aca6f0e36c90b9b946e9642971a5a18414c8d3063e01d8a906d49756da16f69f456d7b5e84c22802132572ad06efefc250c3a0fac50b2cb5d17c198773437047ec7452a8ad89dccae35c8c0ab4fc6ae43618072356099ce84afc5b1527e6fccde920f73b242e2e22e187f0c9134efded66c3c2030d08182af5b5d1637f214fa808f8354fe39a2f1c98a2595c78ebd758829d6558de0286d9a408e0ff7ba6951d1857d7f715dd1a1db015d046f79cf0d79b3363afe70fba5abc8475f4860fefe1450571d9c5c8ce04b72a79b2b139f5a1d6484b6a9f0f04b8add7a7d8bd8b35593f63b0e4128ec3b1623d5a602067fe78176ebfb8fd0e530d7c7e298d7dcae7fb3a1e24bd2345ee515dd30484a1b738b4bf11a07e27060b3385e73d29fccaa464e42bc0835e781f1ddc79d53e2a5cfba5e2f2be117903819ef7a93e9e37085d2fad2305b3d1f315a80db604fc467c00dc4fc8b462d30bf4145965ca6a511fc378e587daedfba4f9984f07b4b1293c16d91355d2c2070de485003e58bfc9b0ee39035731633c5745575bc4d3c66e6bb8986a4c7e143f0c7ff7b4efb46c95e36f10ca9443ad485766e9687350732626f1d38f4241f6a209757955ac6f81a4f8cc40b61ebcb88c97dca2774ca40132743a5196d23cdf6509d454e11bd66116aaeb70fe63ba577bdc6bf7f8d619a4990046e834eefc55320fd61da98686829f22b2e70e597b48de276904566ae221a8ce6352d93b35657a01a8a700fd041308c38ed8b35e940a16b7b481b51b14fa7d9cdc8123c8d78b8d0d3154fd72e954575f9add4ab23b5ef6d63fcfa923065a0e164f008eb4dabe320a51339013fb3fd8cf9fb1acb930a3018eb66c7038ec8e9f391342abbec60e830d0500479c6e825b59eb5965b6214d2a76e774ffc1a12dd0c78a141438bacd930da2f82809cccfa517f2e6a97e79f83c27067febb7460384a6094d38fcac97ed028d25bcd904234a9ab70683e0ce71a675846705994c8fa6caa9a2b23725f2c205825fd00c0b71da03e28eafefa2ef65bbb794f603b46ac425e1dcd060a86b210d01275d4bedbf3ba5c5131a539476da2b85b36f59eaaaa7ab00fda836bdf3d207ad690318a5b4b6dc22a1b02dcf3e08cb6bb005288a267acb880253cd91a85204ff6db55410b720c2075773eaf6f415b3cba32647a3ad70eeec2386e355c39803 +generate_ring_signature 4c4e0ad8f2598b7d77a053302d5a6795c381364241b30287731d6c7d063e5253 765d90a45d3bedd3c6ee22b5783e15ae9d418c64dabe2683135027a4e0f0d47f 1 f0aa7e8a8283be703ec37480d9a1e445ce42c58dad7d275752bd8ffaae075f9b ba659efc83361288e75dace789db89084f3970e73518e0e8d03f939eabb5fc0c 0 9e75473b1dd006a5b4ac7e448b900941be1dbe8dfd7961fc2ce8d43722823507f328a5882a6191dcf6daebece2463c36a9cfe197362f3656895695e112da7c0d +generate_ring_signature fa75d79801a1ec122a36862796c333cf133a930d25ba2faa3cfd8401b1ce65ec 64c40ebcf87adc0ce335ff113ed46236769df40a1bfa9dad5ef83d8babae3ffe 1 fa560cabefb92c708a2018c978743b79a348ec2c3908c74c44f619d4a437c2e5 c6f86b60576c5b4f0f03bc9fa8a52482cbdb490b0eb9d99b79e319609fd10c02 0 3045b88f6affd09e51c4b72538700cf7f90320b2c722f928648868df1a927e0918d9df6692ca5e71df57f2db0223a8815453c8817345ce71e3707f671e9c5a08 +generate_ring_signature 7c3fb9bb3ee4c42954cafd7b2b7e8cdc0bc46262e1c01911002435bdbbeaa392 bda43de0bab94f0f16ba11829801217e25b467af70657b746544a48667d928a7 196 3d7deb9d2aeb577cf0188c2f8e3226415e5c4f641e83da62745d8f20120a2c46 4f74fe1cb3af7a94a70f3c562eb98142765e1dfef4baf9f38bd368b922515c10 ba66623e0a2b563d871badd3c5dc6a1492d92839cd3aa5d2c0eb5f70c5f79581 71b8b0d917a73fe39ee5f2f3113a90b9b26abd07f56239ea5b326544359b19d3 eefaa73d07640c1019bd2f642cd443e98832f82d7890c49a2ea7d01abeb71455 f9d84b3c3389860cfd7499393b13ddb2d1d47ec3c782fccaebdf892d7341fa19 1b0bdd06f4dab389ea44e9d7d1005d501af618687d00940c2443b84e40e72136 3e1f0672ef333d52cab1cccdc601f87d010c82611598eea47c8b445823f5d489 a8aaf0ef9003a56517acab915650d7dbbdd51e702c2ee3d84f3e62fe0d8c86a8 eedd4498a0d2c6810091b0dcba02ab3e34e8dd4a4efcf2dff9ab5d91056181a9 d020f2842103fb4d38bc130cd14439b4a4957fcc666dfb3f8e9cea602d0648ba b2dd26957db1ee390466b7ff7b84cb95d8989a0aeaa0ddce683b254390d6a6cc 4b72466a6f2eb480af8715b9a37cde092b5beaa597f4e6e00746ad6d2d05b398 f921877891f56881d08de5ac9c2981c54e6c1d0ae2b16c7cd1a677b198864ccc 41f35918409892706539e055bb30aa7f2fa282f432e13fe769af5b0f636cd69b a2b4d259f5bcc195075eca1ff07997b0377cf25d771716bd4560238839867e8e bb4fc78175626e852e68fef83df8968ca5f5c4f81e1e6112ed6451b9d5f5bd7c 4edfcc81529f6e8888764bc5e41a1fede7049dd960f5a5d197f229a5bd1e707d 58e5461abca133964190a634685bd0e149628bb202ca0d5445c7a852765ae82d 0fed57463cca6186faf243735eb3ee19296afe91474c492f5489f8ca8a9028c3 7274df448dc3ec321473fd02de58ae70c0e27cb95f0720826d7853fdbdee48a9 add935fdef42a91396a34e19659a13fff9ee76b437d4084594e7575a3de21b4e 993ebeda5d18e86f53235876c9af7e6d10f3fb65068da9bf3afbb1abb464f52f 1099ba8fd7f7cc772abe480fa5f216bfe48f46e6340736f452f5e59b10182349 1c5a734cab5a13536221c7f83bebccdcf2660425b358a30a13d49b8a2c832cf3 c0d64b092dc9db3810f59e3fb8feec10188f38d31e227adf80496f775becd04f 755a97fd034508b8bc2702ba1250f5d71ce48e86c7e351e86790d2ef1ff825d9 e47db52ba46c257338824e3adf22706fa2445fe44805d4bb94b5e0ad8c47df7d 6b2ac3928ca6dc8ef22afaa034f66fff380bafa2674a4cf490960fc8b560dd9f 9c1aeea7d25156d1a58b0252704b71b3db0228f17c4cf95ea71b2b076a8b210d 74215b03d16e45d3b251a4c6367b54f8ae438f6965167fe5ec3bb645a5885bc2 013aea76e7a4f7c15338d048a54626c8fed0bd291661963e1f3567923b1eb93f 97c048ef8421b828ac7c75253c51ccd77e427a6ca6390d554abe773a947e24f1 a28841ac91711236b0e4e6f12fd88bbfdc09e269a6e26d7aaed06c3702efcfa0 e0b8ac3c9851b8aeba1edf45b2fcacc18d7834757c4df91b1e14b102b215982f cfa5948f6bb9b6e5678f5fe5c45d266c7c9fee864289ca3dfa79ce248f0c0b79 db95bdfd0f2429c78c806dd772fb934c3acad4fb5f7393e25b521afeb6a35c38 6200b0a613b936303102722aabeb1212b78f6af51735a3f0d96bd76058ce0267 79e29d799a6afaf916f0b5ce30feeb0eae2c9952c1ae4d7708a24067169b4ad5 20ff221440a6bb518535f42abdb4d5df26b3297a92b74eabe8d660510d103919 5fd147c22101ad4fbe7fbcd32931d55b13c55cbad3db68a1ab3f6996ea25d03e 01f4dac1ecd9e01bf1320587ec8674b88d34205ca51ba8483ecdd27b07f7ce02 73227647ce4ebde477e0cd99631d977fa049e3f0d016df930d38794d45ce7c32 829d500cb72ccce0680b7445877d1b1ad89f9d643f7429aa103a655670501f43 3f3f0ada3115f1dcf6079c0867c0c9e3c9ecd63c5d02920b12581cd67bf4251c 9c0a5f030055125abf6ef7631709f06c386af32ba9bc659647f6f6b349588245 56ef91cc69961d6b417ac27d82ab9a7c1b56fe8ed7935e6802487153eb8bba15 6943def5c2ada8d0d78fd8da01a138c16737992bae209444f4b02d5b96f3ac2c 3517f0a7f5203714e1b2da2723af527b99acddc6b48733b6cf23d0cfb6a4afdf fbec53b91419e5f4c1e9ea47c499808c27055492101ce15c85592dfc9f87fbbb ab7a6bc753aad0d5485f332d260f351b75115bcdeb32d1b0a1fd0d8421ee9ebb 6d24d7851f0cf26a3ee3d3c29f8e69f4546c90d9cbd3402fae623e07d69b022d 1ec91aa4a3898b66a1ca297e32940ef75bf5695d62408b11e46b831b25617f09 78b9628ae4e16b74d36ededb48245ffc70fb823ea0e2b7effffc34d4dfb8d308 e9980856b66d6e29bacc3272d8d94ebd638117ccbddce2f8357dd45ca32934c4 3263b10bce76a36c53c3ff5cb9d439c549c7de8d9e3e28cc29ed094ea304ba73 7d15f57f8ba68ad9c179b94a752888ca27480d439b13bf7b22e0f09c30890c29 76806ce6f9f66d86d585658d049c90b7a55d55035e7b9f426f2afa2c295fb6d3 da9630706b7b980a5e17e988ae2ff5dcdd0928d3baa3b736ff8fbcbf5e6acb4b f8da823972eefbcc84a68d34ec0cb69538491d96d8b9a1ad25ccd89bca2eb227 2649b2831326133828b22a7ae2dd1c2d794bc80fc92fb219bd038e20b4087aa1 41dbeab376c0cb3badd9ef47886d8e91a16bd176babd5c93d4222eee59583951 507d4bf45b583eecd177a2d7de1d303e908a9e7b326ee66c384074a19d0e8986 c4327912595750e1b4c774dab82ff6251392fd3f2901ed495552ab943896afb5 de7c4677a46a08361d3748d31c1df86d6a677a46b2fc52fb18cc8c17e631f9d8 bd154b97db57d73e1489e4aece2e891cc90689461a32ece0adc0252f2ea8cd0d f85947ac2d27b169e3f8668cb5d309c93474e2b4e39d303ef00cd22bfb516488 ce68cca1c16786b5f84d2d1b6be185c50bb7e06b6587fd12e88aa0ad55aef1c8 fbc677f0efe1e33b870182a6c970805dbd587f7341577ffaa2ee0c20e73e2b19 062ffbb81d55a0599d07c2e7cbafe69b85f1562731b7b6ff29aef4910c83f8e2 516bbc709109e873a712e6ee502612fd247531d24de032f46d104c6968887c99 147992743e4b8c1e638e6c84d6b426544cc49051f098366837217ec6839b2832 283508f305a819032db1b7d8e5ce5f6e9c7591fe555558d5e18c1d8308acc36f cf7ef848184c876862e4414cd556f787f880025486a4932ed1428ea22ea83e5b 688407f0f2c3c3e1d46c2481b4507245be9e897b6e6bf2f71ec42ff60cac5233 eb82880ae90623b8601b37b8f7f1cec0cf463aaa4c7041de35da6bb1e8dc3383 be18599f4111c5d903acb9dfb4c435768a3003f1ad1428472263292dfede4e14 036c74f81ef0d9812c60b77d4d996fa358d1059b806a17686115cb91fcb891a7 56c13bdcb883d9ba092af5ffab17ace1bfbb6a020c562e12cb02c8ac4aa56d78 c0e519110a5cff1bd58e27124f7c2ada7c4e337bb8c6df93c71ae1e01c862bf9 58596e856040f9da1b9996da7ecc4eb82201b92d45c7fd70f7a365b95bb58b1f 58c0e7620d52079f74559b40e84bd5206ff697e8a96a236017d646daff386596 7d9971daa6d9b033d5fb18153c941f468874eed0db6c31597e7339d0a6abb824 1266519036a3cb221de554081a56e9b6ab0da26dca30dd1cda0a08b8f3ae2e53 7ba8112ca27bf3efe3fe5d6f839dd7c60c904013e0c299fca13447cdf4046a17 23ccdadf7fb569338fe0880f84c81c843d32fc8e51d53d0e6cc06288441c12f9 89ca3b7d4bcbc5d983a9210c8e25a5e9ba55ccb51399dc4f87bf766e87a803db 8e1df71b815b60d01596821f77f20e8ba714e13680e4bb57c3650110994106f5 56b73066872d8a4b86f780e8d9833dfa56419e278da45ba5e2db20bffeb66577 2a47099d3dcf25018cfce34ceafe9d87438ee4186c41490fd403e6e42b5c2d3f c7a3399f0fa1dbbd9976ecc6b4f939c860b4af7115a14bbda763632b1427ffd4 9e95ec90e3f86a6ba34930bbba2f93439766b2c1aa20d6b372f53aa785ac6503 77790eee24121080bd6cd771633b58fea9554710b771021f74d7438a99bd783a 53a887bb398735352c8b991478de995167951f2a985275f2c38102937bfbae4c 1bca9a852dc22ba46db7b0bb5793346a905a6e45bf2a7373dbf8960b5b42594e f03ce64633d857f3d0f4b267c6ed14e3a82664338b26159ff25dee6ca784ebc6 7d8524ed9d52118efce4fadef93e0a0bc66011bbc9877e66c9649ecb16aedcb3 cf65cab677b16ce2e76b2e675de6f2b324c6cc4ea82fd3d9ef646876ffc59185 d84478e2ff8128c73b3afcef77cc2f1d9f08a49ff3f0587a3a6d473f55e0eb53 f59c7d8fa9eb320ed90a86c92a02ebdc016390dca8c9722170dd5198cd1e9579 f0b0ede5391b6c9c584a61db76a0cec84cb1640472365fd278f6cd5da4946921 07cd121ae416d38443e3f9ec281774098c4779d712b0b7a85d31721c41a7044b 6f33a40ba6f6c8fe17c1f387b2a15a440afc0b262628c8c189ec936c7ccce868 93d3c1f4187815f7afb9bfb316594bbb7bd194dabec5fb906b83fc2153b4e02a c0514cde62fbd830f585c13491d6567b0e287b3b4a7ee7b7816b1e91a34637de 175954ea8c7a717813d62813e3af15ccd10935e95aebcc4ac60473f3d24de202 7f3f6c6efbc30d15995a2e1ad3d5baf1685f65463d19b98d14d7c22edcd33cee 8da94cd37f45d0993b6f37761dfdbe699fb00446e37766f1a8d2fbed8919aa26 ca869ef84d9196b289c84b0a0f90281d787a4505157eaa91f4f1f6b9e7443a5e 2eda08be6e1d26b9d6bad8360c5f30c2f47af50e07b647d69e0cb6991fa37898 d3ddc6aaa0883e6c155f2118c5e2501ef8d182593518889792e50b1403a04246 944b3af2047b28c5bf51427b1c29242cf2a2a3f6882c6fc7060086bb72ce26e3 44579a1b2fb42179b9e10e232c9d11e1cba5e6268e3e27e22fb292c75b550732 6713824a19a140834e3181023eeea4d9090d4c0ef7938ca5ac760798807149e3 d99e86bba4142a398a2dc7852aeaea64d710e086b241fba4fb70ffbbfe4ebab0 241c2ea4ecd5936b02fadb15c2d763aabad2e7531892a1448c5cb1b2e540a928 6cf74d18fb775f01ceb9222574d0d704f7efe797b096dae146c2d7f860d6ae60 2df994259a9e9279a8c08f7f37d1333cfeff7d4c9b00e273ba0bffe67ee91d58 e1f86f218491f4e1297187b600e17dcae2d71362b0aa051bd241981b4b694902 a85a6b762a221ae263dc0f8568b23388879e94454b9b588752e1a16105e4efeb 213b0ee105d7df0ca3e893dde9f50a57d0ff2e91031cacf2cdfc6547c07d189e 9c5879307b9d6957f504d1b2cf3160fc787f747122abdc423526640327ac59a1 ec4fd6c81d070ee743061c36568f2e02cd1e1b75caef5aff94a6143005a49994 2002f3a945a9d21bb9949e8747df9e40c1bca2d793eaf979ddae2c712ee6f85c 3f0eb01b2613ed363e129a4dc8d820fe325c25911d8a480a62159c7c53ec845a a8164cd59ffdbe57cb56c7c049b1e95f3693b0536831c840febbce5a723fc5da 154861f7eb6cc3253cffbfc3bf8e5dbd79171aff9244a205454df5a827bed731 224f573206dbc13fa4621c6b73b036a241ea25619c14628b0d9767743b7c967f 6cdf85e92acd2dfd4399aa1bd45d803ea3d0794c76945e2d80274f53cdca5f88 0d3b885c422d389a29a0928d6b09883f4a309bde6573b495c6f6a268eec2d519 428e5249c0abb96946314d6ae67a91339e8920d2d6df6bd2ab01618a81d353fa d699f8d209ef4bbfbde089705716e162ef404983be581dfe016e0c49a9302029 9eda3826a1477e2c37e40e687959331664ededc5fc4937d03e81da5c0b34ed68 f8fe870c71cb553166802db6027fca173c85ebf0f9537430371b2ed7c3a3764a 622bbdaf0a8dbc4430d89147f9092de7a2637d0c5ca77d1a2269081d85c3dba0 5c372dc15cf0c42e3f359fd4c1a5c2e1a019414a400e0ebd18394b96a40c98dd 91bd292ce4c3c68a5f2579f90b4a8b09b8030e31f7e773ee844c720b079d1e2d b2c171f58346747d6ed7b02fc65873f33b7e08ac8183144fa59ef23f2bfc959e 5cf6a61116fe8d0b9f4804e6fbc07af6ae15207b392c8783e404d5fd293c543e c6646612e88da493c7944943e2e7bc2ec432410e0f43bf7dbe63545a306975b5 ac6f8b9b72dad35d5cc636b93a3b4c3dc77b0e2ddbfe90978be8a66e98e3957d 83171e32bb5e628424811c615deecd0f89377cb0279186374c36d874b5ce2a2d 474871f34e82e8aae1f236fd7ece6b9bb8d9627d12878e64fba94ee0ff917e90 697ac8f1dcbf582bef5162d945b2dc2d1a1969bf59161c5aa4e6ecdddbcc6b75 d0ac304d9ab860d7ad0ca2ba9b3a2c2b47d937051992b547426502dd8cb74fb7 775252729d52b7fbcb724b63ef65d2c14607fcd3f57cd9277a10c95aefcf682b 8e3523b50d6ced51c5a82b2aa13f2d498b504ecbaf220d23665f5c55645faaa9 40460ae2f74bde032b31812d53a373111a7f3551e0360aee6a0a5468324b29bb 2a971e6b6aea6dd849df590900fc1f2f527ef624b7f578ce23a43b7da1766ad8 64228053b65371ae1d0a5b3823c3bdde6ba4e9ab15cf84525efc24ab7810d7f7 673629e04c5f248c138f987e346d6f62aa8b70142768ed8faf516280f1ea6b56 aceea696d75ecf12f55924214699453432418a6ed52b2954dfdf1d6eb66028d4 124b855dc5d1164885ea22ebea5849b513932aa42feea0df88bc146b26062102 2043c7629e30d8554739ea06709d746206c08cd7998b6fe7278022855ec96f8a 114a9e312df49f4650807d8d568da9c868508d970437d843c14f23a5b5c745e0 c6150dab7d30c4a57bbf9f74bddc9775d86d26bb9c51496b5fb0887faf32ad8a 24335733fea5102fb726536a5f8ba5cdf20ff37b4f7640b116dc72952bd617c1 bbe2bb771c7bd5fd1c79eb68e58bf4d49e0c45c00e274bd5876df1049242a729 a3ecdcdf9b4af0bef4676d65a25188742351af5648c9233a76e1c75a24eb7a8d fa75c3f4785cb295c8e4b7cf4f95e9cdd80cbc14a9dd67a1ca7d544afd7ffc17 b02c22ee4e0d7d797a6d7212759fc99de5594b4075454495f786aca12e919678 c81e4d5e4af72bb134385df0131616470a16e312f2e660610045f5d3031884ca de87536fde596ff29d65922de1d67d596238e5a03ac0d4e5251dafda619a838c ad6c7c271779001b676bc498d945e90fbf6ba0db589c5b2d5a2e4a74bd6e8d01 4aec1dbdb3e2c9c272606ee77ecb170e6e64b0c857ef9790d612aec230a8475b 82ff743e813f4ef077ebfd66ec61c32a27afb8978bcdbfa69c8b8988998acec3 5a0af108c17d6deead0149accb66158f8246d4939930b8683bab88c17d30d30b 0f46615ccbf367984b3a89a7648d557ac69848376fc56e77ee796dd124ee47a2 5bf94829a2e3afb01140433a9d57e8a59899db28f19e64aa46ff28f5ef64cec1 3e01bf0f93e546cad6eb526f1249c1899a784808ae940f4d15e0a896191d4e42 86e649034e59402ab71e9e7e577d427d917a4257d65a283f1d7ac023ae559fef 29a914d0f4951aa24e2f0aa63b1f537c2081b11da7799a70258d7651a35c5747 3f0107399325655f8b6b33023796e8e55d75525a31a9e5c256f24cb23fdcadb1 6b052938fcf90cea2e5caea0d9cd4e183990f1efba477314b8ed59faa89bd34a 1c6a32ac2c6d3cc6541da9afedd51357bd81172dea1eb2d03a1264a988f761dc 889927d51a0256466f031595d94b95fdf732708efd504b9d22c6ff54aa3d4c59 c612ac8c54634bb1d7cc614a177c03d4b0bcd024ba4a74a43827af518ee607fb 6bd3a9348b3e2cf91c5e9431dce292fc2c2322d07ca626767479639c654365cd 9deebf112490cc58fe510d7aa8c804657bec78642f236df79317165cf2f206f0 dced935b8c9df181c26a925613e96193d52dd051f2001e74f9b7e6348d9148f0 3f6277b2f63bfbe985ece514161452767ade8331f20c40f3f0d0a1035419d533 4d95e5dcefe000349998e1a3130b7a7357453129503423a0f02683aa941cc0c0 84bf7e3dfac85642c1004cbf84ca5f9efead8b8fb4ca98b779e9e5f5445fbcd3 c3aad5fc72c27162dd18f9fa38b371cfd98b70b885ce7e0c428527ca7d8b7569 c716e52b55b748463b4aa1af2f5e178536b0ffb6bb62807d0a51960ad5cff40d f1bcbedc26b50cc7de6f7ef24a1f98d58564336922df6e6f4a70337e6670c6bd 65323b25016172bd154dd7336dd6beba5ef6f45a8713797a6ee39d0979c746f3 4204c9aae42fb89fedb2270e6e29eea1df504c91a9a50f33bb3cabb506412d56 6113d4806a2e2f16880724d125ec7fffe7c1292ff38cb6c6eb8a8f5af171d781 0f022e7bae4d0615d72527758f20be97b6ad2a574830b1d6f6c754ec4b478a1b 25178ef51a568a7d23ce35b29ab02a618185fc258aabf3ddd01fde845938aa64 f06519e655fa5a6ed6cc80efaad8db30ea29324c7dc983cbfe0f3e931bd5b558 46b4b06ccdb3670d7027499daddb0bf9a1269378856cec1700cee91ecda64497 2399b6d1babe50a8c854a3bec66c0e7cdcc7959b03d8ab9f7963063e3ee7cd25 a7a4f6c54713d2f6305c2800a582092aaca32c34b20aa07d0a968cc1ba45481d ed82f9e92b53a19571b5366ae203f7dcf90f19fa2edc87335726fc22dc09d81e d9787436fda6cd8e5791574b3aaa0283ca7c4a5ede9b2433376ff45160b58a0b 82 f6350240249269b83ba4ba4695f710ed6ec9b3b5b7b7e322883f24d712cd2403da325188651210c0a88b8b443257a8f760627b3633be35314cd936a3f09ea4073aeaa7d8baa8aa301e435981e035dc2d212b764fdcc9fb65a8c04c0b39086d09d42abd7a8d438dbf16bc1e4795091a00751d2e5b554bb0e9bfee1ac62f014f09593122988773fe35936b57d59db5476dccef7651fdaa0d273fcb0a5b106c3c08d9ed733e2fcee4c97f649380b5665f111047a6fa4736ca70bea8f3d1c3a4250bc8a3454f9a88323bc670d0b1ac52e8e08b66c92505adaa95ada0b80929d4d30475be64b13829d5a746d2b3f3ac654388bb8f63e722da0740fe77996751cefc06558d95bae44b05b1351c6852f8176e3475410c4adfa7923da407735a44b711067e8e076ddb29749028333eb2e7cd2d3ab0c0b886a97acfbeeef0a5f1edea3102c5cd8fd617cc727530c0982073b9c94b2b1d7ff80a7c2e93b80182514f2da10a122fb6efa275d9aa48a14803913174b2c5f947f88891adc4e0bf3878c9cdf90c18f1a17f51e8ae766efface1df8fa0483e35a72e95883d9efc4a443ffbcd350886c158ed55f7631af84dcf9974319a87bf6f8478f4bf23752271b2df831af700d9ed970afd8d9f0cf599b4e5ea3f7236a104ba3a82b54f5122441bf8158b550b86367ffbc6d71137dd9eb048ec554ce0c6a88fe2cb31157a94644f1550ae6603e12f853b47924103dc9b347126d47595afe689be4f36c3340aa07447987e4a06aff100f13c793b149c03abb26390e7a26a89a4a3321ff1164621fc7b87a999000208bf895c9193f87ad6d9649e9d6a37a642ea3e1b287729be0ee6bba6f9c90ca625305d4e2db3c2252a5b6a62e8ef322ccd2b2886e78a6ca3f6b5b3822b1804fbff9ba2c30b635a24001d013f1b67183d3ea49501c1e1cf2ca5bfd93b55dc05cdb228d98043d0e90a89406e0e591b2f90449a33860a2a7bd985b30497d1bd0545e402218e840ddb7b3f4fffb00a90295e611ff5ea05e4c0ccd8c7760f110705c88f997b8a3a43922e5df0b61be09b236feecb23c40dcaff412a81b5d1e1730291d0378e9fa5f737c4b8adb94ddf9acde32dc6954b2b3b8890254ba4123e18059082c254010e93de39be364e7f31f67cd0c7afd22b9cead93d7cfd7eb647a40dff518c859693cb36300d8f3f425fdb3895a407fac43228cdca6b431e551df50f874bfce2337677232892b364b8d846a6fb7417e85919680b2b7644a0eec22b00f7f2edb10a7075a67ce59acc52cb3c0296005df044afa5c49a538715cbd9ea037a14b1ef399072d8867f70441c1c12f4487b7795413f5c4b9390dd59eb58d706f6ea3212cfa6c883885bf17de4ce3b38788ab699becbfb6096111f74ba624c04fb34419b03daa19acdbe83d190b6772ef62a19a85a59c43422d87e9e92d59902fafe568ca0e9f65995d75dbb75afe39b7a04199be7a1d3eda5569be6da107c06f163728d3e70758c9824f8ab7c6dce1af9f7efb973d1bc92b6833a3b16e01e0f57199751c9c678221e4723436fdbc32622b44f9e70a77b1c461bf7a3709a900bf39d71a686e5aa8422a20341bdf318490377000e467e390d2d3fde090eeeb806abc8eb321a1f3473f93222da9f7cc423b8259a69ce1a7b897e8e000fda4a5f0d2f9f046bc6c32f4460c063a0ebf42052d50a3ff445f9fd1a7bd546da18100d05f2edcd3d4d8bbdb990d4ed11d66184515eb595e2a683e348d28a65cc8634de0b4df2a7229bfe47ff76f889330f05c8aa7d7bfb628b425f2e0ca9cc2c1171ab071a8cb373b96533d892896f7e19156bfd20197d0ea8419009b1cf22458dceea0dde173822faf0a3ac17da322c885782b3593e39f440742f72397e8e3f8c15a30494dd94997e13198abf3e37e7e401be4255646a942adbd493fa44f40c376c0d070b67eb0cbc008b598eee224a9698d99fc11e689ec51fcd35b9bd2a38a3628f0f8e5c0180ae8219774da53ac6c2e71ae9d84a083c3371bfd491497d80e6a682055b7840e0f61df614dd1e22e3a87432162888e7d15b9f64c5a3820584f9de310cd14a6dc3002c6fc5e2c80a19d360ca95b384ae33ee8f8dcaf29bf0e2e7a78d03a137f4632eab694b217cc3bfc5a1a0ec1baf4ce03f573b0b4d153936ab82730990c0aebf8e429444c26c7dd8038eb16e465d7d51545a9e6e7330cc4e9e9c720529e3da56bb8b077c013bfad5b86dbd52401fde7d9d9e1c3798652c6a1ee0c00ccc74087e3a9fed0cb78b2b6532c645658459239e2d410c4383f672f2977d3f09f63c608b3d76ef20f97c4b57edcef1b1ad6e982625a67907c214dd4d6151ad02d414b1c4abb3f442c1d91d42b83dbc5d64f55199f675d613e6c6cdd7644c80050551eae8b0d36d8809c1f4357ba3a4486c4f881b7cd8506bb0a8e3a86b57ca0a1c85fbf97e652972503ddbc33a8bade7e0859d9ae7fe1d54fc6d211db533050ef9f94c06737eeaf8399ae4d5f7a90ec6b1c5d87c6938a982d0951c90df7b2300d9d261bf1b60a962471a42014a443b0db313de41278f1b8a459c71fdd2c9500ac4222e8af0b157f89e5889fadfacb299f5dc5fa8ceedb5f392090633c8059a0a9c9e55da44295482fcd02412755951bc77f979c768344f436abae112227394067066199773c7ba88fb6fd73b7740358bb3efcd93c279edf9972f6067c8c1940074f4e5195b3deaab16528994bd9965148c39196ce2753cebba6bd464c4c8fd06b394b48323b1e68635e0faa4280cccf9f15571d96552c29cc5a6ab34516c030006a90c34de9ef01deb2a692da67e3c52bcc2463e9f5636bb38eb32812ca7ff038b211269e6eee27c1f64056defccfb589186580a0e02dab10c0a68fb86edf00e6207072eedbfeff52c58e90c62cc38bf33189703960d60d6fecc9e8891ca85028d464a4efdcb52f5ec9898b77c2adb62c0fb434505084ca0410e2c804cae3c00e69afc48bbae84f62969737ff395ca03b3b31bc2026ceddcf7bd92a3e67faa07ba8c65b2bb2258137f223e21ec362f95d39ee0c6acafec66362f0bc672fb280a6b883a662361413609978b11be0c3064c71f325988143042d9b807b47f268d076d5d4e807a5d0a6984df81737c479fcbac6f6dff715b2c5d6a343e495ff2b80f1719a721a9b8826939f8c4aa7b4b83f8fd6378f07407aa082aca25a64431f500e9852079d1380ea05fc47ca6b665339cb9256e3348ab0b78b7a74f0ca2c2250826497d92cb02405fd9dc99e4e1fa604aa57e11fbfe1f2aee3c58d2c0f141ab00b141c9cc659d693b4a764a298da0e80f797b88a8c6d0922a10ac650abd6ead08a3beb5df09ea0a2ffcfc03e02638ecc1014a31a1f26e763abe94a153d2f20507e5b3674585dab8a95a85351f6fa5466127c37ac57707f9d0587fd2ea7e6b8100d019d24274a0140619acd9c0ba0a20ef09702c4d873197d4db29288a586a9705948a71d9a4dc22d209f6481aa913f1a519ec0d881ac3c1ea07f5ae2b88691a0bd43618e093ca31c99ee842a2218a1effc76d826c42c11cc04d301983c4e3a10e21b101867a044da01ab1654670ef513f55ae830124058d814ecd359aa175ba06854920cf7e3b430f064f9920ac09f5c6167002aa65eae2e0af13985fb3329c0809719fdd73947bdf84ff5e935cbeaed2b6b931e7d477b314756e3d18b6facd043062c84ead44c834d4187620fcdff44c0f3a64120900775141fdba2855d7d00f25a6a7a1fc21261b51854cf6d159cf767d9e233f4a1e2018fdac49470cd18d0f36448ffee53314787c44607ba4b71128b9279f43eef41d614b2615fad9b8f70538d67496496365b1bd714da324212dd9c4c2e60ea34ba1579ea54f9620d8160a725c27bf2fe60bacb3130284ec9e3df41243be21240bcfc82d3e8cac43db8606d85b8c7309c7fd24e6fa047d1f5c40070c1928adcf55171a9fe5a95d46cebc0b9a05af9bd49c2d28ac5da32765b3e2e64f222f680fda5fbce47e3eac66cc510444375cf3823302b3cd5c97406896ca931d78b9696fa88a926ffab60ec9aeb80a42fbd6f741568cd1e2cfcecced70d8d2c93d1e4009003dfa49af4e844216f104f1335b65757bb822548525fa68fceab34ab40bbd5f925c1f94b53c32c17ea6097fb89cf9e7bd36fa3977797ba380843b08d479fa47b5857c152bd22e7977b80e65906fd18a5268546e081e85d6befdaaf3c4bdab8d03429c81f4bfaef06f110123804f7710fef85cb19800a5b5c381cb85fe81ce4fde5bf71747de61943f1a00b9befdacc4ede14e0f7836813830cbf9ed38a90cc7fbf21864991b85bfd12e0bb241875594de4aba4e9d6d0a1b36d5b139746d34e885e7f8e3bbf6678fb411074634b7b7557b66ae7571ac9cbc56951df39140b3ea7d64f9f9a89d4e0a4bcb0562f9eef689e1bf86c10868e952e06ebf619ae25dd39f65555aaf244c1481ab0dd995640e281ef327cb9532b2099c61856ced7d73904e0972efd9bae3c37b8f0c3a6747c3c8968622bbf2b2aba8b3ba85ba62c526a28e736143d61eaee37c95038cd1b43fff3ad42aaba089896678c1e29844cfd7a164418b7d34d7e540f1930630d68e1b62a2eed14924c1860dbfb0320848abaaa5badeb2ad70782428dc0f0362370be553d27ec964c927e75bd309e6870c7815b08ab4d3511b592eabf561080c2249ffbf238bf7ebdf73e301e9b3142ab71c42e374d9b51ac24fdc4bde9804a2b87a298e5384b8c73db89349f3b34ec0df8f2ac5b18bd83f10809eecf067063deb995376b3b92b51e9a4fbff1bf671afe97016895ca72bebd874688bc19009d8a14e268f80dfba9edfcf4f2e17a1dbd2233b79ddfc3d5c9388e10a830e1a0984c8c9e6487ec31c17c2403648e50cfef67b1d47825540d72f37da28f709cc012937fef6e2d5ce5905fdddff04bc275f8ec83494e51393d78144e1628512000a6dea0714254e3d68488a25143010ba0e1f5c42828e6c014158af4d3498a34d03bb5f7ff5326ddecfc3fdb8403e0462339d679a1904802626724b9be3a747c306a2c4057c30dc64937f75f3991d22688c919f4f6b993b4c40adffc49827de500b03d6920f2f0f578214b2ba8ca9c9ebac159fa3f4ec5702a8a956cad8a288b5018564f3f020f9add5627657e9cda655a725c1a81c1b065750ed35983ab73f9e0f543ddfc88c0c9587e47a8352d50daf3bf177d7b8258fb02c17097efde166a00978b627b8442ffff6478ad6fda3820dcdf8066edeb1223d7d76ad8bd32c48f40be9344499ef950180ebb5b19ff218c0b322f7ba009179625076f64fe087067f090a5b33c004add071f32e7f253086387632d822faebaff2d353b05e6310a5f508d14c5634d649c161938cdb4b55395e790217918fa145171ae53de2e225433709791f850c44c1606cf28ef2b9c0348f9c90d15f85c3a5693559ec9f9dacf51f05a01edee43644ac7820a7f6decb2171ebd5e03e8478f79054cbd10b3356a3c60f3f631726928147ed30c75af4bf2c5864eb04b4b4772738073367c36f6ffaa60111cbc61cd34915a4fb8a406e0fe4611ee28c99951ac18fb722e81602d3f74904326d17759dbb8dae65c3647044ccbf5f79477220b76b2cc219932fda9cd5340ca980505cf009be3c9a496d68f93ca3f52c99d49b3dfaaf71bdbf71d093efc20018ba9daf425c152a6cf945b30751ec9a964e179d67b01db5d40a1ec477de6001c19a0a336fc28a1cc77a433694bb1c543ff015bcc6d180c0ddc5d8b2723c1d0361a2f9aeb168f4b5d784caeb8b392783769c3445c5ae7f30233323563c2ef206b6d07b69dd7003980b555a2153841157721578804613e674b1c216c4465fc202cb97a390855f13363aadc55b096452d33b1d45c29bf2641a7ffee2c792c8990e2d87d138dec9ca8f1307b40253a7ca159828782e07a06a8cf9e15c09c5365e0502c104a4acef1df809f439d3d9ec7f4119132963b2e66e7dac6529102b84e60ea05e061f51e3e358b723810a962ad21e7e3c68b826321c18a676e3c8776d4e0ab854c34a34b2dba312a0b8a662126021825672fd6a8ec3b6ce1b2bdda2aacd0054ef2a648c52aa2c8c0e97284e8d43f6e51f5aef1c402ee14f7b34f5db7eb50b619cf0c513dbcfcfbbb54fb9206223e80fac9e5f351772ba39a465d262f6530f1fd9bec7beafcf5a6f236b62617ed41df044a59094961c4673a5026a6822bd0d6af74dd471e2d4a858ab15b8c6cee50e7edf2c36f8a5af990747c01807f8860c64d48093d3a8d6af04a92b881b6f2dcc017507a44b9986d27d9e0739c4478c045e3980693515dc3397a90628e1c1455ff74ec892121e650ba2ce6f64e2a461047abafcbfbacfe6ce332a684e9ab44ea75b117a109b1adcf202591793f2907408273ae83e5a3634715e13bbd0271ec1259827b7d3b8052e989a422ca7eda91c06f2b67d7d1893ac1180198a00b94265ce7ec5aaf3ffa3a9c4dcc013d256ed5606dee7686092feafb1a2628804b1fd5a840eb5a6f078c9d301862cbd1f5bdc3b02e5e6cba8797f50b49f573747bad9390d5e547c7f3670b05148461dffb513ec0b9d1f6e77320b11c883c4d2624f253f99c2793497659c5020c9c498e6a653e60b38aa00820f9b7bae02a3ff08ab17f89b48a3b59f2ced6ee22dfa478a3dea160c79836ea350fafd9dc40747d2769568aa93560e2f7e681e1ef0758640756d770405de9f99a838fcba6afe49b4b4a2d651f968318112c42bbfb26fd227a6a22e0fc5285ba21d30bdeb3d4da89888de0a0d648b249b54e8898341f6775e74ac3706690e44210447497794b2a69f58c6ad199829b4419d96ee56312c9e5ed3972f0e83d70c7e4a6bdba630c154cfd8b10a9800896c278735172c20c86e9d8f48a0070a7f29259a84268fa2ba607d8aa0de19d767599db6fb03ab4c0d7dfd2df97b0c98870dfedc4b69aba8d88cc436f84788fb2dc300783508cae34c999846553d0bff9c1a02ecc087cf45c2fd5d4c99045858cae3aae821216298da845265fb66061fe1b852627cd0d16463b320c6abcf36577fabbd0da0695edd51926ec7a21b0910cb5ac673662aa3a31d10f2f1582037d28332b30e0ae9c0bc39ab57a0bfdd0d8379de0a0edf65a9fbfa4cb6a4e707447603cc1087f6e7313a24f498cd61a608034c9516915e4c7a0fcb6ce200f131e2add85a1bcb2d77e2051a3347c8a50e0e9bbf6cadfad44c1062405c52bb8139280b51582b5660940f6ce9e70cce5d21027b0493e6f2645bd327a40b367243765c72fb1e9ee190628e14f7022c5d878e0a52442d0c380e43b550d713d68da1fb9d598f7a537ff8cbb9813bd2a41ad0cc0b1361a9f29a3a7589436e71983b8a3d23ae2f85f0476cd0248a946e0bef9f870a71eeebc0f80684bba294e8d6421f37a02f163841c2e59f2a02341dea4360ad0dd03651f3be607e8ca9b3f1286477fd943cf06fc352eb13fa54fef500f41a1b08b39206b8da73342d892360798344e321a60652adb7194690b9d7b3093f538d014a7767c5baeb5959e5fd81acec9973749547309c674086d1de9405d34c4f56049497667487ccbd19834293563b66d934db21d8ae5203139aca821207844f660ba8ce39b383c2ed9e7f62d98472268feab6427bc9bfa3543437b9fe14cd73680e6eb165d92672fd238a7cf1d64567d148e6c6fd100984cb4af69e05e5d9aa8e028d72ecd27ffc1fcbf35ef5675ae890c0788665c554e607307e0ee7b1c27ead00bb782fc919cf21e09d6ed17107384a602a26bf817bb4c9541cfac1b907173e09bcebbf86af32a79d2908224ddef1f43b3d4e2427942a9184bebd2904ecbfb00ab020d696bb077d174eccde7df10a6bd3784b78f1061e0af5f557a76858160b051f409fe1317ab73ee9febf68fe787b1227ed5ee50edb259397a1cf2188e4330981db66828fd7ebe5b42713ed7ce4780d488ebe7151e2e0061b46f94e532f4307a59e5470885cca0e8895d54a7182daf327e9cb3eba38896ba1503dccdb44c7094df1651e06370a2ba30c99a2fb6578b84fd36345e0d52188a3f1d88cc030be0792f17a6f68da8bb2bd0e7c86285dc359299e8f01dd0cef6926d847555a06db08c27e9e16ebeca374cbcd8dfc871a09f62bbaf292fca50c957004df6a04ccdc0bf661311325ab198825bb380840bd2e60ef5fb38ae030a077204aff3c7f52b80377fa4c8210e3a4a2f8b8a5d4e1472106733a6a48f0fb72f6e942ef30626fe90e0c15b3c9dd2ddad58b745c6b45e8bfeb479293df5a5a810f4545b80e118665064fb6d574db8c99f9c599c38629d38c45aae348d3d59a423935e7f105846759024af878e313ba20b23eb3115ef2dd9cea547bce638db4f1aa3772e5823221920700e76b84986685272ebb81fb7914365cae882dd0c99a9b872d718f76fec24f0f6bc85ee6b9c8377f94feffc047aa07741f748f09c2939d732b3dae046e0a68060d51e2f82ae09893cb904dd61610aca06b5e5f4abbaf2e626fc54bace3a9e4059113e6bb992dd30d58af07a8ef042b500f4fb6cc1cd8e55a833e761d083a3b0b07cc23c17ff527ed768cac05c498a1bf34d3ef9a6cb781127b326a9465f2cd04e2e6091f29b3dac0c422dd23ca54d1b992e844204d5394452bca2dd2f47c1e09592cd6c516b7f927a1ff09e873556ee8ae2de87efd8c5a2684ca42f8c980a9006e26d71717c42c2392ef59b60d912a766041415df373c535104dd402d290bb021fb9504471832ed06aedd6674638017bb5d714e88bfb6b5b473efd87c24dc50a93ec6626e695286de966932c299f20af54504dc1b3d7bf93ff0bd258a03038058c926928760a30db939cf2dd7cba2d8e3ea165b4ab9bc3de22e4f1bcc48d5205efc78394d64c654f345be89c9cf4dde2a0185833058d2136d0a5738fc380cf0fa623cc9ac6a3308ee2748b6503c26bf4176b08a3793673c78b7d09b86c100d06ee5ba85af63e8dfdda1ab9deea0e6b98a63dac2efa4baf37f61dfa5a12bd8e029c24505f8f7dc577842024f8acd427fc12ae0f4f091826ffc0dfdb0e3942b40fb15fa642ca4cd11669a5a39c90b3ae93524019e380f7df2cd89b62b5bbc61f0d11ef3299ded766472e37f8346ad29945ef635566dd663742279d950effc81d023fd458c5dbce160b8ce2f9c6e3ea270322938b1414a179a65caa8fc94d58bd060fea849a2819331d73bc4592142c17999e5353c2897b402340a7dc653491240693ac39ead4012645fa7c46ef91d53ebb7c17ffaed6c325f266a95e541737660df88f8838eb6f055c838d2990c3dd55eba13fe08f1d0f6c3dbe28f4ed74e67f08e4d79bd76def62b94cfdc06788c8ccdb796b3bf02706724e81b6f24f528f030c31a927a5b35477c67eb5eadc06bb822b018efbad736616246c4b395a9bb89a00d57f42bddc9f8ed6d258a99d3a8ffcf6b71e6e00db6c357734a51d0e2adeb30a317a039d03c1f31086f1eefbfa811261638c5388f86bf5ef7911006287b92d0208f6d4ca4c678e5ade8907b7f0ee13615d306bf43c16a04b38ed6bd5d4bfc40916f42dedf5d9005d5fee45f9208b4b0596154561347f909598723ad91930750b0274ace6998a031bbb1c124ebb481dbf6afc93b8871f8b76a15ce4a876a33d0fe5d182c78c599211af0ffe283074a8011a5531ffb4710628afcbf0b79da9090d27b817f12b1afd9d84400bce134e06ef872554e29c0fd4174fe6ddcf0dd0520e7da6e491846303b78cfca2ee55ebc7994b1960d8c82293b7efd053af4930800870c5cc62d7e2228f6a6bf10df0aa2b87eb842296ff9854d48040a9e7046c350fc9b60f435c30635941e9140913fd2c1b71cededf2fd42fac3c152ccf87d8010a68fce0f2d040b15fe97d25ab49997f8bec2735b61ee39569b40583f2da0086064e3836c427b16e2efddb78efb203ef3074a5c0d55640bcb6c1d925f225204207af9d8725bede99d3f7d8b2b17665718c50bdb49922e56132d7f20ee3b878230a8427acc57e2fe7d52f87d9e82391625bab2bef706cd62b95cfad1d9320f15905a207ff240a7b8098016fe8cdd1f88bbd8ce2f26ffa73754678e89ac17322270050fcfb359fa88971c7777b8190486908fb0973bd521aa6491e110eb9f173c90d23f2c7fe33daaf3e2c561fddc68dcffed8a1d6dff66c2d5f27243ffbf2aaeb0a6838bd775348c53a2ea251fa4c69d3c998aa1f18853bf30eab667cbe91d94200023470ab0ceb7ff5cce3fa4daee9ea4bc162baec38f1b6ff35b820a5df270000f5822ac7c1c00966763b45c9f5939cf1f9796417c299f76d67e14a399542240e058dd45e96e8aa5c8504fb567e3e30f7b88183bd42198df8528670e338a1b70ace2485524cdf704a80c73026f8c1a205c90fdcce66c073dc6d7ed0487f27b70e35b02e44f9f017afe49d0963b5f3de4211f0a0b85fc13de9314b9d05bd27a208a3c3154d127ab3ebdd84623cecafef0b63d27692bcebdae98abfaf342c8a3005c51ee09d0246502096d2a57994071ae266bcd091e766fec6b84193316e3e7e040ef4b2628f8cfbb7a3f96ee76c2adb53b0a0d024649e6c0493bb0d3b2ca9110994b562bbde4e7d2a47f2efc7d84d743622a80d663a6084daa58904c2cff5ea0902bf99ecd39cb6b0301975e8e66b6f704d1c0b2cb179614d98d2a10425853b04837ffac3267bc9555099566b7ea1553c9da7ee1d20a8d055b490d9521813440c6e089bd8bc4a7494ab74d9cd435f4691deeb7f653e18036cee654bca38df160e61d6f37252c317ad6ec1c3056afa60f7c98709df765224b271342916fd5f2f0dd020e56c68e20a0ef3e16597481b692faa22c8a0954698d89c5b6b624853fa054dfaf7564bbebd9eb56f7487314786febcd47ca77f6aba31fac285be00c1cb0949ee6b5965ef7b020ef8ab2f4c8c632b64fef41d3505e92e8c58609db0d88e092ac172befa54262d9696defd21e761da873f7208d656748c8418324db0fa8000764cb1bfe49d1e225ebbfbdcba65fe6f2dfaba654a8d36b0b0c30280b97fdc0e412ebcddf566bb785573d44e2aa58c5e6a9628b65ebf2424f8027ef62794fc07b6d11ac0c261dfe6163084448412eefa21a0192f933919618abc9b1b0c14ac0538fc99939060d17646ba8943c78253140adb7231eef26346b182eb6ca395e20fbfb68b2d262752a6b065b312e76b7db6c0b9b5e13eecbd0aa5fa3ad51c57f808c11e4847a74a4d058f69881c8919c3c916a39219b7d032139f5a4140693d22091cc2eefc1b7733ab74352d45cbbc891b2e85fbcedd2a13db08badbe20e762207b0165d6d61f222c1ca7bcbebe010f9a1070ffca89bf61f77a916563044cd1d02b8aae1bc8117798ba0fb2b702b25b5f9c78343626354e3e441cfadf491fd580e8a51754c85ac61272035dc6a68ba0a557531c3e6c6a83db2065fdbf684cb8008c3046b44e97c901b3466cdc59c3166a15f398c66264ca3faa98a5ad51fabb100e57620f66965bbacb87c972f387b8b0b39c3baca36184e7852e871c65f5c6509bc7944b68fbb6cad83db7cc1ba72d5b2ee986db7623e03e85869b1dfb259ee0482a8d8a015c2515fe9679b40fb802a373a5fe4211f73dd62a4711101493fc904ed91e4003c52a474f8ae17d46852cb5031d8893342d0c1b1cae31fb6e81d490bfc53b218aa0f57b2295e497298e2a148bcf219a114193a0267904fe39d8b410529ed7398186ae46ffb616e886706107c48de85cb0d0064b5eac81270a07aa403ce8028665fc1207d43f80af777c2cfcb74793a81a3a3225ecbfcb42a44490602fcd34898f7dcb96f0ad809ef44bd860411ea1840454957ea3e00dd8647894f016b6fee01616103e7e5beb0e1054cc759b16cea10a27e1d6a6b652de032425e07f1eb718ffd53c0cc1cfcce1131a0f72f9b0f51fc8ea5c0aa40ccc8780fed3b0262dd65e03960648f0a0f94f7ce368f1fe1a43a696382e75b8d30b864e5c88f047430a1323b2f333c864aa37ae4957237bbcb6350def725e7b377ea5d2e10d6028fe66d7c08edd6ccc2d37ac70da1cbfc66eb916d434ebbf7bd064d864c8193002f1c8b911915c3969ff4c0456063c55ad6b47583ed9a7f3240f6effe383eb6071c139d9b84c3ea59a5748b4de21aad17e739a02c2f502fd2c6d1256d6fa9b3025333d118353c7f3abae437350201ba79e80a85abe461e59a14c3367670932a0af05475b46f3f57a36150e7992ee3b77ff09643c203fcf5352628ee107f7cf008628a1cae518684eeb4921eac8aa687fe28d408fcd9639cbae20b3cb97b52230b6ab7b5648e58ebf225c28db3859a2eb5212067d83a9e6f9fcb47ea9974c0d20afcf09f3da6dde29e54a33d2377e661215402ef3239924edabf2b6fe3379b36095a20a4ea32e2484445cc3fc9c0cca14adbd810809c0a8ce8314f6d34e287d50feee6f2015e42f3d2b016079fd462715aea6cbf1e668a66858e2526edc5ef6906104ec309e2e0cb2bb445df9e36241d5933ac651c7e752641e1cd212902538502e06ce87f119514b1f2da2cf79bef1c2fe78a34497aa7332e11f13f06d8020c0a802677625b98d235204f156d26bb96da067530cded07865da982f2da44391d0434d47afff7e6ffb6b0b514769508798e7fec4140faa426d2ddfe5ea8e8c1f3061d84cc1bbe6537fee8a6698780139727476cde09a4d9f760dabca66a84acd2088f962bdd0b3d60114dafcfdd211682fc5adb32b2d103aba139abbfef76162a001159fef3826648dc2f71ad50084c13667d9fe58df188471753273b188238120aed066487e983acf19e1f2989a21d80fcbf0f3a635750e013b5b5d1026491250697c12e1177d9df39c38ccd0994ce0ebf4f5f0cf92a21d4413b73f27e8f64430b7d1fc40420bfcc4cfed689a98ac15faf97da41457320df6d0243a9cc7da4fe0411bd9eb65c600d80754e24dae239df11d1e1df8db4ae58a317538c39879bba0abcfc859636eb0752e46b463944be1610fc0b7b4d660b378fe963d1053592ab0d56d1b0726123f126fcdfa71bb8580c53b97e1dd1318690a3db66b335e7cece0031f06f64ba57c176c3623a3a126426bf3597cb8f153058a6a7d0e463e5c06b0e8d8a5d750dd8546136753e60d982ec1b8d85fad1dad1a90824776a525a09e10de8c3bc2ac53ba8e3c4955031d757e1a45d0ad85ef522d2d55ac77ce8183c950600bb6dae62a86841b01edb43ad2316c95a6146e710435ea0d9fc97eb44fd590f19d92b06e39f5cb524853fe5968a908704df1c1feabdad9be6a3124beddffd025f7ddf27722c14632e84c37828756d7e8070ba6cabdac7fdbc72b75a0af3cf0bc11b1dddda783e360edf4446387f8e2956d96f34e021cacc21dc19a366ac550f87503dabdb62323980bfa31d7d50aee4531a8a803c1fb226c7b5475ffb9f4e0dad6dc42021a1a38f200c46d5ab2d72f9746335816b53cd1107b780c11c41420acd57a582c94fdb4427f08610f2611dca98d640f3edb5df29ddda610c0527800ecacec251609f968891e8518fda3baa395a0f0c07ba31a44127e990f4c5809409010c7a0b30df7952e63195c2ac3f223202100af6e9178b25c1604b69e6707404aeb82a2080a7ec26ed640c7e60e7d016e02aff112ad0cc40000f4c8395143b0e863586522b75d2d17b1ffbd0b5187615acf1081bace08deecdb8f876eee2db0d7d88764f7121f85ebf449da2203f3d81ca0c421bf27d4aa0c513f487c363310df6f9f72946b98f03c293889f05807dfc9c9ef8b1ed63a4552b0a1aff4c9b46087a1c0200eeb7f8efa1dcea86270d2e4af7b9a0846d4c130b88efc55ab00e0d0a49dc57723b95676210a7917817b8d455310eb36fda6faa5feef4eacf73b162067fc9a42947cf34f8310ccdd4bf5a2ade82ede0856c1e17298cf894ba88edad0eaa28aa6949de6c74f0392f1c4d6a57faec8dcadf32e26f5ff72603b6cc943a0994262d59a82cf194fb93d3a0cce6a8f4b0cd984ed3c4d7d5ec4d295097baa10e5a3abba0a426d1c6fc251b31f87ba14fab8acc23ebc0bd31a0711a5b5ac9ca07cfe0b01819ebb04a3ed1221f8f7ccf1fd1b7323334e69319e740338cbda9db0c7116540bb42fe3acb1395da3701d97ba64701f7f5b01e9266ace35c9ea95470218367055639e99b33f2f552ac1754e38d407906980b94034ae796d95dd6c030f0cea9ada0c6bf305638ca222cab96add245eabe309c845c595f8f025d23e600023792304fe86010e89ca50b7472517a3ea33376a7a7fd3c0cec8cc7035d8090a0e71635c33f5b14aba950107551087f95e921b46da4195cc48da0ae3c0e5ce0311a0b9d7e12a54d12cc703bdd700532c3248f2724ca23c01041e2c63b9523e028b1cbd189664330c746b46ba81c7a469beb6a9372a3484b3b1a2c5c86bb50207bd12f7d66b346ded14e6db68deb4529d573f00e29d9c737343f48f9100a32802f83546bb43f2888dfc1ddb0694cff1b8e24a7e4f5fc36460564f96a7dfa2d9058d6a085ca04696a9d5e278c10c94e2df302995c785aec22061fdb66d87d14f02c9852578e3c75b2ec58e7909c25722b629bbe39c11189fc4dd7d0fcb9e737309985cbc207c57bb198e5a09e2b2e7a31a7346907b9d9835740c34b284e315d908b475c3c4eca4508e8a169a6f057fc28d6a5922990697963b3f896e571d2f310a58c386682ba374d597bbb80335d0c5fccf1c77ffa15f4b72c1684fe8f1cfaa02ebdef82fab044a6f8ca690f207f455ffab777cddc22e4a8ab29eb2af9ecf600579161f91e2e0cd5b769937066fbd66c762e45ec01985e0eb00267b82db081203166d6a41b9e1c03bdcca8d077a21384eda20ad684b4a5f553b644a6b8707b40f21d94c917e2d193911562905c29751ba5c95778c32a7e50ed52d29283d315a07a97b4bd4bf48eb4a7707911b41420dd8741563c705723c972f50dd6561920f038beca2d633c31c7788717f2972ab347e7ac2d7d8d7eaac5d206ac3069eb8f508def2568a9487775d61f3f3a085967cc4c086f36def4b4ae9fc486dcb9d145a088b135d8c59f6e5c07db2d994d69c8e033ce1bc46f14093fafa6dcfe7e31bee0d7bbd68a2f560105f5299c355b9f57ea6fe3b41f086bfbecf7072b90ad9a53e01b8bb2e6d51fb575cf0091a5953c74d6b1544b712bd3b5d6b6f629b993f71be0461cb0450b27e8025e736554c94822a0e246a7441700cdded75307e81508c7400fa13655c949ba22bcf757f5f6760dcab8a3afe55b4d36cdef505486f6ce38604f24944e063602d02adc4db3474edeaa7f108871275ee3b3142aed3896b61620aa16b9c3b9141da7a6e2f01244968a99c97f84c60a36c2ea1885d01ccaecbdf0b6835aabb7c099d2d0cb83e3212b39484a440b0b8a8b0b0e6b81fadbc2c155106807662b09e1d9271dfd335133ebf1a2ab1bbe74a6dc9e42214c45e0983251804f1a85b79b4a9427e8220f43f7f531548f0cbeb074a0a469856ee9ea3f10def03429bfa6ea5a638505796a86c37d292cf2229f7199583cba4a37cd30037499d05526344a79ed005dc1d1928e86a021f6913df7448aad9bb681f47c07f11ba1b0ca492e5a9452532f45ed466a52f2486f5f63d879f82c4880d5d40e03ec2f2440551839f4acb75bf239388e2925176230efb301e53efb13e500fe7acd4d2bdb2031faf0974eadd9ddb36f8f5132ffc9b43f90c3b3ffa5fcbc4d32ba32e1e31bc02948f3ab608d7dca6158e555a92ba95b1708358c0486b3b9bf68c166dcb65380678655371b5c2eda2c7b479ed9470a76c8e9b3c2bbf5c22f34270371d48e40e0ba19fc418674a4a9a5a5118956ef0fe35d98760b1861737ecc43f941205077205205cc6cf354daf3eae1173ec197296ed018227013ffdaf9db645a42da368470d6c53e736441fac1a7dda029e94f68d853eed9dc7c0548fb81024d45fb4657a055dbea743485ef4749780b01ea59987e335aa363491a0740d75705c8317c84504dfb6368cc8901e5ec7f69908a910fd5ee6636f96d2f25739f0c5b226cca5b407631290a67e79313176b469df0f41cfaecfd6032740a283da7d0d9d4db20f090edb1f2e139fab5b6f6984aa1a5e859f9be501d04661800bac31ad17668ed8a505550bf8b59ec7e464948b5601b7000441637e5e063ba5bb58d1bc30a6d2fc680ba2d7417fac4065f797372d99b4dc046e53de7d1f18e51638ceb0a98ed0a81b07181ca8124edd86bdf213640b57a907fa3d2d0432ba8f8494ca363227c1fc98068f8b96b7e46bd7548b68295a2a15c3b3b046371e3b5e14504b5d90616fb695015d41d821f1be56b5ab42e9d54cf085c24a2ba33154ebdb8d2517722538616d0db88f693e0f159274ade6a5a848c3145b8bb19f07fe4501f4f0cb336e202cd8016c3a9832592d8e7afcb7fb2c02cfbc0f1b21918c63d292c92c9f40c1c78dee01aa4fed30e8303c3e404fcc995bd7446464f180ea7ec9f975ce74e3968641e506c9474f56c0d5dacaaf52e9a29a88e5105992605b4abe44c428dacd75cc77360dc39705c50def1f5f3161a62c0c80e75dc3c0cd0b6b7e0df64e7305b844bbea0f275b74b9946b4acb5992b035d38b58d7a9f4e16941e6be1b8c2e29dc801eab029e0141b5abc0484e7fe0199bb727bb34aed76ff51eb7f794c550d3f89d55e70cb54cbe4b9b39c1b4853beb22fad7b8c13b5eacee435b8c0af7b2aa10d21fca09d8e2133173eb652e2ea2ee7c386398024c76b33d68c79946e774afaec4b45a0fd7af0526fce288de2b375946e65e7e7c29dedf403c27adddfddd2fc84747e90a96fefa397169bac7d0717ce49a450ba86232faae76e7c1121f36de845ad76a0eda51ab547f17c264c2a0748bef659d71d4dde4fe090947e54f864b97108bf10a6176571105cbccd03fe904acd9abfddd737b4ed4c778a8e02af6cc415c49690f505c73ef3ea3e3e31bf4444600667772af7f23731890774aadfe4c39a36a6507d7d619a28c41a94c17fc743411cfac54af5d6c13794cdf122928f20cb311e100a082a646239be51d8a0490d53b631823f488b4c74ed26295d66e4622d43a9e015f6a671bdd28c768bef1ca14b24e02c35f9a8e4237a677c1857444f6ef0a8c0bde6cf83fb5ccbf0d264d939ec88d434f60d78c682bdb1fe66ab02f0ee0e50f06c3a6cb85bd9858677900bda38fd541866f727bf04e04f14e22168b8b9500e8078d5b540dbb2e91bf1ed34d917954a74fbec2fbd78491673a4ec31bef383b82031ff314f852761de725d892380de08b842a49309edb4864edc26d8a6417603006373f3fd3682d9be4f8d69d310f1176d692b704640407cb43aecde4251c432d045e66da5bd8db763132c2943c8d419ec82a913778dbee2ec9b3e8ae52161bc20a27bbf6c8aff0a82475ed5071f8b5c7e3ccc549fee25825abc749bfd771d9ef0a2f35b5647b25b83371555ac8221d814573386b5a6b73019cf6a8c21176afe40fe38ea84f27ba81effed3447bfbbcb58672e35f55f6c7dfa5064bcb7078c364025ee24d2e7efee5906e966b8757dcf98bbf5e2936450a207c289ef47226d933017e15384c7d3d8f1d400787ce8f4c3da1471f05f18a2089d0757d856ab1e15d0f41453f431cfdff7b6783fae40673acbb8930002aa115d1b173557c8c4087b40a +generate_ring_signature 6a7c21315ea9a0794f13bcb92ebfe303e1b0713cbd6bfacb529134a6ed01585d c86de54a568c92e9d6a2be843389eea6397c740fb17949b70fb10a9a58842e2f 53 a4eab03193f38a2e0e982a87120a234f90b0bc7944f51cac35a25176fd58b777 d23b91b0325fe014f6e53b9fe832d97042b4aaa25cc5f1247658419c48a8bd49 1bbb20d6fae0893cf5485c19db5e675d999a0e9dba0e0718801dd3f2707793f3 2b515426826b80e919c7b7acf9616b6dd5572e0d5dba19bf9e4da51c00335487 7c9eefaa09435f31121d5e355e4fa554668f4837a61973d30dab74d464cde65b 37a99f9bd561f0192816187d019987c0ce5f147d4c418bc66f1a5cdfa0e883bb 8638bfc48383464f756c3664e864d326bca7855cd4f8741e29c74dba9cf4847a d67f42eaf5b97140183b520d329b27d245e46cd7bd00c2a171ffcf3cd8a0c9e0 4e7fb336b76b0304d312f2d75b8bf75834b7398db6526008a74874e4e56e6aac da1afcb4fc99dbd35c26712046956d72c6ae8500c3f916b34d670e6c9daf89c3 3d982fabf70524a3fbad979afbbcfb2d0bbf8c2aff2305bdec06e5c79d98b47a a5f8ac98cba7822b50a7073a987e71de73ab843465b744a3435b4bd005522a94 08ac7bba764eecbd335e48c24dd1c04c69e0f2b24165b12a408901dc5da87043 6a9232cec3fa118d16cd669e6dab9a8ec07a0141b3d3b5c97619289400168432 cdec045aa9b95db4758e28ef5d3375c539019188ed4994d59d932c5147e7d84c 76b7e24b615b9c211c78a8b212655d2abd2ba6da10ced987e827163c9f8d80c3 48da2559b00cab37fbb05f10ebcacf51650976a020f045d7dc83024afe1b2f6d 4f16a0f0e1da96f7b885a88f5d203502d5bd717ec8b5836707b2da85accb05c1 80d6ff504ab0531ce476105fc6c6ab4cd39e75f9ba0bd781b7f6e9ff483f71dd a063b2575fc0ed77466d817dadeb051e1264af664b3baf2fab0b3bf3c7b5cbec 69d8a67beb3f99a7844a980df676962f97b9971a1b084a5220bd830cf279e181 33acd6c839c0c7f438189e1f67a8313be209413fbc7b0b39d1265a6d757f879f 97d4d0006c8c7deb27813cb1235e7c914a20da278801c2f3697b462071114276 f006a40b43795409e5c5254e5486c9522ee2fd1a338ed26e9b40ec4e1c29cd52 eb6c0ccb68a8bcf2c2f322652f6e0635d46e214f0bc0961e6ee431d9a6e70e6d 10a6835fabd12b737505f67c3194489ad1f67e2f75982d50c5eccfac7661c050 2743f8484a17f4b8ab423d9a06e648638f50037a20b453f91da821bb8dd98737 ef6cbc0d2dfe502227ce198c737f0bf0f7a4931444bb8ddbbd82cc317449dade 574b33bf68724f9217faccbc97a60e2e6a7497582224aabd262dadf54a73453b 1996d428c975b3ebc9504f329e76d724f2716fd2d6b09436f0241d55525dfcf4 4aa00e19bbb3aa17adead7dc76b7c018a9afc20b424fd11b53514193ebb48568 346d12690e9ec83837d4f402b0fccf731d999b38cc66fa1bb8be1e46398b04d5 a819b6df989fdff76ab04fdd6cdcadfa2751c54e14c359b6dc63f285bb545ae6 8cae8ebd0995b16248b6f1e3c7c61d9f0de44b582ba27f155e1f315b81c0af60 0e6ab1fadc1ce2f6473481649a3a500a86e4aa00a042d0257506022a7abd0965 e2adb81732a12b14a36d92d5ac877c7eb23b4d365a31f6340ee0e85e3044cd83 557afb592dc585c70ad082f601b97ea5d53acc1e8c1cf2acbf73cb2e4ec8ed20 6e2edee22b8a26501186cf35808472bd9c5343c3763d921322398abd5b524e4b 321503c0c52728139ef0c745f510897978d1805ec1366245f14c12472c8f7926 1e94842bf9529a263ac929ac90835961315297f2d01d83fe9212cd0c5d86f662 f278b17bbe1236d3066be0bd4befb0e914a524f85bc146c117e05db1abc54126 d62acf5d9572433e91cfff5d9d319723e0d49dab4a3ff4a7a2c27597ef4171f9 1cb00476f95508a5c4b27c7de7ae82386bfed926cb335dc6bc934b21460abd7f 32855938be63eaf809c44abd425f69aa8699cbf7f8ddb2a94817692574f85b31 6d16cd460eef86fdd3a4ca2642866ce01e7f09d9c7e3158ab61fb4fe7b1f1866 1382892cc72eaad23a9d62e3dcddc3c8e093177fd99076db600ecfed64b60977 d7757e0cabd39e25dbe09943b20145c8ebe5710004c53ef8355b9e72027f6cca dbcccfcb3708dc00901fda1044bba7d6528a966dbbd4c7fdaad104817a37428d 42296a58204e10349dc6b9e58625ed27b7a0fc30d56f275e5c492c78faf3005c f40a1bd0bf96be276a9a65ce584aa7be335b762ac9adef807c31630587ec85f6 4e4e6efaa2112f4a9f3e2baadd787b09546ae6090f39bb2c2c701ea2bdd8a36c f74d02271c39444a3d2742e7e4015fe3f3a7f3abd96e4c04d719ab0324352638 1f89028e20b6bbd28eb46ce5a94886c0fd79ed9142147991750b7ea512c03be5 fdfa920e8a966735aa26527da416a60a777c4e9977d85417cadbf32400d27204 12 01c63a382123fc6f26b28ad75e53dde45f27e1425728108859a297815a4baf01b220b05e789fc09b9792090fe91986576cf0280a916c72bb8583ccf2faee5903972aef86002ecd629eff90548ac10c1a1284b7abcc438bbca0cd0f096857bb0f1067a764476c4f7c97011a8f1aa4eddcce8a396c0beadcde37fc15da2f108502206a9605ad7a54249fd1765b446442578f2ffaf7b4001c2071b03fe5be49e40583a9eab074267283475d9f4f494138e6b159a241bbdd4b7bf3f16bad4075800d13fd7ce92c25542ce9dfdca846946921590975e57da0e5d48cb49966d57b550543f1b3a0285d9c7230e62097d418fa79a4b7245378fdee40c3454d6eb213f00e5ab1169927e696da6f9b0d459026143a8a0713a31b55049e571e19c5ad427a0df839b4b5f783198889c955fdaef98b41430b0fa5bdf337a569d16b7e49e47e03660f450aa89032d433e3516a968a8d990a38b5db01af52898144edad8f39c304b4af83df4e2dfba14febc75d829f13349984d71bfa7bca7f0ceefb6315e7900c645268f5439c0800530d10f8ad07011e50aaa32f17a7f4b40881da9f31337f03562bb186bec0f06d1f94a90948806f3b0251a407b5aa2faa4704eeb0478342099254937360a83a3201fa4a2c6d8fb1f1601563c783d52966d4a988da36e73d0daffa9d7306adc6cde0aa51352a3bbbc594f61b5fa750441b293810d87bc5250361a231786bcf4d68b84243e58f9585cc2aa344dbd0529d64a045198269c6ed08337159fade850c8e86e1438f5ca51378e785faa1de0960f67940adb9fba8fe0cf563b3686163f759b8e95e5d09f93e6b62071360f77d6bad08a9f2db8d5a1d01fd406c2a9918e3319a9a2074950f7d40a5560f57e30dc1a8165ca70ff01ca404681e67524cc8827acf723df2b1c05445e0ae822b879f4f1689ed1dcf8748e909e37ae8013ea05607658d73506192601c905d88051a82f5a7c93cf2405013cb02913a16c9433500c21d87e4c619c4cd0779a133f86d9b6979ce41d2e74cebc7076261b041335337a3d1e5172819fc2ad48d54f82115737cc798789d5e510fae010141fae1131cd478b326da4da7ad124454fe345f4a99b8d1b137b2bcf9b25d08050772bbc427f203cb338e0e848abe1e3d3488de3d20d4f618765199278d48005d94dbf62dcc944890d573e4b8e551ed61dcff4f6a2474b71cc6b10d0f96fa0750462bcf57bfefab0dfadb15b5a2bb860dd3a00a3681c35a646b1f81001f820bc6bac2edf351d525ff409d03cec61db64d81e670740a2974195e156208b27d0e4de7540b8793618e2b94c8708bdcd5c274aeaf2c3ec1a37d00ce263fc6f91e0b272e75af30574ec0f7c1e23cbf98986c04b0813545ff7cf461972607d485f70ce7b7aadd0a64f7e6bf60f28cd1b3a1ba96c6dc55b16dfb1cdab3b13533bf250e5997a861c32a4f46fe3c463dabe4b4c574cbb618ae9f1e8ff78baebb6f4e570762f69be45b9c31eb090f0800f1a3b345ff03aa936973dc055f2fadc0e5dd25004274fcb701327c5c13d16fa15919f7939ee45f5d415e5f3b671cf9e7e7c8d90f1e0f703414c22cf144bc9b673a400f5af0a294a1b2081a28b5b4fc6cea86d10bfd485356bca17c9357ce3d7872736e8fc56df7bcbde4624bee3005e30be81808e07a6d18996f09c9a1166b271e94637dd3f916fd22bd79e2aadcb120d8be47001eadf8730a8d727be3988fc41cb267b7d03f37073c30a64c022da05626189107366853b358e57e6588c34492ca19d6dccd778c0035a992556397b281c44f48002fcfa2da45f58443108fcd1affb1bc5fbb305269c783096bc115de2f375f4408c1a9537fb2edb86265cf2da37cb7e53c4b1106733fd54a2c3bd9d1b1d1ebc206b2253289fd600e70c81e99f8df555a29775c670c23d805c892fc6c8463f1230ad5d14de955990559bff18c4a0434b031c655e38d8026ffb6dc0db2cc0c870e06fc10eaf9d43615a753860fc453022a8a8d784cee0eb52a2a71180efabef2380c3a6950c0522fad2da8fad28029c0a38a8108934929b70b870575228bb185f30cad8e6b4d67e59b48305d6a8764cc98a097f51bcbf8c7a6c80a207cc80058fd0cbe6b20b4cef59d8f5d54131fc238bf1d97a64412d817f86a21b22abbc17e890ec147beff79438a5f73c5446d110bc26275d769d06f464633262cbb12ee62cf01fd5c606d7b88f81d8d06897b5635e3ea363723c8f22d6a651464a903d5232d03bd2fd4c9ded992f30438cd41d9468d59c7121f7a5c581c41e1bcbfcfda9e1602f42554a5ada6275e69b8215b4bec1e55ab7aed6e2ff89d5ae7aafa0e6ea91404b3c7ed0066d088a8c0efd269de18ee8e48bb4d776f8f6932db0f939dcfb9fe0780c61e39d1c867a22c97df2d5eb4abf8129d5979c1347f33cc30921bad8e7f0f62d44641550da0e36c65158498b6cec865ccba214315c76c301e1a3135f33b0c062e1b38864fc2fb578c58a69a34271dccfb3f9f2c6c9d090c5290b87a7ecb078b157349fe1dffed51a64b10f27188feb86e3c677a298dd9b9ea867032af76093d2596b07b3bbddd67fffe2f287bb529ddfec683c42aa914adda638116bd5e0cfabd6459fb4bd7cc5c6e7c1764d838a1012b187e9cf8548886b1c7d593444801314db5d4550521b39bed0fc19eb1141f10ef694d164a2f21b5110b6294a3ad060cf5ffd035e81000f4a52574a7fc0265ab1f95bb73d996c0e6857ca53b073e0e405207a4dc5dfe5338c8ac19bfbd18b9cc8777cba715daa8639941d559dbb20727611e9b270b1d13e221b24984f36b8b4773ace4628a84a0a077884214d4c806c0b1e29e56afae63743f7747f1e6301d6292df851ec0d0ef40ef438c0b4214083fb941088bff92d1ff2c18347101b7101ca97d0fa91aae26e257a22daf40ed0f20e6fdf1c223b932850898d3e55f8378b97f040b833e51a8be4ee6be54a7400331f0a931793912ec77b55b7bb18c0354fc77bde55465933ae036ef6b83cd1208f99fab41724bb5dab9c53224c939a1d87896dd01d1c7ce92becec09f8df11a0bbfc92ef6658335cddc8f60d2bdf559d11847f86603ef1ebfa9db447d7e63000214d828a0014dfbaa1a89359a43d0f7c262d8fc6f263141779f9d72dda7793d0a795c26f876562d6f666320956119feee80af68e85278dd25ffe320f6894a800fa1449fbdde07184be07ec769163ec11a52162bd69b3675c32c3dba94b1c8a009f2327b4afedc18a722673117402ba9876c6ccc81e16b62ef06d91664b36d4601746f18ebf4f4b6a380c1c0717abb6d89c0a13ac5e2dd9c44319bc7dcb8698a008d86f97a4b4f28ebc8ad83d0f8d0a396d5e1811f5df2c43e041b782b73595d04c76fdb737ae9b247041f51b8d37f4f06211bebf470d93d8aa560c7a989f65d000c43dbe85fa194a36dc00246a3f4968501ba5745309870388b603aa865615102c8d5abc6c8da5fe814451d0b4cfc2e9bad59b198ccd7bd4ed80c2b36c509440dd8d9e593f86673302b2cc54111814dee6c3796693627ca43093631b138844203ceba574dffd835da3a5be309168750b242ffd44266a2b4667b9967dce3581a019a7ba4184e89a37386b715ba9c801368d243daa408e8fced9114dbc31ea4c40926fb1a2985277dcda4169bb0ce5bd9cef3c4301fd3de21c0d37638912d194e02b2a55e6dfe13b3685f0a945d6704dae1aa7392ac6db1eba5e88c2fe395cf9003b1402be4317accb61c411ccc0446964e0e3a9795605bfb129a34562dc4969a0425868ba0728c582192f02bfb3dd37196f256c6b32c96cd0a1509ed6dd965eb0b90dc350a736806acfade7c23055afb38e50b76afc0cdb1f324e79f852db4e00e0a89f1a0318739d50b8a1cd6ade01e3d6b4b63bcc244819ab9729ad0cdad4e04a865f04a59c69f7d82275ea317bbe574e5a42aa31a733e67d235be708eaacd0269fb932855f30524f44f034ddd95df4c19ead1fe50beb5a709d822a259b1590c830448303ac0b5c4f5a071d8da8dfbdc633f9425cf7909276eb81554b5b4fc0fc32216512d49d4edd7c0ed12a2506e79185bbd9e0dc0b2564379452f723ea503b4d30e235f124d92a6b49d5a56fd018e90e8dd3d169f3867da7e2e365b93840c027a875a1d0d9c881187771ac5bad1e6ee893d194a099109b0cecb34d6d7770c76bd3914b3318fe15769e7484a0712168583492ef40e5cdba5bbb8069620760edfbe37a8f42100eeb4e930569f3471b3492d29a1faaa696545c50c5a1bd62502e4b7c2c9c25efc4f10449a791d6bc71073986b8443c526c4f0551247bf5cbe090bc72feec42635343a63139963dfcce212f0d0563d2a3d4488515708721f02080be78c58ee2e40a014885eede95ad1cb825de8683392a9c7d0e0656028def30f6c89ce1c27c0342739c2a8dd9392f0a4306dd77547564c44f68987a0e6ac20008d23a013da1d12ee937bbdcee0b4ec4cf0bfaa13a4657fc5f3f694cda123a60dbb44b5b432fe2fec21aedc83fdd66e2a74023da8430ed92c347f247830cf3603631ea97446237ebcd26d508b62cf6d9e276b1e92360ba014e5467052b15030065df45fc5cd67a5baa144aa60e68d36855ee4998889604998336cfe85bede160a19fa485ebedbf33ab73fe3a373235e40baf7bcd1ba480b9aaf3f33904abdec003e1f1a9a13befeefc8d4c3c0c72e7c246f6597e2b22be2e5313e1d4265d99e0c7babb43c8fd6ad5edb2e959598d934dc1b0516d02b3e5aafa75817456bb67c01 +generate_ring_signature a4f99b4aebecdbfa9f6c5fd9d62aaf72bf17ba6b85b2b86f6857d4eb5aa4e2a4 903b964eaedb5d9df0b0b34f0b20d58cabf1279e7254300089735c55779f6d06 2 6312750888bfa7ded17884f70275bf7e07062a1df46e580cac091363ce7030b2 155806e2d34207010d5b4149cff7eb191ccd3d38dd5a1cfd9dcaf19891878dfa 04ffca61416f5b7b5d918e456a81e4f50a9d4bbae583602f8544be5a74c35006 1 c4dd6d38a37bb46c327c8514e14b0feb3c65c50f9c43f9562804f10e5f5ad70eaee1c9d3dc8562b2e09b6919c8251cbee6af2f122147a763f7e0e0fc7077b50df6a0ba56dbfca296ef0aa192a215434dc79a73068e1a887b2c915c938bd3d90937839328ac0713aa5ef2b277667fe3aec7e89d3b40a2237a0fb04a5398c5c205 +generate_ring_signature bdc62a6efca6c735edea0f7c692ebf61244271d37dcfbd89d538eec558460cef 615390da874162142d31fe5efe83e353bb9a35a06e861b6fa96012afb6606e53 3 f0927d23a105b3550d3aecfa2c3115c5730636fb068080dab5f9e2a91455fad5 c7a262ec1e963a0c885a967fea2e3da4374e2400ba9645db84ea1c785d13d07c 38a3d5ff005353ffd24da4db56e22636e1bd2c0182cf4e08a84cb50af7752351 a31a2f30ef28f312d39d35032878250a53ebf5c77325eba642299bf98b567d01 2 69636adc4760b89545e0a0a5f4fc75adb5b251b3a1b97501a6c4fe55e82e0307785d62b193e4ce8410c5b39d4861058a221b77f64a8477062c4a8a49bff7b50088039bcdb453ac577ab0952b07bf05572dbfeb1920110d172e11e266659f7305276e467f940101ad5c6ef06cffd3d9e8599aee30be02845eb1731ca2fc916c0351d5ec49d943bac0a7867a8011d21a008dc0ce649cf4c0acb865d13f9bfc7401b5f11146b91a28b57b93f4a7aedb329b6c9adc5a5c3486c31a9691ab4d2fe401 +generate_ring_signature eab1439501745d1a9b34fcaddb7a42e8d09aac0a4070e49c193b7eabe02f3e72 6ce8208563bcd24b2582f5c8686df7670c4046c6639d9948bd844d83c79e6813 1 df7698d71575f97f8c3699da593b61ed18f032140799e2e62c7a14e191ac49f3 004c41b8110c26fb97c3ceee44a7423e7ff0fdb3e7911af60bc4a03f2efd5f04 0 5ac5bfc46ae7b60a4e6e2a4b7b72db8cc31d51c5d0262c7cb8622c2bc2d0c307fae1a2340e2e7ac92fb344c6d40c73e43dfd118841eddfbb5bf16796f85f4b08 +generate_ring_signature 50d6c84602d35a33a30fd22db0d5cafff513d3947624c0185dbea80caee90c5b f686926e40d3a434315e5f4ec24c8282275b89773f52a4ed817025943ff7f022 25 9a30a185b0624525d23c91ea4f28bb3721a797a790c5cec3a7028bbb8e191027 8f4f792489a3796f4c9ae40b0e7fc91a7de29072db0dc09d3c5890a294d01a8c e12506e001bc9c5bafe5301f3df40bd27a974ae162d1446fcdb268a2406193e9 e250ded73cc3dbf89e920217cfca4c614d4eafb5a40c6e36bddc349a4c686597 b8b0831d43d7e2af8aa0d607b3ac194c33dfdf7d3efe78edf3cf6546011810a0 76423bd48cf42c31fc156e3091f20982c6bdc3db8e792893528279ecf06384c1 b7cc082b2637338f2530bb5340ae7c4fee3a2143bd2453970ebaaef83c997592 f85494d2c98b7f25681f18bc32565d0039015aa5266f65dd232dd731b09b4cbf 3ee9148bb2f4dbceb9c0869f3c4e7a5245e6e549f214bcfe4d91f78fcb15d6ea 1b250b0f1e2114b6cf2d6c7fdd4c7b9da1f7bf721172be560e2fcefdfd4813db 9d1b3233a32073ce52df7d1a307de6b836582afbf0474351e7f0a2b2a7a9213c 83c98a063202a587794fa6d5b0fa0d3c18a21b81a43cbb366d26a91735117f86 537697e77585c2097b51341c2811cda8fa3550cfbc44e529f0a63d63ed9290e7 5da85646a0b264efb575a635de1ef2c955a765dd336351e1b2ec3994d2c04e5e 832efcb83d53c171206dc4cfac510358bba39225f385a551897c4139e5eab6cf c6c37d8fa87c45ddd9c6d9f1b770c6faf56f903b59afaa8803ee7fc6ba5a3e14 6389ab8261b9771d991039e4aae4bcf58fa807749905593d1479a23dcf6d2e3d b6fc1558d3db2bd362d2aca176659835a3d7f34d5ee2c6da1209bb2355b4e954 91c3a0980db59fccc7a90a69af24680af4bdc0d17e0a72fa7fa5da59bfa997c0 e6f8b0e3e397895d57639d5aadc9881aaa3d8ee04d31fc68d2f5b9e411683075 0a4503f9c48b731d1dd8b2280a575c15e5fef2ecaca934969cffc5cd115dbf26 1327c1f73ffb2ac17233d79624a17b1aac6b645f16f2407de8a92077c19a3c7b 6dccf4059e35ab49f66e199315e763efe2815a503eab8bcf44f4d25534f9d200 f947e8966541a52c0835c2a064c2cb71bbc652dbcdb1dbd3314fcc8e75a01f3b ae46f670527d4c0d9f04e0a4ab67d23a4e4089107c3250ef62c9a43a27c1c4db ab8a1a9091fa8089477cb325d13df16b35fceccaea164250309204415733760c 21 cc961eaed416a4495985140d947180deb28e739c7a86e3ce80c6010add9ce20610865f9518f63f66456c587d138293d60e382c2532198b1e1b8e8c16dd9ab2077f76649dc6127bacdc33e1265759d48f93c39bbf798f1bf116cb5e82022c880e1d0f8968981cce1db021e00b78a4516eb360631466892d80c13141805f806b063a1f141ba661e8cd96a66a783d9d2bb762eb626eff7cb2ac20bb826b2aa1300f6203c331934eb93f64675f7d80fa540982a6db494cf240b40df950ea1d06ee0beb03d1b7304113671eca73e5ff0c128bfd75a10d840701dbd631feb64bcc7e0189c74eefc3d069b55d656ad81af5fdf846bf9c169ef81d790b98d9e886f2020386e2227bb587ce4f28f54b94c492d88f047a498d51e941b5e6223a047b1d9601c76eb05a8b14faf52011bf63e59dd950eee58e6ab9d14af92f23a13cfa06e40dc4338f6183f5e0281c341d051ba3e77e2c336e35db65efefd5bc829352de5008766801bb0cc50f410d1d3542ab471a40fdc78e1665cc04b70e0819dfd6817e0607a026e7bf6f215aa37e7a242d74a13ef46233212a85bb95a13296585c154201e659e3c7383a2781f7bff424a77eb91d60bcfcfa94ac057be5d2f53e88cb860e230de56079cb85b9d3915166929548feade266b69df96c9d1734f6a115396c0319cef2f5c36a6bfa34b2c0d4762dcecd618a27344eb8efb9e4960a92eb724d0339e06ec463ace0ed8d9f83c5fa5048321908ad619098a8b4fed5c823c7523d0b7df8411ae9b141dabed269568f289cd26c9181c6141916eaebab2af15fbb190869d2e1a68697d0d82d5f5bf72a7993995ec925da9181dcc7e70f4fc55f16fe013e07c6a74c39b454cac5dba654df4adb31849a7b981585183230329a97ceb30bee5a8a6ce2e996eea1cd29c20434e92eda6f6b0765756999652d3739fb0f0601aaed133843bb26454b15b5930883a5d46b0955ed313b090e6de8ba2790b76e003d2404bf066ab82bb7581d869ca53168a46aef1709ff96b682d0128187bf400ac2afefd4938645991c2222e453159bcf7f9df786d4da14b6699efdcb97df0701e16442d73100467afcc6cf64832a8651bc527c0f08c4476920977db779b5c60c8bec26cc1adec998a601a4e003beba0f3762bee2b70437130340d56cd7bd7c0948b394ca7f7aac147b77831819cde8c6db61efdf4df5cac7d6481656db3e2604afe2a85243666e26a6b52127ebaa9c4c8ce62e732ec86a9cebaa27d2ba1e5105bb511c1b56cc7aa42ad24e2c631dbbf8f2d3bf42422411494539ea9abb16aa0f899001604bda965bf3629be7eb7998e36cc9c7570a016290e29afb3d8c4d550366400f8c6e94b8d685daf9338acf4c2700cb13048fc6647de067e6740db47b0ae90e0232dac5803237ce1a738bd18a14ce1686307f29576ebc0acb2d5e9e2701c24aabe397db8d3401bf0e91ec8b55e55e115f3a993697f170a54f9a5cbd6a0abd3696d56f9eed21eb86bf6419d59ff35652552d4f90a0dca304b760fc5fd101235231cce4802982dc649f38b51a4ac5dcff07d99ec7610981a519e69826240d72aece8bb8879b86974c9d17d8d468bc7f40962b385a02c578297c56d0fd1a0646cbe64f6bf8ca304603ca241b938b06d6412e3f2aec081b999e9a13221bfb008c923d90900daa50720d96aa03aee4c80e8070d79c9ddb94ac40c23d9d265b067a0ae3a4a1b4fe26ced70ae972ae08e8684a6c02881420cf1886081a22d92808f7eb73be68ca0d1c5eef5edee6d264d335bad8d38675e6a071b5775f3f32700038b35e7b505937fa31a0e479a6e9fd0324dec74af6d13bdfe4f8e05565882609b7fafea7c3c45d7073e1bbdab18214627aa98292d93aa7b82adbb1cca6c0700cf43fc3f71cf315acfe4cca6323942e30dc1ef14659e203d232d75ac58dc18c011bb39e14662b6e1df3c82836767c99113f118de66b4a7e51d7044c5cb7ee230336ae5c857bd873e6193b12eacb2eaa7381d7082429b932e7cb58a0a4325c0809b8290d4a9b043ee69fad236c7921c67bedfb1ea976a9f3aadf7678c72910d007037df603be32385b2ebab08ce07fd4c51c66c88aa1b497d4b3bd2ae8a2270f01459a8811576fce6a8f477e9ce16222038cfde19dce9d64dbf019618efdca100857680d301b7f67079f39536e7857d750d2f5c6782246eee663f8a544d342620ddc1f1a88c9da38a67eb939cca8cc9bfbbec1f653d0964ebfa8b6373d6f988c01 +generate_ring_signature 24b6afb3f6d03575e6b84afb6fd3787b6554e649223fcc94f0c3f8aefabf9457 c34607c491db77c2a81d12dbf15e28e3fc50190e43560765d84b1d88a04d763a 5 37604db2c71da54aee4ffa062a3ce264f6f968bb22e195de69667a1f6d8346d7 92ff0f511601d6610f31f3a53c956265053e53a94a9b08e841da63cef7480fff bef1ec8aa444f5d1702357ccf31de57d9d08297471c8071ca27d3e9f30302f6b a0dc011ae5cdcdc8ea827b893a02feaa74556f6a50801ab1d5994f13ffffd133 77ce2aea1d830beb85788d5b9b9ea39a1aa0383807299c479547e16e7c633acd 1c5e52449305df865f8156ae662da8e69d334ee7d0c9ac835a359ce5ecb0eb05 4 6f2b673cbe3900f0094d3c160995450d54eebe0ba9850d48be2cae3d4984db03b3423116443ea6e82f04dab1fb425a1d077f927d75461eba92520b93ab74aa0bffb148c2ac06acc04f90b9cf4e282b4b5492c0232b74d381f99f457c6613df01ecb2f4e32427bde1ef6e1244aa61009990fc247e3f2e95231a3f8d709fd9250368c4316fba9074e6531594c9527f2395b78d77a07d29cd0cf607d3ae0ea98300001420684860a03dfe1ab6525ed46a93bc3207476143794f688492eafd1fc40d1a48c146e8a10d2464e4f9aa8f5d51b4bc369b85032df5fabb6c1283e476d70ce4a9c5b196577df55dd1d610fc3acc5b64b5dbaffe30b3790611922c304fdd009a41d86e9c4f5b72bcde5ff5bda27bbe0864f27b8c839ec2e3c792c53ec8e205cd62c106dbc518ea63f1127ed834dfd8e239d7b079ca29c98781b331e33ff007 +generate_ring_signature c5629b2c40a6c6c737f5dce8411acc9c276e6f0a56e707f8e57d60a7071557d2 743c872c39ccccc663ca95a73a624559e470c89275f9451e99b943a12c917508 4 7675eb1b2c42c881247435df509b540e8af4b715b863f696cf8f1d7def9492bc 2225eb2d6559955c01988be31a3dcedf4cfd6eab26c1b894f0c89b6625bc207e 287edf6cc3280b1a0e57115d79b5b762b3dd404ed1749aee4cdd0f3850bec996 601df0bfe882a553240b1bec04f63aa6592171d4f1da9f9bfd6509f1f76b463e fa9e98f42c3d58380216f5c6aa0ddeadf5a8f7f7e94b0f5e8d68215838d3bf02 1 660f5d8d336c6092f47c0a09639413edd484c38e2e8dc2770e6e1f95cfd85b067deb9de591fd90a2b433610b255b22d5d2598dd5896c35f2f3cd90d5061253042d72db5fba39aa722236224b4a336897b6ab165c76cddd756314010fd831300ce4c133dead1fb448194527b960a901cdec1caafe865f67744c333eff15ca2c06c131d5365395a83b91222e5440e6a696f57b39a1adea63677a452685e88dd203c799a4a792d1f1c16ca9239c7ec00107049d45b124b3f8888940c480bb968800d839779bac97e86c4e438dbaf48cd62471a227339c2d2c4d95de56f9327d080127e0a7adfd10fe06342a08f5182597376f114ba748c7490b49690fd9047a620f +generate_ring_signature 1a4197dee423f190acd42720cc120eacd6fdb3bf10b79234630b8858b6ca9767 b4267203b4ae75d442d1ff8149369c96273da7aa9eb82e40b905e1dd1637e96c 2 8dceed51a14035531d0438a6e2c16815792a3e4d76f0f7b34b5491e4da661fdd ae627eb1310b295996cba5c7958b1d0f0fe5bda5ebe6bfb1b4b75e8f82a46b10 0db7b3861e845b76870c76b143d4f559cf6449fdba4bc46075817caed034420e 1 5baa78f3494b392e645c5976af1d036e70ef7cb21e4d6ab3d702ee17881e72097fa5e0c1695bfec4f1a64eaaf3e9186b79a441282b7ec4d1917921aa0870130484356390e0512a064fc9a6c0bd205556583458c211105bdc6aac52177ba62007eeb0c2687a3d72056194090c7a787b90b5936ca2273ac8e7feed811fdd7e290a +generate_ring_signature aac5d207c0aa7557360adc8f06738e1881fe94b73f57368d845f5682f8096f4e 552caa3ef09555e0a216cf8a78b2e18271373231c4758eda7a270b2ddd71b92b 53 6fb3972559f40e71e36a3f1106a7866ee3ac12c0782692e78c10bca229640457 e883af1eeabbbb707cfe9f543956f5bacf9bbc169183279e901b91a1d2481e45 f1ffd5bf8f58e9e1474d1305a55939efef176dd58763423eb3dffa481e103c71 18e614da426c877dc72f4229ac2b4811fa69f56feeb194b73b1df699b14e79f7 a1ec96815246af7cd69ea904d218f724d15dbc0eb271235a4ff1be126925d4fa 344278387d740c1965901597ba56b536d71aa9354b209819bb4a0feeab3deca4 9ae49f5ae55a66e5b3a4b78e1c05756c13c7f7955805e984e8955bc79a7c8640 1c0fbea44d7ffe1a9f1145a760f6f42f7470e8e4037ba9cf4da94228b91d5380 57eb35ad73b6a99178453a88a91be2ce87e886f38b50167b7d121906883bb4d7 2a7b54e7aaad50e8c817096733116f69a22a72aeee7d23b9ea99a8a381015bf3 bedf676e37a4e4dd53b92a8a469184ddac922854327d98a02e5fc648232bac01 e46ca855f80c8e707cffbda4f0cb6ddc8875548aa8d30e1699facb2b1912ef43 89d6e8228d7a16faa1b37309835249ee56870557877394a039fac2d2dfaa27ef 2315f8280152ce6b1e5634e2419b22dd94aea973193b61d9296dd8bfd93b9ab2 12cc102744cfb58b2c388e52fa9c581c2f4ac84e34073a2a96376c6030880a62 f6974ceea92b921fd60f6cb02e275bfa7f500eaa682c915aec114068d6db88f5 138b0b7687520bc45d8bc3e6d9bfa314dcd1d8ad51c48c449afaaf7e7f056d71 e3cf7715e05664a5cd498f79055b41a5bc60b4b8827fc1fca083ee55822eebd5 4bfb5cd9dbfc3a1c41e59f9e1c00237a46819643fb967b5b92a80e7e386430c5 04e91cdeebb6eee9643337c58c719e44d401eec9b044969798f92fc2208d6ea4 f4be010794473e1db3049ecd4d84d05627dd33be6858ada87513d89bebd93778 b422e821b07ec1531698e2b89d50997475f78f8c59ddcf7452fa7094f8994412 8ff811aaa240794bd5e8cf5d21ead05fd755678656e8f0e7ae030a896ad0e3a1 b2b31ee946f51c58dc3d1e831acdacb308da4c894ada26d92cf885b466da12b5 2e333a1e3ee3b906b058bdb67db9884f2286d53bdc14c5143054b1e6348ecf63 cdbdc45b81cfcaa2bdde6d4319b0234ca2b8c464e6aac3ada947a181463a27c4 846eff34251f5c0076e4e2c854983c4044b6fdb836b1d6958084404c842541d0 31b2b6d776b38f559c1e8f6fbd7701a1f9cf067bedc98b91d5992579a6fb20a6 753c3a97d7a7ac59c3e32b3245b4c1e6a8c65fd79e2645dfec9e08196bf5c5c1 facda9cbfff0b7f8bdf25dd6af2534f64f3edf18109def802733de31abe06579 288da7b095382a572bf2b269f3d2f0dd91468d458a2c50be1139dbc014572af1 7edee65275e7cb061af3b8538a02dd1cb54c3a0049d722b3fc295af17c95814a 90f1b088ff7cef4436e5cad92502d21075b84748c2b4758dd0c1fdf0396c45a9 e1e9df368aacda8282da3cb81ea1758599413bff17aa9b3ed4d4c58a26c27857 7d59b675fcd945c0cafe8c2ba2623064e066fcca4127b04e1750baea465528f0 74e8a9e84b57bb4b07e46a3ed620a85ff609dfaee364bcb6c1dbb28de7f1c812 14fd789d3530800344d64a8b0173693bc41a2a909b18cfa88a5ca700acdc726a a6b766d16ee81a8570f6e7e3fefa39954260442b42c4f51a3b83ab6100292baf 6c8a23d96bd60ceb6b63e8353c2fc37efdd85b4af8ef9d6bbb6cbc56b78f3ce6 2fa3b181f1d202dd58d0b064348bdf31c1dad990dbbc8e059a1b414cd126e918 d2621e0e30d4c067701617544e8c86a0d4e2bcee498a419103b500868d9606ae e654d8b768ecbf0b688d3e513858f9c9515de599c70e4403236436768d1a1660 6e05f7f1c282324b171d197a03ab799a0bfdc371ec291a5dc8ab1407bc0d7e71 793bfc7db631e1edbd61fbec38831f9b5e324d2342ba6fb39e1f066e2d8a812a d869a67a0a327f783d72c395cc8b3319fc55edf427f2233b40200a7a76b3e4f1 823c7157e173f079713580b594edb97a0cc24feaa2356b5c493d927b25e576f9 1f52f97a0f224dae75244213223daead4262a21324f336affcb1186301dd851b dc4d8714ba6fb00db603e63b71095e0c0f48375647d8328bd1f1a98ddbd758b1 52b458e8782e3afb49cf0b4142fdb82de0b9a9b02bf66e396291581a96ac660e cc7a1833b75ca30eb566ec98a16e444022cd0537e9eeca574e5279c72cd402ba 492dc7df7860ada5e7fd7c076a7ac5515934d345ce74fc7f4461b19ee0c95dd1 a393560e00ef2187f5baf6338066076d72d170d8f3f76d53058804ff7ff76be0 77a6d6591d159cc018704b75d4ed14a0040fb8ab7924a6504e31263404ad7c20 d68bc46912d5f41a65b74c8cf7b0f387363e2d02b1cac744cd4bbf48c072e006 13 1dd697c05ceccf65ec1acfb57ed849d8a852cedcfe00ddb20e02f928ea1a90015eb5cef88cc8a88dfdc94707bc2f07d79519fa00cc9e387973116d56346673040d062b5460d2a20ea2e6fbe07372b981736f8ceba7807276b93932ef6b47a20a48b17209e58053afb7e1b4278eaa44900af892e5d163668e339821a0ab22a3076ae9da770c578c56cef6741ab2cc938ab6ef4b2b43f67f432710bc0a04cce60b5358714793a5a1c8ffd54993e6cd4a1a1630d697c82bde9275c0a8acb4e8210a45813e8e3e3984e259ad6f224d8a40e8c476b2f2595adda2a0bae542b11b9309c2a3fd7d38970674d0c38de2614dc651362df4103698aed29ccdcef88338340f62eea7b6ada86f78e7bdd34334230e9ba1e10852a965ea50c9a500aabd575c0cbc3e855dfed20de9c9ea1dedefefbe3790fd88ac21078cb61c919721ec050f094be144e6401b58936c1303cc43a4e3308f1ccf39b44d4a413dc4151afdbf050a0ea5e5aa4e4c3eb6ac9ba32221fb0d945a4e555128d03e591a029b6738d57a0b80518c3b6669b6bcbe3dfb49a7091515e2dc35359ccda1f089cb49ad9d0dc007cf7b8482032bf741b46dc0ca5fd8019cd721450bf5b5981378a39e6fa4a39b031cd4233aa74834bdfa15fdd65d798fe8f31fd13d428cf162c97100181a3d4d048dd9d4477e80d6ed85dce7496a23f1d4ab3fa28ccc9ca29e57552b4d1e49200e243de57989bd4f52d3bd59a00c7f71c090f743d84a16bdb6f673f34c065a3b0433f863405d24ac07a162bd6f7679049bdea8ccdee7930aa0911debec26de4a097b2604683cde6475217c3477615bb2a8d0dd136dad3142b65f5a79e923becd03ed30c2a9fc83b62d3eb7e24fcdeae4a11803a9a295dd4cb17e3b7d5f61781a0175c02031a60fa336e3896d497cedf922c5b93eb9b69f1bbfb7c8b8310773ab02e8f0dd96bfaca269e3e2e494a28a16cd2576b6a94e2d3392cc4e3bc1dc30400fcb46046f54332962e59f82b8dc3064f935626b06fe34b6101be66ca92b846b00dab39822424ca36445e17116067a60bd9bd65d1c1d06c59450e9e7d6028390007e11a696a8b3ed26e85ea873ee849feb11d3c7a794dc348609169ef852f20100402e537262d78915788d6ba8bf39bfac0cb7e8290c055469346eae64cd6a310560f0ea2ea24d6884bc6c7d5f232c13b173682de33a02c90983f3d711334612022c6d4b839e9b7d0a4be62336da93fa2da98571d3526ea5a6947154a33f519b04ee064c737323c1c3bb8eaa6a77e577c5a6d7ec353af451a29fde6f0555d679024e542d0e2e0c6256ef74006a9fdfb36591e357ca051294d38957677c1827030a7085d7c1f272bb302e6ee55b79012289afe9ba505896d234f31b3da41ee7480999c585c425953cb57973af592189e7d38c7112b3a81962294673957bde3c2006b52b9c2030646d43c276a03592e501fa7b590448c3d7fe44ef835c73162eb200795625997643762ae42dc7cec3729e4c32820a1880202c1a9ec439af5f1f880685bf74beeeddcdfc279a1526ccb0b82fa2d12f62e2c5b1338284e93b47be590abf0d73d4725c4933d265f397661ab8249200ce7d01675c6767a0e411ff1b460231242465e5295bd9fcfd5814b2766bacb1bdf8bb5fe5fbf6dda3a7943d925806c1737ce82e4400f4c7412d819a344488756a292cc5a27208197e8ed95e4beb089e627ffc5ae59671affe6f12d0cd62fc4f7888de36f4c22d9cdfbff3620a270357aa906800d87e3a3495deaa701999a652b82aa581651b0f3ad643e3d31a090f30486bf44c7703b78993482e8e0bb99faca2a99d108848711f79b32e37b10307e6c8b2041ec8e07aca9e6084edb35b0e641768fa8acbbf0bf3e20b047fa7ce03842632f0dee74e53bd04f4d2bb6259b97079b5ce04935021c0d79f06fae8c0004d11387b1b2d75cdc301e4c280c77d237219acc0719cd9dae4045d0e8f828306b91af39536d6f850273615b51aca9465e8b65eaa7b4eb05ef11ec9990161a60abed020e9d2770ecba25690a0651728110c2d0c27e3edaa7a1fdfc5415534b503c6439bc24d1c0fb445acf4b4cba99f4ddb40d5dd82657c518fa95a0433f4410c52492f96ffb7aa814ecdf0ec685a66170816217f125a4a1fa696cec1592fb701f8de55cb334e9f78915a1e3dd30bde5c66c9f6fe1435d7aa908e0245e3ba930bfb0f02960cb3cbd3d331c2be7e2dc1314a8bf67898cce0bfa63813522c4b900eac9f8fe14d31f2f71cfc42d5b0bd48ce3c6e8d5662ffc9db50e7ea7ed0b50200525c20ff6e6302585cc56b729891c98cd3dfafbd729f7e6dbd6338ed4a8a810230b8b373d84ee0b7a4d3c28614ac3f934c366a0487ba62c4ac23dd4224707a09ee2e2c66ed53f84b026c17fd2396a3be1be6aa6150c9dcebc8e13c02a4ef700edca35862b5ce285455adec1e581466254ae285c444b39decee060595ab85bc0434051aa473ae5df96a0a1cf114c094365893059039713a22640e872ed944da06b7afdf02b93c04aa84ea90c695774eef32f50b55e6c5ac2c6cefd0a42025d0073724cd5cb89ae42b26ee3ee9c0c3e2a8e7cec2457bcb77aa09d7e3c9593e7c0fd05492f53b24c297d0314a93d9ee73dd7393ff197f455e73f633edafd8d62b0b2324b4295d1b14d288f78d42cd87ade5aa2beaebf9a489c061956e851ee28001abd5bef6f8d865c620d3e29533fc149697c14a5d5d16e7142bf3dc413429680892c5be7ae973c0db15461c0a7eb4c7c6fa93e9eaa9bf635b3dbfa3bad5251a0ee943a16be6e9ca58ae2758c0e73ff6038e515a5a926e7617059e0867c85e89078d2e2ad5bcde287e8c860edbd671ab942778bdbcc1c7921ffc26d337d9af1a0e115f43fbd394b3cbb5915aa47eb3246af5ac1bb52a139b02388feee54eb47004e554bb49b97774c8097fa018a7d56a68f670b35161d2ff5bab6f53bbb009350ce62227e052748a445c4a4fd56d8e69c9a05b8a36bf049eb788ccfeb4e3385901912ec481893a01db0ec5a8a5b4e40a1d6120231e218018f8414a84f1befd8d0bd8de86c55c0ec8bd529dd4d3e7714c9a98c5ca227a337549a04268f00576860c1f75cc3f4e0ff770e84b6840459a884a3dd11a5c4a9f2bbd477dff1fdfb2e6053ec432a735095e59215e32cb897e9f12cca62bf65daf38660ab17dd3985cb900efbc7323d1ccea72299084ec1ce0b0d58a9419be4d65d09bc24a8a2dbb7a4606846b000c73ed19afc1fee71aa3c864cb51434158c696c9c76023b5961e2016041e7f621d17a76e6481cb8bf28ebf04c213c8647dab68667b9d596267215e2e0cc2c40f8101abf8e4b919755f51c8acc58da76fcf3ba38eea4003bac28f366e0360bf5e632a3538ab92e07fcc4f154660e3bdb270dac301f92e519d46c3461d045ba6befc421ab03f907849cc21563e05ece092e26d725c4974157cd55c1abd0f7e03fd550b18f75e96e22c9e159fe8dfd629363caf0ccdd57bf2f6aa93c31d0d8e4946b723824364b5e2898dee78031483954d094688bc0925e486c4b9102203dbbeeb14d648db7e79de18582de6c5c7bcc7a1fd11daa8586f685755a4d1b50acb47e43bf0f7b0a919c7bd4a9b6ac8b1df838dbd556eb327516a04a7276a5d006fc4e5e57eb933a93f7ac57f2143f3a4ecbb01bf894e50917e8cf04523c1470a141fe37ad231f9a074fbdc2adf2699ddb43afbaed1894c27a0e53db3ace41e0fe58676b2ad6198c31c31d4c2c9aee45f3a68d3085eef2e7748ee4dda795a390d4e17ce308d2059433eade2147578cbc92bf877179e62d11feb03448a00daf80e13323c0796bc7ca639c95034ed47310b5bf98fadf5aa628fad189294434fde0e1aa0f413ba0b9408aea01da087f516314d5b65ac164f6242fa44b664c0918405c5134d7e5a1880a358e4912d3d9402f55f2528e1007a2875f74359223b6e490b7cfb31f3b348fd689fc57ef24560f0b20f4aaea47f04994bf5c8cdaba93e9d0f4654a40603a34892e68b0bde87570a04f5d4252701738e1161abaa507b4bd40a7ca706b235a061dfe9caccc6ab7a77f3959d28e70d311a41ffa12c8e0553e208d4a9ec6d841063fef1b6a36d98bab2f3953b4cae4400c32a1dfe79ab97f51209517b630ba3c6e86bf110fd27fe5576fdb17ccd7742c48c2e5652cde4f4242206702e4e864f210442545db89086ed156c9e12e7312b6e6d55124ad65d7ad2910be9cbcf85655bae5c348a3059539ff1e13d69644cd6b2107fa1783ff16fbaf5042da2cd33c52c9737c80187d23b8ff82703becfa82a8436d113e7408e475c430d535079c531c3a632e5b66cffdbbaecaedcebc107b1c0ccc09922bb03ff619f085226648bd8ff368129e0721315cde38c6df25c8bf264faaa7170f9d36e2f8b0c6f2b09d6dc03d1a5ed21b9661d9dcd4070d79217af70769c03c29743929bb809ebdb5c0334231f372e0f241cbb60cab80b763a019cc65f40f466a4cb35b53d016badc7705a8751404ab345f139eccc757e4e226156a07340cfd03b6aacbfb10b362f1e874fa8da5609e479cf975600afcaf36fb8fd6b420d1a9e1da0afd5760b12d7e4a82e8b590e594a0c40b32994c2b2572904126df150a76d0393c2264f09fe8d7e57b1515326e70d09496f7411113b3f8084d224e4b2be5a7b18874e0507feb653c395a5353f1ee55ea1f134aa4c915632de158e6699af6e9b0c366b580e4e4e29f290eae1246dad892c9222b90c414bf12d7596354e55ed2e8f1f5a1502 +generate_ring_signature 1b9c52310cd90de6486e3c8b73ec646b0da895b54b118acff6ecfb69afa6e346 fee5ae2310a6b91390b1f30f2499faff560fb74ebe4b32f965af0edbb140a740 1 8084c2112b5d153f5086f416d6d1c059843bdee8f391f547ba9460225a69cadf 56320a68733e538cca2d2bc41b01634fc3b9e2ae3f9f83635b2574a4245ae00e 0 9e6c9eabf842016b6a3c949da8d02cf32997f4aad8332dd326aa5001ddc0540d5a352ba32fa6ffed3d6859805145d76e3d8631f60ea059fae8e485f29696340b +generate_ring_signature 65e7321376ed6c6696528042a65a9a4f6516d65fcef80214808c0c3230a52087 fcd664a50e9adb47d9ae24dc83f707e5178d3235b84c17e9a6f586c0bbc52a47 1 42fb2300246f28cb82112974815f4c14cdca8750a20b25ef861621effd08c45c 8e82a603216e1835a583482e580e635a34b431012284d709815768785245f800 0 78dc036f67afa2ca950f9474b5be60d764ea9eeafa4b69d1e201ec166d3df3060481f0501f38208d64b94a97599a5fd7dfe76bbfbd6e97496d2a511fef603607 +generate_ring_signature 5fc776eaeb6aa0303db0d4397d093d225c8cc0e00caa55d5e3110e9d7aba1aa7 5745637caf7435d578fb680de1416357dc6c6ef0ef7f00c0d98952cc3eca7d74 13 31b7451326d0a7a224f17225a19e946750d81bda5a2f56ef09fb60bb2172a44e 9665dbe2e581c02838c7406b1c2632ea5898f527c27aee64001f13fb69d4e46b 43522177f2705f00ce314e061859663485afe95dc1103d184dd8445b51f8d943 d087ba1e5c49e3d7f627e402554bf365e115eb049d1f7101bfcd02bbffc09d5a a76ea4f37eacc9214defe54f2d59017a3d410499c3a6c7784c538d480764e2ec 881632bf12f572675667d5b546c761b3448453c771872793058d7e74975d616e af5bd86056c8494bc987c9c38ca25b9479c98749dc1db4a352ddfa119c436afb bc6d378f748e912b350e8716c0965c91fd00798534a25148a9cc8308b0ef1922 bb0e87d6c20206a4237b34b1deeab57891c6750e4d152e28a6477400e4d5b3a8 3556aee9033cd19cac0d3aba95b99694deb7dec82a18509529836cb013f7e656 1b0e39b149d8425fb452857732ef05daab09881647d5e5e648f57650a5fcc5e6 c2a218592130b95abb79673da2204d97970894818e0cd4ed17569c973403aabb 3a3a3c9771727a8adb3029e1022d766357396ac444aa17f75ecd13b7dfc4f25a 20fd014c0ce804e8bc23ced4b22b168bc3c94b8f76b7b0f2366c91e4196e070e 7 93d772e28c853f001c864f4cb3a1c75c1ae34b180bbc3c638ecee1230d8be30777800b59cb4242b9c9fc859e506edd2f26ac3ed2d30c64c73be355e07810280bc7d4a8e3dcb26281dc6e95cfe861c5b138292809a77d0ca1dbffdd2e2066a00f8c7b79688e1d24aae7e18f65740b899b5e3767e27b36926faa7f1321791489077439c6132c8451f169ce7e96d0e05dbc9bd748ec339749478ef8756767fad10a87a271d42874b85c729f12d514e49c9cb26d6ce7c5abb96b3df4c99a1db81c026039b0ae079dec47b1b861c0caaa53ba18f050cc86214af7ebeffbfef8908b047498ceb0cfae3c52f7c5454d337f11322d0a9d261eb65aefff524a165e3cab0885091ae69aee81e0a85cfef61a0b596fbcc5b864c07dc2d7227a6cd95db426021d51e7a8f1c56c9f786a59f2ee768c1285e526c23d30f9f6f087b8115fde8a009cfbf59104be29e9dfdc982ff880f840bd4865aaa5147df8ba3d2739ceeed900a1069774454116bc7f689381a9fcf5aa2c6daca1b743c08ac40f2ec877b9e80ed491321eca693a74d6c5e19fc63f41bd9124891337dac863266b5d2cc629c80883757195377f736388e51c8e2581321112f3792a6d2b4f64af3502127c6e060edd4987b7c916bbb271c9601c08c6a985fcb0a7eaa76ce955e5d3ab06823d7007852984980aea4543ffe64479992f5c5ec145bce52f76245da21bbbbe723f47006d09a7c24f8409876937284b23279e91a3d67e775ba79c887ae150372f00dc073dabdc3d371b60eac924ea4802335b2814ef81fd3f740ecc243da8416cd6320eeb6cbf23ead4ed2d522c94c445c4ee3c1da584b71a7fa7f35151733d847ae80a48ee4f3883629fdebb7347295b7823115a24e70cbaae2879c3eabfbbaecaf50c38f9de0b60bfade3951de997742c4b997759a25951d08ed2b721eb1f4e8a7e091b871cb07485b3861957a21201f9372c5e21f06d0e12b6a0652c3745f5dbec0bda07cf43d0e9c70f40452d340738bbc883c5687bcfdf918840fc3553cc8ecb05c67c944791304f34f04bba487832fd9b04a1d48eb95320b820bea53d0bf5a50f624365a429a6e79aacb5055c298cfe4db2c23a0be3be9ac39010d71eb2cb3d0ce3db316df6852cfcffabe94172f31e513e25092d55b944f5535040080e6e920f +generate_ring_signature 1b670fa7fab988e6f8fdc8fb107b3d075faac101675f315f48f069d363482811 311bd02641a786377befcf7f879163d21693f0eb1bcb162e016f16961adf8cc1 6 81b31e3da8c61e445c7f342caa50aa1f14e957cbbca3d541c909dc5040436732 bd9772f8dcb21506b557824bb497ef50079ea93d74b936ae6ee40fa1ebc5e261 7a31c4a1f85d63b66d38c7656d27611f99b933c8b97c1181376acb149dbc2446 763dab71cdc26c00204f5d24ca3dc0bbf122401d0bab86246774d04adea8d2ef 19d20452c993dc154c00d764ea28ca9c18f92df93067a40b90cd98cf6055f2a2 0765b3b2cb35ad43f4b64d7da4ea43c89d080c201bdb45d5b546f1ede6eafe4b 8ac480f5d3827bccb2bcf68e45cb0ca7cf3e9c876d80405a7c455b22bf68b70a 0 57b4559598c54ee4843fdc277c20f1d0bd86b0193c87b2efcaf1afa73133e808b7ed6ce329b8cc4103501581290d9f2949fe5c7a5db53bdcf4d020a34a8680016b31e9ad695b778bf14f5ae3043da1d9d3901b798025b5e62c592decebdb6f044adf0117bbb960dd7ddcf9a5d4c0bbe338139c17bcc5c13974485487e6ebef0cd32c9f153acf7be0668b03ade1e3020b7cbacfb2738893731ce73f9dec630600143c099f919b16be1758eb553ad9c780c8290e2fe1ec44d2fa6a2d7758d8fc037ebd2dad517cac1f698052697e10abdf35948b0d23332f7c264f9e55f2903a0385f3b8a38b40be2f0e7a4bda96f81f60bcc82ae6884b28f01218dfa6e450b2062fbc622d4bd472aab4ff6c8da0c254370aaad03a0852fa5a2dfe58c31a0fd400aca0e93c7dc9150fe5ea164b773b5e5c1df27fb9d72b1beb82f1d11f0fea580bd6273c34033b08a16e927542941576198f359d8f0e5fde177bd1a6ccf4ec9e0492b56a484be513bf4f73390537dbce0dbd6d7e07c68c128376406b636e61ae08 +generate_ring_signature 89102300bdccd553ce352ef36bd8cfbdf13f099c02bd18596e3d42e6239bd3d2 66b67ac092566c2a368b9a8d9ca4c4cb6a98f299e5f410c662017950512d6031 116 aacf971f4cb8083e4592930c84c2f7e1e814359c56cf8595064261e3a57062d0 4286968d242a26dfb7144780c2399aa1b000e5c64a7fa136663d9e9129974657 914d0875d0b0ebb1a309ba776dfe0a0e0c3ccb37d57da02a0adff77911fa6cb1 25960a259e5be8f63b901767d00eaff9e3b5b920f6080b957913c065036357b9 f42f1612df591adbbd3075dd4d7e13f632262a2aa4692fb66a9b23f929520ecb 2cc95b8fccad32778dc53e534511749bb98138621eba4b49df2ee579c12970f8 b613d3379b8bc47e960b43003a77dee82913090ef169ec2c24bc1e2e849c6ac8 a2fdff8411483e8012060880b6b2ec460ab8c4092dc88b48bd2111593221a425 3991843e89714483490b27ae31f275df2dbe7e29b0adefd7cd2a985edc5e69e1 b04e1160aef718f8095f6d74b592429a04998db7e3235af0805e2393ab257f47 f56c8839ad45f551557e2f0207ef083f0c5ab8afd19a093106f079304bf1fd8c babf3b67c8a305bb3fb26c0a0cbdbf11bb96df24e36903e5d7931d8acd8a4def e08078fa1b5592ea810f70aa9ec2b5af155d158cfb72a4339b06953d203a98f6 24de47d9b5fb0f83502c076360a5f84ff10fae7c178dcb6899f0e54d04c6f744 bf656a168108aac05e7489c23b7d3aba492ddad0a7305b7a235cda9b5f28d62c 20df1335f52c54cd9a273021327eb3cde3927a2a1c589c0b8fd2bf5305542255 6932a7468388e9361a00b61444b2fb0eaf68d975c554ffe92d301fa54277a9e3 c6878450d4032a0a632133777ba8904cbb2e6034d05d5ccfe183d9189403d913 27780f528549913bcb7d6bcb96e14c6cfacdd4a229135dc06d7c5102219f0110 92a1e11e5d0a1e83ef1aa41bd739c136fe4d3b2585c0d8ad15061d93de77d704 7ca5bca6af948f20929a81e95d75faedc991ba2faccdc3f2d942265d0e60beec 7d0299200ec4b03843d3c9c78d33d9cb871902c2da6e871f5328e1330038991c 95250393ccfb12b976d783e295fe5a0986370b05c48e564c2aa5d5c3e3d49a05 81ca61171b3f4f312a2460fe2f3a9a3d70a4c648a1549ff47ac4f621ec00e8d8 8eb43535fe2ed47605beb83118cde781c3699ec00473a56ed1ebb72bf177b356 03e96f6ec4eea800c6f3ef8b2c43f31160570d383285ecb1738a481cd3d5c335 209433cb2ab66891b1f9dd9fb74a75dcdac2639611f72890bc4c2a90ee0ce990 1c64633169c011513bc0a3c23dbab9ebde0d84ec021815b5efd749122a316d39 aeb62e7eeca2e3d46381c5411a47372bd9ed18db465d99a055a3b47c8be3aa1b 8253bd9c2ed9610658e5e339f2531f19fd147d0782ef9f60917e9d06babb7e68 2728a4782111a52f676bee5c3baa8bfb5c346b560510f38921cad69f9de907ba 12d57f3b4d36edf9656e67cff6dbe2d6bae85ba9a4365d04c066cb9b85eb4c11 e458bfe87a0561429dab19d989c37b09726656c8a399d609559db03680c946d8 e273d0effd007e930b1e9e130b4f87497188c4ed48fedd3bc34d169f83735576 31b09e291aa05bcfd743b3da58eaa02c772b817aff414d469a1f668f41ca908a 2309b29e52ccaec650074476470410a53fe1091621881ed61e30240b7d8e5ad6 f26e0a3ae0c0b5d5c53b4fde3a017c0dfb1cc1e67c7e9201c484256c02fbf584 b2369e479b65aa0e85c6d61e312733724eb93cb2c5b34b088adfca7f61c939c2 bb0e268150f215a3fd664363b2ffda9c7f8cea4c47c1efc43a9118f09bb66cbb 71b08cb319616d98b8ecb176a8d109ca5adfc90e7d88838cbf6a92de3e8c7ecf b2e5781e43a4b2c32d0acd5c373cab979b290928728e9ba476791c4dbdd9be32 fa305e51d4f7c53dda4689c34856a691ae3d6a9d01ee043f2106b4bc3787dda4 fe970cb89108b4e704e492c8db64cacaf564956bb1c47610ee25245a842fb210 336aec71dbefc4e4e44fb1e19239080446d9299b0149e1fa171c48d601a41c8e 554b235718cac2e9355720d4acc8838de199b59ace20cd1ffd575f0f4631841d d3ff0d68b3ff9683e5bfecdb8e8377de4ec37ecb155cf39c4e63dcf94b1ee979 f2521d0a0e9836e48760f0dd9910f229175740e2c81ecdd62e3859a0f4e0c7ff 66b07816d226538b578bb1df23e408d754a8a07f3ca5b6374ec386c5134d2697 ca59cba4793221d8430c41eb4ef32de270d0c89eca0b858b420a57696eb30be5 c3c213d1c7effc9e43a51d247f0fda635055491dc26a23201ea60758a37feac7 cb0f2314b2ad60b4230957199a9de58698da7811f47847ca973102a66f0d9498 c928cf24971c0890606fdb0b56f17b9409595764e7e398a2e729ee7838b0de64 b189e86e14c4ca5ae8b4cb715feaac84b921f3bed879deac20c9b27799176d88 65e86d5133b1d43edb8213bd3bfa7babc6e23628e52e36cdec478d39759cd6a7 3407636c7c04d71490e9edb5839531aa4724402b3c663ba22857af6daf6c9353 3445879109faedda39c091848b3b49cdbf61ca6e95ffdde56bcfa28da6d9d27d de4c9c94c1a01d5d177b47355118f70a68e7cea90d162a4ab67d7f8b8be582c4 cd847f96764801152575a86b30e6ed3a75acedbfdb16a5576d3a094342f599bf 6890ecec3024edd3be7e67817ce51b8de27b7a4feb288d8c4aaf6c91e5e909ad 66e74b36d7939f347f0acd6699214d4a78a016d9c2ca512a6f6112fc4be6bf91 a582a1c2948b238fc1de90feb779b9d11e57b06410ef58e74f565b6e3dec4fd2 1d58c0007cbd13072dc8aca24abb0b6cccf238b47c897a1010a300cae267c021 a309f20016a70430700d55c29521f51dcbb9491ec7a7be3666a0183f7b5cc032 23c15ac582b1d2443eb5b4e1aab30a44f108491057a87064a1784eb64023e96b 49796b6bfbbcc45aee369a4cd875e73b43fc6e108ee97d813dbb82f4227cd821 008de8724f40b50fb90cc68e804d395de075bf3f40888741c98fcf0df2cff0a5 c974385a5536e2e7018885cf4efe028760084ba063279d848293ebf7cfb5cd90 827792ebb3a8a1283d94fb063877561a4e92c709e9541b7c87817b28ed185696 2fe3aa80686718b9739256c1a433a37109c903f0be3abb74819cabf35e0c1bb7 e93816be20d1dcdf6ee39748a1f08e06f8f39490991d3058abbda941329c3be8 ee1b391beb2319d8f67e7376e68c069c0011ccf712f5351a82c13552cc890047 eda56aa82c4e114c8aca9636db3b356e7ad9c76c63acfd1ee135d3a2ec3393ac 0bf5483e4bdcf85336f82b77f70b1623d201ff601877bbec4b7b4963268ab62e cd4567b648634eb4ac39958e55ef352570122929639894f31abc61adc2609fdd 0ad0e927718cf2b4eca2e50e0d27d99c75cb7cfd33fd63b7fa7ae38387d92e12 6735f7d46c51519a4a2d475899fcae2f47e08c91a08d28faf81ae21611548f64 210e26da394508be17607c6d23d08e6d93ad5009f0677228c754d212a8e084ec 70bf02ec4ffebbce2020b5db776c6eb463b24989f1f3f8aa2e1bca91f2a4e315 498b3093b6563f383502e489fde1cc1201acdfd6fe776bfd68f674c4e4a2e8a6 8e3a7e23a5cb28de1bd8e28ba5d87a1f1f234fa405dfb5f9206dcc1df31378e7 9dc0a522c312cc2a6c95d954ded0023fa95e049848cbd06cfa85798b91d9b96a e84f3f5612a23c4399389dfd2ed6972e6744b860a8f110ea83ebd77a3a7f632a 670b5b7c96794bf0300575edadeb40dc40f30c52ab560f55a8f7219c2c7be945 b97fdaf538c771ef870edac92c52b266eddf2f41a662c3b812483423f1172f32 34fcb11256ef3dc85e4100bdcecd84e89b64d9c39da22b7f7383ff1b172f0327 0d735c44c9c7c5502d4b4b280fba770b284e2eae7f9446d0964bb6ff7b4e2f92 08f03cdfdeb880a685504b775045779c86135aa6dcfc8e06899bda0391141946 865c08b9ca9748b72018189051fb1282dcd1662aef708c62593dce09981a45fe 647f241c0da6d5e897f96f709e4c5e0ee7db1a90026e297b2b98739662599656 b424e2d17bad69bee7e51c8c8c017a3689b4cdf52cd016af5e65e7084b3c380c 671455db63d8773c5e95e71d37c3bf7d3e6316a39cb2fe7d234899011458c83e 28119b556f4048b9b31e7946073be2b62f74b74a56cbd31fee1cfbc2f5f512a5 a8e89c237d06199bcd94c030f5c58ad1a3caa2ff5bda6d45de213262d038cd03 4d6ae40c4e28276d908f10fac7db8fb0954d0b09f3d516cb61bd9bf9b5df9fe1 7fccc1bfba50e840563c220d2520c9f77afef38d9dfab6e01892e6345ea100e2 28e363ec69911e6cd79ef7ec1c6899a531ca6aa1b00d00f68d71cfc038043847 21dc113dbc94fad84468f32b6b654976e9e2b7ba9caa011fc46394cc0efffab4 513c7e81377e13bd283918a5a44a5ea8bb253f54d554fa760e04523c27978471 f121a815f969fc0597b1b5c518cd49ba4589394fc511633cfeaf0554a33e5bf6 19b4883add93f293a640f138d0599d8abd50027f605f68e78e398568ea444647 ff453b1975ed16f8c0e1411dfde72046542032a9e753b4cf9bdce4cff141b734 4d39889a38efe6d22a0d3569d79b2d5d27a2caa9d40f8d4232db0ceae78c4980 471dd89be76b7673c0948e9dee567ba70acf98d02ef82b8ebcb73dba23a25aed 21a96e9e7fed5e8301c71774469297fa1d0e095ba317b916501070d18be35eff 1529c4c48b69e33c78314005df30b4e24f25341538b4e4784187f8492a95ca4c dd5756c71342bc91146a6d89dd9a1755b2e67297dd08ee2ad47da6f88712cfde e223d3cf9f77cb85b9443da601d925305edea5d1f86b69db533edc032dec4132 9df21b3f335c553a66f4c6b1dd7ac870dc885de1b3323e86dffb116d3012a430 c545e90cde0ea37de654dc7f6cab3042b9c53ebb923580740bad667891f34556 cf75bf6c505a45d0bb8b966e4fd8fcdb60caf6998310f13ef23d48e9f8da5f2c daa6ca75877e1e7eb9c9a1aa990f850d3748ed84dc65be4ef4509ac2dc15a50a 93d1f3b4a03ece48c32a6e8f2ca589953ea4eed5c53798a388e51f9a6a5b9e57 0e41584b69979e002262d1cca78e9ee773e22a4458ebaa53de795a9885051fae 4aba7f5eb551ee6c25d9290c10ec73cc2d1fbb0fb3646f2c3d2959e620d6543f 6e0fea29e401d70f40f8be4d865f7db6add2fab1ab82090f3b85e53bdf9a6cb9 743899b36c46807eae625a8fcb717ae77e7119dd436a6cfc11a7876a1201309e f8fc487e376e13bba04de3825648ddfe435e78b4bfebb43e5b0d40a33859a500 6 843bee3021f19fada8791ec911e9c879fec2ee6eb8903db50c2b9a71ae18b80fd5cc566d9493ab01078495f8163fedc996a4a13c7f1170436e14b1d914a76c04e0082e8b1ee2f2b3cdd86e8e3e0f68c123cc8c04bd517a25e80a681d9a75bb05b74eaa1b946d1b5af93d42bd4a1ab49f08d33a1bdf0516bf110a1f8a064fa507122c188f2500651d5f94b9d44b449d12303442153b042a4769ee3dd90b01580ee02c0e5036db23d70bebd4145f739da4a8c6b9b9682ecd36eb591e18947d00096f41de0c51e66430a23bfdb67378503c6a7b16e5b491efc4296254070b099d0039114200b61fcd7d070aa2f756fcd1d6674ebbeca19b7f04627afe036012a80949e6c9387941d518081094b9fd1cabea95e53289b62025e801c5a2cd1148160ca04c483d4d8a61ebf93dd9aae43ff8ad33c344a983f80babbbd2dab1a6644a0d54610f7a546840185ec5493490da7142788a19d6c4286fd32d3566e12166600fead97175768f8b81fb354f20e923fb92ab563d3b67e238b8c04cacaca8323b0e3047a1ccbce80e2dece176a279877c654f6d3640697f610622c8cb0741ff6f0b5eb0c327fc36df752ac73c1d037b197eef9d2df6b875c866763491d9977deb0d73b68b7f5b71e13ad41b5e9e8463da272b5363679616231b7c3200b21c09c4098a3e241e35c65a15fd6bd2cceb3e82e69fe4780b3c963af318c600e020cb9801b9277df3df1cb89ff13a6e51698ec34b6b968bce214fb26f26f9a1a05ed04801e822587da6d43312701ca6e950ec74a4a47404afd14b89834834a752afa50206128fd543095165f46e2fc25e94bf5ff6b7b8355e9e4788f26eef4dad0569e70e0099fa6f66143faad21af9abd709a65cfd00893296d54081c055078e8b6bb70dd791e00d92dca8073a4e6ebac2f3a663aff43ef9c1823cf2844b0173079fae0cde03ca32be734cf8c5f908517ee0473a548d7a7fa2e3f464d41910480dea390232942a44c00590373277eb80b03a6773331770e824e1fdd26d307003f9d3f008ca4bbd93084017ddf51053611ea8cfd4bec3c809e34481bfc835ad9ac1daeb0a1174640168b4dcfefdc6408f46a94add4275a18e3ba410fd5777b81d8bc1a808ffdc6b6a82680a0b684aee0d7b2814381d9e0f281f6f6d19ba5f22cda814930ffa0f447be2f7ff2cbee3c71a41726484b8816376c192e6d8818803c6633f580a4c31b11db80507911137920be7bc1e8e94a5ef5211c3dbcef02c17d6e0622204458e4489b6278c9bf4e6dc37f5b17ba5afa092b3fcff6f39794b8a5aeac3a0000687f690a5662ac5ce6cf563ac7602ad558c35e8618e2d0eb2ff8f2f5ad508083cc274de7ac5c1661f5865bc14316700d1bcda79622a6c521dcfdba2152f8f0f79c73e27aa5ba0a352b1899ce188868cfd959ba6cde3f1db5a82c2c61bec7e0e46b3bbc7ae294395187a3f6ab65fb646be3595609ae8190cd82af93602848307db1cfac6900d65e82ca93f66e0222bd254e017d1f23022f76b22dbc696fc0f0c699aebf95bfb2876072221a838242efa4c41e47f8cdb231b7b6a4aaf62b3fc0ceec422bcc71e68b4085de03bdd36f73bad8a715b975cd6ed87394a667552750f4a7c45065ff1da6e221006fb6176879e2e6cccf4da34abc5741f0e9c9bf7530b1a3ca21a5c8c7420712cdb0ed3336fd4cb70620e2037bcdfb3193d6feb4e070fc72c6314917a1c3a051781fd5c138706d0de066f959e03c3fdb32e84ba42cb00d1f4d50efbd76bfb78eb50017674e3fdb2536f7fe1d86cf79fabdcd9ea1c700b4438eec37af8005d7f22cebd13b496a0d90eadfbd4943b0d120b4fdf9e890d0aaf9dc3ca85c63c7fdf9a8463984f0a6411324214b7c889cad2f618f537a685095cfbd0666b116c22798bfe2b2ceb0f247de8756c3bd5f7ab17c158658b10cb09131f92300b295fab075796927244d23f1f04db1da1ed711d4e745d5bfbcb9a02ce1a22bf3002a1a4cab1dbcd49b606e40c53a91aeaf6bedf01fd53f34b31680fe11f46a5cfbb0996ea26efb4aeff5a8c4befc90a3e76edcfe4c5eb3cf7949e0b9a1ed381c8e6d0b844a7cd3d0566c43d3c87d1f0284833466d9d49c6d8cd9a067d2b3565141cd527de923ef38bfd5699d7f2366f44f809a40461678f1ed2cc0d4dae2bd409836c3620755efcad2ecdae3b87de6be8014352c9e8d989c66b3906165fecba7b494f11e40686c2d46a28602b3909990f2cb38534e37da6499db901a6e2489705eafc7aabe77a263b0126e36a288437d6b744777c9efb7c1814140944de7893ce7b02a50bbd9c3dacbd4d3a832a1849f4f690ef437ca32751b5280880e85f355e0e3a7e6fee12d74f3aaabbe3d800f76c7a99aee977da97c8168b07b34272b7fc1ecc8711a600a012ffd2747d1868e85e312c5fe46533e28ba6a60b61b094b1501cc2d7c873153b1b689f091eb471f6c7053d1ef0c14c61c50957085ab26191f2e43b6a3bd81b94778fe73a457ef7a092da38923cb7bc87f1ffe405fc1d3d74ec288436d39a11b7a937079d8802d53ee484de06071a3bf755ec22040fb335cbd138f7973b8eb5124f4f4408f7bf7061e728bded1a9dfff4c36c18036d3d7a2b8d3dd560aeb72c65eb5a180a04c3218fc3a9b25cacdd0bafb2e3d00bf7e9b7136c517c6da294ca2dc0fdd27ea0bb8c44a79cc72ee009cdfa9c80c307c3fdaf30c70efd881aa74f3ecb22edc67c63ac557491f5d4d037a14a17390f0df51b9cbd46cf4ba88d64edde5b0d31e781e270458dcdeb2586594c1a441c1b0f3d6e9fabb7d8098e2e576a4095d3d233512dc5a33bae8ced3c4b602dded84b012e5cd5a7d801c5a2248173380cb6d2044330f1b833397fe85a65ba0815d44f0bc5dcf3740089f0c2fe6c52ace47c649021404f123ca9db6a31c3eea5e1145607161e8eb5c7324c58061de7593e9cfc9cd82647147c9350cc9336e811df37760780e0ae17b711e8f9ad8ea550346520f8f5613e5393ce996044b61db4d467170e90d8ec6616021d40955aa6526a9159d1004f33ea9e480e3c1f70766a174fee08d71c7231079b69bfb86cd32eaf18d1e166e70e9ffe92f299cfd29625fb3c20077c0bb0a04e0164c0c442a95429964d062dda87f103805d71f273fbd98093a905f3bfd665c411530479d358d573ef0a60367ea9a39f3b14c478c6a6a3fa36760d50626f2f9535e6e341e26d1f5ccc0a69c7acffbd1d902c958b2bfe234002ca0fdd4ae97065ac8127445893f047b1e8b8ed1587e4380b504b6b7c3767552fd601b4dfada2756e35f729f0cdd6464e2a3b55eaf2f617bd1f2d22cf7b4c37588a02da8c071cd2d2def07efd3dff48f3ff417257899a74d6c4cdc9c77c1e0eca350f8d5678f02da637d26293afe30b11787abfcec61e305fe0f862642ec4f58aeb0bc5804070564dacde4cfa88fa549520d6357738130732ce6e36e40c036079e00138d7e752a8f849a9130a10f4995ddd5d6b56ecfb598964fc8b933f68a3d650046700e54281dc187872ec982a30f3206b1af2bb2d079ffb6db148e33da687660e7648bb70253c3e6ba1cfecfd4e7f803d70e76a8b68ad846434f043546e237809d2bf48116abba1d2948aec018e1178679133c4279776f7f23f980a2916a3bf0c06339e395be2bf4d55ce3dee813d12836183ccb9c4c15d3581187ac8d7a60d06d3365526e825344e7a6bcd490306d9c2c9bccdce0c64f65fb6ae948acd3b0e05fac2290d8a9ac6cf8efc42a45fb308815386c28afb146bbf4bbc95c1786bc30a26b70c634f23c8d67bda12b0a169653a89050928f9a9388264db675375cb2a0c5c047b9d0ee8f1d270d153276b591212daf6744ca9492d4ab4680ea4ffa9420851125ecc22e5f22741d1fd6fb438d0a54a2e2ab3180f12ea437e1bf339f35108ab89c2192d4d093374e5589759e21fa7155a88ebc1a45a49f780287fb31c3c0da1467c0aaf63817b7d9c8c3e9f8c4e913821cdf616b4b467c11cdaa86ad9a70fbb1e59c16bcabdd8cfb26e842c576dded2cd86dfe983e4ecfc5a09838227430c42faf2da6aff8095579656ddd5c073ffb6645ae2df3e20d93de1fb7ca21d5002082f4b0085237d42d51c484a704d3fbadc1c8b413440ae771685c97102f9bd0f548b5a270a5822ab2d23aafe270831d3e2717a1a6ed4d73b7559ec497532c700ff1f48e27ea86b838e5b73268f91e9d8321361f85adab7e907082f806f704503b2620155cdee7f98951233db488799372fad0fcdc3e14506c9b9ff085961f70c2db280b6fdfca72f4700df1a92f301d98fb9ccda81dd1cfce1c8950a790c8b0fae6ecf403b5f9d3499038c8277a11d05f58fa3a071345ad978ab75069ab6ae092d0e65398f8eb45299d33d282a91e7e5c34c849883552762352fe3a0017c340bc5b8ca7cd9b6773e35e38c6dc65efa4ced0ec4153b9e12985f8df1d6ec76f10f6a40b42669386ddaa15e6fabb47a5ef982f78a0cf243f0b26172cc5675cc7a05a9ac88d74ed7f3dbc34992b20ded541ab339b9fefd97f368003af8845316090f0ffa5e4656d7e3c789fce2138b683de1e7a10fc885b438d8d5911b70e2126a0793a3b950996b551e835a5f097bc5553c0fdf6ae6fa138257c490173b4004120fc534d58bfbb22293767d56e8bc866dcbaccda0fe473882f8cbff6ac34d2d9507de095f0e422dee20c57b104d3b08459377d37a2df822e21e64503f5b0b037f038f6ea6095e8f0ec3e33fd424c852ccd5775c822bb3992f16ab58a14674c50608a0d65154ff4edfd430fdac3c695adff068a0e4bad77ae75690e5636cc678cc074a3514acc4f135e7681c47cde9057e883c8d8f874703fa0033aeced1e9d7cf0dd9d844dfb47526eb72177eefa470d3b9547a1ab3afe41dd8a346bf3c28bbc20d0c317e0c0ddf9701a099cedbc245867ce2fd113726535a0552a5b88d5020650fc3bb6b7c835267e8225eb651b7fc81489b6da3dfa5286ef2727e7dee0ba4f608f4a0bd0900ab7d083b091810d761b9e632b8840fdfe4864a3d5e14b1869bc10c8200b248731ff36ef6478a91595246769f628b96a919b82c6b7c394056d87701f62bf204e948a8bd693d22aae3645a02727d950ddb752bb86f2acfe48ffbc407eb3315311243c8e54835c4a8019318748c61d64b3c6ddd62c6a1a0fcd9ff5f0ede06443e60856efefdabf99a6a1ac5638d69fb8395aa9e5457815b8191ef050017b050fe1288526e735b94d1934c18b3d9f7156a45d073d7cfcd58aff8e69c0afef5da22bbd78edc19cfd9e423386fde0eb62bad363cf2e27247654abe58040dc7a5d4faf95bc31ff5b54ae47ac079ac916f90bc47ad6c542edcaca72d86960cef4522713924447330672851f0e135c571b52eddd4fc327ab4599037dd7f0a05c6c58ec3e72f53556311265d817c769e655130155c6d583190333e0587929d07aeaaea316b3398679227068022b1720b327d4d0aea82985039ed20389d5b2901f2ae0c48d2832a9f516cbf49e53709d28e7237e148f788489b91daf4df267708c34d148683e551aa5af15bc23646f83a84d145ddf210d10373d0abce5d2b92081ca97b46a7276275c689ebec0972f557f802b31360ca7560511a55e1734430075532c6f8461db6b3ec444ded07fd430d20c0bd1aed791ca02c9a251289fdf60e0b67254803ee39204629265014fc6253c2db7a3d0a6c4acfb143dd8338f94507276760e484a3eff1bfda5572f7fd1c75da51f7504888853eccb1035a31e1a502ec4d65507121e736f6b49b523fa3c96b74bbed12cc01820e3147e025b3b96a01f4e3faed1810628b9296f127bac4994c0f7bc106a3a12779e40a8fd8ff31df0e072af4413d10941c8126d8c3fa0e927f60dd4377463fd434ef3896b23695de00a7011ec98f709db4e46e9502279f2474e548af10481a6411b730255d81909e08d17137beb1f1f93628afe1ad77ea7ee3184aed0078771629797403d6e9b51e0fd8102628c57d5b2474ff412e65cf0b6ce2d2f10177e1da21fae8c3123b4fc90099db6c53d78d5f5ca64bb6d171f9e6f59ab5857f97febc3bb13040a5b4cf3809dfe40327694e5b170720fd08ab091013b4645bee213f42e07fa7e95214631a08c186096778d2c6df8173915ef1bbe39437d6073e4409524fcbf5045ee260ec0d603a44976af15955995f75a773229bdd7889a5aa0184f292bd6b2ffe2bb86407a066477364b553440ac6cf9f7fe4636b48ca50e89d0d8891ef754134d7624c0db30d2a500c99277d90089542cc5058edc224f06b87af48853766926c03ef2206bf654cf9c3e0f6c74c42fd047c1c025a2709524087259ee25306bb861316cd08f77ecdb7a6b5434e32999aa66def3e980ed0729fca7743f95239d3e6eb0a260a83aacd68aa70217780e0cdfb64463cb38de519836613b8f6d6996402c45930041cdebe5e9af616c368e9f10a036c8ddaf3b6fc9d3fed325b52a59fdd5b83f80b0585841d04323b6b82186d988362ba8ed8c3c51e7da1aa4bbe58905b256c3a0d831fa6bfbd3623cb409fc9358e611013e7298607a0c4c9a9bd83fb4575c72c0f04fa15b33e5b64536294982e0e20b8d36a06605bd040de744171af0f020e2f0815f9e6c52c2345c8966b93324d503e40466335b79beb83d862b30e4e3e15370f29709581eb06f19d8def04d6b3c123a84a5cccd9246d683f157bea5f25f7e00e9b4465540565c021401ca6346c7452c106f4cb5101a0c8d92889bcf6ea18fa00d5a9eaa390fe15432dad58e0257a97c766446b1dcad9e224f70ef82b42dea309fc8c558fc5ee33829a3e671d023f144ce98220c7df65d490cfdb9152fb85af01a06310775435362854b0d8fe5d9c930bee46e91aa8df6efd91c9f8412e3c31011668a872c614ab34cf519a3a44e3945f5e693f83a0308417e3c35522a2f5290711c748c3d9236a119f322b8f70bab552d3725ee62ac7763ad19b1d111dd8610cb18a28ad3aa5086e98fd9c8417ae8000f5c30cf6ac2d1c2578cdc8f9363a760d63dec8b0e97e5a8e65405d1bbf17c11cf8dd86ffafef84511d61468c7d1d340527ed234c4f98f170d045aa30463d9425cf76b602d8480d27c394a5a3fc6ef902eabfef77815e10843d3e5fcdb5b4c68c9f5ffdc113cfd0fc47e7a80fbf91d90550d696cc326233f97a8e460f75dc229c0e962ea75b4183c75527d8d46ae6fb004cc12bb4cfcc6752c7ca98a006be5d5a440fa4451f3adae49de7e32cf495f9001ff1c785b3823f3689116cfeb584c3ac1ec8395dfe95aa695040411244e58801af3e7b94e372a2cd01edc5646267f7721a41834c7e67440819b5e9413f43010a5b07229c103aa6e71b18dcad9c92cd1793c72a9cf2f3217e53374cf48b7d820d511d417e577caac31677c3160a4f8001d30a28ff0c8fb9a92adfe3290409c7071f56f6d92e6b36b0303543a68c1170fec87d22dc517e2403f566b1df590bed0b87bb1fd985dc5596801a864f2b6da927d4bc47bc6fe74852825b2fb3f274e60c65d59eb1981502682ed9e3f6b66578a32ab8900e560aebb1bf9e5d2957a22a0f90106fd77e4a783f3657c3d4f312127a38100f49ee819ba3a5d1e621fcf9b80d8913f24f65fb90264f400302731b2eb959ec0e5530fc5a2eba157bc268516e0af351cca919bd51fb5327dffd52acf8e9e46711eb6fd0852b9bc6c5cb3350c50df4fd8cf11717ed66437aee867eac3179b071faa1c3278b1c350b0ed2d3fc8007e61d0c0d3e0507cca71e0c9adf0fd456b0646254e42c8143affcd4d630cf3b0f9611dce910d92189d4e0535bfeae31f2c2c41d376552eb6b1867cc701df9d10afb27eb66905421fffa2bdf2fea125ac0f132128a6856dacd2b450140b2f4a10b619ac214a953b719dc182035e2f2763b6caa4d0c85f924325c25258ceb936a09e58b7f8401cfc6b1b4359f4a01ebf03f683609cfef9e93a547ef3c76a56a240bb5b41b235b44d863695179091aad432fbab349e758e1456db4b195fa95deb20c3c6ba094317e9828c5d229b1f878899bb37238a35034902677efa451280f7709f8e08099470dbb55db6a56db92d0cd6a110465017d3d27c3d79f2617b0b5b60731682ad7801a6c3bca9c4942abff0242eb88df56e904bb820c6825158154900d4a6d2161c999870d541e59b5f21016b3c451efeb418c152aa3eb0edbd8205e0d4abef8f516c96fed0f6ca15ad47e1cba9043ebf98c104e6c28b1157eb99e260642d7372cbe316270b007f694e1fadbdb8d84d81082779be9e103de2b5c52a00c6c4ddd69be693b2fa5a70363325953799feb1a9cb94e03e2a0a506f4c0ce5a059aa16b454ab7bf602bf46d34b69ca3fcb1fc0ac9486a3914374120189b183407b99274011778613c4140d08096f03d8b8e161562f98e2ecbe36a1acca78f240703e7390ffbd248fb7cecdfa77cf4328e17412f6351342a3dce3b4814affe7307bdf318d457f330e83f3e7c4b3170cee1a14d9568405d71aa491fa763efa9570946bfbcebf5f5cf641d35124e05f2e61ef020cf59bc5786476561b409bb6dca0d97e051c0fe964e2734b6b4ba9cb92a5b78b186d4e17fe15c07b3e3ddfe4c5b026dd745862425cc1eecaa313a5bb29cf3e3733fde098dda9d18adde0eecd4b30373c3b908c685d7a56420fdd6fda2801be0b92d1a66139002ccd5ce7e63c7b80b745787494d576c732196e4a1473423a75465c8f85a1519711f87b796700be805e962167b4684336656e266d39c115ca2a7a0b768eaad2f1ed4598622a53f230df49b0460d8f5670377e01955cc805e1ed4b17f0d1f2f138bdfa8e4cd732517018b4e5ea984d85493b71223b52d01c9b0525fe69f92f38fbc1f3d6414b3066c079995ea42670a44c2ba4ec7a8ef8dd8a86053aad07fc94614b8656d347a49490bcfccc471878c894f758dbe4620a523ebdeb45d5a0d5ee4a6bd9d1c197197cb0a48d85bea6093cb5c7bc0c42b39342fce57e676638c52f64fd37016bf0e6e590f871d04072d18d8cec1f4e05e8018e7be7f4da767cd1bab7120d002ea6ac98c0f3d6cfe479877bb43cb50e94fe65ec59d33ecf5b2ba71744b94ac4143abbc2704bf0fac99b40fc525d81e943f06faaf1fec84d13da278c18bd43397490c076d050153778e2cb166009ec9cc1ebf954dd930c00815e87f4cee7f969dfcb1d94a0f7b378b94e35ca7c7a31ef10d4b5aa83192ab6ad240edefcb18e13a5c94bc7e006d8a66bfc1129d90b0378ff62b564ea62d26d92c1f14775e44e4f453c4d398065af33ce4b4c0a00b4b64665f91a7d7d84e361c284bb9cd274e85a306b9cde304c0c0393d8da71d7abbf2fde949934468a1425f19b99adabfebe1287d6ff9dc011b6824fce6974b2fe60cc84499328134d386508c92644e63b51405aced3ae20871f7aff4a88951f947517b69e1f0f465f78e8bce9379d90b90a3e2cad4bcbe0eaf67b513a582dacb284ef738384f41246d5938d75d4ee9a39719121a1e56720a0df68a0be66ac9c36e9837f0675ad1030727ca886fb510409ab1ce2e6e0ac208ea0de4d44eea670280248aafd93224a89926170760211f38c13edbf1e41b3a044b7f59d32468dd82865819245f9682df76bc82c44ebb8f451d23183f23e281033bd7f336311f658b9f27fa898249640cca89ad18aaa2eca5584dad9f4ba25005e1a995bb84d74ead317570faa7959b89cf0f130d96b34564d74bd3814f33c50061c30aa0a4d723189b726e89b7eb76aae0f069e4f0bdc9d6d0220a614f6fa100677f62769d2d2f5d9049d333559637a920e92f22e1e64c2b0491c7c3257fca05f68b640abf3a99c2c0462c66c5e29fdfe1811067dc2e786c07934a736ccd540f955a8ff46f4266bc634e2eb74a5f56078e85065fed455eb9a0a6624456a3d70dbb37d3238fef783782c547a2b5b8b91b2039cf6dc21b2d89a1a66417482d3a0f64d32411c2d58c9556a5aeb54af513b88bf26f0b857f17c5c21443a8641cd401d9622ecfd21180593228c9305219d6ce91bed1844b1c6775ca8114f4b960f500a4b54b2902ca36407ffea886a99f8940ea3dc9cfe5e24f451cb19585f6e68f02df59cc218cbea3e0ea45cc72e574d4f9cd113a429f44264f794fafb88da9560e2c9f439ca1fd76da39be85f2f6b953c9c92821ca5619084565cb920d23265903ccce9bc2e65b4cacb3910c66e99c63f89a967f20ee16849746a680b487dc1803539b5e8abf713a316e0e01ee758a19bb4f8882c9488f8f088bb7cd6f3b6a320b8cc38ba2ddd50598245b7cde53815e9e31809513273b1436b47c2115d5e7260a5e072e5b5d35f3587cc3a763333e712ca50b5189a9714473e061037ea8746e0b8c3350ec1e58c402996d6d4453ca673ee5a3bf59153ac2bdbb1ab24c9307c50f94047c5f9d7c99b849a09a1ac46aa80cc56848f1767f3af49d13ae66af9b5100 +generate_ring_signature 39fef726944368533d166d84ca3f2ed35aca6b33e5a3ddcbde30f1a60465c61b ba1907948b591f4d5e7faf586b3f95d9d259ec089ba3ab71ef4b57beb3e5830e 4 cfc47ad6292db3248c65c78fd2db49eea2c2a6ff4c6f50771decac7631c4f866 4454dc103cf1ca4cfba718e2d34dd2489b08e0b350523dc9477dea5f16743e73 74d30aed08a71ab71277adfc83d8e0de28b2eba61edb0e94acce6309973b6d45 2aefe7ed1319282d5e1e01220850c933406384c6a931b0acdcf4957de3891eac fca4d6c4cc291b9db974d09df386a7742740068d0db8e96b1b4faede19f06e01 3 a46e93d15cd4afe575a7489891a49a182b2cdfdac82780ca3a8ca17d52c6f40731cb42e8b48328dd749e2ce5e4ffaa70db997b2ad141ef5b5dae346996a75c0730611859c709c494f09e397bf5ad42380f5f1507278920abca2e5e71357cc2086704e7e93cfff3c27eb4e33ce02efab7ba1c02b7ca2ea6132c032429b937b309b0b0f7bd409dd7f7170c3509cb5d2c3dd42481652c071e44a177b64965ae980c8273f599d619cbee3e91e8deafc7aedd2707783b44ecf39ef3acdcca0c1b00047c22052f647a7e7bad40116615a41cd77125065b2aae3737bb5ee68ff31b80057ec7116c8fb01fb1441d0e567785b392c4caa8e9ef37a139f270798599b4d105 +generate_ring_signature 7f0c29493bb36b01a82a2f7077d547890e5bc7831ae6a35a2f31a0f902d4854a da08db64452bb864c36174d98a4e14781c78b7be3ff474071c0afc444fec84d6 1 bcf34b4ed58ed15b02861434750fb724d3101346d5e8303437f56bcd5eaa5c8c bfe6a1b8cb2a570d84f6df232db97b7a8e4fa3dd8e6af54d09fef6aa6f67d305 0 9630dc704115e4f8b83d1536533cce80761b9a3a17210f893f7cdbaf78565506b13fe19ad00f070459aa2e4567e6e44818ca6b268ec62576504fc0795412cd0a +generate_ring_signature dbde6983e1560c26fba2a47c5e5d55dc182a12985b43766992a1e1f119947126 bd9bd3dba5bf6a2d3e986daf25c2cad584ae7c3afa7c27f5a98bc220ed0378ad 14 0f89f5a886f94ae576b8e5d8b947f0e1c7430d6187b9cf04c718ef3e99d945e4 d3e5b4d8755f61d6ef6943f8ba572fca1041346eeabaaaf4d53b6820cda40b3b ef305918a04cf633ab888ed026dafce004b79e96ec7bdbed5ed73e7daa14f5d7 bca88a261ca9d4ac8b51c8880ec327b1893d829605be97a299e9f29998a90d42 aa06e88145690e0e77549fac710a5c2279c1cb330203a88efc44dcc81465ed19 a2b43e260b1ad8a55ee794ed03fad1cd4a7a80371fa5799451593dbd4d4c7685 2fcedda6848e5af9ddbb3c94e181c8153a6229dbc896098e1dd4892f4d4db92a 117ea92dd03c8e8d8b54d680f30ae97884be678c4a868e672c5f78de1012f66d 20b0511d897bcf5c00b6d601dadd3bc7a879fda5fd41644dc07015fb95de9a13 38ea2cf665769f2661fa7e08165a9bf94cb807ef946d2cae10fb0cf314919620 d7d6c773b3294e5aa5436ed9c61ed5f03213fab5b30b83ddd0e7c12a412533d1 de39e3972890dd3e175e30880c96f497e180070bb64d726b968970d2e3be7ff4 fec305745ffcfb15d1e52cb29377b9a029b555b6a4470f0b8165e32d7bc8afcd 623eac57d7111b44d17da4b98c585b59eace5b904538060f2e4527b2f08d7d96 7817e9be56a20810243bf96eed3585470b75dfb717ccd52bed820321c9999e0e 13 38abafab2f704fed4a09c8585c6eda454ef38b0ebbc1adfb6dd6c026200b7c04951c45ab5c63e8e355f1eb52d14d7281c211e5afbaa5a1c42a70ce602c8aeb0568f599d03b038f5679fc3ef0871faf4d5ea9bc33a3774cda9c025c0ae300b30319b4b046d467fc820bd77f9a6dd31ac7398c2f7fe769d7808671a997dbaf650c961b152c4f5b0f65dabc534bfd7901b36b5aa1d086fbd374b8ddd4e8ed8fec0ac5e637d0f302f972e8116fdfbe4efc3d71f2cdc23d65c21b73661f83845c2901f0395f0cfd7c7bb0d056f246431470914081f2b7f53be8bb39d4f366ab2f040541c8f1108135f5e2109331ef71924debf1507e41d6ddf137bf2447217f5e1c064b575cc4a93766c87f87a21fef76840f3b2c150e82643d066314be98df9c330a42ffcc9a483da1a136e2dc906cc081692703da848de6736cc27b8270052e390f7c06c837d56eb78ac18c4c5ac0cc20e1e4562da82a161755f79bd6035d720407d54c467f8bb1a70e23b75c06215828cd1a5888db8e6bd5bd43b9f368015a4d098cd41a2c9d60dbbaae059df4a0044636de663c65fa06a0661d6449f5275d200fab38e6c65f7e1af3a15afa1205b453daf1ffa2f621cfceded82dc359be74c30b5fba3e1a0edc73a7a134682b2f73d3fe6a0392e239f66803bd167600abb5650763d782f12f16b3deacc5f31b37e7a60aafc4afbe258b8860591a2c889c42ea0e786c6373a4faca9dcf6b0299db5531ea668f1c1dd81c482d605d34ce7c3bd3048f6ba7847127b72171e258cbe3483171d5c0b511fb054e2d9f5bea46bcc7590f3e9c216e8c96ce3c6bf86b478259593e6b6129b1d95547a97c67d615e8b7920b7c6ba4b2c7a093787ed6ada578221ba058bfc244251449693b240244328c97034b0b07423844159bb77ed30cb5f76c9e7d36f1f8ec864ff03a8e541c81cd540588e4622ae14f99258cbbe0c788984be3f04f066fc5799ab49cae51774fd37a0b5c8eddd8585ddd5a30017c91fcd9b217321def9551533e602861b3b9433d9c0f9181a8023ba5af0cfc964162dad655ea443010473e1cb524854e46f150bbc30b79933768d9a8a49f26058cab67b5ff540338605a193a70ad523b800e7a27d908c52e7fa60d5c9e746354373173862a9de283a764db7d0e4c16d1a88f570fbf0dea67863d5ccf685a86125c6ad5d099197c33c2434228e6d199c346f7f38fe60f872b9d54831c706521cafe5ac9320fc5a42198acb6b9389846320545b5004906 +generate_ring_signature 4a049f0f8bf7379759bafc11f3e9326258df0ac45b612ad5088bef00d28ddf03 d4eced528b619b2c7e3478ca4325d630c3e79822e59327310e1e58f2a5bf46a1 1 8e1cd22c64de56e319bddfd26af3e8a6213dabdd844ced186eba1fead7172564 ec5b99eb1d24eaf612b507786695acdf1d15372e3acf311457d7197159059d0d 0 f89f7594ac7a0dbb6eb7dc9ae4523b34fb5e25a58f0fef549350a07d61f76409542a4efc736abe78eb60cdbbb143b02f41276d0f0145ce4280817fcbe41d5805 +generate_ring_signature cc597b17e1ff8657ef92c92504a0a1638229a7960b286503597687714d90c0be 55ca58a01832cfe103ee846f2a11e237bd11e22a4baebed2548e75ceca9b2eec 11 02c74957d08764bb2dce5202466669f53b66570d75afaf9d6394bdf325be7c93 7aef7a7f9f34bd0716ea1483a0a4372b437ecdf14874b98455ebf4f6ea4a2314 affa26c8824fc326e2024d05c1286ad0797e4921c3c75009f80f965ad0b6061e e9946e75782aa240166ec2d39b2232303b0f79774d2a9a08310b9336eeec17d3 a7c3963b8e1784fd9004e58fc205b2de95f71d24ccb474cab1cdb15080931520 80a6a8dfde031883f53bf598dc1c47061487b20f393d0a630f0b15fbc71449d3 d9583c14e71f5d28c474e25fbd43336c5542ee1a4ce603f5299e0273f889f9d3 2ecca88312088b7e4e346b72d37ac2c9f312d4d82a842eb9393ebec65a0d7fe9 b59e25c663d8617339865199c0500feadbcc5e2b9d00819a3b91304266cc98ed 9acd42dc028bf3b39fe1fbd98d8eb7c7c3ad85acea86efecce7e41831e5a0e03 3304c25e953f30bdbfb6ed159e4a344c804dd52aea4d104bcab5a281d6a4a594 53cc0ff1070cb40bce44ecc8de8f6b189239790afb0545d951992845cdca0b05 6 d23fc7f13bec16e31897c9a74569e5378f83202001945ebd8a3956c6605592008209ff3ad2607322aa4969db900f1cb5b7428e9d1001956e22f8457c726e760bf13f64d4aa8e207d2e4e36e0bc8b47c619d3cc1214ec53f4854ce26fef3c680ffb3434a75358b5c9920475283acc64a141cd7a3cdada076c3c753c9fa307d901a118c34238801886893a205fb2175b7845cedc638b8f80a4f7a4a619fa6ce20d94ca17cdc5ef8402a585937083ba55f1c971933f293eeec4be5e1f5d2e7303086da6dbe3834bc8750bb1472438133d40b68fe2cbbc7fb83a7d4d65ac4fc476029c78beda3ff8482417349390807c669ad878c79ceb45d71726aef09649516700bb19a45f8503b7fc501643ca8889a9679694a288bea16febae581f2b2353d30c25cbad97b0e3b33f679604e3a50b43cd60b367605464cf53d79e3c2b24f17206d298e214c8bfd42b86b2f4a772c517d9363851c45c8e091e325e9c1d61f53a0dc64842ed4c9ee025d1caab83c3868946ea3449193fab6a766e0086b8920f880741a6accc085a48176f549c4d0014de06a5b7a803f754de752cbd3c6de48f990b32305db58e83090d857b8cc068d1d4b4b7ad75103b7745d0c1630e4ba9cab80e24f40f78624cee8559166b65ebdd8a69c0da92c82b0fffcbb776acc052fc900258f8330d168224a7a96770faf0e2a987a90c251d4e76d5bd11e11833e908f308d4d4f595af5b9a4f678c72e2b9deff2180f96e36abcc63a57a35e446c56230079bbd24892ff1d1fa29965f5670a37c558594515ffa64504b8ffe97a7cc180607064b55305d6a0d85cbe95d8921bfd208a1b6580a34a6286566f292f2d2f88e050349dda72250da36bb35fe0d2514b347cb522d817c7d76e43581bb3942165300dee52e6fd22237605beac81126ff4cc4ac1cc3023cffb5dfbd88a46e65130b0b93284a5bb0ea6883c336f28b0e2595a7a8f97a74404df21e2d9a6ad41689a805 +generate_ring_signature a1a10532175cdd68eeb82f0f46b27f97cc2bd57ecbdf6e339a92c61d67056fe7 a7cf65fccb2a26a3470e9f90ef57f9c406df48f0dcf5e9819553605479d54cb8 1 516241f236a13881ee4aeb786cf686b340ea9f3dc8f142ab7939b63ea948f9d8 0666045383e7f9829c827c19f36ab1b57e58988af20ce494064ec1783c85fc09 0 47dfca70942d66d5ee61d60ffa16076146a3af2c497ac841b5cdadbfa266d509e94c85763c2f5cdf4594802c4953632d23f92de69ddedc8678f41ef7aa033009 +generate_ring_signature 33b853afc4a8fff7ac0b290b524bc23068dc3bd098dad3cf44bb96470ceaea6a 13b719bda608fee66c92ed1f005cd7993c144ce764fbfaf5349de4ccf5b6c319 1 29b8fb819c8be48673c0b35b8d3dc52b81fa528cfc91ac486b7751b1ba88ea73 bb666988157a61e08efec906b79f3e1321fd06d1f401712c0b4c47a98de66907 0 34dc6f9fdc4343c15313ac5f504bb1773fc54bf27a452215235efec0ef6d2d0f164e1b31206a4307708ed0d3549f7175d6cf77ecf3021fb7a472d48cc8b77b05 +generate_ring_signature 7267598c7cab03345e1d5e770ea5cb4fb41d934079557f538b0fc4115962e89c 72a4cb672b3233588ce82c8aa41613f0e1f087a370871ed79b72983d414d2dc6 20 1fbc0e3d207a90cfb27c1619a4db82fa106454b554910381521071121f7cb756 3abb94f2520ef80147aed005c178e6ee800ab93d91c284f924871ad3baa3d607 180edd37508ccb4ae708ea73f0e56b0bf4d4a0367a7fabb67803e1e2937aaf70 947f5548e9c8937ecb3b13d7f8c17889369ab8302ffb140a742659c2d1744043 54c8e1ffb3f50f9e364aef8d7164980cec2ceaf36edce662252f53ead9a784db 613208344207cd0665eb79c8e0ce0fab7f8b864bd49014c7d3fd20552194b947 338aca305d87c2f8792b82136cbb7396bdb218213d5e282bb4d29cd713389a33 ebb825b0cb8392e3dbd324e009fa3cf5f22662c70b35ed38ad32155942d2e7fc 2a6a57bc6115aecea112235dfcb6908a5305b54c3e1be6ad47f4286b4d94fcd1 1e9131251f0cbe92c17dbf1cf67836afd9dadefeedd0011f3d53292e889e750c f1d339e8dabea718797095a461fb2eb70e536fa2690a639d486c027cf5af6cf5 4f4f6582bb2e5eea2f1b799635680b34e5c7aea6069dd434a5b1df7ec53eed40 00ef708cc6a3843468e01fb87abc5a78fb3e44d1adde671ef9f977652d93f0ad 1b441c5ffb9d966ebe924088aa42718a58e5f21129fbb5ab4710b30a5eab0bc1 28ea41a63a7c05801ffa3f0775114b52a07540e024e4f437d15c6f596999a54c 5d1635b9996f202342826c0462a030f4a3926923201d97e2e97782dde4232e8b d63ef61485f58a8a8421c1030c63b13e7f9285b3d17a97c0ec617156f3d87e12 22e861e8e46894f227e0c5aef38e7144d61ca338a95c8ac00c222afc157a012a dd99fb211e2e4fcfef75cb569e9a5f751bed5f29c5f69e4afebd558e1a915b1b a79ebc1f781ad0bc716d9d20ba4a4be3a41babd8b940b57419d4090ebab97ba0 77458fd9ec7a1208f2ebed73ce83b8910072cd2e4658cffdded55675eacaa305 8 76273d2678872f9d628f2bcf2fa4e55348c347f6d5cd5add5d16da2dcfbbad0a9969da01f59edcc8d997e9baef87fac85cb845d627a446494316f698c5156b0bc526d485ede63f84581f04554a7d4d49cf27ffc42eafa570130178eb0cd40d0324129af54a9663840a790dd79b4dbdf8ab468dfe88a09522c504b88d01193a0363112910a3870934632f8b0acdf667224cb464376e852f5908af32ad14376502a74dc88ad52de891fd4cfcec22815e175e9bf5718225e8d4a4e14d3effceb40dc40bf784b80e7ce3acdecff718860d31c099bb2d73cb5b10360558e32ae05a0cc98f34e4401846088db15ff27c4d615463bce242ab4cf24b42676b53d00141028a1f65e7ffeee54af647b8826ba60954d85dbab97e59d6087663a14c66fb7f0069cda230bcef707cca774c9bd6df0a0346b9d1eef1900c93118aabee9d2f740924339358b4d6e6f861c969b2ab455536d1b70b65f1ec9f16d960d106c1af4f0551e1e45a607472113b6b88e381156fdce641fc66d66539561c0ee6bcb539d40ebec532499c6a5c28966f69c43d6c25e0a208feffad242ddc800b8b9c58e1f80482b48ba52f661e0c28383b5daf6999fd1c6c1bab96d42b4da848b37d2f4bcc00bc788fa7863407b8b5aff00c1c50ce435e058496e0c353b264dc39ebe9a15b000b8026574ccbba296193f1ca37ad91ab5ed182d556aa674ba2449f2627bcda0c52caba61510c48ef69e578e615889e9f99e69359c6bc73f07047f8aa27fe7208e95317ccf056c35e1f2ee3a7f6a56c9aaf7bd7ef663c15ace114e31c0a97870891d847f551e4b81c697b6fbec00953fcef9062cfe894b070064a5d7deff78d08445b922062643e71ad988f4b34dadf5972345bc8b36697021b9b8868de765a06b6c8b5dd51ffeebae285546da26165e8c096cc90882c34f770552854e143d402c5d7f5c26285cecb7b3166b4dc5aca3462ac707a5229636339c26bdbdccbf40de5ef3fde8afe304d7a2aaa835b767f7cf0d669bcdd476bf3224355b622af3e0cc8759050ded35ed5076d552e4adf9348b56d2b027b5f2b27f127e99fcb77ec0b5ef4d4b596a421fc394a3bac5325df4988eccba27d17408b6cf59a13d8422e030a2c9f8621d8326d6b629c8480c748fa989dcb0ac5f448b7b69f8dc32628ca0ebb967d66aca42fd9662f9b35b541fa6e795a4459e8037c839f08f4acab9cae038c2b9c9cc878d358f95f10b179e1bbfb26d164ff665f4bd7f8de47f19ec45f03bd669aaa546df1756350eae70de45e4f66cdf3363bd4bb07e50be2b5223f920107258939ccbf401519f8ecf15461d182ec08fb955da0032f06d7bbf665a5410402c1a159c93098f3db5e6b7cbd47194980b40772311d0cf91345d01e212110069e472426cca9e9a72f773dc248a9ac58433cfa7752a431cf1d795a1e661d4a04ad9404068c21d6cbfa11058fa46ed4682ab4700e0afb893d1973c4a13624cf02e128a4730d146a4f894d1441f3b9fcb0721695bda019ace0a24d53bc19d82e0ba579adb76bd7837ce7243a0b46160862a729e73806fcddb4543e8c06ba88150a7cdfae57aa221fd68313cd9209947318324f7b3e55a11cb9a26602168ffd0100256de511cdb926b31868e1c9f9221f2abb4c799b8c1e1bf9cf67338b9e8c690763eed483e67dc7b9921d1c89de3af49e2dde297c06cd3d5464b58ec9db90600ccb892367604a44f4bb8872f116df58ae643771b357866874937de0d7bc26810efad047ec17247fa1f94bd5d7c8538e126ce3b60a5e89ea434fe879fb07447a02 +generate_ring_signature 43790ade135a2bf9ffbec0b7dbf243f6dcdd40eb7b420d849868ff7aaa0f67d5 f454c7087f82361c3912a9120b4226db15f0d752d96a5f445e19ab88d0bb32cd 2 5513355588936c635e602614de59f0dadd566c4e7a77fa151830e454838fb72c c00a25f291c66d07365ad72d80b0562e7a91e990305a0bf0e5b01a0db499c8e0 30c8fecaa0b7f217aacb273eeae2ae495f65dec9dd62c17965c5f46beeaaa705 1 6a4ea6a569c0dee9f677473c89950ebd2324839deaf287be71f3fcb450912b0a5cf752193bc2e19ff9044732eb4c46a6f5c1a1d25a2a1c281bb8868732fa800e3403afb281b29fdccfbe020240ade7bdc019aee7e322be81f4e3ca4311bf3502b5c27740c1d99521338059f9d083e85f3398504dd22ac6d243b2440cb3e88303 +generate_ring_signature f745e1b2dc48174a463a7b510ac8e6bffdc6303c2816ca05195d9ae739db3ff5 eb4669ddcb40d449366daba63b22670bf36b64ea51970a796f07fbe78b6e1af2 6 fcfa341e9f83038e4f10b48ea65db8dcc728b2324140891a0566c0cf16017af2 3abe9c454ab3179b0fdd96e644d37285582e54423cf27904fff0cd060e3522ec 202812d70556c9afedbfbcb2b863e47bbfa43a0f0e366d50fb369cfa9ba40496 f3280be164b445d7605ed53195350d332b6c4a0425993782d6f5974520f433e0 8b368764599684ce8308969573d800ea8e4e9dca46c25429005d23b8c2ef0f67 dac4c7e0b261d9ce63a7afd3a1e7f1d3c04682287567525b1696ba305a26b42c 40e0ef7967fa1af5d40c8e74b5aa2ce841b04634e8eef869a3e25b4920c6f405 0 13ebfbd2a82cb89a77afbfa6b183c7cd1e853902bc08bbda5095577a87e7830a2de1bbcd4468ee58ee8fc28ada60ebb63d80c10d807f8702325ccdf5f37cb804c99e3ffb1ce151b516b3c19950dc0c28065ae07e348ce1614de1ec87e36889091846a38162ba033526ad1f90e9a3c05d07c3d8dba8565122b3a99eca239fa30d9e9c618bba7bd6fd0098fcdbcd2e9f215eeca594b2d670b3fbde8081f146eb0a8a28f1750a980b595810f85c5f3f9654d167d71a703c20e8b2ef93c92ca9980a2316e37ddcecf447431b594f6dbce33c4b580f100b3450e08fc8e81a0bc6b403163584d050ac517fc2baffaa5c48d5b673f1b8574c745861f2774b04c5665d0cea4a3c6729236227d5ea8ecdf624579ff8abb604404ddc0f9a81c5aa3e0c3607025106ca3abc098c34a83945d020a0237fad8c73201f3dd751b282b4c3f62302ece2d7da870c5d88643a7eb4d9c9b8cc93d86c4774ce0c583ed98c71c8937903945294478a131f7b2fb66b5f6b3cf4a2c46fdf89e39219c493b4506987694400 +generate_ring_signature 0c1ca4f91f49d1955400c6f4f0ad43a05b4b8e5bdf8c10da751c98dd85c47d95 ed2b4cce5bd48fa761dc4b884062ebfcb4d51dfb6add0bcda77488c533ec29a2 1 c31c24cc6088cf25e09cab4318376a3202945099c5b2117ec04a0d03da2afea0 7297a530706b0a9826fee21337f341f3a7df6d4b53e78d21c0ce596ad2c4fb06 0 d93adb2ab195dba0942ab3510e046588d264aac31129e53ecd572627e3074f019a4b4f234d0f59ee934ada5b0528b3287536df05599f54d8680062aaa393bc0b +generate_ring_signature 31e7df067e668a7056c57de9230390b3b21832b0aaf26c1d136442f138615387 5a53279d3b67d60495984b9cb94036d0504971c6f5d582b8a9c868bfe5856de8 28 d8e11f5cb385732a6b28074afb6337a101560a0015e9772d3f30d3948adfa268 4da2764bb6febfd8c8e04b2cfa881095a1311336854fd54fc4b6b1d3b50b3087 03601a88b19d5bc27bab15b33d1ff472d91e7a928a3ac537c709dab71bd56e0b d18d584e85ebc1788a95a43f24242a33cc9fd281a25029934850752ba44d1cc0 a2696d71168201625a49011911d328a514d6ffc61600e807450349198bad3d8b b1c2f0574ff45ceeb330de965a3ccead9738da629a941436b22f709939a536bf 7d024af0ad9a8bc11b1870d4e4bb34a3aa7f615b47728c80e366899088627861 5e16ab4a356ca7682ef9b89c2ff32ab2233393c1f6f8ec39945fd8f68d29df5d a4b8a7093c7b2f11f4ef98f3e17f398c05daa7f6778c4ef6bfe8da1b6ad8638b 0f3c7ebdd53bfd02e2f96ef56487d96efcd6c6d791486816317d624ee90f31e4 744845074f17c4d32bf7b9c0d4580e94a1e86f2c5521c5f3a2c08a815a0978b9 31298b4531ac19393a103da8df5afdca6312fdc9bd467bd488e4aafe0336563c 9127fd630d5000a395971aa0d908cf98a5c7711e0f01d460a2a7684f52d059da ecae915500777293d1a23bdb2d70c17c964b9a63ff8dd4ce6dbcf45772c3ad3f b48d34c124988a550b37c4a1d823017ba38b39b790880379ab0d9cc0031f934c 2de61fe61cbcaf6ea1f10cb8ba8f4fb8df780cc00c0e517bcaf9284cef02bc46 040f04ae028b915b6d1c7d906be11eeb401f7e352def5f7613e211fb0fb558ce 551d509feb45aec8e434baea8603a2ff77b5e3a07cbb0d0b527c8558c4c64708 d073b898ab4ee3836c67d0e5d1dda2085f4c12aa416c81bc340b85c3b8b6ed52 435503b90a2d14f405096ebca6b42282534834fe9ea39a6bba5a4caa4f079766 2acd80251b3515fb625a9a18d2154b9ad1beb8d8b010d8be83ef0b749c5dd6e3 e5215f531238d2c273de542c6f4fcd444e82134080f087d0afc64f6fc8bd44af 22424ee51118bf80a8cef77b8e113cc0330e24a3844dfd84917fbead9b8c254e 2fd2a01313fc8b08b276862efe9a959c3b1a19c26615d90530bb81a9f7bb86d3 ed488f41eab4fe62d9ca4b7b84264cc8320704afcbaa174d0cce1799d577e741 4294f3ccfe624c32b9b2274e0c12e55daa840db023085c7e25ec32e00e889bc2 0f8c0b190eb31fd4afed7e449e6110176f33ccc4d986e948104607a326c879d6 3bdeb0e9895a3814004480cc6f992bb3d35b747f697bb88a04147e419c5c2c72 3e8890b916eea212d4e1e8c72b2775339eae8c42e4ae8b43ed09e24c694e7e0c 6 355d54afd091e0f6eece93deb42e5e513d569fc1f2a97722d9051e0374f9c80490096611769068f4e97b2416b7e1cabc9ec26e34f134c900539266afd1915d0408532b389b8eabc63af405bbf5971a3193b759aa2ec253d4a82de84ad487320271afe8dd2c60d07221f412f2be29a0779f7009a0bc6f62eb7a87bea43bdb3e0a22001e2c1d45ba5fcb6cf44b33f463b28398d7875099aae347283bcd1d37ee041ebdae7ed155a0d36fe41374c8923d9fdf6b70dd823063b08dc1012d803ea10a49305de83002b6027b0870647bb15c084c944e403e8a1ea638b29ebdb0fdf50509eb7b4aa6fea61e0300085682add4f1e63b10047e0e66ebaa4e9d73a47b380c180c8c318dc111b57893078c35663532693591bbebfa1064ec9614051c6b62091dba74033baf6534c26201aa3ee53f008122de11dec0c7961957c775137b68013736676ed025d98431e8342fb9dd50775d8fe535a194df29f10c02645c107f05ae45151697be0942c015c17b0026c14be13b9284b57baa749f1b4ce250c3680e83dcb2b3217a9a281470ad062aa2499e334b99b9cf30ebe838b17e543d285b005ab7549a312ccd71c4dffbb2746748c81842bd41e0e16db8af3635ade945f009a311585e4e9373a4d7d9d5b0bb056e24e2b18c473cfddc6dc8f3bf1147295f0302a999e2c615dc1aaa24e254f6bc36f04d58ef686ebd201b5dbd03df0655b20dcecdd14451a116deff2edf2c11f32e94068372c8cd1630c486089cdb2e18050e3cff40c25a3f70d9c53237a20c4507c65dfffda88e4c422b5235d25a0b2a050a2202deb50ef8d4e3215b6e378f982cf1f748c2250baaeb12317c62b13fd75009d1dc55126173b506c8e7fc92a6a6c9ebb4d1b8d41ff825827d311d4715163a083e01a141aabe248cbec1ff118c93ff930e2b1fccd590d6134ad4b5f3020ab406ec8dc82f6f0763b40c04705f322639f6ae44dd3c44c3bf83f6fb777110880e00336bcfa9675938990fb060cb7d668f9c3ee5bba02ffa6a672beb6e42c441f3080e361b068a1aa4a9292ebd37aad580e181cdd511355d039190491a7ffb70870d0d128f09f91e837f4b712fc4844a5ec90935b550645b4fc17cc8a03ea2c39f0b956b81a7260317cf7e39b3bf61fbcb68e497fa045831e143b0aa80aceada8b0ea7f3c20f7489305598e24403ff1a1ddc5481bb6bd77e2c6fad8a0c59846afa04943b4e22d05bc79cd58c81816011f6945b34c1b1d56f22751e6fe9b22ab3570bbaa850caf74561fa5b7715fbbfd9ae7adede713cc5b2a864cd2b397430c52c0d0c6b4a9191aa9791e25f56cbf26c48e3aea68352e9950a6343ca396b1ebe8704f5892cf44957dc513c7004e819620869cd40bd1f3c1e544a87f91d71e06f2f05716b742fd086ed3e7f58d9b2c09001762a96e3b7e7daa9bfd7b7bcf4ee722f0302cd9d25af1aea9cf4247c7c749280d6ab934a9d1247e978d3d3269e22e16c069ebed3661f043a257242969700885965f99b34444aa31accaa22ca51b19f010446012d08b61841b1940a2ecf0f9ddf1605109e6fee9a77bf81c16184722c3e059c49020686d6d63537fbdeb4ccdcd52ee5c74ce635fe6e8314bedeac4899cc0b46696f07422e14ec73b0e9517bbcd9ab4d5c300bdfd5243bc51ac4b98148020fb77b95c55470d9eb6d98ffe9a785f34ccb0c0e669027fa3578ad3643e9e0590d2c4a0631ef7beabcce3bea977686302702d629422d0f2efa8901acc221ea0709a4453799231d12e4caecac7d98ef5e0d0d1b75a4050a8447acc8740c92c8e009660e50274992c65cec4b9e9e8083a135262741845fbf8879b7ecc59659d5c90a096fe4c7f6bc15c715501f970a309a6ae9b302bd4303457e5d3db366e6910200cf685719c94311c9bd9010c2fe29d4bc7dac6610f41dc65570feafbd1e602a0df8820262a6ab3bdb886b1270abd83ea27540538a791dbab3618f49f2248ce609cf8e570e4572ef234d70588cc02b77464f4fa92ed2ede86bc5bc4ad42028c20866e6643b251b214cdb2c8769556dc9e87ffc74cb9ee70911692249b72b863a0fa8d80c39e6fe9fb98c526ab6dc71f6b076aa58758f78a3f1a8d34229ed996303d807e59e3ff468d510533b44d6b11d76fc01e74fc158ab8986b5780aac29a00525aa4e1fe57586132cf310fd250501a16a93d5fa4e96927989d65c42ac92b40849f5a5a5496806d3deb5c1764dc1a8e79006e5f96daba8756de10757c5fede006a5aca2408dd58f40a4347d0cec2e0c7cc073038d54eeb6566e77f0d969f3c0a58526f0fe78355f8e21fd37dbc9005c91a6040a9f231251da4ad375ef3467307b93863bdbf06a4e6536024492654206804132eec96fab2468a2674d8df5918005776c7ed12a9c2b9d3ba0da860fb35376a5b6c55e8b59bb26e26ed1f94edcd0486a8561e2fc910c4cb9a7c348a028b2d167b2acc54eb4d243db78c686bae720cbaf7990c189b4125039450f14403b318de0416e85b78e0f4aa2003efaf1bbe08 +generate_ring_signature 74cf9d48387f68da96ca0b0be54b436b877a40b8d7ce35afbae4930e435245d4 21d51622f92eecdf0071d205840bb1e1e1b8b26d69942dac91980a694df9641a 2 b06cabb47b0111da68931631552e977c5d0f7391abd7e835d4865ca6b6ddc4c1 c59a24c4128d29bfc1d676496b3b275e1623dd226ddb23f8b4852eaad13038b7 880eddb85bcd967112fc751b1512b490b11abe5d054e43126990afc8226dba0e 1 18fe1cf1ef04059288e527be172f4f154e60fec10084f577775d03d8d0911a0dcf08cf595b04d52d3f82925f8e6808eb60781a3ebc1c877a8108798c6e4be40b26a800947f513e7a1c472d996ed1ff457385a42b3fdcbf1649aadf6dd54dfd0ea1e086ab10ee713608b32953935dccbfdac554c5656681aa07c837ba8ad5290c +generate_ring_signature 9207d102e70ef77349166326193c037511f13940a761e9caa6276c186b3eb2dc b935299ab3141f7bcea9047224771b9eda89b7e65d5bbc85ca163f1d7defb31c 1 764d6791a583a488cdce815e5fa424f70de370e2669d6767ddd3d553c6199343 f6a1a2a2a3dbd61d40508ba1f192c0dc37fe3d297f3df14c9730a6f084779706 0 54525337257b67ce746fd584757ed62908bbf359bdd56de872872d330a1659027a9b63a75ec7da67b3a0d72f3814a1f703681029dce8bfea3351e286bf220202 +generate_ring_signature 8f1205e1c7bb2c98ace5d21dfc38b0e52715a4dd21f9b7de40d9dc516c0483fb d27c1b3252173f413b070231ffaa38185f412f2fc8af2dfa34c6923146cb8f8a 229 52c5784d3cda705f4866716a833c47355b5fa4898cdf0f719014b1e06da6e6a3 913c3f015930f8ef9ef6e7113a6d9dc22bd50d047517e2551fa3eaebaf108502 6492b0bc2eb958caa42949a7a154c2900bc56ed651135dbf4b1b170fe9cd7045 15511be2cebf723622ccd3683485b7643fc64514f97a882d9254f4dcba06aa96 30b0cebff8941b4295fceb60692aab5cc46f9080e27da45272545311f81f211d da45fd73c50d7fd41205025c634b92098ac9d86dc163fbc5cefb2bc8c50ffc5c a6bf60e5242b2fed9b365e5e30a7a400c1ed7a182291be8661340f03a63ee265 5bdeb86000a7c98f5c7c3570e807dc75355909ddf07ced6b1b8a49b8ab5b4b3b 7626e7ddfac740421e4ec2f375da22498175b569cb9ecb7cd0ff729f17c77cb9 33f89703bcc1f9888f44ac7af120c14ac800adf93302e7fc80b6953318683540 15ad941b050df08d5fbed5646703b809a4b2bf59fc806f68be975a1659a3d67c be0d234f31dee1eafdb19d6219a12ecfb0cba4b276dbcb9c7926588efe936bae d2c6f00ce060342eda234645e3302365ec1b1634b24a3b48bb83f7c2e38a4c58 68e9268bf9af8e28e84ca36852a5cdabf74996854218b84e62fe1821a6fd3be4 de95a3015e45e1e1a20ebe69066248bb6d9091c33fb5f0fd99c99e2c98b3d9f0 175f159b521035a0d4244455f49c292cb6a84c4820ddfe691d34c960ca04f7d7 8c2334a87ffbdda21fb11cb805d7a0ed8ce0bfe34974660956a8ea56395aa4d8 c7edbee25c17019b2202d4d0536bed6c36c0cfe9368be0a937587792be18a73c 42b6ab41fecf4dca2b1150f4d8952ff6d3e26c124d1abe310be551f2d5f5275a 3622119839daf53fd79c3d53a87e92b7174a4ca560cbad31f906b8def47149d9 1ae04ed9d6599aaa3208bb092eda99dfc9e9b48f08b73b45211d907038f38aeb 01cc92d5068bf3d9ccdcbd5622d574a02bfad10f4efd4b38d0f443da3ae00e5b e862f2cd0bcbd35d523302201f9bc7d15ba68b2c03076e475005de87bc5bac25 0a9d2fd156f8c3e893f28bab84b7b9384e31a15d1131386bd66fc345e5599653 ee3144f7734cb223aca913d15b02900aa7122f079f9a6247d37341be18c7493e 49630627a6644da9ee51fadd02c54dba4abd237db31d8e7f911f9b3669c71ac3 cc1323b8356b0134cee1836eb0e42282f78e46a54ec1406a7d28ea639fbdaa92 3cc0a3b7da1acc1ad6d518029595b1221e9b632ac78a707ed136b597d18ea8e5 1437804f33e10dcf092b2e2de5ff4b0e541b103b05b160e6416fe5d915b3d867 a28c48c79a7694db14669c83277b53961a86332fe3e488074b3b4b637e7b13a0 0f352d25647efb575677787de2e358d579be0aa9bea73dfbe3dc6217b12706c0 ad3a5789bf9a2500ca930d64d72f5166516c71f42534055b3a945447bb0a4fa2 0e338d303c59926ff532b127bfe7f5275b6ba6110631ad6932059d028fa49b7d b68a76cc12b0825d96739793cc5365d02bfe50ceff68afd0b9865f65cb60a3cd 018de5869e7859cb475b48aff57f07f0aa8c1e1ffba1e8e96e87fb32c6d684da 06888fe284c0789eb6e33303797f365dda3cc8f2a2f9ae7754ea1192ce14d435 7f41f8ccdc6f2b5194de7e0477302d1fdae0a74239d94d481d3147ebff4f635f 1ff844011bc0f9a1044b23ab46fc2acbe00d939a9fa90b32dafb8d52e25c14c3 1559cd22ca6b489236f6854add12fc7c2946c2f1f02d378539ecc9305700f87f a597e24bc6f4dba4354d97eec4ae6eaa44428e3f35ca2d060b85bdc2785b2dd2 861635da1e9955e43980a21e4885bb8998c8d86a047f382f94f93da569985c35 66f0dd261e45dedbe26d5e060b60cda4da5aee59cc0ae63387dbed7baff10649 447477689524d8c7a55799d1133c47352dbc5d1e71f1355822fc984ad6cdc2a3 1011c08840a7436f9366091864d940e93e6ccdf7b04189907ae27e4d7e00d96a 954b68b72e15fbb72d805b79c8137d01f8a83546848f8e84d99d7e049dfda8c5 160761e382b3dddeb20b285a60335140f03f3d75acf9005a8274769d3d2b3b60 3fb8f5f3539927e5c4d8d254d696ad4a2eee6d8850d9ceae857851a608dc11b8 5597e4539febf5cf5572df1ae65e58ceed3d7de6c7d8f48d4fb0f3b895951b5f 5c84d316987cb2949689b99adcff5ddb82e0c1996f9ff5e7ef510ad3b679ea1f 2721a20b915b3e8b3263055b1e819947c8b6acdea2fad1d5f2799ec3f52f5423 abbc7b0ba883501c0d07f898df3d11080eb4780ad610e1e8155b4b31458b93cc bd7254abfae24aa591fcc630b3fe13b2f6ecaffa09d1f220ec3d2cc166709ced fc3646f77bd6635c64a53e50517ce45fc7a60e84dd81e4ca06235693d8cfb44d 9fcfeb091e1bf9cefbf395dba14848ffba2714efeb80f49e9b00b00c9f05be86 8c6ef973374deb3c15fed4721bd7aab0e6cb36eb543146d69ba5b99cceeb2ee4 3313b1b042d283088915c9416960722098d20dc06e0805f9d20dc2eb7b31b46f 9e44b4c47f110e2940b199cf3ffceb69c711876cf5f44b3bcddc9424ddcc6218 52387c696e8b95cf5ab7f9fc26fe4a66bf8e1d84ab56b787591619fa2c3e44fd 47ecdc3e664495b46990625452266fc65083351cee005e2a769986e161788ad4 93b8097c3c625640736d2558ff7678691cde0fc00fc2a4e0c4e7bb1b54463447 d32b0abad912cbed3ea7bbeab6db254e521596bd6fd944df06144a2cd685a68b 6b2a2312bdf27d04cb2aacf4a26994dd4b307efe7dc2b1393e815fdea8ad6e9c ebced6a281ec97f6f7ce32d1e62da1ead1173bb873770ccb11f79f9d196b4307 16fdba74bd5741106023583564de63f5b77fd0ae433253ed67d554bd7bcb2826 f1ed0bf4e6f4ee1fd98a9a9b69645fdfbe81ee7908dd0c21cb1860b62e356ed7 681c3a1347ad98aaec4d7031be4969b3f26bc09b03e30497d58d30bbf95f036c 0b9211db6b2a938346aa0ff7df2800f81b4c45a58e5d7689503d584d0a0a5b0e 7dddd689afeea27ecb36fb61df6a0f088152a5694f4cf4155cce68fa2397f6a0 accaf8a5f922e97e1e740b5e8f60674563ef8efbd6daae9cecefa048705ca80a a79aec40aa552d5d2c8564d40860785bcd12aaa001bb3c1beb6846908eec519e 6a8c92275c25fbc29c8b9e9ea0a7eb2d50dfa48836a11890adb27053114e730d 604d081c0de894e8a44412d641baa0e067fc038347ac1302aa2a9b0baced9311 0ada2bc88e8648a5e0c01a90a72ef1ef334849a5cec553309769ab2ff98618b1 3e89073127cc5f0fb823d9d0c8b7ff60974413a12754775b9fba0efc19efbb3c 01e8a98e41bc850b040d84719c66b985e798a624749dcbf8b358ff7d64c233fc 6feb1c7182cf86bd80f8eab7f4681e6f4af6f2701a024d8dc6e581b4a4168ec7 f8e67fea54bffd71c8629a90d50c7f6134a0c2b0c4526795ca2a5e07f146f392 069158fb4cc625c32daf2608bf603d73b7cf3cd344670e218f3e8e54ee691ff8 4cd66ad442a4cfc55b4d0e913daaf33cdfe7dfd1da22b6c2e3a766d2e60d772d 1d0bf5a9a0c93b83efe4143b4cd759079984ee4b0b56512a3a0a5e2c0c9d287f 4df2310fb9561413b277873f38428cb814f221dcd694af87c2a9dfe676a64b2f 370a267d62385479b270e46f8578fd2f68325de6b7c71f7bd6ad678b061b71a5 7695614d59d1ee67af6684e4e9ba5e82cef5880b53b3070a9ed5520757fb2f2b 5c95cabe47f6be580ba29dfc59a01fe24985b9cca5ad1c8f11d94a3c231efed8 520519e1a10836f288b25c7c32c15469bbbe2618d5193df95381d1cc32860847 0d1f46f19b2ddf805247e8023194a97e1f25a23d7c9fbcd9ee75408b369f89ca 6691f76d727a9fcd6729798328728e9b4991ab4ea23a0e8fe35566985dddc1cd 1e9f2fafd07dbe67ce07bdc4b81cbe6bef69b5f69e90db19f37bc88680d67513 3a44c7187849ae084e96d6e6fc5607550a96d597a298c34804edef0c611718b1 f6d7535c498c428a792217943664569f4c301481b400c11a03c03fc156fdcd51 2dda0f1b716a5a96014d1ad7c0b0d6c3049be66082acc5760b70db40591b7059 97b342dff13f2ec104afa7ef42af22d053c0d4724d5c150a600309f679783c10 397b9cd9cf85af509978ee6324ea25ce2ad46f4b6fffd70fd31376c411c98b8f a38a93655b55c9ade39d4d1e6a81b5e3014066fde7e81e91ebf5b82f6dd139f8 1cf789d950a4748478226d2cdb521f75a63c6dc3edb4cb561c2e57b38750cba6 4644dbd47839e1e94946ace12b1dcf5c64920d0c0188649ef4a5fd11b5075599 765b04257c56f566bf8748ce698d77f0961dce48440c50673e838a9f24233a88 6b61314fef1282d0eae6088f5180abde895a022e6cca980cc193597a2854ac6f c2baadb820f257ca6f3d48de4c9768c4b07c7b8d4f7342acecfb12becc6879ff 0cb01561b6391e1493e1910575fed3fc3c314a417313256912de21c61610a077 1a1c943bfd4be26fc17ab352e30988407bc7de6de0899e3c8aac2a575b84705e 0b2dad0d3b05d15de7f035d82acac91d21c7772aab52cf2f35ee17cd1f7496b0 7e3b55ad8e3a235dac80156c46e290880d9568752fc2843851e6de584d7fce99 2cca8f02b11d269de7a1790ba4ab530b9f0d893d6a6cc8369d183170d940e860 3a7191d183ca61fab0c82a531ba5cf5b1da51ddeb1bccc8a3a5de1b3a08ed590 3ffaca59a42c9a06585132bc401078b1e69659c151876b562918cad9c66b080c 482a252d0b29f7fb876666d565f5f67aab6d39f29317d31236129632585b2ef4 4163654838c2ba6d17590d6710cfcd1bce67f76b7298bfcf92139d2502b899ea 94a1dc49c5222983b4d843765d51526f0f1cdb54bfc9a68f62bee58da9cd0270 4887f9ef5441a1f87896339506af632b7d8a9c2df05b002b42c5b6c32165fb66 c53bf4a93bdaf03f2e3c4561357ff9a247cf019dc38b621b916f2c4d3395f9b9 f94b686e0d068cae20b55014454f50fd950ac9f84ca705b629dfde4baecf1ffc 2a3f77e3c18ebe3ec45879fab23e3e3f1db348d06eb30666e3a185484a91b7a5 5a40ba01f1427edd310b9408c5ab2488e5d05ce48b8bc85f8c0081adf11cd9dc 75abf56aa4921954d4423e957f680abbf1e3f458a1717f21b69d26bc7132d484 08a037168f337c2f30ea5db11153eccf6f2cc847e052ef0f2dcca49e446f9c2e 9a88ed5ea6035728e6cfa1407aa9467df401bf31e5b9661160bdb48ff7e1fc36 5c86516712f28f11b0a96055acd38d7819d497ca2e4283fec8300da62612ece2 b8a0708e9b6d8586fc9bc3279a5f0a1bc99505f627bbba52d9cb4e313ebf4d4d ecc9011f2f931508fd5b199f76df7bb96ed8c1345a1787567d80b249d2b0eb55 18275f7f1472730153d052fe574b8e890a4a32b012934ea236b3663dfa28f14d eb3014649405efbf8bfc962ee7706e9bee6a4ef5625eedeafaae0051aa721917 59fee3ebc15513a0c63a4040bf31bb02b6c20c9246d006b4f026c1db2e7a49e1 8bbaf1b46137d97273c26d93918ac0baabba90084bcd209a0a172eb8e7ef9b65 8b2d7272c1ae09827cf434578ad48fe3ebba74ce2d3fa00a35c55523e3a9de89 e129b195950d493e3c9e498f8dbea5b3e1eb4dea65fc03ac2bdb26df885e4dff 3671edffe7f5fa8fe14ccd74930c7ef620eaec25534f1e0db04046db3a09d3ca b086b636c71efd2445cf6281fb3fe8c858c5a345a6ab38314e3d4cdbe962c34d 7ce5992f4a5b9ab21f3b00bd9d03eb3b508c4e8d472f6ce75a624bf69c489cdc f709e736c33fad590fc82f9a7147597d3ef86a3421c0cb90d4f7824f19ee0643 0a758da68465fe3fae79ad29012b6035395373d0959fb27bb440dc9468683f19 5de2ab6d01977528e26cb98e22ce5205b76ec3fe33dfc38beb8ed1ca8d65f41c 0718b9494418118f2da64066b22439acef7fdf1e0f8b14f0522d42d4ecff4722 52ef5deaf9620304b0dc480da5db8e3cf017484061de018008e2ca1c2a6f0675 cad10726ba8716d69051940c377ac5f6a82e2e9a23096597cebfcf06bf515e86 9fbbd93d71ad8ce532ab9b2024aa3cfc17b89137e91f4c3f93097e8a34a10e17 d7d5f11eacdc7cbb053d15d3f63bd0e33554b9dd2eb8c83800f8fb9d0b2dde42 07027433acea249fa21af4cc3df4123babd856022b1a6e7e972a80602a5292e4 4b1cdfb44d28cbe272563682d11e1489f4308bdb836b6ff4a61d0d38be1a959c 9f35f5c9b5b382dc4b6476d912351a322cf349d8b5861df181163a46cd393fab 210cec3467f2c3cc24ef57caf3f7fbf6b7a8b46edf272adbedd8cf67ee954aec 6d5fafbbdb69bd02b98a2b4bdf24065092c0fae33cf6c6279647675cf20f5fe8 6814c20e384dd2298476d630badd43d8834560a06e4a5d328268f03b9f65f714 d8bdec2059ee9a599affa6e3548a00524dc582cd194a66b5740332d8404e43a1 8e446db99e8e579e5059ac28440d2d2c6a6f1838bdfe074f2da61805b213c11e 50a06a07245c8319c6f64966086e439e8445382b79a31513ae10998537568235 5efecc1a91a9a9df0fffb1050cb1ac2905100ca92c0ef87074d50e17a54c4696 ddf9201bb6ae23f18cf6ef069d183d0ecd22b08e481d2f1c4760f3a029a17ba0 6c1f2b0a8ccce1c65d4f411584c4a4811894b96a7c74dfeb4ed9680e4edf0259 300e358000c2b357e48e532f4e02dd6901dea80a371cf4b4856cb5adf2f97c5d 49ca50fd86f5ee0445bf9292fd492e4140e550fc6a520024619501179732d503 026d202c9bcda09cef16ca1c5dcaaef6da40fe42e533562c530e1b4a69c17277 8e4d82f0a0384babe7fd0a4326952955832a37d1152d0fd189094fd0922cf106 c3ccae4f7e60f4fa82bdb101fbff68cd2071e2c7c5729b3e9d7a0a6a51809807 e2c970b2577d34c1a4849fd4ddcbf48bc88627d51c8640b3cb2ff73a0ca852c9 054bdbb5411a58a04ab389997a4c85e38f2c714137252db2e130b80947c505d4 491f4b4d406f6e89833f4255c2f53103a26e3fc9f2d3f04ab6f5e034f9d16a3e d7f7a5fe433888c71ba0567bb87dd28d719e92c71254a1f84238c7a78937ea2e bc03db54203b141f413912cb5a0cf4aca06609dedd432042f8775aa2524b0a58 5e59b2c9319d9e6b450020f4b19b4c30bc5b2be4d32f4f635005f3efdb40ddc6 4d3553533863be129705f3008ffb8cfc0477860675c0ab53a642a13445185e4f 10837c90037eee815d50df2304f1c5f35ccfe3bef086aac31ea953fdd5b1da1b 5783cfc3d851b2043684d08af46bcc28c218c4800aab3e4a25192990c3a3c143 a529b861e4f2a800c334f542c958072804073d33ef707a324ffb950a0d9a3bc7 533de95bee68271d28cf19a0cc1eb17310c12b00516d8cbdf11a0af3d90f6ae1 ec2a1aac02d4a55ff2436405b7e821d9612406a4e1aca17b3e05f54039d47fa1 cfbb9f0fe10486fb902b329603cef2d1ed5be4e50557e366dd2d9c75cf535129 b0fa5d3efcee11d9e75ae5e77cb0363f64278fc6958114c6896c77f776ea456b 92562a6e185be15eb3dba54eba90080b2b556ea4e3244195e97c289f2936c09c 1130fefded4d6afe6bd3c775c6f3d92e7c49dc0b5f4a64ab09dd94efe5bb27cd 03df5ab7e0e605c91b33709c625af020147fd3d14594ef3928524b3e41956276 fd4730ba5fb0ba5e26f9bbcb8e24be8e92768b874ba84bd850d3d6c6bf14fa36 ff340888ba7d0ec25503b411fba67bd3eab35e778299f4c7b8c4685ca0e4073c 7cc168482cc27ace90bc3f551975052082c33d3c74244cbf423910d00122e760 b67e965b6227c63f7b1f7c1cac3f4ffa044b499ef2126be0e1874db9fa24a6e8 af6ba3f29ce5b209c40565ca02b58dd4380715f6f10d872006488359e5a468b6 4267ae8273f14e15165df0be29aeb50a9a3bd312816a9be63bb554bd6b9f82df 4ea2aca4800d87b6df9995e3d83240df97e309fa4de089f8b12582cda536ca05 bbd135a87a41a425b196297e060306fc2ea93a1aa2b9f3e6ed2b66b52f4c1f89 d025ed814116ab93c9bac3f9a4272502bb77bf9f71562de1445129e041bd2831 12ab2d4d0972a1c1cb4edb0c36bb60f3c347a8a651b814325f85b326e48707e4 99f3623de0fedae77f920301cb2380861f9844fdbf0d71991b0942331449f9f0 a0f626fbf3ec494ab01485e7e9e49f97a28784231070d4ae3c6b7a9df94c37ed 580d0cb132d0204f173abefcf7caf3abb8bf62bf65bb4954b29f4451f642bbac 8c97a982ed265af9a10f3f8093be8fbf23bf583fbc5b85e8bceb0aabdef3217e 66c73b6297879ab3b614c47308a3e64501904c7bb61e2896121b3c97b12d3ba8 33c536581435b1ab7a93b47ad2e8ee25d3358873c7f13e07e38ea9d1fde9581d 358af96d40f33c96c703a54970c329d9cb71777c66a41b3706b161730e178e6c 973bd3b32a458e0b238a95feecc044bcc7640de370863919a517629d26a0c100 9d3ba5fac2f6aa8fc46a7558bc756ffed5a1a2ae57aebf71360681fed878424c 95898052706ffa6d889c76a090e8244d2e6e7d339610a429da38c3e454465e8f 6604e03547ecea591a6d36ed604582cd8abd72bdb2b49e0a917771da20bcbaaa 38d80837cb55b1ce698fdd5b8d44ce9bfccad9cdc19e0e3b7bb7de9f5eea7833 16bb6df962e6127a9b053dee33aa890210c2afb63058011a95d5d6217aad5d41 09d9cd42fbb4bcafa7fa122ee44a13b420e77c58add73a305eb3c2b89f81348c c5aa1333b34398e500bb2cf60376e5dd6126f4d3db3034259fdf55bdbd3ba7fb 3fae5690d4a5bc412b86d7618d36dc4ec01009aad3edb77ff776c673109c7548 b28456140a3e985c226ab99a6c80f87afa3519e955faf49227c7de36f93d6d5d fa133b36fbfadd578d68199bd44c7e2b902c2ace06dae2ec52034875ab963d0f 3a5c007a828fd572ff8e0e713c46fc41f5aee958e186c1b88198135b116e5ed8 de33d23fc56054e68f333fecfca5f4d576fec6c500a494b008591f99c2a6c126 8db348260e9bb621ed1ac68622e551e852db4e8bfefb048e31e606e71cd9ab0c d909650ed9a50ffcc7f26fafdcfe91064dd187eaea4dff027bfb66d734a94bc3 2275d3df45c2e67a1831735a9852351d1e40d7903380cf3b33ca7ad4700ad8e5 9bf506cd884abfccf74b7ac9899e5430ab9be9ce1dcf4339453cac9308ab4867 044e10b3a3f390f0e44eae198a8fc246162762c0303b9326cdf01ae02285cf27 3423e004c3572f016a2711b9b7d5cfa4be8327185f4782a83e719fbd880ec73f fd57d3173d91f4f5b7991b70a4a7c17993e783c9a250f909d8a452fa1d4a7d89 4fc2721e8e5cb0f0e49791437299a6969485895295be74f63d8253c3e0897622 c370fea6b41b19482dbffa79495759699404f5b8aec95c42d022e710feceb4ee d76fa502cf3ca64f27d37460208b45d8bdb4343aa09f60bc86b43b45b3bca456 63fa51cc0c431db9458fc137148bc7072aff9e34af67204b0646139b5efb43b9 09ea32768ee291622d18b4ab9b182a0158604757150dae3692016c830f19b508 f2b2230fb64c40711b943000fc9faee75bac64677635f21b141fd76aebb38dd2 5e39938c9c977fbf84df5ee0f5cddded6d55f17eee0a38dd5bf01798a9df1c01 855f49af12792ec85075cd22ce20f3bcdae31749371e906bd96504b1662c1466 4fd587a7358b0de45ad268c237bb9b299d6a9fb06414aa30300e237ba1a3f72c 3edf61a65c3ce5226dd877d6aa70d639d52ebea7fb4f3aa7259e0efc8a5ea1ac 5846a56eb003d2b04f8d8a5cd02391ce10bdc43ea6114b740f590070d28a7003 c842f7022d26e8f0c9b832102efa259ce5e77ac2453fce14a364c590d1ec5d50 f90822ac98bcb91651e1f71f9c0849f821e2810743ff1e8e7aeae5909908f451 45091874969d3c9792356d245536a8da824e9adff04698cebcb99ff8e9e20f3b 9542ecf82586fdcd124636a4ee4bf2c4bebfa0f98dd76b45adac28227b0f455e 38c69a23cfeb562bf698b66058d99e63b5ecd7b8ca0b1354a57e9d60140c35a1 f7f75d344ba6ecd4ee5072363a6eff47161aa6334c86e4f3ff832074fb064b16 f7815c6dd6946ccabff6b93effcd8cdb8dbc9630ec5274dd476b27c3344438f2 b21ed1f01a74f7cc86f2ebb376b203a82bdbcc17a6acc4700d314012d3ca7e6b 54655a6c6b8e909278c760828a75b2daf5bf809aa10d84fc68bf4e1d3636d5f6 6b69083974fab0a280295796253901ac813b657efea7348aae3e2eda762ff923 fbfdf4bf87b4bb696d14bc2b350acd77eae89f267666a092789e0af07a32740d 38 50530d5c1b50c1fcfc784350137eacc142220fa028419230e00ba4354d916204173fda0603a66f55c672c0155d049828ea04dfc387dfab5d5f9d331e1c4513091986d1a8a74fa3310b733c01ed012db2315a6dc68614d2135f1eeae13ff872027a6ba1a177de6d619f32bbfa41ac2e0f9c66fc5a565d717b40b4b0eae5649500a067a4d901b99011f862274de2c0fb6f8d3b450340920750a6b9f1eb5a29a70fc6d7512ab7c02147da9dd5512d4f4adddb5620ed8e356f34b5750aef2d309a02241ff73998ec9cdfa9709573b6f7b00f6252664770a90644aace5bc2e19472054a78e9f9e18d4a29d972db99875ad3630f8b8e9a947bf40da4ec1350a352d401f4d53782615dca11a635391692bffd0f4309411ad9b206a3c5c9adce5f57cc0631f38b4da1a6294b4c9956f9e34c2f7f02ea56b61639db7e67514ecff9bf2c0b98201351fb4ffc8230abccc674d3cd8dbbd959ccd8b77fb546634c028713b80af4d033fe66a787037fcf38e23b84c8f48b0d5f8a48c24b1992bb82f3c5cb1c0f0f1446f3ac899ad343c187ec29eef6328d6bd4a07c6636b5349faac50facd906f7ca340c935e677e08682f39fdc48da4d8cdbdab86ce696e3bb9458fd40d310b7e06f49e51e729ae2e705ce1b5cd7d0fdeebb8da7dae9ec721c77abf0fee2f05b051f9feb49496fdded0f87f2de1186773cb5fbf3f32f9de67aded3f2deab60469584cb1d1f696c5e1a994f19aaf5596d9cc7193f908a2d34391bee6f4711d02b093ec04e1a3b796798f1a65a656f38c43f851236eea699e610a87df289b42026e9eb4c5263d3693df9458ae32c85e0e778bf7dcad72cf194101dc2aac61540b8815ae39f5dce41cebfcf4f2ab4feaa55406c6db38d3ed6c2538c55f417c2f0d1fe2a0df06dd3351936e7ec94bbcfebe0476a4ebe090c7f34c3712f13eee0906b3918da84b9520b5c889c0924239afdafe9f49a39e8f40af461c8fdb6623ed0aee010f345fa58bd1442fcbb177cc23aeaa9a9c80aa311f92cd6754ceb3598409c071c7557df871a5bd8efd55a77a7fed0a2c2f0b4c4ead01769eac1825b8d40556f8609669c8d04cab252a288048beca6dbe72df33945f0b436d20740c3abb0548bbd93ba41cc3e5baf1fd825aed918eca542b21af05e284fa5d1940f5d95e01cb226242af359ed089f607ed380d46e947058228c818122851f880ab8e7171088bfe7206f84c6dc247981abeaa724ab4c34a21e9557ecf8ff6baeabe6991470b06365d278c4ac03fc5e9bc4a06f26acdc12294fc2bb7447d2d2bfc4ca058c707a26332713bf61117edfca06aa7110b9d036ff090c32556d671d0b4011d139801affcd2b3552ebb196f01210bc97c59b5783242a8b0bbbb046a05310e7bb2850e7f59eda6bb5216d9ed9187dc9536e51b8cc7a1b41c805e652eda91964631060622cb5b2e464bd5ada60d57952e787e2d535df78c812088d088b7f14c6df7df0ac69469c699541ae3863e80bbaa2ff686cd5d2ebafed1aa85c3fd1f5de51ae30d637a4c0f64840388b4b4df37b38f77bc22e9e37a8c03e027b748f0527e30af07a00b09c1cb6b59259f247db4e4c00524831d6d90f433cdbd3a37e7d6025ab200256c9411d1c1e1d688563a84f4fce67b5e11123f116dd78687baa72fff53100693d284374489d97bc23a32f52de697a219f945ef9d27d48c4c75275758e37e0aa8067054df6a037fb51329942667df79958c66512bfdce8ddf6be7b68c88be0ab509da2b26304cf0b9d3b50d02c2102266dbb90e1be618c9c61e9efc151099050b20d3818c5897615a9c99fe42de4c3002c91b3cdc456a825a0cc7df3ae6d503edefccaee3f2953ee2a4823c97dc1184f16f6780059dec788b502458795b4c04ad511550d60312a882177660adbe84ec7827c8313bfd67de62df338f391a13032ceb01b49d9a107c23e5a789eac36b77f900f66cf096093595ffabd43a6b9f0d68c2219740b0549fa2f1662b33f4999a542fee6aa7a3426c8bfdc862a61435013c298cab85f68773df3ca2d58c872c7d376db95faba7a910f1f7757f24618e046c299c43ce8c2977b96757063844cb76d2ad209badca2d2b701439704979ef078c02ffce66f8e49f6123b56cd83a9e645c882f5002fd268aa30ca99260258102efedc6e7529c0f3119bc75b1c4190b9cad55d4dbd4c2cbba314215d8762e6d005b1b5104e008331497c958512cd5a11a0e4209eca49b13862b25eeac38e403038acc74c8d9cd65ac2a5615ce141e156d32bb14620cc151a0aa2d798be6668901bfd8ea74df2a427e3d04560d3f5a82ed25773bd080f340cb7e34daa3ef631b0e24c1cdee1be4a9cec177f3b2d059d620c48729d53bcc7c26f7afdf64a3a0ca0c29949e2ed5c20585182ea370e5f2ba552c503b75211ae01aa44b3bc29fdf7c06213ab3844afdc91f09e598a5f08a2961758570c06f4e447d27307908016e51005c58bc9dc0affcceac613129029eca50059b527395aba3dbc678ace92de6b409c9f4cb5fe59d3db5aa8975a6bf44bd52a90f31bc8a6dd03e53e42c6957cee101551a54ac6e216bbf1a7b0e26186257975b7c727201eb1eca65a8e024f6aaa301f773b438c69b1bbf8b280ae10597a4c7657521d699c70d63019a0a708777fc0edd2b17461a87ee3e6b4a98b320b7a5fc9a041a75b2e551df26105edda35b7f0655166dfe0bfb1261e96a433b6da50c7e31e2d698599ddff6da02c6576f4bfa06fa2d834d299057616c4a98871313607f46fc0a1f1e419250582a885e75aa110c70a69066771cd2374b5f5ee40f2cec562d603f77f0d7aba9324ea584cf40fd04292e5db9aebc3e124174a57ea393c2f5a3f152a6fd83531b267216bd225a1706480b6320a639aca669faea87a5b95a8349f47a362620db4da044b2bac38d530d45605992eeee058fa956a79a9a22423ccb959aa4e0542c5e27814b3b9072a500f88e4579aa80e453528f22157cfa4fc90d2399169a00db3c054096813e024a04a358cd176ae873af48447eba47c679e01c292d17d6a743c4c65dd58537bbe40c584a8841d1334cf4a011d713114904ecf79d29690fd474e02e02a04886a08f051ca5a5a1423d16d952c6896187c66f809ae4eef226c0096d352724d69f76ab01e694e178bb95c20fe9f4d32a0166c2d12c7036e4b0f418354b0484e41ede20075347c11f7f2e88f9a017beef6bbe803bc9b1ec967e4f29b13323532fab2e8b032318c6d362e1926ceb1d1bd102e02e9022e44f4e09bbe64f6c84f454a7bca00536b1bcc4756f8b0e04cd2e4b69c4e7aa4f6d048a9ced8a79dcb59267b6823e0263236ddc08ca12c1185cddd8900aeb1615dda54ca2b361cc15e2f91ffdce1f0715f16ff14eeac60fef63ffeb0f7859963ed8a1f58f18414e932316cad3822906bd67264c5d65856608faed930b90950fa84e586322b6430bd10a9b0d4cab320dc7bbc7fd5bfce8f16cd7aa233b3c2fa62571927321a44e07043ccad2bd806903391100bb7599e3a5763544db299b6d84a6201dbf19c67d8b3a1ce167f9f69b0229e1568749e08ffdeb71ec520675d24a8d935118a4ceae340b0a7ac8cc0fd90b07bd9420bf2f79baf2c835300e4ca929f3b1221e210b1b03aaded917edfba4073f5c55d23f560e23815f3c190de64b1fee1027da74d36e1a166f043f8f492f07ef3c93544a02cf1e6ac713a1a33002ed2a7d847cf61e8cf990a72d31a66fb20244bd91dbf2d8d0b4ed5daa02a68c166235eaf29ef8da8403a63483137afad90682cb208b05f6a3ea93dbf61887b770daf247b1b13622299193b20fd313985f0e7f15f3f9c8000b257589217a445df19e2fdcd71cd01fec01ad71d79cc34eb70dc955c996f1d1a1ef973a009d28c4ce69d7b00d4b39cf17e9820286c8ad992206f9b268a512a5b909ee087fbc25516a14196ee12e88d7b3119fc4cd3c713dd20289247912b66dead861ad7cd73bb24c29b6b841ce7f81d8d1d87f4fa42e4ac0087073290c46b78366fb297c4a6fc0c3122368e67a94614dd7ee079afe9a2f620961ce78f19c11003f734bf48df0eec2cba8190c98bb7f40a9eeade6d2037ebc0dd21b41ba2fe453862bef3be436a0fab704144d85ce0a9204e36363339baa4507230b6c76b4401ab7871b63f4ef73d568f874ed6c89e21cc62822098141e16f0fd8f136d4464f016ec7abfa58cbc4e604e3d425e3adf2a94ed6cd1392d56f2704b14c86023284c029c04f3d2cf0fa2c4b57980e4a0f56cc5ce2191dd3068cfc0e8d97eecedaf9497470064cc0ce125b9b1e1bacde5a9587fdd97a6bf54fd3230b5523a3b5d85b3393b584b0c7ba2dbd6bc39f799de6d4130a4c830ac98c0c15083db6baf4e2a7f2df5440003b4e42a4e254492387b3de04890bdb7e3ef428c401322bd14ff8d538377d1800fb39623441aa01b9eb22a8c649b20614d04b591c0b2bce9770ea16458865649dc9e0fb34c1ec8c2db7cfbde9de58d3257c8953d00d66ddee0faed1397a7365d3c5d8c26edf42da2e7a64000e4d2f6e17d38d4b3d0b2fa196680e30856f7ba26055cb8db94f1f959f0b0c0e6c03fa6768b1f630e404768b1a88ee8bcd1863a044710449321166c9b5655c217306ad619e873b153b0ccf61eefff7482121646c59ef2973dcc57fa17560588500609e6da786e3e2350e923c7945ae5e9fa99315bbb6c99d294b42ffe48dc3bfcbf5a0b82cf4c2ee2607534bddca825e05f452b1b6412bb05a98363240aece15a731815d6f0f58dbb50b13cd03e2bbc9d2a6a9163c897e5dfa0a9c2e5f9052a64947891598dfd76c050a04cc7e2b6a2433344c4d2f0fa0bb38e7bcccb0ddee095a79371a3482c6622900816fe80f7ceeb7eab85876196c4925f04a192fe59175281f70c2a98afebf2300d28f5eec4c036dabdbc1c5c0438c6488d6e03b06813901a162e463f95966d40149e6058938c78fafce6fa11e77b5e095f4740a99ad4d61e270bcea34b2a3c60d5bf79ef4c99a97fd6cc9a6db88d23a0b0c6e075b983babb8e33a5cd1295314086042bebeaeeffafe09343825867243fff629fbfa5e43dd8c814d83b041394501f76517f7829ba6b27ade1da765539299cc3ec55aae8cadb9f388d11f5e46540b50c1253f2a74ec837ba6f0c889130a5fadee2c24aaac92b7dd7c96cf3d4764076757092486c32d401921756faf0ae54f671806f57baf20c7504ec27fc840090a345c46de1f0a213093e4feed0c2474e8d00751533eb38f21740f90a532cbab0938aeb2eab72983201e67fb8cfba1522a380c2f7e52c5ebf84d480312a305fb0267a32d20824dbce4d04c5bc81c962417ec834df5b5a2a20b9a64f312398ebe08c9fcc375724c81701a9c7571959d4e98738ed0b836fdde7e69f8bacbd718dd0b93dca81d3a01ab939eacc6c5290a227079d14a637451a4bc4ed6d95dbf1bd9024c1fa73c8c4748a7bece777ba89e5289a266edb0f190c0eb204a2fc00638150eeb167782f024f5bd2a675be480742265b5ecb2f0c7cb89ccb5e5302b6110b801e998f336f53fb681e6024940431dfc8f0760be8c0dac0f4573e2d4aa80a0b50012b36b36a95edfdb7172b4c12586f2e90f0ef029ad46d351879758dac532200d2c57ce3cbcb6d5b6abe275f8a98631c91126caf4928e2ffed2a8478c76f05506011093124331d057ae84a3054399cdd872c39170944434b270730c09d6b2360680d668677be702c0c4b14117d7a19051a950f20b8c742adc3eb29c2fb4883e0544291dc87e1397ad049d446638b55af62efad0585257be515bfc9f1a290f5f0cc6f20ecc2908782197af37edf432effc87bbde671438723f7da2e1133a7b95015b645c4a02a4aba14c370b23cc006a2ab5132f83edd6c59c7a633631b0279e0464741eb9e7d97234e4d859ca4fa9e828c502af81365d5895a45955ad814ec8036121bb5395aec20006b840b4b45bc2037e9a5c7d319923cd64059cd21139d80dedeafdab448b13bbf0ce43a0c51be7072e5d62a91354f5995644b88492723505cf077984d1994785d6acc1854941849b926995617de6aa21ffe87b4c0e897802e1600678cf650c009cf9279077202b4aa01f3534194af2f2299b426205a1a0030390f0eccbed460d9ff6961c475206db0339323d6af2665c97c56f4574a8a905bf80a7b8c169457211ab0ea0fc31b71fecca1ebbc2db659a3549e84f519d2a005d33fbe158caf318e557f39228c8ab0efedd6a6dce9e347fcb90b0d213b1c807a990953495688d41396f238720d2f942873e42bb2ff280298481f0e4f3f8c80f97a6669d384ce3f333f3f71e0d591f107266cf46388eba3f4d8b8bbe9e6ca804dbf782bff51a998792191cf6048add724e3c620083401b09c59104e482f759012e81e47bbeb8d6b4001cc272ec43248f3a03f77ca61a9a813d4b446be5ac750cd9662c7e398b7862de1dc0e9571394bf5ee5a3cd905f18a58afdbe5555cdf401ae6ca5da84581e9bc99393b68db21a6dde189a8fde88d89cbdb8a78be85f290bbb652b01b3fd963eea02d3c6fc92e9778d585a927da38fcee52db599b74e86014ed68a16b58be7b05b4827d65edfa0d52926b3074a3bd033ecd4bb11a5a2640122470a79aba24bd5ac5ad7dd1363403aa6d08ca05e3049e791f633015b6e6907299eee090468dce011cc5831e50b854ac27dee76168c481a6d5f5f343257ec0823517da298103681ee0b76eb36fa9546e6fdbe53c1f30470e8dc8d782c10f20e1f98c739d022bcaa1f3e9d39447368747b058b18c1ec82dfef49fa46f5a3e8040601bb0d7875d6d59436c781c80b0f563f77445936ea7bfa99c9b202b6fc7e0bbcd2fa2a656e280bf3e6ff4fcb7a447d050c4ce8926b556ab4d4963f7d1a330418594363d1e66674a09147cd3c0602923d38c6e59ae3015ce767ea7ff30f4c0adb30d9a00c10c1fcdacd8bdde252e42bb633e8cf1e802f37908ee2c6ae05f50a8bf771ea62e4ab6c691f65d66cbfc23cf18e7664f40e9a81b9cbb856cb33cf0f51926a1e0446b105f8387e8a80eee286b643c3ad48b2702164055d529ddb9504d4a44c6f357a21edf9e0b6c6d1c9a2f50aa700c0e9f448b1cb37d6be73263f093099b30fd1d3e7ffb2be8f008c494ac7ef7c662027000166e689edf9778a63063a144b0d69b382d2b3882497c3efcaf2016e1a16408a34d66a2e8241e16e930d3463075738ca95874e96b56055d3fb524fb6c8cb78f07b9c91ac4bf50c89e50ce386f717cfb29cbb94200b268fa2dac8ee7637deb69c61ffc4c457e223f17f076d39802bd6e4368217b7c660085b2a73fc81025606f0b7fbae61d078bbbb9a01996de5f69ab332095c3f69fa953133419e4e27c321ed8172f66a2aa28e9fa00285e5872de02a4a7fa8eb9c237cea623dfcaffd774a58dff81d605197a9f0a6069b8d89ceda19207d321a6babb00b14ba41c0f90556e6d528b40e87bcce10a803d208267c873dbdd050c6236dca754d516630b964903df0a9bdb1c16b74ebba03abd556a0ce6c12d0cc7a0aca849b9c2bf51a54c721257e1cae3b6c5091e9e00a2e0fcc498465126d4be33eb978c8bba17ead82de93212aa597eb70de5fcc920f6947781427e35107a86b4140807a11da8f8972af5ab00c0143a898d2e83a640d68b9c7267b29efefbd5aa6dba5d69552aaba10af6b00e28a448f86bf1b95bc08720ddc61d8816c59520e69e34703ee9cd4cd92b5b39450fc906cd864273fca080a1bcb6dc37b990723e056422e2897ca1b47005160b0c4f9896642526dba8a038bce61eabb2945ae1165ec98a7456dd91a89fc2647ad3d83c78a0db98fdeef02d8dfe1a2a69ead13134faeea677a5dc60056b979538758736e4c22be4d1c0b027dbc2f9780a49ec94860aa0fc0fd06a88df8c79c1e81b802e793b38da9ae8b066da8cd15937fcfedcc111a355cef7fcac20859b4e020660cc1d568290ab8880e1ebb71904a36f1fef6f19873a989b7c73ec96dee503c2ba3c5af2b81d41f5f08ee2c001ff5d1e278ac5584fdf4568fc29932e66e4b3fd36b441a8ff3a265e108d6cf11dff6571af308637cd7dd4143489760cd5e988c5de2dca986601368a50a6728bb4b4ec22ce0107d733923f74cfc6a3ad8b02946365f9945018f95460e01bc4c4d47cb1c21526b21ef7d855eb4aa5916cd514a73e7db3e02ef9c260b46001dbfac6929af65ab9dc15ef98777936d5fbe345977dcb7f14a65a2c130914b042d6f28c4cad41cec7a58cd817525c22236e1ac903f745c28a034eede566e5200197f53bd9d85170e47e09dbd33d44e9142c15d02b975271b08d7ea4f701d940e65b9181698cb3a9de7a119ad84468d2f496487cd5dd94bf0dbaf6260569f0a0735270f8632614d89a67666784cafb467c664ae0b31e27d4dca9ee596e05e05034988369abe99431eb9151b98edd9b52d7aeaaf58cc0f0a88483dc06b769985051532c1f167b0012b6520c997886c1941c54cdf7bad5c411345eca8d0dd7c9103999e154cc35456b21fa753d270edde105609432c546de1f38790ea4ab6b49c097ce2e2a83a0c67f98bf8c339065fa6409895be5e31c483171eff8de7e85aaa040678cae66e64a583ffd8d2e07332bcc18c8a21d913161eae717905e0fc94f10e79f96449ad1cc312d124f83e2435238456297d5637eb1a2bbe8a68c6d1fe490e06b05430d4eeb2c11b3d93afd95eee82e7591872f544d176b44267611c1bed0596f1e9f4b20603e00bff0f1701f672c987b1df0f673b994bd655d2a3ea9b3b042b249fcae65340f381137e34639cba49de5be81eb329153617f0ea0782f4d6048653e96c9b27491a074fe02749a33f0ee013488c9168b18c20582bd6e5e0320abf521fb4df547c4f7dbaf94c6178e2d0d8907ac33e77031e9bae1a80d017a3099e9ba3c16a18b9aedcbfc8d1924618f7ff58135ab0cb3f85295b8766ed0a1d08f680c539cd0ed7b1b24630bc9f5c0cba555f65c4e09f4712da4941a2c733ab0a08f79fa6b2681ac05035c24e300ab3ff54dad61eec6865cde08e69ec735209061379c693f85c3688f4a6e04601fda6cbd0c028a4a80839f743e79eabdcb9ba0c8c333ca605f3a16524d18e3a25dfaf2d06b4cf109e66e5d92f0af1822139460797383edb729bb35ea05156de7ef609ed5ab3890b5b80c46a278c392c3b75ff090c7b77f5b1f323e63fc3fd47d64b9a250ad6779099f6b9bb05073709c031110f66ab29734d77238e63859bfefc960953f83454bd809375ef259dca1dd030130194b4f11dca8767af16c5762fc0b8d300b9e603eed9b68dd52ec723029430840177c555e64fd7024244562b21f7aaf4bed96ca623b58b4e9cea3434401227a20445176bfe361f413d4194693a275502f6ccca6c2f8f36f9db94a6e7e6924e950d802e1e22428971f82e5d68275bd84096ce901ac53dc44ad6dcaa3836d9a8ed078be51c9de93333316eb59a5fcb86eaf42164df35a9a5d4221286210078d5cf0779f249d7bbbab6c7a77dae733acf47082617d8f76b899378d8200477d178a80fc69e37a4463af1e35b45ed62d09a2a53cbaf5e26bd752f0321f091f1e6d9ce00f0587954bc47c8fa1adfa8b6b4a8e89d593f2acb8782006fc12a50a2c9d8e60edb6744f4223436fddae4520d21dda1ff0c019cd674e8fa0f7d86e20502ef2c090480c96fc5f281c09bde6b836fcdf9cebebe890a9c7d32b2fcf51dd184245d02b5520ab2ea5dc52943ce647a24d0f460ca71d5becc99e6008f4e4b5504a3a4018548fe0df0b71550f15f6c780c7a46f2e58354080d83748a3833bea7295a47072c523fd2673646ab48d9e50e69fdf1b5b6a6268d339a2bd409db4dfb5a580608e6135516e2eb4f825d0aee624639c765f57aab35bec7fe6ccb544152edcecc042bf6919f45cedc9c638e15919d511fccda85ebe6c4b8f3ce48f98dc6114eef0951036f38723bc901ac2a27ae2f399e625e082a7da1e8fff3e53ce08ae798050b9cb7e886bfb14650b98cb2135f836f9991c714f88e647fcdf4737a8ab074f60d5eebb0d22f1a6a156f41d47817f8e71a213a2cda9fc9138b2141b6dd1bd1b40a789adb540f827cd2c481f27904ae6a3c2ecfcbf8871e4cc4886f2eee673d280954e12ab5491dd2505156a77d0b9ba4bc5da27fac8117d2df4417d082152a0603fd80070a826088f496277e838be997851aeb56d6d0684aeba687a62932b4e20621a646f3f799526760c39a0950ed7a43ba336212abfba34540c77a28d9f4bb06ff979e2a48aa1f7e3cf50353355c19fd124f0254c1efcb7fe6e96dcc99d36907fa24037bbb55bbdab52a3df1ee60a950ed23863f12388873f3a96294f21fcc0a7e0c619e8b8eaa2c92eda8c4ecbaf2e0e459d4f956f73b66b126cfb123a9c20b6671bb24889ae896edddac4dc7ecaf6ebe6384501ab97b6cff92b6aba5651b094a267676f9a5190a4df624e4418982725d5922e6097d7edcf9f4a0841d873809e2c3a8452222627a30dfe73f709fa4697ff5f024796fd5073ffd3fbf0d952102a6e76d299b2ce6dce9b27a5469ad875fec609126de610b0c1edf38bbd0f90d00d770dcd629b37a883b0feff338c0ff306c6e8752c2a821ef4e19eaefac504e08695977fc2405e2db07415ea9a157f5f27488a735c95066bcb050a1c583f58607b0796c0732709efa610c18f84eb8a90b754b8d2fac4e77ecd50c7211ffac870390405d9e281624d87cd12bcc435dfa080177aec9e6b5859887d1afe26898330e1fa4ec1473a73d78a4ed539a39972c61d87ffe78d915cc95cd3e1278d7177d030ad3e6a8d3cf1cf28b4d38a529356c58b78da55e5c48103a801505a040307c0207c05942b29ccaff175185691046060ae4ba48a4b7b804bd0506e361732a7b0bf71d2f6d35bc418b1fe686ca6d3915f0c5b270872611e3dea817f6c49b4d0502ff3ac42ee57dd553bb74b0463c1a04920c549c74b2acc966a262f55cbce7090eebf981b139f527c39b6aceb80905f186629919ea8444a89c8a3d8192b5bca702995636ab36940ef308beddeddfaedca013a37beb2fd41224b6fbbcfcf4453b05d946790e7fe83f4ac68ba7fbfb6db4f535eff2cf48dfb8ab991813a6b4d87f0eb5578faa8daf01b197582c51bfe2d6ce1050882fa96e56fa8fc968af560c7c081f02d4d3d0440581f59e940e9379ddbf4d41045cf5759539ce8f4288933c0b020f481749ec39ae928a674cc65f61f9aca32cbcec456b9a5ed457e900e772f40e1be35221de2c1351f192521c4d730620b37ed34d9ee4a3ac7c6e8bb783e87d01fad72001c6b344eb08fc5e1c2cd0be939ebbc1367c884e4e2d40267958d094068ec11eb28fdbb43b57cc5f70c05dfad08114acc8b8adaed02661b5cdb471b009b86de0e47d3e690fdaf72cdbf0c078a20ab46c68a68fca8c6b7db0198203030d8e24064caacd01a80b20aba98e3d3f3a51cc53c998fd9e13efc7f1764507eb0861ee72eaf6daec8b1f639d7314a972a0d2d28af36790b00f851f51b3c10a25019af906242d45b508dd511fdacb50df785908d4dadd67cd06246c1759a6f8870ed73acd6dedfab49a0132df0c22235bf78050c5c44f37067a317afcf493d1e80bc0a0e9890ad46377cf45286f31d0fbdab7c19862475899df9857d8ec2ee9c0046c9d596ab0b81b2929445028e3d6e80c3ee6cad52bceecafc83490fa49733f02e5066c618c555963e38b930d50be91312d8453dd719481714d3333148c86d507c081fee225310379d1b58a5542511a5d6be472cef944e9697ddf22e143b3100bfeaee842eeec4f27e344b381c00cecd86401f5c0b8c9d2a378963c0b7bc54d03e1ccc05965a4a084e0e90aaad1fb9a1813ec90452c85b86900674adbd1d9f50b7eb522e8a3386a259f12ce42ef2b5c7f3ee21a0602e7a8ad330a3a4f20bf5802e74bfc22706f6fc1d4e5e90b3fc0fac2fbc687f7d1a89e4aec13255b6c930309c9956d81b40cb57db49f7029e029b49de5b2eac7d0fef966cb01461636682801e55f60c2d380fe1826725718c28315f3f7d35aa542de5323337e47b6c7923505611676679c592eddde060f26b4f374410a4522eb35f064d071081e0e9e64b50dd800e9121b7db458900ba7c7fe160cbcce78eb3904fd27a05378b06b7d204502fda82f24f719a0e9adc6515cb75159eac217a523d7d91b7c258e8f72a97ee607ddbbfc0a421c37654716202841b428a9775447b70ce124f4cd92ddc3867ed006ccadf6b1749d19fbeeb11a13276a7d6351bef5696f107dbe5459a9116522e3095b0a31f0eccec9d707883517c4912fa89c14c69dd5314a12969b78bede7b90060c204a95ee2e62723425c5355dfbda1e6c0b3d56a8742d52a1ec6ad471e05f0a7d9e33d19a221ff68085df2ee5c562c6e0e204e1236a5b0ebf43584bc232690802c3bda6bd812ba50e521334c5f69c3bd36a5d10afa89493032b3756f2bf8300bba5a1266115337e3c30839b58a1babf35f687605b5ff5892a8ca5124f25fe09d7e05d56341323b9cf6862c9fe76b5cb9e23094591f32d5b9d82a6ffd139cd0e10a05627435f7ba82099355f1833b43184b15970748f4df35bab0cd0b3a927052f2674dbe1f68c5778e04eaeb07b0b8a5d032c4d143064b4f2ba6b02c0b34a03a6bd5fda8766a42ce12917dd4a8cebb0dc120148ce92d6fbc66a98b00728b60e773e83767cdea8576017744683dcf211d6687e174827445418536ea8f8277c0ea10606d2e2e78afc78d00253666ab905de8fffa97860c9ebb9ab72adc7e89d009725cc85ad44f0346f6fc67561a6854c13873516722d964e93d5f5e6b80b42032ab5e8a9db46dbfd6854d5f515eaeac6583437ddd6f8e17a5b662e748ea8b6072e7808c64bff2de2edc045e520eb6270dfe865e6a83de0a967d07e42d710a90e6846466cf9605d9199e4b18253ed635c453285f3a98aba257c01d98e845a2609d056cf8a13c17966e06cff17109e3089cbb2fe04e87308c64cb85e330b9922070a64733849d9a9816296966121e894724ae138d629051de2ade2b0ed3cdfad09d1cdcbc0acf0adbbf36caa14033944640b4d4e1da76f7e0cff7bff0940bef80f370109976f394cdf02f63bc042181edd629474f9ca4bd6e5f777108545ed690b11d5f4332e5b8a04a7984e526123a166a012d1cf02cd63b3d386ebefe90f120c774dd8d60dfb36da55f6f372a20466c103fa6c35f004deb76505f1177980a508d58f83d31c891160ab486496a1e58215274ddb3c9d147fa882ca76c3b50d690a8a06d03195369d0c99bc096fad0672333a0f56ac38b058edb707d7a9836cec00f3a2d1810d4b9f5d88f1f5e4cb9e6c0d6cf7ddcf68efdd0f5c922d301d951703b40171346860d16a37fe8b13ac2d17ee4f3e8596bf095d97f48dba9b453c1c0705397093259a98681b44ea99fa44c3c89346534cb813d82e5632aedf0de29f019c2eb2a126b57eb6e2ce33a5cef25cd2f55662a5cdda73aaf60c635b0ac3560cc28f84dd01010300e847a91562fe654a337797e40287f4f7e8c5ef44d730be0d4bd7be57c3229d49e44fc13bddcffb4c74ebd0171cd51e2b49582c9801450204ec07084defb841cd1dd52cfce5599a76d3a5aae0a7030300bb338002757afd0689341be22f73572c5e430a2fe8972cbade9bae152cfc1ad9da8a8fe82f28f401dccc75a32d68861f8fa4a07f653369d0f3621fc0bbe9d65997930aab8b25ac07cd079d43a0b9cdd4a1cf1cce46839d9ab0a26f9a02cb0307066521f4496f110cd74db73458078ccf6391be33cef79182859f04a93d9a92ea48d384c99e48b90282d775145370ad05c3b17dd9357f4149332efc4498bb4065b5b51b00de6314051ea6bc8f61492773ccef7df9b0310c210b65ff7d4dc41d79388b5c4cc6af7c01cfa3e0a5144414c00fe006fa1248891a86beed1b7ad5a055a8b85a33842aa80f8f8f91fc2b9c987ee245cc00799aab1984131d143527a0e1c1a123906c896c0d7807727c60af304bc2034c129cfe002e0a72ac225a2e13b050391d24c1629c0de86afaa0762d65404530585ffb1090fbe04e314ba18ad1001641e82babbabc01f5cfcc92ed3dea9c042b8bd12638d41b909fbec2cf471a6c275da8ff2c991a08ff2f8d0ef14a5f7005dce8a070ac41f9ca74d9f85e5cc7d54dc13277e43c28094a674e4ba96026785f00a1309a1f24291cbd0e1c6aec09b96b43aa18c0b25104208d63cc2cb2d7487aa4045e75e61b999ad56d7412f174ed2676b142523be20c67672c1c55632e379171744ae0ba9ed5127ec93457e9b240231ab97a6bb40e00be85e3ac91470e13ecebc8f2f711592e9f0a5c51fe87315ed53e61e182c3b7062cb071b7fd42976670a7c0e939cff16f3efeb9749550b9b4c3ee4628afb752042da7e1e318df6075336f018f6306365ecdd6e6da00ed1407663a123a81c9c30a7b9154344ebb0056cc69acce01391cdc68b3b7369333b56babac7ba8f12d3c0ea18c88c7ba103ea701691eae77b3ff399c1319c939135233c991371c48b3e9039503c2b3303655740b8ca7823021002d877ea64356e23ec30a3ddbed8f311c084a00102e40e3f03d16f56be99c746c4cec5d855c7ef77587bc9ae58ce52a1e0152305ad3871dd35f73f20cf0ed7af7786d5d9366cd55e03964bbbffc2f0adb0e8d47952b21c1585666487cef82d40d6a879f86c4e1bb39beba3f680122a00d0ad0453b5f68c46469ae6e8a555b0ac2fd1b5dc78f505080479f9100d1c936ca0ae56f610bbae7b68842bd33789faffd7c2ee4b83ee5af164ed694a44fe92e040a04bd30cdd64126a47d8ff7c8788afd5e1704091c20b9fbd5be399f0dea62850bdc0104759f7475654766b09b7788d3e1a090c59628ae2a3860647907a125270237defd9a5ba63674e0f2db561ceca2753a7a7223497823c368e6a813d56a250b379abd33cad922a6853c4021c13a420069b296f7793bfb46974a597baa87350d226ec6fc0c32130bc13519edc176fccbe844aa9aa9a3f31e2de4ab27d05a9701c30982ca75fe915fbe58bd1450ee11090e3fdbb6da76e2fef320bc0cef7cd807ba545ccae4b8bccdb79ddf4c0b30aa01e845250f16d2723358db03aaba996005e00ee290691f63ad61fb224198e56f410c348ff76841f3bc2b93c4454aaf080c4e4916fe9d734c952848135e1c63dcdfb26da0f8c4ad92ad2056df19184ba005d612e9ded7b8a67c6f857bca5e0aaf4947966b8f2591f40295cb429dbab62e07ff96cb9af45acc89b3b2f2f9c3a87de522b337c066f51897bebf4b9c2df5a60861ea24083d3997560705d03df070d9cabb381ff9828f94c3fc65af8a19e51104512b46c95855070e6a418b9348f1d78e76a9c290779c0327ad2c530a9813ce08b51dd2df8f341354ea419ea1fac81251a704bd29d347b79e12e33c8a4012040f74c28da721d51c73d200b7af8331e91d183710203d07d3326106895c85abb60cfb0f7a760044d58e2f7c4492894a9db17e659b303b15b57acd5c852b1e636a0e2665a972d2878f3d1999a8e64eb9236b9e08b39a5436bf69a86304e56ee0030cad6b4a9c82e8621fff95554c6ea8d6afb9b691a644d570c34c20d69b49511309f4a62245fc6204c41b8fb2f27f3227472ae1b5096bccbf981516719159ba810254cb039305ed4b83b8e97265203a049707a76f5d69b2f836e298f3f117f0290da44bc9a371bdea377d9274d50a5638fe2f77b0709b7bc9e22a02ada43f38bf06438828e6d4e0aedc22aff795df50934bdfb3235750fe8eadd9d4a542a0ead800a8b529269e00ab39d3b208884bdd3c1bb2d491a1eefda07e6886ff21f031b10d6a1cb099b670aacefc5bf51222b7b1643ecbdce466309653ddb712bc8a65fd0bdf09c79c0e125a2ee8cc038e9b185e0c9906fb76ac4188aeb760cc87ee1f500e1213d1af889a245231aa0adaa16865d2b372c8e90e39d6691859b9bf2e57c407c73c43f7b84856d6e26266916dc7c640ffc9fec6434b300b43871497f680600603bfead9c4d1959291851a4e8adf6d7ef6309b37e54a67a129cc14de00b39308b0bcc499ab843d969442cd1db6443bd0c5945c6d36c965af3125be4c4b93f704e2d7e8767dd7551249775e00b348af8badad1e67c95434ca871da77910e95f0c6cfe063b4a339e8bf0fda3b3a1a6a05391acd34f29e94589398d351c11ef6405f9403954b7a1dcd357b9114476ecaeba72b6f902856df1dbb07168161d64b70d68fda987397d4c11e3e4acb52e6b34d701da68eb7af0bc5dca60900c12354704ab2ce39f67e6a98338a6cd7ecce590e6d40f081403ec9a9889271bb4372a5e01b46c547bd3a667cd5e5c2f35d2aa517e73f7bf9eb55abea1efeace25b57b2a0cf700028c1237040867b6b60051a32e8729c0c4430478aa67ff8b6a93c627c40ea9d027fa2b30ee0e93b6f937e252955525c8091956bc31eb539b813cae5fbc04b93e4b8b045fc09ecf3fe79d1765c4d0160a1fffb36cb12e386d826e73807d004b3de97c96bd29829f5244bbe74f76118027ad699e2f66da9d318961e0a2490327f1d757fc9005ebc3008a4bec7946ef692ebbab986f7854fc2eb02773399106e21c6cd0af51a6da094df8b017fd943cc0c191df3b8dedbbafd0a7c3f74dbe0e4a538abaa4def3909ca7c6a5c93d37230237ab903e45eee6471c1e505fef8b0cf173108a6127e5017f75341f15d08947ea6b32ba5d91bed3861a83e6a7ed890c2ca1c4b1b48193b9b579e8ed409abd2b702d78d2ab03f5fb0c72758a28644e09f32a8099da4b6b05feb1bd7bf20720fbd5bb9a6dedeb822785dfca363f78ae0e53441b46d77d364118e5c3408f6a6675e1aef56bdb490f4dd95e91b7eccde5084bd5799f7904eebd47ea9f7500ef803a0ed0edce33921c8d64239c71115c61045b1507ab6b4c7efd8135ff7290f647a6fb6770dd44801386e542d6659ecfec0d301677a504c29389bea096f699ce3989174c4d576b1200737bf35187e6f0db0a0c16c7a6bc6b5ea500721d437e398b16bbc0818f28c47e90e2dd3d14a879ba0d14bf09dde41526f71019824eb410b74e43eb3a0e76677bc4fec5d20eedff200b91d506e90ed00adf535df746f22885715642bc425ad03894224160203d2bbb0ef70b23c6289161ad59419742f227294032a78ac7166ed7bd3fcf7faf7b2ed502074e4d17bad33bbfd31d8692238f43079d7d4fb5e92a2f74583ac0cf9be3df0e4c1c5ea6b5fb2fb41b6d0b2cfcb23fb0ccb316529ef6fb1feaa90025aa86b80069c1cc7a7a47dbd32d268f2afe7dc7135c9123a9a28ec8cb9db5b3fdfb2a820b7df382cc5b962c845ca92132d6e3effb5b7a78f12433a85e62693b2e81baa8078bf6df3ee9584ce4306668330bb7625b9f55e995640c839cff378855dc3e6605c376ba4201fe0c18777d2ff98c5f59f012d7471fdc94cb1f317e9b081e4b250eccced3c3e24f940d3c0e51f6fad44d9fbce3a3f41a8d44cea9c06a63a2c2ac03f24faf7af58de7d54f52c2db72d73a9f045aa940f8cf3e96718db99ead9ad40fc5ff99e00cc19fc20b0f4caae7f9f6b03c2ddd7c105d92157f094933c2d1b704a8a6cc52113a1b23b25f458097a0da568536995ef8e794a88ae3c88e49d92d08c5d0b2d4433ddc0b28e741c1da90876c81f77b4af7229ae53bd172433d45a501ad5c65ef8ec62c758a1044a8ef5d086ce9b4d7af97d69de2425ceea3c79939076ac2ae8cd9d2e178688fb1461bdfec2c4ded9b4d18509cd8d15a8eecfb8a730db1e6507ddd993c72f0e54a731fd6afa225e51c5c1483b4b0c6e9e51845cc1908b8ac8b8e4fa4f1bc62402c759b3c7b59cbd6d71baccbb1e883248f0db119640633994ace444814ab140804e9bde53c5a7d1279cf711f9c7eb3d47da09151e10d2addb78e055be6d7a1b303544a10a64ba02e2545eca5b6ff741d8bcc4db98b0de347f9a56997817eb627013a27c185ada17b4c027289263cc36af840f9adfe0d43b76ad46d668de9ec0ce7d4a1e33113786f935bc5c95e0d3d05c9f0e363b2055c416728b8e5439154becd4e8b3b4df2f418999fdefcab7ba80c3325a5c71003ddf1f3730eea84565b18cdce7fdaead6a99fc98bdfb182f90eb627b87ec28801f6c24b90d0d89ad5f90cf00da0ebe4bfd4840afc081c3aca0a661d93624e91023f5db6123e52eba574d76e0b1179f7e6f6c37cae330ab4dca30de6c6873ac402bdec1265399977d48cf0d3d47dbfe5ec96b0cd7c8b2fdca922390c653e49e70e73b23f64cdaeb13e7ead5e9b15d8122decea957f2aed9f71f7ae03d70c55640569c0f776e1f6bfcb4b27395157aa499b46b6121c570934ff0f2848cd1d1c2c0790ea267c661e816c465115e1a81d115d8bcbb950f7a375c530d7fb4a8c7b620c8bcfe4f4c63acd00fe30dece06f29c5371c536ac0caf91d6dc881e00d8b8f70cbcab1c3663e07803cea73f86ea461deab1c75b76248aea6152ee730a7d56fc0d0857a41e4c6c77cae72bc8b868202c7ca1dbfaf997294ca6313cdb6474688805ed1735c98048cc316fb16a78f1a51a39468f4c1ec850d8c1c30fdf1eff11a207271485b81d8959e3211efdc037220bd1de4000daf8c4982a6f1c53f7e4ce230ce35d08b8492ae14f2b3cbea4e34ef8daaeec3498c6d6a5f7de06ae79e6681f079d3a1767d5c7bb49724d349729669a91e3e8fabbe565c2d2f5808a658cb0a906fe52c1601e933c25864e76818fe7fd8ffb90c6d1ec9e94458fceb5db613ed00e9f770a283f1545bbb5de7374ce4a751c131cafb631e371245b7bf3003f6bae06fe0d685e00bb81ed7d66ad9d73afd5b7a05d7a0782b8164e211ca69af3d89e01fb52ac96b1f71372ae54db73244c24b8f68b33f03c150a032969e11fb5fda906eaef3dae2226bcd99a085d1cd509b51d08622edb5474ace3fbbc8faa88ca3e0c5e9263a188698f82635b82eb665a354329a3fdcddc591a8a6eb737ff944cdf0effd09e1922c744442037c7c07fb8bb92b97549f8dc2783c45aee4394c8ad4104cffed76cc280bf01847bab2579d92d57627a835e1dc2c52280fbca07f849500cc3f056a6fc89df39055578335737c013350f3650811ef998617d713bbc1c1107f5b4ab46fc11a4764d111762c17f18941f8b706fee54537f82c34efed627690f4e83ab5a6b17dc0471576b2e85894793e635b2ecd2c008beb6ce0e1b1a750d08a36b81e710a24ada5990d56900937db3e471adecb06f9c78b20d8c0848f18009ad7e0000d383b3214aded17407b2920e906fb0a2a762d423a8d961b1405f790b5c549cae9be9294d3456642c225f646f35848b9ab332422248b1512eedf4060a40bc57df6fbabe3a57dde3382296f5e5c45a62da753cf4a42d623fb67283d5087cec9a68bae7a9ffcd6a2af4cac2957a4d7d895a1f3e51a0ce24c6c035a75b01e1e51436943b6171811e43d91329718041b64b81bb0f4bcf49076a4b8f8cfd00e08800d7c3eb22cc46a6cf31172c20ff2a0085e7bdd508e2235d80e534c1d5067d6594bd937b6edfd0bd190baf6ab2a96679340c038ccd2f5194293a78e14d02aecbea3589f7a70296cece754f58d20d9fdd317d3b8b7455ae27e8c08df0e80afd423d75e311cb8364ab4404702b9f19d3be8c32cd61322309d929062871af0af6453c2a45dc99b3b723667358d64f205f23a4b9f60212f1464fafdf3a994e0f26efc55732992623186135bfb5ad53eb7b19c1c20ff80f1be94c0a68a2248108f16a1d9476e69b21d7b2e8e45237b4feea110347e266b5c12f904fcddd13810bc5799ee53c47cc9469fcc71d7c670c281dfdb37da2f3b590732fc8c1919697045d1a8f76003d5a7f1a0f519ed8a862cc4bf267a731151166089d74d1e033f00afece9ad7dccc774198a8dbafde6464f77498cd25f073dce5c6e302cb4cf23101590ff03ce9d837c1d853619f3c272e3f50868c7e4c7a756c251cd9c2a5d116071ca2012660b7498487d17fa2c79b98edf53b7fa77797271d76e057f050199909f343d5e9ffd52d98df35b722ae7a13c8b4f6c9c5e5371d0a988cfe7fa77a250cd7065407e6e7041668483bfc910af18c948543abeb6958928ab32ea024ab050fe0ac4f8e00b26e065dbd9bfad0f6bcaa43308f59b8e9ac87096073c5ddbdd90d14713af4b470054ee3bdd95cad78e22adb63f0bf7a4775ba69693ec23bbb7c05eb3dcce7e3ebdff42d0e828500bc6276a7ef75e61c992e7f573bc13004873907e7c620856a6d4d44aaf0e61520fbc2c59573cc01b7c5eb138d92b40da701980c1561351508a9a6f1a0289c2c2d547d63f294d01a4b4578dfea8b9649aa87b804998462bc5ab2d5313079f42f91ddb31f6eda7bcbbfffb024c04b25841b88780275fa3b145e089c079f41d6344fb73af2818316427e864438cf2b899b9a0c60062df1583e756a669d0dfa5f54f530ec2d6bb1777e4e90fe3c845794ff8c463b02cdf42992f50f6304df2bd9036fcb61b32abfd768033867ac46bfc08a90bd3f08c85b6dc30b63687948fcd4fe63391245ae8a83ff33d01a23c21d654f55d18a0256f2b28cc791159ed99f06869bd556621505805be8f151d00e6f0d89d970f50e +generate_ring_signature ff48702510ab57e5c8d1b6e81acafb78f7012e10e03ab15b0f1827ef34042dd0 82eddeb24599f7945a021098f99c7a1cb6edfeaa937e824e2f529708dc25ea77 1 c2e3e864568b78db05944261bb131881cd05c85c69033962d3c4f7e2a25a98f9 bcde8c2f9402b56df766a132e18cea4bd2d2c70cb537b599c2e829b7e3af4700 0 16083249d8eb17e3ec2e7e0402bcb40fef1063cc8803aaf787f0d93b86e2c50d4e5c106acf41a95a8e577c4d5072c253783e86cc6a33c85c02b1c2a77f2bf80e +generate_ring_signature 417b4e63adf44a5a461ff2ff030a1757fd342e7f93ebd920c25b4c8e6d740187 bf738513972b08c9078a1b21cd261df99f52670326ec59dc94279e626c0ce9b2 2 f204e5533b350d6232e62308092afee62c4ec0f4fce45938a2bc17ec3bcea3a6 50ccf363fd401389de4f584b3597c3893faa78316cb8799ec6c20a37596677c4 a1bffbc16adc7bbed80ece0ae2b4978a0b3325257a96a7e3c3c097584d096e00 1 4a55d011d013948e7923b11d22f762459970cd62fd289ab3edc1f631a546da0675c7f877d8fde2341b3374c9947aac2bbf72a2b6dd59668ee1995b5190973d0583d9e293651ad7e95861357cd9da16fb57d95114d943b16882eb1a699c905906fef023a873548b92e025c25ce2792a7c7809d4ad6176fef7699c6893fd23e407 +generate_ring_signature 030be7e561c24a2c9a75cf63dfe5bbb49addd7023362f7688d24ad9369967bea 158ff2e128941383275c97ac9c0206450dd2f16dbad1a0f30b045cbdbb76c2c9 5 205a0dc801db4e3d217a9a9e91bad16ab78ef983f799b8364ff9ab44add8ad6c 0a6f06fed33891ad9f778c3689968dfb1283af71b48c1690dc941ab115ef4d69 a19641d3c2804dd2450d313d1ab0ea95b16c4cc1cbdfebec643ba05604625dbe 93bbc7d65e865f094d1f7e7cb5b07f734016648b7d3e104db00b0d8899d19e8f 68e6e3257e7e974b4ceb1f7c4461950e60c1e5d1d8e935e02f4116bf89f5d842 0e0e85834add085696b849ea3ac806740cbbf7e2dba4002934fe022efe25f60b 1 56ebea714cfd75acf7d27038a622f8b8f319ec60bb44cdbc0a4e8e0e3b47560948a8d906f379380f1d4399c306bb0abf6473e368250307243c3fb62d6fbba50b1ac7230b005602fb7b6162023683bee640735bfba21da29b0e6f016fa60b4602c3e85d17c7f3726c9724f22720280668eeac8983c84c10a09cc8b5630b735d0df316c2981e3936b5518d4956ee8a460e33dcb4c40578a054ce0cf2c32a708c07edf12e999a005030e675a4a0d40760bea4f0dcc7e2cd65eaf582df22f521c50fda5e9236cd8f7d671ebb5edba063b5c6332e2284123c4ecf67760357be1af1079fb440483d44351b98c6ea0b3b72f44ad7618b252051e18ec27453e2994c4a05c9bcbc498113f6356c434f9f16a4f53c19993cfaa0a66bc2f2289abbe015500d1fdd04c048fb3c8400999d88919d369029cc97718a674f18741d9adfd1255002 +generate_ring_signature 676d9d3f03cde540717f27be188a1f3f089b9de4264a66906be09441f3910378 1b768edfb4e27ae223a513c913ca9122e2da6bd2f88efa1718149068e6a000b3 1 fdb9b839c1c33c111ee96c1fba14a6ba9aa851737e89a629ab9be2c215c1bc5a f8eec233f256d39bf9d6b86bc1858e47748c5686abed539c8c44457cada7b202 0 4c0ebd64b0d7d2d200b9458a34cb1d2b881025952a9ce79c6a3bc774ea1df10662726540a8adbb99aae71c5cb60fe28c62560fe135f37959785358032d5bf908 +generate_ring_signature 6b1284d1a3858c8b7932de78cb05afbd1d97616929e31905ba975dba70d7507a 4ace77c3426f132a65348c8f2abc450307cfbb5aab6b83748cdd9da470b37162 32 8e02737d48fdf2acb36863a26c00930d9d7022156fea101760d6f178ce30e0a1 7dd3e2d772fb4626db9ceea8dd6e455d147d86a4aacfe0f8dccba90937dbc2d0 413747d1db30c5a9e8723aca5d8e2b105c8be221c1bb4337222689f184c4a6de 297bb55ca843b5b0b291ec07dc6af5746d7348920fb57138bc2a6ae208239223 eebe4b70a7669dfd49a6996775053955a4f03e98b74f1ac029c1d3ce1579fceb 62d36715fafc49f61c615704f85ef67bf6c82c876abeb029e875c3847e9e8d21 c003d25e8b139b9a40b1e169a8006e335b7cae4a3736026a4ce0ae55f1d1154c f89a5190779476851312b1297ff0d8bdb0d6032edcbae23b48f9a8241fb7b54a 22a64918ea6e8d63399c1837210716fea97d6022c3657c869d7c9255cae853eb beb2dbcc8a4ebb25afade190a4b396df94791d873e34bf4fdd04f0a5a5f86753 51779058b46699ed76f017f551b53beb6259dce7238fcb23f62553638c0a0721 077f6bc7e6eeaf2cb3beb60ac00eca6412980fa9eddd932b9a408edca4981ec5 82da8fbbdd764bd252885dc704945be6465fc45cc30dbe3eb6fff9692ed05210 1df2acf66b87bdcec1b2d8e454e73fce0e6edf521d9c2ce5d8a0a5d8e7c4bfc4 c4107473cd90199469995334065883df47143ef21704bad6fef7db88a11e4799 616adf3cdbe84f04cf90b894eaf7a3e420d8606b3f5638feb3dc57684b63f606 180972d031b5a05c43c1822aa2f391de533069c98bcda58962e8f124a5816f79 e7fadf78edcf92bba764a30e00c626eecda4fe7b732e588f1fa668dfffae6425 369a2989333a13a52af60cc2400536292333a78735b5e2cf12ae1405d8e29c70 0036cac6d8ce1a2a5e623db6f9dd8eaa231184c85c1b7661e4a391288d82e7c5 dfdb8d0684014a38ddc314d51c948bb1fa93d2f491a0cb71c0119e7c3c677023 dae655dc8a1f360aae2d2f97cccfc95244703e91841372ad4e19ff62bf7ef77e 79d75438920510587b7e8935b56e1182a6b1736ec651a624385215d8d461820f bc7705ff99d0becd021efeb88f032a9f1a8afb6e4215da04aae62d4ccadf4b2a aa92d90286a2e97e8deb50bd1f88b0c17af828c037f5d6ca756461ce5aa50947 8a93227c8c929fe5668877d141cbd701b9221505a0af068d7de66651c3633b1d d8c07205cd999930a681e3df4c93d0f0306d2f7af98f54b7b0f9cc6c856164f6 71027190c84d4ecabdf9c6e5e4e441532b31da01076940d9ec6f8212674954c5 16fa8ffdb9437d1ea18c12820a0bdedc301adfbd3c525408784a5af4fc6334d2 dcf6a3df67483bc91e2cfcfdffbd967f1c50724d15754c08f46cb3afdd16775b 6982f0182fb32a36fe007faff4f28c411a686f97a40b44c4c825e865f9487400 2b4cc6cd754512d8987ebd79a820b681787aed6cb7bbd7cb5ef792ccf181b228 0b9d7dfac5f2c2203dccee3bf001cda08ef2b12f8cb201e2883df36f61970405 14 93830f08ae9942cba1f36cea473ca8265e87e3bd34de605e8344b6f92bcf970746ee8b5dd837f1ee0eacfc99f9811fe8ec8a2d7fb77852051148bf711dc6020c101d7ac16d28afa399868679d227eda9c93e5227f12309b17fd37e399ea743021b7ab1b6d2ee4f7fd4ad3af7dd2725fa6f4320c1464f428ee30abfbd8ec75c00ae16760df49b4d71f966be497734cde62bb7fe5bbba8507986b10bbc05a74304fdfc3e522287f38806308a06d86203aa211db6c1fd5696ff87ed7c3b759e86059eec15dbf66326e00a5aba1d140d17dd3a1f97e2dcaa5036d26c977d68aecb08d35b6aa339bc09d9e46625d1e7047649c3170a557b7751ce32b77ee74ea0d4050f1189a1de30dcbc65530960ba70d46c16e9ff73277786d8d2945dd193808b0fff56c591cb9f6462a6419318037aaa0bc356890f1f4042f7a1743bed497db100755dd5a649430e5799f055baf7eaff72019ebb3eb10d955c56fc6324a8278105b6a0ced3c827ff6bdac8693bb5d51926075053e957f5167850b7af7105f0a80fa69e67bb13f411d66f3f0ad07ddde933db701a1990f75b1fb5fbf1f93e08e606d369c896b30d39166544ae7e19c5b0a958de00cc2f403d7d4a722d2813f60a083dbed9cf6433c5338d10bde8d56699f89e4b75e255872e0b852de4a0d758ab0846301f7f3ef92152c9dfecaaab1e5b253ba9ce3beea6a333cedf9d6afbce19030ae3377565ea9293ad5885a62fcc86bd9ad24130f7cc2a21627f701b64d4fb0dbbc9a1917a2bdd7e386df85d054ea4b9fe82a71e52b7e9526b9c75a4f51e80070ebd5b8e999d6f1b11221f60971d1e8793d15fe9ab02823393a413018e36350fd4664808044c50c0c0bdfc87137bdd6b6afd6fe5d6527bd6308d31aec39a1409b7327171cf05654b9d80ece30e546d605e8a5092f1bcf7a6875ff29ed7f71a010a0032562bbcedc9a42626e3310a2faaeeef9d63f2d533858182e9d55ca3650726a767b8996965c873d09043b4fd2a26023981b8fc05a91ee91ca9bb790d6907415e9abffaa10eece461b2e4bc806ef718e6584f81053d4633cb53acfa151206af950a27a616b979b4dd67726c6992eff5a6b3b22ab7e14f6650f38d8618f5008e4c07207ed936ed87679fee574a64492e938dfd738813ef4ce02c01b0ea77087587bd2fe291dd0adc371abb2adeacd97de12856fdf3e4033a12bcae71388c0341b82dd9544ba729bea1c0f3e9908536c00ca6e08babbe1a82330eeeafa8d1060e1f11ea98f0522ba9957dc64bfc729803c94bfbcc387826f22d07886b9f430ae8c483f4128c3c395fb42edf8b895957a0cdbeaa2ddcefa4a091f3269772360639b4ff7bc87a3a459e1ec7367f31ade3b6e7cc9f3dfe8405a8758d2e631e9202a33e79ae93762cdbe2458636ffe68c17633d3b49192d062f26daa713e179d90a4eae783c5ad5268d734d65278b26653d564eeeb580ea2123c1789b0752e57d07a3a71d2ef9b0ca3a29c962537b086ae41936be90768a1398aa4c7732cd15e208536fc831c214d9863f224f4c4e46badae6766ec704bf54e4aef06a720900ab045c0628a1d3dfef4d6a60e442a1db1dbaadaf0440b7833d670a515df088949309ca6e9b7f92b8f7bd0af0e2ddcd682ea421c5cf7f93df7fcb750a8747a3ee0c09f46ec265095cb46305364d9357a2d3b1bb10993520b9c54b78649f6e65c8d90c5e700cb96ec53b09cd057cd4265be224025d4a5bde024144e0f47ee09e2af7079d6445e4a156ef9819ec938dde87990854fb2d66c7bbbe7c32f8ec316d0a6d0b945b43608a0bed2b8f792801f40b24b9126df545aab60b1c0b7cf63ed885ec0743995ff7bdb55a930d8896352084cef8b3b94313db1bbe966de158464ffe9905bc08f9b7bd261f437bd476ea4d4672847de617d7c1910f525562b1b17f13360496144ee3e8c93bce388cb9e823b98840994692ed5d249e5533a53a581888f20813f98c7bc7ebd3d35e9b481eea89106ed53e1c0957f6a6598ba7f1efc6917c092647d11360121667ea91f0839749ab84f346a7f35c3cfc06abaf7186ddf5fd0a3b75cd676d0dcd6f2f56a1ca7a495b625b72307443dd26c065eb41468e703a07aad60f535e2e7f060ad8a101788fa3a9d0c1fd19d3472cae3a7e50013354d407ec00b9168e6dd72a87ec7c241e8d8b4a87b3c5d5630a684eb5e2c6fcd928bc01f0c195550db9795091c85bed3c8d12aaad12d3477a9b157afab9be4fae8d40033f55dd084cc234609d3cf469aeeece5d1eec7cced0c4f27944b2d58a8b9cde0135925319d6ebcb54325a34def61354e8c17b03e1c28f7ad2f3fb4a83c0f7dc034fd27c1125cfa56c1c9e334750c2162221e2db0840512dcb4e089b768ae2fe060993029aede6a16eac47326a5c1daa83f3578b58e52fc36ffe0d6034c6124b0bb59fdad3bf63b3f731d0a17344e9a3a9301b983639e8626971dfb2700522e404454ef5e0a40a579fed42c423bcbdf43c08ecb4ddf0bb647986640eb7f6e57e0dd2a02b03521983621cce0be340bcdeb03db94adc99e9985534276f4379fd04026260bed58930f997a461f24c131d5e689c4ed4213e28af4c28afab4e0f672905470b7e5d4201ff7c393fb3df17d16a6a744abb39e334522f283d401869fd8504dc00937235c5ced65fc1722a3ee8e6518ea38ed597ca8507eefe6a420a5fd408657fef85d221e008b156af68d2070e40c8a447afa34c90edd9daf5f9b032490e1aa549cb38764022680fde63bb08f49c7ccf42513349ad93141543eb8723c4057492079215faa1e457e41cc85d004fdb4b749dbfba20aa639277ec5ef44c360f98793539d94f2efff4ff9379d0d53fc891fda3df5a15aeb1265c77c916e60705 +generate_ring_signature 2877c2572723b6c1de6b392c1fd7e6b9b06be04a33b2c87ee27559a4f440d301 6be1605f102b685abebe480e495a6ee11b401fc4f8ed2c7a9d59372677c51133 1 43f61d5fa46d25cff1552dbd032d2072537865b23f7631b16355d6e04f57406c 5768afeb110865a5c863b330dde198fee80d775dbd33ce56e639cc750825e60c 0 50ea7774a66bc24e5a10c9c343f543a0e44b881300472bfec54e78df078b73053693d9fe590bc17a8435820fe0eb46978d86b5b510ec558821b9803c0a2d2a0f +generate_ring_signature e85672e6b328687d087e5e27a222d908708082526eab8d9d1ed9c741309ae642 1f47514331ac0da99d0bb8bd185aa97b127a5c428ead41a49a1df9795df80a21 9 5d81cfee1bb4c5d9f12691a0a7f099897a6d2b5db92a5ad6e4f16ddf67ed1546 b352738407c3d1b642ec14ce4e87783c3461995d4a759f213a302d2f6644be10 2561702e1179fe38a61701da52b2c6470b7ae222b7be59aac2a4850a00a0517a b8e838d471c530f3c0eb2b6ef7a5e91cba4fe4ae976f5b9dd34d388678ac2c7d 00e859925f2b79171a96df93368feca24d15d9160aa005d86343f69b2147319f 59a3b6c9ca5cbca2b1b27ee13a158565ecff5267bfe407da2bf94c863afd94ed 51eb2c685edfba3a962e435aae95b54f866eb1429ddc3ffc79573c076cf4a638 bccd0d7379c0efd79aa6f27515826d350b8cbbb6713802a834a1f34f49a09fb9 5b7b1cc1529d4eebc5fec0b0d478591c0bb0bdae91eee28219841262036a8a60 4442e0c6b2c4e6cf3f5a1a33cfd304e8fd6c0c1cd8047061a19d83525b50b30a 2 bc7e5b7e533f53512c6269a99f0a01cf95eb0276eb6f2b962fc8bcae02b38f04b23b890dc9e0cfaf7e47d39dd6ada779f5fe59230957b6020b755fbe3efbad0ee1a9cb4f583bf144619ba1de7b8f6f02b83ec26f00847454a5e73660cdfbf2048b5dea88a03869d90bd2596cffb17a074871e553e0e67078fb21636e0e13e901bea1895f03b55187de499c69cefd898bba90d20d20858df84fb797a63d39e20b17da532aa921cb15b417274edf5b8d633648fa8970b795067a17a372915d6401d0babf744ab79d3dbf1475934fa02ded36b7b615f924d90388bedc13a8ebb201076da73121f10a3f12e13b41284a95469335592463f6712ec909f1a568a1fd045b2a46664fd42a8686cc65b674395e3c6104f8f072d6f08fbdec560cc0ccad0c27a6826bc5546059c982abd75c4764d1c5fa7d90a8ece40521564dd07f257e02554a8ec68376fd1646056b2887359c1001b621f0235fdcebcd58932f069a12012bacd07c0aa0b78da0fa952b9551e5e5223e542780dda3885a527d82a46399075ef0697fb6087b8b0530de6e85b87c430080ee788d965932028620aa95a7100392978c3880ae3412c57fd6bfc7f21821becfc968b4274398d4c08b95b1f9c909d3e63647833eaac1bdb43ab9598716aed4622477718aea434e56589038f7f20e4e65db948a69e60eb24ca706a932ab39aedec10ce00d7652c23cc7578f41d200c9082fec6d13f3d74b88cad2866cdcb8ceaf29d124516923bdd7ca930c2b110799a8601a0c066760d721bff206f60d317a9c4aba466021ab2a213c4e70a5f80b +generate_ring_signature c960ac5d7f59051cc139e56674bcc5a3f0fd10f6d4525685133ad71da9505d03 d110909f0a37135c260f7198ab302d84f9980cb0f9fcc863b9865e0fd76e88ec 1 5cf0e409f6ce507bb1d619490f4501603aa0b5b11c2040681f5691c5e7af95b2 1f795ee966c8a672d15337e590b1d327632928970274de649f6d9a6d71cf8906 0 3958e3eb485a86a0a14ea4f6b3939dad078484c516eadbbd49bd0c8c78865e0da096ceec6bbd827ca6adce49bc6b6d9a2cc34acf37ad95e233fa7efffe69270e +generate_ring_signature 00480a8cafb58dd4fac3d4e0b78615ed33fcea74c26ad9c23d6f610dd131879f 2b7fbd562eacf805c3bf9aad99e90ecbd22a521dddc5030c2777dc9f139219d8 2 66f670b720ad778de82b255292fce0291b5729b4dca211c9f0def3ecd0f8c143 58a740373134543502818f2326766e0188b935de010814e3e61fa44a2d1944bd 118bae54eddaa218b8e7b8c9079fa5e42666d38b08677a64606708e0d6574206 1 e7d27f0ddcc67edefb6f34b35a3543bbc04bf03c525536eae7afc7e231a84e02386a1e2c5905a97f5f76671cc23bb6e6045f757998c424b6a1ce77ba0f04ec0343d8060c52fc351b1534cadb6f807502778a05e6ffb5e54d2c664457d3eef60c9cf336864925074c2ba3f34ad84cf4c764ec05b7f2b0bea34768db9a9e32f10a +generate_ring_signature f92442a7a535e39ea68305835767d33b4a1527539ad2a184188fa473673e583b 9f256d40277f781e035f26613b45660acd3f41f24a8179b60a56999115a83d77 172 fd881da6976a55847f9590a313352a1a24a7c5b3c8c568bc37b920abf088ebb1 ce48a50c2e6ce8edf3a295368278eec1c9b73b56435783886ebada20591770af c1533314426eb66f59ad0f7469d65e8019f902b053502e03b0dac849b7262414 284bae0be6d2bd1ecdfb9ad7c6857ee9a9ff6ed1cf50233e87a997ee2bfdf909 060002eb3f3b22f173e4ba9a50b9140c3cd5c7f7c3c307369d3c87466ba9ed8d d7d32b301bf7bb28ead0c666282fd23a0cf445219423997f8dd30afdebaae9b1 56367289441de9f8938588385f9a3a9f4f9a63f871cd3b72c471702b8712cc2f ea5c570305cbb52ba6d889d8b7a340e9335972d520ae71c9c13832e491567464 071eac248b47a2c4653eaee65e55030239c5a4477254f12b2edf3b0be8367ac6 3f3b3221a7fe3ed062a4d5af91c3246cc7d2bc30e9d3f85947970944058d6be4 bf078413d79661eda1d8774f7003a5816a93632a8cfba1f3730d8a127e28a9c4 e889d95ae3eeee41f3debf69be540254c8e68347e8b2d19d96b7759dfc14e377 f5dc25d2ce32defa29030708ae1d6d36673f8b41146cf3d89c7aa2f0f2b6e313 5205a7793f0a4b0d6e1e9257dcad29614c9d0f886fdb16ef4dfb4fc36af632f1 cc33629b3226d7404851fef79927fbb90c1df81cd95b7703e38ffa526ddb206c a37b372b2c312ab90f771dff4b2053d95ef3099c76a6fba984bf916b29b56341 f4044c8f9a9801a5a04a157b7c9aafe40c019207ee66d29fbd3a356bf710fe84 dee92a17e7bf79f7ba3d6b6d01b213bdada853621087e1ae1247b115a98768ef 0d696f6a9682a9f2d4c0e582925281368f16efb8c3cdb700154db78114377dd8 57728b15184b062d286f942fd3a163ba68cfca54ae3304e739ad3076e1cffce3 82ab1f9afa7f7f77289c00080b1f98a487a14a2f073cf36bf96a30440f20ca52 139c5e0efbbf51c5af2b9117b7fa58d6412d46d67eab6997857701230a94825e 4e17a9d3cbfff868b70ba95e4243a2da2df968ae5b0b67fcde527eec0c084244 923577965437137b6a933bd61505ccfffd228aae996d25fc96ae9db5b98d07fb d841ba1679e8ace379aada4547333b839b808c514f6d19e38895ab48b1a9d16a 8175b06c4a1b58b90b367aec2e81dd9c41db930a96b3e08cf06ef9162a21415e 818abf49a345f93c1275d55321fa70cb50f458e9e67fe911aca8e9a4a253a34a 2f521138d0edd239f6e54d5e4d94efdd9749f6b520fea327e642a0fbee8a5c04 9f46910d6268a0dce884a538bec4a81c3bd550b739bf5d02035174d1b6707a17 64656d4ab3a6f1c92cd71ddf45659176f2f37789d0338dcf124b1e7ad1030f71 f8c3b190e7a9091781da8ace4b6019b2d68f05dc92e54960a1a8571702b9c77d 9ae039b7b615745cb4e51634a5b8a10484d73b81a9baf555e11efeebdb5fa24a 75157319ba0ed1b0208d3764bcfe60cddfac56aa2330c76439923d245bd7d81d f997a99abab99f25b18d72b7d5b73d4dbc1902dc3e1e01d1fd0d12b633772533 aad3267d5679ef6eae0d094ae5df02b5228d3257d9a1edc0af7aaeabdb9051b6 1eb4d7c23a4c40827eefad193fa0c778f1f84a07210edc51b42d3150048f90bf 70e8bc3d0136207ee441333ab2f463ce6a456198aa7d7acf7d1c966f89371bdd a6041cc33222e72a94710efa35235937f843d4372ac73668217849e4f908f4d0 265d61d8b2272325b2b69dae4f728d3fbb3073da4c4006d49867abd4c1575806 502d8c2e6f00025493227c87f12a1319199c3283503748b32b23af0bd20eedc6 41d762110cf7279095cd2116f10ec88f99520c860d3ced6ef72ae99c53468ec3 1270155b3fa3602160171da175a36e4ac52adf90a7f52ae84d8be8471863f681 f4bfee7e8374801d097ba1199f24c2750bee92f29f5f84174200dc8f25234023 ab8ece6cf4ff2b2bf545f8c57791685361182df280ff1bbd925e8fd3c16dc329 04f1c90fc0b45e41ed9cc34a012d623d0a71e726eb61a157f7e5fdd331cfea20 ee65cd19e5b17a0dca4706ebfaae7474929503051fb26bc70c7f78f986311e2e af5af1a0079b7b62f0b2eb03964ca314a21e0be6685c1c6e6dde44bd4346b943 96b9d0ba83bcd6f976a964068dafb5329d349380910d3eb67e550fbdc46ab884 1956cd083ace90b869f0fc7041362b47a5317164ff30d5d4597f205d53a71474 402f7334d4db7dba7b1ca8572cc893223cdd7fa520459080f70cefe98a093635 ba1053f093a6d06659433238b107558e26a28d2db942a84d9747fd05839f5056 89b8acb7bba7b8cfdb045e158837a4beb36c65fd064fdfb2715ac78a95dd76c7 7d16961a37a25cfd9020b44566facccb9ee31c8663c3917ad7ba0cfdee07ceef a731d84951d200dc2dd94d18c77712c558bc3704acda6085d6bb46d0021dc7b6 a14c510bab57377909416af4573bd3b8a551d2d35421a706758408880bc4871f 59f8144bd5690d28f29907c8a958a1a70f8bd305a36162e310f04f2413ac55c8 0d56e71a5e55aa4fb86756dad3e4edf87f3a01a81987d1e13f86099dfc3b9494 5510c0c357755864b4485fa43bf7dba01d33052918604ec41533610130dbdc35 9fb86f44b481cd504258ac3975fb5a8534673fd77765f5ed90cd310cdcb4006c 3298a93187801ec62be93c5aa5900916e6ef57a4e19331597b82dfb9c00b2d9c 55b2800d41d2641fd75a214efe80a565fd5f27410783232f2a44f7a774ef9f2d d6e2629ebc2413e4f294af37b2fd948a7d1d71728fb59794fce78ab173f32a5a 23617f3efb68af4f70ba8173f61b95356389c4cf788e3b8f72cadc0d681975ff b06347741f5fdb84b017a177fd904913a409c46e97cc00440ed449900e9ec2f7 e88ad1d059d2d9aed7150005189836ce56dec709b8a22f63ed2304ad6c42c87a 2fcb144f29caa8d4e19a07f977ae6917e8fa0c830c52b0d4748ebba4801edca9 a432e7e9cfa465440d9a0b1df528d974cc32d4c7f25ceb53440e5995e9b8feae 0b0428e6f8ed8c90dc54832b15a20fcbfc82cb5f908f36045b1dcf6b69cfbfca f4064a72fdc46314d3652c0bdfb6f08f1b248d5c747998fe412cb86e97c6d83f 45cba132b9b9a0ea8525b70a158d531e0f4bab123078906e1257558b9904a24e 9b41948b3d7e5d4636bb670ce3b66d16a939f34320f0317ce20ede8a9651b700 bbccf33c2d44e1e59f62fa8144edb353961bd522a1e380f95ed006172c88af0b c04093b6c7bcd3446060f9c18cb62503acd1b1d4d5c4e7818292065bb29bdb88 5cb1f7658f73d542bfe7b10a988f45db4bb9d777ed6b0f780049ae54e82b6ca5 3a8cdcff1cd09bf1ba1952514ffdb00b204322613221f6c6efb969a36c164adb 03f8c02d0dc951aac9f5b70c1c044c06c9c98b0f61c5b30d6045f9f1a12c1fe0 0e7c767d8a26d57dd35d5aea58aa9d3a6098dd8ef2732c66bdf0e183ba23f6b0 1d6d4190d0b0f4b8ce1c53f1ab48c601ac7f4c487834f2ed355255a62813e11f f609212468d6b96a6ed41dc61708c2521aa924711029801e8e994095bb5361da 87f496fc9296d7e4a2b3757e555083f89192935073915fc41bc8f4bf447bdecd 1741f6e096f8cf208f002cde14274303ddcb25c2533b9dd10f0728e41f28e501 b091eafa29e0509f605d0671e4c207a74acd926ca791824d0e8751f58124bfa3 8fef9d73d54f5984806448be3a3b469b1b9a50ddb6c7a69a53e404ef3940e32a 5da7b39dfc6181a2cf1ee4f9f2e695b5bed73909dfc32f575eb815f53c8c0484 5e95b7c9f65a53d07781d57093ab9cadc813bb153e669de752f5c97e05571507 505ed9f5b5ae645ef41900a40d7157b332290bdeae3d19f866af304989d5d8b1 1f8959af3cf6788fa599a3a00d84c323bcf29dee02bc65171681fe42c76d4b5c 443b4dbe3217e35f436a76531ee08d19024edc0453c2d341991a8390fddb1568 7f3f7aaa9da801b08f6cf47eb23b3cc7d098c5d21bef44ab449ac00fe6a19299 6ab9c1bcc391acb14e701e26b32b7a6f7fb09da69d51b289469f2a977bde80d4 8efffda82d82d52bb1cefad9ed90fd82956db431019d040f6100ac161eb7779d 59cf1ebb7bebd9e07338a515fa9882239bcc77f6e8709f4765b463388a7f99a8 efd4bb0ff013d411e7a7d220f792ec5ca72933777cf416c5d7f2a2945071beed d1daec9942d6cfe1c2a082609eefc2c9e831a0c07dd21570390e2cca7f2dff50 bd3adce1a245373d0073f2430729aa57954748d90e3718399028fdbdf68b05c3 b93a50fe5a835ce86b56209a1057babf323e6dd32fee9433db6ed3695de7d9ab 3a1f69a2825eb6d2c90b438e9d7fcb3fe8c1e38983aadb0126aefa31bcf6c645 ad8be22685e2be87180baf881ab3dc90cc636da658175b732adfdd968e6e0246 9d57a848b3079857b0bd7c7f961e61f3d6e3d52c2194e3c3bff28dd1bd5080db 1c1d0bcc04c7ce4cc76effd19c8469638abc1e044dc2a79c7eaa0613528c7c67 f562f27b6b50c3cad5d14e7c4f12ecae046dc008d5dc888a89d796aee7d92272 e292217b111114bcfb21cc886b628e57eafb81a6f15eb72478b3a58c9fae5ed7 0398e72c9373ab5a0e21048f4fa031532ba8fa7072d08fc12fdb9cadaf0f160a 77c364f1d84650d7cb383dbc06e3c4570dcc2a343ed4f0cac0bfd76e1a0d250a 067c1fd7d8f49457bfe82088af2622f1d164681e70865f2b317e8a39b5b1d5fb 32a06673ae1fafda5af9e2a4400b0b29397a71e148ab0a10588d97cd408ce759 5a9d9c4d860c661e86742c4b8a2f9f641a50abd42b85a702f0f9078e06189fa2 939d92a6c0bab1d47d8eca4c7a2637498e41d517bfe0af1578ca6ac2d43fac67 b95cee77da3467db2e20ef20a9b88a31f1160cd4c96b6f08cdd41f719471086f 36ec08a5ba086104f1e20aa1bee9d911e499d0a83ee3273a9afad03c64d86885 d322470a709b5aa95a584918ef8e80351984e58799fe061c8112dbb8ed166e00 3bf94b5d1bc3af26948c9e95f0efe70707b7567f6c868a26fe0b3736f4eb84c1 0dacec7f9473b709d9d08eb0ebc09f8d14153596afc5f2151e21ad5f4ffc552d 91f9062ae066dc0cdb72a9caa0dfa82230fa2db6df73e69d4ce042a8c060d813 689f47516ae100226f511b2491ce607d33565d036c270dd879f725fac4f85ae1 38a3a226fb70015ede495dcd52d5317c8f837ccf80ea444e0872742b959617d8 2698e10a18971e5533259238128acaae4db48bddde16b3671e0ca608ead5705d 41e5a86e6e2986ee7803d5302b70e50086b379232a81b8985de0c6d8072ba128 9904888e211357fc304f14a141953565774a8681ce718cd669ff3d0cf1b796d3 6f7470a432f921806f7704af9e2ae3db09e79a98691f5fbb355ee869c824a9a2 71ed2c4844a82c9bb02a0ed2ceaa1bfe5011364c90ee2bb86bf2eb9ea4656198 2872fb459f19143c897500e78f4e03ed59836d14c8a99abfe1c45c25fd9dc225 afc7929206da56bfecb5fcbd92f504b8840ba109f2bed578179316f2840b7493 740e6ac8f581a0d48d1c890ae1efa021348711b7668c2bf44ce4df9de3900d8e ab637889c7cf30038e81325a13de81d28096719222b2eab649ab4dc46e306abb dcbf3053b800c54b354f4ab29aa1470d2cb41f516deddfe7dcf37a32c6baa4b5 43f4f3389d1301a51d22acee3a2bc19d8ca3b4051279ffd1cdc43a81ef0f3120 d53a2897da965ed3ec8fe3a64c84e94148f5a44e26aa618f2d7d6ef6e1fd5f45 eb36446a8f29a00e560e3539910c595e84159b0097ca45e1251e211efd4457a6 fcfc38062f786c990627e08f21824cb2d7aaec22f7b375e5f9dd32d82fb9ce7e 8b639553c2a999201727a1b7402b65f75e048993ba308690ad9ba2b65361f507 e71aaa0bbc4e864ae50dc86b9ebb8644320d91352025fa0eb0f60d0a3d054334 3e0aaf77018f0588e9bbf0adb974a83cc2fa77f42cb4209c24766282cff72286 52d0a11678b725c2199ffbda6814f92e9033c2eb5c5ec249d4fd4fe94e23a726 8f8c15d5ed07695a7d4e815cdcf4dd3dda0926d0d752468948ed919e4729ccf0 aaedeb70ef549d4196dca9e3fbb7ae4bfb81e2908969840c384d2afd34af9f1d c4033ba752ae96463c8c6d0d2b84ff52be33f3215de8f78e89d817ea24f3dc76 f1207b72213b423c405c200a7a5fd7f8023e1f239c8e606ddf71031525f23b37 baf147ae7bdea07b53a5f5e75ba469179543dd0ca592095ff616ed04ef9beee6 2cce4a9d993261d22aacc8b5846160c0d1c4fbadca7a70479fcdeb550c959c83 c43edda5a8413902774b1f8b09b27182bec45f69e5889e202060dfceae6e9ce5 22832c1ec22d2ab3b19093ac102a7aa2b8b0bd38952b9e35e44c223de1269a0c ccaeb8254c1836cfe80e63c41f1b0b12cba744f6252a115ce428368eaa19f561 aa56531344d04ac78cde18fe6182151d31569d6989ee9d5dea5292b21da8a3d9 543c8af32bfbd127e6719470804887617c42fad95fcfcb653d49009ec615b5c2 9c54714b1fd93b07226cb356e7e29e1fe9c093a22f3832f3498b6fbac03f50af 0a1d9f709bac257082747850c6adca588a7497f5853cdf90843a4deefd0ebb61 1accb6cb2ad322986802e1cf695a77856dea76a0aca440e6f7ddf7c6995bf1d9 5a077b219652fe5072cd730e904db6069475fa9808c9cba94668189922e3fe14 90a84ec912c8cf108a484d9305d0435f6f8aeaf48bcc4e11f86f5bcfa27f1f94 0600ebf5b2f516607f12411699f6dd8c8817c88cb9f3382d854d4f943ad23f29 2559aba16f4afe15749840263fda8974a76f6ae4e5643e3f6b797a3c62cf58ca 7ab8110bfecb7a962ae0c9c503a44ca616d3fe93adbebb1daf376ea312adbf6d f43d50e52ee7398b0fa244e144ee76d30d39a41e7199424950d4f00e9796f9ec 78cf72929a258d65087e8568e2088a6ceb6cb807a9ed07f5af1af426a59c5eb7 1d840f3efef11524a202b6b4c55d15f152ebec1fbf543292464bb3de84a3c0ac 244cef52f6ecc47defa48791392fa2300201d8b10310aff5450038c14991948b 74779637e05d6c6634b4639a77837b33a5931db6fd4669514df6fa3a95db181e e2f711df4622b4ede67c2a90f1b54e90e8cd0a9e9233c30ca82ebab46c68d97f 935c0b5866b20fd6094efea23ec5a44d9f38dfc5f9e13aa13681f6c944903946 d7c11734281c2918cd59b872819af1fe6808b67aea22aebcbf9dae2289eeab50 b8496e518ba54a9047c61e1c88255305f43ddbb46ee1952e5261728f6f233950 a12f64dd6adcefacf9a68dda0307f97699f45069750fd2842dcf49d30d9ed03a 8f98e2e04a873d27b24032446f3802d96921a3d364c825e6b918f4e8f3e8ab85 03b646a54e208cd8e396a18b43b96fc1e742843437aa917e6cac0d706b0782d6 30322a0e721a026ef6ff39158e4315aa2a492cbf3763723e7bc78657d9573a3c 4060d5f0af5ce15d7a8d1479313e0fee2b20f8e968cebe186761d6c01317bd05 825b5e2c98d748a4749705d0ebd93e0baca50c01b072dba309b71e7c52be9e1b 57deecc6a18a1eb81dff5424b8da3f6a6e34ec7af818a361d583b905ff7296db d576304b302f68dc38dd385a2241268c204f6d0219615dc123b0753ba0cf35ef 13f693db38785ee165adf0cd566a7402f0d4181d2bd633c081e86c5509013fd9 258de71f92a436777203c25e57a22fc51750bfb959022cdbff5fc1d3eab8b41b ef87aead744d41649ade14650cf65f719a7a1083495fa3908acb756f84468a0b 99 a84568508239b5dad1d95d23b8927605345946bb7a295a6cd84152cfec6ece0527f3e2ef34311de76772b74096eedaf2b62dfc5967f0d061bd5f452bf94317076aa39f2e95dafc34cc7b550277db171d5131635b2285e24720478477189d030a16f939a1fb74c7597865734a88b0b749365506ab1d7a078f8ce2dc946ddd310fb5767372faebac4d4be7118bdb91fa58378a63eb703285118d2675aaae777c0e236ececdf98d69d79a414f99a98853f94a4ab5e13223cb1cfb519b3c127ee307c435745533cb3d016f9908f48bd6340c994a3626da9fa2bfcda0968d526ab60887446cc871a01451bbf7dcdc4c91f3d378a0a29d5e8f42bee345f83e5e6643046fe23634b2ff359783a20d94df69ab3a7c7d9b89719c59de941e9fb229e6e80cd71cc4c593792ce04fb9266ceacb39d758b06daffbbc42e4a247d75a0db17b01da1e94a2a1db829d58caab5d25c9c0f458c93df54314c7d7401a25e708d21c07aae4c196f17ce2ed2c9ed8fee96fb6c9b1240afcf52ff1666813dc06ca35b000715845bb324b326dd5163d08c23a028a790f444a79e51a4062df5b395ba339093e1449fc3afc61a5cafe3eba4bb86502cd0cc9232920319bd6b1a24de670a807dddc70ea9c5901e13567e5ea249f189b8bd9c4d91fb78d610c62cd55e567d007f6d2969409ccd8adde436d72d92462849eaaaa04fc0e24880060d63bfb96c90a672ddc3af84ac3fdb64a21f908ab54dfb7ff5d0148ab8c8617d331130274840b7570f4ca4d00ff5cab936951bf361e51fa00f0770d3a04a647718640892874015bb9ca4ddda77074f85060cccadedb0e8e424ab044bd34c9043d1c29cc904e0a40a07c7caff75383ad205f0c47a1b900b665f22cebdb653f506fac082fc606080db48a99756ec03acee8a9ba52f06fc4598a94e4cdda110562cd614d1a53fb0c9aa5a1939d3734fffb2b04dd91ff7212ae07473d4a8024f52f7f9d6c4de03b0e5239012fe1a1ae1c8fb53718065db6de23a8f0e3673897c5ccba578575528a0ad26be05b95b4b5a703841df12a1156a39e637fdb2204f4a6f0b8d940476f660f02b621bd71520e66c582b6c93a37c24fbf1e4076cbcc682fe2f122a12ac9ba0fd7560ea6b1c8d83a032e889a6a4a900435c1b9c6f7979ddbcb594da8b928b20767731943e701dcdc050c02fa46526165b82e33b37482355a3fe934996afc2d03830a73f490cbbe876a1db7f2b19216293f240f60654c50c94d3cd57e5b5668026919c7d8b3730af368b999e27b58a8cf2eaec6cb80116eed284952a288aee50d760f6f3b4ecfc82784961852fa301f8e71a668b2c5a9198cc302ca6599b0640cb07a49c71d3fa0ddb6997ec31ac9cefe4082433acc71c928d7f461123c4dd30d73a6feae954222c711c269af99ae40f048e6f6b1cb92db3ef82152028bec1b0e9618b5e0b0e107865e0012e3dab4676177e1f1c9a5f5e67238e6b77c9be2b60c5fd06ff0a2d07d388de31772ad047fe42ebeaa4a6d9e2814462a8627c4cc7e0458d4db2d36f47ae440dcebeb6b5dedeffb1eee50b97602e06f14c2cecc56570c3ebbe1256a85b1fa9682cafb31745cdab5278a1bf0c41cea863ee158e166bc004f39c387c0fd9a4716db7780979259d2db8458000df4db26c84d0784b970fa0cf5f7532bef0bb545665ee021172362e7c5a68e4abdc9e0376b323953b31daa0d0b0fc9ec34a2d31fc267fd3eda7fa743f15567ff331a22baf37acac1a1095604ea5a898cab0cf8dba8c20bfd8561827e8e4589e746b53dca0795e2c7c172a1005e4e552d34afbe881e9e0769735fdafe0d237b499b1b417313eb9df1fa13950e369238dec465e8a261ee192f7fecf80351b1567f5d8e5b5b9409127b9ffc18033e1551f94bd2c3d6c2b58943b0a335e78302dd72023ad77a4dd924ad5c55bf03b4036c03ffc45a5c76c4b6db45f2455a7f862e34638613fb85d024013225ea0df500f16cfe58e7948968079b5fcb588e4d9fe8a09afec7bb70294421d0b16206cd4f32eefd342a3d1742451fb286c629b4123c400b36add8914f3a3b0b17cb04307a6927d6731fe23432697368b166a9500697f50fe408ef56cc5fccd94a740a42b252edc5f4a8bea37eca9624bb286129aad3b3ba8ddfbc7f20dc1dcd0a43039f8097f4ab0deb1e79ac4f00b129980074ad1e5fdf54f298540f3b389937880a19f7ca59e8d4059d1d1d70284bb3c53a7dec8e2f3dc6f58a1f1e95ceb21ff90bdc35f9603b44baa41f6d137152bde5d994512882bdc71a80590ed2e3742a2c05394b5aff7c681300841a02330532ef13b29a536464afa7c1dfa9a19bdb4a51028022c0300523497f0941efb90d29a7d131d9bf4e75eb1cb7ca1960ee5657680741a309c9ba28fea23b0b5781994f3a7f68876dbe85604a09b3b34d3d604ec90a5172fa1ac29f3dc07a322752b8b5ea95e6ace26d18ffbfe4dc819018144c8c0dc49323427ffb782769c40a757f1f6253e40b15a4828b242032c7c877227bf0087e753e620da8dc3db98f83a1c76691ee92ec7785110bd86ea27f0df26da06f0f2c862d403ee510de00d36cf6c402b55474fa4e692a061dcd552f74e7c1277d053b26c1249d1979d541a66b5edbd387e0fedf21bb6c8b2500c774058cd4bd4a05174e3243ecc50a10ebbaa57704f28effd9f80ff94a4119f2ac8ff5b1e0f9df0381a4598ad2d3e3d0a017e01c7c6b45eff04546ed910027836e316c92541ed104d4f47faf3d3599dc33527e144e0f5c123b1d3fc565c488166f4d0de870f9530b54c4836a0ebe17db565526d226e44d4bb53d77df98bbba7cf8e672fb35ab6d0c1b797983dbead52feae83476ac04b62d1414939bfa03061550d6843b6d0a4d04ad2e73d359891b09a6a7ccaf99198b572808a7ef52df9601839a1fa6f1a70d04681311c2441e0fa321d5b4aa34548a9e1012254c434818cf076fb2ee5e03f50d086ae081b87f1deb29fcaa1c08c791fb24f7bd8223d211abf914aa04a325da00911ebec8f4d5ce3d127e733c6143817d814810689d68ed1cdd24eaa0eb3ab407d1b7e80f7af2a88489a65e435e08cfef4d6058fcc75f939a834fe3260c8b3d0594e7a76381e08be446ca51a6ede565c4ad05a2699d01cc6c7f393d8a846d850c20f44e5d6549f89df33e19ad41a1afa9dc7d59f776707e5f2b9364ea15d4ae098c57448f7d38a5e063778c2c7ee96c22a1fe0f4d6c9d56b62deffccc3dc5360ef84c8e04edf660cc59621d029c355e3b0aef571dff402eee7ed4cecfb5ab2308c5ac8c492ba2a355283a9d6661a657c496d97835c8d14da3286d04b2bc874f01ee2e9137f43fe3439f34bf811e0953783cb371be6a40fca756c18413afa6a70af73758dbc3f2bcbd93ee32fcd504fb13b2dbbb2f10519438a7fb7284edd4fd0daa36e280d6a3c9e9d3e5042e99d73d921b902f2a6c863b065f40d4552c47ee0cbc9ca97b741bfc8e2fac7a21707cc801e68e41609754879e776aa72bf6831f0ad2b8adb9d7c1d6887a34f38ec0617155001d1e911b943324d309bcf562e36309ca2a29605219369a382eeaf2a14baf763bf9d0e46ed1da7624787659fcb1d50e8c14a9e67dd40bc9ec9e23f0bc4847e8573317a3bb8fd1a052d6b2e2d3598d0ac2c6b0732524d496d6d093f36493c6a82d728dff3b164deb5de2577c11f07e053e323b7e6cd815c13cd07469bca408f02318ac8d5e540a6cd96be9a2e4498e04f8d4cecb62b0a228fd11b0ce98c5b18c4a52c01f3bdf58dfdf2cab2498e8180947980bd9f9dd5aa803dd03ac334028b0eb4396d750c5ce461dbc15f9fa2a2b06e9f5710384dec1ff5854f2abfa8181fb5a676b70526d72a666bcc2db617fec0f695ea529fc0663362c471ccfca81a9e829546fea5c035f7e8dc412e8344ec90484e175d0986347f0c02e8b9e3cad695a985fa31ed708682a8b834bbbd427ef04450fe37337fa55084487d0cc9c459b04fd14508991410ada48c546e0518c0801dbfc8ebf6396eeb8d66f7b55251c009d7474cba53d2a72a1fb9981a6e5ad5a09336a91c725f585d014ef164198e85c19eff83637b6933eaedb1cc12ac7c4de04620ae7c1d71b4b26a95989359a2bdb7a59b1c97d9bd4309d374acedd522f090cd356d695b800728b331cd32c37d9d6a709f34ae55a8c6fc7b97b7c506618b0062a4c349504beafb6cd3359ae2b27f8256c6597524e9cf287d9344ef9b790c804af530d75bca79d1965127ddcd1bb79f13077c0f37790fbe18122924817ad860ce1dff09feb06d942dac26d020a775f95fdd4726c762bcbb0d8c399216ce9190469540f82f88ea7cca298b721ccc3f0f5578aef36e9b4c6473fea33ca06e875012f2b7d40f2c48feb2e42009e8841f451db2a5f23ad6285ed2bac2792d77e540b58c337ded280fa8d728401a0d84c4d3186676c8f328a89fcb18c2086885b8705473dfabc0ac481a4bceb4c144187e1f3f2a3fcfd6840aaa08b389696fa4f5b0e0bf26019b574c5032994992e097c204fe2c1378b9f3b4c52e65a076b90dab6027f2f2ba47f96ddf5dea8f10b831a9f4ff092b020ba469178a7852caafa341d0a67004b91e4a92e5a18b9d0c962ed6893211ee012be6ce3a3c704ad4a70cb950d71c3481ebabb4125e224c612e4d6550c8ab47a7f34e1f10e5e27d8d6705bf30f41289c66ee07f12fb35c22161cb8d216e52c87bcbef8686038f31886e4e5d50627f78267978183f3aa5e315bd5e0642666cd56a1e759d1ca884d205c0083ff07beed3d67b4ee1c17ba52ca73d0ea56b967754f223b9ede1f3c57f439e41d930e04de6e29216be06691aef455607b2c17dd7537be9baec2529dedf1586f5e90039c8788fd3fc9649a081ec8dc583aaf7b1ae5146935eaa0b4c897be88ea5ded017a51fe4f4c3f7c2f8421108e0dd2a610a9a85ded2c4a0ac2894a6c7aafb4bd042baeb387495fb151484f6ed0200a2a5941dd7b2beb0140beca2592b75cfc7a0a69922de9e6f267bc6a69e05a4b00ac20bcbb6e6c986bd32dab570eb2a3051009c708b6dbff220c6e0e6e42c1abd42084ec51c4670ecb8e501d9f1e8e73a7380f973586555cf862845778794cb465481472141ca3fb45770a97d079e0d27fe10fd20500fe4c2386cc425bca4fd5a51202c38943b3be428753ba5daefbcd6a7e0580c20f4913eb9fad486cee11637ec662c254cf7d3f4e0ab008bb8bab1f59e306d2b417d3548975f449eeeb0e73038da0c7a051e24ccf268a3a646db8e734d80e6dc63ef3da73f8504976e10de048f599be95026ac79b1508b2c85b8a57875a0d8085190d2c0bd903dc7d3d8000ed22d33fdff4cc0b50741ab1078cf6a15e4a094a006cac29f11e33d799601103a19eb1517427793e90e5fe1a6c21a3758c120530ab91beb030ec86aae1438a1444d1353ce07c6d2af53609b186973c5cf05902acab15c573ae94611b0c4970f1ba03567a8bdee75e8ee200096dcf3bce228503c7b826a5685d4c50e06b6693683d9d3ba36ab89989accdb020793f9404598909ffff41a1892a40032be4b12b8dcbe7bd84f38c47a835e55d2a90961bd62c9805167e6f5b83e0cfb4547a3dcc7dc81c0a76716530a2ab6ec2cf6802cd09425303a03dade9f4810517b471d4f086132200b5445c590b241bba071afec7f86e0f006b29329e7e64905ab8bb32497d8d929e45ac441079d65a76971d5593dedb8004eb42eed62d4fcaff967dadeb4a53bc07d518d487aa04a367396c51861561090e4bdec5bafe793d4aa39ffe2fbc853552589f3f80acecccaa175cdd82940e45054a25e633ca7b62285553e1772670abf700b56d4dac532099b03d2aba407c660396cbdc37c5b1c3598af49da2e509f88657aae137b86153f5d296383917f39800bbd46d03c138269f3f45d3559ce8cce7671a0a4104fbc7c1b1ca1c1501a7ce06e37a89865aaac6ecba6211b2fc80841f0ec430cd9df75df232f65d59d853200473f878957243105f545b1bb91afec1bea9dcf0c84fb7e117582ea2271222520940600d19da80f5d36ed73970cbbef20fa99c2c8fd9552dc6db8b864df118840903d310a43c54c946776d6b822deacb72c3836ff77c14a198c091aa6c2e6fbe09a8e2286691a9128ef32786793f4ceb75cb5378aaf74c92faf7d1452ed95b9b0b4e9c19c1e2196426f4ef36add5586ed3d65fb7a7708ca8fd49465a769bb7e609ed86d9020b4d4246cb53c84b63f93f77d5eca34ead1666dc19e621c5543e88004842bc12327618386000a00967376ddd74ae0e5a6dce99da58221204e8e81108df55619be27c6a64f9c82f97f4b4004df09ec82c3fa4ba43a91f1770d2a9ac0c89e5a50295355ee8f53edb968f8729d4267c7c0fa0a1c7bfc929acde8f861c0d3d3d1265f66d0594738f7e1828bcb560bb232b539d3740e7dae5e32f024443095c0d1749704aff2324c39c4b09c7f3ed41b333ef027e60a69cf23e82c82a6d0ec4045d7c0a4da39e3e1fa88b1365677be76f3dfa2efaf137c4c541d5f00a8d004281b3b8b3ec3b41112165032fa59de3c026e67b0a8bf5ff2c9f44356c54620323da07f40a5020981133c933ffc6cb61bf3700e2e8b59edcb79ef28545ed8703fac42e6ea66625aa8e0b82eb39c974816818e7b0ad12b2647da24aa98ddd240a7f6b7322379951113a9341fbfaff02716fe2f08e50304aae89388aeff7d44106448e0820013de42853b9553577347bf570af530e26795971b1aee9a75de92c0a310af83a427ef41a55ef224a49d600dba2ccbf30095dd7f56149a3dc142de20c9d91dcb36b467b6ae0b1b12c5b47831307a7ddcc2967f5573b589c082497e709ba99cda53215192fdd626a09c1390e83e7215c0d3b467aec4d4e2b30e5874809cf27af46cb2708e9c81e0e5c18d41a5afe263985aa658ce7d285cbe7845ecf02d110edaa9a26bada55c9c10a5ef7bc00a66d1fef26df48961faef442566faa0f29929d3c2a2feb9d75b1853f63c8aafcd12148a674b0066d6f26c6f167770d0f6916d0480770ed37fa4d6ec3ef29ce67bed101124bab55b824686f7a5a963f06ef285dc6831330f62f45eb895896f15c3009f85efd45e06babc216e52962390b80eaa9f8b9d0005716305beea0852185c507b09d391090fb75a502a877981e00811f18d1ea1c75262a4f538345adf2b98b2617dcfc96eeb09d0c8c6d627c220140247df13d122376dfe1b764d15d6faf70dfc7bd2a124aae7629308e576bb00817c69ac56cc8c835435efd1d83df31d2d71e6c1884cb1e8b1de6459b3c83a306b35a1ce08b6f5f769360f06b2545bf9d4c4e946987b1f166cee68490a0879600a649ebf25fcca2f0df87c69eca7ac637d1c4747b13c8c4824a8b32129917f30a7f41cc4c91a43902ef40f8c6d1d7d9d6f175e5a70991c2968d1b62f31493a8001b697112f68956049c45fa5a56b01360ad1ab8ff8b446c77fe30fa7b3b643b08dc0790f8f8b87f79c5c1a3d9752c1ac373c93d24edc2523455629f22c8d6c20a52746944d3806f1f817d75e9f78f113c682426155b8a5efac535d4702ba35a09bec613ceb8b2cfa2f838701e22254d7a26cb144b5b697b3e2a740f238fdf450dccdaaebf4568d74349ff1e5e8c9d3a902d54f6937feb0b6ef8a13360a43fd9083abc2cfeccb41f575fe2a921dfa6f9a4110e7c37f1a1e78aca2f70602bbf9e0f4c5d82f67040c22f736cb0715559821b5f1587e664ffb12a1a8fe8b4a4c1c50b5aba150696176d6db6005c6287a1873d16d0d3db7b9d272d6da1adda52da3e0bed216fe5f7788255d123126f4fbdcc70a61a324773f3b5d0bf8549c706a0660c49e01203b84fc55375730cfa97e3d24ea648442482a3da4d6629dda8b9819e02ebb4a54385958db14a9c5de6636d06b13af64026912dc6bfd9b339c2b0c6e900ebadad69a2e0e312bfd422c36277e065ff78c4b55b1ee67ec903926c8df117002cbe83c440ab86a67c6ae8f1b15ecda6562daf53bc2bf22bae1308da10ddb4018c67f590471f05a10159410b47657618fc3e70917a9379c84b1aa1f96494e708e00fdd82fb759a83b4e741171ecb6a698b69779a17926a34ebb25a04dc7f48082b8cb38b75418689edc8c2de92630ff6227186edecd1f9f363407ecbfa84f40752224f589689e896ddde22cc8efbd9b5a5fde3387f7eb9f569d5e3234181e4062e57845ff75b0d095abf284e5038d14ddc0bc8ebba5637ea7a6068c99dd5e105e781c7cad2ff62c2a06c866509f773865328d8cc85a86221693c4a3df3698d0828411f79573139717be4a80f2cb7e4ded5a68e3a95eca8963552fc8425f696068106db04216602e3f197a14998db49266fd0087d0761b1efe35279d39a9ce0002e6f2807dc15ffd8e5bae2e38ab7fe08cac64a7698f849ec44d39b7829cbcc0abaf33881e0417f41fee7faecab25ff830fbf4355c2c125f3c2c0654dece8fe0a9fdbdc49bc8df5c8086fd7f6033e4f45a2ee6ddcf1417a6493229d666f324d03eef5dd9de38acee97a42a32000dc89586f5c8acd42519d27da5d6d41f355500cbdc78451ee62c158b09dc2b901c92785ed550ea7dee29b04fde0d5ec993bf00f4b1deecbe41987ff73b0320efc8488e8627ad075872eed9625ed128a3810520e5f90bad449f005dc829ccb99e00517620295bef693658ad2c792398ffb54360832564d65ad58b252dc06461e27ab42f3b94a6a60c63246ccddea4774b16313013314413406c79ae195ab6f421694b95f9dce505d18d2a1f8049e9c50212b2d058f09877ee1dc51f439d68e6aba3a9f53bb450c0c13a3dba5dcedfa7abb04ae00eb81a33070e893f6a3f66a9b01d4dfcc9384b5a58afc607e2f355a32b318e40b78f5c44671c1d834ebb7010a3716fd99eb74c612f34ca5049e9e43328af9060c5a9f83bae3827328ee5f8df6392f6de77ec3202f22fcbaa7241067d69728e30e5bdb2d4d6d2061c012612fdabfac2b116bcf81d375a86fabf47f85eb3cb2bc0825234c36f49f083c64032888eb4966a154b504547fae0c86a83b69ac44e0140bca02c44ce19e886cd19b33c3efad603b7a7bc527e0c7be1c2cd823d6e3c815069144b0854bd80f27fac1d308688b5340da080016139de9d0b43f263ba559cf08ab63ea84a85cc3fe52f91b04fcfb728c848888bf3878e5ed730226e370ea1a0c6cbda91b0c6fab36c4d95148c335f0d303a8b7ac42b0a20f80aceca2481ff50b68e1abecc9db05f21fb9fba04a47ebe94f78c51049fd9619db5998047525190a8e989f7b4ab4d003f0c6f6dc9107a1b03882b287c49259b0ec38998aef62830176d6524ae19c8e1a19d19c787a1305d2145831ba455a813b7e29692ff293170b918c8503d216b7f88f05cfbd7ef20bd78a90a1e353cd3bf78fa0eb66869fa8076e14e5084dc6bf07808f7eebf07ec1ba84bb965db016624411f415b71137f80192f28764d765f748746652f139a328deb75a7fb08b39512137f888eee5c70009a6129f5689b787054d399df0238a18429d60483304ecc85984f09b124de1e10d6cc0cb0e551109c6356d89914cfc84785a6d951fb094212973d76614b85fab0217d133567cd0e2b1751ece1da7352fa10a1a612c74e261d0cfde6a3d10a2a40e16f7ad1cf97673b032d92d9a5362326b790f5c45a0f9b5df9808385e1dd08502da953710f6c7e31ff5170333cf40d30022e04d68e917c459a9329c2c8a53c1071308733466e8ff9cf631d973c14838dd364a1e0fe77d6277351823d2e5b0ce047c6a1ce56ec2d126d47454ec6533ad0ea2b121793234ddf99595c80777144c07ade44f3d81b2e26634e69da5b29e52fd7863089d949ba5321b5faec4ab3a33097e440fdec037f97a6000acc5372b09011829a16dadf9eb7dbe5047a5ab28610c9a04267e2e622f742dcf884867316f4135335198e67a4ec034437b8e98e6c107cf0a537162d7a2f0249076be0c326f6a4b9c7c0bc050974287efcd3213509f0db11e2bf00c82e53f21bc25aa71a244204303ad78a271078c758d2e9db14362082743d2399bb3e987ca46593e90513faae5c032bdfb5219ca96919bcd57f3270524c74afadb045f3a36e0cd1cf68e3bd68d0efdafec8b0d56f11afdfb04cac704c7365a596c169fb44ed7d1fe690c7150c82aea164557d9bb05ee53ad3cc14107e18afcd2f153733f296f977ba883111db4bbe58b6724346cad4b7f720e191f06cc98cbf3a023206972f9f821579d997a16ce8dd7a77e04324aa8fa8fa65f6e0c8cdbd1c34f64ab225f2c1ce17615cb049c452882694934bb23a30dc722bb0903715370dcf2cef4cde7db004276474ae36bd6d244597c0adc6c794b3e1ed707000fa82bbc98558714f01c9ca28c855e1a3ac2ccbdcc090287455383a74022020d1be04a2b5f7abe2850295f49e7c180ac8e99ac4d7f8626b997bbeaf2db4b7c08e29b2787a70bad475ed5c172d2a476a666f6488c21c0123dfdec5b91f52dd80b9f445b634f4e51d96b9cfc37fc38fe84dbc2fb24c8372cfe04fdd54f03d45c0cb39d79222eef1e5706d32eae767b0a68d5915049a3c583e16243e0a5272a7002fa9759cb6bba23e2c2c041a87bebc1221dc3474d609803c213aec7866676ac0cd3b0bb9f4e360c5d0e9670e5e3ef6ebbe73fc5b9e82b28c0b1b53fc194d0940c08868b1150303566229a9192e32bb8bca9d3ff8e0d240d0745895f7e9a2d2401e2d70008ade16084f13278a6b22ad92af563fd9c709af36fb9cd8e7ebcb3110f7b2762d32a2c1e1d662486351ac820b32adcc80523db3405fe448843dfd59a0afeea65c2ef6271e374827ada480f037062b7a0316a1dc8952f6fc133199c280544a125457f9a001a45fa4760c763756fb9ba0acbbe777b429348d834f5866d0b367f5de43deabf8aca9682a161d204ee115daa3e22d1dc19c8a981b4eee804010b79937bef1f78f3cc581ffd9991f87b3349dcdc69c1d68bc673a6464e39710935b3eac50aa3b85fe3cb6ec793189cc617cd30eeb5cb57429281e69961121d09fcd189c24fdac0e7b9437a43a68c76a4f7529d86a872fc8a74b1b666044bba0deedbfacbbdc6811a305a8e985ffbcc4f75ef1aca4642b624aaddab2bca1be107a2c0717a976c1408a4a5967d14f369af318ef0e1e14e2056eb12324ef207310c863bd9421654e802e4a5f90f8899776a984de4dc88c43cd69cc4163fac367c0a3b3a1eda93a52457409e7c9898c3d63cdc7fc5684dfc68ae8b75f11c654cd60bd595e06bc45f6975304f88264cb6ea76fb05b4529c246feaaa28777dcbac6601f27af7b803bc7d2f66888772f4eda421d26979fe2c69304916c26e226a01cf080275ea176e0bd2df44e1bdcec64bc63141066b87d055ea85b5344c08c314d50b11359d2c67d80aceef4b984d08234a4b881895109df15412f1ebf5d4d4355d058352f701c11756a476fe8559f6b6b30307fa96ca39f8418bd8268550a1321108897aed8ab31fae2c6e1aee769577323e33bfddb05e4a066fc704c6fab6f3680b2ee0891f61e1d827659df21ac609340e17ebb73a2f7f270e54cc65a84fb8ef0de481f11a136fa80c18b7373add3037a737767c8cb30f314d9eded61b35813f098ac2c7ce53216a76c6ad0ac9c20c5c2f9a9aae534986f6efb26df8153f4ff102ba0ed11b06bef078241b195412f44bcee5633432ebfd0dfc8791c51dc16cc002553b32be3f0879e82607c58b38517c4dfb8acc6dbed3f63bb0805f7854f6200a63c90bfb0e86d61ea69130358a6a3d24e0cd991d448dab0a8e24f2cde55ac801765b7433b15b5cdc2e351861db5d4a01a31a8c76bc9177e01871e7fe832d540f82b1617ccdec3a44f6b2d610655b10c04063cc243af1ce1993e3545d82d02b0a9ee0795ba84d22eea67d6113cfc3e756fa80fb4dbbafebe7ad261b0c7d8c31045fc8ceb7061f6524ec7493231288e17461323690962649a1e19e557d236c46080059dcce443421cbb13458781836a8ab1d64451c83e987d7393abc34c198fd0a79af78da553af13701594af9f7d49d9908487cd2ab7326f2d267951293be9f045435d72558cdd5e817bd445285add0222b2030911a370bfdc369c3b94c0cc9057245e840918957f7a1d4ba91b88f77b7396af9d183a5f77add127919d78048033fac954ac51d5eafa75871446e071b1ed2c4cec22a87f3b764b1169fa52f8c012fce1b729872a3a8b675fd501e8c0a1907c4bd29d8d32c8a2cf812dbaee7790e7cc2d004c200dbe824bce46d848de436be9f4d776e628fe627741d1278292b03f8d325e471b62ebe4de12ee5adeec74333af0ce3ead8dca6678c41fd9c07240624a0b7cb1a7f0d12e76721976b45bafd3e73994edcad29cdaa468fc0b538a407fe640170b06423d575f761b003ec60fa058a896441456b112abb9f253abcf103f5519579906e0e0d11b7c4f2d93f8a5a7e50beb53424f04110c47caba39da10cf3bf5d06cdafe550fc5e9bfaf9f8b82257197b8bcac41f3186e36ae6f743e10f12b356fa7fe522fee7168b926100b57901e56dfe38fb0e153bcf48361f5739041e166cb3b92e27e5a7d5c1739e5bfc00970b2e6bc90c460f760b210185dd2d077ebefc4eb216ba10debe0feb86e5281506ef231fb49a4787a946eee0cf268c04bc000cbfecb4d2a9923d270ab34b9c8222f81e63aa73574937f59a8ad84194026ff39ccd97650182451124dc48a5f30a7f67187014e976438a01eb0881435307ce236da50436c9116e13d8bf8096abfa94cc7774fd8dfeac3e741e750a5f0d0fd6dc9d52d702eead69b11c32f46d3a739138f27b0533e9222a2238408c31c5063b3e64285824714097b78f9c9bfae30250add81c11677bb9f26be3a2833e5b075cc3f0559de4b3a415b0a971c36da19a7978e85d905d21a001bb19796130b100e5f3003f382a9b7a56ae251a95bc8dd31ddd20e4b8d1784573a089bf32f50e0142f258948cb600b75d719cd3ab341ba0529bf2ebe56658d3c787eff6619acf04e9df5ac6e5376a11f22d20246099d1a55e6d74af05c861a5292671d30a25d7088abf432cdcada442d32cb37852c6b5e885b460da78d2a19ea030f1ee4a018008bf9a5589a284c7c7055eff2757f905e6eda950a5dc337f2bca9fe04f28d7260e4f8574d3b62c2cd5fb3f6f720ec8101c18e1de5be99047836780751fafd41b01aa109292605e1913d02b300d263a7b1b7cb994d70e744feafd1b288ce8b94e05e69059e098b42900529473eb831354436c56a5431530b172c60647491ffa110a7476bd5a42e8cb412c0006df2ab7221cbfa371fa66c6b71f595675887d809c0291014a92c329c42e2f71ea18f45acfe18bf398c96be94e1a147e79f64c0030075e445a671121810b393481a7606b1fd2eb2d224db7d29b01bb63a2c9c865c70d98f598bcfc5853357362fe888b4a959d36494787e73327e5ab8d8b13db59d707d78c62d721f36d6ec561a17b651f52c24c0038533fe190ecd07cd3957aae5f0e81b559588532c205fdc48fde6134cda60fe1db5630015d3eeab0eab1e17ded01b3cc066608af7444e4c54c189682703b0a59ed8a89f4ba48059e5a0cf6e2d60bbc2706c04cb5ad2ee6f2e1a01606f45fbfdf7942490440e0afa00bb01cf5a500e28635216f752e78cf0f51c7958f8c8aed819379a3e839d4dadfb55171329401334a54ef085265bad5a5c17d283b6043dbcfd4c720859b167e704c90d6f7d30de187b76df69c5fb76c2f5722d119bf1fc9117ce46f3cac75c71704e9a41fac07b8264b498a1541d761c7ce5ae88f69fefe807e7afc836aa0a90e04e8a6005d074340a8016c934c2a6c3e6c86d1b755fcec5757db2093c95f1c9b805cb189920547a96286e94f1b99649bd611dbb061b585c214ec05c6f03bcacd5f1f402b5e091ca3e292394394845af85526efa20c8ff54f96510c2eb1c8fad2fd2071e3e208e80d5d6040a7c04c3747d8be2d744ba39f40a90aaff13290fce0023553398b0e36ca418ff92002973f3b5d520bf0bed2ca00ce79d8d89c0ba8394b10ae44290a397f3e50a86a64e47f29db45d3e3a642c4bc8b5ce2f8ba6ecf8dbef6f301140a1203fc5d9d76e9a82ab32dda8b4159c6b06b314f96fadc33ff58844f55f30e0f46ee7d6a0444ece436af6b74efcb447e50b48fa80c1805332dc67510b01a8e076a44fecab6831026cafda074bea61ee36ab18a6b2885faab940ff25dfbd5880a4fda7aa4c607d65ae4fcc91f98c8ef7fd31127059734c580faeae0c9a445f10df39229869914bece44d18bf3fc8b504a06c4076aa7054cea1449853c2f77eb0304800ab486a51aa7e789616ce7b1f2f4576d822e7f0a496d81c4e989dc169e04697a53388baaf75b8b505dfebdf2f348438355c026a6cef96574ae956da06f028f5717ec26c7f9c8794e808fc03ace6921865fa532074de6e2b86d531db04105a1f85b24cc8159b59043c558523f69c5773efdb35e4b165030c5494d345f5d0efbb419664861b37ac45d86936fb1417e25427f57fe63a34668c3ea856621bb038b79b1becf4dda51c1a7b9bbf561fe2fd47b49298afe0591d7b7fb4db026e30e1b5c76e3f9d62a3f0816f63177249bc85f6f53cc4316fe1aef1c987834c10c02ce8fac4b9cabe0cf5ccf69132f42a09414455b3241f34bc85aa4a3f06fa93c0f6589f5f2594172cc802fd03e04a8981c7282b6a5b9ad2cd932de76101582d406be03c9c20466bb6b3eb78560bfca6457e52520235dbc114268771431e8d499090522a2b60c769de3baab55c1f7ab1ba0f2e237f8b0780d47969b92b7f42d500e98aa2e11cc0ff955fabda4769b52627c178c9681bc8ccdcdf5983ac1cb851b05ea2d1619f8385e0a23e4ba3c993614017d74a7a01e16e68cadbd29c9c9d3fd0defb22b68bf6ab829aa1bf78ebc1f8d30e6067f005a8f75b0fc6e1e28bc0e29080fe70d937af655e3189dacba1528775183febcbae8b3fcd78523eb6f10537d0603c4ee2c39f1bf1bd379092d3cb42b4580c5ca3b278b018f8b3c9fa868055505363f9bf5d94e5b55575f35daac172617c9672ce781030246549e10f9a8449e095855b6c79285a1a220d6ac4ded198f3a8681a892a397aa337a4724c7f7031609a8259e5d76d90f681564a98baf2316925936cc73191059b478d80972d19bd60b6be7ea56a240e808513811ab998b13bd170282fc439b421f7c1da5f497c0230d3d440a2e1ba92d75361dd2127e2af67da8b280e3eb7dc8ba0e4f997f3eb3840129be81e9b091c1bcc8ac92beb571851fba0f23abb783b4b95b1e57e943f58e09c2745e303ed17c24d99e319996288e69c52e1683c98150dbedc3867f74333503ba6f2dd8e5b8999772fedbb111c5a6c4db6d4db757a6db807599e049f78dc20e2322b5859278d3347c663795a6e2f2042c6d1a3af3e2d7462de2d17d5310530ddde5a7a0304b4c0adb2d80b9200d143d90c3f5b93d7028b0ea9e2779fb0acd03 +generate_ring_signature e46bda5f8d177a85b3d4f3f9b52ec30d3675e7239eb271e9756c1b9dc52d0c1a fb375e609a51a1a54d30f6554e5481a94158e49705233340357ad15f25c832b5 1 d9515348ed96ba26f155412e0b4b7fb190f48c1adff6d6f7bb0d68c4ebe432fe 70df55444de1551ddad38c3ba80c388032316cba280052447947c02151dbef0e 0 e4b36b7bdae0946cb74d25f50e2b3db7990a295543e7f3ee042b6b6f0e230e096192f33bc07335ce95ffa7631adb557bc9bc8a4c15531c72a62374b2c5cc3406 +generate_ring_signature dd3a63be8c1d0e7c20341ff51de1ae69be6ad9a4af2494d969de4b5c5a3d1213 bed9efb67d0318e6e2fa22a32ab381332b38f0894f8a8ada7f8b4372ebfc967e 4 066b617b0fb79775aa1b548de8757a121e7d0e38459a6bc5dd0a587a88fa26b3 193a48039163ffb32e1ffa931abbee6e1aded29f388aa635a3ab148c8d5e2568 4732c8e3a686c813b657069e304e06df196259ac5f1634bfb7713438345f053f 4f1a2284c22c27aacd12d68d25ab10b1fcdef99a708fe2903c30e185fbc99c28 79be700bc846a57a8404540767e0c3f22a32f812668276c2d6b9a2938d286a06 1 bb40985067d244cbc7a03a5624fdc0a225c41eacf3276cb53ed5e6b108a0fa0c55bca1ce5b58ca218e994057375ee04eb95b589a3af45033316631483ffd620541cb926d3fa5128a692f4aaa923e599536dc4993fe69ce2c41d94d693ce0f706d7fda63b9d6391b79ba008c0a0d71ca405cd4f5d46205722e3b27af2cf67cc0540e55a08348992783fdb36c530cffc272c113d96146cb5d73ba2c5d4f25b290b8254b3f7dea97f6b749189f65501f8e44ad8a247b22f983fc79b924ac552200687b9a43d8cde69813cc46378e464c2ce1fcb3c63df8a26fc42b1fb79449356051e019daeb4533064bb7f62539e2f6e9631acf12a0049e19a5ac1dc49b5a4fc06 +generate_ring_signature 2a3fecc5533445d1ff407029a75e714626b2eaee3f6479c67a27201ed06b2b9d 01c8dbe8167151ed13b296b133178b80e39a38b0c0c38051040ade484b69e4d2 221 8b859d51a272d7d7f42eecf840f7fa9149a4dbd6a7724f6afa17c4a1bf26d8ae 8d6f021c956ea9a626077dd81b5fb6e459a370b56deb4f4fface816bfaf00668 815a27ec056a040e436e299d9632876500d90f3dde3eaf1107d9503788cc0c95 a24932b33273a1ceda8f5b32f270fc6e0df415fff64ad6b39017af5359242b6f 9a0adcc60772f3f654b3b417943433b00b6bfc27e8b8afe5fbbf844147e8c5ab 90f1e5a5891e354d4fd02205a33f49657a5de15d7ff4ddc31f39d8643d62aac5 450f08d11598d355afdb687cce5632cbbf31e3c1e0766765ac352dcaf036a67f 3866d2f6934814b1095f0e0a1f147b93c50f15716e254c9e7d74645a4df78e0e e3491b5ebfe4fd7c5bd3f1dd3a40ab2825bec7c4d827e0599f1145fe51629f3e 62c9bd5660490a1d2e9ff39215eb040f736051a242963bf2f272eb9d73fe132f 71e01607b9b65d973be08bf5983d862bd42ef2c3f0fd6be7ba33a54a5cb909e3 d561622d76d33431f0a7881258e4906e5774696441e93194eace2bede8d5d095 9e1c44bf1c3513bcf7ad2c087c0eb6f0d19ac9288a21838cbe629312543a7d32 506331bba887f11ea4ad8c9044e332c082302838c750f0b0ba8936b8dfc70715 a1f5054ef80b2ec1f151f60451f4c982280f128b8ed831095ff4479f2adc8b19 19dd0493e1890f8e0ac05b9fcdaaa0bd9688e2ec9f47e2432f02ca60992e4bb7 8d2df708b2ce601d1bf7d762da0d31681643d74b8ef61e061c1f67b8e88f3975 b765132b1552f0c34491edcb6d601849aee7557ca805edc5296334860376838c e4e824505152dc5a1800451cfa73437c266b6a0ddc9a6b13f8a82f2a308195e3 33be8cd89800df491acc53ec6eff8132fc3875a454d2fccd019fc6a3d4aca291 f7289f047047bfe7fb28bd1466daba43a6b73318aaf082fe49a9703f2650c54f 85aab4738840c444824cadc97dac6f1b738102ab8d495c5760ed553ec8cdb8c9 eb87a343835083e45d815729559c3e1de67d69ce50f0f1bee874a3e90b8701d8 c58861edf4520042f37e873b69016220706fed7fbb5f4ebc1e21b9fb5018e20b 9febb8ed1c5a2cae82c73149c0fd7accdac0451b8fdc81121b954dcc500e5dd0 c5825602f9ec7f01f1d7905c3b3e7a4671178863672f3ef2c83e1abee6788522 fb3fa6e53af880f0cf31f95a65b5181b4be788265f9a1c0cdd5c3f1718b5bf83 f6b63d638100268978d89ed0f6005d24a1b143c112c73a918ad27b6eed6f0f1d b4589104a456ee51feadfc532a6f52e5bca5eb9070d0a77a02624d774d4d2eca 1fc0934d38877661c56143af7277eb837868e8465f0a3351efe115d1f61a6b20 bc4f9dbd0695c462a8b57fd6b0af3974104bde49c6062b5c4bcd09615d028b7c bbefa2f48cf69f7b1df407805e23764ac7266494449ab9fdef0641b4f13fefc5 1c9ce4f9a6a3931a3ad753ba874fae5acd3e85351b3456dad3c0a8ef85028633 b378c247b6855244af5246a0760ddd1a703629716b16b50f2f7afa5ebfd57e01 88adc9c2bec405b609d7190671cd84ca990e3f2794ab3550fcf5ceb569009fa9 d063eb0d4f7ab5f0b7bff340644c61590014570207189c73846322e0b77f8392 7ef5e21552383ce730b75abb6de94d8623ef8987e2d382d85dca46d2f5b94324 7aeaacdda090144ac43de8e04075421917f57f1044871738ad85c3933a7b92ce 73efd0833c7b48c215c0f92d2e72c9584bf1a5d6f15c9d99e19a6f6808a9ed8b 65b8c07bc87e20fb9ca0fb72787720d7a6653b04e11d4d31f6c699fed3ceb5fd 250511f67f3ec1d43778d1c712a6b72090c1812349262f5aadbd37e6f3cb69ef dd168f71e4b227d7417b3a6d0c6dba72b1fe04e47b3816569f149ff7e736c6d4 e1837515ea0184def7085f6455cbb2ea7d957942dc3a67d8c6c2ac5c3f588528 be818f8f702a06b5757bf5620b6ed5c110924a73252d5818b4903036b38e9ac2 9348070e09c4ea8e76401842a74161a94a84a46143a1242e60bcd7769f8c10a4 775b7d0938679d7a173f56742e08d0eb911378e65e137548d9ccf8ac6f61e00a b44cbf01cc2e599fdce193fc44b58c7e9f67532e6aa0cc18a771823b7709f379 2452d9e33927a56350678ca3975ed7b2c8e6d4d567ad7ac0e4126b1a55dde552 75b837f6b344b941183721fb45bed9ea0f5ad890e05f465b4f0078b8c860ea30 626ef8f4b4cd5a655548792ac7acb47f3bd0f22411a91d39a6460773b8b962d8 173a57cf7b632d55ba237914c471a75ebd5023b471406501db025318dd7c5afb 6e50ed5141d31c5c71a32b01dff6c0f9b4d1fafcdb59e7363d0b0de0f6f22049 353c625beb6b2e3ad123fbb9a5b2596f38021bbeef7b5e0c10ecc9234f6d553f cd24fa2bd9e36f5ff131b44852c0bcb99d82f055792ed8dff48e837d1b4212ca 2388231a621404db213c4060ff612cb04291828799919be7462d9b0ce8db9642 f05660f72b5d1b9c8713a957604cb32b1713a8cbe32a3ed4c30f9f581d1b10e3 a9604a2437780030a1ea1fc481a7d2d538570c08f355696156a8313c4dd6e00c b759e38e1dc01c64386765f177c8aa429cee8ead275d6ceb7eb13ba22780e430 aca51ddfbfb7e7d73b15a6a620bd5be30c5ea0fff58d2952f2764ea5378f8e15 7bebea82546589b5992f3990f088c948ffc03551d65275de4cf379fe08a231f5 637176cb1b76867a4a07c3f4a7e972ae621c128cef42937a4f367b5b52688ae1 444b6b8d2ad3f031dc9884f1c8d33bf92b0f8e51a9decd2d1853a613a09ef956 d2cabe5ea3d6b8e8539f6ecea33ec239ece6b1d362ec8ace8900c7f5d32b18d0 12ce5eb61291c983d787b75b4bd4b4fcec42870f7f1cfe8d7864d955705863e3 ac72fb9e0b6a14fe14a7e4313c3df10a5f6a4e424c8467547d02ee590df993b1 8e7757946777d73b44177c05b9beae59bc440eac16f548c95931ef4d608401cd 649919d443bfae5542ed3d35dda9d4a8f5027f8529eb735ed8cb27ee408783c6 59510fe2efccbc9e071932f0a1d6295e9f0c23375af49e4e1ac630b6b2ef7ef9 bf061ea258631a7bf55c1bb2e782d745f8fef6433688f4a254b5871f1a59cc8c 37542533284da65b04bb83ee315c0aa265552d9583d7805f02a4d683ebe87846 b32389352f301af4a588d53580b2af6d76947705d45414e18c4ba8865dff0f33 a48963364cf079b4fe0128013c3d937ec06ac6d3cc4adb28165c39a37a0319fb cd8c533905d1ff627b1e69130e3758472c86174adb5002f0220369d51133aaeb 61e6c4d613863a1bfa1f9124380cce995ac5dd90732f5979bcb29d42de22eea4 2d0723b5254153eb2a17896b7fc15b8059d29e5005020ef172aa50a9ab7ea7a8 8a743f0297f0efe2ddca293984ee8d3db4f5cc461c2aa9a487f13494b59fa25b e6a3d6ec91a5aa85079c7580779b393a04c54782b61e0bceb0d0d0275cacea69 0df4d37fb5c42f35624003a5cfca5c3d6eb240758569b5d26f16616551574ab3 c9a427a5d45f34e865751f516eb16c1645fc0d34f9d3f29d15defd41c90d7c11 d611c94f2cfee7f21c74272603f669eed93b9be74f5e0aab045bdeaf02218e11 4a414aa192df1dc95b7bccd5352c3dacee9da798a587be8d0dcfc2d932e53c23 d432cc97206bf2028e875b0c39e098029670e2c499b88ef451b95c526bba2f09 bc4594e40b1c06c2dce163483efb045e8378d73d819d4364f8fa4519c8704a16 37e6a276d50c83cb2ab5a9f7ced57f2b229edd17e2c91fdacc32d93925f10145 290c5152fffc9d95e8dc1d815fe633cd79b1427d50c8db67e8b68aa2c4b98470 8fc57c77048100572648ff75b9c5d82dc1c0d0fa5e06f05afbf9f201712adc4c 0bded12b4809fc9ac013e84373728305e8464ef4c098932625294a4011450e25 b8e535e32f58d625101ff5318e30492fb54507ed21adce526c366d5d3e6830e0 f8377198a04f2faaeddb95b3184eda59ab45d52583bc8e6277e326817f5e288a 8ebb388549bac9d0bc58a50efa290860bafb5c558ac5ff97014e5e91e2b5d6f9 80d45483e6d7e55efe1cf485514b7c9b15ad69550f8228adab97dc7dedb77f2b 860df3068a952468d7de7b480ee3c114e2af6a1bfd57718ea70a532156d316ae 1e7db7133690a920da094aaf299bce31255ebbd1ff89019334069563d97a428f 4f729843f70c02f0aae4848573fa65fc44fea293545643effc5a0414cbd02b72 f6ea093551a609547278602ff331bffcd788474b51a4ccf1576e9c8f4c351d0f 0d1425e162b53dad767159eefcc68e3481e7aa15cf5dde15c560e86e9cb0735a 0e8af77622167bf235723615c1c3d7a819ff60db6c5ae32e80f5a2856a68daaa 1e59be38167c56a186e49d712150083c5c1dd7588433b428e23062de4221fff7 b43c12e5bf504f04fdc66bda7621af9e8660bdfccb2816075159ac2713ca3f2a 9f7666358a33abab5fd147f4adcdf57bb32e12150c079be07d8fdeaa9ea8beed 521a52a0b3e192d19c0d35c561f27f6eeca58ff13e58d529beee488b93d2f3d7 7e7effff3b399f59166c50e33f5cfc0bb5260ced230184bf8992be8dcf887b10 ace89f0a5fde0334b8c4cd6372814c0e424e477a71838d4ee4be6b063ef83011 c6f19f9441c7443c9aad2a73076f466f5e4f905ea61c3f294bc20b588959ee2a 2a635eef90451e80ada03b004c75fab54e15e69f569f9c3e9129f58c713f2b49 4e822815ba216e4e657c7a4ef7937215b6d62196d294345f321589d5dce6e209 a68901cbeaa21bee99f17aeda62c6fe986a2938494df1fac1741511c6c11cf88 43d3eb9c030f4d9964d5e9c6ecf2b639525d633187e11f0da531bab6e5ee8a01 c0f196df45d950b38ec8d2629d12aab07856874494c29f71c6881c1d9854d2f8 43c9afda75cb063deb114f4b37dbfb0078f8cbee6b8cb740b97227cddffa6a18 d75e8c0dd232a4a241372836d8f12afa216dc4aba3cca2f7238d37cdaa54e1a1 edf772170c15f645d820e11095642e27a7fcb2a1850d1fd08f3e8f17655cb480 9c47f9140a0615c1532835e0f0bd405ce7ccc8b385febd11a1bdf68f3e921259 9d73a698ad37b84a11b02b49d6bfc96929194baba505645ef1761bf23fedcf61 2643526f0e6e1cf9f2af821278710b7065f0cae0ab880e9058c329ffdfdf3ec0 bb76790fa787e08a246e71857c921d4748b40ac6e8451baad291e7424edb40c8 35e56823de9d39318ad185de2a1d4568835b54a6abcf49eecba5f97ec49006c1 9c705590ea073318a4982ce47e67d422e751ad1043f7510e6a104fa8a7a81496 1bdfd29ec07987e54e8c928f680cc028dd1672ee6415727a8d66639cef804fb6 6b389fe787a31b450f1818ffaa0db20cdfa9b6880fa0ce0a7c541a90dca40242 dde10545b8e2fd54ffdfd483c18afccd262e204605538588848ea1c0c99efb03 4a10e9ff89c15561cb1157fc992e6133281504420f132623b9de3174658d28c2 c05d11b8468a9c285d195c40436785b680eff853135ad3202d85fd6b3b71efbc 709d67e136f6fbb15c6b209d56c894a0012d3a3010bf785ec6cf46565c7ecaa1 a551208cb6283ff8ddab393d47d2f930957a931a70212bd55fb83eb03497ffb8 d65abbf9e83cd429a72a2c0b11e878e5a4de06c256eb6ae8b7ece0ee7ec4e899 a03de6ac90e23e9470213a21b251e70e74ecb35077f2485ebb2f7d150c1f79a1 83ce4ba9a0d68fe3ce9421f42b8a010c550fb6100c2f8ab008be42902f3c036c eb4edd84bbf5d3299f3dae898586c55b4483e0afe6f4c253a779b59a928d21a6 10b0465dbbc0d6ccdd8fefadffcdc6cf636c7d6eda6ba735718e6e0bd4ea0ee7 f77556104aa4371f176d65aa01c0c3dc4eda40e10df76beb443b450ba666c16b fceac9a002728d8175618729f289d0e9a1dfe429ef2b9758aeaa63990daf74ec 96ac9c4c4680607dd545ce646e48ba793e146988aada0c9c0581a41c7d9de1d3 0f749c6dfa9b9d40996764cca834443751a654c1396161ff146f145158946816 873a8cfa29fadc9e3fa66fcdba54a99c0d5a645880fe162ca31dab20003988f1 a9138ec342b3cfd9fb544a5e5c148d2ca59bc62f54d27fb22c39e6f6915ccae3 e43bae09f5a5fa2596ea6f61dce8d81f0b9d51ae509cdaae1a24b963c274ef40 7a1b36d60806fbc951852e66ef531c403925e9bfe7ac324fefbb2fd81a43baf8 fa159a7bfc0fd40d2bc5a70a1bc9852bf10bcdef8d8e2e1ca9c62161b719e1e6 ca533537e8ea96c9b417a07b70a3ec07d0ec256f1bd14e8b34e4d1c89f72097c ae8e7c402fa13e037cc53e9fcabf06811b17afa21020b647b1dd686834a2d67a 6ae329a6be8103e2e4976e0950fc024639b41b8bd921ce630667216be4359db5 1a5b42a72f462555ea91f9e43c52f9154feac0f2b4ecdedb450143d090b93d06 f6e54cd2ebb518244dc737487da1d95e303b6ab78196a6c9c59212f18824b0a3 51ad7925ae3bec9cb057ca255ae54aa59698c225e5a0293e09d0e83fc4e5b7df 4984ed3a617023b33947a5644cd4bbe8ca79b562a091f7f61080c96de880a9fb d9fae11e8d2eca9d88188fa1b5dd6088ce1875eedb85335003b8aae6abef11d4 e20fba3947dc0003f5b6ebc49a40df8c029408546659375d5b22974c7d3ed1fb ed2616df75233d9c496a1f0d130ec9bb0a318c0b05047fd8bdcf1ebc2edf62f8 482f06cb80351780d5d49898014ed4f4582348c4ad33f283311027382516c54d a59efdaecb58328250fe5e506a5afe36662a5265cb4782eac0b3839761e87b5c 8870807b28a03b28321d06f6296ecace564cdb01d7f37592168b2d2ca075c7c5 62a59c15f0a3dfb0c1949dbe156c2294db9f840dc3bdd4b342b8405aa28391fb db2b5cf69db1da72690f3d0bcdb621e1ab6bf2e8e40e1d0202dcf35d49904067 31aa4a6adbc872d7d62189c83880b5ff945bed0da282b75dad30a60790c0f33a c93ac37aea14d028789d9db7fa08d8ca9856c4b1c101e5f212a2bbd71e1784d3 c8bcacc9a538112417d16664b694a837e6d397b1a4de3aab80db4d326750cee7 a784aa9d92f6e9379e576afd1175a0e5b0540f3145173fb30784a830e85487dd 0a564ec2c2d56e504bbc96330a884de705a47a25142e44e039b915264d74fd3a eb71a630f352135a48b03da1d0cf9d96832fa4ce940e6bc1ff73c47371b47754 36431d4d8a33fc41e52add24baf42d705860d5cfc83aadfccc6e4fbe7c6c972c d16de71a298b57cb77398f2f0226415bf28602c439bffe0334b0d68905d219b5 4ffdcfe47d26d0d30ef567366c6eb46275989a8f847b39a8f30d89a74ebde012 1c1832371c681f58df93c6c4fe33292285a801c2e21ded6e8191f80800b981ea d5fe4823f4b5c221a275060de1d1bdf72672dce31bd3f2e0a474fa8c38c41077 bab9b85dda37d0559958c8cb542609ac95a5963fd4631ccf14a6535d320cf9e9 15f589eed4f67eb0593ac0cba466f4b1be1bed4fca49aca54536a4a24a77f29b ed67d0fca43e7dc33c83efb68375c3a19fa8eb4536c49acc27621ff542e86ab6 ca9dbdcd0b47bf2adb0e773a0cede86e7dd2aabc5e6b95c2fc3c1b8c5210ae59 5e915792e97503b657a9338082f5ba9b24e2fee4d1a2938a3acc902e3dbf4997 d633420dafefbf863766da7c63606d22239d6548894e26f06d891bd406b21524 cf4f849796892dd5adccde35a74999c25c6ad3c803718becb4243ba6d8c7e1d5 13167c9c0793e87af248369823f245d99592a43c60a15349d44fe233c5bb9f2a e183538bc5ee8ed570eb66d393fd056793e269b109043eae5c01a0a090d18b3e 276b50ea1b15f2a45809d0b22cc7834e406c1c1054c0c7f7d8525c32e10719b3 191e9285d6d24e95fd7934a09d44920af2042291e4c9a8586e0515225c8413e6 de9d26522bf6f4ed113d33a1443c5f160de08691daf09272e7ea03232f4e6e84 d333341edd7b38a52be376f8287d13f89bf6b01dea8a50aceb421d9f602b05a5 b8a0364136c444f623e4dda641be4088ffb270a4c455c6e941d341681c6d6d6e a62fee4d42bc6db241ff2513f2540f6c7db4fee24b129717e3004f95960397af c259025eb09f04eb7431f508b3c6999a3418bf6bab8af9b55cb7d3fa4eaedb87 c27c59ea6664edb562515b3f4c71715483aac96657e26017b054f01777db8887 f91c66dd8483e994c9ebaac3688076e8797d4d67668909cb2192d279d42379c9 9f58c7886468a9c83ba1642052eef85ed2a45ce928fcf10d173f4ff4c89dbb44 4653a8407b6d1cc000eb05b1b840dd14bb6188ef1d37a8ac72e12217fe166472 93b14e264350b8c30798d2a39b9072feee77dda2b52e375196b3106022b4bedb 5273509157346436df1b7f67faeed0c0a43e999f398466c246bc2e9286b87459 10017a84966ba1304aa896dc9fc5708330f19054d064687b39376a9fa3241fb4 9d9063ccd0d2d540300637243750c6bc652c1f119651f81140e5322879d82f8a 940eb9dccd7636d1f891ade6e4306521419fe57030ad7175cb3c8da0fc72304d a820c82bb599fdf8d086d39acd194e39f132a85f18d8300f4cc56a8220d225c2 233233f3420506c6227ac4a72e37a4bc907d63b291a4f32d4123a7da47159514 7fdbf1d6f41f271391410a05f7a8d30e55e1777905673b8d4b3d5219a47d656c 2661848fb57f9b929c0982fa6fb2ed2e504d2d44448cf087952dde5ef2ccd758 07621d43208d862972ab719f654d757ceccec4f52dd70f013e2cddbb6119219d 53f0af85e186307dcff8b2ae1b87f9dbfc5250f5bfdb77f36ef3aee934853150 34c6dc33ff9b31f5cb61c6cd9cac5a57494ac89ff81f6eb768373507e2331f2c 9dd70bd2b9228331231be2a27d40d3d9a1bcef5c5065ea456f091d554b47e5ce c3f51b37f9ca58c36acc1832c7a0ae39d1a4cff8fd2f754d3d05d546d2c0c561 362b58b15e123a74435aea20c0c96ddb5ffc7413018c4ff6540b6c3b941d1b88 445a8726a0fe3b24c15b4d1df672059bace0614e07f61b3984a624b9eff63aaf a49862a6574460fc5e9b3432da844458d407ab51632f28b02aec0d5af356937f c9d3ce57149377557ebb03ffd48b85bfe30f5fe44819e2d589ebeefd05f4da1c 9184c6dcbadcc0425ca7f69ed9a5f120cb9fbd9126c761cfb10307c90f75af22 e5b3ae461948bb71e5d5c1c408cb68a6fc1773b89f2a16fb06bddea5bebfe84d 78717fce1d774e4857b31faee17551a3c70a161f9733b9e82cae3839de372e16 5259c3ef1249d01c1b4270759a51df4e9c04dda8a96eebf5031b9b49ad47a5fc 2c0a3e8f2ac581b434d56652e75893f86395d8e34e0852ddec0496e35e286b91 3b2af796e8f040399653cc212a709de714d5259e74869c8ca1879c4c35b16acd db2975a318a9c2e4e8fa5be0c62e49d88c4b6606dc1d9cf71538c4508d68d92f d5c78555d2a2a033d104c868c3d908855247a0a9b31047b29d169b1be2eb20f1 d1a7e0ab08e9236ee740f2c42c57212be40213c9a5507d1f383d1c8371b47669 f7b7d65be98a75555b03e382aa01c790f1952dc8f8b019a34f2d6418ff64466d 773bc5294e59c1a624f89f25b359df72dc603234815e17abc0afe586dd33b264 25806ec523cb87bd4c3f5425a78fd7f879978b9d0a5bc2efc4db3a80340b91c5 1a0d6042f55fc72643c05ef6bd3a0c3a05589780b9c37779dedfabfa12be6926 4474180e2cb3f2d3ee664c63cda703a82d49c0da75dfdca8aa10c173a85d04f7 d2f254cb36b039214a42b95fdefdb45ccff86bcab3f38bbf3f06f7bd6bd6c324 fff1eb7b3a6e85f22fe1cf95d3d7e28b2c750a3e711b75ecda1f21279301cd7b d82cdfe7dbb0d0d15a39d392e5529b61256cf6dac2ca0c04f10c81feddcb5502 1f7426796d532dbe452a65916e56583c418ddab1d655dbfe9e4047d5fefa95c6 acd10a2211b93dbb4ab82079d09b712f7060980023a09ce67440af525afadf04 190 e0e5b56710c89b6905912b5d93190d46fd14c77416acd56177225901d85f160b6f772504adda9dfab49ea1aa2549be7f7357e8c57fd4b950a051f1a448bcc40db7bbf6f8668441411c756ae84cbf1932c95891859846cc181e28a746310b1807139982afc11cff2962a9410528a4c73144e56109b56fbc55f07075ad7dc91500982f633d6a0a1ac393ab8566266e05780f949dce7e3f438c29b63d6a05b69d0c6c52564680830cd0ab643cd730839bf5b4a3ee623e56dc927abb9a322146ef0670fb48c4adf0a26aedfe3a1441808421022c9974e3136097a07fbf2b37fc700a557b7a68d8fd39418b74499ddc7ffed68dd834da6af967e17672685a06f255017e2eab40f67985e0a3e787d352b75a1ab7ae983381ec1f42a40bebf0e107f80e5b42eab4b8669072a7bf00946d8890f2e1512645fd1885d845fd64060ca9e30c6179f5a48ae2377ad79765a25d458076862b56f06aebcf10bb15f634dbb86e0b79e0aea1c5fc1640436b9d33f97786ac3094feaeb2b76b138b722e978455c6085399c288f25a534bc40d39055c3f469780372589b8db96721adc65fbfae41c0df5e758369ddf3a20458883dca10e6fd1ef5fa3e19012869752c5c30a4d022b0247e585ecfe5458932c060abb6165803952efdce7c0333bcef3823947f00412028612597822cee407c27f4cbd902b8dde9cdbc8ae6630c6eaa7f154b9e9bea60319bf3e88892fe67a104217c1ecbd02648d861a44d6c128d55c56acadfa037b011dc6201b4a13909db017475218ac303130174040563a855978e883582c1ad8095aa23b1265d9e7eca8434455649d4e6770b445992fe368b15abbf5240f318c0adda4d6a8f06ff6f89328d45fd772e6804c4658567489b5818a1c16c241a4470dd500e3a9883982b9da0522853d835d7b411785c9eff31494bb89af48c279c505a2e2dfc13aeba8ee39aac52038bf1571c79c9033b269c8264b39a616a85a50076faae678254409888f5b1124866f01f3413dba6ef86e7b77d9336c0fe01794032b4f1e048288dc1dabbd94b0ee7729eab754a0d35eae60345b1ea197aa1e2608a352ea941ba65864c883e406e512f2befcf8faaaff3c29a8cb39277fc1bde70f59d45a6e7efdcca8f35395dadc7db8c91e869dfede900888518e62e652e9be061a5401571aec991859219bfdff864e6d10d0e74c81530c5c856a0cce0eeb0000c69242dd3f8918da327a46909db295eddfe4b42a3b0d229809186e57f4dcbe050818ae303c1e2124e11b949f6b0fdea7449776394447c7b807f46f89974dcc005291af72b726a8a2eca3e26b34dfbed3bfdc372de904ea64b88129a2fdbaf3002a8abe9a17038aa81120add5bbb856677ad40622d8a6a0126c4fb0313026cc0c055fbe3230ef2b290ac14c9ff173741b008a6fc17c8961a4a431bb583627010717403319af8a383ad64d0c68a2c28ed80a503ea473c199b49e06d1f5cc056005124ef390367e389a6ba862d827bfa0e64120322949f27d5d3522a4b039943b04f0bfd20b793442f74bd2781afd6bce8708e41ca6aa9b0894d4b4480e5c5929090874ac770c68b5ec20acc49077d1e512732b591ec7e7668d8acbdb5f4a3bce056720f06026fa04ed2a8d928a6a44417a983dcfbc28cfd8323861d2abb6a268018b3755d48c49df8e7fa8bc81c49618639aa6d9c0eabbbda56b5546e68bf0bb0aed05d51e59de326c34eab6e5ad0e6d6313b13a572f4e81bf49852b7c6583460c43153fb732723913d66f34f0fbf9f2197fa21c0b5736b845c3761f3ab6d71c0174b5949ee5b0e8e4c5139ba340ac0a874b3408b6ed930a097bb4c528706dbd0f2bdf376087d3ea5e565537fb91d89fb5c82e34edec4de79bdfb6295e1194630d3e4b16ffa9e030335fa329d3de09e3d61a151b7bb4f7865fea02847af6b58c017dd5d09ea2a92ae2c1d146793ec17d82990ed31270998ddd8f59b6220527d709b640e8102d3a1b3817d3d33e3de6d12a11f66ba893b266f68744463fdc21c209c49410774bb59de4fcb2b496cc5ac85bbb99a68844618b9b5068f2e1e2452208acf255c33d8a9be21eda174c1adcaf61a08a4cd19c9bc148a85f78e9ff24030d492017bc46d829aca317eee3f82f1a5d4f48e99aa17efe065c7215a656e1570b56088257b444966a3f257d692aca91be53b2871e6638440de6bb8f31e469b8084d9403a11f219d861c2cacdfc33b35938181d6efec16620b2f56662a4506540ebdb6638648361d0c46d03ca92969a087dad38f95c6155b3f0ba08f7f972f520fdfe68848f59bf320bac3f6fe8f0d4ba0ce1e9382694106a5ea6606794891ce052031e7cabef2b11d748f53b635db2f2ecc4e73f8563c55399daaa6bd2ea7570beffc472b5f4cb53231f2fb4e3f2676ff6c05eda6d80c76efafaa4d1c770b04072d8442b5dc23f3fefb0810861b1abddedb4a604f0381ac0ac3874401f1ae9f04a5480976abbdd70182ba817cef39fe7f0046fbc7c70f37570588affe7ffacd080c0741c25bcef17183d7cf83cbde7d8d0c9b0fededef7a924e07b75ddab0df08ab25994dcbc003c70d8b7c2d56613f8bc6f89bd2cc24f5302c87ad9acef6e0080eaa548b00d284a587a5d21cce894c750cb2487212b97a839c985eb0d71c720879227ef868aee3c57207a5cbc5b5b2cc7a9434bf665d11177c237f4b0f7bc2077b9d7f51e2edc55bf66480afd0777644c287e7c562dbbaa3682c868d2681ff00fef3abd2da8266689d3b005b1d812f55041a65345a783621b5e399b20a33c00719ea615e443fd40e431565115a0fda5aeafae37f2bf622e3f4e74c456cb3140b63dcb1523d841413687be06b0bdd2f783ca208672193e77d93245225286dd207820989c3783c5c8dcd6accd3731df33fc3da5a9ea4cb1888fd9691ad0818c00bf9313c27f4ba9af58209d6254bc7db105b3110963991be8d9fc2ef396028100c592ac03d67a52113ea59e9bee05d2cd55a3caf55aada1405582063357e82a7083b679d947f0308a9aa22fa78a348a0c84e1c27afaa0f49259ea86a72aefb4206fd3439199437e5219b9e3f626389fd19dd779e8f260646ebb4079fbf3f9dfe0e47c23d32e51eb553e411ed708d09844e9be693c97b1f8e04cfbcf8864502fe02778c725e20a52b1213b49b1908e63c5a01e04735a6aa633f149b53049785dd0fa341f0a72003e112a5a25622cbe636dd81bf5189616ef90197a1f5cee5ac0f0c8c09dbf72d2cf6942fde5e7395be69e97c9a9a831c3a90fb3020c39e2042170cb472ef176d7f94ba117c5f81fe49adc7fac348ba27fcb00d324197c7eca4a504ad10899c8e68949ffd867990984c1f333aa965feeba8ef4295a844968117e50c08025198fcb4e0f4c3c7c0bb804870e8c2d94c80898be9bcf9caa70e62a1a608801ee46dabb9844ea170fcd7d9d2e200cdfc337fc01b3fc8d45d95f39c11d203bd747c153b48a51d995ccc7c545c3c2eebe79e54b6a99c7c81b41809d748d209ddf36e98950b3b254f6e500524c276342764aaf754e54c3ffbb8cd3d6300b90c6f01bb503680db4822d764611dd19777244eb6f0e65326a514cb5a4594b45b07afb9dda3f4949842e244af88db19cbceac5236b29dae48853c19d2c5f7b7f601578f66701d4792af936a8f9d5af36ae32f66c04e19d2053c3c618144ca9c9d030468fe5be2d4bfd8946bda43ba42ad3297068854d532a5ae30d9069305ad7209c80b0ec1c3c555ecf8168c2d07c108ced64554e1dfba9c847e6637b36a3cdc05c6437a8aa793887cb3593cf64e58a32ccd3afe2a56b423bbe1316788084f6b0d5f592cb4f04dec5fcec736ed25c1e494452165d299deacfb053135d23940fc086f43906197d023f6af703835583127e316c4ded2dd4f2905da84f64273e9b5032db5cc85e3239b363305a401dd5ae7b45da846adcd7e9b242ef050e76639610e0dbbe40247ca29feb097d5da8cb83e3c7d5ca44a87daefe25467866282b0270ddb175d4d8b2d58a00e6d3a1be655ec920a47ad2a1b6838c20ae5fba3b85d800961b591fb9f656da834f2ed5cfc4513d3577d2a3e6dfeb06d9ea306642f99b405ad8d0ecc1d7b6feb92ef5a0990c6e2ac6cfa49b5f525bb65cad4fe7093d8b7072c3fedef9cd270e833289c67eec91e8cd36532306c84745b3bcba4e26f26a207e01c97da39f5c284271b83db54b7f6e0268b9700f83ee8b8923287499b31870621e7384e37b698a5a6e0e6340e8c46cdb0e7da7cd6b04042aee93e282bb63a0d86864900277b779f949f679806b8e84c62e5096206bad213c86480f7110d1d0d57a3ca9a97770a5be17a1ac97ad7c7bd033f7e672da3dfab63a65d3d8352e607a30bab6e4101306ae2b1aee6c6827e60aa2424f6ee7dec2ac75c419e0454690b1ce88c87510d00e01dcb69eac3808a3df2cd3c4fc166fd174cb3f505f1382408c3f644ac5ae85829b62a7743b7b927fc7e3ba77a8d3a9544da65055b07f85506ab72b78e733fc115733554fca7e1f72e6a2b6187513d8c2f8101dc5325488e08de8c01266473fb088de76fd9533412c321d5ea7fca27d3d7a86940e3f861950e3a3f7c20bafdecb6b1692be84bd7fab818b1e64537fac919bc3b4d8ed91f9604ea427e79a750cb7a62c5cea77077db02628a55700f3256d04c74c89a4eb8350798ad31fe813cc138760418bb7bb070d31a12e6f554ef0ff1001801074b6d510b49e6c4b7d5e5f148138e58ead90cf74a85d847e0028fe2acb386a1cd0e74f504647cce52c056f691445f8879e38ba016a394296a76c64696effe043d7574d00cb64887703991a0ad3e05c00fa9881aedf2a7dd42bb8fb0028c1d8bc80bd5100c07fabca514b38ad34372d732dcbefb185ce06086c0dbef0a29fcf19eedacd900a1432cbc35f0e70db1286d60b334b9c706156c43a79acbf6b60c686a4f32760c4fed0e56a784368df788c466ac3f42bd1183fc505e151754cd3dc0fef66be4083f76d7d1ee5c68301b0f4210e2112ac6e5160188808951ba1c27504a64db1e0704254e961905ce11326d87085d8a2b27e4fe2deb60ba6dd0a70f25641b52ae0cb27b2e81beba5a1059c51c232e84478b8d1fad044a1c2fd5913cc9d2f435590884eed1456a21f7a32a122ca17f77037e385e9bcfd26ab9f266b9f0e8ef25f502a8b078fc067a70996d3ec5979c9e866694940480324303e0ea9afe5fdbbb8700f0fd271e18f63b313c8926a825d8a7dc4e9264da9000d6f7c05470237b6cde0bcc33f51f5812444ba3a3effe65fb5bdc75d1a3025cf0a7d902af749000db4704f1fc3f994d991e9d7c898a19a9d03f9e265f34a8d7d503066d6bdce43922b90b753377ca54b7ff031f5f177f4aae7805dacdbd351998a27d4213078c568b8a0040ec2400665e35b4bfb9b713beac4592662535180d4275ed7659af611f876c0be7e8ebbf2d4eeb999a2dd6b4a5cd9cdab39f9088c30be0200a164892d5c157023ddc86653724953cef780dbbb150d76d8efd3f6bde2d26d3861b351f13b9e00efefd79f2424b143bfe7f0d3fdd346e27de4de2fbc6f4a12173ffa68449d97c0cbb859850e7303e597bccfc4b372c5ebb2d4b591088b98e6c9db0348712261b0cbc87167912ae868e85ff1008adf3ab59b4a54089294585cdee5117f486c83709faab527c50c415d26967101e613c25bf0c9238ce685f99c6f83611b72d073a054034dc2066fe5216a887e509784c9c6a794f86bba684e345d77b595ac37e320b482fd755886c6ce4f76c22e73c1c9cbb8e4633f6a97882d5764da0319905c20f5e110622a0157c689be8b35ec4484d903679981ed0ce293015a2ab6926a84d0b7d91695756124810049fd53fb6759c4c15302f49e75a73625ed1e43e4813060802d1aa9f4e02ad255a200ddfeb7aeebd1cbba209b4fb31ee77c25808df013507994a641b3b1397cbfb66c77e1a8b8308e35baf1bb57c4c66e687a2aa878b6707c2ff0024c004402bb0680fe16e27e020a33c4b8b63187db36260f379445d940afd90d0b209412b98d1ff3dd82504a85c1731e1ca912b23ea491062e441bdd70de74ad8b574cad5b38c740718938b54072c8cf1e6e2b0aa840acf4ef1e0beb104610b337feed6d95ec83ba94d557a09f808494eb73664518f47edddcf1ae90b0b3d07a15529b7f8f38489b57826d7393219a234365917755ef5bd58c5fce71504c584409e6b661441d8b1cfcd274214f448e92e3dc60cbb1c536f0463770852077e8605756a28056ed72ff446952a3634ede88d13f6cc3a0667757862b5d81b09d148d15844eb504df6a682e4e6cd76b8246c7edfc94c7b33e1d24c558b29510d5fbfb9eb946b4f9eda707226f3da34b365116cb953e1333d44219a94ef4d170e10ade3e9211d80eb971ca6b91b214ed168a8e29335228e6a91bab45ddf08790f6f4b428043d21eb53371544d2d7bcd6ff1a27ba7f384db5810003e7e73cfc107d40167f4b7992df9bc168d9abf68b495460769b84767869a36cab441c0255b0d48f2b51f729392c7eef43304cfe541605d34525d32ab013a3a7817f451bd4a056f7c4d21c56a1618da1ad2fc7e379372213ce4bea71c3f18f0f579273ca9640405d499b0d35d7d410b57e01182b59911ec9e2ca7fb87e6bd4d9bd079c631ed02484bd18ad90c09aaf8670506373e54544c2fac82e891b3324a1bd1ef996ed209be20a5a53da64d8b1c3962f268f96d08f4b81e3d3f3eb756560d4e468a50430736895be5ce333264aca116707b5d200182cf3325808b078b3f6dd1ee20429d09610efcff54684579bf487675dfcc11fec86f6559d1da7e8e12125fd5315b910700ca2573dfdc5beb5862db5f88ae4dd72016ca722218e9a0f13226448fea5a0c0bc7ca27e3ffdb2f2f7ff80a8952e0871b9070e2d3d0b4c466ed3b7e3e146c0ee97b85607a2bc7de7253fa5bf1d5518d7ca6bd92a246502710a0b3a13bcf7602c2df9791ed0744c75fc227bf74c38613e1177d9617904a244eca2726f824040ee1d2a7c3d8e5d430a43ac409ef65fdb4dfe4327d41f213601e8348384221220368593d426b0a33d4933458b1c207217f82cbcf8650cd0161482d69e66a0f810daa72f1efd3c03241dcd1e75c03da07b79cbda10e06d68798706c9145d82dce0fb5502b96ef3eb5b47d87e617174fbda95a7690b34928c8da1a182ef0933eed05261d3f1ce448f4f342038806ce3fc6428df94bd4325234a2f45299b4f168450ae38f81af1c5e128173891e021d7a87906811d2c688a8c188f10cff72e3324e0d22095d9a89a30ae570c3540621ce1f28e3b452fd31d410b7bb8a462e2839cb06fccf49086a4d22cda1e5f023d38e79cef825a4d7d9258e071bf0bdd8087dea034185ba7e86b85b5c902257d1616b7c94960b64ae8538880bb59edde568ef9208050f0a648bfebb15cf919e4bc29ad0ede506d8121d974c56b07b1f63759fb7073b7800e9e5bf895e7a825e61d4d1aedd0c9460acd391f2949ddefae69f451d0b3e986f5f8ae455df05a629f134e9f813c888765cf95046c6b16a6d505cc9170eee008feb0acf2498583a9be0d00d613a1fddc81b8e534185a79d7157bd50ab0447d0fdc6368944dad83e986f1e4906df1590d71b4067fcef8fa6fb613fa306042dab11a214f7cb3e9b2373233a7c7c1f9a1f1ee4f7158ef559ebd4965aaa3e0d5e47aa407383b97a8cd5f13e786038e92d900dc84c86321e19133c261af5df0e09a47015c1e5aceefcfbd9d757de9d873c2ae1be3c36c5db5cf3b797d8d760081ea48e1ee12f8b67dea697feb474fa182e2060c8b538e16eed5de732d251aa0a4aeb90e2eccca92b8778a0e1f504dd4d75ad6e518cf6906d60200879bff98907a2325b509ebd5e5cd3b53c6e2397b22b7021231ad881dbdbc03365058a572504b589295e9b33eee2f2b0dfbd2482b00a5fb6dfe9dc8d54ef775880dc11674400bde795a8e574808ca5ee84a936e01d4acbfb9cc0bbd86cf5bdad7f6e090b020085897d3f628c2534362f770a5d20350589be62f77efbc7da311ed79d9d2f490fefd460271a8addee32b9fd4e6692234beab893bc3a3613f350b091a84502e908ed83fc164ee45870e27675cd8df3707ca09a49c26b208fb5ee72b3891a9593082c2933aba8e0868cbd1af14e6fb72b36af8ba1ec6c10551272b036fc6fcbf302845b3440c8d8cf3c079f368a6e653b07045b026c54ef7fe987daceb4725f9c00f2bc1bd1233574f93914bb3c9042d7c4b0b0c272ddffa95e096eb7b64441320ce36904b5b07df38d1ef9a22ec5b183fbc3eaffcf999112a16c23b8fdce5c0704eac81e503110e59156fbf64561b857cf39e156476e29ef87f4a6c08640fec30b7faf06bf4a9eb1e19afa39057bf5d2d00ea352fa0681d64fb7b8325eba168d0dbdc5d283f631b0c55f575f76328ee49c99a65e3e7a0d329d3c16559d1de4a602cc02e44f1852631e7e190c10a70ce79fbbda7bd8915dcbdd7ac1e23f6e34a900ea22a7cab6b2d19a6802803fd9d1765b8067273eee4b80f603bd701c5957040f81e74c0eca1b183d7e564bdafc9d460cbeaa740241f72d0eada097aeb61fb9082be81ba42d22f3741b5c4d28cc59b99be2b9b0485acd3bff88dcaa5cbb15cd0e91f601ba0eec61f606d8c70b87a0fd02b769619da91d88d9509dde0cee67d900cdff92781a293fbf52d10fcd52ddf7089c3a9ef8be56837e52018a7d7b0d3c06c7fdb183a424ee4e38d59cc7ba522e8e2fb13dbd5a27d9e7b9df116e97bd860aa04f8045d8cdd10ff8a4a13176f5bea2ac1f4e699f12c2c6f6072d793fe99302a4376e7e54c5059ed5670197918eef15f657f6996cc3c668950e5ad9a96b840c836771cf1f28ae03393b150c12273cd6bea973cc4d7d8599a1aa84adf3bf4f0bbc81b38cb8b41dadc99dd5518c8692dc669defe87cdf3265fb97a8d364318a0fd4f37564cf4aab35de09f4305a3ccd12ca7c647278e5442a8ee61b1eaf9c5c0758d015bc699791c37508ff52835e1da95f55d55060c6dacb4350c32942e0cb0d2d8f0e1ddd6a393f8308f649c294f3c505d429582f66b676ee50873f174c630c221502d922650df39c8454ce394ccfb9df4e1b5563ad16f3ae2615fc6e33e508818e79b782b533d1eb5d79e929f1af9d38bc2452bd285e268e19bbfb2a99250d760a50920aed383fd1636e6ec4babb5c1e7f0e4beaedf75281180f1344934c056337040d33b411f4459b68020a9e8cc838af1e4f027b9f5cc17074418d082a0f525cb684a6a54c6d61fb3fd404e8b8c20a3c97802da110b58087253065cb150b93e3a27fdd2c89b7e269d708565354ba73b325d112bd1ebdaf5219e000742a03270205c6b573e06b3ce41c65bcd72574ca79c9a6193c6e98e98586672bcef50d731a79df35c40b007ea43a6494c804614f12b5c0a313ad9f575e6e1a13ed3a0f692ad2ab1b2b1805c074c4512049d58f8abd80dd76afba02fafd927ad593d60001bbe5e795fedb3d5687c879953046a9636b8da6e5679553b05871ab1394c0055e609a0dec32f69d360d96b1fcb7fcdb7be722232b34c51c618475bbe9059308de132a9e652a0cc1073146ad9be58c573d9a777b84329e1ad3ce61a256e05c0f8abc4803b2012bf2caa0e00048d9e3db981241d4802aa39c75103e8a91f3df03cc69e83b5f6beaf69834b28225c80a58ee43884ff524ae4b0b3dcc18f1f675082f12d55d2bddce8533317df105b4d8dae3b14371d13ff3c86669188ff2af39005fc3bf577463f492cb6a016d79312365111f9f3cc1cbcc14192891a2d6ed860064acd4d129e3f334c96074efd67c16863e93bda32fcd79d242a12d666a3da80b2937f1b966baa2a853a49e15a427f0ee0adc14913fcf7eb73743282c0a726402964b97d68c45baa50aa961508c3e430f44061260619c51ba9d7d0d67a434a4039ad6b26773669810af7b97fae7da6cec672a644dee16c308a692f4dc31906b058b1ef2d137e317a87761c18cfe7788af8de1038933f3f38232e18aa5165fa50aae0545aa4d5df4310bc004155527ff40dfbfa06a7ff79ca0c4978e058bc57f0f06ea87b9a75c95f34399a9300dd27b3bc379e1178caa6bd445a5b08f7e8cb106c6e81e9d06fd2057df5551e8235922f7a7cfe9095198d40b686a7971be7c7d058e65bce59cbd2e5ee05a8d45e7aec14cab8b5849ea0b6693094274a5303522089e2a4f6e79ec1868e5389206db372859777be80a10577a5d60a472b79874530a5c4bf979daa7c0ef9eed0a296681fc67d0a02419e6c9ae2053866b6ed7e92f054414e3a54c8df51ebc2ceeb10b26cb10683145af60f395bc19bf40436f128001e6af1a151caf5d1e9577a3b85573bd8ff2fff447f4a3ae99668a196dbc41070e1464a1a08b018c9763ad03ddeb6d6b0174844142ee62d803a7a3f07a68f58805c1c9404f12a06947e22fca1d0ad78e8b4480cb7b3b517a8900eaa66e525105051e4434976348d91fda947e0887d888968bcb4296776e8b5ed5885889da06e90b5dccc745e24ecd6de28a08ba6fef685ab2bee8aff6cb2538fc6f00a2fc08330fa6b357325eba9797023711e612c1e56f1387fae09db90a1b4a4054794e9f4d0ae0a9ec6e46587de68b6203eec353976246860faf9a60fc88b3f7c4191b6a3a056bfe51500bfb297c3e2f4c371aa9196de46c2684d1388a792b6e605034253c0c0c38e28498d5a6ff52d78c62e9d40e05485a0febaba0e2b37fd2b4afeab721001bc7d0925ba6417c141c5ccfb5a424438649cd70d8a35ffb40290365de01270551b7dfba790a506e528a8282165809648ad15ab29270d5297ff13497575b170e214f2fdd82d0d6c69cb32a457f2057cfab1d8f159aaa1a99c59ca17caf9da8070d5683120e5e9618cf9e7f03e198ecbae43127d67c7a31549b5c5c978f7704031f101fd1ab5bbbc68f5af2a782308fea09bfb51ce4d60a68714c920bf337340e3bca9745d417541b02c6042ab9049359a497bc5f48bb923e05748e1f8adbcc02875bd792eb643ffaa485ad848a32168c87a4d1d4f95414b07a7fb07c74bd51060a048d6932c2a38bc827d87d1c6d9cb479c2d1049665a51f39799f5ca0d15d0458ac85a2ec8235cf5077b049565a678eab6c523531a15d233d50c9c094d3ad07dfaffca637a72cd96ab46180a0ab47161bec7ed5951d21d60f800ccf1396b20b9e3d7bece0a9ad9673a77d95210a40117c8918ef62be61afc746626863bfdc0481c5c4b531d362a625da44120c0ad73bf452ffadbc1391d3c66d12a5aa0d430112ac8a6e2ab872bb81fbf3061167ed45979c76c391d9f7a7197b8c03825b660c8886c9888a17a622272997746905ade13e92774e5b1768e3875012a9d1f63d04e659c0bdeafe671f6ec4aaa80d810fa1d574fb7cdeb86e929e42f0f5f92b36018397e5a0ae76721d994a32da4a555a8e0464296f511a8f9e050e7d1804ee810afa5fccf2ec13bcff5cf7154fc7b5dddccdcb3cff4aa08e0fdeedf6d53cd24c05e3fecb18dc5526727c4202d669e7d6fbcd921a5cb6dba90887227f381fcb5f090ff84c43b7778e47bb5b8b1265321817f505997531471290766535624c2acc099fc28e97363d3766bbbda47638b958471c2075d48d84a863f930d457c5e76705fb2a6b243bc6929f2777a13c6994332a122f003eee154c24fd60f971e0fdd20ef2871ba9a3c7fb2bbf68d00388b6b26e89ad46acf4ae921a1a709ca9b431510634805f76b1cf51809b496a79fb7069a542c05d3fcb107e1f2632795503a6a30c5c1a28d9d2afc8b54591df4b6493b66384a4a6a0d900daa9dfa56b407891270824b52b6b2abb96d3cf61d4aae158bc62c00e0a87d2c2dc9a797b8edc1a3035024d4fb500efd5fe823a379a15593c8d67993cb7ba5be34656cbcca8035f7327003dc1ad2942463e474eb6b9389ad1e6803fdde73925e7f8fcf683d47d8157c00c50239a1c4d207d9621dff960aab87dd18bc365b36a13b80d937a809c3ecda4051a5e5df9329d89b03e771a98ccf4833615f5dac627c7e89aacffc0ba065eb7005d542d8d48ae30766bbe9043ccc0256f7552d474569bdb735778d81dae3e32046e3a710f970373195c12c728f437a76d075ffbf6779a0fe7271645f08e37e7094a13376737fbd66fcad8fb7e1cc2a9a02ae25c66e0f03d6b29207f5b9c51a5067ff044552a82caa4260a34df846f6927dbe34749af17cb57e7d3c1b26a683c01136d66869da3419345f3fa323d7cab08cc1ae43296cb217684cd0242acc41b04246ed22fa78c7b83200590e9d4ee706ac36d5b764cae469022ec200340df9202985a9775b2c6e449e7baa996f1c69015a7a4381061ca019807335ed8c017e206029731585d6976022f7108dff3caed5718bff56f53ba8f109f7ca24964c2df01f10a0061a61b58da384953ca0465f4f0c0a4b48ca78f8b2ba1649bbba84d540a7e9d0f19b1250de23973101c0e4257cf5b91f1d8433791b4a6450ce77de5d001a1cf52e0a728bbd2df289a353ae8aa2f4fcbe78877251bcddcf8c189d14a1400bd4a65d1546ba357d1c46199ff7e4429cb8b29ecd446cfb1ea59d7c693d1090eb01c67e6d7a2384835e71454bdd4f6b151b27388a21a536f9133bedbf805110e814081341022f0e2a38fb646f1d9307978cd395a3d69052a427f40dbd41af40e045a4475d035c0b03c1a0955a91d8f691979afa99dbb9c0cc0d5b632c62f1d0b3923d31a37e8dd56ee3b4e3a6fb8ba89ef135ab5b347eaaaa72834e61cac320f6e72013948678e2858f39d29a79a9f0d89abf766e8f73bc03d0dc48aaa5495048566650dea62bc8a382b921807b5e602ce1b81f60d7170c43141ff49b848b504b17c5ac85f789fd9abd0925622023b5f03ffd409b57f5f468d5411493294a001d2da9e4dd77a2f730bacbe9a3dfb624a5ac8faa39377a7a1eb8d3a2eb5742004886dc84967f90ab000bcc5132e7487ae0b13ba7c2b226d622505600be9800c0b32b4de820e742c3358e75ff4330a3498fecc808b31a255a1cd1413a478cd0e0e985dbf21b92fb2ae1cdc19a7240e3a646a53102ce10c5e4c71a24b637a47bb037ddacb3e84c98f2c9d6d9b26d02b3a270be18bbac13d58972fd8e1923aacea054f7a31db8d61778d49e284cb03eb1d82b0e6280848ee80e96e7e3cd915cba80e26c8c2a6af34ba6867940e58f7753e6d7181b1b6ec9d9bc5315108d43e0065041b5bca8b38b5d4c55cefd44a9dff77d440e76832fc951f376afc47e318452b0d1a0d71f26b57af2b7d2cc77c7f410b48f8bce9e265c6acf07d188d99554a4301a07aeea9d979ecf35398ac4fa3eedc02534c50f8e6841770818dff3225958602abdc21ad474ebdd429a6332d803aa9bd3fdcaf19bd57c58b1e7bab9fb9fa8f0f3806b837c259acc0d58c6012a75314054c84167a56e057515d1fa8b2fe5ed500cac8aa19ef1878d4dc5cd9f1b489a00754f60e95bfbb4d4aed701f70c9bc5202f19357d3ca4e51c2a58a163e2d715fff10b0d7288bc557d45bc82cafc2bbf10fcfc2986b6ed4e2113fc5aca9a8f1e7ff40edb017bd874757911d8f5c96a9fa01d7f464d72a2a80634f3655eaf675755fc0e81f96a55f994bc96d6e7100c9970fbbbd7e875fc3588162194519485476b1aba3329cceca66c7697a15a30c48b40eb85769620eec4ed22db9ab7a4beeb196a94e4358464c39d7df59e8fc4852f9012a68ac10414a132bbf5ed54c585a9ae8e5d69414b4e4d8c044170f369efc0402ef1067f385fa6a6522dc79f7e1272dc2d8817e326a5dbe8183e4abcf6b33a4083b7f531f641e90c9c418644e749c9c564078c0cae8150313f0056da5bade9a0bac34c6aacd391e5c7eba8f8b9c9f5f562ad8a16e3a92c0f1974575d0cd39a20d90f7efbfb164798ddc03c0312cd3f7fd69fcb880ad1b5e73b78f8e61442cca094322c42c27943df2f81ec138abd29ceb7cc59e703ee881328e50f26818f5870e7e9118cdfd85cc34e79965750d74f7e4de803690b346395fa634f865acce780c8aa5289c8bef404a33d345ec0df8fdd8668775ab09d7d057d05a1d8bc103ca096e53ed546bd808915900746e38ba9f118fdb43e768c0c02d9d21e1cffde0c00953dca684886c45b3d34ae06b11434ccec98b85b33195b9ea23a7d6fef2635107ea5a6d6c77ee61e33f22ca4fe9cd92e00656439aa3538710303c489fadc9a5043eb7ad717d4d81574ce32e83e775b67430ee26f5838ba1964b810315106d7f05c1bd4cb51f5c893fc78a92cf2e711e39ae74683138a0dcc0173ecb930e11c8005002a196a236963073c8e1026066e738883588bc04e5178a04a6d2dbd25696077a0e080df5d40e5d3cf26f894fb8eec246d7d0bf0f1d8730f64c887fec31fb0435d218d4cbc5c42e68a5f7bb2ba529dd8aca08bd3d3393f33a3940baae3e850495dfd762cc5feacd8c146567f2ec17f86ea12f79c342dc5f70bc5b123b6b2c0b28a339dd26fd6c5343537f788295a16f23e43063424f7353d2524714d5415b0f32a2f87c9bf591ba1dbfaefe2f0e06b60a7e8c73848216ab32a335ab09eab90ea86e35405a07ee026fc43d4c299b7d158665ef55b5e31fa9a31aa149144aea0324cf58148ff4122583868123edb10517799f9a31a3ac6e6191b17927c9037601da5059c37d2e37cddb48643f25af43b9ac5e78372343a50138477ab361c4e90f1d83c10bc23a31bb32e5a2859a32a323673c4d839bc457a941c52f5869b2a401f22b108839c2d02f51cc6779e577473969fdc0a9e1505dcdd45a57dcf9239700c2f7c0931953f2d6e3d958af895d71cc83bd2ada24a287574ab9ab7b030c8406e4d80dfc5fdb5b5af3cbdc0925926ae72e3d1f24111e2ce4b08105b852e6ad096077576bc8a9ca5be6f43e8566068b7f3620234f7a119bddb6b714262321eb0c39fed73029b828ae4a0fe92f6d0dddb49bf7afdbe251107ccc0f6e42b320aa0c3db8cfd704111ccf7fb57e33ed71fae0f866b90ecf090043a27c0630f2943f0d39cda3158180f1f8fbf77da142db4291fbf8657fbb0a2153b1b09d5d9a778307325c6eac179a1bb6a54db77f33f0a055ac57a91956b9f758d35a8ed6d5756e051eefdc28cfa90541c8894a25c6bac132f50880275097c9b402b9630006b33b0dc3904d2f1f0b5ca838725911b227674e9816012386093f8b0ecd771bb615f4027c5e21838b6817cbb3335f5815a44b349baae068d4e38ba52f57f9831c90860e1c449665183f7a22a0c54551831c02ca83876f9f57c860f4b681cf63793fb8098a518875d846dc4fc9e2a2304213893c9783dd8c743bdd80764743eba8b2350f2e59c48cdd26e6d8cf8e4d9adcbbe034eab37a1dc9ba9040a1a2c0102074010daf98f314c905bf3bedd1468c4ad576e234ff478412f1210a2ec2485113a3bf0d36552b1cbc7717179728abd519987c011b1318509dfeb60fd42c706a77023b05106fee3a72395c528f72f02fb3dcb0fd493f87c8a4b356989147ebe416784007a55457089945f608435aff0d0a2d18893fd810a4616d6030270545436adde809349ac3a9cf2c927ec40428614af36868d14d627cfdd93bbc5f6cf8a21cdcda0fe9874ac773be6eb5022ca057a7f1002b6b9e4dd67ae4029bd16d6bfa620e7e0ba70524683c7ea28c1128ccdc8ad7ca4e558027fdc195607aa1e2fa3cca509c02dce1864f338b8ae1a0e6c4d20b9261755c0649eed775ab774a8dbb56f82ea70b4f1d4ad58ab8aef1c222736d42b8a39be6353ca29981119a1a7404bb21d4050d0f698e272311dc1ba5eff85d07688f190e8709d008b047cd44ca90f716adfc00f345f2d648ef2acceed6499bc335082b1b7bed72b9989426f01f2112897a1d007af110ead6941cd742ef1a0dc4c90963407fdc5f10d8898acb21be43d275ee0d31737d92b33fdc5cac1ed8f5838055fb13f467c8eddaa2294900fc1cc808e40b94d6ed317a76f3788f0c857ba75a8fc6ce752ec3ada66dc4302f776e6cf8ed0aa7b383becdfedecbf608e3df224304f93444e6cdb936fb148ada29635087b70802eda172f60ec61a883b9fe424274396c919f50fd07ab0754c8170a7ccb62c081ed8bb96c8381cb68d3267bd6754b6995f69f896151f1633768ccdb30ce8ae082b337d82313bd5172b7cf3cdaae73a08fd4f2d26f1e96f140aa062362a02e2034246a8fbe2d5ee0b6b82b15b6caed6f8f54f539bc3b593b9d8ef43a7c1574302fb9872aee45ae0fe267a22aee24cdce5deab4e408919d91a8b53e75d95473b08c82ac4a5175aef72e5ce6d834c401c4f9413588702438e95775aebc970c95308912b3f2179764d1a6db3785f03df237b745f5356c5fb018801b42e74ef6b830258d46c290ce7f3d619d75e5110ce7602c32dc1541bb74e94aafea42f003110067513d74aecacae98cd1363871626668d3575bc70a8c05bafee08b5df24ccf30cc20cf10a3b9d9d01d88a2ec9dafb733c077fb90cfaa9848db658981188088b0208b3faf042e2b35918b6e8ab3f557b9eaa11f0726f6c4d672bc43c1f61be440f6989955bf71b92d45c9842666e9fa39f6bb7450355755ad2d05b6208b4ea540bf516d02a72db654b8ae882488d34c3772a63b121ad9881db19de51a6b11c0901874af81c08cd8de93d47cbcb3fc4faef512885293f23db9c1a78270b0f800f07a37f38297534629fb1e36eb31bb6457bfcee70aaae60d1f6c394e5848b12190c7598279433edd0e90eab560c442da49b8fa7c557a33db151b045ec941521f10fab4ad5a179924b52dae1fe703cd06eb83f1b4755f2f5436c8aa19117cd4419001b35c0b04653ad2308831326ade6b82bc05edd2b4ddf57001a3341fbec0f9307ed56a77740adc32cb20b7ff73a1ed20b0e11c860d857146de643ca1664a2b602edf49af1993946126b0523703f3d979f7ecb30a5f677b9a672118e07f1abdc08730940b4b8b2f7dd8851b3aa9a6c02894e90d3ddc1e4f20fe3be395144bdd00504ffc8dc8fcc6c3eed60d43eaea4dbf3f3614759b86457fad2ae4c3b0e031c0b54c44234dfd529514bbd76f952bf1512a6d84b5bab97a7f5390883de21aeda07583e5f699e8b105c3f1f499a86bf066509a0263be92c78d9794f3ad12e4b8e069924c7686278e35abe68e9e741749768f5ac5cff828cc74a13064c78c0556d0c76fee51b6bc5e7b8793c74d75e6bf10e86e2df13ea32ac61526f25e3ad85b80fe260f0e874edf0b7f62522209676512cb3f88bc31d17d1e9d981162da3651a047a8c006d50763acd5ff9ec0f83f34176055e198fa75442e9366999c5932c280f8ac50bef654479571ebe95c808f91410a61000508d1833b98eedcd29a96cda04ea28833917ac55f62be462c4a85a04033f6b8f1070fa746cf8299b0e75a1450fc20441c768a58a8297250b384d6bcaf2572d9a9b91c8b5cf3158c39b0fee800de9a77b7643fc79279a5dd6f25ca4490fe3706b8ea32fbfb4f98f0896a3e52f0140da4b5e7a9033b46a46ddce75d48f0c31a874c385e041647af11a47d659cd0518303b5047f6aa6fde079d652566fff924799293b768037db6850d64329c620805b0e826e4f171a61690cf92779b948b54f41a3943fc278ee0ab8479494f770086006ad414290d877ba9650d8782679246e0c53092c8b4120e1fe545206b0c0a73bcb1430e95a6ff86302047d5176196a24890d7d7c8e5da204ccd3554547b0abe99de271f9ce6b4256f733d744b282ab35ea86c6034c18ef395f7b9efeb290791dae06180a32c3b02c5218eae4ac14ce9c629a65fc44ff15afb2f50f30f6804649b4dbd8f7c746e09977f7ffb6b29b3a7e8b4aeec0cbc1f9db85a9124fd0809e3f3f05ea8400a4e4d58daf604b49cb51e901c8c7d9d0594fe20349ec633150b9dfa126d9f9335773b043a888f7438836e105cf31b5b35294403ebdab3f768046da009bdf6a9950e0735f88ac3d33bf1a8b38b109afa3830991e3e5a708ecc0b5dbe69c6be585527e96c50362a69404b81c18900aabd1512201207906036740129a050819c2932489c68976ebd621614b63797fec6dae88d1e80b5181fe66706ff0ec97149908b97947f5ccbd5298c2ed346176ab7adfd3788d277bb403b4d00caa8f3fbe5cffdb903d9ecceaf81e5db0b0151d6472b5e1c2e976ae5c89a040fffda036ed7228a7c40ccbb6918f270b227b1c821a73fca4edc92dc486d63ee004f1ef59f87f491ed3fb801d96b499bebd8a794f8c643e14ff0c0061486b58a0b100c33f4b94e26912b06a009bef9a6541b23311b865aaf1a719844e9f9761e010f77bf3f76c6c983f88d2e8d31d5af52899fc1c1d37cd879109781937b0a240ff7c791420a9efd7cdc75f2bd4bd78cdb73d81d3b08b0aee6228653bfc12cc908d72e70745e29e0f1c8e13067d1d02c2a680c83dbb8baf6a290fecb1e70bbea0bdaee2bcacf997408db98949ec0b36e29eaa190fce14a510ea2dbc6935daf0c01fdf17211ff4e74e7d0594f2d9ba5b99c29ca61a0a4b29c1fcb5035cebd171d0e43eb63200bfb73b7a2e01049a5f0935829c03e5333e158cfe40068f68ba4f80da446438ab8fc425f9a43844c085bb7fec6e5cd47f56b15d63ff26b3b79542206f24d3445cbc746207a9456d3626bef29bfcf8e67316fd2fdf65cc6864de8e000add13b62bbc801a87ff46a2a2773fdd883e463e1e34a73c6d7595f0a09b4ae06d96e3cf8fe1e4f3874c0df23324dea74668c5832403057eb4bbdc20c5cf81e073942ff1fb61d3479f0a1c0add58ca93edc7bda90e1198b5672802d9093c6a00905089c50c440f7dd9286bbdf24ef57a4714ac09cbabd7e6a19209b9311d6650ea87eafb06ae4a8125bb3c18c81a7519de252d0edb0651364a4499c19a2ce5602e6f101d0e1c5d4029e2cc94816fd3cc3c7cc19de8fb6795082d55e4b592d480f126b5ea3d12e0ca7b4856aff1707a19402580a79d5c241f59c0956c15c96a70fd3c54366537a68e5c689b934c1ba22955e65359ecd9f5812f9827f0507e7ae04fe6d660a566dca1d40b6e8c91adb94f3443320bd5394ecf9c41d4df136896d06f3068bd9ff11899e62cefbe32968127e19cb4bfe19e01d100c95f253315258084fcc6c02d5a9295b123712de898aac3db16be9ec5f4447ff6ba26558856cf80eb2b609cf6a37cb8ca0894e1c4e634e084113e536ad305134656bbdc57e0f74097101a8909d9933d8099b42a4a80ea1f1fd2dd65d1d78bdf67ea247a64f6cec05669d75f76c57afc346ddb6776ba53f41f65fe9a1f4dff9c8238710738121e006529e87db539acf9df114a9220e1e5f0e2ce25dc5ae4dff504ae3dd5aa7a81901a73e1e7b9d32c9c70d5b81efa57b6c259633b1ddc9ef98b9a00c7d341f5dab00fa30796922db48d929d731a713447927059093ca4f3bd9e2fc07f5fe4f873f0bbace7386c733fae904e0e2e528efa66c9e06ca5e3330fd980c41fd72bca38e06520d6f997f6f6bcaee71602b7a5ae2f35bb6078b6bf6d815179d32f723b8e40f4cbff32f1a32681aae630fcb454e9e0921921bcdac9b19dc814232040bf7ba0be80152bda1b084f32312ec0b33f0628101e5f2fde33ed1a47a170a233f988f0c5c4e7c069c66894d8ba3ed3cb9ec47d5d7010ff1c162484376d1595a09dc7e00d85454b69212351e18ba29afd9bd672867316b78b34192514ad87b858b2f5b03379979a57c3deb37fc8e437354956609ff384a5f9177f9f29899dc5cc3647403b4f3f92942633888f2ddfcdc636463a3dbe0a4bdf8b37682d4cfa2bc03a1af02b243b3ed11c7e56bcb8518d2af6dd97f52143b64d3e003ebd5da95c14bf5040d464ae3d976e7bbc143f87fd63928b1cdafcac2e65d5ab5a4e7c063dc576fab03 +generate_ring_signature 67011525aec41e62812368de7e56ad8ed15cd4845e00871483703bf9dcba31ab 819d1090586ddd1ec978a2f24412bab7d583208042f35c68d6ad5ec98752bba7 76 dd964f5695c3a008543c185f0a1b5fa461e9c22fea98d1af2a1e5d60cdaf6e01 d1b04957e8b634589c062eb1b743fa1cffb725a8e272703bc10f50d1f5a0642a 51dbe51747f44800638559a63971289e43845c9286aded8b96d55d982fa22637 81e0b148f3ce2bfb07971eb4acf845ea0b1cf1c08b27ace8b0714a78daab6097 9ba5b03511558e8edd7b3c0336d9086011c5adc81aaa03664841d8c62f1fd2f1 3ba3b659ae309970f3494eb0ec612a5cf70da1357bb5beecb2fe946a9913f6f1 882ea42f44c98b4e0d85af542d9de44ed889c3d65f9ed6d24c9eb751b640c12e ce38c8d666e28094548fdd3dd3a9e9706e0ab2c863d5e1c43fdbc0682bbc00e0 b0998d216a9ea0224668c114c8db2efa0a565838075f96126bfcaa22085b4745 c83836b02f86df9d9c8f753f52670cb80ec5b6b2720cb2b7fd7fbbfa2d838e5c a441967d23071f5a95a1f82f5e2ccecc2dd3d31bd1849d137c37e9415c01595f 0322b7bd2b2430e428c8f1273fcc36f45f97892b5572bc53163675abcd987753 b9e1f6ea22472fa3db4957c448172b1d58aa61f6048aaefb75d3c647743c87fb 348fea709d69b0752a6f382577e2149d83b39c5aeca6f0474d13b1d4627da825 50360c7ac3a214e93473db297a3e1211f08704061bc868bdf06976a95db2e6fd 8a5ed26f5ceb633b0e25b2a4410178c89ab38634fc36175aac9847fe666d6876 9b2690089def921d1d5cbf63ddd3f58b5d7fecb4ebb54b9b900032ef0d687084 4a22af02b3ee18ca29add712fb0890f5fe0bcd52848f1f8e38df6f38dd5c99b9 46b943bcc3d9183b473a4d522e4a1febbd713e23b7ec8959e5a4fccbaa9a4e58 ce8f7b05f9e53ca34b01d6a5bd63ee14991d7ba4e42a236a7248855832023dcd 851d02e432b19150a6f451c82eb384d730b0c3ce3c35a4505765785fc307ff36 7ede31e63912f8434bb525222bdc771cc1539e42cccf8953ed50b7bbd152f87a 989a4e49e2169c52b2e8ed72378944c7f4ca80cdfeede413096d6bc6bb481987 8d197160b9241e31906172e6e59aca990939999d13f247f5a5d63feb35218761 cf685e95fa014fbd3a7d23c9345b54c8918a82cf04519dcce9aba2064e703bf8 7b7bf2a667d37550e4e55a37e728ccc78cdb856082abaf80f30bf1b9c75805b7 b63b938e1ae69254a31620ed6db8a682a73755ed347b020e245209f4e5aa344c 8e1bc9db8e3ad41682859991867e2096c5e39067bc4157bdc5564c3391902df7 998290f1542e57fb84928d36aa67ceff21910f22bc8c3558a0ef10398fdfd3a0 f4aeaba0a6d239ea8a01d9cc7daf6ce0109d26aa92cb30f4456bc5eb2f3d6738 17833eee37eb03a9ae32973d56754808205ef421688f18fdce0caf0bc66e4f27 30b5341b038b23ae69a365a896790cd64aa19eb31864bb1638c08285909d764f de2d29581951dfc59b9c1d2a2a4ddf67919dbabf8a58651b2fa527c414a5cddd 0457828b3514870bd16433cba46f8738c173d41eb59ded65acc6c7dbaff5dff8 5c9fbb3ee625a4c846821074213e505f9c51d5358abaf3148a8d154cacc6d6f1 6c4485b140aaad6b9e994c7d2e5023d0940d85e19af437fd21f236ec3a4733af 88e354a64180b6869ca2192aff2b69fa306c43be47a4f110b85dcc5495f1c977 6a6a1de9b1c8cf8b9226fc675ddaf1a032205f897d0727829da84b8b89b22d51 78d1502e1cd1fe7c525ad2bb4f7c9f742d679f7908e1a2d4f7bde67ce95b8ecd b6ec7b175273d7aa77355401a3c36d43d003f6efbdc0a961564bad698e8264b0 b4cd90e8ea0018b56c069551b6c43f45d5e330633ef17161b85acd7418294d58 25281c2d7629d25ec3b0bfe45d621b5429c1588f2831611c642cc7dabcded2c6 6dfc0172238b46bc6b48fad9ffa9ca9e8dffd0667ef95611bdeaf212ecd6457f fd8836213387691d192f743f779da56e093a435d355426422afed7cd71d18cd3 d32a9bfe7024fd29b185a1308ac3fe06e21b181ac51ab2de211270a503ee93b5 d65eb25830cb331b5bf837c591ea4e4a350fe3cc01e795e0bed07d38b4f84991 c521b61b43eb63632c484c6955c669f84095d769f226524f2b324d4243398cef 3c282a717091456d676299112eee95a854a7a6a74e890c295071033c4086760e fdfa169265150e45aa61bb1450d7a1ff82a7f9f076bfd1ea5fcb3fc35b527299 139659524a57f89d2425bc842cb106d8c84c9dba73fcc03d61ef2b7e6ce2e002 dd28d9609d1d3e4f53c48cb86fb6af584275dc00ece5322836b89209bbbef2bb 139e90fd22032ea389767357866c7b2ee9a19d9637d5911e74556e89687e79ca f09a6690d27cd15743f95203885b89545c0d31d6f745a0c1830e9c2c613b94f4 b39a46aee128baa794634dfff8157c6d3971de45ea87b210a568b21d4cc2cd39 8f63b5d7703ce9dda77b5fe3a6569482d1a42a2a7e7aaa46e3f50a1bdd217e12 14f4e2881ee2111945d653a6c5ca978361671932c50890bb355f277be25d2a77 e29737b0d67fd4b843c907975e594978ece72d400eedeb0133e875cd65710c3b ea3cb93a2202ce93bce08902a70149ed46a56d01d646ba50c39f8fc122e19926 e60ded286f6ce5f73348f53cd99e4a3de0c5e60297be0d7f066fe19c08c13c16 77754e38b821d49702150ebf7f43fafb0889c05cdab297341578cfa18128133c 434012a532762ae1ebd6706d4740128e4f1c4b97488de8844115de50d7b9149f ce7d22e2a914b82c673b65b28172af3760540a84a45b62bde70bfd5833c33509 7af0361c2aed7982fef7782873dabd2d0ae6adc240dbaacbff15409d916a6a01 d3bebf533d2922ea2539d196acc3e160a8c776bd0305992eab11cee72b51576e 68bc2a53fe9f28b0fcac97ff57c0dd6469b3387741aab8bbe8779b72264f10bc 97741abb965b119d339269b289ad2b630e8152a2e8ab33bc9da9fd155a2453f2 a549ea88e7610bf3c7d92fb93bb175146bca920a8a566a6b8bbaca0c73fd31b3 fae4b40e6dfda8cd353c561aec3c9c8da0954d888b9c6adf883621b50c3c99b7 55e367e48d3ee954646ac39548bd79e9e56d216b1ffd07d7cefd5b99bf08ffa3 b5611452300c2159de3e38795fd01a3fc57dfaa516ade34e288e984ef3a0d604 3ac22c7a0b7ffc3611cbbb883cbb1fb6b4fecfbddf4d43c2c4fb484d4b103868 94d7a77a15bf45726606d1a5f4ebdb46609b7cf029cba1e51a629e1083f3d76d e7c85510fac98d7cdf17ff2c1103f65411fd196c37571a4d2002bedb00258cc3 023a807dfef8c1e036c0a55e6b1b09ba9aa0637caafee1fd1b283f48dcc7d88d 72638bdbc1acec76e018aa9671b04f82e1e0711f708f6424bd77f9c048060ab7 f19bab5af9575092387a5070f63e2c8bb72c14cc9f1ffd5944c2c24d82e880c5 b5a3a51d296fd23efced3457f883efcbdce7b2e7ac1514e5c51211be8c328604 24 920bf2310814694920ad659f87290b245340124e5a179ff7e8e1979383e5da069f7458dc3b9c47917d710b431d26c3884d37c188a9cb3f9638ba323fe8cbd70df3fff5bbeabb10ed8dea39176b3af732d56c2acffbe52226557b9d304b87c50d108cd063f135568fc32672dbd1986062ca90724e54adf7483e5206240df20f0588bb84c60859b8dbed44dacff238cda8b9ef478b6396e096485b8d52601395062578d736ba6ad91747d52e3f228f19b6eca84cd4c984190f5efcb3b3924ce60478df2e20845626432db7066dd9ebb07836ff742b8b349760e7392104231a8c010bb6e5db488566176e337aaabc15b4f9d963ec59f41f91567f7f5a2c5c625003a8ef2e0d4c0b471384d4ad6bb561e881992e74d317f8962cdfddd3afd1beb90d16264e0249ae0c139ad538be083aac8ccd8e6671f3972fc8942311692bf7ff06721a7e0c4ae333e78d366eedbd3378487a4f4f137ea6eb4f221f5f6720fbfe0f38f7bee76cbb6a997330bb4791e244fa6fb9a75731f90eb812c77dbbc15ffa04241cf3de420b6e8b2545998109ad3f35c5b5e50541116c609e6f1ec90a957001ffb794427dc5e4dc913a7043240c27a3350623bcae1f431f6f8c03ea41fd240aed5c0d77ef9b6785e866267d8b62599933da672ce47fcf2e9ef796b8a87fe50b1b8c4f1d30e4f6c103367e0a20a53e9ec0a1c1d90001f23fde8bac1363dd500e4d539461745554b8fa38a824bec0a9d356007afa7d7586fe0ad58547d6c65a0d8d0cde78240711c2154baabc630c5dfbedae5d1532d5fdfb78d2b7331791e6010c8497e941a0df1b9e6cabff3e2452717635f8354b6d07b92db6ed10ec286401eadd7a2f191e6061dce3f95c8490495d51b06f13cfb8a2086b0e3f89b8c8150d4bf14c576c1cc8cff43835f6154fe91b2df67686daad2201cb59669fede1ca0aa0d4f554cd58d7fc1ef49669dd20e24968ed73a92920482ae11df6c00eb6950437b49ca3c12db5d12bc2fce95900b99dfe45be731f9eb58c04b928d3b4a38809b709a3f34552904b14dae710ebc4f85274694ee77d7f721457904caf6a3c9308b4bd79276abeaf4ccc26c98173b96fd3fcbc905f787d2efbf9228ccb179c3306090e008d0d1b1e93a9414bf24c25d3311a7cae586d1f30c6bc5f4d2effca6a09941df962a5cb2a765663232e6720171174c0caba8772e8ee4b619e9025f106017e4fb3a6c32f7c902c41ddba24630f64b48ad42f57c778918b17eba9d2b853081f18f2c8d4e6b0fbe1d2ee08c1b6ceba4761a0e172ee2c940fdd6d0a7ea576060febc836130cd04f3e54dcbbfa430556e9fe547f59f394e565c96d5936dd760c02e61a15c1fed0d247bd33b57353977afd85f6322fac67292ba1a6b4f768e802a6f7b248d236f8abdf7ac55ee0a107eef738c31bdcd8d17e68520e151582bd0789baf0f9b6c37ac95c0dc75824b9b1d091fcf9e42b80c5fe8ec1c35d901ad506119e56966b63eee2e7ef053452bd66f5059ebf6aae5ce0eb0ecad8e1758989006f86ca3d8d1c85897a09eaf95f863c9200a6236305ec79ba2fe9434fbfeafd09fcb7d0fdfecd767a968099e1f755d085dbe36b8a247a009e654488438eb4f90ce71795b6e5dfc2e095ee0adf68338e8eafe6a7842bc8a9df00c945caf85676057d9c4cdab14a9776f1c4e765d30f637eb521710bc8462d568e6410e4eceb3608751877fbcb2b2bae5247f0094bfc1f675e160255919e21275ecbec348d21bf03dcb3d184870ea5b214abf0a59e8a81fe0971895b9fc8a9a4c1abfe7af2611308117f493eceb827cebfd2dac5a43fcf76db58ddd652ef7e6d9e224140726813033423db4470aa9c5f2a17744c1ae408eb84fc56e9988af5a3816c36446f041f00fc3d732dfb776c5ac88c82fd914641e608533461a6adeb90d22d6d20a3c9c90c4c2de90383313a37b5b743a93010dab0e2e51962bd8eb2619e8de8014cd2e00a98eda024ee8e7516b0bfaa4987662eb804672895cac25483960f010db61e5402cebd00a1c2a212d1077b33cf684d70804523349de60c69627d8d208b8ce0d20276d58c8ad7600b9d0ebc05a291fd9a7b697845e9a4db4123996414dd58ff130079941f0b3f6ea62ec2f7e6bd2bcf6d171a13965df1b78a63ffb9f7b4fb0778059b71640309b1651e5a72845b11b9c84c4083ffd322f7014b8ef4fed0449aeb099d604e154df80235438c6c8736476110f134db0a5345e1fffe57d70e1983000c9eb1915a7c15553f9f6f7322cd57334ac147ea26a32d3f8fe8b3eeb59df78600921d7f37df0a335bca22f6d6033036b3015df9b85c704a713959bf7b123ebb0b26ba2149f292eded1d35f269f1cc97f5ed39ad726d2ffcf39f01635ad365050e656ad4368c94afddef6625fb2af56682c1b75780445aed27cea5950c84b651062532822ccf263df7a37f57d4a92d398e3c69aeb2db4333a4ad8a31289e602c072f88c7deeb21faee4e2e5edc8d44e6726298971ed614f22a7d6e194ddf94380279678a5737bc6c66757c35ab471fdac89dbec0038a8ae1ffac103c922ac9d903ae97d68692aa51fa3b0a124b737949fe6b837446e14726fdb37aeb8d32d6700970c096ea9484c2e3faf3b588de149e1d777665d4e8a05e9769ad54f5be5d9c0532a8e3487de282779e4acdca23c5fc6d2815b04680a88ad77c7f107a60096e0d900094cc338ee81c6c9a31d3ebbf45e925ff3701297d0b2e6bba4a8a7b392306e588b702ecb907784bce3f0d3925499fec8ecabf6ab3a1835bb9c0e4665c850c399cec505ccee4f8d3e93a8885c481c4e49ae83dca2e8cbf4eb9c731717f740a0fd06f1923493c076647bf7e5f67aab18ecbd6e1c5aa7bfd11638f3e3f58c40da3e2503f4f2d6e42c6e59854f0908ffb1abb35f118ff05cd38efeb020236c90f06b4e18c247d2a4ee1aa5f56055957cf8150ab2c0dce289cb8a3e4e8574c14059dc9a121d7875d69c2cb42dbd7e39b514b699d8864310cabaccf365e3eb993048f84f60bcf2467035c7e093161e39db898470ae91c85da85db40ee85cad4d702ade9f6e8eb2afee1f69bafa935fc89fd79593da0203764b2e91846593d1aa6053fd0f087874fc1c3b810f28b23c2d16be52d9e84ea33fc49bb730731e283400a9fa73b07dd605bc5e3e630ead6c8367742050db8b73022953d4c36ea2f21aa00a2bfe7ae0f5beeda4dd96132a9a84aef3b6b37bebf67da239e9dcb420b014b078a692195f4fac817c5506ed9c57dca7c1299876a7fe6d6ef1a1e54df9a987e0ce083e5370a0e920a72138ae8d67ce08732389bbfcacf359264d6aa07345a47009c32ce14458e89d7a3dff9000ab78bdec0166e18537ecba2e6a452b4de451d062066fd747e158cc7e9250164e810c4d1ec397f63b68afe3a5877a81acae32603b0ab12da9e0242c2d641bcb3108bf6c99702d701cd371f6ec7361fe9d9cdeb0854967c62b2702f8d0012a9b3f4fd8b1ccd49112213d85f7160f59e17c5df080e8329dea18ef49c6f513e4c24b94e62fdd82f91373bad888326cc0f818a18e009c4fdf30e59278a2c2b0e8ffa1539aa8aa97305b52728d3f329f60b796c7c5f0fc8b49f9464658433767c31c544515d8a321a3eed8bbb16007f4c019fca010003b1e0219c70d54d3b38b2ee4778bb6b677dfa61bdc7148964d39eeb7fe42a3809d3b4ba22d276169ebcfaa3634592f6aa7affb18fdb31407ddfe25b7cd910c109c125f9a8be911fa2652fbb0160b1573bb50dc86700509984c57e3fa5b07bce08c8a5050a89325a27c77e746693ac5326d2d7e52a9483115aeb1097f9d3c15f04bbc1c22d855059f3ad26c336dddab464b54a6d551f07b6acc9f8d56b103f630a6bbe13fc8d0753efb2b0ae40beaa06b009df2a7f6ff59b3cfea5c7718989770cb0caa371d9bb42961e3cdb9df499f1b415e659c5c81da41cd115afea47474204044c863ad26602504db19ccb016a43a7e222626a16eb5a0ea55576dea2c2790fa6b2ca68b9383c8d1fd2162d3f15f1cfbd16fbb8171d2234d2ef54b7c81f5307bf8dd8c21e4e8f2cb0544dab8b8c38e01ea90e133a7b8bf3ecfedfd976517906c3b9a213ae7a1ff8f0727bdaae386f9f855b457ee7ab219904f644804d21100293cf4e30e650d8d4358afb5008f6b76294caf87d5f6f21b087fcab93bd4fc109ea50572841fec74ce6bb93d540aa9977f48b74b52d33cea53513033c3176e60866a8aa56d33a3ef01cdca4ec142667b7cf9f9bb91aeeca2db5d0942a80160e059ee319dab36e41269c2af1d95ee90c75a1905e274b9a46c78277fdb6d7fba30f13abb9f6a00204c22f1c478de8d537fbb7d7a419e992c9247654f13e64a11009bb2f2f58b705f7d3fcafd5f273d235ad22cd5a5f149e637624810f2a7d15c9065b65ebfcc0108bfb281377eaf0465a9d5f348283e06139e9c31692a88ebb6704867750e20b49f577fdf565ec146a8627deb36137ee3cd19af656c2fb6a8963080118048382a852fcf6d7b63883cf7324dde6e80cdeda1073582cd7f589498104521c71b8f12c6c9391b632a0288077ce2a17c039e517880f9ebf1a54fd58de0ce25c0baf8bdfc83b272864712bc50052317968ff8d0fd777eaeaa36d51cb1805690d394eb19b872274e73d95aa9e1f57d5af90afc8de74d10b4aa27b7e7520051bdfdb548d7b881831f49b9bba55b0f79030c99c53386d9303bba4323b5fda07fc5f61420c049abd3a4d8539276ef14c5b46022b531d4109ca4a2c972912e707925cf05655af9fa2efd347708d4fea96e5330a70a5add156e9908c657fb56909616570ff6d756e41c9c6470f19e7f6c1948f159442604ba5dffdedf32866850db1dedbf17f4ef852ff232c126c566de1e8e10fc0a4d544733135652e4b7be601d9eaf2a2b25146b92506074ecd91d3826606bf63cd80451ac851d95dd0c996076e8d9e8dc544e3ec75151926099169f9fef5fa3c962e534607fb810310c89f02c72e0f0997339ba959deec557397297cd4a17ada436145f150ad7ac638f0560f9c1aecf615c3315fcd0b8f5498f7f102bb207d19433ecaaece0c6531372edd0801885f9822ac577988db7674e4de1f2ba7966527f24b62c777f41e9be516210f10ad775cf62753d62ac12033d4a415f65d3fd56115ded54544deb37a9839ae00afa1f722391aca00dc92439b14a814d801de52c95262f51ebb82d07f6b6f1b075fcb52ee33f6cd9443ad27ec75cf685002e06c8cd1afbf0be2f7b35330fe5f0ba2cbee426af9a537498ff7f6bc8f28233e8fc3db1ffeb329a907eb650184a705dcefd32f6ff6dfead03dc1c8c7da9bb4eafa4cab334a22a11be3a47676f4280d83ca57ea87fb46f5882af55b56bcc5ee6025fa4760ed2e74e94e9e5ca56ed007828910f35ae0c35b4da2dc805f064501872c4e5a2906524bd33e79817b28f30e29d29f097340f2121e2f27c48fe55f3ed4d6e11411b744ec4aa8cf6ff0078809a4e92071957baa59ca1b7a8f80284ded272c12f2238921b61f591d6b5389e802c68ac968b598bedad618d5f47d692227607dff4d1a47ba61ff6ecfe74ddd200644e681f4c35a164d7f56070ae61ad807186ae9874f058c9fc5a2d8f53e0dc207b9fd3a106414a8a2daebecf36b5de9f057d20ed61143f52b1adde856d909350c1332ab7a5b5ebe7300d793ca298212347a538caa2aa174b11bd66844bdcfc90ad42c371483d832d49d2c17f2265628ff483e88bb416f2c0996638aeb365ff6051b56deae4a8ae8662d20b721cb81fd96b999d0fc594ef0a9bc05c1c98da3db0343966d2630a8a96480fa6d650061b636a576cda32602fb9d57b54ee9deaf4c036678e082851e7c88f14097a1bc2a87e0d624f4fc9cf7aaee648553fc1d94580e28479957dc158ba3de11bc0ef020600da1b6445658254a9affc3ae2e8987190df565fb436a2348da9e153e052d510c464e9adc72aa5beae76b65668c2f043807fe658432492c64c4eec2d55ccda78ea16a687ed971ef841a1dc6869bea84e603b3ab9cd290f41c3df348c0856b0b52feb35a9d2688cc7a3d3dc2f7f401275101d73828ac2a674b879e250a5248eb50ef970f8b76801113f2bff003ff5bd90904ba35c9c0f2928c3ec58adddc5e1c0ba50819ad468b0fc8bdcd76a53910568302c8eb13fd88367618391431bd63301441c55646ab6cc2eedc05e233de3a7ef40fc9f873b4d36d6a6839702f56af687f20d0139aa616052edf007edfbfbec0270febf061fd4cfca4e4cc5cedfdfa5ae3b0f60cd90219ba23b9963a5ae4bfba2d0a11e697d37f2ca997dc723c21551083690b0dadf3a8eb6cdfe80b675f57fa610f52994497ae1e7213332ec3a05049db58b825f9ac0df696e7567249dbe733e40e13b0bf7a574bc7f344a3bd75fb92acde599ef715373d7ea56ac16f74c00fe50c3bd54a9850ad2281a0de9629a8042feb256a0fb737ccf9e5e7223ad53c4e7f0f5e8ab2dc6720378ce8f8dcaee9d430462a813a6d73601d65425cf3c72ce83f087cb1100bc71a5e4863e44877b0db2eb83683468a5821fcf5623077eacacd2d000bbb5669ec44c80c47d44691f03ff5492430edd26ee9ed9c2610a235d36cd804e6aed960e4abd542c2393d149b4521ca2a11470dd8a660a8782f167e87d3d90846c330e39507ea7ad281acd0e0842c0615f953e476b6aba89ee157b904fa6105dd713307414d80018002cec2aaa20f70848e25c50cc1cbff7f890811b5397405d657b8f71ceac9da056102c67b1d506da30e8e703e367e4fd3f3b9866ae7a40aaa953272b2ab61d93e6573f2dbfa34a2c894a925ea42048a5f29d4c36531a20c +generate_ring_signature a204b66b297db8196c5e43fa172a9cf72d610c1a3e5c14a7e64b6e77a902a7cc 360b1eeeadccee686eabb2475524e968331807e166ea52bcbf4b806e056ee332 6 3a819e2a86cbb7c93d82eefb25ffc9d557aaba2e76ea0cd35ef017a0f9db4a74 fe4bd986465cd8d4684788e3abfeed9a49365cf9a40225a9b5f7a8f0d27d4992 ddb1f912f0733db94098ad017feee9b550c2afdae5e0bc4bdaab634dde7485e3 ea08a323f76486e70dcdc071e43b7458b070d5e15148e57268b4801fc0e9ecdf 16e7e2e0736b76d75013cf19835f4b3130b7761fa2f1243e513b1940deac38ed 9330ae8956224cc4732f9c94d92a3470737d4943400c6b837d8a5e4769e4c2bb 5f961793fa7fab2364e40a420192a778e214079b163c235d48364ed07808b50b 5 3846e8200f1e7908e143fb738ba457a39530bf3264969b56f21bcdc093863b01cd9ba4b97fae73c626bd1bebba775d9bd3410da5e7ff35c161d0433be4403600a9a0e1abdcf6d4d9fc2a54b7b7c2fbbd987efa816f3fa503b1783bec61acaa0d2f44a73bdb0ff675c6f9ebff8a541595e4dd1c3c8f9f77f6a46bb2e575e0b809bae12fd93ecf6ff452e58501bb76b902d2b437d528246e5e28fce833255cb30141c88bea17b67aa047171ec0723f2a6177f72e90442309100cd2daf3a8e91b060273fb31b6e0d6559c91c5210d6bf45058890c863b9a2e726982ce4a46b8b5036bf83e119430d3925bcdbb033651a31def9e0ef1b278b2134143d8d43257940cc70992704c00231bafa60a9ecdc893698c62653c6c5b147cdcdbcd23f7023407914c502e5111df0b196aa9c20ddca9512c3a66103597d1bb36b5c1abda9c9008b6a98728245b0efd0b1eb784384535a2759b56695b6843812b2fe1b455a6e00ed1469c943f21c99796518a88f02a33cbe2010473dde87ebc15909672ab761109 +generate_ring_signature ef79e077a9e0e9424ccd7c150414f789a14759ca964a0e13fc01fa5466c81e78 f946890532edc31375a4fc9e0201f16121acea77989bc1f44f7cc9e27d618cb5 7 7833f5dbe94cb5307fa63720d352767c4b1eeae31307e89dc2bab1b483eb07f7 a7c0d7cedf45355d0d2981b5f47390c3e452becb05e015647e39fc4221dc242f 883664c5618118cc6d2e9982d3e3b6d28916edb1db5db6db7bd5120dc2ed1f7c 1227bf14d8642d1ec64199c7b955557194a4bfd8962aac9236e38d25a8fb47f9 eb41c810fb20bed74105bc9cff98bff7526462572cf709a8b85ae65462769d60 55e0ae0f1a539622d44ef3ec8fa1565017e9f763c45f27eb5cbf6b926a414bfd 7af96fcfd866484934851fda064375a00816e21466ffa8fff2425997adb7c190 0b0c659145f52a67e664d6c06aa96452c552c1884cdd0f9e5b7819adcf173003 2 e58d912c22045e874c20d6671f6a23c1c76ae91f6972e98f5377da62bf305300f545d66894af9afe5339200927cc93abbb5ae09e4dee03850d141a8291d88c07527d5788bb4670a3016dcaaa1e31ea5cc8708d3ccc1bbd6620febfa220e8d509f9e134dc6a91ec51d62507dfe8e5dfa291c5234709e4177d4d1c13107035e50beb8f7811a5d5e633764883fa2cd8548b1ee44a7142ebe251d75795cbe285bc09637bb91aba76727808a890457ad1b027fceaf920076c6aa37c37f39f03502e02dfc2fc547a7d853068e2b43ee434b96097b42dbea15bcc3bfb85c25bc5160f0d53a226bd44f3c2f0aee264798307e579f1d8c9c16f51d353e7da0722066fd90dda88dff6a09b5bf860c998bef0063ae4c26112d434d72913a1ee89df7eb97606886116d9a213de523004a7e817cc52e61d978caa6b2cffcc43443ae190fac1010b6d73517196230af2c9bae8efaa0b440343edb7e02adbbb26a8065df63dd60e52d9f64fa4a107bfa05179fb551eb245f399dabb80816aca08266d0874f87b0a331275a71adb02c515eab7cdc96db6d83d5fff17151b1b7c87c210814ddd2002525d4eedba5640f0a3447ad10bbeaa22c75af875a6c9ed5b08f5a891138cdf07 +generate_ring_signature 78e0172eb16bc072a3b80ca90d93b44df26ffbc7dce563174f5865f7c16e5f43 7479b29e23de8cff8858d8ce192a594e7c4c3eddd8b898300b3994efab06c5a6 4 ca91beaf2146e06879051b0b1605935a0df5b5eb1ec9ea4f7f8d0c698e7c5bf3 567e5e858d217b840f50e66af8547d3bfd23c76290ee017b1c5ea07abe4ca354 c24d4eea3e2e636a9a24934ab8174a05043ad5612cef38bda772063f291d090e 7c51495c749ae14fd8ba542a7fc76aa77d4160b73f84e67811c1087eeca84d05 ae5a08468ae07c2ae86e46255bad3bec88fc27a5697b88a0a426c8ee41372102 3 0b33d2aac362a6a078e8ff0ee628810d5b1be449d06e0e0054c39a59aef01107ed271794920905eb30a376997a1cfa6671dc172e972e0e1d4ccbabc2d7994e0aa3aa7e65563f5546749671fc0d91789d75298312c45298cae158a30d5da4790da191ac1335ba4ceb5b4f649c093cd0c1929029bba3ea62613ac605578a400a04d9d88738e20a44c8518def60d06fbe6bc6d8820d724734dc7535de7bc95501045cfa791d55fcfafb5fb6796af6221f1ffeba3f0bfa2f867c8d773a15bbac6b05c24346e8d4e7fdab8e3bac1c164c3f57f7995236f0ea260b701c9706fc92570fc25726663bfed4034b30a1a3a5e3896c19304b68dd27658fabfcc11128766e06 +generate_ring_signature b2b17f8eddfd010da161593db87e352a00d0f915b3095657ce31bebcf0531d77 6d9765acd0f77a17564da4a5f7f07a0b918bc309f136baf6b452eff47b5278d4 7 0dec43ab1cb7836dd07b41edf9013b8f8565502509bd853b73a3fd7c2d8332d7 d007bdb3584697e80ca791a489452dfaaf96690715738e9d0a9772761622910b 3bb2e27057e5cb52140c29f86ec9072947931c4496da0bf88eadea327b45e13c 85fb98fe49d5489a55a67860a4dccda34a81b00bf5796565a5bca4258eae531f 3d1c25052eaeb43c950506c73a61cdc464c3718a502d77dab4bd23eb34093bbb 386800a322ab462444d1bdb3cd943642b4532cb4e6304270d56606daec593bec 898e99644703e2ab485bf42197618479f68c7767f1a81a754254194df7bb5541 8ccf33c9539ce3697c1ec001f6374d950dc0f5888fb2459f0bf5f1c12dd3fa09 5 f59233ff89bc30e2a8752163464db4817080711d54f58fcaf848fe2d0a5b380bb74bfc580a047bd6a46232a855907b41edaf556df8ce6de61102fb4db7813308e164104f51ccb9b8bb92a52c735e820ed703a709d19e77b04c5e3bba66d2a2030b305aea6ffe10438f6307efd7ff43ec44998bfb91a4f6c9dee1a826ba053707fdf442cbd7b24265544b42c3b242eb6580c3ce47ff8897648dbed8a187777b0b978a31f16975ccd0d0a6a44a6f6b63070da2dc155960dc5a906107101d3f8800794862402d395a0ca2de95d7e4d7a21ee69706e6ebf312e713d9b395080ea905b79c3845745d4c382826db160faf5d3d4bf87f8621a2f2983cd6f72961cdef0a26e216a99b499e351daf4b803db95c6bc72b57a54b17db5c4a28fdadb3d40d0d40780753d1f9e7fe7933ba267dc9399020e5c2e3c623d2a49a7a505135381804685ddbcfd7ad78cdd40d07c0f17c4ae06069d6209de00e9e163b8ec6c3b3a7039f3bd470670bc47deca9535c4a03c3c1a3a84ae08ba2593d565e94e61383b40630bbebbce8948af3aba9e2066e70b79afbcf5f3e036c5329ca4447c696e4af0c8cac596607a20a382beb88598e1c5544392b7eeb14734d1baff9c00e5d546a03 +generate_ring_signature dccd54de1c3418a71890e09bdaea34de43197a723146a148dfce50806f6351d6 beb57de477af6fff12b965fcaf9ff7229f670af5466c040902abbaf20ad26281 227 de6f898395f9d3acd113f747c1ec42b3c669642e954e078a84625e04f1203a86 50e0ec8c3ba80da72d39132072ab6db97355bb6d689df8d49323d6519f7afe76 33214ddb5c37f8ee1f71d77ef8f8389cc93ebe3e0750f0ca750067116ba6dfef 624036187cd190236a3af52cbd8ff1551af9ea618b7ad46c4039956372f2b37e 4d8a76e47fa3de3b4230220d19f147eb2ac1ea9cb0e815d5210310474bd722a2 9dbcb6dccb566b9b4ee3d9f4dd096ad64b86de505861a4b27007ed26bd7fa057 8afabd34bb7fd38de6ac26b47d135d6a0c05b890061de8e26e719e87d1140637 7d8f3290f75e81a26454b06a408ad4a5a025586eec86b8f1d4a20c006b0cfd5a a81cb1aa8dd7b2845b6f62cb21e37327eafab75c305977a487c7dd9cd9b72285 586bd7a57d35523981bb88c3a05c38f6ee6f7a4596a5c70d9bcbe72ff94d4230 75c17101e9fd6868e7881f5dede9b009aaf2e6945858c286ed121c3b912b9466 bcb29dbd41f103217282fa56c1c3e49a30bdc22c29f490a0c87f15979e90db94 10865f15bbda6df7774693537a26ffecf4f8ed4a9be5ea8256fc5128a5f5ab24 79c038c008b87d3425473433d22a6ee12f6a94912b2b473be3525df20304632a d2ea981b421db4622dac964447a5fa0f0b91253cd985fa651a0a94bb06a2e531 40360e8d38645b50466c06c3d2f366fd3b41ce9dfd854b4b6a6bbd91b9f2bbbb 85386e78ee0cfdb9c053759b698aee59487b080a3f9bb73636b6e9a36e80ff91 938980150ff4af1e402456d64d15e1a932f5b9ae0d03b7122c952a35456b6540 aa274c87ccf47e58a227424fbbee715aefb91a6a624217bd3ff62f4295200849 17ba30bae32dc6e3aff58c7b865f28ccfe8ad56d1779c3a40c9091dce280cd21 40182f7b319e2332eec3a96ae080935a8d06376a85d50e1dc1e54459b00538a4 18772a0589e44334bfdb0154f4ab5168e7cb33c2aa77a7603425da7c12d6479b efdce92d903112472849ff28ca2f7e312873d9325d28a378ed723d5fc2d0dde9 c874df6ef1ad049bc46597e1de0533c878070fda32bad8dd6139e98b04a44af6 09d67f7cc7632824c92065fea6024d80f1a5c9c2fc97d66150a5e77e9b069fb3 7bd68164f521e0c47994aa974693f8bd236564ad73add045a1f06d5d9a42da0a 7aab16af4335f06f3f24f38806b10c20ecd7f75e16905a97caae144393c880e2 096bfb98ae3213965acb6b92a60066b8f8ee495df93e5a2944de1646c369ac30 460ff31e4a5363b5aaca21aeedf944a713196ca387f438268f5817de68c22293 2ada78c71e899bf785980d8cd94f027e365684eae7c4292cc7da633e00edcb90 b84693047173cbc9166b0ad16a918d2dd5cd5b4dcb3175343e2a061f83623e23 7fcbf67da417193a649c5ca188c3c330d1615cf12e6854cb45a7899c24e08aca 1324e3c54e30e3276fad872fdcd7ba4f9ddc97cebe3f886658ac3767d60843d9 e555257d3f2fd95dc9555f8d89ef1dae813d0f6a9ab1e181f7d5ada73c8efd3a e52d868d66be401ee50f7eb5d74746beb94f677a4254eed91ab753f738e75da3 1d7355aa5837df46db3e8e8993e73c4a294d646d190a73ba40aa3ce841a83534 1aa2563077ff97e778155ceb8f8b4c98e45295e005fd9a5202e62ca462f995e2 f4e6929b34d3833940d5d30d2a7b0ccaa425360c42effb1940a10f49abb4b8d6 960da78fa1fdebf415e0baf03b63eff38b81ed99639186748188c348a3d5d8e5 ab52db15249b26d53920280b2b4686454ee211ef81bc330128e7c7365728d36d 72182c9dd9736c191efa97312318003e1550e18af5ae7b5f57b75a78d93462ae 8a822606f03874e68a1297636b7ddd645966b342ed11e826390a85d6fd13c3e8 77ccb0cb46f40123a379e014f46103cb21169b8f8dc376f34602a61ff3a164f6 c4a730fb9e281d183e142c9c6256183bba9f5871290071ead468d2b5479e2cf1 def7aa66dd688039565fa35a223d34c83aeefe5a6e702889eaee554028efd3e4 c42af9fb89579eb04d706df14cb7c47aeb844fa1c81cbec70512323ab608eecd 6f7331a1adfd3751d3edc5dfa02caed59d35813e646c474854241c7573beb1b6 91573e6964a2f69fba125d7897ee25fef6b0227a51a2deff1dc9205ed0778ee4 ad9bf2a571f586d8368024107021af31d5f5751999b25129f660f5b63cec9c97 0837392fd063e15910d2192b3c180228bfc7f12dd2428a81cfab8f91cdd44bb6 9c363f58e7440049d17164c4bb1f5a8a1ff444e1c26cc1ff97e43f4fd21f1b56 7e3e818d6a8d02896dcb8a7d53add542cf205c46108773495810bd8848d13e3f 4788b7a8e7b695a8ce58a3d61a7a3bd37d2c65cbcddf0f8402dfb8a5b1996394 fb352441f47b8f406cdb638ac64e7b6e8088eefdc9e757b9eacc7d3f72222a82 02ae8186d25a835ea25bdd979a85e2ed9681180b51fe5812ed67f431ae4c5f62 099abc67b8f2b1411f365db32e1973dcb2f6193e674f5ba9615cd3665a509a22 f140bb04214d43c84272acd28a16c49e2b6ac054ca2edb06542c2c2a764f6a80 cb2a56e6e72f1017eafb033c66e4899cc0da2b161c47265124ebaf0ce5c4fec2 838c1eb32105b74439cedb6bc89f68fd1e1359841994b58a4a7aaf5475c54323 e1c28c4e44817363335668ad1b2a38b2cf8ba1c0da151c1793d6cba07af2c5c7 3cf16340f818400832e2f4d3ac53242aa822b581835c701be359124fa74d51da bab07fc6e7065cfd2ef24b0d99bdd0a37b7c3a94890a0ba6e112ecefd9b59fcc 69ae4430e581881a5666177cfdfb2aa4d076e7c7fb1fc1df85f4a42631b652f8 5cb788dadfc2f0a8a71a53cdd95e973eb56ee8d8120caa38c9075b1e1e00620b d37ae42bacf5b181aff456091f7142680b056d866e1dc537b4c9c7c47d892068 5d8879fa016d9badd76b8e69f77bd6f02ad5b0ef79323306e8cdb3d3175fab59 b7e0d03bcc3356971ff4e5f2014a1ea9e2b8a3f87a170d25cd334ef440f1cca3 1cfcec5e2dfcb2243be40ae986f597f5e62efe2056fc0ae0f093a1ef8eac4c10 d45fa110c2c973d529ee68f8b00a7599c9e9821af0006cedc1ddd6ab3e37d9cb c003ff2afabb78406fdd999a1b48796082f4106fb616ba7afc27b475f2d78b79 6579d1ac0b18977a0b4a3184901abb13148a833b29445112fc0936e7710834e4 d2742bb8b5bd2fc348adb9121eb048b842ff428edb4cc0e628a51b235453c183 bf09a5bc58fa250176148cffd82244e614b0fadf94c23e53abf288facc92510e 6d37834e2372f26ad0ba8c510660ce2d74a495419065d78480332253bcb686e6 56d85f362ed1b9d5cf0cc9b22b58f704d7a1d18cd9799621c158e0cf6eac263f 15c8bd061f78d454c02a67973a18883014ea1a506740e3231a9b942b405099de 444188e9d62b697974066852422a091f9f9687895db8036c4baddf71bff17b63 652c85a355ae256e65bb47ff48c0f421633806c127bdbbc99b11131986a17476 d6d364039ad279968195fc81f2b2b1b8e315fdbf21618d05976eb434533ddbc5 082d940a66f319b4f2a26578dcb0277c9dd241d209f11059aeee396c767d6943 0f1ba3b82c1278d71c7ada842514e9e8a6b03d49925f279a55d84cecf4b8ea97 64369ba0557e73fdcb4fab986fdc58db1965fcb1b5fc2baaf7c86bea7e4cf0a8 c612977b21bde87630763327ba5fb9bda6312a03fcfed6aaf40b56e65c945789 8463e1860d65d4b64eac0d5367a5af5bcfa203c16dbfd083353917a61a74bc14 4ad00dd4cb6e7b62c74a36ce1ed7720b8c6453b570677012091f47ec7632759f d544467e93925c0fbe87a630d5a2471f3b67e79abfa1f8d3e89833e36d57c7cc 1127b1aa8e3d8bea0b4a9184720eae39e1879fa973d87966cd3fddc8901e0ed1 afae49672415a9cf1aa4f5d5a921e6ade299a517a5681c5888e1eafac35caefe 1bb1d53b9801aec3210277fb8af2e473a8d1026495c0900735d89f91adb54508 53c979d5d09084b0d729b5e740ef1ed51f99cc416b3096869eca4a287598cf60 42da4fc63c86c7a13bed979e30195d45e73d0b959865411465c2ccc30983a0e8 b0e4fa801af1c5c2834b31cf80831fb11d626020255f2b0bbc7c96465f523288 2af31e59dcb552b4eed7558885de0cffbb5cfa7217b423c590017588b488bac0 6acfb4632b22521dbe49fd353a239848f53e7265d43c89b59da8b0cc3f8303ff bd720e79385f6d2ca5f70fe141d02b50e21648cb3f959daa425de1e4392e5c75 0e3e941a4fb0c523195cc6a0dfdea6f52c566ab82c25483b9a10a9d11465589c 85fea41341b6d49d4823e309d4468d7cb655811177bb8a53e236c0747368b819 32593bb228b2f454aa091fe6b2e4716bfa29be3089306895310b1f2f57230c56 4ce8bbf39404f890dd296a2718624b8845eec23023437ad83dd3f90e3ebeb52d 434fc3946e64e1d07b97b77988cb48b8ae1133912dce2b9c1902bb9c83f63886 14354e897eba43297579a03878669d513e37ac42bee8e7c64e354ed39ba6ac3b 67c9bd298f98c083736bbd6511fed9fb238ba09634d630acf8c13fbf5d4139cc 3c77c3a7286acbf62237efbbae13eac56c4c0bd55f7fae2176550ae2f49b6b46 5149f6fe63a8042b6fe16c6e31b5b3da0245bb49ec249045152b1814e777efa0 e9c51ac176861a0c5e72275c34686f38e8fbcec99f81176a4f280e50c1d68de8 6d2de0ce0adf4eef46e9bc7a082ba9c45384c5e2766f7cd374f6e7ecf767afe4 7defec0b1eb6aad14ba9f886a3bf94df39f8f9beb4bf3dcfdd8e9f30c74b62fb f816bc04b50cb419e5342f8d9c1c45f61e8f7ee1021271cab7f60eb938619856 4e740f39bde4b3ca794f5218df1045ad330c992f198de22c7b1581e585f6e8bc 2a707dd3aa3ef5a0fb89987ef90884797e9b679941563b1b0f0fe482df2cb704 780363e8eaa858601ceb6eca2a95ff77caccf4a4ea15893dbfdf1d97f6196b5f 7954b47f519dd86d64fe572f5c83746dfc6cb7ffe388e257e5a27242705a615e cd730bc5c83ab9fd608d5e4d0ed2fb3a090e993da29c0341120f94940fb31a54 50eaa1323e56b6cb217c2728120f51cb7fa19c2dce41be26baef95c6f61cc276 811817719c3c0541dfeceff7756e80f7c868d56d6bd06feb1027a0c37b9957ef 1221701c18e4cb5e606260d2a85c99433c136549ffcbed18cf2e843ac4118695 972eada79c154e43a5ab8797202f266809d163f8a1496bf750667667d1f73659 812e63c9f4f8225eb94880915c2142e26163ef6d27d4a240b9bd3424ab0568ea 65e81550555313646f8ea5d2e1d998039c087825103a1cc9aec56489d6e7cb4e 4cadbcd7d0be79f6f32dfaa6a45a7479081bb824b5029c3efcfd51cd218791db 163486ea2d379505656ed6065a355a2b5a0bec2f1c56121047e2513708af0ba6 e312f142355698ac9e4705286e24ce259986cbf9c475be9908484ded0aba457d 5cf113e03b26cb54d5f672b6997a44b28af8421d258d1a51244abae07783dde4 7d19c56181925f1502281af675823ed9799978028ea3fde25e7cb7f2b2bf1af5 561035986edcd4fb791798407f9351b9d15ab7ddec1b1156211e4372f65c081f 9c2d63e65438f187250b110223fc1a41600f1516b75299d418698ebdb278972d 8db1c5443b19e83d124cfb93cb7659022e0ab39ca30fceb1cb7eebccc04c33e9 2a0beb68b0cc5fb35a2c8ad37619b7faec3a573380101bb1f3f8f930e22f17c5 95a8467c529e347700ead64b0f2b2520edba9317e1988a5e05b48d88de6b23c1 1f07b7c84d37af770b0d4dd3db8031fd8671db285db5fb292bb24b4cf03a66c6 03c26aa45c9344f2108ed8bceda99db51e2b3e476a9507305f4a264cfc22487a 7acc92bf21c416c9c2853cdbcb75912d17768c0558f45a4f9dd89f9950c04925 570dfcad88ccc890f989f6fa90445433718d1a33c2f6cb9d06f01e105641a0a0 0e703be79defbf776eacf28e3c02faafd451295528af4c3c5abb85af27a26c6c 8868637d4111edc6b9967b4817419116ff4e08342f94a1c919f88cfb66511db8 ad34c041687a0aac2d5b95645c3be9a092854f05ca306fc4df87b66fa20ac854 3c9c07cb12c72cdbd9c0a53a56dcf49286ccf1443bb46e389bc7f98e9c1e5a08 0a73a13db0b8a4cec8adb5f49b3ef1aff9116ea1b40907e7d7d53747914a6165 301e0e2771166d45a7db4739b33e67ded6f458140e03b77f7dc37dc10e5795c3 456ac73e71f674bd8436300971c616ba64522aad67f199c8600ddf5de5a5e6db cf529e39c63f83fdeaf309fe226248dd7c0d8ece4889249b1ee3f42802e84bb4 6c593de6e012579b5cc3f43dff7ac21e30433117f39e1dc5d17627dbcccfa8bb 2310887b528cdb93fbb62059afefb5dc8bb1ad99a6c26f470e8dafea9a21b75c c874e7cda400a4a7d347b9ccc3849b871083bbe16ba4a0961b5407d885d885e2 7d85f52aabe672cd6374d1f45ee2b8bb64bc9aa713c9d5b11164358dc0618043 ee63fc1d84e5ce7b6fea05733df25621d53e2f8b59d46cf6d3c206e0a1a4bbad 1945742ad66ed67a7e7be7619553eae5772137b123efc125cfa56771f73628c6 16578d8f6792c063ffefbb9fbda79cc2cf4a217a15d09fd6d9e8c6f5cb3edfb7 2fb93dbad3bdd8c52e66bdecb845ac12df250668987a46533e64ee1702586c11 0dc58bb319f98d536c5aba1b410dd591de2cfbbcb9626004e73f953989a09063 8146f9ce2ec99a5581481f5f9ccc32e31550925b16239c20adebe48c2a0dc8ed 6fbeeda5f57a6c3bec5266808f679ebe1786ad8556df24452d9465ba0163cbca 434b44876cfb72d61daf97f0bd8aa85d323af4320f52b880dc55a9c06c3c1463 c13ff3702adfcd8acc2a0b6e4e675b82f503549dcbf14a7c29f66393fad8093d fb76c1d8836c2a1f718106011e3dc5ad544b893726fa72b941d123ec6a20f785 2b7ecd72aea8643057327b542103b08e00b79ae6198592dde61cd62929089e83 e7cef581b5062606b00a2ae4310940b5f18d56d2742705a8bc3c7c54042c1694 d5e7cf1bfe62c0c6abb750e4b22fdc9b11355e4b34e884c94571163d21a81d6f ce69ce14cb9153cacea90c7fe3e8460653d27c61d239718a937f1fca35f99d17 b2aceb0c7bb9a7f865b3f01d06eac0cb1d3ef32a4e2145a49473135641276c0e e0dd5fac25d7e724aa18512adf237fc463676a5d1c9ce42c6a8b2c5cda013506 f7e58fe431e81b6fb8d5db68f69a7e4596c76227c0291f73f9754640085c7675 b63f41f757fe3f6eb32d2b7ecbcc86dd06d3ed3c68f22e41db42550913169a45 3a143a89e143e860c93e71c71f42a04ab75dac68baf92da4fefa6c6b173523c0 7417ca2eef7e735a3ab12e4a0e3b3c2439c71dfad03014200b8192206acc78f1 3e0136f18d38405b67567e2ea5165d8782a1ced39df60f06980d3d2ad9d24f3b 4a3e58971a4e4f94ce12c054249d1fdf9dc371bc7b5279f78197800c2a51bb46 269cfdf63c238721dba6bba1b839759bb0fe9e83d609a2901d141786090c3f94 95eb48427cb6c4f471c2ea568ed9df6633862be02cb2ca025c73b2d624b056af 421e453d565a46650ef8227bace09af7c068466da857357cd9b2873ad1ad09d6 822692d9465ea2005914901f30869c138f9a6351ee06b318ea9a26d443d97d39 fa23a03fc5b0b6e1150a54fe2bdfc78e925f4a66443f7e4a918a7c44cdcd05b4 c40394856093b0f40c439a94508d1fc3cdd5d6f1747d7a876c3250deb24261f8 0082526a179e1f85f2c456b87355d540144ae21c53cadf9783c5a00cc145fa73 91265fa8f7e3ccf55f695c17a0004ac429cfe485463c2dca00a116b84883ed3c 81dc3104800931b6a4c5cece8d3e2e8629722bdcc210bda4cbcbf9871a43edc8 aeeefded266eb59949423a42d3ebc1af07873e1e954696bf44daf3a75e7dd5cb 230cb94219fe81dec527b602ceb442d2fd047f5f69f94e5aa5229e18ce6eeb72 e495df1e8aa30144401c58dd35d99e206efef5800b42ae2c855ba2933ed1641f a3aea8193f840fd72d17b18a89b937a4892fd267a117d45db566c334763275f5 21df42a8e0ebc06d0be965488fa6bc6fd56e9a8071e7d7066e9c0be8a18715e9 199b10cff8216a7ee22ceb37cf3c03d219233e65a473f26fef00137d8c52be50 69375507f886578c829b830f5964a71243a21a88b9aea1555bb34b136776ae64 53d95e59a7cec2ea6ba975536d48a76fb560f61e988a7d5e27b2564c4e429450 9840ea72bdb5e374a4b515fdbaa737f50be2d4115e4192d0973a652c10d553d1 ad8d699290c6ea3864c6dbfe1fc2df282a7033a115ac050af16cadb47f1814fd b9b84b4655239182a7c635dfda8444a090d56ad9f36b39e49c9cc04c9b903d5b f5c7569fa43ac9d2639d582f90467c15ff8edac68da3368307be710019cc73af 52b6e9e81e004a4d350d87b19d86dcd759429a09954105b4b884508d0fd2b022 194d7708a9ae555cb73ddcd4b5e41ae54e297c19b03525eadf28030b16c47388 d158efb1f35f7d182a24ae62a543440c932d48b056d62a6bca8da8fa388fa251 6aecb71bb4a7ffcd6c4d15bccca66e1f2bc16d4a6c3d75990c3dbd30800d0282 5ecab698f65743d8bcd619885f36e574f28ec1f665847dd87ed66c7bf94bb8f9 5824367f4a299d2f99dba1bed610b421f6486ca776d3b1b3e8ac8e9c7567b4a1 9b1a0a3bd2e544a7cdec5b13861e77c8103386e57710ee6f31ee7ac777d3e089 eb852b565d9a9a4b1175a30bef0ed763c6d2d0369dee85bc28671c7d50dedc79 845b3fa7475922b76431644b6be2f0cd48c997ee497b0e3ad7ea8c3d1061e1da 1e9b85af0b4eaf78c85ff0089c6888b8cfcdd54f876d7111a3df6f96bcfcc678 d30f8e5b89b088b901c943e89f093b40838b706757139eff1b47c848edb286f9 aafba65a11d917cd3b38bc357cea2ea44cd018cffa6fcb9045e8b35501f93ed0 931de2cdda585f0ff0f7f81e747c1c5b20ae49a930a943871c8581dbfa5467e3 6f7ec2a05580bea3790eda02264a371e19ea10a05818b2d1f9df342945276a76 f5a08ffbb5b9317ba9281c7c77f3f6b91b02a17b8bcd51b7e0b2a84bfa0399de 4737d5fea3b9e3567f1c74a6527c2be489002195ec96c75fa7a412fa020c4b90 8693790f118dd039b89e51cfa8b7887c98bf8145dba4a981adabf3e354e45d77 b8a660ce9846d73f1ebb888faea6345ddc5c2124c9eecbab120d6ed427c59f2a 4b1ebf45036321b68ec8b0543203d21bf9a639027fe58261a98b44c0af19bfbe 24b6b654c8f53fbe508e669b3804cb9cd55056540a9b7df24ce403888b3999d3 fd9930b13d52c5d70440304d0e1e5b54a4b6b1ca2a435677c5f118f07e2b36ee 717eaf9e1090b2f1894e4678602a3cb5c0f374858af6b0d4fc723b396353ea1d de9c034a546b2c6cd88154fc9eb766f30b986dac38c3cfba22b16ddcdfe9dc7d 93c221d3be2d20f4ac343b9e67beb6dbe181acfa2e03e80b536b74bddd754f38 4e3424bb19b878f1845783d33117f315a972e4cb8a4f5f39218ad3eb081e07d8 4f254a776c0f3bd7779c82c22c33390aa41909c89ea9bdcad91dafc6e4003050 2050b427b2a2ec9dfba6c86014777901852742c5783c8e89d114938ab728ee18 9dbfb19eb52ca6e2ae0ee44e5df65bcc5e7439af40389244cb3b54fd9866aa26 d8b8df21ed6caea91e075382344d7e63de02addc86beb7d76be24ef2155e8353 22662c59ef7015896560440498100035ee0763c5a6de0b263dca397058523c34 0b8d591914e20c40bb5fa99de44ffbaa993b8fb08938e3f5033c07f9e4bfe881 55f9e2ad6e2699c81c525daa2008c323a0978a3b85dc99d591dda69f0aacba72 d228415156119c0157cccc74483b149d443a4ce32971461239627b7aa02a4b89 e8c7e96a2ffea407a803eadcf5ddc6254795c329a6f7332fe8220bd26cfc83f0 6e14ae550d01199ae9b978ace5b382fde0807d8671827a75f3951b18827527d3 259bd7e461198a3ca17d4336ed9f6214cfd10404d3a6f6a9a0bbd87c26bd9076 25e4b2650205fe5dd3c4b1ec5677389b00a4912b5810622b505d72125200a42c b38caff798124570938f7d2e92aa8b0a37229020355e0525069cb2c2ea16eebd f6d09aef0f9a2820f555475e44521817a2044a407da71731aac20fc4b6f2c26e 1fd4bd9f88327912a6c6ccf04009e9bd3cf0fe43fd654e1fe96382ff0ca4c509 35 4afdd9ce9b2cf891a521ca6030b377d52f1790a5b30f3bc06af012ec26df9108e67a76dc1e6c748a35fd06f8ba5947a4c4ee894896345c0bbd7dbf1b632bdf019bdc4d3741a904daceab5df2f650fb419c46483ef9b6fa02640c5c80aef11f0c1b36ff945cd67dc78da67e90e7003d95e1dd2f343a1a302ce7d91d1da7c26600d8e0bd5f66eb9fdf11ae5871908809afa33a4231a34a3ca603247cd623ce7d0ef8b62e82d48c5d258ee253f58dfc01b999e6de56666f6f9ec2356da0c9abbf0356a404246b99adff9e66f32e2e95bfef63a46e4e6caaa9fa7f1827beaa639209ee3c6b5ccd0f8df3d584f0519430ec449f7b669d34844b2a1746a688b040e60af90238674d8d2ec47900141a6bf470c823cdb36b717530b52df807b7fa01540279022b502bc50534603d38f8dad001d7378a960152454d9f0336e8df9cf38e087662ec9b90f4a43cb141ed49be79fbdbeae47791067673b01ab1cdf587886c0ac9d70a206f65754dea18586d384a9bca6f30db22b04f31d63bd919b6980fb006e106718f2f8b7d8f9f2c431b5d985cb36047000f8e99da44ce6ea50cceb46305097c447bd959ce3280c3f6bb4e455c172936d8b8bfca3c7baca17c63f8dcc20f55809e73a9b5e229019baaf9289ba419045981b6194a7b810c7c64698256f40bf4f5f64268a13847ab2aab05c587bb0a065ed3b2c2c98944a7736aeebf4ec60c9de4c7ef0aa74044abbd78800b848de18a5f33f48f74890895d985ba470d2c0a95921d22e5e88d7a746c84f0096c0543b2f400eddfe4b06a04b634b25f2c43060e4b00151e0862dfbd0c882a5baf3875e3dc574d849853992fca4e8edba64a0bf0c0913a5c2caefa9f1f372b543e2fad581659bf2b86d04c32b115b57042e601209fc0dd5ef64c69ba67d72ba389bf4dd478102e99957a1f8a518d27951343068473675f372ba861b895a3d102ed8f1c0c1daf15951b78d154228391f9427900aedf7311a79fa594acd29311df3327a4bd120f13cf5ffeff1633f98558f5090be19d0aed620e35626443a1d0fa9a652016852742d2ba5c8b9844b1a766fecc078e2af3a65c49bce92f6fbf377fb44d824ab944699d9d26929b76b8d42648e8039d42b6d87c1a57beb98ca6dbee45ea89876e6231774f9ea1e4e9820b4cfd5c0b68486b6d0818df67145d0568b5d8c87117fad3b7f94a3a3db2a6802a574ad804c8dde57905880fdc9938901acaac91fd867d2337fa278896e962a0e74bcac60746cbf9ad449a07ace8ba6df78305ee8e1e887733849b09d2df7c4feaba75920a7d82db7d14e3452c0ab08ed08a4d42d80aeaa56f41d656592966b6d6b542890efbd63209bb69a53561e6e28176c405a699d3dd358dd6e00228e824d5167ea406a9db3738fc77cfb68c8a57392186cf3ab6bba4de90493c4186f3f4cd06552d098393de955a26a0b1e600d2357c1bfdaa7e4d4002172f6f6695bfcd0aa752860579cb787b102c6531a07aae7bc8e379f3171be8076452f6948a47142216267405c14339ddbec39d2263c423a5c562e2d89daf434d3a8159300c14bbc3941ab00e4c21e550e23e9c5e6925e48e83eb1a9aca0026ed9f45ab4c03bad98cb110d40d11cc7e57610316979b40c94a91cbf83f6200ba942a8806ba71e5b82726d3ce04d68229f83db82468dc6ef41f40c50e4609d06dc817b3e26a751e6362994e6b0cc599c5b863f4d7ce46af7dd8168335207e08e6aaa0f364fa8140851bb2227e0e5cc3f3f2a3655040d32ca9e318f93b86955f67ca2a0acdba5a7ffb4580a66b08896cb3776b658aff6a7b2f1ebb25ab20d39d87a5f1d2a1ee7ac8b7dfb66848076ce1807db53c6b6e58740603094bcaf45a4f551baf0a2762069ea1aff3186c0b18dcef53704f18d4a278335f80b0b4a34c07a936456f4771d1c5a095a6f72b0fba9c665f52b552fbb94b064d161b4f1e173c9b99ad9beaac3017b73ef1d3590d0130db21fa48cd48cc974b963a2f1a0f143072747412921591ad23f0c3e672046f00914f388d1c0ace9a08982c0a85d7c2c855e846825632f329f627bf031b093db8f97e2cf66318fd1029c7b6f110697a2def0135084edee2e755bb8a38cf0115f7ed905d5e878d20e2bebd237cc6e1d8700675f6a745a9e031fa4826e2f7052d41aa8697b224afd4efc0afa3289f74f86cee9319cfe8a5b068c16bc96f740579d4a87ea6e20cc4894b491d85f3f6bd5f53adb07773fce2f6ce54392b5a44082b22fc424f2c0275604dfc881523347b8bbce18d304d943bbf47eaab8fbcd703bb6b3d653e40d81997058aa9c62317c42e788bbeb61b523fc774fe8bf675010778fa38987d06b237d0674b9f5d0ac8ca47fd9ad7c9f7f9a66b96a6e55ae3bc0ebbf96660a817de1f1448d2affa7a8459909055d5d66a7cb41b5ab4242693470875227f888012926f6843cfb89adef037fe8db4ba1d1e17953e8e9e6aca391606d08a3b43186112e735d00801b77e3a8f5c330e29db8dddcea26cb28409aca509faf1f4550c5d8ebf707cfcb40b4c8873e50e5b69c9bb214c100336474589d80d27a8b503f6c916f1e795b7193d2118c7a4157f8d198be9cf967eebea6a57a205ee133b0ccf95531313a693c2bd64995913a6625f6b83a91bdd7e83788d6b010dadaba59ed93c4902a23babd4f0246e87010618ffee1aa720d5587d9648c8150a7563e51f340de57f6218ac5e719dba15be03df5a144d52a6fae34b6d7f9c7d0c9b3c67f28b7fce791b2364827e41caca673afd3951b83a5eeced6e013d1e47094253c574029339e7461941ea2683c325e42f8a6a63b7998da597fb81532771056ac413f98c97ad74f263605a3228e081f0e93075ef8f09dd8fe863c964c92f0512face777d8d42478d812f33befb43aaffa3b03e801ebb7234afce6664bd230b96a7809bf6ad1dfd5462d5931ea61fb8e55daf4cd999e1231c2b4e068012c50ad1ff32c4b54efd4c281ee54a950b2bcc1cafa46bce884bdaabf277c8ef589606ae1c919a4185400c197f71a67c1c3b6a26a8baaff87a3c4329d5da13a6be2908e892daaaa07a9d785fde0992d089a2cbeede5e10fb1afabeaceb8c94ae3a3a08a3dfae81709bed09b3598086a4a0e1e586df8bf03e23a0a376a8c6db5246a30ff62e46a5a5f27b3f865437a4253b3efe4255fab3eb7d8fc7a1518479ffdd5f016deb73da5dd44c141cd1a74ce3df0e3fc01ea8a11bbe3afc708493affe98c505c14dd5ec3d784dd5bbb65489a926d794401af4464a81fdd41c10f5f01ccd7b0d45417765c89cafbfe6723745444159dbbca31e6ebb0fc637b34485a207f5f90bfbfca520d4bad2b4ff3b91bc29f0458c2c3b8612fe29ed6d3c0244c2d6c22f0fdb13e5088ccbc1603a9b1e2480a5a8b19b01898f8695ef57bb7205d8a9287a0783c121f221bb615036e9a333aed788d4ef208df46b1cac1fbf3273787e055c0cfcb259073ba9bb09310520808821f9280948ca4e2072662fabee3f062eae940ca0b0fe6d4e2db78fc1e29e18d9fbeb12d6d7dc4adfb72e90488d0e2c77478901af88cba160a94b41cfde1ccc7f22ab3332801628e6882830a6e42641ea02d90d0310238561fba2423b43ef75f003606fad9afdbf2a040831269f925715a0c3034027cc831aaa5cf28686c36b3b89389ebea5e0ee36457211756aa3dc9bb51c0603aac2a84f1ebc9e676c94e17dd0750ec5ec22fe87a5a30737d04899a627f00c74c7837892028f8091b4b7be653f9cc6ffaed035f7a253e1f21258c3e2698607541c66f1a6c42778e9d6b2b45e53329d4bea3cf04bc8b83ca250f148fe0b10034723e0e38513938a9f115a576d385a6dcc3251aba17237e57b5d214a5b19de04ce4af3634d5824bd124a48a727f318404a87b9dc9cdef7f6eba710e46e636d0763a5a5b5e482a3f46efe1c2cf410f5a77e0e7f3f8bf0fd361f3e7f956da3300800d47e4fcccb3e7d60cd4c9c224acd7942e693e7d7b807025e8d2f8dbe402c0db64e5713ce1aba30c0eeb1eb99cf680b4d6139c26abddcdeb94f796298038b0d0ba52832204a46bfa1f1721bcad8101b914e712bbc1ed58087024e514fe0e307a4416935c00a4b811ad4f78a77f915e25145108c1d683ec8ea85624a1fd94e070ef4a830e2f26f3cfff0bb139da3f4aeb31887d6dcfe7ed5ee337fb6fdb0b70b005a282bd0e9deefca82dee1c1bdafe99f3030a15860a5a33e2c043e3504c10da2cf11a1307a92754b5b807907913a35a9a3b2c3ff565c5183b38cedd4e5900acce4a01df53611bbfa8c9676e11ba13b1b5b4f44121916f87265fed991350503b9f090c3afa665baaa3b7669eb18403bd23a43d4bf247c3d9a3533eae3f3160dfa97bdf61160000b2f35291aa6c6847fa26d3071ebec8793c66dfe90999ba209b68b502eed1db8f075aba8ea7a02040253a5303709f41edaa33bde016882600c2791e4a42f8ae4a55ceba608ef1d0a9e75557ae8a66a6722d668fe29ba229800b5726c5dc041a76b2771a3d4781df098635c8271d5d0c5574a66ce24e56bd9040e321abb4fea1269df0333724ce8efd47b15e9cb8d80d2083c6768a96f4dd50a397fdc04ccf538839e255a8b38fe386f11bbe0d715ea61b8d27112623183dc0b4f958c0dee540104d3b61ea658c9fb05d371a03ba802dea9dde14b2dfb771b0cae45da2764f7f6ded818ee6d0a1032500f327f48335c3928f7fff6af469206011450dcf4f203ee43a6cc8b41d331383eadb09946cbf5956f79c8861ca610610599e858febd45996caad51720ac8d66e075ea0bd4821de154053337fdc4c3940e2e6acfaed305400f196820eeabbf17876ff2e1b9070a4f5c011f138bb0e797065ea529739b3ebcc2fb1a5563f62844562850ca9f994c235fc088c74ea9fe7d04200cddd1d260614e60de29323a0984bbf44522f14f9b032d8c8ebd1f9b06ed05f3d5958ef7fc1da6e2d01fc0f402e4be55b48d3e2448e5841ae2789f719ca004bc072814cafae46928669642c7b75add8d184f88c5ec2465a6c587a556bc110598033b7b6a9454754abda131ac45dcf195d300bd805244790035c644a77cfa039b26a7b87be7eaa3193b660cad41695bc6f7039aa2395dce1ad76434d25f6e010136a8b0d1190d59a2299bdf3955480344716df405d804affbd32b88db283b006187ec38fcb5a16f4aad00293a833e68eaf73a4ecf5afa60ffc507f709b0e309fa9c51aa73e4cc70f927ecc5675e839176ae7befcf86fe179378b4d1898ae400d20ca7c6c2c3e8967369e52e2ae41397572775ec2583386f3a1c2a3d30896e0d07ef5f31b4a04bfd61f08f76e02a9b04bc75a849155e8bdc9a3249308ddfc6007007ce7120d228bab4190ae42a121c69ffba72f122cea31eaf9068a1d355b1054a6295dec77ffbd824afe5590c8172fa12fc6ae6950785a101b6ea40418a2506b76b737479e09af0f99186d14de0f4513fc4b80457b7d80f3f7b95ed9d3b1e071499d968b1945b0f91bdb872acefe0be0f984be457ad3592ed052e958480ac03870ee50c593513b6296ac361fab232d53381d251ce8ec4090266fbe5adb8d7034302647da066e492641819592424f619a38abc7d12b2493823334cd3ef612a0bd8625da2d21a37dcecebf1d7a57c05a6e8bfb385708533b8084505257d888d02fe0f7fe52ffd1877cc357433a603d29ebe9c6b559b4ead2a3fa7bd7985d21a025bc4adac4aac357cd8b97546de4b24bc4a21c01e0467f61115ac3a948b73260ff8ece22080def2552d2f95aa2deff214ccfa02baa34dd42169260827215c320499ff5d6fe90b58c61cf0cb52c36e182f842976b1a361c12e61b859609b0a2b03c55a425106f31e4e344b1ca3e2464ad705964e89dfac1533b0c3f48e829d7e004dd12af36dcacb2945c1963aefba5d71888aeb65cc18926800f7a02485eed60b724cdb27b3ab18217911f2d347fdc35785e32c640425a8a41b30224dde40650fcab569576fad67a98a70bdc5a9911191bf731d855ada7d2ad19ea0b9588c800ba18e098bd0631f13e54a03d4b1c28210db97b607b74ed02c6f312e736169af0f3fa72678de72d720f86a198d378b6873581c186993cff37292bd66b2a2db75011b0dfdfa67ebd77e4c4e1387742e1157c5f9d0293066ebc5327fd010f9e2cf0859c111085eab993e42c8adbc819e19f54a315534d6c682900db08ba33a09b402bd0c0a3697346b315521c1cb49e8c8c551c57fad7f54fa61195708d6ed1ddb04a967d8e2c35a9addb5b0616650bf3256d11dc75a5c8d38559cbb8cdb37e6810b046b997049a2964da6fa2cdb506e79afff50230443f601257c90fd826dd1b4035b0b1652d980dd8d066b247dfe379d5c47c2b6779b5a8e9f9753f863287f7f0fe3892d67f4cc4aee6835b9d818b118d09fdfe827f5998ac704c1982a76fe9a0bc9369c4839f9fa92a10e26345cf3bdb893693f60cfe9e303f926b22e3726960043f71c42a900bd067598ecc4067f520f8c877186efb67b43dbf03690d14ba5072c618b198635473135e3964fe55638e5306eb8b89447a2bf33b7b5ded2dbe701ac43de1037c40455cd2bd0f4b92fced20560b4544e4623de1471b9b129323a077cefd2bda2156870c4d3d22a2b82952af40593d364a49e48beed8ffdcad2330d6ae95f9bf156b0931ff1bcef9d536ca619f31131ffbec74636d1158cc3f6d7059bf30901a2c96cd87e1a2c77267afebc5b75e4ed22255deb1b005a3cc1d2630ec6bedbe4467bb2ca4b73457f504dba5ca4bbd928b80798e770d77cd74831ba051f3e147741f0174c68029e0d59e03bdb3fd108a2acf8a96e4f422d537f03f2039d374c851216c433dc0a6091e68aef707eb76951e4772012fb6776e96366330c1399d6470c69d1b04dd51c2320fad7e804587e794a0fe56042bf729553e287088f226e05ce230b1214b3e605cdbc8c1060ffc130168d1775e7972a645b20ac039ba823b5de8eff9af4399ece8112f06a8b5c871918d5977f2879ade0d225d408bf66042a6b1e6cc847c9f7865228d3737a19238a20bac1dfff6e0ca9752d960c25a8301a0ed70ac6abdb61e1f987081d5e9b834626da0c176fa66681e2164f079f0a5e5a0f4a205b9603efbfaecbdb16ad34ca64df2bab9c754e087585cea304d159bf4ec959d6b56984fc59217fc42e97315ce059cab3623bf45e16a8d9920c751718d330337787a9ffc9556c5e2792383d915ed6fa92603fa49c4fcedb1606337db1f56172fad5496b4109c201ac8af858f75452bc4f56086b9b369ed6910887c62abd33b2501c81e0b263e1398a0ca031f10f91db4416987bc552470eaa0a69ffe32f38f7469c44b4e6cf669a25d9deae27a32d8af292d724b026508377012a24f8fd21ebe2183cb662b1aaaba8d79c1f35e4f016764dcd2a61e9a3e7c80bb9c337b526ec23aea6fc68fe9e80c6b055f331191fd317adb3d83cbbddb07002ee1bedb5829d89ac4651ac3ce3318cb794d5205fa1acb3ddc6033c60dd5c020cbcac5fb9315cc2b4424414f7a373a4da5843a7b438abec1d348d1a62198d240667cd78d6f67b8e28212db0adfd4ac29d544effed0bb6288cd009b257d6f76e0e5f10c57ba00f9148bdcd1616adc7204020124890bdf01652617d19f9676ed70c630094ebe0aec7c9ae2210eb6a03c169d04b693313758ece011070c08ec6fa08c50ff04f6929174d8f6bd76d52fdd9a19956347530318e5aadbfbecd8f6e430fe9bdf03019c9bda49b8b45dd6a593a137a6bb42fa12d00491e4653300a59370362dea01ec38a685b58406cce0500540595d79351adecad060bed02b404ad840628f43bd0a8f9b0428bad5eec1e392ef2a3de056c7677fe450d5d7bc5d7800d06b32ebd84b79176f5166ec633869702bf23fddcfa7538d69222a19fb4791d350c38239903d414792102828c8903232b4c2cbfec9d1d53c0fe33d8882be347a4095b7ae9a982082797c98b030be27bff6b4623a37d6b3396a4f56ac545e74a5501edbacd9cf5c98846a47c6af9e81fe9f622b260d3aac0b4342293df67a068750712712966dcad17f47bcad7360c90c06eb81cc61d1b16d840556c24fcdfbfed0c54274a05458a995d58bb0fa421964a54b3031fe9887f13c7f80a8418993caf0b06a3779dbb07846d617c645732809d3a286a0320a643b56a65ccce0e7788240793119a50d2d47d4113b72256a90d5feebd424dbcc58783b7ae029b533df9500ae60de13ec48d30d6681c94596223a3e6f31f67bfa1ee86e054006ebcdc813b012ccfa23615bef1196441766158b7b6e76b4789f29533ef80af3efeb200fa460348f4548ac1c448348f26878acf8f49e896a0aaa75e44c021eda842d35918d50b7e98049b4c636cf5c6c2f14361e071fd5cf082e0eb6f957cd02496390a212d06cfa640e1de08c15b308aa946e1119800d00d7978177212dc7520ac183e02970870aa22b16e29eb828361cdb104973a1942c0fa525cc955712c39dd56c3dcf10ce647ca40722adb7c18e1dc458d87724144b89f56a61036a610e54d7ad7eab506b2d0de75d48ee90a5af4d566b784b3d4fce7314e95564553ed6c4bb4b579a8050398b909d7330b33d28aac3ea097cc4ca4789f7401515afbc0d65896f4761601bc7037b40e746cd17aeee78fda1edc72011788403b33bdf5c1fdc7f01358c40a0656a64ae6f9e7e123f3feed0eb4dd9d972d258404a1dc8bbc05cef2090c3304db27144e75153f789feefa8f1115b020233906c8160bc0458e7d347ec404440f9f541aacbef1b9f640e60e1ed4e473242e47988fb941d3bcd863d160bbfea800f59cf1fe64d6e5d959c7aee993129887e520a0dd4b4f9b1598b97afd8e7b8c0dcf475f46b8c826f9c2aa6a643fd44d488f13d10208c16d7d881d5297f758870f033e0316414853e507699f407073af47fc524af1d2ecee69f20e3e2da789e80fd5cd632247aeb256c22d8b8a2e4d73503063d0012ce4eb967e1e4d08e9e4be0c886d77a351a4c3f82c22ed761eafeb87dbb09da667f6b01ce23d29892615c604fb25e9360bb86b7719638abba883b449ef20809bbd01d6ded1581c3fb855740a17ed02d464bef0aa12df75897f5d1cdac3f1535440435bf0b5a8824bfe6f0208976bca6f22edfebdd7cbcd1d94faecd549da31dee042de099bb57028b2b3e1039d0e072c7da8b7cf3463ea9caef7b0bce770d3f6a85cbfe153f58dc1fdaf8a09e5f2df380e2d27f5278a0d5a2b00410a563b1e6368d88b85ac38ee3411997d0134e538d976bb4b8aed41a527ce1b2926f101891b102800ca34aba4a3f623df0e92d6f0214b3f7bd4667e766e3e83a54efecb2e9b77c99db254b054f904b19d0a478649d93baaa36af9016c6e9a176877e9a7f9e04773a9f2c747beb190aa3c0cda49713d1e24ff4a6f200681f0c9c11c4463e37d2f366b15a54ce815341ea5073a12f34cdc89cfcca90f727d478b0d67d4dd755199b9493f16fdc9a50c373d07e08df1bd2d52a65524561b817828940eeec49aeaf86ee22f81271aa6640ff1032c342935c51b37f7f2bffd6686a050fe16241ee8fc836b174f08ab15131a2909cac1988f337211067071fbd0eab76de06eca02b7d7e77b65aeb641b0bf1a8f03523681161d5777cf307b6a3170fbc548f9cfdcd668b17d02fac72e4f5fca3f066a442d561e9439bc4f96af69467b27ca6de1e9d2c365548e99d7eb2f4087ca0ca14ed79531f112a033aefa64fa4ebf8248349be7c8b00a6d8414d28c681b1e082272b75753907c43d9c08d5d8d25b00778e2c0fdd4893c2d85770d09593cac05d50b61abc9c1e73bbc2abc8892975f70b2f7aa25d80e7e1962623021ce594408a0e02f3fd8e0c5dcf3b3deb43fa79062bb026aef3756bbdc2782eec9fdd97b050886c8fdef73601729ac93a00eade0026ea6e8bb73b651f66ca3877c812d600e790b691d20c2c30d695709bec05239afd15d5fb220279365714ba75c5f874b03b1e3ffe33ec7a2c170c14b635234c2d976f50db33c9d411027e4401c545e0b0b5135cf1ae832d4b62587ace504ff21b039a7ce70941633a7f5140674dcca3b0ae9c071d6960e92259fdd7a90cf28758b9305e6f1e4fb5c464ffbc81acd32b50603cf348028ec4961f8a0730478963f1145889fa28e9ba87c4cdc7dbf2310eb0a9d94ecb72a228a87706da1e4c9b3564f69172a39663219c68e4c7daa8ad4200beae6d421635f5f24274f3460968c091c6fd05efcf2130fe3e775bb14b40c6d0bdc77f81728b5982cf7b46c5951d2688168532e377ee2466e6295a96c35158206c3dd86e7d55e3c3760a9a9eb42a0aba66435463705f9fb747a4c944f7950d007e5347501b03293147a73bc7cc312427359d8edfca34557b70b4dc1895d80a40f753bd8c42b0d38cc3515c05f50ef12bc5d34cab0cf6820669abf85fe66871c07e344df3f74ac05bbb7270e51cdc2768725c5d50f458e7421c37de6bb9f2cbe00e66e46139a1f40742ad48310f09e98601ab636000bb2ba047df9f232e29ff7095d68e33256e5ff239ec680132d6d9e915bd563b3a0612edb829976f620e9ff07e8667295b7ab8a1ca7f21ac429c6742490492c53f4440920855cfbd132df500ac27676d1febdba85a616b17e5b2bd0d6a110b0d258c63f663f0922c907f66d052d2825b622ecd08a3be6a421db918bbc8a394e5b3fa21b1e9d6fa4ef6b4d5c0105ad1278836f10ee948fbd4cc7f33c76fe457a187b11fad96f07a5c3b4c61601c062a9484c258d37abd2da09bfa1f74aadd31c850138b69ca03ee2ac73362205eeae22f7de0fb04782cb2a27aea68a31f31b9639af77ed8cc7c6e7ff1fcfb307a9800c1c10dc42efbb2098df81096ff82b4ddd6fbc1c4f4972a252bb920a930965df63a2f6c3a554b571ff23ed60dd5d430f59c60761ee92883b27ba5cd3e60074227bcb9b44997e043addfab96cb438f4feacab64aa12e06684e6546bd8e608032ab771fc1b7433fa0fc42ccf837081151ba0346322c587c7df4aee726e620667d1b509d5b093a3c0f70b130d4be2ff196a16df768446c97bf9f7d6e0db4306921052ee334b04c29e790dabc94674bbf9b8192eb5586ff4aa0c94ee66121d078daa862be6e228085e30ff12e4d17b50b57448c0540d74b0da051a241c7b3005dd471b450c67fd80b59178d227ae0ec3cbadf7fed1f99e017c1098ff5542680bf6e54fcc2ab4e1cd20e0cffe22f12152ecff46aacd1482ea10f56eadc6363909e256d2beff3aa78337008ec9723abb40ce6a8dbe17d43d0ce8d5f062c999600176edc662c93a3ead2501295b827039bc5aa621ad1ecdbcbe0d132602cb9c2505482336c253cde5639ce3fe67a1d660a4aa080a74ac876d5497c448841434cd08d2fba2c6831f923b1634a09e599da97a7606d10baf902346a5c3b92ddca0d3078606e3986d24d5cd5c1bd1c7a3f9d44325f081c388ef8d2f76dfcc8339fbda00779486cc3f8f7becbdecffbb5a918d218c30ba32c2a822f63a8536bbb9fda2085dedb86ef1f3567b6d0b2555f9504fabbf5f889fb1a517109a71dc961f75de06d8519d69375d802b9cacd2dece92e6b837668b52ec32d41e093e184345b8f70f3f556d19653b10b681a67ec93c54af13f6e7608a17e688e65cb1300510baf805f64f49b9571a855318ae1ca8fb05824ca7f1492db8f6d835033184ecb185e804b17f4e55db4439eb2fa94095b7ae4228f7402452b3efd473afbe2460ea269a035df5ed266089f216b9d7e16acd0bc1155d92d3b174deaec3b3dd1f3e2b968b0a06db920045ac4fcd7bb6ef27f7f45ec8c1366aefa7170c3d404b293d6339c0054ca8a6ac94c9d75eb68ac095f9c7688cc3efd08573d0f72317f3e32f0e3a13028ae25edbfd3103c13f0d1b03e326566cf25266276a1b64a379aa775354d0190cdfd8f2c203ec0b1298f0fa835405589d55d4b4f08294e6324a5ebe1dc1ff6808a93822859fd379872b174f8eb2c20c2bd7c307c81aa37e1dcd5cd2a0d4de7b03e0c033161cd653ff9e52b7c13c9fd951af4642eb4ead0587e2ae20e37c6b640d2255b7abbb9ed77314dfa8dfd97792537c0e1e7e3ee70a0329666e49b88d8104baa00dc0e4b257d6183f5b063a25e9d305cd46d4440583d6e2bb3ca35c30c00faa5a78f62acc5c0d6386b32bcfcc1161321052403669bbc16d3bdc414385b60f394a2301b76e5c3f3f389ebfdb2e0af058a7090be2b7c93620dbe8106284900eecddceb90e821771977e29dbc75bdf1c9a4b16334ad85ba19b8c0ec932cf79007c43dbf91e4eb769e51361066b79f94de6c83ecb3f7bec8ccbabfbc2d266a30380f1eb10559aa693631a4233239f7b08ce11e3009e5b7caef714638755b5450374644432183abf91c2b05599e16d4ab248ea9e19115b810ad54c602ffc69e50b644caadb02d241a7f50e8073a0eeb8e784e12273a8d90d5d4f421c13a3d5f3017ee68883f64a6742444116f1c49cc5adb8cf8a3e294d81731d9278e3f881b406a266bf1cf9c14e5e48a6abe135cbba1174051be1d95bf6dbcc417ee654b8a50bc76968e04211bbca98e7289d418f09667afce3064622bb5733f6801d9e93d20a0e75d6dd6df5a612231bb868ea9ca70dff09bcd8327b81eef9077dfeb07fcd0b661cc09d8c28c94566888fa4e91a38ef9d809d8cbf7c2a96d42b81c8f32a5804ededd5fb230b3466dc5e1f56197a4c567e03192f1e461f52f18d525c80144e0c14c1372017135d52450c930ec01b4c0ed2075e24792f16f93c6a76139b9342026eb0b3106262dd92c7b55a90f9d3e884872126c69caf14a8d8014cc7f26bb20d3804aeeafa75268c4fa9ed9f5839b156cf54c79fec2f0d31fd9a117c780e1f0503562a24958a26822d8e338ad6b2d5ee88760cce0912cc83ec9d7bf150ff55069f968b62d6da1561c19154e3f0c37f157ca7c7e454248cf3aaa6ff74fa465108c27b0d60c09ba38e9373b014e91b39f1ac35276c7f136adeb73b43300371ee0d0f6a86726f2bd80e55766a4e2f9e1f9f2c25a81412d489b77708fccbfa7bfe030530f72653645f666d82c9674cf61aed175801a191fc1601a82ea0009044ba0dd14580081885e3ff96775735c7df0ed9b96cd3d8eb2daddd8d3f528143070605962084b919317a1dcfe053cfffa5293e76b4fdb8b08bfc2c0d9da67312a3530b6ed45d5445fcfe67ebae6da3e1c2a58de06e6255205a27fdd130e476c1aaf6026007952e4d2646c8521f761ad029083f2cadc38af0b4a9b1dac5c3fd36f7bd0a85067ae4b23b9ff85741ef3b53a729f492c0c8bec7f9049b4be7bf1949649f048eb45f80cf2a0ff4f28f5b0db8087e8fa748be298919f685655bdaf89f6b620664343951c0184d3aa11a2b7845a47da4ffeaf75514464466cb32eb921cd2680a0585f660a28d21da67eaad8bab25fa084f8a2d9f362a057bc4426077a261040b8cc31147dc38d10fa1e242b1d66aef3a370223944a615732861012ab156d5304d60ef10cfbffec1b6ab4aebce6f25dc127c4c03c07febf1d2939b675e3ac98078f40d37fc4611904476af631b7a2b77a356b4c45986a4e4ab9bb82c676115a008492833044d89a4630ef78b87b74233b1274c76ad59a9871e7e335ca1a0df90bf55ed0c80b84f6a8a43e645e1bca9ec5e22bbe0d8f065a3110ecc1fda7534f0cb0b3a408477e93d04402a9f19f64701114664ae871f6483d734bfb3f7074540d168de1e3aeb0f0d660592cdb24dac3731280b60372459cabcf3bfb1fed2bf2047173d1fede108ec244eb1216c75e8b0d82f856f3a05fae239533c70c657177014be0201fdef4c4376d35f7cea673d61c643430085b24c667d5d1e8142dc57802e16b847045db744b472f0d409f9710b571111d8d6062464f867e02a50271090bb7a80dbddaee992d3b09c9ef54facfc24680c9fcb3c32e3fe30f7fc8e4aa8b0f12fda6b1faade1deb60924fea0055d24a3a689698e794ab8e4cf32a42d5ccf04b84d4867e5a9555365fae23e70ec38a183cb74550c78cd7996f209c04f10bd0acb6eb3a27fbd90bb38e53a10b9eb2cd0c68a2b2a5ddb3df6c86696f52c9f0d0abe1be3f67a3fa92fb85b52cda4bbe874ad1882b9ef9223e2c1d333f65c92210ff63671d453db964ffba0f8239c02131e2910bb4c6a6874a45a32e3dbc558ed01b741228be039c14eca86427205fc5003c9a75bd8c908634f9dc5eacf3c98c60dd79a5dae7ec16b432cfe720158cdce0aace0b874aac03a75fcbc9d4f91cfae0ee84888b230ebf0dcede39fd808e8ff736059094da5ebea2dad746cf199b3550644b9d1daff0da7a1255ee669c44ebebd115788cab8d9baf09454323a507e0200dc75eb17af2659cb89f17faeaebfdf155363f5a0a4feb7400047715c9cd68f09cd659db80d8f77f40408efa50dc621eeb53c38e39fa7ed54d0033ead2101a4023b510d8c2b0ea7867cc566b2df81d226f690b179cd526439284a8261a8902f04b91dd0303410fe78cf091d87db65454ec11d9a4ecd78cbf51643838e3afaf405b620010e2a0c03711af3a53e463a1b4ceec7fea2ec8dce0c9f3a09ec2e9d1d02a5f42f16f729be1a25a2353917ea1c599d8b64b99827ce87cee56a7d364f0c08a65d7ce5ab9984cd84c401ae3cdadbca83f6624e6a4db2bb730a42a21075cc03205dcc9708260173b322c19eb7d53dd446314b0c5c333e990327d7293495e20003326be5a6cbba34555404a114883d26741d4318cc6859ffd88e1abdeb27200a470858b413ee882dbdb29fe9a6d974f3375e2ca484c32509f5c017d3c4058c0fb8fed6c5e209bb0e55935874dcaf290eebfa465347c1bdfd656898f67e8c240ff5484de93d094a7b10b1987845befebded340f90480f677c2d7ec1dc2bac3c0f2f8d1cedd8483edd8dc20039fb02261d375b788da6e4f88bd6bf95e1d4b25d08937515e629c155c74ae6242c02daaa1815dc4911ef0e160a13384897aab2360dd53cd21fed9dfe414cc82e279a47198bc0798e003260ee451bf0623c6975160af198bc474af3b7f97c606d96708e262f3bd9b6d124981893914d7a6ce59d0d0bf520f8850a1356c842e5b773b7c4fcc9968ebf4b8cbc35d7e49b61a18d783f024c252f5e5578762d67d90417560ffe5d3d43173a78394c4147b2afa5f803170b2b3f5c1fbe7906b0d383d5137d85fdae947ceba628632cd4a4b716c3587aca0a2d9ebf03b2fa4c9e1e62352648f5c2c5e88150f5d8e7a22c7fb10cdaa0e804048909cd988eaf170faa9cc9c81eea6779163ef4507027673c3c87f876392f270d1876fe7cf44709165611c7814a7d97aac477af52d92760be03fb9bb5a016b00d8a124238fcac4f782696a92bed8d97a35ee341930f5eb96bb83b441dcd968007a49231469ca502e0e39eb68792bab8200f5eefb2e9bc0e6540703ffac6459d02f7ec9e749e1ddcc134ea7afbd346e3109d7b746bac3c63ed47efdb9e74f61f0ef10ba3bafba5b9a53fbdd84c25ca5f1539a1baa68cd44529693d474c4a451101dd575853c8e7d149d6f350d834cfa4da694428955debd45008ed28e10d04f100250725a5940f56b6b66767f0118baa1a54642d610e9e4f58bb18a07e7ca5da08571a351763d9fa4065f9a36021fdff0d1042c405ef847c7303cdf092269a680cdc5c72437b75d71306fb0d7db99f6635d5f384e502901a9c23300c6cc8dae1037a85ec96a12538bdce0263eb4791822c4200984c28be68a82b0be79d02976d0cce3cc2e688a60b9d83caf08661445b07256d790d6982817f051b97f4a593f3093d2d135cf780f7d0ec4d58ecf201b9843d7281cfd0c6e203eaa0120b473fec0ec85328b811e67170eba7ec33388c1ecaf5885165b4b181690587f695e1001e0da014d2622285a91ac52181365aa1b4f4307dd6f1fe4f46cfa1b88bd883b79d02f65653716e90fe24ec9158b21d8a381f11ac073040771fbe18bf5b39f676db0198f7c3555e9192cafd175e351caebd8c96bf66a6164c97b6e2cbf2a8ceeb89068924b3907220711c688f94c001b59169a060634c4cb77e7dab09f7b1a768ac0c29599dd7c455b6748e2b72a7e96da20840ab54d2cc0d20c8ba9b2aa5a6d7490cc4f194c0dbf6f4018e087b6875b8a66215c52499ff22d10c71520ae9f4f9fb0f3223fc16d58d04d653b3ec085af7277f28b7f08e1472613788a1d43bffc2370909d3a1f88dce132ee2df2a839339cfc502a7201d89635ba243832722e5150f07749204cb85bc5cca30f4e177b578c9621660d17966fdd6386f4dea45e825a20f9b59b8b4de70bd3b7860b09e8167bf88377c79fadcdb40563b91ae3f7da6a709bf4922a7ac03682d7552e9d7396be0a5c728e57757acc5ed9923036facc6ed0645eeb7f2c6a07b602907a2ee4da70f292a219404a0997b7729a52b3f2f546604e2a3dc4b12f6ad6e2e9915120847c1c91d46a0e13b1715a92c7bfa48c7d8480add8b7431c884048c7e530bd1144b7b2626680f70a57a9c2ba5c73545c9f89f0173f8c3698228167fd686aea41c27e0ace3b81cbe69aa74bff26a324d6604d800c3ee9433b0979ead3696319102e3024c83bdbd35a5f34264becab480b4aac50414e2ef4368df08a5d1d3f7e895cf2830c1c09e8ff5ea527b966c75bb07a39a0b85dfee234520e39d237446f28ae1c7b2110aa098050fa3cb073b8ef9a215a609234129d7e9ce505b79b10db50ac955c6e8f757adf170f99a660a0f5b6317770c584da3a871196a929f2585bab2462508e40fbb87e0a7147c8b9b2f9a5c36b40e22adc78a4f782e75f160fecfaf866f34a92627965e0854ae75e1ed5e243fd1054f74cd38cb66bf0149ed7f98542bf8dd569e0daeeb9c46bdcef6d6fad12dc00fabb4cdf0515fead723efb704b3a4794aec05fab2cf19a4e80a0c93aba79854013de5a1bce843641c5b30184d2ca391f0a2230c62bd004f53ba2e4011566df1029400057a21803d83301aa02e9ac6381c5255bc0e05c0b44ab2dd94923aaf50046b06f0ab3471b0f8b235c5b51b90f4e84cb3ac101bd33fc3f21590a8fb70d40df846bef3b97de9960c9b32a9fb021c271652f2d0ffe5d0ac271ff1130123910adcca86dd60c54f2ea150842a7ad876e28ebeb7854785ac25ac83d1612d95200fa58ddadc4403459bf5c8de88bda35de29b8eccf8b6a2011317c70cd546a2b90ee6bfd5e96ea87c7845032ca252afa6629ce46b5782ad901c1f8fd7499fde80093c98a5098dcf97686e5ea7000ccd3894f4ff67ef913713c6333faa28e172a00aa7488aab58a6e00bb629cf5218308404f95d3a3a63d439e143eb5b255c57b30261b34d39ac6c7049c6aec81131a410d641244b6dc897ab5e40668a574315170ac818616056412516a73b94cf9f5a845c48b38be6775c0b76f27aeab53f45a10e2c546a8aa21d9641c6de187a60a987f39d5705a409eba6b5cef24a70a47322004b4a2555987f48a485255fb2f236b6f2ac959f057b032c8769473d0437d4c00bfa14c7037b331295954a883098122fc61a206d8c7641c15676175e6518e2c6000ebdb435c702cd60a4eaebabd9c28c600111bfe89aebb50a94eff36de842c60216b8b01fa94b5e50072f5cfe6d89956f7bbee1965c375edf9bee628c9f8d1702df04215204ef6894d814bfa0bd88b7157c26522b3788aff2dd58181bcf98440a6fb883ed81261dea166316e41193940f5930cb4b003d473a66b5e4c52102ef06438e5f7dd895c693a7c69b3acf0d4bd0690819ec7938a82df134e0b95da1210649e136ac162f85682c715ecc1bb947118d73aa13f217cffb58b80ad12dd8ee0760196ae2479c60932f404f2ed1579688c723d7bbd89055a8c6f6d75b370f7201adbbce7de6077976939268a9f64357e6f4718e1a09525401ae5602a8be9f2d078f3bbdb519481bcec7567811eec10a99fa214ddc339b13b5ff092911cb9188079f9c488877ea024fde8cb4fa37fa85dbb51003d7120c6cba58a17371f2d9200ae2667a2d3f8f5cbd84f45c42132606fb1746bcac8c0cc87ca7e94d8dca7eea040b984e9b6f135e316fc91a92042025183eda4acbebb37344f1f88e7ac60cde0ea24d93581b05d60d788d2c1febf98a6644e5d73607a9467d8c64f98a8adf2b02505e1ffc6e946b639855222642218d7eed129ac7a3b97bc18bbeb8824339330b01147768e63e31834ef9e0e892a5dac8fc67fbfbb8c9588c78675deccbca0300a5e0cdb626032e763179942404b9ef462fa24db12d6fbec69e30b71913ccb905a416304aee4e78ba5220f6a75f9a25fead1d2ba414822775de23e81d590dda0ea48e81668c4a2a937eb3919ec320ddad7e0745908515bad872b1967507a29400646f55505de0fb9d6b25e5f940166c858d88ccb324470683ea7e86bf28247805826fa9322eedd64e24dae1539267e425eb720cf3c28b82253bf73cd26bcf820c20c85c2f04a2412164830dc3c3f34bed213f2024a7d4d081dd9e070bc60d2500b2c193d0310a28bfadb3c726c54a0c196fe466c5e2c8ced323a322c488745e0ded55711281a776ac22a3bc7c5cef72fdb8bd81f6b51695a2cf53832fcd1e4600909691417e737b8f8994853277ef4b5035845c3a236293daf42608213992090c110cf0352e38fbd28bde85b126e3229beec14be1418531a4a17ae7e6eb0c110d4920593cf0aad3c73475c522e8504fa64bd84082572d11dc33bc51f7877d94083ede2ae1e97872ab4efb93aa448cf67d6bbc8dfa918465ddd93174369e82910da68d261379b8c536247121899a3db0c4399be8282d0c2114b72aa8e3eeaa4208a75a6d45d091b7a0f73471080c10599dc9f0948f1d485168cd5bf862650f3f06d3af954e97692ce6ef56031e87e3afab01677769865b1543756554e1b5c88e0eb5a6d40f4e5b1a0dd3093cc20f4d9e4259238d3de00cf9f13fd5c32a702b590fe3e0d624540afe8aab9c71cddfa39c40217fad437432654c75d409f0243352032f6747b5eb02ff0871895f86048955c2a895e3226397003b17acdf4e6fcee10b6ba7a94de7600c5451b8b964911d82de6175b90ae72ce80d043fcfdcdeb6bb04e94e9ecf96317298990c34db47c7cd0e72fd480fdfaa6bb25bc2d1c2866fcc035937e40270c9c8730c7c053ffe96e02567b64b496198c6b1bec8f36dd8800e0cba0e8a8001f274105017c73fa0c634b556431f24e3e72b6c82df468aa14c7903bf9c0a7568cc59b6f5196af8059fac305516b7d8ca5a636e5de7a04d30dfbf0fabf8b0b9baca85c3672f674e94c3b1d1cf2de1ff1b5ad03d5105aed3e3940e0ba2855887982bb0012ffef9bcc1b788143b9300d36e3155548d4d5483141ba40cb24957de0db51ee90786ae295112d8f7a14201b30aa0fa5c1ea3c00b45a254055d55b880fe032c4b5f0a7066573260b4b2db33ff8ae15b325d6ad85a82629d0f1ebf913a3bd8ef76332ef71a5ea7e60e4a7e1d2434e243ef70ff00c27f4a610f3aafe8a597d791d503bcae33120755248d622a5fcc9c815646ea105e0342e10e2d0f4b54539a67203ad6a65963083f6daa7b3f9d80edf5dd910ab2fda07e7b05435154cb94c1ab236bb3c9f898a51046a9bb2f4a8542b4dc30115ece5a7327072b79e76d8604a424ee065a9fddb2ee17e85091339bd5aedcaee25e606ce07908876d81f643ce0cc276d1d6a24b9b162cce63c39a9f868aa9c631e4247a2d6804a449286340b2a0cab47f915c301765496bad6eb1059cb6d7fea2c8dd461277085a539877cdd601cb6bb4e15aacd0cf83c3991c29a5aaa63ae98cdf12be23a408f22753d6d5e809e0fc39ee3d7f384b5ae57a03901df297d019c74ebb464216001b9f7ed7cc932e405c3684fb9538851bdabe896dd4c013d2d437abd6c52f980db5fdc3a18713428e7b3134d5dce455c6418b0aca3f16d8a1b8f099de21515a028508ed1f398e780f0b53cda46a45561ad37d3bef7e2b8f0d56e643b318523f0b7e308f9108d9f3921d5962875e9b937cddd86c67f606ea8492b5f38c1502a103121e3a84f0121bd0af0304d84533bb273d4d7c58550988ead7c9303ba7360d08eb80d12d809290ec94c35edff2b817b85473f87e4b58e26a356017bdad08a60ba11aa5148c5501c75abee978b9c04b5fcd775977f8455e76e52044c51d6ea503ccab1c00cfbadb06876ae1e0c9263e459188aee53da19294f5ddf5f72b94350f52d3c66d8394111a8e6924df6e039569394f84dfc973130a06155f5803024b043e69295f2637c10e5ec54538cd77f85077c1b0c097cac40f437270c289b5350dd3cddd37bea0ad347c914fd540de6e52fcb0bc585e045ed0dc1c92de785c570e9eea914820ad7346e3cf1b1ac5f6b4569797fa85602321442b6856f8325ae70751cfb870eabcdbf06feaea72edbf929ba302a5f658031b6234b5261adb534a06 +generate_ring_signature 511e40c694c62adccd1cd78dc759ad6f7e6dfc6f65c233300edd092548e6837b 1f100b5863c7a8cecbca53896f81bfb37129724d1ac0482da5e3c041ff57c7dc 1 25fe770727b3555d648a78a3e962b1bf25f9733c0fffed8837ced7e2b3214a07 805b31538ebb4de57afbd5abba894511ef846fa6c94906865803092d7302fe0a 0 cb8ee33cb70cf743d9035e38a44e1fab872103e2ebdbd12961da96e465b05f02c5d28969c44759654085b1e8e39f1f05b7eb49f3335fd41a84780511b0c1de02 +generate_ring_signature fd1acd2eea26d5ea5f10a0b1e26b68e4e89fb9760cb610bcee9a0e6903a25904 984b195e9d1b1019e51a1a00ef3fead39de4a03464838690084b5b1f5b49eb4a 26 bed2706f07b60e6e4ffa986002009646f5ea5fabd1b164bab9644b690893d9e6 a4fb36914b96a15fd407598ec221d6d6a06bad7c21bfd0079e91db6b64048f91 ac5d1a9778bcb740b0a04211516231df150d714a929520183c6dd54153b07eb0 c82a344033f5709ae3398a87d909ae637b24c0b355d25b76a04fd436c0c01488 56bfdeae80cd043158fd30b06ebc4605b4dcafcdf90db2982f1cfeb7e5494ddb f6d0da924cabf77083bc07058088dd8c4074e33c1839d7137b59cd665ed18637 d4897cf986fc87998d75784803bf73a1e9854612b9cabb0d5a91754a9587c83a d0261ce00fb5edefe2cfc4b2f1152a5802e64bd8bed7ca4d5ce7ae8e6be671ad d5d7d51abe48bb01095b73590a322c95d0c2d8aac5a30cd9c071d42fd222bca9 f6fdb08161059d27e267b29730e633e405365951a79a9af34e64b2831510bc5a 5dc9b05fb96aff4ba4d6589ad93d086044a0e6483528706bd65550ed154657e6 a7766d3acd6e9abc9c2925c3d1060214894f6b084d42907bcd8ce486a100348c d681d22b74d9caab9d5f8a39c2072a899fe687e74c04beef4dc50c856eb18407 45151bebf7146e8115b238efdd4a62e9902d8ec3b2d17bee96e177e6d7aa19ed 9f0f1064920ea54f315688deb2138113e19a1ca6ce6401fe778a01749a2a8736 e862feb485334845db565de4af0b91d08cb2e4488553054918a4fcc5cdb99ea7 c07283ca458cd202e47d486a82345801fd8351b6d511a7bb5f4ada80d3c6109a 7ba6f60b39d016bf3ab7752a09d9a9bd72b34af8dfa098fdb1f75e565e5323d4 75a784cfc3245741caf9e5d074b516bdcecc8e27784230f92084850460c6986a 1b852eb3b1840382e80d8beb354567e7d6ac15e5abf7e450358b70f067388d68 9b06b82abcd972ffd5bb38d7c6bda7a4e50e79350d0d22e9ba34231db2c69d6c 0a65a8633f5152b3b3514e838be2c0a6cb63c686f3be5163044812ba73372779 e535860453422af9b12fad4a50fcb1c233b303c4c1cd254923b7594ec0e1e95f 5c70df9727b368bcdf48d910dd9bbe2d113d468e22eddd03bf268c6194f5e46e 934174a3b129c761d997d0df693377e44c5303aeb2036e6b26fb0b6f7c688146 a3a8c856c73b2c20025a9db3d15ed505a5a3cb453c7dd31f318a76fe5098f59f e7def0f0562dfcdf304d8ee8b7483c1292e92a39a2b6616e0763719aeeb4c10f 9 1b4ed62c34da2f877a8686282e905842ae30654d7f4e1ce7aacca0ba8c1f780f69e34c2de0a9839ae12627afff7280c23e0db49b5d101c8b342f3282edd917052e466dd7b71f2e1f35dd6f33952527c28bbe51138a21abb702b5a24f4425400bc6c99eb14e735541b99090d1d88c7db8c2ee45c9d81bd0375f829c0a9d9b3e0fdce16ede18534548eead784e03ce7e331114f7ba36c5ae3d4a91f481861b0701ce3d999e29e2c14378a1fa7064abb54cbca5e6df0d3f290245edeedd8ff3910d54335d57b7b23e0d1d35c4e1612e6488d3fddd32b91cd6311ce5f715298dd20a6a7848483b0f8b623b1fc92abc4630e71a333558d846e86e53a73f14abba4409c23cbf48ce04822d7db21d501594aa59251a5e932cb75c968b5c752c3709c4064aeeb62813a9c66c3d67f9f55329bd2dad112b6fdcef7e58a9f18a9dde4ef30ccafa71f2e7132ac62217a4b837ece3ed2f858ba5f244a1c05fdbaea5b7cf6801e18c1902c1a4c4beeeea4ba074e786471c553252e479805dda2d97edfe7f16032be1eeb66f54cc6c4dcb8c8cebc0ed6f41e41c496f6fbe96a92cf0d53aa19f003d3ebdb9c86fa3eea9c9ba992d0af03e98643ecf495bfd6f7a7c15143510e70e833719e3713de590e6837552da1ea891034447e232818b7eb8dbe9732a4a4905996b121cd8fa375f761c31cf6e3371c98f71bb30c7765bcdc9a4aa6f959b0000f3cdaf5d4d2a12e9cea4bb5428429a1b0446f1b6749461b18d28260a494aee064f8a1f6f92d8be76dd9056ed37bf0dd0b8362c026c90ce49a85a52bda6f7340a741c9b4e112d6d51b86e9f93910cf36b7e7d904d8c416817af3c416d02c64a01ee33905572415c2608ac5afed137200aa0293bf1812ed157a44c217fe3081e04900a44e7a673b10b42e398a64c8ad309026acd9866d0df03a46ba1866077490eba015528244082dd00cd98fe0811fbc9ea543ba296826632ba3d2b40ef79be0a1f5839d89034afca07073f656d3742322b0545c5f2c8aa300bc1868a7569190c4fe1e9ccfd5bac13fd99b797c9b0571a08bf73ab8adcddcac3654c24f08200024b5a82ef4b1b99539b7dc11e57a18dd2cc744e12bb19b3060355dd0540018f05b1894c3ba57c3df94d78367bf49e795d3d3918a3b71e1ddc31684939fe49380706ffa3267749183987d9dfa191a30c79468ca27b4e48ce7ea29ad6619a35b2046442e99e8772a5478c5e2668322825267cc60e71259e1ee21b0fd71990911a02b3c0eeb2e32f589d42a9d7e15bcd18aec78f11f6d3bc31f0f422cc2f0afcc501f2932391447ba4afe5da0bbe7d783936b8b70bf758f3b28641f07316c69af60782dd9f89a4d75596ecb66e27bafed76186a56156b2c98fdc54f96272233f4207fabe4a1f5e647add04ec9cb25de359774f844a86b69f8833be44beacefcb200c143534426aa64d28068e1a84ec617a0ad31995873e47fa91180460090e4c8206123d39777fb7d83ea96d4d13a78b6e45076e625a227c79a6fe0410d2e42d080ee386f376655611fb1e9ea539c991cc372140183fa45a9761bec5de4da7353c031a4a6463ced9af2c960b6bc31dc43750350032be1a509fe1a9f6b3a7b0522c0ce9340b12f8678452c36b065757c05c4a2690c4d47048d05cc49d92d667e8ff05e4f85f84864125e740ba20552831db5af4e928c6730399c1d3b9f8c1f4c30501df1fe2c5dc184b4793a8b2552b4123a35c93f661d7fe78441cc377fb50c3dd06e6021e4a1b84db5463e801ebac2cbda82904bc076e33a78746d94378b1fa330475b3f01b6523524816c3967e57af098b681e46f23c34fa9af4191b6fd5f74d08ce536a5d770924f875d886ae885695ff96cb6d1a4252a0d381fa4dc11b92c9049ae652656d075638dbf7549155f66c6202e2b0645dee068945b621316231a605553adb374fac14369cc66101aadf70317ef7d0946d9b5b6019aa85681d49bf02433b99b625f001c652bbf0c1256b4a83938410297f8467a6b035c8c24cba2d0afec80bb6dbc6caa0a4ca980298e03a2c047913f23ef07b26cdca76705ec3650d630fa66f40c088e4a82f517e9ff3c26cca3518953405d194e54726a3324a8a0cee9257d0c63f1f6f07119a5a3b400c1d7d9fcb0d3fc4470c84eb40b74d14710400ff55fdb4e27e4be497c28c96f20f962901fd8b1a9a25d2f93b6861a1afb403855923ca02f030e18d9b8409f7ed72a020fefc0e59941662bfcb5285382f420119f6bfe18d79b078c30c4d2639001f578805abd1f5b022df991525acde1abf08fc3435eb89634ec41b40baf9a4c6b547d2142cebb06ec2ad2f9e0af044655f03 +generate_ring_signature 5a353b51a4b8e73c0ea6abc2c657c04a77fdff66fc6725ef72f3ad627f1d475c c9900fb41f580b8dbfe112df57f0c06e1ce7fb0130751cd61c16c51120cf2805 31 2082c30f4fb72d624bb617a6a03dd887a65bc0f54d266caf486fbac1aae5442a 0eda2f4ef08a2c05146633a297314ad90dd695da99f4f765c18c22c0c808812c 749d789d269f4a8d46b4af5ddb19cf5ee7f86c54e0c08c6d93691d96a1fb348d edd996b1ac97ae752bb02bdd19976097ddcba82f6039f8115498fbe93cfc09fc b7123f37c63a6ba41ec9b4868113d6f66cbbbaa8d80427ee6964172265fc2e8b bf64bcfb1fd3669ac6664c3e9352e5f30ed3060fd80c97bf43105bb062b9beee 991ec7c190a8f7b9accadd7c2b7ed031fe9c579f343499814c4c4d898855a3f5 420ef41f473736a88f14d32ff6416ee906a4bd91c3a573c9299a4f1c054471f3 236a9c9deb53c00f8668443a9515510ab1e9b968f4be278a94c3bd17c1bf06e8 0d96fc77c34ffa4ef13b0de637055983224a12c1dcd206b283c797aab5e7127b f11026dc54d653154b6f4a9c29d188e9c8d4633605e689426cc3fea64d70b114 04b312d50cda555c47641f109b9f4c6778d9a7c52e2ebd57bbbbd32c459b5c96 b1ba5c22e1a25e62c099f43f3e62f3bd082fe17b2e0334d30b45bddb8290fda6 b69eb8187d101ca4ebb8d84c72592d77f57d04943f3ed6ce93f56bc370b915d8 a0c257d7c690866b100211a0555956726db6192ef9ddb6569b0a452e7764b0ee 99cd8de3617f2f157fcf318c43e96e37df9ed7303c27b039bad46a8ee337b684 e929eebe671159239cb71bd63468e94a2cb90b756400a389b49376f84aa269ce 8f56d7e009725f04ea1ac3521329a1572dbce6fa2098cbe4ed7132fa5ccea342 47e13fc70a64213fe9d3278cd08ca6aeb844bbaf556df1c57d927c30f6d2c75e e4632e8650a1bd477c11dfb50e3c48c77c0bb5ffbcc2de1c41ea85ef50214b7f c8d0e4cac23ffa3b13127de2c01f885d110620b899d6d1ed4fa014c809642284 33873c867e6a07e795638df98011dae680049a28824194c4c7d5924d0f7bc18a 7930cbe3c49a2067ca5a88383454ada7c1529ac75665be86acc0906a63d0b84a 803714d531449220c83f1582d3a0b96462e6a1c4fac0f73bf486fbecfd99a216 6ab2e19ea796cd40a1973def711a3c370edd3afbc452afec3a27375c468232a5 5f58473e62a5a53727b3556b0d537a5210c77effa6ef4c00a00e6ab328f29133 228455d4ae9f1cb40781b45e6bbb26562bc01fa91b81f16f46e018f299454b57 5ebd456bc28a81eb4399fbce59a8c8ce0d765543e7d1dc876ccf2401da38e483 edb57f628c6675f649fb2947c2b7abb9504e00aac31d3be494b258daffff3935 44d94d6c395ebbd88bd008d0ff9802d38e06bac61a71f3afd0c1d6b75f5517cc db1c12682ce582aecb3ae22f6040d3c804d0d000de0b051c8739587850534ecc fa0835dfecc3c5213938d2abc5b71467e1412c22cb0cd2c42011a03f15af9f0f 3 23aa305767a24c301ef4eac4b87f9724fe9d9d7c5427cb07b12b1270decfd9062976a2b8e5873082d95774cc0292d361d863d96915f61be5e02898255c050f04bbf0f8bb3b2bfdebbcea259fe15cec09a274fd29de9bb8c38f0e4dc108bf1b01e6e7a89f7664ec47899e55497deb3fae8c9dcda6dd8d07587c65c78cbc93db0cd65dfb91859a94d9ce830a9c84ef7b52ede7e721a1c0c3dea72e26fb7582ff04c2fb7a7ed8445136ef37ba1b91945adf2bec1f3da834e3a3157037db7634800d726d91904e27ebb7e5ea143711a5546ce87f9fde522874afbfe1f249488bf705b18e862816d0f6a718e8bf06e0703025498bbdf1cd1e54cf7dc5a9166e530a072a37c09be69c54830efa33c46b00f07816e7a845494896f96d8f6cec3faa8d0c222b00da1784ccf31019e409eec43e81f865d5767e35fdd9ac90725766321e0e02cc4335d67be30c859e2e66d09f651148e3250f3bb15bf444b87b503f20210bf56db8e94a8a8c3892bef31d4cdd5e942fae892e53430d59c7f9559bdbac710d44e03a233322db8ce32829a58982b70439c56130214c7bda9fbe3d40eed7fb0e0c3a9e68c02d43a26683cf166521745c1935b039b3728ab51a9893e361057a0214856779e655b319dedcfd7ce2844c104adbac030e0322d9216d2bd4c02509070cd3e9e91a11b8c0df4bf8ab8f6c8b0dc15d62506868e1ea72d919de2b0f920ef3722c910032a1a4cf27870a7a0ed6decaadfdd529d75a4e742bd66ea4a5ba048e9d1d8cdee7f0dcf3299bfb01032aaaed959a6f7b7b2b2738ca3f4788eaac099ce98b80d4a4e2e86a45bef0fd34bde2449e7d7605a3cc52f117ee295893ec0042c335d028a33ad9ddfe2fd4daa8a25cd2a5d8c213fc69eacbe64a97044dd00a5434a5d3e20e771530c72065c2a86f2353d0600e308a8855377da0c64f6bb90e9017294660d13ed05302631086e5c2faa87263ab8a85f620c6835898c6b86a0941843df16dffac01d9c926ba0f02ef85a58dfea5a99533c95b110c4e4c220b0d9945080986bbadfd9e8fed9c8ba93060f9e0f0e24bbd3f3cc02586404929f0075cff8e6cf98bf37debaedf04cd25bd591368ce6ceb39a635f695ddca1a69ac00fd3b1668e9e9a851da6fb6975c5f01cc30b8a4ad91c13daeebab72f15bcdde0e2a2728a60369eb1dc7e96f3b5ded85ba47b89bc0b080cd7638f64b2c1992e205f8170aa457f84c5d831b2a6bed84085ad9899ed0a09b1a88aa0a24d069c98d07426dbafd82b30ff6baff6964d0f41fddd6719ff4f13387a89acaa62e3bd2b501dcb0681bd3c08d9b6682e044dd30bd25086191c2e184a5780279fa69a79f550d773bdfad65b31b7520749a0a2362c3347c0263a13313f7dcb9ed079786e8a503e678fb740aebd8a8f0995b8ef1f87ea9e83e3a459167a7ee260d52e6f0ab940ea8f018fa2c052bb5ae444fb5844dcb914426750fe05e99e71566c9e44f0cd906bb2c20c508e1bea70ea03310b53a87dfab6884530f76b64390954ac9512788013a876cf8fccedd160493c05ef77474050f19570b732fc23c14573f9ed628d00a4abec2fc43ca826b7a77e40e4bc38af18d04c1fbc695465923526cf047947c016901b45f6cae865346f580da8fba6d38731d95155e111f0f5ab4b18377056d00289a8d9a00fe70082e1e7dbeff8b8e5c8827b30a8dab4a2f93ce7526dac5950e9303a08e6c200cd95b25758e5cb4caa5dc3d3ea8814a06338e8e753d6847a10b41810df0afdfe1b4564b148867ae98dc136b0bf3d6e7ce78b59e38e885d3c600e71766dc2fc59fdc28f5f07bc50a7f204222d2f73aeeb2b909a7dde5095d29081de7186f6024b5d1df8a5798af652345e84d99540c7c03425aa59add7b10560b2466bdca353f3148eac51f0f020223d1241091426709afbe8681cc9a378c9c0f54648c49751971e97294f14d4b80075a2876911b80b373a1f181e9113f2fff038c893ada1cee7b7d1910f1701374aa255e5d991cccfd3b6c3936495fb37b7201935d6a83487b882e62198ee84a75fe9f6ad09086d998b0f2dd72067365db8c096030cfde05b6243df956207ba3f41dd20b518d16ebe94e17248df8d6ed365406d631186aa29f261244caa02a856f8e07b931872637d8d84688ad92887b8f10089861e13c4da96cc3d96d67d609e01bfa42c7c2bdc6106b918ef7190f20cc730592bd1fcf0a338df807152712c4f88695d202de2c132c4d00696a6f6113bbf1090d3b9cdb98cce551dd3780e259c9be821b0d71defb7f5ca9747372f589257807a18fd5cda88586cf49ecc6a019293cfb04e7d542106c74c79791d3cc763a660539cb649c4cfc8593bf95e131609cdcb3b51dba3022d429949d3ef92112b9c709e815a19337ebad3156fb2fc0d93bb4f2042a012da19b7c6baef7b6fcfc6ef7050a0c56c816b314472a28c30739fe5f5c34b3199b316a34625ec2a916278122085b4a5901e753908c60fad34fd5309d2897d942063d748d73c2c34fbbe3cc5f0f562af9a32ff51222487ad1a63c6e1094f459e648ae2ded85c8cccbfe8f301d0a9c9c2bb1b3d99c2f48bb4b0c35848f4bc1835cd5df5343b17b65eb51dd47c2018fe1ec2f4dec7ce976bee8a5f10a0d41669c773ae5f01d503b8118fff4a0b90fcd4e610588fc781edae15c8339b8889e2df6ebf78ecd3a8d4677043a69a2fd017a083507c67396cd1fdd8630408d71c16db0254b5ce5714e141ab8b4652d34087e5a2a1fb9be9688e1bed67e2bfb38c9ae4fe14b394daeefb790625c7a5b7103 +generate_ring_signature 6b0442ce1572d31322392813b8f2796600e1bd3a7f311cfcd5d18db158df3f83 005e98bbb03be89de4e329438452ac2466eb114dea37227d0583067af043e361 26 d753796ecd8caefcdb6d6eaa0b9f198541cad7e68ac70b436a7c5fa4db496797 6ae845a62d710002eb816996c34cfc5534d1323ec9b664c20151c4571617185d faae0348d8ea4771b6855852bb5fcc60d992a0fd9ccbb4418f9f205fb3eae956 c51b9891e997455b4b220b2f1b57dd8cac0e35489e9f8156cbac6b7792a35f42 eacb4149226b18cf68ef4cf0bf21d09d3e094002482accc00b213d0c32010d25 da150b24184ad0285d59eade87dcb51e73222301f46a0b8cff4007576858e11b 731a7cfd4b0bfc6824e2b5cb6e3fd66a77981d707259a9d2dd332168310e0128 b8ed9d7e6d9db63cd5dd9f5effb80843648c18a5c63c32b67ef6232240707fcc e611578ee243322c9d2e3210f57abd215388bb1e79319fccea9944dc8640e294 410acc54a3f9762e069471c4686a7e9e3e92c61811900962d6ca2400188a6ddb 87d32d08f2338c3da64bfbdba28f6b75d46dc4ad7fa2f018f033d09b608871b1 bd0219ef9562064deaed5e8d494ab9a22c32f468c5573258d6f8963c5402c62d a56e1100ea7ada74f25f46b738a3101732b7fb2a6a24e860fc42a122cb295603 b5c1a4655e455a01e68e3f6002e6aeaf2ce8e84d610c5e4542fe2d3100a01df6 6d324750ad63ef0f6be7ba47418601b0a5b5c1317d151a9449c53d27425131fa 46deeb14d5108ae9456f2b8375dee122dd93f8c03fb326866e6409586b44c7a0 ff9057e3940c9016f2dc47f986425e3d4f7f751ef2f54ee3aa1aae85a2f32460 9598db5a457095e3d02ea5c1ea0c56f8d43a2febcc64a089907219992cc8e4e5 afba70859ebbf598a74ae65fcd63fce51abdd43b5b6485bc8dcf9a2eeff66d7f f0d872a622b64de9d6f5db16745b7b7dcbce78595217317b73637e9c253cced1 c244cc03d464699ce9f3c9fcebc80a8131104d03f2fff938dfa1f76dcaeb6ec2 ca824fa57901f10a1ad1fa6c51a444064870adb920046153246b60176229569c 2ca019b674ed3157c84475298abad0f6b62dc1cda2a11a92fab49f9743567a24 68903516c9127c4e405d1583738f2329755d88724995901269931006aed07600 0f8e7fb6d91889ad5a0aa80048a6a1d941f666e2f5c9ef5b322bd3729de419a9 6f87fe92f681328fca521963539878521e1549077f5851e04b200e3e5d9859fb e4887420585b1f8449d75da7de40507abcae71e73652b880ecfab2d43a9fad0f 20 a834e60402dd63e5ed217f5d4d7466ac13b4890e8fc807563b3ebf818242770e845bdec58e32783ab54ae7d1890e1c01fc7d0ec9062441d7bd9249dd53dcd102e9f19db13d5019e20271d38b2b9ce8b57d321722a6c6a986233937ed4d82ef0a0589077a5ce9980c4c5f64e5f8886f6744ef0392cdf81c89e5e14d4ba81f950001200a976bdd964481ffdc47e0e5a28a931c95b5d8734df7f93c3875c57c44058974d666a4f3077e13103b52b3228670b8149c4a0e44d07809e35342d1269608eba69190adec9a4ca1b3b525a3b1a743e161bcfb19b12b025b689a085863450063c3afe8e2dd5fb7940c235e5bf535cbcf1cdc6facf0d37de514ca07c4f6b80a47fbae6c5aa7824d8ed2fbce81fdc6a3bf2191c5d6e82d5d95bf76dfc1764a08d57e57cf80499db6ac9d0abc5c3b282a0bcc65f642ab02358f12dcd0f89a1109d08cbe79c92cbe430f3d04232196d27c59507ff5fb63c79e8fac140c534784013e808f6470ae209d9bdf9f3e1c5246d9669383183cc94e8f7d339d48adc7ea08b428bc89d26cfec99921488bce8eed207d9856f1cefa9ba69ec9316d04fff50e4a297db97f966152fdf849724e979a529e2fcc98acb39434bdf16059095133003f05ff953c3128d2157134f539f4c68e61a09d60a0b188f28e05acb6b5b22c071f9c54958c3ef46c281ca99ed65c7ad6fd4304b8a2d927bc1e0cb4c82208a204fdea679cb68cbc95382598358b4e8036ad186ea9db67285f590d6acebf3c910fc3acfdf8dc27a6360b3c095f6bbb14e77c593f834d237f45725477ce97177f0c61aacffcb65509e3d5a2cf96c17df6c53938a51efbca665c4b0cc9383ead280f2384427a134de05aff0df35a3fdef397e84d4f9c46de86b1282c24523b6cdf0e0db46e5b33160606f2f1d06a20076ec5020701705110f9193dca35e480a91d0389b3da164d94668702a5db7fb9fb11960da05f77d112278747ec9dd7dc725c0deb8808ed2a1dc37c24ee6dda732fb9a57cded01dbdb174522cc8f48637ecda09fd23953c1ab7f7cbc47ce6dc66806f14dc8ad6db2e44a0cf7522f51a8b8771022e80cc3188012f3d388ae648b47756970d7e74c1aeb1350e1abe2c876fc915025368a506ba5dbbf56ab8a019d6b63fd03b4a526e475cb0cb0aabbfd2348fd30e2280bf99e868d2220bd936f954037adcb6d93ad2e6578d24872db2afbf25b40aff7e03d45003dea6bfd76767aa4cb287b5d8b8dc0571d7aea2c9be170aa7f8096338f26eecd554b123e6334887034dbd86523c6ae1db1458f13d152d6d066a0be1a6add88ad6a2d7e02fdcfde77392735e686ea8b198059b5e364d72204db70aac27b4f6239537699bc716c988a8e0efc0cdf883b967aa84592093c2e3c96a0373d1525cbd7f3aacc02908e0a5151aaf6629f0b639e4fdb44e9e6ff5932e0b000e9e22a6a3b8b575b1923089ad83891a0a698cb226fa9af785823cf4f3b12a01569420e28a5eeb46c008dd64204ae81b66f094010c7ce6d47be254f704c2340f3c3d2a13e09a13f77e4a8dd49e5d518f72ea69bbf7491bd7a25ce27d896df608ac898387dc5f4236173f4caeff65954f6bfbc90ca1224c1e7ea2b41e7f3eb20547fccb087c7295adc740881090273371979a2202250f8615bc4b843b629be90413cbeca3532b7e02db4baa9c8cb2ff62b7a8f17c96da0de8a96135b01313740758a0e52e1d12b4e077f3307b8be96239df0628b3c47e152bb986d2e228de4502f761e22a2b74f011c8040f55b56728e508a5c0d4fc8946492f8152d9d88ae60473601f67374c85ceea306449a37ba293286b806e25a72b555396b1d4d48cdf001a110f70d4f5133e1f17a365ae7caf395da13a9c22073a5674bd1979f04ce70437ba19ce48482fb55387611ead9e83cc89555dd188c0357e48ffab30287204085f0a81d9fe7d661ecdfddf37f19c1d2f2f4343fb6e8bfb3739e96cb92c4ae40ab8896b390e8a3f5b936508206799d96483423d2bacdc2cc6af73e8baed1fae0d6769886aa370f610f38b028746887caae32598b41c800571f1994bf3b490ff018655235dd40585dedb9aea2611949f8680c75bc2f5a27ccb162a95a68e95ae0f788361ef0e67e927db71a2bc083eb94d6fa3064bb287b6197a725197cee0f502382c3a1e9ea372d0416185dcfdde027d512c796f25114e5d216aedaf0d41400b4e9ae7f7c97b68e53871cc90130749bc38646d9a031cead7bbed1706d1abd606b9389d13c1895910e520e86fa5bc8a37bc60b92181fb5e83324029eeda6aca0647e812c5e3688ac421cc919126a2324b345049418769507170d324cf131c5d05 +generate_ring_signature fa878e98be7bf61dc3b35153e4ab01e1c444b109729d4428288fa17dd1277318 c711a0a27fef0f9531030c710cc93fcd675120c2b44fda635fc3fe58ce68d5ac 2 8705fbfb8783ab5987596b73b4d1ff0156795c951e0c58b8091724678d9d4174 aeccdc9ec7f198a2f4824e33ed96d40215f9b22fd69cd2f0f84546093fa44c67 128378ed23f8edc0dd5305fa3e39996706a4c77d63b5ffda8b294b057c3c580e 0 eb0c48a87e20f1371074413de07e52488f53350cacc8e51bb0784f83782fd80f1cc94915efcaf4e3e25748bc4da43c22aa94a36d1f07216d044e62e79f2b640487ac1bc6c2f7856e493e3dfb28b57e60ba62a7fb3e9a779cc34e3ceeadbf9304ec7c441b6a5c3cf2a51b45c80b4b4d39c7f76d74f3c39dab5514cfb5eb562405 +generate_ring_signature 4dc38ce91c25bd6cb03ed5c0900c0b3a3d171ecd3f441d8bf38218214082d784 4279f878215bf5455ef8c99444b6a8cf0484d54010b0d1e8fe7adfe97af85f10 114 bd939bb5f29b32bd0b9b884328cb04da64b7a77b9d0f1975a42d74c06222906b bd64c1eef3f01b60b4c60765795c12d9d1e67df40fee313bc7b0cd7d769bb669 85917e8366e4bb6557e7e3d6d0851f0bb72cdb2f5605cf80287dc503333cb4ff ae20b8d284cc742818c38e284160f244b157b868fbb088f6125b8d039623d282 67676a9bcf5d35194deed9e14a41c23c81f5e96a82ec4aa28d9c54574c27cae1 c57610fd10ed400b939d00134aede8e719c8e4a8abcd18ff1b32f7fc96b9c937 494be2c5d57bab3e0e2df1715d4ab09912124a8eb65d44745b6ed4bd50718f10 d89243a7661e6cf3d7ef223ad3eac26916c71f9337e02d56db8bb710a41dca38 bedd21b55f596d4fc3ca8577ab48af6d0e4caf878bdbc81c61368799da91b655 c18ae2c77b4f87e07ed8564e9eec44a7fa841b9deaf425ea1be3ea7c800cfb94 789dbe3cb82cb86630f62da491b353336731b43ecacd9d76841917db6e265b50 d983f5d7e4980efdc335a6eef84da9d194aea20eadaa2b1cb2a2dcf6e510cb24 3fe08f0aa6a0bd5ffacc337d8cfb3ffa5ed8b1ad2717d0d51b929d9a33806790 686623a9f75270dacfeb22784afb28c0fea864434b32fc76a7c7908c378f1e8a eb2af211b6ec6d3a7583c0a264a4de602ebef841008dca26e06a659e933994f5 1e02ac91f995e252099050a2f9bf0a107500f689fc785f1f9d221deff9354e50 526b8e6185f40078ccdf886172921d276549dfbdd3a0cd27fc65f172d3bdc2a0 8e3d39b85ed3a05da76c47c8f70b76020002823548f8d45fdc27df8e6852af9d dc0915a34b7411206b4694438d629c17f84c2c07aa745284b1e84133765b88b2 6f1070b084301889189f7db4aefba51bbf037bee8dbdb086ddba9e9fa316502d 8cc4b03df9b06722f19ee747f5e4adb7b6a5ba3f9473bb33e98f06afca0155ff 7913b5b2a3371c554ee75295492f120e4fcc1761a2e90c163800e0bc8566530f 62a6ae54a6ad56bf2cc867132bdc8ed65858367d7ad38ffba12b25bc2f44a923 afd37d8701510ff65f36a4089d28a116e923640d83cd013c9ce2bd232f689cf6 d2b980b075ad35c7080194272558a004747fa3d4f54d52e54d7eb15a55fe47b5 09dde581825bb3e27bf96127461b67b50bb5258077ab5773544f29fdaa4cc48a d5e555016be782538646c00925362d280850ecf85d9c1975254025187739a0b4 099ec3a3c0b2448c583d9279b8df8d6f9d95a524d7ce35e5ad796619559a3c6a b1785018039ed1f0e47624cb17cba05a29daa6af97847e985c77b5de9e2f90b6 4d1d4f2af470f9e5c21fdf9985312b217dc866cd3c99798322d4332a75ed3f83 61bac09466cc764cd2549229e63b21ec0e00125211c18d2e784c027edd279198 e401492fd7498a1281617bbb9750fa4dea2f7ac1c05d4601d7b4d6f93f05e05b 4b50fa467dd7bf98cfdfa98b87a924aa5122b6b09fa19e2c6b1aa82e4f109d71 e4c8c681e9f7f7f0607ba801fa44816a802e81e8fc42faa343d0c0ebfe8e3e78 8a0e62086feaa8a6259ce3a21c4063fd4cc807c1beb371372f45e7aef1493123 fa7a5f9e71d90eb5ba18bdb7a9337243ba0d8735c4721bb9b65be880ac4ec6e7 8c89e1ad8f42ee19016d782eb7489ccb70b72be6ed9bc3861647bd742fba528f 339678b140b4c32ab322905eec017d40d039ed7e02c9ae57c68d2fa7e8584626 6c2ceb1dfd2d66f045bd54bfd7e5908a57bdd5216b7b17ea808e479c0e4d7d22 f36e853ea751ae307fdbe0837663f823106aded803139620a9cbf8d65d85c1ca 1514c9820ad846074be5e94a1a460efdd832703bab36dad44b04f6723e6b983f 4734b3ad5971011990b5ef237b152c24a493f304b337f556afba97607746fd81 8cb350acbb7d6e8c4da9dd936645a8750b052a29414c450a9bc886f1ee58bc9b 90f095ac9e66ecd8c321797c8cac0b6ead2328db02968466cb2a813a14b97b63 b6ca5b532fb55b28dd5788905f16a4c017617e45bd9b59ddb916a910c004c906 2acfe7532da865b1eb9f8ac6d344f535c2dc9e6f38be192986a02ff8968af635 e656d87021f86642a2f147b58869913e1721e8c8320ab77acdf32775ae4b816d 45847b41ac23724e860ede8d7fabed5982702ce646484b7c008a603b48b08a4d 6d0c71b58f122a7c9e6f4a71c0a8ef6ab1d598d67118486fb704c4d1fa8adc99 abc2b523b9f0111245bfa413450546125e29293df013aaf0783cfda5db038302 8649564fc912d27de342dec94c8dee22da9d5953045463bcecd0cf111a2e19e4 7ebc13266c2d167736b1fe30b6447f51d915a09cedccaf68726bc2dfde668816 dfe2f28066a7b2489f85153ad3fe8c42301efc3792e55764241f0377b1df59ae 53337434326613e0a7e86c87effea7123084637fd9ec488d6a5cf79678418d71 2fd4edb314b9ed004f702e97673312cd247ca6cec9dfdcae83ad266cf70d70ef 63627d0e850e46d81bcc136ad2aa095ad1a451f2d40d0954b5b9a99009c9c723 22d3231a1d7e59481188324c8a300004065010feb4408ae9bb8c5a6028099005 00452956c834dc93e022257d4ccf84a981262c21e5b0e364d606e5b8b35ef10b 8e4624bafddf2d0659dd9568425153ce7249d66dd796ae9d9a3958c207ff621e 18e20d7be6b02026da91d6a20212fb83271ca5c0e41d31f7742f9e5d7c9f75c8 0321996b983d708e35a7062ec8de17bdb8eed2aa44a33da0d2d1fdad633641ce bd8512058818d365f2a894bbae3fb48a8d8f683cb5b7ea86c20876fbcfacfd4a aa8206c4c30cae28a9539f34a06071b321f3bfbb1192890beb6cfcea066224b0 208e753a3e2ad56bc88aaeda6673781d74c4adea302c24bb430bc9d2ad99ffeb bd60707aab510cfe9aea55674eab81065c4481d823653bfdf4ceed5aa4cbd2fd d73cf31ffb213b78260d22a47f44376c188231f066635944f43b5ae6c487fdfc 04acf87b977a025d7aed687524a1612b4ec58f042f570dd537e2b7bf1f374819 b67f9de08052c5fb3a0b62ccb6ba87ea75cd0ceaa251708b40844267f6b014e2 1ba734db12fcc7ec682fd0ba5e50f8e201f88bacb180be02ca298bc501a04334 36d7d9519faf0b07448f93704963f2d5be500feaa60567408b62c2feee1abf63 fb64b38df7b1c5c931251663722e1bbcf64aeb53da9d97989e62eef5b3d33185 9934ed813d8e4ff4b96ea8691f2a73701443643065025a46b8d0ffed57deedcf ab16da45b8ff0732acd013c1a3574d7a76d4f8c510dc7dddf54723f8bc9235d0 cb6174b0170ef65b191639424a1d18c67ecb6366d5e789d006718ff192b74e31 5e832d1026ceafa167e47f8e846d6f9fe37d337fcd63cfcb0327ae049c79c253 7495dff8ec7290d6672d5ee2f5bef600fe0b573dd51d4d356dc3093801b1db78 218cd5ae20837d084034d5de568343e729c8c38c4c1aa9a7129eadc0b155b2b7 9466ad947fce451cf7fadbe9aaa5c7b6084f72b3421abe042121d6947579543f d221ba32ba6279137c88c55d22a192535e263d14033e775ef45eea9c076d0dc1 c428cfb99f6446666b862996418db4a552bb045ed8d8fcfd2b08deae775398af 8769dc3e2d1ad107d4f0d96cb5823602daf842cb159238809a9088752d340ca7 4083c2735f5c674f4896893952c90d275c6d28ec96961b36e75164b42d63469f c1f161d41107d3e258a1f77985876fcf02f05d98183ad77c5c943944024c4ce4 7e5fc3484d81d4f393f6fafe0dd4357ce73d08b6db85aa6d4a5dfdf61586f9ca 5c39e84b62a9dbcbe60d5625491f3cd44621d990ee50b74b7b3a7862057c7c48 34383e8918f547536c4a41cc91b2f02f642905325140b52f53589bba81f16383 1cddf5fc7808b6466f75be06c1b19b90025a85e241a44512e65a94b275058179 141df5ff0158ea408546d801ba6f0c6af9bcdefdf23ac134cf932835091c2f22 d476b262891e7be025046acc191b5950f598d26b940d883be486e5032cb31445 522d85cc71685afa492a62c6f4508207849af1987a7116cfc90e4c19ebe400df 1d1f78f69b6744335233e84495b0511e32d3c720e2373bf669c27a4990668e74 905d0a24578ba9bd1bc7b3686d1b08848b470ab12f4956824cf3b0fcf056c0fb 8a3768805b5a09ebc505e5c0d4242b617adb9e0f3865199bbd2a7be7579024c2 e7c80d659dbdd822a62c5a2b5580932a55c9baa6dc0818e8ae5467869f87375b 1b32d833d664cf3338c60fa3205c119e1ddc8c9cbeb44702459a97512575c832 12abc274c96f4ad4062309fa3060d05df560ec075cb78a80251cecacc9000a8e a01aff1dc079be3335a3efec1cb3be3eaffb22080688a4fea7ef634f8b1e5bac 1f4f6d983fe92cbac643d9a027741439190bd7d911d90c50a86bde27d8f4dabd 5d82c7c2e907bc4f46744c8bf1d8e441c21e28d3e194ad9acabad465022496bc 8177edd83f79988face73a00ead13d6c0ecb1db4f365b2e3f9568ad58cd8c641 2ef4116bf37982032ec32ceb4e1415331f4fb988957d113425ae1268975157b7 58a2d5b81c539077063bb9d470cc5aaa3f5014295ea7790b6bb002ba368ec551 452b24765b3f19045dd8c1b37e16823a6ea3c91d9500709ea0aa83880ba159f1 2e967b6d4aff868718cb1a7b26f50384b1012eb02313e8947d8e9a7c52d28a7e f160277b45b9b94f4004260a2dd9b2682f13081a1490cb873207ff96874d296a 6b9995916945798f3a838a968e36a030e64a240737da517d6c29fcb56e2e033a 3d3a67122086e15daa676f97a1f704008dbc47084ddd75bff2d52de83ef44377 e2c2c8614448e6b57b2bff177ce01d466211ec6cc80e26e9c4a9238657b13932 240762e3135c801ffc2df0714bc22bac52f23089d3698fa14c4f9dfd1eb09377 1b120c957aea684c4babc04fd213fcf10b20f56f8873a808dd707982c73b349b 468c72e026931e245e55e916ac2d0235c52e4255826f113b35c9857e171b2901 4dbd62c32aa0b9fa0cbb9c7f8174387957f23d2b7cf1386f39400b48f40802c8 a3d0a864f3226f810e69cfa3c6fe0e2967af9d69f12d39f85ce0c2c43e6310d3 3e7bf7715c43237de8eee1de54dc56b73f8e7982b30c1f93bfecedd49be9adbe 00ee10408bd89c7576d8e154cac0c7f743aad43ec26fe575f3a005ffadf84606 44 747ea911ca5a0243b6b0df4deb8cd31d0c268267ddb82b25029fa52c9cd32905bb531375a95b2987f5ea4e6c82db0205fb74ec3801ee725a5869829fe5abaf0caa5412a2fba581aebd07ac193bce1be8a6ecdc06ce7fc1d53005ddb72c7ff0048a8214009150d6e364cf07243016bd5fd7236c179011af2c29f09b5cb2abbd0738c4d84430f1f330c16d09653d88c396bbdad126ffcad281eb210821baa4de063fb32f803cd07afcce7f83227b3556276d113d6b4c0aa41b06d766334524d805726132fa59e479aa3fca261fb1b0dbf7bac6d3040a8cae36a50628daa91e940a6a8730b5ebcbb8b384f5ca886e9ca9767c567be0bb3bb6049c0f8b4b95ef8c031c80add827b75e22373a80161ed441ebccefb66d1b023a7a6cbfec90f9c96b0a5a2d5b1dba2b308816f2906073cc5cb9c3244306c728afdf17f3a6269e8a540d69f8a60aa4c2f62368a5cd7cb9d9d44b6a8e1e9910f53f8cfc49df4a4c26920ea41b4f0f862a909d6bab09abb805c11444f56d4faa59d53bbc747e4c06ed6e074bb074e98e01a0e7c53edf0e8e9f93c560ef0568ccdfd127abe44b41b3d5fc09717802848b79a5e843f3b055e66be9238b089b22de3313826f91d85ff5165c035efc463e802fb9e6e74784086c0fd8796ba99f30ac047cf418f40056862b9b0ef7f31f409e03731f97a72b1c0fc7a438d8baf79f8d0e837ef6a47de55e2dc10ab691298735030640e91277a872bad7a760454ec7a8f8cb5b6b6dec410468a30d9cd3c5ebe00ddcec846681133a97950893bf4034145fb79b5cae017e643b5d0467e73f5763149a1c614b03026a030dd5724e0b8f51ae5de9dcc989109c9897046c24f40ec49c9d3271d9a9047b477954955065bdf3a4c0690cbdb5c79d6a6f087c8ac80e88876e8dd21af696a0a625e6c8367bcdfa66acfecfb352a2fc926403a5278e77c75781da2cd38525b339a255dbce80e4ff72215333e5f72969593501a2f0cea5a24458ffd04ae63c5e60331a5f49bac3bc404acfc065b26afe8d9a08b3bec0d08b594ba2bf8a984540cd1d073236fffef040711a7d8360e59e5e7e0b1a6216fbc82a015fca730ba100fc9fbaa9c19970378d8735769d644dcc19450d19601d5a90783afd8787e13c78d39499e1f2aba14b0b89935613049242956507a3b2146549e776d9f9ac61f0024d4e0dfa14618030d758c2edbbc618c9ca8b0ebb121a9e5bad7410f82a49f4cb8b7c6fb14edb276453318703f5253d595dbe0c181ec17dd0cb73381342ca4cb4d5f81e0721f7d2d1e44539b04b1ccabeffc90e91620d25d659b1addcdbef9a851b0057b0552fdda4bc0193e86bf409ce65a10a310a9d68ddbfe3fc33b95394823e74af06880920ffa47b3457669368089be10bc7db22c5f64025c24fbfacec410d6db94bf0e20f6cde7e593d33ca980ac2ad07c0098f7479cd461f3de966a6fb63907a705f3828030a1a37714001eb4b68420a3c032988b60b4967bbd86906397734af2a9f1acf28e6415fc855278904fc0e08e272f2f150e42082e9d9c64af3df5376aee6c4e9c65f01c6f67c1fdcf7515f035995db08f465bac830f57e8768d0d504f713f26488087e1b4f4d83bb4a959a036e5377118a3029df6a8aad18d79915da351166bce1626ad3b70fb103d7187b0040f36a7cd387c2cbf75ca42e1f3753cd914b9b17a2d7468bfe6cdc26556a5e08bb0169076e6bd98244d58a87472540a28c8e3624b71335c02c08381049140e07e7064668a6f7250cba79241beae7bf761b6fc6620353a6de8f827b75b2f92e0ccbe815f1c48d41fd29dd3e1f57275bbdb06275c7255fda1db2da004ac6afc70b43aba531b3d40e8172eee3c3af0cfed3d0b3a4d4e7da00d5fe4679d37ad38908ba924197b8d3dc5036178151ceca051283187965f381e7fe2ec8a14fdfa53300a343cf5ea93ca310702762d788480acf1c31cc35d56aef708c6a5c800bdba006ee5d983eff36b87ffbe125b87e9c16df9012c147b6a58e2e395a182159c3da04bddcb5df1231ec7f3638ee1412e3d06859f55abb79af3b0e760fff6805d2b30f5dbf1b1ac3435c6aed26200a01a412ed3a0e904c8bd1d33b80b8ae819b93ac086901838ba2166f9ae285d296e5313a36b9739901d682345c2933ef7eacbf80069490d86f9f5a4f44f7e73a2c7d0a1e486f56bec7d1fd67475bba6c1f0a5813089cef1f2de4f3ab7924ddd0e730b48101ba69240ff0a99ed04bc1a999c8dc1d0b117883381cac06ab840ba890c65aa93103aa29045aee55e393d3084f42b14201353194b6e05a91a886c22292d11199b82e1bbf3e30b329b2e03e544df0e92b0ca3c203f3675ce8197900f960d0d1c23f547b88d3a8ecb9022355609239c56d04fe8ba00b10bd656a62b56509f26ec99769515f9c58864c483b33149890c27504fc7e041da197e7065a40e938bbacb8e98dc180daab05ea379904536bff5cf409145e2a06de08b3701ce310bd2a90af0befd4fbdcf9f9ed1218bab1d2f7971a0c2956d4e98415bd16f3ce7c2a92aba3098d8793e174db9603eac09cd22c2704061159aed9f3d9a2be8f00d73d8e73691fdec4fdb875b4be159b378494dbc10405c3421ada30693f88ab3ae0d34a9e8ddc4f6bbacb564aa0d8886bdce425c9560cf6be7d4028238ee8608efd4b5c3443b8bca5cc897f6ea173e1cee38de66b02020d2882379f321af12062f9b21c022cf0b32a94ed95236deba98f1946ad4b260ffc6edc4eda7c0e49bc16937d0d3d370d3c6ef8e52a4dfeff525dbd6d3f9dcf06f13710590fde31f571e3863dd71dbe6adfddf81aecb8781ea482466ec30997010bf656cc40d44509840be524f976965f1f5a84a9e71ca305c4d33737c7702d0067362b7b1c25d23d50eb211c94a5745f941ad46ff21803261b8150236de0b60367f00942be190e9b6d5120b8498820b5c464947596a30d691586baca77adab0ac1c342e42fcb0dcc28bea9fb9235bfbcbc210da8d424e25b3022b8feb70dcb0223e6965a516bd68002b0efa7c81f3d06d83b9249c9db8e79122d7ea899a5a20a4bbae76c694bf2680e31ceee22f19bf82ee098d5a52f5870380e7373ad395501fb9a422857d1fa766ed2332be2a69c9d8aed47d6137193409e2c83308bd48d054ff0de9fd763701e6159ff7a315f3050ebde11692dd4d64e901569ef2c68680b0a02f78e5f65cb748d0b75d533837feebe3dedb8f4263871abbfa2bef3ba1105708c0e4757badde88f56f5ddca7db74d7738045b95a6795ee7a31cea52340b0aa8a62fb37cd0260fb5ed73a45ecf4fc6f10749cde7e52d50ecbdc69eb6005a003685180b2ec910ae26216e2c0a1e96a4fe69a19d6db41847fcfab992532d5c0dc233f5ee18756651209ef425e2acf995dd44390acbea1a23ba52e0a540650e0a041ccf345ef07c4fb5d78888cf248e758be46d3ec90d0a69ab3af5d85fe91e054370a75edc76c5b20bdaef3a4ed654356c9d01f5c9fd53e30f7404f5f9d5d706a699b87e59b6e524c88e62fb4d28753ca6c53b96813a1fab2890c10da873e30eca4fa370c22a8acf94d004d78add522c4c462aec16d5c8488f39cfed78b8bf0715d40f78cb86c849ce67c80e851b4d621d0241c0fc33b8b7b976f139ac4a6206d8ac43f84c33ec00bbec205a7742e8098bce09f542f116b9da3bd36347d6e60a8745cf842d82ad31b0cf60153777615ffc03708612186b0edefa9f1e4c877a0f18cfa7e9899cf5f70670a9474f6b1eb19cc5adf6b30297530408ac61ee3f4807b003a0dfe5a05a6c7105c279a09ad2c3a2c50822f0faac88de8bf622bdd9b0043cfd1f878da326a384b563ee5beeff0af89be348310f6e1b81f1e8b972eb6401969730d4acf9a806bfe10b040389a7cd994de800be734a27dd691d7194d1040de3f0260119c21e8a8f764944bf95987ca37c20fe7956d483a45f3a4dfeb1be0029d4b546d859dd03aa583158f00bcfb1a66e41a68e8466f9ed66af4789e15407617f252f2ecfee3f2db811a0bf2b600ab81f44b918cb70054c366fc9e00d7801c30b0d00a68c6ea654e56f2a348ee3380cb709ccf20a299295fee486df40e5096569eaa86d7c7d0223deed5b9bc94763ba679f8a0d7329bb5b3fdf0aa660360de7901d2957944038147802fd36b1c5f0b24eb07dc4d208bf4ffde380953f5c07a7eccad3f39c4e1911b5ed640745e71f052c712c6ddb401fd8ebefc9a3aaf408759a209970780cf39c62312c8690bd77cbbc95b87f3fffbbdb3c1f95efcc150ae9947588bb019af154967b04a70453df16f2eeac93e85c3c11e1bfe15269d90e9dcd37d73af6bf1ec4328e63f5ba6c52e3f2da253f96608f0531ed366ff5290d58e2c24bf594ca78f0e791f20172aaaa838f61b22dfaa332f36e18767b018f06f34b1ac8ce7ba882e996d6086c3a264e636ad16721e8f008b5b19f06a2de3e0abad7dc659d340d8e36c2fc68097e99e994255589db459cb17c361ffc303d420eac111e8d1601d6bed243a4d2db89fd5cf3883308181b3f0b3f07a5489544ce06a27647744548a2f25e27ec1651de0e962a00812039b5c6fedf998076f57a880e9519651dbfd803d4d723e17b7040c05101e3b69421dba0f7ee6589ae8a696d071aad4a8faeb258be7ec6c456ca96944c502b8ffd6a97e421599e8f94d5780904d8871304f8835e74c2480892b54e9f8e237efa1dcdbf4f1fb8ac81f3dcc25c0219efbd2fd1ef67b23c7da232b5bf2bd681686005bec01b283efbfd524198570d62e58e9f8e39d383e0caf88ea81b1566ea75ddcbbccd90adcfb8ed63a9b40c0c8bfcf34a3f194081585d90f35a79082bed4ea74f739650349ddb49595a980d01a74df4f85ca9bc47401bac53dca8548ebc97207663fb0c5fa62dfe948b98a10a56e78f138c5d07c13b6a7252058b3209b4f178e010dbc39e62caea46f49dcd0fb53eed92d2f554c26e7362a6b1d8ddbf0e121639b9eee14b202e485a2ac3e209e90581243dae633c655743ccdfb9c34ce1e901a30d9095097caf2bcb475ad301efdc4540e55f7bc810a02aec6d3948dae0b760237999476f2a272afc1fafd0046fddf000e67a2d3efca78ac096e9dbf05acd314e099c9382ed9d1592c2335708ee198a353e639a57ed639bc33dce4c0646ab8d3541eba898856738ef00411e09370a0423451a64bf09004a8b5cba32f7d94fff9eeeffe91df31a5728da88ab0b8914c1b7ac795f90d6fe9245c4ef1f542788e7ce30262685a2e6593e573e920a581c7dac573d08ff551501f7c975527e58bb7be29a9f459343dd05c29773ea08732a6da07be781d0cf8d6549cce95647f8fc977872f541415ad6d442a01c360eac8345d49b0278b83bc4fe3563632992e4538092c28ecb22d0606acbf07f20027362375eb2ddb9cd367b77fb6f909f4998fec5911fe39bc7b28f6c2a6e56a701dbc21dae903e89b9d12656f1dff6f1f67416223012ec32878b8c680d69017a048117a926c571cc9406ba3c9787891809437736ffbf1d29c6463d00e458e1c60f89e1b9498d1321c2dfa55c63822499e4cd4529a033f382da6580fa8818b79d08e49ae3eace2cde08fa76fe0a496750c89dc682c278062f597bc618ee6b079204551a3e33a5023076ab12fdaee5da6db11d3eac4df762d8f7c752f4b3d3439d03de70f5d58193b9e343d4413d45ed52fb06d22408411c4eb2b77134376e444e0c8e93087b2cb4788c3fb6ba616a82c910bef9dd3a1c953946b8a8bc07f876410e69ba45634dc5334ca1bd8ed1461254c134d03d2b3f79201810ebf0e2baaf730e3aa6ae820b6e2707b84d7bd150809b3b17d9848111facad44822750b39d0c9006cd6a570ed1243d09600cd85f745be9713e3dc6abc45a28461b3e66afd88c20a7f6ce4e8884b4b0d84ceb6abb4549c6f21e3082bf2153f4a28b07bc5b658c5008b7a5740185cd455bb201f6f6f9335bb0ace02ddb89b409d5268ef929ce63702324c558ed020218018ea3d28ea64f69d5ad843f3edd19924066d271d6e44e10d67e20711496f92d51d9cba8837df6255170de993ae0b3278c70c520cd4246606f04de5444492e23ffba975cd4aaea44f6c1b2e3e6051e7e62485fdbc68515205a9645802b9bd82839085424b0ee46a8878b1f402849f56e6b9bedf2415fa3c0c0829d07b65cc44a6610a0da42d3e1920754ce696e8644af377ce57489c2cda081356c1b8629a9488a208bc0811b0bdf79d5ce0977995ba728e759ce8fe84830c6a7dd2cc155157982e8905386f50bc3462e94c2353b7d32ecd0026679c279307f7b996258b07fd6de1403f3168baf815b3a189f6d83034f3866f6e7d3bc20503c4400620c75d9164efa7b721016f8cc101252b879e630eeef8554ab186ce550af6075198fe8fc899cafd03786ea7c490f57b44469598c1f5d137d767855a0607cc99afaf6e203542bfcf48b1fd7d8cea2f183f6ee47213067efe336c9017170c2b25b21554710c31a2bc76dc3780a036c1c1c6e05ef351e29133cb3d1428f808301b50b062bf0a34fc525fe7736dfe2711969650fe2910704d9ea74e9955700756ee0193549b09764a1d17ff01035094300590b48e2b461582fcb97f89e3b9088380d720e4b762a8f54184abe5558e2ed8f2291a0399147202ca852dbed31e0bffb652976cac42df3a41bb80a9205b8d7531ef91117661012aebc21422a4c007c14dc4a0a14043d3c9bc2ba41883ba53a5fc0a4f7cf95a9df9cd54752710f7095f2f4ac4b6e3f855a08603f1d75c412918d7f3dc155b3936dd137a6d266f20093a02241cabbbb78818a1af24075ee409c2dc7790ef7d0448c05ef964daa8f40780404c0b6f4fc1a46c3420ff2ba8970d365a3dc6986b5af4d33c57e2a78a970109ca32d1ed14f99c1cc87a15a323e6f2341f4720360681bf9da6d932f2d77f01a56f946d5256e4219baa0434f1a2a26824d3d21b105b6ecb1ae32a50eeca2708dc6f5064eec90df5a4e586a2ed0e56189aaab152bc823c881e7baf3a8dbd9105cad4538e70d403db8fd633067ff869d5439f9ce186fe5a6ae5d4161e22e5050f00f1eaee484f60428731b9df5f0585becea0fcd1101e50a0dfb20d64f47bc506a42c7e512784f414a8c93ee1bb4db9217d7bc60a263429935cd8d78615973603d8c90911c72f85b2b0db4212df4136e56e6929b75464e0485de93f5955b59509fbe6a66ef75d35f7f5a48205e743cb7df54ea681f6b3555323562a0b2be17d028e4d43bf6d5cd4107b9cf3368da9f7b9ef75d27a2bcaefacf45ffa53f4cf0208fa1e45ea0151fecb0ca5ae78123bbc374c120524ba487b08515016a49323130210ac4777678f6a757533e55644462cb9d2c371c032cdeb5df1b3ff03bf2c5f07a64843da23bae5931a77a306f816d7a0034e06ff77b1bf3b4bcccb40819e860e1d6866df65c00006257a80c8e366a827658f9cd4531c51f51b92845a5d41ee06bf0cc8a7b41a93ab19ba40f6a24af1642f297b222ff5c0ba7d53658a62322006e187298e0fb1107ca216ca491a0c8d9201b00384c08a9932711bf5b082b3c40defaf5eed1dc613b70ee379cb9db6efafe068e4691c950bb5bcc4bff4929aa70e8b51aef378bbdb8c91c6ddfd366c9c2dc1d002c2efe1b275b8032167dfd1a606fa30af25f40f655c5c5c256ee850acb325952ce59fbd71c8e63ab81dfd89b301649bb53e38f01bcd2c9d2cd2bb7b6f8e1c3f590ca020e0093d49da2abf4af70212047b62352183e196df1083a1c5b164bb7f0ba00ec4a6b7f1e7ded07c6dea09ec2b6172ab6c3f0f8f79ec8583ecadd38c54e0f9eed122f4daa1294698ca7d0a1669b616f2d2bcafdeb73117ca1cfb9c40e8b32cbbce61e7f1cb478ec2aa570a8387c3bf9ce73315dc907b9134b4c2a842799d0cc9e54405d7a42db32a64f00322129969e226463e13f1ff4a7b055d12c718e1b6c67d1afd8a3d2be623b7e403762f4c890ff6e40fe71a6bfdcdf9301fa4de66733429bf135e9c0697bf507106b1278afbd8f4576bc6ea5dfdf9789890501a0c392b578632983f6b1c7a67fa08b1e13a6000c576f8f4c549b5308ed1f3123c22eb1edc9d2ab13942e86e9b6f058899a673624eee13326330126b7cf121c35951dafaea8444af2f547c91a2b2076ea0a791ff0c7718aaad3e759266825d9efa222b9d5684baf9b51f1c015c4e0248f28d1b309097b09d0929c5580b108319274819b6db42953ebb07b9b7c1530509502f194b66f34a982bea46e37619ebced90ff09ddd23ce0511f20cef02120edba8bb7aa844199b034bf02475e022902e18029789ff4e15e880b55b9ced560a824bfa6e7ad37f5102ffa70022b2bb061fd6aea7f038f8d01c9384097109b50bdb3fd5a3a0e1ccfbc7429a3e1d9ee8b07db2af1b0aad79d8f1f8fe675bf14e079f0330f116655f14a2c2c3572a69f4ea3ac8e7750c91501e435d059aee3ebe07e2fe3661bf5186b7c4c5bc0dad0954f17514a8de8a4bd022511d89c645e2170906c347ae4e4fc77e40c73786bc1ca49f6c37185f4b18c98296712a248c23c909becb1a4251b343b5f5804ef4643bc442d96246244b3a5e39edaf929f9675df03456d8f0dd9124656fa8615ba5d679e6423a4a5adde1b2836434c65591b6bc20bc3c002559725125416492b2d937cdd895eb4eab2eba576e3a996de79dffbb10cf6c48562c604c78388d135c88f856721dfe5448a4c88d6727d973ba577418000a3a9c7a260276daa1ec7514d7cbe7d47aea92ecf4ac014e3828f86cc2080de089babded2773d64dbfb5043b5ac220e37d3aa6401324f107a29a1ab5e919b2b078a5f31b00e931d9f6bf5ee96a5df1064c5d96291da01dbbb135bdec9a9897f09ee1c2d98fcb2df112fe3cc53c7679215cc0b937cef825b5bf9ba2823f673030d7a7e86ab41c616d58ddcf22c58ba5f58948d745ed31b6f92d8eb2d31e95adc0a66b5df50fa836da39787433f70ff7de475c6cb36db478cebef0f2ef8873bfd0208e3db699097ae772ed80958d43c17428c2a09602dd260670a7e57a8d9774006f3cbd405764d7a9d33017dd7dc41503a90cc6ff984263b7aa5ad8a7ff7d8400e31cdec158c95ca6a389e4cdab231510a76160514c24ba73d7cb65a5ca1c57d0481471330e55c072406520c26c22c8f7aea87b8303e1a417181dfbaf1cb4ca10c8776e513a6e4412c3c21032e9d6e43e77b41f4a8835ec5b0093bc84f4df5140b0d7f02e6de0072d7ce8f8935279cec4a40e365d296f838ae92cabc6004234b0e2a5a38a8a2ebedf1d6f61161f0bcfb875ac3dc2a11a29c71a6af852b863f3a0e19e3e15f2182a31d68e8e194f42ed97b870eebc6ed86eb4a7520615a23fda302f4d7d756ca6c22494029dbf44312a860106cbda5c88a737aabaa359b51ff9f0d86616e89f1e292fe3a3dc27c47d717e68617e083c262fa3b697c07d04806730b4a966a6e57618e33f278364d919a5ce60a8f174e0321802e07938601ac3f070f948accde198526df578b916c2e1e02bc562128818c70f5d48e077b5171057c077f4b36854b01bbb63430635b5aaefbb06461449af9c4bc5bec48b708effb3a007a1c02d16b40dcb20b11e166381efe6dfcce5cda786354d66a6ec9bae8c58e0f7955b6fb065662ef797e961afa00538259a737d32671e5b34d85e9c3a748fc047cfb99874fd6e6c82a5b9272cf2cf29c7e05750da17819c0cb37e8ba7c00f50b14f1302cb747858b197026b77309c2bc88b0dad05693ee76551abee1e6d1c709578ff4a26e5689d8e9a7fb03d7dc0409b205196061b2edd08a6ce6e73774b40200098dc823f5c393d9183f751fc71b3aef4a6bb2bebe5f54345f7de75e39c8096c12bd7e7ac994a4cbd70903d54c817bf758cbc5a00861d60ab1432873ab7c0c957249d43dca6ee291143297e28db4ce7aae348458b9268d8208ecee87999d0df0eaee097736bc5aad5c7915afd956b439ddd4548b11cc2530955e5cd9af2505b36017c712c32b7e6d9cf74daf01bfdbcd85f06c949ac1979609c7a427c9160a35090f7a102bbc8057f85c8bd21acf0d688c45a95f886f066745944cc6f67b010de33898ffc94e879db9f2162c564acde3089fcef5d446f004d23ad0f116310481bd07fdc4f06bf0ef0636d6d64755825c35246c6719de4a4b0abcccb088410fb18af86edaa62f20856211b700ee1708f2d65dbfd2cfd6ca995ee5c108c5740c36b92d8e65b4959008b7a726e0d9aca1acd7a6f5e7c543061eda54c4beed3306 +generate_ring_signature 52ab38afe83396f4a7abbbe478732d39260c8086f1b221f37018ad83a56295e8 52144c557bee42c63d3943a1da22bf53c53cf47e18e39ec7618060fdfa2a056f 113 2667878a43543a286946b627dba44ad682f51a0ec0dd5885c0c17706e1f27962 56070ef37ef631a894808bf2998c18079451cab0c36076b94ba7046928c7a1b7 09d61f61e982a1e500603b81bc56fc727b7ab3822a8af511a213619776bc559e 3d16d0811f8d8b1ff564124ac0735d77c2b62ed3339a2542deb20167ac8d78dc 8d1e73a58271f020e21201b77b3e1a0d5802960cef0da9c30f88331d1e53b7b8 b15c3a90c6d12c50c12ad1f1cd4f5cbca77abfbe26dd1003c5f92d256b7d9a2a fce4121de27006176bafef1742169e769f3a25a075b413ef0c3f7affd5150561 23e7a79af125e2cc0907abc7b61ebb2b6d712691a6c556474ca79c1cd2873c0e 1806559d6d2e9812dfa4d97efabbd8ecafb8331b2a836e8b94212ae21d9e935d 3d825ca551aeb017319626965977dac767f90994d4574ea52b0600086f745c96 9e5d692b5e82670f6284fef4efb6a3dce320ca9644126d52782f922e2f1cb62d b04d172573b99e1b8074d362c5f6b997b05ca74a5aa4d35c957853f9078ea90a 451d26bdd2e49368fca9c893cbf9a2551aa0bdb1df3d919a75f16da4615ac00f 39123ff66a0a8cf47643625b997f3febe9b843028a733213f920fcb0fb224321 2e344a31a1f4abb279b66741e22b00d72342c93ddd66332b9480f38ad010dbf4 174dad431a88a820abab2a8ddf30bacd6c0720da30f98ccab7c821f2ce13570a 8fd6651dd86f87c6e9baa019e3222459a3495c481b5983bc1f3bdd43600538d4 70bd22972b4e8c895d93c5313a2c4de3f096b2832401b34492d8b63e4c828b93 724ac189a333456efd5ea95bbd6c3174180204a0541f56c9d3c4e82c1b9a9430 ee0295b969e97cfbe6d47f879da1a789cb27f9bb2af514fd549b4c8d8db67ea8 6516c5de7a016a83efaeb52dc3810e147831cc6a7bf6d556aa711e3f26ae74f1 3f8aa4e1f31046011579a2efb2ff2e98c2e94868bf61f529b28e0c9dc922e65a 40f502a1fc081d3e0870baf688962eaeb053998be9e61627a99ea713bedb7d33 f5de2cbe86740e20007d273d240495720423986ad67d13022a69f67eb65c9db9 a72c9067245c4f1f7d3c6411578b2e02e18c373f78957b0c011d1ba817d5fcfa 2a6f3ed6fe0238355cf8a1bbab5f2c1f5674c2432cd8c964f4bde62d1f84089f a1be89b4e0cd03a7080617e61c08203f935e63429a34f8ae637c6290a5f855a9 dc25b39ea362c07b69225919ec631e1de3e539a0c99076421a03888c136040de c42663cb57da0d67ce5e40583deafdab17af7f37f4e9cacac7be29510b77ae60 57e85e3d5bb0bfb51da145a2345412b3d4f1bef0a9ff125c2533e3a76c2fb261 51d82c0f6c42340c6f37f6a4d24eeddde756700a2a674f0e5745b35b0493cf47 d6239694cf291b89f96ca1f448b250193f738547b70c7627a72d6d8c3edef2a8 3e3ef92d08a0f37954c6ada45ef29204a7dacc626c7181d7613f2fa613a7d515 479b439e8cc29f89d9dbbc3acd98fac89603d262b014a2f876ae4646ada1d401 ac9c823e44caa76f6d0d2ae5da6684a6fe0fc4c623cb28bb0ffedab0de052047 bd47406403e535790864051db0c1c2d09b0e7a0fa9df52d23036106cc5eb915e 19abfae288790ac7d77c0581167f78415897eacc19ae8d537d118c47fa2b1553 b5a5323c096b566ec9e91eb9f4c870869872499205d05cf3d7b58811d60b1f58 36d46886bca44dcd834fa408bc22275efd1264644143dc3fde9814b06d1ca44b 758aaa67d8781b59b605c687e993e1d43913e3693a351d9addaff6a21cf196f0 32c1e4af3a5597eef97f47511fd377a961dcf5e3ed4c1b8ffe981abe8ce31a84 ec3619a0a1928ce8907e344b0c7a8e87e15fd53ba8693341138a5714442e2c34 c6bd33f733cbaff02918e91d14855be7966fbe29a04b6149833010293b04920a 6b8a52bf35bf9bcdb80f5c22fa241b7342b4f6bbe085f78e5096f0647f0298ba 3222525c78358332d2571622030a2c91873a8912f815486ae7f1b38418cccb2b 5ffc8527b801db0fd1f9fa568e6fd8915afd4d2a12c9e760f8a0e3f65c13fee6 65cd0954290ad98ee8fc0ade4ca8931b1f6832199e69496a57d71b25e0c4da6d 519dd0ce81bfb0e2e2aed5c4404fd08cc5dfc32cdebd2c4eac8e8341a99593dd 028506245b4782ff02e531921ad41f33458316d2a04701949c9a1130170f667a 65479d0e3b8c5e054a42165784f71979e44c5ec86edbd9360d364bec827c38ad b056a8e8159cb51dd0ff6854f0b5cb7d73eb6af8a5056f7a157000fe950956a9 121bab1f2128a355510aff20a2348ca726015f44b14247ce79d17147a4c4060c 67b7dd5f52f743bf4421b83e735123e1c17173c562bebbc92f241f748c45c682 1e8a956e74016f5431b773efa5ecb58a388e94f91b9a5a4d928c90b987298361 928bca6f3ef639fb399620438c215df701e992d50c32a7d519c9c4029777d8a9 4b928f62407d82ea63fe4ff44757b0e2c99b3d809f473a2d9856a4e7915a4048 2638494a4220023d7abb69e0663e321321a39f10ed88170cad8c098adc2b5762 b4e4fb545e5daad738d95438f9caafa048eb5b7b6cda4984f0d98b218f8ecab9 4e1da4093412883d96f6080929c73604c9b918e4b4eb3263edd50d07cd370ac2 1825bd87bd4c8621c5d585e3a150b810734249c5f8b98826d4fca4fe17a479c0 afba4add454e41364dfb8f3f10e613f4379125837d809f9617c0c59557d8ba06 be6c78f9549f725e77166b209a3a62be24858c6fa6730b751b454d8db46513f8 d72dae253fef5793e2c4b21266aa5fd4bd4bb298ac12024c3136bacc698bb5b7 3cccdd128fb4279cdb8782fe4e891c92b9212ca7df38c1281a7c23bf0488c7bd 38d08fe57e0103171b5000d5f7d6f741eb51c405dbcc7ba351ced61d610b5e0d 7877f90fcf24f4cf3fca2f456e942af7cbb7c713aa9a26a437870bb0dff5adec ec4175d3e5369062603878430224568d1d9f6b01b48a0377dc82f66f9ca309c7 eb039d354117c3df90c53e9eb0492b4cf2e4f6b4b57bfb6cc809c22621edf016 6ceb1f244447e6c4fb2f4b7abebdd227271ae511383515241e146e3401b47afc 65cb32f44ecb9ce88d08bac89c7b36eeac2e52fbafae9c104b65851d0d3fb689 7ae2db115d82335fe2d49f12ef8248994b958fbedfde2f99dcae864daadadbfd e547d52a6eeb118a7cd1147895f5a75dd0dfca914d50706f6a7033235e3ba07f 6ab9a84a88f767a1cbc69b2740c05acaa9fc9d84ae58cdc77e01b0900cb19ed7 601efbbfc5cb40884d47fba0a5e1e5750685788e4225ad69319f0dedc8053cd8 151f98617ce7dca0ac7bdc7910fcf5afceea4b8acb144110377b458ee877eab7 7dc10dc41ad38ef8c879ac0c434ba7dfe0c4ee458285bfc0b07be3127c970bca 171ce0ef0830d4ed99f42e0c20d063ccc3c6ca50b747b36f24572535d28c77ae 3f55caf66c98c9d773a90472b2432e6bcdd84a286b518a3f3f95e2ff104847f0 98ac27c0ec172728c1284698b62bf64afcc2cd1535ab245b6ef9e39e1a1ee486 38a2e914fce5327a0510a04ebfc2843e5ca25b995ec616bc1e214df14cdbb2d8 6ede2050ccc3ce325d911fc26311bc74f9f09f51096acb61ffff4b751705e68f 527e46d547a1337da68feb3065d017f1fc3d37fea430714287ac3bf13de5e43f 8208fe6fa4af1af795df8b07f36dcb08d87f9b5fdbb06059b6ccebb6cea006ce 41cc08d2fa9ca82df528502af00d1d8ab83840d3961cce3a000909322c393b15 c04393bc4ae049524110432433f0290f23a88dc4b0bed266bd3c139180f4571b e41fde50f6a402f874e366619f17cf3af987c3641720207c0e48b30f3321d462 d680c870d7b43c6ae308b818dd6d14b29758aec61195bbd3e354221c897f5458 352582605e62e595ee051a22e47c7f10c86a0ea59896c907afd853c418893bcf 39b1b721c361d5cc7d3455cfeb782aec7f122348a62caa0d67f4fdbc98665503 66e0b54e8d0d0b0b61a6641685c1f3acbe72bc1e55254d88a2cbcf50399fad68 c3afda12547982d6afa86121d0eae5a549d22192469079100f272ab6d8831338 3d8021bf75cd1a3b64192e532e21744cca23a32a7a50b459b635d8cfdd6e28be 176079f943ba5100d89a6f665864407996e7ea1d554cfa79322d38300fbf3cb6 735b236716beb3d302ad5518901b9a523d51fac099752fa0c1714fa342ecc944 d6d69f6f715109ba6b81cc303efda0abd38a312f526b49bc058ccc44d076be32 1e2dd2d69008482d8e7a02b3d026e549d61455b1add013bc88e131dbae129b16 e02a717aae13cc6ec9a9ae8bfeb952c42d8fc709233cfd1ef7ccbc1bbf912bbf 009b16fd9effa67a4c4c8eda2b15fcc67adfb5aec379d592c6b80c63d3750a9f 40cba48b6fe177037c2d2f652e35278d5aa779ec0e37a01a3338154b0109c7d5 fa94d28721ee024c3920937cc597b6e440056d873da9183a4121740079e91c52 b87e5b2635dd6e4bbe8d22f83e55a9b088fc79bfc79b3866ce37aa3be95a4783 705a31ef4484a1d621a26ff0b0250ab8f4b4feed12227f709c41b03aef4739a3 5c424ca54db641680633f09638dccf23657a0fc34f09c2ed97b3ff0193c330c4 f00e3bff74143e2eb81b5aa10d4f8e110d6f82c12a6ecd870f786d120a863ce5 2b57a48a8c801c44fb5a193e27b51a3b63ba879a68a603f282ee29bb06dc7b20 b02e81daa731f503076e99d7e975ccd900b8a4f4a20768e03225a74ee7769c6b 2dbc9cba9c5b1c99149fff8f97be8faa42fc16d0be7bc5ac77dcf8886a290e32 0027178fea8c180bdedbfcb2bb7e394185b37a42977afbb70ef8cc3f5b2b1997 c417798c3869d3bef770f05c7eb4e89948bd4c76031dc429d6a52fb199e16b02 829c84deef8ab603af8fd2a06bdd0daeb12820c32345488d074fdf0c8f004879 4be25ba569f1b4aa9c55a3e6dcf232d3b3ce4cf9990a6f8698b24db41ca20eb8 37165ce3e5c4b593456f947b9813754b44e40e8407b81178db50716df2352374 b899ab2a46ba764730d7a822b6e24afd6d6d276c4a73ee66fc39eaaf2ed57b84 fae3ccc4f506532923a8f03d2d227f60d7870ca2c855098aedabd89abfebfb04 108 a39b9cb892025d99ba58a8fad99dedc462ece235b74b8d1f90cad933e8f4260994b6b5146c97887dd30ecf0618d8cdf40f30a05b4043bf5412fc56336e34250f7346743d52ef21865344c531731bb9fa25993567171d56f453edac0a2af25003a08e35eebbd71d6bc371df17ad61918a0ad6ff7586909a4986a818d3adc0a30f478b0f261a7f0276d35a93106a7cabbe33680e71e92f3baa6f8ada72234c860dab3d4f698d02723ed8ddb0bb6dc43da792fdc70802652ac1137bb651879e560b51ea5156cc57a6e8390e1fe5f1ddebb858ac12d67518af739d17bbea1492c80246ebca7dbd471690e9d9eb4f0d7693899923aab1731184e127f819bfe65a6e02c9f8121f44d9dbc902ce64468fbe38cfcd0217f0937aec4307d2641163b98e022f1aff8e5f0f3a9ea9aab568e6bc0a0bc009e7d1a358f6d6c13e50b7a78532037f9958900545259239ed40383365dd0ec19b422a18009f1d6ffc260a129a7b09781f054f4701b19241340cff7033c00605b12e7c831443274dd25c4608e17501731c9001cdc97f378cf9e49c9f064735639e9e7cfea635e953b728f4ad77c20ab387ec5510beedca6fe2ddbd0f830b84ef360b683fc0423c8d660b477977a808ed31c3b980bdea7897c7b53161db0efe895beb770bfa603a9470f8b90169f40e6dd4dd9bb2485e166dd18f5df7d73d938bdcea271321c32660db40053485ba0bd598192e3dd41dee39252cb89c5a3e09e2721d9be1d11b5a1cf63d3cea1eed0088e9664de8f95d2ecb59162473cf3e3a72331038a307f13a563ede0bc13d0e023a680e9111151d5327e902b2ae9349dd1f92aca2ea562a92ac857c6fb875f40624ec08548a7397df8ec1de57daf97037c37aba167f663b81528c91ffbab9ec0922452216c801cda812daac6f354527241d573122cd856fe597d46e8941b23702abf12c53f4bce240553016f1c782cbdf505fe8520b924f6d7574394b3bdc3b0734ca8ddd85183cdfeae42b60b4d8fe54303ee2d369c6d1faf539c194dc2bfe0652ca395f7b8b8d6493d5efa117e990d47368f417cbb219dcbf5e8ded6e252c0bbc4d25485705136d017dcd54da69832a2eeba5c9b95cdd24a2faae543d9b48097bfc26598dc19a44410c9fc550c81475d0aad3dd3b57046a7b8e4a166449360593e29628f0384e5c10f422fb0a49094a7c05da11f1bcd453cf76c92d680ecc01854b091280acfdf0ea45dade294e843afc1eab373c45d44a2a7e8cf50273c008d270fb42a8c85e99cc7c04c631f5f784582b27b0e500bad48f6faf9173caea033ddf2269e6d08b9e228279bf77ce7ee597e838abf73fd5d4f30b67215f9fc406816d76174974ad7d9079cd22ade3b8f8999084d7e5cf088e4f2e699ffbd11704a8f610318e7ca6dcf4caa241a6650f9146d13a7440405682d2422a9c7c03de04f38692e460096e2770c20967b2075b4adba508cd872128acb869d12528b91b0752965cd9a8756c5c994bd2759695eade0745b9fe16bb3470ebe68687a8bd49062a78f0bf36e46c99205374a21cde0fe9c1d1613354546e4a9aa9c0fd9e03b30f8888fd33152a35693d5c8e1a9f87587885058b1c8b02934baba31d06cb62720263bee8d91f98e2cf5daeaa95cf572024ea9ee551083c88bd5dd7cb26b3b52403bd17043722db40515a966dd2bff59698ae17a92b35e12b8df651d6801bd28d0d242718a2915569874fa517abbd2ac08098fa3f17484c146a8b2fd5972ae9e50e7631612788326ebf00a7e523b72e02b570e7b2c1bd01878fd2705760c4b3e902614f0d004943ed7a36d9cf58224e8ac2c3783cd4db22674815af9d0eac2a860f398dbdb8037e3df5c43830998287e5393bac6cbdb852087934725dbabbc931034dde1d50549434ee6b3ef41770f67fba6313b970155a8a8f58c474136e896f005ccfb28127af4ccf76a42190e2f4a30c891bf29a42263f265728b7a6523d6b0f6c7bbdf1a9a3bdf7a3c252c9b591060399aec1598fed9dfdfb6581e37b72990f589162219d1a5d8acf4ea8ff42b168e3919cee23ca365a6f5060c2fabf75240b7dae95b17b4b3dd58e91aa05ebf1da0d99ad5b9813278d3b9e3caf40288daa0d34302f040ac7db9f659e13593661ff7568218f60c26cf00c36b979743ecd2803cbb9bcc007cb4042dba333f23db423c0f31e1f3e5ad34a6041fc4a0b6bb2110c9e76530befb7bce295cd79d3226314fc148aec202da8d7992d6c058f6fc4d90ba411f5ef862e9127ddf48c42c27464d5aac0aaabd127f774f218111a8c308902ca0c0f4f7e2006097bc189fa3b6fcb4b7c75cdb7910c9d72af30cb034a7ed2076b223716865f71d2a54c362ed2086ec2ddbdfe8953467daccbcc9337d9e42c00d63252c8be531070b638b5d2ff2ae2fd307d481d7b679c14bc1f862f26ecb302c56620df8ed8b24c031f8806918b2e5dc83f82f2bc8604d62039219e527b4f0bafea9ab8f880bc36aaff06649fdbe1a84baa029362bf6112d69022c3bb4a40045f2cc48aeb932ea562742eef2ff63a5a8213c365acde7e59db54f48c6dc0c50cbd04c187e68661400719187095e8ebf509c8caf823a9d0cc932fc267025bf4071488645280c04ff840361366fe3110f0a765b03306ca84a51a30cfa0f722fe0b661002a6e210783b9cb4929466ec6f72749137f4b88b6952943228e4ba7e75007e6d472952dc010460c52fd0ef1c5909cd625733f6495fc3c2a99441aad4e90fb78c88850708079e1b8467efe3f38791e3e6e494e7b7d52fb6b0c6f89859e70bec7621d076e3849a527b5faf963f1e19cd3a53e6a5b0f1d03e8ddba6f08cce056f14b474ebef3e7473ebea0b078a4481679669b54da1c15ad1245df986857404a73c2e8ac84408272110efdeca8aa91c394ee911535228eb9d2ebae9cf2baf0ce19baa2b708c009bb8beacc220cd91e2848da73cf6debc8714572e76063b05020f72e4eb4e9a991b8d0a1ecb30955e4342e026910ac49c4885ba75039e01400f5b9e012af76691e0dfd584e14e2f534e209877bebffda30f66948713f2516a0f5cbb65c96db3481cfa7eb35f9170d068d81129a24b82cda3c4c04ce76a3195067bb653df0c40741cdb45b76e33d842061b64c4141416f5af7e78f391fe90e402a864419bb8a128afd13c2eb82b4d303cfe7931e7acbfcb60cd88141c08c2bc047481cd80a1209a2aff8cecc9ce26e1f51509b2af8c54b9f6322553d36317ff0f270c0f4675aed8064f88b5b40636ec95090c32605adb0f1a0d67b951f16f0f06db419d6dcdadfd0284d080623ed5cb70038086dfafe87278683f3b92ffbfc1094567ef31d92ee9ad621052bab4cb36b3e7abc242b844d391aa06832973d5d10b3be7e386257c2d98d5b838af5d8a9decfc07c2b46bdc8beb4d4972f69b8140013a589f32386732af2917d8e367b18f3ddf73722727b72e927ba2fb74c4bd3d0bdb36a7d302f6f2cc1b849d36bc1291c1deb3a68c51fce69f8bc1a87e6192ba01af34971c4c031c662a2c6d4552d1ff849b6abd49d0272dd1367844ad73994203d1946e548e369f6c6f5258a117c8a6ace7cc5c2474ab80b33f6508e16d42b00d571c03b1c0b906c49cd0fd39c155c0f4a0cfae524b0509f03cad4bbc10ebdf08c6822c67eb2249f3a442dbdc2633297b11f2fa073bb076086c0ae5344b40d6093277f11ac09b6775117872f9bd66ea450b148effe47d8a3d4f28f6a252d8860db528078987e3a16da014a935a111c73cfeb23bd53b6740501f862359fd43090bcaa76038c8e479d9e4cb303c4fbcfa06ba26b53a035dae3ae36fa6efa1b8a9005ec1b16f9d3f17dcec0a089ebaf66c41e335bd4469aa3369d95a7277f5388c0d2b28ba53c01d7deb416d950646221f976bb29c3992d0ba9bd4f0267dad66db018da778c841e9ea9c1be1f2639191b9ceaaae935eec6be8ee68219a125c063f026e79123c8982509f46e1d72694f45cc0678ea1fe396db43a715e0f7883cbaa0450af1a7f190fa8844a7ba235dfe4d01b5571c07111cf491d5f2801b83b4e370bc3aab84513bf9cdc84bfa6cdc7af852054ae9fa8b2ef1776729246059e18b902341b373e955ea3127d0d5461895e6f4c7c35cbc86f4921066fa62a59d3f00c0d6129a8b39b45bcd3fa0e4ec29a5f0a2440ae7592518e5464068744e3ef547c0ad2b9ebe218f5f8cebe2ffe16a98c335bf7e09367ce4f7e38f606223d9179280a124af3437f031d41bdb44e70f5a1c8dd14467aa0742ae0a12c55dae83a39a80bb3bb951bbd367bbbfeebf304349dd228844ff9dae04a4e8a359cb9eb89084e0885b1164ba7f5393ae319ef93caee9891ce3f3aec1d5edf2f57315d0f06c8790357ae1b362c443729ea1f990a1549bce040de2c8e94dbb369853a412ef3779403bde7d11335a54ef4f6f25a44ef72f39bbc2d1bd190b1650f9eabe67da372740b2a1538cb8ee4f637786af56d3e1f2998f15f1076b7dee2b55ebce5bd1f026801d4c12c5515a2600b11778af74641174dfddf99c3a0acf1809fd63078dad8d60ff94d6855459e6fb901980164cf0e477a22ce5898a9dfb030998e3895967a5b024f4289c4bdc663c62f00349a22eb9e80586ceda2fd20378082f12d54a92d2301023833fb85903e1e376d45a1df47f94cb33865e23bf120b88faafffa5b76b30332c0b1fcc7a76d735d33104d4ceb00b3ff5390b1283e9f9bfee5300200a4d706bd8e03f46373fb9fff891decfb39d58905f82fc53124275ad2719eb121814402cce6dc9d62af0cd1e78483e4a6dbf72f6aee3da68329210713500853900f0a0660bf007998ceac9cbfaf6cc3c93acbef21ac3e84522b4177262be97f4b7fbe0a4fb4ab9f79f84c214b6e0f306e51abf05763323635ba6c3ad407641d4cc0180dbb6340d0e7c7ffe42f64ddbf87fab6880b044a38a7f0f49ede342fa6622c5e039c127a2a115a35aca8bac60fb060dadfc7f68000582baa638a861e5f7dbac50a5db8503d00cd91662bfb55714701d38d812d88e091c6b63ecbffb866b7e798001f4f3aec6b3713781b99527b36871e5520e87a6c0109e3adf92a7189d301a40a7894cde0b740db61d37e53fab2adb066c00a62500231d2a3a47a6c053da69e0c234847784ddbfc80603b16d1463b7226d3b61f457baf9ea0521b09f92f350f088ad7ba2d43507c70ce1126af4883e7d43876cb701968818c448b4f65f8cc150cdbaaeeb5b3ef7164c6c5954ef8dcd9a553b86aa4c4676685304f2fc45707010a50b2b431c3ca8a390e54aa03c6a593c5def5cc821f1e66a569957f5a68ae390f7bcae0e4037afe17e17a02e19fd80a199b167594c1aa50d0a8447b0318c74806e8f9315b78fdaaf486a03a7edd1efe9c309c63de886afab3accf5e3b5ed03d0d7d8fe554623e2a4df5f22f7ec9bc22f62a0b2a716568749a7ad3e2b7a7c01e05831ab5a8811a11de433b39fefea883eeb995eba8e00ce4ae308c6fff7251f20fbeec3d1a72219b74bfa609fbca57b6af8d553b8e823141e3bccaf76f553e9904402879f25c086fbbde800f4477b8501312b3c7c8b9581fd805508dd6ebe4ac00dea99795b05efc8886a02dc69a5f44bf4ee87a9ac851dd4b572b6aaa5a996c07af9fa35c15ef7e974c7d5f8af3e509a3636f0212e2fd7fc5c08cc91f4a89880984b33e066abc1d5fb6f1f07c5424b782764b3507735cc9d4af89a534a57cda0573fc73b32d1b2d3d1d2f3c072db3b43fae0573b4513f11912411c1d41bdd4b0af0987aeba25237b47c5cc352747906fcfe8ad1a563d6a4026006c5101d1e4c07bd20e360305f569b8b7afa09273c1dc1f8ee570f78d93112c938b7021deb640c86f1dfb9bba6356b8dd01b05bb40a61b29b4579fc92d92143727548f980d05004690d4c4f3542503bf483b122fe98b98a105bb9e09a49756b62dc3ebe029ee0cb83626a67cbe182476f78411e8b20fcdbf4f5756e0e608cc7590e0dac0e17d066237f3845f78fea87a312b6f6b6f518bdbaa014586fab04d0f400241884d880ee215ba9e24b20d6cdec807d21d72ba39308aa2313bce08b0550894de2589330d1f6b31d8dd215cf7682605026da9589b10913996da5ce613de86228dc20f5a03c37c7fb6e87a004b2f619e89b682dd2b0fcddaf4e2b1ddc7374e49ad2236d00300806a887ccbb198f7a5d483fb2fab1e76d5367e4139c0830bcf343c808dd3043560c44abde6517a4d19f2ad0c34a21e4b442a002e3e3de01b1ef2ac5921030d44e36711cdcd8696af838815455e49a852a8e48ce6012abdc89214f555a974013a9e625cd686887a071428caa54f7e41dec52190ab3e76372064ed35982b5a06c562db689e42e295ddad75ef892aa9589ff69f01a537d0cd33c06726e7272f098ee6e3575e6da89287b4e9237b71140a0619643fff27f55c957265ac62dd5303478d594e8639e56e4fe1da783bb733a74f5a27027c85193c0ee2aa5248a5590c96ae810ba38cc3997649dc90be361bdb84e711af41091a9dc8a3536657b71500679c30461f74b4246b0e18d00c0e0526bcef750a3b4fe50c87e6414484c7280c12e3530b236684545f3596c0b32bf83efed4ae47c209f6f83c257c7d787d080a474dbae2c47d543fbb0ceca72dc7cb1eb0271a6b4ab1f38304df705d76f2330e199dab48d4c985de0b3f85de47e09e0dbe95b4e2d1beb1bde359f59253bec50fa4e389b5345611f537aa154140c33f86c306b7250406f57261e194eedc5f2f0c8e3735a618ce013f0158ea52d2aa0415427f83f1e1251882fe6a6bad068cd10c4905eef24a059aff58b51b87f3280417aabcf15c3df498c1587e7d20da0e3e0003528982d52fb5585c5c2ff24c974d5b4c358a3f472c366132aa10c9b342fd0d089bb3ab6c161ad99081d05a84da9654b43bf20f012e4df7a8fe7b352abbbf0834910b6736160ab726a10216d06988610bfe43a7eb48051f348f819730730f0687f9b960b4b956411416c0e97a950fd0b556296520d480c8dd5454fdae9f9804ee643c30d81a88f34a48c1704f4a993e371edcdc194e0b69022d014b87849e06400056cf375c4e9c4c62400653cd27b2f21dd1d2e41ed7f4bbf7ba1455a9c200acdeb86611cea04de14cb3004e53148bc5c9f195e027b2b0e6e5fbeac886ba05d823e57d600e6cefff70d38aaa02e0231326386f910904551535319bd249b508b5efcc7dca76ddf1983457b797a50770dcc3460774e34c590ee373d30e3f6d0b1b4592d5576ff1735ee7af8c7388aa5bd96709350ffba4f25195297a706601067cbfb228af229e363b0883f4cf87da258af323a14e007cd050f82ec0abe8030be3c5ba50c52f7e729aee539a73ae989137caa58fbc900495c0aa5a8a72b3c4044c153c7d659c440d8986bea7c03a62b83006d55ace4ea136dda030cbb94f7308c02aa29d52a558f3e798fd45c6c1a9ccf731382afd37ff62dec5066c01535b0683c1fa1afbf94a0dee0bb0984afa3ce320d1eb345efb9eb30392675e93ed3004fe53085482ef7a0ae2244d9bc7529e98204e03ed3474fc7a5f8533055e303c02f34ca8f726b18295a1c077d1831e51ac0b20ef7cffbc5b84f3d5a3f6c58ae7033924258dd46d6c86e469006076c5c100407c80efa4ad693bc76fc17b44ad620dbdf240c5a2d9be42a01b08ba23a6aea28bce991cfe4638496f46b2f24527bb01f51054cb47037e7cb01838eb585cdf4edfc79504de2a7dd98ee7dae95071300be73430d5b23cf0bd463aba726e2c05919e8fb8b736063164fde649fe5a5e1c0d2faa33c957418c9e6cd229bbdc581f149c5a48e53b904abebfdabfbe35d4e9017f2af353a51b6b9694ead1dce4e0050c871f22183281e9508a1633b873ba4802e6cb728d118264d848fedf0b6e0fd32cef9f4c9dbcff7e46f7cc1477419d8a0ec097a9e2aff6586a7eb9704d931de04b4f19fb2ee125071357cdd18b97ac3c0badac0b1f35dc882ac42cb94ce34725d27af65876e042d9e25a1cfcff0479540fa9fd42b736a94371fdf4058cf5425108f5e3e4c3fc14f28a0fecff1608367000907aba24099bb53285d235bd7dd24ee976904dd301733fcbc0a0f9dc4db79607dbaf2a06f9a48248cd59ef6a29bf829ce8eb5e58fe78da2cdb8f00ab96def10d95e38e3b5a105ef1d4092329d7d56cf6c16a25fc3644aa72e52fab26ba6ccb0daff69b73eeb0a3b1f315b52961e865b9be70ff95c38a18d73dc86b6771dfca029132a46cda910a4826a3142e72a1aecae7646d241139c2ae99c63a6f094b72003dc42510ef14d0c3c0c1dfa901b9e6871d97bafaebfaf529be2308f3e36cb105575f85c40eec91f18823b92e5079d3ec5c15a8fc7179ef282c6cec79fb9c8c0eae6a5ff61aec22889b283ce3372e73509dbf156db41987cba704e4ea30de8f08897e76171433589b58d35a74d608e2ed4e458052df033ccabc53cbc99842600d063d4d774cc494c204e570eccac5706a05ea33960a8f6fdcb98f4fac9cd16e0cff82ce221fa5f2cdb6ed8b1b368cdffd6632b612d4e6361cd3109d84be576f08d5fe4f350fde798530a61dd297d75422694f0045f6eb4c6807cce283de4c8a04fa065735846b93cb6cd220609783a15adb964bf7dd6c8aab1add54ba4deaa40bc5092e22ab8d0586c5e2482917370bb1106094dc3a21c2df7357f45c4a06a305cc9ca5641760cbf7b7320d3d353362c71b05f171f510cc3235862be20f19110196e97a157077da3c35d25ac91ff452d9855874b4c7694189e6765e70017dd40f9d86592dd045301c51fabcad41d3c0b43ce137092ae87eb7edb32c9e8542be01a2df9b2d0a3bd8610d75eb90adddcdcba1b6f4450fc149dc01ce57cdcd00e8026e8f019fbb00badac170329fe83306ac7d244963ff31bd2b7169436c384a960b2475e50f2678ffe9e0143374f8e29b2d9475e25c638301fc2daa72a5e506210660eb7e094078aec0b907a4e8be2b84b4a51c1357593bf7cc94c24de5b21b020aee576c484d1d340d0c7dc94bf02ee222397b9e933be7bcbfbd9227b3fea6820244e5f6918868486a070eaad080ff566c18fd7c40de6e15cfabacaf2f32977d06ded6acf6deb45b1c8837c42e0872b2393027a3fc8df8f98f3ec3af145f185502cd807d306adae9f1005e441b80bd2b5afb8a5536397e2ec269ffc9646889df00f759dd4dfc3335ba9f866f118c4c60af808bb6ecc6fd03ee05efbfd5a867b90573ea38606265a5c902b961ebe0cdbe99d8c22c014d8a641a4b8b807eb7cede0bd7bcd41af4ac0e3fc4925ef0aa7a34181ec477d55ceb294d91e647cd35f0e0038419102bb6b448c89e66512e700a1a979876f65b5c409a97878f4f54d6f8490fdf211c368cc4d27d905f80926e52afd618beeffd666e8b82ba957a0745c95b02939ef192eaf2e1462a8f785d7978945f0b6b66792fd1c7104339a044ae94ef055cf84f84b4f2d2ac397550122800ebd533b904b861587fdd7a7ed21ba1ce950185031d63371483c4a3b725f685a004c6c50d248a70c84aad172adeb42312da01b9f19df0fff7071223422e86494cf0d3c6b32dfbdbe9b5e44342d1b1a05af70ddf792526495e999f6830d95f5fb1c042e6c3ab8f3281e46e94635846f5fd1c03714448126c5096a9b0a16b35c2999d0e35bf1aad48428967669160654038fe0b50972a6e4f9327950ed21c6daaa3163695c909f83faa4c72766f10d5e89c0d09ab5b2499169df84ad0c324df131c59446ede25708ee726cccd0a8cae3eceb40c04d752c84c98ba13ba594a12d227045ab26f9a7bdbdf10c2435f81276ac7a0046ad94ea0f676ad968077e30950d4d67b88ce7232236b4a5817191623cff2080f85d72b67cd24a5b1f1dcf7b201ea7e7737587f67266a2f224e50e40d169aa10b055f7bb7b0c742b07fe62b1d72da02e667fa5ae60bc27a5c93ff4a7fac1ee00137c17561e4c1741c7403b5352999d560737003c3c6d7529957bd669126ea950e0021bf7b8396f7bc845ea2c88d41503bb8e5a73550ce30359c6c1208fcfca40e9e53b8bcec5912304979ddc9a4483a0393941c3324b01bcb175bf9567fc59c0ddc66d9b9c3eaf9615d0160428a6151320675e104b047be7e4d20739758704d0a7541543d0f86a5da0e42bb18a7248e3413b0e51a184291b2226de651ecfd420d +generate_ring_signature 869c7247a0b0a1fb90d96cfbb2e3d17682be83f64ea5718718768a7ff74bdd41 cd4c787f13645ac936e8e981b3c725d1bf042959eab770f7c28179f6f37f959a 50 64a0db89add71f4dacf4b369f61a58504533ede4d3740cecca23b82f3a75f4ef b37094f708fb5ffce04e866a09c3aa4ae4e9693abdde06a7b22dff21330d2865 e80522d9eaf7c40d7ebd82c81d893dae50ccc030c67eae697aa0f7df696b87d3 603bf0a35d784c9788ce83017240d87603463c6c41f61896f24ff3a54e5183bd 2879ca5cbcd35d10079dd6b0875cec28e8f177fd12a7e89a597d4041c60b28e6 8f16a24090b39a5295926e9f7e1e73b85fd8f12f96e58862d5a70b5b8067fa74 af4aed48e14d50dd553871225b4cb21dc488041ec203ae1f4140c3a46595ba69 91619b1d38238a1d1ce66c10b3c474893e0484a3af833c55a346d08df4520b2b 4fcd543fdd76e2a7d5a31e6d0d39ec96e4d70b14ecf3419d8f59f8a87e31a26d 84fb3a395fc0fe8ac6bb8fa697cb62d3d56cbfe568c24ed6f6c973cc674e63e6 2c9215c4af4e6ba4447a7ff5c92670eaca21bcc140aae3ad637a93ffa4e0c707 5384ef060ba220e21f947772eb03716fb79aee73e70298e74003d6150f4fe609 ef2500d30e8ece7ae0a2ca2026d4f176ace683edef6326a16f631e42029de6c2 4702a38b0795b6c71a0b8934c2b43b0420c29436fcdeb1ff04c5d44470e900a7 bcf1c1b26acbb158b8d4444fc9951fb62388c9e2e37cfaba70a676a0166bdb04 32d56ab2539721810ada48acaf38e0d28a2dd6e4eedc2dd9c82cac01786111e5 9c3321f4e62d07e104398e1e405823e9e1ed36032ffb78ead40900ec52779db9 8b732bf86cb9368873cbc81c0390eec33c88cefdc66d4063c54b09ba3aa2e78d 2dc91d83ec7a70f8fa663e49c70102671b43eff575c4ec9dd2ebf3abd7c03d61 f982af7048136c5075ba09d0d82da852eb1ff9879a49967cffdb181dbe08d576 a603ae7cd1acd05ddae21bb0803fd7d4af1a4fd56f995abc3343b3d86827093b 296b597866b55b7eea58f80d58ddaa00b7be7058e07b24563c4732a3de2c23d1 1a0a0ebf748500c4c58716300a78bc636d8616b3c6d4cd9d27224ffc6ffd21a6 2a2ccb830271f5438d1a91b5255ba79c629261eda2dc9237d63963c2650e7038 5644c2851b08f83e350bd96db37015bafa8100cdfaafe8d9576b7e7b5d52f76e a69c652a4d177a681277d5c1b4ad6b9ef22737b1d49789380dc890069aaa3046 3e7facbdea7a85a4b59ff60f20d441179fe72d3e07719597b11f544341fbc223 55358eef614502ef018661f3092b076e66612215a378f67e060fdd3a625bd41a 92db53a847ef3a1e0786d07ec6dff53daf37c2358d1b76174406a75bece6a192 6c248b764ac844f7f20317da6ee0ade57c3addf491a6309e19954df847fe0b57 c2b3c177d65920dc7e16352f4d4a1cfa82da74c45c502ffec6148240b048da0a eae88428fa3f81f6a565c6f71a34a1a282550b543d7af367ae568cde957a5adb 347737d568850ab93cdaba356e2f2c932df6a8b41fdec8b05b9104950766e803 40473c24f38722a5db64db65f713d670ca27db39726f32a728eb93774a89ad9d afb366a426ce9f1906a9d3673aba98e048aac4e4e668dbcb17054378cd42ab44 e9f3ab459f7194bc370c362fd7d8a6a75ca199b9ab4eecab528939d27dedc48a 0d4b4bca9ded630b3612d80d468b504d0c180d0cb434c46ca42c68ee98dc2cbc e1a6e0b00675b3b136853539a4e7f82877bee50b7ecc3fa26b8bef50ea81e5f9 7ffb6985097f8b43c0b1d8e645e7a7a92c44f72d6fea1ac90e429ad8cd6bc389 9cc6611070bee3ad7b9ee4cb7019a55e89981fb33689d4ff7a876d543d0e9112 e7bc5ed886bf0e3d7f6f5c226f8fcabf9d1935e7e2d609932ba263f451cd9d27 1c65db720c1282e65a0e49d0b06ef80fb5bdef56c74df1989eb020a3568bd4ab 7cc29b80758c5528e9534bf02225fe899ce2d91bcda453e046f275cbe0f1f9ae 51094251b02255d1ee35ef29afce78bcd0082a50dc86a164aababac34c46bf55 ff25ef58937eac01fffb1d4c73935ae9852a5612d26c13174f7199bf48a6c25f 69c882e768b9f5ab02710125377cd5f2e137d22b25ab1e8e3ea7421e262391b4 c4fda0318a3ddcfe2017ebf0bd023beac85fe29e49ea175b75846fe20a97d461 49eee66a75a60155e24d1337eac7f8110bcd122a9a25309383135d43b37a80ee df2a2fd55bdf1941f0a7d40293da98f050c253827d420f6e020d11e81613a0a3 d56f97969fd7002aa6a3b9448bcb83354ddc3cf148c4e9a5e36c050fbaa7df42 b61e797b24014d16d9cab92b84a7a057a1a05054a1f1de374cd61c040fcc7c00 2 b854df5273bfebbece2e31741311008c3540af4c1e157d0a09d65ae3ee6e5c06436b2d82e8c8a348bec14601db213fa843c43887576b1655b8f522c326f9a60c1feeea5cbd128c8397cdf3c63f97b843a02dd368de1f919a6c7534d0d21bbe075099dff3aa75ec9474646a6883da266a550fa9b439cf4d1b9313ed3242875407f643f5f1c5b008d8df2a3801a32accbdb4609e9f3b8c887483efd232ae14050c4f58302ebe83d8821b8773e6faabcb4ae101ae948f0313cef255ccfae084800de04b85325eaa695071cad0b0c8b685e053a06edd4ed8d82e921b6a6e6ae92909404f36a771f95ea10e3910e5da87a79bdd09f68c42f2ab581a79114023d64908d3e2f95c81ecff1bec33dbc54adb8ab66c1bf1ad9b4def708d077623462c5d0f56298adaeb0066c19cdd2ab8a3c12a01791091690e50d0a39087ee09856bfb066726258fcfe26d43046fcaddac4880ed85d2e4e125586474c43553620b37d10a3e81f6137a17356ca613263a387c1060a855f175678ced2e1b2f0487e9d4a00300aade217e03de51a135f0f5678f32e0307027a02fc8ad219a29e86c495f0a0a282a92d4cd6358ae229073e6164481451b48fd5820ad04637d48f23d8cb346069af074eb9a672d4fe5177270bb64646dc24c3ec03aca505f8a9cc4bb21e8590cfe66f8f59d313cf86bed554bd8c8b63f06b8e92bea191cc37a8339fccb2e51051632f84c0f9870d2968b9ec55bbf06c566186ab36bc43122340c99d74a07700b512718a6f701f1b172eb6cc44435a2d4120c66282733fa7a22e116391e51ab06ed314b106cac92ac73b7bef6962d156e7f9ec23cd2b241536fd8dcc8138baa0b11e3044a60fc69f10523ffb84ae1a435a583ac3e028c588edbdb75e138f035047a2bf137d9b47cb8105d3423fe4ff2e2fa96a1b2ce7f2604cd650b4f3b658e016271ffb7e88d9ec23873c16fcc1d92798235496f182b2745bd4df1028074840e06a1d443907f515d834f79fab8082273ffca1c8703706ec07302d4a1dc5b6901e19b2623e26ccc30b4ab5109c817f7163a00e2bc6f6e5955e75316410c195f01422d8dec1a27c664cce707530e85dc1c302e3922cf4ffa82ec1a80151a44ca09c3579ef56cb563c8329bcc739005bd7d057a2e6ffef889e543d6d20c0c69ba05a907c05bd2ef258f61649daec2202b531104fb1193431d8f12b6464ac5cf520b809f0b496e0e34308a65a25585cd8d4eeb6dcb7d73b3389464862fc9164f48092f74b81a2c99a57f306055f8bb8338b82627b19c35877cd578ffa6447564c704912b88dc9be5fd8703cf96ff3643c7c8334d61f89077f62eae126d8a69c0b4065d4a00809e6be1aecbee4fb53b1f756c1c79feb82bf44de8c833c8931aca6e01298cef11bd378804830e958ceca623ad97172d5f2ca7b5353eeb6c2d9cff0f067d1c7c29b5fbc0fba774220384a7009e7f8ca0e8db8b7bf73992afedb534080ea6df6a7b0d1e71145a7117a5e16f607d132f2c2512c3436580e809c45f797b0f585409a4a5b5026b901067c2d130d66bbcef1bd85b66576315cb870751aa870ab65d3a9e6ec44fbde5ff8bd520b9b29cc572e413a428f9005cad9df8183f0601f23537d7c3054c51e4a95cab5acc4f1aec7db14b6febb75e3266367d5d596e0dea036c798a978bf880423093d4929c6d4b244a9874b5cd3500095b319b8e0107b33b4d9c60dccd53ff651565a687a88dd5f960efdcf29467b5d04e321c2773083602313ddff9a642f4ffe8f147d99a9eee00aa5ebd66764d172f2ba22c038c08538ff944d6ab9d4796e5479b0b3339c5c78690f8db36aaaf75eceea4367ddb0b11bdecdd5788bbee3e4363bada8ad8830d75d2465b4070f4312716c5ace376096929f6ca8867557eb0ce0f9012e6aa397be54579234001dc96fc2c7cd03250098ff6e080b7228981376b93b6af674bfe0d39a6c9df262a2a80f73b9531430301d262e638a96aa55fff4a00f5ceaac44159ed85ed37e475c524406dd096643d0735797f98e52db02565ba93388fd3e75c38b0c4d3276327dbbb12a51c1569c601723682178103a17295b81a060c099371a837569f362984a722e7a4914fe046050f9a015a2f91a2fbd6a0a76ae4c1b072ad3fb9a6122d25375033ada429b4fc0f0d38870229bcbdf4f94adad372b332ce787a3ceae44e84514bf26c6eaad4ca0437ad225442c2974481568fbd539f9059be80fbe69fad56263f0f427689f6910828e4679dd1ca75430b69897fa58065811e1e6b1b2a89ed7226b17f31a7a59a091aab5c83e2fdeb2c8b7bc52d84af68d4e3d57e0e540d38a3751ecc3cf5111e0c24e6744b8b6e2b61da27d8d2c40d90e01740a900df55f5f5dd2d21f1e2d4210d097c362d0d66f38894b4997df63b06d41c8094231167439afed0c23349b8b0095573ba5c72bc1238ff91d11a7fbd1bf5f03d64b72f7ec8e8d0330cdee9ecd5026f23829ff8175b81f03066bb2b7589c37b88230e7e18840504bfee024148d10d0d3e246b90670c04aa1981bac67ccf1c0e81debb920c53e3e4bc31d56da46c015c4039eea9c3bd4e9653ae03c2e634490f2693dde90aa6a38525eade34478508e4d8a6062c07b2020eaf40b43c8216f4d0730388879518c31f72bfed2ab8e105fb78a06f9ad875e380f32ac2ee353cd5a293047d14272c9c8d046bb297be680286075eab2fe1a5ef43ef61e338bb7b487a788c609e8b74cedf4fe3eee9c2650444887aebff0c33649a23f25281f7393eeb6e4ffd211edb57a0a6a0d2ccc2eb007dc237cbec050a28d1ea6a4badb286e1a6fd8fa2d9726194307bcae809bb6d09509427ad297934ead29d912b86d7e47f52b975957dec8a3aec22018f93248e0771094b471b590fc011cfc6681d8d5bb21ce58f87e355cf0fdc27443b05ad60084c7fce3e3d401865e252df9725c49875cf206b9c15f91269bc68ba2b9095e80beadf571b5e016cd8ebd2aaddd3bf3cd512787a6fde7e3d89033cc1f30e5bf20718f0f1a0e4a585950a3c32088672bae07dc8e06c419c553123344cfb08fac30049985686c20c612c7348e2f37fb9356d292337d90f0c9a495ad8b447e031fc040dfcb46edf034cdcd7f7317b2625396dcf70f384ab683c8480a6254308fdd307c8c962a133d2b685fcb688d7e0d6764f4efe37b1e3dd6f6aed7bc247e1a0060c061811214a3d0dcc33e7a9519ac4d7f1ddb1334c1bd28307eafea3e3131b6f07caad0dfd03da229cabf9a0c504edda6d3bce3ef3e754d5d4cf078c9361a5fc03d8a1b49ef905630712609ecde497c1b54e008b3b38527177df60d7e0ce88ae0287b34dfffb0daa0f9ff632c779dbabd8edda87d779ca6c11296c168f6cd49105ab86b375369ce70a82a0c1e65338584db8d2c2f007dd9e28ff816c95d9c4c10bc439acad9a05fc90a4190a10b1a3400f97b1c34f2bf6630bf279183567ab24018d461817de728b1b6727fd62228fe3702e67310bf6f820483b24a43dcaf226005761495e717fe30e5292f051f82281a9e85a8cfa0d9a52680a056ffb53c53f049e47e80d9aab19243c2ea1d8cba4874d073dc8d1adcad742671b68802ff0c9051a7da1db4830a5b14899fe12c8337f1a00f88796541e37a85c7a8b6ae8cd2c0db4064eab0f390d15608123eecf7cb49292021d53a28016238073073f743de50e6e01f71dc1c36244724857c176c7340a8907a195b2b19f76a0287d42a9b5b407b570bf698b40386c641bae6f0c2cc72afcf7706fe65d9b78192fef1da8ee690f93ec8ecf413c06bead493b824e90dc8c5c958f888c11a6873764751d17f9e301998d47b7e4d1e00ad610eb772150bb77fb498ef0f3a844c7d45187e9d04db3075e6b9ac21daef6e3df7314c6627cf646c71c85b05dc0a0ec2ff4a0ef58331001d32d3124beeb1212538450443bc5ae823506d4077eabaafa414509e302e03b08335ea3964782b982c078dac2c271edca8cb798a68b974962753935a822c72307774fbca91cd19be4bd8b5ab1a81eb007c2498db6ca94e74ed61b1bb5f556cb0419c28bc88e8be8b8877745e4d050794b2b1a5c549585afb5e4022872b614c8084473c65e0e2d4e18e4f790c556976f79dd5c2ffedc5d3a467c5f8e4dccddd6038f05ebfd7cace6e82f9d069d74a04b67e083e58b1514cbe89bf5cac23593590ab744712f1c80ed6499e25ae85dc636c965872c7441b96af6b9e1766a4502d60436adcae780f3ee4d097c6b26591c62c10eecf62dcfe8b9faed1cc3436181f9096fd3e6546b8a683d04ae9d35a5246e26c0c3d67a85523552ac135e8fd74c4e08916a7051715b4a6d8bab0c88cafb55ccfd4d77684292993ef1a62ddf3ef00f0ff1f3ca2be5631066766d923ea5d45c04513b645471d2c698fee5c11449cdad0420191d2f6f7130db95889daeefff4b2307f441ce2e1d2c7b9dffe373a6db4e058796df6a4a485647a8f9f660adb6f35a9298c0f427f3cf212757ab50a2d47000 +generate_ring_signature 1d0b119ca5e69bfccdec2771ff272dc2c8638c187733438939525ccb8005f4ff 8645d7285139bdfe550241936b2fc8a26757ffcaa7bac9084ff8a85cebbd1e89 3 8a075c4f74b5520b511ee1a487cb31c4cc93befa5af0887414efe0115fbac0cd 5407168cd81fe9cba6a34e7e30cbca17f448f2226131ea57acd74420675830fc 2ffe6b476ff37d8d6487cc1c7e5e89ba0295a5d0128e6ecf8ae64165d6d14d84 ffacc2cc992ccbdc7cb0cc1a695ca31a92f6d6a2563b03349688a63a86f8ed01 0 4aa5ec4893a41bd3429a0edeed4721d10dafd3f1b2fe3fd144a2691a9a16e205f3b6b3f8a988790fda53f53cfeea236dadc61047372def8407f7fbef7c5fd206db64c092b429a9921c904aee753ad3fcc1c5779c2117fda0ed10a6ebf77d310470bcfcf55f6f2d3304b91f29d99099e284c8d1f5032efa5456af2bbc4304430114ef8c089866f7125f66b759d1059ca1c98ce2ae4d90e68d7af18d7931a5ee0ab40c025e00fd8c2bd450aaed9d6d16ed08c4e499ebcae6a45cebfba66656260c +generate_ring_signature dc0159dbf72ca06954ef706baaf14f7c84f6d6e96aa47cb0fc100a73f21506ca b0dce2128797d8cd8ea9c4dc13be5ffa76e3c68278d8721835f7bea75d42621e 155 55bdfd958e609cf23a67c353b313cbbfef67c4b9f888aa9ff96473fc9c841e61 5cc2a7c274ee46db7d80a45e09bcb4701ca0b6c651a3f71698df8681f565da1b e1ec3ba3b9a5c1f93867401ad6f4b8f45a81fc04b057bf48198f93507db0c45e d26059d3c9f334e298bc08d99e64060f1c68e8cb0db08904f3f2e989c8eb0da2 06ff2aa52649f6205f044d65d691168f3bf22da79ae46a294a362c23fd674cad 376f687a817012087ac04320874b9e169806b3a384ecbab35aa7caabe11af3af e6f0454df292cffbefc002e20637b78ae2c52993e2f1d7801fefe9894babaf97 965c5c80ee12cdc2b0ef724fea7b86aba5ffa1ef7a8d371f634177fe0c77ed69 5cf4164fd1d89da37159323130a12b0dc4d22b6743f7a14f37d85675cb7711df f43d9857a3c0ced069e7e66e99416b0f4969010ae1ec4f90568fd9bf1ab42d27 15a59c1dd5958f6b8b48471d7fd113b4a761808409dd5606b5eedbb3fce5749d 4e8c6e51b88c5df9d2f41a66e80a5b443be79333309de74e36d26867c5260f29 84d85995ab7fba0a34a50d10c6c9ba52922b7f5f1541e7740dfa7fceba592b3b 04409b6c2ee649e8836796a2d0413dae06f8f41cc352fb00bfb108a6f608ca32 9c207be7f2a862125bc38aba0e04e98d16d0d2ff2d36461c0480716a95ec0a36 39fce2d41d67bf1f182d1ccf23e140ceaba4322266b10ca3c950055b6be5b023 fef4c2cf18221ce0ff9810a1928d9168e1b88db9f42f668d74c2876286c848e3 d1ebeccee551e9c25aaf9c6f1f6334fb5471e5e94f46bbb1d80729919c5691e6 9e7ab6f141bd4ecaa6d7885514127168338ff935f1ffc56eaad972e19b807aff 4aa10541e1a9124fcac6896b065066ed0d73150c9e9455f914e4d96ec07adf5e 32ca3c20ab39e82821420d6e2e37cb9a72f19d1df5908fa1fedb306b16c3273e 8172aa6cda51efb16683412242fc3b90a3a37c9381e4109c1f00521546fced9d 2f9f8b8f71b8e1d5cb244c0f0a14caea1c5d77b13ceb6a2ebf2b600ca2d236e6 719b3d1256ab1d9f286f9cb4bac235da7131be9dd47388b91c6eac952c53312a 14a64d08f79f8b03c321fdc291fc633fbeac766125cd5bb1293028bb7e86e4cc cdb1c8bbcea2d12159ca80158b1d8944d839d82f94e1c0c3ec84c71d00a67659 aface084d21571606d8b913198308fc78bbfe4fef087b2cfdceb8c335d756d43 66502a8fcec2e95a45c10fd5288ecd64e1f880a6b7757a3921e14f432ece527a 63b5a9153f88dc28a9dd325a81edb0bb2fd73fa2ad2aca31839f9350412b357d 7c377465d285f2f6d31834ff61cb8a9cd5ab2fe99b4ff9c330e0d59d305b21a1 ced17c63ce3dba87598c1adc062f3a8af81d4937447ff8991f7c780bfd9d9631 d33c03c444dad20c86164d634bcc2689be5724091a95c006723756544a5f88b3 42c6f935724c8f7f3f5c53645123165daf862cb05366a895eca0a7656cebe76c 4950dc9ec99c46c3d605d97f96407e9de344b0bfb7b19f976c9c84a18b3d26ab c813aa66c11bb66586ad3af0cadcfd7f4678f9ce71478135b8cfaf3f7fccff8a 91f5b936445454387f607698a4b2ca38191ae36dc6fd0ab0580ca4b80b058d8f 9b8741d58259a1f279a397da968d1df565d8e133ee7c69e1ab72448660625adb 4a7c1752977c764cd5ac091751bff8dcd41500f38b7c3baf458963f2133defc3 2d2b4a25e1f4a864c3f45e0bb5808484bb51d2e35b9180e3565dd2945c13a9ed aaa64e83a28293a0f8759ed4cac37082552d3935c827293da30bbb5d3403613d 66452a289e79a5361719e68d911741f20163ef4896f0257585bb9c832069c5c3 a14e0b54b0e02a7e81fa314190c273653926c342c819d74e9aa461300f238855 1c1322db318ccf855d7a5ce5a6aed6bface24d4086cc7b26ac67733be55570ca e10ddca61c7790d94984c7ed066543eb76623923557c610ec2f8de6f79f635b2 7588b14ea4f0e4a215d9a982eda345bdbc6aa4cfd04511867c40f9011556434d 409d5ba7c80a7e1c29df9bf923ce011ef47e284c0bc462533245be82213b4b7a d5e6a2f9f50e6e03b514ed898ac28f24fbec78eefbb3dbe0a6a00627f72aaf4a bf34dbc0ff7eb6c8a74f111324fd8eeb2be93a93c8975635ee06b526ff1b3ad2 ebf00d242b0667a638b7c93c397e45f92d1e8acf73bb2abf73b03490b3b6c3ae f3688388ec40d6680cdee04c6f11d79bcf9eb4e5ac2ae253b4ba852826b76bf9 0ee543f8b280ba4381bca59e1fcfff6dd425851c4119e251a7732c99b8d2f168 d872db69074557c2102d81103935a90bdea94ed0b0200c3ab0847b526e29b4f7 d4db1b4947a3e86d998ff66601af2f2da8cc84e9d724441b464143b171d7c89e 746e4cd0a3813757876862505807b4b78270c0a170b888a3bb9e3e60c0101908 8d3606dc0218adf7c809f52dc2c19c9aea02db66e95b21a4dffe48680bad98c7 721174c2d937c62637e492c02253ee2a7defa7d4a3b6d5bd47bc6f0addf40ef6 97bc500b936ed73732b36010e062fbdf149dc2a5cce48c1a648828156c956c28 f3422baed25571091c63261b7f854a389392cfee89a8aafe67b0986c77f933f9 3224b4758162f6a3ad94d76f096029d96b8542e883a50f48d189fc9ddd927efa 8634ba86f40b66d5e0ae98089bec9c49bf7ed348c857e9a8ae6af9fc1a1f1f66 afdc97548124eefa649ccc49f8c4895e1503a0b86e4732dfe073b18a14c6e0bc 5290911f8661f9a415535158f2effbe89a9178c4194c922b660645825e234584 a79798f044fe2f369b259d2b59c949a0cff4c4eb54b5464a1c07862032180273 36f35784685306db02646934f6ee0734226dd836ee407bc83ca232539af2a10b 1a689224e864e3777accd246ff0ec5ed4f78b44c7af8f551bc9b411f8614693e 37d040f52915b13ecff79dd88fb88f109f091a5716ec289f72adbcd9d1877221 3f8d7c20a19fc64d9ca3b1eff52f6c4c062d6ad85e9b242b3d16618cc5c359b7 8fb07bf7455db11b402bf9548947b6af97803a02577e538e9ad452fe51960335 e457e7a04242381202e5ec2f466205ab1cc3fe0fa20a97eed9cb1afa6f04664c b8b4761d93cb707c2e0fc386991643d770ce3309203f1b0c8f182ef797fcbd3a 4a5c2e5aec7e342cb8e6cf16f17678553cfd06e5359be5994ee6e50bf572fb22 5c16c16457e9fee9a62c4ba6b6dd7e46aa1f3f85d68f08629ec7a96b85118869 b7299ed0fb01db3149fcf30dd1d4ba8c99b9384bed66d70c3580e042a6f7833c e6c61646a287ad0a53d582ffb300a86755164342b83f3a6e5fddd5471068658b 21e7442030bf8d818a79e5674f1b5798a576fbb1ef84472add4689990f62e8a4 7755f1fcb777b9182eebd528bf3f60f6a2da148514e90695acf897196bd897ac 8f50370b4a8db13017296ae820c4b728f46e8244824e590293dfd9db7888ba5c 2fa322e48e87ea8a9ce4f70ac45fec4bad47ed617817a39c6ebb38bf007f3802 add067ff6442a2d93b12b6de049b5fa78541e45dd0a0f74c2223ad7c61a7198e 46554f1886d0ba1aa9e264a5f29b08c957b5c2896974664b222e60b6e47e1b0d 4e0a19f0b65791c9b0b510e49c670cc06bbb324d67f657a4028ed9f03784d8d8 386291c7799ecd8cdcef7fe30f6021f42ea2918b06be3fe8df2f47a0fcf2d616 2f4a5d75e0868c2b8e523ae394049ed0ca390bc64f641ba203b9b4dbc8d41d2f 841f17f2584641774eb003c751d0ccae29152dbbadbba8eb066a2ded5dabfe98 d96e7157019eb21d9ca9ddad08a2c2cfdd752fa10cf6aaf11089c180f6dfb13e 7360d3476419e86cb99abd0a33264327b0b5171557d812bdcf6800ea0bab7131 463083e7e2a8fd2d956876dec974816bde097827365b94a1494d5f7169f69686 44e8016a6c0e2e21241c67bcc8b844793daea164b5e2a14baea66c3c7a3cc773 22764f41e82557790205bc987553010dfc5bda9d8b9cab62def4c881e4ffabd9 9a52e8f5b5cf1bcde87297728a79c4154c272fab3a31505e9de06cc22db12b20 45ecf071a3f952a3886e388374de59aaca3109b8a9424b7cc4e9844de93f3c38 04bfda9f253526a91d0a4eaae8e8449bdfa9d200346509ad9fdcc90c9bf72046 baec1c08bd22e1d1803758f86de1dab9d472cefa662c4db5da8bdc3efbc19b34 efc658768831e5dd37bc425c2d958f14c088f72d86651f63099b6a59fc956aad 8bb4c7e070bdbdcf0bc3ccb85a7f636c40f6855886fb9e5afe3663c78ad39122 a4a4c96cd0361853a0f6e464a2ef681a05d30501c71191f74883a7071b38ca74 1f0eaf33404e3d3acd817f9f8a49200f6610b730b03dcad2c75829a92b67d8f2 693c7c1e884e24acb6ea9f79df9a4d82343d2f00a36617e80b2341f4a7061e9c 57e1c0ebdb580b1ef2eefe50d96d81d9182b45cec86b8c2bd8bc70d8094c3a64 10b2ab4153737474de7bc454ad5f247fd398761bb29f665cba97dd2a446f7397 e80e6ca216d809401268bea920b105ae5bdd440577b7a9ae2981b3d75b39bb55 967fcc98c8830d8374f52e19229f50d39ae130caf369227941c97f432d6a381f 6276cd137870acf4b11d90c2aef851894fd6aa8d8ef3a2e6a7464e0daed09c87 43a43751bf077cba57e404a62eff1082d66777f1e304f0251dc884a472d65730 199e70fda56e43e548af5bff218590ec49467db20d932ba7b93490df9bb79ed2 75621e025d68155e2501289bf8caba1ee9b89e6389fd2ee595e72baf5ea3b34d 6b7e8ef6c4575bac539bc5fb12d6428cec7286e03ffe1f00d4996ac4214051df 3a28bc22d5954f34ab59bca16162feecad41b3a25ed1008b21729917e9e4dc4a 8996cb1d13337dcffb5f57547eb7c6be1cc2af29d9bce46c4dac048159a15920 7b0eb9a962b2673a4c3385f17fdf9059f202421a36ec76a2190eec8ac1680d1e 6da2909d4ba18f512cbc36a2221a2e16d99a78c6e526e802fd9fbd38b8608ddd d989d9c710f84bd67771a252197af590b63b424ad1c89d623181ee4dbcc2acb2 5f03667eafa7c0eee3c741d4aaea93246d9085248002cf92b4fbf664da891e5a 4e885b308279d51ff6ba3294f150cfa79de993e4b4fe240e0383926eb1b72a7e 48310fea7a0b977e646e440ccfd050663c1567bbcf716c18738631be861bd928 2d8e36d9c5d5bf1a121d9b86dfd22dd40df765a8640383aa3a98e86815f6b202 c2ba1b76ef0a6ffad1f816d5a195b4290ea5bc5a195c21b99a2205a0fb0fe19f 9264af1aff612cf6c5423fba55d78357d35f1507961a1e5777cf9324496ce5e2 ce48bc8a5d073ebbb81bf4e4a31d30b43869d47aead425642fd590c2c6b71ad9 415ba1f571226cc741585b624b408f244b226a3ef68112a787b7f4ab117b7070 02690c0871b65ed57af53dfe9ad9af13fffa80e17d559e3ad8bcebec4e3244ae 28a00ccffd9aa89903398ac9b36e8bf24e77b25000ec0cc05435f70caec00f5f d71cf74bd0d2adb4721b4c2a2601109e25b41290716c2dbd20cd71416560042d e497022d82a79c271eda123b3f2cb12d7e050eec55c7ba3ca5c18f90456df49e 5593d828a1c1ad5fffaff2fc0e4b82c488a4a4fcdee2bee513fa7f2b8ca21402 ba7deb31a63aa2c63a9b6de0d018061bfd5bd1305de6cf9be496f2d0b38f0f1d 2fdf34d6c3f7b14cbf3d6dc057f68f9238a01843bd79f65c343f8888c57e032f 0ec1bebdae697a17fd38bd3c2b1d466c6a2cd62b221663dc14450fa9645f8f0d 64b8735f9e0d05b013bd5649e8df55455cf90d0a32e01a5bd47ce4bae2e2663e d3210f6fb94b6157defd835fbf6e24f335a53470ccc876c8f24b9cabc4bdc689 854d5cc84664a763d4ba94fab9f6826e4b6795b2c4c4644d1272fafcfb38dfe2 ef8341e4a2cffca78f4f85382c1bb11231f98e313e8b4b158f1f3858e0f1bd89 721bcfd1800fb89d20114f080b739a7f577466853064735708dca02bce6c08bc 2b21a17310ff3da504aba575ec91cbeabfe7cc7ddba637140f2b7ea4a087e5d2 c9002d13dbd6d60da440acd4e2fa2a96a51cb18380b2304c45f8d55d9e3a23c1 9c5743359406a6ff0228502eea24354ea96edfeb39d4149612a9f84320c3752b 4fc972f7883ce8ea63a0579fc59ba3626876688dc96b3b2774202f8c2d514671 8262e5c2fdc9e2d7add1a28b1ab3acdd49dcbbd4ad6b733de427fdca8bbdd9bd bcb2d7f1ab48ae12ac447d9006b14953c7b75a45eba9d7c28f3b596ae67d90d9 26cc343804e2dca0d14ab0d2a2d7d03b794576bf270c1e79b737191a78dc02b8 9acf167693db32fe00a5d4ec090129992b39c269833c6666c1946d8523bb054a 507659e6454ec03bc6228a469717eb91adc0c14f2dafa266c56522e037bd543f 6dc86ba6eb6846cf225842fdfcdbce3b702041a03dede7e5003cc402df63335b 1677fad719b74408ed9e1b6e2f9e5e6f0d5d54f850f8e4a4307c3fd2a5db6d0c b27e2f7563d41739dcc27a208e3c1cc6d7925820e953b36906bd63456c23a4c7 46a4d38ba7ef139dd455ed55953279c6229eb792833d5360a449e84d31ec9d8e 97d72d2c3deeb90f2b7bbea277bb5409dc5e185443550599dee57628b152cbe1 06cbf2f8915bad92aa93e100fca048910bac864de2e67b786924a5dfa47ed2dd 5f01c55600492999cd80dca1fb95bdaccc1ccc4807e274f5e2d76780a62ab9d3 bf3525ee75abe62a109fb35e297a6ae6ab51d430756ca8a44c2aa0dc558623a3 3a78768168d7f695ea5c96485f80efadd5d0434c256732af421ca95921cbee87 1748b5a61482181b63b42252c7663b9c19d3386000b73e440d49a2602801a192 47fd23ed6490a2ca505a01a2a0216e518b5459c621df2fdf9f4090575ecc0819 22cfab5bcf95785b94f17529b1292b25b8ef368d6d3bad17438c9fc4c41709ee 3309c171ccd892d173085fce4bda373b15bbd84719baa5c86b00bcf2c04191f5 6e8a6e2009014f498970673b8c94765896e485f7f5fdc8d36c97e1daf93c6003 77 8d5dbb7a0466e3ec9f214327c2746c946af769bff38da55dd5ed308424691d0c1ffdca53753ddb7be6ea081da0b9596fa8ea4d72ff582b86c3778012f5005207f7f8dd669e9108306d477530008c43cc8cf08c6497210532f729e3f084fae80a8bba574ef14b654f503d66585eb2acf19e2bf1a67fcaa554786452e0bfd75f0d276a0ed021f30fbed1848276149da319ff4e768a0fe08ebb9921af853c8d46010bf6b10c066f6de7081bb5a8b9c4e613a3391abad46bd9cec3317f15c8d12100d4549ae6bf63dbbf3937a6278b31bf80a987a10f7000de1d6181a7a6bc633d01fbae3e7a41b8346027170806b2920c6cd8e36e62eba3103947fd45988ac07d05fcda94ab8708da35c84fa5e4cfeb59be89cb51afb39a3a6ac28af8172a547008076d47811ec74c8627c4d0306ecf1f51ca03229d63f31de267e7ffd299557f027cb8b4b8fced8d08561aafb32970bc3dca5e617a91861d1243ee53e639712b07ac23e107742b7316f184ca6ff68efed2ca5bf76edb065a0080df2443e488350278f065b68920db1efd041dc7663befe068b35da3c3e94e04dbd13d929dafa10fd164072166633844f21423095e878fe5902418c2a2152e8b78a009482492ee0fb521d632ffe50ed732d0005f9d47b57181f7312b1a41b1c877ca02162d66d601aecf6ca866dc9c8f2a4430a9b9bdb740f24014593c53eb244651b0b09c605501e3228f67b83ab6ff8fe70eb5a14b66a44e2ac7180a4976fc37dc8227d20a2007fb88b9ca14c8d298fbe9d7eb42ec2f53f10c8a1c54cbac585d169a11ae73c50899d6db4823745089b89bf31b65a10c597651f8acfda4c2a0b5ab2bb7f554050eb097333ca2830915f8b90673ca90ce52d2c3fa9a8a4d756a2919d3c22a67ee0d0478f2776bfb69796417ece78a52c998492d7832080f5f52ca5691e16b0eb305f0bf5994284bf5a83cdf3f14cbcd4a5ada94b0b2760f3a865ce2e736a527b108e1757d33ed4c7f13fea7e327207bbd437f2f9372f941b53874ee6249c8dd46066659d4b020e1edd486de54d73fe49a1e030d9374f0139a0a544239f5716d7a089b2f72002b6bf05886408c2064f7c9e82bee35e0d2946c91805c26276f01830e000ae9b9532053074c0fa5949c2fce2603b1ad334387f0bc64959c167da5860f1d8fe87a047d577be053459554790e247b46a2e0c537bac03440b9a0b49dd50168654f834fc64604a3fa582198f8cb184a1619c5ce144ce86033b14f520ef30f8e0abff37da82b3cf379a752203ad9485960fe653e5ad4a7dcb835edb09ad10ee4502989de3aef26a3b77340ac584cff691d3628ca727bed46be34d186fa19064aef1892b3eb4e5265ad2c14815dabfca977c57412c2ef14cc22dffb4e975a0654b43d8c4b288d4ab7b7a8766a6d37f5f534dc3c61063bc3d2e01ecb534de806e6bc1e003ae518dca85db46d1f3f5b1a76ac554cadbe80d83ad96a1ef524880baf80746fb9253e0f56c7eac147fa9ebb98c66cf6292806b83d75ea8bba8efc0f3859c2632502cba122db858f09e24d8b2332e0166848be6c09007dbeeea91e08c61cc0482496f4faabb08ee57b1826843f13bc204cd1d5d30fcfee699b0eb50603658426fb52f84b934e900fece01c168a5f0870a1cea2c7387f9ae232ddc40b611915a52f77d95e2eb5892bc2d1646387a1428f36981b44e38987040d0ab10ebb9887b6f0fb63cea6debc60a9c569bd56f38f5f68a57d51adb6fc0aa3a0e700b9051a49969343ae55625fd1be7d46f9c1c399aa82b6c57e8fe808222dff0e01876c2f88fc8cd84670af0ff6a854bec10951a833e98855376bdad2d5224da4044e15879a6fc3c0e3d49c6ca77da12568f78ec40a3dd05e466035dbf987046a03bd1c7973f04d98c8bc232fc8cc5b65583f3944bfbe212dd961caaa0fe48c9d00f0857609e752c014e83a79631e866f86e7796b8b2501f82c81b513a4b59bd10c6f506c4bd45457f45a332132c9faf89ed50bf74faca6f79ce2ccc63d7e528e0703fa736d74f47d96d0166e7bff8736b37c7da7f781232490eb360dacace781017874de714a5862df11a193a8a2397928ad3399a6d812511bcbd579b40871c60af3e87e9fcde3f04031f8ef4e1581b3792c20df1480730f57c9e0b56ab8bea30b6fe472c524ee3096a5ac53830d39659254108d2d31ee7700ce45f8566b394b03269a3fb390646237f7de1d9c6bb9f916a2353608d354d0ca77478f29557bda02fa89154b3184b63fd62d953d52f4e1866b72e38fb1129c5a7ec57532f0be18051861c0b9ca8bbe81d60a3f931b731603a2f2faa76b447ba2502f000c1e11460e8925203532a0b182b2287696a430ab2102e919f6c38142c685207c4d7119d00b6ce2da2cf249fff1298c815fd41768873677207c28e25bc4373f1cc32463c00540812b690dc1fbc38cae1573176b9e08c59c0ff6c4717d459f234ab209b426058b25e7789188f29ef01def5ad20237a3d0d2197da121ed2920b2852288d6bf0ce025da3764337443243d16c5d2dd1a6557df48c4ef8b6ab1a2c215fbd904b308be4ca810aa8a0f9acdd70fb3ffe66d2430d1ee242c4e1fe2c3dd06a7567f930d3119aa0e6843460f72e60c67844a2f5d1e501dea1c9d3892dba51f6bd7b55803560212c751244f0b3f97c2100b93b0f096d0194aa51d2f865179dc00e6a2ae058f9563a46c8ab11dedf879f079f6469056a0f9e193f60f4dc6e803dcc7e97f03d292472a20b336971cc84c0df1ad14384433ec148b0c78e1d349e78cf00e440c9a7afc466cc762d9656973ae25e19886182b5320bc468d71c955ed6013d38c04cca336b21e593e0b5574a6a5037ce4c8a9d7faa3141e5e57f6399acd04a6cc00e6a28ecdf54f8fe5be58832ef1e2a0e9705974253550c1a05e69c3c72e3d65068814395436df1459c78c8acfe7f4db4afb9d1346ef8b72c2e137535c5c6fe30dd4431b8b57769412492b1a9c9fcb7190d551d7199d023ff5d858ef92cda2c705fe68eb8c4454291a16f1071e5d9eb29ddffcd621e6a34f9a4462f32f6906d00e51e3b7a0f4a32cb83b5ca111e4cd1005616d8464446c9e70d32cc39dac3d3c06753f849ae0d60d8655418e94c88ebfbedf0051727936cbf825928a16b0b33d07e08ab155ac6b7d07daa2a83d61548c3a27ea09fe450de550f0ee29cec2f03a08388a63328c23b1a0b66eeb266f837abf657b9a649eb35462b461bb533e3c2d0b69af1ee57a6b1df990a4574a6bfccca5da1c23eed9fef2a9225663b63034190008f42234965875731dcc76803da1a58290fe2e5e8f88f44d9bcc035809627e0bf6632a71eda38b9e4abf69fc3cdde99a897920136517cc5be2f3db7043925304ac27ac718da62b7c550e3e8a908831cbd0a5811b211d9f0f25b612811b7c7a08c51e7fd191b966d012f22b75d950e2ee11eae12de1dddb061e504c2bde0cf50499a643b46797e190635206a51da4a9e124a6c0fa78827db20d6e21df67441a0223e7cfa5ea7a34a76823550084d3b8a6a41ded0b321b6f795a792d4098d9960580d89db4dfca3eba564e4c0743d4e117e8abb7366fd0bd6a175dcd020770930bd8e6dc9856b3ebca486f38190f5a3d8e9bdaef525a4275b2cc6411cb06f2c30700c365101ce07900cc0b580556c0afcd0ee7ad0e3c42273ea776662081b9030c5e1f1c3d5163a6674eb12368e6b34f0be4d4a2e69fab2732c2cb8dea9ebb3e0e94a8e15630532444e843927db3b78cb90771d3b411e19bf7ab09dcbd3ee3ef0a6075746f5afce41aa48e77b6680310ae06fd532ca3b1121e8a1392a55bb9cd04c8ea8bfa4153b24acf1be0d25a9c1371f43d3fa02d6ee4546524a9e3a1c8610694519c16fabcc3940f665816ebad79c5891f68a357b8cc36b8fb3950ef42780bf0954598c888d722527f0bd89c856e2e9a99868082ce00d22136172aa2201f05a3d812e20cace6d618d8f27af5727117fe13159d7b66ece3eab1926e5a22f50bbfa6f0026ff592ae7f2860f78579057db8f7d95ec685b07e47e1505cf7674c0f33117901aae02d8cfe31dc75f74bab3acf5d708e725333a586810e5cf70647030998795eb6bc85216ceb58f1f3e966c52e1fd1e641dfd6a389f2f3baeeebe50eb464d2e5b3b0586aab42d33449638378d83c5e33b68a72c581a3f73f851e20094e0fa8196166d1a392f6318ce7571c3052398b82cc427ed01a1084074b85f40a592d22f3afa34d5b87c09804f4d261b491b8eccb3ad0b6ddf6bb30b83e611c02d018f85e808bfcb5e85388e1a80dd63252bd7e995ecaf60b800235386ee7660a0ebea6cddf9442751cb6f8a1560f1f387a432f14aabc887dd64aab57925f04084cd6c4c48adb98cb487994c4bae683b0c4d21e0e6b297d4404a13c7ae74c030f54825445da3ccdea4916d52c9da05c0e209838597688fbe1fb71c0f17d1cf00a07c909ddf3515bbd8a971999f0927f1748b535031249d1e5c61a97475c09b60d13b2c49ac131d2fe8c5b20681921adcfcfe0bead3db0cbbe9600966bcab0e309e0da71d8b3f00a0dfdb0a74f0337101c7b7666acaee601ae248daa8c6555060ead14fc3a792d05e35b99321429b1b81a392faf52e7edb4ffb0375b7f6c39e606df5df228ee7cc06b285a2556de8e5b7fac02fa1dbad6a1d49f89f23087fb2902b46ad07e8b68857543002ef7a69a65fbcd04886a944f8fc358fc5cd1bd8aa5087dc0d8e5a44fcf955d989504e837c846173cc1966cec776108c991f097c9970db3d8cefe26db33fc78cd1556b6966f420c6405f8ae4082c62151af10e7ea730fa5222fe431d116e0848870687747954a5929a4e06bcf942b38fa366675dcf80fb1e7e63373d0e9a8e0ff77bd4a2bf63f85a2536ff3402997b7dffb20af408409c391bc20afc1f86f1aceb81b04ef5c22106a24900cbae576340c191dcde898018989906d357aa9c9bdad2b288bee23d9c77ecff2bbf35d7f2a6f097bbadaf50a6f1ed67abef43550ac80267233ff930e9d7b313d1c21745854e16813fcae820e8f4cc8725769aac0e6f00b1c862ffdb37dd3f8fbc62532bcf667e1ec86845207077d85868156d541ccb0e1ebc9b96d63660b0b1a966e994e61b572302f88e908f85092fce00b56e943c54d861705ce9e0e5531f1a66bda27078eacc36ef3590eaf00c63b5c1675ae6ada64cf378e777e7956074b04a813b34fd929d0acab10030b8f4d6a68cd8d7b835a83a6b0ba7a6afde6862bf328b62d67a8218dc20f190ce764c0bd424f78da54c700632aab6b9c19cf6ef945dba74af420c85a57bd710ff57e0b5e0f18ddea2cfc96293d235e5943ed9f8afe5c33746df67e6ec905050a6024e1d446198252bbf4014b5794b8a7d9fb74873c1dee6c60330ec1d31bc60d113ab95ea4e0376a715fc16022a5a965606afaf3807726bc78b6a27207994305ee15c391b205f71a62da15f7dbbdf52463932a191884388609d9bfdbcad0d0055f334ae6822bced23d07d303cd35841aeffc65388ab80fcedc66461261a81b0dd8cd34270be2542eb2d4eabcc42a9e083a07846efa79b351db493c5174d84900bbf4e442660c051ebe059550e2c67a7a8434faab10c6bfb2802b1e2f04cced0519d047ce3c502abe2ff94dc8be59f6e415016d2c77f1b54bfbffe179c9ead70aec1fa21d4a814abd41f7d5d19bc6b77f4ab14298a1bb14f7483197fff2b6390e2c3230700ff95ef79681078d49f0ff3a8f51138771989c3c1a8e18e13e49a90a3fcbc0a7b8b2458c0b6beca04c5dbdfe86b538e57850222a24eca0476c73b70654f3b8e29e227998fd54ffe06ad51f831fb4dd0b07258a17a9d27595738c060b4a087c00389c596fb33c838f4c7581663317da9a3a941056d6aa000734e380005b7c550677862c23689eef181e8107d1ff986c9491de02d8f6c001789ab222032674a1feb232ae673757ef59122249400cc1ba29a953815aa8da9e8275b3de0f3361574f998cb95a4087c880c87c8593c24d82772867ed9f2437f8b2465a0b0e13e36a5a15f56e04f4e861c1dcec4913c789a96e556e1b8155fa9e472c8007024f2f0d7978a7aeac7fa54d59acc6bea8758dd0b215a240e8fda5b05440fa1c0c933d982cbcb6e543ae08fb82f33f97a0509da0f42ae235f42698b1244e6c9902b5cf3fbf95688c9ed3ac06b5073a03faf591624f4f4e76cec2a590da26d60306e34eeff5b3f27e6d8cf3ad0dabf417397883c7505b911519b5bd8aa9f9d9930c720d534e362a1582b9e3e008c339d43e1e1c3a9f26cd7800cf4752491fb2c70a3e49b2bc960a44168bd04284b7abf6506672a29e5a5b42f27ffb1596c544af00709b832bcb891e9fff8511d0c75481db9e7a0392f16db45873fa1d45d7a85f075d05b31ff42bc26cfa9c87a6400939e9f32a7388a867877de470cdcc39e21302b44d9f40e1810367505372ace106cfe324ba16f8cc6c6f9602bbd0541761ff0f9cd6eabcd67af7bc6af0a981d403f2cd2a863fcb3d31cab9e34f60115f5be00a5fa74fcdb120cfe179703ba26691838145a2c0b1043d0296d27e88f173f3160cfd1fb21cad26e39ad6dede6aa15b40cce45443a1d9b1de22b9e9c63ac9dbf4084e1204fc9cd654f68572705fa66eafb934e924f64682ccd4c65cc38cfdb956079dc39002ae8995c740352ddd5b84795b53a7262d231d2c309ad1888301920408173699be4eb061febb4351ca82398893cfeacbe55e41d7c2a7046846ec0b940bc6d1df129c92618fc7da7d8c7a4f5b100faaa52ab538d592e7d38f446fb005032356d8a445faa7d655efe6d6459d05480d88472df5ed85d3b34ff34ba6a59906ef7b7849802186ba3c50abe2f2995456da2803cd96d0d97478e640942a63e603e22f2e89274c79e8fb3f5bbdcf3c91426510988730ac9637ffffb660ea1cb70e3c95c6d927be58f5d32e8c7340d47b55ff103f474d9dbe55d405401543e0f609b458d2e0dc06f9b0962ead5b5bc088e9ae3884bf803470993f761630cbb80108a70b30678e11e349bcd4d5b5a80ba85e80162dd08470eb7faba473c3f4605d0c92cedeea55f423c1cccb7c0a9a2479671b96c9ea1a3329c1df5a71b9011a3a0941c3b646395255e0e65ad84ab2de4a8e04c54995dba0a8c36bcc4d56971e350b71d7baed141a9ee90672ab3eccd024095a354915bd6a3e8e6aaba2194ecb8202c3b328b8fbc2b8587b75d0ddae8edc5b9129f883e1ed4210358a99b74fd72205065f05f72ec6f988ca2a5d713761c56b85f808d36638bab082c7e670f578b50f60cc3cba90bfbd2868ff15909e92da705f38a6e4ba0b0cc904a4815930232600e9cb9de5031f79dfb98ef497742d176b5d431e98bc992779bd97ad4bdae26e0f592483bd5d4b550eeefd8a1567c9e349159adcd3c41adbac9c55ba8ce494c10569410b9aea3b33dd25b887d26a618e5f3bd323672a56f4cbcff3ae8889e7ce0aa2b86431718210ef6a49cc5083fbfa5ee538ff6b95fe4dd7cc6d565228f8bc0f9e3ab33a4bcdc3c49f8f15a8084b9526e874b71989ec8be22245e65944588c016cc701f511e4c5445eb7e40dae1011769be29ab8cc5a3a67cbbdc60e35f48c06ee90b79a7d05059137d32fc78ea7e7d302c616a5bd1d88fda2a6ae963f7a5f02cd71f007a49718f0afc04f7b0edde7c517cefd623b89bd6b5644d4afe353ff0be7ef516ff029ad53713ff564b808388cbad04d200f396d69ddc9f152856d930fb36ffcd1919822df876c3a43c9e867f69efd77b5698cd7af8d63d1ea7a5b0d030f6fd54945de51a6a99aacf4c1be292bb858fb44c2e018f62f66d78fbb5a5a0ffc518e75614cd6f291128b5dc97a539ffe273a3579bf7e5515a325ea42e5b20f5f8bf74e1cec27f4fc3236560949fc57577978c2f06284e4dc5bf61b501e650f09a314026731c54b61d84adf4d9be32e88ffbeffd4f094df5c5f0068d13fd40c35ba9e69a21063aed2846db36ba7b0c6653c1771f53710927bf5b58faf7fa103ab86d54d4d8b58fd7271845a874ac1cbfeee7bfcf0b3e69c466d80dedc808c0d8d704b4a52025b34668b8bfd8d50f00eb2b4229f7c4a4c6a03d36771b093170f1a5ef4371a62115c4738ed0475f022b26564a53f4fe400828c73b632922d9409e44ce61e1f42eb35de0279c8f2cce7576937a66ebf13c317ab8d1e16497bb50e8cf4a3ac4f69616aaf24bc2a788032fc98a81e31eac6a15e7d51a1c356e9fc06953254e68fd218334d1425d4428a417f5a787d848f95df4fab09b3a46abca60db13ed3720b4ead6923126bd5d801fec0ce795ce4f2e7d65cfe67045f1aadf20e713db4ace52a22c88d526dd37bbdb2debeebee5cf8a526bcb6307812d6da5105f8f5271fb36bb1aa9ecad5639d5d1890125a34025bec5fd3d3d347defad9050ba5d4cd28c1b83afafc7383601a631efc3d3e7b8d9324d9ef2e482af55b4d00005e2f48dfad0757d0ea6868f66fee9c06a75f8097c417bd52b5f3fb8688d55b0142128c7814c5770e39e0808fc5e683953a2c4de55d481802e53cb005c16374036821eb2b0ad3cccfe05880b051e6ef461ed4c99a155152dd5e4d2976837575024572406d50d62bf88713cd45406e59b96fcbb227f41b9e1d738300a9ab504b02745dc8be0d830b453eb453dfc1351396ae66e50f65468cc40e93d58b5be92805a11c74feff56deba891431fe7e9e07f585a266c506fd79c8f7f6011375a5220991a3967e449e92a90b1d8c823170401d49e721e433af0a58d7e46d3cc534880fb8757cc001a8870309ae882f765d248f7df51d9ee0d0f0e3338d01c20fdaf4007c83cbe4188f767a8118e855a805b386ab766529b86f7abc3bb216412b94d60bca2d0be6bedb4a38627cab5c3b23576be308c2d6c261588e4f2f97907a472c028345c9fa3e9994cb617cbf788faf4c60efe7b4d97f9a88635d99b1e9874ae4017eaaf6bb0e0a508a7012a4aaff74f55fb306af3c06ba731f53f5e3496c40810f93afd0a700d9635c74afdfcf71d3256ecedcfb42752d2409a43d8c2fb1462c0f920e94edc3e3fe99994a5f81cdcba5cd20216d6898e76de5d92d708a8756bf0e93737aa75140672b92cb03cd32b276101f3f11fbf4a99f643ffd111f7269e409d9d3410d720b7781d23815d4cff5567b6d4e46228465888386e462f0a00b4308f55cc7c7ce54342b6cbd055d91d1a8f4e9439d34365feb193873ac8dc89154083081c38859913fb9061b781a877c7edf186ea6b0f2d2e52d8580e908b39c8b0621fe0ddd6977d109f9e7358485f9f9a52c3809611c646e518ad1bb8ac253db0253a673802ba860474747927f8aa745c74a4f952073f58dc44d89a0153dce4f0f9fef063d2da49d4c2fdefc611fd41c286e3adebc3c10a6638e2d1417015dae0257dedc7b75644fef8954191eed5fcb84b2609cdd906d0e819a3fc1ce5041d20e360435c0f0f4030b2928eb9cb1bc466e9b180c2c5c496b6c738df0d3060bb10ed00cf5a74fd092bf8eaf5405f8b6dab8e769247a172293b4c031c062506bba0e3aa9ba72e1711c53ffb12e91ee280e357ee4d8f3cf7cbe521b804c7024903b0dd84f7a2c7b35c4d40ccbf07265b043fcbe60c5575af5febe457d1b03e0317d004c6b19add44caadf00f38c32f4fafee7e79ce7e1d88ac7df1ca9222e0975d70d36b8e303755f8281563cd489395db91ff6e79ad496088aed0f69e3a75a24350e775c1a72650811879c928071a4be511c3b037fe11217f80bef3a134c658b84002880261e04996a0ae38048ab94f55e7cfd2b8b626f0e974064603f9de1cfa10bb16e4d30c7ebed0467cc763f9a11bc5c365b95e32afe92ee602f1bd087ec8f0779cdd310ea136433fdaaef52c8b1790aab02901cfdb877f23aa9d550c031bf0cdef09414654a92a941f7b2d508075d5786e075f73ccbc3575262af3bccb0140fcefa6ae93f5a7f5fa29874fa7db6dd9cf7491021fe0d0d44f7d2ef908af2fa0b017f313b514f949751a675513883c675c3906750901ae6b6c8b606519b33b60367172af2f0b766b1265e316d48a29c5de48efecc9ecc0e6133cf71eade4e2e00425999bb393e414d361f2eca1f78ccaeb595a90ad0f54736dd52f33428eba701cde108345e261414b0894a2dde8e608749dad05b53ac95a9971e9b1558d365054ec6b2c2bc3c0f19e626d7b28a1827972565c4a27528ffa288a5ea2475115e0b42cfce09fce1c3f9c3af277a5178e1ec17056ef7503d61d3eb6eb8a7ab30430d0a38f3b6cbe966b85b0b15528393406ccf15276e9dcbc0ca6f064aa46f20560851569d165736fcdb0e2e132ea336e01e4cf4c601ea6e8e87dc3fe2317c461105f05d8f942bb6a985cc6683447ec6e24d7f19dd2d1602eb0935e4ede46c1b3a072208c9db676af426791d8a7cde51314ee458551b02f44e54960d55e4def9f406b01f278c3b6088ca6f1b0e941d673c7dbc466546136e00537a9093d8fbd16f0feb755aac9bbde7fdd13d8c697149247150f8f6601c27b4f44653662a102b9201edeae8fdc3f7db4ac6e486b7647a496f1f3733163af928202e87fcc2bb6352036b47ad21fe16846877e873f082dedeb92698a418db3ba6f66468d9f7a9d9420266661dae496379488b67bff119c0bf8bf76c3e1c11b3e5ac4e28b77ed9f99c0f79232081f2e49cf483d098e55b4c4c0063e44f16ff7ee79ca87e0791f9966e057dc60dac78e8033b4c5112f7d1fc487663394d60725f485885961a5979a3ac0122204b36d47c0721e1e0f02cfa75c9dccb1d336fa120eeb10b4d4f4f68e5730e3f8bed25f378742697bc7b88a50469414d42973f02f49d16a2d83a7b9c998c0768ae277e57ec5cb2f9f8be5e9247bfc66be5e8187902d0d96571e2980ccf3c0768e52ad84d08fdbb6c8f48df91fb5d7a3cd7434f260a2a3c8d9b43c9a77ff909ce44c4edc26b5cc82ae22bca3e4231044a22b31e396b803fb2a03e9e3de05d0c75384c67725a0d962540169f348309d00a501d6d05f9f1e44acfebe40e21240087813f2649e03707797db2871da837d1d5f187179e8fcdb7bb1d7618dffb2605bfade539bfcc9c06c8167cddaca619fc400f0412b4db4ccf34cc51ccdb3d1505e0b96631a802f937e3aa2507afb006e5dd996880279e6c9b32a6d27454394b06ba8a4050e39371697b019a2dba3c494c579be7879071552ebd6f19a947663b05cd40ce1eeafb7c8d0a374735c4aaa6611c3abe4cd648219416eb2df625b4950adaf0b3891a8286dc9e732fd88da59f3a4510777da9bb8021c2e947520a716c05dc033297b8b210cbfa750e12489a3ec71bcf3a77aec537825a591d1c40a6e30bc471ccd02ce021a7b03fb5394d4dcc437ad55e6c88c9b7a441cb085da3583c058beb975d8b5544ac8f3c24a73010b3918cf3359425773f99e787c1060a0f3e099750919f5c779fa46882b9a2fc60bda1713ef87be883986e44e6e3f7efd8e60aa97970164451054f3a8c7b09100cd62d0c28de11d28a012866dc81beddc2e30a1a98c6eacfb7a6629e2027649268de17236194551e249b6a5864be33fde6ad068a832b22ce00ca7659a6e4497fead24f915eecdd73358dc87b2d10049afe46082289a6d84121a1e9f91048dd0c54949d9762e38775e71faaa3c1b433859266062b633f727cf2578d255f1e593650db51b64d4fa94aa63744978a6330290fd0025f2929ed346288aa5f405b3160ab1381ec6b16d1c7137187e9c603e14c89140bfb6402e8e72e90aeaa3f04a13d9109d81b19bc171a08b95658d2e4f83e9bab0c04863365dda1a0b560876a02cafb4ea5899a4346e54fdd6109e995a43cbbfc053cf7871d77ff40b8b5062b1b7b3742489fab3f4f8b14ef0f8372232e5a559c0d393293d9d70518b6b2cd4c9d969876c239ad55c349ec8976e9c03fd21c42c90f4bc9a240d5bfb043b3d68acb5a928ac67ca230ae94d8db2adbc989e62da305047663a834846650d7d7b143706bf8a03c247800806b5ebecbe81927f6459bdd0a50effd74f5d581692b6aff20a94e7046dab342a266a5c9259d8100cf9b4446046c6b4e747a1e2fdacd9e454f6059a35b4bc8ded4912f0001afc3e0be9882b702099343a596c45317c8944fee535abba364fd13910bda3a07781ee2f671ee0a01b531e3cd32413787e48785c887bc7ccc8aa85c18af5d4cbc8629dd3eb97806098789c054a723e5a0b7106d0a7ecc0755608c74f2423a701984009bbd30f625076beb2dc8b99e3d60701191992e125e635c0153403ef6437d6cafdd84070a610bc1ad231726f7aa0e608914509da1cd68f20f71d2cbb3d13bcb502dfeaa65fd081a837d233a2fb9809e8971baaa1466f189be405df4f402e26d0f28974547290857a6cc7879193e54f8ac2dbc42f3acb16e24f3b6fb8eae215a439b1bdf6e240723a1dcd6a8a1f088979fe7076481c6a3a54c1841c67abb4873613858a09f1a0e8129523d6cb0a1d2aef5a7f3b090390a12b4796ed1ceda834f9c4997750a3d00eba2f76a66ba699d20560ff27f855edb77152c8551c5bb90bac6461105801703687107edee576299ab5e468f230cd84309b5db5ca0818911d91c7fe988272a08c52ac5a291e45e6890a52849fdc5ef90dbc3d93b3c0ef67305712a56af8c2203e337eb974bba80feb7706799e77cb5e3738c9c424fc820277055274e24f5c4016f165ccdd3e46eca7e328164369bdc95c68600adaefe90cba45ef24465740508a2f8a712541d6fd3631d1ef1c96223d5d74210836256ad28fb247d110b4270034c404bb4248c5b0279a8d0ef775bdda7118925f25bf1622bd952bbce96522b047091e52481d2857532c2d30e0224c27b15c9c8a9532695a54680bd387c7f650d4f7d0af3912fc3ad0abfc81e4a505d728b8d2d9b1013002cc9f99bf5a969ac07c92c62cda3271262c731461cdf2d9d5da07081c6ddb6f4fc4b19c43ad0127a032389eeade1076c02c9d10cb2cbfac86b81a005fc89441a58613c2016b25cb30694c775d142c6923094462751cbf5a74367d11eead92bd18b3fe39e0ea2d63c0f9b7108c4641d977daaf015558a577bc700a6260a62d1fb6e13909d829ad54d0b7904ab823fb89816d93dd8c5985da32a7d91154a1222259ec29f8882fb1e850c5f1ab0e571da4661ea79ccd08cf91a43c3cf6b4841298760e89c4e8bbcb12a00cb9eab296e40c90404c8180efd65d1fa65ada931f3d9670977d4a4533d0875032d9744af2e148a05737bca54ef678dcecc8777a42c0fb5e9a519717f05bacf0761595651ffa03809c719163add0365451bf4e12dc9466ea51f80e8029f61af0b5c57abf94b1366fa3d686abeaf57f7d8d97f817e0986a4c97a59d5150bca3108271177fc026a66d9bd5961a2ad61bce9d1800c41e6ec76e5080d9d2472e7210d828a23a7a784bec681829377af5fcf6d232bacc453b50b13eae91b7d8283c4010212bc8b01b7ee7be48b32849d980c615343a50c367f0308fc1f954ff77cd00d97ec181c777c907e3dc5aaa61e581e037a66e6996266f2b14d48c108587ea007d3a118bd8e4fa7658f86d6a73468907d98c6c5c6b4148ad6aa1c082867df0b041b4ed7eb08ca6ba4b92f11b54c3c2a1d176c4d135d020338d125f659555ad706d50ca12df34eee61b990997a26fdf2df2f003226694097c431dd0f1e12f2110c1bcfa523c55dcf3ccc9b6d93bc6e1a99ab46d1bc57e239a11ed3f20f3ee72407bd6adf6b9e51af59ffa0a104b4b8ea8f171eeb4afe94280806c22b4f789fdc07beaee8aa6e515dc08268e0a8354ab4606269ff6435f6720ddbbcadee5720ee01fe0e6299167fd1b6da222b59ff7f375efa176f3de30e736b703e0975c191e604b8bca01e671dad21b36271e63e8c7203fcb83b61069c82190728537df4f8570bc8262feff976aa76967e86b8749e1dbe68ef63cae342f4f11ea9ea1d5d38210e +generate_ring_signature 62d9fdf998799ad5f0044a6a7c5bcbb9deaaf78ac678f0ca3750aee518456f70 e85e6d34b7a44c497b42634e4e8be3a56e714cf5c44792c29204903769a21091 16 21b726d56ecad082666ffe11fa61408df99af9e47500483421b47a34bcc410c0 314d10d957af2e4da98a98de73d201ce595460aa9f842237ccb0347e9493d3cf 9cbf055445a0e7121e267b3a73e7449e9eb5915b70922f47437dad8f4ec9417b fefea43cf649abf557a369c3f7a11d4812394d1def349ab23e7c2e44d019288a 48360109d5b6da985b6701f47397ecbdc59d97383be7e9b067b318acdd109ecc a97375453701cf393e2a8e95e5b6c2ce365c461eaa62cf1449633e850b5a889d 7ca32230254a075dd5d166b06603ed21cfc4f5215c94bf84ce9ccf3721c44df8 14beb62093b4712b058f10f8232884896e4e85d2ed8ffc1fc6e03b6e1080e2b1 a453729d18b0d90e519e241710b05547b2569dc07ed744dbe3a5c97942e3ca75 5c9896d9305a062aa12eee2bb9b6c8e3be3641528c6d19847081172694d3594c 574a15a29cb4e3c1b244fbb9e2bcaf0cc6c964d19047d3dd44efe0d5bb5ea1ce 0980b5584b6a796bcd0d1e87ecf3be9f1615413e3f1ea237bcaa17108c11a5c8 653a3daca423c001f6f69ecc804ed50a82d0d95cdbdb35c7483fdaeca547d807 18f5a832f606874954b4316e40f69c9df460e505c0a7506f0d42af45c58b483c cee4f248d50d0302575d03de3e792cc5ca9a2cdf58abe5b47be7e1e4a801771a d63afdc5a0cfc9a531b4f099fe8b74b2f9c758c39c1cfa3fda7def01abb4e422 7c23e8fc27aeb5d238494829871baa490fabe516081fa922f3a4161ed0e7c502 10 f49c88ea1e4608925a207fc998700851a1ad3b50909c5cb1c5ccd2988ef6f7044e9e9c8713df6823ab7607ede709000305930dab1f297793f54ac2ab4b8397003b48e6ee50adf19e27d928d63c0792fa2362e3e278115bdc0a528676af00820a6d39e813ed3898c4b0c52fcd5bd91a0ad9b3606cdacf9635080348fa074b6d0dd9d1cc3fe3b0c4d606739d490986fa3b20e6e17ebc208f3a2136de78b9bec308b74148b7ddaf59d650ff0906fcea41d7c04ccf60834612867a24bc4b7c3013036d3d501b933c9aa8bfc4fd92db6ea8982d10011c7b48cf8d463466264ff2c904cd04cf8a2a684eb6358636883cb47b7a17e5202bfdae039f29fc5157cbebcc0d24d47c1d64213fa64a17d69b25dfeb926a7a30a5ba4a69c3dc0d86226cd4e400cf06fb56af9342d892d9c60c395b7e2359fe40a16006af791fc8d8f1d4ae7205d63f6e5f2589c30bf87a12d86ce777428eb0be137ef96b46df6a545726983904a78a62aa9a53e10f685fbd8a72c77dcb99b5db596adfeafb86a66d2ab48cb908ac2419dd4bdb9743a56effda54f9d202763cd4bccbf974600ba9774b410c0c01e60f890b8d5cd85fbd72deb9dce592dd0f629ee6d47e22ebfd65188a59147e0a5138ae8abf6962dc5a617e9a8ff173f51098ba5052d2416accf7625d5d94df029c38119eeb6f19efa18debcfc986ee9b8d4e01d5a6d68d953594f3bfc4cdf30bfdb5964d7265a52b3937fa49d6b6d971b6fa93389c0ca677180211a0301c190272b833b16d18bd9ea3bfcc675a65170ae6fb487bc1be44f2547a0422867bb20e295d27df2e8658b30de1ce16d8949ddd3b27d04251411fca62e2b52230d3e408444729a1ba2e421c4145865d8b99f9b873694453d629233cea095c4c2e1f100dbddca3c638e4efe324eeb69f9c133b2db7a4ab3a05201692c0c32aa595bd5c0a84e0e7134a4c65b946b442c8ad551382c7d5a81b4cf3d924a2c6f97ca7f77b0511b4989d7c5201be8db3dee9631f94c41629867759e8ec2bb67af7b2a8b1000360b7b0750e6ce880ddf12d50738651c02d08b5fae1e78ea4618d39ec4ec97f06be1d7eeffcb6d87e9a219dde2e3a9f5ea4811ef5e02baf4cc69f43dddfc2240a4a51ff4671d4826d2a3f592d3795e0d49ccdd1e19b30e44343f635544d70e60996b705f44208da03bc4c1339692ca62a3dabf16c054ac323295653c496976f0f5ab184356778cc98b32816756e0dcc4a3e9b0ad18cbef30aa93d27c242c601084a22d0c9d061c25350ef592e209b03a5f4edad466d45166d54a7fb02294d6a0fbf70279b0149927673d629cff01f95669d7c66a3e52b39b62433f2f81fcad00045fd498037b5fc8da56ded0216a66d8cbfcddf2adf0baa6ad45913fb8c6b0b009ec2ebdb6bbdbc704e634288ed6f644e9eedd23c9afc74fe20037a27016fdb05 +generate_ring_signature 10f3730c2f6a2514d89bc556346e2a37fc87d7e83757248623edeb9fab8ac049 0add4f035c3579eea25efb66d55d73cc4df230ee3a749cb5ec8ed434d913e41a 1 8c906227edaf3c2236ca3f0e9b6aaf208bcf39ff871919427a7719ff092d26f5 1fd2d19d0945cd70b8a3104d3f0a7548a9acc311648967d48ba83203f213a50f 0 1ac82f142f35bcd80feca8aa2a31daaa4a774d68ad7370407282fc017cb2180287d83d815aa8919177e2453f31aee5908891342fba2e41ed289fe7ad8316170e +generate_ring_signature f4555c7a94cab7fa9604d4c106969a84ad66a469599db08ba49bc24b1e1488bb d97745abc00bb8228a40b47a0344c9556d8dd15964fcf20f0fd82341d6f18670 171 cfc4bef5eaf34348f327005dc7f809d94e495153532aa7bd337e1230de4974da 79b0a445dd281c6c167dbc468a4946bc46d7ea55b1393895ff1e8008f2f53a3e 411bad6789b69ae4a955d7d5bee956a5b7c73ccd3481b6e331fffa049a45d625 c5e8959c5e9f915e5af54c1f77a81fe3cff041c001bf163243bf59c206b9b78f 401660dc495dcb63633517cdfb4c83f7c1bbc39b510caa85d77861bc3f221618 6ca7e36b209d1e1c5b20b78e26ca678325502c504c43e51fe2c9e12d2ef289e4 b295c552bd1495b7b21d99ae5bb7b8025e507a3042b6fbd81cc78f2ab2878927 1a10dd6423205ce8dee6302ca9a40f2257aacc9e954bb6fce5cf4a14889b00fe 4def6357385d6989e58e06f38a50fa51503aaf3b13c2bffa146d2824f93f2fe0 8efd4d3019835bec1143624705a46b9f54dd4f410ad23a75e39f868728585a6a 448e81181967b7c2f211960907184ccc9dc01effeaf2bf0ff3246cf715fa7841 e12006e490cd7037403ccb0cd61a54d6016103d8228ff5bc5b178a4be5b3d5a2 24c6dd871e6f6d1e466e1c2be9779ccf2567abe7533a6d0868b3497346d6f08c 4dc82719c9af722b68c9c9b7a6eff94600c7e6a08240307ec343762f9d24b142 f72f1ebd2e930a6f94e2b3487e3bdc9f8f82c78e8a890635c76455bd12d2620c 508410277ea62390fb737108acb07efd9b4afa8cc3f0492f1735381a6bdd85a8 f98a6c409991d99882a77806afee0f5a4f479f4840279447945b2873c992d257 32e736d6c58b4a36c91cf1b8d9719430db9182e15184a30797eee75dcd966b22 f6fdd93cdc90c61980ea7069933b6dbbd53075b5a0dfea2079a461b4b4ea6658 38cdf0a99c31eda7fc48ffd68989add1a6224503e269a5536701b11e4028708b b1aa00ffa31d1d3d7e645dc9ab2c9d724b3a699702c877e7ea610808dd2ea9f5 1a8f990377f923a024effcf088cc532ea6049d533d59563e398140dbfef2790f 635710a81651e374f11c728151a6b81f8904f4036f70cb3be54c4a1f394780f1 d4c8b7a93f5aa7b5029651f44bfb87ed4e762e9a166e37db35eed7ceded15017 5abde930e31af431a396c120cfb04ae6377f2f653214c76278b5e93ee91c7989 596acbd0cee6be1584cd61634edd8ed33f0fadd3918e8b3398ddee785be0d2e7 197c6902281fba43aa82e272c5cbeec79ba8b28dc0bbb1f1ddecff2c91cf0444 88176dadd11bb0920f9dcb0b53cd9bc720919e663588317d6d48c38fb4c6a795 c623bab71256ec174614b343d79a6b1c7c29f89a94ae9758f60cd5f2c01fc40f bbc6e9dd8b262f08d09935723bd9ceca95667d6000b64d6566985d8ceb02f5f0 e8d10be27173f52da0711d82d8a2ae34925fdec44dc232eacfd24932b2e459c0 05d9f54e15501e036c89fc60c8fdf9ce39a7520d0585e02e852f944a76cc47b4 bb548d6df5b6e342173a857f8378450dfd1c1526399648a05f81b7e72cc5676c 037311c8983b23d7ed1450a24706026c1930d7ead062b4c5806127061c96fa18 41d01eb664f28f27bd51f1959a06120d7eddfeeed185fc4b5b9c67593ca3f750 ee1fa901b60359598a0985f6642fac8604aa654e78f1f3d18a1fc4ecc87536cd 7d69624959350420a65aec671b481fa6ca9f3406e9080acafc5b6dc251e50a56 5315e45e258217f50b9bc1d79bc411aa350d3427080b3cdf5c97ac703861d519 a4ab5d6d62a398b29a4bb0ff983060158e2ed7a81488fb1271e380839d5ab8b5 05985546d407861f5c113c25061eb90876cb7b1d043a74af25c62b406b821337 bad614857399ac6ec7ed7887bd1e9e0fc0320b595233fa0c6797f8dce599ebda eebe0e178a0e1fe78e6233eb6d86d3bd701173831d7f40da0d64cbc572826cea b329aeb55ae0de7a468892cdb57aecde5268829aeb84bb88245111fb438dffa6 fdac8651768a15a0f8e502319d3cf2dc41fd737e975c2b4a428b42db1dcede27 88d3032b6384a94593f5c782e3e7bdb027414c3fd99d8730b2252a7ca744a3a7 1771480e847547152d3aa315218a1c2cfd01cd45ba95182a1b6447103ccceb38 37b27bdf4740b2a100f54f9a289cf58c2b66a4e4f1b13e577095403c46ecdf86 427e01a2c9473a771c6fa5e2dbeccb62d351e429e2947b2cf8c228bb10da4649 15762146795864be7e50a35b2f3155b05eaef4d1b01c61347db5f11d5baff073 69e02c54680cc7205966f38e4a27a37a4a7357026fc38b1b40bce7e7edd5d1ee ef15e86c3ef859f2c85cdf828cd425d4f4ab7aefc11f5a0f4a16daa2b5fd22b0 618cdf2644069de2e8275619d923ead50f93789a4ae2ee8b68b625cfb206b39c 50d292bb61966a8d4beb864d9c120170f1570bd63cf07b41332797b6c29f5c9e 0a34b827392ba1883b610d1422c11696cc281c8b6ae75e961c42be3a3671acca 14730187723cc634969ee839ecf45452304a07bca280f7dae82ab0edc0877c29 699a24951c6ad1649350086f99a1854c89bda4228cb4a472179987daf854cc10 09aeb8ef6645a359661d04a03b7b7ca72c17a0a31b88997264cb49a38b8d7c13 85b0ab6229bbfa7a3b5b7b23811785805f63909500c94fb51d89e8f0554e70bb 3b665ca09ac6eb886900c99aec8e95270ff3ea73c1d8654cafe3acfd40019003 cdadbf8b0087a497967578999992fdb5f6dfbca21531dc5430e41151e051ae56 0ac2710ec9c037dfc4c3f93c5191a14737c0349a2c0ad7f6a44796b7bab64ea0 ceb2bda229231c4d5dc7c031cf687e6bee4d94c75313fc3d662dc8a6925dde77 a530dd5485fb70af577f782c9bb1b3694f832fea5555309dc992c65950137c14 2f55b2ee169c1115ff9eb53e24e1a240b7759af68bf305667fedce45e3f0d619 69aeafa707c68a9aa05a273a1b3fc158a5fdc20e143523cb6362f6ca37f99c25 2e03f9603c7abff4fe2766d73c4a39fdef14d144b0019896ec3685684443f1cb ca18d53a70086097a653b294e2eb531efee7c58909c0a35c80202224e4dee356 aa7b68adc147c53ae015e29d898a72b94ef6b6661f3a54c88a03075c73fbcc81 70cd2e3c6c589814e7a3191ec0f20839bbb2849436b9108110d689abb9e0027a 7dc0f441b3f1c7b35cb5ea301dffdb55e8bfdbf0acad34bd01786107d43a847a 3f08b78c2866d0779ef8a6751b7814b6a509a091c99e96fd3734886a6d001ac5 11db0478b0e9a19dc38723770b1798e3addbf704cf8f5d2e2764d139f0d22a51 f961c491a8525f841bac81919a905dfbd249a7a60ee6257584dfe276ae7950f5 28565b59bedbe41949595332aeb2711fc67733117120b1822c2e9a327e977125 022098f9fa98ecdfcba9ed3a8bf49c72ccd8117cc14d21dfbd22db54deda7ba0 68f94489f7a92f0a9222e201d2b4bba8ad6daa41b4de2c57c7ce9b393dc9365f 34b9147b28a3ac76dbb13ecaeb3f6d6e722a4a8c7d0bfd8efcbeeb187b096a79 b9a3ddbedc533698050e8c4dd60e05919b70fc5d487df6d01b62858b05f48aa4 c214edc1e0d6f77f18a3beb648b37a547ad6f929f3bab96586ec3034d6f9fd8d d04804e17f6bbd4fc3248c049895d3911d3953ac98790ed97f7d038928be2946 08ff0bf8daf6b3b57164169c2b48ca64ada70baa106e164513ff2a5e00a29ce0 bfc8cefb5c9e90ac9e5a1d92e9b7529d813f8041e519fa527b224151af806e26 a07f1068e09111fb6b58ad945f1c7705afe8ffd16cbe5488bc8fb94b8d53caf0 a451ae9ea7500d137403e431646e4ffdf6292489608606042f1a0e373e062f7d 6fe4867afa167c2f14ef976eb6403af05c632057e0d0c5884a3b83052a9cf32d 2e2e29ff51678630871baf5f4b1c97d6474647749de46d887ff31916194cd43f 662a6698e43f9c15cbeb38c3a8f31fb131e1d9b476f0f3a0bf40ee0e8e6a11a2 8421394abfa917e685bec5736e2492f825e7b259b587d6e568929d4a05ae2a0c 442f5c4e472fe9a9ae50496e3ee4281a7945d55a585aa296873e28e2cae5fea9 d09852ea077348503bd7995157301f844afc568e86d3cd18f0b6d415643e3e20 268d7e0eb3a46a11012dabeaba1f7e3574d1e32074bf4a2feded65c12b97453b c122fc5e2fc268e3b10f328e4ec77edc375399c1100dd10acc894903da97b9cd 9f39d95d583cbd4cb2779e0820d40954218f009a7cc5df92e030ecd9329564c3 98e17aee11922bdb6a06e8d5b639097fe9127dbf79d12aa9a8adcab208b36a2e 43250a86c378ab45ea8f34e71a451cdcc8e0709574d40f77357ac3693db3d4b2 f33bf249022052081d7b5da52abccd5fec3330fa176306958c7e3d6291f52984 020c044368cad6dd0e1d4b563ff0d334233c6a875a652e551d0bf8855c9d772b d32198328b301c208a8ffc272e512f909012a07cc99488ca9bf08c8fd8940f83 0832c436f450191a0e0ae66be14f07ed5081fc53f66a0df1315d7358cb299d52 fd2d84f1afa4fbe177b4da82bf8f6a5b46406e4dcd6f308fc54c6eccd018d707 c650a776d5e5f98ca43507f46d2d28048a3e21a5196dbaba699ba1904ff2571a c87c053930f772f7cb317a3191c3c114fc323220d74216c28b9d1354c35a866e 7dc1e344d66e726db6bd8d296dee9d3f04ef75862bf5380e445ecd43b0932618 af34f348b06c894e95c02c6a16fd7e52da6b45663df93c6a2533141959729f7b f99155d1317e0a8014da9f95ef688226097cf59080edfb3cb1a7d8c40c236517 bcffc6582fb43aa29d9df01cfd043166191ae64ea184af279d3c4cec05e46572 dd56ac7d1111f96f932fc79f3b9a33bbe5ab7c2dfac8d3c082c1d07c31147ba1 af799d2346c63aa6e1aff8bcd560b70bf99b3a84780a2186b018f87cdc7becb8 a613368b100cc5a85c4955ad5bc04e5f8d95fafbcd62908e699b984210e548a7 f6db5e3e8cf9f271b129038c706e1a335baed4cb85a23934722e22ed7aad4814 f94f6840a410db8d7809f6f9b6e4898bebe6ee6c792f046cf08a0e192f0af4f6 cb6060273be798eb8e209509a44301993613f4fd5b56b4535c515fa55b4d746a ed1c8d689f250b24e66c8153558ba88317c26cc02ddd3fcc6c9c59cca038dcf8 68d13f2e581dcaa275f2523c351febf927fb6c93e65ca9a293ad6e812b413663 46f723ca4398207c1531aab36297a3f437f1a26458eaa3b7cae6dede9fe8bf91 d74bd9c293e3022a7f7a2a5cb8c22f6da99c4dfac585bc91d4a54428af645a8f 30eb33b7a3cfcb4ce2bb552ff92711152b2b114b9a3dd027a7367b8e8426d5b5 f61968957b10bd9c877b50c5f7c8beb6791800f1f3bbe9b78648d3fa0faeccb8 04e2acbd42014dcb32cc1e7690cf83bc017378fcd3b391ebebc56efb6b515ac7 bbd85c1e26423b3c6c68739a82bb5bb1bb045b8e154ea69faec0c4e55400b79d 87e234d1e02dc9a3cd8167b7fc36b72b2cc9a510dfc160b87e4c3f08046e504c ef996edd8c19019436b04acd173b66a4a881ddffefad2180c07abb7534021af3 2b75cedb11ccebc4875dfbf2f4b18ef82ed352924567cf9b8bedba2e79ac9b3c d012005892ad3bceeddb59a34f98d1717cb85daf2e9fdff671d38d29919c3306 5934b1dac37b15070667de83bfcbfb87386f93dadd3d90abe02115ee1be25511 8c8367ac396509cd1bdc3baf341cb8659e85e597c321cd8b07d8e349cffb27fd db8e1c01cbe556892ea60baabf545c1944bcaca8b03c22d4a1f5e9167b5749c2 26929b9a191e52549d227b3798974397b97d8127911f6945dcd52c3a915df871 bdf06c632061e00b667dff7405eb578912508ce8b1cda679ba90637a6ec9d755 adec4d15f5b6858c8c7fba49da88d68d4bf31cd5b92b34ff29ac5d7cde88cc98 d70026fa9b5753d42069c8def719a909d34d6cab3b1949b5398564bf6f408d70 ace300fd54f1eb3b6428c46feee6824f1ad1b7519c099800f8c90c92f4c52833 0d6a0b164b9b02a3877f8326ba35cce82e4eced1d21af4d2e80f86ca1d8b72ad 3e65edc9aa0612700e957251c766be20acdad8ecbcbac2a645e286c3c42889c1 c797cc975661a163376b9d0ac24abd415490f5c0e5f70f87c40cdbf7f0c76c29 40f0a14168aa61ba89b9e5c40a8548858efaae2990b1a102a6810cd4e14a4200 422dc367b19a024000e1f102653a2db986d13c1be3b0fd9a6d9882f6456cac0b e69f2c3a2328b8546bc48b72f489d782e4f669f0a95e759e2c58101b10fbbbb0 d0b9df63e05f270697be34988384816f750d2cc5f1b058637cc4e494bcb247d1 cf39c2a55ff7c176830e14298088e6482b864bdc9935a880e54000ba2eb0ce9c 47b5d892a0a98abe0646e21bf3acc9414e08e74d9d7ebc46b8c5127e5aecb478 df6c351cef6ffc4738adf60d0f7f995a651e93dfa38d18b5e8be83d6cf7ef6e7 9f765118726950e8cf8f2f6f6db2cae8e49556b0432fe6960fb31f4262acac57 9cf2fdb6049dfecd5cca8e4a5fd17364a89ad0ef7524a28f48aaf7b32309b4cf 13cfdc82e184d2626825ccd9f10915fd95ec8adf1f11dfca92f5fb5771f48a0e a3aa71ccdf007f88880835328b070265dcbec5b8b537af52774d99cad5aeee68 3cc2fa6550177b8354d2f5e241f8b721d2a5366c34494df2cab5ba99864cc23d f2ce0c858dc7639de0154418fdc0f5f36ad7237830b43a200eb1e5b8ed713345 08ed90cab1be91c643d1d9c620c3bf85f3cfe1173c7cadc37ad2dead9b5ad176 00ad99b49db1adf38784bd79bf313794e45de8dfbeadb26dd8a2d475b49a6b71 37f121e481a9282144254a27b07b031e44bf34a47e2ef1bcf7b9b8524db52050 e00d06925df9f5236e69fa2a78b78de859780ca4e8345d50efa819179759e483 a4f6188c99012e9f26fa24abbb7dc87a3057d1bb4b99f4f384e5decf9c17c36c b5a5e73fb99c679b4357da96990a6d19a881e12922f1466958a4daf9af573e88 4a52f4bd038ea6c046ac554f842f88a654a055e5e9bc18bd6172f78dd2c97cb8 8efa9ea083dc3fa22da94cd582a3fee99d6a51db50444b1aea61c4bccc2b6140 ce192be6d8d50cc467a4b520368ab399e880b3eb4d93b8a96bbec74070e7c155 f22f7b08626b947b8d6017b846b258c75d55e1098d381bcfa7440d5ae51ff91d f11cea7db46c8bce9a69f5eef55f9a4131bcb465ea1153c9144fb698b1d936e5 b134a75ebcc9fa5b09567511151c8cc6cadb20af14e11c040f19519a6f613102 59b74ee6ed5cd8ac35f7dcd3b5b3497d391a3cfcbd21afa40a72713cd45b23f1 7f31beff2c2c80200ba74222781dc3b00d1cb9c2a92d0a0deae2032b8b6ebe43 acf94b13dfb0480f64d8f24874daba01d93f09d2d29be66a48e076dcfda39980 d31da219eb8bd9b7ebb4d6723adad876c59e1cb458f66a11b8b1e494940ec782 0f493b671148ad3cc994506460ee02bf973068429f9f1073d2cb09096918a5c4 e7464582dac622f032f7964927c94b2d801f92464c59ee34d533b474e0c4c568 faf9274a260a3f80554a0e9b6015ead2b3c7e39d9d5041cd63f834c5af85f398 424919660a91ecbdf5dc035759894703844ee28939b9eb004ced281901dce148 08df61a2481c760147c0a65a188ebbb4c0a3394bbc7850117317032ba5f7a31a cb51316d6b4d9797ef4ae30b6ea1314aff7d91e1e8b0cdc3d56649b9037cb193 fb517591cd9ed330972170eb93c3563848becb59e905f421afe8fd8f37e5a1e2 9cd6bf970dd2da5899dc28da8446cad1bc6881cea822a9a20debf919b23ab20a 103 0d00051ac182fc638afadc3cd95edb75c80c38680d43307b7288461ab76f3909f9d8fe414fb7fb68fa84612fa4c266962469dbf8745f76bc0d2e0ba83b60b00ff78c9ef8be32f69036bfb0849ef9f32d742b3693d102905b43df77bbe5ab070e52df078746535674b4ee2589f79e819f85dda9dafa3b4101beeda425c283870a95767577553260ee68cdbfe364e63c0b3372847e00fb5bf3c817dc3ea7182009bbcfbbf9930323993a38df5030a9f258c7f41ab5b803eca4f1245c3ae5aa9903fbd7c374940a246715a20633310b85ef6812d96af1182c14a3f967332f599b0c8cfc0cb289f1b73b4ea0edc6b52a4acb24fa2e1bfb5c401d27d8e0b70ee1b80dc9698285867cbf7b1d1ad5bd23b3a1d135070e2fe8198b9c3eef7c3e1badc50c1ce39ea8251ef0dc91e53724b4e84e0183ef753df684c4b460754dacfc8b160b8f34c1c4bb1de364353e8efcccdfb26d4340a1a5bc5a238e75571eb96e43030b8358de0d88327d6f112cd6ce0f640a95b564ea7999888466638b0bda438b580e950c9b8fa38899f091783f5c0e686a1d306b0c764a78cc7c0a679e744d813e0238b4c0562c66affcd5fe659c27c8ca29f0c5759ae6115069575e924ce7843d02df8412079582e12e2be58019fc6f22456b6367c9c9216eca68d7bc392f08170fd0f67f9a142e98ef570dfbf4a7abf9d01ec40dcb7fe1594b4edcaabf04e27b08b239643e5d28923166119665407586cd44926bca5671710be5cf7bfc6173c30ae8a8d5ff90f8e78fe98fb2003a04a43a7d3ea311e808546edb2bd978ee349f0bf1cae6bdd5989a93a55878ff144836a56dc7325834b1f06f0d74a85ff138670770e0b67a92942ac86936dd20b1dfac9ad4dc1b2c5dc459805f6afd2b973d160ab0ecf481faf1bf274a6978f9dcb1acf32061005f8d38329ff1ccd828c107c50674c77fd7f4c784a81c6a6b4b31e22e7be4148bbfded3cfd478f8706acfbf8f0428b6b0c3c6645380a8e6044bba8371c18d895572e17b204d8e54a6e687f9380236eac290d84acfd089ae8fa82c995b292950aea1c188a0fa35223e38d73085091a8c8862a6936b34a3723744e1da6f2fa41dcd912b14061b8de4b19e5b032309d0e99c5462575b3c7343b6a4aebac0ac2072ef31b9ea8bd47fc089e862b04e007fabb3f0cb4e6e1217fec843ab8f4507666aff47e882d4d367f14c17d0d2e90c7ed7048186db17dab048e1d9bbb9efc950382828ad6a5417f19f615aa500b101baee484c5c2ae6db821dd8954a31a9374093a8d61f93b5de70dd8a78d747080f9e3f9c55e5c094bbfeb3bb49ebeacfd00c9961801fee73ded65e132a60e8fd033a74f19de4ba291127b50303982034bda3ad174c95c72a019e6b4c6ad439bd071b4bf2b16c4e24cfa7b2f696815338b733c6b441390c0fa621f742d90e6cb90457ad1bdb020bb07a019992a750750dd35c9c14342ea53139eaffbcbe83dd840f01135546a59793bbf054327e3ef6849fb60386542f306be1d92ce0374387cc0155a0ecab065a16b7566ef9809009c4e02eab1bb11e65d56efc370d5707ebd301719bc91212305a3c1e15262fcab95565b2851a42a8efb02491fc0ae62f933a0890878f126acfbdc21181a05538446a8512bc94272ac18c21aa152ff0e1105f0ea96806de8ba2bc3bfd2e8e398c0d4b559f34805fda6e6d64cd9f35c5064c5e0872edb30bda7f405d4ce2c823e70656089e011783d77f1e95231185eeaeff210bad42992af578d07741e57b21981dd04121001f7290c5fd85bd96b1bbae2c5a031df82843f2b4a2b0535c38f415ec0e93cf9785c4e1ab9cb25ba793a2811d460ee6de6289ad56de3f8bb9cbe628ef301e1acbf394d1373461cc8318049ce86607f6ba953dadd15fb6dea6aabbfb119687ce8f5cd36f905d6d9059535efe8d7502c9384a0f5e4ef7645b36a5e516187b20192cbd1c6d3278142c2e829a9980a105e31324a47998c1d0c6885f2e7edbe71913ba6dd8b79e651566f402a2ecb6070b12b2c7e93b62384efd51a792edf02b63f0096994754e846c07a6dd804023680285f9654c0fe2f3cda3a9e52b8e9474a00b8e15f959cd151da93d1f11c40c540b918b68a189e5a4a102fce3731e12ec0dce5184d3544ea659ea5211caed66430616a965962cfeb1c38e31c3948809b1fd8c77082165afc8cc6da51893a3d4b901aac0afa2471ab5576f183514902f39d6779a9a54e3ba5816bef557ca0c35dd0273ba3797375490799ecab1f196edec4f6165e998f83d8e97362559fc8cb5bc0b040b940347b0990dc18bae453b2a705013f5d2a1b9725746ebbc5b409f508f06230ce0876b73f8b82a2d07e09a3ee8987f66516739c78b5335c163c55d257f0c5cf569d28acd154de447d970b9e3320b7022ffb2c8fe88460d9f81a03f62260e27c916bf72b86d8f07185e3f72216557c616d5251c7a8f4cfe45c349fceff305438c8e334ead6e2c5794529edbb9087b4a3ae57f68fd01d979da3d065e704c0e6a2780bbcf62f286bea2d8f78c7a63b967b629d00a16a5731cfd5cf1339f6702c61561248f1e4651d6914eb5db9228f1cff0f04c9a173e910ddf0607b3a4860393e3acae2a0eb728b335edbec7c6aceff8c8f1bf13aef20c589203eb786e0b03fca6e770f42a008d5a4d239957332f887ca4db45e082861aecf991bfc9bf060b11e036d9caa2ae07af619eb1f5ba082f0e20ec6f24279ce752ec7a6d75e6b301d21affd3b23ce9082fb68ae24ce9a04614c072371025c820b4014d530267dd069a8e81315d2117daa4f5b1156c6f5dce53978c7c999d739cb8c3bfc3e71084042baa78a8e6e8987357d9197fea662b9ea2e6b9f4bf986287d987d92e7315c00a827066c843697d7646186cd6e446efb1a1c36a259cad3f94a279ab044c12e50dd418b145fa43296d01baf33c3ed9ae9a402cea0ee2a4175937c8800496375c09bbe92756b2f40c0dfee7ea8cd0a318c209a76b00c0ae42b0787be71fb87e5800efa4ab8f1dd9850e7873de963a5ac14ef40348909255dcd3c90b18053f617a0b50f90298a404163a9c3bc1c041de2e3caecde9bcf4f75faa854a543e0dab060bfd1127c40f03b73526dc16f68522ebcb9fcac9bc1ee66d80cf95e5cc43b4730db44fefce108ca64be56ba53cff6077cb222703d9f28e4a7cab64a8097eb4ab08776b22eeb9e4b724cf731096c1961dacd1b42a0c966343c9805df4c9248dfa036605945617b3933d10997f1756bae444bfb8abf4a29778ef446198455ad53600b6a228a112866ec025e3768f6d5f88ee84184ee17275aca2880c2864f35ebe0e6b13f572d951c83a2988f97d6e702a81b789f566a4c8675ecc4fc9cd7906280d1f474dcd6b1a12a1ec7c5e09202e17453952518393443a60a3f500a29fad820237729e5a805314c114580684b4cf8b80fa2effbe48c43bbdb4d07d831a2412050acf1762ccf5e96d6a8db03dc05b21e3adcd498d0cd7bdbfb196e5ebf33ea6074890ae4330cfb01beec7751cec929ca36c53b46b92bdfff1a9c26907c9bde9089fd18dfd62c528b04ca7637e3c291a0e24ca9565c90ca6cdfce6a241ae68b709cfa503146b532d8b4c44c906d56df944624cd79f8880bdac10102d8d63b05d09dd363ae9fec9282cb42ad80e1fcb364f7582ae97654f232b17345b723880a9044183e534383995cfdba1e890eecb79fb62785c085c966b0a95226f526cb10a046e693fb62cd3a2c16acd4692ce06ab668a178f0af8f4f126878fc69863a89a094214f094d6c89d48f7b743bc9766706c7457e64e53b1e1020bb79e9b0c691406f2f62e0671f61ba2e18f2aabae91e692170b953ae2e177e73c638bcd726ade014272ced1232f9103f922f2dd663941eb9ddea9d13103b622a2f94309bc7e5a0085a172bf87bb0f6b9a9b9cf3d861577fe87570e459710dd0ccec0bbb0adc040f9bdf17fca8217cee35bdad24e41e4619ac237010f54c60686b252c2e4afab30ce89281b0f28e1afadb7af51fc2b61d51adf7432a6acca555c3575558e6f413032488720c172e0865a0eaa3cf8a11b7bf714d76c9eb068f4edfa3270df2139500281e570a4ddbf51d5e487bbb9962c1f6a8d552c4df717ee1ae3b3e4ceb05f00afe1eec5bcee035b1ff64b5e5508c162ce396daa938a952a29cbbc2968dba390ca0f5f97c23a2c9fc2d22ad49d1cf470d3426c5bdc5531b503c11576a9ac52c0cbdba208e30e2d2727a7fe893aa6b1df6e327c64123dac1a08ceeeaf860f04a064769c973e446e0b50b55693c0128ce7d42e3963115070cccb077a2eda5cc5e035ecc8bb77be23e6e15bbc040d6d2275af2e1a419cf6b3175aa0d914e0fdb6201d8e5642a492887bfb713b5a8c75d182ef883020b3ba0936a445685b46cbb74089c605f786e8226fd38f3c92ff91a55322639584ea423df71bb84d7aa87181e02424f4fefcdb1a546cb6bc78c9979e546fcc43bf2468a85a60e69603ac7aea30265b5abcaa22f9cf79e01f6f15cea4ea9fdc9e3c450a5d4f16d8f907325ac680ef926a619d8c4cc94e847305c1b20ab3069fafe02c798e0a79319a84080ba390cafce1ae8e8d098803eeb4fc6164e459660431bf74effe1af78319d94b1cea607bb4ab06c0bdfeb70f02beef2bd04be87eded76532aee885a4e24b23dba353601932d9de456be8ffbe9733c3a7745c8ead188e02cc5e8f98b8e1f7a2024a58004a5dcc790aee025bc3b4cb5f1072027c58f2f639cdfe2d1b8a6b58b7084d22c033320199435aed1e54ecd0f57f639e0216b93c8582a6754a00f7a89ce4f688f0e497b954a725b3a62b7561649e53e73671d61cb4e0318a905f08b4ffe002a5e02307015b2c3fa9e6da1625620a925d2ff3727296172466e9a345f8bd2122c82098be157bb4cd58e9edf0fde10e652ab93d05980762ccf6a3c7a4d6745a6dfe80f3f4d3f2a610ce844cea7887a7b14d9a105099b7e39140b90c17b3990c9401c094aa5c6e1e8c107dd1af7e2958e2715494265d81ca7e362cd9c6bd61ea538ad0c4ffa4d8d38245533454c9180d0eb9e34fd68f1c877540ba5b6c7d8fdc4cb2c02f5faef49567f8cfba896f7bcde64d7e90bdb27c1fb88b114f3ba0794ef40120686b79edceda4109f272c54b6f36bbdbd496ea8f32aea7c86f9a78113423e9708a0672b473b873b6c91327f77fff2af210885074571dab80b69467d639cca150453571082a4229478d23fab17558550efa02a0da8793d1d9f9a06c77ffdcf77091afd82034b8e46db301b248545cba23feb78ef3591853ed78b657c0e714c9c079d65ee2124bfe03f2230d2828d659a6d0424e1cff8d5780f8a3a3a7f59a41c03b493d0a6d22820f98b2c58d1ecee371b5d123dd3247ade42645162c9ba9ed109bf8db464ce6cfe11d9a8234ac3b34c97b16bc2325d0430f5cdab7e5a7d6a760385e186dd93e84e57b2ca645a2eef108d259e2f273f273632ac20e0152e04140b0f3ed6e69d6af352f1a06b49a83002256dcf99ea88a4a1ef175ccd96ce93820177fa68184d3e9cbda09d8b7a9027b0776460b61492951941715588c29bd01101fddc9a4e183b4fc33af3d2d43d33927987889f6bd545d3ddda6fda16262fa30a6c2649fa2cc30df112a0476fbfcc909c272989001b17fe1c184eabfa355a1e06e558656cbb731dabf8d483fb9c49ea74e49555d25a910c1fbddc301cf3c4ef09e1d7941fb5f2a5276040aea5e4ae54361101de06e3139e94e24eca95640cbd0dbfb8e289d335b3d1daad70b96710019d98aa7f74b61f7adc99993f20abd949093b03bc3ef2987b73425df926586b3e83a7230371653d60a9a5f7582bd6c0380aacf28742e3909997d16b7b528f25fa475c188aae67e51b152c2e245744578806c359ab4773595a8a2230b9979cc37267322892233db91a4b3b7c781a179c93004957ad257a75f44ee0988b6e787750abe90c3095be44aa35ece10cedf5472c0df33dabdbfe526a133d0b07798898babbcd3f09a3efed5c91f901cfb8adeb0b0274836bbaf074d7caa22163b722a1e65c8cd301b0e69a8eb232cc7107fa6da60e3886c480ddc25600f698b4b4ea246f22411cedb5a3ae4ffff9597fd9c027170f2f75f65b87979894bd9cf3a4461970a7afe77f105c120abdabdea1889fb8820d5b4cc2bb8011f12123f89ed074a19f89bd7e19e5730ca1d95ed5f4b1ff38b80eaffa55c2a2c05b76745a3cb58db2f0d6f0db013b4c457228786953e5a13bbe048d954b4728e6bdba9f8fab277e1a008b676cb36ccea12e45739c3e00ed031a02e8cff03b7ea8beb9035b98d2459a250b69fdc9785635b42d1db42b81231d820ea5eb39aa9c4767f6b43b7269597c6462c193760333d821da73e6935327fbac084528e307cda0bda9947fcd732ef3c54246e3ee3b394ab06608b87626bc97e30ed23632a6ced000af0c795a1c9b5722417f17ccfb58bd80b3c1a854a9326668099e433639b9b28552da5b1b832afa54c83859971db2887d94d33201e31b694509f7f4d23d772dec780b7148a28d958ac2b4afb248434b9ec5792ad0b04045130c473e8bf72eece12bfab252fb6187f88999472581c8d7ee5730faf7c161492005ac2345fbf684e1e755e88b23b8fe3d0dda4bed52da6837cdf637b2afb8e78105dfc2ce19c4021f908d5b5f42938f367dc6b7a8bc8781ef28dd9b80b0230e420fa925e61db3ab214b0358012d1ae09d7b8ecfd4c9c5b66f5533c4e657c7f5370ac6016a6c9ff46c9f1d29be4d14b77813f3764da1360f7a85ecbebdb6f2607f0524a000f731aaa124ab2bc9775582d91a8ec11b227fca7876bb2233e4fb8a1603154272974ea41da40244cdd3108e182bb1175acc9e245ecf0120c9e335fcbf06990b8655896a4d047f0f63ccdb30a9b99d76a62560fdf7a7c8730380f67823096e0b1d698367eb78832f5230e6688755a549498e971b8c3b335f57c9d3122a08124849cd8acf22e5b6193eb778f29e013ef6f20ce309bcdc4cde42450739020b7bea62f7e877d2d962341c7c04a9cb371c8920d8bcaf3b5b1577f357d4eeb30550d2a7b035b5bd3134026d84f6792524b66ad775da003e06c018b9e6e0622002eb6c77aced104b6a71c9fd2fd5e6dcff4997deb79436bdbcf5f243c9fa613d061f9f1c57de7ff728244ee73744722b3b1f8eff492814f3369b08e1b51c51590afbd8ea37cf8a23a8c4419fc39b64e049dd740523bd6b7690b32d8bdce0bf9f07c75050c4b2c509cb3e4e84643394c978d600c7ce1985805bf8d40839de3588070cd1d0ab303c185889ef8904d2affaa1f1aa42b071b6d48add35e27876939e0100f999941e5b8b32a22208f7a09d753c03bb4d7e5023ddd422ab3848728bca0d864bbca616d7b434f3bc10d86e069074bd618754a5d42b931abc861a45ff7f09f9c737c602e7787bfea644bd33d22ada14a7ed5cdbda889949ea3f2d6ec8ef013360324ef7a6764d7e4d41993d457873f40280327c990536adde132605d60e025f0fc8038c2c577a16b9f7868269a998f238abc1b1dcd86d91d15f9c6b0b63011ee69dd5191c43ebc5ea6b414226d1fff0fc98b5859fe31063c0fc7f15dd5605875a262a79986bd5371db23fd2f6fa7b2e033a28d8665e46fff39c1895ea8608cd0aa32ebe39e8b0eb8e96cf594419901c73de9b168756a3a49722d83c2d470e916b2aade568434d123bb37aa30211a9c972164efb900a152891c20768839f0d2afd2fabaeac299405a92d8941731d86f5aeb7149d140f17a6e950d92361ab0a1244341273ea65ded016704cff76d539a5560258ac11e612e3c2fb8dc2b23b0b2caf309e545b679cefa2200cb5ca63956b7c58e7e7ed79827fbac2cdb188d7030388cd2ccd1dfc41349bb5aa2356ec4c44adbf68bd29f06210717f6b6a854d0182278ccaccfe43b2aeb66d58ad9e4d9575f89b1929635cc7824c1210a377850c605c943293f9c15a890d384bf42f03ac233f2d92028b02900f8cafbdfb9d0a06a7f2784c0c2a3df0ed61e9c4c48d570bec77599f3fb3c4cd60d27c0b41f8b10e087e8c4a9119c724a918ebc5638be8c94a0d88151434af46320031bae18862018b5c0a5cea422ecccfa854d0c9ae4fa41ddc2cf5d1ee646c7ff652de27acd703ca5b9afbcbe46a9f046a3b4711b8dbd272b46b5b2e9860604a8a4ec7175caa0b9e791b3e35c72de0ee3aae342eb420ccf1e67a925ac619ba5a91f9837ac82d06ea9f783db129eee6e93d51f679dbd6e90c39510b6e390c4b764c218df059330dec562368f8e82c244fa6c727ecaf42cbbbb26e3e677af63c80622ed55352710b538273db07c6fb56c99f429c7a1af2913a4ffdb2f52db11f8aa6878c6c5b2b0b1df9555977dbf4ff5fa5c4f5da52e2b44415f541a1395cc880878af1f72bea0e4603069ca1eaaec9792b0e1bdb87d12b8e5136b08143072c6eaf12a0120181085ea01c5864525b04f2face202dd1dc4f4cdeeeaae228a37e6e93dd62fcc8e507ff8361c115df826824707075c8ce3863a5ed56bca381b16a29d3ef839d4d8c0588a634fb9f19698bde67c2f85960b546196b2d503f941561af764750f2ccbd0f964f1aba91908bc5383a86e42b1d12a626767ae2266a7d51abebd85e71adc90a5eacb3cb318b4cf9841c622a66267e4f849c1da7c1918f34b30b981051925c0c303cbd855169d8e3929bf41ceba6ac9083a0e4497eca9f90d858324dcbe1cc0197e01e96953944ec5eae98109276c148dbd8454b843b3ccea46930324053a80f382faf1f50a9a2cbdd9c9fc5eaa9c4dc2b9ef491aa510478d9792c72bc805d0653fa7ce8847905357dced42de31f37569666981abd8ad79fd134817609cad30838cae4119e243621403f3ad0e648f8c554e70c50a573a9b12de6d063a0ea710c6b7295caecc2467b14e6c23d119cdd6a683988e27a427d641097d9b3289b60082c07a17d3d2ce85e2d81a51e6fb6e72564c2d83b3fdd8e13858303f211f82202a25825d8f5df3bf90b4c44476cb27b5afbc2e1332fa5d5407280d268e6d745018b48606119d478b0a6c17211004a141a9d260d762340eda14d37db218fd5e00e9379b467e3d48fc6362f66b7f96d30f0c9f54a56c7bdc925fc19a0305b30420f1abb7c6cd5b70b2f6aa4f7c93e3db7475e7eaa85fd89d35ac303089d4076b5068e60b1df9495bfa5189ce85e9e488cd50dfd8396563710225c182f167d882d08479cb30929b8f8483976a25c39308e4aad44202c71891f0293b6e6cce8b7810f96e54e952b82a733c3dedde9eabf3170e5f2522a4b43dd0654251b8428bae0074e836ff3e3005fb1a1c82233e00be804fd53803bd7759d2d2b805135a0f17f08f5d88eb9a6a07da23ca431e20c5735a6a125e056e645c23aa7d9f98fc64e9a027102f05de3cbcf931ebf190edd0faadac44aad21fb6460121557ee79ad3e9603392dee0d10ea6add93eaf2a61730f0c23697156b41b172197c811186efa0c60cf2792c23c8669dfc57b631f4c255312c01c5581333abb0050509503ad762e00690c6f7b793994e837934fa5a570073fd26fe4461e57387ccec4828ecae56500671adc03ed8ccc6965ca95d5fadeaf27ac9b16c877eeca9e4cd0151c3d279420c70b55f6dd6717129d8cad62d1accbb33b5008676d153a755db1ac8a13ec3d7029351c1a17c4eb10d2f675677233af56bd5330b76b4ab3da25ef737fe3f79e1011d8dbb369786c10854a06dff14982cacbb665c6cc959f073d4794ede912e1d0537dea0239cf59cf01c02a85686812dc24af2a1c526bf2e82918e92b3b6f6a00c024775c6fec3893dba077e51269e15ec47b961819f925726e0d18f8d528b7800b0093e7418641f60c58213f6005f7656afbf0070c794fa8cbebbc411a8b9700f060e12667176ed4dbd6646412034c7751d42ca838db3c567a75303c5d275df054956937bed403331db088a89c148ac06fafe19ef37615a3de03fd3271db2b508166f1f1c8ed6124529297535a7c469eb27dbd934465f02b563205c553c442600f7046e75ff841607086eee7cc70d93ba74ab011909e678bb6b45ae91ddb0670ebf3289cccbeb98df119488e228cd0f9d7c1a0be9010075faf4d9e2ea0b72e90d7d6ed0fd8e8e369992465f83c04a49609656e41afb7478140ed58966bf365401007d466c688664c9fa2061ed008f4a3614b9f651ef631b429d660488b0b30e033002a699da2408dbb877ad5b1d8e0a7a651df2996d9d41b10e0234c78169e009f3ede121b2c80b7832496679fc1219a7cdb048ab06be00839eb740cf7164110c11e1ef1b2aa204e8064272ce4c142744a20e93595bdb9d0964577244ce79bd0addfddd902f85eb5ee839809647cb34e13a0f01c3cc1a2dfbd7ec8ea477e02409e44617e6fe7981c882919114241212aab2013754b7b66656e892d63cb3be82096c421f809ce17560595af57e4578345602d0c448b40d32c6192a05a8dc377309f6c03c86334397306f231c3b63e3ef152b06f6bd2553ef10fd02e89d9c0e0a014489afdc53cd7445d3ff3ae1babefaeb5c580b9cefd1fe27322848854756d5070f831a406ee809cca27bb1ce73027879a639abe6433489845c8d8060c8af0a01f2b9f04025daf6cdbc4639cc9a20031148d73ca3640c2b96d7cfff9044320b07446fe1af874ff741fb7a626c9a87bd99b4964c1f52e2876c6756f78ab8172704d0afdfc4d93531c9ff839b120346cd31352c31e4d1ed6b4e41f4d59a1bc3450cb0e6ca3c711e3efc8bf73065f8ad6566b9d4d7ec6e8dc1a74733ef5d5a7eb20b73a11159b4552d6149a5cef62161f389893d9bee70792c1dc4328166aec37c0f24bf63a1a1cf456576aebb89f405fa1d5e96e3d3fe44c07dfbd583ec4fd6c40ed080485d844f35be2b856bfc9d9c444beb68c3243180da045afadf292d41250f01a0ee65f73131fd931184dd272b957f6d01c7f1fab57539cdbac06bef0a1d0afead4e2f8b46d2e3183fb001ea2467889e20c5f666e2f5d47589eb6518dece031b0db48e33e87a21d6d258bdcd24d9dd353226563948c40208656f889852910a07002b8bbb7bde2093466d5700f124fd6d9ca7f8d00acad20356b10439fd410e9e050614364268d392d975da9d837fe281e4b78d81a0a56cff2c30dc844ed40254d3c73aa2d51437e276c56d6497583bf42c6ffc7a8596428a49f5743976450b2e3b4823f670d038e2ae12db8c650ba4ec7962192f479b859956bd952168a808159691b912f197fb98217426a8b6b5385d93d6627ddd6be0c3df6aa944bff10fa32f7c60444f6bcc460417acbbff9adef5280360e32f61c35efaaca7f36a0401b50ae6673e0646ce64f527876024381a2a096d3b3d2d3d739dfea7afd6940604c27db89c4af12437451ef23cf034ac05944617a19234b9107eb65bdf54d7c702e2b88a4ab3fc44c7b0d797e70bbcd73205c20a0d982c3e04c8b2d65ef2e8f2045192b64f637d296e789ba72d4bdd13ef6621a97eb692030daf6fe37b4191340883761b28ac501f2196173af058be041bf42ed2dccbe507005edefdef1db7000ee6a70f3751b08a66a30f8fa6e1676636a33e2776e7d3281760013d1fd4e1980df6ab95dd154908254b248efaea1e63d279b465319e5f9312133da9f157496500b2ec32ade20caef68905719e9d186b613228a69bcb7028ec04ae818c2d601408ff5c4f1c88461d1a03392dc1c7103ea33e25976ed50fc2d1d0df87337bc95d0d4b8372735aa002bb94838436b278979bd3e37d46e7e98b31e8b2eb00dfaa080f47061c6e5275960c9a1b27b54e6fc391ada47d3b86c5a1d03eccd8084a136b0eec50ee903679978e29693964d5ce1c6142bf60dede0129917898c2b5cc811b01ed4f06b713bb059de3a4ce2c563cfe76218d7fab39d39eff5fc224ca43d5e703c0c2a17e22738baca1cf014df191de8eab17680d8971b7c3f8ef79245dd66f072ae39c4d1f2688267a053c604a5b761a30a904fc4526af5274b25cce9b206d06cc840f5ff52531a81bcd786762117cc0bf3f8d32b79d602747f02b8834a6e809f5bdc841e92e7ea9106852a785d0e8b4b06a953d44117854efa30a18b3600000f51a8b106bba84b3da14393c9016b8fb1d2c2b14f8e9056a183de02b4963130948e5228ae038d24ee2804995fa2269a447e56de83b42e24589d11a4b191f0205174e7610a308d8d7935912ab83c63e6047055a590b374767f6dd59bb210dca0e33dd7f8738946f59c2a33436c51f71558354b51fe9ff0e4ba465fc2b71e9790172478ce72ddb2779aa3fdc7b6a650b0fb0b515342b4a553c2ac8a717a526c40873a2c912ff23ef5f4c3a3318f51a369ce989c167688fa2ad999744bbf28b730780af0836b2e88138165511bd17f1e77465e9785d7f4cb814e683396e20da37040ce5e77b5ff607fa38e769d448450bd30adcb397d6771ad0c20b0e9cc4ac29063499d2bd323094aa3ee406184c6fddeac2469ba61095483f61be306003a6dc0a41e0a1b14d6b65ad9c2477a884062dafb551e42464928898606d702858fee8027cc101e683e444645f62c4509d6cffe43c9cf259850b2bc02b6b9be3b92de409d4ddda3755e8fdb0ddec68267876166a6613c64320a992f020606c87ec88a20e295338805b407327e8e2b0ab7d40869257b2675f1d8937cd486746aa431de20c7185be7e083eeb8a6283929cbb52a7b0b53c21f5f706d1c36f93cbe4d3975908425b7869a85374e0895d226099e3907405cd1858ffff3b5e0857d488b2a7b40a4fd5f14a480fad18d1efbdf2aa0ccd269083577debf4b1eb73a76c93f517440abdd1e3935edc2fc5143e73a908c8ee75e5c78b1c6b4a38db93a81e4a0f9778050be6f9e19682af9b9da65ec9fa09807549bdf0d12b66b4e55fc82bfe0bc7320c3d5c4a82fb9384c7565cfb542712f6190ec3bbd89b5f0abdbee8c6d1bb065b09f5135f9f0246b5f42d664da17164b9cefa3ed421a45170ebd28b2856f6ac4b0c5dccbc052b3c4a406046f5dcabe0b0c444ecc48e61a2cc0a93ef022dc25ee5041f439cd52bf536e8d05e469e2ab59772a44f3b5597e23d7dbd36db4d616f6701887da077d80fb9c8c7eea8f21eb699dd4b7206fcdcc696c5cf947fa41794ed0fb88a914c9cd7ccc54a03faaae73dafc3ef44cd0cbe9334135a0c919cf7103c00ef004e7611dcd5444005e9770abfd4b9dd8b779b2152216f9351d7e7ae10ca0935f03a04d7f5a6433892200c2967f7cf95714b1d3ed7a855550d0891a5920c052607a40df1ceb2306f3c7afda563f481155738cc7eb0fd4a2e8e297d02b5f8095e72d4f7673ca79d84cef4c54d8232a948f01d2fa232ee25ca68cca823d5340c641acf44703e17db8f7d3c91ede3316e2374681f4a8ce817733c10e575415609761f1dbb03ad6d761f7e10201b8f067aee6d84c3b84de6d64d401c0a94348f05551b0d811205aee855c2d675fe4bc2f1991a80f8e39baa7ec1ca9e1b8a48c10c189004b1f52541c38f654436f971199cbf0fbc5548a39ae3d0058caf64eac501166bd366cc08fd9f12622683ff7de0d4c3acc33685b4a18b398bbc13f32aad0eb513b4944dd4b006adab78178f71ffa9e8d9d3217afe19283ca5fbb1d4383609078010b21954e09edb71a5ecbbd72d0603e6395ce25d2c066a97b94d6732280f9c5c807e912751bf5b36ba1dae4a3f725feccedb740e7d4a273da96934b3a7030b40d0a18fd3932b14fe482906af27924395f28763b4e068cf86ce8ecd20eb0207147da79d85c77281ba79ffc0876441ab14b5d23e13db04ae459e752a1a3b0b2c41fc23499f98a3aeb0d31c2e56300301363d932a8c48e6582ed07cac65e1063d9c66a028f873cfe96cf581fc4d0fbea94358fccbd87b29f21e25231cac19011a7a76a8b7cea34f5b2ecd278a86acf3e7658343fb93c354a5c7f0e141fa050c0f516dee7bea5c35b398524f3e49c8b0f078b35a79831d5c548e4a56f6f0dc0830ea88cdb22d257608c149574e7e39404bf0e75fbc2dd2dc72cab53d9c099c04621f903d7d7bb08531ab702f05fc8d984f122dbb6cb5237288252d84c3d56b01186481ea688728b45b91224e10fd2a3e68c798689916e27d270777b1926dd90df186c265427948c67bf1b46097ba9725a899d61b987ca70574e240962f02050032cf47b1b7589575edea7c1bd9e6a055c087a9109b358526480f6470a24be406c145337c0f2205b861920dda31f6bbd57f17bb7dc5091cd4473b5adb6aac590f7cb7e8e2a005f4b8a54252ef4fe3768568ce894b56174d685abf80fce209c20820b1c9a4776d04d9781fd3b49a4717ea8426f4d5ab8675790fa1d3537c41410e41f2b1e573691311a1e1ceceebca95155566a3d154865a03b429a2e2a579b70e95eead357d6178b5c2ed300feafe558f40de06079780f7028e7923b0279e0d0b2c2f2aa06c1bf9f2838b7d4b6e5da99daa9068029595d572248a9ccb7b58970751f3d506c6b8e8fe436b562a28656cff90b56df696b178eb56f102a63145720eebe88e2f471d7fbcb6b9f367d05b653ca0da921dc52654593b53d3b44fe2e50cb98a3154befedebe973f33f9ab36c8b79cf8d2645f6ff7aed1c739406549700ceea093c34a5a040e39740546cd9b36d43c0b4883154e74f5a2ace94ceee2610160d133137b6e00b8d075b7156033ed718c4d7375ac4cf35280726acd13d91503ffa7d46c887c2fc764b39a184496eba03113b49dcd57b5ad99032a0749736b0d3ecdf282068ed5efbd52a5ff5408f6a5a5ffef062886c8f1a7d67190faafb30d2219fd70594e2e4c371bbc77510f10de9c517ed66b313758afca036487ff18023696161642bf57f5a2aac821db1d5949810a0a1b722e0436deb2dc94a67c6001da71a2bee39a5441a9b90cf30f7f30e675375e422542bf6d217d7987432bcc03ccb5c143e3140dd0c1636e93801b1e7d7d361734c884145973f019760099df095c8b19af1c46e8cba8428492c46ff802b720a11b97f6d55f3157718ac1b47b0f7742ab6886c5ee0b5de548ea69b2a451b31d39d641bf451fddf5e98685d6a40258cff4c156a85e292b6f452df7cf4cc0946edf0e9268839e4175f2481665e2088abb68739d1b9f93c348298ec38ae8c4b325e2ab7c0469f4e91bde5b9aae06063cd23003e3b8f1d8da11730cc83eb8357f4d1312cfea06dc47240171e469e805cd472b8269b22ec99c1792594436fafd734b265b4338567d6054888727e9d708f297035ca0e4aa2a3f2bf5960d5012d01d0f7e934da0c25de43487aa42605d0cb9f5504205005030429ef943c5e4880189aa6d96b9e3641faf7d19a7dc6fcb067fd1b6182e38316e2d8351ca1ce92945b63541e51405b224fdb9f1e0b6c1670e +generate_ring_signature c4f2c0a39e10a7d2881c8753890aaac6ac136088a60bfdb67d9f4b17f5670464 8330fbc47f5ef2d5bcf3109e30396640363dab70a4760847e1ede29a99a660e2 112 e47318b68aa07faa35ef3ae5b8ac38acbb0fbaf3def0a4bcfff10395650c1eb3 0059e481fdff16f9b76cd2203d707be8ac31d48614585fccdc232a1e89841d2a b16f9868b930ad0f327f095f2f58eee17344ef219e5119c2a4d23078f3288af2 d375e7d98e7f286e38459c0a90a742c0e9db87f173609b3e088d6b0d1eb3a71b b8aeaad7d8293c44eba8932b8d7ebdc654d48ee3bb99a2ce9320b5356c363aca 016437d4ce1c2ec84d278ad1151e86005ba0757cdb110145110fa26b74038590 70bbd94b724d740a11d7d4a816c4c87f3eb7bcb2b17004c0ca11afd3671d6bf0 8346fdf809bce48d576e43e8005cbd6290633094eb508f7b1b9c2a8225a169b7 d66885f9ef8d956b5f7f65641651e31302075ce1b5865c5a241fe9eea9b29d22 8314224a7d53944a56d8ca1db88ce4f86a63b4663eefb779cf8153e2561fe761 bbaaa6e1e54ca7dbf72e37893f2154e027f4fa16175be97626efbbdc69586e6c 113bd03d75850ac055e90308da8b18f336ce2f7a33a88403dd26f5252506311a 652f8202dd69d0d86855a85f39f01eb961046f598588d8082ff4b4bea0501af0 24342da5fe22d17ca26d88f21357e5d375dea5e293ea81bd8ddcd5727213f196 392997ed25a6b43ff9f800a04131a81fdd28b839bbcf017337d407b145856907 abcae499ea45e168aa579ca1d7f5cde47450cf61bdb768b74f38684227be9a20 41793fa54c828bd0eb3a127ccbe27c4400055b2e7199ea5c918b88ee0d983314 c57bcceec6f61fb7de098dd8ee46f9d5cfc42cf864306601ab6dac9229efe5d4 2f9c53e941b12af7d6d1f49617aa8984be45080837d56c015ef28041d70bbb6e 16beac4e9d17d70a7eb517f110d8e7ab5cf60b4234f0064a884330e7af8f8264 fbdd6593adcbedb594273cdb4f71d628e6922f572ae7b94d560ad1ee543e17e8 3cc322f308c404283bc3a5476b262744a2d23402b4c8edd729b963a1417f08a6 1cd533cdf11e6c7078cce85de6290555fd75411a556c128a9962b7dd6f4d5c09 51ecac75cd208d0dd87edbafff96006fdcc82eaafc0a6a4084444802ad396758 1409b737766520c2d4789b6d59c26341c7aa1ed815f5674e794d9d0af5d83647 ff676950fa8d97c9c227cec21314b2970fd0e7fd688c64737a246eee1ce7167f ee4cef48d1ecb46fbceb2db3768f26d5d41424c5c7263e5df8dc206642445681 635b8c1a27a5ad357b46ed43f5911da74f20df7538ccab7afe574a4ec152b4c7 8f1ed5f84e8d913a43bf95b9f1566cfc3a067d30a28194f3fca347d2b937851e 1b97e52ae79c274e456980c2930f47174197392c8576111136cb6354d3f844a5 114069c991bde006821a4bf4d7981168046477d02fd97826d812d9f16f77907a b655863086ef74aa89ec9dbeb65bd766bc59e600f2fb91c06de972d813eb2ce0 a0f739a4e1b36c8cc807d771c84e081ea83a49ba98e194b0604d2d516665b778 58fb8b5f2a78e34edf2caec39b3f382d5c5af7e6efc6260e55d139a7371d25d3 821efd6c97ca6faa08c9b14624e4e143e52cde411d27c05cd1ad1c4b126f6e67 b20135c3919f7efc856e39bab403fb72d11970c31660a418b8aa67a427a0b303 fefdcd2c9f62d2788aed73c44a3632486974a7c146d5814229132b136e21e413 db6b3594fc8d6e4086aaac78f29e786d988d88818f175d2ffda41d5a472711c7 07b7567fb88ce0f9f467d8c42f1432224fff4629e4e46ab69026340c6b2a7e43 a1644980560aa39caf5deec4a899557be279f3d9503b973450f08c4dd6e82fae 74eb226428afdbcc7558ada5d79a5b6bfdcc9bb8338e75b750a27ccc083d919c b9239985dec6a42c08999efa4e7817fdab6b49301f04559daa1b80adf42b355e 10113e293205f5847c7c8d8f41083e82f3a525b5f56de04359706e5b473babe7 62156ff12c819c07a5b399c6a5694cf81b3cad3182d9c89fe9493399df4d7fcb 0d88e5842e2a1507642926ee6f947772799e27c4276e84a0a377f28e8787766d da17155ac68b93a53b3450cff5c3627b633b2b7464d3f0a74d9f47bc7a9b63fd 027b33143e2bc160670358bd4f206b7650ab3ca6120f163eaf7d52b1f6419ad0 38dcf4d9c7f711c8c3f333ecd93ec97e22abc07670a8c8658e6277d579923d7b e88323c9eaddcd13f3348bf85f5251f593f034ade1ac3b5309b0d542443a5e37 fa14c4f0c750ce4b52d4811caa95d3c9a7ad209966683cbf083e24d00e1765f8 838365eac90f707d698b76078f9ec1d896590f9adfeb5c0dc219d80b42929d63 e599e66bf44e7fccb2722f3a97df6fe782e80811e957a6d79108dd700d46deaf 63e1ac5f9583e1463db1c0dbea5f5780eea86c3863fb7f2f7144b094d52713c0 f30040af05b4f9d55c2cbe1de1c2be3d0a464a3c2a07590ca5248eaa76947ed8 f293f6c22c31534998d09fcc9f83c6711345ef9acb4799297af1a30ba50889e7 6adf66f4a7655d9e80dd691cbb6ba6b0c34ddf01e00bef4020f5fdd993bfa62e 7413a65c5acb2f77d01af852e1d17d05544d767f62761ec4bba98ebeab91db0a a604ccb842e25ad2739ada5513fa55c922e98a1cb47db75cd945fd1821a8a84b 760744f0d42cb0fbb23e3be8e04860eeff2c489c93e39cb7fd3e644313376de4 d3319b1bfc438b6c652aec300eaba43a8d1ecb0b10ce7b1456732042b0d6c219 f8a118056a6be318825229a5bbc9800b6002522e577ddef8382d272513672bad bc8b2c33bb713ed0d4cbd68d7c118e312fcad230965cb8086dcc60e0f725ce87 1d7bf114a3d4e60c584046097d308779be8ebfd81bc4cc2ed7434f700d0f877c ad197648d3c14b3a127c04a02b1bea5b8dc8e369096a3dd74c6eb1ffd9686449 6d70e6bd2eb0a115f51c5f4a1a5fcfb052340110b9db067916687ec8e5f581d0 5708259e096e2c0f23724fc835626eafbc11e98a8672e36360ab580e8abc23f8 64959a011b73de580cf315a0799bd7f4e24538dc149ffe9fa582fe16a1389a4b 987abdaa231434b344aaf7dbe32040701e1c7a5bd7cde69e92aa17800574d6b7 71e094387ec015e8bdd1684f778d544e0868a27a2cce16e3245863e279d36858 297bca83ea72ace5734a5b734743de740fe5d17f2d9a61afc28b5d3174a4d899 4b676cd079de1a9222bb783ea75c17ae3e16bc08b3618e4ff201a9fe849c042e e927115998105d74e0f76b3ce1c3a46b0fef5c68f6061949c3b3fe7f21a321c6 95438c8204ca32bd089293645bc0eafe8552fe14ec29a232fb1ad4fc619932af 5b8d7ffb49e11b950d8cafae7bc3319c9b399dae92de13a01ec7226a7821fa65 a1a64ad18b13235f8ac0c33eef61c152050f8ec646f4f92d7fc9848ad59ecdc0 d728a9547eb0391c9009cfc4ac05409c42fdf5609034354004f0fa4d5441878a 784d8afaad3bf0437067961f1ee47c71e609cada0b97c636aa87a4da8cd640da 9e562362de224ee6178006c3f3eaa0e211fa9c0b9e4a909659e7e0d2a28cdd48 b31b9f4a7e801c99f98d1b4523457a434d623afd8631163f7ee99e14a7b6870f 9164ca548303e3f8e0ff9614e064af82f8cedcec6fd76541210bdef127eb450c 82d00ea6aa39897b10534f681a739925d179e3c25f87d582982988ff8813d4c2 c3cc009f53709178261b9fd064f31bc3397e4652f37db77717cac41430f68b0b 3c6a52119f73f153c9b740b10e160e88a878a15a685c6e426494c1a190bf2ba8 787fd20038a29141633d628f1d9be6c78486db3256641d4c5bff7bc6ddf3787f 5f8f4faa52b8c26f56831f67bed9ceb8a3e98243b5d89944a0e21e78c523be86 ff57fef6e81f2c1d5ea0f39579e30a2330b7b30058d65cb5100f6fb91db481e4 6faad18ac496e6517c09c2ffb99ef74ee010f1a70016477aa92f04f1272cd725 8bf8561b844beb409a9603af71af4ffca292776452278995a2768f924069132f 0573f9fc57a663c0ff3b2cc35f4301465e2c5737ce086d2159adb28100a9d8b1 44273327e8d0447d0205ca23ea4991f0167f82a7dc7dc9a30040eada716d2855 223250e4ee92ab39a66d8c5d10cc1d859f8e129522763c03afd9c1ff982c8d3d efc9951e85bd27fddc0dad8179ad34a125b21a24f0f27dee656e5be965f54dad 2b31f9237409aa3ddd3789f095404bb3bf9557c7d1919227a4d812f2eb7afb9d b4d5426a38af058bed01586fd89efc34fc60cfbc95d4a3a34c722e05c5457c1b fa9cdd9ee59c34fa855609a835d3bde169d545ea653702f0a9b7645c8a8d472f 377077cbe71528c3b0bcf76ab93ba7451da7adea27d31234099289b05b22ab1f 8e5ea1ca5ff58b0d5e73e959b45a650332202e6e2c182672bdfc365b4b19f550 260285a632a4ead67966de806b34a32cbdc69352ccc25299509a3415bd6ac2f5 16c8b44afca503068a5117a0fa39b1cb5866672ced428ae720393e8140e4958d 6ec0f1ba70f1bfd60018d9780c58c09ef50ce619155a91fed21516d72fa65549 112cbf0a773da739a875b800bca212c1dfcaa8a7b006bb0b1cdd72e197dd5fb4 909c49c403a2533b78a8dc96119852c226b8a93e302d9a34ae910a8c61ecbc7a e16ca70091bf8859d39a34dc2fbec79f00888832d287e0bd0a3442a6067b7206 b41959aaaccedd4c7b4ad47f694421a9ab5f18365cf45a88d85dc4076e87c649 aa268761491f71d9cc3b911ea0db0efdc35676bcdd5194952d9d0f1dd82d18c1 cb1fd93f7c9844cfd85a4c0f89f5a41793bbc43cee813fe3d5ca10fca6538b04 9aeabddccfe892522302b7bf3e04f4b94773b0bb89b28f6f19e24220495c0caa 81cdf2134d20d8536596154521f3cc259e5b917c9cc4373c6f7adfa0b19e8009 78154a42cc5ebc11375cc35cab1a274f024301edee8fff0c08b5cdb0dae37c22 c29ad72588fc320a019c6c102e50ed32ff4123df1f8417e0e3ae315b8a6a31bb 5e053eb278d157296654a846a072b83224dfd088d8db57abdcfd8de00b2a8bee 5804ac28bb2465a4a879f07c063dfa4cfb2762fb9015da611c9b36fa62b10c5c 314e8a0ff8ce6e952150be70fa590a975e6629b6d6905e3f6233672af926dc0b 46 1fcf7ef19f675733f91dd4a8207d5c617fb263438f64803e8ec140d75cc0d00c6018706f263c7e8ae43a221e41f664d1641bd89b2697dc4ee8b2d6b9974c400c26c9520d0a995370e7b2d52759b8dc92ef93943fe5df0098155cc454d03a660f354b7b5d556faf76d5b926da008aab440545514256d1867de6ebb672e7cef10ef07666c0c575228094bfb5016fb28553042eb1bd880228a48401d0bd6793560b0186bb00e0c8ba9f9960d068633025609e6709289c6c6ffbbec50cc20adf7409b6ee102bed2e085cfd1d9160d1d3ea7581f1023ead418c24d89d4a933a4f110585a54513357e8ac7cbd234a835bcd53a9d1c5f4832f07aa5ec213c9a6736d70419bb412431cd4dd4c5ca857f939677188560c4c2fafc6053bab6e4361d7350064b2473e267d14f4b2bfd87aa2ace397ca1ca62ae417b35e497795573a175370ef3ee8626412dcbce1593f6e1f7f310b550bd8b54c4f12296c87b1fbc6ec3ff0d2948789a4ca19105d67235fa749467ac14682d5a5680b6267bf38bd4c589e9082759940fdb611a47eab4a2b92e5c51d63ae2f17f1aad8df975125a4d43e79c0c00421cc83193dc826cf90572e57da088a0262e9b0851c5e974643263e445c900d60f3d55608f081b106facb4d20b1bd93f80fd95a29e5fbdd0886487a2dfdf0f1355cd98bfaedf9e0d65ceaf59fb575b346b70d74f4a099966f8bb77b86ad60991767c375bab84e221f5b11bb693114a2f03439f2b52939fa7f50bbb4f804302ab40e17a7f04a23ca0890b6e77cda648c3dade5ff6debd9bd6ba2edee9fb660d018aa4aca839165b06f1c3377501718eb80f4b49a49a5702bfa871d8f2c285056828665e0f5c0ea785f39f6c18a29aaf7b58a0124483c9c33a474b597e317f0bce0b6562387280e261d94eb5070f2a05c8794612f1ff1dfc3b7b9b39963aab07367f70d908e4bcdffb3c9f0a2dbe3fb3d4209c7e046bc780163e628edd68650104052ffd574e9bbb478f73e558e70206c04ff0fb625b4a537ab0062bab7ffe084948c3db15498f5d4a5421d7a7ca5f4ed6d6d8c13969ba65e50ddafa1e3c4f073ad0be8e94a7156b642fd05393d502ea31c7fc6de80c540e4410793e5496bc06b2d74fbb6acd6877085df8174566d60bce9c74a055a1b4260e65379f2ceab908076f5d551c5f5b7d8c272f573a0e0e77163fca0d908e48b6394da44811c1e20731635492dffdbb3f625f0d73cc968a1d31aac3e4d7b0d62148d1240d0cf691041ff63f9bc0117374591a7cbf75e940756ca26f9ec2cadff72800b50af95b1b0625215639d06ebf0b502e6fcd9cd3cd9ea58b899c5ab9cc11fefbf2d82914e10acb7a5d88d2976df2fcd6e76b5777a3035a7a0ef8d862363bc1c352e32a3b25082a6046fde3ef65e4057d0d5b49f5a99cb7c9372469cdc8c52514e57acb4ff20efae06293f2650cd3cd15bf74edcfef458f16b9f258955674d5cf336606400b0fc363c21ce6e1665bb8b3394ae3ea1a9b5e36678da68b8956ac0ad9f904f2780bf03b6db98470ef4561777798009e858b53d83d5111a90f58550e73dea455480d6476d06b41182c229fb44296b8b3e06040ca154f31a41c8350532c6118eab30585c145aa3252bae17c5600132412e6bea08d343815e172d7f10386c9270fae0deb06ba0e995671c98fa279141aa7329970d53e762d1308303726e1f067a39d0509f30be03a052e9ea26e93843cbf5c5fb4b925ea78a5c8ec7cf00b925d079e02dc525662e01e6facb323ddbef6f6a47e30d4f2839b4d5813683a35bee0035907320f0affe129cfa6640645a12ea630445351d62ddc626d7ee9b9ba57a4005f0a890595e1f2c4a61c22e3a8cba39f4e8e7dda7d59f5ae9a1b440129898d6f3208b5502afdff42029b20a98ba62723c16fa2f07291a6d769bb062fd08e054390094cb4b87e0fb32100ea4dfbab06f8564e4bb4fa5d9454bcc6ac4e1cfe615d8e0446d904249e7ff62315742268d35e23bea759fc0f0122e3fd9d820d429a505a008d833bdff859f59493e5e47e7fbf0d1b4012fbfa778314a7fc88b00fd23bc1004f7957cd14d2f28852305c2c7db50e7fb90446a72e49f886251e20dfa48c850b01cf1212d2d1c97d983942c004326fa8657d78c0eb6fc7cbba32dcdae3bb41074ce6594a35d33578adb837431ef0ca16303bf35431dadd8e0481aceb151df700821d546f0902b173475c562d65e85312266370b97aa05e5ef6c9b5b5d043ff0249d051fe80450c1cd6289db78ea29638611fac124253fab2b453d099fcd973082bf12b9e810cf5587bd43b2cd50c53a1bb544df0a674792fee29c925ba04d40bb9caf043f967ba9ef9c03a668fcfeb9774c5914d231985a794d10aae7837b702adc438a2cebb9afd2dc7aa9ee4d8fb448b16a8e963015674eadf289338215c07d66e5ed23f72d02bc316e861960c414a45eb69309fedf7685506a07add025b0c671b5b5883a7d42f9aacfeedce9ffc579aa19e14c08d4a9b21489b238c065500d64e3d9605d9ec7106ba103b34a498c03b10cb0e2ef5565c45a72b7db6b1d5067f711f044b2aba03b6a78bd42b07ef71431c462e8034a5672682a0619c5a6301f55f096a3cdd405e538e92b10387369412497586769fe931cd64939cc5760c0c7bd12b399546a1f7140795b6ac8ce0652d5b2f8ed6c44baae2d61e4a216239073661df3a8121dced23831728e2cc697963aea388fb2bb21dc86a8a34a09d300591c9336f48ec25cadfa0a74e66d190b7cf9f4b825f67ee9a5db593481aca2a0672481feff11eefc7b1db169173b591efc318c1348fccb31f21e71faa9e575e02f862ffbc8578bcda117226a5acca369bbfbc50be304ef0e774e9488b1279b305541012ffab6a015b55f22748158a72ec38c6292135e52620a9b8c19b30b1e907dd6862505652b018ec29a4f268a538c26ac2b07c76fdd58e6f02e83356b1d100b5327f65a24e2d4c19603f4506f2262893e6b29bf2e5ea6b17bd816388693805be4756ab75f2538e89a4bc196395069a0354112284730ca74f83c4fa2859820d2999c33aeaed013c54c1c6b53404a4ada1416060a6625fc23a2f31482dea97028839136beb71935c1441e7736e0cd282ddc65ac21a4364c5a15573f4eb33290c5e3cdbb84c0f4e79009a41c7a10de61dd6a65076c4e239ee947226be924f6f0a5cf8caafd27772b248a4eec556c7e7f490ac9d614dfc8128a6d1de5078137e0e824d7061e7303327224970670c613b843a5b0d48c9692c18d6554baaf6c6cb00c82c0d3882fcadd5dd73859c8203d0465d2f1cfc0d33801beac9ac4f3645c700690bd497f538d820299dc08b509dbf9914547286f558b18ad6ad38b0c90b4c0e7d3405053a5cc3963c487d6674b3f493a2c933727b78146d9a80c2b4702cfd0810014d5a975b1ad6096425157ea0a970c5096366c5e03284e07a4d2dcb1d3605f141e7f0d3c0f823844cb20de86266da8d5471ea51541f84fe73fa7c02bd5b042d56ff58815b8951f723f63b635ea4d2db7d1284a613c71cbeef9c0c13675b0079a22f520eb7ecd63b819dafd026ba49b442646067e1705ae967f46612b029045d5f2b3542afe57d3455afb5656329df7ecd80632205fb3b6de3bf8433c3800bae113de16afe42173241cff67f4ff1b634c8fac81d9a14dc736b99669b27d80072f987a19626b820dcd22bc88f7914f1a9fb10a456b106aeee1e9263cb1c6c079a8180ddcba1ac6a1b411967b9fd716defb6f456e1508bbf7d2808d4ba559000c2b57f62ae16283ff7e2e144ef2847b5dec2803323210d78b80b5cd798e3910d6813363c7c3b3476d0105f21591cdba1eb5df9cc1c051e34c7c6ae7c186f2908f12abbbfaf07b6fa0184ec60f18ab4f5ff5cd331029c7c632bd2bd9aefaa480c6a59bd4acf9300ecd5f2b352ad905c3fb0b2b1ae1e9aca717caf9f5dbbb3750393de2d421f373bbaaa6d2772839d8e5dc45fbe3d5bda2f544ab58d578351b10e14416add30cf23ad95370d404e703c4f64b042c04d355671666b3a90e631ce0f11e7007027a514823f7354976272f14191acc00c6a937a518057d79b4ed26d0aa7880bb71fe6938cf3c3911e83a066a658fc653c97b8fa00795c4a95d4c5ea04f73918c007c9a758104147e4562550cdf3203d3eede59deccfdf8f56057a980d29efe8a5efc5c6870a76b66b504d5cb9b848c545e73bb5daba695401e440c201f631478bf56ffa954e772987ca8c2336f8855b8dac6a547090bcca325c5b020f29bee4240c111025ea6e87e97301fbe0f23b81095902eb6ff7528c89abb37d037796c1def752c3c6e48e5addc2f8294deca3a27e5b02c016facad87eeee52c034678fa092605ab1bd8b1bc246f2012acb4b10b8be70a6cf0210adf5542d377041af11e95833b3d069bb9f56584b64ea09f7d8e0c81a9843b18c902ee5d544b0c1a3cab85cc41071a96f3a532f9c1ee0f4739e2c6644e8db17211aa94e658e5084b3d7d096b543340307467d13cbb2f19f4c29f9907decc7a1506e707af264d0528a7b66bbee451c535ab394691f9a960e85cbdbaa98515f9322ca3dfb11d8f0f954e8179164072f90cd9e3607001ed790fdfe7da2f0be821142bfaa5246fcf0f2bfc7950dffba24847f0f6dcf83f15f6bb03436e5e4f7c90aae0205255e6c30642d1c5dc71ca6895df222a16ad4ba71aea8d3e08e50003c96e3fff9566a6670a6debdd28130b43a6c4ba97aebdaee39703ae4901742d254808026affb5fecf0d182d9a0accddf7becd0561d3b09ac1935845037d618690788b54c032e9583a00380bbbfe6c327309c65a62e1d52d9b310e217f66b795e39830bce54dde81f800d981a58c89f0fd73c5360e984779d4912137f1ac3db98351bf31815ee69f51034a0f34050d57b1713b95ff0e04f80b5c90c98e62c284d5d163f0834611209f09a8f439e5fef0b8e1700922c27ed3f735e04c4b44a7e112b9a93e0d7a35eb3d0c9271818541b912251e336327a90351b94234f1e68b16f2d5e8a449fbbcb50d0179cc4c1262f883c1d8ec610de1f78a51964278aa5cc682501e6cc26d069d070d372946e3e647e44448160273a0a0cc576e3ec9f094eca6c2803a025eab8cf50573d48e9714c4c13ebd8603dd4c1c5b790bf24afb8a477cea592fd278e9d07d05b75ed86d75bb89e340f620be4d7eee61402703916a3dfd88285af2a5c3ec370a20941c79f0ffceef712d922c9501d61a774cec163e54a54cb804c5f9982f210d00489a33637c59daf1b428e3c4a42d25c54a917d206e5ba5fed7fe572748b50c8549df20fa19c5bb041e303ec58f4fa2489b4ca4426b6dc340ff5a6636d53806e05d03998b5bb41eccde4794040a564a76590068578f2315f9eb5013b417b909d62856e9ec7226cded9ee1b9e3a0b138aa06eedfe4ba0ef50676d6a4dc4aec0d1d14e4c0ff95d02372a3d86e00e720e5da906e54b8d1171ea45a7f457229ae0da1c298f4bb2dcb65ca2b6ce6314f329b1bceb8d537d193441d2177ae5f6a760830b77a027fc52de393d317696b1e5f5539e8c03f827c0bea22c3ae55b5707c0914b6b46e29e8ff49b1a1d587f862cd923e02a21930c056ab1981dea1e9220f089f66de862a1b847433f09c8660d1fc0410e96d1d8b56ba5955213f64a0fb120e9d0f1931cf023f7e30a83d035a19fad0eeb7a094e0631025046b25da73508e0ff9a6a84a4e9b43dab3a1a81c412e554e99f5c5907161f0ae6abea1ef20068e060bf9f999e47a021db0c1160ea8c51710c10f934b1b923c4c8f80a4adda58280e161cc8901dee6ba80f8a88c96921f3896ef991d935a2ce8cad2a7c9b410ef1086d1efe57b8477a8b9a9419dde319bf226d0a2c2716fb414bc0feb40e940aa50d274b052d390123c3daa4f7559bce7be2b14ed0915a5fad3a6a6cb8fe4e76220c4e0612201d877a5c1533ae62bd2a0f6573220285d7ad4d04eebf9c35d91cf607c0c28010248a208cda7a3bb44774f6129c7edcbc73339c1410bbde758ea21b0a5ca8d90a720f2f1a8f3935f353abfed8331b50fa5c6bd296c9b4a43a5d451c0fe35da26963bd5ed54cf9ae77c7393e7f734465ae293cfb945a061184bd5548003d4bddf991e00bb3ac577796d32f28c2e2c874e7dfb732bb51fb5fd4764ad103e9bb2976c05b09e0767ceb05982efeaba1cda179613d5dad0383fa3eece52209a244874b963d33fec20d1d9baaf5ebe99c7ca445e0b86747e16544e1486b260bb43e048046520161c2da0408fddd4c5f164040fc5cf3e51f8f1d687f00f260005e22593815324593c150e274c2fcf2d53cdc96c81bff8729b06a82ff76e2800756a33a7ace3e03275473dff91df6e5822abca60a960a2faf4ac5d60a1fb7750cc2e6a542eb7e25790007cd2c472fb73ff102b0a8037416420408bac0535ef807dacb574c20d9ed95cbbf7854e2038e160df701886ba0622b21dba4f1cc901a0b74c8be25e7a0dcb23b729f669e0f2edb78d90c9660b05e11efec9199bde9960414dd33c318df89222adf62e0220a31ac169c7234685e72f47e45ce1f82c3d30b867c8b132ac8589d9f2bbb6e8889c7a822abd4a6bfebfce22e3b7b2acc797507dd25e810eae298e73ffd99eac44f9869f1947c39b1ea43ecde0397a9e3b49b0f48c1ee4b1fca0049c1a71192b18debd481b3a2fa3f6306e4c6f08c96555dd7031a3b8766a34c777701debf292c2087c0478e1ae7b9d21fa69f76fbac53aa590185056b7b86993601c2870615d23364e1cbd851f47f67eb72881c31319f97ac06636bc1fae90fdf67e44c614438e446a3f1d404d722cea1a3a4549499c0d4c80505e5913484cd245b170c4d7875b3cc7adc40d1f639f92075709abcd0afd07b0d9354f108b09191ce0765383accf5eeb0a3e28a8496de4801f3fd2e458280fa02d53d4b41a36f85eee29805b18d0906ac7e23af7c713dfd7c72810aaa8942a706e946bb57686c22465993bbd160af52445e1d35fcefe4bb50bcc84d7f0c5f5404fa189ca866ce2cd5f131340e507106c25a6954c8f5696b00d4d6f5e094a3fa073e41b50296530a0300fac26f8e4c0a8f36fcfa95487d0b9a06804aadfdffa20fb6a78dcd773f5c7f091e655384b570b948d13c9db744d2ad2be61762fd528304a55c93cf9683dc11f35d683165ddd1e708f5373ebaa137e40731d331688f4a03272586e31cb38f45bc4a51b5b48e2ad29c6650bfaec726412cd045e73f78880b37deb590d996bea622d8c6456a92f0b1cee5cb9f24906fbab482eb69782fe0062584bcddb549a91c20d1271e7b38fb40f59bc2840ef42670d7454f048822d207631934280442fae0b4a69ecf5cbf087d9d00de490fa703413c2476abecc5a10d975e8fae0a1870300fffcb9e8ad44afca4b85ba3e42cb54a998683991025ad0d7f32d641cc5452e2e78739d63e07e328dc19d1aa8c9fed56e8dbb79d9e29880ea2a01a3135ab8321e8276caed898db03008b0d2a1994b2c7cc8078244b58fa0b8e5a9cd24184e2fcc23e8549c68a0351a47da14028b5ececfb82f366e76e2e03c75bb8bf36e3983fe07b2f10f73bf6746c11b19798a1cad183d7c3cc36ae52013c9074b9755a6e95f619abbac953d6626071883ec5aa91af02c41c93adf6bb017acbbcf94505d6271f02f445f78fc3f081e707ccdb4c6f271953df358b6f1008ae795c6401cd319271cbcc0b1e773d7d89f5cc4c20a270c1cd687a72cee8f702863e40bcd13e274e4c00019da0aa6e42b25b7b52935765100f63f04694dae6010c129969c7b8cbece68d081f1712b23e4dd7f4eea2cbbc4e7ecb6d851f084a03f88007f4301ab7f6d14eb3707e2fd65bc1ac9d61bb264c96d38c066016eefd02ece5d026f6a23c78aeed4c515d18c85dc3c98a208ff9c31a87338355a1ddd4032d233fb3aa34d66634b910e7b0daffc06e582d91bdf0bf43581eeb34f60943091cd79aa5979bf310cbef72a315ad6cc311ee8d570501da0c3d01d1a09e72eb01d175620df6e35279c642ae384f090c2cccd0d2e7427c7c3f72d8d6c531f3720b1348d9e3bce76471479a6dcf62b52be88deec325685f484985e04848b8d8f8087eecaa711fc0c71e1f359a12e0ece74e7892ad33a53cadedaf896d914f91790905881846ec67d764935d6c040dba760a8e40161753de1639dcc9cb740a2db107fa10da97ed599be265dce75afc232372e3a8df3c822682f146be03e780f1300fd24e1e33d1ef5967386c9d20b4a360bfeb1b4767c2dc13a35338aef71c312b0d5c176d26abb5b92aa80122339200c4b7cc03963c34bff697f72ba071385c1903ef2b9010affcc4c76356e6228c3c76047c70905d987fff388239eb48c25cc4012af1d7c05f3b33dee915065392d0ed1c5265935350cdcaf638a86db2d14cd00360fd0e6e2ae2fc172c73c1ec090beb344b3f54db1d0824f52d7488a9fc214b00dcce1443dbaef00ecb07bcffd9ecf8ca45cf4e3569e703c94b2540655e13110dc04bedadf1c305c8b27e7392bcde501d294f75cd47bc58855b1318739c7e290cc87beed32932ea4a48293e47f367cded0a1c3a4db4e9c99daecfd1d1097cba05af0ed127ad8f4a3ebf7784ac7477994bc3ae303b79d1875947ddc6c0da61fa07d12bdea9a7b17b5fad1fdf13ee4ce7b056d7f0373dc4bd4c154146a49adfff030a8e59831c3cffb03488ae53cfce79bf4e6b7bc98f71e274c44520140bd3130c45e28fe5cf6bb4289649fa3538c476cd294c53bb40d715448e43d0bed5fad50754aa52ec4d686e75400e7286dfb39d6150a7272719d89ea1f922657bc5dfac0f365c468633f0679343b8e625e36b18bf9f2c5d2d6feb156945e862948f6d2603719f830650ec2c2bb194059821c9b6c74a1f064abae3c72ca801439b03d16605506e7524c75c84b97b6e7112c48a1aff4bd563fa3163b6fa4bd1e415cd9d480d98be4d519ab047b3259c1cb99c1e199142942b2ec1fac20e457419d27310b20ef5822441014a18cbb9aae5b75f5c07e73e17f90cf1ead39bda032a8424ee0807375e9f69fc74723b1b11737fb37e06e1419faa9c7b55dce9a3593d215d6a29041f0b57ef096097ef424de85ac80347ec09ef8c2317eff31008b0ca089a67f404cbe5bc089fa687dde3091ad9bb81a9a52e0de14eb6fd680966d3e5c55e29c5011607feb7514a3f436b31bb480e7a2681c708833dff97a8bff685a1b15b2fa405b14c398582cc7d730493235e38a1c3bfa5705ec909a36d66309dcb87347d3d0ca8c784a70d4608ffa0f35ea3bb2d134cd55caf098c6dc2c44d4379a3b78e4c0877464d1f3ef97e1359f005e5c095fc9649a17ef962e3f3d6c9aa0caaa6fee5072fd4d47675fc1b2377f599dfdc0d6cdc5e5e54919f1d0c9fbe24c896b8984101abac9e1fb9e2cb88c502e5d60f46771195903411a48fb4545a451453871e4c0ccf001f74c8c3054b604a9fd097da2adcfebc84980f9aa493a8d57acf959310016ac9c84254f0af0c75cff4b9708bc1081ab6e9928f6108f736b1b49812ab7d005af0de23d2e687ed153e43b176f0f2c7a95f14ccc2ee1082ee73f6b97c86ff0ad21c534ff329000799d7c4c721d72f3af6880767be30955ccee7535f1256a50ac4005b7f84099af86d99f4c4d4d88c86b1d309cfb457d2836b09d6507427e205584ceb61fb1c4c6a9f09042fc06342c94f48ccb65f3b33af21a5ff4f00a0bf03cbdd1e1bd5097866968e0e30ea8f5178ce5240c22c8a974e08adf8d0fe3ae40af32492a7a679b89978cb637ce74e7cf2f71f206d504b0f531ee50bdab1960209c90d925d11af2ca2e502fe88c91e8765d05ff658fb23e51acd408e3ed5542b0a38ae390169c8e8926503662f2a7255ef2741d0d4fc4da24b22e24d4e4409a20533cee9a8b287eb4e7c1d868f8efe97cdc470401b0991df22ec7e46644b3efb0dab6b5db335ad574f218251cdf9f2416f7150781ae7b5697b4064290a284606005d93dcac56034235ff268ea7848befebfcff1084b1016505f65dbc9da14a180b92a0025050d4a89db2dabaeab5ec1751e3dc2508068e22f4d213afd6d590b809 +generate_ring_signature 2f70a3f91cd8002c712cc239ee2488b0046d4b010eab9d35554f4e1bd9d61b0b ad0464c09da58d6bdb00c070a4e094c0883cfb6eec67fb6532093193b4b1f6dc 55 e19f645f9ee2bd327eb51f336a58e2c9db7b1a64a97d6803d6b56ed4fa9cd560 2c9c1ca72314e021d1cebff7509cd33dec503d78b8249bf712cdfd55895a3726 7bc59484c4005b65ef76ca020046038e3a524db3c456d48bd6e6dd45f38a252e b849fae09d21667f19fab5fd6c7d0544b59bfbed39a524a942d48828106cb12e e16fbdc60de52e405d04eeb52b3b00c0bd1fbed1d5af08f4f35be6428bf4fd8d 9ab4b2beb1c9a8ae1c4c33c53fe19581488a836bb933b45bce4884604a5ffc96 0fc8e4a7ac769f9a692ec80395494b43e581f82aa65b4247ffd7a67291fa3b58 af9c421abc18053d52ef23a6846ddefcd717a96fd90f2b04ec33eab670dbd39a fe83d20f114e98d35389b23ec392dce2f3a110c45710f0c61905bc5c77bd6389 ca5eca751a73bb5c81f1f85ee75c0b6933f364579189a9e010b470495d1d4166 678ddee968928b2be7d171f934fe13a681556c03c4471d2b3a0c106aeb16e0af 58a41d7ce0ed959b012e587542acf3031f7a878d0668573f296e95e79c0c56e3 1f98f698a97f4bf968d8c4a073d62bc50ab6768dc8f0253a6ee7d0a9b8e400e9 203f2fdce050523df6932b625fcd99c5d592853d69594c6ced0d8d1a27e2df4e e682c2bb504201724f9d6831aeda7347efc2aafc78397f237ee36a2d609adafc ded39b9bc8849e513f81e5c22bb93f4d7009522eb63f580e9e5ef369a009f63a 9b4566467f59a6f545fd438293c87f895979da6151e0f713f0535a6a78edf605 b16fd389f7553736eab1855cb33822999b4c4a28ad1aff92776724fb2935e91c 1ce0853c4f87e754e05213c1804225ee1a2120494b20fe23bcf133b33166504f 0ba8b536b491f31696ab1d4dedba8164f7a1774d648b6aaf571e7a1dc00962d5 df770c4d34b57b2cf0dfd5e59b8778e4f6821796acf3e5a8a1ef2b6c6caea12b 000cd6a7b4564634f50f4cb3bb34040bbbea725ba56a0226603e12f16c75c838 68d4b4453419af5172aa54d1ff68004e0e8bc785605c87dbff1522a69fcf5eb6 6ea42b2fdfabfdac3d4e4dd520fd923c25ce1d66c5c536f21ac14af60a3a69b0 e6c455a08d17e0f82fdb4b1d2952d1f03bb66fd20b40d80f693e6f1621261b8d aa4da257da007f817e0ef63694a46500b56c649b6430cd8ad2cd98cdc92fd5b9 ae71c3343d5a2b6124deb034ac1c381121b80e9cdd3c1a3f8ca645be245c802f 55c97d73d6cc3e432460456234d554ebc88f4153ed753ae69a42ed8827906384 7d2d00d52c811603b99a492a7a2459d1c88cb5113a22ebec3ca09ffc126c8757 b487a8889eb4a2e809205aba036adb11473ec68efe7bacb6df6fb0ab34b5f563 636fd45289cc28718d29ec8dc3a53ab20f2dbdb81aa8a7e73ab256f16b075484 d4c8554683898da5f9da8a64c30fb3e343cfb19eb88f7fbf567901a9a98d2d71 160b282251304e7cccc5682a64e5f4a4c7356e199b023ff9818c25defd1e47f6 1a5b8c9c7a12ac3f2470048f0642602e07796a4bc7bc095aa88a30976fd3b873 d39fa1a932a00e90d0c2339bf81666c08f299234846b54124942a9db33365b48 d023e5c5466fbb9f9f4210e53965f90b51efaf8181b4eb11f28081781f618fac 441afbbf59c3ce187d0ea4b7f0b8c886509b32f762f84b64d64cb1ae7e4661b4 7d9521c9c0476cb8deb152527709412eab60f79e6dcae7d6a8bc764b521552fb 7753e5dd3407847543c066c3be5b57568a00ce2156029dced77a7d7f84b51c49 643c25c296ff6b10e044502b84bbbb8066dd60c13642ed568cd3a127269cc683 af193ec7757ba760a786e1bd6dea91abf67e0d09fe1dde9636ee740cb64b3881 97c86f4eb82cf9b008f34d77be77474a9dccbc7a28f8af3135804c4be4d7f4c1 42a123aee5df04b5d770c8d135ce837ca7b61f889afbfe459affc364683bbaf4 82443654c82e18c320f5c5a91eddaf6a009a9ab264e19fd377094165553a5798 1c281ae660b2a48d4ce02e48fc43d19d9506fe50ce98be6138ce2a12f104171b e697e05d9ca04429039d3b472766d362bdd5bc09edc5749244a4e1631d24fb19 c64794f14532943a569709acc96c45ad352cdfe950a925f2d6d5d15461e24dd7 215eaa77ce36cb9da74e8b4cbe60fa4effe632bc03b8ac2972219d7197b1755d e45863fc78b8e87aa3e1527121dc382a16697e8febcebf7371975d02a8c019d6 64c05b4302440eebf39e77dfee67a5c556c28240d204684197c36c61add87089 c56a0a14c23839ebb8fdcbbd53da469670546a8a4d9b988e4283fecba308ad63 ecce137e698c68abfc86d1e30b88654aca22c4a81c5badfbe97db39fd069f4cf 0261b71c4342e73833ef38913e92cf7acd43191b63872739d4c419daaf35d193 978a3653c3a18d1f58e3a222176e34d37ffbc816b80d11625e0ea049554b1778 bd8028231d3f30ef112db35443850f73b573f8a9dc3345ca5744bb7b97ff4009 8eedeeb643d1d8dbc79f2f62d47dad575e1965b8cf1c25dede6f010cb2e50300 24 59a971ff2425fad3bcd13992dbbdf9785305cea18f04ce131770b4d2e28dba02a00e3b05de5d0fde61e63bdb786ade3ca58947073bb488764606b3ebd0600609e9d9c0adaf2373024a69ea44acdbbd9a84ae74f25488df0be2738eec3409b70045ac54ff862a8c4ddf5d13e95ad3898925280c2485bbf589dcf12a02e1b20a08f8699b92354e4a384cb2ca5fa840c04accaaf7542b9c049fba901a262c96b60beec5d4c2c6022cfa86c49f9e35532a66c94aee232245fc805bd3001cdf05f107994eaf7c4d48018ddcddf742f73dc706880354e36761736e78592a62b72916009e2f80ce8ade0dacfe8655dab6e1d8d4b239e6779620c613778c93c066c6cc0fa61c8d21e5285eccadfa5726dcd0f2c56fb7188ff06b0245ce0579ca01d5e004a9ccfbe6c1e1950cffa962a60c61910dcf778ee4ca227011cc7d7d9c0cc8380ef863d563834a3ebf8cd61a2a399d83ec0f5eaa5c2ec8f10fe068e72892b74a0d88a34a33380f16bdea2437889accfda618f3838ccfa393df5af6d97c7939c20c2224da8f7eeac5107361b7083caf977c138dcc8bade5f68d2aa2caa075b486091d7969480ad8b535041b2c93c29dd893bbb39ec6eca8242120795e6a8aedc10245c83d9f15b0916326980003eb60cecbc47751ce56bc9df1dfb63959170726008cfff9ea58554992292c866075f5778ef572dfabc69a82325949eeb8177a5f09e9aeef78e9fe58d6658d18275548fd0e147b8d60d6e6a577265994b741a3cc06f3c03da8f869a69778d9327d094a5a41c06e25e49901aa8b194aa08660a19603767b339e28050f4bf2d2dae2010e8ab75fa99a1c3b29253a8601009e17168c092ebcf4151f2d51070fb2fef8943cfe456c78cdc4bb7dda09fa768984a88fa30593198e31fea0a546d46f22c7de0c0f6dfe11226f27691deb01b169adf587530f3bc9270b9e1d78a8a67e4b9d70d9e12d9b5f692bd108a2644b1be761729ca40cabcab2cb7bfdea3362563452db9ef7c884a82d0dede94538f5145f313c7f1a0c73cc2eba8c27fcc0b8955d920de6bc8c92ff3e4e7ecc0d1a1221d9407e5aa1034ec66fc12a939a0f2767f2af343a46852fd64c850d5fe82af921eb60840f320319de593ba7c3ec9508c70172aa3b9e0bf2927b778b42b413920fc22d4439d505b6e6469fd6448fd92284c69f912ecb7f4ef0ca274ea68983cf4859d7bd847803fbe21297cb423a6dae7a947384944fcd0c510e149ee52a751ebd4ce214b829086a7c494f58b31ae1e2e1b412d52873b81aa0b794909758a1c124b28edbd56c06aac302a458417da82e3af5234c925df0551312615016a197ca727adf6e83740282039557233a0e92788b195d13bd59a6b348960dcfddf971274d913d7166a1083dc6ee8c25f1510d056ac0106932d9fb49b48cb1a059e70ab14feb18a15455084252a94d7520172a28ff09631273278741808316fbee95fa1a975e5070281705867fe68506de1bd459805414cf2ad43ced52da167396d1a5104297eb19cce901dff29dfe5a9de9e56f1276d842727b6a1fc2a3b003865b4be8b6fcc44b31990bd9f4c703a5c1081168c57ccb92e969272294d354050d3533b51ceb1c9444a009c09932b58c6c798abd336c413de060aa96c22f32baa3dabb0187d5b45d69270359f61a9832c53ad31dbd9aa5010c9d6954a95128fcb64ee5c4d7d2397188eb0d685d5e4b123494f6094f3fbe103c6ff75e07ff6899b1cf82e17420840e049e03ccd1e9e3849d1e02c9dd3d17b6db737f56b669bc67038befc638b1699bf7240fd7f62de49cf873da500655c3380865c72905f4e58036802850d5d2ae883d220c7c222f15cc7437d37d44dd891c20f361b7d0e1653b3b359d504affab6c25940089be406d304b3cfcfbece51cb505bda6b4488fcc9c9fc7da6babc9bdaf0d2d09447adce0101b60bbd76e1c0bff8b9ebb25932907c9e5e21e88ede4a884e01e0354013f067ec762031c18d4ecacce884da16b7ec49d753e636c9bee70e6b83700542bcab59413799295e58cd0615a9bde3e1425699633b92082f4e2266d63a909892d437b7b6970de0cb3f632a92dba085ba5bbd8b2c02b09a94787daa3e0c90ee4015aae33f414223c3f5823b4500b517bc050dce4b6d8f8f17ed44d8322300b2ca9a26962b7e89cef388d39fed0d76ae9a53977a5d65bec353f54126c9618061af5016f8e93e51f88df3eb1f13a133ea6fedbe101dc10d18e6bafa4bc2b59057002048f4bc81912fd84ceaa12fcae1957d91fc9195b995ebea3487a88997903eb932a8bbaa1df1c7940ccb6369eb47737e95d1ffd34ce9c51488db480471c08fbe050b02dbda9253163237f14ae7533e1b29a39fca035fc1f102a80a7d4160d3feae8f5739ee867d319648fea77094c707846e4541b607e4dbd4f0bcfecd801a76606bd1cc2edd04bc51217f693e873ac4be75595853a402e1686bb5726790a0c7da0075291bcf33214bf86c9dc3fda63861373713abb9490d6c3c7b2a1970a38edc410272942f4758aed302f2184945bfeb26e538788116bca0133e5a79300be3170da7e3544577de06f0ae3746a9e5fabecfe62e80d7c830ab081dba8c1078ce784d26e7850149dcfa5c4be93a6c8621ee9fe02029de2813c5263ec4ba70bd04b6a9f852ec02e101de57b8a7ddb6e7b4e812722c9e1ae1845ef8ab78b800351b4acc41e2160825036c58af2cd05166fa597281eef026c647c3acc69b9170a408783f88f183cff88549c049f3c54f2a29e3b7891aac7d1839346378139c505781b02293baab8a2eaf7c40d11e684e7c3e8e7bd04b5b376c663d506a42faa0f6703f10992af9e6f6639453f8daad4e476c0d49085fc3bf2146357e357956b092352dc209c724c6b45bc1c7491065864df2c7948b7cacd0abbfec7597f930a08046a347b7e18089e75f50b65878e59a3ec8158e8d2623828215dcb45a97b410d519421f7367efad7d0b6590c23b495b9d5f751ae444e98153e7929cb75c6ba0b0907731c8b5b36b6f3812cec4f4b73301813e7574344c948fd3d087f9628c30e86c63e16abdc3eb2b0f802d8834dd66c36a2b899448edab4df2d42bee0ed7001c952706f90052599beae04b67833a556254b6c505a92052d4bc653f1b7ed2c0e2268b852cdfb990a561d98d1d621245b3ba56f2317dffc97b2a548ac66df3305e51c094fa1ae62ba9cf528bc831439e17c2c707dd900982a1e873217b1ad9d04684ed87c7a14bed1b3e314cc1ce27098d38a9f985c2d575e1d73e5128467ce081fd1841d5dc5d495f2e559032f7136d1f9c2c31c17f9f54ddd0419eeeb9f6e04656f902111736211a21d464a249cff3c7f60bedda472df2525783e2711571a05315cf172b4c1fed6dd6551a068d17bf71ca0e65a945de61530619134b3b0740d335c10e604d5b69dfe3b4cfae2f75f0e915221a7a944243dfdbb7c160f6e350d1a9982b0c172a914480550e778bf345729014189a2e2a7fee38e8db067cec807f74a0e070faf4df92404372367b2538fad8eaafcb797432393351dec2b85f606222476bc4ebc7b409915b9fcaa2dfd3e3011dc50443bc110053c7e434fa47b0649f66b5780e8c9e07f8cf1eecb416d6a078dc6b5e7b6649195552612b91fb603738a109038de305169b62869f27422102d29743d725e72ac6c38db98d5b54304c0d774cfdc66d69cf60d375b54fb8faffc3b6de7a3cb408b734f919643a62e040ef47039dfa2b7301efa06ca348c69f3d0a1343cb2b81a9bce0e5e7812631302545adcd437356948ed0440efb14476623608bd17fca782b8df715a18a80a8502203555efb76dcaace047db7b58e14a340a4c40df976cdf1a611a800204eb3d06dde5af61a81c2bdedf93a0982cec2d7e7a2e06f05b0b29df58d22ac0e3f96b0c5312fe5e33fc0a2d8889612765d7a461c26ddc95b6344d6af2f1f6f47b895100ef828d42b6947fd3584b41ceb237c7e9d58b81d95c2e8fda86829e7caf89390d8b7bb98c8064b32e244461952823a7b486d4c77c84f6f97cc871bb397369b40cee4ad48760a76d265c236fa2033fdf937d7cade969de7a63c93363834e1f9f00a5f37a535dd2c1ec403f2475d91464f7bc5caa3f4d7474a30c2cd67c22515007173f2aa863ca6e44adc2edf8b70f6b0112a4134a4c23eb2a06baea34befb4d0e4c6f879a3fc297ff740310327926312228c24e3bda34b1f6d96c97cb415192092338896c126659933003f85bcdff65572fd081c4507cb56b138c488b9a41540835a8368cfd81e73988b1a68c7b1c3f02d3f6f2cf3f72fa4c2a5cb312deb6a10555075870dcf71bd3445f6f234ec13c07fda4ab1b5601c7de4710e9d9de7ed10d0c4ef6661650815e44ad4ac7cad3fa30906caaa9eca732c7fb834fc06f768204039be141561016e8811a36244dafd4477637fac2d8739c4b65527cb540a2980dcde5a701d76c311809cb780271fa03abe32d6a29194432e19d1ccc5c3b821e0617ad6a028ac4897c698d730a9dc9e6b1f5214fca28b2962be458c5f282809a030b0055344efe8483fbe7357e9e77fd2451a524e2f5013c86bde4c748acc6d60525c22e8581a116629e190c6f216d42e47b2deae5bbf9e21aa58066c11865a30df9951ca6d8a4b94745b8042ff09d3cccd4fd5048dcbae803334f81849e07510980a959409402ec713d84edf4cdbafe8dfac332615004ab6e63bb82273101b2027785f7d4014a0b380deca671056d4fb9fff4f637e900ed312a2896fb0efda004b6abac0a75694b3cca9cdd6240edd6b90d338bd752880f4d66e6a29f0c47940053100625e39ae536797a4fe909f5b779a4ea7fcd23e6ce9b345f2d86a4d69f01829b711cd78ff96036fbc6082b74a41de3953080fa7fe34976b0e3318a6ae3075063081e3f7d69721b08b18fcd9bec5374cc049a12018f726d150087b36cd60d +generate_ring_signature 0ba30de6e6d2dbc9fd491a2874728fd0280ced45df74f8c8d32cf2e77768e7ae 0b3de9afe1359f3f83c005c7631c44a73ffba60a836ae3839d8d5927c4471ed0 152 3a358906b6ff770b1f077ae12d8f7f3cde8cc6d3c19a8c9f5bb6ee11b7388e7e 472a126f08b58e6cbcd37f5ac22cfc6c662546bac3da95da2ba09452f2437a91 fb4235440693b05fc30539541b237b7f9b5c7ad68df2955361c3de5dfad8e9b3 591196da4d50c814756f5ba064cbd38d1af3671a407d8a05cd8d0e056a4e012f ae702c49cb7fb2dc5df1a5e1c39f2b2ce402f2945ddf59241dc047b4ef81cefc a585b5a0091db1a7ab1bedf09903aab8d0b0a844d74e67de526bc99cfc23534e e092843c820545862a9e6bb15ded38458d654c953971ecb97fd1bf7603c1dc6e 322a688cc9f928b3499215ac5bcf36b55b781ea58280315c156841adff146995 ed842c7281842528fa2b17d4d910377ba970d1443a686d3742a18816b10b4ad9 daef8362af755e7e0d52afabe3a44575242405bc654d2c5c59517b98090bf334 1c3845699b373abc21d24b1107ce31e3d3eef3e7ea96c491f7c6652ce57465fb 14261e794ec119d49af09f570dabf6729560be83464419a93d02f0da7ddbbad4 33b42eae69927195bc2de2fb5206054ecf6511312a2528d4929a4a9867002813 c796fcbba62668d7a0d2348a1d9b5f06ab4fe9b157b0d846443b41edb9a1b6fa c95fc5d08879a12aa68952ae167d17993a7e2623297f75fd2272c82e32bfc37a 6cb2f098c37f9b3c863566c29d56939ebdbad47aa24cceb566cb410223a846b5 b77692430504c280106fdb7f639c495d8ef0d7d558dcbd75b23c03f51f8a3e11 4159b10f826b40b00b32991efab391e8f6c0222bcd8ebc0ca35f01c56023e0bf 3fd351cd999eea1dae072737a2352de6e0d35cc5c03b7b66784aae6b5e8a1466 9a184ac51ae37b7fd07b91e062c085b6cfbe8d9fdb539da59cae447ae7a7b78e f3542561f7f3543004b64d6f2d45dddca1fcc7ce148f8fcc240e5dd1edd2c294 f84af966409541a111985fa9c0ce4d203fb6d449f337eac3527765a7026ebe87 c85ae572e78401bbc3594bc748bca1f6996461cbaf8c28064aa3ec6814bb41c2 4aa24501b140eee2efa6fb6980eb6bb4b703eff58c9069b54f1b30dee82f46a2 c61f9c3d781903381bbc07c6ccd2631e6592130c7ef184d2936fbb156ec1560d 146811dcf8fc8172c1504d032ddec6798525e1d8a9429517ad73641cf2ee7499 556394b1a728ad1d4cd280e5e56837702e029da3d8718f50e5bbaf6f0b05ae17 0d694f1df6ef6156bc6f8c5cc2a3668801e9a9f29f8436d22d25feb331afe929 7ba9d54920fa1923eb772fc59f73ec3578fa08866b226d11e983cc8d2f8ca631 9e4f1d09796df5a2f21b9732dd9a217ff85b1acfa8ad071c0f8cacd16c875025 77c0433220a41feb333fe7a4c76ebee4dc10a08644bf530426b99b21dd0ce3c1 1a34d9fe7d8b4503fae56512bfb90821147cbd0d276ced49d456da3aa59f50a7 70f6147b9a07429cda27dbac9f7b69ff87293a49a6bb32e48e5bd7c6cece8bc2 52a798ffabffe412acd4e9afe2e21ca0f5c3b7b83481d18e98c03f916fad4f3a 6fafe4e0b6a1bc4e19439958d5b5eb6300e5685637a976595748955ac294450b c9081e39f92a9d9c0b0d120d3bd1bb757133873ee5e02dd6e428083df7c89cac dfe7f7dd98096fc79fab45669c8173226c19f953bd7d7eb2bb2739d79dfa2e23 3c3856df0f874c2d766f14ec708a366d23128ad13df93d73db9156b7d9f074e6 866dc59ada75d08e8c8ef670218581db6a3fcff78d62d8f058c4d7f767ce6e21 53ec7e68ff4f0c96dedaee098825b83a4bf56c3f6e590f787e4fb02a0491a035 66d5a0aa788d312053b71aa88fdb961ef22eb238afa1eb8a50f739d821a27e1f f5cfeeb51f1238168ad45c7daa7caf2632caeccfe64a2d97e6f93bea5fe902ea 575fcfea8d4bc586a780acaaf079f4a75d4bcaae1ff008cd5e961fe7f7a7bbfc feccc7e6f4619532c2b5cfb43a0e7240b35e7824b94086a93c2f8ff76bd01392 7fefcab77bd3284fa4867c63503d1ff728ebdac0574632be0dd8afbe601f3b81 6bc526e9c885d131970279cfc139e14d213ca40384f021541e669b8b64cf6c5c 864abdb33355465fd8d918c99bb840169d53e1532c8d82aaff27ccd1197f8ba2 2d37d9199ec4b6660639f4419cf184293ecddf90f8d40420e61bea0971ea583e 45890e5e880c0607c04b9e703270355c33cf305485b9c15b9927ff2728bfa5f3 e5778f46b5adb329727cc6f39685138b0ed0932b3542873dd4448909f7d3acdb 7fbc3ad923ce86f8ff5c34ea3b657fff3eeaafe9be2e00ad74e02ab4a579e558 a247dd3e76847f4c67f98e8c62ea0552c69410b57f59bdfcb820dec44fe377cc 31f23aeac4ecdd85e4833c8adf88b7c481a6f687b45920ae746796c878ef16df 7a812f1702f24563d4af961789b40be3d5b7836277f5c96096385d5d373c02a8 6ed55998c547fde1f832dbd3c496c4b1de1d17cb2e2cace2cf188d38ecab1df4 f24160e9814de8c26b075a6f11f085788ee84abdca189158a0420aacdd9b6eee 8255924674ecbcd958d0ecbd07c8962bef86f2d2a5aef852ec8f1fb7f9d69c35 129592cd3a9d7e1463862b37909bfe1d74927582b6c45a6afd259ab07ebccbbc 5d44bbe0a39fb5f35dab4e900a447a42ec4153eb53f69eaa47bdb9bac8137d8c 18eceddf52dd350616f472d7d1b8fed16d25297913d7f2f8ed04883b999ea48f 3af3a5785978cc66e200dba17afaa3b40ce4a5783fa9333a6424c4ba06fb7618 901492fdad5dfded52b21c9959a178334f8e7168b6609bfb077e2a7b93ede507 f7d79b9ec77df91be73f405bd30216aaacd3a055c63efc4f86f0b109798655f5 dbd4023695ec11a04d54740936f407fb2c2b6cbe979e6ef5bf0767a801d0a178 93ab27f15725d4630ba876f4a58ba78e4e560a410aad53a8a735911b7196c6b6 545578c450ac54f055d46e661d12d4d0adbe0849a61e2ea03d6e3d4638da7cd9 3391411ea286cfb663d15115d113f7b2f0826a840395939e8d5b611433f2d113 57ef1e875e3855b4ab4670fed3d630e6cda0e1b9341891e59b7e2f9914c947db 658ef5e1bcf430e63a0b9122ee3a84ecc9f47388f7b31c6fcf366eb8fa9d93bb 2658013beab0b98888d1eb2f795f64f16c8855dfc503d3a66239a0047c5593f5 69277ea51de11f6fba8a43c41fd968d901c4e31e822f4b5b3553318f847b1995 77257767504d0df2a8e5500dede46246b257f7a9f304d5e034268bb02c23e209 06dffc165810f727b325edf311d3839cda6b71ef24fefbc3f455121092d7a938 a50590f3d9193887a33303080421388a59ad10c546a1311e16c8a7313dacebe9 4a0796e932306dda67589cb37f697c2810df1c1747e2b2fcfa293b4f4c40c4b9 c5adb0180758e9a960558496d341d36e639d8355e36e076ad31859371c8b1014 9ee7528e99713c1bd54457781063dea844349199756561b4be6c384b779ed8ef ec8f58b2e690c33d2d30384142e787c7b380d422bc7845a99b9d36ea5e1a3c55 151a797a15a5814ba694cf2bb077185e5b1977d9d18eac0ad772e1282ba5ce80 c08da9572b6395a5cc018f6cbd1da4883d6a2f7d3d76502fdfd72b655e1bb5f7 30ab619fe844790c294a0434cf663d887898c694b1bd374b2558216eda20e683 196b383d573af3795f23d86ed51dd55d9c3ae875464825141be817a0be662345 153ef73d1f5b17c75c970bc76c29e4f2ff6bb212d76e0ae7ac38445c7c76ce97 4c8e7f367d39ea4210f0154dfb333766531983d43313240753483e00d1b72116 dd237005fb83081cc37a3d4a781426d7c72fbf170ef7973256d3b9cf212f2f8e 8baa3f9913024928a3c62e82d8d89ef7438fe7110b9dea1dc138c7618837403f ee427f72f1736d9a3b416b363db0e19250a04cdeab9969f6209bfa556cf79e5f c7662161c5e8c2390fb938a10669beb2713a9eb58fdf61d4476bfef7284db7c9 f9bac6ab6e3346e88b5e48eca67640c104dbf8520f08e240416c3ef27a29a332 cbc2ee1e4553e90b60ff83126c636bb047e95d7d17e941aba994bc5e122280ec 601b1aee63a11d7e9f930d9a64f672280b17787131d12e46ab0140ff01a3372e 90fa3f00483356004def6de99c8dddf30d340b96a065d0e14e7e2ab5929771a0 5f762e1c5d76870eb65f31f7751070f2664a90dfa7ae1df568f64f8478368bb4 8c03cfc38212d86cd7002a0947128016a0131983552f6826d20a84bbb052aea6 b188375c340056fb061f1ae3bb28ad17beefca3e7b5473fc9087e257cae927c5 dffe5382445976ae1ec4261b3370718468ba4ecab5cbfb50a22ab6d38285d3c1 7283670d3cb766afff7f34486489d5a1a5b0bb823fab655657166de815abec24 f7713361d1b7b267f55265c03a458233b8d077007687308da0ae02a3075c0d4f 202b3150f80754ff14b48f57a8cb648ac372fabdd91874e45fd0b6b5b26b2de8 cc9ad47925cae8fadc55c3005147ea9f93b4b8d7b1517104c24bf0b893ab46e8 be42bf5d3f94f09be5042260f359c8292dfc6f7c27ab8da88e9d4d80ee553e78 3bd3222539be23ca0edc229d3eeeedc1b41b8ce296978d73c86e762af79aa887 4080704d2b09ab7ed4eb0b8b0e439ec8a2ead3a06f817ce3f9363563950fdb0b ad35286dbd79ecb282fc7cb18c5dc7e7abd53bbcb26c824a3141fc054b8d15db 4aad9cc0beaeef5482e2950883d7253a309ef56e7fcff5df54f5f8e654868cad f1d06103cbc99b6de6494047a63fd690a1feb3082c52eed0b2ecffd5872629d9 3b55b2070aa5fbbc6f5a160de4e9f3c2f4655278f38d02bc6f5c5987f6a5d46b 8b6e16fef782152e2e03abe8a72a0c961bbcd899b27e62fc1c59a9b703aabc87 a027b3419222bce3f34445a08da62ff76712b33bbb62ff25436046e8c97ab78e 07fc0c70593b4023360ba9026368f270ee095f65cc7ea57f459b739f73328ae1 a2bcde7f605fd6d05046e0eb333081e8491057e369713b9f9adec7af1b55665d 687186ddddfd074aeffc932f3d56fa3edcf50479c2c537dc81c712c80f0d60a4 868475fcfd1604aa98ef79866cd4a7ce314850928880af9bc2e31eda14f07f79 c46158842eded9c26dedcc934ca9d51ce3eebe5a6173710225bdded6ffba7643 1ad3ae4a9d113f8991939e7396f74fb0d96280837f67caad692d18722a93a200 0ef7b4ff25837eedf897a910f445eaefe4520042bce6d666cac0b206db3dd1e5 7734da981ddc91893bc8a527007f824a22b40844d0b4537209e5d3d37bb27091 ebe6fbdbe09907e6fdf2c89841e1c57cf69c6e324f8934559cef075f7ac0e2cb a5ffed386db8174633ba84fb978f88f8217a6afda3ca2e5acf6e70249b0b4937 c130b6a8e631f76d972d0f155949fb7fa8d093e576abdafa584cfd192cabdef6 7edde741298c76767208089c421fc96b728a108eb96e60618ed458a25e62a0af 3453fa314a63d4eb7ddd4ed46dccefbc3c939afb8eb2d00a3ccb4592e5e1c39b 001057c3d37ee9247b99984c5e5270911227156b442a879a9ffa598b9c0521ee 337b79ce5ca206ad07c09efd4b90abf7d907be87cc842cf4c33a4a75f40d03b0 13f81b423b6fd6096ae3e0877ceb6fe79453a2714d72f43b8779d3f9ba7bdc56 a6f2f646deb6f9e205ddaee63ef8a76b3a5b54a928ad4f3e1dd88d16fcff3992 65cd6f6ebc27c988cf885cf88705f1868f66350f1aa9eef50e3e9d032f8f110f bfe7674163556b3b7f7d14d706cb97df910eaeac8e523d564aee31a02d63ced8 5fd0212e3214b85eea338d564a336905fa46275d7207da69f5c94cd76444b66c 0745a8db9d2d5d2cd987cf39a9719da6ccc397dc8a979bfe1b98755b83ced8c4 8d47529f198578fea2df336e62bb2509a978e570d20a03d0cc5ddee398b90489 3c7ab76d75cfe7c749c818939a4d00b22cd55d17811f1e81a2943368acbc9930 9032f04a5cfc16c2560a30ddde438fd67b34f03d067266cc1ed0d6b1f21a8da1 82a319462f7be63add5b1de1c57d4f96b7d01a37d37c1402b8ecfc7c23172e45 5fff19c41880b0ab48f57fc5453d4a14d5c22d78f10ae7bc7a5ec7c6d397be7c 7b4bf36034148946aa80874237e075fb735b3a5ba7a25a085fbf70fc19f63f16 5e367870d1be56519048148b998a8da59d93b302f8136ca1ce8265d92653398e b1ae44dcdc1345606bc107fc2ff729fab2c215540b088e6117fb82f8469bcc49 09a26ba5b7ec87989a79d47fdec7febf79647abfd0efe6ba1078a15b345116e7 a53e112ca9565d939ac0f80c9218438e05ee1cbb40e094c4c6b9778cd1ee9341 4480d3899ff9742956f8ea9686d3d52082cef3e150fd8d647768701d99805550 0cc2d147b225cdeb658984df806fb6121de31e3c43d73cbe979c8fb8251b0bfb 42ed973a0b53fd57c7676e9facffdba1fa56437683ea6839537af906ed04733a 00ff260d90022060b2c237a1a68251d150fc53b94af0b47adc9d661dea155785 8d7bd44609717a19a777658dc0aad8ff10c8fac87e643378a683f0097e916057 47f05593d2ee2b00a2ddaf85ba6a7bb9c56e09cf8ade444503dc4d426e2af9b2 caa9a7998ed8f932e5d50c969b38da96ba85fa5501bb63af160fdeb987f6bee8 8629cfd12d7e4d98962a96d5359d6df658740b02e3178842da6536006b11b20a c181bd65f77ad32482f0e347091f9e6469d6867b55ee420a6201fc7eaa5f9c4d cf322dd9ef25987283f3e35f9f457c5a8b04e8ff506851d068ae1b0ff35ad2cd 7a1257577ef572707447108a254387944435ae9e37eee8b92ac3b21164599e0f 57bb7764c06e796b8594ef58c605ea682790abf86cad7c3fbb6842f18c70cdd7 1358110fd9c8fca453bfe9f048ce071eaf67dd7f1cce4f4d52e9cad916554c03 107 513af6a58e3466c8545e650e4bbb7a6e95a7596a8651cf3742291ccfbe21a909321081dc89d0f26b1815c04c437d304e03629370974f109a536237ab3764db0491c8251627f14250e62c371c5037eeff2b264ad4b720ace967dcd3fd7a0bf70ce9f0910bbd16387cbdf2927bab2f77859d94c5988b6d740d2315f9823d987d00b4dda02907ca773852999cdddaa3e74069aba75eabf06602ed315c341993d3090dc2b077196cecc070d99f374f271535cddbcc4de93addcedb3ad21d370359084bdd3df0b5ec967e2684c24dba4e50fc38a6d14aa8fa4490341b4c993824b402ca3313022f243268d53a5628b894cea7e8021ce4312717d649241319f04fe90a5e91f8ad38e9795bed6536655af386e299b45e7afc3198b090d4d04ef203cf09ff64995ebacf67b4f40b6cd16f023c2836b72e30700fc9bd276163227fd1aa0062fe4f494a855aff9fee649872bd75d4a254c1a1849a0f6792ecbee041ddb60feefbe60689e883ce19568ede10a402d483e1a0b4915534811d1c778f43195d0fb8f42600e9bc83a81a88b36f55fc966fbd86dfc2b8b9876811c36d830c29a606e6f79f67842ec1eda59a530180eff96872eed57d50d5c223d7b10b07d70ed702a9e7612b81bc298554a16b86ea9fbf491f0d03ec4c63e9d88570d10ce78e6600adcf7ee7d949cb8a51277f7aee1f9925c1327870161ee54de401a89b0e54e30bfddffe9f5a45e8e5ce2c406d8251f8ee8519c0cd949f189e2a805c8681e05808ccde4e1f20d48efacb9f407bcc2f30130e0d94add8c89aa02badb1463560ff00aa5faa03df299ae067bf972a1910c7ac2273281b3cdaa76263eea27f432d710b206c19c819848bc0293a4f1b57efb5c5d14cd075772c3e2c0f3bc86551137c062c9588a7e2f98bb2f6328cda55577be501450a737ecae4155d031b5b4c616a09e4b596583962a7ec631e28c49e4da6c7c6d45260d74f128ed7364a54fe82b205ae56b8c6fd079cac3886abd2260aa96ea1850320c3eb90c90e52b79d4bfd4506417b8cb3335540665a6c35131f5fa5695a6ba89e821ee622419f9c3448172906ab19c61f2f190166419a79a00020691da7eba2414531c5d94f6c2b9eec972d044b85f586e75ef500d84accfba411397d141b5c0898dd0b5f4e240106e4b01901ec315d143fee6cb7ef1129cd814d4baacd49e6ad380c58bce567209ab449af03e7a1d392ea99c810ebcf757915f601383fdcda4ea584a05e0b6085fec3305e0ff11e11e298e7bd2db47d8c40558bb3568fba5503703222b8947ca69b8c63300c72e257655b8a905cbbbac6fe9646c61fa59193358037201064e84ed8ba6af408aa9bf4eefe93893d7190153524640d8ed37adb397f0b14067dd1b1f98cd65b0898cbeb0cf2a32b2c95ecca2a1b454469d6d46d03c4c4ea25b8df0a9faa8652065e53f66f5d597d4c467651826b72d5e391c7066a6559375271d7fa6f12ceca0be2af57575eb9d729185ee66d07072507f37e84f20954d722402f3d6a88418704d78ed32097d3a1868f3dd38b1690c6dccfe7c18085626dffd8899e860f19ee07d8650453643ba6728997c9228077e63225ff99019d6645fbcab469039e5a1a07c63e611ab552b6ddd6d6bcacf5bbdcfa08a2a0a02d11ac2ee35dbccfedb46c0c1022ff7873a3a3ce1cbb5c7633005f85c352ebe3fa1e6aeca55564334b776f0e75bac8f1366d8debb23d36d306a47a6c4c1a5e6caba7d07d0c07fb7c90729401d59bdaf85069f33765a1a6fa2f8a44b4c6434d6802d94c8aa78d1529ed5ce208a28a7001e1be3ef09b597fad5bbeffa10cca5871ab50797bf58bd31425d40e05cc7035ebcc23cd214f9a0882016a798cf99473f1a63bc1d650f5da3bd2211107779497a9ddc7bf0801413e600fe02c520cc9647dc48917bd2e0d4c6514d678071415954a00064f863c6ef5981bad9a0361f77d0920616150c67c9db21b5f7601af40b4432d6ffa8df4a1a1a421e0b90dc29d10ecd50821235fcf8d0077da0f06313ba80169ea4fac296376a43ce092d73d597292548e3c9f0cdba6daa27c230453b4c83109c9a38b468a99185261adef5f60c4521e168bc092108abd38531308548187595217a1b1bf20d39b0add80fe3513a1ca2d4ae118f69dc8c2433b230583783c168825bd87feb84a40cdb826a66d85ce7ff06ae07b828e315da385a903ab156ad4c68ccddf1cee86e01c9b7c0144b311dc09737d57089cdebaaf7905056e809f18ee6130f241ef59ebd6252fbbcc1048efba218c877c1a55ac7945640671e0ebd27ecab1ceba6501b8878c9a7c77ab06704d665cad597f0a4ad6bc4e046bd3a59fbace06d3f1067b18307d42b278c6ddb961ff168c205c0f4f872dd10fa077b7daa4fc25e2bf234c1d94848689cf4febeb7dd0817d56bfbd034524590d3cd69e780fca7f49ba6ceb76e8c1889a3c2cbbb0762bc8b434854c0ffdfe04085adc5d7fd8341e1d3f5ecfbbdab41cd4c80c72b3c6dcd8ea9630c2221c0be80795e46530e21a828f26cb0fa55880c127b059b968d910dcfb59b044176d82ca0f2c67ff28e56218d44896a861228e769cf2616d0b1ef07a598cd8a940ac4f4f05d62461c9c14241b9f5072490b9bd09a4e95b9f3e26afee603ea6a4ec95dded0f1a2538b0efcff1ec808e73669c36df0bb9de2a7b25470b28580807fd7b685d0e1cedc076ac99dcbb166c2349a6046c4d3e8aa7ccad710a15d6f7ddc461b7710182402da2d909cf2eee7427ab38b0cdcc9505928a76a2ece24261b9e47ffdd60c824e4ec14caa27c5f185878a5b5832bee3cb90b8966f08e1df25d3913c72c505d5936b43051cba251785724f3f21a114e0f184d3ecf62807260b2ac86fa8840f4f0861554966445394c4082905e5d8da75a3f1e068366e98312088a93e111602ae3bf228c29390ee8aa0706245750336bf77ae40935c24d92e5c4815cc36560d7926e77238bb7aa2605ccfcf4d2399d36d9c0e9b8c1b9e973efba8e1fbf0c502c6964a26ba707ba9e743c5f05dcffd4f2f13b2bf187cb12f92a2a96c68be9506b79903e78dbc97b451f113f9827377a33f96a89e05cac3d5d7b9e2f3a68e610dba78a42da14b4ae6d4de224f535933875e98cac72a322d83897a46de2601a70a0935b938a07b2f1b3c3229b8c213d7a8454645de3b4c0abea05b177cb346520b4b57ab4dbd112c902c295d5e9c70caece6e848c26250e1bde26147370089a1028a385f4cbcf446f2e4eb50a640a6f754cdde3154066d657939d89560173120045229b5ad986b8da057649afadc8e7d32a01974e40ac0aae49b81f823dc3fbb0fcaad924dfd5d020df02dea72c5d9d6d4e1301f7c9031ea2115e88003b210b60f0e1557463125960487477583bf42678c1e36b5cc21a57f562a42e8759d2f06098bd1a87edd22860919dabd94a782a2edd71dd92b90e672243c8ee039d6498b071efdde3575f9fdf02edbbaf1b7e4543814aa416e4005d3367dba7777f05494083f0810582d9b2ade551ff4408c94f95598164210037884811d6bb62f7ce8520bfdb65bbf538c332c39f64ccbe47526d3d525a4e5e8418660be5a68c29308660cbfc3728d762977266701f873128e8c0a1be969c1bf3a6d0146b76d79d6bfd70940917542a0807e6ae41122e41568e9defb378aa97e81563357a811ade702d60adf978f3cbaaa5281b50dc36f6cbaf422dd3782fd2fb6ceea22dfc1daa58df00be4590cf1ae0fbdb601913511ba4001340c859bdea4c27b2019534f3bed911c0ba285b4c2e86cb7bb6d7a63d42225082ab086da5330ffdc31c7110cd803fffa05a67f387eed0e2c8ad597bc70dbc6256581a71fc783c6a46482aa337e19a18007c04f68c0287b8d67bff5d2df2328bd990afc5f06ba5bf1860f0f4b367464a400bf9254a3cea617f52c0914ab8c55b3ca424797fbef9dec1b1968f8d3be700d044c01602a7fa630cb1333d93bbb46a06bacf33b41fd9536f75c9e2cab52a99e074bb54808ce4936be1e834caccfc22f1b6fe95ca3dc9fe61110d7044b90dd560e7983cca9680c838d16ace80671ff7a8187996ab3ba728967f0be634ae4452905ea248df97cbecae786d8de14787c6d9bb50cfbf0a0941e181d2f8b2988538d080196b32319c11afa12a1fd670dbe1da4da1d512f16163c1cc24c81a2a683e109c0855489e7339e0c02501454958273b551db94e2416e30585059f36f7abe75060b55f4195ead79c0b47ad74b3358a05f4b8f48dae88d363aaaafdc639ee36c000b634b766f638a92137dc1bd35e515f4faa738285f6e62aee8e1f0b479172b099dd621fbe820165aca0c4cab402cde02666486f51a137b8c9b5bddf4c1a70c06e3f7f2fd618b0223788db4958f5ee3d034c720b08df79b189561e97d10d47105798bb0b105c5e4ca6669cd74886cf41542419b4012567fdd220d488c4bf6d30d8c8682347026a1aac889c74c31a6c23287ab862f7174ca0b95982fbf465d810755724204c9f242eaa8574afa905861933721bf29db791fd5405fde784b506502780d3f92cac1621d3a78edd3027a191759792ed3e2c3346132892040a1f48b01cae02f2fc732fc280cfd11f7307020bdc5bf3fad212919d49cdfa886eb104c0c914f91ae618347b43ea84a7dabdb4673f9a779e61137640c8581552e5bc14f0dc71b08f4ae16ae354b00939ff9b9a934a96872c4ac5752f0a4558322364efb08a8d6e8d473a28efcc482b5ecb8e82fae20ff6dba6be658e31a1ae789de6e6702f5bcdd837241599f6b674bdd17e07c1b5bd3a9f49b8ee4e8a071a1f3049fd5095f799898915b64bdf7b95bf6107af49108e37dfc27f5b97f9dbb97d36cf39605a870cf8ab5b2d6355c39ec8d707fc4e0be499c743d7ccc657a3b6abe096b7a0f11cabea39c3a61cb1a42c88d3bc36d26206b13d7c53e497726e65f454f18ae06acd7ebf0d8bb2f63ae1537373ce69ed9c65b4c46b4d582cd5471dcc9d285d504fb0a8063614fc87335ef44f77020a158b53097d72ee85b19239fb866aa86150ae870cd6c1f8bb86d443111d4248b945eebfe6246e3cf17fd5b13fee1ff35b50eb5f58f2c8a36c13e8447075929ce82e509ed19e63d347c144a2dbce87d33e40bb53e7cc2a31154de4ec5ae76146db2c3ae5bc8b53a472625a047b986ec305007ace4e9309794e215a708dd43932692dcc6364c5f94961221fa978ceab4725c004925f96dc6405ee85d0f7722b3075360f2aa08994947add14ce08ce2cf69d4043db4c8dac58fa3e3e13a80e9e1087cea9adb228b87b40922e8bf626b50a531056b7c29a9dbc7f2c3c34cafda827cfb8d1a29608f96b629bdc612ba08d3c1f407b769ab8f820adca00226bf94f10572c09c16dabef485574b27d4a592302ba40ecefdf9e16472596adddd35539fc41e042574071fd579ab487ab58d4fd8d8b80673e3809fb09e00ab1cdff8d628df800723db33095e9644ea0b078848051a6c0815a597990c66ed58a49c1a882f6fb98beb92c5a4f95263f99acbaafb310ea10eb572d3e7fa254af28cba87fc73d12696d52a9666e1d74b2618c61f61427e4e0ab06a53fc1aa297e1c1cc97b85b3bf0a76e1ea2d84d46a7929cd9c33f4ee5220a689c0b99f1b77bb677a89d4919f85e152302050ca441234d6668294e8554bf0bf05c12a024dad03956c3e71b77679dfe44e049f105dc37be6f07f7ce034d8a038cea4756c5574ab2b08af331da602b123e4c48ec5fbc79a1e1619de988bece0ebc8d4699a8342d74aa51de0297ae4c0bc372ac8d5ddf682cb6e8c575d9ed7407db7c382dc2fe7d005e7f28b64131183dbafe80f016fee800f8154ea6fddfb10d071e6c4844fb93ab55b8216d67c329ecba25361f54ce5f129ca7d95af68f5907c7dd785f2d44b735078d9d85c23d24fefc3c2fbfb73428b37065ed2a37e4140745810f5d09c84029572ed5808d5328bf647a9267493fe6bb986d5dbdab587e08c82f7d0541f61927688af3640983368df5fc4dd7f12406f526622688477c5a0a7a999bd74539b9d8394039574adc34481b8baa55194ae8ba963c7aae52f92809cf7c4e08bf94fcf0519aae4b0d9018de1c5d54b74093fad40a1e379c6d8bad01524c0a1c6140b8d0980c6cf202bb9600dfa914e025fe1e60c7a4e81af8bd3b05c3892b87bb58aeaaf3664d01e6cad4c1e699f50842b2235c94877be821f6af08ec653bdfaa75288bd30eb8951ea1d3f1c07e6d95e153185a0183b9519d0e690f5226a0abebd8426f3c8b81a2ef59adabb9acd956fbfdf1687c2b8858d4624707c642a5b942c628a46be04015703a0ecc6160b94a68ac59eb428c7e730c04410240a1dfc9c2d4f86ff0b515fa433e607ea565f3316e356867dd6f284dba6ef700b7bf16825d6e87ae1da1d260421ca3a2402da69511cd4b55dc0e276b4ca61504c483e022b236f9ccfa169e20c7b799631a1a8144245453b8dfd0c415cf5c0301d7c954434150048d2db19e665c4eea2620bd8c92eb4a6f0de4be567b2621670ecf253972dc86805691f520559edeaa18a3158c145f73a4174b9c5e14b9139e07fc680cf861aab7e581ddeadc5bfc25f3abdfef060341138449aeaa4bf8844c010c8aa2db9345a4673488ada9b03c0732d796f74fe391ee337b9d391d126c45035a9c6285292c9dbc262c43d6ea067ad9b78af6ea05d7e372a0c3395199fa300669de109c9b3a4f73d6feead31dfd04aff779d51afc58815c3eaea53fc631220257a74a0e20cd18f75c1e816fdf701181f589ff711207ea6d31d8214d2459fd0be8244fe07792aeb38a23d267cb90f0b62f871d63010ff351804cee6a4245c009d5559882150c1d490fd72c5ceafadb96518bb31dcd23ec7b3e67110e815ba905f8ba7354b08e9a9442552637d6196ea82d89d85c55f8a2aba141883e6dbf22043fce50360c6841f821550820e178d7aa65044cf8df8d2e3ed0165ec0f17c280d55ea15df2f7591c9b9b5430bc48154966caa556b124e9c82a259b54417afca04024a2d4a8404b72b42ed3aa8a0d58681ded9b4c79f9e2f7b0f65fc0f067c290ed7a813cc3ccacbc6ad3b3beff2e5db5923245ab9ce5980e04fec4afcebc3e5086db8917d93c4c36ea6dd8fb832b42ce017d242979f9622f4dfb56f19b710c50c86fee367f08ae398fa12350cf6ea9e3f02304ea51a4480f0b6e5db879912d70a5083d7fbfa72d9c2312282dcd14bf6d7df02d76217a57057c6c018f00b720406d586aea6b712aed2153b71495f6788566efd13ef83af4b97703852722696450aa5c95eeaf7d233e09a7494a622e976a36b2024152e3d2550e3c16481cfa51f0a0251dce06d84a8356c4f44ec2aac2ec3a6e318f91154262b9a66cc83d4524e039bf7661be91a8a74ee96e6667db9ba9b5a5b77fb3fe01c942441027e6cdd010ca2f460d1a7b80b60fe866bc4de84d14891360afc0ebac9b712f851a420b2510c8f6932c05d2664e86ef37604ce4095a2c24e4920298e31188f0b22621b7b010e41267131b3f298f2d620318611d41836ff7f2a9c5bf12ebd55d2bb8b53706a08b751a484c683ae034c334c912cbfc31f06cd1492b03210ada53fc03c871cb6020548c5e502ac55873bc1234ba8424057407f418de57b5e1e65e65e84befa2b071ebf7b5b205791a716c24d60fd7165e25ebe34e523eefbd6a7dd55e6334d0209644f2a77e4326dc4d650e42e2734ec12f943c5554d480e206d4c02b326ca3401cc34f1812ec0c138a8a1adc4ff3f0900d0a6e3ac781e514739816fd9b3ebaa01a043d3722064168745ed1e7abd00d13db2f817f341699e1d95a057020c9c9a0c8471f8be4d78c21e0b8fcc4d6988683e399cbc46a77460f899d698e2769ada0ed6304f05cca2cd8d492107ce32328f6454e150e1c568b9cb9ae76e9fcd74da0f7bcd4fa301d47e6ceeb64b513d203cfec1a14b1b0ce766ca2b7b76344d01e00328dc94f66262f4d4e9f05d7ed3f631b71980242a3fc3390f5b2a17931cf0e6020dd405ab2f6dba054f20c15ae5b2530e20fc9d3b5cff6ae03bb2099ad8b6650d47e551e29840c7a3af5592b12bee0ec826c88743cf17319b9237933544fc30040f467150422d493469a8bc7b290419a3b5ac0e12dd82b185a3d689b51308d20660471b6e27392468e6bdfbe1c8e97e71d28f217f4766b392e7966ff2e734ed05e9434ed3865228e9bb974410a30a4db297c1bf6acd48116b9ba6c463a673ed0472ed8fe305c4da3befebf5d502f8c3cfa79ad7d88b45fa3977085332116c69066610918f4fb74eecc1befd3f2e69d3f5e198097bd0c9842a541779f92eb27506494ae483fa7afdc1191f394ed70cddcede4819039dd3d6ef388858050cadb40e5d7354ff9d1ee52674e8660b815551415dc266568213832ff3244ab70292b108d448ee52eb8b47fb5b71aa5eec54f09d595cbeb021e56baae6609348ed70d40d234d65a1bf4f409c859a5f2365083398fd5463ee536ecc9755b4754d69692505551ab8ce1f18cf3c1c176ccd3ed94c53964801cc9f45857303fbc1ee56d8ad00ba6aa5a54245715de37762ea80e11561fdab977b48f489526c7eacb11de664077c831ff5716a56dfb371a87926be80c339ec86f37bce3f4b319b339b7271f70a928ebef14e8bd021f30b9a2627ecce281a0d2c21c240231a77f0a78d8642630d5bb20dae55979d6b6551e3d8892008e2af2f4da750d9ff2bf0e097f6d0f80109fe016be02b7279117d12ac833bcf63c46bb274d71dc3582540d0264924a3ed0b88e1b27c02dc0c2c6b94a01ec02ba6ceee7c0d74cfaa0315d607f4dd38112d00ae7c1091daaadf9581a1d95e8fa16a51690ca9a32cd1067bd4bdee63cbc8f304e3cb7e2e70ea30f9cc30dba0d50c26318bbc3c4353501636a4fd092dcb52030dfb10033569457345cea511310b8ac9c3f7638dd36484040f9fd358568679af08d8c7355b9855d515f47999eab3b135b39e611f94887e1bcc278a8084b57e8e0fb2892c956ccc0e008e84e167a228508b03f49bad890e1c7ed0791cce3a7d5d00c9b20a71b62843ca34c3445aec9c6e76c4adfca122e998a82323ea609a462600cff9a28597e67d3d19a1d9ba47395286ff836bf343a042a6e3012fbf0622bb079cb5ea29833e6282fff347a12b32ccecb2a7330dbe6512be4d4203ae9ce9110de41d3681cf43d0a80fd83709028441ac63bcb940d33fb7bb0c01bcab116f2f0428eecbf87993a73bc55b93912ac8ebc23631c44a4a9006653d035d196a0a2d09dd0dfbcd4f07c56cf47da88e48c2f67d5396364920b8ea9b3ae86a7df54238077a4458cc51589ef2078b3ebe4f8b078b00c8156d637672a719edf12e5fe9ec067b2972b80ec2f9747270748f042dd2a9b2a35e96c64407b4a345b6301f590407d45d9828fd360043d9d0757b8d32a5a5fae234bb43645e5ce4d95146c910e4072b9bdf9d3f555abd7438c20821630e72a62e640a374033a971d52c8612053705262560181519e2822f9bc350514442c58b0761f7f67c5726025e23550c9da80c97ecd16e9c56a8e8e2b33d4a076973d7cab7b9c119052a20cba15f3305007e068da9c16fa464531a47021c6ed27ac7a6c28caa472a306214fd2d6bcfa9d8c50ff75521a377551480206b18183b27921dc37e27aa686b581f49b02439daf4e40cb4b73141ee0ebd6c10291285e0225d863c04cb3dbb6d4bca348beea5b16b4a0b2a6c3913903791b2c841fea4321776b647d3c367a710b68ff661de9518646b0834021bf0119e4b2e55bcf4d5e7b04626a92a3e124c8296382883ecd9a9cdc70a058760d77b227eb5cbff83c631346572a04cbf4ea5f101ec578ad598f2cc0b01396f8f7ef41ad3e6a0610436f71ce32a80d2272426a91be8b6899a4fcc6af107da520e92f43a0c0b2617918f2da88e50724a69fb8f08ec39e43ebc86355c0c071ee9deecf828f27f22c72b9dfa50a330cc16637722dfc94869c8a03395131201f61ff990e94e936579d0965a7ed235b093eb1239d9303f3216726153e4b4e90f4a864aabc64cedb7cde7309bb29e8f1679e1d35dddd89914632f28b789747f07c23604cf99a7aea96bdca25a7c0eb1048f0d0ed7c538b3ddd7b17b9d663cc806a822b1b6c20c748743511e29bd6bbb63a92905be2fcbb9cd59141cff7c001800bb621adc38dde844a40136d2e792c775833bc280c2b830b68ea2de1b8b833a07d7a7ed08645bda54ba4301f26e0f29e0576b66c854bb2b61e11f4332fcf7a90f03346f16fc29d2190bd5c3c1e5c3eacb0b1acf38a5d805901173199e6e4fc608da64284c5a840423aa43a32e39615cb717c924176b7954da847eb619fa6a6609f39281f51130ec5175209361935ad03f32f59038234b0555d87eead6fb5a2c0db639121d4e4003caf2e27058e5709f78a53f6cc4b5b0fecd7266e528f0d70e0515845c905b136b752975689bc8604a188405fed19ce6d003b829c601bb6b17020c4ed76cf1c5e2b2c13b36011f308a7cce19b2ffd8bdefd0297fdd2ed96de705e8b5e0fbdadcd83fdb76cf89c23c73b325585a17772a5bfdf8ac93b94480660c2919ea069fa4b0288669633a3d54b930f5fa395f321cccd058a2d7981253000940eb471834db32fe7700dba57426c23dabc2499ada11aa8e5bcfe568c4f5cb0b0c2a9baff4957d45964a7ec37e97450681308f270dfa347943e3691e8faf8e0ca196a02732a75d0400fee8681d2a49cf83e04b162f25bdd825fe058d4493f102a609181b56261bf5d4a195c1f14c07dadd9a9d3ad47e20fbedcca3d66a6a300528ea3d8c5f1bbf699fce60869ef4ba24c3a92952ef89b25de660884ff5145404d6e87dae6a06b41a16cc020fa0840653bc7a40cbb248c58383940856809c9e0c09add695143f7ad570b8c5190355e5ebe8b2a576b98d7968b67ea0e5df6a5803a263ad7b3a2a9d9f0e51bc97de6d7ba61410fe17652da30e76ba09048c90b20369e091ea6c9627e01d0c8eb87be56123cb8c8643ffcbeffc5bd0c10078cb950e13699713db4efca2b055c2ebf3bb08d7b1f2e6911b58668ff34e81b1e44dd2023e494438fa17cc3d7e2573149a648f81fa190ffc06b9c38a4694d49723181104520c5496eed090e0cba75fda6813b95ce5a07803e1cb7666246783ab3702e30a10bffe445304ee6250edfa9c96193f35763b9ab21eebfd78d75a146ef7b27c09e6394e928331aea229cc0957ed93bbb3828370e7276674876bcbe9a40a4a0c0f9678a22ff7a4d289555b0b3a46d0a2923b1d99d06228f0da93c15813de6cdd0a99da82ba4172a6fe8896b605e0eb8f5b156be2af8afe083258ce2a38cc263305b521b2dca996c041fe1e999884f467aaaf2e5678941074c05a7844a88f619507f49e0a88ea12128d9ff573280d65470d385a4a14c3b461257d1e6611fff34f0b5a61d745cd34f6566089203452498690faaf2392bc11c376e0078eb16d09d3003f2b9d4937fa80a9f2b41f09f0ab08d46d84dc51080639f4d8e08195b03de20b0a9db2cb9a8b33ea4bc495f90ce781563298ff78ce77bef39ea96e37d66abc0e2985c5bdfc1782d4b6a351da491ae3303ea79278d07deb9053c3ca5bcb05a00a7fda7e61e1f56bc195926b9fd767a7813b3eb0e96d3e4d8c7b44945ee58a8b0f6c421ddc255d106541ff9505fcc73ce198c5db718426d207e9965c2f665a2e0faefdcca951c06887238fe0f63c67f38d3caab59cf140942336522b7476f7670977d1d2aaf6ad40b177ecbbc3e52d4686401c4125c5fc8afb2e7fd21ebbe746050dbde8816924913ad82e86ee96e655ce994bf9303785712248812282670d0e06e4a93bef51eddb447f7a65791d64616658a5ed0db0322e0f2b24a1e1b8dcce0583e6e0f87b7f93a5c2011b65f9924f59bbcb2060a92e36923c6a9d13b2e665089eb0dc6114a685fe05c1023ae256353f7c1ee96b04a578704dcab7c5e17acb086368a420ee63ac374ce0f02dc1c185ee507dc96515cb2ad8b2460ffe6f17e6077fe1ae38602bc3ce37d402421589baff5dd56d0a0a66f3df855697f4c888c20cbc3172f2cfc795560c3e5c3823c7ef1ed9e1515ba368ebff408bf6c3371a1406255d67bc70ec69b86e9738c3c26c4967fb1efc493c8cc04bb45558a6ee8d470f4fb720eff24573dcbafb75c533b54a4729912f067a35823a56c790f457f6da08deceea2354bf5a99afa8960afcfd733d9e24dd15d4df748a24bfd11bd7461808c8f9ef61efebef8ba60a37e484ff0ef885381970d0747b10ab3e5f21f6b3f10df360511359874da7781cd6f6fddec53a4f912a724f74106e96a8b115f43346047f466110795487bfb85104501a7de6ae76784f1a1880f63d40b553e3fccae90e658ce849b4ec0008dbc5e1a2a0791a19ca0aeec6896b9e8c152ac4452d72d903ac9894a9a3049daceb988d6ca4a6808f9079b58ede63dfbc262f94531c4d2705397b08ca15958b64f52b19bf1e98ccc2326c688c10831e269303e6b22b47ca0dd0934de1902e302230a452904d545bcca1e181ba797f977ef43d8a1f9a627708e3354eab711c3da5bdeb95d32db8802d93d221e6571feac35d71c331c4aa2902ff185d232615ef6e67ea63cec0521322d7667daaca6d5fd7d2344afd79e4e407fb90e8749944eba5ea59f39414c20befedaf6c08852c54dbc22e033c98e137087d1a853b3f61a59bbcfe03f5fa54828d13208d84458ad9b0f46180179a7bcc0ae482f2e0b3c10d9b2aaf1cf665d0dcdc74b304a738638650417e6a411f05030faa75f1305409d50bfcbdfdec8fdf1dbf618a5db620a276c55e8b222240373703400f79bdf32a7f392503007743c75f513b645e9e0b1e59427a22690faa284608bfd12a949e1c3f5bb01b8d2ae604e84f2f4c5f75ae996f49bff9778622c9940c33d27fcd39d754a1c961b4dee0375cbfd42d89ce9a57efb356bbce3d5e1b2c0978894b43385366888bece77f0160fc3efe1e9b5a7570a74add6cd94cc2899501a9bc57514ac9dfa1f0f72eed1334476e7559a6c7709a2e9199df8b4e4978060e14f535bae6776868a9b2d207cbc16c1c8fcc0a72963dc4b1dfe1a3e23df8d9025fa3558683789af8d126282de4d6ca9b3f1a61644a10332fb068b34bcd9e210fe0e202e03fcd5efc4b1e77db443f75f7ab7e09cd4f111df691d71a11aa67040e993d6c61413c6a8980f15077322ae80f6a2b715b8ac75017ce5c2afddf9fab0bc535d9e90a43770669be198029c656c412c2a923483e6e6daad77344a2819a059cf8f651c1519ef1fe38b55dbd718f99195a3e36c5d1527061ac851378a3aa0dd6af9658355a1ac6c15a1e45fef3a511de69aabbd6bc083f554dc8786d5a190469d7b057fb58727fa537aeb0b5ca9efe4f5d89f210a8198e6a9081963ccc480b701c8caa3885521503c80512f575cba6494017b740b55deeb3be7c49002c3e0dc25b51b2cb9b2f89bc37baf2d71339d430b0f9f0c5c7bd4f52cf031ca74b77062d889a598f66f35ec5108185a96c839e852afc9aba532cc55bdc3b514532810caf7d4dfd2ecf2bf07aa4765266c1e7db0d7cf946425d77d918161affd5f22d02d18fba12a1f8cdc5b7b1a57515c4edbe26d3c11e386f9313458ffa8dfe11210edc973608a9b164a2fcff94fece921e7e52b69b08b16a5d79584129924e47e709 +generate_ring_signature 70b22a0dad712049354729ee250c77812c8d958133d282a7ccb5c7ce404a7b18 fe481951dcfd22fe788830a0710c2d3aed379ba59ce250ae71ea46a62487f0cf 1 00677c75a2b2cb1c5b946207d8f6a4ad98d9adacea1e5481fb84af52da4c48e5 e6bd4c1635814c70cd87d7b1e256e002a954c151ac5e0e6cbbecb0ab7cf74801 0 2d59bf4419fb732ab7ef42fb96d657b32efb1380f772e3ade4f4ecfe0aee7508595b80e87eb9415397c93bd25ad85a328cf851df9efa5b080b5563bcdb680c0f +generate_ring_signature 70c5e47ad8fea9638668fa564ba969be479001f55eadc7869b102d77b5cc5214 af2e9cbb09401113f23399722b7118d38070d67810cbae3c18e82e7b7da6f472 206 a18422fb54e5bc1a14964fcf02ea976ad907a99c9de543aaeaf998f049f92d4b b51182e7531087236c2fcd70ba1c99604a790e6543540582a638652844f962a1 6f8b2edda8e71567c9961ca07b818c8dae7288aec02c148da0bcf1fc96bdf146 7839c78aaf168c645786b1e646261a865ad44b0a83024f719271bd08e9db5cc6 664a1b716e8f6d679237984ca759520ab88db8dad87bf34d581c61137f93044e 3c3120134830ece01517323ab484002429a65eeb0bb17481bffa97774d5aee7f 933409cfefb692004ee42f1c281c0451050964c115bcd81f79dea07885f44948 ad6921f89907b538f3f08e34c1d253cb0d5b8ff668f335a9cc6e718e9964d170 1c2aa68c5a31e9fe7bbb8623570e67bab36522659cd88321c3f1f1dc468cd8a5 66078deab22c8b165e30dbcdf5b9ffd5734f7df003ca3fd515e535107e0deb0c 4330428b7fd83c847e0949054d66632dbb03bf17f9255126175d6d551b8acfae c6a01a0bf78fa2b335f0d5eba32fb0fed7a5453ecc58042f97a57abb4ab93768 36637941f031cf30f9abad0afa6ac9df869c4dc7239035f00b2536c83eb07f6e e582018b9874cb88b09f9e30ec9b471cd154ffe4b79685342f4959c653c7e30e 9d988d6cbacba45ce8492043930ada21ee880e0f9f7c2bcfe34a978787b7317b be59db2de9e9c18d852a319b8021db050c8684e9b4fd27cdcc70d7972f262235 701f1b7057adb0d1a917d09f9703ca267c6523a15a42d4b2903d1c68bc9dbdf3 ccd77941930d74002e7be55e8cf6b51b2efbb534250352f9841cab4b09d6101a 9bb62944367b74b680de5a491449c5f4c89922e21999e4749c63bddb96757b45 d4f1497d5e1602dc78b67cc2410369ca0b65ca3f43269d48a505f35794abb7a8 545c4f9c95f6387f51da3938bf05d6e1dfe24ce7f47d00673047c6d15b775b85 9e16b849e343e81d0a8e4856e5b61f24e5839b3aae6e3bed70218a831b7ae4b9 6b85c3a6f57abef1ee42b1929198b80bcfd590d2927465bf86a708a8d8935016 45702a3b1ea9f88fa318ca774673c9f5305b70f81eabb243ebc51a4d456a39ff 14e17ab717131d76747f7f89529456ed4b7e0b4bfdbefa66b479a1cdfc2cf1c8 b28bbaebe6e5a2082179a5d40f82b858120207ca642c4bd208f86d1981e968ac fde5f21d0002ee5fb68b31f336de025dca70152f8fefc8c96d9369c8657bb45f 6b6250e0a9e114274c470d03b3a09adb267eddd060fd7180a3d59f2b4c84a255 3f912637b519de978a550c9ce554c4cd8aea77b7c67bbb4b61b7d35dfcd6cfe4 2030f7603dea048af9075f8d5f94503afc5e9de977d18606915200f186c7cc91 b243f8f735967e6d2fef727ce4ddbb07260033eb06e22b2c2a6e7c573ea8b957 a4d61eeda78d420b95dff8eafe85b94c4876872f1da29b344d213ceefc4913d0 c6f13c6b465dfac7794fdc9b025461ee81a20a5e12aa1bec8169cfe89c66ef29 a4653ef4b4897b15a9842bff5c3dc1511ee1fd1a4709eb9bc11d479628b5a49b c5b6f5f523e94d64365318fca8eec9f9b69d7517b9d0516273478024c07a552e f9e16f2e35b355a188119e38acf7bc16afc4e0e239fdaa97dc487b9789ad2093 8e32ed09461857c41eee4eb6f4697107373ac5bfd404b2aac521aba53c1e4606 da10a8ca7ec34b14f75c82fda8a295339db1a95dc0ce4d51c92dade911a7118e 00ba18bc2201748eb0ac8a35142ef36a1f054f45cf328ce6d4c3a7399434b51c 77e93d9c6e4d0fa69e03244504cf715ccb6e1771a68c5a4bd01e7a7ce1e89ba3 cdfdff3ba97751f3181e617d7303bf4d8dcd5163bcc40af5390ee071a729370f 36e2b4cfaa03c516f3833c40d9d8ed3e5f123f81fa878aa7f56ee21c687a1c2d b978726e14c14fd17ed98d7124feeae05714a8109e1dbc14f503a7f04178ac0c 29dcd31fd684e980ae3fc46e5da92f7f5e78babdb806087ca36ad8703734af60 c1c96cbb9e90a08dafab66240ec2a427c9427dd6cbe2c649aadddfe2f2cac4d5 ddf16af1d9f17774b2d18a01f21633c88e676729fb92ad1ba2f5a6e4515faf3e 7f3bfe385a2aa865c30d151d1d70f7780b9404c3ce0b80cd8d76ae0bfa2d48c2 33cd6755c2a765f34711898c5cdcaa2ab13ccb4035809cc714b8ff1b49e312db 6a9c43c587cbc9040a1bbbb5ee5b31b5fb15c8e8bcad62df9ee4234c0137b330 ed1e2acb487769fcdabedc3a39a4a33f00689ba64d2853c247f1a82ab5d9c900 a7d0aed414d50b92555e68b1627c84600850b2f67023eb90124900fb54dda7e1 9c6072d044134b540033a836fd2cc23887a8a82559355d7e05934c46257ddfca ff51af4f58762907aa34f99131a60a7d303391b059d05fae1d4d4e52e9a7ee12 ef073664eff8f23d2db789333d15a35901822b75146bc40e6a9a60bc348b0f43 b20fc9ed263e55e0d3b17ee113d43547e373cdd165339861d1a5f00824954bf9 da9614943a2b671472b15a1da5689b2a22503e468857e9fcd5a80c8fa0616927 b1d8c70e8927f0a0949c7ccabe0f8420c7ed3db8d0fdef72cfae6c34ce3c236b d2229f0f33a9fa68062a177416c13ec529f36dc95429c6b3e2030e7998137076 1cd7d9d9e748868bc060399946dc24d156a1b392d6894bc1ecdc54874eb26d64 870f6592e775e7787cc3141ec39a4bf8fc40216d768b215ed2c37c020663f568 c7ccdd2c40f607a04ea79b14cc3f0e1087c1c1aec9cba9be3e9a040153878cd1 4efb40425203e4db182ce267e1ce8f9fddcc7dea9c231875dd2b477f6160f93c c77b8ff4f3990a4a716d9ce40d9dea47d675d4e2e8032eb4e158e71e22b593fa fafea62add24d9bfe2c5678c3dc32c3460686350cac842c68ee8c9dce4befd5a 0d9d2879be4d5c54549a652a0332937b19a171d08b87355a057c155a49dd3511 7d37429fbd0fe2b2188a93c537c7e55283ef4fccf2ef28dbf393039edae68d1c 9647f768f127751f8d2e8df5bdfcfe0b50ab08d002b859a36be77319d2f626b2 25a2befe5ecd5c5afcbee35e708c513e9980d217b9982a894decf8e723f4267c 49fb16a530ab7e69538cd98e63e69dc602ecf3422f854d0bd9dc0c56a6fe435e 9a4cc03169cccbe20d82c8d1c88cdad2c0e16bb32c22fed4a5325ba24c5da531 92ad7fd060ff5e009df4146670aa6f3c48add5eb9201ae12c3545334efc68d8c 5508d45bb35097749c0bddd3041a15f3f30a73f8d8e6bc26edca97d2b3ed8eb3 085d6e6167b1711a5f0246198a0ce033445c56c308caf2ffb67ed4bf492a760e 814453420ac7935b45302b60a76d60ceb3d875e27d84181cd995ab0cf7c194a4 66a3b5485bdc1fe37020e728315e4952d501260adcfa287640a15e4ff29934bc 7d3202c71e8352547fef9f2effa942969472ba6b2b711685f1e7ddf767bde373 c603687740f6353258d1563ed82e5e72b7ef7738425b829089e044312668092f 78a2b79ae83a3be22e894c61f9dd9944816749201ebede34760f0d97bea2d29d 77915a974635dc324949da90d5a6414a9abfff9c6a1fd2de2397ad515ed1ec4d 394e0b6cb9bca29f0889e679730af807cc382f846291fecc23ef891bf4303352 03bf7c7d9e5f15da8d8f4d8c8242eb7d0f8173f66c9a709273e1803a073e7c0f 885a745d8efe981be6a9aa5eba6b24b23032229968d62ba2f680a437051957e4 bbbbcf28ff988f39a47cb062cebac6a1ca52cca0b7553f1e64503c9508ee27e6 e4253508f5c9313bb1519bae17f58c685d49e4194ea7b369ad0e079878d253be 33e5fd5640355e45d35e4dd7f1e8e7cfa2998a9ef48c9c887fc31046881663f7 8aab3224dd2af87ddcb5831c1282df4fd90b353f4269d4da50252aba203d19d4 be6533d22fa31ffe42c80e1a1eb71d65bb27a8e63c7f382d1a00c254dcd986f8 9c0652aa08322b9db87e6b8bea6868994d9ac10fb89a5c1fd79e6cf05e4f451d 99c615eab0941b915fcdd01beba0f79d841455986f64b211a74631c04adc45f0 eb7436280e32dd1c1fd11ec57d44e4b960630debe8fd3fe9b16f7e25455153b3 dab838aa3a6646ae8523bc8e612c5f76bb5cd21bae09af8ae035434a9545e1bc 6b0f31df949cbd288c5d24063851ff1c107938cba425be209728e09dbaad55bf 83eb14b50510e48cb3f336fc4aa0003c1fd2dff27e26484c9e3cdaae21e0f73a 37be5905a9f43cd4e56d974dcfd016461c3d066d3fb227d6411e942705892208 53963e49426946c393d7051247a746783821d70b04889a094a5c99f0107a48fa 3797c08b0780ab73b9f4897a12174a42871968f024f767ad713f8a7c35995b5e 35f08b38741b662a557627dbb793e4ddab03a144afe29f15d2582f528e3f54a9 34087c19447afa9ebfba8b6312969741fa38dce9a3c52294c08d949180cc79e4 7352d684d1137c23c8d55ff9c01d6dac19ab3d6b8f8a30ebf5f9789920e5c3b1 d20ac3c612b2b275c0c708040418562f80ec07fa66d5b8bb166d115e059421d1 b34a94287b0b92f980fdca1985f12feffbc33e22194cf83f7c64f9db3959d810 b00a64ca8cd8d6dd32d2e23e22fcbbda2c979e3a25e095d9bc984b75e29263ff 88905bf24369828cb2d7789ede9efa19100e1de11fb23fff84c5f919caf1b200 f550c0946b5bd38adf6cb83ee5f66a33f6df9a352920a0608cd6973294b88591 b84f4771e6e6bbfde0ba6380d7b0adfd745782a79c665ef158b35f30c3f2aeb1 6125547278feb8959d7b44022834dcefacaee1821a2b9ad98072409fdd1fc5a4 2bca5c5a2f52ddf22fb94c1ed7f094beedec8423c2d908530d56bdc6dd8b33f7 d122a98f60cbfc9afb08c4a3665a4297bea2e28e1aa14248e534792ac9be9754 0cda988e49b35ca39b860348c499ace34a1cedef1fe980bd791e85cc9a3eeaae 50405db106877d4f79bba49df0d00186a34ba02918f38d10a6772a08516f358c db86f45ea5f440499c1fcbddb9e094ec839219d90ff65ec5db7f00e401f294aa f2b186741767357374da23c9c787b00f7715f6ddd2bc13f4ce0c7fd8af871af9 45dcbdacb01ebee6cdb99b6bf299a327d7600f911eb178b6b040e427045893a5 7c665eb4e236b8fc0df26b4e7006ea202158ffcde5bcb01bdc76955332dc4612 e5c13f2bf51221881634a0b3be87f9bd3b77ca6fc5190ba73496de2025d9e9d3 0f5d6fed8deb031948aa27118f24575d129130cf4d54e8c03bdd5b403077b9bc f5f83a10c8257b8571056cf96b205d6e29ae49a045165f9e81661ea60d210b46 04f5cb095be125daa3ad6f020c25bc4eb60fc210c3c55ea6975579c57704e006 310a935599ac84e860c339e951c795d560a8ec6d0a9915e36f54bf7476bcf7a5 02e7263c5f19528ab4807e5cb0de10f754189d00768dfbd2ef200aa1ae8bb2f3 9e7512f100cd122c07927b9797b694e4829ecea344c5aab64c31e2dd4fcd1f4c d5882dbd1118a46af3c624b569edb0f66d6c7eebbbc822a09e74210605d05858 02fa26513c2e35299ec5634188849a3c7876f283d8e6d95875184dcfe90f928c 7c1af6f4bfe0fd44c10c6e17382585eb1f6f6e1c0c0774fe66517839b4e74a69 ee9ccd0b683adee6b6c99eb80bfc58d50ee650f2089b23aad6a53d1514204d3c 7a61e0013420f41c550184125d3810897caee0c1cdb035921461d30c070f5c44 5a3b4acb99a292959c09c3bc164aa35b8cfcd80e8dd1e5a0ac18b4b20c1f7beb bfccdcc76e71a16d7cb5cd68daf3c83ea71ff3ded30cefc9a574d75cd7ed3cd4 0d37450354f70f3421920262eedbb2388b4b3025fa7b7872045e108cfe506a69 7769a6ff5204841123e2f786b9c438157a68763baa0ef3b911b1918dfc908fdb 0281057269fd5c1792dafeb5dc50f5fffc205ef14b1a1b495335d41fe9833641 eb74bddbde03604204f8d59400fe0977d2fadbc4591d25092dd8507ff1ca0441 4984c0958c38d0bf7db3e714963b7ae2be3f14e4247aaf8625a1206bfcff624e 416cc5e0618e97a86a868b745b730cf5082736b28f158a15fe97d46dd18943d7 c0334b9b1bf615d4e50d93c5cd68c004f616c96448640f96abf15a05f259b6f0 72228197fbf42e0bc7fb85daef82dbe1f5e2dd7b173e80b590bc6cf985d5a065 74d54c40ba88a6e7e407696c81045f77b7ca443b5f676f9e7ed2133004c220d1 da36cc9ea4368c90ccbb962bb33c447d7f1c57c6b5f0073f1bc1f453a58a51a3 29346ae924c2c641fddc37b5db1a1cd7d8e8dc6c10f397ac1e4296fc50f957e4 8ad915dcc38e22bbe3808ddd979703b55641e5e082d922ddf95eb55bc1dd1c99 f9602f4dc07dbcae954cb895a266f64f0ae8067aa0de93c828b0b63ef77b1286 127806dd2c84355c8f15d5542dbca5d2f545bf7aeb97da34d09ee353c18df7b4 4808e46928e4e630867cb664a2a594e847858220ca93bfb33e06ebb991816f60 f45ea82edbdbb2b01bf809edd7ed8c7b5d5bcd610eea3e3e65fd3d2d0813e738 b9cfcc23cc02517f75dd3ba4f05fc727681786f67e6cf81edb3bd39e945bce60 e1f5bdd3eb6c2b9315ebc2fc8a2265b6103a68a966992ffc100e00a6bfff91a9 b0fe946f3fd0a6f8005f857f84d96a929971c37caa1b7ec7f8f76781c10f7659 a0f943eaa5354a75121d68f221d7f4fd05820d142c52ba0e613ce40a94ad410a fd4885348d62e21aa70db54056909d38d6a0434958a88bba1b00bde9b5d9a68a 81f0f73e215de76d5d9395ece7e348290fc38c254660d07e5bc1ee3af399c349 6299a39b5110643b1ca175cb95efa2384e6ef5b097e104d538f791b61c934039 7107d2209213b68af9ddf368bc4cb14a7eb4a97c2d12cb016fc4829df353b976 26e8f097cb2958051fab454439aa1dedb6929a218d6ebc0ad71ed240288d5848 03c22c8c6e0d2b2566d02486f8d281d47757cfb55aaddf6e9ce709d0b434bdd3 8f0851c2b5c3ca4878ad6c9b7bc5d0961d2c10181b346bd04024a1c3c01ca783 49ea1b8ca3b5ff382ae05817952efe5b1e492dfad8864520909211db36d9a3a7 4b4077f01a37c8c41d0a841b197f90bd81b0f60e8e85ca241ebcdc75ae7ca7b0 c5094f0a05bfe6bf19b8aa4294ad8ad350c9da12fb2349e19f20fa468a8d767f 28620428aa5d407387a24846a62cfe882bc32222b1e0a11e0878e69142f927c1 469a5d58cda2b621561089a5a84923527f3a7c34d73429b32f12165453fe919c deb95037d7f978e00a400165cdcd21698a9abc5543a86a39c2a3a2a38df0147a ac3a1f62cb0e149eab665764aaed0d534c57bdcdd61badfef5e8fbbff284da4f bb95b6728b9d49af7954d46440c0a38d95f97dc319a6bc801fbbab115a9d227d 51e67336b6a0277b50c6b8c9461b570341de5c545d6ec069133fa52fe0fbe96b bf9ecee1e808820f1733fef3d8b26831fadce90ef25c2c9e69f4ae1583c2ff8d c2ccafa1afd4a0fca65c04cf04372a9949fc82e1cd44d3fb62372c4eef025d49 e6df379d0ae015a6e363eaddabc993ac719fbcbf0c426923cef3ce181bdf91b5 715a8e056a708fcc73e370b8c8189b95be07c48f029aad9d78318bb4211fafc9 33086563a891bd5405a0c4e6c823aa6caa40baae56af2987d0fd5926b7bcf92d f135dfaf3da2b5b44d02fa04f5808eb9d2f98908d5be6084694a0d0f0bef6b6e 86646a742b57067e655ae93ebb181f34b2bf68226725b7fd49b7891c5e8d3c0e 76f0c9c066cdaea4caad46ca803c9aefc3a11dc75aed472479652f6d75f9f593 4d1772db532f9da6aa39d0644867e5ef9c429cd7986f97eea7c253a0e43e8698 57bba026eab4e72dc1a9636f0c63988275e9eb38f66c56b0f6d998fc281f2f0c 628eb7273a6845f9636813f810760b69248603686f21ab695f41304a5259d7ca a83d219f94eaddaf2bbc68d387db7d477f41a6fffd90b307c45342703c987a8e 149807be6e62c586c635336a9cc8e1e12491ff04528da3ccbf4c62dd49014d72 5fced27002f066f6e03292c55c36bc9f4e5be911738f25f889f12d0ab576d690 619142a6d9c825b6b874b1619f723382fb91d1cd94d59814adb195b2df8e2afc 46a9f5f54f2c432884e00bdcf31a1f2832aa3fc08ec5d613e39be20a8e82ace7 1da5ab4a03bb087697f2149715033ecc9fa93f3503c0323f2a4763ee8c8bd51f 481a87a30c3af37b339dc69250c71ca8a922e816667443710671a80dbe52ce92 6f72c0e69adfdaf0dec11ab94da9e9607fe1af9b19d2942499f2f3b06c70ec10 3f27220ae74e591ed12f7a5e53d9899dc3016346747d8ec9fb0d8c6bbb7c2a62 7be4d47e1841078f34a8bceb4a63e3dd7d84a7a15d2180fac6c8cf9409ce02d9 4d781a55176f8de667ae70e9c1bc7cd4fd263930b82f4a4f32ee12957d19b4e1 b5df86e2b91c3dc2f216c0c9ab065ffa1ede0d6ba02fc98df834c77d65b2ee60 448250ef38aa56bbd00f29317b2a48212acd247ea64550dc411ad9b176f129de 90899eabd9f089088d271399c46d2550c63e6b3eee2ca47eb1a1b01220abdbba c3e9bce3229262c0e60a477d16d898464d78d94b5ca4ecb64f769ddf20c5c440 67ca124eedbfd419a80a46588fcda09e2f5fe336b8e69d989c210e613a82e724 f36f0c8aa0d5711221f96dc637e34e8d4cb79166136b77637401449596507b8e 5a7b4baba7c4e9e7b0bf849d2f3734a5b822f30f132d3dd1f262ed9551a2bc58 a528422be9a71e011bb84759bae4421c53e306cd112a78ea9f79f1a2b19b6c17 8a80facacc40636b9445e719bef3a4f732e26fecf9fe9754919ac27b9c53fdee f9cd67c569544c62a0c73392289fb7682d727ffd10e7a79697a4433e06470f8c de9b69ec46282341a42fbbf8de6b54a232ef50cae2ad1d774f3630e60c8eea92 929033db79ef727eb67d6dc4aeea650c01271b3d2a6873afe6e6b0bce5650cba 301ce60b3754afae20c3deb7ca76dc542dcf5e3c37650258e11f666bd9b978e1 b07597015e477302bd1f044c547f7246b74de2e4b069de91314e7023383e891c f6be00b7a0bff65e3d29bee8a690717c412bedad30eeb1b9623dbb7744fb72f6 afefd6e6e0544512a57fd39de6adedbf6d980abc65de3ec99f89ed06315ee378 43dd0a609beb44b6df8459e8dcd769d48e892897872efcdf1783a5a913f5dadb f765aea469de90af8389652bc1cd0aa52fc42e57bb8e546e1618d818128264cb 51e47a387db4adeab17ef6abacc440cea6fc47e00dd448619843ee6aca670536 b2027fd7a8e36de5a752b54332d2449ead5213aebf6c678c54c91e35e6d87fd9 fbc0102c91c3c12182445681f5f123ceebc65bed2d9932afc8a2f6fa78a04b0f 48 2281692d047d66754f0b51c4be4c173edeca1f7cadf6f4e2e4c93a52911495031c88faf5cb264423ac02309eb316b2b378ecbeca2ba385c97bf82d249706d704cd0b12a9e5804a9ad7f3614151744a12126bdf6f720dc16c5e60bcdadca7f00ef615b9c50a0a6fb224acc72cc04d3dd91372d6622023cf81a7b0d815122a680ab92390263a254424a9d30d0a58475a5e48b73538394128a66bfd944a7379b70ed5f8a69eb4f9f22f076a845e9113d8c46689235a337fb4cdcf33a2be85c3ec04da67c5d4d809a5f690c7abef43d4f8d4115b0f8503d424432b2ee26c1cbeca05621a7f2c60072e4d79e2fab3246dd26d7b4d00ec1dee1f149d3365a64cc0510caf4e6449a3c7fe5ef8e485eb5e7abd30c60965d149819ed4d172bf1b53c6ee06c10294716b69ab466964b50a18eccfc4f21a03618f305194dbd168b999a8390937b7a506aa191904fc8b55ecee44bc54fbe4598b0a47f96fbce77bb858ef600b9753cd7f97fe1cfa747a7b4e0a35d7d154f88cbb58d0f6e219cb9849ea43d102035d6ea4cfd79e8c4df0c9b0251f07882dd0bf56d845d4e77d3cb5e06cac41074eca8ca8be72041a753c682776286c0f1a5cb1e462f61c4fe34b8e1b3a5d520f6cf7db15cc7fa7147d9a4aeb9bc9a12d32967d6d731eedd9284dc356cb0f2d01a59c9d3f3fb1738dd939549acb35cdab7ec2687028b46e90384009797eeeb305ac0eaf530329635c0b3127fb9f19d8e7499618276306e2b3a529b2af617d9c02d8db455b024365ccf402d0dd052d0e783ae945edd981d9b2474b8a8ba31e880199ed518935f6f58fa8fb13626e1aa9d24e534568dd5a24084c74c39d9bd8d20b19cbce0fec136ea8f70471fbef448a1bfcc99258c7d11523094fbbc7d4bce90af19e38700a546e80b1a9c2f59c0be7947201f26f50bf8f2dcec61e9b331e1803dc0cfd5e7900b9048680f3929880bb250152e15d269f387de0a8609efed38f0cf80faa4738d2ad80e41dade9f4a10a86e2cb5c53b075c4414a5c646d64e7e40e01cbdfa9e743f7a020ee7138dc8fc3179b9953cb1e6e889632f0006bbe10bb00b7dfa2c47840936f11021dbba0b20909dab77852c7f91149e348c2cbf36a880aeb52d41fa689d20e9e693d9f3300f0e46547c63f06533f41cc84c8243ce7dc099fcb2715177e2bd057fae0f563d17daab53569be0c0835110b41ad804840d20971fa941f4eb15039725d160e085da2ed5f1e392e2464d0a02e1479cc21e3d508ad3fce67fed18525be8fe5bc1be202ecb79e7635484b35fafcbf19fe806e410a5bb070d0dc93d28bcc6c754f0a6ac66d0dee99f64bdb77abd4dfc413873a2c016aafe7abe0dd2c8b3d5314d39258d61cd6a82a3dc810462da092eca95737530780d4597c9b255564eca32c4c1296a6aff4f5a7da83b7fdcc65364845e25c4e06ed6435808edb9344e6d231d354835301f342d32446984f76a73b36c01984c8028c7002f0ed1f1c19b5972e41cac78625cbc18e6d207ee7769d955a4167ceac023dc0b85f4ea3b0d7df0925d5ab7dc79d9f862a68b49bf7c3926454da6751fe0ae558adf2c6e0f685a5f248413b31269d552b887ef939f4305cd1a0b0d72f9302b257215ba01b4ce5c4a138475d95d6ba7e16aa70ff64f680526b4f5289afd0070d8f426774567163b38b76fbdbd4cd23c363170fbe0bfda6fdba5f6b85d17705cd366946e23af146249884017d934c78aad10f4af1c782980a5067bdbfef8702092be91187b89aa2fedcceb1518f9b71210aaa487c810ee62c1f4696348596030f4895cd2d8fbc904d43dc3493a913d2fe17b897db84c180874a8a0fa4962f03d39f2b8dbde2b3c699594d83eaa986933f13ac6c6fa10b3f42b47a516892450a2f6cfedfaad75ad0f24094fec0d41f6aa7c6e5b7458ede51f0961d58a160ed0db6a7935df9d522f23268e4fe8fb500e4aece2a3d240a9cd83239d1f11f368803e2aa58163bd9fdbe880c470f633225cb64d61617cf97b017bcedfcbc6a64170e2100039fefdc23f7af3544d651daad7dc1c3baae68519a014dc737a5fc0fc30e251515605904d9129e97040c503fe92a73b3d9768571aff0c8ec8a322179e603263652ccff21c655d5a205df7dae200975ae9646ff95e1a1d913a6c74842ef0da92a1a981ddba4d5deea5a49d9a0e2e9a143e57a12e5589a1b93e6f0df5efc05c7d472f63c0a177e028f1716c9c6d3a22373d5a8eedf83dc185bc23b90426c0635116f61518ad605d53c2ce996244ed2c6a57f522040ed31aef386a1a3b3ef0e6d45be7c1be2082fd7e498825a0a8260f16f4ba6c70c9482a1b061e6cc310c0962f48d9fbda1577b892da605bccc93808771ea1d51192b309714f4f2341e1d0764b406047e1337ec83af00448df774ea0634e5dd556f20af18d69b163db9c60cba79ee212d8c54a3696646f9bf15bea4100b18170aee86bd35da56777c51e10d1ea56c440e99142cacae9bdf8e83478cf4f7d1b340932d2f816e26ea20151f01a67f139c9b861ffb300a3736d6593775dcb6a124d6b6301cef32fd21485d3f034163e355e1c237a905357f5b66347ed3e27f063f2b0b0b9ed924cb0075c6f5090d1be47f095557390873e0bd46b07d7ae94c9e8667eddb2252a57df76b3f9804b8ec8dfaa02396ed96f177bb0a41a02917428b8d601ec2d6b95e4d27e754150f2cbf42b99ca47ea9c322d10526314d565096248f202554270fa93e842628850506abb962b3101b35c8791cc806f0f075279793d207c528a6c3d6f0d3cfbe4d084e3902aed389cd0c55930341fd213d3ecc937c0a22690a8579e1724e5354e90951c5d8800df8be11c8673c1b8746ef18f33f87d284007ecea582aba0d85be30581e4187e29c2888d457b4ec0854ecdef24401115db8c16f106e07cdf427fcf092d567284f44083a7bcbd6c35eb03ab7fe90e791290d4d5c055d466aeeb2dac0d9c0e917857d695d444e202988e0e198f15f8e15ffeb7eecaac3f950405249503752d9d1b1f86077d9827edb660dde77d0d893eb025e2dffea829a510d12eb409cc44ac404f310b36af86a7f7611815231491b64bc8d2f2c3aaebf9cd736ab50147b0a8d2ff62bb9ae013b5995695d19b80397b6b4fb23446a2b34f9da2a495013a7203f86af6ee795e68ffc16ac60bbfa684ba1a5f73eb67be117788a41b0d00c3bd6fd1d8aa55b0dfb6dd1af20d9e02f8a58859002cb5c409fc82788af65702d9c12ee62845d4f3cf4992ea253e0ec0749cdb421646aa7f0b532d97d8bfd5023ad501a901d6acb77fa267b675b323c1e0e0086d9b38b909ef402ca7f94f5e0286f6cde162bbb220496f01711d1f5692b8d5f50cbcd8035706f812eacf3ea50aff453d6585a06684b181e410fe1ee6a935d1f20212e52f84d2aa1a3d2b3c1700eb739c413817378ea22fef8d031ec12157b88e973d13412c08b95c3711df570f77b99391ada37d4596bbadb80396d2e715782c014ea7cce672b6bcab8482a005d3726cc8cb2139d498a5ab05f44d6d61cb4e84570dc73c6c55658a34d77c63091feb693618eae5467d91da37e5fe68c044336c31ee89e5224e0a7a8477fa31068a6526189705ac7ae14bf99caa56262b564568e3e396715ad90e36ac1777b1037ff41ee261e4a1ed11c0b3819587523dcfd36611ae9872ad51b8506212172d049ee4a1f0a13035968eb60e4bfe87c46e1d7083a2b564962e11bf8cd790349a0e0c370320723de812873dc4ad195491310d1a877d6855414b994f7fdb6f56de0fa27677ce0980485cc189c477915b5b8c1bfebb850bba88434031bfdb29cbd10568bb1c70f25b127cf2dad52068976d99bdb46e2b349578b7e533a7d2a2fd53028ef41438439928dfcc1da355ab9c21b908c45b3e1678cdb403da9e5797d1bd090c5ca2e5a5b5a332951eb2feab1039cef63876fa208f9bc49badb1792f79c8064eb3b02ba1c662a5563e44d63c954f44d0e1f1eb86842a6fdd9b8015b67387021af5ca34f2170c85fd3ce4f26b2bd79721c13ff069ff53e6c6694c6973f22d023661f063749e120ce23800e47eebac0054d8b262248f17bb9f3437792d725d091f4f319a2f631788bf75d16f33889c502c5c51a469868ab591cae2c73834000d9f2ccc60973c99a4aaedffc0df9025eedc50e8fd3000bc51051f4b04e4eb5b0eb6560f9ac97fec4a83e36e98bd49da09afc2a464972df66320ffa5138d237c0434029e6b51d2fcae707ebff362d7ade57290c2dd591acdea5e71c1a05475b70ea7bcfad566e8b55af8687aa76b5da905b0970048b92aee41b5981ded4dc8d5006a7ce07b268ba658f6dea170062405932081c1fab6e60c1fbae67971012af6008cfba0c3ac982508986ba9a62f7bc125b8400fe2c54e4b08fa61b0a27ebe67070a800456a64222251b4e5efd4e9be2f715bdecb37b64d9c194bcabac6b01a70ed88fac5880bd593f2ad2f0de9132687ccdb7aaf6b69cae0ce88ae817cf542400dee0dba2c2dc53651eb79c894951893c3e76a05764020383b906fabc799691069f94103d9074f2f7a1ae8b369bbf532d6eef8361bcee1f482b01452ec064e40c05f39e295a074eda84b5eb646e84f09765ddf8a4770e091bda48dcfd26a85a0ab075ae6bf2231fce46d25a87e520d379da873b3bfc23620f611140b8022fc30ce73ef3378e3dfc5aef08510c39637442f9dd24c7044d44a00ff4120cd0266e0e9d63fa1720e8f6bd80b5bf3b376e9e585deb5276cafb3fec26296cdb12123c0f31cc7a09e5b2a4d5087f0287e7f53a0cf2b590fe8a96e31d7941dc41d105f20b92214b21a916c6dd7889d634d5c0f8fee2d3a307dc82eeea1c1f6606472a2e08d8d0092d118676582d44639a7dec783126eeb889bb74fc4218642808cb016a05769d0117ff78e8ceced59e8a65570f26d589efce998c4256491b86b77b2391037bcc66d903766c6e894615180370b419af30f5798921faf9707662a995b6b801e4e1e044fa5eb81ee59d70619ec428bf36ae5416b678e61f62016b9fc0c04e0417325862c9eb59b3bcc338cf9a8d639b77977e3a75b81d31f6c7ec8f47b9320d97b01f87571705eb3f3e544af04e300f2cd02e60efcece137e0aed7d19d2e00604eb7419d6d7a59cd6449c3b8cdde052cda100382e5e9014ce71763b74bf8106a0f659a8b0f03c18c2a2a51b516e8ce7fa028c30c0980c02cf2e6f0a4abba208f4d99858bda95cd632236fef30a7a94223771a91f7c79b842cb4c6917db14f0b4dc01258f1eee375c1de7f203e87d148ba893dbaf2415e7bd7412345a02c630f04778e72b1c93f5a3ab2a0355bada13ce60bf92bac252bd9f7e2208aaf3d8e092c77d4a1e7a9ce39b0434cefbf36a7efb6ab9d79fdc8abb0e43810cb75f7930c20d5ca6b6b5f83921a33d91d4836c1802a2b5973df88285aa21074158d24c500bcae16a86ef6c7aca08e6685d8a06c5db9bb30e893796a366428c81151b01a0e018d0f6ec7686819abc26ee15d646fa441981db9b0a0b97151a629590dca5000a612a24a2617927bb95c0b579eb0e383355d6b913625f90116bf1e216649040d59ee6c9f806151878117aea663053041f60618830ed344845a9abea0e57cd90c4737572fa1773f2e71746beaa3787a9efc487756f2fa3d336fdd3506af1c0a02c0bc8eba12f315926a0bb9f81927f23544c1529e58800b954f4d02426917a10af2bbf3e675c41baeb8ee6016a6885c6cc869446669a5eb0e9a0b252ada0562035379ececaa47f0f81e61fd74bd1fb378e12091fe1c8bf5c13d2d100d9a59620c35e7478f178ac8eb770488a2db4152188e05dacf8c544e4cd48d7b24b2275008986e38451610aa74f9f9e5aa366392a1789d7366de07204abb5aa274ebb8b1001e1ab30b156b3be2c74e77e47e3a1d8fd48da9ea4b4fb2acc2db2bc10e519602c850b2ef5ae991febfa7a60f83805c4aaa91f5fbac4071b3f9d62bb43847810051a04e88f96e8e259d775895d0ce6c4b0491c9856bcb1dd95cf599a895694b09f348f64c643bed85c714550aa6b134956b22f785f990dbd227e4be2d32646e0a994326eee8b82509d9bcd6db7320aa61f62cb4f2d98a48c9085c6deb96f6d508cb91ae1ca2586879def704ec86066b2cf446bc4490332a4746028788a10eff084d44ffcf25af752d22d010d3c293bf5e7961bd8fcd1872484c2bd4206793230643c13fc7aec0cb2f2b544188c505b4b35f7a111c3efc977b26e7f79284fe20093b41591fb2cd741acca1a73372b22291f1549308d02b652a4501d9043545320661d35e132677ff12b0248703307a545cb8e6475e324635609c824d1cf74bc50e33f1e855370b4cf7be8f92e9f5efd7f235670098e351b31f4bf66a6237dd3601d3cf305d2067d6056812c7d71c7809febfe24e9ef206ec37533f77dae26eb00b92b41f1bd57e194fcf21a85c6adf084ff0300e7387230975cc932aa5ed1e9f03c3bc7f5d643b93b7f4aefa2c768e4b1f9e8c45eecae224cf79efef73f533420a07305fed8c760bd5bbbd929301d43aec516f0f47483312469b24772027c11a0e021efb35fca3c8338c8bd1834df5cd9163dc6356e1a0fbd6e209140284657901a842edd438d192266db750f52de081c8afe3d2eb15ed02863fe2fef41fa035002c92322e3dc56d3be24fa75d7a43ec4cec48d75ca3a5e822ea9625a42feaf900996d37d4d41f488c263651414c5584168adcab739b52b7688a2c3510881059035447894945033fa3b2a5b6f04cc7ca4be59e7053d99ae8f7d38aec60265dbe07556e60b3fd66e879755df3f1dad0ddddc46a9da8699240db2819b5ed5aed1908e848c84cf5276d8b5df2e564ab36d5f1a9e80f847ffe9dceaa852577b53d110ab5cefa3e9ee90e72ab73775b1b7428269d171b3ad8ba6a1696a77c895b8fc90049dd1b5dd899c125486a8545d957d1b20f97e3be534f066c4661bd4da4a1bb0dc1d7a31b2a2733402919105bcd1f2310b7c1ed4bc9f2ea3ca5b05da71da82e0d749b2bf513ae3c6983691001ac60ba7a99b42cc7d5d4665a15456cde340a600c3951559e615638adbad7f9eefd6e5b97462a8f805016bd6cc28b1942b569630a5c71325e319533c92b343eaa009823f8503b2d73cb24038fee9462c55c7d920ea11b0c1fe35e0d8cf0d1c54494a50511470c991a295b8f1409fd7bc43c3c050df37179f8d27a8e8056be89f5dc6d575769a2665a11e1e5bd93f0bacdef9ed70b96c97f833342aa5c9e6464d2a559be3f480093d690004dcb2de4060999c79a086e30663e4bcae4a68ce731f408e890af7ff4a9e7f0abded0d9f1541ce7e7f80935db3ac5fd8f627687524da4868b0a9deef9eb046c476bdecc7e3f5dacaf0f0420c03e125cfc30b2558fa7ba6f6248f7c3746eb33329c772fa7ae63ef791350c95cfa856de5c30636e5d2a5b2d083e4692ae2c6e6f6526b62ea2499a7770ba03fa930941e51ee7171d234b39242dab32b7a95f28eff35b652234fbd0629080091cb3816dda3d746ce0046410fce064614ca6066273bb234772e639e7f6ff4d0f34130af8da8958233076001e84c540683d1845b82e99a98cea14136e611ee609f62b7247d849f89f9d8f99dac928a5a8744f843fe07fa4bd5e263615dff5a90e0ecfdd8feeb33180e0f72e5a687228b82e0fbab979226a0f01b53672db4a740daf6e233407840063542bbbb6fbe176fbd48da75c12a86f0f87c7915857ab6b04ce70351953dd52cddd9325b9a045f9ee0a4f8dcae5e902cc25165838df9dfe0bd79400496b81bba078a2ed8e2e4eaf612831e75b7003a0638d25ec52fefe0a0400660bbb895ffa8cfeef54bd26607e006a6539769eb7fedbecc3a44ba23aab06a893c527d0044ed859ede45adef7b2971a49838459a2188c3320c1755f80220a71b26e7f8a12e08fe0cee83fdc6f629810be178764cb1a6971fd297b9e9a5e018a97737061b5442d8e7cd9754cad2e10e603b1ff30e4255db81c1c8a62c8c900f91133d0c5686ec65379052c1bf04d61b997a217ceded857fe4756ca27c9c204eaae9417376a2727ae456952b6c77c5f38b9c92e4fd3efb869a6cdc502010b0396267d2697d38dc2c0d3f9885fb0d4379aeeac7984dcb723528c058fe7fccf0a0b2469ff87c8432d74ff080dd77539d351c7d993bf8f591629c9bbacb607080ccdd9ffdd8405dd4d9dc00ffa6ec3672a19d8f6ad2d0458eca37b2e6c7c6f89083e9aa5422f51edd7809b07cfe04e6efacc67fe42fc77787bcf1b2d59ba0d7c06859a2e4232a0171db5d55785d4b9a48fe62455761947763acdb568b2b099f007aa22f02dff0da9dd7b90862fe231b57a967ed78c686ec94e2797767b1d36db01222ebd062911c5dba991ee6faf24229925290dce2d25b3eb8b878009b5332a066ba4354a86a64ca714063bb14589b6b12c891c3532375334fe553feb4b32b6056340bb3305d8b1fbd423656b6bf75af44f3d386a3f141166bb65c566c8bf80007ee029310b82e1f2efd028caaed863b6b4c649992c5462e82ade7ce699191f06f152c4014d8f79d15e18e0f6bebb9701c14d261f3b799329066b5253cd64370af0cb6924072f3fb7dc1cd392eb78e71e33c7772ef6393563d12e73509c9c040617306dc1a88f66e3e7f988647a810efa4e4a264781504020fb8b7c4072ce8b0b89c17f947b2b17c92f71e9476244be865262ee2407fa3339ba5975ea97f98d0c883e2e7e9539a06cf25880341e885e84d572c14acfa266319b0d37ca83c5e00a1ae825930d8c9f0f6f52e475222e0190541602df549615130b9cef3867117b02a6a2195c5b439764938e418a0e08ff17ba4aecf71a15a48a3d34028c897b000fdf8d73d8977464ddda4eb7eb4768d8ac75193e56d05b6b66d16537985bfe3402cc900fccaa26b56a1edb0193f1db92dd70daff618243bd88ee1b859fc7a8fa018bfedc642ac92a75f45897d164442d937801482f835012377acdb6013e6c9607036d14fab4bd810ec7c52f3076e2c3312eae3a6c9d9455bbb5e03272f7abc805fe0c7930ff94027f0045cf34444969e84289270c63000977de2d1eccbc4c660bbea06d523eeb97cae1bcc36ad1258c23dfa3f98a15593db287f89905e587aa040d16849607f0c55658d96f82b6216a62911594347fe259b81b1707cc963bbc06a8c0a3a2667e0b011d448f931fb5351aad6dd3579578328aadb9b6e711531208de59fed8be1677896b15a46e9685fe60529f7c19c1209175c87cacf4d5ba1a0dc47ee237063d4a8275d60ca98e9e2e873094df5be087464536ceadc366e9f80a3257ef387248eb702b85ab4cff32c55c25bf52ec106c744e6f482d5431e9b709468be2303ab951539c1007988523cf47f32263347de210296975c7183848a202aa110f4d57801a1cee8b8f80809ef5a4c620e1f66b148b8445301409157ad203809df456ed951adf7e693d046b372b3a106f5d162348e290f650762d793b850109951f7d11cf72284e937ea6bb27510bac5eb19a722956917553e369e3ba21033abe573cc9ce4a7cbd71e4addc33fe2c3b434aeb3cf3911e63f6c41bbfb8cb077c52cc32506c4e4e54d2f68ce4a36639cb5b8161eda46329e0f6ff9337b8a20b4c82529001e10e9faf5520aa8a489b93f5b6b70d96e63df35c85acfa5ab48d07e161ae389dc35429a9cde17e258e7d83acf149190505d13db631216ab9e67b095e818687fe94cd4df7c6e0b0ff177d71aa27f8874f320ab0d599f635ddc0c70227fb81b00f38f23633ca1a5c43d672ae793be916ddb2a671cce2a57fbde01b0921611c08e2f0559e197b3a6a98fb2172b81e3f50b2dd9119c13a3ecd0df960010857730c8997a3839de95ce0e0681c4f0458ebb22ad2b9ee6bbbd2f6849ef206a716bffd9de5e6fb898393c3806a80c000b20069bd363d940fd3538a58bda70db5aa711c0f919b7118ea3346c2a796f41425d126a8189dad387d72bd7612150c350c51ae9446846bd499a6a1f53db916f633c273275cfb7260732a949a4e5a0141e7ebd4ed46c0db37a87a66c8ebe624ecaea0f2c3c954ef090322504544840e52857fee8bee484f3f633dfaf1aa06b2bd654f42899d551c317534b8c13597021e736bbb6329e9fb48aeea0ae1c8fb5a1e7f79f2b1e68d80412ff757c848b80483b19b8e3d350b37a140e8ac974fc6414223993d77ee9868456e09db2f9b880833519221072db682a5c6ee98b6efc523abaaf3290654a399674729d6cb2ad80fed946c2ef29c0cff0e30198fab09d6683487d1cdb7c0a26ed6685eb96ba8d50026ef657defee88d10604eb63e650dcafd8a612f507556fde6485da4691c60d0093ac5dc0c5c36aecf65b197de594b686e33cf9d3882b5586e31ff54dacd9ad00e3d57d7e9a7671f761fe15bef823b48b3de7d07e4e51a0b2a5d30bdd2fac5c01315fec3dc7ce5a002168920c597bb91a4da2024b507a05d29a75fd82def5470531c558cd909cd07ed0cbec68bd3a41d745b663f35b962bf92d1912218482da01dae9d9e7d38b5d5a6d76a8b2bbb242466d91a9b3593f4683b83f2671ab2f1302957e815c7ed1562e22fcfb19b7f59853691ee93b9fcdffa9ae42780a01f3430c0f58ba37d5ad4286c5c755048350d01d3f5f8f02ec83205d1effadad700d6b0eb93ca6c851e711f1201c4a5c60f166cd81133093409a6072437c0a9a778e910cf7c392bf13dc9475b203d02225d98220435904a145f7645532a24663efaddf05dc2bd08ca29b6cbd79308f9e79fa50938b16b91db53ccec2acca982c7960200af4b2740914d9f8cb018a451e4abe62d7834e450a8b99d16c8017a5127d2b4708bb062672f28ed0a90250c4cd754e04ef17e7956bebc857600835621a854ad506165904f04af967c5cdd86b276d908eb510c29e4b35726e40ba2660994debf70385c1995a4fe36601451926d0a76c7beabbeac83fb9e56bff487dd07840774e0e4f71a849e6bf3c91463b7f7974b10a2d227e28ade756a0178c48f60bc52d9f077ad674b8a7fc89cf6d26f14546f7373fae88cdd4e6faf8015f9ac31996fe2908a3dc9dcd66a34a025fdf4eee018de32f3bc674eda88923da8afd6744d7e02306494a919600f4805c30604adb0a530fd08d281248fcd1bcc9ab1899a225c6e10074d3e99b93d4affb1c9a9bfdcae352556e44b0a4b478a2c8c2a809b27c9202056a40cddfacffd4c4d31804aa715771c022ceb6b1b55ecaa78a8d84d6c0600805e2eb0a8177d9080ad7be1cfe3b1f6cfee69ade4341eebdf3dbeb5976295deb07ccd24ab4c7a4809ef48cfeb8c39db8f931a9fdda4ae52e9ae6b4e91a075a19090b84d65381051e02d0dca60ecc80a315698608207a8963fcdb341af8242ece0e3b75341340e2feed3f74de77d21f0b2befa50f8f7e3d5059ce39b5aac6958d06c4cce49425dd6b3a9df40e9c1fabc82529d5733306332ed0d111670fed29ea07ad6251d7f6e3d5937c865fd319e230f236b29c8882c8d68b310e45d79ca5e209bdce9813668c97d0689b58433a73ba8f3bb563025350cdd2c64c0632d5d86a0fef746c43766309dccd9ccf9e5cd5a793055dca574597bda93935f62b96d1630a7bdf953d3594587085e7a77acbc10e83c10b40b78928c98cda3c172b455a01085d198bb2560d587910055135a549b0b73b488d30389b055238fed433b6f3e303135d34e9796498ed2891a9ef78d9dffe0c68ee911eacf947d2e1c216d2e0740739543419d67c80e479b1904d751438578b73d9a50b63b8563553eee59f45570c95e10187bbdea4f19814e1859119077e23147ae8cdcc0e2ebad55222b3c1d7054214a3e7a34f6e161521cffa00e93d09a1e339f9b2f22844ee1124f5334bc5003360185c32550c06eb51ad2a01db6fcb59bb9b39cf4f46f52e146dfd6b6655038f241b7397d5240f9c2942c95e6499cfeff0a5eb3e602a9d56b305689d7cdd03a8bc9e601a41f080c7e1010e2c7301ceb2c8bcf2bc5eb0daf9726bc815aecb068009ffbd354ce575f0372b1dde38c125559f61bc7dc8903b991fd67165d75c0fa2c7443145836fe814858b5fdb77b7f096bd461e2a1687045ad1fc9036baa10631afd54699063ef52f9de8c2dc11e15223e0f01af2258cb6b404f665e04ec60b1d6e2acbd2193d702d63358604e6ad9d9c9f1bcd0a3601232cb970258e56490a810aa07de8c58f212fd098db0818d13ca4bfed5d0b44a78a34c5dc625d045a0137789e1cc12c5d2ff583f3e2c7f5b845ea29231a23fcc79e8b80450c6c86840257606a73f3cefd3027d88c23ccbf6a2303d490ef5ed6e1af0a849f74364256099e7774784153f26129a683fe15a87970a9698faf4bac120754fee7218248d30d6e7c39562d4fb59bf693dd22d89c248d18b90938358f4eb49a2e3633422add03f45ab17b8761f12bcca8c064d3ac1252a6ec66442dd9bf7bf19364521444db0b85f735d14008fba4fa218c2a834ae780f360030b0a1ff5952ecb8207b304de07a896c255f098da3fc9701e89dca066ea3c72692a8fd0e8027b34bb0b191ebe0da61a9c1f4fa43a993a4d37b6d33fc80b5e841f9aa39ab459c4fba269c9cb0601b55df58b2a5b3b22844ecef8d8d1ca84d73c325955264197f2b142983f503c0b33271571b3232a23b53744ea341ce5c2ab2b5c877c669d95dd52ea8a486cb90f16f97c1bc644280cf6c86263f0ad2589ce731e5265c22bb29b7930d84bec8306e213ea4ccb67ddfb51311796f5db70fb7b8eef92de905828c349075e91eb3b0a84b2b8f91d23913ef090620b0d9e5bf504d9cffbee67c48189f6d38e92e82c05ae13a4e54d0ed852411ae332dcadb4ee45409187e19fd812eaa4b614edefcc03cbe27612876f3a106173f1c4d948da216876826b4096be5ae2b8320bc915ee0fa80240fc1843348ff92025f48d6259fcaf2984b2c46c9b631cafd366de874a03a32661d79b918a2a09c89161a749c0f6eb6fa4f7fc9eff4a53cf6b0a9349530e70fd5e519256dff86302bece079e9b1e9bc1f3f063d47b41b24bbfad6a44790007e7afbcd892175bbf1a106895490070ba5dd74a4ba6e97bd9c5f1dc5e6d9d03344384259cf3984160cbb7ee78765bba146647e994fe29569c8ee9e551bd3302f4a7945d157b128ad73c8658d060b750c404f89a868e4a7113b4e8026fe9f7006918ca80ff6544497771ceaab420caab0ec60d9cb59a44fec7a75914a88fd7028180a20fb2d9c91e20abf0bc4b1d9b1c1caafdf9aaf0580631d64ede07422507848c0fdacf662cc9fd1cc58adc663b801b1819348c70d7050c3ffa19f2818a0f7733bbb9dbb547894d181c6d11baace57991c8de120fbe53ec12033b6e773807a84d6c6bf1f117ddd8d1f610501e24da2fe67de79ec69e485b383239b43b1804df1450cb1f2176aba74e58ac5b30a123318aec9cb1b8e0108d246bc489577a005ce98fbd69220bf9e31c989be15d0a3f4bf9574c4e3dd7d6f61f7e69ad7d5d061af789ff84cfe334e2dc01e9be3b6fe460160fe76c7fabc88a76a5c0f357cd0c85e6f175494476ea8a54b4fc342510e6a0f90a699c53c732477a91c97f908e0b7d48672e301bedcb5c8b0130e158894c1e14ab2df94268ee9567539247f4f30465cd47c5688b42e321e8692c9d6a6646b83db2ddc67de0f75e2aefe06e49b10d29b9af0f392611e6ffab054f62ecb84317f2a907dcf3232dea6c3430f67f77000beecf89388987705dc8c9328c0e2d00100073cc0d299cd22d824e5fe1e7250db49a56fe3fc9279b7467e1201f75fe684de2ae1113ee0800a385356853f36303ba7b9d43f8887aa372e86828778d8ab0b7be04b31b8c028907d9e808c3cffd094fcd5149150f914109e69b0104d3b4ad23aa2085625d721028a11c460da9370b517fd19f66b72626c9df5f8ad35a4492826f9cd57f35f0ff65912dca47bb8104db074ff6df7701c2ffade238672332bb92a46c2c6799fb1a63904818cb654b09a62e96e9a9c362d0bba455474bf7e9d6e8f20891b85aa6171d389b0f4425a10a670f82788cef79b731d35383387ed525698b923960871ccee2eaf214fb4c510caddd1edf31c1c08e2d6364f718258e928cf1ce118aa8d7b722502fa20fb97801f227fe677f35841dc50ad6eaac30fa74fe3da2bfd5bbc2fc85e40d26f54bbd092ef1830d9db570d1672e2de8a6c6e10be99e3038c00b0db4fb77c6be170a8801abfe3c6747b04920be58a8a0dae9ca15193c5a551e6506d541d4209ca859bb0abe6acf7ad5e7af8df47f4d77e59dd550a95a1c0cc0b751a1935fa9a8deb45b09ae093ff9057c2b34cec119e6c343c6735a9f8faee189fd4941eee4900c782200c2685a5091dd2278cc27f89fddfec1ce6ab2081f5f38f3fe855c8dfd2916560cdcc7ce9238bfc44b21e8a22412be4a95b8068b5fe9dbd6f7ae61ae80a475830eb7e91aeadd28bfe333ac9eb06bbf7753240df35940b8326524a929745164f605d6d04196efdb0b93867b4ff6a91e533d11214e31d0262bb0099e373451c8f403cb3885c4556b71b1b0143c1ab3bee5d18efe396bb9c2087ffe6f1092c7fd620119a5b3f2db9ac9b5ac608f46c427b6bacde43e05707e0e46ecfa3bd72f26dd0dcd0487db71c83a7275348cae3ecbd2255263860cb6063b7f80ae1189f966030ca1da4e230e18156838fc7e674144b09660f775233502277d8586f2d81582a1074287bd247e03420160c2b3e9a7542e0ffa7be9c199df46c3e8c04e2cbb49990e9cc08c8dafdd5cc550eb8c181ebf01c64102165c4b042b1b540832554b64dd07735cf17afa86dfecdc9d4ffffccfa5e2808656eb5bde2c9b613b86133d21640748258e09e0695e14adb92c9c48bf81f3dc5b6cc638f240242ebd66752a6c9c09726bd5b92093ceed83c4e2c0462caa3a9f9437ad942c33126f76731ff9398c0049275f1d186e86594b8cdca8b7248ab82094869daf35db534c980de8df27fe04d72955c77389f8a12d887a578b312d024a154a1b92b87e854d50134b9e29e50eb5bb752789d1993dbdbda5160c02bcf3a49489f959c9d101ba657aff043d7b0801683ca20213b780edfe4b5edb32e5c1433375092cd808f3aff7d8db94e81309b1a300a7abb258e417124a2e902d2790ad17d31b534de0475f74d998628b6f05504da3910e262cb27c35f06a724802a321262f2be26e6d2dac4f959b2d928008a22631cc8d75341e48393789a9527ce77452da8519fa394726b17d83fdeaa0008f7125d0e787c9ea999f0c9a9622bb6de26b7ad69466a0ca88075741d3296b01be696ad70d0b09102664ee007e4b92473134f9f3f5163d2cb84780360b9130015da065b467b731096ff052b2d22b332a811f5a35a13de51e363afc12355bca0fe065881920f117eace034e78c7345bd8fe56397816630fa43efd7227d67f4707df8293b1cfd588f0db13eeb16edd25e264e292121b25ec031c95cd6f8cec120cb79b0caee5b2fc39ab83bd6dc69d2deb40babd36b5ad647889252eb0f911af080a6608f0d76e5f4c5984e6dd2869f5ada91cfa0faa23182350f423879ecef8057486c664ae11b6f7a578b48e2bd4f68cb857716f3dee5470d08c9068d2c6c7095bd09bf5c48b5fb8bae4b14ab1eb28527935cc4f9684b0b3bcb443344d00f3008a08659135815cb29cc1c975c9af8c5c3631ab47700a5606a237835bac9cf2058f87e6478a060e1e30215538d9a174d0c9247104ddd4a1953639d693b49eb90e84ba9175388fd9ffa986d0b9eea4829bab68f3d347be37a9bd762d2a57afa9065e45e91e44114f5485dfa154b2dfd11328fe88da51883c65c3be1b248a32610f8050ad7f30c41b0e73db7fd3b1b7b89ddd25cf804e33f6bc23b774284ff6e60eb572041fa3f26ebb4474514b8744a41022a57d47858bd7169342eacfad90630d219b8df25a1869713d23439b9d5661fd30ae9176a3bd4f7afa04933dd5feca0102834c162776b07649845a0bc8f03e2ec923097fa1e1c0f64831e2a19357370256e423d20fd5dd117f20e8082c8859ce148653c2694604e93a8821d309c6c903bf82b5becc8a905dcd923ac964882a119a2de0ae2a31f31707059bb8f11c530944228c218ad16fbd11285833887d04a627bf8eaf44c4f55d9671e72378bd55015b03192e5ca22a6c048d9b888def6a63653ba6a5a286e2981217b333e3bee403538d475bc8c9a03ca32a229433ce877093a3099886bff0bcff17a7bb3f4ba205e6bb3579533fa92154aed047cf14579ced6ae4a550a065419264e7f793595e0ffdbd40119ba7bcd8f144fc8fafdb1a57919fb207950bb842a8d0781d08cbf70a2430dc76d9213eba9da4d6c927afdd2b65cea338f2a50deaf1592374b76dea07e827f1f6d41cda7b176be2987c09ae7ae6bbcd95132d075cae27dee168d6060f6a8876b9ea0a7c5c241c8b5bdea491ed694f7c2eade495819740fca07ae590048da949a90964e43ad5be2adf0cbe2e865fad6f48c2b8e5cebc81d21b974a060f2bdfb5ca38bcaf8a40beba5c36a898721a74549e570ea3bf7e3516a7062c9406aab469e0448096d52a0b1a84066db8780746c01c30659132f8ff264122b1b008b029e49dfe3569bbbb92998c409326d98bd3acf5f11c4f2d647845ce2e54b0012d619f4428abca24f5255cbec003c91c70b72767b467728fed9daaa229fef60c7e182a0acb350cc1a6cbb3e9ddfa4854ffe7473a7d0f9e8cd1881871ff69990c0b20f40090db92a22c768d50dc8c5fcccdb7dfc18f96d2acf6c3e1374533dd0d1d65302779242fbf2406d92812818405caa3ce9ac3df979fc078a40e2ae9700c5549087db7dd29aea603784ee2e5105a689ab84857be90ac2e02caba82df080a3b91183bad553d7461409be7535a4392af205380fbd9c933c60e3b3870a89403387b5d6f33131b3c5fc251495045f7fc4cca8d61d386f10811ff97249e5ea70a1c0b5962332c27ce1d6f378cda113b9dff1bc08283b8493d13757f308889eb0968347fcd23b9fec4cd28394eab2ece663392bbc7b8df9f6f7c12462b1986640f044b820929807bf0d107807580bc6db0d52b4dd89b9395457079ff982961630d25a1e8ac911ab8bbeb1b61f7537ea0c48bfc6e20d6207e3add7374a29dda490c92a429ff6d174d086f7ba00ea22d9d14f3159d48948a696d5a86bacea90e2800d32dd0f193935273f09c498e25ef22512bfde8d8be17a0d87cf85086c76a010e0b5a4135cca42f2b6d053f16480a25653f9ff921513087028b40bb759e2de90197e55599327a5eeba01dc4cf5ef8c88be88bec1364d011e4ad9b860fa4490a079676b17c296a0d0e40780954c3dbff491c398b456ff13eebfa7d1a8994b953038371a5b1017d7c3c0ed07ac256025084b63c1bf8478c8dfdb7bea8bba6abb30d180d07b23f6c055668146dd5524819ad3e3919fb7932c401fa54e76724ae2800c297191d86b1a9740d872eba9b27259b870c9432545d9bc1994ee6b7bb84d60eba61b3080600ab778e08564b76d5a2788cb874e1d2a176b907e205564422be0a3c1f9e07648bfac95a698763c42d34d345b389dbc629a34a61b62776b7eac80ae5ec26fe23eb62a833d3faa5cd49bc39992e849f522dba394b004d3b93b99f02d18840dc7424e930a4de4697c0b26a3a2cba81feb6e3784b88131dedad5fad0e1f5922daf2506c4cb6bfb0d2c60afce34f546cafd14522edb79dfd2077501f0612645d312235698c37f1e4ffaf36eb4c9bec18f89283bbf022b943f644c19d0652a413ad6ab38947a8e2bbb1a9b8ada2fc2fcda51ee8d163fc7cca74ab99e3073f84024893edb8dc5280720a729cc8773f93d93ccbe0a2506f68da2b213578070b693c9aa896bfb690550dcd5ab9494be35e14a7d814b7b4d399bda90c438008e4416081d79c33826ac671167939594560b3e56b23cf319942e68ac86163c9058f4336dba7ea8131b5d83d0635fd2221623be55421831dc232c1f82a6fc35b0d3e5a9a5a38537eccdd797f2ce5650e204d447ac152d6cefe448c95d54efaef07ee67b976ba89009d9c7da32150fbbf7e2b57c60cc2b77edcf68964f0dff1e404eeb5463f7e0a6e612b13407922e2b69c30f3b59358d52f31ce60f37e40798701f251d2376c87a530bd497e2b4a4bfe80c839280888ff1bda10541c7dd182bb025177deb3b9bf6c4597c8551cce3a5cff2b8b6332bc4677c48e0a589d0f46f5074ec287bacc81357cc1982b06c7c1975debd9ef4ba815c93dd1cd25a7ec985908e59d7b7d353f0c19b16131011275cc5d139de46510f3c64f6e9514f51368830ced8e08b9c33d0e56e0cd2dbf6eda68eb0b67126df0e0224b20e03c8ed5a5980f4436207c314a9af8ad76868c6dd0be717e8010162eb491b16bff18b3454e7f0c2a54c20609b403c3d52b09795c38286d8f08d8ca6665c1c9f1eb2d7a6871750d6a0faf7e45e3cca6b7e58a81124ea6378ce39b3e350780abeaa01e5b190393045a7558fce19385867f17b50429321ff5bf229a2889ec96bdadf7db29b2c3940e +generate_ring_signature c9ab4560e364fa2cbf7ec6e3aa25251bcaf2beb043ccacb0a4624058fd88d86a 5d6b8e078641aea54474ec65784fccb1e95d3a0f6c1b97005d6fb65077c145ac 3 56d63e1b1a487fd4d7975e66dc212e3ba4180fcbc6ba777bda12c4a957f359d1 0ba8218820fc5a47b7449974d27f4cf1fd7ba6698f087a6b007a15637c8c56ca eec4a9fdb41c38be9bbb62e86f0d497b8adef1c297306cc3a209a700f1c76981 461bd2cc07b9c8310b74820b6b7fafb962605dc168cdb11be6995b344bf95305 1 6d6b10e0b4a58890ffcbef0cc87fc466d36105f6614619f254b6fe895bd15f0048864b3502d902ca02d03002a2f2e91cd5c5258268185a43e51ba911419a7f05a929dd17e07286e0f4324df0903263dbd0451d33bf6761f1feeb5e664feaae0dc73d927bd4f3bfc1a82f8b63490efaef3069262bd9788b1483baf5f7b645bd07a4c0795ebe9cddcc95acdce55b9a36faa9870bcb4fad7dd694216ce07973040aac8d509dc86fd616cf50b96e0cc30bc9bd0a48a400fe3a16abf875ec30173f07 +generate_ring_signature f075672344407c2c73e656aab50a5308cde472718afb873c3813cd31eb083a22 725e94903757033d3ebc8b23440f0c208e60f8932872536ed80050f0ce714156 1 ac769e6e63bf28b0e214931c70c958bdfcb8b7e662f280fe1699e9570b3e4df9 34a4a033910e6aee4adaf7aa902b9bffaf1ec93c9949bd358485f59c45538306 0 2ba9a0b11de0274310ab0cebf49ac3ca88fec2e495670d57a2b1d0b9cb7f8f010dc3103844c4ac508e4f30c4e50fe3021674605335b452f03f55f7a3a66c7c0d +generate_ring_signature b5c9ef14b9a08e78925da00b25dbfc501c26ecafbfd1710539c0ebf3f0c4fbd6 bfc8153ee1fa82bc2a51d1e74adb672f8354f3e11591ffa0253c4a3a7843d759 42 3cd53e438e8c719ef4087516c7124def7dd74122134893d56fc52917f9ee9b38 f2e4139786fbd913a4f13e19d484bf62929447b8afc84612094b0f5bd043df10 5fdc376b219fe822837a4ad8c483f1f392a1cd70141368a20b0d47ad9fe1e009 727d639f4fd6588673837ba332ad5c0ccfd832155dc7e194dfa9a8aac128869d c98ec078ac512c8be32d11374bed3fd019d46dbfab909f65b47052a0b36a20db 272da4cf42e06b9645cba73ecbef4c57b64b99e481cf3a1867ee7c971364904f dfe696e5068344bf3f7994528217694b8b3d359eb52a362423ab2dd23aa0ca5b a2b507f5f68b776722b35012a49fa542f58eb1f6f5a4f2b03ea507e306dcda46 4235b88c24272d62ebfb9b75e6af06479fdac9f26ee03560b53e33d48a820c78 74f869ecf9de6d2b0835ed98600e6c24794e549725eb338f0243025d9945c008 daac00d7a944c053a2e423047c1ae410cf73d0b3e3a0c57072016552cf940313 a6fdb201cf3f7b8aaee0409bc5098d0fbb791e4da2e87846e69c0387ee917048 c556403a2899b4a1288c81e6f4e7f1d2b8adc7e1baacb2272f87407a5987ce4c f9f08e37a0c25ecf700e25fc7107c9bd008931cf9fdc39c454bdc4a8f66b716e f2c59ddd77f72881f42cea3a1a1053f9b4e4723e20e65a1874fbaceb9fced0be e7ea591828e31b78bc7634275bc73436b23dc1eaeafb86775428e5c0a10cfd39 7c15e3d04367d0638758a8c9ab73eabbcd356909c04377d9c3008e70e1ed0eee 3bde3e1aeb47353edb3a007ac3fb658471f6b3c33a67b8224534301d41d55769 8b778667d673944e41147d049effd5e9197f6943b65d8bc47e251c7d66e614a2 a566e5cb64d80f5eb09d5d8fb0c7bd67fa50b2847b7594a6817c94a2d2cfac40 44d95857ad4b5254b378db5d6f5de3aa0c866e0eba2757695e5b955a71ad425b f95a8c8f71f794894ead92d7a8343b7f92c2902376c1ae65891b425d7beda62a 29ec148b76bad44d003a3e53c1cde766fa9918b011696402b0b5546f6cc98c82 2321dee77fd3f088ff04ef45e65fe6baf7cc57a2e8d5887efde37d4e5dd5940d b094fa11e71f396fd2c5efa723ae3b86784d3b4a3ca28c454807c379fd36d8e2 62b4e2eb263e0af951102eb0db0ac934087876431fb5169f04e3033ed66473c2 3043bd14d14c669e87fa0c47de6b5253e1c9b660a200b528d5d008dc6372ec28 81837f200ac02a8ff2949baf7e2046dd41475237d01dbf8a7ba05435d4f56542 b374ce8d68abd8d30d806eeb3133692abff1cc03ce765f4d2189f420792d0fa2 8aa45f186737fc070eae52127397db1c1d921b3716233a76538ef4cf8d98b006 094a03faca408ec2ef2422d1e8e93ea9ebd15ed6793f909327515725fd245d8b ddb31f1ca2d6a32e1d6ce1e3c7935d2afdf32bc00b185ed92832441705af8ca5 cf9923a125eb3d3c6a27bc8abb15c9a1f5ecd97d6bfd4101395c547c92f53b62 70b0954b770448de581288b0c28ef89c95ba5bc78d70302f1b3f8befda378e63 f32f02453664f8af919094f4d8ddfa34781c83f4e8b8e76bbbdda82120444532 a1c063c2be3b23be7ce11920ad588cff49f0be61f4cf1d86961ad990e0d74af4 c9ccbb04e610a9d99373863ff6334908a4218f3a27fbd9e97b76d5a1db666609 7352167d50a292ad64b7c1911ff0d3245ea58be061baae00519af17ec81f1cea 7340ce3795cbaeeef9586e1be8bb45d0e11835db89cb991b1b9042dccca58de0 8486d053b5274d48b7174efe4246d6e0ce405a90d0101558f9ff98fb0f1f684c bdbba1f4e3c95f849d2cada4a88daba5965c9b1707e3b963cb130bf9ecbad8bc d077d77756520959c488b842f761257f35fcd5190e86c4676a4a44d6ce2c6bec 553cc6b8ef0b6b67e23e2a5474a2c74b954bbea6e8e8e8c6e1fabbf5ae4e3e0f 10 eaa9985c37648cdefc6abf1ccd6ac210118555593561c1a7e2ac49512239170bc76cd1ea7bbea3601035d9e173884f722d2657f3026552646a259498b4dfe60c1b8a9823a3b92c1d6c169cdd654bb5255066ab180effc1893383211fab1a2e0a2e65904c3797293925a3d4c32ee26194e6429c778313c518f9bb64ec4394340c2caab05339016465f9476c7eaaa201ac8ade7c480a059d6f291f32521d389d0402da00b01d55f131ceda07ff92c2fe2229943f40e31ae1c9a95a6e5a4bd3180d393115f29d77e5a11fb448c180fa7f6ef89666e114bac616f2001a2322fd5f022b389a6c55d1dd49efeeb32eeb338ba3f3f8358dcc0fccc17579ee9cc4b70a0ae9e22c8afc08814689e6b189bcc84aa61c025b2fb79f32b7a01327a1880f9e0eda47fe156c120395cc19e9a4bed46938519a4b274d413e96a4d631ed291ef70ce61d08a712b10bd11f78d9faec82e69609251ace440636fb17377ec6e2dfe2061fac9d0fe80c04d9e3b4d4681baea3c5288a06b007d933ec2216ed81c73add01c106acc2067d07b54306ac7e4d024ccf257e5647b62583fc6adf52ee766ebc041af8897f7ed6e09b4c9cbaacc99ee3d3a1f34d034a3934e9105d3bf623cba40a1f1caafd46b77b36fbc63d85aed99a97955f76b539be43c8a2d36738a5b7670a07b17514d664a009067740b9fa2e0e4e7a8014ede8a6e71477e2a5c77ed8840374bdc3ba5d844abffe8989f450dbc7256ecffc2a85b6217179c74628ffddb40c052b3193929fccb11941d18cd50ff1e47876dc7d10e4d48bd4261d696a8e3a007f245f9c48a8365bd64b6975f0a8abb994559df4b3213df56ae7ef13bbcf0104ba6408a7f3047b718a83ddfea0a76d954dbb2dd747ce3e07eb1bef9aef5cb000a7cb183fa82d2baab8a8014062bb0d70d618c77da2d45f285e6e708ae57b8d0ded93b169594a79b00b182d86ae54536925ea3af28708ca80a9a6bcf6d922c10cb0251f9cb82413f510c32d06068b942021f12cd116e61275b97505e752af7008b1b55dff950dba575586e08c3817b8c98496b3c8d6e04ada9e2c25b4b75b810ff7741130fa6455307291ef8ac8f13ed9b3c93d6478cc42370288855beac3fe04235fa66f970906acdfdd7756594a388feed42505390eb0ebba94e80daf126a0b2ad37cfdaee56cbec5148a6998e5c95c7bc4e7332f5aba91f443b80f29055e0b78b226c5fb7da592058f9e624b5131167a4f45b30041028643ceda71f75fd20689077661b4f48801fb6dbc9a17437565d3250a85266bd0f3b92130677970ec0d8dacc889e16dac31063d2f8c0a64b3bc258485ec7acfef24d21325dd6a8be409daf37555212f985769de8aabd4f4987208524a08b310fb82bd2d77a49e32ee0d08e4289345dcc750558297dbb5ce64508b70493735f96c9edc10ee45b0fc6c0a117ca42176f288e75c599bc66b1b2f7c678d17fb9f649e49c1cd6efba829dc024246e2ea3db76fe309420f69e7c62ab339f205f3993f9e75713422e25806bb057b53eedb05630e1213d0fee48cdf09f9d6a561dfe3c856eb2ad5e19a7d5fc70064cce0d3a57732c6c6bdaf95605080f190d13592f22cfe82da94d0a634a8080090fe251b1147b8f3583c3af98d09b8c8f427fbf92e0baeb37872628bf5ff8f06663e2696b3130a46d05d6d850be0a781d16596d87c5f3324398b83cba840a102a12597bee995a49c7809b9a0e8912764b0963352a63b95fcf630dd2400b1bd0d206fadf62077f953d5dc3fa2415e49cfaa29f07ab2cada25a5bd82ea0afa8b0039896b299b694da5dfe5c9e0888eb7913bb4a19e361bc634da386a41b5eab5057fe9aa84b4a4888c82f737d5bdfaea35e25438ff1f5a7228491d93e2f684d809ff8b1dc1708f01054aeddc46efd52254f76d39967e5a7b746c4574050bf2640d875bde27cae3870448a70abd01ad15c15cc253496e4d225b18d30387e7b9d9032ace4fb89513c8a3bbbd8c95b071fffd7527364330a4c4c73312a6b0b48ef90b0166747924511a378511cfdb9c1db2878e1b822aaefd2551a0652a85a2e18f041d23afff2c809d6ff422e455e1f40227d753c86e1878c98430e62bf9ed28850ec9f8b5760276bf4e4bba1b416b55dad0de5309713b067a723f8b0b741c68f00d2f3ae8a07a555d77b90bbb70e6fdd03f1460d2805a5167cc53668ab705fc9d057c5485138a89fbb6d88c52c89cb324a727134b10fef2bff959dbe3a29326360b90891be9325c73a69cbf8d918b634198de770c793728edd27cacadb5c0642e04f203107e109616e1602eb9f91b6f0cee7716387615f9eaf2c4a2cdac13a35009fa2603c2e7df7749f64d901b6a6b356c341d44a8c8489436cd1f0150afc00b0708ebeeb6c1272e3f840b2c3bd0a97dc54fc5e58fae98241c43f53f0a5a934a093d77f09cd0f2c31d5c993868e31062ad2698921b2f6f53d4cc7601246a04b308edc13e44b851af90a072063daeea8ff46825401d4b54ac9ec68ccee5536352006f65ce2e21ae1775007a18e117184cf079477dacd79d8c12fdc4512947f343026b8fd5f85a5e2678ed3ec8c574841c9a5cfd582b8d7f1794f097ff3e04a8e00c544c654895cb5c3c783e69a33ba223c3fa73a878a4721d7f535f1c7a6ef058021b05c9ea3a145c80ff849ccb8ecff88aacf3dfff6f37bfddfec05457167cb108b137eaac5e17922ceb0f564e06e19eabda5e99ecac8c5f1e0681026ecd3021027102d0fdf04c0593b69854b0468adc2b0f230fa0eec90a59ad74a95cb71210080d1c2155eb51154dc6b372523c7fd8d7a95a98724ce60ffc3ab5bd7511a86702475bb2267c4f632521692ca34d2c2972376708da2805fdc72b8f5cf6baf3490e2fe6a70a09d4ff4bec406bd1ca11e6d48313819dc488196d0796b7901c3ab8040048f6212b847707491c04445d6a5b6a25b6f6a6fc85b7800a5ed1d413b75c0a9a1e0664c9a8b2660b238d30c20b872d1c65b724ce6c82775611571fb67e850de732d8ab1751ac2f9b308f6e758263997cb12bfa83ff18d2a54f51335ce71108394233b6b5cf0924cebd82fd5e1ab5bc8f45a090fab15c09bb0f375ae127480d61e0223d001a07086c7a28a2daaf95255293285a56e414b594ad4bae49a21a0038be0ca7732e64364015ce9a271c570d8ee9f5893a50b77ab04e0b9fdb34b3069831eec9619b63d1525d16f2a70914ba5011bd92c586c9129790006ee91b6f0094b8f0c2d75aa3ea399dba73e54c73ac7afd02de9a6ce6a81d5d13bb1ca5f0078bb9ec2b63ba79b96df33aa64514184aca3a2816569103ffd38274fb9fc47f04289bab6adea974e2aa6877950c3df0103b302da4ec181892e78fbbf4483aca0f782da5a872afef5468d09635c24aacdf676d840554c22109e781eb2d09097e057a21b25ab8bc39c281ebc21480e6d9bc972e2b1ffadfa450051dcb1e5d637c01d0391506787a9cf0bed6273a3efda0a0321dbf48c5fe4a1e5a470ce108d5480ee24c3eed1330051c46874a674ffa202cd545f5b22354a9f91576dfc7024dba0642080a5e080c5b9454d3a0025fc80fd315e32d83f9677cfbd8e0ee5039011307d1d3a9e90184a12be9b390fac3f9d8242d4e8fdcdd50caedbfe6b73c9401dd0e95d112b28a604b94bec5dd802eb0db53d8ed849f81a85190de6e71d9894d3c04782e2923c57977b30aa55a58f7d73334537c90d263838279b939777a657b570a7e1d02c2debd71258676e57c804ced408187a2453f9732b811e862eac282690f +generate_ring_signature 9b329f5487db8fa896767fe45c6f92096dfe0be8251e4cd36d07c0919a9c7dfd cc275cc9d60c681f4d00425e16466fa9f2c36f5bb333ec2c95aec837a40d0fd9 4 67e340c96d30549d1dcea389f686423bf0eadc42fda684a21ffde3fe2a0a1d3d 118888e22f09ffecb3a079f729e993bbe3a2f8ad9b3ab98943d7b6d039c93e3d 1c03bb98ac40e56b9101b0a628aff1f3ae682a026cba93ede7304f942261f04b 9f8aab00b42766e651e5d5c5a71ea8399f52bab563afa059823ec0ebef99ae32 52b84d2cd9edce72b79d4fe908f59290c7231b8fd6479b11b81e990097c65707 2 6061e39d80b0ee493d603780a60e97398fc7ba7b97b853b74dc58e38ba53a104bbf6143269c99075bf7bb68be828857ab394b0427925bba7b7c881003ec7e50cf3706763308aec4c363ae11d6ebd93955a06105611d3fa76cdce4184e81e45067ca70f26da138c87643fbaa0cee071b69e01d589d18d2326392853d2a867d60583810b131e3969ad44f24f01a0ff2d56a9b6a895cb5d76b15c421c9858adee094031dc7a986d7f497fd63292482035e27971f6ac43e57d2f20f77e37d8f58e0288a6d787a62f27d363fa91c911215bdd9980c08974b720d66b05da3ea0a45d076e6914b5237006a05d3fa7319f690d22f9e08cbc81088a171159db5159627304 +generate_ring_signature 3e8b6dc355913127e29a053eeaa791f7b9b25c96292970b20617a77f2941ce66 864ec9b981e85f596e34ef440cdab5ac85878584c8bf0990753d53c281430f5b 4 f04f4e042649c5340e6decd37d44afc47a81e00907733866c866d853e10616d4 d7ac266b6fd14bb55b3a4c3fff28017b1f2d51591a8a9a38a921b55e0ecb2b36 c579e81fea2b7202b881513f371e0b5cc4ba5e941e7378cedbf2355e5df74ec2 16cd14d1087769260824246f32fbe6c6e8068e7efed639574c837904fa186e57 1d46be9f88c8a3546d8107e6460b04cde2821f0c815fdeea2a5ee8556b36f006 2 63d08020499a59cbb41d88ddb1d301cdedb7491340fe0cf9656daa03f2e24f0e36dbf1874d8f54ababf888410598518797d4b1c96358b9be3b9a4bb39b4787086605bf5b4e91879818f499f7648688738cc417269be27ae828c1d9edfac8040fd409057fcd2b97d8f024a6b9573cf9e5cd69346ca6fa60f9b9574d23b8d0de0729e83e3e1d0ba63f025eeeaf217693fea4894aeb407fe0af4ee7f640a456b20d22b0ff39997648ee5393540ba3ef81f7928e11b56271fe2542e8140cd3ee170c2447e309497fecd794f5b430c0226c429ce6b5fcd586954569366b0bef476b07e4c1d6049dbe4838a212421c97496b9d2920d96f6ff94dff6fcc965551d91706 +generate_ring_signature 4eea1e52284c31388c572c77b4dd6bc18080d356f22b220fb2cf4a1706bc0f86 0317dcfb34494772c5bdabcc64b2661b8f061614472914a82ed7860376853ec3 4 35ac95d061c9f478a387f5b33ee56b5c962c622cb8335e3f5b05a50dcccb9567 eff1403b48ec6986a6f3a436fa75390d47df6b75578cf7c00c9545fadbf9f9f8 bafee79e294e0d60c0cc2c4ce4fae48df86d0ba91e46e4a2e6cd033b34c74414 1161986f00835114de03ed5ac2f9b94de944c1a2b9f3a237c8e3bf9f0b048349 324b8b23740f0a95fb37e26b28ade940114335d0c395200e3df2dbccf3fe0b02 3 733325b3c48a360fac99bc2436f612447a7e74655acaf68d6c0327829067770da573351126a1db507326ba31404357c53208386916f9ef8d7662e8f6b3471b01da0e2886169c9215ed1cb9fafd1da3a2cf00917aa7007f8779ec4455277ecc059d933e2afce960bd9f7222e7d1f4dde040fb4558f69048bf3a1b46cb78237801f91a5a0676436ec0b7b0f10b1bd89b790214bb54f64f5867ef8deafc51004d0f3cd89555d9312a768c49031940ee3e108ba6448eb24fe02bdd04d0916ba0b2034b60987756fc0efd29274dd2f5a5c7de6f40c4ef02a35943f6152c590ba5f4001eb4cfe7998dbf59ef1638e9089b532a46f68271beb1b5f6ba39f82aeb50a403 +generate_ring_signature 3897f3826263809665c0f79b257b70f91ae560f59533df45c79aa481f14ba6aa ed20816021e0870adcae45b087cb64978c27a36fb94967dcddeba7878c43065a 6 1f644846ce53a77e39b3e5ccc0c578bba7b854b801815d27e4a279b929752d66 9370f055164552e621e0ea348794778e844013451447dac7420ba92789bf23a1 58d1f500efc8f928bae7a56d15ffc8b07b65139f4578ec2ee706ccc992d46cf7 07c2dfc3e82dd1625eaf9edff3a2fbc75e6e641a41a2ba56ed0c939d2b81768e c2156a0f6cb0f9d9c49abab8124b36784d2f0c676c9af313d1215357e5203e4d 016c41e09ae240dccf9ec65d33ee94ccc74845a9c8c233c2a2bfa220be6dd093 2753960b51aa5cef3e1fe2f7766429bf0bf3cd91268e609c44e5e1779005d20c 2 636ae7e564274559f211d61f15528b646b5e0354ee792528d224351d4f5ef30c6e98b14998f971ad67dbddc6204bd4b4df9d556202d1124ac342ec5061b1060014b9ac25d1e90d4188aa783f6bf5d11e2bd288136f8567e30a8662de1fdd7d020aa61bd50a63777c9099965b1825951321f901c8f513ff03b5cd9f2132a63b0f8653fc37c9ec3f990b2918c35c13032219c24cf6becd9d710a80b8e42871a70a5c39cfbfc5005d5db7c7566036626f801d4a2943ae9536f6a2c0592765613f0ea8cbe091dd4b4a632052488e0b843bd302d8ecb77a39684b49564364205bcb09d4b2d55b6f2610c309f4f4153defa51a2c71f7dd40408faec0ff3397295a750891f4a3d203ea2ea6d10d7258f159a569851e6eff80e980d94ca3d53245a4fd00f75d9085940f7cc626c1b342f73f056885db0060ec6816467cb60b885486160d7e2e775b6254b3e13310a4229ce0d52ae7af95792a7bf11d956f6b77cf58eb0fe937453c16ae218429f759b617fd1c9a1b656b4dfb6e37d0590af9e76d5ddc04 +generate_ring_signature deecd93de3b6635a3900d9205d9a0445035451960faea63acfb11ab858265584 1157cad423a531df089ff8735908f4cd8d8804ca6f796839239c18df3adb224d 1 888be7fe0293f3f66e8d0bf3606153505f274fb692431e258bea9ca2d140d85b f8dcafb41c048b60f3119e9537c0e2d44cb10b1e6734aae324e473769a63870a 0 5694400a4d63d8600fc80f713b24f3345e6241a7077eed86fd2850d674c8bb043e3358823fa0dd05dcc53447acd2c5fe2c7154f7ac2162f5418a2ae35c6f7301 +generate_ring_signature 81b47dad14107e991eabca238e4b65e7367928f92b795b2f3a2508c79608dc19 c05b11bf0e1c3e0f47038d6aa49ab4daddab874de20e0886bd6f6c578ff6db01 2 b7f3a03806831c048c28fa2ae2f5fcac0e6d4a76cf9fbccdf2ba1d0e3229b35e 6638087a63c6d537b87a22004cf2364162a52246a68162872931a6c0c35aa5ba 75c26eb3a2b4a277a7cd508b08879524621a628ed9ba713b276161ceccd2ba07 1 623ef1e32a089ef4bbfe12e3220759754d7fe25c90f5aa2dad65b678c4ba3f03f8fa9bfde7093f88aeeedab8968fd0b5a1d0bf9ce57d042853b3c79767c4c90eaebef5afee1ed2cbffab2acdae94aa10446484ef59495520d1d3fffa13981909818b180f4d206b575ae8bf131b7dc860c783acd935e1d919e17d30d130882704 +generate_ring_signature 27f39c66f6a61282ebe04d3c6116a57e4133798f01a738294eb6a52c813585a6 a9750add17565f877b2b22823ddcc5ee4b89f41c728972523d61a69b78e9088d 1 b02c8a057b5cea1652d1a4db956781e6ce07e6f86e747ce176a7eefa3d4d652f 8ea9d363e3c1ed113f8b6ae7672511441cad4877336596e940db05efd1e9ec0a 0 5e6f4558481fb53ee5fc6cc4e3e9761b95081eb3c5d32f28bd7f4935ac3e8402d1a2f63993b4c5a49dc3b438e9a0fb19b6a4d627f1fbba6767d2d0550a934703 +generate_ring_signature 5c37b80efb792c48e4c99395fb19626df810aae0e617e587415938611e35b37f 952470262e4fc8ea399640c866cef6d408edeb219511cd4eca7006622386f661 14 84cbe808524c622505b5e67783989b593fee2b939b5932b8c3fd77bad3b4647d 60f3e7f2287a85996d5aac23f440ea64c6354fcb1f7013a5b25b081f2dbd991b 3f4a81047e7b9b1b8d642f8586c6f98bc20baad33f75a7504afa7c109b0fe612 40d1ab12988d9c1766f01559399c0e0c3451da872781825364a1c42b46760ff6 549564baaec6c44ad533e9f01a4a133f2ba260da2127a78ce876c30e97c6cd58 82961348f57fc20143b0d6b30e6bafc63b8575bd0a55a28df76af8629cdccd00 119798a0eb51777954ca108539337f40554d4b2df47a4d21de97e135b66b9dd7 ed90cf28e5407fab6b8d8fb70a98d9fd064cc0beb47c61ac94845dcdeca4eceb d4b35cec0f367a4e133cb2c6d4e63c07ee92247ea1033cce6bfdc7a67474e224 d37a52f026a589b51064eeeb64a14aea05420c2bc70d5a04ab1d5128819ad3b0 968604beed7f12f1058ac5312bca68c811064117b189e0e4333db93e603c8be6 b3793cc7a8a5daa5f02ca4496390157df25213562e7d4fcecca72e9a23119e71 9ecb2e012c207c1d09124479bdc8ba9fc10cba28ee51301b5c7eaf9ef68fa355 011a63f6c9050800a210f1015674fa555ae80133dbea7e709dffcefce488f691 ee5d09e9d9167824d3ae704ba8c5b4d2236f69da9002c28cc0faa08954caf708 8 0f13a3f63e0658ef31f2d9b6831062ccbd95c1077fb366ee5cd482d6f199b10be0da73b421074bb95b7d4d4fc77b27741a21891f4070ca8b6c47bad24410c40f51cef80f07ac0b736b81c72f489bf1c98d5452c9b1a376acc02f316c3d6ca2054d9ffd7b9a43309e90b0252719090073389dc92fb283bae482e10b00bdf9740b623f154f2e73c1012463c5d1bc1fc0821d4b73a70cf147c3044462b0ee8fac02ce9082e7552eace098a227cfa2bb3e770abf744b8b7c5a92358c853bb434b906d0636040b6a5ebae45bc63876faac43885febabf59c8d3c3f1ed817a158e7606e522b17a5f61b2a5828561f52ba7eb9c15917f07ef58dc330fcc27e9097e390a171854443c37d603f1f3d1e263accc5b219d9a79b7b415c8d860b9c3624b210a89dffcc7aab06f1d13cae86c3476f037f5209968e471e888bffb41f016d1c50ccd68610e402564580a4bd54d55dd850ee19ddd482b5d0994460691a62de36c0dc175138b7ae6a5ec21d0f2aa78393081ef7d638517e9a11cfed9cebb1dffd60386eb62ba5a7622d5bdc7414ef4ee279492488e8a06996c85a7cb27c06cc88e0318ea764c56bbcdff92b07747de1d96f12d29d3b0802182d7ace3c08f7fc9890bb84b992cecee38f8d251aa7ffea6071b1d2d5310ef322ba96f577997ec15260e11c20204aced8235b879d4bcfe9304a4032768324549c77726474ef6574a530a7900ab384801ed3add08b9326978bc98d6c43a2ba64b3af02ca50fabe0bc3e038c3dbd5c940b8a64034dda01f96af84c7b776e02172479da44e0b6ab6b9f9c0c2390e9424e0f119b0940f3bcda29686f25fbb9b929545fdd075346eb88941c00105726fbb36b4fa9115c0359bd227aec612f9253188377f8db9751ba768076071881159d2f5d1bba54825afbe244665e4dfe7ea562b62f28b746ce0f32623601682ce2c3229a5ff14dcba206cf7d8ddca1e6cb93a29a414b2cc65826faa7e706fd37c4063cc19776c4996c87bccc37538d45a0c80b907b3720ce606c42c5850f0f8c3d34016dd6ec1762663ef3e83013b2c1655e4e4c20e72b1be7f069b2bf0ee1d4858c37ea52c3a2980ed79e78cfb6e86aa8f85686299f23bc1fc62c55570108992b33d13df169abd62a25595453e57b5c6e1c2724965c06b7aa506fb4ec095e0c86a73db10b2b16a3667e045fbd8c4ae66b636156be75418be3f71904c1089056026d2c527458eb04744b316018d3bb17b8acec3a0f8e919bb259fb88c703 +generate_ring_signature c5541e41e2a344f29ecadb669ec32474ec245ef6b2b5f06717612477a8bda42d 62feedb1dd4c876f4e95c2733a958adadf85d278f946e4c82f222a7711ca10ec 125 2804aafd5a6c29ddff9968bc1d6cdb3ab4d346e83d219fc96abcc5729f6b703a 77521a9631c275477f4163fea03d7c3fd704fb7b5efd379320e005840539af0c ff24636208c5422a9c83e3e8de964ed134553e54fb7e8205d2e77b325c66ecd0 f21c08aebe88ad781e69ab0026121fd5f134720075db02bc436db5b6ce9b459e 0535f689f85a203f3612be098e8fa8f06ef477af3395c6a116bf9e3280f57975 ee82c0276beaf45e6efc7ce81696bfff42f557029ecd81e0df7887b7dca4b0d9 f760789ca02a9fbad11532b7cda06619a32e2e6e66973039f4f843a1cfcfb906 f41125c6fec4783f9578aa8fe9fbaad0dfa5612a829c9d5b055c778f404a120a 0e9f1968af9a915ce9c88c0ee9a1c42bc4d6f606262509404362a80feba773a8 43d5caeaae639a65004bcf71222e8ca2d3b2851b152dbf7bb89aca28c456e63f 16a37a71f407d8ed2bd161cb9d3f45a9f2801ecbe67ccfddcaa31cede4cf986d ef3ad750bcb7779904bd2bcb5561d505c1c1891d8c78e46e94cf1d63a0fadcb6 746178b33c58f06a6685b550b789d398862762f14ba9a3f8331b2ba82e971322 ef470ff38a5ef2fe7edfc030a77d086100965fae7a341afd095867a411eb2745 e8d43a2b8c03e0eb1d64109b1bae138ee4578dd584480fbf9becd4e63ddc3ef2 f466151692eaca15a47af224b8b220c1f71c51a78b581b1f12695947c790d09c 0b064774a419a807e737a7ef8ff52dac16c372448243428c321c024aac33078b c4763dbe8d39b3f2eadfd70260acef19c336a1fd80a89d68bf8d5564c467ccfd 141ba183ad8dbde5e67f98828c4adc018d53db2cae83c34e3be314bacf438591 41927644356a7633faefd0bea5fdbd25bae1e720819d2fe79500a950e3fe6d98 90d8b56157bc869813104b12784c4e88e908186e10435d50add8746552f89c08 9f3eef380682bb8b6e0998bf7e3391992492183d624b829ed3340c34a6affa7a 87397030797108c58eb9502a52a18973db5700f8bdd610dadbc80aa3b6c66e59 2c5d5a0d6bbeffb62f288ee87e5762d6fc9074bf787d5df4dcde7a49e6efd1bf 8b2c1a8dd258009d5751dfabecc24fa5935f0d252871dd66d293ad0185915a5b b1ed2a53a023134c2023a77c7725817a9205f831864acbca58f9c79d417bea85 7f55eb07859de3dfc0a8e206d1d1cf4a0342488987a6d2c18f41e97df0df014e 5188fac915e9e03a83302e4ae128f1dbe63b89767b91a4ff3b9295c30dd3bdd7 10ff7af1f258091927149854228a5c7d5ff271bf4bda55a9ff34d1ba7675c509 38e38959c1ebde70dff0a5bf2257a13281b11d432bf7f51d3737c500c36f7f2c a19df45899c18cc81122cbad000567f8fcda8e789293f9b77b5845c03892fc4a 4c33aed9b6b8ac36afa9892e7183675ae5490d21449940b207aa6466cc1e97c7 4292a31b6bed65a201ee83b71915c238b72072ee439b25a2cd496d2cbba85250 77891645ef71973768d5086c5e666eee6cd22c18c9c027277154c294e58c1107 761de841439e26204b01290f022bb014db8df120501179be8f3764d7c19fd8f5 9e711d6b3abaf3a78048a9e1276e6d70aa4ba0df9673d7b7cd653494125e585f f9ea96c8410b15246095f15b1a080578a3d2e4a42c9ca7ac41d713d69c674237 13b6fcf0056f59eede98eadae5e9308012083fe4986c744e1fd93db114c389c2 1ab06de0e3067113d4ecc48c5321fd6928e8f30c0b4c073e21a629f794c930e7 f2ab29c1b2669413a71b096379c3fc8b21889ba95518e3fc576215fce0033592 9463f8f4a96d456025108c444132060d710a6895da60ba9ed29cb0e7fcd222e8 f17341125a334c6f5ba759ad278014e62bab511f9c7fa45890f99a07463d5299 0cc4709fefdfb59de0bd4bce0f3833a2e3e9bcfe56ea4469f9c1bd9e219ad662 cf4a202bf367be4e41350c1b3a49a90f1faaf925a73af48224b02d8679577d84 844e462cb86c7906ba82a2cc5eb86828fb9bfc790abd59c2cf54ca6c0524b6f7 265cb58a1b994444fd2a9ec13e22f1e219ee2910b87bcc809e592d4597cda731 eab37e95ed3dcd62f3ef9d98ded850d36c437ae0f7c4d360eb9bc0006567dbf2 a9bc3a316ee0f0dd1245d33aa0f2b0a65dab787db3b093b583c1d183cdd87388 c593bcdf8162435ede45858a3f82d18b6e08ec9917574bb630b019885eadc15b 519bd964446b95b440fd2832a2bdafa6fe9dd41f91bf9c190827ecd014817149 3c97c72e64b47cf79222f987d41a9f95959b05f60aaa714ecdb375f6bea2f24c d0799a853482f9870120c87d82efe93f6ba672e361244a1308f5a918f8026204 3fbcbe6e8afab9f595dfc5d42092b46ced57cf4a77a7732010e5435df18bcb35 e7058fd902caf725e1937654bcf210f8a08bbcf4c174127a19bd013a4ed13c5a 3538cc278efd09cfcd347eec14091864878040351f128a36f17f8eb1bc1bca93 d023d792c2ecf5e174d78de4f4eb1c972f05fdc31510ddf285ddac03edb6e9a8 e3bbc9156f2d1efe4b0e5bf24370772956146201f29458902f299e7b178e2926 5ce05d70587d6f961dadb852cbf573da00d3575902e5a111204c29c1c1995524 13d6a79c71d331cc44369af63eebe06208038fc18a35d65a9bcddfeac86799d3 f0c18a55b75b0e8b8e34b5efe0d3227be9898fbaf8b270b82a347c477442331e 6d941ae5057bd14443053028bcc66e3df3ef8002ed4889722a619d27af42c4c0 65d401e25158b5d536010e71ddd6face36fa59159c7147f57f98dbabd6c03e3b 236e3b8f14794886df4b2e6cfbe93af86a369ed36ac7a163855fc84a917d132b 2e731fad62c827847155d6b543e91656f33a37f29802b99c74b5ac3113bcd3d1 8bb40fa5f58d155cb5875f14fd8f540b6c5dd7fb230707cfa3914d8bb76a9985 b741f627de1025788557446cd8571f965165f3b87ba70bf9593d2543060b1dce 40c2cddadde1a33d787f42ff20b897470f6c49a2d1cd8fd9c9aabd4ed20d8098 b9b5944a94b1024f7f03d858245bc7085f2bf8c9b559040404b2a8f1f5668353 229f8995a931a23752d3617ba4c06a74e48a6f3c8bfd40aaeacfa2fcbc6ac031 c97156ee1235c56564ba3bcfb12c645e5eef9bcfa4173c3f7efa755646a3999c 207cdf552b7744e8e68e4721ee56795e2ea0d00db61156784b351b07d91d9b16 cde0f0dc90d52b59a17d9f220a8993787153aa1b2dfb30074633219be62ed6ca 2f8add5d450bd257117c2c40f33b50dd4a85ca2946b10217344e842ad29a3f57 198859b069a1c48e96f6420b89dc69cbfff32867574717ff02965e9ca9aaa9f6 da1c7cfc3af582887f4bf517548956f949e1a83a8b82a5c8a396df15e1ad1fc8 a0e5719a9ffc23af748a8e062ce1ffb8c82da607c2ee26993b0e76c01c1951a3 05776203a11284fcd79016b18d7b4544d10b9ec88a861baaa3b980ded424da0f fcf8075b1a91c94ec4b6f8412da739dd74d749a3cc55e9574e0b9d982d21ef43 d567383f5e2709fd6b640dad0915a229e62d8e44880cbc20b71637ef6c883cc2 8c1c065394f4585c0244671370ec3aa9f31c73c109f50ef0290e82b41730f3d4 a6def36e17f8f1bf3225f801454d57b2f8792adc94b1933fa01af88fe8e967ea f61371c2ab70bc8012c87fcd14f12d7ab1a2eb51875c764acfdfe3a2b3f69487 aa0303635376c96892e2e2f609d626b6dcca8b19879f5add956927ecfb6112ec 327a716cbd42649a2f59d3fcaa59cdd2049e94a96bcf21d77249246ffeacabe8 50123f75a9558eb33656757408e2ab0250269a03f9ec1dfa8386b38ffda39f6c e38b6d66bb8d6be42b76fd58aa01f118da2cd9249adf097f1b3b4f46a54d7ac4 108e7f9b934c25bc12d2fbb18031bb211dc7cdf996f111d0a2e56d6cb9c6a9dd 5074acee3dc35437abbeb588f5d942f968d449823b29942c21c79a16f05e65b0 6038f6d5324fa1e378010bf8ce3bbe897d5165b764396e25c243db6906951f3f 969d74fcf9d04f95b465ca2b88e50a79c678cbb3d1e1cfda6002379972eb676f deebec572142847258635858b17708930be57b82404f14d028005099d670675a cc8970b85874d414e741607ab7a9692512cd3108c0622c89128101fde33eaf83 ddc7f19c8d9a83c0c32191ca81a3430383c6de882741218a4150c9779559cae4 2270ff3129579cbaa7f986cf738785ce9fbfe70ad863cb39de9418905775758a 6e2a1ad2fa32e93d2dca5ba62643116e6b0788fcda52a9dd74c656e358370580 0d7b0a579493f836a031ba1a45411f36e4174ce06998bd231bb22e4a61aa4340 eb7759d06fe9444869c5fbfb6276a97ca4c8fa577030618ee50c7684900237da 799b5c7306c3f2882eade612689f64b84e03fd984f229b2bad363e9d22b33895 271ece66610fdafde9ca4766cf6e9cbec05386e840d0b161e5508b1a21d025fc 74528f7ec8243c31361f0c20b8fbdc3001c7af4a03e156d907048fa5b02a939a 5cc57310e3f8c9b79dba293353aebb162d7bac8535ac93366bea3d4ba7421dac d0440a843f298088834e32c073f27400c239423b5964cd4cedfccfccb0dbdf7e 61b3bd3533f547cf1c95755751fed8295be21372be495dbd6adefc160bd8e3a8 0a62af61f1c5b60e5d8e0a73ce851c3118b3a33b3e98248508ffc21c12e1aa30 a2bd0986f7ba0a3e2acd06c9e5bdefd96e901ba630b261ab1dce6ba18628513b 87a2209b6183ebbf569c618925fa782208943c0c4ba3be4ccd1dbbfe4fbefa80 c929225b641df9a42614b29645ce066050299b51fa4f76e4d5badfa50f62faf6 02b21e01e28dd2f197fbd265b82c6febf31d13c357e2e524fe770938786c0898 e224e1d91b7f496640c10c658c983faab5626f2ef388c8573262a5c2b803d737 f7648874f6126260ba9b85d3dd99419ebd95a187a00f113efa1cd8e26e24e66f 70d018da92f36ced31cc9298b8be6e9b7d1873b3443c604e0911be4cd6bdb190 0f7966f0a07e18ff4715fb0d0cd23d99c8c6aefb0295670e86eba3100458c466 327b0f4c5a5d34c9e69b5f3c2d9e32191ea616f31afe0cbad2db717b29cc4e15 e6c620872b328204fc60016bfd6ffcd5f475868e9eafdad2f90fbe8fb604653e 367bc5e3d53ecfb280d5bcdd33d37c3995a9ea2f4488f20b0bcb8bfd84b9e655 b826533c6aeee95b7f8aa6b9bafd6604065aa3f048e55acddee13898e7f9d41f e7a4ad5121e7e60dca0ebf2f49de2f19f622ac3bfccaf7c59d548e08f5176156 7b9802431d797c61656841f32129f8a99e23f625013df856eead6a0eb63709d3 6a7337412e7935d128dc296c0e35be814127f25ffeb42b64ec0dbd294985ef11 2ad88ddc9f00c78f253edf8a26757c38f2ad59cbfe69ce6cc0cb6577dc863782 d8e3961134ba49851ed743543d66a85dae08fa786e859ced4d4f1e9eae6c148b 157eab6090d78b4383f756450430cb3a4a993ba3f19e73d04fde2425aeea0703 614ac9e9b8f848877e3ee8e24d1b4c597f6afc2e518175b02b209a69c0a565c0 0a4d2290321b8aeace3965cf602c32739a0beeaa91567df3ca40efa915973447 8ef0ef41d7e977f0c0f2b955e8868d331a2cc5e1aea3cc014a64d96f1653b80f 6f8dbbfadd4f875bd3fb7860e6b522be87b40a36a9aeffb7d8de0115f2047b0b 66 03c51da13dcfc9a1fa8e5c13ad5332b30ab297f8c71020d17d97d4bde7fef30c3478d97a496667c876cb4575e00868ed4eadcf01138450aa42287afd5f188000d15fd50f43e01508a008c4f306831995dcd88cd80a3bb9d133f7eb7112b10b0bc5ff61a955864b72309d25dc0e45053bdb884ed93e6bb9f0779a225680648b0039bf608b39c3da583f5ad7670077afbe3f41279c9df7760126e74ff5055cf20e0de870fb41126b9da1e1e789fa09dfb2cae73a5f3ec2c9c0ebf563e7502f560e0b24fbda4ce29f8805c24d20303e9a3a94772a57b6668c12340391b0a466f60ad6970ea7a5813f77a20b3620b9e1e433f003ac04988c2454b776da39ff89920d9d5a20fa2b3d4bfedb40d4c384a91b719483af62ddfcb141230cf957de6b5e06cdf17130a8c3233aaab69a4c47b3b67ce20d47a39df64f424e160e6cc52e210f9409c8ec5a6711b97f20096ec1c3f102d4a9daaba9c3f867dae846cf11583e028fe0738057a8a0dcef9a6ccf88510b7dca83260001e3253092f3ff25791d6400880359ecdd45c79f48a2acb125552dac5e5926faf0e7262f795704a61d3ae2088570a4dbedc6ac3b6f58639144faa2eb8fb09a6f1f5a8ceb42e1173bba76ce071082d4d96a654472963ad7a36890388074953b20279f2aa2630d5587599a970fbbe535d782d42d4ef315ccc95b92cf8f8dbb9e8322b17730cf7e055898b9f0096e5dc2ee04ae051dce7e9a85547f7a85f7fd17d2285d3b49ee0695b95ee6f401440f8529ca8f2503f2169e95de3fa059a82b7eb175555d4c057e18487c97f6022b2ea08c73223f41b5179cf0a5ad89314f12463041e13d3f1812bbff34e923008e684d70a5d6887fe9648ca59172d1ecdd396f278476b9913e029037dd9d9806e3c6e1031cf6e76251c7dd239b9110ea6fed10572bfd402d8e4505c8c689ef06decd16ca06e9ddd74422d0105720b7e89fd94037b3ad11118690d0c7cb66310f2b6b355304dd4f37f41e78c02385bc2acbcefd4639f73cb867af108cd9d5e400195513de1fa4dea7ef9587ed647c3907f7406fc270b782fcdf2e05149063db07127f2c204dc5aad3e7e71f8d7eaaa4ce6a82fa6ee58d2300dcd3c5b2d09a4309b0b5e937f272ccd9c3de375257c9af37bfecf4c5b6ddeac00753832379f1ea069be2e7eaa2f85e53afeb9a2c104b1058bf862d99c0c0fcc7861fdc35ef5a710e45c496802905c34e71a170f60c0d5ff5afd149ae285bdbc1c61f1777c71fb001bc4f0d378204307ef691a36e5b3bca6ca2e1c45b9059a7d2a54b7245a6ed540839976d0cd7c33dab7d617c22dfebc09372cc3afd54e6e4b9ea78ef9d5a797e07fe5689dae6a53c2a790612d53ef918df706e4a120906f56f7bdf446d84733c06319a7cc3712dfcf83eb43ed60cc79ce7c8a6f1e1949d7ae10ba40cb6ecfb290bc7f1766e342f4dc52b59ca2430293e94ee1fd8e6a49467b7d05f13e7d7940709a8198613d885e9cb81535d1bb823f37a751871ff44b2635dc251736eeb868606d9cd5092278d9daadc0d7d43885f0017124a46047229cf11359c992f616b7a0cfeaa52ae24e14c231b641ae1c7e224f3c415a4acb46a1d358bd1c17307ebea0ac5c8906563c63678c95075d9bb9ea4a12f9df4368658bcf4b84cd0e895a0f30245d08fd3ec4cee9d667f562f79e2a9f8e0b76c3ea2d34eee094422b561772e0da7dbde0f80df0414b68c1797b5cbf208a2c1cb900005e79ad08632247e501509ff883b41224ef381d7fb414e58e6e4796e5da5e449baaec1af97b14a1e44880d658d571ae26ca9b0b9f9df5ef7cc5ee161a4c19768619ebd95c5c0451895a90912b02449d9f1242f7d57c56a07dd6cf7f261954ebc33837fdb3ec53b443c9901716a062563ddf9f93fbd7f9bf1b91efa7c0adae3399d2a34d388202572b19e0128e79f778b674e83ba210e8b2f0146d6529b348a2a884fba193a00746894de092e7c6a084202f8c9ee82eeb40de38d1c92ceac085b032345b00dee21f4f3c10066f6462ef5ba113918dcc1d785c6cb095590df263ae60660f9704862554ec80e2bfd353b7ce3ee7fee8c27e46fb3307c4ca19ccb3a76da4c242fc2d2850fac0961e358bcec2d97118c1b5337eb35746c0f13156682d5b20eedcc23f421da6001ea5cf0aeb54ca01f457e9e5f8007a24be9a5e6c6f644030c55134d25c704af0b2575a5d4df990c460edeecd8eaf7e18ecda4c710824cebd9492a0d4398a0790d4660854973ad4311eb71a9cc41c97f6c3cea1ebebaafc7adfa53bf9736444c06ad9d63355882eb4079d88c79422a1b363b555a413803dafb9844cd7716ba3c0136bdd402eef6669328cab8e858fc24d831d44f6f35b6ac15abe4925615fa570fa60203ae74cd04e55d3940dc223bcede1984ef9b9c9bccdc3a6d020201381200fd7545ece2194e831dce2ffed5221372ee9fce6e74063e7256b6681e3ca2f00b9a4622b907ce1f05c280fa192d943511354e29146854331554707539f4066d0c09899617d3bbe68d3d881ad6826a592e972ced5c50aac80818df150180e31b040b04c1f6bde965839e3c96e0795288d122fd3c56781d14fbd9879fa2c06fb204c752903af2e755bc1e8858338e2b765c44f9404e4a18fd0f91b3596c9271f406bb75e09fdfd2f4904455c4ea70b054b751fff7136a773d93839d4f02edfbce0e56cadeb1b6f6eb529d8242cfc8994a58337c28d01228a29d31099263f05e8c09b807a97e73e015d71e133b986f5df9282833690c6536db7e7379a747f0b48b0a84e235c633b3331840483b7a8702a6fc3c0fedc43d4ff22e0da1d018d389700ef635d82e8b5f530984a6af95acd2d0d0808d698fe1538a9355b141a9da3b760c8535800cfb9711700786653cec731f1774a04c4a950a6a109db39e2d6510930210e6345da5412f62cf67a775b3d62822e78c32c9cac5cab36f3f30d3edc1d30f00324828b0ef0be92bdaadc599097bfcefc43e4e4c3624ddd7fda7b52a22d70241e3153bf2b6acfa043eb9eaeb98054bf9fee0c0f634c18a3ba9eb34f1279a0bf6bda8447a37ffb5964d43d7dc3746e680f9971147fc988db3a90e80f0a5c10d1ab067fba00d24c912db2a7d9efde5b169130f124c609b2c2994334d9ae6130632dc2b46a184502a09c2968d07ef8dfd6097ef014091ff2ebddea5e3c09efd087a2ddc5cebe7f41f8f54bbd5d26b651291aa5f53a3a825bb8ae21e9a6f78c501fdfc728e3591fabfe66f1f3a00295abec0179d9cdd9e6d875621ee870c14dc041ea89f7056e2344698cf7dc4617f694284d8b6a2d206bf96febbb49438df6c0dac8e19f37e64d0e792713f28e771dc631a01ad06289af2de182282f6a1e89305beba4711b86a82a4ec54ea0fc3226f07c2966cf908c8351ad685228913863900b0d35d17cfd369c374d1395d5a364527d53524fa4f96707a7b3a0597acb78b0bcd07e8f7ca27e1e5c2117bda6be169dc92a392031af88c52811d169ae2137f0d1639c41b4739d4691f8f57d467945b0b1dc7d82459fa678f75debb643b2be20fbb18612a84583618eb0ecbd99799e5a23a05cddc8a2ce6f3275415681ca8e20ae216298b5d526c1f74b503514ddb32b4c243c10813339db16eb91c578ed1670db4a9d2e7fa13450b67e317ced5ed3eb4edb3b848985dccd452ab6be85d29c70b7624eae5b56f44084b576eea89dc6fc85c6454b2bce98b19d9724fa1fad5c30edcb1d40b3646753c393d0a93c2dcbe9b05772f3a2b2701c30828c541ebe0a50b54df2180afa9bd2ba0d8925c8dd9f4fc6cf66bc6698cab1d5a522d57f90afc0e250ce977176561b3e909d7a2a2383edc06df64490e39b503d5f6ac44a3778104ba7674715304b05df024969725c024c55f01ef131fb9a0048af416d68cf8130dec17a7afb80bc03912e4b31d2eadc915de1bba343c007b5b5373cc32267ce806dbe00adf2c2b714332b3eb9e9102f20f2aad2f232a9b46d251fac0cedd64bc0764fc6a982a589d68e0a8f787e41335ae22e6a1a5930870ce413ca7cf86d13f05c90b6d8fdbcc74c35a34c24c73b936f918d5ed83b4b7f61794b033a5f5e81a0fe189252508a23582fbb86b071d0de463923eb699fef4e9d7140b4a68787f0f054a4d81f7498be4010ea8514782d16b8a486d0ed80a7948bda0e0273bc14b2403496513885c5417bf007a5f93fbdfba9fa3ecd5a3a871a77670a5ca794d7c950a50d316b3350a4f1f0ca2ffb150fb729c88905dcdc89fdd6a5d13d0f84a8e7e0b94d15f66d5270f4dba5b7e809bbfdb8cdf50e0d61311a1d6e5b5c94f5901a60e9ff691632f0aebd28c989ec35f7e2f4e234f7cb9f2961b6211c5563ea95ed5063e8ef823f742950b2b93107ed3fdca7e259225c1a5d6d8915f2af9da37feae0df0f4a7f3efd4cd358529cb0aca99ae40b8220cd0b14491914a5ec266556bce0d571605481662abed71571f011d6e7c9f31f94bb2a2d48126d8478e0d49ae2004e5559a482a01ae8c1ad0c736969891b07d17a878535c1bdb572bd08b23acd20a88128123843c4db57b52f18c880f3e3983f93df6e1b60548cd65246cffb118095bba492204d33367da8cdea1439d5f5b70376d689f42b1ad7aae4ae71e658a09d2db14fb0473d848dda3980149322d3d0581ef979b723ac8cbeee5ef6e6ef30c99ba14abff111fd533e31dac4efeb7e95a52883e9b2e17dab4765ae77b6eef01e1ff2abbc2bec91e033c5957b53255182492a6e95e4c3705c0c95b4e37eb3b0aa88e306e3e2e25dae952b8302f0ad9a635655884e2edf73735864b0814299f0743a6db7d478219fbf168fe10905c6f868300b7d976c04cde92da5f82318f440bc3fc2328e9c4eb7f4c27994cd45916939c0b4eaf610f1670fad5ed0fde56520f8ba2093199fa7050e6dc397c68a1628ad0526ea89313c4c83a52fc6165934302d82568e965ba51758994554e5ae32169189aa0295d3452487ed949b2eed4c10bf63222b64e8a7662643c115a0ed6abad31df5b8f59ce6d1da8ecf4a7cadc1e0b1a799e0f7c3290e2338c17674a51e150f609de86a99ef91b1006297b4c37f80ca43711dcf7b6180204e14ce0b147753d55047729df62bec151d2cdd24dfc540f14bf6e1bde71d4eeb25ba6d6b652a8f3f9618787cc665be918f1759601720c0ef386e71627c954605269024bcc08dc713edc59ecc568edb6af317cbd9448c30b5329b0c0d950b0e1a59a994aeae062f6385d638ef3af45b9ed1b121cba975105a042b692c82b722cf674ebe787980a4776b150337ece086d26d13a74b04b4205b2003c5819029659d532ab6328924429cfd9432965e9caff62d5daadd2d5ad004d78fc7d1900cfbaeba3e3779f60ad8e3fb142ffc5b4bceedb7f3399dcfa0103b95f6f1284a1a276dfb75791d92cd4dfb75a497a84979a18380d17ac4a4e290691032287351059ebc30a157a7828bc987a271aa2a094be0d6d27e3b5248e9a035e1365092ffdecc6c35b5d6180c32b3f9ee5f98a3b87e0744d598534b5c4980d2320c9b07c0294d8fa323585f7d61f1eef8fe92f027af2687277949222566606305c8ddbcf05bca04a157a9513642789db3dd674f56225569870ee3cbe18e707580ff74a3cb72af39acb31f8b2d61c5eea4daf3f164b88609161f4254fa5a30ba4f9a5507aa45f53af37f707bd03bf1ecd90eaf80d59d7d6d7452db69578e20f0caf1c15368b7796c18b5d911a317563b4ba02e0b877e1a94e403301b27c8b01570e149da07f3b5e5e1b3b8af933cfab70d971b15dd5ea2fd804ef0b07622800d4c62080d3eb8731aef44c554f8d21227e986edfc023e05125c58d6a9122120c11765913e60ee2972b05e81fb1a17ecf00ac29c4842ba264ef3703395eb62909f32b5d852a39234cb8a77ef60db93cf564f9a9dd2aa2c736b63f79e8e5508609c88db5b11f7e5666ce5e3d26df60657db2b3ae1c19d72a031616a390ce055b0bb67afc359e637fc6de1fe8062997dc5c6e8fdc92042bc899a6b775f6d3dd390ae2e83a44fe167cbffb1903c3ac24649221375a7be3730959c96d66928f907509c00e242ef536f72adb1244230cd0c9111f0464e98a1d8db78005ec45aff6df01ce2e4ed27770c7b1393c05dad6a7196d2adcf18e7f89d819a4e077973fd3030306faddec05a6b0aeae8a196d5407de08c7a65af9b6646b5930168646465516000a81c7cd41620892da603cfb9c5b69a0a5519c0e88d33da4db2fe4f7c8e19d00be28025e2be62a58997d7071cbdd29169b0040f1714ead974dfbb4944abcd40b03ca39e49153973d4b5db8c9086523897bda887fa239c6f0276aaee5a594280215cb987d1a9fe3531256be856c094393222f2ae31239e7c6a57fd751f4fe22045849b5eada89f216fbbd0e70126029a265bf0b1331ff5c9739f5f89d31a07a088ea8c1561a5eeb0822f66a29dc3398736fac23c4a233e961b946af8e33a43409d9eb922701ffd0a098ef09ccc4ef2c8672d29432c21bdd9bd1b418ebbcf55509d65d16ea319219082ec9d7313f71c78502da080e78465ad72cf983a8da8cc10b2aadc39e74d5db35b65c5fcf169fc2ec82799f5dafdeeb9edbb234095b3a5b0cacc31fc48e0add8b664bf64a462e21d68e1a7121036af4160c09034676bbe50b1067847250f781adb2cc354ed0e1b16d1a8eb0609f3a5d824d547cc5ba0891008e57232028a283ac84d511918728b20f8b06e0f7f000526ebc2bc92878ede8002f0a3b2c179609a23548130bd942991b2fa4b63ecd135ac04cdb685ca41d50084167a81b3bc3a772eb1e8f55deea9cc055e7acfedaaf7dd5fd31ff7a0fd9bd0425029fe6942d785963d0b7b37045de8598cd19d12be5133162a004f2afcb5e050ffe67939f08ce4bbc9249eff06d402cc814c36ca12a0e7dc8ef95af6b5f4b0ce3ba69f5abea7cc5e74dccbf9cf7bc431ec562dc8d0fb6c36bf6d64fba64c004d0889af8395674f043c732256d1993ab6f861aac75330ef56921449260ab95097a92c1b75cee135ea8d0e63d1a0d5b5121f082f8fc4ffa2308521a584ccb2309541cb395ae243bb1fcd8be306d1e2ec6042ebad97b12126098e52be84fca7509f003888a248256796f038f30c59dfb2133e9f42f6febf4af86dd0e815e73cd06f6adde63c7c603ea806bb9012a5105d5204b29b23e16bb21efd96a43dd4c2c0a7548ce93303cb226edfe90d637d13f06d73f70f5d2f407fd60a45a6e01bf32085a83e9b88fbae058442a96c6843bad1529156b5144cf36f40fba36d5c5e8cb0af59028e1d629b55166c7bfa0fbb65354970ca7eb18ef7053d0e6629a7a75d30a7067b93a34057d8a3b788c12b245434180e1cfbe507faa270f1809c14fe79407a3f7ff59d3188f25f92c0376f26d0d322e7d65038b96b9436aa1b95cc4677503be84e6cd5f01359e5eb862c11ebd8b45cc18872518326b1f9141515b8747f60665015cfca5c04715d9168663a2b190cfcf198b9f43fe0e39b48d9e458502d80b3dc0b49a9dd3fe77820f7714270715656acd8047d28d4a30ca4f5285d9e19c099209bbd3a50c3cbf58d9620b725a249a9c849d0cb8388dcc7f2a90502e5efa0dac0f9eaea95b72a31afef787d38b3d1b12753cd5427a3549f97545918acbc10a81ab5eb0bb841eab9100a7c81028a32c8d3826b836136942234e829ed2212a059e9ebd5f7b37417b4fcbe5c29ad97256d4c8839b18f930e88492ca2c24b59b070460826fcd5185c05edee9740e6c10733a047276de769b55d352d080a7227d05ffdef14076d65e5f51ca1aeca5611f7628714a2be8e482cf9533ef9040fd0e03ce97908629bb2ff05b40da50d3e52729793df7b1af7b80ade2da610e1cd3af0c171b287af79e054a9586ee6dd208c1236c301c7fba9edff173f423187c49f500b0c405ec84e1d116cebe34083e7875a80a3cc273111239dd088a137a3e4166058ef6682eba4ddd344d3a2ef203fa59213ee8931e73faa6d87ce98d19737c76009445ae9f4d31bb8a708127ac42daff428b8479416f7770e26297890b292a9d072e087239be25a2377479481aaf3554cf74850e77afebe01f64edfbe5b9147101aa8afadbf7a7bd80d25b2dde042a67dd45b2b39e99897473e858a41e5ada7b08431fccf2e2545bff71f76b763bbc44014718498a0bb4af8c55d2f63233192e05bae827de253f07ef551c81a3e75db3986e281619696da63b623e29edf998170f069f1c4702977d87d5914e6491d5876af99b0b70c778b53123fbcf92bf10030df768f6b40eaa62f06ac2450e8cfe45d57cacffba3f938c3152c3980fd178650d80532104b9e0f031d0e9fa15d679df8264762bacfd18c6839e77b8349b462f09ccfc92c01f5520694ff846cee53e587870710c32d99e25b2b11fcdcfa096520b1a244add0e6ecf2d69ac0c9f661efcc88b72ff8148e5c4669f8b9c7e6321580bdf1c857c0af522d1c14b86274fdccac009a83ccb0171e449af8451505f80d000eeac91ab84eb89f5827f0081a3ad92f5eeac3176e65d29ab4bc2e061a5305a049698c66c0ebdaa2b3605696fa1132f19737297404d2748eaa1bbcaa4547c2d0d22441a8a146fa6da58f08557df4fbcc7d227d5bde237ee5d4fba7baf132cac0e9f5d3db2ec2f5e42776b8d455ec93046ffe391fec70f3c327f09eaefda8799026dbccd6c442d31efb4e47488acdcf8b7cd15c35de959f181a083c0c02b759e07667805be536e47ed617a228dc9a57cc50c1b732ffd44b0d912845ff3835a0608ae492f7981a6ea57c20c310813f675056fde9bb1b96dde014acef3fdd137e20a961766d4410711df70bd5ac52f24138425d77358a3b43aaa5edcad2518dffd0c6bf1394b8432be78275acb5593582872617baffc7aea38dbbba3c9beb4dad706497932f99a04b978341b8e411abe55c1d675906db732e938b5476e4d94aa48081b2cbc664ac0ec7dadb6b1ba3e234672c8b5ff79f15e2804036a88f2545b70098946bf46e0bbc30c7bf95fc42d4fbc6b0acbf3139086cfb21dbaf85875d78502feed91b22662f5c8740e393e8bbe0bf3d3bbd44bfcb1fa0eb6de4e2780c33706346cded5a4368d68824ca575f98ef74369846de062c0fb855fa1758685758203f3e3604e55eab54d33d3e238d54238a7a3871e6309f0278b62ace6b8b9990408c977b6eeea0310dfd37bd1f3ef165340ec8bc0c962682ec53b66b615f72b16048537d80633ed368d483199d79100c10e1185a79c30afdb47e1d202a25655d004ada330ace94a5640419af934888f83e6a60bc88249d44a791589e41d9cf1170d2066d8dddb16be86c17b64de3276bfed708bd8824ec15408eb4fdb87d5f8a107305ff5d4c21ca34c26dee48f22d06998b03829d6fcea08a1fcdf0750bb2a510fdad8ff1429b48cc4f233422badf7eed7db6f04f32d711e77a4a1a21ff122430dffbe9577805a689770fad814643d398aa5c8f82799a1b45e2d001b8ffd0981004ed12065d46d0c4613844cbff8bee75c592e89f1b3da4383f8ba00ae6d28f60fe27054487ec5c8c1c0f351db0c0cd8bb7ed5c8d8140fa5781e62b8db65d2d803423488b01fd96996f66590941d325d4fa202b04c3f073f74c441533d16be1606afc3ee9824dada8d7f5b0d27b66d2f300d0396a1834f8f4d5f0f56ce61c4c50a6b12f9a2a4930f9cab4dc40d1976c727f8d785963711a5a7545149fbb7ce5b050ed4f6792acaa88f182a5f6dfbd3fb2c0d565e7ffb3827bf31a03d1ef7f6f900c7a83cb2be7d1c3c3d3bd3d5a4b68fc2d8727796572758fb1c53e082e3b60b0e8e829bc6916e2e31ef802e1228e5b095f9cde3d9cecede8d5c1e846a40e0650811f0d6b1668b97b9fa401a70efd3313e8a86cc47f0a4a6f090d99ed659b6800d7e657486f4aed9e00d05e643df3545855361b5c556f8cc13477f2925c1c8dc0af4c73a0432f416f04c0907b89f5fac84c1ec8cba4f3dfc58617dbcafb512d601282031f9badf79999bf015c30511cff54b12f6859b0c5f66ff0fb186a5c5d70ed0edcc5898e1124364fd41b1d513dbf5131ea81b7d27fb89e2a69b4b8ba35f0789d53d4a69a43885473a7d194ad09489592b194df1c93dc8419ca0313fbce20bceda08d246145d6b272f20a46434ed0e7a5ede9210599837b66a8df158ab690ba9d129288ece220a546a28e524a9c19331bee27c73e98873786044d9aa60460bd04e1adc411385b7a0894ef821068143d8cad40ec0cd901b514aee6d9b2fc401b83675f28c36a4b181958e46254059e0df2838f2a2975a18dce87a34ecdd100db72c4dcc5c9e09f7b57b707b91886ebfefb8c938928f8927268d50d61270720b476b046ba1023cad1a2e3b6643e1204a229d82077b5db9299722aed9496a970ca3bbcc18da52f0f56008df59948ffe24f9cb95a132e60a1ed30c4c952134a90fa130f15be236c08f7c612590ebe317bd911d71ab56e27f573eb22b66f3e3500431f87fde1d4b85a9e63dbbae60b8c4979608f669d367f382e523b8dcd1787b0235f9eaed9a352c3f1a95b8423696eea1115865794f0e68c869072c07518c9301187d9143dd7c9abe19ce1ce324fb321ce260e1365603f0a36ab0138d9c40b7035869608a42c31e3fbf9a53a17f3ba787a63dfe964b25fe1a7c242af20d65440d044da61d7b167467676cbc69174fb78c9ef1cb0fe813771ace6ef039fbf7b40cce1cef74723c9db28219cb0f609860e8fd6c0bc4dba65b9208969f6c7e665e045dba93fac738a92747a46a1562404f312e281d50c40ba0244e8f0ed23932140c50ed8ea343568a74d063bf7d8d02efc81a840a65595436952ef934a65443fb0a273454e67654237a99c75db85819442ebcb0e01ccf6bb4e7135882c796aff80b1b137e7f2e4e1e17c73fd95e40d8ba75484b5c9293f70e44b0f22c531af1f7036445cda03cf6e253a0179d4392669ff380ca9a632349e04613f5cc1f171e5008bacd84dc144ba4b3951ac8975498dc129f8c76155da3982e8bc1001a07ace3085c7320402035732865dea7630a66ffc43ee7a8ce372fe00a04c3ac557e86950bfc40e4a28a9aa2c83fc323cdfa3100570fe1c811e9cef28229b8c571e7fdb2033c0b580468a97e52a6450c469299870d80fcb8c22051bf15f225fbc254141608f4c0b673da5402d2619cd1e0114fbabf6997a9f111f7dc56482d398cdab907024fced55a0b847be69eff5d491eafcd34f1e29fec721375da9153dd3267ea9d0c +generate_ring_signature 6050b724afab4e33fc1adf423689add9c50984ef8df4b93034fe824ccbff6d6a d1588a8bc29b2df0d555b8b0632841b68cbbb4623ee615c9499862aa5b732cff 120 ef87037b6f29edae32f566f14ea179ecf470fbbcabf36b62d252b85af30f35e0 0adbf81b03429adb494d54bad3a726c919e81df09046e8f237eb9b5f82882a4c 3539a4bd1b04de484d125456d2135230caea0bcd47d76beea4d4521918f7e769 e01e642c44600e167c640013562d0d83d62e9eb696b70e9ca217725dd0b46ad4 9e748c90a8fc9e8839f770f94ed282e08b2d0319dc1287bb2fb3b240d84dd055 43001d2b2c696470582c98b0410879d5f5afd93d7bb90cccca625d289bc6a3a0 dbe579be20a891db9f42ecaa18e45ccbc4abd200ab7258131365a4d5c93e776c 69f3b6889f8d6d446374ae878b38da35741eaa4e4a88ef220d16163703c244d9 f8b561dded476626a7c0ba1adea2c1dfd69d96f0dfcace37406cb1bb25b19d14 881e289bc813db26f4a718a6d790d553c8edd952fdc6e70f1434e0cc81918098 0a56f9f412b6080c9bbd334a6a0ef92ae6a61b038d6a09b0b4f1fb38611bcd21 2b8c0b64bab89e760d5a74376f331ff45e5a5756619836c00ce5882b08e3c164 fb0b6c65d3823cffc4fd3fbdf0f7d867017a8c2d2070af7f69753836a10b3346 d58bf0a33db172ad6cd6460498f3fce85fb3a138694c3beb46d48bb5fec7fe26 0ab01cf3ce2a8d87dfbadb6477bcba61ef64981fea057acc295aec2dcc9ad983 3936b64dd7d013462f90d1969d8c601bf6a4f0bf45b443534eb2ccfb03998ede 412213951f3a59b88d161c057933de94085d7fff3fd1e370b22b16855b6df2bd 5d6a58959691c9c8a62c09bd015b84d4fd7a4c8ab3826100512dda43cbbb4ff9 7eb29652b5ed2b1080aca08c6eb2bf7a41e30df6c229fd56b5d5096905b2acba 732bddd78f3cfcfd342547d80cd2010ae931a76500c9fc073cc193a843839d02 e48eb1544264647008711c351e81c32f81e41f5a7c85a7141056c253e8e856e3 7288c441a034b859a5056dfe0fa9911c24775637c5f707c2eb28c90961747514 f06413f8ed307215eea8842d1f6aca79eb1846c21e1c4c243b665ba195a1781b 01b8892d2d57f8bf7cca182387a6d0872a92fb1a72df366d873307ea3927fa12 d729b986311d8c0da3ca87ac439c5fccad8128a5be990850a3f5820846147146 4b4d2bc6efb964a9581dd77f183a55567cfebf196353ded9b03bab6649ecd10f 4f12843900a11cb9802ad2474cfd41edd21405a2bdd740e9739c66a5bbe50223 d93acfa9256172f808b269ae6faf49ef9cc3c86026efba2002d2eb6a1da504bc b869d5d99868014123044ba4808bb55ff416a7590cc23bec4d46f7a517ba5b41 35b15cfed88fbc7ad9034d47394fae12fa8287dc371b78a7970c51c0697d483e 24c214c701ad51ac08e0a57a8da5c0459c2499910cf99a6a851cd435b47627ac a92fb963867312988139b9e3c29d2076d1a7f051513b6f2c3c24d74f377f2e37 7e4054200f5643f3437795f83bdcf506d97221196ea711b1d69afa5e4b345978 a9c74fd8309fffb5f589dd48f55e29653b8d0638473139eea572bcf4356bfa13 c8ffc26337fe41548090425edcfbb21989da5914326fa7ea776b9214252ec87e 3e25940afec823a365f77fb1f13aed2180167df85773ac52edc44f2346ff7c59 ddd96cfccaf4b991b9fd6f819ca1ecf8e0996e42862b9d0ee71f0a446620822a 50090e56c723895660648958c033bde07fddbbe89149b1a8c8656a6a35a4bbd5 74912093994ca326fb15659020de86bbb291c425b8937324a0070ca4c60a9165 68fd8c81aabe602c09f4b37046db3fd2c15267d974c3697c5f6f35f25efc8183 44f490d63003625443747a7243287d28b3f5fe4ec2a273131d8bc7e09c461d05 6359841de569f54123834720941eaaaaa59b8f9c2671fc7c83ded6f831e9fcc6 ea75a676b28568f3330e7d9421ea92f3ad3cb9ea67ca6a1662c45eadfb67182e a6c073f05c29b0ce08c57cf36d71490d5d40187d51d382e09fbbb2a54114a376 f4b02dbfd2253dbe13ada78a09b53ee799fd347705c07a9538cca79fe719845f 4535ea3b1f6aa90a6b98e0b940c164b31f4787b6a847758e88ffc7fee05d5cd6 8772138c613d9fc8f3f62a0373d7040616a372212328d0acdc333d62fabf9a40 a8f52f5a71eb7d703f5478f4f382b2cf3b0efd6538b24ecd632178dd432dae5a 97215a35ff24137d83c793bd9057ebe8ee7e310964ebc5d41eab6d15342479a7 e7ee87976fac8c0a016d83d26fcbaea4c18103ce971a1d695333632432cfa1ca 00d81de15264f2c13b567041ed3a8cd5331cec6305e4ce7772138be437d62437 d452fc10e867349bcd7f3a783012d1b4e26befbc821b29f8fda8cf5e5b8c9b03 96eee1a1c980b51b51a3e47cd893a4930acc2a61ecda8beda97ba416fdbd6f15 a828686eaf20007dd299f869ef52fae1785b0f25810a8b8ef5b47d2294b77349 bcd0fce555fc44ba05a71cde39e36de093d44149f803781cec70a1c040d4e114 e5d10dd7877e7feb14ff7ff3074abbce9b62b7845de46880a1a3e400269e23fb cf4cdb04cb0158c1397ebf413b9940424f4eefc3aeb315b134bf1c012de95886 e99a22d2d2d0bec068aec00b14213757b498140f6a637b3d14244f4a83391640 e1d337d2a691a786e85f0f2b6be24fbbc6e3b0916986de5551f2e04eab58bbcd 1dc8e63527bf9ab5699fe1b2e6d6aac976da2fe8c0f3ba390239067f19168d03 f32db1edd95b03ec7a6cc707383072b2f1d9bd7553ca3213a76246ed050e5ab6 9b6a260abe2e997d96e528bee60949c7c79d22e88e3f97ff9740a40c030e05d2 ba6364da3293a9a53a9068e15387444500d6d5a91c45760b30b900cc5a44cdb9 5739ad6c057d2c16e74312a7123fd6dbc46a1f34067f1a6d3f8751f801fad433 e6bab56a1a5f21bfb687e77f65d0ec0cc0063576708f02b204a6fe716f8db773 97407b2907cb431220e5553ee94eee4b92fcbd7d3d26f11e48399f5c9ee85be3 861f72244c53d41969ca914dd57e15b82158270e5f133876664d689d541ed165 0de2abf3741bc18b0f5937818f3a1e33523630ad8e1cda086b955c2b13c4817d cfc22f7d43b1effacd87521b5463772e8453a2798f2d48c2918d264f15c563b2 26c67ae82b3c310202c1908af303e69ca94c0ba83a8176d54d509781da183e86 75b7727257ace3fdaf28bd08606f4e8d471a805858a4de3af7ff1b295a8877b5 8cb68849c5752cc92d8c718605eb5390ba07013bab0659429981cb8249148107 10e3bc9b4705f0a5545deffd9d83f16268f4963d4d12225086432dce3f317d82 994e0e93851f6565314a797059f6a68746533f6d8afd7164538c279e3983bce0 0026807556960aa20611418df4ad89b46722bb4273305ab5beaee0518bf90b4a 5df227da750dc157f18d54abfe7ea27bb64eee746b41315c843b42ebb60a93af 6c3d71b333bd43ecfd9bed9e9c6a3438ee386283c9de2bf1d9cc6fe63eb3c7a9 5862c6323eeaa240cbc96df54754b7f9b38a982646dd58b29b7674fe280afa47 e59d1cbd91f6a1da83f811068d2c32d3a4dce1cc87e12dc670b3c8f4cd837668 e01b48407c6cc98e591279d215168d45f8a9b0bdce74294c863520a96c1f3578 d123f51fc47d4a4a23d2589b3ea6afacac1523ae68c9c3e987efde55960da989 b24cbf3af9e8598a861c21eb667e305b275091ff54d619de94427c4e8107b4b1 ce5ece118e978a798e3bec113fcb05480ca08761b12f4d82de6aa20c351dfd4a 881e216b3ed4aef9321ea28d6f31d565356bfc4b1df72b877881273b55de257c f086d77f57298e4001ff99f30c1ce019cd81a74fb77dc8d3b5e286a972b52b78 22359fd9b4985eb46e587cf19bb5094ff334ea115c12eedc31b14a0c1a883306 f4ca0ca1c5e64f8143edccbe63ce32279457871600f83f726706a37274f0dd82 2aab22b4fd2e8d361accdb45a9035695c109d53d69ca0bc4b6cbec1c5a5f73e0 d4b27fc292dfe7d49fa7cf49901503f5c6fa53812247a99d09fe2b540c1393f4 136c4bcec68a9a9d675f590e35ed6a9e51a85be74c269c66345265620f5f196e 2903ea5a2ff85ea2f92a411467005858b3a315b6b6b9c7a7b406fcf2906a69cb e86aae3208c02700d40ea0c63ec911ad32aa67fb4d5c7b055ea2161a877cced9 c2523fc728db90b1111de2a58e424cabb7dc53810094cbfed40e0f1899b31cf0 239b2dd969fdffe6ae68c2a227fd066b0d08fa305c8daa807db24925d2a7ba90 2d64e595338b931b929125659133566e25fc56874ef3eae77760e289a4e12227 64ccdc4872ce46da3421e9404faf86eb8abd0046239c71b8fcd9f2b7e1fa88bd 85c0e8646ac761449a58f53106cf8406af576c36b70c76410a038d36762d4abc ea4dbf46f8653be48bd964ccc8171a87d06c3ee1874eea739df7de9c8f06553f 31ef879b28137a2252476dc796f988465ef7640224a5d9b8b75bb890e8a8544a ab061319d1d6fb3a9cc5c2cde8201a208b82e5eea782b88ee93aad24785c2d6a 43d69deec91854813f55eff328db76ca3f1973eb498eb0f1951a15c806b8d9e9 f9f07b9a4f5969d9ced711bc842836faf8049d5feb3f4cbcf094089d0213a079 efb00a7103ff7a73f36a3b7daad7efbd296feae5fbcfc8aea798a5921fd4982c 9ea8ac862144b79a9715c672a206686f4ba6790c08159746b2707a8f20845b44 22f9d130216831692a2fb6be1a5956179794cf0d3ab5240aba781add81c8eb7a 2e43959ec556d13a5e30403182b5d786a6c90b1271333bfd306b15525c3838cd 7dd14d4250642888be66c827013a345b63ef223c79e5410d86fedbe880f49511 075559e15ccdaa2be0d98e6a4e9248189168612117f1161da8523fcdbf62e725 c071bc9b096c8e911e9f6a4b05726b4bd8cd54ee358d611c0bf0caf467764aac 82126c2b00980c6bbca68944706644332100586eae865a99391c3a99fe206209 955eea558bb0799db9ee5994a88e8d323e27a63075def3cd6d16a2ed82359240 23a79218069842b0364c4ca540ca80374492d6d3bdb578515eb5c62935e5cdec 8c107f0b24dcb8d4d5bd749b90782be058a6665c71e09052e6521a5a23148ecf e55ae85f46ff1d248b12fb35c35df934f4da4865c9969504dfe03eac92112b11 9d4c8f0d6c14ccc7a9c9438cd11224344b31f50c9231fab574d3923bd2ab6276 6475135f9644ca979ce611a47ce21f55f16da6edc548a88b7f1f2d5cb828abab 3f78644f896131d3080551c3b5dc669884f66a90069fc02d0980c8cba93dab5d 032cb098c9caae12e929023e907322382e07864e0e03891710413bc9baa6f628 03f519eb0e73ebfdfc8791829aacaa3c10fbf4a69505e658abf61ee87b6d101f 8dccaddabddeba280e5df36ba751d672ed25f786c12a8c725f972b6f11e3c638 e567bc025376197432a4459ab346d82730c42b604ed31e27b6f16fdc61351b01 16 afc991254c1f0a3923d5fb8d63e1dfd41ea1fa27c0b3c400335758880c55ae0ae4cd55795145706c3ec04a3bc87eb8e46858fc600cc6415539ae986a60adfd024fd93d63e1f3fc5d32e5bccd21630aa700aee62f7b1863b468e33243a7fe2c0be096261e629dd6a788fbc4b3c2474d444c0e2a3353a3193d8a66c73806abc60f224ae8f031adfbb93fc59d36bff07adc81a53a0bfcaca429584080d8627b4f0cd66dd0556186af14de6c18456c7ed31c4e3cdddec608b3c37cf182bf885e910237f2281ef98c41e0b54120c5cd0a71a6aa89c3a007b02b3165b23ec22d22c5032d0a64fa68b4d7f79d927e10c056a5762ce492817547594a8b12c81ffdcb3408a0ce9459ae1f59f6ceeaf05d5907accffcb926b8bd89fa082bb2a0636ab6f20dfc7b22627300cd52fab7f48bf5ec2ec66a97ddce816bacccc21cca27fb26fe03bd234330960b687fefe0fec7d80cd0f3a2ed84c61825ef3f7816768797aa7a021c76b6c42ea236fd4c50d80b4254f472079bf1009cfb106b10b69b79480beb03572ce46761b729efef9374690df2c6d274d74b122bb8aaf2c8653cb1cdc3b4045369edb043d9a4b9f21dd2625de372c74d21395df7753e97f910459e6064d20021216ac20a1dfb58a0e3abb7db16dd001609ba833ff20f63ca6aa0fe221db305cde31f51fe24c0d049045dfe7669216576a9a1fa9e5a266093264c39dcacaa0a5bff93c4fe782c44149171f03b3265f9011bff9888081b8537baa41b436c180f21532ef05670c2ab267367369443630c67a61ebceda6534ad52e06e2a5dd560215db5849fe97ebc71214e896d017ffc327593fa538cfd85a80fef032ee8e7d09009f066ce7993dac042d11fe630da9b36a570bd13c7a9069ea3f8da33fa4a50fc1e5c215d8ef5a08c1c3f7bcb3604a86062f52792f71e17b6df3f95b116bc60fe793674c39e9613e6fd530678decc35f6bd0c534ea90eb024826086e8be69005e26970fe98f04dda93d17ffd17af637a780d44a0d414aeee146b7cc03ff14f06235146d4d9fe85cff4442743bb3bcbde3e313caf7c6fe38f496411e1ec9b2009b28c043af665bb91f4d67c0a23a55ed28cacc344b57c7b93f1f3220592b07e08282790a2f4d4da49d5f393dc6374f3de747d6764d066a401be349994bf99c90a18a739574b1ab0727fd79a09e11e33e5b1c53eaa17c97965dcd5078b9ddb2a0bb380cd9faf8e2e5fbfaa036dab63b132d5618efce5bd8d8738b313dd91086006a809d52e85800e9f098afce1955ddb561ee71e4e966789b8de8ca46921b41a0e80095d88ca7b7957825e7d0a5313f383f9b0168e675f6767dd9cde055576190202db994c851ea2a5e7f5b05dff3828b994a6fda52928ed1e1709506a4762280d983941fee08ccfee9da56404c73cef174a122c468aa7277f31cbcf20170bf70eb7d0dabc06a7c96af13df7fe2cf73c0007e26034b964e3d71071fe2827548d09dc89de2ccd7846faa236b12ca3feaf181b199c391a9d4f658e7a836b4057800ca99342bd100c5100c958ab9b986c6a5eb926dfc30dfc7e4afa8ea4d1a5b3850e6e0cb85aaa97374ef0ac6b863ca699040520edb93fd26f3e1e2d5e9153ef4605210a626d5a6d87e27e76de71b1b6795439e020dfe0e1318dffa1f912f6e9490fbcc0a3c3715a06e43a70da3a46511212fc94f32e9224697df4bfd023f334110388d86bbd40fa09a1c0ea819a617a294f6d7234ff959fe6e4b6f34b85d02da709375a67fe558ffe4340d5a44606fd206a287e2812abf1f30aee96d3940d0f9c02dc044eb15670fbad317a2801a38ae9b572c31f5409ef67f20955dd747fd021059403b3417ca0b6fe1d6656848dd23be31e945a4fc864d3064151bcfcd4df5f02e8b7519886fc6d990d08f923e712d3e971f590ea0cda3d4194fab45012c4cf06fb090b6b6bbebd887782d56cdf7e92f6a42bc8defaef6a7879594e1b4b9d1f06deb368ed5576ab75ed61eb9ba4927195c683184c9bf52cd4704ef11c31fd7b073cb1148f263d70d0c20c79b624de1696b13376badc92eaa859e8b59aca7fd6067d6a310064c6369df31ef634bb0832d1655a5cc7d8b4def43d7670148bf05f030248b0c189466b497d6474f421317b520d5bab86af02733210a0293d5dad20089e4fe71dcb644146747adf422d8f279d2508dd1781909ae042799798d3c7db004667384b154f3891ca8a155e41837ad53088b0ff8e9e8e63b7a00a5ec26c910dd7e213093cb5f9d65578a11e909f26d9c21108da3b07fba09ed7b57d69f34a0b5a56ebcc650f624477c4994ac53b9e328394265e72b612184be8bdd57fbb7c09cc31440d264eb63767ce0383dbb6ca2aadff4fa245fce1b956b01015e5bf51012c15c3622ee553b32696b78fd789ae40f50bfdaed583c129b7cd5d098a3f6f01e1a6e1272ad7e47a2f9253a313655b409bd9182992010f5454f20b07014ede016d4bfd954dc5e98462bc560e4233b71a35cda8bb502ef582e09971389375720c3c730af280c9c3d1ca4f960240dd1424b1ff29b82363a6d81d93c4561e69d00cb32b005ae3800f2e90b1495dbb31b609d784928d1ca9a1817ad515d640651e020404da4123c876e291a61012a3d7fcc4b3c257ed1c3c36e368a7316b6fff840ba7526f19dee288d1fabd20a86e426c1b94812f1501dae2e3143e5a723b7a59068f42717f3c53bb509822a200c026caddda75b5f45611ae0427c68f0883063c021a084c394fe33e5fbf73c3eb4d7ede5137fd1a3dceacde6f049ea2826b7b2f09dc2cbb78d55a0faa675465e28c01a0eced7914b700de2470e805cf23ff350302567db7f518aaf8a1190cfe2207175fd6b475bacb7e7e27c851c9e7f9d702b20fc934bb7992540f75d7e5f43d9a48a0ed0f554ccf4e86f5f9cc3f92b8d725e405dd47a0129226965b6c127007718e78366d1c19d3d7fa4e9afdeed5ba822ec90cae5faa72a5f69a6d360970d76ac37fc458cad791278ef874208ed91ff4c2c50c8897b25d9ccfc208245cd5b4e0f428f5e49d8286c2f862ecc2674cbae2a29903152a389262076882bb2a227ed5a3a14a7e09d9a291da498cd7e8295c77b66c022d2319a3354c453ec3ed86413fb267e2b8cd3ea7b9c69a898423544537e20800e48e8f72b7e7ce02aac099db89fd629e0bfd312d1b06eefe3a15648654ffc20c74513478a8ab14e76eae374162da10679c907f482fa4a9bb1714921a457039020a651493e796719ce61bdc19eb2ee5968655dd6698919e169f595f76296d4001d8307bce3b2abe36c4b630eb7e21a4c3c47e3dfa8dbc82d2c10288aa750be10ce9e247e5037c4c21893db408c5daf1026cba8012c8a717f4ba6346bc58dfe102fd2dc28e50207139418c6171f130aca3aaad5069b2de5ee91cae621bdbe1a60dab4c22fa1ba8353c9bdbd2987b021b55a97e45a52f7c391849d8387459dfcc01424fe127902932560127aa7b853a31bcc3148aa9686dd54a6781be7e92744209d337f929a0a5e66083bc5739f56537663a0311163eb1a6be7b81f1681dad45006ce86e013b66909e5be7f487f0d249e70a8e272dd4ff2b25e473ee8cb7596402b4b2cc077fef5bec3c816552f8651ad1f29196b6ba7fe202cb4c43d5055d4209482c2b19d03b179f9a40fbab0f364ade937c47375151805bc2bcead236c8cd0681d6a8285e4e88864975b358c4164c2ef6da9d4441444ee25e2d23da9847820ccd4dcb064d69c5bcbcf23b5823c423f0f8a4f97ce2405705e848dbd67dfd1d0f9d79542127e6cafa454b807db865c810fb6734248ef1d12d7fe79495b5be7602d901b23f20ebb0b997fd22d581c28c92207b56966f84f8560b8a2f2188b7db063c903fc578c2e36f6ea58399153575961df232839b30ec1ec2d9327b5a91a80f255bc0e671d85a3edc916009e94a362ad8f57fb9d9e8039a53ef7e6033ba9407685dee8de695a409352bb98e09958c0a78728732884f4503c891a7ba224c6d0a488425e05265d745f55c30dd2a67ffd410a9ff3b4ecf38f422f8faf9fbc6ab0413d489af4a20a553f0fd9ad69cac2d09f21eb74256a90d4061d6f4d33468ee007491c9201545b58dbf7c6e630790946c1b5fbe127f36982e081052a1e0f54c0c52facab270b821cdae76c49715bddf5a1bc27f9ba3f3370c838f0cd280807f003496f81b9171ac3672158e9cb9cc23a03a260f2482538e7c243063a4bacb3f00f364faf3ff9410c8f88a1ba981a37d17595fdbd2a965907aa91269b58f933d01ec2726f38973aa54247d11781a0f34b4cd893fb278c2a98c37515b8fcb74990dcd01bed6c0808b2c4cbefa9e7ea7ad06f6e7653a74cf357e5bc18e5de7363e00f9f27fa65cd15840ef409b87df54f208f00758f7113e53570bb3f151ea33100ffa86a9ccd268422c4acadd62909f11f49f9dc60ae24f97d511a80e7040aa7502f1eff2615252a09a5310cec8afe79c35074e8d8c425cb509041bb165edaa9a0b85e8bc589536783a9f0b39cb2c3efb983cfe09603e7b518d2feed707a525e300b48adbd37cdb77846747a84e3566fa5cf06354a9cf189b20ed289bc3edff2f041e8e0ac5d81f24bfebd536b90432c4ad2e4e275fa9f8167289796208be628204dbbf38ec58cd78baae7943acb57b843ed0af82ddf40ed88edcd569074256d00f73253fae72d8da95ae49e3c3e6b6380c7a24260a9562a03c0699a6907fbb9e0c4b1103b503d8e33a13754eaf9e133282c737fdf59b0584b6ae7741424a3626029b705618d345d6caa6c85f3905d8e0b786cb40fd5df8c7fac652487fd88bd40053647419e772f38176af89a43482a0f7ea57300b047581b22600e1c7d960bd0b530bfc4bb4fc0c999e6c01b60bb9db93d813fe69472e06e6d4d30229f761650d37b1a08ff1d6b06cc3e30ec9b712b15a85b0d403c2f67f2d185159c87abb0d0577071d668fc7458d0b9c87b893eb000b5e36b4a8897878f59afd3c718db6b60838abe11728c29fe9ca7438b5ccf8db1cf472a7437bf3bf7156f033cd238b7206e428b653399946d64fe8253298e0bb825ab9420b91bd6fa03a2e05f3fcc4bd09621d40ab275f971b3d559ba4b7f6d9a41ee00652e63d0e1a55aac6fc5f454d0de9fa69b91333924270d2403b42b3cd6c4f2ea20a5e895b46152b2d6c463bd60d903d692db29fa7ef438a8921d05b1ca38a650e3bd91a78ed66c96de3176cb60daa8b9ccc2953e59aec1925d9f51e1671fb6c40454d0e3d1c4e122849be16920ee7b9e5b541643b577a83788b74161bf9909ed6e72f767925aef9e07826e7b7003a100c97416d39ff3465a92b4582c3050f3988756c80160b7efc697f1da042026e985495f173066f69bb1bde2c413c010b9510cc1a2e8b6a85f3983e443fba0c1334bba7df3a859af711978d365c0b03cd8e5eb8a92bfc52f0c5cc931306370038d5ac79d9b0357de65b1789113d65b1f53a30241fd4397fd32e16f3031c590a3a3c94c75758f19b9dfc25851d148413316d822eac18fd698dd2887e5cfc6e064ea07a82c35b7d5b30bff932fa089105e8e4b1cfc41f4653bdb5d992404c7005abb38828b80c5abaef84d8b5907e55166b02875600788c11adf4a674f8104c000922af0d0f735a179e92d39d3422c6f8b4ce3c8aa1f99bf320c1960a38cf840901f26a631433301d1f2c8aff8907fb860a3326b8ffc816d3a71af8f7ba93dd0251bcbb26367890002ebbb81eed772790d554525bbe6ac2aa5e717ad5e56ea5034d573c49e9b0fffe2468e5f410e84582dd360d4ec50e29955121db4844389c075198aa1fb3b8dc7a43fbb1eb9811dfaa344f1eaf21d2e037b3769675562ae00899064076cdebf34fef46ceceadef79acfe34b1b170282d8f26208d84f125f70c6d88114cbd2763289ce31cf7b5ffc8dbc523fd10426b68aad03cc34bb91d020c722bb047814ed3f2d07d748f112a8e085290e21d1e56e809f330717b0e7bee09827991a35d04dcc9bab009da86c1c3a3b98d237771ade3a79d7bebca3678f80bbba4ce3e2a349bb6c9735235fe88658426c46b464ab5db2a70783287b2fc7307390d9ef9cfeaf1732aa297de775f22ed56c4e8547e66f55617654716a652fe0d066306458d6aaacdad6c9d0c9e91986e4022bb310dce8d3e3d649915556f63042f0bdcdb49f62fb0be06df83aafd3cce1288caac6d471ab3b2fd14e40b947207cba62596b423d7839292f383b1c6b32cfeedd33e83095213c466e48836f12c0377e0c6c58ce67d266b33a8496e237da5c7ab2f5816327b9b65a09315ef4846006d26e1f407494b9a28c887e351fde02141bd93355ecc9a35e8485b3358c8c50757b56d582157cac6bbe507956b8a249519adafcc9249153489e9664094122d08554e98cd6b0a0c236126c8b30430522e94268d57b92d19e0f1626eaeb88f180c47381f988477ee7ebf4fe78b56c6b44053cd10ae8c0fff2cb462396a5832a403a701da48f0b1c8ae3120e35f13973e9ba93ef1be1fc2138ba0fa60d8b3db6f0ce006234c894491cda1992b85219f7c44ff7f9f8170b49effa4dc8f3d2f200308b06d8c6e9517ebae3318113e8ea894b19b73c1ea3c5a73db5af999a012651f008fd4cae064b076b0bbbd04f501e8e2afd6ac0b7308aadd18b37cb86d04e1b606c8cb1d27040522b195d3718cfc9fc81acdb4f0390db61f2ae62a852b84b6db0bdf29c7cf92449afe6854fa0f2a9bfcd27daa41f061d881ec0dcda6bca5136c01a2407deb420b56f4a5e299c116ad6b28abfcf7b1b93a6dfc7146a29665a89b0268993a701d4bfe97ac264fd4c8c1fbf5b08520e801bd433ee3291868d40bad07fb00f5fc513485c6fb7867dfb34d5bce47cffa3c890223a8589ab8a104d90b06adba2d7e86265e0b9ab00a26ccf55616c92d0fac50a241fb8f09c3707955be080a81923f3a3e333cf7fd98156cd6023ba2fe981603a7dd3e324dc2d8e1a8490fca9c589e532b2bf928bd54268149f09c210431b1c719fcf2785517d86348da0103ec98a9944b92546f4ee0d4982c8356b4c58d72086f60438d8615db634dd80bff4209c07add031c5ef00e238c17e36717cc636c787c6ce609946ce21f62530f9ca43317fb531c1c050654cf901aab3bab440b05a50acdb96013038bd2cb5b032c75b8cefb1ed5a28c989efcf0c8fd2d27900c17bb3bc87770d1132a1f74b80c4b691bad4d3e2e165d35e9e53b8ceb891ad903f030777b484ea7cfaf0a18ed0a510e1f7b2c3dd46bd292d29127ad191466cd0f3595ff9a0979bd4af445cc7a0d4d9411617c2bc0efcf025c13386eb7c0167bd90f5c6e1dfcef9c3a028888970786be01ad670910470c4537a05b25d5fae80f1e8e5fd544fc151f79babdf43f0f6f20db2885a2eb017bebc02a2080e25655ce8d63caaca184a6cde01c9273d00e34c7783cad2a21f57cd423393a587df3f7ae9a191b7fd3998c2859723ca428073439f8b6ef77f7f3e6bc894712e595595c6a9362b9fb159151310237e8c2a80a771bea5352efcb34d37f9cc378d71061d605239be13d53aefdf15eec2101950d60a78109c64c8ad13096d074d9e8c571e374d456e638fb31c700ab64d7fba305c85d95cfbb18f2e364027a26b24d013209a0ed549a74083f0ac2128b4be294051675448af081286cc57f185def44fa5cc92518bcf26240b6623de279d1575f0f7d2ad23dc8bf69b7f3e13fc28b8a497f51eec09f311dd0521e4f33b722e1bc0025800a3fc6ab930d32aa4b4dd7c514425143f3690781eef513557d1058c2f0055693aaa2ffe77332bde0a50c175324047770da0243d87015667a58d48fbfa403c5004f7e538fe639bb0cca21f3ac21b63194bdd7a991b8697d02ae3de88acc0bdf021483c58dbc328c607c474eb638b234768e9c6092cc5b44c4b6b41a99fa0bea35e53be5f1f925dc09b520037a14b4d85fb163f59a8e3a9217c16b8edd0509887df1fcf3c6d2d2569702be90958c8a5f2cb2e8d5e177a48ae46a1026088709aa3aa5aa0e8f8b9bd41aec8ea33bf0de416b91a6833c9e6794840aa2d59fbe071ae86a3e884002f7ca2480f2ccd0c8d1a50343a61eeb649f30f79c2a5039fb0f4ea7bd1f1b633cdb06df788387ee870b2747bb74405fce0e7e43bc89a432b800f3ff885a43f2898ff2e9dac151ecc8e1fef69fc3357ed8af8f5594064e3dd20cf888a2239fe4b31c5d835d6729716171924a171ebab8d6edf94afeddd700c403626e5d6150848529423071b15abd0b642746d5946de05a0db3142ce6683dea037e454e9814b67280ced1cfac9c2ba145a600bafff7fb96cee795ad5e910f3a0aafb5b426bf0faeba4baf5d625d0095e3f5844694129c43fae7724afdd84ac00f10c9bf35aa1feeca09ca43787593efc6f3e9ecce378e084a7359c564b1a66b0c23f83f0d4567d5d6feb806bc689f9e105a4a501b5f2db7fba02eb37a435c76042397c92ea3c0a60b596766eff99eb82a83fb0543ee2ac766c6680aed4808c90bda954de7e4b897cf7d937b2226ce78f5fe6486ea9dd0ff7c66cb6060cf638d0bf3157b43ecbe6a28cb8397f62bb861a605b168bd4722da0490d4f0bc31aafe02d67bfd2cea74e01500943382551189d50f0c15039545e24b7d8a5305e5fe530efd5f7a275dd7a474642724cd319a5aa33ffe0e5924900d66edba8b86cb0a18031095f6c22b983d91cf022de992be4972b987996e4b347d4a4ea8457298179c0aa96c79efa689232d28c83364226cd8fd14db16792c9968f8632b8530b87f030b2e7185fae3a4219f0e552585c5a74542b8c41ac2c5a34e4fa3d19dd5c8288d0ee06f56d6f72ec343ef5de521d8e75f2aaee739e5b56ba3e6d9a89b37fb9e800a6848d3720be1f6adb4070106eccb16e6c86a3fc2e18af2bc3b2ec83a737ff80527335dcd593839163840cd451c94383eb1b7779dca10cda136387e5768570c0ea0c6242630b25dae727ced70f35e9385f6f78aaf65743d4c0aea6045bd59b004bc76261c573629f23e889f4be4c50c2dd6bd42e8e5b34f5ef5938203ad28a10b80706883cff45a206d00a9ab21a3b784fcc4517753ae2f1e2fb1a364ed33d10d6b99dbd07000bb490d08039c7d3a0dbb9763a4158cea2cd7c5eb24bb57570f0163a7f01a9534bff3d6c9fa1e4c82c4440277a9ba25adf7f6c9260be16247790cb65d629c89757a353935c999c51fd8461e44ceab8495d75504a54c71d09d1f00097fd82a0d9b3b115759d1f0fd76ec9d452779316ca09c158418be280154710968597ac3fa1f7d8dbeb521691d9b993f7d70aef2b1d06a48cd20fb8c57d60904d853824dce3011bfbc07878aff4dddd8d6c0c6462287aa2cd128821a547c4e0ee3cc7b6f4c629f06d532df3cbf76ef4612158f3e19d1c9db7a1ca6a32aef320964f498a1b4ac7eb1527e3944c04fd472383129737d425522cfad128c98985903f1d3cdd52aca595d2b9e54b5eaf58ea97cdb1ecaa2b22270a7127ffd96163805801ad6ddc2346f146ff99d4d160f0cf8f933c715263c69387c695b28aa6ee2043a0b4239df708840080ad08e5ae177340fcf91420a1f0f6a8195f3b2fcc79f064de6b2503105c98a69b64b512b3e2e4179af1ace089f135d7cf06c5424e34f0fc8c67d10648589fb37c31e151b18bb121dc40cea2abc88e21cf512a411f46105083599f08f8ade88564cea215ac27f4592a556cde38d407972baa5d8e21f5a0df73e2d0943a79640b004d6eb1b29072106613d4ba8b5af8c10af96ad2059f4027bb5be10aa600b16b77c8628db747cd898a11f017f9badbf8db345323a67f20a6bc8d24ce2480a8469ae192b12da5efcf79eb97ebb627ba0e69c35371d0be40b03d2a10d9d91829b145797b42a9b4fabdb6623ac2e2d1faed5b48ffc8964a6021b2ed8a0bf6d39a217bc47e2ec052639b96529ca89891a0b0977417d0d0bfb02b0372195543e6be33359528cee86f5738ca51db216599280a8d81cb54a5be80031343edc6af0c80fe21e32907c8350e166cf0ec7611c58beb253e231d88d7c0930b87e9bf63dc74c60fbfb75566b9a56cdcaf12fa2bd2fd2c03ab3925b31b50e633377272ac262eb63ca1d9d5bd3f5e455d4752db11ccca6ce28e153b75c2b0fbb8be1083ed1d220c92ddc2be37f8706f8231cd194df98033fcfd64ad59565082c286bd5ac7fcd1712fc5357e05cc0508e4f9f24a810931bd6e7e4ca8b7225040cac9f93b1b87a8a703466a09001ecfe2228e2fef0da29e33c131122f167870a4b21a47649e3db8c415c7dc82c3e601f1faa3af3789b3e9a71c7a72a01425f0eaa520a6b751a71d5f0ff7f0287a9522f6471faa5abf93570d09e65b7d1782806d8160db43c7fbb5af25b04ed2fe7746fecca5eedecd66b51ecfed54f62852b0a9b84960fe643835c6918c0744a248f8cd9551f712021d6af55ce62135e314a002a7fe8f6c00db3f6b91cdfd9f0d4b00b931e6f419bb656dcbbfaac2ba876460f3127543a4bf2fb4a74afc81a30744a9f4b72eabe45652970c11379c995023203bda96f2936c21fcb7ebeacd50a4a0427f2bbdd8f0724260f59e2460ac9f31c0e879cc29ec9da960488c964a8e28ab4a0484d8110137ccd30832a9644f8a3a8080bdad28be182a714fb0f8a13fbe7e200826e44899d10e9c4193d3192d605be03edbb18fde21d8f7ee69dae1ce5aae5949451c0f5efafa900a28959cb7bf2c00df4decbc27fcbc9fc884a7e33c33d2e999fd6c25c111fe0fa1ad6464315276a0488e1e906792f06cf78dbfab354541314abab22aa4af14d49320f196bf1dcca02 +generate_ring_signature 9dd907994196494b8125e30882384a88166cc89ab3d0c91f6fde9e8ecefb5e01 90dbda83e0a10b0070bde90aec62e4dc65910a922c21ce75f37c425cba693876 1 b8780402a1279c031fd5dd4cb89f48bfd15b5a8dfc140d9fe0eae67a51d18df5 5631b1eed32e0c03cc92739379fefaffc2389bc6059c623a2df77b13f41e3209 0 686fd73d1d2f2cdbd77e043143b03a30696f1e4ee3b1f3577787439e7678b40d8236294b31e3213ead0e10a46aac08d2917a80dab82936497324bc9ad57f6704 +generate_ring_signature dc57ae672f6691bb5adeef2f47e8eb0cf0c5af0d06d479a1b1294e5b3d41c06d 3025fa55a862d8127dd4c6c3d757a2e555e7d50356c3028f6a0027aa786c751b 2 e6ca090d9d3cad0b144faed63a19b9f263b793259f0a84d3465d9567893893f1 ae20f4f7f9038da72a39b4618b1a9032d77bf1787ae00632e19b50051db8de04 0c51d9cdc712d60c0fa724e226ba82e337451ff47b69da5acf95fd41db1d8c09 0 0aaba160dd5e2aed6ade146e31a374725bf9c99fd8aa8b4e20f53a0e9f54180c78bcb635cab685bfc0aad9abc67766f894b0f34f1b0b9cf12b09cac74b541507793e60045a0e7c7336eba35db6e1597ec5809ade6e1a043bad9713c20f549b04e38197c186524f08eee4faf1d1e8968c4a6c5ed4b2c87a178e64e496d77f4408 +generate_ring_signature 2e3eccf3241ad759efd0759054ad22f235e33e882f8b3a0b8dcc2bad44cc13b0 46083a5c582071ccf8cd1c9f33bddd7b02328a1d68cef46e82f41baa171a2fd2 2 ea16dfeebbb925edc360cc2034ed4a7c45dbd9a2ac5c2699cea5d822a31b6187 64c01e0efec188fdb60bbf359b073f613efa84fb51d764cc716938a6e3cbbac7 1742543972b8075a2df32275289d6be641db11e78bd88f72215a5d2376203901 1 55b2967846296961ff4d19da5b4d269a2fbd52060ca13cfaf5618ee600b1ea08c6718b761eca00d1bc84320e14d81371112ef60045ed6eeee7e0515dea378e0d22792eeb413da87c423a6813990662402a40ef04b86b576bdab40c0127c7710258dc1ceb280148757bd82d2c8e2aa629008619966b20725defe80d78e4653c00 +generate_ring_signature 5324c8a8ad37bb76e86edb6127499fcbf161e173ec4cba0d426e25a26aa7c2e5 a3d91b89186b32fb14d79601878d9b5cf0289b0ac68d19b474c86f4288c8422f 1 ab633b5c1c80ad6bf183d24f4f37eaba1c4776e8383047290503e920ccf3ef59 a7afdd093c3a4e7f64896c7fee5b6db5f6a57a6f14c04f48df5c4a4a1219cb06 0 37182c23e8e5ba154766f587ccf563244ac14bcfb8cb75a0ea0c0c022543b10f4076babdf429fe04a17cba13b500fa6ba72ddd63770dfc622ed648a446ce3c0b +generate_ring_signature 9ac64eb93443ad9fbc9abc23cd255253d3f61fbebe818fb9436f2f12397ab717 0d24970317c011442316da2d75ce0bb19dbe3c33ce6efe6495dd185ff0b77a26 3 29316431df8bca23ff0440601e07bac7ca40edc4fb0f948d1cb5a4e62153a1b1 3af36e933fd1d37481499f583155fedbec8bd3e131d278a28b209d5d6938ed7f 5ade6caeaaf734a3f6435719f88871b4094ece978b37ddf6b0554aba023ad626 94c2c27e71b84624c2f55761fd6b36a2f0f835a67fd12bf7b892dfae86c03d0f 2 fb851cd56a21494805c54cf6b839eb7b4be17334385ee614a90876d4dbd84e03f3e23ffe0d26aef43be2d0b475f864df3c2cd9e291b279728d3bd2a6970a6c00c9089ae1c90f5d9b8f66281e981c67c69f915e3c24d45dc0b05106042e07130690bff522ba91492aa07256ccbcd8b880d86424dacba5b69fa8dc403c1c527b0b5cd298bee50a5ae03ca5cee52f3ffc82010f53380568103286ce5ec88bbf190face288fa5d37b0684b391dfc22b9935dcfe669a968028fe5ae2e3f5de050410e +generate_ring_signature 733c77641afbcb27266517b8f24262be24609a4729609ac2bec71b4aa86f67cd c2474848d390a19e55e10d80834f6426d2421d3c0d9348e81312b9c644072e79 2 5eadf01c62bb7ce2e1cdf66e49982fccd9965769d41846e1526cb9eaf2d15395 ba67c3a77e88593f8ecf2c137cb0fac4ce7d2259010854396991fcbefde294f5 c3c9808a7c62b5542b5c054bc98c5f140820efb26aa6adc2f48f4d0550536b08 0 f6b8f49f5e6e0282ec410cbc1146d872104af9d277a542821068426734e1a80e9aa080bb86d922a2abe26cae68f82ef996a4e7cea62f0d95cea63b662b2082075c73b2a96346cd8e12ea502d2de1010afe37a84921aac4c95ea197437e7f8d03687d79d057dbd907fc253419bfd9e93a1621cceb02389c9f017e3847e56ba903 +generate_ring_signature 1792c680135fb955b884861240d9c55b6ceae3a130059fe1b3ed2e9ad5a9de97 ba66d0c9bddf46eca50a3205269fd2c427e40a9ca780d09d68b953511561b396 5 bbbc21787e57aaf4928a2de53ad1d1c7527586f1f8337b1f3f8d4d37fecb35ff b00f959de68120641ae043cc9640ea2a5fa040ee950858c1e9f16b427128a212 c5d5354bfad3251768658323c092fceb2918d8a700557c79ea5fa638c18fe516 e731fbb5657553ddf378c3d60e0b12b1a5e375ba1154c6b79ad6d276e68f75ea 1936e101b0e7612be29fadb4d8a17e3dc20c44a7f065fcccb1f372bd8e3b0c19 747205001f75da90ded4f907a518903090940432f8959d8ddf25413fa3381304 0 887297c00cd126e70eb70dce237b24e4d082f2579c28a7e08c8b524e8f3e240fc969f69ffbd359a6f070cfd2e57d127bf16a324d53b1fd758a9f0842b760e205beed00c63713327f01cf4118e067f6e8da3812b2426f37a8aec32f9e059d8b0dfb7bb054165b6817880153c8634d9c4e44e7a2d63080009636cac2b4a91ef80d4df8d42fa575ef8d2f8791c00868d126a13611e2e723f2de9e0a65c52938ff04a54f81690e76e29f41c629d02cea978cd1bb318813524db6cfff08f25592da08866695532e0475f2cc9766fd13220c7ce2bc3cd953bf867e5947f0ddbd33760bcba6f9bc070fc52f371cb4a7cefe0cc2eabc0f59a26faf80c2592adeaa367b0648693b7d5f23623a820c98d527a2d6e911251d0f23f8ca8eab944be874211b0e787bcfb21b6b448a1139bef04470c9b975e6c6b52ba2ea384f2de51ccbbe8704 +generate_ring_signature d432ceeb293d5ea12e583f0e6a858000ee675b292ace24d2ad53d641988ff416 03776cc64fcfaf6b9a23a85f9577bbdd429b653f732b43a0e8f43d67efa63c87 4 200d574e962228bc5b74f2785ca3aed1662541f7300c818a4907279fb763f5f9 4c89d8fa1e9ce61a0f8ccb300b598c795baa7dc1aed979f22fd19958412c6fc8 287c5c314c26c80e50266bfeba4676980391addedde9789756dfaf37f5d5c120 0c294071658273a2f36d3bf44863fc65c8732d46e5f907c4b68ec8aa0ede4643 4ccc770ed00b9eed0888d3d6346bf28324e98418aff1d7903daf2ed68548090c 3 da6b16811b36552a25c4d3ce5d12b537959c985fcc0ef435d3aa66994bd2890d0b24d1956a2c2997acb633018f38a362c53418701d2ce92bee50666636b0f30607dc1a48d7396d8ca51b6b07ddc35ef2627c8c5231f3faf6e7db34dcba78ff095ac35abefc2b33edf1608cca98631634a04914d296b8b74aafa442a1a0e38f0168a90b49c74f9b03b4b08bac28e985c0f121ad175932f202ee027c63e842180be407571b4db2ab7ef165e33a4b6afb1a77dc042482d734009d47d629ea4705057cc3bbaabdcd310ab252b17b7feac5ac93d4d2e8f6fe8b0330183ee6f7ab1508233b2da86acf3ce6f73dfbfe2878407f1ae0c0c411617728bd017278fda5c702 +generate_ring_signature 5de707be4d1ceba4a9991eda597450d72c752ffbf85f714725b7a53086c2d611 ad59d7abf4332dbb03984884318194af02d41844ade4e9f91dccc65be8467abb 1 a2103cde970a000902d7bcd98045d5a688cea83d1a0cdd1bdbca4c087249f11f 6eee07f5e11d2601d7175b90135c8328c797d5f4952a125a96f934aa82aeb006 0 65427eb202868f11f21b47ee4986db17a9c56d862d6c8630e049cd1142eb590ccd16472e787b06bd2742e19828f09eae672e759d90d8e6a1d81c46fda0da6a08 +generate_ring_signature 1516afdad27c8277ff77ebe9cc6b9889061ab85d504c7678b51d1b453e656f4a 77eeb7c8666282fa03e473416d2b495c62e9b8423bd30aa054cdac22f0173b75 4 294897bcd480edc6eb3f302bec49fa75aa38de4ea0a5b3ce458e284477a4df2f d7b3729fc615104085544ea277352df10f43e24e8b7f47469893f34df7197e95 9e4ab024bd6a82f3544a941c0dd88b2985601df873cfb6c82c669562d0ccb2c1 768ca9255bad7ce9db858bf51271f6321620424e7e24e5422395b10e3fe48a04 7328152575f971140847e181482617d1220f0cd933535cbd8a5492e8c857030d 2 ca5cdfb40573b257d12ba020402ec3af7ffa5a0152af83b45142ce727c3d590929dd1d4ca76f258364c46150c8f8301512afb6fec95af1336f74a7537b3ce000fe1ab9605ef0696950caea46af9fd3fa10aaee09f1bceb8ad8b2b07a0e53fa0678f5f36ee6d02c65ee966c0e8d06b263c044a59ee0bc5bcd3e46cfbbb4fd20045bb535bddd1c196a5c0530f7be5fa0e4d42fd16892103c6ff7e754d503801e038b1562ae50e775b20df563e49eaa8d6698991e6ec225307d8806c39a5ac2bd02d085647604450989480445bbe222d8bcd0fb84d01a20b328dfe8c1363ac6e40dc3165b4057e621d42108cd35d1ef1bda1b5c82e925d4e61ed8bf5bca2b096102 +generate_ring_signature fba004537aa4d6db41185d8c4b12b3256048480c65d99eac669d156968585162 ede0caa2b77adaa6a0ff9cb917a79b644d2587b7d3821e5632955403ba4c9d68 8 62c27334f32b1587534ea7810f3356eec492bbacd7c6bfd2cc91b084dcc38643 c6dcdc2bfcfd81b385864f46dad8d1a1f608eb4d5615debaa651bad8eeab6588 806806bbbe254061c70ae2ab54ccb2c10886f792d9b3d0569fa9753e4c44562c 9e6598f7e3b174857ae16fea6948156db8093c3f991bff0da5a2d3c8f302c9cf b4df03f1889ac5a3b21134d6be2deb378a4c228af70a3317218fb34acb3ec86b 00262c572aceb403da34678e64368766aa091be815bd42bef5db81946488b366 c77fd924daaab02e4f95d653c8689ef3d3b5c71fc70825483bf36eab26280ffb 9af7b0c4033b7f3a8de1ce74f80b1ec03fcc3b92f2212ab8ee5a9c68869b5995 404d2882583e961947d1903d8bf28d3ee2fd467f01ccefac2d2ac3431ae30506 7 a7ceff744a1bfcaa750927065654f105433516f6b533592fe90ebe34b78ecd014a665f54e3189b24de6c2c8d2231840d0606e4e75ec0e961255c7ec554c9fa0d988c57a0f2952ae8bd47aef4308fbb0b915551487ecf272462d6b6319243f30a19ea5b978602cd52803ce2b66f8d2e530746b57a35da4bcd96c2fe88be7b33041208a6445854ff23897751f4fda6172098d872b46f62e0df23f1ff933b832f036481068286e50a28ebf24f5e47da0f9b1bbb51f8ad7975111170cc24c89ef806aba96b08d4a274ab16fbfa4a1528d72b6a9b9e20c58ab2783d8103247295030ac0a4ca63103c146df9615277392c6379012f692bc957a015200f6ab669cd630ac7c0500b67dcdc9a8f62bf2b64197f394eab6cc01d8d68d9de76d82defc3a80c5655dac9e556f3a009212cf0204f244bb35d8d61eb56fc33896ab75d1d2d7e0b7c02a8d08b6716fc5e5e19feaa2c9c2d9d5fdce6041c583236d5cbe8e4a40e05911219b6e21efc65e1c950c350c98867e7c329342996d7398c9036b4a0f56502bead90b8dc0bf3e88e8071f10f4112f319905256b9b0d9c2c68acb731493fb04fc4101d6af21735c3f6c9de0c653e362e48dcbd6e5e27438bd4d3ebf4e44bd0562cef95f26f102903508ca28e4ff2a896887c49ddc586dd192f4666db13a5308e713a593cf6770cceb80db87654536ed80bee44afc2bad63af7372c489dc1201 +generate_ring_signature 3ae3d9ef2c81e08c3b85166fd60d74ae81f1be0abcac3690480a1ad0186e68f5 27e97d10d75e9108d8c4e89e43ba75a843f4b250b3873aabf158a0379f55986f 7 1ef624898a6fb35a3396c517f90afe615d97e1beb426a8bd63de31e3f4725ff9 db1b81edd507d1773035e62c458b4597707bd5f7abe52f6503c7e94372699daf 2d0b80fa6db1598fa34207dfdbdded71c01c7a6e0c48a9895d103ea21f88a765 b75766e4545583a57ba86801b55b63f7f7c875f6ccf2e567048d191230901a02 6c633936bec4bc1d110cd8c1ef9ad728d43871ed5c25496493cd5f853e871b42 37426776747c40a3e60b35730a93d3aa3753431e7d8dbb2b61a5aad33ad8f6e1 79ecff41ce5665dcbadad024b05d9e26f9e6c7b9a7d10d6d608ff0fd4364895d dff0e02f69750454db98ea1c0486d8a27a105362ba9b8679b0bf2725967dae07 2 b21bb74d5216f6351a72c666d4feec708fdaa4c77360fd160502b115ef06d20e17513476aea0368a9e6eb863d2ded816a01894a511d33f22ba5c2addead5300f184c4414172e0ad247f7ff57aad66ca351daff60e2c4e13f5e4c8403c4b3b3085f0ff40145530ac4343b5b13e3ccd47b1ae9f645f90ce0909ed7e37ce5d1180b1e44599a85d2c114246574c512c352f2853c44d4ab14d0a8b5fedb5e759d310f1c803ffcaaaeb0ba87e09809c3f6afa6716d79e491e337a06bcb0199c169650efe9b3e311ffcbffaa381c08e3f8bcd6d130c58c0730f56e9dc7293f9e2a859057c3ceb3e812822f8aee6f9acd2c34809c5fec7b9e6ebb0331f012ac29dffb00492741e3aa236116a98e25be43effa716ac850021cc5be6339903591dd2ff670d27b9dbfe288a978bd1af98bea75ef4b5ef1bf0d829260dd8181650052ba7bb0d00bf17525fdd4967a0db619773e0370aebaac15d1651cfa3a3c2d76139fffa0788208ad71eddd5490d0569f324aba907cdc6a2bc3d5f8799545d36e56d46760d3b68318850b8169be86170f9e59c37627cae33bb6595f510e5bd0fe525ae1204c15b89fd37b1f7fc89a190623386712363f3e96b39d108bda90da8458d32cb09 +generate_ring_signature 5ee5ba303fba3f86f72178eaf964147c0f4728181baf66d0d69886ea57304f1d b252f1d78bbe4179682604610e30821f9a161cd81ce886689a1aa9199ce14c19 1 cf0e634f021ae9a7741780f42dccdb7ffb0c5dd00e99b208872e604210ad5926 ed4ecd59c016635ae665994d6a1698ba6b39989fc31bee19aa099bca24bca605 0 7329b03861da35923c9295791da8a2f48306f7324336e88ca0da8002150ebd0737df3895850ed04942a53d7c844905a6d9a4b33e2ef72e7ab19ae8c2396b1d01 +generate_ring_signature a168acafc3f3634fb3afb2fa4c85302807788e0b1d6db633457c343b83d4ba02 2ed829909d69d8bff8cb268783d3e844ad3539ff90fc6bed846c15406c237801 3 8eb8412c40ec4e21cd9a4fbd2d7298232370a4ba83ac5b0d1e316888b817b511 badaf9725b5d536b6f3a66ec3ef108a4b3115025df7f43e7ab249f3f58059f6a e30cb9b423f01c24bdc64c739a31419cada83692fe0c4d64fcef6bcb1776d592 7e76841378d75e2606cf68cbf75f3f3db2cde74b2faa01a701a3c432ea191c0b 0 b69f17ab6be454009e01387f477d057c3ca530b458c3a70f46e6e0d894828e01edc580eb6aaf7cc7b231b6f60e4785162233d5a00dd91fa1a54a30a1391dd6024b4100a5c9754df4d1f52992b7529db545b03444332b5b3b4afe384919c64608e04f6defc8b34bbdf283b3b7b9b1e8642b9de2c4d9498a068094ba6563d89007863de6d863feaf14d71405610fda0d21a05f5e1ec6edeac4d4a742e73794fb0a585fb55e3f8e2ccd0438b86b4843b7ad6a9d39591e219087541448fe15a1f10e +generate_ring_signature 76c197a029a4979d0388b7ec7e68ee11ccbc66a8c504502adb011f718f46ea51 b1490f09967c786694043061f7b498ddb9b064091bc8437ce133d71fabac2f6c 31 72b83a2fcfa3b21c53d07c617a198a000d5c4446bc05f142f8d42e94938d3c89 bda3e253729f9b6b189e923f6a5cb3b36163b06e8e2e5c1c6d685cd272ca0ed4 a706710f83c922e3aab795c56883186dfa8dda3408ee314f04816e9b8fb92f90 5c0813cb343b1cb1825ea4378014a6953f5884a8250d5766b23a9af5b43d2dfe 506171faaf0ee551b7c2dad4b1a4edac2239be4e7fe76479cfaac59551deb880 9e58cd307a14f6482f0c00d9342fc0b08776deb879c567b53c9a5ecd58d96364 aaeb56ebb9049870bbf2c68ed50c74c74f738c282da33a5897213c7e305826b1 d0e9a71c4f7b38d6e32f455107a814d6ccab122a3d027f320ca36f072f58caf0 a7672d1d2178777608f058280cbe24887cf1c80d54e4d3ce8c6572600887238b e550d5bef941cea97a3ca5587654794b2cc95e4ace85043435632d6fc9e6c239 08eb2a4f3d70a4e70bfb340724fe58e71cf75de3952c474abd8270a1a4145c67 4c69a16fa040d1904535fc5addfa4ea00c6478c97fcf349094fa4cf540fba173 844f1c9064fd2337d653c08109662a533ca1ba3adf29f71ad52fec1d581df0d6 1f38c8da9e1841686caccb994796b0d462db73db8bd5b023f47438da226212d5 b0a333c00453586b2585617916edfb5d7c1e0e41a06638e8131960b9058e0486 3e1ef31dbed8e4ea54aa290b70cbeb6674f2edd2f1e187634e7489fa52bc1d68 cd5dacb09ceae7dbfd47d22450197370322d2e34c5061ff0f886147a4cb3b444 90b87ee3103b7ca76cb968e6781417438fa9603507b72d5bb1abf1157576bcfb a8977f55e6aff38511520a9f07959dfed92a336e0aefcc6d10d21bc9937ce18f 5efc3ee01e44a3a68febc8ab9dbde69bc47f943de706c9e1309718b18b66d7fc cf1fa8638d4113d43b9a9795c37891dc10d1f6bd71919b014529f59cf2bc0d6b f03eb4af7517879ea5d377e49ddaaf2533e4a1e61935ea0d857fdd1387ebc899 763c9a6765b4b5ac7f6e53789392a1ffb43a0bc850707018f6419ee7fe8c7d0b 8a524e3d21eaa69a18ec74a26dc2d2c6f93689abd3fa4ec469a9effa1cd4bc89 8b6581e491580aead5297d1415c29bd12e15c79ed2d0bc2a25246b97a8337604 7540c5547acdd0df7dea03b49e2cc77d255385817bf3cf6ffce2caebff519074 45dd05c9ed02f168c67efadfbffd2a95f0f1cc84f4292826083bd10dcab56b14 bbe9ed0564e875b45735b0fcbb7e52ea810e54fc1f8fc7e1c704a16183f48d12 0d8c787d3134f90078bd47ec104b03ad4fac9bc6d61673c780fb445bed6c6da3 83cac99ef2be476a29ed5a3af28a348574576a086eb5ce2afb477f5ce5aac752 d5d7bcd8f0c14dcf5f621aa4f9dc1670efbe7b82dae76b43698fc21a2c05b2cf 019a7f813771d3f579ed6e3bf4722ae6ec129e1efc8854fcdff5c992a8e9710a 14 39e1486b0456765dd2de72cd67228305c2bee2eac0f1bc5a3ce923d04df96c093efcac14b790cb60628a1be3b9a63ea4ea98673f2b5145a0390e0a73f1cd6e081034fd0e787ff0d5f2e0b55f19c0bbf333886509ba577a5d13101f70bda15a0ee60d1589ecc0818fc9c00e67b35e306fdf237637461c91f69e05f694052d5e04ecac599c8a07ace93cef69d604849bd621259e1ab16ebaa2d26a7c8a9441900e46c36e14a31de227253abf35f826a1b0772ce60d98a9758d000a7f8a94026e03949af06d2528a82d7ce9f9153ee0d03dde08c8f4d532f9cd3804c5eca63eda0a149ce7afc28ab4ca5c7b0ec53597dd311f1e507de2c86c7f4cc47ae22270b401ceb4e7b4a7dc92120bbd5f18864578c3179c607212bfeb7b258836d81b342d04ba37ac88879c8354674aa021e8109f372e06fe9d948974f5e526d85767966d0a7b6b572c1f9548f2c024c29dc5d7536eea97b0bfdc938d8cccc2769db32eeb00921d03c41c62fc6c0a222ef6e6b4684ab505f18e7f08ec6733b2dc5115ad3703f2a1e817e53114919e606b1c71b0ef595673c52e8ed0f4f6b17d09e08e72d40cf69a68a179d1fe04af217ec526afb028906d1b5dfa73c847d95b9bcb4683cd0914a20c8b15684d4f8f91dc4287122942a5d0cad863e6a9c100649d57878cbc0e914fd43bda744193ba84437d30afc9e3941125c71a448476d63211389939c50fab39878d8962743382673c015c0adc18d9aace62eb3eeb6964831e322f7ea8037f67eb8eee9131e950dc4f259adc15f4c300979668b7bf6aa69eb4fbefbb8d00e1edb3fe5c07d6bcdea9597b6623468ab0f816110ad72ea5bf2f167ffb96b909e9e7a704496600992ebf26928f200867e4b74b2c93b8a4ee0a2a8216ba5c210a9cffbaae6229f10392f0cef218a9d99582f0abb1c2e180fcedd3137302b6b101c13953d4bab22f7c00cab61809563cbc7363530c63cdbb922e0836c2a179580ded4a7c9f91809fedbd1e4d12ac684defc9a8f58580cd6a532a03960185568203bc0e2c75755f9796e13d21364c86c7591bc63018dc2ce7122a2231eb667b4d0189a1e9ebb297b91ad182c654b475905bb456f251f92b67ed7663e3be2e89a701263413be601e1b24cbb683676c977d7a998f64eb05aaae5504065ccc2bb421055a93468ee30986ea0f71c933cf1d0de159534c1bc113f664c83c6460285aaf062610f9bc21467827b64c0eece7684c1bbf1fffe9889da6b2c7e21a03bd3d73069e23d2fdd84b58aea2edc39dabd072fc722ead19b104abba815684e79533de024c3360c28e3b47e4ab438cf6f49e9625b948839cfb7ad31445ba817c8d1f4308ad9322f3de86b09f7747aa3f44d7b5d1b0b4d26c77bda4381e26c6c5bfb3160f6629328bc8d959b627b288849ce7e721758150f6d5daac9937303953de38f2061e75ac8a363a209b5c37d5f93466c48cd84d120ff94e112fd763fbdccfb0b10d1b2a95f43f2f92ca47d4e08aca57da5e2adc13c103071ac95daa4491c0866e030acb0756abcfadd58c09dd00983ba0d6871b9d3264753d12e426f688858e640b46c70f5b81e2291c49be1ffa2964df355781f5466e1eab2f388382c31c98ba04c788690f3bf5356fceec3009f56dfce2a137dd7ec8ffe93007953dc048ff580ec1581d9540631ce2966868d0fec7e4c676906887b94a4d16679852b625fa9d01a07990ba0a3c457e78dc493427e406afb97b002669959fb1c768c55a7f7b96016c8da559c0500fdfff680212db4b9c30243aaf27271dfc5046e9a313aa40560ed3d3c3f7a9eaebfe556f6f5d16194ff1106fc89ac48841abc1cc69bbee2b0e0eeb8849c6a58f0617dc59b1bfba8429979784cf63bc1e7bdec89bcc44eb3e090575ea9d98f2c12a6cb9a41ff4dcdc2e390ad5f8a314cbe33683034a8908470400c8fe286d93a6b1053b5e6f5e478cbf2dd10c258e1c34fd4b431e56581afbd1084e71e97da3c2a4511a2dbdcd8cf7d8ccb89c264714f941f49da7941fb1c11a0b83a241054339ca83784a712e34d3a686d829e50de74576380be5ae1c1cc99e077fe486fd923a435a19d9b6555ad855734add72fbe7e719b9578f63e0f1ff16032abfb77cee40451dc6e1d9d5611b7f54daf589966824cb3227d55bc4f2b9fe0960acbbf64e522ef2f738b7fbc8f3cfb4ec092e7608e6f56c0a94afb881f5700361f7375c98c8aafb25f1a52df900f252c7b6292dd85f1ff53a8869ceaecf430438bec3b830e9da4dfef7d9d0316d4803ada80812518d6db64438dc4204b6f20f5fd2f368d3def5df71cb8f882b283393b0965637d8ac400dbf971471975034072c5102599b8dfb098bc41dadad8553f3d8de80b97f7f825be031e4993720ca019c0f6710615bdc607281574c5649551bb4f157162a71f89b5cf57b4f83b4c00d11a5cae362cc831a2fe2886cf766382700b8cb3b63e667ef57c99c1f7e964e02acf16e1b4858d5aa24afd02c8117f8841013476bac8bda6a87731fda498efd02b77b439f4258f3d88a9cacd23fca62eea7cf6bebc9e74448f2979b92662fa9039f751f3d49138cf3c9f996627b3654828bc118c761e2e674d6acf2b4e892820b9eb34e9c5f3755f0d84ea3a75e57947cfaa2c1d2aaf9e391906a92f5aa25c00355f7ece91ff9e71722cac1395e0c0b1829612d1d901360272122a5e4ee592b03f738c0489fb544b24d02a8d28e231378f0dc1cf12814571c0aac80f14eb04a0ac7f5632475083d272560ac01537389afd92a8e8890de713a0d2bcf6566c72d00 +generate_ring_signature 98a0d34ecad7f93a524bdd5bbf05df6aabf1edc86e6dfd555409eb9f12b970b6 9472ff1d85dc16f590c6b034169850cd9a7c61aa49991a2abdaf9924eefc483a 17 808f7fe95ba368b13e3b5f5bf8375263e293056dd4c0b946b15b6811047a07fb 8b7a69805ccfcea3c45182def8cc422c1f23959e156bfb4b94c5fa3392589454 d56fa8d5afe511e42e28e98f7e24aaed8fd49280766b40781ac01b14e402a94f f9e92df33c3a7deaef73480de48f287a96692bb05f964f331e86a7314ac3cefa 44bd6fe3e84c4b5e931d1751bdb85138dbc2497dd25ee0acb2340adabcc3d2ac 5e0e3b4e8610b3ad968c0776fe185d5821b440b1044c3cad601377b92792dfc8 701052782deb012f529a3fe3636fc4e6d4f3c5319c5727db36b7a76a634b983d f37e7aeda09d6da3b5f9d06dab4c809a9a70c58c9cddbfc81178cdb90be5d511 ed952f75fc7fbe0c454228ba22ee45bc4d54438d88e5544cd74d33c5e851e80d 60efc3617bdbc7957d8511526338e57e34f9a8502a8911684d24de2f76a87ce6 17323e276a428b2b238a5c03460a881ecae3ea9622f35add96322ef1b42c1ee7 9e51a49147a1029412502883ee90d0b683925d611e354913af570c8be1549f3a 0ea8252e6e1faf7fbbc70ed8040f9c57c87bb42876ffd8564032776d81dd5dea a7924de7fe171159aa57a7d22a5647f2e968396e6a4e424afbb070b98d0b12f4 f985bff093c1fd67d92b225d00bc4ae37ca856075940461b790c17c1a73debe4 247c72d2e0916bdfdaab6abd05ef5a877b7f175bcfecb8a499b59c6577b93e43 12ec03a07f4f01fcece9465d8967580241577df2d6da53db9a23f5257a62ea6f 4b9071d06ca415811ebf1038c1bad7d7a2338f82b500a3a61c0312d48b09040c 13 229672b135459b0b00e180db7feb3f48084c6b03eeeac5e2de4c97102a366c0d645c9f2df8df0d6bd74eb96020d532c00be3ea652572d0f7be8eada19a1a81068c330832a4b560014aa9c6c5bf20f5f45cd0e3055aa66ad992db93317a907a01e52135d38bd7d7622e928f7fd375aac38e5fe379d04efadfe315feecb25f05065591cc787da2607eba658a5b596b3854a805ed8aca657cf1ee00a9fc9c0fca05485eea448330e740647790c3a658040d486c79cfe4d7d59365099e680b0d160399c8b4ab33083b1f9b2d30edbc4eaa7cbc9ddec02dff44055920da09cf69a90893fc900c2703aaaaba3cf9dfe505cb8173272660dac59cd86aa15e1ab8816d05e842d89aa868173666c2e077b942f733052c7f2c971ab720599be50fdfba3b08a4888c33ecb9a556c153dbbe515ba7927ddb0051e88c965c647fe4f1def8870cf386cc4ba9b309500795c7a56dd86fc359a7a099d5af9076c0944c08422d4503815597721bfac1b774e9b0ceace12ca6f8bddc8dbf57c5cdb37047b924cd25041541e38ce85de6d5b06770c2703b6ea4e856b524d3431b2b9f1890a490d9db0d532d1e7a2828f340165b7ead6f0b855787e18cbdd68c3d631dd814a300dcb006a77f66c1bf3aee949169c2fe8d9acb131e32f9c2ffd23ec56a2829908d562601f3eea6208bccecd66f31f596fa9f00d18a0a15691560866ef26d3d430f618b028916cfdc1fbfd1afae37da8f99a13edf81a0ff3760af4be77e4240afd58ee80bc7127b404467ff65bbd3a8f9e4b642d471461279091675c66ff651d1c42efb094148b87d094133ba314676a5caae8dae51aa4733ff8974b913d8b0c4186e3d0ab3291402abc9f06317057cb2c430f6b2a4908d8f0337a4e562219ccc1d086f0343fb1a2d4f512e98973760206403f6315a59cf5f57272449d04507f4c7330106bac1d2c1c406fdf5d3b0014390cb71a0e4392ee27e22854e09cf6047b048e005d3704033300f50e6224fbe3b62dcd74bf951b8a7fa0957ecf4a226b331ce7f087bf4b8d4e15b2f4d5d0b1b82b967405b9aba037efc362198157f61c4646c1b0e2c398117c269d0777bf546cdbd438a9d820bbd538d2028cdbd8d9cd481184a0e65edc53e29ef19d014298a3ca602259eb53099265c4bf08368466ea5ac9f87084579f421630418d081c3a82bbb32f3ac79bcee4d717e4f6c01a8811e84fcaa01f70de472b5c5bb02810bf03da9adf93823b3d08198aab3fea3359afe1195630579e6a2077f7d711cc50a9c70ae1a111764445ef92e677f1008ea236dfe232d03e4b26105b27f1ac86c2a31ac87cb176e415b529438607dbe899c8d0e1c2dcf07369f9e4c1914b03389c910d8ab43b81ef611b35b518a8854e7be3daa14451605378aefad4ccff7dc639326ac778ca35538671bc8825a110d5339a6054690920abf57a686516f77a23169c4926019b6edaa8b27266bbeef9d29cdc97e8650290e26d7aa625bb405717826284e791bb9cf4deb47fbd0ccb9ed636e296a28882002 +generate_ring_signature ffaebe5a64fa21b3cae1f3c067113c4cf958a4287801c6a10ba0d63a82a16c0c c44d1d1d668711d4ccc3cfa257b24e2ee233322f078e4e6f82a17753e4f5c8b5 1 47d76caa6562600ac2e06caa3b861cccc17d73eb25df6c34308e21876aaa54b7 005c86d012510a55a17ba3300ea863c7179c91e876ee0138f8e987fb4d7e0d0c 0 45016cff505b460747ebcbef4c9cdf8a4b9d12a79a27f3d91c704ee0623d6503d98cad08df6687b15791ea22fef85b50f3cb608d444eae76be8b9b1f6116e10c +generate_ring_signature 73733ec5b86946952811b69e7bf7ba5c37587c91f2d34cb2370d2b9be05a22f7 d8e042940c4c896d6b06bdc0fa35e077a07e6a39cb15c2cbf9ff5c6df99b1cce 15 9161d68233642bfe6035afaba1645dae605eb345093bc46f03d8f142d5fb9fb1 128cc56981de785308fc47e1edbaeee881f818971d65a8a2c0100ff1921288cb e3ddb25dea20e2fae36efcf1c8cfe7d3514b371157a39108f4b0e7609928c716 d08ed18856d466f1ef3f50e49d0986e0cc3718be4a5dfc99311070f7b135891c 56cd77bf457f0ace98ecf454913a8b6940424c0e12e183b5bd084c34122084a8 232fb54db3f3758c5329d8d37726dc8bbdbf44403192b6dccfa8d3783f657969 554b67d108192723af618ec6024f9167100dd252cfff52cc9288da122350b548 049a7ded353d5a0ab8661f1342bcfb123ae5c8369c8921b5589a0ee96ae49512 ea95222a7f00d7c6aff189b8fc0c3844e24375a511ea4d62386dd6d5599f165f 558cad957191b01fae7f274202d8faa3b5b71348c1ef4600302a84f112bd2f37 c046f7d11f1a0eb7dd6f25dc1e83c2ee571e43241fea595625b06b18180e64a5 2f203ef33ccbcdf41813ddd96364179f00d04ab0c475744f66eac76524dcccaa 1f427b4add5faad3d81832802e23ae646a2ae862c51575d6e753b35fc87c51fe 9fa5579abfc3a715e844651c5985800b8f77f4b2d2c1ec4168e6817fd97cec7a 56144586fedbe763b3b0f3676cae4e49507c79fb23b7ea08a8b755e70c46e634 5e508d8a5e99e8ce441898c87d40de7b4a0cfb2bffda4b57c89d20065c9c3604 6 3396a42f0704bbc70dd830a500ce3d1484c41c475af49ae31c0e8e8f4248a5087a77d595078a1035042868f98373f7966456cd8109711ec1cf4f6a9f44dd010a58ed9578348fcd9d1c8cb569d81b95146d6b42909d46fc52fb06528344f3160c0b2388c2ed0ceaf32da74a5547feeda44f08bbaa7d04628109e73649b080120192c9ea78a19e3c1cde8ce487d07f25e2c4df78ad19f41fefcfd245eb03af380c097add1152d58c51e97d830ef654b15a93afa0fcc0f319e7304f7e8fd331aa047a23a03e544c33471cc97d6ef893b61cc74295d03d1dbfa105e5a02207ac47035663503fda553319ab0d830737ecaf8ec2b27e23cf5034bb003176e98319f40a970c7c7d865e7e287f028cfb8a1bac0a0565c0cef9fd319296597dbdd44b320d4dc0004a909b0ea093f3f5a7bf9395f1836f675f63225958ca66db4244c0610824c5ac795e078a3ff4d70c021ccdc506e522f9b57d6ccd5c61a14e84bf7bec07c458a7ffe6df15fbdeee0f44e89a762e47229748764fd8c2f653927dc65bd700adcab9dfee11bdc83fdf0945a1ba0a237dfd7c7f1ce75117fd5eb17536e45d06f0b765e219588b62f336147036fa13d0df44b8f1535c740f8b9110068b4bb30c78a5fba36f3953aa802e48cbb5b420f34bc3d29445f7099462637dd769c1dd0a3a01e6d2cfce3b2bf86dab33d4167d307d1d25339d10854dd345ab54cef52600d6e377bf9c92ac9528a4ff2bd4931a5860e7387523cfc7cb8f70e95ef5752106eeb98b8985bb71d16d0809ed483d87cec578e795f1d6e650abb548d59de9640c299d63a321d9bbebdadc554982029f0663e8392a53829475308fa7ce53b431082023ee77764f52e79ba7cdb268deb5d8a13cae9921bad88597cac23a33d931025a12788a0254eeafc6f242646e7723ba124c3d30476ee70097114a7147599605eb282bc86b5c012e08176e40cf3930fa956b0f340af172933bc824c21c177903c70f70185bc2fe378e6279e1588a25f178ef000ad8a6008647d53742cca5ae0871fb150c700cc649c70d19262811dea8912ec0900429e554e56a6412cd492606e2bdb0b2ca12269727ca3e3b2e8cdfa738f8730914c63725af4c7a8f7b8c100b414794dda4fd2477d63a74f167131088cc070bb9aaf9f14173fc02db48a2ff0a8d6a78a7d3ed7ce29b4869fbb4fc1404fb4a9d2530d4e0cfba4afb242758f5004b7b1efa019ea7e30ab61f25a8ab5bf92c0721e99700eae5ebeb9a9fdd3e66081ff4ba01ac9bafe46db58d196c11cb9304b14ae3d7a3385f6cdb7faee3dc1905722eacd1e4d770923bcad99a45aebcc75b602151d36a2a83e7c625cd8fca480e +generate_ring_signature 778bceb8b14ed5f0f51e4483bca6ed959b851aa5ff880a59320d30d0e9c9ad06 d8508c6187929646cc7231cb18a959d0c181e5f40e550c32ebf11dab277cb36e 2 dd0e07b025b266a88482d72d7d3122d2513b11966b5f86b0b3190402e30343db 903bff8f1f2a393c6f31dc6672be383ae112737329059fc46090bb1a9d684c1e 4a41c53827294ab03c79424b60a5faec6f44fbade5e01d59228680eeb4a00203 1 2b969e32a19ca91c13b003e1d038f1b1b61dcf5c03a44d46932157d48e77d50430d0294cc416ac98a306fb9adc248d16cd6674baa2b24998860f366e3f2b4f07898b4093a049b9e6a79b56fd94a82f8446e7dd273d4471d7867ccfd5c091f40199c88f0c2d935e9257de150ff0a23cb57efa149828022869df20d7a1f5b04205 +generate_ring_signature d0af946a7168a2b284854db904594d1ad9055cf337f25b80c56f218d3c0d8dc8 ce5be5577913123659cbafc8e7fe1b31227e976ec379307282605e229aba392e 28 b5bdd837cc0aac94b3fbcfc27fb023126a3ca0308d6f9ba22d24322d5eb01d57 e1b478d03240bee41ee60b3ce5c2875637836588696ea197fa4cc240d9f6ed44 4edf95184182c3034efaed72684168f95ad8ec6250c25b075f0912e2d4f63459 1e9cadb7f1407262d64ef55add50c2f6875160c2fb645c8c8ac96d2605915e77 4d888e5b483d209c20b60c5e5601c42deba7f05592ec656cd665576a0bd3f742 bda224dc161b87b51264856b6478fd355106105b80380ceb36d2e18e5981e6a9 37f0548f3545620b3ef1515fc5b522bccfd8b8a068598495c4d2cebabff9cc02 e386b54fa02234238ca51c9939d2e3fdee81abcb94853f033c615422babc8f63 4247bd9140878709938dcb0432c0ad95159a00c66902c004d2ea09e2335cdee3 93ce5626ab90afc7f16c8fdd870e9d3640407fbc4c29cc12c11108a852208774 a68380092c8ba661fb24f30b21d7df4b840dbe8fce869394986c7ae4e2edc0de 25be966db483ab07c610bdd83a5e26019a21c9cf65d582d3aab40025284dd4c1 ecaf62457619b1c1362b35dece2209aa5eb9ee8cdaf59ae1d5be775fdfa987ab 5ba393fc4c396411dd2e3e93455b31b17037e14f9564d9896de7455a1994ba29 16b37fbc30dce9dffe460ded732c588b2a863563c0d724cd909cca18df6ab50d 4e97f0370be8608c175717e554f34aa4610daba6cb16fb96c4136a57ba230b9f 86244bdecbd028e5be7c98b2d347e79647333e71784a584eacc308c094cafd2b 25839bc668849bfe64fc9be62997fb93d1188108f7565498c33f3f4ea4e1bb23 429f58dbe7f3eec5dc1bf30ecef4293381c828c5bfe7b7d7bdb6acf942cf858b 2e852cde3f41675c3a1aa901653dd6f91229fb5349b59b95a86669b806ad6d49 b0a6aa5f72e0b404b831b691b29c810c533abad713128efc640b78b46b8bbd6d 8bc504d0ccfc3d825a1de31f005b02e5d7e8396b213ae78dee2745ba94af12c1 4653b7942cb6e119836df837d39f7b43339ae6faba28856d987a50ad2794b292 454a9c491f09eba303fd689918d9ae6ad662f8adf029fb687dee072d8809d26b 861cd74d161b68c89564fe7621ed75778aa4fa86bcfd60b981b8fb5dfdcddd16 da9d169079abbd9219fc9d1ce674378a218433cd3058d7f48e71891724f8e3cf 90e52c87f417b04bdb42a50cd4344c89d2ef87d722ac451d8ce89cd148b9a69c 6226f09a0649ce2c264d056d3dfdc74cc8edca34091423845c78bb691bb6d89c d06d01f7eaea9f5aa3836471b07f66cb15f9abf5191f03245633a73abac12609 25 e1b1b68b33b8abf7dee5dc42cf1fa130b9c9e5108330d374b37f154599ba290f9b983c7942f66d50bea032c6ee85b9472c186e50c53689d09a97cc657697e9018a3207bf4d9859058074682b23d7603fab003e18b19c0975174be4267f275e01284d7ffb807527bde515b9161f7708a30ef256ab7dceac24044a918d8ec01701282e8d37142e45b9d6ba348e23e2aa37cdc6c0a4f882f48fbd93ef0d843f6405af3f86e986e4fff771a532d0f1def54ccc8c7fd0a7ecc6196069ed5235d35505c24d5e3e1a1c9b01d130f1eade76aa4643ac0434ded63599bae730532253d605fecb9834d901326f3928733a002d9110d737a79f397630af8be30a5e4fa027046414c36e1bf9188419d80ae52f9d309e1fb1f45ab402aa2b4544d805a5c19207fe45708f8f01111502742e23a63b61763e3e81f48f88344771d8b50740fe940edfafa34d2da5d0312d68a5de4fe27f95b40382eb048b5d17edc58c5117b21c0478b40196daeb4e191b9438401d51b96a43664e8425b1ed3f3a834b7866a5d00dc584f7e68c4a54a1d02819f4855ee91a8639513fdb94ce05d936461013a4420c8b14ffd7189c6e88124bdb69855e23790cbaff2daec526ff7daea1cfda670c086c269540d92290dba760b24ee696ff5e061e6d18b25da69a6cef3af82e08f708c027bea729340395a89a239d4636e7079f95c768fba29b7d2c97c7b57d54590dffb96fe728d290829f9382e50bc3fdb14b832fab00ce44c5cf2bcc9382c3c303d806a497cd1e8d1c5bc13183b9c0b3581f63fc3617f1c6bca6d3a953a54e7f0d8fb4e05aa99d90b3e82c8d097279eedd21317307779aa1217d4b9a65349cf209394a10b7fbbe87dcd98f9defad1c39f2e59d2b5b511b0a3cef72846f339cab0a79e2b8fc82666e6d6164ee050ff1a74a586e9bd7796acdb337e154cc35feff013ee0337cd1b6291902f904a3a0c0463723ea2efa0b530b2748d30367dc51b7081cdff2cdec7083a3df621271930200412fdfae3a1cb69ab25074ac6a2b260209f185c74313eb8986e4d99154cf0011ef57778013d80205d8bcd4ec3f3d602f00ec4d597d9c207b6ea53062a36e0f7688de8641cfd09c418ce217e08b7f31a10ca52afc702255a518e24f2d9d78fea290ae9eb780ae51f5f75073948960fce00d906fc4e84a7670bc547708d2a52b3ab3381e7a540a77c1ebfed53de87dfc81046e8c74e582d864379050c61296d720be792823eabee0fc7a2f783a902ea020099c1e090e13bc4b92db2cc059b32a9bc73cd598bcc023509f6191728f353c93069d637c734d5f860f801b4855c9328bab9b9d59eb5902fdfd2a67e1d26ce7a30d5cc693fc0bb0100f246b24d59c784e029eb490518402fda1cea9d3cb5bc62f02a179ec62f872374a1061d9a0c05eae1bab485edbe8e53ef85ce34b89de471d0888133bd506de75de0b29d3c5c40ae4c78f15ed4168edec1a0d931fb30b457e01bbc51160e27c79bd01a440bc79d0b6f49e58bfcf3c1e2da8e11b7b4354ea9f067d3de16fc82e9066d181744203447c84bad3bcaeb81a737ddca73e29405f7404a30b2cdcf2eccb50365d45036f902abcbedf6e3b9781993f3d64880ffb65b5066fe8c78c26c1f4090059db8feb5aeea02ccc86cec3a6f18379465f18fb80b40745dbffd654db4ef3fa0ada21f542204df570ad54696309bb331dcd6456fa9b013c6fcd99601c397911d4a053407c4fcc742b6043289d036bfab167ba1d85840d9cc14e881e52f68e7ef84f895986f5a5c4c82c4d1974acfcf348bd382e6cd1034300598fb6b438164d7997c93f3be5a3c94c4856523209a9768a5ebac7866406e2a3fa1b21d7684afa80afa7ae616143631f6344264be67968e4ace35cd8850b11b94c9711f89b43172d0fe7c4119e1480b50900399417976abf1096ac278e08af40882eb26f137446c107b5af3de323287915b727741afeb8685ce8a0c5160761b2397955cfea1e719fde1eb180bfe4375eb36d4d358e4ccb3f05e1e955ec01b5e663b12629cc8d5afc25735a97c1a8c53d53deb8c49014423f6f953fa86f0ba4dd5194abe5f6a1ade9ec84a152e4bcd95c909a84e709cc015ee37999a4ea08d904ca5be74aedccd50b45a2a892a36edf5868cd87a282677c091b21c91e010f91151e185cf33c68854011540159a89ccf582ae4b605e168ff3d7c447242dd07cd19610631cb4e817e879ba59c637d5e0eedb8d37f75f90274fbca5d8da2d605d872cd1792494d2ee321c83c7cf73ff5e63cd74c1cb8d59f2810fb7808de050d166c9761d5a28ac38f7e71c9ef0216d833ff601bfb201205e5e740e97078a40f6b207101bb41f5bfbbef12d043281d6763881c7f58dd3a0ce83f102cb1e24f07afe7e3132a83eb35d7506b842192b407041a219b8ff76757a5acbcdee2847700696796152b4e794fcd481520fa47fa9ffa14da0eb305fcb5c8c71de1446f370679bcffde16f2c7a30979e1047855e8116a4738a82ae4fb2dfc3fffe893b8830a +generate_ring_signature 32fda91fee7ffd86261cfba41936bb2a57a1babc1e41c93bcce51132d3e9b507 faf0d72af0aa2f1935f9dec6852902445190d777581a778a7e1a92c1bda327bf 7 6e89346180becc891a370752d14a032274b762a037103e634b45bfac60809226 97d5764cdab85f5c11a86546a36a96bae26bd080c451ef596daaaf5ea684086c b60d1e57e2d34be3512e8a2be4b3d00ae2fae3632b5f9b0ee1c71705600b1c0d 3f10de099eee553e1b45f8f68a760d6516e2690ab993b9bb75d57a09a0556f70 070eb1a8fcd9732847154aea827954d8eac4034de82aa78cd391ae8c8f395e19 49ffd7d2431e8db5626d37d6220b630a431cf592bd72faecd522feebba1f2291 cc1127fab637befc072b81cfc583d2d93180133cd0ead88efecddd89bc46e4d6 84eb3ef42330604ceff1a7e02b17de15c717f1a904f34db6c724f1702876480a 2 63b1587bf7fd448a3cfca6ee640552adfa52bb32620a8b01fc0544f6473d3602bdb97235dcfb7d12dda8a85dcb4d346b3933873948f3929ac8f54fdefb486d00e471508918c1f7426d654c32d1ca8d2517dfa246060670e7ee56b2e9d7a532073f356fec3a2c9d94824f3f702c036b58e71a76ba9f309736076357cae37be606413e0a5bb7681fbdd6511b74eb77edf3c7a10616e26d53c91bf5edf267c48c046de27ed709a02fe8dc879f3b37c08dfb8137e6b035db8f8d5d92411a03ad7a06a5de9268dfddd7cf39a8105c375d4e5ab6003602a66d33e63d99f966ea569e0a1f221471be8cba8575f049ead182886c339e7af1c4ad797906faad46997fb5084c7164b1985a1c2cc2c903200d2257124a9c2067c2e19a24549fee85eed6240cf5d288d87511e5963fd23c89575990e7f8eb9cc237b14740a16987b99cb4220caca046d3644e742f8d099657cf68945c4e1e502195c382daf2429bed25dd1b0761d9141faf6256ead78c7aee9dcc42a505796bdb35d94ee565e468bc7ea00006ca58e6f4c6dd591dbfd6f3306d2d765522f68bef4ede7405190da56d2f3f4907eb98883dbeb5f022bd4190e8a34b2d77f7c626e75675ee08b51f1693af8cfe03 +generate_ring_signature f95f58b92f28fe5c8cca37b620c77466d564444b3c4b27bda95be071949ee7f5 0c7a668470179291b39470d30af192a98277cd4c831bf6fe9f3501489ddfd8fd 57 9e703ea6f7136edcb82cedcbf43a68c6782e8f1e57c5c2303b4131d1d5215b78 2ca97ab38e7199a22fa6cc16ceb84711e9f2a41a8f997386ce5b60332e752d32 15cf730ebedadf9fff98d1d7c42b42328259a37645d31ac52a1ef24d67208fb5 bd41a6107e68625847b3eecad7c295f58cf612069e47eb4a713f707452687a1b d95b91d6438f3fb2cbafc7977aa1c84e9869cd78915800f9560d3f0274b2accb 698db750d8b5ca89f0a4b0d0ced5f429626aed733dfa772cfa6833c2b97fdae1 4cadc08cdee26ac4f3f3cb932ceffa9ed5e936df7bf97492fd07bea007d5aaf7 5ff610158afae988f8cc3731b3f0613d1300df97a6822626f845d8a73f14d839 46aa6f92903c682a2897c8d73559f1db32dab440f857d9d3bee4e098fff99656 20bdf6ed73381e3da67d3a8dd62e82bd51afe2f750b7ae124b08583c450365b2 640e7073de6dbb3a8d8497c4a3f9c60332b485645519b2283a238742da08fe46 c9572e5cab158cc073919303f7c3288c2245c49de1129aae637b38c5bb62303e cfbb23c7d6ddab8a249ef1e1dcc823e9bece5a2eada6ab13fbc1242131daa612 8afa786d231a0c09a13d63170fd8226330f81f708147a1f47fee7557ba27d3ed b365ca81fdd650d274f1ea94c492a4a65e64adb7b0fbb6de9528782a3650118c 10984b7aa7bc1ac1e54125f0cf87f802a9d64ef28ebdf3dc91913a4eaf8aafb3 cc880b625163e20cbfc65210c127325e4b3a17af070d1b74126c7227bfb6d065 0344b564c3e1b91487e607626636a5027dd2a9590951f55647853ab8a886bfbf 5c568bf19007ceeac73bbb66d53c2cb062eea710fa82590f76da6845517aa8f8 cf31e75da46ee36623789933c452326df8b33609ff549b6709bd747f3a973ea7 c3af861bc2c38f2d94889e5738e4a756b231fd38b39d9fdfa307a6af6a26fdf9 3dec71fe173c27b02df24e8989cf7075342710a13976e63bb740be0ed3cf8881 71221e35d8ff84de6fbe8a8a23a6c94d4a2e5c9dd5e0806c337b78b40972d968 7433536546f072ddf45b1cb55fbe68a3c3b6154b4f43540974df4c96c16df3ab 62b2725a6f4ddd4e5bbb0728efa86630b41d8ab848d746f73af95767fd57fcec b6f19566fde140878f4f1fdd0f64ec397ffc1ecd66d780af774b35ec329d2139 b1e53d524b31832419ca5ef8960245fcaab7cf1ee7211f3de92737fcd32a2256 156c9189c4541514c557e3767e3ee07429b397cf1cefdb7eee9c978d1b11f6c4 4babe5081a6e5a1dd8ea579522c8f6a44db64bd48229ab6ba7f9758990c333e4 3f6ee7d39a89bb34bc68f02557cde48c0f1e4ec9654d65bd704637d16fd26721 4512838f751891c81732898eb640c8512b6a77cc7d63a3e61ae0827b7f710627 a69bb4cd67c4d72585a8d3db4000429a3ca1691f2da44e01ec0113ff72dc895e b737c73f3572c71efe7cb285879ade2b174b65cea150f180eaa17014d7320cd0 7d472b19d3b3a828dd67749dab91cc686c0aefeac6f10b021914362e9e3db34b f6158b35f8a7d3bbc700d39c43483aa57ce38c8e6ca1195eeb87c673e5c2eb48 5dff3f8b3f1d276f142d69dab6f425f4f78b1a18182d1ad207c027114a694b13 e54fb93a3f15286ce5f2284f284927eab88e48b8213c1a41eeb586ed999404a5 7dfe099cad93d510b49cd166c192e813c3e512a62dc4ed11d9b9f781f0194c80 773cab6f26db9c2c36da474052966fcafa308ad649ceda337f764428948abaf6 aa7946ff4d12c48703c04f6bfeec86d18c4a854109739b3863e4b5007999e2c2 b386b4f889db963dc4daeb14893a3b0b6c3b09a3920a1bcfd04dedd217e573b1 0726fc793b0c7493cc0439189bd82d5d0c3dd117b9aa33d6a0d9553de873e88a 93f9a1f0eda3a75467c99b01005ff16a4c8b006649f77533cef185c4f7a30b08 377b1b8895d0b601d45a5dd36b93eb460ffd9e30a0cf1d96b91f7f189f4d8732 5730b7cb7e779695bd04de02fbc180f8a7b1a7e6d0fcc066bb28d4c94b3aa021 548678ab5e2fb6d870d6c05e39b3267101011c0a842f373b0c9735313fe7c207 788e4bca36e99ac9bd39e7e4188f88b78dce485fd8ce7408ab5d5588a82eea61 c7fa217234c15a4b2af0aca4ea58af4d3762dcd3b17a7be13ad882ea91539416 12c3585925770b39fe686a8d04ee10251d504c94a6c16853f7ef1a6f0a525556 f8748feb866849ac48f120940c6731791a593e5973c9228693397d8e3ad65268 8bb30ab41ee5221c65b21919b8a784de26c55983fdaa5bf635a1156b51213f77 70a7fe521146c4e2c6d0673e9e31f9931c0fc79d516439422dfcb86cd52d6497 a85e0367501bb37a0c8d92a311d3b6ced453790b116246c9c5b7a3f6022d7dc3 062fc5d81991c3e216ddb0caed6fdfff321d73c2c5fe54b9d956d18cbf7b7c53 fca490659c54bb57d385e33e8b67773bc912ed88506ad07f33e4acd1444ff692 1cfa1c7683fd787875092bb812b4064d0beecac871e1af17e72d359f27e2d87a f2a11397ecaf7753c18f0a6970da0573a2804bfc4f48c099b29e71ec6397c2d7 25a78e09d6d2bbf9431db8891b048d8429eb7768ad2fe5f2482a76e03683e908 5 f9ea10294467d8c136243972b0fdbb2196005c6a1f3a1d6b303fbc3e4ab33c0cbe87d5165649e1443007d03c41b97b01d19fa6d490cc96dc93ecbe64e164e008977bdae51d5731bdad097ef740c6b12ebc634fdecb82090eee099b72966356006c89681f1fd2776c29950605daa95cb1a0fea3ec6be1a7dc91f8dd626c570506fdea4eb5cb013ca970c104e0a39096d5e4a7388740ce44ca0d64c2c6c7448e0aa867712abc79beb2d5366f368a75edf4f6870094cc06c091b0f188cbdab84d0e2838297f675506a5914845b282bdf3c6e1120a64a64fe0ad2ded2f5f4e86970d09db1b11d7420b2aa592ea3ba101390beef50d42596a44042abba6b7d8f2f40d7c7468f1048c90df151aab5192309ad06a3674ca1514d92236d7b22e1181ce0f4eefb20b710fc0dcccdd141b012f9142ab7a35051242fb329a56e499d1dbb80e0bc1a3d5b28e344e0dd4640f16e56f976a82f31b06bdca058f9b4c5a18d18d0d94a18c531034d4ec97312705c893313cbf3395e1e071681e468c43cc39b69f02630d6934a0036bb8d3ddaf6b5bbec7c7635bd64c633a8a1b784b0652df984a021ea14af799a5e00d5245115081686a6e16d867a37c7a0ac864b4fadd125e0c02b80dafda7e91ffb641ff964384b9201c0697e3fd500babda58839f453735eb0c872bf6dab726fb303ff13cf7b2730c0bb8b13d96333bb01e5e27caaf4b6f760fbecfc17f0359b7e33745774dbf05fecd45519acaf6d0204d582dd60df48ca30946e6f2ad7e28ec2e62d3ef75a32b7434c723c28bc15ff71d0f7f8a6e2f6151021b4502ba6ee6042d56cf7d8ddf9d7a45728ad1be62aa7078e9baaa6cf2cbe80d336d7422f29c6354f73292f3ef0d19dff321bdcfafab53ac9afb5ee924e31f07dfdb9c832f2eefd29d1e44435e8ad9fa64b41b612382b1362a3509d78632e104167cb17bb645a4e261db047ea86e6261373e1d67844fcd7e87d8d6b24b0b99083569d0497527fa36c53bc9fe0bc4ab94347fd9879a79501cd19565d81718970d9b863026e088463a9181254bba9bf233fcdc22c5a5e3379ddfc33e950b11c8040ab1557a7753244175a3d434862bb07844dbd2da6087f9c1524e83c7e8c9d60ee56b8f55cf0b61cf122aae9592d0af9a9abcaa9dc366862018892676cb9645027c17e9493bdbc53e5ae8bc29ab6751f25c0e041a4f8acef0a2b6534b5036420e2bb54030f05959225d4c9d0ddf2f9fe0ce1841d4380e52ba5fadb5e586582a06e68acfa26cc07bd8b918d4d59bc9900cbf525586b2da060fcfc9dcae2fef270e25a28ff4f1fb449aab653b865061d4a3789c3201d6bcf00c13f8678c934d0009b27a5990281b6a3f977f7e2bd656aaab4cda8911da87b1499b17116b202f5b02fea4ddaa82e5cb4b270b6142572eba727903033a45267567a39c86a3199a1c0eb2a97f5c5e1dac1fd99a88eff6f1930f3b5d32261ef6ce8bb3f721ec58d2d10dbc8b669044368af81efde77025e31ee9c5e226acf4856341a47bff97e97d34093db3b6d11d4c3a892fded7f9ae333749e1003df3878707f371444dec9f756804e3414a70d52120cfedd38aea649fe4d36ef2dbb4ad8b7e9c58a2dc586a416500f817d95d36dd89214f5df4783f08ecef3b7dfe391a5044b77d7b70e9507c3c0bc8f96d8716eafc2310c17f6760b6b3451dea0a31194dc4fd84a877b6b9c41700d2ed8eb936139d08bd0548dce4a7437e6aa6a17b528f5a9d8f7f01882dce8402e7b19d53c2f8ff1e2738dc2bb6680c1be82abd48ba09f9452ece81d35d1ff9058c38d2dfc00b6b4dde5df1b0e59f48302332e35b5227398497aa80ce4dd891019879a820f92e3ef301842993ec1d810016d21148543991549c110598d2c7860d2b4a459e75f8a5a3bf8aed975bc4335c4f6aa2da40b9b4e9875125fa7146c60d535f56953630fdee6df568aa32c406e0fefe6fceee7129353103cd37d977790fb18da1650495640fd49772dfcd2f8397a3d01b9a76ca4139ee8e9f6fb4399e0d3d14412fe02a78c0cd3873ad2f3a32c31ae05a98427bfa42916223fdac912b0190111e7ad6fd7c3a438594e9a2b2264abea9639773bd22be11039634a35d3b00e9daa8823e4fa8b077df4379f1ee1f32f31c384db9da7590b3e30d1cf7225b02272a19e373cae8c7a1d9e7310183af3dbd3ae19a6060d3b23071dc8008487905a0ef9011dcd39badf5e1e4092ef2bbd51a247d84d77820686d38c26e7630970fcea629f12bb7983c28be7d73a92fcc401435095ac66bd40350056445867d7b0f37aef3134b3d01444c9e670a6615557c283a7592ee5f446480c40fb6ae9611061588c8b6528b0f8b6037e60f4272258e886105e2d48eba295348abf04816450f6e0ff1dd7a9cd8f278b76170b8092ecbd63236ccea97539c4708fb212a4ee5001f67a175b927bc5951c9c0d708340248e59103b86b7d32c591251b55f753e30d404bf8dbf40f0800348b301ec6b6b9b508667c8548cecac573ff2b9a2247630c51f58d56e558e39fe65d104cc73749d686bf8071da26a2abce09f5e91cb39c0c4f28da63b74a1f27a4eb9fbaf27732a3341daa872f87e74ab38a694f54da55095bb5c9b4ff005615c7cfbac47a55a79000f3765b20b8e409a664214ec86e5c021412f6505b59d347d98c644f289dc752b97a20767744864d6c85e46fdf543b07290aecd9cf9afd8dfd2cde0fef08fc85c3b5fb1c59f3725869b1e883162a2406e3aef1e43e983f1fa91d03d6b24cb8100717138a64561bb2582884d7c0cd3b017f135a7ba72ff7fd095cea52906040ae914499567342d59908544a8d1e7c830af8892a55f6408f8c45cad16a23a1ed76262a3a5dfeb8b174996263a5a39f2b0aa458079ac018f048658716bad78a2f263fb041d322a8a437468b5292ed835a0ac46664fdb56173d4922102414e37cf65473b0754ee0112ab49cfe997323a61001f581875efd538f8c6ce3bd16d191a3515c8248f4f5c4b6e7961dcda9286b503dc7d69eec532902a8137c71355671d69ac71645a5742f1dd8c19b1801549830550b600ca80e76d21db282c2706e5dad59a1d8067b20ac564bf5bd6fcece0fa02e00ea91e70f1ef97f0109987761778ab1ee5dba88db2cf88c652941b5ea0ea03c0d41a55845fdac42fdbbb91b4c78ca2fac40f2786d3445a116f50cc22519606ec742626a24257239c18640c7d548b08cde9ba01c2890eeb975bc1d7e90f57088ca8e24a5261cefd62eb6cca15415a23c050d27da45cc0066a80db5bbef4d90928178802434ace8553ff4f54a12b8f11981f757be7776010e6436e0c72820509673ebf236897067cb144ab2a14e7c1a38815c08d7ad3809d86f4e4ba3f12060faa3cc3d56eeeb259feb81c1e19dc6ff6dbdc19b59c8005dc530915453362880aec9cdeaa0f720c2e1f6d9dcf8b2c805a42779ff93f4f0281e9191573cb29ae005b0b3f61fb7a1a8672ab2386a2a258cd3d579cceb7b81cdb78c82030a497f80876b4293ab137f0459119092701cbb0491306e89753a8fecd8356d068f843a500b3924e55199d1de3be74c9d722864018f47ace0b74dd4f9d639ce80d04abad00347ae4583990c44454d7331cf8cccea96427a4de05d34a3a955c4f1e746a430c834de19404a77fd33796ba12600690bb4441f7620a7b21e5252021d6f460cb0c59b0b022c97236c98550f26499beb6a80c8c5c6c2ab487d15d0d285b366c1d039378e2710597941242a64a2a9d3a3b9eb72118ed58b18a2c5bb1572e91806d0cebb74327e2e0760e1e81a2e61792e39f4f6e8e374fb015d57219078f8e8dcf00ded933de3cea84f7ce9f47210d43cea3ef0971b5e428f141ad0dc58ade09ec0eb36602bddb295784497b2ff23d589a72900b1c5bd596f7f3eb9805c9ab6a7e0dbe75f936497cbb41a029ee027086da196ab971cceb28662a1f0a7ef8b5fa1d0b1824e3a45f9619b5c6beddaf9d6de9fe6247094e73667d6fb0f86340e9bd4b080ac02f73abc702cdd9ff4cdebcc512621fe0e6e533c77e96f15dab1766a4b00a15e5d2219fd4339ac2ce51b33d8c93994f80b6940812a97d6ef5d75f079e3406397254b1aa03d06464fcf4b1175e2986f76f87eca47bf9a12526d750084f75026ce571abe2aef2dcaac4d34fb704fac8a375b71cb24696e51d783cfce68b6b072775589a34609c5644e1282b6df5b59365fd7b6e67e2a1c38dd3746eb2d56800ef7fec80fba750ac12e0e6253b0f47011d422b73796ba53ab7f47b3ffb5cd300b0b8ad0aa2f416c22257e6214159935a352efe87bf1407856784f23fd1014f02d44bfd5e56094eaddb138e33d79fad843507acb4df64dccb9a3e08cc7f352700fadd7c8fdee2868d5f6ecb32da1d12d4d782e788ebe071b78fed25bdb41589017fbb07f0dfdf9b45512c972adae139476da1af30eb19c34dc1b09f846e4b9e0d435cd56833b2d7a053e5e3475dd788e6f184b75ed53c9223012fc7385856a6038239e38e3b15169a049ecd44a04c3dd7c4493ef64bbe1a4c248eaa47917be80833b2ee25df9ee4f2748fd67439e41309304a8a8c797d14849d939bdbaef2c706065600ea940ad7952238c7fc512d9cea31e927a2b6799aed1c2a89a5d13e8607b49aac43bda321e980538c88bc5698c7141fe6feff5bac98fea8633aa96d3808606d545f289dd6741ef12fab862b4ae4e50400e140e930540dd81cf78b2f110123dbb0dd77cd6481a245e16d242f2d9aee4d1c132beb8ea45ff2e33e6ad8a407e20028074f1a89b6eaf6c9e2c76b8fffa8096603a1f41843de0130d968cf2c0b9ce0b54af3c39ae5dfbef615e8a437aefd3b4e8f276edb6a79b802238d995602ad64f4c7dfbbe2803be40cb3ac3af6a67ac86e1bd115500ffc95af0c68885102223c21be4e38ba59c440d3ad778ea28a312d93b8da981b615ec14eb638ede802f6f8b7a9659a178a5d0e428710b407ea1f0f981806bba9dc7850b15c3371c3092b299dd69bcb72f2167a50ebfe66d75b4f256fe16254792f5518e1389585d80c141d1cc2116189e70f5d790e58fdbe1055e59d4670810169d19ad0f5eb40af0dddc7f10e86786ae05cbfd4a5897d00e3f175203ecf39d6e33e252972d10ebf07 +generate_ring_signature 3f9d1e8c4afb644f791e59e8cd50f02ffc79029629d27d18462bbf999fa28537 6b176e3de6c8e0d8fabe2e2552415c02af6c8d2352d99c208af199dff42d0a89 1 0870ddc2441fb0194765bef22a548260bca7fe9f8480a961f108f601798dc115 8c1cf72b82661277cadbbedec6b11e35f7bf100ecee3cf1fa9dc46de1d9d1201 0 449bbdd7fbec125afeb0d6efe02138156af9ed187ebc6c87ba1effc72b58bf0caa111a98e845e31297cea029579906a9bf19de85350f6a3a932107f8a752b909 +generate_ring_signature 21021e77c02b18cfd15c18a1a6a46fec6a5473f49fe7f17f408c9c5ad3bf9f77 b34901b76b34408675b429898c4c3adb74859e3577bc512353ce51e338bc1b80 7 bf6aeb0c9fdc617e09d5fb43f98f77c0e4db61b442411f17612d8f7d68030d8c e3134f86f35ff93536f816ee7c71a22658f0922dd6d977141fd3251117adad6d 0351df4a97e005521dfdae09511278b8789a7f095ef151c134fda3d71db05438 31ca8ba0c25b68cc7b0cfb6d37ceed81333f87469880e8a4dc431daf9b3213cb 12887b59f4b5af889620abf19a52a7bd1973e04d7b949ff683dd3da922457017 2aaba178d00eb926ecc67d750d6ce2f10402e59cacf46e1d60cd2bd2dacc7c06 ab66bb5959bfea90f0ab7f1d6c78b6e380a8c91ae5b77ee24357abfe128fc625 9e682a0ce957782de7ecaef9010f9bf77483a51ad18b513a8acf4ef2c7562600 1 db0d2dd9515c7577b2ada453627af0762ea281cfec691f15daff0f52394fca0e15e77e76f95291c4fe218a781fc5e59c686395abaf78919f65a89c907a29ad06a8dc140b4baeb9a4d79114bf3ce5f64cda97565cd0b7f77336e3185a41b40b08ee72d407cda37652362a57e961bc03f855a43bd11a4154c2706bb445a004a10c6a8be05349fd52b13382abe407f08fcd76e82f874a380be55e02c92827783405c5a4c201e4136d37527fdc5450fa536dfc5c029b85fbe2df2a451c65fcd1520a73d6d78fff06142f260eff5f68f6c6d6a473985d4259a50ff54a15a7ce0d9a053621fbe346a8fd4535137cfd5198a1ecc5cb2ec7e8bf4f7e48b4d4fe8abf9f05ed467dab5a373d91ed646b7183fdf5263dfc4ad173714ae7b236d1fe6ea45e08e422649589ace8c836c991b959155a8a61f658a60f4c7b1771a0b56bb37833065e3712f8a4d0f41adf484a03a2db86cf3ba761759581e9f339c8723133f2e707f5415c1e6d32c65f6917497a739dcb633a51be56c46baa4196e0057feaaa2f09efa4138cce6f362fa26d4664700fa5e7dba5a9068dd05e75279d7862b628e503d6999aeb7c7455fc1b6ef2bbe1605e0cd615f80c17ad4f50f568c75b8b34d40e +generate_ring_signature 953630fc2044cd653f7a0ba4d3413eb62f6e17867d2a24283d65c3ce6318f887 e901f99a3e172a3f7de853302c9ca5a1ef79f5762c13ae654c4259e8cee66e33 4 de453f88739ae0d8339d5176fee305db6c4558ba79cf29f7cd9d578ed6f93f73 2662a16a5721e8273db4eba161eed7f6c55372ce1b57ffab8347f94ea937ba77 9b838a770120cd96e91ea3753b6728aa50c8428a6bda2dd55ebb2ace9abefb72 7555929a6e983390a6d99b9fb21340bdea436104456f7345e6319e772f17fa82 47baf5064573771c80e48605222461043b10259e4b1d5ab00ee4c5109eaf0509 0 4fef6525cff944181de55e1156888fa0dd29361788b954996b257049c1df030f9319222ff4d5bff80c67f42e1c30eb5990db306329b006babffc92a0a373ee0d95bb38dfe42b9095c27d51a8d4ab6504f2b3a4e88912dc7d44636ed6dd1d7c081ae6b0f0c7ae51fbea62feb5c5598265532b4a6c361fc45346f02fb9fcdaee0bd094a11ba49e0a635affecc691e01515bdc139a5761e263e87cd26bbb4480a04535d7a04daa59b88e7b7772c450059531b7aad08f1e313792eb5f106ce52000a078ff032112aaba4b6b461b650be2607f562e1f00578e0043952cd49db32100e1401f313f1f56ee68795aeb76b51a09d8effb36343b73bdbaec36ee10aa6a909 +generate_ring_signature 389429172b85700ef011454e82461e30d9df22fd1db8366c615775683e19d8e0 999b6e454561a04399883e2349d36225d208c3426018c8a5140b5ed688601c1a 1 ae6e602587bb3d69854b8ddc46a38071e6987cd8dbd8e5317bc22ba20e568653 1202a2169995970dbfd88fd2d6bf35111e1a13e6b0f32b8bc93d3b0afd206804 0 d2af7e29bd8d3288524d7bac412c2959dc4e92bb892d571dc8c4e814e7648e049d6f48f5abfe2f9b1568533ecf245067b65bd67ee501374d150b0ff0b43e3c04 +generate_ring_signature c37605f12deb3cc9723bfbba6a865ebf42b6f55ce8f3d6f097771ab2b354f3b0 fae39afd0699fbd2a2ab9403bcde544420b66224cba89e6ef4bada7ec9f7ddf2 3 7f973eb742664756b20e8dfe86e1e12a62ea6cce44e987474d3f0d5fd115da7e af79056ddd39d65eba37874cb91566c6ce0a60305380f8007535d2e7dfd7d8fe 720f9e325b8d682a17ec1e8c9d118535f2102e9e03b570f5cc74b50e8ee1d12c b57bfcf6db2519fcc43ca7650cf3248d8385e5cfa280d6d90dad4b2154e90b09 2 4452b9de98fc99dd355196ef6b6b8aa9a26b5c59fbed448a1a707d7f2fd94703631477ba215bedb1a9aedaf0f0ea6a8d187ccaa3394394599da419e914822903704dcfbbb267b0b11bf370666c3cd3e085fbe36af49e6c108cfb729635a4b306399a12a1ef3fd6669961ccff82ae74bdb2d35e6dcff068c2646c78847e69e60403c6abfe66b905581659e8ea71b1c43b490783f28b8aadfc83145d5d38d7190e453394ceab615f2873151441fc0ef3ce963aff9446eaa8e34e609d8648ee2b02 +generate_ring_signature 37671a1d249e1788e7c6193b699c5e54f6be1ca35714a3a3e4bb5f45572c01d2 e0e86972cdf25612d13ee325998e27afe1f5ca20cc558021bfeee6b8437062d7 14 f41482621e6d7291ee1837f511206f285589e82270c54f3528e9188dc39cf6f2 ba41a5e2f314fc05a8f86861c2e3a05318556814c9d209e4363e363476591f6c da784f4125cab4638fa28b78a7e1040b68b0f4b782bc53403d9b311d1c8418ee 1c765f10d5c8315d648a1ffe3d3c81bfdfa6ffd0e32935b3f4e63f3f563afbc6 107c411025027e2d443aef21a7587dee87fcd8d0201a679dbfdaf4f2ab19a2a0 67d5eda8542bd0951035449c08bae062f28a7eae03acbd4a85c70e98321df6f0 90ea7de0f1638302ba6017957756f60b85de1f18d415b613c0c7c9d1fee2b020 714f410e3f73569ba9dbb4b8f973b1432cd573d33d24ef35ae7cd2f7ad385cee f2c0ee9553a23167d0e49f274abc2dd3976c1cfb91ec2254c8c88477f46ab46a fd5de7201cc934f74b307d5f5f63758e633e9d60fb9d3eaee47f2fd2856fe9d8 086925bfc05dcc018b7b0494d8743328f5dc9b7d6078c3db4f03e2d8be5e2aca 8fd012389212df1806ac761c9a70f1e358870177b639ba7431cf708279e1b77c ae9c72de597032207f452e71b0f4885a4ec933c9908068b41e9a1a5d08eddef6 668fd60e30f1bdeb678c538fb5d94a1836b1e038f20409c6608f857dd3c47bcf 1a128edd23b4090c4eb20ad7ed850a3bbfdbb4bf0ec91066d34d3b8d90433b00 4 145e0ca5bf43956d33a228e877ed4f5fdeb3a618bed80c5e67c12f59c3c9c0008de90e6b9e3444ed6b027d8bf42798002622eff383220f1bb884fe3552040c0c6687e2bf0a5da43ece1eed36784a3e31a7c6e8e57643b4e84f7896e7104468041185477047411afbd7c0aa103b812ce0fe91b8e141c0b9812bf0400275fcaf0a8cbfa14f2758539eb3c62041cb9c511eaee8feb4581e0c31b1f56791986c1e09cae2c1ab6a4158e83016d29542da36fc7fc15fcb13285badeb45b462c231f10513667d398826b6910dfe0d65e57da0eb687a31893228f85a81b61a08e77af30aa24302fe34a3cf2b4c200209c63737209619bcee377a31f436036767d0cafc08adf3fdb638127149f4f0fb68cb23593f42de7119449047a436e76757e610f10a297fa47f77f6a196e67ace0616283390e4468587874bf4729d37f3a7eef2e207bf069190607b448d0e948a18cd75bc5028b8f8fd3d8500fa70c5aed87ecae003dcbb694ab60cae0e074b98ff0631059f01df0b83ce70a12d2178d4c3e31b8001e10772fc6cc5da07abb8ade5c72d25307a7edafcada5745637398666e0538c0243ccab54690242751b84a34f0f7cbf6793eb7c1978d57f2c4648eda51929040ca1dc2e63351b213ba5b9242d1bb82fe5ff347629f73dd7e846533790de4a0c0ff0061c9ff5f3962ab4fcf50329c457bdca5e1fcc102da89869b98d4ca0661701a51576c8b5939c98a57896052f84e4158ca39d8456a3d6ef78ec751a910ae70a1ee20227067149ed052e4add5edb294875b5b8a27206ecc2036df19cd42160028b23d984d1900112711083a1465576eff6b0bdb8184479079ddadf3ba6da74058118583787c7994d247562a67ecd8e54e316890cddc8698562a909d74e48390d4bdc3489613e9b6a5e48006163f1b0d8f93c4baabb54d3b19e557f93580a1f00d1d9999d7f6c510a267758ea5f4e5155d364c47ad0405589272c5ce3b0af8908b129947c63c6de0658084111b8e82daa500f2c0d487f4e46f7780699d9be4806e77798a83d366511797b48294a314ec53345db6e10ba721cb3070c2d3b17e90b31ff22e89ce20bee3e7f0b665b3cc60a8ed58a413b13b7368da5ff89b32ab104612f092203d286f9e8339a998035946b6a165f9182a6eb66d2f7478abe8b660eba8a3cb19164ce0f43cb350b3547bea194fd120bd5110a100fe6d9738207ee0a2d8447a7a9de8187e2b303003a246b0a7697e4bc3e3ab082601b9edf190bf40d +generate_ring_signature abd653f7ad7fd63df48ac6a7e0192cd459c65a8240f9d2cea3676a8bf574d3a3 4ec5408a2203919766e99425df38cf93d465ee4e7179d4140f743b780950f7ff 127 f7cc7ad1d5529686cb49d9a39db137ad1c4c480bad36c87e9874db399df6e2cc e5603615a39caf26768f8f006d8e7fbf75559d8f20f1d668603021cbf5b06ede 35c398f97a395727bb667e2d1b2e4ee561ade6cdce28decb955ea40e3dc81b19 39f7d4ce324bfa1d831a3ac2a26784f4d9858a1a7ee913f0d753560f0fa205c7 3a70187619d98252083118eeb6c43d9f23a441d081c06da5cf1538ae2f514b46 324c0c07fbbec5cf493db7a55f4f2944a88d66fa29495c17d2ddd7beb799a981 8246ceac0bfbc5c3bf76bf1e188c6edfcbe7e8a8b92c0930a0e9f6d7d9bc4efd 46510f6fe33f0246f667ecfac5e9d01e62f9a675b3c9b43267f7ac6e9e055eaa f0531b6c747fa76dba4a033571b5adc2affec1d8ee7c3172aa25a35643118ac6 c3080d681c17a1a9294552e508fbc3a0183a17a1e2708fe32552580a44ea4cd8 dc56dfdce49cdb9221d288b78779a6bd84c4cf8e3c5d7dffb0c5ad507715f174 24b46cc382e88800f74d1eb5cd8f81cf60002b5ee67fdb2f7fe69aa3f921bfe5 28672e60cb393cd812809e8092b639c73e81cc2e0f8867bb2f136cde06c4876f e1ade5706d9f09a98f177a310cd7b8cda1bb72141283205abd27a1db228d8778 be543df678f6169184ce2ad48e7830679ccccfc52a63f8feab3d5ee79f0c1054 b464788b8d9c73bfc942547d9a2726e2c63106f18e322f9b690efc813c68afb5 4fa40c9e5d07a7143203d40e401198a589eb8751b4dda6bc8cd1681586150590 ae63e7c95e21ee618a4bf5f51a9bb1349a56e13045c1ffa54d51fa732dc88a98 788277e0c0c724a631417c4caa078aadd6dd7ccce6a2dd3b6126490f9cb29b03 0e7f64e648f936b92ba48d50f642d4c59bb972837a8d0c698ebd3f6e8d834756 8c9b5957c1c93c492cf3ec80493c9a2ca5c8a296b47c45a6ece5a9c1829249a0 8fba8d91bec11803d4c5762227b2a87248ba4f468c2ab1b4b99d37f605b6c942 25d297ff24cce2c8763580a2cac0775cd77a4625f877b6ac39bf8b8ca06eb121 983429fa4e9308edf662f138a32bb5b5d667fbad795482bba974751c1cddb922 a4bf3f834a9f55d2667a98958618e667207557636d212af92a5f6334c812f8a7 f35b326077681c3290f31fe27fc154716e58b7c9913a77cced12a56d1c492a9f 323c052da3cc1228ee8c14a16ad1c955df440e58cb9811673f49acadcd111954 f01661bdeab726471018f51d247c872624fae8e5cbf34071c49a269957756e0c b67dcde3c5613b2b3b599264f06050fc144b0beae6e234830548b6af5a4ccdf8 38af053d20c292fa28d084721700d138b911430c73f397ad67cb878e115b2beb 27c40d8f771f20559e775713e71ae041abe5e1814e6631ef3eee841539e2d262 7a3a321751c2b1e32dd96af7d33d60184d8d42aedcede75d4e22c9572771d6c0 166a8a31964185aab43c20927b122f4457005786e3d8594cc5512ff88f6778fc 37d33c370f64d5c21fcd80739846a39fad9eba9803afd1e3c3db6c933f600845 68ec83d3d23e6054492ea161ac9fffe1a42ca54f28038bb1c42d3b7e29fd333d 5384f0857de1ed5fa5db5755828eb4e117465dde04a15a90215612782e29f4c6 f93dfef70ec9bced9b7830d6dbce44c1aa4eb671d5ebb3b815d654224db90f1c e386cfd691fd2c855bf8a5c86ccf228af6d9481e38acf5cfbaa9d8accdb6f740 9380536decd8199c51bb9cfeccae5b75d423f18e1de0651bf9419cb9b484084b 4689cb44017f37ef8ef63fe68d4ad26018e7beaf3486bdab9c6c3c459c3e7835 2baa6a00de237bf2bb2fcd3d106601e57f33c27a1214ebb317f53f20052bcd73 c874b88ba9c5e2ce74996d132be4879f2a589b21efc30314e80d0cfade1958bd f1485b76e02c7e9b402c577182a4a941fd4c60618c6f92f7ece4f1f03caf723c fbd10d5ffeacac15e16cefc049ae124ee6dec10c66b6f5b62bf21d8aa41acad2 f48ca5d7ac83ea3e8d9adde2745fd6f50fa7639824db2b311bab61adbcce559d 0d676c1b31a9de877928419723a5eba5d37b2378d2b3d9e846b6cdc865cf6f6e b45daf0605d323651751912084602a122b3a39611bff1cdc36fd74d882e17201 0ef240390d83a22f5e7b9685545e94434d7f667141e55e9344d50753986d4a2d 138d36e66f4cb547e3d2e2e32856a10f04877cc45a4d94d2853c7ccb9c29a05d 3c616b6f7303de221b0eab85a33ce48ee0fb91b125b69c2bc13bde24316fb146 c808d1403d310e1128b18554da2a8dff773e7711104495ae2d4c4cef80c4adef f00a9429229a6c135aeee20efa63cfadc5cb264f965d5bb99c2622283688953c 9f763318111c6e949abe452fc29319e2c0cd855ef13973355a458a3b7abfa5cd addc8266481e686f0120ac9537d03348a12823ba9ad2064c8fd3c056af87d9c2 9e3163d748d6fea21146280df9c2b01c6b46300a40d5d313749982b94caf43b6 09daab1f1bcb2f17d13c0ce3024631c834b845ffc29656cac32decbdceb36dbf 966e9351376dd899b4b8dbcae80f03764a7f67ee0d1c883ef1ecdf62af6a4c70 526b72a160bda748d06fcba2acc635f2370c642defd1c19280ce29111912adad aa37714f944dc1ebb4a5bff29adde7ba2b3bcf1298930cce423ec8bb71b46301 7cb9588e9e2a967a8a5a1486864106a667a277e28f65db460b3086772f06a97e 94fb2fa586d2e0850db9c6d30b4cdabc2f2f12f59bd1c9536fab74d9766f134c 1c466c9515e20c18a56bfdd03bb7478c965a7d12d702d7d4957a63a560d10266 609ef0ebd972a504c818929e4b680aa2d3af312353eb0f8c886fce2c2ca18434 102793b591bdf4a26d4277b57abb796e5066edfc167aea07ffa014cb58960e75 4a94b3f8577cbcaec6b0dbee10ff8f66320707497543846b19aec8f922b4293b 6697ad22d8ce84fdb5fc90cc5af87d5d2d962de46cb53ca843e9938681484d68 18457de093c4a00394f250ae8db6cf086e33f6d5d14dcb3040efb86b3a3f0b04 aa9742d9efbda738d62ab7625bbabcf258ce112757d0278d160b15936abf3cf1 76bc78c14142bd24d386b391e510a448084640fee6d5c89e78912563a30c6082 5a31d2c3cee04912b6bdee1af63d791bbbb9895c97d40f64268d429c29142985 575e2c99943ee27d8962991068c135d934f8d7189ec84114dec86da9f8c86d7b 653841686d1dd0025aa32fc36e2ec002f602d6063433722d32b438d5e2d75319 522bc0507407007529b25d2eec729a59c0f60e98373a0f539aef20df7f53ea69 67feb74336641ee284e032ecba89e02428d2829af28d12b0e5bd9376a60be00f 3c865f1ca2bab0db4eff5eb9e4108ac90e1b33362d43910ed423cc670035f039 d6e4c9d3d9d3d99471e5973327d308fe8faf93727fabfbb0f748c4fc9fba82d6 d70a8e2810c33e4f5ce14666e6282b71db8ba4b4f25984761a61bf21a80098e2 20202ef0bd6bf3faa3dd42b314b620e15fa03cf525b7fafbce8b1f620c86bfba 8576732069b9c355cf922f86b90041baf4d4d44f79055afdb35a958f8ad9fcc8 5844694e707777f2f9499d4bdf209fafaf286fde9040b51657217add3e345bd9 ebbe61e0c6be3cee2b8f2825806423b8368a7f649a0c842fe537873674061d8a eb676ad1281e502de98d3e9c4732a095ad28db45c164ce7893547fe6d776cbb3 ee6ae2f3a4e2c55c347644afd43a8e3ba646259a4939ca5d0acba778d05249bb 377de8f232e2702372e38e93858ae04ee8729ff65a76fefd8b961e64c4eba497 a0ed9e2d5ff4c1c414edb066792f9026692e49855bd6f0c3d69a1ac2413feb9e 1f6c215399aec9b4d8bf289d372c2467f560896aac9b941d3e3c0646c4611f79 a98c0268b55e338c26e4494a4c8a8022d9653647103a0f1bcf91dcd8b3ccffe2 7ee898c856b5fdcbf8003dee310084f8e5d7553febd3d4d9a4dae9728ce7d8f6 e549734c11a2460d6a99322b248dc590074d36a74635666c0167f4d6455a9b10 801df1a8e2aa0edf9d00861bd977b0e4f5d369c182765852539e4eb98d58d9d1 6b17009bc4da1114f1c40a128a5f9238a5ff65e43b0e3ea6be474245c63be927 86a0be9a8e802b0a83eb58fb288e8eb0169085599fabe73df43d98dd538e4fe3 b52cc90b3082ea8bb1c16f4398fa9852f1d7bb3984701dcc59403ed0ea11756c 2e093e60b05a8dffaab61ee017987832247f2980afac47bdf83cf4d4c9b09fdb 23ccba870003d977788fb87907888460551f208dec112af68b493e339324fba9 4336845a60783d068c0693181b155ff8a927e2ade96175842294c5269bba5fc0 885cd6d8605166246c5ab4add221064ac3307ad12cf0d76961527722baff5b45 3640a825842e15ab7fdbd183861ccde121bd494d55dec192307f6e26d7257d42 51e8532b10c76386fa77df1f0972770a67b83d877946387075f159f58814e449 775cba5f1da6c8d6ec21a32821189f46c4acbf8248b236b1e14ae4550607ae54 6a4853aff074835c48ac5fc3288f185e2ec3888ac41ce5fdc6d7b50abfad9f66 73789c6ec8839b4003a2045a47c9602f75a55fd2632f4c1e9361f939178ec98b a548db9423100cba74cacb67611f617ba18b0b65d29fd55ccab9f81a0613f653 e89c5116940301a8cbab6c88056e479ef6ab6605b0ca9cbdffda08dfafeb697e 77ca3397a46092795d90efa06d1bd62da05986b7fb733ef666fd387e39dccb91 b16e1b9bce92e7e72834af0964871ff655d94223f297e2a916bc054b0c4f8a73 b53dc02837033e165910df5ba952c0ba9c3afeef594666dc0994bc8cef844cef 16e983fa02cf9303daa709d001566d3683db349cbca4ecc9677f7da6a6a873f9 dd6a59c284336c7248af37f73cd62638b4a1126028f3088f7809093bb9f40c43 ccebd0ec548dfe03c8576949bff066db53c08d2ea96fb7bc3eaa2e35bc4e549b bad4168d208766a192af7fbeb089e80fcf3ba50783063be866b2afe7f2bb392e d45a233a18f241b0ebc2e27342eb7d059257a766409c5471a725cb13c4331ae4 99dfd92c18d6d113ade3042702cbbd6bb9a79c0c7aa934fcba3382c31dbd7e7e 62ff7d2b14a161f835ba981bf2d97470a2df1438e2c1252441555a898e1e0aa7 ae772f8ce1d252f53aebb7307c17c4e0e7d62f419acc3a5ef596ac80f5f95d49 95abfd3722194601a8532044be8d20e29d027d0e2f4055bfcb51c000439dbfe8 3ea674df981be77af3101ee05efbada58aa84c552b85528c9e96137b0b317f9a fce584e406a2166a6e4bc7576e45ef838e4ce27d2065a45a19320a7baf163f01 0def1fecee4b5330a6488df6f248df22ba92af84bea002746a0b647e50941c07 d692409668548677cd700cda6f35836b205eec4de848518b6a883dd1270839ae 7e1d912ebaaa566002057b1a6a174539ea9029cbd86342a8aa3ffc748a36da7b c281754f3176f07b395486b21e69fe80cbd853438f37a25af70b8becfab39fc5 d0accbde0cfb2474ea79917c09a5c6948393d625f29affecf51bdc3578e93e67 0a299a649e18631ec310b45ee09d737eda2cd32e6ba100ed3bf0984ff88b18f5 e27bee21a8a3745f69a8bb71b60907892f43bdb270af1d4e682a28112c80e4c1 d8f5963afb20f917aaad9e0d0f329df6daa524c0c4d80627c537eaeb7c6eb783 0828b7115e8631dcaf475cebb907e6aac977d9938b7739617e480846e8b0833f 4c50e16ebc84e90f0d414526b053d3db85e9c0f1273217537805d9d7fc03d001 82 fd084c664397d05a644a5445e4619ab71b75c8878be8b638f6a0f4d09e81f70887323fd93acb4b0584e3ab1aba68655e90427c9a1a2694ecd77a80d6071a8f0e811fdef1faf5a2cd2809eeaea033e3f918fd51157d0538d61a22571313ed560a33971875c62813364e8aa6be1fcbfdb3cf8e261994ff2f3916ee0ec7ac9ac70dcd70a95bddb71fd57da3c4e3d22d657b8ba8b97017d531c64817b6c659f51309bc5fb75e2223f5becc6c1addec9bd113e8b662fb66a66e8e7ada31c6529c4508b00fb5794c7086b8b9fd719af69074d01f3329ccebecef1479ffbf02abb6860b1c6b4af6bdbb7dee15c2e5e824f1a3d8a19fc8e8fdbf17cb541ee6c8edc6fc0972034bfcdcd8e0cf6568c5dd8815f3821d254a8fdac4c4c9f59075fff2b3fe02f371efc09679bde59822a4d17f37383bb528fb0722018ed742823aff2944830b818312cd8553bac764c2aca009f760d68a45c0e9b6e8ad23cbda753edadf030ed290d87a9d7d91c864655460fe6b91f412f51263baad7a3fb9cc564556cfd403d41395a65b03e13a2a5a0d318f728c494548e83f0d603ef6eba9f0b30965f8021d9c1559dd557050df1aa1a2b7e2c2bacf2aafd842645871d058e273d4802e01e5af08974742816515cf26a531e17834ec7e774c7dd42b1b7e327c0f1617f70a9e5aad969b628dd5549c859d76f097e0b047a025beefd8f12ca947df02c6070ea06f65a7253a736ce1056ccb5e3ff713e451a85f97ce54185b54019708b8930ac2ac265b7559df6d5b13354b015c967c0227816e7a881cfe073f2d30d72b2901b3a82df48bc56331241e096f22957609358ae75b9cb5b2be7396cd960b2541084953ce2e87f4f7deebdb9d415a050e8f891e8059bd9c923d861b4c479386b4012c0f25b5c00c54989d377d4560ee99d973e57f90009766834f0765768e0f480f414f29416dd53d1da19c27cb4b18fa8e6c0af16d34e787a463e7fee3118ca90377b1a51daae573b5073d0ef6af05640f78317823f11be982016e042905da000d598ed64481bd862d689b25815e27a97674cb25f4cabe85803be0239bc1b2b909828417a1cbb97af967a3245657318f5c73cdc436738734bb9c0954a63879330f26551a552f0d9bd2fc9ef55778df4f610fa08297103a2163dfbe15486e908a05de50591c9e5c000e3c89e45d37dca7fb7d81e42d213b0f8ca6f1b57329f7390cb92efe1bda555d83f484ec9ba003df8e94e16a58b88de6b475362d28e6c2e305e9cbd35fbde879713d5f3185ba07f460f0ba71977fae4e1e8a78033da53bda062288073960b02eda2a5188b919342da3947017523a52ab1a4da5b421ea726e036c75a5801a209bfc18bc4e010076e51f68f557c14e4f41cfaa25a163bb4916034a0904e7d2f01f9203fe6e89c0a90158fc1cc11d9eec28f931916cd4e906ac09caf1c454d72a44f52e141d3a7448da808061b59c2b7f7fae9cb96f762377ad085994f63970df0559ad8f8a84ef17ff34d3646a87641935fe667459b8744a3f081238a79b3e399de8560f4f7f86e29ccb2285b5e66119ce55df50b8d86c926a01f8d2fcaee416919827b2fce6b6193d912d282b35d4176224da640ec70f61c406af8dc514634f852cd5364cc625b9b3bc6158a1ab8281030b5c8555f85cef4f0bf32ad788cc4e7bb0d506a8e612e439854ff7e8725779d89041806cd73596ed0a29fcc805e9a15aad6b8595f2c74b48191fd71996460563df11a8b16a6d047b096d6eb0dcf97c901246b2405d6e081aef854ee7513886e9ad523c8e9876f03c0da84e4da9a01b4a577168ea293f6cdc8da22637d5dcb9f33e3bbfce6fb42cab0bcf20181635163dae25f47754e7d45b246bc422ab9726594cfbbf9a15b1b04a006fc84ada32d366fbde8a5c3a2275ad295a5dee6b9e69195f04f197c817c1470a4544d9183502d01ba36abd8e90208131c4957cb08bb7994aa66a61caa798940e1f30dabf6a797301bcdfb04b9ebdbb6bf2289646278e90fb185a2700ba1d8403eb3404002393c1530f63991f175afc675a20cd4402ec1a1bada9e6e4853d5f068300314303312a498fc5a2eed1f5257b5d9425da7a40ba93283fed77766b20069453839299fec4eda12df847453a20f26d2c614e39c8c0d2f36dc08af23c470d0805c49a1a04a71fd0eecb1c1a39f95003892f1101daa46738247362efb94a06bfa2a610e52f7e798b3a98d0953f76cd8b27a58e492b1e78aa64abf30a316307292a39812a6a3206e8bbf7787d4a5cd42e60e9d0bf59e949c058f954efcb57040ccdabf5ff5244083e4074156bfed2640b75fc694b3e1d17f52ee37512d0e20802cdaad46c3d7fa436d6d8b6323566b6cba14a504983eaa6d0fcf0dddb53ab00ea2f5c7269b6a8b5796b55566c51de992166ecfbda52e138e7acf1dda84dff050cf4c6e9ec192d9d774d7d6f51491b676e8afa592e9a9dc52586d0bd7686f302695188350e3620e559ecae000c698292d7e81ec8bad50239c0c0c8863a85c00d286115c7de5139ccb1c889e2a5e6235bea499c04e5ec369e0e761e2683d5b8060036916866dea40d1860c5f6ce5980e8dab61aaa406b1fac146300847a089806d91be7394c54312dcb6bf0e218d88bab339298d8c69f6ee1ac1b24614784bd01c387dbfdfbb056e35a5fbd387a6a7f9ab5b2c24aab2732e4f25dec1d3f31fd03aa358c1a72587296086743bcef616d05fbb25292c2d3cd3a9da32b2db6a1700986338e5c280c660724497eb0f0751b42ff55f2a2fce5e6a93ef68d348e20f40386aaa3dde23a7936a74a47b632f8ac89bb7f32a3279d00022932f9c0ff32d707cc91c527a5c507cae8b4c904eac893879e9a09854f1688c7143fe688a35ef8091857a0ca007123d5c69efc6de8d43ea3e477c9af18512403ad5a426533e89f0abfc914f8a2dd6a54da70eaba6ee9440639458ab12234aab3e44ef953419b6c0460474681609cca8a841ba607c2ea91fd20976e421a2d340085680bbaac63350e02f48fd6a8c6799218416f698f13ba3e14ca3115aa96abb4b7e89f000115180d9584c1480b2616b9e7ec0d37c2eaf7eb0a2ba7e838de84281aa980bf67e60804f4955648d75dd6511642fd1ff772230bdb65f8e755f719789d1701c30360bf02e20b60e20b26f7208ded3bcf7776075d97462e268448db8adf1bbc649acb9a0df1a23132dc981fb0b897f2c93ed635311de94829f024a7e8060cc74714ca010ff8ae0413cf0f4a378bfd07323e318ad186f7bc25a833c5ed36d3209032d9170c1cc3a5f7953fc3e8edefbfa835258e322967ccb0f8241034fa6a36b93d3e5e0a7270c01c6dd4a3d576d464dc368c41e96ef686d31d846365e18b0822ee7afa084d4c276bf832f306d69fdefdc419dc4239b94019e8d108543f4668078050820ba13f469fdf41b088325fe90e1eedc2c03158fd8cc324feceb27aa745b7bca70eabb4cffe24e0b5fa2814e7f0b625eb0f5d4a005d7cd7528b9cb007af74917e0f20d1d9d2a1003962d3a6c9e33d1e36d15e81a26b8b540b35c944774a5109f7037e28452ade490c56e08c14e7d9f481ffb49f7146dff13b2e48533e54deb6040a8e710cce12434b5d11e4f7abdc7963528f42741b6b7a52bc1eaf81d0d6b833084eb864c30a01c60fbe36c4bb90410e0915c121386c735a7b59d5eabb350e0403b7489d204d5bfe8be85e75436566607c8ecd0bc8bc53cc41890d7b20b1db950982aee4933865a304aec8c81a83e49bf6a1330d0b0beffb133add63fcd9ecc400a2719348f1000cb9b296ed33ea306dc9fe1b5e639c689b9959640b70b47d9906198c4e3eba23cfb7f2fa45c9e5cd4d7b163aac12b139658795274d33a7f8e90281f78b40762225e68cc880f4434890df6c44020027325a8266ec379c984d8f09cf5319b419fc2bdbc518abe7740236853e691540a85717f061a218821f235e09936e427dcb532fcc9a9708c569587b7701652622ede9bb16efc9820e82cc2804d976a866ac237d4955f39e27c3f0cff435173e9fbd778237b64460e8d502dd013c97b8b863b888b40ec9dc946d2e58ffc8e554b0f4459c772962387d416c6405ecd6a9b167198aa5bf4e92075f00a93fc33905846d50182a5500253c9d93750d8d72ea9d2eef4b12a570ce1ae838dc902693efedb9c8deba1a24e4ff43f79906983b3b062563a6b359eb8ccca0eba1767eee2fb3a66642d8fd058d47c9b42301ce5d9ca6db48b8929e222b81b2faab5a428cc8b8f477e1e464ad62998173240a03795ae90f21c6dfd19bbc9676ff9bf07d97dedd957fb71b96c4eef3c2b3a50bed78ad13967b339f1565f682da373ed3496d82be68be00e59c81e495cb089501621e2e2675a2a2d2f335808ea4cdc236823cd6a3868de639d5869d18a34fb307d9ac341f8360e85fc130bc6b8755fe475c9ac6c88854d7f2a33298c2d9892b043d1d66008622f34065e4d837c2444356fadd2e26ece01a6259f9b6e0c4e1010033ffb401f4056724a07769565531a0a6cbd73f66bff3ebad1cd6431d33ddc90cd904696c52c71178dde83a27601fd186916d781a44f552c957ef234b11378005e293310e3194c0ae6e0dfb764085f9a2372da945e01b72bce7033238e15cf20f62c4c9134b9187de1c5a263f542f238328842b4e126972e6a3886385582d980306e07ea52c75618229ca83279865fe5e5a1d611f2efd285deb8480033ba8170fed74e9ead22c04d1412bfd610bd320369105bca72a00b4bedbadd16a50d58c07c84018e0da506ec11ef232079fd2f9ac8d62bf4d875f2dc8bfe62dad52c7a70bc7d6b6c7eb6160a6d069c3c596a33d5647a14b5d1461b41c550d74a9744da90b783030dd3c2d2f904261caa44b26064b223e071c99ea2b5439edc42521f1ed0d52c7beb8027334a223af2d5e2055c1c6b9eb43c75389ec246b82835677d6970e121646e85f7401e30bc65266ea2164eb6d8534ab3827a9360a8848344ea27c048aec4cdd1a1719ff4cf8075ba4f4c3cc522385e319157f444a00ea63d16a470ab0fa44153fa0d211371acfd5c28d85470ede784da43ab32e79e335176ecff101968e9e0d77e45f9efd4d54368c33773adf9f189a0d4b80a2dbff98b1f67b5404aaeb17d533d9e0957adaec0e8a3c8a34b168d437485c9478e7c4b19c51e6810c86497f36d454de4d95413c6d02efe3fe638c65b4c5204660f7366f2358ef7202b49feacf535dffd2090db55a1f3351825d94b528db11b4f681bfa7b3df42f80d4502f7e864021ba6707cadbee6746e0b2641ee0692098ab45e509b37d795550e0c3effffc44daa7227b6b708a3d628498cbfcfe13eb0549e098de5ac9ed9d10f01a3877be157ba860ed9001ad4a68b2cc035d2c2234810225c57ab774bb1f006fd438ba034cf055e278b86cf584109f85854ffba9de710b68c3f835de3ca1a0b9aed77ae64f4d752fcaf489036d5cedff31036a40f3b4f16304c6a31b4b0d80c77b7b5ba7f8656556a21a856538cfe251baf3a5dd820dfb2c1fb453f0caaec020e0dc0fadd1683b92eccaff087dc9fc6977b6f639ed2eed120e6ecdcf2880c050296865c9cd088ee84bd52917fdba4bddee173346df948cdc89c64a4b861d5084559666c6ff130422d0caf43db44c3427a4d5657d4226ec51158b690ec6cd50b6ff6a016dc880a687a10f20fcb2057317faac6506dee3f906b5fe32b8b416c0fde397c8750a61388c798b2641d09f0bfacf8a071bd0e32db64458464967fe101a3cb5bae64b48558e1bcb6d01517915de66c140f287ad79c39a957b20ba6f30fc36303c1cffe0f37606eea932732a7cce7d0c8a3e7f56cd254c429f8634f730d850f7f706f8e08531a4252984012c7cbcf51e6025b095a9872e4aa4fefe187032652c9a6d4088ce17470bf650649691b980533e671301cf7a5ddf4dacd2c3c0bb972445be569528ac53f5bb3e0b426af8ae8fbc2c1b0ff626d7670085fc75a098a5c7d5cfead3ab28a57ef6ecd3aea2b66c79b6bee959288a9f6e3967a06010070e3433961e33ad162ea260dc5235cb51233e52ffb770dc922b361b47d80e6073c1c5cccb26c0a4e5d7af61ba1d6ea820cf3859595c3d994f16fecf1826eb90b23a191ab80ed8f6225282ca112f6518649916fcfef9254d542e30ef2d76b1800361d6fb6a9c559096314875aec90b1baec12d4bd8e8a5eafe2902ae146396404bb7523b81d55d59ea7cd196065b89ca9256f34c0878048bc7baa53763fb07b066f59bd9397a9ddafb4986fb5bdb5c6a68b52ee9d88412f506917a69d7a098303de15e1349801e828be2f3d46cfc51f4acc60d3a56ebf7690f6ec6e62b97be202922c4ee870906dec7a7d81a7575f62309d191979eaee2dd8868e338a17b18908ac26cef563b488c775efb792bcfe501898e4b1081f5d8168f43851ad7571800cbcb790963072d28accef73fd99da11a180a5e73c3b136e088dd3109a87e9170cfa181cb228d01588467846faf834fa8caecb758f39910d8e96c21432f2d61901560d6084e30073bb63008b25323457828048a351e39d23577ba982c29dc2c9084dd3de94dd6fd57d3713969b059398bf7ed6f3088688424e03bf0f5ce056110dbf84cb9eef5996e1a2a934a158c23a8bf009fa8ec1e6463ffd67db8628bd8b0e997f21300fc9aed4008581b1d67e2a5afe9742dc2e4179cdcb6df9701af3fb067a801c702a073db4cdadb8e9b5b64988306b1de13744f77b4ac6e71477e2da0ba28007220cd9f8b83c811b86f8ee31b9f8ec9decfee25ec0cec47465978c8f0035a90e7e02cf8ad1ddcc3e41af3f90a78b0f5867a3ffb620aa412217dc56360621b5dad0cf8413adfd47202e83410edaeeec32615e333fd394ec754bfb694a0642d86ccc9a0d98b0d9495f150086f5fc5f20dc09b734aa640faaf2f6b6247a0ef18ab7835892733f1716de94ebfda388a9390eef1f9338238a131aef374ae00df939552ef1075de5a600f917b0f13e69186a075629cee5a3ebd4da6081166908330a6288f1a53ce312275226f5aa382168f5ec6444ac8444048ce859df7e820b4f50d9ce8ef300012b227075e6e2a2cb818a3eec6c6d6a5dae8038ca3f9bf504267d9ce0c37e69498039124891027c11278fe22774524a0932ed77f99d8bac0afa523094a8d0ecbf6b3930ad084f7cbf5dfacaefab0e56c27a1becff63260208bc624befb99b5b5f3e63960941f370d70afd8d513552640978100cfc150b0601e584d598e632cd2fdc39ab91a0d5cd9cba480d6682eff3389a2d3e168eb76b0bcb2eadd8b48e43df853309d2ad2783c76e50e6e1710d48ff8446a7640073b7008de79c263d439f7caef45091d8321b4de087c8509032f5c05482c67da36bf20594edb584a927264069a1c31bd65ae81de03dff445acb8677feeda57c6a97b102ce3c43e8bdc8be3e366eafa21682583fee68b831b4344d9e4d55dc792a5be60d9cc25a374eb88386ed47152f1a6d67fd1be74d91a23693eb7aa6d5bbfcd8fb0ea587266278f698a6500c4c23fe8668d0827c05de246d2f0f59bb005a3933680d214d1bb3cb624b226c21e803ef2f69cd15bdea593ecd27a2ce550b1046eeb50d7f4e7fd5948dd78a109eac27a0ad76be9d25aa229dbc0469eeb57a170c9c6e0700d7414dac696c2e043877cafe52d3f3e396c64134b1dda19c85e8541a73540b45b068cb3644afebce94a24ab65888834476fae8d6830eb7416e09787a9b1000fa17e7d99b2a3ba5322bf100cba7285accb4076dbac9585908b044a925101c0dffe83e945403fdee3a8aa97f5acf6939e6f9893244e4459df32dab4ce705150e0fe137b81018cf05add94ff99d166b3dff07e9481bc7d36045985f5ea6a71d01e5dc8a06d65801c31352095ef736c453456700b51e5334f7697398ba1f9d450ae40892eefff78d676cc3b291aeba484d7c6f101747326401931a1fffd9adc00aa637ae784ad424e1b1a912f3a7267706d68370761f3fec379a2c4f1f2bcd3704db2d17db46ffb2bdfb82c0e6d6e742cb368b39a4e76f663d801004c31ecdec0da4eb79ceb526fe005ff8cbcb33a7cf3c8fbb6792fb5fa7d3878357221997d8034e126bfcd4884f8a08557637bfd2546b7cc55a3f76cc4b1f7ddeec632fef7c0a16c92bb4c42dd3cc93dd211f1e44e42ee309ab5f1be2b33872a3e46df8671a091cc70bd9db3be7248a4acc2c39193d448cc29d63be907a10041a25dc4a7dc508fcd71212c351039fb80200b7d031b0e098a3dfcb19627ef047ca56cc5ba21303a0279587c03a87cd1de30e44fb3d3baad883e7d5381d469669b19d38800f7e033e1e78dca43f7ef5b2e58a13cd9df531b79d6d8855eb711bdc52258a9ef810093ac7eaa4d6969380a2fb89250d204550544860aef20dde610f352e887d1d3402c07df9bb9fc3a582bdf0609cf76853581dfbc7c068ac8e47b9be82e7cfaa050f44438fb534c08e84bc3052e130e10f555b85ad1e191f180042920f9e4a55cf0e2a6403c5eb62502835dd66bdbefea6892bc4758d6c505dfe60756d276493ce0c1a4304b4bf614ddb558a841ab7c08db5b4a6d721b0009b03adcec52e79b90f03c14caa0ce55af33efa8cbd9cea826a4df383b0d5fdcf0702a640e99b41a077015b84d7415d461e0c3f1be93b544f5195f775968221df61b9d686f14c35552b0e8a1beaf68827c429e578b5b73a3c5e2c5f0882cd3502e93b51d960eabcf73107f030c1e9dda3ab056dce89f86a5b246edc40392bbc1384368fb7da7a988ae50d3a63dc437e03e96727f43337775dccba1e38c70af957b94290fa2985231f4d065582a14a05614ad207b9defcabc16628cc04afd522a1d7d3d8321ae9c6311a0541bc7af99c98196fddfe1eaee74c3b1c9cb033b77fbfbda3342059439fe9e9029801c15743af9341d3e49e55c4bbbdd818b1b126763bb899cd1c78c62d7e220ddd1231220465d7ab33e66168338a9939ce17d415877437531b3424b201c0d4065828734aab0415dbcc08f019b55f5b82215bfb81077e38831dadf4441ae0c504394b7e89836939ff2d594880612f3dbb076be9970bfc037c88eeacfd25a8c003873383523633818340e4783327cb55ee182e056535816c4fb1dff9a42997e308d09bd6d61cf01e6523c92b59400c0adbe6d45b0f9fb7a13871e5779981e94b044de402494b200fb31f51b1cd555f68797897412188036726f125ee0b64da13056d7e80484f5f1611479fc592033512ddf3d0469d104ac149b0968c3ca4849f04b2ee55599d73b29b911175b69e2acf20bdffaccd1ac62336a67755f107a4cf00b117924e05e5ad2ca073e9fa719003f6c0c325575d4b6b99c469284d1dbe54091d16dd8e654f02be709b8e6f58e9f90a58c5c53710ec4dc8dfc136abf38ef3033c1cbe049f2361fbc192a8a3467159b9a3403bc608592ffc1fbac9eea8148d043cce444bfa2716cdab74bbdf2e43918e20731ed1b6f2eea45676227552a69e0d5e32ae384626bea99ed6c775943850d9883730248c7fe65cc6e862e7093db9082168a910480bb246aa6c08e47ef9376eb9b6ea0b471a8da411eda068c79af5097d8928fd852770e8afc67936024f1eb489e610da2a816f5c4230082290104b0f023a2c810981c26d9576146d44ab5cffdc414a92e309a31a4cb78e2da6720a0e4eb3318e6f58b44716885449175d8fdb343ea1d96bc884505a4636d49214a00f3dab8c48730000c4037d77e15ecdf1153fddb97e3e14938b17858aff4b892b056d28fb3284f370b94fe9af7a319d333eb13196aa4055d529a855d9976048130c24203da087b5e91aa9df7290fc93892512cab93309e76020391ed56c0641df015c008a9dc2b95fc44f8cf0ac69be7c4603948f1cc4b5072d19cfaa966f8cf507bf9ba5604d6247d7b897d0f32a8fb035b7dfb5cf276e42fe0b7442d1f092a1049a541fdb1761bb9f54662e80b786c027da502c39146bfc5287b5abae1721b204b2b9af8a8c178937d6155fc88faf7f1404e91cb7e4d295d8a8287c21383366058f0306529dde88ab8a8c9b6ca3647e0a4539c9f479287bbea67c29fc352f5b0097fd382d4e0d68d10d85eab181c7a1f43dfb5709f5bae0adf30b245fcf25f407086822d2ec8cea0e72ed4fc1dd1615e5dd2b79b28d0e9a97914f24ddf85d930c3fd0335954ed4c83bcc9662297b6c32dbec08fc303ca208eea1790252c838d0bd3fe76c6a91165051a39d775c01d65c2d926bf6f250f6abaceff71ed884c0304fe05a755cc465b3bfb04afd6eecf0966db8cacd64953969ba2f688f5858a32045692d0b393cc68de8f9e014c9f8cfc82d18cdce0e2184345a4b3eb9f0992d80966b9551d5a8aa0866beab77120d7b18c3b8eb943f9a5bf79a5441983bcc3250d9a095ce348b263c67488719795c6a0261f0296d85b5bf9374040274da4ae320a5d50ad8f96ca0a5f644f837d55fc1f11ed451576ed2feb697814c5e72f48340d813e48912c75000b35cd14a0459e90b63ba21e2a7fc4f3cf69078931ecad0a0ae5fb72e7f4c4453ef29ae2133ac7c0aad70afad5707b28e657a76bd8daacad08f58c4382a374887182e8e167ba2c09a945ed23c3938a4e806026d53b01186508ebb44636a3a81c6d88974154bcb981544893275401958de595867d81b13f730ddc9446e1f18ece26e0ea789caa8e9725a4aaa277dee3be0d6d3cbd65bbef7c06c973dfaca004dadb831abca4aa30e7d318fd1dc05690242f880aa9949bceeb0d5bf0620ccefb0e50f709f99874abd55deb8432ecfbb91426d4eebb959ced4609ad0681d81c230df81f5719e8086acb122f1cacc1a2c679a2d27aac5acb26a909c986a83890a49b1bbbeb67f1aeb77208b00a201d70ecd60f3d5e51f87173410ab3442e056fb2845748e308daf5dd7b60aa6ea973784c08913d5e970f32e3160f65947585d6abc7034ebe1baa675487c236e718a0e4f92f586a7d415b46c52e05f46be003058d4fa734836c07b660024ddb827e0d81b7f836bb3deec6015eaa004d4808475ee9b1835c172801a0190cfe4b8ef3279e4ac3dca3a95f5b13884006c52169cc390a884c45c7fe6666ed9a068c90856c94ffc8cbac0530ef5e672e0637625cb8b9e2d40766485f8547cc4756e29fcb5c9dff0f0d6031d7d3014bba062682d76d6d6335a0abecfba8a82ba69b7b5a26a2816b8673967d8d56fa5b110c5a0d59a5981273aec80b7d020e55a448a7b7cee91dee0e78933cc6ee1f41090f8caa25915905e576aeaa3e8f2ea92cd989ec2e18787996f772e119703d80b40943abf8d7135ccde0324292c3b576014ed5289c6e3c7b5a77e8711c4433a3aa06e9f5719f2a7e09631a05a4ff817db2d0546c4ae6217810dda47e5f6309928405ea9ee251f0a32f4510db2329585ff35810babf02f3c7dfb6fc22d68f5540b008 +generate_ring_signature 1bd71e0dbcfead5409660f7e8c3127a3d0c42fabf9ad6c0d82d88016ea624ff1 df36b0898025fc214088fd247b1b2e2c49d8b7112158410e9c2bfe9922c43dd3 6 c2c9a12dbbd3c694aa2dedff6015a22fd8a849edf52bcc7bbf8a05cd53f6ff23 437bbaa4c47db3859620b779dd5d2a04962d006d16f9bd04a7a6593ba645794a 4a32f65c25000f76a5af3a41ba8bd88d0acecdf6aaa2c55688deeb75625e2de5 f3a5c02e272bf7d1028f201e33c3549631c89ba801b5ad1cc7981424cd1c7c25 ae2910331e8e8b26f7ab2075d3bb9608f666fbf0c4c71063c58c2bfaefd7c055 889845375f869b5bb75e58c169cb19db753ca9f558f806b47c160f1dfff52084 4cd9b90686b4bca0ae584a8c6aa7aedc6d22993c380e03c55abfa047978b4a0e 0 ca79682655c0b7f0e249ede6c8014abd78365d372348532c43faed60f3f47c00f687f1cb7be07f019bfcad498bab613ad11a843533eaaf372d94e98079e1b80817c00512526b92515e0600797a57c38998142709815c46e36315a77e6e689d0e3b8ac6d2bbb06f1a0a4a99c45dd4033b7ed8d04fa3b1e84f66ba63c73ba6a40e549b5384204930e89dcb0bd0f41a3ae7f937076fca2050a65b4e4b4319625c0cadb73a9f83389bebd8ebd89134c027cc197a55c29224de9e07a284f539fa1705db8da16b637f7264f3acfc0bf4005bdbf492b970d619ec7155492f8f904d2f05c0848a739fec2ca92543777cdc1dddd7d5b7d870f0ee8c2e1cdcfec75abdcd013523a1c5880ac9d7edc3732dc0206835b0a56a9200f6cefe8040c9aa0d44380b664ee8f4b84679550e782481c4a897e9ef91ce092cc93318fa74e2c0a31048068bc761f6310790597b44ca6002fffd55b413d2a710098843b3cda9254260c80a1f0ab50e81523e8ac6e85a8d39f7bf193129c7f261584ac4f14342c7ba39ce02 +generate_ring_signature e424f4b58872a89f8d5cba2367a5c518d6f33932e829f1b82ea361005fd789a7 3881cd8adb14d6d3486a135de75961ed9ed7cb92294019d81adb8eb07344173a 4 08af7a24d14e395c22d134f5db91bce9bbbd0e05625a0817e7925c7f5d3a288f a0833c919f066178070650518818c09a464418c0579ad6b6f834b377035dad02 72d51c7e3fd7f62b2c2e108749a71a52e59072f9fe9d9eb78a9bb7c7d04b5358 33f26e4db6b10c1ec6205159c9292d852a39d8d4eff9b34147f9021e15cd4021 b0d7f260e8c049f4773e7a7957656bdb3426b3ed2b77a92963e25351afbab80e 2 43ece5700864c385d093520a063053219629bcfffee6c2d16f1aca8f5cc35c01edbf3e94a71b4a4315653b12d9afbeef726beabf0f29b6b76d1321743832350036c7583ed471c8612970da5033e94d7e40b8ea94504f48b0d552f4e9548efe08b76eaeab49c551f6e4d318e1888bc33cdbe394d0214c41b6f2a9373544f39e0f14ef86df269209f745a1f9f8d3fbdc1bffb304c550117460b63f8b314e286408896992abbd0f10e3935688e03e7e2d835cb775a372426216a3ea6a1e4d4ca702f2d1cc1d885a31626a957b4be30ec2dfae693da2d24944d6b5cdbe3076751008c03cc94609c87875401da849432e482449ae53ebb44940966d4f65793069dc02 +generate_ring_signature 5bbe504919c3ec458ead546da6a26736d2502e6a05308cb5625c39d40c3b0c12 af979abd7a21ec14aec19f65b49717be0e48846576d34c27404b0df29997b81f 13 d151a6ab8f224c3b9b2bdb438d5fee09275d134d320af24552c67af777d396bf 5627dd6d295bc9bd10039aa49cd520ce164dfdb98b5586dcf38ede1cab9e41dd 1e7968c3440d4a9994dfd89fda5d7f399bd609d7d428562aad4956efddbe85ba 49058138f3cfa317adc8439d479aa62adc11ba92670252048020952d91a949e7 206246ed0a40f7d750ec28040df4d659ae116b1dd5863f4372eda67025952d13 d3c2e54b9ae6962ea49eca392655fbf8027346ac63dcc309a0899e62420dd273 2b13248ac56f9f3bc37b3d49b2898fd783668af84f8a9738e610931e59e66842 b76331e8fac5e727716cd2fa1b24a6c5703bcee81afcd923b5efa452b0d6a869 87f3a2689803f1d825b4b7d9591c4631e2319b9b9582666d23b15e738939a03c 83179f1ced3540b0293518d30fad1b29d8227da77f1a32a19132b638d72d6d8a 7d1ff46774fae090d9433060c2c38b3e0543d2f9291f469f4ac0d75d6b8e4f90 e293f3c438ee82c0bf1d5b7d0cf27f9daede67da84f44436e395aac9021c1d3d 49541a49b7d1df796b7def54c7b0f8fccfb1a6674680d18f67f5e7124bf0a8dd 579e68d5f338d7c7e0e07ac07e0e592c9dcd18b87291a19316e66e57513d690a 8 7fa23a5ebb603a1729a86e964e5febf65677d38e7de8ef3947c156608101dd0b867f4a9fd07e535a152f6db6ee3488bdf6245444c52d7682b146b3da79aef204344a97940018fbe3eda7a3f395c85a2ee989c3c86b206ae8f0a10232c2da4b0f9591a5d7eb40194f84d019e18dd626d367d7890f59b8aa7e2d4d8ff4fe284d0053c3b6f7c6b06b9bfcc4e51018a057961feedf48e18ae3b2b15148bee630460e78ffcc973ccb130e664cdd23fe7778c45bfff32dc96389e43d2baac6ed5479081199dee6b9c040c9de8e48bbdc5d9b5fe703d401d75ab92702f83fd3b7c54c0c4a7f5388c1dcef3e9605c9cc0166fa830695a6304383e3e2a17b233186e5680a55be3ed1d7912d6bd01afa7f4a4bc921f1d7bcfd5ad3ba48537d4361a5649808ab9371f126709020928a85fe94102f8508b1641922f5a5b8657bd2322fb7eb04b98cff5d4e0129f5b3e66213a42f42f50e45e414018ed5e2005722e7222f180fa2d4e4eceb08b7516322209a8fa61a533e7c327a542ca7ddd0eb0cc51b65dd07b468e2ec7be89f8d61d3216b4d533b69ab8bc7308d224708f7ec713ed89de90a5cbc132c5dfa27d4d253ef77afe3d2935284840d019ff78b6172eea4a8ca5909435e89e3fc34b6a35f9f017e2c91d0405fbe77b99df628be43cebf79361d9909469ddcf9e6729df07da7024731f0d6d1fc35ba29b0fc6e265cf8119801d6c90d13159994497724d9b873f75833cb3491c896275abdfcf2006587e1a21bfc6d0fd1933b1c1d2978d27d1bdad8774c709435c269cfa93bdba3345af27252070c0c29dc937dcba837e605950f9e441cf7dacecd515f8a3df4920d57559910dffd059f47828358ebb5cf25a78ea3af7248fc6f615641a23252ddeffef9f3eb96ea031f94ec7883d39ea6edcb6d63afd8efed2d39e17ac655b81ff63209cc456b3603fa4727205e613fe4f2e09761bd0e2e7fec4acca582a17ef208f250556ea930081adf925e36f15f031ed1a91ff880b33077d7dfb69d0a0dde81ff3bf8b265df087d8d8d3f76a993480a00dfa24d3baf594df68a136cb341c4cfb5fe057b413f09f0b81f66807d9e3a59732f29f5a18e2b6455a87cf0aceced2af694db8cc50e0ad4f34d48db994a8b5ba154ad100ae1bd85a365f68eef11abf89b3a57d9698308 +generate_ring_signature a0859f82b14dfa14725b605a1f66c4e7e3c5703096a3cfa833f996b5e105ea0d cc280d0af6534604494020baf8cb120bffdec0339aadcf45b3d97a2b7965d393 1 13f43d83ff833e7b6ed996c43f01724dde26aa6d0ff8bee55b7f2a7ae080c893 1693e87cf56c39b63aad39216be18df69feef1484ef89a9d20eccf59584e360f 0 6e8eec0112b3c9fda911937a840fe56f09087d0014a7aeccab40d190b30b930dc2086587ee4860f3bf59a326dd32d3065bc4ebfa5e217da809bf274921e06101 +generate_ring_signature 0b93af27e122fda8495915b5038a4135290d292040914c8322751c075859176c d874a4e8dbce217f1f0d503daa4d2833dd8457d2d29022c39b63c2ff18295462 1 fb104b44d767fe74de8cb1c133c2e1d253857eb003c6c63528d7cc67b3f7e49b f39fa6fd80c7a487e67ce834393545ccc91891b663b57ae879ce6ba4079d600a 0 e51e452b0feccd0f42add0a613e7da9e5ac7027b25cfcf7b3f795a1bea26a7085ea32714f6f8daba1d632709f678bdf01ba1d4f22a6b59415b93a91654d9f30c +generate_ring_signature 88ec571618126ea8a58e3d9d6d3415253a7a9e2a4833ab4c68869ccf369a1aa1 0fa962ae711149af59f3923efb7e275ecd525f065faddc47b94d5b77a1d058bd 3 147eef3259895073beefedcdbc2d0373150bb6dfdc255b9c58326fb443cf76cf 48b26ceede8691804ed3476374d36b2e820ee44c0792361a511080de5fab88f0 2798e56eff7a2f665c67a1b615e19834f2095580047490ed3998cfa1a5ea645b 55597215ee22059246d3b0ca241f9fbeea9ab39876dc981ff1fe7f70ea10cd0b 1 fab54c65e1111b735cfee5a90b76e429dc84206547a3a73d42ae322f39bf3d0529a8aae101f990028b54615d20b957556feec904aac2aa2bd2cdcc7064be2a09d98b1b6079fb0f5c22019518269f8ceacab202c0a6bbd9da4374a2bfe705ab03a0b3a41038132743114db4f9f55792fa3a71f94089a563ec707627f676ffb00bc54aefb383d4036d11f800c03404a0f0196929bdcc009b3ed3b05297a99c970ebf9322f5371c9f6009688ba1600d1789fea18c18a197e1a850a4c9f3df7a7a04 +generate_ring_signature 7d0e728c17d84fa5a6380b5d42c2874053f090ca9619c72e8f856aa878300a78 406841c5266b911d87602974d79515ee3cdefdc52ee5e319c934adbcbc964735 26 e134815b7a0d32a792a347b2f87e63aab51b90b3e63b281f4832e2e18470e452 7b5604ae9a247eff5c40efa5965808a9294586dfbd6d96ac962167a4134acf4e e7040750c32328c80ac5608f9a0bf591ebef09d0630f5022e3628558c91ab2e9 3c358a038783a448cf3286470996f23f42d97e3ca2cc4bf4fe62ae3a4f974466 5ce0c0f74280351838242547aa953e6ef42f3830c9763f1f201c95e116a9cbf6 6db16ea86470b1e4bc1aba22ffd2f6a309b8c442cbc82c9ae1d7503ff44ba235 996b564c3f75320433dcb6e93ae0c45f1d1bd63268b2dcf97feccdc2ce8fcb02 2a7ea0d2ab7ecd8275ff6c47dca7ec0fa796fa4abad68d20384a1314ff83db12 31ecb4133c92846d600a7004a619e5867595ff17fd4b4c4b6685a34b0a64a212 e065a64af314013132daf153c9d7079292340724999e9b9e0e2ac22c4be269cd 44ae0fd0320230f57bbe081415831d4da5ff3a4c6fe4ae24a2f9721df86e8de8 8ea50a4f60f0c9d389940d28fe7bda03dc202a8187b2287c5609d0a86d80b970 b0fdab7d002af49b410025b061cd946fa32b4a4fbaa400d8b05ad89ec6c102cf f39415c4eff393fecd622a777af99d13d6ada020e6b5f154b0721f91bd36e005 99df2ae81c858e669d81270858e66861a9bebc89abd36b232d2fc70415f32a66 a3bf1ab959108e6eb6044b8d3cc8ef0fac7c56d326b225948974c66003a7a49b 3296005eac9a12ea9a9160bd2d224e549a050f37f7b8a6643007f953cda3964c ad1056f0da4946f740394f3c044438c016bc31ef30bd1ebeb4da58fedf91096b c69e1a9512027cbd747a968593c936fab41dfc0de4189316f49d731dd5032cd5 cfa3c7a19dc9fe7654556910f7e6332cff284d94787d3f1c142213b9ab388aa1 a8a526d7c0cbf45988a265d3f3874bfc16fd3e972b5c6a02151a47aa44f07394 1b4b025ca5776cb79a04b73e1cd207f7bf18f388bb9732279f870a94c20eb53d 9223e36a7f6fac4560bd6a82a48d6af7bc91bfcebee656f6f014673a0289b485 9a8601702f972d76ff9959082fd1ab159e5607070cc24c09633ece1f65d65aba 73980dab5271d0312d3736daa5ccffe20edc58040be9a59d833ab288f2623b38 9838bf0467b2e4c5b42c2558fe202360778154a2df347fb3cbe950d677b7caed 9da3143e8f9e479e66ebb78947eccfd708b8dc2af91e13ddbccda8beab2b560a 20 b891e40617e15e645922532567b31be47337c1140bff027b36a5eeb8c7962707bd7910a0bc2f158cebdafb9ae577daadab7160d5a3a4bed0f63064308cb8e802f59be263479ec1b4a7cc3514dcda06954513737b7d6afd30544cfcc548ec7d08a32249e0411f75234533459be0534b730f82ef24cf49b54b8d0e67358d1c2c0a050a87e88e745b0aef72da495d72afb76397b15bd6608002802fad039657c70baca8dfeb3ae93709762eedad733ac13521d5da1aac34833b2d4ff42a10be6b0e514f401001f1c4319bf29f40f117c66b0c5788fa2de6a9830ed970c8719f23062ec54f1ab3d47ebfa50cfc9895669390d1c09cb553e2babf43c3db252c929a0fcfc2a1c406c2a8574b9a49c728e4701934a91e59d3ea050d0c6a34c785d6e30cfb9e9c523a53b777f2113f228a732f53dce35456ea54b5d5787e05b2189c4304695bf977007100a2013474c7e46366171697b7bbd3e049917f86a2fa59888e01148d356627024a4ceb657bd5562f87492845f234f09db51f19c5e67d4ba61f0179a23e12fdb34b15a16d39b9f9de4e4a03353a9e9480a782cb984cfb3d815e031d8b648a8d2dd103f9db0b321d2d43a8d1fe84f98a1cd7fd36e74381c6e38e0717331f4379c732c010d0deb02cc63893f973ab5cca9a2f01c97a3dd76764200ff3a5f78a3910710c4e34c41230fcfa77b0683f164122baf65a43ce3a5cc58d0a2d6d465fc647510dd95ad1cbf67bbdd4d5f9bcd6f81f240b810b73bb3c8e9c02deccb28ff9032a67a1aac0c4c0e3e0b4bc56a86fd342d36024ad8c72398c580acc594cfd86f3828b70dbe6a20269617537b43115d0681488847674610d2a23007ee786cc4a1d833d446047fcd6aa100030158d60f1e35eb6e3cb64acd7756e0411a2e376a1d1c6d055885bea1717aad45dbd3c25340833187d6710f04261a502d91d5935d939043cd3d37329e968b20c00cb0c8080e9f21baf5eb3ba6e2be60aa200f94ec13a6a4c5fe059d682cc61f8606cbc370ad52060b3297e664adec70160f308b42d4ab41c82c26dad8f57686251cbcd5fb4b4b64c631c857e9ff9710599dee2fa471b50ba8981dfcc5c270a67df5acc2dedf010318127ae7bd358550e0570b3ea79b85615c44edb393d3191216f6ae6bc6de1a03fdd00a097cf24950bd88ae2ca1bba92ee207186040eb76ec6c6da2f877e7081b0e48cc661096bc003a3f4778e2f20e34ee38093f9ddf03f7c1589549c606606f01e912fd2705e2d0882583a8c640a3daf385ac7995b7d0f6e790af5e16f7aec2564a2516d8dc2700fa69930edc68cc4bfe8b15a94016fabc986e5535d4846faa0f6b6fd6f89f5f700ea1e784b8e09a57b078e3666fabbf808cf930e7e9b81e04f162b35ff9ba95a034f7afa2a736229465536e67c68ea63a36b1e45037fa97d9b03842f89d346e1042e82da4609f47eb803f442a3a6375c9e0b6797f0b9b858e4c1f46f3ab491620d115b42ab21664127e12dce3ce6da36f7bcd00b137500a9c36aee81dc4449570da5918134b6462c76ba245711478f74b3c5d2b5419b4c7bd795b4cb86861a8b09be7ae7af1b12d704d53055587eb26a20d9fd0f10e69144a746e4e44086ab0704a6e35db50defd44043da303dce83cbd5a0f4ff3c05a17bbf1bd5c9bdfc191104adf136de1b8662cfd4e8570c738e86632f26ff93d63863283b89722439f86f0376d5f5c9d9bf4a97e7acdad3ee41cbc69dd76c7e75cdd166e181c1ab58ab9e096fe849972d98bf267a00c7e6eb86750323e935fb28d99e1b7a36650ea89f3100682b2f45f3d8d34a872dc11562feb5e30d624b764e57244d27d4488db92f830b2e8dd770787cc48c89eff0e32502df12e69de441eda5b8abd4984888112f330bc07eac1361a586e306a911a0bdc8ca70eb0fbb599c462d6f6a4de41751c98d0afa3acf3a707acde0c669fc91d4465af29c41eb3ea365f6bfc653019d91797b044e186d097cce7ebd06c4721c06d8d5a20828eeb11ba707417de1d328ddf36a031fb1de95f29dbce1d377dd7e5c8f1e2e3ca3136209e624b588effa2997856904f4e1937397b743050215c000b227d110bfe5263e96830aee34dc321b58b49107400a45ef4344c27aa292170c52cd93a11b9ca7325094d17a414fe00080676e06097625b0d262a2142d29e9da764eb52c7d5b78825815e02e070872ca62b5020048b1221dd9c23d7bee7af6083a267cc0c200b220c8d959ff32e4100421a1ee0b787c29f0422d7c1bf657c777d4240c811982cd1ee38d3fb3cdf6cae4fd6225073d45caaad9ff3975a5e561c728a2987f3763ec609a224079114b61661044670c +generate_ring_signature 65915976dad0b79ec2f06123198fc3a123c37fc4a73773487e857da9a5c54c71 7073df50257577f8b723f2b7268b6d026d172b9fa7bafe8e0d1712112b026e09 31 a2b0a4460179b04820d33421d1ed3c5f984c770738e6e734176c1b69ba5be705 d172bfb94a40f6d5e3a512f19094f112ee1ab673f54ee9968556b127169952cc 39c3b2c50c49fbb9ea7f49ebd3ff1b21c6120fecedd83b6fbc88013dbbebdbf9 36fc7e7fe71707ca4777c30c05d7020fc7da04b333676201efe55e93a1468797 7f1971181921ffd10a03172ec2726b7c95b714214b94d040e914a4a549d24623 2013ffd455d969d46ef413e6cc8114d2b6a25de9e5fff6aabd4f1c84fe28bf58 61e67258e2b7ffab772eb1e68d832f940bfed8d3ea7e56f9fcfe7ea26a8d1999 64e5efb93d450926f1e6115688897055b968f93a6972172719d69cdc21e93e9a 1db41b3664617a8e5dd42df836433ccda0abc7ff1d94590706d506cd83da9c79 722a3ca714a18f10ad273c30a5ed6104a00bed41e5c6bf5f955ab7dd41a49f1f 32367aced52479bf495d60e499e1671537ac2d8711fcd83ef8874c667fb94fd6 d4052c8067abf0112c03f4ef277f7ee5e0c351b245c1f922d2c82bb855d6c341 537ff1cd54e1e52430585be5197b3da8954b631e423beba3e39dd3dc6be19004 66b18195c83e626b6a9c315854420167a09bdb29c02175eeca18bb1996893a0f 6c8982d18575be7948224abf0157ef3f788de7294ab6ff5c1cc6d9bdd5647527 6251ef481c86959a70d700a5ec9892ba415d370dd1fb140eac186f74090b59ae 25642851c0c2540c4a43e28ef53f2923af198546242bbec704db549933ad6498 002c5ef9e09a9065372ec5c408cdf6975b9673d416d78204ca1ff40b3a2307bf abc5cb8512bb1db9b640c4890e68dc3a7e0b492202e48c68c26ab68501150352 0b8a2f4c3e989eedaa91cf4c308738a050b33d28cf23940ed9070a576b07aaba 97d865b7b22cd95e121679e94c5cfb4b1870e4779058d308d565151de1ffc754 b3ed05b092a76c0031c064d505430a15b1bb4071bb70991dfd111e04ec77ad44 99096c10ba7981946e06381fb36672c611c0aa8ea97a3bd8d171a4a188d70e91 fcef5abfcf89053360ceba60f1a0742f6a209b4e9bd3ba23a0491b25b18d12f8 61c1720dc08e8fd3241ed1c0f59562dc5a39337f2a33443ab4f041ec9842e216 cd5d30ee14c6d6a6ac28024b55fbe2c306a0dda2790957ec2ea3806615e9965b 65c60d4eff3add02a38c4876bd36586378abd726502755756b1ce232b7fe06eb 3e7c1ec3ef42e896cc5564c1881ccaa0ba7a5b5e616f069a185cbd6c6643aea9 521bea98888e7645384b810063c034332ea7fd15cbf091ecc24a9b2d629af997 5293f3c7583d6e5f28b5a08282ee05a2aa2e8afc2b35db0ed6c4aab167de4273 a18fc87524c2eee2b4cf3c001ae2969837e11bfdc9e135cdc09a3c5854b3a04e ffbadfc27c1d36aa85dd83ce4143d666a9fef3b90820373fb96f7976117db103 1 1c9cda2f3a9320e833db5beba7d82ea79a3ab41fc14596280244c5bb75b63d038f2bd7d605f0be1e8a7823d17b2a4451c2073d617026848f6efcfd8643ee7d0c96ccd49d92737bf30ea42f890f60edb1c1449f4294ec8d36f01926678b4b3300ba15b9d734dca7c5a56a0dd66c5860efe1c76bade8069bdbed8d9722d580a10032781675d3e1854509e4f02f05f54c5aa0004726802b4b6203a5a45002c299033b1ed32c6ffc69c87192d4b15c02a7ed7900f697a6c0d9afc0cd4fda8cf1e5018e01fcb365827eee1c9bcfdba067587131e395338be94ff70a5e1af23c41300da5cbe9ef39047fa4f15caa7b8a48937790faa1d9ecc003c592335e11b753e00c85799bb114b2d77586f32f085a202b31d1820794470c7086745cc047b028d90e14a0a74df45f4d325443841b1418e58e98edec29512a6b365dbf26f4b790260bcd51db03ae50601b12221043f02a374015cd69d7255976e4fa164b83f980740f368be694f43183dc2ff469e6cccb08f7abfac8b02b3addccf6a7383151fc750af1cb3591e95b12e58db370f245d60038df752bbd70f65139ae11ba9d4a6fc802242d15c70d96c5b307cf673c67a53aa3b885b36356fc55d5301f6a9a66deb20e1a5c563d1714f3afaf951fce1c57cf0a35d9928ff45166bc21492f0dc95ab7032982239837eff586ca787a9716b35112f0e8a1085c0a9c8f39c998472c69040f915174193bf367ddc9c5ba00df82dd92d23076df3889c6c1505083bf8fcb700b4f24baf11a07a194a1ac2b0d6557c075ba82fa4298e19d07972910fcd6f595066e5b499b5c032ebd316150b8feac64837d47d6cb48f1e62ca369de4878fe850cf46cd3ae66a658c9c4ca7286cd1db79e854679e9c4959154bb642886a8cc23062a62d11b0458974feb9ad40df7e9147f2d4cb984082d64017c0d826d7d57d2058bad8bcae5b0ade7f4d2cee051a97e04f5e9f8272a3cdd068141ade0c28164006aeaabc6866162bfd6f2df30fffb2832af336bc8e0eb9197ab5f6c3e8f95d803865707f4bcb1db7dd7cd89e856b6a10005a020e514024b55805da63c833c1d0a32d3ecbc38cb9851db07f183046a8784fa9b6700798fa293d942879748d3a004035a93080dcb8b93c9e656434ce3b759615d9ef6375c9ef65da4e469a3e13d0be93ce82a99940245640b8dd1343adc3c902d13550d0009076610f9fd5ae2a20f9521cd1042a23a5d7125fe6f6b168aa15038e303d0bb2e30f26e123cfcff2b0cf6cb10576ec43074cca73e39a108eb8be2b771df9478c1bef13e018bed8a350e53a3eb816116f57123414f791a170b83298f1f60dca8fa84d8c1083d200a910bfc8131cb692b924a41ead51d512bd64dc7f925a7cdc5d789b4ca860e17a618087018bb410997e4cecec255d1fb709b9fab7598b02f56ddcdb603e170e054f10e43d5455e673cd080a167344cf5896bec713f814b2de7839b69acb53e5e35c10b77200e508b9fdaacab4ee81b0ac42491d3b48179b17f4034a94ec80505a2ff00c3249e6bb42c067949a4ed48b06842415449512775e53c07f156793d4dc0ab004fd86e64fa97c8353b696c6a81b294ae66e0336a8aee21d301a1c2cb19ee920cc58a234e65fc8ba21605d397278a5960e3f86693d6283127e3ffed187bfbbc073b9913ab6a4aacfef80ff3bca9d6de3299f6783db8146047338d113159b81f06bd62fa90a77f4dee7bca61ebb3ba6e963cd9c5c64c938b2a0ff56bcfadbca90215a310ac4ea3f2d37ce487acdbf5a70c0341d257bf30d5b75b30cc033c07570debe16ec26eb5539dacf6a06e71b609cac5bb41bee606a7dcfe26ec973c412701b90abf86a434ce93f80f14c1fb739b645413c4146252a1a6c965416ca6a4b7054e1c3ed057106e6f41901cbbf8759fa02495797692e744c2256b77322ef12d0345c9b32693250b5fe75a4d25b82a04e3c7349356c998e822fe30e92b2367d408f3643e2617c6f022acdc349fda1003d1d904a1d611cf47578a02fe55db4b09039497d45d503eab3f736b8de10c744e469bf8a205e281f82168531563542aa9047a5cafe4b5ff237877488e9bfbb29ad53764eb80264d92966f305cf515842101343236e743efda7022cfada2ae9ce027b9d07c7edb6e0f4fe09b4338a111db0366e2a32b0f7c3e240eadd98b09c85d706388094a8cf1434fee740843e257cb03859c1e1c5cbda894530f44e8ded45304fa80f98800fdd4d428af310f674c510b466d49d63c20a0e17cf5b0f9064b01e366fe8200a7dc9ccb8d0b8f78a168b409699898a81b8754dc6e21d0b8d3ac6480a75e36928468f66332e1e4f816e89c02e177b57ec9a0a8e5162d25c28579c79cfd0bf52cc100d75d5d2513344cb2af0dd10a614ffd7682bfd04e879696dcd667764045a30b2f0be6b4ea82dca29f5e0c1a7f27c3ceaf4d095f7c52ad678002f3cd1064f2571255166115e0bf92cce90139e446e1467a363e81f8246e019eb0e0d8bd4f7eb08e8fa06e14bff30fb5f20b2cffc01b01cabe03605404835509413100dd34d4190ac0482879091aedc89e08d1e80e76ba33679093aa6dcf1520da84592ce7555ccf219ab3e169f58945d60d0f9503d5d048419bb9d45e0ceaf5a7580e6c5375cd938210be5b509e5522d207b1eb21ed8b6ae3abe7c1898d29c458dfcdfab4181e40d4cc9d234ca203c23d0ab620bfc3729eeffaa1568695feb283fcb0cd822eaa8b22fb1a0b59178d2fc306571263f570a357ed0aa7d2e2cc2f1983ecaaff08323ea18daf7e850f2a26ac08 +generate_ring_signature ac3e3b092c1e38aa072cc4210d9bb2e4ce013216d06cba6049ca7b679bf4822c 317219905c41dfc83057f3a6a0d538f47add4d4931b087b6d488aee4b93ff7f4 1 a957ab83e1decda794a51d72c6b411a526b193dfcdcb97941651ca61fb40a066 cafd4da25098d3a9667da2474b43613aa07f58c8cec919c02067c70b02f18902 0 03efb0bb6bd63fbacd5cf4af3ebabbda590c37dcec4e67b224609205ae9a090999103995adc2d71fffea1274c993e62683e0a1759bacfecd94cd77c817d04800 +generate_ring_signature 6107adc2ed0507e69710223b8f25ad15872db003a33231b30b13e693977a9a04 28c0cb6ee37eee1a2282c28676b5b9b3ab652ecfd46c4cc29b8b6f4ba8cbf514 1 ddfb74774075531723882e838680b6087bc40a394ddfb6ad1235e233491f4a7a c4aae45c82526a21a7eedc6caab8558a2bd4f54cbbd11e95e72bfe372bd1bb09 0 4b75cb0a560855d74db19851a1add2323364d748c0980a690a3c0ac8bad04b01e14be709b127b791cb2b0837d68b7d3b56dc61e65746b5da7dd04b79ee55ad09 +generate_ring_signature 2100a5f4e410e5dc62f19a0c5e87184e1d148a8dd98b2466964959ff2381da66 d6d869463615fbf48380f9d11e7461f8cd5bc1fe91fb99f685743aba5ae70101 28 793ef8c181dd024839f3212f25ae757cb80bec1c219db4246c6ee2fa052b6f17 2aba2b63e6491a35ef32789b0c7a6274377cc205254e9bf2f69cb0286dae5523 3fa876cce9035a3e6a4d5d1b7a8c09e2df305701c39878bab4da23bc717f2eed c9e31cf9d3551e3fb2af4fd1608af9627f0a417d3cdaae50424f7ae0ff69783b d0c8613048181c9a3694afd2a02589c944bb3eef2b82b77c250775536449aee1 b9ebf2faf7aa48e64ad3dd91d6c719ac4f765c31b03bcb8fafc869c8c7636f91 e9f8b1b1cac9b84936264a4752dc97d3028a209be61bbe6bde32f8faf5463a72 2e66c163b5b33bc4c675b99736bd883533d8cf58ff92a6c6632cd47898a8060e a993576fd3d80b0925a900c3072aff58cd46dff9d10f166ab52fc57182b7afa5 da828df878c59586d46a4c49696661c3bdbdfa9f36a053d5806692c42e3f36f4 d2f4e92d5e5d70fce216e8b6d243fb32014d8abae37bebbee14ea9b8a3d84b8a 2f1f24c37d5eee2ae72a2dcd3b1b6ad30f5d34734a762fc4ab7b8956ff49dd02 cc7d90c3c1c794b6406cb1fa52f61a0045a2fdfe1bd83636c848f18a100bd98d 481a170059326d8eaf5a6885213b915fac4cb27a8eb5318489a75fed10cf50e2 dd2cd3093ca1a6169b55964de9003e308736bfb3903f3c8f8d6b02f252df474f 7dc1c9c1fb20dbf1c50b213b43df2fc31dba76b9afbee67b8b0faff9a7d269ed 50e9f8e8964df954a2c522a8d373e52d2187bbc76919287a59d9b506249ef137 8902dad485e7e3a7b9cbb784074a11b2f75686b7bd6d613027a0bd91f0a96c2e 33f2908d1fd2d85c821734bfee6f1f08a1b70b82b95a7b592d02a3d09e858cea c70aa472bbea4d8d55b345cc2948ffcbff1f91294eb23062088332a5d78b22dc cf57313df41a81100e9abfe9d50146d4bd97dee3a4633db1d47cda8874de978e f661b18e8576915d55a6a23e8d201ed5286a576f2c81c2fbf4ec7945e9b54f7a bcbfc29481405ef6941a8865ff80219df8f16f972e6db14ce5ae1f05aa3e04ff 1c5b932bed93ed0c1b0cdd46325126b6049b4def7a3bad6b7edbb8c6adb628cb 089949b4a4c24c2131989b09abdd0aefdc12c1c1f62ae87e04fbe0e9da567544 0da2fd4af5735a1b90aa73c411039d41dc2f61aa1d1ff7bbb76ad39e8e2c5082 81073bb6dd2b22897882b3c9d865bec7f568b80ff23cdfcc22421fe9771c3395 5b87191663fc83c7ac5c0a1936e414fa357bd8c83323c08c5aec0c65be085458 6a668a19b1bc83605e4aa62bc2a17c45bcd68210cf2b05980ff205babdeb8508 27 b55dd140afc90f4b6e06679defd00098ed175ad20bc15b8295c076479fe09c0a3ec14584145f2ce63210f0447890e01642e738626a19beeb6dacd55ca322d20e4c9fdfd9595b4683e4e3e3a602911d629f7a119b201f131916475532f7839a01ba69e15f4ff7a681152175ec1ebfbbd40e2d8ce5f27aed2274608ba0e63b8b05530c9c1b048587436bb8c9bdecfb34abcf8b20b977ef06de844bc7234abcd40102831bd109af0f1ba440aa64d780ff619e74cbdb031efda3e7f9ba8323c9c804086653aaa4bba433347c4693e062565efbdc280b313b4f29370bf495b887b50d3b4bce34bb4ea94088ef2e073d358765e4daf994689c6107fcf7e5dba13b2f08db464a06ed3ce6bfabd11cb5cc0b2897446b38c774f1fdb59cbb8c97dadc100e296a999880693ba6a27bf84a0ac07d6485fc803cd52887f293e2e7e5ead4df011f36a05078ed3baf55eeff5d1a3197ad465741c36c51157d8f4674d5abdaa10c549383d969cf139abcda55a6bae19649db8ced58a54ec748bd3d3d0324a33603d04675451479f3bd2ee43ab3e9f7a574cea3558babf4602e34210b0ca9cf680ea08ca3f5fe73a030066f67c8904e5ace16a590da9f0557ceccc2012f4946a10b3bbe2193be51b8811dd02e03db8169c7c7fa854c122f74410c9573a1c8f30702b3421d70c2b86ed644632535ae1102da43661347756f0a95bb29967e5db59e0ac20ce20f5370fe18456c59bbd29159733d89645a0e2e2be82985891dbff9fb07e31f82dc4d660cc440733bc6ada51b4e2073a18820b3cecd3b1a9e8024a77509acbfa539afdf4da2a4fcd6b15135038f33046cbd005032adf44842a9ea12680cc9b88c1e3af379575e40899d2adec5cb83e5a3a5f640486422aaa7cbf07a94008fae45d390690f1f8c63805df6a21cfcdcfbb23382a28eb8fad0cedfa1255704c2832878889af865bf940af113aa4537f5d8c134fd3dd949dca384de2e31d30ab3c351e57cea5c5759ca0b57884fabe028dc9c6185cc8b4d287dcd69c6eef20d0d3f000bf5b9f494261e1baccf24c395c3847ec397343c46958cc67efca1bb0e0cf2d6dcd53918d59651a6de5b0998d1bd6b7b36a2139d37536e20a10618ab0e18a2c1c53670c77f096c3a6076fadd9dca4c463c546d682bb39161fd41b2d101fdb829e55148ccd65804db07eed4e90bd86f7bb8710cec2526c0abbf9d3c620227574f5d1be708450be128368789ac3ac393c052d9975c22e81eca28fd02eb0faee0231339208ed1ead0b1e6c9af1a5d13078045cf2a31d3f9229fae9ad9c806d9c80784748bc18cf6773fbf3ac595b926d2242897016cb2dce8532c0ad2610008998882fc468b2eaded12d9c4f7b488a434d9a9ce7a609a7031348a904eac05170cf699f45ae5352eaa2ca804fe6b8f68f83f2df8a08f7298bfbbf630b4b10ca42aa71bdb7ae231490fcb5a65733afe50acebfdf526a2a5139cb63e21c2b9018684d7137bfc9d3da812b8321a6840f957f4a71a629f52881bcbb6c495133c0619d6daeffa7ad7de74627e30b2e4e709d73fd166f7d0c1b6f7755f455c90b006e50fdbef8d14398e33df891ea4cf25bbaf32612a0c8a5bd8c03bd428fd5abe0bbace413f9217636270a3b6b83036b7d98ecbb0d0ccdf64978feb7f3afac426085788f852b8f4cae321dfc104c6a1daab5cece5f65360de4fe5fcb82c89d45906e4059ace4b54f91825912db55afe71f2d4734db085b01aca8f2c0e6a3af02805ca764ca6ac38bbc3aaf92addb8d918d269c0d6da32931836a4cd41c755dc4903b1355049469fdc2ac6251c16392b21962614c446650d1472ce5404b6bdb0a100ddb8b582bd55b883dda3521d61ee48718d2fb924f74ec600308c3130b4d1d807aa92e305c02b74466647d3f7c39ee8368a3fe2a8a73b6743b5c1d5239f4db60e349b10ae9902208c0bca72576fed11d77d2cd51e120febabcfbbb2093e7e0c053e9ed7b820acb48f2b95fe94cf61e95ca729e0a7d03019c65d6e6ab01e6fc10d5191425ef7421c768ec83a4afa8be811da71a2ef50aef054e8b4999012fb9b04d148881fdd57b3294b09d115da884326eb0839e96fda767053b1eefc5716e901da5b580d3ad2288dfb6eef87037b868b8eab66b406a12d8a84aa56e4bc5349038a61796bb8436d12c1a7e629f0ced6006e5b722c31d914431f61d6552f11210af88519be0c5db6ccb80d7f064b998d29dbdda9bf32e77d5b1e677a055744f20cfaec6be4bd9dc4fe43336217cf393024e656d98b1a9dea814174b0bad1a3090bdba8c7a7a284dd56bfd115516bbffbfbecde1401cf62692c4c0110cf1f05ec06860ddad8565df50b6cd6d246331c76a3f9ab5153910cf7f91c4e5852789af006e504ae33ebe172677529875fc95bc74d874578b9d37472016895a31a5f950801ec54f77cb4d5db7a0e88f23528b8457d149c0b5cf33755e5368fec71f50cdb09d757378ed351b6a23d426aef8ce73c8b35e5fa44168cc2f33aaa17394fa8860c +generate_ring_signature af71df96a0ce2242af718f9f36bf7b1e2e54bf52afe541127dc2b87f6ae259aa ca8423fd0e91f8872e0a32bd20940a577b0fe5939ff8c684a67587c699407cec 22 1258734c3315b929610f4c8215a30412459f294317eaa246b5d8867d12c69363 aab540da690563ec5971895052762a8e8998c754f895201694a17c476dd598b1 74990fc817461aa56686cfd5f453b41a69f8aa901fd4e8d4d1f1a0b5f6ff8c91 be833b7186433e5d760182cd8ab18751036d1b0e968396cf61ef0d903633991a c174deb550d5ce869ebe3ec05bb8fb582cf4e27c35d5c190b7da5de77f28dcdf 8dec97e5c5778667e0ddd106fa037ed7c45eca6ae55c3bcf25503d41bd807fcf ebb1afb03b050a92b8e559eb8e067b545f63d8099821e50b1c99799b7d1991eb 7e9eca4eac87463a8a0706af0dff91dd9000aaea65a691255bf3d4891b55244e 51b1223f80ed22dd385f378a33a14111d712ca3018ba967a587bed35d8b798cd a1c58243c6446bfc860b55045ec7607dbb23081b72265365fa90cb90eba8ee23 41910bf9644f3f9fe19c5a219d3b7f96ea6168133c19629a2889a73de302b5fd ac0940d8dce80710286d7b2122907d0c2a8cbebea6493e44d3ebc88b131e98e8 e10b2dceb0a93a22d8c62e6e4f8c7d766c0733316e6d9af29f6a70293b2ee109 f2553f4c0fd73109c497c05a0524430184d0995adaf87df4b35b48dd589db98e ac12b75019ecd593017d62134be2c9145b530b80d0c604f3beedde286fbca385 366ffcc3d9f2704507e10f7945ca35af510d4917ca6a0f320b22bb9bf2d126e4 6e8396f83467caf6c90a774f7a35dcba54461a71e2ee2990df127a5271b8093c 3d1e476c5c17a2a9d875e8e23243deaa16b8ce4bcdc2dda4f11d60a521fd83f8 c52b53a7882356adf4167237b853e0605029776fae814d3fc7fb9f5bb8722f2d 524c073fa8195ef0ca8eeba82d2182b8cb026a4f0759296cfc02e5a240e6b65a 0214ccd35e3432dba23b879df17a8efcc9e2e56826be4d0ed4cad87bafd20c9e 9e572b2ccc41e5595b3c74f6b1a571dad53ce4efdd29e04fb953b7e8e5abd8c4 c379fc436343668d69d752ee38c2e4f989cc013b9926f3c54568eafdaaef8603 7 7bd2c4792bc05abc21bcaebf0923eab275c9144c80ae806a781653c40abaa003f8b3b085c8c653338f002969b223f61317162fe0cfb7c02df508e539adf1bb090afba55f7be6fbe3d73164429c946a29acfaba89321368fbf1ec88fa0f7cfe05ccaa3169e9e9249298b47730a1ee026f0a1ce38e84f94b8d79152f6fc505ac098a89f2f816b1510e983a61e6fff890275a5d4b3f7e6cca6856ae85d21c0dcc08acfa7a0323ce302ebe7c597773fb3876c37143e175572990de6b0e66038d8607a52cc9e23ca724149ca49689b65b9f877f0910ba87a3468fbd1f089fa9a66104f8fb2087a7ddace7d2817e91dba58878fbab281f4a69d273fed6cc4f556c480ae527a2b69c2887844217c6381065f1da64d5ca2fcf42dd4193b2f156adf5810a601b5184473ed3b918353f29c1fc70b2f2ad706f1367d17cc2a8fee13199d70d986a1583b2033055a81581688a8f4ae84d676e160e3cb0d77481446bc41f5907f39d9cadd88a421412342994a8226ddee48256c08ba37b7849e824f885c5ac08ae60dc153b19c11a605f7f4f00dc48749dc447e507aa593065b2d4da1299670b89c882589707c218a5def3ed377575fb159160fbe2059bf32c0ce988cc43500db56863d8876ad64bdb832ca649e13c88ab71a0719e9e0daee872338d82f2b30da27579e341adef0abcee6d61701d690bd1ff00fd547660be245f9d6a6c62480ce9e16a145e17a7e4b2470d6c95a063198579bdf344800676b67e02e40318f20b9beb98709c039a2cc7642f921e367bed48c3c5b03e6be8b056a8e7726752900e5b0a139ec47ff32a493d12adb3ae7c184a2e88dbb7212818c2c580dc465aba03eb465a4c9e17853e6a6e617f87cf294094135ec48b4717c0abce8a61eda5140d506eee7d820553c62aae4dd01b404e85feb69b61ed525e0e8a5b288211ae0b0b89b3e4f9a3c042f5dbf09ea88cee77e359207ef17fc2767b6a7cec02d3fcbd0a88c6fd3fac1f8617686fd61caac6ac90bfcb4362fded2da360701b319f1f7605e3669e59a1d191a63c991bdf24c50d3f970d648c763cf50769192cf72489ee0079946d777a82adfcfbe5954b7ee6c2cb334c8bb2b03e2cbc7f23f73fbd8adf01752c5faa7c0a3fcdd6e591a5fbd3c516edb919f4229e413bc3c50fe9baf25b0535098eb0e315fd63671c5b248d203a71a1057f5688fc8213817f3fcc98b0db0fe15983768c57a5d4c28aff5f7240c484fc1f2763d9c2e36664ca3f0b4d2e3d0cfdc0c42f84deb8597b9c223d4ce75587447e8a7b3f08827704874c65e0db6e06742caa0c741e16dbe4c60e9554ea42c8ec97f899a4b79a934fdab4db1cefc40be3fb1e63b85abf67b1b6fa6293bb93ca95a6e4b13ded72255426d2721cd2960a72d62c0bb5431dc77d79d2da0a47bcb922b638ea10574426a83d9056f7ea5d0e322e2548caf7286f2d7badac6d42ac61b2b1d0524bbe11a81edf6c98dbc2060174a3b5330a88c0b046bb042e6ec11b746f03c35305889ce2152439a01afdb60696bbf66b6699c03686d161d9eadd1605f7ea34302a4a798fc6ed5f71e09d8e0f69628629566261f40f41f753dce47533d4dab4d3359af56719e4eb8c108beb0849fdc0e99041c2a64b8444809c7737152c749742d3745e3733493c9c1c768508c94103969397af990202b3d5e45354a7766fabd502e8ac65cb9d95e7766221055b497766a15c0fdd8ced4664a0f178631315600fbeb8bf88d4fe5676c372970ad15387638228f0fb751ae7a675e206f9efc31b3783b5809ddf508c840d4d11035e44f6c3cb140162c3e606b222fb22ea62f15be1b4d3d228778c71993b0b9c016ed70b6bdb0885febea0eef3589c83863d45e5143c243f33921a1db96a11d00214682dfe8b8d097ff779e4d05279182433fc84d884afe6d59bf1fb3f904f3c02fc35df786e57a2f2bb97d979b60026b49d7765378b394d854c70ab016e8b170e +generate_ring_signature 4512063bb19daa1ba31eb0145d48f7dc9d06fd806ca89540becd2b5e6826c1e0 89a8e66b8da6a4002c7cbd2dd887bdad6a08e3412d1972c1ddba31be29ad779d 4 104de0915736fd728e8c86d2458441d876f459f995c7256a276534f438a614f8 05fd6561503fcb29ce98b70157dc619b5c4aba732aabb0b0d10b8298d1f5e155 2c1a30eb5f25ca5ef00b7806c934794f03dcc5ac58606aec2081f9522a216749 133392cef31dc52c7de272824c7d487327b3320b2eaf1caa827083872002b16b efcc49cb457ad9394617b802a3be8b9292ed7e88c782508899ba39a152e73200 3 3450a20dbc46af7995de979e4c776a2abda7b657f2a7a606c76cf534258da806ca1ec84d596b13b1cd199a120e5ee866e240dd51a23b2dd184cf96a09c181d0ff215f5148823f9d86431d7e02735ad4d553da0778fddf8faeb8cacf52f765b0a3d9a873a4f490afe2167ea8298824647ec7b50b945af20b36ef9dce700ef740ff132ff39df353020c8f547580f4b7e10275a1f8a29733c7eb60e9bfb5ae84002eeb384abe845a2d71d3efcd97f83f6c51bb4b5b66f25b9f78aaa2e76897e1309c86d009489a09871c49681ccf781a828a7770b80d4b0762101b70cd64c7e140ba8d5cafcdbde2bab42e0e1008ce9c06c90ad560da6c34fa70b57a28a11a80001 +generate_ring_signature d4a171b6e8c5a7881d47e5e059129c134a12972e6cf446760d5ea3f5d9d8a526 4995bf794e131c0a54e6b94218aadb1062967bc29978ef1e04a5ec2a622bed38 2 8a1e660522cfbc1da70e1f269efb738b9efe941435fe7ced85bcb8b2b445015a 52a0a2d5f69efa6666a07a177725d76f60a1fa078e7328132ea81e2a1aead5f3 7799976d0f2f488ab7dfce43781bbf6d8f64f4c17c6dc5e357a98ad83f23a20b 0 3ec3c9fe0e6f78489dae5d773b5df03bcf11c23d369864c1acf5413cf72ce6092c1cce0d50f02675c4821ab74045f478a5508a475a76c9deaa86e37f94906a03d133db7c07cc91c9d6f7caef4bf7716f2ec6281438dd86e751bd943b145c1409672aec2f673359ab6e61fa2a2a61dd16f2951d6b8e0a900016e1828e2a79b50b +generate_ring_signature af87b1fedee0e438f10aae5befa088392ff4dfae1546b8c8f779fc50ad51da97 90e690a1501ff3a3fb14070bd46a4b4a7175bb31f57956486ca61f2e49cd4ab0 9 35f64d12ad8dd1c71084709e6e868e68b934eb407aae5fcda2505773503025a7 c80dc8d3d3abb474b56a5c054df286f87f5c58881451feb22cdbdae8f3f900a7 3461ab681e2e79261f83d37d82d4982892320fa386cc6e6f5bed308bc1c13d12 46d70d6342274b6fa1e9e3d5b5de51c4627000ba00432606cb4aeb362e25da6a 2b561ad67dd4aa1e38a5fe1c8454218127a73881a206b24862e136cf2b255780 31053ebff5a815b078f8e94d9f0f044f1688b0133cd883d479a94ed066a1d1c2 968233788adaae5fc7466d8390d94d6198074b114e2ec9b52c4d851ba6832166 f668b4ef8431e75554c02db408f359ef81436a0891490210bd509923a7e0a749 fa4407f6eb50927d9c17ca60b21e8129a19684ddb746e4c186b88ad5113dcc86 020bec4c5ca87f397f5c0919116c54fc4fa83c1a650b045ee4385a3d7bb40d03 5 8104e4aab9cebdb578e8bbba5a6e9ed3236b655173667faac09dcdae12fc6c08b3a69129ea3b203634a00a5aaaed6fa6f14e73795bf0f5e00f1df33020e90a08489d9b6007165452979e4ecea64fb5764b1c0488a6b9489c5691e4575caef50fa42e51e1adeb9763c5a84edccd78da62e5ccea264d4f84bfb38d70981b713a0969d670a07bdfd488eeeb02f722e281dcf1d83c29d5fb5cb1b47b54fc37bff00b1610b6e0e3497928d87ba95d0aff4d661c376359d0b3e187df603adc697f070a340ebb0aa0d0e7b2b067e9030dc66646caef70b451c68fa40ff7c7f3f3ebbd0edb120cf829039726302d18f8e656bbed04bbc5ffe3e48ad29f578bd116ab600d9f220b487d36e27564de0a7795f89f842e8cca4d8667d9a2fb2703ef54c78700cafdfae9e01d8fcb90555f5dd7f0e7a05230b871d2935dbe51dfe4dab2e0fb0d03fc206aee60dec9deccdcf2fc911c1f2f9098dcb40d4e1a425659768dc6710e4b9ed203fba05bd91354a8582726c80253bdfc21f414c432b50e036afd4a910931bb54ae13620964cb242989baae1902e2b74c1b353d51d084610194963d83042bb8af66a24a2e43864dc4a7730585acd16f2a43bb50d8532446937b77cd2d013ddd668f53c94a12956543ce125b4237cac099d8bc8bd50414cebefec3c0ad01f7dba7104bdc71bcdfd275aa9e55980dcc3bae1b33ab776fa84df2bdf0886208a112a3f59ae23ad19d1590e5df17a93d145c8372c6875a3dfaf134d86c721d0b27f7d788a2035ccc721b7c41d23a974ca4d742e1125e99a1d4a4d36f449f1b08 +generate_ring_signature 2d2c11cf68486227b17b80fe6353ae59abf53ba0b8bc75f32a61007b557c53ad 35e426514c73e7c66880bc26f90365d770c31fb753926f24d23848697bfc5a88 57 a9919f6a2b7acaa39c078c3b24e3487a89c1e98f72c6deb29190efe461915b1a 97078cc1079d661dd75108310685f568c813d7486064fc35b2f69b38fe6e94b4 d6e58715307fdae6fcf242a4413b3264d0550ada54a02a233e3488d63dac0307 a6eb853278a50ed8333786b3b15dcddd3d8d784cc647adda671f710a3cd46bce 204fc5f49b9e9247b2245d0b29b32a697e6cd5b1c4347430cc2002ee6682551a 19f3496ab38450705b89e6ed8fd2c725a72ab9e04daf81b3e84f762c6f368858 cdaab9c4d1337195fa27a23ae9beb85e1b421162b0175b01e5022a8a6693a2b5 da64b3606b987f43092b844e787c73e147dd3f1401e5d4de45e6defeebc4c542 8636da56ced937d7942364cf6791b38e8819902811b071d88a7e9f31c9158318 24d943b065ad70668edf4dd47bfc174333547e92fe95a4840aa1cbe343ad8c7f 4f633908fe98dfeaf22d5f82a7bc5c591f68f0a5c087df556804a218ce5b539b 550f1304058b94162f04b4435bfc4190006262a55c326750c93aadc37c491239 2a8a480ff6b6e352d3eaf025a8a2d5f7170e8c72063216af052d14050d68573b a7a57ab7e2dbb84b1b687ce4e37c966aad92e8d63a80a67b399c3bc1775bc570 b1b394508b9e74e44ed21f6f38aa8844ff16856e1179b51b73968582babe8570 fd472fe1eb884e3f57567ba1ec8d6a3839e944cab78e639146224f141aecdcfb 5ca43dd0779bc74b551aa2279219b77dd51b6d84698949e23a5fd73663f5e5f5 4e4bbaa324ff9e710ddd5f5e837df67df9ba854afba57819b919b3481fe374ff f9f50fbf4109310755f80a3920a2bb47e297e4420b5859045819b8f2ab68bad6 4bc0b971d4bab80d4013dd6cf6363ed852b6b95a94b83380eceee179611f0126 9f5fb2b0052f5a19f77eaf98b94282e1f62d09b3dfd090074ba6a99d7d3cf0c7 570157fbaf6de931c767a74e01be9e00dd875477c18a556c93187cc9aa9f51b3 5b581778bb48ba15fa9bb4e03524b5206268bd2ad52aaed0ce60ac577cd3ef94 00c51c2ea99904e5d933635fb1715c3abb4ff07642aea7dbd46624fd9f1d825c d50322d0ead2433b3977ba3dce5964d17979cddda84a13acf5f5c824f110cbf1 bf25117e9f951431febfa8370999db5159ca8511fde188cb0166624773c5f0f9 4c64494a15cda58cc9def65c4746cf88207d32d24b90a0c134dd0ae01b09c144 01032bfc7e3f6e6b0a30a3d265e01e385771c8886aeaa6948965c05728b056a8 060f286518d97854b81a3ab11a55141d4edc97bbbc93fb0bfde999234b05400c abc25998dea92a2cc721cb7bca4ec8890b18d31fe9b130e706e9f9c231933aee 0d462aee190385626534a8642fd579da27e8cd596f90b3d5f5e7fe55407bb405 04042ded8ccaebe4ba0dc9d67fb8bfd9f51c6a43f4dc154f3858b2f34624573e a8c3ee54ed71f11805178141dc71af46d0218cafd72ea5adb3b54ebfbd2ba1eb c4d103d2800689c4b1f2b984ee4b0565f5e214b8209fe622db3f0b8b8fbd3dfc baa5fb8c4beb0204f6be08ef6aa3ea2351a81ed5f169315206a089e7abe8e691 9f69cd4518c0732b7e0d34fdf8fca4f449b391d66986f4032568375532a596bb 2703488d85817e84c47dbfab7d96a741c5603fd38674f9a14dbf9c0785f90a3e 18271655568f950df4aeeef27efb9c59680db900232da356f3bc940e77a661b1 a260915c171adc5c17beb5b39d073adb213ec6206ca8cd6656ad0207f0675c0a f3304b1d21a211a6a64be267512752e8fe7e4682fdcfd42676d4fd7fc49605f3 7910d249a3c64181a1737103cb8a0cc85dec99873b99169cc3995662ad1c2397 b19fac0f51b23d973d0b7daf502321f1abcebd28f6f8abfd75b377db40a0b99b cf3cde5e0b30b42c5b610d5087e32d21bbc819a6ee816bcaf928ba20c45670d0 64f3ce114419a4bc0eec99a1f65fcb2096c94c65ef8a5ca44209c48b6f364045 7f757bdfd7cef93d1ad0b987041bc741ec64dc3cd78293506a5bad36e0926d2f b0155d119bc08df378af49e9eaaa856742bf7783f3ee16d9d545a6064f12acb6 5b29fa21c990c8b43186c1d6d842152a2fa26eb6c0866c10014baac7c82367f4 6fa38c3bea221425d2fb979f5666b6b0214f9fe9ce0abd6d39427dd22bc20c6c a6f86b5127deee81e39532d897d37407dd7348beee9685f0cbece5decfa5d3da 1827e21b68bf6d7348b325fc74d8f65289f30a38ec4f84bfb126d3d94a6e8cef ba62987bca2eb991d123ef903a7377415eb9ac77f244042a87b0538e233fdac1 be54b474591ad0d58a89c6a696abdfa17005717e6b9360c34cd95634210eb8da 78ddfa3c43d923ca2037e3774c9c4c8260cdad274487ff71dc1f5b739e0ece84 6a2184d5c8013feb86b8fdcb6885ce3331320d53f4c02245bcc90c34f4f29bc5 db01a4dfb62b753a5ce1109a566604b9eaeca13064b13ac2fa24b4bbdb859236 de3e15f15f67e61b3f05022c387ba7029432f417c1ed96377d0fbaa9b9474f4e da88bf9678f4d1594a8899ebbe347e7039f5e23287dfa64d5809f0e70a359f2e 098a6833175b819831237a5b135e325dc1e10b0d348a07ca831c60ca31862806 1 46485922e0663680e42c890bd46625c70fe5fd55e1c7cb02e59c9951a53a94005ef3caf7a7ce2c650b2113c33e25b30957c94cf0538b7bd53436ad2041156c0da9de9bfbdc1e36391bd8435d85adebaf594edd05f2280cfe7463c9be8a6e530cca9ccd79cb09401e7871965d536929f14befe23389d08ab13166175293a0610374ec0d7fb08c28f14b03d2f3a5316ac1de3b87c0daa4d1447e911de5d284fc0d7b0f0f77824313a58d624c2f261349ebcd23ce34351685260126f2720fbf89064629c7b7b28e84c4d3d9f0aaeecb9b44c7443c569d88f860506ed8f09cba35055f9ba5151b934d4c0243448fa1d72ee4a1460043da70349a534d7f6f3825390a1348788daabe964f014cca277e72f27145875e19b13f9bc94d2be573ea1ad208587204c10528a5a43198bb0a94b990ee680c3bd6016e14ef2b789d6ef61c1d03f56361651df09bb97a8412a338ef64901790155f65a9325f4c2221c9a385d00402253888463cc64f1902c8790a0acfc653f5abbb1becead628556c770affac04a6987fc9cb4eb55179b5f5f36b13b1b4dea9003db2202ee5a7e6c6bbe6fd4e010034f1a7ad53bac65dc590436e12ee080ad65d819b143e005de20c58c746730f04ffcb50c4af2dd78352ec4639da2e152988e9b03318b33f39c736e62b2afb0cbd3ae7759629f2d11304551ba72801ebd8a2adc7c071174feb134ccdd46c720b554e0c00d6421274ea7f45613cf1753fe5385181bb4584fc96fbcd5ba16f79000f7a49f2bf7529d577f8118a3ad60aa200c4e54d9b5fcfdf0144db9639bfc80c93e80bb7ca79a00371291cc19a289e3ec9413e7c835f631c70bc684b8e0fb60839c99d618d969a8df3321ce8da00692e7bf7adf30bc28936e3abc5d89deb11037c38e1534b617e9eafb9020cc1febe2cc619db3573ee3239f3d571999b198802ca6bfa30637a1d3794050f9dd9176121c3d373a45cb54c08b706617dbc4f4b0a5abf5cfa37149a54b30475d95f1481ac287375f46c9e186bdf0307ac3d2a5f07e7dee417e5a48834b45f26b5745bc09bccd92ed1c37c765347e648b401321600869411d9629f5c141edfdf1a9e1187cf1fcf505c22a12e5e1925b5828d2e0f03f849fcdbd78579deba7ea616e5eba425697f5904b660027ec4731a481dbd1e0443591eaa4bc33f189d3483cc3ae12ce0b1dbee50c0c5508398f6ccdb21e3190e4c64d2d920654ac28695e84fd6f7124d0faaa1d772bdc09b88d9f115f642c7072f8a819c67c7dce0ef8a391cdac7f49ce97eb072a91e294f8bcd563607b0f30bee2118d042fd17dd46eb049fcceafd63421216b301d099222407d642dc64330dbf96b9dfbc4616c8ea6654b0bc4f51c8e08fedf0a0ad25a08bb9a544ceca520540c2d4af6eb450c69e0b720ece8f6a8dfce12103e58461f7a34df2aba942a50996f0526524d39c46c2372f88e19bdd0c56ce41e6d4ec3913fcb72649131df8001768bd61adef1d3259d2edceabe0e53ba004da1c518b61119d29d4db0f16d2024631bd556963760c923aa51579921e746fd669aca97eb77bd3f478e82adaa30f7ae3a2f0a55f83061b6eddf5339c72c79bf8d5b00942db42b70fecc6b947630461bfaf14649d0dfb627231678c10c9a85fd661d078640bc88e03ac4b1c71cc0cf90306ef97b4817c368f1fa9c4dcd66fec7c272fe89a2446a8fc93e28d81a60c86a730b89e24f970987c83d4b7c364f0c905516858c5f750b3fcf894f55cfa030281eecee1b921e2d0cb62d63d58f5797cb42be3b65adab953508824438dd104642f8df0fe521048882440b71f168518b27e87da854b3b056d6b45b2e04dbd06ac7d4f733aa0994993e0e598695835ef31d45197e699b35060ca6e4cf807a602c835666bcb80b84ffe021e5425a3b20aed0f73a46697a0e0244e88a06cf45501457f6f748c499bf4e3d948f7969d34f06086a58bf3ffae84300bb431c5a5cc0807e2ec78af5c240b856de50e260a3a4732539f9f70187a64b6841aa12dc5630ec694ff2f617cb7c6b4b7cb858230afffad0dae587d0185aff1dfd43077cc640ec912bd629e5455a905f11fee1f7054a2dc1852bc6ada4e933197d75e5837240dff6c2c100507a72fe847a8ab6318358d307409c36e0ac8b0600e0f8c555c8b07b0b329ede640adadb5ddb7aa2389bba1dcb42ea0d4c62221b604bdd10a20950cf9c65f05236dd3f3176bc06b0a54b1e6475d3d8da7e3f6791a8811ee49c30b05368c7f6a8a1b99251357a8421878936e06723cac41eb4af36f4b2aaddf233c02a7359f323817f3a46266f4fd0eb6ad1dc6091569182dae3566a22672e360af0c02df92f3aeb714b2bfd08407b307cc14b12562492c6e891baddabd8d6b20de0aec5e6028f3a84c7da60d69a928bc9c89c15840c3000c076f484dee413caac605501a2f3a307d1dc44c53672290c4d2973c1bbe63503bbf617baf643021434a06add90c9c16ddbb49bab63ba8890a546d3e6d8f86528951f9a0d00bd20335f004a6ff52b2a95cfa75960cf61edf80b71d38b2c866efcad95b13a2ef78cefcd00b6a236aeec96e01295664a8e8bd04285918790206ecce3259bc89e5d766e3930fd351e8d68955a6a8190651687356170b93257292a99627e4b520e9c85d43c00462ff0a0b6cdd481a0d8268ab5602b663f9804b18ef5fe3b1b9f4fdf361f3fc0b0800ab519b986c77d595ea12c4dc4a78d71adf643cfca4cefc68bd038e2dfd0c50874db65c84b38f98a4116639922bf29272c36f32363b850a19145fc9faff01c8d3e98a3fea838ef9c0e36aeb36813968c34ba1f078f61c0b4c00b1b3a83f0fcc0bfa12ac950d2b2240a83110a080c58bfe27c57f4939b7bdce9a4badfb28097e1b30ca6701fe17171369e1a318ac031bead9140d80bfa4f8e52434418e7c0fe81f9d0d5bbe329bf34e25d08ebe114aab7b9fc1fe131636d977a083ca1e8700b4d52cbfd16e0edf3e90a6363e88229d9ae295322a2e22804b3bbd8da25aa80e768658fa643a52599c5abc54566dd568f1f487a614ab9f074a0e29a8dff5be06de85d8b0199a6dbb3f3cb0abfc92248605831fbcc1be9592baf51b528ec65e0245b8ea254a8fdcd84d13ba4707f48ed4c4439091bef66d82ea19feeea757b90f29cc9d07e235245d0f78fbe7496ded41621cdffbd675cce3518f0ac63c1479012b06b14737724f71ad074017728d3d55cd9655519d9156e9878d3a07104d69035a5b770ba5c95657caba8380288ebcbec239cb19f5faa8328cb2f9282efd24005d5a7eb7439a6cc20313a7bec7171a9a5163cc34682d84feec5a1400c590ac0c68bfdc88ead31c34bb1001cb945ef21b36fedcefcf9a522ba8231fb9ac7f4807d17c3abc706da669722eee6cf82fa9e534fb54c87c0808fb158186b3442be8064b3c32b257885c4f20eac683f0f0adddb1398866464a6f9655814164857b7c028064072d475acbd8ce2b18f9950701de75ecdbcec3c1754369773c3c4cdd9908008184866c5972acd64bb760da5a351fec2f04f16f50a041da0e68032f2987067b1a101732a847430a698cd39bdbdbd59e6f173956be1fb7852e0519238e1f0d113de9b1c3e6d0a4992100006a02ad18f9ff6188930f58f98ce8a88712ba48026f0d2321b20c9c84bddab2a649fdab94bd4c0eefe7a9b4cf97ea80ac7868b10ea48287edee1171db95e66fdfae79435846d93156508d2b1cd34ddcfc788bbb0894112564fb6567caab167d4f99bcc7c58dfb0f744a966760212f22c73df873042165f9c59d69212120d250ecf5ab45dfd634debfec9270800a009921cebcc900ae88fe11dbb0f072adbc34e02b408c41624e2b05ffbe91b1cd7b784a9e12a00d34350602c97d6f12a5078709d34c0092516400371d56d54938ff8208921b9a0f805a2d106a901f11880cee0fb0904242cfe8a281b0ecae01b7a0f564e77c0f0bcd7d27f21c15ca2f6a54737e9f5711d34ed2bd2ca9e5c9fcbad896f5ea6c6f0e8c0bc8c74bcceb6d19ec1259a5bd3e931c06fbf835afdbb865f79120fe38ad0a7687500f22e5066ebc51982e5468f80d9afdcc9c8d15110933ba465859bbcb00203f9f06ea6377eb73471f746fd58befa74dfcc0c86a361aa56f3d5808942b062d624eff791432b4a68a453d7dcd1d76c76e4616e3fd7144bf50f764d0cf990b9ca9d60ab5e3ba2476af33af73e5eda3b05c69df5628f4d06e0fffccaaff4c050e511841e5e4ba66890f31b7b4d650b15461e96d3a054cd8800e569fdd695503719e17b9e5c1405fa9478c0e594bf656fa5517a2e1315b499dd57ced95ee8d0a9f41ec2c66e7462613a93a0aa29cd136d89ebfa4e7b2fbb4bdb81c0b6b4ee30bd8bea453f78199758a8dae88be26a4d6056169c19f0b8a669c4c01a20ac5aa0809c03f9b77f4cbaba79b0b3bb267226ab457a98f3db49b5ddd76938e173045036ab73092f038ba4b8137ce824bb678eb566522f17a5b5906e56591cec091990267877d5d53d959c777548d2a324260e1b02a6544214bc0079088937967720405760e32111d911d6d74675bd5da8cfcf23971dc2f569bff43d9118f9229921d0b01f9371cf50e56699e72d4ffdf8bc0fde7b4cae29afe7e628894a2d1a83c160c4ef81f235b8055c2cd10171c86f14ab13d85a075586af8cf950554eaf102c403ca8e8b480087aa11efc9c07042c50b29a66069e574a38ccbe4196233ae7ee807c875e24b8f056e7b25bc7a16bb539ca72c8c9cbe9454e1ad0417417b0d40e109542e18e3cfc116ab87f05eba020e1218554d63e841feaa7cb2063beb9664dc0b366bef65a49456e91f554f627d51315df7fb8bcbb97000443e071ea82959140bd7b9d11d8cb9535a5afc47a08a87de27e18291a803326693a4f576dde707ca02b5ee92a30fd8cd837ff094060b75490f8848136453ac603a5508f9de19044101404a5f45fb167be250b9dbe50bb51217dfeabfb2f36fd402a9e9373fbac8d30c50eb415cc80e5b3ddda0861bb015afeee835a346a755d06fb0f83a043462650fc2062dd8c0b7dfd44a713e1f9d9010bce783b0b22ab4b00d5689ecb7cd944d09c543dad3d20d18264afeefd857a7313a9e1e2c70f26a50564efc233838aa8000 +generate_ring_signature 5f538e02b1461f07c98077400e3cf540b0626000edcc0ee4f184bd1f72604f9a 6be7e0a471ad7fee54ade0d6615b22f36f5ef44992917c3981ef7a0a4d561da8 7 4648fa9cfdae1cc58f504ea9031acb69b269d148e581e01294730540f5ff6930 9dfca258921efd4ea725792ba16046d64831fc572f3dc72ee4fca1100b966ddb d7f734b73581e4fcd011a57ccf613b25ab32c3e61dcc3aee5b65ee0d118f3858 e11aadc5cd441dd0c48f584c8f92cd17d1aff66ddbb7f86e4ee6deae1870f0c2 9893530b57c30c46ffd006059cc5ccf20a35632060107d8ee0272da1cf219b7c 0f5a132da48e2f8dd651651c00026b9ae41d909503fc5e7b64c808201a06d2fc 69fcfadb6d9b4b296d86583324f22d124fd6764ce0dc6331efe72adef2ba1a26 02043a6d949d79e1a8c63c231e3db3bf406bf741d9e4a35b14c41e9813e90a00 4 549bcb0b353d421de2d171d9bff3dbfe67bad88fca379752a76d7687c987920e008aa8258703d05597dc0b0aee74d0e7f7e24552e62650383f794d422a92da0163f1b9586ee00f40d8ad8ca406d892b06cf4325fb2f8e1c319b4e1ac3ff43b0765c29d68efb289478a52694144a02fe0607bfc467af3d67dcfc7f3f3421be10bec530ae754f26939473c33f1cafba3964e6ab44be00212d0f2340f7fe3912b0bd8c348471ef8d6c046e4f372910f1c6f86f667901c9b7f6145852f392f2243074b74e1ea3922197654bfbb8f3e7ecd737c2a3c54966942874062f165a226a70ae64bc92d4079e5d2badfc83089ffc9768ff5f8e7d17fff1394edb4aadc9e9207cbdd2874fc1ad9facce162eaf91b36e7170c58e5fbf5f570c2d55be200d1740d208f4c0762a1e8f28c235c914dadb73715d4017b11145bc2d764595d5c5a12067b15eeb08e1b995e5e4c4ac6702cb3b447659c229a56dd221eb8d13de35e6201f50e23bb16b8396412f0f2dc55b5b1d7673b914f284091265ac2ea5d163ee605b84e4b2a4b3c7620863d63acf8f2b62e6dc236b590bc8912b651a840d628d808a0983263e06be3a710fd7c6c2072657daf66861adb5c766c7f58169fb9364905 +generate_ring_signature 39bd24a7043973bd7a7f4c8e448e7787d1e5aab98f333b25391f624a492c1d35 e7551719351d2f367292d49a58da045bc9af52dd31cb565a2020f5fd3333728d 253 87211d95088dcae2b1d8db1e408b1eea3050193114a62975b8228d69364c2e16 d8080eb5ff65b1e88262670190e68166ea45b3b603b37b6d7373cfaa636f165e 241d5a6bf98df975d09c3fd82f28daf686e24e8d577632498cf47a80742fa4a9 28044c0d9ec190be78c95859877fc3c71a5eafb944d87af6657986098d5df61c b5380a0808e51b9bb85a54c703ebec3c1dd5d00ca4c776d3a4d88a3b15fe13a9 9b02e613f1bd267ab8ba9f17e1f44dd254e539ac7c4ae51db640be7d43aee526 b4dbc4c9bfc1aaad51e0a4605f40f3e4d86bc7483e9034c60412b099eb36dacc 94af0b33beeef150aac1ed32fab925099b688b72a6d854115507e893d15663c2 7e8e137d9e882f0fb9e8eeb29e607cdb113578b086780a0728e926492017232b c025e69848c70343a238a934746b0dc0edcd2d545af7003bc00e647cee2f635a 80c47dbf387d8fc014051cdb257585f7b85b08e41364e3a6267652db57967cf8 2f16c481aaaedc8ba701a58363f4574d21fbe7d9d3b225c200b7fa9725f15948 8ea6e2ff9ce7991d7764a92cba2c865f5e2a5e258588a43f76e17e41de039808 75ba819f4fbfdff82330cc7afac927e72fdd861cd9243693ba5745891311fc15 23a6a044fc33f8f2e7f8aff58e94283ea45fc8202f1e84c71914073fefea600b 3662f25a290356e28770c62bd711ad6ad929ecab25da3f515a3c053e6212311a 192b423ccbb0d6d329e42a8d0317c8a00db0e5a2decb455b79f6b7d9c0737c06 054535dfacb051e8f8cca57c43ea456cbf563fc80371b8ab750b4d9e660270a4 892ebd8b4d5abca1c059e3aac1cb2543194108cd999debe33e7a65d112760d2c 6627c6b5e09c06f9329edb030089e2bd60212ec499bf9e00ead218f3b4c4a94d 0323b5f1c8df8fc71595693abe6a5423cafcc7379ea59a1fbae58b1c820f5f66 8cc337574d514c3b74794eeb2cfd25a2b0c10768e631bee1c08499ba34b08c50 42ac8825861673461fc8e350040863a663fc03a8c7822d4d97ed3d80369be618 c4e5dc0e598b2d75087c6fe50b411588803f1924ac9cf53882d952b6bf175e20 f93279c53d909208453b55837953825d8fce2dd9d88d98917e7946016653d867 094f2ff19126af7b3c0f71d8f0d569edb7d4ab103a7b541a85defdfd3f516473 00da2bfcf3f2f224fc3536837ca93891dba7254213f5314015eb6be4f365c6aa 99fd38e293ec436c242c51b8d7688a1e0da8b8d9498f568c8c67b7fc7b03ff35 e8b3c064790b8c6004889e828c28e4a13c94de102ff868c0cb30fa7a1b310455 e009ac341d6cc6f400c9aa812eae38b983ff1c3950ec0ad32f54a637714207c8 41d6e1013a167657aca3c785b428458a53751a3ce4f55e7f69d1c2a732dfceae cb6646dda6cc5d0f46c3eb31b6956d944b63687ffd3ad12f0d58fe4a1412021e 989c30d40c19570e0fce6aba0e6789ec2351436a0deac9f4bf373a5621583610 ddc4aaea5c7d9b2619c2cc955076f63ad67beff0f57cd678a43b6aaa935629c5 7137f11a9d15db1ecab14ea167381fa81bd092040a9bce49661788380f5deeeb 92670f852c2cd07a97830d3f4db9577d9e933d72b46524dd05c65325d9a2f875 d053e29032574a0eb93bd7f30dba833b1da8181e2093e3b50d28a5f39dca6b6f f4e4496e938470ad634e61275427d3fb275fcdef514164975d93a320f5882e88 80e0024f178225cb0b40aedf698b8f4b85e413a34e29df3e3adf9bab15296e0d caa36897b70299c47f3a0cc3aa7433b9c5273e803dabd5986f84763492a41a90 7cd4fe492d5fa570d769270c0cc8ebba8fb7253dedb141801482ecc5fea15a98 a2a76ff27b18546a18b6bbbeafb1ece1272a03e2f147e9bce94da684f018e322 90a46155d50366bdf2a2d7e398aea33224a295aa3455fad40dfb4515d365d60d d08d9934354be29e663f1c8e50b6e3610d8fa15c10e12feb4cbfb1d64a07a059 8555cde97863f54e6b9ed852e3c2a26c2ea56d815d710939d89eff70153d579e 265617d3c9973965a217a9cefc0200f5300f3ecacb1487add5e1bb141400147c 6a45afcb5a02430e57bf0af7572dfff1841b9740f5e5052540db3dbd64fe3cc0 1744e17c9cd258c8a7396e7d704bbc4c6c13b06cb92bfd176ba1567772cd4ae5 9236692660d3647d50a61c688725baefcaa8675ee933596c42886d7e57d81b46 a8a82c4536579ebd4e35bf3030b1d18b00f3b56befdcaa94e6e6dddb00b3aef1 eccdd01e8deee3c4ea8fffc8b41bcfe089da7fc2d0d250c8d81c790a0a340127 a1b33761a1691e68c0ddadae7965b912a0a2578b27eb6e5234cfd1f6bc175dd5 65df31e331e3a1f31f01892821485c796e18ae9be5046c567c2f9f31edea5eb4 f51b804b2b4c7047e874db85fc1f827c78facacef789bba5ae0bac362a8719c3 cefbc7087a409c7bfeaf01713590ab8ba8cf200f0e253ee24513acadd14eace3 5e24afee28b5670695148232ff4ac7aeb6d028430f7e52ec699bb8d2fa423543 75ca63027ccfa35301adda5929b6d34db711287e8c20049f04682940a2574cbf 6d028deeb9f33d1e2dc9a7815aed9d46c8bc5ef5a24ee180c51b992d02447feb 0b4862a56199782c3db8d96e126b52966d8857c030bcd12bf78dcff477de2dee 6f5a8b4bee8f6d5f58db280c52b72b24011168a95f856460018c6e942cb93018 a8866f4e5582371713d07a92b9db45fb32f27fabdb45fe78b71175af9b9abb05 f9abffce30898c135700ac2872cce9820f6771733cfa615a271529c04e619c2f eee59d2fd563cd83bf665f28f327f28f2236e0d7c72e034da73634668014a050 22a58e501959e7d96664eea0a947f95643cadab389bd257649bbcb75e52b101b df4b5654604c4fa3b69a9303047f39149a9ff62e5294ce1cb9f03a6599128759 892b52449e8ade9f51e72afa4d16cfd61025a0b852b4aaf0b62771ca4e4d1c03 e922bf917ec5c7181a864a2b0fab689c90593a47591b3ad0ad442ce8b632aabf 09622f5fb64ce4b5d67a424a280af79dbaee60a557cada15a72045f27c839617 791107d5f62b4de6c11a38bcd84a836ac5799cdb4fc736f1f5e14f8d4bb56d9d 3279edd7b2fcacab9810ac647eac12ce8b16994829f283d3eb83f8e13a4d1429 739d415d0f7d8d65675ab5dee02fba52b22baf769fa331477768e8fa21341d4f b6bfcd65dbdb070b48930d06a83706aebcd7be61fd7595c8402da87f09e8303d 9007464c9c734c561094b29f09be140baa1565ed3c09196f399e82b489ca5aa5 be6092d1c575e39349a043b24d3df2a8e9b4938e8ba67796428ad0a7309f808f 2ab34408c3bacd9bfea53991e4a6e69ef5c6bb25978bc25f62244b143f9bf52a 76a04b6675637ac67513c8e6f9d89243f059e3407a7d04d534597bd0c7e46897 06325655016660438374f04b5190d361b605d30a2df103fc4f1acb7e28b7e6f0 5f3db63b41e7c2789a9839ad5fa73abf78d9ee2a6ed7fffa7ab485ae0b1c21c0 481f3b51347b46eabc5136721c1edf697febbaefadbd1d0d72f8f792de0fabf0 a8fb1a7241ea84c5e50739aaea6761d538a042bb33341adcf37e088aa1d51477 10c28dfb14d43cb7914d21f8a5875d6825d44258b8cd578706befdb2bda02092 5fb5866fb47158c2a5bf8abcb52a9c53a2d4f9c0c549d352394aa96b79e406ce d3c12eeb91a1d62781ebb072b272ab1bff02d2fc5c0c8f2af0db54696121c282 d7cf291e972479633e7b3b3c6fb8019fbcc26888e6048d9e78eb63058a5ea47d bf0a952706bbd8adf29a83b681560fb826be849ffbc69d7fada22e90fe83f9de 83b805751bcde4a3174a5f6531efa627a47b849f702d6e7ff871ab792f0cc818 c3e23cbc18a7aacac51625ba45f180e4fac85c76df506553f5c1864fe17c086c 3abf67694d6026a2cdc3ac07aa3281e527594c551319a2e6d9b257b7d46b58a1 382f03e3d26afee7c3f7a8aff90539d0b05521bb3458161f05e472717e050924 1a2dcee09581ba083f476068b6e59c97b3179c2a9759fd5062f6ed03854e6738 a1837059296356f67330d65f3ec669a77140310381bd40b8833038da9ac9467e b786b45a36f1fb2ab17fa149b179db91ac9214a6331990f899b9c9d607a96948 b3d9d31002353f99de917df0fe2a29bbf9468cb39f3ac6f15cd3693b9bec9500 afd4d04039fc38e10cc42211f091880c106b4ee88cf223d674b72691ef04f0e2 779fe4986cc325cf9d43a81527667f5477bc6b0dab67b5deaecc1c78c3b41228 6967bc33b9751da2b33cb217691bbd5fdbc87db54e360c236725df760271a6d2 20b279076b9092772984b180cfa0984e2ed6588a2c970d6a406b2773170a25a0 26109422f9bc97fb8374c815a93ed9634c8140a8d0e14975d7f1e52b66580946 7eeac26b1ba8efe87bb115537a60ee5a2bf6b16a269a518d7c60c3a17b3f89bc 98e996ba603332be1162e011edfec5b73a3a6184918c34d81a6d8b43a4badbe2 f92c62570ca18eccc7778273b29c5c817e19aa5559a5104cef66e4e89dc9ff9a 96ac32b1c4d83ef670005b00e79131cc3bea1253d5c082475e6da0b399b8ec46 13bae2d12ee9264bb9291453cd7019a57958f502960c34e42017c13a0d428ca8 a344ba1158f690728f90eff634b62ef5f2ce2b8485e7ec9eb3d523df9ce9e20f 540926e4afd31183a2d64de8c688960ee63aad78f8265810d24750989af3703a 827ca48a9bb00510c9c89c629ab3e7fa5870fe2493bc6e07b86390c7f893e91f 7724d7adaba57802ed1509ec9030323f08e6408afb4cdfdc05655161b75e1525 a21c61d032a71dc127b1677cdf43876169493bea45add0649cc9d059bfd20f9e 62ed1053385cf71c7f25369a405d4b30b726588341ed822fab9949216c55269b 0012dfb8eebda069b6b178448c062b01df2580dfa68356ea9b18c466d7c21a1a 2b87f48472bb3c7e4d2cce4ff0cb1ae568db0c8731e6c368252a791bf83836bd fb4c4da5dc1f72661f0af5db7637f1b7940d849103c430d63968c320a02eb9b0 9c52d72249c8cfb3821117962383eda8c12b6e3f8d23986ab4afd3a488437fa3 d2aac9ca8f90feecac1c737690c26d3b3ca4cd90841001749b22b16bdc1e43e9 0392f0abb11ce9258379706f9da4703e71454fc7d8d67536b1f607f207751b32 78a67470664d2bbc9b352cb4b14ef9009d9e90bd4cbb0026803d1968a3cd1078 d3c46ae28f78b2aed09cbc451d9923667908a5d43a8e092b630ee4be84394500 89e4bd7046c2f12dd51effb3d2c800f3ab40ea4da49977c1d552a12d7f8aa959 1989bff2c64645d0364924db8586d990ae186ae9f313e91dfb4b3b70d05c8f93 42a1b41f6cca4410e04819ed22f20c9182e7a9b9bd7e8408c41a2eaf48f1d192 35b4663612712abbe565843fc2c8761a1b3b0fff08fbaaffdeb0e3a7f6853638 3daf4ec635bb2e54e527afe6df275c297f7fe217724781c4f8739ccc9c9b2fb6 5afe40899e4e7b817bad34de512ee2077227facc7bf4d3af21ae52fd13526623 b0ff07a6f55a5b48ac6112e029541eadeae416e99a88a2805f230346eed89629 7d6a9122f5df8c327f111e1b3bb934067ef9d0070c3e34681560145cd3544e61 bba9cf327cbd4ab53e16379ff673f14ff209e9f69fa78507504290352b22f1e0 09f78a7968c74f519ec07af117b5937a93445fd1292b3f4c6c048ed3f2ad473e 4cceabfe35704957d8d765ebfbb4b25e7aef813bbb69918e328a82ccc9cd0ef5 4d072bdb1e147c44696d3ac42708497cd14bd5b2053c4231e0f269ab68801d38 fe2581a5df60a4be668cf4eeff3b81b1535b62a8a073663d25cc40ae7e727bd7 201d6fc7a1d66b80f66b2a7e7461ff48c2f7f494ce75cf6a8fd07994315c7d3d 4aacc4df48cb39506847e47fd1de8aecd36644ea9a0a3715aa6410f90bdd17cf 391c4953fe0d607a5fe0757d3b6d89f377eef9472e2df092d84330dab9032c3b 7c0b6f25bcbdfddef802981b87e2d2602e796ddfbf38c612a1ee279575b473a8 7d918f300409fb5498d22dab33d5fabb006e03884a8120342e8c7de43a0ddb41 b472faed5d81a2ad3b5abad7bc4254a17e227e6cf61dd85f808343ca66d04dcd 56046d829e429c14ca5bdf58c1735f9ed29b23d82dc82b865f4404bf2164f78a a777c375406fa5771e7014fd9c7f1195047cd7afafbfbc4e90895f07b25bed88 2c8a6d21d61e1f11e8c4384310f41a6d170302ed1693767879280e6d26a2745a a629e4931c6b0932c982fa5204e98907abe2f36060e8571eac9faf4214983ec6 26b14959b10a5fc133763c1042da576408b7ef0722e74c7c990771ecb67194b9 33c948c923205f23965294543804368f8d60f355d0b812d7ae49100ac3dec0dc 5e334c7ded8a7fc203e7b4b7e03842582d3f87bc6d2e975091c5b1749dc3afbc 9ede74c0b6637781bd4d617a1ce397c5c6d985f56ae0a3a55292139e636e343e 397a7f6cc7cdd493461ed52f39dad6f3250a8463472c95ed9d549d6d64c934dc 0faba779da6568d7f50b60ac6c02ad0abbc93f4da87aa61940a159b4ae7f96bc ff1543693433d98347ca081f5450abdaa0cf029ccd8654b31920dc8630feddde 333f205783f49fa3f0c93d9b97791d7d477a9731131559f998bdfe978885604b 1d3b152f9ab2ede0ca97f01ae350441b4aab27bc99419b2b65a499785c4fb523 67d42536c5b0cae6b6613aa4f2a9655fb108a1cb9c741ec0e8acc47b0f50bb5b 0ac2a1b9379b4eb1c63d742bf7789f3f9ebac237ca1890cfd527762b7f24324e 8ab3bbc165e4d338e6a06221aa9d7bfe583a02ea4e411c5712f7890e87206362 2b570b3e4505e0c909b0b5c8516bf506c47f4a46857255536e9ed48cb668c8f6 c88352c9f9f561fd50106608d456a26849fc9b94b9b6fe630685500c8c0a9374 2909dfaaeafaa66a84f68336277f17295af6f389bad3ef74fa3f998fe1d7aabe b59fe7f21465882cb99b1005442917cccd40b9991f9ddd1c0a5caaec633e2a7b 0af13e35bb870c074cfd20e6488817842223336da2ac422534a4e47b5096e14d 31c21003ebf459dcf7d60d87619e953d60cbac7f3e56a3006f783d7409231169 58bbdc210a0a3c9e6d7a6c1a739e71385d260acb26caf1971161f1ff129cc850 a0c1fea9d30b676be2bacab78a0a803cb91d0d5b7dca34e7414b623d31d760cd cfd7370b09766f1129c6f7154fa9173b72b15492c96ff5423112d81aaab345a3 1c4adf684aa1c063c88f48b6d755b6ff3e234b4abfaf11e669b4b049f3990ed3 10287329dc43f6f23651cb0b6ad8cf44a733a6d62f5e3bf0bb564f9411b8fc53 eae584bd1ed75c877553e40e71f0fd3368fcf5ab466f60fd51fdeef2f3163ad9 20723ccd0d19029a89eb5a705cbf37c67fa7482b2b5cf32b269713f9e82df0a3 4b435f890fbec0afa63df7ff10216141b4cc91f2ef43e45960fa369643490fae 3946de1a98c9dbb03306cb44d1345352df983c0ee81c599642037ec826a95a73 81f7954e59f94dab306d170894f26a64a3ed794e58da478fa4b1c97d3e7f702a 7b17975da7e5f925b7c00c9e49ab67c1c05fdc84ecf7c7c2bd9052fc1792a993 c2a95abe1d8563d55b71d31539718f81588180dbc1e7613ced3cc8883b7a4ddb 4151bc7f598d8b5f51c06994350ce4992cbd5cf5f0af19131f2eeb2930e0c2a6 e6d57d2471095e9557746dc61e51d13d23a13a39c21cb2f5a025e6e57d955319 f6948af76dfc38f9f369132e61275d3931f73cab4be55e0c74c26f3ac06f25ce cac3b7a21c358d6bfa6b75afe0ac3ccb00c8e1e42c1cad83652d21f687953df0 7f80969a5e9ae3b12dae228ec1a9705e9e5cf8822df26f4b2e01d33d01960ffe 7f88d5c21dd827ae7133e3685fef7cd74348ede6ce206f77c48bfbc3ca8d9d16 0137e2fc4336f7f6e5c58ac7de684ed6fbb80b94f9a566e462397185a83aa3bc 4e09fed75cc9ac94c945f26099179285d323109b9e5e6495a5fe70352b47b23d 014decd861cb19767ad2aabb1df2a1a9c39a90ebfb0f9bba99336101a3caeb04 6a8e6bba480e9236ff6d502a670c9c3214af2c2c54d68ae26373be3ea9f6ba54 ee16d722d807012e9b33dc391fa877d6ff8b4c28d8a60bef98407d595fd84bea 01c76b8e1b6a8bc8da70dce6e764ae7c3a5e84299e5ee08cd549452e8a7ad5f7 7f9dddc19df35383423444f76b977bf5f9f8aeca8ee4d12b1c2d47050c4865aa e31923c564f3331aca4266e02a02fbb38082782bf920c73266dafcf5c584a938 e9e1a4257cf560e8c93178a567c31cc5b0da317989e91fbba69e19fdc144a850 d99b31b583a68991c6a729ab3e014e8efa878f4d73428a3e7837b4ccfb7ec34d c43dd8c6692eba9517699c6ecdcb4addf074078005e66901131e3a951c1b0edc 0c4adff4116912e3cddbd8af1e0a54252745b18c8069f00848c86fcaaf1b7aee 71435bb799f392c3fac1d37fbf25cc104123c4200deb7027a25c83f14e1376a6 106deb263504c267e112d2a5a0119a2c56801262370e5005798474cef408ba50 39287346a77fee5f44ad898f17384b4f8d6fd9f579ae9b1a247c0092ea61a459 2227d6bb59ff0f8b917decbf5da7fed3e6b1da14d1acff753c24e8900dc37e74 2bb4d37ed8a566931a8b423ec83989cbf87d6c95be7348060bece8b781706a01 08092eda20bdacec2c77841cd6cc4c5520f526f95d6f0826633bdf037d9d4113 1c2c619b184d8283b6fae53673fb2b157236ac33610eb5b83071d2ed211e0ff0 8e2cfee0c3e50d555312177c397f1f7e28c137f8c66adf4480320f809feae542 91e29a009e5a842cc42d63fb6df9c01d2d166b97128e9e30747cdd6bcf40b27b 015e3a83975191cee58d69290ca0bb424a728c4016bf7d7a8446045f3b445038 0e1644bbae9ce4dcd9310271cdef3f5a1e50dded3fc252ea67d4622f6cdb3f59 15fabd6e07c43e4fd09387cab79bd79d2d1167254e03ea4b2bc14a79d86d3d73 334c7d74257b32240e6cd3715e5ccad9c9854e499e2a0a9a965b05e66a158c11 931728bb4e71c9ea18ca56741a4ce91611399a12d55d24c5e926d860c9671f67 e8f5006539db80c08d514de53e33c196fedfd6cc69d25cd854ec7e620689f605 184a126faeaf6f5a815c95c47e9c04a7944eb0bf9a333ad1e170cc214e0c89de 30243847c6842b53d49252ec2cb97d6ed6380c6a1b51f38aa5c22734eb444af4 4fbbf2cee95f7dcec26c8dbc0c6cd3933761707f72014b23754cff935cb17bc8 9bf3ae0a3eac604de96bcd6601a8c7cf6e4b50a0cdb19564202c56ca566f7e76 1db713ff96be67e88510ada404d59b61cb72233bc848a67a49218fa7eb03c580 11e055e9d596101236c23c1ec2547d92d43609e34f9df12b5921a1eb86d94c6d d2577aa223e766db511f51c5b2e682bcf7bbeac3f1d62688676eae35d0676a18 94249cd701e10680522711d48a1c700f65ee7a588eabd3d14db6b00d3b0a883a d3565a2fe13cac9f6fdb94345fadbc56e9925d6f4e23a724aad18f2ac389d0c0 e76aefa00ff29a4f6b79828490b0cf6a5f1d80ba4b6a261c1e92db2ca2394f53 ccafb3c0c1bf893669cca0d35e6cca664e3506dfeedbe2e9ad03118c97101ccb 2f93eca42748aca9b75b35d4e93605dbeae6899aff2243302b90dc708b619b91 9c5f644fffc89210281ed0be8025d6f26bc199f6acef6c7d540db9074d22d480 73d571d06399b629e06ddb6570e0f8c2bbd1f77e533ae6299f52d41a5f7338c4 15ce90fd29a054ba8b0b6d055618880b09bbd224a023ea05ab2351fea9d803fa a989382b2acb0beba1b03b963333f871eeb5d33d3fe7458d5070ac2792197585 42f972b27b415208048a2b9a889b68da93265253bab8e0734d669999e1aa6d0d f26d0f678d98edbf10d7cc58d02907283cfb4af65ee711da72d049ca2d45db46 bbe344aad8977ce28c67cb5a68877a4d7c17f386a04a5c17616d1180b46e02bf e0ab79f061bf88fdd6779df98d9dda293f3d2795aa708a2de6490ba655834006 88c2506e0a3f6e896df79e698020e240452b32c6fac52bc977b25747f19f64af b4f594a10eede8ad967bdfdc073119224909381b7dccd689adab2fcec0144fde 397a775a0664b932a0d72a7c98af6d08319dcad3c32db270120b0e277d79a3c3 7d63131afe8aea760a530344ee8deb6b7da613e3ddab7f85c3e1f7035769f782 8a71c81729b06a8c8627850015e8d7561040187685d648d0e4099ac2dc090836 5d17966c6bd9faa7cda178016d03b4aa310d78bdf42eee6de5dbf5466a9d6c58 9791a2b9abca7e54d48afe35fcceac3910298b64474e867a3a3a8593201ec83f 65829bef7805b4703ad88fc1a7cf848b38c3e40c0b16a7b7104bcd0741403e56 60512fca2ed6efb77f8299b3b33688bb3e81f71265a1c4fbe1abdb266ead5057 2021516ef3799cc02c7a956d40f0efa1d4f95ff405ce8dfead6989b80b32bdb4 8fd4b02b418427901456dad0cd1ca52671894ad62abfa6f227ee2fb62538aa27 1be3f560260be66bac669acbe18472ee86b338e045fe6821d0de255ea839cb09 d5ae308119a926b3a4a359e0114ee2f938158c61f484dd750f4489cf0e535e10 e218771ec2e03708e7f885f14d9b233e1b7a7d262c56d4f009311a2aeda0ea4c c01c9457d1ad329799a61fb10620f4c0c0b500ba26ff7cc5c3351f1ce90f5b3b fa27dd75891242297128724a5e0f2cb0050f3952b21c3028e29be67af64d7747 8342bfdd59eb7d54a07830ae4d09a0d15064fc19fd4f174427cc33e46d8e535a 0ced66b48f6efd8b0230dd1bbd8c5550e0019d8def29913096e02d39292961df e98da021b8ec628abb0ecc8a6897f3324d7680db16ffb46dbe762c30779e038c 258d59f6081f46450745f0f7c8a5fdb41fbb4ddc0a0149ddc267630c2e677d9f 0f86b6e98a65ab1d035e0fd02262daf83b21c8ff9cab3cdf7afec0c43af3d1a2 25442f835deb1d4ea6333eff39668c84a94e30c57298169935b5afcfc36d7adb 303b1075bc6b497650521361175962ec0385dd87bf864def6f575c2adc3cd0a2 8ad76afc1d698b50abbdb1d94a5c86ccb49b17d49af4d36f39dfbc66ea953fe3 b5218d6cee39e1d1a74e500958b718e406a89c7f468754a744ffa8a39b54e8e1 fdb05ef89c3a19d21e8bb34783a60888a9be53e1e7672d1a3e6f5c6cda4e7029 1aa8d8d92f535ac3bcc0af296a3ffb2c977953ac1e75a25cb65c4f4456bf5ca9 890d1506854a507ae800a7edefe094979769b1e9ef9e376296e7b328830de625 7017bf0e6491806767601a30572fc2dca74d1de7cd3e0ddcf42d15373a04bc8d 71c0cd41b5e501771a72c57a6868c082d4076256afba7569814caec598602f27 376b3198ab6e5849451279c39453c528081337f80ef80e882e954f60b1410600 22 92d9e5b11118cae16a1bc26cbf8e6f9968920a0254c3b2c5877db6932ceaa20f66a9aadc5e070cdab52d60b41132087a2bc1892d8f5294515c595ec5306c68035378b35c912f0dddade9dfd15c93ce31aacfe54c61f8ca69c8441897ac46370b9dbe7e31917c7235b2b81fd805bb907677a52de7a1a10db66bd5b0fa822fb1073c5894288e20a392c5e3d0db38f295917f71b0d98af0786df5392169889ad104ac1bfdb0a87c41268fbb66995d7f6f0adc60f945e70283c2ea49b8eeef38b4051faa9c714b412dd76c2f7ea358d7637f1c295ec920e7630f705ba7f7373fe50b82ebfa730640a9f28b5136d14420304a62f19187cafaf131aecd7fd3bdf1eb0eb667b357b2e0f97a7bce57bb99975b44921c3aa43a23332a0babcd73e4365308cb3d66bab782c87ddab879ba13665afca42cdfc474956db57724faa7371cf90cabaf45e8f873564b4b606031bdc55980811dc78a2094bff14c28199403d57f0640fd5cce993495cc33ddb536d551af26a2af7912a8d93489960c2eb349df970a85e2f7f261ea564f03739ef54262203c36ba258948dbe4941b7d91ac075e560a148e003d9aa5839d2d4e17da5ea6a026eee750de02a7047b10154f30ed812407993dd3ae451da38187863c025e0d3a8f0ed98b20a1200c355174e76b46e2d908b7d480d1368262f147f71cbfd8f5e723a739677a316b6d9322cce582026b1c05d2a335ae99c77389ad718df8601f70ddde0e5d323aebfc709d27e6574193a00ebab62c02fee131511399a7c06ca2c630616aa1f626feb21a0eb98a9de5d471076fe3b331438fa57f4e0b84fbccc55b598874ef3e85bd11bdfdf6b15353442a09f780d182f57595f7f493fc9ac06c458d8a7f89a19e721e2d5f1e721d1967ae0f9b0756729ca85252b80699d68190879b0dcc3bedd62628032b5df0437b04ba0ce941f1d40b98d3c51508b6007946b6c74686241369caf65df71fc64c970cc503e9e09d2069a8cb439db5c3397e4dbbcd0ef7fe8093a2a8ab28fd8ad40412d3050ea154ae7995347014e8e2b7d44f5243092155ae20cc1b7079ef14b970d6ab068aa31719f15b87b524aad0f62440396e3ccfcdba087756a3875ad552aff1290c23e5f4060305fe03b4d492d0373a2fedb9484be4184b84471b5ce2aba441570082d6a4c0113e3a5361666e2ec206b3ac148d7b6482bbc5e74fbae3841169eb06496f4b5f529d78fac4f1a59f575b5ba3fb14279f87d5a37f78d9278ef89a5a05792932728e7b18c071827b9559f5d235486ca241b493c0e565fac373dce9af00b70b72afca797e9eb1300ad9c8728f48045bfe249a1ee8d9ec772dc5e99a8000041605e39d17ea3b20b2844e0efaf113f5574092b35da1e338aacc48c5dd6105691990852e49b5052c83821156ee2f8cfbcdb30c7d95d2f2af56c47f67a96a028955e7051907435e74216e0a14770ebbef577155afa6c30d881df0ed046252042c7ba13631f01d54527ec6cc2664933b57d7bff192066c9aaf9c53898695f70c2069adbed7a8ff2d8531f5a2139422794fb07ffd9c6bab272b322925a4148e08f3dc866d6c34296225cdc71cf328f04119c468e73a9be25d6fe611635ad62e0719b9ab36102bd1f17d3e70f80ba7098e146d80a510b576f5a0c1c7e21c6f38046543f6d0aa261413de0199f12ea05bf03f0412395e91c63a48485845e362360fa5d41f56e746084c8ef2c6e6631c2f938760d42c18bfe8ce2b830701e1a3ca09a8493e9a7dc9ac1db6e2c0bb8ad6bb5ea0c95faa2dd81e563a28bab999fad70735c14ae16d5e117e7e31e0eda7139dc3f3a5b75f78cfe2a898ff148b67a99c00740982d7425b45b2e572fa458dc5c965c5f3551b3a89ecb2b281faaaea6d320c0e9333342bae47309030877b42c6ebd3f798289ad26560dc2348637122630e0e39797c36c61d362444e3001ea8c214d6e343b15b0b071e2445dd8374adc6790bfcb3092a38d9f659f49862f5b4cc7e6659eec3e9b2396b64c3182e73dfd3720a85340d4462077f2d2c87ecff60523e8d5c78cfd55bba5ff34b738574e59e4b08c680e37dbc3b2060459ba126c845ba1b0a14d3185a06875a596b737de3f0ac084bee93168d5e6a7308c8b1debc3f79a94f374110cda4c3b367fd500401f6e50bf20677c99968b8630258e19c531aec38818cdc490e1790abd76eed78194fdb078d4e3327576cef04c1e2ebd2e8ccff0669e305da2d76387de39f0886590cfe02aeb9004ca8702de77a68b87327cb5baccbb773350617b87c853baef120a41e0bc666e3c3b50e914195085ccda3214dad2b79e2a855191c6c2eb8e50713a108092ce90c7fac40636e542c1957e97ecd5d83a5db1c56d4c6b09dd1d0e880c97e0fcfa64a73c3394fffb771ffac7b429ee67b97d81d041975f9ae0d925800a5370dd0cabb9447631c59067c5656d09ee3badc392c06963f817317a84132048d1100f833db1780685eb559d8b88e804e597d9d3f178eb46f7ea3da4980798291560fdcda32f5070f1f3462d1fba3b8662955ffc6b1249912a84519ed6993d1d5920a459c587bb6be73a73dabf95e3cb87f608ce8ff0d26f62aa02f8469c284f7af0bf15dab84d8eed10d1152f500cf24a358a7c52f703f078cd5fe9fba6a328a3b0988ab8d821c5c0538d14224a6829c88d43194254f8447ec922ade8aaedac07e03939440b9d880f5b78bd216df10dffdfb4562378fa48ae2a9309bd887b0cb1d03f995828e5eba9fe7e2db66da3322b19f035b2f4c79f995523d5c6dadda9ba20ba1eabce9b12cd26c80df1e7724c96371655dd0c5772a0a652e762ba79407290dab34b4331aba23d95dc8b61eebc132eddca71e16f9241b6435906b97e4cf54084977bd6e420fcd253edf6cb11ec2e7aa189b3d02163fd94c3ee64552f6c9230dd16639ef54a3f205ef719abd460f6d4d6667eaae7edb6e87d717977eeb950e04a3eae2c2fe832d539ec3ae4de06cc8bfaf2054597f56623e466190d0fb930b042bf2dff9d73d31b3b8b2d6a713495248597fd4362245d645c3248dee19a5970bc0dba8a070cab0a0b478fe2053c4faa28bf295baa80688954250a2907f8db20d649ed40a435d09a746822024fa785e1efe531a77b60369f32322e76fdf517d01218ef14fb0035fa4f663cbac04d8b78d314bb0d6ab1b3e7a53a7f760048f0c069069188e313020720bbd60614a5d68a2d0805c64d73d3762e44ae6a7b83f79036e1025915823feaaff5696db8cab673ca6ecd4707386202f2d1cb68016b0650517f7cb4fcab6f58bea3c53ee72d245bc6e27075aa2027f020f976f73f76688081ea64d9ff6b730503800af08ceb57529b0ea04e07e994a81d5a4b9e51480a10e08326a66df552b572401e2b2f441a67f71e1fd0771d204981d619351ca0e1e0c0d41636e99f7e3f3007c8fe8b75c0b84e2756b2b86f7785ce81edd3a7c75c507f46b3a6fb8b9c993225254bf4f848f71121baff7ee788e808de4e9222282000cd2dbce4ec700c4b572ede4794dc4ac19dbb0181c698134cb06acc69c0f6abd073b9a139e444cb973a7d0b1954fa10286c28c9b7847d831573c2c247be3ebc9064ac329185935cbf456a567bc6752c8a86e5d89ecc2e82e4913ea4c73d4fe9005b65db02ce67ae8e2080362c4e41bed6228e9fc0ce4095c3290650a053ecc9c0404ff3d1799b999470aa61fd44d06a60c34c08ea4705afcd7d5b86bda1cfa57070ab4c723ff193653c5bee763d016b952bac17ab62062bd60bfcf024f5ff92806eab845e34c83b374a37d962442784bb061defca3f86bb92d3f89fae544ea6f076f15fa92be0903d1dbef149574c9976297e5f0db8c67a2b380c4b25573f7b30bc472f90b8deb89846be7e4458356c5c65a97008f34bbbbb7101ac47aa75b9f089755a98602a5bc148cbc882783f4a9c72c5ca4a9e6209585898497b1f7488200bfea01fa829fb56834b0e0944e4d3491c56948447e038efb74b9530f73205a04c577a85047bcfbf3f870c0c907e9fa279608b77b1761320c075dfb10e837170764ff8ce80092e9a4edd49f578e697b14f38b675e829ad1ed5312887c5d644707a8d5f8784c1b59a6239c6d155f12b82d08dc79c14b1cbb83476ca859365de00e9553c678d595507f2aaefb206e8950eac162d40e342c07c20a2b3a3e272a720fb82d333c3e66aba6411df3a35f3d1f7e2c2181901aaf53872aec11b4d2d678083859e17b45758983b2d3f6d2c143c3f5c40250428a3d5610d73471884a309607a5ce1ba1db3ae9a61ee61b992e594b66277f7172dff0a517c96e245c2156ef04d3b14f2838e9351ff58de60b80114ac7acc6cb66bc3a7d8285d5fd57bab3fc08f75b51697dc2d3d55c017906ba365db248774833538edb58a3a9031de8b2150b2cb1f8f9c8aec9e7514e0bb38fd7e7dc5e429f4d10d3a8591b8d4200a813e107f08aea7cb9539c59d03ece09abf6997de541c4e81d0ccf68e3058d5849fdd6038a6e0af5d7f8e5487997b62b5c4298ef4c1e7a99c8acc37ae898074d0a6137049cf07a1aa9004bc2600b5a239d79048b835f86cd51906a95a4e0a336ae5a330f1f72f2f1c14b9bc192241d78afde9b8a225bbc0a720f468690ddc95450e1cd08e026d96b15011a4b03a514c66687aeaa0c13fe27e3b21ea3d04bf98bbd088502b79dfe29fed5f5650664223344d3812906078576fd9143e31928847d513e2a0ff47326e436baac4a794f1ac63d8657ed66de24c852d6e7db6f548ad4e1b8bf0f2e29604974b48be27fe24034f8609edc3a481d3b298b4bc5dd67e5493258a80a667e230413426e0d82f6a29d240977fd49b506603bb766643f5a23791a57c3093b5aad541b63860cae683927e6c642afa861403d106e55fc1d97f5ca8f80590d6da2cd340900d6ea679aded9df38c442a19501f24a4ffc4ebcb8cad7cbf4760bdb4b6a1ec37f60ead4963aa29cf94a8a817df929d39b161454025db9ddddd70362a33d3733aa874f0daeb710796b67d898064da0a20e8ba0f69e21fa376f220a6462b340c0e40ddc53357245ec302f85822f65d839ab7e3737876f2a488d5b0ca65fd2be689044f32ec0376f14b1a8e991ba8691534f6ef03708670033beb00e1c8cb1df6caba8886e7c616352bfd4dec0f7736dd60a7c9572e1d9a75a2b210029bbd260ceb701b099acfde721285fb12c0264873f43d6d22bab3e3acfb86706d51db3b945b88cc2bdbe7f79322abf30242e551c588d53090fca816f2cc84a05149ead4160ddbc28ff63ba1db4e1379b534653528045fa03c329bf0497f1210715a37e457b737a053bb4bbf79b8467c4f08d1a4b710f26c450db42d2ea5cff03647c8e59d58e92ee4a069ac47b2a2b417a345dffd439e317f258219eab3f4b08ba431e34c9d7a500d188d827eff15effb5adb21d393539dbe558b3917bb30b082722fdc84249d1450bee8feed23b350448c9c81c3a55b096c165468f3edfca00d52c67cf526ecf33935770cb960cef064b9fa5daadfeecd2071a3bb944af540b776b93777f1511db5bae6777180f2c950ab7156cc5dc1801b4384ab57781090997fdc8da59c33248fb118f6f0ce73b9f0d704a037ad7f461a0f41a55174f0f02445325e596340a6d4eddcac5cd7611b561f66e899cba04b555d2397275c0fb08d61bb1a125c6aef7960495b75016937711df3f3cc0988638c1244f256b307104283ef6e1fb0ae4f410a2c008cbd11f7c83bc605f1a944b7d55732fcc175e5f07f61e47a48f7ba75f56af869ec4c35ee8c6221388a6fe8cf903a7f8222673010866fcc59f17a45bc05bcaf8f9b3766ca7eccb9b6987aebab657694afc99208a03faf674db9c9933fb7f472401e2b0710516c42cf225b4b92dc9179b5ccde34f0ba8eb0100076d1f0e4985eb3899cdec838d2b77b211077754a829ba5b00bab306192bc41e6c54f6f2a9d60adfb2166d932cf1ae0e1342e3e0927df54165dafa0ab2533aa2cd9161453ca0ebd2c3b01c8e84699d3202c5e366c6e00af61f9b1108e75897ac1c112ae93f583e6a400bf8657d05ffe4cb3a2ff0da2bf46bff35a1039a14ef51b95e8f69191b66ede5cf9761928041a325e5b005165947c4c03bae068343da0b8d6787cbb76a210c6993270be23f9bda32420df5ce92ed71e1ca5907ba11d83d6f78a4cf82ba4bba67f680fbfa8f21d3d21542c1a64d096133b50a0263c13e3c9a0089de524433171382181a2382bab9b843c4b6bfd90fecf2558e00051658a22508c135be89e332ff4e9501f859e83cd96332e9244fa4a03a0f8e03d798975f109c75a588b5d17bc9c95e19dc09f94d922a931af2ccdec06cd21c0b2739d739bbe1db39e2da9d6ad72042eb236ad1b9d6c9cb7331e15cd81b728600a0511670c8f1d0f9498e36146a8bfad5bd565ded10c2e4350fca85e19807750ec7433f0862b35e7136183e5cadd1bb3789fa9c45c62f4841c7cf6cf8ac1b5a0c466909467fe3b1b22c7fdd4c2ef03ca789ddf4eb18f0a42c3b4454b280d90100b3216cea185191b2697e15c38c11816ecc530b2cbb067d70588c2a1a469b460865fa32d45b876588e90d397557a83a30ab657b6e7e97478fca81e3175414e20d3f223d3df672806509b676d369bf8095221d2e83cf05852887b8562f27e85600a52534ece6ffec518585369e603468a0bf0e5267291dd2d2f8e1e568aebe2a0c9dcc608708066c80e39112a5f2a8898f8adc590d9063a851d1be1f1771d5ae01aa61fb93ef39d9deb337c570a3626a2f3f4931365376a56743a22ddd35f47d016e12bed89505a3db2396c45e23cd1dfb7adaccfa1a25d9d6afec6a6d1c10df09ea56357ee470be6a4f5126c638db97c4f2a389ddaf883ec020c619562f003b0efeef365236c9ff90c259d2cc29570bf31afc3d39d680a30dc2551f6ceec9d607a973ed9b8c888a43e77edd806ae982cefa1cdea0a0308946627767595ced46001791e317ef3f5f7c2de8f8233bad1bf1532abc1b27d75d27a8023f8b85305203c6ffc6c0beb7c107c45e032ecd135fb9304d7ba9fc145225cbd26bfcd33c5602e86d8a55948bdba71338d5e2891504376c4993f5c428666b77546b0ee6804b08d2de92c2f5cfea0a0be135979305bfd753b840f201b3d4c657571c787b61680910e7e79063b81d6e23261b62694492ba077eff11b21e24d36b12e979d907880b668547f23450358144c02310a16c7ba2cc3d5ae40f21ed1afe6ec48412bf8d00f8d047ab9e959cb708fa5732e59d826c2769c8d39115acb794499bd720094703ddcdf0b0085a0715c8678df6e17ae5d335df411640de5cd830d7fb83fd8b44092121275dc2aed3e52576953e672bc6e8008408c881b61205d29ccc377431900a863ce783e08854cb296570dbcd915c83278a5c06614f447d56df8e934b5e5a09b1fbafe326ac97e45fe2cfecffab74f64d7ae75e31f750f4470b80dfbcedc703af0ed97a656689ad2253af666e385c04e2254184e294e93fc55459e0c8cfde0f035ae9173b1483918a4642dbe07dc581240a820e9fd87f2e2487c00a52c44c0eaa7bef377453960b8bd144e4a67143aafeb93f3895314bc6eec354665d74c30b536717010ed0e006d614d7ea4f66a72872cd91cf5cbe4f96f4005890ce513c0d342935d01316c7c203e3917cf7a0ad1bf1750ff37f146a94c5015712dc08470b8266473b5ff202a9d7b4f317381686d2d58af6f7c8693cd5b517eda879603105c307c62e00a6047378319c5cc013cfde28950f8b7804e126ae71801fee0a5c00004e7ff8f81b803bfd6f47578e1125ad2db84493095f34ed602297991e3ff207bd54419cd577cb09ae5b6316e25ac1c2cfd4f89a3af6e7ccd2a6f91a187d2d0cd6ccf6e0e98928855bc6cf1e0c78abe76a64d9f300a78b06748a9a79d2832808f8826881c1f4de1c981acacce079bce2425207961420e88787108ceb2254a10db33f7ed9abd936ec22b5fa09103c20864c9645c48f459499e2b8de99fec29407c858c429b2495de220fe24113ad3f1979fb6f15cba254c6bbb452a6b6638f90f8f388018205042d7c26a1385115b6d97305e51649f88415ffefda5e9801b7c0b280127828fc62f771da09670078bd53b7a1c0f7ab483c72dc881c43c59c20b0bf443f077861ed6cd8169ee62b95b0ab5d8fcba335a2e738de0202d7bcfcb8f0f665a25bf643d59c84c16b6de2ab3158a64a56e607a9419936b8bdb316937030576c90b147ba80251ff45acd9362deef2347a46e30d16740b7d6f44263c1c1c0b6540e2983ac304aa152a28690dcf573107989b3c7e72bb0dce9d9ca747ff1c07b98c8caba334ac334c77ac11a35ac3dd042f4a682697b7e21a461fef0f584004b8b77c4f84fe8901f7ef7b1b469faa05e1850c3de75c389561b70e03ae8b25087d60095c59766172690ab5984edc8d09aa26858b9a7515eb67f12c75d6071b061182c4a3db65334ea499f5c0314f794fab84a4c9ba692745fcb93726666702070975c3fbd68abf7d829e8f011821090233e298fbfddc3771c4a32e7789d1870cae55bb6725c3fe23ac65a3021590e3c873db6eb499b13a4a5b9e1ec6c986e70e48008b04e7fe7604aca5ad73680b55515f32935b2a9af9dd3e4929587f65df0de6223ceab75eaa447f1a5a710b6acdfdd84f85ed4555035471600b9e4ec5e404861b299295881bbc77cc931fe0433f5b7f3bf59c247e63968820e1e9f601360a6b032bc837e53a6f362f0de6fb58a2631e3a5747ec8dad4e263b5e8349f2c50019158309cd5f64239982f6b70167bc5091919879289bd552afffaaa14f43030fb924ee73fa988566e6c47dc603e1a6e88ccf2a0a80ed55302b6bdf94a605fe0f32f7ed12028f5de76c9ca6dcbde595222e594c6b93c8c8be341d6c49f513480ffba7e0ac8ed96ff53aa6276702b9709dedcf24f4c2540a5efa8f5125012a1d0361c0f92b7e14f49f7fd3011a5ca3d1be0e9e03be1ff94da43268ed12af4cf906a836a2bc495bb653ac4dbc8c11e79ad34a9ef66126536f38b7ff40b6d725140ae85396b4b26fb72f19b30e805c89f0094898878fc48c926e71c13e204321600759fc9546bf3eb84ccc62e20c1949aa5ee092c1897ec237ad1027ec2e576a9700693301c0b8d4e9e831bc050d1ee8f415c0ce32a24fff5ef50b79c6060f4a2e07785956c6189a19763bcbecacb60026d3776af94fb88d76186d569f6011bea60d932c0b09186301d34c3a39e1ed256bd7ae5c05b3c13a42773c3f37eea372a40e8f189c5aded55276bf1006cc0d0a37257056619f92995f24ac70f6e1d7c4a304c9cca712ed6ec96bae5a17b3a3dbf089dfdca2dac6e23b0b5da1230374c5a10ede5032e7de45ace504e48811673f485007470633b160ffcc0de92a5268ce4904446ba2fd351bf5ecded525b8de01e002382ca32200224e47f2997cc9de7e9b0721fab6ab692e58fe49bac57b8951420774dc85baa0f214fe681d5c6e34d8b6063a64d70dc6bf4245bcfee926c5cf78d3defd7f8cf6e6e3941bdd4cf220f27202cf18f1bbf87f6f21abb7daff15222df52b62856e7f7b2baa284687a2dbf62f04fa376b5d93a0663854dc3390b505001368a54755ed4a3cc91f2564bcc1d63207651def03eb6a2b6fb686a1ac11c6ea08e8f02383b21b0bea3c57051f2246c50de206142f69ad7a051b23aff871904a74f971bb016d482a99c30ac8889d0768010d6d9e94a1ff0eacb229ddcf9ef67b5f54c9c04b3af634e1ea46831afec0e001fee3fd46cc10d02225d04d26b34d9599d74298b272aaa1abbd8a1e338935ea0f1cffb6518a9e7549762f5c5b4addc6576a77302c7ca826d49b517b1947d2cc09e2a82a758d7acc912d9de4795c2bd51b988648d7b11b6a1a221a2b70b412120de8ed32cb44db2c43c6016b3767acf4dc57cc27d10aeeda01a2669bb69c9671078be05f0081a399727a500508717896c24b7d92416c673d24f30336a4841ca60a449e81ce615855b3487386aafd427a87b020c8d35688c95bb290adf336394d0edc8e12c888064c120c1f5f8edee0932374ae62a8e0634188bea1267580746106c715d88b86401ba01b5818c63e52107e24a1239effd48a3afae452b050322e0a30dd158b7d1617e54b9c4f239eaa722f670f1233ecec04d5c223af3417966f03e107ead4bc0dfd6a931a6eb99c2d5d6cb7d9f3797902b06e50049da9e31b3f02963cde5e1d06885c6da542ba65f332e09708a8e3bc2ebd5571e9cc45f3ff4c055a41ecd74a6fb856049637c6ea6b50b7272cb023d805f179296b642c9b22450a285218c637538eda7c62bce016474b6ddde8f3f5a2cbab94dc99ce982d47240dc667433e0024d2ebca00edb6df360459cbc45b8504125dddbe0060f752ab7e0121e4409817f342e283f2e3f1551f3b58077fa8cbd949093946cee5fa0256ac0a2406137fbef3aa02a430201edf4315dfd91ee7f768bbd0ea66e8f35c04d816019555159ad25039f0eab12b2a244b9a496f689426d224c33ea1ffb57b3564a20739920a5d7cf66ac54d47c45877c86896dd96d8b530a9edbd7035c1722069010cff98fedfbe615ab12dfdc89b954d3b9bf0bf8d3fd7bc9df1f7c1dd3688771508f8d4d30d7be6a66116789500efe21b1e92ca03e7b1358291b32de3d0dd9f90031f1a5d6e105ecb8804395cd65b4134b28b2b7d8116118fc8c05b95581a0a4b0ecf90224a639824bddac80460d55ebf8e62917feec850d9c5fed88371708c090ec874c63a31d958df041b9ca37f6bd128dd7480bd26bb33e9d97ab028ba736d03cf471e66634bae963a8c34fe471e8259fb17e6965ff2ebbb279c40a55cf0720b78ea31ec64cb4e9a3242652b016eb308a34ab9b779fd9a3862221698de03380f6cf16e297fb217dea0cb6ac8eb8f22ef55951bbab237407f84c748c1ec6b750ef55677fea0e0b2559b14a367ff06a9ecaa9d7fd4596fc980e4a1c75ad1d0250bc708a2f5505b8f48f1de0625fd58d4498620345bca8952d3e24067eda38cef0fbf70315d79da519acd58cfcdd0b29ac016bf744bc86b9967c6ffbdf7cf14b206516130088b246c0caf2f4592dddff59800e121e32338839f50d0ab708dd01600366adbdc79a39969f231bae6e76d9a6dde4bb01517d1ee41e0c01efb4b3ad0019354130b9cac0b34dcfd2078af5b1ee29e0f7a04162835cc88ee3631fb170c0c77eaf9213eccda45c0ed9f486369d40a989052ad711708d1935388d99212af01c452c1dbe2b3043e8c32a82f868cb4a2169847ef3cdf231c9e5029776e2cb00f98dd11063242e7c3383454acdeabe2f22b824c908cf8d5f3e62070d696390a0c417e7964cbffa03657bb37e42ffcc64d5a0b42ecaf103af00d3df1a33fab10070d9bf58a728c05e274264966234c25a33a876a87b02075a1c7ab00620e6110030c7231c34312960938d9526b3c949ee0534082d332cd459ee4649a1fbdaffa07e2719e544af834b1eec3eb1c64fd29d4e1c49c9e80910344c9f5f342075b2308efa5a3d2e7da8644a1637bc872d2f5b8abc5deda5f52cfbcdd13d1a5b2f87d05e3926b6344069ab238da7a62638abed9cbcbe7751e15099459ca9c874468120d7acde5ff0a32ab0bc631a11a11820f8c23009b6c3d123493cc37d2a111a1620d3197fc09d0bfaf39b50937eee037703d9de092c0724eb6ea761566893317100a6900ec0eec169462e681798c160f3097d94216b0bb8ba238b112e2593499d70de840aa37c673b2e1fdf7b9e654dff07a556ab53b26201ff2eefcb46dd20f040a395fbf2e10c26be9721b08e67b7757827a0a67b889dbd0960decd7227458120847953fdf2bcc35215d3af046bb92142ec4dea4d008d824926180608f8e281000d02722f6a884f947267d2c896c437fae2f92ac73f2af64d900c5b63d9102f50f7aa5cb7974f26f3ebdfeb28fb7792a2ef9f1ea313c5f3f81222a49bd1da0840a0236391a96c281d360e866a5c72e477bebe911c2a06ac338e1c57d4b2aec8e02b8e0b2e8610ba747e7495c3540d2ea35d673bcbe707fa87df23b016d58b0eb0042ea961ed2d75c79d35083b9567e358ef5c069942456282b1476cc4a4cab660b4eed05dcd63f6e6149f290e830d1197e621ac604830d5ee81c281f443d6b7f0db8b64e870f915ef180522381195de0ed5a26f259592dc693f5a835e6f5899505b73af986f032b559932dda202a583b388fbd4e140485ba385e43b755d7a8350508adf1317b6f16ac0779e095bb4fe4397abb1f0e68ade8e37954272a57910e036488be0f17434b1aeb76473d0fa69f4c7b524db6e1943290d57b935ce3eae405bece6e6f469e8d09e843054a94ed848fb34d5956bbf721baa011f91fb4c66207e2c76d7ffc59104022d43069035679855419a7a7984e397edd38289ed536f50c3ff95bc7305bca5e56967136af04d92f11dd9eae0b3b27f76f719f71309b3f00762d9b3ff2bf30db3e455044cd4d7d570ee35872411a40a7939556f965bc030704cb9b6e07e00246febe622536f6a5a5f0794b292a8b80ebdcf95ebf52e00a07a09ebc9db5847e97ee4a993d5f505f90b659a9d0203470d240771bbf2ef9530d27d57830d62e55cfc7d31e9884e915c5b7cfde2b78c0bbbb50ca4401ac6e790878d3296e91825409f2aef37bfc3dd4b74ce5f2784ab829ff2bd8170e110cb10a93c206549033f45f6a06c7df431d4c4c7e92bed0886ef8a9bee5134ea9a68804317f612e0da0f23075b53d3310000648d33dda6aa770153b0a0c04179e501f02de7b76c59b663785e74eaacf61762a7a1cb6b74d7728016c74742cca5e78de0162fa65a69e56504181391c6545e00ff37a622bcc8f013882dcd9010bab7e9f098085d0ae0d80f43301ed3be3ecb7b6e1a1083faddf87fabab3c78851c26974083067ced06590376a3f2b02d300151b8f20fd50387c930d1221129162f025d20fe3c60fff2148f9bab332925e6949cac9ba74ab260813e69749ad24d18d378105021b7d1aed602be328141dfc8cf8ff982dda82a5a96c40b4f3ce751a3cc8790e5cbf929b4e43cad2e1af6245cb700a265b3bec4b61d1a8776020a5560a070d0969f33f8629c5f66489e3f8f90dac2f692864b752bdeca029221592d88e6b7409c3f15f25c5768b0edc343dcba5939f3c94565589e8077713b9a0de02d79d0b093cc4b4ce1db3eebe85eb1a44efe2d31ca2ffd9fd780d6182d0f830393522620bdb771278798511bd8f8eed10209b0fb8234e59f1e68888eb2ada93d10113bc04342c1e7c0b11b7bed70fb9298c351a8d80d35d38ab5e33c0bf819987baea2903b1b723a36c961469377e4ad65aeb950c46f7dcb9d74f83f3540859e64728f40f283a331bc661e6ba172d75d2e0f1aefa8a7ec5a394b77fe75691e40486cb46057cdc2ea549c85fd72c81886698799115b19d689109a9d338d33f817016577b0815c5cb3d44f452310dd20621d45903c838acc2f9ddc2770b2fff7cf1139e2802c13865ce1f4fc2497200f9bb495500c3bc2b9b9cc1f86fd9a9c0af1c8e4a630031c3b9fdef6a1da4790ea9f05b99df5bb2b065590926d263a530aca8c2b0480ab50647b857f0bc80ee5e0fffe473f59a6c6d4b685fadae2a1b7611f719660f0a1f4413a52bd14663414bc0257002d2fa7e2e86526e3ad5790ee3690f14d75b0abae817c13196e5ec62fed760709a3e579b66863b8a39cbb0ebfa063f0a7cbd06eae1df4ed46c98b756353b18af6b7eef296863a3d31d619d34ee80e3953232011a3fd3fd645aad0e9f2d38af95d27f5c976a5816f76ef6e20dc70c80d31733092402858b465c1cd7fe50b744af8a58e11388e3a5708ab3834ff9d3506d0ea304851928b1e2d5d05677015fb3ec4e9beda7b97b4d2586a34840629c26f637e4052a9bf782c974650c2be26fb96282180550a6d90ddab197e9fe4d91952c934c0d87280b5ca14e21550837643977b73ad24d9cb03b3ee618794cd2e5a3155b6a02b93d5c2053f2a17df7092788bcab93a731c93a831984125ccecaa14dffd0c807df6ba0a49cd5d4c0caec4d670bfe168e4d923741367b3f50a03c1ea1ef863b08b25e4d118fcab730177457e73b5cf4faf3f4443c8521bd07a7df18329a71a001b56ea45a1663e3f1f11d8511aa49e15e3cb137254e954b7ca7f0fc610d26b20aec60f8f5ee3e9d462039798c8d0f140242096f0cf75c66232f22a32cf7ec5507c9b5c43c58fce8e4e28687a1805af6334a9a11b736a2402cad89712dac6e440572a993e0f4d4455a6863e6c6b10a5bd58d5d9172fa603acdd3c488bba9a2640ec71d62f8665458e564cb4523c1a895e096b320c5d5f34aa19a048ccab96fe20f33e81cef258db44894281d2c15becc43f0e2a37ad2da905aad7cea25b77d9a0350aae4942be9343cb68633d88f0bdd5ecfdebcdf347a55553a4b97816ee1ef0ae78786d7dc7502f778542b163fefbcb15cdac5cf9c6accfa0daee47d9f6b1b0d233da8e62abbf61c666044dd77eb68f3c5a79eb3ea99755fff33e5085a5aab0ef462fcd4d67f9c7b40ea18434c01390e6d3cda376622a166e0d7b7072e3f2503f8bf57615e0285773469cb6612a76d92328da1a010ca2d0794ea126e80f2bd00d78d02fc2c60a3f64a287de1d5653bb05d2da6f32f1b86b14772693d4e12060ea80457812ca2554ed9e44c8332b80a7383337f81e2a94ef97afa9a83451e38049e9d3c04b41bdebe0e1516a2ab8ca0674c707d01c82ced0a7c3102d0254e77072a3ee20f7271356652afae3208093a7000cb4fcb68e3230a787cc42e6d326d05433c34e8ed59ee83e2d6abf144beb911ae28c47143405b67bb2d8d9084c5ad01b5e212f418fe441b5a353876d6278c135e7d9aa33fac3a93733b93c61194e40688bf935c1ab6162866348fb2740f8e67bc33e26abb12b825d24798319303b400e66adddd953ff91481b7d0c4c983b29e5fc2d373096b87749130097d6e43660cffed5daa25e306074f5a09f88b20fa6bc9ea86615d9e98c2c0a82078eed95003498a2fc1933fc2996c73d82e1ac955948f3e8460947779bcb5257b0fc41c6f08b03c2d4e9f9a437d2437325ba78782bb0de3442c907a27b7f2a7ffc761fda50407d99b7bbceaaea57875e80f26126ad88c8d09789941228a3ec34800d7791906e34f21727ecc3ff11534ef1c7843946469e33d0c385644a082cdf94077d76c00977d380552c2e6629a96cb8793ae9c58a3f88e04312b2760f91ac5d692bd1e0b766a667dbb9771d955572648b7dcca0a75305d3bb370df1e577b291698cfd1073cc2bbfc7ed47c0b84402f29b0634632eefe188e7debfca0cbe7cb48b3cfaf0bc768e20c4014cac3e3ca15da53537c05c5429e04a43060c988663e4fe1aacf085f53f0a55bef34192913942db876affbb3fae1ed5f17e1ebc9f9d353ab1c08014a0c3646e77b5f25ead7ccad33c4d40c75c09fb2208886d077c2bd625eb8430e77477cb5f331e95ac9a8be3c55c2b3d6d73a1eac470434c41d8eaea970138e075f35a65d3ab8ef7ffdede43a840919ff9cdeb17de0e60ed393712ab339d7e9089d2ddfef4864cc21d7ed3f96880e214c0f8ac8c7319ed7dd5d8152075e95da0faf368c7d42a787fd8127cdc6a412c802524fa4329af935876cf1599831c42c051d3f64edba02a5a7a0672f492e5cd248df3bafdc66da693a394a29bafd56cd08e8ff5e0b65c6e46d3826cb2d5534b419ee2c6b2a2672ee1d92b42ce70f2e7207fc91498fa72cc44ae7913f8a6d42e1a2db89deef51c1b41fee656718b82c71081526fe4675e2fcd87be90a1287e71258e618bcbb7db48f0ab80498801aff4a02e2c2a16a5a177ff3aaf50096023b686c547d084d0056b10e49d4fa85864d650a7ea0e3e0a7861c49d673ac53266e9043a6eef45357cd268695f8216e26e97106f79c7cdb585246396d27f3f65a0be7542470769028255c0dd621b189e835080357591250da746d276f4b932fa218964df6227b6b1145868d23c19b4dbce34d001aaa83afdbef5eb9e86714ed8d8465eacd04ae11992f3aa8ecb1ac9efa8b4206153255d219812b70490ef8de637d6dec98f19d87b330b614fbf011ee6c0f3a02ad49d1178157061716615182ba12c949d379991bd6eed839e105fb88233d660bd20f42b5a1555298475c0270f2b7b47015bb29585442ecc71e7a929153ce7e004380838f0c02a7d3e06b6639fba7d250e1c975d89c1cc3bb38d0b19845d6e504e6ba41fe5436090affbddca7707fc95f60ca3955109bdc77601f06367bad4c04f4eeed9fdeffb79cd8e36fdbb3038c4c624715fd07a48dcae04356b577bdb60dd5fc6d0816a9cb4c9c7195d88569f4a6ba4b1f62dd2375f7add1b85dea22530937b9dc7ab6169a0c897454476bf10e120fb5840219344c4de65d0aca7e55e808573b62424a6057c0c323d7fcac81f4ae0a0b7b1b31cac790b5e625eb062f6209300b125c8efcf418b312d23e4f15293ac3194af866a7b4709baee85de56c6408a2fdd94d0c7797818c2d2309209a6e32724c9f1e3c8828bcb52155982ae6a0000ee4211f48be5f0b2b869729a575068549063d97f0728e197831c3525df51c0d2d87ea585677e743812498b33595786860050bf07602795102fe20f05a42bb0301c2a59d3d6df160c3c7fcd44ac27b6a4acca59a3163f30295efaecbb3ad3603e09cbac03b271e2fec9b5598f612c1d093233cd790ed9c5228ec5e6edfa61607dfd29302f33b84786c3fb17b6febad25767f153aa2755aa3fb0c3e06d11dee0dd9a22a3bf73afdc14a126872384c64f2f636aac5d8a87db1f9837662f6154f0038c222331adc4ac8a8c4ae677af76688e6145615a8ccf8501699939776b4650fdf8c97f558e9f95b13948d5c9d60e900cbc2055347dc4b41ffa966b7f70bc50437494fa889ad5c6686b0a69f0a573538f5a7b86543dd67d8b960d04eaab1920341adea81b6b7d4e0cb2eee4d56db0317556f98aa9c266c0f4d6ab6d09ab18e00b95306896f0dc6396486c3cebaec3c997a3e1ec433a17264c640c419156eff0ed34ec919165432c50f2dac7e1ad1cc7f2dc387df81457153ab759b27740a04043f958618e8fbe419a0161f0ccabecb820943243fec18856b0979f1691e40d404325e456c11776379052eec1f5e5bc3c6f7e44ec5d292e651f5dce3111b1d4008e6f9ba7a184ae6a60adc9d8393b43ad77385ba8117555d316e2d7dc3fceaa409c9147b5727d66b95eea2ce3ea847e60ad0be4a1a455072fda76748fbc424170ef92aa6ba23b9a63f6ff892f5c536b1e9b09291e7cb1b47cac2657ce7cb1bfd0fc900c4a89f8a6e676fa39538ddf0c8c572181dc12ca66862bf13b0c8db29e10792dd4c1de50e0b3ff1d7cef0a4446c52bea00d794e999ea5b244c87d459ba906b944fba8dd559b2df25967379be7e631f382f8d05659ddf1aa61c06231077a090261bb6cda9b85227b3803db6ef276da6a412cbd524ac3403bde9396e401870b7b851474faa7b4ecf51087fc5a6b56f39812914a47961c8fdfa0cdedfa59e3075b1687f01292c8344c7ac61d2c4cdac3c02ff7269f9f6c1ca5eedb58c1260b0101d6b9814538b5018f5e5ccf0b30292d73560d63c380fb73fcee38788ec378047a6c994ceceea7ef000241d7d9f2cc2cd74b87dbad5d3d66f32fc1a37749fe0148690210f553511464e003e689ac33b8e1c8690d330f66df4a48fcbc52b92f0b3fedd7376e970be7b1f4288ee94fb9c0711008b032fbddd8bd8086ec5d088c0383740ac83379df53bfefaf7803224b8951e1849c31ffacaa16465cded123090108a76ff73d8fbb9d567abbb89cf8166e6ecbb8ae98f282193fe587eb2ab0cc033de4716df0c6c245c5c31dd4be2c89a2d9bde699c0d7c95516dcc9e409c7ad0c37614ca66964cb196d4fea602bac76a60c75937de567a26796a53be834a017013a4600971dcd8df3c4758f6bd21f8ead8ee17ac0f7890b19a0bcc377b172080815c16f420f0b4d55884210f6f153b5ef5ea6f1f663a3991fcf0f25966d044502214b8484ebbb88db6bb1662d80bcbacc70de501e34ef4b1052fadf0e12783e05d06727812ff7f40ddabe2d2d6fcb83d2ce79a65f4883f21990683a037272140911a5462221a79dab36eaf72c1b6cdb249990b52a0fe7e4bfabbbb12fdd1c22076a88f39ce2ff234cdd70e97048dc40fe21154e09df562b78e0768e3c2ee2fa02d774b997d2b49245b13983d2494bf7705a1ecca7dbf7aacea87daf47bd813408b3db0c6a004c47075ede405cf729874015299950c5bf825c7908336ef0d5e6071de715da2e8a476f73bc84f89e39cabf496b41794002d5f32b4dbf5a9289f40938b32016eb8a665e10c59f989cf089e9d05d3d286b2c83c5092d613e56abff006419bfc0d0009cd5c3ba8477a02abb4c9cc6ea0cf7482daa6f3935b896139b01f5cd778d413aa5b83ae4af0566e02135c2e7293b75d7866a273c6aa8f1ee8606058c6992e269c9b51116da6d6d3250d79c18675c2b5697dc3eee68f617420d0be76ec01a40aac669cc29f290745181ed264b9446e08c0e99969d46b1556861091df36faf365387a864db8ba7154a5453de2137a8d2cfbede31418522f709e60fac6b782e3075fba83a26c6c001610e043e7fb2f4d979597bc50f0c87a291b901946aef3ac851e81d0d06bd324f1843e3a3b9993d94e24714e49b24f48ae5960d6eec300c43e9ed42a5dfab3d0df7664552657ea1bc52dfa00874572480f7a904f58162df0792be94dea4ff03a5586e0041156b7fa54a6a52a25f6eef830511062365eceecc8929d9dcb3517da5603b2b01b501c090a871c2fbc55c76e7f380011b86838d1f2e96b18c35634188154f310917caf7c243ae1f6b437e9141c8330e8d60b08f5a9536796602137d18834176aa48fbdc616a27081a61fee25b317d08b6a0d9ad0f238e0af6294b066623a782d26cd6de9d1de327e8d6188090439d0ab76e73b2c2d3e3a582de7c332d80f7cf537c80d93db1d0399329c0c7bcda3401469891c447c680aebecd3f92ca45b838cf8fa7b2dae97749fa0aa33d5a6df00e645dfb81149422dcd4018550464042f2ff4b6d948cf6bbd15548d39b3af061055f2e0dec36f6ce8295a11b21a1fb2ed745172343e6e188f07817ee0dea892d0c9f3a4ed82d641749cbb54decffec80798916b3fac25cdfb33d772bff165fd70fd2b11d7b465c4ceadf498f7869acd2253d694e4c88aca2f5f1ad426d920b7b0efac57d3e87c7f39d442459f7563d70f5191fe57e582c635fb90ae1bb580ead0c9ca4bb61b06221858253526ae3683b9ca03f69f91a85c806324f56a56d4dce0a4ebc72bda5955302fda39f081180030a79acce778fd0a881642bd2beca36ac0fbb83309b5f5113800d51783a244730d6b642ce3957a9ac1c8ccef5fbdf156c0291d178d45b21ee8c2ae7030bced30324b3304534924284468ff909e35c08e303241b1140a84f7312a9aea26de5fe87cd7eb189822191f8635e7514cf69fa0803e1e031054aba103d309ff23c6e1ef6ebfea2ecaa4d134b3c5a26e750bb5e750bd1ec3efba130c1c0e764ae0541877432a9a134890daf637c6b7aaef90bc5c70e20a8c95c94ec2e6fefb21f1113f207f53078098d11e4009d9f56c86773000e0319d3e595b90e8a646c8e1e5005ab83ef9284d499d6420e069cd8b78138137b03762e1d0582f50946687193b607f292c96c38ed1903914cd771f45b0da5514a0a6c1e04ffa86e04595a71dba9072dd5906b0656f886a2e80db8c6705a50891a021ce1c47fa9f5745168d44cad0b642c7f2d922bfab2dd1b502cbc85d4584b1d078d9890022f7b1962400bee36f4624944f0b7f995ccc87a6dd96dc6a430e65a035cce61b1991b4de039865a7b8fa678ea585da815b26baf5d60ee4649c8e89506ecf7af186c82e68333db8b420769bf255bee1e53b5abc0784724672225658707449a66e0d7eb33bc9cd9f6b913077bbe76c3c1ef2f649fc6846900a9e4fae30a333186d3af0819e34bec9f01f278bdc83debb2251c456df0b84cde6d16a2ab032811f6d0c95fab9b7ffbec0f53147971bb28d5e70927dc1b595c86baaa15c80cfcd3c79b16e0095e76466d482300294cace148270a790a337a7dcbaa430ed105ca79b271a80af7dd38e28bc97adfa8155bed333c671461d9666e2db21d64d003a7126f26c022d3c1b36804fa0eddc311dd84a7bfc4a0848c701b1bcc9076160646c69abac06425953fa682947113f33720dab0c7e3622e7dcf5a520cc7f56301be0cfb1ee90854f8bddbcb6d63bc83e6db96b0296c2ac97905b1c0ac9188f80e6d6acf6a20a80a24dd41c8c1cad0303200999abdf2b6efd9816ae29b812ede013d5a17e3e2653e9fa4b9f5ad693fe06152b9314ecc9e8b8e32d8331cb09ad90c4b1ee92bc59d66741bcd904e6b204d87ef3cbf135e19a7438970b571109a8702e399026238b71f5a5a458e1cd26b32b1daf994a48a327afa5aad003918e3740dd9dd391ace6d134f1003c570c059241f8c0683a303411c7644d86209fb99ef05878e6643f3f474276b5ce4c1d76037fe50bf7321e995cdcd8f07994e02389e0e5fb41ced19511837ee37e7502fba3fb5e4ab33d2caecc2dd8372cd346e0de50458105d8e32bc180992a6231a3192a686878e4ee35037a2f36d583d7dc910bf0ca197fb5318b07b41a6174b7a18c0e1e9eee3f9df46dc0e69266fbe71e90ede07b09a6072a5987797255cb632ce8de054bd9c2abe3a772c0eb2198bfbada57604e62f177c630b9cf78dd72f85ae17b5584946e8d929e418fa9cddef5366ecb00926457109c1d6a920a7c053472b5d54e0c410af44ce0c562dcdb194c02fefea01513244b2838132196da731943a1bce14fece3ec9bf22e704a2cdf259c918d40115fbfae1b09bbcca0f753519b5f7e017a26572d9d53ffa376bd3508595c41f08a10612f500efd9e10ce26dd9545d696bf411b98e4afb80e84505f09b8cee0c021f03aad100e80bc15ee1fbf3d849e1d092be486415da42f0a25ab82f7df576076cc138d9ca6ad45ad33239f334c242aa5b750d5b5595ed6d6d9c94bd7ab91602c6512e7216bd8c8a990a7cc0e5f9a2866f07e3b6e4df0a001e5dd7ace49c91058af2771e18f7672d8b48615989e2c7bd47574983d57aa46f9fd562d8d7442100779eb8d30ad91f5e9543ce5915b47e0b9f8c4a4eb294af64da76348d29a6ca074a7d1d89d95f82866a40a85bb5039a597269d3ce9ebd8f3d6c71e4430382bc0f4eda4ea3b3616a1b94636c7d492a82e9ff868e7f261881fdd241faa5b38f6102e22a5c69f6b69be687e52bd487bbe64a75abb66a58368aa0b4652c133f9a3b00c92c2306c3cb5b8f5f6c60f26c7ed101738c5328ee0cd1c46c10462d2b4dd0078f2ab1d86be6fd2710be0fbd1bf5c148b574802a9aa0038b38f2d82b264a87050b770885637958546d679eed705b972dc9ca0395ee8fdf43c3b1d76d76f3b10785a6f6a9611f43d2f09a82c544f462c982dfcbc32429080e2d4f05a3984bf9075b8516307ed325cf84371a50350c86b1e155c480578a1130d5df634f55cdd20c79df9b61f6c2cfa3e038db159e8b36afd4a5ec5b012c52340edfc63255e0e30f564f6e12c478b0989d45029a975f5c3e5a7397ec3b41408b4bd212735ea697082650d2f76929631250221697812d9f29dfb2f221f868b84b23477f35b8c9dd086113c3ef243b321be5b7a07b1f1256075229db03f5b4fc15aa00b08effa3c402b941652073ae0d3a3f56c68e1f0b373ba5099bf7df8a718913a858f33f71710590dfa937e90acde15289865763c9ef197367bf716a79b47c598105b08708700099743822bd5a049bb8be2afa285d8bfeff7992c95a5f28f2749751570cb3320ce4e62649f9389b222370dfb832cef4664f19e1c5dec59bd0549ecc7900aa430b625be6b684221e26509d038d58f25c6d3f32db09efa6afaf9f0313a12cc659063e89654c1d590cff19daccdc5f94675f1d1375999fa39f3dedbdaf2d65fec105903ea624e0d9009e1f14af218f669cf9a97a12672ed5ecc52b746f1fab78b005ed4dd717042c4a7300baffed39eb2c2fb5584d7d1f442ab3d741e61b63b8c90d87f896723315285a01cdc8c237ab2b558caf27883b2250978cec131c8eb4bf0fef06125b4bd986b095a07e4d756b9dc2b8a9e8b7ec749f75e7b030026a6d0b075ec4aab8c3808112cdee7c16fb29154a1ea143a57f45d468fea51171cba8d504075849f5d72b9c8e395ce119889c0b5293e493b59d7ba85cf95963d03989890586d31e41ae2affb2e6a2b96a372866ce646fcee6c2740bb0e4726d601d25af0e56ec3e33fc94286c0c2102cf35a98e8a2153a31cfa5e9f7bdf522255790090068388f65ec318bcafaecf2f234a3f3b0bccf7e6bec7876b8339e66d584742e707cea273791611ddf0ac02d5c9d193b7068da88c717742731ba91e84c2b1681000648d6924a11369fc5d2bade59f09b707b28e90f1dcf89e52276d069679ab940dccd995fc380e89ad64efa795a244ef66441b633d286b3855a4a70ea63dcb8e0372cc9ab9bb112dd6b596eee8d52ab50cbd5dd7fe62c03fcb14554ab4482cb60466c9a0565eca33f75423ee4ee506df9de4d2ae801070b8bc3bbd0298bddfc300ff7fe6ec8a3ddacea1ee7c658f08bb97e264a944cc17bfb2e5212be4ee9ce10e329f88c610d9205a43f5b690fc17ba426971197ba0b7ab6717503c9b50af8804 +generate_ring_signature bdd604377d0adea441787f06cbd71142cf15d55ee20ec1bea85f573661c71201 2487ddcc1b463edd2a754b037e4ebce25e5fef7d87a227d6eafa588404345543 35 b089255060a9bfb64276f30e0f156291d61ed74376751cef0c3c519bf97005cb 71344fa8a1d99b228c90f79d26b10a0936b43185ae7e456376f6bb527bff449e 2798b734c642a9ec401cf1a33c14c239c2a59c5f48eab81450f06b8824589ae3 3aed394a9a3077b2b7b6254d4ff647bb96b7438be120fac9204096b5f169673f fc7b91dad8e497665fad7726ccff5cbb5c611400743fa25dc395bc95f09c7704 d4a4dcb19764fe5a25a5963903ff0c0b9134c4b8be2cf7f33e7bbf42b59618d1 38b63cbc455b1340fbaf53d4284ed6a0db201b4e4aacfcdafeb6273b1a307e3f 0b8d7c46fc803560f12ef832de6079adcbc1ef9f787b45de01a737ff5e95836d c50649bf69d8dcaf869c7e42948ab1784cfdf39af5a7e4f710726f439b25fe51 cb559abd56c267e40422864b8e58cd27ee9f9076f08da0fdca1939d20e6500e0 83c0c2a194cb48bd356a96e50ba828121c00be8e57a8ffe7460fcdbd543ec13f 1cf20a067afc5e04c12b6ec9ed5dcd70d647fb13e390b35b24503db9590faa9e 77ccbfb6fdc8e4fdc4b9f1d5b642a0be86ecb52d0760e9d37949c2a08be3b17f 95061c0154e8feeefdc01a2d1fed47012266721d0fc3b81f1e39ecce4f8b2850 2009e95362d812eb87acd566bc521ad12249dc3b1919d8af30ae0aabb389b6ea 7a8431ca2ce7199d1db1a3c786fc9405dde6d0628952cf95174f0d35267a41fb 8fe2a2d24ca5a08caca966a0a5175b9807f3030631c5b93b7ac35eccf25724e6 67a3edbba5207baf306674a7c24b2093a4bc41c3d43bbfbd545175c8c6028bab eaa0962f91596cee665815b64415daf81bfca68eb9cf5eaedb9ac0a0c4ed0900 2f87c482a8ebfa50f9776869b0899613d31302f61bb9a8066182782b738db442 1fb8bfaed14ae9aa8f13807f7a07d705d47cd642349fb1787734233b7c85a3ed 35be0bfdf4b725f01e4f05af0bb9f02ff0dd4f612ded87a2340a1574b3aae315 4a0fda512f352146f7859748681ba33d2760bcc72a20db5922691856f7e603ca 33f200d19c8fad76478d2eec8699beee2061ea1f31a6f28e764cb7025691266f c968d9bc39daba4299986612b3467ac3d45ef0b830dd62b497e52219b175fccb 22460e30d871caf28c49e4cb59cf296682dc386f5eec6279ffcc150faca7cfde 1f92d5efa075ca1f939b27e1b0aad182cbca7f20d2da676ba1992d5696dd17d8 73cf74bf162bae040c2523789a0bb3a96cdf781f1a766754a2e2ee1bb200791a e669e339a639b731135147dabc872053f458a767ca38c35d3e9a3049f7e8908e f8183272074d1f826677ac9d576cb3f558fec821f5e32cb337107ad6cc85e63b caf86118b2e212f253e171c428e935c8eb6cf6ad085f25af4a0a93f9ec59ace5 9dd75314c1d8ba4bc81914778dd77308015880272b65bc37c402b1cb832a69d0 bf83ed74a2f7948e17828735a98afdb798a3f8793d1df6d4d1d8069ae7403dc2 b553310ecd79a8254d329a3d6e2002c89a501c06b6ae3b7feb152293dd26397e 7d483ab7dcec571e016a577f74301a6614a34734be679ecbc324170dddf06aa6 57993693eb82f28e7ec9a7bb128da07bd30e23fe4522dbc460d96cbc87482706 9 07d3702cd16495adf74d067f3c67b51d29f3a130cddf8ef785af58dc7598830a0a7fda5bba20a94a7dea5262be385b66d999070b3e542ae9b4cecb64793c8c0d06cc61b0aed2017c34529ed19fc056500db5030dcf684c5582aaa353be6e3c01fe0424fac328567920ce05662c2b8e7ab7ef3e4acdccebee49f3e00e8bc9f70e30b829d77645f9f76db0d2da4d1d6343a3b31cb1338a7655f0161127b74c4b066de546b7a96b09f516c2b71e0cdb3b955ca4795d385eb223f3f8a0650491020683edacc93b3ff82c8b14e468615d09f702a6a82de37d0e09300c2c8228513b0d10225a10d16b92d46b1116dc764eced1ebe164eed912b2dcf835866038f6be075b5fbd663b44e16b44c864585b74c199f8c960dda5a456a7c471233d806fa8096e556b365384956823c73ee290c0c9fa4f41cece32cd60b72c26e9e9c7b6b00cb9c01f645e586a2112cbac077143f9f10fd1323fe5612ad0fd868ad4fbfa0a00b5db0edd482c8f70ac15dc3ccaabab86f23f389101524a48b93270901e0a59052f727a159f763909ff10073ebe1b612eb5f5d4c128a13285c30fc4551626d706e514e3fe8c0c410a003ec217ae1188e3c8b317030c21cce978ac9193caf00a0501a22913a76d47f5c6e6e53a88a792336053e7e0337d3d405845de0ce32d5b06f7ab9fdb839cdd10956f59e9a4b595de1558aa57dc305e80a13a781b209987088f2606e5bd4caad396fa2852a5479a5b7068fedac6e79d8c68c97512315ccf0faca367b8616b7e954cb434afbc335e7e01ea7d552e77178b1fc800c771b7990371ac859b54d208e308b9349f1aa0c7dd0914f52b87f315c0f80f6e8e5709310b84edde2055279f3d92ef61a48f490a307fd8d3833f78418b9cfee2d68aa49102cb79ff0bb0901fe0321fc41c70325a33b702c56375d9bd85945bc7b833c32200b249c959d814f048be4c7c5414e5fe801324fdb2a660240da411172197bf4b0880627bd74f967b4c15b2d289740fe4362777e7beba012ba7e3c4ac088ea35802a5e42e695d86be71d3c48f85598e2d547c6adc27925b16a6e6b6c51dd29f960ca5574519107556c3a36722dfa78fe6f217c9d15b5494455ca7b7813b3f49e60b126e9e535115da83522a0c81aab9fe2e5cf64e8273440fd2d00388e9363d7b0019dd6f01184120ee68f4bb80cb7b3c043b32ddf0c8e67d70e1afbf48c0252a033b410a7913402b87054b54b759ca6bed3acda99335218077ce1d5549b81491089343c05de444ab18a470761a6a19e918fc8538d7b5b23c2d6c76568e65edbb09abe66447a7261b689a8c5165faa9dbc6fe384980148adfe99a4e7222ed929407b71dbaa0a5c448a79d80a085ff5035a9ece54ea89a353f5ca61a0bf57703720e6e4ac852485bf9a029e6c24fb973f3f3840a6b532a597a91595f89441cf4b609329906ee8f4698bb37be0a0e0c0e558e284b72c6da31e10afe0feb3cb3b24e0679b40cc1d175558e2da2995769b12ca6bb22444730601acf9f2d575baaa91008912e2592f41b4916a9f9627c1421864e3f19ca0eaca32870e47e402c4f114503e2d0f6dfc6d1733d090cc82aaf8ae82b892fe1da599acb3e8db2d3eecc14d207ed7cb97aed6d6aa0fea3d7b6f314639e092a91199c9b77eaa9d1c363c0857d06f572aaaaa4991f7a55a9f036c373fe299e3b8a85cad50c4d55e01738acfb1703ef4f1bcaca154e2767f56f40b6b01f60e76072fe91b1e8a0405beae04e103c0f5afd1f9667e1ff33bb40fcf6bcf3c760201e39912dd8149cd73abde8723d2406952d166c303c7f822195f59d48e42e1926b6a35085ec3317c1e9d024498ee90d3d45f5c3aeb18a6275cf207caa116136dba92954a85adcdc5d35bb2a4877e609ab43fb2f51792862dd6e42d2ff5215f8599774d346dabe90f1b1e6ec30f9180cdcfd1d2c93e3a88a48ceaee0bc5f231be2976529be0fea473c6c9b0e7910a70308c2cce6d49d0441b6d0869724f81c7cd4e565a55db9738cf4d52aedda5d6502ebb03e4d191fa13c70901e22daa333c2eb7c259b44798303ae974375d0b46f0e11b516dbdc8fef6b5eefc4923aff4483becdd5d2b8bf34ce8cfd8d0cec5e15063a5d0109e704ef7dba81eb3d27798cd9ca77d607cf18251302eeb0096795b205ca8e9ed46f8ef0d81eab9316bbdb265d7d25610239e52e6bfcafb598a01d950ad2116b4fa5c436676734d9a46b3a483f6ed2163237bdcfc30f343e74bab739015938ea48af543ec234debe7061a50fae07698d0592606b768d1368b9d9ee970d59e6e5508c3e58ef952cfdf29cb29ada5ddd254b43620a165942ac42b3636e0d9992f500931ff7832bbb50126894780e600da117a548d25e7e98850715e9b1073ff3d31215f1d22f9ed6d8ed3c501585a35a2a15abac89cccf016100842b53044852569b4ef3ebe7f616721151bb96f8b7c0605e2f6db08da5fd9028ffb77b0fa7933c55e7ec5aab3f476f89dd578895365a15434b54ea22923185ea4195ba0d9c1ab9b4b168dc8e619b811129c12d6fa3bbf34684fb8b3a2e26e42ea6ace309368fe6a2f687df4ce7e55fcc992d54891bb9b158a9bde23924206fbc198e090649da00f34ae324111749b7a87b1d932bcef1bc86d5262f79abd7dccf6e2600025dc1f187309f39d5d22617803a0c332b11ddced9bc6a0e6f13ab3b6cd40a970c2211ce4663ac96be5a19065020e41d5c9ade02ef4092f178d507e8fc5e05740587a23d310036c02d3fb3f6ebb3b0f89e338d521edff6cb43ca48d9fef7fe7003e1cd86995864359357325a63826f23bcee9261e32429e638ca44c7a26832420f6e9a25520c0658a24f727383e0fe4ce6ef8f664364ceb69b67982119764f0e03d51936fcfa210351d569193956f06fe0945a6c206d56b5f88f466364efbe6c0e32b7ac71c8c912c7fd291d4a30ab857d9fdc38471d0a43d97ea4c98da064f60fdd4b2271de9213aa4b957b4926ef7cee611d31c6b58efe9c3d17432db1eab9034ed19720d9ea9ed4b56e41ecf233ffe45b2b5fa0c560fdb493c8ce21a4327d033a0b44c105f1f453cca7526c80f726a77eb3ce460d4ac74a10053d0385517a0836b69d48e9c3622e883d1805c3ec2eb867d34cf15e27cf5a06e203907bdbb50c +generate_ring_signature aca251d46d3b5ba026de943e11da65c82565e3661f1aca050799c330dfad3d41 b26123f9a3df78771873063ddd286b3b07e8c622f56903f2efce7499de4478dc 1 332885ac700a35ecfcfd9d4b87366e052b2b64a9b71cede41d1498ebe448e3e6 e884832fa0894e874fc141dd3685f50e5db4e63743002c9005997948552f4b0b 0 8c0f522b270f65db7c71050982fd3d32b0ced0e5effefed89fc3967241a13c0546873e6f7476e32fa5d1fab62092353e1b70a3f0a4ee672a01b2a4891973a40e +generate_ring_signature b775c2fa902004d9f8b68d5e8d02f5a8c1a5368339cd1e9a5509f9cb5bde73d5 7d0c3bbc111cee95905b30f237c3a948d90feaa912301831d3b3d0d765056b96 1 8594f65a950e1a254db53911145528dc04b86702259d209172a832b7886d2d2e 007a01d31abf4ef99af89f0054b67b885b1964b5ecbbcc2f1c9e5dd1157c2a04 0 59ecc7db6aaf18ebc47637a70364ce3729860008353a5d45ea9f6ba60ef30b071c5798ba34f54ca91380c82bbc813bed45c308f081297d0deb1a30b6d01a8c0d +generate_ring_signature 677e5736293b69b1f168f92d1f194d05ced68b431ea47d89d1805e285a75aa96 c7fe04a57b9bc912b8b51cb394ed14d95cf3175482764e5a9e311b79669acd05 3 bd2dd96a9f97843f6f9f67291f4ac742f7dd142e4bc174d83242322ea2ed6578 519650d18da99601cfe0ddff1cb8a6c3c5a3166ed0f4b4d5df08e731f1794af2 cb6f9d2a06625c1ca76b07ed61ec15de053473ddd9b648ce6c912a3d176ed6e3 7fdad023cd867a5981be27fac5ded58a4fad51750510df61abceb2cb6cefbe0a 0 f49bfe07a2a130c32c43a0f50a689653d0237baa6724342b5b22447dfd5dc103885c905d22e6b0514e5d68012a93225e02f450e4f457bfe8f6d80568343ab509a62f5f2934f86c9f102d7dcf8b8542fb1b0e1007e4ed5f2ca7114beedbed8307df73093abd8d1fdc654d4d054f0f97a669312f086ec8f921f88fc80870d6c20309a5ff593f5ff3295f4ead0aded9ae766692912b8781c31d4839d407be330b0eba7413611ca47f2f2f5850eb1bd405418f32e0afdfa938a3161868312b13640b +generate_ring_signature 2c56d0869d611a98a8583af24571d794a9f7d657bc9bb2668f54c91339377b9c fc4553cdaedadf367b81758a5b277e20625549411a88c7325bd8a7129bcc476a 2 e82c7b44deef558ac8ca40818f843d27480d89f5851c2e0ead9e2fe58eebbf9d 66b8b0b3f84eac9fc67ef4d8f5324dc53526d1906f0f830d21bcea089e0c42b7 7e23cc4cdb791d7b4ec1ceb2ef16f65d29edc81cfe5786a62f4abc457c4a600c 1 8c2d85e64db452f7f8abee33c16e41d3ff5f5ee6fc92dcfdef484ec26db23d0ef99aac0ea09e2510cf67ba9026c35d25afb3df4622f0e9fd90c83820a710b30559d5858dd33a3aa7fce35434ce2d3d2518f16efea32dbcc142f20aa4abde16057328909662f1090424514c7f8ca726d47f23f631816b60784e8b634bbe5aee0c +generate_ring_signature 8446c895fa03164711b6289f8dca06a575ccd8558fb070d1f07a053b6ac62a88 8f78a27ab3ca15e3a040e4ac2fe32902d418b7317666becf389f520169099aa5 1 05291f379474a1eb448d27e66553fbe9df2a5133b15392f6a966ace067a870fc 7bb9bf9cf9611b1609b19513734454f28f49f896fcf29e689a937abcc07b4803 0 9052555dd0c07c6c34f6abee431d9a5d54d3e735ad367d8e926f3d3fa169b1047f24af04bf43e4a302de49c8a402ad1cb742db6c74a47c132d0068f40151d408 +generate_ring_signature 89919f2cddcd14dbbd6510687053b794e5b8f01565250bc8968b781f24739668 0279f476b72eebe10b6db1264b63b2b074144dcdd4c0c2764cd4d1815acaf713 2 f82d16dd5f4d75904b7b9195713ee68a1595aa8d9de4fed48c72c0529734f52e 04569b72e8939aec2b6db3b83ee34c21326a951c83915e1f318435f609445b41 824dcfe5b0051072ef13f8c9e183c0d1ff5f0dc9a2c6f397bcf1bc3d626a1803 0 83123a75381c606bc3ec2b0ae44fc4a82b653963329738cdeccc068951f91806f12bcaa4ed51da12e414b650e698a99e60b5fbe46553ee0fec6f414abdd6e603b08cf0e2280dc1df8c959689b318c85bf26f36d4bbbc4af33ea8a1ffaaa7970dadcc791450f3af3e2c47e5f314913b78aec586ba5fb69da2a8d43f3468ae930d +generate_ring_signature 0d45a262ba21084d5b11dc6f7df59cbed5aa38f517ca4a814ff490923916a652 9b86f1081957871b7575cd304b3cbaaa38d3f00703de9cf9e8e184128f864375 197 d0f935d39c2c505fd5a8121bd2d4a741896f55ee2470792d924dc0101a6a0366 460c54ce55f47189b9ef38efcd9c2677e4f3b7705893761ca701d0fcbb17530f 497b4f9949d0021f02b66a82223c4cee3471218d072dd5bdfd3cd75f22e7c0a2 86234ee6f836e7a59fa06e91798301543347f89beb69c47a5610cd6a48b80f81 eb8da56b6a7011e63dabec4649def5c6b1e90ed607e3526ed329dad2d201681a 2d35789d85de0049e0b401689d2cb627e88d8fffa91cc98cb6a0cf41d596c936 c3789543dfba6c37c771f175366171d91d5ee954e9a0626df83d371e1c03600e 19096bc68e91305027ce6f497869c5187fe39a606064f01dc45f696486fa24ac 59731aa199ccc0a87aa746c6e6cbb76295bedcb6269906637ebf0ec791706b0d 608f849ac3d56aa72ea3d80df7d5a784dc4210ef2196ac1fd972e9bc7828b378 e98d5ee1f8de14bccf0abab68e749a9c3288d3d0fe6406d668f912ce03e5830f 3ecbf97e70c7bb254d6afe53e6c15a9e240f26fb732e9c8ad1f13e6f5bdbd766 bb32c560feb78ac2da03f973c620b99dcc06c726b2a570b732c862c95a1a8f79 7475630c541b4b636a91e93ee3610ab5ababc266db827320a8814c3a347b9b8e d0a372bb94a4850540f4796fea6bb38d394a47a935d2dd4a5326d86d501c767c 74c6fec0ee4b8931974d59e8dfdc4ee0e28e3d1418d23428234b48ba8ad5393b b688d964bdd826f6748bf989babd2c55febea15e51bc92d3ae961509c0e336c1 90d569472bc45d3201db602f71869cbf528b2b6b3fe19105278ab39bbe1073b4 d9a36d7afe645436cd02b3e61a86cae1999ab5242d039b4097508861a5e247a8 22c1541a04cbc85028279c5acf1b54b6151b82d09c16513b646a14c6944c3f5c 958bd65d4e627939b83672a58ca806770be18562c061c2a225dad1efe0d95b6a bb3f7a2da142d46d520a1741c9c24d85804ea3da66c691d836cc3b8c5f7421bf b5194a6a410afccb0a4963cb71afe4c177cf90f9a7a3a3d4e9660f1ff064ea93 4f7fd2fe01c9dae2050735a578bbfe329a5f8e6153816ac53dbd34762f87a8a2 6596a10ef0c3eaca356f8873042150216ea7df61d25e36136df4746fa77ec0b4 860402d1f5982aafdee30a7f8830a0f4fa64877255abf4a5e2abde02f43e5c2c b86ef36d3b6873de1efe9e02e2083d3bfbde0ab81aaa37af162f1a6fa0eba0b4 5e7000837abddf0711071b6d205f999327522033d068d3d029187b083b5d88dc e7c7f0e549f921bfc164a4b724f261759c46b147b8bbf0e6e68c39503c198b64 fa55f966b88976d859d6e4776ed2dff074761de70d589a1c89c86279f0005a3b 75900a1d92813d506556b6484ca988d165f54008f1a8b50e0ba8c7b23bdf871c e7bf33d171b351a061ed80d3c52029b6627c7b73167d04f11e339da701cd0d6e 655314b8659808e3993409e198dbfe6555053ed5e0c195d39808ea0f45972b49 89f9d50a6e5f312d92da3763101453a9ecbaf69e84f47c21d855a05bb54a219f a64975ef5c421dad5eda121b3c3e58f818443428a05263053be3da99fbe77df2 5fc852cc8337bd39173274d4f3cf102e0c2fab30ed3d8ad70c753e3c344ed4f0 61298f604f8dd7e109b8600eb9a84001c3d7dca3efae6229dd12adaa4e3d2c6a 07f4d5b629d9c2efe6705f2adb2b9342822e615a9fe6d98897d74fdd89fe2878 5e0f62fd8243023c0b9e7dde96d4ef14e3079f4b0d7e76630c670c76847aad5a 345e572794d11d758bc761d9f22f977c827ed332108e810b21b85cd6378518a0 8afce8fc456c8724baa05516fd9af2ef8ddd29e538aaf1214756f683188a1bef 08897543e204208ef1c1118b4153c450245dcfb2b7746e48e8e389275e816861 d10372082654fb3dec772174e0967ea577c5d93d4ecdef99c70867d84829a10a 4e038f0e07dfc7e752952b19ec3ab3355b2b92e7a39182d3eca79b6a3f87d14d ad67fe5388f5e92e911157fb2b034c1a615a1eeccd3858f255bed067540dc711 c40a5eff26f7221382959ee22dacab3668894870fad1934eb8ad8a7e40ed36c6 ca5f7f63c498e39e135e8c18f0262702de1348dc79f8204c216651a9c7f9ac71 e578f8694a5e92e48f06d5709ccfb681b9c8a738abf20861aa51d61872cd3348 b238cc4ba4613e26d7d41996e6a15b7a1b4314aa7157a984eea7d2bc0706d00f 52a762e09b64943a304ac9c2e110ec56493d00ca752ab2c715ba72f7d69bec89 b5b444ec26de88fc6ff295056545fd65ae83c012a45683b9a22a379efbf186dc b74cde735535b0acd9ac6da6a18c10c4d3e889f1b0ee33aabbfe3e942e9f6321 ae98eaed6da71726406457e4fb6b8fd6577e545ccd7aab51e0c5d51a44265e4c eb366a542d43efe8e33f1f3733dfaacfcd97e215a44ab0cd2aea54a485bc1ee2 710ad4431c43814d664c3a3e0507f59cb8c65c3fd6f6b9382e84bb308ce2dc52 957765427ab11d99da32c054c7c68f888f02f1f2fc10c5883fb866661b3f0e1a a453b57b38dbd7b2af86ba28379d8832e3bd57f3b54897875b458ddff98e7949 a9b5ddbc6bce04caac06aec9761a507f0e09a8bc3f2e7fde93304b5fe5e08673 e8854e7fb42255389b91010d08f90ac2d86da53d338f914fa5edecd400d29a7d 15dd3f808f9f9a4e1f0f68a6157d3541dd24f5e3e51b0eb51543c1ba1dc7aba0 4f187a0886930e1129c97e3373b873c4be9875f745ee91a2e20c2e713a133d8e 64f4cc62ffefdd1b73eba2cd09c5f7ee3f2433faf82129ab79ba6884040fc3ef 735c79657390255c9072a9852bb1d92425811a7703b9809eb3793f4119e00463 5b88ede31e1f160f65b6063921a2bf8b5a28788ec8c3f54089aed3d5aabb983f 7c1252e028be184bdf13a60a46bd476217cceb393d19db69ef94bfe6f3380ac5 d2ca845fc232693381d777903751160a1fb43e818d548f0a0151dbd23815b260 d8ac75db6b5eb39e3f5e23d0b88f82a51552150419ad35e2ce1eeca110df4552 71686dbbe145ed2962b857fe2b732bb0006638ec2c91889f6ff79e1729554bba 2ded0ecdba64251aa08c39c52d0ddc5eed4c85df82f9856cda1e0309315ed47b 765d23651313db76c45f44ae14865aae2c57f8c67beaf102cf299f8f4f5d856a 998456c7aec76489456b3700990c3bf373bc85eb5643a15225819c91c8642b85 340176f1b4bb47be1b0108d75f4f06adc449a28a3ee4b3b7cd58d186cd6c7c19 7d3293cc9c72bbb56250a56c44225e67c63cbaaaf65f2e3671e3a8553889ce75 ac9752288d33835a09b7110f63c38c74a3f24b97fa26471a9d5adef3c4d27373 e152f9eef552515995ef4e9ce1257287e5c7848da1a19697c0ab30f14f7d1d97 08ffc32c3134d2e1ab2f57d3b287a8f6ed83231e756905136b42c1b3aa69928f a5180c65796b1a1ab3bb051ba05483f31e84f49c1eb893392fe987187ef85c63 8e5e0df1415bfe86c31d128a94174622e9323cba4e1adb06805e92e7b0620fcb 8bd78cb19bfc01c452f2ebf461670e00a3c3aff5f7ac6a1a789aa8e697ac324e 4b65071088cac227ca7b21538cfbc0cb09d0be5736b852e44f1b02508900cea1 6256b8a6eb474cb662edf8e72d45598a24d9c9a5d0c2d4ce90e6e4eb4ab72f8d af391f1ce7788799623687e8f64fb61e742273a8a7344a6098dce9f6e1b1d78e e74249c6cc363e2017d459fe26ff53745f0ebb45716b03f735b00889811935ca 5010e69034d8eb2d46d1a8b4f0982c2ff82f6a13e81c61ed262939eeac5cf3b3 88f249e548a21b58d4e63560be38b14054257f5b88adb0c1b2db7248035dac78 925e9971e38bab4865df5368cfe172581a48e8d8a25ffcbbca2dc00a1c765488 e3087dd5dd33f774691f876a3755f311cf77bb6972eb2c6f56928346973d8e99 56c686807919352f157d48805535d6824158026d99dadb72a104764d7983c2e4 46800e442d18322d36f6978aaa3790dd145716459f3ad4a04be9597725af3767 b32dd7aa461a9faeef0e495886d5d8c7fce4f8f5b7fb3fa42ac513bae5903793 b58508c057d5cfe3a4c4524c96c74f5af636b5a9a56cf1bc4cd816e6d4d465bc 5cfc9b6f9b677441ae34f285fe46e36c922c15ae955a9169d490984bc8b626a6 d58b254b005b382262704dac32494e11e867b30a92df690ad0883a5bf7bebedf b582fd6d2430c8651f15e80ce36cec80b79d7283bdcd5168420fcbd779d1e9f5 3e684f24aaba4b871045cc521acb81cc4a9068e06ae0a7c0c4a7d5ec7e2947db 809eac13d43c2fff1e919d0d5a93a17f97775858fd822b787cfd9d040cb0d341 6a6b279a65c84c83083de47e5ddf51965103b6cfdc39be8f0920cabc138d1b32 11753c1fd004eb63e3296009423f7a455019ea6122a22e06d300edd724dc054d 2d32f6d1bb3a0761755bea3b77ad838c0e0b3fa3fb52186d2ff037fdc3c0f198 3f8fc50bbfa21a30257686beda5a777728a60a3d187fcdeb5e361ea75b4d66bb fa0d4059819fe819544297431c1f676d1b486f9daf8611012e8ffaba1030d767 1902609eecfabcb88c566f1f737acc62b41c4131178eb8a8ff68506e2972875e e536199a16fbc159054a32e48cc24c7f151500e82c2757353cca78df3b72d22e 659e8fa4ee5592b00551f6f3c6e8746e6c05a31a46332717964ffbcf24643b30 594bf8cb04d93a3811fe7bd3d3f1a413775aeaeb28d3b06f7f29617e58e3c3ef 7c9d7a620d47d9512b5dad55a6f4fe98940264b316372b74c0d39a1f7b355663 ce45006b86dd046a5a18e70801360901b0d6174a695418bfef4dd036c55753a1 f199d0a10dcf37bf413f9f8617863577ee4a3b86454e3e4c34833dc51ce8a9cc f65ea29258bd880c7924c54f538b08a9795212830240e606e5d751b3ec8e3b6c 4a4093fcf50674032c280905fdcbd285a626d87b9d077973eaa690ca95c4c71f 2f660dc6c1a14877e7898aa47ec02bdfd278385536fd9fff368f5303f1b82f70 05821ee0f3ba4a2451eb951afd27a624348f9bba4561b1fb9089e974aafd1316 af33925039e6797a7d7663d6c693ecdee23099b60ff22c559635b5aad147814e c3662d59040b9dd071b53edf6e41943332e09c6ea7e4e2ac12062992376e7b9e 67c71e230ff2274b8fa392df01d43ee6958d4e6f07da64410754ec5c5ba52881 e2d574143ce458f5886f24d031c49180b3f78c55309365715ebcc8a3620a7575 63160938651dd3ff9cd282fc5aee479afa13705c7a2c43cf8fbaa286cb216070 e51f74ea5fc1d517a12b69e5451f3f6780c5640e5d590c380f18a3300b935c3f ea8345cf437c679dbdc05fe2bf30dba47b35fe45c5ab2e5b68592c4adb6167ba 893d54c1b4fdca988943c4d51d87f37185139c9cb4f8e3626501e36d6a6c5042 92722b7d3ecd3d5f6a50ee26efb4de32b26545b58d83886da5d09518880a6ac1 59255ac1b983a2a2e1551a8f19b4ce70575d7ecf4970a250e6ce5634e7220a39 e76d98db55a8444e9d82f28903072fa1b9a940298b2a2b892ec198bbf576cd39 0c624da5122c9be9c1f0f3d6cc3caec5eb3c5666d13241be0e7f2e0f8ec303d8 0b5b10255ceecca806ddb8fd3f09448367cc961d2cbb6e544811e5a6adbb7b82 264ab5191f54099261d36b2fa67fbf503042ffad98ded6ac5caeee9e638b5a6f 1ea24d52a43ed3fddf2a4fde7d13fc73c8757e7446cf7e95bcfeb16008895c22 a369d000754b106a32c7105623859a2b44d167ba2662474d64ec90103cae1782 87e6981a1eb1f422b6c482628204998236f01cd4f563d9b883decea4781b65c4 26fd4292f36e22a31a5f17f918364d0fa1af7038b64eaf2c77abc071ff324911 1f7fba3490dede66a8ca0b0f67f069f48943844c22261c69d586cafe9d3f86f3 ff7c7a106db23bf12f87313679605e6b9e0c5364c20da190d5af82b5b6b22fab e33cfd1d5133ba44214fb24911a44deb554830bec522fd27f0d9c3084613f413 6dc71dc6f84a8bcbdef2d72e2fe12f21b29fe1253a015fd95dfbfe755486313d 6ba2e3f0a288699640458bb12023f8b1c6cf01e292f386730a7e04ebb17462ae a1ffb0a73d396083ce3a51fae7a47c10bce4e53f736331ea791393d9149ad791 fdb87a472b97c99a0c6bfa8c8ce93c6327dd796f3d71a3a34c4c81926d6da322 91990deb0c917e2d68ab5177ea86fe68552736ac7b702fb81dd994581f60bea2 093beb91bd66615026efeafe94795e5749797c8339f61f9ee3ae96e8a1a5e0fa d1bbd9eb353fbe9bc9c78fcdb9f49d56d310e287dc698ba37f5943660f2294b4 8342b638e5299018ecacc42e496e7b476d7f35ffd6568600573da43331f36226 0de99f05c276e608427855984b17f6a513383f9f3fc5914d59b85a214dfb85e2 c9013f923e6e641de8a15f21c821c00ce771fa5f36a35d6eb1cf71fb4e633296 a3ad1f8872b82cbf7e2607b5058ae202ed1c4f6b5a963db93c46722295f31479 f82e25aecb0428d36f2cd0ddd00a066b4d1dde1150f0a098c2df2c51003a180e 0b12cb3bcac1c79d798fc51b32de043cba54ead89ca92ebacba60d25c1eeb057 d5a7bf94666cca12b65df7241020dadb44f4321f8a1784a3467c2a2950723465 c439609c1bf47a2dd78f7bc5fec76ea959e61a531ecce3c5132f0470a438ca75 88fc504b3792b714cf1a6f09ea06a61fe625aeb30656061e42d839f0edb32db6 e2564ee229515f37c70214195c39dc123f988a4ac285f53676330739b5622da2 ffea0d4088d7364d36827ffd49a02c5e67d2d1fffda60e2268a361f9e665dc41 b90a124da487e998d333f782e11a2811d686dbb2387fdcdda8a5d03197bcb4d1 de4c52684e022e46d24b2085c15ee9750192427e7a9802e1a36cc1ed2dffbdd7 656f299420103185383c44c5962ec031388ed71a73bb7044d789f2ef6cbaf1c3 970fe375583d4dbcc1c7ee1ab99dbb0c96090524ba6eb8824b1675c15dd88d60 aab8f210d3a0fba5dfacb2d7173f21afa3ee0d6a987478f4feb3ad810c5f6f03 3396e08c2650fe809a12b5f44bd599b2cd4fb31c4f46ef409a49fd84a77a01c7 834731fb9db2e5f2d6e27bd7301e26be7bdb804bf83c1937c3c4161aedc86cb7 f242fc60275cc30369ead9e735952f6d7dd15057595ca6f609dc5d58a4791703 14323f5c93b07305aac7426b3799b4887a475c67dba4765ec8a70fd80606a399 dbab57d98c775867d49d6c52423c0b126804542d411ce9ce25cf3318c4550e13 d3311c559c2b7a814beb3beadaf4222bfb4cac71bcd7983d7217cdaa543228f3 de0667f53f27ec36fc2ae62706e8f1f31ad40b7c41c75ed114bf0e330fe87e2d b69135ff45f3dc2aa4801bc87c3fef26d331bc43ab564b85c13b068af18108fc 661d565d6920d157cde619ef12b6a1c5423c76626316733b2f292d9cfda997e7 a0c95af16260540b15491b134d8edba37295aea89c0100a1d48ed2c2b6d48503 92526a2a4f3a617b69c8f512790a038a7108df70693170aad803110083c50aa3 721bdf17a1d57f5d868618a0ecc1b30e5c7c532d4313586febd088aaf1e6e0a5 b15a677ed4b10725e31febc960832c10fe1aa4fdef17c7689dfe10b4ed11981e c556abb91a48f5bf50334d76d1a57a158b724738b1958de18091dd10c248388b e15542597c42cd9489f86844ee28eff51fedc25230ba60b8cc0e4364bcf91b98 d393f580e3514fb5b11a65053286acb28f27681933179ea9a876b5f8f93b438d 89e823eb75765537b62451caf9716647134188fd01e20fcf5d64c91de0fba39f 3c2aa2372f3c532107f71b749d27c2e6ff868b6284ba697cdd6248a2282f7abb 47cfaaa08546aa6c24db8b82a782231827772af391cece7b743e458a4d2f27b8 022d88759e90a3a7fe32cf5d4a589e2b6945a534e72ab513416410d5e062d0fa b1fd2452b06dd3cf267af2838907ad6e951be731fbcc7948b41d4ab9e2f3e6ec 1e669738dd5d5b4c60d68ea7b83543be705962589858f38abf7c94154778340c 6704174c51e37e606f2f59bb4b0d81e7911a7106f067275bccc9cc728167969f 27c3e5582d3ae50115cc2ed27ec69dee741d220be586a8e4a15bf11061f5199a b3e3cff7095f52fd5d429ae13feb9bb07d950421ce8d6eb5545c9c9f37ad7e98 c4e86321804d5a694a9cb01c250da8cd8ad9ed0018a57f753a9727939ef43636 8747be44c733b2774d99dc0ebbadd1d5a265990f3a89ec700cf2c2bda2432055 f3fb7830410b46dbbba5df560109114c9b93cc53944cf66657bbf67a4a3dab16 211000e8e40923d62ce5d876540ef386e9bf3d3198644fcd5aa5e3e82066424f 2013502249fd648ff99a93f5c1084e6b241d048348cacf5c07ca96323798e31d 3785d7050ec2fab2bdd440022329e791610e489f9a295b71e241730578e270bb b58f968cded07722e0ba9b26a0be633d011797d1a98328b938aeda8a43815466 81b119e54b8a5c218ea177dcbe332564e8f58c22c08965e6a697595b708dd9f2 569f521c520a7bf7c26733a9cafa9f68da5c35b0c66f737e632a1e8789e68dcf 20f86cb06e37a7a714ac5dfec96d1b59babed0d5635e700fe647de211074cb96 7878ef11b7770e557684f57ca6bf19292f8249ecf579320baf1cb189643f0b9e 80b6f868d06af612f5b7607126bce9df1dd538b90bd227074a493bd0f5a3f67e 33cd0f98b0d746b94675d42147c90b1bcafe16bf4234388af6cb8cf5672e372e 96bfdaa51f13ab4b987db32c5f6c2091c930e2141eddea4e71060d78da517726 f04903094be80d8fadbc7adfa9dfa821aec0e7d7c412c43752b1b18fc02b2f59 1e1a145654e2c3a77663dd13c2e83bf42b183438281cc5ee4f9496120dea8405 50c1b066abade654288d38684a982d38a346295559d77e14eb87ab9c951b7300 69 21807f71e356534536607e1552c248c5a2059837c4ef95f0a68b93e98896d8042c4021f37da1bd996516b681d2e318c812d535e44e0bcf03a3182e5f3f9b130d0e3563b5e520c269ba709823784272b111a0aecdd7fe8c716a94acca97f41e0e8fc81ee5ca1e91977ddbbf4c74e1ba5a5f4fa6e88c7eb572633ae3b626c19c09a55f2a44da0fedff7dc0d24c27bffaeb448e90079e22d9827526a05e6d119d086ca98786b81bab9a975ecb97186697af5d18261bd74334e6c153512a3c9fbc07eb9463ea338eef67fda11fcdcf32693066e3b40dac22b12da3bd874aea89ee0676090323d26a5dbfde226b4c7958d9055e8151bae38d0cc23f443d169f49bd0ab79ccff97b47b3660b41db58351cec4bb1bd93589d1520788344bcd0a0c81f0f270679613d96a024e27530e45e96456833fdcfbc4045c2a93f8c43798f82e000ccb6f485d88d592765ed40c5775a9f6c8e59636d2181ab5bd07657c856bb9a05fa70638081a029acd938887391d4140cf35218382de51b58dfd6549244ead60a33382bcf3d1a98d7d644216b59005880927f4f4b592199ed9365b0feec5cff0fc3b6e40232ba8c6aff262f04bf4d4668dd28ff8356bb8615fae335445cdc4e08fa93846c258f76146d969c380a591c88dfabf9e201969a94f250e4035c66db046a373ead5283dfd066616f1295961a55d24af8b7a75384ce05ee3c67103da309ec4c2a1c47d5f92aa278b1ee3bc55ec919e394b69687e756299aeae435c20b0869c137c6c933f2bd088d5180e580f497e25ede00d2c4785efe9c6a5eada7900087147e6b6cce9666513bf97536a2ef3014a63b5a18ecaab4f7f28d98f56185023d2fee7d6178df4df31ee0ef47542967d890eb7e10820c072a10a685bdc39b08a6ce5b8f37811c08ef1bd01a1be1fcae84b6e249431fac0e323b0c51fe95c90fa8715857d597305120950eddcacbebd54a2bb7f0287dade22a9be012eb84f70dfc1a0b459b65d6c14ae09ed0e7b1ab4466f5a7623ba746335357ff157d670f0e4bce93bbecfbabc33366568fc36693b46840df702626579e62e9516f0e4b9e0202ab6b9d8a6f2823b05023fac29ace4b15b5ed8b8c6bcac06da835c106aeed0c1638e5b29b5572b72acc82611047287fc2b3a59093cfd318331e6504950437094dbeb8961078eab9c99d8fa5bbe5bfbffdd8527c621daa6e7dd5a1a0442e240cfcd5b5868bfa2da07b12bca77492675dc42cfcb566b34a359091d12a1056b70a7d6e449a11ea39fa27d7d7a696411c95f10b6551896611b1d4c4869ca2ece20364266d3b028c0435a1f136ff012de7c1360d18111aa87e7f12aaa71f78d2d8010fc6b0c6e87def7a42d42dbed8834da0e67aa29d84b721396fae096582c822068ff9378df71cafa852910d5011168379fcafa138bf745931c08de73a89a81806c8b08f388321ec17a80a34c88fcb33d38760d46cd3facd1d8f22d511be64af04cbe1e759fe03dc712f0f2c43219cb0d18f318626b27774b9639b90e8dd9a2603b121222acfbfd61222a230256ec665ae0f9d83f85694ae5b48bf2d0c2f801d020865529a730c1385a82dcbb77e7fe21421f5dd0b15340bf446945f101b3cc50fc17e4620dcda2c8f46db467c3e3ebbacbdd9758a4f6f81d1343449e7535de20dcb984a9958e1ca69466298ad207e287fc363c19a60779bc9e6b1cdffec47dd0c8e4255bfd134463693bfdd636398d148923dc78a1d53248df34db30bd8524500f91f907930cbd92a38fffa0452d7bc42ad1a025aa8e8b6372617ae071f3e82044199f8d6909ef38d2e8b6cc6802dfd1ec0d06517d3cd0293c18281e2b81a0b0513f67bc2b37fa38522d657843b27a6cf762ad6ccdde704a1fcb18e18047d370a1900afa71baae8b8750a2f3088edab7602ac0bd09e2ab536f1468d8f82b57701ad263b58586f566f7fb002c90ae537386e7df7ad41d8398fb7ad0b7ce6b64b0d52832acad8c5e6f25599d4e90079c0f0be88548cd09ffb976b3c4e87c7d9ae0e84302423f8f346d048a3d877752331b70e841c7608f89c1172d507734655e606e1d14675476b15cf87290a5d1a0bc7e2376c7c594b727d1d0d156996bbcb280d69c3353a6eaa79815ebfd2c49c52df4bf46fc256005023845e4bba0750ca80070c32ce3d6549cb135f05bdaa3de1730cb3d1793a3907b5ce1bda53a317ed3c0b05f780848676d2df00a812b2065e02910bab2660ea9525aae9fbce20eff9a306e80a54b06297c79ee6e29d574d8d5d5a6a8e6e7f32a74e13bd007d9cf247f40a116a086c86fbe1e7bc2e0afd9c3e0bbc3ae7b04379ea77cc55c93c279903d10d3ff3ed6aaddbacc75779fa9146892a2d1ea3901f19fbe83c191e634e62e8660dab541971156a0d7e483471a40e5040a3b75f1ba6df46abfef2ff2ce075db8d09065452a13ac563ca9a828f945308a74efb39a0505090f01e02d396eb82af320b14eb31120fcab6efe256c00896cf4b84ef1b6ba19b5691430b6cede209d6a90c63f9810f550e346999233ad550f5f7fee6a55364b26e51fda1cc5804b41c0c0ea52909a62b7f00677cfb7cba9c18f14336c61436a458478b7ec4e06c41f828013f4f7559115967432a4878bce9f861c377d4243162c601177255b30ed8f2720915581c12ce5f7a3f63c4ae2eba416abd39523e85279ade2532a00437f6130c03e4ebf29b8aafcaeff4908aa9b587459670a70623b9d56ba6c1ffe800e17bc90cf5a926310d71f4cff9c117bf5361c6229f960b46245554437b31a8bd26de2802f47f15cdcadeeae51516fc0cbf7d8de2b3bbde11b45c3c7c5cb6a58cc564a70d377cb8c1dfe198a2f3bd9569c6a01ff94d71f3944a779cff6ef278dbe363800073cfbb463b0fdae43f7005111fd85183028ee8644250c9670be031939da7840d08e63e81378429db095cab27595802554754996bdd2fe580350800781d64b80c59b87a01fad1383a5467c719a1c0ac0c0217401b10153b476c3ac6a818e80c0228b215a75ef433a597ae3292dae49d532d1b6812ee9291f87f248ddf47e99a01dff46bc464540adbc59cf39fb12e4b2dba9c64e0cc207a78d50d676e37d9630a575d1c5a8bd171d7211f76f00121bffc602ec6cb132a431c1281ab99e9cca00f8b653d76ef6c38b81a2f3e8092d1de12e02ef2d866aaabfb59811921651df206daa281d1a854b77958b955c68fd4d536f3090a8dca403ece38154f812940d101cbb9e4d85b2d796e84c2124b4bf364b2eb88bd80daf50300e011ee05fb132808493ed12c5752d9834f3281da388bcc75ba5f9b8cfd709ceabf63d50e700d8107828c6f5304fb6fdbffcf874cf05dfe16a7b2a606d739abe3f991dc68a60fb7074f32a9cb2affa4c1dc92a95b19bb4868f3ae4bbf4a0629e3cc5a46dc259c0d00ae4fd36e28036f1e947391326644498e1ca4e7a8f043057d455e53dbf31d0f0c741407b5adb73509e838bb156f801809be25478a7c7433283bae5a5a3864dd0bd49a0a8e9d0cf8d2d0005d6354758e91a66f45ec95e74861195a156dd0b36f07b8076a14281fe3f5c42a18928bcaf61cd064b36465aea87b7aa0ec75ab38f10a4e6fbf370031a9428baa85d5553e3ac0a1b1e4f56ade90d7709cd4f12a4c9b05c02511ac95010885b8a6001ad6c46497ef1c1810d80839662242fbc65c2b700a82b2b06afdcd6c4d253f3a06850ff1c1c04a4879711d9cb7ac593f53c04f5303f03c625938d81cb575e74921534fc7023792bbaca28c85f456d6c85bfccdba08080c7787f2e66a5dd660f21356a281863eaa5f1424312739a65560895fc0bf057df124c8962b5ec2dde027f46c986ffc1a427dd428c73f2575a3dd8288cefc08a062a3c67240e41978f3ff93436f89777b58fc58805e60f683f9bd6faa864e0126ee980fd563b7c0442a0cae99d33565a28a7372469b371befca5466a3846000d87056007539b2f0d79b5f413a182af5794ac9b950f1981b36bb9ba50c3766049eaa8bd5aabb317c91f3e32d9b93dd84ce5184f474ac43f61592ee70e424f509f2b7bb892a1317ec666afe4b2eeec32cbb7a4044e944d718296e74c1426d940d7997512871325ed1fe29718800fcbbc009a5d93da5c910e60dfe1b2430eb0a04e558e4f769f93616b079c1b5efd25db61c5f71d44f0346db37380a7f7846c60daa9c1f594832822207caaf744cfd28c8bdad9189165cbc2a676ad5e509e6680029362665b7474cc37f2657dc2b7d8e495fc0e8c75158c44a365dd7deebe16b02e36a6dc11b4fbaf9e2d74497ab1978052e26360f8a07c3ddb70f7d73b11f0407fc1d285bb960a853f3d7db8fa5a9b2dd07a664fb62de2ef4c4a5ca9ad79f30046fecf542355b6dbcd761e55eb3ae9ec32b969f64eccfc5ba41c1415d0763b90703eb78735c7ff5372a65236e1043ff08e77170487acd3476b82e5f0f21dc1f040c8460813abf7ace96d536e4061b64d08208dd3855d3d77ff296a0193cfd010dfafc42748e8f44bb89c2c385ead56cb0a6500fbfa83aa2d33c184ab37f2ea307ee97f0ad6899e1080396c7f5244d85a972b7b5dd7b101a8c601ea71e9a56ec08efc784bd9e755bfc7081763b2bfc3241b2382cc2dcc746c1c2adf2e0cddc4e00748b299641fb1749e4444e1df71397a96219d4f371edf754ae1c3bb859130d031b73e213d4d533cdbc6dc0702476273ce93127c95e87f27303436d3ec424870d58ddb13cff028723a2b211d5ab87acb3031f0ea5a03b3ce14199283dc2fafb0a8b8944d0bb6a8ba068b6848bae939569b554099a8f69b8e8aed526a4227dd90f2526c3bf44a34b679a9eb033df96a0815bbbe911c1171b4777f6ff6bf516c707dd2c8e59bdf6110df9f8ba3349e23deb479199b5d9998e61b3e78a57032f6b0ce3750f544215a14a72b434246083314684946b2dad612fcf550ae0e7a60343028c3384754a692098c30d38ea2100a4319067f73349a8156b94dee3a8a6baa50c8a02a684cfc3882cff7548cb608fe0f7652e7c1502370656656552a0ca7ef708d3ede8f5e472606a2b92de0c19d40f5fa4bdd6e24cd15bb0319ee66b13c8560f8f915d065f3542d6fc7fa4b28aec3ee3a92113b75c7bbee2ce7b85caf9e6fb0cf78c919c2c372535678f426be28a1b6aa4c878589e985b62494f52a20be773058c5a4319b5c107d135151e0567345139a3592e071fb96a035d8364416f8353085a4da7d68093a2a6adee33f8951f8697095ea093b5a28d6a2a6a1c09115c920ed3b40825ab8755e2b1a3bf2a57662aa3dc78404731ea989d385b674ac4ae8f0cf3ef4b51b8c82cb3bfec29c12934f0922e45b5ae2641788c82f9378abdd21506f5196b1f1c4e15f36c8268c2865681f266e98a616b69a19882d816dc5ece43027afb68d919b9514e18ed47fa5f9906686ac07b6e15642d7acb17f1ceb03bb309d70be29ffc8f714169e214148b628e014e9ba5a840ebcd48cb45361332f57109f69a1ee2cbd31ae2b1dab0a86269758f5ee68828b9a506539e83157be2d078001a88662286d5ddb163f5fcff2a305132f1c643d644bf829fe5fb2d1d87fe5b0df774f29b7ddfbacbfa290d638eec8e4087ab74f0d0acfc9ca6e19cee44ca9703c39867bde6b7ac6a654acd8f799e81f551b7df6353f844708ad15026a330410202cde7fb5eaafd7141150e89af6e23c31cddf13f430cb7f5e174d121cd94c10a2bcca9f833521405ec35f9bca031710c4405542d936a4588295ad30536aa8608c63f55adb8bf1b5478bf3c8990d9e367786925a2ade306ff8a4f44310bcc7501594cd0dfe9bcee0d004127f13c125ac774fdff5ac9d975e1b773a236dd02fc0ebe3e81b7c3fa5e104dedb761831388b49a08559700eb53be744cfee4ae2fca056e78c14495b1a1be73b257bfcafb3fcef8ec6410bcce57457355ba470b23f30add59d49217b65f06b77dd23bb70a3bf4cace891a1c8ab20dce3eb5889c56db0ad46120222ce9721cd1dda0e95474aba3e4ee98c5c0a9be3337cb812e4dc86b07912b27a53c3e04191fa516cd32f3d48f64d61e316dc4d751d4e042c07f48ce0de119e10d7ee53a6468d03ee9acaf0bd36219c1c83f693090c039cc53befce1065901717de9718811ba5ca6ebfa807ac0936a5d552670fdb141c12f19911bcf0afd846f5e476747374a516af468711dcd39fbfa923f061489352b4763fc554702e68876caa56b45de0b68c2fd801ae0571c602adbe322db947b2438bb484aec0df622adf8b4719045973ee18cb5215f2c4fd9d2d95a8c83844cbbcd07689d670406712d01f2d14ce08ab83389ac5dc8798277622fcc698bf97a36e13cd4cb950649193b7ed63a830159a33585539f1d22d1516659fa3891f67c281deaaa888f08583bab5e9d2f4eca6cc65b1eae7e7935f6e4e85f709207d4cac1d5394964930e37874c30b18591a9b420c5e0b460e50f8cf27e929800b8006f2be503763b8b092825230a2e884d2d9a26c140605fb7953096f59968af356b661acb65cae151071996777d3160cf40204cf833cb24aba69d73127cd5a6f53e101b293c3f07df0127c4d55cccd4d1749cc5c9612e128b8e108a0c34011687ec96b5e2cde281e60d776aa652d7f08e73b93512eeb14e14a60a93995fb4518592f1eb197a879dfd02afb1de3926e2c3141742236ad35c5e920d4549a2a8d6a970b1e1ae00db9bcf04f5e0f08df98c8f7432b531492c926590ac6136fd56306f8efe7043614ebd17044deb383d2e219fbee78f9cdf63825ae6f757561654ecadd5b8e28bc4e7dc3f0589b26005d4b159a6a5d8d27caf9a5507eb7aa3f2374c0e2656a3d1c088341106d1c38c1217e72b155babd4a67d301b3a109cf932ea59fdc27811d7c0c4762a0956eb4940c88d113ccc65681de6c854102d77a82c6075f53b7966d5421c424b0a8a85f1e5fc72a59338b59cddb3daa816bf6445f0ef0c02ce87c273d2e5de770751328d4b5869440e0fb58292223886ae2de3dcd35a0350eca38ec536df24330d83204fb31746c6283c8c61efbfa7d99e4cb17c27f3c9572014384610236dbc0b90ebb3c4c6be726dec00443f7e7424abb4edda50598e658b52235eeeed9293022ff1b37eb77c41161ad4554270d6ec2d11c25dbd4b36d6d943429fc4e4b529020081bc873782c804fb7a89f55199245ee0b55d839f0ab9866a9bdecb9b416902b081e532196f8597b497d578828e3f579a97962d7ebe328da5b636628bfc5c0be8dc2d0db4e88cccc1e0cef2c384e43c835f58cf2219dd3de0870129082847090804eca45c7059e07b9e4febd2c77c3bf02f5126e8921ec357a36d5fd46ec30e245865416799024c61adba5501d1e6a1810e27ab3baf2013da31949566b397035ddb58031ffdb585eea0fb301b0b67d739bc80c86ad4ec3c809bd49dec27100381761103e82118cb185f2c07a2a64f9676de0e0534205fd79b0c9a968ad9af08ecc95a4d782cbf56b15b7213082c25fba5a16f3999574dfff4cc9703792d6a00f061b05e8a8efc4aa087e6dddb15128df91f92355c4c335300ac3501fbe18b03dab3016868bb2e68f0c0d2aee37174665d2783a95f94cafcfb448d095c89d9098ec327a99e893a1ddd6b52e7861ac018fe68a2dbb8e7e1a03fea94af644e1201843f3476fd359442764609d39add779589f3a2c8da5e848d860f67e4555d300c601450698ed41e83ee306bfbe5859c66d028082c4554eb6b4394c5fb9ee06102a8f4e4497abb3af7b99264021ca8d2de203b37464284f672299b3442c7a2ad030c9e8f9068544fee2c1de301bca8fdb4e7a996ad3958c2335078618d8ffa470ba59652c9cdadcb367d706b0010e0a38d88d1ba52ba4ebc93322c2a8c54bb010f2d2499194362cf761d0d594464aa63d8d3590b5c4c3f8a0228ec02e9a0012f01b7233fa6f1bc29dd211463fd4224ebe57dc2c557e7b3fc50a8ea38721513f90906485d1ab6cdcfabdd4d599016aa9a0fa8eec1bcf49943292320ca7bc4a1eb0b34f786e8a4dc7b81ca378ccd121c09f2dbba0ec20f7145aefd4868211a3c52040649c49d07147be02435df395ed18daae787448d07671bcfc8697e624b12f1023c5710b65b7de9f62c9e253427b4819e17dee5d7aa2a509854a7d399ef1d5a0d35c55358fee19b9cd6836b3b5f1a456decac07abff363831ce3148f406533e0a08e01fc2fd942804c21a5ed4271d98ce3686ff2f7c1278dc15cbdccc80168b052ed1a0cba1e14c8f7ba7b065953d6ba340cd56dd8d886a9f8b1e1ef2ac3a3d0bd5009b9e2bb20feab1e0440c989a2e94829ea0f01ffc5dae5b45b2eaa25bc5054467aeaccf6170db78aefafab5aebe9bb3cb240141365a933c2194c40ef38c0eb6707ca694719713d74468eb24887851174a44a53cb8a7a4bfd61e8e051daa0ddeb397c87d204400958cf72841ddfc9cd71268ad962a8b815f030d057348b40d14a599aabd3dcd85755f4fa178b80a97d3275c1cdae97d26f45d57810e75f70cc0ac9ee4eefbd522f56890b3332216c642a7eac26345d1c4572d3146b2b4f50aff57f73e97d7ccfa54e3c276affb495ff39244d1eea42efacd11c3970ba90508281c67476d48e73048674f6fbda6c80c208df1d01c460ed8728947260dc7a80e8bb0ab568e1096c736f9f3740f69ab311c0f2d8f7054f6bc3b6883e83e921c0125e9fd2c2c8155f0fa5dab86d9c2b91c417f18e8e24845646ba5fbc96293d4016dcaf2621d40fd3c3d38e5cbee5ef24ad15c26175152031622b4a7f81bd015081f425e3716c2f940f7d1b73490274fc656243526180f8be43be13c2579caad0c98472be6173becc70707554feb37925c96ff08b9b97de1ee95eb976f915ccb0bcc0ae009b6e8d0f116394e7af83a1ed6070eccda664f038cb4f6779dc20a690ff9296e1f0694ea293627acba003dc4dd884d2f4189997be8ba66988e51057b07b6c9471cf71d25ef0d756f3dc76c4baf1c9de13958174af259d92c47e186cc07e18ade94d882809dd2c577a14f043fffe5fcd7b6944e56cbc675b88f1c77420c92c625567a08ede95f185735389f4ddfc9853e7543bdc483d878eec058860d0c537d8134777b23cec6bb11b7cccdc9092d446cca977dba95c830a4c484a70f0ee3917f751b966cbb6ff9edab3467f7900417512fc574331ae790196ea8d1ff0398e6ea670901800b150877188330eba41c382b14c62b9ca58a65a8a11486d5009d2a01a67f54328c3b009a156b44f27f7ffed30e0b04d38cfbcf091b91e0770e53201f3d5e841bc8677146e61ce3bc647a0acba5d3a940568e0c0e74027a800a1b83c25be06ba0269d9d52cfc16e511303071116c4841965c0de3105e5405e09e7b2dac14b9fdf7fbba45eb948b280d73c83bb8d4266062f4951034e1bd14301e510fb1c7db15e79dc064757d4f4d2a4747f8bbd5fc9d60404bab83c7b34420c5909c6463632342ed87cb3b00d0f18707e37bf1139d1c6e854089e09421522036ddf534c2e5080a60883538b31aef144660e92daafa3daad44503ae5d231a003b56e45558694782cea04c8949dea9ae1866514a84efdf850b1500926feca2e08d4a7c7a7aa1c3a354ad7ac1926087185c19d41df381836df5b743e646c24190f7fa5e3a1c404d8f27655c65a989f97764cb61ffcd0624387af29ed0374b6df064de9a91efda7e504435d7ed70cc65a47b3c5c2e5532453211846d7e607844c0f42ed7301493ddaaf2cae5ed67b5dd1e05bdaf6af277a4001641c19787d6e780d4742ce77456da93ffefbf7feec6a2102063797715ad167cf0d9e5e90f5d4f503ccaa7bb17bd10015444b0a31395fc23d5f62028240593fe2ab9c0c3492dc4f087dc0f63e66a6abd11070ba69045ef80a1f2c4f2cd44e8662330f56ef5801090310adf3daa186a524ae82e468ff8765d882e865de8c28d229f7f96adbd2abae0d8179923c4137a24202c0b4ff9e682a5aa158e8172d1efdc523d021ec9f37ef02f16c5dd35ed1b7484920b33ae4ff69655b89f6f30eb1f6864090736761fe4e0aaf8d5cc7dfcac9802da71934f8a9b50520badf21e07dc4571dde08cdfad57a0c9d9dfc0e74ef75b7333fa7349a07485ddd0580ac240e3ac2c78a86d47377700ed83b138fbb77ccbbc17ceba465280bf9f3836f91f8c7eebed4d419a6a2fca40282da21586766aca928221900268c2a6436a1c0d64e18fef0024688402d86ab0abca985171f1a977f8270cc60b8dd5ce454a3b3b3e9231aac844a984a4f151e01d601870e91a3faa786aad7a028f5b3e5e12409838e2b2168e46e17e57f583603404e9327ae88b00b94b914dfec1e54088af2df9d8596a814ba44a0875aebba0217c3c44498321f07149801983b87cf162ab702a3e36d9484a908b477d3a74e0390602e11a52f55913c0d20926c23715b97eb54acfdb4032e3b36531567d3cd0d8b18909ddd7000586c003b4ea027095d12d3bd9abb19561f1295bce26cd2e609c2c36d424ab894da43c47cc2deb4f76dc570d67dae88ad482d8d0f93b31a1d0efb1b94e0700d54deb6c840d2db4de8ae397195e29d819a5d4ececd13a5f23f0a5bfb181ffa6fcee5d86333abfd95b691d0d951f8bbe36297ec8607eb00e6110153cd7ad846c15003e8c9e2171a979b956196c175dbee74fec593f106a0219302786f7fd0b4d9e5a9dfd944a1513899a0414ee184ef86af17c5ef7b5dac02ec0d820906640c1acd6464103255ec96f7a76dc90f1bfa65dbcdb5893b979444e609ccbb165a73dc70f88abffae3e1a3786e9cc75840d5243afa0de2d835683ada048524bceef407639edbab890c6fd2695bb8faf801e960c21bb1b5e23aa2e94f05e915c1d88f296a34c4fb88eaa3fee002b9247234a65d2b3d485ef784d7bce806a7db21f14adbf56dcc3615d95a0671ce0e973754924c5ac891e4029523e9e10693321f0ba9f668bfe1ad83bd2ce768001dd002a46ac589937ee805bc8b75220f7183a9dc17e6bee01da9e400db37139d5d5f2bfab567f56c5971f5a45e300304f00f39ad39afcf02ecc843d9e93c229249ad547f1f6680e2ca27581e9d621a0df918ae6366e80b367edf6e97cc59773d7bb9e3691e167f3bc34cd95b1a8e7d0d800012c97cd4e67942d5cf249ae36192acb01d8b48d04e0cf4475636c7f8dd0dfb09890bb32b263c0cb964d703edd21b4e3a509697d7d2589074b930f4c5de00a9a347be56e0f4c4f59d62e091ba7057ac9520437bcb0b26aa9c66c668273c0ac75cdd7f3fe72d8d0792a87077a018744c02292c603a6475201886ce83d8a300e89304190ead434e518057f5d8dcbdb277c65d247b2d2c668bdaff700e783703ed92ba2a2e276265a5c58e70fe1b418c1219d2411a15c79d936263e26164520df441948bef0404d3d1c8797c84811978021d296b6926d648ca8b28463a840801e7888dfc2c5c21a6cf6e28aa0a74101703469b0af8086caaa0f3bddff0581d03acedba8da5e59f57dd354d413cf35f65479031aa5bd508f845de206d7d20c209755c12bf15a924e6a3a40f4f7846c5d02750bc219a5ae2130b8385ea8449850b3055ee15e2f3d62eb4c98d180b0a7aeefdf485c06623c17768007620bdc69804331a91cc1757b48410556b2e604803c6c67d35ce3a560602311b828c9757b90b4508f5c444bff75e8e4ac71094f0d380b616b74ff5e813b033cc18c7f2d91006c64b36366f0ff561df09cdf0713d8792c98f6dd17395ac14447381c5b90c4b04d555124609db930c7dfe231909a766ab3ecd0eb32c4d4cfc073a60ba5ab07c0eb52c10613d3ac397920830c13e7e8f6d09293ec1f86b5ed1772115352ac98d0896a47a17992c10ce9ef5e496e3003733353feec37de5105539242e4efb4519021ddb78396bbeec0eac62ec54cddc4865a468c1ad02c07f5d0c23c1b9a85a5200efb9c51d6e3ea194c5c8bf9f4c8d770b92035582679893cff995898821129b02b9630e7419b4166d3969654d8fbdba6f0572849d30d8bedcef91e0b472b21c0d4a896f9e0a080434df790f9284411d11ed1ff5da21552a6f979dd7d738d9cc0865fb58d781eef2cba1b0fba6cbc06932de1b19d1d0e4904118453dc746c1d1079828f0d4ffb5ff1e1c6c3449c230777dd0cc5519dc702ec8720852c63280380871985c651fafef2a7ba123b4a864affd6cce48fc2810e667d30722ff9f19b10115151b154f7c7983deee1e9666976308ff77ed799a9acb7588c2cce94db8b50c61f5a839202c67803ec7370dfc5f3d0619d578fa9aaefe2c6ce58a3eb1729a0eee287dc746f0db3f6131f5aa42a98df719604721ae0ef13a0f0c20775c53d00540d049c1e70e203b672331e66c1e25ec54cf53f46e324671af11422ac599820a72c1fbb59c53fb7b578bb0b1f504c03f7f22bbf83f5b7ff045c32e84ef67ce0c9f858b8fcb4e4644cfff99a776ce4a06938a12d1fd04d76bcad793335509080e34534fcc2839197ddf8512b1bc7c14aa01e137fbf0db058762250271e7bed10d183517e6972bab43084f640d0895d03d06675997063cc373a0e055508cafbe0661ff6fc761ddfb10063b2c61b37ff53de1e8cd04f6ac8b4fac4f70a5e9f3fe0da33d92fb6c714e3ca71bf5244f8ff0ee9d51256a0656e1869f28e9f36cf2b700cbd0a10cc20f92baddaca5689dd096fa4168e0b59945cdd4219a5854dc2fde009fc31a0a742be28dcdb8de52ef5cc20e6026bbbc01a5f742f251f189ad853806aad1adb69c2cbd12cc0328d76c696e88eac8e252e873f738b5031efd1002d40817e9282d946dfcebf2af541d66e7ce645cfdc8b693b4653206ca88f2bfb81e0a74a916617923709274e8e787707f81295603f196d1a1c11ae23d10ddec60920f1c86607fb381d156f909d9aa607a6589fb4f6d810e51694f826e56ddbc49280228090e40fb7e170fec7092ccb40c23267ffd1045b21b58aed25734b6a62d47057941a0aadd627c4507bbe86b1eab8f4787bfa62a2dc480a6dc255b94094c210a26b69430aacbd7d4ca446aa2dc8320719fd765c8a616dcff7456c925c7cea70cdf6eff6cc7480f53ac9a183d7653be427ea4addde8cea992f41a90f01d1ae209f3116b823a70cf5d25967c7dad95c637c1b81fbc0ae77ab23684af73fd70740e7b92490dd2d02e5ecc03f0d2c31a3514795668ff3cb4c785665f063ac8e3f506a6a1de911d46e32fc713c5fca9782c9041b4a771dfa4a7e000fc4ee27e89e10b3fe9ec821cd7631f108a1e7a1980ba068b73810829c5768de2441131567ff70b4b5e6138a341055bba7fb16599f8704024761931c694f6974ffce9af0f8f5a061aaa06ffa631b457f3d67b17d946195ed83019826b435cf65aaaf4cf3164e405fe9cc4b25ae704d682823f77b9a6a3e242e26341c51bff6db15ad61945a085030a9a482c41e312a5077a80da1e9b1a760644b3d5afb303a9072bde673c73a60b0b93baf4397ef103e48e97001b3fbbab794154ff7151f369c24b7d737241ef0d3f88797a365a787a916151cd9392e76f06c0fdd2da2e85ff8e3013168db9e20cace5780c92a6e85bbba2655af55341010fd0f43b76c513b630257a1eb2c20c09bc1cd68c5015a5f73b1254bad08bc84c7100350c7cafd43b4e10c402835fea0f6edef05971f166899baf1ebfb4e0096f3db17dd8f9387e45ed58ed642b3b5007aae7a88dc8491a07f33505c6c850662b292a3f2c3a65c1c9ecfb8cbcaa8be100db4ba3c506df12a9ac8c19595b0c86add4c3fbac7d45df6e91a2046bfc5fd20a52ab6073f99023c58c25bb97aaa51f21b8b94012893b3038b25c93d050c135036d57cd81557832dbd01d2b230b220d0dc7a84e682edca4a48690a017b3fcc504a41c40fd023e565aa6d15e99d504232a1c0f349555b8370d3421acea2e66af0eb82d84175c4f98da1fcb80fb7f56b4f32836275bf0bf790f1c4ad3b17423d704a5062fc8c654285e6917bfc9bffd80e68e665dbd74b5727e1fce02c6cf060e06dd479fed34c5a6e6c085729ba45a34d09c94ac9d7bb648a6b42d679134e8bc08f32ffff623557c9b53960cfcf2cd78fb00f0b4e9262814b24799d9a44b56b002834c91db8d6fc45e36df359360d452aafaff806d588223bcbe0fcddfca51790beb54068dd340bb4dab0f345e3d2ea30c20151d37966e546c23f6bf8d73738a09dc9c1d8f43c6831d30349221018ebb901b44bff7b43d2a174c4adc08d28e9b0240aecc1374723aae047fe34fb5763cf0aad158b50b6525a27d18f6c06d6d7804e2e9d39f7aab825de64278ec9ff183f08b7d20333944401c6b5b7a6ca2a5fd0e862a0cefa42047a48203d4ae4e427e9a6ce04c23c5dfe00fac0fce5eddcf76024f610cad126018f8bc319bb82459216a36928d964d6916170191ca9a8323dd0b141a872419db99500dc6cff91528d582ceddcc245290868a69b7f6d9d812a509a28323917bf9e0786dd77dc22af6bcffa6d6fa908dfb9789eceb96426739aa04e1971c48c9ce5418df5a0fdeb2ae84da5d5d053ce5eec9324ec49930892637064b60a44e917c25a61958de20d994d123bb71c9729d48a8704e1ed199d842500fc8325252a751c9b426433fedf63344ad62e7517e567a9edca5ba06ac1c3e4005c28a08894f1103ecebac79a7308d69023a995c2ff73bf9648235b78e22b2c1064def363aad8282e74f15cbec4c82e705d64bad9188b0dad43e3b4a7a495b1c09c612d228793d7a4ce11cb08a320163dc7d177ddc52fc7750b9ead57371b23c01a1201eaa5c3aa0e23628051a8b2cd91f170c69a56a4c12862d60351018462f0abcb0513fbdde9caeca851a6973f96e7aaa31f86efe9ff92d6cff98b1bfe2800308fe607f53430000f104c31035f9dd9f21a6baeb63dae98fa0d957accec70102313f304bc6cd2248b7f7dd9b497b8741c0fd746fb10811781591082fad2b570ac869ef721bc8909a06a9d08a665579164c374cb839594c0c1a0fcc4697be6f0e038a34aa3ce5356f99c75403de0f4d18e5524c406aef8b6ca85aad16a6ecf30f9e74b05d12286f3b7000877eba9e9987dc920d7588bdd0fe9cacee871bc3290979947d782eb432f4fbf2d6b0bdd2184ef72a04cd2316ec824e6500d788ba7e079e5cc224a7201e4083cc231b00fb6549627cab00b6d493ebba1cce0d463c99042792d05bbac96cdbb416604809e1fe1b27f7998685d5e49c27d04f04efac3b06442e57d01632c869c5a48d16e09ccfd1df6c306e63376c90762d35a7f244cf09061697e839712f098f9596d0cf32f6bd1ff76b7659d1b627fe7b3209078ffd0bf1aa7c7d48bcf4a0f98409e8b01dbf329855783838b78906feacc8ec6d0758091aaa46d79f13766e433b0dfbe42ca183797aabc3c738353cb9181a09cadd2805d9c46e32de01c6725b550e3cad4ab4d5e047716cdab08cae95b953ebf3da130b06cecadc0db4601a60b44f9847379a5d961926095e6c16f9789eae958ece700cf6acae2143dce6ce2ded99e546386630ed94ce2879cbf2082dee3a949d38040f0902a37ffd8627cc9445d11b05e473b11921f958a83f2694d85f6aa6d5bbc60811c26449569217e887bedb2c21672b5bffe6e2bd4842a4787f96dfcccd06f3007aa8ffebbdbd67c54aa5394ef8a3b05c37c0acb19542c87bed99be92a7845004dca73a6be6de8f03d86f78f887610a45c22b375be60c89e3bce66025a7070d00cef35cc273425624bf81552d0c8cdebf21853e1f27d7ec30ce58f0baa63372098fee116ae8e719b0fe6ec51fbf254ce382e47cfbc768d12c6d9bca35809e8308e46579c1fb9b931f1326cf8cf58bc4ccb06ac4ca00727aaea1ec496b6a94ff0caf2a051331bf31151433ea38536c9a64b84e856efa7651ded40817e78bbb6009660cc8e1ccc97167702577ce3c3efbcaf5fff94745cf737379b42e9fc2ddd504080c3abf9c6ec85867adcf51656531833343d33f341d2eb725e3c5e80a3d6b00b90c38c93951fa8d635e24b0b0a48b2777e13e28e58ceba05c7f9bc8f3322305b530f6a457319701669c0b135583c05a2c44c029988bfbd50827e57dd002130517f4b8c06b1b64d89f44708f9f9be94d0e74905a8103dfd8f82f5dcaa168d40a7da2839690c9beda2cc82f8b81467f92c3c478aac981ceb429b3a6a3e5d842016361fcef9522e3fb1f8511a9ce446a37ad86972948629d783ec7df5767abd20625fcaa37690501207d502eb1729f30394f4e1688e7e7e266b85c317ad2ff340ca56d7a23ee1df0c73fb27bb22965c03c5cf5cb04cdce8fd3b1e7e5e05578410a9579eb3ec10a76b94236f2920efdcc72d3af010f6fa23612808f660bf2ce7c0a87af607bea164a8765703af3d16f4df4d20e69f987efc9edb5a555124db54a096572308654574d0612f64676c3b223c8e0eb2007363d134609c8d6a742968d0522b2252f8cc03a25aab5774a64c5df7a7f6711546092487af84c4607483a2d0b5bde96f702df14927b9907ccf6eba88977ec7b24834253dfb6657c351321660848d68c7fd33113431c12089375bd914a449bc95526aa4ae83e3d165217dc020cd6e3f60c57897ba86e29c056396c0d27b491c6aba1fcbc2f402a0f2a1033a8052781d57ffb025d3648e7ea938514e5ed5f8cda1a0eeaef177772353aeb6eed0e7867ecf746a1157ea58891e314ef9a4652d59e415ad82b9b887c19d138f9650753286821bbf782f934a0064178ffe6bda710f4031456b48cecfe4aca1bc42602e918aa46e512d94adf4f218b68f955c158794a54a13e69375c0e48d0c43b710ac30118ee440d7a501e724c79bc9d8f08dfaafa4b658aa47cb624990fcf6dbe0e26611ff81f1804487257c6094b228c555d5330f9eb617294b9614574e2df9c081905a187b7333629bf71f1bc89aee43494b1b44746716d301f1b0fb4bc9d15025b2686b4a6fc04d026196a8ed9f4444864fe4d0aea2a8b38a3d2dc39019c060f27cd572411b5979e3b4519aea6540c21ba95d55e11b9b3ceb26d522458bc7e022d6b0359b12ec355dea821c82ddf888473554083d0f36dbba8e9cca999effa0c8b0f4e13e9559ee50fe42d7bd071ca97f3455a348985c25872593b0071e196059bb82db11518a38ff6b91fbb263f46728ddda2f357c992b2d803d5faecbc0e0891ef4f92ab23d624dfd30a9efa25fd88456c4e84abf1bb8c11f268b5e0ba4209844e72fc68a6c3a26564d0fbbfc88431da1d765c292a81391ec5daba34d31507ceb8fb3044d9d1d1f99b4941a126e0580a255fc98fa2bb7ab58259d23d0a5d0a0df0bea82ecaab07f30d97d769d5b40c7605b11735ec813875e61a551a192304f8fb030c02c6f182bdda1d6ae85b8271260bedc2cedc301947bcd8a19470eb02969cb572cb4290989b0a9cc0938bd92218c65bdbdf97101cf7da93be851d3d03debda376dfddbb869e2f0c669c287e71de604a4682b30931f8178c70b8ecb8032401da4c9474ee1693df584e3bc074c6b3284b0962871a784d94012f0ca2890923f0f4be09049085029f38dfc47bfb9f289202b5d00a3d19de77ab0d07d88f0ff220751f75ab02690e02afc8bc3472c502ebabc9a09a20e636ac86ffc96529013c74764728f136711f653a8c9c3c2b08e6c9822691973a41a7bce053b5002a0a84e5e6a91e15ac847330943855a0aaf01b9a20e4da42cda63404e9d1a15b1005daee460c950776a19cdc223b1fc6fba907a787790f598ca5d0034c8bdd9c5a0e +generate_ring_signature 4b99442b09d30a94e40a661547b075704ff7076e432907efa34f28fbf8f98c3a 8c817e1ac218112b22b9f47fd1d7de82f36e48900926febdb32adcfc4e4503e1 2 3596cb2eedbe31599dd34e5577a038571b60800da674802f977182ddebf3cefb b290773d661bfaa5cc2d1db49b3633963e714e9c1f3cc8d843fb7f9e57e199a8 1452ad276c1cff34d8ed225e848e5f61080b131f2500d6bd06b7e85f85d08106 1 ed4b0070fbf1e81b572499d71fa5595907ca348b232a56b19e5f14031f08ce0707dab2b3e7c7056ccd9b259f4401c6533a4a18b9f6bedbdac04445db0e4b4a09577f217d98681e6fcc7e24c3f85aef8b224ed3ab2531e3aec9f74d8c5bff940b6e372fe9bdc18dc0c8f088886ee30a37f59e8d2b4033055f810b060ab09e1a04 +generate_ring_signature 308bdb322aa460f8c564d2134e23833f4e567150599cc3cb027083c5172a9ea4 6025c2ce5f391b371ceab7d0e0a0718eca1a660603056c887e0117f0c838737e 72 2c78fa1ff09188a0c4c26871aa125e9078025ac1e49d77593ca0dfa1989421a6 4dfd23fb69675f8836f93cda1dca1f2c55b68a16435d8ed3902c45709f11ce2f 9562994d83657b04fc8a26ec25ec00dd6c2650781d81e866a1e4ebf78e0ee80c f5d9c7e8ad13a830598f6f587c48910b3cd4b8d338c90a3194f3cc6b8c0a1a89 515aef296c04dc838810cd2dcfbf8f4f42ebfe4942679929cd3247f333a7734b 0f0f309eacd4b8ac55489aafba5cacd746a1643399130d56ddfc77e826feebaa 464b240b5fa690508441a556a6e7043451d269ba3fd38658a46dcd78d449b781 662cf10b9f6900077f61ef37bf3b21a4b42e0d65ecabfcd5c593ec23da6ef016 48095d922127ad39050e52130b408147dced83e557b81f237e67864e68e2103f 55916c66cb8086f42769ccf831cd4356d31eb6c3411db78d8b8a8e5d7e26849c b72e843b6a252e3d6cb4f98bccc29bc494779c107d385cb52fc9d90fdbbdd43d a9264eb06d803e5d7c9f5054678d649d87dbfc7a2c826a2346e6ac929b55fc48 df7e5cb855d1dd60f6efd88d00d9439c92fde3b71567cb46aef17c76fe53e51b 5c3b976629247f7f10f4c6d6c52846b9b4de1d7a258d84ee0811d0a417939e98 55a366725e671d0136fd0b711fdce650b77559adf56753f07c4130f18a36f024 c205931d4633f04b17c931fb00f2b47b8b7fe2c9de6def25496ebe5f61640bca c3baf879f8a858219e26c7983a5cc8618af19acaf1871fdecdaba355d6ed48d3 5fb47938e220e2eca446595c8396c75c28d0e180c2b3b6c3b4d9c9c1593d3ee5 ba26eded826bab30fba456ea53f5c34c97a1b5a985dccfaf6718d1231db6bf50 d5c01cedcbd2bdde6d37011766d8a864ca0f53943501cc0ab3933a86ac0a530f 434dd5d7e49617695b786c2ed3e851b1b76a5140369e2a390168d21cb99864e2 f87c29400d724f5c0c8e4e48049538035a4eec610a74d2730ed76176efbd84b1 ff55b2cd5d13d4d8da692ca9a0d1af104e1df3414e4b0b1821a56ccf676d3562 0cd6a4a67367d58f553ed01253582a17d8c85d8434b790fe0d79157e8b7a3fd4 27f75211c127aa1f68a3d22dcd83200fc3916cd1c7951e538600a31d19202599 3a23e03dc653bdc805cad9a038cdec71a0bb2bcb6de17e2db4467df3639ca7ee a1b76ca66834623b4a2445c7f369cedb1b2c0e884f938598bdadd245822ae52d 57e14ac6cf4de2ba8f4a4fa39131a40ff02398b2a2217a0747b4645c5eeb5703 0bd34d6cc73e4824f3b96cdc68b939fcbb3f3d64f85db0e2f404189d39e1e3e1 abc73c606cffe36f175a81afd69e3bdd7a6d534aa8da4541aebae0c5d78ff2a6 23eec063528ed18f12792077cda4ddcd7623b8ad7a8d9f194c0b25495d6d774f de751896b52bc0803437ec63efe0f68e6c25b17211373a6c083e9233cecd4c2f 88be6f30459ff0a926a4d7f57b9a71b55250e9387208b19b235f4e69511ce887 d64854d2a0eedab738b9155b41b30d425512d2165fdf68b60963e6586f0a75f8 29a1235869a8d737511ef31916570692eaadc9fc5a836419d91157959bc7408d 0cfe56ba540437788376011d248c5b0addffd76c8f183e1798a81a05995eca77 1d14bbdc17e017020d8c6696a1780ed8a92c1d25192da8ca83a0835ae6ceeecc 603114e5f9220594cd088b81a0cfe4b54fd73e0ef821e478fa1b3ce7dceb32ac a0fc34ac08c99f31ed89e5e310ff55208bc3fa2b53a750383992d460c2a12dde 83ed317fa3bcfcd2d5119593bd6e24db04b15669af5384d08d1bf32ca220a60a edb90d89c6618a866613546e755fb50ae469b95fc7148baddae72f531090e1c9 d29ec006b1a758c0cc9c6d3d9f2493295c574f90d6c6ee53840ad28c629fba2a 1e8eaaca2c4a8ff4f4dc13490237a0a97f061741c0b06dc5ce2a6acff153bf94 68df50cb1ef38e0ae678b4d449ead853d4845db7c1d41fad198cf2aecc594d13 e01e97370bb7b5364dff8611ae6da78f1a38102bd5e03c5e24eebf24f4ec00cb 5553e29cbf778f6b48e8c5e2a68c9bf3d81442e1ed81f25ec700a9e23a662466 23024f3db8eaf17fb8e0e05330a1c9760245afcadf2efcc400df7c7d17a2f767 a827106be8428f79cea92551f543d37393685ea2a286c66cae92f8182cd39605 0b08a56085462887c422032a20128ae61ed97dbf5e74fd8d93cdb1b6e19461e3 3b2c211dbd384da555d95b648a128b56ab6643b216cd0ef0b3efd2383428be80 ef5b4344e2685e2cd651042f3f03dec4e83d3fae8e19f7390756aac1252e8a2c 6874856045a450c60b61ff651b69e34e2c834ccc28f7f483485e43f2b7e619df 397019b0b5f8892c9cd5578270342cc060f29908a62afc7833f2132ddd890492 56cab4e804d55cfb63ce4827aad3984945bf52a980afc5fe65fe9724217bc007 516eeb63ea2cbd880702aef419a1a7d6b300523168bb60c1c2f2176cf1d3f0d9 0e9ae60794a835ce5d1988d7c461eb18f25ec62fdabce76be9ba7937a9f69217 0cb857ba94a45956dbe3c9634d5c0cfd5bf97ad640af92d0b99fb0544d7693bb 2095075d719d82294627cabd25b7dfaf7158c62ad211c771d3644c29a5e8bc7f d45ef2f378c76e52ff85f3586e3fab64411eb387e3a68d54834160e9d4f75195 28e2f30d2847b093194a3effa41f01428cdad1f2d20cfba6eb5139f9e0163a5f 65bbcc93001475bf68096f7cae42be2412e3ab74a60ee2f4926fe5c6aef83f0d a61e3661ee0c48cd01ada4fd2be409d2b461acddb708ec548cc1bb0f7eae6f97 d26de17c60cdb8043f11c087f8cbdf014dd27c7ca80a08fe8aeef96d0a1745d5 1a493350e3b85b91b47d8f1f52effbe30f2927f6f86b73d13a1bba57eeb6c67d abd5c231d76667750f9d4a234631bf3f72d067f1b88a4b0926dca81004b3d0cc 1a3e09ab6047738e738872c6cb46d5157a0978ba84af4e4f4436fcec61ab6e6b 29231906cfdd684e0f4f21ff0b0ab42e9969bf6d6064b38b735f90428296105a b4f5a4ed8d4169c040d9a4c387eed3e2a2282668f95e5d59cda02b9282432bb3 321e8195768e71c1859bc220da29d8b7315671615da6f7a1c70a65c08a1c435d b8b37d590b0147ab67db2bd9cade249369b44bca21e7027d56b61f375e643a7c 4f8253bd0d973bd1079b792ce8e714edfafc5b30625babd7c6c2a9f04a25f074 466cd2e93630e51c245a31c4d6cd4c6918374d45324eb23022b87214a23d4fd4 990b405d17c5c8583ba5b4967781da5456316385111c52d4c1761d44062eff05 19 1548d90dcce9ab43e248bfc01034d28a19ec4355d927849f7553b4b289830303e8c82b37157120c61216e4711c7ef107591bfecb5e24ca746e0f992984082205043ef8b7fd5e3d1dce67cec39463a3859de87010a75e964cf2c09ea2d983710b055fb8000c5f8ee2f7c10d973d010548ceefb1699c5c80a24f9fd264fded960f0a5b9fabafca8659199e076a78283d6f291d79890dd0568cd654fed2d0eeb600bf96b8306a3df449b2bca6d176073a106e53e3a02eb1d5b12ccbfe00341b3b0034d3a83e9aff008d2f029b1252e62d55b5a7c0b6b30aea3b78ab92131fca1b032535f849044c6567bbe70ebc388d898fa231bc2e61fe387ba4df0070fee797005c443acf774e192170bbf7df813650dff1c4f38374e4b5a6cd4c1636103b220c93405333c6622beae311836860a889aab363eac2610166c6912619b6b4b69e061a720f5f99dc9556b8031b385f732db873767b09d7f550d8ba348a686393d208589bf347f450bd4a3e5e02936cecfbf85f3d23828f3faff9d94f3092c13d640e33b4ff8e7cce8e22f86ef223c3d20685137817bb092f3e9253b3fbab2431a20c33d7999bef831c3a149bf9378113389e162d3a8229fe5194e8c5f72aec836309cbe02c4bf37b6804d6f261b6d0d982a7fc3b6652b6834ff24e01925dab1a100474ef064fc1efbedc116ba9164398db2b55f59289575a9a30184895c0caa13c09b271afa9455ba5ad23295ce604c2623600266922eb11d82b0a3fc7ff5700ce08fa19ce5e0869a99279011ff7e58dd46f0728d2c481d4e25d7298b2a57755d40b9800794d6eadc7cd744fb28d72c6fc830e84b71e5552af17b083120c6d688c037be9909484db11efb31fe69490e694c903f1bf93671c8b92995347ce56d5a70400779af62ded79b10fadfd9ac1764a8077d7c8949c477847701459f10baeab0da8367608f69e61e6c14ae2ab3280042697e03717e6b734d70280bbc9e60dd309b4167d9e058328db60916d48bc61c35511f642fc84bce5c485dfcbe6b130f60beca65c2b424da75a24a4d3866368561520f8c315f67a14d38a47b60147de8a0000957e317d015fbee9c1721829939c95b1387b72023e209bf4ad3dc55d7cd202fc77ed7f91c81d1b55e74c6d56f5584b68161cfc978f406898e5ad417eafad0813aa416e5b34cc21838ddcebfb8d276bd77fb0d6a6abacdc774c676be02510001aa2ff2387d1b6abd1baa58c6a14668797a57d5487381dcc4abba1cfe90574000ae7ef1a808cdd6efa461b36b54c30881bd975f619772d5fc9d0b3c503637209ffe76828bb602a12106f1d39944b45b8fb516ba7ffd6769c5a56900a4e9f130f5a64a5173f468db7f56fc52d189616825dc996e3b4b2ccc097b3b858c12511067a1de9746514eb68226090f4962047091ce5cef53db00719840cc23687cd730ce0dc8d665150ce694a3277abf1183d62a7a0730e16286e0476bfcb32e287e60b61ddf6724578e6f6ed5b221c565fae8df2efc90bf5b90ebdbc1a3fadc6f0540f9f01b0865da5c8b83bce5e7d2b1c1c3361cebc685d97445af9eb36596867a0084b483c0011f0f414443909d368fa8e1d3578a88e69b07dab67c7f2ccc9eb0e0df783767bdb2ba1cf25d60c2bc544d40fa98389e22fa65879321dd289405ffe07237bbb2b33aab42aca679795161727fe472232597323df6ec7e7d424ea4df60453dd5a3eaac1934222299210d9521dd44813fd68428cfd6ff558c418b6f81b00e2e2fd072f6dd56b9b9a159f6fa592e36467b310bd9c2c36a37f3d8f3572e90fe437583baa28679f2eee32d4f6b492f7645c9586bcd19c2745e32e7dc7320b0337512313842faaba7e55fdd51b419c2ae5c805d8288e66852ab2c331fff8af0c7b48c92c63fa84b288da54cf08ad2da2934c14b7f3f0935e76db8e5f1afe1d0748dddb147aadf4943e045e0448b5d2bab786a85a11c710c51828d6ed5ee9b504a53a08e5f472dccb019ab8875e76e73572efa1d6c88c849a8b975750a334b301ca185e101a3f41b90ac8b4a9db4da764c432141f9a7c86a522fd6c46e228610cc7d6414ae413ff6dea7778142dd808998cf3ae2495668a74326dae1136052a0101f1da16df5fd0bbd321d7f5f693801757d6f12a20c251791d6391e3e833a5099960b5329c02e88c48608a68af41d360ea63c73c95ebe52fe624ad1cfd3a1d0216a1de5fe4fd39d0b9521fbbfd78eed2d3703f9cee0208f78250880c9b0346090992b95bc551edd606545654e3f4859b7b1a1e023c4fd7f86d251c282504870e56b3ae705d3b3537d4b1cd114c215ceb56731451aba5db7fd8edc0a2f9caf50f17af24fcc8cb6af0f0c06559efae18fd8e38fd51ae7a6b03db906783a9e8c10e1da5d4e0e37d3548c9bd14134761a8688dcdedd7d9ca6cd03e9ce2ede7d0ef0865f6d77b4e472ace4126cce423f878a2581bc6d799433f67e7ae39862f59a103d0c5fc5a9a86ca2cca982dd0212bda765a48a0a4551252ea2630388b235ca30498b517fa80fee0f458d9b1640b6441fc6078100d268b7e473054834c52f3040591b845f08f5473419c1d234a4a83c57aeb9db06e65ed3b5a42dad007bbda6001d5af19e170d61e1874484a07d414f9d8ae8a9cb78ca5eb82e19112de940d9c0446a923187dd64de324a1cfe85df417742db730ab15f6ce4d48c28b59872e8b0ceb4e906ca27dc1badf99679376535e315499d9abe3f1ae766ad155ab40d76103efdbb3b375db760f2f114fea19520e9c30edd14ed8ba79af1909838af3300a0a4de783e5b06b5619450211de457d07bb6cb5a1ce107d05042146a8a2982bfa08fb231f18b59f2a416840b92cc8480657ef2df2226a170bb5f25dd9e4ceae7a0856ffe10f5ef5dc1fd449decf21b5fb558e556197d53827a2ed88c8976e713a024cfc5643398b158365216dbfc9c1f657c4a81d999d63df9dc2259126f4ef3e0503432b9ea78865b14b8413c6721ae7290535869ceda71d97a5665459ed9e1806a9968e6361c1164968dd4cf4bcc9ba28c482ea38c8ddbee268d3d9d50163b4013dd5cbc611b7f6879b068672ce19abd9bdd572753bc5b5a61a291ac6f4afb202016d2c80b2bf39952739796afe4fa699b762c85587d11f18163dd3f0f3088705174480b27eedd0ccdb59194c21ac8416c63b6c38ff3b85ff32b972fb6a84930714f4306968e96aaa4212bbd29ff39ae075f02b2a0ade1031b30bdaec186e9401b615ef26c4badce802cc714ad5b808913e41ecfb72163702b97bb18a14a93101bc9dae3936df14e170670545e460acbe1e51ec756fd5542bcf1ecd9e50088a085f1923bee4dd73d1a82a3abb492d4ab7287b9f33c548cb0be80e6382a4782f083e9a5be2709986a52a4212e235438bc28ba4e8d74d5e3cb0ac122869a42f460e3bffb1f0022f7e8c8947b2fd677d3c148876bc11bc0d1ff48ab02744736f50020df4e2b738984dab9ece08d4cb6b2244466a8005cd381f766f888d6edd123204a4bbf94a5a92add61655834a959e9516afeb5ba4f949464713c9bb721c64ee06c607705803724ec1aaf927352d90145dad07f1dade956c0d4f934a0df14b0005c5e46891291084d940792cb48fa2f0b985308a941e9e83375a1fa8330157530652a878cdb1a0747f1517321424181a5243c0786474c331b85a2c599b1a1c250698223770a4a461af7897491005c71be734d55572bd22fd8fb4fc4e2fc3f6c7024144b0a950d58e2b0452333a903b694c24e5a668e0627f24435f66c3aceb2d03fa326f7d5f96939c333003c14b2e1b076162cf9d1beb1136a0245bd225ca910f0627d8392c1b13a2d8ca1bdae05ae4c4668965133b15c88f9b1bf76897d5900290996237522e41abc39bd1c71dd8aa8377989d5ac6215f23a274b7c1bedee40cea49f60cd0fcec773b3dd99827f3460b12f759e592b817a4211bb6cd3282bb0c47388cfee71250a08ac6191c7ca93e67220a25cc7b787f8e48093e3dedcf030eaae63a1e03cace1f807e7b6a3bc4cb4d102ae93eb8309e5e4aeeb08a18af730a045a4b83a00a258300f506a99963773439c9c0bff4bdedfcb4718298645455072ce38c10cd912f31e78d6d0508ac19bc5daf3c00273dce16293b5bffcd2b8c0c936a4941d7f411a0420039da80c8d0677730d4e2d4b8435ed7fbfe4ec042be08d70ebf121fcd9581437ad540c0483fe1b7d012a9d76e9e0f7b202ee521027d07181d57b7ddb57cb608c41653b3c79b2359d4c7783bc2f8624e72691a26d35f0df01c422a9c744e8267110efacf09ed678fbb539743ad19251a82eae5a2cd840e15652a22e6d60f9636df5c168c34841c5aa475f8e2007fcee564b5a445387c07303fd415b2ea74aab647febcf5c73c974c6f321e52df8bb827357beb42e60e0f43dd97c23b8e73a45f9f3046b08290008066d4bfe5e8c770ba4af256fcd0f003288074bd65529500ad54ddfb45a6e2ec5cfaffd7716f9ba14550602f3de7d801dae6f1a480f7836b51381be68a178f41997a8bd98cc54afda137c96003bc320cea216eaa45da57536df1b7f1ea84a51f96bf0f4f0cfae77f631990a6741abc080bd4df74e3929b66a2a3603737a6274e1b03dbf7abe7a814a0c1a91ac6933701328b142ae5247f5b91d5f1d6d5e676bbb0b9a790da87a4571b2d7f69074ff60c57665303e316dbfa008c8e9e7686fc2c4b7e76813def0a2d007e7a4c0bd2e104a2edf7b87ce28011b78debc7a7770f0f493674f93dbe8b6cdde89aff353e07095a6a14090f9c4215bfe23b3867843b6370319c9beb1b67af02fe44f3806e500b1c2dcbc93a3e741c8414e073b2290fa3bc21aa90ea80357d73a8ea5bff5be5012ea41b72dd7572afa81d7b09845b9d5318f7c4197359f0c4f40925b5fdab8e076b81407b1006d0de544fc16908fe6b59ea2e11c621bcee70d9f9cfaf21e44800e2d57e48c6daccdb6001bd23693e36bab674cca1eaa27e3abd617ce2cca9040de7a7fc5fd0549484847b142bd217ec43959e092d950bd4956582886d84689f0c8d8b75a4abec6ec3f6beb0d82084d018c33a57704107457961a2bf8f079ea209f90f391cb50dae3c2f1611263576448d70449fe30645af946c86851ddbdf18019727f506a36b00ed5e35abff78ffeb2d106a8da732d64917614ac4d5556cb6022e8aef8fefa505fe293dc89dbca410d7c22a524358c6351f7619c6ed93ab840f5b971b11a5308eb18bd74aabb8270b7ed94d68858020ea416c2075997475830a3ecaa554b812c104f67472a94b02ce9b5c766a90f40ff0d35950e862ee3cf50cb1556e62bc04f564a13045255c7a80fbbcbf8c8ebdf82af3fb8233ec80c4c705539d5e6ae645766c50e0905266b734484e032c529e1747242d5b76bf03ca9209cfd5d35ebd5a4b311a6d3bb7e7afcf340c18afb53145556a8cf78933360d380963aaa2a945c47a134d5183d31bcaa204c83af7458b9a357e0adf1f2f63a9010c7903f3a4fc2189b3374a7c27a9d95c5405fb787af01864db6986713a25ea770db16de51d9bdc11eff18ff26f871fd4e9920c57eb7ab537f56898a368e615b603d13b5cb665164fc6696b5667a2ebf828b37993fc9d3865f4ac7cdf8d97e52507afe89e453cdc359402aed1f7f4b45000def9c1167ab4723288849645af72fd0a146ae27c0699864e20224c6f5e9914425d2599032aff78ed9f27c240ef218304d9992cab0170546dc6b6b0ab40aa5ee824e14169a5bde5a42dad7107a3d08e0f8c2048d9581cd470d10049f3769683634f9e6b387070b54f2985e3a87fbe920f9f89de81ae8b54a62021089c9e2518bbbfce05be6214d3cfeb59b74b8acea001814b7d09d8b0cf8bf103ce787daf009ac204582622b7959384d7973d6da30f028d64255fe55e2563943421848e7db99beddc76ac1415089c639e21f56f7d8707cf9dc0187da082d52347469bf04fd685b69960f2736d6198a710c8ac92c3fb07f73dd4aeb85751f6a4c52d8498de49087d717a994e2005b34e9360f1471e700b523258b3667f2a9b43caf46eca4e48d78ad8e46750b175fb4e034581c7937c0159f135606df3e174563b8c4e7d6c90fb6025308d68651363e0adb803c42f0e03aef76901f55ec1512cbfc47dee2c871339bd6136eb99d95d7198bd790b3cd903a8f0be754fd553c7431efbe59c54a3fefe653978c5e49b4e1018d9c0633aef0e6e8a7bf90586fa8cf36180f9badbae530cb946375ea286472093964dc539c007c05345a441903a7c55c92b92d932afee86e8b7d6f923a7cff3559dc2da358c0fbe2dfaedfa165adfc03598f176fd1e420c281001727eef40452725b7888cdc004c3a65fd912abbcd4b200f174401149092562370405267bdfc04a7e130d1cc05b8abc3791ad17c7f29ad6f1e360d87ea0ab2349f33f049e26b7154a5eaeaef017c06ee0f4fc43d0bf8fcaea7628b42a44d95b2c0ae979c37cc57733c45ef1b0b +generate_ring_signature 19b59e689992b33510cb3a4641a0487214eb16b6c4ec84f17a725a64d241eb02 35404cf6de872e69cc675a0c374d23085e607a63b198b243575c3aaccba5110f 55 96bfedb655e4ad5ae088e1170a9f8b58daafeddb84a3d8922c7a695e82e66963 b57b0dd3ab098d2e5a1cb9df3b9ecdc5e05a5a79a40c818eaddeb80ef3502be5 679c0ec82de8ea3d0fbbd4f41f61cfe30d486e8d2807a7b2da091c4e79cd7efe 1859dc973eb9798fbf6c7cd07db81acce29d707577dd72eee64a3d5373103ff6 4749c0e2a2595df0cc7608c1893942e2bf72f1ceb3e4609d0a12737f3268378f 34980ffb911d8f163de0a1f2da648b989d2b38f41e9525b4fe2e1f5647a15263 8bb5ae4cda78148b7b0333f2ea45fb88eaf413880cce4254f6e84dcea809ce23 e02027de37ca5fa4a7490a35a52f26d3e1bc1a462f8357c3ed9db7f7ec1bf6e2 dc30251df7d13fb90afb8a6360bab069a15a7f18b2db02a80da3a3906b96b479 e72e6290ad812eb649b4a722ffa13919d2e4fd49ff4a44d5e1f8d80976553fb3 70caa5ef3d0766d48c6d9a6728d0d539290b4a68452876c9b8554590429da46c f57560f08f8f42d053aad27a4387fb09c0c914d921b518f1d158dfdf16a4e17e 4655b554d751125b469451635239474a94238a5e59aa3ed0766083e11ebfb9a7 259012fdbf5f5453f7aa98d6b021c4da9214f34f297b11e32f1effed4bb13909 81b66e8895b7411a2c7b8390c0b20673b1ae12dffcbda94d5561646a6d461dee c62b504e655ebf52bf1d72cf50cfe4b4e25a67cf6e968c939e8baa09fe05ada9 139ed705b0a5f440be69de7d7d3ad3a2996d36f8f809f02bfd42398b02e91dc5 392f1fe7ff4620ae2a3757acdae3b4ab011418e843153628c3193db731eca520 33c7d48405a1112a28fe51de2e6a9a9fc35669d246f23b66b88fd65480c23a80 2ecd2cff507a023c57776b03ceb8e75536c3ba9d734bb08672b7aca0a81dff95 4608c674e9421be71e557739fc5b2b868c8e46717d893c499a575d6d1f6af1a4 5e89a1023aca7015745d6e134222ae6d36574605626c816396755f0be2d68bd8 004f0204e19cfaad23af654dc4ac284fa89229c2ef95b9bbd5aec1e0e106fe02 20087f0163ca1244c5d52b7d9c343f4859f0fb8151f0ca44fd58e9fc28622cd3 d061d7f431bfcafe091420eb0bf49476ee690e680f63d2cd8e57ee04ec315d43 17107bccfcef930b408cbaefb05256f430fea8dc5fd4250ac9dd5f4ed3fc2547 ca339d35f0fe605eb0587ec378bf0f3bdb44e11438f999c1bb1c3c5637b7e2f5 2f89eddb111d0b6d8ef5a6a5c265c2ffc491d0e9d09d0017f494df2dbc360f0f 88719f6e415b781c843652d420fd554d291f2c0e8cbebd6d7e0fad80c04c809a 6e0b292ee1b4bf0767a7163b61c7d9cb7d4cd45276a78913b07b73f1c3c1d64a 4eabea46bd0266491d0228719fc8073a404fd25a4e837accd5251a61cc87c02b 2017496e7854f8fc95f17df21bfae2c0afeb43aa28c245ffa1b5047dc149e89d 24589b406b4a7698016ffb8aeaf5185993b8502e46d46e3bf37bb078623496c9 e8e32089aa49dfe331db6fc798abbd5c3f2daf7e1c98263cc7869e66dc7adacb 05b2f33d72ae54e95169937adc6420774768db8a9e3d7236edea05e4455e18b0 6a4b66dae9632c12f4daab911b0d8b9945fb75c25360549c23291cd63744c3ac 8f423495dbf74ee63563293a66074bf15713e1d3f3a16ee4d5f33d414bff6fa8 3f53e929272cc0ec8e023cc81acdfd50852273ee9274732acc069ff56e8644f0 f0a84ced9df533d2a34935af3d0bd07d544b2e84ada7c3143df14a529302f09c 39100e3dee3d1985e04694de6a49a082df90f3f14e07837dfd96298ee8019252 895b06215ade6268bddf5c5accbada81af003ff3a8326701c7c4b2e4af1f3f66 a99ddc831aed70624f0e17f8e1ccfcf5add0d30ff448ce7bdc08d6464fce9e1a 60ce654405b62dfea39278dfa49bf1cd1cb640f60d3bf18fe3dab964832bb7b3 0f755692573303969da6af7969a990f4fb4d0d5a22c1c446338c7aa394b8ea55 10da39906513a827a213081f345f6253bf93cbe5717b8add690d76499580ddf7 b363a3561c0abb151066a5a39b623c9c1b7745333dc16e3ff858b227588b525c 6436c0ca822aa4068aa89054638665f1936cd2a00ef7c68c18a200d5731748f6 310c66d3a506da4d1cab6649b14f875c07df63139e6c4424791fdd7ededca9eb 5137254f8aacf7b9b331927b27c932f68a248df87954633c08bcd84cf7bdffb7 1616d9caa4875622e3802ec550aea5d449b648ebf710a77d3c22eeecbbee6f76 56441b786f910a220f80a7312b1f58175bea544c2831d29af67671af474cc5f3 dbb337b8152363bdca9c7c7b15992fbf2797f113c6e035310becf222ab12b970 36fd79a1708fe543dd785cb28caa54f1d2224b6959821294d8bad2ba982ad4ab 745e169e91122070e4320302d73305504072395f02a6eff85884be79abce0c07 870a32a647e2db50d03544860d834c1c4666eba0e351ff13c0198bbfcfc89c46 f708b34270bb6c3817c74e5227e43d13c13ce3dce8162b8ac558da1c2e81be01 54 a9dadc8c65a1061b423ed1e53d5828d6e63125105723cc2388bdb794d590da07a50778792bb4005601deebe971214179db3df008fe5d97a49b6365d916950406e02159a59b1104f72a08cece141b7df1391a81e5e62e92102ec74c93083f7c02bb126758ce4b5072468a8c9e78633252a49f94b9ef0045696ecdc31cc9306c036317b48dda42e4445f307ff910d29bfebc640800c6709ca062645489fbfdad046d4c364ec980070944cd1eafbd222c8357e2256f4606718377b72fc42e80df07f6314dc9a9fbdf81956e69969e4c4a8155bc1618f21f5745b6e95dc232462806028b302d7dbb6163fa3788c14ae1b69ab43853f463364a93360cbe7b8422410c861f4d13a3c445665d33a87da86405287fbf82a45e26e5c10b5550469e9f3507cc1d15fc4f5276f22e03ad4155e8ba56f56bf802e3927efe024a0258227232049cf306e84ed23c7419ba12fa48d05fc4cd7d0f9fc5e0e5919dde94aea775aa0d5a698236d3f3653499ddf3e6e32246e7e4a0d4bdebe50dd99ac8cc47d6e3910c5b724397812b387b0151d9c7fe1db04555b7bccbb6cea9fa037d70673105b500b65f726d2b3928dab55afbc5870e25cd176aadbbc845e1883ec1d8b14dd780080a5756b7a820455393cdbf75aa6da11648dff063dc1182915db97f0cda33cb00ec955b8109ff41e7e2fd519859f72ee2199d73d831a66f4d0919c637c630d30e0a8e967514c71d2736fc49418283d979f969c39a503c84b607f737ac1aba8e0b0e4909d1e2e842f295a73059d7579137dfb931f2362a1e1d497446da51d0bf0848aafb11ad41e963a0c7f45211bc524503ed2017b97b553448d69f343ad248050ca9669c8be7ca1615c1d4836d8e2a4d424cc2c2be302b236c8a46d8bd30960949fe54726ad3c3871624cd94ede0b6aa69804ba9f55544171db4de0d007319019abccc7dbf158a8e628708bc25b80ffdeb4fa1932436f50ae7cdde5bdcfda602db79108872caf07874914b459b246417f8aac5d7a563351731d29c21c4d6d30605008961747a04d20db8fd7c6189811d672a8a948ba843e6db59d439c0809e0e69e4cb7ea493121893fcbc58ea3afa7e9d4909e6a364f536d1fa1255f0f5580636dcdad4d6ba5e15f2dfaaad2f8f05345a02ac39d715a5c22cc5817ff9a72a0d0bcadc40c6ef13ce30bddd72f146e5ddf77e8f6d3b5ef001d9f87bdd160fca0618ae77ec6cca2f7ff437cc78934157f495184a7952a69d0581749dbb4a4f82045f2f1f55776cda7fd275ac14d1e62abfa868038106ca8151173df33f33ee9c014792395c1d3fce9a58a6da428f660fe6758999fdd52475bfd5e1dff9b387200b753006c904c3de0bba37650a66004660f51444cf0ff8addf1987abf051d4df0eb3cf2c718f12decb2d3eccd95a53e087ae0b85e47f1da52966f9e0f34a7812028b0a7ca592c7df6ba343f2321c2217fdaa7a659a9bc6a701123176be3f2177086025e5bc3111ff6fc3141c9355b1cb1cc8be1df7afe29256203a98385110aa0cf5610c1a996c4db92024a57a63707b81574e40f31f4a7bf92b3954f217f69c0dd997ce5d1e55600501058b578566330d00301001ae2b74aafde3a6798c40110438d5c2a30d41d6a1e2206bfbc3610990e92aa9e986bead84d686f9a9e475720b848785acd1001ab13021700a4fbde4ffa0212a751bfc13654dda23ca9a1c25022fbf9cd04f95fa2af4331419aad79afe7407f653619a85e3619e624aa6565404876651dde1474db090ecc6e7977d8bb622c286c9dcaaef4c240c0fae20f34904e4da7cc4015e260406c87f9745a2cb6eee401630d8287954a1c91d0843a1f702ee57a0900a7f948bb21396f406e350496f5afe83d9abcf8eb2483d0af453c30a5226324449b92f753aef636ec185edfd3264f7d2e0bf08d31caad1dc418de50579661eccaca9d2d300a1752ea1b3001e2be58a6aaad0249334629882ac5d390db863a3863a6045e98426924dde4ca7eb9aacf94af1808c4cef5152372cb0590585a3b668edd6dde937426552c854899115ba031f3e411cc3147e4b4593a5bc0ef9d0d24e4d20916927c6a0e494934fcbbafa48ee568dd31f920f48b45deca200a08c9ba8f441c2056c25e8ecf0019e39a8a0580ffcc21f3f73e5bf10d620150c54d0b9adbaa036096e2df0431d983a8c059f2920195ee805b85a4e8d24885c053b0c16025bfc6ca3d0ca125530b1d945a3b03bf149d2cf3fbb625ebd29795d0e098bb366a8dec65ace29acf8aadcb959e02b77796cf0db16877adf112383ca0964420dbb01ac01aadce2502e597e147c5373eb38191f76cb547182ea56bc870451409b30f88225e808ad47a6bf20dd902ba982ee34d87103387638d11e3e0b0a9c5f61b28897074c4f551b3e1dc62f30b020b39b6805c270ea68ed9cc4127b0eefb2fe1cbfaa9ad1086bcf8abd803a02059c02481fbb8bedc26bac402449d9080b5e7cd3a15789e2c5149cae4cbe88d3e0608697c22fd0428073bb2bd015250d98672264535b2ee62e559ef43e375256da548fdd7321187d1456feaa1339af0cac9aa8f6d149ba336e027d1b8a4d6819c70b3b2a04e38731d95f583fe4cd360bca59351eaa03712316ee6645a0bcee7ceebef343758744eb14c51499600ca600a6edc358e4a6b166fe2daedcf8988d4666083da05522287d98f555dbd0945d05ddd34e4dbbf0014d122a14892b0c9bc0f35d79e2770bc0ccc6203b60b11a32029e42a4fd5fa07efea52d7b50aae093d08fe2bfecb9fae99ab33c8ea08f9097016253e5d9f991a21b01ae845133556d1cfb3585d0855979d40c3e7de4c97d5e09e20cd0481706d2307b7626c5a593008198f758efeac817c985495ad96eb0ba05ba6a8a1a1a9e8dede26043d6c3f549d0f6164c11f8953030f24621eabad6880a96a6fc846a2a662fb0eaf75d89609d7b5362ca39f7898f07dbba0ccdb82b7109349e150a88afc4131efcd2a4153af304dad2dda0937197194b2ee7544af2e4070d91f697c71e237d0966b7785570c1e548ab63d374cb26743d4d540e299abc0250fbadfeb4982ce690d2283e56481d809f6f0413b79f5b0a6f98bd6c7b237e0da579e1ae7fb621ffcb814a3fc1f99689b78a8f992f47bde4d355944a47e5760f9c17ab5596f5a2a51082b08c5ddec7d55256ad5071379654e937f141fe5f810177628c21daa2af136e195d0ad690faadb41debd67ab93eb1e514293fc94bc407a234183739693564be9b873f7a7f788969c1da1883336569a00fea857dd9810e7604f45c6cb96865ad1503dd4b512d703bf16f652bbc0a653bdd62b4b11873003536265839659acc1d2da7c0f27a9ef4db7c59e87c6b69ff41035dcd132c9b0d294c876f11c30210d95ce56d61f362aeced7ecefd73a9ffa2ed6396e8d98030917aaffc8b00c94135dd010a80fe8e8f8164c86fa28b18bd9caa5e5fb608e7d08749c8def35aefd86a151db658ad13008dd7eef3ed3d78260aa090a680a7d000220a5b95fc0af46442d1071a87be783d477cc43dd93f80d0a8e577e0c51a4180c5f633b3ecf5124a5ba1ee16f98eae99544a37e17e3397617ee364b54ea7faa0a0e21be35940d43ba8cff07abc1eb338b9dd1804259686c9fc344310b93956a07b67c6f9c393d99884b6bd0578e394637f8f4bd330f67826d57e095869ab0ca035235b55d90b1f0811c2c941f03ccfa51f3d0546e1c3ccd955d4ed8521a40cd0e97e331f03ca75fa8019486cf625cc2c8c5751b896ffffa4b932b5a8ae619c805add99024dda69d3d8839c7347e899f2a70658ecc9ac06c8fff77a7a4355fb005edbd0802061ccbfbaba8490565952350eabcd9573fba632b0f6edda7430f920c972d48ce4ffbef02840029d55ed21dcab4a0c090a438cd30ca1405d7b878060ce36b2fe99c9544d27e2cce11e9e3d55470cad45df05840f29861f189869b2c0c0a665ba6807d5b10028d49ed0ddd2c7ac0d411375164217251f9f2853d46740121fdf5642e94d76a7b46515293e98b9ccf1f6f79c4b1e338b616d1ed8d72890e9adfb4bc23678e19917268a07b698ed65946946458ad598ba604000978e0dd05872599ed4a8f8ad2d0a190eec904161d21b69095f9070f12cfcac3755441a906d247128a6f3246f7f72b119e8abf9ea022c946181dd86f04dfc85e871299fe083d31c7866ab001f247a6a56b1fd5341dde2dd660c463fba4a72dd3b06f99d2096918904767a9d31d0296d8d043d87b0ee73a3c5be6dc2abf871adafb6393230ecddd27402000636724d249809ed419f4e7dbbea5c4d2cca76150b016309c2b0734f866b46fe186b18e0616facb1e4db47cb070366839fcae651a172145e3790ae96113f75419fbe836769161e9eb59e768f6b449fe84a68742d88ef103fb690cf37fc41843cdf1c3aae75bb779742d178c426eb1c41b0b89fd35b01621e8f003f5b71fb9d881c5bae0e414f4b869052d53af1e1188cb6b3fd40cdf5c953181061e4f3299f4ce6aa95bef8bc523af17c64e16504bedd089d736ab771f7e7cbe0c1b9eebff64bf0337010609833cef60ddee4abc46d34d4f2a2d76086006f509029e7a04822798a49af80dfc53fe3cb120ab5e7db0384ade1178e04a8100631a0cf4252d454735765dd6ed2909af333f4f51bba560aa7fe3a078c8c6aa8c2900024cbcdc41fb28934b1134364df1d8f5b49cc964db7bf6d2cdcb61514f8b540a0b2a55e214743312ea901c96d0ae4d6e0ab7243149d0de09495b150ffc921a9b0bceb7f71fde4b917b7fb625df5eca84d9418b7639b3a6505d98bb3b047b2aeb06bd6ea0f6cc677a48c79d4626658e5a4c9f2caf520b60b2d99788b79bf6886808008954345ec618d85c386b0e074a93d8dd57b3e6072d20909780f9fc4956bf021f8e874641c8940f0cc05ff35a2f0e628178477e461250e74601519b2d522d0b +generate_ring_signature 4672f905fb42dc0475983eb5a48f658a06268290809009c1c1b1d2c76fa8b2e7 1e95cfc5d2d71497ba502d461fcb7ea9f9768e229b9c268e3f8341a4f254990c 1 3d62ad8a5671f7bb33e660429e1a8d65f454ca409bded90f89d659e10284641f 303c8f50c931bd0703582650568fd4d3382117c521de689e1630abaae8a4440e 0 9af776dea0e4b4f55930e52bb8c9a2779f73e23dd3641d4c2bf4d1ae7c7ab004750b543424f64c68e91176784b0d020274c1e134444233ce83614783734aca0d +generate_ring_signature 3c562fe4a9bf99c509f2e8d4032d42128a7e92b168392d9538b06fe8f57ffe7b bbf7fab81426cd9d7f448815014c590fdfdf9438021002f067664326bf4c972d 21 f766397c6872286d33fd553796dbfaa31e7b3d1fca071ec0a4460dbf140a9f1a a6a61c5ffe6b77455c458b3cb3e48ec99c70963f3d0b7476f2f3fd49d798bdbe 23ef9c123a46aba32944da02867fe6dbb83456fd81e57ac37c04fb398d748e2e fb3870eee10bc2a23e5cf82e0023c95d7de15ac76adc77a78e4a4c15a743b52d b433b1ea0f29c61a863315d234cfe7abf86106226da82d4de2a59efee82d4a97 90c7cc26068024a6a5ea19303358a9768440254c5fd395e60770dd114003b12f ebdfdeffcad6e468659e5e55c0702cebf169e0b6505bb802101acfa7936b5971 b558862930e7fded4b64474777d7e762f252d7e5ef32cc0862f259ffa0cc074a d10554549af45f28017be503d7f9d838d8c20afa543b0da9cd28f45089401038 939c678793f7619c5985f478b78f90ffc9b3de93a2aaa1674ea9a3b3f5b4f369 e639f8e4a4196ea5094fe047663e959e329ed2a9c5b205d4192213c5f3c45201 1b4d75055248504ac3c2821e2cab34035c4c28941960bbd177208e10499f0bc6 1b6e7a5ea11b4e4a042e2e197f06dbeba08163e681566fd83737e209ecb69678 209c34fe577f2dd7cc74706175211a65b87489553fb104c9da0ff1cf5e5c402d b1ce728ee6de1e258471179dd350967dcba276f7faf60a9659756e1d545811fe 8b8d736c76157dcc516cef83ac9318921e9d6adfc0e4a40cf686fe71504d79a5 96331d76ac46063e2d60b4bd809c91e77b893c8d9e2c53d27a1c378c20ab40be be0d16a05eaa11ec4ef8283d5f1b3ad1cae73883c059d855c7d0355c1249dd23 ae7000fefca7f670daeed94a5f3ad56697fef12313821842c0981271f2142d77 8c5fcddd3f4b3855f1d17487883f33fc05eaec1c7949aa9effcf1e17eccf8895 8900e46d54a0a2ead552e74ba2753b5c8d2b15e381daaeb48569029433d6e8f1 edbafd6cb274f37b1783450c83485489e72afb99e07afebd2853f9997418980d 19 65948e78b6cfe916913c45cb1908b918b15a9ad22d811da44084fe94a2284d0fa53cc2267b53e5d3329ef53d4531d60e51688a45e1556cc38d6dd787305d180779323e6d837cec5fb2c3dd20089c2537a95523bd12bc1d46e4a985f64fd19b0aa7ee84e9e2a0cfd4438b4949e44e637e432e3fda35b6d3610948adb37ed84d0deb4012fd79bf4b34c0d3b5eecd20a3a9beefedb224afa0ea1d61f5fe288f8f0540f4515f2fd4731ce06be5a1e3fe319b97bdce5c9162a4269efaa55f40be760eb711b1f0770f7a8f3851f5eed2403193c57859ef3a9c0dde5c7ccfcea87607079bafeacc171cd555b4683cac10174e7691b6050447811315245ffbdec8b10707a61551307b1731e08501c4c77d8705f69a0fb5f51d44bea7a1757ab49f04ce0ce5934ce66033bb3ee52ed145c02852f0c817579ce9bbfd0dde35dfdeed34720c73713c4d18a4620608747f8ba3d7350e5e607ca0d53efebd3521373a49cc02063164c9bca26f0837f32c1aa1fc5c60bb118d1e760bfc7cad26aa58a106a30e0ef26a4376f7c81394c686869e80dec659aeb631521e643f8a561fea7b2274750982c647d92cbd9ff751b37249af2d628290ede9b6c9bcddb4ee2b64d977d2680e765ebd18e7aa240fa0e7033a84c644ef686ec0c92bd4b5aee22cdc307b2b2608ce0a6937eb4caa3624251e940bff10e433e85dc72752f4fbc020ac9ca0ae160ed6e345bd91b7f27fbd398d1a271b2a910025ef90186d48e134ffca401f6a6a0beb675c4c8f54d2b1008c103147f1a034486a05e7150ed3fda45987430573fc0ba4bac3352a84342f17d1da8eaa5b81014fac3e5cd165e4659beb9ab6c2b4910b3d906e77f7a8b34c20de1348bc9cfbf1ab4c6f824f3fe4dada7169cff734600733abd9bbf0137aef6901d11163ef1a0e130f918fac0c90e8e1c280031c070f0bb38d38fe55b844581e6677d313fc84f0bec9feb764b9f3dd3f6e63b8ceb84f0e2f8501f8bec43dac4416bf2af1246b4acbd734abbc7404905feb8bb936420d01c24f0058a5019696d548db36ca2a8e8c30d66a6887f37972f90305aaddbe5d06ea9bad064434673aa92466a2bc13b729f1a5acfe1e33bea1552b283b2eadae095aed91a34452ffd064e1033868b7869829061046022bc7ee97882c1233536105f25125c17a81fcb43bb1d3ef920cc4abcac82328f6f01c8fa1fa763e2d13490756b4346b89e664b2666a99faeeb06a7087108c65c7ded2079890252907a7f4094a244833a3b184f08fc04d8d4bda3d5c157bcac3f1f6138b5cb8eb989a9f3c029f2cb8c010fbe3743cb906c5ff6bf93a881914c930b06f0322f1f98bd94c08050fe98befb6c4776b52f7a58a114181e511108fbc262c1af6d6a922d82e4f9505e59fb9b74428c3e06570930482f82b2e2fbf1ea57e149d828f251ed2c470110f89a0593b75e411f597b5d8cf22a24f207dc4147e2cfbbc520e75bfaa6f1b0d0d31477637e850ebdb2bb7e44aa3f09cb379c23e2f77a4d2a803b9ea99e0a8620868eda97cfdd52858f3859c7bab7069776194d714bf7de7416d50749754de3f087703207495a373c29f096a00ae5bd03daf4510392578bd580d77b355d0a9b40cc9a2a25c03770192bb645d4cc61499b58f46b8c0ed3eef8e855a2fc7deefaf0983430ad06d6c7800f435e4c8b928646c43be78f8632a093cdd5943a43f8d060860a86024d44d79173706c6b26b951cda065c75b1de3c9a6af87466cb685ea00d8d07171562747e9370ad98542f99500c9fb01712cb24c5574f9a45ad1555400aaf4baa2a140231fdcab55106e91db93933164d60d76e67f5b100a4404dda420e56f5bbd0d49c92ca07515e74edd629030f8d2bd2ee0a2deba9146dc5a7dac409 +generate_ring_signature f429996a2c98e465ed627943859394523fd3edaf7ab2a919b0d190789e34546a cb0dcebde38589ac7c0859ec7885c7e6952debb5cd69e6b0922e73eb31ba5068 14 7d8cf927a4b89584ee99103b0203a51636d454aeac07e163065565f37a22449f e5390b19dc3e87c8f2e8adf3fae09348f3abd92f936d3a4c1ea8700b29e31dd0 af63ef0b26af519197bc1c456474274d00301c68111a6552a781de6b5989d86e ad8a74a8276ce918dcfe1f633b4212d61782b38396082709eec6547be24cbba4 dddfd48e4e8599d65a87c7ffd853402dd1dd945df61402d6f5d1ee5997bc6f04 f5ed6a7ca50fa4352ef8b230f8f043d2109bdc4d914492233a24bd51571c7bb3 e9c6b1dbb79c841d2f39407336f0536b30466d76dd96c30634acfb4132718d99 06d9d6ab1381c4b6e3f914ca3273965aacb4479a575468aa84dcc088f675009c 4bca1da62da88b5c0194f893878425959abba8f1b59f70f8fc35e90fcf04607c 537de67dcb5b0515251c02ceefe5edebf29f96c3dfdc4cbdd80f677aa7a86feb 81979c19b915ed61382c40953dc698d9d2ab5487d8cf9de2958dae69d165f8ec 939b33105fbc1114c67916681405b0dffd88c6b9d265023f1889a0ded6b6f715 1da95472cf9ea935e2225531660b0340f21d8db50b8d7f9ef889ea69386884b5 bc01a282651fb0e13e062be2ae48dab4533bac2bfa7a069d281db33ece3bbef8 9f70dd260c97b39abfe0fd3a4773ea3e31f4d4a440c3f998f68482a6a580910e 6 d089823c8685ce1bdd7672ddaad2330541e7c69c224b4bc560f50c2e6fc0c70a8ebe3d2117c03e88a9edb8b4e322c1684c0890797e8b0cc8feab549f1b9b3e0bb83c49bc82addb1a69f533e69c40e3ad71cbefb61fcc4e49ec1c0cac07a943052c640b76fdb3d2bd7e921e932bf28432beb3763614530a9d641122150a19270e6ccf518acb0175eef69879627637d8a762ccb87404d391d4dd217eaab0189f079ff8a990ce72431af49d4d5badd7462b78a606fca18f52a23a56d5ecc7c7c80999bbd1564c9b43b04efc80a665141ae0824d3e3e071153bb7af1e7bfc2b8b30996b9aede9c29d8f2f1c7694c9c465f62a441051f581fd0e8b9dd2efba7543e0920958cfa74b569da0fd27e9837637589d66e272f4ec4b8c251998dc10f8c90094e817a1a4f64047bd4e89abdc3856a30bca6465a0107ebebe62156803c6751040f4da71043cefb5d0e2f8c72f8f9dcfa7fd25f7338a8806edd293fbcf25b630d1a3297eb00c3bfde2a32a45f3c8ec85c83799d8651d5673a5990564e6b46590cc8d12210d441d6b9a606d6011e5b62d455f239ae4b1b7172f5886633a724f10eae87f990010d90d15abb312bfe8a7eea7307c127405fdec8cbbb46147a16fd0131aaef5a786c2890ad36af71099c8531f57cbbc75e15c505b262d05216b77903fcacd0689630d18a4422bde8c9d929a0efbfa2478c6e7ea6d825c12fcd815c09f6527c09a43545b6eca924d94369d33df092f97760ba1ecfbe962a5f224c1a03be6324db6faea93ac57b2c7de581f74f8b729ff4a6e1d8de33ef0f24471e6408b3ce4b12361cfbaebb894a6687be08a04544b9037690c6648c9d29d58030e102d40df79ae96091c3370832a4ba2ee7166c65c5f74731cb4fa53f795c6c6ba10eeb06eef8d06cc359802f960c4475585f95a05a1ae87a181d896c034d996a45073b8113fc80dabce86ea4c26b3d943a64fff78f54c96eb417b487097ce8885b0132640f58830f6b2c4ad3ce132b4ab0b6c8737546eb45a08585bebd3ef20c0d01da3a2798cdf9d1a734394f3900953f43a1c62eaa2d26949e2f9651774f61a8094ffa30a399ef4204687a3464f8e64ea56aea2f06e17e2ce9d24403c8f1c23b0a6cf0fcd37c5836d9d37a50eeee6058790f745d7333e0196a6f12788deed3f5078fb201ff59faf7a567f09a9f03548b5725982268c6398ed0c67580fe7df5ce034f7de93e3bbd7001dc6298ff56b885b21a1ac6cfd4fd3f750775bdad9f913d08 +generate_ring_signature 8d14132e5e17124e6b09f1e79ae09c053856be240e8c7382f8d6c420f7904300 96eff4358f28c028507c8e7f0972dedb4330b822653b2b313f4730d46839464d 6 c616538cd58a741d5b8a384cdbb2d17de994f61c90f280f7977f1a485c2cd43f bcce7c9de27adf25424520a824e71ed3e00652f7a08dbab59ef38b690bc64d3a d2ac5e67b93192d3714c302e2c933c9a303d484ce2c69c242fba97913dddb0dc ea7b1655ef60438b22f1e7d37324d92b4b548aeb12d7b870f2cfceb28d0977c0 2cb5bfe3c0d79f7fb25ef00316e250bec871a4ad7f103b6a9d0c0ac7cea10375 0d5bbb4a6990c3e1c33f173354732dceb862bf580770829ee361569a8d77b44c 1196427b5966709ba0a1ca8b6cfbf60f91fd6a2c7c7e7a6609a63ee0f801300b 0 2ecf7fcaa5b59876adff7f152ccc676e1fb140091f945530762f22071769160ca199dbd70c877a88d6845b30ab0e3f4cd55d74a15c9c2dc608a697da567e230062e12f0e6867cdfff1a3f03e8f99dae3db4fbc5b90ed791d109bcb296876dc0f1344309c66fa2fc37c2d5aec0e831c44cc4acf3937fcafbf0266103f007dbf0c2de154e44e94d8cfc797b53e05dc2d3d61115dd154ab15610d74c3424fc78202008398463eaa06bf687780829df04b59120def1b22a915d0790e664f5d8531030243b54f4824c77418aedb58eacca8b850d5006a8943193349c3d74811c6570dc7a3b596d308d44fd2e3e64f804160fc2f797c5c15ff4fe1083a4861cdc50e0f07b331b4f32e15a5aabc617c74eea170c6214b2786876d670a5e989e4c006f027c8bf25459e7cd40d2f9834a2eec52c3dae4b933fe39703e8b69ab46c871a2029b96c2e758cda159248b93543dd85e3efa10a003f5bed993532f43dc0179cb041e5ef9cb37a0a5f10dcdc255523228cde8d3d3636d93f906e302db718c415e07 +generate_ring_signature 05b70ec90350d0aacf2b9be53ea0a7e0912c456b4e0fe7f3efa8c7fabb1de215 db3f8c06eef1a728af728ce5e028068dbca392543d43b30e3408e70a5301e4bc 19 fd5ead415e17536a9a92d5d8063001eeeaf376a4408d3e4d3f3351200f2fcb0e 05fcda741a631937b631b745ef0451150d9442798aa28288c6a2f7c02d12b08b 04bca31da70f07d8e34aa70087d78dc097c478267db53798b1a4003ca02d9e1b 8001d9b613fc98a7a3fbeaa7382d71a02f566f02e1281abfb83888e3c83c6825 36b1a72a97fe92fff3d983c734cdbd2187f34763c98e85e9bd42f90541aae212 11d585e09e6cf199be4e13c2bac0b996a4addaad8b1451e5b0afe18b53cd941a 766650cb51e01a611c1724099e9999c60634e1a3cb36295c58ed35d4d8ce6860 8151bbc0a9b80790b44e6ce4542749de5e5b91171f0240b2a029d27e51c56836 a84a16dfad85aae7dc4f86f3576d396cf2867961b129eefba1c40a9b87895f0e eeb46b381844257d051435756aeb6e235b92545095136c1db72d84edb64fef7f 78ca044b9a1ef85d91d558d71046768bb5ca5e4cf1a97a693a51e25c3590d514 953c11498b63f8cbcd143d0515aba347c20c61fe47168e7c862466ebe875908d f11936b0f1dc77561fda254ce5ea7998bb1c00f4e3e69e6c63b0795d99961d93 5de09f7a41ebe987ea155d42edd7283ce1548191db18aede9bf0ade990936baf 26d83642ee3546f8334921be1fe4c766739b3e92dd8a29894e1e348bb6fb428b 48a98894200a4b25f10741c42195b8700bcb390b790ba0e01000d3477b36549a 4bf26521935253ad92ba75a2cc88b931d82b3c79fef8e5971f228e34168ada07 6a5cd2c7a32cecd50514eb46046ad996bcb2d1eda668a7f82ea105756cac2b08 63b28fc379bba0a51da8d41d1d89ab5cd2d5e514fd7ce0830963bbadbbbb236a 15af32d28b4350f74faba181075479bb3c5527f1ed7172c00ac28b703127b307 8 0c305769b45a1959b81ca8854ae7db67e702a533e9d76053381696462b0a8303a4c9db1137fe5cc1b444e04d3a82a3f1d5b7fade44c00dde807f54b2c1298b0b0da9dc829b9c7798e10688bc8554c1bc148c67f53d10eb956d9e9f7ef1fea50e8714a884d446f8f1802d8defd2f111202dfe8b9fa577a834f611795c14cfc908d0e6c3831d3edabb06228742c3ad6d314926f2eb73a5efc9cb396b98a2b3bb0344cfe7779f78f142888510b4b5768fb7d76d34e782f9b8ed43a30460d9c2720922ee2b557e15c6ed4782306930181901075dc6c15ab0ea994af85c854145c00ae848bd4e98e46920b99512ddaf48d6476d59d199180f389c57a08eaad39bb009568daa0b4a6a7998f0ff6675f207309db1d30a565bf50c03b4063c3ae0319601faeb5b69d5b7cb0f5cb7cd7b7de440538651286be6825d087270759649b2e50260c794e1f45bf0837934fb0c565e51d659af70a8133c0e9cc734e856758bbd0b3cffd96234a40c5fa95595d5f421c947db1054066909e409a24c13ffecbfb50e70337af56c5282ee673c0dea3af3599667482563d53f174a32a2528ea4c90c0b04c6d9d06aa373e0efc6d4eade376aa52da5119410b62505da31be7e37954805ca39989ecaae27e8f36fcadd566acdfb8fb28e0bf8b728a8b16bb7c0fd5186079b6c7ea2d57dd12cf0e7d2377ca1bd3188a96f163b05e1a4c7f2a9a648f5f204bf6394b3e9e3e8a3da1c38b0c81678b210c2186817720e503572317600acf0018fd58c52ef94cccccb47de1808925ae0cbf6884d886a46508a7936d951015e0fe7fa9c30c0d623f858d4c009c9454929cd853c62ee265186513c3524457b1b035b3a6d1ca267be5a651b7024306c525c27d298985280d8137af5cc583d59e50980846774b9977597328e2e565d65a206be18ed5b4fabcd32f830986ea5b806079969bc84d4ae99a7a5821ac2f0fa11f045de8295765ba588cb38eecd98b35e046b51a9c9a7865574cbe1911d04ddccf73c410265f21efb25883bf2ff99860e0805f26a7c36026ed5fbdfa85faed307b08e05c85bd1db3811b4838ed24882ea001a647b6c993b623181b2cd84414433932091252ffac639edafe643e05ffd2a0f2fb4632a5dc478e705b1b0d6248067e9face7cee3eae57c0952ae5d895fc19048d989393e3fd9c83440127e5fac6bed1e629289fa4f290f1abc711dc9f74e203508cb5427d5f283618ef311364245897092a8369be7550d4064ed8bd283d630690f25e786f726a96bfee1a7d062c7086a5ff2d38e01a863c44c8a2b3d88bca019c3e5c6e8399f5f58eac9890ff36dc343cfd89d59aa0e0bed2faa718a988bb040e5bb8c301f30b9b26ce46974ce6c6fdb0679eed96abf6c46d60fddb4cd37807376c5ec9e6d541d11d3d91eb341ac86256fac22f59ec73ac87306b5d6b1f9c0c0b44f4a886f0c929d79186e9c38ef0350bf15987a98584521b17fc7d89f0770c7c787ab6492c292fbb25bc3c097c844ff40c5089c9ab1e014660b1055022500097e42dbca4eac4c90596fea1b1201a1053611d088f3a2e524d53705365911e016cc3303b6aee6ade52cc6f88f54a8d103945a2e17250cf49d252c34a7c00a9003842fbfe5a664d518aabf0c8147c870d8fc0b70b4ab432cf968398d52494be022fb016dace2e2520fb832491e793a19ba8c7da4b4bfed3c1f19f86e2dba44b01 +generate_ring_signature 8e7b0209eaf2cb145700a9519b958e08189855775468f752b72dd90602caebf8 e128395e02c5766dfe8e16fa00f544a0f7e6cb5e698dc00de3683278a33a9d11 1 702d51626defaab76f436ecbbefb7a1bcd953735c1b585149a4e6ae7c87ddfec 9caeec6bceb4ad72ca57dbf1562d53ea0a93feb6a69236f8166f061d93f2c901 0 564878b94e45a813bc05a1d5ab2980eb3e2aeb75e38207b24c73e800f9780004fc4f7b4f3db98674fe192cfd3435d3342de9d391ff9e724318b8255b40c17200 +generate_ring_signature 8bd72f709b787215cd41c9f7953b0287d08f4e6a73780b558ccd03c3934b5918 8d3904d2c864c2c47ded0b25d5e6b125a902b075738deceafb17fe51df3357bf 2 ad75d42030a6426aeab0303392ce21c936df265c5557d800604aa7c3c0e390e7 7d31f2eea57234b7d6d6f09d4ff58cc4bb7d4be04d9c40fa925706466bb82f0f 807012275c28d219e1b973c1ffc62aaf43bda1b49fe3ff094879f9676253b102 1 2f9c5bf84fbfdca94340a9731223e44e03c7936d7e71314a6ecb00599d3c4e0ee15c6a4efe7f11f08220da2d758b4d444db3892674632a28934c29952a1435053eab5c3173fb6b601209b2ce1891418a298f3f87832583ea728d14eba615020a6ad221568f045d8516beb64a77fff5fec2a246f34dfad80c5ce45eeb062d420d +generate_ring_signature 21a6e77355023a1ca3e620126ee0d7f247f9a814e40125e2586bc9c6773928cb e2814a98af57ee26de7edb7da847473008e128902c90ae796a9980863d8e1df6 11 c81a625349ab970763589667eb533b4fcc76f764e525ed10673e5bae74bf508d b2143c5206e143dd966e38b3d6e785a87b631bc5dab23df88c2e357ce6753e35 44f17cfc3e461746a121975377a05cf87c6bd41ec84a480fffbf045a4b17c0d1 737dd0a57c5bbb2c5038fc3d084871aa281d087040d47b5cc36c381fb25e0620 8bd71c4407f1a7e9048cecb474fdbb527f15964bcd2f9a06b540050b372bc542 f31ddccd182e3b9530ac13eec95786b47013c9566499c20fcb8b31d6b3dd91cb 074096dcf159f4a52337d58bca2b695a95f087125676381832a4547ae6161d4b 8536caa0bb2488682c0c5eff2a2cc7723dbe1741e3ee28194228235a363e7f6a 3ad9404f37be6a07cc9de38bdc1893c172c9674cb186070af90ca0cba027035c 9cbf183bc430c397a8eea5cf733dbf92f7ce3a0365319b979dd32cfcc3285cfb 817989a15ed0e35bbaf2d62d94a2a6bb3025c795f830753679c3773a8dcf6cdb f84b370bd4c5aee8c383a1cde66c5ccdb497c2266a6b15e53d4bb6cdc0535305 0 ff2c13b3347bf3abe96cf74febc4f52f0c52daada62056ed4cbc4fab2f5be10025cb69df3f7fcd3969d94f737ff3c89febb69ba6cbf3782e8be4630580d78d0dcc92d981b05200c9eb0057484a8550be48d8be660fdd90b827c38a551b6ecc089c2d4ab9a37ebd9fed1c9656880accdcae9db7b4a183c8618a5b7b3f07a6740eb0ac7ed2276bb1980e9957da5813af0fcf3bf453338192050720ded52a56a3034155bb47c3592b977a46062d4ba1e5468d30b7223c8953bf1a3af50ce29d4d08f0654388f8735b2ae0f12cc96a7f71e1acaa12e0f2fa29a99dfb48076e549d0384e55f60d9c18e407b2cb1acf2bc34f06c7fc49fa3f6e79911bf885764a34f01a568e48ea4b09382d815a20a50574c760b99efb97a0a43665b2d81944e878d0699717339a18cf15d5059abbdeac15b86f2534048c0de4f079ab6b0a6bfad0e02ac86b85b009b38b11e865c9cb031babdc4932fdd8392425bb7b90c372250410c4f9be3b8b986da1f4b05f85604b38514bf69360f9632cc373ec1128942338d0e92413236517d8e95a65f04b8aec29c06b0345ab0f90c1876bc0b4fbf52024f04f64ff19458af3e94b8eef46ce2559c1250f0b0b12e3561d86106c284fac78d006e91430a08c5112f5067ba27fb996410cf6b3766f2c7408831f3023e96150904f4770b73eac0f83bb16f4b6b77aeaefd0dd2ed2f1511a1bd1233780dcad5490f4e3989a1f646f1555fae4561333e6cd098429523d84ecf3bf20aa27ff41a980004de4646e64263261c47aa352427122ae5164d1dcb51e24677b30e8f6bc9d90c2efd4e65f9d6ed01a9a90bfc930c21f25e3eb552439aa008577f1be28039e008c7b227d1eeffcbaf9da77057ebc1bf2e991ded6c69f29a5725a9c9bdfac4d20d1d1831136846d7ed5b5a03dadcf02b22060f2c1a07cb51eb1012dd711edfdd0f02158ac98b5e16ae4655164293bdad41a73e49fa919cb18b3540dabfaeea6006 +generate_ring_signature 267687c04961afdc4dd6108ce46e82c9c5a60a6db9b613cb071a86dea4069053 1f8b194a5dcd594d315df03b43f6e6c6d8ae58b51fcc06678c93ef532a7c2ace 1 6bddec7e07d75ea37fd6fcb93b7094d1e73a56715a904647d5b0d572a6d2413a 83e12ef8c17ad0741746e1edde68f34fc3a241e9d612df464f282e449ecc600e 0 878ea47006bf91cc6ff9c68e77a23604179854711863d909668e2d3ef936a1052b54eb8df9c2ecdb6b56e3244fe7c979e3168c8ef94de1859028317a78d52b00 +generate_ring_signature 9310255e1d6492094731550312eec4fed0f54ea5d706cb2a611434e94de2f67b a6b30c2ab8c81f1e2b826258e3800503430825f7f111a5643034ddaefb4a9fe6 40 41d5a10bee397e496d882d7dd820e3854bb222240d4fde670ec2340931bd16d4 dad6b13bc8910f762c3badfbef8a686fb787b6511eb20e7f6fbe390036b2d3a6 100588d38cca1dc9c852d2f89a1f11a246fdb955ec2f73b8d5f8ff3e915beac1 b8b3ed919d7d75574bad2a81c5057b596f62796d96acea022784cb653bd4ad0e a0e37438540bd74fca28cddf345ef304b579ca4fb60457b02a9438dab0cf09f5 e5971444bb60d3b5cf42a088f0e318d2b3c22e356f97457dbfb7362d91f866e5 a159413d63e3466dc7cf257d0e5c094d0d5f87003c9bca4a00e0898fb137a364 38af861b033f1aef2c996952cd44a0120bc4d04d179e74b2ad9d21596a9b8730 bd0a348d3280f6b986c74e6d3703729374158bf1a069701f4aba16f73254c0aa c857108270e21b98d602fef841b56f0411c12305f38ff38d14372c8718f7d2eb aecae0afc964ab34c2f5564c220cda5182896dbca21635ac81026d3c29d0feb0 7bbdfc571e773e399b569f4ff2830e8d9b518d0b5d113c66c78b7f4286a97848 d4e44123919ce55ef7753229180e82335c43c064d515bbfdd16af5459e6fce9a e9454bb7137d5562ce7fd1a5d387441792a1d252af2e7f8249da3c143e7ca5f9 f8ba4561c33a80e40c7ca29743aaa5f9ff45831ea41af4e1835af4843311b5e7 562e1b85aca51bfe7fc455fdbc0060a3107836ccb8e72f197ebbd4cae6c38240 314d5ca7078b9cf66cc9a127a84346dc7a07934357ebff1f03ebb46a71c3b29e 15899bb4e5e5f5ac515e9202d3be847d7bc4a5d2f8b10606a5c25d8deea117fd b088006581f476a6f974389367a8d751e3e77db254b44c37007512fceaaabea2 ce728b492bc3de4934263add7ec0e8b8e8a9befcbf6d303804e8d543bd00935a b18e46b791bf0f12877386efa7dbbadf980d2f090fa2e59826a8eca0417cbb8b b1367e0a7711b395a74cbce696bb16102f8bfcb550ada075fdd28ae6f91ee820 f9d2d946be5236f38240e7750defb8a2e6f9c938dabc5773e8fdd8debc50d6fd 4423c9426972d73a83f73448e6bca19ed2edf3230ea018ea9cad3b1f1d76c4bf 97522c269b46cf817c95aa9fd186b9c09f9ab2da7af3ab55bd562d3cf3b51ed4 9f9380bdfa737fa00f31bfaa185c89ddb4a431e18f4a17c12afc3233e236483f e9544769948638dd359c9fee61317f0c93e4d476c457238c7f8741d4fdd20ffe 033aede3e0d40659cef397ad6250db441c97dea5c26ae4771a9f4dbb1941cc87 a436a016cfcddaf1b1f1fd9dbbfacd6979269f0772526309cbbbf7f40fe45920 d40b3ec269a31e412505088853b395405ab22a54d2fc0b7cf8f36d3746ba3e22 5127aeb4f206ecb11b191437e41ae3ce2e8734066ac559921a470bd656d56c24 89b0e22e57e9182a1a7d02ed51a5e6811f3ac915de5164664b296033124ec6ee 5937d8236f189d12fd6cd9a2ba68df4d5ba2bf77e72ed9449bce95cc0105c974 bccdc7108b06aae759d5b4d0e7e03ae74d5dbdacb6c5ae6935289e231a1bcb7b 15b5ddbcf9014f7f31170a82731321e9cbaa1d3b1d374ac8e9baba8e301fa1fc ece21182404939af7ec56ffbc46d8a72ae114945aa53baf864c7dfb925506b47 fec8930653c39e756c9ead78a921a02bbf3cd46e48053766a3ea05efce314417 bc04ea71c8a2d6774c477819f1e2be43fb4e8990b064e6c752756cd8fecd2ded 373a4b62cacd09fd6ed9e3b8354445b8316d15c11dcf334b28c2bb7e3458e848 c81605bf680bc260a7090ccb84ffc13e1f1e78fd94c2320642a3786f3fb2bcbc 299563329c5dc60a5689618c81e1e4edbfbfe96dd877c27c30e96258ed287405 10 a8370bfce21c305439b37c109e59eca60f93ab9638d47ac0c2d1f72fe19141053d3efbed657c2f625b44d21d3390d2faf56052b71e2431583191725e902eae0a12756cc894a7341dd1ed147d7e57b9ad6daf653d921558bdb14afd0ef601330edbada0a36445fc6840ee49f39bb3ede767d76552e84ca2df0960a735f97e3c07459e774701d39363dfb3b2d108064e9c3b2be6f8d1c5cd1b13673dc4aa11c907aa116b94792f691ae1d91c860873edaba43e5180340141c0fa05012ad5e21e08eec566ff54ad190212f115478e7584c4ee7bb51c0165287f484ffd846f335307bb675c3e0bdcb3b0feae1a2b66ce58aea59fedbc7637a0e1cb8ae06314c55d0cc400dcd66c9ce4ce86685cc8acde97f62a69f516225283c4aff3db88a91cf305197f9b94edcfe8a28a4e78b14e4399564c04cffcd13d253eb700317fe6e0c8063261649161e04ae8179cb4413e0078462c2cf275683e24fd045e28a0fa505f092eac2d0c056a2366ff5c8112351b25e24d34deaf2b6a949f0d7acba177b5bc083634802751410c043f6243854921c7497d229ee0969c589c2fee4f7b3bf61203688d748e066e7caf88d71369c6a683e34a8da494e17ce743d8b159a10d7ea80ab05f4d852046c5cb70efb4aa0426d602e5dce0432656eda9863becca0f523c02fa44d25787c83770581fe7e4368a3e3a4b30160847b701631a10593634888c038b142816d58f2a7e43adab6759e7551c085a6bb3111abda63cdb21f4bbabde03c79fbeaf3ef2ca3626b21d96f7ced93fff24ea7bb0d6da1c5133e480baa44c0afc2b61f593ecddd2a22ecd7405f87798a70aa3e7f2ef617c1170f850f7d0180c95314569b0316695fa565e5f47ee7bc4d26cb691f0d78f480fdaebab3f5f6705ea128f78e6af33ac28ecc3f78a91fef6bfb926ba473eb203e1b2ca89326d160347afff7f8907fd3892380d7c9025632f83f8a5eaa128fe345bb2b850b94d530e4bb1ff9801bf4066c3233428a9f7f968cef7ef5ed9c3bee97758651005b4250385ec154a1aa38deba0def3d5088cd98b49ed9d7b689fadad356fa00eadf59a0218c9d90b4adf0ef371b4b0e46ed9ece4d7a6e2c7de2070476f871aef20bb1a08b983bf4cf20e174971ac7bd35312ee8104d7ecdd2f95d429dfc51520d90fb0059218483beb000c8506c10c7f89b0f818dd47181a52b2d09dfc3c001c9159780d0f257285050863192edc696178fbfd8aab58b01e0a93e28d472a7a64a33b8000ee37d2d8cf1697180a1829335b603d06adcf68f746074853c9644c55dd9d0c039108ff7a9bc98a6e8d4035a05f0f9011157d9172ed1353b418d34eb29bbd860abbb7cb38ef8c2d28d103ea47ec924b3a90321ccd44f948bc6d547aa4a4d68a0540a2b07205e3ee3d5a4007ec92d1e4696ee1ec735b8a567c68b8775dcfd1880adeb5694be4844d0776aad0ea3f05eda75ce3bc4a9673c18caf57cd761f95b40255de7869b3e4d33a87290ff6b647d57b9dff39ea65e8339f773d7e57295bb90f96f4f4701156eaecf778ad2a9d2813699f6f16488c073efb5b637e4e725c2d00f9f5c2040868a7705fe6b395356cdadb21ee9ebb8504f6a4730050a4672dca0cd4e3aa473ffed04bd6e13b36f6602e7f5da33b7683eb5b20de30ecd754eecf061bc1752eb0179724c1dcc45e84bd62c92d430ef2eef0f3afdf6832a4c8946304f8252eae0dc9bed1b7f971b13975459da031b81a7f68834da247660b7390ff0afe5a4b2f319201771e5d97b9c4eb01505511ef60860019ddc7168bcd3054b6014c3eb6364ecdcfbf4fe2a2e928105a4d9e0596f029f708356ebc8f7170cf2203f7994c32101ac0f20a49796c3522ee0d6c87946b0aa54eebcf66a87b411f4c0e92fbcc534837ea3755beb2338cf05651e06827206c8531524621c96eeba0fb06eb99f61d215d8e873043cc0a39dfcf4a917c94fa00515c4a60d79f8504e5140b29081e52b82cd2d9da48321c45aea6667dcaf982583dc1f46cfa052fff911003f2be27cf931a1890f9484d8044bc65e4ec9386c24ee17e95c00512aa9b1e40048302e62066d4f64364f8c03f783a3c21f37fe8e6838d3ed31c90df360fee930710453502ff90f05fbfbb3d09815b086c082b385ac0affda9a2b10b670fde6f0bda34038f56622c38ef7cb0ddf88c1a62960cb344df5ddbc4e9e7c8a4a7669d07eee0492dbb5b9b3fd1fa48047e24974c6991bd2a98791a340a0effcd42cb8a0dca0cf4a41f2a8b7fd62b8015ca06f2eb68d2c9671b0a59cc9c6a78814397c0022fb2f61948dc917375ef30ebf8f8c8d65dcc9b744c68e20c0504d294ee1093060fa8adde244a30a558a8f48fcbb0d928ff8cf446315ccb460159fd1b53dad90a59bab26b208f99019054952c65d4c70e80d58129034b01697e7dbb72345a310840143dc46d5f19b4bb14692e852edfe2b0aec265ea67dc08a7eda3c01d05fd0d3b05f28eb2dad0194ead51efc141a77be97135f38406e932ab1e3257b731000adaca02e1faf3bb7e5501fc7b327df9af47925e33de27a5179b60e4338ac8d505ee41ac311b80df97716990e121b9f8e1433f341cc70d086bdd781a527b1e870bf27d43c38485aae5757903b479de59124cd255323f0a549f64a78a5f23969809deb5daa333afec4042da25df55f5d132dc2a7f941738c7fd196dfcfa76db1a0bb9216ab4d6f366f9c68e17153e36076f9ca8c5084343b5925e19af128ccb210e4292fe29190c5ad23d35352704e0c1de097a60914e1958253dc885aac2e4b108906b103f38ea55ba036a60595e09213237211181bfa4b3e002fef08749b1740f516f1226477565830de455436ef4ba2b15af376ccb0a8d090d2204780b30da01f728ca300c5c07af81422a25ec86946630cd61a2ed574e9b42f11720e937b3037e6154a3d38f08c400d519756360142750accc313f0ca989c747a8488c17fc0cf2603c61a31311e83843ef53f9cad5034b35e19328db0b2c9338dc61afb340031fca9bd320a3d5cce21e300aa4510198d84ff85a4d211799b16d021a8f4e1f02f345ad7fc08566bfe20edf13f4b113107b20a78cca1bb99c70f06b8304f6bd088e2b380418007535e18173c1c7e85ddf5d5816f23c36480f4607cf4e0881a409b81d11f310ae7aefa24ffd06ba45f812043b76fde0887d256452bb8d6822740540918ecb1c669e373ebd518a40e8ccc6e2772657a03dff6ac7d6b9dbc42aa00b6c294cdb557cf06ca1962f365d5d94706cac4e9ae3a5dbd0c653f356a753330f4f75e995e211fe14583db569569ad5ed133d1f2df69e34b83e5b25be881da507a0c65f5fdfe4db0b964038cebc1fe9aaaec0e9df0225743a1e1354152cd5590e04f1014158d4048db661a701241793f54debd8693d671cb9d09b883762e4d20e5f0e9f72136447d2205bd1e465b29dfd37664a5b4b3bf3803f6076487352a30e69c9371c8bc8611f446145ea9163a9810bc63abbf8d6b3548fd2ebc3ba19650b3528eec70b1c92e39124272b41a3b023e87fe10826154668f6566950341c4c0ae5c00cf4a94441321a7c3acf5a6058ec455f299acf966942bfe74cbe75e5d207 +generate_ring_signature 657d817c2d4d9a393b1d9eda25141349f6daf11cc4d6fd7b8a1f279c12187e46 e8c62926823b84157dcb6145174f85084425a5c705ed0d37842430352451a394 1 6ca123601f7636c3372154cbba220818162efea295240761066b059d12148b96 eeb5e6852d87a410c402eae49f12242b35702470b648824c817adb253d119704 0 83c370f6cbef1de5f0dff9b17c3b7a4a7707e5e5269f5407f18d9bac4cfeab0c5192830362e58681439839d0b6fba76a01df1668997160e63e07a265d6dcca01 +generate_ring_signature d2ee8055b5e9fd86cd9e9cdeb95450590ea7a48e976337e8af699593d15d6232 cd23327ec509965ac07ac7f31509833e47fc56b96dda646223d917c02c292ba6 1 ae47e38a341217de4e0562f9b146299c0f7cdb971d314ace7522fd4fa3e20fb0 8c4730239e8f96e53ec2e30b856645506887527e7b6ea24fbff166a727a74007 0 20e08c6ef9a3ac8b90ede10ea7c833ecb39c0efef679d716c1a91ce5854bd1064600f4fbce02b45c9d3b69124f435739690b202ac327b2b034d51a430293ad09 +generate_ring_signature 5f6aaa96065ebdadb91cfc017ad7e81c1052623a75dc979d052c43d025572d46 e96c5739f208695639dd5120c89672abd6148f185164bbf7e17c643f2441ed18 1 71b0a7ac6902754f376699e4526f3c9882787ef2ec7477dc2cca2b5d6791af28 0dacdc8c2bab9aa153b91ff96e7dcdd6736e8829632e92506efa068500ab4b04 0 d247b01cd1efbb2f680f876852f349370c3fe8731e15fec25664f55b48e56b099f860dbc8a7f8cf406cfb94e9d2454a265e1fa9993ad2aa7abc32021c54f3909 +generate_ring_signature 210c782e19ba6264cb91745cb5cda5ce13b234ed030561310e88f6dc2722b483 b439238aacc9b192a9d7d1b73f845d24f574997d88c949d54d372549419baa7f 225 385d632938755662d282c477ad5bfb19bb1d153e5815077216a4c4e2b394e211 5e180c966833b87b3003a824abf2c6966441760258c201f7002e823306a9c2c3 5d040395bd315a7bde66937473a7d96ea72829d2f2f868258edb4cb265aec30d b5f068ea2e517abcd21e927c7ea996c5974cb5c681805ceeb348244594a342b3 327d212984e2e84026317ccd150142a955be2dfe34d19e194a4357bdd221a9bc 752baf4d17686fa71a2534a6864477b608ded4d869f847586fc6ff4e4d266255 05c39810cc10183513ab20ae2caab4448a0429f50673b239286c2843b43a9aa8 f60a2de08e5a77b7e56777d6ef84a5b6b546e6934cfc3a635378c9af0b7e2f1b 9986783276b0dd845c3b0c56ecda1b29b28bd7a3ea155ae6fab4376012a40180 0b3b7b391bb34851c1720cea7925614177f278deb37b16d52197fe8aa45118be 9d41a41006737c046947fc176183ee7baf4c37114479616e89d7517b9d039a56 d057fc6060c31d7629edc250791ea60c9f49bc5ca3872c6146030bc08ceec217 64bfe3083a136ae58ba33130ffd58a60b338245e368db66335d4844bbb0e25a4 4b7b5ae9dc755559da17de7325ad60d80b4f442bf508e304d2dfdfd9a3853a5e 2a5d589b910884a9267458678333e8a3818a71a45005a7aa3a9e088ebfcb88b3 eebb3f88b3f7951e243d7d8db9003edca9f0d9001244476efd46074fbd904fd7 a9ae02114f76adcf94ad23a9079337f1d1edfd74fff2438ddb47d0cabc1f5af3 db9edc21464cb1d6a8001bbb2933214b5ed3a2824935d63c05a55bc5b681953b 5afb033005752c35a5e1fcc95d2341640f532d11107b3a54c212b610845db203 8ec392866d432fa11d21b4293ad1ebd421fa859ef7c5311eec1acf73da95f366 2d372298a9b62e508013d83cbf0d95ffd72fc8fc6fb0d623db98a47e30640eb9 7d13621c703d7bbe44a196819e192422a9211e53a8a6ee138d99f541c7c45bbb 00a26e1fbae064a1c2c800ee32ff1bec58ea68e6bc3d9319d0e6f7d9d4858943 b3e674609b98360bbb85e1f9b80b779453ae635c894adda35bd100e7c6b1879c b9fd8cbae04c271e2e59702508d371c15f180310b6b5b16bf78f92c30cdf3451 c7d7b20e3bac8ac1a104ce0015b29d6ca9f66e4b921f3b7760d14b0d0ef806bd 50771023cdca6100850cdd2f60cabab98e9e42e6de099a1f399b898efc79321a 736e41ab6937e217c5ecaaf37eb7bb7136e8f9e29089c8be9567e8ec9bc76002 52cddd12cdf1c506e78e29591392fc24e7be5b9c5b6136ac2ecff15a94fe0768 132e70b68a7ef9c5f401b812458745e73c3b1143fbd6d548266d446e8ed21800 a5c2587a5b911408527f894750bc2fd3ad05d88fea96eb3fc521ce217cea614b c36d3589279a9754ed703a49e284243064bb8201823bb1e6c65ce1f1cefeb3a1 f352384e3ee128d4d9f5e53677e193699a4a0b32b87b494abbe9affe461c8224 623cb978cbe7068f3f5573abdbf77acb50f1fa21456d6c426ee7d14d925cee2c fe4eaf7646a7d7edc86ffc7bb3e02ba1bddac47517eb676a73c8cba574ac7583 74564c30fe7b0bed8908ed7550c7a1c0e81dcf9972c5588223a5c31f7c5f24f4 3957b9c95219d16df5af553548404c6ed013feaaaf3311ccc19767979f81afac 52e16912389caae211a4ca91048df9d62541505cae921b1adecd1c92a5e3106f 9aeb3d3ba84f8209795c9fe000a920d7b58e361c2ad09856e4b385cf1d3fabcf 52e159e9ed060899121461c71906a83f47c1337db4d487590c1d7b742e23e29d f4042896920a3546282ce109658cf0f1535d98aec685a54bb653bbb52f71f560 81581d762fda656949b3c072d157a16cbc96e27f73410fed70cc2d816ab76632 01d2d48e6e5599d24534f3482427eb4501508b8c1068583f7354074462aacbfb 323f4706c986053428d87e580cb45426eb38eee25fb956345607f71f76e2af64 c48ae1b3e86ab129abbf82123f987b773cda8a621313d5e3e12a82504aa4b4a2 764a1d46d895c15e2de0d8953d4a349c11ce203bd8fd5853c7acb497040e818e e59cb3843b69071cc6a876a73433694f55ad77999c1f2d9840cad6f4d46cddf0 f0c7fa7f51616a2b8b3d3c66fcd1b999ce236223d899a24d21d7cf51c7f8320b cf103bbd9665692f9ebb884207be5d48260d16cc118184ddeebaf8db303372d5 718247883127bebcf88b3c0aa856d2c82f205f0ad882cb40fc308f011d4c6ed9 12d01937773a71a29ddc4fcbe01005e7f3736b25414dbeb69f1f15504d65cd2b 8570f352e0cce7b04f9a415cbf78ea49b22c6dd1e199d2bf2a36eb7863b52633 72f0a2aaa9927f98bb985d97aec6cc91caa36f06ae37fd49e717f3c465943bf6 955bf1291296b84cc7f1a01a9d38145a747cac1f901739405cc358c1a791543c fdc3c3ca79c46bbd3226776dc9ed47e1ff3f3a7748860b9894812132f0290cce 5277b50bcf94ad33066eaa0d94885009bb6a2ccecc8748ab5d2b053d1c4bc8de c82775ef48623297b0ff928b04c03b1502645d58ed9c111478bb9c158a6245d7 88cd50b04d60e049714273798db1af00d5106280849efed1a9c1e37ffd97e253 d77f732b38cb637343ec20a66da97c5b39c9c3e8ff4b84a444e3d32164612791 cab9c3f461b91e213008d896bba641ad24993f98d1c7c872626c00a8b7c001ca 4c62c3d7c18c0b5f240c56b6f20e1ca4eca30b7d8806f66aa43f5df8a8d382ac a70644c6f3c2cabee8ad982a2994c09e81962abdc94f0fe48a5de7b155941de9 3ca3119e94ef5a78db0e52495b37ee42d3d87917cdee4cbf8ff53989939b626e 0df77c493d22bd419c3db7ee8f464acaeb6d83d607a7bd5a6083a62c1b318f94 011fdb5a7173b0924e03210b8ce3d0bf52a5982574faf3b110739d0288e5da3b 3361b6da469b5eacd5a5699ec7474c764d1426ae5caab18133252b5d186c1f41 eb68f27174f1dd2d342ea6be42eb3635fdd597031142086cef689f143e149faf 1fd91c95a7eb4552eec9f60fa61d3f904ae3c8799fa1a80926dea02cb8b69fcc 2fdce58215cfcd09250e3830dd355ef53090b5f8ea6c65ea7db805d720ead1a2 b1678ccc6288b290116e3d8341eb32e9bdc0e7c4bf1872afee58eb9430f82c45 48eb663ff455d22f43f0b6cb27f7d5eb0943d4b60b683717198002d7b76bf4c3 2423895ba50880058a75cbbdf5a535ce176ec31a14ab32d9de4dc3855156b8b9 06043986a58cfa6a7fa0668668b39f297b00dc2aa7470bc9608021165442b15a b881c686c1b423b1c36eca6246e5bd5d0dbf2f1bcba8462a008ca7dad7b8ce9d 1222668bc17ed0be0cd5f58172d8c058cf3869d26b201b850e46e2d1ba6528d1 1bfa0e56cb48d57372b35238c12746ee52345d52526ebabc79bdc28ac559f1ac 0dbd0538a75a12d385837b24a7948bfb3e7b9ec2e10b05516396041628e18a30 99910ae1888e67a0de161a454574c19c1f008f1c8559204e575db88dc80f1a94 1f000d2ec665610f784536730adf1b3e5b9b9db13a42165d9544acb881b0b92c d4970792197ccc02b043555225c505be8495eaf84b6a70d55139dda4c63b20fb e4601ad66a30cd9bf6e8a7291282a91731c303b459843c73d6b3538bfc3656ef 256a7723b4f9b7d7f652579beb53a1de9e7bee8e75833cf73b259452783f3251 613669fc70b3044796ae69b20a3fb3ad32f2e0e64d789a00dd880ec974e6afe3 0a9baa39c17da06593fefecc921b5a56b08e41dfae48234f0fc23d8f6a376ac3 8fed0f0e6b4d42105fff2fa2f5d17c1a29959a58edb4fa15f137f0676c6ea7be 630f0d0f9a93c58f56d9cd2f6ffd88e32588b5a2ceb0e1888429d3a38db25ce0 7e12a83617a864086ecf6b8c440f108ecbffc96bcbc8df5f3eb3c72cbd5b4e12 d267956f1075d0755c7f76b498b63e7f51c6e1c4902067d3be637346db102f1d d2e828db06faf7dd49e7e5223c21231a3b4cc4c3342cd71a3a92f06d727214de ce057552eb966328262a82f0106561632761a1872a5348c00e2fea537a946a4a e44b42268cb4127b29e47f5cc6499e67b618afd48462eaccc13477423abebca8 f9f0712fed976ab4091ac0dc3c15b3c2dee4bd54eda3e08c6dd2f9a4e4acdaa1 0e65a84589f21ec3b9ab6aee1d24ac1be5cbf7734450bef6f523b1052601341a 12fee1a3b1c49e1bea073a7bfb93c8879582febb9c28354ed5ce0268077fd176 4bc6cd65e4451fae3817ae3210d8a59303520d0eb1fe4c5d5e43d8466dd784d5 b96717f2b1ff0ae2dde66343dc8e00268366d0e8688337f6ab7d18508968ac8e e095f6be7cfbd4143c065b3f74abd9efac0552e91bd66c50fafb075534539ecc 750c8f66ef049a2f66dc488f51a125873b97569c692b9c31040bd4da3759d5ad 7612ac603bee6381390e5a20fff937b2532f880a0e51671f2641b67d58135f60 ebf737d8044309797fb792a059b02311943c12876d3a5c1384166ee2b717820f 80849e5e6d4f4415d77a52dcd6fa289881920aee19735d03fcf5979c2b001993 c97589e7bce4464b1f1921265e8ec6af29040970f09f2c3475487e7ecf1d489d 9c407322aac4ed8983ca8b8dad19b211f0c0770195119157fe44f1bfda932ed9 31fbe13706f2716dc25b149e77da52c1ecc55b70053e41e8bd92221b1b385783 b6ff14454cad1917030df735d2c9220b40880d7fb0ed08841e9e705eedf9036a 06afd0020bd36ca861f8202223febfb21eb5c7e338c907a4ce654e457cb2a315 be6f0907e14047eb8fbfdd1f878550770c6fc2630832b81948927b6f80617372 163f776a0f464f59a6fa6bbbd7e93aca17ab04b04b7ce06d34226bb7e900d7e7 f1550dd1d473f38ec080a6dc9872442350179aa80ebca3afe3286c61b1ab732a 38610d484a664c9cced181b42bb7a96a076921437de67f6be1c922e07ca7ca25 5990aa4aa00146e517e50f3eb04336597f2f8deab18ca1439ee5a90863d4a72a 50d7699edcd2730a75ba37516553f0548e2abb5044ea89cac8851026aa73221f aac4a77bad6ea4d5dab8b739c0a01c9fe78dac1fec94fdfb1168bd5cd59798a9 95022a31b8a904b2ad50d8f60e7779fbed16e47c07b1ea65c19a13ad8ada2291 439ad6b57a6dc6b7dbe15edaf44d7582f0d6b316ff823d41cf85ab381d35b860 38bfbeae4653dd4124de9a1a3e53bfa3066d4e5961412d6c1de12cf77d27fbbe 55992a2b6cb34982966bd89eae451b39c701e79de02d7f3440a8c493a51d9d9c 4b44ea04e75b073a4d597f4d1fdd414179bb7bc5b8ee9001a3c3313eb7a81028 3bd990d568b7f23824d36b441004334bc7d88d6552e1b1b9a6f772ccd02af8cc c6c13ff416fe823ac2ebdd4d8c96c9dcdeb678ce832218eaecaac26d227aeb93 384e2915e3003d1e5a32fe42c165eb31ce1cf2f7972ab7080ff9dc95146cb44c fa79bb9d556b1063924ff37f150aecc8590ebf234550f4c90135fd301010d020 a06676590cf910a41cbe07a80e3711ecea47d43343eeefb106027aeb81f11fc1 359028b96cf085cdd4156f29c48aacfcab8974c51e31d1920648d844c48503b9 f4fe5c34eef748c3c9a3dde8eb3a7cf88f894f7f29275ea11ad9d21c2da7487a 7af8f1af63e71d95ea3c26f57a9a3818945cde9f1f70c77678e501a6ed2c5b53 df5347afdd221d101381ca39489ae4a40c79e60dfe914640b7c9a15695bde31d 9d68f3e4e218ed9d94181094ec24d78d8e5e74462edf23a04e0f5c309a488ea4 f69e67c58bf7d1f54daff66bcb9f967f4a800bedde5c1e8e3388594d2b6162e1 4e522383f361282994b5df8bec583c9076915963c387cd8fb79c5a143b77b20f 649473a9ea78b524cd53b328a181eb40c0cc67f93545baed9fb9d013a218829e d3dc41dd315b7390789ae65cef880d5b87f4b6f1806877f4828313e8842fcd02 2f14539f942ee6e9b0f10fcedffc6c2928737cdefb8ec12d1100296ceb74d56b 9dcb4fea73d041a83daf21a9cf9cecc054749ce61b55161cea8533d0ffcfd66a 8683d13dab4da5823053c4623a860b0f30990ee197a528780a276f81c70b639b 700509bd43a4d2b1cbe027b952587f67bf07617ef194f1d182718bb1761ea6d2 41a1e9fda04748ddd5fec36d1178167776ad5fad58ca7ae08c83ca4fba14897f add8a8ea5b584b8eab15afe856925109b90a73f21700ebe6be92064968ba8766 e6db06fece8a3c69c8345ebcd3a5448348e3ba7b3fd15a05f2eea0ee45783d5d d4c104b6d17052fc549dcc764684c848cd7aa470cd478752b814010cfe8c31d4 e36fc9e9c235d35b997678b41b2702b931498e32d22911d3c47aea55503b0033 c46fd9dc260f6d25ceed78280b2d5bbc08657efa5f7b962e30e22ed3893f768f eeb7a4cde0a142ea63cb9580b0938366b3b95324d18b17da2be4d2249106d3ff e4987600c30314a65d4ba41c132d4aaa6df9bfdf43c9f6edb4aee71afb3b1ca9 26c450378bd5de84dace9354dc11164c0df30a66c2623ffc9821e9ba96573474 3768619c48bbe89a1929c7d18f71dc321ae9147c29e1e9823e15389af035f1fb 65c1b6c65fab69cf2026b344b5b0cf7e312d8554c8ca9fae97b87edcdea5f945 79be69b0f629b18930c38f588b76f86a2c91dd5f8ff77265c58004639539767c f5c4443cae1a272c3ea900331bc349b72f7537e4ebc4ec9995a5388ef922731c b71e544eaa0ba427d75dfa2bbbe03694da48ef2be247833d143f81812c7b5a47 b7b2457939c77d5ea8ffd71ea933e4efe986ca8b455e53e0ae148b4ebc4d48e0 10fca1960f5ef371ad93ba33f223b7d2851ec0c9c76f70b2d629d6581368f90d 988f89d0727350eb720066e198c14229bd9c6b30a4313419df9ed31503ddb02c 2f81e060a1c1d035ff2cd062ff432329b6b16dd5e5ccd3ba1e3c64907ca41351 335def56d9aadb5e550a9a87df2c4171ddedc3257cebd96a88ba2ed0b13f7301 1bfe59272dc577a9821aa956551cb1f045c67d4b9228a04e0b4449a8b462ff0f 444cb383eb3f041882c5ece5a3ba472f6cc4586f101c63050d8ca8e4ccd0106f 39c3b97d1ffcca4f7d0560f49f5d913f67a3903789743d29b49b902b897774c2 fae6d7e20a850723d9764e97e3856dd3863329e66705d8d0ee2b9889aa70c327 1a095ec877ccfd6ad7c098273feb65d098e1f573626e57de6ae4dc61784c9042 d562adedb07334daa8ef9cbbefaf98d64b24c9741dd72445a9e120e183a63c6d e80223440a373cda0d6adad064bc2148b320113d7406e1eada98f1de93472b0e d15f5a5ad17f8a3ba30847d4e85424da0114eb96dd2eff269cccb4b3cc364591 48707fd6560c4cf9cc8222491d45810fe75673ebe2a7de749e9dac85242c1104 8963b85abad1a6a24eed9b63dd46902766eb8b0dc13d02b9e80e3ed5dbfe6511 49d0fe1c91a4037348cd6f6b8c2bddb8da46214c33e8c39c0630483b83305ab6 f803ac0ae722d368b352c47dfae3852904bdfe9bc7d4642e1126a482d5e9eb72 1084f0fbc396d6ac455df3ca4fdc22a24b8d1e00b3f904ffcb6d2fab8729590e 4314465a59abb470b1e05dd90925da4035ba6aa20ea102c56b6365865cd05a9e bdb6292729ed47f044cdc357e7081b249a275ba904149ce9719b57dcc144269b 033d157a3b91aead40b8a4f029b61f2a40d39b86ff38e8e57b52c03c426dd10f 138d03ed71356e08e6ea8d29c57dd8b2802054587a058c80773a75bf74bfe371 397cfd01c6fe89a34b41873338fbb70b4dfbe8a954d895e88cc87ab2cbcd7686 292e2bc17fee6d9bc8f09c710411605ba57f8534063ee3608ef39bdf73ec4db7 8150e00b1e5b68586aff8612515be21fc803344d3d0329badb0cdc99b80a1362 c92a75c221dde7e996ae5f8ea43a5760563a0532dcc6360a60dcb0c7abc13f75 49bebc69b650aeb8ad9b8382ecdd65a74d640153ee047060db71536e5166e58d c03564454188c4a7c29c94b4d128246140bad2a621e400137c7c8566c3ed98a3 75ccedb4415bd43430e80668831b2f667bcb086778ca43805d9b67ebceb0138e 47a95d5a7fa6e64dfd42fc92f103795e8bb26d8548cda156075d528f4ea79c37 ddb756c6e856bf99b3cda839a95509f50a9b18b87c8d9e07395eb1f37f351004 d813a9adfed2a92f4d2a386acba181fd12d26e8cd139e67e39bb1a45775b3f8f 36c6a368a17becb5b42b43855f1a1ec9b958077077a9ae8b2b6186854f2d7b96 5698732e696ef2306c582231ff9d48f919f4f5d59bf11df3e2bc7a9511a8555f e0f7dd725ddf4ca25c9bc32f1d6b33a562325573cb3bd9f9bdd03eb15a568bc7 6ecd766abcb6ddf79fbc0b7b510d7be17bf5497fe57e54fbab5f44b59522eff9 29ccff9bd63867d4bdd3d99c79bc54b9503d3312ce4792f280da7435e22c773f cee276d9b36560b5078d93780431258456ad73e47b98741c4d885b7e917a620d c465fbc35b063492301a77e868a24728a238335f1eaee5e7c94173fd1d5c2bbd b8a805da943c09244669e79bb62d6a58e80e0cdf069445905b332e0ff2e0a4b9 081c277c8956e574ce8315e55a4d1bc6a1f7084e3ef79c565c5c920e09ccf7d7 62a0c62da5b16a818926f5568bdb97370612c34391831bb8fe60ddef00333e80 e98bb0d8e342ff5ec1041a49101a848ca973b3143373404be9a6c2045244abc6 4667b53e81243320173ad6bc9564fc5249fc89410c70b915602a8c164529342c 26c435b82bd68d0b7ce15e81bc391b2b60b554be5867e72a9566a101e27ea9e1 9587ffe6e571e2e36fe80649da50c303ce81f852ccaf2b2e9b7b4664260c00c9 3b28089761856fa94678ff62ef7f5ff7bbdeba5ab033f2bd71ba5850bccdea9a 5d92b8261d4196ba81ffef7859087b51a05ae5121554181cc687a4a9490699d6 297f21664140a48c0cb3fd6e6581ff9acafceb152c76fc4bc9d31d946e2aa54d 87d4a74090844bd351a393e7c9fcd7fdde317947281a8680ef950e5b71cbf8f7 1435d4678846561678bf9d5600b2a787b6339d4ea3b8187a47ab5c6541817741 a8ddb8e7b2ad56a9d46dfda69e17472e610b68af71a3f7ea908c9bd69d68ac62 d8fb6e4733f9fb707f77994667f77e4e3ca818bf8a6af8120e50ddb02ee65f83 8c34552da56de382f71218a665199132e665a1aacf11cdfbc77e5ffaee59c61e 098d1aceb9cc5ef48ba98dd731a3440ee771b9ba272a2c3f07cccdd192f76661 eec48d281e1ced0a49fe3259dd5b4834e22da58794495cb12b14c50f42f352ad 01bf24b8be84788a89206619db1cce831a71cdc4fe0b51c61d0d93144557c19f 53559b4a639f13b09851a396796fc6ca68211f3ecc2a00a687dc3a526bc1efcc efd8b29f481a043c230077c3eb0afa01d99835eb6c5432bfb855b4edfe57b43d 69cc325592eee89f8c1219ae28e35e515f167491b1a1a99987fc1091e3d7ec8f ee3e949a0957a440e8dcf6401c7483a97e78c90248ebb05bf3fa2259fa3b767d bda559c3325659ebeb39078896a9076f66ebdb69b95d21477d422bf892c81c0c 435a8f4867263036f7af465acc3c052161c75a6e983e8ada56e5a88fe04b4a6d 2fdfe818559614cbdc8428e814aef218181d888820c66e8e92b3d0e038b7d971 9f7a9fb7d041cb442104b1042a85085541b4e19332f837a6bf8200ecce1e4e70 97b37dd1b11cbd70c90f0c80fc8c4ae8ee7dffb1ddb1a9b89fbbf94a53152516 238255be5a20745de3541e9e269b10bdc886707eb44e6b7677ad29f57c2e5380 18203e567a0bc5b74c253fe7f3f55632d245f17e1acdd0efbd806129e2c57ce1 183149a1e04a061ccd380488268820b73083007d21f9f09ed559d49b2ed9cbe5 2dc198fb09f54ff3988d9c90d94238ddc96197722d71cb1793164eb352ff4a5d 45cbacaea04505e21430785d1b66aa47eddb172a078a578fb976b018b3902743 98938e4ccb446cfe999b091234c844e2a6648de95ea4b7408320b1b37a0157a9 d6b18d00da6c1f1585aaecfb15f8913fa65cf12466dd5ebc55fa84b28cf39e2a 56fda2b69037627ee3958547c0eafc7f376c0941ee1dbb2dd5885b63727392c0 b3538a6ac0908d7f225b58f2185a1735e2f0013d66a5fc5c7371158fe97b1005 4f4ea02eb4ab62fdfd94367557069356661e2d2032e9ad94b04e9ff3a7c44a01 204 a905229f448bcbd6b4df58e365ef53b3116e842f5d51de1367a74e64d9d1320c2598b8ec8a28210d5ba475d17f7abbcfde3d04b3e81dae851e32ec9a7cec2c0620ecb02a2f1c3067199071a533cb967809e4fbedf147c2a38c82f5c40193250af758eb6cc4b732d92ef6cae9c7e4d3f733ab49f89fe923be0c3a8cc8cbaacc08a4c1ed0f185f6d66a8e6e7438536e9fec766a89d8ca89e16e14c58ef9f25220e43436f539a30ac553a50a81cb2d87e832dbef46467eb62049e7f80e87ec0a208ecbecc910f6ba99e929096293accfb020b843cf006737d0c69e6b4bf10b17e07f68bad5fe751a7e6c015d46c042eb0f100e6df524d05b2f123a3cad2ff203009b7f7cb2d44bfa4951ab3010bf4b5db4d377e33573e04abdb06de0511e2ea6e096ffd9cf62314fd6a88382e2e0466ce91d929614fe0ca6b64aee977618e65ff09fa70d7deca54c729c009ea73105b9e6475017f680cb34bb5f2a255f868400c0193c376f7ba24e556641cdcd64afdfaa6f3f0d378903f2f841b320b85fce9960abf3c360a659951a5afbd16fa9d4a0fee00534831f5ecddef5788bbf260936602d88f893ae8a8165ba80fcfabb0e29338e077b7f71e2ad8c29dc02416608f790667966454f49f775500f05b3a5321bfc2e7c6f06474b50cc565940becf78796058e20ed7ff0b0d721dbc3bd3e4bd71ac6b7db831e4bee48762f9081de1603280b7027e9364c446689540f1dd3e7d0ea034e7e76357468dfae80b4cc2b353bae0d2ddf35ebf0252f281cfd23e61d6b289508ee40ce1ce453c2e1e2cc9e3a580d08978a2c48997703991a3922f68d36a147c817fd9d6eab228aa1509b4b850de207afa40fd1d99148dc62b44678d959154478b5cff99a6cb4208c65f3d514a1f9078c2415df86a1af7d953a31f97f7ef99bb9bf43a8a2c1a2d553f4b016a694410c2d13b0c04f6aee390c4ac7f360351ff086323b907a48d0e97aca9858949dd2084867a0744c3ed5e2a7ca4aa77f727ba23ad4c8430bc6d0eb7e674ee493271e0f29d882710b6bf73c07c1fec97bc84b7816b3189e9a57cb7518178079514b780105578f6a783ad337ef71e2b90134d504b6bca5446b57d357f4b1a6ced2813309aae612c5bcb48f71e538a22ba88b2793955c71b3bbb75de05f10941e83ffec03303d7a221e4ab1c09bc767f66fce1b0b165c8d6fc4590bc047252c53a7eadf08a64c357d5e442298cbb39d7e744d6365ae4869efe258d3a775af25282e175203db96e2c8901365cf0f37521f166f6aa35d71810bd4a5bc3baacb9eb3fec75701839bbf432e8bd02da0616216dd1b3b1bc1f4a87acce1ee084e00c4388d487a0b906ff188b5aff18b9282a16385bd5d8b27f929e9f2bf4eda70b5b40a3a067901b336a0f76eff2e4aa73dfbed34fd46dc7e8c025a631d7274a5c7f82c1eca1f02219d29daf36fcf86d2794a90eb45af57bb06d9b079ea80a2edb9000d9b2eb700dd32bc8a5acfdf2c59ac7c0ba116e362f2d8a8291c11fe7ab43c14d1c995eb00b89ada2f48000c4137b330688739f5bfa8fee35d2264c4bc512e078fdfb28809be3938b9e91a0576ae7fdba0f03b04a73250bcebf651e98aaeb19657101a7e0f523f96b01f89a52055c5173ae44af145a36b779ad1acb70ee397a2834a240401f8448e04061d0017e6b6d34d4b96305f238db7ac6dedca3d5643a648f672b506430da4ce89c8a33e8be5b60d2dcf6ef0a204f6a6e0867d0c3344effed8505706bab25c7a54a57891c97429ec649b7978d4c415d29662dd2147f37ea97513b20edef5d683963c3145fa73a33c6ebd93b6c9dace9ddd69191321cb5c2ed406fd07fdf31309530bdb101fd46ce639ebd158f2e8ba786fb1fd62983d22276f167301ebcb33991d030eff9acf56497021a14620978773e3ce6f281aa56ac154af590829745ff1d02317709745b2e50474050d2807ce953dbfefce566673a7249b17034621026a6df859880f9c4871745ce520b89b7cc2ff558f17f93f73cd2f21870d609a4d8bb34ab213dad81c15bd3c84eca4f6a70f548fe6f4387585a04a6e7f0b5207b947be5d6bc4c223c614422331cf9ed419c2759cd0bc7bc24b2ee5f38009f8c22893be48b1f8b84159303d7f8fb70a4d155f9c9155fdd3383b0d933e6108dcc17735c3a90f667f29cb7db6789e9f0862b89b51e9503dfa76e300bf4cb402b5c147e306994904b828f39e11679e41ea3abfd3afef0f813ba98c9654d62c0501edb686e7c22bc923c250e312569e102b721a55bc72f61255fbdc19b23c640813d9b35005aa8536d0cf7ada2342a6c034d44d180e2a4b78ab986ccb64a79007e75cfae974cc46e90c3ebd3e492ab761c437b914e53f6f9b399a30b42c03640f48d7f779f49d6d2f2315f7ce6a40ea1db9a59e4d69a058abe94e7708ab8d9308da8de9c07cc5b0b79086d5f9d2611fa4c383b80b62dae2b7012148a694d138035e22d55503a71a5a8c51ef6cb730b84b694b9d640f302a767513f3647716090140dc7e9ab86b73d4d72ea069275a168667bebf74bf634b7fcf38c29a7645fc0e11ce0e5c7bf32e418228bdf5114efe80538fbea9c54dcf9d0b38aeb0de60ae0a201dd20af7297d3701c3369ee9ab69fd437ee170e3e03328942403bd67ca6d0ff833986e2839904c00888a2a61e74dfb3fe7b9dda80aa5b8e31f1fd2ec154e00fa93819f02e63bbc267a621df251f1c69a3404d497921a3b0cad359562a1d801e2dffedf404be7c36caab6526ccf425bcf939406e815f85802e7e5f9a3830d002834feebcc0cb68c56615b3d5c69733b63756a5238193297a1c15efe969c6405f0b82683b2201a9bfe3c452b67788bfecea92a4511a45f812e639b7ca78aa40d77ce773666518034887b921756a5aed92b79d8032fec550e90c5002a5db1dc023d39359979ae9dc880e715d2f25f592be9510aad4c52cf33f18d9cc800a51d04c20b8bd80b4b1ecce94c453fd73083812f05ba69c5258ff5b192c6639c717503166d197a5c02174eb0422e58ac1d2461b5e8bd0f722178565f879d723888530b543ac81a6c07e4a62422f128252636525b7a78f3a60745e5cdb1783338be5f0ed17d0189f1fe9488cf7a1051fed0c9c9ecf96df176092c47c609651c35094904b70c53c769c047fe8e479326b8a121d4e4e3b4d42fc833ec65b6e6bd7109f303ded7aa4e749c68a8a8b05a7765c172ae4f0b541402817ebf08cac386a228d3078aaea9acf4d000a9c4d78856734c80123439a46c781927c4f5dc4f8d2563af04e5673cf2b206faeea1aedd05fca70453210515cd09c0dfebdb0d0b532e8cbb002578e18b6620adcb39cecbc79d67a7ddfbbd9eff51bcecc8ae5693cc632425037e2e097ed14702da2dd08f154d2c6df01c8de2f496fb4a1050db0df38f4d8a00a9c8e79cb3bda8ba286177d77fdacce0011d48bbb7f9ed536789b5402624f1066656b32073904cf868da4f3b5984807ab70d77f5db8468fc56a368a4348b0d03fde6caab2d466884f4389275af6bb4ed4a5e845b37ccffa5c2ce8930c1169409ae87c54edb44d322c07bf7cd485804f843a6f2aa93074c077762f45572e02501dbc53906d0d056785637d272572d9bdaddc5218f3a42a39a2ddd7f092352e2057628cf83613674832e56c552aae03e85074bb6191100a0c110c627ddc76b2b06ce9258be5b2efc22be6867f2ec28083c210a886c9d3d02874b9dd986029fe90ca7e2ad951dbeb8933785d70ed6ad7f2deaa3da8f0266a196714f7e7ec72cfc02ee14a6c48780d75db575610591b23a5039cc5a88f3116b2c9d619976c399f30092c2a906fc2d60624614123496df4916dabaf7bc7a108c4cdf4ee1fd5acf590589a394546d5d930d6921ad89059e928c84c1d831b9dd84837a0b1c0e218da6094a5f9e784c0d288d3fb08a26dcaf7b4fa01a04cb96019f9c7d67dac56eeadd0471058cfe766cb95a438036679e2389081963f536312115991b956e92631853019a85eef2ea4a792e0bf9940f254dd411ac7856960a8c46a5d4ce16746e443a08ca4e288772180219ac48cb649f284d875a6d26b09876d54b23d3eca0fc04c5080af9741a9408fc857c9dabd101fabf6765cc4dcfff839386f9347ddab7d85b0d7b12b438ec95d130c169cebc81f0460961d124447c06257f7b016d3537799a0f9317ad97415da98570f615923fda90f5a12ad6999d0bb1b08903c366f0ff1405bfbd5dffca22012908ac68f964ea9ce9bbc8af6da6c00a35fd7970c6c70c40003e4e6ebdc99fb03928b98e49bd25a2f5b727809ace603f46c76b6f75f15f2700f418d88eb5a195267a536db9ec99a6855aee5c120cc198c67113b1f9619c1e0a2062052349043b5b3ae6053ef75b19a2505bf19c2f3ce6dd9b6cd38e52bf3a0ef4f63a9575290b71dc0efbdad543dbc6d8334e4c85b47d8c82009bc477243000b0a5a27b25f6ea31a3ff0303e53ce4b46ecf3030ff3e47849478882e8d4c560983ee5001be5c72112ec58a0fc19087ccb075f83244d38fbe7082ec952b2d4a0a19b1cca4d5844638c28e1b6c6c57fa4203fb6677184c750d04242b8e216a1b067bc6ea154d72c86215cfb6eaa611d3d7afbed45308cf1aaea4bf4fb463ac1b0064d4a9ece22700d79c0ef69f28cfadb95110b187b8e8f7337c50d5f51ec6fc0d85e69751c968ebcab44dcd37971e732c889802b1d3e1796e66c23da159f5f8015ff85875b6e43318d59042601e668f5c1fe995dc6ebddcd46e5d65b2efc26501842244f5fe28e998ec051274013966785f76a39dc7be21121c1a27c1a1988f0f6bc3a157319c2a129b1e5eb220e01873b5b3eedc88739a34cb157434a4655b0adfa7fd337dd235e44e062fc75ec7dee81fe39169777fc246cf29bceddd2f5603488472441d6329d7a7a94af8fa7d01804d66fae0b1c9c987928c025ca7b7b203522ff96496fb70086aa61f3f12a9d94fbdc20ff88a3dd524bb0c369804c3120ba47d6d0d22e2c28a65b7c376e51f4bca00e307f4d2a5be7692fdfab601b24a00690eb26cf2a3f305fc565edb277c019340f5cb4ae72062cee928f40e3905f30ed58bf864a824bf8d9bb68b46b1e1286883b3a974e54a8b77f0dd5a4476949403a1b0da02e687e6d1a21d39a0f67cc8c5c85c0f299e8db42a5b247825787f180a6ff2feb3b8ed46743af099d36aed6f9a34fefd9be2c788b765ae6b2e07523b0518047035f9411699c63e8595a4b9320a481207e487332a87d736c91cf4eb2d091eb33911b92fe4678e1d8f13c19ca251bb8f7b20441d47e6c799dcf4096e6109a05327c481e6f79df04c2ccc993ca297b824baa8470e4498cf43b826aabbb302c43fdef413815ff25fadf84e9e3fa3086705b62cb710c74da79895f723a7330324816407de1271b60e731977d1af4d86e3d034a14a3e352f05f88885766cc3068ddb16ae7985db7b4edcbdb70de4cd4eb5f94654908c4039c3e317049be20c0f448022c0e3e9f04ad699e15a8df6da8ee0d9caa317cb489dc5ec276e77a05a089b0a0861d69e58788266f7d1bdcff298ab878ea92172354f08314b2a3fa10b0bc46225b16593630a998e044ec5a9bb1643056e3dee4c6f2f5ccf9daecf6a5e0894d7030025f9fcd40e05c9e73f6a54d730362e1b01cc9f2d5db45c336b18b0014fb89a21a8eac0e6dc0403b9d032022d44af3671489b8b6bfa7fafd3df8e6b081116778f7f3ef02a386730b643bde59acc2db7ac753c7270cc46d141b7ce900c4cdf521aa68da139a00b59bd361cc3ea376cae14253c7b8e320f52b0ea6e6807a1b2b6ea29934ec3b0cf15f8f5cdf964f373156581e78eb6848092953b24de03cc082ae4cdc71501b994c65c48b9df73f2c44c7092bd53532b287dbe7faef701adb22b822c36c19af77916590bc395d298d4e6ddb1e7ccd7bb7933bf8ffd7b0f682527db4141308c3af779b5e2558b66ce7d5916ea7af096418fe3d65ce4300a2a1328d5ebaf7647c6ab32399151e1b8adc25e0b12d4ff960a440d11f5b0d005eef67c33ed3f4b4744d7d98f1d1f50d368dab30c16b1f7b112d9c212fb2c6a0c69cb437b2b248f68eff447ba39e4a7ac8d97273f2c507378b168ae88779e6b053455e7b29e1294a4c8a93124532701c84541d428a84de5acc2b2e9d7eae8dc0b87289445352cd29aceb27b5a6f0a9623e127f84b28160642ecc003aff0035b0ecb224e50bf2a10a84e9268b6417b7bfd12c33bd27d7c5a48d6960c01d8eeb40ee0431f73805bc6b3516780c77b8a70cf5b003354c529f39f45c1211647a2d30c8a810c54c0909d6482a5aa2e4a9f0218ae551a20a93980eb11c80d584342b30e0ffb450e790246bb91bf0b7ead7161666c2cc64f79b745c646f514b45c0b1b0f39facb1925899eb80c2a50467f301e7f1b7789b6206d9658222b85400b19990e819c1ca5106625324e25a890e46ae8b5817b0d81a47f775f06160844ae8d0d087779a213a0d6e111a2fc71f860b9f80df3c38e08ac7b71fb3af53172f20d2004cea1ac76af87c6117749bfa054a3f69521b34b31d58ae8456c4ae33e36f31d0d4a5f3429a5c926b4fa2e356fffa44d9ad1a562d6d9be6a1896fff390d5194e0b94c2375aab43f8a147c5825f054932bd9b88decb2a01a65a4618d26a4862440d3e3a8cd082c654ee9e011c3531f2f4ff33b1a9eeeb2025075e3b9fa6ff3d290168844df4da8d258a829b5c36a9a46b0afd356b9ad5bab1d8c4d7a7c215f4a800a2cce1d29cf64329d601f836731b2574ddea2d89738016949a36539a4969b4032b29b12c8e1029a8875f675ef74ddcbc88773b3fac28b6cd53fee4cb47821c03d4968eb2ac0e2e91b41e38dab10cb030389e28a7f73cafcd567429a8418e2105ef8ac5c2ad71f3f7e2f7682a73c66d087f67409f736d04d4b60f68754e1dc90c2412d86bad431dfcc8a869c5ee1bf96ea7b4d2a35ae1d3e0d3bb6bf76cc8e605241a67f2379d7aefd2bf3abb9a987c565d88847ee6f8c2e64eb15d1e3b2d0205b922d042c20bc376cf61a1386cd9b079d0e504169794682fddfaf877807cfe02eea07662ca5bb79def9b0edbf6b15af6455c3ff18f81896ef039f28c195cb50565e96c47072171879bea8eac4e0766a59d1d19d404366d897bcfc55c06fa100a72bd1b764d04cb5d94ddd553eab51caecb49380fd56c3bf23c40dd8ff37f7e0e852a6f78760a395324b1deaa1ca0c4a52033bce9d37665cbccfb0d628a0e4c0ad05e7c5d37e387d90cea4890d7e9c8f976fa4ddb60b3de212469569db616a607901fd285abb313c11a8959080b3d756450b1448a494642d5bfd29c1d92175506014ce8419cd49ceb69b9e0cc11e78001d4387c16536dd0fe697e4f49f3d7d0009722e254ab780d37fecf8bf58a2b5674a152b4ca68e3fe7e5baf6a959395f60ce3eaa6ecee3bb34c47c84f825433cba087b8c9e2f0de0f62eb2c755d0861f30a05c065a53439be2e794c3d5cc197b5e25b5124d743d9468db8484c65bad12503699c33d0306b5e71df09cc4cf50cb9bfec7f8ada291d7ba77d079a0291e09e034e8da6a27347d48f5b9975ad92a4d84c7939fab99e89f319719e3487ec8fe409629eec569c9928663cd4f4efe35ae8b6876122ea4b1e8fc4869fb16ae58ba2052f4ce344eb030d2f5b958b8a0a230639b6025ff6091db523d74654bf6c22830a77663dc6e3c17992edcf882fec55407772a403a66d74aaf7c4c8cdeaff486f0056cd005772903c3e8873c2d98b7abbcd35b7d154795c2f73dcad880f390eb3035fb9fceb50a8e82dbb11e9e27b7d08d5ccba4b7b825be799c14204c9c3cd990f0182abd0675108e7641219e2e287aee0e453026618b384f7ec0475b6c2761d06539dda33e894dabefd0595654ae0fc1fb42c70077309fcc58a221630bbb86d0dac4048b707e179797fc99600c758edf10ff549089f7d66bc096bccc7859115013be21833ffb1169cc1df865999c6e18428da149ba4cec11e46beb5cd8fbaf40412b4b42362bcd36b56b78b04c882f99ddafc0e41e0675fd463919fb10cacf80fed5d87efa5703abf57d8d366a2bfa5f1fb796eee7ddbcabd9ba35cf7c9fd9204fb45859b8726ec0ee70fb2ab873caf5b333ea273ac9d6bcc59e4f15d63891e08c27fd61a9f583b90d4cd19d8c06b91a78c6bc6eef4f81920d4b001be90a9520eccd8b2018d1c62a38d27388bf91c620739055d174c16f36f0abef8828a58ae02c7390070c03ac9a3bd18f1b3996322ee0d6a883cf009cd234dc936454fbdb70a1b174de9664d41dfeb6206c394f5a0ac2bad288d4951ef45d09028c07aae8d01a02416f42a3ff840b7b37c9073e5df67b32ae5e2c0ba9d79394782f33b25940a6444bf52187752e9686e8d07a51a906ffb72f0a653870e29c38148fdd60da50771b65d9c65eb306efd0e6037d1f4356baa6f0af7858e1827d6cc7e0fb7a6970217f6f1ab34254a47a80c9d615c5b1de576350345eadc68cb05eff8fdb7140d014dfd4977d85ddbbcbabcd33844ccfe1465a180c22d844ac250c6a36cd33d5505411ce0f59e32b073e75fb11426cfdca258f37fe8ac4f86b237910ac6b7bd6b0790f2ae95924abb00c3adb71eda0f96828f0a548c9b54f4b521067ec61d643607f235075a90e1d6605c3342c26173f941234cbce6a6bc94f8110b35b5d58b7f008d232250f6a4fd39831a5ef6f11245f3a36cacc3d8f21acd7e113a5363ee91095c4000176df4c981dfb3f976b7d3f90fcbb7f9180578278ed148bc10eed10d0b663b50375760ab577f84172d0c7aba9c8f85c0e805f123fe1bbd8b4b3438640bb3b1de5d94203dba6a929b33c4a7e8694c7394522a48337af5cbe1e0c203cd017ab565f66f3ee9a2892b2da2f4b905a5d715f0cae5b66576a592830a5c8c6301c445e5bc769310893c33340a4ef72aec9ede613f6ee25c58068427c7727ea104d163ac5a8441b156593059b6670ded5bdbf51a1a9a8490fc680eff9bf6630504a09e0497de94419c2862d9a70441634557ab3706f3b3a57377c8bf9327d2ba0a8ff2959855984b7f85a425ca73f83c1504a76c9aabfde872c1de60089a873b009327195aac6b916980434bcde81fdb1a2d635e29bf77d0430d27b2a47ab6250c422fa9fbca49e7f9c3ef8cee46522ea6f1b1dee38e91b7261c28e48576c9ad0302ea8fb85c0389060582e699a416dc503562826c63fd18b96aad2f7150356f01e962db92adae0cfd872f3e14216606ade6df351dbd477751dea063d05438390d9ba2b48519031a0ef8bab9560f27fa18add5aa559e5b7f3b4660c121a990b30f1605ffcd2907796dc5a83a2967474e33ba236f4460b519bfc5eb1ef9dcaa22056460a35cc59469e3d11b5562a3311f8dee918dadb629186b7fa80354ad09920bf1192144a9d3b55c4f617623cd705b8f87df12701c740e59d608620d051cdb0a681240f5c3d0738eda7b6992e6b17d314a46b99467c56e7dc3cbce4421d7a40f6f22eb6f5530c938b11387aaeb7e86295dcff2bf89049611a2df51d26077020ab668a47ba24e2746018dd3e0a95376045c187064a5c09fbe38796fa5beeca80335dc4c3b71385101bbd8366eff8240bf7043b7452a515807d7976d754e1dcf0dc3f86be7e2b5f7767c2f5454cda40b2514ab9d7fd1b2c2ed4ed832021481c8028c3525173166789b5b6e85a9900bec2bb826f6c469ae68033dee628716cf0b05213960bf87f65fa170cf3981bc53d9f0e4e7060190bfcdebf7047f881b1bfa0df4e4868b44120186524cbc65f081ba132c094d990c36c53e78a386b89d89920ae39525506af0312d9a8d53e3288d69fa44f5b7efb80fca91f71354da3fcd0001d1cc5efff003db4208994c93b1c8ba8752611ced0b6be64385dff3e3a1d99603c3cd630aec5182a7628a9bd583d3e0307e130c3c056ce53df7823781b2be6f0e68366929e3db1d15163699cb52edcff18c7754746628ee8b83c94e32fcbb540433a3e1ce3ab88fef6f402090efccc0704f767fbc8c37e697445ac53c3c7c500d01c921f64145178fe1482a7811ca416a917f8c708317df8f6933c586740b5301ef611168662eb451e3c87cd9cdf97ae0ed16c7e8833f617af3fb288eea9b3009e40130c467268992e59afb94063f500bc1d5773fe816fa6dadcf0607a2e4960edf80cc7c9f3e0d87d11ef867474a9f5e2344a777db658d4befb424c855ec0c081461edbcae88127fd292f7b1cf535a0fda7690d37b6945161e8ecc35f638f40bd0832f4aad78ebb0e584cc30bfe8ccc2e75c99c0777443b8959fa21385b75d0958a141b7fb96b9f2685848d287ca4304bb4390b3758b856ae6995d7e67a0340db71239a5993911ef80895ccf5b36338fce1f4fe234b7c722d912ee0e94daa80abfe2ab020437f57271af71cdb218d2fbc924008b5e667a062fd08c6db388430c30863da329717b25acc19f33581fcab0e3bac58c208fde5ab9498dbf22ea1e0d3f5247b9e1549e55bf786de6e1a61ba4f12f19ccfc53e01d79fe76d180b657092297fcbddd5e079cd763b3fc25c9a65fb0a7e03061e14340e60de0751285d705dea83c50aac7de7821758e4b754e5fa8449c7a7630addd177721a8a51634bd0a08e4497e610d8ea8a63d317e9ed4534bd7773e6596ec0ea2b4c2927a17e50f0241f0bbb40456d859a1278340f9e48f7bf9bb7b588a290acb19c9ba56a63ba20ab053242b08f86eb28b911f313913979f06f912ca40681ac2b01066410108ac06eec23df6c2dc40e18871c41f6e071c795a40ed49e37eb156a632ad13a4926e03390582609857a672acb93cc2c50ba103cce1b4558430c8fe3741909bf5b011010847f0b8083577cedcd5282bdf132d8c3f556b3d3e31e0e2220b7e87742ea2017a5667f2c7754777123e60f783f2c3ff712b88a46462bf36db6265469cd85a004473e6ac6729bf13285a046d8149f2ca793b39e90531f02e56f7989c2671df024c7084bc037d70b28959d8a6a9b8263ba30325d42348a4a066c9b2d56fa60c0e522c097187ba5909b5025d3c578746b97e411ead24a457108e905d2835bc2f0298717ca1e9a337529fa274d92c8b5812806f9da9885ac354200f9f289f33d603643b05e0eeaa0fca529ab7f8234a9ba3c67bfd146f29922422da65310b8fdb0bbafc5901aae1573ea8b37eb05e4c0d09be63d4b62dc13f3077d58dd3ac43cc0a9de82e3c83f8a234c1f2b72621b09c190f828219c364653ced8621e3172c57063cf45e40a2a82069da9f3b4182ac71eefb4a5b05950760c715809ea3b625030a2f32e42e8134da67e1191e8b995d06cd6dbf8a7e8188edbd7157e8f1043fee06629fe0c7e045a3c28cdc99caf78f6e27bdd8273ba5ad7eda480b1da10a87c9057020e229e972f294612b0e4ece4035f6db503d6b5822b12e82359d82e2bac301d8d04cf2ae0b891e2cd4a98136d211184bfb5bf5ba1b9de0f93ccbe270fc1a073d3be3d8b76c7faa81e6f585bd87535fc65420920d81eadc6b79401f65b7bf017759ff27515ecc89d960ea73be9e55ad57bcd4cdd032e08359a5046eb8d13d0042daed43382c0c4724a6aee3eec70fbaec9f28f3f35d8130e2cc738a04bd0e0bb49ebd470ecb7fbf8fa434f848e8aed33a1fd7cb65fc2415e3ad3bc57bb50a09747bdade1e58fd31e5fdb498b8f110bdfa390fa7651779521d1fdc9c3279ee0a68921330e26177d3e50ec20cc2efdcd3bc0a3fbf42e1f85eb184559d6674280ee849f04313627801561868e3228b1d3e5a020190131c914c9a02f9c60155fe0cfdadc634aa3f052555b2d9b0352d5710cdfea7d838104daa0d1b9467f06b070dcb39dfeff739f04f5224e9d4bcb820fe5c2f1771731bfe4b759140b7956fae0e7978415117745d1d57c5a944119c62b02321f549cb8d1a487078d3bfcb278907491c1808e65df0fa1e365f7d8a571fc6b43c8756093126af5454d4468c66f70dbff9a48615d7a41e4f32b4320b30df1c23d7f03c5632c40167a5ad8f293a150b56f91b38928d56132d78f0a28e1f01829dd27cf6cb3f75f00770c68df9fde10b3872e42581fa87ed4407c088feaf408d9933cd7e1ed859894df3c1de211c1408d151cfefff4295e50c46b4f7f7d3747bd5983a25a616ec095134663747079504bfe13d03791da920f5c23091338a07ef5970e76fd98e76f0f241d4aec484960523ce18f4a28f19c68699aa26d312e1a8407b7282fd5dd7ee4641a391eee7f20b5e693f4ae9cef7219688d70adb14bf582ad3ac36c9cd678e257c52aa27f3ba034c06408ec109986dc525c3fd0569f4c87af71e2e6998fd52a369cb7ca52eb10732dd4a18f1a76bf1a0216db6d3e89b5f29aa661570328708c84ede69aac65b0249544addcc3fb1898d33b9f87272f45a9b797f97880f77c03d16e84195041400c071c2d900cbbfb08a5ffd7183846726884e77a506321dd0c395271943a9dc08f4b5c8cf5872eb64d25c34d3830c4c45f7b1565647b985834be21a00fdd2dd0bb6116d0621d3eef312029dcd6e67941a0d13a3132c2db6f307eaaec88b5d6b0f8b9c1489ad9792006052c0305d03e1ca72d6e0bfd00254a7bdb0b5616c3b5f0bc70b8c47f6abf58511cb7d7474435f839812d0db83bb5152fc7c1bfdca2cc40d7db234280d0d07672e262533d9be4e7cb4fa38d266991f892c723d579404aa05306cbad97e179acb8ded8be33e87c3c1b7f0d13c63515170a5888135280c360b6554a5e57920a494728709709780766406988305edc2d3e70e36a335a2290908f749e424585f34db52bb23f266cfc21ed7fbc3d8c361c5c841ad52c05203e40d987e8c9f277efed398f9c02ba060a8b368794d9441f003b5485709680b5f1506758dece3a5456739e3a169f54f2a297d1f4b7179b996277f306db2fdbbe76e03041956fd992ea5a6282b81bd84b7fa17275bae847cbf6b7b0ce38b3b91548e02abd2b9c4d3ef42762a6fd8df382124e0bf149e3e9d4323d0142e898fba78830ca0344c27f1616ffb7f8353d0dac1cd7d8b172f8daa7128ed7f79770fa476ff06f23b93f506f4908ac698d7bda1351c54f97249be14b744a943de8a03999e630bb059302079a6c3f1a6d8e56e8a48b7f76e05dded7e538be30271c4d5b3bc880fbbca179510f742078390c7ec3a99a1e982775a035c071b653075f4e2a378f0016fa0dd3a0c9bed8ebde17c9d1d117b8a3aa9a4ede663fd4cd91314905df06b0a83ab5aff06ccb5e4569053161cb76e74be5749cc50c3fc26238b6245e580350cb966b1d375f2060409cb0b25620c4564b5736a12443d83c7b7720cc6e2cf600827f9a6fc1b221e59fa1e14c827dd1513b512dcdc743cafc375cdbda5bd788d0fa0b5faf78407eb59b77c34eef638e28e155b21cd6a744c0089792c54e0647a0459540d8c6c880aa75840e85a791de8a0cd107d6aa802584b6ff25025020b490b3a178c1ac3adbbd4d024efcac5e6f7507ac9c4955317492d53a6c1a5bb070f05aaeb989b5dfafbcd0b676b973057e7d683d1c891cbf5be02dcf1177caddebf0225bd57aaefaf5a1723887aedca0d8e55696222a81822995fc4ca91001c7dda0604603fd3275542b104240752c8cc50bd45453f606c0afa49cb627e302088c70a6f403e7ee6837a9b0c3d8ca404ca829b777f7d5eb3efc96481f05ececed3370fad98b4da97e7b8e5381e82ee4f3d07a1682a0405b68d7d8b46ccb2d106c1550ab4f31226e835e7ad9d5d63e17a57a6bb14358fbba10e6fba89fcb419e8211208796d43e190523a9268300660eff7d12dfdd8ba737fa36ac8665c831cc3600b034f217121de144660f41447151067229610227ced84f8829cbcd7059c074cfc0f9f604b5b8ddc02f03a371d55167953557700fba084a7e7a6fa5046b905642e031366d52706175e0b09027adc84d6b799b305ab984e7b86c3def7d873d8798603655ec65a5ca477d64c9e5cdc589091d702a047b28d48f4bf97d748717af65f0eb7bb81fcbb1f6e56f3df0fb12f89f21df6b0127479f84b75f9f360bc76f4de0c087e5f8883c9039939842369c948e29597e8230d6e6c9243544c4c00b90a270f12e1db4cb5bcb25c35beccfceccaa5855d5a86cb0c232536d3cbaf64f7ff3e0ccfefcace88864fedf39ca25ab28bdbdeffc63c9d8bc84a846f91ac9cf4ca7f0f5d4b48cdc30af64ca7ce116a5d7db2d02bec3897583d786a9956af7482cca70858604b9f6defc7c609670acdbd2923cf0baa48fc9c4e3512ef0de03597a095054069beb01b72bfba5803c427da8cf7a650fbc45be786c999e9982c35bb1b020f988496b7966daadb50c9182f0a96251b2139bce6d2157d257c113c0bd96893071757a8ff890aff9dc94cc152691b8487705855b61e21ee22a30fa1ac3b43ce08949226151c2b8d82de0073d0187c2580a53f0eb32147385829bcf4442901500378cfc3f49c16c4d7f226a0d3b7fc6098a5c7a5b510babf68795360b4402a1b09647bad1da714a07b8bfc08627543480b4cb96ec61a3de329c17d5f055159550839db697d633308a8aeb50f5099ea78bd484457ec9e2e81224365ac78adb1e605b76436fb16950e4e13e9d9b9308f0cdbddab1e8e68efc62084849cab91ca820eb787605021ce1322da05638501cbe914ed3ced9ba73115e4746f06f055c65102313765aea37ae8349f2b22715484ebb6d05461ea394a79f02398eb668aa1ae0bb7a3dda94881db130b704cd288641321a90681a54034165a43ddfbeb2cfa9f01669eef11b225bef91b379b88968bde6bc8a638a574a3e3300ac8143b13f5f902d5dcf331c168304a7668a783e21cda7ddf3286bdb88ab40d3630b1bf9527e708e05c02ba08fec5b4ae0771d173c97b81773c3ed55e900579d1f4abc01ca7d405cfd9d5b877f8b29a2c3eec59d652f5f2b16ca729fef248812e65a7d45a3a4c0f5b0c6233e9c2287956411be9075be3b05bd6610979eeb54683fd473e44efd509e52e64df862b1a7d5512b26d4fcae2f3ae4dccdca15603ff2c46a71be6a3e806aac3227c5479e067e410931975f5cab25bdd9e52ff3be6a99b94b6263f6ef60a8fd8ea935c62f6b11386ad8da37f288fb137d985c199d4f9a296573da418ca0ecd01b2418499e64c5244cd9c254decc386f8b6ae4e03d0ab17a78cbb2e89c702ce1e1c9b637e12079f655ce79dbbdeb45714ca40275606a80b9402c83ae71809eabcdb609928911740ca5e1443a99a4b69cb544dfc05a9bfd335a8e73957e20f0b88a62ab868cd2837f6f667e3a865896c323d9389b91834da434bf71a2704055ca01a63e73106ec6b84aa638b502e858b97a13b857c19f5940a1e206d304d03600040018f6a0bf6fbc6788463acf5b25f37711abdcfe77cc2059d7d06af2b082dfd7409e505447cbdaebedaba426b7562485034a2a7472f934a41c2ca902d0ce2b501cd7d0686a838e640da652b738ad74ec10381cc0bbf43130ecbf202be05d0e2a4e1987d0b31cfc1e6736d6825b974545a03d23f58655ffef5304c0cda00ff42d40ce3341a1f7eb10a553f7c455e95be138f52dee26a90ffb9ea63c0170f47b66bb3d477a5b04351efc2172d60e25d7de574c6a9092d9dad8c760bbcb60816898fca364efc2d7b09d4021b2bd01d5b2cddde228aecb8ba95b0f42e31d50618fc5ec26512bf8286d0b6df805b2cecac7d721822138e6cd628e7823b221b079569d5acb33d57c44c3c95b473c81f9e6c508ae6d47ca4549df79ee1a4ae4005493383663459c326666e639f292946a242c6652ed0d804a0bdd9496a6b4f29050202ca0bd475463aa1894cb91ffb176e466df39c0e11d34ce231bd247484cb08559c28ee8fd0bdb4e94db9d995e3b6dee8ebdf263fc9515d99a555cbbf0bc806fa115a233832d759195a91fcb37d2aee13ba510e5c10dde8a4d33296d97b730a0fd97ea4073ae4cf8e0bb8ebda36bb58baf695d888cd3076d7eb5ee42ca28a0448c3663455792061b2b95556d3d6b087f20902aea04a2327704a8aaf07abce0269343896743263ee03f888c2c538de426e5d96e33de2d478f0949e1324fcee0df6ede249618b5a567d430d9b6a2a2f51c0d887b55ef4f9364c69b7f29284d7081ec2290ebda8dfcfb61c9dc988db38035afbf437ab63b4b3abba168a58bfc702cbcff10e2d992f1f3caeaba8376de5b8e0a73b20b2fae09f396a9960a95fa00248a774092660bd99afeb6b0907d372be6973a97646a4f7866eadda42bf5a40097ed147f36a3c8238f2ca734a153e2e52def8dd344dfafebdfd35bc78569cc706134cb21608532df9083c4e2df48c74f6e731558e6a244cd50b221ce298d3d1066f46091248718fcd9c45a6534b37a37cae75ea2a4591323263020d076f6efa0026a17ef5d04ba3073f34599d61d83460dbab88efe06bb128484b973d276a990f643b4a4463fca29efcddd070ee4816713eec42b57f059b7f4c556ae65991b709a1e7566b7b493d70d40c6b7813bfe2c127bb75165e31ddbd108f4dd9af0a5e06ef4b1fe7a9dabbd69e38b5816090dc63eaee84362a759a171c6ba361d17fc907cb5fc186931c35085b4a3879d54b4046b20e943dcc03dfdf764ed5ddf31db40eb912568d855607502149716b3209638e4827fe6ffe17322217df4b915d9adf03e2b87a48bbba16e3f430dcd02c83b453a9c18d98a00097a8b76ad7eace043c09d3148435b866df326835049461c52a0a027b7c1986a425608f98325e9b3f27067f96b197442a48120993cd96f8df852b343b1961a72397728e4bd398d623c30b5e9cd054d1bd6bb93f9208529e7ecd4474d250b811132a3f0f0d67fd40fc07013feea269de72c83f7bac8c7578807457e199c56b6352d3cbe1ace5ba28e3570467d51b1f2127a5cc528ecc35894d253d026d5706577f0f50521b77690cb0e90fb94137bee9c728c07265bdcb8db835f35ddf935b6d6bc03a1535f6df38a2f60f269bd871f3e5bcb9b53ae3dcb046cb53e09415a679a953739ce31e965bd40601b5a703e07f4c013c9c2cda116effd81e06f2d39bb698653c716d1108c6e47c0c1eda383a446e6811a28c07af7b42b8f5a43f91874ea2f5358f0c12f245bbbb003eb9d288b53632b31114a332b26abd81593258fdc4eb6c31f51e36eb8cf98c00850e45e356eb37afa936140ad2f4a7ba0bed11433c8d798ef9d4b06b3aa038010eafcaeef2b942d5a5ef611d6b8e8739105035f4c3ef069b3692209e66c06e00fa07bb8b0e2b5578a396202d2e3117add3c9aeca2c95c742a1f161c3abac3f07a5d6cf09323a2ab782873af2efe5276a25c08d401c5ce1d9a2c7590f1b848f0bef3c40837da48d04ba3005efb74f7a6de2c689a210d46124f32691829443a3066c10190929c43912e0f042ecebb33f0a2b384a07d8757f62371845e5eac8d609b2a899b896454ed1bcd76969b40674b9618d7c7439c5c4833f13c21d84bff800a002f17a6c4adb748657dfb832d43a0c412376cb44bb363bf0cd0ef205c66d05c722d2ea1780617b156e531ee0fca7845a6a8b66ed0af7ba056a6d230e5f23012d3df0a011fb91f74f1d14487eaf3e77b0c2eceb7533c6ebe2f2a3dc6d655e01083e4d139f9856434847b06ed41c12d474b4816673a439d3bcdb6dacf992de0e18b11fb316f432a72b5c3a28faaea2a14bfbcd3e5e391c3b625b7ecbda2cf802744996d081263741d9821dc1533ddf2ebe767dd8bf697ff023ae7f63c5b3630ea71e254a5eac99d0c172324b8f06824890222833c4a3a6d3f7127aed56480007702d4644b67c18d92906dbc980efcf693ec31dfea9ce1f9061ed3808578d7b07889f27633c4bebf62154fef766bb523effd4aeabad0d950b86095e91ebbcce0b99fbbd5ffae06c4a2afaa187cb9bf488b95a7bd32d5f1f9d08e04eb80852510df4c6da68c332a727f927a31fefc1b1f0c63344218c2a4f416cfa2fd7acf90d0c3a0289e0631060516e08910abb896325cb39e2a9293339b7fd450da494f14c0cc6282ddea0cc43ff2955f1437cce7c72617d85a3853f88b9814daa33039c940e2dc9de37dd680039e18754161b906f0cda88bd8a4f4753a802a90663cf10e80ad1229306fac3408bfc346a6f53a9a32487119980e8db237b5f9cf206d32016054c6278eb767f894f546ffd94c6d391c85c8d9e00dbec79ada19fc151a2e6610a39f60c64b7a73e24595856caaa1d0d5a2dc693038289a4369ee0b8bd6514910598e10cf6f68e4bd551466d0aa4640981b05739e4ec2d52bd545e3082775bdd0d2eadcc3db115a0fe7a2de0c583a4c769a3631f55d0ca147a17d3c4ef2d866c0f31bab53e282a113a55b7548db5ec963e4dc7ce58fe0ed0aae72902d8ca358c0fa10fbd0d82f1b1b75a792b63473d4247556eee79de1a1b0c114175af6b79c40bcf20afca171ddb744ea85f3fe8e10852595e42b89593e5782de681dddc05a0082c61662fa38267b1a36df9fac97cac0b8d39737aa86c9ec3703d4469851794066784f7243d37261b24952f5bb5a8ff0add82b0e017e247db0073e2482e00ef0e0b1127618077fd0bbfb20ef0eea0699ee9f9c9b84bb100120b76fe27fd89a6088e9ee3cef1a8efca20c6928c0cb498d387515c65c1b77de63a93381a1f642b07902d2533502d99b112422ae5147bc3cb014b77077a25f56586e215756dcf540e726f0c16f688faa65092d3c319767ac5c15f932d6af960e4a288de367731210a42fdd27b6e17dd7989b7fc208c597a8464eaabca174de591024a83d6313f250e9f30cab3a53e963e32cb7feb40dc1fbd5cfac3cbc03e6ffe816025798c63ca0d388747a2308c5a4506e27da110a1994df51f9dff4c3078ec266df02358e96506e32587a317ae37dafc381b18dee2440aa58ebed74ed9982cb003fb679cd7f60a60b87d161a706128cc8c3bd934749659170a9d682a500de195abda568e96350da68c2a3af5b120807775a44837406f4f2548a8f05897f196ad156611ce2d2a0ea7fd03b5e19df312eb8688c7d86730bc9cbcdb307936633eb4b2d000047e660e19733502e2e9de1b4474ab78de43caa7069b5e8a87b9fe942c14fb0d495d55045799df8f285a28770e44e27a20e7ca80c06c764136c4d6f7e21c7fb11303fc0fb26eae64a3cdc9771d8cf8a19a012e18c8a06921b00fcd71fb5e110045c2220f508703113e8e3bda762379065e243807d8f04a1ee82a5bfdd10ee3cbe7ae3f0c0377f69c949717afd959f7a7dd38f964d9b18759645f2efcdcb32a22c808ba0d13c679743b13d056b0b405cdad60b222d2cbf6f8c926e5055c1af6110b0e860a90a83ff0a852923ce25e3d41511c5c0c36aeffb7b26cd05f24804e82efc4f605434c53a239d12fb53df1a997d68d8cfc7604f86aaed1f6d7a6031db005a552094f390c4cf98475007b2c319681fa9f1b0564cdbd3be881a596167cdc8d76f70a11680bd2a47ea2daeb85d4dac3ebaafe5c190ca369501cbe21623e207e3ede0a6f0adc0d89d967c6a7fbffc4f257649d8d1d6e1b6623a18549147207040fe30bbc6c05f5a8c8df8d59e9de86a2228562378243d79aba40d79d7ca1e50f78670662f447e6561d2ff8493b8e66b9b24c4685ed5669b721c744534dd04e3916a208a02ef829dbf6a1ff4b4c538f39984b34828c0f1b38445e7faa071c16fe8ea50256904880545091d19695c58a9302de787eed93dd68689276222745e0d6b66f0855f58f712298de9c45593df3356842d9a5a15e9da10a2c6d59d759d64e1c0a01c401a226dd32222bfec5e6804f2f2bfda6e5cfdfe1341c27729ed480fac36505d0aa2725dae3346b63f56fea6b929faf34bb144bcdf66daa426cb3ebe2a8d90598fda9d458925b4a07b194f8839d50ece5fa2b2580ec851a4fe70692ab21d20e372f364be7424754755d9d2e4d384c8af4f046a082a3eeafa0ba68bb9aa6d705827f7eff085c961805eac36882cf54fa46f65138115fd99fd0424caefbc599077beca0a2a7060be90dd380ee4f49232b4a0d98e89f6e864c4aa8d4cb6407bd078cd6ff873dac15902655cd0890953ac2d0147b6c65a2663a589df32123a8b4091c1baa35d69d6f99cf70512e62b1b27c872122d0d5444342dd57b63ae0992d0621095bb7dcc56899ebf6d47d536b8341eb28db0806cb5c4b480e97c56a6195033de18ec030acb08b6453b562e8ddad0bbcab5b4bf5e3a2a91f367dfbab0951031d219a2423dafea825e61e118259f5bcc1f46e51133b217b102ec8b3ce159202 +generate_ring_signature c94de04cde5cb97d00fc58347c9d43c5e2ff19eea4318f3ce8eeede86e590181 dd0cd265cb990195247bcff884ae711d6d6e27a552da53c3871f9f1ef313119a 41 fa1a0c591987eca8d52794fdfcb34be618b911c96bf95dac8383b875200f160b 5df51ed1944ca217cb3aabdf05f9e84481cbfba603863402a3b0bc3032345285 aab3f16311418e85c428006e09f6ab4cb938193554381b480c2ef44782ab092d fa2d0b52bf1b930a1f0f482813498bd527ce090daa3f4285477aab43cd1c45c0 954e9aeee405d40869ae3c3ac2ffddae7c00e08574f8e28528d9efc994885f51 1ff131463c64c2c3a1b7af41435e737718ceb11fc26df0e48f192cc78b49606a 05defdd1653a375ee7b758c3d7bc997beff91c486ef9acd1f7407599ef9eb509 4db7cf256f884cbde45e0e580207029b4f5fbaa85ad7464b20e36100b70083a1 581797147df7936051e989bb4881f330344d5733220ab185292371438a9a7660 606177bdf0e2889440bc7c26fcbd0f17c5a204d1c20205dce16be9eb561361b1 94a10e3d908cac01a162fa1087d08145fb3db70cacf955bb70d51bd0c0cc2915 a40e979b15e9b750a010c4f924a6da214bd0a0356aec01f392e676c9f9d42a4b e4e6ba7de1cb51d81bf38ad8e9bc3ba7e3059b170566e6188e5dcdc197f424cc 0bb2355397a31022e06f6edbea574aa43c63a063f8287fe3de58a438193cddbc 1994a036f18f48016570cd7ce9c56458df51f532738e2fd45fc8e09dd53ef228 0ab9a2f03402f2b2d2d7e850d682cbdf1a82b34566059897b754188b09f84477 338c19bd0bcbabee027bddd1b819ad49d5c37fc77c7cb6d6ad64862e23ef632c e91daf7d75e20f04693b719c473fc61a15d3076e1e372068316e0ef056be00a3 f547d83a8f49db95529bfb04880da8d1856c39a35ae73070dc84b3694e49c82d a3f131eff367e0c26660772e1598e71a430daa4d7ff274e3c8da018a40b7f765 205875d30d48dbfd44277116bb0d80b478d1f8a0a83ab789ac0404fdbc03617a 92c1fe822b784d0dbfbb2ec60c8c8e9e9a797b807648554bb5105b951a3d9d6d ff72f514b8adfc2861faf09820604be178b7daf92202088a85d2d0e66bd57edb 223c5ca852fabf656ceb333b5bf01d7f1f37f2566b54b7c4c29a86f18d1b8ae8 14a1430cd78fd2039ac5d7df2e3069b24cb36b12f2576771da0c1911f49a273b 69df315a3694a8a96963810c498a765f95eb4f84478bcb38a8775797de768e86 e94d3267a6fbec3acddc3ef82a82bab6ee8b0fd4a7defb1332b936a5f1013fb8 ccf5a0bbf7e6addeed9cdfc3599a5a94e47c5faa02a3ba4671a4c008bd403f49 45f5cd60d7af60fcade4173bc0ed1a36091f206dc28e13844a16c675422ee1af b1907d4d139c71715303888acb530cf952f70e777b3801a0f402f2f0585d6930 ca8744c0d9e716417589570bf615e2f97e01a83992b36558af37d7ff28714523 fc201c54527f971e930f3d35bdc20ced6a666ac12d851398a7fa9f26ca509f53 6efe0cfea913636b65c218d9eb260c3b9ac83018e18623135af56184a418b565 e35ed29a37ee3eaf9d9c8133a0ffe4d0b7b4b0358d5889ac0b3dce4bf4bf12b7 4f336bedd6f2044ffb6866bf87bd50c3bc3f0d814b18be816f51beec2f29f1b0 eb40611822d44136ae6779a5586246a2ded4d005c83334cbeda1aed834b7f888 64b8c042003d59c3e9e1c4ae0d2ef6c1d151e02c4c5e7c36c7aa5b59b7a74357 e7ebbdc1ca40f25c085c1d573b4951e9d0e15cb0c0ad0026492cb6b815ec2595 2148ddd29c481bb590a19dc5091847a0a86d1a1f6cde6a8df6f594be8dea66c8 96c16cd72fb2150c2371c2313d1d24520bd660b248c5cf3ee368f95d7257cc0d 9cf1735d67ccbd6c29457094d09bbe4b18c3824e97168d9fad6c3b97a177f9c4 25cd26b4ae877a3fc7251903d65736fd36329f066ef5043d715032b1244cc803 0 94531be2aaf28336b8add2e441b779123046ed1f8897056c4b13390ae64d090fcdcf3ff0669aca8894e424082ebdcbdde21812b17577cd441934a7e9cad2ce06c205b3a610dbf6cfbc4e379bc2269f4d7389cd8c6cf2e0bf1c8fecb4f1551a0b56c6b87307a788205800d9c371bfed642968eac96d323c530e49f92a7a43bb0ad23bed8e642670ea2ac1b70e74fac28f5f4e8a9c8356a259b1992a44f7e6860ca2022c7731c6d34640857ccb54ec53c85e051c67d49e87fc5ba6a35bb268e10f9e917958c72c091a170f222bd8eace45113b78e12edee412883f6d59c8b021033e9f00e6d569311d549ae95edbe49768651f16c36791faa6dcf346f223a31b0496d6d39a82b8495960aa56958f423cecb69a3dc5229ef2da50d002a57567bd0e411ef01549190a9dea6bc2849e143784a8469e928dda2db82a5dcce15bf02a0800a6c55186a68f6e94329dd05b8a4621f1a8ef0f87ac79a4d8f3e3462833ac05eaba87aba0ae563789d17823ca6d3395e42fd8d704110f8f0014b0119645500f0956463f5f19ff420bfaf94574297304a86e943958567f6f2398911e4ea3530fa0de3bad6c83de2c3a9838e3852ec17941c1a907905ffe3dc9ae6cf05116d409211d397bda1831ae225402f07e8ac3ac910493f7fc5f4c13adc64e17ba6f5b0cceaacb9344dc593c57bb5ed14123e75c8930a2470c240f079d6c002eb973a60ab868bd8ba803f66c889b64a2935f3044500a5aa39d65a6521289d3327a10bd01235316b8f29897b372f7911fc4ea88edc38ec2aa3678a3890f2bb38da4e253016af8b5c9b1764d4c7d40dec931326696b353c706ffabccc8051795e332efdb0f85d50fff295938fbc91fde7a2c2f8d8e13ed9bb05eddfc83aa8ef48c17366609150686186cf718416602f3ab5714a3217be8c101488689bbd42e57825905fd05d4f02e53a21b7aea582c2349e750370406e97b3ce971d561691876c0c992950db16cd05c786618cffaa8e9f3a63b9ced6782cc69f8425274a5c236513eaf830fd370b4460e5b0ccdd066e50ddce13779391d210cf4bf524152e92569d8ce830c1f0f29a1c5c9ea885301fd0abe33ac10858cd6849181f9982fe2c8f169da90047d61c3cef15c70784541d5275ac99402dea98a8471955f974d09761f55e4bc0150bc778c4889bd89842d8b563313d597a1c9f8f89ce41205be2257a45217f7079007efe31adeec3e1cdc479780cb46a8a61cbf88de3394edf91c0c368f424904f8e7748274b801e514ef3a9df2bd74b60c2d4553ede7acc29a6e18734e182906722e39106b6b406c5928286a94340b70661d1055d0ad9205a2e71839981f330ea0d62f0f80c155b9e20606e180119bcc506c98cd5e06867b3a8acdbf8c3ea009901f82662380e9240cba964e79a82ea5bea8d56fffe907fe994d07f23e9762051cb0aa362ca0f716d473c18239a38bba97624b04d537b95710b260b12dcbb1010030b4537d1f7e4996b14ec7991fb0d9e5a9263863c2c1d72fcc4e38777ebf0f86bec748b36497b57459eb23bbeca2fbcea0ab111ceb0994462c7e74e54fd106eb725875c68ac9647d543d6c9421bfd12ff9d5538bfc26f4fd234bedbb1a0701916b9385013a0dbb26087b32a74df8ba2fcbb706844d1c308675f742bdee1c04ee644952565eadbb1458593694682c1ad9f7cde09c02ee6a5c3dba92de016c0c0affdf6bf4b2ca84d0ffc8cc8753f4f3142557161a02c43d38124c04a9c2c50325cc9bf144cd479c764b44781e441702cefea42c6977aca1410a003ba9685e008240546f3fc9b3956ae459856803a27193179e8e108bcabccd2c38bc25a66d00f0ac9f5191b7b215d695f3b0c43f8af577b26e4f9c1426a43051d22e5a4cbe0912b27395b6d9785c822060d710b2e2cb87b41ebd70cf1bcb8ac66928452f030dab293cbf2c1ac966d311a79711a9f1c9df8e6848dcf5c60424cf4f7aad0265002555686be44257961baeb71087560aee3d842b84970bfd5125010d5891f85a0065471bedc4db39ba93ea8b729e62a72c02fa78d4fcb23c106ac4431e6e9adf08122717cdbd02c1be09b34a45f0314756109e0849ea60102e39599376e7f57c0b5bbf2c0e71fccc029139ab6bea7ceceb47935c3ef3f844c48a204f476d99ee0b19589c40beab8fa1bc474b5a85fb8177e42665ffcc21cf614f320f2212fc370451e9cc7cbfed55774cc19ba8e4eeba40b4fcdfff8027721e25ff1ab11ea6fc0696aeab993b2ba87dffa35c2620687f1081c79fc15b8964fe58636102c6225c04538ba9df4b089bde96357f1b7529167f606f1d22a191fdb698b6688cffe0aa07478ab4632eedc8a6fd73d532dc708c5993c2fdf629ab1ad39878b070daeef50161174141368451014097f5488c7e03181d0853f54d02e24e93267f54ca9bcd0d2298af2f543c5ef6e9850549e739f5e0ab0ad11392db95443f0dda8d3a94850df8f0198d55ee345c55a2db1c85320390e2154ecc7df786efd7f483b96b3a170de973d0ad93a6cce8c6642261b08a1f99da721d8d0b1aeeaaec4f26ce2a54db00cca418c80877ff5c5d391b38bc71f70755d197322c10c72536cb69c5d1d21b00e3df4614b4443d28db24d6e8a03e95cdf2467cd6741f017d76ce34f46585c30fc0ba9a74fcc1f3a4330a8945e848465f74a52beec2a4445773f4e651bd1f140ac6eb0cd47c6ad6c7d0a356b5315cea8dd2030b220e70b8d64d1096c19b3e8f0ed655ffe8ed4115ee277e974881aa42076731b4198c9c32a5673b86d4a3574103ea525dc4e406d75869d30a3803c5d2b0c86c5be4236ff534a84e5aad8162240d35b62e36979566e75d6793b21aa4602a8e8b2173624e62989f409a914b97b50ac872b72eebbe0aacd4d044fdfc0961c9d79644cd13d6b87ba4b8cb3452e9a90d0f779527631294f7a6f630f9c6065090f59eef2f5d6f65ed1545c78c7107e601f8538cff77718952c0b4d14d222604c649b238fa9dc3201487fabc4dc768130d22ba9103b06c5584c3bfde2ebc8b9c71f339e99c33ca0f45d4b0ee69a3797603d9a8009c7e4d29c7ea7ff3b21d46e8d64cb40c59dabd2e72e48d282f5b6acd08f307760cad0f368e9ee84404acc11ef5384ecabf20dc1b244f99754a63b2fc06b18fe28e7c26b2cba2ca8adf264598c2ee67857ffde4d1ed34080bbb36a54801bd3cc4c04016950a8768a4649e05c941b17cc790b9615d04bd69a8a05540420a16561d7010e9f1baf7cb230b30c07bfc93d7fcc7a6c0be20cf62c4ff3ac12d01537a9ba21209f62ef0d5f26373f3ee755a4a7d7ed51f4cbbc0433c0950ed930bcf65fc192a962cf9c5dfcf8d62969adc89045750a6a1010f0ec41f9027ffc40a7019a9ec3cacc52bfcdc3f0ffa16c27074295a6464c4bd2c49c075e15b0052099499a34575d4b7445b023d7802f010d081662ad83ca601599f15ed6c8140fd02ca088b91b9aa0135dd250a7e412b7a59cee80d9c1c9adb96c8c6177d17a64407c51b3c410c8c3c5962b855ba7cfef7868ea34cc132dab4258bf4dd6b45e7220cd718317c0c411199df2fb6716d8e870c582e299072021ed25769a60e3774f40a4f240fe027b405d6958241118d69224e408c29c6c538b4268125ee56e818f70f20dfec82fdc6879fa3e699ed77537ddefe769101dc6e9228cac80c7607bcf50e +generate_ring_signature d6ebf139a45ef1fa4b4be6a9def628430e9a0ece08b67e60646b44d7581f62fd 009fd2354de45de4f50f4171609d01f3af1da8c4a966e6613656ab7ba547bb4d 2 6f791430dc6089fe5726dcba4999c2f277ed2515275152c3615756c85ca7fce3 fb5ed1804e5b50fd5e0faea33284e7b91d9d881a69067cc49560ca97e1828d7b 689799e5ac8fae88a1fa82a03c0dec56a2ffa69f983d929bfcda6ea30e735f00 0 9a283b6603e26b20dbe9b1ccfb48e6bf5f601e73d61f57afd6b1bc43c9fb990d1737527183a77bf6011395e6aa9f6a15ea5a1d3fe58530f20436664f4ff46304c462be3389c4f8ae83c0f6cc1f614437547811a29abcc49f9ce5a6132b781e04d2c2fd70e4d109d76e235bd755759ec32d2b858bbad926f7d389dd64ed971b0d +generate_ring_signature 0ec44a65dc63613b9be298c6039f1c13f58071e1b8f642259fad92b82e70ea6b 9c1b7841db55bf2d432d77363bf8f7871946d1028ac185176bd270b9b1c8245a 22 0ac06d71a291bc9cb8a65166f6e267aa94f67345780fcc3a88990a1fa5ddbbae f4dc2655b78a75a5c02d1da6fadc0e7df8d10024cd2acdfa75d6b926d9df26f2 b898a4bc2437e9c7aca7ae42b40b9f55801251be6a22e06b35cfdb9b519fbb07 5fad8c5d05bbf6e210b426f1c85cdf65c610189659bc1dee66cb48e155b4848e 06c86b3de6e5b17a6b18bcc3bea96bba1f0e53011abdfc8d983e7128686aa565 1981523626d0ebc509c4975cfe7855f5935518d53bfbd8020103875bb04c54cf 71c3b087b4ac47bbf525fbe96f827dbb8ff8cf477ec15e188df1f7468f12319d 76ab284bb2b33394e49a7b9b6ab4eb0fa9175f8cc0549099afef7a425cfdee73 035ae37614df557e2879632c43dcb2a6e731f45ed71d4c24813a2fd0b33e27fe 4619e99967c91eddc5bbb3326d8bafb2d91a69e99120dd426dfdbf0fece87b2f 6c25581aef5948e25e70cacf2143b8aa5d09c4f0f71d6aa72b8f97acf504c9a1 035708993aa26e4a03188068a9053b2c4daaf5e7fb6fb5b63e4c5b3d5fced851 7046c37e9f70f71033fd835f432553e867df9ce1f42bf67e883fd1eaaf6fcd91 fc9c1fa387d94e42b000d5196cd36b4d9ae84e1a4cf2de91dd15a8e9c655995c 80c9ac968a6a22f994705609c7f829f80e9c56786ea24c1048814c9bd8ae39a8 4d7eee539bdc72685a3e4239f78c67756fe3972e1b88ec61f5ce7de6e90cbca2 9f080a14a10352a412dc2067d03db1e23a55fc00e1c90ebe2e3edf4c9067f8ea f124e82150067aef668390263f418cf8bd5ce9a01fb2907e6847231178f4cedc d28e3033f536023ea168cc178fd5c9a9e3ed795f8598f7cfbb973122a860e43c b501e956550a6e563a89978557633f9d61ede3fdcb4f5f73b10fd98961369c19 a7c9d688441935ef112dd091d6f934bd055fdc508e39f78035da02849b5e374e 5585b13645eb85ee005065fdebdd45914a3afbefcfa4d5aac0b2807c21bfe0d5 ef411cbe80bc6bdf3cf2c9ac140669cccc0c9355fbd42d32c545a67b3bc96a02 0 acb7f8d139d3f0606e0bc120333cfa89b0525e00cfc0817e65a40cb476d3ab022594bc42a7ddd5aca68f91402b3b8103d452554703bfb40fbd1a5bd901a36e01fcfec231b79083ae656e0eed52934f0e16f078e32b222e745df0c29cf5dfd205146c72d81ef244508d263053f8e9d5d78d9fabc095c970ec8901764f4b44590ce37a3d763ac1dbad2adc2b03f7cf2e71366648e9f33a83bc83145fb0ce145c0d5deff855c81d8d6db6fafa8d8d0dfd41a4cc90eccc66c0a78be5f2f7ced8fe0f1bc84892f4a08a764e2b240fcadec69dcded216d15ac6e006436d7474b0b1a007ff1f544c52886bf6592c3457753a60c7767a983876579ab60e02460a6c217062efe9cfa3cb22e648c370c7182b779241316033b7421bb25377af4e81465d80a7b4a5d151428bd4a6c4284df63d3f5faad79c310e26f31ddc8ac02c998eb7a086dd6e13ccda11d5d90961ac81859be8143ffd28224ce332460d134f1d702cf0c4d64014eecdf7a881522ec826decc97ac32eddb4edc8ce0f57b3e0c1d6a14d0f414bc7fc28ed4a2aacfab900d476242eaa0015fd95f7a89d2ee1e562f91f6b0776eac2f17711261f9a820b200cadd522b11e4bc19a31e443a884a4edece40e0c658c9be300378b1108fa6ca8c178e65eae8c4e8881486d802705cb10f81bac01d60e58499a2e62435c653a41a1892addc2638756977196050ca196c64fe7980d36408819b9c71fbc83b1e3b753b155e2c4376738567da7f31fb75f26fdccb503edc4bd88f3701b6cf4e0503bffc578c5d112c6151bcc51da22e186380470900b95685260a428d08978cadf34b8c0c6499bae140b5a9bc5ab29dfd59ded9eae0cd3f1e02ae5a54143af1e23e12d8786febc69ae01730b1771947b0f4f280c5b0025363a6f88bbe38a2a13dab3ac92ff1b95002a81fe1c60a4272fd4ab22bbcb033dfd63cda389f41f75d968502efe105fd20d80676061835331ac556ab47bd6071188ac78b4cbd545c11f4d6a9ddb4df28382677e5da30301bca9fb95ee68a70b1acee24fef8fa2855b1ed26b80cdeb860087cbec760dba1dc911b161ac04d9074059bdfd8a0e2739c22032b92d6912f1617387027d3b677df2ad8ae660ae0c0dfacbe6bfdef0ee9fc15b73f3b462652b9a28a46c9ebd1df5c5e8d386a43b59003c808fa828c76f556d5fca6a30e06f518194f87edeeb7cd6a8b91d437121da04a7147e686741cfe5dc9f49711d3227b12395bafce9def7b98319888ca1b85d04ccf772ac7af47434d132f15d201b95508a57cf531a69643d03edcc115444c3031ec3d5a5482d1b2943e433a5d3213287ddc363f64203c920049e6b98c433bd0b0f818535d7f72d565c5e474f4450087f490db02366339963859d937f85782502bc24604022f7a3380e707644219bf7216d42f85f9d10db65d44ad53d37bc430a336f5546c949e67aaf8c55d74d165f7bb3096123702872f96dd5935d8e147709f3b9934a9f54a2562d151eb58f603f0cc86afbc69358175a38ea8ca3a38f8706317bf73b80204c0e010eeaac2f076259ef551b1bbe8a6dce11aff53072aa2e08a25348b750163413ee37eb5653b53b255c8ab6f9c024d8b07dbcbf31e835740fd5ee986edc0638378198aab5eb3096571ffd9bb5c38422fad73eb96767ef980a47f0b27e1caab297ba2df2e4901f6e509f8cc583c74394b6e15fde83816e2e013baa1cca3e88572af1e1a2d627bc0046ba83614ed490bd3133ec82458445fa0d366928a1fe6246745361f2090e329ac938e171108ed3816e9eeb3d2a247fa80e539911235a92d83c2cf52409dde29bf433e6471439470db6a1dbe2513ad9db0b0d8d5db3c70c26351fff2399d927a5124dc9d6eb818dbc773bfcf7bc94b370044d185865a3db9b23b42ac3b85dbc26b70260f6eb677571fcc7cc0e7def9c3107d223a558aad17d12b6a38b8b2d2fafa1751606a0524b0e5e4b78324298c2d100 +generate_ring_signature 93493d23fb44416ee09be43865923d0e1dc1066d56f5a3d0de81813af3ba0dbd 7748c0a5f3f87b8261d37a2fcf576f3641db82845d8c9baab1255a025e947fa2 27 2d160aedc903d73ca9290d7a6ab88c0e9f34d8d1eb85ff0c2123e1e619aab827 7bb969822d0b461e0f71f8582559be4532c9f9ba4b98a3bd8037f3ae2cc99086 3973974ed9fab1a8bfa2bd46370a22e6aa9ee366333379802af5647a360dd8c1 d6b7ed18d47a17ddb488bbf95b3af8435f2beecd767e1cef3bc7fc0a4ef7c4a2 0b30df77534bf83ade55d67c5525d900a8a7a4e45d22af5d3fa8036ab3ec3a28 7fbc57d8de03940bc6ee8cf3f5598cf04672d58cc53793c1f62e0f193a2cf264 300807e7fa48d0b41448f7307d2e53d080ca6da2dbe0b49856acbfb5ed7e126b b8caad285713bf9beda3f580194fd57152f67aec0e70a93c28928f5f486f59c6 a07af8e32900154e837d3b7b74d5eed2eea6b5fa431e09f4927256459a381021 73aa4e3f354b1059b14d1cd48f52502231c181cd06d3e377e93ff7d7e4493348 ce6d6cd79f36aa44b40bd05e6a087cde2fda0d82d4cdaa6e2b0cd36b0b3803a2 038030ecee860ada3ba07323cfef9534ea0a90d2b5d30f2af5cbadc1bef72e60 dea728c4b55cd4db70c5c69438fd75ea5180675a5b9d66c02fe1a7199e9bdb69 f27326d480de4e3b79274bd526dd79d24f11ebd046b9a8c5b376c44061d23a9f 136ba04808b1ddb0227d549f18e8322002c8f9e75600a3abd5c73559ce0260ea 601eed6733db13d4cb81bc73faf4f9f5af74ce56405f4bca0a048333bbc439e9 3c0c6f776ae4ee29c1c691d0b57309ed56b96a31a945079f41d3ea89e80f32d0 7249c2ae5af899b9283262f07f522602c6d1bf3d88ed92e0c1b9996d76f0447c 9518aee525652a3dcfa5a37d3844e7b2bc051db5335ea438673b94b01a04f8c9 2843e804e929b6da93b04026f44ee744eb364f20610f686d5a73fbc43b92663d 6b5281b6cd170d9cc7ba7bb56af507aa3dc21e816f0acd1659a908ea9a416366 ffe9b0f145fbc6ea4dce6273b27e9287654cfaf82accf33885fae7b152fca9ce d1bb3f05ab3be0fdee933d8492e1c5cc24e7488e44c4258dec75b4b650a9892d 8203602357f52070b4bcfc3c5240704ed87ecb93a0b4812512e3db7d9d6ed061 1568a18b7fc569e1cef7a211eabd5da6fd118cff94cd726d1b4d988598a51117 0080b6bfcc6e68ab3bd176987ec4f0ebfa08e2d5bd6901cbf24586bed9ecb4b6 6b608f086d9d4c67f3f1daf684659a389c5c9140c7b6e5ca71ab5b107cefdd79 dd1d64ade0adf36ab84cb537861c99b79a6d012ae1f994be411baa76db298b03 0 8b6d8b001f70d1cdea070a0526f5faee4f3e91bf70d8cd5a44625021631d1b0473e9eb251480a1f3abe25269431098399233c79ac1a0c7d6308a1202aa48d70a9ca77e496fe4ae604295d158a2ef4d1acbf51c991e1fefa33502c0434aac6d0a3545e701d7baa15c1d9bbfaf4881ec9edf22ec7a99d61f55dae9f8f44565e8044610f3791e03249cdcc28f52f23473dfe7bf651c53de381a64ba8c17592de408794478970be2bb5fa5e77f2aa3e2080e6bec490e5d2ba96d4e24c207adc4b30cbc7d9c6956c132dcf6123fffff763b9c7487ed53732b028b5b771650ba857e0f1a739d7343ab7ef4fb55a530450fd11d04eaa9ebd533815fa4a8e8210ad4800641337172b7f34c356ce0c7ef0fea248d2f5b92ecbad795faf3f6e30e4eba270cf0bf21e571523fa346935f0966ac8c1cf8b870ae7dffd6f8cbde8cf4fd126a07c91c38d7de3aea2f5246b6c6e2d45baeb3dfbaf6caaab1271c57b5c0097eeb0e6523d34601abf5bad92957419365dfa53dd33c1694f91a255ee5a6451fd3470b3498d34eacc0132518f74ade75deadb89c2c0e92004ce7349bdf0ef4077ea90ac40cf369d214d75adac60b0c7b03b18174e9ad037268d32bcb3f68eaa3f85e0770630cdfae50efb715a95739c01735c1ef461fa66f41f337450db30abcd75105d3cc27692f04d44d9b02b387e55e61ed7a936221c0ca532310dbf9dac51b2f006cf2249aa834c5e2d59b264e077dadb62367851b8e9cf8f67e1905f01ad98501f03220a4fbc719d29e963b2f4bb0c08441c68b30f6aba6eb8a946bbfedbf3c05471adb66caac242c0bc6763e09cc61458d50af2a71edf7a86d055f72f5b870029aad9f7320ff3124119ebfd9cc8f5c1cb3d9d7a77b8903dc03b4e68c5dd9e20ffef22824cac4e54d3cd025d472686bb3314373266f54ce21ba4ad4ffcf3fc50c86434358faf8671fe1039260497fb9d2b83b5519d6bcd235b9e44305c472f1028b6fcfc369349d2bef66664e6f66d5ddb5786cd1f436c5d2307300815481c603c63a95c24ea4ac6909ee1276459466758e52a74a0d6dbe374047e2ef0ec88c025e18e97152dfa259dc82b43525584a37f0f9984d31c287c9c4194ef1adbadb07f8e9e5525f40dc1fc2eb66c982b851c5c18f1673d9f50b4fa6b3178802ca62030aeb6a71a17dfa87d2ca5d0fd3994a404ad861d0e7f7c275c4d24fb555da49017decb2e1e7245c31ca84fb836b44b345c0a31ddd21773db5e423bac0fa438807820b849c9ba5eb3ea9d3cc7cbe945e22739bff621b23fbeec57cccc1486760043d92b3c66b3f97988de4477128b596af6115533d319bde580786202a0d5a2b0151cb97530bc5a5482818f88938825065e19d5c17a3d644f8f97d035c6618410b7a4ff378477a10c53a9a7b1268a5f8387a038bd4a7e9f51fc14daaf7ef8c830cec7e033717b9f8fe567754813ab4d253db95dd3b756d63491c5d6ecb4d203a0b24e629b047f0ecd9085457ddafba19230f8957005c2c35c8aec41145cd812b01887e37ff98d3191246d9918ffd8b6e1912e285d5650d0b2a38a3bda948502a0358fb25098336ac96d055dc0322ee7ca39f7544148523242148d9542f7c7dd90b3ea9a70098548621c098d7e055bc4199066bb0ff476358612388c9406d964200a9c1879892bb6c4196d9c8f51c66bdb0f465cb4c4dfbe3db874694104fe0c0089c568dde8721f75516688093312523400955ebc2d3f51d1485035555b131890f831edcf7fceaa7c628ce50bec8d3d83b9109b64398b633f6bdf1a9f20b552003b9c0adcd5860bab47e8961d5c4ae05d02819c8a761bdbe761e57bfadfe61a509ccbba8e53ab443f30c9d0b3d67f68281abae4e7e51bf11263f80b1c80d9eeb06642ef595a042a788b106ce3e3b7d3f8c88bb05e746434ce1dbd525c5a65a6006998c597fadafa011815319d24942132c3bdcc700d4ab3d6af8d249a567f6bd0062e5a8af71825f21b31cc2e343c8fbd927f212b9769cbdd202fe8de4e6eeb705c8fded12288c91aedc16249ff6737a32cc97b3190659649601f12e6044d56f02a01687e4a9df3afbbc3ea3f6c154a4d847a14aad1c856f8d119b38ae408c0a0028a4103a17afd564556db21fe908591b7dd6af25760089fc249da1e4e2cefd00989137f09498c2ee3a5b56638b7796511367a6f114f3893b843bcff886e4ad030975073c6a76e3e38f0753ed2960b5f7f85ece867f584df5d164cd86150b8805e3667802880c08f55681c311fcad9fd2fea62d2193590354e0aa451312fe4708acfad1a9a8e492cf3a03418f7613220f662fd56d4889936eaf6e0e2e3c401f0d88812640f02576d42f00235c72bf7a5fa6fc051e58b75d5bd07e98ed501d210598567534918f09ee5a554df4958b7a0979054905c0b378f61709977f5b2bbc08 +generate_ring_signature 47a17eef9aa4f45e349474251fa7db40f4dc3b2d9cb74a0f63628730e4f087fa 67206377b4229f14b901ee725025ad9067500f80708603d343cde543f6220070 16 b9d6ae2e4275913b39ded0e04f23f415e21d0755e6f5f15398ce24db187b80be 7443760d12012330c27c0d958be3f5bf3c543ea087b2e710f1df3aea40a3597d d58c7950dfa2cd1e5d5958b03665844c4ec07d3266238af73c026b2df9c9d749 22c2ac91231c9618673ee8d8cd01a3fbfc915f6da971019e5ed1c04cb848eaf6 bf376c083d6e0298d8e0bee38fc8a296ff9db39661ff0acac51a7cae47a528ba 4d84063c54fc35ef611c69679d6bf8252aff307262372e127ceb6ce28a4eb57a 191d335866139d9a9d70172dcb623d9d0d589bcfaf29d639db9408105350a6e7 16d1388ac89e6e7be13d79c597bab902ae51c727f4003e0e32d6a9944155f5eb 7161b56af7340827dceb9215c1ee38f21479d7deb8ca9aad4cadad12dd190762 eadf42743e1b0f76badbde7f1b5600c599eff2855e4af3ba1e832b56c745121f 0113294d12228749802c3502457a95df6875abd7dd63631232e319cda4ea7176 517b3628d5b1f6a781dc2a65084e515d45f745a55acf671b478d2553006ae2fe d1a16b1897c1379411ea2bad7ff86ac19c519141174182de83c372da21e04676 9c6e206bf2d21ec5f36fdc489e51f9748d748a8064e5ec0ed21e7210b6075d71 fa2fe7158dfba5f1083ff8db88ca7510fa17a08da7da486f3194297ed4ed0afd d467bdfb269e9f5e8c72cf6c27b5c7eb4c2beccacd7c0fa37d22cdbe2d15807b 02584ea85f70c3ef4912ee658341e6b6dba3f2b9e3cef23d99ced95aa50d680b 8 9b503abf4e563414238704dc7027c02e116c6880f42513268ea30673efbadb07021964f0f109e9d3d50b4c9ec2033e0b3bfec3bb6e7d4c5bd943105087755507556460633cc8f4b4876f2d1b7a37ce5da9787e09b842f2f2f461846840439a0fbd7491c068b496fd622d9bb3e4d64161d944c60322f3db0ddecb6b459707260000155b55012d89eb61c830a798e591bdfd7ff132302023bd89d77896a4ccf30017d244663479f9bcf7b38261fd8bd2888560997efe5bf6a5ae665b9dc803590b35c3e36d2b24f398ff7c75607088095d86fe956d26ce9aee10749c734c83b40abf88a1ab1ece77643c87851229645cad07b04a029c01b977a203ea9841bb1c077ba9a319937d126de3828e1fd3a43d33f7f925a4ee2487f81dfe4bb6d7e2a5092fb00260d1b6d95a26596edff3da72011a923132b3b8e7cb743947750e1a29061dd223b2432bb5dc6a91a3efb5a887907c201d2402f5479267a56bb356bbf50b8906c1550f06534c2ded19c9991b12dde68594d8787085b37c51e70728ac300754c61a0e658d279a102a6b9ae398d8804be338c518e9da6a9a641b998aefcb074213a1e45a946c4a9cb136d27e02c72be54be5468da5f522e73f52b43266f20e6845b6b2a2594f5239abf145b596b68455d8430a90785c940ee91b06dcee0a071c2870d3a2df188daf811a19ae31342efa8f1d5b7ffb8f72e056d5dfbe52430e966f24b3a0c910af2aad898be8e0b5f6afdc829a1fc3dbadc0ceeea9efefcd012924525f78bd6b5e484257a13fd6c7db0a1356374dadf98a21438c140a16b8043212a928fa682499556f8b39497f31244ee070f128bcd0016cd8eb35d97bc10d9d117d43edf0748ca7c1f7d7c6cbfb43fa47b216aa166a5b2e8c6ab4da27df0190e0faff082ec92633eca71f1f53b61d4dec4828502841588eb1bd3d31c5560b563297de39119549e7d71a5656e24c80ebdd2380a7d435fe4e55b136345065001de98a6d10ca53244f09be66917bd3c9d89f682faef90652981274fb4912c309474f72d315ac5ac95591ed34d4c78c7ffb9c74de7e299d3c9515bb5bf2ce7a0832168d20fc064ce000f715560de40a22c3ecf058be09fd7d56d5a0dfe7df43076b9f5161d34119f4d3300b8e9a670d810681eae268b8c88f2f70b2d4d428b2074b60718054e8e943ee4db73faf8b5794175140242b890298ddc98e5ba9032405e1a2b6be0449f24468121c5c152a44bc3ab199bacf1eac52487db43ee73bed0aa81e8a795062d13cc1f27ae64ee03c8b863a77c53bf392b796690b2bdca1540442c85917d0dab2184777c22e29ce4e53eb0df6c9838f6d3ee0af00993a8f45074d719fa5e4b8971b942d584033b5d67af1357be6a835ae3f06bc26455ba1b60e6b891d71de1f5336c9b92747585de5c9dd005113cd54687d19eb71c1b5eb360b +generate_ring_signature 9a7086a8ef73356a7a113ae91f791ea57a32bf63cb15766556218bcb2f7582fe 9eb46385239b056e240bc6a1180c51a025b0837da355c5d60055da138d05cf09 75 d716b1fb66fc9eb0d801d13e48a4795600b8afd004cb31bd7bb69ac7bf26a5b8 facaa9a563716b9d22e3e8204e8c38ab90e4329812d9bf33dcf49322105ef8bb 092504da28d4089cf7fe33cbd6cdcfa5ebf9ece75d42805975564bdcccf34497 893aac484591284d041d6cab92ad3a0e187834520d90b3a6686276070ac380a7 4e8670484c0779ba9975ac8bf55da8ae29d278a0334b23e670fac6eff5bc133a 7fe32c5fc50564dd44faae596d56dcb817232c1e50385f248e6dabcf382d0d20 5560a7525b10a96fb989ffffaf9c2a20291d0d28be117be81cf7292344c26a89 7abc90f8cf53e7b31349994334ab3388d209b38b0a1747d656b064255933b80d 4b5931de92f69f1272ace927b49149cc942276296ae99a42e52d7d83de3fd414 a2e67069563571d1eb1f16694869da1a9582511ea81b005eecaf1f63adcd779d 23c1f904a58e6ca0d91c4caa3dbd7cd5baae653299b339f9859ce870200db57c 19d779d89ba045aa643e717f548b247156a41d35e7be773d5775eb452587d44d 68e999d5a013b3d945434a46adacd5a2ef18ced42ee0259d949aaea9f06479d4 f8c85c1538d967eb627ec666563cfa8203b978a8f88a236f4fbe179fa791c596 19909e7839625dbff33ff26ed186110acd7b34179b0e55fafc84a71b7a3f7e31 53312455ea259a3056ef247f4b25e63a807fd2fb463b0ffe1417cff46ff4dfdc 3380930deba9c016b036d71ca525f349ddbf582ecc80ed127da3272f6aeea4ac dbde3d341c05dd02ad333c64a9bf35866b1f44da659a07135875cc65b4d65439 06577af36ac3f0ac371d8a2167f637c741b9d18a79afedafed8e943a081733d7 944ef7b3bab2fd90c5a46437b068c23d4a5074ccf0d0a6fcb960ed9763c0b880 01cd86208d37c5512d16d459a4581904d13eb862fbf9e34c24e8a1c3233da0eb 8a10901b4799674e91e6c496deca1f904b720dca6c3a81364bc2ff03a7e57897 339b3dac7330ec98d76e59a6e414629a1cd465d14402c6404c9655036cb5a010 c0f2a7cacf16277a4c84b115d21db048e8180a15b013af3f295739cb0e5e8c2b 9bb9566b6ebb7e992a2e6138c810873127f3406860cec5d3e867f676f23cbb73 3a31153daf08deaee78252f49b658c875d195343bae2a187c16465b4615b64a8 5047c33140837bc18466fc3d1e178179768860faeb7ff166f65450d53c7dd290 bc66bc18c1d6601746fdbf34d4f9c4e7213079d15eb054cf570edbb66ad70591 fdfdd237e667d70a530fc4f387af0473f99a1f2988dc480ac1606df7798798d3 d982e4a92446e08a2e9dd91b155e580f3d181bde1d5f5e69a6cf5e82d35607c5 f8b566a67779c1ece46c432d20b280c5cb8da1184f7eb242c33759434d7fcbc1 6fcc2b37559dd4cfc22abb8b5fa07eedca9d56ade5372f2e4a038ad1d0b92c0b 15ba3fe0679958f07c6deb5369d356b48b668ec67d4832ad33ff37b0abcc629c bc70e3eae472a511ab3e547f91aefd53e40dccb0b030fe7f0f5c382f41337be6 e74bbca25c9180dbf84ee1feacbb9e6d0514cb6acadfc7fe9269d8f1441c4004 0a681694b9181b8b0eee8388c9714f2920c63b46ddc955643d9ec4781c2a820b 377e5e05a7d1fda80259beb3d2d4067cf955e08089a74a45b460799745a52532 198981c0b8d166af3bff21e762bd85cfaa43cd7241d7fa611905b4fcc67d6236 1c533cc6c0bb0f4eeb97e36be210351f39b1a4ab10b7a339e92aa187a6e08679 955803e9b32dbf08ea6a31dcb5bfa460976d058cd5d35fa2cdbd446dd112b3b6 b6eff72cacb508187b555d67f22abb6e73ef2528404ddbf17411ac4510c44fa6 f55361c4f5dda43876eca6af215d10fab43d1fa4f029a370a08996e08fe5610c 38d3a3e8c7d263cf018d96a9c81737c34aea0b2d3092b63d79ca96a2289046e7 5a6424e37427e45b539c65f46272da6b578868ba83a76e6a0ac240c3004ccba0 80d9e5a24fa55306544acb007c88c87a5c65b6f3f814d3138b56d914a7c1f046 7635087c2fbf829094a693322f3f3ade9c719ffb418e5265c0186f4604a294f9 00ce84cfb403560546340864755a5e399e5b2c061645bb7c12a7c99b6098ae82 dcf0053ad01d6cb871a35dd4f255956e50f487ed81b0135862982eb4843df3e1 ae49f8be1790b697b4e8dadcfdcb5786ae07e2623798d494c18f22181ee1d4f2 36cf774f577b9ed47efc0b0b8d38dffc78e6372ff1c3326e336b71600789f487 e30e26abc6a8adc3d0e8a226fee82efdb0462b698b98a6a1878c640cb1cbed61 11ecb444c49b4a7571625fd56f8e30c9008cdb5ca45acbb8d8b716480ca9bd6a b89f7406af985457210d4e406755e995cc07515a414c0c6f751c4269ecf03eaf 7456e8c3d729f835db509c26a5b20a9349d73cd5a59c2f09978df89650f7db88 378ad7b8655c6acb0309dee66ac1cbf99454869528c5cd45b17cae0386db60c8 86cd4f6a7bdd988a848508a368343b0fadc1193111fa561687db3cac67e2696e b62cc61b3a0e5cc7b99bf1107caf5d810d95ddd4102ed701d862426639bc3735 01b43550d9efc0413fededc10d91ae556a36c29151bf36e94c391f162ca325ca 75c92f49af4ba741ad911d40d2c4e021927009b71602601d9432468069caaed0 4952e76de4f8e470060e655a18c697523d7ae0563ed61dc70a54cc3830e3c988 562ef593d5dd96f709bb82c1b59ae43ea34b365a05026a7344010abd6c419fbd 4699941b91092f0cf560e7f9f35db0295f952f11c5821635676538495f663201 ea0d5276b2de554255c56fc0589e3795fcc9f39234b354ad8cecc554b7b8f6bd 685df7e6f427618f22fd206f70ae5b44d71f408de837502005777fdd92bbb4bf f364ed496716cd88da9cd2b9b404f620868e8195de8d2f367f2c4c80e708a16a c7c368adbe6409674f1a2fc603ae4fdc1a7cb31ccead9b6e1443a6bd90fb35be 248ec8d63f6c5cf526819521d866ab1bbdb6cfa84b0e87dd8a7ad7d1a47a841a 4dc9ca992f062b7a011c372b3e99f87d54de6883627d42cc97bc7a576a551d1b 3dcfa728ad76ab77e634add3524207937374f3eeee11a566b5babddedb647fd7 77fb0e227ad84997ef3a5f33c800b7ad6033aeb0f3eca8d688abc8008dba62c8 b8990b5dfe159a6db927724d9572270071593aadbed7d4e9b9acc4a1458afb70 72886ce644da16d21a4eab8b7d00dd65f639a40a5dea3579ad7923cede155007 6ce176ac239a4afd1d9f61f7cea9286ee6b5a6c3f5d8c76c02a3e6c59600deaf bb67aec3e0b94a73aea72380edf585f9c47232f471b81ba1725beb05d6352cdd bd4034fd4c3d280c619ab29786e48bcf7bcc8e839941cac09d57eee9a67f0cf1 2b9967f5aca1eb4e0601d393b1989438c1934a0b0dbdf515637c2fc7c9709a02 17 49f32c1a4ea7f629cbd25ce611e62f3b1f15afb097b741be253699e7af38b208f4ceecdcaf0859bc947bfd19bca13eb0c4a79edbe179dadfe60ce6925365ac041554d97ca72204756d8094425d7fcc47ecb56159b9ba6ac3013f56c9ad7ff50e28abb30e9fb96eef331d2c30cf01a2e01228743fd427c161e4c406c952979d03683d5a04f98be9270e2d72a7e7508d47393d59cc245a4e4375836f5ebb50220fde69ddc39b6620e6fb367220226a779f9d48c43c2341aea8f494335ea6fdee0228b59bac066663f519221be8243748e672d8869ed6c4854bb55c285d984889028b4f3922d68ea29a4a78d70c7cf6fc5e0870595d6a1b637a0a0282574146bf0ef2262fa30bfbd262496b950705c1f45a0721ca59cc99b759650aa806edf7750e5936ebd37c845bd38b24de7e811148c4056b75a073afa81a5b300ec67430940cc3d689e46669af53d9005e5ded7d4540e98d52ac6f8b94d8ca8b748de3b8bd06132f3b781124bdfbf03f3a15723c07b834c5e8e2e9781b9b130f4a284e850b073ed20dd04344d534a3f034cbb5071e827412c0dcf88af33319352fc128f0ee037bfc2b3b010b1f8b1aa340d9716b8ba9a819c0eb220776ef2ef67ea60567e008717d735093ed42396a08f82d55681f35968bd891c3a02460a46e6a090260500bdc01337b050806ee9565f9cfcb1321da58c19fded8de7dbfac35c15f7287b90ee07e538d31607c23bd31a9c53972dcbc824deab45342d41b5c3fc28dfe731f0dd161b6440fd69ab03d6a7dcf8dc47ffea48cf0624f8160a1c817d0b4d2054a087275210884126315d5b537490a67f851da27834a40d0289593c5cccfff3fdb0510721ae833298b06b1be4b23d77dc510255d7cd6284d5d67e585d0071ee3090ebcad8c7deb1ff30e3a04c4f0455f559351277b977c2d6d926a0c7b9c55bcbc067d4664557df0bb5f48e30873f29005b53a1ba5e36ce7541aad33712e92642505b5454547505d08a28b3f944721f4db925328997e45d25757e6b1afc18454270e71aebdbc5497ea2ca6e11da434c39954828fbcb0cfebc32662af2b37faa74a02c4e313a0ea1b35a94e77ed6fe0123a39516d7d7317937c1b1e6f2cc3895d6c0f93a983f7c0ba910d408aeaf7d4e9c0b775d57cc2a81af7cc1aec102fc786580b7a75238b2bd01a3f164ac617e58b9673280131b43240e850ace213c2c08ed6094bc7fd379452ba684f1e2ed6184aef38751c53d70f3b11180e1452a91ac24b0591c2a27746d6c020d3d156b9dc1fc5633bad202cdb67fcf20ac65ec6061c470c537b092b97f25e9617f54b31357f009265eae4bfd2a8dd2d8586b0517470d301456358a1b1ef9ac19879b6c781ab2ed5931760b1da7c6045cbfa8ac216a4130fef6f678681b13a8b38a5c34aafc4bd70fcfe996d29d00b7754c4b4a014abab0e037536370b390b09838efea5d673f1ae4dd5dfc832fdcf51303259ecfe7a6a0dbbebdac8e4e06ff5cfaebd35934c4ea095c6a7d9301c99a4db0f335daecfba0bd12de94aff1a34e342d3f473d9d5fbe2334182fb83df80f61a679b06b1d1060978b857bcbeb5840c8986f2c5b9acea2ce3f2a3dd7ee5c2488d3e521f7a7f5006281b3440a6552f990db9c07409b5813d1b15169b771d50a6e68077f3eddd6f08454a80f3321a3e77a56d091ec57547e95509cfbf41fd3ae364387073549162056ac4bfb296d50dc52ab4a73e32cba3f99d1bfa92fd0dba27fd3f7fa25089fc0b9f4233b85c338e10e96a0c755ad6d8f5073e19882753ddc2eff46d1eb295060661339564afe2b84312162545e634784144063d993112f8ed45f4084d24affa083c5b72117d290735121aec439f4626046066e9dc30106c8b682aedce0e2c410d552e53a83e5aead11edfc421e2778e09500bae95687fac02b68facc7c5dcde02d996fcfb0c95c49b627d1bd3493c5648135ba09ae031a8303b87ed82ae746f01eb396ad97b5c6e971e63f425581d4d41ddf58f2d5d834e7c7c6229dd7f01fa0df7cec1c568d6b1efec96bd5267a061291b1bd4b85196f77232a235bc94fefb0cc4b53a739609476371765654b03bc91086ce943cb6e41ada1200237034cbbe08982830f70395059a92f1fccc3152c3fa18573c0936f7bf927907046f71a1260ff9fe34d659ebc980e5680ee03ef8228c76beacf36013427e6e21a6eafca14101d7fe079ff665a57ee84780411543981440343c4a9860a34a30d057eb98d44a0de3f58f1ff763ceac4f192de936719ea5015e604680db535f8299939aa1a03c0866fdb1d6b276babc2589bd7c009bf0f46c96dba0e24d0e2113046fa39c55aa003f61275c78362fafc8f1f880622f1f638f03bc176e4c20892b9a6829b43d9b0d791c5b1f356a31e2a7b727d38fd61fbe7a2ec653c3ce835fa8ced27381bff604663d86e9c855285d9b35213cda849efab1fba58f162a3db7ef7f7b7e95a90803afbb23f999bb012b0b9ac0728032fd6e35c55eb23856075eeb520ad9f71d710c7de491ab9c2cb5d6a034206d60c0249715f369e75b14c019ad452aff4d478a059295984afdd6ed2dae90a055443106586a2c97736c60de180b1030ef84d90f0522d47943d6c8673425e1acba41b062c97277d69efc842e4e46690a69e1a4020f5acc288c518416192370aac4da4e984ca9fb8ebb1cf23fac7412daed53a2060272b2124f671fd583527c2c52de057718264fe3aed450e3050a62a488dc7c6301630c13e084d3f15362a4618f3f6393d888664d4865f32bb63834c71d74c9fa07bec0314d8b6f1d925094c4a7cf98ac84464bad2793009c723128e07fab983b0e5d2b3bad4a8e28b23de778e32d5e3fff8c813097ecfe8d1ee777c10753481f0d2053e080463c670ea38112dd3494f8a6d9c01d6bcc10a20a6665a99ebcc3100559a0fd1e43e29b7b4a922dcf8ed35ceaa7e04f3cf144e90db0d758cc5107600c86b289b70b54f87dca3cd81437f5e9f45d06a332cbb107d8ec01f3d1b3b74801eaffa35f18bb3fcd209f55d5f255ca4275c39deec9dc29dfd7a9831884acb000506b821849582959ab0279ae00513476088d532960b778e627a8a79c7d0dd60ba676bafea5c6e6260b2f38953d847f560b4661c0cb91f8b5bd113c297d35800e0a6ffcf2ceb318a25b93d7acc2057d5edfc955e5856fd5555683b5c181f9290b4da2ac34e6fca822dcf8e406b769cb85615f02c82baacebfb7c24bf868e5dc0fc8f8f9c5f371b2060b7a1707aba634581626fe4566874e6a5dbb5b34f85ac300f3ea63612aab3df71c36cabcecde86dc36d241d84e102871a4060018bb825e0bcd5ab727c7adb2c2e5042a41a7b5e7fc32033405534fcce627f67d9a61853000a09dcc2a6f7ca3b885ccde29fd51160ae7e778f42581a62d806c71ffea308c03d475b6e100379fa04a22f1887c94c71856a9eb2f1f0cb0529d10bf3a25afdf0b7c9baa29a2c1a4290e48a947fe52eae74755df1db952b83b3f0e0eeda7d7cc081e58a96cfdb229ff1067364ab778527299238252c2f5b6b54ce52b404a58b00d3f116e0a92e439730e43afb362be35141f8ebe7e836104938d345ac9bdeea204e0721b64f3ee540b6b48acd683a79fef79d4e1419dc82e58a64b4882afcccf01b16a446559d396cd81becc7561d45db06dba2b2b1664eea21de556ba5a51680b09a89d80c6d52c9102633385707b48794e962821ef884462782c972e964d5a062b1550a9d385743ba10ce6c1c01e222334a61bd6a6eb03df16bd3941e61fe601632191d08465fd08baaf22f7b0f9741c2043c805f58a1481db63931d5b12ae0838c8911d1a3fad7d6721b7bc02ffb0af8f5a163bafc414f7acc54d145e4f430a58abdb5b50a7d944a0f154e50869438526d10c987577134689ac8d2a98b90c01a9d705db5056137206bf5d2854631769970e979efd3d23154f7be752ec3cec009d4a6284e4852830837f908fcd21fe7b8f2d7b9675841d14e91e35e98320bd0339c36f4423cdfc798d01950e5ccb547dc5b45ee27f578e4d22f808ffb37039092b188f0fd24eea22ef91cb20a57d8ef85db92591929af96e47641ee8c478140b148f56e466b5ad3ace2e200a8d900c77bca53936944de83f1e99e4eab716440ff391d234ce1f0505750548df78274166b79a7430d0d3d79a589e9f9f71bcd507c75a0b61bcae847371a9d38a21e129eef8ce0ca16bd069e142e88cbfe829ab080cc2a7d2e8fdc80d3fe0a9026183c2e1c87c4a47dbdd82a92be831b4117fda028701ef5c1103fdba5ef685de1c36750bb7324b12e1816457b329027bdfb1ca0525dbd465789a2fc8213f01b30c3533e03449afb949158683f9f864517584b905ae46072de09885fd53a7c56f03b596988014d0797724e3404216daa4bdc8970715a79457ff653aeb5f8eada9a45bdb12ce7077d1b8bc4f8b00a83e08198c290022b242d7b1f2325acb8cd457774ac9f54fd12233a8006171175e588af6e75d090c8f4c9d44ee19d95e418d6801841e5a74d16ceb29313e8d6413caa28ec23905c05f3022e84c1ff7c14603540f56bec6f2c21c90f5af510dfbc8c6a55045850671536c95a00fa68817b05f2828342a862b5cdf318869bd45ee4146324ba4c508603c1eb26e97e995e1377e2f6cc06ec03d430a3bb12090e5934ad653bd4c1a0150fcdf100b7459fb95e7047090e824922b2ad57a8a0539a7a2e2ce9d87f88506f972372b99f49bb3462f34e400b3b115555be7ea58c9e5c0b203c80846e2ee0c35dcf7c756aee357a62bd3f7118f36e1ad541635cd4c3746c7f11fc4ee9a9b01ba4fe13dc2997be0114fc7c69aa617bb39c6ef84a1f1839b3210e3f128de1e0f8d4a4520ce53fc5eceb402d1de6230ccb68b2de43071137aa36c592a6bfe62058bdf57169725ab6f2c925e75431cbe3d992d463e7d6d2d3f60dcd8717d9deb026556ba6d14b5cc4f73d844cbf9f8ef77536334ca7984a7bd0947bde09361870fa25a6ce41f7ab117188545b5cf311b1d88415f2f053443b6c6285a3def1df603d692eaa79c0e5389674dae2669063595257db7e3ce2598c0c9c8440553ec4305ce3d0bda6f4c05f9daf2214858b8b39d2f28df1949941b651b77e1128c0e89099440b8b0e843f0a29bacbe0118749993f1fb801f72c22280b4dcfce350c93b012f9867af2a83abe72d9e6ab2ad0e597c7b9e45d2b46f46588eda644ccab2a8020f6ac108ffd076f6c0516bcd0d550fff5da3b14aabd29f4c27335b0ab4932d00478058792e7e8da0cd843c3798a3521f8c270f0ec3bad76b20c7918622c18b0ef7f7c65665b2fc39192bdfdd372d7377019215546fd7d5499d67095c2f094909c77238e7301ea963097ee3f11fe8f4615c72db8f0fd8a550bd406a4500383b0698026ec113bef8a794dd4ffd6f08c8752850abf701adca05aac2a34e7daaa001eb1bf39d35d136bcc60c8e6b836234b79a86c72fac01b1b4013b3c6d81358c01c95fcb809430c91c9bfffa3c61e2bb89c06a80a9055303e59316191a6751d00f99465e18f23680454247d470366084811d7e1f464ca01912bc94f2cc624e0909346e8948f995d9e59f7d30dc5b6e40f3ae2c60668d5a79c91b1cd66b97d9800b438ca0e5ce3ba16da904fe02cfce462ceb9e8aab7a90e7bdc045204e6e84d60c6c17b4a3b647b6e446f19c8fb0c6e24a74e03ea8deb9e57999a532fddc9b8a044f0097570277084dd23fe2ab782a19dd0934a4b0f7378af215e345c7da9cd90a6d17b682725c1f50ebe09f2674368f725d6bdb7612f5a154f4c1fc2c97545a03e001eaf937778ed931dcdfd549732c5698a8b92e0fcd2fef8e328f73a9634c00c11ba0239ca60a4ba2cd69b37607845ec81ada0d0701a5ec53055ce3cf36c40650bb26f85eae2548b791cee8e606a99827ba4cba107de05c84afdd24b522fc0251a40917fa846e8de5341f3fb24714329b21263577bbcdce2ebbfd8125fca002e56d4485c57caf8748ae6462840f01bc159f011d18c752475836e6376a548307771afc8c206fc57833b8bbc5888d8cbc484525575afb66e70ab5021323743309ef0b032c1e16b039ead8d87b411f24a4e0be3fa47c21f610840736a7c7c32f071e062cb729d351b92311c2cd074ecc7179c374a0015b5ee84b493e897cff9d0a53b69db8049c710282db431a3bb00ff4fc04e30d4d745248812cdd4de9baaf07af2384d96b8c48e3254c65e646a2b9ae57476ba0c7eb75730a471ca6e997eb0d289e832fc38f939fe53162f7f39f22ae71c6b26a13baa1baf00f1519220ba004bfe9c21488408f71b1e9b05c9d69ecda5152a6400815b12d8b4db63b90375a0ba7bce7dd7ee54ae6f80d7e501ab6d6ba32b61e4062d0f3cd73b22b8fe9734e02403e509f00431f8cad1a39e140abc67236fa1ee226b62c54c8b729e0ac434b03f2d52417546006503061a950364141174ef086fa164bed502dbd1e11692bc60ae209d78244595bb90950056f0ed002ed9b7910f5ee350de05443ba6beab04e087706dfeb36744085f5202772d91dc13704390e887f7cd416048ff1151342090d6b665088d1c17286cdb3fc21430f00c06a1852b201c9e8f892f76a5c2a68740a57cd673d402e34bff1f2b6ba4332230175a4ebd0a497b022a14736d5d6d73203c9bcdcaf79cd226fb84c88295176715e7f717ae8fb623f9921eea1a30620070ba4db3b822878b6105d31818f8188993d31716893327e1ae9159b3efad6b0f702 +generate_ring_signature 9d3b5964da0a0dafb5a05244d09c44cc052535bf41794549aec9b85b7a238998 b7d7b25d39766c953ee51d4057e3746b82c88731470657ffce7f90bba173c870 1 a0dd3438cf05d1a81fcb179ce77f0a61b8a47525d2faf17808662ae3d2127d4a 9046bd3b0ee4f3b9f6874301485110cc7a5af1806eb93acef62718598a837d08 0 e47a594a30afb2de7cf2dc87ccdbcd957092e9a5b5b98f73b987349149aa6a0efcda77cc3bb88651c4bd6fae17a7e444d00029db1d93734ed31d159dabea8c09 +generate_ring_signature 36c2cbcbb47f9040cb04a7e8e1bd128dd73240ae49d6a91e793c624f9a1b5680 faec603891f4e9da1cdd3e6d205a4173aa202867a1eb5959cbc9e93f353f36ed 2 2d266206059c398811fc3ec5e99c37dc51af758c47f094bcc5354884fcf0e83b b76f2f51b0e270cebb200499466d003705c19d8589e62d6f2abce941455aad68 5b96fa1f454618fba2f17fffe6a26238269fbc0cc08b9361aa03c451d1fed50f 0 5e167afa304f84ff0d7940faebde8dace2a4d125d9c3ce4ef3c6cd98e8ea090999e8891bc94cba5b6e57ad4638be74413a0f4b6edfc93f392a17b38ae1b9750184f233618bd9f0105c19f44f67f8ae9e0f2284745935266a0a13f0be535efd09b2ba718e4fb68e05db1b9f1080411f3cbaf0e70cd0e3ec29242fba231c91f804 +generate_ring_signature 8ec53a5456f968a3c524f9096eaefd8df6bac7b84fa3a94d0bea97696520c66c e55faa7e53c815159484d92d413bcda25408c57907fb97debcc43b82bb72454c 81 4e6ec9a062da749b4c7ce55c1771c5be74038853f1ec913878dc89b65a98ff82 76f3b513e21d14585ad5489f7e7614a99d0f565ba1d9c74d7d3ac6f4de6cd0be ba18df4320a46e06f5092c242c34b1e5780ed295992b8988d8b58fb4f4af8fb6 038270478eba4e0041656da105b78146c1934c9e8c43e54e37e4103dd9b2d84a 1d88989753b94a019df5b0d526a04355b5caca57eb89dafc2ddfd166cc2d9b16 a18d580f24cbc8814533279e50c1b76c62a3f84c8149a5f28985330342a5510c 8c97df0e0ed3cd10d4546368038ac04a493fdb4f776b71f2883da82cfca39ba0 d51124bf2d485048464f1292f68ac4f2f2d381ee4d776f442df04470341e5dc4 76e1c7489de49f7c029256219e12049f8868c0326dcd9fe7030d4cac30567dfa 0481ffdc653eb171f9f868759e310680c494d060876e40ff8259129ea672e213 c086abc24ec1e5d6c8f1a88fc25aa1b8ded0665a092d57678eeefc7a8fed692e 63068e1ba561aa0b5b7e3338583da9dfae07af9198024cc19636f2ab864ca457 2523398a630cd53e849a151ace8438fddefc758d65a0983556ebe4849cec0e69 05715bfef2fb4e3d04fcd6caf880db87df20232d9e6c22f3e536a051833eb97f 79afae0b5d5f0340259f26c0ae49f2d7b2efcf451f721386bcbd3db0cc516cc2 32dc102cb33a1dffc0551aa87f896bfa4ca364d7e473855053ddcedad08f6192 28772c16ef4767cc67a4802d334e62b3cc366320ddcac5db6ed6da4a3a518e48 ae62ab17972d879f26be0dc8a4e0e72cfabbeb48a1f6c862a566744c73f0d5b3 95757dc182b24d6e76f770585632e8e2293ecb0b2e068b1415c5aa6b8844bbf4 a9a01f9794d39e2135c734007c792c0170211b2f31d22ec855de6c2c9bb099ce 809e8daa0bdbf2845adfbff43ed329bfad793cb1d50964b76b0d2dde834cafba ded1d37ef497ee99ab7f47ba850d3d1592469939b25fa0dcccfeffeb6e487256 5f0c974156a91fda39cf74c75e8418f5dd735a30c3e1be7fccc6e66ebaf51bb3 df40904f087cdb5c2d375fd9e9cc1b8fccbaddd8f8b366bfd6c4c73d548c89ca 86786f17d9de29de6a6f3a96c1f15efd1b795d97f316b2945ea60497416c4d22 571c315699e3f94b0b49c31c9603c952c1cb7b4f501ebc975e7cb9aa76d22486 6b37e86d97644021c4aa8a7570dc5c75697d8a5f48c3d1dc40c5d3bc534ab466 37bbbb806e9bb6515f1b506b554a53590b078f3fcdcce8accb1503d83b4fef11 ad7c90bfb7c44aa341d1e52e1b2ca429e29ba4db54dfa33b061cf6ea1eb00f73 a6562d8af16e8877bc51ff84af564dc25a03f7d0d7535bd2c5bbd130b3e762fc 15baabaae493637cc08130ebdcc165d6250f863613d137e986c3318eb1e1d53d 30bdc4dc44932cda6b13dd13848dbde684a136dc36ddf053c021a789875fa5e7 486d213c4c340c96fab9ceeeb238077f728c3ace8b01862fceda8d0552b285d0 31b5688c7137a1f2caa7356b494db41e82e22dd6a8fbbc1d6f7f2c95bede6e04 df368afc6547d8757f35c2f1e925b2401a976e3dd656790c29df95da30aa7d41 5b457edbef079804a73b9b2c07ddf6795cba1dc7b2b378efd4e090206556c0e5 1de5856c9fbcc5b9320f75715d93718fc5ef2e131c202c109ec452576ad8c0af 57efee62fcef10bf49fa000f0859bbb6bd87601ddb2fb92c8d5b7155ac088d37 a66b2987ed02312dd641783d5e0667e1962271ff175d92a9cabd9f8ee5d7efe6 1d295ca90c2ca4e776946f589090f8b29ed75cfd4912b24335d1d3af6904a165 5836d1b2feb67fed61162fc0547a2989cff2b8223a54e304731ddb1777a53ce1 cf6c69da62ae9770b7cb9258bb6e8b14ecfc4d48157742c2795dbbc757bd9730 15d960a1be78b06fef10a1d748f4b7102e16e7b9b515b85e4ed56366bbf4d347 6f4084468f6082c7a3a09ba66ece708020d294c17718c8a15ecd4c84cea2e269 db08f8b2fd5a814a77a829c3d81da8aba108bb0a30d0ec79095f6272fabb29e9 bc4658cb9532f7dd50cbbe9cc3b69c42c684f1baed27c68f7bc61a3d0ac6fbfc 70118d671fc682d4ba0975f6db97a1e946ae1523a1602e980be873b3bdf7e262 100e6a645828abdf759c25a993f3176bfd861ec8b14fee0bf2257c6942f3cfe8 dd4a958e1f2f175763bc424c37138f7f6ace5505b4730c1474f13e29e9fee09e 981f550230c2ecc818356c5978e09c7bdaba2bfa50a18cb65861c757fd2a92b9 c4591c778f2af35031f0b8c10a9ff2076ebf4743dfcc683b135af85c68692734 ae21b69401e1dd790b5d0ab2a9f302f9596d399233c527fb03a3c04c174e9deb 1a479edea2a50f19902e1a6f7222d5dca50220170d3031d932aabbb2a2c60a50 ae222e075a61554b2931b48ffcced2deeb724b0931e57a7fa42c83dffea81be4 e09cffe50c23b6b501416c062abb82c4350142d512fa7718a1a7b4bb0c9c89b2 140813e40064d016f31c79e98732ff2488d8f5203755206ae3ff8b43ae29c2b8 755adafd8cbfe400bc7f0d6c7e9a6745f805094fa56411511cf71a842dcf5e95 d2f4bd013ff2a5614a0f46d8f8291a727974291ef07d6304cf43a3cdfc8020cb 77b077c9ab0974d0f7feda41526b5f3c49aa93128c71c20a32210320e1f64b76 5658127bad4fe2d7f6dd4dbc60a73717d42208a526b6d0cc42a0cfc72dc5de47 d990e1f4737f9389eb33c7ffa8b5ace778993c3e7843fd8eff9e5716d7dc3823 258ea018c125c4f407fff137b02e0b3f5746d2ea37e5b3f0ca6adcafd4d9fc36 15df78d82effc9eacf8420cc9e11aacac8d5e909cc54acc9c5bd7c4c871451d4 dcae2deb75447b6ea9fe455cb32c80b6d9e756547da0645f13d1089069238913 fe5566a38dbd13b5a0a18c0e6b39c5774a98c588d2fb2fbf062a6a313dca8e15 852091726bb4ee8baa253c406c0faf71cfc6214aaaede4a378465c6b8bac7d21 927934f87ed1e0f415b63e60145baa00c5974030a1c5eb8f24b7188f10fea32c c7db3aecfd44d679199341764a02c3be4a87466677263b8b7d05acdb694c124e 3afb101244955d7befd723e91c81a286ac7f651be08f9895d2273e2d0c49a300 2500f40884d6d748b93f852b6ee47039fec6db5d3377d28569d0fe76455ea246 e1b1e24c5a4eb749ae2e2cab6fcf3b86634b426c3743aa9ccb25f50d99ead1b0 c344cab976b25c1785abeca1946186a1b4d5c1ff5bbab59d8dfb6ad5db01a8af fe2baccb1e96d61f5be322ff3e39d5b72d5cc799a758de1313d4793b5a723fc6 83779c08a1567d1ead921064d6637784b8b85a2d18bb3facbb48e530cd5830fe 5560502b0c56672bcea621eb22343c543696ff0f25b230409984d89b083e399e f78636ef78c66c68d74165c4635fae714db6ddd9ad3b7ad51c7c45f125189b37 f344bdedb278b1a78067d1effad38e71921c10c7ee69b0f597e4a481b4a9b014 164d7bf3bfec8c94798fe21c02efb54b58665b26d7796d0ffa3679b5cfa02b31 a7e4fc8d4ec066b75bbe98d9cbcc648ea13bf6b32646dcb58e5590edec327232 03220e9496c7b992044f1d2f3dd65b6d0e8dbd4bf2f5fa7036508d9fcb28a147 6610c3995d2a266a69d4205027ac22196f9817d66da97a547a2d9a41ae582d22 e95249c7c9018c9c5e46e59b620e8e412eab445e832cc46cc99b4c9178100504 68 fb9e3b21b18825fe552b55c8ae3e5f0f6f532724dd3df9606470327875f3250f5291d72160354ac92566794736330d61a2fb53dc2836ef05ccffa11fbfa11a0c29cf06602914637d6703a422bf2cc012267eaf10f9c0f1e5a2f29200c5ffc1031d2ea4acd4e94d6085a370a6291b2d6c03e85ec7b53b37f33dddf5bdee99fe008442fb0bf43c8510c46135a14e7692c986875187c18970822168c4636d4f4b0f7b27ad184bfc24d0a439c3914d4c4f1654b0d785fead82fe14dd65faf3e7550de49dbfb75ab8f61e7deaaee7aecfd8987e3331036b64d846f6c181547a68ff09498e8f3072b3dcc9cdc75e0dab3d53e0ec4ff9b9b8cbcc8f13b955dac8cceb082f235a784fa6f15912094941b823f6420667c83d663518558957908f617dee0e785b718f95cccb7a4e5a57cb9f6f93e1790b122a39cefd67d5e35455f62bb5031a44232614a697ee369bf5a2b17a287d7b2c112399b98f536b59aa0c1aa2ec0ed6f3e6cf419d072485fe69bebcd5987cc8240b40ef0d4b0c289ac5c27aa291018553cb7d3b29b866e1210fe18888fd30f9a750532f7c5fa040ad69d3f2327f09497b6670dd35e3ce93001795a469e97fed68e7382791c9f38be295aca11c5b06b6169e068b723faab33e667d09aed5a11ddd397b5ff36a7630bf7a3c4e6d4509773876dd25089c008c2f7050c063541bda43a85f9a3c0f6dbe057f28917cfc07b8727f8e56dde493df3d34a701f3d85bd480a57bd0f764bd7d3e9351e20e900b12b66263897e006da183828805d9a32ef7458651bdad8e30f0896398d5d36d0a88257c70b4921e21a9d87611c2a4bdad9980ca7c07f44d7cfb605e85d4d8540944a8890690ba252fb02466ad3d78aa12d69ab0c0da23b04f5bd1caa3d91e5c0529de3830893598202484452cfde5416fef5741780b43fbd1a0dce7abe3540a0a8ae162cc27d3dadc7d24b4a2eddd9946b360cf9b50de985789479206d5129308f8dbe1c001fd74d6489feb42f632aa4bf10c84c1b403c32f1f7595839bdca209a611945f3813b3a46f951f6fceb9026118a47677e8fd6d4b7979cc014ea3e40abefb3822d551cb89570772fa1e508191c0a7e43018b61d5c2e0fe30ab028d40689d43b92c48a35790d39f63581a59319708ff42dff56751ca44b928dc870af0a71e982212222c3df945172c35b3986608e78fd187a774fb661dcfb18923c67091872163646b8fc9f7020f981b840781946d0b1c4f900e5fbf965ce0f1c5df8009935ccca54fb8e56bfff385e4b54d75bd64e4658ef54fa00a2de908d4a315606f308c5d94340fa52139cfbb6dfb0c459e050bd6869a7b51efd0fe2ba27f9e801464d0eab476d705c01819d0e61cc2af785bf5529c2275f6e163fb261c650250d5119e7418f44032be271a5ca6174454040427b6562bac5518d0004bc9a493c0c286f5445e0612188606243acb2d8220bc77dab3e8475813c9490d7e7c98b3208775b850b39580dfd45981a761b12408afff711907df44c2286bd18fa0a64d6081393638431da4888aadb3547285c544bd54b27a9d9b5f5136e28476fc789a30bffefcbd9d67e9963e47f8f711a9af038e992699dc63fa1b3a895b6eaa84478036b6908e55abc08f1bc2afe6bcf6f4b11e68d0ee5eac4c8017897f9226e27a60ead22365f569e8bd15fb85985ee8e51e0e8bb6dd70a4c5f0b87484ac37e4e6b0bb80b579ce4df91ffc56c3479b9151159e92f56316918499e1a950ce596539c0e3ecd955894e288a9c23e14ba741dad99ccf57d5bd03e5b6411bc64a1c447560380a11752171e4763e2fc44cc4bb5218b87deac9ff497e72ae67bdedd2b66cc04e7fe6e67ea0b3e71f0e390a5fa5b7839bcfbd0c7e31c34be6ab0da7dd230b4051281f7dc128e6e9b17cba45071181d4998e330cd72c79f240f7689a896ee750516e419538ca50ed94680f3a13ecea37c21e8cdaa4fec621163935c2218035a0abb8be68930c603159fd635f62592c22c842742eb2d845a2a0f00a2da754f2d05babc0534b9b2c908de5138142cfddb036796d4a7c057ef56de4200294f886f09cbeff39b1a0f2b98c59d33b9709095aa7b26245c8d7b28fce123677db92f0c04db68a76cd0477edffff397b7e8ad1b7a91008ed41d8c1ad2a5f32d32ead9800ad8327c39a72f33cbe342a0b610e6b5f66a0f083ecee31b2d40b9951a9333910f0a7f5a91a5ace137adacdfe969fd95fa101acb192ed6f1873b2764c39c85570679075806bcf626ddf4c9966e103379ac6d5ce8d8b1b00d97b6d4494fe917c706a8aa2265fd1c60e9302a903a1e7b198e1e879d7e828da04ca9b914cc8751980e2e60ecd022a942ae3b0db4832c3530259c3e4c9aece72992070e5c925d6f730235591fe2f287622d881e3d8d80684a40b4045c3cedfa4773e22c39d1ea602c020b0f42a08162e91ae14fc0d66217c9178b008925ad08cb4aa956ce8de60ad50e954c1e7fdac604e1783c138a6ad51f295b8d85ae91c1f5c4b35028e1a372da00f84137eea8de263dcbca6935810e7d69e714f778db75701bc03f99246f24d009dc56f481cf8ae2c2ef03c8143acb6fdc8b3e70348b5efc205ab8e407b76cd30294ab8cdab4dc1f4cab806c9763827f29dc4fb41f04a2416690720e0fdcf6320151b53ad2cc7b2a18aaa5e40647b4c1dea3cd9634747e006f8d3c7def6645e100e34347b44b1a5383f014faa710d4f7a361e8868b76939858df4d51b2ce16230439332446cf298d178a590ffc82018468da7d853b65ed5d1bf835e0cb7e429b035fd3065dec39648af3973f551c40638a61268f4ad4fae0303a26ebe12d554406afa92575ac82e732965c1352e3ba0ddd7e5512f8fffe614a3014cd095f2c5405b9689ba74d1811762645ddb3fe09b3d8bcc5ce45cc63b945adc45c2e6a6e8e0a2dfb265ab77590c4636f2975b5c9eedef807c7dd50915caa2896931ff9e43d000136cf77bb49e4214490a19ba0b883e93ca056f108f3b0c7b3f83c9b0291dd05aed430c3fbcfeac1fb2a0356759d1fd18e08f2eba1f9527d5d8ba2235f648b0ebb636b067b469fb9474bd9a180fbe1d132fee3563cb10771faaa4ae8eaa76f0ba555d2f723903bd0390fb518e724060b6877840a523932fc3349e739dfba7805e26d5aaacac5b0bcf57ab48971bcaedbd3553c474e809bde1adf9b2e24d254000f87d3bbf4c15c31b886a5e94694e3f3b737670e7dacdad2a257cf3ce7a1a609ff0a1316ab8e5942b2acfbf93bfa7853c5396e301d126927a16e283eaf35ab04fef2a1a9fee695a3d503d9c27e677b2282768a7a9717ff1fdada9fd2399a41060d93e02b05c28a19f8223a2bc4e9c24732252b79154656191b2baf8abc61980920c7cc5e425339f24d3ee8440208b0d9018289cf7816996ddf40dbd17b15d3093832f025b9e2a828a5f8e68ab0090e896d8b8d132da4972fa06bb77d6f146202e41d09f2dfb81bceeb916a5adee209f2e7486d7b53c9f07bba4273166cd1af061d8ed64260353e65ddf8c04e47968d2deb6ac37113eba1066d5ba933c3b5e50c253e5cdcbfa765c33b079fb5a21abb809c14d4f8ec3154e1066e2ecc6a56f10c18f2c71af5f566239552628c37ebc1b472e1350fa9609ef7ae1f57de662251024913a9de56b950c37909c31b58595634cf69a377243620a8b3e7f566ad6e500a9c8bf63b1b1a935bc7762b2e56826bd8e14c2f4376fff3ca49a9542dfd6e6b0e6e15ec91fa4d1b2ed4c282e65e333aac5446408ceacceb14bfded640f760720c37851b04d6618da04172b0c001e2f21f16d9c94d56494ffbdce8881223e5c302a14febd128995b8dd1d3c367d82bd4c348bd0817ada2d50e92b3107d688bca08ec1c9edd4e6a64506ea264b7378b3a87251bf39aa53342fba1d680dd5bff270d5d04535e058a3378598f2f6c23c571da0ca0686821ef9d3627a08d561cc82b078612bd5a0abebb9213f319f2cd0584bd1780a14643e90b22f2cc2e3e41b0a30040ac76fad246d6a21db47d97f5dbacd06610bb088f2db94256c129a38f6b960145185dd690b8493eeb55f859d2232ca1fbaf02e939b78151cfe75b59f99af701d8090c4f96743f581de28b9bb821cea6708573663111f34365203ba7bb08b2094c08d93f664d2c735778f384d51a87787f17ed27ea8bf6fa4d26408d03050705c7444ab7f1ecd2b5358aa70770c53f1dd90089b0aa442e0e6cc01045b12c2b07397211ec466f29a556dcb75623a2982c57d5925ebd9a69f4dde7b4842f26d30db278f6c4bf53699a75aaae3663e6ba25ab2c5bdb3179018311d128818ffac3078a394e13e5328a3c6e517adbfbbfff80bc4b9455dd86f6ff59cc5713f0f3bc042c6d4b02a0263e296b2877c1808a7ee2635f762c07019c490618dbdeef741105ae62e6fb6ece1b60518eb1d66ed80bbc085ac0f354a74705b3fa325dec07b907d6d4caded00e9aae8aca23f722fc6070120711f9e20b97ea5aa8d2d2f119b9054a710b6432a940f208ea1cdb44690246cef0516d811ad544afbbc4e0b067160d2f814b5e6ee49492142c6fce17e855f256982f919cc492b50fe57349c156db0baac808c51f0c9b54be9978eae208506fdf04f01233e8af1074f7becae18a620c7a8065d9b9648c28186247c0371df92c8c5a5e5f6b19d80016864bfd61efb608af98f7a7eae861aa6d7212f2586dffc8443f4103a9f0d8ad2f8dcda496a5690275b6759e25f8b41d5f5c5112007860cbe40f5608a507aa86ed8a1078224e34041c974ca360398fadb5d4b0581e1af384e6fd86c1a68815044a86ea731c2564078c17e1a257270d1c84157d1025bfc807a022e6b54ce9bead496ddced6debf00177708c1e6fcb221442c417c27bf8e7cb3ffdbd48e0ae023695498bed036808091df16463fdf882bf8377ad04b4141de04dcdd242c932b6a0932116385a9275062fb5835a8c1e0d85d5da4772b7c73a43c6b540f099c0cfecfaa08d12c521b0043c51f707e8873c6701eb49b613601dd8dbc5b3ce3a9c5423747d840b2fcd190d4aaad085d3e99eaa28d37e1597b8e3e0414dddcc5da32a98839e68cc572745047655b5938b6993adf0f0b1d5f7c870e56b375a2be5185e7ed119e9e0c1e197033970730639e383b0cf5a799faeef906d4d29866eb453e5102b8eada101671f00da6d7a4b36633220c311546e8952c71834ee7def771346f2f09bad8141cd4c02e40da9d005566d44a514dc8cebc4f70d9b410b6cc13830d2b2c3558f1dacec0256c1e492aa3a72026a08012658f29ee26e0c4605b4b768283b373336066f3f01062ab4cd91a941f84abf7f20680261b22893b0ffd524afaa9abf35cdc66a880a83c4b60c404a7e398ac61899b9210df8a4606d0dbdd3619cda46af803a03500428cdff39b4af0435cfeef4c21246b7e017810255b36d19bdaf09a500165dd702cf05d9a51e916a88f148206cccfc4a57337fc7ef3f3542381fdc6299a56d4a02a21dc849cbfa65c7dd2f79ae66f85bed57ea1baee35f5e3821faa5c6b6837a0afc686b2e3345dbe76a055c8adc1a40612fdb090759f0666cf9dd707405e08005fe933768e0eeec889f8d74596463cadee4f4be1ea919cad166953f9ccb8ca90ae4ae642f224e7b93a7221b44324cd31268c5e48aba977aad1149f543edfb490edeef8d06d1629d30fc4608019d29d71508422d0ca83e49aaff40428707e1670e4a4fac31834ebbd978f4f243ee7097b064ec400a486e5c897a0855980764e806923857cc350a97feec97b9108821d4b12e9f60f6e16e433b89c4bc59f33479039ae9390e27d395c014fb68d603acd915a0ddff2dc9a2d3e7021ce08d363efc031a9c64597b1d076fb2c74cecd61d1e8861e11f8e72897ab0ba27676ae6ae3b042e9a83eea905b02b5cdc10e76645c8ce41cc99893351d707eda9f782d50d12087886d5ca78408ac81785a60f2bdc2e6079ce07ca4c1d921b6bee6fa1913b430511672278a08ee394d6f39eb13281a2b8fe6ecc6118b4fd3617827c911363130990fef13c790f6f82f3f0607e9abffa36918c7ac64dc4982788aff25ac85fea029e4c8f6c7600ccc74fd4da2b2840774327604582f5f80c0767a0caf6cd02660e710891991359298f6ea73f4cb2787788eca1c7297e6dc85d94acc0f53098db0630cbda99d1085eb66b0d846bb3e5d92a273c5bdc53f34957cb95df6962815508fd6a8927774bb9e423c3e6fc1994f921bc77d48b4cdef75c4cfd2c5bb2be2d0615c8917b0df429844f796b2c56b05e4c19be253cea6ed8e30495dcb65c78410f94b1e102e05945643e3c20a729e040f35388aa0c18dade36068436a9268e980def3dee9143b1616c035b591f762cb208239fcaae1165feb808bd9ae739458409e882a944f826ee5f18469a21357ccaebd0a935d25c954ae969890edce7dad40eb3a716a957a339944d8f5e99ebc3ad4eafd992e1759071f3c0307fb33a595400c08099b22cfc8f4133cb18d3f4743ea56bb989cf1b1d603970895ffd54817f0b04cb00b6589a6475a35d42316c9bceba6d64f76d242ec8951e900cf86141d70bca9d1558b29144724f97117571a7528a291322a2ac29ab4a4927631510b0c2045be7e45cf0feecbd36dc6c95c78f2259e0629dddc62decdc5a1078c9a34ffb0d73280fc992cc3b0593e8316118e3ba44975a082840fb7aa5d5528c372ea5430e7a391f6ca74fecda3dfd6f7d1755f66c1a5b91cb39b5f18f7d842cc02aabe206cc75ce799e3aa5cf603b5c226c4e139c84512221c35609e6b97a0e0a54792806f4b37740f15b3e185dcfc89a4a1849c272a3507f0044440dfbeaa4a46921d50822f69a3a6feb27c6f9f1dadefec8f967d92fe0031152b220199822320072ad0ce836b6d24ccef0af6db6a7a6b1a1f4fa2d1350207a50d84db55688a4e4f0b50ae35035298490fe503f3ca00b04feed7f3bf008f4e49eea7078cb81fd9c4e6201dfb2713f2f57913d36fa6f2a95fa2ac072432383135c62ae31d97e3ff0352407504cab906bb799179b5af1809f82904b5531a02c5b5f7a02cfcc1a07ad9509015d29949c67d4588999ce67c403aeb48b289157486e83632571a737bcd9abe80298d8e140de8ffd0268d8cd2725cdf2ee78d854869b67758609a59e544e35790f036a3b1ad729a0372bdf1d6d001073f9cc702bc9d009e4fe66f9b61389ce920b6d3ca0bcf2569b98f0171bcaa81f6114e9600a5c59e808c5b8ace5c750fa610a56fd72c8304607a2a9fc664cc1a63a49f26196222286258661edc07af5ec5c04 +generate_ring_signature 713c4c8803fc00e35bf91007f00baba57486e0d70d332c9608d09b6682d5a554 794244933962c44feef2118a18c784f069ef776f495f075dcc22870eef06fe25 4 d6ed7494656d90bc14042ae12e0dbbd7b9f890d2347417b21830785a32fb3b25 dacf20780d08fb684de5ac429259951b81deaf781a6e31dbcda6ad07f10ff0d2 d0e455ae02f0be142f67090ae09f49ef67d65c5ca67a2edd0e612bff1b04245f 61b716ef95d86ea4d50645d4ecd717cce494c2d4d42aa30fd13a45e3370a7f34 da2cc4f0ebc2d7f6020c9dfe8ede0c1b216075c6c2eda1a9e10969a69a35d10a 1 e89a53c9d17738531e3806ae60d38f25fc9dac1857e3141b0b353d81b358490a61497fa3216e66589607eff192818d6fb27616ffc69f91b4b57b46d37564e3056ed16f995b3b5c019a18251dbf4cbca1937189fe29d0d8e0d9ba9648aa364101a54933b16ee9e9060a63e5665950318e79e03802463ae96ab95d112eb522c808b198a832f91eaf8967af31de0e3b04c5057ad3e33ab68f7bc80358971602290718825ce1dd00a6d71f6557bab44e983ae84728f2c817cb269e486c061043de08f31a676e5a20d53dd661568f75442cf4c9ad103467a3004f2938155efb883b03e9e5d96539468dfd90bd0364179f101f338f49d2455eb7c10830fa65d28f5007 +generate_ring_signature c24d45d5956e2ff05c5900e0e3cc833784a44af630d7aad0beaa57fd879825eb 359095816f878d15ab2b0a2186ffbf5d95c777c21ca2cb72d2266d083a4a5809 6 bb3e5f6ae5df3c4a43310d86dad1560abc1f6626a09d5a76eddfb78d652654d5 7a4ac8d3528abde1baf73df38ad03a857739fa446862d1e28c4ac3c83edfd15a ecc674b53bb166ac2be28a7d51e66edfc9f95a324277a2d9d1b908e0f65c5e9c 5841a26c6b246992664b8d8b58769db51a4f7a194fadf2c7a15046a0e2770023 75ee9e843ab7975fbbdd99bb16392452a10f7e7b38144f29b9d706bfa22cfd65 3de3c211b808c4235fba01b016862f8305f0deaab1fb58823f1be27f151acbc8 9b8031370c48fb1cbb36f400453a00108841cfc20f4ef9d9d206f33159cef60c 4 404f56e864763a6217e54b5b8e915a84026f83c596be8c6d03cc4f9790c54d02e98f44e7e069679157101c0cd7f4898e7497ed566f95b9d9373a5ce3e0535d031e4d733c5cac601da4b6ce79d092eacddc7814dd10e8cccd2f18f2c0f3ec2b0695019cda44e95c70808803953e8fc9373817a492f4837d6fa45fcd5d1bc2af016ed3f2b39659ea8b3a5d948b01b506b618befb251e6f2b664892629b235aa60d6dc9bb820018ec47a97b5766ccc4276bba11aa66cb1b77d014916557d43d1507cd61e671d7034943b5b8dba7543645cf8dc6df3268625c312b70d42303d137019be8d84be1bc63af870ce559417eddcfe146854bf2d771508d2399534629100a374e727d62787b81d2599ec925d7abe9f4eb06ba7a517b196c2a3f98828164002f3f86645fa22d125dd014e5df254a7185cdc687a5f786b75b6e03f945ddeb00e010f8d9ab5cc12c1a1e90dfb6c93c76e799e10f340cc907a053bfc30465020905ad33ca6b9680d5ea7592808b8a47f7d0554347cd0cfb4a2dd10d9916853202 +generate_ring_signature 9b9e3fcd3f946f6741e6186234eccbf58f97379d2138b6ff985ede15f22f113d c3b4076a7f669ba7d594c52e660da73a565bde7416c9bb99e06e9259d325724c 31 c468ab3f7c3268f7a1839d256c30bed690689a39994e4afe3512c765f2b21ae9 9e8f235c70243e95b84ed1e454c1c86b10446b699f059f66c46e5a1b37dd396e 5742fde4cbfc7422341b8a5449fdd125d30e41357237e469bf0fe77246577442 5402efe6137d07e5b71f0a1192ff212ea8959e080d32b012f937fefd0edbf337 2331347eb9271235c789b6d2be8c6dc18713e878968d77f72b9d644b16f26dc6 0bd583c1d0d8b4b2f8b19609c8d928eb4f4196a491ca45fb1f7d27e9b1a92c5f e1841b87e3d529490cd95098d08b589f51f0c84321b656ba6e0820c41bff4574 aa142732d8b972888a704821a22d62e92eb09b620f0de227981a7d9612333591 d80b7da6a8b938599b5dbba5941781b1217e4ae5a90efd8fae4a65c49c30ca3d b6d8d385a96ab10a4cb6a82df537be9ed042c8f6c42ae261baa487f7e927a384 131a2aeaa5db3afb87093ce9ece283ff1c3c8f7ae83f016612a4d3c866035a54 23cd7cbfd909e99e696f371875e9d7d6fe1f99a0a091dec26dc79fbcec6c29fc e496229d63f8c8b61f17f330dfc30417adc1306275b55adebd8b2a2863f72c8d da2db6040913049257b6ced576f35e4bfa431f25ae137c6cdfb562118bde066f b658b88b06cf34f1897ed99a26a20b0eef67ab280913d42a688b3d862cba3d09 da1f11e2eccd81c0de8498f22659197dbb66bb0512188ec900d44e8036bed70b 9fbf6c6e3f494eede2ca88646a1f3c3e3c40cbc0216227e0c474f5ed7355275d 5246031ef62f9bb1399d8c444a9e3ef99b0da76ce5cd7ecc882dbe9847d1d62e 8e4c0645b710436a74749e8d5531ed8719df52a68293713e61fbc45d5fe8a68f 18a5567a6e61cf2d3bdd2fb0a58a39783afabe754ef59dbd81e370e35954f1f3 a4c53ef53fd1c7dc628b6cac4bf35a5b84ce3703c07040924d2db4ca523cdf73 7ade9695fadb65c56bdbeda04307b304a04b9d5876a1ebdc9dfe35f7484a3ea8 82c7f5919c40ac93fe9c30b9b50b6353dac39748634b5afb52eda0aca5c00c68 12ba3162a1d7ea4b0c110e4b2f7b6f83a3874ebc983698258e9bdb187efd2ec6 62f6e20381447fe7c19968f5eeaa00c04df07ad01f96cdbfed367b6d34fe7b33 f27a9baac0ee08596f753298a41c704066556ceec1afe5a3c300e339a709225e 6b15357d01194d299f5dac3ac8dd4ad6cd02588038c3d9a8fc4cf322cca7be66 bcda402e1596fcea31ed893a65251f5fd60cc2b3571c5fcb1c8418bb6ff390cb f04d671aa35a499ff64ac633e18ced492f00946d4e3bda70d6274350ad1c313e 6b11299411b8c35cf07ee188537faaec524cb4ab00b28055554673450183d288 cc0b067ef56c580d768f01f0efc8bf7293e408d0369d5c3f0666a2ee4c70c553 28c2450bf0e73521266c017a04fff88bd10933d316572e91a497ffe3e9a48f0f 15 ca75b6d3a8d6eeda543bbf14ba9b71c7c0193f3d7b615aff09fba7fc4c21e30a1bdb20ff5348185c7d153af260a7e9ab1fa61f44078c0a0d02a28e58e6b91309779a1eaa221a031182c59af732ec9409a760b525ff4677829a80fb761eae8d0ef70e0aa96c6329814b8ed3c42ae6c027406bd0bf4ef1a3ab5ab52fc1d98695000292597d4f4d4dc054a0ca200c03f38fc4163d1ca9b442e707411c12907d9f0effb4ce25fbfb2253fe45a575d9a2ee41e3427a84dce1c32a50cde3d2a853ff0071f0314b2916526c034e23452b64123f11199b771ee2b1af0e486c083a801f0096a0dc342c13f29c1a53af8b4d732f18e1c4adfe04c83c3694023b0a0949ef0b35ca14f33d67090c0c01d516110f26151ee2fd405335ccfd8dfb8561507dc30027c3af61d6ca935f241305b40034ad8720db6c1b38fd10eaf34165e12fab2c090717094149c49aa7e28be60c99b5f7d9a66a09a91d0098c081ff825a28c270048db1c81ace94678cb22e908bc69451b77aeedeb2f9890571049fdd39d9ad280eb63751f0b4963666afb016c990707252900715688790c642026fca2f086b6e05d354d275945a32db0451303766c2d7c3cacfafcc37a5ca057af8c1a12e92730473e4c42cd654a9c8f606cfd80d9199301b8440644db32a411f9c9ace3b55e1084b65af44e1ae299f808d0c21453e99491b439bf5759b10723ff74d22ec9680063ce4e984a7b2f630ca95303dfff9729ae09113af350c36ad2aa53e3ad5641908972949bddbf204e3138c42dff2a4fc32d16b54a0831fc5241c89be25d8efda0c069884d2f1fe5f5690e65e111a713e4ae6340f4d7387c3975bf7f09318f6b10cb1b77ab274697410c3b4ea5ced839a0c642cd89e0d0a9da6bb1a958a93d5d70951363f4555cc34e2645279ba3e20352a0d87ef386279649ea44dd2cd9d758c0a8d8de625cd4b227c4bc29fb6b0b36b186f375c4ca65af35ff85c3039501a050e85c72fdbe25dd3bdc67ffbddfcb3b83c4231d6f1781dae5fe365b2062ef4330850063729202e507f2680f2a0019d06125d24bd0c728ef8b73f36858892c53101926f6c1c068a356be4d67a73131d6e4ad7c34db092a873f6adc20bec57e308012a22b6734f091ab85850990e75148eb913cb2a2d14cf843bb3b5705cc431de0ed9fbe3e1cd15a57a22a63fbd69e3e380b8c00bfe3ba89a4838123b2bff9b7701f2e8a65ab158a7d37ef52fdafe2cf69afc13ff79694fe320b6f81642f20d8108b7e54ea1da597e65539f39b505f67b053e701ae6f978e839030df1e0e4da4108163ac5425ef2ca7d15f8d65aaca655f35465561c3078b27e6b401a9841e79c054d863779b26c75f29dddd3d82d52e04a3b45123316309aa1146f91aed722a90eb0cc74cbedc90c6b98319e6c5939ff7db08b4a06b838b8ed68a896d0a9dd4705742c06317eb859e5f3f0ea5ddada506232216d1857f94c0e88b952ed47a6910430ab3d73a770c5331fbf93950d202fac53ee7be8eecd6ec3eb1ce7ca60321c0e21dca91a3f95e7626bbe8cc99bb6f32e00a5c4cb021108f0665dcddf6e51e70de5d6773c5653196e53065c0a55db5150db641795eba6f4dc6a75d9e262646803f3b42dfc878ab46ca75c5c972240a55e09a5213bd818b002125b2187379620002625592b59e844c46cbe065caea8435306cdec8fd75a06297555df76bd22bd09bf86cf07f53e7d65b63dfdde8f850e704a96e19e6eb8bbd883070f00a5f1af03e2cba2b7d4ec4b79b00c26fd1ade75cae58db490a969873fe04fd8495aa6820b34d48a59d16d0b62c6542109b5d0f028febeaaff7be514b2a11bc9295eefa200fc1eb14982cf794bc8356f140925c3ccd6d56a3df7aed7abd5990a2b448fd40f35c8f88073099f8a4bacd22a4b6842ea6c1ce5009a16b66e0ca62532b5ca0f09f8250cc4ec1c0d17cfab374af2641252df977b6266aebe6a1f8e4873ef20bb00a2115674c94d3ad83e39a7ecdfacc69b6f41f982926b83e45fcc6cc84713050a67a28576ee08599431bd7bed74a451ff793aff50ff17338405f3d8d114521806a28c8b27c64871b1baa08cea4a7386d36d3a8d27e21e9ae541a1becb55504203bbbf53a14c550d5842a7d83c304493e9d2a194b4bfd25996761b634f669a120e0155fe83c0f9c5abcd68c235cbe6d7a1142c9aac98c87fd6a0beceb5e4e39c095ea2784e03cea3ab9d0349f33f07aec785838cd41fe6d9979a3b36b02b1b1406892939af622a34a2ef570ebb7a4b2bd8289e9560592ed2fe324e844a5be1190c12b6cddafe21b50f2fbe21c31cfaac26675c5d1a1cf76baf9feec4f1f1ce0708b98c321d6e881024ff6afec0f6a3251167e91817d904fad589039dd8db14be0817986f8191143abca5dffdd49f09a4cd9e9d5455c23a47d35f84d0569b379e09580f0346aa8d8837e7aed4f0fec7cf67b80fd3f5f2e2df48125ca6b98c518101b5d8d187ab91bbbd1accea50ba1bb92de1665325dde6d7ff89165d882ccc78025dbcfbb5795d83b797899206ff8ee04821ce86cbbf53077fc1441f9184ab440925ba058387019eb286594c2a38152548e027e8c2ee9109da30c60d8b2c42a60d961e09657811c6df334d66aef12fc5cf88e273569cf44cb9406258496044e808af22dd00a1561b4ef75343dd2052735ca8d4a8c81c27447cb0be59447da28108ce08d22221e90162c875dec610c5710b40375928af94d7d59296754f52050107d0ba13af9e404b0b055a76149e9cba9d2826c24a5ea34886b015abbfed3fe603 +generate_ring_signature f31b094e55ac7802f86f73c3525a6cd8e769ee880a8c63aa2f5992c255149a75 b17df6621687c3f37b1a5ce5ac09d95546679313dff994083f079b5cb462c930 2 9085d0eae6ab0e2b4c9289ddd4b4405dd818dc5218188920df043336d491f918 5048e0efec6bc401a73f920934508f4d9b99ef5ecbb439f178b7e65c7d08f410 39467bd15083c5504b8e2a161aa69a6e54d336270f30814bae129f1a53972306 1 fdc0002c6a2df1f274f0766ff9dc5f5579aa59290948163146ee04855285f90d24e07459daa71a6b1ecf7b1be2147696655f18a23e7c70bab4b8c63368aef10d5ca545e8b2126f3c2328d8fc3027e830ca5e359ff4c5b5f83fd9f7bf219be50912d71b77d41b29ae380d3612ad1f9f2f89deb343999d029f6ebd83a5e3416705 +generate_ring_signature 2b1ed38fd7d880a817ba1a9e09166f4ebf6db200b718496e4b0e1611b699a71e 71dddaf7adc360a91390f506b386c69a1cfdd89e948d803863f742d9fb9c5453 11 7670293c88d3439719814fa939089f77b31911384f46863e903d78704c004a4d b0bf008c1c329ea891d807a1d7ef55316b480c19dd90a00233ed6027d566aad1 726dd2e15afbd42415d0bfa6886d84e1f3eb9442f71b4088b04c79747aeab11a df4a86c0db52362d3beb62ee1083fbb3c400553a99b793ffd20d4afd8cea6a14 ff9ca05329874655d5be3d882099ef375017081b3b16a0b7da8cac1ed3820988 88baad2c438cb5208973869e561254d3a38f4848039b445b9a4e8edd2522c325 7285ad0124a73272138c91e701daa44aa52cc647a73351f1f842bd7454efe5ca 0cd91d92f61536a7fe4f7c9a6dc04e2dd74dacc2f2f6a93af216dce3f69ebcec 0062e10dc722a08dbaa346d3c2070973ccfbd511dad2db35f77e8c31eb95b913 a9290ab629ce61f962650140314ba4e6e23ad47e1196460bc33f6ee92b18eeea 6cd25a8510ff4112e5f2c4d15801b7a006db3092e24e2db9cc216c7834fafcdc a5d6b5f4dcfc705c6f42f3ce3854458503a5b82742a2857903bf9a57f297e703 4 9b438c43c904171802140e18f56f857d97eb2835117aeaf602a4d1ae0c72550108880489a007c1ddf1c37aa56f23d0f80bf2b1d012f4d6fa0eded13178240503753627914817389eb02480e1bea1997ad0e0684f1a319b0e3760e91b392ea5041679da09728a98ecd59742fef00d6cdb70ea08a2a2535d35c092937445551f09ea87b4410d08ef6a2c9441c8b32e410edd3a9e2317ab32e8d3b6a2374e00420f64c01ec37ec2ecdd5aa92b48628c11dd30209092d9f9a26c4d42a4e414b34f0f0005a349f8c7b6946313ec69ba63bae3c2013442c64d27b31c4763eed7f24709a6103a39fa57d94446263735995cadfb4275d3ba4f069b414dae108a4ac8860ca0c56fee65c88bb65a6a7ae7bd3bb0c4ac0f5fedcbe61d1c5f45ca1acca8ae078e6a69979ceec3d2b92a33ec7fc7169d129e2b14d22f79336b3306d0ac93d10f1594d733958ffe22a8a35a5c9230ac051b7267873f62e2ff056103c2730bf50821a36d8cb15978ec745a936a357326e66b324db4815cf3e775837ea458860109b0f07beb8a52512b6c3d2c2983956f808a1f3eb161b1674f48e27f97ebdef60f2aaeba48671e01b83808096d3d3cf5c8ad96dab79090b2a55a219d868fa45c05d8ed0b962a61af84132aa99cb9fd028149d458c0426fdc8da30147c9e39c1002a02730a489224bf62e20d431dd92350c1fa9df17b21588cd3e1eb7b238e07c0d9b9c834008a434112d33db8b1bf23c0920dc450c10b9f219dd42ca3541025406f62b3fe1e5a7bbb24d97febf1241311300631ff4a31c33871c0063d37339780e8669563ebfeb03027c736ef3e4140b3c3c86bf3f7228586e71f43612200f090875abcbba5cee99ee79d3ac7a68c91393e1e63eba4bd2f33846b21263a84bfc0f8f7da3a5adb861e4b0e4642bc14c269eed41312cfab11a8bb449d84e81cae90199e589e375e8732dae771246923a64e92baffe199abed788577f4fd525c7e40a +generate_ring_signature c5093dd27848ac8566eaedc9052fcd6197c28bf93c33afebaa7ce2dda5876a00 323871a9a595066bce864c151cafd777f14afb4943761ad5a574eeadf5cccb1c 251 39937708a3b6828e2561d337b4bb62a05329a677891317ef1fbf021efde4a32a 7d853d909949ca86efe934596d599e2d77997f771aa4877b6f66c9ef477cf18e e983c352edee9ff1590f1b148b377e4a2d5acf31be2fe34df8f6a8d4c4e4ba05 7e1871074a0892900d96e11c48249bf88d429d7bbfc5f0a1029dd27ae601cce6 053b105d261dafab41652fd16d5f6fd87e2c3802d396097745891a1f41af5c99 3499b5ae6a1a148a140469d676a0f42c4422cb71202196215c5e35b35dda93b0 cb14c49d87d8a24cfb716a35bfc392ed5ae3695ce41a9c65c34834f3c820ab4e d4d25b34a483a582179cb1c171532f16f1672c5350950936984484e8f2256c1b e657b8c50f8c92b530cbb8d9e77f3db440326b397a54ba56e3cc6a0b123a092d 4dd6a6ef7f8d5bc9f80693c0a886b0c4432eeab776c17346ac19504f46d622b5 130e7e54142cad6b55cf6143df37f9d206ecab657e1fce433ae278806ca1d26e dc7113def3d74145205db0179dd574c8b00b0e708ae5eb7510c2624500274532 7335c7e6cbd4e8153b9c1ee028e3412f1681058440bf04e6613c49fe1f1bc75e ae3948dd1c2d07972a05cb741943e766fa304e2fea461cf909eea69de08d4e79 28408929a927aee09552e8a162937eed73757ad37ba996365672f1204ad92717 2fdfbeda21d8293c0594ba9671d0110421fc35888908603226cd7eb0995e1ac8 3cfad5a488402caf59a69746fb5cd739782d61d6e2cf71c57bc8c1127055fa19 cea1d4b9951267cdba6ebe4c6bcfb7ff7f465582a73f3b8d60726ee1ee4564ef 36049feba81aabdb2b44241538d15f60fb851dfbc19d13a6e4de240be745fac3 d4225c2a253f2cbd16bb65b500ff4369240284ef1a4cb1f77e6e8143300d0fae e8ce1f23cf3ec0f98eecdd9c744f9894a5c8b3dcb0b29431c4bda4658b4ae24f c1456aae2024890d5c914e9e0a2926e7f004c2e2532572ce815a9ab91f8e282c 959ff70881dbc4521285d80eb7941cd4ba94418da70f041ffcc7479c7c513ccc 7aeb49c0c8b4256f7a718665b575b13cc0688964a8c947edb78eddee1b32656c bc18deebf265b86a577800c425c3c194a390b295063a87aebdf816315e04a0d1 e3e9862b6b0ef2c15cd2058dc35e03c2aafed007e25ac3aa59cbe2654afc8d42 00d1abb0f3f487207b0d764a621ec24265e35ef7d5256647b7404976a8bee167 9db522d9789398ae5954197c166cbd9f876c342836c100364716a3d23a3cf885 30a63e8040c68e413514de31646a18847214d70363850e40bcf5e9f5c3d92ca3 2a78fde45151e821a1a924b5241a2403ccfc6ed62d2463b09e7070b7279c5a9d a26c48fc6e7e82af42fa3cfbad13812bb6395aded22dd250b79f47ee7dfb6581 a801330fb5930a20ac3e1d928ad94a70faa44e7d8319cd6c781d3d5e0b7ce0fc 7ced5508691face4c0630aeee6dd57f510911092109720982102ade5361833b9 2232855cb3aac2d84031685bbe847619d358070216d20f681104f55bd100c2e9 6e49a809ca9d63a6a21496ece8bc4bcf3768b8588456ec1d909c2925f60e995e d3a035827bad58e5a65284003b112160f3d2f45c103bbbc13f00a92f101b2e7b 3abf72f7ac3ffb7fc6113fc42e26031badc02e4d8fdb3f7f08b436514c3f5a31 2d3b155aa6fb6ea05e5a8367039d257fa0b334039d5ea0ef11fc56b8117c306d c7fb3b153d7b88597b92ae7d79f0e3185716dba81744ddd9ac1fcad2e0543fe8 1325b0d92f95fa8ff2cd42384cdef4d2976e61e76ff73072bbcac1369013789f d8cb35a8558bec532c929325f135119af32d6e46a2aa9931a7464c6d469cdaac 7a7c8d38b604d98886d467cd766c40abc920d751c2c94574fad91bbd6a8aef5d be6b00d3cb61d3032253e1a7347e346dca1bb51a92a3eb8b071af0c891665b37 0717cb474be340eaaf4a144b64dac510b6e8e63e3bf9e8bcbb3c46fed88b0f52 3542fe85a3882427abfe0b026c12ae8d195a3db1534254a8d1af81d25992489f ac694745614759040e5dd4608aa75f9b570f77d2e166364d6912cbb21fea0823 5cd8f7e533b3c94444c897c8c91212f0a228fc719ceb8bd55a5c033700dbeac2 872355c0b5f2347b4d2d7fca96f8df10e41b45b9ffb72043a531274409494385 ff1d9017025185587a0a4cdd7c884cc70cece019b26ebc15b09f716560dedeef 186ba15a08137c92659ef620170b35f6b1bc9ecf4c029732451394adfc999590 9c97f115d584768d386ce5204bd2d3629aa63ae97628146498ca37b61918a442 79f55796b89a671a06bfebdca61971130b23fb61eae4704d2fac27538ac499e7 b90a0e602d78353e01b476c3a2c35a5f0c7e5f415bf78d46ede20024a1d3c4d3 a670570bf89098e8eab1fd7afe3e00b01c07049c3722d66dff9b359fa895d70d fd465b0756c76e548d9ca89b6523c153bbfefb1ed9f32774f9e114b60a551d1f 936420d78379ac16945964a1dee95d71940e87c2e88c0a309f70ea710ef1a1f1 7821936f936122f4adfe274bbd32089d4cec99401014b67f0cffbdfd3253bc51 30d8216ea0f746b13f5e4a43f6c4d297d7e6db7e19445749d595eb028ab09ccf 7681954cc4cbb792670aa9a21e64b4723d86495e4d6d27b3cd606b00114c4397 e9663cfa339901c3282b9d2b4560015f5ebd7fbbd4827023b224e54109933369 dbe9eaee8efc256b605483f862a3dc3d5f70a4053ccf29fa4a52d008441decdc 633da88c3db244e95ef373d027a09cbb954ad208fe938f44c3dee2a5c9bd7a23 a1aebb8588a8f423fd40bf80763d0a0e5c4b1bfd3fbe76f14f9b307561ed03a6 9863117a21bc64aa4a8a301aa9798ff1fe6febaffb1e2958b259e1783fb5737f 2eec0edee3b2793b4c35d7759054e7b0c15d4d450b06a5025fb65d8a60f15372 8ca8ed9269c7c5c7ffa431228e9f688716fcc4133c8f4394513251ec26fe3159 f345a4005a7c36b6b78d97a2a030e84cc8157daf4a5a02d63675ede07529dde0 f7cfca247ffb2ea7cef102761986bb68b2e5032245960d800d5fc65d3947f9b4 59afcb1a6088b9530d8bb2435c23a885ee82c3aa0c2e685631a21a228cf07e16 1f4b5692aebadd8d08e8f4468b568a94b2eb59d5d4bf26d5343cabeb20f80f01 897ecba2d98f671188525193fe5dceed743d68886ab7fbaf5be3d09564b619e7 bad4d546d08f62c1e14500f7e340a2eeb8d39e5aa99b9f66d329dd0bce311a37 a6fedfca7f611f99b505df971c935955e2a5179efba1f0323340d67962c4d84a a30f18f05878d4815c755fbe7569d5c042331ef9d94571b0e506892355bf79b4 fd7bbe962d8a76822895dc0b08c9fd60cf1e66e7d91cbb4d88a32d876941463b 5cfd62b1a9c70f8805539e08134011fda0bd8512815c04a96ab1b79f84c6ca91 07477415ae11c9974543d373acceaa7ffac870868220a69e06c3b733939b383f 947545a4a8315cfe81d61a3caf96f5f1a41d7cf354d7095891525ba18d5edc7a ae3e36b290fa5663f46cb37b4d8785778b6e7a5b5da34f28f7a1771ccefdc084 54d701879193377dc59c6df056652fd546b4f3accb0fabc6b6019320cb5ea088 18e49c30704466549121a72ef2756c34a208791ffee54ba4838225c88bb8a8e6 e569ad0ca542a034679e69d502cb792d6a6f8c864c6abdee43efbd188008e9d2 54d46ad00303564a2ee8ff3360eef10952abe041485f2876016994dec2f7ac1b 612af9076950f88f166138e7bd7eba7ce342273816ce9f701b6a3ce6a385159c 527ad33d10c16c2164c4493cb5ac7e3322cb31282c6abc8fc60d5c19395c291f 85b25c37f30e9b1e6afac878fb0fdef3b5145443bd9ba551bca138ba379817d8 f1ecc0173843823f14104228e526537ba7d80aafa2a3f048cdacb2c0640001ae 1cde7b25a4c9b20d6915df9262e220cf42af1620dbe43fe677f97a1c5e021194 40ccb1739d05ddd2e883bfe67a4b4b00807aeaf758a68251b109049674eb627e 541beec1429c13d96d5daea9a75dda434c11c07f445326b1132582caae01d282 646f5b9cc6746bcdc22265a54b7c8043cbcbeebb1ae15b9dee7f6d7c7ec0ff2d 71471b752190bd2ced82c80b406ae39ccc88db4ccc597a24cc1cebfe24e42e63 8cc5a53f3eea773c29cd1a51706f768177f0f388b88d74b2b705fdca00d41cb2 dfe6ec108b198bf4ab586bf12f3f337d341c1a727348582b02e9649a2efd9ae7 02a64a9f14c464086daac1deae485eec3b15b57ba73a3cb6829a45942df6c885 7993899437d2e12076f3311006ec58cbdc36498810766a5825434b3cea5a9fd4 8a99015c83d9788fd6890af7711c4a3701a18cb6691d01c2911daf81a7036e52 6bc9edf373af0048417561db069c88110da2929002ea335ec61b7869501066ba 212d2fa1f059a592c9698bebfa9fde4e1a42a7e5cd3ebcc5dfe4cff5e61150f4 eb4d38583d7578738306c3d8d49bdf9536403765691d7397dfb870b056806878 5086416d7d2681eaef90d4767bc362717d1f75738fe63fdbf399fe987db43485 164a5a51776f41979c044ae85dbfe48a718dc637e7f77602ac4745da472cff14 93cd3e88854c1f515ecdb84622489175df9af084ad7f7072cda98f3b4ea76031 83a6a90b6cba9599afdded09ca949ff11c59f21d715dbfe1b7bb69e8cd30e39e 1411f05a4deebdcb245c7fc6e1260963e848d2d5093bf81567abcf9f84823b36 0d7a2530fb5a816088760d2ff8268e77dae532a31d162fe4538f75faf017560d 0fb071cf8e1fe1698f021a4817531138967476a396b75b3cc904856f2d973caf 030725321cc53ccb7f6131762f53c5e56e9267c4b43acf557be855e62ac1555e e552bf40c1ffaf28e1c467817ef78ef8364d939f5005f981e3c15af2a8e1f68f 7e11b3ad88eb6d844a993b9de6b85439e897ecec629a27e001482461dd40d0ea 16f0aa77b2720fc1c010682081d6cf1a4dc995ba28641cf5bb3ca92be1396083 0d74a5621aa39cd36575996f46f70cb2e17a65a48544ef8153fa3ebd092cd2ac b07a03f471b407eae66bbd77e5f32d7df9ba2bd53600644a6c43ccf2da37380e 2453ee3f5ebc0f2c92ec0b9e520fdc85a5bfd1094774e89dbcf7c47f6a3c8e44 d251b156ff019aae5893d61e0a97d790a6f906970232452c420c2accc10150c0 c5a56fd86a0fd7b6a17cc704b241840b377d47f47eeec7a46b966354655f8b11 9cc2e36eafb7a43d447577fd8ebd8daaed083338bce3c7d150a562e5c77c56c7 1f496612b8a0a887f9fe7ba917df15a26c2a0e5367528b7dc207bfc731bb0ccc 9e53a519f3f0743b9b02d1869a9acde5ebc122f764facec61fbb1b344d71c26f 090a467d9f5b6e63f1d891861ed4b07ca59c39957c94a58b61bc31b0a5fd7ae0 0ef42450c94af1bc08b782b5fd13d4def2d845f1340e911cb3cc1a99deef0987 f56cf062d1975b7d2325078fccf313b0ca0f9bf47fb81a1f9496c59a56c38c9e 72a867219b50935dfe77b3b1df2962f2693f35d1786e586c1106f275e2fd43d1 0ce8053f27a719156673574afa97f4d4472cc0e61508e5e46f34d60349d70a24 7ae67af34879c1a48f48338f3c6a43e28b7adea79209cfe307929d2c213d18bd e8bc556cf00960590987c6b8e92c034421699462da965550e042b0394ce5f3c4 006ee6f0266bc3d1ee4de3c4dbabfd237dad65f3d8d1883be6e8261800a3f504 8bef60f2f5d2a4b6f92113fc6e6644e25786cde40c5b5756f0f0c00660905ee4 d5ddc9afb5043d875d63729e1ff1454e33b625c4b8809d6cc78a722fbad332eb eb9e35797e0754a91ce08ea61798563703fe8209ff6689c88b36d6a30440cc23 32e5d527199ef20bcd81d4a66bdc2ec4e06cc46ef4fce8f047267313b26b7739 bcd9bd9ca2c136832d0469c6e38b8df493072badc35ed90bb6063f10f565ef95 587cf5785217edbd9406ee2210fee0b0963001048943eb4360da7a922e09a6ca 66faac7543d5e35abc41ff40e93d26dc3dbbc0225b283e6803a8586a25d8f83e 481a8dd416ea4cb95da47d4df364da485d7733bf9544956082673aa41655fcd8 87cfab1ca3d4e95aa3419c6c42fd3eba0ec55dbbb4c1dcb2f344a10e0a4c1fe5 66925ceed101bb8ba62b1023f59f4caf1f30ce11d98971e5d26ea31419849e5c d5b3eebf8aa62351c4b731531ef851d9fe093327fb7a4598a5e3b0fa11d1aefa 144b857e9e1fd993dc9bc2677345d5cb721171e42eb90749675e782664e6c002 b93b6b29b90149848c2452df74b309a91ba6b67db97f03d85f0337ebc8cc624d b7b8343623c8331428a87549b7b93cf932dc3008a94920a95987226883bcecb2 7b4538e82a894a23770c06c18aadd0806ba8a9d2a001c07cfaf4be39913c7d2f 925df872ca181459906b39330b8238642f0c2ee8455e79378077064b41615316 c474eda94a395af8db75357c336d7093c996d9d73572fb646bafd395c8ee14e7 0d73fbfc77b3fe3a5750280e8d5a5427417a5474180efd55342fdf464a286cd9 64be1caece30b05367337ba9e0cae59a8b5fca0f872a256a2ca529db87bb56f8 8be33680a41f61ac87e8834991bf5bb066d6761d6b8dc1ee3261ab31d9489e2d 181df403060aaa9e45775e7711244a3eee977179a1a8b265ca469ca37ea8b918 c75c38b856bcd1aba8f0b39da20e99454a829a64aeda962211501db1f44fea65 ade8b070d01fa4825714e9cff03d3888b8e4494aa106ece1b5f19ac93ad662a2 be8cb23501c41cc8da43ff11695b06f03a7bfcb556eebefb3ef756a4d3adf39e 635c8c8532405004c47ec4f598eaf557d0f190101f2dc9092cbfb5d2c194a632 9f0303816b3161b9a54ed048c58f2aebd4b50dd1fd74759b77668d55aeca6966 6913a5aa387f5fc1df608509e94efeabbe1e645a7a0b2ea1731f5c2b76c4487b 3439a5b52138d8489f8e4ea2b6eed403591ffe406c92517fd92a0b94699f4338 e37f7d0be2eda682c76b916dde8e1f59e49a3f728d0e6a384a70617d20d67b1d b608f6462485000a57441392ba0a6f3e080a5702a2e1c2f0ee076c89396e626e f45b075f8bacc04dc537a68e3152714f9ec771cca01e8dedbc8ca0556bae3e50 ab88abef0ba0c0f80019a69d3edf35bb3acaec3b4cabbb999c2811fe6c0e5201 4131146f23703cd3a999104ad4de0e6cbe70617a18db2f12fe205ac0145c9939 7533bddc26066cbd331ea83cd47bed0803dcddf53e44efc8d08bb25622008642 bd4128d7a66046ea22c24c4113bb19550e8190873148ae4f8f7c2ce5088813db 97b798c7b5bee39cfbdcdd05ee03cc41531902fbf2510e2173fdf65f77d33e4b dcf940ab3e938ebb84705381e9bd8fbbf28d38147333027c931969294a73c5fb 8847b8216ce4370e2d6af86d9078e9076dd0d1254d39fdf268fe77fd555ac582 1164bc0ceb2209a98e74b2c8b0208d87e7b22faddfb85264d193b9e635bbfa0c 6389eededbc5d132c379c19f329b97a17504c1d15a0d1394f0c5424d71afed2e 23a1015cccd6b3e32b86be91c5cc6e284728e7361365492b643695ca569bec6f 994c0fa0662667820fe339e742f682eadb7363c2f32bbedb3c0581eac6103130 a07f149f06097c6867f376efdae00a1eadd77df6dd962fef3ff384aa62dbd994 132ee638838203d2f73abf3d2d6565a2b66a49182fd1efcf4e74f337dcef8abf 6e88dc3ef36edcc0a0855b50c9b74918c2a97c143158015391435bcd51cd997c 2f667583cbb5396449332bbc7eadd753dbfddbd858aef3427c1a612d5816233c cea8feb61dce52b4289a8d5340b4309b1c5eb6faf13f1119cd4b2bede2a197d9 784b19bb39c04a0c64d8e03cfa02cccf2bc421b68641a909367d0328917b707c 75beda4e48f1475b63c4e878d44172bb4c4c8223af792ea94ff990bca6b3069b 7faf00a416bd08e6e4ab4ddbfdda1a081a00a64fa0392b95e9230eee21b652d0 2fb7d868c25ff5d388eac019245e59490a83650409c4e6e577df9b3c42f0bed2 b69baad2f76263308d1f073fbeb2f1e8c00bc4bd11191eb5def5a9fdcac60ff2 666f450028ac20329193551b9c2610d8b25dcb9fa8f5940f43e7a60e9c47b7f0 84a1f6033685833b55eac7e04c741af9f760a50d56f209d222b0d2b46d42c532 f227596d9f75206ce74f2f6078986571acf0eba96100e76e01333836cca5828f 787811688624da50922ef60b9fed8899a3734ed64a553ea174255c02b775059e 0c38b0514b4afa77993790fd35a2313f70e2a5c7f2e57504e86b15b5be965b92 33e697073eedc087320c51d1ecf61b54d5578e355c636418b217f98ad8fbdc53 4b64e1c35f9eb38ad17344a4165489e69ea3407101b409465ad17f8b47dec206 7d6d53cbf0c498461fe18a8e68a19ab04374d171951c61bebd95dc4564ce1c98 17066d4063e136e4ca567b7a2dd79aa7aca40634f87793656fb38fde733dd759 fb9ac5740f31fff598eee443097156f3790a54ddb14cfe02aa6cf2e5b3263f46 b7f18404b45acafc9bb8cb10a186a696ae7ffb84126e5458f50a2f1794e15469 929ec779dabe57da88b1281ce1792624c729187e4fdc0d50585ab8528702db2d 8cb2b46ffcad9dcf356bb089b8beb2a461e4ad8cbd5d2532780350e37e41d0b8 25125b917658538e1d422595b7c4a5917d81e47d397b74baa5d713d1babbd730 6ab9febd5a2f5836ad625968e702dacc6babc7fe52d428d7bbae17ea7c3ad61f 4874db513848b00dfa108c53669ebc17506166896af48e3c68148d4bf8b99939 89872f5084d9875e216519bf5a6c0b9211d3ae603683f411ecb84b381895e863 6cd5ae3853e0abe7ab6854b6d0b0926d92c144293ef4dd4f9972fef1ce5d6e37 ab3475fb2007c87278a0b7a48147d165640842d5f67169dc0f3ae2fd305db10b 1ff198d5440e28b78e48d730cb6c210adbe74d42862b41c5ed42515b967b3c68 9cb44a35a2a15d1aa9a94b71d06fcba5758f1f691b48d1817a063b4be7f2ac5e 3b1552d31a70d241c3c33b5ef0358cc846b2565427d7c66094f08fdf0dc553de 5ab0a9edd5f873c69035024f5ce6dcea1fcbae7c75a35ddd3212783d0c692957 ad1d6326f5f0f122e8702a8494a3cefda9c5ecacc61daa3b3fc1dd94fd58e5e1 f8545840aa70b10af0918892800f095aaa228d8cc94527e93b1e5040d1413c88 9209e8b69e44f10f57fd5b60ffd7ea319ee94679bda2321cce9251f1260486ae ef5b023e360229edfcb38c0357ccb791b337630d5296f505763d48ca6d332114 641bf6bd2b1b1356498ea723e0018eba1c4126bfaaf51cedcb144ab2d0362398 6f3e871c296ece9eddc5461072ef8566bb4ffb9071eb591eea8eedfd0fa8a97f 2487fa37a0778bcd6560c8a445d09d5c7fa8ea4f5682c04cc446cdaf1af9f579 7126fd6c1918ff3feb8cf821b586142a07680460d7dfe528aced2980dc403076 d4d6a5d8655a8119d0686d5a82f74606037da1a7a2996ed25e9f3fdf77ca391f 8cc8830b2213ec306c201584340f4b4f5cbd3b3fa3eb36f75786c822e22e594c 32d173fabfc93d005f3ac3ad2366703b38907a2672b5bc724241ed87289d48d3 231ea19cb8dfd1538ad9358c94f381884e5eb671ebee6de0032dfbcdb53740c8 81346e00b86ca5b96febb07161273ebe427f374522df2ebac148d83fb1c84b65 6622ad031e4a255114ffcc1b993d8d3e31c6d65e40a59574905b216a352a37dc d74f5f46d0a64f9dfa77600f3f30b38d2a0143a770e664119f9f77ab9d2f09c6 8e653adfaf5064ea5eeb09d51dd65dd8655fa7fcba239f4ec6ff41379d44768d dd71ac0050e36750b6e33c90efa389b856cc6d06b4a88a2ec732bc505886f114 005dbef9166eb9d661b8954120bc5d3a26f0019ce3f3ed9323c45319e1820551 f5b548cc9af5856e732b3d2d40d73ed801d809611be1b95d3a0a4578974b2d20 defc412b437cad2fdc7299390a68aacb97e78252f38a80d9edabbcd3a4abf3ce e0af56e16a967fb94821b853f6197c6d9994ee0aab2b081ec16ee21f228ec0fb 2853b9be2f74e4731ad0d77b05fae3297fa7087f6e9a6a61dc8295035ed081fd 4d6a31f13950296e764b25be58d3f379d79b3bbd6b38f01fb6d3e473a4f51712 623c7cf4765775246300ad80136a7362cf5c9d862708aa7a19f57f56cc06dcad 548e4d75e578610781844f271035461009b327954bb099a2c1e45ac9b08c6df5 191e63823ab830693cf02c68e19d49e9307c7a4f044b7698dd94d476df250862 e8fd2c2f0a999138fcb936569f3f470c4d683580d72cbc1bd1e4b36faea2d972 925689b1d36695f45765184f979dff2f2bc70efe57e37d9226319b50b90dd469 8fd4bb24b442796650c1f0d825f468b955a34c5b61189a1c44b6df47feb40d8d 0361ed2dcb2a570f577b35cc6d7eeac9b617d70b7967fd4d30f94da25ffffc39 d732a6674821514311651afe2142d14be9526596e9f45e9c8cb658cca6fe53bd fa76c7ea0f87084e9543939eba23cad3d3ea2a0df03733044e73fa25859b8cd5 c8ddeb6e648cfc07f8ebf7a677ff6a038e747e37923849c15c45342afbef8493 5c431e3a46089c0b41ba2136374f0e42ba6f9555b0019995b690e02d1800d814 93dbc3d9dd0820e634aeebdc808ccabfea052b77199ae04fda47859928a371c8 df9e4ec31e852616503784e26457faad8ecd94428884bda9ee6d81c575394867 f9707e1b484adfcde45bd506627735685e0b3663ef00a41c48bb1c11cbc266bb b123a4cb6366790bac198d2d3d400b201c75cc4af7a3430c8a546b9891ae05dc ef38093824a8b47c138e20844f923934f435dc18e84cce31a679a61fe68917c0 e81b5c08382f256377a7fde70b56421e7962d4b9ee90378b201666a0bf88c6ab 256e4f321a15a634355690e49bd7ad6b92cd51c8b1629f85c49260c0c3431f63 ca7b3fdca514a286c7e8f440e8353af4a030c31e5f27ecdbde302a1f8269c482 e6a199df5a488561924613397989d00c595ab63019c2bd1d8b5df37fb1ac7ada 4610c481631c285a6acc307c9439f8f8acfc306f47194e2343cd74efb7007e4f bb2d60b1aeeaba077329246a5a406c310a98f94f3c51ee6dbd102f9e6677198a 834ef843a1b0508f4862ed8013d6555cc21a23c52fb5609c2698c20db9912922 f624c48256355e29be4357a424d2d5d6d9d0d4d8ed3045fd28957d1b747d1867 6168d8666d802eab8552a1908420575c4cc9b5dcda2bbad9c10df93d7b665931 206b2c718e2f34a009b1f1ee7df74b9e813831f175ad5d06e520af8d0012d178 61981a77843ffebd3625d850e0419fbeaaa7a08688d92266f33100d7b6c40d0a 141 ab1fb215d64fbc7e4c3c4f01ea4376de6e31f6a8a010cc658420d009d36e55089e7f0d30a81d737cdca49a0a1008ff69fde6ffd1cf2e611859ca1ef81819ae0ebc557327f33e38f2750b6d66ffcde96ae11e625dd3b3380a8dc199f68a063c0380e8cf746b154b0bb32e13746498492cfea4f64e08225f1b48fcd49bb570be02ddc692fbc8525e38ffdf80ee1cd3e206349542e04597273f7263816959b7970e31eb189c37c67dbf4b840b984497102c88d0400de78ed3a39b52aaada390d20bed22fed65744eafaf541661470a0be697eda136be7ddec44bde772810e147f0791b2096138a56c0db00acf93054f91ac6bc0e3657e203410ccaf656cec06480820791ba583c3c89fe6ed44d39cab0fcb871ac47007b942bd974ab5b80e8f9304350f5cdc608bcd4e9f65c6f8ca48bdd3d17eb196971729627183f4a485b872032adb03ef61807b494560353a65b3091d41baa37955cc7cd4756505c38f4671085a84845566bc7b1d19ea1c23a08d9ff0f2db5cc6d6858e9e1e969075dc941106f3027c7e26cc38c8b8df447d6bd209ec9cbf963b2b60e2030440d0801c4e110358f7c55801369b23f8e4559af84ccc9d87aa14e9f00a1fe65ab1c85d0c070e05b2f2d7f553e032af8ad700937d5830f650880c51033c2c1a8b89e0659f2f3c0a7b937bda0acd91d2c1cfa3ec862bc2bd49666464a4b71b86d0321daa0139be093bd15251aad8f6af5e026abe6a3063f7fdf76453429265d136fa0eb62acff00a08fa64f9e63377f34644e8ff27db06357cd0e5fa31b3d1da7f02091abefeee075e0850908296d9daf74f360c9af16474572c38d928aeb7e7e3b1d299a0ec570fc63989ca6ce05c42df06e6409e37c3fa263ce92d361ea315940dee71267d9b0a09bb21390b2e37d7fc0e2ff5b93f3dc93997cf0dbafd27bbe0a999a56bd71906e618f93df4f53e309147b58b3978a1b7af931d884cc2df5fe18a2f5f6256640e2498eeed0874cd59217c7a5a2e2572006a2c3eafb08da01f31291ab69cd4b80a0d46f6cbb5b05f15bbeb931567e3c1d47f57902cbbdd9708cd8f9311e6fec00f266989a39d73ed9450205aeb878c05af1314c8d062060355d241af56145c590fa24335ee26b5b010b3494b93a37bee088c0185bc1751c6e01f4ca5d233fc2c056a08ce6cc681323982281d32804b50f510191c6147517775135c118415e4d40463f5bfb4f36152d050f908fabf5d714441d08474f5facb7432972fefa599ca0496f314d1737d48dbbba0ea092930261298e51f98dd2bf2eb0c3c2e9f84f0c308197a7ea2738129dd2773d1309e3871b01f9bec883508fb69ce6fe5a162fcb80ce851e11aca3f4cc918367e40a10bc1bab765c4f8872eb60f34ff5d282fe00f0bfd5d3e5168ae90fb4200851850d5a88aaf650bb3c0f356490c7c8cb5dcdc18026645d891455c98be8b0abe0067d0f1e9aaa6930fc8e3c3155fd0d8748c79170b5cf8e73c8ef4bd03851a485ee0e8c5e4ddaf24555673a06debc8c1a47818520b088becbd7099212c1c4ff64382c63d9ed1f2cf25f3ffeb7f31b9bd589e7010024e3f99eb151c294198dc98f04d08596da3460659f82ba21369a62c0304371102e903fd4bd2d78d06f97564307566642b50147fe28934cf197ecc8400bc4eac0065f1d2e53672e229ec0bbdd45e26e3598c523f4c1e7255329fa501e64d70580ef7efac180f95770585486b8c620cf724edd86d367519f7273deda6efb33ddb071df3cee79d69811fd4f8075bc03f8619b21c276fce3bfc45a92e0baef02e240b8be54dddd9d8ca16a49d7894823b6b22e61a0194210c5bf5f643e946421c40067c2c3614a2e7d6abaf14de09f720a8ed5e038eafffb178910f66f2a275588e0a1df2abc2014d2db73259eaf18ac722d94ddde567805370d1f860baf274fc9d0e0914f64755376fd53152a3b13847b714f1b86f68bc90795d9130b726cbc99a012b0763d44270c11f5873e9f8109a4f83eb83b2e4e7681923e8f30467c6ca9803fdc5905d54b66383e3cfc1b7c5e7de5db9985eb335c997fe2e920da250b7af0034e34b01add89f24a0cc92e82bad0e4328bcaddda232c05062895c0db6cd520afc82f3ec771a90a6cb9762e7421e39632c8beeb223a46a9391b34f1214c1050bb377874ed8e6a08b0634da87ec1fa1afc76460111bb7b607dcca77b3e7d9fe0d791be4d72409292ff9bad34e67cb21cf5d6ba6b220d77d768546b977f4c02800c502fff761a4384d1fda556dbcf16ed0fce9213eb1ae4ecc11cb50a16f60db09f0705eebe70056716413da666920d7ab0fdde72f90fa49774449d4c2701c9e054573968cc5719a63bc4b7ad50b7ca9efd6b1d3b19a1f135c6128aa42c6a0230f1f398b45b88f69c9c148c8bfd072dade1a7789fe25f64a4525b4e6d75761c50be2e8f0ad01d966ac7599b409a101c0959f22870db5f8d330cf2fdec26b34be0ea54801cc0d685f89904924cba6af5cbd7bf2c5865caa6c893886f3f1d6d8200668948c0855a018e3fd0c74a58799aaf7207704448408cd3ee314cdfad49dfe0e19fb7b86e762f94d35081e6512252f3055216bba4460b96fba0e75ece44bba0705f5b413a6b88a2fde10630675aa49cb926b48ad1ac79452937f49cece871c050b39d3a54fe0a8504984e68f751524120b3aded08ea867d8faac8c688e6f880a5accad604206897b8a8b067e15a41aa053aae606ca5963ffa6e538093ad8280913e56105e7c11e9a3335033fd03472d76f50082cdabe05fae23b1c8a5196a10b8ec387b1dc87902010f25caf6e0af83fe5299396c85c866f436b5fd9cf20390bfc10c7a0056bb78d6537b918a826d2f8b80520bb8f61d3186fa6b57685e2a2061f1e2dd90687c2317a5fdbc1c5d88c99eeeb4d03ff66096803ca14669e2bcf03ccb4722719db4928c9fbe97298999a21abb195cbc6fa331c851faab9b6f84c029dc9702d89dfeb143bc11c80a89929f10d4dab8c7fe04bce0defa51c3f815306c75497a6ac01116e1110d500a855243a8c932625969aa74f504571619e8f7f00e5269170c817c605aadd7ea60dcf5bd2bda783e7bc763832d0b158bfa4ad9c057cdcd027d39817ea1d9451f7e35a469b5808c909423818656e6e49ab7df8590c71716df02908ebe5b114151206c27c4e6b4faff654c9541498d49830d33f150abf6a39883e365e33cee6f69f9d7389459a1a27e9a959b534ee5d9734d03bb30d9300842d31a83f480f481927f9aac0b45addc03eaec44043bc3ec45d19f5e3043cac7f300058406bc9acbace495c8682c7bdb74c7bdf07359f84c378bd21b905a08d7507cb76385a0c8d15926e3cb29cfac7d02cb52e2ecb0681c960f6de3c0ae985f5e5447f204d3d8a1b53e607029dace2bc74c42deba777a34239b99c080a61648582e6e068b153542c3cd5af2f5adbcf29dfea5b16e28a1d6be47cc82b0c616acbb4c79b149df5c052d80e4a7ac4add12a48a22edcccebe2657cca5a2f000ac7300f55ca56bdede30cb3283756a0c11c01a607d9c762f5826862beb83b039366c5504e2c70ae0f5b18c1b27e49033b0f30dcbeaedf2afd6e9425f90b46065dfcc0f351fc6064406514ffc2b3a93174d80ac67161531a4b39538e6e2fbb0e0d1e2049d8d11d58f0893a8a913857baa7afe9dfa0c4c615439e654283b37d01aa0cc42f90b06903e4fc4e18ad8fd003b19709e5fbd8f643a86b8d083d4e07045002fb6a8aa4f414ac973ef3741fcc28437a6ad79605beef16bcec0f9807580b77566ee36360e7e3ddbf7163435bb1e98d2ada225777f05ca84226f770fffd042b12e0ae3594fc3e8ed3a290322c223f553d334211c0f381d43836752042480f8926171845044a4abd09e895bfe3ad2c9d01574ea3d008a228ff827c5cf25e017e8b969f07b04d0eee2edd6f2e80d5a7395021156fcfc7227d4f4ea224ef05089dcb07f8e0ef02136cfacafad31cdb783dc31502809b9486963a1bb24eb7e60c2d43b048080affa018b7913a847432318fe68e6247942975f7ced72039e860043bcfc9a2bf30b3214b1240ea03959071729984df735129eb9b1d16c956e30e0ae52509f2c205a82eaecd0b7970ff6ade2bc081979cf06ae21af052ba2816420634098c4fdc8c22817843e2c08af864a261319877e35f06b54542c4d80ada710fee11d3030ba1df9d61c572b58154ae658a052ff4cfb7ac3bc5939d4f27deeb053417eb3c93927f8fd7dc5e20961a09a5d544c10efc076e5a25507406bd29ed0f5963fba069d4dadd406b143e8b361f535ea3697aeed4b8973c63834b50293e0340e2bc94f77eb38647ec0ca02122dab1a3205a538b12bc5911448e9e4da9950fb3457dd06d06b3c284e3ea6dba3f183d2be52d9263f1103fe009613637930307dff5b15208a7cb76aabd1434210cba0e734ef02a3f8ce36764f593acf23ff50cf237540a827b14744f3482cae9ff2928a5de660920655fe42c87e9e22631d10f5e16190481dce7cb7599481c27d9b1ce20046b99e3697992f12e599695d9bb0c8149a988e7c93eaa91fb3228b151cd26cf1dc7667817364c53d8460d307a930e028cd29407453b8ae839f0989171dcf70ff519e5e9e4fa15e6ea3b6b0b41dc07d45cc09a08a09da72561f891e79492130f00b2d3faf1d2e5f220f1dec531800100d1d82016385933fe98190f32c81422ed36a26391f966f10fcaf91f762cc8047f9ce379c2f2962c9d1a38308d6e10c95d540699b1310bc041d1f888b4229e02c19c760b77b37d9985459eeecb12273a423ae0d5605c39a7abb0ce71841eca08a006b9579c1c08d2a29bf8f2bd14f51abbe0e8ac9e8755951377171b13164c091998712b360b8742d0102e67372fa53f9da9220e09c8881f9926fbf7e6cba608235130abb062e209a5891733e8202e8058f78370bca5ced0e4aa0185b63edb03b54c372a90f21f75613585a4fcc20f08e2c00aa5ff0da55dc4955c5e7361de0aa561488997704865724a8581a010a9ffe74560c24880b2b4a0c8996920c29d0b4460cbe6da64df6c538eb828f16bb3f82438ee3b594a9cf4bbfe13e5bd297d0c7cc4920319ccb0efbe3afceaed02787515d82d99ef73093aff2079e8db8ed20f75fa33dc24a823c6665a249d4dc661516a4128fdad663f0ee72d092bd41a1b0b645805dfc2dcf35530ee735b9f3590343fd965dadd952b3cff6d5df705e99904a5ee01abe290f1d86ede37ceb70933d790ff53669f9b4e5117ae03172cca9b06afcca3a72786e5d5b19851935ae54e5659540adbdf7c9c0a9d38952cd9f5f10da48a4b0930a5dc83887af02f56438334a77c8db3a683358a558e715c0e56c402c78a7d09a78e765033a9d42e5f20ef551d980fc7770ec0643cbb7762d9504505fa41eeae028b235fc636d46041d772d2c180df0ced81559a8bcfac842999850f203aacd834622c2260ecd19d825951ef1ee1aa34a2a31f4ec23287de0eb74104efbc3ed8ca4c5033f0d95f427ef3a483417edff1fcbb29271d0edcf154765f0fec9bfe606453d3c77b23905cfab13cb8044b2776c4c5d13bc73c60b025b48b047f35fca842ae3d3316ae2a0aa61eca434fc79507124081505404b8b32ad4070f635717d289cef521b4d6e1a0e3801c3ad12c5204776cd4f9ede04f45265bc5063c7bb74da601392c99199097c21dd43a1c39fdf9966f65ccca7f3e866981060468f423d4896043bdf4dbe69e656dec113e86a0af6dd8acf8030482c527d3d501f430b0e1cce73c91a626a5209b74e79a508d8836870fc85c28e4e4dae58a5900f3fb4b28223aef935f783b2aa1be5670cfed32dfcfbec9fe4956ee9a5742710164340b658a2d51760a3f6b992ac0d611566ff537fff9c85568432298abe6900001adf3372e0bc5c8adf10877c652ddf6c0c7b3b7e1a55330cc61990101868b0819b60ae89ce1ca35d0f91c88737b29cff8cfff5fefd7fbf6760aa66c0373a704d9ee152dd3ac8a45b1feef865f60269d71fdcdb5e64312bad7ed57f09cb9fa029319eb67a1860dcc6dc9293f649030bc0b72723b6719e1d8ee1a16ba8bbcae013e6b209056ec2c0d71e72a29679f2e09b0e9d96c5a73c113304fb2041c15af0a719c570209fc35b1cd2e4045395cf71126068f850b2ff54bfed7d7df10537c0beea4a69b798139b9d7091da9735b8a026bb0ca2d75cc2a2417ffd14ac3ba430e628666c91d88d920cf5e1d672cc732c8e0180fc0653bd48d344e67abbf56e8044f1ebc12e05cc48dfb0a0614eec0fb4a4369fe1f764a28979e43c6c0bcb1a30b654861cd62197b0035a40da110f4239b07339d06d8b9cf3d918ec7fd905a7708173d5fa3addcfad525ea1301e08e8a2e4e3ab5c84b33a8a9bc861443eab6ba00596719ff66e957915f0fdde36c96ca0127ae10468de11ed30e0d9b3245626404aa958e3214f8c2a577ae9a66a4156d0180e1c955b36f9d32e046cb9d33553803215e93ceac4afe88d91caef2efb0768bf3cefc109c1e9a12073d22d46e2e520336ded892066f76566383550f04089f2a3fc23594bcb903b580aff57b8fa1d104241b3e18b2441eccbf09710c15f59f41c1e606622ebd803560cc2f0b22a5e80d8322bda71d6d5562dec57f57961e7ba2186f39812f391e08fd21fe6115836f07722a88e2d2f06d16ccaa65f1d9406711d6e8f9cf1f9cf28e9b65e3eda094a50c96a9dfef4dbd0ef94cb5327694d071b17a17fdd86f81c55a25e2268f3af4670a32e8873e35c7320aaa8b793f060011fc8e71dd3594f106f340d86f3990d2b00b3d016f8778025b2f2c241507179ed165b8bce6001157368a7e5ea50f7475e60e91f4cb2b41d23fecf2835993295f2c0e871be5d8dddf7cb2552c61afade985055d95a8e6dc6f5e69ed49c9b05f4a0cf54e969c9b10cca60da19158f5812c6c04cead56dfee889193ab86e803dac1c5ef2e187c6edb3dc88ab775c1e422ddd3090fb7933dbe284baeb1de3f10e999a9a745cce17da2d7c0a360bc69564f92860a284949f29c9c396c61249119cb6e8a38c0f921475962f4cda6fc42c718e9ec046fce947c3d284b6d4139fe0c7bfaa26f75492e25d7a132154719e5319e6a0107bc81424c0c2d0590ec5e2332c7168a1b260ef2a95f2820148541c343d52cf809638581ce07c9f12efaceec80548043fd7d47f4d25e57dbf80ba55054b6890201fbb4ec8d061ba553d9b099999875a6fdce15af3335db0651c98c30e68295de03c31d8dfc059e94a24ee022951981a11ab491d99f01d2fbbfc21e5ea2babd290ebd0107cc4d770dac328077e71f7aab62001184301dd86ba403e0dd66a9fdbf07509b6600fc7a32cb6f36013b77987599b0adbdd507786c55729b284a83bf4d027bbcf3ca4315634ea40863ba60439a0933440178f052288610b22a73220ce9012ef08b538b46fb24f06c7895ca84901e14bf0797494b3ca0c3363b078ae9960b0ec81b0bc89762e50acd775cbc1f27f5f1199792b937287d5ee8d2e33bd1e6003969b29a36333b16931c5c409258833440e662301533c678b4f2bdb63345070bc3d233d1a8e60b6162e790a3b683ce55cf3acb7a3603d199cda5dad2ba9dea050512dff61ab32e0957d69a87a5d2eac76d2d045040a73db8bd1515122fe4d601611014aaf1235d5611371d9e8a4e5200c7806f591c48168fc4a86d37adac2809ce0bbcb537a5b469e131e79a08f8ef9cf8348b11ee2ce2e938d76f1bbc59220d459d4bf756ed9867fa30fbcd369c9aabe2e99482d39b340823fa7ea24a63470379a61e196366c5cac51d8b1bbab1a93b0804edca1879a7a3631d6e110597e70756b7e2ea006e4a17542bf1593fda7dd0cd84eebcc497425f355c217cc222ce015f29bd08cc1d5cfa95481bf2029320ac9fb99c2e5334eba5f1699115c28a89066f5307f2735c48604281d0df91a43144baba41ffe1d6660cb24f6373ed1afa0b928892a95b235b78d4eebdba762b96c688436216fb48e5e34eba10281254c20dd37cf56aa24f97fe7c55bed85714e5a0307018262885191f8481d5a0bf8abc0d92978c85a8587e855e86bd5a92b8b96ee44add6754f181fe1bf129109cb283018c34846fc01c2b681befeec173e0ebbbbd9262ab19a9c1395a8a363018b47a0799edbc9472040266ffe8af19c1e0402c290eb718a86ef0387e397c945f44e800935b4137144d742899d3111bbcb06b548a8b41425474148da36d9ce21feaac0abf7260624331a4b6d97cc26cf652b9c51f94f23d933ad8acf2854b579bb6ef00dd709624c761ea2d706fd817faf74c88058ba08e568741b599937d14c2183107bbb012884340ab18c6a17ecacea91826ec7a32f282912126eb0e78c468723f0c1a481eb4b702f6241baa0167aa8ca7ba150ccec658bde2aa9496c69963dabd004525a6749d3618908fe941203ed085122563bd69b49e10f4c390469802a3240a14485da825b22e44d685ee6e3fe170c554b8cf2960101b6be98b3534fa00c4038839667928405113ea086fff8818f0bf9a45ab0ef3b7dab8f8bab618af7df704d19f569168ef56e22a0e203d9e693a65c28e0e5445dcc90f4691e397ffceb30ef2e3c57bcc069902f708f2e9980c2a06c7bec2c0153785864288010f539bff0cd801ca46e1d153b2474b4a92815d32eaa47c3d07d359b1d71bd2e1b5459dea08fd3c78385cf7abbad28030e9b2673636a108ba2ac1e98ab85d1632292399d80fdb0b60208bded3a97ca63fff65cf13d6d482f0d8cef1cfb588d677664cafee064ab4a739c5cf99cb51bf7fe4e0d4fc36670605b2c59dacf9f5164a66ac119c0f4038ba38ea06b8843c3040a3a2d9e836b4eac9929d60ca82ff81f339f80b7a0a3beb37d2685f08cb48aa99a6e7812f501ae3a12e3df224c1695580b6452e5f0aa81dc77eca85b503203956106c545c062f3634d017f3860e870352aa0ca03f046e1f9d609a155633bc25f9515212a3f4349cc9da21b8b2fc3a4c57537c30800b4bb5c597ed3d7530dc29b6381627ccb0e8145b8391d277800b5ee5386fd8ab092b6d5098bed8341a7f062d58e5381e610792828ebb3973b00c7b941361ab2b0759a21dcb35c31aa15833bdbb3abdb6e1a24a28c0b78a42cc2fe113665130f302f728aea92d6de30655708ef3fe32a296628dbdbfa5521de8dd716911ee6f34058210f60c294910a3711d3bf5f060ce1ef07b9947f9ed243ba94f4f97414c060f5a805c1ed5fff948823615638384054bd322fb128967e8e77ac1e8e0b589e908b086434b474c628656cdaa2fff803d50f688eb4f2de41da0679401d81253a1028e1b826083b0cfaf4bb527d38051e4214dd492d3fcd93c0296aea777c0d3690efebe7ee1104a6ca67e109b35d21ddd615a4e4f4db02ba694d254158413be0605b57dc9d2157741fb603ae5839c1f4f67fb4bac8575dbee59287310d625462f04856041895f99cf1e73a6ea4065902307f0b5c9bac6b0ee90cbd65f06471e340324727ea47c3a45f1666bbb7913b15d8a92e49303d12c9e811b8d1f895bddbf04ec2d3b87fb2e70cb87a0431d5d7a887116c45968fb79a870dfe3e297a00439063dac09f303f07bcb73665552a4342490cb60c30aff178319406cb9d97de7aa0c3e5e5254171a11e813bdf5494e13e65d2c08d81371815b9abf1f31031c185f075df543c58df35b20a16c7b5f1a23d7dab9a8e81007db9a292dc63a320d5b880f17874be10ed6e8735c298f0f1696608168247fd2c070bdc670019880ecfc7803e45303ec93afc4941e2a6a90cdbc9b463114eb5f4eb9ef3b4c24909eb96b510dba51f59eca3351844cb30be921d1ee3e2520418322e68751c7e6aa7c9cb8ea0e3e551da1008be9ff608b80a3e7ca60512a03dbc46946f29fc83be4c681f7200a9b80e6721aaa118a2810fc9459114ee073eaf6601d3d88b40806b9ba4edfca0240c9fa671f6c5445716df024c5a0d2459bc366b61b8b19e4922c959dac5a600bf63c8e69182b0feaab2f55dfec2847e0dceb5e8c52802c43edc34824190a6c0417f52008748cbf0c252a7436d62eb974bd2b0a33a15456373d7c743b952a680e23f3897f22904cef840efcbe6abe093b900ebaac721194b20ba3666eeaeeb8084cdb8b2c180d7d0a6a9191a2a3eae9fc1eb8d386caea56277c1eefc8cdee7605efe28cd8d32d53c4a98f6459979683fac109a73a52c878a029775bca072fff0e2840b88533ad7b08ce0ccf3676673d794d76f16cfab5346634f0b6548e32c5051bae29a08c2a0bc46dd7232dd60b69bfa66ddb1afa271371ba83ce725ee5700df87bf68c623005c2052751188fee58c03b1c38dc92e98ca4a68d1d32e6799601fdc87e24d70f9cafc2d99746063de2da2b8ac64e7b01048fa48cd25fc0fd3407e1f66da0234dd99b8ca21b7760734910879051f46bbe2ac46d4afad0150c360470938abf0eecb5cd0a0619c8bd65b47594d6de315671a26df314fc7f10a7cb04939c89117a4815f2fa4373793462a8c71607044e567bfee8b619816cd204d80d72e9155da7a82671400d1a2cbe26bf87756951dc57a893aff7a1569951c7c90f4971a8e5231e2ff5a28b9368ec4f0bab8d270c6f00f8896deca5347b91fe4a075a7af8387414cd330967b59238e872b218f6de2a0329d8fcb38e5005554fd40b211a91870557d6d647cf244344f4878ea1fd4f5d56b21f9bd2616e83bf587b0889cef9f631f8c69554d521aa9008883a33deb082cbf40548ef2d4f4ce166bc0ed3c868014c78c5be6c4070b28a864966311976b4f6705787861f53e5379f840d1d96ed4b7b2aea312b1f34214ac5663a8f243f288152023c85ddcda052660f0b3bdd3e48a69e7703d53d579fc5225e7ea0ab9c716ff8a693494ee85e46ba9b0a2383b2dcb87aebd42f300971e57c03c963b20f8b59c0ce68dca2892da8d8780272253bb9f3960a1d18e10a5cc272deeb2458e7fa3293cb4356e8559e2cf64d023441b0a116a4b3822b086bc560e1f4670ab2993ba57aa4b2db1a55bcd25fd40e34f4661cba161df71ac414fb46e3f9ec4660bf11d207afea16eedf9cf9ab4702da879313767d399577c103c1559452e8087690df929694b1b417d4a5b367e70852d731399b7765897567418f9f52cc41ab6af07487c0538a5a080a81d9bbe80b089f98c52bfc59ffc3977c0550a832d670b695c5a7eaf880b6f951568365e508889cae5e25da80836ba5da46112b7bc90f23ae0be21ad84c303e19c450d54c081fa3b220460418281559d0eb7c6b6ca0129bdd16b2299cac74c27ad4f02f7904a3d39e398903e19ccccbff8f07db4d0eaaca8568baa49c056bb6139b594b8c02f9e4972c86e5ac463e0ade613585c2e546c6c3ae9e293ef9124143c19c97aa030f93af932fccca44286143691d9d9f6e1b0c7f9ee73822104dd0e4251b7b400a0ab3bdae3a10605db30b88244fb252405767da5035ccf292cffcf09fdde12809e94b96f541aa6324260333c6914afc72ca1bff2a3dd5a057ffb20b94d008850ee2ce3173aa08037204d4ae3cf825cac17e32f284cdb0f6d8388abc6a8e9f4a0a6d7343303dd58f09d36e2985707e0f41768613efc107e1ce3f911372b6dfe603921aebba2bb8c0cf6febd785b6ebfb1ed5a1452f2067ddff8bfabb38c9427b0db0b64ef0702e53c995fe7084407a681e692b689b43b900c6c7980ac934a5bc017f0fcea68b71c2f398911ad990faf998746ecb3a7139074a4edb72f0da158b06ac869e7dfbce2c0bbb59392dec43df6ca1005fe55070641cb4e2f9a098449c0d206121a48e1df26cc3d39cbb3a5c97252a6f7c020047e60b9f34d3a444a0ce0218db46278dd1dd0687d8c8df5e9b4c8f2b28cd304b32b60fbe144b9655ad1508391655bae6fbbc044aca2768605dd2fd29950eadb9d2595b0c85348eebf80001a975eb9cd8c1d7280d8eb4fff5a8583e85ec03b864211d518e038c28b04df70e08e3e5847c10a6c389ae0fac0bb738948c702df6643509541cbc6d72b0512705c026cbf1958a90f5a5c2afa868f4977aa0654af18efd20f6c23eba86a8cd3207bf8f599c70dcfa6c62822bc97a84f3e2c555027c444e63448f7e390bf9d9400023df81a5f7286047cf7ef6f599331360559011e6d223ebd7494e3f685bda7e03d527abda260db3e74c8d3dda5dec5f6fc86d0e06b689df5d5f33fa47b49ad40ab62897bd66b9dff75cdb66477a23b99e6e6fce13329a25e4f8963c5482efeb06f3f211a5ca7e3197c6959e56256444ca318b52b25547161a750b754663a0df073922158d2201a3c238fd558cad934d7dfb8b5841d2b08ceaf24f6d3f3f8d1d0235053c2dbb961661cd49ab3ea072c7d5323b73b9742d0a413296fafbc54f860fd6041859f72d9ac9335529aa0f120a55f56c41df4573ecc017c3f293a4219f09ad36ca72d7c9565730dbd4ec15c3493166bb8bd24ecd05ba50e19baae305c405688eb9c2b5ae213a998658aef5ecf98344d9ce29d1a4ba79a58aa118929c830b4a0331b6dd837dbb8820b33e3417e3479225dccdb72898e80b2a0b0f02a241097db0a9848553024adfd5a6ae0dded46db0bf8664e3119da60523b707481a830e60bbccdaf4fec18e87e5594c4e725d9c86b30f42d33a6871da9592c49284a10d39c97e208850b25043dcf5fb57c85e024e55361c163b0a0d31374ac92e40db08ef827a970d3da95ee27e1ab3d7a06b075e87c18934f0aef35e466c1df14cb3086a71d257a5db4172645e149f3b66f25573d373cb7102dbee41759fbbb7825c03adad0f8b2868fd06e7c5dc20fa1e8877eeab6f65a4c73edcce23921c989e0a029ba93869de4f2574823f1e1de909c5e1f773a2dbe5102223e61fa84ff70d120ce4a46a450a62eb338f2fad947ee40b66d3586c0fc9b760677cb0a64a6c128a074f5e5138f2cb639a12269f9326ac484334879a31d1f11fb7f7a6b6ee46c6a7053d2d30f871231942d5660c3d3f114406c683126b64918c19d5f90f951710f6024708e2f569ceaf166845ca952c093ce5b138ae6c2f33d4f307b22c156cdea00063404304e0bfb586a5d4b88f70a3a271e47de6c0455f330e0c7b94ac93d35c0309e9cda85387821c6ba956bd39b1c2721aee2ca0fc1251339f2f0a45d0e38c02faee3b54e3ccf5e6770560b80308395d10355dfc3caa120abe0004ae628c1e09c88f6e10d0431b1a3e90762d8f138ff7e54e97561a0f31ee9420a13f17cda1044efd7bfb956c812bc6ef656077557b7fea2d5d0d47bf18e2faa5fe3f393458096271979951f4307cc8a69d1f2eca3e0e386f159c9b43cd28729900c0646b5204f9959387c4d54bf4ae40b3bccfe312673530d2aac16ebbd4455f675bbd660403a6a8cb841afc7c01f28536762bc1c3bc57f0fde5ea248822a88034acf68c3f0ea42d352e5bcf51c5ef62c17bf0ade7321dee5de65a95c0161751c08b2444f00e9039b031eb277fbc08e45b8c232e87bc668b0493bdcf0d7b1498552c82fa6f050772eb6e20a111d6bf6caba0eac1958e084dd819396f08056e5141ea74cc2b08ffcbb6f7b2f19d8aba02fe0b09f6befacbd2308fb3fa91115975b6923c006e02dcbaf76b7a4c2efada4eb81d37c6a2be4b3f271eed710fd13e4170dcb9fab80af5f2bfe6cab56d5ed2528edea9256b34620c363f4ca9f064e4f937e26a801d08866b616762d65445b4d11be160928afae8559bff299222dc532486e8bc20a7008928b10428fa49b2b6d03a9914f9bf0021f649bfd62b32b4bbb8a85acf68390997440d34c1bc8b7a3bad0c145433ddfad62bb5dc5a79ec7990ba1ff36024a60988c05ac4cdc7830ec062934b4e4c60b1664006f1a82e75da8c87a8f92eebd10dceeca0df6af81a48656e888b98b5e18108e5d5d9424f448089dd4feb9a3b91025687f6584d810484620302c7cd27e1b17cfb3675de2f5977887307a0e8ff73021e663c816ce008cf979eedc9eefc8a252d577bd187c96883dcd50da771e09f02a4e9d6a7df61958926d317afdccf83f32d92155320d718f6b2f3230249ed73018308ca28a0a5d0c517ca50682310cca727252f82bb852c1fb79c883f4ceab20a2b3b8c3421b94125c16ba95a9e551e9e688a263023435b2c66db2446046a5404bad0e48ab943e93d754013ee4de57a38dee3a9777367dada4158ecbea6b4200431a81c33fee4bfef863a9335b086af8872e06dfc691c04e10cc15b1727344709e2b77db6f6ef04dd4aefaae96cf568b56dad2ef0ee91ba79a8800d8caacadd07f8ddb4c72519a34b5688eae4d6c99517489a0acd3094ff34466664664ab0060f92e76bcb678b52ba78309b89b5b27e082a02745f60adc650fa104b66fc2f5205b2b87f5cb966a73ac301dffa8c50723b433cf222bcdddf4c62bafee78c3cd30866216d56570464d76f2c45ad4d262363489887589cdf787dc66f405bc6a66c0b85c9dd5d3418d79ac8ba6e6ba49cc2a45807a4fbd78183cc3538b2a93ca9e50d964e451f9ff097c9ba6ecde12ba25d18ee0917fb5a337278d085fbfd17466f01aa5e0a018f804e6cd08e22835b48a11ab8d08a10dbae6a511f4e1c5ee7c87e015755356f9fac2f75cfea0012ff04fdfeb4853ff200d34ccdc7ee62ef3b39f50471ecbdcc0cbf1fcbf7233de10b141a0b4fa167932a22e7c94712ad0ca9b00f08f5cb26e11765c1075a0608afd6e10671dd944cad6eacf44834ed32bd1dc5e9039cdf55334debbf5af0b5d7716afe8885c4e447538a051e8f355c3768af32a50821cdb3dd16c6cf865e278883281ab0813c8184f7bb373b09a8a416bfa9dfe8052f1c2391a0152c43c0b16fde0e74a0c8f574457128a9a311421fe485621fd80969e4d2b8886de5954dbb5ee85c8d212c74e8da355dca69405d8c3e006d509c030fda69ca35bbdc55f8466aa5d91ec91602afc111c2896e9758240df684cad008a7aa75bad2414cbbde2a0b1203fa27eeb7e121e726db0d5116d67a87ba12a90c8405a3fcac5e66e154fe1e4df99f2cfb5ab1356f005310739049f47181d4fd06e1f7987587327d506f10de7931e5c08954d80848b53c4f5986e501d3ab59760ffecd7189f0063699e6dba205d9a90b7a91be2badf2e693b2f77f4314bca2160b1633d4f09375d36925856556cebf3353a477d6085e2f3aecd4381773bbbba70735480e0dbd1ef69760c627e2eb9dd0a772111c4d2c9cab14e53a41d832443d03f3f6c3a5a6ec67c3286b230e406820d245dc4490a9007ae7a92455ea4c80b900305450261262855560526a06bc63cdd5a4f3b0546c5f0038b2c24607acdfc30e416ecd95a60c405dfbc05331d385ae1b53cc06fff212db6b55f57a7e3ea5ca04fd0be79230ba3b22bda44012df65f57183a9718aff784cabacd38184884c300960bd7452e3c278f58784b39812eb2863ecfdba5a5fc00efc1c2c7c4d9c9caf0fd4e45a89681a1b412eb5d4f7a4ed374ce365282cc3856898961fa6427029040e451a45d6508293158dda5d7aef9be79f430e126d35efda48a96c2d5187e67709e84148a8092391f6c6dc16114bc190201db6b0e4eb4ea7f026a123bc5ad7d6007527728328fce97d5699090ac1deee665a9f0bdc73d5fbb2f68db89c35e0120beb46178a1098248a484f2a8bec5d839953069258ea50db97bbcd347f206e1d04c92421b273f6a14cb45804b6cc406cfb16460c96d29d070d1e77a30cff01020b4845641c2cd5a4289f86dba16dacddfc05fb087454199a68d9c4ad448aad9f00ad13aac6955b148ca394237ca8d607a168ab1e9788357f6b8c71abcb5afab009ea2573a4fffdd9c77bdc93847645bf39fc08f02936efdd737c6ef9f9fa697505f42530421a12759843125ab0ce55f491780690a697bef1078afe63a7ae782d02e33b4cabef2472e6e3b32839e4cfa3d6b2b62b7a52b139f257a2e1715925e10c3a310c941fe87d9df0a4da465403b88d10e228cc540578247c7dee57fb598e0f5482a1b00f1f071ed43e5a9b5bcd165a8af1ce8fdbde6dbc2b90d2c8c97ce00da2cb537811b79827ecee21ebeb477c1f0fd0301817f28774ca21c812e6f3140c0b651f08439eb7e5d68fc6aa52fe5c3466103d65f65f2e60a303b004ed8a6f0b3e2bbc4e9c43ce1873a0c6f15898f9b1bd465c06ce483763f862c45a7122c100d37196d463d4a511d3323490961b9aa6a98379b5c4fd2de367229e800c45e201a08778d829f529d38bc23e1af382f8cb8b5b4b2f8f9e2b1b954ce99c4ec2ee07536f04960af4ca938700b84e8bf3663dd80f4e6eb4e5543535e417c0b690330ab3e91f0700390fad60e4168f9a766a54cebd1f254baf1d60c3f1441d247d960fb17413468dfb6258f2d6b8f6c5ae26ab902655e92ca3c795745b5799a0436d0a0a67e9f8a786f608669b7f2f3ada944e9db979512b3f89b64842533545f611094f319e0f8c434de546649b8213b241630335201e350cc9c49374c4127b96dc07a1a86c5fa76dde1863292eb7bf7fa33d9f254c63865afcbb0060c6189553980b247168b2cab577006578ee58b1cc93c53f31a8197de6b908734a84be32a17c09dc585f7a441016186ddc8b4026b89ed255a48c5df17a5257d83c75799b69660e64873f3576357d10656e0f399d334a5ce77dd7633498535ddb91c399050f63082bef1f63d923bf9fe6fe2ec7767aaa8dc1d01c9d396228e2bd318db4c1b4490e91d767ab0f89af08a85ec0b1a5e5f5b664ecc53f7a67bbc9861f4cacbab7b40ab93ce0780b42ade40849e8f51560becb47aaa2c5c97c30f9defea8d4e86d110e62603bc1ae24d41171c1a63af6f18edfa7949af088d12971059156975be9c40e00933b9cf66f8c691d29045070532d0a75d3c155cc6c5c89c811158fe4392500652fee0df43e37ca8565c814d8d6cb0d8efb346a7e6abea2c7f133f2d3413f0c38ada81184e0f15ec57bdd814b10915ac3dae65f57a47ddd875e8d9ea35c80094b89a38907ebd6b5c28a2aa87a64e4994a4799b1ad48206c64c9ed62393d510fbb102a4060b0e25f64956b9b3883b21df88500577b2632f3b8cf53aec2f6ce0f576aebc66d943b71deaac22d455136e024d318f6c6aff081a091ff6dea200406098006c1359b4d8613cb8ccdd87a6da93d7b5ef7031d54ddc8afab77d134260cd7f8292836dd49b8f0d44acbc7ccf829a229577b928adafe8331010e0b90e70017dc056496d6b1caa56929300911f9ca8ed42544fd7a51f48f777573e54e060370f005a3801734c8a3e4cd783f55a6204573a282ddd0c3957d49bc30d7134209374e29e04080020ac2c09f372119903955c916fafecadc51aa07e7b7ec03230f8899eae59702de18275d2a6ca2e9d6e2e0c9102b87ba2bf8c09cc57ed18c43092940725f044a0d73c7dfd04ae5c5c12efa99c47ed0942df7dfee0e811e4a8906015a70b6d9b4f94b6fa3f35468433d1117ee04937575a6cdd1e9be0a11303c0e95dc7ff3f792cef5922a19d35b90228d2c020830ca174a38772648d4ee11f800a8464ce9505e48de3c5653bfbac11fc405c20354d34e745f90738bb5bb200b0c7f82f57f0073813a41187603a213ce9957f7be693f353472582428cf5e7fde06de569a5578ea72513528aba714f00676622847818800c503e370e41b8150be056269f26db3dd87047b8a482963712f15089f2ba6c1aad59b44947fe4e3f25604a9e448fc52f5a50f47c0b00991addfe9c2b1e41ae2eb813065c181a54148ba02695efa2cb55dc8d84d1f574d03d9e0295229e6dcb3b9eed50f130e91065daf047b4c8350a02077a31d59c5cf73cb70b8d65a5efd6b66beea277032a4482ed60f946d7986e1e1793a5cfe16723af882b0e467d2d8d8c68bacae688dc5b5ff2a0378f1bc70212177d569df9b94acd4a0c4ff632ad452871fe2e1712a61426068071c40f15a610b84b55b443ae6f7bdc463e839688724f9ca5764b5822f2b4ded0ec9ae74df3ae9b855d8da7c0af915023f81155bd602c55ccd76643b79ee6ee804f51c0dff6a13b4396a551ddddf56f87a908a356aa2084c241dab30ad1f5cfa0a5932eb1e3f268d29e8b70c2d67d3a100800e602818ed1582378b7494e5226b0d439ef4bf56d18abb171730090fe6a8e2077baca9588eb8b4568c4acdeb09cc0b9ba9da84092772b73a02c10d68904e1df5211e2314787cef870eaa08590c010c28cbf16fdd74e52d987b67b580a3b756c9bfe9f972874814ff00d9123c774c0a1499ad079044c423a4063a746c221b7196e46d0ee3cd727dbbb2b54a98def806ad3b71731873ff59f9322d2aa05f8d3f4bcab6b4274253f3892375941c72c00de58e2c2b80002ba3c8bba8bc240d9b9f2c28a9467406011604037c2609cd830cd4edd516946affbbb55050c4e263654d1d766d4f391f2ca76eafb48cdc3e5f0666f058e007d9c96558e3837991d42d69528900f804780d8a7ccdae4772cfc90bfc13ffe902b0312568990758a5e4526f4a623449b1c51aca4f98dbd21fbd740a665ca4c724bfac62d510bf0fee0daebb042cbe407b7c9d4bb45f82b17a849803090209a422ae6b579dd14e015ad5b4730fad267b0490165398ca0538d638d70988527e1fc8967c07bfb39ea958836c5df6854cad6f478e468ebdccd9c7abdd0cf5b1f9dc95a15158375113c4ead6777b000b47187628f7f7f9e118dc7e031401db41fb600c43750a50d369c502ed069954e1f3eac8379079d2f73846b6464e0f7711c2df43adfa9a4b5e72d39bf1c965963748e489bf0ec0827ea2a43c74530492c34d31c156eda9fe249cf663d391d977f93d07577b5ee9102c9b6718ab0e0c91fb16c6e2be9986fe301f09e163eb13e583bfb7c660f31017d2e5b67337910b18955c54d4368a441cb3832bdcc064804129a587d2e1f5f1aa3fc48c1877e305793fc5a7b6e1b3c46a5b6dd2e1a3cef701e08d06d6620009ff17d9f5f8bd310a3915fc9620a214b44ca4330ee16bb3547d21c9071afb83007181ff63ba16cf00451edb71ed22be3347ebdc53a1f01880c7d3fb4a57df73bcdf213cb557b41a007e1a65e5aa0f627124158d05d41afaa1c6045519b6bdae349a41d06709827507fd2fc6d14a37a8199962cc9ee0ba3cc30739e7a6d468bd48b1d1f72cfd55fe06ef59db9cffd08bd51e635879e6ae1bb66cd53995bd84181e52b3041afb4a170d8882369e2aae3edaf892e6e12cafde26862447a91e518d4b1ae26dd68d5c6a0060af9e33e4e890dea8a4a791ccb27bc575b6661b57f70434e070c9c410757102d62a4222d814429914e376099387c35a613b2b84f5b88bc68a10d00b88cb3805af4eec30920b5361d68fe562109d816f08a3ae2f48292f0c37f72eae0a9c610c91182ce834cb8640e4ad8658fdb0ab0c5607e93eabcfbf6c44997ed09d004f07afe14f05f5b8defabe47244bcc50a0db18ca66db64deb8f6672a5047bb76060ab1d0ac9aa708743f36936433f98c18dbac3545d36f4cfddb0455951ccd0db1090fc8adb82b12308243fadb52961b2068669e12b73d931a34d7f9b1b95d22c00e6243c01d061dd6bb1f9b49b59decabed3fc2fe9c643d61e8b90f839a4949e90f35032aab34dca4c06e4e3832186a8dfe05551a7c85eaecdf4a0388a69efd2204787609978f997649e6938c1572ba589c551d2f63f65e9132053fa5039216280c59210de7fe150f42777ba6453fe65ee80c9082e8079a202d90d2090278dab6032be9732402408d8498f471ede447e4a08bf543500e0850b8946f949450a2230d882ab915e7b45730af26f843949f22f2f42ffb28ee075358c3bac90ea2f9710d99e913986f3bd7302a8c843dbfadd16352df4aea22da55e79379457fce72fb04b2898ea995c9b73d03a152f5c4c41940ac13fb049600ef29445cd812d8196d023f24143e72586d4cfdd1273cc8d73d9f829df19938a81bf5c3b5cb5d1266910b1d0c65d258e7f23e0742a53d470cd859d82ed831c32c946ba7df9e8a956707031e3a5480623301c3f92bb429e5aa8b25b24125c2526b17afab1b74493353c90d3616d12f19a38cb37db8e0bc5b55b89617b85b3343c8d805f3e102b5366bcc04a40c1041eaefc3bb058d049d1d27265f5010428ff77c469fb1540e8c616a380993741a55f853fffe8f63159741fe6472bdefcbffdff49467008c3b45f45fda024a4cdd813b7f9a83328746863f0acb9dfad4f0a79e493166ba0e81f95ea98f040ab85093b2a1f18d58ba5d3388a50a7be32ce5e13b9087b9c1c1cab2be98f6056ac7bc41b7795ab46858ce7250ce69cf567d17acf4e0d885e898a26bc0d8600ed21c79a9642e20db569f02a5e5762ad5fa7dbc1de01cab8c5dad06e0c327e4065ed4063b87d629759d18e5bff5eb23b184e118e06326f0ebc015aa8c082e30032da8a9f908689b28b4d68a2faeca724b8a3fa4a19400064e88120aaa001c780ad640ab4299b7e72f813675a48936ea220c973af013e2418861e2802bf3363405c0290d023b71be7a6164e50bf3b40b048514cf780ceeb1b959d0c5419e017008be397a37e7125e3e0fe28dceef3d0530ecda6853ff8e8c9ae8be5aba50a48f01cf4050224dcf77ce8c641bbd98b61ce2034753619ca96b99ab206474932ff2091ca4b0ee5efb1e722e22efab6392bccc03436434ee6f554ffbef847d841fe701bbb7b4fd8b3f669c2c463f290f492cb406d05651d0d7ad5d5d0c59f21d07510a0ac2f7d8aa9f17868a69aa9c27f0aec811de5126ef073737d1b3d9e202842b009ec25bea5b571ddbcf5ae407ba4b5fbae1b25323b17bc58fc17ea4bb439e6800a661f99fbbc3a4b8f0b5c7df581e59ae1a48fc5bf973548af75da1891d05a800a0703ce3d607a100085174237ce57d0e1a991e7aa58f4364837d053ae1d3b80bde48bef6ed248ef54510ed8063158cabcb1cd1d831e24371e1d8dae3ee25380d068e61dab85ad6e96c412941806ba9f3cac029f3f4877c904636443063c716077073c657eef097f972a81cd7e663dcc05538b6a3dffb5f17c10478603e06b60a2dd44dc881914bd8ee321e3dbef5005724abcbde7bbc013244f32463b1edce02eaf0d30a408b981ed8f58abc6e3e353737e7e9d4ce242e6c3b9caeeea9bbac0efaca348789ac733b1cf0009a18518f7bbd9cdb14a29cf7400387b395e0512f0be046d4e16b3f796f938016a263535c43d973e6c687405b52370627af9a11a304990e02474b54a2d999aeb53a10ae7f0b167ba9aab3064d8f5c89384f71296803cd71aaaa0d408ac449ad47f424fc15b6c63eab1211a1e3949e1a1c575047e604590299ce3e4ccd17484998e3dd92570d9487abd52213eba890b810ce1f16a60763df8d0229fe69d9f44a4e789ea00f84dc23256de7075f989a9dbeac670334072e1ecf44994057baed72f5c5920de737ec3b23b37397a1df52dd22e2c0ddbd045285597c9cd52f090d24fad10769ecfaf5db73322598a765f0383bd0efcd3b07bbb10a48b14fc757eb4b95f72fd4a6f6191a950a3d2bf83aabeca10f7b8fb80a461d1d663d78e579e24123448beaf5dbe636fbc5de1876234e84eada0fb2290af87b7b46f6e5064ac532e94bfa9383a8081623314eb3a47cc7bba298674a740fd8060cdb214b0ae414845662fc04687cd879a6d38d42b47ec048898145e68002a54a79ac4362ce06f7d2277648302a21e34382b7cc2c0e023bc0df5bf8e1dd07f4dde27a71085f9168c403c8f939a304c5f38e527cdcdcf7012eb4d64a7d11078277dfa8c57763271caff630e4bb2879c50f4e6bcd09619624b1372ae8f074044f2504c4d7d74449e37497cd23aa1961685d41e8ae35e8d4768c95749f1f9308fd35da60b895712f72e4fcfb4a0e5d53864513183afcd5c43d4ac9807d56d80da444c730e68ddcf048a78a8f162a268d872e84b053771ea6257a94549efdc000d1dc52f005443989cc609443e4fee4a2afbf420b8c5b0b44bc0da731cdc1d80358a4c1b47c9b4351752d760b45025aa4721b934a407f1ea096f88a6693932304f4514001a93582899773a68e6c63cb844ec4dbbcf2f5492d31ce3daccbc42b0aaa4ad238e08cb446c88839ab5889bd1ad120142393e8c55f04532f3f38060f0c40356f9e0d2769564eba415012d1aa74391dd2c54a45ea3bc995968608a0960568ccac49e52825d585a07c288c628ff1d943f30cb7aa5b652bedd37c4499040f49d83f8b3aa4d4f6c65356212d0b26ed2c6a16a2d786e4be3afadf70bdebd407d615b41c41a80c9d339580a17daae33501fb42b5e3b695f579c2bb3527818305592976625bcdb79d2965fb5cb240c46ba8a40506151fd9bbff4c472ff421c60408df1984e029617398296eb1e9678e7416d0209084d3301e1d45487d51f74b0b316d6bf5afc988d7402bcf14549c740f477799cd6a0dbfc67de22fdf8e9a0207722af14b29f364a2a54e922f98491db250379c73ced139bcd2ce176d7f3c93037e81bdf026f0c71a366b6c903030a72d60dfdc7b442b53e57cd60ab912ba6305becd9dc1e5207b68db934f1c0bb6ef7be553e94c517423214d9811048c97db0f7a58392b53522c938ec81016d4ae7735b6d9de1cdc049b57edb67855ce8e7c0f +generate_ring_signature 590a993f96a147077c4f5cc32f91a7c802e654a5c8586e9598d0b6e4fde6f48c cb9194bc59756cdca58afcda4960aefc51304bc4f6ed04c6c2440488f42b6a40 2 87fde03c5506336f088a68e7bdbaca0f4f0e8a9bc143808305a7047194242664 8b7ef8a586c5feec0dbb2e72d8036764ff5da197557bf179192e31aad1d5beff ec722447735f098024e362a928af39663703309bdb68b3a5e7e42ef7601c720d 0 5d5b228897ca33216bdee5473aa2dd7bec42e0d0068062b978f3648dbc45410bac1eb34b1c5945f29e7ca90cb529d841a0435996db66a416e1411e9979f9770fba66f9735c20627728c2a9129efca42bab42a2bf9edb62f43d3bcda433fe47025fedf02136fdc76223c2c8b054d1289df02a0e2a7b83edc97890d4c4de42cb0c +generate_ring_signature 0f36247a48d15d7ef13a065c7b1a1ee40149510d7297677108020d7b2a36375f b0226919b26683f35354c80532460ae47ac0c70b2f18a7155f9582904058976a 1 24c4f1e4a4d51bab40ff04be8bed03b4337518300c1a0073bd59011b3a0fdbc2 3dba1bb1ca997825b955163be13e92cb7f823c13db9de96570a1b539c4c1f607 0 f716cedbb1d448a313111ea25377169b21ea4b74c6eb331093ced4a26bfe390d5eb9280fdd4bbe33d8194feff077804ef2a1f4483ab0839f7af79d4158938a0a +generate_ring_signature a1831c2903f8c324b1693adecbe806b81454c15fef50af931c62204b3e135bc1 261a8904b68f5185ce1657f266f83cbbb7cda81229e313d568a15cc55cc86521 40 9f6fcf297cc2dee2ae973a51eeaa6e940388bbb75065504f449cca9b25267d00 98e264b0c531599a8a579074b2d927f85e0c8b62c437f6372267a275c4e10169 42549d197b01ea3544e172e32b102414187e707f3bcabb6b175a48e280ffbdad 5cbc67dad405316a18ff8863ff2bc32fbe25e08f8c291e790733e39e83c42947 dfab77a0540c2ae33cc85efc014987cdc19cc435463a61152c70336fbaae0715 3cfd622fd739f3eb972eaac07aebf78208c6558bfad030afe4b6b7af38ac5581 2625cf12b9544cbbb8cfb6c43d176cc0722487328d7ea20a7ea435c7beeaa4d7 aaf3c52ed69792553ce48eb77242d350a8cd10ca9cfef151c4634a284338c15c abfb16ed19fe8aba99218c2734a87c62966e7450f66592a47199615d8f08073f bddb2d703ab7e9b711ae268e900ce8ffc7ea314ba16f69a839c8784a22dc1cde a4a71e5b7225ca67a6ca194f5f650cee3ab4aad608f27e05c2a72d5ab1417399 397f57af3d7105156e93c47c7e75205ce4b199d3d668e701414f62bed9f30a35 aa89fc94e7ab1e9c47e2be820e4b852e2841333375c7181534c1d9f6338b2b22 12574a1031709e503b7b55dca440095b5ae32e7e49960df3f13af0e3545856da 2cd8ad3c4c1479a755671fc233c1ca15da6d1319d58ee7fb46634cf5e6d2c2b3 f72d700961cde8dd195b2bd34b8b33c27cd38ead4ff52cd65f32597d9f845c25 dc50f2aeb860353b9c32c9163d2f371cc9b1966ea4099b783db95615d1b347db 02f9a85d776b326a14e3c116f3e34706f831e81ccfdc4323500d28e525c22fde e46577f6631c36676b6cc24d154902c03d8cdc427b8eaa9a16bdf1600dbacc5c f61fb173a89280c2c853240f345f1f4acba37c73fab295c6153d5b0c84ff5f29 78d202b46b95461b1f0850005668ddc15e38757853e48bbe6f531deeffb3c5b7 b4fbd260b5c4d963f1f1467eaeebdf072c22141d53d5b87d4b8b98a162977021 496e1bc0694a985482d5e4deb35a8f5b048d3f6af8d0d12a8c7e8d1425c16cec 5ac968233f0006c4849db8c0134ff928fc34212a6955d2fbe6c4741f29ddd1a1 4d29eb966788a97031479b226bbc1fa8b8124ecda89c039add1f48095bbbc2ef 3c721246302983cfc7fc5505fe05ba883e54bb4b50e87eebe01a44322e356cba 634e670cd777a9df99da4be3ab467801b4d87a42d93e057fa798e08fb239c91e 7f972510a0eefdc9ceb8ad6bc4051d8743642c8899ad90f81882a972042aa120 431c662db985b69fdb1492a243237c0b6575a137065ffd665be0df48773453cd f0c20daf7e7d96d1c1282bfc919af7cee54795c544bac82adc854040ce5bb142 b7429f8a8bda10eb7e6993550f7e967b69a4ae04bcf1be65bdb252f0bde3f097 ed293f21c6a1269a56ca8335e5c492d520fbde3f70b877f22a6a780eb1109bea 0a6b31f4ca18c8cd4e1b6860664e445c32a314b3cfab312f7485b35701b8d033 ede2afc010140fb9b7e89924c1a3696d1883d3255da5aecb64f64ba3d471a90e 1dba5ccec546590f8a9ea6e91170f0d0c505ddfc6793b150feaf64637ab6dc2e 9398df9e62ad755ce37bf7d03b555316e7a3a54714031fc3630e997e8ca226c5 39cd3807d39ae3de4b43789511593e57e3ca4f44d3ab87de4dc50fe8c79fbf79 678358781b39ff78d276740e2c8c2cc482c5bad694edaa12b194bbe9dba7f78d f965175ebd6af2efde584f6bec3180fe5da01682603e7b9a54a610da393fda68 793abfdb3fffc1c2669b18d68e3239c0662766c5745a0f715fe9af5530fa6d2e 07a99a07a14dcffe0a3dbd5e14332410dbb5a035cce4a0171ed6540eb09b1505 2 981a0bec2238bca76abe80f07d4752f50d3d7f5b9c7c9dae58281445f8aeb30dc84de88c4f138eae11bdf4feb9b4c3296319e774034c9ebadf14e25175a6a709b00b10fed2d75a40293b2777dcabbbcec7d713d4ce2db9a64b929dd65189010544cfe03c8f3f3979b30a3d5ce17815e36f03f6e7b9552f96cf98dab4ed0c830643420b77faa6c7994b9d2635f02afc86f1b6a71516ca863cd28edb4d95de1400347c32bfdb655241af0cab53ba973c0a1a5113f3790f0c4588898feb0a53a5072a3495a39b7a15a425675260595af6deef4bfa8695cda4f42ec444d4d4868b09749f06d7d2acf0f537ded7d32bccc4f17f6c34aede942b8fb9be350abab5ab0a6c328515db6a0cf897f59839d85be6506e0a4197ceb3ceac9c6043e6e9593708b2d2257072c46d0846e46848d28f7c99b0361a76e0fd22ef7642ba95f8dd1804408f511092b4c4085c4f0afe5baa4defa260e724b0dabb09a54ff494c6cb540758044a274a9edafcc314d902c680fa885e308d17f254d07cb95a41961df7be0b5d65b6743c46258091c9842ff6232dcd61317ffd1414bcc425f5f4f61ea4b802d7d10c1eab703e50c3fada009bff2d054524315132b27d660a97aa600ab4710dbc7c1a7f94420ddeca4cc070b45402fa5f267016749fa471f457f87e647058009ef22567f7be3d81bd72f6db6aa065eda0cb7a2fdc46d2d82830c16f13fa8b0a2e213790d8f0e403e93d1e8ae047dcbf51486f647e73da8ff397c72e53c2060cf00dd30028133ffcda0de47bf91672398a56df656a917d32ae07414d19f8b7023eb05c88b60997835f4143f82f750881ac768230af688d267bc200338f4ad903faa91a93d60f5206a6cfbfcd8597419d0a87923fcbb66bbbdc139bc6495a710297514767c4ff3e2fe52dfd0b0570873bcba18c2cc36990253817d388056e79096b1691ce2473d4ac32445449a8e686b62b9a373aea9cc44d5a46c2ff5adb960cc218a24e1a85526a751d7dbf273f28ac238998e253d35c537f665482658d460b6faf6bc51c0012e301af13c403429077009257765df26178c4b1ad69698a7101a77df2fa2682ac01269a0fc4eef569cc277b1d13b4c1b04efb86823b2d8d1e0d58ecca65966c492929667efb801256d8a26996c8193aeaa54e8c4c026b7b990af04889d455f84a4fe96ea86e2a96ea38e44871414b53d126391183ebf9f06509e0709044435b885b1b866047f6cbad74e0fc269064c974a98bc591e4d7272f04a48ad884e29c877d5a478914e7eb5fa1afc14315e2794e9ddd9001d29156ec0dced39d640528f2898daf4c71ee72f96a424cb060688b1a1809d06d41dc76af07f7be406d259f320e56643780865cbee72021d9627d6cd0d034af82a52233eb0ed1a0d0c8fd052a443bc924639d729baf64357455012142f5ef279b72122ca30be5697b1115d24eb30fe7190484ecbf1eb8e313f491947c82a337af83a15a910df11d9bfe4d9c454630a9d834f5f2c96b01e905217a305e2ce48b2531b75a7f0bd8747543eeee305ff059fa87d151b8570ca7cb5f2e4aa8c13bfc77567d9c190cbb4aa17b661ae327db5c069b93c156876fdf2cb3deddce4b1f5788cf5c8c6d0cb93a5ffccb8cea902cf2df27d1802bf8ee44efb0a57eb167f433228c84d9bc008a1540fc4a2aa84b6f62cb958ef83d2258cc091f19228ec36ca7795b0b5ca40efacea614ae0bbb12c8b97da05cc4993372828e745ee902ff8deb05a2c7652a0e851c75fb96f8f70c67e2d165a22c96e50f3d57900833d372f5fa0db94a0d82075b9e9f2be1a03a45409bcb580c138eb322b1e5e2bdb87a908b363fc9f3debc0d5ef894eaf3b5415eb418c627a85a4a04dbaf209aa73218213e6eaffecb144e096d3cbe84cd6c48777a0872ff4f77ec3576037c8a7ba87cf795e263afbee65d06a58726459942930171d204d554e3673f9711763e13b0e05d586e5e144663f10900e52b6de41be11d57a840c602df5b3eac5cbc2dcb63328ef6d58768a6ba370b971265d07ba7969e3ded0dedd059400459b61dc14bdd60968741453eb74dca0decdf36a2037496588c818296d4b3733d5230cb5db82cf5c3c52d32f194696c0888a30efae07630542add79fe1761f41a72e7bf4044d930cf8d94b4650f8cae0e6c80aba538396988092503a7b53e1baa96e3b520ae1295acb358f5bcd855c501f67365790f7b568c85b5fa8b360f9dcef14871a659b5fad199f3f4a265d30004b278e109980eaa8f6caaf471348b3815517722064e8e31db372717c9dd76110fd13883bb23ee54c145ad851177d7eda3aa79bb5d72e85124618044a1945475038805f65c66cbe58d5db81870d62382580345a4e2c0c4c72d9aae34779f29340e5324b085ab8f20c022a1878c568bbee8e36ef0407759ea4471e1927e7eb80e0f68d15657ecf4cdde557117d4274b5e027f6164afe349637a52a437adc8bf630a9f0019817b317c275a55d4095793bd27b6b08eae54357eeecfd28887c8857c0ea717f35f69df80d3db21b68aaf15a4133e76b8d898c12d84464efbc2b3525903dbd971b570c4f9a45aa21a1dbc37ef54411ad261a377f2c450d590c4dd630b0e96e581eacafb7dbf115038ed36015aa1829b8460042b781b4114d84e88b7940dde26decb1d75b6ee4a1db215b4a75503947c7cc98bd04a367b0342b7877d960b2be7ef1facd457e6e1a93d58dd4b96e3c2faf684498284bb2f2cd7d499e1cf080bf975859169e7b4dbb1c20b26b807cb65547facc7dbf3d1f15b50f1436396049418c0b1c4cd74202bad8aa97a74e9d77458ce39c9149fc5f2c0a599438a010ea615b5460e4c4705a6a222657d83080b07e331a5cacd71e1fa96afee87ace3081788db28b2f3f35e75ce4ff4e87fdbb3b3a457abd4fb9497c29663164d6218069e65d4032de080a624053e9ebf7279f5fade0af4fad8750a44d825be50fe6e06dfc73597178491e4fce8e7a70114eab887cfecf620586d519bd383e3975b2107466bbb16301686e958f38a71a3ce774b4fe1498afd0816e4c23c2a638e308500463ce694f3ba203669a149282b09f2e5f1289eff160e598953f6f8ab9f7dc30e147a1e18ba1418f379f59705610ad814a507878cbd31ef0ad99cbbafe3c83800ac952d05194e52410678e3b5a5fba1edabc351afedf1e3a1eaad92ad6f4eef0eaf7cad976cf571b9a176c27cdc0e461c3a2afdcad5f7140761037bada6fe1208a53c485241f9f3118e0f8f6d93128e4965a1fddb2a08fde668b321dcb889dc0aafad0dff23e303493e6b7e62f320fb87d211282828fb3875832cde7606e3810b955c88cbf796ad42a8273faafe8d89f9fb4f8c12c900802d303b9376b82513078a63de112d845f7eb3d832de837bf9be5ff110d8eb80fb4b01a03b2d3d82b20c9686aea679d687f024698f60146629c43232af3d8b0e674fcc3800b60083240983f128bc61116b00274a8cf1eca764a54e73d7ea64459ffabf94b810c9eef80da761dd781ab8bd551cadc6de9b855fa4897dc790e15d04defb4609397d5e3401424b60672ad99f626b66abf6db7116f79d979099f4160ed85fb53e6b8d659d09 +generate_ring_signature b9ab0b10afa5860d279a36ca738754958805e5bd3290604096442b8a4dcf9730 425b3eda70237941990ea68b9889230fb9badbbccf08a74b7c4a59ce552adb78 1 a15898bb31142d00cea651b265aa4ee7e73189b383c616eb0f6e37ed23ef7eff 84c6db89df73d478f2725b0ce36218d81fa68d1cd5ceaa8a1f8f2f10892c3005 0 7720960bc7faa3faeca50b02ee312fe1e40a8307102c4aaf9491bdd45661340f2bfe4af9a7eb7a887270c6cd900939e9043d81e62ef898ae59eb0c223fe5e502 +generate_ring_signature 77f35661d7757d7d03c765f11350f4df7bd28708a37163e7520bd8c8fc622503 2b129b323db1ce4fdb915ebf2ddd4be3ac0798b4f9fc3e7188846d9993764fd8 10 ab241334d6e35fd6340511d9c72d5a18159c125336c76cc06eeda30ab23ca126 80832676389cb95756b34c8df992e88936b79d89114dfcc8da1e6eccf6320239 c5316c4465366ab16e1922a835d9a8b2f2ac89aa43e2f6c254c703b7cdc88519 74ea52737c3db895c2b38faaa7d1b47496998d4defde5cc72d070a15d622908d b1d7742def18ea0edf1a0bb3931b3777d85902d969b9a2a4ac30d997773de9b5 8f6ed97932d63ac5c74dcd60385536f4d3905e5697e6c27ee1fbe15edb0bf7e8 be4a83371f1d524c26abdfa898e92049d4f3471acbd5fe9b03cdce08d7fb3f4d 3d1d9750e65c8d279fde02c4c08a86c781880d3747b0d1a9ee063bd978c0921a e9d2250439b623b02e4915ba6f3eceb0a74bb7af6bd8ca70ba49e477f69f5cbe 09aef8291d5f369067a350126fb37112cd0550cf6534ce110100066ba0a8a7e6 7d6228970998328079db9ffb11b5340bd972a39cb5fd090f400fc2f4d9261008 4 2b91bfd3691f1adbf3901d7dec727d1cf4e1542440695bdecb589c8b2c75ce047280c0a085ba396c34b30d16d4b3af5c413b333a1842fa0a0678984168c0d40f28c4fb8361b59e9b616871e82c280b7c17addd59487987ec023303e2a962e1061059a97043e3914ad1fe31423d9d0a30b052eb9672332128c8ee5e74ee2b990b8ba0de941f522131225e11739a26ba0a494831e19fbf2e6289d21c3815202c029c99b2fc9a7a492066d722b43e2e3fffa9b8c711d0b9368d2ba19b87226385042f8869a00538995b5d028981c0faee06cdca8b4c6308a1d56efa7fd772ed4807f28ed6bf6fe2d61056055b7587ddfdf37bd31ede1d31e78b3a1dae0b415b6a0ad0098b7050a54d397fa3058698d94f6d5e342ffe8cf3abca59384012a848a40f947a0f338911acf1b4cfd8ed0ad2a73ff67163456d8abb81c851c8c449b76e00718e075a0fecb603a3da413d9da00020e8db194408447d173503a67655dddf03f8f87cef2d55d4518cf4be3d6fbb224d08c74750f5c6ceafe7eb44e4e70c34012a7d1ffb9f929562c234c39f5300a41e9fc5abc95455cb8c14e1238ccb107b0a720e9be6307b844e9e8226b9a5a6de44c87faf7f1bb1279e97c8a63e4124f903e1b811655f719835dab14596612590344f854fff143f27e57bbc588f945fe30f6890abfd567cb38ebbdc01da0d393ada5cbb98f753374f33792843758298d001268973b9c4d71679d7969d4453e7e2f35b824ae86a0f94c7f6663f7052b8e40ba36495e9a3b5d5ac05ce1eaf11b766052b13b03bfa7faadfb3b0714e652ca005da1aaff1d9ab4ab18e213980e015ba6fb176e4fb281ba0645e229b4b30897003e47d5da289311db7677a754a1b6672087b54adc902b537c6366ef7b06fbcab02 +generate_ring_signature fe0e906842bbf5445baa4ecabe98dd6ef27226ecc2b5ad9834e08c046d0f578a 0e4320a4732e89ca8a53cea98b44492a77168316f9e8ce95fbdb5197e9d14d62 30 b7258c82c9b3e0adfadc33a81ca09cd307e70ba065c16144f46f552414a9a629 54d94e93bfa71f1ea7c1d64902bd8df7602d7687e43b983ec3ff6ab88b4765f4 637d164f669b1111c41a5533ec52a4b05a515ee5f46f74ab8e50cc481157edc7 66fe4748dc0ea965eee04b152c0dcbe2a5fea11333951d568491103296730f02 acb9c2c966da9415c9b09bdce3492e7962d10ac1c2a5e46938a6651e09fb5516 c2d7dfd2f498249427aa0eea3b192f4802a3d212f7fda58c6961e231ec0ddad8 c830fcb8aa75343dd3722955964dcdb9864c7922b872c1a209f477e923944379 bb23e3cba803bb4750739171050a55f31d479ec0ba27f4c0fd5e8a207257fd29 a6afa3958567c006ac5a61fe4d40b5e34aa0f796aea13c2ed3866a1f12fb3e0a ad6765229bf2c6c88971c254e49acbe6cfe0310049673e1cdf346cf09da3f56d 0edae6331033f401c42e320be461975a86552f196f495b3a4e3b0f547617e963 a920e55b3c7f3a4a8653d75ed1cc731e31ac880e175959f6e267fcfcecd22955 b4d509383bdcfd434c407c5070f125c46a46733da20a3f0fe9979df94c31d5bc 25daaf9f93a6284f702e02395babcc7598031c6940e7914a93a8e9ec722e7fc1 2f1c7e264b1262b445f4178156119b3fecc1f458f7044cc4de63304e14c97587 a487d33950e0d251e92691a34a583e13aee472b4c841843ba5fec5b3c7656ccd 48971038b01b0fbb7ed269349420385f1231bca51ce21913572ddb33162c9619 f222a85417740af8ea34ac66322a4f494ca309d7722ffca6713400e4be4fef81 696f40d88004d1a539495a61f35483afbde4fb225483f1bbf7c2f82c7e59dfde 9a3b1cf51901567f6e504c0c8b08a503b8cd633d6f542c9020cc4d238e6c00f5 3fc2d5cd18e5788a96f016cbff76554765afc0428cb260219b81dcead3edc978 ab62d587fb8948401a9a3cf874a024457791d3f2532803e39e00b7e522cac759 3dedef9bd6efc320fa1bc5dbf0b0313244efaec9a7fedc18667bed47a1e97af7 b0342dc39ce8e3f1b5053747f6fd3a450319d7568779dbad042e76b31dc816f3 8b3365279c15fbb8c7d2758fd0de17503c48d87aa9802593c22ad59a27d845d4 4566ca51354a7da4bcaf7f457bf803c6e32ee109a939a69c342ad61534831c44 da8e0ff478e7c6b7fe83467d5a5cf90fc769db0d8230eeab2e79424c262229a3 2cea0bf3ddc9e0ad18757bd6efc37a6e5923dbbb76d22a06463f25177223f3cd ebdecc636abbbd1fa2b166bbfd742ade21ad6a22dfc49fd667cc807b8f51db2e 5293d8afca91f70430a90bb0d05bcc4e6062b20578ff2cae721c767b6f929fd8 33c6805f3997d25bc420affd33636816459bc9b8cbc2f2c65fe2ebca22879b0d 8 f50d9ef2cc95db03f5a46375d92cfb01fa364f6364a1c2305b2d4197ae5175074379c17d0e2b0c624487044896ac762afd7293d4b6dc02ac78d41e23dfd192056288522512eca4c1b7390e15592159b1781ec042b136a5f62b674222f52e2f02b0d151e275b3e4560a7eef14bfbdac4728e4e66f85ffe9f88dc765212413910e262d430180bfced320cd67d7a3458eb53f6d289bec1b6b2e19c70de043a8f702013cb6165d9f858ac9ecc2b78d6886e6323a44e5d3f16766fb9a88e098584c0b53d3594d4ae3cf974f16f40563d27bc35b31f343dd2dc5437357197b4e4456015d309d774d032f219f205ddb140949432420a4936cd0956fe9b94aac518b180e6019acfa875a441fa41ee165a6dcaa0189c314ea519ad916d5579387a9e22a07e62fe791688f540c2b41646ee634529803da6e1879fd4832c2f8d6d02ead0c007dd46f925a8dca5f3326f100cd72a41d1bc250d008a9a443b8ba968e59ce440be6217b354b3f00dc97848bbe5d60a03c42127056f2a7993e58185bc75d755d05b9e9301d0a8e7dc7fcf030e5784a06da6ad16afd03eab8286ccd73e299a61f0fa37bb6584934cb6fe79202892743083dfe59bc1a739a33ff9f3703cecc690e05f0841f210613d5c62393d39fc76f57a581202f5b57aa5e48fc20c5b85061f3091f4e75699944dd669e8a465766afe1a8c3dd40509ca18bb9149c4f9d48572a02841da72c95cdfb0348d701212d73d02b34cceee1c0ffda07178c68c158493b008871bb0ad74a0d6d39d58c895402b6d2534cfad0fb217b39a1ee3560a0f2910e58950c202879c830b131c3c7b74e3a5dbde2989cd9c980150c7bfc4da920660f3695f1c8852ca4e8b1f8be6e1fca07ad9e06a88683a1d65f23fad09ea52f6c00b1696494519fdedaffbc464ccecede3f32eb1d4aa3d2be87766b678b46c1430dd0a178d47bdbdfdbbc9cb5b84864f4294b1a8ed13366dde262c771cd222c6c05916c1524299d1585e8747f1fcac2e87f52743291c3cdc4fe1204c59eaef1090887d3882bc8b7c49fbb388e505e03dc48527da85ebd8da0f293cc28f32ab2cd049d4d2586859a5a44ed576907ab092fcaa3b3cfd3f0eec54183f699edbafc420619baa20598b2bf4d4381ddd69b65f24fd73a1ac075c9be73995e69a08b35fb0808fba65c0e09c1c678eb8dac6aeba3008dd83e2031a3a22102b85c56b0c98a0cbea48333548a44cbdacb81af646c4692d3a2fafaecf1d557ae38d44c1e5f4106afe4715b5f6e5ad018cf2cfac81b996c0641a94101cc2bce4b2cee501bb3fd0bf908ad106a6550cc254f4a62691202555a3835f2f0708db355d5229a9b2033098756a5114a3c9770306fd51b710b14e1c0b695502673417dc87ca34c7f74d8057e39b2e738f74812729a4a5f0fc6b1e17a40bb20cd1034647eba953139267e0c0a9ac35f04fe82dc4b770dfb1e20b594688ab9e837856249bbc094b67ac2220b2dee4b4ee3e28fef5743704e3bd11d96d9eb529b402d7e98d149959ea386f800c5828fdd058cae6f2b405a1eda3a08338c129ceeffd3114ea4b64c10eff59901bc593718659361be70036e376b9056fad105dcc21f338af9a5099a3267b6a707c905f794e8d5182505868ddd36061fdb019451c2bff2a3160c095efeeb5d5903fa4217e5a11f414b678737b3844ebc995a6e58715b9f44db071ac3e041766f0ddc051e01a95bf5090b0c6a81a5c30ee2230bd6c946ae9cc01cc5b4d4e494be0ca5be00c329853f08d4e520acfd6cb627b307dc20600eca8a0d916d5cab538b0c851b7de41f13a230d6b174cbe94f6f45481d2f9a40171d6eb51a1c0603a6fe02d7a3d24f008b91c428bdbe4398a2aeb93997ac4cb0d8ecd3d6608f194894990892fc48cee0729b6c31813e360b7bdbba134ea93ffb24fe41b075ae8687ce400ed2524d8623d36e8312998eb41dba8ca73cf605f3df6be3bc0ceccd673dd57b0c4fb9efcc44e7d099aeafa41c03905fe212c26a90d0877d64ab9cc0790871f602cca960f5852539df513f152de3ffd5827978dc351288c5e0138b54e697ad0d03a5cfebb4d71cfa6d49dc358f4309a3d47d19a8d0d38908795a470350604eb20c57ab4d0b9896945f4a88dd69bf135aee3ccd44c777dac24379adc149f3915a0a12bb4c02b908c5e932397d6030aca3df38937a37d8f4883081662b762707e000693c2709362f1134d960efd0c121be47b599a3117244b207ca673bf6f777be0b8cd811a6b50498ca92a92a19d141a8ed0e5343fb87c41e99b3444d103c679d0aade2b9501ce663decacd5ae8478999631bb00803da5a40e81c8ec7ad896b4d0b90924d4b1987a19ca15bb9c5f5b10b79f3260d6d64cc7c928ad759098d69550c3ac2df95fc5659a6a61e1ee20cb54f9fb72ec19f85bf8a056e2b0732b42db702ef76cdf48529074860baf484958e088636eed5c2b6dd0abcc0e506c778dd710a4026f766ab1c8081b98ace78f5e53a147869c761c5bf759fbf820f40b7f1d40663219feec371b348319f4d674a50be827987373d8563f4c9e36d35cfef442c05caf61e094ee2c07729ebbec7a2b95e38a13018e1be9b22fde45acdabbbda55026e7fc9ee1cf27b424364e5411aff1f6ce1b0bcd404145498fc7acaabd15ad30e2e4fb61d4acb3a6ee0ffaf1939a0be06677978fa7aba04d973e4687d7ac2fa02 +generate_ring_signature d44366265cc5e6e8a13f3d2f55c79baae89befbc5ac99d063e6e0dec1d5f8665 345925032111e3150664a24dc32937232ef1bb457d164c57c24ac1160fb7d6bf 1 0875f733705d14f8dc398a529ca0bb633914572d8849d084dde057b82a946fa3 f51168e99b11a987b49c956969326d5ab4bdcaa1313fa7ad146b24932208d607 0 9f27213883bc1408571580309cefff9488ab66e41b104b9f92f8d16ffef2f60241d5a17beec564185514ed16a3dc1112664ba3099abd7627573640c494c2620d +generate_ring_signature 9b43013f26543ae86b8194bef3e6999d7a787ac7d9e69375e117de5f6a963a83 ff20e8a898dfc4e8c3ee2864418a757fc9c52a5a6941bab0c745d23846a4a0f6 5 551ababef74f99377fd5d68b2ad3a2bfe14ec6b4afee4c39686508184f87cc8e 25d84441eef268e987eb34f24749b4a13044e341e6399a5cd6b155a87e6ff0b6 c3850ee99faa03c06b6574ec52d2916e32b399aa82286fabf4936b39a916e431 42dd11fe00b24c64342341eeb6643d229ad1673a51f09192b3f9ab4b93256cbc af4d559997026bb67abd8ee6e469dd35577dd529ced3a657726d0c02edc3d5d6 b34b5b99dbb26140e778ba6fb61449721e4c7c8c1bda6e70eddbb6c0672e9e0a 3 82d1143abb5c3706c629c1b9739f7814366ec1fd406bbabfa25e52a30ca9fe06c3358826e931d82e30e12d2eaba19bc5d82c53cce0ca3548793ab16128a8650863df1ed605e009122eb2ca75c962bb5c4108961ce12ee957ecc212bba620ab046f96502dfc1693325ed41f38331c83ffe959cad53734f5c20bb9a9953bc7c6092c6ec30294c4caa14aa1a41e0b4d7d68c41f0cddfb2350c07a78908af8edab050b6f2c46859002f874ba8f8aad578ff72b472129b4bbedad565ec4294961a60ff4db8294a9a024906e9996e0598740fe23ab1307c9ae6169caedeb85190d9c00b3d76199180674e395573e4835ff2d45bf490df20207b5fe9579454c07e6ef068cb9767c904744b20cf80a8af5fd60de771c4df2dea19d648289300e2d87d907fadcc3a4f482720b1e0b7b21e4e392dc8032719e12bfaf19aea01bdbc1f7d006 +generate_ring_signature 3c53431eba5c16dbdd1fb2f98d6388541b7b85cd5dceac9238d6aa7dd5e8ea8d e9c7b96e13b6225b03c9c774e90d2e3f71b7be553dfbd22cf1767888c4f83b45 16 70b95fdf50d68749f55586737433d11e0506886dfcfe08a82b5b01c173dea87f 9a8bf41dbb914dc402d80b6f1510e0318fb908181d765b578776b034d6359ceb 87a438d3d769aef03c070d3853f17c4e470a4a7ec5e4a118a8f00bb0966490e3 0ff0242f7714946d5b872f9fe6873d237f1f4fe501b88119795f64f744e8428b be4c9bd9231f25e1743419a2858c014ced12708662761fb36083aa29710d1120 94b62bad7ce972fc7ee236c909cf19203dcd46fa48552d86f85a2dd6379e4e6f af00070c55a10d7ea2ddd2953e593fd5cfb29eab6c6b676472d029152120fd95 e839d97bfcee72acce077bbf20856232fc8e31d27fd71da70a6f0600f85dc9a6 f35bd0d64ca12db2c9548255626727e57b4eaf37b42caeb5c4160e5053b54903 7b23cd36d3ef9cb17d8afa4346fa949be91492241c2eec7d02329f4ef37be3cc 7f5580e1ca9c5ad57941951ed0de16dce9a031761dc476b0a3f4733bfa76eb75 6bc5897d154e23c56cb1216534610d1d75241d7462aa11b8a80d6191dfed1354 99884db56a229765f038e573fb018af4e2c4e75e9750908a6dfcab2d4ec7a821 656458506acc81d90dfe82decfbfbb6b5cc2462b6e18ec798b486add559ae372 0d165d983a91a7228b44dd25f84ef8246fca9530a6f7e15924c102d4f4b9c038 83169f90ec014494f2e8dda969dc1dd5fb60f47e3a4386945b787928e56817d4 580db78b04c538d490ba0e0cabd646e357f6bbbf3752f0ea350165b3fae41a0f 15 e1cc33ce14cde0d3823504d6326fee43b0fc44ae7e7fd38fa6a38b60fceec3016bf6b5044296316914ab57bec34f848557a611a8dd8025cce87468b7690a5609d2e9b824c501556fb498abcd38cc1c9afd68b0bf1c01e11d380c985f45ac9408a5e9466e9ef02cb335052f2b1073215b1a16f8ccbc46aa01ec42b1defad4d800a22582ba59e41451bc28f3a8632fe3761926fd2d82dd56374616dae1a8cc120e8efde44aa4f379e92dd694586e52004daf0f35c10fb41ae10751adca30c61d0a8ab0382ce938ee6e457925abf489d4291bd43c4314c6cf30ddbc5a16a2e75b0713d49666c219e12e0c52d1bee6e74f0723eeb16e8d17f95d91cdace8ee6cc0011bae00a02c129f3815b84a9742b80c1940cb322d58e639f70d36efbfcd23470399d0c661f39021ca96be4d3053f566ccd11451749bd77ef5654d53c96177180a5b62159b0b111e8bdc29bb5cf3a866f70636d341de3a2b15562bf8139cb9c301c937cd6e0a5b29c471c9c22ee2395170eb4946f45f6c7bcf03f0e69ccbc5280b4d632f1b7e8aeb92e6dcc6f4c59adc99c7711531daa387e6a5197b11b35b2f0d9a1abbe7a2be58f15d3648de884a855e8be284da30078167e4f41ecf561943048881ce4157372bf7b143941be18ceca6dec78cef133545d1b458f04365cc57004083642de348abb049f2e0c7ae8ae5edeac583574aee572c9692e2e089fd9501622cf6346acb8bc59aed648ebcc19248f0399a286ba21cff0232808d39ded00bccc01d8cfea2777629ab002462bb54712cf0dbd7f7d5679676104a77c7b2890af00796c798a78a3a4e9e1ff9e3433231c02efe3056304f8b02ef93b85873110c66ffab4ff083839e7f5b7d2daf7db0a9c35c7f0aefa3b6b230a5f5aab4a6a0036005746dd22e1a4134075d1d9ee24c72aa7c9843c1c9562611644a9aea236303b1191478faf4e4f7a99c3741cd294c1d9e61d18fc9ffb16853640f402d3884016668b76f1d0ea844212f43b649c016a4e30a33b471da161cfeffab4ab2a59b0f9e66692763f3797b64037adb5a57396ed94a3f5373a0c5b782f1eea94006d10ceaf552c3c68b7068b2bd223abca4977ec6a6ee180ed881c9c09c0114b9ad820b66042feeb500eee8b7f5b57205b5e4be05d2e2ac9973b74e733df1cf3aace509f3c752e828f3af4d9d94e054540c5bb96887ac025a4802285e72733b64d4120e1c23aa5f9cd78a3d6165ec6b463c2f9fc67f3887f1394d7a8ff7b0a779483d0f01024c99f84dc88a3a5694f222edf9ca1701dffc16b88332a3db56e06a90410c602b51c512f29d16726f4c0dbda42b69bb909eb85c8d3680cad54d6d322d4304330144385bf839c27df0e764be7612a70c3c6412d8bdca8a2656e065bc33be0a7b4f335634ea361abc94585c567977693bad5d0cfb533f409a61852103549805 +generate_ring_signature a2848f3b36302284378d0f599c7fc0b7911a94281e33d4eb4d47f7554971f7c4 dbfbd2c763cc046137ae025d4fb22914e8e7182f3cc727d2177e5670ae95aaae 2 184816f5034af3d627d6d835e5c2913953f985f597b11370c779ca34048fbce2 85172db3a5e5418276b0b57bab2962b26cb6bb159f3608bd31d5eb6fd507b799 d598ef43cbb2381ebc6a1585786dc1afd6f3b2fab6ec7c7c020b934bd44f8405 1 04f45468810eb03f0305054b9c771748595686d9ca26af4562ba93490f993608eded0bcb2d17354bf8b08a62bd8313b3dc1d6befe8ba9931bdc337520a36160c7ab8797a0ff358e5550c9f90399a86f841bbe679abf9cac8a802c46d1ae7480d738d6680d82e7e5a3f0556ebf2dd8244351501a80556b7f966a872df557d5408 +generate_ring_signature 3bfa708865ea752237a4797383b6ae2d4d3c41482ab53d42ac8feba9f80b62a2 2e4d774207848de566e97eea6262bb6ea87dddf04f5dcf911ce9914e9c97f528 91 38f7acdbe90c284805550b51f1e9929022e7d533bfe75bea0dc33f717a523e4b 817262805accdb4febe4c20a8037f50aa1fa7a00592836fcd3d213fcaf022f45 13c55f83cf89d5272dd1d638e2b3048653167468c11a8bebd335cdd72e7158fc 71d23b3dd7bcc81b2fe24b32e9d3e57d638c21ebd4039a73c15bb2d6455f3b8a 2d30c73750bf6f92c3bb59771cdddc7d0d6e0dee4d4ef60b443224b418b5689a 5c0eea3463693e350aea35b9b75c918ab6782971cd4aa830180fff60f6084ea4 72d4ba8604da472325d32ddee00e21d844275c3896911c26f94038f30a59b305 2d09540ad3704fb6791fe07161f12cf7c634b173b4348dc2fa2b2d91b5716d6e 6cdd2f19ce8037aa1d0a1b933e2c619c65947fc732acd11f115c62d40e77ea41 db94bbbe5548ba971a53006889f253361d986258b9a641737b88d6d1c1a83aba c23eff960fa6ce574cfe1f74248c29b10843be110f8321641c2147baeccdda1a 47b9f3ad5306af76c7045c93b914dd0a90370ff9e3888129421ed8b78d5b6725 b749de5034ccf7c0c1bcc7a76fc3b71a90b395f8ce74189101c8b78dd08f176a 9c5c2afa18b46a710f5c2bc387d61eec6eba8c59a00781486a5504fb35b8e46d ea7a0f8cc1e7896b4de7ad84a8f2223c1f4cc320e466ddf80112b01e9f7383e4 8408d1626f6123a3c60271334ab9ce1568f4361c9e8961a9813b2f82947dd0bd 5ffb6207a836af8db9df4bde8a1fe896f864adb6d4a1699cebdd134250d3627b c719c4908860d4a4204a100951cd6f6a5f523fb1c25af8f4e1a7d91566042583 1588e45a7cd74dbe403112737070ea504804a951b592d86308aadca05e19bf97 2bc329ac65a06e56aa65e146f5ca37b15c707a1a856681f1b6438b876a257a62 6cb6add63061cb03876eee0de9733db3cfd194b529b92638d74ad1e3197ca55e 869f1663036ae025ed0696a551fd6153fd0eab16437e4f5ebb740975530cb4ea 565c6df71b17757170cfd147fc7ef7ef5442d60f420779de08537e4854242034 ee1361f2ed36794b34210f0084ed1e853d79403287ac7e422a9e2acef5d43171 396a2402d29083eb8514421bfb8b841f699d607565131c44aa72680c47ae6cd4 bf3e71778ff37c494d0d588e4c240a7a1fa28dec561e5fc95ce52d0795d30b0f 0b1c1afd2a06b982d99df49358e06aba690af29ddc2f1c6d5003e6b44b670eb9 0967624c84307d50ff5823e51dde55c2a0f4dd3e54c478bebfc74567bd7a1b27 12a0cf3cca9791f9d9188e21f8d5c4c5632ea737e4a548a29c6116009b1f583a c26300d73a72480a4553d325bdacc91f0c3b10b7dd53d490cb3d9a69ceab15da f91ce4b28de23f339c6ffdd175ece69c2718e2a3d9b22a80961f6aebd990f09b a5b04ed97ddd4a071ad49063c159c6e1e5bd53be621c2103efa9944a504c430f dd1ce2e7ad25135322058928f7e0176d77097063eb384130b19e30357b4d1a31 2987d815b4fa2b7214a0eca3d95b3dc8bb79ba433ac66aad97f3e5ecf8a67575 dec31d9c26307ed50d5ad50c5698b88d561b3732303d0ab09f2ceb106b2f0af5 7ca0b73fd6dc919d8380b22294516103ac26831cacfb46e0907223290d5ecab8 aa97e38b8e804aecb8e2c1da77776e3d0582341b2d39be6a45f8c513c99cd5f7 cb32604020edae3f1ac43f49a50364a09e9277ad9481f1632c7e446ff24d376c dc66cd2e4cbdd497703f1bd0953033cfb6550f46412250c4b62a8e44f20ff7e5 d713e361ad8a2b8715bc3a8bd0a64cdf4fe19d6f4bf2c20970572a5aed81c14a 1952d47e81a3e2a02d59f47090da2972b89d8952d498bd95d24256efbcf56fa8 33ffff80dbb6a235d0d6c0cc52dc0dcacb4a692cf09cce398423eb8742080853 1e328b3b594f3748288881bf6df6c2400fbad42e1dc53099f98945d0776357e6 e45396f2fc37f54c9ca3af36970ca0ddf908dbec065b232678d5fdf9cdc115cc 369cf4a82d27c83b295dce181970028fe53d6265380cf87c01819e36d1563ce4 7a68d3887599907fc20337d5f7b7fc4cb4f88dfc6759a0a35bf7a2a077659f20 0e579c35139219430eb86bc0da2d37f269893ffb6d10834a6d04f0a7f283dab4 52101d8a151e0a535bd2f5fe4db6d1826c47e6ccbd8a06d1ea8e05537fbf421d 3cc96ec853bf5d99eb69530adecd6aafbe9a95ba14ad506d33772c9de1cfe1f4 0ebb479ce8e81559493318897f9829cbf14499fb639f99c5a6432900b955befb da8e0e7f63a5f460d64b71a38263100afca62d6ddfeea1ac0db0a657f1296af3 119a595ecfa1514529f07f7a90cd78d4b7a98544fc4ed0141ce1c7fe2a9acee5 d9faf2641c4726c711f0d4136ac280e2972425b5ae7a3c27bf5b1171b378909a e807cdc919a38d3c286abd67ae7f0dd3376ac8e9ac55716b52b5c44fca5cb5c1 59c7d6c794047bcc905097d7fd8569a5e4888aa751065b66de32d8d00890bc79 39a5852394a61ea8ef293b244f4a2e3251939dd6dc383940e4b0e5f49b963c10 7fec3deb4d91e02f59d75bd1e7ac2e92b5f8030d696bf88463288e7a12bd4ede 9b1364077d41d4c6fc13b5e4a77e52c27b2fd1dc7765c1696ebde46a07c4abb0 2f6956d8fa81990810a2ed1f01e04b4484c0fd3a76cd84ddd2a9619e332e1d88 5e135779ff608a35cf5da0e30656090fe76c2cac427604b732fdc826b7265198 8c27f69dc560a8e8a68310264d9e65e7ac88beb237a9abbb7708266844057ce0 efcd93dca818910bceecf477ea4334af40922e56c9f4db357cdfc3321abb0f68 fdba4d25f7845c2858ca4e6c1b077a2b7f0f54bfba930670c255f254c277ac2e 04a7e77ee772a997a8954b709cfe1f660576adccc0bc828042a6bf9978594618 917d17c135e20aea7caea1dd22cc6752e4fd5ce05098d2836a146c793eac61a8 b45cb5ba80a17e6c0646adaf9cbea1f7dc5f3799a826c9f088722a5cd527b82d 29a200178549a18673e0eb92e8bd384dfaa695e130c54dab6cc44e826e7c3112 c8303040ae302f47eb64d676166d16b6e38b8996a88e49a0cf1a679da3dc40de d0dd2eb2093b1bb607c5b53a9df148a7af9ab8eaf50e56a9a19c4366a4b873a2 54107acc6285e280bebd6c5314d9ada8311dce901bc812d700a3e938fa628ee9 5b6748e854d70e02a91b3642e600fd32898279ece0f10729127de0bafc7db0ed ecd46f5a0d0719d60a71739ea93af27400770994db68ebe7fa98f9cbb97f5e86 9a5cdd5c941a30e5840598daf4e0e4dc646775ed5080ddc03bc88e74e57dd7b3 b76f4e14bc66012de09bd3fb98724759e0fb3cfe68b17ee2f236ca35fcbc058a fb0f82776ca7899d5cd705d784cb0a30d9a705fb5817497d66c048709392fd8c 6ced641a3d4c402a7bdf2de0d000f9512d6245cd946971429ce8abbf13ff56a8 fef493c6555d43b0f2303815f086b7de4c13eca9fad0bc7cdb75a118bd433392 3ab468a92ec76d5acd3837aa83b7ca933984be9c167dda2a43e86f5b5a70cd01 155bd8eb9c7efba4b2e45083e6e70539f68b0cc02a23aa1ef40d94424b0cf257 e51320a48a75b74d223cbda29a41403195300d6da467c8d636bc909bba0d36b8 3fffc66702b2144fdf6fcc3be9545f7f5ee034e399e4db1c44f7d7960cf0580b cee707102ff886386a1afc90ac11eb95ff796df190068216737f85da4a99a85d 27a33317c49c01e292d23a085ebc2af814f406665c43f9f8e064234bb9022a08 de53a7f01a8b11731298523138bc022a5def631ada76f4c513a71e5398674225 585c96a449f6712c701e231b526202e28a7e7878d8c09c79f103f2c734b106ac 55dc8746379b0c79871bb5c3fdcd4d07f16567e4ae20fb7ec2e794d27785facb e9a7d69695afde442c58da9339bb8d00fe3a90a74f813f00880f28784797a309 6ba12954a1b735fd842fd5534d28304d9819625ac0425b128850b5369e2c88f4 d41537e1b86925fd180c1dc27f7c6491813f3344d4b9e7bf26062f3c93a4ca24 d04d80299b1f40f97eef90c85799b317154baea13dee98f721fba3d6736e99ff 9629084c2f4e36d15a963af5ae25a8ae70a20d6d4029b19f313cecae8c810163 5eb7b30d7c80f24c1cd46f488db56a4b930cf1c595878682025f0315d1595401 43 fcdb87dd42aee80293b1e89e3182ce4e1d5f1b7c5cf5cbfdbb4f4bc7af8a900ca562c974e870a3c2a05e8d15316c3f83edb7b9043e2503373c12765363bedf01c01f138f6700c9021da1d362d0dd000cc7514e78a0146bdfed847c8f64edbd01280a10add0f573bc2278154db5078ef688cd91df0eb1bc82bc6616c7207574012fd09b489ac09ad2544e7aa922328f67e1e2b0bfade3e03cf09656d7658a0402f14c10de89893b007b15c52e8bea8ea89c8e15c47067eee237079a08c0adba05391a806b5e329dfacba975e6c6f0c639845c72ec2a8f11872a5ac3007f09980cc730aa193cd66ef63bf52f9bad55d68366cb07421f2403d71db514556e2fe900af988b561771ad0c71af192b18969de454111ce873f62145370aa9bb7dfd7709f6591f4843a2539a91b0cece37f5185c8b3718fc49b076f05bccdcb3d475d807e602ab60a086453f204622a9ac975c263e048b3f3210dff5908aa3dfd46d770f3a2780ddf4ef203225bddd898024b05123aae2779887fcf4289c53b35fcf3701a625ee97863203f076147f221e7184273a30e99929aaf28d2ca6ba90b6f3330dfaba4fcae3072b388cf57b32cca39b06d634dcbf24f14971d954f96472081908f7be2c7122e71c77c39c89af70b7f93ee6fd833be132d8621fe4d92f79a6bd000aa9262c492cea68922ceccbcaa0829e62a61ecf1a83d95cac3e08f4dbc7a209f295530b04cdbb0eb8448c3679b0e0a2a8c8a1d99de043919c1f7430aa85670a65d965a150ae47e3f50596f43b148afe03729c91b04632e4c6c94b6bfba7cc06a0dee47db68e89349d8b3d3cc889e5852c55e17209a71c1ae598e7167fe2bf02493ac42f91afc58588343a20c1482421488686ff456f1aa74cda2a103f38220d3a6448890cc050abad4dafbb17c0e1fb0db9443fee995b1d574287046ec3570d2208e6cc6ebd0c864fe47ac692a06eec096f4e0f9fd469355001cb864262510a46e15ef5f45f3370a9521f402369ba5692e081678ca073c7e89c0f5f840b32039a6a13ada04107cc722c36b1f66e66e3d9443f228e186c407a67a958fc19110b576585e343613674b3f63c1082e9f928f7eeb4aabab3a09d115936f7dc2fd80a70e8d45db877ae0a62ae2067bd2b9bf2c94a3e8eb32831e22c591054c804f50dbe2f59a7d8c62420c2eb8f3b73df5d328d9a87cae2dfee1eb88299769ab6700907cbe9b7274b904fa727b886487a6cc8006e419fe53c20cc858f9b59f5b67d00fe80d668e875704c86f1c59b2c228d057b627ca54e346bf79f5a56f1d623310dd187731be8b0803022d94898a7cad048dca68256976969650c9633f4aa09330b7cd80871c0f15ccf3311f83ae7b00af38cecab64a04319fb5a4aaa9377e5c502f2d64e1db85603b1241666998caa97026f71d57b891afbb4474331477d17540519d23ae42ec8181efb0a1441e48bc0aea6037c8b77d0b0933e06b20d9d36d70dc13e95f1cbaa6518e59c1a91c42f81ce38b518d526b02dd8dc7daea6db0e9003e8efaaf5c8f7fc780e5010069670d7e5702748b4b7816a76dce6a3cdb4899e0ed29708444f7d200da63740fb7c6537f6f80feedc6aaa8d4d754c75e0fb30e50f6ed9e46cc0085ce15097d5bbe5573c157b067a0a9ac489e8dd0ccaf947ce7701eb39660c0ca3dd107f1771c5663edd23636590677f5e9be06152acbaf383690a640b14986093df332005f0f3f60a69905f19d1a9cbc5540542108a2c199f830f3a2d1c5e28c80e720185cd62d43ccd697f0ba0c95a770751b6091590709585032b0cc3a0a913db766c5ff09e036722a61f15b8648dcaa864fe361f69ae6a5d002fe49cdbdbaa26ee7982755f756f4faea78040447df2832f49e1f0957bb4ef02a1b6b560bb2d2b474b71e16c9e4cd2d5a1df41d2df68fcaa78ebdb70badf340ad9de775504910be3cae4fa2e2ba919617667e591fc6ca7c6d3de32aaec3cca07b5b9637b95adc97dc6499641a1a31780b4dff64ac5aa8f9a7d02db722c577707a4ad72d6e5e4adb18325cceb4fd6cc492510e0323def59e62d968a870c6575090666f02b6df7baae501833f8822f785190d4a4231abb04a83ba8f39bfb7b7205d9a981bb8fb491f8d37f8ff4314d5c1bcf6245c296c9fd4a9d754573bd5d5e0d2bbca164ad824025f644588b431985d18a35f0cec6bf7ca6631ce825e670b3068943b553c4891fa50a9af200122bc97a262a1e6d7366c2329284cacd8387ac0dd196d9d8f996630d2ad1ef99bf5d171317caa0a0fb94c86115162c5b9e76750e4f5a081df272eedabec854c4dc9efc2aa3acc03e5cbd52980ea8be434830730098b71bf670b5ca1c50e7228f09ee5760e9fcaca30e80568e5a2d560c5a49b704353cd3982be53a945d9bd28db2e2628e47c3eeb3e2b07781fb98ac01958ed90a77de31823c9cc5b7aa1f0481edb215cdee65bf4f5c9e0f1310870b4204706001b5b9bcceaf34d56abc9a111125ec04a542938af9f39b20c8a2a7d9c78dfbbe0c4a41e595be489c4dbe92d040817144e9d49b4e32e125f7609ed031763150e80c29244ebcf8833f2c9afc31385504c302cde0101519e823c8000725ed290091094f9ea1152c164a25e6785958e304a6b72a986672ceef6996261ca7595cdb4d007ed36dd9775b2b20f74c5a15afd8257ef16b66dbb842a6c80538649b58aa13015d5fdc609d88b949f4d628b53c8d3c5a3ca33dd8b7f742e4f5f32e82a63f130485e9924b86256a14474d87a1a670b672daf38f5d7c7ef1f7b9c45d67354f1604528528ddd60c139ca0833ec2853c3b847cdcfb1195b0929a8be690e7d627f701980cd6fe9250a84a92790222193217deb7c423256b9dc795e1a61cdbeccd780d3be9d2c0117f47cd278f87e9683673f6dbcb6c412e5921060c72f691c61540049b96068ffb5129c7038d7498d14ee6be5ae2db581399a3e5d5b97fdabdfb770ad5623fb28b4e5dd1012af0edf9f3bdf8ee2ac859db2cc56bad939c2b237e4a05d08a44534277230f4e144a462738e6bba05fa08ffc42335e3cba52431d62450cfd734241def81f5301a1a360d3bd8fb361267e76b7921d554a0a18be8ea13d0b2f37f7167b7047cba35e810975e574e63fa109ddbc304aaf543a7f250c4cf10b4ef39fbd2125e53aed3bebc387d98b82b31b786cfd8a489254aa6a4c29ac5f05063f77bb3d8f5130d2750129eb1fd1beaf7c9700a8814662d79cf0ce6440bf08c1b5312711bf66bdfa6f7e31b6f3146302a5bc13f876fd4dac1ddb50a462eb05a292b799f071a599c8f509f14357ab9e2d64f0bb4ff963a3f0bea411c24e5b07880a720d52e1a9fbba609a86e57149dc1f4cb9a9e98c7e42936f1eac1c63930a9c9602e214e422408c6620069839fa1f2490df1eb01d57085baf334cba8d79057d0aea419f503a57874fa55a9cf13b1dd9599a644fcb90d859e97d888ceff20cfe2ac392b3fcffbbb69a3cf91a5c7e611e5dcc0822b6bf453fb9303bf96bd5011cce1be35dce1f2837c80df1374800811bcc9f0170588b3f8cf012bc7151eb0a0e22dddc7d5f0508afa8a4352fb218295d78f021bd54c704d9de4874f258ec0a451e83ed9ccd023c0d35ddca5acb2a91de6586c617d942e97a34cdd2f9533f0bf9d319a8965e7ba75cdee818b4c0c1f5bbf2f46e97808ed3b498f79a6857fc016d35d1b126fd1f1fdc6e9afcda7a184eebac4d82aeb9ca3106777d5e98d3460a23ac4da841430f2936337645611bba2d65ba1481be6959ab29d0901ea471780f8d15a5e151d55015c22576856bf054bc3d69755e253a4a34051dffd6dd45650c3e2154f5bae965173ca2f360c44eda8dcc07771266aa132db5bd6ee67ad27e09d8cbc2a350615d3af6f58a2cc3c425b9b613e4c9b553dbc20c2b6859173d8600f6943bff3eeec49794c56210e7632f5a63f8fc6bc7cfe8882093c28a35927c01e4e35cfcbe7e60026b4590f2fc098f80fe3b410bd050e957f27ceb56ce187a0bc0ebcff5d60750ac1daef3458a9ba47a52738e87d585073975078b0144d06d06546f15f137b3919b5d5ecec0e0b9dd5b892a25b3dfb429462c9cf4d1ca005c0eb21a2d9a298940ed8a9f46d13bcd36908946e563034e21ce01eddaa8ed112f09e293e5e7cf56f2853849f16502e76a124e2ff78573dfa8a999468c1b67b8e501970df04b863aae3f558331f4f953bb357d8392ab66fa82b528fbf897da00f2094879e82a71ed2baf5f8ba0b8f616cb50b435ed56a7c9aeb6fe9d3d06e01cee0ba16650b6b53f852cc229d46a7dcab1f6a9bf0475ec8d98acaed8a916d061340c8fce4968583717b7673046ad6c2b402687e5f0cf86832d05db989da49431b00663f599718e68040631d86af65ebc2455ecb13db4678bc4db94e8c07ad07f0703096298328c559f8ad15896177b9ae22ac5300df758c5f5c6e0470071ce7e2403e7b9acddfa7a8b26dfe474b09367d55432de66b45203f75bda06c58f5eafac07ede66027b54bd81ae0b376523bebad5b392bfee557512abfe94dfd9a916ea4005b76627163172cdc7874b118f219cef35f8fb9e24f7280e5d72d4c0fd1adfe01d6a43c90b85f2acd859bb242fb1f9ab325d50092f755df8a37092da21bd8d701776267c1a9f824b3bb52edb31a55346c1b036fd9fbfc441e1cf1896d9a52330b6f046e6b0804f8b92e1c58bf80d0d9a6824c534c1b00b6a7dedee98c3ece7604dc52ac61f6c8cdca14e30c49570bfc7b983f6a86636b451ec9317d5630174e055e72e58852998b0022d72bfd9bb7bb924cc4189f33f8178873735e4e6190160c7d43d52e958605e89fbd223c62a75c8b9190a2e07775511b2983e65423cc4000e458bca4cf0713aeeb81a73ba918dbab9631e1cbf5914ce74af2c629758859046f1b8ebe057c8ccdab02361c0b26ce0e5d625d19741e8b5300423aa0eea6e20ec67f938ed8c01a4ac90c61578ec6519e85f87e7419124fa2284c84be6ccd860b7f519abf1b744b8571038bc38589f17fb3770e224ff19617c4f710a5a5f6280b5e8cbf78a2e7fc08027582b163891e642a82a38672f5b7ce688a36fc20e0d50ee4e38c85afb5bdd0e9ac8def5c39a8849aa7f66753f1112616f768e1026ec40aa8e91cd0897d37c39a50914949c3ec95fca4267cca2bafc6bfe908616d4e1101490c71beb31686b6df5c3e51ccb38cf41ef403fc0725cf625ea6094ea0a74b00b874d65bddfc11d9034f5d4a273c870bd75cd07bd421f4f915095b6aea434b064088ae3e2265d345d4a7564c35a19e5c9e3b5a3fe6932687695197b419c4140be00928fd5354edf7a4975f8b17e9478171c80dd808a9aa5cc197cd94a44be90ee40e12215380a43ee0e23e586666eec332bab42e5baf42c3c300b1547df5f902fb47e77e7a0b0675d58fa7cdf28d7efd405075587dde50f1ee1a4e4d08b8c001f52078f936f4fc464275c8d7efdaaf204fae9f54859d771b611bb4f40726660d6ae2c5c5c817c1dba6aecb9c68ca7920f9419f01778a45d4a780016faf22040852e1bf7374585a6c2daf275bcf53bae45862f7fe0e7e06425f0c1580f3bc09042af1873c896a9e38d3b3b9a0bec1b5c2834b5a34d1768d1c72cf0f7407c99f03dec7fc38b807e0e71fe9130516a44319a94138ebe4c5454dbe2ae97ff84487099c7e4dde05266349d93a277490350f5344662695ee32e25d2bf81ba9810ec8065f6bf1042e41fcbf0d39243528fdf6dc2c49a75440f1d4f2d5ca5c63eeff400b2a5fb4a6d99e264ce6a3377ddb452fe77b6d4de1e311c35b776f1af20afbac0c005cfb8f3e85e7a4087627faf6f5d6e2dc23954395da31f6db131208587403096f83912d456a82c29cd8217a5104bd5b9f3c447c21cbc325a3069e93fdee3209e31576a78f0f255e6f22bf9d344f4deb823ac8ad341383d82a07b8bffe1dbc08628facdc6992579262679cf2248740f43714e830be162832a93d90cff1eaaa009f3c15f0d7bd2ce540f18b8715d85111b86cc79c857079d33e97f4bf1b502507bc2eedb85db6f4b28f3eb957a8d21fbff8234773e43e697b01dfb8f8c075d60cc7bf48cf9fcc106d5ccfd308e777130b151e23c2eeb5c1408e9783fb0e82aa0cab6755bdbc5a231defecec0c9f19ae0b552a941be878feb41abb94e0e3beac024e4b606268058a85049ff0096ea006bb62e912a1512dbabf8f7ccca41d8d960ceb3a7188b2ace696ae4827156dcc91f064e95eb254941805b77ae2650f00f70a78b4c200c690bc0a0dd392169dd3fd3453d91700e87a104b9dd051018850f7042e30f42cd278f1efb1d57ca40bb0c9be1fb959fa6205527cc325885862272c098357c3012fd27494789a50b4aafb9d490b7b8da00480add7c400c820477f0d03dc121832e5e9b2f4699cb8885556645f839d639547438199ca87f14b23b423041a8fc77436154d6633695aa4916bb0eeb77927d31fb7389ad042b5cf7da6f40b16da701a7c5228786c9aa5fe0c3b2b2abbc973404cf4bf0cf77c2ce992f88901ca7910708b537aad408351b23ee31e8a71f2b154f39ee7ec071e7d8617843e050c173fdaf5104de4ec725f98088fa8aaf6b2ad1b5e1cf535f5e45b303bac3a0e49f324fcfa06ca00b195f994e0d5187d5b07482d9bcaea296b272c506f99ea01dc6cad19632c034a01a546ecbe8d1be78a733653e8dbc61a721deb5eeab57f0115ccbf2e2a70e6cadefe5eb104b6809d78ecf8727519d1716588a792819d72085603969d35d2230ca826a8cc760414c7ca768b384dcffa708bb14abc3db10703bcd0ad1b0279336fd7a7540f547731e18a38085b21080c124df0a95063ef5c08fcae305a8afe1e0b6e2c4d568b43ffe828d0c40927cd5353db9a4f13b8d14901be99ffba31fbf182cc90b9e3f1a9f1b501cdd26e47b28ab2154b27247339460759ef84a8b47fd2d856f190c384f0265a0058937e2220c3a9a10fc81547b77d0d64b7de49084402573aac65f3990f2384f7652ee883265e34dd808d8bc08a2400a8887f50b80d5a92185ef165a9eb170f477b13b95922debee1b43516ef599a07f54c880d5fed6a106e018792ef76be1abaab1467bd9f2d313b1189e63fb7a30a2fd0ea02746858d87111eb70680406c86f4027b03174c08e7cfa20b9e266aa02b258ada57a843ff0036cf1a881c4fba860dbff1d244eca76d114b6ab636d720574d0feaa8dc4fda1eabfc723de785b97d2c616508927f17b28e571d98a83ec0dcf4d22101ab265aca302b87dacbaed23387bf69ba86d5e5b5bd4ee97671da907db6240529de4708fe305d067720456dbc945a219f0c40a953d5a23be5cb1de0decf6e7947312214bc60666791e71fd801112c2352c9bcf3031ee5f821bd35008a58d8eef0d6221083fe92ab0481d7d0deec9800c923dfd04c1a8a0c152ee140ae56e7eea817a7d4a63e721833d72c9ffd3bc6babb949a5bdff4eec8c612e44038e3d59d95ff73bfec83024964f4456af52bea09c35a07774290ade9c77d7600c24e3638ba1896157bc0effea656ffb444ab75f36777ba94f158335f10ec9ea07576148d0d880a3f568ec361689e86aa9eb4b0ca1942f11e28fca9178c352ae09e0332d2cca0c9177f907a38ce644bcd499d3d0a6bf45b8fcf4a6ea90c98f01019df4cdfd3986023dedaf1f12a2d6c83e3eb223afb9b7577db81f12b0ed094901eb84118895d379330ba82914aa3bbf884f8ebf703c99a7bdddc9d65604b43f0fd1d54026db98106a6e2b5f05dc7213ac689ff0561f1940622f2b50fc5460e705cd15d45703bc316772cef60e91a7463f7ea85a68b77de5e387c2b592d708d800cf16d0150f33e8b535a2a66d37077a6fff7d4fe21a70e1a64589d22a3f7e680f0f856029d69a1861820727e5006e6423c7a009cf28edf3827ee67c38b4cccb0d5a0d323f53f3831d71127d98946e3ba4882913c8039c7999aa505e7285ea7c076a6dc4ee6639d14b2038d1332a7632283ac9116ea7fb823bc37ff901de5a020494f9b96618b9da1b7794407b91d97464690be79eec33480aa378f31bd2ccf002156493a41e1f852c89a2e57eb878b95c87cafe8a0401e2897856ea853acc9e0bb855e2a398128226aa239206fa5d638de4656f7507b4d226d20866bb889a040cb88e6805d0673d552e46fd9e436ff53334d3fb5423774b0a3f799fd83114e80d +generate_ring_signature d9e4680311d1cb9dfb01254b08fe8cd0dcb7b3c503d6859c59dc47e25615024c b8f8617d742f1a96ab3b79e141b52c76545b39f00fd00729ed4325c2e8e839ee 35 c67863dc9547745b0a1835bd2bdd3c7f866df86486e79b5b23c60dbf330dafbd e837d13ecbb2a5a0bd620f59334475bdb332d44f44ae4220e5b30f4134416a87 c00aa3422f0a2f3a5a89edb8eb7c99d642bb33d2b5d4ae42a228ef3dcf990ade a132684aae1af1909b7d32035c7853359deec9fd5ad14e5548cc2e241223988d 39b05e702beb2ef5e6f02b67d46fe13923ba2629cf6dd4d813f92b88ce94e049 d3f8732f7598b1e7d51388a77e409698b1490ba56ff02df6c9091fc3723ace03 54929c78aa0ac34a796a230b66ae375a443a067a07954cdfdf4f34dee0a08a23 81ef7d3eb1c810cc7fdec70dae0a75ca8084651cd9a446005f7af0a37ff68c8c 06081276051edd0d6f829948a77a1ac5c8eae9e492880cc52c3a3b7e9442ea86 6b8762b54c942dfc5a701842fa7cb5ecb20ead13d5e72ed2475e00ad78f292a6 031c76372a7bb536cac58af77c11daa08cfb59f990cbc8c2eeaefc4ac1a598ee 660ca8b174d65ee995bceaa95e922dbb701ddb6c4df76e7cb46a75fc19b13eeb 81822888504f072acfca4da1c30575bf5efd17a769aac9cd0ba165003de67927 ffb833d7a1d148e158172ee880a850d83304eef3c6746427a1ef1370fe147474 23234646c19c1022929d56a62e494ec2d45e7188863f375cc2ffe681701112d0 227bed9c4db50f0e54a70edcdd4be63ea2f6e7b3563af10e01c9a9c5997fdba1 d5aff7375658c886005af953d831d6e4e2898b1490cad7d44a1b428e87e8c2fe 546e5da5f5599dfd4cf7139f92c80d70e6361249ddfcc36a64a4a6a4579ed6f3 4617768b70f157ad344866c8f0d9575c7a8029b2f693ebd75202fe238c9f334d c505334dbf2103cb24205e0ae4a660a592921c5132906cd7f634b78ebe0ced01 688761e17fbe6024f8e51c6faf00112256440cc4a2c7d37888ed4f5692e26b71 fc48bb2d96d7ade8b51a189f4ea1a1a427669fff066da86108899e2e069c37f4 e80d7e7298e64f4f273548bf0e2bdfe3cf8ff76f86f1291d28249052605dbf46 23345ed9e65ee1d2f9f0df21ec20f4fc506f837f54dd024ef770a81b12588302 b572cec572366f8fbaf5ad8ca07cd1cce301e56ada7e15fe2ceb03d6f7c615b0 ad65e69ee23a2d216d437521cbc41a946f1a0e2e350eb1c242e53d845e664a19 9d652c7154706b781272ea4ff1a5b3b84d83b2ab86389e927b6b0bbe611a207e 05bd82e4dd30ef4ae5041ba77652e173ed932b90ae8f26f0c7a1c924dbc16bbf 95f6523d233a5180cad52fa70fea8ba013a1f565f9fa5d56e6099b99018a5948 e376bffabf575bcc111d39638e0559a8d7e6055e594f5f43fefbc5add7904697 022b90003abcdffe3444bf899962aa0173489163c45d6f3a1c023fd8f089cd6f fbacd6c6ba0fe19d9d48ecb207c66a7578648a77e9c7e4475721510afbaab99e 88f5947ac68fa3b16c1c768a9bc70ebf76ccd2800e6acba428ef6d8be78b8b34 c4a86247b999e7c8460f3784603080ad902ffe2e71c986278c7a26db99c32447 1b83e2998db2167cb4f9133ec411f62fcb2246a84ec1ea4acaed25ba5fd60d52 a3480165d43b66938e0169faeb99f7d09b4c918620775b48e699b9e3e78dfe02 29 d392363e5095333117c49a962825fd195062e800bf70c56113bc43552e51860d238d88360ab32c01657adae7ef564af13f9fd4204866dd7da5f17853bf1a23000415bbdcd6d894bc056d377cc4ab1f08d694bdf62c572f6c359a914c1351a50b6d861bbe3106919d2f7d88c9edb1de76b8b6d12807811967ad84e42d04abed08d378f1467bcea70b154150670ff65547891b4857a5db01ad7b57ce416bef16037fa3a58c66852874e413bf557bb47045588b279e56517f12c1e123cc9b4fb9004e922754f84435d2a6bba08b1d08cb54b84cc3d64c36bd893039466aebb48b06cadf8468100b5e921eb05ba1ca821fa8e6754988db9033e3af252e66def1d308a5c106a7964734bab8c5678acba8f5b07a39bcd04126d2d05a1936e7e1ad570fa8b326e66fbcb73b86636b12e7cc728139e4d62197f428fece963074cff7b30df7fb235cf50a9e6a2c7816e0d21880c2191a94319a998c32fbb01174cf3f660ae8ececaca971b44fc0a19944eb7b48348f8da3b0c9b4e7e9ce4f0abc618f4601a815be934cff18e9662771b0039a39168c29e2ab2b05baa3fd8659657f5f4c00c32894a8cc1754f7ab3c13d06dcc53276ef617c6382fd1b4bb4b601f688aee0c23890314d6f4509ec1b00bd8a3df2775a5032c54ebe6d1aa6c9f129f4214bb0f6accbbbfb7b9b376ca44c6f72df7c03c5fe7718292c59853f6fef6c91600cf0c9c1476b2027ef8f475e15da2a8df91929ca0f4ce687590d95ac9e6e2d0878a0ad8c38092dbc484a278b1a0ae2da6e9b1fd105f3454dbdabc11c39bccf3302000ec9ad809de0b247f86d4e38e644ff7b29d52cdc5dfb23567232955dc7171690219f164a52b7c37b2d59973e1e58cf76cfb38d02b59a206d212093492442f4705e8969b8450a74c0dc4d9681d43ecf433c4e72ae8041f2fa757c562715ee5470aaf2ba2c951a8c7d6bbf6fae29b2c6ffc193c0af2fd419c2e87d6703f47465008353fd035ba7d3e29b40642d905a47235045fac3bd0d65c186fc83543e82fd5059f02cf54a9998ba3ef2e3ce397fa72260c64ea56674e8e9ef96b34d3d05e1e01373c5ad927623a312281fad2b6d8d0c4292917304c147df8e1aa37e6517cca09fda6af031fa6ee63e0a6692c9cef71143458ad073e3bc956d27c3fac68358606b1efcaaf2118bf88255ffe8318c1472d7ab5f4175c1266514a06e0b8233387025c3f5e3c9d46429925800d464a5dbb306cf680b5a8c6fa047fd6cf299fca380f4e67a7ac6cd1300b79a1790f1fbc535ec33969dfd79f9b6311e93f8dd35da50ad98a60c96327e1d573de75d5197ac694ac66774fb4a5f011b3442462a9c658022d687fb6ea3dae9c33505085ba037046155851720940686e88085f18311f5b0a8ee3858eb99cc087b95950f355f980a4f96d85f360e43762d7047d27c4e7dd0d046782e297b0ec579aa52b0002c62cf368259710878f3b5661af152457f28b001e1e243964635c80b1721b4bf11e5515c972743b9b33906c36f9c89cfd7c1b056871b6ad76d71cedfb11fa2d29a5ba3d309c160f90c4f48f1718ffb2310ba7067d769e772a0f82734091062885b0f379af0dde6090751de1f179853e48752603b03671cded7081c873b4de5a61082e9bd1235f7abff43f052b5457cbfcb8fa074555384a9cc8722d3ce79599b56777238aa78c09009ce198a57a9160206bfd08bf4fd8a1d4f2488174c67c49b39fbeae0ee42f2323a232b0bf380514b120960212e1483a0db6dda991f2c8736b9df9e7d31c981d7c928daf12bce0b1fdd49a0728f9e00861dcdf5fd9b15455132a5240d5389ba594f15438bdac5e4136181806c422e629d74126f876a0a5d14b0f7544980a085ec1d119cb9fc8d6379577d40ca62b66182b2e1790f55dc0e10fdfb3a8cd7b28da07e78512d640a1668eca950c5fb61dc96ba0d777ef2287b042a10c8eb9c526a31927200dd1097bef7c25ca01eb78c3f71630b880ac4cd2625ad980c0d2169671c8efc42e016ee7e5508a9000ac015e392716b3b9e7151013725e06745076684abe6441cd18e554799d12f70d9f52ea2355df3546b3835c7f9705c6ff7c9ffb41ff3b3263a9ae32eb7039f70b9b4bb332647fb99d7d61d05d38132aa68261f94bb6ed18bf100ecf9646dba1017ccf1e9aabdb9ead1974eb1d1c1fc9a059ab9788c0b201d8e5de85d76642e30ea6f7353b99dc6dd80ab0a740c50e0ea1e7151e318007dbb6d51fe42409f5b40a7f6e01bfabc19fd3149b4248e25b016219b99d340acfb3d9bb716afd8731570dac6bdf299bdb7e4515d8e0eb1fd251506074e08db975a975e620a5a31f9d7b0aa6296ebcd0d3799784a3a151143349e977dc8bc09ed6d89d0d62b93d143af50f2b6800dd90aa984bf33da5e6881b8e2e541f3bc8d8fc2f789319314f8ce8850ed369009d20ffb10daf1634e68c3c011dc8d8d9d2817f759b6e9603d13f4b740f71280430425ede8c579f344964dd22cb449aa31f64537414a80633c1cb02010328a7b38b703bcc632979024c62e92715e8f2adada6dabc007b8c78675991d703b2b935754000274bbeeeece5afac04415974fa15434575878f3006ad4cd389031832adffab26b1cd6d155a7ddbde35e3b0a62efc05ab8684ba374204f2336c0d00d1c192cb0a6d854b764ed8d3f83e2068ee49bd07e128ba615777ee2b7f4a0090a42dd8186a0d1ab8b906b554aa4ad21129411deebdbdcb856c177981cfa400cf9571db8d53f7ec1b29a9a9bd79f5df1139b42e2a2584776d23d4b43ca23209a5ff9d6a7ed14b42885adb3c17f3da044059a23fabc7e7208de27365612cdd0bd18c042cdb282a3f7f3f16bbb79113df7b4d2182f1bcad7d695882cf0607410cbb3791961c3ca45b5ee8a18d8ab6d14f7aeff98294769cfc0e75b6c03ebe9102234c1eb380868c0f247f5abfedca6a071fab84bc88dbb249bad56fa54e3b5408453873905b0137da3d5e29d778f37a989d6480d13e4386fedbdfed3578426a0619393d81047fe2b099ff81b61f41ced2e97ff14477fa6f506e1aeb8fc9fbfc001d77fe4252427d74a8e231a95546861d0c1490923e6aa0458b24e2559d95e60c9ba5d9c8533713c8fc975f18c534283b95974571a78352d467ca2775f64e2308 +generate_ring_signature baf768d9e42fae2c59729a1d2b8c1c90345ba669b954316a5674d1de6220a76e 4d7d7d439f8fea0f37accc6bb4b1d9b3d2c6a8f1de4c4080d058aa9aaddbdbb0 1 782b450055215a1e6bc07b6003187d9560cee16e6f5262521df26ece593c89b4 388fafcce2f0aa9c54a2cdeabc47075bc4c6dcfafcf8bac5a99cda75c3e61b01 0 02c92f3789d4e579646a7d07750ee92f9ca4317517437726849c661714511004014c8289905755fcba47c89bbe6cc437f0d54b346ca4c961c5f68bc311c54f02 +generate_ring_signature 01916e70c1a168a97075a7d873849f7ac03e65094ee16f44ae66ad4a3e0a9a61 19388d755023e1604e7a357953c2692ebf537afcd3c5b175b18b4480c1770ed4 53 242cfc91401e49fbe717545536ff1288d9929ecb3fc5fcf431ed7e457bbc4b39 5720bfc3064c22d0bcb46686feb470b9483cdec909c4b70c63a8144c603de1c5 3144d1064b96500b9fa8ee6ac4f95292f6d92e7c6ca34b5974511c380807739b 90aa403c95a6a5ea6866ce56913201a0aa37d5c09e3e0c0150b8f23e6a8f7074 29a6167a49da7587f4a4a05e534e194f7fb0858c8b187e681104939611678220 47a0530a95b6e548ed923ddaa08d8cec94bb9afd43a716602c73f7a563485426 d7792a71e94ddef9dfc4300d460fa547d0318c04a0f43513e98fec2389fd03a1 84ef4f5e3c509f8110ea7239b531431da9420ef98bef880020ef1565915a9a10 1a32deba9900d23de6dca4cfab511391e4bd2ecc9d153f2cec3a4ce4fa4c54df 371d5595b2a49bf72d7824711067e3248f2429e086383d77de2035a5da111c25 68bf85ebcae2c713975dcafc9200acca99d4d740f05bca766d7eb82391767f66 837dad3d55f3fafc1717b116c0f7e7121ce70b4cfb542b5452a08f92dc59ad55 d66ab88fe75167e16bc30dc727e2862128b938292e5bc60a5eb03390edf0b133 32f67f886be12e0bd1c98eeeb1690acae74e7c6e321ad14bf6dfe7bd843176a6 572c46495fc92467f1bf1142893e0edf08ae501f806402ed1b8ba58cc767f8ec b845884ca93520147dbfcc37a28b5d899faed2f821235f2b055ff34d2ce0ca2e 00617cc79d54d01e4bf16be365e673c3cc6bec51a5c337fb736a885ba0acd573 6a8278978430c6e99cb857f4e4512e8278aef7fe70e4b2cbdb0aea6d5baaf14f b0177887294e8717c7c4300e3daf4e5d35721a54fb85aefb99954ad1cf15228e 5d0a7d23e13f32762fe5e66ab9be9aa73336f9c385772269046132a11795caad b229f7653c5630d1b2ac5605a5b2419d7c8ad9879d6d296eddd14a1ed788eda4 97e01654bef78ba3a81c4bcb36b07c6dfd723a867bb2d1e1009574ca5a4a4444 05a16ea1786cec3520ded847a0addf9ac3dfe96c3315e785927d75834f73b5a5 995498a9ea1ba686429c39efe8fc92cc2bfe7a4a3da23891b302d56b18c61075 e4f2da569effe699c788939b58b7271eb5b63347382d7b9fa650e0c16caf7dbd 62b2acfa240fdd2888dcd3ae4b3b60d9aacf48d627ad4909f0ee3614d2a1d8bd 6d52a488709aa858e528c36acdd35cac6cc7a1e0d612ea4dc68a4393ef095a56 da6aceaf9e86d64910f2f90e7e7d30a3459260c9dfbcf427b0704f5d848ddac3 84c11c1ddf0fbe484e80c375f0bbe985133c72d3be646e4a62691b3ddf02c93b 132529a4a7796849c67315835700cacd444e85a11b9e71afb5ca41fa81dc8373 69d1d9c94d25a965f96c89bdfe92d5bd5a10a145312a46d990d8747d9b54ce72 a77f3f1c05b8b70a0203e373031adf0596eed28b5a434cdf0abaa7c2221c5a93 a611e3a402a42a33cd8f832dd46c794c6adc9df2bc32747686ac7614a72d0c2a e8f60d367002f5fda4a024992dba1b161fe1802e680977b2e2f55a9c3deb27d4 e887fde0d2c22351ec22b8aa8889a80c0917613ab397c978b2871af576c76fbf 9a90e74a7e602b11e1085681ef5e08a59827b7976ecd8e14f5c7a81312a9b84f e35b60b7564725d9a7dd34a6ff0dfb5d488e3cebd79f8260a7057b2b2089c233 71a3cdd1e3f0840ce0cbbc9049efc87f376938c4a6fefda0e4364684176e6bac 6dabcb53034fa276be2e73851d9a39aadd74b3ac7ecb0eec92b43608cbf4b02d 13477a1e0cfb62bdeb1a30889489446cdb3e37bed0e868906ee91da6ee4de0aa 1bdb6348c889278979c6064c256adb5e3bc76b61e332b2981a49fbd79a14dfe0 e3c6ad547fcb3afd9dbce9593931897d8f736b5044f543475757c7775a58168d 379dfebd4d07db29982a708e4a03ef03a583e869e704f36dd62da8fc41867cb2 4249977ebd5483286439256595142ce68bf2a88d40fa2a0e204bb8918b2ab1f3 08710fec6ed8004733e622281bf186975b7c7ec6e2a85d9cd7fd146f9386908c 0ea6d13d9634d24f6aa872f341b2bfaba220045e6dfd752f0746cc1b5e9732b5 201ac295b1b5a10a4317748a29f94ea0e5b6b069a8759eccf5bff9067bc1c829 623ea94a4d6de8a3db5e0c19026fa2623559fa878030c98495111ee9b2951247 f1382fca2d626d971af139e3873405119843d0b0237b48d08287d893e7f003b9 5e536ecd5570c8ae9165916d9f14688dbc8c82130e1c589e23ac5ecfa8a39435 f18095254b9f272c5e5f10322cbee3cb62cb40e75a900bfb69b1557c254060e5 d1c0c862d42a95b7008215dcd1cf6c4516df9830ea11c217042d0f3df720814e 4eed5da8eda2ca0a8436e337346fc54f3dd38b90748bd4023580e7fbfe271dba 8b58a9e402a6a320edb50825a07279ffdb434d5bba8c2b93bdf568144e098a01 0 c99a49941b816b7b2d4d812ac29998cec68644d61c7b9d00447960fe098a8c0f1f7b2ae405c3b784f9aad17963df6a69a20db822e1ddb2711612b0295d7c0f0cf40fc9778cfba5f0520b2b6c19e88c67f63f36a1d2d3455b40051d095ecd360a0516cbb8a7c86ecf4bd9987c6bd981c3abed6db965815b0ec20571c90016380500bae8ee2cc3dfa744dcde36255aac1e5fb795617e1e67d0fc9e8d766ce26905dd1b6c455f095435ec412e7a93637c734e810eef1c862a51ab12370662fba80762117a0a65481b98d7f92528be2469bc9b7b67779ffdd06b7b953f29fa040807840913ee988b4974920bfa08e71a8a09d43c38c532fd9db09344390a610e3e01d8d27573f8d6f0618b79ba6cef66470c646b6bba1b8501b57127c7837b24c40ad3002e6740418aebf28bcb3d236c8fa312a0dced5fb5e30aa451a5179da783006c7801089b53a6539188bda423be7af7c42a56216cd8f74d9a2878246d7867026086e912efd959ef41b6974a413e6d5ec54fb39d0caf03e76d6e52f2ddc1b401737b847da8c1ea3a26ea79437875b582fd22c2a8c8a1982f9925c70a088fd00f5a60373e26344f28860ccf8e6ab361676e918cb73d73c3e1ff18f29574459b076522d6b6a7d7292fb7bbf143a8c651c14cf179ac582a532803749a465f8cce096064409c944aaac8933c344b2fb714645dd9dda31306ee2b17960929beeb13032e058aad5888297a1fca21041e51cdabb38157f157458d3a546480d1ebea0c0c218bae518c72ad1f096c1ae339a02933c110121f1d28f53c7d89729bdbf2e103d117eac5f5f7a0408bd9d1a702e25142fcd9ec521883c11f818ac58e54f00001093d6e0daa39a484336c4aca8c444a093794d9abc3c9bd3c4f89d46d64af040c8cbf27dec713ae9d8342a9c5979735e2726fe7668377ee37ac80cc7a605afa0704983e5ce71c0ebf5069575eda2f54396cd2d1100adfce24796c7ddb5632ae01f3cdffb60309e4748f4b5c8ec7eca298757c9bc9f1e73a843bf65477fedd0e0e5a61765bdcc15bf9cae2df7be445b91dd80855d7570ddadeb318c1786d9e4404ebc558369b09a0cda3939cd9e7ee6eaf4e22e4dc3336e4b7650f347c8642df065f29c55e9e40320639aa11206ecd5de22297c69bcd781b3f42e565d3198f6607bf192fe5f4aa21abd106ac2e093d107b243d2ad48a2aab1b3b5832d8e472530845e573874cab57742cc31fb0b1194f7e6d77d491dd377b55fd2a780bf8e3cc0791b6529f5897038e98e2d33d3f4465800c67671c5cdedcb21c2e792ddfaa250aa4eea5e7f81b56e4ffb717bf0228679cae32ff073e0f0a7fc6a7799de52e49026738d6cd7d1598c840360cb5c168d98b86365817c50427f30d5e12d60280dd00c25bf5199c86a8f58c7681754e6dc737707a6f55347ffe409a04bed4b577bd06af96d8545c8c0cd7968f9be5f7c0bd9775aaeab7161604d7e36d0b0c848de30002807e8ee3a5045d591489e0b33169c5882ee700cbf2570a17ee7cf142ca13036d816b9aadd06fd77f43a9e0b40b7d229375a7eb5f6186453d6668fc18683609a28007d19f1d56a08630da9a7e4e3ad2e70fe9247ffce23eaaa6b74a33346503623cd0a1811c329a25b6850a8c2efb3001da50fd433e20a85dccab521d9e6204acec3558784ebfccf56114aa3ae7f69311fbbcb8d6d6b0bc5fbaa281e2abff078f6c12c4a289d0211eb036c8b036f306b9b6c32c88d3731f27c7e45ef27f2b0b1d975a5a614ab986d65586339115121dac6fef2dfe50431b6d1b023b50808002eb36beab4532eafdfb967675647e4b6d7310e902210d22d125173a817146e20145bdfad526ad1e57b57dd6bcc86fbc9e8b44051f5d0b69128aa3a965200d81036b26ce7f4dfa4994acb50003f8ed28913cff52a9bca774535ce8f78045688400169e42475e1174d5da6412e0879aad9fb77add817afcf783d9ab4ee83aadc501eeaa4939036df968ded9a4755b2d757999c262e85745fbbae746e5e50165b60503f670cf0f7792d56112de68aad7c1fef98fa01ed39375d0e9855ce7c032010a902b51cafd56d37364eab9c3ab21f648b159e3cc082d652cc8bd21754e2cac040f838be62e832e995c50b0610e5e4b3e767f8521c1745a3e63791a36f8475d0181507f31220558f352c2acd8be5beb2bf71c0c20ecb2439b94d3db429797eb0058e4e7894d0aa8313688b5ec6df0823783bf606bcb14de2f040805c9231d7e020c66b902affc191fc9fc25bce65c42facf62f6a76892c054a5531b48b0d932057430e5f81cebcd9bf6c33161f21b5fdade5647792c9271bc592fd173a363a00a0460f0c19dbbf29ba107026cf0cf172b4c7ed9cee9e9890863c65d666f205302bb6af64a9698ec2b1dadb2eac59438d6d3c6a4e6fcf79ff765cc9b28efbd8d0b8034de405dac0ca7688a1bb9e6cf5d84c4f9865fc86add46a2ea4717be88d00ad099635bb30467bea5a53e6918f3d9a9616e26ae2553cb08c44c4332bae35a0cc151842be36c98515c3c08719740651784ec93d2e2a47c7be9cbd8c71473d90f21c803384233e07bbcf10964985b38d7d935f74749cad59251153f4a7d27ed0c4ec1276018522f6f2ce46a97ca1b25989ad5fe9b92bc6b1396112df79ffb220833d75be1a6b9d0e6d17314396d0320188ded49127b721e113d51d2eb3ca6fc021f91c52554ce98b54bcfd5d4f3329fab0e03b5984aa08f19dfc9615f5ef2630aca7cc525de7bfd0ae0ba54aae895fbbc260cd2fead7b5055e0664c2f0ded3501c78b6a530857967ba3d942fd0ed3d0796a11c03c1f86778b8195fcfd84d952057a533d04d748c77c0d365b77f1c0dc0dfc69cf461580562322567f8b0f460504007832dfa354ed18ada7f0abf2ea030e4c8681452c063df17597f74130884e0798a29529b624df50c49a3ec4102e2db13848631a78777ed6df003afa0206d70a9e5d31e059dddd0206dac32bf083c8e51f26cd53006ff2aa45edddc588a8c103c611025b883f9597fd32e1a6c9d2b99db3ff6c43bee87c0b55194b0b927cd909da8475b2a19a24843a492df9d46dce549db892c5aad79653469b732b794d1a07b52f572b6f6abf3a1a9fc4489bcc30ef9f3444261b944a92d5fb482d50ce4d088a79c14cc07953072d778b0b9dc7f6d91b4aec1c1a1218d3700a8be986d4f20171e51855cbe709567090f2ac9f50b98b990a66b25ae90bf30c8260898c3ae10fa033c17f463ad520bf60d18d159c1017fd1ecbfc4159fd97f7dbe94ef5e63e009fb47b0844893954c5edfd40f4c11840117a275b76a19f484a0943422b6a8e09742bd7745bf312b40324ecf9cdde61c7b2b7da2dd461e5f585853eab3556870f81ed26b26954c4e70c4ada951c3a81913cb5e01816f554c9c3ddd9c50480e40382a826235cb02887af2c37c9f8f983788713b04f3f3b8bc8c1b3af3ae98afb07e07c19c47559130fd03356d8ff2e766a0af558ec090b3fd13c6e4cecf1be6a0e37d02e193613c3b4df12a4d7229bb6bba87caa16d21e0bb6a447cde94a5b210fe1bf41d1237318d7cf841c2c1e88afca135b46ac4d3e48df0972841434165106264494106387b6d693bb7579e71daf6e4d220d22961e7acd111255401300c4039a0ccaca5a4eaa7d2483f41df06cabb1d6e35d4ac321bd13f45a0360a3415506811ab32cc6c32430c426ac484d12e6125ae53160747d76a2620582c14410d30d4eabc1ca13e0966898282f9493457b1472fbbb57a7120ba8af7acf811426340f658a0ca5911e76974125cac2006093b71626d6883d8dc82c23ab38531f17d802000375368f07a5994a9b4c8c651cce873d4cb192328f6d7ffc3dc32c292d47048e6739a3faeec4a0d99c4ddabfd70442a47756ee6897ba86b0ee4bab30dcfc0422af7400a5bb9ed4a57062bae7b3e9f94194ffc76087f6e986252a68c2eb520d8b4d8fea463992312272ae6dc503053bd8bd58cafbfc6cf0e778a05636b93d04de19bbb8a764f2663d63247bb7cba7392170f097795ad3e20205479b9d6c3d0c1e3d1aadaabc580112dae35ecb5d57addc00dd52d547741ea58fd017ba4e5b09f8da838d473aa5aed7fe26b054b217982a7bc79b6f1177b930c36eb5a0c4360c58cffb85abfd55a9ac6f3a9fc521022f18a377a5f874c6fa01ebd6ac2202150fcfbd787aec86c540fc64a636ca92636fcd290cbb109e206deaefc4e65b0f2e00b0190fe0dda4353d4e2a929ed9e4efac45a9bc93dcca748970460355b9632307cca776d7c41d8a77dc84396c4bbf5a9772c40b007a0df203531d2884e83bb50343a39bea1e436b3717c29c5dd29a36c208c22293fe75ac1e0ced941cf2d96103739401ba57d1c7d908d7388dd8d4daf08c1c9b678e8393614496ce46a1bd870c64912cba2d64c528955ee84e35dd9f85476de412c22056c1546561cb1f113e0f511e0216f12e7751b661832a52586fd908fd42e2584a658edb5158514f13040a77010defb6bdb5db11067f12430c30a28d2518c01ffb670e439f730aeade4c073c6537abb4fad0d09c8cb41546cf8a03e1fbd0595e71f75d034de629c6a0600b3cf372cbfeb570f0d196bc51a938f92252e661ccc023ec062117b3d28d163e02d41a651b463a5dcece0669b9278e3132ea18402986aeeca50008f5dfe9eeee09a377ffbb4e897e0af1c7d5a48c2cf87c4a30b1e56dedb1d25687520152c2b108dc3d4a7f7105c2cd2816830f0b27c7795ef4d58a947bc6476b10e6e1d883cc00 +generate_ring_signature 0fdd09cc2513c1d346346db21cfda3bf3da4d65bf66a91dd87c83fda9b9d407b f96cf77c4abc31236ec66ab0e3c56d25860cb2027897a5fae40622a7908ab147 16 a5f687daffa9505005c73221669b1a728930db51d4d40b78ae6a821e9b319440 07a6ddc48dfad0383024bd700f46f56c88129345439bda5e7bb7f356ce11c8f5 585bb3d7f53e474d75cead5d1ebd12c68757bfe231091adacb877b09e34cf3d3 bd06689f501f10bb2f4d5e3cdda3954a6d55ad18c3ad485fa98a4e83b163fa15 0908f88df8ad262a40203ba72994f9bc919d79acf8f3847c5ae72205f8ec29e7 6ada309079d68bab1123ec762dd8ac04166d8ea824acd9408f502731dda08a8d 80d9f89d04bdf2c205d6955cd4f285790a4282a6d75bb555b1342138b42c9364 77e56ccbd4d1ad228e32d2be7837e3871495df21e94dd1328428251d7bc3729e 6387f7309b7005b5073e718b24b2b7fef3fd84749fa98e91dd1f83912487cf56 6b7e693dd187ad5c38f73079c040366abbf2990dd30eee6f685f0360ba22eeaa 819f739bedd0589653cba095292e436678a1fd38767d4a6e9449f3d4246f12c8 5b0d6f09b5ad89d7cd8ae24e8ba3c2c4440cb8858c2483ff1363037491953fd5 e3a579a3dcaf3ba92fb5f57cc4469d1ac00cf048f0f3950819875b1805e43a46 0b650b9de62dd063d88549fb717d3ebb8fc15b3bf7338457c53b7cb4c2b1350e e8ce03b5b89b392e9d2de32cd39416b7c189f5ba81954c37bf64586dbe707ea6 feb0d23239826ed5813f0d76ebc0934a4ad72186f9e43a7895c54e5e03c55b32 e01f9713a2feb7d4f9a06fc9b89f1f438d990269f8650286146ccb2df251e309 13 7dbc3cd7dd0cdee2f4ea6b023d54fa01a5201268e80372d7279dae38d1b0060a5d364891627ae4972ef69051d8b80289dceeed2554f0eaeb7efe0fc75173dc0cdaad9c881b5cc5da881594eb3aa35439e80ebe3cab22c99a5e927ecafc0b7d050981d651ad100f90c81ad9fa1d8a3c9e55162253d80626712b5076c34cd82e02ff2cfa0a9b141bd1e60c83f390415aa89c6f45e543e1141d60ff7292a240b00cb2042dac5e2f90f800855b1f46ad67789bb2c15a413376202a7481a31bea9b064966cf5b5c8b88ef8149963cc3d486b8f2b67d568b3eae8dee0cfb88ada5470d0f7a843eb7aa0f241f6ec12cafc3605ec246c3f53e4e9eacb3fabc1e2669e20a756d5b85a68e09988d3ba58fb2891208fec425c32e143f0eacd1ab18c45c4b04ad6836757009e32b1e2aabc93ccbf920141645ecb84d8529b1e80ae4738ceb0c88e5edd988e61de07166ef5fa497f62246508e2390271f14603b2a5682c60b09fcb7053857cb24b29bcca1e9a1bbb372dc55436871199caf0c06ef087b08f40531b28ca60402baeceb90602f7b013f450d153d770fef8434b881f0ac3ac6410d038395d459aa07594c3b18151ee930f4e608faa998739da5502ba8d10ab66a052f72ab36b4ebf52ce3aaf1cfecdd99001448c2b2705a53babcd9a4a303ffc8057cf9e6482be3c3bbb1225e1eec07412028f9d7e00cc59f8fd800c4623023f2051c2ffe5b0bc18048ed78196bd0b152269f379b23eff10e6cff2a367ec69bcc0e6df5880402e32cfef89622781316ab6a7d918ac84ba7c2849ee0a02fe1f9c40dd2a5af52b04426b3b7588469d11c2b9ea8d113025e4b2846dd998b9629ce4808c8dc582dd2af193f027e4b1207f71fc34ee81586813d950275dc33610b38aa03524cbd0e5fee5b3ad6f6ed4ff907233c7ae14b3849782e3ac2b5bc87dce5680ca5146536f323c0d7e213f15cda539b7ffaf6eb1707077edbb9e21112a615160d52df5b4866199da8303824879cf62bd300ee15362078d7996c14ba490e90ec0f42cc321dcd24b226a1312113bbd2b7e9044d20be8c3a505989f10ac9ed30190e8596691a8638d247700928d36db4d5d3b3fe2e5b39ace8c9263891bee7e43e0d172ed241411c3b52b4867601a27bae38d141c6f34dbfc4630fd6f523b7ff430c3ce8d644fccac1997895e22b03f12710e9418d03155df042e2aca01d3d3ba00bb96524f479e199caec5aeaa03ceaad9500945df5a59f579412f5630c725fd80d8adc31ae1a5556e2f1758c5bd4e5f43618dc135c997be33dfd07c9fe3b7ee70ca45429d0bf98375d90e5f5f682ab1bb3eace739d95f875090c43ddf426765f0583ed1ea01096f30dc3ed33b88a7ae6a88cad49e9885fc74501ff1325dbb02f05ce5070dd2854c66ec0a03b256d4598b26bc073f9161c62668f16fe25a641880d +generate_ring_signature e3495fc2ad438c8128a655249d4d6b69b6c17ee1dbf96ed1acea6380d07fb724 2adc1d2a97ca897fe0342c2165b8ac198eceb0374a7320da794d1bd38a45c962 5 dada0d56d195390308e9eb9304b877ed930a1c15de8c0a28ab04066cb0cb379b 85e9284587832bd7e59fbd7d3fb9b37b4b63e801522f187fd5bf45cc4f5454b9 ca11ed3ebfa24d358807b3ccdcf4c623af574b8c07c825b4b4b6f68cfbe9bef9 f77887b1191a51859ab5bfba228a360ce889059a60aaa740a5de8e9d0a7a1e57 c445962d9a4260693d6307b3305fcfd65807ffaeaab251349e02ec4dcb4f2d02 5d0db6d9854ffe9d26d8df64f9a0f5ac01aaa30ff2819e6377724f76d5c8d802 2 5b14de234b81eaf22a7a339e9cbc1525f160555014f1ad0ed92aa4f2ea70660f91e5d586c0e2b8055396813a707f4e336fc1f29ebf23bfd43e87af0930ae000080d19fda872b57d018fad4d217fe1b2f30104b9db0f7643c649ede742bb33e082cc736c78f5c52f8158c149e06496e58065aca611b9233398c03a4fd4de2ec04ccac11085fc697e60df919fe95c2f405ae3ca5e443d50d3c5d56619c86c0b70f15bc31f4faa970f4ce75c8278dbdeb50fdb56e1112caa684d486084a3d2667051981a48729a575eefbcd9180bd2530cb4f554880031cbec9c250f4b736bac10888c97e0c0c673dea61e28b45cf86909937351d8791a49f389e05e612dee52f0b61b053206a9c88ff9e9bdec0c69c14b408268edaaf6d04a21917bf05848d2d0f0c3dd76a5067219510a382ef3414512994004bbc36c28098bbca81f7e798a903 +generate_ring_signature 923a11626de7b0b613c07f95a600a1ae1b62ef2b0bff338120f4aca08a518f0f f12c207e70b2dd9bbfc6988a0ebe5f07f915b5bf2b1f1a8ba23c5db2475e8d26 4 eab9a7d80ad2d7e9060076bda332b1e2b31860426710e7071e5f34afeccd51e8 8d48bb5e57d8c7b0950384093d6187ccd03b0c535a0edd6da35a6f015f928cc6 079e64c24eee1da696543bfb274ead55ee33e3633b9601d9e3512371194dd4f9 6348488a0884315336961ace563bf106bef9f2c5e745e5204531a3e00695d5cf 2d4e461db0a3b63a7c05d4699b1c790f86351dc1fc96d1f8365ebace89d9db0e 3 b04dba2e3c4a03a63d72d1220c6da3073303afe4f792b4416907b31d8697230672887657cd684132bacc87314a2ea693ff6f55f006175965793f10dff6e3960b60764dfdc141284bbe78d2ae1c2b1431a16470a1cd563992918b565980c6450c40d957ca80dd7a275c5069392a5f1de2094ff2e0b5154798afa64e199cae9107d34183134c6675041a3364fed3b7cceaa5253b9bc99f8d7c3be09bfdd130ea0c59582971248b038956be5aa44e9437c54f2342c6127d312e39281af5dcf2020657e5f1d0891eb5a46b0b651405ed053a4ab0a13b0e8da31ec2439899e0f2300f7172125dc4294a93d4e6527c7ecca987951512aefee33a27b9a7a10eea2ed702 +generate_ring_signature f7eeba3fcbdc35c01d69774f6d1e4ca270680e87e1af40b2773dac9e9b0a56a0 6f1f04eabe8e9213c7c5d4c4a4df1b5564e63b054d3e09ad81eb6c4d930ef44f 7 ecbc3d0e415e2c5360b40747cf604fcd6e4751e125ce2ed8f7922a317bebe282 60887705484f05a205b5e6c98ec1be1df8cdd4115f0f3edf9b545370d81b2283 4310521f1828d60b124567720d381d203d81d07b8c66434011e29bda436bf7d9 4280fb5b19e595916a02527cb77814868af83620174dcb21bc8da271ef680004 f2f8b898e39ad301c969cc191c11b162995a5e1f813dd63aae200a718c7cdb86 867556a39a4dbde3c7fabd5180eb0e7ce275ea211db2fe90e13c4c040c0cb28d f6c1111d0bdc89c508faad4ef2015ea98e1f5416324def724136e030ae647603 f01ce7ed8d9dca5629b5666899c8aff6ce0b58ad2fe04b77ae75c2ed6b9de30f 4 02736e71e54f4fbd27e02289817995f7ad15b50fc8a2a27be822acf7ecfb78003e829d6bf32e4aa8b64cbe3a66de7e76ec40f0666776e5e863c48d4115fbbd0d5ddb3a0adb8558054102c34a9e9b5c0a6b4721064c7d11aa00080bb9ec3d11040dd6d8ed85c0fa1633ee2c1a7688b8fab9a16ec6bfc42243c0a80c662d20b40e7ca9322bf94591cb392d2f1affb4ecb2b3f0512d94571088a775af791e4603051a4707901a550c3104de4741078ca43b456fc9acbcb67aebf46856f2a062440846450e6af6e635d6e91cdccd8b7d97b95ec5fe0a6fe0616d2192c27f43786f04df12ce29b07e57d97f354a2377a29fed4c63bbd9dc2cc8ece9b07d8c0501070b4c9189be08957fd4d3fe173ba27906ae16bbe07a5630435c04abcf280f18be0b72a12fa67edaffc7b8aae244354e04cdb18dc478e4bf804e70c2278010ea8d021ef154b28e8452c201db3f644282edb7d04330a2633c42917bc07bb1980b550d4ce481c6134e6ce3805de3a78fcae1cb255624d164349b8995ba13c3bc1aaf0a3398bbb2ad49070286db8f9a46f17f6ed2fc9fc1518156dc6c1395685a0609023a9f21b809008e97832399710ea9e0d1c12f4456a878b2c5086e915166c11c05 +generate_ring_signature c4dee30ab0373ada5dee59e1362d805d6a2eb83f1a878dc9e82e1e9dda566d60 66250b52e8ea438a69f00cec532367c889ac73727ec2b41f696bfcec68b5788c 169 f2f2b60d7675c181f68eabb0946ecb76d12c2ae176c8d7f2b2f5cd7e5390b732 743abfcb7c102fcde3281f0989bdf8aa23a38aa28370e9caca172f5befcd9fb1 6925c7c3b98df3427d346866a2063fe956404bf6dd718ad32176af5f55fa4932 e13d9ea26cfc623476efdc90ae5e746d5c01ece1c662c1b93e9cf19a70830b7d 05d454706821b18b611d100393ec3307138bc84b0c0958cea0bc4eb1e9341236 cce2645b7ce500aa4fb89088e6ba8b90d488e7adc3403850b6fd762500c3317d df18cc2a78fbe16f092a779a7f0503cd26e45a8258379e4535d97a01e4f3af7e a9d9437498986268c6e2594b4932f8ac8798254bbbb9f17e9fc5be12aa35beda 9a8f7b61754085f10a5ddb5a7bc293ad28e8365f8b51e94a18e974b7b536a883 3295ada3db3830f1a2887c4f1403eee920a836108a42a748414da663e7fe9108 80545b9db676fd424f717135f3978b39415e045225c2aac5f340af7169e68b06 3d9d86d009b0be89558db01f5ab33c2bfa32242167d6a7afe06ac195f6c500a0 37662037db5136dbe094d1eac43c18c9239969f9d3e0039df9679cfdb4f3d18a 3bea446ef619e281d5fc24c358629581d78385b0556d72fb244c66d97e2c6483 a28b168bb36453c5fc8ac19c55ed117077e0f450eab8972815682e1fbad7327f 6e28882488bb1a06b52d716767a61584235e7351b839b84fb2d340230dbb75c7 52a7690a81457f57c9e79fcea48a019f3bd405bb6b66e61a6f63d9151d719a7f 9a80b4b0f25383a2c2f70d94ae5a4da7b15857d3242d05669e84f02d66e92edc a801c63fcd5ae02c607cc766f3ed531cf1e94316ef2d2989ebc611b200a300a8 34e4278c824bf5d404204de86aaa1a806ce70fd062eac373faf51353e9fa6202 4b6ff12fb5ee85425a5ef473502e22bb78aaadcf63ad4d93ed327bfa691d5a40 27dfd189f1ba9b2fc2b0d48bc6086b1a4f242130ceeead85acefa3a92ef86ce1 37b68e0abc377dc3c967591e5615c78e49ebb08f1b77952b5bbc8d9696f2aa7f 6bdc04cd1004485d5c703f63811fda02ed60d3e90e0dcbbc4e870027807f7db5 e106081b39c6bb35c5f5607e57b1eeedfba6a6060f21ed360faa2a8ca5af8d1d fbfb46345f0bd2e1711359b292ebf8bd6a7e39e531f986591954979fb09fbb2c 37b5b8821be52009c9e93c3ff1010474644f5b2872a8736650134e21b387ab31 c83fe1124f489b72f050473d52932fd5d68f2dfaa2dcc21136599cb918b135b1 cecc1ee7fdfb34c04581d11c61b300decf57a42e280edbe70320993be72af60a f2b51106e9a9d3d144df1c152a80a090331df2efc91e310403f0a05b9eee87be e17858155d4549918dea501437c1148710a310d0f90620fea070e83e02e53d12 46b090083bd9288b6acc4812e363601ddc83c03ea67b482eb55d2a790b77e4f8 bbfbcc1daff1f526118950dd3e2709c845523e19026123c5369a13c4d59939cf e075c3c1ea09cc5b80799103ec90cb60576c33c3b93a73c24b0d1ceb45d295f6 af65af5d55b0d0d15fcba45eaaf58ab174f985bd4d41c2d20b7a4526247c9714 80bb8136d6e99bd8016b594c39e7b137326ddb543eac6fedd100dff6d6b4b5b1 5339bc37bfce89a3dde58c7fa4db847a4158508bb50bafcacf80255382ac7671 c81b42947cc5f69eaa5c203eae4df3b3d020dd3a0c5018f8a9f5e34348624d0b 6d510f05dbe39d83d6640cac35d0a60068331cad220b17c520f23fa4552fcc87 d25684244293b811b3551f6dab2a5050fe9dc2bce52c15740a2467009222ad5b 9d87b136332a86b9c5bedc40467ccfb345ca8baeea24b84ca338928ec5eda14c f2e3f7adad9febf75773a3c857d62d3263120100e2022ae9b77c58b3c7b894c4 d7d5c94f7e248cbf878428a2b144af620e4681da88e766ae43b1d6dea2169967 30efeb1e0e068b2c359373c7add7676425c35d7c7fbf3bdb90b82dd824008ddf a761d5d202b96868e878551709c2b5ab877d7fe56995504bc9052ae0f0200bcf 55aa7d97269864c26740e4be038efc3b0c5befd21ee78be97639826f5f0f28ba beaa56cb576bc41b36f5751c3c7251a70398e4db0a3c09ca35791e8981ea1f91 83d7a2343fbe5165a375540f07a124513fcdc269f32c397a138f8af02a44ded7 26efe640c840ea1a9322378e8e90f84a17627e792190d3753a4d87bd730b18b4 f1a97f521feecc1049496d25dd3648443c601de11949d575b0c550d8baba51c0 d3a56987efaf33ad73e78557598c79892562eccd7a36207e1b4a8f2580b77bcb 5d74020c3d7c93bbb99d658b8fcf1cb18497208ad1c44bcfbd8a8b956646051c 0a0c3a31f1d7cdacaebb20388dab4a8ee07765177f8cbb039719985a5a942e74 e8fa5aa4fc7d0821c6c013cbafeea5d28eb6a24c9db8779e0be56f87383a3acf 78c803ef1f3df340b6cdd5855289dfde75746ae4fb6e6f79b902da3e6edcb510 5bde60d09e8518e581b09e441d9e9ee10fe68d206984d8da451be2969dc6351b 9f0d4380fe0bfb2639c08219c7c83b8d0dd4f8a37b9e7f956315cbcc91df1fb3 ee57237455930f2d6a13257fdbc4010bd95502b156592117befc744e68b6a4bc 05845a51848c70ac4ca85654d54962644005fab916c14b572137bfd21c90e893 cefc22e0ae4f7bdb5981e9af5226769bbfb4117a75bbfe9d0c0aaead403ad02f 79df1350f974a43e500894a2ef4d069347a199579a198bfbfa7309818f11cd3d 0043576d4b1652fe8a3006e223fe2907221a22c73ae9dfffb4af218b970c422b 178c74199c65363956e4c567def65f8ae5fc0ddb7aa7cf04873db552a18631bd ec64d4014cdce524f52ebaec746e4cb7985db07efee7f230f7a45ba0ebaf2667 61b2796c0984c0d366679762172eceaf6cacea13c448f10c01d9b95a3c0bd932 78b5e5e15304a5d7deaa7fb92d1dca0db3e8caf4a621596fb5efc9e45b56763a 8307fa27a58136ddaab152cb540dd912a5f9cc467f87529fccca7be31e3360b1 bce231185b0032910b1983e47b427164c87735004579b80ff136b48dca7dcaa8 14b20e79d48470cadb4c806df5af9b034d8df8097a3be1f2d7928fe34d2b3cef 4247fdc58e6f242735df1b4fe9ea9fa87c0f93ec02b7a1f57314325ffb849cad 45c59346b2e561a5ce513d69d53d60b0513d0c34fca33d1a82147187c05da5f9 5f7f797554373b48cc0b9fc19fe98fdf53fd7dac6895a3f7a7e773f616501c35 aa2bbb46678024ccfc9a9087a282316f6af2bb04c3757ef7228831d9833dbb83 dc399f899363da744d9d4153065b6b684bd658c393efd3590ecdff3d9c2ed52b ef6d0d6e6176b560256198b8e349dee4afaba86decd2bcce727dbe95e2b70636 d32ebfc10103684af4d1d40e94d595541aa541f4580b1f772655c653a02051f6 7eba6d64022bd3abc8a5c86a8895bc2997d77dc9a1945ce761b65b15da53c6f4 cff49af65ffe5745dca4cb015ff2c06015337e90d3eee87ed64de0490989c684 4c63ffd66a6dadb52cdf67ddb33d710dbccb0207c1e5566ac61f22a21bdb129a ce65e5281d0168a505605fdb278f1898e30d0a941f8b0f9764f13179b3401aae dd903cde97be0cbe8286e4fcb959f165ade330f86c365bc5373cc5d6921082f4 38346157f200df62a9caa5b51c0b39266e67e8c8b22f31876a0737ecb3924c64 7a59f714f0e320e8decd66d486b6aed8285ae48f77cdbf8db8496e43cf327dc6 43549791da8e97a5b368cde89d57dde61b4c7b1826d2bdca03c98547d6c1f210 5a8087729bcba594809cf4a31b6d2a66713d11f44282fe19fee4555fa38f33a7 80de3bf86da79e5ae3c839ab0a723291d3495dd3903c8f64a1aec3c388e774d9 2953ca5866e7d6eda4551ca518fdd1d8b88f5621483cbb9ecaf29097ef6876d3 bb9814f0e3957bd5dc7ce3fadea884545594cc240806159fe497ba5888164654 335a5909bb1f4401db26d7e55f726b209d154f632e713e1bda691e1346fb1fcf 34865ced6ca72c9e1ccd2635f6ff2a3689d3b968bdca016b9775e4df7e58377e cdf0adceffeb97350dd41a3b6ace99484a4f4f7980ba08c3c22bad35b2d25622 1095dd8c0c3555876d83821ef96927bcdeb3c33f5785b7eff6b23012c84e6bc7 e04fa71c25a0e3484b479825afbaed78bcca81d1ec16d0e02b0ed26732ab70db 383dd6af2e2638681fb025379fe1a58438a5b71ccfb44f62082fb711937dd982 3dbe16c9dacc2a7c3d4f2a7aadd7323208de7e81cc92dd4f8958768574ba8d0e 1b724b508e6f688287fc9adb44f097748eebc537b8a9ef2e5ffcd5eb0db256e6 a8ed0d0d34c15f7b9bd8539eb4f0db1a73703f7b1a684590737870417889d75c a1ab8437038769c0677d621cf9bcf25c02fd4ea19386e18e7a1cc4e27ac591e3 d8263c35b3be8a8054c7bae2c394b6c6dbbab44c0a3a8ecf0d705dd1fc8cba16 b903646b44e144d83b2a5338054fb318a0cbbaf2d4ae28f4e683241c72a45645 f66868f006d85e3cbea999cc1de9aab9dab8ed420e887eb6d8b8bd5cab1094e7 f062cc8d8b539657ee47edd97f11ff9b863157b951af13a736b8d16c82a84363 8c9fcc3758b9ab2b89d1ee8457b0d666087169ac25bbac716414ba5587047695 bfd1f74391c25ee492570d813899533797a11e321ea9e3461bec229061206ab0 455a4eba5a915e05782377566b72dab647d9c633dac408aaea6f8ba97581f044 e0c54ce9fe9341fafc56791db8d5ea68e8cbbaf222ff855120afd8dec9f62695 377c0338298c3f0f80e509182a3fd5a40c81f40d15b46b762c0e5598eed8ca41 1c107e944813fe33970f7d5cf7e1b12539e36364181450a0f60631c3b10f9813 8997bf02ac05b9491cd822642d487c72084752b5e4150b0c703e032418d754ca df6b6f5942e2fd0d674c709dc04297c935b33fb597edc3a5734af6196318a617 ab7f3b2f0558840dc839c5f281a190d8277534848c9f64534d9b47f887a54809 78ea46342cb94abffecc038e4e00ea9a5699dc34f89dcb625b35c09c31c20090 209130802e9d6511db53dd050c8c20963375343d5e47823fa970c40ffc553c3a a7b4251d7524597f481c5a5308d1bd3b3c0254d352a9a5b78f18336eb123acbc 7dc00f08f1299dbf52bb029f19685213291c8cc9508a1b2143d5e7b7b18b1882 ea3bc724e789117a5c484b5b84441b515b758399062f2bd98209706bc9a8c3fb cb0f6539b7b8dc5dc22b2301428b9e9a2f6ab08787853b664f6845ea9e85d9fa 315c2d8496df14859b7901592b800da7ae4db9f8c92653dc6d0c108e8b4e0eb2 980a0e7e3ee524d557a0bd194d2b81c5c305aba1c8c195691e4d4ddb4d257f52 41763dbab5729980d1bc0f26643e657852421493e1bdde3b0ecc756780fb6c57 3ba8348fe5bfb2577e997df67623e132d5a290c2eb381144bd42470baaeed8c4 6d9b9089ee7f98aae119f6c6b622bdba6955abe4e874a085245635b8f2b94393 4c82127d23c46e3053c6490ddb8aca8eb567ce3bb1c3972e26a4d47dde728567 5a9a20efb7bf87a0e7c91eeffd12efbbf72d7ae4c0a8c25b9d9c3a4ff8411c67 1d186b6ce7892fa7a1c3f4f00a8b1fdafb82d97e9e7aeebe18750f45d114069b f367f4b4179fa6d22d6d22a828c33de8ed0298cde5fb5d17863509f9417af0a7 2811d5b3ed14736137126bfbf65204cfe201c5298f70aba9d4d3d0470d729ae5 cf4b99cc377fcff0b7ddc95b4f4b523c2310394ca5bf1a17e802afdeb906cf32 e6a2fe52632d2367d577c8092a66c377ad37ec2cb209c7786886e5704bdbbb25 4ced786fa5fe2666af4caf36d267efc92906c327c06d449b601005fe4ecf2ba3 c742a00349add70c374c25e31f1e192e97705e210bcbe81294380e8df3802b51 6bca8c87b78e364890984fddbccc8c407e512a5e691f8c9e4e04f526eb27db32 33f41b7270fcceab849b60835b0c5b8f3d0a3362db18f6428ac8d6cc629a52e9 f6ccb30dba421f16c87224c1fc6c910c28d928947aa80a4aadebe14b5472e3a5 b75d3c6321f144f78bd014df235649645bf6eb8d15a0b412c8791f97dba6ce96 1ee09cd0a0c0ffe069acb5feba91b0d1eb78b810977acc83131b03415a3fa2cc aa4181c9559f8e935047ce91591939a372dac2b5daee47209472f919c6035a02 147b4551c883e364fe17ec3d1e9a40592cc27f8052e1fc7d17a6c5ec24e2494e c9e70b872854e07077e80d0f66a062e15c46c3e108d7cf656a5acbb5097d38cf 32e3e959f6dfb3e9e3bf1b1fb3c822bd8bb584966fa11dc1e444d2ce4cade8c8 842e0eee7a3fe30185d75956878c418aaf33dbadf2d95223031edcd9334a14fb ce6acedb380e0506c71df56f08e37c9cf6a6a7419a0a84d67421f8c56524ce82 c4dffae7b32ae71007f42fefa57835500094a53a7e59b4003da57be6d752a1df 7c3a885c38d04251b942ae97223b302ea5f38383fd01eab497709c42d5798a6c cb5531c9cae36b968f165726c3918cb6f0904779851d8ed46fd9504a90a39776 7229ff35e6048fb93a2ddf96abfd5642442d91ed4ee2928e2dd2d9819604b79b b79d0f869bab272133ec14603e03fe4cbbe5fafcd859b8751d5cffa2f13067b1 49759392147b1f835d36bb592ab1b387a433067c4ff3ef27c65046c868028b51 466ad6d9a84e0662e61b8a8abb0bf5df7beda276d68909d944a28ffdeaa8dbd1 a3b15d7dc0194fb2f1aab6a358d2b113f8e82a5effc3640a89671c76e6a70dce 43b84023745566f7628a0c30be507cb86dfd35b80dc8eba994cd1d2e0af685f7 b8fdd27e4e758747e0d303623d0eb13a255037f5154e0d869fcd2912436d0036 1070a72d4d5efdbef3183f5a0ac7699ca4f91f3d17883f44bf7fbc51b1fae1cb d4506ec0ae0bb3ebcb7d481bf5ca8a68e19125b15df4c15d955dbee943294e55 858799a67150b2fedf3544b0f1e6e3c3d26f7f886926f57f53dbca535c8f6cd5 3c2938a328956c51e42ba52e7bbbbdd2d85cd9ab1807ca2451822ae8002a9f47 2a1e89c0299dee6608a8652416d21ee18b71282dd0772c65d6d2af8174de8890 c710afe34c83d62d6fa2713f8ecd695ba6f7c3556f7a84f9f9e817abde3fcd14 9195d5d5b1a96ddb0f8366a2ff9e0ba783767d0bccc52449136ed07c05eb1729 8324d8cfbceba7901fb55976c5fa6acb13005fbd838dbb42e77495c867adbffd 5dc1c7243b65a5a6de9bfe9493ee49c369548a1b0f7a707c50b49fd0f9273e5b 8cd9443a7faa14d017876ac6116a4de3633059124c9f55e71687317ec4a4d4c9 0749cce6e8c6eb0b30cc9599b9d1e2e8f536af0a52e3883c9b1a0eaf60bc61ec 1900841d34f0df254a39a2d586c69ea435e108c903e9dada712075752da3c470 72fba31c4645db0e3fdfd6c4bd4bec66dccda0e3b1f39ca0963dd6ca237eed10 00de416b0503948f1eedb67da56b1b6b529f648c69f43bcf1a91bfe88a8c0e15 40b401518efa872876a64431ac7463a297acce71697edbf95bd5a4584385a91f 6300f0d82da691b8d88cfe2e2766f7547cf1f60ffbe70ab984cf1b8946334fd5 fa3eafab921b0a825cbf4841a68094cdae5734aee61725ae8c598ed4f66d43ad 45f89106066fb315ab9004ae5031b1f914599c3b0d9f59cd27ae15c9289dee0d 51 eba04041b199c295583b3d5c47f5f3a4f37a5e6ddda05be78a1c0a7e3e3bd5006c59410330fbbeeaa2024d495e77d3dd82d7c629eeff41d06ecfb2f6f0bbbd0bdff3987882f06455af41a7ae98aee1bda15b1803e25919632fcaba14f391ab05538366e6a2c971abee38a12580f1c28a313aa08b80347edf8bc9ba97cc3dec09c9307b37fe6bd16b31b5aec3c432ddea0083c6250758b0ab710d550e797fbf02f563e3296231ac35a26a85bdc40d50f8a71d7b0a04fcac8d58e721eedb1c850e5014485ac3eba8a1f838aee68eda74474a3835424994098f369992aa8e31520beaf70a8ae3a29f6cfd38f3c3d692df3d03274efb0f2522e0234927bd327d470513c21e34f7d0797211f35b17a276796322201fec51c251b160ed49a833922b0e14f251616a6930236f3075d222c5c1fe7c5fe3c904eb4f2cda39cdbe4bf3b80f3d99e00b12fc167fdec761dad45d7878ce6191eb440fdf8d3b590e5a791a3d0902734b97c6acf63d4a03a3f4fa923f634cd31f6eb5043aa302466cdeb56179034aedd4195541e6aa0ce4b14ed48f494f9cac4d5900de8faea15958302f8aad0a6a97adeb3d61f8c0a66e97dab9b6c3014bde6855d6ddd4f27a61d78cf8804206159ed3316425aa5a8da34c30f798ecd5e0b8deae2dd89e62a50f2a093a33d80d246ad0e707fb290a05aae2299232860027aa27dcecea6b8cef8fbb46ec56f405fa85d97b631e3944bc29d606f4a897f53144c66bc6236a4ca0df3a996d2c900d2d9007bb220bd4b6b8ac7b15793eec9f9e474af8d085407ebddedda4b60b9b0b9e7d05e2e4f6744b072c228a963642907e44dac5960c41b7da56354b9ae5490945796143ab74cdf9227dffddb856ce63dd1705d57802d7bf5cb9b85c6e2eea0c837730139446d602414c94f0798911d8ccbd3d1ea4a878f799d8aff09a49e00d160841e884251827f78dace87c09fd5e69754bd50e16a4a7246d808f0e6b640f097aed72e68d63408dbe6fbe687bae732d1223fabc1804fba9c1ddfe40d65d07328496fca25a94c4d255330f20b685600525c111147dd5064c0df65a0eb3dd0a2b1614251710381d1ce49d2f9e4c02d2dda4d9445c6bbe420552a7140ad16f07eb8b90901bd2f43fb72d575539bbd0f1079645d9dd7a410097eeba6868396708e131f344e3139bbb83b3acf692389d5ccf9933f5a4f07d972dabedb5142aea0924baab9baab4a16d6bac38589b43a9a8a631b7e84d0490ecd65505750624060626485ac46d4cad98d0bfc1a22e05faa93c4f19a898cd76a76295582331e589065a3120d5586a65206e9d54c529532262556a6f0f4c41821d69532094ba2a2c0f2c1150e4d9c829cee1f48279d208a1aa18cce4fb0757e50cb7721b1b57f77406e8d96c180fe8d245d67246a51e0e3ce476644fac65857c6ac29e26af06b760006b90f1e5a0ad8e3d069aaf50b7cac0b71a8e336f989cf0633bc42bc1d2c9a9009ae9bfd5d540873a99af3a8bc06f35b31b69ba58d759fd6129bd3df27c85ae0668f4e695c867992aa30b113456b1b5b3f6ead1ebe744f4c478583da28a1f83059e71be14e7e223b04809d097a3bb04a16612891b5dce672bf026480ffc23be03ec7cecaeda733e8d94709de1452711bb89bcf2064c5fbf54f8dbc42a09a72904904dc6f61cab975f5e6285872067a4b2dc81db55622cb349a952d0b8423c960400291dace75da275d0190c3ae01f5f7a23929c912c2da7e7df5547dfdf1f7c05bcc1a56e1de7b800b1be637ce2f1993edf2dd69f5062377363d37e8452831403b2dd54d6d7170bb0debd886a6a50fb28ff77634c4f8e8b0c949a989b4f0a1d00b1df6169e54bb450ece8282b6fab5931e825d26cab9c75afc68cf58f03d2ae05e556b28634e895b7c1adf29a5939cc8dd1dcc323bd2377e4d26ffca0bf1d1604de6df4f31a0df8a31b8b68261f2c5a28c10ab713040b99954917a75ad31e400bce87e455c3e39d6c5ca11bcdef5df0b0d066531561ca27558d346ec3ee57b7097e2811824cf7d441c42538fec40f6783c695f6cfb698361d21ccf30cac708602bb18a5e2a627d2609e9c5533efc346a2a6bae08b1ff1d340cb67264e0adc8401ee9c24454dbca98653c19ec92e7def47d9dd398fe2da283ab466f2ca5162b1027db2d7aa3a85ac5786d1869caaf84a3c715d108121abb7ebd91f1e127c0c880364aae15de3901be5e0b6fa1f6181f0586f9df59dab88db9af0aa289ada08ce0ee773cfb2917358248594de7b0fa9be0d0699f54c16ab3ec581c2c9fc7154d703fde9316c838244f1a9dd3c6009f4f6f7bdc4e2826a0d400ebe322758e218980cef3044b754a86e113023cf973b55649e482e2ab18182bd34b38ca33e544e72023fbe2f23ebca510c1d257dcbf2a68d38a1fe1f9bfd0af64f8c8a5ae6afb3a60ecb3f8a43f0a6f589f0e178110bc6f2fb9e46ef810ffaebf9e1956a1a8f82c601a73e6f4d6b05740a1a8941ad4a53465041a8cb0082e1104d26e992842178940b4d621815c75ecebf31e96d0a34a5782d4bc4c8b5d4ecac55898d033e267dba0dff69d3bd914133a7afd4be25d20b0d8585ca5852b4f5caa14c1099a4430e4901668c040437235625422b6a3ce0ccddb961f3002bff5a7e95e69ca9f208ad950f2d96d5de67fe4a3efa801431a12a274eebb021816ed9a32f40245471e34c5d0cf127148d3867c8f98a223d8c30589a0a55d3ce32a0b07d5bbde6453d77d62c04e7c881a4ab2f2f8eec40df0fbab2e7f223f21da20ca329fc78bd1a8b082b5e0aeaaa110225d0bb065e40b269beb295b16126c04c095b58be9d4621f6995e7103b3fddf74f9e26ad5a5a1bf7884be7573d29a04baa7e52452717502314725050017d4e6f91e8822704460820f700bb33f1f51464f4cdbe9081612e7e5c907790c481acb9c159636920132508dee063e943d3df139dd4b5db4fb07dc82394cef00ba923a769ebfd0b8752c3c7b8e0265e0506b410dbb886f3c99071a15cd192a030a41b11ac3ac39a8eb39c0e7a5d326c590d33a3038f97ba28a0c61c787047e04c0815a502e89fa1d7a3cbb0b5b233c1fada19c6799991a4f922309f9201d7106ddeb0bbddd8310085f7c7d5e948621e2b3283379b3a9cfadb94834f9fb73760edce404bc17cd91c29e7f0ad88af434fdea071660c59e5c46c028f232844bac03964aee4678eaffacc944b06db61b66d716c3749077164af13c539ee41be4450d974522ea59219c73064da294b70f3f6bcd08d00c49840f28c31aea56afd25b0d772cef073acf5bf95d23e678203446583093621840d854cb02c8cd1a52ced50e2390465b5e521d937f6bd58d43ac6731241bd84c085c3e29d7335765d28e3106648be285aeb932d5b069ffe21341c1845cf964a74044a6bde2842a63e7a5ae0f8c36f434f1e7c525fb3ea5b3f3033dd54e25d179c9d524cd5e7c3ccffcc694050a719728aa8f54e1a3a889663569c0e65d603d7331a82ec3fa97814ed8a08e056a5b3867f45759823ba8dbe86d4b60102d026605d1ab8ff9eb8cf81ba561cc0aebd01b5fa5b046adf96ba75949fda75da1a3ff3d091307f721ad4b4fdfb62b06a69b6f6bb6fb32311484835290e384c17f58f1c36e235d41aecd8aab78503c0750746e3fe4dc9a9ce5e7bb6ce59df759554a9b057dcb3f9af95be4178c34640e7ee8c1b32bd50ce661528a209c3b4967dc0abecde33701c9b7f806b31dd91d0f6f4e76dabbfef290721bf93e0c3e9a2250edfe5fcbead26e0cc7804900945707eb7dabdba53b56fd428e52c01612a04f48c8077a0fff421aee3baf2c23cc400c129f98f17900c53560520570a59b5a3ae121cabd2edb7e19cf482daeb30e7d08f57afefe104efd55ab162d2ed7e9c171f78f25a54272cebfe57cb2a20e2d43067136b89a1a81be21727e7486cc2afa40886acfb7f3b04aa24332b2e91f38b505b27c0e2690ac0000e8da87a7ee66d8cf7ab7e324837f9c8cba33c6e404edda010735f5d925fa66d849a4cd2d7cd56f5ac1228951244a27e542ffc6b0161e9b044fee3e4c4b22bd328a4e6e74add87f77b1c9d69531e5d43380f7dad20ff3eb073ecb0a8227ea7fbcb85c314497700277105e705f8daa79b3d4fe7323c3dcda09753b9f99208f3622fdbb826165bdcc4508df12e5cab71ce52b1fcdcb218f1c0c6123ce1c73032a6d63b0847cf75ae949d8f9ebb14c2ca1b9a9d832a8cc1e770950a726e16a2bd5778d27ec46ecf4274757649301194cf8c486328b705e1d6e01f195a1d4660e78f5c9facdfd09606835fd764f7e21e6d48ace420eed20dc9e0787b6a8bff2cc9aff530e5b63396db5c0c479330577f3780529a2e7890366670cc2ff7f3466955b86b47a72300df87bf43f2c9cd2be23163151d041765f1b2103584a3f90beb3876fbbc41b7de9ab9aec34ea2cb81f535de36e1759a97d35850d62107620b2bf856b5e76c8792d86e362eeb7c033082c24c7ea4e745452c4c209bf5a053e576c4f2fc07417352903c345be0d167022ab65ced737904e2e2c010a9bfe31f13120de87534497a80e8a822f422dc69a38e246e329ef1f935d15840c97ce000cf8a3f714a6422447b2106298de42caf512f8aab40d3ee3adb1556e027e3e254ce0a8072c314f10a56f2b9f9ae4393948965f1464d16b2e0311b00b0a99d213ed84011f2b749885ce2be1b4c6999cf3dd11ce329fb6672e614a82910906c0e65ce0a49194badf352d05d505fac38cc9ae4eb8f246d245328467459f0e405a98b2cde688114de7e73f2cd6b26359b30b185af35b9fe33ddbaeb355870a5ae0a86d3deb581df03c0a26f8d95327c9e10f35aad9b811a05a3829b81fbc02bd36781af9873dc983a8618e27790665619d9d0dd2efb6b838588ace940852005f615367bdcb7e3a6025c49470395a674bbc113728a0ef35583ebc5bdc8191008a6adfd195a2741ede9a6a9a0e114f66a695124c5b1e28125df3a98d4407c40d2f0439d43ea5110ad5a0e9ce0dcbe747906f83e6b020b63f65be447c30081c0a29a66b074825584c67f3eab551fb82d2cd16e1977fe60e7ba4554ef1d986530774d005fe259ab622fdec78fffb379e8ca7b16c538b1185cd81390fc297125006a216108fa1e51fb73b1b0d715ddb573e5219f3145948aecf9219a9e67049f801208af0e06e8bb93d70f2aaf6b3102453ed4c73cf0842a598825f7a3d4d3d040d2ccb60ce93c393392d11f60da7b06d786db98ba632726f2cc73654073fbbf10aace74a3ae6ff693b3325b7efe95b5f057b6b05629eb4e230faa1a776a01abd09adea1a20e7e1e2ca29b497cab9c752406619a1d4e0f67e1166be08a1b57a7f0dbba02cee84e977cafd3005a8360a4f9f3807dfcd973bcb0f60c6f6aafbd6e802772fb78e769a009c627b665059ad3c7734504e391f7e091a64ac8abbeeba840a871f7510529a982f8ed0ef0bf5e2211f19284d900b894c39379d72c0e54bc8018d7dcb9216681bfd8ed84842125041efca0add66d7dfe5c720c0d7a4b01c1c0c9087309b98c3213897d0159864d53c70b326d5d786f17fc62e2431c8060db901018315b20162ca127d03f5fdf689a57c7a542f05add01f500a25a0450ab922096c71e4c631d27d2ca09049dc81bcbf61009ab17ffe167fb8f10023352997850f3ee3a87f8fa039e9a1b22449f08d531cd0e248e41774653d56d99156b41b56094f85187f72bb0de2056af17b99d67185e5618d0b8fbd77f8785fab75358eeb0cff9f481d2e3b7e968f4107068b36ff4a5da44ed60a88f77b7b70f55a690b590c749fb6a4a3180db6a127f548b96171bdd8fdd124766d5fc22a5ddfd48dc07c086eaa9034a7a74f62a648b7a4f8d09ab2fd59fb428540f0ff1ddad1313f415506114e23f574ca17ac664e0c09fae3091489f8426be2b983044a5c7b922b47750a64a4ccb21000e31c85d92b335a419086ba5e256acb7335901e467c52f6e7a70db25ad7cb48d7ff1981a3b22264b3d67090d656599a46d80e05a886fdcea140069df7eed27c380cad9464b071f61c51e54eb35d977743bb49188745b8c8628c0174ef53502575389133f4d28828ada9b76cbbc82f419217f6395f88063763ec09f9e2d04ff0162e45b264b263e591f07580305f8f2bda16eaba552ed6212e9406ed4f6e57aee271e9599d98176f5c6b3fcc2e3fe6ceeebe48a38e3b8a6104540109af1233a481e61c1d8f7190c69b49c7d18f39bc3811398323bc664c57573309f5bac76a5b51b63cd2c284287884c2857dd9f2ab87d306e67c8a637adc085b06812f76f41dc1527101783a2b942e88d694dbbf5df525b22d5793ae7f7d7e8807113350e14bf7b58b7a4e11a052d8c2a9bd01d320ebbc50c94fce8d859af908081857d11c50ea4f97f7b357fefbf64a9365004ff3abf7ca7bdfcc4bbc2aaabf097d068434d843dbfaaddcffa3c183731f5484060467a732b61a0f15192800020fae925adea64a6f658fcf392fb2b4bf5ddd64467dbe8c08f460f5062da8055d0615e9807d6ea828ef8595b182aab943f04d65f267cd61a50244ca27a03c4c4f0bc4d69be239988132591adbdd8dd76dcd85647d768cfdcd5842ebe8cca88d5b04e6a1ec26e637cc6a14dfb02ca0001c4ce9d95d12305ff3f0c11ed6b967623e08f20a465d4bdad27813d1c00ca527b2cd3fcdafa14e21d9423da6cc7c04c87f07a1454eb92c178d7ace7c1ba90156d2c550a49843ec9d13132a817065f8c5a3030067d24e1299a0fced20b8e62fa4811c2e2dd2dbc1d7a87f91939a057a570405ac9df5afe55691f94c79afece38c030f6f355ce4ed4784bead56a3d21c6f76074e3299a8cf37ed66c9f76e055fea6dc08d02d8a4051df482907f6425cb478c06433553a8d1da6b3e35f395403dfc1ff6302109e1b6395030934f32dfae4ce20536892f029cdfab6227b5a3e527cd0be1e7339ba449a900f1529fd654f8ae3d04f209afbf4b1b1c519852a6296ead7d150525389761baedf44ac6071f878d71050beaed1e520f631a0bde169a230038011f07f2f990ad52f07625021a254b4e018a4ef75b6014042aef20a9225d3617838ff1b37b18afe43aa449e3b49f9e2f05bd89598a4eac23c70b3145b1cd1577d8dc2bec5551165956f7eccfa5a507da03a65f6ace76a6057cb4064998eb3f960a5f91f4bfcb40a9a1e0806d22781d2d05da58e2aa1b183b5782e65442511b5ce6dd776e3f4a2ce95e8a3cf900df1783041477cc1dd735ead1425381e8a80d123c979b1a835e0928cb2b84984adb60f4082b8ca50f332cdcd6dab039cb9fad1ef2759f7cdd0dfa44103195d862b6f3bc0e61b5ff393a7558baa72dffd3c6ad39f7dc023509004a12722353db205e431606c9d85a7265c08c38744ed948c8d526aa252a7bb8971498faf318fc9652955802aac1a9b15cb8da39c54e367a3f3ea782c2b52f532f04fe2bc4c6e81bdcae0108d3e3393b7a7179da8e6fa02d219050d13ed3968a392200abf8df9b2139f5b50640d7f253f8ceca1c7296cd353559f850c5e5d5403eaf13192d3715f9c6db0d076a2bf0fa3228a45a3fa3bc4bee114dfda6565d38e9a70d975a0bf649dd4bdd0261bac65cca7b569ada19ddfefa126517ac5e2ac3441ea014b3f84ec7ce69a104bae63da0ec377e02bc209fe08262aeb2a3182aadaf87337937d93cf0265f880ec4fa6937027da17ba90de29893fdf65d0705e4c1c3c3ae497a6b8f702fb3df0dc2cd00e48ceddbd668f4e4bc5eec6d332500515bea352e8d897ef7d49e76390a5e298ec66a838f2216d3f1f0547199f40c4c4a453c8cf014c09a0a1b25e96c064f6367eab9c1173194917c15fa15b3b7a7be00dcaceff71c265f2ece50e67e0550689f939b8792e202a490c0a6060a0a452185097974c96c4e990ea59d0a140b23ed8bb2422b96cb27a662bef936f5e2f7ff3ab4b019a4d6f6051e334f4fe30f5c932fa98971075c6483fe6a2ce29810318ce787c101d4b1ba15a457dca7cd02629b7227721981f7851f10186de5da4a98edac7701b797264edb30fe1c9a21094ac225a28ea9962f807387c24298ca8700e8b609d58bb4703906488856388a0fbb2f4f7678d41bd32114202f7492548957f6c711754aa348d02143681a5f4905b82ef496b1535f848bcd4ecdccc4c8427bf2403d3dc0a681767d0f7ed7491b002d11c85ba1b8352887f981f5247d6fb62e23d034c22b202618512408638b1b03339c7867ec8ea70d7694b5ead1372b657595fb3530a9738a9908fb0e24fcd306d09f666aaab90d4a6e223d2862174b96dfcf7365cd3e6cb6affbb66d9372e602370324f7993150b96215ff3a8fec8f1158f91712ce37086dc7a59d4bddb588054f22284152d2b3b1e591c6b27b1b6af1f92ec615cf5ef9076fb90089541da5026f651189cdc770cfb0cf6abbcdc9af8e36128173ccbd3a35afe1829f9cacdb0b6a20ec5035a4a4cffc2e85aa284e4dc6829e553906f8d39b3a3142289e1c080b5da4e5c489185ca64ade170750f0c3c872b899a6e89b62b644713c56e035b804f90d95a071ec6e1f8805edd90f8c57e8d886b90ca362d6416fb34063cf928609b5fb77b6d87135e2a5eb160fa79f24761aaac4e7bb740bbbf03e5a3f42a6ea0ab76627b7d3a582b71c174fcdb535662c6170977dbb818ffade87b39b268a4e06432d348c279af085217c0bf2fc05bce508dbf1408a211d025ea73adae34cfb0968c223974583cd36b178aa748751209e29a0aa9602f20a2d7cc2cc9411fce3032a742deab670b9550cb7be44d47b8c5cde9362a3642baa92d48bb3be29defb0000d4ab583104e1ace4703894a88c9283d6e1340682377f3d7414a6a002a3e705a8aacf50be94c1c56b699aa95f7e6fd92d8cbd4397490e3751605a62f97c1909fb71ff9c5115abadad7e79cc844c4891df22a869e47febdab14da164c7715c077ce0d312b79887f8dd7a6606557409c654bba0929a98815bacdf90df9c42a202d10bd228f4634f8a5ada3e9c147cdcb65c509594db62959b5c891aa4f363b40f58d6b8c547a85b527bff20d067a12eb2571f7dd98e857e0861f62fdfee5540020d590a06d9397c973a289e3d9a7cb95bb3f807db306158c931f2c30872471d0c33c49e15b70bfcd3c238bf2594e222a33676c0259ac6637668704546e142ae09066ec39540d45f0042c514467abc24eb943ae12a4f19d1b54204e2e881b37a0161cde5a4ee3a56c584bf8c86f232aacf5b6758d2f15c36b7ac7c9f05e8f7bd04e4913b31ab651e05efeb7052dd8277765ff5c23bde4ca362f603a2463a6417053bb56338e1ee29bba920fcb86526a3fb849f57b5622ba1bfd8223f21f947d8014ec16d5f7f4bcd96c63d40e4a39d81367791bc23cd423fe84bd1fd43c706140498c0dc70e966a36d60c97c3081e84a495fa9c184515162d7fb0379293b192c0a2e9ac7ab23089ade0e4daebf4eca54c658ac16e79f0562f206e1bc8f927b190c79f87d86dbca24d116c086fd3eb0a2247aaba0ba1d3982bf92ec30841fb12a0715431b678af7be6e71f7ded583a46e85e0a5d6a99c7872e4028c2b682ee17c0306c1c22266bc4a9ec7aa5bdaa65d3c78d0ef04d4e7d31bf4f0df889a57bb18002b3e7004e9f7f67d39a89b72f44141bfb7beb00018536c5c06b6e2ebac45d50a3ef547cac7806d02ef06a328fe818ee70a906d4c0a462267406eb280c8b1be0bc734ced8874e46c5eaedcb4eda3f5065fe668e58bfdec19dc44099739303f70871bcc8729f9a49915edff6b381eab8caafca01b506a8ad4258ad326f1c164f0cbb311e72e172c8500c093e336afcca4228e12d14e7e669b578fb9e03898abf0599a079a0cf3c8bf5bcfde3feed2744edf02918c1712c6b39961a27162311350cff9289e670d576c142498b8f9b3bade0c250d6511fdcf2ac65398845bcd308043315ffc67ae233a28178f1de692281cb749c8867de7ba9115c04ac1e67709e0e137eb48d3b09ae04b0e8692c344ba6e8b6ae3306a1918d778845d3264d6e660c10442576b87edd5e1ed80115a39d5c66510b4287af5bfc2b329239e8a0ffeb0a518977958b11b0376329e59ce00fe2689bc4d2b9b67b98e0ead436ebcb94fb065db636235c8b94a11a249c14c4f26c4d137af658cbc19ab0ca250961fa3d1d05b87bf1047bee2a882a3c8b14c8ba50f32742081a1c135b3c19ebdb5a445b730ac123613196b99b058962108e5ed86356c103bfc4de82f16c18580b7d9a27bb00ac153402cd742a1259a8db7e88bdc367119c81b204187204944c2e42601637019c9c50fd7ec020d1451809b687f3f068db50b4e8a39475f8662c6c76c86ba607ca94b40b3e1079fd3f321f4cac7ae196d0301327c7dbe6dae5dad63d4d16390b5a66ede93167fb71b1bff91d17d19baed6a5df2694375856c99eb1e7a7b0d1022cc27072ef7179bc10ab3ec2db193de33447f3ad92263db9bf0a5582ee2bc50aa947768c343d11eeadd55a5b258dd1b8209d2a40441e61a82dc80be68958af00c1973befcd6b6e150f190231fc286af21956f9b517a2fa4b1c8d614dae821d0d8059a3aee9c2313983975c472bf015831f0d3a9a6c0b8e75e6b9002421bf9c0d7d4a3ad73c95fc6ef174066adf6da2dc78edb5646e5fa4f4b54ff330014e7401947ec253ac9c2965ea0114ec9970a8678e137a31ecc79d230820f7d66a926c06bcde6d63da5fbb76ea477d86c5f9442b6fad3bc6c04be7552845618b709a350a1005be0514567e4b48d8cc1937f32f962fa8450541b1a6b97cf7a8197bb604077a0fc5e75da43f626d866fc72bc3c045b0e728eae2b5cd7c25c6171504e070081b591420d8251683d91b69ef95eeb24efcd2ea4888eca0dcd1e1606c35575504776e54e00e3682c416a25bb0e650889e75c395b5d3745fd76b003cceb78b100574f900ba6b907313b8e1a3e3911ee034323efe369cb42fb4f10dc9ddefd3e70dc2d7675edec4a31783422069eda787f42735733bd5e885bf5cc91598385b2f0cda66e63e0ba6b0b079e0f9eef7b281df74514de287853e3183b8926b8ab0050a4d1eda80b80bf7a8663eef022cdef9b49b5359cbbbba4bec5a8e755fb7a8e304d2ea4b9285fb762e8de825ef8989b6c79d80f9ccf627992d3bebe30911abed07562c3ed0df19d8078196705dc2e530d6168872697fe9ec82318f494d81b7dd00e89510f37fb753e6e919836f12619ac5f42922292bf68d04d0f669fc745706056de262d3ea76467ff4f4b299e0bdd5421f908c7312c2b5310e6bc37819009d0def1952e3c7d7cb4b5f230af4e4098e42c3fd1d0cbbff9c3d66aed4d385601f04912a00071e446191f8a576dc54b4a1843634de988cb5518c64e2c484eac5b409214f3aec60478be5655297390fe4ce4c569822c0d349cfb818148a5d3ad0930808f40d8faddb86bbee303eeecd980d70a6d326bfdaca3234f24cd1d5e94ea80ad49888b14ec6768dc5f1f2666dc1d0da9da22099bc33b2b64c5d757292399d057ef6cab0e919bcc72806b6be6c2de83f4a83f52f5bf390e69bc7c279c53ca20ba002ae8b978751d01388b2454a1027730b62e0f50b1052edecb9d4bfef2ea6075a93d40b3b241d26d26221e4c6ac078d3faa5e20267c5b90735fa2bc6a036200561bd27e254bc28a15e05ab65686e2ba2c87141f90606ed2085e8794e59a730eab983538ddec3eca8182d44d93212aa0385b7212a48d34199b9657a39cb6f9030e476432d2acd77834b896fa2667a0517e2cbb90804d3da16647255738e06c000c44f606d9cde9c614f02c8b39bd3de77239fbf71fd26abbf65aa459a20c340ac807fa8efbc36c879611fc9448c7b288be230156478b6a5fe9612297932dfb006d2258b39e6347e7a560d29c9aed2a9cab6ed1c4c02730f411be183e8746cc08badde9636618d17541656c2d3b29adb73be7a1d946372a385605581f7089930dd44d04a4b4630320d67b8300ad2abf82a09c49ce1dde83f5021a5bef2ef069079d019caf190f32e9b9ba45abd4819bfc0a2a088fa11f77bb34a051a041bb4004d082cd3a4a1ae2669eed564c0a5e1d1421617ee62ba61e97cea0f24f19572e021bd3283d07627d59673b929bf5a706bcdb54901d238c8a8871fb5deb842de60218d891f5250e89d63c78932d72c9996f017b528cb0a0659d95df403e12b88a0d11f2b408054408c6089f2618cfbec6358e8b50e321d41651993841cf11994407f09608a97ebeb79a1a02c4e92b8313c24e70a0e9ba5ccbedf26bd18d9d8152091e905ce9baba0dfd43c13d28bcac56cb659dcd5f853d465b9e065bd6d9f2420bf0979e663c432addb78f6b01f55b99860822e6ff78a697efab397ddf82a05804be12fc595918933a8cc6f0f02a13777c777ecb8732f8977abd928f4688764b0f4490153fda77c4802e00bc720b85ab986936bedac95e3ae1bc5c72fb83d8ee02b18b774c56d1b5e8a0137d153bdf16e39f239c31141a79962c079a664a47650e2a5a48e23e2a20a82f958714ba4b6ebefa43edf8284a66b7e9d950f9a38d5d0bed183ba5f6b3f328bc50c8a995ce513cf922a8ea65b9d62109cc35955f82de03bc498deaa2f0f013b64841c317dae3f2797eb0b5033f7c591de9c001fde03a055946124caab7773263d9d499b71d924e3cccfb713865fc12f88d7bbcc1d1a50bd01b25055b53a67fe44d11ab7809ca6c9841026b05e282c9ffb28c02335a6c0b33267fdb96528a4313a7a19a54ab6af0de42950b908236367b30180cbccb830f8445a270ba8696f91c51b3f99ab2b37a48c36bacc8b60e168ef7a348ede5ba0c6a7b0c86d53de5d3af4919d40e7fdc9a7214bbdd97abbe4eb5eccad9d758fa0c5fec0f076dcd067a1d699e7d5f71581ef1cfc9b810ec1ecee98a3542e8c949088419f3c95b2c73252d7ed2fbd13aaa3adbb10a6ed9f9e9fecee741f3ebb3890d8cbf83eb83b5351bbfa4787793e75c11d51b80ef8afb608d4857b1d6faebe408c8ed5f08cb77df07725e63fecd9ed721d16c3c2f6277f800434dad54b833d2070fb1b8d69b094203f78cc2312aacee53986cdf23c96d3181ca6b108c10dfde062ae92258e0929d0ee3038ab0fbb70b0df02f78fe203249b86a4e483a54929f07a1088a5d4a400efd984742efa00cda5d0a5e396076e1d0a4c7a906fdfbaf820623f29772932b9f26c63e3e78aae4fa79cf4b569f4ece90658c82eb9aa0659b0f839c86032aaf72ee5e834277308162f19985729af0fc21f96a3ecfc91a1dd10dfa511155eca952b071550c0e067d15d75a19775ac744ebb4ce7e913532ffde0226183be8fa5fe5fae160604e5c73ce26734541db9dce026f87370e1b1a18640c0d37bd305c5f0a63cc7ad2f5bb714a3f73fb6c18946e49272abdd3513babfe03c9fad33965b53dcb506dfc7dbf325c308cd83e360b3361cb156998dc79900a02fa852db74398d27038e6a805a7942dea87c529bf7c97857b61c81d02b638480b897d8b8ee5d6b06e1e0aaa3375f28b9b11998f9644f973345d6f0931d26c410e8b2d06ccb2d7be1f80ff41a1aeef00255c9511b731a86e845eb05164d3046802636d2d7f59c2b909328d574e8f84238db71010d421ea03d79b353f0c5ad32a06cc132f21d5c983d38cf59707d9df5bf44223a5eed0f6d93d3dd8280ae801ef019b271d4ae78beb72e3afdf4403f376c197fb3814a18c135e22e4cb7032166d0c6034d6aa3b26049375eac910719e377d9c73cb91fa0dc72fb3c2936daa74260e1d81b82ab1bf9261be6ee42f1039fa785071cb474b540771953048feabfc700782f355e06a5e57fa4cf64679b53cf3f917c58c0d3e7c9b7dfd23624baf9784027b53b77f3183510393ab91b8820eea9523dba15c9e6ced65e586c878ee379a0d7f1b58ea05e54a386f40f3621430d0d39454e120f7fd426e32a69a94c5e77f0e2dc1a019eaead12bd794e4eba898d203bb264c3e8af1b5ceee4872eab16e7a0c7d4f1ae1c1a1e97ab4d2b2e2b9f9862810fffc6c406baa895372c7bf252c1e09bac4f20651131dc487fd60489dab1aecb3a1a1fc628e5777aebc4d33ae6f70068c27f5e80c3c0cdac9f9a3d7d5dd423a23dae655222b37e00aecc00d39e40f06db09f83590612bc8a0c23ace281018fcb84125229d05849ce22fa24266852108109ebde425b24807c09a4be7889f9f6bfd151a82ccad7fcc71a73fa6f7b22b0fb2ae4d7930ab842ce89c6286f72ca3edb2e5517f8a2b10740df2aa4ff500510afc4e7b75c1f6211896b68aaf84f83f371b04b440bc0030c4df498b2ea56193035800bb9d69c677ac42400fac66b716b40672337786cd61ffef2f854a1b2e6a030688ff39c18ea36e684034fcd31037eb9d7ce15f23e9b750a6dcf7bdcf6158061a5ae95770ee24b4631f5856b019db3ced63ecbd912ac4f4418c3275631b9a0fada3885ffbc3e77d411831ed026fb4acda588f776ea5425930c5a347e8906804ed18dc5967f9c02ec6211df275518215909b3500327c298a34e3278b94ea5d0c92d47f8a911ff48af2bc8840803bf86f8723f496f59595adbdea5517fca80308581e5283f0fbd1bbe2b781e7921fc8fb528ad5907ba7d4c47cdbd4c67dddb90c29cc743d57a5f6ccf5386026b46670ee547e8a5a572706050aaee31cd7307f04298c18a0f994499bd398ead0fb966e9a2a92c8a1ce1069dd51175f8ed9e9130526af789bc4583bb52a30be1983bbcaf0477a9ff96d4bc4bd6574a2ed4dd17c0da471b0ad1a2fba6c4ed923ddae0e548aafa53228e298b6186008c0ea61dc850e29894f98dc0c244d7535873b4303d9cbda241380f2079b056f914447a946e405d0bb72d1286dccbfebc5231cfe4c60f86cf20aeed368d1b589d4758c5743990e100f0f00b23da52a24917fecaae9780ebf8968df5d2394e74763da1a4892ee033c9c73be5e52a9d77f12ec675216c33b58f29289978ba8d8c0074c26f11a1e0844f2eda5a7ee8d3913d3a22dfafe5d150791d3cfc8f5f5b8592a1c644bbfce012382d59f1f5cebd915c9e04e1304e2f083e45d42c5b67f00fb40d99bcdb41109e698966696873e672b60425d5cac9d8a8e5d77ae5476950afe5c635dc08c2905049761c0596aa2c5f320555e77bb411c835373aed3a8d64f988ce5d216e8c50e02111a005a1a7776bf2a76a11c9e47c1969cc670646745e7bad5cfed1d42430c +generate_ring_signature 23427a37b63e16df40a94a569475e086585f88042e3c6933cf1c7c089b041a45 a680bcc8da17f610deaae851e49a1153a41cf2a0e7b4df452b0cb0e06fed4fc5 27 76ef12c44e822d190d8591a0606a6246e3e339c3c0d09a3e4ef9b9f3e537c783 dfd8e238c9d58b0b26de9d6d577cb9ee7fb353d5e624577d8a7089dc7ba75c2c 75d01aa0ad629f58acb073ef222e20cf3ed9cc497ca0c0faed5328da617201eb 039651d4977f68975edd0044b8c69aef742b79b553550bbb89d03996940f6a65 2e20014f619c3253a8ef76ada8eb6b6a90b48d80a0442afb5c49bc677ca30633 b6172170bbe84ae154fc5815d4736578dd9d30e1e0436501dd36b09da27bfa7e 8cb4fd174df4dc7db427d121a19bf938b4e8aaad7830e9e638f653ef0011ab54 049bb382150f20b7205ee71165393d59fd4cc0d1a690a088387f8039867f5b08 a3ea8ea364079b4a02debc3fdf1b6d7a3791981efb1688a876b97008d3aa27a9 ffa5fa37dceb7570f33e6c757291119270ac62a9caf79c61a1f73347996b42cd f3d0898f92b979728369d0d9abe73aa690292800f3e4efb66de9544e95fd11b1 29291a457166cc60ec27368846b57c40876d1f573ec9af3f0adf44e478c1d561 195ea8899ba4e879cbbdcb3946d8158b0db04d9f147a07342e73089a7aaf5c53 0cfc96a760e8bba3e0a54bd8f64868fb7230f025603bc1d7517d5238f309223e 0beb14a39881918f54137e99f016277f66d022faf43dd0a4312de3611ef62167 87e660091dfe3e75636c7dd731a7aceef1aa6509a4ed0a5d9dd70b5ff02fbba5 4e1dac7838a601b8bf319f75d333a2488feb652d3f2c1610fb24bb66b5dbd727 6e2959ddd5b086f020527fb71362b3d902b030a27a873654c22794471312ee44 2c75319035311b2f58593503dc6f6f0f5c9d6a5b414586818f48452f5e7846e5 f204e336a2710b43975568558f6845fc099637b05cc8921e0557ef5121672e06 83210f8e7869415f49bb722f02ecca7b1a39aa5cb90ee5f62015c26b5aa7e23a 3ccbee824b4d6ba42ed29e238af0d36fb4213986ce70582e2b52e8e519b23c1c e42edb639429562afb90c78af73c0966e4a38f892a13e29c778af7febd30267f 1bb904406811cbe96212e0b34bea451f8fc119a7559e7bfe57eca21b43eb55c1 8414918482c2104b258f9095e099492c5da1aab97173d21dac8c083206ab739d 65bc67958d05c81c80d48855041e321e1e74aec3006c2cbdf0d9c6adc0549271 12fd3cd5de5c0cea07d92c01871687c5dabee74bd383fe58a0721e5c0658127b e3bdd2c25f7b73bd7570bb5c6d3dc6469dac206a4483a6d8dc173bd2b23a6f05 2 ac4b55c7d32736e7918787a24f0b0380964a919a33d017ee0da4eb2046890e02306bbedb2716fb5503048ec1f3182b65f1919a42dad2a46d7de705998b0d8c00b4dcc465764a0782f41c636643bf767bf325039517be584d7a65f12553844705ccdb3ef266c02c285ad0a0cda8aeb3adbaf94f2c28007454f51b69f414aed40c69787ae300e7ccffac14f771dd32946d99bd37c481fcf2c974c8500b71e5e90924ba74f82e40750c8f14ff624c54558a9358e82d0c29f8731135a296c526bf0d07028c723eb884b800117a2558da1f66d34753f43d3c81a074644ccb7206e60bc8b7a4e79c37c20e21a880642c9164aa532b95ece108f018a39ded89e48ab500b832b4ad82163649b2bda47002ac8054e36831a8da997ea155860697ed2c2f02e91d69f842ffeed056a28be2156a542d458d59edb1346b95ed1d78e7c04d7a0174d369a7fe03425f97b8bce2bb3b0d7f38477f05fb39a3bb1fc9e2f28ca27b03ea9ae5b3dabceb342afd551006a735a2dd1ca5e4cbb34918c52f20a5629dae05b3af34d91d73878dc794e19927e7ad88c70e3512d6e6874f4620acbd150ca70c3f8581df9f682aa7b4ae93db7a6b2a194a7ebde275e04c13702c26df94ee7308fc006408eebf1c39968a0cd7dc6df99933b0ca7724e9dfc7130cfb26f758120e9cd51382c2a509927845f7807fd06b5d5b0f6c2baefcd032971ecf225a4be00a55d4cda55ee6ef81e77cbb78c4246b30b794351980f591e71fe98f8355b08902a9c93fece9febe0488b9d1d0ad3b46c32e1b11d02bb83a45f56f1fb8b1089a0f8558c1e58ab09760751a63a9f1a34eb1265edeca6516bd35983f8deaa3c14309300a1b6d671a73261fc260963e438cd174b3b10883097c371a6c5b534a6c890f0107111e98069aed13e5dcd8ff3e8033a22b20a58356eaa173e3b4c5629b54049a8390897e74f28cb71ef57a166865f97ba50431f9e007a1b219d3169d0d09058faa8c4564ebdec1a86a22e8efec9a7aaccbdf30b5ceb73dc19a913e4157aa07be61fb36087ca3d5b3c4338254ae693b9be72125579e4be6887a675deb034e0fa0f93342171f10a6b301d12591347138a4452f08310d511d77b2c86db8d3b50ba8bc1022f59b3f0debb920dcfa6ad32829f1874e9440aa3eab0f49bdb7a1260b645e56fc93792ce94a830a2f2455161fffc7434bf6415a30311e1aeb2f908108f3886d6dd8fee7f359b241cefab4276258ef836503d7077e7de9595b474c500b1703ec7dd1bac6b0aebb57a5b7fa75270706d21b955685b4c50e36a2da0f290263b76de4df0c17114a3e909b8e4fbf2a37cb0560ff3a76ca8df82972582e790f1d67a5f7399d4cbe094d2dc252de3163fee75bd9ab17a838d6992bc3ca0e9405f81050902f13feb35d50de7d1e3ea9ff282b78df49a32c70410849465a91d00c2b86fde9714474081f9a37327faf111240ff7ff81dc5bdcd3d800348325e0d0d281385d2a07936cc43f3ee625e977005f82ab07cb404156902dc8de21f5871052210f5a15bdb2b8f6224d7cc88980631bec59f756427a180242becabe1dff400b838df84724e49938facd892481f18384aff124d065f15a4a16ef3eac27b630e3a76cf606855bbd0e2eb097ac4360bd004ec2feb7ef9e12cb7047ceaee19a70106fad75757b02894f017dfb2328fdc72fc2c64a1feee065cb781f4aa5a549208c1081f6a903abb309db7dde9a1fb4be5db81b80e93885499cfcf20e263813800ea2c9efdda98b3323a6eee42676b4b7577f4eef37cc8b06fbd7c855472f2e305b5fb29e247ceca85b4198e563310093713f6101bb1b2f03b49181f8d857a350fd197d6f216250b3775ba694794d122a6277f0e1b91cb28d853e9af4edb7f6e0950c6d97a4d8646baf4667c78827caf90e9f948a131e051b95dc31a1479eba70b3e9664e415344fdf746e8fc115261777209f8208a0892167e6e47383776c110aa66e892ba130e61b3744e719cf4b503f81920537169b8a9cb9797516d80bec0ab00c7813e985a970815ced3cf3d154426870a2e1f9f1a1c5151f25f54474080c8304bfcaf73d5d2e600b49e16a027f92830c7383ab309397b31f77c52a007e0f81ce850ebb25accc0a9d456f5cc5577469b8653a1ab5f2625d906f1ff88a410332c99e06696f5037068f8db6c96efd4d8d54df5b1096b06ec2f85ba1b1101500391ef6956d235c8b5c37aba56f7446f67bce0a370492ecf0883c9949cac27c021230ec9bb86491716fb65fa7aea9c6e2deecdc85d9074b7c875839f359288f037a9e339186e2e690298ad57c95662e2e2899e7f33ec32f06b74ea2c3fda22801f773f2ce3070338ace22c3feffa8cdb198c844fdf4e2bdc7ccb546f0405e6f0308f7ccc5facc037727078d9645a6c8193cde45dfadc2ebfe661b030d76bbf905 +generate_ring_signature 4a79e4858cf84189b1a787a39042ea6be11532c2bc4c1e87937546cf467d05d1 e6e7e9b18970c931eda06ce590197f03131062d3d1b5a6ad71ca1e5abcd18e3d 12 2fb5a4364780ab0fac68569071652025fd8b48e74aa242c27adef75f375d94e4 3c46616f02f3b6d9fcc70f74f9319547b6114a4b2af80da69a665b9edaf6a4d9 1c4d1f6b0f21a6b2a975e2a76e7c4c735bcad9430ae693d69b99db3623944c1c 2be94122483ecf69df0dd4920519ea1ce71af7036f03e27466ba7272421deaac 8eb99f028055ca92189f78726acd9b93ab452227084fe718ac4dab9e8f4389dc 226f4f356c64efa694b8311ad07d4ed444d940d98a54920d2d1f9fa687cf20a8 4bbfe2a4a7b779fa5336295fff9be27b165d9a01920c3fc3ff28d4861997c3a9 3c50a93bcc8b0ac7cb7904cb370d850c81750e2de67ac9d4a769f551bd28727c fa5880974ca82b96b3b64d419674cc7efba182815d23f8424e7e354cc3e63dc4 710410134c629f3565f3706878f34c8b4b049625d520c4efe0b8d0ff9ee02fe7 b0d02c0f6de3ec3774101beb260500d636a2a48c5be06472d17723377f82e0c9 7fc89baf0a1f51aec3e249259b8f22194c406956d27410ce5ffebca081fdca89 1d8156cb422b95597ac3b4ae844934b8e729b09dc95d288c4826fb2b3b8cc90f 4 a2c1ace08199c5dbc5ca671f9b7026b0f6804f4aa77c87efa62fe61eafb49a0ae78e136cd1b24d73c7e94d872134165f6cea6582fe278d425bd2df9050b8c802c2e713cc06358da730fdbba92dcbdfaa0f72154cfe48979f5d5e1afd3b64d7042ef74e7f63fe2b2b25a039e1351caaa91512d827c763f7445a8610b900a5890e70bfb237d7b5341090da9a954cf9010e26031bb8248327173b15b82cf87bb708e446461c1e7d1198f02dc08ee0408c7dbe648eded6846960745d619c0b2264091ad8ea498dfed073dedf9afdd884f807a82350b4b38722a4b2f80e692cd7de021ba71ca5760deffa13cf5b07cd93960a07ffad6f0dac9c6595c92115f2740b0ad0e32bfe715d7c0d8a8e13b421c60d247893ccedb9ac2601348c0c253865a206c86bee784044d1c92648f942b786fc7309143a9f7550c20f4ff0fb75cd3989046a054dd740c021aa622816b2546e565f05f78fdd7b295db143a81a038403ac08158cb03c7f741e32235316141a659e06a0f7da5ce18f6055e9f2fcd109735b09b3fdfbfffc6c634c7d76bd0be666466cba7b35113e561c0cc445ebc016c37901062ae0e1a5db644250e32b5817e4cbfb9cce8e5995af01905a95b23808b9da088f22ed2488cf7f64779ed7dfc1bc2f4fcca4bba8934bd9f17be1d26898f54803be0317bda7e600adeb9b4a2971c828b379243676a23947fca75580c3c8667400e922a8ff1356832ab1563287495bfe1242a4b2f5de56f02b9e2af1173e59570bcf4a2677469a88b8de816253633f344ba7239a8a628754821998322fb01ae30e2957a883295145ad4b7e3651cc008e6473d00f0af5ecbea249db9e7b10622505dad2eeaedd3481852521cfb0d61dad9ef797697f918e8744d2ecf37948a2a003e18b4fb6d0dd1e5c6c45b058178ef75d4a6467ea2013bdf7d5a903366f382906482bef4bc476b834ed11a854307d3a09d0d06937d07f47a11fb38a5120f6c00ea507eb0593162071fc570e1210769acdf2d19e4e7864c188286de498336c4503600beecbb9669fc81176c471900c0508c63980690f623035b380b942db27bf0d +generate_ring_signature b3a73b35af9a583cec3e5ae026c0974460a27f514a1e57863ab5b18303b49bfd e40c3300a1834002a79553eedb269f35f9d7041cb646e3e6db9fca5f153dda0d 10 ebcb749e504392105e194230671d48c40a2122d199dc6ae4e0ba73efba82bdad 7859f6fd20abfa37a3c77079adacf378ca5e510c878c37c588a9646e93fe8388 427f5fbb4eab74be396e86079a6f7efa6cf50d058e9f050686421abf936cb4c1 0d6be5c57e41a58ef7f994a0face6c73c93aede764b54cb3666453d57c2ff4ca 7d0a29ac592eccd5310a9f6ef5cc6ebcfd854b437325c38254981fa83a35e333 67d601df6e64415b9113817e05b525ecde13d8f59020680a700768f9df9ce0ab ca677493bf0e87103de142670672bab6afe534f83fbf59bb7efbead953f2ae79 0146d12aa7dbdf94c4c6c9fba9ed250f5edb2042dc0a6b6d143155f2f5352452 2dbac320da8dc26a2e4483bcd01eae0ad7748c28e4bb6793f182f976f80108ed 87db7f074e179a7998b44b864409980beee78a7ea3befcc7fd1fa697735562bf 35b98eef6f934ddf49deebc1786ae2a7c69d7c061a108ea63be86644aa65510c 1 a5e1c34d5a2386b9f585191ff59d95d5f2ab94ab453e71a94d79074eb9bfa00c448c4fd19738c9b4eaea1e1cca372b10fe7de4bb7ab6d9c14bf58f1ac47a3509cd174bedbb310aed91cd93e6fc8c71affcd769b5b9936c8a5849f93ea6d68a003252088c9f1a4fd27d4d6089584d61a8ac92eee77c52eae0ff3326c9151e2f004bcb4dd8d264e5cb021f604155df24f375f693e406e88f4e9e3fa935eebcac0cd5c2a37cc33c741bb494676c710484f00d5513828da123360e1d4b6427294900f746e74e783a85650b27957a0f1fa6ec828e13b5b702eea4372655ed569b0d0fc71791f51410632e304d3f4c9112fe821a62d836b7ce6ea81c2aa85b4f00d7040282f2d11eafb5783b01a0be4b591a1ad7c24b62274502ab446d896fb59ac60ba5c2101e9d0cf5854cf942a41cce01e2863a492b750c773d6a71e589201eb80d2e0141c0e5eda8f65c5a56b2c3c44fe2eeee59cdd8a2440c69a1f9340f98fb09c3b380fd7acb101c204a652d001d7329d154eb37ec91cc481b94db779f21eb049fc23a444f23fd53566653036f4392f1c33d4aa1e22455254ca4ea81f89d230f7a74c1e49016f06b0d3bd5a622c8e097dda9ddab02f6da4c650c499f8d1c820f1f25ae532208e46194c83b7e76a27668b87765863ec88c59542311d389327a002c3d6a3451c7ce0426a5704f312990c040758d0ff1309ae349208d4e412cba047145b28c3fc4a1219031df5b4f265215c2bea50861760319b34c0f3b73c78b0c89826b18249320d04cdad4fff35841220e9c5c26ec03ce569e9cc796bec87d01dc2abb4de17cb29d7f1c09a6796949e8a752a660b3c723bf709afabc9df91e04babf5af074d528775d583e0b247943be9c582251c902e973fa7297b4de0ce002 +generate_ring_signature ba2cf253cfce5ac728cc5bdfa9e02621cac271d7d640ef00c7bad3612f7ea07f ebfa9411cd1911793cd8c3c3751fefb1a4f26ca477020409303e36d624ba31f3 5 a8dd3253a8e5d1aed79cd6b19d6f8f006a6f755c8da0b20e2c9187fe203f6a18 f7cadf8be983339ac7aa073402ff1d5152c7db7a2b1ab927aff355d4ccb97538 beb5217ff6e8217cfa07a89e132171eaae685ffc7155e1349bc2ccb6289970da 6f7165dcfd5f3310abed2c531905a5c69b118b2d708ade5721f0a452248e458d 04201b3245cbf0b7225718ecf5aa71db813eb5ea54b21423f93fc9ba202399f0 d5d5570a52159caf96724aafa56bb402e9340bc605d665b4fb283c87f3404306 4 a0f7561f9de2ac6941281dbb0be67b4dde21383b79588c6994f0912e1ada5c0571bef6138c8db1fa6741de3dacff01d93093e3acb8f2fd218104c5fd461b750d80bfa0fc47d230bb2e0dc16de4a585d64e8210dde3bfbf4c57748f9bac2e2609253b7d0c83901c38aec080b2751733cc2c70da2e0a60bf38860f0a643c9f0a04ef65990acc1a94470a719b3db9f37eb8bbfb87a0cec86bc827c16c606abad10a813caf397627ffa3d70ec8729e7b8f194c8e79cb63e72a628204a7dd96db0b0fbe815ca9dfd827e343c845b6aadbc2e99a7567bb22f3c408b8fe33722dba3209b04a80d481492ca510e76afa5b83f5d826abb5b16ed1e286e5d3d9dacb6b250d35f9829ae220c46dc8b9d3bc08660886249660aa5b21da6719cc00121e223d0fae7b6882d6d319ccbbb7dc82b774fdf02766689dc65abff4523932c6ddd0d808 +generate_ring_signature 07d546720ad955c6ac191f0ea16e5f7d843651501ec655bb7352f0cbfc540cb7 9c58ecdc8162a18d21f31152b55b98c21529b1b918752e05d6440062b320e36b 34 c5de097b79f066a3bae592e76e4f681f9f9cbddf2d1bb9819d8988f12e657b28 3f2e00f51eaf8c766ea0a750a72aa798c3323c630bc6bbf66796d9eb1dcd7814 0108036469ee5180b39ab609a7cb4a4ba3f4c6ee1399f5a5475cd7abf56f6562 c607fb7f081e02725de17473c3358cc3863eebc8306403fc097d8a8cdf56bc5a 358cc0d47937f554bdfd5cad829d6d4c04bd7b4bdeb8138387409f51f5bbd233 c585912932e94cedab2246ef0f35ba86de9ac8816c72f39fac1b74ec849513fa b967097a873c451309dcc10c8a7716802451bcb666e7aef43c23c4886e958f59 edf0437f0789c2f1280f946e027b9e9d3cd7a7450b77c0c29cc2d1a3a4048e59 6e96fcc4fc42ec8113e21380f6e34dbe8a1fc39c8ec605413a6e4ebcef95a5ee 3540744c779e95429aedc594ca3e7f144fb36f2354c82a215ee3921eee58a687 eb13aa3f8418b863153d0ffa0a185060ea881d0bf26ec385511efd7d5af9a9f2 7f6f7a45c10655b51e31b6d8a8d718eb55be8263be321b959bd31d8175067833 403cf1c69bd4293df454439957b0b82b4fbc10de841225dff9bfe9f09d0b1e00 8e79d62b1b537f5eb4f56e876c25c5419aaffe859b9a281792009937d39e3a18 2c69ecd10e42299b2775570761c7f256084b0ae90d49e77a84f1f728e1ed9eff a15aa70042d5321cb041d4bd2204a7b3cda423ecbadc33aa57c4bbdf22e9464c 8a01554c542f2df7d9ca32dbad3ee49473c064baa299d3b659f30fc0cbf19b9d f2a1a19157f813c81ba6633b903d7c63ef3aafdbd1001206e1b6b1334260eeef 577dc9dae2487db1bb743f56d1a016e8352d2eef75b8439f7a0b06d2484e6329 c405f1ded4cad4af0084231859177e971c5525f1bb1854113ad7c5bc62e21dda db561e3f680279ff441e82c2a7251ac1e763ca0624ea03eb64fa2a6ac72b7b93 a38531b78756f9ba162cff58ca174efc1d776e9c3375d43a366c5da19e854a6a b12e648ca8bec1098b935a509295024ca47bb4f2f0f458cc371afd286ded5bfb e0e9d1e673bbfb6785f45e855cacbfc081725ee4f9572b152976c70166ff6f92 be23ab7ffbe883d989c97c708ce49e6b7847a4b42a78d7a2a122de8e7ed05aa0 d5a6a40407c2aff52cb6d80fe6fcee2cb265517744e655dfcaa45e9b5b159e3f 90e4110de219aa004caa3aed8b67108ff8888aa4857c54ce6d7191e8b11365cb 9dff22c48301e57a059f72497b5b04695bc6f69ed27d12650b8b5e48c9f8f8ad d056b92a46fb72170ff6d95012156b3c75abc6b19a70969ec132f93e628ccc4f c6bfa573278be6a28702532d85b56cf3ecac307a53474f1599bf35ce0c39f692 cbd889739f84e045de92495e182e47d1b87f2979de5eda0e24eb15078756ef4a b56c32d9e333345df49bcf546e4b7555e5820429035314341146e2eb555b736e 1fabeea644179badca2d5a7660fe89f61ef1e1975046490dcc8ab54a35b2ea12 8576859fe085697bb50b74c16b8f8d75e00ec1f6bb6207ce506df6b1bf8dd8ef 85c20f8768a15b7819a3885ecf1c285cfb1b5609a93007fde3e1964d014f5405 13 cc87ef949cdacfda5be3b111ecaf02725c1c901f807bbba49257b4b8d1e35800f34241a9f56106971af83837b87c6f95dfcf7cd2e55ba0d644d41d614a0d5f0647246a1617529e4af6adc449c7d3fd0b599d23fd0a84ff680090a51eb821ad0c61b2cddef7e79ec969b4c4802e709b4bde35d392d3557cbf6e6de2502156b90f627082ece6744258443f92e5a055577754bea0b6a0c0b44bf2c4d7464882f80a9eb3443b52a8d541fc0dd9b4f1d0807b9bc5e9cf6c79672f3a53960fd84ca10445788f3acaa4df522b14b7bbab50e7b0581e1c297bcd0f7f06d43712be225c0fa86af386e1117928a5df4e73746cebc724db20ba3a1a835fd96419ecb851b10076b614f68cd89e3a180b9162482a7def161f48fcaca082749bc0a496ff3f670e645980ab312a193b5c480a684edc9febf18000bc7306b02f0a2671db4bfdb400aefa3d9e221e000cc0c121daf7977005286baedf84fe482faa6276f9816e1300ed0c574792c6539bbb812e0e9dd9414ec9fe7e752b1ed20f4e8e886e29514406ef65cb982a9e2bd4227779549121d5c1863bea2eb2877e656199315cefbe6305c2689dec309efa27d6bbdb5b9bde168e1b747b7606215bdcfba9950f31a6850ad45d4b623b30b09a350cb710adb7b7df91fd7ef369c0f5ff8103d1d645e9c60c2920bf74cfc36d58fafe73077cbfa74c2fa20361a8b24b44835f0f6d2426e90beee9356d310392f802c1a34ab52ccfb3995504546eb3a9d8b6c5b8f977f3180813188bc206e33c2ea3f8e4b43937f8d6d93c0f3db397b0486fe70cea90b3710200b001e292a25cf9de46b3462dab637e9a296d16d034d5ed8d6b5d039ea2670c071982eafd2ae5e692b0b1a66ecf016193e2a7b5b7ef114cf2524a4623251c06acf4780972215c5c375a2a2e4bbe637f9ce7858a6fe084451389be7e4c6f58081ba550c3287f36974dccb9433379067e7626b7ffe231f2469f299dc645185404dd04adb1228d303c459ab917d1237d0838d2171b7b26161b8d7188ff18d8bb0b148295c0fae15b386324599069654d55f03cde21268631b84bed7e1430f7ed03919a1b2d2aa3caf0ef5f99ecf58ac6d68e7f4bb5d2de8daee1a66c9d7c445e07af684f2ef03ec401f9f0029a52dbcfe37bc846eec343eed97ae8862a3d385c095cf04e5d79027b3c44ae288f3ff11b66c480388048a49739bbd9e99f059dd30f1f923b110e21d7e0ddcbc7f92a68337fb39012ca8d6948aaada206ceabe3020021b83759262d5e3a12489d405b2775e072d59a47fa5c7d63fdb9731a77438a07298e3093753353ac9223827fca0599a725cad6c8a1f90630fbf50dc480211100240c4706354ccaa03d4d750caa9785276ef60115331dd1818bad57b45e7461015d3e97ea37e852dfd8202f17b5d9b4ebe72c5d3bf75080536407786a042a1c026a4032e5d1b95f849bef992006147750295329c7892cde5c8938992f0835c40164722b07b4f22823d2fca62826430024f05a251e38cd26dd201e9aaecffe2508440ca1d438be15b7d3187d4dc7e8cb8c6798a0086a81d8129d13b8be9087ef0e8ad5db0979ba37249f8bbe11b22a7ab8320550cd7713c94d36c8520dd8758305797ae9cb593219b6fc8ebbaeb3a1f3860d041e79b9f733756f463cd8c8adb10e8d7a1b9ca71fd87c0294d7f69bf2167356e10c5b5c2f490b4ec1d68449a0b80438b1e5d00f74c31d342aead66ac2a17578493674b9507f76a234ba886666ad029355355fb95489b89682e35e9ad288de2beaf33701e7bd078ec8e9e0061fd20b2e730218958e2479f256030c68c1b97b8deb2a3e2d77bccac3cdd07d8fbcef09eb980a87aca6032ebb34dec70846acf258dbc147c0071def9da0aeb3920ce90ea268ecd38514f199b34574f1af45ab62279d70e15a9b2007fec23c4ce336440c965fe7e2728bb8657ecfa8a13751c8bb611c01d11e9023695e87a199e862270b58b536ee8d2f801a9dca33d7f48854fb432cad6923bdf95af59d4d3fb35b24018a181b272c6206044168b0719da3f473d05c2a7fe2c0254cbb3a0ac51990700fb2d2633f7bcd569ae7146c0f1ecc9db593c4c37cd2954357a469967e393d8b00c555a071c6c057530a56474bae4f3e500d188d3b13f6143181b61cda4baac90d59d0f147a4b628a606d96323f4784e9b1e923478741d06d3cd2a13a709755501511fc6df12c2f735db6ec40edd9f3e34ac653d2710b2d256baffda360c98350be6eeb698a242e14693bf8a7450f7a8774d7aa957f7cbf01660c636141c657d06c19dbe686b547ba6d62dc3c59ae3f5f1d967218aec23fe6b494def21115d5a05bd1301a86442a380152c30bae6d623eb85f0dd33634e231de178738a5eab10024f03f7700efb88122be88b7e23e5bae2d7d9ac36cac0bf308612892c2a09fc066c396ddee1752737b7a820bcd35a681ec7759a3ccc9c0b70f47249fb9bf3640870abfd5345feb1f034cc276f3d3c8b250905f1931bcc0703a66bf6018787520d6894b58beeff41777a509076b68216c09cd6f4a5a8fbe9045500ecf3487f1a003779919555001e5c1749736bb73095a1277ac1acb9859ad4031ead3c7c16b30bfe9e82574e5736a0baacf56cbd6dfd3fcdc2aa3a0d4010baf1d22fe4bfcb4b04dfae9b5e7e49ef88ddd959c23327ded194035f07406a21830f34049db6fcdf0047236fbf76defeca1573450e8bb6f519937d105520b854825a04d150301033009a17f81175d24703c3e5da295be2ef589a46c1adcf3dd0e493af7900241ed805b9f4f8ddb3250abd1c698b769f00624e85c48f95dd5fe0726f19e2c1f0515f08aa59068ffe6eec5f3862536f41e69bd7bd53a5cbf6fd67f5dbbfbeb7e790e3040dc97c7cbc0e3f2d574ddb27628de755d6f7af504f0fb9ce7b2dbb7b6b45cb04ee948cd0faabcea3e2d23a119c4625abaa4231814c25ed15e16d893076e2530a5fc5b2daf9a492dffdc587555068c8efa9c36d64476872e70be513b06638600fef12a4a8682b371ee60ca22b60669e462371d04ef987b4d2092cf44f15126c03 +generate_ring_signature 0b1546a77f70112073985f8a806f191e83e9d3cb9f19e41f15a07671a7d7d173 0ac40cb07f49b58cc8d7c8f9eda97937c5cfb83fdaa0e897e4aa8507cf55f2dc 56 fb504b3a12b0e8237788b91816e395f566762e9d85e276592b9f42eb46b932b2 2de49b9fed2a1379e27ff9df1387c5704728bd81a61381ce8da4d0190e310cba 4b42cb7ed8b175b0d82c6f6577b3c2ab65bf0e0cbec21bf00a6d0a532d508383 6996b0dc98d6d30c76d3424d16591495301a6981e8a4afe7b0b7b0f1682c0c8e 8c3d881ee3a14b52541c96ea7ba2200a17a9ae2123c15774efff022603808f16 c7bc7b4e978d13bc12a50ce744db1c964ea624d53d57ed21aedd761fa9e5dc56 84230301ac02a11ef46e5e7dd0e2e73faf19b28e3bb579374a805a3a07feb800 0f5062ed757ea9f3a1d9680003733cd69ac3077de75e715da4c72774fddbcb78 da0d99811f920053e451849dcb82c6f9c5f6f2e1e0435a52265dfa695289bacd aaaf445a2d1bcf716480c3f552efb0335d76633b4ab6b71ee6bd9460fc24a1ec 1f7884f7dbce7ede89ebec68fbd6765b2cc92ffa7f8c819b1a98c86c0166f142 5e1592fd36141e29de682b90ffd13d68aea02e67c8c75e872ba66690187fa6a4 78f92af4fc0e7fe8c117f1dec9d225cc1a690abe427f626466ad5768a1578932 5f34d7ff989f08ff0839d1df276a0905c9ddee265d652e2be032f59b86686d95 7525ee1aba8272b610df2377c0c275202fe06cc0589b9213e70a127a849e198b 43170ab7baf0ffdd0fe6bd391dbdb7e2dcd1b89707bb00dca9bf12e5025b0fda 8b84df55edbb4cef851c9674e435639a0b147456333b55f2ef083e572313e347 fe394491438a5a7860e525035b70555caced54a2ee0d0d7b23a85abb6b8c6a49 682a71ed5b369424431725db66925de5175d081d65f6a4fe049a5748836737fe 45ad3881f548cedcef87954b2c02363e0a4571bba5c5462d16bf5ae4f2dae423 8c3947dd8a8959059543c20250f6e83bbe841ea641759cf6f6cf0da204dc3fc4 11f235ed2bf9246af8ba9fc067374693fd3150529e05b138dd6b2942b7b8ef0c 57a1abfacc42c7ec4f8933bd93b59fe01f0e49690621379993bbb03ac100f036 0ed848133ef3457e15f0977f10a76d7e535b26eebf9dbdf97264a964214a05d2 fe282180e425a1bd0a8b7479be259067de45fc6e89243f0d22c7565148acd310 81857e68f244e6d5bbb6cde0c7ca8e5b8662870472f78cda46ee11f21ed85b48 545ec00ff569c1ed27563608e09719ec282f47e8517ed95bd1398ccc0f7f0404 015730048da5e50a112a705cd3110fa035634991efda22bcedc9ca6eb6940979 0e3c5354e7e30d619cf5f89a31817892507e64ef94dd9ddc36296da893c60389 9f16a094d0358ef39bbfae78c967677fcb3b701245f66de2faac17fbd9a50b3e 3ea3265959f6857f1b3de569fe573268e3ccd4f4fbb3fafe0b63524c13df0375 1b510080c98faffca1796b5937611e55d2d91ce491789a65df068ba7a06e2fdf 2d1f63f2b1f54755b4a3d328552f79708a3fa6db59dd970eb068845d8536c432 d9f5b0a6f2f92e8be14dd2ce300333d20579d3fb6f8719ef8a8d5ba5a3e72cfa e4d7b759782849314e443316bf297f0ea63370eacb54839ad9a377a54f72be32 be3341838a0f2bc12009e688ca22178361db99df8060bb520740138ddf5645f8 11d8b6d32bc7a35768648d631e4d320ea8b56e932f1a2cbff0d40095fc29f80a af23e51d53106147d060673d7fb4f2a47bb2ab72b2cc255797fcd818f5135220 3ae4c97b960f65673fd5e01d2c92b3220f6b285b748a546027a8b1bf59e8ac6e 76d0434adcad2173c4259116139ad0fde9b2ae309c1c6e332571794cb588d152 08d4b2c32fca4c8879102396427058c720babe1e39b90279bf202931a0f621ae e8e3cc79d0e05cfe951707e1c903524084e4aac4c30f9179c0be50b7beefd7ee bc9c3ed0a2c25b1e59d70d738dd9da4ae3fbf7d535fe58846d523faf47bc42a5 127d126506b2c410e2c8ac9ce472b1d261932e3fe361dd90880864d003812be3 c894d10d2ee5c17280e3e53c026084229c4e9e875cff20d608a1ef71e4573320 02b412846cfa7350e024294beb8fdc1e2587557e8a7b4452d4e9e9eed14c9702 c5fea97e5de8cdfe09a77f6f78a302e9db64df2137117a848c46c79079b6cdcf d7d0505214530ea4cd905270f664d9ffa08585a7ad28123156f52bed892f5055 fc78f270e04a04f38ecc4b754ed926fab86d7fd5cdb959e91b9ad15ab5677b6c 6fa027b87aca6842606c8f8bc4159221eb056c00d56553ff60884ade17445fae bf5e94eef26a03762c215cee6dd95140ef2ec454c2faa05d2964095992a47705 29440b94f3701df4472ac2647af0de415c2fd191c23dbb8b8f096d3f7ff490ff 6d6ef06df5e113380e27e8ea590b8548c81a715de4b54dc9a5d35d1dc45dfee5 c8ead1f8291072758ec6bf2c68a6d31e5f18a9906b3f22b9de6541f4d09f4068 179c75dd86d37ae7ad1ba856d31f36d6a0089ee1a363c540f0676e8dc727be9d ff186cd81fc7dffae43c919c60cc0da74e722d269741c3694c8ea925ead329e5 901ab283171d866625e3b45fd7fe13b6b829a44224a37795a61683e6addd1704 25 775a837f4028bad9749b4ac9eacdd99bd4b7996d953b5dc21ac15e6566665d0e7e90b7de500076c68ec74ca34305f6156e7e34017145320cca59c686eb52cf05c4d60d3d980bdee60897feecd6a57f0bedc8d0b7d7ceda22ab06a4a9ec0e2e074865be89e5c547bb98da5822bcdb92a85c98a2c9aa2eff5bf21f212f8cfeed09c1633b725947aa069c4d0842ed007f9aa8f3fcd3df6a232fd20dbad713f47604fa2b387df7262aa30456394ddd3d4972d7901ba8c54d830f005a87daf3988b00733bedaa0a03868b7cff21b9f7a7b2c5eff79fe08c249f7a119868236874510ea0f2e7e0383c97a7e78f43555d4ed5f1a81191fda0533c0d0215bb225886af097d07312ee870127d57dba00a4bd7e5ec165a53f7c916430e6e4ea1f715a2e3018f326baea21cc4cf50dd031e588bb4d6ba5f819b46b4d23cf609ef0facfd3c04650c7acb0249389c70087564d0340eb8cd8341920ac71ef7101c5d05b76a0d04d6c9e3b7c4a609a6066c408127693181288fe3740758bf4c12c0d7802188a40d8c8a00287044c0b083c3137365ab72cd2611abec4b7a7b800cb473250ab92e0da194616bf7f76bf5848b0f64b800bc320cd05a8273cb58c0f06dc1a117f39c032114dfb4ba47c7fae3bc8fe012a9fe0876322330aaf5f60068ad44c4beac2b0d7110adf9b21a3e5f7ac271fd17fb4440c83a81f16be440215643977861891b0f34da67ae15b691339c51bf8fc0ab06eb480de096ba989ec346b98ca5b7cdd101d0371834480b2ab2aa759fbcaba7c21c44983d51998fd76782e4c3bacab6a409a9ad50b32f69987e9cb1e273117d2f1c64f540f93477c346135a7cc8256446073126e28ff988849a5127405768b21128399f0d4bf018e3db08508393a1ed8705378e795153c9fc6e99cdc69f0cad6efa1b932fa7a317e6737e9d63e17b87c1063577dfeef974e82a74cafbfa84f1c67b0b1055ae2fa613659ff34a088990ae035345fe0285439137c03c72e234872875bb31baaa249df56f14ca0bf0b9066a0b1af02147f735bfe562d207ff3b2a88e91f8f11dc5ee6c0fd769f2b736159bb0fe36805a6780ec62a4dfd121fad7a6ef5f4303302f61cd421bc54b58dc986010c550ad6ff49a1a4b818547f5550e1b132ad887f856a60b913aaeb866e22cbc60f31649c227a5597dcb65a7e391fd2996e87c72affe6d5693a3de90ec5f8d64c0167ea55430816f1f85ad67274c235bd428b0f1b3b76185167c4b7b314f39b3c0160b63afaf1d130495e677b1de3865bdcdc06d22dd14612a764ce8dc71cfe8f0ba4026efd5f13da7368d45a8879a4c0f06c2a290ce3eff4fb79465d3a0bce0d0591abeec4615e0005edf47bd6f73ed4935478d8a52974665429f0d464c610270bcd1485a8b67f7141723e9d4605fe047925e8374d6306fc977c41c1473250230b25a480cb1a318be8cec94783d0d9e8c5c1ddebc1ce78b84728fb36488ff2020d1d4d08554d757b7595fa336d0cde8191f50e471d219e08df5c33293cccdd680eb34f81b5da93e1a450f0a3059f238e4643ec59ea19513d733800acd83dcd0302259cda4a13932e4123550795d63770af8a6533568c78d288ac95626d77d4060e0bdee47ae8db7a3d2336b495f9a3611d69659d5ca7e83c3e40dd1286e6cd040388a27da7674891c4ba96d02186c6ff01564c927c691e37e0056d45523ea1db06765f8b6900b11aa51fc24ee8580496a5718ff21ae9f5169575808d917bb0b10a2076f2f5ea019cf7602051e9bba0c0c4fd18a5ac79b1741fd5f823f6de57ab0e5d8356634c1202c3c1f8ca50fa8a7bb64a286a46f8e322c92fa64c93c739080942f261516a1c7d6c97037d1dcb5f7744a6fd68776309e23fcc4a8d354a658d0d67c88778ad32280f0681db5101493cfe2b73b9e12160b73ed918012cd076ab0dafec70b48a4e8f8a3ed9e46b7a4d24f3995354247eccfe86f1515da97d226605e5e814fd7e2aa476364a67c34b32928e97fb3184e1bffa18327a6f3f087de000ba044964f187570aaaae6ecab02dd2155a4b35d9b45afe2d228fa6b69d72e50eac80b385cc01315ab733e6851cf7168af46bf7ddb8f97d2203d2c7efa057a9092e3362efb0ae7787b86fde7aa61d7248ddedfe906259efae02953250c2502207f336d6453c3a30ec8367a796c44102f82869fb1d8cd15a83878925b976db46082ce45feceb7e5ff50cc41f78318bfcdfde684c1e5529ecd390b15bb3b2e6b402ea4a5ec73a782a90dc80e8aea5fa5a91b0c72a1227672413704551d4ddd0b003ae1d54c355890e21725ee6e8052cfeb69e49dcd512a78a41fb6bf36b920e0c019e80d45da5d6378508cc8dc70a6a332abba95313f3b19d245e5087f51bc4af08542317f9339a58e606aa2333f20faeb15ed86e20afc3044889b1a09904939c099525771d94d84068ed1527f387fa7171d84a83d4ef28aa6a035ea5062e942c0805a161f960a680cbe7fae0411b82699c4787ab597daf6b280cab430921d1970dd17f87fc1626c904d558f2cfbc74e8d9686ff3a0d05d8fbe693934f26b9aa000fb5ef204151bea5a8b39cbdc9150f3551d3d2cd9de389d4fd4db7e7aed3e8d063f461d8162d15bbbe55909cb9da4e4702413471cbc1d957357e6b29748a10608d021f14dcb7ac9761740e169b9aadfcd4727b4c99ccf66c00b41f6c189ac4a06eb96d0f2f3f97825811f42ce789c07c9bc02b24e554aa471559f15f87dbfd601753fa7cce2dc4403e22e365c9bfabb11ad394d041d11c4fda96031199c83160bdef56df1066ccf8bd41cfe5eea2affbd596ff975dc1eb55d9524f0417efebe007a15ef47e71e9a8abbace6b33cb89c40e532219d8f76f51092e9005ff5332f0ada57076e7d0900234eaa853c5fff469e14cad4c404a721900f8d9095c2cb2b00c6e0574787237836ebd0ce53d898d55a967015cc3625d5ff8e76662593264a0bd5b3b0889e1f949569adac819f53044c912827e9eabbd2ccba473532aab815065fce040587740f7f56f79aaf4cd31bd12d692aebcd2a6a9ee9ad5407e65eb50d722d9091d301b49f0eefbdfa3ae7ba7e6e516e940970e125e8a963e3bfd44e0b0b2ef05799af592610f66866f375da52e0fbf9f9bd75d979d6ab7e95e9a71706469fa2e5a12ab5d788fba235a2ecf8f6cd7d3ca4d4b99aaecc73ddedd60afc0932a62d81433e4f91f9fe6c197749334f37fba39fef3bcbc4ba72c036639dc309fd48db5a8a41b4fa128929ff9685a9a0a6036b816590ae7358eb10af8ecb9e05e0a311397c03b0bc5594a6f1a94fc2ab3cec20ea4c7cbf2dc462aeb6372e9903392e9798e81b7ee3aadc603195cc5ffd7b764a0e133e22b9288026877196e909c7718317e03a76cee16b341f769d3666c438184bbc22387f6273e2d7329b460de2a40c00b52d11dd30058a9d49aa70b84eabc97cfe8a6c4c7424b52a4cec8309d8e11866f197c0b36cf097a5dd1cba984074194b2859fde7afd8bcfb8e757c04a203ea3dc101a6aad375bb151eac1b36461b7d9ed359e47e462d1083b4eed709fe77aa12c6e98be0368fab0fd09b0c7e8c4690ce708a9dbe60f2fe6ec10532025f48755e1c8696373602b7918f54c954e1dc8ba0ab1aa3cf78e7f87906d47705d8c4e378a3bcdd3216c944c0d4fc7631a31bc54103481955d59f20bfffd882014bf07b8a5600ffa46baf94023413edde9ae24b2e2b92fcc67714795230405f00473fbe45dd324a7c748e845cdbc87729b8c85631221e83e77bfd96dc23549c011ac0c9cf6b52d63b0e4dc2322ff9dd4c17f300737279bdf178f4a9bea330c30dc7f6b3470d81b338fbf73d53585612128adb9d86df73703dc8b57b6def5fdc0395b4a8861604f7b927fd6f19c7f54b3801c62ea0e282c25901cdd447fc2b790612a1ad62947946ce9aa32cdc4906557a1d88610a078635b3d7cd88df2589880aecebd228623fbcaa4a5b8dd86c1b4b54cb6107e1408b2493c9eeda4b89ddde0e96f832972cbb1a69998799514dfe2d21ae7a00de1cf19c6f19b30652857d4102937914e5536175e3430c9cde0e742439313a6ff6acfc8a3e399899261291a805a95e054eb0d0305cfa398606e3ba6388038780c32dd2a9e34629f77133a4f50437c1a8296128ff523fbef6f67f0a0388d43839b17bc711fd19cfee42d8d2fb02890f8f617fff8c0c74c7edd7c9f1757588038f0d7f2320fa65cc02c5eb18440049f58cf564456958601bf33af35e802b244c2e0733d11c5d25d2c4a11844a808495a978df82c24ab7374b0cb95fc2cdc22efe70744472340dc650d7ba81fa90ea0fe27c6d86aac4ba162f80c81dd51a5b957db08b0ccb2147077e5fc39f5c805db08788241aeec6ba497a8b09416395b327343ad86a4e186a811adae66dd970ac3e9323f2f639b5d9fa9ac20beeb3c2e4596ec5855c5fa0ec13db230ff51a900f4bd76b44541c835a95d52a1d97732773a735b343450a013333e068fe8853b07111a2ea5e48ef04b635609b6d44701c8d63de27bd64f28101053e3de0e65a5073bae8c01bd3e89782df7d5da58774f07c919c27ac21dc7727eac824d2491a00419c18764ff35e2fcec387bdbfab71b50c11bd1863c535ea9593a2f9048dd1c0751f48f2d62ab8a3d383cdc7eff66a83eb88d3865a037f5b6416a63f6cba554061e5f076f31e448933e066821069ffeac74a8b1dcd20dcc4e095f4ec29ffaf20d3ee9ede95ff2ae4bd9dc8a615334ca5f27655c455655776147baa73f58ac1509d659e1c7b3800df8871f17db7a440e87353efc1cf0dd4e13d7381177a2b3b50f9dcb17d6c3d178450f4f8369cec8d2e41584cb9396a95e2cacedca6cdf45da0fb37d8ac92775c798407d588661cb3e1848da4196d29d6a1e39c7bdbb1fcfd20f20e648a526f184c339e5ba2fcb97ccce3746d45bdde60f98ec978c5dbb81fe03a91e1e7ce570c555f270c390767b8680eef6171c1d247728936d1d407699ea0296eb0b6d2f1d11e0004fd9b918efcbe13a16bc5c0ccb9a1b4468eccba6a7760e +generate_ring_signature 246b0d03ba218cdcb8142ceb5233708fdc1f453f1a492cd962e0dd9b191ea00b a58a14933f07ddd1da220d588cd863ac95d4745b46b0bc581c8b608b8aa48f94 198 0db161f672914d04b3da1ef8fffcdb431771826fc0c197e8825f2b16f0e1ff2b 6a77d52d3688f88f6b8bdaafba20b78065cd9a9fbd05213a96a125ca224b8eb9 e2ea7c4d07361af255042d42a83fa1ed8c49a9f454c7a8f6953ac4a25efd7803 fd944b028ccf14871fa10383afe9e30660a86635d20503c3001960c37de2e69a 61410433de0ad6345b5991355caf4432ae0f6d68de7b8b92fbee59a8ef3461e6 b2a13b81e18cce2587150264dcc9a4b7d5db29199601ce267381f912f3950b7a 54e61f2d4c10373f8ea74c8c262df8130e8d9b92529d9f4010822561ddf431f4 243e9f19ea8dfe283cb4cd1532744223a9530328854c771da9815e411c3ca262 f7c880c639b2cdb9f5bedc069e18dd5891428036391b3872de804d2347e06bfc 7899ec95851d38036fa9305b0d06221227ed571c0f488f99357e74d0e97f2f41 b55d7ec0e21c1b1c397775e2877af9d50328d9bc1d1d9b41075b2c82e59c60d1 86da65cf84ffa0efc5d851f16927ae1ce5cfe37f22ca1ba6bcb0b0d0eb64e5f3 a0baec146642142849fc2bbe21b3fb8dd36c5bbf4c4c8400a9a718732be93895 18e7f44ad2e9dbae18937a04deaf986794c4d1de98423a0ffe9e838505218ea2 085fed1c67c7a5446f05ca2258b1dfaf302d2c357c5626db2f6ff1472be6b789 9a7a89bb811e02200372ebe05f263dfea069011f51616bfeaeeef4d06b471123 c7da7fabfc31f636d3357b0153cfb6dffd2ea29dbcaf79a51b0c8d2b9ee141cc b49528744efb738fbd350f830e7c94d14fcf929490b1a7a7ebef9cd3c0506bec d392408898105d4fa4ef7a113c5e51fc9ec12e73d3a3b681895c5d1f8d64f9ec 14c14d0a7083d434ee67caee6b865733aad7e1c6b53260adc4a67ae429001630 d0a66f5a0b9f256542b2f47d20d9ef0c9f0ce902762e794cb6bfd0223bb03309 53640b7ae4b07158cad551f8b87080c9665cad08ffae960cd538eeb202566880 333c1d4edb0dfa89b137577862e6280720ba32d5a8985cba281e9708a350cdc1 9c85633679a683c2c00a653dd983fd6e6939e9a5b3fb1a91857226ec720de3e1 bb1f5067b77b9f97c17f4a94e9f23c83ce86290fa675f0af3a88bdde6a41c8c6 0237b12838ac6dbae1e8129a75907939d6995c2823fad75c981dcd983ada76d9 5222c496e1219b242efb961b9061080da46d7184ea84ba3f443e5f56e6f8e301 1a73f7cfd54d0c215775175106a40c23a418861b0ecb10d9aac208b5cb917dfc b2ff34e86f46a9e541444950f04822c87a9f3fed09eda2e354ee00a25adaf5cc a37896dbb89f13cbab665ebe009de96110741380b6ba0fa3303d025eb2328c60 2e123842381b4b15f6c08d5dce5b7cd375414fd0309fef0f0234da74f928545a e594b714f1b8cb58d6c1784233d1889c036ac446f4a109db65ad3e504759d3b8 44e1e6f6481996fdccbc53330ec84315b23f2e6177a04a838557bdb2bd967ede 21c095ad1a318b4cb437bc85018015dd88f7be33d7a8dd9866c1748e68586c5d 91c5ccad9252630c2ea99586a87420e8af58c3348ee379c2d1ddf0a221b8a6bd 406ec1214dd65890ee515b98612c06de1fb192b5a9c79a62a30119622a63fc92 b97aebdab39ded19b5151cde77e0dba3bf884b20d76e989f998555379e279d1b 2ce46bb4e29bf4020c8f89041a0127191c91609c94d10167a8bfd0a05436c7af 38dcc4af14c5ef185e7eb728ebd9856666ff74e289176bde4e13f2e89c916b64 22858147faef84673a869220da42dd7ffa011b3b344c2e78d5f060207d030e34 efada635606131016da8e1cae06032667d020a4647fb543730168e424a5b8e3b 267cc134a2557c011b156d1b9d5f9d12d8cc1ceebf5e3071fa96878aefb28980 ec9eaa5c03b8773659309ddabdaa3cdcd7007935175ea3a6f5b3b929b4b45994 1832d72a8c8092c0d1edff25076be448986ffb145a7eac5f4bc99665bc4e636d 76ec16c44937efe375a1923cb4cea0d42a394233d00ed4e77461c0bb19591f46 387cce667b9796139aeffe1f79997a0d019299a8129b946a849f5f537cdbdf6b 79106c954375fcd054ee0e558d8959a6e8b100c1b2475c1f2a30e12e936125e6 7bd06529c0c944410e0027d4b418105022bbd479d2791066aea07763a2beca9d dba510ea42aa855ccdebbbb71fcadeffece08803f3c2760c1822a1e5f4fa9663 c98f55e44c5213fd51b52e869c7096ea5fe9620f8b183d484d447ff8a7779778 1dad1ca1319f93621fba40e4b7ffa7c939cb43525421df2b096361be1b8b1ddd 4ba49cac2da0d71749bd8a99f60bc231bfdc4304ba7d33323a362ba045003af8 823f604a64a454fae850acd9267ab3a7eb96deec9476d2ac69c2f013023ff2b3 afcc56fb9d925c8c7172178f518f795dd100013a35a22469aa01850d5a2b8933 3b02bee1a2346707050462002b2e0624a7f3beb0f61199e8082503ef7bbeea13 a5bf9d17c3fcdd0678cd6e02a3a44cb04127c3cbe0905dee1ec3e2f207e8247b 167cf06f2b5cb320d5d8e82a25312c768d176c1a8d7c2a978b0a6b355d9291a5 121f682795848f0cf6881bfaf24cd161e1d48ec64861a2d3d6f5bd5bdd8d1c19 1c9bc3a726a992f1e7afff27ee6cccfcea8f103dc018161d0bc3cd3367bb8424 4a5293fdea6a697bc9a561326b2ecb6a364a38d28d5b51ac517f8ac36a598633 fdb2f1a88848466354fb68e56ce89e17026ca60d049e063a67d85f6a29848aa2 8056d4516ab1042b2f40fe62a3e1df9eebc350f4cd39d7c60744a25f127f9f24 43039a60e66e80cd341f0d915608485413cf54abd00d6f74ae7d6b400740d82f efaccf178d84c5bffbe97a3f0af3f982049f3b4f7ae981e80b5caa19d887b606 532b117cf74e4766c38d3bc22de22b831a81496e04eb9f30cad2cf1a08c2e371 517fa25d585f74a45202d4583f084d656ea1854b0d03219792f4f3a28f23d58c f472a57780e1b0043e1c06079f64664ae911603ea663becd80d6ee23009000b0 eb6d7f2c9d42f5e9c5341ae6df2213ca5aff31308b8e56b6d9600fa2b3283a29 224239609d5215fe464286cedd2a04cf5be2b4865f3867df83543b1b9405ff32 54ce5094e3d07710882a35a255de37cdf2cd31d9b9c121b3bf91ab7bdf65c887 a0665b64ee617e93e6b2656ec248f99b568dce3cdb93d0cde77a59a63153f467 7a87b59a3b81eed644cce872635415ac56b14e8ce1d57758e3b17d208f802ae9 cd266d34ce426739a6817e41b47da687da15d0fccb44bcb63afe3e6d21808304 91d6a6f62da7e9086bb77ef0fa1652678f4112bf8c58966141812a41bde21014 7f11b0dce98b3b5b753547cad841a49bc70c50979cb7e26931188b2805562c11 6ebddd1fa58696e991018d0bd21507c9fac9670dfc09b83460831d0f99d6dbc9 d2a836ad7b06d482f0473cfcca188e2667241e2fac3c61446616d85e2873209a 0787949bbb01720189c8c681c73df597e5604d268f8ce00990f2e3d5f21e2cbd f7597c8aa7d943292de1f422b9ab12ae9fa26e6b029a8001fd6af739b8c5d16e 3938d0588802af284691bacc09e8924d5339abcc01664cfbec99510906fb8f06 0655a083cfc8ced5a2428b8ac6d90fac5492cb59d492b50c82ec706a9ad621f6 e67d8a5f62c1d7284daaf885e438f79fdd3f473cbbbcd7a12955ef107ee85c17 fe075fc6115e419d5e51a05bea69b864323bb3223ffd2cecef6e0c34e5b4e1fa 231b075c7044e047993781d57fa4d637f5df0cee973f033702ba468fd11a1e6e 63be8069804734a71417e6c6492aac78377a94411dc38f6ca94c1687fc0fa574 a71d86fb97b927e7a2c37baa95b6be30bff078fcdea7cee9ffb2ae3032631867 2868f924fa5a7633a1465a19064f6fcf49236cc893570256b5ff83def889dfee 9327dcd74a80d8e531c1355dab619058fd5cdc4fe01a06f037818a975a7fe74e 2499435cfc2c9432b3888b7a2807f192ba19b62b45d7d273d7f5b0a204d3202b ed5ddcc23a3f887ce3fdb9bb25d758312e7909f9535f9a3ff1624cd86f903a3a c32b0e534cbe8a00ebb0576d80b80dfb4b75f5b17f8f38c9c84e3fe49d13bb2a 9fca90b55ba9b6c5f2c050d2b2f1dbb3bd9e5e51e7b8476cf1355421b0f59b7c e7f9c9aef7db8e8dd1078201a3abe2293b43236ab521c8b0792d56bdd3008246 c09f4b85470610997c9946ed24c314d56689990756c11f8544420cc87826e683 38323e53c2f779eb1622324be8a5fb006af48ea5ef5e3ec00148a147b00f6542 1a06eb4466f0ceb6a73be5b1d799835e86f6ff309a8397a7738351b9f5cd1a00 f1ce554ee1a5e1bb952ae702018ad3ca23eb11ddcd1bfa11b0c1c55256b1547d ddacdb96a51e0a4627d47459904ac22d64a220a1d1bdbffe16f5aed08820fec8 0022e83f981f666993ce52fef3d82566be91bfc1954673b07b7ca3ff5fc58e49 4fb2031fc2197a88d496854b3935daf08373093ccce1f3e69486e4b35c35961a 12f5aad6c8f040e99b9426b95229f2498481a69f4555fc2a593768b68d8df433 a356628599009e89718a1d1d6966f28da025984e3b7dbb310de1e39945606db8 35a5213725ccf4d076a71e87981b63097228bc1043506e1c2ec429f13355ad88 1ec779087cfb19cc36ade2d26f64f9bda01057e81ff21fba482aeeed4ac12335 a913b76c8eac995496954feb8bcc402d6d6f4e800789ba28bdeff1025d818bff a75d75ee55b992b952ca5cd226383b3964322796819dba518628f2b4ffb2fd84 e2ea18fbd119c70d15f4223d594d40202614979a08ca9177ed2c8c76862b2e22 a89ec97b2fe0a79fe66416bc90f396a54b020381e2c7942fede9d56c8b2a36e1 1d27f8fda1fb4ebb4ac24e91716e636398c702214188591e68243123e126186c 02cb80704c2f7e0b1776e82a7e16258f0a8a4c3ebdfac82423e3f72b7ee56d4d 9a524da42a15229a1c21aa734d09e4a71c0ee202f5334ba972c59e00b0871fd3 04cb489a417d31f07b8aef25651e7ecd6ca857605c720860839562f66bdf19d0 d543251d5e015dddb344028dc9325456e3a65d33c5de7d3ffa0bc4f77bfac4fd 70f3c9efd0122620789d9b67d84eba1218f40df0ee75fc6e82566e83e888b990 643ac4025e417233bdbc3b1de190bbb1a0cd3c2dc8de7b9ced271bf3a067e391 1f86b62e7e9a8373f99508c94eae94e160610de9a2885dc75a4704f05d569b37 a329f36a793abf7b70440a1b88da55f88de436e4b65e75cee79957eccc454d94 20493dd3fc860598e2953e9fd29ef927ecfc661443285e7f44b55aa2853b8b40 dec1cc91cbbead300e627e6aff37467273a6deccfd077b4f016bb2ac7f54e591 49bf801c8c676cfe1313e692b56aebedd91546d3e3037d72cbb957253777313b de0168b980e3e80133c7dfa74f76a8eaf7a6e39c4c6f5e2bb9cdf9bc8ad94055 26385c685bb1bd0e809fc3732de977a3fdaf31e8547a78e18225b83120bc6e69 90dae46f81b1994f6952fe1639f741006af0c02c44c72aada46d6fe9aab0b879 cab19752deb880f776f0fe03f32025fd7cf1258638a487698a90302727eb80ce 90a85fe21ccee828f07c00b4c85f6d54516cd4bafd16a8b6a6ae81b2b5466785 430fc038dd9548be476dba2c31c6748c7a354e3c67966d3250900dd39c809e28 49a2d2e4c02a5b94b5ce54609f7dac32aca0a4b2051b784ade638db8df4eecac 4d6ae1194d575bfea52a4e09266ba41676b7a552346100db98908e927ebf18f4 1b0bb0578845f9c1f7c568ba36e7936729fa907f6c1a8c1899229cedaa1aa306 10d3aa986969f9c45562adacff4f74cf399294ae3d6a56c6ae72135f51ea90ed ac69f664f096b6a8684c5f014a8b984f1eb9ebc2cd7edd2b28b37ef25e3147e7 d348cffc84741e63d73f26e953e1a0c6dd8349008edaa22da7612600561a5ff6 d8513404ebf2c16f6f7775d3586391168e0846a973f2229d569a12a06429eb93 fdb70b83761ac9e5f0efaa7af09e44edb8ffa0183b75ce52ecb5f6dbd0abbede 595b8d61b840a5659888c9bc06ab291df02f4cf5199157e0a5b509c382198067 54cf1293b535ff5aacc99099974dd99a1261249472edd6e6b4086fc1cba8c90d 97c875ce3d7224207c85371c7b1def7eeeb5b4690762b719f9f04bcfb866c479 c348eb0c65094a6127d7fc807507c8302a1c69895a97364a2f01ca5482a20cd7 b1308b60a84a9941dd55462ede7f9a54be15fbbb3cc28d7d3479252d0aff9563 c9517163ac2088e0387a0cc36e85345d134fa4104cce020658fd8f542e836edc f64f3d2a5ee687e1f8dfdafc7b06b3b62f1829d4510ae5c41d1e637141b45f80 44a63864b9473c34d0eaf8ae941eb127d8413c6629b8c36fb08b0ca4dc214df9 93a1bdf9e791ee990bf5508b6bf513409cbfb4ebcb16852a38fcb493810ae898 fc94f570800fb6581c4eb3d277be0a34891423b22e1f3391fdae809f9e75729b 12122063caa42018d7beb28e347bf7c0831da5a492b9faa318f822ba6b543008 0a6544c33ea85db30ab5ef3944aa87b5243c6e44a3001f64ef98b86edceb9520 64b6729a7871fc0f35ec31ec51dc6e444b2a5afd02c508e336305f46d5eaee60 bfb50061c92ceda81088d5698f56c4ec4c554354060a38711460332d38e21a33 d77091a9d6d90d9e8d68d1070ae328ce59f7a6a6599068e7520af35fee82fc94 d09449e1b37600ad3a249b93f2decb928c3ab1916c38cca9b56c38e93ef4d987 bd1feb8de1340e0ea9a15ba6ea5bc4f897f0b3d86ab4b882743620cf7133754f 00ced965f3ad93b796fc644f608b94f5851bb8be1559a5ef9a072f07437cfadd 610ac68246075026e34fe339cfd31c413a4fdb201bd7cfe8773875ec5f08bb79 10ef02726da9fa5618dbabbe19e3670ee4167b7c9228f0c9367a53cd8c5cdd95 0137deb5bc0cc9a05e0f12f261da6584942c556c0598db0bbaba1704362a8fc0 f69de7e6f5116310708c3395a3e4e95e4e58aee0cf39670a69d167cb308daa8a 17a8dc951c11526dc54a5b877c78de0267a21841a3fb137f0037666f996795ed 28d84bbb485761c0177ff4b35cf8982f98f7092339e8d2fc448aefc8845c0876 540ffb7709f0e719fb5125e443b79c3bfcdac655671d33187b750bb3a27cdd59 b7e545642adf2ca59cbb67c5161f4fa5c82d42307201b55b55dced00107de1d1 bbabd53bb8454036ad63cddf866f7e6942a5e65d740efdbaf15393a46cc2a5b2 6a19d37e31a1d58fb394814334fd5a85f9fcd1bfc3b816990292f8d81eb2519d 98393707ff0ee3143d5c0e397dad545f7edce40c334f791df327ea542d31cd75 1f71b20fe2cd0064eb2688696006fcb45d5ad0b722891bd7c8077d9717914e01 3751f297c85b2064882e0afab06492cf1b103824cce5c111e2d841d8e8f459b6 ca24b137032418a3d5805e53f04ed21bf57524caaa5cabfcfa19d48061f5f612 b89270edc915387df517efe1ef3d13561001ac485733775779affb438e71d8cd 051a33c231cdddc05ee22d707ee5e8eff9d1ea12dcee617f7dad29210e08f6c4 9119b076330d06caee1dada7957dbea09e03144a122ab049bc0564818823ccaf 04e925699f33291b1ec77269f0f3a02ac1013939697ef6e1ed1c040ab59d213e 9ffcdfcbc96482ce62bcfff69719e9a6ced6e3cf172d0cd234ed9c7e8e5586da 9c35c55dd07ce906697dd1b1951fe1149ebd04cd7f31a0261804db2990cb6274 359f282831d45f2d2f915dffe9daeb8acfb4d99c5e2f1be17ff3671b378a80ec 1c10d7e23136bbdc3b829338ec8a11bca411d5faed84fce332ce88f7426c43d4 6a60603aeef94a7bacc061cb070fda7db41fbdcbb654a4999637af158acdf1c1 97ba1f621d285ca0222a2e31ad7685dc7aa40921f8e9dc0925bd84854d05dce8 6ac558b2d25d64f6b3ec05a6f1515f50474071883e3212cca0f1a84deb99ecd0 e490ef89f3ae5442e0e7afe3bab29cc80801fd82f32b65237208a5644ba942f2 7a904de44a30db4455676a6cea297a0bf420f5e9cfb9fdfae8aa833995fd7c65 58f12241a8a1ba839dad5b602c6ba45cde6113125e59f9052da4c832d14a66ca adef9f1a7a83deb20af284ab72e4fff3c573bd3dbb991106d40f4f725f289c8c bc3930af2f43c34e6d904ee625bd2beebd315d583eb7523c18f6958526bb131d 86e0d0697f039e5271ef13abaa28ff801f90e6bbb79ea905df55801bd0462286 c239f19f3a2be47fcd0a23cf95ec09547157010d8e6efc3315651f23e2655176 99e7300e40160c9b8dea5c066c1578aedbb8c9e35eebcc8ca77f2b2ea2b02dff a1a55f538026ddafba163ba90b5f348df85a214e35420cb11477d8391f62031d a298dec7818c28ffb74b359efcc38eec4b32c1e73e0e8881febd3bd04da66040 b2bf08059fff6b7ac09b835bcfebf106c4386ffab05295dddf769653be295a54 6a3938a46207a8cc52ff35a881a7ff5fee19b918c8d354ec074a2943636508c6 4e96f1e895e106ca0ee4fb9ccee77b63ebbb14c1d514269affa917a0249413b7 4f1e9be08fcee2d1ad61a1fd15c8f0c9a1aae378a763e1a953c96254f38b99de 8321c7ce4d12a3ea5003bb741646c771079875712d53d9ad50068e88b7de9fb1 d0a5e457c374b7d188834afff3ab9aae45c86f7db697b26b21b7a8220563c46f 4565759b70e9741178085228485c81e1bcfd8a8ed97b9e80850b7052c3bc7ee8 133d0f3f9a55c3e714eecc0d582a6efef92f78eb607e03bd505970d631714a63 83a5bcbd0ffae9cb2f11def4f599cbec5bfb02705415ab68dde796c121523a06 c9028b0ade18d0b941882b9ad366b079ff9b1074c0dc2b9b1286f2e3b8e6d15d 3fdeb6bfffd1afb9ebfd745e369eb82c8a328985803ae385f265e7c7c5417370 e24eb8851842daeacb0f9710304506f90d32cf3c49ea8a8463779a8ebb7add0d 25 8f3b87c88dc4adca7f8b85eff3e3d64bbd2278c92b513e89f269598ac170440730ab0f83a0975a57bbf932d596e72233156255bb8f75aac45c173168ba29e40230c5003896cf9b2a1a1b1e594ba2742435c9cedfe576714d248e995cbcdb13069391bacef5055fb0562796f076c46ca59124ef5cfc5f68a720233296b3991b038232555fd81cbd09423c05f7cc34e2a802e5767cfa62d4d134391aac04629c053ea0a240c5fa0e08bb31f222d841cffaf0dd98ea58ff9b9f98924c84e2664d07120ab9995ed6972b6199343cb7bcd6ed511d5f051e4d9ac07885ff57d9ce6602fc2de5447578204e2802c4b08ee2d70a756be0e1500a2aa0b0d25d72eceb780383d9840d4332ca8f56aa43e08e31ed5fcbf982f6fadc4b75e2d7bb8fd3c8ea0bd261d27c8edc81bfe94cb431e3a56646d7c73158312b058f1928b165c75d2a055e56621219f274c79e48fdab342c9a4efd2e50414d2deaeb62cc7b57facb9906d7df14f39d7f0c9e5cbb966be6907fb04826875fbb5e12d18fb6bee5cf37ba02f259769ee50bc6597d95bd5b7d79f20d31196717698d920778f83c3dec8195033b7099d88cea6f0478164ae6c9001511989ae3acd759b34082de19c0dd28390d68ca78138739dd60cb5284c095f50504a470a6239689b3882864d6cc042331099a2a1669e55046b106df947a28091601618525b34f3f383c9549f9e74b0a5407cbb875f7a1fae649c93cf48528f25bb5713f79372e636d827037f343496202033e5a4aabadf8f5bdb2f1bac693b51b558db8eb6cd933515c0675f90676b6ad073e05b8b4ee373a098547391b31ad1dea62b001a9432df65ee2328a3ba8637b07b22a4086b14ebdb70937f51ec7ee20f85e9b2935d8e4791c8aac31dcb5d4a1077a995c779baae86691a9b89517c14044d9e84ef9b2770363569ee6c0520ae30136f6c6940e6a089d74d2a91a7c5bb7016e986f538109540256da1aa436002006e3e5ed41a940863253c4eacb25faa05a0170d987913b2a51ca8f29a4fdd99e023479c0cb0478b11c5ee4b9fd63963117715d9efde2de988812542f301a56880c791fe8c487dfc6fa229c511d0338b1e81926fba688c09e722efc7dec6b9c990b5e40ab8a9175a7e91f53ece9b991cc6913642217332afed0217a57b40fe62d0eb511378d1cfe76a316f8c36339a647aa0bc71fc916e5b9d334bf0cc1bf7adf0e7bc27c7f9ef44603eae38eae83d420e9ddf9fb5bb5dda168fc4af47cbab1370d0900a1ee0ba632f8889d6cdcdf44df62c3162c9de25340d2b406330a472c7e00c598783110bcc6cb69bb606005bbeef6b043cb7ba652fed4c012e987ef26120bbc025592cf475bf37e8fe615282cace19588a8f396f1dc88a02b29db0d74fe0b18b2c0a63314725044334594f8766827ed7279b31e16dae36f682497036c5e06e096e63a2b5115eb72985e9c798571272952bd9276a4b242fa5d23c83e0ed20afe4d88cc69c7de6145d4963d87711ada259b3cde77df8db5c0a3679c0be1e608e68e09bfb25f17a82864d44a5b01394bb2bd47e9bf0c4d5bb06ba6854937490d51eeb4952a307e1484a285a24a9d83426395bd991c9c2d1704f41ff355b298060454a052881c0f6a133cc9d38146512f6b1a8218a3bc7b32b062e41451f8c70d8d6dea558bf1c8dbfaa1842758a5f05f0377f35b8ed567b7bf48da58e9dc540180efd88fab346c66b87f14955c8c12dfdc63c9069353a3f731ab91daa0831103813f6ac0c1c8f74f86366afd925913c08b017306499d507c72472d3d10ecbf0e72cee2a2425d35170221e056aecedd3081a155377fbb51cd901f0d2f02b8df0c898207071f47ece88b1dd2c10a3f5f0ac904fed7fc48563474eeda726b84b20e79428b1204d475d74eb519bb6598d976455bcc90634afbaf0d965cbbd42fca0650d2abb6e6a4443e052bbd787efcbea78a1e3ad85f0fd841e2152f23f45cc5047fc8488359b43b4aa998e41d44ca2ca1125d1f4d63d7766cf73104d4915d8f0db8befe72f1f64871081577787f8f1db19ff0067459513742d1c6e4c5d08e3d0bb938ebbae33ede5946d1e40f985a7f452fb76a614c8c1bd5556cf6f8d712ae005ac78ce150c16538e5914c85a852da119cc0388f6168f894b9530b6440fcc905fd9419e0c5bf1ed2673b41dc533a80b6462eefd42aebda44226bc58325539c08f9306b5bd00952bd77075afbfafd124999cd637bab85f3c63976618c7b3568004fe43689306e467b9b9d273b5042d2926280cb978fa3efcb707e5b4f983a5809c1582f02de7022aae6c9519a5f8918a0707c2119d3569e8b4203e11cde96210529ddc5b573a48ca3f85d10e920eb24b944c0e15ae88add3e1e81ed7c6361290464f8dac9ccedc60746000107a47699a5473dfdf53700381751957e02a07b0308405223a6afcf95e949ce29612aa7ddb67b5ca47edf272728420100c2ac5bc2059fafd5d5dabdfcb1d31bb71b56de855c1d8402dcf38ba04cf6a8841849622806be820a42e871d70b840ae945945df131eeeee530f290b8f89e5fb518d107ea016265ef77bb910c3cbda66bd7381bd60801c70549386cc06498411081cc891409a7e99ce434e2481d5824e9ec0f7c4e93732695710bb852de917a62be9ffb040b0ceef880075d3318cb028b47f59363ecd9925b27fd987c256eca83f868426b0e8a5d3b408940d94195201b9e3676ebbdedeaf30b4fe3a35abf36d4e0f2a1dd07d4cf8cd7df4a68b5c2de1f65db90d8ced5039ed98c6d5b54cab8e26e739e7608a2c0061a8ac18a8c06da340a6cbd2868fddabdfa3e0c709ce304e651e8b08e08d38f570f572a681e0452cfce934cc4be342cd030ac2db872581945d5d0b446029610934d35e9ebb44629d42b14e1d227b3cc717cebf39b1c382b63d11e930603734922d22d03e0d72c2060259e1b71d2e35712feb498a2b4919314d5aa467103144494cfdffaf66bcc705937fab5a477bae868d0671017cbabb4e7fdd861990c29afa675c3fbfafed07c5e6df79ba67b6932f82bd5d266833acd4505166dbc03e325fa2c51b420a6281c0c17ac57970b5a3b2407b4287f8490fc47bc50dd430b544b4e78a670bdde495896ea2a5ac55f5b16d28bd00bc847e618c015719df90c22e0347e83b937bae5cab1411f54ee6a88b81749a84659c338a6d3dbfc51bc0613390a5c44f3155f20c4c8b7d7ee8723fbad528b0374d00274592d9d1cb4f0042356010188bbd30e40f5b63068871de6aee6ca4ef164443257e0539e9322b00bf9638e41b96fb93f429fcf4b15d2846f79e71caa2a3e3e348050fdf5d9122d0a182cce663aaa350ab818b7dfbf23ce4b373b004cf28011818bc1592dd9047505719b94a330fe25192d4e566df7ac855108fd15695eb0625895d679a370ef390d718a7da5ecf43449d3284c5fa53af73efb2caeccbfea0268339c03645dc22305f4dce933d41184afe2a2d8fd8cfa18483c7a90e188d8274f4d89cf796d70b108c57411d249f1607847595566a20b430b36011bf74f0801863ca1028dd0489702569a85e98c6e12ddc382f3d097519d0551116d94757666c638f478038ac0f5002158da5d14b8bd9349e6aa9f24e6f9f68166bce65d61dbede0fccc153011cd0f583e3f0af65e0aa84b1426fd7c20cc95a72acdfab8a09a5ab1ec1275981ce7045170fe75a50a7b3c1de6ce10a017ed9d11d675c4d9bd86615131beb646b944076ce8557fdbb9614b40ed8b63dfcae03fc2f3ac6247c6a5f967be9f4b23f59f0b68849d1434be889efae22768e7f3c3b572a9afa58d1f824079c4689212b26f0af5dbe233618c5a46f7b575dd7fcb22b51c2c668fe35d4d9b124a64a0929c05053faa00c2ad98e97e27805aff9d3c23c66b74e342ccf48d5a44a2c25f2b791403dff4c04d40b30be1cb10b607a399ceac6a1d567c7201b5cb1d68fcffcca31c05f2aec81512a05c54db85972cca2412211c7473704e9e06ec856afd77b8a4350019a9487e723dbb104c165e2ef621b1dab018564fbcac873c81b5997543d63206505e1fc04c4ec67942039f399c5dd9ecdd99c1cad6d85a978813d1b2c824180b752f4e9ba6951a89a5ada46bd08fa901ad06beb5fdd841d9012eaea30a00d20be0ac0cdf675a023c94f0361f11464dae390be8ec77da865fd4fead09e29da70bb41a4cb873c4ca9a1226c6bd825dac965f705a9f2bfdf91791d6b49d5f9e4401ae5f56f1b39ebec11e0bc52bd19adab9f33d4350ef32eda32697ee371a5f8905a17370a57b9ddb10c3a59d0f33105dcab393b615549aaf791d1cbe92e920a80b020970969a06b3afce3de607e4118db0169e988f542e43d76a03c5ed9ecd2a0a20c66da2407dcbbd069b179b800f29c482126ebe32e7174cdccf063beb6d190efde1df5884020e4c30c4d8fa83807bffa5199314f05b2b1fb8d3842fd15c4e047f2dac875263b2de232dff225f24573f7ec0994f7cbfbe3e50cfbebbc61a5f01ba5a8056d4721bed705564935fd080114c8b37873742e416c04c6d897b6aaa0f638e0d96c809f8e46b3ab671e37e8cbc73ada9f4ceaabfebf7c32c50a415e60f309c0605b88875e377e3d6af881e703823b36133c2a1d173e64bc998102df70005f648583b0024d9c56a45689a711f89590f7d7e3e1f7cc906c776ba3a278304402c66967ff338497897cef8f4756b533acfd2614afde3d8dc7677411484590cae3e747189445add323b37794eab1b61ddf952ae72c0d7e47f81560da4a9c40221f4e5848cabbfcfd67fa623954481857436131ae689b1c61831bbb9bf17770f7627a53926097f618ae0e6e7106209abdf0164e51264dcf198b5ef6a08f4c10faa9d8ac222f6fda070612a9e8dd051c20d1258142c67d3ae50d4101bf58a4a0a9d1ee2a14c48ee45369f2a10688d7da8cd331d5765a7f5567cde91188875b500ce6c9bbe42be21af3c550215b24d08cac0e09a259faf427d3b8cf2a990b18d04aaba48404a896bc92c5aeafd067fc325a2d5460b50dc92d26069af2e57cac40b4a8d2dfff81716189ef2a8febb6f06ac428edf6d1a0cc342b7d3389d405445059eec86bb56dd4034459dd9d6bdd2ee63797efbcd0a21e74f5509cd3cccf0a10ed96c0942a02804e8c7300e8d094bcfde46a64c12d87c62552ca5df1730c3b0066c98067fc7c50a810f819b16ace8e841ed6aee6091b1977028a992df92ee5200ec9ff4919e8106fd9815e7f9ceb91b1cef4f37dca1962ce297f43f2fd5ebc90cdfe99c8de010085ff020fd2f53e5ff9c5a693aa856c9913b2d6266f0f74d4500e5139b5e5076c94c66d7ed42260fb5d4f93e0910b6ce736d28ae1baef6c5ef098cc3fe587d87a211ed80067354a31aa33eac4e6eecc58e7aecb385fa4d03090873a9b28baa5fd69810e0e7dbdf1880c1e9faba696bc17d355babca58b0635a0d2eb6bbc0b544dddb849f42b92ac6f02b5d94df207f4d68e584918ac1f85d800152f7a8a21af8382749d23a78375d30bdf760ecde8e77bce87a0f640f41778b07f8cac4ae1d0d1247ea8cd675ab94ec057666dd5325b6c8f898553e8ab5a88f0ca3ed47ed793c289e7a198c5b115f6075c1cd170a0717f31d4a14150532c601070caee6aae8f7f756ccee18b28afb327f0902800c5648a23551358bf3e661630a5ed926ca2fac1a2b872cae900e19eec41e565a52a9243e6bae3852e263ae2703689c2aa49f520ae01616e2adc70aee9bd62a78ad63545e1a268661aa9485ea0179e99ade674e0e698da1c8015b284cedf8bcc6cab49e964c34c84713537bb50e495cf0e0476664ce5542a660133495c993ab363f39bd9eb288825b764e309e024f3672b263968374fa854ed0e6fdeb25a11a81943cff7d96308b68a8834dbe088f5e3bfe4a6b1477d9248d89eedfff7d71805bd1cdf81c18475e3a6255532806c14bfed5be4f67fcbb24fda0298dbcb1d12a3ac8e64c582dfd2a359d8c64fc0d5193a40ca88f0f760a28205950655c2cb6dd3e3445926c274b7bfb92f6923203d49b53ba5e591169998293ac19f23c1bb579ba937f5c843ba7f5124cfe12cf005d1ee3005f897c0d03091144207e3fb353c37c6855f12c96f60dc4b895480f06e84876bf871e1b0a08e6075bf0c2387e8f9210abef5e51b76e1c236cad84da0d5e63e03d36b55771ab22c0537003128bdd9ce9ff6ad2605aebc9f8952509bf0caa108acce225571004155a51f8f3ea552af7a10647d4a8b3563e4f6b95329d08fc091404508d87aba2246088504539c113fdc815e78f41b5edbe18523a944d087213bbca7ffb46514164e849bf0837b04838809d5e4bf96b06487c560f074b0ef9222f8f8e2a1889bf8b49053d23581376ac4abe4c45934b6aa93fee1d6e2e01e1db0f08cfb5cccbfa4face2b012daa3cd84903f7cb107f44938385554dfbe024e9ce2e3d9d000f53affae715e90279a78435e33127377bd7fbaa9054be6d00c7097737056e7565fca7792edbc2984740099575ea3c1f663d3ce237ac6e18e017aa614fbe5bce8c90ef9a5d58d4d5bd3084c7d4c290a8f4ddbd9add898732e02ed16945294cfbd77500ec361e148f3124213d8f8476a43b803bc377919880d0f16cc6cdee8f4512136b030c0335acb862fafacce525b977b3484d591b2c93f0396a45f559f0bcdd53a3d98bcdab020baf7917363e5ae4ece87d159e5d49aca015bb7df31a82a8ff485e3f41ed1a4dd45fd0c023b3ebe67ef5886dd73168089066f253aa431556dff8d113cbf16d8fed89d6db3baf83099b77083901bee90dc037e49e74d2a66f3e2d93db8607ccb946423f4c6b49833e814ad384bdd2ec6a9020369cd7c1717ed59c7a526e60d01cc166ad8f3b000095b79ee8f90cc4c272600d3aaafca34afcf7131975e0517ffa74f1e0ef8e51db38d0fc0aa90a1662d880ab31a000deade65f92768c6a7419f59ff25ab952f375f42ea249184075aecf50ea6ca7a1cb9e374d1d7acc7d7be78344876bbd8cb87fca86b2709145098764f0a0e823e57d69ace750ea58bf6f0db549531a655f23a85d2a05334dbbb55d6a00a1c3a1dd6472017f97436898075557af1dbe64e01e5ad22bf81be33ff0e2ec00784afa88a698128fbcd3580ea2303611f9337f1736fb2e23b8398f8908b179708342f3d6f586a14bd0cac0ed841098bd9104d99519b290dab5a8d90d3174ace0fd2e870cf2b903b73d614d4195e7f8dccf4308d3f4268349c13b6d02093429802665e2111af809831d8acdfd81aae3fe4ff196f33a4d0cbc93eb32335979cb40efa5f14a8120c102c979e98fd02d12d9a064a93d0c9bde6bc09d4ef2a22258c0b93c772e3fcbca3545d533c88d58f83b1e015b00526ef92b76f24d3061c4c7c0a106f248383955392e8f45fbee1503ea8e6a7c0e40dd1f451fe700ca88501a007280f337d5eab54185287ad30b921c454dd20b351d606ce7688cece3b3016a30db7c2a3b7e28aadca9cb50864fdabb82a7b4c14f072cf0ebbc90ae94b9299db0d490e612214bddd78c57459d55be8f40dc815c6a23f12f9e3172e9482d2f07209eeebd59d5d8c2aa1ebd5455541f26246b5a85212bcf309c51d8cc571811e290ac2def5cca70ce7be0259f2d1e3cfe5657df05e776c24910ccf04b589cc6f1105f06f200ce863e672703e6040e1aa61143ebf30b4f8d06bb951b8037241c21309aa6e5f7e5a505b817c965fb5230a8cc8db94bae06c282225eae54b8fa3bf6402a4ed950351406a7b1fd6ff2ea14de9bdb5530deb1bbf88bf0a72ec0e31ab3d09c937c367f3e97d7f20ef150c6be10f03acb0c89e63d46d64f73c31508eff5e059e29380453d02c27c28c51949ee208a8433ab61bd1e776996835511f0937e401ec63add00fcbab6594ae38cd63518436a5533b06c9593282335ecc0a18f242004fbf2354935e1af783c20c2789d01e480b3255dc9342bd76065a28e904e0780caff08eff84bc92e0cfdcd324870a227c9008fd7396274b33679aaced513a670e5b6cbfb0b480eda0d3a1001e0936534ee564e63160c413524280a9345b66d90a9b542d786457984d97bcfb82f0e7ace032598b9ceb2eed153ba1a599c7b452014c509d49f481ec1774a896890723100352c78275c4b4a053a50ee0440e93770156065bbc1c2d9e14ef6a021816db11bf6b60cb95dcb0d11891815cccdf034e012a8c0e4425aa83c2206ec7d7792522bd394d176ddd859316f5f5e9ba51f6cb052be14312239919f1abf04fd8d993330f59b6bc202379695f0950aece7cb3110b1f6e540fc240b9011d9ffefc208018993d5df994986c3374e2bfbeecca834d0fbc804017f8c86d2526b37aa833cd053d3eb1bf63564aad4d7aa653b5c139b109f3f7f2013c9a70b5a609c9c0960ca43c42e8c4327748d33aae982850da4f690fe788cc121d73eb71ea878d2f5f746174c46b49a486ed1f0e02ec5c7c17f9bb0f51c31a90e16362e4327211e8f33804fa36803f298d8196c0e708d699ceab7304bf62b94dd15a657949fe1f67d10ef6d2fd710aee911ef0570aa599317d45f40660bb1a8cfa5b25f51a93d746660d8095070f1310ce72ac7ca0c0d282991b080aea67892f63c0315b3717044251923f018e4ea71cd73aee1ea535fe4b97bdb50e42d06ae16bc94209d0d3e317b4f06330bf7a5050dd79b631c3ef5404b9608d09a95ba6e87b631150a661b63a82bb514f201c0b0fcd670ced919023c7c15fb2062d2deaf0ff3a6c5c003bdd29c0322497322c1e126f3693dd9b5348f032d4200b68d984be379698bdbac416c8c3c91cb7cdf5d816320888ac4f6668b4faaee30f7c4a12bc65fa1db5f9bc9c8c3ea8cb93c016463b1d05b3bcc1671fda8528840cf5689195a227306035e6291af75514012a3b21667128821f6a28e26a7528800c1d83be7e41d78340bb4fe140b5df70f37d62b551185965fb8afde3d986a1dd0374f942d95b77eb9b56e3af94e93996951ccc64ec67c27388ef6c035d055c1202741f59f8b8e0b8703992e086a3bba8adaa3f916ce0ad5e6750bdcff2518dc807373c468728183e05f46bcdea1470d8d798ae7cbc2955671bb8cede79fd764209736717295f7f10ce1e7db42e1928d8f0f4711537b19702078d2579f9ff3169072d9d086c7428e89be222068391ddd57225d6908e0283f6981539b926e95b540035be300781440a1ffb0dadb4ee1dcbdce0b3f5e596ec29116a81a0eb6622470d98d8cea11b261dea4996a426bf66eb63820706bae1ad65e864dd117156e71202c4a51bccaa7c50d4651b2a6a18ce1f73aa5d443f531066f494e950f8771e900729d5f4b5d8bd37e2e947f55fe0e109bb67db3a2335add8dc49467ad71468ac0f1c6c2552edb05d797ec2e275cb3653d0089eadfff5a1822c94c39b331bba7f0bf5b6b92904c9fc6ba8029bd61b18c540aa2f6fda19d9dba901a11fa43033730aa8f9976f1b307299007eca72e21a0b9f1cdc559081321bd18acfac996ce0150795611f1ea27d57db1eb548b9b83e9875dd38f1481d6c14cc19ac880d7d2508059d2889b0c4a4932be1a6aadf7999b300e8fb5aac17354b57ba74fc5b39f5860aaf71f5b076631468b644e3e8efe2d2f6b5fd009d35420cd4eee378e4113ed608b5ea394af859c4008674311a478ad64ccdd6b9f240ac896ba5e1431c45c2e905de4e9f4fc6b6b22804a817ae2f65c71f2739236b0f452ce622bb1db320b2690e6513f1c3cf8382d264b01a9fe8175b9f22f4752fd7934d37c8d203ef3af7fa0415759656ec966e46e8661f6d80a05205ea095fba0a5e1183ff625e116d9f4c0a3e3112bd160f7fb0a42df58c96664a0fde979e1c1a6cba1643f1f48895d4a607a92d715b31b68bd5ce1c2a8bee3f34b6dbcebc56bac2e480f6caa66b816348096602e3c9f49f2a43a526c7c252513c6b6289731c6fe2e9f29f3f428d608db0040d182278959804dab293cb5d201d49fd032557a54188c555b70dae8a6b36ea08314fcef701c2edc503fba49ac0304e00bb512fbf05ab2f7117682129d87c030e700155ec01b8407a6ec7f40ee1add38ba72dba2f971c95a06c257df268545d0ee7420822d8f62bafc20d3c41852a22784408caf29d87b1e8743a43d146fd450143435f388d53d027bec2f3ff634aea41b98d3fd0a91fdc5843f5aec3ea4fc607986bf868c4839d767efdcb4cd47fcb9854a0c8a464aae9a569c54efd413e8c08de1136a11a22e37c9638f8bc144b5e477cf7aa521c4bd2c3c4200cea51796e03c54c9f30baa7b1530a5d0f19b96f9f731cef39469ca82e8fb943f7b72289db057bd851012bd066f97037ec08c16a5e5bdd3ed6d58e06d6cf62d14e304253f0061ad2a67ace7909d5453ca332b89fbd4e73304778061b36f024d9f68f738a050c7df2bcbfe93d5768a80b5647341a7e377be710eb154a5d7cf1f836d3e2948401c38df5776f04bac6bf7ef95c4ea4afaa066602fc2bfd2ec7966f215fa576590f2b12ed60a54017e42d4df0874c7ca833e4c74c6b104439ec14f6c0889f713f0676fed40e35319ff57b391d5cb1c707307b614eaeff8141e44232bccd4ea7140853185f2384ad78fc0ecd4262137d4a4520639e3d8475facbb0e8540f7aff7705a03f7055b72013db93d3626c84b9a2e95db0bf6cb6296d82225e722ef38f310cfea17f5dc23a132d96d949dec90b9094296826ec34b4e915baaf3b6610df5a0d8fd3334b810f00e1e06e63618adb3bfd8a9e7e1478d1c3b1b2e4d5388248bc0ff2bc6b13a057effc9ac818f3e0b4bcc46f9bd36f3a913e28b76a31aeb33fc50839420d269f799394d86efa1006a61581f464b099e1cb3810993cd789adffbd09087504bca594d90ebaf0d18648de5f80cda5d8a64018cd8919b5e021a3d5e005c00da6b225b8315e1b6961f0b2fab2aced687df2a3c0dd14463579703fefa90cd45313ae0ec87915ee9a2fd71e47c155c0efd00efb49c88e1b5a193946bd8c0d086046114c15739c423919beb362923e4386139aeb1f889146a79fee23de0f01d4176198988ced521653793347cf193de33b42a904aef79e6bbd02bb485ab30eb4da829d4139bc32636d2e39a865f058ad516777a96171d567d07cc245041501f4f82bff8674c47f5b21c9fbb9a4974ff1516c005c02b94a4a27a50536926609bc0ae6633d3a7ff01ddb28b0a2b687617801b9d3ff42d709f7bc009d9b4f9e06f0fa7f66ed13a8f49e4d97dc6fcc8b95c7d7a88f6af9741d7c6c3542ecb84a090e4bd9f5496c11b669bb3be377223909d374af355cc579b9a129b5108477bd02c8369ac5f22a9fc44899890e55f8b59bb42a98c3ab61ab260d5da7f3eb98ef0f8cf10688274b7d6f81a89679ff0e6556d8aeda589ecee73b3e5a62e494a92f0af36e805eed96c63b69c6c1e139a11b98c330711075bc90d55ad592fa8fb6eb0c96c2277fc1cb2390cc3b2cf48b9251af71a9c81465517cc650b1b9c69fc2e60d6c20c17da0cff1ae874af430a43ec8f697af597ff731221dcaf7fceb974dc702900f58393d6101ece747af3a341d0c3ca4c9b75193f037623b86d231acfa43083eb7f24ee11db68345ad5c9ed7f5365038a1d5df9c304ffe9f5163a296492601c75ae6284c268dc1ca4f858ad7617fda4d8d509df0671fd2ede7faee5f68510767af721bf06ab3ae1c4bcc512bb8b3cdbb721a86295620c8ee21d096a5734e04862c1a054a708241aea5ed4bdf4f7a45094692397b5971db4566a26dbe42a10bdedf116f64ff38cf29e5d773955c87374bcec4e45b3fa12ee8dca9a201415b00b562e112cffb04c20e10da981c2ed18c33b1fb111b64f077d1d8db8b865e5e06c391f60a44c16186fd1473d2e7d684e0138859e927076802777107fa5a345b02bfd7cc4c97bc236a7db2931c3ad4581ac7d7e17f5cdcefd78956002354696a008c17c6a4f316dbf6b9a42ee397b434458097ab9043507e1941359c9c59d96306c53449864e6d6e58caed20f3f86cbbe254952b2bd1c697b1a117851e5efea80535bcc44db680809aee50f100b75fee39c0d6806c5c2562c605f125163618b70f4068859c266336476aa69d13bbf13e352f6ec58751f59226550c3e229eec9200df314c83e93d70ab8675ce0210f7d05b85da4574d55d293c47ce0e4b8c07a60020d00fd6ed703803d28ba3d86392d615449dd5db7a6ef8ba5fd39ff24cc453036306583174a75bf83a08fb6c1a3637e4c26551a9cdd28ed61226c6c8555de103373e3ce46c71a4a3fc6fb0aa806970844c7616b03c88f6306a4abd48d7f3d9062d8bb2228e968c3ef155f78ae43ba48350b957efd15e117ca1fa022b4481890eb66afaa914ed9da87b14ea4e4188decf45e1af8f78dc082d72f2b3fb3ba6410105cb789f8fd317b65396ba8b34d742d2581917b6de1bfba41c33d35a947ba008acfc83bde74e9a37cbda481a8c3930b0c6d369540bfbdc72c244e09b9996d00cb6886e6c07266c24cdea522b68fdde31f458e7d2990b848c448b69dec0ce450c339752b261c678415850f0f5e19b95aa2c126cc65db8feaa78cdbe80c31ced0418f436fd805bbc202f28e11ed0538df15698dbd98d2d44ec3e8001819c398a0d6c239b9c3b46497659fe5ecf96f5b33ca09f709c5f61b4b8800d3ee1e1c7980cdebb148b0b3808362e8599ba1fdd2666735ab8a9fcd5be987cbdbb5b6f863e0f82fecb7435a67c29a6e5a20310fdc85fec8989f6220575ef6e2834d58989da07b144bf7199498823325701ef1dcb166b1875b0dbf1f92f8d4b108696f71a660d84a1b6315269f8d6bd0eb2c9a161305a3f1f4269cfb5e85d4a332e6b99e7c4081bd128376494bc1cf308d5835f8251f72acd55228761997fa2ab38fc0e02e305d20a8d2181f121d4af43547f5fd324c147bbce81a371d643e93c66dd98196406ed9b7f9711d057f9f2d967e2d96c04abaf0ffeb56769a66763955b9933ff7e002191a2ad9851a6cd5cb7ebf52c166f271552f283344f2c70a5ff7403f72d1504c5dc792ecdb6dd615c467e5017649ad82e40e4c0eb0ce2caf6284ddd6ff83802fe6d8a6d41d16027c15d2661654ce416e5ac0936a4a95a011b1221a5b38bb6044733c983ea0d7c11c488dfb577ef1379a625f594461b9ba24783f062d96f7e0b084af26ad7f8d28b87c85bdb7ca6c1eb35dae7510f6f5d0ab9680eaf2c1f0804e6f4145016371f8aa151f97e3fede60d85ee890020873847869e42cacd7ef906e63abbd55b87acdc4aaa1cc70a08c214a37b95098414298672853b8859cc24017fd21045fc2412fd78f1b69af0f08bb1e4be003dbd785ceeb843f651ddd0a906b17d52f06a635cf6d692f4b331fa850687d0e541baa7ee2fbc7669becfd3d3027a218a18b6c0814f04143a64d9a4d37391a006c79eb148b3f4d12e70876b010827fb7d1dcdc006dd3d55876f3fce3a90f62b7bc5c9ccd84aa3d28a94dce3350b76f0cb5a5d4048198a506dcdc1ed301609c04a011b4b7b89535a72ba207eed01594380d224173317d071e9fd4d3d6f72cd2e5918624bb4a9b10c60f6c30b9d0d7d5944eb974216c48bbdaf4a7f69ef92b20e03ad824ea78f41bd7ceeae73c00373139435c7841cb737304ec5add479f140fc06e28f67cf92de2044f4c23c0400c39ad413285f51e76c087ba5d927a300d44a7e0317e35be94d41cb89f66af40c6994d0df763b00428f7e94af71aa00c71227853f1a1f5878d02c85108bcf8803ff9e8c036495bb118eb35979fded8c3f8dc8c331278d0f3942d1752a2b79ac0aeb3d994f8c4204fa96787571924379697db8ebe0fb1688b15c6853f85c20110dd972052874cafd60b866bd163e83a975fa19f1eaf5daaa1c84de7acb867a880cc64aac0160eca5641070631d5f85e0845430f1fe3349fdb95e27dfd1e095330fd8e531d764605587b36e7481708978bec8d6a0f5efc188e729f6475ef9170c05b2510dde7fc1dca90eea757593daa442cc156a7bc09ffc40837e9395ffcc640350057acce214e5c3ecfc7d5834a9ef1029b32d84ac1f93784c279cc72bbd8204fd9b5af30c739d5d0ef8b5121394ea1a9fac2d1972366291a47213173e26d2010ed400128c775e733af9ab3fcf090707eed20b3b477fa3753a3455444333c805ac46e2c235c79fa20c71beb420c3ed022561076d8fa8c5a96e480d09562951020f24a4bb49abc3cbaeb0e0b7eabcc700b1af7e6af785213fb11636868f1dff071009389888f42b29f8dced9208ea91f9c5444ae02a261efe1c907e55ad90a209ecb57980bdbb5ef293359718719bba53ece5c16e9e91037d5500c599c5836c08473940755b3f465558847f606c162022f061e9daeb0742876661b5bd7302850402e70e07fc11e3751db57cbbcb77ac087e5d1666af91e3dabe4acd04ec67fb0c4f4e0939f8803bdef7d6339c5f37e310e21ae217dd5a553873cd01ab1db3a10d0676f5bcff5da1c3c13049dc3faec02267424e7bbac0fa645b5c5dc6b06d1f0034a89cae995d08ac91aa59b7e81e476f6b250b1c14e6c42f4603e50c8dcb5e08d6d054b4b5c93ffa94c1889a20bdfa7893c4550c1547ca7ad21067a06d1ed908eeedf44e0fda2a91b1606e16f382aba74b1cc2bcb4226a7e5eb2d0cc0192820c1d2a97e21c46e453719e4f4ab4c55d3844f4c50d1a63bfa4783b9bd1f6a20c0ded2d41ee2218e45e74daaeaa11838e518cdf4c7f95e94727a15a6e5ec21a3108ae5a098b3988da0fd6bd4601fb84434d5d110eaffbf5fdb3fff485f8936a6805b748c44b1f5e610ecd6abc4f7fbdd2240802099d3413fa9aeb2089f7a8971905ef5b397667e8877c878ffe2991390de1b23e075b39d85eefa1d6948390b033064c6f966d30df6e2270794a671b3185b23180e01b48288c12c1cb56aec222a7032c1840c0b0a8a93702996416103907888902b9c41f470b70cd309ac8802e5a0357968ccf1f821e109543af1d90e9675d07feb78a5c39d7f1007f5c8c1d9fa9090ed07cf5eacb033f2375fc6364c3bc30744ca66e20386109b28842ad0994170e0423fb67e47ec48e0407f3627ffecea725494de2dfd8e2e061240f4578310a048229189adccef6f4896be90658f3a3dd338a838f484803d6f7d5997794c12c0fe0dcaddd85375ad1e365807f9568c18d06c02e0b38fe77a3500c2cfd472b91062c39d7b3a61b969a3645f2fadb91f06c2da7b717e74ae8d48e8355360aed24009413e4917e37f291c842ae6158b62b06c6582fb37bbdf6537bf40a58b3ea5d0f69fe43dd4ac5de3f4bc23f45e098d6000c3a68a4867e7adab640a5baf4a68f0aa81f0be7c04e0d8d7a9813caa3f64e08d72c3e8093fbd4edc536297b5388c10729346d4ca87bcc2eef0710ce23a884ddde40efd7ecee8efa34ad191184eb6c01d95e852d866e4c531db1a7a63c8291353fec37f838037a9bf4c4b21e97b87e088698f4352edde777b66f41c7bb1cb0711704e7f6a85e173fac67bf4c19c73b09e8f2369999f12b625e3c5f85d62c9e2336216b693606879b1cda7e015abf470c031d7b81c90247318988012e509a31a8cff4a1a1b55769eef3a8d2c83d9d9a0f8d754c8f129ed8919bfa9ce0e9c4f7baa02666a352be858a0a789021ea1aef0f04d78e33db565b093ab0bd5ec9e73ed57d9274f851af5d90605a2727986be006821a1c54b0918fc1256fec86bb33bb9ee767cbe01bccf04868625908bd71ae0cb18711fac846b4c9e3740513373e910025facbe7c9633b09ec51d5e12c9aa30da1189c040c5b3d0a0b91befd7e1fae61e9157cb9487e2d99251922f65443a80a97c7838592566c5d10adfe8f483cb7ec4aa4bc9c7b3dcdf17196a19beb6975014f0da6a6bbc81ca6d64c2cacc3aa95b5e25d928dd72c53c386ab3cfe011dcf00703a1f34594a0de03e2b18b6d61c449d742b4ec98228ec23638da3788e2be401ce7501b18a656fc5192a6dd2eb05345a89d2fa0872e470539840f2f10d9c5d02ee60b0fcfcbb8b4459d73a094ecf2407e19deb71f58325b13d037dd3dc74430141b8f2ecc3cdeedcacb087c659d186f36de2e9c643d8f8283daf4cd95631170b7325ae6c41730b79e34d127212f2834a6c62b1dfc56fdc676fca7f6b1b42630d92dd1e5eeaec7c20840ff55d6de5bb7cd1cf0b6f1b941011aec0fe842902d504149136b3398da5144fe1cc8c71e9cb0d6794bac16e3abcea9792915fc21a060267a8c0b46b7c60e5d9ffe12ca4fc69625488c723e96ea2faf0af2b430fc828059d46a2b02f047b9b92a4f2f9ce514487e0a97192702570314e61d1ed0d76dc0908eb5fef74e1aa83c93d60c289dfa174cac28778dc0f5e50ca8193c18f33f5049fd2d5982a2c5d3007625159d873a71ca0f1012d3e4200a6ae396bb12c41f00d4b95d8cbc1e4b0d887c14084b5d795d528211efd24d8b0909669a32083d6a7004f572503d0dafe8190c4f5960e151fa549f5363f6fdccc6939dbd597cf5db60ec50d0ebe8a92436ef20456bfbd2b91f21df5f061757e6297cbc1cbeaced3cb0753dda12de97ee3bcda38122ac08ef4465e52313835f4e5ac60a2d5c84a21140d48bd38427129f7319fd2d37d8fb0d0ad65d319fb11e36d13b8c3b1fe79156f0cfea6d38a94ec9ed6d301584220ab9fb1210ee635af52b726618c3f1b0ff42b08045bd637569c4e3d8a32c67cce796175805d472778cd43a278993c94f7af7f0435bc0a9ca41bb6cb123e7d652d2a70d3e8dca0db564247ea617d29c25810d20c760d20ff6671634e8704a6bbf0082d27ead116ab120f642dd7b1aff9cd01ba097a49dc7b8bf73358eb0bcb5024db650e740f79bb3b62de674715c29ba2887a0a1e341701d54bdb791d96252bbf7f2125ae29d52549cbd7800e72ff25b0014e0f1bec3dac65f1d1324aa604ad53260f2ee3a8d6ede607394e5df1a3a80b8cdc075f39840ef73502adb13e607f61945dab75a0274cd07d22d41e3b534294d073027b9e3829affd4b8e0a7814a64ac8ed6957dd377aeded35987c412046e6b22601bbfd8ffe1c94c54adc310e7d9d1300d37e9b8c326a57f8f788c9680a8e14530e344648c9f776501cca0f7055af58c9b553862731e05d2d6951b1e10acafde109be17aeac17d7b7be8fa4620b93a633df9b0b087fc89a927d280e39bfeed79f0ba6c6b08a540fd5926cccff9184cb0e39258bc531c06011cead0479d19a9bf107926eb9b87122eb9aa4bfe85ed709e72c386fdc6a195efdb3c2c7c789a511a00bda737613ee8e1dbccc0d977a1512b9177fb04553c1891223fc352c91951b140e9bfb3b1847aa182ef05adbebb105a769160e2bd63cb2335d4db6947876d8b50f0e68fde6d3c687e114bf72cebbb8ce98c9def1c85bcc579294a119410c3c58018a55ceb9f0e00dd9d5a9106057529fdacf61750413e3f538e82fa367f19e5b04550f2cfe247143d73b8ca8c94230aea263cbdea6941240298a96522a699ef30295e4ac9fa151405a5e545c475d6f6d864d4722d248b5e9fad5500c0c46e8b8085305395183db1f246fae4c0ea40e76be4491e0e5a888415a0b15b2dcbf17b80fb3a3248300cb1d61c8418929ee52227e8dc819d4f5a332db61956e17ad428b0cff00324b1ac30ca7993b73942f9e9dc1b3775414071f066a531ae765e49b250a6c21fa9ca1f051603e0eb0c49d2b1b637a022db29f19cfa983474bd62a0fe901aee7329c23f522f01473f5d764a78589b97f24f06e82acfd38c07d368ba02607e0d0653463b71d8d9d228946999b6487bc271b0f285876705cd02b2032b501086a45fce6019dfd7e8c43db56ef03f298ed1843d8af0b8da285231c65a8e1900d +generate_ring_signature adcdb7399ebe573a2e88f555775d8df55ceef28b0f51d1256cae8f109668a24c 447ef2e9196b56579e07bf5411b980ed2bff6414024f79852d9d4af70a449870 10 9152fedaec98aba200129eab484df0a6366db49094419265a78ddc2b57380e30 b79be97e80cfdd3ab77c6855acab29c655e3d1a07a6e2b53462aa7b9ef83bcbd 69864e7c079c36ee8698ad1b54f66bfd101bf1c835670beca641f9ed37736f99 ca0520d1c7e07f43082c5a46ad0dbb4aacb97e88d7246a60a8ba3667f2458c9e 053d4ad64725e121493158de54d28826417808669ce746b807d65b1f11839a6f c299d75d2531a842aad42ff488b2b76112caf12bbd500d503f43dfd9708746bc 04dc77ff1925242237f287d9ccee87c27ebd75ac6e3a45c357d9bceecd937f63 ca3895a0d1560e67451efdfd8cafdc838c7f1fbc22a4504323ee47e7436ee49b 3a8185cf5f418483607610c29acc87d2b5b0eb5705a25252dc151d28168f65a5 7ccbafce5134beffb22c2906ab4008a62e784b46bd74ffe5bcb2386a990adcb9 f00cac90c0731f2c2eda3e61a2bbfa99255c22990d697a1008ce4a53d42a8600 3 c8a3a2bc427c23b03e1efaba87938fbc06d549b12ed7072cbf9f8c10edcc9c04748044f3a359c9842357ad9150b225764d1296060b68cbe961fbf7e8768ed106df5d32528e9acdce410cafc9b6b0a90682238e3848a9d679a481de980123870fefe61d4d2e7703bf1b26ee9d01aef6e0889d5a0a587c82f736e49ec248e8c505abcade97aa5a018b78d3fea96c17f79f6db7e0b9a729646fec2752eb5e9e460f1d540c660f483f26ccf2afb61cca612f85533a0834b523931802fba1bb5bd80666471106041da4d7785d6ff183697c1b63789dfcfa1c033135da103523c5490154505061d91a00b8362537bead8147e40e7568b0c914646b224862195e9b270b35a85a5988bc00ee6b59368bf520703cb69112d61d957e0c044b48228ed06a028b3ffc9e4aad4ec9a02295581c5b6859b6e1c6398cbcdb00b48608be1ce546035d2b98386520fb3fb03bdf36f58ae11423821cb80e18f9073ec7f1ae14f98b0e016d2fb7d6fc2be583fc4271eb65456630b5665d913f5334456d65ffa5425709aa68bcda0225092eae513213c35390aaff684cbd0c2646c3a20415800ebb3f060ef700a8b17e146adfeaae163489f3b738166518c5aa0555c3a2cfbc2a1a020553836ae870433f1c3c0e507d12ee7d80a2d9ff7b2dd0efd78a0a1ae7f788170ccb8b65cccb581c3a0a9391b7a52a2faf7536c3ef816e40ba7c4ea75b688b240a14cc3ab6dbb2209bc81182df55b68623c28293e8888ff25a790ba8daad713a0ad47e978ad935d2be4b07bd281c0ab2a252038d227cf9bcc2d64f4193cfd3b601b0ead5123b91e69b2afc0c85539f7083ab4cbe0a99fe7a414723bcbb7063430687a18661b7fa620de67e978454f87f634cf14a28c684756cef67135d60982706 +generate_ring_signature 8603bb45eb1799e1bc1fe6038b19a52bfb9ad7cc9cf44446f164acc3ca40da1d eea6a1e1451c63be7dc890f76883f56b1fe5b41921b4e9a5f7757b92df2b6a49 10 278124100668fd040c4da5aa9dcc1961b3e51c0c1c427757e00938d4584b9a72 1e7124d6beceb0fc37efdfb8e2098b24518f431bf8c0b1d5ebe553402c025b99 73f76c9a7b6cb8d8bc3996ce6fdaa00ef47e3c4c0af2fa6cbc794153d4ee0fc5 59bcb04b3649b9d1c6a697ef8465128d7ffa20ad00d4bc2f3651ea8893e75e17 8a996eeddd61f604a74434deba30fdc66efe9a92ec938471b11f88ded7365510 124691caca477ab72bd7b69ab0e991ed6f6d30e910f34997a8c826e5f9c3e502 e80acfb48cd74ae789a6591ec70de50049fdb9319c8b4cbd814e463113e97c23 4be725c440060881b1dfc58d506b5c16bdfdd539bfcf02ad5dea50748ca0350b 57f42b791c1ae5f5dbf20e303be722ea94fd993241ef302e94da5cb017802ba9 dcb72d6d16b55946296733c9638c60dff04002c51c55234878846bc1b6dd1864 f0dacee794abc5fbf38c017120a19c7e1c65637c65b4103fcb8c148af9aad201 4 082007a751f92b55a693a77c0e6199cdbbb85e0827348951f9da840d07cc6001c95cf68230c8c6115668e682cc483e76a3af70bc770eb464d3627bc041daa9016ed9ddaa9205295e272bb3b3ef3172b52ce39338929f7f944e5258798249a30b57a3397b680d70ba5ef5d6f30d1a5c829a82d7119a7f80a578a64e1bfb5f85081b82124e8ea116d5bccb8ab41379a52ab317e51ce76506db98f224c138a845088dc6d6c74ae16e330e74aefb3b358679f570b3c758b46aa733e51b29f3c8f205284b749f1135ec3ab8383c160d33039e4e48aafbb607fdd7152895d3a00a860fac7ac7056cc9820db1f5991de300159dc2975ed101345e8e715230b27ee8ae0806137d03d58dc8c87797498d19fc878a09284ad29bd75d9daa893255ff88e4057ecba8f25a988abf91956cdf876e1c63912e50abfe9dabcad136c8107fce140ec959b8bb60bdacc774764deb71d000e5fcd2bf47f888519e10b5524d15df38090655c1ec3a231268f8ef87929fa92e2362d33e566f7c5046b78518232304bc04909b52c267d5e41e36f998254074c97a56ea2008631156dae267581e93da140d17c03b20f2f53919d896a0b52454bb8e19adf1314f5a9d9ae5aeaa8349d7580fd4c08c1da9209cb9f3a17583af0cffb89c75df70080f6653ddcb20b4b326d308c337636d587f90fd2c0eb13060617a4e16d9ed033bceab9f22bf2697dea10a0ff1a186837eff11209cbc4de5b035274f907ef87d5b8e6f1b3adc9eb8fdf8200aa04a2c0d28000e0feadff43a9ad985f0b8e16a124e4993254ee22869ded70f0044e26562145d155ef60f77aced604aad361b8eb573f7c504398b83ac25b25c0d6ec98c238860462d488e8369ab2a737835d476dc3e7b7f811d04858a9f346c0d +generate_ring_signature 393bd6d7e3d18366b43c7f64f94c7f3e803c05a357fd4c9ccab41f235545ee23 ad175b4b3efde3db1a37d5860d51d8c1e71bbdef25a0d88f29fdd6ed07309665 4 beb4f6cb5a63cfd76a7e66a78ed35d788947613b90e7bdc25ada761b87ea430a 0e37fe8e05c17b8ff67e4fb79a6849eae9631a41fccecca28618418746d0a9ea 087f54a5745a7fd38e45534fa0a878b582fd7d16e6705e0bd195d9c11ffe9638 3c91a5cb9c704c6f70c36cf483ff5dfb14b45958ee50b244de2f8c60e3931a82 c022e13c7fad4dc5e547e92919763f8276ba20a839ff4790f7423bfdbf60eb03 2 ed28c9ab941d91f81abf983fccc22841db7c0171e40b8aa59d41b3cc4f618108d7c91b213f6eb2d5c8aebbc41d5c3c2571b3b155cd1f2d85d0c961e7e6d51d0a10a393ad2198fc4407b86de23ded44f86b607f094cba653aed28f6ea4137eb04ab06a5b215940fb4b0547b4e1e416d6925a1d94b58d76b46c31ea3ee082f400c501945b17f12f39108739e2996f8913e45f46c5950fcc13a150fc9936e723207b7f38c9d3059a34efc08cf3c74e4c618acbbd4166e5cd29a3841f1184260e40372b948a54818660920bcd731cb00880dd6daf963b51b708bb02eede2336f7f07ba366256992311d522ec0c9e5e86c8ec1bc48278e33490670c90daad6970db01 +generate_ring_signature e565abb91e365168b01e67f4a3c568d32789fdc1e6dab2f448e9f38d091a3d4e 9408b7dd8b3cad102645c2011cbfb0edf8b012cfde69948fa41745d9b2e0d375 1 353fd42821e9933571099b5e6cf214b0f20f3b6d012e753818641c618d20defa cbbbb2095f92ef10834a02629b43f7cdb9c44d638c6972b9030d793472a63207 0 dd5534feb2f07e62aed0f9fb8ac5abbaee801bead110e3433199b70804132c0b2527d683576fa89542b92bee0a68613d7da2446feacc3529244ca12087f23501 +generate_ring_signature 7ca2998d7e7f0adc4ce35e5b474e47699d5460663aa16ab449609fbb00d500f8 7fc9c544c3e934782785e9f73fe032d96973111f922034ca48bc825cc27736c7 64 483168d096ddf7c014a148e53be2d680079bdf94ddccd86b087f8b33d357b7fd 86bdeea8a6d0fb1d4c7d5a173d5468a55f6787f612cc997039307ad56f2ec6f3 c60a76b900e4670551e578ad687fba402b25416433d72af5291ed69e630337ea caaacc734c97093c58dd64102a4246b2a5840c1c813c4e338394bbac7dbebc75 1ef3e4e217cce535fc694fd8c6d3e113914f0a519038690ce7324d06e4d1f8be 916111041980474203cd2afa9043cf5d9c3d636fec3498e1f6b06115b668bd1f a09a5afac52945be31fc7a2e7046862c8d4806649359fbf8b5f7c69628b4f167 6b5d1fdc1a962a295746d49938647583ea088de7f8e241497fc6b41bc9121e95 0400eb6d12f71290e0bf2e6af6ea14c37198a7e686b63e0569f6741844f0db28 235285f1e1e1a1bb6daf5820e3f9db2f5ebcf8a3c1dff2a988953d60d77c2c90 847ebd598b288b0052a82a35c58fee0e477556cad2bbf15dc60208ed14712b08 a8a54162f2a6e4fd177b3c727dcd2034643d6a43970f2bb9804cbb5f24366b5c 37fcdd2a3b035e5f5f4951d3ea120dabbdc219d9a6c385d03643a7037eb26af4 c3c68afaa4e7cc9c7cda7569cd3b0e880fc2b39e418383c4f7d6aede362acaee a14729c01c6f8c78c68f4863e384162a863d304e780cf1d87835369d6c0f4c42 ba8de594a2ebd411901147db78dce4c6b5dd35dd2c85ae6ce2e2f48f3e47c122 f9d0351c1c41aedcc6899d3c963c410b3e33510f747c1a3cce8ab1823a3414ac d8f4ac38ce7be2c45d3b74880338bba84e256042ddcdf30ff25089726edbcee9 4b33b840fe9c767bc2fc9b8f989aed3d8012edc993776b1d2476f6542ae15cdf a7b39b9014bde6702c0c7baf60a3245a70f8db5abac0fad30bf98c36d8b201a6 3905a5aa52ca2d61f49e770c53c6663687c2b6565736b51527b8332730d283b5 e9932651c0ae63cf3738fe067908dd46644f1d2235972e027beec99724d013f0 804f17dc20b27060756c20a2e3b1bcbc8fa01db1672c7aed51c20a868b0360bc 138c0ac27cb68eac5dd51b8f75d1c31a215f26b14445bcb3642fd00a176a6639 0f283696b934fbcf7ce30f78f8664d8f28c986a202a0c340b2d7d5782cc7bcee 36415f082045b4c3b1b0f805d2e6ade990723d39db0a53cdd723d10a255d41d6 16a9cec53d35cc2861126070e57d228c20f3350b93ea4b46d8b62d01f3209f20 a5c9112fefba9ad954476e87f670af6dd626898b3953a31cf3ffb57886f10d11 ca10bbb819ce71f840e69d53750dd43adf4cdc2c785e517c7edde54034a3baba b1f8df73868c6f39af5d6a71b16fae7c882cfa335115f62f0b093873c308d06d 557f9033e27f5ffa3268c4a3f3fc94dc73c2e3bc70908888c3644143503796b3 f2cad5e736f9839d99cf515859fb8464fece1f85450d5bd5558ce750e60e2942 9becaea439d210fd173a374e51586d125508c458ffb0eea0257416ae62813a81 a56164a43e06f4da3d2cfec1db2c1fbc2641b9f86dc4869e06e55f0a9ffcf751 c8a1abd87b2837247515c9736804424e235d61d6c41f90e748e72859446633e6 210074f11031e5ce0d2ac8cf51e9fc7981155fd1011745ef1e74b342672b453b 8fae668e0c5e30c77823534bb06c660867896f016907fa8b05f5a18452c7714f 0e1a32d6619800d7c2fd5873d124c917752f058318d43b66b2512aa1667c5151 6803d84d7b5a3574328f3403b2f4a79b5262aa31e6f1c971c179c4ec2c8560ab 44c61ae79c631193c330a66d64dab906514cbfec06c8bdf57d5cdb1844b2f789 4000fa60a283326fdf215ceffc849f6f58cd74b60bf19798cd6e54b6e3d8d06a a78e6293da0c64e26b788e55a0afbd8e4273a226a514cab6e3b4beb8d214c9ea 12980cd87170fc759380afa60290915389ff1929ab5de05f1e8549f014fb2b44 a1b83d3f280f162cc37feafd51e90cf6e1da6c82d25ca9ae12b4acbee46a949f 6cded174a9447758824a50352936a539d97c0977ecde4eb9df83c0244a44b89c e6a9d7f60b9d6f367befcfb0578605aefffe810cd55081232176f23cd4901ba1 13fa490eadd0b74699af3be95e1f5b2e488826a104779877768d5e10a506bdd5 5ee53f2482db49cd3373a9195fe2067e018a081189e9e0ba2500357fee9f11d7 0cec68b56dbdd3f61c5b5f242928af02ac0f1bdffc5461b5855fe58b582f54cc 6c17365304dfcf711494cfeeed75cf5e121ee6b59cd67219edaae7ea07db4250 6e801ef00a31b59ad896ab91c68c67ec24aac24b03436c7013c18df945666875 8326bacb4818132db5ca61d73897c1ec0769d9833b9ab677c42bfb9b177e0f09 2b460dbd272c99ec3ee39938db0555df0f23e8090da8e115a912e15d51aa913e c3cb48550117623033617d274569087b44d1da2dbc0257bbf45f35e3581b536d 110d6abeaf7b20668c3891fc61240bb2c3d67736f5e80361217156a55e142f5b 79e8696c0f50252f81b5f218eac91894ea15a95a48ca68594de8aafcae37d7e1 7308404a054e1005bdf9eddda7a5d0ac0b395efdeb81a655f4b8e8819bdc583a 38239bcf14fe4fdcb14d6943c464ca8cf401cdc46d3d212b4f1ee52161e3b4be 3a8bf4e796f2cd92a78240df064c3520f4966257b89e49ffa2ac6b4f70322a97 b4310494a59ac8bc4ccf06b17f70ddb789b387215fe2b73d180b3dc1779350ed 51275e0ac22a92d506d12e7969e28f060ee7fcdcaf100134af046d622ef7c8f9 d509aa1c71eaf0259e74c41d404c25ed03fbf75f249214b7525570eee1eefda7 388f6ce354823892c1cbe49d7fd79d8c62627308a48291af34e16bca292a6ac9 7831cb8fc935ac1eea198f48f6632475f8feebf686406eb00d43f4054299f8f3 d62eb32ea87d2f0efc686cf9d79d111ee668a65a48c3ae2606bee28d8dc54202 15 2ee2dd1fe11afca75e34f980ef12a9b69c39a5046dc15febb1e53cda653fbc0cd8b779b0bef68e2e07caf8793434f36fc5b8908e2919a6231728454a7c31670f0660affe8cc0e6dbce8a1c5f08b1a9ad15b0c25e635c4ad1a59a37120300b60522527f5b4907cbbef7a739cac0edd54cfba16b42ac201fc22b94b9e2848e790ff15b0613a0382ada2cfe671f6929b7bfb032ffec6a4e6f389ebdf8c1167dab0baa5397e4725165e21644189c43e61f95768a1a4cd72cd4a299b6036f5325ba043fb0be698ea3a76126e222f5f656f858bd1c5c3a4fcef55d55a81839072af5044529efb2b8fe57875d426615768435b89da774045cfa7c43ab48256282547b0afbca3cd889d897b42daf38680b5e505bbea6975fd83a5f92c6ceca2c2ad48d04b5be5f14882c82f255d8265238237899a22c4e8d2fbd94ff7e8ec7f7ca12af03c13c28a3a5e94979e158482cf922259c27c96c7d0e3113af8b699a74960ecc09a62cd9c86c313000cbdee1411d69c3d28e12e067ccfbc78514277294a80cc7084680a24893e6ca23c9c43e31c7d3d3817933a029bb236230de0e0b918a44a603069c7cf48ae8432f23a44c75c38161168723e302e9b22c9d7157b7f00ac7970be3eb599d09df2313c0c0bdbcb6bc77e8de48246d7a4598ace9df80e055e96e09b4b6a4a1c826b5876c5965873647b7daa63665058c45dd5ba651a4b518b0270f018c5d10476e7ced2b9f6eebd132b37bf3d2a13a55d338d7c5dcacc72f4dd208182ccab9910f078a31be6eed73fcfb5d95fc8a0ecc66a806a7d0bd8e3b0197077d39621969d2183ba266f22b145758c4d82df8b54c7a2c82135021a8dbfc4c036d4b51f51011b1a51a5a0cebd6a511fce1838d330288d02d0f5149adec4e060a0f644b7ec30aed5a9268e1ebb46f52649ae96ed48ec947f32238d6802b0b890bd664500ea6eca23f74fd4063a41ce356c287345a04de842bebe17658de4c33049fbe98bd5bd68ad9d744dba870066d96658384e21c5a27284055c74b40463b0faf29c0dda1106b762c2d4633ac7fe6d55783f563c51807fc1b725d8d5d92450ef05c97a28f49dadd28d260696fc8e3bb4cac4217a5665de8041c0efcda79420f9f58b372437efc4a96afe6a2dcce3e642648a270cae90fa4117e75c605189e027fc84bffbcf3cb6c0304fbdab524f50afde3d0e760a15f82e35eabfff4dcef0595384c3dd73815be1902860070a92f9582c372440e45c4061fae081f1738dc0679214a61bae33a47a1cf4ab43049d271c142b02c4db231d6407d7f047d5c120a099c81deadabf1bbb59ddf3a7b30bca9be16b98c92e28390c5212c188d719607348bff51578cd8bb113b685fa15e809aff2922daa9249634608982a6bc60670eeeb4693cc5f4f2954e31f6c1a9db4b359e91af70a3d6a859181ecc14651396047a319df55fcac89d55f28bef3f33da75314ef9d782c617502694b7d517d7530361aed5ef08203e4ac01aba6fcb8c1404d41f52f8e746a0c91fd8d89f00df810b9ee016de75a61ef80111752a39b413ec940266a9fb120be4512f30a3a622a80d0d8a266c9be3fe8b742ed8d8fe2c54e8eaef06677a754798d6ed807516f9940306264a77c824b064f0ab1a47bbe197bbebfc5e0277dcb54c4415e35338d21e0c933080097a69ba5329e52f9c927c1c143c68e0eac2a3f139b37ce8cfc761be0aafa2a799b8bef98c2aff2de4d30606d031e490851894d9d74b984127734b19024d0058c98d86a530e49c8beeb714ed3197eb09eae8bd8b9fcfc0d6cf74b11300a1d043ba357927ff94392bf01e60e021a540f962afb1141902858efb36877c0c11dda8fe449cec909372f5f4784ba23d8661db1bd8ac1e30e0c6b1427a60e00a7eb33b1e0851b354f5cfbcc0d561ebc9cc53a443ba6240cb15fd7d56ade3130032f5038d8529d014d10eebf3e3cd57e23a0da2d672b3556b10fd89c1cc37ef0c6b6181e3dd4fea0d276084744e53bba3e68b81f851d1d9e5bd7130d3579faa0d977c914c6aeaff3354a6a197057b6737c757533ecd9b7f0142e097304c014a04ffdce71633d8f8bc0547a3ead1cfd5e16e23767079cf80b12fde1348b586430d6b207f71b66bf200a9dd7f4c9d16293500c8a967242beb8952a2932f2baef20772b02152f6baf2cfb847e1d311bfdde2da511d9e27f84ce338fe73e70f16fe0331d87c54e615cd3e7bcb10b58dc8d8d211734c952e6380a3e06fb3a2486afa040893af010bc2b1449b316f28e0f7918f5946d561188fe264a131b06faed5750f90aa4ff1d6bcf0ce5ff9347ef0b4fb53d8df66bd4cbbc0072fce0b9193b2560908077e7b9ee0a18011947ee0a1143b87ec52c87d418b909a7ce5f11e0d3e410e8104337d687c3b53d3eb821d6c7065cca45f358739a7adb4f8b99fb4d40b6c0c833581c60fdf04bd10a03dfeecd68511da41456941672a447ffacd7c75651d020553f976558cb338977e0aa2a1b26a722357dc86fe7381b77cdda3cb164cce0aaff5d0d9e21c46fd188b378b2a9f460cb3db1d934c18fb75302effe56c8b570e8450ac5d48b3bc4e5be818c1bdece9f28c295ffa790a6d29656e0aaa3f3624023428ad317749322b4fac899e4fac6e1e36ddc42083579bbd7db80b750a94e0054fb39cfef6b40b1ad03fae31f385170143c684c3925d4c25c6e8d0cf2ad8a9012733018daa75a0dfe6dba31d2d5af36833dd33521219c0e5fd921ce6b728af096284cdaff9e192b9ad120192f0a628f8f399438ef6275542a30681622eddbd0f19d08b98ee131d1303ec5637996f5b83f0e3748b84fdf5bbaf7d3f911a60fd06ada63a5b60d779af22bc9b336cd3adb42305e62c761af2957f184104073cd303f64db90d5228769ecec72c4301a7b1f68ef14e0f6533d8e2f4e460d2cbb79a0a8512b7a6ce9991355b53fedc05b1c696a10bb0c69fa99a287de4243e0ec8490322c214baccd20bc146fbf5f8e5ee85db2afc2d8b834bd2b086e28632988356058790993c85d636c00f1512a80eab31eaf1bf0fd481ed8a9b8f5945b04289860a42f561b24ce53793d69934a0fbe93a837e18f4041ec6e38b620db9f7dbe4ea0a408d4187eb198a3eb31cfcf7d20f1446f78a412538ebdc74c9174ffe99f2180eb179a255caa1fcd072bcc938a17024e799be4276fb9964e60aa9d4e465a0e20b58eee935f84c3e2abf731bd6968a39bba4af52fb30f8b4129f187bfcbe9a4107986c5acf2327597eedcab62924bea6087aaa162807b77f73f1271f338571f703baece5d2c84b9ce9effa23f40c6562933a9e63d4aefa71bac4b201f1229ce80905ea987f725f3818cf3112cd7ccd835059932337fb688feec3e24fe9160cee0360122164528078155d3473196d63da43da105a3edb8dd56126f5c00407290e0600d511250ee64f9308ff23d92bbf720e16cb8099cc1b414293625ec06edc63093c84b10735ddb806fc425f1126ae5c0b8abcc0567193c9d55cc2b619e842ad0bc4a519ad35ac88bd3dbc3e704614d8582d0fb0bef4533cfc15127d8cda67590155cf69ed41aaf9a71dbf83545991766cd7d68e47368f7e20af227106f1bf2b0216a8e199f9f0fa3067d9387e0c5399f0bb6e6bec51749d489a6489d8de4e360df1cc51722fcd8fa18775e05b9a5793961fe0db7b5826278aa91ddfbe15ecfc0864cb0b50dd8991b554bbfb029c72b0fabce898943c603d50eda6270bbdab7d0bbc2cadea95f67911aab0e151cef5de98ef9f0e3696b52926f26b24e2fa9be40cc1cb5e8b2114b38421e53d083fa62d7bc9bdb8be7b17bd8323685628caa53005c93d4f4a0daff10d166df97bcb632b9ba2a234df630792002aace248971eba0144275a3e15b7fb41ef51365a635231291e4b6ff2ade0b4123c99555f644351003ba557cd4d0b47cf8a1bb91378e0fe2c90c680d812816b46aaf6f8ca7456bb0599f4a76cfefc5cc954534fb0eb1a2bfb6ccc719099c669c49bf02ce660e0b90ffef7308ee778a7a4acd9f561e983417123ab7eb62f97f4b89d48f6150420850eebe38a49dbace14c90e531d837d994697023678c5d6ebcc49e1715cf03dfbd0bedb26f477e970356e58d4b5ac533ea479b0668d19c4e6a39b9fdcc709063e60e1b16a9604a70fc71afe4b33177c372085663a941a6c6f6077e5e521be105fb09d5fe92b1650cb1d8cad7ebd2df6a5993fb236a080d38b6398f82e36ab01c28005392a00ff0423fceca664a23b529de58994426b98eb259e49aa85435b392f50c2ca96a3142fe083696ba54979a168cac9a9e89a254c8ac610c938bb897050e0a5c7808e94dd1867a34d2222e6797f053b1ba32c4157c0f040ee2b46b19c9d80f5bdc8788bb88c3ddd5975ace0881d39fb23ded2300c62b0bf2793a36fd92e3006aec70a7159ed709ad70f3654273c2b88ac5a6b73ed11b0e34aaafec01e3bf0aadbe3b7958dc71bb07a18efd4a939ee3b65d16129777bab2db1f9575d126a707b398971b3afe8fb5d8e4aa830bf7ebd7348155fdd7ea62d0c4e1d21ad810950eac247cd29ee894e2061cbd3113465d2ae91052b61499cbfbc75622157b9d200487aee91a452d767553fd1eedb11027c612e2494b23a1a52d52e91fc4b8fd8d0492c0dac6c0b1d67dcb28385a8cd72e85b5919d1728293ee29e711d60bfc7c400ce7c2a0cb0ae9e4093d11955007dafd6ce1eadeb1a24377c830bce37036636069d93925aa38f2a6d8b6f1f48f999842010f5e01a395726c9e5734866e71ae004d444a58acabca849265f18f749a967b7fc17e56a49e46dd3253f5bb16cd3bd0ca6fe23661851068f0f4fe15f998e2ba86857bbb451caac8387f77effffb22a0caed422b23792a5bdd681bd97283c2b59df097b7fa4ceb89df1ff0ea7a1de080d1ac6122ea8130cf9d5b4ee15cf3ac689fd019ae9a0500cd6d7b17ef8d8215d00b0a40d2d85288f0aa3c94caba8deb695c4dbd6066daf8eeeff9081e262e3640eaa5aab602329b4c7a42aabf380eb804fd56dc475d58cf9f6eb6106582569c80719ae734362b450fbd0d51740fe2c44f871cb7221b9a9b6a7a4f281a2a28fc60345e9850557bdac3a93fab7f302106ad2ed2cd0e4717c79456b69865959f98b094331860bbf05393e18d43038446c185b728480035e1ad29652eb35dda43b330b361b63f34847448c5db957bede36c009115bbe7151b8ce5c7b7a72bea3b9a2042e0a907d9137581f3341b77a92b4089b01031097f40b1e23db8818686e1d6a0c827e44ed159fffdc44b65cf56509cb539bef77ffd8bedbbb0fa8f2cc846385001ef1adc1bc5fe6cd7f31b7409b3b07b40ee67b02f2c90d8de7c4dba372065104df9a1666c09d7bfd08b14a21f7cfb758137e296386ea1ed73eee68fd359f1e03cf94507002645e17c60182ae3462d44a9d9aa522156d7c2173d6731bcdcd3e0a17ef4c8ceabb347fd59001815fd3cec24005cb9aeca0a24bcf16b5b799c14d0747aa7485aab69c7914d40e765b7296556b470feea7e497b32e26387a6134fb01f170aa9899aa178219359b0d182e14cff5f7fdd3810b8f17fdc4c88a15364a0db47dba15577acf0e1d01e9f45029364d224bb671a616398f9c101855991a4604547649a901b4006a34f5b46321a2f6ee5f2df205c3f957414e39604b9272380760f39f1a44f9beafc65a88c853c0c9ec755dd9dd0eadb572d00e994a48e95a04d95caf2b6416bb39dbeb4ca5165d6b7a6578d96f13d922c1a3801c03cfc5e30c +generate_ring_signature 4e6823185a8771ea63ca39e1aa4dbb7578a6fba3da566cea485c82b3c0efc115 0f0ffd85c0de4993b1c69e5b0c21a3811b49f6c0f4097a81e33448c1149afaef 2 cad1c5a19a24b36c12ba2812652309ba4234f04ca20812ef2d76405d7740afe2 4ff3063f234d5d7b4717b2c2b9e4c09966f69f1c1083099420e37baf84d8c9ba 071ae9ca27b1072d58abfc39b4bf143d61845202748c25189525172e1d081b0e 0 32b8857f070d7285b3c2b43e307d593fb35142f4111325d1f98f83074523f20455d68c886a802d0f84a38aa10bc4af10679147da4979eba30464ab408afa6a0dd2957b1f99f00cd63dc7eeed770a51912350d65c58013d159125bc2f350413047bd081ef106e72c2f19538c9b7bb0202800bf3302d9cc095da9021d5836eb20a +generate_ring_signature 91cbc9e360956a6ea91cb542dc70d6cec885b8e2a1b763a3e352389041be1aa4 077849a2880ed750d786a1f1f0a17cc01c256f896373c465779e5154b3f7d955 113 1f4bdae2817d67f27dc0ceaf976717df975fb8353daf7fa01fff17ae37770146 fdd656b891d9e758069f81b2b2daf433fc84b3dc8eeefd2d295b7f5ab9d75c92 0859b4fd8c367923f1061c416b7e8e9ebb99e3829e50d8d21fa659ca4078330f 7e2da8ad81daf87ae03a1f42ccad8d8f3c8e1d4f75dd89416119b1c71e8a2416 c32fdedfa2464148a62c7630da8f598ff39f13628b221142f7f2d5b61fd5efaf 76737534abb4dfdc6ba72c40f3b406f9cec3a51fba44b56284fc62db05394e79 e4e6d4b71a8e963a256a300e4ecd265dadfc6ffb1fb7c46a68b9badf18e3e4d0 b4ce84dd04dc6ccc4b85eee0925825b4436237ec68b324f66f5f9684de4f66ba b1c379e91b9b72abdf75c4d25174bf029926cfb3498beb075586c9ae3cc105e7 2267492b2a3131012bdf68b84d681f03824aafbba96b2b9735343abbd74b8cb6 00ae5b1f0c470c254facb1b12ba8ac6a31191cdd01709d2ee6b37c1caee74cd5 bd859849cad2bb97e2da3908dd8b90578455599705674fc0016ff46c3549fea7 bb21060aae8d8503dd930512d7a080a6828223b5fcabda0c161ec3ecaae3fefc 66bb5f6b1c081e0393d2224ea522cf385115dc03b1970c2e7e3a5c72d8e7bc50 33cc10d158229e8603dc7895a81a8b6c55edecf6f43a506625074261d402fdc9 43a36814c2c72f6a273fac7094f9b00124e0bbd332b9ee61ca41ea231b018816 1d7f55694bfd332d08164d331fd276e56d365f2a7c5fcd3824c77a6809b65385 c2eefbf1779a3dc88c493b6512ac8d2393b2a65f195681baa41bb05e2e58f689 981ed644db662419628670953465ebe2ac3997ebb4d8292b24d2ddff64fdcd86 123dd138e0f62fad60aa9656d484aec34ad87fa623b69ca4f77f36b5b903d71d 29976e6ae7245518b0565907725a15e1445bd1c0730b2c98433c47e13f34e4ad 541da01c43ea8445433cf70817e7fccefa13245c1d6ff34ada5324ed8dad3d04 82a982aae68c079dedcd3455d266bcef67e4d39028afa0df883dfdb4b36ce979 7561dd51d46d617281a314a4e112228a6abc1ec8ae26f59f5d691cccbd96663e afa6f7640f981e3d4ed2b85b74151061aed19ff5390c0ab3791cccc1a21ede59 54c84b57a8749841027cdb4555f8a8c03dd9763957d801efe96096ce6a58a1ee d4186b3f8ab4c4fb9256161f632c9fbae63912909c22636357b001ff34486de3 e845c35b7b319a99099f122f0acea3e39e82bf536c9dc0a7fe5875d6b0739c74 faf9769154330257db19465d7ae0f2f211f730e4c83220c48d7648596e91aba5 3bd9d7b85fc7ae7d7bece942d0ead33b882d0c35d96d491eaebcd6fce5f345da 1cdbd85712849004e3e4069802d7387ef46a4816ffb84fc626d5c1b9b7a60a23 d284ec26e2df785de3542990946152a736f729a787913dafe58f8745b0d263db d23bd5efd82b47c8d982ed9e1b4dedd39a3ee3badfee703dcc33d3c32b2075d0 f1eb248b21f1a5abe42327d1f203121a0a113fb1cfd61281e639aca1a15798a7 dc124febbf2b8b75ad19408ba905ec2660f8641608048d4053b137c18118285f ff0a4193b301b36562d8c1ffab7bbb9c62834b0116a48b992a85c1ebea6b0a81 8ebd75cea0d1f657d506b3cbdb855a9db21f87d8e0cbef42849383f093b7eaa0 9e254d83820a33fd0971a3c7efe2ca64c35a3d5d50ac3884bbdf7d6f77d7dd5f d2a69bb8e79306446c6b2cda1ad9c3d1bb571720b43e55491abb505b6aed4f6d b60e0fb3e1013aa0c1d196cb9d2fce8c1f201c0a013e6634fde756f6023c36a7 262e4efc7730fa981014d1567de9d429eda860bfee22ede1c9941ef94aaf2159 8a40d305e04999c66638cfb169b2a991c0995c814ad978eb9f1e951bb3465c40 088739da61d37ad97d467ec8bd7ca4139b311f7f8b6cea6469aa4e8a4972ba51 6874ee85e75171ed81a59ee5030a8f5af72373719a8faec2680c00af75fbe0ee 0ec37865399810603eeb33048982fd83b25e9e1fcbeaa91c0ed06fccc47c3f80 5ea898f527a48bf7a4fddf87f26d13637557b6214da4eb1b0e4e0495111f9f36 b1dae8a393bf959ccf33a86ce48214f4250458661892fd8bcbcbed768f792548 25a26575e7b663bc898396ed9ccb961e9bcb00d107f0662edba72d2697a78d4d 927ac8a2052c2635eabe2602f67d1e024ff0f04dda5a09a1abe3475cff9b4f78 ef6c5437357e0b31c6a3ddc3474ce246f49a669ce06acc00232a4cb170e0b7ac fa6ec2d86e6f12a008a2415f6bb6d62d8f4530b7ee264e6335421b464033b6f1 77027c9a7b41d51ec9851dd80e52221d541330c4aa65ae9604bb924874dce56b 6229ab07ca58513e9a5fc1db57e4c1bef34e4007206e440b26707594b3cf88c7 137f3bea2550d2307d8a733cd7ccc1c6f80fd9b4f307b75583193c826805588d 48f0e380c36fa89f755054572914efcc6ccb415d77348416a33d5512f8376380 4f5e4429027959682771f088b7101e1cb07d0183052627e44191ab65a4d11e98 d40ec8d941cc48b7edf706b778d736183e05856d03fd929adac4eebf3268cb68 8bfda414414ad854211292ba745ee96f200c80e3623506fb8525f20fb2271fc3 1a615b1e5534445656037b118b8b7bd13ae02ae23436b4ee338d92d37c3d4896 9bc163d094d4f87154cf3593c1edb359a903dfe7509524d9335623a29c656663 eac712841f6694776756f6a89d043bb062861a4378cfb13af76d301c71cbc6ed 7ef33bfc75e86390bc080acbe35bbbad5ddc51da165009bd0daa10db962ba996 054e6574ef55c9f9e94207ec107352a0dccc240ef20c033dd6d1182f7f62909b c32880fa3ce928700ac24530ead3571072e12b03a49b26ef6b3d35d0f4c59d53 b98d0748298b80029c901eb4ec4cd8a436e83c7e01f440c786fd16e15107ac49 ebb0e6eacbc9c5f35484faf27ecacac6cc694ef4b09d807029ae6f510efdcda0 b490c1cb481c3ae08a73f63a1102b316d286d93852adf5648cb0dcb6818126d0 d4f4da3f84eec9c39a4c7cfe27a3bcd39cb9f291005614f1487e0f45a4f1ec00 aebf45b322432696c7b67d3cfc0aee50ff8e40c51ce8cae8a626812449d3a54d f606c7fa4e43f558fdcd80fe7a73dcbb249056b368f5a44f3dbcb9324b503c34 106f85af18b3197ad3351fa8fd8425d260e7aa0c05918af757bbd3361bfd69d8 32256ba58423e1ea10dd4f501a5d238f31499624872406fe500f498e66d008b4 d292d6bd8bf7432aaf9c61d7dc96c73f0dae8132673e85fd3aac5fac1a93431e 52b24f1118795f20e46b90c1b047ee5ee2d3652ab2bce842a9cec609fa62aefa 449fe393def04380cea7cc4c3db08cebf0482f2ff57127ffcd987d92c3fa6163 7a8d3c4d6eb1516f2fe284e496574b3f189b5015a489fc50e54a9f414dcc1b0b b39077b6c733c1de5db7ff8fb3873f024b40fca72f9cac1fc08af28b18e1b932 0b203cae9dada2034024effca44f99b52a36ed00a2f4b67f03a4e0ef5b7c5dcb bb56bf108fb574114fc98c31e713ddc445cbbeab6b01d4e568dff3bd169fbe2a 059819ee8457141574c6dda4edeecda5e62993b800bb2148b16529bf6c0a7d13 79688125c0e6b72e56ea7872416735714947f586635bea64120945fa37cc59e4 5adb1c6cc2ad2431222dd58e8a6f3571063b3ef20bb123e3a1071fcc60ecc9b1 cc3dc8f1ffec0e5f45293b94a5a7bf3ae58a4d4f572a9f5ba8ec3b4f34138369 3999f2af3d71f38b14e98dc84e2530f037e83e7394bced0b6d681ac73029e563 67652807e4ed16e014757a70974b4f8db9e6f6bfae39fd0614ad1f06e525c081 d3813e43348dd6866a69fe1755162f250e8e3de00b7ff0060cf6475d2445836d 438dc90ded371c003c1038b170b925cecb796c3074ccbebcb98e3168af4d39c9 740cdd1999f72c2a29922d6ea744085a4d9f104636ea931643943ffe673fb15e 585fbe2386bebe0fa46eca5ac524a3cf4665498c01929b98854634b0a0d113c3 de3706dcad8c44c755bd56ec422c99168fb5f8683866a13d7cf8c2145a49ba38 da4157d8f82d2a54744daed564c987c996120211b30d482fc0bed011e8f94fd9 721a665b9b6194d077108c0797031347aa6b2d6183812e890ead8f7ede04fa99 67cd0f8158601c13c2f85d32fca57f324985a20c4766cca265693c77d87d5143 9e8803213f74d6e5869fb505e8309245889a807a48327769b8476f16992a8198 eb535a0a39ee12899ad81b8327bb17194757e760e134a0bd34a38ca32b7fc9cd 1a94815e92a49195b30d5c6d08c6011f615a876d9f84562d13e20c8796bbf944 ac695022107503164727535604598ba50cfe2c8d2555345948521d94851caf8c 4819c71ab8e12d613df31c3e4302178dafdc21ae33baf2ee3a9f2b161aadd640 c5b8a211af4dc95ca5ddb7554270215cbdec87c34dde54c484e1bf8ed7a5500e 375f63727c1dedae8a51f8424156f97f9ee3b54301423c8be049492638476587 cbe6d761149db8e9231283d7d3e27b6bb107068127e49ab0ea318ae47a52d941 d78379ac13a4e4e05a8ff9cf451d22fcc16d17bf4b06f66c55f8da8584b08fab 6edfaf19c5dc75df69facf72eb82bc2c016b2650f32c4afb731f7f3fdcdadaff 44d3fe29429f69fec91ae3e2e33b227fdc00a8ab78e3510b2bf03322f20683a1 a859389fd668d9b8a8a5fcbd3ad6c49c751032078462fdf6aac4e5600b8bd37e 6808fb004f96d638abd7d164167fff230265214723a7b65344011667814ef5c1 6c3654047c65a6312b5f785a9246e064f1d223913b7e11db00bba27b8d6e728f f1383ffe364151b77625632904f34bda76a33df6561c30d591c30cc492b0fc41 6cabd4505bd1a98ff5f7c1c75d7d4e328d691510f4a23ab74098c3b54a08ac03 c4818a93d8e531cd4534694bf915b7bd5d65baf66976fea183e3df1ba69b65ed 4ed680ad71299f0ee843625af25736e020ed7bcf82ee266c0e34537b1cbbecdb c8a92d1bf5112f1781f2a7a528b196a3bf4ad426a48c30174be6ded892be8be5 6ad5557af5108ef9b99735168c733031ca356c49e9a4cd26bc6f3a332d9ec219 5c0ecde6ffe8646985d4552fc134f6d013b984474f29e62d6626dc941c23cb0a 31 e09678c6286e175d47fafa72f5d04fd5833415510d8994a41037084e99f7eb01942be52177cbe5938cca162d353d5531c612be695f341b69458f04e6f277360cda48b874dd0f216161c87af81f450c42d3118f9734a61c30c0f73fa572ddfd099feb99360e6b20c8ff24609393b6b825132b67df31cc042e0f7290ee727f4802ef838bbeac63fad050ae612dc8d7f5ee20a0dae75dc43cba61d88f19c6e1fa0eda384f429d11996ef2a7e669ebe126593d4efd86e83d1591a3fddaa42544f2025d0f33e31240ccd925cf1985abc614ba50ec49430e89daff56640ac587f3420686af1ced9944741c869ba7ea50cd6bf22ac3a1647f015d471aee150fdfc0560468f23a0040d40ff7a49d54320bf02c3361fd8d0188aa979de8a5856d593c9908d726cf0acd5e84a59b168b20ba2a7994b778fe5affca0322ae2a6111bca20201dec905b7d3317b33319cbe00d4718c64db3a11d6f365ef311816936ca3052d0716b57c354fee3c06d90eed59577bee10758538e4ce2a323a09446811dbe02f0c9aaa76595555977fb03073f1d30df66429472749ba11366497ff6a658715f504abe5f5ff5845117efe1057a6c6321c8f851ceae6af9f4641c0e965cdd5970005d32a920722b2da3b8ae5d178f5d3fdc5697543934d7be637d52aee1e06ddbc0a6aa682c560baae8de3ed965a5ab9d8dd337f60c9e577db9bba0f1e6f7a87a204cdb74687b04c7dddbdf079d29b92cb3d21182bff1d83fbb72b54ae7a598d44023e25e1abbedac7a2dc20c303b29d931ac18d80bed543803d65dd469febd9900a12ca20491c6c1c6925f70accfc25481f1ab619ca358a2ff8aeb0ddd7c465890244ab0eeb0b4b6ff35c0a198d25b679dc8000e15a098d02ad71dfa42b39839607213b35cd7d28f47b0d15eec12c1d1d6e0cffadad7ea636834f244e954079860985b1cb9aaf8465729623250c669c481737411bf4ae4c9eadb78355c6f976ba0d4d5cc6d696186780bc7f53941d7fc6c50715c4c975ba2d414ed065db028fbd0e44102c3004cd41ec297c997ba05cf556fa077e1e3eb27d661ccb9479da859c0c6e62cd1642d5a8418dee5c5ca3bb72d9d9e77351957f74022c914c58dfc0ef0d136dc631d7a2f9419be922277cfa8a99444ec946f071899dd973340954612b08ba99d140aa2b3b0ebffe0e0858157b33fa8aa635d1120cd5b4f091b2f7d4d70d752d34ea69b42f9c24f8e20db8f8b48d6018fa3c1f68e82945c3d2d7c75c4001ac6070e9f37649995d18f823f2a387910959c7e4b45b52f20960f42ff335f40f6b29eca81894b8327dc340d2e349f3b89ac3d81b899f4b3c871f8dedf0d32103eb819e999fb0d90a75d71b9dc4fbc7fd9c8091dfd0dd9ac9e0f26e39dc9b280ff60fd6702c6dd246e21c7c0bf8edc4c2875cc3d0fbe5cb880ed1f4a95b8c3401c1ec866e1313dd20d1863b3c223c62cf13f5ec1289a88503fd4d93f8d7cd4c06a16b811bda412dab1d3a0ebac89c0c63b2e686ff274e3ed11fb81e5a8c817e0536e5088246a51c1888ab3396623933240e1e51b332d8162cd39c3414fddc3509ae1d46107d16e66db727d4e6833c9bc37b41518131ce274a20b2919c36ba0007dad9f262c3915c174d286808d9d69df6db283fbd916b4984d986ecef6cc24708893ae279bfb5346570e0903df8893b08d81e6c08072d6fcd1b5e1201c652fe027302b5121880483d2dc87365af6ebcd76096419116c79ef3323b43176913450fbb1260896e75a0be1d17801a8bdd6d8bcbbe0d2bbae720e384b728aac4f2970cfd590820118787936bbdcceaed78df2e8736628545804baf900780de46c09b0e66b035d6f5b5e6d185ddaf2919963447c18ac502837d5b4f51c6ed68bbd3bd0799589499c41e62779817ea25f19561e02082754e88c931c50c24f61869e5e101ea4b9ff34272e508cab3c9c07cd7b800883c33a065f2ce490bdf12ff3342400efd68d22c3e83a43303daa633b9b6500ebf8e42d3d58d1723bf72bd98294310077514f10278cca3f2caa7a8d4d2451502e598f37332da1c9bf86805f422d5bd08d97c2a12c7a72a5516962d966ff44a5b45c1b12bbf6da474813504d1edc693062fd1551b84bf4ad7e7b2ce18892905b5fdec551d38b0837f55caa56910c5cb0327188e15872b48970d75661c5b76f7d0f07dfce3fae5a7d28417d0648d383d097bdf15b78995995f581cfbe9fabd1fd7097a27c2d15e980d1e2bf6d70ccc5b089ad000145a4c0f78a1667258e695cc3b46f82c596f9807f81d1343d787001f0c3343dfed759eb42e66164dc0bb494d99b55a8748e1886cef1e47b15af0a6ed0b69aee2ad1511f8b1ef1d688fea65238939dcbb397c8f2fef42c896ffcef95907b5e101af3cca741d52a6f2807266ebef644b9b7396652c2cd6ae773795c4ec0a852ec1b9be565a37bba45219f3b06e8a0b00a8cf0503a25297068e9840c4f509d21c4ef0b03c08f3f8117f4fbf703a60b8be2a75736cf387f33dc4655bb57109c84a6fc95aae017894a502be8a823f469c6aee9556e3bd75dd2803c99869ff024007359e8ba6d1e3c0d8053086587e01a735339b7d2dfcf466177faa64c19e0410eea74d493684b06c376e695ecbf7e04ea14f5f0c046307d874228259254a047bb1263e30ea1fa1f8d89b1178e83941e192350f8284aa75b38c3541ba0097094ef1d1e002adffe4e4fe29cd2f56845e6cd3c11e4ecdeaa96effb41852de400f1bd2e9a712e7cfc601cf62051ecac58d86dada2acfe7e789b511e840883e5506d86fa92ae4cc1c46f7dc857527919f471668da9191251a60e7713f5c49d8e704bd710a58b6737b3cc607081810e09e8f5e58a72003d22f232133e7b031c42c062154a51d4cbfbbeeef4c0eedca5c73379adb1d743c5ba66b28dfd7d6f8691405581650bea1b09f5e9eb95484eb2358392d43e0afeb1b8cab2422e8212f09700a84fafdc7bb6c33557620356d4890c925470e30f31e7cc431fa72e5f39e03f604cb21362b3a19e9e4b85700323fbdbdbe2111aed6cdab45d805ceb8c715c35507b141bb3e093c69f9de6212822dbb5318e02eb40a171cbbf949e31407b5c9ee04d1a483e85fbda27a92287d85a52490c3eb86718f139837c060f802a3c4b807064c25bf40a9e047f826d1f4af5fff76d04bfa99a54ced5d80cf8d28c73a181c0ba3f4aa59a28a38b387ebb46e2b7b94e8c960446891445b54aa52857c29c47905f41d6c00b711ea92d667e4ee6abf0295f4104527440e4df9b9e238196988c00eae5517d7f41723ac9eac1647d02b500db7e7eb60d5612e2e89173562133cd80959314f95ade28704cb9cc63c8967354789581142611b8a63421a56bece799705b929bdf292b065015b4f6b6e582a29a4f175a13ad69ef897ea2012fe2b7c3e02009be466bb14c8a39af33edfd6ca5907a2888c0b8d8e5e1b99857060fd4e74059e773513b2e4820e8b76e1273baa0589b126521293a9649a8ee412ffe1dddb083375370318927df8608de41b6f37416ad920e8813f4dcb47f01339557f986402451207edb5b442248aa34ca5c4946bbbd1ff93bf51b9001f0d735a0c4857880deec9b59ff810cc193b8ed503f8b8d5697f2d736030e61cd40cd1cba00aee4102eaffecaf7f49e224a3425ca9cd850c3fb71a1dafcd52a948eb0e3dc57bd0510c1ed101d7d6dc0ee5116ce9ae3ec0734826cfa6f9ff8271248c72acb807072906f90ce457871f922b8d74c95ae7cc6ac98ed610f65fa986b5d49523e4f31e1b019cef1ca0f8219ebaea071b116fbf8c1d38c239de5341fe9f899420d777183309020d86a19d9dfd2fb0caddb266c8e7d9f3207267405e554df1b33dfd519ae400d05c70332278841d8d62d554ab9e43db5bf634c0aba75047fdf8f11bb40443026107eb3c7e401ebb07d3b298e8d335e5fa84f8d835495521f044fb2927a625068216ba33efe82b36f6bdc29b1acef4d7b999887cd5d944d639cbbc3b38eacc01508e8bccf0be4687ff8b58098a87ae2b1978960378ba23e6a0052fd105f0f403ce969dc2be880f589bcaef738cc90722883c2b0c48556f14b85b9a14542f97081cd63c3545928a261ebb19757b0a57cf4b3667c2702b96649eb2d9d18e8c8209663abe8e91098cf1bb1cbc79399651cd7cde887ae192306ee0b97a88aa501806e96a4c23263c3b51033f733f540d4da59c9ea30e1f9724c745b7ab421d63a10dac08488ae51975071cb8c4ae6df0553fa349d62e5a7eba57912979f4efc3050f33ba087decab2a48d22a1f26bb48467fdf54eb986fab3e74270c0d89bcae0502c32cf0a88992ab7bd11184b638de5b1dec393d0fe0121f31216fc26ffadd17050d76fcdb239d02b2e70e5954cb19ecbb84f422e583a81868c63a2b13b782d7064c506f463adc2809de72e51cd718fe686e17e30fedb13481318d739d19fd260173a5cd8a3d00742e3653150bcf677800bed17ee6b2e1a63903ec7959b5a1f30b9b9ce010dce7908da3ebbc3c1ec8c4a1003bf4e21eb779a42f5d03e04b934704d1e9eb5ee8dcf795cc8a13376c96fc4294d8647af67f590abc4a18955e5c71078d918556d56b9b07a00e435b9647021a9264bfa93092fd76857529772f87a307fb93efa2190e897f97880d259697c22e8cb8a5880f1408a299ccf3368854b709e9118c03384911690a5a0bfb49364b2401fd306eab29e0804e6b28e03852f408c9247325ef760ecbb6e2cf29f4cdd1112c7188ce37803cd9cde6e1ba3c26850a7c11ff91063972535830d78907bc5d8ee2f1ccd53179cab41870cf1959861d03c1a76b3b7106e8232f842327f7836e52bd59c45f260a81576f67cb875e5b1601ecbe45035d21fb76cee0f1cea49e2fe599b06a8b9c5de4805aa3b7f66ce3d502822a2927fe05f67c48d029d01fec72ff9ea3709c7c117659d8b168d22abf0600133bcf37195ceff135d7503da655409949cff3f3b6c80e3c73fb533d618dd30c15cec98d5abade4d78b4761efc4b608f1db13d243d94431abc8988269d3a2804b308b2ff7968b0c9e5e8e4e1cdc9735884fa5ef6ea86e11a208687268aeeba0a7a4b33e8f7fb7cf3b038208d986743ba37eaaa41e3ad9c22c59998f2b23abe0f5f741dce25dfde2e8fb69a3f11d51efe4f3217586b42eff8e1a8969e473a6f09ed6090ebc709ad61783d512c80d51d08e1e701b26aa2e152a55020518ba7330653d5893d0b43c18bff7ad05fe3655c8895c5c9d3184d5ab221699b81fa875209b3cacc6685ac2aab99df5fa3f53fb439fd294a2599b2a12a8c4a6548bbba8801835671a3a21d39dfb6323d8af9cbb3c44bbc7559f9946e7f4103d7b0a9605a051e76976d328ab3dc2ce4a5a1350e80db20826b285f2dfae02f969c020b59a60771a85eeae68b12e65a7c1bb9647c34587145143fc3a5b505d140261f48de2f07910f8fb905b22379217907253ddb8632299b57aba1197c910b47cc4551b13c066c104577849af237093a4b536677b3f80962023c4d89b98f9b55402594dd2d033df05e049efde3f7516f100f441003159cc23d0deb5b79b456d07a4a80652d08f05db319131f5ba0f54f9c083e445ade70fd3785ebf31b3e651af7aebf9f1e02b9ab7b2e98fbde30042f1cd7f616aa96eef195dcc93b78f9cd4ac974796a78060e88d404416c567e1345dbe50ce213ae900719dfb0a4737999432a01fe8c9f0e12227668445d56215fbe2521780a07c2e33a16adaa6a77c13c74c5cfcc4a42005697d8aacec53ffb0b85ecac45fce1330bd8bc4899fa91cc88e1a1caa223b2031fac5120d7bc8aed9c1e59d52ae28239aca69d6cd52c3950715e27695db8980ab38afe5ab51a4252b157c3ffe7c6bd2b75b8c93aa80c2c733920b2ca6d52320248483f109d327f79d4e78d5b1d6952efe147979c5e73a15af1bc6789fbf4b80c9cc7c364013dbe522cc37f8e86df62dec8e4a12d80b5ea89cf8f45569a54c50e385651561acd3eddafa2db494d257b66bce2be2feeb5ef0cbd74aa0c550ca70f1d51e324c4987c8895ec75046756eb8cf7d59f2d8ed32a247edaf432ac7d5e03baeb9ddd615057e6b863d453b00c1a617bcd4d9340c196b496bf39506ff7b602586b6466a92ea148e4910f7a106c002277da66f3c2e2e88cd816bbecc6aab20274f248fc73f02d3dd2efcafdf2309c24132f231949ef3555049be4f08dbafb0eaed210c99cdd6648ebe093a93ad20cab93dadb8246b096f32eb2516f6a89ab091595cfdcb3f252108e1271d8f6ebbe0ea5277047a9c4f666599fa31a1e8f3104ebe636221d96653821f54b1d745a1e448cf61f6acf62bf22592f6523eb0c900e46b0547622d76d8481585cf909c4e04c2e2850f3915ca7946984a21b180cae0c4dfdd44310e8035a6cb70dbd7274eb53b44911651f04886e8de3d8feb58eeb0bdc3f6a63b550d96840a0f931d4600fa423371d88466669fc0caa70c5bb45a1079448a0141fb8dbbe36887c708258705ae13b131a5a5fd3df759fcea11caadd051402d001350e4c08d67e239b8b3515dcb1bdda1e1df691f38e6132cb9e80fc0bf81dcc709c7e29b01b4a1ee43ad9f24c11cc804f26c133bfda04f1eafb16c60ce7f9ea345fbea54f7397466cdea5814fa843dd372d30ac49393b9cc74d3f3b0ecef4bd90217b8c231ad0462c29387b039529033130ba34279986de7e5489640354ba38d1bea2f146684424bce21e4006be1c1cbad51e889a94ff5c37992f7b03c0a898f1f2c0976b16359339b27e0ad286d3da23337c49d79d8305bea06ff40b56c250391317c0ad3dea1f3be23be5bac9ed6ade9e8c75df7659a3a00b1c1d0f7b013fb839d66ef102174096fec84c50af0362ad372e4423915d36f3d812e808a2467598e952e516a29e16e92f1cd6ec18e57523fc2d4b70a0552d1f46cfe70e403517d598eb3d1a20b87c03a909bbe9ff5f233c88c0124e7ad7a4d2ff7e4005b9d354ad6069acaf7eda802b4b28914728b5898968796baac9cfd9c2606d090a590cb064f53e5f892504049716f98d846fdb1bcbef0c61f83732f7820f7f21048f6ae1a3a4450b897397569222ffc2893d4fa280d45d23e2027c8f6314b0080d733dd234e58e67b4a31b5324d7033672a19620eee270e85d6a0eae3b921f0d01582151e29a844d0cdf6c1da9023c4941b189ca2c049a69ceb8a868837cbf5c0cc90361e66c6c1b0ef7df5fdef097d5a447c0e471f145d29b43bfeaf66f0509049ce9619ec2ff8b7b457f6af9ee79a9cb07033bb6ca1da962c2d6b678f7065b051e0147e5ef60e9aaf51b8cee66580daf2c69c67a9744741fe6e96c19195b0e0c99d0f070a45dbd0af6bfa3bbd210e50d2382d858f9144104942272321bdc5a0ee42e5d9315ebe848c16ffd85dc464194bdfc0f09278aed72beac0e8ec1940505cfd3d874594f4ac636fbe6729014f239e43b471a3ae3012debfc944a8fc0780142daeac8f8cbab98058f94d97a5f000634c7d77d797c4fbb23eec8747b1d8e04cec159026526333304c9a869c5360bfa1532f4b2b658a269cb56da17da943204c43e3583fc9c6785b4fdce469c32ff433da659f91ecff57c9c207151bf36fe0a06de682d18630614b99c15c3ea1347c293b8f183f7ae3e009e88d2fda0109f0f54b80b9a2df089c1d0c6a5494e6044c5003fee21ef217c8d802e1b6310cf6601611d8ffed3ec3a29c786b5bce3bc8e4d3d975dc674fa1f17c15180f5148b6a0121082e9d9b30aeb18a4058c2ecefce3f3e9631d5e93099c9d47f87f374630d0b29526cc2a15c76fbbe774d26f0ed70b86e7ff67463e3204ec8a482ae4dbe2309276eb20fda1f7a5b3d0707bfcc2beabb0dda477ba68f39071bae70425e7fab0ccdd5efc4fd6284c76481b8e7365a4438b0d9463b8163411962a12ee301d9020d5b31d8d17a3252d70fd56159cbbe3cf5145c1e7e4659098ec58ad38fbfc1770173db35636560e3f7fb12b6785f62289c3f2aeeb81937823cdff2abd377c9540e57296b558d7f67f49b4478b464f98bb08d1461a58c7f62e719fc47ca08e4f508370cb139663c12712dc7b7cf5f0acbdc08cb8145739f1ca19440fa9e26c99a0bd38c1e0983cafe1c81314f3ed8445aea70d354127b17fd6ca0598ea50808b907c0ee41e6bc76831017fcea66103f153666aaabffc496084a43417b0c3a84630f3b97ed8847d94f5b8053dc3c00acffa1544aad18b4fd56c78b3c9949990bf2013f529b5044beb9d23a55096ed9d7865435c1024abd2ca87dc213e1dc7807af018031661841d36b72687a7151283d7de42ced84444949bc004b5edfba099e800f193f09b542b30aa3f4edf5bcca516f05c8ae00943a413bf8c2c5845a9dd5a70d16576f2c229c8e8d8a7a38e317b72adc83c1d53bb9c39af06addcf33b297ff02756b9e69cdebaf6a035d79a9f06370aa8c86d549109c642b418245f097e20b04b01c166a16f69ee2a02ed8df23c6eb9f5edd974abbe9cf83cad6ade9e65afb00ee4ae28ac9c73f16e24e95d3cc2ad92e79fe02be99a7b66ac7c19fa8f4873000e2591eda2565967f65f23cfc082d5c26a1ae09927aea39467ed67e53200bef0318792d9432d39360f2b267422a9dd6f2bb38a971d905ecd0c548647a532ffe0c792f689e257f6760e79e00d92cffaaf2cae573627b4577c597703ad95ba83602147a0cbeb3b7109b3df7fb487636e58826dfea0b4f100cea7b8a7b797eb6e204800445d108e4b2cb3d750294989de215a9f801db9e13141bdb7066178de30b00f54c66e912f66fe472a06c106f1d9d581edb74b02d51a780fcf4ffed6daae0055d3944393edca64e8ea3afe95b640957398153348bf55c94c03ab1c6105f950a6028cf6d69ebd747f4ad241ad908d54eb83544276a0a8a3143803b89bd2cc80a00959bda8845088916105ba8dd1b7627601d43533bb3890bf85e41463055230829a5b5a1245a0b1e944adedc436e254be2366ec5e76d2d4b9318a86b5f7f490da0bc882d1d13477d11d17c91f7b63cebb1fb10bc92967014bd16c8a5965e5f08dc5f2369ce95b34d6c8d2d2d25b2f7f75b03c41fb002307a906d29610931ac03c4b800978d38de16cc23ab92d4caa800b2add89cb119d0a7194d50d1ef5287003c4fccbdcdeb8176dbbc1e964e8d6bf9a9be4401c1cf0072c2de2e9515d6f700a78d470677986c418e43dfc6f0f08245d3b8c301a28044c418625fb06ca4bd0472bd0fd4b01137217866b2f4d5273444ffa94b1c43e156add2dc3bc22546f903cd80d6a9e05548c4672e70a93a1a797c6015358efeebb6807d283ff856204705f428a3a06a011e07c8daeccd0fd63373b437611e457094f7b2d13172374ac70a8161f389fbb6421bea26b092a4bf8a3b9b888eb47ba82ef780358efac8503307094c7e0145f366ff3a4b9fb3c94d46e0927907579a7a1133ba345ad79d4dcc00a7834cc6e376a78c35ab7133f1e482b4c4d4effae5facf4a9838d89c072d7e00f4b7effda8e257ac2eeb46ea82dc6396d52ed9607504ff6b852432f318a83e0bcde26e122971c7dd9d92a1690ce70b5aa7b947645a49dd3262bd2c1d988c3f092f61bf555795d4dbb539ef593b3c2f5ccae19087a9f0cad6a47d70fbed6d5a0fec7f88d6652c529835167095c69be53ad2224e3b28369bbe3ab42045398fa70738b9f0756d9b0beede437616e33d65b9cc09f306d6983737d5e62491e0a1090ac852e6c83f13dca5d4a9e08c76d82f774760352ada589ee0a9bbcb756ee71701a02dc3df690218e664ebfeec6b782fd06376edc57d10513676b4054cfbd08801135356067624bb2030cd2f644616e5526bef25df44b8e3b573b0c2603b514d063e7d5fb0170fae65aa37be832ed397206f333e76094a44e7be4ae4f14a175a02163fbb4363f672b2e47628d86355363660a02c02a0d1f7ffcd496126451c0d017cafd06bdda34dc028d834d77c6e7ea508f1720b360c86fa296f37330548920b48482c0594a8cc8f0db2d250d1d1a95c11f27ab5a61099b7a949490db45fd90f677bc646723f405f29076ddc98c3a8f40e1c82f85d3ca5565de539baff9cd50f0c9c0cc6c764dc1657defcfb6ff11b86e483ab4a46507f08af763dd40fb4bf0aea5ca36c9750a32814f5d3df4a27e6b14e8155675e593785f25efb2d4db44b0e +generate_ring_signature 5354b346c632fb825e3d4facd91c90176cef0f333295379b68ae2f3d646796ab b232e87202790b0f139b5abf06b5ed9dea9fa10b45137abb748bcedec49957d4 2 1d18a97357d5c6f3660f9cbaf1d05bec77fc60225b96c643af06888b41d560f3 e4943e8f3d243545a50e1fece9b992cbee891844f6920144321f5026d51c010f f0967d0fca4c4f72d2cbf40eeffac2483d32aec3c862f83c0e938e8788e95602 0 731ba2db3ec9cca7a13892123a0f613d248868f529cdcc11c2d64945fcf82a04a1147104050f4bd63c6bbba07f7ce19cf0318e5d18114722b5a7ffc1940ae804294d74260d8b51569d7ec2c49903e8c6904078b324dded75463a1e285a95510c56d30bfafad9b6a184ef93147cece263b21542f048415f8867a580d8a02b1300 +generate_ring_signature a3e9f19a6821d12b0cae5d619f939c5d9beaeb9a361f9d7bf374b3814ff23ac3 5be7e561234f7b6bdefeebaf9a512ac4d97b77dff058f832100634dae4b222f3 4 1385acd49f2edcd1d00c3e69d899ff286d76ba1ee5e7684e480d914d31f57a58 5c43220a60eec00974abc48b6dd95e001d4b1e362aaeda5b712d8b6aca644304 02365a93fcab00824d25ce4e4bb58a49b9f68ff7b1748d1f03f8e5edd6fff416 a1abd0f71d7c05bc675f911d3c4e54c1b8618c603951a1de691eb38f030199ea dd3b77701253a786191b9d59b556f2b96336027fe8b0de80bd2b059acf610d0a 2 b9c1fe225cf0ca30b89d0c03d118e46f91f513356976a89df306a988aa96cc055d1a221eaf3a00fe25989d14dc40ebdf6cfa48bc50fe8c676a9380147d7ea70387287c180bddb6ced712597189b093966ed73589fd9de75c8872069deeedf000e7e68164c5d5dc4ef5c8e052e86617e198c9d90eb775d7a91978a035c2873c0cd7fb8fa6a64ca4e2a3f770713fe89196d420e493a97431b97155cd3589873f0c354ddb18292dd0ea8274395ec921476a7edcc498d46abdc4ad58bac0bd61370e492f2dc757db6b2dd42bb80550371202d9a293d9ea1d966efadc35d2d4f7370e33c9d6685c207a5e11cba02bfd5b45970d76fdaed73ef87e7e52575e17693f09 +generate_ring_signature 095549371963a6086a8533f8182dac9a9288863a9816d457484aae549c10c454 034fecfec4129e575a8f79e4a2f329ed0d6e804db3c6b30178a298acce98562a 2 80e4e87a2b4f800d02c125ad32c11b8d667705547775533c48d73f12f39e1c41 c404cb7233f19eac34d072f1f24f9edef448ab74024a8ddd8d72639079be844c 47b6e374cfb1b6ec4adcd3183f7b9f54812d7bb6d87adab41e1713b89a918c0a 1 d0fa58d03cb64798a267b6ca4fe130c967674224a2ef5af6db8e2fbb8cb0470c2e7e8d73ecdbbcb32f187272690e238b48c5607639fd05f0f44e2a7f59adab0e52b128213a44c07f5f100cbea92167372aa358bf893500130cb4b51ddb2f3e0ad517ca1489c322916f009800a3e46b6668eccea24d98a9ab1dcbad560234f305 +generate_ring_signature 765d32e597159be85cd75d6f4a26b6afaf0eb7618a10bdbd64c3629d5f37829c e5729996355a7f45566941b16bbbdc3e9645df09d11c7a4fe0297d9046d80876 4 ab4b00cd5d57edf83bb7e34a17d61fa41fd2bb00eeb8b182e03e05fed0d63047 1f121a1695b39b438807592a0364e537459d9ecaedd7be6ecdb71b9534ef74a9 02849420f9ae2c064385bf53eb6a49ef1ced6fa4b2a386ccfbbc279633f3a4d7 4ae5357926a9a9e9204bc6f2c8d3c05bceffaded63d44c2e52792fbe87964b89 fbb4fa26dd9caef9daa40f9f451d01747fb79eb9bef92b680df1b0f52588fa04 0 8c714abb919fbb5502c3b9d0c22cdfadeab6241a4ec8e0d4ed01bfd062bafe0886996adf18aa2a1792a5d7c57d63844d6a033ef1f2d5da39ec6ac6330908590149dd2b84dca274f08d870e857b375837b6c00e269d73c73e20393bc45fb5fa058edeeaf8585e261c854675d89852599914862f451867ea48852c5bf87757b40b955eb8a953b2a9180795f69485e0eedc9ef69d534d7aee0d38878f69be585404defa08da1eb84e80ceb58623ac4ca7a6de61a786080162ae2a8e134c942b5b0f3a79729276cd16a02aa859369b5cf79911d123067b456247ae1c1cbe06bb990424a406104bf2557d86f6238dae70a5b6096fd81581bb7727df228adbfe885605 +generate_ring_signature 5607d2ce8ec511c95bb7a1ea452f4574df04bd5bdbaeea20ac0e508f13feea37 66293e624f791235be8fcd3944938a213b1449de9b64b840f46ab25c244e2eb8 15 252083243400c45f44300a90a5a72cf124586df2fdd358c3f2d8a10a9d3b9f84 dbfc0f9a60359bdb13b1eeec597ce25a39019303f53e214106c1b6efa039f41b 1799c271c54721cb9b9aff31e770a27db2016d3462e8f7cdf97e58f5d957d1ea 0f3e0b58254ed1f16875206a5fa71d8b2bd3051cadd875a85c064fd43fe972a6 db61f4aaef31bec7a76142570228880bc1ba95aa3e130efb815c392daf1f648d 69a59d101b46108998f7147556e1a489d50a8de2822cc4b616fb316ba6308890 3216e6c0b89b0e9dc558f22b0646340901d4bff8dd6d0d37b428de10e1fb3d8f efad5c615373f47a5391c88bd7fd426915d61f772f8813fa1998007ee605b032 aad7a20871ffcf814a70a4964aadea64a2ca043ea3ed90c04bc0c581ace03197 ea57e5ceb849204391f7896c7cc93ac01645bb955a35e7295a6201d3888072b7 ef11e7753f6973b1f3c06b2b7dbc596db6f16120715339b17824086c12a18686 8a8442aa38bc171b5fede9ed5892c4c6f8b7834f6d84d6818134a2f61125f86a 12fded8c7ee0e7511d3f37d7fecb900ee662c3f7dc36756d64fd7bd5221ff607 97e073bf305e6e79f257fdeb5d5b126f12f818edbf3502a129a71948afe94933 71827fa61bc9bdf166378ae6e479ab50eff55f8498804bf26e92fce047f1a76e e1c93e67a747dff61c24a89817f62f6f84ebe585721cbb46d0139ff7d410250a 10 b2f03ed1ff9b3847c77ba6b73eb273751c0e01975d52b04d3b5f05d965cd410d45910e07b6cd217ce9080fcd84191d92c7a1c55dcf6f77511e90ae8649fdc6054eff8ee200f61047ca8575dfa779f6facc4f74ad75d1efaf171f9c004afb460740ebb29de09dceacbce81b590061e213e62d2dfe4761bf97ed9d7ccc2391d803ccc58e5aa54cb8641209ed899b1913d9b692142d7f45632915000ce507874d0b3bf38e7e7034c8e60975fb6bcfa2e0882c8681e62859acdd5c339dd27f664003b33d730635b7a262e5c97dabdaf00753925ee57920f83582e93fefd1d5073205e610d05cf7cb3c32af73feaece4a84596feafe08c714d8c24bd7bc1e436d710492790bb7320a56df42f165e47891fbd10a804a9278266c260e1c348cfa5747098c0f37d780402e08638c7fd2a0e0cced7ab579cf7f935d91db49dcd20499ef0a61e9962b7c454e9e8308e9a4ebc0187eb60b00a2fd007ff4ae11c53c29804c013148a67e294e754b2765bc8611df29d95c3fb468e6844f724136dc47bb082d0a453e6a8ee62bcfee6d9602766ffa50497cc4c278e7207d3ed115a132a4999d00139b6725e139131f4bb276f823bb823dfe6be7902caa8f2811fd136362589b00ae178b3160c8256cc7c74100a5c9bd14cd7081862c85cf68f4ad664b618320057dc07e4f19e5e16230c49429f7d1fa97b534829a48c78b79a34f13b8de38e60016a6f1a8df7d004710a22e2f28816d0ec76a7f8e76639f702690a3bd87653408c134abdd131a057ffeb9bd9138f65ef2aac6f1df3245841c3e253c7744d7ec05e81d092d0aad6d215c4495729db9db88cb41dc8a2ebe480ae5d102a97b90a10dec8aa10235d82775b5e46d324726c06a5fb1606df32c27c1579acca543a87b0ab3951fc67a38ddfc2ddb9fa88967c8cc28ca1ce52dcfa86a28a91d0fab700d05a1d7fe50b13af92124a6bc06c3f92c022bab544a5d3d37577876bdc57588220b56cb694ec36c8bdc928e634a6a8ce4121debeb7c97db6dd7641b5d404e5c9e0a0300d423011fcf8367eca32333eca36931efe6f15cb8cb6ce9e2c352189cd50c6b2a1474c267f5f7abf4f49e2284d03c019006a9615bbe11949743eb64bf710f0ac80c7219ed024a9297c882be1087ff02ffbac14b4b2da87ec9ce583ada0e0018a1db64a022e9669b537a4b30ccdcbab69705dc7ae85cbe81009279796fa901cc4b3fc14b24ce61c8c8e7e0921f7ae468611a0dbcaa5c68cbd30a2df1e39b0ce8594d2a8fc7ba0ed48c09550682c648cbe6ca8302a2d16617a6a9bb30bcc201b123a72aef2c024cb24a8ed16a0d839b801b0432c21d6ae0db155f045ad81209 +generate_ring_signature 781f7aae6916cb86442605ca1c1329f08692a28c5cdfe0cfa95d964ecbe6f9e7 dabd3b459a7ca4562fe5ca42191a402e51cdfe567079cffaf7ebe599459490c0 49 6d5bbeae1447773bb341d4f6253c84a563d776c81124bab9c82b8b55966ef9ee 5f3582036521d737a102ab0878f3482825882d869168795c8d29501d25741e71 52f9596059344eaf95f52e49d2ec46868c01a0612413866c50b351c5628fc8e6 57d139af17d71882f6a385f6a87caa657970517595baf226175248877f5ddff9 a9f4ebc8be21b9348b62361a712c90841c4ff4c595b36049efe2d101c4efd321 e8415eca3390ef846f46259c0e0fba6dd7427a7b5f1af4cbdae1cdd34abf7569 4f3e26a193a4cd0e338fe5ac6b4451217ff963c1ffc7ed2afb8c86d534b0bdcf 438597f124d1177200a93dfa9d8d0a9cbcceb2cbae2d93640147ff1eef7a2233 f5339ce166c0ceeb926acfe4a017911f9e1e3650e4eec6457e20cf52355ac4f4 4c59880049b15c24b6f54586a69b8935b5d8893a7dafa1550c5123cf0a253cdb 18a2d68bcf6db85d092a4362767cffbc973fdeb9eaff23d260c78777f8f57681 0d45035f8548a968acc0b0815518ea3024360446580b0e5878d75b0610911340 724763763a18220ca705b3221d8ee2231cce67235d0a75ddf076e8ad5523cf60 65236dfaaf133b1dce26fb478a81305bab5dd30e426ada4a399e29a7c02ba4ca eb7717bf4521a54e02db70fcb96c20d9d4d6673378f6b2c196bfc22a3d5dffe0 6752e1853091c6b4aa5f88df39696cdf2b7ab14d3e4b140d1c3905a6f86766a9 ffaf2190b741ec45ad0bb7070e66235764c44449ab408c6769eff87ee92df421 9a3fa68c3398397d68f7eac4a19e7235bd4256243bf8667082c4bf5bbc06b386 c0cbfc6b9c6b2e6c7c696cd7a89e4c79c7dcbb394199494981a6342fcffdea0e 661f99232ae0a6143a994c679146f2756cb4dcc6c465145b05d7bcf57aebaace bcd4b4ba71a309874300bbc35f9a9a541a7ee8055f798a4ca4dc546ab021f25a 8937c53d0262f927ef14ae7dda2cbd277363612e98669e58604547676a862af7 bf01ff591c0a495d7938ee4e3aefb0e20b121823451b1d902dfb8f2b460aabd4 6e0d51f94745295a30af485bbd46ef078fc52172f142f1f73e68d5d0d9ab1222 36fd64b91f05287e299200deb9fb4cb0e3de6f0240e2dbf274912579a8a75eac e72d9f05f370aac2cc5e0777bad931d6e4e193179e822583f02983f8c6bb54b7 d589025c70a128d8fd4b6364ada77612879a039ff49a61b710ea5ba856eb4cde 78c4e48f85675999752f7e6114460354ef4615e3ec05d2f6f96b85a0feb2093e 50f02e55a8df0e9bf0c44c66403ac989c630d21c2389ae73f3413f1d07f8fd2f 9d4879da832b2027ebd9dfe0d5d361a4dbf32158d039d6951d20d353d0129c6d 9e5f72821c4ac472b040e19d85234f46aca39613013ac66788c3143eff365d85 9d1d9d4be6eb21f591cef27b387545a22dfa1882a7dcb30fd5f2141b398fd2e9 35147ca542ae0c529dc9818dd8e4bcdc300a867254b9dd0317bf74a860a66817 17c55d7febc20cff8ad649ba7ae32318cac1750da6b4ec47c31c0f49ee1643f1 f24f5e7d6a9a0e9c457a0ebec586b4bb0a3a5564559cbf377138f64562df2484 952e0f4633631f3eb0135819fdb7aae7742ac5b2024c5f15ca1cc65e1cd08f24 7b9adc5c33bcd0feca677012599cd9a7fad17de30a30efc0981029e15c4fafbf 11e437c3869f6f8d822ee753c68b860560480a37eb57706082d076e0f601e54d 7b89c9df6a8a9f261d298a996c3a1947a6f676c2c7be4ae7643c2ac5d8e89c62 ff3e6f71a711fb28a24a2ea10170ec29d4fc3f3e2f2de6a8698783b0664d941a 919436ecb0dd620ea94686ac3fa07bc17a777d48f9c0224dde1703d7a2ebac63 7088fc87666f3a284b325d1a50ef179e47ce44f546bee688bbee3377b5462e3b c4bf7d3009908f391b0a36d2768394e429a4afb69d789d64bbf1377402f39b01 5626037572ef6d5c06636c8d2c7a56e19e4eaf2bfd6229204d4a60157b7c3d9e 94c3d100bdf06065c3d6c21e4d743d925065888271afb52777926c1bb49698d1 45591bae02bab2a3b21a83305a149c0f1ad63d16f23501ac471fc5195eb4c934 fe5634f879e4007ac0ffe322a23d96d428ad09df6eafd123e67009c77d3826a7 e131ff9519e778753cbb08ea67fad0bf1349f8bcdd3e2a9e30556d11ead0dd5b eaccdcec9531361e1b4559e4a9ee176075cc22a6770864c21abab1a28fa062e9 b6b0a5cb6c1acf7b032fe3401997b9be29ae854fa7d6c1dff8228a85426e8e05 35 9355d3a3afe5002a6098010220f31343a446361aadb2788e1b7b49aff354fa0ccede8d1e5d53e011df1242eec4d74c03c5f5eb4685822cbe6a497ba52da04000e9f88ed91565f4fc65b3fbfd8351f82fe4d960e22f71942755cf2d3641271407fa5921ffd803e00d3068bc1fc0941eaaa6685f08552bcd83b8482ba63379ac07087893e4888f32d8f1f618aee2e3c35ea84b5940e5ca3e580d12793981955b0f9975ee6006450b5681c94afbf08be38f518c296f4df53b70e338fb358c1a7302590162dac7eeb32c4eacc6d6c4f4f7749d9c9687c020f8a9ae13a84b7780500389af7f6a3e191273e7722963de426fc974226463a5e34af4d73a64a258d5490f929ff430f05f9e01197cdb143fb85ed5461fcb8be21eec1872f5bde0fd192c0cddd2c4c12711f5b3968e72e5cd309a22f492eeb13dd8db744bd764a9cf6d10027691aba258214eea546dc949e9c372c30b17ad10a9a56b755915036d09d8e2022da76c422207094cb3e37e2856b2fe51107fc15958d841cb78a99c39cdb5dc071f4cba99574d24cd898c297362ed91389cc5b148965934330720809b50cb010c022f36cb9eff3868f43acd5b3af37945c5bc51c61a95c0532fb2cbd59bbe310da48d59c57f620c43eb9f7e2d9e278903978813c3f5b6582eeb7d7790d0a81602b8e30b363626d50390b9afcec243a348535a3515ee78a9d3b81720c93fb75c0aafb09829315d933c3ce46e71017128ed0ebcccaabaebc4c4c281ad4279a813024c2af572af2615bccfe88571dcd9aa4df64b6218f2c083889407513625761300e8bcbef06be6bc034510979835818ba827e9336dd2670a5be31c6031a05c1005a45de60e7811890278f6c7c744f8ba59cc98b24b3b4ab69b0d8c9801780a9003623259e3fcb8a0df87be2d5035081cf934a97982927a2489b6283969f24ce8080f3b07076f61cf859b2dc96d76fd39e85b16f891059100ae9072be37d7a9c404d1eead8761e72e927a85728606da45c876ae03fa2d0ee79eecbe70d8450a41089b735448461c9be0f6b5a1b7b156e718f7520a06720b4ae337d6f6d4bf4d18097c9517da14d2a782374d94626fb388a2a8aa13969d0a59e067704617b010b503e6a008855d9e5c54700ca8852cf2f424ebb0f795466afe212f9c7e11fed252010e4c983c216964c2e08ca015b4d0f61c338f6663450576cb583ee542a1b1830ddb9902e74707af9380a894d1d14f72b3ee8b3411a8f76a90545b48e2f6e20507938a8febab8d207d6d680caa72226cc0a6d23f29fe67b61db2602da3fdca4b096af3a7693aa5bf1b7064ffa0fd762a670d79f577cc9eb551625df85f647434039afcd243d85920e39f59197fae25ae38f1655e8111e4b3204ee96c9af96db80cf2e7f470dbc808bf6c3b7138a2d902ab02331cb8696f5cdf42df15f001a33c09068f93d56df4a57f5a35ca0aaeacf4e5044f07799a47aba5741c81982142b60d33d6afe1e8cc4ab0500b98a4abc3d26f70fda407df8d606918dafdb089dc80085e37e658ba320d15e9692f022aaf7b6e2e282dc6d192cb409c5d1085099b130cfe71f476300be43345f81005dc3d7b651f6080253835837c428a9e702d63d805e64c67d5ace65cbfb6255f8ea6f7f19fbb3644a3dd92a3b7e6fb6ab3c78156027b471ad6a218ca5fce83c3ccc671f7b2518a9dfa230cee43489b35fac8ba7108a2363460caaa18bf63c7a1a8acc6e2773598a308ec4a349546580ac1ee363205c5473eb275878ec49f2cd30064ab14e7aaf69e7bb690fb11c2e17327c04edf0236090edbf9506aaadc3c793c97f36b8d1125ff24b872371e4586d75b1276cc02abb2cdc21e1dc603f9506f501d369875eb982ac684769b90a42eea5797230d0818de88160ba2415c5bdc5da9b15fe698dcd0358fac44a62fa3a6bed7c3dc9001cf122a1eb07c9842d4edce098ab99c8c1511070dcce0c3f0aabc854876d7100a1225c10cd4c82e63e1b0db5267f2c4649bc575df99353634f09a3cd7af0bea00f746ea235bda7b2cf01fa0d83c7bfd3b33fffc2776c1da9c74215dc84ac9fc006cc51c2d26938e32ed3e7fe2f6dec46e76401f76548a541612cab694c6dc510d655e36951521f74488f73f8c748b97225642a6eee956e6217fb561e9f20bf606778a2ea44f9365ceac5d1a2df14ddb71f455fd52233817a942db0c9aaab9aa0e563490341af8381e7c74a6d7c5824b3d2d1975fea8231aafcba1a2ef5265eb0636e6cb6fd842042e496355b13dc4fcf1ff6706b18c63b30c374e2c5bb3110c059c5325f9cc53074351b3805ee1135d015d8f1e9e272c7b9cd663815b27ccf200c66f3db1b7f037ef149082e1157df89338b987456e8c31459e6a62967c58600c886400b24e5ed151eb1d02da908381b569963c1c30b3e24f99a19bc8482d300481d17ac2310bb527bfaa80f502b317d63da6b0b5d12cbc28d690f1a239af20049cbaf8276a36ddf2dc5713b86cb89fd80c24797a3442b495f6238389f466c30250179e19a7a30a5557c6c34e3d4be18eb7be5774cf0dcf528970676caf8f3c0b8dc2e8b2b459d978366af8da0206126142271ca3065e591b7953808ba039360c981dfeea37cc01a88326c80cb579ea64de423b3bd9f37fe60e5be036f76b2a0c63207787a8585ac866756d347e52fb7dc329cc96ed47c5756815d0ee698571048890df269e9eecb7923d93f62e8ab3d019542ce074587ad5f8f5055aeee57804611755646f644a62601fa8bcf0fafa12d7a4f82f1b331826fbd217640acad80107fd50320de0c3f43f3c4efcb2ce606c14d68e95854d241a5b275181a2ce760bf904803119422dd9d1a39a4fc8770498ebb652338e23cb93ce7889d9809a0f0d0f78b08f8dc593bd107a1d7e185932f9640f66814fd0948b8719444c9a317f090778b29287f2b1a9787191f90d46590e28ebd40d83db74de4c08ff6a1f437006d1514db193ff0124393df6191b56463a083a7afdc3726c0cb3f5382ca4bf2000367500d770f5e6e9805ddbdcf58745905463230fb8d6020a6c169a34f5609a0cebf78f364216dbe1a85144a5bc0e08ab21e22dfc88c78eada90c27b97e8d1e083393a188396e32e5618b3c0904d1c3c9d9d3613b3ba8d921fc7f7e419953510278f18bd6a72ad32c056ec8c2777d1d85914a388d431a664c744f62c62f22770b26ceaf0ce30eb45f8107fcfa666971644017deaebd8fa707881cc7396f2912048dcad1523dcac5399446fb24387cb5d1480a8652c5ce87ccc10cc4dd0c412c05da55f3ff8b591188eb5c3c6364b75ac7752ba1c4df5359e7a7695eedd50e80052d65574b6ce59b0e07d30255a1119cfc5e43d5f0e97eb92a9a2253e391d9a105e42c41debca573a6e0421037d451bf13473b80a06d2be6212650d0c244db59071542e9477a14cd35ab47744ea265f45d9d103e82c2828baa471ed9376a4bf10d5745a1caa0f634f3326552f56edfb4b44c6a4317642b6c1ab39cc19f7012f705ebd6f5afe9fa18c64d7a5b5748a5c39429fa9c53c310d74643cbc516f237b203fa66ac08c73c2b8c8a0c4ae8792c73e2ed2850af287268abe8080da8da91b0028c598da48d0e8544eb3449d1de52b7b83dd6a6f86acfd42bbc99d680a2569d06412e0de04d11509efe404aee94d466df845258599c70e6cd2c5a621c2404c00efac5594132ac56b4fd04f35e2b0c0178c571de1059dd4bf5642c7bf0416c820b9f5a2eba303de9e8c2c2c6e894155640713c80be86310441812cfe262b389009fdb8bd46e9fefdc1dbe2f6560b56f29cd706879ed5ae794bdc79ecaf57a7450a9c15235e55cc262c02b2edcc2ebf795ec9a37f039741ec3435ec5e9ca49fe00a8facb37d6d69565ff7bb35aaa7a1933b988f6e5fcb3e44f73df4d6a31e3d650c1e999bf28cd34556770d0086f9897c9f07e755ee7eb73f5a4d18a6114f651b0ed07afd371cea2d8d831cfc62228a38bd1762aec43bc018fff038449126e81f07ea7f6a21a379e80b5d22a00bff43605a5c641ec986b955d75cd6983a03e5a40a15ce6134535179a72be5ba5c83502a052abf50cd6da4aacfa25ee7ba1361930821c2a9224299c1c3268131866e4f9f304bd406276e04a369818dd4924445ac085b5c6fa5174fc4b659b57102548835432cc67cc9c182b853b0c235c4ff93cb07bbde23d68de1117a7983807ab4362bee70f01eb91d90ca5f788e196df69c32041d2e0a8e37006bea18932b84ca68a744ebdb6aa6c077ef32d5f38b8aa91b5203280d0dc71dea4cd0ce59dc3df4239706a24ec314f08c64dc3a9ad70d4102a90b0a0445306210dc1a7e2e13b8acfc87a5783810e8e1114c3653e57a8c6fd92a0ff00861a19b6c95e8488e5b941c734c04b3ee61a6c8d8bd96b256989eb9aab506 +generate_ring_signature 0ca6be8442f73c39adb0992700397888777437a7de0da8c8f80ac7397c51f46b c2483ecf2cb22c97aed88f73d621ddeb6f26c3417ed263dc17a486ff77274806 1 03b86aade5f2eb2b8868d951161eda03d4a47efe945a9dff7d630de9089a94f2 ef2190e473cce3732bb33ea3a62a4d8172a78336453c32f4419d1437ad3e950e 0 fa2b4488e06308a905c5e20581b8508c5374f4f75410269da03ce838cd2979028e69fb7ffcf10007636e913d3502f68021b4994fa959ddcce562ca8c02b6d10f +generate_ring_signature 79c5aa9e030b432d9269f7e35bb8c1ed8eca493372526a02ea1d6ebcfa52b385 9b9a27939cd35b70d56eefed6bf3473df1bf5e1cf3ebaf7de8ea58ef212170fc 16 1e6c15fded661246e31217f773daa1c73c6b5a535dd39cdeece6347aa89981ed a2dac02c4e2ecf3f06cf95a267f7e1db2bc014bfde9b8d5e4698279429848a43 ca579ff489a24164edf6a84c9bdc87374b47efd80c3f994184b770fcce575296 2e247431d695436c7107a280e966eaaaa4d90440d824f93d1c96ae49bc16d4d9 f2609d17a8633257d1cdfbae1690892339e49f9a46eefa9e7b97d5b0570f9cf1 bdca7e43816c3c6fd0013557b1e0f2dce14ead44b6ceaa381986cf6c3055adbe de1b17fe16b510a67e0fc049a5cf4f801a9d9550e7ab8a5e4f74ada85a4057b4 2e9281c688bb6d020dd8a4079acab780a40329c6c54e1947f0e0e7d90b614aea 51dc71ffbdba2913ec8e578384e4d25fd2bed760dda9649155d4ef3f49898c63 88d6f98dd9e6c2a990aa0120152a372da00c455c97b22767803121f55b9d3433 6ce4fc262a6b4837e5f7baea0a512112a2d72dc6d36570cae857511197eee9d0 ddf3cf1ccbed6da657be10b878abde58598a07eb6be65cb870978429bd6550f3 5469427cb812861380add098f93b02d766d7b9de7b5c34d17bf8b2105bb99cc8 ae7c7772243d1b1a0939390bf562946634fb8f3a3df045c15f622aec4a19b05c 62f43f2a86d3cc9a59a82ce2c087c9442c8f0de3d648e319793e8c7ae4158735 1fa26c1a7685ce10b3734969ee68b9d8f441b0ff1beeda2a6a5ce41d7857727a 7f846dc0a1378202cd26c66f6d80322192979c9191c9bad913accbe8f3b4030f 7 69b1e5fe87a16a5a7a54b64d7b8d83ecd508fa0d91e8ccf3571b88d7a9cc970349a6b0ea41d60015b39185d4e73839963cf7c928787f045a393ef4520d423a027269151204c961c41870863c88252587b2f65b63c6cd31b14afeb15af93aa70b68d6ee70e252b2dbf7621662a0ff8a4b50f65972f3401145103f3ef39020c109445ffe882b116927ec96214d4eaed46118840473f03e657fac317417168da50ab497f018501f319826c069349a509da85e91a14af7ceb39bbb03e9076bea4104a25c119e34b58e1f06bfbe89137e74337dd379be370fbd71502a44e28abf9704b174c466b962ea73d91faaf09a520ace560918d3db0ae4f596817195b552f405cf375ab3cdb82edce5cdabfc4f718a0e33fab7d735616c6f83ffa4271cad66019d33be509eba4363766bf685a64938b21666d786f36ae8303b8cfe82c3296a044e9a33293d814e7cfe7f324d10bbd55e4b3a4f8e7ac5f3b42e019e485f3eb9073694a88531baafe2aa47621519a2396a48b5d38b6695f5a99eacc3a627e66205fac696ddfee0f963f1435f29f0c59d8099db7b25e61c44d5aeb3f6751b675c0ad4a0e77ed524a5e8d30c5131aedaae113bbfc2d9e10c777f46708af2ebc9eb0cf12d48dfff1ea1ab3eefb3531882660f349420fe23ef158807c947b6d647bd0c55ba39948d308000311d00ebedd89457f40c482d43616ae203322577ad00320a78beb707e00602e7e2a78fdff44d2785f665864c752e9baa744b0b717d4f39083e393498d5fc5d5137617b251f135a792cf1538c8114d20e5ffe90a9955e9903cc2a1182faf69702d5d0eb2a3ac119ec6fd00ad6bcaefd2c1a975b00fb5004068afc023901f8a968248deb99cec8a1d00d457eb5232f7cc58d4432da1c6c930a4def75a5b6850c1eb02b133a6c74dc07d81995c45120ef6cb09cc4842fdbaf0d4043e912a7e9c6d8d8aaa44358efdb8f5ef0d440599b02271cf8259d518e490a178aa3fea33f6487f8bf19b8754d28d9188c104a0b537d546ecd2970a9a70805ebf353a68c761acaa7a7382abd45675d8ee1e3ea2ef18410cb690a94067ba804a2f752adef8c7887bb10128755eda3ee220fbeb54f46dd17c0b0a4d22067d7024393fc9af0ae196f660d9bb91b2235b88606a8d2663d5c2393f785de1dec5204744fd9d0efa7d2807912dd2178103353116954d9a84683e660b9e4dad076590fd6dfd45c9bf67a3bb8f768caaa66755103e7a14ea32ca2ad47449e01ba98c6030834a5ea66ac038aa6f97f1af2978c9c6e167d99ceecf6d03960eb16040b910eb83e84062eefbf3983d775eddad5fc7cd18d60cc146c7439c86f186d950b060e83fa8f838cc0f37cdc964e364bfc78b73492fbc6e599033a745558a27ffd2b061bb9dca3fd448bc00e37df84b03548bbb774c0b4fbf877a3c3b7cec2c0013804 +generate_ring_signature 80e43999bc762b25fa9d83c6fd111032ce5582d573d6f0f3e82e0f989fb6b8cb 1437aa8974c08719cc58a5334921c3201e9f45a5290f2581b26345a659b86475 17 40584e3d53899817ece3a763d73fbd5d5a09cd75ff713d3e06c3eba2fc853319 e4b87de4b1b936bf74e0bf1aef738e47297e65f2df50c566a9d5177c75917534 98449fead3b69ec5ab2d9f524ce8aa5e6d84f14917b3b03575aad4d4c291a634 23619e368d268b186bef7a5fa0165c31ad8a3bf4b0220bc262f484067d9ad4c7 06268863803442caa2e603b4791a097a8f33c45683ef55befb3c0d7e3055c36a 61ae5b158be8ad2e489dd7b0b78da17166a97f09629f96342e8712788c1dfc0b 4852fd68ec5cd1231f48b79a8bca21277e347d39af3349bce848312452874d59 5446a777840c6f3f75aaf437d1f84addbd22b5d5c848ffc3b7fe16e1157e4819 29984210fb9b7462a3cc598bfcfaed8a0d704d02851f1ea7d3e7e3cb8d73d3fe 93d4243ca3db959b7f3d7af72a0bc85e27226d1c716dcbe1c5b3743ef5c289ff 7efab8e221de5b67335eb804564b60b5be37ea20497329bceae89822d9e530fa fa084a1bf2c317822a31681302722b4a8001fa2aa9a0190e45b68346298b9aa7 bc15f7855be9e63f35567ed80b629c270a1cb1de56ed670714645261edd0acb9 17749387d62c8c3f725f1acd5b44c955bd4b35ece33bb5b3fb121ae52dd07750 7b83783748d179d74bf5f8a177a8e400ff4783ba1a24b7966d99b587f6e4210f 235b414cf437b43c611267566496a834045ba01b3f16c7b83a838aedb35e5863 0e326a30399705ca5c7fc10ba5f072fe06656388cbbf8f2417032c6d3e1f1519 0be7d9b1884397738bd4495a62ef77233f1b262363539f6bc3834b3430c84408 2 01a14d4bb61696da5d5e4e6f5557cf6f0049ef4af152477d630226da11dd0101f736e1a7507fe045e5cf71b4ab749da4b9a88982716441f33f2a1b2ad286640a2acfa1e05244be97251e9e01da118edd4258a1d57e35b06ec83a02b7293e4a0c6d3a8e7b1191a5786ad83c068a3996c937d5ebfa236b9bb75b0a5408a61e160ee89fe7f15ac9341205aa2d22a6115fc621548c92c35d64946125a945be7d300f2556116cc4f7bc3498f3bb5e54c95970a573d75a70b865215e21f9625c53f604b25d6cd86fe8556607f55e4f63292b5e63de758094ddbd4e119cb1baff0776034b0e8ca5ee48b4dabd9c06d89ca726382868180b0960a96b974c4acdfec55e0e3a895d58eb158543b5f70c30a07f4cf1933e498edd6f1594bcc7f269cd2b670526f5cad7cda88db8dce8629d8b03059f44946aca76a2b8aad3ff50547f97aa0301ebb366b542e75cac85550a01edc5d9f124b87b65a26928b7237529c270b809b93d85eeea3393abef724784b8307d8f71e5d11d5d57c1fe67f65f507eccaa063bd1c7509f618d6dbeaf3b697188402db41b353736b0761d08d88d883a2f0b090bf2d6f121f9d28b4d616d6ac91e28c4edb6877f5fc5557294056784a798230f3cb06fa88ce1d814ab01fc5b8c67160b1cf4a4e1ac45a169e3889798e36f750a4c390ab3aa66299a3714fa0b8a91901ed65c701580398186d7ce24ae1354290c8f397c93a409beab93e6091dd842f454ee3e62cbdfcc29492bb503eccb2a1c0c885bf070d23238ec149c2daf3c5be9a9991a9ba255ee891799743f394f93520b2d20498495f8c3b5069d904914429b35c416057b71ffa2bade0b6f81e3beb40bb54a716ccf419c65d20fdf51eee71415e68ef134d1b7315b2ee62dc770229408d3db59c0e6c2c9efb19da96bd7f84c7fcc703388835911e2083e29accb9c8305ba311334ee6761e3b92a399dbdc882af86497e5e9e9d80bf00f6bcf53ea21208f7dc2ddfe35d3fdd46517cf64dbf149f5ef2d02cac8bbc5f43b8fb3cde77c20553732322ed3db3e4686b1c57a1b900a7e7a3e3af6c4c0e907f2274df6343b80a7f6988670bc7a0a8f0675eb99a89d861d8834c6bdf28abf44ef694d549e239041ea31c10ba19b0369a11f61fb839f328a39b9fd833f64d740e74241f4db4850f22382cdc8654fa088d55ee6b62ed8023dc363aeac53e95653d6fb9434e27ef0f275db1298d0d11fd767ca64b9919273b075dd4e15a109465ed413ea59a6cdc0948c46562055cfd7e6acd121b63fea957186f778c8ec1eb0bc12ca80ec318330ee996963b34a4646e82a38437af659a18d0c19cfaaaf5e119cb1dc50f21f3b700822986d743b03cbb34a36ce09178976ab9cfe8c12b26e2f0336f07edf471de00d25d772c234c55be41166c12d83a4b51aaab4b3ab77b54ddeeff4b68b003fc08337395a34260b92f7656e6208524b1217bff180f25e8eabb136f0b1e51d4e605d298558b39c34ea22f04654a158527ef85889d7a9d41551d8639ec5eafae5e08 +generate_ring_signature a1cae1149c356e23100ecd1987c21504dfd7eb93e828bd3e67010b2618b67d12 41ef904648e97ded7bb6cdb675c0eb7c3e265920e0ed3a43f6d9d52b9cac4950 4 8af0cd069e8ed1cd5b5210d4f3b1234fba3701a51f71223a642afc1ab7c2ccf8 68a106230168fb6b767c70b9bc50adae625609a4deaa23607eb431a125d62acd 7f77b78b984a927a28d64f19feb63bab35f545c419003dc6804fcbbd0a6a7d89 02e2ec9fbcd3da1d36c4426320a0ae5dded7b03e360e801c842d6da1479119fe 9bc45f2111dce6e47ce84bce74bdb15374994ccfdcc33c497c8c6d02621cc402 2 796345c40c31b7c28da1b765be18d5599137915fecef65eaca9c7c4c78c50b077836cecb6c522209d310a0c07f170b09c642f951325adb402d595e53d73f5e0748ba180db3b070039fa090302f73271b2dfe937180327ed3b1405ac9df198104dda7f8c8ea6f31b3e92eee292451a9a5dfe3af2703580707221a9ff8291a220881febe9d0f91d9e7b421f2e278b8ba89275cb7ae5f7855287cfdd49fdb0a9704a6998a766f27586c40504c4b318ac90cf42d73fcaa731a9ea34a7ae61418900a8a6a7dbf27512441a5999d362b628e634fd3febc7fc5eb862122aeb1ac6bfa080ea30c00eb18d5c047656bc3a796ced004759f1ad04f1973901b10cf4ef4490f +generate_ring_signature a4a40107ca42f136d1a311b9dba01b70ab6e9b488c9d4bb1f82137a8de045b0a afaa82207be08f51be6d9e58d2029c812fca1215e9a4c9ce7614fa9b1ead0e33 1 21eb68d3bc8a11f481c4dd1aa33a7eb137bc0266faa99ad02035de1940e96ba9 4fbd33282caac0fb0207af80c006ae9da1993618bf7f2eff764426fd0fe7f204 0 8b3618108d922e7d6d2d3640d58230d1bf725bddc7bf107711e16ebb8f89160d5d4d5758542a5fc57892f704dc6b4b927e2e0af722e6ab04d600cc9b6e517e0d +generate_ring_signature 856142e92819b975d12e0fe26c75ae88da078d345246b985f3d2ee7b2c2f7c5f a7869efbf3517f7b3217cc10c8d34aa79dffcbcc332863aeb9dab30c14f2c216 4 c2fe2e312d4d1b483105304f0790bd832bc2bb194157b215d265ff8f1fe5688b b6db213bdac6431e7a58bcd7bcad322ac7dc04a2ac609b2e2c1942aaa2acbe7b a9a365b5196b89e4ead8efe752dec4900446c49a93fcaf75c6e01d6155adaab7 ecbc8dbe05d49b8c9ab8538a959747d3c965abe9bcdb090829e109aa9af410bc 4ab503c0deb81e5867cb8acfe683c713eecdeb27bb51b5cabe78fc3d287ad507 3 58001d1592f13fa33037e4bc22ecf72a2970db98d1e8d82722f1d443c2501f0e4f423eb7767c41cf4e1bd34bf17a1440d6ac28053b8b0df157aba27547b94d02e0b288abf2efa8b4348025fb47e1fcff1fda0cab0d6eee78607b7fc25ee93d0fa96a93fe64890827b8c31d267027aedcb2a9747285aa83eef4d557ddc1ba93011ad0823ce50a6ab1906b1c2797fc7cf576736b3ee7b918544535c0679c656c0d182a693681682afc8f7b34f9c3f2b681a61437b2435cb89d1fbd264ecaa8140555a82893d0857a97b81b5581c722763b1398ff8f9d8f153020d179a1a8c78a0bab7281b56141fc77ef8109aed5aa8cde7bcb698e317c8e945ed245f86e172802 +generate_ring_signature d43a0443d5c3325225fa5986febb44adbda0422c3198fefc5c6f004c12eac890 48a03abbc676e7c1e6595e7871d3e47c65756783745b6c83beb3966c83b24426 7 54c73df736d858d956c6ecc78f71bfa621f1668529798aae794a2ebcc0cfe8a3 48f1b704c8549362e4bd701890d49bbc96f029f5b51740cd9af23be3c8e330f8 34d8123aa5765ff6fab0fc962b525c8ae0bce152a59c8336155f62b5f8261ca3 82f6e242df725fa43241d94c88c371eff160c9bca40e27c1ccdfd5465f8d1195 75ea08cb3c88c0dff75d744fe587524a5b3cb012c2f4e7299673dd24a07cd85d 8a3935e33e50f5f9ff79a529f18ed5c88340893bb688622625bf7007e15d5fe5 3261bc8eac8e3f468997a2bcded49c910fdf5b97056bdb5e81535665a23cd13f 55cd53ed388daa9179037a611a241494ad182883ba0fa337a9d6608a6f554309 2 b132af9651833f08264a742dda198646c69fce8c133a70c1846bb1a3f8e10803a07b25e8ef629b1216aa3e2e188daaf8a7a00e7375b4c12aa8607d73222272025a1facc8bc5e1112e42f836c8c9306e2d90f98ade556f4f321a7774dbf68620b6d0c72b20732f83ec7a355a4510508ff5ac223a87c193ae2598f53eceb0eef07260f6773c777bb10c6ef9f3e20017ae99520192733b399cb884773dd7dcf3b09fea3e961efee6502c887bd2430de22b87ca1aac863ab9eb048b4bc11bf71f3075b20c6787939d349627a821fb78aa4e51f4858434c15d9d2e82fdaba90bf820eea738ceaf81093afd3ad7d1ca9a9d7e940741c8497b5f174c8c28e490987970580842bcb73c62e0b98695d43d6c877ba243cc8e13be27224f46b457d18770508e2893c030f58c0aba39f192bdb04885f8f7b28f84ccff9d774e14944e40ea60d5ce1e4c48ec8c425fd377331ee7c495585ccfa993d598da0639d597194aba207891ca46b7f5994f5c4a6a067c76bad2f3ace342a3de56c99a58218699e41580ce9bcb060b69561c29bdb39ac0a32c2ac38547b36c1605380cad8e584c28d0b054c1e110d0c9ed87410151da57a5865806828386ea8401f84f1e864ca80d2d607 +generate_ring_signature b2a6d43314f32e184b6224f1d237368213d205e110a06eab248d8ce14dc66b35 589f05748c0e2fe74f2d93e8bf91c6dd062456acad1a8c440151142a36e37366 5 d1015e1ee08e69977d25d7e23692136b840a702afaa2ca04c7a1ff3d844ebcd8 bbde63dda3a37b486f0f12757b2e5a560d47a041f4bbba732ecf55846ef97288 839a000be768e6908d46ee701b19eebc912e346f98cc523c2d8ae63caf9c6c57 10191593db747ecf070bf88ee12a5f8c16f8ef506c6f5caac4fc0e0d0dd2b6d3 446c82636100dabcd3fd93bd36eecd42dc10ded9be9b37fd1c868ded993a8bd0 c188a0b57f2c52f5ab7ad0e98f85d05d317a631d20a45f2ff8d65e4dd9d00f09 4 67f6fd35d9965b2e5498a282606b90e0f07305a94753a919fabc1e12376ff204b155f53c6b4aa36fdf67ad2c306b1e1e7c109f9c521f25545ac6af4e1336ee091e7ce65b3f281c57294a76caee5280283c98429ba6191e6dcc3cc7b0870b9f0ad76748877be793830ae2a96c8ea1d4a2ae74556e0d692498b296533d4cd27404fd67a698fc96c43eb7d40eaa3787f3897466945ce1ab3a825a9c45e40a783003a5cdd368a6879e842982403b9988881c3b1b0201def49e6699f98d9be55e4105c2c879c99f93da90caf1f004d30f20fff6af22273ccf4f03f9aabec9042db802e0774ce4695d25c33e1b4ba73dc91bae60fa77dbf524c25904bdfafff210a20e36ac00388a75eb42a777f0476d8a23d49866547dbfce1c6eebb9ab59d22b900079fe2ab9940a33b0e071c8f2a43ab902a56e4726fbf3c84ec72bdf41b107e10f +generate_ring_signature 2cc6d7e8e09924db18a5cb8454d9d4651e68b7c40c10f2124c4178819c166731 8a63ba236ee52e329eb0cec80e8281fec17a4553aacee39d386e7023e8c49f1f 211 402a41ca99cd815d081c2481ea92da40524a3c0d1115380d080643fa3d9b0261 c643929caa547433cd00d1e0cd02b77e37f5de0bd28fd21018040431e47ceac9 989a1efbfa052314e3f222b0d6a1870ad23a7759208790c4fe0dfe84f9a682dd 28478f7385c01c31b55f667e04f71eaafc7615d65f818155e4da35a160cc4d85 94a4beeecbef6b573e9fd9b3e959fe53b47de4d0da7b9030066e8ffbb31357da 090eb96dfb16bdeed9a02046eff14c0b3da54c8d93d4708d336ad86355ba116f 7b77baa8eac66b27d8c3a7b0156fcd94d958be2551351438d075b91b63c33a53 a58ed775d98bc67e07945599536d3d2b4cc06cc37e4f230396218bfae0fb1c44 29320ad589c514098a8ec72b9349f0940737f2bfa36e9330f2d42c00a0120386 3a9a27201c7bb4bccef5dc6806d040c30a8230d34eec0d685a6c4e40751f49a0 13f2730c4bf1c2b5a9d35cbefc51d4f74de8ca3271033c7c4a9d0944dde08c1f 73872a978fb3ec59c4f7f86f5c008cd9ee9f54736b180ec968930983176bb464 a657bf78310f970b68ee552e2bda5ebe5da601b5245d2454a30c0c276ec18efc 5ec07e85ab34bcac5d5172a700868c29b9ccbfaad9858276df0f2eb75e142996 9af36317b0c92e94bf9f88b3cb32eac5e2022d67c5843fd761328eb8d2f85783 65631374959a3b4b0fa5538d510a13edd1f616c1a7b304f1916004695dea5eb2 3ec33d71054ad6db9e4c10680d2dd4dccaa408e8796ad3f04f63e6fb6c9436c5 eb7fcde5107a6e168a6bc7bfd51604c60aacf0ffbc41c4ee9f004eec92a441d5 4d6264610c118362726519f09cc02b1dadc926ad5d3a1d334d3203c42a7eaa9f 0053001c4a77bbf3aebd3956aac9b8420bc67d84947128c32d651d78634f2890 98c403100bc3d1135388a8899718c67ae72d86fbe32bf4ad6430eb0e5a871f59 1f0f066060620f72fc27072fb04d111d7890db94da780753c565114b28fc61d6 c7bc71f7658a142c8c2f32112d5f2fa2bda5140632b577c4ded16dc0e0324bc0 e1d43f558301785c73f060139a114b59ba8260645d3a42256fa1554b50d7d1e2 92b26634220d7b331cf050d947fc8610d91f129412b01c29969001e7eaa9b770 a6db9435005617130ddcfbacd5f432cd688054c7bbd5d6c74e35a6b87b36fcbb 8fab60e3f2b22ee77a896e2f244f683e0215baa6c22124227548473e8226ea42 231600af4603f92dceee9d17187e0218993f6f60a91205a361a63a1edd23f31d 41065d0f4a7c7bc1e0e1921ae8db77c6e8bc58ed6eea0cfcbcd8ed75b7a657e9 83db2a59e355af551f2385866b1479993bbf3297877032f14a53893db3c0eacc 1f286383aa01569fb3cee63a35dd32f41c575261cb68afbbb832b3c4eb9135d8 14157b52262d16b5b2b03e0bfb051211b111776d2a777872dfae2a1f3dfbf780 8b499e0ded8c18e93b012b857352ca03f7c53d19a7b662b45bd6f0ce0fea230f be7c42646fbf9d17dc2c09924595162813a1cd92b41ca029465240f105ff498d 5bcc54cfc168b31f99d15c2e23cbbb33889107430b86dbedae47393121c7e575 9115043833cbe33d775d09472a193354f00cca070b86e2f2c55a3c587ecdefaf 62dae9a21077417d38636f9766d2b23e8f31c11d371b941600a68123a0e5852b 2f880dd8a7785fb4f6584ca858b7a9df171393eb1dbb997e049c3c74bd5c28ad 36f51e55611ed2b0ad671bc3b5a67dc32e9424baa52b7dcfa886fd16e32a4a92 cb88c24731f1c01341bb16711cccf0262711c5d538b5ee3d91e618a0aa94ae57 774ee3b25c731b1563ab1a4023808d1083f4d019438eae312a071e0963320b73 80f340dcd9f0edfa672adf1028fbe5e7933a5f412609062951c9c13984477c1f 846e5bb742c7d2c5e540a41b112dc6743c145a76dac105de39dfec0c03804934 6c3731202f8f8da0d540616f32fb1261187b0d5dbb8f4f86e36324adb50379c6 304c36bc24065978e078b24b16bf8811bece463f53926d8bf4cf14141a8accae 6e39e3ac724c929ed1fe8d2a1bba08b81b757f32ee119a07f8feb66c990cb484 2fe3718912375419fde8d55acc1e9f7ae8f3e8e4f7e8c253f180967ce9f6e277 1422514f9fd55ec628162935e2736205f7b19562e10f09a24b671fd3d363e807 ba7c20056d4c14ffd0f93dda7c39233f2b9f005dcff265a9ec774d54a16f21c6 4e024cfd9598522249b0940e0a532f8a2e460a06db24702c8503a7b88d8ba9a4 8bb41c4698f0c4e1afe52d5110012d704e063471ae568e4ec407fd6a7f97f179 1e5665d9af4551c32f5b41cb376f6ec70dea9a3b7c8568a8ce24c525ab1cc65b bd2af664fa7374d46ed3a2d6de4295b2b6d6d241af3df086abe5b9ee7765c8bf b598e6304c34c0a3158998db4877c8025e27de6ea53305f445f774a7235c60b2 7817004add781de4c2bb6afdcbcc88165a8620994a27e96e822c8b599cf9181d 402afa1c572a3e19f68ec8dd5c3f2ad4af9ec3dd0685019da41b208fe624dfd4 e1ff43e5787e2832904d4f55ccc3f24a896a673b5841cfb82590ca8889074818 2b8afb146c7f80094e3201010ff0f6c0503d4c916219e7f08523b6eaabac0627 671fac59f003840250f4070a05f89d73abbfefa4f105bfd8f85f377db6409f70 bd10a4554ebcf405fad8a7371ea2aff0589d0c554e83dda524a04663a7d3d694 81c03045a55f1c812b2280e0cb4fb6e122466d47ec60e10975eca58ab9a13d1b 1b3dae6b495af9875c3705bf1ea6695e7bdaf39c20947e061eaeb820026e9920 d89c734cb3226910d0ce056da4cae31648f5f7689f4879cb440afe2b783cc92d dfe58bd956769ab6129bc2966895f3eecf98d596a15b90dce4d41fda89f51908 90b7690e81a72de5b64b94be37faf4cf2e053c0560786cd3832ac0a887b6c2a0 97f5440f4fd3fe8928b1da92089fa2f2a2cfa22ee836e84bfe6f0f0ac2c0b639 78733374ee6577eb4aa1fe1dbe30fc49a26ca6709515f9fb9ca30ecec256e525 0cc4bceca6c04f76c8cb0579cf41869b523ed6dcbd0a7cca939040b113c5ecb1 a77eb08d2f61991f1c5d2d5c17ecff62b6f355f2c184586458aaf6f8fe1b0c47 e904d9ccc3b5d0727786b623997e85477572f374a157dea7a2ec15ac0b8cbd5b 529a15c0030b5ef91a2b172d050ee093b6a008726a5f30b4ada8e51272c89e61 e484b6e14d164bde5bdf5e11ea0360f4b3751add6dcb86e0609060903db9508c 678782c7d1fec628538b8bb22e04867e1cd37b82fc3bd27af6376049edd52027 7b75224203be14b0d9648feb66944b90a538a38977dc9def8515fae3d3b65446 471cfb7f41e6716e40f1e43fd3bf60619bb61cfe9647bae7bdcf159c6c011b6f 9a9abab7e9ba931b3e07d8b5f2a6b367e83b7fd27b876efdc15ab64c56bb3e99 3907d8e20f2cbdcb064d0f0b5a9cc39869aca703fea645e487ae7569fca87229 46a2823791014ddc54c9d56e45f469871e4f14f33443f7dc337d5910beb1aa19 b30317411d74a37484df3768877d0e92b5522e5622cdeb19db037688633a764c d63f7433d699967d4dea7f0353aa6d83a1db6688bcf05eac535d806f2861136b 05e06df4e9ab60de679307e3b12231ef37c0a7e8bdcdbeb792a140e0236486ad 543583fa163484a44a43267e2ba34db90e9ed2cc570b7a25c0e45b22b9ca1eac ca42a5c54f83e796076e644a436af8565132ddc1d075b95ed355c7f2b0b556b3 f3f5efe8d35449192c8795d2cb1059b720d0e1044a3ca69b1f57962fc819d56a 89bfa2c9258aa739d4fdbc65fd3b6f0a544d9cf4b22de25be25b036e9d9ab2a2 092f55c0c3bc3a275c4ac457c0b15d676c8d5b2a072472b624f1874fbef6c372 11595707e8ea5783c592db350724d7463f8cc141fcbc60a9863ff890d783131e a381570de73bc10fb7f4b4ea3876d21bde840c0cd5aaed2c2521cebbff77d258 c629d6bfd1ea0dcdd46444c5a560a4f386735c7e1dfba644e119da62637e6edf 4605ed8bc6ad9c8734a4f9fa61964edb5b73f1746b568a3525b088b7e4e28738 d2bd09313210ff4eb285b2c1171af27b1f7d3a14cdd78da5d36d5df33821097e ddecb9ee20cc01e3e00884943e5b284088589501ac73c033648430b6403bb0bd f983fa409d58a694b709658f79f488051a5a3627a1f5d3d8ab4f29b88ec85591 11b78bd153835d415546c093859342a069c2f9179fd77487ddd724441f8a1d00 a1be919083bb6e1f0e9ec941588f3ff0cc80bef966f32c1e57fe51f9d740ece1 c5c5a8d4f9a3c212c8ab2cb9bea0fe4a2d1b28ef78d0d92948ae2bc58d879924 2ba7ee31adfff772224a6915cc1026733d9750ed78b0a6003090d01b5e4800c7 f31856d475a6d9e542a8c52940e65ae76aaf239c58c7af445011118479ba2e97 d8ee080399b781b97e9e320be1efed8826ab3332ccdac22c412b96b587e49f3e 046b156f6016b3e8c4e28ec46e6a894a14bd085fb98d272f954646aa6a68cd8f 67da4100ca141d0b335ce9aa673c8ccb1c241d54e8e2d33cefd70fceb5b1d25f 93bf5b1c7a6ea142589637ede192df057328a7ff99325e8d143f5933e0e8d094 2013b7002841ce5b4c162f543ce204e55ca37c290241703cd444638b7e1956e6 e1fb9f7f35c2ce2f064db2652a494fc4132d67f1435d2c422651282e2d5936be 6b84444a3fc1f4ed71f07fe9807aeedc3d765e86a308cbddb549e41a07637540 6922d129dffb6f2e7e05e25d67a675deacf4a3eb7591cb8f411b4bb02fb352fd 807fa83b273eca0d0cdc181b9839f806164eac0da439354f27bd4c999fa3e112 ddea38959723583da1265d5bbbc23fd21d95912ab44ab7bdd388b8f816d7c950 d31e177c298fe21d24cda414ce09ab970fe07a16247afc1931831858f682913f bf212d78a9d4b8141c0e1e03b553c0be1bdfeb5b17cf2b9b109a1dd2f08fdc19 07bbe8caa6552571cd4fd46f165a89c5eca829e04ababadc29fc862625ef3415 43339e682fea6b57b40f7c199386f392488077429cb491f0380d649a87324411 46c1cd36c1efec4e065c8e64700fa8e225fdee7e7b5d0455184acb459785e924 09ea83b1d7d5a7b580b54e8e95f3204374bae8ed92e1271a8573d9d72baab4a1 8a7700e99533fcbbf456c9b22d519a25f1f5bc3099c71aabefee801277d0c19d 909b328ce25f2e5f270ed63fe45b43d242c03c3f74f3ff6001978ebeb418cc61 f8e3cf614e7bbee6985e1d5604dba2374630bbdb9651e91dcdad5ab53409630d d6052da08cf10157fb2a2e3b44c85cf76df325fc919c588086972c6bbfe193af 9a3b931fd12fd1f0d68fd76d68e44ac2de9f0d82fa476f50f0dacafcbc38dbf6 f07f3e41a4f7f79500cebf1b351ac5cf8346b068ab1cbef602fd60136b20cb6b 15f00a7af5e20b918db78299f63ab9ff993ffd9b9c3e50d32b89d8d68f1cb6ea 0402a24ffea45621cb1916265651c80c570a55e8ef7aa8577afbe2b15f3560ab 0ca97cc9867b2edec0d46d9d0fd14071c4c904025fd0c5ceaa5b13391a7303c9 755f312086e70719cf72de5564ccdb28288ac1fea0f41611f5437754cbbb360c 4f865ab94b9747b5219e5b62f06c8acd434b8ba71f9a49656bafef74e0fbe000 eacabe372936f28985b08db8fb4c2f8c9b4a48c261d698e77ecae3c3232c69ba 66e7c6a7231b1d3fa2771babe3dbbd42f1d32cf5f80e8112dc65ac08ea630c05 826d230e93e779a6e5d9ba481cead54668b91f7934e5a47f6d2067356d88a432 38d8c90a333e211e35d18433fc8e97a2912a4481a31007dcc3cfd7d02d58e445 b89ce70d879d1748dc572e179124da2922b52a9561c4e5d4ef787e65c3092bc3 dcd03083e2edc956b86afac0b6b72eccf61a96c0b9b1d8c49ed5fead44c22164 0b3b6bc0b8dd2aa42ab1909e31585da82da55ace9c06a9075120bb1584c4e65a bd7ded926e2626afadb1ba4c6a6484b02fbb328965bee31607f24c1f11cf35bb 1b822414e321327b717a8b73a68759528b22454ae4f1efbbea4acf27553bc7b7 6fd47667514ba98fb485a526bfd3eabb680eec1e6f6ee9b0ea242f051dfcb62f 10eaafcf82fb0ed3f7ac45f994eebacf1794bc7b484c3bcf1d4385534a7ac8cd 2f874b03e03e634e4afd81c541ec6061d956fdffa59940360b6be44ba08baa39 415a29f704999c6a1d57de28f50b6c8a28aa3a45e0f090971f0350169cf10442 65cc454756fe9f0afcacd7ebf5ecef668966b8d0a689ee9f8a80a0d672662d93 ae853a35374a5f088e4811ce400ca24b7292209f5591fb286a840f811a1a3a4c 13fce6e2bbc79ebe247e21edb3221333aea417be828cbf7dec641711cd009c0e d0d1c7e0df37e6dff7fca30ed034b174b6395667162b7ec2f81922433700006b 11700c2375553b574770775e7ecf74d356024c6cdb73a12040f899b072febab7 9f2045dfcf371ec181d645514a7200019f6917be67e5b29b27a690fdf434720e 9211009b28ae0d38739fda0cbc46242b9c091dc864e3849463f7d5cb6eb4224e acf85b5927f99c616e7f0119c2635f9e56689f1cf771e94c29d2bc6af30e3b73 fd8889f59b8fdd47277bea541ef26a7861a890898a15fa55f19df6eaac438054 dc0db4e6550ec7cd5ce876416f54c3bc59447b83c02415fae918adea6df7a4f1 29f5752cd58eb91887c95c38cd3691a9b404c99c5022e3e644947c58a62405a5 90d99d090249b1fb30482224f3c6d3dbc285c8a2f35a417a1a4559479a5af592 81c3b1b54dce4e4bea68f2cf57d5d10c6eaa396eb66880590a9d68409ee96e3e 8e78d814062170b9da0f2df53876e50d658e8abf5175be44f1a847b25456adc8 5c8e9a46ff66124cb418455a16ae3b78eded90d8d0e6b87f69e0d2dae684553b bd3bd4c32d490375d0652524597c89eb2a8dcda40278e9e17eaa0895fcf3cd63 37d269d95abc4010b6dbb4a1f13b0081701a625fb496a554ef50fa790503a0ae 069716673161003f4f4e03e91e61e4c35307be3285e9b9f4f96fc87d9256a112 3bf47bfecfcb4f13b54c8a5388623355fff92f4e991b1439ef4bd2c04c25abd6 8322ec655d08bd2297a67c7d218f22caa679139679f03a0bab4c0c07e74f5a59 4c7ffce48eeb64c719286644bd4dc84a6ca8a09976cec4365ed8a9f1e52020c3 1e66c12636713e73ad0661b537ec450f53bef1f34c814f53c780068c3cee944b 3606237da7504cdb79140ae14dac5e9970763a3c9f4a7d74a3721c93c7e1431f 1fa3ee9449761613dd39dd33e274e6d86709e83d747edc926b115659fab77121 14c7b97c2462aa3bec7a691242367004906e2b2daeed42dd2ea8c0aac75dbed4 70c011309fac84d7b2e71fa0702b49b21fbfd75204605c5bacc0c74dc5e8dc33 189ee51670246ce6697a111207191553afd5580f11cdf6859746993754e7ff80 1131c9a3307f39ca82c6232e5852e4461d0ef37afdecfa26b5022a93a7e5abff 9b130da9fae53bc05605bd8b9b7a015713699c5be1f02227a9c74da3db31a018 2ae654a588871677c065d03dd1d1d4232e1fb67b191a32573926c62d70ac7b34 a1a6f173a6aebf9df3f322eeb425a596e71bfbd8b75148232328b593059397b9 deb8c6156bb9b1cdaddcdcd83b0286e746c59d2888dbfefcf77e5fe1cfcd72e3 d007cf856dad279f734fb20b0e5c97839ac2ed18a607f8581b43fc5b0dd076c8 990073943718cc401ddb885dd082049c0168da46cb6568a56a4b287c9d959fa1 dd5c9a93ea17ec7174a091e41d91f3a03666ebd3411e5ea74938ca33b05dc162 c182c5d4f1d8be0d7a5f1b6ee8d126b397fc5d7fb52dd58b0f42f9b1d65e5d55 7adaeb0744f933f647464c92a39bf738067f6e1b4b996b4f2919289f2fa5ce9a f9adbfd726b517b55912e28c83f19d182b8df969ad4b12347131fbd7e0a8a2ee 0073fe5086e6319f79cb9243f359519f00da4d3be8855fa79f4233f8a50c5874 a6c4da072b6da74e25de82ee19976195b8483fa6a054856792d89b1e1f68ee44 d5f638f1b8eaea5e2da06bb90bdd5466830f036e6093df3bf23d03145d315529 1483358755a29f66d238dde5e62a125d50f6d22ce820553e207172859000a96c 72e77707ee4d52fd0ccfa34c57ed5d2339a69f39e6aa6f371080a3d414e25505 b7e9e15b52f4402ca9fe210563a213e1dba8bd02d0da57440a03a98980550a80 4b1480c24c531e5bee169e7ce570d89ecb0f0c7b3d041fd93f04abd1ca8bdae5 682b6bfc350ad26c92b229abbf92aa82a3d1c789f124c63c166555f4f960f592 94e2a267bcc92476200aa4d5fd0b3d6fca8f2c6a2c69623a22931b8e9242ea40 8d09501afab7b3142a44a531971cdefe348be311412347c0ed1ff2be5bae723f c6a8695fdc9043bf1a698ee3e2df46bc211ece66e0a5215bc16c8db3c676ae26 fece9504781b2b510ce438143395d3ce8f6ed69dd1179b9615680746b4260b56 7e43c14f5b5b2dbe7e3b37f9726c32a04244507d09cc1056084afbe29b97ea99 feff4768795d67539c95ebd9a89f8482775f595d8ef3852a988ab14fe95f5227 e88d342f5edbee919220c56ce616a548f801da5186ecf00a3fae3ce4eb163fe8 bf8e39152682f122fdf93ec892eda4246911194534a15293badb5e09e3c110a3 6654a6a6b4a0f3111b9c1bc051403c3d0a519a5721718e370190d833f63a8b88 a05d4624f0b50a2d8cbd071ad862012b3b01e98b69969f9e5d17b7660396eb4c 4bc3d8c6921685728332e49f6f4ceecb659504966c1d3bc49e57a79422c1e35e 3c497afa0fefe3026683a39fb701024d7ba204a2077ec0daf03d6bb1ba9ec005 3034c04416c57bedd19c75e57f79e9330bca3456c43418e5a6bf002d969b425c 5aab8831da8f0c192081f901a62c8768ea530c96a3b249aa9cd0cc83d404eaf6 ec54beb7e480aa22d6fd6f0c785e45c7f2a191bafdfab0bb07d5b48f092d9c5f 9839537dc7da3a8141b41c159b91c769d0cf2ba6e68b94217c602ebdbfc6a599 ed86db43e4a4868efa115d887acf04af9da75527a4fcd3c6244b6c4d61be22cb 8c507a0484046c536423e8d9af4e35f74ab7d30e0f3d41378b95da880febd57e ffd1a7b87836064b4247e77e6d4e88e944ab3aeea5c6e069161227e0d540482a 038230489f2a54958eba36e8609ead2529e3932f8b89c4204fc21ad19920adc1 ef2b4e6713f76a01478aa2d01d3caa45467de753c810df2f9b61caf0a526b699 abbdf138313206132f30d3c3376318e3c2a1754d95ea64e14b22e60d8dd8af54 5d3dae9e4dd24dff168fcbe2b21ff0313df82a1180b7d7aa0cd4aa1d9584bb5f 1df861a9b7b185f0eaff1c005d7c2bb89fed2ebe0f32f478d2f345bd678b49b5 829a61bcd2a3ad8a8d419c5c8b7fc26f2d13428fd97b7c54d6f888255640762e e6fe97cc23d26246af4db30b1860072a4841915bea8e575ddc5d7739a6b96954 7e5dde760460e9b910e216540728b4ccfd67182c070c6ec2afff9d1bcd0674c9 cce6c582a6b4d913727ed464544472bf199cabdd81769de5009814887650660d 170 5fda7276bffe02f353d71d6362085e3d537b8bc068d8d6857d2b3cdbe0feb9036c97fd04a9047927e652a7759ba47e518c527ad8660ba9a5a3deab787e1a6a0022765a4a0645d610b6d7b7ffbc165c39189f92d160345b2250b657ebd5d7810dba07b24e98aa686c455d96b35d7df3883bb4befbe54e8d512600052f7062fd014e0f925af398c80d8ab546c8c144f40d8f6e4225ff13609d0d95f1ab7db8580f6785f5562ac2c50d8fa5153c3e151c46952adf2027fdee5bbc378642efd0790f403292110b08702f9495037099dfacf8378301df774ae05b16e29c37a606d20d91699a92fe43e1ea98614ba322db6376e183cd772112f41bfc616da7b5a8ae0345487ba93cbd8cd70e4991486634eb4033e06769be384223ce423f2dfabcb8046b6526a18d3fad7866bd596a389ffaa41859f65f92f73f882c77b3037aaa16070aa6a4532d034356090206306fe901645c5d779ca039645f7ab61908be7d9d082bac632faf9d769705c528d02af6b67ee1a36b15f12c5778a49c37735614b00039d8e5e29b4c411dff1ae7d0a92a60fe069e84ae4583a5099103768b82c80f02e264ed40e4d965cdaa9af657a8b5be12975c453cd9db34f0aaf434fdc170ae03c73df3fa30ce5847ca5c44b5d67997e3deaf0fb1ba9fc5acc0b1acb685600d0b1dd56bf8bff45af73fee3540a57a55830e3e7aa63f450b11f9b5421ffbf0af0d62e5f7904e585485f939f8fd99fbc93ba3ea0555ee2880b5379741f166cd800f7d4cb49847f030c49b0876f04003ce065442df33f687cc6fbdf82310e6d08a0fea04dac85fa056c299547df83280d996309ee2420fe199510c346a3850e79b01f6ee83abd38802bcdd6a7e6ae198946fc6d706cab83598f3f84299becfa1e00daafc7f4d96701b59a97645858c802b54256abca1ca596d22f18c9f440fd5d10e542ec3066c2412b7aebd229a9693c2751070d55ff1e248f11966c03ef3c6ee043456f3593f6eb82d1b99c21a73c826ca0570e8a93790c5250cb3935b6b62e00075c09978b2a287b93f30211ff1dc8a06e4d44b240d3676ebe738fb7c498b2a06e61bce59d9c6aa2e90be4cf1e62de6a3d4e329b978eae0284a7bf36228aee903884cb456c866b6ba662d621f153b30fc1fab7527bc8d3f12336f9d4afb6c3e0eae495ed06f2ac43ab52eb144e148ffedaabd544e16bd99d10951172f1b573c0b08d5fa8afca8e3c5a4ee46ca1a9b8f3107a1326e09cca06e83590e63e4b9e70d94d629b1203c54bae9f329105e9eeb447aed1f9ee2466b918bb36039e69d52075a0fe42273b217acfcd403af135c49b585e88bf3a8a984ae22ef4567878aab0e9fbf012e019f54ab863da4430b62ef2c924f2c1fe6be41d86303462e24e2bf092b3638c9d65968d158122b9d6a964a94d4d93e1a4b066f24341c95c5a8a9540b73ccf7b95826840f3dbce8cdbfed75e3ecb3857fbdd3ee13f69a110a96ac280bb52e6fd2500f35e6d619ba24f47a50346efa87a3ee50e97fda50c6003252e10101bea9ed9723b3d5faf71d1a573c5f1f588ea06ee149519d68ab52d8b70124055d056221d9c5c72e8c08375ab3c960ae6820e47ec0cab360b9b98049b8c7cc07a599802a7658fe6ed6527619040db407226db299ee03733be5d92037690cc202f0a828e072a47936ee3ea94b5fdd515e7ad58980b85c79c0338a44cbd52ace018984eda632b3e182c2baa576243ec05f772d07b3623dc54611ed9062f352cd036ec60d28f08380130b90ca023188aa4b3b833612664fb027a9cb69510e698d0457df021827ceb55bdd7c11321f6663264acd85856ed7dda036241e6db096a30ac7d7b0ace5df2e568f9fd56d2d2071ddde4805d2cfc005ecf74d99c5e5ef5b0175a54799f9368c2f4ac6d22352dd6b0ef765f19dbddac7e1864173f70a19680891fe7d839c70444320d0004c0de49f69eb0e19095355d1add6768e0a6ab8bb07d8f9e8c83bb088a182906fd0f0a5fb211f0ff5e578181f0d2a5241a8aab4e30141226e5afe62f7c524df3b447ebd2cd0512eee099da450382c9d46266755cc06ebe0e10980f777c7204b50628b09dbb44d04d2a5066cef4c03830178b2b3f40923fe5a13c683dca11086152475e9e3c78320ca0baef3b20742a15225522fdb004d8e0d330d35e128ef26897f39f49f8b33cfe292209ad6409e6f0bad0a30bf06b5ebf734a0774fd388611125b9e74c2943b5bc33409356c9af1965bbb4ed5008a0232979193615dd2ad14065515f34b77890c28de49cdb2e8642fbf7ac251605438ec69cd43f0161f913de67729f2e5390d84d6606164dd30917ca54b9a84c0efc9bb6254cd6aea48fec1efc9a2335bf6cb232b406e925df5853630fe8d7ef06a75bfc6b9417f76e4d22052655da4b0f177df410310efa14ddd089f904aa8c0c459c0b20d106a92902828c2fa62dd8f44a03de236870f6b2c7c649713607b104d9d83fc4624c793c933a806a5fbdcc49d26094025e09fa63970f436d56bad60f4af3a66c5729237f613fa7947521e66425d4ade98222514c6a373bfef59a0b098a0fb50c7f72116ef28d4d488e4ddc92a66ce2e508954364f2f1107a6ccc2b03c079c461f77a8624a632cd446e65c848ce0dda4e650254155a7622e535ca7d07af089ed739c7482f430981a29ba377b7734465f767c8773bdf5719856c241c00d229d4e42b4f5f780b74412e712de26c63a5c1b88bf09a631fb47aa6e802470db9b3db90666412281b13f42c3447f94d620d016dce157954c331c7c4d777d10b7d3f81375c0e0c8f8635d2a8bed3c93c0828b6b59a0c426a22e1889744e96f0a1a799dfcb662c9bd87e7b51eed8fc0fa28719328843e443ec2f5187ed5e58102dc22a0e0b41e98ce363fda693cd1c0ba1a2aa00b513260ad8943efc6f566cc085ad495aa0dc142edda93a60a7f0eed7e62c46dd0d0f8598f8c14e6f7d3e1a005832b30d50a8dc2cd075aaf50af96a494c077462fdd283e2a8ae7462582ff1f0eccd12217f9d4bff5e99be831d4d21e0a5629ab5b12238d9cb8600f4b101ad80dc4d0d62047fb5986ce9f714a831f39a32b9b90d9aa74276658b5eca31b894905af0c026d4ff041bd351cda99703ac9bcf057a3ed5c4a7c6de834c8f72e60ca0291f8e60efc5db2bd0bc02c47cdb5dca7a0a14d6f5d24650e78dd885dcd4b5c0fa478327ad6e358d54b4e5f6eaa8e7f0ce2d9922e7a1a15b221f6bb9f3174ec0b91e81ecf00d141212b3e51e3b2e8fde71c1e77c3208f2b3681841bb6b87b8a0fb903333460153249e52af97a82270ced5e2f3dea8718d1665ce9e611130faa0c0cc166cf79ce59616237806eff24a9bda63bf2ac5e6d48979623cc736d227608ac09742106f5bc93a9cce7d166260b313da04e19b31bde9c3887a3180206660e6ce6d1c3fc94117196c4c890ac73c6694f9b414a337cfd264aa864d6571aad04ba86c688d497372732be3b6b6e80a1600e9bc70fef1dfb1ad72bc66c077ed60ea9a03b83160cb86e6d4cdb41c3c3e82f163d2507b182aa8191777eb9c79eac032974bffe70736c81411750a08781c2c97620fdd26a8e39fec4fd19000461cc04d26ac78bad1a7e508c940b0b7e5dd88b3851af0aea68041d07989ac02516410b8350babc394bbd84de52f0ab1cb5f0fbaa30680e304fd470fb7c6a2144a8310433f9f7972fe04b84acf7bd7bdb112115a9abb0a357692c7731d8490faed54a09ef095859ec566a698dd88ea4412bf3d62059acbc2a694f639436dd60aaba4f0fd6a180c5ef697a299af6e6a18461bbae187fae4762307ff28c29df48ed647b0f7b486e6966565f4cb03b0f988d520e2bc9465daa7f97b914e0678cd064751b00aca3dba380883c0353195bd7f261d67331708c4f602e2edfc43ca987b47b60056ce116ffb54ce23c2c767b261fa90d1821bb3efc63af74e9ee21ef793fcaf506303d3afd833f825ffbb8117047e75370441703085d86a4a64e654d9d261d0a063645166d6ad995240f0c1830b3fc3a485410da57403b9cdc591d9db2283d000bfd47c4d17cc2e024a77d45a897c779473c7e225cae0436527b70bc782db5000609fcab48484c8ac9a513e86aba1295d7dd7b2bd97cac26b192211386c5d97a040f2bc0b48ef85c5021c348b98b35b69cbd6a2eb8feb54949b7c70a7158e16e078ff54dbbb6abc552f0559746754e4d5feabffc5e6ba3affef36cc01c78def10ea4ce6de40fa498f21c22d434494eed600df26622d06a54bcb5c8cecb425edb069b4111dc66939082ff71822086fd4e5fc6bc4d1fa6ec15575385be72e084490ddc1be5fb2d581d5d909ca46a0796461b6effe82963d0d571a62e9086278e8307d94f0e9d952413a08b4a0733f704e4ef56486e8971ca01967305e9f9b6f32b0f7cff615d1f584cf5a72d99aba4c401f609a6e495891200e6163b9fe38ecfdd064dcf11f5576ade2bb1db21ef18e953724d7a598d94e071932b4b52333480f90ee69258f73492a51f5ead29c642de50a4853839c78e5bcd9987f02d43ea8605016eb51065dad2d45633b7fc1a9b694bf47661177a532593eb261de041cb9cd10fc5932f115f12738783db8ec19ae959a8825698def6fc56b1424dddfb781e4201176973e8c028ccff37f00c8466f7443bf24f0443f39b02b8310d55d7d3f22e0615a097e8968450698eaf33978b6abaf7309a8b3ef120db57b25db0d60a32d40c98224cdaefc5fd58c28fe63810303b3bd856d511da92cebb5de3f5967463280d4d8b57539813f692e3566d1981e35e85d891c41430f4b73c0bc58ce2290a480c26fba04bf8b1a34ac21a0976b9d7741e5b6de64c40949a3f3cf27cc10807ef01063f22490855680a800a0642e982ba524ab62d972960d90fcc14a798268500041bba9fdc494310f11411b5c6114ba48f8d796395075b7faee63712ff463f010dc5ed204f68692373dae4d5da1399aa47d4dd5b5395defbfbdde24786bbb28b066b46e351b6155761543790ce065804e5264f0ccbd6fb952a032df317b0d9620cc78530ed46ac12c9162a4c840b8dcee4958c8a334820f6070db308e811174d01915d4bdb08ce81dc320ff528d0ba126f3ec28cf95c8d83dcca655cb225edfd000a939089c26eb8b8968d3064d3af109b4a2ad71a05cd167720f280a2a8777b09a909c1d571a79e045ef7db071134d26aa241483c205e667e77a4c406a5d3f1032f3a121cd8cee8fd985473b6eca2b397233a395aebe4982aac52c05416ca9a048b0895da9052b2c2fa00b26772529e7487069a48c277e294bf0ec4db923ef000bda2f96f9df6bbf3eb15fe17b077a8c96db63db56af40745a6902520ee797f0fab36b30a38754e47a88e379299af6ef2510bed802b110ddc9872d52513c2ac0486ce5c202dcfeaa326a67ae6c1195531eb828f7f605fb5be826ecd4ebe1b4c067e0e8ec0d4a8c2429a4314d58dbe983b78e0bc88bec77bd585dfeecd6753b807f280f75aba2c23201e555173e9d19e081b23fc18f561567d1fab358c9be7d508f96b353c5fd1bd9aa31283b4a2157ee947f095eafac073aceb2239ea96fd590d2bedecac821958188dd1ed47c7a5aa9ff74ae83d7e00e60b4f618f0647e6980d20c42b9e8765c19f739c505ca33158596e4445efe28298c9ddea8bfe174bc30a18432db20369124bf7f24c78110e7ff04b35a2c8fb76c992f7d820d526d04400ae9ec601545269d6ea40c6ffe90be99a4605b91f1f2f2c6da4b2eb1856bd030944a278e887c80d63446c74aeb34c3209ae9bd165ce39e2b5097b4f2d0b175b067512b7373c4431ff39e448675481311888ea483e4f4363f28776ebb8fae743035bcd5d91a985d0c4372b14af50f9c26b92cee26887c30d20a822a8404c99db0728170d61d523f20bdd125f3c4903301f4ba2f957f2b11e487cc73b81ac28d609589975c0c87cda5c8bfa9b0ef1ea60a8f5dcf2b8c892018a419f5596a804380571e674a8422e8e688ed2690ae968b95b4b291d16515febcb0fb4ca6767113d0b3884ec38be277792183667eaddcf424645b12684ff816bd1d4482abfc49d480f2f038784dffdb22b7d60d6b15449b44d4b2ab4443bee8de5a5c22694f695ce0abbffa1d34e3aa8427b91d21fb4bbb43deee1d6fef21f0136575dd7c7484b670d24726ff39b10dcb41798923b2fc1489d22a2e5a95e1a394b8c89be2beb1985073056ceb10c9900ee4a23b3dba2658db70cea0f2a14576a17a3d4c46dcf63c902ce1b74ebf3fee12c55ba9e61c88b58303d89e918d12b96842f9cd686a70bb20ceef9cbbfb0d7f20c0ce6e95e93d2ca69b382132252b5c76c5c588ac07b98f7014324a11c1de768084f4c11c09ecaafb84fe934055fe0c455d81e0429fa74510d31f9fefd65f25cf573c588baa13a36ade0c005931802243b8e45895fb5f733022f1c3039bf0e353d63c790787b32e963a5b64a6a055abb7fd65a02dbd862eb07a3c25bf473bd7b0c6a319da7b36d7a24b280610bf26439f860c6915c1d72d5033930162f0a344bebae233bc3440159a5517a8f3eea84b5911d2099d20c099b092fd75579b2cd71c0221e31d55cae5afaeb221cf80bf24029e10496f1bea42307cfcd880562756bc12138edef7f8f256ef7906068832e4db67c1c71684d0dea05d6e8441102a9fae0e1e1e01854354a00b2e510c677e37f7928657b28f900ed080fc8120d61fb0ab548d74ad1ceb030b271ac6a6fbc4957b7c74b326ffed88306625f47d9307327492a2f89e05ed78422d300eece87787bc09fbb159462bc250b9be0e5f0b90fa26f3e902e09265848ec3742de640b908edab1250b67b108fa0425b472c34dec48a8a5e6fc563e535295843cd6940c28f8fa58c5b4a0874e0f02ed9dba6ec9830f937e83f3c712066e7ae0f657da48744433d015ea2296b4d40eba46e4cf25b9cc162e9d24d192fb1d0da60e75d7f769085aa3503342c8eed90d68f81aa54f62969d9fef3f50608ed0c1d9266516b2d459e7730590d9fca7b70e2cd630d0b43e216264eac09d2e53eb7bb27b9b708b8e4f20d9b5f2b92917c90e1c13d02ff1c6af4fb468848844e1479997816a71c57f617b7a699170409a580fb78cf0b8eab962351f253dcac75aec34891da2c1f428e4dcad12ad85e72f2d0f54d0b139b858daecf9bc75dd77baf10cb699e29e982b8c8deab2075388cde601739751a4e4e44084cd919b3bc0a45dc32c9d5734c688e0d9a6e693b7d12fbf02756a38aed80dc085ed934ca0755785751f4d3859f06375dda170b6a088e5ec080935fa52e35c7b927784938958b34aaf78c14ead3f7a265d2bb968d4ad242a00de6a7c4683d356c58a385b20efe7d3f2bbde5c7c9c7ed795db106cecd680070fed9afb5162564594c40d2f398b2734b41d24274023d11efe08fa540166e4a303af233f140a410f77f53beed9e8bbb971cdf2fa15bd1fc1029664f7592b25b20f20f08ce5750fd8ff3efb2016ec90a2461faaefc8ca4ca38bcc5f47f39d11340beb19222c43d0aafb2ade825e7125a967c2e9907432816db7c3bcfc418f577e04b1b8f631b6cc7c691798de7713787d557cd05933f44ab2818b6a24fe9791e80d2eb8d7a8d449a23a821efa8c5421b20895e97b34985c13f18d185ea359061b03e3ac695997ec614f82fe8d59a99dec3ed2984df4286f0e5b39e7998c29a8cf0b8a863ef5c6607c57d2d1996a7311a6aa6102342d3951243b8fd5262da46fb80241b55647a2e01dd6aa1de77b929d9fb0d51ed6c862d39c282d1832c0f8c11b06fca7cc3822478816988c6cc5c9dfdb009a642cdd1de78c243fa39c6df308b7085da84a1a17996bcf1a47586e76b9d149c32bbebf618fcf5be646ec708a64b406c57c90a490a0e5c58a41c48312db76fcd1a16e3528293770749cc40c2bb0b90fa9522183881a324a971c112b3dad96c3cb6052ae2adaa03d7496a1caacea7a0aab8031919839edb89e7e8c749a654cba13f8cb8344659859a379aa6a832f700667e12099ea769a1e8ea8e7108cdb07bed50ad60601513791216b4c2382135b06cb44ce9f5d4a6f36e668145d9788495c310217423d859ece5c014e9de01c430e89e3689272ea2d7badb629cb77dae0eac2fd6b695aa4d7ed7a0e3c7659096b0df7717c27cbbd2a7bb777440d3f1b29a3b2eb2aca6f6acc1991af0cbb1458d806b1753696c05755befb92d3f23c5d42aac1975242dc2049c4d4504b462e65410707623ce04282c159cd1dc0eb2776d797e40691526052f717ea0ffec3353fa405e95fb65467eaab4fb248497508c41d0ea71554fb026634fc76960e78ae0f0b04c8f836bd30f29305a8cfa2c51bc411656e98a2c42d02bc742392ec0f967f8b0c32e799657f175738a62f8f08afe00c43e442c93fbf643d4c2633831a4f5fbf099f3149fe42194f5aa19168b4b5f1640d0a4e9a484464f365914a6251d1720b018579ae58b287f58f8961922c015417790ccc5f3196b81a0140f2a9f2b3a12a037f6730eef1b164d9331ac13ad44ff1db00dab5564d2b57729184312d0808910c38c6247da6dd22c1926d957ee1607527ec835042b47b078628e2c0e154fbc3092a8bd2b26ee18f3be850b06f74754ec40a1a4f0a9683c626eb541d2edbab130521b1c980bf71acc5e3360b90bf62507b9cfbc2e668b2e0b95ba229fd6f7dd9095e8899b6bb49866d68a7d6475c6c305997fd823e265106b3622bda831b24630e5fb4d95d66cdb8e5624f09df6e95ede68934779e663da92d646691108df27b04ad9ce0e62f411613fd0f25602db2337ada3be3194dfed48168db6ff5aadf06083af04660fbe93f64a5ca9217df9aaf8ce9f609ed7a31716e31a3aa825f9ae803b878e66008ba56da671c1d58515fbd5b48d2fe120dd0745f6c64115848e0ab061c9f9f8ee13d13614331f628c3f5730bba0af989d86912e31f80c2eb8ade5e08043c58345d18f20cc71393414f8e052c987d3421519b665e328146bfe115ce0cc1daec25fec9bf801417ddd038c9f01bd37f38ddc35189f61d8b97aecc5356002394aa1175b5b234208ec7f639c5891c2dcad8c773cb4e65cd9c75ba9599290158c7bca37c78ccaf3e4fb04955d7afefd7a8b17d13b1fde83dbfd7e8d747e402f2bb6f5c271e44787e787d5be836a83f699341c07e1d515c4d22cccd9bce2f0781d35ffbb0e35ca9aaa5d8ab6d27c566b42f74ceff822a200a96f17a216b240ba0da2a917a34d256ed6cb2af3e8c4172eee2263cd85220e9d677af879d31da0991965eee5e81fb7bc547c4735201d798a3bc3e8dd2851102a7138ffec5892d0c2aca6d8610104621f0f54c78e68750f2e873f20831ff4e982d5efff258decf0b298e4538d1c55a6bb163985b207156d492617add7381c7b387a6f01adf576e09f32106f50e4ec47311b9103152bb2c18d8355cb6a301e2759131090a57cd2202d36d62e80bc62d77f8ab56b6fca813b24e9a0ebad9a44723eb8657bff211c50c0b7e6ac8d63ea9cbf971160e857dfff9835e49c47bdb930a4920958e6abfa70cbd1a09ca61c9974151d9fffd8e627e90702ae4b99c2f9e7e37b5cc0aa84dc30812d5290f2e7307942b22db66b6673a5cb3b96109b43ea5ce59acdab85ba6e30525800e98d5cfa6c5f5070bdb0109b37fe14c68c21310659beec8ee27f62aa50c31d0a0aa2d21ee33f4723870633ff89f776f40ae7ff9f1425ee32516dec4f200613837fbe1f00179b58cd6a678b53560362c5e07b770211f1bd297033b22d40698e78bcd093dbaed71f67fe0b1f8057ec3a0daea31fe76be6387f3f66d4f7506bf30d809b9fc3c234587f6b31c8d2c07b3d88b7f8fc232259de33be47463510cfb87f3afa13b67e44e650c26610672c5f067740cd54201984b07bc8cee2f0e02277b0a72c46b8042da256e57d1c3eb66b124335bf97dd06ee20f91cb83e48f02d163b34b853c800b507da8505be1a7e558ae5e8f8c7e7858d4403ab8311c3208de79c79f235612f6137730ea4df4c4e0e518578e3bb6b24c84d5f56ff05ba30586c035278711cc00b1bf0fe22f2cf15552639614a240b65e298dac7986d9ed0c5ee38f93d578422ca60e6ee9d893a95b378096ee8a164b6c7e403cd5e754df03075fc826b87553a67f33e93e6dfe51e4d2f242f4222cb8bb456119ab5ecef600a2745642e57ae63e62c2544720d3658b9534f6ffa010cf4032f5b3f16a7c4108bb7ff357b070c8b83554fc06d1ba2881278d28be137471c72a4e6af08c4afd0b91fbf9395ebc06572c7875b43d06ab3e4d9da771c1fa3e5ab78962d27d93b50713fae3be2a4a59675eda0104dd1b84cb42aba8c501b05c489f10a744acf02f0250bc3d744c76e474d5f2ca2d49cc87589e8ebfb3611a9d370227d41e65df200f729d4e28f0f6d07612ba9de438fee323e61e1ba275b4fbe2cb24940feed4240ce05e7a5c6a00b8ee8bee51fedbac4ddecff70c4c9eb061d724bf4353c7ac68099ac8dc498e8bc9cad3c3baf1bc36cf10dae1bd63f91e705df6a28b945969ab06831e4e6a4e7ef4a486c2253810870b1b6281a7e5191c4efb5fbb3e0d4c3f16016a06c9cc206c116496e4ddd85c7302599c1345dd7a01c5f5aea3adee1cc88005e343b5c5f0856b2908f6b7176cbef56123e07d666cb61b407ac310cb41cca804cf21ca1c32f816df08f12f4860f8a79ece4f62d2851250b1553769e5002f2d061a11515f6b66ec23110ba4126d96ecf2822fae8bfa98ba130e7d467ed93f280bbc20802a528bce488e9e48893597f20377076f0d134effc68e343584c404f703a846c5adcb5db29e56f4b6d58e74296f6c38ca4e113bc6f175994666b3f57a01a99f216f4465a29c195fd991165fa0a50e3dc5840999d214792d4d368c15150f5142626b85461ce3f0e6b4829b2e121f64c733a60226530244fad41014774e020f6939a396182bc6f638cbb64814d4bdf6742a2798f4da39bc9472cfc6755c0a911504078a3544e44d602087654928e84d85aa7e4087f9e831c05737bf29a108012c93376641f9e78a3059bb38d9e12c11a69e4a87ed0255869c94b02bacc70e7622d1c84df9ea82c4ac6d31de599b2af9f7ca9fd5b3c345b350b9b01c21dd0c8c101bc11725cac963e593d3bec607cfb393e09695300453574b23e01fdc490838ad57e08dc6b852d02abb7e4588dc708ec9d5fb21db2d70a64b4d19437a5e0439d95da018acff669c5fe760591541eb0dce5d7104920202718501cd69bcba0fefd7e9ad7857bfa1b004f41ae97e1352fd9c8f5833660dc677a78bd15243a90225d48df8c28bd5faf7a8cd221f95b6d38103ea4c3520cc4ebb8156f5450b680c1e4ab0c38e9de2d871ec17bd7916eac380f4900f965ed4e6e4a76c2ff7f3ee013eb5bcff371183857c03f62ab73a6cebafd705cf2d476a9ec82689d898181f0e52896642ec8b96ff482b9d1dad4f311feb5fd9755dff1f26ec9f755e910737008d00817779f5ad405700f00d2337e38dd5793d0578f7fb26ef62f8363c86a604c9258905bbe52992be611ef36d7814296aaa2fb124411dffd2084e88a4663204f3b616831b05c07602125487d4225cff288993ed26a1588f16324dabe05df5086554604dc57863e7e6c02ad8ebfa9b7b58f24ed0e7495eaee3eaa23f60decc03a5d9870aaaf3168e2c4c5b28169e8d34fa8ccbac6932a277db6dc628051de20c54289e5b922debd3029cfa453232b592e182b8429ad33504ec30021a48c5da04779395912260137868a57d6359f63be0c4f7c80c742ad73e2a7518d337f4b60c2c6a5371852d8d3db84093354c7d82f6e7192da0bd27c383ec20be13fa90140d132215ad5160a3c245ae9d9272aac87454de860e2fdb08bdf9a6961021c90a01b8b0a7c2b27674d231e5766f9f206284a2ebc4c72e792d8fee29caa5eca92e04bfcdd858480311131ba4ad3305e5b4e2f8370eb3f1dfd3d14a49f8eb783492028343860414a5ab3cf645da149b623a9c25a5ac2eb16f6aa761e2436426b003024818656bf12dac5a2dccf67be874458e3f28764ab48861c13c03efd1f79ff202fc362b2911f386d0f7ab062599b881399a7405eb0ffcc3ae90d611bd92e8bf04f5062c399cd6008b46c7f5a72e608acf21cbe708ed72d7eb82889ce8edce1203add0f76ae8c2920cca192afdcf8dc2cfa027b3954a6b135be14c7916da25e70e8502306fd3c50a9e0477ba7d8b91730e77c643182ad3aa4a48f9725f28ec330b6b8f2d0cc4a571729dca34099d4cf199a0661244c17a02ae4d9e552d13faad09710a3b6b42ccbea9f615b001f09b02dbd2b9ddff9a923dbff04aa61954a9be0ff1b8500c9e0796a17b36f447191f5a5159a03e2670cd0e8cee6f4f13d6591a080f84dc2b10c5d663d90133f86caf52f7f751efd7c46806bf006acdc21a1b07073aacc92f5db917564312fc8d068e5dc4225cb1230454bf989d3c3c9b87ace00c11d019878d3cf1c267965e4ac2e381f8d3bc33bf6a31b684b9e4d3c5491bbe0e5d368965739cba92380d58f7eed8703eaed23cd0a2fe7f6656e05449604ef505923f50e2dd5050c1b9691344a6bd2b63312cdae32385a4153c72890baacee102df13e3fb2231fa2ff47701ee7b4842fa4d894dda1104f2a591d23ee767e7290bda41085079ea544bf09e228f186d8b94d6fa7615980459c9ceaf0a933e4ff7002a1e70eca0a47c0cc08170738ee286c873d77c77a4d78a1bd65c7203d179c405f5156103452b7466d8d3c9d0d686ea0fb5e39feee4511abe3c73fbefb0612506140e9cde797fc0cbcee9fe01396a294064a11188fba3d8c749e4909623840607eccf527978073b6206db80253333e427b65c03075fda4c9901bf9df87387510ce7f4abcdac44d4d2b240a859ed839bda0dc6abaf175b30de9fedb3c99097910ecc96b4bbd92023af202f886a350b6d128599bdbba366af266582c92cd661630b939fa1604c47882585ade45814f94d717e6d67a52f5fe13aa9d69a78fe41a00669bade2d2ec8ed0197606ca09ea291881c061b3ce8b4f2b1f5088d839787730f4f232402962f89d359776f81e82fdb8d90d25c0f396a70a572760e69165d2201671b0b19f69a641bbfa7e420348347301397ee1206e6da5bf67642c7c830a50676813e6251feffab2e587956de1cdf619efc0b0dfe85bc2653e335ce1e7d010b15adc24eb4ba2a064ec2b78724bb586524788386a1b0ada4f8dcf24303993f0a4b0049d7385396d764d62d87de60b2f20e7bfeb771b4f42fadbb975770f4630eeb73381744e3c6d8fc62c2fec1d6b7ab4e9fbffdf00fc27b705ad6679af98b09a1cc86ed9825950a78e9a5c27e5e7983c61182fcda36e75423d87ac9041d320abeda411ab96dc4bedded92752b0ca4ba8860bfb8279fd4d17374c606d4e09d0bc85ba45eed1dd4f869af265f032cf89058adc0a8538ce8d3243f96123a430c0309f8a5ccc588dc9d7cf08824d789aeaa0a405e687ba7b97b711da0912e35fc0f9c946ab6cebb64b0133e441d8d02bbf061fb77cb36ca452be312e0ae699eaa0425ed7d62876d0c945545ae1a3c9a1a4f7cd5b3764bbeeece90afc6a629c8f90f5097b9e767a4486d4f8607ddf40dd25c2df16c961b0ad1f75764df8a72aa6907f97e1fc0c11c5627b95f68378ea65d726f56708780cbf0f076009783f6031a060d8b3a0675842049af91b419402d0e7fe286a3e51dd094731e585960634eff05f3711c43044c89e9076f1d9c57c5aaee2d921a6b32e2e88ed91b7d800229b60d26abdab5ada93edefb924150504c95ca0162c49d45e234c1f4e26a2a96d7ac01e0e529d97f78e0aa1985b31c3750e4c7810e99416d7a09660732f5671848e909bc42fb8784dce3728579d04a09615c6a09fd49e1a4f985009672037e34722b0c77c53229832750befd88f80aeffa6f1475d873613695181a7c9fe64e9e8f3c002aa73e0eb6a21a85a512ccabb93ac0e1b089b2ad900f717bd60841008e97400968ee123a39eadf024077247a56cba05f8ea1e4a8b0d616498709041d3971960d068487d9a6d3386c56574c6ae9b1fee0aa09c33b24b206c3ffc8e6739ceb910dd7c12d235ccc5007e1c91b91e9100040c75eaf3bcd41e5f5e8c62e84809a050effcd505448b3adcc70db588b9782c09dab732db476aa483366927f76515f9502e3012971da123c8ea5e5901382da58cd269bba30a9682737bbdef4bf901a0903119f98c732aa2eaaa9f8094be64793bc38a16d503cddbfbc1984c87480883704224e938adf0ea5b6927456fc08132f6d52411f53f5d41df9eac9f109f8d39207439b510a791516de6986a5d008364f2e006313af6ef60438ed42415d791bb70b090d06eb3dc7f597f9b582426277de4b7eabb260e647366adbefa72f45d50f047f0be10fc5e9064885c66ed598e460311140db05615192e5e059c55403777a062878628b75db81fff138611fda011a062ada194cb80e2bb635e657d4c5773f03b973fed6428fd0932f21a7ac026b8b2c94dde1cd3182d525211982a75867360b36f819f2359665c774e72bd24091fd7c4d9160c62fd92367eefd9115ccf57c07c5a61ad23406fbc369ae3e1f23f635a9126fcf89a525d7f28e1df60a83d0f9063d0c7b57befa8b2ab425b43301d639f7579af638eff5ac1cebfb0f1dc053240dd018221c868ecf390722d013b346f21a755592049eb55cc066bdf9a613ac18013c95771c8e97d38cc2591a8e6d053145d3a4c15b71effb726bdac189af1b7f0f0e4eefe9f006c78ceb33f4f48fdbd3567dcd9a28ac763beb1a3e2e74edf43e02b6a0e08599d58ea64f8732a8fd2cb39e76ec80ced1212ed5e35cc7d18c2d770eb4d7e24db9e651bfcfc9e5e22c329c846dbc42712a3009ac257cb6cef04d760bd9c23a51f09ed2080f72b3e34f71bab5a601458f2106d3e6e6d6d7e6c03e0b0997daf163144ed852c2200e2450be39258ececd5c117becc500ac5b79e2d52707f43b12090c31e2bf9abcc692263047243c61dac20ba4212079d5a2bc364f1001966a85595fb413102a7aa056cfa886363d55cbd9ab0f58a365e36e7a219cf10b45ced70c0b5f81793fc5639d7dba3bbb06a53a81d54e9a33a26b8b005a82fc083a84478e289b3fd24d3dbbb5e5730bf9cba3dac4ca5dbc362935b971af50920c9eb46475734f7d42f176e78c8a226baf097f74fab4a82ba0dd721c50b8e01809718cab67b368ecc007ea05783cf80c464d7acce98a44a6eb2053393d3acaea04c7c88c0ddc657b807ca68ea0953823186097c0c8b304ca516a1a39cb35d4c20fc38e66d62a01d74eaab3bcae1d80af89219a025e56a8b34959098bd35b71bf0d995fa176d00efae0d8765976a1fc4176b6c67ef895eb64e30c3ebfda14c2850bea6f068a4dc113e8c6e412b14e347c073643f347daf88cacfb668a309462600d257fe62504693dd813d55bd5e5b6d75c6f24dec3d10fa1ca8b062deef38a910611399ef2ba65ce299a088ce2f6760861000703c9a8b63819f8cebdd87e0a56062956224d5f08319ec945f50f57fd42fc98af19a02075e0ec217a747dfb3fd70e80a57b31812e9995f4780870d81457ad3723a0ff1b065f3606482f2b64d8090e3231f373245376f49e25a2a925f058b632c699c32e4d85f28db31bdef4786f0e1432c8af25e8a66fd924feb1bc49ee1c418b0dfae82991edbf9ed677c82bef09456942f258efcd9b203a140a0352cc84fbf276c94323d37410a474130d4ecb0f76814c9830408ab5764f1bcbb6a7048a4bbf515826bfe8282697a4cfbe7eaa0c65895648d1378164a9bc787d3e6ccfd3dabd7d87d9053b53f8cc6fe88279f80c2df6eff62c7bdfe626507a67ee295100fca8b1df2e6887516177e727d08d5a0332dc8be98862c587d2c44cffd94cefc7aaea5cf195643be9b0f855747e44c50b45fa6057d9e3dec3a7af9e63b8650f598504243d1a7439b5af646692f1de92008e23015b9f5057f78ff5aee33d946cb38bef508caccf03965d1e16042223950209de0d44c16488482a4bca2c4e882952d57f22f0d58ad488e5fa25395a4d6309ffc01afdd5d134a9423f102254304d5339a2d0db63711bf27e00622373e11c0d35161da5f4915e520aeff3e0d644437335e18d9145c38078714f964fe9774702ea31907cb1e0443338640bdd07bfba58edbb8b3f3d4a0c2d87a503360c78b20890dd8457408b712fe95b93c8eeb81224ce7373ff394857d4c0b220ab8b10ca086a3e33782e7b6b1fa84ea82b97061f430980be5595d0493e80f3c20f2cd10b0539f97352b592d42e00091fc312860d6506609f68e682eea30c972b50a53ae70e31678b1d2888198445363ad0b571fafb63c95178a38db0d6a3e6ae15d30c640be812265cdeb9e136f953e95930d367989c2fdf7a1a8c01aa07fea12ce29339062c1d01eb0997b7e606b9112c48556e7254cc986cace4980c2f285d492383d30e7d7ae722a97ce9ad41231865fb3ef762fe5402e83b4c41076c4a2b377c36f406b452e83cc6c4a1f04d469d86d8618c180bc92b722ff0fc66aa4db222c0bfa00c36d9e980a6558d3aa912c3c198e30ba06610a2cf53421565974678b4035d4805973c939dfcdb7a35d325b4f22449d1e83308b98c4be1351c4647dad678563d0e471f2fa769a615ee51be5bd56810f54e964eda3a4a02593e1dfe729a0925a00c3ae32a9513eb8577d59c9ca6ec8dc574cb5e6ced89e376453480dcad563f350cc5079a8f55c252c8f5982ffb66fac1bee2988a0ef6f14fc22a0c7a5f2e2a2107f7f5d0209f0bbbf09da9e844b1a3f59c4c12655664b146051d557ecfb3f12905a7bf8d0bdd033edb4ea70b35d1df5bf723f970a8717d83df9cd4db3760832c0218a302de4a350540914ff78ad63cfd5e311a6edd172084d15fe7cc30a3b59005cfa82e2a744966b85244b494b51d913d3e3a461d72da466d2e44092d451eac0614e3c3f981e56a488dd7c2655048e283197a3cb4223d6b38df3262e20add570aeed51819e04b645a538e476442782310782df1e971dd61d7b77014a464198f04711e3a7c9bd6f62b37048446db74080b6637ce264bfb901a583ecdb3f01ef404c2ecb491e10a299eb20be84fbbd929d833674177915b88338a80aa4654114d08a8390ccc731fc443454b005c2fb964a51b220cca7e6442df825b812369e6960d434f9debfeb29a574595e8126795bb75babb700f79d0813e91a144b2fe33d90a6b80d03374c62edf0a6b3b56d7b577b6a8e515e1fb0c079012cde87a8b6bae0e493b7649d9c76f48a7cb30a477c77eac6689e5d7db9512e3275378fa9a6bc2079aa5d456da9a504906428de84f9b34e0df23c264b789d79aaea6c16db4f81c041bc90fb45facb255dfbb0e5d2521ae74fe4dbcc7b056ff6a2e19085455cc9c0dd18a86e5d1ab695905dc95f39f653d6db128a281d3d08af9ba20691aadc4170a6e4a3ea298fc04c45fa7a2f5b8007ae277847128180a2e7375b9498fd517130baa931b6826a0a20faae159a1087c4e2ba26034652c0b38a53b0aeb96e9ca0b0f700ce71e41249cb4182997dd04393d81131d579902335abb5a177c138865c20d0663ad8395afdb154c78578c58e4428907bd3569b9d7cf58c0e1c53f3e57e305d2d79d0f023944cd466d16212f4501e2ba289883b151dd553908141c28f3cf00cf4894d8e3bd4f0bd4ad4403a72fce4822ca9eadd4acb82cc086c164735131035b46c652f905f48bf2509b2a78150860f4ab8a8d65dc610dab2d453f12bb69036119f0746eadcf8a4a03b1de0f8c22f0801884334a4b027a0a47d3c4bbe0460938a3f002061ffa01dabda2f96a786a4a19fcd0d0099d1a498c8b76004732ac0f5f518d07a775fed793d45508a063c3fe77135cf68e512d2093bea41bf7d9ad0e67466088f4f5bb5614b7f3822993b66e88fd118b3c48f9e3452314db4f8842087198bdec5f69eb8ae73453c8af3dad211a25b2c83157749b14ac9228d7e5ff02e7622c37caf11e219f09cbb503a00f7f2ea0d7d1b0147ea225411ac039b88a0b4989287f23603a1a32a19823f0e238c7418e3002d7c8a5ce212b25108e738101db82fe2d88d5ef70ed231804e1716333e3cd21f8976c556e2af79643ae21100755ac97b7a5cf7e660ec162a4dc7e6661d31a804a51abe6178f7ff2b4a5cb0f0716401d87bca54f1d10b3ca6a44457469fb4052cf008cbf4ea6a0292de65b7b085e630d2f9f57e0917ba530095a5f512c236e4888077c64eb3fa43b70974eb6041e71305259839f7cf236d1e66e488204c108c9f60da7369562bd9439f9d1a10bb3dfaea30e7b1eacdaabba3696a4ab5df990fd7332c58776b4a87eef1f98ce0efd45bad2d47965c955aa7a2e4a93a6cde28e67ef7d6be89ca917b77c4d7ac30d42fb9bd5f1e5e42bbb6ea6efa84ee8a0e119a751f6be839882eaabda76b2ce0c8bb85b16b5a77cd0849040b48e63a96551a1416e712e09713acaf1f6bddd1a063870aab5ac79b04243ff3b1a23d265c8bc6c151d9ba5ce38175a736a38b63001aa96f91071849fb26e1f4293419874c887b0541ba0a84706f56f6793d1119f067a410d679e909e93fdb99b04a42fc7d1bbe873f0a6ddd23f511992c81de5d50a43d105d6db074c03cafbc6905323a0ec9109501c41231e913a9cb5ecb01efc0357c6a24a6286d8833857e19195cb37f5e18148852757b19b3ea136d2b544560513e8094a108ad8b50136d7ea1a5689f748830d234e7d6b4e4b9fd505af622a024ea25c55dcfe2503b095e085957a30b9ee55e79023c85f7a82fb1be5260f9908b3b02054d1438726c80b2cf030b132f59d08fb3d578316165f846af287eea00e246845c15987f0b84bd05899dbbf348e52be505ab29f67fa261e564d625cdd02d63305e4267448fea8efab8c2c6c124b3a1e763b28685280c37d1adb002f680fc17a7e3632dbe18c430f4b799c3a4660faf039ad7e67d724bbb2fb9b10e5dc0e +generate_ring_signature 68d6b1b9d874d51227c9f0a28cda04d8172e7cae79e06b58aca4cb5fdabf36c0 3438eed5f743a6715d57581bf005efe4fc4cce9447e6d296bd602250d8c16fa2 32 97f5294c86120cfa379c931f3616ae5853e5650dccf93877dd3d22a949deae47 20456187ac5551528a6c1e1e6e6ae511a8835a1e17c2d8376fb0d3d68f8ff749 0b8117871c4b8a996719c93ec132408c440b9f0a73d36ce619e4ea5099f46f3d b258d44bd5ecceec9ea3b4fc8e95496d997234a63c7b6e5128b39bbefbbc4bed 7c68933b4898deb06963efe87110b3a446466a13b18660dd8f550622629d0c0c c2a30c8b5167c28eb95b91920dc363bb6f933bcd64986c3434ed89fc077536ee 3c98ea89ace2a89cee7bc6e06f63cf5ba9297273b9044d4c6ae81b9e411bb440 cfbad8a65a06a22fe90f2bc11ffc003601392504fb1b3f85177f769e22481b8d 8085897e5683d6b33672d6e2e7532337eaf1a6c47d6eab0832460f5460f9f495 a4545f4596f607250e5de364cc2e0e070e37d1c330a6ac6eabb3d03af415209a 9febfeb7e7bbcfc9ed9d663b81671638f03555fdbad469150cb649f765d60d6b b7240cef5233c3eaf7ea031d7ed769d65a7362c90448afe2fb5fba997ceb6d45 0343b7459f99c7ac11c3d9f829f5615c5bc60e35569dfd97b78e6ae2e00f5d8b da9d89d8f350d85ce47516472c0e73dbe1114aa92de1e847d7c6a1903651671e 3bc5140c5ca0e3df7a69f91bdb268dcfa28550c35d64da809ba9940c03dc842c 85eb184236053a9e30b23e189e446a46c11be28359c0b4f70fa696e88a425b39 d08857473602cf81bbc7b1b17766fc09a7fd97c3994f8bc4de94c6aee03f3e99 7edfc9671443ccc734800a1479d6e7840689872b8652be4e97c9ea7aa9971e3f fe172c59587584facc28059d30713ecbdb2f38d75e967899cce7043592ad3e02 d073e626d083698553eb8c7d60e5a526e06f9e288f2c0216cc71535b443a3528 6621abc1d1d77e0e65d363b1dbea5a4651a810fead6d57fb116791f83824d668 fdffaf67600740168caec34bfd37b0fbb16275b155de1eb1bd7b39f1150d0c88 dfddcde4c8ac2861c78bc7df7cf627f7bf8d115c825a10d470ee665ab72bbb22 4d93013a13fb22587ebfdb63e9d8ccb1f7c04bd51c199346461fcf3314094887 f008c557a5edfa69389b32f0da30d88b2e6b91a4e37600c14772ffd578a67930 d1ee1579b8fe43e9faf76280b8c012985465491c20bfbc29d9b2f2e69083e16c 5056cb0d29f7e3fff91d6f9ddacb545f2266163f049ae76407df41c25101658f 80b56590de9d2826db4bc73ca7f18407fd0e5c5c03dd9841c9ded9b8dafbbea6 62571c909782c70567e9968ded1c05a4226a3e04a07ae9db48e0153a56b2a468 fa3243902d44e63e78a23d70a6706efb6e453d3ed42d087cabc7655fb83ca3e4 976c32ea460a47aa3596d836d70bb40a84e6f3d9ff1e2e01a516cfeec938a2f1 04d573623956db0dd22344c139dc7170d8ddf6296ccf558cc2bacf230485aa05 041c83987a208dcb9b7658b567e4baa29c0fd278a85a7ed885d26e4356250908 11 f671094a78aa561b3b55a7f48d64975d9e9affbe91004b50d9d94e2244434702613f71f6a4d2ff96c5ec14b35f04e7d6634aa8df18f7cb354e3410b9273eee0a215bdfca3db61b3961e6efc29e6036a8dcee279d82a32008081cfa4c8b7cab076f34223f8563f8f4406f0cb88c8b5f9e30ff3f37c48eb80814682828dfb77c0129c1ceafcc2da0bf24133b80bade09fb6651fbd68f2872a44d4fb47be30db0006670be7bc4f0f6d3b0cdb31276fe0deb50cd17bdab908d3f931cfb0870dadd0ef87fc22eb156412208e4296f221bab9bd2b9f628207ac5b5e2daa40257892d05d7a32e8b8cfd84db9a2c048b417b474f859ad2110ec0d7cc99a1431224acdf0c102423cd4cae34298f6d5bbe999359bf1641d9b184fc4c65ad363cb3ef8f410c5a696eae469985d0bfbbc0aab3ff609c8e88e6defc0c1a2f73d2b98e93a5ea08718d856f35b6b54f8eac38a3da0014adea4be6c5570d79aa1abee1d66603280f1890eee8cb87780032722203f865fc149f197f69a597409535b11986a9fb9a06116e557210f7b19b3bd48428b6b5a0bf560e27c196c5c3caa0b2017bd6278807c34e5cc292e6a45929650b358c9e4e06cdf8720eefcc1652e6e05f7d10fbdd06ab7fe0cf50b4de1cee7995ae250da3af0256ecde371d60098ed174437a2776064fe895c89b8e1cef0964745eb829dde215303abf16bd38d6152b195c89764f06a9443387b5a5a993d8a92afa46f8ad2dd6ecc9c71b0379ac7fe21e6a20163e0ee949ce04e30101f2a4776df1dc04af4a6d4665ad9469a54f2b9fcb948b696a024b6b6e0f1b60e7424b74b0b735e9232678c87274fd931ac18f7fc0064ad82a0c4a794bd5e298b43ac5491edab3b39df33135617d5762acd9a8664ccf8ad4ac09994bea862bae4298b8fcf1bc25cf5f5501d6dd6f1d9aff1a9a642dbe001e45029f0248687977fc591ed17a30e572a019c5c939a892a76cc54be41d9bbf378106673983da3124c04caf0f84a00dfa2df71d8ef63c5326cc9777bca134ab209204358791c4940772f91e31b6b2293e4df1d419b56f75145c93f4377edbe50e5d088ec88ba7a5a015c08d2f9f67b89b43e7f19fb1a6608d86e3094c48196d479d06653e53cfd9e2b415c0e2c39fb7b60ab1f72b6d682aa85981ff6bec05e36e8a0334c707b7c92e0b42aba055030938cb1e60c9c61e24a3ee2568b394da6ef1af0ac20735443c6033777ae285d8e239ec9009c0c1c18412889ea5a064c30359a5032701a66d6cdca2756438765e401205d833e397aab5b68da09ec63d3958994407116e2f18371d2493ee497c8add0e58e3c2a08389b0ff709eb6790a01c16ec40e4f93c285b621db15f45be3acdaa81eb61afa47b4b95017c303f7b1122f38630eb0c5d5694630f5533c8bd88d33c0aaa299f67e7c30ee766565208c428f51560fe55c533ea708f10a98fce6d7924e0c95ad8ab7f32975f2e36aa2bc69cd0ee200f8b64affdb7ece73942627162170aded7a030ce093d1c90f986786156bda4b0a698140b00b2c50b8aa0b7fd5a8aaa2e3aaccb227093cc68d2ac59eceb0ce4d080744629f0b40bc96ddff73b312512b3e3886462fdc2c4efcfde9e74e0eff8f05b0a3ed6de5ec750cb68bef1a99c4dffd2bc3fa90a76496c3e890ec1fb54a1d043481b7d5961827c355e4e27dd79b67f03ce7d92075a368a0716dff52a35bec0bb54f00fcf2f317a7cf26243ec4764a90277d1396a9bf175e4503bad41d34900a954bd362cf87d97282c5662ec5c2c34db7ef9a2707cee69477956ea7ac99c408772cd1f86a4546d3716b7c0019a12398c06422da7f743c51d45bbde7f500af0721513c9d844ec9b6bcd984787df569351407eb354d78eaad431f4e1082813104c049144c88327388bbe0088fb8af619213eee94c43b79c0a6cc6a330eba89a090a17a2a79a01313e701fc5d89bc5820462baf7233403117644bb167567ca930dce25f0a4dd3fd82f31bb60942cd73e9e49e17fb8e200acf57fec304b7509080f74bfea3a21626125b4b784610900713739222f7e73a2a547b6e26c991dbdfd0622f96f5e516a97a909d983ae811ad66a9a95134295d4765f83860ade5866b409098d5ceebfbf682dc288417b7aa06018f87fcf84bc9657af0289a1f4c99e240822b07d9ece9dd6134e026de189194270547847d85a323e48106aaba573230d0e6305e5674707af1ecd706d61fb3ec9d00adb297c70a7e49c1df9f36702c38b04956a41b2403a02c455691495ac183640746df4b3034182ddbf92c874fcc063011213dc8ad9a4bfd250103e98c73053de4d014ba146e8b92dfdcb0d2c7b49a5003a72a16440938e6dfb3fd9eb25859abc57b5dad2128a7d835bdfc78b131d840d968bc131d314a50a92cd05748666dce92f899bda29d8d80dd4590d792b42b00277cf912bd58034b9ee25d633da6958e3fbb312d129fccac46602aac8e7a1c202aedfb4a68eccc527813534ac26e1cc4df49281949e7dd8887cde8b4474ce3409bf03302bbd01bf8f145f5b5c5babe2066cacce207c028e773cad4888d5b9ac0823bb6f5db6d4d89a2d8f78395b6961f972a47daf5af9bbfebe75f233e64ae106dd0199b0e92ef32e9b2a8d34e932000f06045674bd3c9a5f48b85ccf894e050da36b4bb21c0391fc30a7834fba854dd1985dbb8917fed66e53d589fdd7d4e70fa333632662b109c834144757de67974f272b3aba9d1859bc2ef8c1134c63a502760c7379af1bafb7040420eabebbbd57d62386df763ed154f8083607473aac03dc69a24901d3a18d451fee65fe0f7a8164824e50405ee161280a6df87e817b054fabc2dbefed3afe6bed3115e43a7e5df306505b5ada2f1ab5b3187117ef990c check_ring_signature 1eb5a959cfc7a40b661728d352c6287e9dc310fc65e4c0a918c20139d7607d08 7184fb63c48a07960785cb450cc4515b97e7b659c762758189a4cbdfd15ecbb9 200 543feea2b11f4c1999fd15f1968c57a31d76969ec3c84c25573b3cf2bf9b5311 f7acd82c5348165412cbff4df40ddd3ed317575cf11e2b47e2ac6b5b7934008b 2442c5df338c960d7c9dc1b3bc18c6a3a532617265d74eb65bc3d2f8c6bedf3c ec2e1890adc73628519c41299c4056b5a517b614401ca8eb9d1e891f48805adf d49719b604a8c4e7733a9a8581956224e5e9e814562df70c5c25a0a7b5dca7ce 7805c4fb95bc45642f87d5abb0c407f519b5664010294cf57ac09f59ac28867c dbed4e7268bbdc7dad3f866d8ad59b98ba855ab32834e6df09ca0f9710067d4e 3eb3cb8fe7eeea2ff5ba051e32fa3a2e3b7c711b828d8a76165cdf7b2cc176f9 94df9911db6f6d46b49115349ed48e8fa4fe32fed831c9b31ebb0c85faca116c 992c65174fa348e589d5f550a95d83ca76514fecc90d0f351d92d9a6c0df320e 225712dad2f04909e6d79d01ce8fb7d33047f972375a0ef54e8a5fcf3d875f7f a9a86880f9e0078a4947421c95987187dfc52d96adf363c502f30edc6fcb7aed 504fc767e317ee865214245e1410a400133f52b83badd645c3d2f64e48568bb4 a820199ede446a1c1b7ba39c3158128193d1e6285a1c546d7b8dd9bcca63e17a 8c9badfaca415bc7848f951f197edfd7e4da91cb0fd14d177b26b82c94063d37 eb82e30bf22d75c12cb67589bdcd56f9c2ee3486a1818e54e7b0e64bc23e00ea 489cfb0a793daeaa0bd62951309ea439d363bc1ab2ae5f08aaf8d6a0db866d87 db74a07a7f44f6262e709b945c4d8a21ab57201e3bf0e0571c022b8d7c927226 f347a3bf74560dee12fb32bce67c02e2ef61dcade637fb7666567d8e8f689376 0422c442ed56f7210722910a5138b93f885928562641477ceec412f895a6e48e f725928a066f1205d0a3c7c06124b1060d782dbcd5faa053ebb4c3fa376d83be eb0ebdf89be52235d34584264893dfed22d15019d0d0e6046f8bf35afa1a0f90 1578e3bb1eebd60e77205a9cc7ddce1d8cd994d8c0a57c683444622b895c6c42 d5e7af099509b7e97265f92f9a232c2c14183886209f9e5e6a9f04369cf87136 849b1e0918fc19c02871083ac8637df704b1179f03ae7fe0fb535bff7aff3d9e d258100a0f9aa386969c161ec81f8ba8eb5c33db0a2b6318dfdaf1e212652c0c 6f4e276c39fe940712737352d9aac0d872a14bfb0e20e8adb912ea9820a772af 1ebe7ba5c7d9787b4d448ee29f0b5a7df81886be38817a75cf099c1cffc8e806 a68e5c9414aff70b56a736ee21682beef2c8a446773abd14fa65ff4d9939efc8 76a2a0ba74d5786f9fd32f0e0e4ca5ec9c2d915878f629564b967bead19d03a5 e5d25bcb19a15506ffb8ebda3168a847cb1a4c3e1c883593963d0815926601ca b189a35b6584635e2ca225b99d10f935e5e2d9aacad94deb7159cf41c8057ddc e6af85777638abd5e11c416ea03972b4a874358e2b3d64dca64ddd456535d128 7c9ec2eed774675459197aaf4e2180bf8e9bf80ec7a0442d5f5659c71fa2c897 49b298e3e80b9c0003008b62cd6c5a3cc7f4229850300fd5c48fd2e24dd81650 f95d9552653ba4d6f3bff5859d6ad269cd7291b2892001080888bc619dc4a046 3680c7fefe69716f04f4314f8b409677dfa82557e994d65693dc7d7f8ae5614c 6e506622814f5d90ec809cf2302d5cdc275f29665009656fb1f941754c649b3a 667ae2afbe462c765f0b8cf5d2e9bb5b68560aa570efecdad57784585a1c7720 2890a34891ecbd6788bb47aa0681962cabe54f06ebc27b019408d7bdcc6ba637 87bb518c7d847f9fc2aca39317dab6b1a0c75c091b9f22a7f1848364b34509d6 0c838af55d313fa455f90656f7c7d97a1ef503417a97a74f395dce0524d789d5 6ec977027721921b53909973a702f24a8d366a45f0436a0113d7cce6993f53ad 71ba0e015bb7be397b27dd1789c94c4c017f1ab681a0d3846f0353a85d057293 64190fa9576c454a48d898256f23ae30fe7a500d09c68634366b5544a5ecbdcb a32298df698677db8fc50477a0043ff3bb022d27d63fce6de0c913fcb14ac637 98a1529478e55bf403fed1a009503bcaa71391dfa83e5bd0d1c3c74783c0208d ea14c8daecea208f07aee92f4edc7e00fc5397bdaea6c5a486036c517099cd9c 7dafd59d7f155aa634a26971c4106a24c172a30cbae48bf6ea1b1d72b6dba1fa bc7967c001f400998e18fbc53da60ba187a1480b731af2e09762979f7c4362d7 6ac5b82e87191fce298281d4b3520025b0eba743aeecc42ac9d218b30a781d91 e8c482ed4b62e158ae0dcdddcb794110c4f73c5abe540ec3fb7ccf8a9dab3a74 f7d52dcf00ebb2810331d1278b4ba03b0384f47c0f89f92e8e037ddfa03054f3 f123cca20321b7e73faa51c8255ffa7bd8266b1a39991bbbf8115570c667a306 ed8980dcd37a86d7f7d1e720548fb6ed8bdf33da32d8e33f681a93f6f5459883 c85766a5858537a13822419b9af7136875a760e4dcafdfe13176755499e5fbdf a3a94fb862d0e1c1867d46b6ec614a9bd6ac5164e8de19e29b8fb38e2a6436da b1fd45e36bc57e1c8672f4076dbffcf2bf09035dc5e4c47f14a6c01eaf3caba2 ce5e1669abc0c7f060ea303f41aa1197b90facb7a2fa2204726e7c57ebde9665 cfd271968a4967ffec462606fd7b195b03f2af58de867bc5278657a33f710d06 e3d31e9be390c1164c32441ac1fcfebf65db22c2d3b7b29f4e054894d854b217 809148d336d7f80f701a80e5eacab1de50f1165d03e5e352a7113d6f1efc6a2a 971ed240b6a0298187f27d4dec358f401040830673b07839f74e5ce7a7c82ff6 29618c8aaa9af5c68825a87aa8be826876e1814e854c86b7d76933b449d2d279 26353026e1c4758ebc3c432643a7f611590ab32bd7710529f2947d47f98cb072 0cc7ca72f7c934e5334af028989c07a49229fb00e4096c070dd24b87c2e2f690 c814ab0bd6e63cc3b2d7a6695dcb30b7710f7f2a7421ab2871ea2a4b5a9d5f8e a0b3bad37c0e765c22ffb2a526d0c2b8111f16e59c7cc3be7e6a1b07e8de767e 3902bb51c23ee908ab925e56fe904b5e661fd795b4d0ae83ee111dbbca78a819 10546ef941398f600a29d7eb6036bf371b11e4ebbc953b9c5329b219edad3b68 7323fcd88ba69cd500283550e1fc13813d73c6c8927e3705eccc63866bfce833 5bf49f286f1292c986bed0f67522965665a461c38852786845ba46ed654268a1 97d85e168d5987d1fc79b0e887aa7611bc298143795e9bc346b235bed1f08f46 ab25f12c7063b2483515c5b907dcd34fa0db8e94ab1b06bca82a0a4d7a21f166 b3f3794b37a43820d44a689b2b7b1a8df269777a21957f91b4308d2cee66e45f 1117043a0689cabd1960d1ef742bad37c510731992d024a7ebe7a2d63667e7ed d5525971a5cc476083846c310e77ceb540ef037fe181acd00afa81e29b67ae14 5db681990d100c409663fbf6e24b487bd7e4e915704fd0d841508630a613f097 56d7cceae4ef1712eb95a782dcbcdff8d959861b9a5ff56d395f0b2d34f4f12a 017ae0cc1fedfdd445b4fef15938cae99abdcd0583a188e07557fe2a65842233 4860520043dbe07024a476c4091dfbb17e8398ef825f665aaa11ed63a62a4b34 99913d4fa4a13a2a3732215ce2adef2951d4c4fa31191c62cc8cfb5555e27d23 d2d029ee0272ef1ea773fedbd8c464a1858bb4238198d2d4121393e6c8326b3c 87fde213731057da37cf5701dbdde968af42a328079e52157e56a4b2b6c95cf3 7b416abb2b0081c4205a614f1de524752cb5729e4431f28086ca888d7cc87860 38244112fd3bdbd05733434fd81a649419f413c0a8c14bb52263a589f0a73af7 63f4dfb6c5fe738cdf13cd432954f590bf00b4e81893ccdd5b1696e0049c8d58 723e7e3418302ea27987ccdf280ec556ad72cde3cb2a596f3349098f27a794c4 05e2cac03c8b1b049c9bc473f0894b8ba9b34aa506831e06723b416140308133 59d4102257ee505cf877a216aa22c840b7214764532b920bf8260a7f58a5dfca c4f3578faef7a4ff279ef30a71a06f56b037e0231c3fbe5ba778c53d524b101c 73822d96d4f8c8dfb37e8eed6aad9f19e9466b0871c917303957330d900dcbc6 ab3220323c42fac9e304170080e2f77315dc5ac77d46892308fc76a721c5773e 8ebf74406a07554db8abcc8713a23b3031c99dd6d232d478ccc5ab9fa54e4a53 59681c4bd7a5cb32ed92a2b1d8cc6156199921a4f7696d03eee11d3dd64b86cc 2a5e0eae43611e232226409667f02d74412cf4ff1f4b7135458040d935462a31 0bcd81359754353596e7e67369dd00812a607c48d6e4db6141ea84a70b9e9d30 14331aeb9f5a2f2128d40fc738cca6346ce2cb2df0df94d068c5ba0623cf7c65 fd07c4ae1e3fc78b95d7ac73a73ba18f6c1df405d28e3661ba860b3030a835a4 39f3ef8784ff04275a988836c1fe13467a3b2c5c538e34cab88ab03745531cc9 7144f8f4e2ac33178eecec7ff144123605c1f1303773d049dbda8b2aa34f163f c40805c5886287f2d2d7246128b5f64eb4f3d1428d3605a06ecdfb7ef66c43ef 059c6721140ae041d768b7384689981a13f998f5e19c4bbc03df95f8d4fa866c 9e995343b7855a18d916a9913aa7598b7b108ffd35e00d2510f17e842e71f45a 7d8a69025c207109fc0529fd604b76c4523ab439b00907445e2424ffffa98f46 6c568bc59db99d2ae9f78813e483de0039137628715e481870a42215502e241b 9972c9e517db11d6ea09e48c7db0222e64da5e7df3f78cebae553d4f8a0d05f1 3238ce4c1788fe041a12cae1fece1b6e6854f9a8499b3c09a4a08365dd89ab74 1eb6ebd1d5fca4b4caa9a1e08734c15057daf9aa135cd9b5c81b6b9838b690e1 5f84f99c4afa11c9d03111be7077f386a34869930f1c620619b296f297928728 ce6d586bbba966c28d152af4644e21f519d51a074e9d51d14aadeb500b4171f8 979a86122b24dbf7787836445630666d28710f38622b2372687724884de8feab 2d31c50d507f0340f5428678b5339f43e677c4a46dd9c3981a1a96cbaa251895 528d682b3782df90300fbccc325f62f11997f660a168444d69718ccfdfa616fb a819364888e956816954687dd809ccd3a1aecc32000e7a699a6c24771dfd6cc7 6a720408f24f4a5c0bfa9865513f41fd9e55c5bac0d3e7cdac06a7ee66fb50d0 4fce289cb8c7b82f183ba968834165040eec796434551de337d05b5f44bf0e7f 027cc53385b6d116160036a9ecddb3434b2562efd45abd0823839b70508912a2 636e066a5802d9504b86f1022b5a8b93474918be38a2962de9660d358e0094e4 c509514ef85df5dd5a66f619c963b5684878d1290ec2976e1702963eb97c794e f11e96dcb3820fc332652e6e973399f6f0a990ee88ea90b1e3710161bffe6797 c5e990f41806973d30789a085ec52291431d3f66e926c9a7b0fa50bf7b234f87 281463828afa2de23dbb757568330562b49c3b290aea675e47363fa3918b45fe cca71fda3caf010902660bdcbf6dc15faf08b04b345bfb6d4414f3e019a7bcee bf57436908bee12116fc88573ef538ae22699e66fd7d10304c13f5c83c2f0a1a ddc2e241acac4159fc35e49a8937afcda1c85e92ab47e1f659e7df2053ee006e dfa9a0dbeaebfc6948f685d905180e3dbe629df2973c961e49224cf1a104c351 846ca19fbf02abad29916e23ccfa80d7a89ede3f441ee77becd2a67bef045094 4849b1f596c629fa04976f04f1d1b797da43f6ea4130aeecc07bab8b37ff047a a3d2d94b33f852cd770fb595ca4c6b1fea367dd5c0fc1553f9168b94a5220fbb 7add63f8fadbeb00c6be6be1c36605d026c141cf4c3cd38bf83bfc296d99db48 6ee0daf17d82d17d4d53bc0b54c255e746592caf7ecec281bf0a44dcb2b5fc49 3bc952eda5f4687969715739a6892d53975a0f6dbffa12f8adc2eab46ee29d6d e5fdcde88c9d6175f3ba2c3e9a499033ab1a5419a70f3b6ed2d017c56da92f36 e309c4d435010678c8750dc2b3d8d4e250ba9fed2a2d7f46668878e31282853b 391f19c85ff9bd2e38d97998a41446207b044c6c5293f50a7e47e4f11edc2cbb f1f226812c18c243bb7caa6420e56b85378842dda40b358566f6dfed0dd0d48f 1c38d642cd012bbb3fcfc6e3ae33f0d3a9ea0f5dd6f7d9f55b6b51dde70d3379 0e7ac1cabce9bbb6012f866b5457ac146ecf181df31a0adfed70cc551f33ad3a ce6d87fa0d789679f90f97bc0ba84b149907f73e90d31af191cd666b008851b9 d70c3fa70104ac187ff11e87c88c3d439c32e1bd545e9fd03f0f623b3de40742 7a3b502186e37eecabcd2f59c5245787f4c9b9eee5fa5d41a1d9685bfdfba5cf 29ab3109d98ae17b91b533884a50a6ce720ff3559b94991d9a47542a7898253b 6401b466925bd5e24859cb228f22e0c2d3d1cede7a595daec5b53a1abeef7c80 3d084b70ca1190fbf49fb87a7256fa81af5dccdda264bd0fc4e44e9652c2144e 8739ad8e09f754b81cd511d55fdc96f09ffe2d036c7389014eec318a4090e7ff 1d0b13a09908544823ef82bcc0ee0702f771677396887243e9b855ae10fa0d3f a0dabc3212ac005f328af1b67f3bc40bfd568a3bfe23ff1d17724a2fc0a9b3f7 47ab08ea0a5d1ece88d24e91608cb486d48e78b428eef7d5af5b70b804458124 532dde7062bb3ac560c7341edad20cc4b3d1e55ed5446189ac3ff1bfd6e1b375 c26be2d6baadc86a620565d30fdb3e3875c04679f5cc462fc090c2ad1e9993d6 3f24a8cec1584ddcf6a36f82e21f5d5d3d14bf5fa6693d770bed98206227b5a5 8c44348acb609a7de70b5b3967fcc350f2a6e6fbcc3bc8e5b3c0d3d85668299a b0fc060e8f9c61cf0a65d96e40fc1eff32f878e8efdf2b9aee1802900c9bb812 a7f1cc91a33b8236620adb78493b4986f6baa36a9fc0ca39de708aee8b03a9d3 d9f2debb03723b5a5fb3f1eaca7d757cc53e6a1add37fbe97a44c6c995697d43 6c8b6bc336ed423fd2b8c688355252219f100ae0b3f7dd49715d2fa54f4d2dc4 0a5a6089033274496bac02a0be66293bc08a6323a7a9197cb5ee8b881b79b91a c6c7e200df00a5c8bb5cebd4819272446669b1a55dec6b46f9dc395ee5122518 317183a7f4bfebf4b8eb9d45abaae34053d561a29d4a18fffe4ac424aadf9a1c ed2719e979b9f9120a9fb07010dc60d4801a2a7d0988a7f2cb185693ff6dae22 93bf867715511b241f220390ea0ddc19bb430ebcf0197a23bcc866174c9ea270 f811165233275b8883df148c4e0aea9d344c557c965592546fb35057b73c9941 6413323625835409b033e73cecb47c414b7313d74c0cea45b231b9fe4371095a 4b3494d57d4a869dd7ada0b5c02b52c6eef052a60160b6a61d05872914569732 b8f46e5c2b7e79fdcc92aae87d8fd60c8178dd6e771ff15094a9da652f8269f9 195b6edada34c6068401ccb49b9f9caabcd9b51d59877ea6a7987253a7c570a4 944627fc5a0a7390208233ef15712c2e4f4fb0fa4f13f356e6d5d226a4b028c0 12e4921b4627591f5d4b9c3a704271175ae915d0ae8d9e350a225ca2ddb6902e b0614048fe6f4850dc31eb26140d577f367d022ad4fc13681245152ae1775deb 55406f7f4b2325cf39a34f916591155d671605c4519e4329a0f8e468805820ff 9e9a6827fffc2b03b4dfb4a018616c99e3bfd904857fa557316c2a16190ee91f 827fe24e9360186380c8373f428be2974709770be3040afb6f165f55cde6cd98 035b5472508d2b6599df3f46484bd5e2b798b8f2407074c2b3c5deb7ef7d1bab 36b3c7034a6a0bce5fffb24e89f5b34f52ec666b6593566d2bb019f12dd1d5e3 bd3fb3283305397254bdff0a0b7eea8edb3b8eb624a59a05d379d7b9a75d9482 5e3646050305256601ffdd954d32c7aa26bd1ce5cd64bca3ab158392d6f39813 3ba181568063a0920047f366be38f8e73eee814cb48b90a01f9496ad8bc63bbd 572777dffa2d63a4078122cc97fba3e8f9eaf0da391d436aa82d93374a6fafed d3d57c5790d18da0df8b9f8fb2be00eb3ee2adac775e5117d86c0084f3ea7787 73b4509bf34adcc3e4bbf20f60eb771c173f906c4a4cf5e59a1f74c29d4054ae 822e5fd7ecb36e2280d3fb300f9e2d4221385f421231937bfd634c5873892457 0ec5b38fbccdb87a07423ee0d7e787ab152e61cd4ce85820c22706f6d899a63c a5b289d4e5a8afcbc5fe71209e9af3b0922e1a1dea7fab4029932d1e2359fd34 dca27c0e7c2a877dc3ef1e000b0bd9d74eeb9defb48fe33ea19b185eaa551fbf ab288d412f5928b81ea2d7c772cc91414280a9e4ec5c7c3c8bed0ad0aa446fb9 e6399d35535d7fb50125496965791e751a906159d92920e21c147ff920a7f33f 265c6d002d46892c66a22a3ccc496f74983690e9d7a00096274ca4be1ec7356a 0d0d5998b3c2bcd15787e24d2c7325aa7c76155632d68dbf57461665b61253b9 0c3691ae2daabbdcb784ea3c0f6f68560ab548a12ad28e2bd252910ba78ea4d8 344bee7a3fa92be3e138402eb69ced23c34a94d7a60b6bbec466b156f286a013 9c76424430af08b8f5ac377c84660321dac7c87b02f55dd69f4151142ce7aca2 197ea5230ad5b754b94de2da099a842892266157d403b498a542c93a642d38e5 42ceb7329b551a2ecf1c3377ca2490dae242e8d92359f6b5d619002bacce37b1 7d24dab492d677ce092a87be26a245482b7e89b79205dbf76c8ed491a5c66518 5465ff982b133a9e1281c0ea318f7801915ee2da70f269735a0e17c7259b641c 3e31784aca01ea6728de1110ac04eaa9099348d0bfee82f920fbc0d53e1a587b 54dc85b634b92b67b53a63b955f5560c600c0921e7a788a826f0109e4db5013b ef2117c227b0f301500939f2d255bc805f066fed8117f16431ec7865015b3502 6bdbdde97c4c53684f7733531bd5ff5a0e6a0b5bb786fa193d1b81714ca99470 6574c7ea90add532ab17e8218f992a4be754579159c77e1b1e0c025c90e6c607d79db51a387cc6d1cbbba32f914ec953317c8915da7a28ebdb88169d99f8e70c388bf3d7d4fad9c11dd2c46f3944f378ab3d2bc0e1db0393b2a611f74de32e0b7a7198a0165d43e0fffb81c2034e5a032a9214c90197d25a021054498727ca07dac763ba6c2b47a30ac3e221521ec6864226cea23a054367fd67daa2b3fad901d98a68284aae665c19f9342c8293da2a1b2efafdc071032e2eb88dcbe587a8015125eadeb0fad1a0d3f8b5e71c477c96f0d2c97a56bd819f96748514b97205041eb159a2e4c861ecbc012ee6ba2c30ac02e7759ac2d932076a2d9713ec049e041eac3039f8a2965860515e700c9cbd71d72ff8665dfaa41e676e319783d9a9094bd0b6a4e560247d344dd5b006f091da0fe91bbb672295d82cedb8750ac3610dcc704382a3b118d1846af03cf3b699c9b240d6e8f9efe1a32cb088032d15580ce8c4d5813e6008cb3742e9fcc76223b966f2a1a64792cefcaa361e5b691c05024d0ed6bb607d67fb22d853ae72d9bdefdc2804683042a9dc35af5972f015870c36cf7cdc43228d717e79deef034cad0b8a30aba230dd5497ba18f533f101890ae402d83420ee249fd9f988649e2f58ec5843f245e6dfb229893fee2fff4e260395fbe236ccf24bc01b937efdd49b1adda3a86d9a8a8c34b00c29f679ec65950a47d23b47a80d42c49fc0af826c6f0d549ffe1971017848fd8148008b060048077ade0b66788c3dcef70ca09a6731f97ccce3207a9637f1ac5befd5bd34a546087966d4a800cb5ee22a92a6749cbb941e2bdcd078857dc003e33a1a51c0986b0d527efdc308a03b3a0ed935b329750f093759df3cbb5fc680d61a1198ab61a30cf3a7a1b6778498e8e74d42e5b1f138dfdc50069ccd566a42966955fb4abda302d611addf86710e8e1d7acb0216250658cb22634cd0a6caadf3a700f042c93b0364c9ef395cd3da91ab3074771f0b781498e78db9dfb875c6b371f88fae58ed00a6907684aa6475bc07809ad920ede6c548a36dd02ade6b69bef5679ee60ec00634b403e5b14020e4b271328de7eefe5aa442381343b871282c19cf4a90c9fa0ee15a8a53c96741363d05f736f9bb56185759c9f0728134a3789265eee027cc04b2bef44210f7ccc2850661e1e54f60c097949acd0e834e79efe7fb380983b205d90dab9d57e6a0dae8b7b8e639612473d5f8712c45a6854bf685412d6e08e00304e57c661176367151002b4bf745ed242a0e0b8d8201669db82534449138ef020c760c9555438f48abc355f070c9c746054cb0391508197525268667365fa807105ac420f6dffd08d7bcd2c3e6cd4ce2be13b5235e977f23e51a02fa9ac56b0b8e6695b1568e83575b4ce420486b6ef3b4bdfab73afc75bed1cf03ba895ac302eed9dd63db96745a44efda268188e96ae9a124fa24ca4a4aa66f8faea80d820336976be54bdd1002d5f42548fe8bc7f127c4b059a6744467aafe95266814840ed2ec7fc9aea084f1b4b48d1305b15fd0bbed6d4a6cd7bf7441a8bbfcb5942c07ce43b6cddf00ca0724faf4fae8fa2f959d3d63867531526f90bb5afcb3638c042d308a1700deaf49ab0bf0344633b860afdfe47b41102925e8a0eff12bf9ec02380b16a5c8b6b7bae6dba854829bab8651e41753e0800eafdc3466a08244710ed8b2c3dbc5592244d3a88d09d8124b85b39627ba45ff1c35568b2c27ae4939050a6472203e93318550d792c43e92aca7e5eca4439d617a49c430bf224126f30818b76536524d119c81823f5907c370deeab707eecccf22dfb7d90657c5ba530493c224f6500eb65b0b02585a1ddff1ca326bad311b768fef98de94d1b8241e07cc5e901331c3e085b3803335236aac9a312d347adc82aebd41e66391ebdd670d438303bf8efa18391d1cac0ebbe0303417acefa53870e4d7d56928a79f5b18022a42bafd1cd66e0bfa621652d599f0d55747d16eac71a914ffc978df21ccce01758fea0311913ab3c8e2ba9f22f860cd7132e2c43c6975874a3c187f2eda39034d63ee0baa78894f4d24714699eac0039ac7a50e6ad215b26b9ff029c6b320028b7e45d6dce6574a2ea91ec4f1fa5c6af9fcb8dbadb0592f7f1b99b522d34207c53b55ac96003831b79a768cdbb1b976be4c955cbf65f1bfc7fe94f65af2be0e85ed5c627428ec93aa4b0742960ff34c915c9c5dee8056e5698720abfc316108b272fd538f2c25e25e16608ac6747c9d21d077fd0196e81ad002ef9d9a87380ee1297c7f0b3b875fcabcbbdf1dbc8774dc12855c1e750a08077b3df6a87b5608680ca8af2ee893ca260213ab79be2722c8c5cf409410bb170c62cb4a7421c008c890c27a318c2ae8f2b62f1c0ccb0bbdf839672776026df3a79bced8a4f0f20ec84e1d47bf32e7aca64e43c2ff8349d00af3f2d61a8ce8bead082d4cd2fa750b80ee56bf43bb16701b50f3544b77dcb0ea88d631c3009b952bd099574848a70dd98cf7ed7dbc893621be5bd97e9701ba50f0e157b862fe9f7e4b5fb4098f7302ffdf7ccb310c42b05328ace52cee383c8d1fa4c921492bf005699537c40c8307bb3cc354268589e7d226ae2db76dfa1381539e66e072cc00fb3d7ed6fa78ff0e05f566103f3789c8b338603d5bd7ba193f35b8a4f58011c8631bf8ed7717460a985c0083eeb41939d3d19f286e0e424802f4763e1ce8bb0630cd04ab5d001101523f7e5b1ac7390483afe3c5d89053d84a2f48e2f34fbae7f7b7bf441c21fa0c6079f6becad400b6009b718aa2d335e3baad5d9e5ae22282cebb702f18bd5b0cdaced8d888d5b06db79fbeca7ff596034782c19c8f269cfd9c456bbe67b9fd05b0228415623dafe4bab86d378e42e60c713a26819ae2067817eab824e9ddd2039730c10fe7ad67896ca8336273ee601b46f3f4f5315df0f10207c45b1e0a1408a4d99d26d2e57682320a085dc673b15c863239f3dc17602988add7a3eb05ee0f148917ca318a6bfd6e926bd7d72235bb8b7923d71c28cc50a05ad04471adc20181e8d718c211125307e32cfeb604e668fbd16c36fe3238ae93ea9bafe1a49b0058b7179b1264155bd3efd5a3f66b357831662ba9fd703f52ad87af43ce03f9051442c8965674bf02fe138d3c7a18b39a6d174ecdb858547131e974702985e20f26b95a51bfbe529a0b3ab1f95a0099a284c8a8c60a2b710f18fb8f3d1d689b042e9f4a1fa9d3728971178fed2b71130a1d8299061307e1431723b68278339c01cee39b08b9d1b543d7a8c69ef725208578ff893475b967b862c04d63e8400c040b4b2ac25fc44464e312d86c004f68c1ff83fae64c694b3699cf8be0041a380ef42edf932377186d2499d4b07e37fd61321164a9b89c7d4d7f9a453f736ff60b5b9274fb356fa7eace6c21da9028228d5f6e0f61cf91fe2de19a3235fe28ff05fc077223df51d769a1acc61bca6a36e06c6968d85f0240858b7e54a8ef42aa0bb0b547783eb805256bf2a8b6e0bacc0e8881eb20abb630488d1168bc76ba460b0c20d82cd57326b419c066b0d316f8f8d88b73a864d3db84384e4950299e6e076b3e5c48410274e82e39d4b7eed1a00f8bc8501b5ffdd93169ac6e5fae9a860196c7b843de2f086e627bd40a775ce42d76b108faf1a066b010263c10c173430148e4f97394be97bcdf5c5029cc8d70bc39629812e7766ff73c37652c10af360677a9b8ee5550788d46a02150d965a78c1b9095da18283d732635715f78c9690df6879f44ee2a8145b71a8306d1bc27acebc8cdade42013c072777683d8b7d00617663009d1178aba6d544c2dbf741b4f6f2dca51b171d906e5ff09920c21090fa43bdab26e65c4a8e8aa6d053f14008a6d50709bedac1a28c33157877620410917d5760480e0d2007c9e4871b947349cbcae81bf5bf1f66829304fa5013af90e48b698fe10d1b9f4974ec20c78eb86d15129a70f879b54ff91cf4bf424f9b2040985daf3493898006790036ad7cc033c73490826faa507a2407f3ef9b994ed0cb13ee39397da2ece753b5e82cc79b9199154e0361c0a026ebfa66efc7f8c5909f35bf4296dd75a5c37c194521d2a268f95ded22535c51d04c6da379afaab9604bb17be7d4e5ab4e81ce51a19f397c6230c0c9d6404ca9472e4842bce00bccc0af4cc8a6a20bab6a551db552c0592838660db7dc4e9e85093f3c0cd90a6ad6109b65f99958e002873b7a163685738d9edddcde3f9a412b31510730ad6673d46014fc3a3f5927482e9d3cc1fee75a782465a09837dfff95baed79bea641dc31f09629c50efb1705cdf2919451b2434579136c6d456f72d0d40f5c9e7035a9ba20aa09ab5c6634539480e7d92fc630406bffc031298b93ecae9f1b89b72a6979a09318bf4c00f30533ee6737dfa86d998fef55a2f83a7bbd67d3371086ec94d150a4222f7f26f895a8a9ee8aeaee9a5267e825d0081f1e5c9883a720cd13a40680cf8015c0f317f6ea10d0b08c558706697b6feec3f48990ba5ff837116b1cefa04d3994fe4739f42769801532a616e7a50412feefd93c459b2acec97499c07ce0f8b47b89191e729f27e30ceafe883d1f436a181e1699a0ce9cc18777b601fe008e0ff102a75a6ec2c5003a2583fee0c5e56987d3f4c4f8bb5b5177729b9bad002351016c31db3ebe62b151664fe5fc2e5fa4d4c3116e8ef4f77108025986240079aedd3f12f49c0658216671ce28424e644168eebdbf2408e6ed94f640a7b7d0a48e981e9030fc1de0409026cb59a19a82854f0eefa2d280d4b60a46e358d680f331ae69c5191053d94dd92c6f851aa9e04428e615adaea0c00b2e6d375d79b0e43b8bfdab96deb1c354a702f8e0383dacd3e941fa921dd035e1dbbb91283440dc060ca229a49601e45c933dc1ca82a26ed2f6ebb7f4069ebfaa142ebe26cc30dbd10ed88d8704da012a7bff2beaa177bdbbe65aecc14317c5fd4f30b215d630a05893c062aa7592ef0a1924ea74fb108c65789067d1349a0399df6c1dd802a01c4392e48f72f1c10b4ef35c1bb66f2f3369f1168f23d425a8babde13e9e86400f2c31b9fa07aad174139153e07c23a43820fb1f1b621e9820bc9bc3d4bd5be09dbc0870c73715ba44158cb1589fafcfaa8bbe23f1e0216c658054965adb6e60ab92521e01f558d577067134015beada31dd6898f24419508d59bb8c09190080a9cfeec60827d6025bdd30be33eef8cadf55bd5499d93bc697fa4a0cb3faa260528d3be04734a3a772877a42ca56838a5d9b3f848a311daeeb373d958f37e63078a30c18cbb0430a5c1655b8202bf613b72a62472d8798b85babcc20b5ddde0067e78c74b85fc7224617b354771e5eaab6f4fd4c94d189d2bac244d4e7eec6a04522c6cc1a4e5cbeab8b0ac70f843c43ffd73e35be4a7ef0d971612e89a760605e2b4cd237933e4692db1642747d38541fc77d8ffaaad2bca53c7ad7fcdd39e075e39208d9a431863a3ebaa112d567bec95fc14dd96b553c71907a7f086a7210fb3968719ac7d86f9e1c6625399ce0388fed307df64caf5c4600aaa5956165b0702e3cc1ab0532b39e43fbe1961a2de0968d947244dd7ee990f247ea0d3730c006f670649bbd4d5cf38be5799375a922443dd81fbff8ee615d55deb58d56c00062688a9a67a6520c49bfe2a441351a57918c6ac9b8dc6ab3687a8563e6106630e32f07186c57e2d9160ac42afdd875a4ef45fce978551e7cab19f328cf99ebc09d69e1b70349d9ea9c22aded1bcdea723cafbb8e3f143ceeb1204ffcebc6e6b092009cc4720a3be9ac89387c4e73b4057089d021d7cfdc07a15ed1b8f71dc160356332520174dd9990ab8d34161292dde08e6f3c77961108c20d09dfe3b52c60875bc437be1db6822e0102bad0d908f7ebfb172c724ff5cd1559e4bde8e22d505f251a919a44618480fc6dbac82c3fdb340fa042e010d9dc6dc59344bc379a909881face2d2a544eecf1b7f1f0c6f267d6003b93a41e3ba21e85525b031b28f0572295bd7ce62fe348524e2136a542ce60ee7e81a666822b3dabb6cfac498b70dede6fc207764d734a64d0f7b68c9c5722651f917990cb447915332b9cc9c71076065f580cedc3010a4b2e4bdc0593718edc01bd6aa1396698f634051166dcd02cdec8627e61f211ef1d377a00a7f846fe999fd26134cf3f566d9aae5211fdc072e768ef12202809056ff599abbafd4c5b7a25a592fc0c16a6a50e4e737bbd3036400564f08050e1aca147b33ce3c30de48bea1881b471b311a7776bce851d500f9248afb156f3871644de712d40d901334ae2d3c043a740a5c21717cd6afbc08c712f544f2884f4d82af848a15761ccc259380589063526a93b2fedc4543ef0f89993a7f5adcae5b6e1202047b482c9c61646924c70c8464575158963eb3cc0956ec2ed8878b2c838de760dc3863fffdc9b2058087ff4838fcbbf50ac49e4405f16cc0659638797432ff56f010d8dbbc3dab0149f424f01a29a95a2a6fcf6c04864c45496b0fb865512cee810296a5525a085aa05f4e241f9d0e132e0f3692093dfbb5cb614a0c4fc4cbf009ea0b99438b4f4f3c1f617bbe58a4c6b578b9f9049656e5548f58e2613d75cc01715c14bf4e7dd28c48df6a7ffc726bcca360d50d68314ad6f5120cc3f5ec2cb578e4993627908513fa061f9b6faf3f018c596b08d5586693b2e5c5754582875714975e9aff44613c0f462d56feefd246eb703408c3ce415c5f244cbf1b1d12e7c6c585a01bdbfcac1c386c1b17829dffe13aa80fd3e357f44195de100e9d3f695b349ddd6477e25cfbc7e6aa3dded90f2137eb0e9b839c049353ee34152e70313212e007e688c15c72029f09b6a4b41d46295209f0c2432a0e762b3dd266565ad4d6d15b27e50ec831882ec85f64d6524e7ec10586a00d662160071535e89168dc248cf4ae7cc31f18e21487b6a03c90e738520f2a577a52d5b89af200a22ac083879437bb510ba626320a912a6425e087171c0df98ed7436a027f9482370440340a67b22d519676e5b181ff644e909a14c30904afc293a9f5374c67a93160c0cb9ff5ba0476d7d915b47e4d453edca6357a340d0050cdd26b45d8d81c453a079c8db3d3b6e5287269031ea01d4523276d142f005d1c0f78fc5c44bd546bf0ce0a8ffc514f0e7a942733e32b514b49bfd60a770aa7658a6627b81aefa120f574f51fbef466d85fbbcfb060f75e9ed8419a55700cdd948e9a791fd92eeda363137dfb4a46290b7827e0bea07aa5b93b431375b804261273bdd2a843fb62c110fccf9395aea73f6cdc6c4ec74411df35b4fa7289024adf4a719dae9a539569a4db6599d787e02cbded7b61205e0f4c17c23bb85e0f24394ab01eb41f1660c00662754e35c3c4f64bb9cf225ceb448c135051243809fd469571f4f155a880094e6dab6f79cfffc375c2ee2edbac1b4081ebf833ad0de996708d7b0c8d312c1781081cad3791def4bc6d61c1e9ca554e2483ed907804b457e1301a912279625ac841ada755c1b8652f65f8a229c8c695402d6414e5046159ba45de88a3fb0399e5bab9d46fbc97e283de4a9cb18d353a7d1df57a3b0a37c45d5985c930ae9a61d9e3c3308574b8db6ae781385543bbf212545c9b0a08af7a613378033f86caf2a598f4a8185e5a724fa6d6a1c49e3672179698e85f01d4f31b0041b96c59c1a7fe185c43f6c7f79ea943e402d0013f49dda188108b0ca140335892e9e67ae887a97700ee7ea2384540cdac804f9eba866fa4e7344a09c771167e0810c7d240ca11dc83c30f65354160b2bf67eb2d585fe5088f60a90b523bda2922281dbf1073a91746624d50ca04ba5fb753714fc724cb9f08201508214f86d04290578ef0ffa9bcf386a74de796f7adfca6a91389a15a9db0fdc40ba54d9d546a5da435d9aed5ba17d3aa0527210dbeadaa9771b7537a1880eb24013176c17d0f347b0603f4ceaa58d31538e4a2570d79efe90f3de72b520fd96601c549452372bbde8c8ed5754fb4b1b4fee09bb9270f7526de9cccb204abd8d10369375db73e85860bf4daee9ea65d58307c01ec44dd71ef2c90decbcf22c5430aae2c215755da71a8c36356730f08a312ea949144b42dcc494ffb37f426d749045910c212189f8be0cf63b842ef8379f440cfd4e13eb1a34426859a85469d4c00fe826d071e54c81afb90f13326057be51ebfd7fa2f72273a77a551fc580f210fc01feecfec5c226062b5ab043984852381bf5642cf3f0568132c87b358ee3a02cb28a3b2fa0b0d90cdcb22380888943e3d8744c0c8f1104d4831035937af9f0b2c010065e23090e4f96f6d662ccf4b2d23e6a3994e41da69f0b6d7403dc44f007d4dc1b3ea89d5142263391da3935a801a3b666f74bf7733335cd55b7f98c7007aa493d5364e0e330e93c195f6eb79fda9aee1840f6fdefa2ad9409910617b0842442dce288f46d04ad4e72929c1374d0025cbb971e59ec20e5b06abde36550ba333026c323c840f877596e0965924dfcd184ed799d2882c4bdc23a880776000274e28a5c8599ea62e91f1caab43e35d69676f6e513d5df265ad4d6a53980701d46e1b49bbf875602580ef3ffc38311d0d6942154fba52a1cfd888aea545700fc55d791f9da456e26a0665b5e9fa37d165fce814d1bbe7c3bd4b17ca08bc460f9bcc8f479ab8776379f43b4e182015cdb269a193434dac91f5353de7c90e7e0d49f2075b6c4c39a9e268be24338b5c6a45d3dbc178b80834e788e32079d1810d015804bca3566f28f4362da9df42986e15ca892ff1a0bb9c03cd3e6021e74c03f88548103c7a4afb6cb4df706f26ad412c5e35eb6b83e7e479cd37aab750b409eb04f68b746b722fc18b3b971c40553d9af49f61360a8fb0ca36751a726c6f0a7bc20208e9d2bc31d130d5ad2cf8213d140ba0ea095215fcadb33d2f2c209a0702600305ab97405225caff0c7ddd93bf04b3c36c37bfb0309b3c050b8e471100cb4d52cd59f022e0276b28c2d61a0952121d24f54d8e5fabbd00295f51fbf30d03523784a0dc69fb7e5af7e763eb58081c4ea583745bbc552ef56e0be040b80ffd384198b84d28f81ba72cc18abd2c7ec1931200c08062c1c2806242b5d8f2012c1ac370ca74498e79a4765cee7a29de977fa6012301d6da16f4f499d6f0b509923d4b8b09aea483ff261635696a1e3ce7948ea8865377bf78dd27f01f7cbd0e215f5f837a1ab10ae26d50b3764bfbb29e5ce93b9658ce7c569eccf13a16050c6e811df9731add88dc5b5bda5fd17d6dcc334838eb9e3945eeff8e36826192052528f032a00ba355f13bfac34cee4b84146940bef6c23c63963488ae620b42070430b50a7b03eac908f19259c428b08d10d8b4f5e67144949c1be6549fa282092c9153a399e6ec749df58466da26c95707b48d2801046c5c7aa1c7af31e85e0f56f41cfdb983b6080b612bf408a4176abc4dae9385654c7a7975ef5440b3a107268495c6d79d99a1334e9029a5e316838ff5055f4323d29abae6e42ba0f484095f5559c5317904b04e6d0ffe1f7805dc75b987476582354f642f79e124017b0f9d28f8f6fe0a610779a9ae25a53eb5cdcbbbc1085eedc3313847a41b15e1a9077ba6045bde9ab6a9fb576d985ac0dbdf54d2bd4549954c63bcd1f6d07c0c7f0add9fb398a7a5b72f57e4e831e4aed867db3953adf7518208e7fb0ba60ff9cd06b7df3eda50db9e0f4d8ca467ae6381cefa34ac0cba0bdd554dee41fb4ac69207430ac7a574894281088aef716227b2493065a062b937546bb2ffb2c43e52aa0ef05cbae45bf64b454ca6ab57c7ed808d479356477c903fe8c8b3d099037254099cf6776315a05682d86ebe596a345e40ae3d22d275d8074dae2633dd8460ef0f86e91f62ca6e98952f6f00e09d2d1a6036d01db043a5033bcd846081b625970e64fb9b188fc289ee61c2b4696ff3b4119e9f188dd595e9060e735ecf77d4a30d345820d1991debcb1823a9f0eb3c9a7bb257493fb6cd7262a13eb2fd747dc50f6fc6bc5a336ad0f5040f67890ffd9a7e0362825a0aa80f8eaea6352678873c00c379d4f2f3f805ff643d7426fbe1e19fac34254e75513690d343c57bfdfd7b015de9e262b25ce8e3c47136c17d90fe1cf959645f834fc2fa65c7727f0dbd4e0616d01eb262d97e5776e7dd3e4a7e783ef3263c2a9e59e73d41dd160c36adbb01836dde27aca1d62741f183599b85f6f7ade0557b554f03b14f71a8e5979e200275c2a81dc80b64f3f53e7769cfcbdfd4c9ad1b8dfee5f174f3fa4d7ee25a900ca8364125ba7141093077305afa3842b41c6ee0fef32b91c9b655f855e9dcc501c5e77e0e1b38c8a9b71dc8a03f389253d9a97193a3a5472257ec6305aa1e700aca4a7e23237d77f0b919edf0e380d8a3e9d7c03042abfed4fc4595443df6470f5db6410ef1a46bb45319f00171314d73c5565c3c85dc66d0eed7a52c3ec7d00d9c4eaab76640c384e8cc65fa21278b89c7da0cbee25f9667baf8be1a5fabdf037364ca7d4f347d890415bdfc151fb430c40d8a4aa228ef3f020ab5e384739f0c294fa36e411ac08f72fce3b3c2e9a5cb2f5a8c5fdb6d5898f4e87d85eac5370b129e1aa7039ba99ef81ea34b7b9549d5d2546ed70dc64f19a5fb26f7eaf8840e5ea513bbf9aca8462d0db78119baba8ad995f1978ffec53dd4edc93f5b18330214e4cd6b34d91f9201b9f457df457422c8b444bcd45d52107f32093797e0c4007d26cfbc521458e6601356a45554d456c66f0f399c75a7dc84a49d2f113ed1032e1bf7b7a30394fca199ab7c16ab7e3e78890d32c66f665ad89c4f033fe66a01456e8958e347a28dfd8995d1c5bf2568d01893a21b4e71dd85a8ba6f5f924d01a084a5ed00a25e2366d0e8c4a8aa934fcc73e2ee7d1228c716c47b67660c3b00168123c4e63ad3234e8e281274d8bc7e8a0be2c525d86a9639d21d852910210d4455d0e001b2da13869131c38972076403bb3574fe270ecfd47b60d385bc2009441bea4710edd0ca90b671f89513db5b2d46b2900ce42e95c9d8367e50d2e6035342e3e702b714862a212948a82de93f56e5bd2c3fe0b4bb9e853e7af3fac605e4ea52a275eef49866183f533eb8b3403eaa675cf262d46b88690bafd18d930038bcf4fad829e014929f4934481eacf943eb077374553ec5b5624be3a0ebbb06ec222e6833d4d6dca6eaf90ee766b0cda5fd040f5c77f9c4d594bd53f8bcaf0b0e01475dfadb034c0d9b9721b77f38e9513037eebc09d158616e80089d169105737daeaa26366b89ea7b9ec31407cc23ae312d2001ea5937377e49661d8aa2027c78c2f236db0d42460d273e4edf5a7b45c3a6f60313f655ae458c90973d5e01bac1c3d47d8db627f7f1f85f1bda702969165df95d2f66d6758147c0552c3600324e841e30ca18bace5e0c01313402a12603e95064eaeccd6fa870490c690e01355f79a532fec13cdd09187169aafe4c623102cf4cc39e747ab60db88252710d0881de3dc70026dbee1dc3c785332c15418ef65af21c6fb17e26f9c9a875bc09795db2488677347d7ba2ff7c0c738a95171a0b5f62308a249b8bec203cb44409a4faa09a0ab7262d864d4b15d967901c147c989a7640d3f6d2cbbb24de6c7f0cdca451ae4732c326be5beaaba2a5ffd471f1f024c5c09548a58f13f3818dcb0678b8139f96c7320947784beec04ad9b24e72146b58f70d56d71d5233e344d80f57cf44049eb3801625d09e538b1957dec8a233ae63ab30c138204cdaba0fd90513955109554d538266f0a1c3d24bf9bac6762c5aa51823af8054356a17cd0b04550211e34f39114c051c784222e00dc2141d7add8480f80f5698c68690311c0f0017465b91da26079b1f17aa6372a8bdf8d67932f3baad1f64b6fcb0a57f990e443f0cb35cb85073312baab8312066e3ee6d14644b42f9b8d06fb32e850b920d54920ec420a9fddc519c43e8d1704b1bd72e1f407022c09abc2103f43327250b5ca0cd69cbdb8536a1402e846cc0deb8ae23432d4c9f9c75a474ae3819b56405ab236d541be5582294894a3c691234fdf5289cc721c608801094a2b4181ec6026060a68da102f1f60e1120a0e0f74eb95cac771d87b5c23b1ab20a621cfa93033d738973ce692f6fca0d6f3b891c790574dc8add1efb6c5726afbb2b756feb0d8b3b87d1b7a452dfd18f0d648b210085f43be2b5673db4ec1ed077fb7a818e04a748cd211de5f551c10343f00e19ad53ec95b8267d1169319b4b82104f40ec00c6b5b51f08411600c56ba3c9968394d22535071f3d9964b6d9687f572cfb9b094b39adfff37cb229494564df2bff906b735db59d247278f5cdc0b06aede2ac0f677b34d8f2f63ee9a5b4ed7968d02b62396a1b6211e0ddb0cbc43fec41954b0beb1d5bce7c9e5806bda84130e5b97e2bccbc6ed68861ab42cbbd3e2e3af5e3061b44ff05520dd1baf283ec9695fb847d8db8ccbf536c6fc9eddc145f28e61d020a74d6bfb726e7c6f6e4c3160cc6f144d7d05fc6e99d20d92a369eb8f207b20efc4ad28230ca2711faf4ccc75937d9553c46987c2f9d0656e439d206165cef0b5555a13003dc93921e28555a66b2e0bb74e7ba8330ad10957581b9e57049b0038b2aea15eed52d716068c93bcc5241dc0c360e6d8c3f6818d36738939789750e455a10bdd1b2853a61d295db2d61b61103b56b3dbb7a9410feb4c565280f60008c410fc9d261e25af33902ceeb694c0e902ec5970159a57cdafec01e4c46270486b938592ce986333121315fe7ab5bbd6cbe5427e59328679bb7c01f3f9b620bddb31cb73b49fd8ea3b66e683c1bc96fc440b7973616bf21cb5f3d6aeeb1540143cffcf2ac64abd10d2141e7f3e89f16f0d2a5668ebdcee8f19d23d4d9b1800be112f4af82c92ff48e7b65b86aa07afaa0986c77b39602188084957bd25d5c0711418b73b54e1a7a3183816a979cb88dff90317f015d3e2c6e27cb08baed8e03135a480d87ccc31d2a9627c1baa2e53dd8f38c1782a119cedf877576b1162f066b75bfd854709a57b9f8b12466cb16d72635e71bfe38802614d74d4583ed72003273a48143211fb3be169415775efacaf0f9b3aa65fb866fd423a1014fc38b0f50dbc61fd603519c61dc4efd6d367e4bd8e5b05abf4fc594167aad6bb82a510d66017b8b1f5cc625f0b37aa75b6b413e5239ebc70235481addf60bc01957880d70edb5076e84a69b6ef16b06c473b51e98fa013657835a977fca84f737289f069635c0f029bf697abcdb0d5354608868edea778a5d33adf255651ac158ce7303457c2aae48d6d75df7552058e76870254e8c14c8abe3bf96160fdede8175ad00f77d9523b10b338934f79d3baee5c5814cdef1b764f296e9745bb591504de50a3af63516059aefb2af8d64f0211406007ebf6a88c4819768d777d629356c7e0b6c9c8ec227b3a418fb9dd6da12253bd9bed14880f35f76e3564be69de44ef501ed9e28af287005436778dff8893f1a2c1007fccaa05461e6ec7b4ac53dcdf30e2b43bfc4019f66fa27f9ca3eb1b715a383f5fb7102473ae44b459c0c563cc306780d3374f9c52e476dfa372602c4a8e88aaa71280679cd3a2d6e2b380071640e81d32b8dc5d3134ad8bb5f22898318c40e485fb758ac2b49fd647d306d305200ebab9f03f96fc52d4f2425806c4b47c3f44b36ef5fc564b0191e3274ccc93b0bca96d799dad028ba32ce93f0a38e08816830b8a10ad029daace6d825a450390b0dd302b6f4b58f261189bb11cdeae8e269778ad120e3d1f1e4adfda1386bb00cb8efb97b4737b05fb9e6b83725cabf5d6fdce10613db96055ebd23467066d80ba53e15ba5b821857808318820b959b943b24ce5eccd642fef8749a1fe0c88d012e9a0044a05223c0566094d2e7557ee273380b12c78610bbf840b313223c1a08961c2b3056e58ec2901629dccfe070b01dba0edb0d0492c14705dd37b242e207e4941ea4d4f7b99641d1c1d7c0dd825f4ddddc4ae90d5adb684985ca63490f04d83a7de60069a69674e34e9190b21dc2edf29d301aac1420e52006e19cdc4b04a2084335d9b4ede83a0ec2b508cddd131078a0eb345113e75216b793293aa9006be87039c822621e37906147efbf3ac4668f6d5cd7f8523b7cd387f036e73006ad5c935ba8d75696941a11506b86f3cb4713cda59e20660bf1f0008c65dac804d99e60db0369bb9530f9179d0f1e340b99cb50d7a23374fe00bff47d7a94840bb54d81bb6501307f8ff9d1cceec3a7e79eeb849d90b6448b3a04bf5790aab9090d63db0350ae9dba81b6e69a359d314d97cfe4f4fa5f7dbeaa3c22b5b28cf50507f3731146c60e3ee0a2bd894e2180f30b82e6b7006d1e9867dc531bd5370a0d79da1a1fb334e39e37a9ad33d5d9de3c501c96a3c6f6e3659665b8c664c08107703e25913bc36054d0bd4d2831ee876315c45bb58a47feb849ec50fa359d71024520e326b8a97729bb6083659e9a6c934bcb3d256c72f508f0457b1afd14b405d1d9618d80f008b65ee4477490b60902e33928a42bbebdc8ab7fb8e7c7b3f70c8a9c9dbbef93eeacf0304fba3e1f7e86ff73d12ce4961f264dbfc28d69be2e006aa96993296cb3edd72b84a66baab093660a38dec8fbc578021853228e4fdc0e0c7792c82bd52f57bdddc2ce177af2a325c2f225884b7fd02ba80e38bfc485037f2e1307c012442668b1ff7c73af07fec7be794a9460c03085adfa04ead6b60847f7ec625322dadf787ea430d04d88f591c66d2310b3f8cd7aefc4e983dfa301b26b88ff3459f2dafca3237be06c09dd61a9557c4aa316360d2ea0b7a3fead0107b41709c93841f164f649912f1276cd055f9e20031666ffa0a5efdffd5f2800830248963e7e2fe330db56aab8944d352cea075ddf16d8cc3fdc4a4bdd49390435ae91ddd2d5e9e7c338748a68cec114175992563b809877e658ad8a5dc61004d71f84ae6819dd0cfd62c6b5e8f8c72db877faab2b24dc84f269d0fad372ef0f795806dff9f95790d1ea4c0b5efb1ae79df105af676b77774aa7dcde40940d014dfa7f9e8545a34fabec7df6088e44657d9e28ca5f67fe966cb299f3ae9fbc0ddcdd263ae5910210378c2a4e312e58c7ac4cc4c747ec01d3c474fc998651d107e798498bcfc2cf97b647beb5f133ca878bebeab876a6d8d65ec28374254d5b04a086d230dfc448b9d635cfa59f4ffcaab74c324c88bd1fa0b96b1cf14787a60266a4b3c15ea0828f0bd6794cce450b368b01cb1da066b40f66b6a5e9529eec05b06b3e218a611dcd2a0338fdb7db2ffaace2fa31ac5f40bba888aac1203121026ce685a6888de03d5452ee603e8113beefc30dc14cbf25958a81a8a4a840240cdfe1ec9042309ed91235799be2f902003ce3b4976c18b8ed73b18678794dea0f4dc0d8b0ff2938a4d29ec756e1306fb018c24b47ac8ae1da1a9fd547769cad08d57a5451fb6b275e718db32c44427d9b0a7fcd0a50dd5807cc817b9f9f1f0d0e4ad827bffc12d8a4eb60dceb98ff5a01550485ac4ebb60b0a7ca661e1dbbd30871bb1df8ee106a6e3893e11ec46d9d188ff9f0359922c70ea794a665e7f2a50f2128d3e63d9e5173ac7e9d83638c53e9de0d0ddb50daad2cc303cdd6489ddf0d7fd8e1a8d59a8e5d70a909dfd24d2c9d742de5df0c1f390011f65906a189370d0e9f6405a716ea316006a2526a78cba0bfed5de0b30ce20e4264c8a4b94e7705388a445a24b84c8bb89da7c59bc5ee0a0edebd87be980dc1f0871b1a7e069b01cbd8ebc3923b1a4a15f487ce47415f5276ae2dd3417609c2325f334330308d0a95e529dcdd6bca69a5e6286668e078c2a6e624c870dd7de23afdcacbe6074408db145c0e6b20a878e713a5476b2aa009ade4efb006983567694e55f2f695e3034d372dcbd7ed79e7a0d78274786d2505e59d7383ba0879d0f1934fa87241ac03a66b57accc64db643108ac2093ab18ee76234e262c73585b40f148db7115c707de5cb98d48b7769a4ef62262bf72a953446a3a79c2fbbc3f26a72070cdb1190ec6cce473a90450c794b91434e6e78f9b47cf54810300672753ede88e98c8dd0a3d9ce938da4cab3a3228cfc9e9a8d253906e7ab45ab1cad794da355b197cc00b0aebc5a1bf6defd40683f1caec954eb81e889bdbbdfe724fbd3beeb5bf372301611791f51dfd3cdf2b93e2d8a72ac63a459961b017778827e49e5c0e26b62806641629d374055b4c9ca9b4786ebcebf3012f792ad4181d4747e59ae6fcd027014f66cd168735947c1572c3deb712efcabca9955eedc877f3e580f4373e4a6f06c62a28262ef8d0c88d4cbcc2dbcb1bc8a867001ee63274371475ccef161db00c9c4e19636f611ff203be5bdf0d2366a4ffb659acfa67940bba39b016fd92ac01e5da21a1ca7dfd457db0a2ad2838aae11107ff4b6d32e5de364f300cf1014409f6aae39fc36ea8cf70d34ed1e11f3433f52796f42336c80d32b195b273e0e200ed6217e30e2585580600d3ad67869361346010cd23dceec4d38c3eb2b759200963cb4452dc9fed21f6f60d209a0176358f049583c85e9354e55cce488d9cdb0ce45abc53b6a9333df888e2d3e7c63ededd44f57257c6e502f22c30e3a29dc40fcff1bebdc3e672746dc325136fec244649d5b144ab0b90220d842ff9bf8d940bd2025cf7b0ab9c0f4f0575eb2085b3cdb7a037fa9cbf171090ca58d3cb5e520b7d519ff9d24de471d2a1a880957b5c89e3d581148a28fcf403e125b1bcd0390f22b974b9938a6e987c096aaffda697d2f50b487097a05cd447110f1c24474f0ab007d30ecf352f078741584f2e53c2bc1eb01204ee416b76120858c8c33d7b04d16858a989432e7d5af36b2ecdc07535f4f895fa078d929fc971cf39627edd0f9c1b76a0ff81b0e872eada750d0a9e32a6b0f8ab8d71e4e913b122cf9f9c090686dcb3a2b162ada6f92a1a5e4dca935e734c0b7ea62deaf190f64cf80cee5b0726acfb18ae407ea619e78c5195a46ca8059efc586d618780982a87ab5d0c88034c59f947f8f92e69145fe788838e574ab159edd184e0706e804e050d1f3ec7087a9e4f4d0ab12c0066f2829ebdd87503ddca3090b15f37ec3ba9c0c5036579063427f51743df6bdaac5468dafc87e02983ad981600198e67797649ac56598d08099f6299dfb68bf9891c966eba1a9ec6e0ed33c0f012a4e49de28ce45b92b80a987ba942328772dfd0267b7a10401c53a8204773136c6008cff98ab79c75990ebbb7bd00709bde6fcaf8e45d509a8305f1fb1f447997194ab3933b1cb88ee00baa5e31cf5f7838fb62e2191a94e35f5618be7d42d02f645f071408ed13fa780f44de54d83862bec967cf3c1f00f6a69afa2851965b2570a7fc6557ab331ca00bfe3794286f279e92d2844ace81c8bbceb89ac2b1ddb6d824dfa17274193e0a038cd6b514fa84a19594f772ff72f6c4a488df37801d2eb9d29f9e13bfdf0260053a6f937f07413fd607adec071ca80f8625569f3953fa6f4c05eb092f910aa40378aa0ae264c4b0f471a83a64898f77e1719ddde3d930210013d9403d2ed8a60fddfaa4eb6841e4f75622a5576b6f16a962344e325cd8f5ddfeb879169fb1180fc9bc9f81a4b9dd06848107497c6d4b478148a3f8f915d1c014a9b7d09d92c30619cdf4c62407a3bd1aa4d68e4984b3b54fb8b70575977440b70d2705341293038cb06cd66c7a01c074cd22786a032303d7040ac15a1bbe2940409fdbdeede3042558ee40c033aed008fd7c6d6b6ddf36569699e2f5fd0921921105aaef3e3e0b578bb2c8a141fa52c6b395ff1e0ec247e78760317089e491abb282a7dae0b30e396761d9be46c452b5f3506e069f1cf5e633855e845ab5e706af6d00cdade40c7588b30d8086039cfbaf7a7e341bba0c0f39c24ab5b7ef8c7b6c3134d0f5c201591f285672d937a284b71abac38ef299866c4976798b82958e6bca727377db03 true check_ring_signature c70652ca5f06255dc529bc0924491754f5fad28552f4c9cd7e396f1582cecdca 89d2e649616ccdf1680e0a3f316dcbd59f0c7f20eba96e86500aa68f123f9ecd 1 9cc7f48f7a41d634397102d46b71dd46e6accd6465b903cb83e1c2cd0c41744e 3e292a748b8814564f4f393b6c4bd2eaaface741b37fd7ac39c06ab41f1b700db548462601351a1226e8247fea67df6f49ea8f7d952a66b9ec9456a99ce7b90b true check_ring_signature 3da5300a7aca651dc3a85016824b0620a19973eae4af8910cc177faee499358d 8d39d8d877d74cccbd5fad872b8297eec3f4b3f5187486f8c98a2ff27f994800 16 7af6983daaecec1bff70b05c7369fe1636270f8dd606d39eba974b8c1d5f6091 78c2676d12505b7d5a63ce29f736124b48a02dc78bd0ccd1e9901344811bbd3d 957251408e9a8b255adcabc52bf15cb8a05501e2892d7cdda22ce672adc0cd12 73e433a1668d056d9b651aead47658476cf23c39cfeb4fd23625ed94af439677 f58dd3a46e0a07000ef6e978cff87604c32cd3df487acd220b53b5ccc46d0bd5 3480f2437e01073133ee9cad9651665277b09bc0a46618f975a746500f9f34bf 0ed796ebd217fcae58272ed7c4c0b058f558961f95a68ea52f59e4e6f0374d73 729e5938a034b2f50b583d4ada5541a12de09aa1776653a821da7d6c6b057716 1a9855ca5dc19cf11f49a87b182695451e83952f2df4ee9009bf0f72d6e25194 c609386fb270c7af8dc4ee102fd33ed3c836e7ea493dc79655c9feb1cfb9c869 94ce9f9d3fbe4848aeb59231d749c6c9f7bfaaf99c31e4317c2b5b1b335f20f9 9331dabe4d6f230a7c45417dbbb28b0808b4b6bdcba83b774583d784413ddb4b 437652a047fe0872b264c094440625cb5cca5cb8d10cda950138c97dd09e5943 5c470fa7fc2684336917a626e2dd4a09d68b4ef9499857c11e8ef0aff77a9262 df3ccf869b0262bd33952ace2b1320f809e227949ce6a2e89a245ce5da75e250 4ec480b685a07d091057e73954c8bd5e4646b2bd0bb0a46a38f74cc44e0c940b 4e7ee4fb45708e2bd97b2ee4e134224714c2fe1c0b679b7de838d715e281f10e4da8a6455bf4683a91e6e56be119fde36ccd61f35aa4867e9725dda7c18bb40afa097778cdcec51fe2d205db00ab9a00dd5f6f0a2a3b8393a7ae2bc03d6ff5073b25f72be8166bdf2e21a4745841bbff68a54d6fa3c77577a6b5c0f0b7ce0a120d07d704e9a30f306a63d5b137534ac4b60953abeb420d526f4b501008bd0a01790d806d86cf96391953e8b630833a3d6a01f023da720e26015287dee5c9b9060f43fa3574626a3673628b6b82c4b0251b5251173b59177fdc8f79974205090da7a3d93d1d274ed39654c348870da21ac66ee7a0e072e504aa01ece4051c3f0c93eb6065ae0e4d05e49144b986b33ee741c406860d39c953062531f2e993140c43aeeef6b144cc42bd13c2aafb10402edddebdfe0b426730163fd530f7b2c3009d4b98d761131c5ccbdcb737b4a1e9fc72c1313fb45eef13ce4d31c40ec94c0466cfcba1771229b0d2e014d716c9a2c10f6191eb67c1bb05e72f291d1d98290c2b4542d196df41410992428e36c62965a2d68f1fb99d6d4058b7e0360dae2c0c56d7980a546f547d2944c3bb6672fdb7d40378d47b0bcd9ca9ce55abce22ee0d94a7906ff1e31d37578a919dd92b4615ee0930fb33cb494548e13b731b33320193bc5b88e5864fe2d5d9a1b2bfb343177ff10d647337205f22a37b5cb385090bd2a050d055cfb9fbe01cc88ffa3fad76eb5b7baa50cf5f379ac6cf2636da8308c945c859cae02e772e432b177238a6e3d75b5cc6e676d1f3989d78493d86440cbb5552586755101dc4dd43bf51cab188fcc919012f7d9b19db5189fad02362059c8b3cacc8f80413e9a43f41cbe154ad55acac98287edef98240b6d8a04fcd0a020c8481164041bd7165a6b90b8560593c8848d29995634392dd22f3e993bd05580e41349091cb125eb2048c53dd230808019482f4b22c83ca678d9b01931b03f84ff3b4a78c138fbe36d013c9a423e0233962be5f278b535b20f05c829624043641b8386f7cd01a77c4077a5a6da0eec912042c60d9b6bcb56cac9713dc7002ab69ee15e0013204f68d6093b158c21f3a09e205b15e627b3fa33d9a0cd0300d9287b5d75ab7dd914ed95c8ed3db0bf05f68792be1492c41854a2e36c123d30427ff0fdf706d5a01f6cf6b1c02e2140f7b165b2259904528f12b527a7de76a0d8f90c3c027bb2f71cb1b345fafee0628b3f15049cb577b780890b9b96c53160b9ec99cea512304c94325b2c894b6dbc926c9b2b8f497a765a180f70425174802033d83980e2b28cfaf767d6a4da871d6adee474fb093e89df7eab67255b1b70821e64bee166892d1e5ea9ff2dae7b65231427e01c63164b5f3f84626511d2f077de2741fb75e3d940646480b595338c6043cdda23f0fb48d875498675e686eaf false From 539debc477a756907a82a45fa3d414e4b1a3b300 Mon Sep 17 00:00:00 2001 From: sanecito Date: Sun, 7 Oct 2018 14:27:41 -0700 Subject: [PATCH 0063/1007] Finish all contexts but simple_wallet, translate 23% of simple_wallet --- translations/monero_ja.ts | 600 +++++++++++++++++++------------------- 1 file changed, 303 insertions(+), 297 deletions(-) diff --git a/translations/monero_ja.ts b/translations/monero_ja.ts index 939f9188f..17815d982 100644 --- a/translations/monero_ja.ts +++ b/translations/monero_ja.ts @@ -34,12 +34,12 @@ Failed to write transaction(s) to file - ファイルに取引を書き出せなかった + 取引をファイルに書き込めませんでした daemon is busy. Please try again later. - デーモン忙しいです。後でもう一度試してください。 + デーモンは忙しいです。後でもう一度試してください。 @@ -72,53 +72,53 @@ This is a watch only wallet - + これは閲覧専用ウォレットです Failed to sign transaction - + 取引を署名できませんでした Claimed change does not go to a paid address - + 請求したお釣りはもうお金に送ったアドレス送りません Claimed change is larger than payment to the change address - + 請求したお釣りはお釣りのアドレスに送ったペイメントより大きいです Change goes to more than one address - + お釣りは複数のアドレスに送ります sending %s to %s - + %s を %s に送ってます with no destinations - + 目的地なし %s change to %s - + %s のお釣り %s に no change - + お釣りありません Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu. %s - + 取引は %lu ロードした、 %s に、%s のの手数料、 %s 、 %s 、最小リングサイズ %lu 。%s @@ -126,219 +126,219 @@ payment id has invalid format, expected 16 or 64 character hex string: - + ペイメントIDのフォーマットは不正です。16文字または64文字の16進数の文字列が必要で: Failed to add short payment id: - + 短いペイメントIDの追加に失敗しました: daemon is busy. Please try again later. - + デーモンは忙しいです。後でもう一度試してください。 no connection to daemon. Please make sure daemon is running. - + デーモンの接続が確立ありません。デーモンが実行中になっていることを確認してください。 RPC error: - + RPCエラー: not enough outputs for specified ring size - + 指定したリングサイズのアウトプットが不十分です found outputs to use - + 使うためにアウトプットを見つかれました Please sweep unmixable outputs. - + ミックス不能なアウトプットをスイープしてください。 failed to get random outputs to mix - + ランダムなアウトプットをミックスすることに失敗しました not enough money to transfer, available only %s, sent amount %s - + 振替でMoneroを受け取ることできません。利用可能な金額: %s, 取引の金額: %s failed to parse address - + アドレスの解析に失敗しました failed to parse secret spend key - + 秘密なスペンドキーの解析に失敗しました No view key supplied, cancelled - + ビューキーをもらいませんでしたのでキャンセルしました failed to parse secret view key - + 秘密なビューキーの解析に失敗しました failed to verify secret spend key - + 秘密なスペンドキーの検証に失敗しました spend key does not match address - + スペンドキーがアドレスと一致しませんでした failed to verify secret view key - + 秘密なビューキーの検証に失敗しました view key does not match address - + ビューキーがアドレスと一致しませんでした failed to generate new wallet: - + 新しいウォレットの生成に失敗しました: Failed to send import wallet request - + インポートウォレットリクエストの送信に失敗しました Failed to load unsigned transactions - + 未署名の取引を読み込めませんでした Failed to load transaction from file - + ファイルからの取引のロードに失敗しました Wallet is view only - + 閲覧専用ウォレットです failed to save file - + ファイルを保存できませんでした Key images can only be imported with a trusted daemon - + 信頼できるデーモンしかでキーイメージをインポートしません Failed to import key images: - + キーイメージをインポートできませんでした: Failed to get subaddress label: - + サブアドレスラベルを取得できませんでした: Failed to set subaddress label: - + サブアドレスラベルをセットできませんでした: failed to get random outputs to mix: %s - + ランダムなアウトプットをミックスすることに失敗しました: %s not enough money to transfer, overall balance only %s, sent amount %s - + 振替でMoneroを受け取ることできません。利用可能な金額: %s, 取引の金額: %s not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee) - + 取引は無理です。利用可能な金額 %s、 取引の金額 %s = %s + %s (手数料) output amount - + アウトプットの金額 transaction was not constructed - + 取引を作りませんでした transaction %s was rejected by daemon with status: - + 取引 %s がデーモンによって拒否しました。ステータス: one of destinations is zero - + 宛先の1つはゼロです failed to find a suitable way to split transactions - + 取引を分割する適切な方法を見つけることができませんでした unknown transfer error: - + 不明な転送エラー: internal error: - + 内部エラー: unexpected error: - + 予期せぬエラー: unknown error - + 不明なエラー @@ -348,18 +348,18 @@ Failed to parse txid - + txidの解析に失敗しました no tx keys found for this txid - + このtxidのためにtxキーを見つかれませんでした Failed to parse tx key - + txキーの解析に失敗しました @@ -367,17 +367,17 @@ Failed to parse address - + アドレスの解析に失敗しました Address must not be a subaddress - + アドレスはサブアドレスであってはならないです Rescan spent can only be used with a trusted daemon - + 信頼できるデーモンしかで再スキャンしません @@ -385,17 +385,17 @@ Failed to parse address - アドレスを解析できませんでした + アドレスの解析に失敗しました Failed to parse key - キーを解析できませんでした + キーの解析に失敗しました failed to verify key - キーを検証できませんでした + キーの検証に失敗しました @@ -421,48 +421,48 @@ Specify IP to bind RPC server - + RPCサーバに接続するIPを指定してください Specify username[:password] required for RPC server - + RPCサーバを使うためにユーザー名[:パスワード]を指定してください Confirm rpc-bind-ip value is NOT a loopback (local) IP - + rpc-bind-ipの価はループバック(ローカル)IPじゃないことを確認してください Specify a comma separated list of origins to allow cross origin resource sharing - + クロスオリジンリソース共同をできるためにコンマ区切りリストを指定してください Invalid IP address given for -- - + このRPCサーバーのIPはだめです -- permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with -- - + は暗号化されていない外部接続をできますがSSHトンネルやSSLプロキシの方がいいです。これでオーバーライド -- Username specified with -- - + このRPCサーバのユーザー名につて -- cannot be empty - + 入力する必要があります requires RPC server password -- - + のRPCサーバのパスワードありません -- @@ -480,7 +480,7 @@ invalid password - + 不正なパスワード @@ -524,18 +524,18 @@ 0 or 1 - + 0や1 0, 1, 2, 3, or 4 - + 0、1、2、3、や 4 unsigned integer - + 符号無しの整数 @@ -595,7 +595,7 @@ failed to generate new wallet: - + 新しいウォレットの生成に失敗しました: @@ -622,7 +622,7 @@ failed to load wallet: - + ウォレットをロードできませんでした: @@ -670,7 +670,7 @@ transaction - + 取引 @@ -751,7 +751,8 @@ Transaction - + +取引 @@ -790,7 +791,7 @@ Transaction . - + @@ -850,7 +851,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 failed to parse key image - + キーイメージの解析に失敗しました @@ -900,7 +901,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 sending %s to %s - + %s を %s に送ってます @@ -910,12 +911,12 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 with no destinations - + 目的地なし Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): - + 取引は %lu ロードした、 %s に、%s のの手数料、 %s 、 %s 、最小リングサイズ %lu 、%s。これは大丈夫ですか? はい (Y) いいえ (N): @@ -930,12 +931,12 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 Failed to sign transaction - + 取引を署名できませんでした Failed to sign transaction: - + 取引を署名できませんでした: @@ -945,13 +946,13 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 Failed to load transaction from file - + ファイルからの取引のロードに失敗しました RPC error: - + RPCエラー: @@ -984,7 +985,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 invalid unit - + 不正なユニット @@ -995,7 +996,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 invalid value - + 不正な金額 @@ -1005,7 +1006,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 (Y/Yes/N/No): - + (はい (Y) いいえ (N)): @@ -1027,12 +1028,12 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 Is this okay? (Y/Yes/N/No): - + これは大丈夫ですか? (はい (Y) いいえ (N)): Daemon is local, assuming trusted - + デーモンはローカルです。信頼できるデーモン予期してます @@ -1047,14 +1048,14 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 internal error: - + 内部エラー: unexpected error: - + 予期せぬエラー: @@ -1067,7 +1068,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 unknown error - + 不明なエラー @@ -1082,14 +1083,14 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 unlocked balance: - + ロック解除された残高: amount - + 金額 @@ -1099,17 +1100,17 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 Unknown command: - + 未知のコマンド: Command usage: - + コマンドの使用: Command description: - + コマンドの記述: @@ -1237,14 +1238,14 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 multisig address: - + マルチサインアドレス: This wallet is not multisig - + これはマルチシッグウォレットではありません @@ -1320,7 +1321,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 This is not a multisig wallet - + これはマルチシッグウォレットではありません @@ -1335,7 +1336,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 Multisig error: - + マルチサインエラー: @@ -2085,12 +2086,12 @@ Otherwise, you prove the reserve of the smallest possible amount above <amoun Error: expected M/N, but got: - + エラー: N/Mを欲しかったでもこれを貰いました: Error: expected N > 1 and N <= M, but got: - + エラー: N > 1 と N <= M のこと欲しかったでもこれを貰いました: @@ -2105,12 +2106,12 @@ Otherwise, you prove the reserve of the smallest possible amount above <amoun failed to parse secret view key - + 秘密なビューキーの解析に失敗しました failed to verify secret view key - + 秘密なビューキーの検証に失敗しました @@ -2157,7 +2158,7 @@ your wallet again (your wallet keys are NOT at risk in any case). failed to generate new mutlisig wallet - + 新しいマルチシッグウォレットの生成に失敗しました @@ -2199,13 +2200,13 @@ your wallet again (your wallet keys are NOT at risk in any case). txid - + txid idx - + idx @@ -2220,12 +2221,12 @@ your wallet again (your wallet keys are NOT at risk in any case). ] - + ] Tag: - + タグ: @@ -2240,30 +2241,30 @@ your wallet again (your wallet keys are NOT at risk in any case). Address - + アドレス Balance - + 残高 Unlocked balance - + ロック解除された残高 Outputs - + アウトプット Label - + ラベル @@ -2294,7 +2295,7 @@ your wallet again (your wallet keys are NOT at risk in any case). tx id - + tx id @@ -2325,12 +2326,12 @@ your wallet again (your wallet keys are NOT at risk in any case). payment - + ペイメント transaction - + 取引 @@ -2395,14 +2396,16 @@ Originating block heights: | - + +| | - + | + @@ -2454,7 +2457,7 @@ Warning: Some input keys being spent are from , txid - + 、txid @@ -2482,7 +2485,7 @@ Warning: Some input keys being spent are from This is a watch only wallet - + これは閲覧専用ウォレットです @@ -2565,12 +2568,12 @@ Warning: Some input keys being spent are from Generating new wallet... - + 新しいウォレットを生じてます... Electrum-style word list failed verification - + Electrumな単語表の検証に失敗しました @@ -2584,7 +2587,7 @@ Warning: Some input keys being spent are from No data supplied, cancelled - + データをもらいませんでしたのでキャンセルしました @@ -2600,26 +2603,26 @@ Warning: Some input keys being spent are from failed to parse address - + アドレスの解析に失敗しました failed to parse view key secret key - + 秘密なビューキーの解析に失敗しました failed to verify view key secret key - + 秘密なビューキーの検証に失敗しました view key does not match standard address - + ビューキーが一般的なアドレスと一致しませんでした @@ -2635,19 +2638,19 @@ Warning: Some input keys being spent are from failed to parse spend key secret key - + 秘密なスペンドキーの解析に失敗しました failed to verify spend key secret key - + 秘密なスペンドキーの検証に失敗しました spend key does not match standard address - + スペンドキーが一般的なアドレスと一致しませんでした @@ -2673,7 +2676,7 @@ Warning: Some input keys being spent are from View key: - + ビューキー: @@ -2701,13 +2704,13 @@ Warning: Some input keys being spent are from daemon is busy. Please try again later. - + デーモンは忙しいです。後でもう一度試してください。 no connection to daemon. Please make sure daemon is running. - + デーモンの接続が確立ありません。デーモンが実行中になっていることを確認してください。 @@ -2717,7 +2720,7 @@ Warning: Some input keys being spent are from Balance: - + 残高: @@ -2727,28 +2730,28 @@ Warning: Some input keys being spent are from key image - + キーイメージ unlocked - + ringct - + ringct T - + T F - + F @@ -2758,12 +2761,12 @@ Warning: Some input keys being spent are from RingCT - + RingCT - - + - @@ -2778,7 +2781,7 @@ Warning: Some input keys being spent are from the same transaction - + 同じ取引 @@ -2841,24 +2844,24 @@ Warning: Some input keys being spent are from Index: - + インデックス: Address: - + アドレス: Payment ID: - + ペイメントID: Description: - + 記述: @@ -2886,7 +2889,7 @@ Warning: Some input keys being spent are from failed to read file - + ファイルの読み込みに失敗しました @@ -2933,7 +2936,7 @@ Warning: Some input keys being spent are from Address must not be a subaddress - + アドレスはサブアドレスであってはならないです @@ -2963,7 +2966,7 @@ Warning: Some input keys being spent are from (no daemon) - + (デーモンありません) @@ -2983,7 +2986,7 @@ Warning: Some input keys being spent are from failed to parse index: - + インデックスの解析に失敗しました: @@ -3013,7 +3016,7 @@ Grand total: , unlocked balance: - + 、ロック解除された残高: @@ -3028,12 +3031,12 @@ Grand total: Accounts with tag: - + タグを持ってるアカウント: Tag's description: - + タグの記述: @@ -3043,22 +3046,22 @@ Grand total: %c%8u %6s %21s %21s %21s - + %c%8u %6s %21s %21s %21s ---------------------------------------------------------------------------------- - + ---------------------------------------------------------------------------------- %15s %21s %21s - + %15s %21s %21s Primary address - + プライマリアドレス @@ -3099,7 +3102,7 @@ Grand total: Subaddress: - + サブアドレス: @@ -3109,52 +3112,52 @@ Grand total: no description found - + 記述を見つかれませんでした description found: - + 記述を見つかれました: Filename: - + ファイル名: Watch only - + 閲覧専用 %u/%u multisig%s - + %u/%u マルチサイン%s Normal - + ノーマル Type: - + タイプ: Testnet: - + テストネット: Yes - + はい No - + いいえ @@ -3191,7 +3194,7 @@ Grand total: failed to save file - + ファイルを保存できませんでした @@ -3249,12 +3252,12 @@ Grand total: %s change to %s - + %s のお釣り %s に no change - + お釣りありません @@ -3279,12 +3282,12 @@ Grand total: failed to parse txid - + txidの解析に失敗しました Tx key: - + txキー: @@ -3319,26 +3322,26 @@ Grand total: failed to parse tx key - + txキーの解析に失敗しました error: - + エラー: received - + 貰いました in txid - + txidに @@ -3388,7 +3391,7 @@ Grand total: failed - + 失敗 @@ -3404,17 +3407,18 @@ Grand total: Amount: - + +金額: , number of keys: - + 、キーの数: - + @@ -3468,45 +3472,47 @@ Outputs per *: | - + | + - + + +--> block height - + +--> ブロック高 + ^ - + ^ ^ - + ^ + - + wallet - + ウォレット Random payment ID: - + ランダムなペイメントID: @@ -3519,83 +3525,83 @@ Outputs per *: Base filename (-1, -2, etc suffixes will be appended as needed) - + ベースファイル名(必要があれば-1、-2、とかのサフィックスを追加します) Give threshold and participants at once as M/N - + M/Nってのフォーマットで同じ時に閾値と参加者をください How many participants will share parts of the multisig wallet - + マルチサインウォレットを分ける人はいくついますか How many signers are required to sign a valid transaction - + 有効な取引を署名するために必要な人いくついますか Create testnet multisig wallets - + テストネットのマルチサインウォレットを作る Generating %u %u/%u multisig wallets - + %u %u/%u マルチサインウォレットを生じてます Error verifying multisig extra info - + マルチサインの追加情報を検証中にエラーありました Error finalizing multisig - + マルチサイン締結中にエラーありました Generated multisig wallets for address - + アドレスのためにマルチサインウォレットを生じなかった Error creating multisig wallets: - + マルチサインウォレットを樹立中にエラーありました: This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other - + このプログラムはマルチサインウォレットのセットを生じます - みんながみんなを信用する場合にだけこの単純なスキームを使ってください Error: expected N/M, but got: - + エラー: N/Mを欲しかったでもこれを貰いました: Error: either --scheme or both of --threshold and --participants may be given - + エラー: --scheme あるいは--threshold と --participants を上げられる Error: expected N > 1 and N <= M, but got N==%u and M==%d - + エラー: N > 1 と N <= M のこと欲しかったでも N==%u と M==%d を貰いました Error: --filename-base is required - + エラー: --filename-baseを使う必要だがあります Error: unsupported scheme: only N/N and N-1/N are supported - + エラー: 不正なスキーム: N/N や N-1/N`のことをできます @@ -3603,98 +3609,98 @@ Outputs per *: Generate new wallet and save it to <arg> - + 新しいウォレットを生じろ <arg> をこっちにセーブしてください Generate incoming-only wallet from view key - + ビューキーで閲覧専用ウォレットを生じろください Generate deterministic wallet from spend key - + スペンドキーで決定論的なウォレットを生じろください Generate wallet from private keys - + 秘密なキーでウォレットを生じろください Generate a master wallet from multisig wallet keys - + マルチシガーウォレットキーでマスターウォレットを生じろください Language for mnemonic - + ニーモニックのための言語 Specify Electrum seed for wallet recovery/creation - + ウォレットの回収や作成のためにElectrumなニーモニックシードを指定してください Recover wallet using Electrum-style mnemonic seed - + Electrumなニーモニックシードでウォレットを復元してください Recover multisig wallet using Electrum-style mnemonic seed - + Electrumなニーモニックシードでマルチシガーウォレットを復元してください Generate non-deterministic view and spend keys - + 非決定論的のビューとスペンドキーを生じろください Enable commands which rely on a trusted daemon - + 必要な信用できるデーモンのコマンドをエネーブルしてください Allow communicating with a daemon that uses a different RPC version - + 別のRPCバージョンを使用してるデーモンとの通信を許可してください Restore from specific blockchain height - + 特定ブロックチェイン高で復元してください The newly created transaction will not be relayed to the monero network - + 新しい取引をネットワークに中継しません daemon is busy. Please try again later. - + デーモンは忙しいです。後でもう一度試してください。 possibly lost connection to daemon - + デモンの接続が切れましたかもしりません Error: - + エラー: This is the command line monero wallet. It needs to connect to a monero daemon to work correctly. - + これはMoneroのコマンドラインウォレットです。別のMoneroデモンと接続する必要があります。 Failed to initialize wallet - + ウォレットを初期化できませんでした @@ -3702,151 +3708,151 @@ daemon to work correctly. Use daemon instance at <host>:<port> - + <host>:<port>でデーモンインスタンスを使ってください Use daemon instance at host <arg> instead of localhost - + localhostの代わりにホスト <arg>でデーモンインスタンスを使ってください Wallet password file - + ウォレットのパスワードファイル Use daemon instance at port <arg> instead of 18081 - + 18081の代わりにポート <arg>でデーモンインスタンスを使ってください For testnet. Daemon must also be launched with --testnet flag - + テストネットのためにデーモンは --testnet のフラグで開始する必要があります Restricts to view-only commands - + 閲覧専用コマンドに限ります can't specify daemon host or port more than once - + デーモンのホストやポートを複数回指定することはできません can't specify more than one of --password and --password-file - + --password と --passwordfile を1つしか指定しません the password file specified could not be read - + 指定されたパスワードファイルを読み取れません Failed to load file - + ファイルのロードに失敗しました Wallet password (escape/quote as needed) - + ウォレットのパスワード(随時にエスケープ文字を使ってください) Specify username[:password] for daemon RPC client - + デーモンのRPCクライアントを使うためにユーザー名[:パスワード]を指定してください no password specified; use --prompt-for-password to prompt for a password - + パスワードを指定しませんでした。パスワードプロンプトを見るために--prompt-for-password を使ってください Failed to parse JSON - + JSONを解析に失敗しました Version %u too new, we can only grok up to %u - + バージョン %u 新しすぎるです。%u までグロークできます failed to parse view key secret key - + 秘密なビューキーの解析に失敗しました failed to verify view key secret key - + 秘密なビューキーの検証に失敗しました failed to parse spend key secret key - + 秘密なスペンドキーの解析に失敗しました failed to verify spend key secret key - + 秘密なスペンドキーの検証に失敗しました Electrum-style word list failed verification - + Electrumな単語表の検証に失敗しました At least one of Electrum-style word list and private view key and private spend key must be specified - + Electrumな単語表と秘密なビューキーと秘密なスペンドキーの少なくとも1つを指定する必要があります Both Electrum-style word list and private key(s) specified - + Electrumな単語表と秘密なキーを指定しました invalid address - + 不正なアドレス view key does not match standard address - + ビューキーが一般的なアドレスと一致しませんでした spend key does not match standard address - + スペンドキーが一般的なアドレスと一致しませんでした Cannot generate deprecated wallets from JSON - + JSONで非推奨のウォレットを生成することはできません failed to parse address: - + アドレスの解析に失敗しました: Address must be specified in order to create watch-only wallet - + 閲覧専用ウォレットを作るためにアドレスを指定する必要があります failed to generate new wallet: - + 新しいウォレットの生成に失敗しました: @@ -3858,17 +3864,17 @@ daemon to work correctly. Primary account - + プライマリア カウント No funds received in this tx. - + この取引から資金貰いませんでした。 failed to read file - + ファイルの読み込みに失敗しました @@ -3876,125 +3882,125 @@ daemon to work correctly. Daemon is local, assuming trusted - + デーモンはローカルです。信頼できるデーモン予期してます Failed to create directory - + ディレクトリの作成に失敗しました Failed to create directory %s: %s - + %s %s ディレクトリの作成に失敗しました Cannot specify -- - + これを指定しません: -- and -- - + と -- Failed to create file - + ファイルの作成に失敗しました . Check permissions or remove file - + 。 パーミッションを確認するか、ファイルを削除してください Error writing to file - + ファイルへの書き込みエラー RPC username/password is stored in file - + RPCユーザー名/パスワードはファイルに保存しました Tag %s is unregistered. - + タグ %s を登録してません。 Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee) - + 取引は無理です。利用可能な金額 %s、 取引の金額 %s = %s + %s (手数料) This is the RPC monero wallet. It needs to connect to a monero daemon to work correctly. - + これはMoneroのコマンドラインウォレットです。別のMoneroデモンと接続する必要があります。 Can't specify more than one of --wallet-file and --generate-from-json - + --wallet-file と --generate-from-json を1つしか指定しません Must specify --wallet-file or --generate-from-json or --wallet-dir - + --wallet-file や --generate-from-json や --wallet-dir を指定する必要があります Loading wallet... - + ウォレットをロードしてます... Saving wallet... - + ウォレットを保存してます... Successfully saved - + 保存しました Successfully loaded - + ロードしました Wallet initialization failed: - + ウォレットを初期化できませんでした: Failed to initialize wallet RPC server - + ウォレットのRPCサーバを初期化できませんでした Starting wallet RPC server - + ウォレットのRPCサーバを開始してます Failed to run wallet: - + ウォレットを起動することできませんでした: Stopped wallet RPC server - + ウォレットのRPCサーバを停止しました Failed to save wallet: - + ウォレットを保存することできませんでした: @@ -4004,63 +4010,63 @@ daemon to work correctly. Wallet options - + ウォレットのオプション Generate wallet from JSON format file - + JSONフォーマットファイルでウォレットを生じてください Use wallet <arg> - + ウォレットの <arg> を使てください Max number of threads to use for a parallel job - + 並列ジョブのために最大スレッドの数 Specify log file - + ログファイルを指定してください Config file - + 設定ファイル General options - + ジェネラルオプション This is the command line monero wallet. It needs to connect to a monero daemon to work correctly. - + これはMoneroのコマンドラインウォレットです。別のMoneroデモンと接続する必要があります。 Can't find config file - + 設定ファイルを見つかりませんでした Logging to: - + こっちにログをしてます: Logging to %s - + %s にログをしてます Usage: - + 使用: From 85e58cb24aed02b3fa6cf26850e334dd571be04b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 7 Oct 2018 22:20:27 +0000 Subject: [PATCH 0064/1007] blockchain_blackball: fix stats double counting --- .../blockchain_blackball.cpp | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 5eb2acc79..00baad7f0 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -536,12 +536,15 @@ static uint64_t get_num_spent_outputs() return count; } -static void add_spent_output(MDB_cursor *cur, const output_data &od) +static bool add_spent_output(MDB_cursor *cur, const output_data &od) { MDB_val k = {sizeof(od.amount), (void*)&od.amount}; MDB_val v = {sizeof(od.offset), (void*)&od.offset}; - int dbr = mdb_cursor_put(cur, &k, &v, 0); - CHECK_AND_ASSERT_THROW_MES(!dbr || dbr == MDB_KEYEXIST, "Failed to add spent output: " + std::string(mdb_strerror(dbr))); + int dbr = mdb_cursor_put(cur, &k, &v, MDB_NODUPDATA); + if (dbr == MDB_KEYEXIST) + return false; + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to add spent output: " + std::string(mdb_strerror(dbr))); + return true; } static bool is_output_spent(MDB_cursor *cur, const output_data &od) @@ -1153,8 +1156,8 @@ int main(int argc, char* argv[]) if (!is_output_spent(cur, output_data(output.first, output.second))) { blackballs.push_back(output); - add_spent_output(cur, output_data(output.first, output.second)); - inc_stat(txn, output.first ? "pre-rct-extra" : "rct-ring-extra"); + if (add_spent_output(cur, output_data(output.first, output.second))) + inc_stat(txn, output.first ? "pre-rct-extra" : "rct-ring-extra"); } } if (!blackballs.empty()) @@ -1216,8 +1219,8 @@ int main(int argc, char* argv[]) std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[0])); - inc_stat(txn, txin.amount ? "pre-rct-ring-size-1" : "rct-ring-size-1"); + if (add_spent_output(cur, output_data(txin.amount, absolute[0]))) + inc_stat(txn, txin.amount ? "pre-rct-ring-size-1" : "rct-ring-size-1"); } else if (n == 0 && instances == new_ring.size()) { @@ -1230,8 +1233,8 @@ int main(int argc, char* argv[]) std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[o])); - inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); + if (!add_spent_output(cur, output_data(txin.amount, absolute[o]))) + inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); } } else if (n == 0 && opt_check_subsets && get_ring_subset_instances(txn, txin.amount, new_ring) >= new_ring.size()) @@ -1245,8 +1248,8 @@ int main(int argc, char* argv[]) std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, absolute[o])); - inc_stat(txn, txin.amount ? "pre-rct-subset-rings" : "rct-subset-rings"); + if (add_spent_output(cur, output_data(txin.amount, absolute[o]))) + inc_stat(txn, txin.amount ? "pre-rct-subset-rings" : "rct-subset-rings"); } } else if (n > 0 && get_relative_ring(txn, txin.k_image, relative_ring)) @@ -1281,8 +1284,8 @@ int main(int argc, char* argv[]) std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - add_spent_output(cur, output_data(txin.amount, common[0])); - inc_stat(txn, txin.amount ? "pre-rct-key-image-attack" : "rct-key-image-attack"); + if (add_spent_output(cur, output_data(txin.amount, common[0]))) + inc_stat(txn, txin.amount ? "pre-rct-key-image-attack" : "rct-key-image-attack"); } else { @@ -1393,9 +1396,9 @@ int main(int argc, char* argv[]) absolute.size() << "-ring where all other outputs are known to be spent"); } blackballs.push_back(output); - add_spent_output(cur, output_data(od.amount, last_unknown)); + if (add_spent_output(cur, output_data(od.amount, last_unknown))) + inc_stat(txn, od.amount ? "pre-rct-chain-reaction" : "rct-chain-reaction"); work_spent.push_back(output_data(od.amount, last_unknown)); - inc_stat(txn, od.amount ? "pre-rct-chain-reaction" : "rct-chain-reaction"); } } From 6844ae1b8d6b9fcbe4fda5ac5cb0e5a4242d850a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 16 Sep 2018 18:30:39 +0000 Subject: [PATCH 0065/1007] tx_pool: avoid parsing a whole tx if only the prefix is needed --- .../cryptonote_format_utils.cpp | 10 ++++ .../cryptonote_format_utils.h | 1 + src/cryptonote_core/tx_pool.cpp | 51 +++++++++---------- src/cryptonote_core/tx_pool.h | 13 ++--- src/serialization/serialization.h | 23 ++++++--- 5 files changed, 60 insertions(+), 38 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 5fcfa33f6..9e9c12605 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -199,6 +199,16 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx) + { + std::stringstream ss; + ss << tx_blob; + binary_archive ba(ss); + bool r = ::serialization::serialize_noeof(ba, tx); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob"); + return true; + } + //--------------------------------------------------------------- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) { std::stringstream ss; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index bf71eb591..725c75f4e 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -48,6 +48,7 @@ namespace cryptonote //--------------------------------------------------------------- void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); + bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx); diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index a725eac6e..35797d2ac 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -250,7 +250,7 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, id, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair(fee / (double)tx_weight, receive_time), id); } @@ -290,9 +290,10 @@ namespace cryptonote { CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); - m_blockchain.remove_txpool_tx(get_transaction_hash(tx)); + const crypto::hash txid = get_transaction_hash(tx); + m_blockchain.remove_txpool_tx(txid); m_blockchain.add_txpool_tx(tx, meta); - if (!insert_key_images(tx, kept_by_block)) + if (!insert_key_images(tx, txid, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair(fee / (double)tx_weight, receive_time), id); } @@ -371,8 +372,8 @@ namespace cryptonote continue; } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(txblob, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(txblob, tx)) { MERROR("Failed to parse tx from txpool"); return; @@ -381,7 +382,7 @@ namespace cryptonote MINFO("Pruning tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); m_blockchain.remove_txpool_tx(txid); m_txpool_weight -= it->first.second; - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, txid); MINFO("Pruned tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); m_txs_by_fee_and_receive_time.erase(it--); changed = true; @@ -398,11 +399,10 @@ namespace cryptonote MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes); } //--------------------------------------------------------------------------------- - bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block) + bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block) { for(const auto& in: tx.vin) { - const crypto::hash id = get_transaction_hash(tx); CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false); std::unordered_set& kei_image_set = m_spent_key_images[txin.k_image]; CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block @@ -418,19 +418,17 @@ namespace cryptonote //FIXME: Can return early before removal of all of the key images. // At the least, need to make sure that a false return here // is treated properly. Should probably not return early, however. - bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx) + bool tx_memory_pool::remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &actual_hash) { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); // ND: Speedup - // 1. Move transaction hash calcuation outside of loop. ._. - crypto::hash actual_hash = get_transaction_hash(tx); for(const txin_v& vi: tx.vin) { CHECKED_GET_SPECIFIC_VARIANT(vi, const txin_to_key, txin, false); auto it = m_spent_key_images.find(txin.k_image); CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL - << "transaction id = " << get_transaction_hash(tx)); + << "transaction id = " << actual_hash); std::unordered_set& key_image_set = it->second; CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL << "transaction id = " << actual_hash); @@ -483,7 +481,7 @@ namespace cryptonote // remove first, in case this throws, so key images aren't removed m_blockchain.remove_txpool_tx(id); m_txpool_weight -= tx_weight; - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, id); } catch (const std::exception &e) { @@ -515,7 +513,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); - std::unordered_set remove; + std::list> remove; m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) { uint64_t tx_age = time(nullptr) - meta.receive_time; @@ -533,7 +531,7 @@ namespace cryptonote m_txs_by_fee_and_receive_time.erase(sorted_it); } m_timed_out_transactions.insert(txid); - remove.insert(txid); + remove.push_back(std::make_pair(txid, meta.weight)); } return true; }, false); @@ -541,13 +539,14 @@ namespace cryptonote if (!remove.empty()) { LockedTXN lock(m_blockchain); - for (const crypto::hash &txid: remove) + for (const std::pair &entry: remove) { + const crypto::hash &txid = entry.first; try { cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid); - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(bd, tx)) { MERROR("Failed to parse tx from txpool"); // continue @@ -556,8 +555,8 @@ namespace cryptonote { // remove first, so we only remove key images if the tx removal succeeds m_blockchain.remove_txpool_tx(txid); - m_txpool_weight -= get_transaction_weight(tx, bd.size()); - remove_transaction_keyimages(tx); + m_txpool_weight -= entry.second; + remove_transaction_keyimages(tx, txid); } } catch (const std::exception &e) @@ -1041,7 +1040,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction& tx) + bool tx_memory_pool::have_key_images(const std::unordered_set& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1052,7 +1051,7 @@ namespace cryptonote return false; } //--------------------------------------------------------------------------------- - bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction& tx) + bool tx_memory_pool::append_key_images(std::unordered_set& k_images, const transaction_prefix& tx) { for(size_t i = 0; i!= tx.vin.size(); i++) { @@ -1301,7 +1300,7 @@ namespace cryptonote // remove tx from db first m_blockchain.remove_txpool_tx(txid); m_txpool_weight -= get_transaction_weight(tx, txblob.size()); - remove_transaction_keyimages(tx); + remove_transaction_keyimages(tx, txid); auto sorted_it = find_tx_in_sorted_container(txid); if (sorted_it == m_txs_by_fee_and_receive_time.end()) { @@ -1344,13 +1343,13 @@ namespace cryptonote bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { if (!!kept != !!meta.kept_by_block) return true; - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) + cryptonote::transaction_prefix tx; + if (!parse_and_validate_tx_prefix_from_blob(*bd, tx)) { MWARNING("Failed to parse tx from txpool, removing"); remove.push_back(txid); } - if (!insert_key_images(tx, meta.kept_by_block)) + if (!insert_key_images(tx, txid, meta.kept_by_block)) { MFATAL("Failed to insert key images from txpool tx"); return false; diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 892cadc69..7a0cc23bf 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -434,7 +434,7 @@ namespace cryptonote * * @return true on success, false on error */ - bool insert_key_images(const transaction &tx, bool kept_by_block); + bool insert_key_images(const transaction_prefix &tx, const crypto::hash &txid, bool kept_by_block); /** * @brief remove old transactions from the pool @@ -478,10 +478,11 @@ namespace cryptonote * a transaction from the pool. * * @param tx the transaction + * @param txid the transaction's hash * * @return false if any key images to be removed cannot be found, otherwise true */ - bool remove_transaction_keyimages(const transaction& tx); + bool remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &txid); /** * @brief check if any of a transaction's spent key images are present in a given set @@ -491,7 +492,7 @@ namespace cryptonote * * @return true if any key images present in the set, otherwise false */ - static bool have_key_images(const std::unordered_set& kic, const transaction& tx); + static bool have_key_images(const std::unordered_set& kic, const transaction_prefix& tx); /** * @brief append the key images from a transaction to the given set @@ -501,7 +502,7 @@ namespace cryptonote * * @return false if any append fails, otherwise true */ - static bool append_key_images(std::unordered_set& kic, const transaction& tx); + static bool append_key_images(std::unordered_set& kic, const transaction_prefix& tx); /** * @brief check if a transaction is a valid candidate for inclusion in a block @@ -509,11 +510,11 @@ namespace cryptonote * @param txd the transaction to check (and info about it) * @param txid the txid of the transaction to check * @param txblob the transaction blob to check - * @param tx the parsed transaction, if successful + * @param tx the parsed transaction prefix, if successful * * @return true if the transaction is good to go, otherwise false */ - bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction &tx) const; + bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction&tx) const; /** * @brief mark all transactions double spending the one passed diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 5fc382a1e..2050e88e2 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -318,7 +318,7 @@ namespace serialization { * \brief self explanatory */ template - bool do_check_stream_state(Stream& s, boost::mpl::bool_) + bool do_check_stream_state(Stream& s, boost::mpl::bool_, bool noeof) { return s.good(); } @@ -329,13 +329,13 @@ namespace serialization { * \detailed Also checks to make sure that the stream is not at EOF */ template - bool do_check_stream_state(Stream& s, boost::mpl::bool_) + bool do_check_stream_state(Stream& s, boost::mpl::bool_, bool noeof) { bool result = false; if (s.good()) { std::ios_base::iostate state = s.rdstate(); - result = EOF == s.peek(); + result = noeof || EOF == s.peek(); s.clear(state); } return result; @@ -347,9 +347,9 @@ namespace serialization { * \brief calls detail::do_check_stream_state for ar */ template - bool check_stream_state(Archive& ar) + bool check_stream_state(Archive& ar, bool noeof = false) { - return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving()); + return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving(), noeof); } /*! \fn serialize @@ -360,6 +360,17 @@ namespace serialization { inline bool serialize(Archive &ar, T &v) { bool r = do_serialize(ar, v); - return r && check_stream_state(ar); + return r && check_stream_state(ar, false); + } + + /*! \fn serialize + * + * \brief serializes \a v into \a ar + */ + template + inline bool serialize_noeof(Archive &ar, T &v) + { + bool r = do_serialize(ar, v); + return r && check_stream_state(ar, true); } } From 17701864c41f5716c5252632a79f5f41b6f27bf3 Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Mon, 8 Oct 2018 12:25:45 +0200 Subject: [PATCH 0066/1007] Depends: build hidapi with -fPIC --- contrib/depends/packages/hidapi.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/depends/packages/hidapi.mk b/contrib/depends/packages/hidapi.mk index d4dd80e22..1c43e525a 100644 --- a/contrib/depends/packages/hidapi.mk +++ b/contrib/depends/packages/hidapi.mk @@ -13,6 +13,7 @@ $(package)_config_opts_linux+=libudev_LIBS="-L$(host_prefix)/lib -ludev" $(package)_config_opts_linux+=libudev_CFLAGS=-I$(host_prefix)/include $(package)_config_opts_linux+=libusb_LIBS="-L$(host_prefix)/lib -lusb-1.0" $(package)_config_opts_linux+=libusb_CFLAGS=-I$(host_prefix)/include/libusb-1.0 +$(package)_config_opts_linux+=--with-pic endef define $(package)_config_cmds From 6653062e6135e37fd36d81c575e70ef33b02609b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 10:44:51 +0000 Subject: [PATCH 0067/1007] unit_tests: add unit test for alloc alignment being a power of 2 --- tests/unit_tests/aligned.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/unit_tests/aligned.cpp b/tests/unit_tests/aligned.cpp index ad4837bec..2b733faf2 100644 --- a/tests/unit_tests/aligned.cpp +++ b/tests/unit_tests/aligned.cpp @@ -84,3 +84,24 @@ TEST(aligned, contents_smaller) aligned_free(ptr2); } +TEST(aligned, alignment) +{ + static const size_t good_alignments[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}; + for (size_t a = 0; a <= 8192; ++a) + { + bool good = false; + for (const auto t: good_alignments) if (a == t) good = true; + void *ptr = aligned_malloc(1, a); + if (good) + { + ASSERT_TRUE(ptr != NULL); + aligned_free(ptr); + } + else + { + ASSERT_TRUE(ptr == NULL); + } + } + + ASSERT_TRUE(aligned_malloc(1, ~0) == NULL); +} From a39c0358466e3816885ea0786b3a0e997fdde673 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 10:34:24 +0000 Subject: [PATCH 0068/1007] blockchain: add check test options are given for fakechain mode Coverity 188616 --- src/cryptonote_core/blockchain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 6c6e024e4..96f3bc7e5 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -341,6 +341,9 @@ uint64_t Blockchain::get_current_blockchain_height() const bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback get_checkpoints/* = nullptr*/) { LOG_PRINT_L3("Blockchain::" << __func__); + + CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options"); + CRITICAL_REGION_LOCAL(m_tx_pool); CRITICAL_REGION_LOCAL1(m_blockchain_lock); From 6ca00b6d75fbd4a06456e23e5982e72ca8e5ba17 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 12:09:44 +0000 Subject: [PATCH 0069/1007] miner: really reset flags/precision on std::cout --- src/cryptonote_basic/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 2bd43de94..d0b03593e 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -201,7 +201,7 @@ namespace cryptonote float hr = static_cast(total_hr)/static_cast(m_last_hash_rates.size()); const auto flags = std::cout.flags(); const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << flags << precision << ENDL; + std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << std::setiosflags(flags) << std::setprecision(precision) << ENDL; } } m_last_hr_merge_time = misc_utils::get_tick_count(); From 2e2daebcc9c2e664070670efb3cad81618567f0b Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Thu, 9 Nov 2017 21:11:20 +0100 Subject: [PATCH 0070/1007] ANSI colors in Windows 10 --- contrib/epee/src/mlog.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 61d853ef4..638155b6b 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -28,6 +28,13 @@ #ifndef _MLOG_H_ #define _MLOG_H_ +#ifdef _WIN32 +#include +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif +#endif + #include #include #include @@ -117,6 +124,31 @@ static const char *get_default_categories(int level) return categories; } +#ifdef WIN32 +bool EnableVTMode() +{ + // Set output mode to handle virtual terminal sequences + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) + { + return false; + } + + DWORD dwMode = 0; + if (!GetConsoleMode(hOut, &dwMode)) + { + return false; + } + + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) + { + return false; + } + return true; +} +#endif + void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files) { el::Configurations c; @@ -202,6 +234,9 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s monero_log = get_default_categories(0); } mlog_set_log(monero_log); +#ifdef WIN32 + EnableVTMode(); +#endif } void mlog_set_categories(const char *categories) From 6d0ca4e25ef2a0962583697d6afe1fbf22aa44c8 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Mon, 8 Oct 2018 15:53:22 +0200 Subject: [PATCH 0071/1007] Prepare Depends Packages for Gitian Scripts The gitian environment does not treat whitespaces in configure lines, like most other systems. The solution is to just remove them. --- contrib/depends/packages/libiconv.mk | 15 ++++++++++++++- contrib/depends/packages/sodium.mk | 2 ++ .../depends/patches/libiconv/fix-whitespace.patch | 13 +++++++++++++ .../depends/patches/sodium/fix-whitespace.patch | 13 +++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 contrib/depends/patches/libiconv/fix-whitespace.patch create mode 100644 contrib/depends/patches/sodium/fix-whitespace.patch diff --git a/contrib/depends/packages/libiconv.mk b/contrib/depends/packages/libiconv.mk index 87e30b208..dbcb28141 100644 --- a/contrib/depends/packages/libiconv.mk +++ b/contrib/depends/packages/libiconv.mk @@ -3,9 +3,22 @@ $(package)_version=1.15 $(package)_download_path=https://ftp.gnu.org/gnu/libiconv $(package)_file_name=libiconv-$($(package)_version).tar.gz $(package)_sha256_hash=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 +$(package)_patches=fix-whitespace.patch + +define $(package)_set_vars + $(package)_config_opts=--disable-nls + $(package)_config_opts=--enable-static + $(package)_config_opts=--disable-shared + $(package)_config_opts_linux=--with-pic +endef + +define $(package)_preprocess_cmds + cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux/ &&\ + patch -p1 < $($(package)_patch_dir)/fix-whitespace.patch +endef define $(package)_config_cmds - $($(package)_autoconf) --disable-nls --enable-static --disable-shared + $($(package)_autoconf) endef define $(package)_build_cmds diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk index c38121bf7..35f444fd5 100644 --- a/contrib/depends/packages/sodium.mk +++ b/contrib/depends/packages/sodium.mk @@ -3,6 +3,7 @@ $(package)_version=1.0.15 $(package)_download_path=https://download.libsodium.org/libsodium/releases/ $(package)_file_name=libsodium-$($(package)_version).tar.gz $(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 +$(package)_patches=fix-whitespace.patch define $(package)_set_vars $(package)_config_opts=--enable-static --disable-shared @@ -11,6 +12,7 @@ endef define $(package)_config_cmds ./autogen.sh &&\ + patch -p1 < $($(package)_patch_dir)/fix-whitespace.patch &&\ $($(package)_autoconf) $($(package)_config_opts) endef diff --git a/contrib/depends/patches/libiconv/fix-whitespace.patch b/contrib/depends/patches/libiconv/fix-whitespace.patch new file mode 100644 index 000000000..531364b45 --- /dev/null +++ b/contrib/depends/patches/libiconv/fix-whitespace.patch @@ -0,0 +1,13 @@ +diff --git a/preload/configure b/preload/configure +index aab5c77..e20b8f0 100755 +--- a/preload/configure ++++ b/preload/configure +@@ -588,7 +588,7 @@ MAKEFLAGS= + PACKAGE_NAME='libiconv' + PACKAGE_TARNAME='libiconv' + PACKAGE_VERSION='0' +-PACKAGE_STRING='libiconv 0' ++PACKAGE_STRING='libiconv0' + PACKAGE_BUGREPORT='' + PACKAGE_URL='' + diff --git a/contrib/depends/patches/sodium/fix-whitespace.patch b/contrib/depends/patches/sodium/fix-whitespace.patch new file mode 100644 index 000000000..c11838611 --- /dev/null +++ b/contrib/depends/patches/sodium/fix-whitespace.patch @@ -0,0 +1,13 @@ +diff --git a/configure b/configure +index b29f769..ca008ae 100755 +--- a/configure ++++ b/configure +@@ -591,7 +591,7 @@ MAKEFLAGS= + PACKAGE_NAME='libsodium' + PACKAGE_TARNAME='libsodium' + PACKAGE_VERSION='1.0.15' +-PACKAGE_STRING='libsodium 1.0.15' ++PACKAGE_STRING='libsodium' + PACKAGE_BUGREPORT='https://github.com/jedisct1/libsodium/issues' + PACKAGE_URL='https://github.com/jedisct1/libsodium' + From c5a97315eede7588d0cb1e27375c72d044417cb6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 14:17:41 +0000 Subject: [PATCH 0072/1007] Remove last traces of libpcsc-lite --- README.md | 3 +-- src/device/device_ledger.cpp | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index bce41f5cf..85c64ff35 100644 --- a/README.md +++ b/README.md @@ -150,14 +150,13 @@ library archives (`.a`). | GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite | | Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | | Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | -| pcsclite | ? | NO | `libpcsclite-dev` | ? | `pcsc-lite pcsc-lite-devel` | NO | Ledger | [^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ``` Debian / Ubuntu one liner for all dependencies -``` sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpcsclite-dev libpgm-dev``` +``` sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev``` ### Cloning the repository diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 456eda739..464cb0d90 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -48,21 +48,12 @@ namespace hw { /* ===================================================================== */ /* === Debug ==== */ /* ===================================================================== */ - #ifdef WIN32 - static char *pcsc_stringify_error(LONG rv) { - static __thread char out[20]; - sprintf_s(out, sizeof(out), "0x%08lX", rv); - - return out; - } - #endif void set_apdu_verbose(bool verbose) { apdu_verbose = verbose; } #define TRACKD MTRACE("hw") - #define ASSERT_RV(rv) CHECK_AND_ASSERT_THROW_MES((rv)==SCARD_S_SUCCESS, "Fail SCard API : (" << (rv) << ") "<< pcsc_stringify_error(rv)<<" Device="<id<<", hCard="< Date: Mon, 8 Oct 2018 15:55:38 +0200 Subject: [PATCH 0073/1007] Add gitian build script This adds a build script to run gitian builds for linux. The build script was copied from bitcoin and then adapted for monero. Build step documentation is outlined in the README in the contrib/gitian directory. --- contrib/gitian/README.md | 158 ++++++++++++++++++++++ contrib/gitian/gitian-build.py | 229 ++++++++++++++++++++++++++++++++ contrib/gitian/gitian-linux.yml | 162 ++++++++++++++++++++++ contrib/gitian/symbol-check.py | 163 +++++++++++++++++++++++ 4 files changed, 712 insertions(+) create mode 100644 contrib/gitian/README.md create mode 100755 contrib/gitian/gitian-build.py create mode 100644 contrib/gitian/gitian-linux.yml create mode 100755 contrib/gitian/symbol-check.py diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md new file mode 100644 index 000000000..1f7d158eb --- /dev/null +++ b/contrib/gitian/README.md @@ -0,0 +1,158 @@ +Gitian building +================ + +*Setup instructions for a Gitian build of Monero using a VM or physical system.* + +Gitian is the deterministic build process that is used to build the Bitcoin +Core executables. It provides a way to be reasonably sure that the +executables are really built from the git source. It also makes sure that +the same, tested dependencies are used and statically built into the executable. + +Multiple developers build the source code by following a specific descriptor +("recipe"), cryptographically sign the result, and upload the resulting signature. +These results are compared and only if they match, the build is accepted and provided +for download. + +More independent Gitian builders are needed, which is why this guide exists. +It is preferred you follow these steps yourself instead of using someone else's +VM image to avoid 'contaminating' the build. + +Table of Contents +------------------ + +Please note that these instructions have been forked from bitcoin's gitian build +instructions. Please also consult their documentation, when running into problems. +The signing is left as inherited from bitcoin at the moment, since building currently +still fails with libiconv. + +- [Preparing the Gitian builder host](#preparing-the-gitian-builder-host) +- [Getting and building the inputs](#getting-and-building-the-inputs) +- [Building Binaries](#building-bitcoin-core) +- [Signing externally](#signing-externally) +- [Uploading signatures](#uploading-signatures) + +Preparing the Gitian builder host +--------------------------------- + +The first step is to prepare the host environment that will be used to perform the Gitian builds. +This guide explains how to set up the environment, and how to start the builds. + +Gitian builds are for now executed on Ubuntu 18.04 "Bionic Beaver". Please run Ubuntu in either a VM, or on your physical machine. +You need to be logged in as the `gitianuser` in order to build gitian builds. If this user does not exist yet on your system, +create him. + +Note that a version of `lxc-execute` higher or equal to 2.1.1 is required. +You can check the version with `lxc-execute --version`. + +First we need to set up dependencies. Type/paste the following in the terminal: + +```bash +sudo apt-get install git ruby apt-cacher-ng qemu-utils debootstrap lxc python-cheetah parted kpartx bridge-utils make ubuntu-archive-keyring curl firewalld +``` + +Then set up LXC and the rest with the following, which is a complex jumble of settings and workarounds: + +```bash +sudo -s +# the version of lxc-start in Debian needs to run as root, so make sure +# that the build script can execute it without providing a password +echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-start" > /etc/sudoers.d/gitian-lxc +echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-execute" >> /etc/sudoers.d/gitian-lxc +# make /etc/rc.local script that sets up bridge between guest and host +echo '#!/bin/sh -e' > /etc/rc.local +echo 'brctl addbr br0' >> /etc/rc.local +echo 'ip addr add 10.0.3.1/24 broadcast 10.0.3.255 dev br0' >> /etc/rc.local +echo 'ip link set br0 up' >> /etc/rc.local +echo 'firewall-cmd --zone=trusted --add-interface=br0' >> /etc/rc.local +echo 'exit 0' >> /etc/rc.local +chmod +x /etc/rc.local +# make sure that USE_LXC is always set when logging in as gitianuser, +# and configure LXC IP addresses +echo 'export USE_LXC=1' >> /home/gitianuser/.profile +echo 'export GITIAN_HOST_IP=10.0.3.1' >> /home/gitianuser/.profile +echo 'export LXC_GUEST_IP=10.0.3.5' >> /home/gitianuser/.profile +reboot +``` + +This setup is required to enable networking in the container. + + +Manual and Building +------------------- +The instructions below use the automated script [gitian-build.py](https://github.com/betcoin/bitcoin/blob/master/contrib/gitian-build.py) which only works in Ubuntu. For manual steps and instructions for fully offline signing, see [this guide](./gitian-building/gitian-building-manual.md). + +MacOS code signing +------------------ +In order to sign builds for MacOS, you need to download the free SDK and extract a file. The steps are described [here](./gitian-building/gitian-building-mac-os-sdk.md). Alternatively, you can skip the OSX build by adding `--os=lw` below. + +Initial Gitian Setup +-------------------- +The `gitian-build.py` script will checkout different release tags, so it's best to copy it: + +```bash +cp monero/contrib/gitian/gitian-build.py . +``` + +You only need to do this once: + +``` +./gitian-build.py --setup fluffypony 0.0.20 +``` + +Where `fluffypony` is your Github name and `0.0.20` is the most recent tag (without `v`). + +In order to sign gitian builds on your host machine, which has your PGP key, fork the gitian.sigs repository and clone it on your host machine: + +``` +git clone git@github.com:bitcoin-core/gitian.sigs.git +git remote add satoshi git@github.com:satoshi/gitian.sigs.git +``` + +Build Binaries +----------------------------- +Windows and OSX have code signed binaries, but those won't be available until a few developers have gitian signed the non-codesigned binaries. + +To build the most recent tag: + + `./gitian-build.py --detach-sign --no-commit -b fluffypony 0.0.20` + +To speed up the build, use `-j 5 -m 5000` as the first arguments, where `5` is the number of CPU's you allocated to the VM plus one, and 5000 is a little bit less than then the MB's of RAM you allocated. If there is memory corruption on your machine, try to tweak these values. + +If all went well, this produces a number of (uncommited) `.assert` files in the gitian.sigs repository. + +You need to copy these uncommited changes to your host machine, where you can sign them: + +``` +export NAME=satoshi +gpg --output $VERSION-linux/$NAME/bitcoin-linux-0.16-build.assert.sig --detach-sign 0.16.0rc1-linux/$NAME/bitcoin-linux-0.16-build.assert +gpg --output $VERSION-osx-unsigned/$NAME/bitcoin-osx-0.16-build.assert.sig --detach-sign 0.16.0rc1-osx-unsigned/$NAME/bitcoin-osx-0.16-build.assert +gpg --output $VERSION-win-unsigned/$NAME/bitcoin-win-0.16-build.assert.sig --detach-sign 0.16.0rc1-win-unsigned/$NAME/bitcoin-win-0.16-build.assert +``` + +Make a PR (both the `.assert` and `.assert.sig` files) to the +[bitcoin-core/gitian.sigs](https://github.com/bitcoin-core/gitian.sigs/) repository: + +``` +git checkout -b 0.0.20-not-codesigned +git commit -S -a -m "Add $NAME 0.0.20 non-code signed signatures" +git push --set-upstream $NAME 0.0.20 +``` + +You can also mail the files to Wladimir (laanwj@gmail.com) and he will commit them. + +```bash + gpg --detach-sign ${VERSION}-linux/${SIGNER}/bitcoin-linux-*-build.assert + gpg --detach-sign ${VERSION}-win-unsigned/${SIGNER}/bitcoin-win-*-build.assert + gpg --detach-sign ${VERSION}-osx-unsigned/${SIGNER}/bitcoin-osx-*-build.assert +``` + +You may have other .assert files as well (e.g. `signed` ones), in which case you should sign them too. You can see all of them by doing `ls ${VERSION}-*/${SIGNER}`. + +This will create the `.sig` files that can be committed together with the `.assert` files to assert your +Gitian build. + + + `./gitian-build.py --detach-sign -s satoshi 0.16.0rc1 --nocommit` + +Make another pull request for these. + diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py new file mode 100755 index 000000000..bd7e70a71 --- /dev/null +++ b/contrib/gitian/gitian-build.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 + +import argparse +import os +import subprocess +import sys + +def setup(): + global args, workdir + programs = ['ruby', 'git', 'apt-cacher-ng', 'make', 'wget'] + if args.kvm: + programs += ['python-vm-builder', 'qemu-kvm', 'qemu-utils'] + elif args.docker: + dockers = ['docker.io', 'docker-ce'] + for i in dockers: + return_code = subprocess.call(['sudo', 'apt-get', 'install', '-qq', i]) + if return_code == 0: + break + if return_code != 0: + print('Cannot find any way to install docker', file=sys.stderr) + exit(1) + else: + programs += ['lxc', 'debootstrap'] + subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs) + if not os.path.isdir('gitian.sigs'): + subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/gitian.sigs.git']) + if not os.path.isdir('monero-detached-sigs'): + subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/bitcoin-detached-sigs.git']) + if not os.path.isdir('gitian-builder'): + subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git']) + if not os.path.isdir('monero'): + subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/monero.git']) + os.chdir('gitian-builder') + make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64'] + if args.docker: + make_image_prog += ['--docker'] + elif not args.kvm: + make_image_prog += ['--lxc'] + subprocess.check_call(make_image_prog) + os.chdir(workdir) + if args.is_bionic and not args.kvm and not args.docker: + subprocess.check_call(['sudo', 'sed', '-i', 's/lxcbr0/br0/', '/etc/default/lxc-net']) + print('Reboot is required') + exit(0) + +def build(): + global args, workdir + + os.makedirs('monero-binaries/' + args.version, exist_ok=True) + print('\nBuilding Dependencies\n') + os.chdir('gitian-builder') + os.makedirs('inputs', exist_ok=True) + + subprocess.check_call(['wget', '-N', '-P', 'inputs', 'http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz']) + subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch']) + subprocess.check_call(['make', '-C', '../monero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) + + if args.linux: + print('\nCompiling ' + args.version + ' Linux') + subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-linux.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-linux', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-linux.yml']) + subprocess.check_call('mv build/out/monero-*.tar.gz build/out/monero-*.tar.gz ../monero-binaries/'+args.version, shell=True) + + if args.windows: + print('\nCompiling ' + args.version + ' Windows') + subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-win.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win.yml']) + subprocess.check_call('mv build/out/monero*-win-unsigned.tar.gz inputs/monerowin-unsigned.tar.gz', shell=True) + subprocess.check_call('mv build/out/monero*.zip build/out/monero*.exe ../monerobinaries/'+args.version, shell=True) + + if args.macos: + print('\nCompiling ' + args.version + ' MacOS') + subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero'+args.commit, '--url', 'monero'+args.url, '../monero/contrib/gitian/gitian-osx.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx.yml']) + subprocess.check_call('mv build/out/monero*-osx-unsigned.tar.gz inputs/moneroosx-unsigned.tar.gz', shell=True) + subprocess.check_call('mv build/out/monero*.tar.gz build/out/monero*.dmg ../monerobinaries/'+args.version, shell=True) + + os.chdir(workdir) + + if args.commit_files: + print('\nCommitting '+args.version+' Unsigned Sigs\n') + os.chdir('gitian.sigs') + subprocess.check_call(['git', 'add', args.version+'-linux/'+args.signer]) + subprocess.check_call(['git', 'add', args.version+'-win-unsigned/'+args.signer]) + subprocess.check_call(['git', 'add', args.version+'-osx-unsigned/'+args.signer]) + subprocess.check_call(['git', 'commit', '-m', 'Add '+args.version+' unsigned sigs for '+args.signer]) + os.chdir(workdir) + +def sign(): + global args, workdir + os.chdir('gitian-builder') + + if args.windows: + print('\nSigning ' + args.version + ' Windows') + subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../monero/contrib/gitian/gitian-win-signer.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win-signer.yml']) + subprocess.check_call('mv build/out/monero*win64-setup.exe ../monerobinaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/monero*win32-setup.exe ../monerobinaries/'+args.version, shell=True) + + if args.macos: + print('\nSigning ' + args.version + ' MacOS') + subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../monero/contrib/gitian/gitian-osx-signer.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx-signer.yml']) + subprocess.check_call('mv build/out/moneroosx-signed.dmg ../monerobinaries/'+args.version+'/monero'+args.version+'-osx.dmg', shell=True) + + os.chdir(workdir) + + if args.commit_files: + print('\nCommitting '+args.version+' Signed Sigs\n') + os.chdir('gitian.sigs') + subprocess.check_call(['git', 'add', args.version+'-win-signed/'+args.signer]) + subprocess.check_call(['git', 'add', args.version+'-osx-signed/'+args.signer]) + subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' signed binary sigs for '+args.signer]) + os.chdir(workdir) + +def verify(): + global args, workdir + os.chdir('gitian-builder') + + print('\nVerifying v'+args.version+' Linux\n') + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-linux', '../monero/contrib/gitian/gitian-linux.yml']) + print('\nVerifying v'+args.version+' Windows\n') + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-unsigned', '../monero/contrib/gitian/gitian-win.yml']) + print('\nVerifying v'+args.version+' MacOS\n') + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-unsigned', '../monero/contrib/gitian/gitian-osx.yml']) + print('\nVerifying v'+args.version+' Signed Windows\n') + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-signed', '../monero/contrib/gitian/gitian-win-signer.yml']) + print('\nVerifying v'+args.version+' Signed MacOS\n') + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-signed', '../monero/contrib/gitian/gitian-osx-signer.yml']) + + os.chdir(workdir) + +def main(): + global args, workdir + + parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version') + parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch') + parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request') + parser.add_argument('-u', '--url', dest='url', default='https://github.com/TheCharlatan/monero', help='Specify the URL of the repository. Default is %(default)s') + parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') + parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') + parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS') + parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries') + parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS') + parser.add_argument('-j', '--jobs', dest='jobs', default='2', help='Number of processes to use. Default %(default)s') + parser.add_argument('-m', '--memory', dest='memory', default='2000', help='Memory to allocate in MiB. Default %(default)s') + parser.add_argument('-k', '--kvm', action='store_true', dest='kvm', help='Use KVM instead of LXC') + parser.add_argument('-d', '--docker', action='store_true', dest='docker', help='Use Docker instead of LXC') + parser.add_argument('-S', '--setup', action='store_true', dest='setup', help='Set up the Gitian building environment. Uses LXC. If you want to use KVM, use the --kvm option. Only works on Debian-based systems (Ubuntu, Debian)') + parser.add_argument('-D', '--detach-sign', action='store_true', dest='detach_sign', help='Create the assert file for detached signing. Will not commit anything.') + parser.add_argument('-n', '--no-commit', action='store_false', dest='commit_files', help='Do not commit anything to git') + parser.add_argument('signer', help='GPG signer to sign each build assert file') + parser.add_argument('version', help='Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified') + + args = parser.parse_args() + workdir = os.getcwd() + + args.linux = 'l' in args.os + args.windows = 'w' in args.os + args.macos = 'm' in args.os + + args.is_bionic = b'bionic' in subprocess.check_output(['lsb_release', '-cs']) + + if args.buildsign: + args.build=True + args.sign=True + + if args.kvm and args.docker: + raise Exception('Error: cannot have both kvm and docker') + + args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign' + + # Set enviroment variable USE_LXC or USE_DOCKER, let gitian-builder know that we use lxc or docker + if args.docker: + os.environ['USE_DOCKER'] = '1' + elif not args.kvm: + os.environ['USE_LXC'] = '1' + if not 'GITIAN_HOST_IP' in os.environ.keys(): + os.environ['GITIAN_HOST_IP'] = '10.0.3.1' + if not 'LXC_GUEST_IP' in os.environ.keys(): + os.environ['LXC_GUEST_IP'] = '10.0.3.5' + + # Disable for MacOS if no SDK found + if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.11.sdk.tar.gz'): + print('Cannot build for MacOS, SDK does not exist. Will build for other OSes') + args.macos = False + + script_name = os.path.basename(sys.argv[0]) + # Signer and version shouldn't be empty + if args.signer == '': + print(script_name+': Missing signer.') + print('Try '+script_name+' --help for more information') + exit(1) + if args.version == '': + print(script_name+': Missing version.') + print('Try '+script_name+' --help for more information') + exit(1) + + # Add leading 'v' for tags + if args.commit and args.pull: + raise Exception('Cannot have both commit and pull') + args.commit = ('' if args.commit else 'v') + args.version + + if args.setup: + setup() + + os.chdir('monero') + if args.pull: + subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge']) + os.chdir('../gitian-builder/inputs/monero') + subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge']) + args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True).strip() + args.version = 'pull-' + args.version + print(args.commit) + subprocess.check_call(['git', 'fetch']) + subprocess.check_call(['git', 'checkout', args.commit]) + os.chdir(workdir) + + if args.build: + build() + + if args.sign: + sign() + + if args.verify: + verify() + +if __name__ == '__main__': + main() diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml new file mode 100644 index 000000000..751fbadd3 --- /dev/null +++ b/contrib/gitian/gitian-linux.yml @@ -0,0 +1,162 @@ +--- +name: "monero-linux-0.18" +enable_cache: true +suites: +- "bionic" +architectures: +- "amd64" +packages: +- "curl" +- "gperf" +- "gcc-7" +- "g++-7" +- "gcc" +- "g++" +- "gcc-7-aarch64-linux-gnu" +- "g++-7-aarch64-linux-gnu" +- "gcc-aarch64-linux-gnu" +- "g++-aarch64-linux-gnu" +- "binutils-aarch64-linux-gnu" +- "gcc-7-arm-linux-gnueabihf" +- "g++-7-arm-linux-gnueabihf" +- "gcc-arm-linux-gnueabihf" +- "g++-arm-linux-gnueabihf" +- "g++-7-multilib" +- "gcc-7-multilib" +- "binutils-arm-linux-gnueabihf" +- "binutils-gold" +- "git" +- "pkg-config" +- "build-essential" +- "autoconf" +- "libtool" +- "automake" +- "faketime" +- "bsdmainutils" +- "ca-certificates" +- "python" +- "cmake" +- "ccache" +- "protobuf-compiler" +- "libdbus-1-dev" +- "libharfbuzz-dev" +- "libprotobuf-dev" +- "python3-zmq" +remotes: +- "url": "https://github.com/TheCharlatan/monero.git" + "dir": "monero" +files: [] +script: | + + WRAP_DIR=$HOME/wrapped + HOSTS="x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu i686-linux-gnu" + FAKETIME_HOST_PROGS="gcc g++" + FAKETIME_PROGS="date ar ranlib nm" + HOST_CFLAGS="-O2 -g" + HOST_CXXFLAGS="-O2 -g" + HOST_LDFLAGS=-static-libstdc++ + + export GZIP="-9n" + export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export TZ="UTC" + export BUILD_DIR=`pwd` + mkdir -p ${WRAP_DIR} + if test -n "$GBUILD_CACHE_ENABLED"; then + export SOURCES_PATH=${GBUILD_COMMON_CACHE} + export BASE_CACHE=${GBUILD_PACKAGE_CACHE} + mkdir -p ${BASE_CACHE} ${SOURCES_PATH} + fi + + function create_global_faketime_wrappers { + for prog in ${FAKETIME_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} + echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${prog} + chmod +x ${WRAP_DIR}/${prog} + done + } + + function create_per-host_faketime_wrappers { + for i in $HOSTS; do + for prog in ${FAKETIME_HOST_PROGS}; do + if which ${i}-${prog}-7 + then + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} + echo "REAL=\`which -a ${i}-${prog}-7 | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} + chmod +x ${WRAP_DIR}/${i}-${prog} + fi + done + done + } + + # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} + + EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes + mkdir -p $EXTRA_INCLUDES_BASE + + # x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm, + # but we can't write there. Instead, create a link here and force it to be included in the + # search paths by wrapping gcc/g++. + + mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu + rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm + ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm + + for prog in gcc g++; do + rm -f ${WRAP_DIR}/${prog} + cat << EOF > ${WRAP_DIR}/${prog} + #!/usr/bin/env bash + REAL="`which -a ${prog}-7 | grep -v ${WRAP_DIR}/${prog} | head -1`" + for var in "\$@" + do + if [ "\$var" = "-m32" ]; then + export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + break + fi + done + \$REAL \$@ + EOF + chmod +x ${WRAP_DIR}/${prog} + done + + cd monero + BASEPREFIX=`pwd`/contrib/depends + # Build dependencies for each host + for i in $HOSTS; do + EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$EXTRA_INCLUDES" ]; then + export HOST_ID_SALT="$EXTRA_INCLUDES" + fi + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" -j 4 V=1 + unset HOST_ID_SALT + done + + # Faketime for binaries + export PATH=${PATH_orig} + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} + + ORIGPATH="$PATH" + # Extract the release tarball into a dir for each host and build + for i in ${HOSTS}; do + export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} + mkdir build && cd build + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake + make + DISTNAME=monero-${i}.tar.gz + tar -cvzf $DISTNAME bin/* + cp $DISTNAME $OUTDIR/ + cd .. + rm -rf build + done diff --git a/contrib/gitian/symbol-check.py b/contrib/gitian/symbol-check.py new file mode 100755 index 000000000..6808e77da --- /dev/null +++ b/contrib/gitian/symbol-check.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# 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. +''' +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 +still compatible with the minimum supported Linux distribution versions. + +Example usage: + + find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py +''' +import subprocess +import re +import sys +import os + +# Debian 6.0.9 (Squeeze) has: +# +# - g++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=g%2B%2B) +# - libc version 2.11.3 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libc6) +# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libstdc%2B%2B6) +# +# Ubuntu 10.04.4 (Lucid Lynx) has: +# +# - g++ version 4.4.3 (http://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=lucid§ion=all) +# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid§ion=all) +# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid§ion=all&arch=any&keywords=libstdc%2B%2B&searchon=names) +# +# Taking the minimum of these as our target. +# +# According to GNU ABI document (http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to: +# GCC 4.4.0: GCC_4.4.0 +# GCC 4.4.2: GLIBCXX_3.4.13, CXXABI_1.3.3 +# (glibc) GLIBC_2_11 +# +MAX_VERSIONS = { +'GCC': (4,4,0), +'CXXABI': (1,3,3), +'GLIBCXX': (3,4,13), +'GLIBC': (2,11) +} +# See here for a description of _IO_stdin_used: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109 + +# Ignore symbols that are exported as part of every executable +IGNORE_EXPORTS = { +'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr' +} +READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') +CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') +# Allowed NEEDED libraries +ALLOWED_LIBRARIES = { +# bitcoind and bitcoin-qt +'libgcc_s.so.1', # GCC base support +'libc.so.6', # C library +'libpthread.so.0', # threading +'libanl.so.1', # DNS resolve +'libm.so.6', # math library +'librt.so.1', # real-time (clock) +'ld-linux-x86-64.so.2', # 64-bit dynamic linker +'ld-linux.so.2', # 32-bit dynamic linker +# bitcoin-qt only +'libX11-xcb.so.1', # part of X11 +'libX11.so.6', # part of X11 +'libxcb.so.1', # part of X11 +'libfontconfig.so.1', # font support +'libfreetype.so.6', # font parsing +'libdl.so.2' # programming interface to dynamic linker +} + +class CPPFilt(object): + ''' + Demangle C++ symbol names. + + Use a pipe to the 'c++filt' command. + ''' + def __init__(self): + self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) + + def __call__(self, mangled): + self.proc.stdin.write(mangled + '\n') + self.proc.stdin.flush() + return self.proc.stdout.readline().rstrip() + + def close(self): + self.proc.stdin.close() + self.proc.stdout.close() + self.proc.wait() + +def read_symbols(executable, imports=True): + ''' + Parse an ELF executable and return a list of (symbol,version) tuples + for dynamic, imported symbols. + ''' + p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True) + (stdout, stderr) = p.communicate() + if p.returncode: + raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip())) + syms = [] + for line in stdout.splitlines(): + line = line.split() + if len(line)>7 and re.match('[0-9]+:$', line[0]): + (sym, _, version) = line[7].partition('@') + is_import = line[6] == 'UND' + if version.startswith('@'): + version = version[1:] + if is_import == imports: + syms.append((sym, version)) + return syms + +def check_version(max_versions, version): + if '_' in version: + (lib, _, ver) = version.rpartition('_') + else: + lib = version + ver = '0' + ver = tuple([int(x) for x in ver.split('.')]) + if not lib in max_versions: + return False + return ver <= max_versions[lib] + +def read_libraries(filename): + p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True) + (stdout, stderr) = p.communicate() + if p.returncode: + raise IOError('Error opening file') + libraries = [] + for line in stdout.splitlines(): + tokens = line.split() + if len(tokens)>2 and tokens[1] == '(NEEDED)': + match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:])) + if match: + libraries.append(match.group(1)) + else: + raise ValueError('Unparseable (NEEDED) specification') + return libraries + +if __name__ == '__main__': + cppfilt = CPPFilt() + retval = 0 + for filename in sys.argv[1:]: + # Check imported symbols + for sym,version in read_symbols(filename, True): + if version and not check_version(MAX_VERSIONS, version): + print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version)) + retval = 1 + # Check exported symbols + for sym,version in read_symbols(filename, False): + if sym in IGNORE_EXPORTS: + continue + print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym))) + retval = 1 + # Check dependency libraries + for library_name in read_libraries(filename): + if library_name not in ALLOWED_LIBRARIES: + print('%s: NEEDED library %s is not allowed' % (filename, library_name)) + retval = 1 + + sys.exit(retval) + + From c95a14088c9105e9be793889128425981e2a3bd1 Mon Sep 17 00:00:00 2001 From: erciccione Date: Mon, 8 Oct 2018 18:33:16 +0100 Subject: [PATCH 0074/1007] CMakeLists.txt: Fix typo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ade7a290d..ae1251007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,7 +186,7 @@ if(NOT MANUAL_SUBMODULES) string(COMPARE EQUAL "${unboundLocalHead}" "${unboundCheckedHead}" unboundUpToDate) string(COMPARE EQUAL "${rapidjsonLocalHead}" "${rapidjsonCheckedHead}" rapidjsonUpToDate) if (NOT miniupnpUpToDate OR NOT unboundUpToDate OR NOT rapidjsonUpToDate) - message(FATAL_ERROR "Submodules not up to date. Please update with git subdmoule init && git submodule update, or run cmake with -DMANUAL_SUBMODULES=1") + message(FATAL_ERROR "Submodules not up to date. Please update with git submodule init && git submodule update, or run cmake with -DMANUAL_SUBMODULES=1") endif() endif() endif() From 77471e23bd20fa90249adb2ba735467c02ebb837 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 17:36:51 +0000 Subject: [PATCH 0075/1007] blockchain_blackball: fix stray ! --- src/blockchain_utilities/blockchain_blackball.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 00baad7f0..03ff3cdcd 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -1233,7 +1233,7 @@ int main(int argc, char* argv[]) std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); - if (!add_spent_output(cur, output_data(txin.amount, absolute[o]))) + if (add_spent_output(cur, output_data(txin.amount, absolute[o]))) inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); } } From 8f22e808650a0d599913f608441515f9d985cced Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 17:12:35 +0000 Subject: [PATCH 0076/1007] device: destroy device objects on exit --- src/device/device.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/device/device.cpp b/src/device/device.cpp index 50041baef..d5e3031ff 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -41,13 +41,26 @@ namespace hw { /* SETUP */ /* ======================================================================= */ - static std::unique_ptr registry; + static device_registry *get_device_registry(bool clear = false){ + static device_registry *registry = new device_registry(); + if (clear) + { + delete registry; + registry = NULL; + } + return registry; + } + + static void clear_device_registry(){ + get_device_registry(true); + } device_registry::device_registry(){ hw::core::register_all(registry); #ifdef WITH_DEVICE_LEDGER hw::ledger::register_all(registry); #endif + atexit(clear_device_registry); } bool device_registry::register_device(const std::string & device_name, device * hw_device){ @@ -80,18 +93,12 @@ namespace hw { } device& get_device(const std::string & device_descriptor) { - if (!registry){ - registry.reset(new device_registry()); - } - + device_registry *registry = get_device_registry(); return registry->get_device(device_descriptor); } bool register_device(const std::string & device_name, device * hw_device){ - if (!registry){ - registry.reset(new device_registry()); - } - + device_registry *registry = get_device_registry(); return registry->register_device(device_name, hw_device); } From ac5674524a485c069800912f79b1b44840e391fc Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Mon, 8 Oct 2018 21:39:54 +0200 Subject: [PATCH 0077/1007] Revert "Merge pull request #4472" This reverts commit 79d46c4d551a9b1261801960095bf4d24967211a, reversing changes made to c9fc61dbb56cca442c775faa2554a7460879b637. --- CMakeLists.txt | 5 +- src/blockchain_utilities/CMakeLists.txt | 20 ++++- .../blockchain_import.cpp | 8 +- src/blocks/CMakeLists.txt | 35 ++++---- src/blocks/blockexports.c | 87 +++++++++++++++++++ src/blocks/blocks.cpp | 31 ------- src/blocks/blocks.dat | 0 src/blocks/blocks.h | 14 +-- src/cryptonote_config.h | 1 - src/cryptonote_core/CMakeLists.txt | 7 ++ src/cryptonote_core/blockchain.cpp | 29 ++++--- src/cryptonote_core/blockchain.h | 18 +--- src/cryptonote_core/cryptonote_core.cpp | 4 +- src/cryptonote_core/cryptonote_core.h | 3 +- src/daemon/CMakeLists.txt | 21 ++++- src/daemon/core.h | 8 +- src/device/CMakeLists.txt | 7 ++ 17 files changed, 185 insertions(+), 113 deletions(-) create mode 100644 src/blocks/blockexports.c delete mode 100644 src/blocks/blocks.cpp create mode 100644 src/blocks/blocks.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index ade7a290d..b890965f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,9 +199,6 @@ set(PER_BLOCK_CHECKPOINT 1) if(PER_BLOCK_CHECKPOINT) add_definitions("-DPER_BLOCK_CHECKPOINT") - set(Blocks "blocks") -else() - set(Blocks "") endif() list(INSERT CMAKE_MODULE_PATH 0 @@ -677,10 +674,12 @@ else() add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED) if (noexecstack_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack") + set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack) endif() add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED) if (noexecheap_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap") + set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap) endif() # some windows linker bits diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 873bf552c..ecd7b754c 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -26,6 +26,20 @@ # 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. +set(blocksdat "") +if(PER_BLOCK_CHECKPOINT) + if(APPLE AND DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(APPLE AND NOT DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + else() + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + endif() + set(blocksdat "blocksdat.o") +endif() + set(blockchain_import_sources blockchain_import.cpp bootstrap_file.cpp @@ -105,7 +119,8 @@ monero_private_headers(blockchain_depth monero_add_executable(blockchain_import ${blockchain_import_sources} - ${blockchain_import_private_headers}) + ${blockchain_import_private_headers} + ${blocksdat}) target_link_libraries(blockchain_import PRIVATE @@ -117,8 +132,7 @@ target_link_libraries(blockchain_import ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES} - ${Blocks}) + ${EXTRA_LIBRARIES}) if(ARCH_WIDTH) target_compile_definitions(blockchain_import diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 134969dc4..9ec768d26 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -37,7 +37,6 @@ #include "misc_log_ex.h" #include "bootstrap_file.h" #include "bootstrap_serialization.h" -#include "blocks/blocks.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() @@ -759,12 +758,7 @@ int main(int argc, char* argv[]) { core.disable_dns_checkpoints(true); -#if defined(PER_BLOCK_CHECKPOINT) - GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; -#else - GetCheckpointsCallback get_checkpoints = nullptr; -#endif - if (!core.init(vm, nullptr, nullptr, get_checkpoints)) + if (!core.init(vm, NULL)) { std::cerr << "Failed to initialize core" << ENDL; return 1; diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index bedda3b88..ebb5408cc 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -26,23 +26,20 @@ # 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. -set(GENERATED_SOURCES "") +if(APPLE) + add_library(blocks STATIC blockexports.c) + set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) +else() + if(LINUX_32) + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + else() + add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) + add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) + add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) + endif() + add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) + set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) +endif() -foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks) - set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c") - list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE}) - set(INPUT_DAT_FILE "${BLOB_NAME}.dat") - add_custom_command( - OUTPUT ${OUTPUT_C_SOURCE} - MAIN_DEPENDENCY ${INPUT_DAT_FILE} - COMMAND - cd ${CMAKE_CURRENT_BINARY_DIR} && - echo "'#include\t'" > ${OUTPUT_C_SOURCE} && - echo -n "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} && - od -v -An -w1 -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "':a;N;$$!ba;s/\\n/,/g'" >> ${OUTPUT_C_SOURCE} && - echo "'};'" >> ${OUTPUT_C_SOURCE} && - echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE} - ) -endforeach() - -add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES}) diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c new file mode 100644 index 000000000..0154b0413 --- /dev/null +++ b/src/blocks/blockexports.c @@ -0,0 +1,87 @@ +#include + +#if defined(__APPLE__) +#include +#ifdef BUILD_SHARED_LIBS +#if !defined(__LP64__) +const struct mach_header _mh_execute_header; +#else +const struct mach_header_64 _mh_execute_header; +#endif +#else +#if !defined(__LP64__) +extern const struct mach_header _mh_execute_header; +#else +extern const struct mach_header_64 _mh_execute_header; +#endif +#endif + +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) +{ + size_t size; + if (testnet) + return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); + else + return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); +} + +size_t get_blocks_dat_size(int testnet, int stagenet) +{ + size_t size; + if (testnet) + getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); + else if (stagenet) + getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); + else + getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); + return size; +} + +#else + +#if defined(_WIN32) && !defined(_WIN64) +#define _binary_blocks_start binary_blocks_dat_start +#define _binary_blocks_end binary_blocks_dat_end +#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start +#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end +#else +#define _binary_blocks_start _binary_blocks_dat_start +#define _binary_blocks_end _binary_blocks_dat_end +#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start +#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end +#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start +#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end +#endif + +extern const unsigned char _binary_blocks_start[]; +extern const unsigned char _binary_blocks_end[]; +extern const unsigned char _binary_testnet_blocks_start[]; +extern const unsigned char _binary_testnet_blocks_end[]; +extern const unsigned char _binary_stagenet_blocks_start[]; +extern const unsigned char _binary_stagenet_blocks_end[]; + +const unsigned char *get_blocks_dat_start(int testnet, int stagenet) +{ + if (testnet) + return _binary_testnet_blocks_start; + else if (stagenet) + return _binary_stagenet_blocks_start; + else + return _binary_blocks_start; +} + +size_t get_blocks_dat_size(int testnet, int stagenet) +{ + if (testnet) + return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start); + else if (stagenet) + return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start); + else + return (size_t) (_binary_blocks_end - _binary_blocks_start); +} + +#endif diff --git a/src/blocks/blocks.cpp b/src/blocks/blocks.cpp deleted file mode 100644 index 0661f8448..000000000 --- a/src/blocks/blocks.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "blocks.h" - -#include - -extern const unsigned char checkpoints[]; -extern const size_t checkpoints_len; -extern const unsigned char stagenet_blocks[]; -extern const size_t stagenet_blocks_len; -extern const unsigned char testnet_blocks[]; -extern const size_t testnet_blocks_len; - -namespace blocks -{ - - const std::unordered_map, std::hash> CheckpointsByNetwork = { - {cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}, - {cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}}, - {cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}} - }; - - const epee::span GetCheckpointsData(cryptonote::network_type network) - { - const auto it = CheckpointsByNetwork.find(network); - if (it != CheckpointsByNetwork.end()) - { - return it->second; - } - return nullptr; - } - -} diff --git a/src/blocks/blocks.dat b/src/blocks/blocks.dat new file mode 100644 index 000000000..e69de29bb diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h index 14e391319..ec683f47e 100644 --- a/src/blocks/blocks.h +++ b/src/blocks/blocks.h @@ -1,12 +1,16 @@ #ifndef SRC_BLOCKS_BLOCKS_H_ #define SRC_BLOCKS_BLOCKS_H_ -#include "cryptonote_config.h" -#include "span.h" +#ifdef __cplusplus +extern "C" { +#endif -namespace blocks -{ - const epee::span GetCheckpointsData(cryptonote::network_type network); +const unsigned char *get_blocks_dat_start(int testnet, int stagenet); +size_t get_blocks_dat_size(int testnet, int stagenet); + +#ifdef __cplusplus } +#endif + #endif /* SRC_BLOCKS_BLOCKS_H_ */ diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index c62eeb738..a6858ce7c 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -30,7 +30,6 @@ #pragma once -#include #include #include diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 231489fdb..72844db66 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -41,6 +41,12 @@ set(cryptonote_core_private_headers tx_pool.h cryptonote_tx_utils.h) +if(PER_BLOCK_CHECKPOINT) + set(Blocks "blocks") +else() + set(Blocks "") +endif() + monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) monero_add_library(cryptonote_core @@ -63,4 +69,5 @@ target_link_libraries(cryptonote_core ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} PRIVATE + ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 6c6e024e4..eb869b795 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -53,6 +53,9 @@ #include "ringct/rctSigs.h" #include "common/perf_timer.h" #include "common/notify.h" +#if defined(PER_BLOCK_CHECKPOINT) +#include "blocks/blocks.h" +#endif #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "blockchain" @@ -338,7 +341,7 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback get_checkpoints/* = nullptr*/) +bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_tx_pool); @@ -436,7 +439,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline #if defined(PER_BLOCK_CHECKPOINT) if (m_nettype != FAKECHAIN) - load_compiled_in_block_hashes(get_checkpoints); + load_compiled_in_block_hashes(); #endif MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); @@ -4401,21 +4404,19 @@ void Blockchain::cancel() #if defined(PER_BLOCK_CHECKPOINT) static const char expected_block_hashes_hash[] = "954cb2bbfa2fe6f74b2cdd22a1a4c767aea249ad47ad4f7c9445f0f03260f511"; -void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints) +void Blockchain::load_compiled_in_block_hashes() { - if (get_checkpoints == nullptr || !m_fast_sync) - { - return; - } - const epee::span checkpoints = get_checkpoints(m_nettype); - if (!checkpoints.empty()) + const bool testnet = m_nettype == TESTNET; + const bool stagenet = m_nettype == STAGENET; + if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0) { - MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)"); + MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); + if (m_nettype == MAINNET) { // first check hash crypto::hash hash; - if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash)) + if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) { MERROR("Failed to hash precomputed blocks data"); return; @@ -4435,9 +4436,9 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_ } } - if (checkpoints.size() > 4) + if (get_blocks_dat_size(testnet, stagenet) > 4) { - const unsigned char *p = checkpoints.data(); + const unsigned char *p = get_blocks_dat_start(testnet, stagenet); const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24); if (nblocks > (std::numeric_limits::max() - 4) / sizeof(hash)) { @@ -4445,7 +4446,7 @@ void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback get_ return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); - if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && checkpoints.size() >= size_needed) + if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed) { p += sizeof(uint32_t); m_blocks_hash_of_hashes.reserve(nblocks); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 9b67765b5..ab66fac8b 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -38,11 +38,9 @@ #include #include #include -#include #include #include -#include "span.h" #include "syncobj.h" #include "string_tools.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -75,15 +73,6 @@ namespace cryptonote db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O) }; - /** - * @brief Callback routine that returns checkpoints data for specific network type - * - * @param network network type - * - * @return checkpoints data, empty span if there ain't any checkpoints for specific network type - */ - typedef std::function(cryptonote::network_type network)> GetCheckpointsCallback; - /************************************************************************/ /* */ /************************************************************************/ @@ -128,11 +117,10 @@ namespace cryptonote * @param offline true if running offline, else false * @param test_options test parameters * @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled - * @param get_checkpoints if set, will be called to get checkpoints data * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0, const GetCheckpointsCallback get_checkpoints = nullptr); + bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0); /** * @brief Initialize the Blockchain state @@ -1381,10 +1369,8 @@ namespace cryptonote * A (possibly empty) set of block hashes can be compiled into the * monero daemon binary. This function loads those hashes into * a useful state. - * - * @param get_checkpoints if set, will be called to get checkpoints data */ - void load_compiled_in_block_hashes(const GetCheckpointsCallback get_checkpoints); + void load_compiled_in_block_hashes(); /** * @brief expands v2 transaction data from blockchain diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 3882a14ae..69e3c708b 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -389,7 +389,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback get_checkpoints/* = nullptr */) + bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options) { start_time = std::time(nullptr); @@ -567,7 +567,7 @@ namespace cryptonote regtest_hard_forks }; const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty); - r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty, get_checkpoints); + r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty); r = m_mempool.init(max_txpool_weight); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 882568330..58fe5b7b5 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -244,11 +244,10 @@ namespace cryptonote * @param vm command line parameters * @param config_subdir subdirectory for config storage * @param test_options configuration options for testing - * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback get_checkpoints = nullptr); + bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index 117790455..f645836a4 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -26,6 +26,20 @@ # 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. +set(blocksdat "") +if(PER_BLOCK_CHECKPOINT) + if(APPLE AND DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(APPLE AND NOT DEPENDS) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) + elseif(LINUX_32) + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + else() + add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) + endif() + set(blocksdat "blocksdat.o") +endif() + set(daemon_sources command_parser_executor.cpp command_server.cpp @@ -67,7 +81,9 @@ monero_private_headers(daemon monero_add_executable(daemon ${daemon_sources} ${daemon_headers} - ${daemon_private_headers}) + ${daemon_private_headers} + ${blocksdat} +) target_link_libraries(daemon PRIVATE rpc @@ -90,8 +106,7 @@ target_link_libraries(daemon ${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES} - ${Blocks}) + ${EXTRA_LIBRARIES}) set_property(TARGET daemon PROPERTY OUTPUT_NAME "monerod") diff --git a/src/daemon/core.h b/src/daemon/core.h index eda8894a6..475f418d6 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -28,7 +28,6 @@ #pragma once -#include "blocks/blocks.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" @@ -86,12 +85,7 @@ class t_core final //initialize core here MGINFO("Initializing core..."); std::string config_subdir = get_config_subdir(); -#if defined(PER_BLOCK_CHECKPOINT) - cryptonote::GetCheckpointsCallback get_checkpoints = blocks::GetCheckpointsData; -#else - cryptonote::GetCheckpointsCallback get_checkpoints = nullptr; -#endif - if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints)) + if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str())) { return false; } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 727134f75..8f446f42a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -58,6 +58,12 @@ endif() set(device_private_headers) +if(PER_BLOCK_CHECKPOINT) + set(Blocks "blocks") +else() + set(Blocks "") +endif() + monero_private_headers(device ${device_private_headers}) @@ -73,4 +79,5 @@ target_link_libraries(device ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} PRIVATE + ${Blocks} ${EXTRA_LIBRARIES}) From f2127f9dca29c8b1e0a51bebeee5e8e49e6f4876 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Mon, 8 Oct 2018 23:14:46 +0200 Subject: [PATCH 0078/1007] Add checksums for download tools The signature prepare tool and the gitian-builder git repo should be checked for their content. For this purpose, checkout the gitian-builder repo at a specific commit and take the sha256sum of the osslsigncode tool. --- contrib/gitian/gitian-build.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index bd7e70a71..2f4c93625 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -24,13 +24,12 @@ def setup(): subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs) if not os.path.isdir('gitian.sigs'): subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/gitian.sigs.git']) - if not os.path.isdir('monero-detached-sigs'): - subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/bitcoin-detached-sigs.git']) if not os.path.isdir('gitian-builder'): subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git']) if not os.path.isdir('monero'): - subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/monero.git']) + subprocess.check_call(['git', 'clone', 'https://github.com/monero-project/monero.git']) os.chdir('gitian-builder') + subprocess.check_call(['git', 'checkout', '963322de8420c50502c4cc33d4d7c0d84437b576']) make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64'] if args.docker: make_image_prog += ['--docker'] @@ -51,8 +50,10 @@ def build(): os.chdir('gitian-builder') os.makedirs('inputs', exist_ok=True) - subprocess.check_call(['wget', '-N', '-P', 'inputs', 'http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz']) + subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz']) subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch']) + subprocess.check_output(["echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c"], shell=True) + subprocess.check_output(["echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c"], shell=True) subprocess.check_call(['make', '-C', '../monero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) if args.linux: From c716a331f34da4ce501674b33bdc0995cd599122 Mon Sep 17 00:00:00 2001 From: selsta Date: Tue, 9 Oct 2018 02:17:40 +0200 Subject: [PATCH 0079/1007] device: increase ledger timeout to 2 minutes --- src/device/device_ledger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 464cb0d90..a17784960 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -176,7 +176,7 @@ namespace hw { #define INS_GET_RESPONSE 0xc0 - device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 10000) { + device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 120000) { this->id = device_id++; this->reset_buffer(); this->mode = NONE; From bd7b800f0a0851220e033ba5b0c4b8608bfff3e7 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 9 Oct 2018 08:13:58 +0000 Subject: [PATCH 0080/1007] device_io_hid: fix DEFAULT_* type (too short) and init time --- src/device/device_io_hid.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index 560208c77..6fd15a1d1 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -86,13 +86,13 @@ namespace hw { public: bool hid_verbose = false; - const unsigned int OR_SELECT = 1; - const unsigned int AND_SELECT = 2; + static const unsigned int OR_SELECT = 1; + static const unsigned int AND_SELECT = 2; - const unsigned char DEFAULT_CHANNEL = 0x0001; - const unsigned char DEFAULT_TAG = 0x01; - const unsigned int DEFAULT_PACKET_SIZE = 64; - const unsigned int DEFAULT_TIMEOUT = 120000; + static const unsigned short DEFAULT_CHANNEL = 0x0001; + static const unsigned char DEFAULT_TAG = 0x01; + static const unsigned int DEFAULT_PACKET_SIZE = 64; + static const unsigned int DEFAULT_TIMEOUT = 120000; device_io_hid(unsigned short channel, unsigned char tag, unsigned int packet_zize, unsigned int timeout); device_io_hid(); From fed4e59886c3410429f9625caff0298ac7523bcb Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Tue, 9 Oct 2018 11:12:32 +0200 Subject: [PATCH 0081/1007] Change gitian.sigs repo from bitcoin-core to monero-project remote host --- contrib/gitian/gitian-build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index 2f4c93625..0a93dbf5b 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -23,7 +23,7 @@ def setup(): programs += ['lxc', 'debootstrap'] subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs) if not os.path.isdir('gitian.sigs'): - subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/gitian.sigs.git']) + subprocess.check_call(['git', 'clone', 'https://github.com/monero-project/gitian.sigs.git']) if not os.path.isdir('gitian-builder'): subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git']) if not os.path.isdir('monero'): From 977fc1bceb3eae6cdc1226313fc8e447b18fd764 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 9 Oct 2018 08:36:06 +0000 Subject: [PATCH 0082/1007] wallet_rpc_server: add describe_transfer RPC for unsigned tx sets using a view only wallet --- src/wallet/wallet_rpc_server.cpp | 165 +++++++++++++++++++ src/wallet/wallet_rpc_server.h | 2 + src/wallet/wallet_rpc_server_commands_defs.h | 63 ++++++- 3 files changed, 229 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e0b631aaf..aa00157b0 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -994,6 +994,171 @@ namespace tools return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_describe_transfer(const wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::response& res, epee::json_rpc::error& er) + { + if (!m_wallet) return not_open(er); + if (m_restricted) + { + er.code = WALLET_RPC_ERROR_CODE_DENIED; + er.message = "Command unavailable in restricted mode."; + return false; + } + if (m_wallet->key_on_device()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "command not supported by HW wallet"; + return false; + } + if(m_wallet->watch_only()) + { + er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY; + er.message = "command not supported by watch-only wallet"; + return false; + } + + tools::wallet2::unsigned_tx_set exported_txs; + try + { + cryptonote::blobdata blob; + if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob)) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_HEX; + er.message = "Failed to parse hex."; + return false; + } + if(!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs)) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "cannot load unsigned_txset"; + return false; + } + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "failed to parse unsigned transfers: " + std::string(e.what()); + return false; + } + + std::vector ptx; + try + { + // gather info to ask the user + std::unordered_map> dests; + int first_known_non_zero_change_index = -1; + for (size_t n = 0; n < exported_txs.txes.size(); ++n) + { + const tools::wallet2::tx_construction_data &cd = exported_txs.txes[n]; + res.desc.push_back({0, 0, std::numeric_limits::max(), 0, {}, "", 0, "", 0, 0, ""}); + wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back(); + + std::vector tx_extra_fields; + bool has_encrypted_payment_id = false; + crypto::hash8 payment_id8 = crypto::null_hash8; + if (cryptonote::parse_tx_extra(cd.extra, tx_extra_fields)) + { + cryptonote::tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + { + crypto::hash payment_id; + if(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) + { + desc.payment_id = epee::string_tools::pod_to_hex(payment_id8); + has_encrypted_payment_id = true; + } + else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + { + desc.payment_id = epee::string_tools::pod_to_hex(payment_id); + } + } + } + + for (size_t s = 0; s < cd.sources.size(); ++s) + { + desc.amount_in += cd.sources[s].amount; + size_t ring_size = cd.sources[s].outputs.size(); + if (ring_size < desc.ring_size) + desc.ring_size = ring_size; + } + for (size_t d = 0; d < cd.splitted_dsts.size(); ++d) + { + const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d]; + std::string address = cryptonote::get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr); + if (has_encrypted_payment_id && !entry.is_subaddress) + address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8); + auto i = dests.find(entry.addr); + if (i == dests.end()) + dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount))); + else + i->second.second += entry.amount; + desc.amount_out += entry.amount; + } + if (cd.change_dts.amount > 0) + { + auto it = dests.find(cd.change_dts.addr); + if (it == dests.end()) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "Claimed change does not go to a paid address"; + return false; + } + if (it->second.second < cd.change_dts.amount) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "Claimed change is larger than payment to the change address"; + return false; + } + if (cd.change_dts.amount > 0) + { + if (first_known_non_zero_change_index == -1) + first_known_non_zero_change_index = n; + const tools::wallet2::tx_construction_data &cdn = exported_txs.txes[first_known_non_zero_change_index]; + if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr))) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "Change goes to more than one address"; + return false; + } + } + desc.change_amount += cd.change_dts.amount; + it->second.second -= cd.change_dts.amount; + if (it->second.second == 0) + dests.erase(cd.change_dts.addr); + } + + size_t n_dummy_outputs = 0; + for (auto i = dests.begin(); i != dests.end(); ) + { + if (i->second.second > 0) + { + desc.recipients.push_back({i->second.first, i->second.second}); + } + else + ++desc.dummy_outputs; + ++i; + } + + if (desc.change_amount > 0) + { + const tools::wallet2::tx_construction_data &cd0 = exported_txs.txes[0]; + desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr); + } + + desc.fee = desc.amount_in - desc.amount_out; + desc.unlock_time = cd.unlock_time; + desc.extra = epee::to_hex::string({cd.extra.data(), cd.extra.size()}); + } + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; + er.message = "failed to parse unsigned transfers"; + return false; + } + + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_submit_transfer(const wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er) { if (!m_wallet) return not_open(er); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index ab896aa3b..69066cfd9 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -86,6 +86,7 @@ namespace tools MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER) MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT) MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER) + MAP_JON_RPC_WE("describe_transfer", on_describe_transfer, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER) MAP_JON_RPC_WE("submit_transfer", on_submit_transfer, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER) MAP_JON_RPC_WE("sweep_dust", on_sweep_dust, wallet_rpc::COMMAND_RPC_SWEEP_DUST) MAP_JON_RPC_WE("sweep_unmixable", on_sweep_dust, wallet_rpc::COMMAND_RPC_SWEEP_DUST) @@ -166,6 +167,7 @@ namespace tools bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er); bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er); bool on_sign_transfer(const wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::response& res, epee::json_rpc::error& er); + bool on_describe_transfer(const wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::response& res, epee::json_rpc::error& er); bool on_submit_transfer(const wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SUBMIT_TRANSFER::response& res, epee::json_rpc::error& er); bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er); bool on_sweep_all(const wallet_rpc::COMMAND_RPC_SWEEP_ALL::request& req, wallet_rpc::COMMAND_RPC_SWEEP_ALL::response& res, epee::json_rpc::error& er); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 2377b69e3..c65c7e9b5 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 4 +#define WALLET_RPC_VERSION_MINOR 5 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -531,6 +531,67 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_DESCRIBE_TRANSFER + { + struct recipient + { + std::string address; + uint64_t amount; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(amount) + END_KV_SERIALIZE_MAP() + }; + + struct transfer_description + { + uint64_t amount_in; + uint64_t amount_out; + uint32_t ring_size; + uint64_t unlock_time; + std::list recipients; + std::string payment_id; + uint64_t change_amount; + std::string change_address; + uint64_t fee; + uint32_t dummy_outputs; + std::string extra; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount_in) + KV_SERIALIZE(amount_out) + KV_SERIALIZE(ring_size) + KV_SERIALIZE(unlock_time) + KV_SERIALIZE(recipients) + KV_SERIALIZE(payment_id) + KV_SERIALIZE(change_amount) + KV_SERIALIZE(change_address) + KV_SERIALIZE(fee) + KV_SERIALIZE(dummy_outputs) + KV_SERIALIZE(extra) + END_KV_SERIALIZE_MAP() + }; + + struct request + { + std::string unsigned_txset; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(unsigned_txset) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::list desc; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(desc) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_SIGN_TRANSFER { struct request From 02c2b43a72c941c7eac7d8f8a9ed4b61597a3fdf Mon Sep 17 00:00:00 2001 From: Gregory Lemercier Date: Sun, 7 Oct 2018 19:05:13 +0200 Subject: [PATCH 0083/1007] Utils: Add Dockerfile for android 64-bit build --- Makefile | 9 +- README.md | 6 +- utils/build_scripts/android32.Dockerfile | 2 +- utils/build_scripts/android64.Dockerfile | 142 +++++++++++++++++++++++ 4 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 utils/build_scripts/android64.Dockerfile diff --git a/Makefile b/Makefile index a0bf86c0e..40b8839cc 100644 --- a/Makefile +++ b/Makefile @@ -103,10 +103,15 @@ release-static-linux-armv7: mkdir -p $(builddir)/release cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-armv7" $(topdir) && $(MAKE) -release-static-android: +release-static-android-armv7: mkdir -p $(builddir)/release/translations cd $(builddir)/release/translations && cmake ../../../translations && $(MAKE) - cd $(builddir)/release && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG="android" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARM_MODE=ON -D CMAKE_ANDROID_ARCH_ABI="armeabi-v7a" ../.. && $(MAKE) + cd $(builddir)/release && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG="android-armv7" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARM_MODE=ON -D CMAKE_ANDROID_ARCH_ABI="armeabi-v7a" ../.. && $(MAKE) + +release-static-android-armv8: + mkdir -p $(builddir)/release/translations + cd $(builddir)/release/translations && cmake ../../../translations && $(MAKE) + cd $(builddir)/release && CC=aarch64-linux-android-clang CXX=aarch64-linux-android-clang++ cmake -D BUILD_TESTS=OFF -D ARCH="armv8-a" -D STATIC=ON -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG="android-armv8" -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI="arm64-v8a" ../.. && $(MAKE) release-static-linux-armv8: mkdir -p $(builddir)/release diff --git a/README.md b/README.md index bce41f5cf..ab33b10dd 100644 --- a/README.md +++ b/README.md @@ -472,12 +472,14 @@ Then you can run make as usual. ### On Linux for Android (using docker): - # Build image + # Build image (for ARM 32-bit) docker build -f utils/build_scripts/android32.Dockerfile -t monero-android . + # Build image (for ARM 64-bit) + docker build -f utils/build_scripts/android64.Dockerfile -t monero-android . # Create container docker create -it --name monero-android monero-android bash # Get binaries - docker cp monero-android:/opt/android/monero/build/release/bin . + docker cp monero-android:/src/build/release/bin . ### Building portable statically linked binaries (Cross Compiling) diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile index 8647341cb..e49bdc652 100644 --- a/utils/build_scripts/android32.Dockerfile +++ b/utils/build_scripts/android32.Dockerfile @@ -139,4 +139,4 @@ RUN cd /src \ CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ USE_SINGLE_BUILDDIR=1 \ - PATH=${HOST_PATH} make release-static-android -j${NPROC} + PATH=${HOST_PATH} make release-static-android-armv7 -j${NPROC} diff --git a/utils/build_scripts/android64.Dockerfile b/utils/build_scripts/android64.Dockerfile new file mode 100644 index 000000000..c4464fa84 --- /dev/null +++ b/utils/build_scripts/android64.Dockerfile @@ -0,0 +1,142 @@ +FROM debian:stable + +RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool + +WORKDIR /opt/android +## INSTALL ANDROID SDK +ENV ANDROID_SDK_REVISION 4333796 +ENV ANDROID_SDK_HASH 92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9 +RUN curl -s -O https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && echo "${ANDROID_SDK_HASH} sdk-tools-linux-${ANDROID_SDK_REVISION}.zip" | sha256sum -c \ + && unzip sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ + && rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip + +## INSTALL ANDROID NDK +ENV ANDROID_NDK_REVISION 17b +ENV ANDROID_NDK_HASH 5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d48ccecd +RUN curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && echo "${ANDROID_NDK_HASH} android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip" | sha256sum -c \ + && unzip android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ + && rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip + +ENV WORKDIR /opt/android +ENV ANDROID_SDK_ROOT ${WORKDIR}/tools +ENV ANDROID_NDK_ROOT ${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION} +ENV PREFIX /opt/android/prefix + +ENV TOOLCHAIN_DIR ${WORKDIR}/toolchain-arm +RUN ${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py \ + --arch arm64 \ + --api 21 \ + --install-dir ${TOOLCHAIN_DIR} \ + --stl=libc++ + +#INSTALL cmake +ENV CMAKE_VERSION 3.12.1 +RUN cd /usr \ + && curl -s -O https://cmake.org/files/v3.12/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && tar -xzf /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ + && rm -f /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz +ENV PATH /usr/cmake-${CMAKE_VERSION}-Linux-x86_64/bin:$PATH + +## Boost +ARG BOOST_VERSION=1_68_0 +ARG BOOST_VERSION_DOT=1.68.0 +ARG BOOST_HASH=7f6130bc3cf65f56a618888ce9d5ea704fa10b462be126ad053e80e553d6d8b7 +RUN set -ex \ + && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \ + && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ + && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ + && rm -f boost_${BOOST_VERSION}.tar.bz2 \ + && cd boost_${BOOST_VERSION} \ + && ./bootstrap.sh --prefix=${PREFIX} + +ENV HOST_PATH $PATH +ENV PATH $TOOLCHAIN_DIR/aarch64-linux-android/bin:$TOOLCHAIN_DIR/bin:$PATH + +ARG NPROC=1 + +# Build iconv for lib boost locale +ENV ICONV_VERSION 1.15 +ENV ICONV_HASH ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 +RUN curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \ + && echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf libiconv-${ICONV_VERSION}.tar.gz \ + && rm -f libiconv-${ICONV_VERSION}.tar.gz \ + && cd libiconv-${ICONV_VERSION} \ + && CC=aarch64-linux-android-clang CXX=aarch64-linux-android-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${PREFIX} --disable-rpath \ + && make -j${NPROC} && make install + +## Build BOOST +RUN cd boost_${BOOST_VERSION} \ + && ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} install -j${NPROC} + +#Note : we build openssl because the default lacks DSA1 + +# download, configure and make Zlib +ENV ZLIB_VERSION 1.2.11 +ENV ZLIB_HASH c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 +RUN curl -s -O https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ + && echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ + && rm zlib-${ZLIB_VERSION}.tar.gz \ + && mv zlib-${ZLIB_VERSION} zlib \ + && cd zlib && CC=clang CXX=clang++ ./configure --static \ + && make -j${NPROC} + +# open ssl +ARG OPENSSL_VERSION=1.0.2p +ARG OPENSSL_HASH=50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00 +RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ + && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ + && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ + && rm openssl-${OPENSSL_VERSION}.tar.gz \ + && cd openssl-${OPENSSL_VERSION} \ + && sed -i -e "s/mandroid/target\ aarch64\-linux\-android/" Configure \ + && CC=clang CXX=clang++ \ + ./Configure android \ + no-asm \ + no-shared --static \ + --with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \ + --prefix=${PREFIX} --openssldir=${PREFIX} \ + && make -j${NPROC} \ + && make install + +# ZMQ +ARG ZMQ_VERSION=master +ARG ZMQ_HASH=501d0815bf2b0abb93be8214fc66519918ef6c40 +RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ + && cd libzmq \ + && git checkout ${ZMQ_HASH} \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +# zmq.hpp +ARG CPPZMQ_VERSION=v4.2.3 +ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6 +RUN git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \ + && cd cppzmq \ + && test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1 \ + && cp *.hpp ${PREFIX}/include + +# Sodium +ARG SODIUM_VERSION=1.0.16 +ARG SODIUM_HASH=675149b9b8b66ff44152553fb3ebf9858128363d +RUN set -ex \ + && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ + && cd libsodium \ + && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ + && ./autogen.sh \ + && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \ + && make -j${NPROC} \ + && make install + +ADD . /src +RUN cd /src \ + && CMAKE_INCLUDE_PATH="${PREFIX}/include" \ + CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ + ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ + USE_SINGLE_BUILDDIR=1 \ + PATH=${HOST_PATH} make release-static-android-armv8 -j${NPROC} From 8833aec08331131c2eb69a1ac3709837f63a14d8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 9 Oct 2018 14:31:21 +0000 Subject: [PATCH 0084/1007] wallet2: fix cold signing using non padded bulletproofs This code was deciding which bulletproof configuration to use based on ptx which weren't created yet. --- src/wallet/wallet2.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7871fe99c..f87edf506 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5563,10 +5563,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector 1) - range_proof_type = rct::RangeProofPaddedBulletproof; + range_proof_type = rct::RangeProofPaddedBulletproof; } crypto::secret_key tx_key; std::vector additional_tx_keys; From 93a88d7323ed72dfc08e45b15f996d94d96bb106 Mon Sep 17 00:00:00 2001 From: Gregory Lemercier Date: Tue, 9 Oct 2018 19:17:56 +0200 Subject: [PATCH 0085/1007] Utils: add support for newer Windows versions detection --- src/common/util.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a1d49af0..35e885fa3 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -307,10 +307,19 @@ namespace tools StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft ")); // Test for the specific product. + if ( osvi.dwMajorVersion == 10 ) + { + if ( osvi.dwMinorVersion == 0 ) + { + if( osvi.wProductType == VER_NT_WORKSTATION ) + StringCchCat(pszOS, BUFSIZE, TEXT("Windows 10 ")); + else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2016 " )); + } + } if ( osvi.dwMajorVersion == 6 ) { - if( osvi.dwMinorVersion == 0 ) + if ( osvi.dwMinorVersion == 0 ) { if( osvi.wProductType == VER_NT_WORKSTATION ) StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista ")); @@ -324,6 +333,20 @@ namespace tools else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " )); } + if ( osvi.dwMinorVersion == 2 ) + { + if( osvi.wProductType == VER_NT_WORKSTATION ) + StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8 ")); + else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2012 " )); + } + + if ( osvi.dwMinorVersion == 3 ) + { + if( osvi.wProductType == VER_NT_WORKSTATION ) + StringCchCat(pszOS, BUFSIZE, TEXT("Windows 8.1 ")); + else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2012 R2 " )); + } + pGPI = (PGPI) GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); From d147d24058ef4d4e25ff0603b6bc89f2d4095874 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Tue, 9 Oct 2018 22:24:49 +0200 Subject: [PATCH 0086/1007] Add windows descriptor to gitian descriptors Windows is built with a seperate descriptor to handle additional changes that need to be done to the end binary. Consolidate the gitian-build script for this change. --- contrib/gitian/gitian-build.py | 8 +- contrib/gitian/gitian-linux.yml | 6 +- contrib/gitian/gitian-win.yml | 135 ++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 contrib/gitian/gitian-win.yml diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index 0a93dbf5b..feb193a32 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -60,20 +60,20 @@ def build(): print('\nCompiling ' + args.version + ' Linux') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-linux.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-linux', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-linux.yml']) - subprocess.check_call('mv build/out/monero-*.tar.gz build/out/monero-*.tar.gz ../monero-binaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/monero-*.tar.gz ../monero-binaries/'+args.version, shell=True) if args.windows: print('\nCompiling ' + args.version + ' Windows') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-win.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win.yml']) - subprocess.check_call('mv build/out/monero*-win-unsigned.tar.gz inputs/monerowin-unsigned.tar.gz', shell=True) - subprocess.check_call('mv build/out/monero*.zip build/out/monero*.exe ../monerobinaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/monero*-unsigned.tar.gz inputs/', shell=True) + subprocess.check_call('mv build/out/monero*.zip ../monerobinaries/'+args.version, shell=True) if args.macos: print('\nCompiling ' + args.version + ' MacOS') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero'+args.commit, '--url', 'monero'+args.url, '../monero/contrib/gitian/gitian-osx.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx.yml']) - subprocess.check_call('mv build/out/monero*-osx-unsigned.tar.gz inputs/moneroosx-unsigned.tar.gz', shell=True) + subprocess.check_call('mv build/out/monero*-osx-unsigned.tar.gz inputs/', shell=True) subprocess.check_call('mv build/out/monero*.tar.gz build/out/monero*.dmg ../monerobinaries/'+args.version, shell=True) os.chdir(workdir) diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index 751fbadd3..e64e28bbc 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -154,9 +154,9 @@ script: | mkdir build && cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake make - DISTNAME=monero-${i}.tar.gz - tar -cvzf $DISTNAME bin/* - cp $DISTNAME $OUTDIR/ + DISTNAME=monero-${i} + mv bin ${DISTNAME} + find ${DISTNAME}/ | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}.tar.gz cd .. rm -rf build done diff --git a/contrib/gitian/gitian-win.yml b/contrib/gitian/gitian-win.yml new file mode 100644 index 000000000..7ae8c58f4 --- /dev/null +++ b/contrib/gitian/gitian-win.yml @@ -0,0 +1,135 @@ +--- +name: "bitcoin-win-0.18" +enable_cache: true +suites: +- "bionic" +architectures: +- "amd64" +packages: +- "curl" +- "g++" +- "git" +- "pkg-config" +- "autoconf" +- "libtool" +- "automake" +- "faketime" +- "bsdmainutils" +- "mingw-w64" +- "g++-mingw-w64" +- "zip" +- "ca-certificates" +- "python" +- "rename" +- "cmake" +remotes: +- "url": "https://github.com/monero-project/monero.git" + "dir": "monero" +files: [] +script: | + WRAP_DIR=$HOME/wrapped + HOSTS="i686-w64-mingw32 x86_64-w64-mingw32" + FAKETIME_HOST_PROGS="ar ranlib nm windres strip objcopy" + FAKETIME_PROGS="date zip" + HOST_CFLAGS="-O2 -g" + HOST_CXXFLAGS="-O2 -g" + + export GZIP="-9n" + export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export TZ="UTC" + export BUILD_DIR=`pwd` + mkdir -p ${WRAP_DIR} + if test -n "$GBUILD_CACHE_ENABLED"; then + export SOURCES_PATH=${GBUILD_COMMON_CACHE} + export BASE_CACHE=${GBUILD_PACKAGE_CACHE} + mkdir -p ${BASE_CACHE} ${SOURCES_PATH} + fi + + function create_global_faketime_wrappers { + for prog in ${FAKETIME_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} + echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${prog} + chmod +x ${WRAP_DIR}/${prog} + done + } + + function create_per-host_faketime_wrappers { + for i in $HOSTS; do + for prog in ${FAKETIME_HOST_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} + echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} + chmod +x ${WRAP_DIR}/${i}-${prog} + done + done + } + + function create_per-host_linker_wrapper { + # This is only needed for trusty, as the mingw linker leaks a few bytes of + # heap, causing non-determinism. See discussion in https://github.com/bitcoin/bitcoin/pull/6900 + for i in $HOSTS; do + mkdir -p ${WRAP_DIR}/${i} + for prog in collect2; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}/${prog} + REAL=$(${i}-gcc -print-prog-name=${prog}) + echo "export MALLOC_PERTURB_=255" >> ${WRAP_DIR}/${i}/${prog} + echo "${REAL} \$@" >> $WRAP_DIR/${i}/${prog} + chmod +x ${WRAP_DIR}/${i}/${prog} + done + for prog in gcc g++; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} + echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} + echo "export COMPILER_PATH=${WRAP_DIR}/${i}" >> ${WRAP_DIR}/${i}-${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} + chmod +x ${WRAP_DIR}/${i}-${prog} + done + done + } + + # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_linker_wrapper "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} + + cd monero + BASEPREFIX=`pwd`/contrib/depends + # Build dependencies for each host + for i in $HOSTS; do + EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$EXTRA_INCLUDES" ]; then + export HOST_ID_SALT="$EXTRA_INCLUDES" + fi + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" -j 4 V=1 + unset HOST_ID_SALT + done + + # Faketime for binaries + export PATH=${PATH_orig} + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} + + ORIGPATH="$PATH" + # Run cmake and make, for each create a new build/ directory, + # compile from there, archive, export and delete the archive again + for i in ${HOSTS}; do + export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} + mkdir build && cd build + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake + make + DISTNAME=monero-${i} + mv bin ${DISTNAME} + find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip + find ${DISTNAME}/ | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-unsigned.tar.gz + cd .. && rm -rf build + done + From bf60e98abc07dd569902279e7879b5198944f66c Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Tue, 9 Oct 2018 22:36:44 +0200 Subject: [PATCH 0087/1007] fix version changes on master --- src/version.cpp.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.cpp.in b/src/version.cpp.in index 55075a064..ff2405811 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_MONERO_VERSION_TAG "@VERSIONTAG@" -#define DEF_MONERO_VERSION "0.13.0.1-rc" +#define DEF_MONERO_VERSION "0.13.0.0-master" #define DEF_MONERO_RELEASE_NAME "Beryllium Bullet" #define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG From 92a0827eea45d06729d78fd3013c007829903f60 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 10:25:16 +0000 Subject: [PATCH 0088/1007] wallet2: make fake out selection messages less spammy --- src/wallet/wallet2.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 7871fe99c..f005d85c6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "include_base_utils.h" using namespace epee; @@ -6968,6 +6970,8 @@ void wallet2::get_outs(std::vector> LOG_PRINT_L1("Selecting real output: " << td.m_global_output_index << " for " << print_money(amount)); } + std::unordered_map> picks; + // while we still need more mixins uint64_t num_usable_outs = num_outs; bool allow_blackballed = false; @@ -7066,11 +7070,15 @@ void wallet2::get_outs(std::vector> } seen_indices.emplace(i); - LOG_PRINT_L2("picking " << i << " as " << type); + picks[type].insert(i); req.outputs.push_back({amount, i}); ++num_found; } + for (const auto &pick: picks) + MDEBUG("picking " << pick.first << " outputs: " << + boost::join(pick.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + // if we had enough unusable outputs, we might fall off here and still // have too few outputs, so we stuff with one to keep counts good, and // we'll error out later @@ -7086,8 +7094,15 @@ void wallet2::get_outs(std::vector> [](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; }); } - for (auto i: req.outputs) - LOG_PRINT_L1("asking for output " << i.index << " for " << print_money(i.amount)); + if (ELPP->vRegistry()->allowed(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY)) + { + std::map> outs; + for (const auto &i: req.outputs) + outs[i.amount].insert(i.index); + for (const auto &o: outs) + MDEBUG("asking for outputs with amount " << print_money(o.first) << ": " << + boost::join(o.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ")); + } // get the keys for those m_daemon_rpc_mutex.lock(); From dc8f6924b2c4e97f742a49942815e3b5ef50d675 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Oct 2018 08:57:41 +0000 Subject: [PATCH 0089/1007] password: fix backspace outputting ^? on linux on echoing secure input --- src/common/password.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/password.cpp b/src/common/password.cpp index a8d5141dc..e41c75088 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -158,6 +158,13 @@ namespace if (!aPass.empty()) { aPass.pop_back(); + if (!hide_input) + std::cout << "\b\b\b \b\b\b" << std::flush; + } + else + { + if (!hide_input) + std::cout << "\b\b \b\b" << std::flush; } } else From 0e33cf89d2e351b2306e66a7d23ede880208fbee Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Oct 2018 12:15:20 +0000 Subject: [PATCH 0090/1007] password: fix secure input with echo on windows Thanks to iDunk for the testing back and forth --- src/common/password.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/common/password.cpp b/src/common/password.cpp index a8d5141dc..7ba3fcb42 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -60,7 +60,7 @@ namespace DWORD mode_old; ::GetConsoleMode(h_cin, &mode_old); - DWORD mode_new = mode_old & ~((hide_input ? ENABLE_ECHO_INPUT : 0) | ENABLE_LINE_INPUT); + DWORD mode_new = mode_old & ~(hide_input ? ENABLE_ECHO_INPUT : 0); ::SetConsoleMode(h_cin, mode_new); bool r = true; @@ -78,7 +78,11 @@ namespace { break; } - else if (ucs2_ch == L'\n' || ucs2_ch == L'\r') + else if (ucs2_ch == L'\r') + { + continue; + } + else if (ucs2_ch == L'\n') { std::cout << std::endl; break; From c0822fdd301a41711dca69576449046b55cf9bca Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Oct 2018 15:03:38 +0000 Subject: [PATCH 0091/1007] simplewallet: mark default-ring-size setting as obsolete --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4ec7e3eb4..b63eb5974 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2403,7 +2403,7 @@ simple_wallet::simple_wallet() "store-tx-info <1|0>\n " " Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n " "default-ring-size \n " - " Set the default ring size (default and minimum is 5).\n " + " Set the default ring size (obsolete).\n " "auto-refresh <1|0>\n " " Whether to automatically synchronize new blocks from the daemon.\n " "refresh-type \n " From 67e76aa06c3db2a82f98fa6a74fff5feb4f4199d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Oct 2018 15:54:59 +0000 Subject: [PATCH 0092/1007] wallet_rpc_server: optionally return tx keys in sign_transfer --- src/wallet/wallet2.cpp | 4 ++++ src/wallet/wallet_rpc_server.cpp | 2 ++ src/wallet/wallet_rpc_server_commands_defs.h | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f87edf506..680f3a214 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5607,6 +5607,10 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector tx_hash_list; std::list tx_raw_list; + std::list tx_key_list; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(signed_txset) KV_SERIALIZE(tx_hash_list) KV_SERIALIZE(tx_raw_list) + KV_SERIALIZE(tx_key_list) END_KV_SERIALIZE_MAP() }; }; From d46c765dcad76ecf0a8b90bf08b1d5e103278d5c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 10 Oct 2018 16:46:10 +0000 Subject: [PATCH 0093/1007] README: mention max_usb_current setting on Raspberry Pi --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5da96371a..36fdfff8a 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,8 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch ( CONF_SWAPSIZE=1024 sudo /etc/init.d/dphys-swapfile start ``` +* If using an external hard disk without an external power supply, ensure it gets enough power to avoid hardware issues when syncing, by adding the line "max_usb_current=1" to /boot/config.txt + * Clone monero and checkout most recent release version: ``` git clone https://github.com/monero-project/monero.git From f2c2c47a4ba40a00d5c6b9d7ea3df4c6cb654c83 Mon Sep 17 00:00:00 2001 From: xiphon Date: Wed, 10 Oct 2018 19:39:51 +0000 Subject: [PATCH 0094/1007] simplewallet: fixed deadlock if a user hits CTRL+C twice Co-authored-by: moneromooo-monero --- src/simplewallet/simplewallet.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4ec7e3eb4..625ab52bc 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -7050,12 +7050,6 @@ bool simple_wallet::run() void simple_wallet::stop() { m_cmd_binder.stop_handling(); - - m_idle_run.store(false, std::memory_order_relaxed); - m_wallet->stop(); - // make the background refresh thread quit - boost::unique_lock lock(m_idle_mutex); - m_idle_cond.notify_one(); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::account(const std::vector &args/* = std::vector()*/) From 68e9744d4465cf809b1b68234876ade8705de9e3 Mon Sep 17 00:00:00 2001 From: xiphon Date: Wed, 10 Oct 2018 20:01:04 +0000 Subject: [PATCH 0095/1007] simplewallet: perform trivial error checks before password prompt --- src/simplewallet/simplewallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4ec7e3eb4..8d24bb9fb 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4715,8 +4715,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector local_args = args_; std::set subaddr_indices; @@ -4936,6 +4934,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector Date: Wed, 10 Oct 2018 00:16:55 +0200 Subject: [PATCH 0096/1007] Add OSX gitian descriptor --- contrib/gitian/gitian-build.py | 24 ++----- contrib/gitian/gitian-linux.yml | 4 +- contrib/gitian/gitian-osx.yml | 114 ++++++++++++++++++++++++++++++++ contrib/gitian/gitian-win.yml | 1 - 4 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 contrib/gitian/gitian-osx.yml diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index feb193a32..eb138e41a 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -66,15 +66,13 @@ def build(): print('\nCompiling ' + args.version + ' Windows') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-win.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win.yml']) - subprocess.check_call('mv build/out/monero*-unsigned.tar.gz inputs/', shell=True) - subprocess.check_call('mv build/out/monero*.zip ../monerobinaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/monero*.zip ../monero-binaries/'+args.version, shell=True) if args.macos: print('\nCompiling ' + args.version + ' MacOS') - subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero'+args.commit, '--url', 'monero'+args.url, '../monero/contrib/gitian/gitian-osx.yml']) + subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero'+args.url, '../monero/contrib/gitian/gitian-osx.yml']) subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx.yml']) - subprocess.check_call('mv build/out/monero*-osx-unsigned.tar.gz inputs/', shell=True) - subprocess.check_call('mv build/out/monero*.tar.gz build/out/monero*.dmg ../monerobinaries/'+args.version, shell=True) + subprocess.check_call('mv build/out/monero*.tar.gz ../monero-binaries/'+args.version, shell=True) os.chdir(workdir) @@ -90,20 +88,6 @@ def build(): def sign(): global args, workdir os.chdir('gitian-builder') - - if args.windows: - print('\nSigning ' + args.version + ' Windows') - subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../monero/contrib/gitian/gitian-win-signer.yml']) - subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win-signer.yml']) - subprocess.check_call('mv build/out/monero*win64-setup.exe ../monerobinaries/'+args.version, shell=True) - subprocess.check_call('mv build/out/monero*win32-setup.exe ../monerobinaries/'+args.version, shell=True) - - if args.macos: - print('\nSigning ' + args.version + ' MacOS') - subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../monero/contrib/gitian/gitian-osx-signer.yml']) - subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx-signer.yml']) - subprocess.check_call('mv build/out/moneroosx-signed.dmg ../monerobinaries/'+args.version+'/monero'+args.version+'-osx.dmg', shell=True) - os.chdir(workdir) if args.commit_files: @@ -137,7 +121,7 @@ def main(): parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version') parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch') parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request') - parser.add_argument('-u', '--url', dest='url', default='https://github.com/TheCharlatan/monero', help='Specify the URL of the repository. Default is %(default)s') + parser.add_argument('-u', '--url', dest='url', default='https://github.com/monero-project/monero', help='Specify the URL of the repository. Default is %(default)s') parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS') diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index e64e28bbc..6c338f1da 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -43,7 +43,7 @@ packages: - "libprotobuf-dev" - "python3-zmq" remotes: -- "url": "https://github.com/TheCharlatan/monero.git" +- "url": "https://github.com/monero-project/monero.git" "dir": "monero" files: [] script: | @@ -148,7 +148,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} ORIGPATH="$PATH" - # Extract the release tarball into a dir for each host and build + # Build in a new dir for each host for i in ${HOSTS}; do export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir build && cd build diff --git a/contrib/gitian/gitian-osx.yml b/contrib/gitian/gitian-osx.yml new file mode 100644 index 000000000..d9ebf95d3 --- /dev/null +++ b/contrib/gitian/gitian-osx.yml @@ -0,0 +1,114 @@ +--- +name: "bitcoin-osx-0.18" +enable_cache: true +suites: +- "bionic" +architectures: +- "amd64" +packages: +- "ca-certificates" +- "curl" +- "g++" +- "git" +- "pkg-config" +- "autoconf" +- "librsvg2-bin" +- "libtiff-tools" +- "libtool" +- "automake" +- "faketime" +- "bsdmainutils" +- "cmake" +- "imagemagick" +- "libcap-dev" +- "libz-dev" +- "libbz2-dev" +- "python" +- "python-dev" +- "python-setuptools" +- "fonts-tuffy" +remotes: +- "url": "https://github.com/monero-project/monero.git" + "dir": "monero" +files: +- "MacOSX10.11.sdk.tar.gz" +script: | + WRAP_DIR=$HOME/wrapped + HOSTS="x86_64-apple-darwin11" + FAKETIME_HOST_PROGS="" + FAKETIME_PROGS="ar ranlib date dmg genisoimage" + + export GZIP="-9n" + export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" + export TZ="UTC" + export BUILD_DIR=`pwd` + mkdir -p ${WRAP_DIR} + if test -n "$GBUILD_CACHE_ENABLED"; then + export SOURCES_PATH=${GBUILD_COMMON_CACHE} + export BASE_CACHE=${GBUILD_PACKAGE_CACHE} + mkdir -p ${BASE_CACHE} ${SOURCES_PATH} + fi + + export ZERO_AR_DATE=1 + + function create_global_faketime_wrappers { + for prog in ${FAKETIME_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} + echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${prog} + chmod +x ${WRAP_DIR}/${prog} + done + } + + function create_per-host_faketime_wrappers { + for i in $HOSTS; do + for prog in ${FAKETIME_HOST_PROGS}; do + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} + echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} + echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} + echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} + echo "\$REAL \$@" >> $WRAP_DIR/${i}-${prog} + chmod +x ${WRAP_DIR}/${i}-${prog} + done + done + } + + # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} + create_global_faketime_wrappers "2000-01-01 12:00:00" + create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} + + cd monero + BASEPREFIX=`pwd`/contrib/depends + + mkdir -p ${BASEPREFIX}/SDKs + tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.11.sdk.tar.gz + + # Build dependencies for each host + for i in $HOSTS; do + make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" + done + + # Faketime for binaries + export PATH=${PATH_orig} + create_global_faketime_wrappers "${REFERENCE_DATETIME}" + create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} + + ORIGPATH="$PATH" + # Build in a new dir for each host + for i in ${HOSTS}; do + export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} + mkdir build && cd build + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake + make + DISTNAME=monero-${i} + mv bin ${DISTNAME} + find ${DISTNAME}/ | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}.tar.gz + cd .. + rm -rf build + done + diff --git a/contrib/gitian/gitian-win.yml b/contrib/gitian/gitian-win.yml index 7ae8c58f4..74c757c11 100644 --- a/contrib/gitian/gitian-win.yml +++ b/contrib/gitian/gitian-win.yml @@ -129,7 +129,6 @@ script: | DISTNAME=monero-${i} mv bin ${DISTNAME} find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip - find ${DISTNAME}/ | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-unsigned.tar.gz cd .. && rm -rf build done From 04ddf02e3a6fb5ee4f4777e14625bd2d701add5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sa=C5=82aban?= Date: Thu, 11 Oct 2018 18:12:17 +0200 Subject: [PATCH 0097/1007] Return appropriate RPC error code when key image signature check fails --- src/wallet/wallet2.cpp | 2 +- src/wallet/wallet_errors.h | 9 +++++++++ src/wallet/wallet_rpc_server.cpp | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f87edf506..b505c13ee 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -10542,7 +10542,7 @@ uint64_t wallet2::import_key_images(const std::vector(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)); THROW_WALLET_EXCEPTION_IF(!crypto::check_ring_signature((const crypto::hash&)key_image, key_image, pkeys, &signature), - error::wallet_internal_error, "Signature check failed: input " + boost::lexical_cast(n) + "/" + error::signature_check_failed, boost::lexical_cast(n) + "/" + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image) + ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0])); diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index bc518d04a..b3141985d 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -72,6 +72,7 @@ namespace tools // tx_parse_error // get_tx_pool_error // out_of_hashchain_bounds_error + // signature_check_failed // transfer_error * // get_outs_general_error // not_enough_unlocked_money @@ -418,6 +419,14 @@ namespace tools std::string to_string() const { return refresh_error::to_string(); } }; //---------------------------------------------------------------------------------------------------- + struct signature_check_failed : public wallet_logic_error + { + explicit signature_check_failed(std::string&& loc, const std::string& message) + : wallet_logic_error(std::move(loc), "Signature check failed " + message) + { + } + }; + //---------------------------------------------------------------------------------------------------- struct transfer_error : public wallet_logic_error { protected: diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e0b631aaf..87ee20902 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2906,6 +2906,11 @@ namespace tools er.code = WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUT_OF_BOUNDS; er.message = e.what(); } + catch (const error::signature_check_failed& e) + { + er.code = WALLET_RPC_ERROR_CODE_WRONG_SIGNATURE; + er.message = e.what(); + } catch (const std::exception& e) { er.code = default_error_code; From f5f7c2ac245523b5a78a9aff57f05077ff352c1f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 14:03:08 +0000 Subject: [PATCH 0098/1007] rpc: blanket initialize 0MQ request and response structures --- src/rpc/daemon_messages.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index 8fff369df..be3138e3b 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -67,7 +67,7 @@ class classname \ // NOTE: when using a type with multiple template parameters, // replace any comma in the template specifier with the macro // above, or the preprocessor will eat the comma in a bad way. -#define RPC_MESSAGE_MEMBER(type, name) type name; +#define RPC_MESSAGE_MEMBER(type, name) type name = type{} namespace cryptonote From 14ed029b241d00f6a711b9362de4ab094ec30ea2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 12 Oct 2018 12:54:17 +0000 Subject: [PATCH 0099/1007] simplewallet: fix view key parsing in --generate-from-view-key --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4ec7e3eb4..e1a98135c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3032,7 +3032,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } crypto::secret_key viewkey; - if (viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) { fail_msg_writer() << tr("failed to parse view key secret key"); return false; From e736964a0cd37d887d4da2ef362e760d1cb7474f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 12 Oct 2018 15:20:42 +0000 Subject: [PATCH 0100/1007] Remove epee header dependency on cryptonote_core --- contrib/epee/include/net/abstract_tcp_server2.inl | 10 ++++------ contrib/epee/include/net/http_protocol_handler.inl | 1 + src/debug_utilities/object_sizes.cpp | 1 + src/p2p/net_node.cpp | 1 + src/wallet/wallet_rpc_server.h | 1 + tests/net_load_tests/clt.cpp | 1 + tests/net_load_tests/srv.cpp | 1 + 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 3a5c83017..5dbb7a478 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -43,6 +43,8 @@ #include // TODO #include // TODO #include // TODO +#include "warnings.h" +#include "string_tools.h" #include "misc_language.h" #include "net/local_ip.h" #include "pragma_comp_defs.h" @@ -51,8 +53,6 @@ #include #include -#include "../../../../src/cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal() - #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" @@ -149,10 +149,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())}; m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_); - // create a random uuid - boost::uuids::uuid random_uuid; - // that stuff turns out to be included, even though it's from src... Taking advantage - random_uuid = crypto::rand(); + // create a random uuid, we don't need crypto strength here + const boost::uuids::uuid random_uuid = boost::uuids::random_generator()(); context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income); _dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index 76db5346f..b53bdc200 100644 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -32,6 +32,7 @@ #include "string_tools.h" #include "file_io_utils.h" #include "net_parse_helpers.h" +#include "time_helper.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net.http" diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index ab8839636..2281d0734 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -29,6 +29,7 @@ #include #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/tx_extra.h" +#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_core/blockchain.h" #include "p2p/p2p_protocol_defs.h" #include "net/connection_basic.hpp" diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index c9ca63f43..e9d2061e8 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "common/command_line.h" +#include "cryptonote_core/cryptonote_core.h" #include "net_node.h" namespace nodetool diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index ab896aa3b..35ea11902 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -35,6 +35,7 @@ #include #include "common/util.h" #include "net/http_server_impl_base.h" +#include "math_helper.h" #include "wallet_rpc_server_commands_defs.h" #include "wallet2.h" diff --git a/tests/net_load_tests/clt.cpp b/tests/net_load_tests/clt.cpp index a65e02cab..275044045 100644 --- a/tests/net_load_tests/clt.cpp +++ b/tests/net_load_tests/clt.cpp @@ -41,6 +41,7 @@ #include "misc_language.h" #include "misc_log_ex.h" #include "storages/levin_abstract_invoke2.h" +#include "common/util.h" #include "net_load_tests.h" diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp index 6518d9117..54110fc1e 100644 --- a/tests/net_load_tests/srv.cpp +++ b/tests/net_load_tests/srv.cpp @@ -34,6 +34,7 @@ #include "include_base_utils.h" #include "misc_log_ex.h" #include "storages/levin_abstract_invoke2.h" +#include "common/util.h" #include "net_load_tests.h" From c3b8328cd3ca7e5052b6cb2f746b19137421d268 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 12 Oct 2018 14:09:30 +0000 Subject: [PATCH 0101/1007] daemon: do not run complex code in a signal handler instead, delegate the work to a one off thread and notify it from the signal handler --- src/daemon/daemon.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index ea24e32eb..f53649518 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -136,7 +136,14 @@ bool t_daemon::run(bool interactive) { throw std::runtime_error{"Can't run stopped daemon"}; } - tools::signal_handler::install(std::bind(&daemonize::t_daemon::stop_p2p, this)); + + std::atomic stop(false); + boost::thread([&stop, this] { + while (!stop) + epee::misc_utils::sleep_no_w(100); + this->stop_p2p(); + }).detach(); + tools::signal_handler::install([&stop](int){ stop = true; }); try { From 8f3c79374900ca77c126976036290d10f9999598 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 12 Oct 2018 21:02:59 +0000 Subject: [PATCH 0102/1007] readline_buffer: fix "cursor in prompt" bug It happens when readline displays a prompt just before switching to a shorter one --- contrib/epee/include/readline_buffer.h | 1 + contrib/epee/src/readline_buffer.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/epee/include/readline_buffer.h b/contrib/epee/include/readline_buffer.h index 87c8826cb..5968d243d 100644 --- a/contrib/epee/include/readline_buffer.h +++ b/contrib/epee/include/readline_buffer.h @@ -27,6 +27,7 @@ namespace rdln private: std::streambuf* m_cout_buf; + size_t m_prompt_length; static std::vector& completion_commands(); }; diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp index 076a63612..da264471f 100644 --- a/contrib/epee/src/readline_buffer.cpp +++ b/contrib/epee/src/readline_buffer.cpp @@ -44,7 +44,7 @@ std::vector& rdln::readline_buffer::completion_commands() } rdln::readline_buffer::readline_buffer() -: std::stringbuf(), m_cout_buf(NULL) +: std::stringbuf(), m_cout_buf(NULL), m_prompt_length(0) { current = this; } @@ -86,8 +86,11 @@ void rdln::readline_buffer::set_prompt(const std::string& prompt) if(m_cout_buf == NULL) return; boost::lock_guard lock(sync_mutex); + rl_set_prompt(std::string(m_prompt_length, ' ').c_str()); + rl_redisplay(); rl_set_prompt(prompt.c_str()); rl_redisplay(); + m_prompt_length = prompt.size(); } void rdln::readline_buffer::add_completion(const std::string& command) From d886b97fe216846647aea2560d423c138e0d67d4 Mon Sep 17 00:00:00 2001 From: m2049r Date: Fri, 12 Oct 2018 20:58:27 +0200 Subject: [PATCH 0103/1007] SOFTWARE is the default wallet device --- src/wallet/wallet2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index f87edf506..d774c54c0 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3611,6 +3611,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject()) crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); + device_type = hw::device::device_type::SOFTWARE; // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { From bf842a6a1e1e0a983d7c37ea7564b7f19d8544b1 Mon Sep 17 00:00:00 2001 From: xiphon Date: Sat, 13 Oct 2018 09:46:19 +0000 Subject: [PATCH 0104/1007] build: use ARCH 'native' by default, allow to configure and override it --- .travis.yml | 2 +- CMakeLists.txt | 8 +++----- contrib/depends/toolchain.cmake.in | 2 ++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ca3a24ae8..6a9b9b94b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ script: - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi - - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS" + - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake -DTRAVIS=true .. && make $MAKEJOBS" - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib after_script: - echo $TRAVIS_COMMIT_RANGE diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bffd29b6..78d16b2ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ if (IOS) endif() cmake_minimum_required(VERSION 2.8.7) +message(STATUS "CMake version ${CMAKE_VERSION}") project(monero) @@ -139,7 +140,6 @@ if(ARCH_ID STREQUAL "ppc64le") set(PPC64LE 1) set(PPC64 0) set(PPC 0) - endif() if(ARCH_ID STREQUAL "powerpc64" OR ARCH_ID STREQUAL "ppc64") @@ -517,10 +517,8 @@ if(MSVC) include_directories(SYSTEM src/platform/msc) else() include(TestCXXAcceptsFlag) - if (NOT ARM6) - if(NOT DEPENDS OR DEPENDS AND NOT ARM) - set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") - endif() + if (NOT ARCH) + set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") endif() message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}") if(ARCH STREQUAL "default") diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index f8548a724..66168facb 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -51,7 +51,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") SET(APPLE True) SET(BUILD_TAG "mac-x64") SET(BUILD_64 ON) + if(NOT TRAVIS) SET(ARCH "x86_64") + endif() SET(BREW OFF) SET(PORT OFF) SET(CMAKE_OSX_SYSROOT "@sdk@/MacOSX10.11.sdk/") From 76d6d832d2a43ff03acf9b4ce7b5f0f9e34231e2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 13 Oct 2018 10:19:17 +0000 Subject: [PATCH 0105/1007] Revert "p2p: connect via the bound ip, if any" This reverts commit 909398efc79cb1fa92e330e9a50a316ca5858953. It looks like it's causing trouble with tor on some setups --- src/p2p/net_node.inl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 74924e4f4..9390626a8 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -937,7 +937,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if(!res) { @@ -1002,7 +1002,7 @@ namespace nodetool bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, - con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + con); if (!res) { bool is_priority = is_priority_node(na); @@ -1617,7 +1617,7 @@ namespace nodetool return false; } return true; - }, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip); + }); if(!r) { LOG_WARNING_CC(context, "Failed to call connect_async, network error."); From 938476c9a59e04c245fac7707c6baf2183964e60 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 13 Oct 2018 18:11:09 +0000 Subject: [PATCH 0106/1007] CMakeLists.txt: detect and use -pthread compiler flag The cmake thread detection just ain't enough to always work --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bffd29b6..d96dd649e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -428,6 +428,8 @@ if (UNIX AND NOT APPLE) # Note that at the time of this writing the -Wstrict-prototypes flag added below will make this fail set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads) + add_c_flag_if_supported(-pthread CMAKE_C_FLAGS) + add_cxx_flag_if_supported(-pthread CMAKE_CXX_FLAGS) endif() # Handle OpenSSL, used for sha256sum on binary updates and light wallet ssl http From 5dff61d4c322734f62422df8dcf181ee73f952f9 Mon Sep 17 00:00:00 2001 From: xiphon Date: Sun, 14 Oct 2018 10:51:52 +0000 Subject: [PATCH 0107/1007] readme: update OSX build badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5da96371a..d6515cfc7 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,9 @@ These builds are of the master branch, which is used for active development and | Ubuntu 16.04 | amd64 | [![Ubuntu 16.04 amd64](https://build.getmonero.org/png?builder=monero-static-ubuntu-amd64)](https://build.getmonero.org/builders/monero-static-ubuntu-amd64) | Ubuntu 16.04 | armv7 | [![Ubuntu 16.04 armv7](https://build.getmonero.org/png?builder=monero-static-ubuntu-arm7)](https://build.getmonero.org/builders/monero-static-ubuntu-arm7) | Debian Stable | armv8 | [![Debian armv8](https://build.getmonero.org/png?builder=monero-static-debian-armv8)](https://build.getmonero.org/builders/monero-static-debian-armv8) -| OSX 10.10 | amd64 | [![OSX 10.10 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.10)](https://build.getmonero.org/builders/monero-static-osx-10.10) | OSX 10.11 | amd64 | [![OSX 10.11 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.11)](https://build.getmonero.org/builders/monero-static-osx-10.11) | OSX 10.12 | amd64 | [![OSX 10.12 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.12)](https://build.getmonero.org/builders/monero-static-osx-10.12) +| OSX 10.13 | amd64 | [![OSX 10.13 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.13)](https://build.getmonero.org/builders/monero-static-osx-10.13) | FreeBSD 11 | amd64 | [![FreeBSD 11 amd64](https://build.getmonero.org/png?builder=monero-static-freebsd64)](https://build.getmonero.org/builders/monero-static-freebsd64) | DragonFly BSD 4.6 | amd64 | [![DragonFly BSD amd64](https://build.getmonero.org/png?builder=monero-static-dragonflybsd-amd64)](https://build.getmonero.org/builders/monero-static-dragonflybsd-amd64) | Windows (MSYS2/MinGW) | i686 | [![Windows (MSYS2/MinGW) i686](https://build.getmonero.org/png?builder=monero-static-win32)](https://build.getmonero.org/builders/monero-static-win32) From 991613f88a6aa789610bd2f646b94f0958f7a497 Mon Sep 17 00:00:00 2001 From: Tyler Baker Date: Sat, 13 Oct 2018 14:13:43 -0700 Subject: [PATCH 0108/1007] Dockerfile: init and update submodules The Docker image is failing to build, as the submodules are not being explicitly initialized and updated. Fixes: https://github.com/monero-project/monero/issues/4582 Signed-off-by: Tyler Baker --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 40ba81d9c..cd3e7df70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -115,6 +115,7 @@ COPY . . ENV USE_SINGLE_BUILDDIR=1 ARG NPROC RUN set -ex && \ + git submodule init && git submodule update && \ rm -rf build && \ if [ -z "$NPROC" ] ; \ then make -j$(nproc) release-static ; \ From a677492f1be6c0ae791775577f9edccc25f7201c Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 15 Oct 2018 11:57:02 +0900 Subject: [PATCH 0109/1007] tx_pool: store hex string instead of raw binary to tx_blob of get_transaction_pool RPC Inspired by https://github.com/masari-project/masari/issues/93 --- src/cryptonote_core/tx_pool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index c31a2073b..c8b8a6786 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -766,7 +766,7 @@ namespace cryptonote m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ tx_info txi; txi.id_hash = epee::string_tools::pod_to_hex(txid); - txi.tx_blob = *bd; + txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(*bd); transaction tx; if (!parse_and_validate_tx_from_blob(*bd, tx)) { From 9ea507812e4a996885272bb8541195762f0cd5be Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 15 Oct 2018 13:00:32 +0000 Subject: [PATCH 0110/1007] README: add libnorm to the dependency list --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b5dd0629..dde8d3beb 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ library archives (`.a`). | OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum | | libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `cppzmq-devel` | NO | ZeroMQ library | | OpenPGM | ? | NO | `libpgm-dev` | `libpgm` | `openpgm-devel` | NO | For ZeroMQ | +| libnorm[2] | ? | NO | `libnorm-dev` | | ` | YES | For ZeroMQ | | libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver | | libsodium | ? | NO | `libsodium-dev` | `libsodium` | `libsodium-devel` | NO | cryptography | | libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces | @@ -147,13 +148,14 @@ library archives (`.a`). | libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | YES | Input editing | | ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit | | expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing | -| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite | +| GTest | 1.5 | YES | `libgtest-dev`[1] | `gtest` | `gtest-devel` | YES | Test suite | | Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | | Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | -[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must +[1] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ``` +[2] libnorm-dev is needed if your zmq library was built with libnorm, and not needed otherwise Debian / Ubuntu one liner for all dependencies ``` sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev``` From 6f28667aa3aea43b6bc697a9896d8e44fd12a7da Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 15 Oct 2018 22:10:49 +0000 Subject: [PATCH 0111/1007] daemon: fix reading past stack on exit --- src/daemon/daemon.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index f53649518..49d6d49cf 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -137,13 +137,18 @@ bool t_daemon::run(bool interactive) throw std::runtime_error{"Can't run stopped daemon"}; } - std::atomic stop(false); - boost::thread([&stop, this] { + std::atomic stop(false), shutdown(false); + boost::thread stop_thread = boost::thread([&stop, &shutdown, this] { while (!stop) epee::misc_utils::sleep_no_w(100); - this->stop_p2p(); - }).detach(); - tools::signal_handler::install([&stop](int){ stop = true; }); + if (shutdown) + this->stop_p2p(); + }); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ + stop = true; + stop_thread.join(); + }); + tools::signal_handler::install([&stop, &shutdown](int){ stop = shutdown = true; }); try { From 0fbbb065d4d384f6f412d866f45b5583ea6098ac Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 15 Oct 2018 22:39:51 +0000 Subject: [PATCH 0112/1007] p2p: a negative result from UPNP_GetValidIGD is an error as per the source documentation --- src/p2p/net_node.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 9390626a8..705c4da4e 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -2042,7 +2042,7 @@ namespace nodetool char lanAddress[64]; result = UPNP_GetValidIGD(deviceList, &urls, &igdData, lanAddress, sizeof lanAddress); freeUPNPDevlist(deviceList); - if (result != 0) { + if (result > 0) { if (result == 1) { std::ostringstream portString; portString << port; @@ -2088,7 +2088,7 @@ namespace nodetool char lanAddress[64]; result = UPNP_GetValidIGD(deviceList, &urls, &igdData, lanAddress, sizeof lanAddress); freeUPNPDevlist(deviceList); - if (result != 0) { + if (result > 0) { if (result == 1) { std::ostringstream portString; portString << port; From e7f24850d56d70c18930da97bffad20710451d4a Mon Sep 17 00:00:00 2001 From: iDunk5400 Date: Fri, 12 Oct 2018 15:20:42 +0000 Subject: [PATCH 0113/1007] Fix Windows build after epee dependency change --- CMakeLists.txt | 2 +- src/daemonizer/windows_daemonizer.inl | 1 + tests/functional_tests/CMakeLists.txt | 4 ---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 78d16b2ad..8baac02e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -880,7 +880,7 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj") - set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32) + set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt) if(DEPENDS) set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv) else() diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 8077f29fb..7e61e3603 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -31,6 +31,7 @@ #include "common/util.h" #include "daemonizer/windows_service.h" #include "daemonizer/windows_service_runner.h" +#include "cryptonote_core/cryptonote_core.h" #include #include diff --git a/tests/functional_tests/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt index 4b21b945c..7a2a7fbd1 100644 --- a/tests/functional_tests/CMakeLists.txt +++ b/tests/functional_tests/CMakeLists.txt @@ -26,10 +26,6 @@ # 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. -if(WIN32) - set(EXTRA_LIBRARIES "${EXTRA_LIBRARIES};bcrypt") -endif() - set(functional_tests_sources main.cpp transactions_flow_test.cpp From e623f2b225106933cf26330fc4814d50a5d72bfb Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Tue, 16 Oct 2018 03:39:17 +0200 Subject: [PATCH 0114/1007] Add building with depends to the Makefile Depends can now be compiled with `make depends target=$triple`, where $triple is one of the supported build targets. Adapt the Makefile for this change, remove not needed windows deps from depends setup description. --- Makefile | 4 ++++ README.md | 21 +++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 40b8839cc..c858412e6 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,10 @@ endif all: release-all +depends: + cd contrib/depends && $(MAKE) HOST=$(target) && cd ../.. && mkdir -p build/$(target)/release + cd build/$(target)/release && cmake -DCMAKE_TOOLCHAIN_FILE=$(CURDIR)/contrib/depends/$(target)/share/toolchain.cmake ../../.. && $(MAKE) + cmake-debug: mkdir -p $(builddir)/debug cd $(builddir)/debug && cmake -D CMAKE_BUILD_TYPE=Debug $(topdir) diff --git a/README.md b/README.md index 4b5dd0629..c9418f81c 100644 --- a/README.md +++ b/README.md @@ -494,22 +494,19 @@ By default, in either dynamically or statically linked builds, binaries target t ### Cross Compiling -You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system. Go to `contrib/depends` and type: +You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system. -* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries. -* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc -* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev -* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc -* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686 -* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf +* ```make depends target=x86_64-linux-gnu``` for 64-bit linux binaries. +* ```make depends target=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 g++-mingw-w64-x86-64 wine1.6 bc +* ```make depends target=x86_64-apple-darwin11``` for macOS binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev +* ```make depends target=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc +* ```make depends target=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 g++-mingw-w64-i686 +* ```make depends target=arm-linux-gnueabihf``` for armv7 binaries. Requires: g++-arm-linux-gnueabihf +* ```make depends target=aarch64-linux-gnu``` for armv8 binaries. Requires: g++-aarch64-linux-gnu The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names. -Then go back to the source dir and type: -* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends//share/toolchain.cmake``` -Where is one of the above mentioned targets. - -Using `depends` might also be easier to compile Monero on Windows than using MSys. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above. +Using `depends` might also be easier to compile Monero on Windows than using MSYS. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above. ## Installing Monero from a package From 9b6dd9348c6447c57e8c03675949871ab21b1f9a Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Mon, 15 Oct 2018 23:42:29 -0400 Subject: [PATCH 0115/1007] Providing user supplied default constructor for expect --- src/common/expect.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/expect.h b/src/common/expect.h index 326242502..72e4060a7 100644 --- a/src/common/expect.h +++ b/src/common/expect.h @@ -350,7 +350,9 @@ class expect using error_type = std::error_code; //! Create a successful object. - expect() = default; + expect() noexcept + : code_() + {} expect(std::error_code const& code) noexcept : code_(code) From 45a6880d789414b85028c8e7b56f920f162d2d04 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 09:16:36 +0000 Subject: [PATCH 0116/1007] unit_tests: call umask before mkstemp Coverity 188788 --- tests/unit_tests/notify.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index d6811c6bd..e2477a76e 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -26,6 +26,10 @@ // 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. +#ifdef __GLIBC__ +#include +#endif + #include "gtest/gtest.h" #include @@ -37,8 +41,14 @@ TEST(notify, works) { +#ifdef __GLIBC__ + mode_t prevmode = umask(077); +#endif char name_template[] = "/tmp/monero-notify-unit-test-XXXXXX"; int fd = mkstemp(name_template); +#ifdef __GLIBC__ + umask(prevmode); +#endif ASSERT_TRUE(fd >= 0); close(fd); From 2d48861db78f6495a1b4bf07b6fe653c818a066f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 09:17:21 +0000 Subject: [PATCH 0117/1007] p2p: only deinitialize what's been initialized in offline mode --- src/p2p/net_node.inl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 9390626a8..17de18972 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -655,10 +655,14 @@ namespace nodetool { kill(); m_peerlist.deinit(); - m_net_server.deinit_server(); - // remove UPnP port mapping - if(!m_no_igd) - delete_upnp_port_mapping(m_listening_port); + + if (!m_offline) + { + m_net_server.deinit_server(); + // remove UPnP port mapping + if(!m_no_igd) + delete_upnp_port_mapping(m_listening_port); + } return store_config(); } //----------------------------------------------------------------------------------- From a7960542a9f8ea0ee0e90a24c411bb98f452c53b Mon Sep 17 00:00:00 2001 From: mmitkevich Date: Tue, 16 Oct 2018 14:58:22 +0300 Subject: [PATCH 0118/1007] WalletAPI: rescanBlockchain, rescanBlockchainAsync --- src/wallet/api/wallet.cpp | 26 ++++++++++++++++++++++++-- src/wallet/api/wallet.h | 3 +++ src/wallet/api/wallet2_api.h | 11 +++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index de1bfdae1..da6ee5d75 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -381,6 +381,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds) , m_synchronized(false) , m_rebuildWalletCache(false) , m_is_connected(false) + , m_refreshShouldRescan(false) { m_wallet.reset(new tools::wallet2(static_cast(nettype), kdf_rounds, true)); m_history.reset(new TransactionHistoryImpl(this)); @@ -1011,6 +1012,20 @@ void WalletImpl::refreshAsync() m_refreshCV.notify_one(); } +bool WalletImpl::rescanBlockchain() +{ + clearStatus(); + m_refreshShouldRescan = true; + doRefresh(); + return status() == Status_Ok; +} + +void WalletImpl::rescanBlockchainAsync() +{ + m_refreshShouldRescan = true; + refreshAsync(); +} + void WalletImpl::setAutoRefreshInterval(int millis) { if (millis > MAX_REFRESH_INTERVAL_MILLIS) { @@ -1984,6 +1999,7 @@ void WalletImpl::refreshThreadFunc() LOG_PRINT_L3(__FUNCTION__ << ": refresh lock acquired..."); LOG_PRINT_L3(__FUNCTION__ << ": m_refreshEnabled: " << m_refreshEnabled); LOG_PRINT_L3(__FUNCTION__ << ": m_status: " << status()); + LOG_PRINT_L3(__FUNCTION__ << ": m_refreshShouldRescan: " << m_refreshShouldRescan); if (m_refreshEnabled) { LOG_PRINT_L3(__FUNCTION__ << ": refreshing..."); doRefresh(); @@ -1994,12 +2010,16 @@ void WalletImpl::refreshThreadFunc() void WalletImpl::doRefresh() { + bool rescan = m_refreshShouldRescan.exchange(false); // synchronizing async and sync refresh calls boost::lock_guard guarg(m_refreshMutex2); - try { + do try { + LOG_PRINT_L3(__FUNCTION__ << ": doRefresh, rescan = "<light_wallet() || daemonSynced()) { + if(rescan) + m_wallet->rescan_blockchain(false); m_wallet->refresh(trustedDaemon()); if (!m_synchronized) { m_synchronized = true; @@ -2016,7 +2036,9 @@ void WalletImpl::doRefresh() } } catch (const std::exception &e) { setStatusError(e.what()); - } + break; + }while(!rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested + if (m_wallet2Callback->getListener()) { m_wallet2Callback->getListener()->refreshed(); } diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 6d343888b..b4637b8e6 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -114,6 +114,8 @@ class WalletImpl : public Wallet bool synchronized() const override; bool refresh() override; void refreshAsync() override; + bool rescanBlockchain() override; + void rescanBlockchainAsync() override; void setAutoRefreshInterval(int millis) override; int autoRefreshInterval() const override; void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override; @@ -232,6 +234,7 @@ class WalletImpl : public Wallet std::atomic m_refreshEnabled; std::atomic m_refreshThreadDone; std::atomic m_refreshIntervalMillis; + std::atomic m_refreshShouldRescan; // synchronizing refresh loop; boost::mutex m_refreshMutex; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index ec1a84877..82627de29 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -643,6 +643,17 @@ struct Wallet */ virtual void refreshAsync() = 0; + /** + * @brief rescanBlockchain - rescans the wallet, updating transactions from daemon + * @return - true if refreshed successfully; + */ + virtual bool rescanBlockchain() = 0; + + /** + * @brief rescanBlockchainAsync - rescans wallet asynchronously, starting from genesys + */ + virtual void rescanBlockchainAsync() = 0; + /** * @brief setAutoRefreshInterval - setup interval for automatic refresh. * @param seconds - interval in millis. if zero or less than zero - automatic refresh disabled; From 4eca42b2411c7ff11fea7b9b64881509d90932e3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 10:09:57 +0000 Subject: [PATCH 0119/1007] blockchain_db: initialize m_hardfork in ctor just in case Coverity 136568 --- src/blockchain_db/blockchain_db.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 396ae7544..71c46d76b 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -544,7 +544,7 @@ class BlockchainDB /** * @brief An empty constructor. */ - BlockchainDB(): m_open(false) { } + BlockchainDB(): m_hardfork(NULL), m_open(false) { } /** * @brief An empty destructor. From 32123789129372f1a4cb46a8aa289843e15a4b37 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 10:14:27 +0000 Subject: [PATCH 0120/1007] wallet2: initialize some scalar fields in ctor where appropriate Coverity 188336 --- src/wallet/wallet2.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d774c54c0..fae972cf8 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -809,6 +809,7 @@ wallet_keys_unlocker::~wallet_keys_unlocker() wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), + m_upper_transaction_weight_limit(0), m_run(true), m_callback(0), m_trusted_daemon(false), @@ -841,6 +842,9 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_is_initialized(false), m_kdf_rounds(kdf_rounds), is_old_file_format(false), + m_watch_only(false), + m_multisig(false), + m_multisig_threshold(0), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex), m_subaddress_lookahead_major(SUBADDRESS_LOOKAHEAD_MAJOR), m_subaddress_lookahead_minor(SUBADDRESS_LOOKAHEAD_MINOR), From 7cc39845be1cfa9286dec589d4f1c94381b140d9 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 10:22:24 +0000 Subject: [PATCH 0121/1007] account: init creation timestamp to 0 Never actually used uninitialized Coverity 136615 --- src/cryptonote_basic/account.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index e891a748d..1dc1ad71d 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -136,6 +136,7 @@ DISABLE_VS_WARNINGS(4244 4345) void account_base::set_null() { m_keys = account_keys(); + m_creation_timestamp = 0; } //----------------------------------------------------------------- void account_base::forget_spend_key() From bfa2dce171e2a04096c07f204037ccd13dc2fae6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 10:35:34 +0000 Subject: [PATCH 0122/1007] rpc: remove unused ctors Also prevents coverity from moaning about them not initializing fields --- src/rpc/core_rpc_server_commands_defs.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 3b654d4cb..b229841d6 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -782,9 +782,6 @@ namespace cryptonote std::string tx_as_hex; bool do_not_relay; - request() {} - explicit request(const transaction &); - BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(tx_as_hex) KV_SERIALIZE_OPT(do_not_relay, false) From 3ffbec1556f8817cb014fcea83bccc41747cfcf5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 10:36:49 +0000 Subject: [PATCH 0123/1007] rpc: init m_rpc_version in Message ctor Coverity 182501 --- src/rpc/message.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/message.h b/src/rpc/message.h index 16b8e92fc..56087b998 100644 --- a/src/rpc/message.h +++ b/src/rpc/message.h @@ -65,7 +65,7 @@ namespace rpc static const char* STATUS_BAD_REQUEST; static const char* STATUS_BAD_JSON; - Message() : status(STATUS_OK) { } + Message() : status(STATUS_OK), rpc_version(0) { } virtual ~Message() { } From ad4cce930b3d969feaf9225e07f9f13688f21fe7 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 16 Oct 2018 14:43:56 +0000 Subject: [PATCH 0124/1007] build: fixed submodule check --- CMakeLists.txt | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8baac02e9..72aec521a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,19 +175,21 @@ endif() if(NOT MANUAL_SUBMODULES) find_package(Git) if(GIT_FOUND) + function (check_submodule relative_path) + execute_process(COMMAND git -C ${relative_path} rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE localHead) + execute_process(COMMAND git rev-parse "HEAD:${relative_path}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE checkedHead) + string(COMPARE EQUAL "${localHead}" "${checkedHead}" upToDate) + if (upToDate) + message(STATUS "Submodule '${relative_path}' is up-to-date") + else() + message(FATAL_ERROR "Submodule '${relative_path}' is not up-to-date. Please update with\ngit submodule update --init --force ${relative_path}\nor run cmake with -DMANUAL_SUBMODULES=1") + endif() + endfunction () + message(STATUS "Checking submodules") - execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/miniupnp && git rev-parse HEAD" OUTPUT_VARIABLE miniupnpLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/unbound && git rev-parse HEAD" OUTPUT_VARIABLE unboundLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process(COMMAND bash -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson && git rev-parse HEAD" OUTPUT_VARIABLE rapidjsonLocalHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/miniupnp | awk '{print $3}'" OUTPUT_VARIABLE miniupnpCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/unbound | awk '{print $3}'" OUTPUT_VARIABLE unboundCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process(COMMAND bash -c "git ls-tree HEAD ${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson | awk '{print $3}'" OUTPUT_VARIABLE rapidjsonCheckedHead WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - string(COMPARE EQUAL "${miniupnpLocalHead}" "${miniupnpCheckedHead}" miniupnpUpToDate) - string(COMPARE EQUAL "${unboundLocalHead}" "${unboundCheckedHead}" unboundUpToDate) - string(COMPARE EQUAL "${rapidjsonLocalHead}" "${rapidjsonCheckedHead}" rapidjsonUpToDate) - if (NOT miniupnpUpToDate OR NOT unboundUpToDate OR NOT rapidjsonUpToDate) - message(FATAL_ERROR "Submodules not up to date. Please update with git submodule init && git submodule update, or run cmake with -DMANUAL_SUBMODULES=1") - endif() + check_submodule(external/miniupnp) + check_submodule(external/unbound) + check_submodule(external/rapidjson) endif() endif() From 0cdd4b074ebab612d7d0a6ebaf3efffb1f9435ef Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 14:46:17 +0000 Subject: [PATCH 0125/1007] wallet2_api: fix generating new wallet in the GUI It was creating a new wallet without a password first (this should be fixed), then not changing the password correctly --- src/wallet/api/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index de1bfdae1..bb1ba83ca 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -776,7 +776,7 @@ bool WalletImpl::setPassword(const std::string &password) { clearStatus(); try { - m_wallet->rewrite(m_wallet->get_wallet_file(), password); + m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password); m_password = password; } catch (const std::exception &e) { setStatusError(e.what()); From 99d45a95787010fd9e38390b6ab350df8a738287 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 15:16:32 +0000 Subject: [PATCH 0126/1007] wallet_rpc_server: fix change_wallet_password RPC --- src/wallet/wallet_rpc_server.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e0b631aaf..1b63d65b6 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2822,8 +2822,7 @@ namespace tools { try { - m_wallet->rewrite(m_wallet->get_wallet_file(), req.new_password); - m_wallet->store(); + m_wallet->change_password(m_wallet->get_wallet_file(), req.old_password, req.new_password); LOG_PRINT_L0("Wallet password changed."); } catch (const std::exception& e) From a69fc05a0cf8eb9d3247bbb0006546ba4994a310 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 17:20:11 +0000 Subject: [PATCH 0127/1007] util: close keys file lock on exec --- src/common/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a1d49af0..7d8c9aa99 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -233,7 +233,7 @@ namespace tools MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); } #else - m_fd = open(filename.c_str(), O_RDONLY | O_CREAT, 0666); + m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666); if (m_fd != -1) { if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) From c77439298591792601f8c3f4c94950ef6e2c542a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 16 Oct 2018 18:08:36 +0000 Subject: [PATCH 0128/1007] spawn: close all file descriptors before execve No need to give whatever we're calling access to what we use --- src/common/spawn.cpp | 3 +++ src/common/util.cpp | 20 ++++++++++++++++++++ src/common/util.h | 2 ++ 3 files changed, 25 insertions(+) diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp index 59f11675c..0a2ce8387 100644 --- a/src/common/spawn.cpp +++ b/src/common/spawn.cpp @@ -38,6 +38,7 @@ #endif #include "misc_log_ex.h" +#include "util.h" #include "spawn.h" namespace tools @@ -101,6 +102,8 @@ int spawn(const char *filename, const std::vector& args, bool wait) // child if (pid == 0) { + tools::closefrom(3); + close(0); char *envp[] = {NULL}; execve(filename, argv, envp); MERROR("Failed to execve: " << strerror(errno)); diff --git a/src/common/util.cpp b/src/common/util.cpp index 2a1d49af0..9afeb2607 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -28,6 +28,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include #include #ifdef __GLIBC__ @@ -967,4 +968,23 @@ std::string get_nix_version_display_string() } #endif + void closefrom(int fd) + { +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__ + ::closefrom(fd); +#else +#if defined __GLIBC__ + const int sc_open_max = sysconf(_SC_OPEN_MAX); + const int MAX_FDS = std::min(65536, sc_open_max); +#else + const int MAX_FDS = 65536; +#endif + while (fd < MAX_FDS) + { + close(fd); + ++fd; + } +#endif + } + } diff --git a/src/common/util.h b/src/common/util.h index ce773bd38..e793a42b5 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -238,4 +238,6 @@ namespace tools #ifdef _WIN32 std::string input_line_win(); #endif + + void closefrom(int fd); } From c39e0a1706500068bb58477e40b92ae411d47e8f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 17 Oct 2018 16:22:27 +0000 Subject: [PATCH 0129/1007] core: don't verify range proofs multiple times --- src/cryptonote_core/cryptonote_core.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 69e3c708b..2fec6b613 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -856,16 +856,19 @@ namespace cryptonote } waiter.wait(&tpool); it = tx_blobs.begin(); + std::vector already_have(tx_blobs.size(), false); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { if (!results[i].res) continue; if(m_mempool.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool"); + already_have[i] = true; } else if(m_blockchain_storage.have_tx(results[i].hash)) { LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain"); + already_have[i] = true; } else { @@ -887,7 +890,7 @@ namespace cryptonote std::vector tx_info; tx_info.reserve(tx_blobs.size()); for (size_t i = 0; i < tx_blobs.size(); i++) { - if (!results[i].res) + if (!results[i].res || already_have[i]) continue; tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res}); } @@ -897,6 +900,8 @@ namespace cryptonote bool ok = true; it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { + if (already_have[i]) + continue; if (!results[i].res) { ok = false; From ec3013903b06768a04d5f33eabf38777977dd5f6 Mon Sep 17 00:00:00 2001 From: Cactii1 <37589158+Cactii1@users.noreply.github.com> Date: Wed, 17 Oct 2018 21:36:10 +0200 Subject: [PATCH 0130/1007] Update db_lmdb.cpp --- src/blockchain_db/lmdb/db_lmdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index bd91f308a..d9c849cca 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1208,7 +1208,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) if (is_hdd_result) { if (is_hdd_result.value()) - MCLOG_RED(el::Level::Warning, "global", "The blockchain is on a rotating drive: this will be very slow, use a SSD if possible"); + MCLOG_RED(el::Level::Warning, "global", "The blockchain is on a rotating drive: this will be very slow, use an SSD if possible"); } m_folder = filename; From 11415128118396a8e99774f4c9cc4aafbf319c53 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 17 Oct 2018 21:12:11 +0000 Subject: [PATCH 0131/1007] unit_tests: fix notify test when run from make *test --- tests/unit_tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index e248ed965..7687e3c52 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -123,7 +123,7 @@ SET_PROPERTY(SOURCE memwipe.cpp PROPERTY COMPILE_FLAGS -Ofast) add_test( NAME unit_tests - COMMAND unit_tests --data-dir "${TEST_DATA_DIR} --binary-dir ${CMAKE_BINARY_DIR}") + COMMAND unit_tests --data-dir "${TEST_DATA_DIR}") add_executable(test_notifier test_notifier.cpp) target_link_libraries(test_notifier ${EXTRA_LIBRARIES}) From 776aefdac1f8e011d3e1fcc99cceb3bfb6e7d8f9 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 18 Oct 2018 08:01:56 +0900 Subject: [PATCH 0132/1007] tx_pool: revert #4592 and move bin2hex conversion to on_get_transaction_pool --- src/cryptonote_core/tx_pool.cpp | 2 +- src/rpc/core_rpc_server.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5a9fcf67e..553a22298 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -765,7 +765,7 @@ namespace cryptonote m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ tx_info txi; txi.id_hash = epee::string_tools::pod_to_hex(txid); - txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(*bd); + txi.tx_blob = *bd; transaction tx; if (!parse_and_validate_tx_from_blob(*bd, tx)) { diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d8f556d3e..263ddf1bc 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -924,6 +924,8 @@ namespace cryptonote return r; m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted); + for (tx_info& txi : res.transactions) + txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(txi.tx_blob); res.status = CORE_RPC_STATUS_OK; return true; } From 825d836f9f6ee724cf5b44ce720ad0bc26730ba0 Mon Sep 17 00:00:00 2001 From: xiphon Date: Thu, 18 Oct 2018 04:37:30 +0000 Subject: [PATCH 0133/1007] device: fixed Ledger Nano S device selection --- src/device/device_io_hid.cpp | 6 +++--- src/device/device_io_hid.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 562aca8b8..0296914e1 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -72,7 +72,7 @@ namespace hw { this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page); } - void device_io_hid::connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ) { + void device_io_hid::connect(unsigned int vid, unsigned int pid, int interface_number, unsigned short usage_page, bool interface_OR_page ) { hid_device_info *hwdev_info, *hwdev_info_list; hid_device *hwdev; @@ -83,8 +83,8 @@ namespace hw { hwdev = NULL; hwdev_info = hwdev_info_list; while (hwdev_info) { - if ((interface_OR_page && ((usage_page == 0xffa0) || (interface_number == 0))) || - ((usage_page == 0xffa0) && (interface_number == 0)) ) { + if ((interface_OR_page && ((hwdev_info->usage_page == usage_page) || (hwdev_info->interface_number == interface_number))) || + ((hwdev_info->usage_page == usage_page) && (hwdev_info->interface_number == interface_number))) { MDEBUG("HID Device found: " << safe_hid_path(hwdev_info)); hwdev = hid_open_path(hwdev_info->path); break; diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index 6fd15a1d1..ffd3f534f 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -52,8 +52,8 @@ namespace hw { struct hid_conn_params { unsigned int vid; unsigned int pid; - unsigned int interface_number; - unsigned int usage_page; + int interface_number; + unsigned short usage_page; bool interface_OR_page ; }; @@ -100,7 +100,7 @@ namespace hw { void init(); void connect(void *params); - void connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ); + void connect(unsigned int vid, unsigned int pid, int interface_number, unsigned short usage_page, bool interface_OR_page ); bool connected() const; int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len); void disconnect(); From e54e5668a85fc5139077351e0035ef1318f2ef7f Mon Sep 17 00:00:00 2001 From: Ricardo de Vries Date: Thu, 18 Oct 2018 10:45:42 +0200 Subject: [PATCH 0134/1007] daemon: Show mining address --- src/daemon/rpc_command_executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 6464d372f..9a0603a10 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -449,7 +449,7 @@ bool t_rpc_command_executor::show_status() { % get_sync_percentage(ires) % (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet") % bootstrap_msg - % (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) ) : "not mining") + % (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) + std::string(" to ") + mres.address ) : "not mining") % get_mining_speed(ires.difficulty / ires.target) % (unsigned)hfres.version % get_fork_extra_info(hfres.earliest_height, net_height, ires.target) From 6f88c03dfc2f2318a13e9c0177536aeeec44ea24 Mon Sep 17 00:00:00 2001 From: Ted Moravec Date: Thu, 18 Oct 2018 09:14:15 +0000 Subject: [PATCH 0135/1007] Simplewallet: update help text for show_transfers. Describe the output format. --- src/simplewallet/simplewallet.cpp | 10 +++++++++- translations/monero.ts | 11 ++++++++++- translations/monero_fr.ts | 11 ++++++++++- translations/monero_it.ts | 11 ++++++++++- translations/monero_sv.ts | 11 ++++++++++- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 47b77abc6..7e0900edc 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2484,7 +2484,15 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("show_transfers", boost::bind(&simple_wallet::show_transfers, this, _1), tr("show_transfers [in|out|pending|failed|pool|coinbase] [index=[,,...]] [ []]"), - tr("Show the incoming/outgoing transfers within an optional height range.")); + // Seemingly broken formatting to compensate for the backslash before the quotes. + tr("Show the incoming/outgoing transfers within an optional height range.\n\n" + "Output format:\n" + "In or Coinbase: Block Number, \"block\"|\"in\", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, \"-\", Note\n" + "Out: Block Number, \"out\", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, \"-\", Note\n" + "Pool: \"pool\", \"in\", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, \"-\", Note, Double Spend Note\n" + "Pending or Failed: \"failed\"|\"pending\", \"out\", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, \"-\", Note\n\n" + "* Excluding change and fee.\n" + "** Set of address indices used as inputs in this transfer.")); m_cmd_binder.set_handler("unspent_outputs", boost::bind(&simple_wallet::unspent_outputs, this, _1), tr("unspent_outputs [index=[,,...]] [ []]"), diff --git a/translations/monero.ts b/translations/monero.ts index 8d4ee7ab8..e28a2a058 100644 --- a/translations/monero.ts +++ b/translations/monero.ts @@ -1727,7 +1727,16 @@ Otherwise, you prove the reserve of the smallest possible amount above <amoun - Show the incoming/outgoing transfers within an optional height range. + Show the incoming/outgoing transfers within an optional height range. + +Output format: +In or Coinbase: Block Number, "block"|"in", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, "-", Note\ +Out: Block Number, "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, "-", Note +Pool: "pool", "in", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, "-", Note, Double Spend Note\ +Pending or Failed: "failed"|"pending", "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, "-", Note + +* Excluding change and fee. +** Set of address indices used as inputs in this transfer. diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts index bac742c56..27c38ee10 100644 --- a/translations/monero_fr.ts +++ b/translations/monero_fr.ts @@ -1789,7 +1789,16 @@ Sinon, vous prouvez le plus petit solde supérieur à <montant> dans votre - Show the incoming/outgoing transfers within an optional height range. + Show the incoming/outgoing transfers within an optional height range. + +Output format: +In or Coinbase: Block Number, "block"|"in", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, "-", Note\ +Out: Block Number, "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, "-", Note +Pool: "pool", "in", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, "-", Note, Double Spend Note\ +Pending or Failed: "failed"|"pending", "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, "-", Note + +* Excluding change and fee. +** Set of address indices used as inputs in this transfer. Afficher les transferts entrants/sortants dans un interval de hauteurs facultatif. diff --git a/translations/monero_it.ts b/translations/monero_it.ts index d4b1695f3..5ab96d7dc 100644 --- a/translations/monero_it.ts +++ b/translations/monero_it.ts @@ -1702,7 +1702,16 @@ Otherwise, you prove the reserve of the smallest possible amount above <amoun - Show the incoming/outgoing transfers within an optional height range. + Show the incoming/outgoing transfers within an optional height range. + +Output format: +In or Coinbase: Block Number, "block"|"in", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, "-", Note\ +Out: Block Number, "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, "-", Note +Pool: "pool", "in", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, "-", Note, Double Spend Note\ +Pending or Failed: "failed"|"pending", "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, "-", Note + +* Excluding change and fee. +** Set of address indices used as inputs in this transfer. diff --git a/translations/monero_sv.ts b/translations/monero_sv.ts index 3c5ddf9af..b2387cdb1 100644 --- a/translations/monero_sv.ts +++ b/translations/monero_sv.ts @@ -1855,7 +1855,16 @@ Annars bevisar du reserven för det minsta möjliga belopp över <belopp> - Show the incoming/outgoing transfers within an optional height range. + Show the incoming/outgoing transfers within an optional height range. + +Output format: +In or Coinbase: Block Number, "block"|"in", Time, Amount, Transaction Hash, Payment ID, Subaddress Index, "-", Note\ +Out: Block Number, "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Destinations, Input addresses**, "-", Note +Pool: "pool", "in", Time, Amount, Transaction Hash, Payment Id, Subaddress Index, "-", Note, Double Spend Note\ +Pending or Failed: "failed"|"pending", "out", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, "-", Note + +* Excluding change and fee. +** Set of address indices used as inputs in this transfer. Visa inkommande/utgående överföringar inom ett valfritt höjdintervall. From 109717a5fdfc9251997cab4933af6c8608d2bf9e Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Wed, 17 Oct 2018 13:56:01 +0200 Subject: [PATCH 0136/1007] Remove Travis check in depends toolchain file The architecture for darwin is now detected correctly, remove the override for it. --- .travis.yml | 2 +- contrib/depends/toolchain.cmake.in | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a9b9b94b..ca3a24ae8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,7 +58,7 @@ script: - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi - - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake -DTRAVIS=true .. && make $MAKEJOBS" + - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS" - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib after_script: - echo $TRAVIS_COMMIT_RANGE diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index 66168facb..f59b7b5ee 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -51,9 +51,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") SET(APPLE True) SET(BUILD_TAG "mac-x64") SET(BUILD_64 ON) - if(NOT TRAVIS) - SET(ARCH "x86_64") - endif() SET(BREW OFF) SET(PORT OFF) SET(CMAKE_OSX_SYSROOT "@sdk@/MacOSX10.11.sdk/") From 8f96c718bc5b3844904b04868d5605778af41c39 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Thu, 11 Oct 2018 02:05:00 +0200 Subject: [PATCH 0137/1007] Adapt Readme and script to monero gitian build signing The sigs should be produced in a seperate step by default. Remove windows and osx sig options that are not needed for monero. --- contrib/gitian/README.md | 78 ++++++++++++++------------------- contrib/gitian/gitian-build.py | 36 +++------------ contrib/gitian/gitian-linux.yml | 2 +- contrib/gitian/gitian-osx.yml | 2 +- contrib/gitian/gitian-win.yml | 2 +- 5 files changed, 43 insertions(+), 77 deletions(-) diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md index 1f7d158eb..4bd326f22 100644 --- a/contrib/gitian/README.md +++ b/contrib/gitian/README.md @@ -3,8 +3,8 @@ Gitian building *Setup instructions for a Gitian build of Monero using a VM or physical system.* -Gitian is the deterministic build process that is used to build the Bitcoin -Core executables. It provides a way to be reasonably sure that the +Gitian is the deterministic build process that is used to build the Monero CLI +executables. It provides a way to be reasonably sure that the executables are really built from the git source. It also makes sure that the same, tested dependencies are used and statically built into the executable. @@ -22,8 +22,7 @@ Table of Contents Please note that these instructions have been forked from bitcoin's gitian build instructions. Please also consult their documentation, when running into problems. -The signing is left as inherited from bitcoin at the moment, since building currently -still fails with libiconv. +The signing is left as inherited from bitcoin at the moment. - [Preparing the Gitian builder host](#preparing-the-gitian-builder-host) - [Getting and building the inputs](#getting-and-building-the-inputs) @@ -37,9 +36,10 @@ Preparing the Gitian builder host The first step is to prepare the host environment that will be used to perform the Gitian builds. This guide explains how to set up the environment, and how to start the builds. -Gitian builds are for now executed on Ubuntu 18.04 "Bionic Beaver". Please run Ubuntu in either a VM, or on your physical machine. +Gitian builds are for now executed on Ubuntu 18.04 "Bionic Beaver". A solution is being worked on to run +it in docker in the future. Please run Ubuntu in either a VM, or on your physical machine. You need to be logged in as the `gitianuser` in order to build gitian builds. If this user does not exist yet on your system, -create him. +create it. Note that a version of `lxc-execute` higher or equal to 2.1.1 is required. You can check the version with `lxc-execute --version`. @@ -79,11 +79,8 @@ This setup is required to enable networking in the container. Manual and Building ------------------- -The instructions below use the automated script [gitian-build.py](https://github.com/betcoin/bitcoin/blob/master/contrib/gitian-build.py) which only works in Ubuntu. For manual steps and instructions for fully offline signing, see [this guide](./gitian-building/gitian-building-manual.md). - -MacOS code signing ------------------- -In order to sign builds for MacOS, you need to download the free SDK and extract a file. The steps are described [here](./gitian-building/gitian-building-mac-os-sdk.md). Alternatively, you can skip the OSX build by adding `--os=lw` below. +The instructions below use the automated script [gitian-build.py](https://github.com/betcoin/bitcoin/blob/master/contrib/gitian-build.py) which only works in Ubuntu. +It calls all available descriptors. Help for the build steps taken can be accessed with `./gitian-build.py --help`. Initial Gitian Setup -------------------- @@ -93,66 +90,57 @@ The `gitian-build.py` script will checkout different release tags, so it's best cp monero/contrib/gitian/gitian-build.py . ``` -You only need to do this once: +Setup the required environment, you only need to do this once: ``` -./gitian-build.py --setup fluffypony 0.0.20 +./gitian-build.py --setup fluffypony 0.14.0 ``` -Where `fluffypony` is your Github name and `0.0.20` is the most recent tag (without `v`). +Where `fluffypony` is your Github name and `0.14.0` is the version tag you want to build (without `v`). -In order to sign gitian builds on your host machine, which has your PGP key, fork the gitian.sigs repository and clone it on your host machine: +While gitian and this build script does provide a way for you to sign the build directly, it is recommended to sign in a seperate step. +This script is only there for convenience. Seperate steps for building can still be taken. +In order to sign gitian builds on your host machine, which has your PGP key, +fork the gitian.sigs repository and clone it on your host machine, +or pass the signed assert file back to your build machine. ``` -git clone git@github.com:bitcoin-core/gitian.sigs.git -git remote add satoshi git@github.com:satoshi/gitian.sigs.git +git clone git@github.com:monero-project/gitian.sigs.git +git remote add fluffypony git@github.com:fluffypony/gitian.sigs.git ``` Build Binaries ----------------------------- -Windows and OSX have code signed binaries, but those won't be available until a few developers have gitian signed the non-codesigned binaries. - To build the most recent tag: - `./gitian-build.py --detach-sign --no-commit -b fluffypony 0.0.20` + `./gitian-build.py --detach-sign --no-commit -b fluffypony 0.14.0` To speed up the build, use `-j 5 -m 5000` as the first arguments, where `5` is the number of CPU's you allocated to the VM plus one, and 5000 is a little bit less than then the MB's of RAM you allocated. If there is memory corruption on your machine, try to tweak these values. If all went well, this produces a number of (uncommited) `.assert` files in the gitian.sigs repository. -You need to copy these uncommited changes to your host machine, where you can sign them: +If you do detached, offline signing, you need to copy these uncommited changes to your host machine, where you can sign them. For example: ``` -export NAME=satoshi -gpg --output $VERSION-linux/$NAME/bitcoin-linux-0.16-build.assert.sig --detach-sign 0.16.0rc1-linux/$NAME/bitcoin-linux-0.16-build.assert -gpg --output $VERSION-osx-unsigned/$NAME/bitcoin-osx-0.16-build.assert.sig --detach-sign 0.16.0rc1-osx-unsigned/$NAME/bitcoin-osx-0.16-build.assert -gpg --output $VERSION-win-unsigned/$NAME/bitcoin-win-0.16-build.assert.sig --detach-sign 0.16.0rc1-win-unsigned/$NAME/bitcoin-win-0.16-build.assert +export NAME=fluffypony +export VERSION=0.14 +gpg --output $VERSION-linux/$NAME/monero-linux-$VERSION-build.assert.sig --detach-sign $VERSION-linux/$NAME/monero-linux-$VERSION-build.assert +gpg --output $VERSION-osx-unsigned/$NAME/monero-osx-$VERSION-build.assert.sig --detach-sign $VERSION-osx-unsigned/$NAME/monero-osx-$VERSION-build.assert +gpg --output $VERSION-win-unsigned/$NAME/monero-win-$VERSION-build.assert.sig --detach-sign $VERSION-win-unsigned/$NAME/monero-win-$VERSION-build.assert ``` -Make a PR (both the `.assert` and `.assert.sig` files) to the -[bitcoin-core/gitian.sigs](https://github.com/bitcoin-core/gitian.sigs/) repository: +Make a pull request (both the `.assert` and `.assert.sig` files) to the +[monero-project/gitian.sigs](https://github.com/monero-project/gitian.sigs/) repository: ``` -git checkout -b 0.0.20-not-codesigned -git commit -S -a -m "Add $NAME 0.0.20 non-code signed signatures" -git push --set-upstream $NAME 0.0.20 +git checkout -b 0.14.0 +git commit -S -a -m "Add $NAME 0.14.0" +git push --set-upstream $NAME 0.14.0 ``` -You can also mail the files to Wladimir (laanwj@gmail.com) and he will commit them. - ```bash - gpg --detach-sign ${VERSION}-linux/${SIGNER}/bitcoin-linux-*-build.assert - gpg --detach-sign ${VERSION}-win-unsigned/${SIGNER}/bitcoin-win-*-build.assert - gpg --detach-sign ${VERSION}-osx-unsigned/${SIGNER}/bitcoin-osx-*-build.assert + gpg --detach-sign ${VERSION}-linux/${SIGNER}/monero-linux-*-build.assert + gpg --detach-sign ${VERSION}-win-unsigned/${SIGNER}/monero-win-*-build.assert + gpg --detach-sign ${VERSION}-osx-unsigned/${SIGNER}/monero-osx-*-build.assert ``` -You may have other .assert files as well (e.g. `signed` ones), in which case you should sign them too. You can see all of them by doing `ls ${VERSION}-*/${SIGNER}`. - -This will create the `.sig` files that can be committed together with the `.assert` files to assert your -Gitian build. - - - `./gitian-build.py --detach-sign -s satoshi 0.16.0rc1 --nocommit` - -Make another pull request for these. - diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index eb138e41a..99c64e9dd 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -65,13 +65,13 @@ def build(): if args.windows: print('\nCompiling ' + args.version + ' Windows') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, '../monero/contrib/gitian/gitian-win.yml']) - subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-win.yml']) subprocess.check_call('mv build/out/monero*.zip ../monero-binaries/'+args.version, shell=True) if args.macos: print('\nCompiling ' + args.version + ' MacOS') subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero'+args.url, '../monero/contrib/gitian/gitian-osx.yml']) - subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx.yml']) + subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx', '--destination', '../gitian.sigs/', '../monero/contrib/gitian/gitian-osx.yml']) subprocess.check_call('mv build/out/monero*.tar.gz ../monero-binaries/'+args.version, shell=True) os.chdir(workdir) @@ -80,24 +80,11 @@ def build(): print('\nCommitting '+args.version+' Unsigned Sigs\n') os.chdir('gitian.sigs') subprocess.check_call(['git', 'add', args.version+'-linux/'+args.signer]) - subprocess.check_call(['git', 'add', args.version+'-win-unsigned/'+args.signer]) - subprocess.check_call(['git', 'add', args.version+'-osx-unsigned/'+args.signer]) + subprocess.check_call(['git', 'add', args.version+'-win/'+args.signer]) + subprocess.check_call(['git', 'add', args.version+'-osx/'+args.signer]) subprocess.check_call(['git', 'commit', '-m', 'Add '+args.version+' unsigned sigs for '+args.signer]) os.chdir(workdir) -def sign(): - global args, workdir - os.chdir('gitian-builder') - os.chdir(workdir) - - if args.commit_files: - print('\nCommitting '+args.version+' Signed Sigs\n') - os.chdir('gitian.sigs') - subprocess.check_call(['git', 'add', args.version+'-win-signed/'+args.signer]) - subprocess.check_call(['git', 'add', args.version+'-osx-signed/'+args.signer]) - subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' signed binary sigs for '+args.signer]) - os.chdir(workdir) - def verify(): global args, workdir os.chdir('gitian-builder') @@ -105,14 +92,9 @@ def verify(): print('\nVerifying v'+args.version+' Linux\n') subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-linux', '../monero/contrib/gitian/gitian-linux.yml']) print('\nVerifying v'+args.version+' Windows\n') - subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-unsigned', '../monero/contrib/gitian/gitian-win.yml']) + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win', '../monero/contrib/gitian/gitian-win.yml']) print('\nVerifying v'+args.version+' MacOS\n') - subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-unsigned', '../monero/contrib/gitian/gitian-osx.yml']) - print('\nVerifying v'+args.version+' Signed Windows\n') - subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-signed', '../monero/contrib/gitian/gitian-win-signer.yml']) - print('\nVerifying v'+args.version+' Signed MacOS\n') - subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-signed', '../monero/contrib/gitian/gitian-osx-signer.yml']) - + subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx', '../monero/contrib/gitian/gitian-osx.yml']) os.chdir(workdir) def main(): @@ -124,7 +106,6 @@ def main(): parser.add_argument('-u', '--url', dest='url', default='https://github.com/monero-project/monero', help='Specify the URL of the repository. Default is %(default)s') parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') - parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS') parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries') parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS') parser.add_argument('-j', '--jobs', dest='jobs', default='2', help='Number of processes to use. Default %(default)s') @@ -184,7 +165,7 @@ def main(): # Add leading 'v' for tags if args.commit and args.pull: raise Exception('Cannot have both commit and pull') - args.commit = ('' if args.commit else 'v') + args.version + args.commit = ('' if args.commit else) + args.version if args.setup: setup() @@ -204,9 +185,6 @@ def main(): if args.build: build() - if args.sign: - sign() - if args.verify: verify() diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index 6c338f1da..473a7720d 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "monero-linux-0.18" +name: "monero-linux-0.14" enable_cache: true suites: - "bionic" diff --git a/contrib/gitian/gitian-osx.yml b/contrib/gitian/gitian-osx.yml index d9ebf95d3..a6fcff0da 100644 --- a/contrib/gitian/gitian-osx.yml +++ b/contrib/gitian/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-osx-0.18" +name: "monero-osx-0.14" enable_cache: true suites: - "bionic" diff --git a/contrib/gitian/gitian-win.yml b/contrib/gitian/gitian-win.yml index 74c757c11..fef5567f9 100644 --- a/contrib/gitian/gitian-win.yml +++ b/contrib/gitian/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-win-0.18" +name: "monero-win-0.14" enable_cache: true suites: - "bionic" From 25d327e796e60b2dceab4aeab26fbc4edf7a5537 Mon Sep 17 00:00:00 2001 From: xiphon Date: Thu, 18 Oct 2018 03:33:42 +0000 Subject: [PATCH 0138/1007] device: extended logging, refactored device selection code --- src/device/device_io_hid.cpp | 56 +++++++++++++++++++++++++++--------- src/device/device_io_hid.hpp | 8 ++---- src/device/device_ledger.cpp | 2 +- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 0296914e1..666255cb3 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -13,6 +13,7 @@ // #if defined(HAVE_HIDAPI) +#include #include "log.hpp" #include "device_io_hid.hpp" @@ -69,11 +70,47 @@ namespace hw { void device_io_hid::connect(void *params) { hid_conn_params *p = (struct hid_conn_params*)params; - this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page); + this->connect(p->vid, p->pid, p->interface_number, p->usage_page); } - void device_io_hid::connect(unsigned int vid, unsigned int pid, int interface_number, unsigned short usage_page, bool interface_OR_page ) { - hid_device_info *hwdev_info, *hwdev_info_list; + hid_device_info *device_io_hid::find_device(hid_device_info *devices_list, boost::optional interface_number, boost::optional usage_page) { + bool select_any = !interface_number && !usage_page; + + MDEBUG( "Looking for " << + (select_any ? "any HID Device" : "HID Device with") << + (interface_number ? (" interface_number " + std::to_string(interface_number.value())) : "") << + ((interface_number && usage_page) ? " or" : "") << + (usage_page ? (" usage_page " + std::to_string(usage_page.value())) : "")); + + hid_device_info *result = nullptr; + for (; devices_list != nullptr; devices_list = devices_list->next) { + BOOST_SCOPE_EXIT(&devices_list, &result) { + MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") << + " HID Device" << + " path " << safe_hid_path(devices_list) << + " interface_number " << devices_list->interface_number << + " usage_page " << devices_list->usage_page); + } + BOOST_SCOPE_EXIT_END + + if (result != nullptr) { + continue; + } + + if (select_any) { + result = devices_list; + } else if (interface_number && devices_list->interface_number == interface_number.value()) { + result = devices_list; + } else if (usage_page && devices_list->usage_page == usage_page.value()) { + result = devices_list; + } + } + + return result; + } + + void device_io_hid::connect(unsigned int vid, unsigned int pid, boost::optional interface_number, boost::optional usage_page) { + hid_device_info *hwdev_info_list; hid_device *hwdev; this->disconnect(); @@ -81,17 +118,8 @@ namespace hw { hwdev_info_list = hid_enumerate(vid, pid); ASSERT_X(hwdev_info_list, "Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device)); hwdev = NULL; - hwdev_info = hwdev_info_list; - while (hwdev_info) { - if ((interface_OR_page && ((hwdev_info->usage_page == usage_page) || (hwdev_info->interface_number == interface_number))) || - ((hwdev_info->usage_page == usage_page) && (hwdev_info->interface_number == interface_number))) { - MDEBUG("HID Device found: " << safe_hid_path(hwdev_info)); - hwdev = hid_open_path(hwdev_info->path); - break; - } else { - MDEBUG("HID Device discard: " << safe_hid_path(hwdev_info) << "("+std::to_string(hwdev_info->usage_page) << "," << std::to_string(hwdev_info->interface_number) << ")"); - } - hwdev_info = hwdev_info->next; + if (hid_device_info *device = find_device(hwdev_info_list, interface_number, usage_page)) { + hwdev = hid_open_path(device->path); } hid_free_enumeration(hwdev_info_list); ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp index ffd3f534f..bb0f0a814 100644 --- a/src/device/device_io_hid.hpp +++ b/src/device/device_io_hid.hpp @@ -29,6 +29,7 @@ #if defined(HAVE_HIDAPI) +#include #include #include "device_io.hpp" @@ -54,7 +55,6 @@ namespace hw { unsigned int pid; int interface_number; unsigned short usage_page; - bool interface_OR_page ; }; @@ -82,13 +82,11 @@ namespace hw { unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len); unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len); + hid_device_info *find_device(hid_device_info *devices_list, boost::optional interface_number, boost::optional usage_page); public: bool hid_verbose = false; - static const unsigned int OR_SELECT = 1; - static const unsigned int AND_SELECT = 2; - static const unsigned short DEFAULT_CHANNEL = 0x0001; static const unsigned char DEFAULT_TAG = 0x01; static const unsigned int DEFAULT_PACKET_SIZE = 64; @@ -100,7 +98,7 @@ namespace hw { void init(); void connect(void *params); - void connect(unsigned int vid, unsigned int pid, int interface_number, unsigned short usage_page, bool interface_OR_page ); + void connect(unsigned int vid, unsigned int pid, boost::optional interface_number, boost::optional usage_page); bool connected() const; int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len); void disconnect(); diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index a17784960..d879ee95a 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -340,7 +340,7 @@ namespace hw { bool device_ledger::connect(void) { this->disconnect(); - hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT); + hw_device.connect(0x2c97, 0x0001, 0, 0xffa0); this->reset(); #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; From 99cd6f961a15d5a16668be44c200b5f78024e618 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 18 Oct 2018 18:05:51 +0000 Subject: [PATCH 0139/1007] Rename "blackball" for clarity Apparently some people seem to think it's a censorship list... --- src/blockchain_utilities/CMakeLists.txt | 2 +- .../blockchain_blackball.cpp | 24 ++++++------- src/simplewallet/simplewallet.cpp | 34 +++++++++---------- src/wallet/api/wallet.cpp | 6 ++-- src/wallet/ringdb.cpp | 4 +-- src/wallet/wallet2.cpp | 2 +- tests/unit_tests/ringdb.cpp | 10 +++--- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index ecd7b754c..24a750eb0 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -184,7 +184,7 @@ target_link_libraries(blockchain_blackball set_property(TARGET blockchain_blackball PROPERTY - OUTPUT_NAME "monero-blockchain-blackball") + OUTPUT_NAME "monero-blockchain-mark-spent-outputs") install(TARGETS blockchain_blackball DESTINATION bin) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 03ff3cdcd..d2ce5cf76 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -226,7 +226,7 @@ static void init(std::string cache_filename) bool tx_active = false; int dbr; - MINFO("Creating blackball cache in " << cache_filename); + MINFO("Creating spent output cache in " << cache_filename); tools::create_directories_if_necessary(cache_filename); @@ -1019,7 +1019,7 @@ int main(int argc, char* argv[]) po::options_description desc_cmd_only("Command line options"); po::options_description desc_cmd_sett("Command line options and settings options"); const command_line::arg_descriptor arg_blackball_db_dir = { - "blackball-db-dir", "Specify blackball database directory", + "spent-output-db-dir", "Specify spent output database directory", get_default_db_path(), }; const command_line::arg_descriptor arg_log_level = {"log-level", "0-4 or categories", ""}; @@ -1076,7 +1076,7 @@ int main(int argc, char* argv[]) return 1; } - mlog_configure(mlog_get_default_log_path("monero-blockchain-blackball.log"), true); + mlog_configure(mlog_get_default_log_path("monero-blockchain-find-spent-outputs.log"), true); if (!command_line::is_arg_defaulted(vm, arg_log_level)) mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); else @@ -1114,10 +1114,10 @@ int main(int argc, char* argv[]) return 1; } - const std::string cache_dir = (output_file_path / "blackball-cache").string(); + const std::string cache_dir = (output_file_path / "spent-outputs-cache").string(); init(cache_dir); - LOG_PRINT_L0("Scanning for blackballable outputs..."); + LOG_PRINT_L0("Scanning for spent outputs..."); size_t done = 0; @@ -1215,7 +1215,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a 1-ring"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a 1-ring"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1229,7 +1229,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1244,7 +1244,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, absolute[o]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1280,7 +1280,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(txin.amount, common[0]); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in rings with a single common element"); + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in rings with a single common element"); std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; } blackballs.push_back(output); @@ -1392,7 +1392,7 @@ int main(int argc, char* argv[]) const std::pair output = std::make_pair(od.amount, last_unknown); if (opt_verbose) { - MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a " << + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a " << absolute.size() << "-ring where all other outputs are known to be spent"); } blackballs.push_back(output); @@ -1420,7 +1420,7 @@ int main(int argc, char* argv[]) skip_secondary_passes: uint64_t diff = get_num_spent_outputs() - start_blackballed_outputs; - LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs() << " total outputs blackballed"); + LOG_PRINT_L0(std::to_string(diff) << " new outputs marked as spent, " << get_num_spent_outputs() << " total outputs marked as spent"); MDB_txn *txn; dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); @@ -1460,7 +1460,7 @@ int main(int argc, char* argv[]) mdb_txn_abort(txn); } - LOG_PRINT_L0("Blockchain blackball data exported OK"); + LOG_PRINT_L0("Blockchain spent output data exported OK"); close_db(env0, txn0, cur0, dbi0); close(); return 0; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 47b77abc6..18b596662 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1640,7 +1640,7 @@ bool simple_wallet::blackball(const std::vector &args) uint64_t amount = std::numeric_limits::max(), offset, num_offsets; if (args.size() == 0) { - fail_msg_writer() << tr("usage: blackball / | [add]"); + fail_msg_writer() << tr("usage: mark_output_spent / | [add]"); return true; } @@ -1718,7 +1718,7 @@ bool simple_wallet::blackball(const std::vector &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to blackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output spent: ") << e.what(); } return true; @@ -1729,7 +1729,7 @@ bool simple_wallet::unblackball(const std::vector &args) std::pair output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: unblackball /"); + fail_msg_writer() << tr("usage: mark_output_unspent /"); return true; } @@ -1745,7 +1745,7 @@ bool simple_wallet::unblackball(const std::vector &args) } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to mark output unspent: ") << e.what(); } return true; @@ -1756,7 +1756,7 @@ bool simple_wallet::blackballed(const std::vector &args) std::pair output; if (args.size() != 1) { - fail_msg_writer() << tr("usage: blackballed /"); + fail_msg_writer() << tr("usage: is_output_spent /"); return true; } @@ -1769,13 +1769,13 @@ bool simple_wallet::blackballed(const std::vector &args) try { if (m_wallet->is_output_blackballed(output)) - message_writer() << tr("Blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Spent: ") << output.first << "/" << output.second; else - message_writer() << tr("not blackballed: ") << output.first << "/" << output.second; + message_writer() << tr("Not spent: ") << output.first << "/" << output.second; } catch (const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + fail_msg_writer() << tr("Failed to check whether output is spent: ") << e.what(); } return true; @@ -2599,18 +2599,18 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::save_known_rings, this, _1), tr("save_known_rings"), tr("Save known rings to the shared rings database")); - m_cmd_binder.set_handler("blackball", + m_cmd_binder.set_handler("mark_output_spent", boost::bind(&simple_wallet::blackball, this, _1), - tr("blackball / | [add]"), - tr("Blackball output(s) so they never get selected as fake outputs in a ring")); - m_cmd_binder.set_handler("unblackball", + tr("mark_output_spent / | [add]"), + tr("Mark output(s) as spent so they never get selected as fake outputs in a ring")); + m_cmd_binder.set_handler("mark_output_unspent", boost::bind(&simple_wallet::unblackball, this, _1), - tr("unblackball /"), - tr("Unblackballs an output so it may get selected as a fake output in a ring")); - m_cmd_binder.set_handler("blackballed", + tr("mark_output_unspent /"), + tr("Marks an output as unspent so it may get selected as a fake output in a ring")); + m_cmd_binder.set_handler("is_output_spent", boost::bind(&simple_wallet::blackballed, this, _1), - tr("blackballed /"), - tr("Checks whether an output is blackballed")); + tr("is_output_spent /"), + tr("Checks whether an output is marked as spent")); m_cmd_binder.set_handler("version", boost::bind(&simple_wallet::version, this, _1), tr("version"), diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index bb1ba83ca..1b4370c36 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2161,7 +2161,7 @@ bool WalletImpl::blackballOutputs(const std::vector &outputs, bool bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add); if (!ret) { - setStatusError(tr("Failed to set blackballed outputs")); + setStatusError(tr("Failed to mark outputs as spent")); return false; } return true; @@ -2183,7 +2183,7 @@ bool WalletImpl::blackballOutput(const std::string &amount, const std::string &o bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to blackball output")); + setStatusError(tr("Failed to mark output as spent")); return false; } return true; @@ -2205,7 +2205,7 @@ bool WalletImpl::unblackballOutput(const std::string &amount, const std::string bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset)); if (!ret) { - setStatusError(tr("Failed to unblackball output")); + setStatusError(tr("Failed to mark output as unspent")); return false; } return true; diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index e5995e7fb..f562d6c06 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -412,13 +412,13 @@ bool ringdb::blackball_worker(const std::vector> & switch (op) { case BLACKBALL_BLACKBALL: - MDEBUG("Blackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as spent"); dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP); if (dbr == MDB_KEYEXIST) dbr = 0; break; case BLACKBALL_UNBLACKBALL: - MDEBUG("Unblackballing output " << output.first << "/" << output.second); + MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent"); dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH); if (dbr == 0) dbr = mdb_cursor_del(cursor, 0); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index d774c54c0..893642af7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6980,7 +6980,7 @@ void wallet2::get_outs(std::vector> // outputs, we still need to reach the minimum ring size) if (allow_blackballed) break; - MINFO("Not enough non blackballed outputs, we'll allow blackballed ones"); + MINFO("Not enough output not marked as spent, we'll allow outputs marked as spent"); allow_blackballed = true; num_usable_outs = num_outs; } diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp index 0d92049ac..ab634ea82 100644 --- a/tests/unit_tests/ringdb.cpp +++ b/tests/unit_tests/ringdb.cpp @@ -136,21 +136,21 @@ TEST(ringdb, different_genesis) ASSERT_FALSE(ringdb.get_ring(KEY_2, KEY_IMAGE_1, outs2)); } -TEST(blackball, not_found) +TEST(spent_outputs, not_found) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); ASSERT_FALSE(ringdb.blackballed(OUTPUT_2)); } -TEST(blackball, found) +TEST(spent_outputs, found) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); ASSERT_TRUE(ringdb.blackballed(OUTPUT_1)); } -TEST(blackball, vector) +TEST(spent_outputs, vector) { RingDB ringdb; std::vector> outputs; @@ -174,7 +174,7 @@ TEST(blackball, vector) ASSERT_TRUE(ringdb.blackballed(std::make_pair(30, 5))); } -TEST(blackball, unblackball) +TEST(spent_outputs, mark_as_unspent) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); @@ -182,7 +182,7 @@ TEST(blackball, unblackball) ASSERT_FALSE(ringdb.blackballed(OUTPUT_1)); } -TEST(blackball, clear) +TEST(spent_outputs, clear) { RingDB ringdb; ASSERT_TRUE(ringdb.blackball(OUTPUT_1)); From ade369f96fd0decbce1489f12d50d741f7c1b5a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sa=C5=82aban?= Date: Thu, 18 Oct 2018 23:14:06 +0200 Subject: [PATCH 0140/1007] Add RPC error code for non-deterministic wallet --- src/wallet/wallet_rpc_server.cpp | 1 + src/wallet/wallet_rpc_server_error_codes.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 1b63d65b6..8baa2251e 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1577,6 +1577,7 @@ namespace tools epee::wipeable_string seed; if (!m_wallet->get_seed(seed)) { + er.code = WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC; er.message = "The wallet is non-deterministic. Cannot display seed."; return false; } diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index f127ae240..9b3a2847d 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_rpc_server_error_codes.h @@ -73,3 +73,4 @@ #define WALLET_RPC_ERROR_CODE_BAD_SIGNED_TX_DATA -40 #define WALLET_RPC_ERROR_CODE_SIGNED_SUBMISSION -41 #define WALLET_RPC_ERROR_CODE_SIGN_UNSIGNED -42 +#define WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC -43 From a7bffead9e5c0f1943f1459c9d1ab581b4ab11d6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 18 Oct 2018 13:18:49 +0000 Subject: [PATCH 0141/1007] daemon: fix base fee stating /kB even when it is per byte --- src/daemon/rpc_command_executor.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 6464d372f..fb2cc15f8 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1717,11 +1717,14 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) cryptonote::COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response bhres; cryptonote::COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request fereq; cryptonote::COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response feres; + cryptonote::COMMAND_RPC_HARD_FORK_INFO::request hfreq; + cryptonote::COMMAND_RPC_HARD_FORK_INFO::response hfres; epee::json_rpc::error error_resp; std::string fail_message = "Problem fetching info"; fereq.grace_blocks = 0; + hfreq.version = HF_VERSION_PER_BYTE_FEE; if (m_is_rpc) { if (!m_rpc_client->rpc_request(ireq, ires, "/getinfo", fail_message.c_str())) @@ -1732,6 +1735,10 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) { return true; } + if (!m_rpc_client->json_rpc_request(hfreq, hfres, "hard_fork_info", fail_message.c_str())) + { + return true; + } } else { @@ -1745,10 +1752,15 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) tools::fail_msg_writer() << make_error(fail_message, feres.status); return true; } + if (!m_rpc_server->on_hard_fork_info(hfreq, hfres, error_resp) || hfres.status != CORE_RPC_STATUS_OK) + { + tools::fail_msg_writer() << make_error(fail_message, hfres.status); + return true; + } } tools::msg_writer() << "Height: " << ires.height << ", diff " << ires.difficulty << ", cum. diff " << ires.cumulative_difficulty - << ", target " << ires.target << " sec" << ", dyn fee " << cryptonote::print_money(feres.fee) << "/kB"; + << ", target " << ires.target << " sec" << ", dyn fee " << cryptonote::print_money(feres.fee) << "/" << (hfres.enabled ? "byte" : "kB"); if (nblocks > 0) { From ca9b996dcb03d3516b4e86a9c89f451467ccb9a6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 19 Oct 2018 08:57:28 +0000 Subject: [PATCH 0142/1007] perf_timer: separate log categories based on caller categories Also default to microseconds, for homogeneity Makes it easier to enable what we need --- src/common/perf_timer.cpp | 8 ++++---- src/common/perf_timer.h | 18 ++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index 6910ebdd4..47f01de65 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -104,11 +104,11 @@ PerformanceTimer::PerformanceTimer(bool paused): started(true), paused(paused) ticks = get_tick_count(); } -LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, uint64_t unit, el::Level l): PerformanceTimer(), name(s), unit(unit), level(l) +LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l): PerformanceTimer(), name(s), cat(cat), unit(unit), level(l) { if (!performance_timers) { - MLOG(level, "PERF ----------"); + MCLOG(level, cat.c_str(), "PERF ----------"); performance_timers = new std::vector(); } else @@ -117,7 +117,7 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, uint64_t if (!pt->started && !pt->paused) { size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size; - MLOG(pt->level, "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); + MCLOG(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); pt->started = true; } } @@ -137,7 +137,7 @@ LoggingPerformanceTimer::~LoggingPerformanceTimer() char s[12]; snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit))); size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size; - MLOG(level, "PERF " << s << std::string(size * 2, ' ') << " " << name); + MCLOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); if (performance_timers->empty()) { delete performance_timers; diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index 675d6234d..1d4dee5b5 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -33,9 +33,6 @@ #include #include "misc_log_ex.h" -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "perf" - namespace tools { @@ -67,23 +64,24 @@ void set(uint64_t v){ticks=v;} class LoggingPerformanceTimer: public PerformanceTimer { public: - LoggingPerformanceTimer(const std::string &s, uint64_t unit, el::Level l = el::Level::Debug); + LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Debug); ~LoggingPerformanceTimer(); private: std::string name; + std::string cat; uint64_t unit; el::Level level; }; void set_performance_timer_log_level(el::Level level); -#define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer pt_##name(#name, unit, tools::performance_timer_log_level) -#define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer pt_##name(#name, unit, l) -#define PERF_TIMER(name) PERF_TIMER_UNIT(name, 1000) -#define PERF_TIMER_L(name, l) PERF_TIMER_UNIT_L(name, 1000, l) -#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr pt_##name(new tools::LoggingPerformanceTimer(#name, unit, el::Level::Info)) -#define PERF_TIMER_START(name) PERF_TIMER_START_UNIT(name, 1000) +#define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer pt_##name(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, tools::performance_timer_log_level) +#define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer pt_##name(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, l) +#define PERF_TIMER(name) PERF_TIMER_UNIT(name, 1000000) +#define PERF_TIMER_L(name, l) PERF_TIMER_UNIT_L(name, 1000000, l) +#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr pt_##name(new tools::LoggingPerformanceTimer(#name, "perf." MONERO_DEFAULT_LOG_CATEGORY, unit, el::Level::Info)) +#define PERF_TIMER_START(name) PERF_TIMER_START_UNIT(name, 1000000) #define PERF_TIMER_STOP(name) do { pt_##name.reset(NULL); } while(0) #define PERF_TIMER_PAUSE(name) pt_##name->pause() #define PERF_TIMER_RESUME(name) pt_##name->resume() From b916ca63a8b28a38bd791f0317ec5b5765bb8686 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 19 Oct 2018 09:20:03 +0000 Subject: [PATCH 0143/1007] rpc: fix output distribution caching ignoring chain changes 0 is placeholder for whole chain, so we should compare chain height changes rather than chain-height-or-zero. Even this isn't totally foolproof if a blocks are popped and the same number added again, but it is much better as it prevents the data from slowly going out of sync. --- src/rpc/core_rpc_server.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d8f556d3e..f5ec1194e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -2118,6 +2118,8 @@ namespace cryptonote try { + // 0 is placeholder for the whole chain + const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (uint64_t amount: req.amounts) { static struct D @@ -2130,7 +2132,7 @@ namespace cryptonote } d; boost::unique_lock lock(d.mutex); - if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height) + if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req_to_height) { res.distributions.push_back({amount, d.cached_start_height, req.binary, d.cached_distribution, d.cached_base}); if (!req.cumulative) @@ -2145,23 +2147,23 @@ namespace cryptonote std::vector distribution; uint64_t start_height, base; - if (!m_core.get_output_distribution(amount, req.from_height, req.to_height, start_height, distribution, base)) + if (!m_core.get_output_distribution(amount, req.from_height, req_to_height, start_height, distribution, base)) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Failed to get rct distribution"; return false; } - if (req.to_height > 0 && req.to_height >= req.from_height) + if (req_to_height > 0 && req_to_height >= req.from_height) { uint64_t offset = std::max(req.from_height, start_height); - if (offset <= req.to_height && req.to_height - offset + 1 < distribution.size()) - distribution.resize(req.to_height - offset + 1); + if (offset <= req_to_height && req_to_height - offset + 1 < distribution.size()) + distribution.resize(req_to_height - offset + 1); } if (amount == 0) { d.cached_from = req.from_height; - d.cached_to = req.to_height; + d.cached_to = req_to_height; d.cached_distribution = distribution; d.cached_start_height = start_height; d.cached_base = base; From 61304151b45b8adf14ed1822971ce59dc57b6f5c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 19 Oct 2018 16:46:52 +0000 Subject: [PATCH 0144/1007] db_lmdb: use MDB_MULTIPLE_NEXT where possible for some speedup --- src/blockchain_db/lmdb/db_lmdb.cpp | 32 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index bd91f308a..0afadcd8d 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1980,22 +1980,36 @@ std::vector BlockchainLMDB::get_block_cumulative_rct_outputs(const std MDB_val v; uint64_t prev_height = heights[0]; + uint64_t range_begin = 0, range_end = 0; for (uint64_t height: heights) { - if (height == prev_height + 1) + if (height >= range_begin && height < range_end) { - MDB_val k2; - result = mdb_cursor_get(m_cur_block_info, &k2, &v, MDB_NEXT); + // nohting to do } else { - v.mv_size = sizeof(uint64_t); - v.mv_data = (void*)&height; - result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + if (height == prev_height + 1) + { + MDB_val k2; + result = mdb_cursor_get(m_cur_block_info, &k2, &v, MDB_NEXT_MULTIPLE); + range_begin = ((const mdb_block_info*)v.mv_data)->bi_height; + range_end = range_begin + v.mv_size / sizeof(mdb_block_info); // whole records please + if (height < range_begin || height >= range_end) + throw0(DB_ERROR(("Height " + std::to_string(height) + " not included in multuple record range: " + std::to_string(range_begin) + "-" + std::to_string(range_end)).c_str())); + } + else + { + v.mv_size = sizeof(uint64_t); + v.mv_data = (void*)&height; + result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + range_begin = height; + range_end = range_begin + 1; + } + if (result) + throw0(DB_ERROR(lmdb_error("Error attempting to retrieve rct distribution from the db: ", result).c_str())); } - if (result) - throw0(DB_ERROR(lmdb_error("Error attempting to retrieve rct distribution from the db: ", result).c_str())); - const mdb_block_info *bi = (const mdb_block_info *)v.mv_data; + const mdb_block_info *bi = ((const mdb_block_info *)v.mv_data) + (height - range_begin); res.push_back(bi->bi_cum_rct); prev_height = height; } From cf75ee722a896a0fee2f5c33b2f0dbf051e66ae2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 19 Oct 2018 21:10:19 +0000 Subject: [PATCH 0145/1007] blockchain: move two new verification errors to the verify category Lest we get people get scared again --- src/cryptonote_core/blockchain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index eb869b795..fa23b6bd2 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -2364,7 +2364,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type); if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty()) { - MERROR("Bulletproofs are not allowed before v8"); + MERROR_VER("Bulletproofs are not allowed before v8"); tvc.m_invalid_output = true; return false; } @@ -2377,7 +2377,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context const bool borromean = rct::is_rct_borromean(tx.rct_signatures.type); if (borromean) { - MERROR("Borromean range proofs are not allowed after v8"); + MERROR_VER("Borromean range proofs are not allowed after v8"); tvc.m_invalid_output = true; return false; } From d3cda5ad393098235637d8a5f8fa52cac96358df Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 20 Oct 2018 09:12:55 +0000 Subject: [PATCH 0146/1007] console_handler: add a global log when exiting via EOF It's a common confusion point for users which run monerod without stdin and with --detach --- contrib/epee/include/console_handler.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 2ccf5b095..6e7efd1d7 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -352,8 +352,11 @@ namespace epee std::string command; bool get_line_ret = m_stdin_reader.get_line(command); - if (!m_running || m_stdin_reader.eos()) + if (!m_running) + break; + if (m_stdin_reader.eos()) { + MGINFO("EOF on stdin, exiting"); break; } if (!get_line_ret) From 62f94e1b9d10ba94228bf772b30ac08798b41d95 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 20 Oct 2018 10:29:00 +0000 Subject: [PATCH 0147/1007] device_io_hid.cpp: fix copyright header --- src/device/device_io_hid.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp index 562aca8b8..4dd827738 100644 --- a/src/device/device_io_hid.cpp +++ b/src/device/device_io_hid.cpp @@ -1,3 +1,18 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. // From 7d21c9b5738e8d3cb1b021ce8b5be88ee1e07e85 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 20 Oct 2018 21:36:51 +0000 Subject: [PATCH 0148/1007] CMakeLists.txt: only use libatomic when found --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8baac02e9..a9fd6fd45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -937,7 +937,9 @@ if(ANDROID) endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ARCH_WIDTH EQUAL "32" AND NOT IOS AND NOT FREEBSD) find_library(ATOMIC atomic) - list(APPEND EXTRA_LIBRARIES ${ATOMIC}) + if (ATOMIC_FOUND) + list(APPEND EXTRA_LIBRARIES ${ATOMIC}) + endif() endif() find_path(ZMQ_INCLUDE_PATH zmq.hpp) From 3a85af403dd92263d3715886a3e12c5f84f19d6f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 21 Oct 2018 17:09:21 +0000 Subject: [PATCH 0149/1007] core: fix handle_incoming_tx* comment about return value --- src/cryptonote_core/cryptonote_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 58fe5b7b5..f43d593de 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -117,7 +117,7 @@ namespace cryptonote * @param relayed whether or not the transaction was relayed to us * @param do_not_relay whether to prevent the transaction from being relayed * - * @return true if the transaction made it to the transaction pool, otherwise false + * @return true if the transaction was accepted, false otherwise */ bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay); @@ -133,7 +133,7 @@ namespace cryptonote * @param relayed whether or not the transactions were relayed to us * @param do_not_relay whether to prevent the transactions from being relayed * - * @return true if the transactions made it to the transaction pool, otherwise false + * @return true if the transactions were accepted, false otherwise */ bool handle_incoming_txs(const std::vector& tx_blobs, std::vector& tvc, bool keeped_by_block, bool relayed, bool do_not_relay); From cf646e3afe89fccb6a5f7bded2eae499b8fb19df Mon Sep 17 00:00:00 2001 From: Paul Shapiro Date: Sun, 21 Oct 2018 12:43:31 -0500 Subject: [PATCH 0150/1007] wallet2/create_transactions_2: removed extraneous shuffle before sort of unused_*_indices_per_subaddr --- src/wallet/wallet2.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..04888d035 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8404,12 +8404,8 @@ std::vector wallet2::create_transactions_2(std::vector>& x, const std::pair>& y) { return unlocked_balance_per_subaddr[x.first] > unlocked_balance_per_subaddr[y.first]; From 76681b9bdae63c31fabc83f32390fcab7069ada9 Mon Sep 17 00:00:00 2001 From: Paul Shapiro Date: Sun, 21 Oct 2018 12:44:22 -0500 Subject: [PATCH 0151/1007] wallet2/create_transactions_2: fixed typo in try_tx=true's estimate_fee args --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..0f6911822 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8601,7 +8601,7 @@ std::vector wallet2::create_transactions_2(std::vector Date: Sun, 21 Oct 2018 12:46:13 -0500 Subject: [PATCH 0152/1007] mnemonics/electrum-words/create_checksum_index(): updated to work with non fixed word list length mnemonic --- src/mnemonics/electrum-words.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 3d6338856..496e26858 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -215,7 +215,7 @@ namespace } boost::crc_32_type result; result.process_bytes(trimmed_words.data(), trimmed_words.length()); - return result.checksum() % crypto::ElectrumWords::seed_length; + return result.checksum() % word_list.size(); } /*! From fd62b6e79f87503bf27a3c8709aaf9cc4ae36146 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 9 Oct 2018 12:33:39 +0000 Subject: [PATCH 0153/1007] blocks: use auto-generated .c files instead of 'LD -r -b binary' --- CMakeLists.txt | 5 +- src/blockchain_utilities/CMakeLists.txt | 20 +---- .../blockchain_import.cpp | 8 +- src/blocks/CMakeLists.txt | 35 ++++---- src/blocks/blockexports.c | 87 ------------------- src/blocks/blocks.cpp | 31 +++++++ src/blocks/blocks.dat | 0 src/blocks/blocks.h | 14 ++- src/cryptonote_config.h | 1 + src/cryptonote_core/CMakeLists.txt | 7 -- src/cryptonote_core/blockchain.cpp | 29 +++---- src/cryptonote_core/blockchain.h | 18 +++- src/cryptonote_core/cryptonote_core.cpp | 4 +- src/cryptonote_core/cryptonote_core.h | 3 +- src/daemon/CMakeLists.txt | 21 +---- src/daemon/core.h | 8 +- src/device/CMakeLists.txt | 7 -- 17 files changed, 113 insertions(+), 185 deletions(-) delete mode 100644 src/blocks/blockexports.c create mode 100644 src/blocks/blocks.cpp delete mode 100644 src/blocks/blocks.dat diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bffd29b6..ae1251007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,6 +199,9 @@ set(PER_BLOCK_CHECKPOINT 1) if(PER_BLOCK_CHECKPOINT) add_definitions("-DPER_BLOCK_CHECKPOINT") + set(Blocks "blocks") +else() + set(Blocks "") endif() list(INSERT CMAKE_MODULE_PATH 0 @@ -674,12 +677,10 @@ else() add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED) if (noexecstack_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack") - set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack) endif() add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED) if (noexecheap_SUPPORTED) set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap") - set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap) endif() # some windows linker bits diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index ecd7b754c..873bf552c 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -26,20 +26,6 @@ # 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. -set(blocksdat "") -if(PER_BLOCK_CHECKPOINT) - if(APPLE AND DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(APPLE AND NOT DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(LINUX_32) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - endif() - set(blocksdat "blocksdat.o") -endif() - set(blockchain_import_sources blockchain_import.cpp bootstrap_file.cpp @@ -119,8 +105,7 @@ monero_private_headers(blockchain_depth monero_add_executable(blockchain_import ${blockchain_import_sources} - ${blockchain_import_private_headers} - ${blocksdat}) + ${blockchain_import_private_headers}) target_link_libraries(blockchain_import PRIVATE @@ -132,7 +117,8 @@ target_link_libraries(blockchain_import ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + ${Blocks}) if(ARCH_WIDTH) target_compile_definitions(blockchain_import diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 9ec768d26..7f92ecd87 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -37,6 +37,7 @@ #include "misc_log_ex.h" #include "bootstrap_file.h" #include "bootstrap_serialization.h" +#include "blocks/blocks.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() @@ -758,7 +759,12 @@ int main(int argc, char* argv[]) { core.disable_dns_checkpoints(true); - if (!core.init(vm, NULL)) +#if defined(PER_BLOCK_CHECKPOINT) + const GetCheckpointsCallback& get_checkpoints = blocks::GetCheckpointsData; +#else + const GetCheckpointsCallback& get_checkpoints = nullptr; +#endif + if (!core.init(vm, nullptr, nullptr, get_checkpoints)) { std::cerr << "Failed to initialize core" << ENDL; return 1; diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index ebb5408cc..30d85adbf 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -26,20 +26,23 @@ # 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. -if(APPLE) - add_library(blocks STATIC blockexports.c) - set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) -else() - if(LINUX_32) - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) - else() - add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat) - add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat) - add_custom_command(OUTPUT stagenet_blocks.o MAIN_DEPENDENCY stagenet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/stagenet_blocks.o stagenet_blocks.dat) - endif() - add_library(blocks STATIC blocks.o testnet_blocks.o stagenet_blocks.o blockexports.c) - set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C) -endif() +set(GENERATED_SOURCES "") +foreach(BLOB_NAME checkpoints testnet_blocks stagenet_blocks) + set(OUTPUT_C_SOURCE "generated_${BLOB_NAME}.c") + list(APPEND GENERATED_SOURCES ${OUTPUT_C_SOURCE}) + set(INPUT_DAT_FILE "${BLOB_NAME}.dat") + add_custom_command( + OUTPUT ${OUTPUT_C_SOURCE} + MAIN_DEPENDENCY ${INPUT_DAT_FILE} + COMMAND + cd ${CMAKE_CURRENT_BINARY_DIR} && + echo "'#include\t'" > ${OUTPUT_C_SOURCE} && + echo "'const\tunsigned\tchar\t${BLOB_NAME}[]={'" >> ${OUTPUT_C_SOURCE} && + od -v -An -tu1 ${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_DAT_FILE} | sed -e "'s/[0-9]\\{1,\\}/&,/g'" -e "'$$s/.$$//'" >> ${OUTPUT_C_SOURCE} && + echo "'};'" >> ${OUTPUT_C_SOURCE} && + echo "'const\tsize_t\t${BLOB_NAME}_len\t=\tsizeof(${BLOB_NAME});'" >> ${OUTPUT_C_SOURCE} + ) +endforeach() + +add_library(blocks STATIC blocks.cpp ${GENERATED_SOURCES}) diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c deleted file mode 100644 index 0154b0413..000000000 --- a/src/blocks/blockexports.c +++ /dev/null @@ -1,87 +0,0 @@ -#include - -#if defined(__APPLE__) -#include -#ifdef BUILD_SHARED_LIBS -#if !defined(__LP64__) -const struct mach_header _mh_execute_header; -#else -const struct mach_header_64 _mh_execute_header; -#endif -#else -#if !defined(__LP64__) -extern const struct mach_header _mh_execute_header; -#else -extern const struct mach_header_64 _mh_execute_header; -#endif -#endif - -const unsigned char *get_blocks_dat_start(int testnet, int stagenet) -{ - size_t size; - if (testnet) - return getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); - else if (stagenet) - return getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); - else - return getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); -} - -size_t get_blocks_dat_size(int testnet, int stagenet) -{ - size_t size; - if (testnet) - getsectiondata(&_mh_execute_header, "__DATA", "__testnet_blocks_dat", &size); - else if (stagenet) - getsectiondata(&_mh_execute_header, "__DATA", "__stagenet_blocks_dat", &size); - else - getsectiondata(&_mh_execute_header, "__DATA", "__blocks_dat", &size); - return size; -} - -#else - -#if defined(_WIN32) && !defined(_WIN64) -#define _binary_blocks_start binary_blocks_dat_start -#define _binary_blocks_end binary_blocks_dat_end -#define _binary_testnet_blocks_start binary_testnet_blocks_dat_start -#define _binary_testnet_blocks_end binary_testnet_blocks_dat_end -#define _binary_stagenet_blocks_start binary_stagenet_blocks_dat_start -#define _binary_stagenet_blocks_end binary_stagenet_blocks_dat_end -#else -#define _binary_blocks_start _binary_blocks_dat_start -#define _binary_blocks_end _binary_blocks_dat_end -#define _binary_testnet_blocks_start _binary_testnet_blocks_dat_start -#define _binary_testnet_blocks_end _binary_testnet_blocks_dat_end -#define _binary_stagenet_blocks_start _binary_stagenet_blocks_dat_start -#define _binary_stagenet_blocks_end _binary_stagenet_blocks_dat_end -#endif - -extern const unsigned char _binary_blocks_start[]; -extern const unsigned char _binary_blocks_end[]; -extern const unsigned char _binary_testnet_blocks_start[]; -extern const unsigned char _binary_testnet_blocks_end[]; -extern const unsigned char _binary_stagenet_blocks_start[]; -extern const unsigned char _binary_stagenet_blocks_end[]; - -const unsigned char *get_blocks_dat_start(int testnet, int stagenet) -{ - if (testnet) - return _binary_testnet_blocks_start; - else if (stagenet) - return _binary_stagenet_blocks_start; - else - return _binary_blocks_start; -} - -size_t get_blocks_dat_size(int testnet, int stagenet) -{ - if (testnet) - return (size_t) (_binary_testnet_blocks_end - _binary_testnet_blocks_start); - else if (stagenet) - return (size_t) (_binary_stagenet_blocks_end - _binary_stagenet_blocks_start); - else - return (size_t) (_binary_blocks_end - _binary_blocks_start); -} - -#endif diff --git a/src/blocks/blocks.cpp b/src/blocks/blocks.cpp new file mode 100644 index 000000000..0661f8448 --- /dev/null +++ b/src/blocks/blocks.cpp @@ -0,0 +1,31 @@ +#include "blocks.h" + +#include + +extern const unsigned char checkpoints[]; +extern const size_t checkpoints_len; +extern const unsigned char stagenet_blocks[]; +extern const size_t stagenet_blocks_len; +extern const unsigned char testnet_blocks[]; +extern const size_t testnet_blocks_len; + +namespace blocks +{ + + const std::unordered_map, std::hash> CheckpointsByNetwork = { + {cryptonote::network_type::MAINNET, {checkpoints, checkpoints_len}}, + {cryptonote::network_type::STAGENET, {stagenet_blocks, stagenet_blocks_len}}, + {cryptonote::network_type::TESTNET, {testnet_blocks, testnet_blocks_len}} + }; + + const epee::span GetCheckpointsData(cryptonote::network_type network) + { + const auto it = CheckpointsByNetwork.find(network); + if (it != CheckpointsByNetwork.end()) + { + return it->second; + } + return nullptr; + } + +} diff --git a/src/blocks/blocks.dat b/src/blocks/blocks.dat deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/blocks/blocks.h b/src/blocks/blocks.h index ec683f47e..14e391319 100644 --- a/src/blocks/blocks.h +++ b/src/blocks/blocks.h @@ -1,16 +1,12 @@ #ifndef SRC_BLOCKS_BLOCKS_H_ #define SRC_BLOCKS_BLOCKS_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include "cryptonote_config.h" +#include "span.h" -const unsigned char *get_blocks_dat_start(int testnet, int stagenet); -size_t get_blocks_dat_size(int testnet, int stagenet); - -#ifdef __cplusplus +namespace blocks +{ + const epee::span GetCheckpointsData(cryptonote::network_type network); } -#endif - #endif /* SRC_BLOCKS_BLOCKS_H_ */ diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index a6858ce7c..c62eeb738 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -30,6 +30,7 @@ #pragma once +#include #include #include diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 72844db66..231489fdb 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -41,12 +41,6 @@ set(cryptonote_core_private_headers tx_pool.h cryptonote_tx_utils.h) -if(PER_BLOCK_CHECKPOINT) - set(Blocks "blocks") -else() - set(Blocks "") -endif() - monero_private_headers(cryptonote_core ${cryptonote_core_private_headers}) monero_add_library(cryptonote_core @@ -69,5 +63,4 @@ target_link_libraries(cryptonote_core ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} PRIVATE - ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index eb869b795..955c6c731 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -53,9 +53,6 @@ #include "ringct/rctSigs.h" #include "common/perf_timer.h" #include "common/notify.h" -#if defined(PER_BLOCK_CHECKPOINT) -#include "blocks/blocks.h" -#endif #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "blockchain" @@ -341,7 +338,7 @@ uint64_t Blockchain::get_current_blockchain_height() const //------------------------------------------------------------------ //FIXME: possibly move this into the constructor, to avoid accidentally // dereferencing a null BlockchainDB pointer -bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty) +bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty, const GetCheckpointsCallback& get_checkpoints/* = nullptr*/) { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_tx_pool); @@ -439,7 +436,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline #if defined(PER_BLOCK_CHECKPOINT) if (m_nettype != FAKECHAIN) - load_compiled_in_block_hashes(); + load_compiled_in_block_hashes(get_checkpoints); #endif MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); @@ -4404,19 +4401,21 @@ void Blockchain::cancel() #if defined(PER_BLOCK_CHECKPOINT) static const char expected_block_hashes_hash[] = "954cb2bbfa2fe6f74b2cdd22a1a4c767aea249ad47ad4f7c9445f0f03260f511"; -void Blockchain::load_compiled_in_block_hashes() +void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints) { - const bool testnet = m_nettype == TESTNET; - const bool stagenet = m_nettype == STAGENET; - if (m_fast_sync && get_blocks_dat_start(testnet, stagenet) != nullptr && get_blocks_dat_size(testnet, stagenet) > 0) + if (get_checkpoints == nullptr || !m_fast_sync) { - MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); - + return; + } + const epee::span &checkpoints = get_checkpoints(m_nettype); + if (!checkpoints.empty()) + { + MINFO("Loading precomputed blocks (" << checkpoints.size() << " bytes)"); if (m_nettype == MAINNET) { // first check hash crypto::hash hash; - if (!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) + if (!tools::sha256sum(checkpoints.data(), checkpoints.size(), hash)) { MERROR("Failed to hash precomputed blocks data"); return; @@ -4436,9 +4435,9 @@ void Blockchain::load_compiled_in_block_hashes() } } - if (get_blocks_dat_size(testnet, stagenet) > 4) + if (checkpoints.size() > 4) { - const unsigned char *p = get_blocks_dat_start(testnet, stagenet); + const unsigned char *p = checkpoints.data(); const uint32_t nblocks = *p | ((*(p+1))<<8) | ((*(p+2))<<16) | ((*(p+3))<<24); if (nblocks > (std::numeric_limits::max() - 4) / sizeof(hash)) { @@ -4446,7 +4445,7 @@ void Blockchain::load_compiled_in_block_hashes() return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); - if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && get_blocks_dat_size(testnet, stagenet) >= size_needed) + if(nblocks > 0 && nblocks > (m_db->height() + HASH_OF_HASHES_STEP - 1) / HASH_OF_HASHES_STEP && checkpoints.size() >= size_needed) { p += sizeof(uint32_t); m_blocks_hash_of_hashes.reserve(nblocks); diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index ab66fac8b..5863d9eb1 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -38,9 +38,11 @@ #include #include #include +#include #include #include +#include "span.h" #include "syncobj.h" #include "string_tools.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -73,6 +75,15 @@ namespace cryptonote db_nosync //!< Leave syncing up to the backing db (safest, but slowest because of disk I/O) }; + /** + * @brief Callback routine that returns checkpoints data for specific network type + * + * @param network network type + * + * @return checkpoints data, empty span if there ain't any checkpoints for specific network type + */ + typedef std::function(cryptonote::network_type network)> GetCheckpointsCallback; + /************************************************************************/ /* */ /************************************************************************/ @@ -117,10 +128,11 @@ namespace cryptonote * @param offline true if running offline, else false * @param test_options test parameters * @param fixed_difficulty fixed difficulty for testing purposes; 0 means disabled + * @param get_checkpoints if set, will be called to get checkpoints data * * @return true on success, false if any initialization steps fail */ - bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0); + bool init(BlockchainDB* db, const network_type nettype = MAINNET, bool offline = false, const cryptonote::test_options *test_options = NULL, difficulty_type fixed_difficulty = 0, const GetCheckpointsCallback& get_checkpoints = nullptr); /** * @brief Initialize the Blockchain state @@ -1369,8 +1381,10 @@ namespace cryptonote * A (possibly empty) set of block hashes can be compiled into the * monero daemon binary. This function loads those hashes into * a useful state. + * + * @param get_checkpoints if set, will be called to get checkpoints data */ - void load_compiled_in_block_hashes(); + void load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints); /** * @brief expands v2 transaction data from blockchain diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 69e3c708b..82b45ee76 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -389,7 +389,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options) + bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */) { start_time = std::time(nullptr); @@ -567,7 +567,7 @@ namespace cryptonote regtest_hard_forks }; const difficulty_type fixed_difficulty = command_line::get_arg(vm, arg_fixed_difficulty); - r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty); + r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? ®test_test_options : test_options, fixed_difficulty, get_checkpoints); r = m_mempool.init(max_txpool_weight); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 58fe5b7b5..8ab7d3126 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -244,10 +244,11 @@ namespace cryptonote * @param vm command line parameters * @param config_subdir subdirectory for config storage * @param test_options configuration options for testing + * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL); + bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index f645836a4..117790455 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -26,20 +26,6 @@ # 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. -set(blocksdat "") -if(PER_BLOCK_CHECKPOINT) - if(APPLE AND DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(APPLE AND NOT DEPENDS) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*) - elseif(LINUX_32) - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -m elf_i386 ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - else() - add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat) - endif() - set(blocksdat "blocksdat.o") -endif() - set(daemon_sources command_parser_executor.cpp command_server.cpp @@ -81,9 +67,7 @@ monero_private_headers(daemon monero_add_executable(daemon ${daemon_sources} ${daemon_headers} - ${daemon_private_headers} - ${blocksdat} -) + ${daemon_private_headers}) target_link_libraries(daemon PRIVATE rpc @@ -106,7 +90,8 @@ target_link_libraries(daemon ${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + ${Blocks}) set_property(TARGET daemon PROPERTY OUTPUT_NAME "monerod") diff --git a/src/daemon/core.h b/src/daemon/core.h index 475f418d6..d1defd573 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -28,6 +28,7 @@ #pragma once +#include "blocks/blocks.h" #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "misc_log_ex.h" @@ -85,7 +86,12 @@ class t_core final //initialize core here MGINFO("Initializing core..."); std::string config_subdir = get_config_subdir(); - if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str())) +#if defined(PER_BLOCK_CHECKPOINT) + const cryptonote::GetCheckpointsCallback& get_checkpoints = blocks::GetCheckpointsData; +#else + const cryptonote::GetCheckpointsCallback& get_checkpoints = nullptr; +#endif + if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints)) { return false; } diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 8f446f42a..727134f75 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -58,12 +58,6 @@ endif() set(device_private_headers) -if(PER_BLOCK_CHECKPOINT) - set(Blocks "blocks") -else() - set(Blocks "") -endif() - monero_private_headers(device ${device_private_headers}) @@ -79,5 +73,4 @@ target_link_libraries(device ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} PRIVATE - ${Blocks} ${EXTRA_LIBRARIES}) From e51c978770c25cf866981ff3227e1dcb9d00d2fa Mon Sep 17 00:00:00 2001 From: stoffu Date: Sun, 14 Oct 2018 16:54:07 +0900 Subject: [PATCH 0154/1007] rpc: fix wrongly formatted JSON for pruned tx Fix for #4399. Also unifies code for serializing pruned tx to binary/json into one. --- src/rpc/core_rpc_server.cpp | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 55ee66a79..aa9d3d64b 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -212,23 +212,15 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ - static cryptonote::blobdata get_pruned_tx_blob(cryptonote::transaction &tx) - { - std::stringstream ss; - binary_archive ba(ss); - bool r = tx.serialize_base(ba); - CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); - return ss.str(); - } - //------------------------------------------------------------------------------------------------------------------------------ - static cryptonote::blobdata get_pruned_tx_json(cryptonote::transaction &tx) - { - std::stringstream ss; - json_archive ar(ss); - bool r = tx.serialize_base(ar); - CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); - return ss.str(); - } + class pruned_transaction { + transaction& tx; + public: + pruned_transaction(transaction& tx) : tx(tx) {} + BEGIN_SERIALIZE_OBJECT() + bool r = tx.serialize_base(ar); + if (!r) return false; + END_SERIALIZE() + }; //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res) { @@ -564,10 +556,11 @@ namespace cryptonote crypto::hash tx_hash = *vhi++; e.tx_hash = *txhi++; - blobdata blob = req.prune ? get_pruned_tx_blob(tx) : t_serializable_object_to_blob(tx); + pruned_transaction pruned_tx{tx}; + blobdata blob = req.prune ? t_serializable_object_to_blob(pruned_tx) : t_serializable_object_to_blob(tx); e.as_hex = string_tools::buff_to_hex_nodelimer(blob); if (req.decode_as_json) - e.as_json = req.prune ? get_pruned_tx_json(tx) : obj_to_json_str(tx); + e.as_json = req.prune ? obj_to_json_str(pruned_tx) : obj_to_json_str(tx); e.in_pool = pool_tx_hashes.find(tx_hash) != pool_tx_hashes.end(); if (e.in_pool) { From 7f0dd094e79d2b0bf536329475ff44adebe09233 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 22 Oct 2018 12:31:42 +0000 Subject: [PATCH 0155/1007] wallet2: sanity check rct output distribution from the daemon --- src/wallet/wallet2.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..51d15c6b2 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6683,15 +6683,21 @@ void wallet2::get_outs(std::vector> uint64_t rct_start_height; std::vector rct_offsets; bool has_rct = false; + uint64_t max_rct_index = 0; for (size_t idx: selected_transfers) if (m_transfers[idx].is_rct()) - { has_rct = true; break; } + { + has_rct = true; + max_rct_index = std::max(max_rct_index, m_transfers[idx].m_global_output_index); + } const bool has_rct_distribution = has_rct && get_rct_distribution(rct_start_height, rct_offsets); if (has_rct_distribution) { // check we're clear enough of rct start, to avoid corner cases below THROW_WALLET_EXCEPTION_IF(rct_offsets.size() <= CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, error::get_output_distribution, "Not enough rct outputs"); + THROW_WALLET_EXCEPTION_IF(rct_offsets.back() <= max_rct_index, + error::get_output_distribution, "Daemon reports suspicious number of rct outputs"); } // get histogram for the amounts we need From ed36335c969a1061e555724467263e22d1738cce Mon Sep 17 00:00:00 2001 From: xiphon Date: Mon, 22 Oct 2018 06:48:54 +0000 Subject: [PATCH 0156/1007] crypto: fixed incremental keccak API on big-endian platforms --- src/crypto/keccak.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crypto/keccak.c b/src/crypto/keccak.c index b5946036e..b095b5ce2 100644 --- a/src/crypto/keccak.c +++ b/src/crypto/keccak.c @@ -145,7 +145,7 @@ void keccak1600(const uint8_t *in, size_t inlen, uint8_t *md) #define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) #define KECCAK_PROCESS_BLOCK(st, block) { \ for (int i_ = 0; i_ < KECCAK_WORDS; i_++){ \ - ((st))[i_] ^= ((block))[i_]; \ + ((st))[i_] ^= swap64le(((block))[i_]); \ }; \ keccakf(st, KECCAK_ROUNDS); } @@ -207,7 +207,8 @@ void keccak_finish(KECCAK_CTX * ctx, uint8_t *md){ } static_assert(KECCAK_BLOCKLEN > KECCAK_DIGESTSIZE, ""); + static_assert(KECCAK_DIGESTSIZE % sizeof(uint64_t) == 0, ""); if (md) { - memcpy(md, ctx->hash, KECCAK_DIGESTSIZE); + memcpy_swap64le(md, ctx->hash, KECCAK_DIGESTSIZE / sizeof(uint64_t)); } } From cb4aafd27ebe452ca49aa5142520a40064c2fcca Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 22 Oct 2018 16:03:57 +0000 Subject: [PATCH 0157/1007] blockchain_utilities: simplify getting block blob from height --- src/blockchain_utilities/blockchain_ancestry.cpp | 12 ++++-------- src/blockchain_utilities/blockchain_depth.cpp | 3 +-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/blockchain_utilities/blockchain_ancestry.cpp b/src/blockchain_utilities/blockchain_ancestry.cpp index 2f0bbffd6..e01a8892c 100644 --- a/src/blockchain_utilities/blockchain_ancestry.cpp +++ b/src/blockchain_utilities/blockchain_ancestry.cpp @@ -407,8 +407,7 @@ int main(int argc, char* argv[]) for (uint64_t h = state.height; h < db_height; ++h) { size_t block_ancestry_size = 0; - const crypto::hash block_hash = db->get_block_hash_from_height(h); - const cryptonote::blobdata bd = db->get_block_blob(block_hash); + const cryptonote::blobdata bd = db->get_block_blob_from_height(h); ++total_blocks; cryptonote::block b; if (!cryptonote::parse_and_validate_block_from_blob(bd, b)) @@ -482,8 +481,7 @@ int main(int argc, char* argv[]) } else { - const crypto::hash block_hash = db->get_block_hash_from_height(od.height); - cryptonote::blobdata bd = db->get_block_blob(block_hash); + cryptonote::blobdata bd = db->get_block_blob_from_height(od.height); if (!cryptonote::parse_and_validate_block_from_blob(bd, b)) { LOG_PRINT_L0("Bad block from db"); @@ -620,8 +618,7 @@ int main(int argc, char* argv[]) } else { - const crypto::hash block_hash = db->get_block_hash_from_height(opt_height); - const cryptonote::blobdata bd = db->get_block_blob(block_hash); + const cryptonote::blobdata bd = db->get_block_blob_from_height(opt_height); cryptonote::block b; if (!cryptonote::parse_and_validate_block_from_blob(bd, b)) { @@ -678,8 +675,7 @@ int main(int argc, char* argv[]) { add_ancestor(ancestry, amount, offset); const output_data_t od = db->get_output_key(amount, offset); - const crypto::hash block_hash = db->get_block_hash_from_height(od.height); - bd = db->get_block_blob(block_hash); + bd = db->get_block_blob_from_height(od.height); cryptonote::block b; if (!cryptonote::parse_and_validate_block_from_blob(bd, b)) { diff --git a/src/blockchain_utilities/blockchain_depth.cpp b/src/blockchain_utilities/blockchain_depth.cpp index dd2387e5b..8060b0de4 100644 --- a/src/blockchain_utilities/blockchain_depth.cpp +++ b/src/blockchain_utilities/blockchain_depth.cpp @@ -187,8 +187,7 @@ int main(int argc, char* argv[]) } else { - const crypto::hash block_hash = db->get_block_hash_from_height(opt_height); - const cryptonote::blobdata bd = db->get_block_blob(block_hash); + const cryptonote::blobdata bd = db->get_block_blob_from_height(opt_height); cryptonote::block b; if (!cryptonote::parse_and_validate_block_from_blob(bd, b)) { From 4564a5d17b4c1a4507ac14dc96ad2bcaa675712c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 7 Aug 2018 08:02:42 +0000 Subject: [PATCH 0158/1007] bulletproofs: speedup PROVE --- src/ringct/bulletproofs.cc | 122 ++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 64 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 381f50872..0e5b3b55f 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -127,15 +127,6 @@ static void sub_acc_p3(ge_p3 *acc_p3, const rct::key &point) ge_p1p1_to_p3(acc_p3, &p1); } -static rct::key scalarmultKey(const ge_p3 &P, const rct::key &a) -{ - ge_p2 R; - ge_scalarmult(&R, a.bytes, &P); - rct::key aP; - ge_tobytes(aP.bytes, &R); - return aP; -} - static rct::key get_exponent(const rct::key &base, size_t idx) { static const std::string salt("bulletproof"); @@ -193,23 +184,28 @@ static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b) } /* Compute a custom vector-scalar commitment */ -static rct::key vector_exponent_custom(const rct::keyV &A, const rct::keyV &B, const rct::keyV &a, const rct::keyV &b) +static rct::key cross_vector_exponent8(size_t size, const std::vector &A, size_t Ao, const std::vector &B, size_t Bo, const rct::keyV &a, size_t ao, const rct::keyV &b, size_t bo, const ge_p3 *extra_point, const rct::key *extra_scalar) { - CHECK_AND_ASSERT_THROW_MES(A.size() == B.size(), "Incompatible sizes of A and B"); - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); - CHECK_AND_ASSERT_THROW_MES(a.size() == A.size(), "Incompatible sizes of a and A"); - CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN*maxM, "Incompatible sizes of a and maxN"); + CHECK_AND_ASSERT_THROW_MES(size + Ao <= A.size(), "Incompatible size for A"); + CHECK_AND_ASSERT_THROW_MES(size + Bo <= B.size(), "Incompatible size for B"); + CHECK_AND_ASSERT_THROW_MES(size + ao <= a.size(), "Incompatible size for a"); + CHECK_AND_ASSERT_THROW_MES(size + bo <= b.size(), "Incompatible size for b"); + CHECK_AND_ASSERT_THROW_MES(size <= maxN*maxM, "size is too large"); + CHECK_AND_ASSERT_THROW_MES(!!extra_point == !!extra_scalar, "only one of extra point/scalar present"); std::vector multiexp_data; - multiexp_data.reserve(a.size()*2); - for (size_t i = 0; i < a.size(); ++i) + multiexp_data.resize(size*2 + (!!extra_point)); + for (size_t i = 0; i < size; ++i) { - multiexp_data.resize(multiexp_data.size() + 1); - multiexp_data.back().scalar = a[i]; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&multiexp_data.back().point, A[i].bytes) == 0, "ge_frombytes_vartime failed"); - multiexp_data.resize(multiexp_data.size() + 1); - multiexp_data.back().scalar = b[i]; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&multiexp_data.back().point, B[i].bytes) == 0, "ge_frombytes_vartime failed"); + sc_mul(multiexp_data[i*2].scalar.bytes, a[ao+i].bytes, INV_EIGHT.bytes);; + multiexp_data[i*2].point = A[Ao+i]; + sc_mul(multiexp_data[i*2+1].scalar.bytes, b[bo+i].bytes, INV_EIGHT.bytes); + multiexp_data[i*2+1].point = B[Bo+i]; + } + if (extra_point) + { + sc_mul(multiexp_data.back().scalar.bytes, extra_scalar->bytes, INV_EIGHT.bytes); + multiexp_data.back().point = *extra_point; } return multiexp(multiexp_data, false); } @@ -273,16 +269,19 @@ static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b) return res; } -/* Given two curvepoint arrays, construct the Hadamard product */ -static rct::keyV hadamard2(const rct::keyV &a, const rct::keyV &b) +/* folds a curvepoint array using a two way scaled Hadamard product */ +static void hadamard_fold(std::vector &v, const rct::key &a, const rct::key &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); - rct::keyV res(a.size()); - for (size_t i = 0; i < a.size(); ++i) + CHECK_AND_ASSERT_THROW_MES((v.size() & 1) == 0, "Vector size should be even"); + const size_t sz = v.size() / 2; + for (size_t n = 0; n < sz; ++n) { - rct::addKeys(res[i], a[i], b[i]); + ge_dsmp c[2]; + ge_dsm_precomp(c[0], &v[n]); + ge_dsm_precomp(c[1], &v[sz + n]); + ge_double_scalarmult_precomp_vartime2_p3(&v[n], a.bytes, c[0], b.bytes, c[1]); } - return res; + v.resize(sz); } /* Add two vectors */ @@ -326,17 +325,6 @@ static rct::keyV vector_dup(const rct::key &x, size_t N) return rct::keyV(N, x); } -/* Exponentiate a curve vector by a scalar */ -static rct::keyV vector_scalar2(const rct::keyV &a, const rct::key &x) -{ - rct::keyV res(a.size()); - for (size_t i = 0; i < a.size(); ++i) - { - rct::scalarmultKey(res[i], a[i], x); - } - return res; -} - /* Get the sum of a vector's elements */ static rct::key vector_sum(const rct::keyV &a) { @@ -620,16 +608,16 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) // These are used in the inner product rounds size_t nprime = N; - rct::keyV Gprime(N); - rct::keyV Hprime(N); + std::vector Gprime(N); + std::vector Hprime(N); rct::keyV aprime(N); rct::keyV bprime(N); const rct::key yinv = invert(y); rct::key yinvpow = rct::identity(); for (size_t i = 0; i < N; ++i) { - Gprime[i] = Gi[i]; - Hprime[i] = scalarmultKey(Hi_p3[i], yinvpow); + Gprime[i] = Gi_p3[i]; + ge_scalarmult_p3(&Hprime[i], yinvpow.bytes, &Hi_p3[i]); sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); aprime[i] = l[i]; bprime[i] = r[i]; @@ -652,14 +640,10 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); // PAPER LINES 18-19 - L[round] = vector_exponent_custom(slice(Gprime, nprime, Gprime.size()), slice(Hprime, 0, nprime), slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); - rct::addKeys(L[round], L[round], rct::scalarmultH(tmp)); - L[round] = rct::scalarmultKey(L[round], INV_EIGHT); - R[round] = vector_exponent_custom(slice(Gprime, 0, nprime), slice(Hprime, nprime, Hprime.size()), slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); + L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, &ge_p3_H, &tmp); sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); - rct::addKeys(R[round], R[round], rct::scalarmultH(tmp)); - R[round] = rct::scalarmultKey(R[round], INV_EIGHT); + R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, &ge_p3_H, &tmp); // PAPER LINES 21-22 w[round] = hash_cache_mash(hash_cache, L[round], R[round]); @@ -672,8 +656,11 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) // PAPER LINES 24-25 const rct::key winv = invert(w[round]); - Gprime = hadamard2(vector_scalar2(slice(Gprime, 0, nprime), winv), vector_scalar2(slice(Gprime, nprime, Gprime.size()), w[round])); - Hprime = hadamard2(vector_scalar2(slice(Hprime, 0, nprime), w[round]), vector_scalar2(slice(Hprime, nprime, Hprime.size()), winv)); + if (nprime > 1) + { + hadamard_fold(Gprime, winv, w[round]); + hadamard_fold(Hprime, w[round], winv); + } // PAPER LINES 28-29 aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); @@ -914,16 +901,16 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) // These are used in the inner product rounds size_t nprime = MN; - rct::keyV Gprime(MN); - rct::keyV Hprime(MN); + std::vector Gprime(MN); + std::vector Hprime(MN); rct::keyV aprime(MN); rct::keyV bprime(MN); const rct::key yinv = invert(y); rct::key yinvpow = rct::identity(); for (size_t i = 0; i < MN; ++i) { - Gprime[i] = Gi[i]; - Hprime[i] = scalarmultKey(Hi_p3[i], yinvpow); + Gprime[i] = Gi_p3[i]; + ge_scalarmult_p3(&Hprime[i], yinvpow.bytes, &Hi_p3[i]); sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); aprime[i] = l[i]; bprime[i] = r[i]; @@ -942,18 +929,18 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) nprime /= 2; // PAPER LINES 16-17 + PERF_TIMER_START_BP(PROVE_inner_product); rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); + PERF_TIMER_STOP(PROVE_inner_product); // PAPER LINES 18-19 - L[round] = vector_exponent_custom(slice(Gprime, nprime, Gprime.size()), slice(Hprime, 0, nprime), slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); + PERF_TIMER_START_BP(PROVE_LR); sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); - rct::addKeys(L[round], L[round], rct::scalarmultH(tmp)); - L[round] = rct::scalarmultKey(L[round], INV_EIGHT); - R[round] = vector_exponent_custom(slice(Gprime, 0, nprime), slice(Hprime, nprime, Hprime.size()), slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); + L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, &ge_p3_H, &tmp); sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); - rct::addKeys(R[round], R[round], rct::scalarmultH(tmp)); - R[round] = rct::scalarmultKey(R[round], INV_EIGHT); + R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, &ge_p3_H, &tmp); + PERF_TIMER_STOP(PROVE_LR); // PAPER LINES 21-22 w[round] = hash_cache_mash(hash_cache, L[round], R[round]); @@ -966,12 +953,19 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) // PAPER LINES 24-25 const rct::key winv = invert(w[round]); - Gprime = hadamard2(vector_scalar2(slice(Gprime, 0, nprime), winv), vector_scalar2(slice(Gprime, nprime, Gprime.size()), w[round])); - Hprime = hadamard2(vector_scalar2(slice(Hprime, 0, nprime), w[round]), vector_scalar2(slice(Hprime, nprime, Hprime.size()), winv)); + if (nprime > 1) + { + PERF_TIMER_START_BP(PROVE_hadamard2); + hadamard_fold(Gprime, winv, w[round]); + hadamard_fold(Hprime, w[round], winv); + PERF_TIMER_STOP(PROVE_hadamard2); + } // PAPER LINES 28-29 + PERF_TIMER_START_BP(PROVE_prime); aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round])); + PERF_TIMER_STOP(PROVE_prime); ++round; } From a49a17618fcb4c734248dcc06954c86dcc3fc5cd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 7 Aug 2018 09:59:14 +0000 Subject: [PATCH 0159/1007] bulletproofs: shave off a lot of scalar muls from the g/h construction --- src/ringct/bulletproofs.cc | 59 +++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 0e5b3b55f..8a6ea2dce 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -1138,41 +1138,60 @@ bool bulletproof_VERIFY(const std::vector &proofs) winv[i] = invert(w[i]); PERF_TIMER_STOP(VERIFY_line_24_25_invert); + // precalc + PERF_TIMER_START_BP(VERIFY_line_24_25_precalc); + rct::keyV w_cache(1< 0; --s) + { + sc_mul(w_cache[s].bytes, w_cache[s/2].bytes, w[j].bytes); + sc_mul(w_cache[s-1].bytes, w_cache[s/2].bytes, winv[j].bytes); + } + } + PERF_TIMER_STOP(VERIFY_line_24_25_precalc); + for (size_t i = 0; i < MN; ++i) { - // Convert the index to binary IN REVERSE and construct the scalar exponent rct::key g_scalar = proof.a; rct::key h_scalar; - sc_mul(h_scalar.bytes, proof.b.bytes, yinvpow.bytes); + if (i == 0) + h_scalar = proof.b; + else + sc_mul(h_scalar.bytes, proof.b.bytes, yinvpow.bytes); - for (size_t j = rounds; j-- > 0; ) - { - size_t J = w.size() - j - 1; - - if ((i & (((size_t)1)< Date: Wed, 8 Aug 2018 12:14:13 +0000 Subject: [PATCH 0160/1007] bulletproofs: random minor speedups --- src/ringct/bulletproofs.cc | 78 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 8a6ea2dce..2d2e6af36 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -93,18 +93,6 @@ static bool is_reduced(const rct::key &scalar) return scalar == reduced; } -static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point) -{ - ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); - ge_scalarmult_p3(&p3, a.bytes, &p3); - ge_cached cached; - ge_p3_to_cached(&cached, acc_p3); - ge_p1p1 p1; - ge_add(&p1, &p3, &cached); - ge_p1p1_to_p3(acc_p3, &p1); -} - static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) { ge_p3 p3; @@ -435,10 +423,13 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) rct::key V; rct::keyV aL(N), aR(N); + rct::key tmp, tmp2; PERF_TIMER_START_BP(PROVE_v); - rct::addKeys2(V, gamma, sv, rct::H); - V = rct::scalarmultKey(V, INV_EIGHT); + rct::key gamma8, sv8; + sc_mul(gamma8.bytes, gamma.bytes, INV_EIGHT.bytes); + sc_mul(sv8.bytes, sv.bytes, INV_EIGHT.bytes); + rct::addKeys2(V, gamma8, sv8, rct::H); PERF_TIMER_STOP(PROVE_v); PERF_TIMER_START_BP(PROVE_aLaR); @@ -515,7 +506,6 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) const auto yN = vector_powers(y, N); rct::key ip1y = vector_sum(yN); - rct::key tmp; sc_muladd(t0.bytes, z.bytes, ip1y.bytes, t0.bytes); rct::key zsq; @@ -563,10 +553,16 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) // PAPER LINES 47-48 rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); - rct::key T1 = rct::addKeys(rct::scalarmultH(t1), rct::scalarmultBase(tau1)); - T1 = rct::scalarmultKey(T1, INV_EIGHT); - rct::key T2 = rct::addKeys(rct::scalarmultH(t2), rct::scalarmultBase(tau2)); - T2 = rct::scalarmultKey(T2, INV_EIGHT); + rct::key T1, T2; + ge_p3 p3; + sc_mul(tmp.bytes, t1.bytes, INV_EIGHT.bytes); + sc_mul(tmp2.bytes, tau1.bytes, INV_EIGHT.bytes); + ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes); + ge_p3_tobytes(T1.bytes, &p3); + sc_mul(tmp.bytes, t2.bytes, INV_EIGHT.bytes); + sc_mul(tmp2.bytes, tau2.bytes, INV_EIGHT.bytes); + ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes); + ge_p3_tobytes(T2.bytes, &p3); // PAPER LINES 49-51 rct::key x = hash_cache_mash(hash_cache, z, T1, T2); @@ -671,7 +667,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) PERF_TIMER_STOP(PROVE_step4); // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20) - return Bulletproof(V, A, S, T1, T2, taux, mu, L, R, aprime[0], bprime[0], t); + return Bulletproof(V, A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t); } Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma) @@ -715,13 +711,15 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::keyV V(sv.size()); rct::keyV aL(MN), aR(MN); - rct::key tmp; + rct::key tmp, tmp2; PERF_TIMER_START_BP(PROVE_v); for (size_t i = 0; i < sv.size(); ++i) { - rct::addKeys2(V[i], gamma[i], sv[i], rct::H); - V[i] = rct::scalarmultKey(V[i], INV_EIGHT); + rct::key gamma8, sv8; + sc_mul(gamma8.bytes, gamma[i].bytes, INV_EIGHT.bytes); + sc_mul(sv8.bytes, sv[i].bytes, INV_EIGHT.bytes); + rct::addKeys2(V[i], gamma8, sv8, rct::H); } PERF_TIMER_STOP(PROVE_v); @@ -843,10 +841,16 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) // PAPER LINES 47-48 rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); - rct::key T1 = rct::addKeys(rct::scalarmultH(t1), rct::scalarmultBase(tau1)); - T1 = rct::scalarmultKey(T1, INV_EIGHT); - rct::key T2 = rct::addKeys(rct::scalarmultH(t2), rct::scalarmultBase(tau2)); - T2 = rct::scalarmultKey(T2, INV_EIGHT); + rct::key T1, T2; + ge_p3 p3; + sc_mul(tmp.bytes, t1.bytes, INV_EIGHT.bytes); + sc_mul(tmp2.bytes, tau1.bytes, INV_EIGHT.bytes); + ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes); + ge_p3_tobytes(T1.bytes, &p3); + sc_mul(tmp.bytes, t2.bytes, INV_EIGHT.bytes); + sc_mul(tmp2.bytes, tau2.bytes, INV_EIGHT.bytes); + ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes); + ge_p3_tobytes(T2.bytes, &p3); // PAPER LINES 49-51 rct::key x = hash_cache_mash(hash_cache, z, T1, T2); @@ -972,7 +976,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) PERF_TIMER_STOP(PROVE_step4); // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20) - return Bulletproof(V, A, S, T1, T2, taux, mu, L, R, aprime[0], bprime[0], t); + return Bulletproof(std::move(V), A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t); } Bulletproof bulletproof_PROVE(const std::vector &v, const rct::keyV &gamma) @@ -1034,10 +1038,10 @@ bool bulletproof_VERIFY(const std::vector &proofs) // setup weighted aggregates rct::key Z0 = rct::identity(); rct::key z1 = rct::zero(); - rct::key Z2 = rct::identity(); + rct::key &Z2 = Z0; rct::key z3 = rct::zero(); rct::keyV z4(maxMN, rct::zero()), z5(maxMN, rct::zero()); - rct::key Y2 = rct::identity(), Y3 = rct::identity(), Y4 = rct::identity(); + rct::key Y2 = rct::identity(), &Y3 = Y2, &Y4 = Y2; rct::key y0 = rct::zero(), y1 = rct::zero(); for (const Bulletproof *p: proofs) { @@ -1224,11 +1228,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) // now check all proofs at once PERF_TIMER_START_BP(VERIFY_step2_check); ge_p3 check1; - ge_scalarmult_base(&check1, y0.bytes); - addKeys_acc_p3(&check1, y1, rct::H); + ge_double_scalarmult_base_vartime_p3(&check1, y1.bytes, &ge_p3_H, y0.bytes); sub_acc_p3(&check1, Y2); - sub_acc_p3(&check1, Y3); - sub_acc_p3(&check1, Y4); if (!ge_p3_is_point_at_infinity(&check1)) { MERROR("Verification failure at step 1"); @@ -1238,18 +1239,15 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_sub(tmp.bytes, rct::zero().bytes, z1.bytes); ge_double_scalarmult_base_vartime_p3(&check2, z3.bytes, &ge_p3_H, tmp.bytes); add_acc_p3(&check2, Z0); - add_acc_p3(&check2, Z2); std::vector multiexp_data; multiexp_data.reserve(2 * maxMN); for (size_t i = 0; i < maxMN; ++i) { - sc_sub(tmp.bytes, rct::zero().bytes, z4[i].bytes); - multiexp_data.emplace_back(tmp, Gi_p3[i]); - sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes); - multiexp_data.emplace_back(tmp, Hi_p3[i]); + multiexp_data.emplace_back(z4[i], Gi_p3[i]); + multiexp_data.emplace_back(z5[i], Hi_p3[i]); } - add_acc_p3(&check2, multiexp(multiexp_data, true)); + sub_acc_p3(&check2, multiexp(multiexp_data, true)); PERF_TIMER_STOP(VERIFY_step2_check); if (!ge_p3_is_point_at_infinity(&check2)) From 484155d043d661ae1a3d7a196b2354719b90485a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 8 Aug 2018 15:01:41 +0000 Subject: [PATCH 0161/1007] bulletproofs: some more speedup --- src/ringct/bulletproofs.cc | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 2d2e6af36..5c75e6418 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -423,6 +423,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) rct::key V; rct::keyV aL(N), aR(N); + rct::keyV aL8(N), aR8(N); rct::key tmp, tmp2; PERF_TIMER_START_BP(PROVE_v); @@ -438,12 +439,15 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) if (sv[i/8] & (((uint64_t)1)<<(i%8))) { aL[i] = rct::identity(); + aL8[i] = INV_EIGHT; + aR[i] = aR8[i] = rct::zero(); } else { - aL[i] = rct::zero(); + aL[i] = aL8[i] = rct::zero(); + aR[i] = MINUS_ONE; + aR8[i] = MINUS_INV_EIGHT; } - sc_sub(aR[i].bytes, aL[i].bytes, rct::identity().bytes); } PERF_TIMER_STOP(PROVE_aLaR); @@ -469,10 +473,10 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) PERF_TIMER_START_BP(PROVE_step1); // PAPER LINES 38-39 rct::key alpha = rct::skGen(); - rct::key ve = vector_exponent(aL, aR); + rct::key ve = vector_exponent(aL8, aR8); rct::key A; - rct::addKeys(A, ve, rct::scalarmultBase(alpha)); - A = rct::scalarmultKey(A, INV_EIGHT); + sc_mul(tmp.bytes, alpha.bytes, INV_EIGHT.bytes); + rct::addKeys(A, ve, rct::scalarmultBase(tmp)); // PAPER LINES 40-42 rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N); @@ -711,6 +715,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::keyV V(sv.size()); rct::keyV aL(MN), aR(MN); + rct::keyV aL8(MN), aR8(MN); rct::key tmp, tmp2; PERF_TIMER_START_BP(PROVE_v); @@ -728,19 +733,18 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) { for (size_t i = N; i-- > 0; ) { - if (j >= sv.size()) - { - aL[j*N+i] = rct::zero(); - } - else if (sv[j][i/8] & (((uint64_t)1)<<(i%8))) + if (j < sv.size() && (sv[j][i/8] & (((uint64_t)1)<<(i%8)))) { aL[j*N+i] = rct::identity(); + aL8[j*N+i] = INV_EIGHT; + aR[j*N+i] = aR8[j*N+i] = rct::zero(); } else { - aL[j*N+i] = rct::zero(); + aL[j*N+i] = aL8[j*N+i] = rct::zero(); + aR[j*N+i] = MINUS_ONE; + aR8[j*N+i] = MINUS_INV_EIGHT; } - sc_sub(aR[j*N+i].bytes, aL[j*N+i].bytes, rct::identity().bytes); } } PERF_TIMER_STOP(PROVE_aLaR); @@ -771,10 +775,10 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) PERF_TIMER_START_BP(PROVE_step1); // PAPER LINES 38-39 rct::key alpha = rct::skGen(); - rct::key ve = vector_exponent(aL, aR); + rct::key ve = vector_exponent(aL8, aR8); rct::key A; - rct::addKeys(A, ve, rct::scalarmultBase(alpha)); - A = rct::scalarmultKey(A, INV_EIGHT); + sc_mul(tmp.bytes, alpha.bytes, INV_EIGHT.bytes); + rct::addKeys(A, ve, rct::scalarmultBase(tmp)); // PAPER LINES 40-42 rct::keyV sL = rct::skvGen(MN), sR = rct::skvGen(MN); From a281b950bff73fc715554d00ec32292ef97b56ec Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 8 Aug 2018 18:39:31 +0000 Subject: [PATCH 0162/1007] bulletproofs: remove single value prover It is now expressed in terms of the array prover --- src/ringct/bulletproofs.cc | 284 +------------------------------------ src/ringct/rctSigs.cpp | 9 -- 2 files changed, 2 insertions(+), 291 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 5c75e6418..09d22c6d1 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -313,17 +313,6 @@ static rct::keyV vector_dup(const rct::key &x, size_t N) return rct::keyV(N, x); } -/* Get the sum of a vector's elements */ -static rct::key vector_sum(const rct::keyV &a) -{ - rct::key res = rct::zero(); - for (size_t i = 0; i < a.size(); ++i) - { - sc_add(res.bytes, res.bytes, a[i].bytes); - } - return res; -} - static rct::key switch_endianness(rct::key k) { std::reverse(k.bytes, k.bytes + sizeof(k)); @@ -414,281 +403,12 @@ static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, con /* Given a value v (0..2^N-1) and a mask gamma, construct a range proof */ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) { - init_exponents(); - - PERF_TIMER_UNIT(PROVE, 1000000); - - constexpr size_t logN = 6; // log2(64) - constexpr size_t N = 1< 0; ) - { - if (sv[i/8] & (((uint64_t)1)<<(i%8))) - { - aL[i] = rct::identity(); - aL8[i] = INV_EIGHT; - aR[i] = aR8[i] = rct::zero(); - } - else - { - aL[i] = aL8[i] = rct::zero(); - aR[i] = MINUS_ONE; - aR8[i] = MINUS_INV_EIGHT; - } - } - PERF_TIMER_STOP(PROVE_aLaR); - - rct::key hash_cache = rct::hash_to_scalar(V); - - // DEBUG: Test to ensure this recovers the value -#ifdef DEBUG_BP - uint64_t test_aL = 0, test_aR = 0; - for (size_t i = 0; i < N; ++i) - { - if (aL[i] == rct::identity()) - test_aL += ((uint64_t)1)< Gprime(N); - std::vector Hprime(N); - rct::keyV aprime(N); - rct::keyV bprime(N); - const rct::key yinv = invert(y); - rct::key yinvpow = rct::identity(); - for (size_t i = 0; i < N; ++i) - { - Gprime[i] = Gi_p3[i]; - ge_scalarmult_p3(&Hprime[i], yinvpow.bytes, &Hi_p3[i]); - sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); - aprime[i] = l[i]; - bprime[i] = r[i]; - } - rct::keyV L(logN); - rct::keyV R(logN); - int round = 0; - rct::keyV w(logN); // this is the challenge x in the inner product protocol - PERF_TIMER_STOP(PROVE_step3); - - PERF_TIMER_START_BP(PROVE_step4); - // PAPER LINE 13 - while (nprime > 1) - { - // PAPER LINE 15 - nprime /= 2; - - // PAPER LINES 16-17 - rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); - rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); - - // PAPER LINES 18-19 - sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); - L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, &ge_p3_H, &tmp); - sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); - R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, &ge_p3_H, &tmp); - - // PAPER LINES 21-22 - w[round] = hash_cache_mash(hash_cache, L[round], R[round]); - if (w[round] == rct::zero()) - { - PERF_TIMER_STOP(PROVE_step4); - MINFO("w[round] is 0, trying again"); - goto try_again; - } - - // PAPER LINES 24-25 - const rct::key winv = invert(w[round]); - if (nprime > 1) - { - hadamard_fold(Gprime, winv, w[round]); - hadamard_fold(Hprime, w[round], winv); - } - - // PAPER LINES 28-29 - aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); - bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round])); - - ++round; - } - PERF_TIMER_STOP(PROVE_step4); - - // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20) - return Bulletproof(V, A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t); + return bulletproof_PROVE(rct::keyV(1, sv), rct::keyV(1, gamma)); } Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma) { - // vG + gammaH - PERF_TIMER_START_BP(PROVE_v); - rct::key sv = rct::zero(); - sv.bytes[0] = v & 255; - sv.bytes[1] = (v >> 8) & 255; - sv.bytes[2] = (v >> 16) & 255; - sv.bytes[3] = (v >> 24) & 255; - sv.bytes[4] = (v >> 32) & 255; - sv.bytes[5] = (v >> 40) & 255; - sv.bytes[6] = (v >> 48) & 255; - sv.bytes[7] = (v >> 56) & 255; - PERF_TIMER_STOP(PROVE_v); - return bulletproof_PROVE(sv, gamma); + return bulletproof_PROVE(std::vector(1, v), rct::keyV(1, gamma)); } /* Given a set of values v (0..2^N-1) and masks gamma, construct a range proof */ diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 0d1789a38..5ec9a1750 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -45,15 +45,6 @@ using namespace std; #define CHECK_AND_ASSERT_MES_L1(expr, ret, message) {if(!(expr)) {MCERROR("verify", message); return ret;}} namespace rct { - Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount) - { - mask = rct::skGen(); - Bulletproof proof = bulletproof_PROVE(amount, mask); - CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element"); - C = proof.V[0]; - return proof; - } - Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector &amounts) { masks = rct::skvGen(amounts.size()); From c415df97bd20b2bcc999c0c0056bb32e9b102a5b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 8 Aug 2018 21:19:57 +0000 Subject: [PATCH 0163/1007] performance_tests: sc_check and ge_dsm_precomp --- tests/performance_tests/CMakeLists.txt | 2 + tests/performance_tests/crypto_ops.h | 3 ++ tests/performance_tests/main.cpp | 3 ++ tests/performance_tests/sc_check.h | 52 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 tests/performance_tests/sc_check.h diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 837d39bd3..5cd054d86 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -46,6 +46,8 @@ set(performance_tests_headers range_proof.h bulletproof.h crypto_ops.h + sc_reduce32.h + sc_check.h multiexp.h multi_tx_test_base.h performance_tests.h diff --git a/tests/performance_tests/crypto_ops.h b/tests/performance_tests/crypto_ops.h index 3c68583c5..4766a1205 100644 --- a/tests/performance_tests/crypto_ops.h +++ b/tests/performance_tests/crypto_ops.h @@ -47,6 +47,7 @@ enum test_op op_scalarmultKey, op_scalarmultH, op_scalarmult8, + op_ge_dsm_precomp, op_ge_double_scalarmult_base_vartime, op_ge_double_scalarmult_precomp_vartime, op_ge_double_scalarmult_precomp_vartime2, @@ -84,6 +85,7 @@ class test_crypto_ops ge_cached tmp_cached; ge_p1p1 tmp_p1p1; ge_p2 tmp_p2; + ge_dsmp dsmp; switch (op) { case op_sc_add: sc_add(key.bytes, scalar0.bytes, scalar1.bytes); break; @@ -101,6 +103,7 @@ class test_crypto_ops case op_scalarmultKey: rct::scalarmultKey(point0, scalar0); break; case op_scalarmultH: rct::scalarmultH(scalar0); break; case op_scalarmult8: rct::scalarmult8(point0); break; + case op_ge_dsm_precomp: ge_dsm_precomp(dsmp, &p3_0); break; case op_ge_double_scalarmult_base_vartime: ge_double_scalarmult_base_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes); break; case op_ge_double_scalarmult_precomp_vartime: ge_double_scalarmult_precomp_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes, precomp0); break; case op_ge_double_scalarmult_precomp_vartime2: ge_double_scalarmult_precomp_vartime2(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1); break; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 87a1573c2..3765d1249 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -50,6 +50,7 @@ #include "is_out_to_acc.h" #include "subaddress_expand.h" #include "sc_reduce32.h" +#include "sc_check.h" #include "cn_fast_hash.h" #include "rct_mlsag.h" #include "equality.h" @@ -184,6 +185,7 @@ int main(int argc, char** argv) TEST_PERFORMANCE0(filter, p, test_ge_frombytes_vartime); TEST_PERFORMANCE0(filter, p, test_generate_keypair); TEST_PERFORMANCE0(filter, p, test_sc_reduce32); + TEST_PERFORMANCE0(filter, p, test_sc_check); TEST_PERFORMANCE1(filter, p, test_signature, false); TEST_PERFORMANCE1(filter, p, test_signature, true); @@ -249,6 +251,7 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultKey); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultH); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmult8); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_dsm_precomp); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_base_vartime); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2); diff --git a/tests/performance_tests/sc_check.h b/tests/performance_tests/sc_check.h new file mode 100644 index 000000000..036abf12d --- /dev/null +++ b/tests/performance_tests/sc_check.h @@ -0,0 +1,52 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#pragma once + +#include "crypto/crypto.h" + +class test_sc_check +{ +public: + static const size_t loop_count = 10000000; + + bool init() + { + m_scalar = crypto::rand(); + return true; + } + + bool test() + { + sc_check((unsigned char*)m_scalar.data); + return true; + } + +private: + crypto::ec_scalar m_scalar; +}; From bf8e4b98709ffcf133ea875f3fbf7f99c28e52db Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 8 Aug 2018 21:20:50 +0000 Subject: [PATCH 0164/1007] bulletproofs: some more minor speedup --- src/ringct/bulletproofs.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 09d22c6d1..f22a109e9 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -86,11 +86,9 @@ static inline rct::key multiexp(const std::vector &data, bool HiGi return data.size() <= 64 ? straus(data, NULL, 0) : pippenger(data, NULL, get_pippenger_c(data.size())); } -static bool is_reduced(const rct::key &scalar) +static inline bool is_reduced(const rct::key &scalar) { - rct::key reduced = scalar; - sc_reduce32(reduced.bytes); - return scalar == reduced; + return sc_check(scalar.bytes) == 0; } static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) @@ -139,8 +137,8 @@ static void init_exponents() Gi[i] = get_exponent(rct::H, i * 2 + 1); CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3[i], Gi[i].bytes) == 0, "ge_frombytes_vartime failed"); - data.push_back({rct::zero(), Gi[i]}); - data.push_back({rct::zero(), Hi[i]}); + data.push_back({rct::zero(), Gi_p3[i]}); + data.push_back({rct::zero(), Hi_p3[i]}); } straus_HiGi_cache = straus_init_cache(data, STRAUS_SIZE_LIMIT); From 4061960a16d27f803ca54b8887f46185c29c336e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 13 Aug 2018 11:18:54 +0000 Subject: [PATCH 0165/1007] multiexp: pack the digits table when STRAUS_C is 4 Spotted by stoffu --- src/ringct/multiexp.cc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index 21957b94c..fb2f18551 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -320,7 +320,7 @@ rct::key bos_coster_heap_conv_robust(std::vector data) return res; } -static constexpr unsigned int STRAUS_C = 4; +#define STRAUS_C 4 struct straus_cached_data { @@ -447,26 +447,23 @@ rct::key straus(const std::vector &data, const std::shared_ptr digits{new uint8_t[64 * data.size()]}; +#else std::unique_ptr digits{new uint8_t[256 * data.size()]}; +#endif for (size_t j = 0; j < data.size(); ++j) { unsigned char bytes33[33]; memcpy(bytes33, data[j].scalar.bytes, 32); bytes33[32] = 0; const unsigned char *bytes = bytes33; -#if 1 - static_assert(STRAUS_C == 4, "optimized version needs STRAUS_C == 4"); +#if STRAUS_C==4 unsigned int i; - for (i = 0; i < 256; i += 8, bytes++) + for (i = 0; i < 64; i += 2, bytes++) { - digits[j*256+i] = bytes[0] & 0xf; - digits[j*256+i+1] = (bytes[0] >> 1) & 0xf; - digits[j*256+i+2] = (bytes[0] >> 2) & 0xf; - digits[j*256+i+3] = (bytes[0] >> 3) & 0xf; - digits[j*256+i+4] = ((bytes[0] >> 4) | (bytes[1]<<4)) & 0xf; - digits[j*256+i+5] = ((bytes[0] >> 5) | (bytes[1]<<3)) & 0xf; - digits[j*256+i+6] = ((bytes[0] >> 6) | (bytes[1]<<2)) & 0xf; - digits[j*256+i+7] = ((bytes[0] >> 7) | (bytes[1]<<1)) & 0xf; + digits[j*64+i] = bytes[0] & 0xf; + digits[j*64+i+1] = bytes[0] >> 4; } #elif 1 for (size_t i = 0; i < 256; ++i) @@ -521,7 +518,11 @@ rct::key straus(const std::vector &data, const std::shared_ptr Date: Thu, 23 Aug 2018 18:52:05 +0000 Subject: [PATCH 0166/1007] bulletproofs: merge multiexps as per sarang's new python code --- src/ringct/bulletproofs.cc | 106 +++++++++++++------------------------ 1 file changed, 38 insertions(+), 68 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index f22a109e9..549e52296 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -91,28 +91,6 @@ static inline bool is_reduced(const rct::key &scalar) return sc_check(scalar.bytes) == 0; } -static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) -{ - ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); - ge_cached cached; - ge_p3_to_cached(&cached, &p3); - ge_p1p1 p1; - ge_add(&p1, acc_p3, &cached); - ge_p1p1_to_p3(acc_p3, &p1); -} - -static void sub_acc_p3(ge_p3 *acc_p3, const rct::key &point) -{ - ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); - ge_cached cached; - ge_p3_to_cached(&cached, &p3); - ge_p1p1 p1; - ge_sub(&p1, acc_p3, &cached); - ge_p1p1_to_p3(acc_p3, &p1); -} - static rct::key get_exponent(const rct::key &base, size_t idx) { static const std::string salt("bulletproof"); @@ -733,6 +711,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) // sanity and figure out which proof is longest size_t max_length = 0; + size_t nV = 0; for (const Bulletproof *p: proofs) { const Bulletproof &proof = *p; @@ -749,6 +728,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof"); max_length = std::max(max_length, proof.L.size()); + nV += proof.V.size(); } CHECK_AND_ASSERT_MES(max_length < 32, false, "At least one proof is too large"); size_t maxMN = 1u << max_length; @@ -757,13 +737,13 @@ bool bulletproof_VERIFY(const std::vector &proofs) const size_t N = 1 << logN; rct::key tmp; + std::vector multiexp_data; + multiexp_data.reserve(nV + (2 * (10/*logM*/ + logN) + 4) * proofs.size() + 2 * maxMN); + // setup weighted aggregates - rct::key Z0 = rct::identity(); rct::key z1 = rct::zero(); - rct::key &Z2 = Z0; rct::key z3 = rct::zero(); rct::keyV z4(maxMN, rct::zero()), z5(maxMN, rct::zero()); - rct::key Y2 = rct::identity(), &Y3 = Y2, &Y4 = Y2; rct::key y0 = rct::zero(), y1 = rct::zero(); for (const Bulletproof *p: proofs) { @@ -773,7 +753,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) for (logM = 0; (M = 1< &proofs) rct::key proof8_T1 = rct::scalarmult8(proof.T1); rct::key proof8_T2 = rct::scalarmult8(proof.T2); rct::key proof8_S = rct::scalarmult8(proof.S); + rct::key proof8_A = rct::scalarmult8(proof.A); PERF_TIMER_START_BP(VERIFY_line_61); // PAPER LINE 61 - sc_muladd(y0.bytes, proof.taux.bytes, weight.bytes, y0.bytes); + sc_muladd(y0.bytes, proof.taux.bytes, weight_y.bytes, y0.bytes); const rct::keyV zpow = vector_powers(z, M+3); @@ -814,26 +796,26 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_line_61rl_new); sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes); - std::vector multiexp_data; - multiexp_data.reserve(proof.V.size()); sc_sub(tmp.bytes, proof.t.bytes, tmp.bytes); - sc_muladd(y1.bytes, tmp.bytes, weight.bytes, y1.bytes); + sc_muladd(y1.bytes, tmp.bytes, weight_y.bytes, y1.bytes); for (size_t j = 0; j < proof8_V.size(); j++) { - multiexp_data.emplace_back(zpow[j+2], proof8_V[j]); + sc_mul(tmp.bytes, zpow[j+2].bytes, weight_y.bytes); + multiexp_data.emplace_back(tmp, proof8_V[j]); } - rct::addKeys(Y2, Y2, rct::scalarmultKey(multiexp(multiexp_data, false), weight)); - sc_mul(tmp.bytes, x.bytes, weight.bytes); - rct::addKeys(Y3, Y3, rct::scalarmultKey(proof8_T1, tmp)); + sc_mul(tmp.bytes, x.bytes, weight_y.bytes); + multiexp_data.emplace_back(tmp, proof8_T1); rct::key xsq; sc_mul(xsq.bytes, x.bytes, x.bytes); - sc_mul(tmp.bytes, xsq.bytes, weight.bytes); - rct::addKeys(Y4, Y4, rct::scalarmultKey(proof8_T2, tmp)); + sc_mul(tmp.bytes, xsq.bytes, weight_y.bytes); + multiexp_data.emplace_back(tmp, proof8_T2); PERF_TIMER_STOP(VERIFY_line_61rl_new); PERF_TIMER_START_BP(VERIFY_line_62); // PAPER LINE 62 - rct::addKeys(Z0, Z0, rct::scalarmultKey(rct::addKeys(rct::scalarmult8(proof.A), rct::scalarmultKey(proof8_S, x)), weight)); + multiexp_data.emplace_back(weight_z, proof8_A); + sc_mul(tmp.bytes, x.bytes, weight_z.bytes); + multiexp_data.emplace_back(tmp, proof8_S); PERF_TIMER_STOP(VERIFY_line_62); // Compute the number of rounds for the inner product @@ -909,8 +891,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes); } - sc_muladd(z4[i].bytes, g_scalar.bytes, weight.bytes, z4[i].bytes); - sc_muladd(z5[i].bytes, h_scalar.bytes, weight.bytes, z5[i].bytes); + sc_muladd(z4[i].bytes, g_scalar.bytes, weight_z.bytes, z4[i].bytes); + sc_muladd(z5[i].bytes, h_scalar.bytes, weight_z.bytes, z5[i].bytes); if (i == 0) { @@ -928,55 +910,43 @@ bool bulletproof_VERIFY(const std::vector &proofs) // PAPER LINE 26 PERF_TIMER_START_BP(VERIFY_line_26_new); - multiexp_data.clear(); - multiexp_data.reserve(2*rounds); - - sc_muladd(z1.bytes, proof.mu.bytes, weight.bytes, z1.bytes); + sc_muladd(z1.bytes, proof.mu.bytes, weight_z.bytes, z1.bytes); for (size_t i = 0; i < rounds; ++i) { sc_mul(tmp.bytes, w[i].bytes, w[i].bytes); + sc_mul(tmp.bytes, tmp.bytes, weight_z.bytes); multiexp_data.emplace_back(tmp, proof8_L[i]); sc_mul(tmp.bytes, winv[i].bytes, winv[i].bytes); + sc_mul(tmp.bytes, tmp.bytes, weight_z.bytes); multiexp_data.emplace_back(tmp, proof8_R[i]); } - rct::key acc = multiexp(multiexp_data, false); - rct::addKeys(Z2, Z2, rct::scalarmultKey(acc, weight)); sc_mulsub(tmp.bytes, proof.a.bytes, proof.b.bytes, proof.t.bytes); sc_mul(tmp.bytes, tmp.bytes, x_ip.bytes); - sc_muladd(z3.bytes, tmp.bytes, weight.bytes, z3.bytes); + sc_muladd(z3.bytes, tmp.bytes, weight_z.bytes, z3.bytes); PERF_TIMER_STOP(VERIFY_line_26_new); } // now check all proofs at once PERF_TIMER_START_BP(VERIFY_step2_check); - ge_p3 check1; - ge_double_scalarmult_base_vartime_p3(&check1, y1.bytes, &ge_p3_H, y0.bytes); - sub_acc_p3(&check1, Y2); - if (!ge_p3_is_point_at_infinity(&check1)) - { - MERROR("Verification failure at step 1"); - return false; - } - ge_p3 check2; - sc_sub(tmp.bytes, rct::zero().bytes, z1.bytes); - ge_double_scalarmult_base_vartime_p3(&check2, z3.bytes, &ge_p3_H, tmp.bytes); - add_acc_p3(&check2, Z0); - - std::vector multiexp_data; - multiexp_data.reserve(2 * maxMN); + sc_sub(tmp.bytes, rct::zero().bytes, y0.bytes); + sc_sub(tmp.bytes, tmp.bytes, z1.bytes); + multiexp_data.emplace_back(tmp, rct::G); + sc_sub(tmp.bytes, z3.bytes, y1.bytes); + multiexp_data.emplace_back(tmp, rct::H); for (size_t i = 0; i < maxMN; ++i) { - multiexp_data.emplace_back(z4[i], Gi_p3[i]); - multiexp_data.emplace_back(z5[i], Hi_p3[i]); + sc_sub(tmp.bytes, rct::zero().bytes, z4[i].bytes); + multiexp_data.emplace_back(tmp, Gi_p3[i]); + sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes); + multiexp_data.emplace_back(tmp, Hi_p3[i]); } - sub_acc_p3(&check2, multiexp(multiexp_data, true)); - PERF_TIMER_STOP(VERIFY_step2_check); - - if (!ge_p3_is_point_at_infinity(&check2)) + if (!(multiexp(multiexp_data, false) == rct::identity())) { - MERROR("Verification failure at step 2"); + PERF_TIMER_STOP(VERIFY_step2_check); + MERROR("Verification failure"); return false; } + PERF_TIMER_STOP(VERIFY_step2_check); PERF_TIMER_STOP(VERIFY); return true; From 8629a42cf6e4650b552925f7637761b8e7ee66e3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 22 Aug 2018 22:30:14 +0000 Subject: [PATCH 0167/1007] bulletproofs: rework flow to use sarang's fast batch inversion code --- src/ringct/bulletproofs.cc | 233 ++++++++++++++++++++++++------------- 1 file changed, 155 insertions(+), 78 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 549e52296..d9961cb20 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -29,8 +29,6 @@ // Adapted from Java code by Sarang Noether #include -#include -#include #include #include "misc_log_ex.h" #include "common/perf_timer.h" @@ -289,37 +287,59 @@ static rct::keyV vector_dup(const rct::key &x, size_t N) return rct::keyV(N, x); } -static rct::key switch_endianness(rct::key k) +static rct::key sm(rct::key y, int n, const rct::key &x) { - std::reverse(k.bytes, k.bytes + sizeof(k)); - return k; + while (n--) + sc_mul(y.bytes, y.bytes, y.bytes); + sc_mul(y.bytes, y.bytes, x.bytes); + return y; } -/* Compute the inverse of a scalar, the stupid way */ +/* Compute the inverse of a scalar, the clever way */ static rct::key invert(const rct::key &x) { - rct::key inv; - - BN_CTX *ctx = BN_CTX_new(); - BIGNUM *X = BN_new(); - BIGNUM *L = BN_new(); - BIGNUM *I = BN_new(); - - BN_bin2bn(switch_endianness(x).bytes, sizeof(rct::key), X); - BN_bin2bn(switch_endianness(rct::curveOrder()).bytes, sizeof(rct::key), L); - - CHECK_AND_ASSERT_THROW_MES(BN_mod_inverse(I, X, L, ctx), "Failed to invert"); + rct::key _1, _10, _100, _11, _101, _111, _1001, _1011, _1111; + + _1 = x; + sc_mul(_10.bytes, _1.bytes, _1.bytes); + sc_mul(_100.bytes, _10.bytes, _10.bytes); + sc_mul(_11.bytes, _10.bytes, _1.bytes); + sc_mul(_101.bytes, _10.bytes, _11.bytes); + sc_mul(_111.bytes, _10.bytes, _101.bytes); + sc_mul(_1001.bytes, _10.bytes, _111.bytes); + sc_mul(_1011.bytes, _10.bytes, _1001.bytes); + sc_mul(_1111.bytes, _100.bytes, _1011.bytes); - const int len = BN_num_bytes(I); - CHECK_AND_ASSERT_THROW_MES((size_t)len <= sizeof(rct::key), "Invalid number length"); - inv = rct::zero(); - BN_bn2bin(I, inv.bytes); - std::reverse(inv.bytes, inv.bytes + len); - - BN_free(I); - BN_free(L); - BN_free(X); - BN_CTX_free(ctx); + rct::key inv; + sc_mul(inv.bytes, _1111.bytes, _1.bytes); + + inv = sm(inv, 123 + 3, _101); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 4, _1001); + inv = sm(inv, 2, _11); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 1 + 3, _101); + inv = sm(inv, 3 + 3, _101); + inv = sm(inv, 3, _111); + inv = sm(inv, 1 + 4, _1111); + inv = sm(inv, 2 + 3, _111); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 2 + 4, _1011); + inv = sm(inv, 6 + 4, _1001); + inv = sm(inv, 2 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 3 + 2, _11); + inv = sm(inv, 1 + 4, _1001); + inv = sm(inv, 1 + 3, _111); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 1 + 4, _1011); + inv = sm(inv, 3, _101); + inv = sm(inv, 2 + 4, _1111); + inv = sm(inv, 3, _101); + inv = sm(inv, 1 + 2, _11); #ifdef DEBUG_BP rct::key tmp; @@ -329,6 +349,34 @@ static rct::key invert(const rct::key &x) return inv; } +static rct::keyV invert(rct::keyV x) +{ + rct::keyV scratch; + scratch.reserve(x.size()); + + rct::key acc = rct::identity(); + for (size_t n = 0; n < x.size(); ++n) + { + scratch.push_back(acc); + if (n == 0) + acc = x[0]; + else + sc_mul(acc.bytes, acc.bytes, x[n].bytes); + } + + acc = invert(acc); + + rct::key tmp; + for (int i = x.size(); i-- > 0; ) + { + sc_mul(tmp.bytes, acc.bytes, x[i].bytes); + sc_mul(x[i].bytes, acc.bytes, scratch[i].bytes); + acc = tmp; + } + + return x; +} + /* Compute the slice of a vector */ static rct::keyV slice(const rct::keyV &a, size_t start, size_t stop) { @@ -702,6 +750,13 @@ Bulletproof bulletproof_PROVE(const std::vector &v, const rct::keyV &g return bulletproof_PROVE(sv, gamma); } +struct proof_data_t +{ + rct::key x, y, z, x_ip; + std::vector w; + size_t logM, inv_offset; +}; + /* Given a range proof, determine if it is valid */ bool bulletproof_VERIFY(const std::vector &proofs) { @@ -709,9 +764,17 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY); + const size_t logN = 6; + const size_t N = 1 << logN; + // sanity and figure out which proof is longest size_t max_length = 0; size_t nV = 0; + std::vector proof_data; + proof_data.reserve(proofs.size()); + size_t inv_offset = 0; + std::vector to_invert; + to_invert.reserve(11 * sizeof(proofs)); for (const Bulletproof *p: proofs) { const Bulletproof &proof = *p; @@ -729,46 +792,75 @@ bool bulletproof_VERIFY(const std::vector &proofs) max_length = std::max(max_length, proof.L.size()); nV += proof.V.size(); + + // Reconstruct the challenges + PERF_TIMER_START_BP(VERIFY_start); + proof_data.resize(proof_data.size() + 1); + proof_data_t &pd = proof_data.back(); + rct::key hash_cache = rct::hash_to_scalar(proof.V); + pd.y = hash_cache_mash(hash_cache, proof.A, proof.S); + CHECK_AND_ASSERT_MES(!(pd.y == rct::zero()), false, "y == 0"); + pd.z = hash_cache = rct::hash_to_scalar(pd.y); + CHECK_AND_ASSERT_MES(!(pd.z == rct::zero()), false, "z == 0"); + pd.x = hash_cache_mash(hash_cache, pd.z, proof.T1, proof.T2); + CHECK_AND_ASSERT_MES(!(pd.x == rct::zero()), false, "x == 0"); + pd.x_ip = hash_cache_mash(hash_cache, pd.x, proof.taux, proof.mu, proof.t); + CHECK_AND_ASSERT_MES(!(pd.x_ip == rct::zero()), false, "x_ip == 0"); + PERF_TIMER_STOP(VERIFY_start); + + size_t M; + for (pd.logM = 0; (M = 1< 0, false, "Zero rounds"); + + PERF_TIMER_START_BP(VERIFY_line_21_22); + // PAPER LINES 21-22 + // The inner product challenges are computed per round + pd.w.resize(rounds); + for (size_t i = 0; i < rounds; ++i) + { + pd.w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]); + CHECK_AND_ASSERT_MES(!(pd.w[i] == rct::zero()), false, "w[i] == 0"); + } + PERF_TIMER_STOP(VERIFY_line_21_22); + + pd.inv_offset = inv_offset; + for (size_t i = 0; i < rounds; ++i) + to_invert.push_back(pd.w[i]); + to_invert.push_back(pd.y); + inv_offset += rounds + 1; } CHECK_AND_ASSERT_MES(max_length < 32, false, "At least one proof is too large"); size_t maxMN = 1u << max_length; - const size_t logN = 6; - const size_t N = 1 << logN; rct::key tmp; std::vector multiexp_data; multiexp_data.reserve(nV + (2 * (10/*logM*/ + logN) + 4) * proofs.size() + 2 * maxMN); + PERF_TIMER_START_BP(VERIFY_line_24_25_invert); + const std::vector inverses = invert(to_invert); + PERF_TIMER_STOP(VERIFY_line_24_25_invert); + // setup weighted aggregates rct::key z1 = rct::zero(); rct::key z3 = rct::zero(); rct::keyV z4(maxMN, rct::zero()), z5(maxMN, rct::zero()); rct::key y0 = rct::zero(), y1 = rct::zero(); + int proof_data_index = 0; for (const Bulletproof *p: proofs) { const Bulletproof &proof = *p; + const proof_data_t &pd = proof_data[proof_data_index++]; - size_t M, logM; - for (logM = 0; (M = 1< &proofs) // PAPER LINE 61 sc_muladd(y0.bytes, proof.taux.bytes, weight_y.bytes, y0.bytes); - const rct::keyV zpow = vector_powers(z, M+3); + const rct::keyV zpow = vector_powers(pd.z, M+3); rct::key k; - const rct::key ip1y = vector_power_sum(y, MN); + const rct::key ip1y = vector_power_sum(pd.y, MN); sc_mulsub(k.bytes, zpow[2].bytes, ip1y.bytes, rct::zero().bytes); for (size_t j = 1; j <= M; ++j) { @@ -795,7 +887,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_STOP(VERIFY_line_61); PERF_TIMER_START_BP(VERIFY_line_61rl_new); - sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes); + sc_muladd(tmp.bytes, pd.z.bytes, ip1y.bytes, k.bytes); sc_sub(tmp.bytes, proof.t.bytes, tmp.bytes); sc_muladd(y1.bytes, tmp.bytes, weight_y.bytes, y1.bytes); for (size_t j = 0; j < proof8_V.size(); j++) @@ -803,10 +895,10 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mul(tmp.bytes, zpow[j+2].bytes, weight_y.bytes); multiexp_data.emplace_back(tmp, proof8_V[j]); } - sc_mul(tmp.bytes, x.bytes, weight_y.bytes); + sc_mul(tmp.bytes, pd.x.bytes, weight_y.bytes); multiexp_data.emplace_back(tmp, proof8_T1); rct::key xsq; - sc_mul(xsq.bytes, x.bytes, x.bytes); + sc_mul(xsq.bytes, pd.x.bytes, pd.x.bytes); sc_mul(tmp.bytes, xsq.bytes, weight_y.bytes); multiexp_data.emplace_back(tmp, proof8_T2); PERF_TIMER_STOP(VERIFY_line_61rl_new); @@ -814,49 +906,34 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_line_62); // PAPER LINE 62 multiexp_data.emplace_back(weight_z, proof8_A); - sc_mul(tmp.bytes, x.bytes, weight_z.bytes); + sc_mul(tmp.bytes, pd.x.bytes, weight_z.bytes); multiexp_data.emplace_back(tmp, proof8_S); PERF_TIMER_STOP(VERIFY_line_62); // Compute the number of rounds for the inner product - const size_t rounds = logM+logN; + const size_t rounds = pd.logM+logN; CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); - PERF_TIMER_START_BP(VERIFY_line_21_22); - // PAPER LINES 21-22 - // The inner product challenges are computed per round - rct::keyV w(rounds); - for (size_t i = 0; i < rounds; ++i) - { - w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]); - CHECK_AND_ASSERT_MES(!(w[i] == rct::zero()), false, "w[i] == 0"); - } - PERF_TIMER_STOP(VERIFY_line_21_22); - PERF_TIMER_START_BP(VERIFY_line_24_25); // Basically PAPER LINES 24-25 // Compute the curvepoints from G[i] and H[i] rct::key yinvpow = rct::identity(); rct::key ypow = rct::identity(); - PERF_TIMER_START_BP(VERIFY_line_24_25_invert); - const rct::key yinv = invert(y); - rct::keyV winv(rounds); - for (size_t i = 0; i < rounds; ++i) - winv[i] = invert(w[i]); - PERF_TIMER_STOP(VERIFY_line_24_25_invert); + const rct::key *winv = &inverses[pd.inv_offset]; + const rct::key yinv = inverses[pd.inv_offset + rounds]; // precalc PERF_TIMER_START_BP(VERIFY_line_24_25_precalc); rct::keyV w_cache(1< 0; --s) { - sc_mul(w_cache[s].bytes, w_cache[s/2].bytes, w[j].bytes); + sc_mul(w_cache[s].bytes, w_cache[s/2].bytes, pd.w[j].bytes); sc_mul(w_cache[s-1].bytes, w_cache[s/2].bytes, winv[j].bytes); } } @@ -876,18 +953,18 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mul(h_scalar.bytes, h_scalar.bytes, w_cache[(~i) & (MN-1)].bytes); // Adjust the scalars using the exponents from PAPER LINE 62 - sc_add(g_scalar.bytes, g_scalar.bytes, z.bytes); + sc_add(g_scalar.bytes, g_scalar.bytes, pd.z.bytes); CHECK_AND_ASSERT_MES(2+i/N < zpow.size(), false, "invalid zpow index"); CHECK_AND_ASSERT_MES(i%N < twoN.size(), false, "invalid twoN index"); sc_mul(tmp.bytes, zpow[2+i/N].bytes, twoN[i%N].bytes); if (i == 0) { - sc_add(tmp.bytes, tmp.bytes, z.bytes); + sc_add(tmp.bytes, tmp.bytes, pd.z.bytes); sc_sub(h_scalar.bytes, h_scalar.bytes, tmp.bytes); } else { - sc_muladd(tmp.bytes, z.bytes, ypow.bytes, tmp.bytes); + sc_muladd(tmp.bytes, pd.z.bytes, ypow.bytes, tmp.bytes); sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes); } @@ -897,12 +974,12 @@ bool bulletproof_VERIFY(const std::vector &proofs) if (i == 0) { yinvpow = yinv; - ypow = y; + ypow = pd.y; } else if (i != MN-1) { sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); - sc_mul(ypow.bytes, ypow.bytes, y.bytes); + sc_mul(ypow.bytes, ypow.bytes, pd.y.bytes); } } @@ -913,7 +990,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_muladd(z1.bytes, proof.mu.bytes, weight_z.bytes, z1.bytes); for (size_t i = 0; i < rounds; ++i) { - sc_mul(tmp.bytes, w[i].bytes, w[i].bytes); + sc_mul(tmp.bytes, pd.w[i].bytes, pd.w[i].bytes); sc_mul(tmp.bytes, tmp.bytes, weight_z.bytes); multiexp_data.emplace_back(tmp, proof8_L[i]); sc_mul(tmp.bytes, winv[i].bytes, winv[i].bytes); @@ -921,7 +998,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) multiexp_data.emplace_back(tmp, proof8_R[i]); } sc_mulsub(tmp.bytes, proof.a.bytes, proof.b.bytes, proof.t.bytes); - sc_mul(tmp.bytes, tmp.bytes, x_ip.bytes); + sc_mul(tmp.bytes, tmp.bytes, pd.x_ip.bytes); sc_muladd(z3.bytes, tmp.bytes, weight_z.bytes, z3.bytes); PERF_TIMER_STOP(VERIFY_line_26_new); } From 10e5a9276953ece1f96d6801fe6d91d550c5dfae Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 24 Aug 2018 18:51:14 +0000 Subject: [PATCH 0168/1007] bulletproofs: maintain -z4, -z5, and -y0 to avoid subtractions --- src/ringct/bulletproofs.cc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index d9961cb20..9e4d85534 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -847,8 +847,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) // setup weighted aggregates rct::key z1 = rct::zero(); rct::key z3 = rct::zero(); - rct::keyV z4(maxMN, rct::zero()), z5(maxMN, rct::zero()); - rct::key y0 = rct::zero(), y1 = rct::zero(); + rct::keyV m_z4(maxMN, rct::zero()), m_z5(maxMN, rct::zero()); + rct::key m_y0 = rct::zero(), y1 = rct::zero(); int proof_data_index = 0; for (const Bulletproof *p: proofs) { @@ -872,7 +872,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_line_61); // PAPER LINE 61 - sc_muladd(y0.bytes, proof.taux.bytes, weight_y.bytes, y0.bytes); + sc_mulsub(m_y0.bytes, proof.taux.bytes, weight_y.bytes, m_y0.bytes); const rct::keyV zpow = vector_powers(pd.z, M+3); @@ -968,8 +968,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes); } - sc_muladd(z4[i].bytes, g_scalar.bytes, weight_z.bytes, z4[i].bytes); - sc_muladd(z5[i].bytes, h_scalar.bytes, weight_z.bytes, z5[i].bytes); + sc_mulsub(m_z4[i].bytes, g_scalar.bytes, weight_z.bytes, m_z4[i].bytes); + sc_mulsub(m_z5[i].bytes, h_scalar.bytes, weight_z.bytes, m_z5[i].bytes); if (i == 0) { @@ -1005,17 +1005,14 @@ bool bulletproof_VERIFY(const std::vector &proofs) // now check all proofs at once PERF_TIMER_START_BP(VERIFY_step2_check); - sc_sub(tmp.bytes, rct::zero().bytes, y0.bytes); - sc_sub(tmp.bytes, tmp.bytes, z1.bytes); + sc_sub(tmp.bytes, m_y0.bytes, z1.bytes); multiexp_data.emplace_back(tmp, rct::G); sc_sub(tmp.bytes, z3.bytes, y1.bytes); multiexp_data.emplace_back(tmp, rct::H); for (size_t i = 0; i < maxMN; ++i) { - sc_sub(tmp.bytes, rct::zero().bytes, z4[i].bytes); - multiexp_data.emplace_back(tmp, Gi_p3[i]); - sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes); - multiexp_data.emplace_back(tmp, Hi_p3[i]); + multiexp_data.emplace_back(m_z4[i], Gi_p3[i]); + multiexp_data.emplace_back(m_z5[i], Hi_p3[i]); } if (!(multiexp(multiexp_data, false) == rct::identity())) { From 6f9ae5b6eb535fb748722ed1c81f981474422ead Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 24 Aug 2018 21:20:56 +0000 Subject: [PATCH 0169/1007] multiexp: handle pippenger multiexps with part precalc --- src/ringct/bulletproofs.cc | 21 +++++++++++---------- src/ringct/multiexp.cc | 21 ++++++++++++++------- src/ringct/multiexp.h | 4 ++-- tests/performance_tests/multiexp.h | 4 ++-- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 9e4d85534..a3af9264e 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -73,15 +73,15 @@ static const rct::keyV twoN = vector_powers(TWO, maxN); static const rct::key ip12 = inner_product(oneN, twoN); static boost::mutex init_mutex; -static inline rct::key multiexp(const std::vector &data, bool HiGi) +static inline rct::key multiexp(const std::vector &data, size_t HiGi_size) { - if (HiGi) + if (HiGi_size > 0) { static_assert(128 <= STRAUS_SIZE_LIMIT, "Straus in precalc mode can only be calculated till STRAUS_SIZE_LIMIT"); - return data.size() <= 128 ? straus(data, straus_HiGi_cache, 0) : pippenger(data, pippenger_HiGi_cache, get_pippenger_c(data.size())); + return HiGi_size <= 128 && data.size() == HiGi_size ? straus(data, straus_HiGi_cache, 0) : pippenger(data, pippenger_HiGi_cache, HiGi_size, get_pippenger_c(data.size())); } else - return data.size() <= 64 ? straus(data, NULL, 0) : pippenger(data, NULL, get_pippenger_c(data.size())); + return data.size() <= 64 ? straus(data, NULL, 0) : pippenger(data, NULL, 0, get_pippenger_c(data.size())); } static inline bool is_reduced(const rct::key &scalar) @@ -118,7 +118,7 @@ static void init_exponents() } straus_HiGi_cache = straus_init_cache(data, STRAUS_SIZE_LIMIT); - pippenger_HiGi_cache = pippenger_init_cache(data, PIPPENGER_SIZE_LIMIT); + pippenger_HiGi_cache = pippenger_init_cache(data, 0, PIPPENGER_SIZE_LIMIT); MINFO("Hi/Gi cache size: " << (sizeof(Hi)+sizeof(Gi))/1024 << " kB"); MINFO("Hi_p3/Gi_p3 cache size: " << (sizeof(Hi_p3)+sizeof(Gi_p3))/1024 << " kB"); @@ -142,7 +142,7 @@ static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b) multiexp_data.emplace_back(a[i], Gi_p3[i]); multiexp_data.emplace_back(b[i], Hi_p3[i]); } - return multiexp(multiexp_data, true); + return multiexp(multiexp_data, 2 * a.size()); } /* Compute a custom vector-scalar commitment */ @@ -169,7 +169,7 @@ static rct::key cross_vector_exponent8(size_t size, const std::vector &A, sc_mul(multiexp_data.back().scalar.bytes, extra_scalar->bytes, INV_EIGHT.bytes); multiexp_data.back().point = *extra_point; } - return multiexp(multiexp_data, false); + return multiexp(multiexp_data, 0); } /* Given a scalar, construct a vector of powers */ @@ -839,6 +839,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) std::vector multiexp_data; multiexp_data.reserve(nV + (2 * (10/*logM*/ + logN) + 4) * proofs.size() + 2 * maxMN); + multiexp_data.resize(2 * maxMN); PERF_TIMER_START_BP(VERIFY_line_24_25_invert); const std::vector inverses = invert(to_invert); @@ -1011,10 +1012,10 @@ bool bulletproof_VERIFY(const std::vector &proofs) multiexp_data.emplace_back(tmp, rct::H); for (size_t i = 0; i < maxMN; ++i) { - multiexp_data.emplace_back(m_z4[i], Gi_p3[i]); - multiexp_data.emplace_back(m_z5[i], Hi_p3[i]); + multiexp_data[i * 2] = {m_z4[i], Gi_p3[i]}; + multiexp_data[i * 2 + 1] = {m_z5[i], Hi_p3[i]}; } - if (!(multiexp(multiexp_data, false) == rct::identity())) + if (!(multiexp(multiexp_data, 2 * maxMN) == rct::identity())) { PERF_TIMER_STOP(VERIFY_step2_check); MERROR("Verification failure"); diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index fb2f18551..178f92267 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -564,12 +564,13 @@ struct pippenger_cached_data ~pippenger_cached_data() { aligned_free(cached); } }; -std::shared_ptr pippenger_init_cache(const std::vector &data, size_t N) +std::shared_ptr pippenger_init_cache(const std::vector &data, size_t start_offset, size_t N) { MULTIEXP_PERF(PERF_TIMER_START_UNIT(pippenger_init_cache, 1000000)); + CHECK_AND_ASSERT_THROW_MES(start_offset <= data.size(), "Bad cache base data"); if (N == 0) - N = data.size(); - CHECK_AND_ASSERT_THROW_MES(N <= data.size(), "Bad cache base data"); + N = data.size() - start_offset; + CHECK_AND_ASSERT_THROW_MES(N <= data.size() - start_offset, "Bad cache base data"); ge_cached cached; std::shared_ptr cache(new pippenger_cached_data()); @@ -577,7 +578,7 @@ std::shared_ptr pippenger_init_cache(const std::vectorcached = (ge_cached*)aligned_realloc(cache->cached, N * sizeof(ge_cached), 4096); CHECK_AND_ASSERT_THROW_MES(cache->cached, "Out of memory"); for (size_t i = 0; i < N; ++i) - ge_p3_to_cached(&cache->cached[i], &data[i].point); + ge_p3_to_cached(&cache->cached[i], &data[i+start_offset].point); MULTIEXP_PERF(PERF_TIMER_STOP(pippenger_init_cache)); return cache; @@ -588,9 +589,11 @@ size_t pippenger_get_cache_size(const std::shared_ptr &ca return cache->size * sizeof(*cache->cached); } -rct::key pippenger(const std::vector &data, const std::shared_ptr &cache, size_t c) +rct::key pippenger(const std::vector &data, const std::shared_ptr &cache, size_t cache_size, size_t c) { - CHECK_AND_ASSERT_THROW_MES(cache == NULL || cache->size >= data.size(), "Cache is too small"); + if (cache != NULL && cache_size == 0) + cache_size = cache->size; + CHECK_AND_ASSERT_THROW_MES(cache == NULL || cache_size <= cache->size, "Cache is too small"); if (c == 0) c = get_pippenger_c(data.size()); CHECK_AND_ASSERT_THROW_MES(c <= 9, "c is too large"); @@ -598,6 +601,7 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< ge_p3 result = ge_p3_identity; std::unique_ptr buckets{new ge_p3[1< local_cache = cache == NULL ? pippenger_init_cache(data) : cache; + std::shared_ptr local_cache_2 = data.size() > cache_size ? pippenger_init_cache(data, cache_size) : NULL; rct::key maxscalar = rct::zero(); for (size_t i = 0; i < data.size(); ++i) @@ -641,7 +645,10 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< CHECK_AND_ASSERT_THROW_MES(bucket < (1u<cached[i]); + if (i < cache_size) + add(buckets[bucket], local_cache->cached[i]); + else + add(buckets[bucket], local_cache_2->cached[i - cache_size]); } else buckets[bucket] = data[i].point; diff --git a/src/ringct/multiexp.h b/src/ringct/multiexp.h index 559ab664a..b52707933 100644 --- a/src/ringct/multiexp.h +++ b/src/ringct/multiexp.h @@ -61,10 +61,10 @@ rct::key bos_coster_heap_conv_robust(std::vector data); std::shared_ptr straus_init_cache(const std::vector &data, size_t N =0); size_t straus_get_cache_size(const std::shared_ptr &cache); rct::key straus(const std::vector &data, const std::shared_ptr &cache = NULL, size_t STEP = 0); -std::shared_ptr pippenger_init_cache(const std::vector &data, size_t N =0); +std::shared_ptr pippenger_init_cache(const std::vector &data, size_t start_offset = 0, size_t N =0); size_t pippenger_get_cache_size(const std::shared_ptr &cache); size_t get_pippenger_c(size_t N); -rct::key pippenger(const std::vector &data, const std::shared_ptr &cache = NULL, size_t c = 0); +rct::key pippenger(const std::vector &data, const std::shared_ptr &cache = NULL, size_t cache_size = 0, size_t c = 0); } diff --git a/tests/performance_tests/multiexp.h b/tests/performance_tests/multiexp.h index b8b87b3a6..b6e86ebd4 100644 --- a/tests/performance_tests/multiexp.h +++ b/tests/performance_tests/multiexp.h @@ -78,9 +78,9 @@ class test_multiexp case multiexp_straus_cached: return res == straus(data, straus_cache); case multiexp_pippenger: - return res == pippenger(data, NULL, c); + return res == pippenger(data, NULL, 0, c); case multiexp_pippenger_cached: - return res == pippenger(data, pippenger_cache, c); + return res == pippenger(data, pippenger_cache, 0, c); default: return false; } From 8b4767221c9b0ff3015229b167e5be1331a16c12 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 25 Aug 2018 18:37:21 +0000 Subject: [PATCH 0170/1007] bulletproofs: speedup prover --- src/ringct/bulletproofs.cc | 54 ++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index a3af9264e..f1b821978 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -146,13 +146,14 @@ static rct::key vector_exponent(const rct::keyV &a, const rct::keyV &b) } /* Compute a custom vector-scalar commitment */ -static rct::key cross_vector_exponent8(size_t size, const std::vector &A, size_t Ao, const std::vector &B, size_t Bo, const rct::keyV &a, size_t ao, const rct::keyV &b, size_t bo, const ge_p3 *extra_point, const rct::key *extra_scalar) +static rct::key cross_vector_exponent8(size_t size, const std::vector &A, size_t Ao, const std::vector &B, size_t Bo, const rct::keyV &a, size_t ao, const rct::keyV &b, size_t bo, const rct::keyV *scale, const ge_p3 *extra_point, const rct::key *extra_scalar) { CHECK_AND_ASSERT_THROW_MES(size + Ao <= A.size(), "Incompatible size for A"); CHECK_AND_ASSERT_THROW_MES(size + Bo <= B.size(), "Incompatible size for B"); CHECK_AND_ASSERT_THROW_MES(size + ao <= a.size(), "Incompatible size for a"); CHECK_AND_ASSERT_THROW_MES(size + bo <= b.size(), "Incompatible size for b"); CHECK_AND_ASSERT_THROW_MES(size <= maxN*maxM, "size is too large"); + CHECK_AND_ASSERT_THROW_MES(!scale || size == scale->size() / 2, "Incompatible size for scale"); CHECK_AND_ASSERT_THROW_MES(!!extra_point == !!extra_scalar, "only one of extra point/scalar present"); std::vector multiexp_data; @@ -162,6 +163,8 @@ static rct::key cross_vector_exponent8(size_t size, const std::vector &A, sc_mul(multiexp_data[i*2].scalar.bytes, a[ao+i].bytes, INV_EIGHT.bytes);; multiexp_data[i*2].point = A[Ao+i]; sc_mul(multiexp_data[i*2+1].scalar.bytes, b[bo+i].bytes, INV_EIGHT.bytes); + if (scale) + sc_mul(multiexp_data[i*2+1].scalar.bytes, multiexp_data[i*2+1].scalar.bytes, (*scale)[Bo+i].bytes); multiexp_data[i*2+1].point = B[Bo+i]; } if (extra_point) @@ -232,7 +235,7 @@ static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b) } /* folds a curvepoint array using a two way scaled Hadamard product */ -static void hadamard_fold(std::vector &v, const rct::key &a, const rct::key &b) +static void hadamard_fold(std::vector &v, const rct::keyV *scale, const rct::key &a, const rct::key &b) { CHECK_AND_ASSERT_THROW_MES((v.size() & 1) == 0, "Vector size should be even"); const size_t sz = v.size() / 2; @@ -241,7 +244,10 @@ static void hadamard_fold(std::vector &v, const rct::key &a, const rct::k ge_dsmp c[2]; ge_dsm_precomp(c[0], &v[n]); ge_dsm_precomp(c[1], &v[sz + n]); - ge_double_scalarmult_precomp_vartime2_p3(&v[n], a.bytes, c[0], b.bytes, c[1]); + rct::key sa, sb; + if (scale) sc_mul(sa.bytes, a.bytes, (*scale)[n].bytes); else sa = a; + if (scale) sc_mul(sb.bytes, b.bytes, (*scale)[sz + n].bytes); else sb = b; + ge_double_scalarmult_precomp_vartime2_p3(&v[n], sa.bytes, c[0], sb.bytes, c[1]); } v.resize(sz); } @@ -258,14 +264,24 @@ static rct::keyV vector_add(const rct::keyV &a, const rct::keyV &b) return res; } -/* Subtract two vectors */ -static rct::keyV vector_subtract(const rct::keyV &a, const rct::keyV &b) +/* Add a scalar to all elements of a vector */ +static rct::keyV vector_add(const rct::keyV &a, const rct::key &b) +{ + rct::keyV res(a.size()); + for (size_t i = 0; i < a.size(); ++i) + { + sc_add(res[i].bytes, a[i].bytes, b.bytes); + } + return res; +} + +/* Subtract a scalar from all elements of a vector */ +static rct::keyV vector_subtract(const rct::keyV &a, const rct::key &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::keyV res(a.size()); for (size_t i = 0; i < a.size(); ++i) { - sc_sub(res[i].bytes, a[i].bytes, b[i].bytes); + sc_sub(res[i].bytes, a[i].bytes, b.bytes); } return res; } @@ -549,8 +565,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) } // Polynomial construction by coefficients - const auto zMN = vector_dup(z, MN); - rct::keyV l0 = vector_subtract(aL, zMN); + rct::keyV l0 = vector_subtract(aL, z); const rct::keyV &l1 = sL; // This computes the ugly sum/concatenation from PAPER LINE 65 @@ -570,7 +585,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) } } - rct::keyV r0 = vector_add(aR, zMN); + rct::keyV r0 = vector_add(aR, z); const auto yMN = vector_powers(y, MN); r0 = hadamard(r0, yMN); r0 = vector_add(r0, zero_twos); @@ -658,12 +673,15 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::keyV aprime(MN); rct::keyV bprime(MN); const rct::key yinv = invert(y); - rct::key yinvpow = rct::identity(); + rct::keyV yinvpow(MN); + yinvpow[0] = rct::identity(); + yinvpow[1] = yinv; for (size_t i = 0; i < MN; ++i) { Gprime[i] = Gi_p3[i]; - ge_scalarmult_p3(&Hprime[i], yinvpow.bytes, &Hi_p3[i]); - sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); + Hprime[i] = Hi_p3[i]; + if (i > 1) + sc_mul(yinvpow[i].bytes, yinvpow[i-1].bytes, yinv.bytes); aprime[i] = l[i]; bprime[i] = r[i]; } @@ -675,6 +693,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) PERF_TIMER_START_BP(PROVE_step4); // PAPER LINE 13 + const rct::keyV *scale = &yinvpow; while (nprime > 1) { // PAPER LINE 15 @@ -689,9 +708,9 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) // PAPER LINES 18-19 PERF_TIMER_START_BP(PROVE_LR); sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); - L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, &ge_p3_H, &tmp); + L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, scale, &ge_p3_H, &tmp); sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); - R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, &ge_p3_H, &tmp); + R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, scale, &ge_p3_H, &tmp); PERF_TIMER_STOP(PROVE_LR); // PAPER LINES 21-22 @@ -708,8 +727,8 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if (nprime > 1) { PERF_TIMER_START_BP(PROVE_hadamard2); - hadamard_fold(Gprime, winv, w[round]); - hadamard_fold(Hprime, w[round], winv); + hadamard_fold(Gprime, NULL, winv, w[round]); + hadamard_fold(Hprime, scale, w[round], winv); PERF_TIMER_STOP(PROVE_hadamard2); } @@ -719,6 +738,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round])); PERF_TIMER_STOP(PROVE_prime); + scale = NULL; ++round; } PERF_TIMER_STOP(PROVE_step4); From a110e6aa18928fb0bc13d0e39c854aea9e99e96d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 27 Aug 2018 13:23:57 +0000 Subject: [PATCH 0171/1007] multiexp: tune which variants to use for which number of points --- src/ringct/bulletproofs.cc | 8 ++++---- src/ringct/multiexp.cc | 36 ++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index f1b821978..4e1c940d1 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -48,7 +48,7 @@ extern "C" #define PERF_TIMER_START_BP(x) PERF_TIMER_START_UNIT(x, 1000000) -#define STRAUS_SIZE_LIMIT 128 +#define STRAUS_SIZE_LIMIT 232 #define PIPPENGER_SIZE_LIMIT 0 namespace rct @@ -77,11 +77,11 @@ static inline rct::key multiexp(const std::vector &data, size_t Hi { if (HiGi_size > 0) { - static_assert(128 <= STRAUS_SIZE_LIMIT, "Straus in precalc mode can only be calculated till STRAUS_SIZE_LIMIT"); - return HiGi_size <= 128 && data.size() == HiGi_size ? straus(data, straus_HiGi_cache, 0) : pippenger(data, pippenger_HiGi_cache, HiGi_size, get_pippenger_c(data.size())); + static_assert(232 <= STRAUS_SIZE_LIMIT, "Straus in precalc mode can only be calculated till STRAUS_SIZE_LIMIT"); + return HiGi_size <= 232 && data.size() == HiGi_size ? straus(data, straus_HiGi_cache, 0) : pippenger(data, pippenger_HiGi_cache, HiGi_size, get_pippenger_c(data.size())); } else - return data.size() <= 64 ? straus(data, NULL, 0) : pippenger(data, NULL, 0, get_pippenger_c(data.size())); + return data.size() <= 95 ? straus(data, NULL, 0) : pippenger(data, NULL, 0, get_pippenger_c(data.size())); } static inline bool is_reduced(const rct::key &scalar) diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index 178f92267..85b1dfed4 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -79,6 +79,25 @@ extern "C" // Best/cached Straus Straus Straus Straus Straus Straus Straus Straus Pip Pip Pip Pip // Best/uncached Straus Straus Straus Straus Straus Straus Pip Pip Pip Pip Pip Pip +// New timings: +// Pippenger: +// 2/1 always +// 3/2 at ~13 +// 4/3 at ~29 +// 5/4 at ~83 +// 6/5 < 200 +// 7/6 at ~470 +// 8/7 at ~1180 +// 9/8 at ~2290 +// Cached Pippenger: +// 6/5 < 200 +// 7/6 at 460 +// 8/7 at 1180 +// 9/8 at 2300 +// +// Cached Straus/Pippenger cross at 232 +// + namespace rct { @@ -543,16 +562,13 @@ rct::key straus(const std::vector &data, const std::shared_ptr Date: Sat, 1 Sep 2018 17:46:34 +0000 Subject: [PATCH 0172/1007] bulletproofs: only enable profiling on request --- src/ringct/bulletproofs.cc | 62 +++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 4e1c940d1..bed48769a 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -46,7 +46,13 @@ extern "C" //#define DEBUG_BP +#if 1 #define PERF_TIMER_START_BP(x) PERF_TIMER_START_UNIT(x, 1000000) +#define PERF_TIMER_STOP_BP(x) PERF_TIMER_STOP(x) +#else +#define PERF_TIMER_START_BP(x) ((void*)0) +#define PERF_TIMER_STOP_BP(x) ((void*)0) +#endif #define STRAUS_SIZE_LIMIT 232 #define PIPPENGER_SIZE_LIMIT 0 @@ -486,7 +492,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) sc_mul(sv8.bytes, sv[i].bytes, INV_EIGHT.bytes); rct::addKeys2(V[i], gamma8, sv8, rct::H); } - PERF_TIMER_STOP(PROVE_v); + PERF_TIMER_STOP_BP(PROVE_v); PERF_TIMER_START_BP(PROVE_aLaR); for (size_t j = 0; j < M; ++j) @@ -507,7 +513,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) } } } - PERF_TIMER_STOP(PROVE_aLaR); + PERF_TIMER_STOP_BP(PROVE_aLaR); // DEBUG: Test to ensure this recovers the value #ifdef DEBUG_BP @@ -552,14 +558,14 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::key y = hash_cache_mash(hash_cache, A, S); if (y == rct::zero()) { - PERF_TIMER_STOP(PROVE_step1); + PERF_TIMER_STOP_BP(PROVE_step1); MINFO("y is 0, trying again"); goto try_again; } rct::key z = hash_cache = rct::hash_to_scalar(y); if (z == rct::zero()) { - PERF_TIMER_STOP(PROVE_step1); + PERF_TIMER_STOP_BP(PROVE_step1); MINFO("z is 0, trying again"); goto try_again; } @@ -598,7 +604,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) sc_add(t1.bytes, t1_1.bytes, t1_2.bytes); rct::key t2 = inner_product(l1, r1); - PERF_TIMER_STOP(PROVE_step1); + PERF_TIMER_STOP_BP(PROVE_step1); PERF_TIMER_START_BP(PROVE_step2); // PAPER LINES 47-48 @@ -619,7 +625,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::key x = hash_cache_mash(hash_cache, z, T1, T2); if (x == rct::zero()) { - PERF_TIMER_STOP(PROVE_step2); + PERF_TIMER_STOP_BP(PROVE_step2); MINFO("x is 0, trying again"); goto try_again; } @@ -643,7 +649,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) l = vector_add(l, vector_scalar(l1, x)); rct::keyV r = r0; r = vector_add(r, vector_scalar(r1, x)); - PERF_TIMER_STOP(PROVE_step2); + PERF_TIMER_STOP_BP(PROVE_step2); PERF_TIMER_START_BP(PROVE_step3); rct::key t = inner_product(l, r); @@ -661,7 +667,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t); if (x_ip == rct::zero()) { - PERF_TIMER_STOP(PROVE_step3); + PERF_TIMER_STOP_BP(PROVE_step3); MINFO("x_ip is 0, trying again"); goto try_again; } @@ -689,7 +695,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) rct::keyV R(logMN); int round = 0; rct::keyV w(logMN); // this is the challenge x in the inner product protocol - PERF_TIMER_STOP(PROVE_step3); + PERF_TIMER_STOP_BP(PROVE_step3); PERF_TIMER_START_BP(PROVE_step4); // PAPER LINE 13 @@ -703,7 +709,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) PERF_TIMER_START_BP(PROVE_inner_product); rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); - PERF_TIMER_STOP(PROVE_inner_product); + PERF_TIMER_STOP_BP(PROVE_inner_product); // PAPER LINES 18-19 PERF_TIMER_START_BP(PROVE_LR); @@ -711,13 +717,13 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, scale, &ge_p3_H, &tmp); sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, scale, &ge_p3_H, &tmp); - PERF_TIMER_STOP(PROVE_LR); + PERF_TIMER_STOP_BP(PROVE_LR); // PAPER LINES 21-22 w[round] = hash_cache_mash(hash_cache, L[round], R[round]); if (w[round] == rct::zero()) { - PERF_TIMER_STOP(PROVE_step4); + PERF_TIMER_STOP_BP(PROVE_step4); MINFO("w[round] is 0, trying again"); goto try_again; } @@ -729,19 +735,19 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) PERF_TIMER_START_BP(PROVE_hadamard2); hadamard_fold(Gprime, NULL, winv, w[round]); hadamard_fold(Hprime, scale, w[round], winv); - PERF_TIMER_STOP(PROVE_hadamard2); + PERF_TIMER_STOP_BP(PROVE_hadamard2); } // PAPER LINES 28-29 PERF_TIMER_START_BP(PROVE_prime); aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round])); - PERF_TIMER_STOP(PROVE_prime); + PERF_TIMER_STOP_BP(PROVE_prime); scale = NULL; ++round; } - PERF_TIMER_STOP(PROVE_step4); + PERF_TIMER_STOP_BP(PROVE_step4); // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20) return Bulletproof(std::move(V), A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t); @@ -766,7 +772,7 @@ Bulletproof bulletproof_PROVE(const std::vector &v, const rct::keyV &g sv[i].bytes[6] = (v[i] >> 48) & 255; sv[i].bytes[7] = (v[i] >> 56) & 255; } - PERF_TIMER_STOP(PROVE_v); + PERF_TIMER_STOP_BP(PROVE_v); return bulletproof_PROVE(sv, gamma); } @@ -826,7 +832,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) CHECK_AND_ASSERT_MES(!(pd.x == rct::zero()), false, "x == 0"); pd.x_ip = hash_cache_mash(hash_cache, pd.x, proof.taux, proof.mu, proof.t); CHECK_AND_ASSERT_MES(!(pd.x_ip == rct::zero()), false, "x_ip == 0"); - PERF_TIMER_STOP(VERIFY_start); + PERF_TIMER_STOP_BP(VERIFY_start); size_t M; for (pd.logM = 0; (M = 1< &proofs) pd.w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]); CHECK_AND_ASSERT_MES(!(pd.w[i] == rct::zero()), false, "w[i] == 0"); } - PERF_TIMER_STOP(VERIFY_line_21_22); + PERF_TIMER_STOP_BP(VERIFY_line_21_22); pd.inv_offset = inv_offset; for (size_t i = 0; i < rounds; ++i) @@ -863,7 +869,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_line_24_25_invert); const std::vector inverses = invert(to_invert); - PERF_TIMER_STOP(VERIFY_line_24_25_invert); + PERF_TIMER_STOP_BP(VERIFY_line_24_25_invert); // setup weighted aggregates rct::key z1 = rct::zero(); @@ -905,7 +911,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) CHECK_AND_ASSERT_MES(j+2 < zpow.size(), false, "invalid zpow index"); sc_mulsub(k.bytes, zpow[j+2].bytes, ip12.bytes, k.bytes); } - PERF_TIMER_STOP(VERIFY_line_61); + PERF_TIMER_STOP_BP(VERIFY_line_61); PERF_TIMER_START_BP(VERIFY_line_61rl_new); sc_muladd(tmp.bytes, pd.z.bytes, ip1y.bytes, k.bytes); @@ -922,14 +928,14 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mul(xsq.bytes, pd.x.bytes, pd.x.bytes); sc_mul(tmp.bytes, xsq.bytes, weight_y.bytes); multiexp_data.emplace_back(tmp, proof8_T2); - PERF_TIMER_STOP(VERIFY_line_61rl_new); + PERF_TIMER_STOP_BP(VERIFY_line_61rl_new); PERF_TIMER_START_BP(VERIFY_line_62); // PAPER LINE 62 multiexp_data.emplace_back(weight_z, proof8_A); sc_mul(tmp.bytes, pd.x.bytes, weight_z.bytes); multiexp_data.emplace_back(tmp, proof8_S); - PERF_TIMER_STOP(VERIFY_line_62); + PERF_TIMER_STOP_BP(VERIFY_line_62); // Compute the number of rounds for the inner product const size_t rounds = pd.logM+logN; @@ -958,7 +964,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mul(w_cache[s-1].bytes, w_cache[s/2].bytes, winv[j].bytes); } } - PERF_TIMER_STOP(VERIFY_line_24_25_precalc); + PERF_TIMER_STOP_BP(VERIFY_line_24_25_precalc); for (size_t i = 0; i < MN; ++i) { @@ -1004,7 +1010,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) } } - PERF_TIMER_STOP(VERIFY_line_24_25); + PERF_TIMER_STOP_BP(VERIFY_line_24_25); // PAPER LINE 26 PERF_TIMER_START_BP(VERIFY_line_26_new); @@ -1021,7 +1027,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mulsub(tmp.bytes, proof.a.bytes, proof.b.bytes, proof.t.bytes); sc_mul(tmp.bytes, tmp.bytes, pd.x_ip.bytes); sc_muladd(z3.bytes, tmp.bytes, weight_z.bytes, z3.bytes); - PERF_TIMER_STOP(VERIFY_line_26_new); + PERF_TIMER_STOP_BP(VERIFY_line_26_new); } // now check all proofs at once @@ -1037,13 +1043,13 @@ bool bulletproof_VERIFY(const std::vector &proofs) } if (!(multiexp(multiexp_data, 2 * maxMN) == rct::identity())) { - PERF_TIMER_STOP(VERIFY_step2_check); + PERF_TIMER_STOP_BP(VERIFY_step2_check); MERROR("Verification failure"); return false; } - PERF_TIMER_STOP(VERIFY_step2_check); + PERF_TIMER_STOP_BP(VERIFY_step2_check); - PERF_TIMER_STOP(VERIFY); + PERF_TIMER_STOP_BP(VERIFY); return true; } From 74fb3d882c9a50798795367ca8cd5dac85138c78 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 22 Oct 2018 11:56:45 +0000 Subject: [PATCH 0173/1007] multiexp: some minor speedups --- src/ringct/multiexp.cc | 48 ++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index 85b1dfed4..6f77fed34 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -473,10 +473,7 @@ rct::key straus(const std::vector &data, const std::shared_ptr &data, const std::shared_ptr> 4; } #elif 1 + unsigned char bytes33[33]; + memcpy(bytes33, data[j].scalar.bytes, 32); + bytes33[32] = 0; + bytes = bytes33; for (size_t i = 0; i < 256; ++i) digits[j*256+i] = ((bytes[i>>3] | (bytes[(i>>3)+1]<<8)) >> (i&7)) & mask; #else @@ -615,7 +616,9 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< CHECK_AND_ASSERT_THROW_MES(c <= 9, "c is too large"); ge_p3 result = ge_p3_identity; + bool result_init = false; std::unique_ptr buckets{new ge_p3[1< local_cache = cache == NULL ? pippenger_init_cache(data) : cache; std::shared_ptr local_cache_2 = data.size() > cache_size ? pippenger_init_cache(data, cache_size) : NULL; @@ -632,7 +635,7 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< for (size_t k = groups; k-- > 0; ) { - if (!ge_p3_is_point_at_infinity(&result)) + if (result_init) { ge_p2 p2; ge_p3_to_p2(&p2, &result); @@ -646,8 +649,7 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< ge_p1p1_to_p2(&p2, &p1); } } - for (size_t i = 0; i < (1u< &data, const std::shared_ptr< if (bucket == 0) continue; CHECK_AND_ASSERT_THROW_MES(bucket < (1u<cached[i]); @@ -667,17 +669,37 @@ rct::key pippenger(const std::vector &data, const std::shared_ptr< add(buckets[bucket], local_cache_2->cached[i - cache_size]); } else + { buckets[bucket] = data[i].point; + buckets_init[bucket] = true; + } } // sum the buckets - ge_p3 pail = ge_p3_identity; + ge_p3 pail; + bool pail_init = false; for (size_t i = (1< 0; --i) { - if (!ge_p3_is_point_at_infinity(&buckets[i])) - add(pail, buckets[i]); - if (!ge_p3_is_point_at_infinity(&pail)) - add(result, pail); + if (buckets_init[i]) + { + if (pail_init) + add(pail, buckets[i]); + else + { + pail = buckets[i]; + pail_init = true; + } + } + if (pail_init) + { + if (result_init) + add(result, pail); + else + { + result = pail; + result_init = true; + } + } } } From 9da67502d54ce9568d6d4878eaec98a7447b8a17 Mon Sep 17 00:00:00 2001 From: Riccardo Spagni Date: Mon, 22 Oct 2018 23:12:23 +0200 Subject: [PATCH 0174/1007] update readme for 0.13.0.4 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5da96371a..601cce544 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ invokes cmake commands as needed. * Change to the root of the source code directory, change to the most recent release branch, and build: cd monero - git checkout v0.13.0.0 + git checkout v0.13.0.4 make *Optional*: If your machine has several cores and enough memory, enable @@ -241,7 +241,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch ( ``` git clone https://github.com/monero-project/monero.git cd monero - git checkout tags/v0.13.0.0 + git checkout tags/v0.13.0.4 ``` * Build: ``` @@ -340,7 +340,7 @@ application. * If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.13.0.0'. If you dont care about the version and just want binaries from master, skip this step: - git checkout v0.13.0.0 + git checkout v0.13.0.4 * If you are on a 64-bit system, run: From 3bb4b0d41f76483c4ae4d8d62faa4531049badeb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 22 Oct 2018 22:17:15 +0000 Subject: [PATCH 0175/1007] miner: fix build with boost 1.69 --- src/cryptonote_basic/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index d0b03593e..d8ca2dd35 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -637,7 +637,7 @@ namespace cryptonote boost::tribool battery_powered(on_battery_power()); if(!indeterminate( battery_powered )) { - on_ac_power = !battery_powered; + on_ac_power = !(bool)battery_powered; } } From 5a2e54a1cb184b4aeca68ce275f169a1f17e8614 Mon Sep 17 00:00:00 2001 From: doy-lee Date: Mon, 22 Oct 2018 14:02:44 +1100 Subject: [PATCH 0176/1007] Fix prune using receive time as tx_weight --- src/cryptonote_core/tx_pool.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5a9fcf67e..df41b13e2 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -379,11 +379,11 @@ namespace cryptonote return; } // remove first, in case this throws, so key images aren't removed - MINFO("Pruning tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); + MINFO("Pruning tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first); m_blockchain.remove_txpool_tx(txid); - m_txpool_weight -= it->first.second; + m_txpool_weight -= meta.weight; remove_transaction_keyimages(tx, txid); - MINFO("Pruned tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first); + MINFO("Pruned tx " << txid << " from txpool: weight: " << meta.weight << ", fee/byte: " << it->first.first); m_txs_by_fee_and_receive_time.erase(it--); changed = true; } From 70877b1d911eee5e379113931ba87993e5d06880 Mon Sep 17 00:00:00 2001 From: Paul Shapiro Date: Mon, 22 Oct 2018 18:51:45 -0500 Subject: [PATCH 0177/1007] wallet2/create_transactions_2: removed obsolete '/ 1024' on min_fee calc --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..a85a356f5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8336,7 +8336,7 @@ std::vector wallet2::create_transactions_2(std::vector Date: Mon, 22 Oct 2018 20:57:58 +0000 Subject: [PATCH 0178/1007] wallet2: extend fake out picks away from the gamma pick in order to unbias selection from blocks with few txes --- src/wallet/wallet2.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..c5618375e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -123,6 +123,8 @@ using namespace cryptonote; #define FIRST_REFRESH_GRANULARITY 1024 +#define GAMMA_PICK_HALF_WINDOW 5 + static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; @@ -6795,10 +6797,29 @@ void wallet2::get_outs(std::vector> error::get_output_distribution, "Decreasing offsets in rct distribution: " + std::to_string(block_offset) + ": " + std::to_string(rct_offsets[block_offset]) + ", " + std::to_string(block_offset + 1) + ": " + std::to_string(rct_offsets[block_offset + 1])); - uint64_t n_rct = rct_offsets[block_offset + 1] - rct_offsets[block_offset]; + uint64_t first_block_offset = block_offset, last_block_offset = block_offset; + for (size_t half_window = 0; half_window < GAMMA_PICK_HALF_WINDOW; ++half_window) + { + // end when we have a non empty block + uint64_t cum0 = first_block_offset > 0 ? rct_offsets[first_block_offset] - rct_offsets[first_block_offset - 1] : rct_offsets[0]; + if (cum0 > 1) + break; + uint64_t cum1 = last_block_offset > 0 ? rct_offsets[last_block_offset] - rct_offsets[last_block_offset - 1] : rct_offsets[0]; + if (cum1 > 1) + break; + if (first_block_offset == 0 && last_block_offset >= rct_offsets.size() - 2) + break; + // expand up to bounds + if (first_block_offset > 0) + --first_block_offset; + if (last_block_offset < rct_offsets.size() - 1) + ++last_block_offset; + } + const uint64_t n_rct = rct_offsets[last_block_offset] - (first_block_offset == 0 ? 0 : rct_offsets[first_block_offset - 1]); if (n_rct == 0) return rct_offsets[block_offset] ? rct_offsets[block_offset] - 1 : 0; - return rct_offsets[block_offset] + crypto::rand() % n_rct; + MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset); + return rct_offsets[first_block_offset] + crypto::rand() % n_rct; }; size_t num_selected_transfers = 0; From a43daebf57560aef4e83b3cce7e92bab3f2070dc Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 22 Oct 2018 17:31:48 +0100 Subject: [PATCH 0179/1007] Add stats utility Report statistics from a blockchain DB --- src/blockchain_utilities/CMakeLists.txt | 28 ++ src/blockchain_utilities/blockchain_stats.cpp | 337 ++++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100644 src/blockchain_utilities/blockchain_stats.cpp diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 24a750eb0..c6a1d43a9 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -115,6 +115,14 @@ set(blockchain_depth_private_headers) monero_private_headers(blockchain_depth ${blockchain_depth_private_headers}) +set(blockchain_stats_sources + blockchain_stats.cpp + ) + +set(blockchain_stats_private_headers) + +monero_private_headers(blockchain_stats + ${blockchain_stats_private_headers}) monero_add_executable(blockchain_import @@ -251,3 +259,23 @@ set_property(TARGET blockchain_depth OUTPUT_NAME "monero-blockchain-depth") install(TARGETS blockchain_depth DESTINATION bin) +monero_add_executable(blockchain_stats + ${blockchain_stats_sources} + ${blockchain_stats_private_headers}) + +target_link_libraries(blockchain_stats + PRIVATE + cryptonote_core + blockchain_db + version + epee + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) + +set_property(TARGET blockchain_stats + PROPERTY + OUTPUT_NAME "monero-blockchain-stats") +install(TARGETS blockchain_stats DESTINATION bin) diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp new file mode 100644 index 000000000..716b33cae --- /dev/null +++ b/src/blockchain_utilities/blockchain_stats.cpp @@ -0,0 +1,337 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include +#include "common/command_line.h" +#include "common/varint.h" +#include "cryptonote_basic/cryptonote_boost_serialization.h" +#include "cryptonote_core/tx_pool.h" +#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_core/blockchain.h" +#include "blockchain_db/blockchain_db.h" +#include "blockchain_db/db_types.h" +#include "version.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "bcutil" + +namespace po = boost::program_options; +using namespace epee; +using namespace cryptonote; + +static bool stop_requested = false; + +int main(int argc, char* argv[]) +{ + TRY_ENTRY(); + + epee::string_tools::set_module_name_and_folder(argv[0]); + + std::string default_db_type = "lmdb"; + + std::string available_dbs = cryptonote::blockchain_db_types(", "); + available_dbs = "available: " + available_dbs; + + uint32_t log_level = 0; + uint64_t block_start = 0; + uint64_t block_stop = 0; + + tools::on_startup(); + + boost::filesystem::path output_file_path; + + po::options_description desc_cmd_only("Command line options"); + po::options_description desc_cmd_sett("Command line options and settings options"); + const command_line::arg_descriptor arg_log_level = {"log-level", "0-4 or categories", ""}; + const command_line::arg_descriptor arg_database = { + "database", available_dbs.c_str(), default_db_type + }; + const command_line::arg_descriptor arg_block_start = {"block-start", "start at block number", block_start}; + const command_line::arg_descriptor arg_block_stop = {"block-stop", "Stop at block number", block_stop}; + const command_line::arg_descriptor arg_inputs = {"with-inputs", "with input stats", false}; + const command_line::arg_descriptor arg_outputs = {"with-outputs", "with output stats", false}; + const command_line::arg_descriptor arg_ringsize = {"with-ringsize", "with ringsize stats", false}; + const command_line::arg_descriptor arg_hours = {"with-hours", "with txns per hour", false}; + + command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir); + command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on); + command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on); + command_line::add_arg(desc_cmd_sett, arg_log_level); + command_line::add_arg(desc_cmd_sett, arg_database); + command_line::add_arg(desc_cmd_sett, arg_block_start); + command_line::add_arg(desc_cmd_sett, arg_block_stop); + command_line::add_arg(desc_cmd_sett, arg_inputs); + command_line::add_arg(desc_cmd_sett, arg_outputs); + command_line::add_arg(desc_cmd_sett, arg_ringsize); + command_line::add_arg(desc_cmd_sett, arg_hours); + command_line::add_arg(desc_cmd_only, command_line::arg_help); + + po::options_description desc_options("Allowed options"); + desc_options.add(desc_cmd_only).add(desc_cmd_sett); + + po::variables_map vm; + bool r = command_line::handle_error_helper(desc_options, [&]() + { + auto parser = po::command_line_parser(argc, argv).options(desc_options); + po::store(parser.run(), vm); + po::notify(vm); + return true; + }); + if (! r) + return 1; + + if (command_line::get_arg(vm, command_line::arg_help)) + { + std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; + std::cout << desc_options << std::endl; + return 1; + } + + mlog_configure(mlog_get_default_log_path("monero-blockchain-stats.log"), true); + if (!command_line::is_arg_defaulted(vm, arg_log_level)) + mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); + else + mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); + + LOG_PRINT_L0("Starting..."); + + std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir); + bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET; + block_start = command_line::get_arg(vm, arg_block_start); + block_stop = command_line::get_arg(vm, arg_block_stop); + bool do_inputs = command_line::get_arg(vm, arg_inputs); + bool do_outputs = command_line::get_arg(vm, arg_outputs); + bool do_ringsize = command_line::get_arg(vm, arg_ringsize); + bool do_hours = command_line::get_arg(vm, arg_hours); + + std::string db_type = command_line::get_arg(vm, arg_database); + if (!cryptonote::blockchain_valid_db_type(db_type)) + { + std::cerr << "Invalid database type: " << db_type << std::endl; + return 1; + } + + LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); + std::unique_ptr core_storage; + tx_memory_pool m_mempool(*core_storage); + core_storage.reset(new Blockchain(m_mempool)); + BlockchainDB *db = new_db(db_type); + if (db == NULL) + { + LOG_ERROR("Attempted to use non-existent database type: " << db_type); + throw std::runtime_error("Attempting to use non-existent database type"); + } + LOG_PRINT_L0("database: " << db_type); + + const std::string filename = (boost::filesystem::path(opt_data_dir) / db->get_db_name()).string(); + LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); + + try + { + db->open(filename, DBF_RDONLY); + } + catch (const std::exception& e) + { + LOG_PRINT_L0("Error opening database: " << e.what()); + return 1; + } + r = core_storage->init(db, net_type); + + CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); + LOG_PRINT_L0("Source blockchain storage initialized OK"); + + tools::signal_handler::install([](int type) { + stop_requested = true; + }); + + const uint64_t db_height = db->height(); + if (!block_stop) + block_stop = db_height; + MINFO("Starting from height " << block_start << ", stopping at height " << block_stop); + +/* + * The default output can be plotted with GnuPlot using these commands: +set key autotitle columnhead +set title "Monero Blockchain Growth" +set timefmt "%Y-%m-%d" +set xdata time +set xrange ["2014-04-17":*] +set format x "%Y-%m-%d" +set yrange [0:*] +set y2range [0:*] +set ylabel "Txs/Day" +set y2label "Bytes" +set y2tics nomirror +plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, '' using (timecolumn(1,"%Y-%m-%d")):7 axes x1y2 with lines + */ + + // spit out a comment that GnuPlot can use as an index + std::cout << ENDL << "# DATA" << ENDL; + std::cout << "Date\tBlocks/day\tBlocks\tTxs/Day\tTxs\tBytes/Day\tBytes"; + if (do_inputs) + std::cout << "\tInMin\tInMax\tInAvg"; + if (do_outputs) + std::cout << "\tOutMin\tOutMax\tOutAvg"; + if (do_ringsize) + std::cout << "\tRingMin\tRingMax\tRingAvg"; + if (do_hours) { + char buf[8]; + unsigned int i; + for (i=0; i<24; i++) { + sprintf(buf, "\t%02d:00", i); + std::cout << buf; + } + } + std::cout << ENDL; + + struct tm prevtm = {0}, currtm; + uint64_t prevsz = 0, currsz = 0; + uint64_t prevtxs = 0, currtxs = 0; + uint64_t currblks = 0; + uint64_t totins = 0, totouts = 0, totrings = 0; + uint32_t minins = 10, maxins = 0; + uint32_t minouts = 10, maxouts = 0; + uint32_t minrings = 50, maxrings = 0; + uint32_t io, tottxs = 0; + uint32_t txhr[24] = {0}; + unsigned int i; + + for (uint64_t h = block_start; h < block_stop; ++h) + { + cryptonote::blobdata bd = db->get_block_blob_from_height(h); + cryptonote::block blk; + if (!cryptonote::parse_and_validate_block_from_blob(bd, blk)) + { + LOG_PRINT_L0("Bad block from db"); + return 1; + } + time_t tt = blk.timestamp; + char timebuf[64]; + gmtime_r(&tt, &currtm); + if (!prevtm.tm_year) + prevtm = currtm; + // catch change of day + if (currtm.tm_mday > prevtm.tm_mday || (currtm.tm_mday == 1 && prevtm.tm_mday > 27)) + { + // check for timestamp fudging around month ends + if (prevtm.tm_mday == 1 && currtm.tm_mday > 27) + goto skip; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%d", &prevtm); + prevtm = currtm; + std::cout << timebuf << "\t" << currblks << "\t" << h << "\t" << currtxs << "\t" << prevtxs + currtxs << "\t" << currsz << "\t" << prevsz + currsz; + prevsz += currsz; + currsz = 0; + currblks = 0; + prevtxs += currtxs; + currtxs = 0; + if (!tottxs) + tottxs = 1; + if (do_inputs) { + std::cout << "\t" << (maxins ? minins : 0) << "\t" << maxins << "\t" << totins / tottxs; + minins = 10; maxins = 0; totins = 0; + } + if (do_outputs) { + std::cout << "\t" << (maxouts ? minouts : 0) << "\t" << maxouts << "\t" << totouts / tottxs; + minouts = 10; maxouts = 0; totouts = 0; + } + if (do_ringsize) { + std::cout << "\t" << (maxrings ? minrings : 0) << "\t" << maxrings << "\t" << totrings / tottxs; + minrings = 50; maxrings = 0; totrings = 0; + } + tottxs = 0; + if (do_hours) { + for (i=0; i<24; i++) { + std::cout << "\t" << txhr[i]; + txhr[i] = 0; + } + } + std::cout << ENDL; + } +skip: + currsz += bd.size(); + for (const auto& tx_id : blk.tx_hashes) + { + if (tx_id == crypto::null_hash) + { + throw std::runtime_error("Aborting: tx == null_hash"); + } + if (!db->get_tx_blob(tx_id, bd)) + { + throw std::runtime_error("Aborting: tx not found"); + } + transaction tx; + if (!parse_and_validate_tx_from_blob(bd, tx)) + { + LOG_PRINT_L0("Bad txn from db"); + return 1; + } + currsz += bd.size(); + currtxs++; + if (do_hours) + txhr[currtm.tm_hour]++; + if (do_inputs) { + io = tx.vin.size(); + if (io < minins) + minins = io; + else if (io > maxins) + maxins = io; + totins += io; + } + if (do_ringsize) { + const cryptonote::txin_to_key& tx_in_to_key + = boost::get(tx.vin[0]); + io = tx_in_to_key.key_offsets.size(); + if (io < minrings) + minrings = io; + else if (io > maxrings) + maxrings = io; + totrings += io; + } + if (do_outputs) { + io = tx.vout.size(); + if (io < minouts) + minouts = io; + else if (io > maxouts) + maxouts = io; + totouts += io; + } + tottxs++; + } + currblks++; + + if (stop_requested) + break; + } + + core_storage->deinit(); + return 0; + + CATCH_ENTRY("Stats reporting error", 1); +} From 6cd929eaa3fd2df4eaa3c9e1be747e400426e38a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 31 May 2018 20:22:37 +0100 Subject: [PATCH 0180/1007] easylogging++: remove std::deque usage It's not actually needed for this use, and saves a STL header --- external/easylogging++/easylogging++.cc | 8 +++++++- external/easylogging++/easylogging++.h | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index a4bdad4cf..1139008e2 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -1981,6 +1981,12 @@ void VRegistry::setCategories(const char* categories, bool clear) { m_categoriesString += ","; m_categoriesString += categories; + size_t n_fields = m_categories.size() + 1; + for (const char *ptr = categories; *ptr; ++ptr) + if (*ptr == ',') + ++n_fields; + m_categories.reserve(n_fields); + bool isCat = true; bool isLevel = false; std::stringstream ss; @@ -2042,7 +2048,7 @@ bool VRegistry::allowed(Level level, const char* category) { if (m_categories.empty() || category == nullptr) { return false; } else { - std::deque>::const_reverse_iterator it = m_categories.rbegin(); + std::vector>::const_reverse_iterator it = m_categories.rbegin(); for (; it != m_categories.rend(); ++it) { if (base::utils::Str::wildCardMatch(category, it->first.c_str())) { const int p = priority(it->second); diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 8e8b7094b..8bf94c546 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -386,7 +386,6 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre #include #include #include -#include #include #include #include @@ -2531,7 +2530,7 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe { base::type::VerboseLevel m_level; base::type::EnumType* m_pFlags; std::map m_modules; - std::deque> m_categories; + std::vector> m_categories; std::map m_cached_allowed_categories; std::string m_categoriesString; std::string m_filenameCommonPrefix; From d6937e373b32628fff414c7d8a07e4323593c6a0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 19 Oct 2018 11:15:31 +0000 Subject: [PATCH 0181/1007] ringct: use dummy bulletproofs when in fake mode, for speed --- src/device/device.hpp | 8 ++++-- src/device/device_default.cpp | 2 +- src/device/device_ledger.cpp | 2 +- src/ringct/rctSigs.cpp | 49 +++++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/device/device.hpp b/src/device/device.hpp index cb9117650..815a0ab93 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -85,7 +85,7 @@ namespace hw { public: - device() {} + device(): mode(NONE) {} device(const device &hwdev) {} virtual ~device() {} @@ -115,7 +115,8 @@ namespace hw { virtual bool connect(void) = 0; virtual bool disconnect(void) = 0; - virtual bool set_mode(device_mode mode) = 0; + virtual bool set_mode(device_mode mode) { this->mode = mode; return true; } + virtual device_mode get_mode() const { return mode; } virtual device_type get_type() const = 0; @@ -202,6 +203,9 @@ namespace hw { virtual bool mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) = 0; virtual bool close_tx(void) = 0; + + protected: + device_mode mode; } ; struct reset_mode { diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index a4f40e041..68f40d91e 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -83,7 +83,7 @@ namespace hw { } bool device_default::set_mode(device_mode mode) { - return true; + return device::set_mode(mode); } /* ======================================================================= */ diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index d879ee95a..0a86e6987 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -396,7 +396,7 @@ namespace hw { CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "< batch_amounts(batch_size); for (i = 0; i < batch_size; ++i) batch_amounts[i] = outamounts[i + amounts_proved]; - rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts)); - #ifdef DBG - CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); - #endif + if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) + { + // use a fake bulletproof for speed + rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts.size())); + C = rct::keyV(batch_amounts.size(), I); + masks = rct::keyV(batch_amounts.size(), I); + } + else + { + rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts)); + #ifdef DBG + CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); + #endif + } for (i = 0; i < batch_size; ++i) { rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]); From 6097472a195fe81b34c2e5ab83ff2a1786c2a5e3 Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Fri, 19 Oct 2018 22:06:03 -0400 Subject: [PATCH 0182/1007] Update ZMQ fee estimate and add ZMQ output distribution --- src/rpc/CMakeLists.txt | 7 +-- src/rpc/core_rpc_server.cpp | 56 ++------------------ src/rpc/core_rpc_server_commands_defs.h | 13 +++-- src/rpc/daemon_handler.cpp | 48 +++++++++++++++-- src/rpc/daemon_handler.h | 4 +- src/rpc/daemon_messages.cpp | 58 ++++++++++++++++++--- src/rpc/daemon_messages.h | 27 ++++++++-- src/rpc/message_data_structs.h | 7 +++ src/rpc/rpc_handler.cpp | 69 +++++++++++++++++++++++++ src/rpc/rpc_handler.h | 17 ++++-- src/serialization/json_object.cpp | 23 +++++++++ src/serialization/json_object.h | 3 ++ src/wallet/wallet2.cpp | 16 +++--- 13 files changed, 260 insertions(+), 88 deletions(-) create mode 100644 src/rpc/rpc_handler.cpp diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 4f8f96524..8b4c27e3e 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -27,7 +27,8 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(rpc_base_sources - rpc_args.cpp) + rpc_args.cpp + rpc_handler.cpp) set(rpc_sources core_rpc_server.cpp @@ -43,7 +44,8 @@ set(daemon_rpc_server_sources set(rpc_base_headers - rpc_args.h) + rpc_args.h + rpc_handler.h) set(rpc_headers) @@ -63,7 +65,6 @@ set(daemon_rpc_server_private_headers message.h daemon_messages.h daemon_handler.h - rpc_handler.h zmq_server.h) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 55ee66a79..dc3860d60 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -45,6 +45,7 @@ using namespace epee; #include "storages/http_abstract_invoke.h" #include "crypto/hash.h" #include "rpc/rpc_args.h" +#include "rpc/rpc_handler.h" #include "core_rpc_server_error_codes.h" #include "p2p/net_node.h" #include "version.h" @@ -2124,62 +2125,15 @@ namespace cryptonote const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (uint64_t amount: req.amounts) { - static struct D - { - boost::mutex mutex; - std::vector cached_distribution; - uint64_t cached_from, cached_to, cached_start_height, cached_base; - bool cached; - D(): cached_from(0), cached_to(0), cached_start_height(0), cached_base(0), cached(false) {} - } d; - boost::unique_lock lock(d.mutex); - - if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req_to_height) - { - res.distributions.push_back({amount, d.cached_start_height, req.binary, d.cached_distribution, d.cached_base}); - if (!req.cumulative) - { - auto &distribution = res.distributions.back().distribution; - for (size_t n = distribution.size() - 1; n > 0; --n) - distribution[n] -= distribution[n-1]; - distribution[0] -= d.cached_base; - } - continue; - } - - std::vector distribution; - uint64_t start_height, base; - if (!m_core.get_output_distribution(amount, req.from_height, req_to_height, start_height, distribution, base)) + auto data = rpc::RpcHandler::get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative); + if (!data) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - error_resp.message = "Failed to get rct distribution"; + error_resp.message = "Failed to get output distribution"; return false; } - if (req_to_height > 0 && req_to_height >= req.from_height) - { - uint64_t offset = std::max(req.from_height, start_height); - if (offset <= req_to_height && req_to_height - offset + 1 < distribution.size()) - distribution.resize(req_to_height - offset + 1); - } - - if (amount == 0) - { - d.cached_from = req.from_height; - d.cached_to = req_to_height; - d.cached_distribution = distribution; - d.cached_start_height = start_height; - d.cached_base = base; - d.cached = true; - } - - if (!req.cumulative) - { - for (size_t n = distribution.size() - 1; n > 0; --n) - distribution[n] -= distribution[n-1]; - distribution[0] -= base; - } - res.distributions.push_back({amount, start_height, req.binary, std::move(distribution), base}); + res.distributions.push_back({std::move(*data), amount, req.binary}); } } catch (const std::exception &e) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 3b654d4cb..e8720cb14 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -33,6 +33,7 @@ #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/difficulty.h" #include "crypto/hash.h" +#include "rpc/rpc_handler.h" namespace cryptonote { @@ -2236,21 +2237,19 @@ namespace cryptonote struct distribution { + rpc::output_distribution_data data; uint64_t amount; - uint64_t start_height; bool binary; - std::vector distribution; - uint64_t base; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(amount) - KV_SERIALIZE(start_height) + KV_SERIALIZE_N(data.start_height, "start_height") KV_SERIALIZE(binary) if (this_ref.binary) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(distribution) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution") else - KV_SERIALIZE(distribution) - KV_SERIALIZE(base) + KV_SERIALIZE_N(data.distribution, "distribution") + KV_SERIALIZE_N(data.base, "base") END_KV_SERIALIZE_MAP() }; diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 9d3b09b68..8822bd378 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -724,12 +724,53 @@ namespace rpc res.status = Message::STATUS_OK; } - void DaemonHandler::handle(const GetPerKBFeeEstimate::Request& req, GetPerKBFeeEstimate::Response& res) + void DaemonHandler::handle(const GetFeeEstimate::Request& req, GetFeeEstimate::Response& res) { - res.estimated_fee_per_kb = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.num_grace_blocks); + res.hard_fork_version = m_core.get_blockchain_storage().get_current_hard_fork_version(); + res.estimated_base_fee = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.num_grace_blocks); + + if (res.hard_fork_version < HF_VERSION_PER_BYTE_FEE) + { + res.size_scale = 1024; // per KiB fee + res.fee_mask = 1; + } + else + { + res.size_scale = 1; // per byte fee + res.fee_mask = Blockchain::get_fee_quantization_mask(); + } res.status = Message::STATUS_OK; } + void DaemonHandler::handle(const GetOutputDistribution::Request& req, GetOutputDistribution::Response& res) + { + try + { + res.distributions.reserve(req.amounts.size()); + + const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); + for (std::uint64_t amount : req.amounts) + { + auto data = get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative); + if (!data) + { + res.distributions.clear(); + res.status = Message::STATUS_FAILED; + res.error_details = "Failed to get output distribution"; + return; + } + res.distributions.push_back(output_distribution{std::move(*data), amount, req.cumulative}); + } + res.status = Message::STATUS_OK; + } + catch (const std::exception& e) + { + res.distributions.clear(); + res.status = Message::STATUS_FAILED; + res.error_details = e.what(); + } + } + bool DaemonHandler::getBlockHeaderByHash(const crypto::hash& hash_in, cryptonote::rpc::BlockHeaderResponse& header) { block b; @@ -804,7 +845,8 @@ namespace rpc REQ_RESP_TYPES_MACRO(request_type, GetOutputHistogram, req_json, resp_message, handle); REQ_RESP_TYPES_MACRO(request_type, GetOutputKeys, req_json, resp_message, handle); REQ_RESP_TYPES_MACRO(request_type, GetRPCVersion, req_json, resp_message, handle); - REQ_RESP_TYPES_MACRO(request_type, GetPerKBFeeEstimate, req_json, resp_message, handle); + REQ_RESP_TYPES_MACRO(request_type, GetFeeEstimate, req_json, resp_message, handle); + REQ_RESP_TYPES_MACRO(request_type, GetOutputDistribution, req_json, resp_message, handle); // if none of the request types matches if (resp_message == NULL) diff --git a/src/rpc/daemon_handler.h b/src/rpc/daemon_handler.h index 5f9687511..2c8ac3867 100644 --- a/src/rpc/daemon_handler.h +++ b/src/rpc/daemon_handler.h @@ -126,7 +126,9 @@ class DaemonHandler : public RpcHandler void handle(const GetRPCVersion::Request& req, GetRPCVersion::Response& res); - void handle(const GetPerKBFeeEstimate::Request& req, GetPerKBFeeEstimate::Response& res); + void handle(const GetFeeEstimate::Request& req, GetFeeEstimate::Response& res); + + void handle(const GetOutputDistribution::Request& req, GetOutputDistribution::Response& res); std::string handle(const std::string& request); diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index 56f6f6a8c..fa848cff4 100644 --- a/src/rpc/daemon_messages.cpp +++ b/src/rpc/daemon_messages.cpp @@ -59,7 +59,8 @@ const char* const HardForkInfo::name = "hard_fork_info"; const char* const GetOutputHistogram::name = "get_output_histogram"; const char* const GetOutputKeys::name = "get_output_keys"; const char* const GetRPCVersion::name = "get_rpc_version"; -const char* const GetPerKBFeeEstimate::name = "get_dynamic_per_kb_fee_estimate"; +const char* const GetFeeEstimate::name = "get_dynamic_fee_estimate"; +const char* const GetOutputDistribution::name = "get_output_distribution"; @@ -825,7 +826,7 @@ void GetRPCVersion::Response::fromJson(rapidjson::Value& val) GET_FROM_JSON_OBJECT(val, version, version); } -rapidjson::Value GetPerKBFeeEstimate::Request::toJson(rapidjson::Document& doc) const +rapidjson::Value GetFeeEstimate::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); @@ -836,27 +837,70 @@ rapidjson::Value GetPerKBFeeEstimate::Request::toJson(rapidjson::Document& doc) return val; } -void GetPerKBFeeEstimate::Request::fromJson(rapidjson::Value& val) +void GetFeeEstimate::Request::fromJson(rapidjson::Value& val) { GET_FROM_JSON_OBJECT(val, num_grace_blocks, num_grace_blocks); } -rapidjson::Value GetPerKBFeeEstimate::Response::toJson(rapidjson::Document& doc) const +rapidjson::Value GetFeeEstimate::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, estimated_fee_per_kb, estimated_fee_per_kb); + INSERT_INTO_JSON_OBJECT(val, doc, estimated_base_fee, estimated_base_fee); + INSERT_INTO_JSON_OBJECT(val, doc, fee_mask, fee_mask); + INSERT_INTO_JSON_OBJECT(val, doc, size_scale, size_scale); + INSERT_INTO_JSON_OBJECT(val, doc, hard_fork_version, hard_fork_version); return val; } -void GetPerKBFeeEstimate::Response::fromJson(rapidjson::Value& val) +void GetFeeEstimate::Response::fromJson(rapidjson::Value& val) { - GET_FROM_JSON_OBJECT(val, estimated_fee_per_kb, estimated_fee_per_kb); + GET_FROM_JSON_OBJECT(val, estimated_base_fee, estimated_base_fee); + GET_FROM_JSON_OBJECT(val, fee_mask, fee_mask); + GET_FROM_JSON_OBJECT(val, size_scale, size_scale); + GET_FROM_JSON_OBJECT(val, hard_fork_version, hard_fork_version); } +rapidjson::Value GetOutputDistribution::Request::toJson(rapidjson::Document& doc) const +{ + auto val = Message::toJson(doc); + auto& al = doc.GetAllocator(); + + INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts); + INSERT_INTO_JSON_OBJECT(val, doc, from_height, from_height); + INSERT_INTO_JSON_OBJECT(val, doc, to_height, to_height); + INSERT_INTO_JSON_OBJECT(val, doc, cumulative, cumulative); + + return val; +} + +void GetOutputDistribution::Request::fromJson(rapidjson::Value& val) +{ + GET_FROM_JSON_OBJECT(val, amounts, amounts); + GET_FROM_JSON_OBJECT(val, from_height, from_height); + GET_FROM_JSON_OBJECT(val, to_height, to_height); + GET_FROM_JSON_OBJECT(val, cumulative, cumulative); +} + +rapidjson::Value GetOutputDistribution::Response::toJson(rapidjson::Document& doc) const +{ + auto val = Message::toJson(doc); + auto& al = doc.GetAllocator(); + + INSERT_INTO_JSON_OBJECT(val, doc, status, status); + INSERT_INTO_JSON_OBJECT(val, doc, distributions, distributions); + + return val; +} + +void GetOutputDistribution::Response::fromJson(rapidjson::Value& val) +{ + GET_FROM_JSON_OBJECT(val, status, status); + GET_FROM_JSON_OBJECT(val, distributions, distributions); +} } // namespace rpc diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index be3138e3b..70f4c50f1 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -28,6 +28,9 @@ #pragma once +#include +#include + #include "message.h" #include "cryptonote_protocol/cryptonote_protocol_defs.h" #include "rpc/message_data_structs.h" @@ -62,8 +65,6 @@ class classname \ #define END_RPC_MESSAGE_RESPONSE }; #define END_RPC_MESSAGE_CLASS }; -#define COMMA() , - // NOTE: when using a type with multiple template parameters, // replace any comma in the template specifier with the macro // above, or the preprocessor will eat the comma in a bad way. @@ -118,7 +119,8 @@ BEGIN_RPC_MESSAGE_CLASS(GetTransactions); RPC_MESSAGE_MEMBER(std::vector, tx_hashes); END_RPC_MESSAGE_REQUEST; BEGIN_RPC_MESSAGE_RESPONSE; - RPC_MESSAGE_MEMBER(std::unordered_map, txs); + using txes_map = std::unordered_map; + RPC_MESSAGE_MEMBER(txes_map, txs); RPC_MESSAGE_MEMBER(std::vector, missed_hashes); END_RPC_MESSAGE_RESPONSE; END_RPC_MESSAGE_CLASS; @@ -407,12 +409,27 @@ BEGIN_RPC_MESSAGE_CLASS(GetRPCVersion); END_RPC_MESSAGE_RESPONSE; END_RPC_MESSAGE_CLASS; -BEGIN_RPC_MESSAGE_CLASS(GetPerKBFeeEstimate); +BEGIN_RPC_MESSAGE_CLASS(GetFeeEstimate); BEGIN_RPC_MESSAGE_REQUEST; RPC_MESSAGE_MEMBER(uint64_t, num_grace_blocks); END_RPC_MESSAGE_REQUEST; BEGIN_RPC_MESSAGE_RESPONSE; - RPC_MESSAGE_MEMBER(uint64_t, estimated_fee_per_kb); + RPC_MESSAGE_MEMBER(uint64_t, estimated_base_fee); + RPC_MESSAGE_MEMBER(uint64_t, fee_mask); + RPC_MESSAGE_MEMBER(uint32_t, size_scale); + RPC_MESSAGE_MEMBER(uint8_t, hard_fork_version); + END_RPC_MESSAGE_RESPONSE; +END_RPC_MESSAGE_CLASS; + +BEGIN_RPC_MESSAGE_CLASS(GetOutputDistribution); + BEGIN_RPC_MESSAGE_REQUEST; + RPC_MESSAGE_MEMBER(std::vector, amounts); + RPC_MESSAGE_MEMBER(uint64_t, from_height); + RPC_MESSAGE_MEMBER(uint64_t, to_height); + RPC_MESSAGE_MEMBER(bool, cumulative); + END_RPC_MESSAGE_REQUEST; + BEGIN_RPC_MESSAGE_RESPONSE; + RPC_MESSAGE_MEMBER(std::vector, distributions); END_RPC_MESSAGE_RESPONSE; END_RPC_MESSAGE_CLASS; diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index cf15ade1c..3b56aff15 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -31,6 +31,7 @@ #include "crypto/hash.h" #include "cryptonote_basic/cryptonote_basic.h" #include "ringct/rctSigs.h" +#include "rpc/rpc_handler.h" #include #include @@ -192,6 +193,12 @@ namespace rpc uint64_t start_time; }; + struct output_distribution + { + output_distribution_data data; + uint64_t amount; + bool cumulative; + }; } // namespace rpc } // namespace cryptonote diff --git a/src/rpc/rpc_handler.cpp b/src/rpc/rpc_handler.cpp new file mode 100644 index 000000000..d4beb1928 --- /dev/null +++ b/src/rpc/rpc_handler.cpp @@ -0,0 +1,69 @@ + +#include +#include +#include + +#include "cryptonote_core/cryptonote_core.h" + +namespace cryptonote +{ +namespace rpc +{ + namespace + { + output_distribution_data + process_distribution(bool cumulative, std::uint64_t start_height, std::vector distribution, std::uint64_t base) + { + if (!cumulative && !distribution.empty()) + { + for (std::size_t n = distribution.size() - 1; 0 < n; --n) + distribution[n] -= distribution[n - 1]; + distribution[0] -= base; + } + + return {std::move(distribution), start_height, base}; + } + } + + boost::optional + RpcHandler::get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative) + { + static struct D + { + boost::mutex mutex; + std::vector cached_distribution; + std::uint64_t cached_from, cached_to, cached_start_height, cached_base; + bool cached; + D(): cached_from(0), cached_to(0), cached_start_height(0), cached_base(0), cached(false) {} + } d; + const boost::unique_lock lock(d.mutex); + + if (d.cached && amount == 0 && d.cached_from == from_height && d.cached_to == to_height) + return process_distribution(cumulative, d.cached_start_height, d.cached_distribution, d.cached_base); + + std::vector distribution; + std::uint64_t start_height, base; + if (!src.get_output_distribution(amount, from_height, to_height, start_height, distribution, base)) + return boost::none; + + if (to_height > 0 && to_height >= from_height) + { + const std::uint64_t offset = std::max(from_height, start_height); + if (offset <= to_height && to_height - offset + 1 < distribution.size()) + distribution.resize(to_height - offset + 1); + } + + if (amount == 0) + { + d.cached_from = from_height; + d.cached_to = to_height; + d.cached_distribution = distribution; + d.cached_start_height = start_height; + d.cached_base = base; + d.cached = true; + } + + return process_distribution(cumulative, start_height, std::move(distribution), base); + } +} // rpc +} // cryptonote diff --git a/src/rpc/rpc_handler.h b/src/rpc/rpc_handler.h index 64bade5a8..3cccef78a 100644 --- a/src/rpc/rpc_handler.h +++ b/src/rpc/rpc_handler.h @@ -28,24 +28,35 @@ #pragma once +#include +#include #include +#include namespace cryptonote { +class core; namespace rpc { +struct output_distribution_data +{ + std::vector distribution; + std::uint64_t start_height; + std::uint64_t base; +}; class RpcHandler { public: + RpcHandler() { } + virtual ~RpcHandler() { } virtual std::string handle(const std::string& request) = 0; - RpcHandler() { } - - virtual ~RpcHandler() { } + static boost::optional + get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative); }; diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 89a1dbd23..7980e8953 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1232,6 +1232,29 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf GET_FROM_JSON_OBJECT(val, info.start_time, start_time); } +void toJsonValue(rapidjson::Document& doc, const cryptonote::rpc::output_distribution& dist, rapidjson::Value& val) +{ + val.SetObject(); + + INSERT_INTO_JSON_OBJECT(val, doc, distribution, dist.data.distribution); + INSERT_INTO_JSON_OBJECT(val, doc, amount, dist.amount); + INSERT_INTO_JSON_OBJECT(val, doc, start_height, dist.data.start_height); + INSERT_INTO_JSON_OBJECT(val, doc, base, dist.data.base); +} + +void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_distribution& dist) +{ + if (!val.IsObject()) + { + throw WRONG_TYPE("json object"); + } + + GET_FROM_JSON_OBJECT(val, dist.data.distribution, distribution); + GET_FROM_JSON_OBJECT(val, dist.amount, amount); + GET_FROM_JSON_OBJECT(val, dist.data.start_height, start_height); + GET_FROM_JSON_OBJECT(val, dist.data.base, base); +} + } // namespace json } // namespace cryptonote diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index da3351fe3..b6384ca0d 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -281,6 +281,9 @@ void fromJsonValue(const rapidjson::Value& val, rct::mgSig& sig); void toJsonValue(rapidjson::Document& doc, const cryptonote::rpc::DaemonInfo& info, rapidjson::Value& val); void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& info); +void toJsonValue(rapidjson::Document& doc, const cryptonote::rpc::output_distribution& dist, rapidjson::Value& val); +void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::output_distribution& dist); + template typename std::enable_if::value, void>::type toJsonValue(rapidjson::Document& doc, const Map& map, rapidjson::Value& val); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6b3a8533e..21793b58d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2865,8 +2865,8 @@ bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector MWARNING("Failed to request output distribution: results are not for amount 0"); return false; } - start_height = res.distributions[0].start_height; - distribution = std::move(res.distributions[0].distribution); + start_height = res.distributions[0].data.start_height; + distribution = std::move(res.distributions[0].data.distribution); return true; } //---------------------------------------------------------------------------------------------------- @@ -6747,13 +6747,13 @@ void wallet2::get_outs(std::vector> { if (d.amount == amount) { - THROW_WALLET_EXCEPTION_IF(d.start_height > segregation_fork_height, error::get_output_distribution, "Distribution start_height too high"); - THROW_WALLET_EXCEPTION_IF(segregation_fork_height - d.start_height >= d.distribution.size(), error::get_output_distribution, "Distribution size too small"); - THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS - d.start_height >= d.distribution.size(), error::get_output_distribution, "Distribution size too small"); + THROW_WALLET_EXCEPTION_IF(d.data.start_height > segregation_fork_height, error::get_output_distribution, "Distribution start_height too high"); + THROW_WALLET_EXCEPTION_IF(segregation_fork_height - d.data.start_height >= d.data.distribution.size(), error::get_output_distribution, "Distribution size too small"); + THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS - d.data.start_height >= d.data.distribution.size(), error::get_output_distribution, "Distribution size too small"); THROW_WALLET_EXCEPTION_IF(segregation_fork_height <= RECENT_OUTPUT_BLOCKS, error::wallet_internal_error, "Fork height too low"); - THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS < d.start_height, error::get_output_distribution, "Bad start height"); - uint64_t till_fork = d.distribution[segregation_fork_height - d.start_height]; - uint64_t recent = till_fork - d.distribution[segregation_fork_height - RECENT_OUTPUT_BLOCKS - d.start_height]; + THROW_WALLET_EXCEPTION_IF(segregation_fork_height - RECENT_OUTPUT_BLOCKS < d.data.start_height, error::get_output_distribution, "Bad start height"); + uint64_t till_fork = d.data.distribution[segregation_fork_height - d.data.start_height]; + uint64_t recent = till_fork - d.data.distribution[segregation_fork_height - RECENT_OUTPUT_BLOCKS - d.data.start_height]; segregation_limit[amount] = std::make_pair(till_fork, recent); found = true; break; From c4fbfd786ab15e51a39183ae6124977a13ae0a3d Mon Sep 17 00:00:00 2001 From: Pol Mauri Date: Tue, 23 Oct 2018 23:11:54 -0700 Subject: [PATCH 0183/1007] Small function declaration cleanup in slow-hash.c - These functions are declared twice in slow-hash.c. Remove one of the copies. - The declarations have the wrong return type, should be void, not int. Function definitions here: https://github.com/monero-project/monero/blob/1e74586ee99e4bd89626d2eb4d23883cd91f0f81/src/crypto/aesb.c#L151-L180 Test plan: make release-test --- src/crypto/slow-hash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 40cfb0461..ed61e1017 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -47,8 +47,8 @@ #define INIT_SIZE_BLK 8 #define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE) -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); +extern void aesb_single_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); +extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); #define VARIANT1_1(p) \ do if (variant == 1) \ @@ -1408,9 +1408,6 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = { hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein }; -extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey); -extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey); - static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); } static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) { From 07c6280909f8d6bb4d4d8e2399b56a0ce02393c6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 19 Aug 2018 22:40:30 +0000 Subject: [PATCH 0184/1007] epee: some minor speedup in parsing --- contrib/epee/include/storages/parserse_base_utils.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index 8c6c1a64d..31495ae13 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -39,12 +39,14 @@ namespace misc_utils inline std::string transform_to_escape_sequence(const std::string& src) { static const char escaped[] = "\b\f\n\r\t\v\"\\/"; - if (std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)) == src.end()) + std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)); + if (it == src.end()) return src; std::string res; res.reserve(2 * src.size()); - for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it) + res.assign(src.begin(), it); + for(; it!=src.end(); ++it) { switch(*it) { From e9fc9ff2684188d9e27ae09695bca186ca28d612 Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Wed, 24 Oct 2018 13:41:46 +0000 Subject: [PATCH 0185/1007] Added research information to main readme --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 6b6f0cac5..9c70fd38e 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,15 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers. - Our [Vulnerability Response Process](https://github.com/monero-project/meta/blob/master/VULNERABILITY_RESPONSE_PROCESS.md) encourages responsible disclosure - We are also available via [HackerOne](https://hackerone.com/monero) +## Research + +The [Monero Research Lab](https://src.getmonero.org/resources/research-lab/) coordinates Monero research as a project workgroup. We welcome collaboration and contributions from outside researchers! Because not all Lab work and publications are distributed as traditional preprints or articles, they may be easy to miss if you are conducting literature reviews for your own Monero research. You are encouraged to get in touch with our researchers if you have questions, wish to collaborate, or would like guidance to help avoid unnecessarily duplicating earlier or known work. + +Our researchers are available on IRC in [#monero-research-lab on Freenode](https://webchat.freenode.net/?randomnick=1&channels=%23monero-research-lab&prompt=1&uio=d4) or by email: + +- Sarang Noether, Ph.D.: [sarang@getmonero.org](mailto:sarang@getmonero.org) or [sarang.noether@protonmail.com](mailto:sarang.noether@protonmail.com) +- Surae Noether (Brandon Goodell), Ph.D.: [surae@getmonero.org](mailto:surae@getmonero.org) or [surae.noether@protonmail.com](mailto:surae.noether@protonmail.com) + ## Announcements - You can subscribe to an [announcement listserv](https://lists.getmonero.org) to get critical announcements from the Monero core team. The announcement list can be very helpful for knowing when software updates are needed. From 9168fc9f78c1276c986c7effd63ba4f258417fd9 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 14:43:31 +0000 Subject: [PATCH 0186/1007] Makefile: fix building without a git tree --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 40b8839cc..f9270ebf2 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,11 @@ ANDROID_STANDALONE_TOOLCHAIN_PATH ?= /usr/local/toolchain +dotgit=$(shell ls -d .git/config) +ifneq ($(dotgit), .git/config) + USE_SINGLE_BUILDDIR=1 +endif + subbuilddir:=$(shell echo `uname | sed -e 's|[:/\\ \(\)]|_|g'`/`git branch | grep '\* ' | cut -f2- -d' '| sed -e 's|[:/\\ \(\)]|_|g'`) ifeq ($(USE_SINGLE_BUILDDIR),) builddir := build/"$(subbuilddir)" From 8a512b1d319847e2f282747268432f0fb7e810ea Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:41:44 +0000 Subject: [PATCH 0187/1007] Minor wording changes; added research repository links --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9c70fd38e..1e896dddc 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,12 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers. ## Research -The [Monero Research Lab](https://src.getmonero.org/resources/research-lab/) coordinates Monero research as a project workgroup. We welcome collaboration and contributions from outside researchers! Because not all Lab work and publications are distributed as traditional preprints or articles, they may be easy to miss if you are conducting literature reviews for your own Monero research. You are encouraged to get in touch with our researchers if you have questions, wish to collaborate, or would like guidance to help avoid unnecessarily duplicating earlier or known work. +The [Monero Research Lab](https://src.getmonero.org/resources/research-lab/) is an open forum where the community coordinates research into Monero cryptography, protocols, fungibility, analysis, and more. We welcome collaboration and contributions from outside researchers! Because not all Lab work and publications are distributed as traditional preprints or articles, they may be easy to miss if you are conducting literature reviews for your own Monero research. You are encouraged to get in touch with our researchers if you have questions, wish to collaborate, or would like guidance to help avoid unnecessarily duplicating earlier or known work. Our researchers are available on IRC in [#monero-research-lab on Freenode](https://webchat.freenode.net/?randomnick=1&channels=%23monero-research-lab&prompt=1&uio=d4) or by email: -- Sarang Noether, Ph.D.: [sarang@getmonero.org](mailto:sarang@getmonero.org) or [sarang.noether@protonmail.com](mailto:sarang.noether@protonmail.com) -- Surae Noether (Brandon Goodell), Ph.D.: [surae@getmonero.org](mailto:surae@getmonero.org) or [surae.noether@protonmail.com](mailto:surae.noether@protonmail.com) +- Sarang Noether, Ph.D.: [sarang@getmonero.org](mailto:sarang@getmonero.org) or [sarang.noether@protonmail.com](mailto:sarang.noether@protonmail.com); [research repository](https://github.com/SarangNoether/research-lab) +- Surae Noether (Brandon Goodell), Ph.D.: [surae@getmonero.org](mailto:surae@getmonero.org) or [surae.noether@protonmail.com](mailto:surae.noether@protonmail.com); [research repository](https://github.com/b-g-goodell/research-lab) ## Announcements From 0aff49873c28ae6d9718f790860b103ce7142354 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 20:36:25 +0000 Subject: [PATCH 0188/1007] rpc: fix build with older compilers --- src/rpc/daemon_messages.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index be3138e3b..8488bab0b 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -67,7 +67,7 @@ class classname \ // NOTE: when using a type with multiple template parameters, // replace any comma in the template specifier with the macro // above, or the preprocessor will eat the comma in a bad way. -#define RPC_MESSAGE_MEMBER(type, name) type name = type{} +#define RPC_MESSAGE_MEMBER(type, name) type name = {} namespace cryptonote From a9f9406c5bef07d4cd968b4bcb9116d3115355b8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 21:54:19 +0000 Subject: [PATCH 0189/1007] unit_tests: notify test special case for the usual weirdo --- tests/unit_tests/notify.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index d6811c6bd..62c8a126a 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -42,7 +42,11 @@ TEST(notify, works) ASSERT_TRUE(fd >= 0); close(fd); - const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier " + name_template + " %s"; + const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier" +#ifdef _WIN32 + + ".exe" +#endif + + " " + name_template + " %s"; tools::Notify notify(spec.c_str()); notify.notify("1111111111111111111111111111111111111111111111111111111111111111"); From ba0faae78939f756cdd7fd03798322207054ce3a Mon Sep 17 00:00:00 2001 From: xiphon Date: Thu, 25 Oct 2018 02:06:23 +0000 Subject: [PATCH 0190/1007] crypto: fixed groestl on big-endian platforms --- src/crypto/groestl.c | 101 +++++++++++++++++++----------------- src/crypto/groestl_tables.h | 37 +++++++++++++ 2 files changed, 91 insertions(+), 47 deletions(-) diff --git a/src/crypto/groestl.c b/src/crypto/groestl.c index c8258add3..d5e2989a8 100644 --- a/src/crypto/groestl.c +++ b/src/crypto/groestl.c @@ -20,9 +20,15 @@ const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}}; const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6}; +#if BYTE_ORDER == LITTLE_ENDIAN #define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \ v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \ v1 = temp_var;} +#else +#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1>>(8*amount_bytes))|(v2<<(8*(4-amount_bytes))); \ + v2 = (v2>>(8*amount_bytes))|(v1<<(8*(4-amount_bytes))); \ + v1 = temp_var;} +#endif #define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \ @@ -68,14 +74,14 @@ const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6}; static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) { uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; uint32_t* x32 = (uint32_t*)x; - x32[ 0] ^= 0x00000000^r; - x32[ 2] ^= 0x00000010^r; - x32[ 4] ^= 0x00000020^r; - x32[ 6] ^= 0x00000030^r; - x32[ 8] ^= 0x00000040^r; - x32[10] ^= 0x00000050^r; - x32[12] ^= 0x00000060^r; - x32[14] ^= 0x00000070^r; + x32[ 0] ^= SWAP32LE(0x00000000)^r; + x32[ 2] ^= SWAP32LE(0x00000010)^r; + x32[ 4] ^= SWAP32LE(0x00000020)^r; + x32[ 6] ^= SWAP32LE(0x00000030)^r; + x32[ 8] ^= SWAP32LE(0x00000040)^r; + x32[10] ^= SWAP32LE(0x00000050)^r; + x32[12] ^= SWAP32LE(0x00000060)^r; + x32[14] ^= SWAP32LE(0x00000070)^r; COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); @@ -91,21 +97,22 @@ static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) { uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp; uint32_t* x32 = (uint32_t*)x; x32[ 0] = ~x32[ 0]; - x32[ 1] ^= 0xffffffff^r; + x32[ 1] ^= SWAP32LE(0xffffffff)^r; x32[ 2] = ~x32[ 2]; - x32[ 3] ^= 0xefffffff^r; + x32[ 3] ^= SWAP32LE(0xefffffff)^r; x32[ 4] = ~x32[ 4]; - x32[ 5] ^= 0xdfffffff^r; + x32[ 5] ^= SWAP32LE(0xdfffffff)^r; x32[ 6] = ~x32[ 6]; - x32[ 7] ^= 0xcfffffff^r; + x32[ 7] ^= SWAP32LE(0xcfffffff)^r; x32[ 8] = ~x32[ 8]; - x32[ 9] ^= 0xbfffffff^r; + x32[ 9] ^= SWAP32LE(0xbfffffff)^r; x32[10] = ~x32[10]; - x32[11] ^= 0xafffffff^r; + x32[11] ^= SWAP32LE(0xafffffff)^r; x32[12] = ~x32[12]; - x32[13] ^= 0x9fffffff^r; + x32[13] ^= SWAP32LE(0x9fffffff)^r; x32[14] = ~x32[14]; - x32[15] ^= 0x8fffffff^r; + x32[15] ^= SWAP32LE(0x8fffffff)^r; + COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp); @@ -130,28 +137,28 @@ static void F512(uint32_t *h, const uint32_t *m) { } /* compute Q(m) */ - RND512Q((uint8_t*)z, y, 0x00000000); - RND512Q((uint8_t*)y, z, 0x01000000); - RND512Q((uint8_t*)z, y, 0x02000000); - RND512Q((uint8_t*)y, z, 0x03000000); - RND512Q((uint8_t*)z, y, 0x04000000); - RND512Q((uint8_t*)y, z, 0x05000000); - RND512Q((uint8_t*)z, y, 0x06000000); - RND512Q((uint8_t*)y, z, 0x07000000); - RND512Q((uint8_t*)z, y, 0x08000000); - RND512Q((uint8_t*)y, Qtmp, 0x09000000); + RND512Q((uint8_t*)z, y, SWAP32LE(0x00000000)); + RND512Q((uint8_t*)y, z, SWAP32LE(0x01000000)); + RND512Q((uint8_t*)z, y, SWAP32LE(0x02000000)); + RND512Q((uint8_t*)y, z, SWAP32LE(0x03000000)); + RND512Q((uint8_t*)z, y, SWAP32LE(0x04000000)); + RND512Q((uint8_t*)y, z, SWAP32LE(0x05000000)); + RND512Q((uint8_t*)z, y, SWAP32LE(0x06000000)); + RND512Q((uint8_t*)y, z, SWAP32LE(0x07000000)); + RND512Q((uint8_t*)z, y, SWAP32LE(0x08000000)); + RND512Q((uint8_t*)y, Qtmp, SWAP32LE(0x09000000)); /* compute P(h+m) */ - RND512P((uint8_t*)Ptmp, y, 0x00000000); - RND512P((uint8_t*)y, z, 0x00000001); - RND512P((uint8_t*)z, y, 0x00000002); - RND512P((uint8_t*)y, z, 0x00000003); - RND512P((uint8_t*)z, y, 0x00000004); - RND512P((uint8_t*)y, z, 0x00000005); - RND512P((uint8_t*)z, y, 0x00000006); - RND512P((uint8_t*)y, z, 0x00000007); - RND512P((uint8_t*)z, y, 0x00000008); - RND512P((uint8_t*)y, Ptmp, 0x00000009); + RND512P((uint8_t*)Ptmp, y, SWAP32LE(0x00000000)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000001)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000002)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000003)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000004)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000005)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000006)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000007)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000008)); + RND512P((uint8_t*)y, Ptmp, SWAP32LE(0x00000009)); /* compute P(h+m) + Q(m) + h */ for (i = 0; i < 2*COLS512; i++) { @@ -188,16 +195,16 @@ static void OutputTransformation(hashState *ctx) { for (j = 0; j < 2*COLS512; j++) { temp[j] = ctx->chaining[j]; } - RND512P((uint8_t*)temp, y, 0x00000000); - RND512P((uint8_t*)y, z, 0x00000001); - RND512P((uint8_t*)z, y, 0x00000002); - RND512P((uint8_t*)y, z, 0x00000003); - RND512P((uint8_t*)z, y, 0x00000004); - RND512P((uint8_t*)y, z, 0x00000005); - RND512P((uint8_t*)z, y, 0x00000006); - RND512P((uint8_t*)y, z, 0x00000007); - RND512P((uint8_t*)z, y, 0x00000008); - RND512P((uint8_t*)y, temp, 0x00000009); + RND512P((uint8_t*)temp, y, SWAP32LE(0x00000000)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000001)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000002)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000003)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000004)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000005)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000006)); + RND512P((uint8_t*)y, z, SWAP32LE(0x00000007)); + RND512P((uint8_t*)z, y, SWAP32LE(0x00000008)); + RND512P((uint8_t*)y, temp, SWAP32LE(0x00000009)); for (j = 0; j < 2*COLS512; j++) { ctx->chaining[j] ^= temp[j]; } @@ -213,7 +220,7 @@ static void Init(hashState* ctx) { } /* set initial value */ - ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN); + ctx->chaining[2*COLS512-1] = SWAP32LE(u32BIG((uint32_t)HASH_BIT_LEN)); /* set other variables */ ctx->buf_ptr = 0; diff --git a/src/crypto/groestl_tables.h b/src/crypto/groestl_tables.h index c4b368584..53594c569 100644 --- a/src/crypto/groestl_tables.h +++ b/src/crypto/groestl_tables.h @@ -29,7 +29,10 @@ #ifndef __tables_h #define __tables_h +#include "common/int-util.h" + +#if BYTE_ORDER == LITTLE_ENDIAN const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc , 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5 , 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d @@ -62,5 +65,39 @@ const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05 , 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e , 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3 , 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e}; +#else +const uint32_t T[512] = {0xc632f4a5, 0xf497a5c6, 0xf86f9784, 0x97eb84f8, 0xee5eb099, 0xb0c799ee, 0xf67a8c8d, 0x8cf78df6, 0xffe8170d, 0x17e50dff, 0xd60adcbd, 0xdcb7bdd6, 0xde16c8b1, 0xc8a7b1de, 0x916dfc54, 0xfc395491 +, 0x6090f050, 0xf0c05060, 0x02070503, 0x05040302, 0xce2ee0a9, 0xe087a9ce, 0x56d1877d, 0x87ac7d56, 0xe7cc2b19, 0x2bd519e7, 0xb513a662, 0xa67162b5, 0x4d7c31e6, 0x319ae64d, 0xec59b59a, 0xb5c39aec +, 0x8f40cf45, 0xcf05458f, 0x1fa3bc9d, 0xbc3e9d1f, 0x8949c040, 0xc0094089, 0xfa689287, 0x92ef87fa, 0xefd03f15, 0x3fc515ef, 0xb29426eb, 0x267febb2, 0x8ece40c9, 0x4007c98e, 0xfbe61d0b, 0x1ded0bfb +, 0x416e2fec, 0x2f82ec41, 0xb31aa967, 0xa97d67b3, 0x5f431cfd, 0x1cbefd5f, 0x456025ea, 0x258aea45, 0x23f9dabf, 0xda46bf23, 0x535102f7, 0x02a6f753, 0xe445a196, 0xa1d396e4, 0x9b76ed5b, 0xed2d5b9b +, 0x75285dc2, 0x5deac275, 0xe1c5241c, 0x24d91ce1, 0x3dd4e9ae, 0xe97aae3d, 0x4cf2be6a, 0xbe986a4c, 0x6c82ee5a, 0xeed85a6c, 0x7ebdc341, 0xc3fc417e, 0xf5f30602, 0x06f102f5, 0x8352d14f, 0xd11d4f83 +, 0x688ce45c, 0xe4d05c68, 0x515607f4, 0x07a2f451, 0xd18d5c34, 0x5cb934d1, 0xf9e11808, 0x18e908f9, 0xe24cae93, 0xaedf93e2, 0xab3e9573, 0x954d73ab, 0x6297f553, 0xf5c45362, 0x2a6b413f, 0x41543f2a +, 0x081c140c, 0x14100c08, 0x9563f652, 0xf6315295, 0x46e9af65, 0xaf8c6546, 0x9d7fe25e, 0xe2215e9d, 0x30487828, 0x78602830, 0x37cff8a1, 0xf86ea137, 0x0a1b110f, 0x11140f0a, 0x2febc4b5, 0xc45eb52f +, 0x0e151b09, 0x1b1c090e, 0x247e5a36, 0x5a483624, 0x1badb69b, 0xb6369b1b, 0xdf98473d, 0x47a53ddf, 0xcda76a26, 0x6a8126cd, 0x4ef5bb69, 0xbb9c694e, 0x7f334ccd, 0x4cfecd7f, 0xea50ba9f, 0xbacf9fea +, 0x123f2d1b, 0x2d241b12, 0x1da4b99e, 0xb93a9e1d, 0x58c49c74, 0x9cb07458, 0x3446722e, 0x72682e34, 0x3641772d, 0x776c2d36, 0xdc11cdb2, 0xcda3b2dc, 0xb49d29ee, 0x2973eeb4, 0x5b4d16fb, 0x16b6fb5b +, 0xa4a501f6, 0x0153f6a4, 0x76a1d74d, 0xd7ec4d76, 0xb714a361, 0xa37561b7, 0x7d3449ce, 0x49face7d, 0x52df8d7b, 0x8da47b52, 0xdd9f423e, 0x42a13edd, 0x5ecd9371, 0x93bc715e, 0x13b1a297, 0xa2269713 +, 0xa6a204f5, 0x0457f5a6, 0xb901b868, 0xb86968b9, 0x00000000, 0x00000000, 0xc1b5742c, 0x74992cc1, 0x40e0a060, 0xa0806040, 0xe3c2211f, 0x21dd1fe3, 0x793a43c8, 0x43f2c879, 0xb69a2ced, 0x2c77edb6 +, 0xd40dd9be, 0xd9b3bed4, 0x8d47ca46, 0xca01468d, 0x671770d9, 0x70ced967, 0x72afdd4b, 0xdde44b72, 0x94ed79de, 0x7933de94, 0x98ff67d4, 0x672bd498, 0xb09323e8, 0x237be8b0, 0x855bde4a, 0xde114a85 +, 0xbb06bd6b, 0xbd6d6bbb, 0xc5bb7e2a, 0x7e912ac5, 0x4f7b34e5, 0x349ee54f, 0xedd73a16, 0x3ac116ed, 0x86d254c5, 0x5417c586, 0x9af862d7, 0x622fd79a, 0x6699ff55, 0xffcc5566, 0x11b6a794, 0xa7229411 +, 0x8ac04acf, 0x4a0fcf8a, 0xe9d93010, 0x30c910e9, 0x040e0a06, 0x0a080604, 0xfe669881, 0x98e781fe, 0xa0ab0bf0, 0x0b5bf0a0, 0x78b4cc44, 0xccf04478, 0x25f0d5ba, 0xd54aba25, 0x4b753ee3, 0x3e96e34b +, 0xa2ac0ef3, 0x0e5ff3a2, 0x5d4419fe, 0x19bafe5d, 0x80db5bc0, 0x5b1bc080, 0x0580858a, 0x850a8a05, 0x3fd3ecad, 0xec7ead3f, 0x21fedfbc, 0xdf42bc21, 0x70a8d848, 0xd8e04870, 0xf1fd0c04, 0x0cf904f1 +, 0x63197adf, 0x7ac6df63, 0x772f58c1, 0x58eec177, 0xaf309f75, 0x9f4575af, 0x42e7a563, 0xa5846342, 0x20705030, 0x50403020, 0xe5cb2e1a, 0x2ed11ae5, 0xfdef120e, 0x12e10efd, 0xbf08b76d, 0xb7656dbf +, 0x8155d44c, 0xd4194c81, 0x18243c14, 0x3c301418, 0x26795f35, 0x5f4c3526, 0xc3b2712f, 0x719d2fc3, 0xbe8638e1, 0x3867e1be, 0x35c8fda2, 0xfd6aa235, 0x88c74fcc, 0x4f0bcc88, 0x2e654b39, 0x4b5c392e +, 0x936af957, 0xf93d5793, 0x55580df2, 0x0daaf255, 0xfc619d82, 0x9de382fc, 0x7ab3c947, 0xc9f4477a, 0xc827efac, 0xef8bacc8, 0xba8832e7, 0x326fe7ba, 0x324f7d2b, 0x7d642b32, 0xe642a495, 0xa4d795e6 +, 0xc03bfba0, 0xfb9ba0c0, 0x19aab398, 0xb3329819, 0x9ef668d1, 0x6827d19e, 0xa322817f, 0x815d7fa3, 0x44eeaa66, 0xaa886644, 0x54d6827e, 0x82a87e54, 0x3bdde6ab, 0xe676ab3b, 0x0b959e83, 0x9e16830b +, 0x8cc945ca, 0x4503ca8c, 0xc7bc7b29, 0x7b9529c7, 0x6b056ed3, 0x6ed6d36b, 0x286c443c, 0x44503c28, 0xa72c8b79, 0x8b5579a7, 0xbc813de2, 0x3d63e2bc, 0x1631271d, 0x272c1d16, 0xad379a76, 0x9a4176ad +, 0xdb964d3b, 0x4dad3bdb, 0x649efa56, 0xfac85664, 0x74a6d24e, 0xd2e84e74, 0x1436221e, 0x22281e14, 0x92e476db, 0x763fdb92, 0x0c121e0a, 0x1e180a0c, 0x48fcb46c, 0xb4906c48, 0xb88f37e4, 0x376be4b8 +, 0x9f78e75d, 0xe7255d9f, 0xbd0fb26e, 0xb2616ebd, 0x43692aef, 0x2a86ef43, 0xc435f1a6, 0xf193a6c4, 0x39dae3a8, 0xe372a839, 0x31c6f7a4, 0xf762a431, 0xd38a5937, 0x59bd37d3, 0xf274868b, 0x86ff8bf2 +, 0xd5835632, 0x56b132d5, 0x8b4ec543, 0xc50d438b, 0x6e85eb59, 0xebdc596e, 0xda18c2b7, 0xc2afb7da, 0x018e8f8c, 0x8f028c01, 0xb11dac64, 0xac7964b1, 0x9cf16dd2, 0x6d23d29c, 0x49723be0, 0x3b92e049 +, 0xd81fc7b4, 0xc7abb4d8, 0xacb915fa, 0x1543faac, 0xf3fa0907, 0x09fd07f3, 0xcfa06f25, 0x6f8525cf, 0xca20eaaf, 0xea8fafca, 0xf47d898e, 0x89f38ef4, 0x476720e9, 0x208ee947, 0x10382818, 0x28201810 +, 0x6f0b64d5, 0x64ded56f, 0xf0738388, 0x83fb88f0, 0x4afbb16f, 0xb1946f4a, 0x5cca9672, 0x96b8725c, 0x38546c24, 0x6c702438, 0x575f08f1, 0x08aef157, 0x732152c7, 0x52e6c773, 0x9764f351, 0xf3355197 +, 0xcbae6523, 0x658d23cb, 0xa125847c, 0x84597ca1, 0xe857bf9c, 0xbfcb9ce8, 0x3e5d6321, 0x637c213e, 0x96ea7cdd, 0x7c37dd96, 0x611e7fdc, 0x7fc2dc61, 0x0d9c9186, 0x911a860d, 0x0f9b9485, 0x941e850f +, 0xe04bab90, 0xabdb90e0, 0x7cbac642, 0xc6f8427c, 0x712657c4, 0x57e2c471, 0xcc29e5aa, 0xe583aacc, 0x90e373d8, 0x733bd890, 0x06090f05, 0x0f0c0506, 0xf7f40301, 0x03f501f7, 0x1c2a3612, 0x3638121c +, 0xc23cfea3, 0xfe9fa3c2, 0x6a8be15f, 0xe1d45f6a, 0xaebe10f9, 0x1047f9ae, 0x69026bd0, 0x6bd2d069, 0x17bfa891, 0xa82e9117, 0x9971e858, 0xe8295899, 0x3a536927, 0x6974273a, 0x27f7d0b9, 0xd04eb927 +, 0xd9914838, 0x48a938d9, 0xebde3513, 0x35cd13eb, 0x2be5ceb3, 0xce56b32b, 0x22775533, 0x55443322, 0xd204d6bb, 0xd6bfbbd2, 0xa9399070, 0x904970a9, 0x07878089, 0x800e8907, 0x33c1f2a7, 0xf266a733 +, 0x2decc1b6, 0xc15ab62d, 0x3c5a6622, 0x6678223c, 0x15b8ad92, 0xad2a9215, 0xc9a96020, 0x608920c9, 0x875cdb49, 0xdb154987, 0xaab01aff, 0x1a4fffaa, 0x50d88878, 0x88a07850, 0xa52b8e7a, 0x8e517aa5 +, 0x03898a8f, 0x8a068f03, 0x594a13f8, 0x13b2f859, 0x09929b80, 0x9b128009, 0x1a233917, 0x3934171a, 0x651075da, 0x75cada65, 0xd7845331, 0x53b531d7, 0x84d551c6, 0x5113c684, 0xd003d3b8, 0xd3bbb8d0 +, 0x82dc5ec3, 0x5e1fc382, 0x29e2cbb0, 0xcb52b029, 0x5ac39977, 0x99b4775a, 0x1e2d3311, 0x333c111e, 0x7b3d46cb, 0x46f6cb7b, 0xa8b71ffc, 0x1f4bfca8, 0x6d0c61d6, 0x61dad66d, 0x2c624e3a, 0x4e583a2c}; +#endif #endif /* __tables_h */ From 91eaea9c72f7104820aff15792ec70a3e69e7f35 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 25 Oct 2018 20:22:13 +0000 Subject: [PATCH 0191/1007] mnemonics: fix words_to_bytes on big endian --- src/mnemonics/electrum-words.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 3d6338856..c140bb5d3 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -335,6 +335,7 @@ namespace crypto return false; } + w[0] = SWAP32LE(w[0]); dst.append((const char*)&w[0], 4); // copy 4 bytes to position memwipe(w, sizeof(w)); } From 1f35de230014a19407bf9c7cc273d4ad7db76484 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 25 Oct 2018 23:02:42 +0000 Subject: [PATCH 0192/1007] simplewallet: display locked/unlocked state in show_transfers it doesn't display the details, which are already displayed in show_transfer --- src/simplewallet/simplewallet.cpp | 9 +++++---- src/wallet/wallet2.h | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 18b596662..fcbbb05ad 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -6749,7 +6749,8 @@ bool simple_wallet::show_transfers(const std::vector &args_) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); const std::string type = pd.m_coinbase ? tr("block") : tr("in"); - output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_green, type, (boost::format("%25.25s %20.20s %s %s %d %s %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); + const bool unlocked = m_wallet->is_tx_spendtime_unlocked(pd.m_unlock_time, pd.m_block_height); + output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_green, type, (boost::format("%8.8s %25.25s %20.20s %s %s %d %s %s") % (unlocked ? "unlocked" : "locked") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); } } @@ -6782,7 +6783,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(i->first); - output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_magenta, tr("out"), (boost::format("%25.25s %20.20s %s %s %14.14s %s %s - %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); + output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_magenta, tr("out"), (boost::format("%8.8s %25.25s %20.20s %s %s %14.14s %s %s - %s") % "-" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); } } @@ -6811,7 +6812,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) std::string double_spend_note; if (i->second.m_double_spend_seen) double_spend_note = tr("[Double spend seen on the network: this transaction may or may not end up being mined] "); - message_writer() << (boost::format("%8.8s %6.6s %25.25s %20.20s %s %s %d %s %s%s") % "pool" % "in" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note % double_spend_note).str(); + message_writer() << (boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %s %s %d %s %s%s") % "pool" % "in" % "locked" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note % double_spend_note).str(); } } catch (const std::exception& e) @@ -6834,7 +6835,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) std::string note = m_wallet->get_tx_note(i->first); bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; if ((failed && is_failed) || (!is_failed && pending)) { - message_writer() << (boost::format("%8.8s %6.6s %25.25s %20.20s %s %s %14.14s %s - %s") % (is_failed ? tr("failed") : tr("pending")) % tr("out") % get_human_readable_timestamp(pd.m_timestamp) % print_money(amount - pd.m_change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % print_subaddr_indices(pd.m_subaddr_indices) % note).str(); + message_writer() << (boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %s %s %14.14s %s - %s") % (is_failed ? tr("failed") : tr("pending")) % tr("out") % "-" % get_human_readable_timestamp(pd.m_timestamp) % print_money(amount - pd.m_change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % print_subaddr_indices(pd.m_subaddr_indices) % note).str(); } } } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 680196f01..509a5a5a5 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1187,6 +1187,8 @@ namespace tools void set_tx_notify(const std::shared_ptr ¬ify) { m_tx_notify = notify; } + bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const; + private: /*! * \brief Stores wallet information to wallet file. @@ -1206,7 +1208,6 @@ namespace tools void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector &tx_cache_data, size_t tx_cache_data_offset); void detach_blockchain(uint64_t height); void get_short_chain_history(std::list& ids, uint64_t granularity = 1) const; - bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint64_t block_height) const; bool clear(); void pull_blocks(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &blocks, std::vector &o_indices); void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &hashes); From dff0adfee5e658ae9442fd8b723b76e963a5cf45 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 26 Oct 2018 11:46:25 +0000 Subject: [PATCH 0193/1007] cmake: fix readline detection when the readline library is not found --- cmake/FindReadline.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake index de9ddc46d..f26911b26 100644 --- a/cmake/FindReadline.cmake +++ b/cmake/FindReadline.cmake @@ -66,7 +66,9 @@ check_function_exists(rl_copy_text HAVE_COPY_TEXT) check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION) if(NOT HAVE_COMPLETION_FUNCTION) - set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY} ${Termcap_LIBRARY}) + if (Readline_LIBRARY) + set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY} ${Termcap_LIBRARY}) + endif(Readline_LIBRARY) check_function_exists(rl_copy_text HAVE_COPY_TEXT_TC) check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION_TC) set(HAVE_COMPLETION_FUNCTION ${HAVE_COMPLETION_FUNCTION_TC}) From 30f728e3627e28ceedec2ef6ce0424c061c5ed29 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 26 Oct 2018 17:01:05 +0000 Subject: [PATCH 0194/1007] performance_tests: measure ge_frombytes_vartime only not an extra dynamic cast, which might be heavy --- tests/performance_tests/ge_frombytes_vartime.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h index ef9625d6b..3f7d55182 100644 --- a/tests/performance_tests/ge_frombytes_vartime.h +++ b/tests/performance_tests/ge_frombytes_vartime.h @@ -49,22 +49,29 @@ class test_ge_frombytes_vartime : public multi_tx_test_base<1> if (!base_class::init()) return false; + cryptonote::account_base m_alice; + cryptonote::transaction m_tx; + m_alice.generate(); std::vector destinations; destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); - return construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, boost::none, std::vector(), m_tx, 0); + if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, boost::none, std::vector(), m_tx, 0)) + return false; + + const cryptonote::txin_to_key& txin = boost::get(m_tx.vin[0]); + m_key = rct::ki2rct(txin.k_image); + + return true; } bool test() { ge_p3 unp; - const cryptonote::txin_to_key& txin = boost::get(m_tx.vin[0]); - return ge_frombytes_vartime(&unp, (const unsigned char*) &txin.k_image) == 0; + return ge_frombytes_vartime(&unp, (const unsigned char*) &m_key) == 0; } private: - cryptonote::account_base m_alice; - cryptonote::transaction m_tx; + rct::key m_key; }; From 3a056b7393aeaa1e751deb3013a55232110c7225 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 26 Oct 2018 17:02:11 +0000 Subject: [PATCH 0195/1007] performance_tests: add ge_p3_tobytes --- tests/performance_tests/ge_tobytes.h | 79 ++++++++++++++++++++++++++++ tests/performance_tests/main.cpp | 2 + 2 files changed, 81 insertions(+) create mode 100644 tests/performance_tests/ge_tobytes.h diff --git a/tests/performance_tests/ge_tobytes.h b/tests/performance_tests/ge_tobytes.h new file mode 100644 index 000000000..3d46f4838 --- /dev/null +++ b/tests/performance_tests/ge_tobytes.h @@ -0,0 +1,79 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include "crypto/crypto.h" +#include "cryptonote_basic/cryptonote_basic.h" + +#include "single_tx_test_base.h" + +class test_ge_tobytes : public multi_tx_test_base<1> +{ +public: + static const size_t loop_count = 10000; + + typedef multi_tx_test_base<1> base_class; + + bool init() + { + using namespace cryptonote; + + if (!base_class::init()) + return false; + + cryptonote::account_base m_alice; + cryptonote::transaction m_tx; + + m_alice.generate(); + + std::vector destinations; + destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); + + if (!construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, boost::none, std::vector(), m_tx, 0)) + return false; + + const cryptonote::txin_to_key& txin = boost::get(m_tx.vin[0]); + if (ge_frombytes_vartime(&m_p3, (const unsigned char*) &txin.k_image) != 0) + return false; + + return true; + } + + bool test() + { + rct::key key; + ge_p3_tobytes(key.bytes, &m_p3); + return true; + } + +private: + ge_p3 m_p3; +}; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 87a1573c2..84cd77cfb 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -42,6 +42,7 @@ #include "derive_public_key.h" #include "derive_secret_key.h" #include "ge_frombytes_vartime.h" +#include "ge_tobytes.h" #include "generate_key_derivation.h" #include "generate_key_image.h" #include "generate_key_image_helper.h" @@ -182,6 +183,7 @@ int main(int argc, char** argv) TEST_PERFORMANCE0(filter, p, test_derive_public_key); TEST_PERFORMANCE0(filter, p, test_derive_secret_key); TEST_PERFORMANCE0(filter, p, test_ge_frombytes_vartime); + TEST_PERFORMANCE0(filter, p, test_ge_tobytes); TEST_PERFORMANCE0(filter, p, test_generate_keypair); TEST_PERFORMANCE0(filter, p, test_sc_reduce32); TEST_PERFORMANCE1(filter, p, test_signature, false); From a5ca7f4fb57634b1900f2e4d55dfd7177e2bc890 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 11:14:52 +0000 Subject: [PATCH 0196/1007] core: fix unmixable special case allowing ring size below 11 --- src/cryptonote_core/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 77b6d0b69..e908c2012 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -2530,7 +2530,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, } } - if (hf_version >= HF_VERSION_MIN_MIXIN_10 && mixin != 10) + if (((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && mixin != 10) || (hf_version >= HF_VERSION_MIN_MIXIN_10+2 && mixin > 10)) { MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (mixin + 1) << "), it should be 11"); tvc.m_low_mixin = true; From 73e504c1391a1ce130e225a8440558ca298586a2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 11:15:32 +0000 Subject: [PATCH 0197/1007] rpc: adjust ring size error message now that too high is also possible --- src/rpc/core_rpc_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index aa9d3d64b..1492fc80b 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -700,7 +700,7 @@ namespace cryptonote res.status = "Failed"; res.reason = ""; if ((res.low_mixin = tvc.m_low_mixin)) - add_reason(res.reason, "ring size too small"); + add_reason(res.reason, "bad ring size"); if ((res.double_spend = tvc.m_double_spend)) add_reason(res.reason, "double spend"); if ((res.invalid_input = tvc.m_invalid_input)) From f48db530be93257c563a66b1f46ce305794159be Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 11:19:28 +0000 Subject: [PATCH 0198/1007] unit_tests: fix notify unit test when /tmp does not exist --- tests/unit_tests/notify.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index 84861cb45..4daeeddee 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -44,7 +44,14 @@ TEST(notify, works) #ifdef __GLIBC__ mode_t prevmode = umask(077); #endif - char name_template[] = "/tmp/monero-notify-unit-test-XXXXXX"; + const char *tmp = getenv("TEMP"); + if (!tmp) + tmp = "/tmp"; + static const char *filename = "monero-notify-unit-test-XXXXXX"; + const size_t len = strlen(tmp) + 1 + strlen(filename); + char *name_template = (char*)malloc(len + 1); + ASSERT_TRUE(name_template != NULL); + snprintf(name_template, len + 1, "%s/%s", tmp, filename); int fd = mkstemp(name_template); #ifdef __GLIBC__ umask(prevmode); @@ -68,4 +75,5 @@ TEST(notify, works) ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111"); boost::filesystem::remove(name_template); + free(name_template); } From 107f33985dcff17cb2bfa7bc448ab4216b0126ce Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 14:34:15 +0000 Subject: [PATCH 0199/1007] wallet2: fix ring reuse breaking when using histogram --- src/wallet/wallet2.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..509c85afa 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7166,6 +7166,9 @@ void wallet2::get_outs(std::vector> break; } } + bool use_histogram = amount != 0 || !has_rct_distribution; + if (!use_histogram) + num_outs = rct_offsets[rct_offsets.size() - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE]; // make sure the real outputs we asked for are really included, along // with the correct key and mask: this guards against an active attack From f067bb0c8b9d43a5c6bd04ee19674e8c574aea45 Mon Sep 17 00:00:00 2001 From: xiphon Date: Sat, 27 Oct 2018 15:08:52 +0000 Subject: [PATCH 0200/1007] tests: fix MSYS2 warning 'MONERO_DEFAULT_LOG_CATEGORY redefined' --- contrib/epee/include/misc_log_ex.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 530f8e636..9100a8db3 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -32,7 +32,9 @@ #include "easylogging++.h" +#undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "default" + #define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes #define MAX_LOG_FILES 50 From 0a95cdaa803ac06d9fb29aff7f54e4a316cba8c3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 17:38:03 +0000 Subject: [PATCH 0201/1007] blockchain_utilities: fix logs and cout output colliding --- src/blockchain_utilities/blockchain_import.cpp | 4 ++-- src/blockchain_utilities/bootstrap_file.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 7f92ecd87..eae078ea2 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -396,7 +396,7 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path { std::cout << refresh_string << "block " << h-1 << " / " << block_stop - << std::flush; + << "\r" << std::flush; std::cout << ENDL << ENDL; MINFO("Specified block number reached - stopping. block: " << h-1 << " total blocks: " << h); quit = 1; @@ -432,7 +432,7 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path { std::cout << refresh_string << "block " << h-1 << " / " << block_stop - << std::flush; + << "\r" << std::flush; } if (opt_verify) diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index beaad2abc..a8c46d661 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -304,7 +304,7 @@ bool BootstrapFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem } if (m_cur_height % progress_interval == 0) { std::cout << refresh_string; - std::cout << "block " << m_cur_height << "/" << block_stop << std::flush; + std::cout << "block " << m_cur_height << "/" << block_stop << "\r" << std::flush; } } // NOTE: use of NUM_BLOCKS_PER_CHUNK is a placeholder in case multi-block chunks are later supported. @@ -479,7 +479,7 @@ uint64_t BootstrapFile::count_blocks(const std::string& import_file_path, std::s bytes_read += count_bytes(import_file, progress_interval, blocks, quit); h += blocks; std::cout << "\r" << "block height: " << h-1 << - " " << + " \r" << std::flush; // std::cout << refresh_string; From 9335d5a2976d97c294c450a9609e32971801e63b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 17:54:57 +0000 Subject: [PATCH 0202/1007] wallet2: save ring in the ringdb once a tx is created Even if it is never relayed, it ensures a daemon supplying fake outs on demand will never be asked for a set with the real input being the only intersecting member (only a problem with people who trust their privacy to some stranger's node, but it seems to be a massively common thing, even in Monero) --- src/wallet/wallet2.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..28e5f625d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7258,6 +7258,20 @@ void wallet2::get_outs(std::vector> outs.push_back(v); } } + + // save those outs in the ringdb for reuse + for (size_t i = 0; i < selected_transfers.size(); ++i) + { + const size_t idx = selected_transfers[i]; + THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error, "selected_transfers entry out of range"); + const transfer_details &td = m_transfers[idx]; + std::vector ring; + ring.reserve(outs[i].size()); + for (const auto &e: outs[i]) + ring.push_back(std::get<0>(e)); + if (!set_ring(td.m_key_image, ring, false)) + MERROR("Failed to set ring for " << td.m_key_image); + } } template From b3e8677c7045858f1ab1dea194442aaedd2c13ca Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 27 Oct 2018 18:07:55 +0000 Subject: [PATCH 0203/1007] cryptonote: use logging functions for errors, not std::cout --- src/cryptonote_basic/cryptonote_basic_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index b18ef1c5c..c4e10851e 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -328,7 +328,7 @@ bool parse_hash256(const std::string str_hash, crypto::hash& hash) bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); if (!res || buf.size() != sizeof(crypto::hash)) { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; + MERROR("invalid hash format: " << str_hash); return false; } else From dad5bbfdf9597eb699f70c209c286b4c48cb1bd8 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Sun, 28 Oct 2018 09:50:33 -0400 Subject: [PATCH 0204/1007] return message in stop_mining if mining never started --- src/rpc/core_rpc_server.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index aa9d3d64b..acce2d5d0 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -801,7 +801,14 @@ namespace cryptonote bool core_rpc_server::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res) { PERF_TIMER(on_stop_mining); - if(!m_core.get_miner().stop()) + cryptonote::miner &miner= m_core.get_miner(); + if(!miner.is_mining()) + { + res.status = "Mining never started"; + LOG_PRINT_L0(res.status); + return true; + } + if(!miner.stop()) { res.status = "Failed, mining not stopped"; LOG_PRINT_L0(res.status); From e86af52e2f0a990a9797c4e4a3a6b4a6df496c02 Mon Sep 17 00:00:00 2001 From: Nathan Dorfman Date: Thu, 25 Oct 2018 18:03:18 -0600 Subject: [PATCH 0205/1007] wallet2: rewrite keys file in a safer manner --- src/wallet/wallet2.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..f0fc94bc5 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3140,13 +3140,22 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable crypto::chacha20(account_data.data(), account_data.size(), key, keys_file_data.iv, &cipher[0]); keys_file_data.account_data = cipher; - unlock_keys_file(); + std::string tmp_file_name = keys_file_name + ".new"; std::string buf; r = ::serialization::dump_binary(keys_file_data, buf); - r = r && epee::file_io_utils::save_string_to_file(keys_file_name, buf); //and never touch wallet_keys_file again, only read - CHECK_AND_ASSERT_MES(r, false, "failed to generate wallet keys file " << keys_file_name); + r = r && epee::file_io_utils::save_string_to_file(tmp_file_name, buf); + CHECK_AND_ASSERT_MES(r, false, "failed to generate wallet keys file " << tmp_file_name); + + unlock_keys_file(); + std::error_code e = tools::replace_file(tmp_file_name, keys_file_name); lock_keys_file(); + if (e) { + boost::filesystem::remove(tmp_file_name); + LOG_ERROR("failed to update wallet keys file " << keys_file_name); + return false; + } + return true; } //---------------------------------------------------------------------------------------------------- From 9c1c92db659c9cc36232bd0123561f327e22d515 Mon Sep 17 00:00:00 2001 From: xiphon Date: Sat, 27 Oct 2018 14:35:33 +0000 Subject: [PATCH 0206/1007] tests: fix MSYS2 gcc 7.3.0 warning -Wtype-limits --- tests/unit_tests/keccak.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/keccak.cpp b/tests/unit_tests/keccak.cpp index 4276b0e1d..37da65d76 100644 --- a/tests/unit_tests/keccak.cpp +++ b/tests/unit_tests/keccak.cpp @@ -37,7 +37,7 @@ extern "C" { #define TEST_KECCAK(sz, chunks) \ std::string data; \ data.resize(sz); \ - for (size_t i = 0; i < sz; ++i) \ + for (size_t i = 0; i < data.size(); ++i) \ data[i] = i * 17; \ uint8_t md0[32], md1[32]; \ keccak((const uint8_t*)data.data(), data.size(), md0, 32); \ From 6789385cd0b98a834e87a4ee5764f217f7ef4271 Mon Sep 17 00:00:00 2001 From: MoroccanMalinois Date: Mon, 29 Oct 2018 09:17:32 +0100 Subject: [PATCH 0207/1007] Dockerfile: add udev, libusb and hidapi build --- Dockerfile | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cd3e7df70..86d833a98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,9 @@ RUN set -ex && \ libtool-bin \ autoconf \ automake \ - bzip2 + bzip2 \ + xsltproc \ + gperf WORKDIR /usr/local @@ -109,6 +111,42 @@ RUN set -ex \ && make check \ && make install +# Udev +ARG UDEV_VERSION=v3.2.6 +ARG UDEV_HASH=0c35b136c08d64064efa55087c54364608e65ed6 +RUN set -ex \ + && git clone https://github.com/gentoo/eudev -b ${UDEV_VERSION} \ + && cd eudev \ + && test `git rev-parse HEAD` = ${UDEV_HASH} || exit 1 \ + && ./autogen.sh \ + && CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure --disable-gudev --disable-introspection --disable-hwdb --disable-manpages --disable-shared \ + && make \ + && make install + +# Libusb +ARG USB_VERSION=v1.0.22 +ARG USB_HASH=0034b2afdcdb1614e78edaa2a9e22d5936aeae5d +RUN set -ex \ + && git clone https://github.com/libusb/libusb.git -b ${USB_VERSION} \ + && cd libusb \ + && test `git rev-parse HEAD` = ${USB_HASH} || exit 1 \ + && ./autogen.sh \ + && CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure --disable-shared \ + && make \ + && make install + +# Hidapi +ARG HIDAPI_VERSION=hidapi-0.8.0-rc1 +ARG HIDAPI_HASH=40cf516139b5b61e30d9403a48db23d8f915f52c +RUN set -ex \ + && git clone https://github.com/signal11/hidapi -b ${HIDAPI_VERSION} \ + && cd hidapi \ + && test `git rev-parse HEAD` = ${HIDAPI_HASH} || exit 1 \ + && ./bootstrap \ + && CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure --enable-static --disable-shared \ + && make \ + && make install + WORKDIR /src COPY . . From cbe0122bf18d702e1fb7c383ff3681544bb74005 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 8 Oct 2018 13:09:18 +0000 Subject: [PATCH 0208/1007] wallet2: initialize amount to 0 in tx_scan_info_t ctor It seems the more prudent thing to do here. It will not catch attempts to use that value before it is initialized when using ASAN or valgrind, but in a case where it does, it will have smaller repercussions. So it seems appropriate in this particular case. Coverity 182498 --- src/wallet/wallet2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 680196f01..caf77c60f 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -229,7 +229,7 @@ namespace tools bool error; boost::optional received; - tx_scan_info_t(): money_transfered(0), error(true) {} + tx_scan_info_t(): amount(0), money_transfered(0), error(true) {} }; struct transfer_details From d9400f69eb8ab69470d6f3040e73a255fc3e3b5e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 29 Oct 2018 16:10:22 +0000 Subject: [PATCH 0209/1007] serializtion: add missing mainnet and stagenet fields for 0mq Coverity 184940 --- src/serialization/json_object.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 89a1dbd23..6e8160d2e 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1192,7 +1192,9 @@ void toJsonValue(rapidjson::Document& doc, const cryptonote::rpc::DaemonInfo& in INSERT_INTO_JSON_OBJECT(val, doc, incoming_connections_count, info.incoming_connections_count); INSERT_INTO_JSON_OBJECT(val, doc, white_peerlist_size, info.white_peerlist_size); INSERT_INTO_JSON_OBJECT(val, doc, grey_peerlist_size, info.grey_peerlist_size); + INSERT_INTO_JSON_OBJECT(val, doc, mainnet, info.mainnet); INSERT_INTO_JSON_OBJECT(val, doc, testnet, info.testnet); + INSERT_INTO_JSON_OBJECT(val, doc, stagenet, info.stagenet); INSERT_INTO_JSON_OBJECT(val, doc, nettype, info.nettype); INSERT_INTO_JSON_OBJECT(val, doc, top_block_hash, info.top_block_hash); INSERT_INTO_JSON_OBJECT(val, doc, cumulative_difficulty, info.cumulative_difficulty); @@ -1221,7 +1223,9 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::DaemonInfo& inf GET_FROM_JSON_OBJECT(val, info.incoming_connections_count, incoming_connections_count); GET_FROM_JSON_OBJECT(val, info.white_peerlist_size, white_peerlist_size); GET_FROM_JSON_OBJECT(val, info.grey_peerlist_size, grey_peerlist_size); + GET_FROM_JSON_OBJECT(val, info.mainnet, mainnet); GET_FROM_JSON_OBJECT(val, info.testnet, testnet); + GET_FROM_JSON_OBJECT(val, info.stagenet, stagenet); GET_FROM_JSON_OBJECT(val, info.nettype, nettype); GET_FROM_JSON_OBJECT(val, info.top_block_hash, top_block_hash); GET_FROM_JSON_OBJECT(val, info.cumulative_difficulty, cumulative_difficulty); From 2362baf735a55437e9a6b1dc73b4ccaa3fb9305f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 29 Oct 2018 16:14:18 +0000 Subject: [PATCH 0210/1007] network_throttle: initialize m_last_sample_time in ctor Coverity 136593 --- contrib/epee/src/network_throttle-detail.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index 28c85bb78..6f727a1cf 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -150,6 +150,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri m_any_packet_yet = false; m_slot_size = 1.0; // hard coded in few places m_target_speed = 16 * 1024; // other defaults are probably defined in the command-line parsing code when this class is used e.g. as main global throttle + m_last_sample_time = 0; } void network_throttle::set_name(const std::string &name) From 157054b8402b8445485c3cdc9ac8ca0237d3b422 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 29 Oct 2018 16:15:22 +0000 Subject: [PATCH 0211/1007] hardfork: initialize current_fork_index in ctor Also order init list to match actual runtime init order Coverity 136605 --- src/cryptonote_basic/hardfork.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index f05b25901..87a394918 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_basic/hardfork.cpp @@ -56,12 +56,13 @@ static uint8_t get_block_version(const cryptonote::block &b) HardFork::HardFork(cryptonote::BlockchainDB &db, uint8_t original_version, uint64_t original_version_till_height, time_t forked_time, time_t update_time, uint64_t window_size, uint8_t default_threshold_percent): db(db), - original_version(original_version), - original_version_till_height(original_version_till_height), forked_time(forked_time), update_time(update_time), window_size(window_size), - default_threshold_percent(default_threshold_percent) + default_threshold_percent(default_threshold_percent), + original_version(original_version), + original_version_till_height(original_version_till_height), + current_fork_index(0) { if (window_size == 0) throw "window_size needs to be strictly positive"; From f3019efe1b04cbb835927c4ec349d57d5991fa17 Mon Sep 17 00:00:00 2001 From: Hasan Pekdemir Date: Sun, 28 Oct 2018 03:50:17 +0100 Subject: [PATCH 0212/1007] wallet-rpc: add on_restore_deterministic RPC call. --- src/wallet/wallet_rpc_server.cpp | 194 +++++++++++++++++++ src/wallet/wallet_rpc_server.h | 2 + src/wallet/wallet_rpc_server_commands_defs.h | 39 +++- 3 files changed, 234 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 6dbea2e14..9c94093a4 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3089,6 +3089,200 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request &req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response &res, epee::json_rpc::error &er) + { + if (m_wallet_dir.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; + er.message = "No wallet dir configured"; + return false; + } + + // early check for mandatory fields + if (req.filename.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'filename' is mandatory. Please provide a filename to save the restored wallet to."; + return false; + } + if (req.seed.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'seed' is mandatory. Please provide a seed you want to restore from."; + return false; + } + + namespace po = boost::program_options; + po::variables_map vm2; + const char *ptr = strchr(req.filename.c_str(), '/'); + #ifdef _WIN32 + if (!ptr) + ptr = strchr(req.filename.c_str(), '\\'); + if (!ptr) + ptr = strchr(req.filename.c_str(), ':'); + #endif + if (ptr) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Invalid filename"; + return false; + } + std::string wallet_file = m_wallet_dir + "/" + req.filename; + // check if wallet file already exists + if (!wallet_file.empty()) + { + try + { + boost::system::error_code ignored_ec; + THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(wallet_file, ignored_ec), error::file_exists, wallet_file); + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet already exists."; + return false; + } + } + crypto::secret_key recovery_key; + std::string old_language; + + // check the given seed + { + if (!crypto::ElectrumWords::words_to_bytes(req.seed, recovery_key, old_language)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Electrum-style word list failed verification"; + return false; + } + } + + // process seed_offset if given + { + if (!req.seed_offset.empty()) + { + recovery_key = cryptonote::decrypt_key(recovery_key, req.seed_offset); + } + } + { + po::options_description desc("dummy"); + const command_line::arg_descriptor arg_password = {"password", "password"}; + const char *argv[4]; + int argc = 3; + argv[0] = "wallet-rpc"; + argv[1] = "--password"; + argv[2] = req.password.c_str(); + argv[3] = NULL; + vm2 = *m_vm; + command_line::add_arg(desc, arg_password); + po::store(po::parse_command_line(argc, argv, desc), vm2); + } + + auto rc = tools::wallet2::make_new(vm2, true, nullptr); + std::unique_ptr wal; + wal = std::move(rc.first); + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to create wallet"; + return false; + } + + epee::wipeable_string password = rc.second.password(); + + bool was_deprecated_wallet = ((old_language == crypto::ElectrumWords::old_language_name) || + crypto::ElectrumWords::get_is_old_style_seed(req.seed)); + + std::string mnemonic_language = old_language; + if (was_deprecated_wallet) + { + // The user had used an older version of the wallet with old style mnemonics. + res.was_deprecated = true; + } + + if (old_language == crypto::ElectrumWords::old_language_name) + { + if (req.language.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet was using the old seed language. You need to specify a new seed language."; + return false; + } + std::vector language_list; + std::vector language_list_en; + crypto::ElectrumWords::get_language_list(language_list); + crypto::ElectrumWords::get_language_list(language_list_en, true); + if (std::find(language_list.begin(), language_list.end(), req.language) == language_list.end() && + std::find(language_list_en.begin(), language_list_en.end(), req.language) == language_list_en.end()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet was using the old seed language, and the specified new seed language is invalid."; + return false; + } + mnemonic_language = req.language; + } + + wal->set_seed_language(mnemonic_language); + + crypto::secret_key recovery_val; + try + { + recovery_val = wal->generate(wallet_file, std::move(rc.second).password(), recovery_key, true, false, false); + MINFO("Wallet has been restored.\n"); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + // // Convert the secret key back to seed + epee::wipeable_string electrum_words; + if (!crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, mnemonic_language)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to encode seed"; + return false; + } + res.seed = electrum_words.data(); + + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to generate wallet"; + return false; + } + + // set blockheight if given + try + { + wal->set_refresh_from_block_height(req.restore_height); + wal->rewrite(wallet_file, password); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (m_wallet) + { + try + { + m_wallet->store(); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + delete m_wallet; + } + m_wallet = wal.release(); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + res.info = "Wallet has been restored successfully."; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er) { if (!m_wallet) return not_open(er); diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 887723ed5..abbbe82c5 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -137,6 +137,7 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) + MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) MAP_JON_RPC_WE("prepare_multisig", on_prepare_multisig, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG) MAP_JON_RPC_WE("make_multisig", on_make_multisig, wallet_rpc::COMMAND_RPC_MAKE_MULTISIG) @@ -216,6 +217,7 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er); + bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er); bool on_prepare_multisig(const wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::response& res, epee::json_rpc::error& er); bool on_make_multisig(const wallet_rpc::COMMAND_RPC_MAKE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_MAKE_MULTISIG::response& res, epee::json_rpc::error& er); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 924f3a0f1..b389c5e83 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 5 +#define WALLET_RPC_VERSION_MINOR 6 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -1924,6 +1924,43 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET + { + struct request + { + uint64_t restore_height; + std::string filename; + std::string seed; + std::string seed_offset; + std::string password; + std::string language; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(restore_height, (uint64_t)0) + KV_SERIALIZE(filename) + KV_SERIALIZE(seed) + KV_SERIALIZE(seed_offset) + KV_SERIALIZE(password) + KV_SERIALIZE(language) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string address; + std::string seed; + std::string info; + bool was_deprecated; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(seed) + KV_SERIALIZE(info) + KV_SERIALIZE(was_deprecated) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_IS_MULTISIG { struct request From aa40047e480c6668a7d2067a5e84230ab551aeec Mon Sep 17 00:00:00 2001 From: Neofito89 <37967500+Neofito89@users.noreply.github.com> Date: Mon, 29 Oct 2018 23:14:25 +0100 Subject: [PATCH 0213/1007] README.md: increase swap size on Raspberry Pi Increased swap size on raspberry pi compiling guide, since it might crash if the raspberry has any service runing in the background --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index be7dc8b2d..bd332ebc8 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch ( ``` sudo /etc/init.d/dphys-swapfile stop sudo nano /etc/dphys-swapfile - CONF_SWAPSIZE=1024 + CONF_SWAPSIZE=2048 sudo /etc/init.d/dphys-swapfile start ``` * If using an external hard disk without an external power supply, ensure it gets enough power to avoid hardware issues when syncing, by adding the line "max_usb_current=1" to /boot/config.txt @@ -270,7 +270,7 @@ If you are using the older Raspbian Jessie image, compiling Monero is a bit more ``` sudo /etc/init.d/dphys-swapfile stop sudo nano /etc/dphys-swapfile - CONF_SWAPSIZE=1024 + CONF_SWAPSIZE=2048 sudo /etc/init.d/dphys-swapfile start ``` From db24a2e50934010ca0638c28920645365d1b8130 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 25 Oct 2018 21:15:19 +0000 Subject: [PATCH 0214/1007] hash: fix hash_permutation on big endian --- src/crypto/hash.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 42f272e34..43ce32957 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -36,7 +36,14 @@ #include "keccak.h" void hash_permutation(union hash_state *state) { +#if BYTE_ORDER == LITTLE_ENDIAN keccakf((uint64_t*)state, 24); +#else + uint64_t le_state[25]; + memcpy_swap64le(le_state, state, 25); + keccakf(le_state, 24); + memcpy_swap64le(state, le_state, 25); +#endif } void hash_process(union hash_state *state, const uint8_t *buf, size_t count) { From 8a7e20f8a5b7984355a169fdbc885500f87a0783 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 30 Oct 2018 05:04:57 +0000 Subject: [PATCH 0215/1007] build: older git versions don't have '-C' flag --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a685ee8e..dd5561f60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,8 +176,8 @@ if(NOT MANUAL_SUBMODULES) find_package(Git) if(GIT_FOUND) function (check_submodule relative_path) - execute_process(COMMAND git -C ${relative_path} rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE localHead) - execute_process(COMMAND git rev-parse "HEAD:${relative_path}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE checkedHead) + execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${relative_path} OUTPUT_VARIABLE localHead) + execute_process(COMMAND git rev-parse "HEAD:${relative_path}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE checkedHead) string(COMPARE EQUAL "${localHead}" "${checkedHead}" upToDate) if (upToDate) message(STATUS "Submodule '${relative_path}' is up-to-date") From 42d8d5085e96732e96fcb39f4b851bc85f4e4a8b Mon Sep 17 00:00:00 2001 From: xiphon Date: Wed, 31 Oct 2018 03:13:55 +0000 Subject: [PATCH 0216/1007] crypto: fix AES encryption on big endian --- src/crypto/aesb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crypto/aesb.c b/src/crypto/aesb.c index 5d57b8af4..8a22a4b93 100644 --- a/src/crypto/aesb.c +++ b/src/crypto/aesb.c @@ -19,6 +19,7 @@ Issue Date: 20/12/2007 */ #include +#include "common/int-util.h" #if defined(__cplusplus) extern "C" @@ -50,7 +51,7 @@ extern "C" #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) #define to_byte(x) ((x) & 0xff) -#define bval(x,n) to_byte((x) >> (8 * (n))) +#define bval(x,n) to_byte(SWAP32LE(x) >> (8 * (n))) #define fwd_var(x,r,c)\ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ @@ -58,7 +59,7 @@ extern "C" : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) -#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ SWAP32LE(four_tables(x,t_use(f,n),fwd_var,rf1,c))) #define sb_data(w) {\ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ From 1598f01caf72eb9a8fd93f21213b5ac2671a7f0e Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 31 Oct 2018 20:00:57 +0900 Subject: [PATCH 0217/1007] wallet2: use padded bulletproofs for multisig signing Analogous to #4540 --- src/wallet/wallet2.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..6ec67c2e1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5997,10 +5997,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector 1) - range_proof_type = rct::RangeProofPaddedBulletproof; + range_proof_type = rct::RangeProofPaddedBulletproof; } bool r = cryptonote::construct_tx_with_tx_key(m_account.get_keys(), m_subaddresses, sources, sd.splitted_dsts, ptx.change_dts.addr, sd.extra, tx, sd.unlock_time, ptx.tx_key, ptx.additional_tx_keys, sd.use_rct, range_proof_type, &msout, false); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); From 09dbd9cbbc3d04587569f26740f875808f2a3dae Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 12:14:30 +0000 Subject: [PATCH 0218/1007] tx_pool: fix comment about transaction_prefix It was leftover from a change that was undone before commit, but the comment change was let through --- src/cryptonote_core/tx_pool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 7a0cc23bf..be00f8fc1 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -510,7 +510,7 @@ namespace cryptonote * @param txd the transaction to check (and info about it) * @param txid the txid of the transaction to check * @param txblob the transaction blob to check - * @param tx the parsed transaction prefix, if successful + * @param tx the parsed transaction, if successful * * @return true if the transaction is good to go, otherwise false */ From cf552c752d3ddc2a7c7fcc4bfab756b794a16865 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 14:43:13 +0000 Subject: [PATCH 0219/1007] tx_pool: allow take_tx to work without m_txs_by_fee_and_receive_time This should make it possible to have two daemons running on the same database again. --- src/cryptonote_core/tx_pool.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 553a22298..86ce83346 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -454,8 +454,6 @@ namespace cryptonote CRITICAL_REGION_LOCAL1(m_blockchain); auto sorted_it = find_tx_in_sorted_container(id); - if (sorted_it == m_txs_by_fee_and_receive_time.end()) - return false; try { @@ -489,7 +487,8 @@ namespace cryptonote return false; } - m_txs_by_fee_and_receive_time.erase(sorted_it); + if (sorted_it != m_txs_by_fee_and_receive_time.end()) + m_txs_by_fee_and_receive_time.erase(sorted_it); ++m_cookie; return true; } From 2bd46065ae894d9de026548bc42ec9e4b8f97f89 Mon Sep 17 00:00:00 2001 From: RaskaRuby Date: Wed, 31 Oct 2018 14:47:20 -0700 Subject: [PATCH 0220/1007] Expose limit-rate defaults from command line help --- src/cryptonote_config.h | 2 ++ src/p2p/net_node.cpp | 4 ++-- src/p2p/net_node.h | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index c62eeb738..496678b5e 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -113,6 +113,8 @@ #define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds #define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70 #define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2 +#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s +#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s #define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour #define P2P_IP_BLOCKTIME (60*60*24) //24 hour diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index e9d2061e8..7cad6e077 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -62,8 +62,8 @@ namespace nodetool const command_line::arg_descriptor arg_in_peers = {"in-peers", "set max number of in peers", -1}; const command_line::arg_descriptor arg_tos_flag = {"tos-flag", "set TOS flag", -1}; - const command_line::arg_descriptor arg_limit_rate_up = {"limit-rate-up", "set limit-rate-up [kB/s]", -1}; - const command_line::arg_descriptor arg_limit_rate_down = {"limit-rate-down", "set limit-rate-down [kB/s]", -1}; + const command_line::arg_descriptor arg_limit_rate_up = {"limit-rate-up", "set limit-rate-up [kB/s]", P2P_DEFAULT_LIMIT_RATE_UP}; + const command_line::arg_descriptor arg_limit_rate_down = {"limit-rate-down", "set limit-rate-down [kB/s]", P2P_DEFAULT_LIMIT_RATE_DOWN}; const command_line::arg_descriptor arg_limit_rate = {"limit-rate", "set limit-rate [kB/s]", -1}; const command_line::arg_descriptor arg_save_graph = {"save-graph", "Save data for dr monero", false}; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 90e2f78b1..1c348cac4 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -337,8 +337,8 @@ namespace nodetool cryptonote::network_type m_nettype; }; - const int64_t default_limit_up = 2048; // kB/s - const int64_t default_limit_down = 8192; // kB/s + const int64_t default_limit_up = P2P_DEFAULT_LIMIT_RATE_UP; // kB/s + const int64_t default_limit_down = P2P_DEFAULT_LIMIT_RATE_DOWN; // kB/s extern const command_line::arg_descriptor arg_p2p_bind_ip; extern const command_line::arg_descriptor arg_p2p_bind_port; extern const command_line::arg_descriptor arg_p2p_external_port; From 00cc1a1657be9b0d726780cdd541631d1b239da0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 21:54:19 +0000 Subject: [PATCH 0221/1007] unit_tests: notify test special case for the usual weirdo --- tests/unit_tests/notify.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index e2477a76e..84861cb45 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -52,7 +52,11 @@ TEST(notify, works) ASSERT_TRUE(fd >= 0); close(fd); - const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier " + name_template + " %s"; + const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier" +#ifdef _WIN32 + + ".exe" +#endif + + " " + name_template + " %s"; tools::Notify notify(spec.c_str()); notify.notify("1111111111111111111111111111111111111111111111111111111111111111"); From 6ecc99ad1fd0f2b86641669077130394ab21e71c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 08:31:13 +0000 Subject: [PATCH 0222/1007] core: avoid unnecessary tx/blob conversions --- src/blockchain_db/blockchain_db.h | 2 +- src/blockchain_db/lmdb/db_lmdb.cpp | 6 ++---- src/blockchain_db/lmdb/db_lmdb.h | 2 +- src/cryptonote_core/blockchain.cpp | 4 ++-- src/cryptonote_core/blockchain.h | 2 +- src/cryptonote_core/cryptonote_core.cpp | 8 ++++---- src/cryptonote_core/cryptonote_core.h | 3 ++- src/cryptonote_core/tx_pool.cpp | 12 +++++++----- src/cryptonote_core/tx_pool.h | 2 +- tests/unit_tests/hardfork.cpp | 2 +- 10 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 71c46d76b..7118b0881 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1349,7 +1349,7 @@ class BlockchainDB * * @param details the details of the transaction to add */ - virtual void add_txpool_tx(const transaction &tx, const txpool_tx_meta_t& details) = 0; + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) = 0; /** * @brief update a txpool transaction's metadata diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index bd91f308a..b1248c492 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1591,7 +1591,7 @@ void BlockchainLMDB::unlock() auto_txn.commit(); \ } while(0) -void BlockchainLMDB::add_txpool_tx(const transaction &tx, const txpool_tx_meta_t &meta) +void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1600,8 +1600,6 @@ void BlockchainLMDB::add_txpool_tx(const transaction &tx, const txpool_tx_meta_t CURSOR(txpool_meta) CURSOR(txpool_blob) - const crypto::hash txid = get_transaction_hash(tx); - MDB_val k = {sizeof(txid), (void *)&txid}; MDB_val v = {sizeof(meta), (void *)&meta}; if (auto result = mdb_cursor_put(m_cur_txpool_meta, &k, &v, MDB_NODUPDATA)) { @@ -1610,7 +1608,7 @@ void BlockchainLMDB::add_txpool_tx(const transaction &tx, const txpool_tx_meta_t else throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str())); } - MDB_val_copy blob_val(tx_to_blob(tx)); + MDB_val_copy blob_val(blob); if (auto result = mdb_cursor_put(m_cur_txpool_blob, &k, &blob_val, MDB_NODUPDATA)) { if (result == MDB_KEYEXIST) throw1(DB_ERROR("Attempting to add txpool tx blob that's already in the db")); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index e1f748ed8..7e76236a5 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -256,7 +256,7 @@ class BlockchainLMDB : public BlockchainDB virtual bool has_key_image(const crypto::key_image& img) const; - virtual void add_txpool_tx(const transaction &tx, const txpool_tx_meta_t& meta); + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta); virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta); virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; virtual bool txpool_has_tx(const crypto::hash &txid) const; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 77b6d0b69..7576e0ed7 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4254,9 +4254,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vectoradd_txpool_tx(tx, meta); + m_db->add_txpool_tx(txid, blob, meta); } void Blockchain::update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta) diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index f140d7719..9639d4e7d 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -939,7 +939,7 @@ namespace cryptonote */ std::list>> get_alternative_chains() const; - void add_txpool_tx(transaction &tx, const txpool_tx_meta_t &meta); + void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta); void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta); void remove_txpool_tx(const crypto::hash &txid); uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index d8c38bf9e..343be0557 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -909,7 +909,7 @@ namespace cryptonote } const size_t weight = get_transaction_weight(results[i].tx, it->size()); - ok &= add_new_tx(results[i].tx, results[i].hash, results[i].prefix_hash, weight, tvc[i], keeped_by_block, relayed, do_not_relay); + ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], results[i].prefix_hash, weight, tvc[i], keeped_by_block, relayed, do_not_relay); if(tvc[i].m_verifivation_failed) {MERROR_VER("Transaction verification failed: " << results[i].hash);} else if(tvc[i].m_verifivation_impossible) @@ -1127,7 +1127,7 @@ namespace cryptonote blobdata bl; t_serializable_object_to_blob(tx, bl); size_t tx_weight = get_transaction_weight(tx, bl.size()); - return add_new_tx(tx, tx_hash, tx_prefix_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay); + return add_new_tx(tx, tx_hash, bl, tx_prefix_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay); } //----------------------------------------------------------------------------------------------- size_t core::get_blockchain_total_transactions() const @@ -1135,7 +1135,7 @@ namespace cryptonote return m_blockchain_storage.get_total_transactions(); } //----------------------------------------------------------------------------------------------- - bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) + bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { if (keeped_by_block) get_blockchain_storage().on_new_tx_from_block(tx); @@ -1153,7 +1153,7 @@ namespace cryptonote } uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); - return m_mempool.add_tx(tx, tx_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version); + return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version); } //----------------------------------------------------------------------------------------------- bool core::relay_txpool_transactions() diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 80c452f53..85efc0640 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -783,13 +783,14 @@ namespace cryptonote * @copydoc add_new_tx(transaction&, tx_verification_context&, bool) * * @param tx_hash the transaction's hash + * @param blob the transaction as a blob * @param tx_prefix_hash the transaction prefix' hash * @param tx_weight the weight of the transaction * @param relayed whether or not the transaction was relayed to us * @param do_not_relay whether to prevent the transaction from being relayed * */ - bool add_new_tx(transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay); + bool add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay); /** * @brief add a new transaction to the transaction pool diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 553a22298..d51c84594 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -111,7 +111,7 @@ namespace cryptonote } //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version) + bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version) { // this should already be called with that lock, but let's make it explicit for clarity CRITICAL_REGION_LOCAL(m_transactions_lock); @@ -249,7 +249,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); - m_blockchain.add_txpool_tx(tx, meta); + m_blockchain.add_txpool_tx(id, blob, meta); if (!insert_key_images(tx, id, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair(fee / (double)tx_weight, receive_time), id); @@ -292,7 +292,7 @@ namespace cryptonote LockedTXN lock(m_blockchain); const crypto::hash txid = get_transaction_hash(tx); m_blockchain.remove_txpool_tx(txid); - m_blockchain.add_txpool_tx(tx, meta); + m_blockchain.add_txpool_tx(txid, blob, meta); if (!insert_key_images(tx, txid, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair(fee / (double)tx_weight, receive_time), id); @@ -324,9 +324,11 @@ namespace cryptonote { crypto::hash h = null_hash; size_t blob_size = 0; - if (!get_transaction_hash(tx, h, blob_size) || blob_size == 0) + cryptonote::blobdata bl; + t_serializable_object_to_blob(tx, bl); + if (bl.size() == 0 || !get_transaction_hash(tx, h)) return false; - return add_tx(tx, h, get_transaction_weight(tx, blob_size), tvc, keeped_by_block, relayed, do_not_relay, version); + return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, keeped_by_block, relayed, do_not_relay, version); } //--------------------------------------------------------------------------------- size_t tx_memory_pool::get_txpool_weight() const diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 7a0cc23bf..09d134d7b 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -107,7 +107,7 @@ namespace cryptonote * @param id the transaction's hash * @param tx_weight the transaction's weight */ - bool add_tx(transaction &tx, const crypto::hash &id, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version); + bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version); /** * @brief add a transaction to the transaction pool diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index 47177db1c..fc488bb14 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -118,7 +118,7 @@ class TestDB: public BlockchainDB { virtual std::map> get_output_histogram(const std::vector &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { return std::map>(); } virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector &distribution, uint64_t &base) const { return false; } - virtual void add_txpool_tx(const transaction &tx, const txpool_tx_meta_t& details) {} + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) {} virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& details) {} virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; } virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; } From 593ef5981d0336bbe745936b166cd24ec754cac4 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 13:36:34 +0000 Subject: [PATCH 0223/1007] perf_timer: call reserve on new timer array to avoid reallocations in the vast majority of the time --- src/common/perf_timer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index 6910ebdd4..c5503416f 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -110,6 +110,7 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, uint64_t { MLOG(level, "PERF ----------"); performance_timers = new std::vector(); + performance_timers->reserve(16); // how deep before realloc } else { From 4f005a77c24d91f9f292530d928913263553fcc2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 13:51:48 +0000 Subject: [PATCH 0224/1007] tx_pool: remove unnecessary get_transaction_hash --- src/cryptonote_core/tx_pool.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index d51c84594..a31c9d3ed 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -290,10 +290,9 @@ namespace cryptonote { CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); - const crypto::hash txid = get_transaction_hash(tx); - m_blockchain.remove_txpool_tx(txid); - m_blockchain.add_txpool_tx(txid, blob, meta); - if (!insert_key_images(tx, txid, kept_by_block)) + m_blockchain.remove_txpool_tx(id); + m_blockchain.add_txpool_tx(id, blob, meta); + if (!insert_key_images(tx, id, kept_by_block)) return false; m_txs_by_fee_and_receive_time.emplace(std::pair(fee / (double)tx_weight, receive_time), id); } From bf31447e9bd9e424538abc8f4cb57bd133f439ed Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 13:52:16 +0000 Subject: [PATCH 0225/1007] tx_pool: speed up take_tx for transactions from blocks This happens for every historical tx when syncing, and the unnecessary parsing is actually showing up on profile. Since these are kept cached for just one block, this does not increase memory usage after syncing. --- src/cryptonote_core/tx_pool.cpp | 13 ++++++++++++- src/cryptonote_core/tx_pool.h | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index a31c9d3ed..19467aec7 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -247,6 +247,8 @@ namespace cryptonote memset(meta.padding, 0, sizeof(meta.padding)); try { + if (kept_by_block) + m_parsed_tx_cache.insert(std::make_pair(id, tx)); CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); m_blockchain.add_txpool_tx(id, blob, meta); @@ -288,6 +290,8 @@ namespace cryptonote try { + if (kept_by_block) + m_parsed_tx_cache.insert(std::make_pair(id, tx)); CRITICAL_REGION_LOCAL1(m_blockchain); LockedTXN lock(m_blockchain); m_blockchain.remove_txpool_tx(id); @@ -468,7 +472,12 @@ namespace cryptonote return false; } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id); - if (!parse_and_validate_tx_from_blob(txblob, tx)) + auto ci = m_parsed_tx_cache.find(id); + if (ci != m_parsed_tx_cache.end()) + { + tx = ci->second; + } + else if (!parse_and_validate_tx_from_blob(txblob, tx)) { MERROR("Failed to parse tx from txpool"); return false; @@ -911,6 +920,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL(m_transactions_lock); m_input_cache.clear(); + m_parsed_tx_cache.clear(); return true; } //--------------------------------------------------------------------------------- @@ -918,6 +928,7 @@ namespace cryptonote { CRITICAL_REGION_LOCAL(m_transactions_lock); m_input_cache.clear(); + m_parsed_tx_cache.clear(); return true; } //--------------------------------------------------------------------------------- diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 09d134d7b..6270a30bf 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -584,6 +584,8 @@ namespace cryptonote size_t m_txpool_weight; mutable std::unordered_map> m_input_cache; + + std::unordered_map m_parsed_tx_cache; }; } From 741e4a11729db74f52fc4b913833b07dd67eb9b3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 13:21:35 +0000 Subject: [PATCH 0226/1007] epee: speed up json number parsing --- .../storages/portable_storage_from_json.h | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h index 5b2eafa9a..0307b732c 100644 --- a/contrib/epee/include/storages/portable_storage_from_json.h +++ b/contrib/epee/include/storages/portable_storage_from_json.h @@ -125,16 +125,22 @@ namespace epee { if(is_signed) { - int64_t nval = boost::lexical_cast(val); + errno = 0; + int64_t nval = strtoll(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); stg.set_value(name, nval, current_section); }else { - uint64_t nval = boost::lexical_cast(val); + errno = 0; + uint64_t nval = strtoull(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); stg.set_value(name, nval, current_section); } }else { - double nval = boost::lexical_cast(val); + errno = 0; + double nval = strtod(val.c_str(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + val); stg.set_value(name, nval, current_section); } state = match_state_wonder_after_value; @@ -208,12 +214,25 @@ namespace epee match_number2(it, buf_end, val, is_v_float, is_signed_val); if(!is_v_float) { - int64_t nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); - h_array = stg.insert_first_value(name, nval, current_section); + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); + h_array = stg.insert_first_value(name, nval, current_section); + }else + { + errno = 0; + uint64_t nval = strtoull(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); + h_array = stg.insert_first_value(name, nval, current_section); + } CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); }else { - double nval = boost::lexical_cast(val);//bool res = string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.c_str(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + val); h_array = stg.insert_first_value(name, nval, current_section); CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); } @@ -286,13 +305,24 @@ namespace epee bool insert_res = false; if(!is_v_float) { - int64_t nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); - insert_res = stg.insert_next_value(h_array, nval); - + if (is_signed_val) + { + errno = 0; + int64_t nval = strtoll(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); + insert_res = stg.insert_next_value(h_array, nval); + }else + { + errno = 0; + uint64_t nval = strtoull(val.c_str(), NULL, 10); + if (errno) throw std::runtime_error("Invalid number: " + val); + insert_res = stg.insert_next_value(h_array, nval); + } }else { - //TODO: optimize here if need - double nval = boost::lexical_cast(val); //string_tools::string_to_num_fast(val, nval); + errno = 0; + double nval = strtod(val.c_str(), NULL); + if (errno) throw std::runtime_error("Invalid number: " + val); insert_res = stg.insert_next_value(h_array, nval); } CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); From 14a5c2068f53cfe1af3056375fed2587bc07d320 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 14:51:08 +0000 Subject: [PATCH 0227/1007] p2p: tone down "no incoming connections" warning to info if in peers is 0 Also add an info if not offline, since it weakens the network --- src/p2p/net_node.inl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index a61b6107f..fbf265fc9 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1334,12 +1334,19 @@ namespace nodetool template bool node_server::check_incoming_connections() { - if (m_offline || m_hide_my_port) + if (m_offline) return true; if (get_incoming_connections_count() == 0) { - const el::Level level = el::Level::Warning; - MCLOG_RED(level, "global", "No incoming connections - check firewalls/routers allow port " << get_this_peer_port()); + if (m_hide_my_port || m_config.m_net_config.max_in_connection_count == 0) + { + MGINFO("Incoming connections disabled, enable them for full connectivity"); + } + else + { + const el::Level level = el::Level::Warning; + MCLOG_RED(level, "global", "No incoming connections - check firewalls/routers allow port " << get_this_peer_port()); + } } return true; } From 99fbe1008b3e576917a939a5b7fbc7fb26423f18 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 15:15:23 +0000 Subject: [PATCH 0228/1007] db_lmdb: save some string copies for readonly db keys/values --- src/blockchain_db/lmdb/db_lmdb.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index b1248c492..d642069f8 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -85,6 +85,10 @@ inline void throw1(const T &e) #define MDB_val_set(var, val) MDB_val var = {sizeof(val), (void *)&val} +#define MDB_val_sized(var, val) MDB_val var = {val.size(), (void *)val.data()} + +#define MDB_val_str(var, val) MDB_val var = {strlen(val) + 1, (void *)val} + template struct MDB_val_copy: public MDB_val { @@ -714,7 +718,8 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, const diff CURSOR(block_info) // this call to mdb_cursor_put will change height() - MDB_val_copy blob(block_to_blob(blk)); + cryptonote::blobdata block_blob(block_to_blob(blk)); + MDB_val_sized(blob, block_blob); result = mdb_cursor_put(m_cur_blocks, &key, &blob, MDB_APPEND); if (result) throw0(DB_ERROR(lmdb_error("Failed to add block blob to db transaction: ", result).c_str())); @@ -828,7 +833,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons throw0(DB_ERROR(lmdb_error("Failed to add tx data to db transaction: ", result).c_str())); cryptonote::blobdata blob = tx_to_blob(tx); - MDB_val_copy blobval(blob); + MDB_val_sized(blobval, blob); std::stringstream ss; binary_archive ba(ss); @@ -836,7 +841,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons if (!r) throw0(DB_ERROR("Failed to serialize pruned tx")); std::string pruned = ss.str(); - MDB_val_copy pruned_blob(pruned); + MDB_val_sized(pruned_blob, pruned); result = mdb_cursor_put(m_cur_txs_pruned, &val_tx_id, &pruned_blob, MDB_APPEND); if (result) throw0(DB_ERROR(lmdb_error("Failed to add pruned tx blob to db transaction: ", result).c_str())); @@ -844,7 +849,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons if (pruned.size() > blob.size()) throw0(DB_ERROR("pruned tx size is larger than tx size")); cryptonote::blobdata prunable(blob.data() + pruned.size(), blob.size() - pruned.size()); - MDB_val_copy prunable_blob(prunable); + MDB_val_sized(prunable_blob, prunable); result = mdb_cursor_put(m_cur_txs_prunable, &val_tx_id, &prunable_blob, MDB_APPEND); if (result) throw0(DB_ERROR(lmdb_error("Failed to add prunable tx blob to db transaction: ", result).c_str())); @@ -1331,7 +1336,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) bool compatible = true; - MDB_val_copy k("version"); + MDB_val_str(k, "version"); MDB_val v; auto get_result = mdb_get(txn, m_properties, &k, &v); if(get_result == MDB_SUCCESS) @@ -1379,7 +1384,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) // only write version on an empty DB if (m_height == 0) { - MDB_val_copy k("version"); + MDB_val_str(k, "version"); MDB_val_copy v(VERSION); auto put_result = mdb_put(txn, m_properties, &k, &v, 0); if (put_result != MDB_SUCCESS) @@ -1476,7 +1481,7 @@ void BlockchainLMDB::reset() throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str())); // init with current version - MDB_val_copy k("version"); + MDB_val_str(k, "version"); MDB_val_copy v(VERSION); if (auto result = mdb_put(txn, m_properties, &k, &v, 0)) throw0(DB_ERROR(lmdb_error("Failed to write version to database: ", result).c_str())); @@ -1608,7 +1613,7 @@ void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::b else throw1(DB_ERROR(lmdb_error("Error adding txpool tx metadata to db transaction: ", result).c_str())); } - MDB_val_copy blob_val(blob); + MDB_val_sized(blob_val, blob); if (auto result = mdb_cursor_put(m_cur_txpool_blob, &k, &blob_val, MDB_NODUPDATA)) { if (result == MDB_KEYEXIST) throw1(DB_ERROR("Attempting to add txpool tx blob that's already in the db")); @@ -4047,7 +4052,7 @@ void BlockchainLMDB::migrate_0_1() uint32_t version = 1; v.mv_data = (void *)&version; v.mv_size = sizeof(version); - MDB_val_copy vk("version"); + MDB_val_str(vk, "version"); result = mdb_txn_begin(m_env, NULL, 0, txn); if (result) throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); @@ -4189,7 +4194,7 @@ void BlockchainLMDB::migrate_1_2() uint32_t version = 2; v.mv_data = (void *)&version; v.mv_size = sizeof(version); - MDB_val_copy vk("version"); + MDB_val_str(vk, "version"); result = mdb_txn_begin(m_env, NULL, 0, txn); if (result) throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); @@ -4324,7 +4329,7 @@ void BlockchainLMDB::migrate_2_3() uint32_t version = 3; v.mv_data = (void *)&version; v.mv_size = sizeof(version); - MDB_val_copy vk("version"); + MDB_val_str(vk, "version"); result = mdb_txn_begin(m_env, NULL, 0, txn); if (result) throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); From 03fc731bf23ec828af1999fc8f4a651605ea6a57 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 22:00:01 +0000 Subject: [PATCH 0229/1007] p2p: less frequent incoming connections check --- src/p2p/net_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 90e2f78b1..cc6e47e4f 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -308,7 +308,7 @@ namespace nodetool epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval; epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval; epee::math_helper::once_a_time_seconds<60> m_gray_peerlist_housekeeping_interval; - epee::math_helper::once_a_time_seconds<900, false> m_incoming_connections_interval; + epee::math_helper::once_a_time_seconds<3600, false> m_incoming_connections_interval; std::string m_bind_ip; std::string m_port; From c17a1d431b3e1c39f7ec79f961ee1f0449793bb3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 22:14:40 +0000 Subject: [PATCH 0230/1007] daemon: use msg_writer, not cout, to display information --- src/daemon/rpc_command_executor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 9a0603a10..f17465391 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -567,8 +567,8 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u for (auto & header : res.headers) { if (!first) - std::cout << std::endl; - std::cout + tools::msg_writer() << "" << std::endl; + tools::msg_writer() << "height: " << header.height << ", timestamp: " << header.timestamp << ", size: " << header.block_size << ", weight: " << header.block_weight << ", transactions: " << header.num_txes << std::endl << "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl @@ -1313,7 +1313,7 @@ bool t_rpc_command_executor::out_peers(uint64_t limit) } } - std::cout << "Max number of out peers set to " << limit << std::endl; + tools::msg_writer() << "Max number of out peers set to " << limit << std::endl; return true; } @@ -1345,7 +1345,7 @@ bool t_rpc_command_executor::in_peers(uint64_t limit) } } - std::cout << "Max number of in peers set to " << limit << std::endl; + tools::msg_writer() << "Max number of in peers set to " << limit << std::endl; return true; } From 71eb32a976512b294e077861a3123842e20611b6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 22:17:34 +0000 Subject: [PATCH 0231/1007] dns_utils: do not exit if DNS records are corrupt --- src/common/dns_utils.cpp | 41 +++++++++++++++++++++++++++++++++------- src/common/dns_utils.h | 3 ++- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index f2b270981..606a2c7b7 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -37,6 +37,7 @@ #include #include #include +#include using namespace epee; namespace bf = boost::filesystem; @@ -119,10 +120,25 @@ get_builtin_ds(void) namespace tools { +static const char *get_record_name(int record_type) +{ + switch (record_type) + { + case DNS_TYPE_A: return "A"; + case DNS_TYPE_TXT: return "TXT"; + case DNS_TYPE_AAAA: return "AAAA"; + default: return "unknown"; + } +} + // fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc -std::string ipv4_to_string(const char* src, size_t len) +boost::optional ipv4_to_string(const char* src, size_t len) { - assert(len >= 4); + if (len < 4) + { + MERROR("Invalid IPv4 address: " << std::string(src, len)); + return boost::none; + } std::stringstream ss; unsigned int bytes[4]; @@ -140,9 +156,13 @@ std::string ipv4_to_string(const char* src, size_t len) // this obviously will need to change, but is here to reflect the above // stop-gap measure and to make the tests pass at least... -std::string ipv6_to_string(const char* src, size_t len) +boost::optional ipv6_to_string(const char* src, size_t len) { - assert(len >= 8); + if (len < 8) + { + MERROR("Invalid IPv4 address: " << std::string(src, len)); + return boost::none; + } std::stringstream ss; unsigned int bytes[8]; @@ -162,8 +182,10 @@ std::string ipv6_to_string(const char* src, size_t len) return ss.str(); } -std::string txt_to_string(const char* src, size_t len) +boost::optional txt_to_string(const char* src, size_t len) { + if (len == 0) + return boost::none; return std::string(src+1, len-1); } @@ -266,7 +288,7 @@ DNSResolver::~DNSResolver() } } -std::vector DNSResolver::get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid) +std::vector DNSResolver::get_record(const std::string& url, int record_type, boost::optional (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid) { std::vector addresses; dnssec_available = false; @@ -289,7 +311,12 @@ std::vector DNSResolver::get_record(const std::string& url, int rec { for (size_t i=0; result->data[i] != NULL; i++) { - addresses.push_back((*reader)(result->data[i], result->len[i])); + boost::optional res = (*reader)(result->data[i], result->len[i]); + if (res) + { + MINFO("Found \"" << *res << "\" in " << get_record_name(record_type) << " record for " << url); + addresses.push_back(*res); + } } } } diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index f46bca3dd..3a6ef68a1 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace tools { @@ -143,7 +144,7 @@ class DNSResolver * @return A vector of strings containing the requested record; or an empty vector */ // TODO: modify this to accommodate DNSSEC - std::vector get_record(const std::string& url, int record_type, std::string (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid); + std::vector get_record(const std::string& url, int record_type, boost::optional (*reader)(const char *,size_t), bool& dnssec_available, bool& dnssec_valid); /** * @brief Checks a string to see if it looks like a URL From 233f00c60171174164fb5170c1a9458748846f54 Mon Sep 17 00:00:00 2001 From: xiphon Date: Fri, 26 Oct 2018 23:07:23 +0000 Subject: [PATCH 0232/1007] cryptonote_core: fix build error gcc 5.4.0 'sign-compare' --- src/cryptonote_core/cryptonote_core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index d8c38bf9e..4b806c282 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1716,7 +1716,7 @@ namespace cryptonote for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n) { unsigned int b = 0; - for (time_t ts: timestamps) b += ts >= now - seconds[n]; + for (time_t ts: timestamps) b += ts >= now - static_cast(seconds[n]); const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V2); MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")"); if (p < threshold) From 97cad7e9796621d6b676a81fef1499037ef16e15 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 31 May 2018 19:25:52 +0100 Subject: [PATCH 0233/1007] db_lmdb: log which output was not found in get_output_key --- src/blockchain_db/lmdb/db_lmdb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 84a083c26..1674c40dd 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -2499,7 +2499,8 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint6 MDB_val_set(v, index); auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) - throw1(OUTPUT_DNE("Attempting to get output pubkey by index, but key does not exist")); + throw1(OUTPUT_DNE(std::string("Attempting to get output pubkey by index, but key does not exist: amount " + + std::to_string(amount) + ", index " + std::to_string(index)).c_str())); else if (get_result) throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db")); From 1c04c21d6e173dc85a30e33f0aa8fea9f15be3b7 Mon Sep 17 00:00:00 2001 From: stoffu Date: Fri, 2 Nov 2018 21:12:11 +0900 Subject: [PATCH 0234/1007] wallet_rpc_server: include additional tx keys in sign_transfer response Followup on #4552 --- src/wallet/wallet_rpc_server.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5e6100dfd..ac0712d7f 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -982,7 +982,11 @@ namespace tools { res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx))); if (req.get_tx_keys) + { res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key)); + for (const crypto::secret_key& additional_tx_key : ptx.additional_tx_keys) + res.tx_key_list.back() += epee::string_tools::pod_to_hex(additional_tx_key); + } } if (req.export_raw) From 0cfd2ae5e774ff845abb669d6bfd63e5c838039f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 2 Nov 2018 12:59:06 +0000 Subject: [PATCH 0235/1007] mlocker: fix dtor ordering problem leak the mutex instead, it's a one off --- contrib/epee/src/mlocker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index 5573d591a..c3262e8f4 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -84,8 +84,8 @@ namespace epee boost::mutex &mlocker::mutex() { - static boost::mutex vmutex; - return vmutex; + static boost::mutex *vmutex = new boost::mutex(); + return *vmutex; } std::map &mlocker::map() { From c22e85fe1ac8f7ee7ab09656ea9b5db63bdc8048 Mon Sep 17 00:00:00 2001 From: stoffu Date: Fri, 2 Nov 2018 23:22:46 +0900 Subject: [PATCH 0236/1007] simplewallet: remove redundant messages on daemon connection failure try_connect_to_daemon with silent=false already prints failure message --- src/simplewallet/simplewallet.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f171d35b6..a810e5dda 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -780,10 +780,7 @@ bool simple_wallet::payment_id(const std::vector &args/* = std::vec bool simple_wallet::print_fee_info(const std::vector &args/* = std::vector()*/) { if (!try_connect_to_daemon()) - { - fail_msg_writer() << tr("Cannot connect to daemon"); return true; - } const bool per_byte = m_wallet->use_fork_rules(HF_VERSION_PER_BYTE_FEE); const uint64_t base_fee = m_wallet->get_base_fee(); const char *base = per_byte ? "byte" : "kB"; @@ -4608,10 +4605,7 @@ bool simple_wallet::print_ring_members(const std::vector &args) } if (!try_connect_to_daemon()) - { - fail_msg_writer() << tr("failed to connect to the daemon"); return true; - } SCOPED_WALLET_UNLOCK(); @@ -6489,10 +6480,7 @@ bool simple_wallet::check_spend_proof(const std::vector &args) } if (!try_connect_to_daemon()) - { - fail_msg_writer() << tr("failed to connect to the daemon"); return true; - } std::string sig_str; if (!epee::file_io_utils::load_file_to_string(args[1], sig_str)) @@ -6546,10 +6534,7 @@ bool simple_wallet::get_reserve_proof(const std::vector &args) } if (!try_connect_to_daemon()) - { - fail_msg_writer() << tr("failed to connect to the daemon"); return true; - } SCOPED_WALLET_UNLOCK(); @@ -6577,10 +6562,7 @@ bool simple_wallet::check_reserve_proof(const std::vector &args) } if (!try_connect_to_daemon()) - { - fail_msg_writer() << tr("failed to connect to the daemon"); return true; - } cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), args[0], oa_prompter)) From 29ffb6bba8867586986345b4f0c560e5ea5fce85 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Thu, 23 Aug 2018 23:50:53 +0200 Subject: [PATCH 0237/1007] device/trezor: trezor support added --- .gitmodules | 3 + CMakeLists.txt | 11 + external/trezor-common | 1 + src/CMakeLists.txt | 1 + src/cryptonote_basic/account.cpp | 24 +- src/cryptonote_basic/account.h | 1 + src/device/CMakeLists.txt | 2 + src/device/device.hpp | 16 +- src/device/device_cold.hpp | 71 ++ src/device/device_default.cpp | 8 +- src/device/device_ledger.hpp | 1 + src/device_trezor/CMakeLists.txt | 123 +++ src/device_trezor/device_trezor.cpp | 363 +++++++ src/device_trezor/device_trezor.hpp | 132 +++ src/device_trezor/device_trezor_base.cpp | 301 ++++++ src/device_trezor/device_trezor_base.hpp | 301 ++++++ src/device_trezor/trezor.hpp | 44 + src/device_trezor/trezor/exceptions.hpp | 193 ++++ src/device_trezor/trezor/messages/.gitignore | 2 + src/device_trezor/trezor/messages_map.cpp | 125 +++ src/device_trezor/trezor/messages_map.hpp | 94 ++ src/device_trezor/trezor/protocol.cpp | 891 ++++++++++++++++++ src/device_trezor/trezor/protocol.hpp | 300 ++++++ src/device_trezor/trezor/tools/README.md | 36 + .../trezor/tools/build_protob.py | 38 + src/device_trezor/trezor/tools/pb2cpp.py | 186 ++++ src/device_trezor/trezor/transport.cpp | 651 +++++++++++++ src/device_trezor/trezor/transport.hpp | 331 +++++++ src/device_trezor/trezor/trezor_defs.hpp | 48 + src/ringct/rctSigs.h | 2 +- src/simplewallet/simplewallet.cpp | 146 ++- src/simplewallet/simplewallet.h | 3 + src/wallet/CMakeLists.txt | 1 + src/wallet/wallet2.cpp | 158 +++- src/wallet/wallet2.h | 22 +- 35 files changed, 4591 insertions(+), 39 deletions(-) create mode 160000 external/trezor-common create mode 100644 src/device/device_cold.hpp create mode 100644 src/device_trezor/CMakeLists.txt create mode 100644 src/device_trezor/device_trezor.cpp create mode 100644 src/device_trezor/device_trezor.hpp create mode 100644 src/device_trezor/device_trezor_base.cpp create mode 100644 src/device_trezor/device_trezor_base.hpp create mode 100644 src/device_trezor/trezor.hpp create mode 100644 src/device_trezor/trezor/exceptions.hpp create mode 100644 src/device_trezor/trezor/messages/.gitignore create mode 100644 src/device_trezor/trezor/messages_map.cpp create mode 100644 src/device_trezor/trezor/messages_map.hpp create mode 100644 src/device_trezor/trezor/protocol.cpp create mode 100644 src/device_trezor/trezor/protocol.hpp create mode 100644 src/device_trezor/trezor/tools/README.md create mode 100644 src/device_trezor/trezor/tools/build_protob.py create mode 100644 src/device_trezor/trezor/tools/pb2cpp.py create mode 100644 src/device_trezor/trezor/transport.cpp create mode 100644 src/device_trezor/trezor/transport.hpp create mode 100644 src/device_trezor/trezor/trezor_defs.hpp diff --git a/.gitmodules b/.gitmodules index 91bddb0a3..6e2339fb9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,3 +9,6 @@ [submodule "external/rapidjson"] path = external/rapidjson url = https://github.com/Tencent/rapidjson +[submodule "external/trezor-common"] + path = external/trezor-common + url = https://github.com/trezor/trezor-common.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a685ee8e..a3dbf974a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,6 +190,7 @@ if(NOT MANUAL_SUBMODULES) check_submodule(external/miniupnp) check_submodule(external/unbound) check_submodule(external/rapidjson) + check_submodule(external/trezor-common) endif() endif() @@ -512,6 +513,16 @@ else (HIDAPI_FOUND) message(STATUS "Could not find HIDAPI") endif() +# Protobuf, optional. Required for TREZOR. +include(FindProtobuf) +find_package(Protobuf) +if(Protobuf_FOUND) + set(HAVE_PROTOBUF 1) + add_definitions(-DHAVE_PROTOBUF=1) +else(Protobuf_FOUND) + message(STATUS "Could not find Protobuf") +endif() + if(MSVC) add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline") diff --git a/external/trezor-common b/external/trezor-common new file mode 160000 index 000000000..588f8e03f --- /dev/null +++ b/external/trezor-common @@ -0,0 +1 @@ +Subproject commit 588f8e03f5ac111adf719f0a437de67481a26aed diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b71c38cd..6ee7effdd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -145,3 +145,4 @@ if(PER_BLOCK_CHECKPOINT) endif() add_subdirectory(device) +add_subdirectory(device_trezor) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 1dc1ad71d..edbc2c561 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -139,6 +139,15 @@ DISABLE_VS_WARNINGS(4244 4345) m_creation_timestamp = 0; } //----------------------------------------------------------------- + void account_base::deinit() + { + try{ + m_keys.get_device().disconnect(); + } catch (const std::exception &e){ + MERROR("Device disconnect exception: " << e.what()); + } + } + //----------------------------------------------------------------- void account_base::forget_spend_key() { m_keys.m_spend_secret_key = crypto::secret_key(); @@ -206,11 +215,16 @@ DISABLE_VS_WARNINGS(4244 4345) void account_base::create_from_device(hw::device &hwdev) { m_keys.set_device(hwdev); - MCDEBUG("ledger", "device type: "< + + +namespace hw { + + typedef struct wallet_shim { + boost::function get_tx_pub_key_from_received_outs; + } wallet_shim; + + class tx_aux_data { + public: + std::vector tx_device_aux; // device generated aux data + std::vector tx_recipients; // as entered by user + }; + + class device_cold { + public: + + using exported_key_image = std::vector>; + + /** + * Key image sync with the cold protocol. + */ + virtual void ki_sync(wallet_shim * wallet, + const std::vector<::tools::wallet2::transfer_details> & transfers, + exported_key_image & ski) =0; + + /** + * Signs unsigned transaction with the cold protocol. + */ + virtual void tx_sign(wallet_shim * wallet, + const ::tools::wallet2::unsigned_tx_set & unsigned_tx, + ::tools::wallet2::signed_tx_set & signed_tx, + tx_aux_data & aux_data) =0; + }; +} + +#endif //MONERO_DEVICE_COLD_H diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index 68f40d91e..1e3d80949 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -69,17 +69,17 @@ namespace hw { } bool device_default::init(void) { - dfns(); + return true; } bool device_default::release() { - dfns(); + return true; } bool device_default::connect(void) { - dfns(); + return true; } bool device_default::disconnect() { - dfns(); + return true; } bool device_default::set_mode(device_mode mode) { diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index dde69fbfd..2f5beb044 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -141,6 +141,7 @@ namespace hw { bool set_mode(device_mode mode) override; device_type get_type() const override {return device_type::LEDGER;}; + device_protocol_t device_protocol() const override { return PROTOCOL_PROXY; }; /* ======================================================================= */ /* LOCKER */ diff --git a/src/device_trezor/CMakeLists.txt b/src/device_trezor/CMakeLists.txt new file mode 100644 index 000000000..c555e9fcd --- /dev/null +++ b/src/device_trezor/CMakeLists.txt @@ -0,0 +1,123 @@ +# Copyright (c) 2014-2017, The Monero Project +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +set(TREZOR_PROTOB_H + trezor/messages/messages.pb.h + trezor/messages/messages-common.pb.h + trezor/messages/messages-management.pb.h + trezor/messages/messages-monero.pb.h +) + +set(TREZOR_PROTOB_CPP + trezor/messages/messages.pb.cc + trezor/messages/messages-common.pb.cc + trezor/messages/messages-management.pb.cc + trezor/messages/messages-monero.pb.cc +) + +set(trezor_headers + trezor/exceptions.hpp + trezor/messages_map.hpp + trezor/protocol.hpp + trezor/transport.hpp + device_trezor_base.hpp + device_trezor.hpp + trezor.hpp + ${TREZOR_PROTOB_H} +) + +set(trezor_sources + trezor/messages_map.cpp + trezor/protocol.cpp + trezor/transport.cpp + device_trezor_base.cpp + device_trezor.cpp + ${TREZOR_PROTOB_CPP} +) + +set(trezor_private_headers) + + +include(FindProtobuf) +find_package(Protobuf) # REQUIRED + +# Test for HAVE_PROTOBUF from the parent +if(Protobuf_FOUND AND HAVE_PROTOBUF) + if ("$ENV{PYTHON3}" STREQUAL "") + set(PYTHON3 "python3") + else() + set(PYTHON3 "$ENV{PYTHON3}" CACHE INTERNAL "Copied from environment variable") + endif() + + execute_process(COMMAND ${PYTHON3} tools/build_protob.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR) + if(RET) + message(WARNING "Trezor protobuf messages could not be regenerated (err=${RET}, python ${PYTHON})." + "OUT: ${OUT}, ERR: ${ERR}." + "Please read src/device_trezor/trezor/tools/README.md") + else() + message(STATUS "Trezor protobuf messages regenerated ${OUT}") + set(TREZOR_PROTOBUF_GENERATED 1) + endif() +endif() + + +if(TREZOR_PROTOBUF_GENERATED) + message(STATUS "Trezor support enabled") + + add_definitions(-DPROTOBUF_INLINE_NOT_IN_HEADERS=0) + + monero_private_headers(device_trezor + ${device_private_headers} + ${PROTOBUF_INCLUDE_DIR}) + + monero_add_library(device_trezor + ${trezor_sources} + ${trezor_headers} + ${trezor_private_headers}) + + target_link_libraries(device_trezor + PUBLIC + device + cncrypto + ringct_basic + cryptonote_core + common + ${SODIUM_LIBRARY} + ${Boost_CHRONO_LIBRARY} + ${PROTOBUF_LIBRARY} + PRIVATE + ${EXTRA_LIBRARIES}) + + # set(WITH_DEVICE_TREZOR 1 PARENT_SCOPE) + # add_definitions(-DWITH_DEVICE_TREZOR=1) + +else() + monero_private_headers(device_trezor) + monero_add_library(device_trezor device_trezor.cpp) + target_link_libraries(device_trezor PUBLIC cncrypto) +endif() diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp new file mode 100644 index 000000000..07c03fc66 --- /dev/null +++ b/src/device_trezor/device_trezor.cpp @@ -0,0 +1,363 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#include "device_trezor.hpp" + +namespace hw { +namespace trezor { + +#if WITH_DEVICE_TREZOR + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" + +#define HW_TREZOR_NAME "Trezor" +#define HW_TREZOR_NAME_LITE "TrezorLite" + + static device_trezor *trezor_device = nullptr; + static device_trezor *ensure_trezor_device(){ + if (!trezor_device) { + trezor_device = new device_trezor(); + trezor_device->set_name(HW_TREZOR_NAME); + } + return trezor_device; + } + + void register_all(std::map> ®istry) { + registry.insert(std::make_pair(HW_TREZOR_NAME, std::unique_ptr(ensure_trezor_device()))); + } + + void register_all() { + hw::register_device(HW_TREZOR_NAME, ensure_trezor_device()); + } + + device_trezor::device_trezor() { + + } + + device_trezor::~device_trezor() { + try { + disconnect(); + release(); + } catch(std::exception const& e){ + MWARNING("Could not disconnect and release: " << e.what()); + } + } + + /* ======================================================================= */ + /* WALLET & ADDRESS */ + /* ======================================================================= */ + + bool device_trezor::get_public_address(cryptonote::account_public_address &pubkey) { + try { + auto res = get_address(); + + cryptonote::address_parse_info info{}; + bool r = cryptonote::get_account_address_from_str(info, this->network_type, res->address()); + CHECK_AND_ASSERT_MES(r, false, "Could not parse returned address. Address parse failed: " + res->address()); + CHECK_AND_ASSERT_MES(!info.is_subaddress, false, "Trezor returned a sub address"); + + pubkey = info.address; + return true; + + } catch(std::exception const& e){ + MERROR("Get public address exception: " << e.what()); + return false; + } + } + + bool device_trezor::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { + try { + MDEBUG("Loading view-only key from the Trezor. Please check the Trezor for a confirmation."); + auto res = get_view_key(); + CHECK_AND_ASSERT_MES(res->watch_key().size() == 32, false, "Trezor returned invalid view key"); + + spendkey = crypto::null_skey; // not given + memcpy(viewkey.data, res->watch_key().data(), 32); + + return true; + + } catch(std::exception const& e){ + MERROR("Get secret keys exception: " << e.what()); + return false; + } + } + + /* ======================================================================= */ + /* Helpers */ + /* ======================================================================= */ + + /* ======================================================================= */ + /* TREZOR PROTOCOL */ + /* ======================================================================= */ + + std::shared_ptr device_trezor::get_address( + const boost::optional> & path, + const boost::optional & network_type){ + AUTO_LOCK_CMD(); + require_connected(); + test_ping(); + + auto req = std::make_shared(); + this->set_msg_addr(req.get(), path, network_type); + + auto response = this->client_exchange(req); + MTRACE("Get address response received"); + return response; + } + + std::shared_ptr device_trezor::get_view_key( + const boost::optional> & path, + const boost::optional & network_type){ + AUTO_LOCK_CMD(); + require_connected(); + test_ping(); + + auto req = std::make_shared(); + this->set_msg_addr(req.get(), path, network_type); + + auto response = this->client_exchange(req); + MTRACE("Get watch key response received"); + return response; + } + + void device_trezor::ki_sync(wallet_shim * wallet, + const std::vector & transfers, + hw::device_cold::exported_key_image & ski) + { + AUTO_LOCK_CMD(); + require_connected(); + test_ping(); + + std::shared_ptr req; + + std::vector mtds; + std::vector kis; + protocol::ki::key_image_data(wallet, transfers, mtds); + protocol::ki::generate_commitment(mtds, transfers, req); + + this->set_msg_addr(req.get()); + auto ack1 = this->client_exchange(req); + + const auto batch_size = 10; + const auto num_batches = (mtds.size() + batch_size - 1) / batch_size; + for(uint64_t cur = 0; cur < num_batches; ++cur){ + auto step_req = std::make_shared(); + auto idx_finish = std::min(static_cast((cur + 1) * batch_size), static_cast(mtds.size())); + for(uint64_t idx = cur * batch_size; idx < idx_finish; ++idx){ + auto added_tdis = step_req->add_tdis(); + CHECK_AND_ASSERT_THROW_MES(idx < mtds.size(), "Invalid transfer detail index"); + *added_tdis = mtds[idx]; + } + + auto step_ack = this->client_exchange(step_req); + auto kis_size = step_ack->kis_size(); + kis.reserve(static_cast(kis_size)); + for(int i = 0; i < kis_size; ++i){ + auto ckis = step_ack->kis(i); + kis.push_back(ckis); + } + + MTRACE("Batch " << cur << " / " << num_batches << " batches processed"); + } + + auto final_req = std::make_shared(); + auto final_ack = this->client_exchange(final_req); + ski.reserve(kis.size()); + + for(auto & sub : kis){ + char buff[32*3]; + protocol::crypto::chacha::decrypt(sub.blob().data(), sub.blob().size(), + reinterpret_cast(final_ack->enc_key().data()), + reinterpret_cast(sub.iv().data()), buff); + + ::crypto::signature sig{}; + ::crypto::key_image ki; + memcpy(ki.data, buff, 32); + memcpy(sig.c.data, buff + 32, 32); + memcpy(sig.r.data, buff + 64, 32); + ski.push_back(std::make_pair(ki, sig)); + } + } + + + void device_trezor::tx_sign(wallet_shim * wallet, + const tools::wallet2::unsigned_tx_set & unsigned_tx, + tools::wallet2::signed_tx_set & signed_tx, + hw::tx_aux_data & aux_data) + { + size_t num_tx = unsigned_tx.txes.size(); + signed_tx.key_images.clear(); + signed_tx.key_images.resize(unsigned_tx.transfers.size()); + + for(size_t tx_idx = 0; tx_idx < num_tx; ++tx_idx) { + std::shared_ptr signer; + tx_sign(wallet, unsigned_tx, tx_idx, aux_data, signer); + + auto & cdata = signer->tdata(); + auto aux_info_cur = signer->store_tx_aux_info(); + aux_data.tx_device_aux.emplace_back(aux_info_cur); + + // Pending tx reconstruction + signed_tx.ptx.emplace_back(); + auto & cpend = signed_tx.ptx.back(); + cpend.tx = cdata.tx; + cpend.dust = 0; + cpend.fee = 0; + cpend.dust_added_to_fee = false; + cpend.change_dts = cdata.tx_data.change_dts; + cpend.selected_transfers = cdata.tx_data.selected_transfers; + cpend.key_images = ""; + cpend.dests = cdata.tx_data.dests; + cpend.construction_data = cdata.tx_data; + + // Transaction check + cryptonote::blobdata tx_blob; + cryptonote::transaction tx_deserialized; + bool r = cryptonote::t_serializable_object_to_blob(cpend.tx, tx_blob); + CHECK_AND_ASSERT_THROW_MES(r, "Transaction serialization failed"); + r = cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx_deserialized); + CHECK_AND_ASSERT_THROW_MES(r, "Transaction deserialization failed"); + + std::string key_images; + bool all_are_txin_to_key = std::all_of(cdata.tx.vin.begin(), cdata.tx.vin.end(), [&](const cryptonote::txin_v& s_e) -> bool + { + CHECKED_GET_SPECIFIC_VARIANT(s_e, const cryptonote::txin_to_key, in, false); + key_images += boost::to_string(in.k_image) + " "; + return true; + }); + if(!all_are_txin_to_key) { + throw std::invalid_argument("Not all are txin_to_key"); + } + cpend.key_images = key_images; + + // KI sync + size_t num_sources = cdata.tx_data.sources.size(); + CHECK_AND_ASSERT_THROW_MES(num_sources == cdata.source_permutation.size(), "Invalid permutation size"); + CHECK_AND_ASSERT_THROW_MES(num_sources == cdata.tx.vin.size(), "Invalid tx.vin size"); + for(size_t src_idx = 0; src_idx < num_sources; ++src_idx){ + size_t idx_mapped = cdata.source_permutation[src_idx]; + CHECK_AND_ASSERT_THROW_MES(idx_mapped < cdata.tx_data.selected_transfers.size(), "Invalid idx_mapped"); + CHECK_AND_ASSERT_THROW_MES(src_idx < cdata.tx.vin.size(), "Invalid idx_mapped"); + + size_t idx_map_src = cdata.tx_data.selected_transfers[idx_mapped]; + auto vini = boost::get(cdata.tx.vin[src_idx]); + + CHECK_AND_ASSERT_THROW_MES(idx_map_src < signed_tx.key_images.size(), "Invalid key image index"); + signed_tx.key_images[idx_map_src] = vini.k_image; + } + } + } + + void device_trezor::tx_sign(wallet_shim * wallet, + const tools::wallet2::unsigned_tx_set & unsigned_tx, + size_t idx, + hw::tx_aux_data & aux_data, + std::shared_ptr & signer) + { + AUTO_LOCK_CMD(); + require_connected(); + test_ping(); + + CHECK_AND_ASSERT_THROW_MES(idx < unsigned_tx.txes.size(), "Invalid transaction index"); + signer = std::make_shared(wallet, &unsigned_tx, idx, &aux_data); + const tools::wallet2::tx_construction_data & cur_tx = unsigned_tx.txes[idx]; + unsigned long num_sources = cur_tx.sources.size(); + unsigned long num_outputs = cur_tx.splitted_dsts.size(); + + // Step: Init + auto init_msg = signer->step_init(); + this->set_msg_addr(init_msg.get()); + + auto response = this->client_exchange(init_msg); + signer->step_init_ack(response); + + // Step: Set transaction inputs + for(size_t cur_src = 0; cur_src < num_sources; ++cur_src){ + auto src = signer->step_set_input(cur_src); + auto ack = this->client_exchange(src); + signer->step_set_input_ack(ack); + } + + // Step: sort + auto perm_req = signer->step_permutation(); + if (perm_req){ + auto perm_ack = this->client_exchange(perm_req); + signer->step_permutation_ack(perm_ack); + } + + // Step: input_vini + if (!signer->in_memory()){ + for(size_t cur_src = 0; cur_src < num_sources; ++cur_src){ + auto src = signer->step_set_vini_input(cur_src); + auto ack = this->client_exchange(src); + signer->step_set_vini_input_ack(ack); + } + } + + // Step: all inputs set + auto all_inputs_set = signer->step_all_inputs_set(); + auto ack_all_inputs = this->client_exchange(all_inputs_set); + signer->step_all_inputs_set_ack(ack_all_inputs); + + // Step: outputs + for(size_t cur_dst = 0; cur_dst < num_outputs; ++cur_dst){ + auto src = signer->step_set_output(cur_dst); + auto ack = this->client_exchange(src); + signer->step_set_output_ack(ack); + } + + // Step: all outs set + auto all_out_set = signer->step_all_outs_set(); + auto ack_all_out_set = this->client_exchange(all_out_set); + signer->step_all_outs_set_ack(ack_all_out_set, *this); + + // Step: sign each input + for(size_t cur_src = 0; cur_src < num_sources; ++cur_src){ + auto src = signer->step_sign_input(cur_src); + auto ack_sign = this->client_exchange(src); + signer->step_sign_input_ack(ack_sign); + } + + // Step: final + auto final_msg = signer->step_final(); + auto ack_final = this->client_exchange(final_msg); + signer->step_final_ack(ack_final); + } + +#else //WITH_DEVICE_TREZOR + + void register_all(std::map> ®istry) { + } + + void register_all() { + } + +#endif //WITH_DEVICE_TREZOR +}} \ No newline at end of file diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp new file mode 100644 index 000000000..765c9b82c --- /dev/null +++ b/src/device_trezor/device_trezor.hpp @@ -0,0 +1,132 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_DEVICE_TREZOR_H +#define MONERO_DEVICE_TREZOR_H + + +#include +#include +#include "device/device.hpp" +#include "device/device_default.hpp" +#include "device/device_cold.hpp" +#include +#include +#include +#include "cryptonote_config.h" +#include "trezor.hpp" +#include "device_trezor_base.hpp" + +namespace hw { +namespace trezor { + + void register_all(); + void register_all(std::map> ®istry); + +#if WITH_DEVICE_TREZOR + class device_trezor; + + /** + * Main device + */ + class device_trezor : public hw::trezor::device_trezor_base, public hw::device_cold { + protected: + // To speed up blockchain parsing the view key maybe handle here. + crypto::secret_key viewkey; + bool has_view_key; + + public: + device_trezor(); + virtual ~device_trezor() override; + + device_trezor(const device_trezor &device) = delete ; + device_trezor& operator=(const device_trezor &device) = delete; + + explicit operator bool() const override {return true;} + + device_protocol_t device_protocol() const override { return PROTOCOL_COLD; }; + + bool has_ki_cold_sync() const override { return true; } + bool has_tx_cold_sign() const override { return true; } + void set_network_type(cryptonote::network_type network_type) override { this->network_type = network_type; } + + /* ======================================================================= */ + /* WALLET & ADDRESS */ + /* ======================================================================= */ + bool get_public_address(cryptonote::account_public_address &pubkey) override; + bool get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) override; + + /* ======================================================================= */ + /* TREZOR PROTOCOL */ + /* ======================================================================= */ + + /** + * Get address. Throws. + */ + std::shared_ptr get_address( + const boost::optional> & path = boost::none, + const boost::optional & network_type = boost::none); + + /** + * Get watch key from device. Throws. + */ + std::shared_ptr get_view_key( + const boost::optional> & path = boost::none, + const boost::optional & network_type = boost::none); + + /** + * Key image sync with the Trezor. + */ + void ki_sync(wallet_shim * wallet, + const std::vector<::tools::wallet2::transfer_details> & transfers, + hw::device_cold::exported_key_image & ski) override; + + /** + * Signs particular transaction idx in the unsigned set, keeps state in the signer + */ + void tx_sign(wallet_shim * wallet, + const ::tools::wallet2::unsigned_tx_set & unsigned_tx, + size_t idx, + hw::tx_aux_data & aux_data, + std::shared_ptr & signer); + + /** + * Signs unsigned transaction with the Trezor. + */ + void tx_sign(wallet_shim * wallet, + const ::tools::wallet2::unsigned_tx_set & unsigned_tx, + ::tools::wallet2::signed_tx_set & signed_tx, + hw::tx_aux_data & aux_data) override; + }; + +#endif + +} +} +#endif //MONERO_DEVICE_TREZOR_H diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp new file mode 100644 index 000000000..3a98bba5a --- /dev/null +++ b/src/device_trezor/device_trezor_base.cpp @@ -0,0 +1,301 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#include "device_trezor_base.hpp" + +namespace hw { +namespace trezor { + +#if WITH_DEVICE_TREZOR + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" + + std::shared_ptr trezor_protocol_callback::on_button_request(const messages::common::ButtonRequest * msg){ + MDEBUG("on_button_request"); + device.on_button_request(); + return std::make_shared(); + } + + std::shared_ptr trezor_protocol_callback::on_pin_matrix_request(const messages::common::PinMatrixRequest * msg){ + MDEBUG("on_pin_request"); + epee::wipeable_string pin; + device.on_pin_request(pin); + auto resp = std::make_shared(); + resp->set_pin(pin.data(), pin.size()); + return resp; + } + + std::shared_ptr trezor_protocol_callback::on_passphrase_request(const messages::common::PassphraseRequest * msg){ + MDEBUG("on_passhprase_request"); + epee::wipeable_string passphrase; + device.on_passphrase_request(msg->on_device(), passphrase); + auto resp = std::make_shared(); + if (!msg->on_device()){ + resp->set_passphrase(passphrase.data(), passphrase.size()); + } + return resp; + } + + std::shared_ptr trezor_protocol_callback::on_passphrase_state_request(const messages::common::PassphraseStateRequest * msg){ + MDEBUG("on_passhprase_state_request"); + device.on_passphrase_state_request(msg->state()); + return std::make_shared(); + } + + const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; + + device_trezor_base::device_trezor_base() { + + } + + device_trezor_base::~device_trezor_base() { + try { + disconnect(); + release(); + } catch(std::exception const& e){ + MERROR("Could not disconnect and release: " << e.what()); + } + } + + /* ======================================================================= */ + /* SETUP/TEARDOWN */ + /* ======================================================================= */ + + bool device_trezor_base::reset() { + return false; + } + + bool device_trezor_base::set_name(const std::string & name) { + this->full_name = name; + this->name = ""; + + auto delim = name.find(':'); + if (delim != std::string::npos && delim + 1 < name.length()) { + this->name = name.substr(delim + 1); + } + + return true; + } + + const std::string device_trezor_base::get_name() const { + if (this->full_name.empty()) { + return std::string("name).append(">"); + } + return this->full_name; + } + + bool device_trezor_base::init() { + if (!release()){ + MERROR("Release failed"); + return false; + } + + if (!m_protocol_callback){ + m_protocol_callback = std::make_shared(*this); + } + return true; + } + + bool device_trezor_base::release() { + try { + disconnect(); + return true; + + } catch(std::exception const& e){ + MERROR("Release exception: " << e.what()); + return false; + } + } + + bool device_trezor_base::connect() { + disconnect(); + + // Enumerate all available devices + try { + hw::trezor::t_transport_vect trans; + + MDEBUG("Enumerating Trezor devices..."); + enumerate(trans); + + MDEBUG("Enumeration yielded " << trans.size() << " devices"); + for (auto &cur : trans) { + MDEBUG(" device: " << *(cur.get())); + std::string cur_path = cur->get_path(); + if (boost::starts_with(cur_path, this->name)) { + MDEBUG("Device Match: " << cur_path); + m_transport = cur; + break; + } + } + + if (!m_transport) { + MERROR("No matching Trezor device found. Device specifier: \"" + this->name + "\""); + return false; + } + + m_transport->open(); + return true; + + } catch(std::exception const& e){ + MERROR("Open exception: " << e.what()); + return false; + } + } + + bool device_trezor_base::disconnect() { + if (m_transport){ + try { + m_transport->close(); + m_transport = nullptr; + + } catch(std::exception const& e){ + MERROR("Disconnect exception: " << e.what()); + m_transport = nullptr; + return false; + } + } + return true; + } + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + + //lock the device for a long sequence + void device_trezor_base::lock() { + MTRACE("Ask for LOCKING for device " << this->name << " in thread "); + device_locker.lock(); + MTRACE("Device " << this->name << " LOCKed"); + } + + //lock the device for a long sequence + bool device_trezor_base::try_lock() { + MTRACE("Ask for LOCKING(try) for device " << this->name << " in thread "); + bool r = device_locker.try_lock(); + if (r) { + MTRACE("Device " << this->name << " LOCKed(try)"); + } else { + MDEBUG("Device " << this->name << " not LOCKed(try)"); + } + return r; + } + + //unlock the device + void device_trezor_base::unlock() { + MTRACE("Ask for UNLOCKING for device " << this->name << " in thread "); + device_locker.unlock(); + MTRACE("Device " << this->name << " UNLOCKed"); + } + + /* ======================================================================= */ + /* Helpers */ + /* ======================================================================= */ + + void device_trezor_base::require_connected(){ + if (!m_transport){ + throw exc::NotConnectedException(); + } + } + + void device_trezor_base::call_ping_unsafe(){ + auto pingMsg = std::make_shared(); + pingMsg->set_message("PING"); + + auto success = this->client_exchange(pingMsg); // messages::MessageType_Success + MDEBUG("Ping response " << success->message()); + (void)success; + } + + void device_trezor_base::test_ping(){ + require_connected(); + + try { + this->call_ping_unsafe(); + + } catch(exc::TrezorException const& e){ + MINFO("Trezor does not respond: " << e.what()); + throw exc::DeviceNotResponsiveException(std::string("Trezor not responding: ") + e.what()); + } + } + + /* ======================================================================= */ + /* TREZOR PROTOCOL */ + /* ======================================================================= */ + + bool device_trezor_base::ping() { + AUTO_LOCK_CMD(); + if (!m_transport){ + MINFO("Ping failed, device not connected"); + return false; + } + + try { + this->call_ping_unsafe(); + return true; + + } catch(std::exception const& e) { + MERROR("Ping failed, exception thrown " << e.what()); + } catch(...){ + MERROR("Ping failed, general exception thrown" << boost::current_exception_diagnostic_information()); + } + + return false; + } + + void device_trezor_base::on_button_request() + { + if (m_callback){ + m_callback->on_button_request(); + } + } + + void device_trezor_base::on_pin_request(epee::wipeable_string & pin) + { + if (m_callback){ + m_callback->on_pin_request(pin); + } + } + + void device_trezor_base::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) + { + if (m_callback){ + m_callback->on_passphrase_request(on_device, passphrase); + } + } + + void device_trezor_base::on_passphrase_state_request(const std::string & state) + { + if (m_callback){ + m_callback->on_passphrase_state_request(state); + } + } + +#endif //WITH_DEVICE_TREZOR +}} diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp new file mode 100644 index 000000000..644a49332 --- /dev/null +++ b/src/device_trezor/device_trezor_base.hpp @@ -0,0 +1,301 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_DEVICE_TREZOR_BASE_H +#define MONERO_DEVICE_TREZOR_BASE_H + + +#include +#include +#include "device/device.hpp" +#include "device/device_default.hpp" +#include "device/device_cold.hpp" +#include +#include +#include +#include "cryptonote_config.h" +#include "trezor.hpp" + +//automatic lock one more level on device ensuring the current thread is allowed to use it +#define AUTO_LOCK_CMD() \ + /* lock both mutexes without deadlock*/ \ + boost::lock(device_locker, command_locker); \ + /* make sure both already-locked mutexes are unlocked at the end of scope */ \ + boost::lock_guard lock1(device_locker, boost::adopt_lock); \ + boost::lock_guard lock2(command_locker, boost::adopt_lock) + + +namespace hw { +namespace trezor { + +#if WITH_DEVICE_TREZOR + class device_trezor_base; + + /** + * Trezor device callbacks + */ + class trezor_callback { + public: + virtual void on_button_request() {}; + virtual void on_pin_request(epee::wipeable_string & pin) {}; + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {}; + virtual void on_passphrase_state_request(const std::string & state) {}; + }; + + /** + * Default Trezor protocol client callback + */ + class trezor_protocol_callback { + protected: + device_trezor_base & device; + + public: + explicit trezor_protocol_callback(device_trezor_base & device): device(device) {} + + std::shared_ptr on_button_request(const messages::common::ButtonRequest * msg); + std::shared_ptr on_pin_matrix_request(const messages::common::PinMatrixRequest * msg); + std::shared_ptr on_passphrase_request(const messages::common::PassphraseRequest * msg); + std::shared_ptr on_passphrase_state_request(const messages::common::PassphraseStateRequest * msg); + + std::shared_ptr on_message(const google::protobuf::Message * msg, messages::MessageType message_type){ + MDEBUG("on_general_message"); + return on_message_dispatch(msg, message_type); + } + + std::shared_ptr on_message_dispatch(const google::protobuf::Message * msg, messages::MessageType message_type){ + if (message_type == messages::MessageType_ButtonRequest){ + return on_button_request(dynamic_cast(msg)); + } else if (message_type == messages::MessageType_PassphraseRequest) { + return on_passphrase_request(dynamic_cast(msg)); + } else if (message_type == messages::MessageType_PassphraseStateRequest) { + return on_passphrase_state_request(dynamic_cast(msg)); + } else if (message_type == messages::MessageType_PinMatrixRequest) { + return on_pin_matrix_request(dynamic_cast(msg)); + } else { + return nullptr; + } + } + }; + + /** + * TREZOR device template with basic functions + */ + class device_trezor_base : public hw::core::device_default { + protected: + + // Locker for concurrent access + mutable boost::recursive_mutex device_locker; + mutable boost::mutex command_locker; + + std::shared_ptr m_transport; + std::shared_ptr m_protocol_callback; + std::shared_ptr m_callback; + + std::string full_name; + + cryptonote::network_type network_type; + + // + // Internal methods + // + + void require_connected(); + void call_ping_unsafe(); + void test_ping(); + + /** + * Client communication wrapper, handles specific Trezor protocol. + * + * @throws UnexpectedMessageException if the response message type is different than expected. + * Exception contains message type and the message itself. + */ + template + std::shared_ptr + client_exchange(const std::shared_ptr &req, + const boost::optional & resp_type = boost::none, + const boost::optional> & resp_types = boost::none, + const boost::optional & resp_type_ptr = boost::none, + bool open_session = false, + unsigned depth=0) + { + // Require strictly protocol buffers response in the template. + BOOST_STATIC_ASSERT(boost::is_base_of::value); + const bool accepting_base = boost::is_same::value; + if (resp_types && !accepting_base){ + throw std::invalid_argument("Cannot specify list of accepted types and not using generic response"); + } + + // Open session if required + if (open_session && depth == 0){ + try { + m_transport->open(); + } catch (const std::exception& e) { + std::throw_with_nested(exc::SessionException("Could not open session")); + } + } + + // Scoped session closer + BOOST_SCOPE_EXIT_ALL(&, this) { + if (open_session && depth == 0){ + this->getTransport()->close(); + } + }; + + // Write the request + CHECK_AND_ASSERT_THROW_MES(req, "Request is null"); + this->getTransport()->write(*req); + + // Read the response + std::shared_ptr msg_resp; + hw::trezor::messages::MessageType msg_resp_type; + + // We may have several roundtrips with the handler + this->getTransport()->read(msg_resp, &msg_resp_type); + if (resp_type_ptr){ + *(resp_type_ptr.get()) = msg_resp_type; + } + + // Determine type of expected message response + messages::MessageType required_type = accepting_base ? messages::MessageType_Success : + (resp_type ? resp_type.get() : MessageMapper::get_message_wire_number()); + + if (msg_resp_type == messages::MessageType_Failure) { + throw_failure_exception(dynamic_cast(msg_resp.get())); + + } else if (!accepting_base && msg_resp_type == required_type) { + return message_ptr_retype(msg_resp); + + } else { + auto resp = this->getProtocolCallback()->on_message(msg_resp.get(), msg_resp_type); + if (resp) { + return this->client_exchange(resp, boost::none, resp_types, resp_type_ptr, false, depth + 1); + + } else if (accepting_base && (!resp_types || + std::find(resp_types.get().begin(), resp_types.get().end(), msg_resp_type) != resp_types.get().end())) { + return message_ptr_retype(msg_resp); + + } else { + throw exc::UnexpectedMessageException(msg_resp_type, msg_resp); + } + } + } + + /** + * Utility method to set address_n and network type to the message requets. + */ + template + void set_msg_addr(t_message * msg, + const boost::optional> & path = boost::none, + const boost::optional & network_type = boost::none) + { + CHECK_AND_ASSERT_THROW_MES(msg, "Message is null"); + msg->clear_address_n(); + if (path){ + for(auto x : path.get()){ + msg->add_address_n(x); + } + } else { + for (unsigned int i : DEFAULT_BIP44_PATH) { + msg->add_address_n(i); + } + } + + if (network_type){ + msg->set_network_type(static_cast(network_type.get())); + } else { + msg->set_network_type(static_cast(this->network_type)); + } + } + + public: + device_trezor_base(); + ~device_trezor_base() override; + + device_trezor_base(const device_trezor_base &device) = delete ; + device_trezor_base& operator=(const device_trezor_base &device) = delete; + + explicit operator bool() const override {return true;} + device_type get_type() const override {return device_type::TREZOR;}; + + bool reset(); + + // Default derivation path for Monero + static const uint32_t DEFAULT_BIP44_PATH[3]; + + std::shared_ptr getTransport(){ + return m_transport; + } + + std::shared_ptr getProtocolCallback(){ + return m_protocol_callback; + } + + std::shared_ptr getCallback(){ + return m_callback; + } + + /* ======================================================================= */ + /* SETUP/TEARDOWN */ + /* ======================================================================= */ + bool set_name(const std::string &name) override; + + const std::string get_name() const override; + bool init() override; + bool release() override; + bool connect() override; + bool disconnect() override; + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + void lock() override; + void unlock() override; + bool try_lock() override; + + /* ======================================================================= */ + /* TREZOR PROTOCOL */ + /* ======================================================================= */ + + /** + * Device ping, no-throw + */ + bool ping(); + + // Protocol callbacks + void on_button_request(); + void on_pin_request(epee::wipeable_string & pin); + void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); + void on_passphrase_state_request(const std::string & state); + }; + +#endif + +} +} +#endif //MONERO_DEVICE_TREZOR_BASE_H diff --git a/src/device_trezor/trezor.hpp b/src/device_trezor/trezor.hpp new file mode 100644 index 000000000..8abdd2c18 --- /dev/null +++ b/src/device_trezor/trezor.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_TREZOR_HPP +#define MONERO_TREZOR_HPP + +#include "trezor/trezor_defs.hpp" + +#ifdef HAVE_PROTOBUF +#include "trezor/transport.hpp" +#include "trezor/messages/messages.pb.h" +#include "trezor/messages/messages-common.pb.h" +#include "trezor/messages/messages-management.pb.h" +#include "trezor/messages/messages-monero.pb.h" +#include "trezor/protocol.hpp" +#endif + +#endif //MONERO_TREZOR_HPP diff --git a/src/device_trezor/trezor/exceptions.hpp b/src/device_trezor/trezor/exceptions.hpp new file mode 100644 index 000000000..197dc43a4 --- /dev/null +++ b/src/device_trezor/trezor/exceptions.hpp @@ -0,0 +1,193 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_EXCEPTIONS_H +#define MONERO_EXCEPTIONS_H + +#include +#include +#include + +namespace hw { +namespace trezor { +namespace exc { + + class SecurityException : public std::exception { + protected: + boost::optional reason; + + public: + SecurityException(): reason("General Security exception"){} + explicit SecurityException(std::string what): reason(what){} + + virtual const char* what() const throw() { + return reason.get().c_str(); + } + }; + + class Poly1305TagInvalid: public SecurityException { + public: + using SecurityException::SecurityException; + Poly1305TagInvalid(): SecurityException("Poly1305 authentication tag invalid"){} + }; + + class TrezorException : public std::exception { + protected: + boost::optional reason; + + public: + TrezorException(): reason("General Trezor exception"){} + explicit TrezorException(std::string what): reason(what){} + + virtual const char* what() const throw() { + return reason.get().c_str(); + } + }; + + class CommunicationException: public TrezorException { + public: + using TrezorException::TrezorException; + CommunicationException(): TrezorException("Trezor communication error"){} + }; + + class EncodingException: public CommunicationException { + public: + using CommunicationException::CommunicationException; + EncodingException(): CommunicationException("Trezor message encoding error"){} + }; + + class NotConnectedException : public CommunicationException { + public: + using CommunicationException::CommunicationException; + NotConnectedException(): CommunicationException("Trezor not connected"){} + }; + + class DeviceNotResponsiveException : public CommunicationException { + public: + using CommunicationException::CommunicationException; + DeviceNotResponsiveException(): CommunicationException("Trezor does not respond to ping"){} + }; + + class DeviceAcquireException : public CommunicationException { + public: + using CommunicationException::CommunicationException; + DeviceAcquireException(): CommunicationException("Trezor could not be acquired"){} + }; + + class SessionException: public CommunicationException { + public: + using CommunicationException::CommunicationException; + SessionException(): CommunicationException("Trezor session expired"){} + }; + + class TimeoutException: public CommunicationException { + public: + using CommunicationException::CommunicationException; + TimeoutException(): CommunicationException("Trezor communication timeout"){} + }; + + class ProtocolException: public CommunicationException { + public: + using CommunicationException::CommunicationException; + ProtocolException(): CommunicationException("Trezor protocol error"){} + }; + + // Communication protocol namespace + // Separated to distinguish between client and Trezor side exceptions. +namespace proto { + + class SecurityException : public ProtocolException { + public: + using ProtocolException::ProtocolException; + SecurityException(): ProtocolException("Security assertion violated in the protocol"){} + }; + + class FailureException : public ProtocolException { + private: + boost::optional code; + boost::optional message; + public: + using ProtocolException::ProtocolException; + FailureException(): ProtocolException("Trezor returned failure"){} + FailureException(boost::optional code, + boost::optional message) + : code(code), message(message) { + reason = "Trezor returned failure: code=" + + (code ? std::to_string(code.get()) : "") + + ", message=" + (message ? message.get() : ""); + }; + }; + + class UnexpectedMessageException : public FailureException { + public: + using FailureException::FailureException; + UnexpectedMessageException(): FailureException("Trezor claims unexpected message received"){} + }; + + class CancelledException : public FailureException { + public: + using FailureException::FailureException; + CancelledException(): FailureException("Trezor returned: cancelled operation"){} + }; + + class PinExpectedException : public FailureException { + public: + using FailureException::FailureException; + PinExpectedException(): FailureException("Trezor claims PIN is expected"){} + }; + + class InvalidPinException : public FailureException { + public: + using FailureException::FailureException; + InvalidPinException(): FailureException("Trezor claims PIN is invalid"){} + }; + + class NotEnoughFundsException : public FailureException { + public: + using FailureException::FailureException; + NotEnoughFundsException(): FailureException("Trezor claims not enough funds"){} + }; + + class NotInitializedException : public FailureException { + public: + using FailureException::FailureException; + NotInitializedException(): FailureException("Trezor claims not initialized"){} + }; + + class FirmwareErrorException : public FailureException { + public: + using FailureException::FailureException; + FirmwareErrorException(): FailureException("Trezor returned firmware error"){} + }; + +} +} +} +} +#endif //MONERO_EXCEPTIONS_H diff --git a/src/device_trezor/trezor/messages/.gitignore b/src/device_trezor/trezor/messages/.gitignore new file mode 100644 index 000000000..32f7a77e5 --- /dev/null +++ b/src/device_trezor/trezor/messages/.gitignore @@ -0,0 +1,2 @@ +# protobuf generated code +* diff --git a/src/device_trezor/trezor/messages_map.cpp b/src/device_trezor/trezor/messages_map.cpp new file mode 100644 index 000000000..b0d1aa254 --- /dev/null +++ b/src/device_trezor/trezor/messages_map.cpp @@ -0,0 +1,125 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#include "messages_map.hpp" +#include "messages/messages.pb.h" +#include "messages/messages-common.pb.h" +#include "messages/messages-management.pb.h" +#include "messages/messages-monero.pb.h" + +using namespace std; +using namespace hw::trezor; + +namespace hw{ +namespace trezor +{ + + const char * TYPE_PREFIX = "MessageType_"; + const char * PACKAGES[] = { + "hw.trezor.messages.", + "hw.trezor.messages.common.", + "hw.trezor.messages.management.", + "hw.trezor.messages.monero." + }; + + google::protobuf::Message * MessageMapper::get_message(int wire_number) { + return MessageMapper::get_message(static_cast(wire_number)); + } + + google::protobuf::Message * MessageMapper::get_message(messages::MessageType wire_number) { + const string &messageTypeName = hw::trezor::messages::MessageType_Name(wire_number); + if (messageTypeName.empty()) { + throw exc::EncodingException(std::string("Message descriptor not found: ") + std::to_string(wire_number)); + } + + string messageName = messageTypeName.substr(strlen(TYPE_PREFIX)); + return MessageMapper::get_message(messageName); + } + + google::protobuf::Message * MessageMapper::get_message(const std::string & msg_name) { + // Each package instantiation so lookup works + hw::trezor::messages::common::Success::default_instance(); + hw::trezor::messages::management::Cancel::default_instance(); + hw::trezor::messages::monero::MoneroGetAddress::default_instance(); + + google::protobuf::Descriptor const * desc = nullptr; + for(const string &text : PACKAGES){ + desc = google::protobuf::DescriptorPool::generated_pool() + ->FindMessageTypeByName(text + msg_name); + if (desc != nullptr){ + break; + } + } + + if (desc == nullptr){ + throw exc::EncodingException(std::string("Message not found: ") + msg_name); + } + + google::protobuf::Message* message = + google::protobuf::MessageFactory::generated_factory() + ->GetPrototype(desc)->New(); + + return message; + +// // CODEGEN way, fast +// switch(wire_number){ +// case 501: +// return new messages::monero::MoneroTransactionSignRequest(); +// default: +// throw std::runtime_error("not implemented"); +// } +// +// // CODEGEN message -> number: specification +// // messages::MessageType get_message_wire_number(const messages::monero::MoneroTransactionSignRequest * msg) { return 501; } +// // messages::MessageType get_message_wire_number(const messages::management::ping * msg) +// + } + + messages::MessageType MessageMapper::get_message_wire_number(const google::protobuf::Message * msg){ + return MessageMapper::get_message_wire_number(msg->GetDescriptor()->name()); + } + + messages::MessageType MessageMapper::get_message_wire_number(const google::protobuf::Message & msg){ + return MessageMapper::get_message_wire_number(msg.GetDescriptor()->name()); + } + + messages::MessageType MessageMapper::get_message_wire_number(const std::string & msg_name){ + string enumMessageName = std::string(TYPE_PREFIX) + msg_name; + + messages::MessageType res; + bool r = hw::trezor::messages::MessageType_Parse(enumMessageName, &res); + if (!r){ + throw exc::EncodingException(std::string("Message ") + msg_name + " not found"); + } + + return res; + } + +} +} diff --git a/src/device_trezor/trezor/messages_map.hpp b/src/device_trezor/trezor/messages_map.hpp new file mode 100644 index 000000000..f61338f09 --- /dev/null +++ b/src/device_trezor/trezor/messages_map.hpp @@ -0,0 +1,94 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_MESSAGES_MAP_H +#define MONERO_MESSAGES_MAP_H + +#include +#include +#include +#include "exceptions.hpp" + +#include "trezor_defs.hpp" + +#include +#include +#include +#include +#include +#include "google/protobuf/descriptor.pb.h" + +#include "messages/messages.pb.h" + +namespace hw { +namespace trezor { + + class MessageMapper{ + public: + MessageMapper() { + + } + + static ::google::protobuf::Message * get_message(int wire_number); + static ::google::protobuf::Message * get_message(messages::MessageType); + static ::google::protobuf::Message * get_message(const std::string & msg_name); + static messages::MessageType get_message_wire_number(const google::protobuf::Message * msg); + static messages::MessageType get_message_wire_number(const google::protobuf::Message & msg); + static messages::MessageType get_message_wire_number(const std::string & msg_name); + + template + static messages::MessageType get_message_wire_number() { + BOOST_STATIC_ASSERT(boost::is_base_of::value); + return get_message_wire_number(t_message::default_instance().GetDescriptor()->name()); + } + }; + + template + std::shared_ptr message_ptr_retype(std::shared_ptr & in){ + BOOST_STATIC_ASSERT(boost::is_base_of::value); + if (!in){ + return nullptr; + } + + return std::dynamic_pointer_cast(in); + } + + template + std::shared_ptr message_ptr_retype_static(std::shared_ptr & in){ + BOOST_STATIC_ASSERT(boost::is_base_of::value); + if (!in){ + return nullptr; + } + + return std::static_pointer_cast(in); + } + +}} + +#endif //MONERO_MESSAGES_MAP_H diff --git a/src/device_trezor/trezor/protocol.cpp b/src/device_trezor/trezor/protocol.cpp new file mode 100644 index 000000000..c4a92426c --- /dev/null +++ b/src/device_trezor/trezor/protocol.cpp @@ -0,0 +1,891 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#include "protocol.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "cryptonote_config.h" +#include +#include +#include + +namespace hw{ +namespace trezor{ +namespace protocol{ + + std::string key_to_string(const ::crypto::ec_point & key){ + return std::string(key.data, sizeof(key.data)); + } + + std::string key_to_string(const ::crypto::ec_scalar & key){ + return std::string(key.data, sizeof(key.data)); + } + + std::string key_to_string(const ::crypto::hash & key){ + return std::string(key.data, sizeof(key.data)); + } + + std::string key_to_string(const ::rct::key & key){ + return std::string(reinterpret_cast(key.bytes), sizeof(key.bytes)); + } + + void string_to_key(::crypto::ec_scalar & key, const std::string & str){ + if (str.size() != sizeof(key.data)){ + throw std::invalid_argument(std::string("Key has to have ") + std::to_string(sizeof(key.data)) + " B"); + } + memcpy(key.data, str.data(), sizeof(key.data)); + } + + void string_to_key(::crypto::ec_point & key, const std::string & str){ + if (str.size() != sizeof(key.data)){ + throw std::invalid_argument(std::string("Key has to have ") + std::to_string(sizeof(key.data)) + " B"); + } + memcpy(key.data, str.data(), sizeof(key.data)); + } + + void string_to_key(::rct::key & key, const std::string & str){ + if (str.size() != sizeof(key.bytes)){ + throw std::invalid_argument(std::string("Key has to have ") + std::to_string(sizeof(key.bytes)) + " B"); + } + memcpy(key.bytes, str.data(), sizeof(key.bytes)); + } + +namespace crypto { +namespace chacha { + + void decrypt(const void* ciphertext, size_t length, const uint8_t* key, const uint8_t* iv, char* plaintext){ + if (length < 16){ + throw std::invalid_argument("Ciphertext length too small"); + } + + unsigned long long int cip_len = length; + auto r = crypto_aead_chacha20poly1305_ietf_decrypt( + reinterpret_cast(plaintext), &cip_len, nullptr, + static_cast(ciphertext), length, nullptr, 0, iv, key); + + if (r != 0){ + throw exc::Poly1305TagInvalid(); + } + } + +} +} + + +// Cold Key image sync +namespace ki { + + bool key_image_data(wallet_shim * wallet, + const std::vector & transfers, + std::vector & res) + { + for(auto & td : transfers){ + ::crypto::public_key tx_pub_key = wallet->get_tx_pub_key_from_received_outs(td); + const std::vector<::crypto::public_key> additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(td.m_tx); + + res.emplace_back(); + auto & cres = res.back(); + + cres.set_out_key(key_to_string(boost::get(td.m_tx.vout[td.m_internal_output_index].target).key)); + cres.set_tx_pub_key(key_to_string(tx_pub_key)); + cres.set_internal_output_index(td.m_internal_output_index); + for(auto & aux : additional_tx_pub_keys){ + cres.add_additional_tx_pub_keys(key_to_string(aux)); + } + } + + return true; + } + + std::string compute_hash(const MoneroTransferDetails & rr){ + KECCAK_CTX kck; + uint8_t md[32]; + + CHECK_AND_ASSERT_THROW_MES(rr.out_key().size() == 32, "Invalid out_key size"); + CHECK_AND_ASSERT_THROW_MES(rr.tx_pub_key().size() == 32, "Invalid tx_pub_key size"); + + keccak_init(&kck); + keccak_update(&kck, reinterpret_cast(rr.out_key().data()), 32); + keccak_update(&kck, reinterpret_cast(rr.tx_pub_key().data()), 32); + for (const auto &aux : rr.additional_tx_pub_keys()){ + CHECK_AND_ASSERT_THROW_MES(aux.size() == 32, "Invalid aux size"); + keccak_update(&kck, reinterpret_cast(aux.data()), 32); + } + + auto index_serialized = tools::get_varint_data(rr.internal_output_index()); + keccak_update(&kck, reinterpret_cast(index_serialized.data()), index_serialized.size()); + keccak_finish(&kck, md); + return std::string(reinterpret_cast(md), sizeof(md)); + } + + void generate_commitment(std::vector & mtds, + const std::vector & transfers, + std::shared_ptr & req) + { + req = std::make_shared(); + + KECCAK_CTX kck; + uint8_t final_hash[32]; + keccak_init(&kck); + + for(auto &cur : mtds){ + auto hash = compute_hash(cur); + keccak_update(&kck, reinterpret_cast(hash.data()), hash.size()); + } + keccak_finish(&kck, final_hash); + + req = std::make_shared(); + req->set_hash(std::string(reinterpret_cast(final_hash), 32)); + req->set_num(transfers.size()); + + std::unordered_map> sub_indices; + for (auto &cur : transfers){ + auto search = sub_indices.emplace(cur.m_subaddr_index.major, std::set()); + auto & st = search.first->second; + st.insert(cur.m_subaddr_index.minor); + } + + for (auto& x: sub_indices){ + auto subs = req->add_subs(); + subs->set_account(x.first); + for(auto minor : x.second){ + subs->add_minor_indices(minor); + } + } + } + +} + +// Cold transaction signing +namespace tx { + + void translate_address(MoneroAccountPublicAddress * dst, const cryptonote::account_public_address * src){ + dst->set_view_public_key(key_to_string(src->m_view_public_key)); + dst->set_spend_public_key(key_to_string(src->m_spend_public_key)); + } + + void translate_dst_entry(MoneroTransactionDestinationEntry * dst, const cryptonote::tx_destination_entry * src){ + dst->set_amount(src->amount); + dst->set_is_subaddress(src->is_subaddress); + translate_address(dst->mutable_addr(), &(src->addr)); + } + + void translate_src_entry(MoneroTransactionSourceEntry * dst, const cryptonote::tx_source_entry * src){ + for(auto & cur : src->outputs){ + auto out = dst->add_outputs(); + out->set_idx(cur.first); + translate_rct_key(out->mutable_key(), &(cur.second)); + } + + dst->set_real_output(src->real_output); + dst->set_real_out_tx_key(key_to_string(src->real_out_tx_key)); + for(auto & cur : src->real_out_additional_tx_keys){ + dst->add_real_out_additional_tx_keys(key_to_string(cur)); + } + + dst->set_real_output_in_tx_index(src->real_output_in_tx_index); + dst->set_amount(src->amount); + dst->set_rct(src->rct); + dst->set_mask(key_to_string(src->mask)); + translate_klrki(dst->mutable_multisig_klrki(), &(src->multisig_kLRki)); + } + + void translate_klrki(MoneroMultisigKLRki * dst, const rct::multisig_kLRki * src){ + dst->set_k(key_to_string(src->k)); + dst->set_l(key_to_string(src->L)); + dst->set_r(key_to_string(src->R)); + dst->set_ki(key_to_string(src->ki)); + } + + void translate_rct_key(MoneroRctKey * dst, const rct::ctkey * src){ + dst->set_dest(key_to_string(src->dest)); + dst->set_commitment(key_to_string(src->mask)); + } + + std::string hash_addr(const MoneroAccountPublicAddress * addr, boost::optional amount, boost::optional is_subaddr){ + return hash_addr(addr->spend_public_key(), addr->view_public_key(), amount, is_subaddr); + } + + std::string hash_addr(const std::string & spend_key, const std::string & view_key, boost::optional amount, boost::optional is_subaddr){ + ::crypto::public_key spend{}, view{}; + if (spend_key.size() != 32 || view_key.size() != 32){ + throw std::invalid_argument("Public keys have invalid sizes"); + } + + memcpy(spend.data, spend_key.data(), 32); + memcpy(view.data, view_key.data(), 32); + return hash_addr(&spend, &view, amount, is_subaddr); + } + + std::string hash_addr(const ::crypto::public_key * spend_key, const ::crypto::public_key * view_key, boost::optional amount, boost::optional is_subaddr){ + char buff[64+8+1]; + size_t offset = 0; + + memcpy(buff + offset, spend_key->data, 32); offset += 32; + memcpy(buff + offset, view_key->data, 32); offset += 32; + + if (amount){ + memcpy(buff + offset, (uint8_t*) &(amount.get()), sizeof(amount.get())); offset += sizeof(amount.get()); + } + + if (is_subaddr){ + buff[offset] = is_subaddr.get(); + offset += 1; + } + + return std::string(buff, offset); + } + + TData::TData() { + in_memory = false; + rsig_type = 0; + cur_input_idx = 0; + cur_output_idx = 0; + cur_batch_idx = 0; + cur_output_in_batch_idx = 0; + } + + Signer::Signer(wallet_shim *wallet2, const unsigned_tx_set * unsigned_tx, size_t tx_idx, hw::tx_aux_data * aux_data) { + m_wallet2 = wallet2; + m_unsigned_tx = unsigned_tx; + m_aux_data = aux_data; + m_tx_idx = tx_idx; + m_ct.tx_data = cur_tx(); + m_multisig = false; + } + + void Signer::extract_payment_id(){ + const std::vector& tx_extra = cur_tx().extra; + m_ct.tsx_data.set_payment_id(""); + + std::vector tx_extra_fields; + cryptonote::parse_tx_extra(tx_extra, tx_extra_fields); // ok if partially parsed + cryptonote::tx_extra_nonce extra_nonce; + + ::crypto::hash payment_id{}; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + { + ::crypto::hash8 payment_id8{}; + if(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) + { + m_ct.tsx_data.set_payment_id(std::string(payment_id8.data, 8)); + } + else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + { + m_ct.tsx_data.set_payment_id(std::string(payment_id.data, 32)); + } + } + } + + static unsigned get_rsig_type(bool use_bulletproof, size_t num_outputs){ + if (!use_bulletproof){ + return rct::RangeProofBorromean; + } else if (num_outputs > BULLETPROOF_MAX_OUTPUTS){ + return rct::RangeProofMultiOutputBulletproof; + } else { + return rct::RangeProofPaddedBulletproof; + } + } + + static void generate_rsig_batch_sizes(std::vector &batches, unsigned rsig_type, size_t num_outputs){ + size_t amount_batched = 0; + + while(amount_batched < num_outputs){ + if (rsig_type == rct::RangeProofBorromean || rsig_type == rct::RangeProofBulletproof) { + batches.push_back(1); + amount_batched += 1; + + } else if (rsig_type == rct::RangeProofPaddedBulletproof){ + if (num_outputs > BULLETPROOF_MAX_OUTPUTS){ + throw std::invalid_argument("BP padded can support only BULLETPROOF_MAX_OUTPUTS statements"); + } + batches.push_back(num_outputs); + amount_batched += num_outputs; + + } else if (rsig_type == rct::RangeProofMultiOutputBulletproof){ + size_t batch_size = 1; + while (batch_size * 2 + amount_batched <= num_outputs && batch_size * 2 <= BULLETPROOF_MAX_OUTPUTS){ + batch_size *= 2; + } + batch_size = std::min(batch_size, num_outputs - amount_batched); + batches.push_back(batch_size); + amount_batched += batch_size; + + } else { + throw std::invalid_argument("Unknown rsig type"); + } + } + } + + void Signer::compute_integrated_indices(TsxData * tsx_data){ + if (m_aux_data == nullptr || m_aux_data->tx_recipients.empty()){ + return; + } + + auto & chg = tsx_data->change_dts(); + std::string change_hash = hash_addr(&chg.addr(), chg.amount(), chg.is_subaddress()); + + std::vector integrated_indices; + std::set integrated_hashes; + for (auto & cur : m_aux_data->tx_recipients){ + if (!cur.has_payment_id){ + continue; + } + integrated_hashes.emplace(hash_addr(&cur.address.m_spend_public_key, &cur.address.m_view_public_key)); + } + + ssize_t idx = -1; + for (auto & cur : tsx_data->outputs()){ + idx += 1; + + std::string c_hash = hash_addr(&cur.addr(), cur.amount(), cur.is_subaddress()); + if (c_hash == change_hash || cur.is_subaddress()){ + continue; + } + + c_hash = hash_addr(&cur.addr()); + if (integrated_hashes.find(c_hash) != integrated_hashes.end()){ + integrated_indices.push_back((uint32_t)idx); + } + } + + if (!integrated_indices.empty()){ + assign_to_repeatable(tsx_data->mutable_integrated_indices(), integrated_indices.begin(), integrated_indices.end()); + } + } + + std::shared_ptr Signer::step_init(){ + // extract payment ID from construction data + auto & tsx_data = m_ct.tsx_data; + auto & tx = cur_tx(); + + m_ct.tx.version = 2; + m_ct.tx.unlock_time = tx.unlock_time; + + tsx_data.set_version(1); + tsx_data.set_unlock_time(tx.unlock_time); + tsx_data.set_num_inputs(static_cast(tx.sources.size())); + tsx_data.set_mixin(static_cast(tx.sources[0].outputs.size() - 1)); + tsx_data.set_account(tx.subaddr_account); + assign_to_repeatable(tsx_data.mutable_minor_indices(), tx.subaddr_indices.begin(), tx.subaddr_indices.end()); + + // Rsig decision + auto rsig_data = tsx_data.mutable_rsig_data(); + m_ct.rsig_type = get_rsig_type(tx.use_bulletproofs, tx.splitted_dsts.size()); + rsig_data->set_rsig_type(m_ct.rsig_type); + + generate_rsig_batch_sizes(m_ct.grouping_vct, m_ct.rsig_type, tx.splitted_dsts.size()); + assign_to_repeatable(rsig_data->mutable_grouping(), m_ct.grouping_vct.begin(), m_ct.grouping_vct.end()); + + translate_dst_entry(tsx_data.mutable_change_dts(), &(tx.change_dts)); + for(auto & cur : tx.splitted_dsts){ + auto dst = tsx_data.mutable_outputs()->Add(); + translate_dst_entry(dst, &cur); + } + + compute_integrated_indices(&tsx_data); + + int64_t fee = 0; + for(auto & cur_in : tx.sources){ + fee += cur_in.amount; + } + for(auto & cur_out : tx.splitted_dsts){ + fee -= cur_out.amount; + } + if (fee < 0){ + throw std::invalid_argument("Fee cannot be negative"); + } + + tsx_data.set_fee(static_cast(fee)); + this->extract_payment_id(); + + auto init_req = std::make_shared(); + init_req->set_version(0); + init_req->mutable_tsx_data()->CopyFrom(tsx_data); + return init_req; + } + + void Signer::step_init_ack(std::shared_ptr ack){ + m_ct.in_memory = false; + if (ack->has_rsig_data()){ + m_ct.rsig_param = std::make_shared(ack->rsig_data()); + } + + assign_from_repeatable(&(m_ct.tx_out_entr_hmacs), ack->hmacs().begin(), ack->hmacs().end()); + } + + std::shared_ptr Signer::step_set_input(size_t idx){ + CHECK_AND_ASSERT_THROW_MES(idx < cur_tx().sources.size(), "Invalid source index"); + m_ct.cur_input_idx = idx; + auto res = std::make_shared(); + translate_src_entry(res->mutable_src_entr(), &(cur_tx().sources[idx])); + return res; + } + + void Signer::step_set_input_ack(std::shared_ptr ack){ + auto & vini_str = ack->vini(); + + cryptonote::txin_v vini; + if (!cn_deserialize(vini_str.data(), vini_str.size(), vini)){ + throw exc::ProtocolException("Cannot deserialize vin[i]"); + } + + m_ct.tx.vin.emplace_back(vini); + m_ct.tx_in_hmacs.push_back(ack->vini_hmac()); + m_ct.pseudo_outs.push_back(ack->pseudo_out()); + m_ct.pseudo_outs_hmac.push_back(ack->pseudo_out_hmac()); + m_ct.alphas.push_back(ack->pseudo_out_alpha()); + m_ct.spend_encs.push_back(ack->spend_key()); + } + + void Signer::sort_ki(){ + const size_t input_size = cur_tx().sources.size(); + + m_ct.source_permutation.clear(); + for (size_t n = 0; n < input_size; ++n){ + m_ct.source_permutation.push_back(n); + } + + CHECK_AND_ASSERT_THROW_MES(m_ct.tx.vin.size() == input_size, "Invalid vector size"); + std::sort(m_ct.source_permutation.begin(), m_ct.source_permutation.end(), [&](const size_t i0, const size_t i1) { + const cryptonote::txin_to_key &tk0 = boost::get(m_ct.tx.vin[i0]); + const cryptonote::txin_to_key &tk1 = boost::get(m_ct.tx.vin[i1]); + return memcmp(&tk0.k_image, &tk1.k_image, sizeof(tk0.k_image)) > 0; + }); + + CHECK_AND_ASSERT_THROW_MES(m_ct.tx_in_hmacs.size() == input_size, "Invalid vector size"); + CHECK_AND_ASSERT_THROW_MES(m_ct.pseudo_outs.size() == input_size, "Invalid vector size"); + CHECK_AND_ASSERT_THROW_MES(m_ct.pseudo_outs_hmac.size() == input_size, "Invalid vector size"); + CHECK_AND_ASSERT_THROW_MES(m_ct.alphas.size() == input_size, "Invalid vector size"); + CHECK_AND_ASSERT_THROW_MES(m_ct.spend_encs.size() == input_size, "Invalid vector size"); + CHECK_AND_ASSERT_THROW_MES(m_ct.tx_data.sources.size() == input_size, "Invalid vector size"); + + tools::apply_permutation(m_ct.source_permutation, [&](size_t i0, size_t i1){ + std::swap(m_ct.tx.vin[i0], m_ct.tx.vin[i1]); + std::swap(m_ct.tx_in_hmacs[i0], m_ct.tx_in_hmacs[i1]); + std::swap(m_ct.pseudo_outs[i0], m_ct.pseudo_outs[i1]); + std::swap(m_ct.pseudo_outs_hmac[i0], m_ct.pseudo_outs_hmac[i1]); + std::swap(m_ct.alphas[i0], m_ct.alphas[i1]); + std::swap(m_ct.spend_encs[i0], m_ct.spend_encs[i1]); + std::swap(m_ct.tx_data.sources[i0], m_ct.tx_data.sources[i1]); + }); + } + + std::shared_ptr Signer::step_permutation(){ + sort_ki(); + + if (in_memory()){ + return nullptr; + } + + auto res = std::make_shared(); + assign_to_repeatable(res->mutable_perm(), m_ct.source_permutation.begin(), m_ct.source_permutation.end()); + + return res; + } + + void Signer::step_permutation_ack(std::shared_ptr ack){ + if (in_memory()){ + return; + } + } + + std::shared_ptr Signer::step_set_vini_input(size_t idx){ + if (in_memory()){ + return nullptr; + } + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_data.sources.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx.vin.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_in_hmacs.size(), "Invalid transaction index"); + + m_ct.cur_input_idx = idx; + auto tx = m_ct.tx_data; + auto res = std::make_shared(); + auto & vini = m_ct.tx.vin[idx]; + translate_src_entry(res->mutable_src_entr(), &(tx.sources[idx])); + res->set_vini(cryptonote::t_serializable_object_to_blob(vini)); + res->set_vini_hmac(m_ct.tx_in_hmacs[idx]); + if (!in_memory()) { + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.pseudo_outs.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.pseudo_outs_hmac.size(), "Invalid transaction index"); + res->set_pseudo_out(m_ct.pseudo_outs[idx]); + res->set_pseudo_out_hmac(m_ct.pseudo_outs_hmac[idx]); + } + + return res; + } + + void Signer::step_set_vini_input_ack(std::shared_ptr ack){ + if (in_memory()){ + return; + } + } + + std::shared_ptr Signer::step_all_inputs_set(){ + return std::make_shared(); + } + + void Signer::step_all_inputs_set_ack(std::shared_ptr ack){ + if (is_offloading()){ + // If offloading, expect rsig configuration. + if (!ack->has_rsig_data()){ + throw exc::ProtocolException("Rsig offloading requires rsig param"); + } + + auto & rsig_data = ack->rsig_data(); + if (!rsig_data.has_mask()){ + throw exc::ProtocolException("Gamma masks not present in offloaded version"); + } + + auto & mask = rsig_data.mask(); + if (mask.size() != 32 * num_outputs()){ + throw exc::ProtocolException("Invalid number of gamma masks"); + } + + m_ct.rsig_gamma.reserve(num_outputs()); + for(size_t c=0; c < num_outputs(); ++c){ + rct::key cmask{}; + memcpy(cmask.bytes, mask.data() + c * 32, 32); + m_ct.rsig_gamma.emplace_back(cmask); + } + } + } + + std::shared_ptr Signer::step_set_output(size_t idx){ + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_data.splitted_dsts.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_out_entr_hmacs.size(), "Invalid transaction index"); + + m_ct.cur_output_idx = idx; + m_ct.cur_output_in_batch_idx += 1; // assumes sequential call to step_set_output() + + auto res = std::make_shared(); + auto & cur_dst = m_ct.tx_data.splitted_dsts[idx]; + translate_dst_entry(res->mutable_dst_entr(), &cur_dst); + res->set_dst_entr_hmac(m_ct.tx_out_entr_hmacs[idx]); + + // Range sig offloading to the host + if (!is_offloading()) { + return res; + } + + CHECK_AND_ASSERT_THROW_MES(m_ct.cur_batch_idx < m_ct.grouping_vct.size(), "Invalid batch index"); + if (m_ct.grouping_vct[m_ct.cur_batch_idx] > m_ct.cur_output_in_batch_idx) { + return res; + } + + auto rsig_data = res->mutable_rsig_data(); + auto batch_size = m_ct.grouping_vct[m_ct.cur_batch_idx]; + + if (!is_req_bulletproof()){ + if (batch_size > 1){ + throw std::invalid_argument("Borromean cannot batch outputs"); + } + + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.rsig_gamma.size(), "Invalid gamma index"); + rct::key C{}, mask = m_ct.rsig_gamma[idx]; + auto genRsig = rct::proveRange(C, mask, cur_dst.amount); // TODO: rsig with given mask + auto serRsig = cn_serialize(genRsig); + m_ct.tx_out_rsigs.emplace_back(genRsig); + rsig_data->set_rsig(serRsig); + + } else { + std::vector amounts; + rct::keyV masks; + CHECK_AND_ASSERT_THROW_MES(idx + 1 >= batch_size, "Invalid index for batching"); + + for(size_t i = 0; i < batch_size; ++i){ + const size_t bidx = 1 + idx - batch_size + i; + CHECK_AND_ASSERT_THROW_MES(bidx < m_ct.tx_data.splitted_dsts.size(), "Invalid gamma index"); + CHECK_AND_ASSERT_THROW_MES(bidx < m_ct.rsig_gamma.size(), "Invalid gamma index"); + + amounts.push_back(m_ct.tx_data.splitted_dsts[bidx].amount); + masks.push_back(m_ct.rsig_gamma[bidx]); + } + + auto bp = bulletproof_PROVE(amounts, masks); + auto serRsig = cn_serialize(bp); + m_ct.tx_out_rsigs.emplace_back(bp); + rsig_data->set_rsig(serRsig); + } + + return res; + } + + void Signer::step_set_output_ack(std::shared_ptr ack){ + cryptonote::tx_out tx_out; + rct::rangeSig range_sig{}; + rct::Bulletproof bproof{}; + rct::ctkey out_pk{}; + rct::ecdhTuple ecdh{}; + + bool has_rsig = false; + std::string rsig_buff; + + if (ack->has_rsig_data()){ + auto & rsig_data = ack->rsig_data(); + + if (rsig_data.has_rsig() && !rsig_data.rsig().empty()){ + has_rsig = true; + rsig_buff = rsig_data.rsig(); + + } else if (rsig_data.rsig_parts_size() > 0){ + has_rsig = true; + for (const auto &it : rsig_data.rsig_parts()) { + rsig_buff += it; + } + } + } + + if (!cn_deserialize(ack->tx_out(), tx_out)){ + throw exc::ProtocolException("Cannot deserialize vout[i]"); + } + + if (!cn_deserialize(ack->out_pk(), out_pk)){ + throw exc::ProtocolException("Cannot deserialize out_pk"); + } + + if (!cn_deserialize(ack->ecdh_info(), ecdh)){ + throw exc::ProtocolException("Cannot deserialize ecdhtuple"); + } + + if (has_rsig && !is_req_bulletproof() && !cn_deserialize(rsig_buff, range_sig)){ + throw exc::ProtocolException("Cannot deserialize rangesig"); + } + + if (has_rsig && is_req_bulletproof() && !cn_deserialize(rsig_buff, bproof)){ + throw exc::ProtocolException("Cannot deserialize bulletproof rangesig"); + } + + m_ct.tx.vout.emplace_back(tx_out); + m_ct.tx_out_hmacs.push_back(ack->vouti_hmac()); + m_ct.tx_out_pk.emplace_back(out_pk); + m_ct.tx_out_ecdh.emplace_back(ecdh); + + if (!has_rsig){ + return; + } + + if (is_req_bulletproof()){ + CHECK_AND_ASSERT_THROW_MES(m_ct.cur_batch_idx < m_ct.grouping_vct.size(), "Invalid batch index"); + auto batch_size = m_ct.grouping_vct[m_ct.cur_batch_idx]; + for (size_t i = 0; i < batch_size; ++i){ + const size_t bidx = 1 + m_ct.cur_output_idx - batch_size + i; + CHECK_AND_ASSERT_THROW_MES(bidx < m_ct.tx_out_pk.size(), "Invalid out index"); + + rct::key commitment = m_ct.tx_out_pk[bidx].mask; + commitment = rct::scalarmultKey(commitment, rct::INV_EIGHT); + bproof.V.push_back(commitment); + } + + m_ct.tx_out_rsigs.emplace_back(bproof); + if (!rct::bulletproof_VERIFY(boost::get(m_ct.tx_out_rsigs.back()))) { + throw exc::ProtocolException("Returned range signature is invalid"); + } + + } else { + m_ct.tx_out_rsigs.emplace_back(range_sig); + + if (!rct::verRange(out_pk.mask, boost::get(m_ct.tx_out_rsigs.back()))) { + throw exc::ProtocolException("Returned range signature is invalid"); + } + } + + m_ct.cur_batch_idx += 1; + m_ct.cur_output_in_batch_idx = 0; + } + + std::shared_ptr Signer::step_all_outs_set(){ + return std::make_shared(); + } + + void Signer::step_all_outs_set_ack(std::shared_ptr ack, hw::device &hwdev){ + m_ct.rv = std::make_shared(); + m_ct.rv->txnFee = ack->rv().txn_fee(); + m_ct.rv->type = static_cast(ack->rv().rv_type()); + string_to_key(m_ct.rv->message, ack->rv().message()); + + // Extra copy + m_ct.tx.extra.clear(); + auto extra = ack->extra(); + auto extra_data = extra.data(); + m_ct.tx.extra.reserve(extra.size()); + for(size_t i = 0; i < extra.size(); ++i){ + m_ct.tx.extra.push_back(static_cast(extra_data[i])); + } + + ::crypto::hash tx_prefix_hash{}; + cryptonote::get_transaction_prefix_hash(m_ct.tx, tx_prefix_hash); + m_ct.tx_prefix_hash = key_to_string(tx_prefix_hash); + if (crypto_verify_32(reinterpret_cast(tx_prefix_hash.data), + reinterpret_cast(ack->tx_prefix_hash().data()))){ + throw exc::proto::SecurityException("Transaction prefix has does not match to the computed value"); + } + + // RctSig + auto num_sources = m_ct.tx_data.sources.size(); + if (is_simple() || is_req_bulletproof()){ + auto dst = &m_ct.rv->pseudoOuts; + if (is_bulletproof()){ + dst = &m_ct.rv->p.pseudoOuts; + } + + dst->clear(); + for (const auto &pseudo_out : m_ct.pseudo_outs) { + dst->emplace_back(); + string_to_key(dst->back(), pseudo_out); + } + + m_ct.rv->mixRing.resize(num_sources); + } else { + m_ct.rv->mixRing.resize(m_ct.tsx_data.mixin()); + m_ct.rv->mixRing[0].resize(num_sources); + } + + CHECK_AND_ASSERT_THROW_MES(m_ct.tx_out_pk.size() == m_ct.tx_out_ecdh.size(), "Invalid vector sizes"); + for(size_t i = 0; i < m_ct.tx_out_ecdh.size(); ++i){ + m_ct.rv->outPk.push_back(m_ct.tx_out_pk[i]); + m_ct.rv->ecdhInfo.push_back(m_ct.tx_out_ecdh[i]); + } + + for(size_t i = 0; i < m_ct.tx_out_rsigs.size(); ++i){ + if (is_bulletproof()){ + m_ct.rv->p.bulletproofs.push_back(boost::get(m_ct.tx_out_rsigs[i])); + } else { + m_ct.rv->p.rangeSigs.push_back(boost::get(m_ct.tx_out_rsigs[i])); + } + } + + rct::key hash_computed = rct::get_pre_mlsag_hash(*(m_ct.rv), hwdev); + auto & hash = ack->full_message_hash(); + + if (hash.size() != 32){ + throw exc::ProtocolException("Returned mlsag hash has invalid size"); + } + + if (crypto_verify_32(reinterpret_cast(hash_computed.bytes), + reinterpret_cast(hash.data()))){ + throw exc::proto::SecurityException("Computed MLSAG does not match"); + } + } + + std::shared_ptr Signer::step_sign_input(size_t idx){ + m_ct.cur_input_idx = idx; + + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_data.sources.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx.vin.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.tx_in_hmacs.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.alphas.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.spend_encs.size(), "Invalid transaction index"); + + auto res = std::make_shared(); + translate_src_entry(res->mutable_src_entr(), &(m_ct.tx_data.sources[idx])); + res->set_vini(cryptonote::t_serializable_object_to_blob(m_ct.tx.vin[idx])); + res->set_vini_hmac(m_ct.tx_in_hmacs[idx]); + res->set_pseudo_out_alpha(m_ct.alphas[idx]); + res->set_spend_key(m_ct.spend_encs[idx]); + if (!in_memory()){ + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.pseudo_outs.size(), "Invalid transaction index"); + CHECK_AND_ASSERT_THROW_MES(idx < m_ct.pseudo_outs_hmac.size(), "Invalid transaction index"); + res->set_pseudo_out(m_ct.pseudo_outs[idx]); + res->set_pseudo_out_hmac(m_ct.pseudo_outs_hmac[idx]); + } + return res; + } + + void Signer::step_sign_input_ack(std::shared_ptr ack){ + rct::mgSig mg; + if (!cn_deserialize(ack->signature(), mg)){ + throw exc::ProtocolException("Cannot deserialize mg[i]"); + } + + m_ct.rv->p.MGs.push_back(mg); + } + + std::shared_ptr Signer::step_final(){ + m_ct.tx.rct_signatures = *(m_ct.rv); + return std::make_shared(); + } + + void Signer::step_final_ack(std::shared_ptr ack){ + if (m_multisig){ + auto & cout_key = ack->cout_key(); + for(auto & cur : m_ct.couts){ + if (cur.size() != 12 + 32){ + throw std::invalid_argument("Encrypted cout has invalid length"); + } + + char buff[32]; + auto data = cur.data(); + + crypto::chacha::decrypt(data + 12, 32, reinterpret_cast(cout_key.data()), reinterpret_cast(data), buff); + m_ct.couts_dec.emplace_back(buff, 32); + } + } + + m_ct.enc_salt1 = ack->salt(); + m_ct.enc_salt2 = ack->rand_mult(); + m_ct.enc_keys = ack->tx_enc_keys(); + } + + std::string Signer::store_tx_aux_info(){ + rapidjson::StringBuffer sb; + rapidjson::Writer writer(sb); + + rapidjson::Document json; + json.SetObject(); + + rapidjson::Value valueS(rapidjson::kStringType); + rapidjson::Value valueI(rapidjson::kNumberType); + + valueI.SetInt(1); + json.AddMember("version", valueI, json.GetAllocator()); + + valueS.SetString(m_ct.enc_salt1.c_str(), m_ct.enc_salt1.size()); + json.AddMember("salt1", valueS, json.GetAllocator()); + + valueS.SetString(m_ct.enc_salt2.c_str(), m_ct.enc_salt2.size()); + json.AddMember("salt2", valueS, json.GetAllocator()); + + valueS.SetString(m_ct.enc_keys.c_str(), m_ct.enc_keys.size()); + json.AddMember("enc_keys", valueS, json.GetAllocator()); + + json.Accept(writer); + return sb.GetString(); + } + + +} +} +} +} diff --git a/src/device_trezor/trezor/protocol.hpp b/src/device_trezor/trezor/protocol.hpp new file mode 100644 index 000000000..99211efed --- /dev/null +++ b/src/device_trezor/trezor/protocol.hpp @@ -0,0 +1,300 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_PROTOCOL_H +#define MONERO_PROTOCOL_H + +#include "trezor_defs.hpp" +#include "device/device_cold.hpp" +#include "messages_map.hpp" +#include "transport.hpp" +#include "wallet/wallet2.h" + +namespace hw{ +namespace trezor{ +namespace protocol{ + + std::string key_to_string(const ::crypto::ec_point & key); + std::string key_to_string(const ::crypto::ec_scalar & key); + std::string key_to_string(const ::crypto::hash & key); + std::string key_to_string(const ::rct::key & key); + + void string_to_key(::crypto::ec_scalar & key, const std::string & str); + void string_to_key(::crypto::ec_point & key, const std::string & str); + void string_to_key(::rct::key & key, const std::string & str); + + template + void assign_to_repeatable(::google::protobuf::RepeatedField * dst, const InputIterator begin, const InputIterator end){ + for (InputIterator it = begin; it != end; it++) { + auto s = dst->Add(); + *s = *it; + } + } + + template + void assign_from_repeatable(std::vector * dst, const InputIterator begin, const InputIterator end){ + for (InputIterator it = begin; it != end; it++) { + dst->push_back(*it); + } + }; + + template + bool cn_deserialize(const void * buff, size_t len, T & dst){ + std::stringstream ss; + ss.write(static_cast(buff), len); //ss << tx_blob; + binary_archive ba(ss); + bool r = ::serialization::serialize(ba, dst); + return r; + } + + template + bool cn_deserialize(const std::string & str, T & dst){ + return cn_deserialize(str.data(), str.size(), dst); + } + + template + std::string cn_serialize(T & obj){ + std::ostringstream oss; + binary_archive oar(oss); + bool success = ::serialization::serialize(oar, obj); + if (!success){ + throw exc::EncodingException("Could not CN serialize given object"); + } + return oss.str(); + } + +// Crypto / encryption +namespace crypto { +namespace chacha { + + /** + * Chacha20Poly1305 decryption with tag verification. RFC 7539. + */ + void decrypt(const void* ciphertext, size_t length, const uint8_t* key, const uint8_t* iv, char* plaintext); + +} +} + + +// Cold Key image sync +namespace ki { + + using MoneroTransferDetails = messages::monero::MoneroKeyImageSyncStepRequest_MoneroTransferDetails; + using MoneroSubAddressIndicesList = messages::monero::MoneroKeyImageExportInitRequest_MoneroSubAddressIndicesList; + using MoneroExportedKeyImage = messages::monero::MoneroKeyImageSyncStepAck_MoneroExportedKeyImage; + using exported_key_image = hw::device_cold::exported_key_image; + + /** + * Converts transfer details to the MoneroTransferDetails required for KI sync + */ + bool key_image_data(wallet_shim * wallet, + const std::vector & transfers, + std::vector & res); + + /** + * Computes a hash over MoneroTransferDetails. Commitment used in the KI sync. + */ + std::string compute_hash(const MoneroTransferDetails & rr); + + /** + * Generates KI sync request with commitments computed. + */ + void generate_commitment(std::vector & mtds, + const std::vector & transfers, + std::shared_ptr & req); + +} + +// Cold transaction signing +namespace tx { + using TsxData = messages::monero::MoneroTransactionInitRequest_MoneroTransactionData; + using MoneroTransactionDestinationEntry = messages::monero::MoneroTransactionDestinationEntry; + using MoneroAccountPublicAddress = messages::monero::MoneroTransactionDestinationEntry_MoneroAccountPublicAddress; + using MoneroTransactionSourceEntry = messages::monero::MoneroTransactionSourceEntry; + using MoneroMultisigKLRki = messages::monero::MoneroTransactionSourceEntry_MoneroMultisigKLRki; + using MoneroOutputEntry = messages::monero::MoneroTransactionSourceEntry_MoneroOutputEntry; + using MoneroRctKey = messages::monero::MoneroTransactionSourceEntry_MoneroOutputEntry_MoneroRctKeyPublic; + using MoneroRsigData = messages::monero::MoneroTransactionRsigData; + + using tx_construction_data = tools::wallet2::tx_construction_data; + using unsigned_tx_set = tools::wallet2::unsigned_tx_set; + + void translate_address(MoneroAccountPublicAddress * dst, const cryptonote::account_public_address * src); + void translate_dst_entry(MoneroTransactionDestinationEntry * dst, const cryptonote::tx_destination_entry * src); + void translate_src_entry(MoneroTransactionSourceEntry * dst, const cryptonote::tx_source_entry * src); + void translate_klrki(MoneroMultisigKLRki * dst, const rct::multisig_kLRki * src); + void translate_rct_key(MoneroRctKey * dst, const rct::ctkey * src); + std::string hash_addr(const MoneroAccountPublicAddress * addr, boost::optional amount = boost::none, boost::optional is_subaddr = boost::none); + std::string hash_addr(const std::string & spend_key, const std::string & view_key, boost::optional amount = boost::none, boost::optional is_subaddr = boost::none); + std::string hash_addr(const ::crypto::public_key * spend_key, const ::crypto::public_key * view_key, boost::optional amount = boost::none, boost::optional is_subaddr = boost::none); + + typedef boost::variant rsig_v; + + /** + * Transaction signer state holder. + */ + class TData { + public: + TsxData tsx_data; + tx_construction_data tx_data; + cryptonote::transaction tx; + bool in_memory; + unsigned rsig_type; + std::vector grouping_vct; + std::shared_ptr rsig_param; + size_t cur_input_idx; + size_t cur_output_idx; + size_t cur_batch_idx; + size_t cur_output_in_batch_idx; + + std::vector tx_in_hmacs; + std::vector tx_out_entr_hmacs; + std::vector tx_out_hmacs; + std::vector tx_out_rsigs; + std::vector tx_out_pk; + std::vector tx_out_ecdh; + std::vector source_permutation; + std::vector alphas; + std::vector spend_encs; + std::vector pseudo_outs; + std::vector pseudo_outs_hmac; + std::vector couts; + std::vector couts_dec; + std::vector rsig_gamma; + std::string tx_prefix_hash; + std::string enc_salt1; + std::string enc_salt2; + std::string enc_keys; + + std::shared_ptr rv; + + TData(); + }; + + class Signer { + private: + TData m_ct; + wallet_shim * m_wallet2; + + size_t m_tx_idx; + const unsigned_tx_set * m_unsigned_tx; + hw::tx_aux_data * m_aux_data; + + bool m_multisig; + + const tx_construction_data & cur_tx(){ + CHECK_AND_ASSERT_THROW_MES(m_tx_idx < m_unsigned_tx->txes.size(), "Invalid transaction index"); + return m_unsigned_tx->txes[m_tx_idx]; + } + + void extract_payment_id(); + void compute_integrated_indices(TsxData * tsx_data); + + public: + Signer(wallet_shim * wallet2, const unsigned_tx_set * unsigned_tx, size_t tx_idx = 0, hw::tx_aux_data * aux_data = nullptr); + + std::shared_ptr step_init(); + void step_init_ack(std::shared_ptr ack); + + std::shared_ptr step_set_input(size_t idx); + void step_set_input_ack(std::shared_ptr ack); + + void sort_ki(); + std::shared_ptr step_permutation(); + void step_permutation_ack(std::shared_ptr ack); + + std::shared_ptr step_set_vini_input(size_t idx); + void step_set_vini_input_ack(std::shared_ptr ack); + + std::shared_ptr step_all_inputs_set(); + void step_all_inputs_set_ack(std::shared_ptr ack); + + std::shared_ptr step_set_output(size_t idx); + void step_set_output_ack(std::shared_ptr ack); + + std::shared_ptr step_all_outs_set(); + void step_all_outs_set_ack(std::shared_ptr ack, hw::device &hwdev); + + std::shared_ptr step_sign_input(size_t idx); + void step_sign_input_ack(std::shared_ptr ack); + + std::shared_ptr step_final(); + void step_final_ack(std::shared_ptr ack); + + std::string store_tx_aux_info(); + + bool in_memory() const { + return m_ct.in_memory; + } + + bool is_simple() const { + if (!m_ct.rv){ + throw std::invalid_argument("RV not initialized"); + } + auto tp = m_ct.rv->type; + return tp == rct::RCTTypeSimple; + } + + bool is_req_bulletproof() const { + return m_ct.tx_data.use_bulletproofs; + } + + bool is_bulletproof() const { + if (!m_ct.rv){ + throw std::invalid_argument("RV not initialized"); + } + auto tp = m_ct.rv->type; + return tp == rct::RCTTypeBulletproof; + } + + bool is_offloading() const { + return m_ct.rsig_param && m_ct.rsig_param->offload_type() != 0; + } + + size_t num_outputs() const { + return m_ct.tx_data.splitted_dsts.size(); + } + + size_t num_inputs() const { + return m_ct.tx_data.sources.size(); + } + + const TData & tdata() const { + return m_ct; + } + }; + +} + +} +} +} + + +#endif //MONERO_PROTOCOL_H diff --git a/src/device_trezor/trezor/tools/README.md b/src/device_trezor/trezor/tools/README.md new file mode 100644 index 000000000..91a8fb3f0 --- /dev/null +++ b/src/device_trezor/trezor/tools/README.md @@ -0,0 +1,36 @@ +# Trezor + +## Messages rebuild + +Install `protoc` for your distribution. + +- `protobuf-compiler` +- `libprotobuf-dev` +- `libprotoc-dev` +- `python-protobuf` + +Python 3 is required. If you don't have python 3 quite an easy way is +to use [pyenv]. + +It is also advised to create own python virtual environment so dependencies +are installed in this project-related virtual environment. + +```bash +python -m venv / +``` + +Make sure your python has `protobuf` package installed + +```bash +pip install protobuf +``` + +Regenerate messages: + +``` +./venv/bin/python3 src/device_trezor/trezor/tools/build_protob.py +``` + +The messages regeneration is done also automatically via cmake. + +[pyenv]: https://github.com/pyenv/pyenv diff --git a/src/device_trezor/trezor/tools/build_protob.py b/src/device_trezor/trezor/tools/build_protob.py new file mode 100644 index 000000000..2611f3296 --- /dev/null +++ b/src/device_trezor/trezor/tools/build_protob.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import os +import subprocess +import sys + +CWD = os.path.dirname(os.path.realpath(__file__)) +ROOT_DIR = os.path.abspath(os.path.join(CWD, "..", "..", "..", "..")) +TREZOR_COMMON = os.path.join(ROOT_DIR, "external", "trezor-common") +TREZOR_MESSAGES = os.path.join(CWD, "..", "messages") + +# check for existence of the submodule directory +common_defs = os.path.join(TREZOR_COMMON, "defs") +if not os.path.exists(common_defs): + raise ValueError( + "trezor-common submodule seems to be missing.\n" + + 'Use "git submodule update --init --recursive" to retrieve it.' + ) + +# regenerate messages +try: + selected = [ + "messages.proto", + "messages-common.proto", + "messages-management.proto", + "messages-monero.proto", + ] + proto_srcs = [os.path.join(TREZOR_COMMON, "protob", x) for x in selected] + exec_args = [ + sys.executable, + os.path.join(CWD, "pb2cpp.py"), + "-o", + TREZOR_MESSAGES, + ] + proto_srcs + + subprocess.check_call(exec_args) + +except Exception as e: + raise diff --git a/src/device_trezor/trezor/tools/pb2cpp.py b/src/device_trezor/trezor/tools/pb2cpp.py new file mode 100644 index 000000000..eaa8a90ed --- /dev/null +++ b/src/device_trezor/trezor/tools/pb2cpp.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python3 +# Converts Google's protobuf python definitions of TREZOR wire messages +# to plain-python objects as used in TREZOR Core and python-trezor + +import argparse +import logging +import os +import re +import shutil +import subprocess +import sys +import glob +import tempfile +import hashlib + + +AUTO_HEADER = "# Automatically generated by pb2cpp\n" + +# Fixing GCC7 compilation error +UNDEF_STATEMENT = """ +#ifdef minor +#undef minor +#endif +""" + + +def which(pgm): + path = os.getenv('PATH') + for p in path.split(os.path.pathsep): + p = os.path.join(p, pgm) + if os.path.exists(p) and os.access(p, os.X_OK): + return p + + +PROTOC = which("protoc") +if not PROTOC: + print("protoc command not found") + sys.exit(1) + +PROTOC_PREFIX = os.path.dirname(os.path.dirname(PROTOC)) +PROTOC_INCLUDE = os.path.join(PROTOC_PREFIX, "include") + + +def namespace_file(fpath, package): + """Adds / replaces package name. Simple regex parsing, may use https://github.com/ph4r05/plyprotobuf later""" + with open(fpath) as fh: + fdata = fh.read() + + re_syntax = re.compile(r"^syntax\s*=") + re_package = re.compile(r"^package\s+([^;]+?)\s*;\s*$") + lines = fdata.split("\n") + + line_syntax = None + line_package = None + for idx, line in enumerate(lines): + if line_syntax is None and re_syntax.match(line): + line_syntax = idx + if line_package is None and re_package.match(line): + line_package = idx + + if package is None: + if line_package is None: + return + else: + lines.pop(line_package) + + else: + new_package = "package %s;" % package + if line_package is None: + lines.insert(line_syntax + 1 if line_syntax is not None else 0, new_package) + else: + lines[line_package] = new_package + + new_fdat = "\n".join(lines) + with open(fpath, "w+") as fh: + fh.write(new_fdat) + return new_fdat + + +def protoc(files, out_dir, additional_includes=(), package=None, force=False): + """Compile code with protoc and return the data.""" + + include_dirs = set() + include_dirs.add(PROTOC_INCLUDE) + include_dirs.update(additional_includes) + + with tempfile.TemporaryDirectory() as tmpdir_protob, tempfile.TemporaryDirectory() as tmpdir_out: + include_dirs.add(tmpdir_protob) + + new_files = [] + for file in files: + bname = os.path.basename(file) + tmp_file = os.path.join(tmpdir_protob, bname) + + shutil.copy(file, tmp_file) + if package is not None: + namespace_file(tmp_file, package) + new_files.append(tmp_file) + + protoc_includes = ["-I" + dir for dir in include_dirs if dir] + + exec_args = ( + [ + PROTOC, + "--cpp_out", + tmpdir_out, + ] + + protoc_includes + + new_files + ) + + subprocess.check_call(exec_args) + + # Fixing gcc compilation and clashes with "minor" field name + add_undef(tmpdir_out) + + # Scan output dir, check file differences + update_message_files(tmpdir_out, out_dir, force) + + +def update_message_files(tmpdir_out, out_dir, force=False): + files = glob.glob(os.path.join(tmpdir_out, '*.pb.*')) + for fname in files: + bname = os.path.basename(fname) + dest_file = os.path.join(out_dir, bname) + if not force and os.path.exists(dest_file): + data = open(fname, 'rb').read() + data_hash = hashlib.sha3_256(data).digest() + data_dest = open(dest_file, 'rb').read() + data_dest_hash = hashlib.sha3_256(data_dest).digest() + if data_hash == data_dest_hash: + continue + + shutil.copy(fname, dest_file) + + +def add_undef(out_dir): + files = glob.glob(os.path.join(out_dir, '*.pb.*')) + for fname in files: + with open(fname) as fh: + lines = fh.readlines() + + idx_insertion = None + for idx in range(len(lines)): + if '@@protoc_insertion_point(includes)' in lines[idx]: + idx_insertion = idx + break + + if idx_insertion is None: + pass + + lines.insert(idx_insertion + 1, UNDEF_STATEMENT) + with open(fname, 'w') as fh: + fh.write("".join(lines)) + + +def strip_leader(s, prefix): + """Remove given prefix from underscored name.""" + leader = prefix + "_" + if s.startswith(leader): + return s[len(leader) :] + else: + return s + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + + parser = argparse.ArgumentParser() + # fmt: off + parser.add_argument("proto", nargs="+", help="Protobuf definition files") + parser.add_argument("-o", "--out-dir", help="Directory for generated source code") + parser.add_argument("-n", "--namespace", default=None, help="Message namespace") + parser.add_argument("-I", "--protoc-include", action="append", help="protoc include path") + parser.add_argument("-P", "--protobuf-module", default="protobuf", help="Name of protobuf module") + parser.add_argument("-f", "--force", default=False, help="Overwrite existing files") + # fmt: on + args = parser.parse_args() + + protoc_includes = args.protoc_include or (os.environ.get("PROTOC_INCLUDE"),) + + protoc( + args.proto, args.out_dir, protoc_includes, package=args.namespace, force=args.force + ) + + diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp new file mode 100644 index 000000000..fc86177e1 --- /dev/null +++ b/src/device_trezor/trezor/transport.cpp @@ -0,0 +1,651 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#include +#include +#include +#include +#include "transport.hpp" +#include "messages/messages-common.pb.h" + +using namespace std; +using json = rapidjson::Document; + + +namespace hw{ +namespace trezor{ + + bool t_serialize(const std::string & in, std::string & out){ + out = in; + return true; + } + + bool t_serialize(const json_val & in, std::string & out){ + rapidjson::StringBuffer sb; + rapidjson::Writer writer(sb); + in.Accept(writer); + out = sb.GetString(); + return true; + } + + std::string t_serialize(const json_val & in){ + std::string ret; + t_serialize(in, ret); + return ret; + } + + bool t_deserialize(const std::string & in, std::string & out){ + out = in; + return true; + } + + bool t_deserialize(const std::string & in, json & out){ + if (out.Parse(in.c_str()).HasParseError()) { + throw exc::CommunicationException("JSON parse error"); + } + return true; + } + + static std::string json_get_string(const rapidjson::Value & in){ + return std::string(in.GetString()); + } + + // + // Helpers + // + +#define PROTO_HEADER_SIZE 6 + + static size_t message_size(const google::protobuf::Message &req){ + return static_cast(req.ByteSize()); + } + + static size_t serialize_message_buffer_size(size_t msg_size) { + return PROTO_HEADER_SIZE + msg_size; // tag 2B + len 4B + } + + static void serialize_message_header(void * buff, uint16_t tag, uint32_t len){ + uint16_t wire_tag = boost::endian::native_to_big(static_cast(tag)); + uint32_t wire_len = boost::endian::native_to_big(static_cast(len)); + memcpy(buff, (void *) &wire_tag, 2); + memcpy((uint8_t*)buff + 2, (void *) &wire_len, 4); + } + + static void deserialize_message_header(const void * buff, uint16_t & tag, uint32_t & len){ + uint16_t wire_tag; + uint32_t wire_len; + memcpy(&wire_tag, buff, 2); + memcpy(&wire_len, (uint8_t*)buff + 2, 4); + + tag = boost::endian::big_to_native(wire_tag); + len = boost::endian::big_to_native(wire_len); + } + + static void serialize_message(const google::protobuf::Message &req, size_t msg_size, uint8_t * buff, size_t buff_size) { + auto msg_wire_num = MessageMapper::get_message_wire_number(req); + const auto req_buffer_size = serialize_message_buffer_size(msg_size); + if (req_buffer_size > buff_size){ + throw std::invalid_argument("Buffer too small"); + } + + serialize_message_header(buff, msg_wire_num, msg_size); + if (!req.SerializeToArray(buff + 6, msg_size)){ + throw exc::EncodingException("Message serialization error"); + } + } + + // + // Communication protocol + // + +#define REPLEN 64 + + void ProtocolV1::write(Transport & transport, const google::protobuf::Message & req){ + const auto msg_size = message_size(req); + const auto buff_size = serialize_message_buffer_size(msg_size) + 2; + + std::unique_ptr req_buff(new uint8_t[buff_size]); + uint8_t * req_buff_raw = req_buff.get(); + req_buff_raw[0] = '#'; + req_buff_raw[1] = '#'; + + serialize_message(req, msg_size, req_buff_raw + 2, buff_size - 2); + + size_t offset = 0; + uint8_t chunk_buff[REPLEN]; + + // Chunk by chunk upload + while(offset < buff_size){ + auto to_copy = std::min((size_t)(buff_size - offset), (size_t)(REPLEN - 1)); + + chunk_buff[0] = '?'; + memcpy(chunk_buff + 1, req_buff_raw + offset, to_copy); + + // Pad with zeros + if (to_copy < REPLEN - 1){ + memset(chunk_buff + 1 + to_copy, 0, REPLEN - 1 - to_copy); + } + + transport.write_chunk(chunk_buff, REPLEN); + offset += REPLEN - 1; + } + } + + void ProtocolV1::read(Transport & transport, std::shared_ptr & msg, messages::MessageType * msg_type){ + char chunk[REPLEN]; + + // Initial chunk read + size_t nread = transport.read_chunk(chunk, REPLEN); + if (nread != REPLEN){ + throw exc::CommunicationException("Read chunk has invalid size"); + } + + if (strncmp(chunk, "?##", 3) != 0){ + throw exc::CommunicationException("Malformed chunk"); + } + + uint16_t tag; + uint32_t len; + nread -= 3 + 6; + deserialize_message_header(chunk + 3, tag, len); + + std::string data_acc(chunk + 3 + 6, nread); + data_acc.reserve(len); + + while(nread < len){ + const size_t cur = transport.read_chunk(chunk, REPLEN); + if (chunk[0] != '?'){ + throw exc::CommunicationException("Chunk malformed"); + } + + data_acc.append(chunk + 1, cur - 1); + nread += cur - 1; + } + + if (msg_type){ + *msg_type = static_cast(tag); + } + + if (nread < len){ + throw exc::CommunicationException("Response incomplete"); + } + + std::shared_ptr msg_wrap(MessageMapper::get_message(tag)); + if (!msg_wrap->ParseFromArray(data_acc.c_str(), len)){ + throw exc::CommunicationException("Message could not be parsed"); + } + + msg = msg_wrap; + } + + // + // Bridge transport + // + + const char * BridgeTransport::PATH_PREFIX = "bridge:"; + + std::string BridgeTransport::get_path() const { + if (!m_device_path){ + return ""; + } + + std::string path(PATH_PREFIX); + return path + m_device_path.get(); + } + + void BridgeTransport::enumerate(t_transport_vect & res) { + json bridge_res; + std::string req; + + bool req_status = invoke_bridge_http("/enumerate", req, bridge_res, m_http_client); + if (!req_status){ + throw exc::CommunicationException("Bridge enumeration failed"); + } + + for(rapidjson::Value::ConstValueIterator itr = bridge_res.Begin(); itr != bridge_res.End(); ++itr){ + auto element = itr->GetObject(); + auto t = std::make_shared(boost::make_optional(json_get_string(element["path"]))); + t->m_device_info.emplace(); + t->m_device_info->CopyFrom(*itr, t->m_device_info->GetAllocator()); + res.push_back(t); + } + } + + void BridgeTransport::open() { + if (!m_device_path){ + throw exc::CommunicationException("Coud not open, empty device path"); + } + + std::string uri = "/acquire/" + m_device_path.get() + "/null"; + std::string req; + json bridge_res; + bool req_status = invoke_bridge_http(uri, req, bridge_res, m_http_client); + if (!req_status){ + throw exc::CommunicationException("Failed to acquire device"); + } + + m_session = boost::make_optional(json_get_string(bridge_res["session"])); + } + + void BridgeTransport::close() { + if (!m_device_path || !m_session){ + throw exc::CommunicationException("Device not open"); + } + + std::string uri = "/release/" + m_session.get(); + std::string req; + json bridge_res; + bool req_status = invoke_bridge_http(uri, req, bridge_res, m_http_client); + if (!req_status){ + throw exc::CommunicationException("Failed to release device"); + } + + m_session = boost::none; + } + + void BridgeTransport::write(const google::protobuf::Message &req) { + m_response = boost::none; + + const auto msg_size = message_size(req); + const auto buff_size = serialize_message_buffer_size(msg_size); + + std::unique_ptr req_buff(new uint8_t[buff_size]); + uint8_t * req_buff_raw = req_buff.get(); + + serialize_message(req, msg_size, req_buff_raw, buff_size); + + std::string uri = "/call/" + m_session.get(); + std::string req_hex = epee::to_hex::string(epee::span(req_buff_raw, buff_size)); + std::string res_hex; + + bool req_status = invoke_bridge_http(uri, req_hex, res_hex, m_http_client); + if (!req_status){ + throw exc::CommunicationException("Call method failed"); + } + + m_response = res_hex; + } + + void BridgeTransport::read(std::shared_ptr & msg, messages::MessageType * msg_type) { + if (!m_response){ + throw exc::CommunicationException("Could not read, no response stored"); + } + + std::string bin_data; + if (!epee::string_tools::parse_hexstr_to_binbuff(m_response.get(), bin_data)){ + throw exc::CommunicationException("Response is not well hexcoded"); + } + + uint16_t msg_tag; + uint32_t msg_len; + deserialize_message_header(bin_data.c_str(), msg_tag, msg_len); + if (bin_data.size() != msg_len + 6){ + throw exc::CommunicationException("Response is not well hexcoded"); + } + + if (msg_type){ + *msg_type = static_cast(msg_tag); + } + + std::shared_ptr msg_wrap(MessageMapper::get_message(msg_tag)); + if (!msg_wrap->ParseFromArray(bin_data.c_str() + 6, msg_len)){ + throw exc::EncodingException("Response is not well hexcoded"); + } + msg = msg_wrap; + } + + const boost::optional & BridgeTransport::device_info() const { + return m_device_info; + } + + std::ostream& BridgeTransport::dump(std::ostream& o) const { + return o << "BridgeTransport"; + } + + // + // UdpTransport + // + const char * UdpTransport::PATH_PREFIX = "udp:"; + const char * UdpTransport::DEFAULT_HOST = "127.0.0.1"; + const int UdpTransport::DEFAULT_PORT = 21324; + + UdpTransport::UdpTransport(boost::optional device_path, + boost::optional> proto) : + m_io_service(), m_deadline(m_io_service) + { + m_device_port = DEFAULT_PORT; + if (device_path) { + const std::string device_str = device_path.get(); + auto delim = device_str.find(':'); + if (delim == std::string::npos) { + m_device_host = device_str; + } else { + m_device_host = device_str.substr(0, delim); + m_device_port = std::stoi(device_str.substr(delim + 1)); + } + } else { + m_device_host = DEFAULT_HOST; + } + + if (m_device_port <= 1024 || m_device_port > 65535){ + throw std::invalid_argument("Port number invalid"); + } + + if (m_device_host != "localhost" && m_device_host != DEFAULT_HOST){ + throw std::invalid_argument("Local endpoint allowed only"); + } + + m_proto = proto ? proto.get() : std::make_shared(); + } + + std::string UdpTransport::get_path() const { + std::string path(PATH_PREFIX); + return path + m_device_host + ":" + std::to_string(m_device_port); + } + + void UdpTransport::require_socket(){ + if (!m_socket){ + throw exc::NotConnectedException("Socket not connected"); + } + } + + bool UdpTransport::ping(){ + return ping_int(); + } + + bool UdpTransport::ping_int(boost::posix_time::time_duration timeout){ + require_socket(); + try { + std::string req = "PINGPING"; + char res[8]; + + m_socket->send_to(boost::asio::buffer(req.c_str(), req.size()), m_endpoint); + receive(res, 8, nullptr, false, timeout); + + return memcmp(res, "PONGPONG", 8) == 0; + + } catch(...){ + return false; + } + } + + void UdpTransport::enumerate(t_transport_vect & res) { + std::shared_ptr t = std::make_shared(); + bool t_works = false; + + try{ + t->open(); + t_works = t->ping(); + } catch(...) { + + } + t->close(); + if (t_works){ + res.push_back(t); + } + } + + void UdpTransport::open() { + udp::resolver resolver(m_io_service); + udp::resolver::query query(udp::v4(), m_device_host, std::to_string(m_device_port)); + m_endpoint = *resolver.resolve(query); + + m_socket.reset(new udp::socket(m_io_service)); + m_socket->open(udp::v4()); + + m_deadline.expires_at(boost::posix_time::pos_infin); + check_deadline(); + + m_proto->session_begin(*this); + } + + void UdpTransport::close() { + if (!m_socket){ + throw exc::CommunicationException("Socket is already closed"); + } + + m_proto->session_end(*this); + m_socket->close(); + m_socket = nullptr; + } + + void UdpTransport::write_chunk(const void * buff, size_t size){ + require_socket(); + + if (size != 64){ + throw exc::CommunicationException("Invalid chunk size"); + } + + auto written = m_socket->send_to(boost::asio::buffer(buff, size), m_endpoint); + if (size != written){ + throw exc::CommunicationException("Could not send the whole chunk"); + } + } + + size_t UdpTransport::read_chunk(void * buff, size_t size){ + require_socket(); + if (size < 64){ + throw std::invalid_argument("Buffer too small"); + } + + ssize_t len; + while(true) { + try { + boost::system::error_code ec; + len = receive(buff, size, &ec, true); + if (ec == boost::asio::error::operation_aborted) { + continue; + } else if (ec) { + throw exc::CommunicationException(std::string("Comm error: ") + ec.message()); + } + + if (len != 64) { + throw exc::CommunicationException("Invalid chunk size"); + } + + break; + + } catch(exc::CommunicationException const& e){ + throw; + } catch(std::exception const& e){ + MWARNING("Error reading chunk, reason: " << e.what()); + throw exc::CommunicationException(std::string("Chunk read error: ") + std::string(e.what())); + } + } + + return static_cast(len); + } + + ssize_t UdpTransport::receive(void * buff, size_t size, boost::system::error_code * error_code, bool no_throw, boost::posix_time::time_duration timeout){ + boost::system::error_code ec; + boost::asio::mutable_buffer buffer = boost::asio::buffer(buff, size); + + require_socket(); + + // Set a deadline for the asynchronous operation. + m_deadline.expires_from_now(timeout); + + // Set up the variables that receive the result of the asynchronous + // operation. The error code is set to would_block to signal that the + // operation is incomplete. Asio guarantees that its asynchronous + // operations will never fail with would_block, so any other value in + // ec indicates completion. + ec = boost::asio::error::would_block; + std::size_t length = 0; + + // Start the asynchronous operation itself. The handle_receive function + // used as a callback will update the ec and length variables. + m_socket->async_receive_from(boost::asio::buffer(buffer), m_endpoint, + boost::bind(&UdpTransport::handle_receive, _1, _2, &ec, &length)); + + // Block until the asynchronous operation has completed. + do { + m_io_service.run_one(); + } + while (ec == boost::asio::error::would_block); + + if (error_code){ + *error_code = ec; + } + + if (no_throw){ + return length; + } + + // Operation result + if (ec == boost::asio::error::operation_aborted){ + throw exc::TimeoutException(); + + } else if (ec) { + MWARNING("Reading from UDP socket failed: " << ec.message()); + throw exc::CommunicationException(); + + } + + return length; + } + + void UdpTransport::write(const google::protobuf::Message &req) { + m_proto->write(*this, req); + } + + void UdpTransport::read(std::shared_ptr & msg, messages::MessageType * msg_type) { + m_proto->read(*this, msg, msg_type); + } + + void UdpTransport::check_deadline(){ + if (!m_socket){ + return; // no active socket. + } + + // Check whether the deadline has passed. We compare the deadline against + // the current time since a new asynchronous operation may have moved the + // deadline before this actor had a chance to run. + if (m_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now()) + { + // The deadline has passed. The outstanding asynchronous operation needs + // to be cancelled so that the blocked receive() function will return. + // + // Please note that cancel() has portability issues on some versions of + // Microsoft Windows, and it may be necessary to use close() instead. + // Consult the documentation for cancel() for further information. + m_socket->cancel(); + + // There is no longer an active deadline. The expiry is set to positive + // infinity so that the actor takes no action until a new deadline is set. + m_deadline.expires_at(boost::posix_time::pos_infin); + } + + // Put the actor back to sleep. + m_deadline.async_wait(boost::bind(&UdpTransport::check_deadline, this)); + } + + void UdpTransport::handle_receive(const boost::system::error_code &ec, std::size_t length, + boost::system::error_code *out_ec, std::size_t *out_length) { + *out_ec = ec; + *out_length = length; + } + + std::ostream& UdpTransport::dump(std::ostream& o) const { + return o << "UdpTransport"; + } + + void enumerate(t_transport_vect & res){ + BridgeTransport bt; + bt.enumerate(res); + + hw::trezor::UdpTransport btu; + btu.enumerate(res); + } + + std::shared_ptr transport(const std::string & path){ + if (boost::starts_with(path, BridgeTransport::PATH_PREFIX)){ + return std::make_shared(path.substr(strlen(BridgeTransport::PATH_PREFIX))); + + } else if (boost::starts_with(path, UdpTransport::PATH_PREFIX)){ + return std::make_shared(path.substr(strlen(UdpTransport::PATH_PREFIX))); + + } else { + throw std::invalid_argument("Unknown Trezor device path: " + path); + + } + } + + void throw_failure_exception(const messages::common::Failure * failure) { + if (failure == nullptr){ + throw std::invalid_argument("Failure message cannot be null"); + } + + boost::optional message = failure->has_message() ? boost::make_optional(failure->message()) : boost::none; + boost::optional code = failure->has_code() ? boost::make_optional(static_cast(failure->code())) : boost::none; + if (!code){ + throw exc::proto::FailureException(code, message); + } + + auto ecode = failure->code(); + if (ecode == messages::common::Failure_FailureType_Failure_UnexpectedMessage){ + throw exc::proto::UnexpectedMessageException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_ActionCancelled){ + throw exc::proto::CancelledException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_PinExpected){ + throw exc::proto::PinExpectedException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_PinInvalid){ + throw exc::proto::InvalidPinException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_NotEnoughFunds){ + throw exc::proto::NotEnoughFundsException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_NotInitialized){ + throw exc::proto::NotInitializedException(code, message); + } else if (ecode == messages::common::Failure_FailureType_Failure_FirmwareError){ + throw exc::proto::FirmwareErrorException(code, message); + } else { + throw exc::proto::FailureException(code, message); + } + } + + std::ostream& operator<<(std::ostream& o, hw::trezor::Transport const& t){ + return t.dump(o); + } + + std::ostream& operator<<(std::ostream& o, std::shared_ptr const& t){ + if (!t){ + return o << "None"; + } + + return t->dump(o); + } + +} +} + + diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp new file mode 100644 index 000000000..7b82fd06f --- /dev/null +++ b/src/device_trezor/trezor/transport.hpp @@ -0,0 +1,331 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#ifndef MONERO_TRANSPORT_H +#define MONERO_TRANSPORT_H + + +#include +#include +#include +#include + +#include +#include +#include "net/http_client.h" + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" + +#include "exceptions.hpp" +#include "trezor_defs.hpp" +#include "messages_map.hpp" + +#include "messages/messages.pb.h" +#include "messages/messages-common.pb.h" +#include "messages/messages-management.pb.h" +#include "messages/messages-monero.pb.h" + +namespace hw { +namespace trezor { + + using json = rapidjson::Document; + using json_val = rapidjson::Value; + namespace http = epee::net_utils::http; + + const std::string DEFAULT_BRIDGE = "127.0.0.1:21325"; + + // Base HTTP comm serialization. + bool t_serialize(const std::string & in, std::string & out); + bool t_serialize(const json_val & in, std::string & out); + std::string t_serialize(const json_val & in); + + bool t_deserialize(const std::string & in, std::string & out); + bool t_deserialize(const std::string & in, json & out); + + // Flexible json serialization. HTTP client tailored for bridge API + template + bool invoke_bridge_http(const boost::string_ref uri, const t_req & out_struct, t_res & result_struct, t_transport& transport, const boost::string_ref method = "POST", std::chrono::milliseconds timeout = std::chrono::seconds(180)) + { + std::string req_param; + t_serialize(out_struct, req_param); + + http::fields_list additional_params; + additional_params.push_back(std::make_pair("Origin","https://monero.trezor.io")); + additional_params.push_back(std::make_pair("Content-Type","application/json; charset=utf-8")); + + const http::http_response_info* pri = nullptr; + if(!transport.invoke(uri, method, req_param, timeout, &pri, std::move(additional_params))) + { + MERROR("Failed to invoke http request to " << uri); + return false; + } + + if(!pri) + { + MERROR("Failed to invoke http request to " << uri << ", internal error (null response ptr)"); + return false; + } + + if(pri->m_response_code != 200) + { + MERROR("Failed to invoke http request to " << uri << ", wrong response code: " << pri->m_response_code + << " Response Body: " << pri->m_body); + return false; + } + + return t_deserialize(pri->m_body, result_struct); + } + + // Forward decl + class Transport; + class Protocol; + + // Communication protocol + class Protocol { + public: + Protocol() = default; + virtual ~Protocol() = default; + virtual void session_begin(Transport & transport){ }; + virtual void session_end(Transport & transport){ }; + virtual void write(Transport & transport, const google::protobuf::Message & req)= 0; + virtual void read(Transport & transport, std::shared_ptr & msg, messages::MessageType * msg_type=nullptr)= 0; + }; + + class ProtocolV1 : public Protocol { + public: + ProtocolV1() = default; + virtual ~ProtocolV1() = default; + + void write(Transport & transport, const google::protobuf::Message & req) override; + void read(Transport & transport, std::shared_ptr & msg, messages::MessageType * msg_type=nullptr) override; + }; + + + // Base transport + typedef std::vector> t_transport_vect; + + class Transport { + public: + Transport() = default; + virtual ~Transport() = default; + + virtual bool ping() { return false; }; + virtual std::string get_path() const { return ""; }; + virtual void enumerate(t_transport_vect & res){}; + virtual void open(){}; + virtual void close(){}; + virtual void write(const google::protobuf::Message & req) =0; + virtual void read(std::shared_ptr & msg, messages::MessageType * msg_type=nullptr) =0; + + virtual void write_chunk(const void * buff, size_t size) { }; + virtual size_t read_chunk(void * buff, size_t size) { return 0; }; + virtual std::ostream& dump(std::ostream& o) const { return o << "Transport<>"; } + }; + + // Bridge transport + class BridgeTransport : public Transport { + public: + BridgeTransport( + boost::optional device_path = boost::none, + boost::optional bridge_host = boost::none): + m_device_path(device_path), + m_bridge_host(bridge_host ? bridge_host.get() : DEFAULT_BRIDGE), + m_response(boost::none), + m_session(boost::none), + m_device_info(boost::none) + { + m_http_client.set_server(m_bridge_host, boost::none, false); + } + + virtual ~BridgeTransport() = default; + + static const char * PATH_PREFIX; + + std::string get_path() const override; + void enumerate(t_transport_vect & res) override; + + void open() override; + void close() override; + + void write(const google::protobuf::Message &req) override; + void read(std::shared_ptr & msg, messages::MessageType * msg_type=nullptr) override; + + const boost::optional & device_info() const; + std::ostream& dump(std::ostream& o) const override; + + private: + epee::net_utils::http::http_simple_client m_http_client; + std::string m_bridge_host; + boost::optional m_device_path; + boost::optional m_session; + boost::optional m_response; + boost::optional m_device_info; + }; + + // UdpTransport transport + using boost::asio::ip::udp; + + class UdpTransport : public Transport { + public: + + explicit UdpTransport( + boost::optional device_path=boost::none, + boost::optional> proto=boost::none); + + virtual ~UdpTransport() = default; + + static const char * PATH_PREFIX; + static const char * DEFAULT_HOST; + static const int DEFAULT_PORT; + + bool ping() override; + std::string get_path() const override; + void enumerate(t_transport_vect & res) override; + + void open() override; + void close() override; + + void write(const google::protobuf::Message &req) override; + void read(std::shared_ptr & msg, messages::MessageType * msg_type=nullptr) override; + + void write_chunk(const void * buff, size_t size) override; + size_t read_chunk(void * buff, size_t size) override; + + std::ostream& dump(std::ostream& o) const override; + + private: + void require_socket(); + ssize_t receive(void * buff, size_t size, boost::system::error_code * error_code=nullptr, bool no_throw=false, boost::posix_time::time_duration timeout=boost::posix_time::seconds(10)); + void check_deadline(); + static void handle_receive(const boost::system::error_code& ec, std::size_t length, + boost::system::error_code* out_ec, std::size_t* out_length); + bool ping_int(boost::posix_time::time_duration timeout=boost::posix_time::milliseconds(1500)); + + std::shared_ptr m_proto; + std::string m_device_host; + int m_device_port; + + std::unique_ptr m_socket; + boost::asio::io_service m_io_service; + boost::asio::deadline_timer m_deadline; + udp::endpoint m_endpoint; + }; + + // + // General helpers + // + + /** + * Enumerates all transports + */ + void enumerate(t_transport_vect & res); + + /** + * Transforms path to the transport + */ + std::shared_ptr transport(const std::string & path); + + /** + * Transforms path to the particular transport + */ + template + std::shared_ptr transport_typed(const std::string & path){ + auto t = transport(path); + if (!t){ + return nullptr; + } + + return std::dynamic_pointer_cast(t); + } + + // Exception carries unexpected message being received + namespace exc { + class UnexpectedMessageException: public ProtocolException { + protected: + hw::trezor::messages::MessageType recvType; + std::shared_ptr recvMsg; + + public: + using ProtocolException::ProtocolException; + UnexpectedMessageException(): ProtocolException("Trezor returned unexpected message") {}; + UnexpectedMessageException(hw::trezor::messages::MessageType recvType, + const std::shared_ptr & recvMsg) + : recvType(recvType), recvMsg(recvMsg) { + reason = std::string("Trezor returned unexpected message: ") + std::to_string(recvType); + } + }; + } + + /** + * Throws corresponding failure exception. + */ + [[ noreturn ]] void throw_failure_exception(const messages::common::Failure * failure); + + /** + * Simple wrapper for write-read message exchange with expected message response type. + * + * @throws UnexpectedMessageException if the response message type is different than expected. + * Exception contains message type and the message itself. + */ + template + std::shared_ptr + exchange_message(Transport & transport, const google::protobuf::Message & req, + boost::optional resp_type = boost::none) + { + // Require strictly protocol buffers response in the template. + BOOST_STATIC_ASSERT(boost::is_base_of::value); + + // Write the request + transport.write(req); + + // Read the response + std::shared_ptr msg_resp; + hw::trezor::messages::MessageType msg_resp_type; + transport.read(msg_resp, &msg_resp_type); + + // Determine type of expected message response + messages::MessageType required_type = resp_type ? resp_type.get() : MessageMapper::get_message_wire_number(); + + if (msg_resp_type == required_type) { + return message_ptr_retype(msg_resp); + } else if (msg_resp_type == messages::MessageType_Failure){ + throw_failure_exception(dynamic_cast(msg_resp.get())); + } else { + throw exc::UnexpectedMessageException(msg_resp_type, msg_resp); + } + } + + std::ostream& operator<<(std::ostream& o, hw::trezor::Transport const& t); + std::ostream& operator<<(std::ostream& o, std::shared_ptr const& t); +}} + + +#endif //MONERO_TRANSPORT_H diff --git a/src/device_trezor/trezor/trezor_defs.hpp b/src/device_trezor/trezor/trezor_defs.hpp new file mode 100644 index 000000000..951a8f802 --- /dev/null +++ b/src/device_trezor/trezor/trezor_defs.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// + +#if defined(HAVE_PROTOBUF) && !defined(WITHOUT_TREZOR) + #define WITH_DEVICE_TREZOR 1 +#else + #define WITH_DEVICE_TREZOR 0 +#endif + +#ifndef WITH_DEVICE_TREZOR_LITE +#define WITH_DEVICE_TREZOR_LITE 0 +#endif + +// Avoids protobuf undefined macro warning +#ifndef PROTOBUF_INLINE_NOT_IN_HEADERS +#define PROTOBUF_INLINE_NOT_IN_HEADERS 0 +#endif + +// Fixes gcc7 problem with minor macro defined clashing with minor() field. +#ifdef minor +#undef minor +#endif diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index ae8bb91d7..b67a0b992 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -133,7 +133,7 @@ namespace rct { xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev); xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev); - + key get_pre_mlsag_hash(const rctSig &rv, hw::device &hwdev); bool signMultisig(rctSig &rv, const std::vector &indices, const keyV &k, const multisig_out &msout, const key &secret_key); } #endif /* RCTSIGS_H */ diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f171d35b6..58d4cdced 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1801,6 +1801,27 @@ bool simple_wallet::version(const std::vector &args) return true; } +bool simple_wallet::cold_sign_tx(const std::vector& ptx_vector, tools::wallet2::signed_tx_set &exported_txs, std::vector &dsts_info, std::function accept_func) +{ + std::vector tx_aux; + + message_writer(console_color_white, false) << tr("Please confirm the transaction on the device"); + + m_wallet->cold_sign_tx(ptx_vector, exported_txs, dsts_info, tx_aux); + + if (accept_func && !accept_func(exported_txs)) + { + MERROR("Transactions rejected by callback"); + return false; + } + + // aux info + m_wallet->cold_tx_aux_import(exported_txs.ptx, tx_aux); + + // import key images + return m_wallet->import_key_images(exported_txs.key_images); +} + bool simple_wallet::set_always_confirm_transfers(const std::vector &args/* = std::vector()*/) { const auto pwd_container = get_and_verify_password(); @@ -2253,6 +2274,33 @@ bool simple_wallet::set_ignore_fractional_outputs(const std::vector return true; } +bool simple_wallet::set_device_name(const std::vector &args/* = std::vector()*/) +{ + const auto pwd_container = get_and_verify_password(); + if (pwd_container) + { + if (args.size() == 0){ + fail_msg_writer() << tr("Device name not specified"); + return true; + } + + m_wallet->device_name(args[0]); + bool r = false; + try { + r = m_wallet->reconnect_device(); + if (!r){ + fail_msg_writer() << tr("Device reconnect failed"); + } + + } catch(const std::exception & e){ + MWARNING("Device reconnect failed: " << e.what()); + fail_msg_writer() << tr("Device reconnect failed: ") << e.what(); + } + + } + return true; +} + bool simple_wallet::help(const std::vector &args/* = std::vector()*/) { if(args.empty()) @@ -2537,6 +2585,10 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::import_key_images, this, _1), tr("import_key_images "), tr("Import a signed key images list and verify their spent status.")); + m_cmd_binder.set_handler("hw_key_images_sync", + boost::bind(&simple_wallet::hw_key_images_sync, this, _1), + tr("hw_key_images_sync"), + tr("Synchronizes key images with the hw wallet.")); m_cmd_binder.set_handler("hw_reconnect", boost::bind(&simple_wallet::hw_reconnect, this, _1), tr("hw_reconnect"), @@ -2728,6 +2780,7 @@ bool simple_wallet::set_variable(const std::vector &args) CHECK_SIMPLE_VARIABLE("subaddress-lookahead", set_subaddress_lookahead, tr(":")); CHECK_SIMPLE_VARIABLE("segregation-height", set_segregation_height, tr("unsigned integer")); CHECK_SIMPLE_VARIABLE("ignore-fractional-outputs", set_ignore_fractional_outputs, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("")); } fail_msg_writer() << tr("set: unrecognized argument(s)"); return true; @@ -4834,12 +4887,14 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector dsts_info; vector dsts; size_t num_subaddresses = 0; for (size_t i = 0; i < local_args.size(); ) { + dsts_info.emplace_back(); + cryptonote::address_parse_info & info = dsts_info.back(); cryptonote::tx_destination_entry de; - cryptonote::address_parse_info info; bool r = true; // check for a URI @@ -5123,6 +5178,28 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorget_account().get_device().has_tx_cold_sign()) + { + try + { + tools::wallet2::signed_tx_set signed_tx; + if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){ + fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet"); + return true; + } + + commit_or_save(signed_tx.ptx, m_do_not_relay); + } + catch (const std::exception& e) + { + handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon()); + } + catch (...) + { + LOG_ERROR("Unknown error"); + fail_msg_writer() << tr("unknown error"); + } + } else if (m_wallet->watch_only()) { bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); @@ -5545,6 +5622,31 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vectorget_account().get_device().has_tx_cold_sign()) + { + try + { + tools::wallet2::signed_tx_set signed_tx; + std::vector dsts_info; + dsts_info.push_back(info); + + if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){ + fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet"); + return true; + } + + commit_or_save(signed_tx.ptx, m_do_not_relay); + } + catch (const std::exception& e) + { + handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon()); + } + catch (...) + { + LOG_ERROR("Unknown error"); + fail_msg_writer() << tr("unknown error"); + } + } else if (m_wallet->watch_only()) { bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); @@ -7794,6 +7896,48 @@ bool simple_wallet::import_key_images(const std::vector &args) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::hw_key_images_sync(const std::vector &args) +{ + if (!m_wallet->key_on_device()) + { + fail_msg_writer() << tr("command only supported by HW wallet"); + return true; + } + if (!m_wallet->get_account().get_device().has_ki_cold_sync()) + { + fail_msg_writer() << tr("hw wallet does not support cold KI sync"); + return true; + } + if (!m_wallet->is_trusted_daemon()) + { + fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); + return true; + } + + LOCK_IDLE_SCOPE(); + try + { + message_writer(console_color_white, false) << tr("Please confirm the key image sync on the device"); + + uint64_t spent = 0, unspent = 0; + uint64_t height = m_wallet->cold_key_image_sync(spent, unspent); + if (height > 0) + { + success_msg_writer() << tr("Signed key images imported to height ") << height << ", " + << print_money(spent) << tr(" spent, ") << print_money(unspent) << tr(" unspent"); + } else { + fail_msg_writer() << tr("Failed to import key images"); + } + } + catch (const std::exception &e) + { + fail_msg_writer() << tr("Failed to import key images: ") << e.what(); + return true; + } + + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::hw_reconnect(const std::vector &args) { if (!m_wallet->key_on_device()) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 39b715b73..7d813ceb0 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -139,6 +139,7 @@ namespace cryptonote bool set_subaddress_lookahead(const std::vector &args = std::vector()); bool set_segregation_height(const std::vector &args = std::vector()); bool set_ignore_fractional_outputs(const std::vector &args = std::vector()); + bool set_device_name(const std::vector &args = std::vector()); bool help(const std::vector &args = std::vector()); bool start_mining(const std::vector &args); bool stop_mining(const std::vector &args); @@ -200,6 +201,7 @@ namespace cryptonote bool verify(const std::vector &args); bool export_key_images(const std::vector &args); bool import_key_images(const std::vector &args); + bool hw_key_images_sync(const std::vector &args); bool hw_reconnect(const std::vector &args); bool export_outputs(const std::vector &args); bool import_outputs(const std::vector &args); @@ -224,6 +226,7 @@ namespace cryptonote bool unblackball(const std::vector& args); bool blackballed(const std::vector& args); bool version(const std::vector& args); + bool cold_sign_tx(const std::vector& ptx_vector, tools::wallet2::signed_tx_set &exported_txs, std::vector &dsts_info, std::function accept_func); uint64_t get_daemon_blockchain_height(std::string& err); bool try_connect_to_daemon(bool silent = false, uint32_t* version = nullptr); diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index be10b9f62..4932dd4b6 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -57,6 +57,7 @@ target_link_libraries(wallet common cryptonote_core mnemonics + device_trezor ${LMDB_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_SERIALIZATION_LIBRARY} diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..f2e54cf09 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -71,6 +71,8 @@ using namespace epee; #include "common/notify.h" #include "ringct/rctSigs.h" #include "ringdb.h" +#include "device/device_cold.hpp" +#include "device_trezor/device_trezor.hpp" extern "C" { @@ -768,6 +770,11 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) return idx + extra; } +static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet) +{ + shim->get_tx_pub_key_from_received_outs = boost::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, _1); +} + //----------------------------------------------------------------- } //namespace @@ -1060,8 +1067,9 @@ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeabl bool wallet2::reconnect_device() { bool r = true; - hw::device &hwdev = hw::get_device(m_device_name); + hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); + hwdev.set_network_type(m_nettype); r = hwdev.init(); if (!r){ LOG_PRINT_L2("Could not init device"); @@ -2944,6 +2952,7 @@ bool wallet2::deinit() { m_is_initialized=false; unlock_keys_file(); + m_account.deinit(); return true; } //---------------------------------------------------------------------------------------------------- @@ -3413,13 +3422,20 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ r = epee::serialization::load_t_from_binary(m_account, account_data); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); - if (m_key_device_type == hw::device::device_type::LEDGER) { + if (m_key_device_type == hw::device::device_type::LEDGER || m_key_device_type == hw::device::device_type::TREZOR) { LOG_PRINT_L0("Account on device. Initing device..."); - hw::device &hwdev = hw::get_device(m_device_name); - hwdev.set_name(m_device_name); - hwdev.init(); - hwdev.connect(); + hw::device &hwdev = lookup_device(m_device_name); + THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); + hwdev.set_network_type(m_nettype); + THROW_WALLET_EXCEPTION_IF(!hwdev.init(), error::wallet_internal_error, "Could not initialize the device " + m_device_name); + THROW_WALLET_EXCEPTION_IF(!hwdev.connect(), error::wallet_internal_error, "Could not connect to the device " + m_device_name); m_account.set_device(hwdev); + + account_public_address device_account_public_address; + THROW_WALLET_EXCEPTION_IF(!hwdev.get_public_address(device_account_public_address), error::wallet_internal_error, "Cannot get a device address"); + THROW_WALLET_EXCEPTION_IF(device_account_public_address != m_account.get_keys().m_account_address, error::wallet_internal_error, "Device wallet does not match wallet address. " + "Device address: " + cryptonote::get_account_address_as_str(m_nettype, false, device_account_public_address) + + ", wallet address: " + m_account.get_public_address_str(m_nettype)); LOG_PRINT_L0("Device inited..."); } else if (key_on_device()) { THROW_WALLET_EXCEPTION(error::wallet_internal_error, "hardware device not supported"); @@ -3450,7 +3466,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); - if(!m_watch_only && !m_multisig) + if(!m_watch_only && !m_multisig && hwdev.device_protocol() != hw::device::PROTOCOL_COLD) r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); @@ -3474,7 +3490,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) { // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded). unlock_keys_file(); - bool r = verify_password(m_keys_file, password, m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); + bool r = verify_password(m_keys_file, password, m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig, m_account.get_device(), m_kdf_rounds); lock_keys_file(); return r; } @@ -3914,8 +3930,9 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); } - auto &hwdev = hw::get_device(device_name); + auto &hwdev = lookup_device(device_name); hwdev.set_name(device_name); + hwdev.set_network_type(m_nettype); m_account.create_from_device(hwdev); m_key_device_type = m_account.get_device().get_type(); @@ -5781,22 +5798,8 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector m_transfers.size()) - { - LOG_PRINT_L1("More key images returned that we know outputs for"); - return false; - } - for (size_t i = 0; i < signed_txs.key_images.size(); ++i) - { - transfer_details &td = m_transfers[i]; - if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != signed_txs.key_images[i]) - LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one"); - td.m_key_image = signed_txs.key_images[i]; - m_key_images[m_transfers[i].m_key_image] = i; - td.m_key_image_known = true; - td.m_key_image_partial = false; - m_pub_keys[m_transfers[i].get_public_key()] = i; - } + bool r = import_key_images(signed_txs.key_images); + if (!r) return false; ptx = signed_txs.ptx; @@ -6346,6 +6349,19 @@ crypto::chacha_key wallet2::get_ringdb_key() return *m_ringdb_key; } +void wallet2::register_devices(){ + hw::trezor::register_all(); +} + +hw::device& wallet2::lookup_device(const std::string & device_descriptor){ + if (!m_devices_registered){ + m_devices_registered = true; + register_devices(); + } + + return hw::get_device(device_descriptor); +} + bool wallet2::add_rings(const crypto::chacha_key &key, const cryptonote::transaction_prefix &tx) { if (!m_ringdb) @@ -9084,6 +9100,62 @@ std::vector wallet2::create_transactions_from(const crypton return ptx_vector; } //---------------------------------------------------------------------------------------------------- +void wallet2::cold_tx_aux_import(const std::vector & ptx, const std::vector & tx_device_aux) +{ + CHECK_AND_ASSERT_THROW_MES(ptx.size() == tx_device_aux.size(), "TX aux has invalid size"); + for (size_t i = 0; i < ptx.size(); ++i){ + crypto::hash txid; + txid = get_transaction_hash(ptx[i].tx); + set_tx_device_aux(txid, tx_device_aux[i]); + } +} +//---------------------------------------------------------------------------------------------------- +void wallet2::cold_sign_tx(const std::vector& ptx_vector, signed_tx_set &exported_txs, std::vector &dsts_info, std::vector & tx_device_aux) +{ + auto & hwdev = get_account().get_device(); + if (!hwdev.has_tx_cold_sign()){ + throw std::invalid_argument("Device does not support cold sign protocol"); + } + + unsigned_tx_set txs; + for (auto &tx: ptx_vector) + { + txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device())); + } + txs.transfers = m_transfers; + + auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); + CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); + + hw::tx_aux_data aux_data; + hw::wallet_shim wallet_shim; + setup_shim(&wallet_shim, this); + aux_data.tx_recipients = dsts_info; + dev_cold->tx_sign(&wallet_shim, txs, exported_txs, aux_data); + tx_device_aux = aux_data.tx_device_aux; + + MDEBUG("Signed tx data from hw: " << exported_txs.ptx.size() << " transactions"); + for (auto &c_ptx: exported_txs.ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(c_ptx.tx)); +} +//---------------------------------------------------------------------------------------------------- +uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { + auto & hwdev = get_account().get_device(); + if (!hwdev.has_ki_cold_sync()){ + throw std::invalid_argument("Device does not support cold ki sync protocol"); + } + + auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); + CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); + + std::vector> ski; + hw::wallet_shim wallet_shim; + setup_shim(&wallet_shim, this); + + dev_cold->ki_sync(&wallet_shim, m_transfers, ski); + + return import_key_images(ski, spent, unspent); +} +//---------------------------------------------------------------------------------------------------- void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const { boost::optional result = m_node_rpc_proxy.get_earliest_height(version, earliest_height); @@ -10240,6 +10312,19 @@ std::string wallet2::get_tx_note(const crypto::hash &txid) const return i->second; } +void wallet2::set_tx_device_aux(const crypto::hash &txid, const std::string &aux) +{ + m_tx_device[txid] = aux; +} + +std::string wallet2::get_tx_device_aux(const crypto::hash &txid) const +{ + std::unordered_map::const_iterator i = m_tx_device.find(txid); + if (i == m_tx_device.end()) + return std::string(); + return i->second; +} + void wallet2::set_attribute(const std::string &key, const std::string &value) { m_attributes[key] = value; @@ -10785,6 +10870,29 @@ uint64_t wallet2::import_key_images(const std::vector key_images) +{ + if (key_images.size() > m_transfers.size()) + { + LOG_PRINT_L1("More key images returned that we know outputs for"); + return false; + } + for (size_t i = 0; i < key_images.size(); ++i) + { + transfer_details &td = m_transfers[i]; + if (td.m_key_image_known && !td.m_key_image_partial && td.m_key_image != key_images[i]) + LOG_PRINT_L0("WARNING: imported key image differs from previously known key image at index " << i << ": trusting imported one"); + td.m_key_image = key_images[i]; + m_key_images[m_transfers[i].m_key_image] = i; + td.m_key_image_known = true; + td.m_key_image_partial = false; + m_pub_keys[m_transfers[i].get_public_key()] = i; + } + + return true; +} + wallet2::payment_container wallet2::export_payments() const { payment_container payments; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 680196f01..7d78a3fee 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -54,6 +54,7 @@ #include "ringct/rctTypes.h" #include "ringct/rctOps.h" #include "checkpoints/checkpoints.h" +#include "serialization/pair.h" #include "wallet_errors.h" #include "common/password.h" @@ -764,6 +765,9 @@ namespace tools std::vector create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices); std::vector create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); std::vector create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); + void cold_tx_aux_import(const std::vector& ptx, const std::vector& tx_device_aux); + void cold_sign_tx(const std::vector& ptx_vector, signed_tx_set &exported_txs, std::vector &dsts_info, std::vector & tx_device_aux); + uint64_t cold_key_image_sync(uint64_t &spent, uint64_t &unspent); bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function accept_func = NULL); bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function accept_func = NULL); bool sign_multisig_tx_from_file(const std::string &filename, std::vector &txids, std::function accept_func); @@ -892,6 +896,9 @@ namespace tools if(ver < 25) return; a & m_last_block_reward; + if(ver < 26) + return; + a & m_tx_device; } /*! @@ -1020,6 +1027,9 @@ namespace tools void set_tx_note(const crypto::hash &txid, const std::string ¬e); std::string get_tx_note(const crypto::hash &txid) const; + void set_tx_device_aux(const crypto::hash &txid, const std::string &aux); + std::string get_tx_device_aux(const crypto::hash &txid) const; + void set_description(const std::string &description); std::string get_description() const; @@ -1074,6 +1084,8 @@ namespace tools std::vector> export_key_images() const; uint64_t import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent = true); uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); + bool import_key_images(std::vector key_images); + crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; void update_pool_state(bool refreshed = false); void remove_obsolete_pool_txs(const std::vector &tx_hashes); @@ -1236,7 +1248,6 @@ namespace tools void set_unspent(size_t idx); void get_outs(std::vector> &outs, const std::vector &selected_transfers, size_t fake_outputs_count); bool tx_add_fake_output(std::vector> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const; - crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector &unused_transfers_indices, const std::vector &unused_dust_indices) const; std::vector get_only_rct(const std::vector &unused_dust_indices, const std::vector &unused_transfers_indices) const; void scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map &tx_money_got_in_outs, std::vector &outs); @@ -1253,6 +1264,9 @@ namespace tools crypto::chacha_key get_ringdb_key(); void setup_keys(const epee::wipeable_string &password); + void register_devices(); + hw::device& lookup_device(const std::string & device_descriptor); + bool get_rct_distribution(uint64_t &start_height, std::vector &distribution); uint64_t get_segregation_fork_height() const; @@ -1347,6 +1361,9 @@ namespace tools size_t m_subaddress_lookahead_major, m_subaddress_lookahead_minor; std::string m_device_name; + // Aux transaction data from device + std::unordered_map m_tx_device; + // Light wallet bool m_light_wallet; /* sends view key to daemon for scanning */ uint64_t m_light_wallet_scanned_block_height; @@ -1373,11 +1390,12 @@ namespace tools boost::optional m_encrypt_keys_after_refresh; bool m_unattended; + bool m_devices_registered; std::shared_ptr m_tx_notify; }; } -BOOST_CLASS_VERSION(tools::wallet2, 25) +BOOST_CLASS_VERSION(tools::wallet2, 26) BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9) BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) From e61062b6f23cd27dba1da145c8590aff6fbf2f10 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Fri, 2 Nov 2018 19:31:31 -0400 Subject: [PATCH 0238/1007] use current height - 1 for top block height in err msgs --- src/rpc/core_rpc_server.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index aa9d3d64b..bd410047a 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1010,7 +1010,7 @@ namespace cryptonote if(m_core.get_current_blockchain_height() <= h) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Too big height: ") + std::to_string(h) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()); + error_resp.message = std::string("Requested block height: ") + std::to_string(h) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); } res = string_tools::pod_to_hex(m_core.get_block_id_by_height(h)); return true; @@ -1457,7 +1457,7 @@ namespace cryptonote if(m_core.get_current_blockchain_height() <= req.height) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Too big height: ") + std::to_string(req.height) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()); + error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); return false; } crypto::hash block_hash = m_core.get_block_id_by_height(req.height); @@ -1502,7 +1502,7 @@ namespace cryptonote if(m_core.get_current_blockchain_height() <= req.height) { error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT; - error_resp.message = std::string("Too big height: ") + std::to_string(req.height) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()); + error_resp.message = std::string("Requested block height: ") + std::to_string(req.height) + " greater than current top block height: " + std::to_string(m_core.get_current_blockchain_height() - 1); return false; } block_hash = m_core.get_block_id_by_height(req.height); From 0afdb00b9d4f6ad276b5b2cd902c16ef6e5f7c06 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 3 Nov 2018 11:49:45 +0000 Subject: [PATCH 0239/1007] wallet2: fix print_ring printing double entries for transactions When a tx gets from unconfirmed to conirmed, the rings for that transaction were being added twice --- src/wallet/wallet2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..659fe0f58 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1919,6 +1919,7 @@ void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::trans entry.first->second.m_subaddr_indices = subaddr_indices; } + entry.first->second.m_rings.clear(); for (const auto &in: tx.vin) { if (in.type() != typeid(cryptonote::txin_to_key)) From 8f3963d20060104c3a74210cf5cb1c616a2b0712 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 3 Nov 2018 10:31:03 +0000 Subject: [PATCH 0240/1007] wallet2: demote a few uninteresting recurring logs to TRACE --- src/wallet/wallet2.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..f3ef67095 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2290,7 +2290,7 @@ void wallet2::remove_obsolete_pool_txs(const std::vector &tx_hashe //---------------------------------------------------------------------------------------------------- void wallet2::update_pool_state(bool refreshed) { - MDEBUG("update_pool_state start"); + MTRACE("update_pool_state start"); auto keys_reencryptor = epee::misc_utils::create_scope_leave_handler([&, this]() { if (m_encrypt_keys_after_refresh) @@ -2309,7 +2309,7 @@ void wallet2::update_pool_state(bool refreshed) THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool_hashes.bin"); THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool_hashes.bin"); THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error); - MDEBUG("update_pool_state got pool"); + MTRACE("update_pool_state got pool"); // remove any pending tx that's not in the pool std::unordered_map::iterator it = m_unconfirmed_txs.begin(); @@ -2366,7 +2366,7 @@ void wallet2::update_pool_state(bool refreshed) } } } - MDEBUG("update_pool_state done first loop"); + MTRACE("update_pool_state done first loop"); // remove pool txes to us that aren't in the pool anymore // but only if we just refreshed, so that the tx can go in @@ -2375,7 +2375,7 @@ void wallet2::update_pool_state(bool refreshed) if (refreshed) remove_obsolete_pool_txs(res.tx_hashes); - MDEBUG("update_pool_state done second loop"); + MTRACE("update_pool_state done second loop"); // gather txids of new pool txes to us std::vector> txids; @@ -2512,7 +2512,7 @@ void wallet2::update_pool_state(bool refreshed) LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << res.status); } } - MDEBUG("update_pool_state end"); + MTRACE("update_pool_state end"); } //---------------------------------------------------------------------------------------------------- void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force) From f26ce08c8abbff51f50c13848e8899865862515d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 26 Oct 2018 14:25:20 +0000 Subject: [PATCH 0241/1007] wallet: add a non destructive blockchain rescan --- src/simplewallet/simplewallet.cpp | 37 ++++++++++++++------ src/simplewallet/simplewallet.h | 5 ++- src/wallet/wallet2.cpp | 22 ++++++++++-- src/wallet/wallet2.h | 2 +- src/wallet/wallet_rpc_server.cpp | 2 +- src/wallet/wallet_rpc_server_commands_defs.h | 3 ++ 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 18b596662..ef13bc889 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2491,6 +2491,7 @@ simple_wallet::simple_wallet() tr("Show the unspent outputs of a specified address within an optional amount range.")); m_cmd_binder.set_handler("rescan_bc", boost::bind(&simple_wallet::rescan_blockchain, this, _1), + tr("rescan_bc [hard]"), tr("Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself.")); m_cmd_binder.set_handler("set_tx_note", boost::bind(&simple_wallet::set_tx_note, this, _1), @@ -4237,15 +4238,15 @@ boost::optional simple_wallet::on_get_password(const char return pwd_container->password(); } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::refresh_main(uint64_t start_height, bool reset, bool is_init) +bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bool is_init) { if (!try_connect_to_daemon(is_init)) return true; LOCK_IDLE_SCOPE(); - if (reset) - m_wallet->rescan_blockchain(false); + if (reset != ResetNone) + m_wallet->rescan_blockchain(reset == ResetHard, false); #ifdef HAVE_READLINE rdln::suspend_readline pause_readline; @@ -4324,7 +4325,7 @@ bool simple_wallet::refresh(const std::vector& args) start_height = 0; } } - return refresh_main(start_height, false); + return refresh_main(start_height, ResetNone); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_balance_unlocked(bool detailed) @@ -6982,15 +6983,29 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::rescan_blockchain(const std::vector &args_) { - message_writer() << tr("Warning: this will lose any information which can not be recovered from the blockchain."); - message_writer() << tr("This includes destination addresses, tx secret keys, tx notes, etc"); - std::string confirm = input_line(tr("Rescan anyway ? (Y/Yes/N/No): ")); - if(!std::cin.eof()) + bool hard = false; + if (!args_.empty()) { - if (!command_line::is_yes(confirm)) + if (args_[0] != "hard") + { + fail_msg_writer() << tr("usage: rescan_bc [hard]"); return true; + } + hard = true; + } + + if (hard) + { + message_writer() << tr("Warning: this will lose any information which can not be recovered from the blockchain."); + message_writer() << tr("This includes destination addresses, tx secret keys, tx notes, etc"); + std::string confirm = input_line(tr("Rescan anyway ? (Y/Yes/N/No): ")); + if(!std::cin.eof()) + { + if (!command_line::is_yes(confirm)) + return true; + } } - return refresh_main(0, true); + return refresh_main(0, hard ? ResetHard : ResetSoft, true); } //---------------------------------------------------------------------------------------------------- void simple_wallet::wallet_idle_thread() @@ -7038,7 +7053,7 @@ bool simple_wallet::run() // check and display warning, but go on anyway try_connect_to_daemon(); - refresh_main(0, false, true); + refresh_main(0, ResetNone, true); m_auto_refresh_enabled = m_wallet->auto_refresh(); m_idle_thread = boost::thread([&]{wallet_idle_thread();}); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 39b715b73..6eedef4a2 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -83,6 +83,9 @@ namespace cryptonote std::string get_commands_str(); std::string get_command_usage(const std::vector &args); private: + + enum ResetType { ResetNone, ResetSoft, ResetHard }; + bool handle_command_line(const boost::program_options::variables_map& vm); bool run_console_handler(); @@ -188,7 +191,7 @@ namespace cryptonote bool show_transfers(const std::vector &args); bool unspent_outputs(const std::vector &args); bool rescan_blockchain(const std::vector &args); - bool refresh_main(uint64_t start_height, bool reset = false, bool is_init = false); + bool refresh_main(uint64_t start_height, ResetType reset, bool is_init = false); bool set_tx_note(const std::vector &args); bool get_tx_note(const std::vector &args); bool set_description(const std::vector &args); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c5618375e..e666eda2c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5073,11 +5073,27 @@ void wallet2::rescan_spent() } } //---------------------------------------------------------------------------------------------------- -void wallet2::rescan_blockchain(bool refresh) +void wallet2::rescan_blockchain(bool hard, bool refresh) { - clear(); + if(hard) + { + clear(); + setup_new_blockchain(); + } + else + { + m_blockchain.clear(); + m_transfers.clear(); + m_key_images.clear(); + m_pub_keys.clear(); + m_scanned_pool_txs[0].clear(); + m_scanned_pool_txs[1].clear(); - setup_new_blockchain(); + cryptonote::block b; + generate_genesis(b); + m_blockchain.push_back(get_block_hash(b)); + m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx); + } if (refresh) this->refresh(false); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 680196f01..679f1c1ad 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -782,7 +782,7 @@ namespace tools uint64_t get_blockchain_current_height() const { return m_light_wallet_blockchain_height ? m_light_wallet_blockchain_height : m_blockchain.size(); } void rescan_spent(); - void rescan_blockchain(bool refresh = true); + void rescan_blockchain(bool hard, bool refresh = true); bool is_transfer_unlocked(const transfer_details& td) const; bool is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height) const; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 1b63d65b6..09f78d593 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1613,7 +1613,7 @@ namespace tools try { - m_wallet->rescan_blockchain(); + m_wallet->rescan_blockchain(req.hard); } catch (const std::exception& e) { diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 2377b69e3..1d7307b7a 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -992,7 +992,10 @@ namespace wallet_rpc { struct request { + bool hard; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(hard, false); END_KV_SERIALIZE_MAP() }; From 177a9d76f99ce259598f85f99b1d2ecf77a7fdd2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 3 Nov 2018 18:32:05 +0000 Subject: [PATCH 0242/1007] wallet: warn if lockable memory limit is too low --- src/common/util.cpp | 15 +++++++++++++++ src/common/util.h | 2 ++ src/wallet/wallet_args.cpp | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/src/common/util.cpp b/src/common/util.cpp index 43973c511..58b0d8210 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -728,6 +728,21 @@ std::string get_nix_version_display_string() return true; } + ssize_t get_lockable_memory() + { +#ifdef __GLIBC__ + struct rlimit rlim; + if (getrlimit(RLIMIT_MEMLOCK, &rlim) < 0) + { + MERROR("Failed to determine the lockable memory limit"); + return -1; + } + return rlim.rlim_cur; +#else + return -1; +#endif + } + bool on_startup() { mlog_configure("", true); diff --git a/src/common/util.h b/src/common/util.h index e793a42b5..1c5c5f4e7 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -221,6 +221,8 @@ namespace tools void set_strict_default_file_permissions(bool strict); + ssize_t get_lockable_memory(); + void set_max_concurrency(unsigned n); unsigned get_max_concurrency(); diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index 95a4e0ad6..b9d0a6a75 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -211,6 +211,14 @@ namespace wallet_args Print(print) << boost::format(wallet_args::tr("Logging to %s")) % log_path; + const ssize_t lockable_memory = tools::get_lockable_memory(); + if (lockable_memory >= 0 && lockable_memory < 256 * 4096) // 256 pages -> at least 256 secret keys and other such small/medium objects + Print(print) << tr("WARNING: You may not have a high enough lockable memory limit") +#ifdef ELPP_OS_UNIX + << ", " << tr("see ulimit -l") +#endif + ; + return {std::move(vm), should_terminate}; } } From 5878fe95ce422a509eae8c5c69e0e6d59e5d64a6 Mon Sep 17 00:00:00 2001 From: stoffu Date: Sun, 4 Nov 2018 10:24:33 +0900 Subject: [PATCH 0243/1007] simplewallet: don't skip asking for password when watch-only --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f171d35b6..27bc05a2e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -104,7 +104,7 @@ typedef cryptonote::simple_wallet sw; #define SCOPED_WALLET_UNLOCK() \ LOCK_IDLE_SCOPE(); \ boost::optional pwd_container = boost::none; \ - if (m_wallet->ask_password() && !m_wallet->watch_only() && !(pwd_container = get_and_verify_password())) { return true; } \ + if (m_wallet->ask_password() && !(pwd_container = get_and_verify_password())) { return true; } \ tools::wallet_keys_unlocker unlocker(*m_wallet, pwd_container); enum TransferType { From 5d4f3df887a4a00d151f61aa6baca2583a574e72 Mon Sep 17 00:00:00 2001 From: stoffu Date: Sun, 4 Nov 2018 10:48:49 +0900 Subject: [PATCH 0244/1007] simplewallet: reorganize SCOPED_WALLET_UNLOCK a bit more Followup on #4555 --- src/simplewallet/simplewallet.cpp | 42 ++++++++++++++++++------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f171d35b6..07b270e91 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -580,12 +580,12 @@ std::string simple_wallet::get_command_usage(const std::vector &arg bool simple_wallet::viewkey(const std::vector &args/* = std::vector()*/) { - SCOPED_WALLET_UNLOCK(); // don't log PAUSE_READLINE(); if (m_wallet->key_on_device()) { std::cout << "secret: On device. Not available" << std::endl; } else { + SCOPED_WALLET_UNLOCK(); printf("secret: "); print_secret_key(m_wallet->get_account().get_keys().m_view_secret_key); putchar('\n'); @@ -602,12 +602,12 @@ bool simple_wallet::spendkey(const std::vector &args/* = std::vecto fail_msg_writer() << tr("wallet is watch-only and has no spend key"); return true; } - SCOPED_WALLET_UNLOCK(); // don't log PAUSE_READLINE(); if (m_wallet->key_on_device()) { std::cout << "secret: On device. Not available" << std::endl; } else { + SCOPED_WALLET_UNLOCK(); printf("secret: "); print_secret_key(m_wallet->get_account().get_keys().m_spend_secret_key); putchar('\n'); @@ -634,8 +634,6 @@ bool simple_wallet::print_seed(bool encrypted) return true; } - SCOPED_WALLET_UNLOCK(); - multisig = m_wallet->multisig(&ready); if (multisig) { @@ -645,7 +643,10 @@ bool simple_wallet::print_seed(bool encrypted) return true; } } - else if (!m_wallet->is_deterministic()) + + SCOPED_WALLET_UNLOCK(); + + if (!multisig && !m_wallet->is_deterministic()) { fail_msg_writer() << tr("wallet is non-deterministic and has no seed"); return true; @@ -1077,11 +1078,12 @@ bool simple_wallet::export_multisig(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); - const std::string filename = args[0]; if (m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) return true; + + SCOPED_WALLET_UNLOCK(); + try { cryptonote::blobdata ciphertext = m_wallet->export_multisig(); @@ -1129,8 +1131,6 @@ bool simple_wallet::import_multisig(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); - std::vector info; for (size_t n = 0; n < args.size(); ++n) { @@ -1145,6 +1145,8 @@ bool simple_wallet::import_multisig(const std::vector &args) info.push_back(std::move(data)); } + SCOPED_WALLET_UNLOCK(); + // all read and parsed, actually import try { @@ -1282,11 +1284,11 @@ bool simple_wallet::submit_multisig(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); - if (!try_connect_to_daemon()) return true; + SCOPED_WALLET_UNLOCK(); + std::string filename = args[0]; try { @@ -1350,11 +1352,12 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); - std::string filename = args[0]; if (m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) return true; + + SCOPED_WALLET_UNLOCK(); + try { tools::wallet2::multisig_tx_set txs; @@ -5577,7 +5580,6 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector &args_) { - SCOPED_WALLET_UNLOCK(); if (!try_connect_to_daemon()) return true; @@ -5725,6 +5727,8 @@ bool simple_wallet::sweep_single(const std::vector &args_) } } + SCOPED_WALLET_UNLOCK(); + try { // figure out what tx will be necessary @@ -7658,7 +7662,6 @@ bool simple_wallet::sign(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); std::string filename = args[0]; std::string data; bool r = epee::file_io_utils::load_file_to_string(filename, data); @@ -7667,6 +7670,9 @@ bool simple_wallet::sign(const std::vector &args) fail_msg_writer() << tr("failed to read file ") << filename; return true; } + + SCOPED_WALLET_UNLOCK(); + std::string signature = m_wallet->sign(data); success_msg_writer() << signature; return true; @@ -7728,11 +7734,12 @@ bool simple_wallet::export_key_images(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); std::string filename = args[0]; if (m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) return true; + SCOPED_WALLET_UNLOCK(); + try { if (!m_wallet->export_key_images(filename)) @@ -7832,11 +7839,12 @@ bool simple_wallet::export_outputs(const std::vector &args) return true; } - SCOPED_WALLET_UNLOCK(); std::string filename = args[0]; if (m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) return true; + SCOPED_WALLET_UNLOCK(); + try { std::string data = m_wallet->export_outputs_to_str(); From 6f7a5fd4f70ee981c4a4eb82adb0349a2c033a6b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 18:52:28 +0000 Subject: [PATCH 0245/1007] db_lmdb: slight speedup getting array data from the blockchain --- src/blockchain_db/lmdb/db_lmdb.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index d642069f8..c4b161899 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -3160,6 +3160,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vectortx_hash, ot->local_index); - tx_out_indices.push_back(result); + const outtx *ot = (const outtx *)v.mv_data; + tx_out_indices.push_back(tx_out_index(ot->tx_hash, ot->local_index)); } TXN_POSTFIX_RDONLY(); @@ -3188,6 +3188,7 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vectordata; + outputs.push_back(okp->data); } else { const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data; + outputs.resize(outputs.size() + 1); + output_data_t &data = outputs.back(); memcpy(&data, &okp->data, sizeof(pre_rct_output_data_t)); data.commitment = rct::zeroCommit(amount); } - outputs.push_back(data); } TXN_POSTFIX_RDONLY(); @@ -3239,6 +3240,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std:: indices.clear(); std::vector tx_indices; + tx_indices.reserve(offsets.size()); TXN_PREFIX_RDONLY(); RCURSOR(output_amounts); From 1426209a10602e07e80cf93117b1c80ca58ace9b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 19:02:47 +0000 Subject: [PATCH 0246/1007] blockchain: don't run threads if we have just one function to run --- src/cryptonote_core/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 7576e0ed7..8b94a30f0 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4171,7 +4171,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vectorcan_thread_bulk_indices()) threads = 1; - if (threads > 1) + if (threads > 1 && amounts.size() > 1) { tools::threadpool::waiter waiter; From 5808530f54d2f24410b24089f6d30163aed71d7b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 1 Nov 2018 17:24:35 +0000 Subject: [PATCH 0247/1007] blockchain: remove unused output_scan_worker parameter --- src/cryptonote_core/blockchain.cpp | 11 ++++------- src/cryptonote_core/blockchain.h | 4 +--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 8b94a30f0..e766fd6c8 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3786,8 +3786,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) } //------------------------------------------------------------------ -//FIXME: unused parameter txs -void Blockchain::output_scan_worker(const uint64_t amount, const std::vector &offsets, std::vector &outputs, std::unordered_map &txs) const +void Blockchain::output_scan_worker(const uint64_t amount, const std::vector &offsets, std::vector &outputs) const { try { @@ -4164,9 +4163,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector> transactions(amounts.size()); - + // gather all the output keys threads = tpool.get_max_concurrency(); if (!m_db->can_thread_bulk_indices()) threads = 1; @@ -4178,7 +4175,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector &offsets, - std::vector &outputs, std::unordered_map &txs) const; + std::vector &outputs) const; /** * @brief computes the "short" and "long" hashes for a set of blocks From 5d7c2316045e416d0152dd5cd3a941be3843c67c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 4 Nov 2018 15:38:59 +0000 Subject: [PATCH 0248/1007] rct: add a zeroCommit cache for common pre-rct case This is called for every pre-rct output at blockchain sync time, and a lot of them wil hit the cache, saving a scalarmult each. --- src/ringct/rctOps.cpp | 186 +++++++++++++++++++++++++++ tests/performance_tests/crypto_ops.h | 4 + tests/performance_tests/main.cpp | 2 + tests/unit_tests/ringct.cpp | 19 +++ 4 files changed, 211 insertions(+) diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 41bbf6ca3..c64ee4daf 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -30,6 +30,7 @@ #include #include "misc_log_ex.h" +#include "cryptonote_basic/cryptonote_format_utils.h" #include "rctOps.h" using namespace crypto; using namespace std; @@ -39,6 +40,183 @@ using namespace std; #define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}} +struct zero_commitment { uint64_t amount; rct::key commitment; }; +static const zero_commitment zero_commitments[] = { + { (uint64_t)0ull, {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66} }, + { (uint64_t)1ull, {0x17, 0x38, 0xeb, 0x7a, 0x67, 0x7c, 0x61, 0x49, 0x22, 0x8a, 0x2b, 0xea, 0xa2, 0x1b, 0xea, 0x9e, 0x33, 0x70, 0x80, 0x2d, 0x72, 0xa3, 0xee, 0xc7, 0x90, 0x11, 0x95, 0x80, 0xe0, 0x2b, 0xd5, 0x22} }, + { (uint64_t)2ull, {0x76, 0x24, 0x84, 0x63, 0xa, 0x6, 0x17, 0x17, 0x8d, 0xe, 0x33, 0xf3, 0x2e, 0xe, 0x11, 0x3e, 0xa8, 0x46, 0x86, 0x9d, 0x46, 0x4b, 0xb, 0x6f, 0xf1, 0x3b, 0x29, 0x97, 0x4, 0x9c, 0xda, 0x7d} }, + { (uint64_t)3ull, {0xcf, 0xf7, 0x7b, 0x56, 0x62, 0x1c, 0x4f, 0xef, 0x74, 0xcf, 0x37, 0xc1, 0x78, 0xd4, 0xb5, 0x8a, 0xf4, 0xad, 0x8c, 0xd4, 0x35, 0xfc, 0xb9, 0x62, 0x76, 0xbc, 0x15, 0x9c, 0x7c, 0x6a, 0x28, 0x8c} }, + { (uint64_t)4ull, {0x9a, 0xb8, 0x6c, 0x31, 0xf4, 0x22, 0xd8, 0x21, 0xb5, 0x22, 0x57, 0x30, 0xd1, 0xbf, 0x73, 0xa, 0x9b, 0x91, 0xd2, 0xee, 0xe3, 0x14, 0xb8, 0x4e, 0xbd, 0x4b, 0x93, 0xa6, 0x81, 0x61, 0x82, 0x66} }, + { (uint64_t)5ull, {0x32, 0xee, 0x2f, 0x65, 0x9a, 0xf6, 0x38, 0x58, 0xc2, 0xf7, 0xdc, 0x11, 0x1b, 0x3b, 0xb8, 0xfe, 0xc0, 0x2c, 0xac, 0x42, 0x38, 0x3b, 0xb7, 0x36, 0xde, 0x1, 0x8, 0x6f, 0x38, 0xf0, 0x12, 0x3c} }, + { (uint64_t)6ull, {0x47, 0x26, 0x2b, 0x1e, 0xa6, 0x43, 0x1, 0x6e, 0x38, 0x24, 0x17, 0x53, 0xa4, 0xfb, 0x39, 0x92, 0x9e, 0x31, 0xea, 0x9b, 0xd3, 0x41, 0x1a, 0xb1, 0x7f, 0x16, 0x6e, 0x61, 0xf6, 0xc, 0xe5, 0xa7} }, + { (uint64_t)7ull, {0xc6, 0x32, 0x93, 0x68, 0x79, 0x9a, 0xd, 0xed, 0x4c, 0x20, 0x25, 0x6b, 0xff, 0xe6, 0x45, 0x47, 0xf1, 0x7b, 0xc4, 0x23, 0x95, 0x4, 0xbe, 0x82, 0x4d, 0xff, 0x8a, 0x2b, 0xe1, 0xaf, 0xe3, 0xcd} }, + { (uint64_t)8ull, {0xd5, 0xf1, 0x50, 0x74, 0x33, 0x46, 0x19, 0xf, 0x84, 0x2b, 0x6, 0xb8, 0xfa, 0xe1, 0x20, 0xeb, 0x85, 0x24, 0x7e, 0x9f, 0x6d, 0xec, 0x88, 0xff, 0xa2, 0x23, 0xbf, 0x69, 0x94, 0xe9, 0xc8, 0xc2} }, + { (uint64_t)9ull, {0x56, 00, 0x23, 0x32, 0x9e, 0xc0, 0xfa, 0xf3, 0x3b, 0x5e, 0x3a, 0x5c, 0xb4, 0xea, 0xef, 0xee, 0x38, 0xf8, 0x96, 0x1c, 0x88, 0xb6, 0x6a, 0x2f, 0x19, 0xd4, 0x59, 0x51, 0x96, 0x9c, 0x6d, 0x1f} }, + { (uint64_t)10ull, {0x3, 0x80, 0xdc, 0x24, 0xcc, 0x97, 0xcc, 0xe6, 0x58, 0xc3, 0xa9, 0x47, 0xc5, 0x10, 0x25, 0xde, 0x1a, 0x69, 0x80, 0x3b, 0xdb, 0x50, 0x5, 0xe3, 0xb7, 0xdd, 0xa9, 0xd, 0x68, 0x59, 0xb0, 0x1c} }, + { (uint64_t)20ull, {0x9, 0x3, 0xf6, 0x2e, 0x97, 0x76, 0x47, 0x58, 0xfe, 0xf8, 0x9e, 0x5b, 0xec, 0x29, 0xef, 0x4f, 0xc5, 0xe6, 0x45, 0x4b, 0x2d, 0x47, 0x44, 0x47, 0x36, 0x4, 0x4c, 0x25, 0x2e, 0xe2, 0x8e, 0xba} }, + { (uint64_t)30ull, {0xa2, 0x8b, 0x89, 0xe0, 0xb, 0xed, 0x62, 0x31, 0x68, 0x5b, 0xf9, 0x74, 0x36, 0xf2, 0xba, 0x51, 0xa2, 0x51, 0x55, 0x7f, 0x8d, 0x17, 0xa, 0x78, 0xe3, 0x12, 0xd6, 0x24, 0xbf, 0x60, 0xff, 0xfe} }, + { (uint64_t)40ull, {0xb5, 0xc6, 0x95, 0x55, 0x6a, 0x28, 0x47, 0xb2, 0xe, 0x1c, 0xbb, 0x26, 0xe6, 0xa9, 0xc6, 0x8a, 0x61, 0xc5, 0x50, 0xce, 0xb7, 0xc3, 0x4, 0xfe, 0x92, 0x28, 0x3d, 0x29, 0xa9, 0xb2, 0x43, 0xcb} }, + { (uint64_t)50ull, {0x12, 0x8e, 0xc6, 0xcd, 0xc0, 0x6b, 0x43, 0xc5, 0xd0, 0x9c, 0x3f, 0x65, 0x2a, 0xe3, 0x44, 0x7f, 0x9b, 0x3f, 0x2c, 0x30, 0x91, 0x2d, 0xf0, 0x80, 0x37, 00, 0x85, 0xbc, 0xc, 0x9, 0xef, 0x78} }, + { (uint64_t)60ull, {0x1f, 0x9f, 0x40, 0x3a, 0xae, 0xa7, 0x16, 0xfb, 0xe2, 0x98, 0xa8, 0x14, 0xf1, 0xee, 0xbc, 0x1b, 0x73, 0x16, 0x8c, 0x37, 0xfa, 0xe3, 0x16, 0xeb, 0x65, 0x5, 0x81, 0x6f, 0xc2, 0x20, 0xeb, 0xfb} }, + { (uint64_t)70ull, {0x10, 0xa2, 0x38, 0xc5, 0xe4, 0x8e, 0x4b, 0x93, 0x99, 0xdb, 0xa6, 0xcb, 0xd9, 0x8e, 0x63, 0x54, 0x41, 0x59, 0xe9, 0x8c, 0x93, 0x5a, 0xc0, 0x60, 0x3d, 0x72, 0xde, 0xf, 0xff, 0x31, 0x53, 0xbb} }, + { (uint64_t)80ull, {0x75, 0xab, 0x78, 0xc7, 0x28, 0x1f, 0x69, 0x28, 0xf0, 0x94, 0x86, 0x5, 0x7a, 0x63, 0x64, 0x18, 0x27, 0xc5, 0x74, 0x84, 0xe3, 0xe9, 0x9a, 0x39, 0xf3, 0x12, 0xa4, 0x3a, 0x51, 0x9b, 0xda, 0x8} }, + { (uint64_t)90ull, {0xe9, 0x56, 0x7b, 0xa7, 0x88, 0xb8, 0x5b, 0x82, 0xc8, 0x65, 0x7a, 0x15, 0xa5, 0x48, 0x99, 0x5c, 0xf6, 0xb0, 0xbd, 0xd1, 0xc6, 0x2a, 0xda, 0x77, 0x55, 0xf2, 0x32, 0x3a, 0xd8, 0xa4, 0x8, 0x51} }, + { (uint64_t)100ull, {0xb6, 0x17, 0x36, 0xd5, 0xf2, 0x8d, 0xef, 0x28, 0x61, 0x6a, 0xfc, 0x47, 0x93, 0xe9, 0x9b, 0x27, 0xcd, 0x3e, 0x89, 0xfb, 0x91, 0xc1, 0x13, 0xd4, 0x30, 0x73, 0x65, 0xfb, 0x75, 0xde, 0xdf, 0x88} }, + { (uint64_t)200ull, {0x71, 0x3, 0xeb, 0x72, 0x19, 0x28, 0xd7, 0x91, 0x99, 0x87, 0xf3, 0x50, 0xca, 0xa5, 0x7a, 0xe7, 0xb0, 0x81, 0x57, 0x15, 0x3b, 0x4c, 0x43, 0xd, 0x3e, 0xde, 0xc0, 0xc2, 0x3, 0x7, 0x97, 0x44} }, + { (uint64_t)300ull, {0x24, 0x40, 0x9e, 0x92, 0x2e, 0xce, 0xd1, 0xa0, 0x5e, 0x4e, 0xac, 0xa3, 0xdf, 0x91, 0x19, 0xc3, 0x8a, 0x92, 0x2e, 0xb, 0x66, 0xd0, 0x2d, 0x9d, 0xd2, 0xfb, 0x1d, 0xcc, 0x20, 0xb9, 0xaf, 0xc7} }, + { (uint64_t)400ull, {0xa7, 0x72, 0x9f, 0xa9, 0x32, 0x81, 0x82, 0x99, 0x34, 0x11, 0x5d, 0x47, 0x5a, 0x67, 0x86, 0xa, 0x14, 0x12, 0xc5, 0xe5, 0x95, 0x12, 0x20, 0xd9, 0x60, 0xc2, 0x41, 0xa0, 0x19, 0x1a, 0x9e, 0x65} }, + { (uint64_t)500ull, {0x2e, 0x53, 0xc, 0x6, 0x1c, 0x6d, 0x9e, 0x97, 0xab, 0xaf, 0x46, 0x8c, 0x32, 0xb0, 0xad, 0xa7, 0x49, 0x22, 0x57, 0x72, 0xfc, 0xd1, 0x17, 0x41, 0xcb, 0x5c, 0x3, 0x5c, 0xdd, 0x26, 0x14, 0xe} }, + { (uint64_t)600ull, {0xa5, 0xb, 0x91, 0x9, 0x9d, 0xf1, 0xb1, 0x69, 0x4f, 0x30, 0xb5, 0x8f, 0xe6, 0x77, 0x68, 0x50, 0xdb, 0xdb, 0xf4, 0x6c, 0xed, 0x99, 0x7f, 0x52, 0x62, 0xa8, 0x51, 0x59, 0x40, 0x74, 0xa5, 0x9d} }, + { (uint64_t)700ull, {0x51, 0x2c, 0xf, 0xae, 0xcc, 0xbe, 0xf2, 0xfe, 0xe5, 0x75, 0x4c, 0x6a, 0x45, 0xfd, 0xc0, 0x75, 0x2d, 0x4f, 0x15, 0x22, 0xe7, 0x7f, 0xf0, 0xc4, 0x8d, 0xcb, 0x19, 0x91, 0x8a, 0x68, 0x84, 0xe0} }, + { (uint64_t)800ull, {0xda, 0xa9, 0xf9, 0xa5, 0xb9, 0x71, 0x33, 0x33, 0xe9, 0x8c, 0x5, 0xac, 0xe7, 0x27, 0xcc, 0xe, 0x7d, 0xc3, 0xf1, 0x59, 0x49, 0xe1, 0xef, 0x4d, 0x94, 0xfa, 0x47, 0xd6, 0x8a, 0x34, 0xc6, 0x75} }, + { (uint64_t)900ull, {0xc7, 0x2b, 0x18, 0xc9, 0x17, 0xcd, 0x43, 0xee, 0x78, 0x40, 0x5e, 0x39, 0x83, 0x98, 0xb8, 0x3a, 0xc0, 0x97, 0x7b, 0x25, 0x19, 0x90, 0xd8, 0x13, 0xc, 0x38, 0xba, 0x53, 0xb6, 0x3d, 0xb4, 0xf7} }, + { (uint64_t)1000ull, {0x1, 0xdf, 0x60, 0x91, 0xeb, 0x6a, 0x48, 0xe9, 0xe4, 0x22, 0x25, 0xb, 0xe3, 0x83, 0x88, 0xc8, 0x61, 0xb6, 0x55, 0x55, 0xa7, 0x20, 0xad, 0x15, 0x35, 0x86, 0xfe, 0x2b, 0xd2, 0x2f, 0xa2, 0x3d} }, + { (uint64_t)2000ull, {0x24, 0xf5, 0xb1, 0x34, 0x78, 0x46, 0xaf, 0x22, 0xb5, 0x6f, 0x41, 0x25, 0xb3, 0xe7, 0x67, 0x8c, 0xf8, 0x4b, 0x4f, 0xd2, 0xf9, 0x2e, 0x1c, 0x40, 0xaa, 0x3a, 0x1b, 0xe0, 0xc7, 0x4d, 0x95, 0xe6} }, + { (uint64_t)3000ull, {0xa7, 0x1c, 0x9a, 0x8f, 0x40, 0xc1, 0x25, 0x9c, 0x36, 0x26, 0x27, 0x73, 0xe0, 0x8, 0x20, 0x18, 0x3e, 0x6b, 0x59, 0xe0, 0x71, 0xc9, 0x9b, 0x34, 0x9b, 0xef, 0x8f, 0x7e, 0xd2, 0xc6, 0xad, 0xb9} }, + { (uint64_t)4000ull, {0x98, 0xdc, 0x74, 0xaf, 0x19, 0x89, 0xd3, 0x4b, 0x64, 0x2e, 0xb3, 0x6, 0x2d, 0xbc, 0x9d, 0xca, 0xd8, 0x1, 0xc5, 0x65, 0x27, 0x6, 0x93, 0x99, 0xe7, 0xc4, 0x11, 0xad, 0x14, 0x28, 0x82, 0xf6} }, + { (uint64_t)5000ull, {0x61, 0x76, 0xac, 0x4a, 0xc0, 0x6, 0x5e, 0x49, 0xd6, 0xc4, 0x41, 0xcf, 0x40, 0x4f, 0xad, 0xda, 0xad, 0x44, 0x93, 0xe, 0xf0, 0x3c, 0x68, 0x9, 0xad, 0xd7, 0x77, 0xe4, 0x2f, 0xee, 0x7f, 0x10} }, + { (uint64_t)6000ull, {0x78, 0x79, 0x4, 0x65, 0xf6, 0x60, 0x5b, 0x5a, 0x84, 0x77, 0x36, 0x5a, 0xa6, 0xc2, 0xa4, 0xa5, 0x84, 0x91, 0xc, 0x23, 0x95, 0x2, 0x92, 0x97, 0x52, 0x49, 0xa1, 0xad, 0x7d, 0xf0, 0xf7, 0xe8} }, + { (uint64_t)7000ull, {0x20, 0xa5, 0x60, 0x6b, 0x60, 0x23, 0x95, 0xd6, 0x8e, 0x2f, 0xad, 0x8e, 0xc6, 0x7f, 0x92, 0xde, 0x89, 0xc6, 0x3e, 0x1e, 0x7f, 0xc1, 0xdd, 0x7f, 0x92, 0xff, 0xed, 0xb8, 0xf6, 0x55, 0xfb, 0xd} }, + { (uint64_t)8000ull, {0x9a, 0x78, 0x97, 0x43, 0x98, 0x65, 0x17, 0xd9, 0x5f, 0x4e, 0x80, 0x8b, 0xeb, 0xe6, 0x52, 0xd, 0xe6, 0xcf, 0x8c, 0x51, 0x35, 0xab, 0x36, 0x8, 0x7e, 0x87, 0xe2, 0x76, 0xac, 0x6a, 0x34, 0x1} }, + { (uint64_t)9000ull, {0x5f, 0xc7, 0xaa, 0x48, 0xbb, 0x19, 0x13, 0x58, 0xc7, 0xe3, 0x4d, 0x24, 0xcf, 0x9c, 0x31, 0x16, 0x74, 0x12, 0x7a, 0xb2, 0x45, 0xd0, 0x8f, 0x4e, 0x2c, 0xfd, 0xbf, 0x8f, 0x5, 0xc9, 0x5b, 0xf5} }, + { (uint64_t)10000ull, {0x61, 0x20, 0xe7, 0x76, 0xe9, 0x12, 0xab, 0x10, 0x5a, 0x49, 0xf9, 0xda, 0x2, 0xa6, 0x75, 0x17, 0xc0, 0xa9, 0xb, 0x2b, 0x3e, 0x2d, 0xa3, 0xd, 0xff, 0x34, 0x39, 0x93, 0xdb, 0xec, 0x95, 0x97} }, + { (uint64_t)20000ull, {0x77, 0xbf, 0xb5, 0x37, 0xac, 0xa, 0xbc, 0x41, 0xaa, 0x21, 0xd0, 0xec, 0xd9, 0x18, 0x13, 0x34, 0xd8, 0x6b, 0xa7, 0x86, 0x5a, 0x94, 0x47, 0xf5, 0xc1, 0x58, 0x9a, 0x81, 0xd7, 0xef, 0xb3, 0xbb} }, + { (uint64_t)30000ull, {0x35, 0xf4, 0x5, 0xa9, 0x5f, 0x75, 0x19, 0x2a, 0xe9, 0xc0, 0xd4, 0xf5, 0x88, 0x84, 0x47, 0x14, 0xf6, 0x85, 0x1b, 0x97, 0xce, 0xbd, 0x9f, 0x7c, 0x2, 0xc5, 0xdd, 0xd7, 0xbf, 0x58, 0xff, 0x31} }, + { (uint64_t)40000ull, {0x77, 0x55, 0xbb, 0x3f, 0x38, 0x7c, 0x21, 0xb8, 0xa0, 0xf4, 0x48, 0x1f, 0xbf, 0xa8, 0x8a, 0xbe, 0xee, 0xce, 0xc7, 0x56, 0x53, 0xfc, 0xa1, 0x89, 0x58, 0x39, 0xc1, 0xba, 0x6, 0x47, 0x9f, 0x96} }, + { (uint64_t)50000ull, {0x8b, 0x7e, 0x84, 0xa3, 0x37, 0xb7, 0xb9, 0xcd, 0x5d, 0xb3, 0x63, 0x33, 0x8, 0xad, 0x51, 0x86, 0xa3, 0x59, 0xd, 0xff, 0xb8, 0x23, 0x1e, 0x2f, 0x31, 0xfd, 0x20, 0x42, 0x54, 0x9f, 0xfb, 0xe2} }, + { (uint64_t)60000ull, {0xef, 0xfd, 0xa6, 0x25, 0x15, 0xea, 0xb1, 0xbc, 0x1e, 0xbd, 0x74, 0x92, 0x94, 0x9b, 0x1, 0x22, 0xc3, 0x9f, 0x71, 0xa, 0x65, 0x16, 0xec, 0x66, 0x8c, 0x37, 0x61, 0xe6, 0xcc, 0x36, 0x1f, 0x25} }, + { (uint64_t)70000ull, {0x16, 0xba, 0x89, 00, 0xf3, 0x6f, 0xf, 0x6c, 0x46, 0x1c, 0xb, 0xe7, 0x64, 0xae, 0xee, 0x48, 0x86, 0x6, 0xb0, 0x53, 0xed, 0xdc, 0x10, 0xb5, 0x9a, 0x3e, 0xde, 0xcd, 0x23, 0xd4, 0x4f, 0xc0} }, + { (uint64_t)80000ull, {0x4d, 0xd4, 0x70, 0x3b, 0x7b, 0x7f, 0xcf, 0xe7, 0x2a, 0x2e, 0x4f, 0x31, 0xa4, 0x34, 0x17, 0xf9, 0xc0, 0xda, 0x64, 0x2f, 0xd0, 0xa9, 0x29, 0xb8, 0xf5, 0xed, 0xd8, 0x3, 0x7f, 0x93, 0xc5, 0xb3} }, + { (uint64_t)90000ull, {0x8e, 0xfc, 0x3, 0x20, 0x40, 0xbd, 0x90, 0x41, 0xda, 0x3d, 0xb0, 0x9b, 0xa1, 0x3d, 0xa2, 0xa5, 0xd1, 0xb8, 0x12, 0x3, 0xa, 0x5a, 0x36, 0x7c, 0x58, 0x94, 0xbd, 0x54, 0x11, 0x9, 0xe7, 0x30} }, + { (uint64_t)100000ull, {0xbd, 0x2e, 0xb1, 0x97, 0x83, 0x57, 0x1c, 0xf2, 0x22, 0x2c, 0x81, 0xb, 0x69, 0xf, 0xc7, 0x66, 0x64, 0x57, 0xae, 0x20, 0x92, 0x5b, 0x90, 0x5, 0xce, 0xe6, 0x1d, 0xf2, 0x66, 0x6f, 0xdc, 0xb7} }, + { (uint64_t)200000ull, {0x83, 0xd4, 0xcd, 0xdd, 0xc1, 0x44, 0x87, 0x32, 0xf2, 0x97, 0x7c, 0x41, 0xaa, 0xa7, 0x1f, 0xe6, 0xde, 0x9c, 0x17, 0x6d, 0xa8, 0x99, 0xee, 0xbf, 0xfc, 0x1b, 0xb, 0xa9, 0xea, 0x92, 0x97, 0x90} }, + { (uint64_t)300000ull, {0xcc, 0xc0, 0x6b, 0x44, 0xc3, 0x1, 0x38, 0x6, 0x30, 0x45, 0xed, 0x1, 0xd2, 0x45, 0xd8, 0x14, 0x3, 0xb6, 0x36, 0x52, 0xeb, 0xc4, 0xf9, 0x96, 0x7f, 0xd, 0x7f, 0x38, 0x69, 0x7f, 0x46, 0x16} }, + { (uint64_t)400000ull, {0x1b, 0xbf, 0xe7, 0xe, 0xca, 0xf1, 0xdd, 0xd7, 0xf1, 0x2, 0x36, 0xf6, 0x8a, 0x41, 00, 0xb, 0x5d, 0xab, 0x2d, 0x47, 0x5c, 0xb9, 0x2f, 0x62, 0xc2, 0xd6, 0x84, 0xcf, 0x57, 0x69, 0xfb, 0x84} }, + { (uint64_t)500000ull, {0xf1, 0xb1, 0xcd, 0xaa, 0x78, 0x14, 0x95, 0x36, 0xf, 0x53, 0x31, 0x81, 0xaa, 0x58, 0xc8, 0xbd, 0xae, 0x6a, 0x77, 0x98, 0xd0, 0x2d, 0xab, 0x6d, 0x56, 0x26, 0x81, 0x27, 0x67, 0x9, 0xe7, 0x1} }, + { (uint64_t)600000ull, {0xd5, 0x26, 0x7d, 0x60, 0xd4, 0xfe, 0x9b, 0xc5, 0xfe, 0xfa, 0x7d, 0x3f, 0xe0, 0x7c, 0xd1, 0xfa, 0xd4, 0x55, 0x73, 0xd5, 0xae, 0x19, 0x10, 0xda, 0x7, 0x3e, 0x6d, 0x2d, 0xf9, 0xe2, 0x4, 0x39} }, + { (uint64_t)700000ull, {0xb, 0x58, 0x11, 0x25, 0xc2, 0xc4, 0x83, 0xc9, 0xa3, 0xd8, 0xbc, 0x8, 0x32, 0x2f, 0x26, 0xaa, 0x1f, 0xc5, 0xe, 0x41, 0x53, 0x2c, 0x1b, 0x9d, 0xf6, 0x26, 0xb0, 0x9, 0xd7, 0x88, 0x67, 0xcf} }, + { (uint64_t)800000ull, {0xf5, 0xb3, 0xd1, 0x8f, 0x66, 0xd0, 0xf9, 0x17, 0x5c, 0x30, 0x83, 0xb5, 0xf8, 0x7, 0x8e, 0xaf, 0xa8, 0x9e, 0xf8, 0x1d, 0xe7, 0x15, 0x8, 0xbc, 0x25, 0x1f, 0x5c, 0x5f, 0xe7, 0x25, 0x2e, 0x6} }, + { (uint64_t)900000ull, {0x1, 0xde, 0x40, 0x2c, 0x4b, 00, 0x43, 0x4, 0x2e, 0xae, 0x9e, 0xde, 0xa1, 0x49, 0x2b, 0x9d, 0x82, 0xb7, 0xbc, 0x36, 0x68, 0xe9, 0xb5, 0x84, 0xb0, 0x31, 0x3d, 0x44, 0x50, 0x53, 0x40, 0x74} }, + { (uint64_t)1000000ull, {0x53, 0x4b, 0x85, 0xc7, 0x89, 0x3f, 0x66, 0xf0, 0x26, 0xb6, 0x5e, 0xd7, 0xe7, 0xa4, 0xb8, 0xc9, 0xf4, 0xb, 0xe3, 0x1b, 0xcd, 0xa, 0x3d, 0xcd, 0x27, 0xc4, 0x71, 0x2, 0x56, 0x51, 0x65, 0x3} }, + { (uint64_t)2000000ull, {0xcd, 0xb5, 0xda, 0xfa, 0x53, 0x10, 0xf5, 0x26, 0x2f, 0xfc, 0x9, 0x26, 0xd0, 0xdf, 0x6e, 0xeb, 0xee, 0x2d, 0x52, 0xa9, 0x8d, 0xc6, 0x9f, 0xd, 0xc5, 0xe4, 0xeb, 0xf0, 0xc1, 0xa8, 0x77, 0x2e} }, + { (uint64_t)3000000ull, {0x9e, 0x75, 0x63, 0xf0, 0x33, 0x59, 0xea, 0x31, 0xe2, 0x91, 0xe7, 0xf0, 0xb8, 0x74, 0x17, 0xbc, 0xf5, 0xb2, 0x34, 0xee, 0x8b, 0x7e, 0x5b, 0x4, 0x41, 0x73, 0xbf, 00, 0x46, 0x86, 0x7c, 0x57} }, + { (uint64_t)4000000ull, {0xfd, 0x2a, 0xeb, 0xd, 0x5e, 0xe5, 0x3b, 0x77, 0xf2, 0xb1, 0xe3, 0xac, 0x75, 0x2d, 0x19, 0x38, 0x9f, 0xc5, 0xba, 0xa0, 0xf8, 0xd7, 0x64, 0x48, 0xa5, 0x9f, 0x99, 0x85, 0xa4, 0x8d, 0xa, 0x25} }, + { (uint64_t)5000000ull, {0xc0, 0xbe, 0x4f, 0xb8, 0x77, 0xb9, 0xce, 0x50, 0x87, 0x71, 0x32, 0x3b, 0xcf, 0x1f, 0xb9, 0x48, 0x47, 0x10, 0xee, 0x23, 0x2, 00, 0x6, 0xc3, 0xe8, 0xca, 0xac, 0x6e, 0x4f, 0x2, 0xfa, 0xbf} }, + { (uint64_t)6000000ull, {0xfc, 0x44, 0x5c, 0xa3, 0x84, 0xf3, 0x3e, 0x55, 0x8d, 0xc1, 0x56, 0x44, 0x9d, 0x3f, 0xba, 0x6a, 0xfd, 0x54, 0xc3, 0x42, 0xe6, 0x35, 0x11, 0xf, 0xe7, 0x9c, 0x16, 0xc7, 0x17, 0xf7, 0xd4, 0xf7} }, + { (uint64_t)7000000ull, {0xd8, 0x9, 0x2b, 0x8d, 0x45, 0xdb, 0x54, 0xa5, 0x6d, 0x64, 0xe8, 0x9, 0x4a, 0x6, 0x22, 0xe2, 0x6e, 0x8a, 0x2e, 0xec, 0xb9, 0x3, 0xb2, 0xe1, 0xf7, 0x5a, 0x83, 0x7b, 0x3a, 0xd8, 0x55, 0x4a} }, + { (uint64_t)8000000ull, {0x10, 0x4, 0x5c, 0x91, 0xdb, 0xad, 0x8a, 0x6a, 0x81, 0x62, 0x4a, 0xe0, 0xcf, 0x20, 0x5d, 0xb9, 0x97, 0x3e, 0xe8, 0x42, 0x3e, 0x97, 0xaf, 0x58, 0xa6, 0x1c, 0xfa, 0x7a, 0x78, 0x66, 0xf4, 0x1} }, + { (uint64_t)9000000ull, {0x11, 0x5c, 0x20, 0x9e, 0xe1, 0xde, 0xf3, 0x10, 0xce, 0xc9, 0xa6, 0xd1, 0x6c, 0xe6, 0x27, 0xec, 0xbd, 0xb9, 0xff, 0x2c, 0x23, 0x9, 0x3c, 0x24, 0xc8, 0x6c, 0x1b, 0xf2, 0x50, 0xd4, 0xb5, 0x85} }, + { (uint64_t)10000000ull, {0x2f, 0x99, 0xd9, 0x74, 0x44, 0x18, 0x66, 0x9, 0x49, 0xba, 0x43, 0x35, 0x61, 0xc6, 0x5, 0xb6, 0xf7, 0xbe, 0x8f, 0x82, 0xa, 0x93, 0xcb, 0x2a, 0xed, 0xa9, 0x7c, 0x87, 0x32, 0x92, 0x56, 0x49} }, + { (uint64_t)20000000ull, {0xc6, 0x77, 0x1f, 0xab, 0x14, 0xb, 0x75, 0xf4, 0xef, 0xd0, 0x97, 0xfc, 0xe1, 0x82, 0x6b, 0x80, 0xba, 0xe3, 0x16, 0xbc, 0xec, 0x28, 0x86, 0x9b, 0x3a, 0x1b, 0xf1, 0xbc, 0x6e, 0x4d, 0x20, 0x43} }, + { (uint64_t)30000000ull, {0xa1, 0xe9, 0xed, 0x3e, 0xf6, 0x5a, 0x9d, 0x52, 0x6c, 0xc2, 0x62, 0x5, 0x88, 0x12, 0x1, 0xd8, 0xa8, 0xf2, 0xc4, 0x40, 0x9f, 0xa3, 0x64, 0x10, 0x72, 0x96, 0xb9, 0xf9, 0x6a, 0x61, 0xb3, 0x58} }, + { (uint64_t)40000000ull, {0xb5, 0x31, 0x2d, 0xc7, 0x72, 0x94, 0xab, 0x9b, 0xc8, 0xbf, 0xd1, 0x39, 0x1e, 0x9a, 0xca, 0x92, 0x45, 0xe2, 0x28, 0xf7, 0x4b, 0x49, 0x74, 0xfc, 0x29, 0xad, 0x1c, 0x31, 0xcb, 0xe3, 0xe6, 0xa3} }, + { (uint64_t)50000000ull, {0xb8, 0xab, 0xc9, 0xff, 0xf6, 0x84, 0x1d, 0x2e, 0xa0, 0x13, 0x5a, 0x21, 0x72, 0xd3, 0xa7, 0xb, 0xfc, 0x2b, 0x70, 0x22, 0x8, 0xcd, 0x4a, 0x43, 0xc6, 0x30, 0xbe, 0xb1, 0xb8, 0xa0, 0x32, 0x8b} }, + { (uint64_t)60000000ull, {0x63, 0x90, 0xe1, 0xdb, 0x81, 0xb0, 0xea, 0x5c, 0xe2, 0x73, 0x94, 0x14, 0xe5, 0x2b, 0x7, 0x98, 0xd8, 0x2e, 0xb8, 0xe9, 0xae, 0xc5, 0x6d, 0xfe, 0x7e, 0x2c, 0x64, 0x11, 0xab, 0x79, 0x41, 0x87} }, + { (uint64_t)70000000ull, {0x7e, 0x51, 0xaf, 0xee, 0x5b, 0xc9, 0x71, 0x52, 0x9d, 0x64, 0x4d, 0xcd, 0x7f, 0x2a, 0x2a, 0xb0, 0x26, 0x69, 0xce, 0x2c, 0xb5, 0x7, 0xa6, 0x2d, 0xfc, 0x93, 0x17, 0x6c, 0xb6, 0xdf, 0x41, 0x38} }, + { (uint64_t)80000000ull, {0xf3, 0x7b, 0x94, 0x6b, 0x8b, 0x24, 0x88, 0xeb, 0xee, 0x1c, 0x6, 0xc1, 0x27, 0xfb, 0xe5, 0xfa, 0x5e, 0xfd, 0x62, 0x36, 0x9d, 0xd5, 0xaa, 0xda, 0xed, 0xd8, 0x88, 0x50, 0x1d, 0x3b, 0x7e, 0x3b} }, + { (uint64_t)90000000ull, {0x46, 0xcb, 0x76, 0x57, 0xf6, 0x1c, 0x83, 0x7c, 0xec, 0x80, 0x74, 0xbb, 0xb0, 0xf5, 0x2e, 0x7f, 0xc5, 0x9a, 0xd, 0x94, 0xe0, 0x17, 00, 0x9a, 0xbe, 0x25, 0x65, 0x2e, 0x4a, 0xd2, 0xe5, 0x3d} }, + { (uint64_t)100000000ull, {0x66, 0x7b, 0x8e, 0x6f, 0x6a, 0x4b, 0x91, 0x89, 0x76, 0xd9, 0x73, 0x5a, 0x43, 0x36, 0x7d, 0xc7, 0x59, 0x2c, 0x87, 0xd0, 0xa1, 0xf8, 0x15, 0xc6, 0xe8, 0x7d, 0xf1, 0x1a, 0x13, 0x50, 0x9f, 0xb2} }, + { (uint64_t)200000000ull, {0x3b, 0xcb, 0x51, 0x48, 0x1, 0x64, 0x1b, 0x62, 0x55, 0x93, 0x8c, 0xc5, 0x3, 0x76, 0x2d, 0x35, 0xce, 0x6, 0xd7, 0x5f, 0xe9, 0x50, 0x95, 0x9a, 0x1a, 0xab, 0x21, 0x4b, 0x50, 0x9b, 0x10, 0xb} }, + { (uint64_t)300000000ull, {0xa5, 0x92, 0x6f, 0x3, 0x1e, 0x6b, 0x15, 0xeb, 0x86, 0x23, 0x51, 0x8, 0xab, 0xb1, 0xaf, 0x90, 0xc5, 0xb1, 0x62, 0xc3, 0x99, 0x8c, 0x8b, 0xbb, 0x3f, 0xfb, 0xb0, 0x72, 0x9d, 0xa9, 0x45, 0x7b} }, + { (uint64_t)400000000ull, {0xfe, 0x35, 0xb6, 0x99, 0x44, 0x41, 0xe, 0xaf, 0x81, 0x5b, 0xdc, 0xd0, 0xa4, 0xd7, 0x1e, 0xf9, 0xfc, 0x66, 0x86, 0x48, 0xad, 0x43, 0x74, 0x3b, 0x3, 0x5a, 0xed, 0x2c, 0x17, 0xc1, 0x38, 0x7a} }, + { (uint64_t)500000000ull, {0x22, 0x22, 0xd6, 0x70, 0xb8, 0x7d, 0x9b, 0x47, 0xb8, 0xb9, 0x5c, 0x8c, 0x39, 0x7b, 0xc5, 0x2e, 0x2b, 0x46, 0xa6, 0x48, 0xb0, 0x2, 0xa0, 0x48, 0x5a, 0x37, 0x5c, 0xd8, 0x1f, 0x4a, 0x54, 0x5f} }, + { (uint64_t)600000000ull, {0xd3, 0x23, 0x8a, 0x4a, 0x8b, 0x71, 0xab, 0x46, 0xd1, 0x53, 0x4, 0xac, 0xfa, 0x2f, 0x40, 0xbf, 0x5e, 0xa6, 0x3b, 0x3d, 0x86, 0x4a, 0x79, 0xfa, 0x84, 0x25, 0xd2, 0x65, 0x5a, 0xe7, 0x7, 0x6f} }, + { (uint64_t)700000000ull, {0xa8, 0xff, 0x28, 0x3f, 0xcf, 0xf0, 0x53, 0xd3, 0x44, 0xc8, 0xf7, 0x56, 0x4f, 0x40, 0x24, 0xb6, 0x6b, 0xfa, 0x45, 0x9f, 0x47, 0x6f, 0xd, 0x73, 0xc, 0x91, 0x39, 0x90, 0x8b, 0x2d, 0x64, 0x7e} }, + { (uint64_t)800000000ull, {0xf2, 0xda, 0xf8, 0x88, 0xc4, 0x46, 0x57, 0x1, 0xc0, 0xe6, 0x1e, 0x12, 0xc3, 0xfb, 0xd4, 0xea, 0x79, 0xc7, 0xec, 0xb4, 0xf0, 0xc4, 0xb1, 0x54, 0xc5, 0x1a, 0x24, 0xd1, 0xe9, 0x21, 0x28, 0xba} }, + { (uint64_t)900000000ull, {0x11, 0x6a, 0xe5, 0xd2, 0x9c, 0xec, 0x72, 0xaa, 0xc5, 0x57, 0xcb, 0x14, 0xe2, 0xcd, 0xd5, 0x53, 0xe5, 0x88, 0xff, 0x8b, 0x81, 0x78, 0x26, 0x1, 0x99, 0xc4, 0xc, 0xae, 0xa2, 0x12, 0xcb, 0x63} }, + { (uint64_t)1000000000ull, {0x8c, 0xe6, 0x48, 0x33, 0xce, 0xc9, 00, 0xcb, 0x6d, 0x5a, 0xc4, 0x6f, 0xc0, 0x23, 0x7d, 0x8f, 0x24, 0x39, 0xc3, 0xdf, 0xa2, 0x38, 0xba, 0xf9, 0xcc, 0x94, 0x16, 0x6a, 0xd2, 0xe8, 0x98, 0x87} }, + { (uint64_t)2000000000ull, {0x37, 0x8d, 0x3c, 0x5d, 0xbb, 0xa4, 0x82, 0x3d, 0x33, 0x12, 0xbb, 0x61, 0xfc, 0x6, 0x75, 0xa1, 0xbb, 0x39, 0x89, 0xf3, 0x97, 0x1, 0xeb, 0xd, 0x5c, 0xe4, 0xde, 0x5b, 0xd, 0x90, 0x74, 0x72} }, + { (uint64_t)3000000000ull, {0x7f, 0xa2, 0xd0, 0xa5, 0x99, 0xe7, 0x97, 0x2e, 0x74, 0xcb, 0x75, 0xf9, 0x8a, 0xf4, 0x84, 0xfc, 0x85, 0x19, 0xcb, 0x7e, 0x25, 0xb9, 0x84, 0xa7, 0x6d, 0x8b, 0xc2, 0xba, 0x8d, 0xaf, 0xde, 0xd8} }, + { (uint64_t)4000000000ull, {0xda, 0x3a, 0xcb, 00, 0xab, 0x2d, 0x8d, 0xcc, 0xac, 0xec, 0x8f, 0x77, 0x59, 0x21, 0xc4, 0xe, 0x26, 0xb1, 0xff, 0xbe, 0xca, 0x9e, 0xb7, 0xe6, 0x57, 0x25, 0x6f, 0x59, 0x68, 0xf2, 0x34, 0x1c} }, + { (uint64_t)5000000000ull, {0x34, 0x6, 0xd7, 0x9a, 0x50, 0xd8, 0x14, 0xa9, 0xcc, 0xed, 0x3b, 0x24, 0x4, 0xed, 0x3e, 0x1b, 0x8d, 0xa6, 0x21, 0x98, 0x8c, 0x43, 0xb1, 0x93, 0x69, 0x42, 0xf4, 0x94, 0xa, 0xc5, 0xbf, 0x6a} }, + { (uint64_t)6000000000ull, {0xf8, 0x3e, 0xe8, 0xc1, 0x62, 0xfc, 0x52, 0xa0, 0x8, 0x9f, 0x46, 0xe8, 0x29, 0xc2, 0xea, 0xf6, 0xa1, 0x9f, 0xd5, 0x96, 0xcd, 0x12, 0xb3, 0xe8, 0x19, 0xd5, 0x67, 0x69, 0x44, 0xf, 0x7b, 0x4e} }, + { (uint64_t)7000000000ull, {0x8c, 0x72, 0x7d, 0x24, 0x57, 0xf3, 0x4b, 0x2f, 0xdb, 0x6a, 0xdf, 0x69, 0x1a, 0xb3, 0x5f, 0xaa, 0xe4, 0xff, 0x23, 0x4c, 0x28, 0xb4, 0x4e, 0x9f, 0xd3, 0x71, 0x8e, 0xef, 0xec, 0x41, 0x75, 0x80} }, + { (uint64_t)8000000000ull, {0x4a, 0x2e, 0x2f, 0x76, 0xe3, 0x5d, 0xcb, 0xa8, 0x97, 0xa3, 0xae, 0x72, 0xc4, 0x27, 0xd, 0x9c, 0x13, 0x17, 0x14, 0xed, 0x19, 0x1b, 0x55, 0x5c, 0x5e, 0x1, 0xe4, 0x75, 0x7c, 0xba, 0xe7, 0x2c} }, + { (uint64_t)9000000000ull, {0x3f, 0x9f, 0xc, 0x4, 0xc0, 0xb9, 0xec, 0x9b, 0x4d, 0x11, 0x7c, 0x5f, 0xc9, 0xf1, 0x8a, 0x20, 0xf2, 0xb3, 0xfa, 0xcc, 0xa4, 0xc8, 0xae, 0x41, 0xaf, 0x7c, 0x8, 0xe9, 0xe0, 0xef, 0xb9, 0x81} }, + { (uint64_t)10000000000ull, {0x97, 0xc9, 0x2a, 0x29, 0x1, 0x5e, 0xcb, 0x49, 0xf8, 0x9, 0x5, 0x45, 0xe0, 0x1f, 0xf9, 0x78, 0x6c, 0xae, 0x40, 0x57, 0x73, 0x47, 0x61, 0x18, 0x24, 0xf4, 0xb6, 0x59, 0x9f, 0xf5, 0xd3, 0x64} }, + { (uint64_t)20000000000ull, {0x9, 0xba, 0xed, 0x9a, 0x3c, 0x44, 0xb2, 0x22, 0x85, 0xa0, 0xae, 0xa4, 0x14, 0x8c, 0xa7, 0xde, 0x9b, 0xea, 0x96, 0x3c, 0xf6, 0x96, 0x23, 0xb6, 0x83, 0x44, 0x5c, 0xa, 0x10, 0xa5, 0x86, 0x77} }, + { (uint64_t)30000000000ull, {0x45, 0xac, 0xaf, 0x1d, 0xe2, 0x89, 0x6d, 0xe8, 0x72, 0x84, 0xff, 0xed, 0x57, 0x8b, 0x77, 0x14, 0xf5, 0x18, 0xa6, 0x18, 0xe2, 0xae, 0x6f, 0x90, 0xae, 0x4f, 0x70, 0x13, 0xa2, 0x8e, 0x99, 0xe0} }, + { (uint64_t)40000000000ull, {0x8, 0xb8, 0x47, 0x36, 0x42, 0x24, 0xe2, 0x9c, 0xe3, 0x36, 0x63, 0x93, 0xc2, 0xe1, 0x1e, 0xfc, 0x75, 0x55, 0xde, 0xe1, 0xa0, 0x5f, 0x91, 0xa7, 0x2e, 0x61, 0x11, 0x76, 0x84, 0xdd, 0xbe, 0x29} }, + { (uint64_t)50000000000ull, {0x6c, 0x8e, 0xe, 0x4a, 0x63, 0x4f, 0x85, 0x9a, 0x31, 0xab, 0x2f, 0x7a, 0x78, 0xc0, 0xc4, 0xa5, 0x93, 0x8c, 0xb7, 0x7f, 0x3, 0x35, 0x50, 0xa4, 0x7d, 0x7e, 0x31, 0x81, 0xb6, 0xb2, 0x6e, 0xc0} }, + { (uint64_t)60000000000ull, {0x66, 0xc2, 0xa0, 0x9, 0x65, 0xf9, 0xbf, 0xcb, 0xb1, 0x1e, 0xa0, 0x3c, 0xf1, 0xd6, 0x31, 0xb0, 0xe, 0x8a, 0x1e, 0xf7, 0xa6, 0xb, 0x1b, 0xe4, 0xa5, 0xac, 0x9, 0x23, 0xb, 0xf8, 0x17, 0x3f} }, + { (uint64_t)70000000000ull, {0x63, 0x51, 0xd7, 0x74, 0xc0, 0x2c, 0x5a, 0x9d, 0xee, 0xcf, 0xdb, 0xab, 0x70, 0x96, 0x68, 0x59, 0x8c, 0x47, 0xe4, 0xb1, 0x78, 0x2c, 0xe5, 0xae, 0x31, 0x6a, 0xf7, 0x40, 0xa6, 0x6f, 0x7e, 0x30} }, + { (uint64_t)80000000000ull, {0x5a, 0xcc, 0xfd, 0x16, 0x22, 0x79, 0xa5, 0x1c, 0x8b, 0x3b, 0xd5, 0xd3, 0x67, 0x9e, 0x91, 0x89, 0x67, 0xa2, 0x64, 0xea, 0x6, 0x3d, 0x37, 0xdf, 0xf5, 0xe3, 0x45, 0x7e, 0xc3, 0x7, 0xd4, 0x57} }, + { (uint64_t)90000000000ull, {0xb7, 0x47, 0xfc, 0x1, 0xc6, 0xf0, 0xc7, 0x49, 0x67, 0x3a, 0x29, 0x10, 0x25, 0xc, 0x2e, 0x23, 0xcb, 0x38, 0x27, 0x4d, 0x63, 0xb4, 0x2f, 0x52, 0x1b, 0x84, 0x63, 0x56, 0xe4, 0x13, 0x61, 0x8f} }, + { (uint64_t)100000000000ull, {0x9, 0x42, 0x84, 0x3d, 0x6f, 0x69, 0xe1, 0xcf, 0x3d, 0x99, 0xc9, 0x9f, 0xc, 0x97, 0xc0, 0xe6, 0xe5, 0x78, 0x93, 0x5a, 0xf6, 0xa8, 0xbd, 0xb8, 0xf8, 0x1d, 0x5b, 0x90, 0xbd, 0xe7, 0xcc, 0x10} }, + { (uint64_t)200000000000ull, {0x56, 0x4c, 0x64, 0xea, 0x50, 0xe4, 0xbd, 0x20, 0xdb, 0x58, 0x5d, 0xb5, 0x87, 0xb1, 0xf7, 0x64, 0xa2, 0x62, 0xd8, 0x46, 0xa6, 0xb0, 0xa2, 0x4b, 0x43, 0x27, 0x60, 0xd2, 0xf9, 0xde, 0x66, 0x5b} }, + { (uint64_t)300000000000ull, {0xac, 0x65, 0x83, 0x41, 0x5b, 0xd6, 0x4c, 0x3, 0x35, 0x97, 0xf9, 0x28, 0xa4, 0xb5, 0xd4, 0xf4, 0x78, 0x9e, 0xa8, 0xb2, 0x87, 0x82, 0x73, 0x89, 0xa8, 0x1e, 0xb6, 0x62, 0x9e, 0xc5, 0xb8, 0x50} }, + { (uint64_t)400000000000ull, {0x52, 0xf4, 0x9d, 0x89, 0xcf, 0x74, 0x13, 0x2f, 0xc7, 0x43, 0x2e, 0x6a, 0x6b, 0xef, 0xcf, 0xf3, 0xfd, 0x13, 0xd6, 0x3b, 0x51, 0x60, 0xab, 0x1c, 0xe6, 0x4a, 0xb0, 0xd1, 0x21, 0xcd, 0xa9, 0x9a} }, + { (uint64_t)500000000000ull, {0xe9, 0xaa, 0x7c, 0x81, 0xcd, 0xb5, 0xb3, 0x14, 0x8f, 0xb7, 0x62, 0x80, 0x63, 0xcd, 0x7a, 0x7, 0xd1, 0xad, 0xd1, 0x64, 0x3c, 0xed, 0xd3, 0xfa, 0x34, 0x47, 0x9d, 0x85, 0x9c, 0xc5, 0x62, 0x65} }, + { (uint64_t)600000000000ull, {0x98, 0x27, 0xae, 0x31, 0xe5, 0xc2, 0xa7, 0x78, 0x39, 0xf6, 0xb, 0x83, 0xab, 0x45, 0x78, 0xe2, 0xa0, 0x1e, 0xfa, 0x4b, 0x3b, 0x14, 0xcc, 0x72, 0x73, 0x14, 0xff, 0xd7, 0x15, 0x53, 0x63, 0xbf} }, + { (uint64_t)700000000000ull, {0x72, 0x91, 0x6a, 0x79, 0x27, 0xff, 0x13, 0x24, 0xd4, 0x98, 0x40, 0xec, 0xc0, 0x98, 0x68, 0xb8, 0xf3, 0x15, 0xe4, 0xf1, 0xf6, 0xd4, 0x45, 0x8d, 0x37, 0x5e, 0xc7, 0x45, 0xfc, 0x2e, 0x63, 0x53} }, + { (uint64_t)800000000000ull, {0x66, 0x76, 0xe0, 0x4, 0xf, 0xa4, 0xb8, 0x22, 0x9c, 0x61, 0x69, 0xc, 0x71, 0x32, 0x22, 0xcf, 0x3d, 0x37, 0xb9, 0x49, 0x3b, 0x49, 0x6, 0x80, 0xbb, 0x48, 0xd8, 0xd5, 0x1a, 0xde, 0x95, 0xf2} }, + { (uint64_t)900000000000ull, {0x41, 0x54, 0xb3, 0x46, 0x5a, 0x43, 0x72, 0x67, 0x1e, 0xa9, 0xe0, 0x64, 0xa7, 0xca, 0xa6, 0x6e, 0x14, 0xb4, 0x98, 0x6a, 0x46, 0x68, 0x91, 0x8a, 0xfa, 0x57, 0x9b, 0xf1, 0xed, 0x25, 0x6, 0xdd} }, + { (uint64_t)1000000000000ull, {0xbb, 0x6f, 0x70, 0x62, 0xca, 0x30, 0x6d, 0x67, 0x2a, 0x73, 0xe, 0x2a, 0x2f, 0x21, 0x9b, 0xdb, 0xe4, 0xc, 0x9f, 0xb3, 0xfe, 0x4d, 0x60, 0x13, 0x69, 0x2a, 0xf9, 0x3c, 0xdb, 0x2e, 0xc, 0xd1} }, + { (uint64_t)2000000000000ull, {0xbc, 0xe, 0xae, 0x5b, 0x9c, 0x6a, 0xd6, 0x38, 0x7a, 0x41, 0x19, 0x3c, 0x46, 0xf3, 0xc1, 0xd0, 0x71, 0x6d, 0x77, 0xd6, 0x4e, 0x22, 0xb2, 0xe0, 0x7b, 0x4b, 0xce, 0x75, 0x67, 0x65, 0xa2, 0xb} }, + { (uint64_t)3000000000000ull, {0x10, 0xc, 0x6f, 0x13, 0x42, 0xb7, 0x1b, 0x73, 0xed, 0xdd, 0xc5, 0x49, 0x2b, 0xe9, 0x23, 0x18, 0x2f, 00, 0xa6, 0x83, 0x48, 0x8e, 0xc3, 0xa2, 0xa1, 0xc7, 0xa9, 0x49, 0xcb, 0xe5, 0x77, 0x68} }, + { (uint64_t)4000000000000ull, {0x41, 0x9f, 0x7c, 0x94, 0x91, 0x4, 0x34, 0xf, 0xd3, 0xce, 0x85, 0x94, 0x8d, 0x2e, 0xf9, 0xf0, 0xdd, 0x4b, 0xb3, 0xd9, 0x2f, 0x5a, 0x78, 0x2c, 0x5f, 0x78, 0x4, 0xb7, 0x52, 0x9a, 0x13, 0xc6} }, + { (uint64_t)5000000000000ull, {0x40, 0x65, 0x34, 0x98, 0xbe, 0xa0, 0x22, 0xe3, 0x36, 0x5a, 0x3, 0xe5, 0x75, 0x25, 0xba, 0x65, 0x96, 0x53, 0x76, 0x24, 0x4f, 0xff, 0x10, 0x73, 0xe, 0xd9, 0x7a, 0x73, 0xb7, 0x53, 0x1, 0x91} }, + { (uint64_t)6000000000000ull, {0xdb, 0x1c, 0x7c, 0xf6, 0x8, 0x91, 0xf9, 0x65, 0xeb, 0xa9, 0xc6, 0x2, 0x24, 00, 0x63, 0xe, 00, 0x47, 0x95, 0x34, 0xe6, 0xf5, 0xb5, 0x33, 0xdc, 0xfc, 0x83, 0x19, 0x38, 0x52, 0x2c, 0x78} }, + { (uint64_t)7000000000000ull, {0x59, 0xa0, 0x3a, 0x31, 0x53, 0xa9, 0x94, 0xd7, 0x23, 0x27, 0xe4, 0xd9, 0x24, 0x21, 0xd3, 0xe3, 0x29, 0x1b, 0x1f, 0xa1, 0xb2, 0x40, 0xde, 0x44, 0xb9, 0x2d, 0x7f, 0x62, 0xec, 0x1, 0x28, 0xf1} }, + { (uint64_t)8000000000000ull, {0xb2, 0x80, 0xb9, 0x3b, 0x1e, 0x43, 0x88, 00, 0x73, 0xea, 0x4a, 0xa0, 0xef, 0x11, 0x4, 0xf8, 0x24, 0xbd, 0x12, 0x7a, 0x4a, 0x3d, 0xa2, 0x13, 0x92, 0x65, 0xf, 0xe8, 0xc6, 0x55, 0xb6, 0xc5} }, + { (uint64_t)9000000000000ull, {0xda, 0xf0, 0xd3, 0xe9, 0x32, 0x17, 0xd8, 0xe9, 0x5a, 0xbf, 0xdd, 0xf1, 0x3b, 0x7f, 0xd4, 0x8e, 0x34, 0x47, 0xad, 0x9, 0x23, 0x26, 0xb8, 0x99, 0xed, 0x58, 0x1f, 0xd5, 0xf8, 0x6, 0xc5, 0x6} }, + { (uint64_t)10000000000000ull, {0x16, 0x3d, 0xd6, 0x82, 0xec, 0x97, 0x7c, 0xdd, 0xa5, 0x95, 0x31, 0xda, 0x3f, 0xfa, 0x72, 0x99, 0x8a, 0x6f, 0x88, 0x37, 0xab, 0xad, 0xc6, 0x36, 0xaa, 0xed, 0xc8, 0xbe, 0x19, 0xb2, 0xd7, 0xc7} }, + { (uint64_t)20000000000000ull, {0x2, 0xfa, 0x35, 0x3a, 0xa8, 0x4e, 0xa8, 0xc4, 0x4c, 0x80, 0x23, 0x6, 0x5d, 0x79, 0x41, 0x60, 0x6b, 0x1f, 0xa5, 0xc2, 0x64, 0xdc, 0xcf, 0x46, 0xdc, 0x64, 0x94, 0xeb, 0xe9, 0x60, 0x6f, 0x20} }, + { (uint64_t)30000000000000ull, {0x87, 0x5, 0xd, 0xab, 0xf5, 0xb2, 0x3e, 0x8b, 0x79, 0x81, 0x3f, 0x4e, 0xd7, 0x6a, 0xa4, 0xad, 0xd2, 0x25, 0xdd, 0x2a, 0x50, 0x89, 0xaf, 0x6, 0x7d, 0xa7, 0x7c, 0xcb, 0x6e, 0xc5, 0x59, 0x46} }, + { (uint64_t)40000000000000ull, {0xaa, 0xe6, 0xb2, 0xc8, 0xa2, 0x9e, 0x4d, 0xbc, 0x63, 0x76, 0xc1, 0x72, 0x5, 0xfb, 0x2, 0x85, 0xe7, 0xd7, 0xd3, 0x25, 0x32, 0x3c, 0xd5, 0x26, 0xf, 0x98, 0xad, 0xff, 0xf7, 0xd4, 0xd4, 0xfb} }, + { (uint64_t)50000000000000ull, {0x9d, 0x79, 0x28, 0x82, 0x12, 0xa1, 0xe2, 0x3c, 0x9, 0x9f, 0xb2, 0xd8, 0xf0, 0xd0, 0xdb, 0xd3, 0xc2, 0xec, 0xd7, 0x58, 0xb9, 0xe6, 0xb5, 0xb4, 0xf2, 0x90, 0x60, 0x7, 0x9f, 0x19, 0x66, 0x9f} }, + { (uint64_t)60000000000000ull, {0x18, 0x90, 0x10, 0x6f, 0x1b, 0x97, 0xbc, 0x2d, 0xa, 0xe3, 0x96, 0xe5, 0xe5, 0x5e, 0xbf, 0xcc, 0x8e, 0xf6, 0x91, 0x7f, 0xb1, 0x96, 0xcb, 0x2b, 0x1e, 0x80, 0x25, 0x5d, 0x54, 0xb6, 0x87, 0x10} }, + { (uint64_t)70000000000000ull, {0x57, 0xd3, 0x4e, 0xf7, 0x54, 0x3b, 0xe4, 0x7b, 0x7b, 0xf4, 0x97, 0xce, 0x4a, 0x17, 0x6e, 0x78, 0xc6, 0xd6, 0x5c, 0xd3, 0x27, 0xf6, 0x4b, 0xa7, 0x5c, 0x27, 0xd1, 0x57, 0xb3, 0x37, 0x12, 0x5d} }, + { (uint64_t)80000000000000ull, {0x5e, 0xcb, 0x10, 0x15, 0x4b, 0x96, 0xca, 0xb5, 0x5e, 0x9, 0x46, 0x83, 0xf8, 0xdb, 0xff, 0x7f, 0x56, 0x63, 0x5f, 0xa6, 0x64, 0x97, 0xee, 0x9e, 0x24, 0xe, 0x83, 0x63, 0x7c, 0x7c, 0x87, 0x72} }, + { (uint64_t)90000000000000ull, {0x42, 0x32, 0x69, 0x98, 0x51, 0x30, 0xf1, 0x66, 0x51, 0x6a, 0x5b, 0xa8, 0x61, 0x9, 0x6d, 0x72, 0xec, 0xcc, 0x67, 0xad, 0xab, 0xa4, 0x5e, 0xb3, 0x73, 0x9a, 0xe, 0xbc, 0x61, 0xa3, 0x20, 0xae} }, + { (uint64_t)100000000000000ull, {0xa8, 0xd1, 0x60, 0x95, 0x91, 0x49, 0x8f, 0xa7, 0xc2, 0x94, 0x27, 0xad, 0x89, 0x31, 0xaf, 0x36, 0xc5, 0x2d, 0xc9, 0x7b, 0x4a, 0x11, 0xe7, 0x47, 0xa9, 0x56, 0xc2, 0x8c, 0x42, 0x54, 0xcf, 0xd4} }, + { (uint64_t)200000000000000ull, {0x23, 0x14, 0x49, 00, 0xa8, 0x66, 0xe8, 0xc1, 0xbf, 0x40, 0x98, 0xda, 0xa9, 0x48, 0xb9, 0x86, 0xf3, 0x84, 0xe, 0x5a, 0x7d, 0x21, 0x5e, 0xf0, 0xd5, 0x64, 0xef, 0xd8, 0xbe, 0xc6, 0x83, 0x15} }, + { (uint64_t)300000000000000ull, {0x6a, 0x51, 0x47, 0x3c, 0x86, 0xed, 0xad, 0x53, 0x51, 0x4b, 0x3f, 0x95, 0x97, 0xed, 0x21, 0xae, 00, 0x81, 0x51, 0xa0, 0x9e, 0x43, 0xad, 0xdd, 0x45, 0xd1, 0x74, 0x63, 0xc5, 0x34, 0x3, 0x97} }, + { (uint64_t)400000000000000ull, {0x8, 0xbd, 0xd4, 0xc3, 0xe4, 0x53, 0x1b, 0x29, 0x7a, 0x70, 00, 0x1e, 0xb8, 0xa4, 0xf1, 0x98, 0xdc, 0x3b, 0xd4, 0xf1, 0xf5, 0x60, 0x9a, 0xda, 0x98, 0xf6, 0xd9, 0x5f, 0x9a, 0x1a, 0x30, 0x2e} }, + { (uint64_t)500000000000000ull, {0x97, 0x55, 0x70, 0xea, 0x12, 0xde, 0x5a, 0xf5, 0xc5, 0x36, 0xbd, 0xb6, 0x83, 0x54, 0xfb, 0xc8, 0x32, 0x21, 0x50, 0xfc, 0x56, 0x83, 0x7c, 0x4b, 0x78, 0xa9, 0x85, 0x76, 0x5d, 0x2a, 0x70, 0x99} }, + { (uint64_t)600000000000000ull, {0xa7, 0xa6, 0x39, 0x93, 0x41, 0xcb, 0x4d, 0x67, 0x76, 0xcd, 0x94, 0xd, 0x1d, 0x6a, 0xb0, 0xac, 0xa, 0xbf, 0x56, 0x93, 0x6a, 0x35, 0x31, 0xdf, 0xe9, 0x6c, 0x23, 0x69, 0x97, 0x8e, 0x49, 0xfa} }, + { (uint64_t)700000000000000ull, {0x55, 0x9, 0x3e, 0x5e, 0xeb, 0xca, 0x3, 0x88, 0x48, 0xdc, 0x99, 0x7e, 0x31, 0x95, 0xec, 0xc5, 0x8f, 0xb4, 0xa5, 0x71, 0xb9, 0x52, 0x56, 0xc0, 0xff, 0x49, 0xbe, 0xd0, 0xf1, 0x65, 0x22, 0xbd} }, + { (uint64_t)800000000000000ull, {0xbb, 0xc6, 0x18, 0x2, 0x24, 0xaf, 0xd3, 0x38, 0xa6, 0xf4, 0xa0, 0x6b, 0x11, 0x98, 0x40, 0x68, 0xeb, 0x36, 0x35, 0xe7, 0xe5, 0x47, 0x66, 0x69, 0x78, 0x83, 0xaf, 0xbd, 0xce, 0xad, 0x2f, 0x31} }, + { (uint64_t)900000000000000ull, {0x61, 0x3a, 0xa1, 0x2c, 0xc0, 0xa1, 0x9b, 0xc8, 0x43, 0x63, 0x50, 0xbb, 0xc0, 0xf6, 0x16, 0x32, 0x6e, 0x64, 0x85, 0x83, 0x33, 0x4a, 0x32, 0x65, 0x16, 0x29, 0xe9, 0x5, 0xc5, 0x20, 0x62, 0x69} }, + { (uint64_t)1000000000000000ull, {0x52, 0xdd, 0xf8, 0x81, 0x13, 0xa0, 0xfc, 0xf2, 0x12, 0x90, 0x95, 0xc6, 0x18, 0x91, 0xbe, 0x88, 0x5c, 0x9, 0x30, 0x8, 0xeb, 0xc4, 0x65, 0xc, 0xb0, 0xee, 0xa5, 0x60, 0xcd, 0x4d, 0x75, 0x1b} }, + { (uint64_t)2000000000000000ull, {0x75, 0xbd, 0xfc, 0x35, 0xa6, 0xdf, 0x76, 0xe5, 0x98, 0x8e, 0xd9, 0xe3, 0x10, 0xa5, 0x89, 0x16, 0xae, 0xf0, 0xc5, 0xf0, 0x5b, 0x89, 0x22, 0xea, 0xae, 0x2c, 0xf9, 0x8f, 0x58, 0x42, 0x3c, 0xe3} }, + { (uint64_t)3000000000000000ull, {0x88, 0x98, 0x93, 0xe8, 0x7d, 0x56, 0x9f, 0x14, 0xb2, 0x48, 0xd1, 0xed, 0x93, 0xe8, 0xce, 0x60, 0xbb, 0xe3, 0x73, 0x69, 0xb0, 0xd6, 0xc7, 0xa1, 0x86, 0x89, 0x33, 0xd3, 0xc3, 0xda, 0x9a, 0x72} }, + { (uint64_t)4000000000000000ull, {0x88, 0x3e, 0xf3, 0x4b, 0xa2, 0xc1, 0x91, 0xf4, 0x9d, 0x3c, 0xc6, 0xad, 0xa0, 0xaf, 0xf1, 0xcf, 0xb1, 0x77, 0xbd, 0x9e, 0xd4, 0xb3, 0xa5, 0x37, 0x84, 0xb7, 0xf1, 0x62, 0x9b, 0xed, 0x17, 0x41} }, + { (uint64_t)5000000000000000ull, {0xa2, 0x90, 0x7c, 0x39, 0x84, 0xb1, 0x4a, 0xb1, 0xf4, 0xda, 0x58, 0xc2, 0xc8, 0x2d, 0x6b, 0x24, 0xf1, 0x29, 0x49, 0x9, 0x75, 0xfc, 0x4a, 0x33, 0x3d, 0x25, 0xa1, 0xf9, 0x2b, 0xc4, 0x32, 0xb6} }, + { (uint64_t)6000000000000000ull, {0xa0, 0x7d, 0x9f, 0x18, 0x95, 0x1f, 0xf2, 0x32, 0xcf, 0x4e, 0xc0, 0xee, 0x2f, 0xbc, 0xc3, 0xe1, 0x1b, 0x2c, 0xaf, 0xc9, 0x57, 0x65, 0x82, 0x10, 0x38, 0x1e, 0x3e, 0xe4, 0xed, 0xec, 0x2e, 0x7a} }, + { (uint64_t)7000000000000000ull, {0x66, 0x80, 0x21, 0xd5, 0xde, 0x8c, 0xa4, 0xc1, 0x8f, 0x5a, 0x74, 0xf2, 0x78, 0x69, 0xc4, 0xd6, 0xd4, 0x93, 0xa3, 0x30, 0x39, 0x3c, 0xf0, 0x26, 0x41, 0xff, 0xa8, 0x56, 0x7b, 0xa5, 0x36, 0x20} }, + { (uint64_t)8000000000000000ull, {0xe0, 0x48, 0x7a, 0xc4, 0x5a, 0x82, 0x59, 0xe3, 0xe5, 0xf2, 0xd9, 0xb8, 0xf6, 0xb8, 0xfa, 0x26, 0x9a, 0x63, 0x49, 0x71, 0xa2, 0xf7, 0xc2, 0x1a, 0x54, 0x17, 0x76, 0x81, 0xeb, 0x2, 0xbd, 0x4a} }, + { (uint64_t)9000000000000000ull, {0x98, 0x92, 0x6a, 0x3a, 0xf0, 0x5b, 0xf4, 0xa9, 0x8d, 0xf9, 0xf6, 0x4a, 0xe7, 0xb9, 0xda, 0x45, 0xa7, 0x6, 0xc3, 0xf8, 0x39, 0x5e, 0x47, 0x1f, 0x96, 0xed, 0x3c, 0x6, 0x6, 0xbe, 0xbb, 0x71} }, + { (uint64_t)10000000000000000ull, {0x80, 0xad, 0xb7, 0xd, 0x46, 0xf6, 0x3a, 0x75, 0x64, 0xa3, 0xf6, 0x71, 0xd9, 0xba, 0x95, 0x71, 0xb7, 0xf7, 0x95, 0xa9, 0x63, 0x38, 0x2a, 0x4d, 0x9f, 0xaf, 0x2d, 0x54, 0xf6, 0xc6, 0x84, 0x29} }, + { (uint64_t)20000000000000000ull, {0xae, 0xbd, 0x97, 0x42, 0x1f, 0x3f, 0xca, 0xe8, 0x95, 0x18, 0x60, 0xe6, 0xd9, 0xd1, 0xf3, 0xec, 0x59, 0x73, 0xa2, 0xf7, 0x66, 0x88, 0x4b, 0xfe, 0x17, 0x50, 0x79, 0x51, 0xe4, 0x62, 0xc6, 0x63} }, + { (uint64_t)30000000000000000ull, {0x61, 0x2, 0x6c, 0x84, 0x2a, 0x6a, 0x22, 0x25, 0x74, 0x6b, 0x19, 0x6b, 0x56, 0x89, 0xe1, 0x18, 0xf5, 0x41, 0x34, 0x15, 0x98, 0x1d, 0x7, 0x73, 0x62, 0xb2, 0xe7, 0xb9, 0xac, 0xa5, 0x28, 0x16} }, + { (uint64_t)40000000000000000ull, {0x52, 0x54, 0xb5, 0x78, 0xe8, 0x57, 0x9a, 0x27, 0x3b, 0x89, 0x8e, 0x65, 0x9d, 0xd3, 0xe1, 0xa1, 0xcf, 0xba, 0x12, 0x47, 0x26, 0x64, 0xbd, 0x4e, 0x7f, 0x9a, 0x13, 0xb1, 0xfc, 0xee, 0x2, 0x93} }, + { (uint64_t)50000000000000000ull, {0x7b, 0x2a, 0xb, 00, 0xcf, 0xdc, 0xa9, 0x51, 0x46, 0xcf, 0x80, 0x95, 0xdd, 0x2b, 0x82, 0x90, 0x91, 0xb0, 0xf2, 0xd5, 0xbb, 0xc, 0x33, 0x82, 0x2d, 0x8b, 0x43, 0x42, 0x69, 0xcd, 0x2a, 0x42} }, + { (uint64_t)60000000000000000ull, {0x21, 0x57, 0x4f, 0xed, 0x15, 0x1a, 0x2f, 0x9f, 0x64, 0xa4, 0x5b, 0xe2, 0x8a, 0x3a, 0xf5, 0x88, 0xe9, 0xf2, 0xd1, 0x71, 0x35, 0xa3, 0x53, 0x7f, 0x7, 0xfd, 0x6a, 0xef, 0xa2, 0x9f, 0x2, 0xaf} }, + { (uint64_t)70000000000000000ull, {0x1a, 0xf2, 0x41, 0xe1, 0x38, 0x27, 0x98, 0x29, 0xac, 0x6a, 0xe6, 0x2f, 0xf, 0x33, 0x20, 0x4b, 0xb2, 0x8a, 0xfd, 0x6, 0x5c, 0x42, 0x59, 0x3b, 0xdc, 0x79, 0x14, 0x85, 0x97, 0x5b, 0x26, 0x95} }, + { (uint64_t)80000000000000000ull, {0xa8, 0xc8, 0xb8, 0x7b, 0x51, 0x2d, 0xef, 0x9b, 0x5e, 0x50, 0xe, 0xb4, 0x98, 0xaf, 0x86, 0xaa, 0xd2, 0x46, 0x4a, 0xea, 0xe7, 0x6d, 0xb1, 0xf6, 0x5d, 0x23, 0x26, 0xce, 0x90, 0x26, 0xec, 0x69} }, + { (uint64_t)90000000000000000ull, {0x3d, 0x78, 0x73, 0x63, 0x95, 0xf1, 0xd7, 0xde, 0x8e, 0x16, 0xc0, 0xb5, 0xa9, 0x9f, 0x4d, 0xc4, 0xeb, 0x8f, 0x22, 0xac, 0xc1, 0x5b, 0x21, 0x42, 0x44, 0x1d, 0xbd, 0x8d, 0x2c, 0x31, 0xb9, 0xce} }, + { (uint64_t)100000000000000000ull, {0x27, 0x27, 0xd4, 0x93, 0x2f, 0x98, 0x39, 0xe4, 0x3b, 0x6b, 0xf5, 0xfb, 0x29, 0xa3, 0xbe, 0x4c, 0x9, 0xb, 0x6e, 0xb9, 0x31, 00, 0xbb, 0x92, 0x58, 0x1a, 0xdb, 0x8d, 0xd2, 0xb6, 0x61, 0x54} }, + { (uint64_t)200000000000000000ull, {0xae, 0x96, 0x78, 0x2e, 0xf2, 0xc4, 0xdf, 0x7d, 0x2e, 0x4, 0xcc, 0xf9, 0xef, 0x76, 0x23, 0x7f, 0x17, 0xc, 0x97, 0x3, 0xb4, 0x92, 0xc0, 0x78, 0x52, 0x6e, 0xb1, 0xf6, 0x85, 0x3d, 0xb1, 0x33} }, + { (uint64_t)300000000000000000ull, {0x17, 0x43, 0xfe, 0xab, 0x12, 0xad, 0xe5, 0xfe, 0x12, 0x53, 0x22, 0x27, 0x2f, 0xd1, 0x40, 0x6b, 0x74, 0xe8, 0x19, 0x70, 0x32, 0x68, 0x46, 0x22, 0xee, 0x79, 0xab, 0xcd, 0x94, 0x93, 0x66, 0x4c} }, + { (uint64_t)400000000000000000ull, {0x7, 0x9b, 0xf2, 0xa9, 0x6e, 0x16, 0x6e, 0xf9, 0xe6, 0xb2, 0x23, 0x1d, 0xb9, 0x85, 0x8b, 0x99, 0x98, 0x7f, 0x49, 0x33, 0x87, 0xde, 0xeb, 0xd5, 0x17, 0x48, 0x54, 0x9a, 0xd, 0xf7, 0xdc, 0x44} }, + { (uint64_t)500000000000000000ull, {0xca, 0xba, 0x97, 0x98, 0x51, 0x6d, 0xad, 0x3, 0x38, 0xd0, 0x6e, 0x10, 0x6d, 0x76, 0xa2, 0x1, 0x93, 0x7a, 0xce, 0x4c, 0x91, 0x53, 0x9e, 0x61, 0x7d, 0x89, 0x28, 0x73, 0x6, 0xa3, 0x92, 0xb1} }, + { (uint64_t)600000000000000000ull, {0x6b, 0x8, 0x7f, 0x48, 0xb3, 0xd7, 0xaa, 0xc9, 0x57, 0xc4, 0x52, 0xe5, 0x1a, 0x18, 0xd7, 0x26, 0xb, 0xf8, 0xc8, 0x56, 0xc4, 0xc7, 0x1e, 0x48, 0xf6, 0x49, 0xae, 00, 0x4a, 0xf6, 0x8f, 0x13} }, + { (uint64_t)700000000000000000ull, {0x9e, 0xed, 0x8b, 0x23, 0x1f, 0x79, 0x4c, 0x46, 0x5c, 0xbe, 0x88, 0x40, 0xd0, 0xf1, 0x6f, 0x7b, 0x9f, 0x9c, 0x6e, 0xb4, 0x9c, 0x20, 0x7d, 0xe9, 0xd8, 0x55, 0x11, 0x83, 0xd0, 0xc7, 0x6e, 0x43} }, + { (uint64_t)800000000000000000ull, {0x58, 0x4a, 0x78, 0x93, 0x13, 0x7e, 0xbd, 0x2, 0x8b, 0xa7, 0x59, 0x82, 0xc3, 0x39, 0xb7, 0x66, 0xaa, 0xda, 0xad, 0xf9, 0x14, 0x50, 0xf9, 0x40, 0x7d, 0x2a, 0x97, 0xd7, 0xf6, 0xb1, 0x93, 0x5e} }, + { (uint64_t)900000000000000000ull, {0x7, 0xce, 0x54, 0xb1, 0x18, 0x26, 0xa1, 0x75, 0x23, 0x13, 0x55, 0x1a, 00, 0x20, 0xfd, 0x79, 0x8a, 00, 0x9e, 0x20, 0xcd, 0xb2, 0x40, 0x1d, 0x52, 0x51, 0xc1, 0x55, 0x8e, 0xea, 0xd2, 0x6c} }, + { (uint64_t)1000000000000000000ull, {0x39, 0x80, 0x7f, 0x3d, 0xce, 0xb0, 0xa6, 0xfe, 0x34, 0xa7, 0xa1, 0xed, 0xc6, 0x9b, 0x78, 0xff, 0xbe, 0xd5, 0xa7, 0x8c, 0x6c, 0x87, 0x5d, 0xda, 0x96, 0x69, 0xdb, 0xb2, 0x95, 0x70, 0xf0, 0xf4} }, + { (uint64_t)2000000000000000000ull, {0xda, 0x74, 00, 0x86, 0xf1, 0x5c, 0xe8, 0x21, 0xe9, 0xd, 0x50, 0xaf, 0xcf, 0x80, 0x9c, 0x7e, 0x18, 0x51, 0x90, 0x1b, 0xa3, 0x5f, 0x9f, 0x63, 0x78, 0xd6, 0x40, 0x7c, 0xb9, 0xc7, 0xa2, 0x75} }, + { (uint64_t)3000000000000000000ull, {0x7, 0xa1, 0x75, 0x63, 0xae, 0xf5, 0xcf, 0xd0, 0x36, 0xfa, 0x64, 0xd4, 0xb1, 0x97, 0xa9, 0x51, 0xc0, 0xd2, 0x87, 0x2b, 0xd, 0xb6, 0xf9, 0xbe, 0x47, 0xe6, 0x7c, 0xa6, 0xb5, 0x35, 0xe2, 0x6e} }, + { (uint64_t)4000000000000000000ull, {0xe3, 0x49, 0xf7, 0xeb, 0xe5, 0x11, 0x39, 0xfe, 0xd5, 0x69, 0x40, 0x37, 0xd1, 0x14, 0xb7, 0xbd, 0x45, 0xdd, 0xa, 0x6a, 0xf0, 0x4b, 0x62, 0xec, 0xa4, 0xd8, 0xcd, 0x55, 0x2a, 0x14, 0xe3, 0xfb} }, + { (uint64_t)5000000000000000000ull, {0x8d, 0x59, 0x7e, 0xa9, 0xf5, 0x79, 0x9a, 0x4d, 0x15, 0x3d, 0x82, 0xd6, 0xf7, 0xbe, 0xa0, 0x2e, 0x52, 0x40, 0xa2, 0xc8, 0x9b, 0x4, 0x1e, 0x6, 0x2f, 0x37, 0xbc, 0x7b, 0x82, 0xa0, 0xac, 0x55} }, + { (uint64_t)6000000000000000000ull, {0xa3, 0x43, 0xa7, 0xe1, 0x14, 0x4d, 0x33, 0x50, 0xf, 0x3e, 0xfd, 0x38, 0x15, 0x82, 0xdd, 0xc5, 0xd0, 0x18, 0x3e, 0x5d, 0xcf, 0x8a, 0xfa, 0x64, 0xbb, 0x67, 0x6c, 0x97, 0x3e, 0x3d, 0x1a, 0xb1} }, + { (uint64_t)7000000000000000000ull, {0x89, 0xe9, 0x3e, 0xe9, 0xf2, 0x4d, 0x72, 0x61, 0xe5, 0x44, 0xca, 0x8f, 0x9, 0xa7, 0x40, 0x4e, 0xe3, 0xa9, 0xe, 0xe2, 0x50, 0x7d, 0xda, 0xcf, 0x41, 0x2a, 0x58, 0xc, 0x9, 0x65, 0x1c, 0x53} }, + { (uint64_t)8000000000000000000ull, {0xc5, 0x94, 0x10, 0x81, 0x54, 0x69, 0xf4, 0x59, 0xd1, 0x5a, 0x6f, 0xe3, 0xf2, 0xa1, 0x1b, 0xa6, 0x31, 0x12, 0xfa, 0xaa, 0xc5, 0x3d, 0xbc, 0x52, 0x5d, 0x3c, 0xfa, 0xb1, 0xfa, 0x9c, 0x3d, 0xdb} }, + { (uint64_t)9000000000000000000ull, {0x9d, 0xe7, 0xcb, 0xb, 0x8d, 0x7b, 0xac, 0x47, 0xff, 0xd3, 0x93, 0x1b, 0xcd, 0x82, 0xcd, 0xd5, 0x35, 0xc, 0x29, 0x34, 0xb1, 0x6e, 0xb, 0x64, 0x32, 0xab, 0xf7, 0xcb, 0x4b, 0x5c, 0x37, 0x6d} }, + { (uint64_t)10000000000000000000ull, {0x65, 0x8d, 0x1, 0x37, 0x6d, 0x18, 0x63, 0xe7, 0x7b, 0x9, 0x6f, 0x98, 0xe6, 0xe5, 0x13, 0xc2, 0x4, 0x10, 0xf5, 0xc7, 0xfb, 0x18, 0xa6, 0xe5, 0x9a, 0x52, 0x66, 0x84, 0x5c, 0xd9, 0xb1, 0xe3} }, +}; + namespace rct { //Various key initialization functions @@ -143,6 +321,14 @@ namespace rct { } key zeroCommit(xmr_amount amount) { + const zero_commitment *begin = zero_commitments; + const zero_commitment *end = zero_commitments + sizeof(zero_commitments) / sizeof(zero_commitments[0]); + const zero_commitment value{amount, rct::zero()}; + const auto it = std::lower_bound(begin, end, value, [](const zero_commitment &e0, const zero_commitment &e1){ return e0.amount < e1.amount; }); + if (it != end && it->amount == amount) + { + return it->commitment; + } key am = d2h(amount); key bH = scalarmultH(am); return addKeys(G, bH); diff --git a/tests/performance_tests/crypto_ops.h b/tests/performance_tests/crypto_ops.h index 3c68583c5..25ab008db 100644 --- a/tests/performance_tests/crypto_ops.h +++ b/tests/performance_tests/crypto_ops.h @@ -40,6 +40,7 @@ enum test_op op_sc_mul, op_ge_add_raw, op_ge_add_p3_p3, + op_zeroCommitCached, ops_fast, op_addKeys, @@ -54,6 +55,7 @@ enum test_op op_addKeys3, op_addKeys3_2, op_isInMainSubgroup, + op_zeroCommitUncached, }; template @@ -108,6 +110,8 @@ class test_crypto_ops case op_addKeys3: rct::addKeys3(key, scalar0, point0, scalar1, precomp1); break; case op_addKeys3_2: rct::addKeys3(key, scalar0, precomp0, scalar1, precomp1); break; case op_isInMainSubgroup: rct::isInMainSubgroup(point0); break; + case op_zeroCommitUncached: rct::zeroCommit(9001); break; + case op_zeroCommitCached: rct::zeroCommit(9000); break; default: return false; } return true; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 87a1573c2..3c71cb99f 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -256,6 +256,8 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3_2); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_isInMainSubgroup); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitUncached); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitCached); TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 2); TEST_PERFORMANCE2(filter, p, test_multiexp, multiexp_bos_coster, 4); diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 3877ef785..52bdb00cf 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -1086,6 +1086,25 @@ TEST(ringct, zeroCommmit) ASSERT_EQ(z, manual); } +static rct::key uncachedZeroCommit(uint64_t amount) +{ + const rct::key am = rct::d2h(amount); + const rct::key bH = rct::scalarmultH(am); + return rct::addKeys(rct::G, bH); +} + +TEST(ringct, zeroCommitCache) +{ + ASSERT_EQ(rct::zeroCommit(0), uncachedZeroCommit(0)); + ASSERT_EQ(rct::zeroCommit(1), uncachedZeroCommit(1)); + ASSERT_EQ(rct::zeroCommit(2), uncachedZeroCommit(2)); + ASSERT_EQ(rct::zeroCommit(10), uncachedZeroCommit(10)); + ASSERT_EQ(rct::zeroCommit(200), uncachedZeroCommit(200)); + ASSERT_EQ(rct::zeroCommit(1000000000), uncachedZeroCommit(1000000000)); + ASSERT_EQ(rct::zeroCommit(3000000000000), uncachedZeroCommit(3000000000000)); + ASSERT_EQ(rct::zeroCommit(900000000000000), uncachedZeroCommit(900000000000000)); +} + TEST(ringct, H) { ge_p3 p3; From e198b06e7aed865b02198a53934fd63f94dc4ced Mon Sep 17 00:00:00 2001 From: Hasan Pekdemir Date: Sun, 4 Nov 2018 16:24:30 +0100 Subject: [PATCH 0249/1007] Fix: out_of_hashchain_bounds_error in refresh 15:43 < hahsun> Im on stagenet and I suddenly get this exception: 2018-11-04 14:42:52.416 [RPC0] ERROR wallet.wallet2 src/wallet/wallet2.cpp:2070 !m_blockchain.is_in_bounds(current_index). THROW EXCEPTION: error::out_of_hashchain_bounds_error 16:01 <+moneromooo> OK, possibly because the blckchain is always seeded with the genesis block hash... 16:02 <+moneromooo> So that case should be allowed, assuming it doesn't break the code around it. 16:05 <+moneromooo> OK if stop_height == size || (size==1 && stop_heigt ==0) 16:05 <+moneromooo> Throw if not that. 16:06 < hahsun> k --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 37b60c5d7..6f494fd05 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2720,7 +2720,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo short_chain_history.clear(); get_short_chain_history(short_chain_history); fast_refresh(stop_height, blocks_start_height, short_chain_history, true); - THROW_WALLET_EXCEPTION_IF(m_blockchain.size() != stop_height, error::wallet_internal_error, "Unexpected hashchain size"); + THROW_WALLET_EXCEPTION_IF((m_blockchain.size() == stop_height || (m_blockchain.size() == 1 && stop_height == 0) ? false : true), error::wallet_internal_error, "Unexpected hashchain size"); THROW_WALLET_EXCEPTION_IF(m_blockchain.offset() != 0, error::wallet_internal_error, "Unexpected hashchain offset"); for (const auto &h: tip) m_blockchain.push_back(h); From f92682ec0aff270f36901b1231213da7f02e8c27 Mon Sep 17 00:00:00 2001 From: Jethro Grassie Date: Wed, 31 Oct 2018 23:11:09 -0400 Subject: [PATCH 0250/1007] build: ubuntu 16 ppc build fixes --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3dbf974a..d31c494b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,7 +148,7 @@ if(ARCH_ID STREQUAL "powerpc64" OR ARCH_ID STREQUAL "ppc64") set(PPC 0) endif() -if(ARCH_ID STREQUAL "powerpc") +if(ARCH_ID STREQUAL "powerpc" OR ARCH_ID STREQUAL "ppc") set(PPC64LE 0) set(PPC64 0) set(PPC 1) From 769ae42a7b0e7e73a13ef578ec9a0ecb06df22c1 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 10 Sep 2018 13:08:34 +0000 Subject: [PATCH 0251/1007] wallet2: faster output and key image import/export --- src/wallet/wallet2.cpp | 94 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c27e4e820..31246d0b1 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -69,6 +69,7 @@ using namespace epee; #include "common/base58.h" #include "common/dns_utils.h" #include "common/notify.h" +#include "common/perf_timer.h" #include "ringct/rctSigs.h" #include "ringdb.h" #include "device/device_cold.hpp" @@ -10517,11 +10518,13 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle bool wallet2::export_key_images(const std::string &filename) const { + PERF_TIMER(export_key_images); std::vector> ski = export_key_images(); std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; std::string data; + data.reserve(ski.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key)); data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key)); for (const auto &i: ski) @@ -10531,6 +10534,7 @@ bool wallet2::export_key_images(const std::string &filename) const } // encrypt data, keep magic plaintext + PERF_TIMER(export_key_images_encrypt); std::string ciphertext = encrypt_with_view_secret_key(data); return epee::file_io_utils::save_string_to_file(filename, magic + ciphertext); } @@ -10538,6 +10542,7 @@ bool wallet2::export_key_images(const std::string &filename) const //---------------------------------------------------------------------------------------------------- std::vector> wallet2::export_key_images() const { + PERF_TIMER(export_key_images_raw); std::vector> ski; ski.reserve(m_transfers.size()); @@ -10590,6 +10595,7 @@ std::vector> wallet2::export_key uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent) { + PERF_TIMER(import_key_images_fsu); std::string data; bool r = epee::file_io_utils::load_file_to_string(filename, data); @@ -10603,6 +10609,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent try { + PERF_TIMER(import_key_images_decrypt); data = decrypt_with_view_secret_key(std::string(data, magiclen)); } catch (const std::exception &e) @@ -10641,6 +10648,7 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent //---------------------------------------------------------------------------------------------------- uint64_t wallet2::import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent) { + PERF_TIMER(import_key_images_lots); COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req); COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); @@ -10654,6 +10662,9 @@ uint64_t wallet2::import_key_images(const std::vector(out.target); const crypto::public_key pkey = o.key; - std::vector pkeys; - pkeys.push_back(&pkey); - THROW_WALLET_EXCEPTION_IF(!(rct::scalarmultKey(rct::ki2rct(key_image), rct::curveOrder()) == rct::identity()), - error::wallet_internal_error, "Key image out of validity domain: input " + boost::lexical_cast(n) + "/" - + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)); - - THROW_WALLET_EXCEPTION_IF(!crypto::check_ring_signature((const crypto::hash&)key_image, key_image, pkeys, &signature), - error::signature_check_failed, boost::lexical_cast(n) + "/" - + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image) - + ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0])); + if (!td.m_key_image_known || !(key_image == td.m_key_image)) + { + std::vector pkeys; + pkeys.push_back(&pkey); + THROW_WALLET_EXCEPTION_IF(!(rct::scalarmultKey(rct::ki2rct(key_image), rct::curveOrder()) == rct::identity()), + error::wallet_internal_error, "Key image out of validity domain: input " + boost::lexical_cast(n) + "/" + + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)); + THROW_WALLET_EXCEPTION_IF(!crypto::check_ring_signature((const crypto::hash&)key_image, key_image, pkeys, &signature), + error::signature_check_failed, boost::lexical_cast(n) + "/" + + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image) + + ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0])); + } req.key_images.push_back(epee::string_tools::pod_to_hex(key_image)); } + PERF_TIMER_STOP(import_key_images_A); + PERF_TIMER_START(import_key_images_B); for (size_t n = 0; n < signed_key_images.size(); ++n) { m_transfers[n].m_key_image = signed_key_images[n].first; @@ -10688,9 +10703,11 @@ uint64_t wallet2::import_key_images(const std::vector spent_key_images; + PERF_TIMER_START(import_key_images_C); for (const transfer_details &td: m_transfers) { for (const cryptonote::txin_v& in : td.m_tx.vin) @@ -10721,10 +10739,12 @@ uint64_t wallet2::import_key_images(const std::vector(in).k_image, td.m_txid)); } } + PERF_TIMER_STOP(import_key_images_C); + PERF_TIMER_START(import_key_images_D); for(size_t i = 0; i < signed_key_images.size(); ++i) { - transfer_details &td = m_transfers[i]; + const transfer_details &td = m_transfers[i]; uint64_t amount = td.amount(); if (td.m_spent) spent += amount; @@ -10742,6 +10762,8 @@ uint64_t wallet2::import_key_images(const std::vectorsecond); } } + PERF_TIMER_STOP(import_key_images_D); + MDEBUG("Total: " << print_money(spent) << " spent, " << print_money(unspent) << " unspent"); if (check_spent) @@ -10751,8 +10773,12 @@ uint64_t wallet2::import_key_images(const std::vector wallet2::export_outputs() const { + PERF_TIMER(export_outputs); std::vector outs; outs.reserve(m_transfers.size()); @@ -10970,29 +11002,53 @@ std::vector wallet2::export_outputs() const //---------------------------------------------------------------------------------------------------- std::string wallet2::export_outputs_to_str() const { - std::vector outs = export_outputs(); + PERF_TIMER(export_outputs_to_str); std::stringstream oss; boost::archive::portable_binary_oarchive ar(oss); - ar << outs; + ar << m_transfers; std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; std::string header; header += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); header += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key)); + PERF_TIMER(export_outputs_encryption); std::string ciphertext = encrypt_with_view_secret_key(header + oss.str()); return magic + ciphertext; } //---------------------------------------------------------------------------------------------------- size_t wallet2::import_outputs(const std::vector &outputs) { - m_transfers.clear(); - m_transfers.reserve(outputs.size()); + PERF_TIMER(import_outputs); + const size_t original_size = m_transfers.size(); + m_transfers.resize(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { transfer_details td = outputs[i]; + // skip those we've already imported, or which have different data + if (i < original_size) + { + // compare the data used to create the key image below + const transfer_details &org_td = m_transfers[i]; + if (!org_td.m_key_image_known) + goto process; +#define CMPF(f) if (!(td.f == org_td.f)) goto process + CMPF(m_txid); + CMPF(m_key_image); + CMPF(m_internal_output_index); +#undef CMPF + if (!(get_transaction_prefix_hash(td.m_tx) == get_transaction_prefix_hash(org_td.m_tx))) + goto process; + + // copy anyway, since the comparison does not include ancillary fields which may have changed + m_transfers[i] = std::move(td); + continue; + } + +process: + // the hot wallet wouldn't have known about key images (except if we already exported them) cryptonote::keypair in_ephemeral; @@ -11011,9 +11067,9 @@ size_t wallet2::import_outputs(const std::vector(i)); - m_key_images[td.m_key_image] = m_transfers.size(); - m_pub_keys[td.get_public_key()] = m_transfers.size(); - m_transfers.push_back(std::move(td)); + m_key_images[td.m_key_image] = i; + m_pub_keys[td.get_public_key()] = i; + m_transfers[i] = std::move(td); } return m_transfers.size(); @@ -11021,6 +11077,7 @@ size_t wallet2::import_outputs(const std::vector Date: Wed, 24 Oct 2018 18:24:11 +0000 Subject: [PATCH 0252/1007] wallet2: only export necessary outputs and key images and disable annoying test that requires ridiculous amounts of skullduggery every time some format changes --- src/device_trezor/device_trezor.cpp | 5 +- src/simplewallet/simplewallet.cpp | 4 +- src/wallet/wallet2.cpp | 122 ++++++++++++------- src/wallet/wallet2.h | 24 +++- src/wallet/wallet_rpc_server.cpp | 13 +- src/wallet/wallet_rpc_server_commands_defs.h | 6 +- tests/data/fuzz/cold-outputs/OUTPUTS2 | Bin 256 -> 581 bytes tests/fuzz/cold-outputs.cpp | 2 +- tests/unit_tests/serialization.cpp | 14 ++- 9 files changed, 125 insertions(+), 65 deletions(-) diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index 07c03fc66..f55cbb15d 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -212,9 +212,10 @@ namespace trezor { tools::wallet2::signed_tx_set & signed_tx, hw::tx_aux_data & aux_data) { + CHECK_AND_ASSERT_THROW_MES(unsigned_tx.transfers.first == 0, "Unsuported non zero offset"); size_t num_tx = unsigned_tx.txes.size(); signed_tx.key_images.clear(); - signed_tx.key_images.resize(unsigned_tx.transfers.size()); + signed_tx.key_images.resize(unsigned_tx.transfers.second.size()); for(size_t tx_idx = 0; tx_idx < num_tx; ++tx_idx) { std::shared_ptr signer; @@ -360,4 +361,4 @@ namespace trezor { } #endif //WITH_DEVICE_TREZOR -}} \ No newline at end of file +}} diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 58d4cdced..babc59ea3 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -6105,8 +6105,8 @@ bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, bool simple_wallet::accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs) { std::string extra_message; - if (!txs.transfers.empty()) - extra_message = (boost::format("%u outputs to import. ") % (unsigned)txs.transfers.size()).str(); + if (!txs.transfers.second.empty()) + extra_message = (boost::format("%u outputs to import. ") % (unsigned)txs.transfers.second.size()).str(); return accept_loaded_tx([&txs](){return txs.txes.size();}, [&txs](size_t n)->const tools::wallet2::tx_construction_data&{return txs.txes[n];}, extra_message); } //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 31246d0b1..a90a93321 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -113,11 +113,11 @@ using namespace cryptonote; #define SUBADDRESS_LOOKAHEAD_MAJOR 50 #define SUBADDRESS_LOOKAHEAD_MINOR 200 -#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\002" +#define KEY_IMAGE_EXPORT_FILE_MAGIC "Monero key image export\003" #define MULTISIG_EXPORT_FILE_MAGIC "Monero multisig export\001" -#define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\003" +#define OUTPUT_EXPORT_FILE_MAGIC "Monero output export\004" #define SEGREGATION_FORK_HEIGHT 99999999 #define TESTNET_SEGREGATION_FORK_HEIGHT 99999999 @@ -1606,6 +1606,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_txid = txid; td.m_key_image = tx_scan_info[o].ki; td.m_key_image_known = !m_watch_only && !m_multisig; + td.m_key_image_requested = false; td.m_key_image_partial = m_multisig; td.m_amount = amount; td.m_pk_index = pk_index - 1; @@ -5466,7 +5467,7 @@ std::string wallet2::dump_tx_to_str(const std::vector &ptx_vector) c txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device())); } - txs.transfers = m_transfers; + txs.transfers = export_outputs(); // save as binary std::ostringstream oss; boost::archive::portable_binary_oarchive ar(oss); @@ -7952,6 +7953,7 @@ void wallet2::light_wallet_get_unspent_outs() td.m_key_image = unspent_key_image; td.m_key_image_known = !m_watch_only && !m_multisig; + td.m_key_image_requested = false; td.m_key_image_partial = m_multisig; td.m_amount = o.amount; td.m_pk_index = 0; @@ -9125,7 +9127,7 @@ void wallet2::cold_sign_tx(const std::vector& ptx_vector, signed_tx_ { txs.txes.push_back(get_construction_data_with_decrypted_short_payment_id(tx, m_account.get_device())); } - txs.transfers = m_transfers; + txs.transfers = std::make_pair(0, m_transfers); auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); @@ -9156,7 +9158,7 @@ uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { dev_cold->ki_sync(&wallet_shim, m_transfers, ski); - return import_key_images(ski, spent, unspent); + return import_key_images(ski, 0, spent, unspent); } //---------------------------------------------------------------------------------------------------- void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const @@ -10519,15 +10521,21 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle bool wallet2::export_key_images(const std::string &filename) const { PERF_TIMER(export_key_images); - std::vector> ski = export_key_images(); + std::pair>> ski = export_key_images(); std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; + const uint32_t offset = ski.first; std::string data; - data.reserve(ski.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key)); + data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key)); + data.resize(4); + data[0] = offset & 0xff; + data[1] = (offset >> 8) & 0xff; + data[2] = (offset >> 16) & 0xff; + data[3] = (offset >> 24) & 0xff; data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key)); - for (const auto &i: ski) + for (const auto &i: ski.second) { data += std::string((const char *)&i.first, sizeof(crypto::key_image)); data += std::string((const char *)&i.second, sizeof(crypto::signature)); @@ -10540,13 +10548,17 @@ bool wallet2::export_key_images(const std::string &filename) const } //---------------------------------------------------------------------------------------------------- -std::vector> wallet2::export_key_images() const +std::pair>> wallet2::export_key_images() const { PERF_TIMER(export_key_images_raw); std::vector> ski; - ski.reserve(m_transfers.size()); - for (size_t n = 0; n < m_transfers.size(); ++n) + size_t offset = 0; + while (offset < m_transfers.size() && !m_transfers[offset].m_key_image_requested) + ++offset; + + ski.reserve(m_transfers.size() - offset); + for (size_t n = offset; n < m_transfers.size(); ++n) { const transfer_details &td = m_transfers[n]; @@ -10590,7 +10602,7 @@ std::vector> wallet2::export_key ski.push_back(std::make_pair(td.m_key_image, signature)); } - return ski; + return std::make_pair(offset, ski); } uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent) @@ -10617,15 +10629,17 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what()); } - const size_t headerlen = 2 * sizeof(crypto::public_key); + const size_t headerlen = 4 + 2 * sizeof(crypto::public_key); THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename); - const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0]; - const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)]; + const uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24); + const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4]; + const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)]; const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key) { THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account"); } + THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs"); const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature); THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size, @@ -10642,20 +10656,21 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent ski.push_back(std::make_pair(key_image, signature)); } - return import_key_images(ski, spent, unspent); + return import_key_images(ski, offset, spent, unspent); } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent) +uint64_t wallet2::import_key_images(const std::vector> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent) { PERF_TIMER(import_key_images_lots); COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req); COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp); - THROW_WALLET_EXCEPTION_IF(signed_key_images.size() > m_transfers.size(), error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs"); + THROW_WALLET_EXCEPTION_IF(signed_key_images.size() > m_transfers.size() - offset, error::wallet_internal_error, "The blockchain is out of date compared to the signed key images"); - if (signed_key_images.empty()) + if (signed_key_images.empty() && offset == 0) { spent = 0; unspent = 0; @@ -10667,7 +10682,7 @@ uint64_t wallet2::import_key_images(const std::vector pkeys; pkeys.push_back(&pkey); THROW_WALLET_EXCEPTION_IF(!(rct::scalarmultKey(rct::ki2rct(key_image), rct::curveOrder()) == rct::identity()), - error::wallet_internal_error, "Key image out of validity domain: input " + boost::lexical_cast(n) + "/" + error::wallet_internal_error, "Key image out of validity domain: input " + boost::lexical_cast(n + offset) + "/" + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image)); THROW_WALLET_EXCEPTION_IF(!crypto::check_ring_signature((const crypto::hash&)key_image, key_image, pkeys, &signature), - error::signature_check_failed, boost::lexical_cast(n) + "/" + error::signature_check_failed, boost::lexical_cast(n + offset) + "/" + boost::lexical_cast(signed_key_images.size()) + ", key image " + epee::string_tools::pod_to_hex(key_image) + ", signature " + epee::string_tools::pod_to_hex(signature) + ", pubkey " + epee::string_tools::pod_to_hex(*pkeys[0])); } @@ -10698,10 +10713,11 @@ uint64_t wallet2::import_key_images(const std::vector key_images) td.m_key_image = key_images[i]; m_key_images[m_transfers[i].m_key_image] = i; td.m_key_image_known = true; + td.m_key_image_requested = false; td.m_key_image_partial = false; m_pub_keys[m_transfers[i].get_public_key()] = i; } @@ -10984,20 +11001,24 @@ void wallet2::import_blockchain(const std::tuple wallet2::export_outputs() const +std::pair> wallet2::export_outputs() const { PERF_TIMER(export_outputs); std::vector outs; - outs.reserve(m_transfers.size()); - for (size_t n = 0; n < m_transfers.size(); ++n) + size_t offset = 0; + while (offset < m_transfers.size() && m_transfers[offset].m_key_image_known) + ++offset; + + outs.reserve(m_transfers.size() - offset); + for (size_t n = offset; n < m_transfers.size(); ++n) { const transfer_details &td = m_transfers[n]; outs.push_back(td); } - return outs; + return std::make_pair(offset, outs); } //---------------------------------------------------------------------------------------------------- std::string wallet2::export_outputs_to_str() const @@ -11006,7 +11027,7 @@ std::string wallet2::export_outputs_to_str() const std::stringstream oss; boost::archive::portable_binary_oarchive ar(oss); - ar << m_transfers; + ar << export_outputs(); std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; @@ -11018,20 +11039,27 @@ std::string wallet2::export_outputs_to_str() const return magic + ciphertext; } //---------------------------------------------------------------------------------------------------- -size_t wallet2::import_outputs(const std::vector &outputs) +size_t wallet2::import_outputs(const std::pair> &outputs) { PERF_TIMER(import_outputs); + + THROW_WALLET_EXCEPTION_IF(outputs.first > m_transfers.size(), error::wallet_internal_error, + "Imported outputs omit more outputs that we know of"); + + const size_t offset = outputs.first; const size_t original_size = m_transfers.size(); - m_transfers.resize(outputs.size()); - for (size_t i = 0; i < outputs.size(); ++i) + m_transfers.resize(offset + outputs.second.size()); + for (size_t i = 0; i < offset; ++i) + m_transfers[i].m_key_image_requested = false; + for (size_t i = 0; i < outputs.second.size(); ++i) { - transfer_details td = outputs[i]; + transfer_details td = outputs.second[i]; // skip those we've already imported, or which have different data - if (i < original_size) + if (i + offset < original_size) { // compare the data used to create the key image below - const transfer_details &org_td = m_transfers[i]; + const transfer_details &org_td = m_transfers[i + offset]; if (!org_td.m_key_image_known) goto process; #define CMPF(f) if (!(td.f == org_td.f)) goto process @@ -11043,7 +11071,7 @@ size_t wallet2::import_outputs(const std::vector(i)); + THROW_WALLET_EXCEPTION_IF(td.m_tx.vout.empty(), error::wallet_internal_error, "tx with no outputs at index " + boost::lexical_cast(i + offset)); crypto::public_key tx_pub_key = get_tx_pub_key_from_received_outs(td); const std::vector additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx); @@ -11063,13 +11091,14 @@ size_t wallet2::import_outputs(const std::vector(i)); + error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast(i + offset)); - m_key_images[td.m_key_image] = i; - m_pub_keys[td.get_public_key()] = i; - m_transfers[i] = std::move(td); + m_key_images[td.m_key_image] = i + offset; + m_pub_keys[td.get_public_key()] = i + offset; + m_transfers[i + offset] = std::move(td); } return m_transfers.size(); @@ -11114,7 +11143,7 @@ size_t wallet2::import_outputs_from_str(const std::string &outputs_st) std::string body(data, headerlen); std::stringstream iss; iss << body; - std::vector outputs; + std::pair> outputs; try { boost::archive::portable_binary_iarchive ar(iss); @@ -11306,6 +11335,7 @@ void wallet2::update_multisig_rescan_info(const std::vector txes; - wallet2::transfer_container transfers; + std::pair transfers; }; struct signed_tx_set @@ -1071,9 +1073,9 @@ namespace tools bool verify_with_public_key(const std::string &data, const crypto::public_key &public_key, const std::string &signature) const; // Import/Export wallet data - std::vector export_outputs() const; + std::pair> export_outputs() const; std::string export_outputs_to_str() const; - size_t import_outputs(const std::vector &outputs); + size_t import_outputs(const std::pair> &outputs); size_t import_outputs_from_str(const std::string &outputs_st); payment_container export_payments() const; void import_payments(const payment_container &payments); @@ -1081,8 +1083,8 @@ namespace tools std::tuple> export_blockchain() const; void import_blockchain(const std::tuple> &bc); bool export_key_images(const std::string &filename) const; - std::vector> export_key_images() const; - uint64_t import_key_images(const std::vector> &signed_key_images, uint64_t &spent, uint64_t &unspent, bool check_spent = true); + std::pair>> export_key_images() const; + uint64_t import_key_images(const std::vector> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true); uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); bool import_key_images(std::vector key_images); crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; @@ -1396,7 +1398,7 @@ namespace tools }; } BOOST_CLASS_VERSION(tools::wallet2, 26) -BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 9) +BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 10) BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1) @@ -1454,6 +1456,10 @@ namespace boost x.m_multisig_k.clear(); x.m_multisig_info.clear(); } + if (ver < 10) + { + x.m_key_image_requested = false; + } } template @@ -1535,6 +1541,12 @@ namespace boost a & x.m_multisig_info; a & x.m_multisig_k; a & x.m_key_image_partial; + if (ver < 10) + { + initialize_transfer_details(a, x, ver); + return; + } + a & x.m_key_image_requested; } template diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5e6100dfd..eabdd9a6a 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2460,12 +2460,13 @@ namespace tools if (!m_wallet) return not_open(er); try { - std::vector> ski = m_wallet->export_key_images(); - res.signed_key_images.resize(ski.size()); - for (size_t n = 0; n < ski.size(); ++n) + std::pair>> ski = m_wallet->export_key_images(); + res.offset = ski.first; + res.signed_key_images.resize(ski.second.size()); + for (size_t n = 0; n < ski.second.size(); ++n) { - res.signed_key_images[n].key_image = epee::string_tools::pod_to_hex(ski[n].first); - res.signed_key_images[n].signature = epee::string_tools::pod_to_hex(ski[n].second); + res.signed_key_images[n].key_image = epee::string_tools::pod_to_hex(ski.second[n].first); + res.signed_key_images[n].signature = epee::string_tools::pod_to_hex(ski.second[n].second); } } @@ -2518,7 +2519,7 @@ namespace tools ski[n].second = *reinterpret_cast(bd.data()); } uint64_t spent = 0, unspent = 0; - uint64_t height = m_wallet->import_key_images(ski, spent, unspent); + uint64_t height = m_wallet->import_key_images(ski, req.offset, spent, unspent); res.spent = spent; res.unspent = unspent; res.height = height; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 924f3a0f1..026b75a9e 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 5 +#define WALLET_RPC_VERSION_MINOR 6 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -1579,9 +1579,11 @@ namespace wallet_rpc struct response { + uint32_t offset; std::vector signed_key_images; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(offset); KV_SERIALIZE(signed_key_images); END_KV_SERIALIZE_MAP() }; @@ -1602,9 +1604,11 @@ namespace wallet_rpc struct request { + uint32_t offset; std::vector signed_key_images; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(offset, (uint32_t)0); KV_SERIALIZE(signed_key_images); END_KV_SERIALIZE_MAP() }; diff --git a/tests/data/fuzz/cold-outputs/OUTPUTS2 b/tests/data/fuzz/cold-outputs/OUTPUTS2 index 907bcdb913d7c4cd244f1ac8a18fd812db5869d8..33cf39024f6bd7c087fd01a35a9568d8304b724a 100644 GIT binary patch literal 581 zcmV-L0=oT8Z*FCBZy;}VbZ~WaAZ2)PZ*p`5G4tp3cqZ(Q5}Lcq2LyX_vmER9<1fN# z;*B`&%2cAssqBhs7ekHk$|^si5j`U``G{LIVivfC8iZw}9~KF$kF4DmoU&PRJHU!& zS;G|gMb_d#19^;aZ+Y037ZNTANPHS+DoA>h23FQyh;r!auZUcZxi(X7heD@2@iW+w z0SK=Pl3EVpvuA=kZpg`Rk~l*!oHqxWwjuL{VWmn=m>JUwv!8>@pDE6H*@*#|ZM$R$-vX9~+^G5~+%jjzW;{_#A-5$@=t#1a* z!+531rB9Y8w7fu48`;L|1XuYsFVDEGhu}ZXn{+s{_{(T5YkX0RX|q2;LY0iQ*ohQX zGA3j4jzP8NWF*EDA*$Di2 literal 256 zcmZQzU|?WmWMpSxWM{4q;bUI*mI)-n#JoF%46;)#V-V~ikQu5!sS8sy! z>^zWVQ1<}UV+U~8F)%8WoR}1N$H(Wnqxq3V8G?7I^sZsxql`hnhN GWB>qDdP|}J diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp index 488a3b931..29b3ed267 100644 --- a/tests/fuzz/cold-outputs.cpp +++ b/tests/fuzz/cold-outputs.cpp @@ -77,7 +77,7 @@ int ColdOutputsFuzzer::run(const std::string &filename) s = std::string("\x01\x16serialization::archive") + s; try { - std::vector outputs; + std::pair> outputs; std::stringstream iss; iss << s; boost::archive::portable_binary_iarchive ar(iss); diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 2f7b5aac7..e1404d637 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -908,9 +908,21 @@ TEST(Serialization, portability_outputs) ASSERT_TRUE(td2.m_pk_index == 0); } +struct unsigned_tx_set +{ + std::vector txes; + tools::wallet2::transfer_container transfers; +}; +template +inline void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization::version_type ver) +{ + a & x.txes; + a & x.transfers; +} #define UNSIGNED_TX_PREFIX "Monero unsigned tx set\003" TEST(Serialization, portability_unsigned_tx) { + const boost::filesystem::path filename = unit_test::data_dir / "unsigned_monero_tx"; std::string s; const cryptonote::network_type nettype = cryptonote::TESTNET; @@ -918,7 +930,7 @@ TEST(Serialization, portability_unsigned_tx) ASSERT_TRUE(r); const size_t magiclen = strlen(UNSIGNED_TX_PREFIX); ASSERT_FALSE(strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen)); - tools::wallet2::unsigned_tx_set exported_txs; + unsigned_tx_set exported_txs; s = s.substr(magiclen); r = false; try From 5f614ba968388ae231579c392f8e793d569b9b3d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 13:23:44 +0000 Subject: [PATCH 0253/1007] simplewallet: print the number of show/all transfers --- src/simplewallet/simplewallet.cpp | 8 ++++++-- tests/unit_tests/serialization.cpp | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index babc59ea3..f54f3f129 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4483,7 +4483,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args tools::wallet2::transfer_container transfers; m_wallet->get_transfers(transfers); - bool transfers_found = false; + size_t transfers_found = 0; for (const auto& td : transfers) { if (!filter || available != td.m_spent) @@ -4496,7 +4496,6 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args if (verbose) verbose_string = (boost::format("%68s%68s") % tr("pubkey") % tr("key image")).str(); message_writer() << boost::format("%21s%8s%12s%8s%16s%68s%16s%s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id") % tr("addr index") % verbose_string; - transfers_found = true; } std::string verbose_string; if (verbose) @@ -4511,6 +4510,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args td.m_txid % td.m_subaddr_index.minor % verbose_string; + ++transfers_found; } } @@ -4529,6 +4529,10 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args success_msg_writer() << tr("No incoming unavailable transfers"); } } + else + { + success_msg_writer() << boost::format("Found %u/%u transfers") % transfers_found % transfers.size(); + } return true; } diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index e1404d637..b4517af2f 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -922,7 +922,6 @@ inline void serialize(Archive &a, unsigned_tx_set &x, const boost::serialization #define UNSIGNED_TX_PREFIX "Monero unsigned tx set\003" TEST(Serialization, portability_unsigned_tx) { - const boost::filesystem::path filename = unit_test::data_dir / "unsigned_monero_tx"; std::string s; const cryptonote::network_type nettype = cryptonote::TESTNET; From e178bf234ac78a689db0f9d1bec64dca4d41c350 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Sun, 4 Nov 2018 22:17:04 +0100 Subject: [PATCH 0254/1007] rpc: fix linking error of 6097472a, get_output_distribution Undefined symbols for architecture x86_64: "cryptonote::core::get_output_distribution(unsigned long long, unsigned long long, unsigned long long, unsigned long long&, std::__1::vector >&, unsigned long long&) const", referenced from: cryptonote::rpc::RpcHandler::get_output_distribution(cryptonote::core&, unsigned long long, unsigned long long, unsigned long long, bool) in rpc_handler.cpp.o --- src/rpc/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 8b4c27e3e..8fc42b7e3 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -27,11 +27,11 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(rpc_base_sources - rpc_args.cpp - rpc_handler.cpp) + rpc_args.cpp) set(rpc_sources core_rpc_server.cpp + rpc_handler.cpp instanciations) set(daemon_messages_sources @@ -44,10 +44,10 @@ set(daemon_rpc_server_sources set(rpc_base_headers - rpc_args.h - rpc_handler.h) + rpc_args.h) -set(rpc_headers) +set(rpc_headers + rpc_handler.cpp) set(daemon_rpc_server_headers) From b3067962faf5b2863fc9e72a603a65bd2e5aa55f Mon Sep 17 00:00:00 2001 From: xiphon Date: Mon, 5 Nov 2018 00:13:51 +0000 Subject: [PATCH 0255/1007] cryptonote_core: avoid gratuitous recalculations in check_block_rate() --- src/cryptonote_core/cryptonote_core.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 4b806c282..c405c996a 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1716,7 +1716,8 @@ namespace cryptonote for (size_t n = 0; n < sizeof(seconds)/sizeof(seconds[0]); ++n) { unsigned int b = 0; - for (time_t ts: timestamps) b += ts >= now - static_cast(seconds[n]); + const time_t time_boundary = now - static_cast(seconds[n]); + for (time_t ts: timestamps) b += ts >= time_boundary; const double p = probability(b, seconds[n] / DIFFICULTY_TARGET_V2); MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")"); if (p < threshold) From f49884543ce77a1bf132653fe1346d1603a4ea64 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 00:34:16 +0000 Subject: [PATCH 0256/1007] perf_timer: remove stray debug addition --- src/common/perf_timer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index 1d4dee5b5..584434a0d 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -53,7 +53,6 @@ class PerformanceTimer void resume(); uint64_t value() const { return ticks; } -void set(uint64_t v){ticks=v;} protected: uint64_t ticks; From 7ae36e91f6ce75ec24b3a25478992b3a71f9ee35 Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 5 Nov 2018 12:13:15 +0900 Subject: [PATCH 0257/1007] wallet_rpc_server: account for watch-only/non-deterministic/multisig when querying seed Followup on #4653 --- src/wallet/wallet_rpc_server.cpp | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5e6100dfd..bec0a3eeb 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1742,11 +1742,42 @@ namespace tools if (req.key_type.compare("mnemonic") == 0) { epee::wipeable_string seed; - if (!m_wallet->get_seed(seed)) + bool ready; + if (m_wallet->multisig(&ready)) { + if (!ready) + { + er.code = WALLET_RPC_ERROR_CODE_NOT_MULTISIG; + er.message = "This wallet is multisig, but not yet finalized"; + return false; + } + if (!m_wallet->get_multisig_seed(seed)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to get multisig seed."; + return false; + } + } + else + { + if (m_wallet->watch_only()) + { + er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY; + er.message = "The wallet is watch-only. Cannot display seed."; + return false; + } + if (!m_wallet->is_deterministic()) + { er.code = WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC; er.message = "The wallet is non-deterministic. Cannot display seed."; return false; + } + if (!m_wallet->get_seed(seed)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to get seed."; + return false; + } } res.key = std::string(seed.data(), seed.size()); // send to the network, then wipe RAM :D } From fa3f756bfb4f0595bd2dbe0e22a9d2f00f4a0ef5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 11:15:02 +0000 Subject: [PATCH 0258/1007] unit_tests: fix leak when the test check fails Coverity 189527 --- tests/unit_tests/notify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index 4daeeddee..edc4eabdf 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -49,7 +49,8 @@ TEST(notify, works) tmp = "/tmp"; static const char *filename = "monero-notify-unit-test-XXXXXX"; const size_t len = strlen(tmp) + 1 + strlen(filename); - char *name_template = (char*)malloc(len + 1); + std::unique_ptr name_template_((char*)malloc(len + 1)); + char *name_template = name_template_.get(); ASSERT_TRUE(name_template != NULL); snprintf(name_template, len + 1, "%s/%s", tmp, filename); int fd = mkstemp(name_template); @@ -75,5 +76,4 @@ TEST(notify, works) ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111"); boost::filesystem::remove(name_template); - free(name_template); } From 00907c3987af00d6eb8ff7144a184a74906a8edf Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 14:23:00 +0000 Subject: [PATCH 0259/1007] rct: speedup commit a little saves a conversion, and uses a double scalarmult instead of two scalarmults --- src/ringct/rctOps.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 41bbf6ca3..6c0588cf6 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -117,8 +117,7 @@ namespace rct { //generates C =aG + bH from b, a is given.. void genC(key & C, const key & a, xmr_amount amount) { - key bH = scalarmultH(d2h(amount)); - addKeys1(C, a, bH); + addKeys2(C, a, d2h(amount), rct::H); } //generates a / Pedersen commitment to the amount @@ -149,10 +148,8 @@ namespace rct { } key commit(xmr_amount amount, const key &mask) { - key c = scalarmultBase(mask); - key am = d2h(amount); - key bH = scalarmultH(am); - addKeys(c, c, bH); + key c; + genC(c, mask, amount); return c; } From 6a1062f56001968dd593757403091cdbec36f2cb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 14:31:49 +0000 Subject: [PATCH 0260/1007] bulletproofs: reserve vector memory when known in advance --- src/ringct/bulletproofs.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index bed48769a..1592e74e4 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -112,6 +112,7 @@ static void init_exponents() if (init_done) return; std::vector data; + data.reserve(maxN*maxM*2); for (size_t i = 0; i < maxN*maxM; ++i) { Hi[i] = get_exponent(rct::H, i * 2); @@ -1056,6 +1057,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) bool bulletproof_VERIFY(const std::vector &proofs) { std::vector proof_pointers; + proof_pointers.reserve(proofs.size()); for (const Bulletproof &proof: proofs) proof_pointers.push_back(&proof); return bulletproof_VERIFY(proof_pointers); From 3b14d9727b6683dc9cd15352254e126e030250d8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 14:43:35 +0000 Subject: [PATCH 0261/1007] blockchain: use uint64_t for block height, not size_t for consistency --- src/cryptonote_core/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 77b6d0b69..e69ea6b08 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -853,7 +853,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block() } else { - size_t offset = height - std::min < size_t > (height, static_cast(DIFFICULTY_BLOCKS_COUNT)); + uint64_t offset = height - std::min (height, static_cast(DIFFICULTY_BLOCKS_COUNT)); if (offset == 0) ++offset; From ac23b10f152b483116419418c4cb11849285cf92 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 14:43:58 +0000 Subject: [PATCH 0262/1007] blockchain: fix innocuous difficulty cache inconsistency This inconsistent state would not actually be used in practice --- src/cryptonote_core/blockchain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index e69ea6b08..82f8579b1 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -831,6 +831,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block() std::vector timestamps; std::vector difficulties; auto height = m_db->height(); + top_hash = get_tail_id(); // get it again now that we have the lock // ND: Speedup // 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty, // then when the next block difficulty is queried, push the latest height data and From b620443b08d35f113a91d54cb87704afa53f0836 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 5 Nov 2018 16:13:07 +0000 Subject: [PATCH 0263/1007] epee: log HTTP/RPC calls at info level It's useful info to have when investigating logs --- contrib/epee/include/net/http_server_handlers_map2.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 00a867d3e..997c801d1 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -39,7 +39,7 @@ epee::net_utils::http::http_response_info& response, \ context_type& m_conn_context) \ {\ - LOG_PRINT_L2("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ + MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ response.m_response_code = 200; \ response.m_response_comment = "Ok"; \ if(!handle_http_request_map(query_info, response, m_conn_context)) \ @@ -68,6 +68,7 @@ CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \ uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ boost::value_initialized resp;\ + MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast(req), static_cast(resp))) \ { \ LOG_ERROR("Failed to " << #callback_f << "()"); \ @@ -95,6 +96,7 @@ CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ uint64_t ticks1 = misc_utils::get_tick_count(); \ boost::value_initialized resp;\ + MINFO(m_conn_context << "calling " << s_pattern); \ if(!callback_f(static_cast(req), static_cast(resp))) \ { \ LOG_ERROR("Failed to " << #callback_f << "()"); \ @@ -179,6 +181,7 @@ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ fail_resp.id = req.id; \ + MINFO(m_conn_context << "Calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result, fail_resp.error)) \ { \ epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ @@ -197,6 +200,7 @@ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ fail_resp.jsonrpc = "2.0"; \ fail_resp.id = req.id; \ + MINFO(m_conn_context << "calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context, response_info)) \ { \ epee::serialization::store_t_to_json(static_cast(fail_resp), response_info.m_body); \ @@ -210,6 +214,7 @@ else if(callback_name == method_name) \ { \ PREPARE_OBJECTS_FROM_JSON(command_type) \ + MINFO(m_conn_context << "calling RPC method " << method_name); \ if(!callback_f(req.params, resp.result)) \ { \ epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \ From 6e1282b60043adf7193beb78d7ccc2f11c630748 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 30 Oct 2018 12:16:11 +0000 Subject: [PATCH 0264/1007] wallet2: fix off by one in output picking and take into account wallet level minimum spend age --- src/wallet/wallet2.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index c27e4e820..439840738 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -6814,21 +6814,23 @@ void wallet2::get_outs(std::vector> //static const double shape = m_testnet ? 17.02 : 17.28; static const double scale = 1/1.61; std::gamma_distribution gamma(shape, scale); + THROW_WALLET_EXCEPTION_IF(rct_offsets.size() <= CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, error::wallet_internal_error, "Bad offset calculation"); + uint64_t last_usable_block = rct_offsets.size() - 1; auto pick_gamma = [&]() { double x = gamma(engine); x = exp(x); uint64_t block_offset = x / DIFFICULTY_TARGET_V2; // this assumes constant target over the whole rct range - if (block_offset >= rct_offsets.size() - 1) + if (block_offset > last_usable_block - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) return std::numeric_limits::max(); // bad pick - block_offset = rct_offsets.size() - 2 - block_offset; - THROW_WALLET_EXCEPTION_IF(block_offset >= rct_offsets.size() - 1, error::wallet_internal_error, "Bad offset calculation"); - THROW_WALLET_EXCEPTION_IF(rct_offsets[block_offset + 1] < rct_offsets[block_offset], + block_offset = last_usable_block - block_offset; + THROW_WALLET_EXCEPTION_IF(block_offset > last_usable_block, error::wallet_internal_error, "Bad offset calculation"); + THROW_WALLET_EXCEPTION_IF(block_offset > 0 && rct_offsets[block_offset] < rct_offsets[block_offset - 1], error::get_output_distribution, "Decreasing offsets in rct distribution: " + - std::to_string(block_offset) + ": " + std::to_string(rct_offsets[block_offset]) + ", " + - std::to_string(block_offset + 1) + ": " + std::to_string(rct_offsets[block_offset + 1])); + std::to_string(block_offset - 1) + ": " + std::to_string(rct_offsets[block_offset - 1]) + ", " + + std::to_string(block_offset) + ": " + std::to_string(rct_offsets[block_offset])); uint64_t first_block_offset = block_offset, last_block_offset = block_offset; - for (size_t half_window = 0; half_window < GAMMA_PICK_HALF_WINDOW; ++half_window) + for (size_t half_window = 0; half_window <= GAMMA_PICK_HALF_WINDOW; ++half_window) { // end when we have a non empty block uint64_t cum0 = first_block_offset > 0 ? rct_offsets[first_block_offset] - rct_offsets[first_block_offset - 1] : rct_offsets[0]; @@ -6837,19 +6839,24 @@ void wallet2::get_outs(std::vector> uint64_t cum1 = last_block_offset > 0 ? rct_offsets[last_block_offset] - rct_offsets[last_block_offset - 1] : rct_offsets[0]; if (cum1 > 1) break; - if (first_block_offset == 0 && last_block_offset >= rct_offsets.size() - 2) + if (first_block_offset == 0 && last_block_offset >= last_usable_block) break; // expand up to bounds if (first_block_offset > 0) --first_block_offset; - if (last_block_offset < rct_offsets.size() - 1) + else + return std::numeric_limits::max(); // bad pick + if (last_block_offset < last_usable_block - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE) ++last_block_offset; + else + return std::numeric_limits::max(); // bad pick } - const uint64_t n_rct = rct_offsets[last_block_offset] - (first_block_offset == 0 ? 0 : rct_offsets[first_block_offset - 1]); + const uint64_t first_rct = first_block_offset == 0 ? 0 : rct_offsets[first_block_offset - 1]; + const uint64_t n_rct = rct_offsets[last_block_offset] - first_rct; if (n_rct == 0) return rct_offsets[block_offset] ? rct_offsets[block_offset] - 1 : 0; - MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset); - return rct_offsets[first_block_offset] + crypto::rand() % n_rct; + MDEBUG("Picking 1/" << n_rct << " in " << (last_block_offset - first_block_offset + 1) << " blocks centered around " << block_offset + rct_start_height); + return first_rct + crypto::rand() % n_rct; }; size_t num_selected_transfers = 0; From 1fd017cf7756369aff4ac6b598cf86a130f78e12 Mon Sep 17 00:00:00 2001 From: buricl Date: Tue, 6 Nov 2018 00:17:22 +0100 Subject: [PATCH 0265/1007] Fix build of monero-gui by adding device_trezor to wallet_merged --- src/wallet/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index 4932dd4b6..4e3fb1ae5 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -120,7 +120,8 @@ if (BUILD_GUI_DEPS) ringct ringct_basic checkpoints - version) + version + device_trezor) foreach(lib ${libs_to_merge}) list(APPEND objlibs $) # matches naming convention in src/CMakeLists.txt From 2587aec121435ade996dbc533eab9503d0fc84fd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 24 Oct 2018 08:30:33 +0000 Subject: [PATCH 0266/1007] easylogging++: update to latest upstream (v9.96.5) --- external/easylogging++/ea_config.h | 1 + external/easylogging++/easylogging++.cc | 305 +++++++++++++++++------- external/easylogging++/easylogging++.h | 283 ++++++++++------------ 3 files changed, 349 insertions(+), 240 deletions(-) diff --git a/external/easylogging++/ea_config.h b/external/easylogging++/ea_config.h index 4c74925d3..4fb48ce3e 100644 --- a/external/easylogging++/ea_config.h +++ b/external/easylogging++/ea_config.h @@ -6,6 +6,7 @@ #define ELPP_NO_CHECK_MACROS #define ELPP_WINSOCK2 #define ELPP_NO_DEBUG_MACROS +#define ELPP_UTC_DATETIME #ifdef EASYLOGGING_CC #if !(!defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index 1139008e2..d57f3f3a0 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -1,13 +1,14 @@ // // Bismillah ar-Rahmaan ar-Raheem // -// Easylogging++ v9.94.1 +// Easylogging++ v9.96.5 // Cross-platform logging library for C++ applications // -// Copyright (c) 2017 muflihun.com +// Copyright (c) 2012-2018 Muflihun Labs +// Copyright (c) 2012-2018 @abumusamq // // This library is released under the MIT Licence. -// http://labs.muflihun.com/easyloggingpp/licence.php +// https://github.com/muflihun/easyloggingpp/blob/master/LICENSE // // https://github.com/muflihun/easyloggingpp // https://muflihun.github.io/easyloggingpp @@ -25,8 +26,95 @@ INITIALIZE_EASYLOGGINGPP namespace el { -// el::base::utils +// el::base namespace base { +// el::base::consts +namespace consts { + +// Level log values - These are values that are replaced in place of %level format specifier +// Extra spaces after format specifiers are only for readability purposes in log files +static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO"); +static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); +static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARNING"); +static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); +static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); +static const base::type::char_t* kVerboseLevelLogValue = + ELPP_LITERAL("VERBOSE"); // will become VERBOSE-x where x = verbose level +static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); +static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); +static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); +static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); +static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); +static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); +static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); +static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); +// Format specifiers - These are used to define log format +static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); +static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); +static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); +static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); +static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); +static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); +static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); +static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); +static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); +static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); +static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); +static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); +static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); +static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); +static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); +static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; +// Date/time +static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; +static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", + "September", "October", "November", "December" + }; +static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; +static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; +static const int kYearBase = 1900; +static const char* kAm = "AM"; +static const char* kPm = "PM"; +// Miscellaneous constants + +static const char* kNullPointer = "nullptr"; +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED +static const base::type::VerboseLevel kMaxVerboseLevel = 9; +static const char* kUnknownUser = "user"; +static const char* kUnknownHost = "unknown-host"; + + +//---------------- DEFAULT LOG FILE ----------------------- + +#if defined(ELPP_NO_DEFAULT_LOG_FILE) +# if ELPP_OS_UNIX +static const char* kDefaultLogFile = "/dev/null"; +# elif ELPP_OS_WINDOWS +static const char* kDefaultLogFile = "nul"; +# endif // ELPP_OS_UNIX +#elif defined(ELPP_DEFAULT_LOG_FILE) +static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; +#else +static const char* kDefaultLogFile = "myeasylog.log"; +#endif // defined(ELPP_NO_DEFAULT_LOG_FILE) + + +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +static const char* kDefaultLogFileParam = "--default-log-file"; +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) +static const char* kLoggingFlagsParam = "--logging-flags"; +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) +static const char* kValidLoggerIdSymbols = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; +static const char* kConfigurationComment = "##"; +static const char* kConfigurationLevel = "*"; +static const char* kConfigurationLoggerId = "--"; +} +// el::base::utils namespace utils { /// @brief Aborts application due with user-defined status @@ -303,11 +391,7 @@ void Configurations::set(Configuration* conf) { void Configurations::setToDefault(void) { setGlobally(ConfigurationType::Enabled, std::string("true"), true); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); -#else - ELPP_UNUSED(base::consts::kDefaultLogFile); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) #if defined(ELPP_NO_LOG_TO_FILE) setGlobally(ConfigurationType::ToFile, std::string("false"), true); #else @@ -336,9 +420,7 @@ void Configurations::setRemainingToDefault(void) { #else unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); #endif // defined(ELPP_NO_LOG_TO_FILE) -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); unsafeSetIfNotExist(Level::Global, ConfigurationType::SubsecondPrecision, std::string("3")); unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); @@ -596,7 +678,6 @@ void Logger::configure(const Configurations& configurations) { if (m_typedConfigurations != nullptr) { Configurations* c = const_cast(m_typedConfigurations->configurations()); if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { - // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE flush(); } } @@ -640,7 +721,11 @@ void Logger::flush(Level level, base::type::fstream_t* fs) { } if (fs != nullptr) { fs->flush(); - m_unflushedCount.find(level)->second = 0; + std::unordered_map::iterator iter = m_unflushedCount.find(level); + if (iter != m_unflushedCount.end()) { + iter->second = 0; + } + Helpers::validateFileRolling(this, level); } } @@ -699,10 +784,9 @@ std::size_t File::getSizeOfFile(base::type::fstream_t* fs) { if (fs == nullptr) { return 0; } - std::streampos currPos = fs->tellg(); - fs->seekg(0, fs->end); + // Since the file stream is appended to or truncated, the current + // offset is the file size. std::size_t size = static_cast(fs->tellg()); - fs->seekg(currPos); return size; } @@ -894,7 +978,10 @@ void Str::replaceFirstWithEscape(base::type::string_t& str, const base::type::st #endif // defined(ELPP_UNICODE) std::string& Str::toUpper(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), ::toupper); + std::transform(str.begin(), str.end(), str.begin(), + [](char c) { + return static_cast(::toupper(c)); + }); return str; } @@ -1022,11 +1109,13 @@ const std::string OS::getBashOutput(const char* command) { char hBuff[4096]; if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { pclose(proc); - const size_t len = strlen(hBuff); - if (len > 0 && hBuff[len - 1] == '\n') { - hBuff[len- 1] = '\0'; + const std::size_t buffLen = strlen(hBuff); + if (buffLen > 0 && hBuff[buffLen - 1] == '\n') { + hBuff[buffLen- 1] = '\0'; } return std::string(hBuff); + } else { + pclose(proc); } return std::string(); #else @@ -1172,19 +1261,23 @@ unsigned long long DateTime::getTimeDifference(const struct timeval& endTime, co struct ::tm* DateTime::buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { #if ELPP_OS_UNIX time_t rawTime = currTime->tv_sec; - ::gmtime_r(&rawTime, timeInfo); + ::elpptime_r(&rawTime, timeInfo); return timeInfo; #else # if ELPP_COMPILER_MSVC ELPP_UNUSED(currTime); time_t t; +# if defined(_USE_32BIT_TIME_T) + _time32(&t); +# else _time64(&t); - gmtime_s(timeInfo, &t); +# endif + elpptime_s(timeInfo, &t); return timeInfo; # else // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method time_t rawTime = currTime->tv_sec; - struct tm* tmInf = gmtime(&rawTime); + struct tm* tmInf = elpptime(&rawTime); *timeInfo = *tmInf; return timeInfo; # endif // ELPP_COMPILER_MSVC @@ -1292,7 +1385,8 @@ bool CommandLineArgs::hasParamWithValue(const char* paramKey) const { } const char* CommandLineArgs::getParamValue(const char* paramKey) const { - return m_paramsWithValue.find(std::string(paramKey))->second.c_str(); + std::unordered_map::const_iterator iter = m_paramsWithValue.find(std::string(paramKey)); + return iter != m_paramsWithValue.end() ? iter->second.c_str() : ""; } bool CommandLineArgs::hasParam(const char* paramKey) const { @@ -1641,10 +1735,11 @@ void TypedConfigurations::build(Configurations* configurations) { } else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); } else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_maxLogFileSizeMap); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - withFileSizeLimit.push_back(conf); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + auto v = getULong(conf->value()); + setValue(conf->level(), static_cast(v), &m_maxLogFileSizeMap); + if (v != 0) { + withFileSizeLimit.push_back(conf); + } } else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); } @@ -1718,12 +1813,6 @@ std::string TypedConfigurations::resolveFilename(const std::string& filename) { } void TypedConfigurations::insertFile(Level level, const std::string& fullFilename) { -#if defined(ELPP_NO_LOG_TO_FILE) - setValue(level, false, &m_toFileMap); - ELPP_UNUSED(fullFilename); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(nullptr))); - return; -#endif if (fullFilename.empty()) return; std::string resolvedFilename = resolveFilename(fullFilename); @@ -1861,8 +1950,10 @@ bool RegisteredLoggers::remove(const std::string& id) { if (id == base::consts::kDefaultLoggerId) { return false; } + // get has internal lock Logger* logger = base::utils::Registry::get(id); if (logger != nullptr) { + // unregister has internal lock unregister(logger); } return true; @@ -2066,9 +2157,11 @@ bool VRegistry::allowed(base::type::VerboseLevel vlevel, const char* file) { if (m_modules.empty() || file == nullptr) { return vlevel <= m_level; } else { - std::map::iterator it = m_modules.begin(); + char baseFilename[base::consts::kSourceFilenameMaxLength] = ""; + base::utils::File::buildBaseFilename(file, baseFilename); + std::unordered_map::iterator it = m_modules.begin(); for (; it != m_modules.end(); ++it) { - if (base::utils::Str::wildCardMatch(file, it->first.c_str())) { + if (base::utils::Str::wildCardMatch(baseFilename, it->first.c_str())) { return vlevel <= it->second; } } @@ -2176,7 +2269,7 @@ Storage::~Storage(void) { } bool Storage::hasCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(lock()); + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), formatSpecifier) != m_customFormatSpecifiers.end(); } @@ -2185,12 +2278,12 @@ void Storage::installCustomFormatSpecifier(const CustomFormatSpecifier& customFo if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { return; } - base::threading::ScopedLock scopedLock(lock()); + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); m_customFormatSpecifiers.push_back(customFormatSpecifier); } bool Storage::uninstallCustomFormatSpecifier(const char* formatSpecifier) { - base::threading::ScopedLock scopedLock(lock()); + base::threading::ScopedLock scopedLock(customFormatSpecifiersLock()); std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), formatSpecifier); if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { @@ -2228,9 +2321,35 @@ void Storage::setApplicationArguments(int argc, char** argv) { #endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) } +} // namespace base + +// LogDispatchCallback +void LogDispatchCallback::handle(const LogDispatchData* data) { +#if defined(ELPP_THREAD_SAFE) + base::threading::ScopedLock scopedLock(m_fileLocksMapLock); + std::string filename = data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level()); + auto lock = m_fileLocks.find(filename); + if (lock == m_fileLocks.end()) { + m_fileLocks.emplace(std::make_pair(filename, std::unique_ptr(new base::threading::Mutex))); + } +#endif +} + +base::threading::Mutex& LogDispatchCallback::fileHandle(const LogDispatchData* data) { + auto it = m_fileLocks.find(data->logMessage()->logger()->typedConfigurations()->filename(data->logMessage()->level())); + return *(it->second.get()); +} + +namespace base { // DefaultLogDispatchCallback void DefaultLogDispatchCallback::handle(const LogDispatchData* data) { +#if defined(ELPP_THREAD_SAFE) +#if 0 + LogDispatchCallback::handle(data); + base::threading::ScopedLock scopedLock(fileHandle(data)); +#endif +#endif m_data = data; dispatch(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog)); @@ -2481,6 +2600,8 @@ base::type::string_t DefaultLogBuilder::build(const LogMessage* logMessage, bool base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); } #if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + el::base::threading::ScopedLock lock_(ELPP->customFormatSpecifiersLock()); + ELPP_UNUSED(lock_); for (std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); it != ELPP->customFormatSpecifiers()->end(); ++it) { std::string fs(it->formatSpecifier()); @@ -2501,10 +2622,15 @@ void LogDispatcher::dispatch(void) { if (!m_proceed) { return; } +#ifndef ELPP_NO_GLOBAL_LOCK + // see https://github.com/muflihun/easyloggingpp/issues/580 + // global lock is turned off by default unless + // ELPP_NO_GLOBAL_LOCK is defined base::threading::ScopedLock scopedLock(ELPP->lock()); - base::TypedConfigurations* tc = m_logMessage.logger()->m_typedConfigurations; +#endif + base::TypedConfigurations* tc = m_logMessage->logger()->m_typedConfigurations; if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { - tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback()); + tc->validateFileRolling(m_logMessage->level(), ELPP->preRollOutCallback()); } LogDispatchCallback* callback = nullptr; LogDispatchData data; @@ -2512,7 +2638,7 @@ void LogDispatcher::dispatch(void) { : ELPP->m_logDispatchCallbacks) { callback = h.second.get(); if (callback != nullptr && callback->enabled()) { - data.setLogMessage(&m_logMessage); + data.setLogMessage(m_logMessage); data.setDispatchAction(m_dispatchAction); callback->handle(&data); } @@ -2559,6 +2685,7 @@ Writer& Writer::construct(int count, const char* loggerIds, ...) { va_list loggersList; va_start(loggersList, loggerIds); const char* id = loggerIds; + m_loggerIds.reserve(count); for (int i = 0; i < count; ++i) { m_loggerIds.push_back(std::string(id)); id = va_arg(loggersList, const char*); @@ -2577,12 +2704,12 @@ void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool nee m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); } if (m_logger == nullptr) { - ELPP->acquireLock(); - if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { - // Somehow default logger has been unregistered. Not good! Register again - ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); + { + if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { + // Somehow default logger has been unregistered. Not good! Register again + ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); + } } - ELPP->releaseLock(); // Need to unlock it for next writer Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) << "Logger [" << loggerId << "] is not registered yet!"; m_proceed = false; @@ -2643,8 +2770,13 @@ void Writer::processDispatch() { void Writer::triggerDispatch(void) { if (m_proceed) { - base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel, - m_logger), m_dispatchAction).dispatch(); + if (m_msg == nullptr) { + LogMessage msg(m_level, m_file, m_line, m_func, m_verboseLevel, + m_logger); + base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch(); + } else { + base::LogDispatcher(m_proceed, m_msg, m_dispatchAction).dispatch(); + } } if (m_logger != nullptr) { m_logger->stream().str(ELPP_LITERAL("")); @@ -2657,7 +2789,7 @@ void Writer::triggerDispatch(void) { std::stringstream reasonStream; reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" << " If you wish to disable 'abort on fatal log' please use " - << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; + << "el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; base::utils::abort(1, reasonStream.str()); } m_proceed = false; @@ -2773,18 +2905,19 @@ namespace debug { // StackTrace -StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, - const char* addr) { - m_index = index; - m_location = std::string(loc); - m_demangled = std::string(demang); - m_hex = std::string(hex); - m_addr = std::string(addr); +StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, + const std::string& hex, + const std::string& addr) : + m_index(index), + m_location(loc), + m_demangled(demang), + m_hex(hex), + m_addr(addr) { } std::ostream& operator<<(std::ostream& ss, const StackTrace::StackTraceEntry& si) { - ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled - << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr; + ss << "[" << si.m_index << "] " << si.m_location << (si.m_hex.empty() ? "" : "+") << si.m_hex << " " << si.m_addr << + (si.m_demangled.empty() ? "" : ":") << si.m_demangled; return ss; } @@ -2804,44 +2937,40 @@ void StackTrace::generateNew(void) { char** strings = backtrace_symbols(stack, size); if (size > kStackStart) { // Skip StackTrace c'tor and generateNew for (std::size_t i = kStackStart; i < size; ++i) { - char* mangName = nullptr; - char* hex = nullptr; - char* addr = nullptr; - for (char* c = strings[i]; *c; ++c) { - switch (*c) { - case '(': - mangName = c; - break; - case '+': - hex = c; - break; - case ')': - addr = c; - break; - default: - break; - } + std::string mangName; + std::string location; + std::string hex; + std::string addr; + + // entry: 2 crash.cpp.bin 0x0000000101552be5 _ZN2el4base5debug10StackTraceC1Ev + 21 + const std::string line(strings[i]); + auto p = line.find("_"); + if (p != std::string::npos) { + mangName = line.substr(p); + mangName = mangName.substr(0, mangName.find(" +")); + } + p = line.find("0x"); + if (p != std::string::npos) { + addr = line.substr(p); + addr = addr.substr(0, addr.find("_")); } // Perform demangling if parsed properly - if (mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex) { - *mangName++ = '\0'; - *hex++ = '\0'; - *addr++ = '\0'; + if (!mangName.empty()) { int status = 0; - char* demangName = abi::__cxa_demangle(mangName, 0, 0, &status); + char* demangName = abi::__cxa_demangle(mangName.data(), 0, 0, &status); // if demangling is successful, output the demangled function name if (status == 0) { // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) - StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr); + StackTraceEntry entry(i - 1, location, demangName, hex, addr); m_stack.push_back(entry); } else { // Not successful - we will use mangled name - StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr); + StackTraceEntry entry(i - 1, location, mangName, hex, addr); m_stack.push_back(entry); } free(demangName); } else { - StackTraceEntry entry(i - 1, strings[i]); + StackTraceEntry entry(i - 1, line); m_stack.push_back(entry); } } @@ -2875,6 +3004,9 @@ static std::string crashReason(int sig) { } /// @brief Logs reason of crash from sig static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { + if (sig == SIGINT && ELPP->hasFlag(el::LoggingFlag::IgnoreSigInt)) { + return; + } std::stringstream ss; ss << "CRASH HANDLED; "; ss << crashReason(sig); @@ -2953,7 +3085,6 @@ void Helpers::logCrashReason(int sig, bool stackTraceIfAvailable, Level level, c // Loggers Logger* Loggers::getLogger(const std::string& identity, bool registerIfNotAvailable) { - base::threading::ScopedLock scopedLock(ELPP->lock()); return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); } @@ -2962,12 +3093,10 @@ void Loggers::setDefaultLogBuilder(el::LogBuilderPtr& logBuilderPtr) { } bool Loggers::unregisterLogger(const std::string& identity) { - base::threading::ScopedLock scopedLock(ELPP->lock()); return ELPP->registeredLoggers()->remove(identity); } bool Loggers::hasLogger(const std::string& identity) { - base::threading::ScopedLock scopedLock(ELPP->lock()); return ELPP->registeredLoggers()->has(identity); } @@ -3137,11 +3266,11 @@ const std::string &Loggers::getFilenameCommonPrefix() { // VersionInfo const std::string VersionInfo::version(void) { - return std::string("9.94.1"); + return std::string("9.96.5"); } /// @brief Release date of current version const std::string VersionInfo::releaseDate(void) { - return std::string("25-02-2017 0813hrs"); + return std::string("07-09-2018 0950hrs"); } } // namespace el diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 8bf94c546..046252a5b 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -1,18 +1,20 @@ // // Bismillah ar-Rahmaan ar-Raheem // -// Easylogging++ v9.94.1 +// Easylogging++ v9.96.5 // Single-header only, cross-platform logging library for C++ applications // -// Copyright (c) 2017 muflihun.com +// Copyright (c) 2012-2018 Muflihun Labs +// Copyright (c) 2012-2018 @abumusamq // // This library is released under the MIT Licence. -// http://labs.muflihun.com/easyloggingpp/licence.php +// https://github.com/muflihun/easyloggingpp/blob/master/LICENSE // // https://github.com/muflihun/easyloggingpp // https://muflihun.github.io/easyloggingpp // http://muflihun.com // + #ifndef EASYLOGGINGPP_H #define EASYLOGGINGPP_H #include "ea_config.h" @@ -94,7 +96,7 @@ #else # define ELPP_OS_MAC 0 #endif -#if (defined(__FreeBSD__)) +#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) # define ELPP_OS_FREEBSD 1 #else # define ELPP_OS_FREEBSD 0 @@ -114,13 +116,23 @@ #else # define ELPP_OS_SOLARIS 0 #endif +#if (defined(_AIX)) +# define ELPP_OS_AIX 1 +#else +# define ELPP_OS_AIX 0 +#endif +#if (defined(__NetBSD__)) +# define ELPP_OS_NETBSD 1 +#else +# define ELPP_OS_NETBSD 0 +#endif #if (defined(__DragonFly__)) # define ELPP_OS_DRAGONFLY 1 #else # define ELPP_OS_DRAGONFLY 0 #endif // Unix -#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS || ELPP_OS_DRAGONFLY || ELPP_OS_OPENBSD || ELPP_OS_NETBSD ) && (!ELPP_OS_WINDOWS)) +#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_NETBSD || ELPP_OS_SOLARIS || ELPP_OS_AIX || ELPP_OS_DRAGONFLY || ELPP_OS_OPENBSD) && (!ELPP_OS_WINDOWS)) # define ELPP_OS_UNIX 1 #else # define ELPP_OS_UNIX 0 @@ -205,7 +217,7 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre # define ELPP_INTERNAL_INFO(lvl, msg) #endif // (defined(ELPP_DEBUG_INFO)) #if (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) -# if (ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_OS_OPENBSD && !ELPP_OS_NETBSD) +# if (ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_OS_OPENBSD && !ELPP_OS_NETBSD && !ELPP_OS_ANDROID) # define ELPP_STACKTRACE 1 # else # define ELPP_STACKTRACE 0 @@ -386,6 +398,7 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre #include #include #include +#include #include #include #include @@ -423,9 +436,6 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre # if defined(ELPP_LOG_STD_ARRAY) # include # endif // defined(ELPP_LOG_STD_ARRAY) -# if defined(ELPP_LOG_UNORDERED_MAP) -# include -# endif // defined(ELPP_LOG_UNORDERED_MAP) # if defined(ELPP_LOG_UNORDERED_SET) # include # endif // defined(ELPP_UNORDERED_SET) @@ -460,6 +470,15 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre // For logging wxWidgets based classes & templates # include #endif // defined(ELPP_WXWIDGETS_LOGGING) +#if defined(ELPP_UTC_DATETIME) +# define elpptime_r gmtime_r +# define elpptime_s gmtime_s +# define elpptime gmtime +#else +# define elpptime_r localtime_r +# define elpptime_s localtime_s +# define elpptime localtime +#endif // defined(ELPP_UTC_DATETIME) // Forward declarations namespace el { class Logger; @@ -584,6 +603,16 @@ enum class Level : base::type::EnumType { /// @brief Represents unknown level Unknown = 1010 }; +} // namespace el +namespace std { +template<> struct hash { + public: + std::size_t operator()(const el::Level& l) const { + return hash {}(static_cast(l)); + } +}; +} +namespace el { /// @brief Static class that contains helper functions for el::Level class LevelHelper : base::StaticClass { public: @@ -710,113 +739,41 @@ enum class LoggingFlag : base::type::EnumType { /// @brief Adds spaces b/w logs that separated by left-shift operator AutoSpacing = 8192, /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) - FixedTimeFormat = 16384 + FixedTimeFormat = 16384, + // @brief Ignore SIGINT or crash + IgnoreSigInt = 32768, }; namespace base { /// @brief Namespace containing constants used internally. namespace consts { -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif -// Level log values - These are values that are replaced in place of %level format specifier -static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO "); -static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); -static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARN "); -static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); -static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); -static const base::type::char_t* kVerboseLevelLogValue = ELPP_LITERAL("VER"); -static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); -static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); -static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); -static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); -static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); -static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); -static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); -static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); -// Format specifiers - These are used to define log format -static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); -static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); -static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); -static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); -static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); -static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); -static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); -static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); -static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); -static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); -static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); -static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); -static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); -static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); -static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); -static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; -// Date/time -static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; -static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", - "September", "October", "November", "December" - }; -static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; -static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; -static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; -static const int kYearBase = 1900; -static const char* kAm = "AM"; -static const char* kPm = "PM"; -// Miscellaneous constants +static const char kFormatSpecifierCharValue = 'v'; +static const char kFormatSpecifierChar = '%'; +static const unsigned int kMaxLogPerCounter = 100000; +static const unsigned int kMaxLogPerContainer = 100; +static const unsigned int kDefaultSubsecondPrecision = 3; + #ifdef ELPP_DEFAULT_LOGGER static const char* kDefaultLoggerId = ELPP_DEFAULT_LOGGER; #else static const char* kDefaultLoggerId = "default"; #endif + #ifdef ELPP_DEFAULT_PERFORMANCE_LOGGER static const char* kPerformanceLoggerId = ELPP_DEFAULT_PERFORMANCE_LOGGER; #else static const char* kPerformanceLoggerId = "performance"; #endif + #if defined(ELPP_SYSLOG) static const char* kSysLogLoggerId = "syslog"; #endif // defined(ELPP_SYSLOG) -static const char* kNullPointer = "nullptr"; -static const char kFormatSpecifierChar = '%'; -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -static const char kFormatSpecifierCharValue = 'v'; -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -static const unsigned int kMaxLogPerContainer = 100; -static const unsigned int kMaxLogPerCounter = 100000; -static const unsigned int kDefaultSubsecondPrecision = 3; -static const base::type::VerboseLevel kMaxVerboseLevel = 9; -static const char* kUnknownUser = "user"; -static const char* kUnknownHost = "unknown-host"; -#if defined(ELPP_DEFAULT_LOG_FILE) -static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; -#else -# if ELPP_OS_UNIX -# if ELPP_OS_ANDROID -static const char* kDefaultLogFile = "logs/myeasylog.log"; -# else -static const char* kDefaultLogFile = "logs/myeasylog.log"; -# endif // ELPP_OS_ANDROID -# elif ELPP_OS_WINDOWS -static const char* kDefaultLogFile = "logs\\myeasylog.log"; -# endif // ELPP_OS_UNIX -#endif // defined(ELPP_DEFAULT_LOG_FILE) -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -static const char* kDefaultLogFileParam = "--default-log-file"; -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) -static const char* kLoggingFlagsParam = "--logging-flags"; -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) + #if ELPP_OS_WINDOWS static const char* kFilePathSeperator = "\\"; #else static const char* kFilePathSeperator = "/"; #endif // ELPP_OS_WINDOWS -static const char* kValidLoggerIdSymbols = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; -static const char* kConfigurationComment = "##"; -static const char* kConfigurationLevel = "*"; -static const char* kConfigurationLoggerId = "--"; + static const std::size_t kSourceFilenameMaxLength = 100; static const std::size_t kSourceLineMaxLength = 10; static const Level kPerformanceTrackerDefaultLevel = Level::Info; @@ -861,9 +818,6 @@ const struct { }, }; static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif } // namespace consts } // namespace base typedef std::function PreRollOutCallback; @@ -1270,8 +1224,8 @@ class DateTime : base::StaticClass { base::TimestampUnit timestampUnit); - private: static struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo); + private: static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, std::size_t msec, const base::SubsecondPrecision* ssPrec); }; @@ -1310,7 +1264,7 @@ class CommandLineArgs { private: int m_argc; char** m_argv; - std::map m_paramsWithValue; + std::unordered_map m_paramsWithValue; std::vector m_params; }; /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. @@ -1435,7 +1389,7 @@ class AbstractRegistry : public base::threading::ThreadSafe { /// of AbstractRegistry. Any implementation of this class should be /// explicitly (by using lock functions) template -class Registry : public AbstractRegistry> { +class Registry : public AbstractRegistry> { public: typedef typename Registry::iterator iterator; typedef typename Registry::const_iterator const_iterator; @@ -1485,8 +1439,8 @@ class Registry : public AbstractRegistry> { void unregister(const T_Key& uniqKey) { T_Ptr* existing = get(uniqKey); if (existing != nullptr) { - base::utils::safeDelete(existing); this->list().erase(uniqKey); + base::utils::safeDelete(existing); } } @@ -1499,7 +1453,7 @@ class Registry : public AbstractRegistry> { } private: - virtual void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { + virtual void deepCopy(const AbstractRegistry>& sr) ELPP_FINAL { for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { registerNew(it->first, new T_Ptr(*it->second)); } @@ -1599,7 +1553,7 @@ class RegistryWithPred : public AbstractRegistry> { class Utils { public: template - static bool installCallback(const std::string& id, std::map* mapT) { + static bool installCallback(const std::string& id, std::unordered_map* mapT) { if (mapT->find(id) == mapT->end()) { mapT->insert(std::make_pair(id, TPtr(new T()))); return true; @@ -1608,15 +1562,15 @@ class Utils { } template - static void uninstallCallback(const std::string& id, std::map* mapT) { + static void uninstallCallback(const std::string& id, std::unordered_map* mapT) { if (mapT->find(id) != mapT->end()) { mapT->erase(id); } } template - static T* callback(const std::string& id, std::map* mapT) { - typename std::map::iterator iter = mapT->find(id); + static T* callback(const std::string& id, std::unordered_map* mapT) { + typename std::unordered_map::iterator iter = mapT->find(id); if (iter != mapT->end()) { return static_cast(iter->second.get()); } @@ -1961,7 +1915,7 @@ class Configurations : public base::utils::RegistryWithPred FileStreamPtr; -typedef std::map LogStreamsReferenceMap; +typedef std::unordered_map LogStreamsReferenceMap; /// @brief Configurations with data types. /// /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. @@ -1998,16 +1952,16 @@ class TypedConfigurations : public base::threading::ThreadSafe { private: Configurations* m_configurations; - std::map m_enabledMap; - std::map m_toFileMap; - std::map m_filenameMap; - std::map m_toStandardOutputMap; - std::map m_logFormatMap; - std::map m_subsecondPrecisionMap; - std::map m_performanceTrackingMap; - std::map m_fileStreamMap; - std::map m_maxLogFileSizeMap; - std::map m_logFlushThresholdMap; + std::unordered_map m_enabledMap; + std::unordered_map m_toFileMap; + std::unordered_map m_filenameMap; + std::unordered_map m_toStandardOutputMap; + std::unordered_map m_logFormatMap; + std::unordered_map m_subsecondPrecisionMap; + std::unordered_map m_performanceTrackingMap; + std::unordered_map m_fileStreamMap; + std::unordered_map m_maxLogFileSizeMap; + std::unordered_map m_logFlushThresholdMap; base::LogStreamsReferenceMap* m_logStreamsReference; friend class el::Helpers; @@ -2017,21 +1971,21 @@ class TypedConfigurations : public base::threading::ThreadSafe { friend class el::base::LogDispatcher; template - inline Conf_T getConfigByVal(Level level, const std::map* confMap, const char* confName) { + inline Conf_T getConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { base::threading::ScopedLock scopedLock(lock()); return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope } template - inline Conf_T& getConfigByRef(Level level, std::map* confMap, const char* confName) { + inline Conf_T& getConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { base::threading::ScopedLock scopedLock(lock()); return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope } template - Conf_T unsafeGetConfigByVal(Level level, const std::map* confMap, const char* confName) { + Conf_T unsafeGetConfigByVal(Level level, const std::unordered_map* confMap, const char* confName) { ELPP_UNUSED(confName); - typename std::map::const_iterator it = confMap->find(level); + typename std::unordered_map::const_iterator it = confMap->find(level); if (it == confMap->end()) { try { return confMap->at(Level::Global); @@ -2046,9 +2000,9 @@ class TypedConfigurations : public base::threading::ThreadSafe { } template - Conf_T& unsafeGetConfigByRef(Level level, std::map* confMap, const char* confName) { + Conf_T& unsafeGetConfigByRef(Level level, std::unordered_map* confMap, const char* confName) { ELPP_UNUSED(confName); - typename std::map::iterator it = confMap->find(level); + typename std::unordered_map::iterator it = confMap->find(level); if (it == confMap->end()) { try { return confMap->at(Level::Global); @@ -2062,14 +2016,15 @@ class TypedConfigurations : public base::threading::ThreadSafe { } template - void setValue(Level level, const Conf_T& value, std::map* confMap, bool includeGlobalLevel = true) { + void setValue(Level level, const Conf_T& value, std::unordered_map* confMap, + bool includeGlobalLevel = true) { // If map is empty and we are allowed to add into generic level (Level::Global), do it! if (confMap->empty() && includeGlobalLevel) { confMap->insert(std::make_pair(Level::Global, value)); return; } // If same value exist in generic level already, dont add it to explicit level - typename std::map::iterator it = confMap->find(Level::Global); + typename std::unordered_map::iterator it = confMap->find(Level::Global); if (it != confMap->end() && it->second == value) { return; } @@ -2231,21 +2186,26 @@ class LogDispatchData { inline base::DispatchAction dispatchAction(void) const { return m_dispatchAction; } - private: - LogMessage* m_logMessage; - base::DispatchAction m_dispatchAction; - friend class base::LogDispatcher; - inline void setLogMessage(LogMessage* logMessage) { m_logMessage = logMessage; } inline void setDispatchAction(base::DispatchAction dispatchAction) { m_dispatchAction = dispatchAction; } + private: + LogMessage* m_logMessage; + base::DispatchAction m_dispatchAction; + friend class base::LogDispatcher; + }; class LogDispatchCallback : public Callback { + protected: + virtual void handle(const LogDispatchData* data); + base::threading::Mutex& fileHandle(const LogDispatchData* data); private: friend class base::LogDispatcher; + std::unordered_map> m_fileLocks; + base::threading::Mutex m_fileLocksMapLock; }; class PerformanceTrackingCallback : public Callback { private: @@ -2363,7 +2323,7 @@ inline void FUNCTION_NAME(const T&); std::string m_parentApplicationName; bool m_isConfigured; Configurations m_configurations; - std::map m_unflushedCount; + std::unordered_map m_unflushedCount; base::LogStreamsReferenceMap* m_logStreamsReference; LogBuilderPtr m_logBuilder; @@ -2469,7 +2429,7 @@ class RegisteredLoggers : public base::utils::Registry { LogBuilderPtr m_defaultLogBuilder; Configurations m_defaultConfigurations; base::LogStreamsReferenceMap m_logStreamsReference; - std::map m_loggerRegistrationCallbacks; + std::unordered_map m_loggerRegistrationCallbacks; friend class el::base::Storage; void unsafeFlushAll(void); @@ -2507,7 +2467,7 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe { bool allowed(base::type::VerboseLevel vlevel, const char* file); - inline const std::map& modules(void) const { + inline const std::unordered_map& modules(void) const { return m_modules; } @@ -2529,7 +2489,7 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe { private: base::type::VerboseLevel m_level; base::type::EnumType* m_pFlags; - std::map m_modules; + std::unordered_map m_modules; std::vector> m_categories; std::map m_cached_allowed_categories; std::string m_categoriesString; @@ -2717,6 +2677,10 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { return &m_customFormatSpecifiers; } + base::threading::Mutex& customFormatSpecifiersLock() { + return m_customFormatSpecifiersLock; + } + inline void setLoggingLevel(Level level) { m_loggingLevel = level; } @@ -2757,13 +2721,13 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { /// @brief Sets thread name for current thread. Requires std::thread inline void setThreadName(const std::string& name) { if (name.empty()) return; - base::threading::ScopedLock scopedLock(lock()); + base::threading::ScopedLock scopedLock(m_threadNamesLock); m_threadNames[base::threading::getCurrentThreadId()] = name; } inline std::string getThreadName(const std::string& threadId) { - base::threading::ScopedLock scopedLock(lock()); - std::map::const_iterator it = m_threadNames.find(threadId); + base::threading::ScopedLock scopedLock(m_threadNamesLock); + std::unordered_map::const_iterator it = m_threadNames.find(threadId); if (it == m_threadNames.end()) { return threadId; } @@ -2783,10 +2747,12 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { #endif // ELPP_ASYNC_LOGGING base::utils::CommandLineArgs m_commandLineArgs; PreRollOutCallback m_preRollOutCallback; - std::map m_logDispatchCallbacks; - std::map m_performanceTrackingCallbacks; - std::map m_threadNames; + std::unordered_map m_logDispatchCallbacks; + std::unordered_map m_performanceTrackingCallbacks; + std::unordered_map m_threadNames; std::vector m_customFormatSpecifiers; + base::threading::Mutex m_customFormatSpecifiersLock; + base::threading::Mutex m_threadNamesLock; Level m_loggingLevel; friend class el::Helpers; @@ -2829,7 +2795,7 @@ class AsyncDispatchWorker : public base::IWorker, public base::threading::Thread void run(void); void setContinueRunning(bool value) { - base::threading::ScopedLock scopedLock(m_continueRunningMutex); + base::threading::ScopedLock scopedLock(m_continueRunningLock); m_continueRunning = value; } @@ -2839,7 +2805,7 @@ class AsyncDispatchWorker : public base::IWorker, public base::threading::Thread private: std::condition_variable cv; bool m_continueRunning; - base::threading::Mutex m_continueRunningMutex; + base::threading::Mutex m_continueRunningLock; }; #endif // ELPP_ASYNC_LOGGING } // namespace base @@ -2851,9 +2817,9 @@ class DefaultLogBuilder : public LogBuilder { /// @brief Dispatches log messages class LogDispatcher : base::NoCopy { public: - LogDispatcher(bool proceed, LogMessage&& logMessage, base::DispatchAction dispatchAction) : + LogDispatcher(bool proceed, LogMessage* logMessage, base::DispatchAction dispatchAction) : m_proceed(proceed), - m_logMessage(std::move(logMessage)), + m_logMessage(logMessage), m_dispatchAction(std::move(dispatchAction)) { } @@ -2861,7 +2827,7 @@ class LogDispatcher : base::NoCopy { private: bool m_proceed; - LogMessage m_logMessage; + LogMessage* m_logMessage; base::DispatchAction m_dispatchAction; }; #if defined(ELPP_STL_LOGGING) @@ -3274,10 +3240,15 @@ class Writer : base::NoCopy { Writer(Level level, const char* file, base::type::LineNumber line, const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, base::type::VerboseLevel verboseLevel = 0) : - m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), + m_msg(nullptr), m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { } + Writer(LogMessage* msg, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog) : + m_msg(msg), m_level(msg != nullptr ? msg->level() : Level::Unknown), + m_line(0), m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) { + } + virtual ~Writer(void) { processDispatch(); } @@ -3320,6 +3291,7 @@ class Writer : base::NoCopy { Writer& construct(Logger* logger, bool needLock = true); Writer& construct(int count, const char* loggerIds, ...); protected: + LogMessage* m_msg; Level m_level; const char* m_file; const base::type::LineNumber m_line; @@ -3378,6 +3350,7 @@ void Logger::log_(Level level, int vlevel, const T& log) { base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; } else { stream().str(ELPP_LITERAL("")); + releaseLock(); } } else { base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; @@ -3385,23 +3358,23 @@ void Logger::log_(Level level, int vlevel, const T& log) { } template inline void Logger::log(Level level, const char* s, const T& value, const Args&... args) { - base::threading::ScopedLock scopedLock(lock()); + acquireLock(); // released in Writer! log_(level, 0, s, value, args...); } template inline void Logger::log(Level level, const T& log) { - base::threading::ScopedLock scopedLock(lock()); + acquireLock(); // released in Writer! log_(level, 0, log); } # if ELPP_VERBOSE_LOG template inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { - base::threading::ScopedLock scopedLock(lock()); + acquireLock(); // released in Writer! log_(el::Level::Verbose, vlevel, s, value, args...); } template inline void Logger::verbose(int vlevel, const T& log) { - base::threading::ScopedLock scopedLock(lock()); + acquireLock(); // released in Writer! log_(el::Level::Verbose, vlevel, log); } # else @@ -3656,8 +3629,9 @@ class StackTrace : base::NoCopy { static const unsigned int kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() class StackTraceEntry { public: - StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, const char* addr); - StackTraceEntry(std::size_t index, char* loc) : + StackTraceEntry(std::size_t index, const std::string& loc, const std::string& demang, const std::string& hex, + const std::string& addr); + StackTraceEntry(std::size_t index, const std::string& loc) : m_index(index), m_location(loc) { } @@ -3842,6 +3816,11 @@ class Helpers : base::StaticClass { static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { return ELPP->commandLineArgs(); } + /// @brief Reserve space for custom format specifiers for performance + /// @see std::vector::reserve + static inline void reserveCustomFormatSpecifiers(std::size_t size) { + ELPP->m_customFormatSpecifiers.reserve(size); + } /// @brief Installs user defined format specifier and handler static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { ELPP->installCustomFormatSpecifier(customFormatSpecifier); From 3dba7f252e080ca9ce9c86dca033e6b0b00ee21d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 2 Nov 2018 22:27:25 +0000 Subject: [PATCH 0267/1007] protocol: option to pad transaction relay to the next kB To help protect one's privacy from traffic volume analysis for people using Tor or I2P. This will really fly once we relay txes on a timer rather than on demand, though. Off by default for now since it's wasteful and doesn't bring anything until I2P's in. --- src/cryptonote_core/cryptonote_core.cpp | 10 +++++- src/cryptonote_core/cryptonote_core.h | 8 +++++ .../cryptonote_protocol_defs.h | 2 ++ .../cryptonote_protocol_handler.inl | 31 +++++++++++++++++++ tests/core_proxy/core_proxy.h | 1 + tests/unit_tests/ban.cpp | 1 + 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index d8c38bf9e..c55499365 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -163,6 +163,11 @@ namespace cryptonote , "Relay blocks as normal blocks" , false }; + static const command_line::arg_descriptor arg_pad_transactions = { + "pad-transactions" + , "Pad relayed transactions to help defend against traffic volume analysis" + , false + }; static const command_line::arg_descriptor arg_max_txpool_weight = { "max-txpool-weight" , "Set maximum txpool weight in bytes." @@ -188,7 +193,8 @@ namespace cryptonote m_disable_dns_checkpoints(false), m_update_download(0), m_nettype(UNDEFINED), - m_update_available(false) + m_update_available(false), + m_pad_transactions(false) { m_checkpoints_updating.clear(); set_cryptonote_protocol(pprotocol); @@ -282,6 +288,7 @@ namespace cryptonote command_line::add_arg(desc, arg_offline); command_line::add_arg(desc, arg_disable_dns_checkpoints); command_line::add_arg(desc, arg_max_txpool_weight); + command_line::add_arg(desc, arg_pad_transactions); command_line::add_arg(desc, arg_block_notify); miner::init_options(desc); @@ -320,6 +327,7 @@ namespace cryptonote set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints)); test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height)); m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks); + m_pad_transactions = get_arg(vm, arg_pad_transactions); m_offline = get_arg(vm, arg_offline); m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints); if (!command_line::is_arg_defaulted(vm, arg_fluffy_blocks)) diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 80c452f53..cef42d207 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -756,6 +756,13 @@ namespace cryptonote */ bool fluffy_blocks_enabled() const { return m_fluffy_blocks_enabled; } + /** + * @brief get whether transaction relay should be padded + * + * @return whether transaction relay should be padded + */ + bool pad_transactions() const { return m_pad_transactions; } + /** * @brief check a set of hashes against the precompiled hash set * @@ -1014,6 +1021,7 @@ namespace cryptonote bool m_fluffy_blocks_enabled; bool m_offline; + bool m_pad_transactions; }; } diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index db159f0f4..d5bb50930 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -146,9 +146,11 @@ namespace cryptonote struct request { std::vector txs; + std::string _; // padding BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txs) + KV_SERIALIZE(_) END_KV_SERIALIZE_MAP() }; }; diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index c2c660e8c..6efdcc25e 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1724,8 +1724,39 @@ skip: bool t_cryptonote_protocol_handler::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context) { // no check for success, so tell core they're relayed unconditionally + const bool pad_transactions = m_core.pad_transactions(); + size_t bytes = pad_transactions ? 9 /* header */ + 4 /* 1 + 'txs' */ + tools::get_varint_data(arg.txs.size()).size() : 0; for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end(); ++tx_blob_it) + { m_core.on_transaction_relayed(*tx_blob_it); + if (pad_transactions) + bytes += tools::get_varint_data(tx_blob_it->size()).size() + tx_blob_it->size(); + } + + if (pad_transactions) + { + // stuff some dummy bytes in to stay safe from traffic volume analysis + static constexpr size_t granularity = 1024; + size_t padding = granularity - bytes % granularity; + const size_t overhead = 2 /* 1 + '_' */ + tools::get_varint_data(padding).size(); + if (overhead > padding) + padding = 0; + else + padding -= overhead; + arg._ = std::string(padding, ' '); + + std::string arg_buff; + epee::serialization::store_t_to_binary(arg, arg_buff); + + // we probably lowballed the payload size a bit, so added a but too much. Fix this now. + size_t remove = arg_buff.size() % granularity; + if (remove > arg._.size()) + arg._.clear(); + else + arg._.resize(arg._.size() - remove); + // if the size of _ moved enough, we might lose byte in size encoding, we don't care + } + return relay_post_notify(arg, exclude_context); } //------------------------------------------------------------------------------------------------------------------------ diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h index 7d36a0f68..023c220ae 100644 --- a/tests/core_proxy/core_proxy.h +++ b/tests/core_proxy/core_proxy.h @@ -104,5 +104,6 @@ namespace tests cryptonote::difficulty_type get_block_cumulative_difficulty(uint64_t height) const { return 0; } bool fluffy_blocks_enabled() const { return false; } uint64_t prevalidate_block_hashes(uint64_t height, const std::vector &hashes) { return 0; } + bool pad_transactions() const { return false; } }; } diff --git a/tests/unit_tests/ban.cpp b/tests/unit_tests/ban.cpp index e3dbdaef1..12625a949 100644 --- a/tests/unit_tests/ban.cpp +++ b/tests/unit_tests/ban.cpp @@ -83,6 +83,7 @@ class test_core cryptonote::difficulty_type get_block_cumulative_difficulty(uint64_t height) const { return 0; } bool fluffy_blocks_enabled() const { return false; } uint64_t prevalidate_block_hashes(uint64_t height, const std::vector &hashes) { return 0; } + bool pad_transactions() { return false; } void stop() {} }; From 840bf155a0ed28902de3d0546dec58fac7966131 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 6 Nov 2018 21:45:00 +0000 Subject: [PATCH 0268/1007] build: fix Ubuntu 16.04 (GCC 5.4.0) compilation --- src/wallet/wallet2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 58ed5dcad..ebf857b78 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -11069,7 +11069,8 @@ std::string wallet2::export_outputs_to_str() const std::stringstream oss; boost::archive::portable_binary_oarchive ar(oss); - ar << export_outputs(); + const auto& outputs = export_outputs(); + ar << outputs; std::string magic(OUTPUT_EXPORT_FILE_MAGIC, strlen(OUTPUT_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; From 1a4d160311df8b3aaf0e33fe0c3b77f1862c395e Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 7 Nov 2018 10:47:10 +0900 Subject: [PATCH 0269/1007] wallet2: remove redundant chacha key generation in store_keys --- src/wallet/wallet2.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 58ed5dcad..df947712e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -3144,7 +3144,6 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable account_data = buffer.GetString(); // Encrypt the entire JSON object. - crypto::generate_chacha_key(password.data(), password.size(), key, m_kdf_rounds); std::string cipher; cipher.resize(account_data.size()); keys_file_data.iv = crypto::rand(); From ba2055a22066c9bba26b39b0d8368dc49b1e023c Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 7 Nov 2018 15:09:43 +0900 Subject: [PATCH 0270/1007] api/wallet: fix compile errors made in #4720 --- src/wallet/api/wallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index ddf2d74ff..7cd3b65bb 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -507,7 +507,7 @@ bool WalletImpl::createWatchOnly(const std::string &path, const std::string &pas auto key_images = m_wallet->export_key_images(); uint64_t spent = 0; uint64_t unspent = 0; - view_wallet->import_key_images(key_images,spent,unspent,false); + view_wallet->import_key_images(key_images.second, key_images.first, spent, unspent, false); clearStatus(); } catch (const std::exception &e) { LOG_ERROR("Error creating view only wallet: " << e.what()); @@ -1051,8 +1051,8 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file // Check tx data and construct confirmation message std::string extra_message; - if (!transaction->m_unsigned_tx_set.transfers.empty()) - extra_message = (boost::format("%u outputs to import. ") % (unsigned)transaction->m_unsigned_tx_set.transfers.size()).str(); + if (!transaction->m_unsigned_tx_set.transfers.second.empty()) + extra_message = (boost::format("%u outputs to import. ") % (unsigned)transaction->m_unsigned_tx_set.transfers.second.size()).str(); transaction->checkLoadedTx([&transaction](){return transaction->m_unsigned_tx_set.txes.size();}, [&transaction](size_t n)->const tools::wallet2::tx_construction_data&{return transaction->m_unsigned_tx_set.txes[n];}, extra_message); setStatus(transaction->status(), transaction->errorString()); From 7c298f5d14e9ef47b812983fbb8a8f446b536fb5 Mon Sep 17 00:00:00 2001 From: Martijn Otto Date: Wed, 7 Nov 2018 09:24:50 +0100 Subject: [PATCH 0271/1007] No longer use a list for registering self references in the abstract tcp server Updated assert message Use a local variable that won't destruct at the end of the if-branch Updated comment --- contrib/epee/include/net/abstract_tcp_server2.h | 3 ++- contrib/epee/include/net/abstract_tcp_server2.inl | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 3f726a352..df2b9d1b2 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -155,7 +155,8 @@ namespace net_utils //this should be the last one, because it could be wait on destructor, while other activities possible on other threads t_protocol_handler m_protocol_handler; //typename t_protocol_handler::config_type m_dummy_config; - std::list > > m_self_refs; // add_ref/release support + size_t m_reference_count = 0; // reference count managed through add_ref/release support + boost::shared_ptr > m_self_ref; // the reference to hold critical_section m_self_refs_lock; critical_section m_chunking_lock; // held while we add small chunks of the big do_send() to small do_send_chunk() critical_section m_shutdown_lock; // held while shutting down diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 9b03941ee..a74eb1f26 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -230,7 +230,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) //_dbg3("[sock " << socket_.native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number); if(m_was_shutdown) return false; - m_self_refs.push_back(self); + ++m_reference_count; + m_self_ref = std::move(self); return true; CATCH_ENTRY_L0("connection::add_ref()", false); } @@ -242,10 +243,12 @@ PRAGMA_WARNING_DISABLE_VS(4355) boost::shared_ptr > back_connection_copy; LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] release"); CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection::release() call"); - //erasing from container without additional copy can cause start deleting object, including m_self_refs - back_connection_copy = m_self_refs.back(); - m_self_refs.pop_back(); + CHECK_AND_ASSERT_MES(m_reference_count, false, "[sock " << socket_.native_handle() << "] m_reference_count already at 0 at connection::release() call"); + // is this the last reference? + if (--m_reference_count == 0) { + // move the held reference to a local variable, keeping the object alive until the function terminates + std::swap(back_connection_copy, m_self_ref); + } CRITICAL_REGION_END(); return true; CATCH_ENTRY_L0("connection::release()", false); From e27e421f989aea2c89d6cdd1d73297243540e0d4 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Wed, 7 Nov 2018 18:27:52 +0100 Subject: [PATCH 0272/1007] Fix version prefix in gitian build The version prefix 'v' should just be set constantly. Reflect this change in the README as well. This should allow building commits as well, if a commit is passed in instead of a tag. --- contrib/gitian/README.md | 27 +++++++-------------------- contrib/gitian/gitian-build.py | 2 +- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md index 4bd326f22..0b13df344 100644 --- a/contrib/gitian/README.md +++ b/contrib/gitian/README.md @@ -17,19 +17,6 @@ More independent Gitian builders are needed, which is why this guide exists. It is preferred you follow these steps yourself instead of using someone else's VM image to avoid 'contaminating' the build. -Table of Contents ------------------- - -Please note that these instructions have been forked from bitcoin's gitian build -instructions. Please also consult their documentation, when running into problems. -The signing is left as inherited from bitcoin at the moment. - -- [Preparing the Gitian builder host](#preparing-the-gitian-builder-host) -- [Getting and building the inputs](#getting-and-building-the-inputs) -- [Building Binaries](#building-bitcoin-core) -- [Signing externally](#signing-externally) -- [Uploading signatures](#uploading-signatures) - Preparing the Gitian builder host --------------------------------- @@ -93,10 +80,10 @@ cp monero/contrib/gitian/gitian-build.py . Setup the required environment, you only need to do this once: ``` -./gitian-build.py --setup fluffypony 0.14.0 +./gitian-build.py --setup fluffypony v0.14.0 ``` -Where `fluffypony` is your Github name and `0.14.0` is the version tag you want to build (without `v`). +Where `fluffypony` is your Github name and `v0.14.0` is the version tag you want to build. While gitian and this build script does provide a way for you to sign the build directly, it is recommended to sign in a seperate step. This script is only there for convenience. Seperate steps for building can still be taken. @@ -113,7 +100,7 @@ Build Binaries ----------------------------- To build the most recent tag: - `./gitian-build.py --detach-sign --no-commit -b fluffypony 0.14.0` + `./gitian-build.py --detach-sign --no-commit -b fluffypony v0.14.0` To speed up the build, use `-j 5 -m 5000` as the first arguments, where `5` is the number of CPU's you allocated to the VM plus one, and 5000 is a little bit less than then the MB's of RAM you allocated. If there is memory corruption on your machine, try to tweak these values. @@ -123,7 +110,7 @@ If you do detached, offline signing, you need to copy these uncommited changes t ``` export NAME=fluffypony -export VERSION=0.14 +export VERSION=v0.14.0 gpg --output $VERSION-linux/$NAME/monero-linux-$VERSION-build.assert.sig --detach-sign $VERSION-linux/$NAME/monero-linux-$VERSION-build.assert gpg --output $VERSION-osx-unsigned/$NAME/monero-osx-$VERSION-build.assert.sig --detach-sign $VERSION-osx-unsigned/$NAME/monero-osx-$VERSION-build.assert gpg --output $VERSION-win-unsigned/$NAME/monero-win-$VERSION-build.assert.sig --detach-sign $VERSION-win-unsigned/$NAME/monero-win-$VERSION-build.assert @@ -133,9 +120,9 @@ Make a pull request (both the `.assert` and `.assert.sig` files) to the [monero-project/gitian.sigs](https://github.com/monero-project/gitian.sigs/) repository: ``` -git checkout -b 0.14.0 -git commit -S -a -m "Add $NAME 0.14.0" -git push --set-upstream $NAME 0.14.0 +git checkout -b v0.14.0 +git commit -S -a -m "Add $NAME v0.14.0" +git push --set-upstream $NAME v0.14.0 ``` ```bash diff --git a/contrib/gitian/gitian-build.py b/contrib/gitian/gitian-build.py index 99c64e9dd..df1ba0d6b 100755 --- a/contrib/gitian/gitian-build.py +++ b/contrib/gitian/gitian-build.py @@ -165,7 +165,7 @@ def main(): # Add leading 'v' for tags if args.commit and args.pull: raise Exception('Cannot have both commit and pull') - args.commit = ('' if args.commit else) + args.version + args.commit = args.commit if args.commit else args.version if args.setup: setup() From dffec2587fa26e2a4a8b0bda8bf0a23d5073fa3b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 9 Nov 2018 09:38:47 +0000 Subject: [PATCH 0273/1007] db_lmdb: error out if the db needs migration in read only mode --- src/blockchain_db/lmdb/db_lmdb.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 1674c40dd..8c66ef739 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1345,6 +1345,15 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) #if VERSION > 0 else if (db_version < VERSION) { + if (mdb_flags & MDB_RDONLY) + { + txn.abort(); + mdb_env_close(m_env); + m_open = false; + MFATAL("Existing lmdb database needs to be converted, which cannot be done on a read-only database."); + MFATAL("Please run monerod once to convert the database."); + return; + } // Note that there was a schema change within version 0 as well. // See commit e5d2680094ee15889934fe28901e4e133cda56f2 2015/07/10 // We don't handle the old format previous to that commit. From 9da6c52bb2fa50eefed4e4ea8db1b651da9157bd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 27 Apr 2018 10:20:09 +0100 Subject: [PATCH 0274/1007] unit_tests: add logging unit test --- tests/unit_tests/CMakeLists.txt | 1 + tests/unit_tests/logging.cpp | 177 ++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 tests/unit_tests/logging.cpp diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 7687e3c52..e63f0058f 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -54,6 +54,7 @@ set(unit_tests_sources hashchain.cpp http.cpp keccak.cpp + logging.cpp main.cpp memwipe.cpp mlocker.cpp diff --git a/tests/unit_tests/logging.cpp b/tests/unit_tests/logging.cpp new file mode 100644 index 000000000..476e92bef --- /dev/null +++ b/tests/unit_tests/logging.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2016-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#include +#include "gtest/gtest.h" +#include "file_io_utils.h" +#include "misc_log_ex.h" + +static std::string log_filename; + +static void init() +{ + boost::filesystem::path p = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + log_filename = p.string(); + mlog_configure(log_filename, false, 0); +} + +static void cleanup() +{ + boost::filesystem::remove(log_filename); +} + +static size_t nlines(const std::string &str) +{ + size_t n = 0; + for (const char *ptr = str.c_str(); *ptr; ++ptr) + if (*ptr == '\n') + ++n; + return n; +} + +static bool load_log_to_string(const std::string &filename, std::string &str) +{ + if (!epee::file_io_utils::load_file_to_string(filename, str)) + return false; + for (const char *ptr = str.c_str(); *ptr; ++ptr) + { + if (*ptr == '\n') + { + std::string prefix = std::string(str.c_str(), ptr - str.c_str()); + if (prefix.find("New log categories:") != std::string::npos) + { + str = std::string(ptr + 1, strlen(ptr + 1)); + break; + } + } + } + return true; +} + +static void log() +{ + MFATAL("fatal"); + MERROR("error"); + MWARNING("warning"); + MINFO("info"); + MDEBUG("debug"); + MTRACE("trace"); + + MCINFO("a.b.c.d", "a.b.c.d"); + MCINFO("a.b.c.e", "a.b.c.e"); + MCINFO("global", "global"); + MCINFO("x.y.z", "x.y.z"); + MCINFO("y.y.z", "y.y.z"); + MCINFO("x.y.x", "x.y.x"); +} + +TEST(logging, no_logs) +{ + init(); + mlog_set_categories(""); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(str == ""); + cleanup(); +} + +TEST(logging, default) +{ + init(); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(str.find("global") != std::string::npos); + ASSERT_TRUE(str.find("fatal") != std::string::npos); + ASSERT_TRUE(str.find("error") != std::string::npos); + ASSERT_TRUE(str.find("debug") == std::string::npos); + ASSERT_TRUE(str.find("trace") == std::string::npos); + cleanup(); +} + +TEST(logging, all) +{ + init(); + mlog_set_categories("*:TRACE"); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(str.find("global") != std::string::npos); + ASSERT_TRUE(str.find("fatal") != std::string::npos); + ASSERT_TRUE(str.find("error") != std::string::npos); + ASSERT_TRUE(str.find("debug") != std::string::npos); + ASSERT_TRUE(str.find("trace") != std::string::npos); + cleanup(); +} + +TEST(logging, glob_suffix) +{ + init(); + mlog_set_categories("x.y*:TRACE"); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(str.find("global") == std::string::npos); + ASSERT_TRUE(str.find("x.y.z") != std::string::npos); + ASSERT_TRUE(str.find("x.y.x") != std::string::npos); + ASSERT_TRUE(str.find("y.y.z") == std::string::npos); + cleanup(); +} + +TEST(logging, glob_prefix) +{ + init(); + mlog_set_categories("*y.z:TRACE"); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(str.find("global") == std::string::npos); + ASSERT_TRUE(str.find("x.y.z") != std::string::npos); + ASSERT_TRUE(str.find("x.y.x") == std::string::npos); + ASSERT_TRUE(str.find("y.y.z") != std::string::npos); + cleanup(); +} + +TEST(logging, last_precedence) +{ + init(); + mlog_set_categories("gobal:FATAL,glo*:DEBUG"); + log(); + std::string str; + ASSERT_TRUE(load_log_to_string(log_filename, str)); + ASSERT_TRUE(nlines(str) == 1); + ASSERT_TRUE(str.find("global") != std::string::npos); + ASSERT_TRUE(str.find("x.y.z") == std::string::npos); + ASSERT_TRUE(str.find("x.y.x") == std::string::npos); + ASSERT_TRUE(str.find("y.y.z") == std::string::npos); + cleanup(); +} + From 2c7195d80c4639e67f2f6d1115558402ae738b94 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 9 Nov 2018 19:57:31 +0000 Subject: [PATCH 0275/1007] bulletproofs: avoid std::vector allocations for slice --- src/ringct/bulletproofs.cc | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index bed48769a..2b9976b62 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -31,6 +31,7 @@ #include #include #include "misc_log_ex.h" +#include "span.h" #include "common/perf_timer.h" #include "cryptonote_config.h" extern "C" @@ -217,7 +218,7 @@ static rct::key vector_power_sum(const rct::key &x, size_t n) } /* Given two scalar arrays, construct the inner product */ -static rct::key inner_product(const rct::keyV &a, const rct::keyV &b) +static rct::key inner_product(const epee::span &a, const epee::span &b) { CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::key res = rct::zero(); @@ -228,6 +229,11 @@ static rct::key inner_product(const rct::keyV &a, const rct::keyV &b) return res; } +static rct::key inner_product(const rct::keyV &a, const rct::keyV &b) +{ + return inner_product(epee::span(a.data(), a.size()), epee::span(b.data(), b.size())); +} + /* Given two scalar arrays, construct the Hadamard product */ static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b) { @@ -293,7 +299,7 @@ static rct::keyV vector_subtract(const rct::keyV &a, const rct::key &b) } /* Multiply a scalar and a vector */ -static rct::keyV vector_scalar(const rct::keyV &a, const rct::key &x) +static rct::keyV vector_scalar(const epee::span &a, const rct::key &x) { rct::keyV res(a.size()); for (size_t i = 0; i < a.size(); ++i) @@ -303,6 +309,11 @@ static rct::keyV vector_scalar(const rct::keyV &a, const rct::key &x) return res; } +static rct::keyV vector_scalar(const rct::keyV &a, const rct::key &x) +{ + return vector_scalar(epee::span(a.data(), a.size()), x); +} + /* Create a vector from copies of a single value */ static rct::keyV vector_dup(const rct::key &x, size_t N) { @@ -400,17 +411,12 @@ static rct::keyV invert(rct::keyV x) } /* Compute the slice of a vector */ -static rct::keyV slice(const rct::keyV &a, size_t start, size_t stop) +static epee::span slice(const rct::keyV &a, size_t start, size_t stop) { CHECK_AND_ASSERT_THROW_MES(start < a.size(), "Invalid start index"); CHECK_AND_ASSERT_THROW_MES(stop <= a.size(), "Invalid stop index"); CHECK_AND_ASSERT_THROW_MES(start < stop, "Invalid start/stop indices"); - rct::keyV res(stop - start); - for (size_t i = start; i < stop; ++i) - { - res[i - start] = a[i]; - } - return res; + return epee::span(&a[start], stop - start); } static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, const rct::key &mash1) From a93571410ee928fdb59c24f33dd31dcb26c13171 Mon Sep 17 00:00:00 2001 From: sachaaaaa Date: Thu, 8 Nov 2018 16:12:11 +1100 Subject: [PATCH 0276/1007] Add new command "export_transfers" to save transfers to csv --- src/simplewallet/simplewallet.cpp | 272 +++++++++++++++++++++++++----- src/simplewallet/simplewallet.h | 18 ++ 2 files changed, 244 insertions(+), 46 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 702ff22cb..dcb7b582c 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "include_base_utils.h" #include "common/i18n.h" #include "common/command_line.h" @@ -2541,6 +2542,10 @@ simple_wallet::simple_wallet() "Pending or Failed: \"failed\"|\"pending\", \"out\", Time, Amount*, Transaction Hash, Payment ID, Fee, Input addresses**, \"-\", Note\n\n" "* Excluding change and fee.\n" "** Set of address indices used as inputs in this transfer.")); + m_cmd_binder.set_handler("export_transfers", + boost::bind(&simple_wallet::export_transfers, this, _1), + tr("export_transfers [in|out|all|pending|failed|coinbase] [index=[,,...]] [ []] [output=]"), + tr("Export to CSV the incoming/outgoing transfers within an optional height range.")); m_cmd_binder.set_handler("unspent_outputs", boost::bind(&simple_wallet::unspent_outputs, this, _1), tr("unspent_outputs [index=[,,...]] [ []]"), @@ -6763,9 +6768,9 @@ static std::string get_human_readable_timespan(std::chrono::seconds seconds) return sw::tr("a long time"); } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::show_transfers(const std::vector &args_) +// mutates local_args as it parses and consumes arguments +bool simple_wallet::get_transfers(std::vector& local_args, std::vector& transfers) { - std::vector local_args = args_; bool in = true; bool out = true; bool pending = true; @@ -6774,15 +6779,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) bool coinbase = true; uint64_t min_height = 0; uint64_t max_height = (uint64_t)-1; - boost::optional subaddr_index; - if(local_args.size() > 4) { - fail_msg_writer() << tr("usage: show_transfers [in|out|all|pending|failed|coinbase] [index=[,,...]] [ []]"); - return true; - } - - LOCK_IDLE_SCOPE(); - // optional in/out selector if (local_args.size() > 0) { if (local_args[0] == "in" || local_args[0] == "incoming") { @@ -6820,38 +6817,34 @@ bool simple_wallet::show_transfers(const std::vector &args_) if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=") { if (!parse_subaddress_indices(local_args[0], subaddr_indices)) - return true; + return false; local_args.erase(local_args.begin()); } // min height - if (local_args.size() > 0) { + if (local_args.size() > 0 && local_args[0].find('=') == std::string::npos) { try { min_height = boost::lexical_cast(local_args[0]); } catch (const boost::bad_lexical_cast &) { fail_msg_writer() << tr("bad min_height parameter:") << " " << local_args[0]; - return true; + return false; } local_args.erase(local_args.begin()); } // max height - if (local_args.size() > 0) { + if (local_args.size() > 0 && local_args[0].find('=') == std::string::npos) { try { max_height = boost::lexical_cast(local_args[0]); } catch (const boost::bad_lexical_cast &) { fail_msg_writer() << tr("bad max_height parameter:") << " " << local_args[0]; - return true; + return false; } local_args.erase(local_args.begin()); } - std::multimap> output; - - PAUSE_READLINE(); - if (in || coinbase) { std::list> payments; m_wallet->get_payments(payments, min_height, max_height, m_current_subaddress_account, subaddr_indices); @@ -6863,24 +6856,26 @@ bool simple_wallet::show_transfers(const std::vector &args_) if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); + std::string destination = m_wallet->get_subaddress_as_str({m_current_subaddress_account, pd.m_subaddr_index.minor}); const std::string type = pd.m_coinbase ? tr("block") : tr("in"); const bool unlocked = m_wallet->is_tx_spendtime_unlocked(pd.m_unlock_time, pd.m_block_height); - output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_green, type, (boost::format("%8.8s %25.25s %20.20s %s %s %d %s %s") % (unlocked ? "unlocked" : "locked") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); + transfers.push_back({ + pd.m_block_height, + pd.m_timestamp, + type, + true, + pd.m_amount, + pd.m_tx_hash, + payment_id, + 0, + {{destination, pd.m_amount}}, + {pd.m_subaddr_index.minor}, + note, + (unlocked) ? "unlocked" : "locked" + }); } } - auto print_subaddr_indices = [](const std::set& indices) - { - stringstream ss; - bool first = true; - for (uint32_t i : indices) - { - ss << (first ? "" : ",") << i; - first = false; - } - return ss.str(); - }; - if (out) { std::list> payments; m_wallet->get_payments_out(payments, min_height, max_height, m_current_subaddress_account, subaddr_indices); @@ -6888,27 +6883,31 @@ bool simple_wallet::show_transfers(const std::vector &args_) const tools::wallet2::confirmed_transfer_details &pd = i->second; uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known uint64_t fee = pd.m_amount_in - pd.m_amount_out; - std::string dests; + std::vector> destinations; for (const auto &d: pd.m_dests) { - if (!dests.empty()) - dests += ", "; - dests += get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr) + ": " + print_money(d.amount); + destinations.push_back({get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr), d.amount}); } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(i->first); - output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_magenta, tr("out"), (boost::format("%8.8s %25.25s %20.20s %s %s %14.14s %s %s - %s") % "-" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); + transfers.push_back({ + pd.m_block_height, + pd.m_timestamp, + "out", + true, + pd.m_amount_in - change - fee, + i->first, + payment_id, + fee, + destinations, + pd.m_subaddr_indices, + note, + "-" + }); } } - // print in and out sorted by height - for (std::multimap>::const_iterator i = output.begin(); i != output.end(); ++i) { - message_writer(std::get<0>(i->second), false) << - boost::format("%8.8llu %6.6s %s") % - ((unsigned long long)i->first) % std::get<1>(i->second) % std::get<2>(i->second); - } - if (pool) { try { @@ -6924,10 +6923,24 @@ bool simple_wallet::show_transfers(const std::vector &args_) if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); + std::string destination = m_wallet->get_subaddress_as_str({m_current_subaddress_account, pd.m_subaddr_index.minor}); std::string double_spend_note; if (i->second.m_double_spend_seen) double_spend_note = tr("[Double spend seen on the network: this transaction may or may not end up being mined] "); - message_writer() << (boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %s %s %d %s %s%s") % "pool" % "in" % "locked" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note % double_spend_note).str(); + transfers.push_back({ + "pool", + pd.m_timestamp, + "in", + false, + pd.m_amount, + pd.m_tx_hash, + payment_id, + 0, + {{destination, pd.m_amount}}, + {pd.m_subaddr_index.minor}, + note + double_spend_note, + "locked" + }); } } catch (const std::exception& e) @@ -6944,20 +6957,187 @@ bool simple_wallet::show_transfers(const std::vector &args_) const tools::wallet2::unconfirmed_transfer_details &pd = i->second; uint64_t amount = pd.m_amount_in; uint64_t fee = amount - pd.m_amount_out; + std::vector> destinations; + for (const auto &d: pd.m_dests) { + destinations.push_back({get_account_address_as_str(m_wallet->nettype(), d.is_subaddress, d.addr), d.amount}); + } std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(i->first); bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; if ((failed && is_failed) || (!is_failed && pending)) { - message_writer() << (boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %s %s %14.14s %s - %s") % (is_failed ? tr("failed") : tr("pending")) % tr("out") % "-" % get_human_readable_timestamp(pd.m_timestamp) % print_money(amount - pd.m_change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % print_subaddr_indices(pd.m_subaddr_indices) % note).str(); + transfers.push_back({ + (is_failed ? "failed" : "pending"), + pd.m_timestamp, + "out", + false, + amount - pd.m_change - fee, + i->first, + payment_id, + fee, + destinations, + pd.m_subaddr_indices, + note, + "-" + }); + } + } + } + // sort by block, then by timestamp (unconfirmed last) + std::sort(transfers.begin(), transfers.end(), [](const transfer_view& a, const transfer_view& b) -> bool { + if (a.confirmed && !b.confirmed) + return true; + if (a.block == b.block) + return a.timestamp < b.timestamp; + return a.block < b.block; + }); + + return true; +} +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::show_transfers(const std::vector &args_) +{ + std::vector local_args = args_; + + if(local_args.size() > 4) { + fail_msg_writer() << tr("usage: show_transfers [in|out|all|pending|failed|coinbase] [index=[,,...]] [ []]"); + return true; + } + + LOCK_IDLE_SCOPE(); + + std::vector all_transfers; + + if (!get_transfers(local_args, all_transfers)) + return true; + + PAUSE_READLINE(); + + for (const auto& transfer : all_transfers) + { + const auto color = transfer.confirmed ? ((transfer.direction == "in" || transfer.direction == "block") ? console_color_green : console_color_magenta) : console_color_white; + + std::string destinations = "-"; + if (!transfer.outputs.empty()) + { + destinations = ""; + for (const auto& output : transfer.outputs) + { + if (!destinations.empty()) + destinations += ", "; + destinations += (transfer.direction == "in" ? output.first.substr(0, 6) : output.first) + ":" + print_money(output.second); } } + + auto formatter = boost::format("%8.8llu %6.6s %8.8s %25.25s %20.20s %s %s %14.14s %s %s - %s"); + + message_writer(color, false) << formatter + % transfer.block + % transfer.direction + % transfer.unlocked + % get_human_readable_timestamp(transfer.timestamp) + % print_money(transfer.amount) + % string_tools::pod_to_hex(transfer.hash) + % transfer.payment_id + % print_money(transfer.fee) + % destinations + % boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ") + % transfer.note; } return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::export_transfers(const std::vector& args_) +{ + std::vector local_args = args_; + + if(local_args.size() > 5) { + fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|coinbase] [index=[,,...]] [ []] [output=]"); + return true; + } + + LOCK_IDLE_SCOPE(); + + std::vector all_transfers; + + // might consumes arguments in local_args + if (!get_transfers(local_args, all_transfers)) + return true; + + // output filename + std::string filename = (boost::format("output%u.csv") % m_current_subaddress_account).str(); + if (local_args.size() > 0 && local_args[0].substr(0, 7) == "output=") + { + filename = local_args[0].substr(7, -1); + local_args.erase(local_args.begin()); + } + + std::ofstream file(filename); + + // header + file << + boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%100.100s,%20.20s,%s,%s") % + tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") + << std::endl; + + uint64_t running_balance = 0; + auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%100.100s,%20.20s,\"%s\",%s"); + + for (const auto& transfer : all_transfers) + { + // ignore unconfirmed transfers in running balance + if (transfer.confirmed) + { + if (transfer.direction == "in" || transfer.direction == "block") + running_balance += transfer.amount; + else + running_balance -= transfer.amount + transfer.fee; + } + + file << formatter + % transfer.block + % transfer.direction + % transfer.unlocked + % get_human_readable_timestamp(transfer.timestamp) + % print_money(transfer.amount) + % print_money(running_balance) + % string_tools::pod_to_hex(transfer.hash) + % transfer.payment_id + % print_money(transfer.fee) + % (transfer.outputs.size() ? transfer.outputs[0].first : "-") + % (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "") + % boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ") + % transfer.note + << std::endl; + + for (size_t i = 1; i < transfer.outputs.size(); ++i) + { + file << formatter + % "" + % "" + % "" + % "" + % "" + % "" + % "" + % "" + % "" + % transfer.outputs[i].first + % print_money(transfer.outputs[i].second) + % "" + % "" + << std::endl; + } + } + file.close(); + + success_msg_writer() << tr("CSV exported to ") << filename; + + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::unspent_outputs(const std::vector &args_) { if(args_.size() > 3) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 26d51a431..421afbeda 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -190,6 +190,7 @@ namespace cryptonote bool get_reserve_proof(const std::vector &args); bool check_reserve_proof(const std::vector &args); bool show_transfers(const std::vector &args); + bool export_transfers(const std::vector &args); bool unspent_outputs(const std::vector &args); bool rescan_blockchain(const std::vector &args); bool refresh_main(uint64_t start_height, ResetType reset, bool is_init = false); @@ -241,6 +242,23 @@ namespace cryptonote std::string get_prompt() const; bool print_seed(bool encrypted); + struct transfer_view + { + boost::variant block; + uint64_t timestamp; + std::string direction; + bool confirmed; + uint64_t amount; + crypto::hash hash; + std::string payment_id; + uint64_t fee; + std::vector> outputs; + std::set index; + std::string note; + std::string unlocked; + }; + bool get_transfers(std::vector& args_, std::vector& transfers); + /*! * \brief Prints the seed with a nice message * \param seed seed to print From 8dde0d4899ff8a346d510dd638b32931c3f5631e Mon Sep 17 00:00:00 2001 From: Gingeropolous Date: Sun, 11 Nov 2018 22:51:53 -0500 Subject: [PATCH 0277/1007] readme 0.13.0.4 in the table its the one thing I do. I change the table. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b542220f..a5ba68ae9 100644 --- a/README.md +++ b/README.md @@ -117,8 +117,8 @@ Dates are provided in the format YYYY-MM-DD. | 1288616 | 2017-04-15 | v5 | v0.10.3.0 | v0.10.3.1 | Adjusted minimum blocksize and fee algorithm | | 1400000 | 2017-09-16 | v6 | v0.11.0.0 | v0.11.0.0 | Allow only RingCT transactions, allow only >= ringsize 5 | | 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.3.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs -| 1685555 | 2018-10-18 | v8 | v0.13.0.0 | v0.13.0.0 | max transaction size at half the penalty free block size, bulletproofs enabled, cryptonight variant 2, fixed ringsize [11](https://youtu.be/KOO5S4vxi0o) -| 1686275 | 2018-10-19 | v9 | v0.13.0.0 | v0.13.0.0 | bulletproofs required +| 1685555 | 2018-10-18 | v8 | v0.13.0.0 | v0.13.0.4 | max transaction size at half the penalty free block size, bulletproofs enabled, cryptonight variant 2, fixed ringsize [11](https://youtu.be/KOO5S4vxi0o) +| 1686275 | 2018-10-19 | v9 | v0.13.0.0 | v0.13.0.4 | bulletproofs required | XXXXXXX | 2019-04-XX | XX | XXXXXXXXX | XXXXXXXXX | X X's indicate that these details have not been determined as of commit date. From 37d5b8d9c2fa9af258e6dc429544b95342b7dbf4 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 12 Nov 2018 22:35:21 +0000 Subject: [PATCH 0278/1007] CMakeLists.txt: add -ftemplate-depth=900 --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 388eee3fb..69177c85f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -816,6 +816,9 @@ else() set(DEBUG_FLAGS "${DEBUG_FLAGS} -O0 ") endif() + # At least some CLANGs default to not enough for monero + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth=900") + if(NOT DEFINED USE_LTO_DEFAULT) set(USE_LTO_DEFAULT false) endif() From d01bdaca12bd759462f91783ca63ec178f6c3268 Mon Sep 17 00:00:00 2001 From: xiphon Date: Tue, 13 Nov 2018 12:15:18 +0000 Subject: [PATCH 0279/1007] common: fix base58 gcc -Werror=implicit-fallthrough --- src/common/base58.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/common/base58.cpp b/src/common/base58.cpp index 75556cad9..b28a04f20 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -109,20 +109,8 @@ namespace tools assert(1 <= size && size <= sizeof(uint64_t)); uint64_t res = 0; - switch (9 - size) - { - case 1: res |= *data++; /* FALLTHRU */ - case 2: res <<= 8; res |= *data++; /* FALLTHRU */ - case 3: res <<= 8; res |= *data++; /* FALLTHRU */ - case 4: res <<= 8; res |= *data++; /* FALLTHRU */ - case 5: res <<= 8; res |= *data++; /* FALLTHRU */ - case 6: res <<= 8; res |= *data++; /* FALLTHRU */ - case 7: res <<= 8; res |= *data++; /* FALLTHRU */ - case 8: res <<= 8; res |= *data; break; - default: assert(false); - } - - return res; + memcpy(reinterpret_cast(&res) + sizeof(uint64_t) - size, data, size); + return SWAP64BE(res); } void uint_64_to_8be(uint64_t num, size_t size, uint8_t* data) From f0459abbb981e88c91c5d16e734fd4ffc6b1a590 Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 15 Nov 2018 00:18:31 +0900 Subject: [PATCH 0280/1007] cmake: move Boost_LOCALE_LIBRARY out of ICU_LIBRARIES --- CMakeLists.txt | 4 ++-- src/simplewallet/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 388eee3fb..311af76dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -898,9 +898,9 @@ if(MINGW) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj") set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt) if(DEPENDS) - set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv) + set(ICU_LIBRARIES sicuio sicuin sicuuc sicudt sicutu iconv) else() - set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv) + set(ICU_LIBRARIES icuio icuin icuuc icudt icutu iconv) endif() elseif(APPLE OR OPENBSD OR ANDROID) set(EXTRA_LIBRARIES "") diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt index c31cdebde..e292f85dd 100644 --- a/src/simplewallet/CMakeLists.txt +++ b/src/simplewallet/CMakeLists.txt @@ -53,6 +53,7 @@ target_link_libraries(simplewallet ${Boost_CHRONO_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} + ${Boost_LOCALE_LIBRARY} ${ICU_LIBRARIES} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} From 6d3311acebff2b7b9cfdceb24fc9ee04b79275bb Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 15 Nov 2018 00:19:41 +0900 Subject: [PATCH 0281/1007] libwallet_api_tests: add missing dependency on Boost Locale and ICU --- tests/libwallet_api_tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/libwallet_api_tests/CMakeLists.txt b/tests/libwallet_api_tests/CMakeLists.txt index ef1b666ed..1a9cbc5a6 100644 --- a/tests/libwallet_api_tests/CMakeLists.txt +++ b/tests/libwallet_api_tests/CMakeLists.txt @@ -50,6 +50,8 @@ target_link_libraries(libwallet_api_tests ${Boost_FILESYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} + ${Boost_LOCALE_LIBRARY} + ${ICU_LIBRARIES} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBRARIES}) From 79b4dae66fdf0619deeec9d1bd49808f83a70421 Mon Sep 17 00:00:00 2001 From: stoffu Date: Mon, 5 Nov 2018 11:45:48 +0900 Subject: [PATCH 0282/1007] simplewallet: slightly adjust wording when printing multisig seed --- src/simplewallet/simplewallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 58d4cdced..fa23ce167 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2906,9 +2906,9 @@ bool simple_wallet::ask_wallet_create_if_needed() */ void simple_wallet::print_seed(const epee::wipeable_string &seed) { - success_msg_writer(true) << "\n" << tr("NOTE: the following 25 words can be used to recover access to your wallet. " + success_msg_writer(true) << "\n" << boost::format(tr("NOTE: the following %s can be used to recover access to your wallet. " "Write them down and store them somewhere safe and secure. Please do not store them in " - "your email or on file storage services outside of your immediate control.\n"); + "your email or on file storage services outside of your immediate control.\n")) % (m_wallet->multisig() ? tr("string") : tr("25 words")); // don't log int space_index = 0; size_t len = seed.size(); From 2b3595d0fe056ec4245ad3177d56c1e92da1ff9e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 15 Nov 2018 13:51:54 +0000 Subject: [PATCH 0283/1007] various: do not propagate exception through dtor Coverity 189689, 189690, 189692, 189695 --- contrib/epee/include/mlocker.h | 2 +- contrib/epee/src/mlocker.cpp | 3 ++- src/common/http_connection.h | 3 ++- src/wallet/wallet2.cpp | 7 ++++++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/contrib/epee/include/mlocker.h b/contrib/epee/include/mlocker.h index d2fc2ed58..a6d94b3d2 100644 --- a/contrib/epee/include/mlocker.h +++ b/contrib/epee/include/mlocker.h @@ -73,7 +73,7 @@ namespace epee mlocked(const T &&t): T(t) { mlocker::lock(this, sizeof(T)); } mlocked(const mlocked &&mt): T(mt) { mlocker::lock(this, sizeof(T)); } mlocked &operator=(const mlocked &mt) { T::operator=(mt); return *this; } - ~mlocked() { mlocker::unlock(this, sizeof(T)); } + ~mlocked() { try { mlocker::unlock(this, sizeof(T)); } catch (...) { /* do not propagate */ } } }; template diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index 5573d591a..eb863b9af 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -108,7 +108,8 @@ namespace epee mlocker::~mlocker() { - unlock(ptr, len); + try { unlock(ptr, len); } + catch (...) { /* ignore and do not propagate through the dtor */ } } void mlocker::lock(void *ptr, size_t len) diff --git a/src/common/http_connection.h b/src/common/http_connection.h index 9fc6be261..554dd832b 100644 --- a/src/common/http_connection.h +++ b/src/common/http_connection.h @@ -55,7 +55,8 @@ class t_http_connection { { if (m_ok) { - mp_http_client->disconnect(); + try { mp_http_client->disconnect(); } + catch (...) { /* do not propagate through dtor */ } } } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6f919d12c..0eda7f52d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -815,7 +815,12 @@ wallet_keys_unlocker::~wallet_keys_unlocker() { if (!locked) return; - w.encrypt_keys(key); + try { w.encrypt_keys(key); } + catch (...) + { + MERROR("Failed to re-encrypt wallet keys"); + // do not propagate through dtor, we'd crash + } } wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): From bd98e99c8095cf05c4d3282c888a87745ad1c559 Mon Sep 17 00:00:00 2001 From: Martijn Otto Date: Thu, 15 Nov 2018 17:29:34 +0100 Subject: [PATCH 0284/1007] Removed a lot of unnecessary includes --- .../epee/include/net/abstract_tcp_server2.h | 1 - .../epee/include/net/abstract_tcp_server2.inl | 5 +-- contrib/epee/include/net/connection_basic.hpp | 13 +------- .../epee/include/net/http_server_impl_base.h | 3 +- contrib/epee/src/connection_basic.cpp | 33 ------------------- contrib/epee/src/net_utils_base.cpp | 2 -- contrib/epee/src/network_throttle-detail.cpp | 16 --------- contrib/epee/src/readline_buffer.cpp | 4 +-- contrib/epee/tests/src/net/test_net.h | 4 ++- src/blockchain_db/blockchain_db.h | 1 - src/blockchain_db/lmdb/db_lmdb.cpp | 2 -- src/checkpoints/checkpoints.cpp | 8 ++--- src/checkpoints/checkpoints.h | 1 - src/common/base58.cpp | 1 - src/common/command_line.cpp | 3 -- src/common/dns_utils.cpp | 2 -- src/common/download.cpp | 3 -- src/common/i18n.cpp | 2 -- src/common/password.cpp | 3 -- src/common/threadpool.cpp | 4 --- src/crypto/crypto.cpp | 1 - src/crypto/crypto.h | 3 -- .../cryptonote_format_utils.cpp | 5 ++- src/cryptonote_basic/miner.cpp | 31 ++++++++--------- src/cryptonote_basic/miner.h | 5 --- src/cryptonote_core/cryptonote_core.cpp | 3 -- src/cryptonote_core/cryptonote_core.h | 1 - .../cryptonote_protocol_handler-base.cpp | 22 ------------- src/daemonizer/posix_fork.cpp | 1 - src/mnemonics/electrum-words.cpp | 8 ----- src/mnemonics/electrum-words.h | 1 - src/p2p/net_node.h | 4 ++- src/ringct/bulletproofs.cc | 1 + src/rpc/zmq_server.cpp | 1 - src/wallet/node_rpc_proxy.cpp | 1 - src/wallet/ringdb.cpp | 1 + src/wallet/wallet2.h | 2 ++ tests/net_load_tests/net_load_tests.h | 2 -- .../epee_levin_protocol_handler_async.cpp | 2 +- 39 files changed, 38 insertions(+), 168 deletions(-) diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 3f726a352..0c2d504d0 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -36,7 +36,6 @@ #define _ABSTRACT_TCP_SERVER2_H_ -#include #include #include #include diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 9b03941ee..ed66ae720 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -32,16 +32,13 @@ -//#include "net_utils_base.h" -#include +#include #include -#include #include #include #include #include #include // TODO -#include // TODO #include // TODO #include "warnings.h" #include "string_tools.h" diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 7e8750047..9b6fc14a7 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -42,22 +42,11 @@ #define INCLUDED_p2p_connection_basic_hpp -#include #include -#include -#include -#include #include +#include #include -#include -#include -#include -#include -#include -#include - -#include #include "net/net_utils_base.h" #include "syncobj.h" diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 1a97e610a..5669824c1 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -33,7 +33,8 @@ #include #include -#include "net/http_server_cp2.h" +#include "net/abstract_tcp_server2.h" +#include "http_protocol_handler.h" #include "net/http_server_handlers_map2.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 9ab485839..7d145ee46 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -34,47 +34,15 @@ #include "net/connection_basic.hpp" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "syncobj.h" - #include "net/net_utils_base.h" #include "misc_log_ex.h" -#include -#include -#include -#include -#include -#include #include #include -#include #include "misc_language.h" #include "pragma_comp_defs.h" -#include -#include #include -#include -#include #include -#include -#include "net/abstract_tcp_server2.h" // TODO: #include "net/network_throttle-detail.hpp" @@ -161,7 +129,6 @@ connection_basic::connection_basic(boost::asio::io_service& io_service, std::ato try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ; _note("Spawned connection p2p#"<m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_ref_sock_count); - //boost::filesystem::create_directories("log/dr-monero/net/"); } connection_basic::~connection_basic() noexcept(false) { diff --git a/contrib/epee/src/net_utils_base.cpp b/contrib/epee/src/net_utils_base.cpp index 2f4015e81..354c3d2c3 100644 --- a/contrib/epee/src/net_utils_base.cpp +++ b/contrib/epee/src/net_utils_base.cpp @@ -2,8 +2,6 @@ #include "net/net_utils_base.h" #include "string_tools.h" -#include -#include #include "net/local_ip.h" namespace epee { namespace net_utils diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index 28c85bb78..b436e07fd 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -32,20 +32,11 @@ /* rfree: implementation for throttle details */ -#include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include #include @@ -53,14 +44,7 @@ #include "net/net_utils_base.h" #include "misc_log_ex.h" -#include -#include -#include #include -#include -#include -#include -#include #include "misc_language.h" #include "pragma_comp_defs.h" #include diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp index da264471f..c5949da0a 100644 --- a/contrib/epee/src/readline_buffer.cpp +++ b/contrib/epee/src/readline_buffer.cpp @@ -1,9 +1,9 @@ #include "readline_buffer.h" #include #include -#include #include -#include +#include +#include #include static void install_line_handler(); diff --git a/contrib/epee/tests/src/net/test_net.h b/contrib/epee/tests/src/net/test_net.h index 04fef089c..51b1f1ec6 100644 --- a/contrib/epee/tests/src/net/test_net.h +++ b/contrib/epee/tests/src/net/test_net.h @@ -29,7 +29,9 @@ #include #include -#include "net/levin_server_cp2.h" +#include "net/abstract_tcp_server2.h" +#include "net/levin_protocol_handler.h" +#include "net/levin_protocol_handler_async.h" #include "storages/abstract_invoke.h" namespace epee diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 71c46d76b..c0a2f883b 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -30,7 +30,6 @@ #pragma once -#include #include #include #include diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 1674c40dd..49d45f4b6 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -29,10 +29,8 @@ #include #include -#include #include // std::unique_ptr #include // memcpy -#include #include "string_tools.h" #include "file_io_utils.h" diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index 6251fcc91..1807d44d9 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -28,17 +28,15 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -#include "include_base_utils.h" - -using namespace epee; - #include "checkpoints.h" #include "common/dns_utils.h" -#include "include_base_utils.h" #include "string_tools.h" #include "storages/portable_storage_template_helper.h" // epee json include #include "serialization/keyvalue_serialization.h" +#include + +using namespace epee; #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "checkpoints" diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h index 61be2c27a..ad2b44d1a 100644 --- a/src/checkpoints/checkpoints.h +++ b/src/checkpoints/checkpoints.h @@ -30,7 +30,6 @@ #pragma once #include -#include #include "misc_log_ex.h" #include "crypto/hash.h" #include "cryptonote_config.h" diff --git a/src/common/base58.cpp b/src/common/base58.cpp index 75556cad9..3ad2c44b0 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -36,7 +36,6 @@ #include "crypto/hash.h" #include "int-util.h" -#include "util.h" #include "varint.h" namespace tools diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 7980b381f..35135ea18 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -31,10 +31,7 @@ #include "command_line.h" #include #include -#include #include "common/i18n.h" -#include "cryptonote_config.h" -#include "string_tools.h" namespace command_line { diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index f2b270981..1d38fbf42 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -33,12 +33,10 @@ #include #include "include_base_utils.h" #include -#include #include #include #include using namespace epee; -namespace bf = boost::filesystem; #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net.dns" diff --git a/src/common/download.cpp b/src/common/download.cpp index 6698a5abf..58ce0595f 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -29,10 +29,7 @@ #include #include #include -#include #include -#include "cryptonote_config.h" -#include "include_base_utils.h" #include "file_io_utils.h" #include "net/http_client.h" #include "download.h" diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp index 4a89876fb..ffe8d8b52 100644 --- a/src/common/i18n.cpp +++ b/src/common/i18n.cpp @@ -31,9 +31,7 @@ #include #include #include -#include "include_base_utils.h" #include "file_io_utils.h" -#include "common/util.h" #include "common/i18n.h" #include "translation_files.h" diff --git a/src/common/password.cpp b/src/common/password.cpp index b3c51128f..5f5cb800a 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -31,7 +31,6 @@ #include "password.h" #include -#include #include #if defined(_WIN32) @@ -42,8 +41,6 @@ #include #endif -#include "memwipe.h" - #define EOT 0x4 namespace diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 37825e31d..cbf7163c5 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -28,10 +28,6 @@ #include "misc_log_ex.h" #include "common/threadpool.h" -#include -#include -#include - #include "cryptonote_config.h" #include "common/util.h" diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index ad7721cf0..ddf072f68 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 33cc0a25a..f22df1230 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -32,14 +32,11 @@ #include #include -#include -#include #include #include #include #include "common/pod-class.h" -#include "common/util.h" #include "memwipe.h" #include "mlocker.h" #include "generic-ops.h" diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index e26aac76b..d41bc1087 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -28,9 +28,6 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers -#include "include_base_utils.h" -using namespace epee; - #include #include #include "wipeable_string.h" @@ -42,6 +39,8 @@ using namespace epee; #include "crypto/hash.h" #include "ringct/rctSigs.h" +using namespace epee; + #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "cn" diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index d8ca2dd35..9bc99f053 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -33,8 +33,6 @@ #include #include #include -#include -#include "include_base_utils.h" #include "misc_language.h" #include "syncobj.h" #include "cryptonote_basic_impl.h" @@ -54,19 +52,22 @@ #include #include #include -#endif - -#ifdef __FreeBSD__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#elif defined(__linux__) + #include + #include + #include + #include +#elif defined(__FreeBSD__) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include #endif #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index 2bff784c7..e16d9f3b8 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -38,11 +38,6 @@ #include "math_helper.h" #ifdef _WIN32 #include -#elif defined(__linux__) -#include -#include -#include -#include #endif namespace cryptonote diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index c405c996a..00537e8b7 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -30,13 +30,11 @@ #include -#include "include_base_utils.h" #include "string_tools.h" using namespace epee; #include #include "cryptonote_core.h" -#include "common/command_line.h" #include "common/util.h" #include "common/updates.h" #include "common/download.h" @@ -45,7 +43,6 @@ using namespace epee; #include "warnings.h" #include "crypto/crypto.h" #include "cryptonote_config.h" -#include "cryptonote_tx_utils.h" #include "misc_language.h" #include "file_io_utils.h" #include diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 4eca2a57b..7ddba77b2 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -34,7 +34,6 @@ #include #include -#include #include "cryptonote_protocol/cryptonote_protocol_handler_common.h" #include "storages/portable_storage_template_helper.h" diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index c9fd40d88..6d9ad9028 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp @@ -30,20 +30,8 @@ // 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. -#include #include #include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include #include @@ -51,24 +39,14 @@ #include "net/net_utils_base.h" #include "misc_log_ex.h" -#include -#include -#include #include -#include -#include #include #include #include "misc_language.h" #include "pragma_comp_defs.h" -#include -#include #include -#include -#include - #include "cryptonote_protocol_handler.h" #include "net/network_throttle.hpp" diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp index 3cbee9c51..5af4e1a4a 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #ifndef TMPDIR #define TMPDIR "/tmp" diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 94071c23c..e6d2a6b76 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -37,22 +37,14 @@ */ #include -#include -#include #include #include #include -#include #include "wipeable_string.h" #include "misc_language.h" -#include "crypto/crypto.h" // for declaration of crypto::secret_key -#include #include "common/int-util.h" #include "mnemonics/electrum-words.h" -#include -#include #include -#include #include "chinese_simplified.h" #include "english.h" diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h index 5401b9779..60d2c5f15 100644 --- a/src/mnemonics/electrum-words.h +++ b/src/mnemonics/electrum-words.h @@ -41,7 +41,6 @@ #include #include -#include #include "crypto/crypto.h" // for declaration of crypto::secret_key namespace epee { class wipeable_string; } diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 90e2f78b1..19908880f 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -38,7 +38,9 @@ #include "cryptonote_config.h" #include "warnings.h" -#include "net/levin_server_cp2.h" +#include "net/abstract_tcp_server2.h" +#include "net/levin_protocol_handler.h" +#include "net/levin_protocol_handler_async.h" #include "p2p_protocol_defs.h" #include "storages/levin_abstract_invoke2.h" #include "net_peerlist.h" diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index bed48769a..63365613d 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -30,6 +30,7 @@ #include #include +#include #include "misc_log_ex.h" #include "common/perf_timer.h" #include "cryptonote_config.h" diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp index edd3e6669..a2ff76668 100644 --- a/src/rpc/zmq_server.cpp +++ b/src/rpc/zmq_server.cpp @@ -27,7 +27,6 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "zmq_server.h" -#include namespace cryptonote { diff --git a/src/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index 346c052b5..605531e59 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.cpp @@ -28,7 +28,6 @@ #include "node_rpc_proxy.h" #include "rpc/core_rpc_server_commands_defs.h" -#include "common/json_util.h" #include "storages/http_abstract_invoke.h" using namespace epee; diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index f562d6c06..b69022af4 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.cpp @@ -30,6 +30,7 @@ #include #include #include +#include "common/util.h" #include "misc_log_ex.h" #include "misc_language.h" #include "wallet_errors.h" diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index dbfd45c53..d3435f0d5 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include "include_base_utils.h" @@ -49,6 +50,7 @@ #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_core/cryptonote_tx_utils.h" #include "common/unordered_containers_boost_serialization.h" +#include "common/util.h" #include "crypto/chacha.h" #include "crypto/hash.h" #include "ringct/rctTypes.h" diff --git a/tests/net_load_tests/net_load_tests.h b/tests/net_load_tests/net_load_tests.h index 7f3c6dfe9..7e92c21b9 100644 --- a/tests/net_load_tests/net_load_tests.h +++ b/tests/net_load_tests/net_load_tests.h @@ -137,7 +137,6 @@ namespace net_load_tests public: open_close_test_helper(test_tcp_server& tcp_server, size_t open_request_target, size_t max_opened_connection_count) : m_tcp_server(tcp_server) - , m_open_request_target(open_request_target) , m_max_opened_connection_count(max_opened_connection_count) , m_opened_connection_count(0) , m_next_opened_conn_idx(0) @@ -203,7 +202,6 @@ namespace net_load_tests private: test_tcp_server& m_tcp_server; - size_t m_open_request_target; size_t m_max_opened_connection_count; std::atomic m_opened_connection_count; std::atomic m_next_opened_conn_idx; diff --git a/tests/unit_tests/epee_levin_protocol_handler_async.cpp b/tests/unit_tests/epee_levin_protocol_handler_async.cpp index 72d8f3205..10e62c167 100644 --- a/tests/unit_tests/epee_levin_protocol_handler_async.cpp +++ b/tests/unit_tests/epee_levin_protocol_handler_async.cpp @@ -294,7 +294,7 @@ TEST_F(positive_test_connection_to_levin_protocol_handler_calls, handler_initial TEST_F(positive_test_connection_to_levin_protocol_handler_calls, concurent_handler_initialization_and_destruction_is_correct) { const size_t connection_count = 10000; - auto create_and_destroy_connections = [this, connection_count]() + auto create_and_destroy_connections = [this]() { std::vector connections(connection_count); for (size_t i = 0; i < connection_count; ++i) From c5ee14ae6e0a70ec229b1b4077326bf7e9953c59 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 7 Nov 2018 21:56:13 +0000 Subject: [PATCH 0285/1007] json_archive: initialize inner_array_size in ctor Coverity 136581 --- src/serialization/json_archive.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h index f906b5d3b..04436c21c 100644 --- a/src/serialization/json_archive.h +++ b/src/serialization/json_archive.h @@ -113,7 +113,7 @@ struct json_archive; template <> struct json_archive : public json_archive_base { - json_archive(stream_type &s, bool indent = false) : base_type(s, indent) { } + json_archive(stream_type &s, bool indent = false) : base_type(s, indent), inner_array_size_(0) { } template static auto promote_to_printable_integer_type(T v) -> decltype(+v) From f6187cd8111e5f7e812d7a153f8cd64ac2c04cb9 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 14 Nov 2018 21:56:32 +0000 Subject: [PATCH 0286/1007] epee: speed up parse_hexstr_to_binbuff a little --- contrib/epee/include/string_tools.h | 50 ++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index aba065cc7..6a063cc36 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -59,6 +59,26 @@ #pragma comment (lib, "Rpcrt4.lib") #endif +static const constexpr unsigned char isx[256] = +{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + namespace epee { namespace string_tools @@ -98,30 +118,30 @@ namespace string_tools } //---------------------------------------------------------------------------- template - bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res, bool allow_partial_byte = false) + bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res) { res.clear(); - if (!allow_partial_byte && (s.size() & 1)) + if (s.size() & 1) return false; try { - long v = 0; - for(size_t i = 0; i < (s.size() + 1) / 2; i++) + res.resize(s.size() / 2); + unsigned char *dst = (unsigned char *)res.data(); + const unsigned char *src = (const unsigned char *)s.data(); + for(size_t i = 0; i < s.size(); i += 2) { - CharT byte_str[3]; - size_t copied = s.copy(byte_str, 2, 2 * i); - byte_str[copied] = CharT(0); - CharT* endptr; - v = strtoul(byte_str, &endptr, 16); - if (v < 0 || 0xFF < v || endptr != byte_str + copied) - { - return false; - } - res.push_back(static_cast(v)); + int tmp = *src++; + tmp = isx[tmp]; + if (tmp == 0xff) return false; + int t2 = *src++; + t2 = isx[t2]; + if (t2 == 0xff) return false; + *dst++ = (tmp << 4) | t2; } return true; - }catch(...) + } + catch(...) { return false; } From 6671110ca3db97f1169dd853fbb22ad725708e4a Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 15 Nov 2018 12:40:55 +0000 Subject: [PATCH 0287/1007] unit_tests: add a test for parse_hexstr_to_binbuff --- tests/unit_tests/epee_utils.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index c2b0b7647..b3c812dca 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -456,6 +456,19 @@ TEST(StringTools, PodToHex) ); } +TEST(StringTools, ParseHex) +{ + static const char data[] = "a10b68c2"; + for (size_t i = 0; i < sizeof(data); i += 2) + { + std::string res; + ASSERT_TRUE(epee::string_tools::parse_hexstr_to_binbuff(std::string(data, i), res)); + std::string hex = epee::string_tools::buff_to_hex_nodelimer(res); + ASSERT_EQ(hex.size(), i); + ASSERT_EQ(memcmp(data, hex.data(), i), 0); + } +} + TEST(StringTools, GetIpString) { EXPECT_EQ( From b36353e2681825474a9ddc6a6ccfe6098995a9f5 Mon Sep 17 00:00:00 2001 From: xiphon Date: Thu, 15 Nov 2018 23:32:42 +0000 Subject: [PATCH 0288/1007] unit_tests: add some hex parsing test for non hex input --- tests/unit_tests/epee_utils.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index b3c812dca..c384ce9a5 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -469,6 +469,22 @@ TEST(StringTools, ParseHex) } } +TEST(StringTools, ParseNotHex) +{ + std::string res; + for (size_t i = 0; i < 256; ++i) + { + std::string inputHexString = std::string(2, static_cast(i)); + if ((i >= '0' && i <= '9') || (i >= 'A' && i <= 'F') || (i >= 'a' && i <= 'f')) { + ASSERT_TRUE(epee::string_tools::parse_hexstr_to_binbuff(inputHexString, res)); + } else { + ASSERT_FALSE(epee::string_tools::parse_hexstr_to_binbuff(inputHexString, res)); + } + } + + ASSERT_FALSE(epee::string_tools::parse_hexstr_to_binbuff(std::string("a"), res)); +} + TEST(StringTools, GetIpString) { EXPECT_EQ( From 6f2497bc7ac1865329527947afd6dacb0b1b6a06 Mon Sep 17 00:00:00 2001 From: doy-lee Date: Fri, 16 Nov 2018 15:32:05 +1100 Subject: [PATCH 0289/1007] Don't cache nettype in core_rpc_server use m_core This can go out of sync with m_core's nettype if you run in fakechain mode since entering fakechain mode is done through code not the command line and core_rpc_server only looks at the command line to figure out the nettype. --- src/daemon/daemon.cpp | 7 ++----- src/daemon/rpc.h | 3 +-- src/rpc/core_rpc_server.cpp | 30 +++++++++++++++++------------- src/rpc/core_rpc_server.h | 3 +-- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 49d6d49cf..13478f39d 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -75,18 +75,15 @@ struct t_internals { protocol.set_p2p_endpoint(p2p.get()); core.set_protocol(protocol.get()); - const auto testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); - const auto stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); - const auto regtest = command_line::get_arg(vm, cryptonote::arg_regtest_on); const auto restricted = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_restricted_rpc); const auto main_rpc_port = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_port); - rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : regtest ? cryptonote::FAKECHAIN : cryptonote::MAINNET, main_rpc_port, "core"}); + rpcs.emplace_back(new t_rpc{vm, core, p2p, restricted, main_rpc_port, "core"}); auto restricted_rpc_port_arg = cryptonote::core_rpc_server::arg_rpc_restricted_bind_port; if(!command_line::is_arg_defaulted(vm, restricted_rpc_port_arg)) { auto restricted_rpc_port = command_line::get_arg(vm, restricted_rpc_port_arg); - rpcs.emplace_back(new t_rpc{vm, core, p2p, true, testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, restricted_rpc_port, "restricted"}); + rpcs.emplace_back(new t_rpc{vm, core, p2p, true, restricted_rpc_port, "restricted"}); } } }; diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index 9621b0d01..37dffc097 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -54,7 +54,6 @@ class t_rpc final , t_core & core , t_p2p & p2p , const bool restricted - , const cryptonote::network_type nettype , const std::string & port , const std::string & description ) @@ -62,7 +61,7 @@ class t_rpc final { MGINFO("Initializing " << m_description << " RPC server..."); - if (!m_server.init(vm, restricted, nettype, port)) + if (!m_server.init(vm, restricted, port)) { throw std::runtime_error("Failed to initialize " + m_description + " RPC server."); } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c2e71bef8..6bf34e9fd 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -91,12 +91,10 @@ namespace cryptonote bool core_rpc_server::init( const boost::program_options::variables_map& vm , const bool restricted - , const network_type nettype , const std::string& port ) { m_restricted = restricted; - m_nettype = nettype; m_net_server.set_threads_prefix("RPC"); auto rpc_config = cryptonote::rpc_args::process(vm); @@ -191,10 +189,13 @@ namespace cryptonote res.rpc_connections_count = get_connections_count(); res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.mainnet = m_nettype == MAINNET; - res.testnet = m_nettype == TESTNET; - res.stagenet = m_nettype == STAGENET; - res.nettype = m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : m_nettype == STAGENET ? "stagenet" : "fakechain"; + + cryptonote::network_type net_type = nettype(); + res.mainnet = net_type == MAINNET; + res.testnet = net_type == TESTNET; + res.stagenet = net_type == STAGENET; + res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain"; + res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit(); res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median(); @@ -750,7 +751,7 @@ namespace cryptonote PERF_TIMER(on_start_mining); CHECK_CORE_READY(); cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, m_nettype, req.miner_address)) + if(!get_account_address_from_str(info, nettype(), req.miner_address)) { res.status = "Failed, wrong address"; LOG_PRINT_L0(res.status); @@ -831,7 +832,7 @@ namespace cryptonote res.speed = lMiner.get_speed(); res.threads_count = lMiner.get_threads_count(); const account_public_address& lMiningAdr = lMiner.get_mining_address(); - res.address = get_account_address_as_str(m_nettype, false, lMiningAdr); + res.address = get_account_address_as_str(nettype(), false, lMiningAdr); } res.status = CORE_RPC_STATUS_OK; @@ -1064,7 +1065,7 @@ namespace cryptonote cryptonote::address_parse_info info; - if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, m_nettype, req.wallet_address)) + if(!req.wallet_address.size() || !cryptonote::get_account_address_from_str(info, nettype(), req.wallet_address)) { error_resp.code = CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS; error_resp.message = "Failed to parse wallet address"; @@ -1590,10 +1591,13 @@ namespace cryptonote res.rpc_connections_count = get_connections_count(); res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); - res.mainnet = m_nettype == MAINNET; - res.testnet = m_nettype == TESTNET; - res.stagenet = m_nettype == STAGENET; - res.nettype = m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : m_nettype == STAGENET ? "stagenet" : "fakechain"; + + cryptonote::network_type net_type = nettype(); + res.mainnet = net_type == MAINNET; + res.testnet = net_type == TESTNET; + res.stagenet = net_type == STAGENET; + res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain"; + res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit(); res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median(); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 3ba882b23..8f0d6112c 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -70,10 +70,9 @@ namespace cryptonote bool init( const boost::program_options::variables_map& vm, const bool restricted, - const network_type nettype, const std::string& port ); - network_type nettype() const { return m_nettype; } + network_type nettype() const { return m_core.get_nettype(); } CHAIN_HTTP_TO_MAP2(connection_context); //forward http requests to uri map From b39fdf8ebe5a19d43be53813f93f107b7410f39e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 13:27:51 +0000 Subject: [PATCH 0290/1007] slow-hash: fix for big endian --- src/crypto/slow-hash.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index ed61e1017..0e753f1d9 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -109,8 +109,8 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex memcpy(b + AES_BLOCK_SIZE, state.hs.b + 64, AES_BLOCK_SIZE); \ xor64(b + AES_BLOCK_SIZE, state.hs.b + 80); \ xor64(b + AES_BLOCK_SIZE + 8, state.hs.b + 88); \ - division_result = state.hs.w[12]; \ - sqrt_result = state.hs.w[13]; \ + division_result = SWAP64LE(state.hs.w[12]); \ + sqrt_result = SWAP64LE(state.hs.w[13]); \ } while (0) #define VARIANT2_SHUFFLE_ADD_SSE2(base_ptr, offset) \ @@ -145,30 +145,31 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \ \ uint64_t b1[2]; \ - memcpy(b1, b + 16, 16); \ - chunk1[0] = chunk3[0] + b1[0]; \ - chunk1[1] = chunk3[1] + b1[1]; \ + memcpy_swap64le(b1, b + 16, 2); \ + chunk1[0] = SWAP64LE(chunk3[0] + b1[0]); \ + chunk1[1] = SWAP64LE(chunk3[1] + b1[1]); \ \ uint64_t a0[2]; \ - memcpy(a0, a, 16); \ - chunk3[0] = chunk2[0] + a0[0]; \ - chunk3[1] = chunk2[1] + a0[1]; \ + memcpy_swap64le(a0, a, 2); \ + chunk3[0] = SWAP64LE(chunk2[0] + a0[0]); \ + chunk3[1] = SWAP64LE(chunk2[1] + a0[1]); \ \ uint64_t b0[2]; \ - memcpy(b0, b, 16); \ - chunk2[0] = chunk1_old[0] + b0[0]; \ - chunk2[1] = chunk1_old[1] + b0[1]; \ + memcpy_swap64le(b0, b, 2); \ + chunk2[0] = SWAP64LE(chunk1_old[0] + b0[0]); \ + chunk2[1] = SWAP64LE(chunk1_old[1] + b0[1]); \ } while (0) #define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \ - ((uint64_t*)(b))[0] ^= division_result ^ (sqrt_result << 32); \ + uint64_t tmpx = division_result ^ (sqrt_result << 32); \ + ((uint64_t*)(b))[0] ^= SWAP64LE(tmpx); \ { \ - const uint64_t dividend = ((uint64_t*)(ptr))[1]; \ - const uint32_t divisor = (((uint64_t*)(ptr))[0] + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \ + const uint64_t dividend = SWAP64LE(((uint64_t*)(ptr))[1]); \ + const uint32_t divisor = (SWAP64LE(((uint64_t*)(ptr))[0]) + (uint32_t)(sqrt_result << 1)) | 0x80000001UL; \ division_result = ((uint32_t)(dividend / divisor)) + \ (((uint64_t)(dividend % divisor)) << 32); \ } \ - const uint64_t sqrt_input = ((uint64_t*)(ptr))[0] + division_result + const uint64_t sqrt_input = SWAP64LE(((uint64_t*)(ptr))[0]) + division_result #define VARIANT2_INTEGER_MATH_SSE2(b, ptr) \ do if (variant >= 2) \ @@ -207,10 +208,10 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex #define VARIANT2_2() \ do if (variant >= 2) \ { \ - *U64(hp_state + (j ^ 0x10)) ^= hi; \ - *(U64(hp_state + (j ^ 0x10)) + 1) ^= lo; \ - hi ^= *U64(hp_state + (j ^ 0x20)); \ - lo ^= *(U64(hp_state + (j ^ 0x20)) + 1); \ + *U64(hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \ + *(U64(hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \ + hi ^= SWAP64LE(*U64(hp_state + (j ^ 0x20))); \ + lo ^= SWAP64LE(*(U64(hp_state + (j ^ 0x20)) + 1)); \ } while (0) @@ -1408,7 +1409,7 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = { hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein }; -static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); } +static size_t e2i(const uint8_t* a, size_t count) { return (SWAP64LE(*((uint64_t*)a)) / AES_BLOCK_SIZE) & (count - 1); } static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) { uint64_t a0, b0; From 2a48c2a2868ca8f2b55468c1de71336c0e440d8b Mon Sep 17 00:00:00 2001 From: xiphon Date: Fri, 2 Nov 2018 09:33:30 +0000 Subject: [PATCH 0291/1007] slow-hash: some more big endian fixes --- src/crypto/slow-hash.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 0e753f1d9..dcbabccab 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -146,18 +146,18 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex \ uint64_t b1[2]; \ memcpy_swap64le(b1, b + 16, 2); \ - chunk1[0] = SWAP64LE(chunk3[0] + b1[0]); \ - chunk1[1] = SWAP64LE(chunk3[1] + b1[1]); \ + chunk1[0] = SWAP64LE(SWAP64LE(chunk3[0]) + b1[0]); \ + chunk1[1] = SWAP64LE(SWAP64LE(chunk3[1]) + b1[1]); \ \ uint64_t a0[2]; \ memcpy_swap64le(a0, a, 2); \ - chunk3[0] = SWAP64LE(chunk2[0] + a0[0]); \ - chunk3[1] = SWAP64LE(chunk2[1] + a0[1]); \ + chunk3[0] = SWAP64LE(SWAP64LE(chunk2[0]) + a0[0]); \ + chunk3[1] = SWAP64LE(SWAP64LE(chunk2[1]) + a0[1]); \ \ uint64_t b0[2]; \ memcpy_swap64le(b0, b, 2); \ - chunk2[0] = SWAP64LE(chunk1_old[0] + b0[0]); \ - chunk2[1] = SWAP64LE(chunk1_old[1] + b0[1]); \ + chunk2[0] = SWAP64LE(SWAP64LE(chunk1_old[0]) + b0[0]); \ + chunk2[1] = SWAP64LE(SWAP64LE(chunk1_old[1]) + b0[1]); \ } while (0) #define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \ From 872c7eb26abec64478e8c2f68e13f12b93b7ed46 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 6 Nov 2018 11:02:27 +0000 Subject: [PATCH 0292/1007] Revert "blockchain: simplify output distribution code" This reverts commit b2bb9312a75781e714acf3c406634b3d4cded418. --- src/cryptonote_core/blockchain.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index f3105114e..030798ad7 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1831,10 +1831,15 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, { std::vector heights; heights.reserve(to_height + 1 - start_height); - for (uint64_t h = start_height; h <= to_height; ++h) + uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height; + for (uint64_t h = real_start_height; h <= to_height; ++h) heights.push_back(h); distribution = m_db->get_block_cumulative_rct_outputs(heights); - base = 0; + if (start_height > 0) + { + base = distribution[0]; + distribution.erase(distribution.begin()); + } return true; } else From 0936dae8a4efc62f4ca54c4872ee2562961372df Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 6 Nov 2018 14:21:57 +0000 Subject: [PATCH 0293/1007] blockchain: remove "0 is height" shortcut from get_output_distribution This prevents asking for just 0, and the RPC layer already does this --- src/cryptonote_core/blockchain.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 030798ad7..798f67e09 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1823,8 +1823,6 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t db_height = m_db->height(); if (db_height == 0) return false; - if (to_height == 0) - to_height = db_height - 1; if (start_height >= db_height || to_height >= db_height) return false; if (amount == 0) From 3900fb779fbd3ebdb0eeb8c9d574bdd85c35ecf3 Mon Sep 17 00:00:00 2001 From: Tadeas Moravec Date: Fri, 16 Nov 2018 14:53:31 +0000 Subject: [PATCH 0294/1007] Enhance help text for incoming_transfers. --- src/simplewallet/simplewallet.cpp | 8 +++++--- translations/monero.ts | 7 +++++-- translations/monero_fr.ts | 11 +++++++---- translations/monero_it.ts | 9 ++++++--- translations/monero_ja.ts | 7 +++++-- translations/monero_sv.ts | 11 +++++++---- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 702ff22cb..505e5525e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2347,7 +2347,9 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), tr("incoming_transfers [available|unavailable] [verbose] [index=[,[,...]]]"), - tr("Show the incoming transfers, all or filtered by availability and address index.")); + tr("Show the incoming transfers, all or filtered by availability and address index.\n\n" + "Output format:\n" + "Amount, Spent(\"T\"|\"F\"), \"locked\"|\"unlocked\", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] ")); m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), tr("payments [ ... ]"), @@ -4435,7 +4437,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args { if (args.size() > 3) { - fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]"); + fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=[,[,...]]]"); return true; } auto local_args = args; @@ -4477,7 +4479,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector& args if (local_args.size() > 0) { - fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]"); + fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=[,[,...]]]"); return true; } diff --git a/translations/monero.ts b/translations/monero.ts index e28a2a058..d17317ae9 100644 --- a/translations/monero.ts +++ b/translations/monero.ts @@ -1453,7 +1453,10 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 - Show the incoming transfers, all or filtered by availability and address index. + Show the incoming transfers, all or filtered by availability and address index. + +Output format: +Amount, Spent("T"|"F"), "locked"|"unlocked", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] @@ -2826,7 +2829,7 @@ your wallet again (your wallet keys are NOT at risk in any case). - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts index 27c38ee10..19a125fdb 100644 --- a/translations/monero_fr.ts +++ b/translations/monero_fr.ts @@ -1541,8 +1541,11 @@ Cette transaction sera déverrouillée au bloc %llu, dans approximativement %s j - Show the incoming transfers, all or filtered by availability and address index. - Afficher les transferts entrants, tous ou filtrés par disponibilité et index d'adresse. + Show the incoming transfers, all or filtered by availability and address index. + +Output format: +Amount, Spent("T"|"F"), "locked"|"unlocked", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] + Afficher les transferts entrants, tous ou filtrés par disponibilité et index d'adresse. @@ -2271,8 +2274,8 @@ votre portefeuille à nouveau (mais les clés de votre portefeuille ne risquent - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] diff --git a/translations/monero_it.ts b/translations/monero_it.ts index 5ab96d7dc..09872fea8 100644 --- a/translations/monero_it.ts +++ b/translations/monero_it.ts @@ -1364,8 +1364,11 @@ Questa transazione verrà sbloccata al blocco %llu, in approssimativamente %s gi - Show the incoming transfers, all or filtered by availability and address index. - Mostra i trasferimenti in entrata, tutti o filtrati per disponibilità ed indice di indirizzo. + Show the incoming transfers, all or filtered by availability and address index. + +Output format: +Amount, Spent("T"|"F"), "locked"|"unlocked", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] + Mostra i trasferimenti in entrata, tutti o filtrati per disponibilità ed indice di indirizzo. @@ -2191,7 +2194,7 @@ your wallet again (your wallet keys are NOT at risk in any case). - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] diff --git a/translations/monero_ja.ts b/translations/monero_ja.ts index 17815d982..7305b42f8 100644 --- a/translations/monero_ja.ts +++ b/translations/monero_ja.ts @@ -1461,7 +1461,10 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 - Show the incoming transfers, all or filtered by availability and address index. + Show the incoming transfers, all or filtered by availability and address index. + +Output format: +Amount, Spent("T"|"F"), "locked"|"unlocked", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] @@ -2279,7 +2282,7 @@ your wallet again (your wallet keys are NOT at risk in any case). - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] diff --git a/translations/monero_sv.ts b/translations/monero_sv.ts index b2387cdb1..26ad43f7b 100644 --- a/translations/monero_sv.ts +++ b/translations/monero_sv.ts @@ -1469,8 +1469,11 @@ Denna transaktion låses upp vid block %llu, om ungefär %s dagar (förutsatt en - Show the incoming transfers, all or filtered by availability and address index. - Visa inkommande överföringar: alla eller filtrerade efter tillgänglighet och adressindex. + Show the incoming transfers, all or filtered by availability and address index. + +Output format: +Amount, Spent("T"|"F"), "locked"|"unlocked", RingCT, Global Index, Transaction Hash, Address Index, [Public Key, Key Image] + Visa inkommande överföringar: alla eller filtrerade efter tillgänglighet och adressindex. @@ -2351,8 +2354,8 @@ din plånbok igen (din plånboks nycklar är dock INTE hotade i vilket fall som - usage: incoming_transfers [available|unavailable] [verbose] [index=<N>] - användning: incoming_transfers [available|unavailable] [verbose] [index=<N>] + usage: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] + användning: incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] From 3998a937e506cef027fa267adce16425ed6193d4 Mon Sep 17 00:00:00 2001 From: Tadeas Moravec Date: Fri, 16 Nov 2018 15:15:35 +0000 Subject: [PATCH 0295/1007] Enhance help text for print_ring. --- src/simplewallet/simplewallet.cpp | 6 ++++-- translations/monero.ts | 7 +++++-- translations/monero_fr.ts | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 505e5525e..1b86e0ec5 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1408,7 +1408,7 @@ bool simple_wallet::print_ring(const std::vector &args) crypto::hash txid; if (args.size() != 1) { - fail_msg_writer() << tr("usage: print_ring "); + fail_msg_writer() << tr("usage: print_ring | "); return true; } @@ -2653,7 +2653,9 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("print_ring", boost::bind(&simple_wallet::print_ring, this, _1), tr("print_ring | "), - tr("Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1)")); + tr("Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1)\n\n" + "Output format:\n" + "Key Image, \"absolute\", list of rings")); m_cmd_binder.set_handler("set_ring", boost::bind(&simple_wallet::set_ring, this, _1), tr("set_ring | ( absolute|relative [...] )"), diff --git a/translations/monero.ts b/translations/monero.ts index d17317ae9..23eadff84 100644 --- a/translations/monero.ts +++ b/translations/monero.ts @@ -1196,7 +1196,7 @@ This transaction will unlock on block %llu, in approximately %s days (assuming 2 - usage: print_ring <key_image|txid> + usage: print_ring <key_image> | <txid> @@ -1979,7 +1979,10 @@ Pending or Failed: "failed"|"pending", "o - Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) + Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) + +Output format: +Key Image, "absolute", list of rings diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts index 19a125fdb..238ba17df 100644 --- a/translations/monero_fr.ts +++ b/translations/monero_fr.ts @@ -2987,8 +2987,11 @@ subaddress-lookahead <major>:<minor> - Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) - Afficher le(s) cercle(s) utilisé(s) pour dépenser une image de clé ou une transaction (si la taille de cercle est > 1) + Print the ring(s) used to spend a given key image or transaction (if the ring size is > 1) + +Output format: +Key Image, "absolute", list of rings + Afficher le(s) cercle(s) utilisé(s) pour dépenser une image de clé ou une transaction (si la taille de cercle est > 1) From 31d80027b5cc59b48205334a9e361c6a75099592 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 6 Nov 2018 14:23:26 +0000 Subject: [PATCH 0296/1007] tests: add unit tests for get_output_distribution --- src/cryptonote_core/blockchain.cpp | 1 + src/rpc/core_rpc_server.cpp | 2 +- src/rpc/daemon_handler.cpp | 2 +- src/rpc/rpc_handler.cpp | 4 +- src/rpc/rpc_handler.h | 2 +- tests/unit_tests/CMakeLists.txt | 1 + tests/unit_tests/hardfork.cpp | 94 +------------ tests/unit_tests/output_distribution.cpp | 171 +++++++++++++++++++++++ tests/unit_tests/testdb.h | 146 +++++++++++++++++++ 9 files changed, 331 insertions(+), 92 deletions(-) create mode 100644 tests/unit_tests/output_distribution.cpp create mode 100644 tests/unit_tests/testdb.h diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 798f67e09..e80e3f66c 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1805,6 +1805,7 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, case STAGENET: start_height = stagenet_hard_forks[3].height; break; case TESTNET: start_height = testnet_hard_forks[3].height; break; case MAINNET: start_height = mainnet_hard_forks[3].height; break; + case FAKECHAIN: start_height = 0; break; default: return false; } } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c2e71bef8..df9eee781 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -2125,7 +2125,7 @@ namespace cryptonote const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (uint64_t amount: req.amounts) { - auto data = rpc::RpcHandler::get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative); + auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative); if (!data) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 8822bd378..64a5cc858 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -751,7 +751,7 @@ namespace rpc const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); for (std::uint64_t amount : req.amounts) { - auto data = get_output_distribution(m_core, amount, req.from_height, req_to_height, req.cumulative); + auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative); if (!data) { res.distributions.clear(); diff --git a/src/rpc/rpc_handler.cpp b/src/rpc/rpc_handler.cpp index d4beb1928..63664bf8b 100644 --- a/src/rpc/rpc_handler.cpp +++ b/src/rpc/rpc_handler.cpp @@ -26,7 +26,7 @@ namespace rpc } boost::optional - RpcHandler::get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative) + RpcHandler::get_output_distribution(const std::function&, uint64_t&)> &f, uint64_t amount, uint64_t from_height, uint64_t to_height, bool cumulative) { static struct D { @@ -43,7 +43,7 @@ namespace rpc std::vector distribution; std::uint64_t start_height, base; - if (!src.get_output_distribution(amount, from_height, to_height, start_height, distribution, base)) + if (!f(amount, from_height, to_height, start_height, distribution, base)) return boost::none; if (to_height > 0 && to_height >= from_height) diff --git a/src/rpc/rpc_handler.h b/src/rpc/rpc_handler.h index 3cccef78a..e0d520408 100644 --- a/src/rpc/rpc_handler.h +++ b/src/rpc/rpc_handler.h @@ -56,7 +56,7 @@ class RpcHandler virtual std::string handle(const std::string& request) = 0; static boost::optional - get_output_distribution(core& src, std::uint64_t amount, std::uint64_t from_height, std::uint64_t to_height, bool cumulative); + get_output_distribution(const std::function&, uint64_t&)> &f, uint64_t amount, uint64_t from_height, uint64_t to_height, bool cumulative); }; diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 7687e3c52..a46f11b5f 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -62,6 +62,7 @@ set(unit_tests_sources multiexp.cpp multisig.cpp notify.cpp + output_distribution.cpp parse_amount.cpp random.cpp serialization.cpp diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index fc488bb14..ec8d1d202 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -34,101 +34,19 @@ #include "blockchain_db/blockchain_db.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_basic/hardfork.h" +#include "testdb.h" using namespace cryptonote; #define BLOCKS_PER_YEAR 525960 #define SECONDS_PER_YEAR 31557600 +namespace +{ -class TestDB: public BlockchainDB { +class TestDB: public BaseTestDB { public: - TestDB() {}; - virtual void open(const std::string& filename, const int db_flags = 0) { } - virtual void close() {} - virtual void sync() {} - virtual void safesyncmode(const bool onoff) {} - virtual void reset() {} - virtual std::vector get_filenames() const { return std::vector(); } - virtual bool remove_data_file(const std::string& folder) const { return true; } - virtual std::string get_db_name() const { return std::string(); } - virtual bool lock() { return true; } - virtual void unlock() { } - virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0) { return true; } - virtual void batch_stop() {} - virtual void set_batch_transactions(bool) {} - virtual void block_txn_start(bool readonly=false) {} - virtual void block_txn_stop() {} - virtual void block_txn_abort() {} - virtual void drop_hard_fork_info() {} - virtual bool block_exists(const crypto::hash& h, uint64_t *height) const { return false; } - virtual blobdata get_block_blob_from_height(const uint64_t& height) const { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); } - virtual blobdata get_block_blob(const crypto::hash& h) const { return blobdata(); } - virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; } - virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; } - virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const { return false; } - virtual uint64_t get_block_height(const crypto::hash& h) const { return 0; } - virtual block_header get_block_header(const crypto::hash& h) const { return block_header(); } - virtual uint64_t get_block_timestamp(const uint64_t& height) const { return 0; } - virtual std::vector get_block_cumulative_rct_outputs(const std::vector &heights) const { return {}; } - virtual uint64_t get_top_block_timestamp() const { return 0; } - virtual size_t get_block_weight(const uint64_t& height) const { return 128; } - virtual difficulty_type get_block_cumulative_difficulty(const uint64_t& height) const { return 10; } - virtual difficulty_type get_block_difficulty(const uint64_t& height) const { return 0; } - virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const { return 10000000000; } - virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const { return crypto::hash(); } - virtual std::vector get_blocks_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector(); } - virtual std::vector get_hashes_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector(); } - virtual crypto::hash top_block_hash() const { return crypto::hash(); } - virtual block get_top_block() const { return block(); } virtual uint64_t height() const { return blocks.size(); } - virtual bool tx_exists(const crypto::hash& h) const { return false; } - virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const { return false; } - virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const { return 0; } - virtual transaction get_tx(const crypto::hash& h) const { return transaction(); } - virtual bool get_tx(const crypto::hash& h, transaction &tx) const { return false; } - virtual uint64_t get_tx_count() const { return 0; } - virtual std::vector get_tx_list(const std::vector& hlist) const { return std::vector(); } - virtual uint64_t get_tx_block_height(const crypto::hash& h) const { return 0; } - virtual uint64_t get_num_outputs(const uint64_t& amount) const { return 1; } - virtual uint64_t get_indexing_base() const { return 0; } - virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) { return output_data_t(); } - virtual tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const { return tx_out_index(); } - virtual tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const { return tx_out_index(); } - virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector &offsets, std::vector &indices) const {} - virtual void get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) {} - virtual bool can_thread_bulk_indices() const { return false; } - virtual std::vector get_tx_output_indices(const crypto::hash& h) const { return std::vector(); } - virtual std::vector get_tx_amount_output_indices(const uint64_t tx_index) const { return std::vector(); } - virtual bool has_key_image(const crypto::key_image& img) const { return false; } - virtual void remove_block() { blocks.pop_back(); } - virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) {return 0;} - virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx) {} - virtual uint64_t add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) {return 0;} - virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector& amount_output_indices) {} - virtual void add_spent_key(const crypto::key_image& k_image) {} - virtual void remove_spent_key(const crypto::key_image& k_image) {} - - virtual bool for_all_key_images(std::function) const { return true; } - virtual bool for_blocks_range(const uint64_t&, const uint64_t&, std::function) const { return true; } - virtual bool for_all_transactions(std::function, bool pruned) const { return true; } - virtual bool for_all_outputs(std::function f) const { return true; } - virtual bool for_all_outputs(uint64_t amount, const std::function &f) const { return true; } - virtual bool is_read_only() const { return false; } - virtual std::map> get_output_histogram(const std::vector &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { return std::map>(); } - virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector &distribution, uint64_t &base) const { return false; } - - virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) {} - virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& details) {} - virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; } - virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; } - virtual void remove_txpool_tx(const crypto::hash& txid) {} - virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { return false; } - virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; } - virtual uint64_t get_database_size() const { return 0; } - virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; } - virtual bool for_all_txpool_txes(std::function, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; } - virtual void add_block( const block& blk , size_t block_weight , const difficulty_type& cumulative_difficulty @@ -138,6 +56,7 @@ class TestDB: public BlockchainDB { ) { blocks.push_back(blk); } + virtual void remove_block() { blocks.pop_back(); } virtual block get_block_from_height(const uint64_t& height) const { return blocks.at(height); } @@ -149,13 +68,14 @@ class TestDB: public BlockchainDB { virtual uint8_t get_hard_fork_version(uint64_t height) const { return versions.at(height); } - virtual void check_hard_fork_info() {} private: std::vector blocks; std::deque versions; }; +} + static cryptonote::block mkblock(uint8_t version, uint8_t vote) { cryptonote::block b; diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp new file mode 100644 index 000000000..649752ac7 --- /dev/null +++ b/tests/unit_tests/output_distribution.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include "gtest/gtest.h" +#include "misc_log_ex.h" +#include "rpc/rpc_handler.h" +#include "blockchain_db/blockchain_db.h" +#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_core/tx_pool.h" +#include "cryptonote_core/blockchain.h" +#include "testdb.h" + +static const uint64_t test_distribution[32] = { + 0, 0, 0, 0, 0, 1, 5, 1, 4, 0, 0, 1, 0, 1, 2, 3, 1, 0, 2, 0, 1, 3, 8, 1, 3, 5, 7, 1, 5, 0, 2, 3 +}; +static const size_t test_distribution_size = sizeof(test_distribution) / sizeof(test_distribution[0]); + +namespace +{ + +class TestDB: public BaseTestDB +{ +public: + TestDB(size_t bc_height = test_distribution_size): blockchain_height(bc_height) { m_open = true; } + virtual uint64_t height() const override { return blockchain_height; } + + std::vector get_block_cumulative_rct_outputs(const std::vector &heights) const override + { + std::vector d; + for (uint64_t h: heights) + { + uint64_t c = 0; + for (uint64_t i = 0; i <= h; ++i) + c += test_distribution[i]; + d.push_back(c); + } + return d; + } + + uint64_t blockchain_height; +}; + +} + +bool get_output_distribution(uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector &distribution, uint64_t &base) +{ + std::unique_ptr bc; + cryptonote::tx_memory_pool txpool(*bc); + bc.reset(new cryptonote::Blockchain(txpool)); + struct get_test_options { + const std::pair hard_forks[2]; + const cryptonote::test_options test_options = { + hard_forks + }; + get_test_options():hard_forks{std::make_pair((uint8_t)1, (uint64_t)0), std::make_pair((uint8_t)0, (uint64_t)0)}{} + } opts; + cryptonote::Blockchain *blockchain = bc.get(); + bool r = blockchain->init(new TestDB(test_distribution_size), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); + return r && bc->get_output_distribution(amount, from, to, start_height, distribution, base); +} + +TEST(output_distribution, extend) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 29, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 2); + ASSERT_EQ(res->distribution, std::vector({5, 0})); + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 29, true); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 2); + ASSERT_EQ(res->distribution, std::vector({55, 55})); + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 30, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 3); + ASSERT_EQ(res->distribution, std::vector({5, 0, 2})); + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 30, true); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 3); + ASSERT_EQ(res->distribution, std::vector({55, 55, 57})); + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 31, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 4); + ASSERT_EQ(res->distribution, std::vector({5, 0, 2, 3})); + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 28, 31, true); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 4); + ASSERT_EQ(res->distribution, std::vector({55, 55, 57, 60})); +} + +TEST(output_distribution, one) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 0, 0, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 1); + ASSERT_EQ(res->distribution.back(), 0); +} + +TEST(output_distribution, full_cumulative) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 0, 31, true); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 32); + ASSERT_EQ(res->distribution.back(), 60); +} + +TEST(output_distribution, full_noncumulative) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 0, 31, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 32); + for (size_t i = 0; i < 32; ++i) + ASSERT_EQ(res->distribution[i], test_distribution[i]); +} + +TEST(output_distribution, part_cumulative) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 4, 8, true); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 5); + ASSERT_EQ(res->distribution, std::vector({0, 1, 6, 7, 11})); +} + +TEST(output_distribution, part_noncumulative) +{ + boost::optional res; + + res = cryptonote::rpc::RpcHandler::get_output_distribution(::get_output_distribution, 0, 4, 8, false); + ASSERT_TRUE(res != boost::none); + ASSERT_EQ(res->distribution.size(), 5); + ASSERT_EQ(res->distribution, std::vector({0, 1, 5, 1, 4})); +} diff --git a/tests/unit_tests/testdb.h b/tests/unit_tests/testdb.h new file mode 100644 index 000000000..b6962cc41 --- /dev/null +++ b/tests/unit_tests/testdb.h @@ -0,0 +1,146 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include +#include +#include +#include "gtest/gtest.h" + +#include "blockchain_db/blockchain_db.h" + +class BaseTestDB: public cryptonote::BlockchainDB { +public: + BaseTestDB() {} + virtual void open(const std::string& filename, const int db_flags = 0) { } + virtual void close() {} + virtual void sync() {} + virtual void safesyncmode(const bool onoff) {} + virtual void reset() {} + virtual std::vector get_filenames() const { return std::vector(); } + virtual bool remove_data_file(const std::string& folder) const { return true; } + virtual std::string get_db_name() const { return std::string(); } + virtual bool lock() { return true; } + virtual void unlock() { } + virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0) { return true; } + virtual void batch_stop() {} + virtual void set_batch_transactions(bool) {} + virtual void block_txn_start(bool readonly=false) {} + virtual void block_txn_stop() {} + virtual void block_txn_abort() {} + virtual void drop_hard_fork_info() {} + virtual bool block_exists(const crypto::hash& h, uint64_t *height) const { return false; } + virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t& height) const { return cryptonote::t_serializable_object_to_blob(get_block_from_height(height)); } + virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const { return cryptonote::blobdata(); } + virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; } + virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; } + virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const { return false; } + virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const { return false; } + virtual uint64_t get_block_height(const crypto::hash& h) const { return 0; } + virtual cryptonote::block_header get_block_header(const crypto::hash& h) const { return cryptonote::block_header(); } + virtual uint64_t get_block_timestamp(const uint64_t& height) const { return 0; } + virtual std::vector get_block_cumulative_rct_outputs(const std::vector &heights) const { return {}; } + virtual uint64_t get_top_block_timestamp() const { return 0; } + virtual size_t get_block_weight(const uint64_t& height) const { return 128; } + virtual cryptonote::difficulty_type get_block_cumulative_difficulty(const uint64_t& height) const { return 10; } + virtual cryptonote::difficulty_type get_block_difficulty(const uint64_t& height) const { return 0; } + virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const { return 10000000000; } + virtual crypto::hash get_block_hash_from_height(const uint64_t& height) const { return crypto::hash(); } + virtual std::vector get_blocks_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector(); } + virtual std::vector get_hashes_range(const uint64_t& h1, const uint64_t& h2) const { return std::vector(); } + virtual crypto::hash top_block_hash() const { return crypto::hash(); } + virtual cryptonote::block get_top_block() const { return cryptonote::block(); } + virtual uint64_t height() const { return 1; } + virtual bool tx_exists(const crypto::hash& h) const { return false; } + virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const { return false; } + virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const { return 0; } + virtual cryptonote::transaction get_tx(const crypto::hash& h) const { return cryptonote::transaction(); } + virtual bool get_tx(const crypto::hash& h, cryptonote::transaction &tx) const { return false; } + virtual uint64_t get_tx_count() const { return 0; } + virtual std::vector get_tx_list(const std::vector& hlist) const { return std::vector(); } + virtual uint64_t get_tx_block_height(const crypto::hash& h) const { return 0; } + virtual uint64_t get_num_outputs(const uint64_t& amount) const { return 1; } + virtual uint64_t get_indexing_base() const { return 0; } + virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index) { return cryptonote::output_data_t(); } + virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const { return cryptonote::tx_out_index(); } + virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const { return cryptonote::tx_out_index(); } + virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector &offsets, std::vector &indices) const {} + virtual void get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) {} + virtual bool can_thread_bulk_indices() const { return false; } + virtual std::vector get_tx_output_indices(const crypto::hash& h) const { return std::vector(); } + virtual std::vector get_tx_amount_output_indices(const uint64_t tx_index) const { return std::vector(); } + virtual bool has_key_image(const crypto::key_image& img) const { return false; } + virtual void remove_block() { } + virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const cryptonote::transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) {return 0;} + virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) {} + virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) {return 0;} + virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector& amount_output_indices) {} + virtual void add_spent_key(const crypto::key_image& k_image) {} + virtual void remove_spent_key(const crypto::key_image& k_image) {} + + virtual bool for_all_key_images(std::function) const { return true; } + virtual bool for_blocks_range(const uint64_t&, const uint64_t&, std::function) const { return true; } + virtual bool for_all_transactions(std::function, bool pruned) const { return true; } + virtual bool for_all_outputs(std::function f) const { return true; } + virtual bool for_all_outputs(uint64_t amount, const std::function &f) const { return true; } + virtual bool is_read_only() const { return false; } + virtual std::map> get_output_histogram(const std::vector &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { return std::map>(); } + virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector &distribution, uint64_t &base) const { return false; } + + virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const cryptonote::txpool_tx_meta_t& details) {} + virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) {} + virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; } + virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; } + virtual void remove_txpool_tx(const crypto::hash& txid) {} + virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const { return false; } + virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; } + virtual uint64_t get_database_size() const { return 0; } + virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; } + virtual bool for_all_txpool_txes(std::function, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; } + + virtual void add_block( const cryptonote::block& blk + , size_t block_weight + , const cryptonote::difficulty_type& cumulative_difficulty + , const uint64_t& coins_generated + , uint64_t num_rct_outs + , const crypto::hash& blk_hash + ) { } + virtual cryptonote::block get_block_from_height(const uint64_t& height) const { return cryptonote::block(); } + virtual void set_hard_fork_version(uint64_t height, uint8_t version) {} + virtual uint8_t get_hard_fork_version(uint64_t height) const { return 0; } + virtual void check_hard_fork_info() {} + + virtual uint32_t get_blockchain_pruning_seed() const { return 0; } + virtual bool prune_blockchain(uint32_t pruning_seed = 0) { return true; } + virtual bool update_pruning() { return true; } + virtual bool check_pruning() { return true; } +}; + From 80be2dca2b8abdc0dae515187038475062987bd8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 14 Nov 2018 10:46:14 +0000 Subject: [PATCH 0297/1007] unit_tests: don't take the address of an unwrapped secret key --- tests/unit_tests/crypto.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp index 29fa88f9d..e09ec7f7a 100644 --- a/tests/unit_tests/crypto.cpp +++ b/tests/unit_tests/crypto.cpp @@ -47,6 +47,9 @@ namespace "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94" "6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea"; + template void *addressof(T &t) { return &t; } + template<> void *addressof(crypto::secret_key &k) { return addressof(unwrap(unwrap(k))); } + template bool is_formatted() { @@ -55,7 +58,7 @@ namespace static_assert(alignof(T) == 1, "T must have 1 byte alignment"); static_assert(sizeof(T) <= sizeof(source), "T is too large for source"); static_assert(sizeof(T) * 2 <= sizeof(expected), "T is too large for destination"); - std::memcpy(std::addressof(value), source, sizeof(T)); + std::memcpy(addressof(value), source, sizeof(T)); std::stringstream out; out << "BEGIN" << value << "END"; From 707c2f836b3136bc88b5aed374a4b3128f9596a7 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 17 Nov 2018 13:15:03 +0000 Subject: [PATCH 0298/1007] Remove -Werror It is an annoying piece of garbage --- CMakeLists.txt | 3 --- contrib/CMakeLists.txt | 5 ----- contrib/epee/tests/src/CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 5 ----- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c38c673a..88a9b8834 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,9 +599,6 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAG}") set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized") - if(NOT MINGW) - set(WARNINGS_AS_ERRORS_FLAG "-Werror") - endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang") if(ARM) set(WARNINGS "${WARNINGS} -Wno-error=inline-asm") diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 990a05c08..3bebbe0d2 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -26,10 +26,5 @@ # 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. -# warnings are cleared only for GCC on Linux -if (NOT (MINGW OR APPLE OR FREEBSD OR OPENBSD OR DRAGONFLY)) - add_compile_options("${WARNINGS_AS_ERRORS_FLAG}") # applies only to targets that follow -endif() - add_subdirectory(epee) diff --git a/contrib/epee/tests/src/CMakeLists.txt b/contrib/epee/tests/src/CMakeLists.txt index c7d31735b..4807fa7ea 100644 --- a/contrib/epee/tests/src/CMakeLists.txt +++ b/contrib/epee/tests/src/CMakeLists.txt @@ -14,8 +14,8 @@ IF (MSVC) include_directories(SYSTEM platform/msvc) ELSE() # set stuff for other systems - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Werror") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror -Wno-reorder") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder") ENDIF() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ee7effdd..a0b62da77 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,11 +34,6 @@ if (WIN32 OR STATIC) add_definitions(-DMINIUPNP_STATICLIB) endif () -# warnings are cleared only for GCC on Linux -if (NOT (MINGW OR APPLE OR FREEBSD OR OPENBSD OR DRAGONFLY)) - add_compile_options("${WARNINGS_AS_ERRORS_FLAG}") # applies only to targets that follow -endif() - function (monero_private_headers group) source_group("${group}\\Private" FILES From 60f36386e4c844040371974f01da07ed02942529 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 19 Nov 2018 17:55:53 +0000 Subject: [PATCH 0299/1007] Avoid unnecessary temp block and copy ctor block already has a default ctor, and the extra object churn due to its innards (vectors, etc) is pointless. --- src/cryptonote_basic/miner.cpp | 2 +- src/cryptonote_core/blockchain.cpp | 2 +- src/rpc/core_rpc_server.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index d8ca2dd35..339d68580 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -146,7 +146,7 @@ namespace cryptonote //----------------------------------------------------------------------------------------------------- bool miner::request_block_template() { - block bl = AUTO_VAL_INIT(bl); + block bl; difficulty_type di = AUTO_VAL_INIT(di); uint64_t height = AUTO_VAL_INIT(height); uint64_t expected_reward; //only used for RPC calls - could possibly be useful here too? diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index f3105114e..ae620fc80 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -404,7 +404,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline if(!m_db->height()) { MINFO("Blockchain not loaded, generating genesis block."); - block bl = boost::value_initialized(); + block bl; block_verification_context bvc = boost::value_initialized(); generate_genesis_block(bl, get_config(m_nettype).GENESIS_TX, get_config(m_nettype).GENESIS_NONCE); add_new_block(bl, bvc); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c2e71bef8..bf70e1371 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1077,7 +1077,7 @@ namespace cryptonote return false; } - block b = AUTO_VAL_INIT(b); + block b; cryptonote::blobdata blob_reserve; blob_reserve.resize(req.reserve_size, 0); if(!m_core.get_block_template(b, info.address, res.difficulty, res.height, res.expected_reward, blob_reserve)) @@ -1148,7 +1148,7 @@ namespace cryptonote // Fixing of high orphan issue for most pools // Thanks Boolberry! - block b = AUTO_VAL_INIT(b); + block b; if(!parse_and_validate_block_from_blob(blockblob, b)) { error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; @@ -1216,7 +1216,7 @@ namespace cryptonote error_resp.message = "Wrong block blob"; return false; } - block b = AUTO_VAL_INIT(b); + block b; if(!parse_and_validate_block_from_blob(blockblob, b)) { error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB; From fc99f177f3bc29322fc93839e4f238c7fba9a64f Mon Sep 17 00:00:00 2001 From: xiphon Date: Mon, 19 Nov 2018 22:36:10 +0000 Subject: [PATCH 0300/1007] lmdb: fix gcc 7.3.0 'implicit-fallthrough' warning --- src/blockchain_db/lmdb/db_lmdb.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index ea3638a85..622278784 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -4358,16 +4358,12 @@ void BlockchainLMDB::migrate_2_3() void BlockchainLMDB::migrate(const uint32_t oldversion) { - switch(oldversion) { - case 0: - migrate_0_1(); /* FALLTHRU */ - case 1: - migrate_1_2(); /* FALLTHRU */ - case 2: - migrate_2_3(); /* FALLTHRU */ - default: - ; - } + if (oldversion < 1) + migrate_0_1(); + if (oldversion < 2) + migrate_1_2(); + if (oldversion < 3) + migrate_2_3(); } } // namespace cryptonote From b9b307d11ade4ebc4a5fb6cc89d7f14992a7b6a0 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 8 Nov 2018 18:26:59 +0000 Subject: [PATCH 0301/1007] rpc: speedup get_output_distribution and decrease the amount of data carried around --- src/rpc/core_rpc_server.cpp | 43 ++++++++++++++++- src/rpc/core_rpc_server.h | 2 + src/rpc/core_rpc_server_commands_defs.h | 62 ++++++++++++++++++++++++- src/wallet/wallet2.cpp | 7 ++- 4 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index df9eee781..f029d1d5a 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -2133,7 +2133,7 @@ namespace cryptonote return false; } - res.distributions.push_back({std::move(*data), amount, req.binary}); + res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress}); } } catch (const std::exception &e) @@ -2147,6 +2147,47 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res) + { + PERF_TIMER(on_get_output_distribution_bin); + + bool r; + if (use_bootstrap_daemon_if_necessary(invoke_http_mode::BIN, "/get_output_distribution.bin", req, res, r)) + return r; + + res.status = "Failed"; + + if (!req.binary) + { + res.status = "Binary only call"; + return false; + } + try + { + // 0 is placeholder for the whole chain + const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1); + for (uint64_t amount: req.amounts) + { + auto data = rpc::RpcHandler::get_output_distribution([this](uint64_t amount, uint64_t from, uint64_t to, uint64_t &start_height, std::vector &distribution, uint64_t &base) { return m_core.get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, req.cumulative); + if (!data) + { + res.status = "Failed to get output distribution"; + return false; + } + + res.distributions.push_back({std::move(*data), amount, "", req.binary, req.compress}); + } + } + catch (const std::exception &e) + { + res.status = "Failed to get output distribution"; + return false; + } + + res.status = CORE_RPC_STATUS_OK; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ const command_line::arg_descriptor core_rpc_server::arg_rpc_bind_port = { diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 3ba882b23..8ada0af15 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -117,6 +117,7 @@ namespace cryptonote MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted) MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS) MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted) + MAP_URI_AUTO_BIN2("/get_output_distribution.bin", on_get_output_distribution_bin, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION) BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) @@ -187,6 +188,7 @@ namespace cryptonote bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res); bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res); bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res); + bool on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res); //json_rpc bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 8e8df7a52..27c77eecc 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -34,6 +34,40 @@ #include "cryptonote_basic/difficulty.h" #include "crypto/hash.h" #include "rpc/rpc_handler.h" +#include "common/varint.h" +#include "common/perf_timer.h" + +namespace +{ + template + std::string compress_integer_array(const std::vector &v) + { + std::string s; + s.resize(v.size() * (sizeof(T) * 8 / 7 + 1)); + char *ptr = (char*)s.data(); + for (const T &t: v) + tools::write_varint(ptr, t); + s.resize(ptr - s.data()); + return s; + } + + template + std::vector decompress_integer_array(const std::string &s) + { + std::vector v; + v.reserve(s.size()); + int read = 0; + const std::string::const_iterator end = s.end(); + for (std::string::const_iterator i = s.begin(); i != end; std::advance(i, read)) + { + T t; + read = tools::read_varint(std::string::const_iterator(i), s.end(), t); + CHECK_AND_ASSERT_THROW_MES(read > 0 && read <= 256, "Error decompressing data"); + v.push_back(t); + } + return v; + } +} namespace cryptonote { @@ -2222,6 +2256,7 @@ namespace cryptonote uint64_t to_height; bool cumulative; bool binary; + bool compress; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(amounts) @@ -2229,6 +2264,7 @@ namespace cryptonote KV_SERIALIZE_OPT(to_height, (uint64_t)0) KV_SERIALIZE_OPT(cumulative, false) KV_SERIALIZE_OPT(binary, true) + KV_SERIALIZE_OPT(compress, false) END_KV_SERIALIZE_MAP() }; @@ -2236,14 +2272,38 @@ namespace cryptonote { rpc::output_distribution_data data; uint64_t amount; + std::string compressed_data; bool binary; + bool compress; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(amount) KV_SERIALIZE_N(data.start_height, "start_height") KV_SERIALIZE(binary) + KV_SERIALIZE(compress) if (this_ref.binary) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution") + { + if (is_store) + { + if (this_ref.compress) + { + const_cast(this_ref.compressed_data) = compress_integer_array(this_ref.data.distribution); + KV_SERIALIZE(compressed_data) + } + else + KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution") + } + else + { + if (this_ref.compress) + { + KV_SERIALIZE(compressed_data) + const_cast&>(this_ref.data.distribution) = decompress_integer_array(this_ref.compressed_data); + } + else + KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(data.distribution, "distribution") + } + } else KV_SERIALIZE_N(data.distribution, "distribution") KV_SERIALIZE_N(data.base, "base") diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 129b96733..c9781f0c8 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2852,10 +2852,11 @@ bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector cryptonote::COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response res = AUTO_VAL_INIT(res); req.amounts.push_back(0); req.from_height = 0; - req.cumulative = true; + req.cumulative = false; req.binary = true; + req.compress = true; m_daemon_rpc_mutex.lock(); - bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_distribution", req, res, m_http_client, rpc_timeout); + bool r = net_utils::invoke_http_bin("/get_output_distribution.bin", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); if (!r) { @@ -2882,6 +2883,8 @@ bool wallet2::get_rct_distribution(uint64_t &start_height, std::vector MWARNING("Failed to request output distribution: results are not for amount 0"); return false; } + for (size_t i = 1; i < res.distributions[0].data.distribution.size(); ++i) + res.distributions[0].data.distribution[i] += res.distributions[0].data.distribution[i-1]; start_height = res.distributions[0].data.start_height; distribution = std::move(res.distributions[0].data.distribution); return true; From 6732fc7fde22d37a78318d350baaeb1c03158fab Mon Sep 17 00:00:00 2001 From: naughtyfox Date: Mon, 12 Nov 2018 20:46:00 +0300 Subject: [PATCH 0302/1007] Fix issue 4793 - M/N multisig transaction signature --- src/common/CMakeLists.txt | 6 ++- src/common/combinator.cpp | 50 ++++++++++++++++++++ src/common/combinator.h | 96 +++++++++++++++++++++++++++++++++++++++ src/wallet/wallet2.cpp | 77 ++++++++++++++++++++++++------- src/wallet/wallet2.h | 4 +- 5 files changed, 213 insertions(+), 20 deletions(-) create mode 100644 src/common/combinator.cpp create mode 100644 src/common/combinator.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index aed9bfee7..3045c003c 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -43,7 +43,8 @@ set(common_sources spawn.cpp threadpool.cpp updates.cpp - aligned.c) + aligned.c + combinator.cpp) if (STACK_TRACE) list(APPEND common_sources stack_trace.cpp) @@ -77,7 +78,8 @@ set(common_private_headers stack_trace.h threadpool.h updates.h - aligned.h) + aligned.h + combinator.h) monero_private_headers(common ${common_private_headers}) diff --git a/src/common/combinator.cpp b/src/common/combinator.cpp new file mode 100644 index 000000000..cb4fbc908 --- /dev/null +++ b/src/common/combinator.cpp @@ -0,0 +1,50 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#include "combinator.h" + +namespace tools { + +uint64_t combinations_count(uint32_t k, uint32_t n) +{ + if (k > n) { + throw std::runtime_error("k must not be greater than n"); + } + + uint64_t c = 1; + for (uint64_t i = 1; i <= k; ++i) { + c *= n--; + c /= i; + } + + return c; +} + +} diff --git a/src/common/combinator.h b/src/common/combinator.h new file mode 100644 index 000000000..72c6800d5 --- /dev/null +++ b/src/common/combinator.h @@ -0,0 +1,96 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +#include +#include + +namespace tools { + +uint64_t combinations_count(uint32_t k, uint32_t n); + +template +class Combinator { +public: + Combinator(const std::vector& v) : origin(v) { } + + std::vector> combine(size_t k); + +private: + void doCombine(size_t from, size_t k); + + std::vector origin; + std::vector> combinations; + std::vector current; +}; + +template +std::vector> Combinator::combine(size_t k) +{ + if (k > origin.size()) + { + throw std::runtime_error("k must be smaller than elements number"); + } + + if (k == 0) + { + throw std::runtime_error("k must be greater than zero"); + } + + combinations.clear(); + doCombine(0, k); + return combinations; +} + +template +void Combinator::doCombine(size_t from, size_t k) +{ + current.push_back(0); + + for (size_t i = from; i <= origin.size() - k; ++i) + { + current.back() = i; + + if (k > 1) { + doCombine(i + 1, k - 1); + } else { + std::vector comb; + for (auto ind: current) { + comb.push_back(origin[ind]); + } + combinations.push_back(comb); + } + } + + current.pop_back(); +} + +} //namespace tools diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index ebf857b78..8fcecb402 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -67,6 +67,7 @@ using namespace epee; #include "common/json_util.h" #include "memwipe.h" #include "common/base58.h" +#include "common/combinator.h" #include "common/dns_utils.h" #include "common/notify.h" #include "common/perf_timer.h" @@ -177,6 +178,20 @@ namespace return public_keys; } + + bool keys_intersect(const std::unordered_set& s1, const std::unordered_set& s2) + { + if (s1.empty() || s2.empty()) + return false; + + for (const auto& e: s1) + { + if (s2.find(e) != s2.end()) + return true; + } + + return false; + } } namespace @@ -6045,7 +6060,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector multisig_signers; size_t n_multisig_txes = 0; + std::vector> ignore_sets; if (m_multisig && !m_transfers.empty()) { const crypto::public_key local_signer = get_multisig_signer_public_key(); size_t n_available_signers = 1; + + // At this step we need to define set of participants available for signature, + // i.e. those of them who exchanged with multisig info's for (const crypto::public_key &signer: m_multisig_signers) { if (signer == local_signer) continue; - multisig_signers.push_front(signer); for (const auto &i: m_transfers[0].m_multisig_info) { if (i.m_signer == signer) { - multisig_signers.pop_front(); multisig_signers.push_back(signer); ++n_available_signers; break; } } } - multisig_signers.push_back(local_signer); + // n_available_signers includes the transaction creator, but multisig_signers doesn't MDEBUG("We can use " << n_available_signers << "/" << m_multisig_signers.size() << " other signers"); - THROW_WALLET_EXCEPTION_IF(n_available_signers+1 < m_multisig_threshold, error::multisig_import_needed); - n_multisig_txes = n_available_signers == m_multisig_signers.size() ? m_multisig_threshold : 1; + THROW_WALLET_EXCEPTION_IF(n_available_signers < m_multisig_threshold, error::multisig_import_needed); + if (n_available_signers > m_multisig_threshold) + { + // If there more potential signers (those who exchanged with multisig info) + // than threshold needed some of them should be skipped since we don't know + // who will sign tx and who won't. Hence we don't contribute their LR pairs to the signature. + + // We create as many transactions as many combinations of excluded signers may be. + // For example, if we have 2/4 wallet and wallets are: A, B, C and D. Let A be + // transaction creator, so we need just 1 signature from set of B, C, D. + // Using "excluding" logic here we have to exclude 2-of-3 wallets. Combinations go as follows: + // BC, BD, and CD. We save these sets to use later and counting the number of required txs. + tools::Combinator c(std::vector(multisig_signers.begin(), multisig_signers.end())); + auto ignore_combinations = c.combine(multisig_signers.size() + 1 - m_multisig_threshold); + for (const auto& combination: ignore_combinations) + { + ignore_sets.push_back(std::unordered_set(combination.begin(), combination.end())); + } + + n_multisig_txes = ignore_sets.size(); + } + else + { + // If we have exact count of signers just to fit in threshold we don't exclude anyone and create 1 transaction + n_multisig_txes = 1; + } MDEBUG("We will create " << n_multisig_txes << " txes"); } @@ -7603,8 +7644,8 @@ void wallet2::transfer_selected_rct(std::vector() : ignore_sets.front(); + src.multisig_kLRki = get_multisig_composite_kLRki(idx, ignore_set, used_L, used_L); } else src.multisig_kLRki = rct::multisig_kLRki({rct::zero(), rct::zero(), rct::zero(), rct::zero()}); @@ -7666,7 +7707,7 @@ void wallet2::transfer_selected_rct(std::vector multisig_sigs; if (m_multisig) { - crypto::public_key ignore = m_multisig_threshold == m_multisig_signers.size() ? crypto::null_pkey : multisig_signers.front(); + auto ignore = ignore_sets.empty() ? std::unordered_set() : ignore_sets.front(); multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, std::unordered_set(), msout}); if (m_multisig_threshold < m_multisig_signers.size()) @@ -7674,7 +7715,7 @@ void wallet2::transfer_selected_rct(std::vector new_used_L; size_t src_idx = 0; @@ -7682,7 +7723,7 @@ void wallet2::transfer_selected_rct(std::vector(), msout}); + multisig_sigs.push_back({ms_tx.rct_signatures, ignore_sets[ignore_index], new_used_L, std::unordered_set(), msout}); ms_tx.rct_signatures = tx.rct_signatures; THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_hash(ms_tx) != cryptonote::get_transaction_hash(tx), error::wallet_internal_error, "Multisig txes differ by more than the signatures"); @@ -11265,7 +11306,7 @@ rct::multisig_kLRki wallet2::get_multisig_kLRki(size_t n, const rct::key &k) con return kLRki; } //---------------------------------------------------------------------------------------------------- -rct::multisig_kLRki wallet2::get_multisig_composite_kLRki(size_t n, const crypto::public_key &ignore, std::unordered_set &used_L, std::unordered_set &new_used_L) const +rct::multisig_kLRki wallet2::get_multisig_composite_kLRki(size_t n, const std::unordered_set &ignore_set, std::unordered_set &used_L, std::unordered_set &new_used_L) const { CHECK_AND_ASSERT_THROW_MES(n < m_transfers.size(), "Bad transfer index"); @@ -11276,8 +11317,9 @@ rct::multisig_kLRki wallet2::get_multisig_composite_kLRki(size_t n, const crypto size_t n_signers_used = 1; for (const auto &p: m_transfers[n].m_multisig_info) { - if (p.m_signer == ignore) + if (ignore_set.find(p.m_signer) != ignore_set.end()) continue; + for (const auto &lr: p.m_LR) { if (used_L.find(lr.m_L) != used_L.end()) @@ -11336,7 +11378,10 @@ cryptonote::blobdata wallet2::export_multisig() info[n].m_partial_key_images.push_back(ki); } - size_t nlr = m_multisig_threshold < m_multisig_signers.size() ? m_multisig_threshold - 1 : 1; + // Wallet tries to create as many transactions as many signers combinations. We calculate the maximum number here as follows: + // if we have 2/4 wallet with signers: A, B, C, D and A is a transaction creator it will need to pick up 1 signer from 3 wallets left. + // That means counting combinations for excluding 2-of-3 wallets (k = total signers count - threshold, n = total signers count - 1). + size_t nlr = tools::combinations_count(m_multisig_signers.size() - m_multisig_threshold, m_multisig_signers.size() - 1); for (size_t m = 0; m < nlr; ++m) { td.m_multisig_k.push_back(rct::skGen()); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index dbfd45c53..823da27a8 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -374,7 +374,7 @@ namespace tools struct multisig_sig { rct::rctSig sigs; - crypto::public_key ignore; + std::unordered_set ignore; std::unordered_set used_L; std::unordered_set signing_keys; rct::multisig_out msout; @@ -1256,7 +1256,7 @@ namespace tools void scan_output(const cryptonote::transaction &tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map &tx_money_got_in_outs, std::vector &outs); void trim_hashchain(); crypto::key_image get_multisig_composite_key_image(size_t n) const; - rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const crypto::public_key &ignore, std::unordered_set &used_L, std::unordered_set &new_used_L) const; + rct::multisig_kLRki get_multisig_composite_kLRki(size_t n, const std::unordered_set &ignore_set, std::unordered_set &used_L, std::unordered_set &new_used_L) const; rct::multisig_kLRki get_multisig_kLRki(size_t n, const rct::key &k) const; rct::key get_multisig_k(size_t idx, const std::unordered_set &used_L) const; void update_multisig_rescan_info(const std::vector> &multisig_k, const std::vector> &info, size_t n); From 23829ebb09cfa016044f6e5a0b361de1e04705ad Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 20 Nov 2018 15:24:16 +0000 Subject: [PATCH 0303/1007] mlocker: don't throw from lock/unlock This prevents exceptions from showing up in various awkward places such as dtors, since the only exception that can be thrown is a lock failure, and nothing handles a lock failure anyway. --- contrib/epee/src/mlocker.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index c3262e8f4..7ac79bd9a 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -113,6 +113,8 @@ namespace epee void mlocker::lock(void *ptr, size_t len) { + TRY_ENTRY(); + size_t page_size = get_page_size(); if (page_size == 0) return; @@ -123,10 +125,14 @@ namespace epee for (size_t page = first; page <= last; ++page) lock_page(page); ++num_locked_objects; + + CATCH_ENTRY_L1("mlocker::lock", void()); } void mlocker::unlock(void *ptr, size_t len) { + TRY_ENTRY(); + size_t page_size = get_page_size(); if (page_size == 0) return; @@ -136,6 +142,8 @@ namespace epee for (size_t page = first; page <= last; ++page) unlock_page(page); --num_locked_objects; + + CATCH_ENTRY_L1("mlocker::lock", void()); } size_t mlocker::get_num_locked_pages() From c25260f51c02eede8adfc5ac06ddb443e64c87cb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 17 Nov 2018 12:47:59 +0000 Subject: [PATCH 0304/1007] protocol: fix incorrect tx hash in log --- src/cryptonote_protocol/cryptonote_protocol_handler.inl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index c2c660e8c..6081ddd89 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1077,8 +1077,10 @@ skip: if(tvc[i].m_verifivation_failed) { if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{ + cryptonote::transaction tx; + parse_and_validate_tx_from_blob(*it, tx); // must succeed if we got here LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, tx_id = " - << epee::string_tools::pod_to_hex(get_blob_hash(*it)) << ", dropping connection"); + << epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(tx)) << ", dropping connection"); drop_connection(context, false, true); return 1; })) From 96e6b439705cff5806974bb34e4b46db40dd3dbd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 20 Nov 2018 22:26:50 +0000 Subject: [PATCH 0305/1007] blockchain_stats: don't use gmtime_r on Windows In some cases, it doesn't like it (I don't know the details). Factor into a new epee function --- contrib/epee/include/misc_os_dependent.h | 9 +++++++++ contrib/epee/src/mlog.cpp | 8 ++------ src/blockchain_utilities/blockchain_stats.cpp | 2 +- src/simplewallet/simplewallet.cpp | 6 +----- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h index 0d09683d6..5fffde8d5 100644 --- a/contrib/epee/include/misc_os_dependent.h +++ b/contrib/epee/include/misc_os_dependent.h @@ -122,6 +122,15 @@ namespace misc_utils return boost::lexical_cast(GetCurrentThreadId()); #elif defined(__GNUC__) return boost::lexical_cast(pthread_self()); +#endif + } + + inline bool get_gmt_time(time_t t, struct tm &tm) + { +#ifdef _WIN32 + return gmtime_s(&tm, &t); +#else + return gmtime_r(&t, &tm); #endif } } diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 638155b6b..00d848388 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -40,6 +40,7 @@ #include #include #include "string_tools.h" +#include "misc_os_dependent.h" #include "misc_log_ex.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -58,12 +59,7 @@ static std::string generate_log_filename(const char *base) char tmp[200]; struct tm tm; time_t now = time(NULL); - if -#ifdef WIN32 - (!gmtime_s(&tm, &now)) -#else - (!gmtime_r(&now, &tm)) -#endif + if (!epee::misc_utils::get_gmt_time(now, tm)) snprintf(tmp, sizeof(tmp), "part-%u", ++fallback_counter); else strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm); diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp index 716b33cae..aae8f333b 100644 --- a/src/blockchain_utilities/blockchain_stats.cpp +++ b/src/blockchain_utilities/blockchain_stats.cpp @@ -234,7 +234,7 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, '' } time_t tt = blk.timestamp; char timebuf[64]; - gmtime_r(&tt, &currtm); + epee::misc_utils::get_gmt_time(tt, currtm); if (!prevtm.tm_year) prevtm = currtm; // catch change of day diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..1c431ade6 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -6727,11 +6727,7 @@ static std::string get_human_readable_timestamp(uint64_t ts) return ""; time_t tt = ts; struct tm tm; -#ifdef WIN32 - gmtime_s(&tm, &tt); -#else - gmtime_r(&tt, &tm); -#endif + epee::misc_utils::get_gmt_time(tt, tm); uint64_t now = time(NULL); uint64_t diff = ts > now ? ts - now : now - ts; strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm); From 6bfcc57395fb3ce0c00b35a07b3f6227fd2606de Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 21 Nov 2018 12:46:11 +0000 Subject: [PATCH 0306/1007] scoped_message_writer: protect all std::cout usage from readline --- src/common/scoped_message_writer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/scoped_message_writer.h b/src/common/scoped_message_writer.h index d887a13c9..42f439ad8 100644 --- a/src/common/scoped_message_writer.h +++ b/src/common/scoped_message_writer.h @@ -101,13 +101,13 @@ class scoped_message_writer MCLOG_FILE(m_log_level, "msgwriter", m_oss.str()); + PAUSE_READLINE(); if (epee::console_color_default == m_color) { std::cout << m_oss.str(); } else { - PAUSE_READLINE(); set_console_color(m_color, m_bright); std::cout << m_oss.str(); epee::reset_console_color(); From 517f25efd1d8cc6f10f777b6f8ddd79a088fae4b Mon Sep 17 00:00:00 2001 From: Jethro Grassie Date: Tue, 20 Nov 2018 13:18:08 -0500 Subject: [PATCH 0307/1007] rpc: add version to get_info --- src/rpc/CMakeLists.txt | 3 +++ src/rpc/core_rpc_server.cpp | 2 ++ src/rpc/core_rpc_server_commands_defs.h | 4 +++- src/rpc/daemon_handler.cpp | 2 ++ src/rpc/message_data_structs.h | 1 + 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 8fc42b7e3..d2c4a33cb 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -112,6 +112,7 @@ target_link_libraries(rpc common cryptonote_core cryptonote_protocol + version ${Boost_REGEX_LIBRARY} ${Boost_THREAD_LIBRARY} PRIVATE @@ -121,6 +122,7 @@ target_link_libraries(daemon_messages LINK_PRIVATE cryptonote_core cryptonote_protocol + version serialization ${EXTRA_LIBRARIES}) @@ -129,6 +131,7 @@ target_link_libraries(daemon_rpc_server rpc cryptonote_core cryptonote_protocol + version daemon_messages serialization ${Boost_CHRONO_LIBRARY} diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index df9eee781..48c9a5aa0 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -210,6 +210,7 @@ namespace cryptonote } res.database_size = m_core.get_blockchain_storage().get_db().get_database_size(); res.update_available = m_core.is_update_available(); + res.version = m_restricted ? "" : MONERO_VERSION; return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -1609,6 +1610,7 @@ namespace cryptonote } res.database_size = m_core.get_blockchain_storage().get_db().get_database_size(); res.update_available = m_core.is_update_available(); + res.version = m_restricted ? "" : MONERO_VERSION; return true; } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 8e8df7a52..5cf7fd8e8 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -50,7 +50,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 2 -#define CORE_RPC_VERSION_MINOR 1 +#define CORE_RPC_VERSION_MINOR 2 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -892,6 +892,7 @@ namespace cryptonote bool was_bootstrap_ever_used; uint64_t database_size; bool update_available; + std::string version; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) @@ -926,6 +927,7 @@ namespace cryptonote KV_SERIALIZE(was_bootstrap_ever_used) KV_SERIALIZE(database_size) KV_SERIALIZE(update_available) + KV_SERIALIZE(version) END_KV_SERIALIZE_MAP() }; }; diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 64a5cc858..e2885dbb5 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -34,6 +34,7 @@ #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_basic/blobdatatype.h" #include "ringct/rctSigs.h" +#include "version.h" namespace cryptonote { @@ -437,6 +438,7 @@ namespace rpc res.info.block_size_limit = res.info.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit(); res.info.block_size_median = res.info.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median(); res.info.start_time = (uint64_t)m_core.get_start_time(); + res.info.version = MONERO_VERSION; res.status = Message::STATUS_OK; res.error_details = ""; diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index 3b56aff15..e09b6749e 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -191,6 +191,7 @@ namespace rpc uint64_t block_size_median; uint64_t block_weight_median; uint64_t start_time; + std::string version; }; struct output_distribution From 40485a73b6fce47324aecf8b182164f72be0ae76 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 22 Nov 2018 01:39:12 +0000 Subject: [PATCH 0308/1007] mlocker: fix access to global lock map after dtor on exit as the lock, it now leaks --- contrib/epee/src/mlocker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index c3262e8f4..b35393081 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -89,8 +89,8 @@ namespace epee } std::map &mlocker::map() { - static std::map vmap; - return vmap; + static std::map *vmap = new std::map(); + return *vmap; } size_t mlocker::get_page_size() From 56e616e8556192aba1e61de51bf3b5086e8d0f29 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 22 Nov 2018 01:40:13 +0000 Subject: [PATCH 0309/1007] wallet2: add n_vouts to capture list --- src/wallet/wallet2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 129b96733..81f232561 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2149,7 +2149,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector= tx_cache_data.size(), error::wallet_internal_error, "txidx out of range"); const size_t n_vouts = m_refresh_type == RefreshType::RefreshOptimizeCoinbase ? 1 : parsed_blocks[i].block.miner_tx.vout.size(); - tpool.submit(&waiter, [&, i, txidx](){ geniod(parsed_blocks[i].block.miner_tx, n_vouts, txidx); }, true); + tpool.submit(&waiter, [&, i, n_vouts, txidx](){ geniod(parsed_blocks[i].block.miner_tx, n_vouts, txidx); }, true); } ++txidx; for (size_t j = 0; j < parsed_blocks[i].txes.size(); ++j) From b5573fc231df88a4673719dfa2997f7283b181fa Mon Sep 17 00:00:00 2001 From: stoffu Date: Thu, 22 Nov 2018 14:45:52 +0900 Subject: [PATCH 0310/1007] wallet2: resume processing when tx extra is partially broken Motivated by https://monero.stackexchange.com/questions/10483 Some exchanges appear to have customized the wallet software in an inappropriate way, making the tx extra field partially unreadable. PR #3716 changed the wallet behavior disallowing such partially valid tx extra. An example tx reported by the user is e87c675a85f34ecac58a8846613d25062f1813e1023c552b705afad32b972c38 where the normal tx pubkey appears again with the aditional tx pubkeys tag `04` which is inappropriate. --- src/wallet/wallet2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 129b96733..42a5b3fda 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1362,8 +1362,8 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has { // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key LOG_PRINT_L0("Transaction extra has unsupported format: " << txid); - tx_cache_data.tx_extra_fields.clear(); - return; + if (tx_cache_data.tx_extra_fields.empty()) + return; } // Don't try to extract tx public key if tx has no ouputs From b0d9d6051f4c3e548cb6d1da9e49279fd3a6b700 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 22 Nov 2018 11:15:06 +0000 Subject: [PATCH 0311/1007] cn_deserialize: allow parsing partially valid tx extra --- src/debug_utilities/cn_deserialize.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp index 3e2552230..83422083b 100644 --- a/src/debug_utilities/cn_deserialize.cpp +++ b/src/debug_utilities/cn_deserialize.cpp @@ -169,6 +169,7 @@ int main(int argc, char* argv[]) return 1; } + bool full; cryptonote::block block; cryptonote::transaction tx; std::vector fields; @@ -200,9 +201,9 @@ int main(int argc, char* argv[]) std::cout << "No fields were found in tx_extra" << std::endl; } } - else if (cryptonote::parse_tx_extra(std::vector(blob.begin(), blob.end()), fields) && !fields.empty()) + else if (((full = cryptonote::parse_tx_extra(std::vector(blob.begin(), blob.end()), fields)) || true) && !fields.empty()) { - std::cout << "Parsed tx_extra:" << std::endl; + std::cout << "Parsed" << (full ? "" : " partial") << " tx_extra:" << std::endl; print_extra_fields(fields); } else From c28e3d2dae392c7df9c04447079ac156ed299f42 Mon Sep 17 00:00:00 2001 From: stoffu Date: Fri, 23 Nov 2018 12:28:04 +0900 Subject: [PATCH 0312/1007] rctOps: add braces to suppress warnings --- src/ringct/rctOps.cpp | 346 +++++++++++++++++++++--------------------- 1 file changed, 173 insertions(+), 173 deletions(-) diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 4db543f64..0ec654af6 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -42,179 +42,179 @@ using namespace std; struct zero_commitment { uint64_t amount; rct::key commitment; }; static const zero_commitment zero_commitments[] = { - { (uint64_t)0ull, {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66} }, - { (uint64_t)1ull, {0x17, 0x38, 0xeb, 0x7a, 0x67, 0x7c, 0x61, 0x49, 0x22, 0x8a, 0x2b, 0xea, 0xa2, 0x1b, 0xea, 0x9e, 0x33, 0x70, 0x80, 0x2d, 0x72, 0xa3, 0xee, 0xc7, 0x90, 0x11, 0x95, 0x80, 0xe0, 0x2b, 0xd5, 0x22} }, - { (uint64_t)2ull, {0x76, 0x24, 0x84, 0x63, 0xa, 0x6, 0x17, 0x17, 0x8d, 0xe, 0x33, 0xf3, 0x2e, 0xe, 0x11, 0x3e, 0xa8, 0x46, 0x86, 0x9d, 0x46, 0x4b, 0xb, 0x6f, 0xf1, 0x3b, 0x29, 0x97, 0x4, 0x9c, 0xda, 0x7d} }, - { (uint64_t)3ull, {0xcf, 0xf7, 0x7b, 0x56, 0x62, 0x1c, 0x4f, 0xef, 0x74, 0xcf, 0x37, 0xc1, 0x78, 0xd4, 0xb5, 0x8a, 0xf4, 0xad, 0x8c, 0xd4, 0x35, 0xfc, 0xb9, 0x62, 0x76, 0xbc, 0x15, 0x9c, 0x7c, 0x6a, 0x28, 0x8c} }, - { (uint64_t)4ull, {0x9a, 0xb8, 0x6c, 0x31, 0xf4, 0x22, 0xd8, 0x21, 0xb5, 0x22, 0x57, 0x30, 0xd1, 0xbf, 0x73, 0xa, 0x9b, 0x91, 0xd2, 0xee, 0xe3, 0x14, 0xb8, 0x4e, 0xbd, 0x4b, 0x93, 0xa6, 0x81, 0x61, 0x82, 0x66} }, - { (uint64_t)5ull, {0x32, 0xee, 0x2f, 0x65, 0x9a, 0xf6, 0x38, 0x58, 0xc2, 0xf7, 0xdc, 0x11, 0x1b, 0x3b, 0xb8, 0xfe, 0xc0, 0x2c, 0xac, 0x42, 0x38, 0x3b, 0xb7, 0x36, 0xde, 0x1, 0x8, 0x6f, 0x38, 0xf0, 0x12, 0x3c} }, - { (uint64_t)6ull, {0x47, 0x26, 0x2b, 0x1e, 0xa6, 0x43, 0x1, 0x6e, 0x38, 0x24, 0x17, 0x53, 0xa4, 0xfb, 0x39, 0x92, 0x9e, 0x31, 0xea, 0x9b, 0xd3, 0x41, 0x1a, 0xb1, 0x7f, 0x16, 0x6e, 0x61, 0xf6, 0xc, 0xe5, 0xa7} }, - { (uint64_t)7ull, {0xc6, 0x32, 0x93, 0x68, 0x79, 0x9a, 0xd, 0xed, 0x4c, 0x20, 0x25, 0x6b, 0xff, 0xe6, 0x45, 0x47, 0xf1, 0x7b, 0xc4, 0x23, 0x95, 0x4, 0xbe, 0x82, 0x4d, 0xff, 0x8a, 0x2b, 0xe1, 0xaf, 0xe3, 0xcd} }, - { (uint64_t)8ull, {0xd5, 0xf1, 0x50, 0x74, 0x33, 0x46, 0x19, 0xf, 0x84, 0x2b, 0x6, 0xb8, 0xfa, 0xe1, 0x20, 0xeb, 0x85, 0x24, 0x7e, 0x9f, 0x6d, 0xec, 0x88, 0xff, 0xa2, 0x23, 0xbf, 0x69, 0x94, 0xe9, 0xc8, 0xc2} }, - { (uint64_t)9ull, {0x56, 00, 0x23, 0x32, 0x9e, 0xc0, 0xfa, 0xf3, 0x3b, 0x5e, 0x3a, 0x5c, 0xb4, 0xea, 0xef, 0xee, 0x38, 0xf8, 0x96, 0x1c, 0x88, 0xb6, 0x6a, 0x2f, 0x19, 0xd4, 0x59, 0x51, 0x96, 0x9c, 0x6d, 0x1f} }, - { (uint64_t)10ull, {0x3, 0x80, 0xdc, 0x24, 0xcc, 0x97, 0xcc, 0xe6, 0x58, 0xc3, 0xa9, 0x47, 0xc5, 0x10, 0x25, 0xde, 0x1a, 0x69, 0x80, 0x3b, 0xdb, 0x50, 0x5, 0xe3, 0xb7, 0xdd, 0xa9, 0xd, 0x68, 0x59, 0xb0, 0x1c} }, - { (uint64_t)20ull, {0x9, 0x3, 0xf6, 0x2e, 0x97, 0x76, 0x47, 0x58, 0xfe, 0xf8, 0x9e, 0x5b, 0xec, 0x29, 0xef, 0x4f, 0xc5, 0xe6, 0x45, 0x4b, 0x2d, 0x47, 0x44, 0x47, 0x36, 0x4, 0x4c, 0x25, 0x2e, 0xe2, 0x8e, 0xba} }, - { (uint64_t)30ull, {0xa2, 0x8b, 0x89, 0xe0, 0xb, 0xed, 0x62, 0x31, 0x68, 0x5b, 0xf9, 0x74, 0x36, 0xf2, 0xba, 0x51, 0xa2, 0x51, 0x55, 0x7f, 0x8d, 0x17, 0xa, 0x78, 0xe3, 0x12, 0xd6, 0x24, 0xbf, 0x60, 0xff, 0xfe} }, - { (uint64_t)40ull, {0xb5, 0xc6, 0x95, 0x55, 0x6a, 0x28, 0x47, 0xb2, 0xe, 0x1c, 0xbb, 0x26, 0xe6, 0xa9, 0xc6, 0x8a, 0x61, 0xc5, 0x50, 0xce, 0xb7, 0xc3, 0x4, 0xfe, 0x92, 0x28, 0x3d, 0x29, 0xa9, 0xb2, 0x43, 0xcb} }, - { (uint64_t)50ull, {0x12, 0x8e, 0xc6, 0xcd, 0xc0, 0x6b, 0x43, 0xc5, 0xd0, 0x9c, 0x3f, 0x65, 0x2a, 0xe3, 0x44, 0x7f, 0x9b, 0x3f, 0x2c, 0x30, 0x91, 0x2d, 0xf0, 0x80, 0x37, 00, 0x85, 0xbc, 0xc, 0x9, 0xef, 0x78} }, - { (uint64_t)60ull, {0x1f, 0x9f, 0x40, 0x3a, 0xae, 0xa7, 0x16, 0xfb, 0xe2, 0x98, 0xa8, 0x14, 0xf1, 0xee, 0xbc, 0x1b, 0x73, 0x16, 0x8c, 0x37, 0xfa, 0xe3, 0x16, 0xeb, 0x65, 0x5, 0x81, 0x6f, 0xc2, 0x20, 0xeb, 0xfb} }, - { (uint64_t)70ull, {0x10, 0xa2, 0x38, 0xc5, 0xe4, 0x8e, 0x4b, 0x93, 0x99, 0xdb, 0xa6, 0xcb, 0xd9, 0x8e, 0x63, 0x54, 0x41, 0x59, 0xe9, 0x8c, 0x93, 0x5a, 0xc0, 0x60, 0x3d, 0x72, 0xde, 0xf, 0xff, 0x31, 0x53, 0xbb} }, - { (uint64_t)80ull, {0x75, 0xab, 0x78, 0xc7, 0x28, 0x1f, 0x69, 0x28, 0xf0, 0x94, 0x86, 0x5, 0x7a, 0x63, 0x64, 0x18, 0x27, 0xc5, 0x74, 0x84, 0xe3, 0xe9, 0x9a, 0x39, 0xf3, 0x12, 0xa4, 0x3a, 0x51, 0x9b, 0xda, 0x8} }, - { (uint64_t)90ull, {0xe9, 0x56, 0x7b, 0xa7, 0x88, 0xb8, 0x5b, 0x82, 0xc8, 0x65, 0x7a, 0x15, 0xa5, 0x48, 0x99, 0x5c, 0xf6, 0xb0, 0xbd, 0xd1, 0xc6, 0x2a, 0xda, 0x77, 0x55, 0xf2, 0x32, 0x3a, 0xd8, 0xa4, 0x8, 0x51} }, - { (uint64_t)100ull, {0xb6, 0x17, 0x36, 0xd5, 0xf2, 0x8d, 0xef, 0x28, 0x61, 0x6a, 0xfc, 0x47, 0x93, 0xe9, 0x9b, 0x27, 0xcd, 0x3e, 0x89, 0xfb, 0x91, 0xc1, 0x13, 0xd4, 0x30, 0x73, 0x65, 0xfb, 0x75, 0xde, 0xdf, 0x88} }, - { (uint64_t)200ull, {0x71, 0x3, 0xeb, 0x72, 0x19, 0x28, 0xd7, 0x91, 0x99, 0x87, 0xf3, 0x50, 0xca, 0xa5, 0x7a, 0xe7, 0xb0, 0x81, 0x57, 0x15, 0x3b, 0x4c, 0x43, 0xd, 0x3e, 0xde, 0xc0, 0xc2, 0x3, 0x7, 0x97, 0x44} }, - { (uint64_t)300ull, {0x24, 0x40, 0x9e, 0x92, 0x2e, 0xce, 0xd1, 0xa0, 0x5e, 0x4e, 0xac, 0xa3, 0xdf, 0x91, 0x19, 0xc3, 0x8a, 0x92, 0x2e, 0xb, 0x66, 0xd0, 0x2d, 0x9d, 0xd2, 0xfb, 0x1d, 0xcc, 0x20, 0xb9, 0xaf, 0xc7} }, - { (uint64_t)400ull, {0xa7, 0x72, 0x9f, 0xa9, 0x32, 0x81, 0x82, 0x99, 0x34, 0x11, 0x5d, 0x47, 0x5a, 0x67, 0x86, 0xa, 0x14, 0x12, 0xc5, 0xe5, 0x95, 0x12, 0x20, 0xd9, 0x60, 0xc2, 0x41, 0xa0, 0x19, 0x1a, 0x9e, 0x65} }, - { (uint64_t)500ull, {0x2e, 0x53, 0xc, 0x6, 0x1c, 0x6d, 0x9e, 0x97, 0xab, 0xaf, 0x46, 0x8c, 0x32, 0xb0, 0xad, 0xa7, 0x49, 0x22, 0x57, 0x72, 0xfc, 0xd1, 0x17, 0x41, 0xcb, 0x5c, 0x3, 0x5c, 0xdd, 0x26, 0x14, 0xe} }, - { (uint64_t)600ull, {0xa5, 0xb, 0x91, 0x9, 0x9d, 0xf1, 0xb1, 0x69, 0x4f, 0x30, 0xb5, 0x8f, 0xe6, 0x77, 0x68, 0x50, 0xdb, 0xdb, 0xf4, 0x6c, 0xed, 0x99, 0x7f, 0x52, 0x62, 0xa8, 0x51, 0x59, 0x40, 0x74, 0xa5, 0x9d} }, - { (uint64_t)700ull, {0x51, 0x2c, 0xf, 0xae, 0xcc, 0xbe, 0xf2, 0xfe, 0xe5, 0x75, 0x4c, 0x6a, 0x45, 0xfd, 0xc0, 0x75, 0x2d, 0x4f, 0x15, 0x22, 0xe7, 0x7f, 0xf0, 0xc4, 0x8d, 0xcb, 0x19, 0x91, 0x8a, 0x68, 0x84, 0xe0} }, - { (uint64_t)800ull, {0xda, 0xa9, 0xf9, 0xa5, 0xb9, 0x71, 0x33, 0x33, 0xe9, 0x8c, 0x5, 0xac, 0xe7, 0x27, 0xcc, 0xe, 0x7d, 0xc3, 0xf1, 0x59, 0x49, 0xe1, 0xef, 0x4d, 0x94, 0xfa, 0x47, 0xd6, 0x8a, 0x34, 0xc6, 0x75} }, - { (uint64_t)900ull, {0xc7, 0x2b, 0x18, 0xc9, 0x17, 0xcd, 0x43, 0xee, 0x78, 0x40, 0x5e, 0x39, 0x83, 0x98, 0xb8, 0x3a, 0xc0, 0x97, 0x7b, 0x25, 0x19, 0x90, 0xd8, 0x13, 0xc, 0x38, 0xba, 0x53, 0xb6, 0x3d, 0xb4, 0xf7} }, - { (uint64_t)1000ull, {0x1, 0xdf, 0x60, 0x91, 0xeb, 0x6a, 0x48, 0xe9, 0xe4, 0x22, 0x25, 0xb, 0xe3, 0x83, 0x88, 0xc8, 0x61, 0xb6, 0x55, 0x55, 0xa7, 0x20, 0xad, 0x15, 0x35, 0x86, 0xfe, 0x2b, 0xd2, 0x2f, 0xa2, 0x3d} }, - { (uint64_t)2000ull, {0x24, 0xf5, 0xb1, 0x34, 0x78, 0x46, 0xaf, 0x22, 0xb5, 0x6f, 0x41, 0x25, 0xb3, 0xe7, 0x67, 0x8c, 0xf8, 0x4b, 0x4f, 0xd2, 0xf9, 0x2e, 0x1c, 0x40, 0xaa, 0x3a, 0x1b, 0xe0, 0xc7, 0x4d, 0x95, 0xe6} }, - { (uint64_t)3000ull, {0xa7, 0x1c, 0x9a, 0x8f, 0x40, 0xc1, 0x25, 0x9c, 0x36, 0x26, 0x27, 0x73, 0xe0, 0x8, 0x20, 0x18, 0x3e, 0x6b, 0x59, 0xe0, 0x71, 0xc9, 0x9b, 0x34, 0x9b, 0xef, 0x8f, 0x7e, 0xd2, 0xc6, 0xad, 0xb9} }, - { (uint64_t)4000ull, {0x98, 0xdc, 0x74, 0xaf, 0x19, 0x89, 0xd3, 0x4b, 0x64, 0x2e, 0xb3, 0x6, 0x2d, 0xbc, 0x9d, 0xca, 0xd8, 0x1, 0xc5, 0x65, 0x27, 0x6, 0x93, 0x99, 0xe7, 0xc4, 0x11, 0xad, 0x14, 0x28, 0x82, 0xf6} }, - { (uint64_t)5000ull, {0x61, 0x76, 0xac, 0x4a, 0xc0, 0x6, 0x5e, 0x49, 0xd6, 0xc4, 0x41, 0xcf, 0x40, 0x4f, 0xad, 0xda, 0xad, 0x44, 0x93, 0xe, 0xf0, 0x3c, 0x68, 0x9, 0xad, 0xd7, 0x77, 0xe4, 0x2f, 0xee, 0x7f, 0x10} }, - { (uint64_t)6000ull, {0x78, 0x79, 0x4, 0x65, 0xf6, 0x60, 0x5b, 0x5a, 0x84, 0x77, 0x36, 0x5a, 0xa6, 0xc2, 0xa4, 0xa5, 0x84, 0x91, 0xc, 0x23, 0x95, 0x2, 0x92, 0x97, 0x52, 0x49, 0xa1, 0xad, 0x7d, 0xf0, 0xf7, 0xe8} }, - { (uint64_t)7000ull, {0x20, 0xa5, 0x60, 0x6b, 0x60, 0x23, 0x95, 0xd6, 0x8e, 0x2f, 0xad, 0x8e, 0xc6, 0x7f, 0x92, 0xde, 0x89, 0xc6, 0x3e, 0x1e, 0x7f, 0xc1, 0xdd, 0x7f, 0x92, 0xff, 0xed, 0xb8, 0xf6, 0x55, 0xfb, 0xd} }, - { (uint64_t)8000ull, {0x9a, 0x78, 0x97, 0x43, 0x98, 0x65, 0x17, 0xd9, 0x5f, 0x4e, 0x80, 0x8b, 0xeb, 0xe6, 0x52, 0xd, 0xe6, 0xcf, 0x8c, 0x51, 0x35, 0xab, 0x36, 0x8, 0x7e, 0x87, 0xe2, 0x76, 0xac, 0x6a, 0x34, 0x1} }, - { (uint64_t)9000ull, {0x5f, 0xc7, 0xaa, 0x48, 0xbb, 0x19, 0x13, 0x58, 0xc7, 0xe3, 0x4d, 0x24, 0xcf, 0x9c, 0x31, 0x16, 0x74, 0x12, 0x7a, 0xb2, 0x45, 0xd0, 0x8f, 0x4e, 0x2c, 0xfd, 0xbf, 0x8f, 0x5, 0xc9, 0x5b, 0xf5} }, - { (uint64_t)10000ull, {0x61, 0x20, 0xe7, 0x76, 0xe9, 0x12, 0xab, 0x10, 0x5a, 0x49, 0xf9, 0xda, 0x2, 0xa6, 0x75, 0x17, 0xc0, 0xa9, 0xb, 0x2b, 0x3e, 0x2d, 0xa3, 0xd, 0xff, 0x34, 0x39, 0x93, 0xdb, 0xec, 0x95, 0x97} }, - { (uint64_t)20000ull, {0x77, 0xbf, 0xb5, 0x37, 0xac, 0xa, 0xbc, 0x41, 0xaa, 0x21, 0xd0, 0xec, 0xd9, 0x18, 0x13, 0x34, 0xd8, 0x6b, 0xa7, 0x86, 0x5a, 0x94, 0x47, 0xf5, 0xc1, 0x58, 0x9a, 0x81, 0xd7, 0xef, 0xb3, 0xbb} }, - { (uint64_t)30000ull, {0x35, 0xf4, 0x5, 0xa9, 0x5f, 0x75, 0x19, 0x2a, 0xe9, 0xc0, 0xd4, 0xf5, 0x88, 0x84, 0x47, 0x14, 0xf6, 0x85, 0x1b, 0x97, 0xce, 0xbd, 0x9f, 0x7c, 0x2, 0xc5, 0xdd, 0xd7, 0xbf, 0x58, 0xff, 0x31} }, - { (uint64_t)40000ull, {0x77, 0x55, 0xbb, 0x3f, 0x38, 0x7c, 0x21, 0xb8, 0xa0, 0xf4, 0x48, 0x1f, 0xbf, 0xa8, 0x8a, 0xbe, 0xee, 0xce, 0xc7, 0x56, 0x53, 0xfc, 0xa1, 0x89, 0x58, 0x39, 0xc1, 0xba, 0x6, 0x47, 0x9f, 0x96} }, - { (uint64_t)50000ull, {0x8b, 0x7e, 0x84, 0xa3, 0x37, 0xb7, 0xb9, 0xcd, 0x5d, 0xb3, 0x63, 0x33, 0x8, 0xad, 0x51, 0x86, 0xa3, 0x59, 0xd, 0xff, 0xb8, 0x23, 0x1e, 0x2f, 0x31, 0xfd, 0x20, 0x42, 0x54, 0x9f, 0xfb, 0xe2} }, - { (uint64_t)60000ull, {0xef, 0xfd, 0xa6, 0x25, 0x15, 0xea, 0xb1, 0xbc, 0x1e, 0xbd, 0x74, 0x92, 0x94, 0x9b, 0x1, 0x22, 0xc3, 0x9f, 0x71, 0xa, 0x65, 0x16, 0xec, 0x66, 0x8c, 0x37, 0x61, 0xe6, 0xcc, 0x36, 0x1f, 0x25} }, - { (uint64_t)70000ull, {0x16, 0xba, 0x89, 00, 0xf3, 0x6f, 0xf, 0x6c, 0x46, 0x1c, 0xb, 0xe7, 0x64, 0xae, 0xee, 0x48, 0x86, 0x6, 0xb0, 0x53, 0xed, 0xdc, 0x10, 0xb5, 0x9a, 0x3e, 0xde, 0xcd, 0x23, 0xd4, 0x4f, 0xc0} }, - { (uint64_t)80000ull, {0x4d, 0xd4, 0x70, 0x3b, 0x7b, 0x7f, 0xcf, 0xe7, 0x2a, 0x2e, 0x4f, 0x31, 0xa4, 0x34, 0x17, 0xf9, 0xc0, 0xda, 0x64, 0x2f, 0xd0, 0xa9, 0x29, 0xb8, 0xf5, 0xed, 0xd8, 0x3, 0x7f, 0x93, 0xc5, 0xb3} }, - { (uint64_t)90000ull, {0x8e, 0xfc, 0x3, 0x20, 0x40, 0xbd, 0x90, 0x41, 0xda, 0x3d, 0xb0, 0x9b, 0xa1, 0x3d, 0xa2, 0xa5, 0xd1, 0xb8, 0x12, 0x3, 0xa, 0x5a, 0x36, 0x7c, 0x58, 0x94, 0xbd, 0x54, 0x11, 0x9, 0xe7, 0x30} }, - { (uint64_t)100000ull, {0xbd, 0x2e, 0xb1, 0x97, 0x83, 0x57, 0x1c, 0xf2, 0x22, 0x2c, 0x81, 0xb, 0x69, 0xf, 0xc7, 0x66, 0x64, 0x57, 0xae, 0x20, 0x92, 0x5b, 0x90, 0x5, 0xce, 0xe6, 0x1d, 0xf2, 0x66, 0x6f, 0xdc, 0xb7} }, - { (uint64_t)200000ull, {0x83, 0xd4, 0xcd, 0xdd, 0xc1, 0x44, 0x87, 0x32, 0xf2, 0x97, 0x7c, 0x41, 0xaa, 0xa7, 0x1f, 0xe6, 0xde, 0x9c, 0x17, 0x6d, 0xa8, 0x99, 0xee, 0xbf, 0xfc, 0x1b, 0xb, 0xa9, 0xea, 0x92, 0x97, 0x90} }, - { (uint64_t)300000ull, {0xcc, 0xc0, 0x6b, 0x44, 0xc3, 0x1, 0x38, 0x6, 0x30, 0x45, 0xed, 0x1, 0xd2, 0x45, 0xd8, 0x14, 0x3, 0xb6, 0x36, 0x52, 0xeb, 0xc4, 0xf9, 0x96, 0x7f, 0xd, 0x7f, 0x38, 0x69, 0x7f, 0x46, 0x16} }, - { (uint64_t)400000ull, {0x1b, 0xbf, 0xe7, 0xe, 0xca, 0xf1, 0xdd, 0xd7, 0xf1, 0x2, 0x36, 0xf6, 0x8a, 0x41, 00, 0xb, 0x5d, 0xab, 0x2d, 0x47, 0x5c, 0xb9, 0x2f, 0x62, 0xc2, 0xd6, 0x84, 0xcf, 0x57, 0x69, 0xfb, 0x84} }, - { (uint64_t)500000ull, {0xf1, 0xb1, 0xcd, 0xaa, 0x78, 0x14, 0x95, 0x36, 0xf, 0x53, 0x31, 0x81, 0xaa, 0x58, 0xc8, 0xbd, 0xae, 0x6a, 0x77, 0x98, 0xd0, 0x2d, 0xab, 0x6d, 0x56, 0x26, 0x81, 0x27, 0x67, 0x9, 0xe7, 0x1} }, - { (uint64_t)600000ull, {0xd5, 0x26, 0x7d, 0x60, 0xd4, 0xfe, 0x9b, 0xc5, 0xfe, 0xfa, 0x7d, 0x3f, 0xe0, 0x7c, 0xd1, 0xfa, 0xd4, 0x55, 0x73, 0xd5, 0xae, 0x19, 0x10, 0xda, 0x7, 0x3e, 0x6d, 0x2d, 0xf9, 0xe2, 0x4, 0x39} }, - { (uint64_t)700000ull, {0xb, 0x58, 0x11, 0x25, 0xc2, 0xc4, 0x83, 0xc9, 0xa3, 0xd8, 0xbc, 0x8, 0x32, 0x2f, 0x26, 0xaa, 0x1f, 0xc5, 0xe, 0x41, 0x53, 0x2c, 0x1b, 0x9d, 0xf6, 0x26, 0xb0, 0x9, 0xd7, 0x88, 0x67, 0xcf} }, - { (uint64_t)800000ull, {0xf5, 0xb3, 0xd1, 0x8f, 0x66, 0xd0, 0xf9, 0x17, 0x5c, 0x30, 0x83, 0xb5, 0xf8, 0x7, 0x8e, 0xaf, 0xa8, 0x9e, 0xf8, 0x1d, 0xe7, 0x15, 0x8, 0xbc, 0x25, 0x1f, 0x5c, 0x5f, 0xe7, 0x25, 0x2e, 0x6} }, - { (uint64_t)900000ull, {0x1, 0xde, 0x40, 0x2c, 0x4b, 00, 0x43, 0x4, 0x2e, 0xae, 0x9e, 0xde, 0xa1, 0x49, 0x2b, 0x9d, 0x82, 0xb7, 0xbc, 0x36, 0x68, 0xe9, 0xb5, 0x84, 0xb0, 0x31, 0x3d, 0x44, 0x50, 0x53, 0x40, 0x74} }, - { (uint64_t)1000000ull, {0x53, 0x4b, 0x85, 0xc7, 0x89, 0x3f, 0x66, 0xf0, 0x26, 0xb6, 0x5e, 0xd7, 0xe7, 0xa4, 0xb8, 0xc9, 0xf4, 0xb, 0xe3, 0x1b, 0xcd, 0xa, 0x3d, 0xcd, 0x27, 0xc4, 0x71, 0x2, 0x56, 0x51, 0x65, 0x3} }, - { (uint64_t)2000000ull, {0xcd, 0xb5, 0xda, 0xfa, 0x53, 0x10, 0xf5, 0x26, 0x2f, 0xfc, 0x9, 0x26, 0xd0, 0xdf, 0x6e, 0xeb, 0xee, 0x2d, 0x52, 0xa9, 0x8d, 0xc6, 0x9f, 0xd, 0xc5, 0xe4, 0xeb, 0xf0, 0xc1, 0xa8, 0x77, 0x2e} }, - { (uint64_t)3000000ull, {0x9e, 0x75, 0x63, 0xf0, 0x33, 0x59, 0xea, 0x31, 0xe2, 0x91, 0xe7, 0xf0, 0xb8, 0x74, 0x17, 0xbc, 0xf5, 0xb2, 0x34, 0xee, 0x8b, 0x7e, 0x5b, 0x4, 0x41, 0x73, 0xbf, 00, 0x46, 0x86, 0x7c, 0x57} }, - { (uint64_t)4000000ull, {0xfd, 0x2a, 0xeb, 0xd, 0x5e, 0xe5, 0x3b, 0x77, 0xf2, 0xb1, 0xe3, 0xac, 0x75, 0x2d, 0x19, 0x38, 0x9f, 0xc5, 0xba, 0xa0, 0xf8, 0xd7, 0x64, 0x48, 0xa5, 0x9f, 0x99, 0x85, 0xa4, 0x8d, 0xa, 0x25} }, - { (uint64_t)5000000ull, {0xc0, 0xbe, 0x4f, 0xb8, 0x77, 0xb9, 0xce, 0x50, 0x87, 0x71, 0x32, 0x3b, 0xcf, 0x1f, 0xb9, 0x48, 0x47, 0x10, 0xee, 0x23, 0x2, 00, 0x6, 0xc3, 0xe8, 0xca, 0xac, 0x6e, 0x4f, 0x2, 0xfa, 0xbf} }, - { (uint64_t)6000000ull, {0xfc, 0x44, 0x5c, 0xa3, 0x84, 0xf3, 0x3e, 0x55, 0x8d, 0xc1, 0x56, 0x44, 0x9d, 0x3f, 0xba, 0x6a, 0xfd, 0x54, 0xc3, 0x42, 0xe6, 0x35, 0x11, 0xf, 0xe7, 0x9c, 0x16, 0xc7, 0x17, 0xf7, 0xd4, 0xf7} }, - { (uint64_t)7000000ull, {0xd8, 0x9, 0x2b, 0x8d, 0x45, 0xdb, 0x54, 0xa5, 0x6d, 0x64, 0xe8, 0x9, 0x4a, 0x6, 0x22, 0xe2, 0x6e, 0x8a, 0x2e, 0xec, 0xb9, 0x3, 0xb2, 0xe1, 0xf7, 0x5a, 0x83, 0x7b, 0x3a, 0xd8, 0x55, 0x4a} }, - { (uint64_t)8000000ull, {0x10, 0x4, 0x5c, 0x91, 0xdb, 0xad, 0x8a, 0x6a, 0x81, 0x62, 0x4a, 0xe0, 0xcf, 0x20, 0x5d, 0xb9, 0x97, 0x3e, 0xe8, 0x42, 0x3e, 0x97, 0xaf, 0x58, 0xa6, 0x1c, 0xfa, 0x7a, 0x78, 0x66, 0xf4, 0x1} }, - { (uint64_t)9000000ull, {0x11, 0x5c, 0x20, 0x9e, 0xe1, 0xde, 0xf3, 0x10, 0xce, 0xc9, 0xa6, 0xd1, 0x6c, 0xe6, 0x27, 0xec, 0xbd, 0xb9, 0xff, 0x2c, 0x23, 0x9, 0x3c, 0x24, 0xc8, 0x6c, 0x1b, 0xf2, 0x50, 0xd4, 0xb5, 0x85} }, - { (uint64_t)10000000ull, {0x2f, 0x99, 0xd9, 0x74, 0x44, 0x18, 0x66, 0x9, 0x49, 0xba, 0x43, 0x35, 0x61, 0xc6, 0x5, 0xb6, 0xf7, 0xbe, 0x8f, 0x82, 0xa, 0x93, 0xcb, 0x2a, 0xed, 0xa9, 0x7c, 0x87, 0x32, 0x92, 0x56, 0x49} }, - { (uint64_t)20000000ull, {0xc6, 0x77, 0x1f, 0xab, 0x14, 0xb, 0x75, 0xf4, 0xef, 0xd0, 0x97, 0xfc, 0xe1, 0x82, 0x6b, 0x80, 0xba, 0xe3, 0x16, 0xbc, 0xec, 0x28, 0x86, 0x9b, 0x3a, 0x1b, 0xf1, 0xbc, 0x6e, 0x4d, 0x20, 0x43} }, - { (uint64_t)30000000ull, {0xa1, 0xe9, 0xed, 0x3e, 0xf6, 0x5a, 0x9d, 0x52, 0x6c, 0xc2, 0x62, 0x5, 0x88, 0x12, 0x1, 0xd8, 0xa8, 0xf2, 0xc4, 0x40, 0x9f, 0xa3, 0x64, 0x10, 0x72, 0x96, 0xb9, 0xf9, 0x6a, 0x61, 0xb3, 0x58} }, - { (uint64_t)40000000ull, {0xb5, 0x31, 0x2d, 0xc7, 0x72, 0x94, 0xab, 0x9b, 0xc8, 0xbf, 0xd1, 0x39, 0x1e, 0x9a, 0xca, 0x92, 0x45, 0xe2, 0x28, 0xf7, 0x4b, 0x49, 0x74, 0xfc, 0x29, 0xad, 0x1c, 0x31, 0xcb, 0xe3, 0xe6, 0xa3} }, - { (uint64_t)50000000ull, {0xb8, 0xab, 0xc9, 0xff, 0xf6, 0x84, 0x1d, 0x2e, 0xa0, 0x13, 0x5a, 0x21, 0x72, 0xd3, 0xa7, 0xb, 0xfc, 0x2b, 0x70, 0x22, 0x8, 0xcd, 0x4a, 0x43, 0xc6, 0x30, 0xbe, 0xb1, 0xb8, 0xa0, 0x32, 0x8b} }, - { (uint64_t)60000000ull, {0x63, 0x90, 0xe1, 0xdb, 0x81, 0xb0, 0xea, 0x5c, 0xe2, 0x73, 0x94, 0x14, 0xe5, 0x2b, 0x7, 0x98, 0xd8, 0x2e, 0xb8, 0xe9, 0xae, 0xc5, 0x6d, 0xfe, 0x7e, 0x2c, 0x64, 0x11, 0xab, 0x79, 0x41, 0x87} }, - { (uint64_t)70000000ull, {0x7e, 0x51, 0xaf, 0xee, 0x5b, 0xc9, 0x71, 0x52, 0x9d, 0x64, 0x4d, 0xcd, 0x7f, 0x2a, 0x2a, 0xb0, 0x26, 0x69, 0xce, 0x2c, 0xb5, 0x7, 0xa6, 0x2d, 0xfc, 0x93, 0x17, 0x6c, 0xb6, 0xdf, 0x41, 0x38} }, - { (uint64_t)80000000ull, {0xf3, 0x7b, 0x94, 0x6b, 0x8b, 0x24, 0x88, 0xeb, 0xee, 0x1c, 0x6, 0xc1, 0x27, 0xfb, 0xe5, 0xfa, 0x5e, 0xfd, 0x62, 0x36, 0x9d, 0xd5, 0xaa, 0xda, 0xed, 0xd8, 0x88, 0x50, 0x1d, 0x3b, 0x7e, 0x3b} }, - { (uint64_t)90000000ull, {0x46, 0xcb, 0x76, 0x57, 0xf6, 0x1c, 0x83, 0x7c, 0xec, 0x80, 0x74, 0xbb, 0xb0, 0xf5, 0x2e, 0x7f, 0xc5, 0x9a, 0xd, 0x94, 0xe0, 0x17, 00, 0x9a, 0xbe, 0x25, 0x65, 0x2e, 0x4a, 0xd2, 0xe5, 0x3d} }, - { (uint64_t)100000000ull, {0x66, 0x7b, 0x8e, 0x6f, 0x6a, 0x4b, 0x91, 0x89, 0x76, 0xd9, 0x73, 0x5a, 0x43, 0x36, 0x7d, 0xc7, 0x59, 0x2c, 0x87, 0xd0, 0xa1, 0xf8, 0x15, 0xc6, 0xe8, 0x7d, 0xf1, 0x1a, 0x13, 0x50, 0x9f, 0xb2} }, - { (uint64_t)200000000ull, {0x3b, 0xcb, 0x51, 0x48, 0x1, 0x64, 0x1b, 0x62, 0x55, 0x93, 0x8c, 0xc5, 0x3, 0x76, 0x2d, 0x35, 0xce, 0x6, 0xd7, 0x5f, 0xe9, 0x50, 0x95, 0x9a, 0x1a, 0xab, 0x21, 0x4b, 0x50, 0x9b, 0x10, 0xb} }, - { (uint64_t)300000000ull, {0xa5, 0x92, 0x6f, 0x3, 0x1e, 0x6b, 0x15, 0xeb, 0x86, 0x23, 0x51, 0x8, 0xab, 0xb1, 0xaf, 0x90, 0xc5, 0xb1, 0x62, 0xc3, 0x99, 0x8c, 0x8b, 0xbb, 0x3f, 0xfb, 0xb0, 0x72, 0x9d, 0xa9, 0x45, 0x7b} }, - { (uint64_t)400000000ull, {0xfe, 0x35, 0xb6, 0x99, 0x44, 0x41, 0xe, 0xaf, 0x81, 0x5b, 0xdc, 0xd0, 0xa4, 0xd7, 0x1e, 0xf9, 0xfc, 0x66, 0x86, 0x48, 0xad, 0x43, 0x74, 0x3b, 0x3, 0x5a, 0xed, 0x2c, 0x17, 0xc1, 0x38, 0x7a} }, - { (uint64_t)500000000ull, {0x22, 0x22, 0xd6, 0x70, 0xb8, 0x7d, 0x9b, 0x47, 0xb8, 0xb9, 0x5c, 0x8c, 0x39, 0x7b, 0xc5, 0x2e, 0x2b, 0x46, 0xa6, 0x48, 0xb0, 0x2, 0xa0, 0x48, 0x5a, 0x37, 0x5c, 0xd8, 0x1f, 0x4a, 0x54, 0x5f} }, - { (uint64_t)600000000ull, {0xd3, 0x23, 0x8a, 0x4a, 0x8b, 0x71, 0xab, 0x46, 0xd1, 0x53, 0x4, 0xac, 0xfa, 0x2f, 0x40, 0xbf, 0x5e, 0xa6, 0x3b, 0x3d, 0x86, 0x4a, 0x79, 0xfa, 0x84, 0x25, 0xd2, 0x65, 0x5a, 0xe7, 0x7, 0x6f} }, - { (uint64_t)700000000ull, {0xa8, 0xff, 0x28, 0x3f, 0xcf, 0xf0, 0x53, 0xd3, 0x44, 0xc8, 0xf7, 0x56, 0x4f, 0x40, 0x24, 0xb6, 0x6b, 0xfa, 0x45, 0x9f, 0x47, 0x6f, 0xd, 0x73, 0xc, 0x91, 0x39, 0x90, 0x8b, 0x2d, 0x64, 0x7e} }, - { (uint64_t)800000000ull, {0xf2, 0xda, 0xf8, 0x88, 0xc4, 0x46, 0x57, 0x1, 0xc0, 0xe6, 0x1e, 0x12, 0xc3, 0xfb, 0xd4, 0xea, 0x79, 0xc7, 0xec, 0xb4, 0xf0, 0xc4, 0xb1, 0x54, 0xc5, 0x1a, 0x24, 0xd1, 0xe9, 0x21, 0x28, 0xba} }, - { (uint64_t)900000000ull, {0x11, 0x6a, 0xe5, 0xd2, 0x9c, 0xec, 0x72, 0xaa, 0xc5, 0x57, 0xcb, 0x14, 0xe2, 0xcd, 0xd5, 0x53, 0xe5, 0x88, 0xff, 0x8b, 0x81, 0x78, 0x26, 0x1, 0x99, 0xc4, 0xc, 0xae, 0xa2, 0x12, 0xcb, 0x63} }, - { (uint64_t)1000000000ull, {0x8c, 0xe6, 0x48, 0x33, 0xce, 0xc9, 00, 0xcb, 0x6d, 0x5a, 0xc4, 0x6f, 0xc0, 0x23, 0x7d, 0x8f, 0x24, 0x39, 0xc3, 0xdf, 0xa2, 0x38, 0xba, 0xf9, 0xcc, 0x94, 0x16, 0x6a, 0xd2, 0xe8, 0x98, 0x87} }, - { (uint64_t)2000000000ull, {0x37, 0x8d, 0x3c, 0x5d, 0xbb, 0xa4, 0x82, 0x3d, 0x33, 0x12, 0xbb, 0x61, 0xfc, 0x6, 0x75, 0xa1, 0xbb, 0x39, 0x89, 0xf3, 0x97, 0x1, 0xeb, 0xd, 0x5c, 0xe4, 0xde, 0x5b, 0xd, 0x90, 0x74, 0x72} }, - { (uint64_t)3000000000ull, {0x7f, 0xa2, 0xd0, 0xa5, 0x99, 0xe7, 0x97, 0x2e, 0x74, 0xcb, 0x75, 0xf9, 0x8a, 0xf4, 0x84, 0xfc, 0x85, 0x19, 0xcb, 0x7e, 0x25, 0xb9, 0x84, 0xa7, 0x6d, 0x8b, 0xc2, 0xba, 0x8d, 0xaf, 0xde, 0xd8} }, - { (uint64_t)4000000000ull, {0xda, 0x3a, 0xcb, 00, 0xab, 0x2d, 0x8d, 0xcc, 0xac, 0xec, 0x8f, 0x77, 0x59, 0x21, 0xc4, 0xe, 0x26, 0xb1, 0xff, 0xbe, 0xca, 0x9e, 0xb7, 0xe6, 0x57, 0x25, 0x6f, 0x59, 0x68, 0xf2, 0x34, 0x1c} }, - { (uint64_t)5000000000ull, {0x34, 0x6, 0xd7, 0x9a, 0x50, 0xd8, 0x14, 0xa9, 0xcc, 0xed, 0x3b, 0x24, 0x4, 0xed, 0x3e, 0x1b, 0x8d, 0xa6, 0x21, 0x98, 0x8c, 0x43, 0xb1, 0x93, 0x69, 0x42, 0xf4, 0x94, 0xa, 0xc5, 0xbf, 0x6a} }, - { (uint64_t)6000000000ull, {0xf8, 0x3e, 0xe8, 0xc1, 0x62, 0xfc, 0x52, 0xa0, 0x8, 0x9f, 0x46, 0xe8, 0x29, 0xc2, 0xea, 0xf6, 0xa1, 0x9f, 0xd5, 0x96, 0xcd, 0x12, 0xb3, 0xe8, 0x19, 0xd5, 0x67, 0x69, 0x44, 0xf, 0x7b, 0x4e} }, - { (uint64_t)7000000000ull, {0x8c, 0x72, 0x7d, 0x24, 0x57, 0xf3, 0x4b, 0x2f, 0xdb, 0x6a, 0xdf, 0x69, 0x1a, 0xb3, 0x5f, 0xaa, 0xe4, 0xff, 0x23, 0x4c, 0x28, 0xb4, 0x4e, 0x9f, 0xd3, 0x71, 0x8e, 0xef, 0xec, 0x41, 0x75, 0x80} }, - { (uint64_t)8000000000ull, {0x4a, 0x2e, 0x2f, 0x76, 0xe3, 0x5d, 0xcb, 0xa8, 0x97, 0xa3, 0xae, 0x72, 0xc4, 0x27, 0xd, 0x9c, 0x13, 0x17, 0x14, 0xed, 0x19, 0x1b, 0x55, 0x5c, 0x5e, 0x1, 0xe4, 0x75, 0x7c, 0xba, 0xe7, 0x2c} }, - { (uint64_t)9000000000ull, {0x3f, 0x9f, 0xc, 0x4, 0xc0, 0xb9, 0xec, 0x9b, 0x4d, 0x11, 0x7c, 0x5f, 0xc9, 0xf1, 0x8a, 0x20, 0xf2, 0xb3, 0xfa, 0xcc, 0xa4, 0xc8, 0xae, 0x41, 0xaf, 0x7c, 0x8, 0xe9, 0xe0, 0xef, 0xb9, 0x81} }, - { (uint64_t)10000000000ull, {0x97, 0xc9, 0x2a, 0x29, 0x1, 0x5e, 0xcb, 0x49, 0xf8, 0x9, 0x5, 0x45, 0xe0, 0x1f, 0xf9, 0x78, 0x6c, 0xae, 0x40, 0x57, 0x73, 0x47, 0x61, 0x18, 0x24, 0xf4, 0xb6, 0x59, 0x9f, 0xf5, 0xd3, 0x64} }, - { (uint64_t)20000000000ull, {0x9, 0xba, 0xed, 0x9a, 0x3c, 0x44, 0xb2, 0x22, 0x85, 0xa0, 0xae, 0xa4, 0x14, 0x8c, 0xa7, 0xde, 0x9b, 0xea, 0x96, 0x3c, 0xf6, 0x96, 0x23, 0xb6, 0x83, 0x44, 0x5c, 0xa, 0x10, 0xa5, 0x86, 0x77} }, - { (uint64_t)30000000000ull, {0x45, 0xac, 0xaf, 0x1d, 0xe2, 0x89, 0x6d, 0xe8, 0x72, 0x84, 0xff, 0xed, 0x57, 0x8b, 0x77, 0x14, 0xf5, 0x18, 0xa6, 0x18, 0xe2, 0xae, 0x6f, 0x90, 0xae, 0x4f, 0x70, 0x13, 0xa2, 0x8e, 0x99, 0xe0} }, - { (uint64_t)40000000000ull, {0x8, 0xb8, 0x47, 0x36, 0x42, 0x24, 0xe2, 0x9c, 0xe3, 0x36, 0x63, 0x93, 0xc2, 0xe1, 0x1e, 0xfc, 0x75, 0x55, 0xde, 0xe1, 0xa0, 0x5f, 0x91, 0xa7, 0x2e, 0x61, 0x11, 0x76, 0x84, 0xdd, 0xbe, 0x29} }, - { (uint64_t)50000000000ull, {0x6c, 0x8e, 0xe, 0x4a, 0x63, 0x4f, 0x85, 0x9a, 0x31, 0xab, 0x2f, 0x7a, 0x78, 0xc0, 0xc4, 0xa5, 0x93, 0x8c, 0xb7, 0x7f, 0x3, 0x35, 0x50, 0xa4, 0x7d, 0x7e, 0x31, 0x81, 0xb6, 0xb2, 0x6e, 0xc0} }, - { (uint64_t)60000000000ull, {0x66, 0xc2, 0xa0, 0x9, 0x65, 0xf9, 0xbf, 0xcb, 0xb1, 0x1e, 0xa0, 0x3c, 0xf1, 0xd6, 0x31, 0xb0, 0xe, 0x8a, 0x1e, 0xf7, 0xa6, 0xb, 0x1b, 0xe4, 0xa5, 0xac, 0x9, 0x23, 0xb, 0xf8, 0x17, 0x3f} }, - { (uint64_t)70000000000ull, {0x63, 0x51, 0xd7, 0x74, 0xc0, 0x2c, 0x5a, 0x9d, 0xee, 0xcf, 0xdb, 0xab, 0x70, 0x96, 0x68, 0x59, 0x8c, 0x47, 0xe4, 0xb1, 0x78, 0x2c, 0xe5, 0xae, 0x31, 0x6a, 0xf7, 0x40, 0xa6, 0x6f, 0x7e, 0x30} }, - { (uint64_t)80000000000ull, {0x5a, 0xcc, 0xfd, 0x16, 0x22, 0x79, 0xa5, 0x1c, 0x8b, 0x3b, 0xd5, 0xd3, 0x67, 0x9e, 0x91, 0x89, 0x67, 0xa2, 0x64, 0xea, 0x6, 0x3d, 0x37, 0xdf, 0xf5, 0xe3, 0x45, 0x7e, 0xc3, 0x7, 0xd4, 0x57} }, - { (uint64_t)90000000000ull, {0xb7, 0x47, 0xfc, 0x1, 0xc6, 0xf0, 0xc7, 0x49, 0x67, 0x3a, 0x29, 0x10, 0x25, 0xc, 0x2e, 0x23, 0xcb, 0x38, 0x27, 0x4d, 0x63, 0xb4, 0x2f, 0x52, 0x1b, 0x84, 0x63, 0x56, 0xe4, 0x13, 0x61, 0x8f} }, - { (uint64_t)100000000000ull, {0x9, 0x42, 0x84, 0x3d, 0x6f, 0x69, 0xe1, 0xcf, 0x3d, 0x99, 0xc9, 0x9f, 0xc, 0x97, 0xc0, 0xe6, 0xe5, 0x78, 0x93, 0x5a, 0xf6, 0xa8, 0xbd, 0xb8, 0xf8, 0x1d, 0x5b, 0x90, 0xbd, 0xe7, 0xcc, 0x10} }, - { (uint64_t)200000000000ull, {0x56, 0x4c, 0x64, 0xea, 0x50, 0xe4, 0xbd, 0x20, 0xdb, 0x58, 0x5d, 0xb5, 0x87, 0xb1, 0xf7, 0x64, 0xa2, 0x62, 0xd8, 0x46, 0xa6, 0xb0, 0xa2, 0x4b, 0x43, 0x27, 0x60, 0xd2, 0xf9, 0xde, 0x66, 0x5b} }, - { (uint64_t)300000000000ull, {0xac, 0x65, 0x83, 0x41, 0x5b, 0xd6, 0x4c, 0x3, 0x35, 0x97, 0xf9, 0x28, 0xa4, 0xb5, 0xd4, 0xf4, 0x78, 0x9e, 0xa8, 0xb2, 0x87, 0x82, 0x73, 0x89, 0xa8, 0x1e, 0xb6, 0x62, 0x9e, 0xc5, 0xb8, 0x50} }, - { (uint64_t)400000000000ull, {0x52, 0xf4, 0x9d, 0x89, 0xcf, 0x74, 0x13, 0x2f, 0xc7, 0x43, 0x2e, 0x6a, 0x6b, 0xef, 0xcf, 0xf3, 0xfd, 0x13, 0xd6, 0x3b, 0x51, 0x60, 0xab, 0x1c, 0xe6, 0x4a, 0xb0, 0xd1, 0x21, 0xcd, 0xa9, 0x9a} }, - { (uint64_t)500000000000ull, {0xe9, 0xaa, 0x7c, 0x81, 0xcd, 0xb5, 0xb3, 0x14, 0x8f, 0xb7, 0x62, 0x80, 0x63, 0xcd, 0x7a, 0x7, 0xd1, 0xad, 0xd1, 0x64, 0x3c, 0xed, 0xd3, 0xfa, 0x34, 0x47, 0x9d, 0x85, 0x9c, 0xc5, 0x62, 0x65} }, - { (uint64_t)600000000000ull, {0x98, 0x27, 0xae, 0x31, 0xe5, 0xc2, 0xa7, 0x78, 0x39, 0xf6, 0xb, 0x83, 0xab, 0x45, 0x78, 0xe2, 0xa0, 0x1e, 0xfa, 0x4b, 0x3b, 0x14, 0xcc, 0x72, 0x73, 0x14, 0xff, 0xd7, 0x15, 0x53, 0x63, 0xbf} }, - { (uint64_t)700000000000ull, {0x72, 0x91, 0x6a, 0x79, 0x27, 0xff, 0x13, 0x24, 0xd4, 0x98, 0x40, 0xec, 0xc0, 0x98, 0x68, 0xb8, 0xf3, 0x15, 0xe4, 0xf1, 0xf6, 0xd4, 0x45, 0x8d, 0x37, 0x5e, 0xc7, 0x45, 0xfc, 0x2e, 0x63, 0x53} }, - { (uint64_t)800000000000ull, {0x66, 0x76, 0xe0, 0x4, 0xf, 0xa4, 0xb8, 0x22, 0x9c, 0x61, 0x69, 0xc, 0x71, 0x32, 0x22, 0xcf, 0x3d, 0x37, 0xb9, 0x49, 0x3b, 0x49, 0x6, 0x80, 0xbb, 0x48, 0xd8, 0xd5, 0x1a, 0xde, 0x95, 0xf2} }, - { (uint64_t)900000000000ull, {0x41, 0x54, 0xb3, 0x46, 0x5a, 0x43, 0x72, 0x67, 0x1e, 0xa9, 0xe0, 0x64, 0xa7, 0xca, 0xa6, 0x6e, 0x14, 0xb4, 0x98, 0x6a, 0x46, 0x68, 0x91, 0x8a, 0xfa, 0x57, 0x9b, 0xf1, 0xed, 0x25, 0x6, 0xdd} }, - { (uint64_t)1000000000000ull, {0xbb, 0x6f, 0x70, 0x62, 0xca, 0x30, 0x6d, 0x67, 0x2a, 0x73, 0xe, 0x2a, 0x2f, 0x21, 0x9b, 0xdb, 0xe4, 0xc, 0x9f, 0xb3, 0xfe, 0x4d, 0x60, 0x13, 0x69, 0x2a, 0xf9, 0x3c, 0xdb, 0x2e, 0xc, 0xd1} }, - { (uint64_t)2000000000000ull, {0xbc, 0xe, 0xae, 0x5b, 0x9c, 0x6a, 0xd6, 0x38, 0x7a, 0x41, 0x19, 0x3c, 0x46, 0xf3, 0xc1, 0xd0, 0x71, 0x6d, 0x77, 0xd6, 0x4e, 0x22, 0xb2, 0xe0, 0x7b, 0x4b, 0xce, 0x75, 0x67, 0x65, 0xa2, 0xb} }, - { (uint64_t)3000000000000ull, {0x10, 0xc, 0x6f, 0x13, 0x42, 0xb7, 0x1b, 0x73, 0xed, 0xdd, 0xc5, 0x49, 0x2b, 0xe9, 0x23, 0x18, 0x2f, 00, 0xa6, 0x83, 0x48, 0x8e, 0xc3, 0xa2, 0xa1, 0xc7, 0xa9, 0x49, 0xcb, 0xe5, 0x77, 0x68} }, - { (uint64_t)4000000000000ull, {0x41, 0x9f, 0x7c, 0x94, 0x91, 0x4, 0x34, 0xf, 0xd3, 0xce, 0x85, 0x94, 0x8d, 0x2e, 0xf9, 0xf0, 0xdd, 0x4b, 0xb3, 0xd9, 0x2f, 0x5a, 0x78, 0x2c, 0x5f, 0x78, 0x4, 0xb7, 0x52, 0x9a, 0x13, 0xc6} }, - { (uint64_t)5000000000000ull, {0x40, 0x65, 0x34, 0x98, 0xbe, 0xa0, 0x22, 0xe3, 0x36, 0x5a, 0x3, 0xe5, 0x75, 0x25, 0xba, 0x65, 0x96, 0x53, 0x76, 0x24, 0x4f, 0xff, 0x10, 0x73, 0xe, 0xd9, 0x7a, 0x73, 0xb7, 0x53, 0x1, 0x91} }, - { (uint64_t)6000000000000ull, {0xdb, 0x1c, 0x7c, 0xf6, 0x8, 0x91, 0xf9, 0x65, 0xeb, 0xa9, 0xc6, 0x2, 0x24, 00, 0x63, 0xe, 00, 0x47, 0x95, 0x34, 0xe6, 0xf5, 0xb5, 0x33, 0xdc, 0xfc, 0x83, 0x19, 0x38, 0x52, 0x2c, 0x78} }, - { (uint64_t)7000000000000ull, {0x59, 0xa0, 0x3a, 0x31, 0x53, 0xa9, 0x94, 0xd7, 0x23, 0x27, 0xe4, 0xd9, 0x24, 0x21, 0xd3, 0xe3, 0x29, 0x1b, 0x1f, 0xa1, 0xb2, 0x40, 0xde, 0x44, 0xb9, 0x2d, 0x7f, 0x62, 0xec, 0x1, 0x28, 0xf1} }, - { (uint64_t)8000000000000ull, {0xb2, 0x80, 0xb9, 0x3b, 0x1e, 0x43, 0x88, 00, 0x73, 0xea, 0x4a, 0xa0, 0xef, 0x11, 0x4, 0xf8, 0x24, 0xbd, 0x12, 0x7a, 0x4a, 0x3d, 0xa2, 0x13, 0x92, 0x65, 0xf, 0xe8, 0xc6, 0x55, 0xb6, 0xc5} }, - { (uint64_t)9000000000000ull, {0xda, 0xf0, 0xd3, 0xe9, 0x32, 0x17, 0xd8, 0xe9, 0x5a, 0xbf, 0xdd, 0xf1, 0x3b, 0x7f, 0xd4, 0x8e, 0x34, 0x47, 0xad, 0x9, 0x23, 0x26, 0xb8, 0x99, 0xed, 0x58, 0x1f, 0xd5, 0xf8, 0x6, 0xc5, 0x6} }, - { (uint64_t)10000000000000ull, {0x16, 0x3d, 0xd6, 0x82, 0xec, 0x97, 0x7c, 0xdd, 0xa5, 0x95, 0x31, 0xda, 0x3f, 0xfa, 0x72, 0x99, 0x8a, 0x6f, 0x88, 0x37, 0xab, 0xad, 0xc6, 0x36, 0xaa, 0xed, 0xc8, 0xbe, 0x19, 0xb2, 0xd7, 0xc7} }, - { (uint64_t)20000000000000ull, {0x2, 0xfa, 0x35, 0x3a, 0xa8, 0x4e, 0xa8, 0xc4, 0x4c, 0x80, 0x23, 0x6, 0x5d, 0x79, 0x41, 0x60, 0x6b, 0x1f, 0xa5, 0xc2, 0x64, 0xdc, 0xcf, 0x46, 0xdc, 0x64, 0x94, 0xeb, 0xe9, 0x60, 0x6f, 0x20} }, - { (uint64_t)30000000000000ull, {0x87, 0x5, 0xd, 0xab, 0xf5, 0xb2, 0x3e, 0x8b, 0x79, 0x81, 0x3f, 0x4e, 0xd7, 0x6a, 0xa4, 0xad, 0xd2, 0x25, 0xdd, 0x2a, 0x50, 0x89, 0xaf, 0x6, 0x7d, 0xa7, 0x7c, 0xcb, 0x6e, 0xc5, 0x59, 0x46} }, - { (uint64_t)40000000000000ull, {0xaa, 0xe6, 0xb2, 0xc8, 0xa2, 0x9e, 0x4d, 0xbc, 0x63, 0x76, 0xc1, 0x72, 0x5, 0xfb, 0x2, 0x85, 0xe7, 0xd7, 0xd3, 0x25, 0x32, 0x3c, 0xd5, 0x26, 0xf, 0x98, 0xad, 0xff, 0xf7, 0xd4, 0xd4, 0xfb} }, - { (uint64_t)50000000000000ull, {0x9d, 0x79, 0x28, 0x82, 0x12, 0xa1, 0xe2, 0x3c, 0x9, 0x9f, 0xb2, 0xd8, 0xf0, 0xd0, 0xdb, 0xd3, 0xc2, 0xec, 0xd7, 0x58, 0xb9, 0xe6, 0xb5, 0xb4, 0xf2, 0x90, 0x60, 0x7, 0x9f, 0x19, 0x66, 0x9f} }, - { (uint64_t)60000000000000ull, {0x18, 0x90, 0x10, 0x6f, 0x1b, 0x97, 0xbc, 0x2d, 0xa, 0xe3, 0x96, 0xe5, 0xe5, 0x5e, 0xbf, 0xcc, 0x8e, 0xf6, 0x91, 0x7f, 0xb1, 0x96, 0xcb, 0x2b, 0x1e, 0x80, 0x25, 0x5d, 0x54, 0xb6, 0x87, 0x10} }, - { (uint64_t)70000000000000ull, {0x57, 0xd3, 0x4e, 0xf7, 0x54, 0x3b, 0xe4, 0x7b, 0x7b, 0xf4, 0x97, 0xce, 0x4a, 0x17, 0x6e, 0x78, 0xc6, 0xd6, 0x5c, 0xd3, 0x27, 0xf6, 0x4b, 0xa7, 0x5c, 0x27, 0xd1, 0x57, 0xb3, 0x37, 0x12, 0x5d} }, - { (uint64_t)80000000000000ull, {0x5e, 0xcb, 0x10, 0x15, 0x4b, 0x96, 0xca, 0xb5, 0x5e, 0x9, 0x46, 0x83, 0xf8, 0xdb, 0xff, 0x7f, 0x56, 0x63, 0x5f, 0xa6, 0x64, 0x97, 0xee, 0x9e, 0x24, 0xe, 0x83, 0x63, 0x7c, 0x7c, 0x87, 0x72} }, - { (uint64_t)90000000000000ull, {0x42, 0x32, 0x69, 0x98, 0x51, 0x30, 0xf1, 0x66, 0x51, 0x6a, 0x5b, 0xa8, 0x61, 0x9, 0x6d, 0x72, 0xec, 0xcc, 0x67, 0xad, 0xab, 0xa4, 0x5e, 0xb3, 0x73, 0x9a, 0xe, 0xbc, 0x61, 0xa3, 0x20, 0xae} }, - { (uint64_t)100000000000000ull, {0xa8, 0xd1, 0x60, 0x95, 0x91, 0x49, 0x8f, 0xa7, 0xc2, 0x94, 0x27, 0xad, 0x89, 0x31, 0xaf, 0x36, 0xc5, 0x2d, 0xc9, 0x7b, 0x4a, 0x11, 0xe7, 0x47, 0xa9, 0x56, 0xc2, 0x8c, 0x42, 0x54, 0xcf, 0xd4} }, - { (uint64_t)200000000000000ull, {0x23, 0x14, 0x49, 00, 0xa8, 0x66, 0xe8, 0xc1, 0xbf, 0x40, 0x98, 0xda, 0xa9, 0x48, 0xb9, 0x86, 0xf3, 0x84, 0xe, 0x5a, 0x7d, 0x21, 0x5e, 0xf0, 0xd5, 0x64, 0xef, 0xd8, 0xbe, 0xc6, 0x83, 0x15} }, - { (uint64_t)300000000000000ull, {0x6a, 0x51, 0x47, 0x3c, 0x86, 0xed, 0xad, 0x53, 0x51, 0x4b, 0x3f, 0x95, 0x97, 0xed, 0x21, 0xae, 00, 0x81, 0x51, 0xa0, 0x9e, 0x43, 0xad, 0xdd, 0x45, 0xd1, 0x74, 0x63, 0xc5, 0x34, 0x3, 0x97} }, - { (uint64_t)400000000000000ull, {0x8, 0xbd, 0xd4, 0xc3, 0xe4, 0x53, 0x1b, 0x29, 0x7a, 0x70, 00, 0x1e, 0xb8, 0xa4, 0xf1, 0x98, 0xdc, 0x3b, 0xd4, 0xf1, 0xf5, 0x60, 0x9a, 0xda, 0x98, 0xf6, 0xd9, 0x5f, 0x9a, 0x1a, 0x30, 0x2e} }, - { (uint64_t)500000000000000ull, {0x97, 0x55, 0x70, 0xea, 0x12, 0xde, 0x5a, 0xf5, 0xc5, 0x36, 0xbd, 0xb6, 0x83, 0x54, 0xfb, 0xc8, 0x32, 0x21, 0x50, 0xfc, 0x56, 0x83, 0x7c, 0x4b, 0x78, 0xa9, 0x85, 0x76, 0x5d, 0x2a, 0x70, 0x99} }, - { (uint64_t)600000000000000ull, {0xa7, 0xa6, 0x39, 0x93, 0x41, 0xcb, 0x4d, 0x67, 0x76, 0xcd, 0x94, 0xd, 0x1d, 0x6a, 0xb0, 0xac, 0xa, 0xbf, 0x56, 0x93, 0x6a, 0x35, 0x31, 0xdf, 0xe9, 0x6c, 0x23, 0x69, 0x97, 0x8e, 0x49, 0xfa} }, - { (uint64_t)700000000000000ull, {0x55, 0x9, 0x3e, 0x5e, 0xeb, 0xca, 0x3, 0x88, 0x48, 0xdc, 0x99, 0x7e, 0x31, 0x95, 0xec, 0xc5, 0x8f, 0xb4, 0xa5, 0x71, 0xb9, 0x52, 0x56, 0xc0, 0xff, 0x49, 0xbe, 0xd0, 0xf1, 0x65, 0x22, 0xbd} }, - { (uint64_t)800000000000000ull, {0xbb, 0xc6, 0x18, 0x2, 0x24, 0xaf, 0xd3, 0x38, 0xa6, 0xf4, 0xa0, 0x6b, 0x11, 0x98, 0x40, 0x68, 0xeb, 0x36, 0x35, 0xe7, 0xe5, 0x47, 0x66, 0x69, 0x78, 0x83, 0xaf, 0xbd, 0xce, 0xad, 0x2f, 0x31} }, - { (uint64_t)900000000000000ull, {0x61, 0x3a, 0xa1, 0x2c, 0xc0, 0xa1, 0x9b, 0xc8, 0x43, 0x63, 0x50, 0xbb, 0xc0, 0xf6, 0x16, 0x32, 0x6e, 0x64, 0x85, 0x83, 0x33, 0x4a, 0x32, 0x65, 0x16, 0x29, 0xe9, 0x5, 0xc5, 0x20, 0x62, 0x69} }, - { (uint64_t)1000000000000000ull, {0x52, 0xdd, 0xf8, 0x81, 0x13, 0xa0, 0xfc, 0xf2, 0x12, 0x90, 0x95, 0xc6, 0x18, 0x91, 0xbe, 0x88, 0x5c, 0x9, 0x30, 0x8, 0xeb, 0xc4, 0x65, 0xc, 0xb0, 0xee, 0xa5, 0x60, 0xcd, 0x4d, 0x75, 0x1b} }, - { (uint64_t)2000000000000000ull, {0x75, 0xbd, 0xfc, 0x35, 0xa6, 0xdf, 0x76, 0xe5, 0x98, 0x8e, 0xd9, 0xe3, 0x10, 0xa5, 0x89, 0x16, 0xae, 0xf0, 0xc5, 0xf0, 0x5b, 0x89, 0x22, 0xea, 0xae, 0x2c, 0xf9, 0x8f, 0x58, 0x42, 0x3c, 0xe3} }, - { (uint64_t)3000000000000000ull, {0x88, 0x98, 0x93, 0xe8, 0x7d, 0x56, 0x9f, 0x14, 0xb2, 0x48, 0xd1, 0xed, 0x93, 0xe8, 0xce, 0x60, 0xbb, 0xe3, 0x73, 0x69, 0xb0, 0xd6, 0xc7, 0xa1, 0x86, 0x89, 0x33, 0xd3, 0xc3, 0xda, 0x9a, 0x72} }, - { (uint64_t)4000000000000000ull, {0x88, 0x3e, 0xf3, 0x4b, 0xa2, 0xc1, 0x91, 0xf4, 0x9d, 0x3c, 0xc6, 0xad, 0xa0, 0xaf, 0xf1, 0xcf, 0xb1, 0x77, 0xbd, 0x9e, 0xd4, 0xb3, 0xa5, 0x37, 0x84, 0xb7, 0xf1, 0x62, 0x9b, 0xed, 0x17, 0x41} }, - { (uint64_t)5000000000000000ull, {0xa2, 0x90, 0x7c, 0x39, 0x84, 0xb1, 0x4a, 0xb1, 0xf4, 0xda, 0x58, 0xc2, 0xc8, 0x2d, 0x6b, 0x24, 0xf1, 0x29, 0x49, 0x9, 0x75, 0xfc, 0x4a, 0x33, 0x3d, 0x25, 0xa1, 0xf9, 0x2b, 0xc4, 0x32, 0xb6} }, - { (uint64_t)6000000000000000ull, {0xa0, 0x7d, 0x9f, 0x18, 0x95, 0x1f, 0xf2, 0x32, 0xcf, 0x4e, 0xc0, 0xee, 0x2f, 0xbc, 0xc3, 0xe1, 0x1b, 0x2c, 0xaf, 0xc9, 0x57, 0x65, 0x82, 0x10, 0x38, 0x1e, 0x3e, 0xe4, 0xed, 0xec, 0x2e, 0x7a} }, - { (uint64_t)7000000000000000ull, {0x66, 0x80, 0x21, 0xd5, 0xde, 0x8c, 0xa4, 0xc1, 0x8f, 0x5a, 0x74, 0xf2, 0x78, 0x69, 0xc4, 0xd6, 0xd4, 0x93, 0xa3, 0x30, 0x39, 0x3c, 0xf0, 0x26, 0x41, 0xff, 0xa8, 0x56, 0x7b, 0xa5, 0x36, 0x20} }, - { (uint64_t)8000000000000000ull, {0xe0, 0x48, 0x7a, 0xc4, 0x5a, 0x82, 0x59, 0xe3, 0xe5, 0xf2, 0xd9, 0xb8, 0xf6, 0xb8, 0xfa, 0x26, 0x9a, 0x63, 0x49, 0x71, 0xa2, 0xf7, 0xc2, 0x1a, 0x54, 0x17, 0x76, 0x81, 0xeb, 0x2, 0xbd, 0x4a} }, - { (uint64_t)9000000000000000ull, {0x98, 0x92, 0x6a, 0x3a, 0xf0, 0x5b, 0xf4, 0xa9, 0x8d, 0xf9, 0xf6, 0x4a, 0xe7, 0xb9, 0xda, 0x45, 0xa7, 0x6, 0xc3, 0xf8, 0x39, 0x5e, 0x47, 0x1f, 0x96, 0xed, 0x3c, 0x6, 0x6, 0xbe, 0xbb, 0x71} }, - { (uint64_t)10000000000000000ull, {0x80, 0xad, 0xb7, 0xd, 0x46, 0xf6, 0x3a, 0x75, 0x64, 0xa3, 0xf6, 0x71, 0xd9, 0xba, 0x95, 0x71, 0xb7, 0xf7, 0x95, 0xa9, 0x63, 0x38, 0x2a, 0x4d, 0x9f, 0xaf, 0x2d, 0x54, 0xf6, 0xc6, 0x84, 0x29} }, - { (uint64_t)20000000000000000ull, {0xae, 0xbd, 0x97, 0x42, 0x1f, 0x3f, 0xca, 0xe8, 0x95, 0x18, 0x60, 0xe6, 0xd9, 0xd1, 0xf3, 0xec, 0x59, 0x73, 0xa2, 0xf7, 0x66, 0x88, 0x4b, 0xfe, 0x17, 0x50, 0x79, 0x51, 0xe4, 0x62, 0xc6, 0x63} }, - { (uint64_t)30000000000000000ull, {0x61, 0x2, 0x6c, 0x84, 0x2a, 0x6a, 0x22, 0x25, 0x74, 0x6b, 0x19, 0x6b, 0x56, 0x89, 0xe1, 0x18, 0xf5, 0x41, 0x34, 0x15, 0x98, 0x1d, 0x7, 0x73, 0x62, 0xb2, 0xe7, 0xb9, 0xac, 0xa5, 0x28, 0x16} }, - { (uint64_t)40000000000000000ull, {0x52, 0x54, 0xb5, 0x78, 0xe8, 0x57, 0x9a, 0x27, 0x3b, 0x89, 0x8e, 0x65, 0x9d, 0xd3, 0xe1, 0xa1, 0xcf, 0xba, 0x12, 0x47, 0x26, 0x64, 0xbd, 0x4e, 0x7f, 0x9a, 0x13, 0xb1, 0xfc, 0xee, 0x2, 0x93} }, - { (uint64_t)50000000000000000ull, {0x7b, 0x2a, 0xb, 00, 0xcf, 0xdc, 0xa9, 0x51, 0x46, 0xcf, 0x80, 0x95, 0xdd, 0x2b, 0x82, 0x90, 0x91, 0xb0, 0xf2, 0xd5, 0xbb, 0xc, 0x33, 0x82, 0x2d, 0x8b, 0x43, 0x42, 0x69, 0xcd, 0x2a, 0x42} }, - { (uint64_t)60000000000000000ull, {0x21, 0x57, 0x4f, 0xed, 0x15, 0x1a, 0x2f, 0x9f, 0x64, 0xa4, 0x5b, 0xe2, 0x8a, 0x3a, 0xf5, 0x88, 0xe9, 0xf2, 0xd1, 0x71, 0x35, 0xa3, 0x53, 0x7f, 0x7, 0xfd, 0x6a, 0xef, 0xa2, 0x9f, 0x2, 0xaf} }, - { (uint64_t)70000000000000000ull, {0x1a, 0xf2, 0x41, 0xe1, 0x38, 0x27, 0x98, 0x29, 0xac, 0x6a, 0xe6, 0x2f, 0xf, 0x33, 0x20, 0x4b, 0xb2, 0x8a, 0xfd, 0x6, 0x5c, 0x42, 0x59, 0x3b, 0xdc, 0x79, 0x14, 0x85, 0x97, 0x5b, 0x26, 0x95} }, - { (uint64_t)80000000000000000ull, {0xa8, 0xc8, 0xb8, 0x7b, 0x51, 0x2d, 0xef, 0x9b, 0x5e, 0x50, 0xe, 0xb4, 0x98, 0xaf, 0x86, 0xaa, 0xd2, 0x46, 0x4a, 0xea, 0xe7, 0x6d, 0xb1, 0xf6, 0x5d, 0x23, 0x26, 0xce, 0x90, 0x26, 0xec, 0x69} }, - { (uint64_t)90000000000000000ull, {0x3d, 0x78, 0x73, 0x63, 0x95, 0xf1, 0xd7, 0xde, 0x8e, 0x16, 0xc0, 0xb5, 0xa9, 0x9f, 0x4d, 0xc4, 0xeb, 0x8f, 0x22, 0xac, 0xc1, 0x5b, 0x21, 0x42, 0x44, 0x1d, 0xbd, 0x8d, 0x2c, 0x31, 0xb9, 0xce} }, - { (uint64_t)100000000000000000ull, {0x27, 0x27, 0xd4, 0x93, 0x2f, 0x98, 0x39, 0xe4, 0x3b, 0x6b, 0xf5, 0xfb, 0x29, 0xa3, 0xbe, 0x4c, 0x9, 0xb, 0x6e, 0xb9, 0x31, 00, 0xbb, 0x92, 0x58, 0x1a, 0xdb, 0x8d, 0xd2, 0xb6, 0x61, 0x54} }, - { (uint64_t)200000000000000000ull, {0xae, 0x96, 0x78, 0x2e, 0xf2, 0xc4, 0xdf, 0x7d, 0x2e, 0x4, 0xcc, 0xf9, 0xef, 0x76, 0x23, 0x7f, 0x17, 0xc, 0x97, 0x3, 0xb4, 0x92, 0xc0, 0x78, 0x52, 0x6e, 0xb1, 0xf6, 0x85, 0x3d, 0xb1, 0x33} }, - { (uint64_t)300000000000000000ull, {0x17, 0x43, 0xfe, 0xab, 0x12, 0xad, 0xe5, 0xfe, 0x12, 0x53, 0x22, 0x27, 0x2f, 0xd1, 0x40, 0x6b, 0x74, 0xe8, 0x19, 0x70, 0x32, 0x68, 0x46, 0x22, 0xee, 0x79, 0xab, 0xcd, 0x94, 0x93, 0x66, 0x4c} }, - { (uint64_t)400000000000000000ull, {0x7, 0x9b, 0xf2, 0xa9, 0x6e, 0x16, 0x6e, 0xf9, 0xe6, 0xb2, 0x23, 0x1d, 0xb9, 0x85, 0x8b, 0x99, 0x98, 0x7f, 0x49, 0x33, 0x87, 0xde, 0xeb, 0xd5, 0x17, 0x48, 0x54, 0x9a, 0xd, 0xf7, 0xdc, 0x44} }, - { (uint64_t)500000000000000000ull, {0xca, 0xba, 0x97, 0x98, 0x51, 0x6d, 0xad, 0x3, 0x38, 0xd0, 0x6e, 0x10, 0x6d, 0x76, 0xa2, 0x1, 0x93, 0x7a, 0xce, 0x4c, 0x91, 0x53, 0x9e, 0x61, 0x7d, 0x89, 0x28, 0x73, 0x6, 0xa3, 0x92, 0xb1} }, - { (uint64_t)600000000000000000ull, {0x6b, 0x8, 0x7f, 0x48, 0xb3, 0xd7, 0xaa, 0xc9, 0x57, 0xc4, 0x52, 0xe5, 0x1a, 0x18, 0xd7, 0x26, 0xb, 0xf8, 0xc8, 0x56, 0xc4, 0xc7, 0x1e, 0x48, 0xf6, 0x49, 0xae, 00, 0x4a, 0xf6, 0x8f, 0x13} }, - { (uint64_t)700000000000000000ull, {0x9e, 0xed, 0x8b, 0x23, 0x1f, 0x79, 0x4c, 0x46, 0x5c, 0xbe, 0x88, 0x40, 0xd0, 0xf1, 0x6f, 0x7b, 0x9f, 0x9c, 0x6e, 0xb4, 0x9c, 0x20, 0x7d, 0xe9, 0xd8, 0x55, 0x11, 0x83, 0xd0, 0xc7, 0x6e, 0x43} }, - { (uint64_t)800000000000000000ull, {0x58, 0x4a, 0x78, 0x93, 0x13, 0x7e, 0xbd, 0x2, 0x8b, 0xa7, 0x59, 0x82, 0xc3, 0x39, 0xb7, 0x66, 0xaa, 0xda, 0xad, 0xf9, 0x14, 0x50, 0xf9, 0x40, 0x7d, 0x2a, 0x97, 0xd7, 0xf6, 0xb1, 0x93, 0x5e} }, - { (uint64_t)900000000000000000ull, {0x7, 0xce, 0x54, 0xb1, 0x18, 0x26, 0xa1, 0x75, 0x23, 0x13, 0x55, 0x1a, 00, 0x20, 0xfd, 0x79, 0x8a, 00, 0x9e, 0x20, 0xcd, 0xb2, 0x40, 0x1d, 0x52, 0x51, 0xc1, 0x55, 0x8e, 0xea, 0xd2, 0x6c} }, - { (uint64_t)1000000000000000000ull, {0x39, 0x80, 0x7f, 0x3d, 0xce, 0xb0, 0xa6, 0xfe, 0x34, 0xa7, 0xa1, 0xed, 0xc6, 0x9b, 0x78, 0xff, 0xbe, 0xd5, 0xa7, 0x8c, 0x6c, 0x87, 0x5d, 0xda, 0x96, 0x69, 0xdb, 0xb2, 0x95, 0x70, 0xf0, 0xf4} }, - { (uint64_t)2000000000000000000ull, {0xda, 0x74, 00, 0x86, 0xf1, 0x5c, 0xe8, 0x21, 0xe9, 0xd, 0x50, 0xaf, 0xcf, 0x80, 0x9c, 0x7e, 0x18, 0x51, 0x90, 0x1b, 0xa3, 0x5f, 0x9f, 0x63, 0x78, 0xd6, 0x40, 0x7c, 0xb9, 0xc7, 0xa2, 0x75} }, - { (uint64_t)3000000000000000000ull, {0x7, 0xa1, 0x75, 0x63, 0xae, 0xf5, 0xcf, 0xd0, 0x36, 0xfa, 0x64, 0xd4, 0xb1, 0x97, 0xa9, 0x51, 0xc0, 0xd2, 0x87, 0x2b, 0xd, 0xb6, 0xf9, 0xbe, 0x47, 0xe6, 0x7c, 0xa6, 0xb5, 0x35, 0xe2, 0x6e} }, - { (uint64_t)4000000000000000000ull, {0xe3, 0x49, 0xf7, 0xeb, 0xe5, 0x11, 0x39, 0xfe, 0xd5, 0x69, 0x40, 0x37, 0xd1, 0x14, 0xb7, 0xbd, 0x45, 0xdd, 0xa, 0x6a, 0xf0, 0x4b, 0x62, 0xec, 0xa4, 0xd8, 0xcd, 0x55, 0x2a, 0x14, 0xe3, 0xfb} }, - { (uint64_t)5000000000000000000ull, {0x8d, 0x59, 0x7e, 0xa9, 0xf5, 0x79, 0x9a, 0x4d, 0x15, 0x3d, 0x82, 0xd6, 0xf7, 0xbe, 0xa0, 0x2e, 0x52, 0x40, 0xa2, 0xc8, 0x9b, 0x4, 0x1e, 0x6, 0x2f, 0x37, 0xbc, 0x7b, 0x82, 0xa0, 0xac, 0x55} }, - { (uint64_t)6000000000000000000ull, {0xa3, 0x43, 0xa7, 0xe1, 0x14, 0x4d, 0x33, 0x50, 0xf, 0x3e, 0xfd, 0x38, 0x15, 0x82, 0xdd, 0xc5, 0xd0, 0x18, 0x3e, 0x5d, 0xcf, 0x8a, 0xfa, 0x64, 0xbb, 0x67, 0x6c, 0x97, 0x3e, 0x3d, 0x1a, 0xb1} }, - { (uint64_t)7000000000000000000ull, {0x89, 0xe9, 0x3e, 0xe9, 0xf2, 0x4d, 0x72, 0x61, 0xe5, 0x44, 0xca, 0x8f, 0x9, 0xa7, 0x40, 0x4e, 0xe3, 0xa9, 0xe, 0xe2, 0x50, 0x7d, 0xda, 0xcf, 0x41, 0x2a, 0x58, 0xc, 0x9, 0x65, 0x1c, 0x53} }, - { (uint64_t)8000000000000000000ull, {0xc5, 0x94, 0x10, 0x81, 0x54, 0x69, 0xf4, 0x59, 0xd1, 0x5a, 0x6f, 0xe3, 0xf2, 0xa1, 0x1b, 0xa6, 0x31, 0x12, 0xfa, 0xaa, 0xc5, 0x3d, 0xbc, 0x52, 0x5d, 0x3c, 0xfa, 0xb1, 0xfa, 0x9c, 0x3d, 0xdb} }, - { (uint64_t)9000000000000000000ull, {0x9d, 0xe7, 0xcb, 0xb, 0x8d, 0x7b, 0xac, 0x47, 0xff, 0xd3, 0x93, 0x1b, 0xcd, 0x82, 0xcd, 0xd5, 0x35, 0xc, 0x29, 0x34, 0xb1, 0x6e, 0xb, 0x64, 0x32, 0xab, 0xf7, 0xcb, 0x4b, 0x5c, 0x37, 0x6d} }, - { (uint64_t)10000000000000000000ull, {0x65, 0x8d, 0x1, 0x37, 0x6d, 0x18, 0x63, 0xe7, 0x7b, 0x9, 0x6f, 0x98, 0xe6, 0xe5, 0x13, 0xc2, 0x4, 0x10, 0xf5, 0xc7, 0xfb, 0x18, 0xa6, 0xe5, 0x9a, 0x52, 0x66, 0x84, 0x5c, 0xd9, 0xb1, 0xe3} }, + { (uint64_t)0ull, {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}} }, + { (uint64_t)1ull, {{0x17, 0x38, 0xeb, 0x7a, 0x67, 0x7c, 0x61, 0x49, 0x22, 0x8a, 0x2b, 0xea, 0xa2, 0x1b, 0xea, 0x9e, 0x33, 0x70, 0x80, 0x2d, 0x72, 0xa3, 0xee, 0xc7, 0x90, 0x11, 0x95, 0x80, 0xe0, 0x2b, 0xd5, 0x22}} }, + { (uint64_t)2ull, {{0x76, 0x24, 0x84, 0x63, 0xa, 0x6, 0x17, 0x17, 0x8d, 0xe, 0x33, 0xf3, 0x2e, 0xe, 0x11, 0x3e, 0xa8, 0x46, 0x86, 0x9d, 0x46, 0x4b, 0xb, 0x6f, 0xf1, 0x3b, 0x29, 0x97, 0x4, 0x9c, 0xda, 0x7d}} }, + { (uint64_t)3ull, {{0xcf, 0xf7, 0x7b, 0x56, 0x62, 0x1c, 0x4f, 0xef, 0x74, 0xcf, 0x37, 0xc1, 0x78, 0xd4, 0xb5, 0x8a, 0xf4, 0xad, 0x8c, 0xd4, 0x35, 0xfc, 0xb9, 0x62, 0x76, 0xbc, 0x15, 0x9c, 0x7c, 0x6a, 0x28, 0x8c}} }, + { (uint64_t)4ull, {{0x9a, 0xb8, 0x6c, 0x31, 0xf4, 0x22, 0xd8, 0x21, 0xb5, 0x22, 0x57, 0x30, 0xd1, 0xbf, 0x73, 0xa, 0x9b, 0x91, 0xd2, 0xee, 0xe3, 0x14, 0xb8, 0x4e, 0xbd, 0x4b, 0x93, 0xa6, 0x81, 0x61, 0x82, 0x66}} }, + { (uint64_t)5ull, {{0x32, 0xee, 0x2f, 0x65, 0x9a, 0xf6, 0x38, 0x58, 0xc2, 0xf7, 0xdc, 0x11, 0x1b, 0x3b, 0xb8, 0xfe, 0xc0, 0x2c, 0xac, 0x42, 0x38, 0x3b, 0xb7, 0x36, 0xde, 0x1, 0x8, 0x6f, 0x38, 0xf0, 0x12, 0x3c}} }, + { (uint64_t)6ull, {{0x47, 0x26, 0x2b, 0x1e, 0xa6, 0x43, 0x1, 0x6e, 0x38, 0x24, 0x17, 0x53, 0xa4, 0xfb, 0x39, 0x92, 0x9e, 0x31, 0xea, 0x9b, 0xd3, 0x41, 0x1a, 0xb1, 0x7f, 0x16, 0x6e, 0x61, 0xf6, 0xc, 0xe5, 0xa7}} }, + { (uint64_t)7ull, {{0xc6, 0x32, 0x93, 0x68, 0x79, 0x9a, 0xd, 0xed, 0x4c, 0x20, 0x25, 0x6b, 0xff, 0xe6, 0x45, 0x47, 0xf1, 0x7b, 0xc4, 0x23, 0x95, 0x4, 0xbe, 0x82, 0x4d, 0xff, 0x8a, 0x2b, 0xe1, 0xaf, 0xe3, 0xcd}} }, + { (uint64_t)8ull, {{0xd5, 0xf1, 0x50, 0x74, 0x33, 0x46, 0x19, 0xf, 0x84, 0x2b, 0x6, 0xb8, 0xfa, 0xe1, 0x20, 0xeb, 0x85, 0x24, 0x7e, 0x9f, 0x6d, 0xec, 0x88, 0xff, 0xa2, 0x23, 0xbf, 0x69, 0x94, 0xe9, 0xc8, 0xc2}} }, + { (uint64_t)9ull, {{0x56, 00, 0x23, 0x32, 0x9e, 0xc0, 0xfa, 0xf3, 0x3b, 0x5e, 0x3a, 0x5c, 0xb4, 0xea, 0xef, 0xee, 0x38, 0xf8, 0x96, 0x1c, 0x88, 0xb6, 0x6a, 0x2f, 0x19, 0xd4, 0x59, 0x51, 0x96, 0x9c, 0x6d, 0x1f}} }, + { (uint64_t)10ull, {{0x3, 0x80, 0xdc, 0x24, 0xcc, 0x97, 0xcc, 0xe6, 0x58, 0xc3, 0xa9, 0x47, 0xc5, 0x10, 0x25, 0xde, 0x1a, 0x69, 0x80, 0x3b, 0xdb, 0x50, 0x5, 0xe3, 0xb7, 0xdd, 0xa9, 0xd, 0x68, 0x59, 0xb0, 0x1c}} }, + { (uint64_t)20ull, {{0x9, 0x3, 0xf6, 0x2e, 0x97, 0x76, 0x47, 0x58, 0xfe, 0xf8, 0x9e, 0x5b, 0xec, 0x29, 0xef, 0x4f, 0xc5, 0xe6, 0x45, 0x4b, 0x2d, 0x47, 0x44, 0x47, 0x36, 0x4, 0x4c, 0x25, 0x2e, 0xe2, 0x8e, 0xba}} }, + { (uint64_t)30ull, {{0xa2, 0x8b, 0x89, 0xe0, 0xb, 0xed, 0x62, 0x31, 0x68, 0x5b, 0xf9, 0x74, 0x36, 0xf2, 0xba, 0x51, 0xa2, 0x51, 0x55, 0x7f, 0x8d, 0x17, 0xa, 0x78, 0xe3, 0x12, 0xd6, 0x24, 0xbf, 0x60, 0xff, 0xfe}} }, + { (uint64_t)40ull, {{0xb5, 0xc6, 0x95, 0x55, 0x6a, 0x28, 0x47, 0xb2, 0xe, 0x1c, 0xbb, 0x26, 0xe6, 0xa9, 0xc6, 0x8a, 0x61, 0xc5, 0x50, 0xce, 0xb7, 0xc3, 0x4, 0xfe, 0x92, 0x28, 0x3d, 0x29, 0xa9, 0xb2, 0x43, 0xcb}} }, + { (uint64_t)50ull, {{0x12, 0x8e, 0xc6, 0xcd, 0xc0, 0x6b, 0x43, 0xc5, 0xd0, 0x9c, 0x3f, 0x65, 0x2a, 0xe3, 0x44, 0x7f, 0x9b, 0x3f, 0x2c, 0x30, 0x91, 0x2d, 0xf0, 0x80, 0x37, 00, 0x85, 0xbc, 0xc, 0x9, 0xef, 0x78}} }, + { (uint64_t)60ull, {{0x1f, 0x9f, 0x40, 0x3a, 0xae, 0xa7, 0x16, 0xfb, 0xe2, 0x98, 0xa8, 0x14, 0xf1, 0xee, 0xbc, 0x1b, 0x73, 0x16, 0x8c, 0x37, 0xfa, 0xe3, 0x16, 0xeb, 0x65, 0x5, 0x81, 0x6f, 0xc2, 0x20, 0xeb, 0xfb}} }, + { (uint64_t)70ull, {{0x10, 0xa2, 0x38, 0xc5, 0xe4, 0x8e, 0x4b, 0x93, 0x99, 0xdb, 0xa6, 0xcb, 0xd9, 0x8e, 0x63, 0x54, 0x41, 0x59, 0xe9, 0x8c, 0x93, 0x5a, 0xc0, 0x60, 0x3d, 0x72, 0xde, 0xf, 0xff, 0x31, 0x53, 0xbb}} }, + { (uint64_t)80ull, {{0x75, 0xab, 0x78, 0xc7, 0x28, 0x1f, 0x69, 0x28, 0xf0, 0x94, 0x86, 0x5, 0x7a, 0x63, 0x64, 0x18, 0x27, 0xc5, 0x74, 0x84, 0xe3, 0xe9, 0x9a, 0x39, 0xf3, 0x12, 0xa4, 0x3a, 0x51, 0x9b, 0xda, 0x8}} }, + { (uint64_t)90ull, {{0xe9, 0x56, 0x7b, 0xa7, 0x88, 0xb8, 0x5b, 0x82, 0xc8, 0x65, 0x7a, 0x15, 0xa5, 0x48, 0x99, 0x5c, 0xf6, 0xb0, 0xbd, 0xd1, 0xc6, 0x2a, 0xda, 0x77, 0x55, 0xf2, 0x32, 0x3a, 0xd8, 0xa4, 0x8, 0x51}} }, + { (uint64_t)100ull, {{0xb6, 0x17, 0x36, 0xd5, 0xf2, 0x8d, 0xef, 0x28, 0x61, 0x6a, 0xfc, 0x47, 0x93, 0xe9, 0x9b, 0x27, 0xcd, 0x3e, 0x89, 0xfb, 0x91, 0xc1, 0x13, 0xd4, 0x30, 0x73, 0x65, 0xfb, 0x75, 0xde, 0xdf, 0x88}} }, + { (uint64_t)200ull, {{0x71, 0x3, 0xeb, 0x72, 0x19, 0x28, 0xd7, 0x91, 0x99, 0x87, 0xf3, 0x50, 0xca, 0xa5, 0x7a, 0xe7, 0xb0, 0x81, 0x57, 0x15, 0x3b, 0x4c, 0x43, 0xd, 0x3e, 0xde, 0xc0, 0xc2, 0x3, 0x7, 0x97, 0x44}} }, + { (uint64_t)300ull, {{0x24, 0x40, 0x9e, 0x92, 0x2e, 0xce, 0xd1, 0xa0, 0x5e, 0x4e, 0xac, 0xa3, 0xdf, 0x91, 0x19, 0xc3, 0x8a, 0x92, 0x2e, 0xb, 0x66, 0xd0, 0x2d, 0x9d, 0xd2, 0xfb, 0x1d, 0xcc, 0x20, 0xb9, 0xaf, 0xc7}} }, + { (uint64_t)400ull, {{0xa7, 0x72, 0x9f, 0xa9, 0x32, 0x81, 0x82, 0x99, 0x34, 0x11, 0x5d, 0x47, 0x5a, 0x67, 0x86, 0xa, 0x14, 0x12, 0xc5, 0xe5, 0x95, 0x12, 0x20, 0xd9, 0x60, 0xc2, 0x41, 0xa0, 0x19, 0x1a, 0x9e, 0x65}} }, + { (uint64_t)500ull, {{0x2e, 0x53, 0xc, 0x6, 0x1c, 0x6d, 0x9e, 0x97, 0xab, 0xaf, 0x46, 0x8c, 0x32, 0xb0, 0xad, 0xa7, 0x49, 0x22, 0x57, 0x72, 0xfc, 0xd1, 0x17, 0x41, 0xcb, 0x5c, 0x3, 0x5c, 0xdd, 0x26, 0x14, 0xe}} }, + { (uint64_t)600ull, {{0xa5, 0xb, 0x91, 0x9, 0x9d, 0xf1, 0xb1, 0x69, 0x4f, 0x30, 0xb5, 0x8f, 0xe6, 0x77, 0x68, 0x50, 0xdb, 0xdb, 0xf4, 0x6c, 0xed, 0x99, 0x7f, 0x52, 0x62, 0xa8, 0x51, 0x59, 0x40, 0x74, 0xa5, 0x9d}} }, + { (uint64_t)700ull, {{0x51, 0x2c, 0xf, 0xae, 0xcc, 0xbe, 0xf2, 0xfe, 0xe5, 0x75, 0x4c, 0x6a, 0x45, 0xfd, 0xc0, 0x75, 0x2d, 0x4f, 0x15, 0x22, 0xe7, 0x7f, 0xf0, 0xc4, 0x8d, 0xcb, 0x19, 0x91, 0x8a, 0x68, 0x84, 0xe0}} }, + { (uint64_t)800ull, {{0xda, 0xa9, 0xf9, 0xa5, 0xb9, 0x71, 0x33, 0x33, 0xe9, 0x8c, 0x5, 0xac, 0xe7, 0x27, 0xcc, 0xe, 0x7d, 0xc3, 0xf1, 0x59, 0x49, 0xe1, 0xef, 0x4d, 0x94, 0xfa, 0x47, 0xd6, 0x8a, 0x34, 0xc6, 0x75}} }, + { (uint64_t)900ull, {{0xc7, 0x2b, 0x18, 0xc9, 0x17, 0xcd, 0x43, 0xee, 0x78, 0x40, 0x5e, 0x39, 0x83, 0x98, 0xb8, 0x3a, 0xc0, 0x97, 0x7b, 0x25, 0x19, 0x90, 0xd8, 0x13, 0xc, 0x38, 0xba, 0x53, 0xb6, 0x3d, 0xb4, 0xf7}} }, + { (uint64_t)1000ull, {{0x1, 0xdf, 0x60, 0x91, 0xeb, 0x6a, 0x48, 0xe9, 0xe4, 0x22, 0x25, 0xb, 0xe3, 0x83, 0x88, 0xc8, 0x61, 0xb6, 0x55, 0x55, 0xa7, 0x20, 0xad, 0x15, 0x35, 0x86, 0xfe, 0x2b, 0xd2, 0x2f, 0xa2, 0x3d}} }, + { (uint64_t)2000ull, {{0x24, 0xf5, 0xb1, 0x34, 0x78, 0x46, 0xaf, 0x22, 0xb5, 0x6f, 0x41, 0x25, 0xb3, 0xe7, 0x67, 0x8c, 0xf8, 0x4b, 0x4f, 0xd2, 0xf9, 0x2e, 0x1c, 0x40, 0xaa, 0x3a, 0x1b, 0xe0, 0xc7, 0x4d, 0x95, 0xe6}} }, + { (uint64_t)3000ull, {{0xa7, 0x1c, 0x9a, 0x8f, 0x40, 0xc1, 0x25, 0x9c, 0x36, 0x26, 0x27, 0x73, 0xe0, 0x8, 0x20, 0x18, 0x3e, 0x6b, 0x59, 0xe0, 0x71, 0xc9, 0x9b, 0x34, 0x9b, 0xef, 0x8f, 0x7e, 0xd2, 0xc6, 0xad, 0xb9}} }, + { (uint64_t)4000ull, {{0x98, 0xdc, 0x74, 0xaf, 0x19, 0x89, 0xd3, 0x4b, 0x64, 0x2e, 0xb3, 0x6, 0x2d, 0xbc, 0x9d, 0xca, 0xd8, 0x1, 0xc5, 0x65, 0x27, 0x6, 0x93, 0x99, 0xe7, 0xc4, 0x11, 0xad, 0x14, 0x28, 0x82, 0xf6}} }, + { (uint64_t)5000ull, {{0x61, 0x76, 0xac, 0x4a, 0xc0, 0x6, 0x5e, 0x49, 0xd6, 0xc4, 0x41, 0xcf, 0x40, 0x4f, 0xad, 0xda, 0xad, 0x44, 0x93, 0xe, 0xf0, 0x3c, 0x68, 0x9, 0xad, 0xd7, 0x77, 0xe4, 0x2f, 0xee, 0x7f, 0x10}} }, + { (uint64_t)6000ull, {{0x78, 0x79, 0x4, 0x65, 0xf6, 0x60, 0x5b, 0x5a, 0x84, 0x77, 0x36, 0x5a, 0xa6, 0xc2, 0xa4, 0xa5, 0x84, 0x91, 0xc, 0x23, 0x95, 0x2, 0x92, 0x97, 0x52, 0x49, 0xa1, 0xad, 0x7d, 0xf0, 0xf7, 0xe8}} }, + { (uint64_t)7000ull, {{0x20, 0xa5, 0x60, 0x6b, 0x60, 0x23, 0x95, 0xd6, 0x8e, 0x2f, 0xad, 0x8e, 0xc6, 0x7f, 0x92, 0xde, 0x89, 0xc6, 0x3e, 0x1e, 0x7f, 0xc1, 0xdd, 0x7f, 0x92, 0xff, 0xed, 0xb8, 0xf6, 0x55, 0xfb, 0xd}} }, + { (uint64_t)8000ull, {{0x9a, 0x78, 0x97, 0x43, 0x98, 0x65, 0x17, 0xd9, 0x5f, 0x4e, 0x80, 0x8b, 0xeb, 0xe6, 0x52, 0xd, 0xe6, 0xcf, 0x8c, 0x51, 0x35, 0xab, 0x36, 0x8, 0x7e, 0x87, 0xe2, 0x76, 0xac, 0x6a, 0x34, 0x1}} }, + { (uint64_t)9000ull, {{0x5f, 0xc7, 0xaa, 0x48, 0xbb, 0x19, 0x13, 0x58, 0xc7, 0xe3, 0x4d, 0x24, 0xcf, 0x9c, 0x31, 0x16, 0x74, 0x12, 0x7a, 0xb2, 0x45, 0xd0, 0x8f, 0x4e, 0x2c, 0xfd, 0xbf, 0x8f, 0x5, 0xc9, 0x5b, 0xf5}} }, + { (uint64_t)10000ull, {{0x61, 0x20, 0xe7, 0x76, 0xe9, 0x12, 0xab, 0x10, 0x5a, 0x49, 0xf9, 0xda, 0x2, 0xa6, 0x75, 0x17, 0xc0, 0xa9, 0xb, 0x2b, 0x3e, 0x2d, 0xa3, 0xd, 0xff, 0x34, 0x39, 0x93, 0xdb, 0xec, 0x95, 0x97}} }, + { (uint64_t)20000ull, {{0x77, 0xbf, 0xb5, 0x37, 0xac, 0xa, 0xbc, 0x41, 0xaa, 0x21, 0xd0, 0xec, 0xd9, 0x18, 0x13, 0x34, 0xd8, 0x6b, 0xa7, 0x86, 0x5a, 0x94, 0x47, 0xf5, 0xc1, 0x58, 0x9a, 0x81, 0xd7, 0xef, 0xb3, 0xbb}} }, + { (uint64_t)30000ull, {{0x35, 0xf4, 0x5, 0xa9, 0x5f, 0x75, 0x19, 0x2a, 0xe9, 0xc0, 0xd4, 0xf5, 0x88, 0x84, 0x47, 0x14, 0xf6, 0x85, 0x1b, 0x97, 0xce, 0xbd, 0x9f, 0x7c, 0x2, 0xc5, 0xdd, 0xd7, 0xbf, 0x58, 0xff, 0x31}} }, + { (uint64_t)40000ull, {{0x77, 0x55, 0xbb, 0x3f, 0x38, 0x7c, 0x21, 0xb8, 0xa0, 0xf4, 0x48, 0x1f, 0xbf, 0xa8, 0x8a, 0xbe, 0xee, 0xce, 0xc7, 0x56, 0x53, 0xfc, 0xa1, 0x89, 0x58, 0x39, 0xc1, 0xba, 0x6, 0x47, 0x9f, 0x96}} }, + { (uint64_t)50000ull, {{0x8b, 0x7e, 0x84, 0xa3, 0x37, 0xb7, 0xb9, 0xcd, 0x5d, 0xb3, 0x63, 0x33, 0x8, 0xad, 0x51, 0x86, 0xa3, 0x59, 0xd, 0xff, 0xb8, 0x23, 0x1e, 0x2f, 0x31, 0xfd, 0x20, 0x42, 0x54, 0x9f, 0xfb, 0xe2}} }, + { (uint64_t)60000ull, {{0xef, 0xfd, 0xa6, 0x25, 0x15, 0xea, 0xb1, 0xbc, 0x1e, 0xbd, 0x74, 0x92, 0x94, 0x9b, 0x1, 0x22, 0xc3, 0x9f, 0x71, 0xa, 0x65, 0x16, 0xec, 0x66, 0x8c, 0x37, 0x61, 0xe6, 0xcc, 0x36, 0x1f, 0x25}} }, + { (uint64_t)70000ull, {{0x16, 0xba, 0x89, 00, 0xf3, 0x6f, 0xf, 0x6c, 0x46, 0x1c, 0xb, 0xe7, 0x64, 0xae, 0xee, 0x48, 0x86, 0x6, 0xb0, 0x53, 0xed, 0xdc, 0x10, 0xb5, 0x9a, 0x3e, 0xde, 0xcd, 0x23, 0xd4, 0x4f, 0xc0}} }, + { (uint64_t)80000ull, {{0x4d, 0xd4, 0x70, 0x3b, 0x7b, 0x7f, 0xcf, 0xe7, 0x2a, 0x2e, 0x4f, 0x31, 0xa4, 0x34, 0x17, 0xf9, 0xc0, 0xda, 0x64, 0x2f, 0xd0, 0xa9, 0x29, 0xb8, 0xf5, 0xed, 0xd8, 0x3, 0x7f, 0x93, 0xc5, 0xb3}} }, + { (uint64_t)90000ull, {{0x8e, 0xfc, 0x3, 0x20, 0x40, 0xbd, 0x90, 0x41, 0xda, 0x3d, 0xb0, 0x9b, 0xa1, 0x3d, 0xa2, 0xa5, 0xd1, 0xb8, 0x12, 0x3, 0xa, 0x5a, 0x36, 0x7c, 0x58, 0x94, 0xbd, 0x54, 0x11, 0x9, 0xe7, 0x30}} }, + { (uint64_t)100000ull, {{0xbd, 0x2e, 0xb1, 0x97, 0x83, 0x57, 0x1c, 0xf2, 0x22, 0x2c, 0x81, 0xb, 0x69, 0xf, 0xc7, 0x66, 0x64, 0x57, 0xae, 0x20, 0x92, 0x5b, 0x90, 0x5, 0xce, 0xe6, 0x1d, 0xf2, 0x66, 0x6f, 0xdc, 0xb7}} }, + { (uint64_t)200000ull, {{0x83, 0xd4, 0xcd, 0xdd, 0xc1, 0x44, 0x87, 0x32, 0xf2, 0x97, 0x7c, 0x41, 0xaa, 0xa7, 0x1f, 0xe6, 0xde, 0x9c, 0x17, 0x6d, 0xa8, 0x99, 0xee, 0xbf, 0xfc, 0x1b, 0xb, 0xa9, 0xea, 0x92, 0x97, 0x90}} }, + { (uint64_t)300000ull, {{0xcc, 0xc0, 0x6b, 0x44, 0xc3, 0x1, 0x38, 0x6, 0x30, 0x45, 0xed, 0x1, 0xd2, 0x45, 0xd8, 0x14, 0x3, 0xb6, 0x36, 0x52, 0xeb, 0xc4, 0xf9, 0x96, 0x7f, 0xd, 0x7f, 0x38, 0x69, 0x7f, 0x46, 0x16}} }, + { (uint64_t)400000ull, {{0x1b, 0xbf, 0xe7, 0xe, 0xca, 0xf1, 0xdd, 0xd7, 0xf1, 0x2, 0x36, 0xf6, 0x8a, 0x41, 00, 0xb, 0x5d, 0xab, 0x2d, 0x47, 0x5c, 0xb9, 0x2f, 0x62, 0xc2, 0xd6, 0x84, 0xcf, 0x57, 0x69, 0xfb, 0x84}} }, + { (uint64_t)500000ull, {{0xf1, 0xb1, 0xcd, 0xaa, 0x78, 0x14, 0x95, 0x36, 0xf, 0x53, 0x31, 0x81, 0xaa, 0x58, 0xc8, 0xbd, 0xae, 0x6a, 0x77, 0x98, 0xd0, 0x2d, 0xab, 0x6d, 0x56, 0x26, 0x81, 0x27, 0x67, 0x9, 0xe7, 0x1}} }, + { (uint64_t)600000ull, {{0xd5, 0x26, 0x7d, 0x60, 0xd4, 0xfe, 0x9b, 0xc5, 0xfe, 0xfa, 0x7d, 0x3f, 0xe0, 0x7c, 0xd1, 0xfa, 0xd4, 0x55, 0x73, 0xd5, 0xae, 0x19, 0x10, 0xda, 0x7, 0x3e, 0x6d, 0x2d, 0xf9, 0xe2, 0x4, 0x39}} }, + { (uint64_t)700000ull, {{0xb, 0x58, 0x11, 0x25, 0xc2, 0xc4, 0x83, 0xc9, 0xa3, 0xd8, 0xbc, 0x8, 0x32, 0x2f, 0x26, 0xaa, 0x1f, 0xc5, 0xe, 0x41, 0x53, 0x2c, 0x1b, 0x9d, 0xf6, 0x26, 0xb0, 0x9, 0xd7, 0x88, 0x67, 0xcf}} }, + { (uint64_t)800000ull, {{0xf5, 0xb3, 0xd1, 0x8f, 0x66, 0xd0, 0xf9, 0x17, 0x5c, 0x30, 0x83, 0xb5, 0xf8, 0x7, 0x8e, 0xaf, 0xa8, 0x9e, 0xf8, 0x1d, 0xe7, 0x15, 0x8, 0xbc, 0x25, 0x1f, 0x5c, 0x5f, 0xe7, 0x25, 0x2e, 0x6}} }, + { (uint64_t)900000ull, {{0x1, 0xde, 0x40, 0x2c, 0x4b, 00, 0x43, 0x4, 0x2e, 0xae, 0x9e, 0xde, 0xa1, 0x49, 0x2b, 0x9d, 0x82, 0xb7, 0xbc, 0x36, 0x68, 0xe9, 0xb5, 0x84, 0xb0, 0x31, 0x3d, 0x44, 0x50, 0x53, 0x40, 0x74}} }, + { (uint64_t)1000000ull, {{0x53, 0x4b, 0x85, 0xc7, 0x89, 0x3f, 0x66, 0xf0, 0x26, 0xb6, 0x5e, 0xd7, 0xe7, 0xa4, 0xb8, 0xc9, 0xf4, 0xb, 0xe3, 0x1b, 0xcd, 0xa, 0x3d, 0xcd, 0x27, 0xc4, 0x71, 0x2, 0x56, 0x51, 0x65, 0x3}} }, + { (uint64_t)2000000ull, {{0xcd, 0xb5, 0xda, 0xfa, 0x53, 0x10, 0xf5, 0x26, 0x2f, 0xfc, 0x9, 0x26, 0xd0, 0xdf, 0x6e, 0xeb, 0xee, 0x2d, 0x52, 0xa9, 0x8d, 0xc6, 0x9f, 0xd, 0xc5, 0xe4, 0xeb, 0xf0, 0xc1, 0xa8, 0x77, 0x2e}} }, + { (uint64_t)3000000ull, {{0x9e, 0x75, 0x63, 0xf0, 0x33, 0x59, 0xea, 0x31, 0xe2, 0x91, 0xe7, 0xf0, 0xb8, 0x74, 0x17, 0xbc, 0xf5, 0xb2, 0x34, 0xee, 0x8b, 0x7e, 0x5b, 0x4, 0x41, 0x73, 0xbf, 00, 0x46, 0x86, 0x7c, 0x57}} }, + { (uint64_t)4000000ull, {{0xfd, 0x2a, 0xeb, 0xd, 0x5e, 0xe5, 0x3b, 0x77, 0xf2, 0xb1, 0xe3, 0xac, 0x75, 0x2d, 0x19, 0x38, 0x9f, 0xc5, 0xba, 0xa0, 0xf8, 0xd7, 0x64, 0x48, 0xa5, 0x9f, 0x99, 0x85, 0xa4, 0x8d, 0xa, 0x25}} }, + { (uint64_t)5000000ull, {{0xc0, 0xbe, 0x4f, 0xb8, 0x77, 0xb9, 0xce, 0x50, 0x87, 0x71, 0x32, 0x3b, 0xcf, 0x1f, 0xb9, 0x48, 0x47, 0x10, 0xee, 0x23, 0x2, 00, 0x6, 0xc3, 0xe8, 0xca, 0xac, 0x6e, 0x4f, 0x2, 0xfa, 0xbf}} }, + { (uint64_t)6000000ull, {{0xfc, 0x44, 0x5c, 0xa3, 0x84, 0xf3, 0x3e, 0x55, 0x8d, 0xc1, 0x56, 0x44, 0x9d, 0x3f, 0xba, 0x6a, 0xfd, 0x54, 0xc3, 0x42, 0xe6, 0x35, 0x11, 0xf, 0xe7, 0x9c, 0x16, 0xc7, 0x17, 0xf7, 0xd4, 0xf7}} }, + { (uint64_t)7000000ull, {{0xd8, 0x9, 0x2b, 0x8d, 0x45, 0xdb, 0x54, 0xa5, 0x6d, 0x64, 0xe8, 0x9, 0x4a, 0x6, 0x22, 0xe2, 0x6e, 0x8a, 0x2e, 0xec, 0xb9, 0x3, 0xb2, 0xe1, 0xf7, 0x5a, 0x83, 0x7b, 0x3a, 0xd8, 0x55, 0x4a}} }, + { (uint64_t)8000000ull, {{0x10, 0x4, 0x5c, 0x91, 0xdb, 0xad, 0x8a, 0x6a, 0x81, 0x62, 0x4a, 0xe0, 0xcf, 0x20, 0x5d, 0xb9, 0x97, 0x3e, 0xe8, 0x42, 0x3e, 0x97, 0xaf, 0x58, 0xa6, 0x1c, 0xfa, 0x7a, 0x78, 0x66, 0xf4, 0x1}} }, + { (uint64_t)9000000ull, {{0x11, 0x5c, 0x20, 0x9e, 0xe1, 0xde, 0xf3, 0x10, 0xce, 0xc9, 0xa6, 0xd1, 0x6c, 0xe6, 0x27, 0xec, 0xbd, 0xb9, 0xff, 0x2c, 0x23, 0x9, 0x3c, 0x24, 0xc8, 0x6c, 0x1b, 0xf2, 0x50, 0xd4, 0xb5, 0x85}} }, + { (uint64_t)10000000ull, {{0x2f, 0x99, 0xd9, 0x74, 0x44, 0x18, 0x66, 0x9, 0x49, 0xba, 0x43, 0x35, 0x61, 0xc6, 0x5, 0xb6, 0xf7, 0xbe, 0x8f, 0x82, 0xa, 0x93, 0xcb, 0x2a, 0xed, 0xa9, 0x7c, 0x87, 0x32, 0x92, 0x56, 0x49}} }, + { (uint64_t)20000000ull, {{0xc6, 0x77, 0x1f, 0xab, 0x14, 0xb, 0x75, 0xf4, 0xef, 0xd0, 0x97, 0xfc, 0xe1, 0x82, 0x6b, 0x80, 0xba, 0xe3, 0x16, 0xbc, 0xec, 0x28, 0x86, 0x9b, 0x3a, 0x1b, 0xf1, 0xbc, 0x6e, 0x4d, 0x20, 0x43}} }, + { (uint64_t)30000000ull, {{0xa1, 0xe9, 0xed, 0x3e, 0xf6, 0x5a, 0x9d, 0x52, 0x6c, 0xc2, 0x62, 0x5, 0x88, 0x12, 0x1, 0xd8, 0xa8, 0xf2, 0xc4, 0x40, 0x9f, 0xa3, 0x64, 0x10, 0x72, 0x96, 0xb9, 0xf9, 0x6a, 0x61, 0xb3, 0x58}} }, + { (uint64_t)40000000ull, {{0xb5, 0x31, 0x2d, 0xc7, 0x72, 0x94, 0xab, 0x9b, 0xc8, 0xbf, 0xd1, 0x39, 0x1e, 0x9a, 0xca, 0x92, 0x45, 0xe2, 0x28, 0xf7, 0x4b, 0x49, 0x74, 0xfc, 0x29, 0xad, 0x1c, 0x31, 0xcb, 0xe3, 0xe6, 0xa3}} }, + { (uint64_t)50000000ull, {{0xb8, 0xab, 0xc9, 0xff, 0xf6, 0x84, 0x1d, 0x2e, 0xa0, 0x13, 0x5a, 0x21, 0x72, 0xd3, 0xa7, 0xb, 0xfc, 0x2b, 0x70, 0x22, 0x8, 0xcd, 0x4a, 0x43, 0xc6, 0x30, 0xbe, 0xb1, 0xb8, 0xa0, 0x32, 0x8b}} }, + { (uint64_t)60000000ull, {{0x63, 0x90, 0xe1, 0xdb, 0x81, 0xb0, 0xea, 0x5c, 0xe2, 0x73, 0x94, 0x14, 0xe5, 0x2b, 0x7, 0x98, 0xd8, 0x2e, 0xb8, 0xe9, 0xae, 0xc5, 0x6d, 0xfe, 0x7e, 0x2c, 0x64, 0x11, 0xab, 0x79, 0x41, 0x87}} }, + { (uint64_t)70000000ull, {{0x7e, 0x51, 0xaf, 0xee, 0x5b, 0xc9, 0x71, 0x52, 0x9d, 0x64, 0x4d, 0xcd, 0x7f, 0x2a, 0x2a, 0xb0, 0x26, 0x69, 0xce, 0x2c, 0xb5, 0x7, 0xa6, 0x2d, 0xfc, 0x93, 0x17, 0x6c, 0xb6, 0xdf, 0x41, 0x38}} }, + { (uint64_t)80000000ull, {{0xf3, 0x7b, 0x94, 0x6b, 0x8b, 0x24, 0x88, 0xeb, 0xee, 0x1c, 0x6, 0xc1, 0x27, 0xfb, 0xe5, 0xfa, 0x5e, 0xfd, 0x62, 0x36, 0x9d, 0xd5, 0xaa, 0xda, 0xed, 0xd8, 0x88, 0x50, 0x1d, 0x3b, 0x7e, 0x3b}} }, + { (uint64_t)90000000ull, {{0x46, 0xcb, 0x76, 0x57, 0xf6, 0x1c, 0x83, 0x7c, 0xec, 0x80, 0x74, 0xbb, 0xb0, 0xf5, 0x2e, 0x7f, 0xc5, 0x9a, 0xd, 0x94, 0xe0, 0x17, 00, 0x9a, 0xbe, 0x25, 0x65, 0x2e, 0x4a, 0xd2, 0xe5, 0x3d}} }, + { (uint64_t)100000000ull, {{0x66, 0x7b, 0x8e, 0x6f, 0x6a, 0x4b, 0x91, 0x89, 0x76, 0xd9, 0x73, 0x5a, 0x43, 0x36, 0x7d, 0xc7, 0x59, 0x2c, 0x87, 0xd0, 0xa1, 0xf8, 0x15, 0xc6, 0xe8, 0x7d, 0xf1, 0x1a, 0x13, 0x50, 0x9f, 0xb2}} }, + { (uint64_t)200000000ull, {{0x3b, 0xcb, 0x51, 0x48, 0x1, 0x64, 0x1b, 0x62, 0x55, 0x93, 0x8c, 0xc5, 0x3, 0x76, 0x2d, 0x35, 0xce, 0x6, 0xd7, 0x5f, 0xe9, 0x50, 0x95, 0x9a, 0x1a, 0xab, 0x21, 0x4b, 0x50, 0x9b, 0x10, 0xb}} }, + { (uint64_t)300000000ull, {{0xa5, 0x92, 0x6f, 0x3, 0x1e, 0x6b, 0x15, 0xeb, 0x86, 0x23, 0x51, 0x8, 0xab, 0xb1, 0xaf, 0x90, 0xc5, 0xb1, 0x62, 0xc3, 0x99, 0x8c, 0x8b, 0xbb, 0x3f, 0xfb, 0xb0, 0x72, 0x9d, 0xa9, 0x45, 0x7b}} }, + { (uint64_t)400000000ull, {{0xfe, 0x35, 0xb6, 0x99, 0x44, 0x41, 0xe, 0xaf, 0x81, 0x5b, 0xdc, 0xd0, 0xa4, 0xd7, 0x1e, 0xf9, 0xfc, 0x66, 0x86, 0x48, 0xad, 0x43, 0x74, 0x3b, 0x3, 0x5a, 0xed, 0x2c, 0x17, 0xc1, 0x38, 0x7a}} }, + { (uint64_t)500000000ull, {{0x22, 0x22, 0xd6, 0x70, 0xb8, 0x7d, 0x9b, 0x47, 0xb8, 0xb9, 0x5c, 0x8c, 0x39, 0x7b, 0xc5, 0x2e, 0x2b, 0x46, 0xa6, 0x48, 0xb0, 0x2, 0xa0, 0x48, 0x5a, 0x37, 0x5c, 0xd8, 0x1f, 0x4a, 0x54, 0x5f}} }, + { (uint64_t)600000000ull, {{0xd3, 0x23, 0x8a, 0x4a, 0x8b, 0x71, 0xab, 0x46, 0xd1, 0x53, 0x4, 0xac, 0xfa, 0x2f, 0x40, 0xbf, 0x5e, 0xa6, 0x3b, 0x3d, 0x86, 0x4a, 0x79, 0xfa, 0x84, 0x25, 0xd2, 0x65, 0x5a, 0xe7, 0x7, 0x6f}} }, + { (uint64_t)700000000ull, {{0xa8, 0xff, 0x28, 0x3f, 0xcf, 0xf0, 0x53, 0xd3, 0x44, 0xc8, 0xf7, 0x56, 0x4f, 0x40, 0x24, 0xb6, 0x6b, 0xfa, 0x45, 0x9f, 0x47, 0x6f, 0xd, 0x73, 0xc, 0x91, 0x39, 0x90, 0x8b, 0x2d, 0x64, 0x7e}} }, + { (uint64_t)800000000ull, {{0xf2, 0xda, 0xf8, 0x88, 0xc4, 0x46, 0x57, 0x1, 0xc0, 0xe6, 0x1e, 0x12, 0xc3, 0xfb, 0xd4, 0xea, 0x79, 0xc7, 0xec, 0xb4, 0xf0, 0xc4, 0xb1, 0x54, 0xc5, 0x1a, 0x24, 0xd1, 0xe9, 0x21, 0x28, 0xba}} }, + { (uint64_t)900000000ull, {{0x11, 0x6a, 0xe5, 0xd2, 0x9c, 0xec, 0x72, 0xaa, 0xc5, 0x57, 0xcb, 0x14, 0xe2, 0xcd, 0xd5, 0x53, 0xe5, 0x88, 0xff, 0x8b, 0x81, 0x78, 0x26, 0x1, 0x99, 0xc4, 0xc, 0xae, 0xa2, 0x12, 0xcb, 0x63}} }, + { (uint64_t)1000000000ull, {{0x8c, 0xe6, 0x48, 0x33, 0xce, 0xc9, 00, 0xcb, 0x6d, 0x5a, 0xc4, 0x6f, 0xc0, 0x23, 0x7d, 0x8f, 0x24, 0x39, 0xc3, 0xdf, 0xa2, 0x38, 0xba, 0xf9, 0xcc, 0x94, 0x16, 0x6a, 0xd2, 0xe8, 0x98, 0x87}} }, + { (uint64_t)2000000000ull, {{0x37, 0x8d, 0x3c, 0x5d, 0xbb, 0xa4, 0x82, 0x3d, 0x33, 0x12, 0xbb, 0x61, 0xfc, 0x6, 0x75, 0xa1, 0xbb, 0x39, 0x89, 0xf3, 0x97, 0x1, 0xeb, 0xd, 0x5c, 0xe4, 0xde, 0x5b, 0xd, 0x90, 0x74, 0x72}} }, + { (uint64_t)3000000000ull, {{0x7f, 0xa2, 0xd0, 0xa5, 0x99, 0xe7, 0x97, 0x2e, 0x74, 0xcb, 0x75, 0xf9, 0x8a, 0xf4, 0x84, 0xfc, 0x85, 0x19, 0xcb, 0x7e, 0x25, 0xb9, 0x84, 0xa7, 0x6d, 0x8b, 0xc2, 0xba, 0x8d, 0xaf, 0xde, 0xd8}} }, + { (uint64_t)4000000000ull, {{0xda, 0x3a, 0xcb, 00, 0xab, 0x2d, 0x8d, 0xcc, 0xac, 0xec, 0x8f, 0x77, 0x59, 0x21, 0xc4, 0xe, 0x26, 0xb1, 0xff, 0xbe, 0xca, 0x9e, 0xb7, 0xe6, 0x57, 0x25, 0x6f, 0x59, 0x68, 0xf2, 0x34, 0x1c}} }, + { (uint64_t)5000000000ull, {{0x34, 0x6, 0xd7, 0x9a, 0x50, 0xd8, 0x14, 0xa9, 0xcc, 0xed, 0x3b, 0x24, 0x4, 0xed, 0x3e, 0x1b, 0x8d, 0xa6, 0x21, 0x98, 0x8c, 0x43, 0xb1, 0x93, 0x69, 0x42, 0xf4, 0x94, 0xa, 0xc5, 0xbf, 0x6a}} }, + { (uint64_t)6000000000ull, {{0xf8, 0x3e, 0xe8, 0xc1, 0x62, 0xfc, 0x52, 0xa0, 0x8, 0x9f, 0x46, 0xe8, 0x29, 0xc2, 0xea, 0xf6, 0xa1, 0x9f, 0xd5, 0x96, 0xcd, 0x12, 0xb3, 0xe8, 0x19, 0xd5, 0x67, 0x69, 0x44, 0xf, 0x7b, 0x4e}} }, + { (uint64_t)7000000000ull, {{0x8c, 0x72, 0x7d, 0x24, 0x57, 0xf3, 0x4b, 0x2f, 0xdb, 0x6a, 0xdf, 0x69, 0x1a, 0xb3, 0x5f, 0xaa, 0xe4, 0xff, 0x23, 0x4c, 0x28, 0xb4, 0x4e, 0x9f, 0xd3, 0x71, 0x8e, 0xef, 0xec, 0x41, 0x75, 0x80}} }, + { (uint64_t)8000000000ull, {{0x4a, 0x2e, 0x2f, 0x76, 0xe3, 0x5d, 0xcb, 0xa8, 0x97, 0xa3, 0xae, 0x72, 0xc4, 0x27, 0xd, 0x9c, 0x13, 0x17, 0x14, 0xed, 0x19, 0x1b, 0x55, 0x5c, 0x5e, 0x1, 0xe4, 0x75, 0x7c, 0xba, 0xe7, 0x2c}} }, + { (uint64_t)9000000000ull, {{0x3f, 0x9f, 0xc, 0x4, 0xc0, 0xb9, 0xec, 0x9b, 0x4d, 0x11, 0x7c, 0x5f, 0xc9, 0xf1, 0x8a, 0x20, 0xf2, 0xb3, 0xfa, 0xcc, 0xa4, 0xc8, 0xae, 0x41, 0xaf, 0x7c, 0x8, 0xe9, 0xe0, 0xef, 0xb9, 0x81}} }, + { (uint64_t)10000000000ull, {{0x97, 0xc9, 0x2a, 0x29, 0x1, 0x5e, 0xcb, 0x49, 0xf8, 0x9, 0x5, 0x45, 0xe0, 0x1f, 0xf9, 0x78, 0x6c, 0xae, 0x40, 0x57, 0x73, 0x47, 0x61, 0x18, 0x24, 0xf4, 0xb6, 0x59, 0x9f, 0xf5, 0xd3, 0x64}} }, + { (uint64_t)20000000000ull, {{0x9, 0xba, 0xed, 0x9a, 0x3c, 0x44, 0xb2, 0x22, 0x85, 0xa0, 0xae, 0xa4, 0x14, 0x8c, 0xa7, 0xde, 0x9b, 0xea, 0x96, 0x3c, 0xf6, 0x96, 0x23, 0xb6, 0x83, 0x44, 0x5c, 0xa, 0x10, 0xa5, 0x86, 0x77}} }, + { (uint64_t)30000000000ull, {{0x45, 0xac, 0xaf, 0x1d, 0xe2, 0x89, 0x6d, 0xe8, 0x72, 0x84, 0xff, 0xed, 0x57, 0x8b, 0x77, 0x14, 0xf5, 0x18, 0xa6, 0x18, 0xe2, 0xae, 0x6f, 0x90, 0xae, 0x4f, 0x70, 0x13, 0xa2, 0x8e, 0x99, 0xe0}} }, + { (uint64_t)40000000000ull, {{0x8, 0xb8, 0x47, 0x36, 0x42, 0x24, 0xe2, 0x9c, 0xe3, 0x36, 0x63, 0x93, 0xc2, 0xe1, 0x1e, 0xfc, 0x75, 0x55, 0xde, 0xe1, 0xa0, 0x5f, 0x91, 0xa7, 0x2e, 0x61, 0x11, 0x76, 0x84, 0xdd, 0xbe, 0x29}} }, + { (uint64_t)50000000000ull, {{0x6c, 0x8e, 0xe, 0x4a, 0x63, 0x4f, 0x85, 0x9a, 0x31, 0xab, 0x2f, 0x7a, 0x78, 0xc0, 0xc4, 0xa5, 0x93, 0x8c, 0xb7, 0x7f, 0x3, 0x35, 0x50, 0xa4, 0x7d, 0x7e, 0x31, 0x81, 0xb6, 0xb2, 0x6e, 0xc0}} }, + { (uint64_t)60000000000ull, {{0x66, 0xc2, 0xa0, 0x9, 0x65, 0xf9, 0xbf, 0xcb, 0xb1, 0x1e, 0xa0, 0x3c, 0xf1, 0xd6, 0x31, 0xb0, 0xe, 0x8a, 0x1e, 0xf7, 0xa6, 0xb, 0x1b, 0xe4, 0xa5, 0xac, 0x9, 0x23, 0xb, 0xf8, 0x17, 0x3f}} }, + { (uint64_t)70000000000ull, {{0x63, 0x51, 0xd7, 0x74, 0xc0, 0x2c, 0x5a, 0x9d, 0xee, 0xcf, 0xdb, 0xab, 0x70, 0x96, 0x68, 0x59, 0x8c, 0x47, 0xe4, 0xb1, 0x78, 0x2c, 0xe5, 0xae, 0x31, 0x6a, 0xf7, 0x40, 0xa6, 0x6f, 0x7e, 0x30}} }, + { (uint64_t)80000000000ull, {{0x5a, 0xcc, 0xfd, 0x16, 0x22, 0x79, 0xa5, 0x1c, 0x8b, 0x3b, 0xd5, 0xd3, 0x67, 0x9e, 0x91, 0x89, 0x67, 0xa2, 0x64, 0xea, 0x6, 0x3d, 0x37, 0xdf, 0xf5, 0xe3, 0x45, 0x7e, 0xc3, 0x7, 0xd4, 0x57}} }, + { (uint64_t)90000000000ull, {{0xb7, 0x47, 0xfc, 0x1, 0xc6, 0xf0, 0xc7, 0x49, 0x67, 0x3a, 0x29, 0x10, 0x25, 0xc, 0x2e, 0x23, 0xcb, 0x38, 0x27, 0x4d, 0x63, 0xb4, 0x2f, 0x52, 0x1b, 0x84, 0x63, 0x56, 0xe4, 0x13, 0x61, 0x8f}} }, + { (uint64_t)100000000000ull, {{0x9, 0x42, 0x84, 0x3d, 0x6f, 0x69, 0xe1, 0xcf, 0x3d, 0x99, 0xc9, 0x9f, 0xc, 0x97, 0xc0, 0xe6, 0xe5, 0x78, 0x93, 0x5a, 0xf6, 0xa8, 0xbd, 0xb8, 0xf8, 0x1d, 0x5b, 0x90, 0xbd, 0xe7, 0xcc, 0x10}} }, + { (uint64_t)200000000000ull, {{0x56, 0x4c, 0x64, 0xea, 0x50, 0xe4, 0xbd, 0x20, 0xdb, 0x58, 0x5d, 0xb5, 0x87, 0xb1, 0xf7, 0x64, 0xa2, 0x62, 0xd8, 0x46, 0xa6, 0xb0, 0xa2, 0x4b, 0x43, 0x27, 0x60, 0xd2, 0xf9, 0xde, 0x66, 0x5b}} }, + { (uint64_t)300000000000ull, {{0xac, 0x65, 0x83, 0x41, 0x5b, 0xd6, 0x4c, 0x3, 0x35, 0x97, 0xf9, 0x28, 0xa4, 0xb5, 0xd4, 0xf4, 0x78, 0x9e, 0xa8, 0xb2, 0x87, 0x82, 0x73, 0x89, 0xa8, 0x1e, 0xb6, 0x62, 0x9e, 0xc5, 0xb8, 0x50}} }, + { (uint64_t)400000000000ull, {{0x52, 0xf4, 0x9d, 0x89, 0xcf, 0x74, 0x13, 0x2f, 0xc7, 0x43, 0x2e, 0x6a, 0x6b, 0xef, 0xcf, 0xf3, 0xfd, 0x13, 0xd6, 0x3b, 0x51, 0x60, 0xab, 0x1c, 0xe6, 0x4a, 0xb0, 0xd1, 0x21, 0xcd, 0xa9, 0x9a}} }, + { (uint64_t)500000000000ull, {{0xe9, 0xaa, 0x7c, 0x81, 0xcd, 0xb5, 0xb3, 0x14, 0x8f, 0xb7, 0x62, 0x80, 0x63, 0xcd, 0x7a, 0x7, 0xd1, 0xad, 0xd1, 0x64, 0x3c, 0xed, 0xd3, 0xfa, 0x34, 0x47, 0x9d, 0x85, 0x9c, 0xc5, 0x62, 0x65}} }, + { (uint64_t)600000000000ull, {{0x98, 0x27, 0xae, 0x31, 0xe5, 0xc2, 0xa7, 0x78, 0x39, 0xf6, 0xb, 0x83, 0xab, 0x45, 0x78, 0xe2, 0xa0, 0x1e, 0xfa, 0x4b, 0x3b, 0x14, 0xcc, 0x72, 0x73, 0x14, 0xff, 0xd7, 0x15, 0x53, 0x63, 0xbf}} }, + { (uint64_t)700000000000ull, {{0x72, 0x91, 0x6a, 0x79, 0x27, 0xff, 0x13, 0x24, 0xd4, 0x98, 0x40, 0xec, 0xc0, 0x98, 0x68, 0xb8, 0xf3, 0x15, 0xe4, 0xf1, 0xf6, 0xd4, 0x45, 0x8d, 0x37, 0x5e, 0xc7, 0x45, 0xfc, 0x2e, 0x63, 0x53}} }, + { (uint64_t)800000000000ull, {{0x66, 0x76, 0xe0, 0x4, 0xf, 0xa4, 0xb8, 0x22, 0x9c, 0x61, 0x69, 0xc, 0x71, 0x32, 0x22, 0xcf, 0x3d, 0x37, 0xb9, 0x49, 0x3b, 0x49, 0x6, 0x80, 0xbb, 0x48, 0xd8, 0xd5, 0x1a, 0xde, 0x95, 0xf2}} }, + { (uint64_t)900000000000ull, {{0x41, 0x54, 0xb3, 0x46, 0x5a, 0x43, 0x72, 0x67, 0x1e, 0xa9, 0xe0, 0x64, 0xa7, 0xca, 0xa6, 0x6e, 0x14, 0xb4, 0x98, 0x6a, 0x46, 0x68, 0x91, 0x8a, 0xfa, 0x57, 0x9b, 0xf1, 0xed, 0x25, 0x6, 0xdd}} }, + { (uint64_t)1000000000000ull, {{0xbb, 0x6f, 0x70, 0x62, 0xca, 0x30, 0x6d, 0x67, 0x2a, 0x73, 0xe, 0x2a, 0x2f, 0x21, 0x9b, 0xdb, 0xe4, 0xc, 0x9f, 0xb3, 0xfe, 0x4d, 0x60, 0x13, 0x69, 0x2a, 0xf9, 0x3c, 0xdb, 0x2e, 0xc, 0xd1}} }, + { (uint64_t)2000000000000ull, {{0xbc, 0xe, 0xae, 0x5b, 0x9c, 0x6a, 0xd6, 0x38, 0x7a, 0x41, 0x19, 0x3c, 0x46, 0xf3, 0xc1, 0xd0, 0x71, 0x6d, 0x77, 0xd6, 0x4e, 0x22, 0xb2, 0xe0, 0x7b, 0x4b, 0xce, 0x75, 0x67, 0x65, 0xa2, 0xb}} }, + { (uint64_t)3000000000000ull, {{0x10, 0xc, 0x6f, 0x13, 0x42, 0xb7, 0x1b, 0x73, 0xed, 0xdd, 0xc5, 0x49, 0x2b, 0xe9, 0x23, 0x18, 0x2f, 00, 0xa6, 0x83, 0x48, 0x8e, 0xc3, 0xa2, 0xa1, 0xc7, 0xa9, 0x49, 0xcb, 0xe5, 0x77, 0x68}} }, + { (uint64_t)4000000000000ull, {{0x41, 0x9f, 0x7c, 0x94, 0x91, 0x4, 0x34, 0xf, 0xd3, 0xce, 0x85, 0x94, 0x8d, 0x2e, 0xf9, 0xf0, 0xdd, 0x4b, 0xb3, 0xd9, 0x2f, 0x5a, 0x78, 0x2c, 0x5f, 0x78, 0x4, 0xb7, 0x52, 0x9a, 0x13, 0xc6}} }, + { (uint64_t)5000000000000ull, {{0x40, 0x65, 0x34, 0x98, 0xbe, 0xa0, 0x22, 0xe3, 0x36, 0x5a, 0x3, 0xe5, 0x75, 0x25, 0xba, 0x65, 0x96, 0x53, 0x76, 0x24, 0x4f, 0xff, 0x10, 0x73, 0xe, 0xd9, 0x7a, 0x73, 0xb7, 0x53, 0x1, 0x91}} }, + { (uint64_t)6000000000000ull, {{0xdb, 0x1c, 0x7c, 0xf6, 0x8, 0x91, 0xf9, 0x65, 0xeb, 0xa9, 0xc6, 0x2, 0x24, 00, 0x63, 0xe, 00, 0x47, 0x95, 0x34, 0xe6, 0xf5, 0xb5, 0x33, 0xdc, 0xfc, 0x83, 0x19, 0x38, 0x52, 0x2c, 0x78}} }, + { (uint64_t)7000000000000ull, {{0x59, 0xa0, 0x3a, 0x31, 0x53, 0xa9, 0x94, 0xd7, 0x23, 0x27, 0xe4, 0xd9, 0x24, 0x21, 0xd3, 0xe3, 0x29, 0x1b, 0x1f, 0xa1, 0xb2, 0x40, 0xde, 0x44, 0xb9, 0x2d, 0x7f, 0x62, 0xec, 0x1, 0x28, 0xf1}} }, + { (uint64_t)8000000000000ull, {{0xb2, 0x80, 0xb9, 0x3b, 0x1e, 0x43, 0x88, 00, 0x73, 0xea, 0x4a, 0xa0, 0xef, 0x11, 0x4, 0xf8, 0x24, 0xbd, 0x12, 0x7a, 0x4a, 0x3d, 0xa2, 0x13, 0x92, 0x65, 0xf, 0xe8, 0xc6, 0x55, 0xb6, 0xc5}} }, + { (uint64_t)9000000000000ull, {{0xda, 0xf0, 0xd3, 0xe9, 0x32, 0x17, 0xd8, 0xe9, 0x5a, 0xbf, 0xdd, 0xf1, 0x3b, 0x7f, 0xd4, 0x8e, 0x34, 0x47, 0xad, 0x9, 0x23, 0x26, 0xb8, 0x99, 0xed, 0x58, 0x1f, 0xd5, 0xf8, 0x6, 0xc5, 0x6}} }, + { (uint64_t)10000000000000ull, {{0x16, 0x3d, 0xd6, 0x82, 0xec, 0x97, 0x7c, 0xdd, 0xa5, 0x95, 0x31, 0xda, 0x3f, 0xfa, 0x72, 0x99, 0x8a, 0x6f, 0x88, 0x37, 0xab, 0xad, 0xc6, 0x36, 0xaa, 0xed, 0xc8, 0xbe, 0x19, 0xb2, 0xd7, 0xc7}} }, + { (uint64_t)20000000000000ull, {{0x2, 0xfa, 0x35, 0x3a, 0xa8, 0x4e, 0xa8, 0xc4, 0x4c, 0x80, 0x23, 0x6, 0x5d, 0x79, 0x41, 0x60, 0x6b, 0x1f, 0xa5, 0xc2, 0x64, 0xdc, 0xcf, 0x46, 0xdc, 0x64, 0x94, 0xeb, 0xe9, 0x60, 0x6f, 0x20}} }, + { (uint64_t)30000000000000ull, {{0x87, 0x5, 0xd, 0xab, 0xf5, 0xb2, 0x3e, 0x8b, 0x79, 0x81, 0x3f, 0x4e, 0xd7, 0x6a, 0xa4, 0xad, 0xd2, 0x25, 0xdd, 0x2a, 0x50, 0x89, 0xaf, 0x6, 0x7d, 0xa7, 0x7c, 0xcb, 0x6e, 0xc5, 0x59, 0x46}} }, + { (uint64_t)40000000000000ull, {{0xaa, 0xe6, 0xb2, 0xc8, 0xa2, 0x9e, 0x4d, 0xbc, 0x63, 0x76, 0xc1, 0x72, 0x5, 0xfb, 0x2, 0x85, 0xe7, 0xd7, 0xd3, 0x25, 0x32, 0x3c, 0xd5, 0x26, 0xf, 0x98, 0xad, 0xff, 0xf7, 0xd4, 0xd4, 0xfb}} }, + { (uint64_t)50000000000000ull, {{0x9d, 0x79, 0x28, 0x82, 0x12, 0xa1, 0xe2, 0x3c, 0x9, 0x9f, 0xb2, 0xd8, 0xf0, 0xd0, 0xdb, 0xd3, 0xc2, 0xec, 0xd7, 0x58, 0xb9, 0xe6, 0xb5, 0xb4, 0xf2, 0x90, 0x60, 0x7, 0x9f, 0x19, 0x66, 0x9f}} }, + { (uint64_t)60000000000000ull, {{0x18, 0x90, 0x10, 0x6f, 0x1b, 0x97, 0xbc, 0x2d, 0xa, 0xe3, 0x96, 0xe5, 0xe5, 0x5e, 0xbf, 0xcc, 0x8e, 0xf6, 0x91, 0x7f, 0xb1, 0x96, 0xcb, 0x2b, 0x1e, 0x80, 0x25, 0x5d, 0x54, 0xb6, 0x87, 0x10}} }, + { (uint64_t)70000000000000ull, {{0x57, 0xd3, 0x4e, 0xf7, 0x54, 0x3b, 0xe4, 0x7b, 0x7b, 0xf4, 0x97, 0xce, 0x4a, 0x17, 0x6e, 0x78, 0xc6, 0xd6, 0x5c, 0xd3, 0x27, 0xf6, 0x4b, 0xa7, 0x5c, 0x27, 0xd1, 0x57, 0xb3, 0x37, 0x12, 0x5d}} }, + { (uint64_t)80000000000000ull, {{0x5e, 0xcb, 0x10, 0x15, 0x4b, 0x96, 0xca, 0xb5, 0x5e, 0x9, 0x46, 0x83, 0xf8, 0xdb, 0xff, 0x7f, 0x56, 0x63, 0x5f, 0xa6, 0x64, 0x97, 0xee, 0x9e, 0x24, 0xe, 0x83, 0x63, 0x7c, 0x7c, 0x87, 0x72}} }, + { (uint64_t)90000000000000ull, {{0x42, 0x32, 0x69, 0x98, 0x51, 0x30, 0xf1, 0x66, 0x51, 0x6a, 0x5b, 0xa8, 0x61, 0x9, 0x6d, 0x72, 0xec, 0xcc, 0x67, 0xad, 0xab, 0xa4, 0x5e, 0xb3, 0x73, 0x9a, 0xe, 0xbc, 0x61, 0xa3, 0x20, 0xae}} }, + { (uint64_t)100000000000000ull, {{0xa8, 0xd1, 0x60, 0x95, 0x91, 0x49, 0x8f, 0xa7, 0xc2, 0x94, 0x27, 0xad, 0x89, 0x31, 0xaf, 0x36, 0xc5, 0x2d, 0xc9, 0x7b, 0x4a, 0x11, 0xe7, 0x47, 0xa9, 0x56, 0xc2, 0x8c, 0x42, 0x54, 0xcf, 0xd4}} }, + { (uint64_t)200000000000000ull, {{0x23, 0x14, 0x49, 00, 0xa8, 0x66, 0xe8, 0xc1, 0xbf, 0x40, 0x98, 0xda, 0xa9, 0x48, 0xb9, 0x86, 0xf3, 0x84, 0xe, 0x5a, 0x7d, 0x21, 0x5e, 0xf0, 0xd5, 0x64, 0xef, 0xd8, 0xbe, 0xc6, 0x83, 0x15}} }, + { (uint64_t)300000000000000ull, {{0x6a, 0x51, 0x47, 0x3c, 0x86, 0xed, 0xad, 0x53, 0x51, 0x4b, 0x3f, 0x95, 0x97, 0xed, 0x21, 0xae, 00, 0x81, 0x51, 0xa0, 0x9e, 0x43, 0xad, 0xdd, 0x45, 0xd1, 0x74, 0x63, 0xc5, 0x34, 0x3, 0x97}} }, + { (uint64_t)400000000000000ull, {{0x8, 0xbd, 0xd4, 0xc3, 0xe4, 0x53, 0x1b, 0x29, 0x7a, 0x70, 00, 0x1e, 0xb8, 0xa4, 0xf1, 0x98, 0xdc, 0x3b, 0xd4, 0xf1, 0xf5, 0x60, 0x9a, 0xda, 0x98, 0xf6, 0xd9, 0x5f, 0x9a, 0x1a, 0x30, 0x2e}} }, + { (uint64_t)500000000000000ull, {{0x97, 0x55, 0x70, 0xea, 0x12, 0xde, 0x5a, 0xf5, 0xc5, 0x36, 0xbd, 0xb6, 0x83, 0x54, 0xfb, 0xc8, 0x32, 0x21, 0x50, 0xfc, 0x56, 0x83, 0x7c, 0x4b, 0x78, 0xa9, 0x85, 0x76, 0x5d, 0x2a, 0x70, 0x99}} }, + { (uint64_t)600000000000000ull, {{0xa7, 0xa6, 0x39, 0x93, 0x41, 0xcb, 0x4d, 0x67, 0x76, 0xcd, 0x94, 0xd, 0x1d, 0x6a, 0xb0, 0xac, 0xa, 0xbf, 0x56, 0x93, 0x6a, 0x35, 0x31, 0xdf, 0xe9, 0x6c, 0x23, 0x69, 0x97, 0x8e, 0x49, 0xfa}} }, + { (uint64_t)700000000000000ull, {{0x55, 0x9, 0x3e, 0x5e, 0xeb, 0xca, 0x3, 0x88, 0x48, 0xdc, 0x99, 0x7e, 0x31, 0x95, 0xec, 0xc5, 0x8f, 0xb4, 0xa5, 0x71, 0xb9, 0x52, 0x56, 0xc0, 0xff, 0x49, 0xbe, 0xd0, 0xf1, 0x65, 0x22, 0xbd}} }, + { (uint64_t)800000000000000ull, {{0xbb, 0xc6, 0x18, 0x2, 0x24, 0xaf, 0xd3, 0x38, 0xa6, 0xf4, 0xa0, 0x6b, 0x11, 0x98, 0x40, 0x68, 0xeb, 0x36, 0x35, 0xe7, 0xe5, 0x47, 0x66, 0x69, 0x78, 0x83, 0xaf, 0xbd, 0xce, 0xad, 0x2f, 0x31}} }, + { (uint64_t)900000000000000ull, {{0x61, 0x3a, 0xa1, 0x2c, 0xc0, 0xa1, 0x9b, 0xc8, 0x43, 0x63, 0x50, 0xbb, 0xc0, 0xf6, 0x16, 0x32, 0x6e, 0x64, 0x85, 0x83, 0x33, 0x4a, 0x32, 0x65, 0x16, 0x29, 0xe9, 0x5, 0xc5, 0x20, 0x62, 0x69}} }, + { (uint64_t)1000000000000000ull, {{0x52, 0xdd, 0xf8, 0x81, 0x13, 0xa0, 0xfc, 0xf2, 0x12, 0x90, 0x95, 0xc6, 0x18, 0x91, 0xbe, 0x88, 0x5c, 0x9, 0x30, 0x8, 0xeb, 0xc4, 0x65, 0xc, 0xb0, 0xee, 0xa5, 0x60, 0xcd, 0x4d, 0x75, 0x1b}} }, + { (uint64_t)2000000000000000ull, {{0x75, 0xbd, 0xfc, 0x35, 0xa6, 0xdf, 0x76, 0xe5, 0x98, 0x8e, 0xd9, 0xe3, 0x10, 0xa5, 0x89, 0x16, 0xae, 0xf0, 0xc5, 0xf0, 0x5b, 0x89, 0x22, 0xea, 0xae, 0x2c, 0xf9, 0x8f, 0x58, 0x42, 0x3c, 0xe3}} }, + { (uint64_t)3000000000000000ull, {{0x88, 0x98, 0x93, 0xe8, 0x7d, 0x56, 0x9f, 0x14, 0xb2, 0x48, 0xd1, 0xed, 0x93, 0xe8, 0xce, 0x60, 0xbb, 0xe3, 0x73, 0x69, 0xb0, 0xd6, 0xc7, 0xa1, 0x86, 0x89, 0x33, 0xd3, 0xc3, 0xda, 0x9a, 0x72}} }, + { (uint64_t)4000000000000000ull, {{0x88, 0x3e, 0xf3, 0x4b, 0xa2, 0xc1, 0x91, 0xf4, 0x9d, 0x3c, 0xc6, 0xad, 0xa0, 0xaf, 0xf1, 0xcf, 0xb1, 0x77, 0xbd, 0x9e, 0xd4, 0xb3, 0xa5, 0x37, 0x84, 0xb7, 0xf1, 0x62, 0x9b, 0xed, 0x17, 0x41}} }, + { (uint64_t)5000000000000000ull, {{0xa2, 0x90, 0x7c, 0x39, 0x84, 0xb1, 0x4a, 0xb1, 0xf4, 0xda, 0x58, 0xc2, 0xc8, 0x2d, 0x6b, 0x24, 0xf1, 0x29, 0x49, 0x9, 0x75, 0xfc, 0x4a, 0x33, 0x3d, 0x25, 0xa1, 0xf9, 0x2b, 0xc4, 0x32, 0xb6}} }, + { (uint64_t)6000000000000000ull, {{0xa0, 0x7d, 0x9f, 0x18, 0x95, 0x1f, 0xf2, 0x32, 0xcf, 0x4e, 0xc0, 0xee, 0x2f, 0xbc, 0xc3, 0xe1, 0x1b, 0x2c, 0xaf, 0xc9, 0x57, 0x65, 0x82, 0x10, 0x38, 0x1e, 0x3e, 0xe4, 0xed, 0xec, 0x2e, 0x7a}} }, + { (uint64_t)7000000000000000ull, {{0x66, 0x80, 0x21, 0xd5, 0xde, 0x8c, 0xa4, 0xc1, 0x8f, 0x5a, 0x74, 0xf2, 0x78, 0x69, 0xc4, 0xd6, 0xd4, 0x93, 0xa3, 0x30, 0x39, 0x3c, 0xf0, 0x26, 0x41, 0xff, 0xa8, 0x56, 0x7b, 0xa5, 0x36, 0x20}} }, + { (uint64_t)8000000000000000ull, {{0xe0, 0x48, 0x7a, 0xc4, 0x5a, 0x82, 0x59, 0xe3, 0xe5, 0xf2, 0xd9, 0xb8, 0xf6, 0xb8, 0xfa, 0x26, 0x9a, 0x63, 0x49, 0x71, 0xa2, 0xf7, 0xc2, 0x1a, 0x54, 0x17, 0x76, 0x81, 0xeb, 0x2, 0xbd, 0x4a}} }, + { (uint64_t)9000000000000000ull, {{0x98, 0x92, 0x6a, 0x3a, 0xf0, 0x5b, 0xf4, 0xa9, 0x8d, 0xf9, 0xf6, 0x4a, 0xe7, 0xb9, 0xda, 0x45, 0xa7, 0x6, 0xc3, 0xf8, 0x39, 0x5e, 0x47, 0x1f, 0x96, 0xed, 0x3c, 0x6, 0x6, 0xbe, 0xbb, 0x71}} }, + { (uint64_t)10000000000000000ull, {{0x80, 0xad, 0xb7, 0xd, 0x46, 0xf6, 0x3a, 0x75, 0x64, 0xa3, 0xf6, 0x71, 0xd9, 0xba, 0x95, 0x71, 0xb7, 0xf7, 0x95, 0xa9, 0x63, 0x38, 0x2a, 0x4d, 0x9f, 0xaf, 0x2d, 0x54, 0xf6, 0xc6, 0x84, 0x29}} }, + { (uint64_t)20000000000000000ull, {{0xae, 0xbd, 0x97, 0x42, 0x1f, 0x3f, 0xca, 0xe8, 0x95, 0x18, 0x60, 0xe6, 0xd9, 0xd1, 0xf3, 0xec, 0x59, 0x73, 0xa2, 0xf7, 0x66, 0x88, 0x4b, 0xfe, 0x17, 0x50, 0x79, 0x51, 0xe4, 0x62, 0xc6, 0x63}} }, + { (uint64_t)30000000000000000ull, {{0x61, 0x2, 0x6c, 0x84, 0x2a, 0x6a, 0x22, 0x25, 0x74, 0x6b, 0x19, 0x6b, 0x56, 0x89, 0xe1, 0x18, 0xf5, 0x41, 0x34, 0x15, 0x98, 0x1d, 0x7, 0x73, 0x62, 0xb2, 0xe7, 0xb9, 0xac, 0xa5, 0x28, 0x16}} }, + { (uint64_t)40000000000000000ull, {{0x52, 0x54, 0xb5, 0x78, 0xe8, 0x57, 0x9a, 0x27, 0x3b, 0x89, 0x8e, 0x65, 0x9d, 0xd3, 0xe1, 0xa1, 0xcf, 0xba, 0x12, 0x47, 0x26, 0x64, 0xbd, 0x4e, 0x7f, 0x9a, 0x13, 0xb1, 0xfc, 0xee, 0x2, 0x93}} }, + { (uint64_t)50000000000000000ull, {{0x7b, 0x2a, 0xb, 00, 0xcf, 0xdc, 0xa9, 0x51, 0x46, 0xcf, 0x80, 0x95, 0xdd, 0x2b, 0x82, 0x90, 0x91, 0xb0, 0xf2, 0xd5, 0xbb, 0xc, 0x33, 0x82, 0x2d, 0x8b, 0x43, 0x42, 0x69, 0xcd, 0x2a, 0x42}} }, + { (uint64_t)60000000000000000ull, {{0x21, 0x57, 0x4f, 0xed, 0x15, 0x1a, 0x2f, 0x9f, 0x64, 0xa4, 0x5b, 0xe2, 0x8a, 0x3a, 0xf5, 0x88, 0xe9, 0xf2, 0xd1, 0x71, 0x35, 0xa3, 0x53, 0x7f, 0x7, 0xfd, 0x6a, 0xef, 0xa2, 0x9f, 0x2, 0xaf}} }, + { (uint64_t)70000000000000000ull, {{0x1a, 0xf2, 0x41, 0xe1, 0x38, 0x27, 0x98, 0x29, 0xac, 0x6a, 0xe6, 0x2f, 0xf, 0x33, 0x20, 0x4b, 0xb2, 0x8a, 0xfd, 0x6, 0x5c, 0x42, 0x59, 0x3b, 0xdc, 0x79, 0x14, 0x85, 0x97, 0x5b, 0x26, 0x95}} }, + { (uint64_t)80000000000000000ull, {{0xa8, 0xc8, 0xb8, 0x7b, 0x51, 0x2d, 0xef, 0x9b, 0x5e, 0x50, 0xe, 0xb4, 0x98, 0xaf, 0x86, 0xaa, 0xd2, 0x46, 0x4a, 0xea, 0xe7, 0x6d, 0xb1, 0xf6, 0x5d, 0x23, 0x26, 0xce, 0x90, 0x26, 0xec, 0x69}} }, + { (uint64_t)90000000000000000ull, {{0x3d, 0x78, 0x73, 0x63, 0x95, 0xf1, 0xd7, 0xde, 0x8e, 0x16, 0xc0, 0xb5, 0xa9, 0x9f, 0x4d, 0xc4, 0xeb, 0x8f, 0x22, 0xac, 0xc1, 0x5b, 0x21, 0x42, 0x44, 0x1d, 0xbd, 0x8d, 0x2c, 0x31, 0xb9, 0xce}} }, + { (uint64_t)100000000000000000ull, {{0x27, 0x27, 0xd4, 0x93, 0x2f, 0x98, 0x39, 0xe4, 0x3b, 0x6b, 0xf5, 0xfb, 0x29, 0xa3, 0xbe, 0x4c, 0x9, 0xb, 0x6e, 0xb9, 0x31, 00, 0xbb, 0x92, 0x58, 0x1a, 0xdb, 0x8d, 0xd2, 0xb6, 0x61, 0x54}} }, + { (uint64_t)200000000000000000ull, {{0xae, 0x96, 0x78, 0x2e, 0xf2, 0xc4, 0xdf, 0x7d, 0x2e, 0x4, 0xcc, 0xf9, 0xef, 0x76, 0x23, 0x7f, 0x17, 0xc, 0x97, 0x3, 0xb4, 0x92, 0xc0, 0x78, 0x52, 0x6e, 0xb1, 0xf6, 0x85, 0x3d, 0xb1, 0x33}} }, + { (uint64_t)300000000000000000ull, {{0x17, 0x43, 0xfe, 0xab, 0x12, 0xad, 0xe5, 0xfe, 0x12, 0x53, 0x22, 0x27, 0x2f, 0xd1, 0x40, 0x6b, 0x74, 0xe8, 0x19, 0x70, 0x32, 0x68, 0x46, 0x22, 0xee, 0x79, 0xab, 0xcd, 0x94, 0x93, 0x66, 0x4c}} }, + { (uint64_t)400000000000000000ull, {{0x7, 0x9b, 0xf2, 0xa9, 0x6e, 0x16, 0x6e, 0xf9, 0xe6, 0xb2, 0x23, 0x1d, 0xb9, 0x85, 0x8b, 0x99, 0x98, 0x7f, 0x49, 0x33, 0x87, 0xde, 0xeb, 0xd5, 0x17, 0x48, 0x54, 0x9a, 0xd, 0xf7, 0xdc, 0x44}} }, + { (uint64_t)500000000000000000ull, {{0xca, 0xba, 0x97, 0x98, 0x51, 0x6d, 0xad, 0x3, 0x38, 0xd0, 0x6e, 0x10, 0x6d, 0x76, 0xa2, 0x1, 0x93, 0x7a, 0xce, 0x4c, 0x91, 0x53, 0x9e, 0x61, 0x7d, 0x89, 0x28, 0x73, 0x6, 0xa3, 0x92, 0xb1}} }, + { (uint64_t)600000000000000000ull, {{0x6b, 0x8, 0x7f, 0x48, 0xb3, 0xd7, 0xaa, 0xc9, 0x57, 0xc4, 0x52, 0xe5, 0x1a, 0x18, 0xd7, 0x26, 0xb, 0xf8, 0xc8, 0x56, 0xc4, 0xc7, 0x1e, 0x48, 0xf6, 0x49, 0xae, 00, 0x4a, 0xf6, 0x8f, 0x13}} }, + { (uint64_t)700000000000000000ull, {{0x9e, 0xed, 0x8b, 0x23, 0x1f, 0x79, 0x4c, 0x46, 0x5c, 0xbe, 0x88, 0x40, 0xd0, 0xf1, 0x6f, 0x7b, 0x9f, 0x9c, 0x6e, 0xb4, 0x9c, 0x20, 0x7d, 0xe9, 0xd8, 0x55, 0x11, 0x83, 0xd0, 0xc7, 0x6e, 0x43}} }, + { (uint64_t)800000000000000000ull, {{0x58, 0x4a, 0x78, 0x93, 0x13, 0x7e, 0xbd, 0x2, 0x8b, 0xa7, 0x59, 0x82, 0xc3, 0x39, 0xb7, 0x66, 0xaa, 0xda, 0xad, 0xf9, 0x14, 0x50, 0xf9, 0x40, 0x7d, 0x2a, 0x97, 0xd7, 0xf6, 0xb1, 0x93, 0x5e}} }, + { (uint64_t)900000000000000000ull, {{0x7, 0xce, 0x54, 0xb1, 0x18, 0x26, 0xa1, 0x75, 0x23, 0x13, 0x55, 0x1a, 00, 0x20, 0xfd, 0x79, 0x8a, 00, 0x9e, 0x20, 0xcd, 0xb2, 0x40, 0x1d, 0x52, 0x51, 0xc1, 0x55, 0x8e, 0xea, 0xd2, 0x6c}} }, + { (uint64_t)1000000000000000000ull, {{0x39, 0x80, 0x7f, 0x3d, 0xce, 0xb0, 0xa6, 0xfe, 0x34, 0xa7, 0xa1, 0xed, 0xc6, 0x9b, 0x78, 0xff, 0xbe, 0xd5, 0xa7, 0x8c, 0x6c, 0x87, 0x5d, 0xda, 0x96, 0x69, 0xdb, 0xb2, 0x95, 0x70, 0xf0, 0xf4}} }, + { (uint64_t)2000000000000000000ull, {{0xda, 0x74, 00, 0x86, 0xf1, 0x5c, 0xe8, 0x21, 0xe9, 0xd, 0x50, 0xaf, 0xcf, 0x80, 0x9c, 0x7e, 0x18, 0x51, 0x90, 0x1b, 0xa3, 0x5f, 0x9f, 0x63, 0x78, 0xd6, 0x40, 0x7c, 0xb9, 0xc7, 0xa2, 0x75}} }, + { (uint64_t)3000000000000000000ull, {{0x7, 0xa1, 0x75, 0x63, 0xae, 0xf5, 0xcf, 0xd0, 0x36, 0xfa, 0x64, 0xd4, 0xb1, 0x97, 0xa9, 0x51, 0xc0, 0xd2, 0x87, 0x2b, 0xd, 0xb6, 0xf9, 0xbe, 0x47, 0xe6, 0x7c, 0xa6, 0xb5, 0x35, 0xe2, 0x6e}} }, + { (uint64_t)4000000000000000000ull, {{0xe3, 0x49, 0xf7, 0xeb, 0xe5, 0x11, 0x39, 0xfe, 0xd5, 0x69, 0x40, 0x37, 0xd1, 0x14, 0xb7, 0xbd, 0x45, 0xdd, 0xa, 0x6a, 0xf0, 0x4b, 0x62, 0xec, 0xa4, 0xd8, 0xcd, 0x55, 0x2a, 0x14, 0xe3, 0xfb}} }, + { (uint64_t)5000000000000000000ull, {{0x8d, 0x59, 0x7e, 0xa9, 0xf5, 0x79, 0x9a, 0x4d, 0x15, 0x3d, 0x82, 0xd6, 0xf7, 0xbe, 0xa0, 0x2e, 0x52, 0x40, 0xa2, 0xc8, 0x9b, 0x4, 0x1e, 0x6, 0x2f, 0x37, 0xbc, 0x7b, 0x82, 0xa0, 0xac, 0x55}} }, + { (uint64_t)6000000000000000000ull, {{0xa3, 0x43, 0xa7, 0xe1, 0x14, 0x4d, 0x33, 0x50, 0xf, 0x3e, 0xfd, 0x38, 0x15, 0x82, 0xdd, 0xc5, 0xd0, 0x18, 0x3e, 0x5d, 0xcf, 0x8a, 0xfa, 0x64, 0xbb, 0x67, 0x6c, 0x97, 0x3e, 0x3d, 0x1a, 0xb1}} }, + { (uint64_t)7000000000000000000ull, {{0x89, 0xe9, 0x3e, 0xe9, 0xf2, 0x4d, 0x72, 0x61, 0xe5, 0x44, 0xca, 0x8f, 0x9, 0xa7, 0x40, 0x4e, 0xe3, 0xa9, 0xe, 0xe2, 0x50, 0x7d, 0xda, 0xcf, 0x41, 0x2a, 0x58, 0xc, 0x9, 0x65, 0x1c, 0x53}} }, + { (uint64_t)8000000000000000000ull, {{0xc5, 0x94, 0x10, 0x81, 0x54, 0x69, 0xf4, 0x59, 0xd1, 0x5a, 0x6f, 0xe3, 0xf2, 0xa1, 0x1b, 0xa6, 0x31, 0x12, 0xfa, 0xaa, 0xc5, 0x3d, 0xbc, 0x52, 0x5d, 0x3c, 0xfa, 0xb1, 0xfa, 0x9c, 0x3d, 0xdb}} }, + { (uint64_t)9000000000000000000ull, {{0x9d, 0xe7, 0xcb, 0xb, 0x8d, 0x7b, 0xac, 0x47, 0xff, 0xd3, 0x93, 0x1b, 0xcd, 0x82, 0xcd, 0xd5, 0x35, 0xc, 0x29, 0x34, 0xb1, 0x6e, 0xb, 0x64, 0x32, 0xab, 0xf7, 0xcb, 0x4b, 0x5c, 0x37, 0x6d}} }, + { (uint64_t)10000000000000000000ull, {{0x65, 0x8d, 0x1, 0x37, 0x6d, 0x18, 0x63, 0xe7, 0x7b, 0x9, 0x6f, 0x98, 0xe6, 0xe5, 0x13, 0xc2, 0x4, 0x10, 0xf5, 0xc7, 0xfb, 0x18, 0xa6, 0xe5, 0x9a, 0x52, 0x66, 0x84, 0x5c, 0xd9, 0xb1, 0xe3}} }, }; namespace rct { From 4cd881369a836406240ff1295739995362c9ce62 Mon Sep 17 00:00:00 2001 From: Hom DX Date: Fri, 23 Nov 2018 00:52:22 +0300 Subject: [PATCH 0313/1007] Updated dependencies Cmake 3.13, CPPZMQ 4.3.0, OPENSSL 1.1.0j --- Dockerfile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 86d833a98..0728c6ce8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,9 +25,9 @@ RUN set -ex && \ WORKDIR /usr/local #Cmake -ARG CMAKE_VERSION=3.12.1 -ARG CMAKE_VERSION_DOT=v3.12 -ARG CMAKE_HASH=c53d5c2ce81d7a957ee83e3e635c8cda5dfe20c9d501a4828ee28e1615e57ab2 +ARG CMAKE_VERSION=3.13.0 +ARG CMAKE_VERSION_DOT=v3.13 +ARG CMAKE_HASH=4058b2f1a53c026564e8936698d56c3b352d90df067b195cb749a97a3d273c90 RUN set -ex \ && curl -s -O https://cmake.org/files/${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION}.tar.gz \ && echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}.tar.gz" | sha256sum -c \ @@ -51,8 +51,8 @@ RUN set -ex \ ENV BOOST_ROOT /usr/local/boost_${BOOST_VERSION} # OpenSSL -ARG OPENSSL_VERSION=1.1.0h -ARG OPENSSL_HASH=5835626cde9e99656585fc7aaa2302a73a7e1340bf8c14fd635a62c66802a517 +ARG OPENSSL_VERSION=1.1.0j +ARG OPENSSL_HASH=31bec6c203ce1a8e93d5994f4ed304c63ccf07676118b6634edded12ad1b3246 RUN set -ex \ && curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ @@ -78,8 +78,8 @@ RUN set -ex \ && ldconfig # zmq.hpp -ARG CPPZMQ_VERSION=v4.2.3 -ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6 +ARG CPPZMQ_VERSION=v4.3.0 +ARG CPPZMQ_HASH=213da0b04ae3b4d846c9abc46bab87f86bfb9cf4 RUN set -ex \ && git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \ && cd cppzmq \ From 3002307418b9ea904a078f726ed8c13306d0f6b8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 13:11:40 +0000 Subject: [PATCH 0314/1007] tests: slow_memmem now returns size_t Makes more sense than uint64_t for an offset, and agrees with the %zu used to print results. Found by codacy.com --- src/rpc/core_rpc_server.cpp | 2 +- tests/unit_tests/slow_memmem.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index df9eee781..d7968731a 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1026,7 +1026,7 @@ namespace cryptonote //------------------------------------------------------------------------------------------------------------------------------ // equivalent of strstr, but with arbitrary bytes (ie, NULs) // This does not differentiate between "not found" and "found at offset 0" - uint64_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen) + size_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen) { const void* buf = start_buff; const void* end=(const char*)buf+buflen; diff --git a/tests/unit_tests/slow_memmem.cpp b/tests/unit_tests/slow_memmem.cpp index 1c67f5b58..436259bee 100644 --- a/tests/unit_tests/slow_memmem.cpp +++ b/tests/unit_tests/slow_memmem.cpp @@ -45,7 +45,7 @@ //#define VERBOSE #ifdef TEST_ORIGINAL -uint64_t slow_memmem_original(void* start_buff, size_t buflen,void* pat,size_t patlen) +size_t slow_memmem_original(void* start_buff, size_t buflen,void* pat,size_t patlen) { void* buf = start_buff; void* end=(char*)buf+buflen-patlen; @@ -63,7 +63,7 @@ uint64_t slow_memmem_original(void* start_buff, size_t buflen,void* pat,size_t p #define slow_memmem slow_memmem_original #else namespace cryptonote { - uint64_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen); + size_t slow_memmem(const void* start_buff, size_t buflen,const void* pat,size_t patlen); } using namespace cryptonote; #endif @@ -73,7 +73,7 @@ static const struct { const char *buf; size_t patlen; const char *pat; - uint64_t res; + size_t res; } T[]={ {0,"",0,"",0}, {1,"",0,"",0}, @@ -117,7 +117,7 @@ TEST(slowmem,Success) memcpy(buf,T[n].buf,T[n].buflen); void *pat=malloc(T[n].patlen); memcpy(pat,T[n].pat,T[n].patlen); - uint64_t res=slow_memmem(buf,T[n].buflen,pat,T[n].patlen); + size_t res=slow_memmem(buf,T[n].buflen,pat,T[n].patlen); free(pat); free(buf); ASSERT_EQ(res,T[n].res); From 611639710d9f3665999b4ec71a52efc73aca4853 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 13:25:15 +0000 Subject: [PATCH 0315/1007] a few minor (but easy) performance tweaks Found by codacy.com --- src/common/base58.cpp | 2 +- src/common/base58.h | 2 +- src/cryptonote_basic/cryptonote_basic_impl.cpp | 2 +- src/cryptonote_basic/cryptonote_basic_impl.h | 2 +- src/cryptonote_core/blockchain.cpp | 6 +++--- src/cryptonote_core/cryptonote_tx_utils.cpp | 6 +++--- src/cryptonote_core/cryptonote_tx_utils.h | 6 +++--- src/ringct/rctSigs.cpp | 4 ++-- src/ringct/rctSigs.h | 4 ++-- src/wallet/wallet2.cpp | 4 ++-- src/wallet/wallet2.h | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/common/base58.cpp b/src/common/base58.cpp index b28a04f20..432105da4 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -235,7 +235,7 @@ namespace tools return encode(buf); } - bool decode_addr(std::string addr, uint64_t& tag, std::string& data) + bool decode_addr(const std::string &addr, uint64_t& tag, std::string& data) { std::string addr_data; bool r = decode(addr, addr_data); diff --git a/src/common/base58.h b/src/common/base58.h index 02ca96956..69611859d 100644 --- a/src/common/base58.h +++ b/src/common/base58.h @@ -41,6 +41,6 @@ namespace tools bool decode(const std::string& enc, std::string& data); std::string encode_addr(uint64_t tag, const std::string& data); - bool decode_addr(std::string addr, uint64_t& tag, std::string& data); + bool decode_addr(const std::string &addr, uint64_t& tag, std::string& data); } } diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index c4e10851e..f10e0d86e 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -322,7 +322,7 @@ namespace cryptonote { } //-------------------------------------------------------------------------------- -bool parse_hash256(const std::string str_hash, crypto::hash& hash) +bool parse_hash256(const std::string &str_hash, crypto::hash& hash) { std::string buf; bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index c804a88fa..0b8131a7a 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -124,5 +124,5 @@ namespace cryptonote { bool operator ==(const cryptonote::block& a, const cryptonote::block& b); } -bool parse_hash256(const std::string str_hash, crypto::hash& hash); +bool parse_hash256(const std::string &str_hash, crypto::hash& hash); diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index e80e3f66c..104ad4de2 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -929,7 +929,7 @@ bool Blockchain::rollback_blockchain_switching(std::list& original_chain, m_hardfork->reorganize_from_chain_height(rollback_height); MINFO("Rollback to height " << rollback_height << " was successful."); - if (original_chain.size()) + if (!original_chain.empty()) { MINFO("Restoration to previous blockchain successful as well."); } @@ -1484,7 +1484,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id // if block to be added connects to known blocks that aren't part of the // main chain -- that is, if we're adding on to an alternate chain - if(alt_chain.size()) + if(!alt_chain.empty()) { // make sure alt chain doesn't somehow start past the end of the main chain CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height"); @@ -1857,7 +1857,7 @@ bool Blockchain::find_blockchain_supplement(const std::list& qbloc // make sure the request includes at least the genesis block, otherwise // how can we expect to sync from the client that the block list came from? - if(!qblock_ids.size()) + if(qblock_ids.empty()) { MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << ", dropping connection"); return false; diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 4fc2736a6..f443d638c 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -198,7 +198,7 @@ namespace cryptonote return addr.m_view_public_key; } //--------------------------------------------------------------- - bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct, rct::RangeProofType range_proof_type, rct::multisig_out *msout, bool shuffle_outs) + bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct, rct::RangeProofType range_proof_type, rct::multisig_out *msout, bool shuffle_outs) { hw::device &hwdev = sender_account_keys.get_device(); @@ -610,7 +610,7 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool rct, rct::RangeProofType range_proof_type, rct::multisig_out *msout) + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool rct, rct::RangeProofType range_proof_type, rct::multisig_out *msout) { hw::device &hwdev = sender_account_keys.get_device(); hwdev.open_tx(tx_key); @@ -633,7 +633,7 @@ namespace cryptonote return r; } //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, std::vector& sources, const std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time) + bool construct_tx(const account_keys& sender_account_keys, std::vector& sources, const std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time) { std::unordered_map subaddresses; subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0}; diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index f2cf7b6ca..87edafe9d 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -89,9 +89,9 @@ namespace cryptonote //--------------------------------------------------------------- crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional& change_addr); - bool construct_tx(const account_keys& sender_account_keys, std::vector &sources, const std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time); - bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct = false, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL, bool shuffle_outs = true); - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, std::vector extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool rct = false, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL); + bool construct_tx(const account_keys& sender_account_keys, std::vector &sources, const std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time); + bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct = false, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL, bool shuffle_outs = true); + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool rct = false, rct::RangeProofType range_proof_type = rct::RangeProofBorromean, rct::multisig_out *msout = NULL); bool generate_genesis_block( block& bl diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index dccd18867..5ad785c96 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -444,7 +444,7 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - mgSig proveRctMG(const key &message, const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, key txnFeeKey, hw::device &hwdev) { + mgSig proveRctMG(const key &message, const ctkeyM & pubs, const ctkeyV & inSk, const ctkeyV &outSk, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, const key &txnFeeKey, hw::device &hwdev) { mgSig mg; //setup vars size_t cols = pubs.size(); @@ -534,7 +534,7 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFeeKey, const key &message) { + bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, const key &txnFeeKey, const key &message) { PERF_TIMER(verRctMG); //setup vars size_t cols = pubs.size(); diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index b67a0b992..459edc600 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -96,9 +96,9 @@ namespace rct { // this shows that sum inputs = sum outputs //Ver: // verifies the above sig is created corretly - mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, key txnFee, const key &message, hw::device &hwdev); + mgSig proveRctMG(const ctkeyM & pubs, const ctkeyV & inSk, const keyV &outMasks, const ctkeyV & outPk, const multisig_kLRki *kLRki, key *mscout, unsigned int index, const key &txnFee, const key &message, hw::device &hwdev); mgSig proveRctMGSimple(const key & message, const ctkeyV & pubs, const ctkey & inSk, const key &a , const key &Cout, const multisig_kLRki *kLRki, key *mscout, unsigned int index, hw::device &hwdev); - bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFee, const key &message); + bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, const key &txnFee, const key &message); bool verRctMGSimple(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C); //These functions get keys from blockchain diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 129b96733..0db110c00 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4292,7 +4292,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password, return make_multisig(password, secret_keys, public_keys, threshold); } -bool wallet2::finalize_multisig(const epee::wipeable_string &password, std::unordered_set pkeys, std::vector signers) +bool wallet2::finalize_multisig(const epee::wipeable_string &password, const std::unordered_set &pkeys, std::vector signers) { exchange_multisig_keys(password, pkeys, signers); return true; @@ -10420,7 +10420,7 @@ const std::pair, std::vector>& w return m_account_tags; } -void wallet2::set_account_tag(const std::set account_indices, const std::string& tag) +void wallet2::set_account_tag(const std::set &account_indices, const std::string& tag) { for (uint32_t account_index : account_indices) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index eb0763131..bcd975d3f 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -592,7 +592,7 @@ namespace tools /*! * \brief Finalizes creation of a multisig wallet */ - bool finalize_multisig(const epee::wipeable_string &password, std::unordered_set pkeys, std::vector signers); + bool finalize_multisig(const epee::wipeable_string &password, const std::unordered_set &pkeys, std::vector signers); /*! * Get a packaged multisig information string */ @@ -1045,7 +1045,7 @@ namespace tools * \param account_indices Indices of accounts. * \param tag Tag's name. If empty, the accounts become untagged. */ - void set_account_tag(const std::set account_indices, const std::string& tag); + void set_account_tag(const std::set &account_indices, const std::string& tag); /*! * \brief Set the label of the given tag. * \param tag Tag's name (which must be non-empty). From d4f50cb109c45c1f50700cbe2e88ec891eb7d469 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 13:47:51 +0000 Subject: [PATCH 0316/1007] remove some unused code Found by codacy.com --- .../blockchain_import.cpp | 2 +- src/common/dns_utils.cpp | 2 +- src/cryptonote_core/cryptonote_core.cpp | 8 +-- src/cryptonote_core/cryptonote_core.h | 3 +- src/daemon/core.h | 17 +---- src/device/device_ledger.cpp | 2 - src/rpc/daemon_messages.cpp | 72 ------------------- src/simplewallet/simplewallet.cpp | 1 - src/wallet/wallet2.cpp | 5 -- tests/core_tests/chaingen.h | 2 +- tests/core_tests/transaction_tests.cpp | 3 - tests/unit_tests/mnemonics.cpp | 1 - tests/unit_tests/multisig.cpp | 2 +- tests/unit_tests/ringct.cpp | 2 - 14 files changed, 8 insertions(+), 114 deletions(-) diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index eae078ea2..2a8a6f494 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -764,7 +764,7 @@ int main(int argc, char* argv[]) #else const GetCheckpointsCallback& get_checkpoints = nullptr; #endif - if (!core.init(vm, nullptr, nullptr, get_checkpoints)) + if (!core.init(vm, nullptr, get_checkpoints)) { std::cerr << "Failed to initialize core" << ENDL; return 1; diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 606a2c7b7..4aa777c4d 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -305,7 +305,7 @@ std::vector DNSResolver::get_record(const std::string& url, int rec // call DNS resolver, blocking. if return value not zero, something went wrong if (!ub_resolve(m_data->m_ub_context, string_copy(url.c_str()), record_type, DNS_CLASS_IN, &result)) { - dnssec_available = (result->secure || (!result->secure && result->bogus)); + dnssec_available = (result->secure || result->bogus); dnssec_valid = result->secure && !result->bogus; if (result->havedata) { diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 10ab3fe65..c164ce937 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -389,7 +389,7 @@ namespace cryptonote return m_blockchain_storage.get_alternative_blocks_count(); } //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const char *config_subdir, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */) + bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options, const GetCheckpointsCallback& get_checkpoints/* = nullptr */) { start_time = std::time(nullptr); @@ -399,10 +399,6 @@ namespace cryptonote m_nettype = FAKECHAIN; } bool r = handle_command_line(vm); - std::string m_config_folder_mempool = m_config_folder; - - if (config_subdir) - m_config_folder_mempool = m_config_folder_mempool + "/" + config_subdir; std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type); std::string db_sync_mode = command_line::get_arg(vm, cryptonote::arg_db_sync_mode); @@ -834,7 +830,7 @@ namespace cryptonote TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_incoming_tx_lock); - struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; }; + struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; }; std::vector results(tx_blobs.size()); tvc.resize(tx_blobs.size()); diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 2eb6c842b..a8bd688c3 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -242,13 +242,12 @@ namespace cryptonote * a miner instance with parameters given on the command line (or defaults) * * @param vm command line parameters - * @param config_subdir subdirectory for config storage * @param test_options configuration options for testing * @param get_checkpoints if set, will be called to get checkpoints data, must return checkpoints data pointer and size or nullptr if there ain't any checkpoints for specific network type * * @return false if one of the init steps fails, otherwise true */ - bool init(const boost::program_options::variables_map& vm, const char *config_subdir = NULL, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr); + bool init(const boost::program_options::variables_map& vm, const test_options *test_options = NULL, const GetCheckpointsCallback& get_checkpoints = nullptr); /** * @copydoc Blockchain::reset_and_set_genesis_block diff --git a/src/daemon/core.h b/src/daemon/core.h index d1defd573..c15d8d236 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -67,31 +67,16 @@ class t_core final m_core.set_cryptonote_protocol(&protocol); } - std::string get_config_subdir() const - { - bool testnet = command_line::get_arg(m_vm_HACK, cryptonote::arg_testnet_on); - bool stagenet = command_line::get_arg(m_vm_HACK, cryptonote::arg_stagenet_on); - bool mainnet = !testnet && !stagenet; - std::string port = command_line::get_arg(m_vm_HACK, nodetool::arg_p2p_bind_port); - if ((mainnet && port != std::to_string(::config::P2P_DEFAULT_PORT)) - || (testnet && port != std::to_string(::config::testnet::P2P_DEFAULT_PORT)) - || (stagenet && port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) { - return port; - } - return std::string(); - } - bool run() { //initialize core here MGINFO("Initializing core..."); - std::string config_subdir = get_config_subdir(); #if defined(PER_BLOCK_CHECKPOINT) const cryptonote::GetCheckpointsCallback& get_checkpoints = blocks::GetCheckpointsData; #else const cryptonote::GetCheckpointsCallback& get_checkpoints = nullptr; #endif - if (!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str(), nullptr, get_checkpoints)) + if (!m_core.init(m_vm_HACK, nullptr, get_checkpoints)) { return false; } diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 0a86e6987..bfb41bbe4 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -789,8 +789,6 @@ namespace hw { } #ifdef DEBUG_HWDEVICE - bool recover_x = recover; - const crypto::secret_key recovery_key_x = recovery_key; crypto::public_key pub_x; crypto::secret_key sec_x; #endif diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index fa848cff4..7c7442014 100644 --- a/src/rpc/daemon_messages.cpp +++ b/src/rpc/daemon_messages.cpp @@ -177,8 +177,6 @@ rapidjson::Value GetTransactions::Request::toJson(rapidjson::Document& doc) cons { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, tx_hashes, tx_hashes); return val; @@ -193,8 +191,6 @@ rapidjson::Value GetTransactions::Response::toJson(rapidjson::Document& doc) con { rapidjson::Value val(rapidjson::kObjectType); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, txs, txs); INSERT_INTO_JSON_OBJECT(val, doc, missed_hashes, missed_hashes); @@ -212,8 +208,6 @@ rapidjson::Value KeyImagesSpent::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images); return val; @@ -228,8 +222,6 @@ rapidjson::Value KeyImagesSpent::Response::toJson(rapidjson::Document& doc) cons { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, spent_status, spent_status); return val; @@ -245,8 +237,6 @@ rapidjson::Value GetTxGlobalOutputIndices::Request::toJson(rapidjson::Document& { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, tx_hash, tx_hash); return val; @@ -261,8 +251,6 @@ rapidjson::Value GetTxGlobalOutputIndices::Response::toJson(rapidjson::Document& { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, output_indices, output_indices); return val; @@ -277,8 +265,6 @@ rapidjson::Value SendRawTx::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, tx, tx); INSERT_INTO_JSON_OBJECT(val, doc, relay, relay); @@ -295,8 +281,6 @@ rapidjson::Value SendRawTx::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, relayed, relayed); return val; @@ -312,8 +296,6 @@ rapidjson::Value StartMining::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, miner_address, miner_address); INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count); INSERT_INTO_JSON_OBJECT(val, doc, do_background_mining, do_background_mining); @@ -372,8 +354,6 @@ rapidjson::Value MiningStatus::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, active, active); INSERT_INTO_JSON_OBJECT(val, doc, speed, speed); INSERT_INTO_JSON_OBJECT(val, doc, threads_count, threads_count); @@ -406,8 +386,6 @@ rapidjson::Value GetInfo::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, info, info); return val; @@ -423,8 +401,6 @@ rapidjson::Value SaveBC::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - return val; } @@ -436,8 +412,6 @@ rapidjson::Value SaveBC::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - return val; } @@ -450,8 +424,6 @@ rapidjson::Value GetBlockHash::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, height, height); return val; @@ -466,8 +438,6 @@ rapidjson::Value GetBlockHash::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, hash, hash); return val; @@ -483,8 +453,6 @@ rapidjson::Value GetLastBlockHeader::Request::toJson(rapidjson::Document& doc) c { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - return val; } @@ -496,8 +464,6 @@ rapidjson::Value GetLastBlockHeader::Response::toJson(rapidjson::Document& doc) { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, header, header); return val; @@ -513,8 +479,6 @@ rapidjson::Value GetBlockHeaderByHash::Request::toJson(rapidjson::Document& doc) { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, hash, hash); return val; @@ -529,8 +493,6 @@ rapidjson::Value GetBlockHeaderByHash::Response::toJson(rapidjson::Document& doc { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, header, header); return val; @@ -546,8 +508,6 @@ rapidjson::Value GetBlockHeaderByHeight::Request::toJson(rapidjson::Document& do { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, height, height); return val; @@ -562,8 +522,6 @@ rapidjson::Value GetBlockHeaderByHeight::Response::toJson(rapidjson::Document& d { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, header, header); return val; @@ -579,8 +537,6 @@ rapidjson::Value GetBlockHeadersByHeight::Request::toJson(rapidjson::Document& d { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, heights, heights); return val; @@ -595,8 +551,6 @@ rapidjson::Value GetBlockHeadersByHeight::Response::toJson(rapidjson::Document& { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, headers, headers); return val; @@ -612,8 +566,6 @@ rapidjson::Value GetPeerList::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - return val; } @@ -625,8 +577,6 @@ rapidjson::Value GetPeerList::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, white_list, white_list); INSERT_INTO_JSON_OBJECT(val, doc, gray_list, gray_list); @@ -679,8 +629,6 @@ rapidjson::Value GetTransactionPool::Response::toJson(rapidjson::Document& doc) { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, transactions, transactions); INSERT_INTO_JSON_OBJECT(val, doc, key_images, key_images); @@ -698,8 +646,6 @@ rapidjson::Value HardForkInfo::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, version, version); return val; @@ -714,8 +660,6 @@ rapidjson::Value HardForkInfo::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, info, info); return val; @@ -731,8 +675,6 @@ rapidjson::Value GetOutputHistogram::Request::toJson(rapidjson::Document& doc) c { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts); INSERT_INTO_JSON_OBJECT(val, doc, min_count, min_count); INSERT_INTO_JSON_OBJECT(val, doc, max_count, max_count); @@ -755,8 +697,6 @@ rapidjson::Value GetOutputHistogram::Response::toJson(rapidjson::Document& doc) { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, histogram, histogram); return val; @@ -772,8 +712,6 @@ rapidjson::Value GetOutputKeys::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, outputs, outputs); return val; @@ -788,8 +726,6 @@ rapidjson::Value GetOutputKeys::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, keys, keys); return val; @@ -814,8 +750,6 @@ rapidjson::Value GetRPCVersion::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, version, version); return val; @@ -830,8 +764,6 @@ rapidjson::Value GetFeeEstimate::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, num_grace_blocks, num_grace_blocks); return val; @@ -846,8 +778,6 @@ rapidjson::Value GetFeeEstimate::Response::toJson(rapidjson::Document& doc) cons { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); - INSERT_INTO_JSON_OBJECT(val, doc, estimated_base_fee, estimated_base_fee); INSERT_INTO_JSON_OBJECT(val, doc, fee_mask, fee_mask); INSERT_INTO_JSON_OBJECT(val, doc, size_scale, size_scale); @@ -867,7 +797,6 @@ void GetFeeEstimate::Response::fromJson(rapidjson::Value& val) rapidjson::Value GetOutputDistribution::Request::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); INSERT_INTO_JSON_OBJECT(val, doc, amounts, amounts); INSERT_INTO_JSON_OBJECT(val, doc, from_height, from_height); @@ -888,7 +817,6 @@ void GetOutputDistribution::Request::fromJson(rapidjson::Value& val) rapidjson::Value GetOutputDistribution::Response::toJson(rapidjson::Document& doc) const { auto val = Message::toJson(doc); - auto& al = doc.GetAllocator(); INSERT_INTO_JSON_OBJECT(val, doc, status, status); INSERT_INTO_JSON_OBJECT(val, doc, distributions, distributions); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..181650918 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -6733,7 +6733,6 @@ static std::string get_human_readable_timestamp(uint64_t ts) gmtime_r(&tt, &tm); #endif uint64_t now = time(NULL); - uint64_t diff = ts > now ? ts - now : now - ts; strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm); return std::string(buffer); } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 0db110c00..54045db5f 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1356,8 +1356,6 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi //---------------------------------------------------------------------------------------------------- void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::hash &txid, tx_cache_data &tx_cache_data) const { - const cryptonote::account_keys& keys = m_account.get_keys(); - if(!parse_tx_extra(tx.extra, tx_cache_data.tx_extra_fields)) { // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key @@ -8105,7 +8103,6 @@ void wallet2::light_wallet_get_address_txs() // for balance calculation uint64_t wallet_total_sent = 0; - uint64_t wallet_total_unlocked_sent = 0; // txs in pool std::vector pool_txs; @@ -11327,7 +11324,6 @@ cryptonote::blobdata wallet2::export_multisig() for (size_t n = 0; n < m_transfers.size(); ++n) { transfer_details &td = m_transfers[n]; - const std::vector additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx); crypto::key_image ki; td.m_multisig_k.clear(); info[n].m_LR.clear(); @@ -11356,7 +11352,6 @@ cryptonote::blobdata wallet2::export_multisig() boost::archive::portable_binary_oarchive ar(oss); ar << info; - std::string magic(MULTISIG_EXPORT_FILE_MAGIC, strlen(MULTISIG_EXPORT_FILE_MAGIC)); const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; std::string header; header += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 6b9277a30..b380aca01 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -511,7 +511,7 @@ inline bool do_replay_events(std::vector& events) // FIXME: make sure that vm has arg_testnet_on set to true or false if // this test needs for it to be so. get_test_options gto; - if (!c.init(vm, NULL, >o.test_options)) + if (!c.init(vm, >o.test_options)) { MERROR("Failed to init core"); return false; diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index 3c6954bc6..810dec6fc 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -54,9 +54,6 @@ bool test_transaction_generation_and_ring_signature() account_base miner_acc6; miner_acc6.generate(); - std::string add_str = miner_acc3.get_public_address_str(MAINNET); - - account_base rv_acc; rv_acc.generate(); account_base rv_acc2; diff --git a/tests/unit_tests/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp index 0b74a6b94..4dc2d931e 100644 --- a/tests/unit_tests/mnemonics.cpp +++ b/tests/unit_tests/mnemonics.cpp @@ -75,7 +75,6 @@ namespace */ void test_language(const Language::Base &language) { - const std::vector &word_list = language.get_word_list(); epee::wipeable_string w_seed = "", w_return_seed = ""; std::string seed, return_seed; // Generate a random seed without checksum diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp index 7268f2690..eb3196863 100644 --- a/tests/unit_tests/multisig.cpp +++ b/tests/unit_tests/multisig.cpp @@ -112,7 +112,7 @@ static void make_wallets(std::vector& wallets, unsigned int M) } for (auto& wallet: wallets) { - ASSERT_FALSE(wallet.multisig() || wallet.multisig() || wallet.multisig()); + ASSERT_FALSE(wallet.multisig()); } std::vector mxis; diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 52bdb00cf..ccef5f3e7 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -968,8 +968,6 @@ static rctSig make_sig() #define TEST_rctSig_elements(name, op) \ TEST(ringct, rctSig_##name) \ { \ - const uint64_t inputs[] = {1000, 1000}; \ - const uint64_t outputs[] = {1000, 1000}; \ rct::rctSig sig = make_sig(); \ ASSERT_TRUE(rct::verRct(sig)); \ op; \ From 5d9915ab9e18deed74d44676897295813d71f553 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 13:51:58 +0000 Subject: [PATCH 0317/1007] cryptonote: fix get_unit for non default settings Found by codacy.com --- src/cryptonote_basic/cryptonote_format_utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index e26aac76b..c2e6cbe27 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -883,7 +883,7 @@ namespace cryptonote { if (decimal_point == (unsigned int)-1) decimal_point = default_decimal_point; - switch (std::atomic_load(&default_decimal_point)) + switch (decimal_point) { case 12: return "monero"; @@ -896,7 +896,7 @@ namespace cryptonote case 0: return "piconero"; default: - ASSERT_MES_AND_THROW("Invalid decimal point specification: " << default_decimal_point); + ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point); } } //--------------------------------------------------------------- From 0dac3c6428a739771795496bb74066b154929ab2 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 14:08:28 +0000 Subject: [PATCH 0318/1007] unit_tests: do not rethrow a copy of an exception Found by codacy.com --- tests/unit_tests/subaddress.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/subaddress.cpp b/tests/unit_tests/subaddress.cpp index 8ff4c5f0d..67802d736 100644 --- a/tests/unit_tests/subaddress.cpp +++ b/tests/unit_tests/subaddress.cpp @@ -49,7 +49,7 @@ class WalletSubaddress : public ::testing::Test catch (const std::exception& e) { LOG_ERROR("failed to generate wallet: " << e.what()); - throw e; + throw; } w1.add_subaddress_account(test_label); From 1a0733e534dee0dae140e38a789c3ab5008e7844 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 14:14:54 +0000 Subject: [PATCH 0319/1007] windows_service: fix memory leak Found by codacy.com --- src/daemonizer/windows_service.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp index b344e1a4b..1302fa578 100644 --- a/src/daemonizer/windows_service.cpp +++ b/src/daemonizer/windows_service.cpp @@ -70,8 +70,9 @@ namespace { } else { - return std::string{p_error_text}; + std::string ret{p_error_text}; LocalFree(p_error_text); + return ret; } } From aee7a4e3642e384c05d9721deb449b39f91857eb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 14:20:08 +0000 Subject: [PATCH 0320/1007] wallet_rpc_server: do not use RPC data if the call failed Found by codacy.com --- src/wallet/wallet_rpc_server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 0eb09b9f1..d7dc2914e 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -2891,7 +2891,8 @@ namespace tools cryptonote::COMMAND_RPC_GET_HEIGHT::response hres; hres.height = 0; bool r = wal->invoke_http_json("/getheight", hreq, hres); - wal->set_refresh_from_block_height(hres.height); + if (r) + wal->set_refresh_from_block_height(hres.height); crypto::secret_key dummy_key; try { wal->generate(wallet_file, req.password, dummy_key, false, false); From 3de7d52f7cdbf8cab4f9b4b1acd99dd989819917 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 23 Nov 2018 15:55:14 +0000 Subject: [PATCH 0321/1007] unit_tests: fix malloc/delete mismatch --- tests/unit_tests/notify.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index edc4eabdf..105d21ca8 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -49,7 +49,7 @@ TEST(notify, works) tmp = "/tmp"; static const char *filename = "monero-notify-unit-test-XXXXXX"; const size_t len = strlen(tmp) + 1 + strlen(filename); - std::unique_ptr name_template_((char*)malloc(len + 1)); + std::unique_ptr name_template_(new char[len + 1]); char *name_template = name_template_.get(); ASSERT_TRUE(name_template != NULL); snprintf(name_template, len + 1, "%s/%s", tmp, filename); From 9b5efad29474416427cfb9b6a696b5dcb57cc919 Mon Sep 17 00:00:00 2001 From: stoffu Date: Sat, 24 Nov 2018 08:25:38 +0900 Subject: [PATCH 0322/1007] simplewallet: enable donation on testnet/stagenet for easier testing --- src/simplewallet/simplewallet.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..6b7681893 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -5942,12 +5942,6 @@ bool simple_wallet::sweep_below(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector &args_) { - if(m_wallet->nettype() != cryptonote::MAINNET) - { - fail_msg_writer() << tr("donations are not enabled on the testnet or on the stagenet"); - return true; - } - std::vector local_args = args_; if(local_args.empty() || local_args.size() > 5) { @@ -5969,11 +5963,30 @@ bool simple_wallet::donate(const std::vector &args_) amount_str = local_args.back(); local_args.pop_back(); // push back address, amount, payment id - local_args.push_back(MONERO_DONATION_ADDR); + std::string address_str; + if (m_wallet->nettype() != cryptonote::MAINNET) + { + // if not mainnet, convert donation address string to the relevant network type + address_parse_info info; + if (!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, MONERO_DONATION_ADDR)) + { + fail_msg_writer() << tr("Failed to parse donation address: ") << MONERO_DONATION_ADDR; + return true; + } + address_str = cryptonote::get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address); + } + else + { + address_str = MONERO_DONATION_ADDR; + } + local_args.push_back(address_str); local_args.push_back(amount_str); if (!payment_id_str.empty()) local_args.push_back(payment_id_str); - message_writer() << (boost::format(tr("Donating %s %s to The Monero Project (donate.getmonero.org or %s).")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % MONERO_DONATION_ADDR).str(); + if (m_wallet->nettype() == cryptonote::MAINNET) + message_writer() << (boost::format(tr("Donating %s %s to The Monero Project (donate.getmonero.org or %s).")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % MONERO_DONATION_ADDR).str(); + else + message_writer() << (boost::format(tr("Donating %s %s to %s.")) % amount_str % cryptonote::get_unit(cryptonote::get_default_decimal_point()) % address_str).str(); transfer(local_args); return true; } From 2be31b4c9ceb4fde1a3968ab0ae2fa4d33facc5d Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 24 Nov 2018 10:52:20 +0000 Subject: [PATCH 0323/1007] blockchain_blackball: spot when all outputs of an amount are spent --- .../blockchain_blackball.cpp | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index d2ce5cf76..73819bd25 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -59,6 +59,7 @@ static MDB_dbi dbi_relative_rings; static MDB_dbi dbi_outputs; static MDB_dbi dbi_processed_txidx; static MDB_dbi dbi_spent; +static MDB_dbi dbi_per_amount; static MDB_dbi dbi_ring_instances; static MDB_dbi dbi_stats; static MDB_env *env = NULL; @@ -238,7 +239,7 @@ static void init(std::string cache_filename) dbr = mdb_env_create(&env); CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LDMB environment: " + std::string(mdb_strerror(dbr))); - dbr = mdb_env_set_maxdbs(env, 6); + dbr = mdb_env_set_maxdbs(env, 7); CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to set max env dbs: " + std::string(mdb_strerror(dbr))); const std::string actual_filename = get_cache_filename(cache_filename); dbr = mdb_env_open(env, actual_filename.c_str(), flags, 0664); @@ -265,6 +266,10 @@ static void init(std::string cache_filename) CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr))); mdb_set_dupsort(txn, dbi_spent, compare_uint64); + dbr = mdb_dbi_open(txn, "per_amount", MDB_CREATE | MDB_INTEGERKEY, &dbi_per_amount); + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr))); + mdb_set_compare(txn, dbi_per_amount, compare_uint64); + dbr = mdb_dbi_open(txn, "ring_instances", MDB_CREATE, &dbi_ring_instances); CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr))); @@ -283,6 +288,7 @@ static void close() mdb_dbi_close(env, dbi_relative_rings); mdb_dbi_close(env, dbi_outputs); mdb_dbi_close(env, dbi_processed_txidx); + mdb_dbi_close(env, dbi_per_amount); mdb_dbi_close(env, dbi_spent); mdb_dbi_close(env, dbi_ring_instances); mdb_dbi_close(env, dbi_stats); @@ -585,6 +591,55 @@ static std::vector get_spent_outputs(MDB_txn *txn) return outs; } +static void get_per_amount_outputs(MDB_txn *txn, uint64_t amount, uint64_t &total, uint64_t &spent) +{ + MDB_cursor *cur; + int dbr = mdb_cursor_open(txn, dbi_per_amount, &cur); + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open cursor for per amount outputs: " + std::string(mdb_strerror(dbr))); + MDB_val k, v; + mdb_size_t count = 0; + k.mv_size = sizeof(uint64_t); + k.mv_data = (void*)&amount; + dbr = mdb_cursor_get(cur, &k, &v, MDB_SET); + if (dbr == MDB_NOTFOUND) + { + total = spent = 0; + } + else + { + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to get per amount outputs: " + std::string(mdb_strerror(dbr))); + total = ((const uint64_t*)v.mv_data)[0]; + spent = ((const uint64_t*)v.mv_data)[1]; + } + mdb_cursor_close(cur); +} + +static void inc_per_amount_outputs(MDB_txn *txn, uint64_t amount, uint64_t total, uint64_t spent) +{ + MDB_cursor *cur; + int dbr = mdb_cursor_open(txn, dbi_per_amount, &cur); + CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open cursor for per amount outputs: " + std::string(mdb_strerror(dbr))); + MDB_val k, v; + mdb_size_t count = 0; + k.mv_size = sizeof(uint64_t); + k.mv_data = (void*)&amount; + dbr = mdb_cursor_get(cur, &k, &v, MDB_SET); + if (dbr == 0) + { + total += ((const uint64_t*)v.mv_data)[0]; + spent += ((const uint64_t*)v.mv_data)[1]; + } + else + { + CHECK_AND_ASSERT_THROW_MES(dbr == MDB_NOTFOUND, "Failed to get per amount outputs: " + std::string(mdb_strerror(dbr))); + } + uint64_t data[2] = {total, spent}; + v.mv_size = 2 * sizeof(uint64_t); + v.mv_data = (void*)data; + dbr = mdb_cursor_put(cur, &k, &v, 0); + mdb_cursor_close(cur); +} + static uint64_t get_processed_txidx(const std::string &name) { MDB_txn *txn; @@ -1193,6 +1248,7 @@ int main(int argc, char* argv[]) for_all_transactions(filename, start_idx, n_txes, [&](const cryptonote::transaction_prefix &tx)->bool { std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; + const bool miner_tx = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen); for (const auto &in: tx.vin) { if (in.type() != typeid(txin_to_key)) @@ -1210,6 +1266,9 @@ int main(int argc, char* argv[]) std::vector new_ring = canonicalize(txin.key_offsets); const uint32_t ring_size = txin.key_offsets.size(); const uint64_t instances = inc_ring_instances(txn, txin.amount, new_ring); + uint64_t pa_total = 0, pa_spent = 0; + if (!opt_rct_only) + get_per_amount_outputs(txn, txin.amount, pa_total, pa_spent); if (n == 0 && ring_size == 1) { const std::pair output = std::make_pair(txin.amount, absolute[0]); @@ -1237,6 +1296,21 @@ int main(int argc, char* argv[]) inc_stat(txn, txin.amount ? "pre-rct-duplicate-rings" : "rct-duplicate-rings"); } } + else if (n == 0 && !opt_rct_only && pa_spent + 1 == pa_total) + { + for (size_t o = 0; o < pa_total; ++o) + { + const std::pair output = std::make_pair(txin.amount, o); + if (opt_verbose) + { + MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to as many outputs of that amount being spent as exist so far"); + std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush; + } + blackballs.push_back(output); + if (add_spent_output(cur, output_data(txin.amount, o))) + inc_stat(txn, txin.amount ? "pre-rct-full-count" : "rct-full-count"); + } + } else if (n == 0 && opt_check_subsets && get_ring_subset_instances(txn, txin.amount, new_ring) >= new_ring.size()) { for (size_t o = 0; o < new_ring.size(); ++o) @@ -1299,9 +1373,28 @@ int main(int argc, char* argv[]) } } if (n == 0) + { set_relative_ring(txn, txin.k_image, new_ring); + if (!opt_rct_only) + inc_per_amount_outputs(txn, txin.amount, 0, 1); + } } set_processed_txidx(txn, canonical, start_idx+1); + if (!opt_rct_only) + { + for (const auto &out: tx.vout) + { + uint64_t amount = out.amount; + if (miner_tx && tx.version >= 2) + amount = 0; + + if (opt_rct_only && amount != 0) + continue; + if (out.target.type() != typeid(txout_to_key)) + continue; + inc_per_amount_outputs(txn, amount, 1, 0); + } + } ++records; if (records >= records_per_sync) @@ -1433,6 +1526,7 @@ int main(int argc, char* argv[]) { "pre-rct-ring-size-1", pre_rct }, { "rct-ring-size-1", rct }, { "pre-rct-duplicate-rings", pre_rct }, { "rct-duplicate-rings", rct }, { "pre-rct-subset-rings", pre_rct }, { "rct-subset-rings", rct }, + { "pre-rct-full-count", pre_rct }, { "rct-full-count", rct }, { "pre-rct-key-image-attack", pre_rct }, { "rct-key-image-attack", rct }, { "pre-rct-extra", pre_rct }, { "rct-ring-extra", rct }, { "pre-rct-chain-reaction", pre_rct }, { "rct-chain-reaction", rct }, From 2ffe53d9e668c1993fc6f1cbcd7d74c895a5fbb7 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Mon, 5 Nov 2018 00:38:58 +0100 Subject: [PATCH 0324/1007] device/trezor: webusb transport added, cmake fixes - webusb transport based on libusb added. Provides direct access to Trezor via USB, no need for Trezor bridge. - trezor protocol message handler improved, no recursion used. Ready for upcoming integration tests. - libusb (for docker) bumped from v1.0.9 to v1.0.22, newer version required for webusb transport, for device enumeration. - cmake improvements and fixes. Cmake Trezor checks are moved to a dedicated CheckTrezor.cmake file. In case of a problem Trezor is excluded from build. - ifdefs made consistent to Ledger. - UDP Transport enumeration disabled by default in release mode --- CMakeLists.txt | 13 +- cmake/CheckTrezor.cmake | 79 +++++ cmake/FindLibUSB.cmake | 140 ++++++++ cmake/test-libusb-version.c | 52 +++ contrib/depends/packages/libusb.mk | 8 +- src/device_trezor/CMakeLists.txt | 42 +-- src/device_trezor/device_trezor.cpp | 3 +- src/device_trezor/device_trezor.hpp | 2 +- src/device_trezor/device_trezor_base.cpp | 127 ++++--- src/device_trezor/device_trezor_base.hpp | 112 +++---- src/device_trezor/trezor.hpp | 2 +- src/device_trezor/trezor/tools/README.md | 25 +- src/device_trezor/trezor/tools/pb2cpp.py | 61 +++- src/device_trezor/trezor/transport.cpp | 403 ++++++++++++++++++++++- src/device_trezor/trezor/transport.hpp | 67 ++++ src/device_trezor/trezor/trezor_defs.hpp | 39 ++- 16 files changed, 970 insertions(+), 205 deletions(-) create mode 100644 cmake/CheckTrezor.cmake create mode 100644 cmake/FindLibUSB.cmake create mode 100644 cmake/test-libusb-version.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c38c673a..d942d31cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -513,15 +513,8 @@ else (HIDAPI_FOUND) message(STATUS "Could not find HIDAPI") endif() -# Protobuf, optional. Required for TREZOR. -include(FindProtobuf) -find_package(Protobuf) -if(Protobuf_FOUND) - set(HAVE_PROTOBUF 1) - add_definitions(-DHAVE_PROTOBUF=1) -else(Protobuf_FOUND) - message(STATUS "Could not find Protobuf") -endif() +# Trezor support check +include(CheckTrezor) if(MSVC) add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__") @@ -921,7 +914,7 @@ endif() list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS}) -if (HIDAPI_FOUND) +if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED) if (APPLE) if(DEPENDS) list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit") diff --git a/cmake/CheckTrezor.cmake b/cmake/CheckTrezor.cmake new file mode 100644 index 000000000..ea21237fd --- /dev/null +++ b/cmake/CheckTrezor.cmake @@ -0,0 +1,79 @@ +OPTION(USE_DEVICE_TREZOR "Trezor support compilation" ON) +OPTION(USE_DEVICE_TREZOR_LIBUSB "Trezor LibUSB compilation" ON) +OPTION(USE_DEVICE_TREZOR_UDP_RELEASE "Trezor UdpTransport in release mode" OFF) + +# Use Trezor master switch +if (USE_DEVICE_TREZOR) + # Protobuf is required to build protobuf messages for Trezor + include(FindProtobuf OPTIONAL) + find_package(Protobuf) + if(NOT Protobuf_FOUND) + message(STATUS "Could not find Protobuf") + endif() + +else() + message(STATUS "Trezor support disabled by USE_DEVICE_TREZOR") +endif() + +if(Protobuf_FOUND AND USE_DEVICE_TREZOR) + if (NOT "$ENV{TREZOR_PYTHON}" STREQUAL "") + set(TREZOR_PYTHON "$ENV{TREZOR_PYTHON}" CACHE INTERNAL "Copied from environment variable TREZOR_PYTHON") + else() + find_package(Python QUIET COMPONENTS Interpreter) # cmake 3.12+ + if(Python_Interpreter_FOUND) + set(TREZOR_PYTHON "${Python_EXECUTABLE}") + endif() + endif() + + if(NOT TREZOR_PYTHON) + find_package(PythonInterp) + if(PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE) + set(TREZOR_PYTHON "${PYTHON_EXECUTABLE}") + endif() + endif() + + if(NOT TREZOR_PYTHON) + message(STATUS "Trezor: Python not found") + endif() +endif() + +# Try to build protobuf messages +if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON) + set(ENV{PROTOBUF_INCLUDE_DIRS} "${Protobuf_INCLUDE_DIRS}") + set(ENV{PROTOBUF_PROTOC_EXECUTABLE} "${Protobuf_PROTOC_EXECUTABLE}") + execute_process(COMMAND ${TREZOR_PYTHON} tools/build_protob.py WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../src/device_trezor/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR) + if(RET) + message(WARNING "Trezor protobuf messages could not be regenerated (err=${RET}, python ${PYTHON})." + "OUT: ${OUT}, ERR: ${ERR}." + "Please read src/device_trezor/trezor/tools/README.md") + else() + message(STATUS "Trezor protobuf messages regenerated ${OUT}") + set(DEVICE_TREZOR_READY 1) + add_definitions(-DDEVICE_TREZOR_READY=1) + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-DTREZOR_DEBUG=1) + endif() + + if(USE_DEVICE_TREZOR_UDP_RELEASE) + add_definitions(-DWITH_DEVICE_TREZOR_UDP_RELEASE=1) + endif() + + if (Protobuf_INCLUDE_DIR) + include_directories(${Protobuf_INCLUDE_DIR}) + endif() + + # LibUSB support, check for particular version + # Include support only if compilation test passes + if (USE_DEVICE_TREZOR_LIBUSB) + find_package(LibUSB) + endif() + + if (LibUSB_COMPILE_TEST_PASSED) + add_definitions(-DHAVE_TREZOR_LIBUSB=1) + if(LibUSB_INCLUDE_DIRS) + include_directories(${LibUSB_INCLUDE_DIRS}) + endif() + endif() + endif() +endif() diff --git a/cmake/FindLibUSB.cmake b/cmake/FindLibUSB.cmake new file mode 100644 index 000000000..7e3bf156e --- /dev/null +++ b/cmake/FindLibUSB.cmake @@ -0,0 +1,140 @@ +# - Find libusb for portable USB support +# This module will find libusb as published by +# http://libusb.sf.net and +# http://libusb-win32.sf.net +# +# It will use PkgConfig if present and supported, else search +# it on its own. If the LibUSB_ROOT_DIR environment variable +# is defined, it will be used as base path. +# The following standard variables get defined: +# LibUSB_FOUND: true if LibUSB was found +# LibUSB_HEADER_FILE: the location of the C header file +# LibUSB_INCLUDE_DIRS: the directory that contains the include file +# LibUSB_LIBRARIES: the library +# source: https://github.com/IntelRealSense/librealsense + +include ( CheckLibraryExists ) +include ( CheckIncludeFile ) + +find_package ( PkgConfig ) +if ( PKG_CONFIG_FOUND ) + pkg_check_modules ( PKGCONFIG_LIBUSB libusb-1.0 ) + if ( NOT PKGCONFIG_LIBUSB_FOUND ) + pkg_check_modules ( PKGCONFIG_LIBUSB libusb ) + endif ( NOT PKGCONFIG_LIBUSB_FOUND ) +endif ( PKG_CONFIG_FOUND ) + +if ( PKGCONFIG_LIBUSB_FOUND ) + set ( LibUSB_INCLUDE_DIRS ${PKGCONFIG_LIBUSB_INCLUDE_DIRS} ) + foreach ( i ${PKGCONFIG_LIBUSB_LIBRARIES} ) + string ( REGEX MATCH "[^-]*" ibase "${i}" ) + find_library ( ${ibase}_LIBRARY + NAMES ${i} + PATHS ${PKGCONFIG_LIBUSB_LIBRARY_DIRS} + ) + if ( ${ibase}_LIBRARY ) + list ( APPEND LibUSB_LIBRARIES ${${ibase}_LIBRARY} ) + endif ( ${ibase}_LIBRARY ) + mark_as_advanced ( ${ibase}_LIBRARY ) + endforeach ( i ) + +else ( PKGCONFIG_LIBUSB_FOUND ) + find_file ( LibUSB_HEADER_FILE + NAMES + libusb.h usb.h + PATHS + $ENV{ProgramFiles}/LibUSB-Win32 + $ENV{LibUSB_ROOT_DIR} + PATH_SUFFIXES + include + libusb-1.0 + include/libusb-1.0 + ) + mark_as_advanced ( LibUSB_HEADER_FILE ) + get_filename_component ( LibUSB_INCLUDE_DIRS "${LibUSB_HEADER_FILE}" PATH ) + + if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" ) + # LibUSB-Win32 binary distribution contains several libs. + # Use the lib that got compiled with the same compiler. + if ( MSVC ) + if ( WIN32 ) + set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc ) + else ( WIN32 ) + set ( LibUSB_LIBRARY_PATH_SUFFIX lib/msvc_x64 ) + endif ( WIN32 ) + elseif ( BORLAND ) + set ( LibUSB_LIBRARY_PATH_SUFFIX lib/bcc ) + elseif ( CMAKE_COMPILER_IS_GNUCC ) + set ( LibUSB_LIBRARY_PATH_SUFFIX lib/gcc ) + endif ( MSVC ) + endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Windows" ) + + find_library ( usb_LIBRARY + NAMES + usb-1.0 libusb usb + PATHS + $ENV{ProgramFiles}/LibUSB-Win32 + $ENV{LibUSB_ROOT_DIR} + PATH_SUFFIXES + ${LibUSB_LIBRARY_PATH_SUFFIX} + ) + mark_as_advanced ( usb_LIBRARY ) + if ( usb_LIBRARY ) + set ( LibUSB_LIBRARIES ${usb_LIBRARY} ) + endif ( usb_LIBRARY ) + +endif ( PKGCONFIG_LIBUSB_FOUND ) + +if ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES ) + set ( LibUSB_FOUND true ) +endif ( LibUSB_INCLUDE_DIRS AND LibUSB_LIBRARIES ) + +if ( LibUSB_FOUND ) + set ( CMAKE_REQUIRED_INCLUDES "${LibUSB_INCLUDE_DIRS}" ) + check_include_file ( "${LibUSB_HEADER_FILE}" LibUSB_FOUND ) +endif ( LibUSB_FOUND ) + +if ( LibUSB_FOUND ) + check_library_exists ( "${LibUSB_LIBRARIES}" usb_open "" LibUSB_FOUND ) + check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_device_list "" LibUSB_VERSION_1.0 ) + check_library_exists ( "${LibUSB_LIBRARIES}" libusb_get_port_numbers "" LibUSB_VERSION_1.0.16 ) + + # Library 1.0.16+ compilation test. + # The check_library_exists does not work well on Apple with shared libs. + if (APPLE OR LibUSB_VERSION_1.0.16) + if (APPLE) + if(DEPENDS) + list(APPEND TEST_COMPILE_EXTRA_LIBRARIES "-framework Foundation -framework IOKit") + else() + find_library(COREFOUNDATION CoreFoundation) + find_library(IOKIT IOKit) + list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${IOKIT}) + list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${COREFOUNDATION}) + endif() + endif() + if (WIN32) + list(APPEND TEST_COMPILE_EXTRA_LIBRARIES setupapi) + endif() + list(APPEND TEST_COMPILE_EXTRA_LIBRARIES ${LibUSB_LIBRARIES}) + + try_compile(LibUSB_COMPILE_TEST_PASSED + ${CMAKE_BINARY_DIR} + "${CMAKE_SOURCE_DIR}/cmake/test-libusb-version.c" + CMAKE_FLAGS + "-DINCLUDE_DIRECTORIES=${LibUSB_INCLUDE_DIRS}" + "-DLINK_DIRECTORIES=${LibUSB_LIBRARIES}" + LINK_LIBRARIES ${TEST_COMPILE_EXTRA_LIBRARIES} + OUTPUT_VARIABLE OUTPUT) + unset(TEST_COMPILE_EXTRA_LIBRARIES) + message(STATUS "LibUSB Compilation test: ${LibUSB_COMPILE_TEST_PASSED}") + endif() +endif ( LibUSB_FOUND ) + +if ( NOT LibUSB_FOUND ) + if ( NOT LibUSB_FIND_QUIETLY ) + message ( STATUS "LibUSB not found, try setting LibUSB_ROOT_DIR environment variable." ) + endif ( NOT LibUSB_FIND_QUIETLY ) + if ( LibUSB_FIND_REQUIRED ) + message ( FATAL_ERROR "" ) + endif ( LibUSB_FIND_REQUIRED ) +endif ( NOT LibUSB_FOUND ) diff --git a/cmake/test-libusb-version.c b/cmake/test-libusb-version.c new file mode 100644 index 000000000..309e4ad27 --- /dev/null +++ b/cmake/test-libusb-version.c @@ -0,0 +1,52 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include + +#define UNUSED(expr) (void)(expr) + +int main(int argc, char *argv[]) { + libusb_device **devs; + libusb_context *ctx = NULL; + + int r = libusb_init(&ctx); UNUSED(r); + ssize_t cnt = libusb_get_device_list(ctx, &devs); UNUSED(cnt); + + struct libusb_device_descriptor desc; + r = libusb_get_device_descriptor(devs[0], &desc); UNUSED(r); + uint8_t bus_id = libusb_get_bus_number(devs[0]); UNUSED(bus_id); + uint8_t addr = libusb_get_device_address(devs[0]); UNUSED(addr); + + uint8_t tmp_path[16]; + r = libusb_get_port_numbers(devs[0], tmp_path, sizeof(tmp_path)); + UNUSED(r); + UNUSED(tmp_path); + + libusb_free_device_list(devs, 1); + libusb_exit(ctx); +} diff --git a/contrib/depends/packages/libusb.mk b/contrib/depends/packages/libusb.mk index 47f8b3cbc..e9663ace0 100644 --- a/contrib/depends/packages/libusb.mk +++ b/contrib/depends/packages/libusb.mk @@ -1,8 +1,8 @@ package=libusb -$(package)_version=1.0.9 -$(package)_download_path=http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.9/ +$(package)_version=1.0.22 +$(package)_download_path=http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-$($(package)_version)/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=e920eedc2d06b09606611c99ec7304413c6784cba6e33928e78243d323195f9b +$(package)_sha256_hash=75aeb9d59a4fdb800d329a545c2e6799f732362193b465ea198f2aa275518157 define $(package)_preprocess_cmds autoreconf -i @@ -10,7 +10,7 @@ endef define $(package)_set_vars $(package)_config_opts=--disable-shared - $(package)_config_opts_linux=--with-pic + $(package)_config_opts_linux=--with-pic --disable-udev endef define $(package)_config_cmds diff --git a/src/device_trezor/CMakeLists.txt b/src/device_trezor/CMakeLists.txt index c555e9fcd..b27c843b6 100644 --- a/src/device_trezor/CMakeLists.txt +++ b/src/device_trezor/CMakeLists.txt @@ -63,37 +63,20 @@ set(trezor_sources set(trezor_private_headers) -include(FindProtobuf) -find_package(Protobuf) # REQUIRED - -# Test for HAVE_PROTOBUF from the parent -if(Protobuf_FOUND AND HAVE_PROTOBUF) - if ("$ENV{PYTHON3}" STREQUAL "") - set(PYTHON3 "python3") - else() - set(PYTHON3 "$ENV{PYTHON3}" CACHE INTERNAL "Copied from environment variable") - endif() - - execute_process(COMMAND ${PYTHON3} tools/build_protob.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/trezor RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR) - if(RET) - message(WARNING "Trezor protobuf messages could not be regenerated (err=${RET}, python ${PYTHON})." - "OUT: ${OUT}, ERR: ${ERR}." - "Please read src/device_trezor/trezor/tools/README.md") - else() - message(STATUS "Trezor protobuf messages regenerated ${OUT}") - set(TREZOR_PROTOBUF_GENERATED 1) - endif() -endif() - - -if(TREZOR_PROTOBUF_GENERATED) +# Protobuf and LibUSB processed by CheckTrezor +if(DEVICE_TREZOR_READY) message(STATUS "Trezor support enabled") add_definitions(-DPROTOBUF_INLINE_NOT_IN_HEADERS=0) + set(TREZOR_LIBUSB_LIBRARIES "") + if(LibUSB_COMPILE_TEST_PASSED) + list(APPEND TREZOR_LIBUSB_LIBRARIES ${LibUSB_LIBRARIES}) + message(STATUS "Trezor compatible LibUSB found at: ${LibUSB_INCLUDE_DIRS}") + endif() + monero_private_headers(device_trezor - ${device_private_headers} - ${PROTOBUF_INCLUDE_DIR}) + ${device_private_headers}) monero_add_library(device_trezor ${trezor_sources} @@ -109,14 +92,13 @@ if(TREZOR_PROTOBUF_GENERATED) common ${SODIUM_LIBRARY} ${Boost_CHRONO_LIBRARY} - ${PROTOBUF_LIBRARY} + ${Protobuf_LIBRARY} + ${TREZOR_LIBUSB_LIBRARIES} PRIVATE ${EXTRA_LIBRARIES}) - # set(WITH_DEVICE_TREZOR 1 PARENT_SCOPE) - # add_definitions(-DWITH_DEVICE_TREZOR=1) - else() + message(STATUS "Trezor support disabled") monero_private_headers(device_trezor) monero_add_library(device_trezor device_trezor.cpp) target_link_libraries(device_trezor PUBLIC cncrypto) diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index f55cbb15d..5096fcea8 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -32,13 +32,12 @@ namespace hw { namespace trezor { -#if WITH_DEVICE_TREZOR +#ifdef WITH_DEVICE_TREZOR #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" #define HW_TREZOR_NAME "Trezor" -#define HW_TREZOR_NAME_LITE "TrezorLite" static device_trezor *trezor_device = nullptr; static device_trezor *ensure_trezor_device(){ diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp index 765c9b82c..a2134574c 100644 --- a/src/device_trezor/device_trezor.hpp +++ b/src/device_trezor/device_trezor.hpp @@ -49,7 +49,7 @@ namespace trezor { void register_all(); void register_all(std::map> ®istry); -#if WITH_DEVICE_TREZOR +#ifdef WITH_DEVICE_TREZOR class device_trezor; /** diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 3a98bba5a..38c20c30b 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -32,43 +32,11 @@ namespace hw { namespace trezor { -#if WITH_DEVICE_TREZOR +#ifdef WITH_DEVICE_TREZOR #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" - std::shared_ptr trezor_protocol_callback::on_button_request(const messages::common::ButtonRequest * msg){ - MDEBUG("on_button_request"); - device.on_button_request(); - return std::make_shared(); - } - - std::shared_ptr trezor_protocol_callback::on_pin_matrix_request(const messages::common::PinMatrixRequest * msg){ - MDEBUG("on_pin_request"); - epee::wipeable_string pin; - device.on_pin_request(pin); - auto resp = std::make_shared(); - resp->set_pin(pin.data(), pin.size()); - return resp; - } - - std::shared_ptr trezor_protocol_callback::on_passphrase_request(const messages::common::PassphraseRequest * msg){ - MDEBUG("on_passhprase_request"); - epee::wipeable_string passphrase; - device.on_passphrase_request(msg->on_device(), passphrase); - auto resp = std::make_shared(); - if (!msg->on_device()){ - resp->set_passphrase(passphrase.data(), passphrase.size()); - } - return resp; - } - - std::shared_ptr trezor_protocol_callback::on_passphrase_state_request(const messages::common::PassphraseStateRequest * msg){ - MDEBUG("on_passhprase_state_request"); - device.on_passphrase_state_request(msg->state()); - return std::make_shared(); - } - const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; device_trezor_base::device_trezor_base() { @@ -117,9 +85,6 @@ namespace trezor { return false; } - if (!m_protocol_callback){ - m_protocol_callback = std::make_shared(*this); - } return true; } @@ -245,6 +210,49 @@ namespace trezor { } } + void device_trezor_base::write_raw(const google::protobuf::Message * msg){ + require_connected(); + CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + this->getTransport()->write(*msg); + } + + GenericMessage device_trezor_base::read_raw(){ + require_connected(); + std::shared_ptr msg_resp; + hw::trezor::messages::MessageType msg_resp_type; + + this->getTransport()->read(msg_resp, &msg_resp_type); + return GenericMessage(msg_resp_type, msg_resp); + } + + GenericMessage device_trezor_base::call_raw(const google::protobuf::Message * msg) { + write_raw(msg); + return read_raw(); + } + + bool device_trezor_base::message_handler(GenericMessage & input){ + // Later if needed this generic message handler can be replaced by a pointer to + // a protocol message handler which by default points to the device class which implements + // the default handler. + switch(input.m_type){ + case messages::MessageType_ButtonRequest: + on_button_request(input, dynamic_cast(input.m_msg.get())); + return true; + case messages::MessageType_PassphraseRequest: + on_passphrase_request(input, dynamic_cast(input.m_msg.get())); + return true; + case messages::MessageType_PassphraseStateRequest: + on_passphrase_state_request(input, dynamic_cast(input.m_msg.get())); + return true; + case messages::MessageType_PinMatrixRequest: + on_pin_request(input, dynamic_cast(input.m_msg.get())); + return true; + default: + return false; + } + } + + /* ======================================================================= */ /* TREZOR PROTOCOL */ /* ======================================================================= */ @@ -269,32 +277,67 @@ namespace trezor { return false; } - void device_trezor_base::on_button_request() + void device_trezor_base::on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg) { + CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + MDEBUG("on_button_request, code: " << msg->code()); + + messages::common::ButtonAck ack; + write_raw(&ack); + if (m_callback){ m_callback->on_button_request(); } + + resp = read_raw(); } - void device_trezor_base::on_pin_request(epee::wipeable_string & pin) + void device_trezor_base::on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg) { + MDEBUG("on_pin_request"); + CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + + epee::wipeable_string pin; + if (m_callback){ m_callback->on_pin_request(pin); } + + // TODO: remove PIN from memory + messages::common::PinMatrixAck m; + m.set_pin(pin.data(), pin.size()); + resp = call_raw(&m); } - void device_trezor_base::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) + void device_trezor_base::on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg) { + CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + MDEBUG("on_passhprase_request, on device: " << msg->on_device()); + epee::wipeable_string passphrase; + if (m_callback){ - m_callback->on_passphrase_request(on_device, passphrase); + m_callback->on_passphrase_request(msg->on_device(), passphrase); } + + messages::common::PassphraseAck m; + if (!msg->on_device()){ + // TODO: remove passphrase from memory + m.set_passphrase(passphrase.data(), passphrase.size()); + } + resp = call_raw(&m); } - void device_trezor_base::on_passphrase_state_request(const std::string & state) + void device_trezor_base::on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg) { + MDEBUG("on_passhprase_state_request"); + CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + if (m_callback){ - m_callback->on_passphrase_state_request(state); + m_callback->on_passphrase_state_request(msg->state()); } + + messages::common::PassphraseStateAck m; + resp = call_raw(&m); } #endif //WITH_DEVICE_TREZOR diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index 644a49332..88d419494 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -54,7 +54,7 @@ namespace hw { namespace trezor { -#if WITH_DEVICE_TREZOR +#ifdef WITH_DEVICE_TREZOR class device_trezor_base; /** @@ -68,41 +68,6 @@ namespace trezor { virtual void on_passphrase_state_request(const std::string & state) {}; }; - /** - * Default Trezor protocol client callback - */ - class trezor_protocol_callback { - protected: - device_trezor_base & device; - - public: - explicit trezor_protocol_callback(device_trezor_base & device): device(device) {} - - std::shared_ptr on_button_request(const messages::common::ButtonRequest * msg); - std::shared_ptr on_pin_matrix_request(const messages::common::PinMatrixRequest * msg); - std::shared_ptr on_passphrase_request(const messages::common::PassphraseRequest * msg); - std::shared_ptr on_passphrase_state_request(const messages::common::PassphraseStateRequest * msg); - - std::shared_ptr on_message(const google::protobuf::Message * msg, messages::MessageType message_type){ - MDEBUG("on_general_message"); - return on_message_dispatch(msg, message_type); - } - - std::shared_ptr on_message_dispatch(const google::protobuf::Message * msg, messages::MessageType message_type){ - if (message_type == messages::MessageType_ButtonRequest){ - return on_button_request(dynamic_cast(msg)); - } else if (message_type == messages::MessageType_PassphraseRequest) { - return on_passphrase_request(dynamic_cast(msg)); - } else if (message_type == messages::MessageType_PassphraseStateRequest) { - return on_passphrase_state_request(dynamic_cast(msg)); - } else if (message_type == messages::MessageType_PinMatrixRequest) { - return on_pin_matrix_request(dynamic_cast(msg)); - } else { - return nullptr; - } - } - }; - /** * TREZOR device template with basic functions */ @@ -114,7 +79,6 @@ namespace trezor { mutable boost::mutex command_locker; std::shared_ptr m_transport; - std::shared_ptr m_protocol_callback; std::shared_ptr m_callback; std::string full_name; @@ -129,6 +93,15 @@ namespace trezor { void call_ping_unsafe(); void test_ping(); + // Communication methods + + void write_raw(const google::protobuf::Message * msg); + GenericMessage read_raw(); + GenericMessage call_raw(const google::protobuf::Message * msg); + + // Trezor message protocol handler. Handles specific signalling messages. + bool message_handler(GenericMessage & input); + /** * Client communication wrapper, handles specific Trezor protocol. * @@ -141,8 +114,7 @@ namespace trezor { const boost::optional & resp_type = boost::none, const boost::optional> & resp_types = boost::none, const boost::optional & resp_type_ptr = boost::none, - bool open_session = false, - unsigned depth=0) + bool open_session = false) { // Require strictly protocol buffers response in the template. BOOST_STATIC_ASSERT(boost::is_base_of::value); @@ -151,8 +123,12 @@ namespace trezor { throw std::invalid_argument("Cannot specify list of accepted types and not using generic response"); } + // Determine type of expected message response + const messages::MessageType required_type = accepting_base ? messages::MessageType_Success : + (resp_type ? resp_type.get() : MessageMapper::get_message_wire_number()); + // Open session if required - if (open_session && depth == 0){ + if (open_session){ try { m_transport->open(); } catch (const std::exception& e) { @@ -162,47 +138,37 @@ namespace trezor { // Scoped session closer BOOST_SCOPE_EXIT_ALL(&, this) { - if (open_session && depth == 0){ + if (open_session){ this->getTransport()->close(); } }; - // Write the request + // Write/read the request CHECK_AND_ASSERT_THROW_MES(req, "Request is null"); - this->getTransport()->write(*req); + auto msg_resp = call_raw(req.get()); - // Read the response - std::shared_ptr msg_resp; - hw::trezor::messages::MessageType msg_resp_type; + bool processed = false; + do { + processed = message_handler(msg_resp); + } while(processed); - // We may have several roundtrips with the handler - this->getTransport()->read(msg_resp, &msg_resp_type); + // Response section if (resp_type_ptr){ - *(resp_type_ptr.get()) = msg_resp_type; + *(resp_type_ptr.get()) = msg_resp.m_type; } - // Determine type of expected message response - messages::MessageType required_type = accepting_base ? messages::MessageType_Success : - (resp_type ? resp_type.get() : MessageMapper::get_message_wire_number()); + if (msg_resp.m_type == messages::MessageType_Failure) { + throw_failure_exception(dynamic_cast(msg_resp.m_msg.get())); - if (msg_resp_type == messages::MessageType_Failure) { - throw_failure_exception(dynamic_cast(msg_resp.get())); + } else if (!accepting_base && msg_resp.m_type == required_type) { + return message_ptr_retype(msg_resp.m_msg); - } else if (!accepting_base && msg_resp_type == required_type) { - return message_ptr_retype(msg_resp); + } else if (accepting_base && (!resp_types || + std::find(resp_types.get().begin(), resp_types.get().end(), msg_resp.m_type) != resp_types.get().end())) { + return message_ptr_retype(msg_resp.m_msg); } else { - auto resp = this->getProtocolCallback()->on_message(msg_resp.get(), msg_resp_type); - if (resp) { - return this->client_exchange(resp, boost::none, resp_types, resp_type_ptr, false, depth + 1); - - } else if (accepting_base && (!resp_types || - std::find(resp_types.get().begin(), resp_types.get().end(), msg_resp_type) != resp_types.get().end())) { - return message_ptr_retype(msg_resp); - - } else { - throw exc::UnexpectedMessageException(msg_resp_type, msg_resp); - } + throw exc::UnexpectedMessageException(msg_resp.m_type, msg_resp.m_msg); } } @@ -252,10 +218,6 @@ namespace trezor { return m_transport; } - std::shared_ptr getProtocolCallback(){ - return m_protocol_callback; - } - std::shared_ptr getCallback(){ return m_callback; } @@ -288,10 +250,10 @@ namespace trezor { bool ping(); // Protocol callbacks - void on_button_request(); - void on_pin_request(epee::wipeable_string & pin); - void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); - void on_passphrase_state_request(const std::string & state); + void on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg); + void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg); + void on_passphrase_request(GenericMessage & resp, const messages::common::PassphraseRequest * msg); + void on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg); }; #endif diff --git a/src/device_trezor/trezor.hpp b/src/device_trezor/trezor.hpp index 8abdd2c18..97dc0a957 100644 --- a/src/device_trezor/trezor.hpp +++ b/src/device_trezor/trezor.hpp @@ -32,7 +32,7 @@ #include "trezor/trezor_defs.hpp" -#ifdef HAVE_PROTOBUF +#ifdef WITH_DEVICE_TREZOR #include "trezor/transport.hpp" #include "trezor/messages/messages.pb.h" #include "trezor/messages/messages-common.pb.h" diff --git a/src/device_trezor/trezor/tools/README.md b/src/device_trezor/trezor/tools/README.md index 91a8fb3f0..b176017ac 100644 --- a/src/device_trezor/trezor/tools/README.md +++ b/src/device_trezor/trezor/tools/README.md @@ -2,33 +2,28 @@ ## Messages rebuild -Install `protoc` for your distribution. +Install `protoc` for your distribution. Requirements: - `protobuf-compiler` - `libprotobuf-dev` -- `libprotoc-dev` -- `python-protobuf` +- `python` -Python 3 is required. If you don't have python 3 quite an easy way is -to use [pyenv]. -It is also advised to create own python virtual environment so dependencies -are installed in this project-related virtual environment. +Soft requirement: Python 3, can be easily installed with [pyenv]. -```bash -python -m venv / -``` +### Python 2 -Make sure your python has `protobuf` package installed +Workaround if there is no Python3 available: ```bash -pip install protobuf +pip install backports.tempfile ``` -Regenerate messages: +### Regenerate messages -``` -./venv/bin/python3 src/device_trezor/trezor/tools/build_protob.py +```bash +cd src/device_trezor/trezor +python tools/build_protob.py ``` The messages regeneration is done also automatically via cmake. diff --git a/src/device_trezor/trezor/tools/pb2cpp.py b/src/device_trezor/trezor/tools/pb2cpp.py index eaa8a90ed..4d7cc775f 100644 --- a/src/device_trezor/trezor/tools/pb2cpp.py +++ b/src/device_trezor/trezor/tools/pb2cpp.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # Converts Google's protobuf python definitions of TREZOR wire messages # to plain-python objects as used in TREZOR Core and python-trezor @@ -8,11 +8,19 @@ import re import shutil import subprocess -import sys import glob -import tempfile import hashlib +try: + from tempfile import TemporaryDirectory +except: + # Py2 backward compatibility, optionally installed by user + # pip install backports.tempfile + try: + from backports.tempfile import TemporaryDirectory + except: + raise EnvironmentError('TemporaryDirectory could not be imported. Try: pip install backports.tempfile') + AUTO_HEADER = "# Automatically generated by pb2cpp\n" @@ -23,6 +31,9 @@ #endif """ +PROTOC = None +PROTOC_INCLUDE = None + def which(pgm): path = os.getenv('PATH') @@ -32,15 +43,6 @@ def which(pgm): return p -PROTOC = which("protoc") -if not PROTOC: - print("protoc command not found") - sys.exit(1) - -PROTOC_PREFIX = os.path.dirname(os.path.dirname(PROTOC)) -PROTOC_INCLUDE = os.path.join(PROTOC_PREFIX, "include") - - def namespace_file(fpath, package): """Adds / replaces package name. Simple regex parsing, may use https://github.com/ph4r05/plyprotobuf later""" with open(fpath) as fh: @@ -82,9 +84,10 @@ def protoc(files, out_dir, additional_includes=(), package=None, force=False): include_dirs = set() include_dirs.add(PROTOC_INCLUDE) - include_dirs.update(additional_includes) + if additional_includes: + include_dirs.update(additional_includes) - with tempfile.TemporaryDirectory() as tmpdir_protob, tempfile.TemporaryDirectory() as tmpdir_out: + with TemporaryDirectory() as tmpdir_protob, TemporaryDirectory() as tmpdir_out: include_dirs.add(tmpdir_protob) new_files = [] @@ -125,9 +128,9 @@ def update_message_files(tmpdir_out, out_dir, force=False): dest_file = os.path.join(out_dir, bname) if not force and os.path.exists(dest_file): data = open(fname, 'rb').read() - data_hash = hashlib.sha3_256(data).digest() + data_hash = hashlib.sha256(data).digest() data_dest = open(dest_file, 'rb').read() - data_dest_hash = hashlib.sha3_256(data_dest).digest() + data_dest_hash = hashlib.sha256(data_dest).digest() if data_hash == data_dest_hash: continue @@ -163,7 +166,8 @@ def strip_leader(s, prefix): return s -if __name__ == "__main__": +def main(): + global PROTOC, PROTOC_INCLUDE logging.basicConfig(level=logging.DEBUG) parser = argparse.ArgumentParser() @@ -179,8 +183,31 @@ def strip_leader(s, prefix): protoc_includes = args.protoc_include or (os.environ.get("PROTOC_INCLUDE"),) + PROTOBUF_INCLUDE_DIRS = os.getenv("PROTOBUF_INCLUDE_DIRS", None) + PROTOBUF_PROTOC_EXECUTABLE = os.getenv("PROTOBUF_PROTOC_EXECUTABLE", None) + + if PROTOBUF_PROTOC_EXECUTABLE and not os.path.exists(PROTOBUF_PROTOC_EXECUTABLE): + raise ValueError("PROTOBUF_PROTOC_EXECUTABLE set but not found: %s" % PROTOBUF_PROTOC_EXECUTABLE) + + elif PROTOBUF_PROTOC_EXECUTABLE: + PROTOC = PROTOBUF_PROTOC_EXECUTABLE + + else: + if os.name == "nt": + PROTOC = which("protoc.exe") + else: + PROTOC = which("protoc") + + if not PROTOC: + raise ValueError("protoc command not found. Set PROTOBUF_PROTOC_EXECUTABLE env var to the protoc binary and optionally PROTOBUF_INCLUDE_DIRS") + + PROTOC_PREFIX = os.path.dirname(os.path.dirname(PROTOC)) + PROTOC_INCLUDE = PROTOBUF_INCLUDE_DIRS if PROTOBUF_INCLUDE_DIRS else os.path.join(PROTOC_PREFIX, "include") + protoc( args.proto, args.out_dir, protoc_includes, package=args.namespace, force=args.force ) +if __name__ == "__main__": + main() diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp index fc86177e1..814537eb6 100644 --- a/src/device_trezor/trezor/transport.cpp +++ b/src/device_trezor/trezor/transport.cpp @@ -27,13 +27,21 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#ifdef WITH_DEVICE_TREZOR_WEBUSB +#include +#endif + #include #include #include #include +#include #include "transport.hpp" #include "messages/messages-common.pb.h" +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "device.trezor.transport" + using namespace std; using json = rapidjson::Document; @@ -581,12 +589,400 @@ namespace trezor{ << ">"; } +#ifdef WITH_DEVICE_TREZOR_WEBUSB + + static bool is_trezor1(libusb_device_descriptor * info){ + return info->idVendor == 0x534C && info->idProduct == 0x0001; + } + + static bool is_trezor2(libusb_device_descriptor * info){ + return info->idVendor == 0x1209 && info->idProduct == 0x53C1; + } + + static bool is_trezor2_bl(libusb_device_descriptor * info){ + return info->idVendor == 0x1209 && info->idProduct == 0x53C0; + } + + static uint8_t get_trezor_dev_mask(libusb_device_descriptor * info){ + uint8_t mask = 0; + CHECK_AND_ASSERT_THROW_MES(info, "Empty device descriptor"); + mask |= is_trezor1(info) ? 1 : 0; + mask |= is_trezor2(info) ? 2 : 0; + mask |= is_trezor2_bl(info) ? 4 : 0; + return mask; + } + + static void set_libusb_log(libusb_context *ctx){ + CHECK_AND_ASSERT_THROW_MES(ctx, "Null libusb context"); + + // http://libusb.sourceforge.net/api-1.0/group__libusb__lib.html +#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000106) +# define TREZOR_LIBUSB_SET_DEBUG(ctx, level) libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, level) +#else +# define TREZOR_LIBUSB_SET_DEBUG(ctx, level) libusb_set_debug(ctx, level) +#endif + + if (ELPP->vRegistry()->allowed(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY)) + TREZOR_LIBUSB_SET_DEBUG(ctx, 3); + else if (ELPP->vRegistry()->allowed(el::Level::Warning, MONERO_DEFAULT_LOG_CATEGORY)) + TREZOR_LIBUSB_SET_DEBUG(ctx, 2); + else if (ELPP->vRegistry()->allowed(el::Level::Error, MONERO_DEFAULT_LOG_CATEGORY)) + TREZOR_LIBUSB_SET_DEBUG(ctx, 1); + +#undef TREZOR_LIBUSB_SET_DEBUG + } + + static int get_libusb_ports(libusb_device *dev, std::vector &path){ + uint8_t tmp_path[16]; + int r = libusb_get_port_numbers(dev, tmp_path, sizeof(tmp_path)); + CHECK_AND_ASSERT_MES(r != LIBUSB_ERROR_OVERFLOW, -1, "Libusb path array too small"); + CHECK_AND_ASSERT_MES(r >= 0, -1, "Libusb path array error"); + + path.resize(r); + for (int i = 0; i < r; i++){ + path[i] = tmp_path[i]; + } + + return 0; + } + + static std::string get_usb_path(uint8_t bus_id, const std::vector &path){ + std::stringstream ss; + ss << WebUsbTransport::PATH_PREFIX << (boost::format("%03d") % ((int)bus_id)); + for(uint8_t port : path){ + ss << ":" << ((int) port); + } + return ss.str(); + } + + const char * WebUsbTransport::PATH_PREFIX = "webusb:"; + + WebUsbTransport::WebUsbTransport( + boost::optional descriptor, + boost::optional> proto + ): m_conn_count(0), + m_usb_session(nullptr), m_usb_device(nullptr), m_usb_device_handle(nullptr), + m_bus_id(-1), m_device_addr(-1) + { + if (descriptor){ + libusb_device_descriptor * desc = new libusb_device_descriptor; + memcpy(desc, descriptor.get(), sizeof(libusb_device_descriptor)); + this->m_usb_device_desc.reset(desc); + } + + m_proto = proto ? proto.get() : std::make_shared(); + +#ifdef WITH_TREZOR_DEBUG + m_debug_mode = false; +#endif + } + + WebUsbTransport::~WebUsbTransport(){ + if (m_usb_device){ + close(); + } + + if (m_usb_session) { + libusb_exit(m_usb_session); + m_usb_session = nullptr; + } + } + + void WebUsbTransport::require_device() const{ + if (!m_usb_device_desc){ + throw std::runtime_error("No USB device specified"); + } + } + + void WebUsbTransport::require_connected() const{ + require_device(); + if (!m_usb_device_handle){ + throw std::runtime_error("USB Device not opened"); + } + } + + void WebUsbTransport::enumerate(t_transport_vect & res) { + int r; + libusb_device **devs; + libusb_context *ctx = nullptr; + + r = libusb_init(&ctx); + CHECK_AND_ASSERT_THROW_MES(r >= 0, "Unable to init libusb"); + + set_libusb_log(ctx); + + ssize_t cnt = libusb_get_device_list(ctx, &devs); + if (cnt < 0){ + libusb_exit(ctx); + throw std::runtime_error("Unable to enumerate libusb devices"); + } + + MTRACE("Libusb devices: " << cnt); + + for(ssize_t i = 0; i < cnt; i++) { + libusb_device_descriptor desc{}; + r = libusb_get_device_descriptor(devs[i], &desc); + if (r < 0){ + MERROR("Unable to get libusb device descriptor " << i); + continue; + } + + const auto trezor_mask = get_trezor_dev_mask(&desc); + if (!trezor_mask){ + continue; + } + + MTRACE("Found Trezor device: " << desc.idVendor << ":" << desc.idProduct << " mask " << (int)trezor_mask); + + auto t = std::make_shared(boost::make_optional(&desc)); + t->m_bus_id = libusb_get_bus_number(devs[i]); + t->m_device_addr = libusb_get_device_address(devs[i]); + + // Port resolution may fail. Non-critical error, just addressing precision is decreased. + get_libusb_ports(devs[i], t->m_port_numbers); + + res.push_back(t); + } + + libusb_free_device_list(devs, 1); + libusb_exit(ctx); + } + + std::string WebUsbTransport::get_path() const { + if (!m_usb_device_desc){ + return ""; + } + + return get_usb_path(static_cast(m_bus_id), m_port_numbers); + }; + + void WebUsbTransport::open() { + const int interface = get_interface(); + if (m_conn_count > 0){ + MTRACE("Already opened, count: " << m_conn_count); + m_conn_count += 1; + return; + } + +#define TREZOR_DESTROY_SESSION() do { libusb_exit(m_usb_session); m_usb_session = nullptr; } while(0) + + int r; + libusb_device **devs = nullptr; + + if (m_usb_session) { + TREZOR_DESTROY_SESSION(); + } + + r = libusb_init(&m_usb_session); + CHECK_AND_ASSERT_THROW_MES(r >= 0, "Unable to init libusb"); + set_libusb_log(m_usb_session); + + bool found = false; + int open_res = 0; + + ssize_t cnt = libusb_get_device_list(m_usb_session, &devs); + if (cnt < 0){ + TREZOR_DESTROY_SESSION(); + throw std::runtime_error("Unable to enumerate libusb devices"); + } + + for (ssize_t i = 0; i < cnt; i++) { + libusb_device_descriptor desc{}; + r = libusb_get_device_descriptor(devs[i], &desc); + if (r < 0){ + MERROR("Unable to get libusb device descriptor " << i); + continue; + } + + const auto trezor_mask = get_trezor_dev_mask(&desc); + if (!trezor_mask) { + continue; + } + + auto bus_id = libusb_get_bus_number(devs[i]); + std::vector path; + + // Port resolution may fail. Non-critical error, just addressing precision is decreased. + get_libusb_ports(devs[i], path); + + MTRACE("Found Trezor device: " << desc.idVendor << ":" << desc.idProduct + << ", mask: " << (int)trezor_mask + << ". path: " << get_usb_path(bus_id, path)); + + if (bus_id == m_bus_id && path == m_port_numbers) { + found = true; + m_usb_device = devs[i]; + open_res = libusb_open(m_usb_device, &m_usb_device_handle); + break; + } + } + + libusb_free_device_list(devs, 1); + + if (!found){ + TREZOR_DESTROY_SESSION(); + throw exc::DeviceAcquireException("Device not found"); + + } else if (found && open_res != 0) { + m_usb_device_handle = nullptr; + m_usb_device = nullptr; + TREZOR_DESTROY_SESSION(); + throw exc::DeviceAcquireException("Unable to open libusb device"); + } + + r = libusb_claim_interface(m_usb_device_handle, interface); + + if (r != 0){ + libusb_close(m_usb_device_handle); + m_usb_device_handle = nullptr; + m_usb_device = nullptr; + TREZOR_DESTROY_SESSION(); + throw exc::DeviceAcquireException("Unable to claim libusb device"); + } + + m_conn_count += 1; + m_proto->session_begin(*this); + +#undef TREZOR_DESTROY_SESSION + }; + + void WebUsbTransport::close() { + m_conn_count -= 1; + + if (m_conn_count < 0){ + MERROR("Close counter is negative: " << m_conn_count); + + } else if (m_conn_count == 0){ + MTRACE("Closing webusb device"); + + m_proto->session_end(*this); + + int r = libusb_release_interface(m_usb_device_handle, get_interface()); + if (r != 0){ + MERROR("Could not release libusb interface: " << r); + } + + m_usb_device = nullptr; + if (m_usb_device_handle) { + libusb_close(m_usb_device_handle); + m_usb_device_handle = nullptr; + } + + if (m_usb_session) { + libusb_exit(m_usb_session); + m_usb_session = nullptr; + } + } + }; + + + int WebUsbTransport::get_interface() const{ + const int INTERFACE_NORMAL = 0; +#ifdef WITH_TREZOR_DEBUG + const int INTERFACE_DEBUG = 1; + return m_debug_mode ? INTERFACE_DEBUG : INTERFACE_NORMAL; +#else + return INTERFACE_NORMAL; +#endif + } + + unsigned char WebUsbTransport::get_endpoint() const{ + const unsigned char ENDPOINT_NORMAL = 1; +#ifdef WITH_TREZOR_DEBUG + const unsigned char ENDPOINT_DEBUG = 2; + return m_debug_mode ? ENDPOINT_DEBUG : ENDPOINT_NORMAL; +#else + return ENDPOINT_NORMAL; +#endif + } + + void WebUsbTransport::write(const google::protobuf::Message &req) { + m_proto->write(*this, req); + }; + + void WebUsbTransport::read(std::shared_ptr & msg, messages::MessageType * msg_type) { + m_proto->read(*this, msg, msg_type); + }; + + void WebUsbTransport::write_chunk(const void * buff, size_t size) { + require_connected(); + if (size != REPLEN){ + throw exc::CommunicationException("Invalid chunk size: "); + } + + unsigned char endpoint = get_endpoint(); + endpoint = (endpoint & ~LIBUSB_ENDPOINT_DIR_MASK) | LIBUSB_ENDPOINT_OUT; + + int transferred = 0; + int r = libusb_interrupt_transfer(m_usb_device_handle, endpoint, (unsigned char*)buff, (int)size, &transferred, 0); + CHECK_AND_ASSERT_THROW_MES(r == 0, "Unable to transfer, r: " << r); + if (transferred != (int)size){ + throw exc::CommunicationException("Could not transfer chunk"); + } + }; + + size_t WebUsbTransport::read_chunk(void * buff, size_t size) { + require_connected(); + unsigned char endpoint = get_endpoint(); + endpoint = (endpoint & ~LIBUSB_ENDPOINT_DIR_MASK) | LIBUSB_ENDPOINT_IN; + + int transferred = 0; + int r = libusb_interrupt_transfer(m_usb_device_handle, endpoint, (unsigned char*)buff, (int)size, &transferred, 0); + CHECK_AND_ASSERT_THROW_MES(r == 0, "Unable to transfer, r: " << r); + if (transferred != (int)size){ + throw exc::CommunicationException("Could not read the chunk"); + } + + return transferred; + }; + + std::ostream& WebUsbTransport::dump(std::ostream& o) const { + o << "WebUsbTransport"; + }; + +#endif // WITH_DEVICE_TREZOR_WEBUSB + void enumerate(t_transport_vect & res){ BridgeTransport bt; - bt.enumerate(res); + try{ + bt.enumerate(res); + } catch (const std::exception & e){ + MERROR("BridgeTransport enumeration failed:" << e.what()); + } + +#ifdef WITH_DEVICE_TREZOR_WEBUSB + hw::trezor::WebUsbTransport btw; + try{ + btw.enumerate(res); + } catch (const std::exception & e){ + MERROR("WebUsbTransport enumeration failed:" << e.what()); + } +#endif +#ifdef WITH_DEVICE_TREZOR_UDP hw::trezor::UdpTransport btu; - btu.enumerate(res); + try{ + btu.enumerate(res); + } catch (const std::exception & e){ + MERROR("UdpTransport enumeration failed:" << e.what()); + } +#endif } std::shared_ptr transport(const std::string & path){ @@ -633,6 +1029,9 @@ namespace trezor{ } } + GenericMessage::GenericMessage(messages::MessageType m_type, const shared_ptr &m_msg) + : m_type(m_type), m_msg(m_msg), m_empty(false) {} + std::ostream& operator<<(std::ostream& o, hw::trezor::Transport const& t){ return t.dump(o); } diff --git a/src/device_trezor/trezor/transport.hpp b/src/device_trezor/trezor/transport.hpp index 7b82fd06f..50c31cf73 100644 --- a/src/device_trezor/trezor/transport.hpp +++ b/src/device_trezor/trezor/transport.hpp @@ -239,6 +239,59 @@ namespace trezor { udp::endpoint m_endpoint; }; +#ifdef WITH_DEVICE_TREZOR_WEBUSB +#include + + class WebUsbTransport : public Transport { + public: + + explicit WebUsbTransport( + boost::optional descriptor = boost::none, + boost::optional> proto = boost::none + ); + + virtual ~WebUsbTransport(); + + static const char * PATH_PREFIX; + + std::string get_path() const override; + void enumerate(t_transport_vect & res) override; + + void open() override; + void close() override; + + void write(const google::protobuf::Message &req) override; + void read(std::shared_ptr & msg, messages::MessageType * msg_type=nullptr) override; + + void write_chunk(const void * buff, size_t size) override; + size_t read_chunk(void * buff, size_t size) override; + + std::ostream& dump(std::ostream& o) const override; + + private: + void require_device() const; + void require_connected() const; + int get_interface() const; + unsigned char get_endpoint() const; + + int m_conn_count; + std::shared_ptr m_proto; + + libusb_context *m_usb_session; + libusb_device *m_usb_device; + libusb_device_handle *m_usb_device_handle; + std::unique_ptr m_usb_device_desc; + std::vector m_port_numbers; + int m_bus_id; + int m_device_addr; + +#ifdef WITH_TREZOR_DEBUG + bool m_debug_mode; +#endif + }; + +#endif + // // General helpers // @@ -289,6 +342,20 @@ namespace trezor { */ [[ noreturn ]] void throw_failure_exception(const messages::common::Failure * failure); + /** + * Generic message holder, type + obj + */ + class GenericMessage { + public: + GenericMessage(): m_empty(true) {} + GenericMessage(messages::MessageType m_type, const std::shared_ptr &m_msg); + bool empty() const { return m_empty; } + + hw::trezor::messages::MessageType m_type; + std::shared_ptr m_msg; + bool m_empty; + }; + /** * Simple wrapper for write-read message exchange with expected message response type. * diff --git a/src/device_trezor/trezor/trezor_defs.hpp b/src/device_trezor/trezor/trezor_defs.hpp index 951a8f802..30e76eadc 100644 --- a/src/device_trezor/trezor/trezor_defs.hpp +++ b/src/device_trezor/trezor/trezor_defs.hpp @@ -27,14 +27,41 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // -#if defined(HAVE_PROTOBUF) && !defined(WITHOUT_TREZOR) - #define WITH_DEVICE_TREZOR 1 -#else - #define WITH_DEVICE_TREZOR 0 +#ifndef USE_DEVICE_TREZOR +#define USE_DEVICE_TREZOR 1 #endif -#ifndef WITH_DEVICE_TREZOR_LITE -#define WITH_DEVICE_TREZOR_LITE 0 +// HAVE_TREZOR_READY set by cmake after protobuf messages +// were generated successfully and all minimal dependencies are met. +#ifndef DEVICE_TREZOR_READY +#undef USE_DEVICE_TREZOR +#define USE_DEVICE_TREZOR 0 +#endif + +#if USE_DEVICE_TREZOR +#define WITH_DEVICE_TREZOR 1 +#endif + +#ifndef WITH_DEVICE_TREZOR +#undef WITH_DEVICE_TREZOR_LITE +#endif + +#if defined(HAVE_TREZOR_LIBUSB) && USE_DEVICE_TREZOR +#define WITH_DEVICE_TREZOR_WEBUSB 1 +#endif + +// Enable / disable UDP in the enumeration +#ifndef USE_DEVICE_TREZOR_UDP +#define USE_DEVICE_TREZOR_UDP 1 +#endif + +// Enable / disable UDP in the enumeration for release +#ifndef USE_DEVICE_TREZOR_UDP_RELEASE +#define USE_DEVICE_TREZOR_UDP_RELEASE 0 +#endif + +#if USE_DEVICE_TREZOR_UDP && (USE_DEVICE_TREZOR_UDP_RELEASE || defined(TREZOR_DEBUG)) +#define WITH_DEVICE_TREZOR_UDP 1 #endif // Avoids protobuf undefined macro warning From 1132436f972643328e81c3f8929178351a9b96fc Mon Sep 17 00:00:00 2001 From: Martijn Otto Date: Tue, 20 Nov 2018 17:11:06 +0100 Subject: [PATCH 0325/1007] Only show a single mlock() error, to avoid flooding the log --- contrib/epee/src/mlocker.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index c3262e8f4..1e831caf1 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -38,6 +38,12 @@ #include "syncobj.h" #include "mlocker.h" +#include + +// did an mlock operation previously fail? we only +// want to log an error once and be done with it +static std::atomic previously_failed{ false }; + static size_t query_page_size() { #if defined HAVE_MLOCK @@ -59,8 +65,8 @@ static void do_lock(void *ptr, size_t len) { #if defined HAVE_MLOCK int ret = mlock(ptr, len); - if (ret < 0) - MERROR("Error locking page at " << ptr << ": " << strerror(errno)); + if (ret < 0 && !previously_failed.exchange(true)) + MERROR("Error locking page at " << ptr << ": " << strerror(errno) << ", subsequent mlock errors will be silenced"); #else #warning Missing do_lock implementation #endif @@ -70,7 +76,10 @@ static void do_unlock(void *ptr, size_t len) { #if defined HAVE_MLOCK int ret = munlock(ptr, len); - if (ret < 0) + // check whether we previously failed, but don't set it, this is just + // to pacify the errors of mlock()ing failed, in which case unlocking + // is also not going to work of course + if (ret < 0 && !previously_failed.load()) MERROR("Error unlocking page at " << ptr << ": " << strerror(errno)); #else #warning Missing implementation of page size detection From 506472e0c6a1961ada5e1e68ff10def760e4316f Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 26 Nov 2018 17:19:25 +0000 Subject: [PATCH 0326/1007] protocol: fix use after free when dropping a connection --- src/cryptonote_protocol/cryptonote_protocol_handler.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index c2c660e8c..1a26e7ee8 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1738,9 +1738,9 @@ skip: if (add_fail) m_p2p->add_host_fail(context.m_remote_address); - m_p2p->drop_connection(context); - m_block_queue.flush_spans(context.m_connection_id, flush_all_spans); + + m_p2p->drop_connection(context); } //------------------------------------------------------------------------------------------------------------------------ template From fc98f7a0a13c1246b67ed4d7fb40705bb68a8b93 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 7 Nov 2018 21:13:00 +0000 Subject: [PATCH 0327/1007] rpc: speedup get_outs.bin --- contrib/epee/include/span.h | 2 ++ src/blockchain_db/blockchain_db.h | 4 +-- src/blockchain_db/lmdb/db_lmdb.cpp | 14 ++++++---- src/blockchain_db/lmdb/db_lmdb.h | 2 +- src/cryptonote_core/blockchain.cpp | 34 +++++++++++++++++++------ src/rpc/core_rpc_server_commands_defs.h | 4 ++- src/wallet/wallet2.cpp | 1 + tests/unit_tests/testdb.h | 2 +- 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h index 174915ecf..b1296a0b7 100644 --- a/contrib/epee/include/span.h +++ b/contrib/epee/include/span.h @@ -109,6 +109,8 @@ namespace epee constexpr std::size_t size() const noexcept { return len; } constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(value_type); } + const T &operator[](size_t idx) const { return ptr[idx]; } + private: T* ptr; std::size_t len; diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 7118b0881..53e33898a 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1307,11 +1307,11 @@ class BlockchainDB * get_output_data(const uint64_t& amount, const uint64_t& index) * but for a list of outputs rather than just one. * - * @param amount an output amount + * @param amounts an output amount, or as many as offsets * @param offsets a list of amount-specific output indices * @param outputs return-by-reference a list of outputs' metadata */ - virtual void get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) = 0; + virtual void get_output_key(const epee::span &amounts, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) = 0; /* * FIXME: Need to check with git blame and ask what this does to diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index ea3638a85..19f2de4dc 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -3197,8 +3197,11 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector &offsets, std::vector &outputs, bool allow_partial) +void BlockchainLMDB::get_output_key(const epee::span &amounts, const std::vector &offsets, std::vector &outputs, bool allow_partial) { + if (amounts.size() != 1 && amounts.size() != offsets.size()) + throw0(DB_ERROR("Invalid sizes of amounts and offets")); + LOG_PRINT_L3("BlockchainLMDB::" << __func__); TIME_MEASURE_START(db3); check_open(); @@ -3209,10 +3212,11 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector(amount) + ", index " + boost::lexical_cast(index) + ", count " + boost::lexical_cast(get_num_outputs(amount)) + "), but key does not exist (current height " + boost::lexical_cast(height()) + ")").c_str())); + throw1(OUTPUT_DNE((std::string("Attempting to get output pubkey by global index (amount ") + boost::lexical_cast(amount) + ", index " + boost::lexical_cast(offsets[i]) + ", count " + boost::lexical_cast(get_num_outputs(amount)) + "), but key does not exist (current height " + boost::lexical_cast(height()) + ")").c_str())); } else if (get_result) throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output pubkey from the db", get_result).c_str())); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 7e76236a5..26159ab4d 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -243,7 +243,7 @@ class BlockchainLMDB : public BlockchainDB virtual uint64_t get_num_outputs(const uint64_t& amount) const; virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index); - virtual void get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &outputs, bool allow_partial = false); + virtual void get_output_key(const epee::span &amounts, const std::vector &offsets, std::vector &outputs, bool allow_partial = false); virtual tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const; virtual void get_output_tx_and_index_from_global(const std::vector &global_indices, diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index e80e3f66c..bfc5dbbe0 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -229,7 +229,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke { try { - m_db->get_output_key(tx_in_to_key.amount, absolute_offsets, outputs, true); + m_db->get_output_key(epee::span(&tx_in_to_key.amount, 1), absolute_offsets, outputs, true); if (absolute_offsets.size() != outputs.size()) { MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount); @@ -255,7 +255,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke add_offsets.push_back(absolute_offsets[i]); try { - m_db->get_output_key(tx_in_to_key.amount, add_offsets, add_outputs, true); + m_db->get_output_key(epee::span(&tx_in_to_key.amount, 1), add_offsets, add_outputs, true); if (add_offsets.size() != add_outputs.size()) { MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount); @@ -1767,16 +1767,34 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA res.outs.clear(); res.outs.reserve(req.outputs.size()); + + std::vector data; try { + std::vector amounts, offsets; + amounts.reserve(req.outputs.size()); + offsets.reserve(req.outputs.size()); for (const auto &i: req.outputs) { - // get tx_hash, tx_out_index from DB - const output_data_t od = m_db->get_output_key(i.amount, i.index); - tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index); - bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)); + amounts.push_back(i.amount); + offsets.push_back(i.index); + } + m_db->get_output_key(epee::span(amounts.data(), amounts.size()), offsets, data); + if (data.size() != req.outputs.size()) + { + MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size()); + return false; + } + for (const auto &t: data) + res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash}); - res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first}); + if (req.get_txid) + { + for (size_t i = 0; i < req.outputs.size(); ++i) + { + tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index); + res.outs[i].txid = toi.first; + } } } catch (const std::exception &e) @@ -3795,7 +3813,7 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vectorget_output_key(amount, offsets, outputs, true); + m_db->get_output_key(epee::span(&amount, 1), offsets, outputs, true); } catch (const std::exception& e) { diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 8e8df7a52..94caab9f8 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -50,7 +50,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 2 -#define CORE_RPC_VERSION_MINOR 1 +#define CORE_RPC_VERSION_MINOR 2 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -697,9 +697,11 @@ namespace cryptonote struct request { std::vector outputs; + bool get_txid; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(outputs) + KV_SERIALIZE_OPT(get_txid, true) END_KV_SERIALIZE_MAP() }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 31be95a61..1638e920d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -7185,6 +7185,7 @@ void wallet2::get_outs(std::vector> } // get the keys for those + req.get_txid = false; m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, daemon_resp, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); diff --git a/tests/unit_tests/testdb.h b/tests/unit_tests/testdb.h index b6962cc41..a9c772920 100644 --- a/tests/unit_tests/testdb.h +++ b/tests/unit_tests/testdb.h @@ -93,7 +93,7 @@ class BaseTestDB: public cryptonote::BlockchainDB { virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const { return cryptonote::tx_out_index(); } virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const { return cryptonote::tx_out_index(); } virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector &offsets, std::vector &indices) const {} - virtual void get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) {} + virtual void get_output_key(const epee::span &amounts, const std::vector &offsets, std::vector &outputs, bool allow_partial = false) {} virtual bool can_thread_bulk_indices() const { return false; } virtual std::vector get_tx_output_indices(const crypto::hash& h) const { return std::vector(); } virtual std::vector get_tx_amount_output_indices(const uint64_t tx_index) const { return std::vector(); } From 0e2a5d75de9a503ae24a347395ae524072d394c6 Mon Sep 17 00:00:00 2001 From: stoffu Date: Wed, 7 Nov 2018 11:19:09 +0900 Subject: [PATCH 0328/1007] simplewallet: use is_transfer_unlocked instead of is_tx_spendtime_unlocked for show_transfers Followup on #4728 --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..784ceffe9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -6844,7 +6844,7 @@ bool simple_wallet::get_transfers(std::vector& local_args, std::vec std::string note = m_wallet->get_tx_note(pd.m_tx_hash); std::string destination = m_wallet->get_subaddress_as_str({m_current_subaddress_account, pd.m_subaddr_index.minor}); const std::string type = pd.m_coinbase ? tr("block") : tr("in"); - const bool unlocked = m_wallet->is_tx_spendtime_unlocked(pd.m_unlock_time, pd.m_block_height); + const bool unlocked = m_wallet->is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); transfers.push_back({ pd.m_block_height, pd.m_timestamp, From e98ae34e4b3487cfa2e7b2278349a49671c2e901 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 26 Nov 2018 23:42:14 +0000 Subject: [PATCH 0329/1007] core: fix adding new pre-hoh block when a tx is already in the pool --- src/cryptonote_core/cryptonote_core.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 10ab3fe65..348c788b9 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -900,13 +900,15 @@ namespace cryptonote bool ok = true; it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { - if (already_have[i]) - continue; if (!results[i].res) { ok = false; continue; } + if (keeped_by_block) + get_blockchain_storage().on_new_tx_from_block(results[i].tx); + if (already_have[i]) + continue; const size_t weight = get_transaction_weight(results[i].tx, it->size()); ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], results[i].prefix_hash, weight, tvc[i], keeped_by_block, relayed, do_not_relay); @@ -1137,9 +1139,6 @@ namespace cryptonote //----------------------------------------------------------------------------------------------- bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { - if (keeped_by_block) - get_blockchain_storage().on_new_tx_from_block(tx); - if(m_mempool.have_tx(tx_hash)) { LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool"); From 7cc27b367ecdfe1dca80ef24c6dcc513cb046dba Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 11 Nov 2018 21:31:48 +0000 Subject: [PATCH 0330/1007] Revert "easylogging++: make the logger handle early/late logging" This reverts commit 7f8bdeb35c73c70b2b65e30aa2a1cb93696355b3. --- external/easylogging++/easylogging++.cc | 12 ------------ external/easylogging++/easylogging++.h | 9 ++++----- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index d57f3f3a0..81179b0a3 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2191,17 +2191,6 @@ void VRegistry::setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) # define ELPP_DEFAULT_LOGGING_FLAGS 0x0 #endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS) // Storage -el::base::type::StoragePointer getresetELPP(bool reset) -{ - static el::base::type::StoragePointer p(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))); - if (reset) - p = NULL; - return p; -} -el::base::type::StoragePointer el::base::Storage::getELPP() -{ - return getresetELPP(false); -} #if ELPP_ASYNC_LOGGING Storage::Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : #else @@ -2250,7 +2239,6 @@ Storage::Storage(const LogBuilderPtr& defaultLogBuilder) : Storage::~Storage(void) { ELPP_INTERNAL_INFO(4, "Destroying storage"); - getresetELPP(true); #if ELPP_ASYNC_LOGGING ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 046252a5b..375010d46 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -2734,8 +2734,6 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { return it->second; } - static el::base::type::StoragePointer getELPP(); - private: base::RegisteredHitCounters* m_registeredHitCounters; base::RegisteredLoggers* m_registeredLoggers; @@ -2770,7 +2768,7 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { } }; extern ELPP_EXPORT base::type::StoragePointer elStorage; -#define ELPP el::base::Storage::getELPP() +#define ELPP el::base::elStorage class DefaultLogDispatchCallback : public LogDispatchCallback { protected: void handle(const LogDispatchData* data); @@ -4613,9 +4611,10 @@ el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ } #if ELPP_ASYNC_LOGGING -# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(NULL) +# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ +new el::base::AsyncDispatchWorker())) #else -# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(NULL) +# define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) #endif // ELPP_ASYNC_LOGGING #define INITIALIZE_NULL_EASYLOGGINGPP \ namespace el {\ From 721aacd88e780b30416deb66a68b87da8fe244ae Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 11 Nov 2018 21:34:37 +0000 Subject: [PATCH 0331/1007] easylogging++: faster access to logging Turns out getting the global shared_ptr hits the profile, and passing it around still keeps it at close to ~1% CPU, which is too much for mostly silent logging. Leak the object instead, which is even safer for late logging. --- contrib/valgrind/monero.supp | 9 +++++++++ external/easylogging++/easylogging++.cc | 6 ++++++ external/easylogging++/easylogging++.h | 6 ++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/contrib/valgrind/monero.supp b/contrib/valgrind/monero.supp index 16e34e82f..015b05a1c 100644 --- a/contrib/valgrind/monero.supp +++ b/contrib/valgrind/monero.supp @@ -17,3 +17,12 @@ fun:maybe_unlock_and_signal_one > ... } + +{ + we leak the logger, for performance reasons in on-the-fly init + Memcheck:Leak + match-leak-kinds: definite + fun:_Znwm + fun:_ZN2el4base7Storage7getELPPEv + ... +} diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index 81179b0a3..c24fb80cf 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2191,6 +2191,12 @@ void VRegistry::setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) # define ELPP_DEFAULT_LOGGING_FLAGS 0x0 #endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS) // Storage +el::base::type::StoragePointer &el::base::Storage::getELPP() +{ + if (!el::base::elStorage) + el::base::elStorage = new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder())); + return el::base::elStorage; +} #if ELPP_ASYNC_LOGGING Storage::Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : #else diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 375010d46..acf2a7674 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -552,7 +552,7 @@ typedef std::ostream ostream_t; typedef unsigned int EnumType; typedef unsigned short VerboseLevel; typedef unsigned long int LineNumber; -typedef std::shared_ptr StoragePointer; +typedef base::Storage *StoragePointer; typedef std::shared_ptr LogDispatchCallbackPtr; typedef std::shared_ptr PerformanceTrackingCallbackPtr; typedef std::shared_ptr LoggerRegistrationCallbackPtr; @@ -2734,6 +2734,8 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { return it->second; } + static el::base::type::StoragePointer &getELPP(); + private: base::RegisteredHitCounters* m_registeredHitCounters; base::RegisteredLoggers* m_registeredLoggers; @@ -2768,7 +2770,7 @@ class Storage : base::NoCopy, public base::threading::ThreadSafe { } }; extern ELPP_EXPORT base::type::StoragePointer elStorage; -#define ELPP el::base::elStorage +#define ELPP el::base::Storage::getELPP() class DefaultLogDispatchCallback : public LogDispatchCallback { protected: void handle(const LogDispatchData* data); From 5ca4994c9c31228139317c4278e1868598a0b975 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 7 Nov 2018 14:57:41 +0000 Subject: [PATCH 0332/1007] rpc: speed up the common get_output_distribution case while syncing --- src/rpc/rpc_handler.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/rpc/rpc_handler.cpp b/src/rpc/rpc_handler.cpp index 63664bf8b..e0a81c70f 100644 --- a/src/rpc/rpc_handler.cpp +++ b/src/rpc/rpc_handler.cpp @@ -43,8 +43,25 @@ namespace rpc std::vector distribution; std::uint64_t start_height, base; - if (!f(amount, from_height, to_height, start_height, distribution, base)) - return boost::none; + + // see if we can extend the cache - a common case + if (d.cached && amount == 0 && d.cached_from == from_height && to_height > d.cached_to) + { + std::vector new_distribution; + if (!f(amount, d.cached_to + 1, to_height, start_height, new_distribution, base)) + return boost::none; + distribution = d.cached_distribution; + distribution.reserve(distribution.size() + new_distribution.size()); + for (const auto &e: new_distribution) + distribution.push_back(e); + start_height = d.cached_start_height; + base = d.cached_base; + } + else + { + if (!f(amount, from_height, to_height, start_height, distribution, base)) + return boost::none; + } if (to_height > 0 && to_height >= from_height) { From 756684bb28482d953f822bbb9940c9b482b40054 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 10 Nov 2018 13:46:37 +0000 Subject: [PATCH 0333/1007] blockchain: avoid unnecessary DB lookups when syncing Some of the inputs for block in a span will be from other earlier blocks in that span. Keep track of those outputs so we don't have to look them up again after those early blocks are added to the blockchain. --- src/cryptonote_core/blockchain.cpp | 117 +++++++++++++++++++++-------- src/cryptonote_core/blockchain.h | 4 +- 2 files changed, 86 insertions(+), 35 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index bfc5dbbe0..a6e35acc8 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3723,7 +3723,7 @@ void Blockchain::set_enforce_dns_checkpoints(bool enforce_checkpoints) } //------------------------------------------------------------------ -void Blockchain::block_longhash_worker(uint64_t height, const std::vector &blocks, std::unordered_map &map) const +void Blockchain::block_longhash_worker(uint64_t height, const epee::span &blocks, std::unordered_map &map) const { TIME_MEASURE_START(t); slow_hash_allocate_state(); @@ -3809,11 +3809,33 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) } //------------------------------------------------------------------ -void Blockchain::output_scan_worker(const uint64_t amount, const std::vector &offsets, std::vector &outputs) const +void Blockchain::output_scan_worker(const uint64_t amount, const std::vector &offsets, std::vector &outputs, const std::vector &extra_tx_map) const { try { m_db->get_output_key(epee::span(&amount, 1), offsets, outputs, true); + if (outputs.size() < offsets.size()) + { + const uint64_t n_outputs = m_db->get_num_outputs(amount); + for (size_t i = outputs.size(); i < offsets.size(); ++i) + { + uint64_t idx = offsets[i]; + if (idx < n_outputs) + { + MWARNING("Index " << idx << " not found in db for amount " << amount << ", but it is less than the number of entries"); + break; + } + else if (idx < n_outputs + extra_tx_map.size()) + { + outputs.push_back(extra_tx_map[idx - n_outputs]); + } + else + { + MWARNING("missed " << amount << "/" << idx << " in " << extra_tx_map.size() << " (chain " << n_outputs << ")"); + break; + } + } + } } catch (const std::exception& e) { @@ -3928,6 +3950,34 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::vector // vs [k_image, output_keys] (m_scan_table). This is faster because it takes advantage of bulk queries // and is threaded if possible. The table (m_scan_table) will be used later when querying output // keys. +static bool update_output_map(std::map> &extra_tx_map, const transaction &tx, uint64_t height, bool miner) +{ + MTRACE("Blockchain::" << __func__); + for (size_t i = 0; i < tx.vout.size(); ++i) + { + const auto &out = tx.vout[i]; + if (out.target.type() != typeid(txout_to_key)) + continue; + const txout_to_key &out_to_key = boost::get(out.target); + rct::key commitment; + uint64_t amount = out.amount; + if (miner && tx.version == 2) + { + commitment = rct::zeroCommit(amount); + amount = 0; + } + else if (tx.version > 1) + { + CHECK_AND_ASSERT_MES(i < tx.rct_signatures.outPk.size(), false, "Invalid outPk size"); + commitment = tx.rct_signatures.outPk[i].mask; + } + else + commitment = rct::zero(); + extra_tx_map[amount].push_back(output_data_t{out_to_key.key, tx.unlock_time, height, commitment}); + } + return true; +} + bool Blockchain::prepare_handle_incoming_blocks(const std::vector &blocks_entry) { MTRACE("Blockchain::" << __func__); @@ -3974,42 +4024,40 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vectorheight() + blocks_entry.size()) < m_blocks_hash_check.size()) + const uint64_t height = m_db->height(); + if ((height + blocks_entry.size()) < m_blocks_hash_check.size()) return true; bool blocks_exist = false; tools::threadpool& tpool = tools::threadpool::getInstance(); - uint64_t threads = tpool.get_max_concurrency(); + unsigned threads = tpool.get_max_concurrency(); + std::vector blocks; + blocks.resize(blocks_entry.size()); - if (blocks_entry.size() > 1 && threads > 1 && m_max_prepare_blocks_threads > 1) + if (1) { // limit threads, default limit = 4 if(threads > m_max_prepare_blocks_threads) threads = m_max_prepare_blocks_threads; - uint64_t height = m_db->height(); - int batches = blocks_entry.size() / threads; - int extra = blocks_entry.size() % threads; + unsigned int batches = blocks_entry.size() / threads; + unsigned int extra = blocks_entry.size() % threads; MDEBUG("block_batches: " << batches); std::vector> maps(threads); - std::vector < std::vector < block >> blocks(threads); auto it = blocks_entry.begin(); + unsigned blockidx = 0; - for (uint64_t i = 0; i < threads; i++) + for (unsigned i = 0; i < threads; i++) { - blocks[i].reserve(batches + 1); - for (int j = 0; j < batches; j++) + for (unsigned int j = 0; j < batches; j++, ++blockidx) { - block block; + block &block = blocks[blockidx]; if (!parse_and_validate_block_from_blob(it->block, block)) - { - std::advance(it, 1); - continue; - } + return false; // check first block and skip all blocks if its not chained properly - if (i == 0 && j == 0) + if (blockidx == 0) { crypto::hash tophash = m_db->top_block_hash(); if (block.prev_id != tophash) @@ -4024,20 +4072,16 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vectorblock, block)) - { - std::advance(it, 1); - continue; - } + return false; if (have_block(get_block_hash(block))) { @@ -4045,7 +4089,6 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector(&blocks[i], nblocks), std::ref(maps[i])), true); + thread_height += nblocks; } waiter.wait(&tpool); @@ -4100,7 +4146,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector> offset_map; // [output] stores all output_data_t for each absolute_offset - std::map> tx_map; + std::map> tx_map, extra_tx_map; std::vector> txes(total_txs); #define SCAN_TABLE_QUIT(m) \ @@ -4111,12 +4157,14 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector= txes.size()) @@ -4175,7 +4223,10 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector &offsets, - std::vector &outputs) const; + std::vector &outputs, const std::vector &extra_tx_map) const; /** * @brief computes the "short" and "long" hashes for a set of blocks @@ -927,7 +927,7 @@ namespace cryptonote * @param blocks the blocks to be hashed * @param map return-by-reference the hashes for each block */ - void block_longhash_worker(uint64_t height, const std::vector &blocks, + void block_longhash_worker(uint64_t height, const epee::span &blocks, std::unordered_map &map) const; /** From 17b45725af754a3887f0c59bd5c67c58278d71eb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 24 Nov 2018 14:49:04 +0000 Subject: [PATCH 0334/1007] Outputs where all amounts are known spent can now be pruned Only for pre rct for obvious reasons. Note: DO NOT use a known spent list which includes outputs which are not known spent. If the list includes any output that's just strongly thought to be spent, but not provably so, you risk finding yourself unable to sync past the point where that output is spent. I estimate only 200 MB saved on current mainnet though, unless the new blackballing rule unearths a good amount of large-amount-set extra spent outs. --- src/blockchain_db/blockchain_db.h | 7 + src/blockchain_db/lmdb/db_lmdb.cpp | 70 ++++- src/blockchain_db/lmdb/db_lmdb.h | 2 + src/blockchain_utilities/CMakeLists.txt | 33 +++ .../blockchain_prune_known_spent_data.cpp | 268 ++++++++++++++++++ tests/unit_tests/testdb.h | 1 + 6 files changed, 377 insertions(+), 4 deletions(-) create mode 100644 src/blockchain_utilities/blockchain_prune_known_spent_data.cpp diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 53e33898a..a8f4eafe0 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1405,6 +1405,13 @@ class BlockchainDB */ virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const = 0; + /** + * @brief prune output data for the given amount + * + * @param amount the amount for which to prune data + */ + virtual void prune_outputs(uint64_t amount) = 0; + /** * @brief runs a function over all txpool transactions * diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index d260caa75..142e86b5d 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1077,6 +1077,60 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in throw0(DB_ERROR(lmdb_error(std::string("Error deleting amount for output index ").append(boost::lexical_cast(out_index).append(": ")).c_str(), result).c_str())); } +void BlockchainLMDB::prune_outputs(uint64_t amount) +{ + LOG_PRINT_L3("BlockchainLMDB::" << __func__); + check_open(); + mdb_txn_cursors *m_cursors = &m_wcursors; + CURSOR(output_amounts); + CURSOR(output_txs); + + MINFO("Pruning outputs for amount " << amount); + + MDB_val v; + MDB_val_set(k, amount); + int result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET); + if (result == MDB_NOTFOUND) + return; + if (result) + throw0(DB_ERROR(lmdb_error("Error looking up outputs: ", result).c_str())); + + // gather output ids + mdb_size_t num_elems; + mdb_cursor_count(m_cur_output_amounts, &num_elems); + MINFO(num_elems << " outputs found"); + std::vector output_ids; + output_ids.reserve(num_elems); + while (1) + { + const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data; + output_ids.push_back(okp->output_id); + MDEBUG("output id " << okp->output_id); + result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_NEXT_DUP); + if (result == MDB_NOTFOUND) + break; + if (result) + throw0(DB_ERROR(lmdb_error("Error counting outputs: ", result).c_str())); + } + if (output_ids.size() != num_elems) + throw0(DB_ERROR("Unexpected number of outputs")); + + result = mdb_cursor_del(m_cur_output_amounts, MDB_NODUPDATA); + if (result) + throw0(DB_ERROR(lmdb_error("Error deleting outputs: ", result).c_str())); + + for (uint64_t output_id: output_ids) + { + MDB_val_set(v, output_id); + result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + if (result) + throw0(DB_ERROR(lmdb_error("Error looking up output: ", result).c_str())); + result = mdb_cursor_del(m_cur_output_txs, 0); + if (result) + throw0(DB_ERROR(lmdb_error("Error deleting output: ", result).c_str())); + } +} + void BlockchainLMDB::add_spent_key(const crypto::key_image& k_image) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -2231,11 +2285,19 @@ uint64_t BlockchainLMDB::num_outputs() const TXN_PREFIX_RDONLY(); int result; - // get current height - MDB_stat db_stats; - if ((result = mdb_stat(m_txn, m_output_txs, &db_stats))) + RCURSOR(output_txs) + + uint64_t num = 0; + MDB_val k, v; + result = mdb_cursor_get(m_cur_output_txs, &k, &v, MDB_LAST); + if (result == MDB_NOTFOUND) + num = 0; + else if (result == 0) + num = 1 + ((const outtx*)v.mv_data)->output_id; + else throw0(DB_ERROR(lmdb_error("Failed to query m_output_txs: ", result).c_str())); - return db_stats.ms_entries; + + return num; } bool BlockchainLMDB::tx_exists(const crypto::hash& h) const diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 26159ab4d..6db241240 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -345,6 +345,8 @@ class BlockchainLMDB : public BlockchainDB void remove_output(const uint64_t amount, const uint64_t& out_index); + virtual void prune_outputs(uint64_t amount); + virtual void add_spent_key(const crypto::key_image& k_image); virtual void remove_spent_key(const crypto::key_image& k_image); diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index c9ad1cebe..ddf575c29 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -81,6 +81,17 @@ monero_private_headers(blockchain_usage +set(blockchain_prune_known_spent_data_sources + blockchain_prune_known_spent_data.cpp + ) + +set(blockchain_prune_known_spent_data_private_headers) + +monero_private_headers(blockchain_prune_known_spent_data + ${blockchain_prune_known_spent_data_private_headers}) + + + set(blockchain_ancestry_sources blockchain_ancestry.cpp ) @@ -265,3 +276,25 @@ set_property(TARGET blockchain_stats PROPERTY OUTPUT_NAME "monero-blockchain-stats") install(TARGETS blockchain_stats DESTINATION bin) + +monero_add_executable(blockchain_prune_known_spent_data + ${blockchain_prune_known_spent_data_sources} + ${blockchain_prune_known_spent_data_private_headers}) + +target_link_libraries(blockchain_prune_known_spent_data + PRIVATE + cryptonote_core + blockchain_db + p2p + version + epee + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) + +set_property(TARGET blockchain_prune_known_spent_data + PROPERTY + OUTPUT_NAME "monero-blockchain-prune-known-spent-data") +install(TARGETS blockchain_prune_known_spent_data DESTINATION bin) diff --git a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp new file mode 100644 index 000000000..1a5869e9d --- /dev/null +++ b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp @@ -0,0 +1,268 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. 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. +// +// 3. Neither the name of the copyright holder nor the names of its contributors 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 HOLDER 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. + +#include +#include "common/command_line.h" +#include "serialization/crypto.h" +#include "cryptonote_core/tx_pool.h" +#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_core/blockchain.h" +#include "blockchain_db/blockchain_db.h" +#include "blockchain_db/db_types.h" +#include "version.h" + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "bcutil" + +namespace po = boost::program_options; +using namespace epee; +using namespace cryptonote; + +static std::map load_outputs(const std::string &filename) +{ + std::map outputs; + uint64_t amount = std::numeric_limits::max(); + FILE *f; + + f = fopen(filename.c_str(), "r"); + if (!f) + { + MERROR("Failed to load outputs from " << filename << ": " << strerror(errno)); + return {}; + } + while (1) + { + char s[256]; + if (!fgets(s, sizeof(s), f)) + break; + if (feof(f)) + break; + const size_t len = strlen(s); + if (len > 0 && s[len - 1] == '\n') + s[len - 1] = 0; + if (!s[0]) + continue; + std::pair output; + uint64_t offset, num_offsets; + if (sscanf(s, "@%" PRIu64, &amount) == 1) + { + continue; + } + if (amount == std::numeric_limits::max()) + { + MERROR("Bad format in " << filename); + continue; + } + if (sscanf(s, "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets < std::numeric_limits::max() - offset) + { + outputs[amount] += num_offsets; + } + else if (sscanf(s, "%" PRIu64, &offset) == 1) + { + outputs[amount] += 1; + } + else + { + MERROR("Bad format in " << filename); + continue; + } + } + fclose(f); + return outputs; +} + +int main(int argc, char* argv[]) +{ + TRY_ENTRY(); + + epee::string_tools::set_module_name_and_folder(argv[0]); + + std::string default_db_type = "lmdb"; + + std::string available_dbs = cryptonote::blockchain_db_types(", "); + available_dbs = "available: " + available_dbs; + + uint32_t log_level = 0; + + tools::on_startup(); + + po::options_description desc_cmd_only("Command line options"); + po::options_description desc_cmd_sett("Command line options and settings options"); + const command_line::arg_descriptor arg_log_level = {"log-level", "0-4 or categories", ""}; + const command_line::arg_descriptor arg_database = { + "database", available_dbs.c_str(), default_db_type + }; + const command_line::arg_descriptor arg_verbose = {"verbose", "Verbose output", false}; + const command_line::arg_descriptor arg_dry_run = {"dry-run", "Do not actually prune", false}; + const command_line::arg_descriptor arg_input = {"input", "Path to the known spent outputs file"}; + + command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir); + command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on); + command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on); + command_line::add_arg(desc_cmd_sett, arg_log_level); + command_line::add_arg(desc_cmd_sett, arg_database); + command_line::add_arg(desc_cmd_sett, arg_verbose); + command_line::add_arg(desc_cmd_sett, arg_dry_run); + command_line::add_arg(desc_cmd_sett, arg_input); + command_line::add_arg(desc_cmd_only, command_line::arg_help); + + po::options_description desc_options("Allowed options"); + desc_options.add(desc_cmd_only).add(desc_cmd_sett); + + po::variables_map vm; + bool r = command_line::handle_error_helper(desc_options, [&]() + { + auto parser = po::command_line_parser(argc, argv).options(desc_options); + po::store(parser.run(), vm); + po::notify(vm); + return true; + }); + if (! r) + return 1; + + if (command_line::get_arg(vm, command_line::arg_help)) + { + std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; + std::cout << desc_options << std::endl; + return 1; + } + + mlog_configure(mlog_get_default_log_path("monero-blockchain-prune-known-spent-data.log"), true); + if (!command_line::is_arg_defaulted(vm, arg_log_level)) + mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); + else + mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); + + LOG_PRINT_L0("Starting..."); + + std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir); + bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); + bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); + network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET; + bool opt_verbose = command_line::get_arg(vm, arg_verbose); + bool opt_dry_run = command_line::get_arg(vm, arg_dry_run); + + std::string db_type = command_line::get_arg(vm, arg_database); + if (!cryptonote::blockchain_valid_db_type(db_type)) + { + std::cerr << "Invalid database type: " << db_type << std::endl; + return 1; + } + + const std::string input = command_line::get_arg(vm, arg_input); + if (input.empty()) + { + LOG_PRINT_L0("No input given"); + return 1; + } + + LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); + std::unique_ptr core_storage; + tx_memory_pool m_mempool(*core_storage); + core_storage.reset(new Blockchain(m_mempool)); + BlockchainDB *db = new_db(db_type); + if (db == NULL) + { + LOG_ERROR("Attempted to use non-existent database type: " << db_type); + throw std::runtime_error("Attempting to use non-existent database type"); + } + LOG_PRINT_L0("database: " << db_type); + + const std::string filename = (boost::filesystem::path(opt_data_dir) / db->get_db_name()).string(); + LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); + + try + { + db->open(filename, 0); + } + catch (const std::exception& e) + { + LOG_PRINT_L0("Error opening database: " << e.what()); + return 1; + } + r = core_storage->init(db, net_type); + + CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); + LOG_PRINT_L0("Source blockchain storage initialized OK"); + + LOG_PRINT_L0("Loading known spent data..."); + const std::map known_spent_outputs = load_outputs(input); + + LOG_PRINT_L0("Pruning known spent data..."); + + bool stop_requested = false; + tools::signal_handler::install([&stop_requested](int type) { + stop_requested = true; + }); + + db->batch_start(); + + size_t num_total_outputs = 0, num_prunable_outputs = 0, num_known_spent_outputs = 0, num_eligible_outputs = 0, num_eligible_known_spent_outputs = 0; + for (auto i = known_spent_outputs.begin(); i != known_spent_outputs.end(); ++i) + { + uint64_t num_outputs = db->get_num_outputs(i->first); + num_total_outputs += num_outputs; + num_known_spent_outputs += i->second; + if (i->first == 0 || is_valid_decomposed_amount(i->first)) + { + if (opt_verbose) + MINFO("Ignoring output value " << i->first << ", with " << num_outputs << " outputs"); + continue; + } + num_eligible_outputs += num_outputs; + num_eligible_known_spent_outputs += i->second; + if (opt_verbose) + MINFO(i->first << ": " << i->second << "/" << num_outputs); + if (num_outputs > i->second) + continue; + if (num_outputs && num_outputs < i->second) + { + MERROR("More outputs are spent than known for amount " << i->first << ", not touching"); + continue; + } + if (opt_verbose) + MINFO("Pruning data for " << num_outputs << " outputs"); + if (!opt_dry_run) + db->prune_outputs(i->first); + num_prunable_outputs += i->second; + } + + db->batch_stop(); + + MINFO("Total outputs: " << num_total_outputs); + MINFO("Known spent outputs: " << num_known_spent_outputs); + MINFO("Eligible outputs: " << num_eligible_outputs); + MINFO("Eligible known spent outputs: " << num_eligible_known_spent_outputs); + MINFO("Prunable outputs: " << num_prunable_outputs); + + LOG_PRINT_L0("Blockchain known spent data pruned OK"); + core_storage->deinit(); + return 0; + + CATCH_ENTRY("Error", 1); +} diff --git a/tests/unit_tests/testdb.h b/tests/unit_tests/testdb.h index a9c772920..5d9ba5833 100644 --- a/tests/unit_tests/testdb.h +++ b/tests/unit_tests/testdb.h @@ -142,5 +142,6 @@ class BaseTestDB: public cryptonote::BlockchainDB { virtual bool prune_blockchain(uint32_t pruning_seed = 0) { return true; } virtual bool update_pruning() { return true; } virtual bool check_pruning() { return true; } + virtual void prune_outputs(uint64_t amount) {} }; From a48f2dab00a81ab716f38022dc3197d841b63b7e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 27 Nov 2018 15:44:01 +0000 Subject: [PATCH 0335/1007] blockchain_prune_known_spent_data: blackball file is now optional If not present, the tool will scan the blockchain, since scanning for this is fairly fast. --- .../blockchain_prune_known_spent_data.cpp | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp index 1a5869e9d..f6136c1ba 100644 --- a/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp +++ b/src/blockchain_utilities/blockchain_prune_known_spent_data.cpp @@ -175,11 +175,6 @@ int main(int argc, char* argv[]) } const std::string input = command_line::get_arg(vm, arg_input); - if (input.empty()) - { - LOG_PRINT_L0("No input given"); - return 1; - } LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); std::unique_ptr core_storage; @@ -210,8 +205,50 @@ int main(int argc, char* argv[]) CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); LOG_PRINT_L0("Source blockchain storage initialized OK"); - LOG_PRINT_L0("Loading known spent data..."); - const std::map known_spent_outputs = load_outputs(input); + std::map known_spent_outputs; + if (input.empty()) + { + std::map> outputs; + + LOG_PRINT_L0("Scanning for known spent data..."); + db->for_all_transactions([&](const crypto::hash &txid, const cryptonote::transaction &tx){ + const bool miner_tx = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen); + for (const auto &in: tx.vin) + { + if (in.type() != typeid(txin_to_key)) + continue; + const auto &txin = boost::get(in); + if (txin.amount == 0) + continue; + + outputs[txin.amount].second++; + } + + for (const auto &out: tx.vout) + { + uint64_t amount = out.amount; + if (miner_tx && tx.version >= 2) + amount = 0; + if (amount == 0) + continue; + if (out.target.type() != typeid(txout_to_key)) + continue; + + outputs[amount].first++; + } + return true; + }, true); + + for (const auto &i: outputs) + { + known_spent_outputs[i.first] = i.second.second; + } + } + else + { + LOG_PRINT_L0("Loading known spent data..."); + known_spent_outputs = load_outputs(input); + } LOG_PRINT_L0("Pruning known spent data..."); From dc1c12528d5cf86759993614e1fdd7d7bf04ff15 Mon Sep 17 00:00:00 2001 From: Jason Wong Date: Sun, 25 Nov 2018 22:08:07 +0100 Subject: [PATCH 0336/1007] add command pop_blocks add new public method to Blockchain and update according to code review update after review: better lock/unlock, try catch and coding style --- src/cryptonote_core/blockchain.cpp | 32 +++++++++++++++++++++++++ src/cryptonote_core/blockchain.h | 7 ++++++ src/daemon/command_parser_executor.cpp | 25 +++++++++++++++++++ src/daemon/command_parser_executor.h | 2 ++ src/daemon/command_server.cpp | 6 +++++ src/daemon/rpc_command_executor.cpp | 27 +++++++++++++++++++++ src/daemon/rpc_command_executor.h | 2 ++ src/rpc/core_rpc_server.cpp | 12 ++++++++++ src/rpc/core_rpc_server.h | 2 ++ src/rpc/core_rpc_server_commands_defs.h | 23 ++++++++++++++++++ 10 files changed, 138 insertions(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index bfc5dbbe0..009c5e2ed 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -576,6 +576,38 @@ bool Blockchain::deinit() return true; } //------------------------------------------------------------------ +// This function removes blocks from the top of blockchain. +// It starts a batch and calls private method pop_block_from_blockchain(). +void Blockchain::pop_blocks(uint64_t nblocks) +{ + uint64_t i; + CRITICAL_REGION_LOCAL(m_tx_pool); + CRITICAL_REGION_LOCAL1(m_blockchain_lock); + + while (!m_db->batch_start()) + { + m_blockchain_lock.unlock(); + m_tx_pool.unlock(); + epee::misc_utils::sleep_no_w(1000); + m_tx_pool.lock(); + m_blockchain_lock.lock(); + } + + try + { + for (i=0; i < nblocks; ++i) + { + pop_block_from_blockchain(); + } + } + catch (const std::exception& e) + { + LOG_ERROR("Error when popping blocks, only " << i << " blocks are popped: " << e.what()); + } + + m_db->batch_stop(); +} +//------------------------------------------------------------------ // This function tells BlockchainDB to remove the top block from the // blockchain and then returns all transactions (except the miner tx, of course) // from it to the tx_pool diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index dfe833fb4..f1e366c9e 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -967,6 +967,13 @@ namespace cryptonote */ std::vector get_last_block_timestamps(unsigned int blocks) const; + /** + * @brief removes blocks from the top of the blockchain + * + * @param nblocks number of blocks to be removed + */ + void pop_blocks(uint64_t nblocks); + private: // TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 1638cf505..853cde9c3 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -674,6 +674,31 @@ bool t_command_parser_executor::sync_info(const std::vector& args) return m_executor.sync_info(); } +bool t_command_parser_executor::pop_blocks(const std::vector& args) +{ + if (args.size() != 1) + { + std::cout << "Exactly one parameter is needed" << std::endl; + return false; + } + + try + { + uint64_t nblocks = boost::lexical_cast(args[0]); + if (nblocks < 1) + { + std::cout << "number of blocks must be greater than 0" << std::endl; + return false; + } + return m_executor.pop_blocks(nblocks); + } + catch (const boost::bad_lexical_cast&) + { + std::cout << "number of blocks must be a number greater than 0" << std::endl; + } + return false; +} + bool t_command_parser_executor::version(const std::vector& args) { std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl; diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index a70070171..e2844e8b7 100644 --- a/src/daemon/command_parser_executor.h +++ b/src/daemon/command_parser_executor.h @@ -139,6 +139,8 @@ class t_command_parser_executor final bool sync_info(const std::vector& args); + bool pop_blocks(const std::vector& args); + bool version(const std::vector& args); }; diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 35504f2c9..527ed2cf1 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -281,6 +281,12 @@ t_command_server::t_command_server( , std::bind(&t_command_parser_executor::sync_info, &m_parser, p::_1) , "Print information about the blockchain sync state." ); + m_command_lookup.set_handler( + "pop_blocks" + , std::bind(&t_command_parser_executor::pop_blocks, &m_parser, p::_1) + , "pop_blocks " + , "Remove blocks from end of blockchain" + ); m_command_lookup.set_handler( "version" , std::bind(&t_command_parser_executor::version, &m_parser, p::_1) diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 5ae9851a7..015e1e1f9 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1967,4 +1967,31 @@ bool t_rpc_command_executor::sync_info() return true; } +bool t_rpc_command_executor::pop_blocks(uint64_t num_blocks) +{ + cryptonote::COMMAND_RPC_POP_BLOCKS::request req; + cryptonote::COMMAND_RPC_POP_BLOCKS::response res; + std::string fail_message = "pop_blocks failed"; + + req.nblocks = num_blocks; + if (m_is_rpc) + { + if (!m_rpc_client->rpc_request(req, res, "/pop_blocks", fail_message.c_str())) + { + return true; + } + } + else + { + if (!m_rpc_server->on_pop_blocks(req, res) || res.status != CORE_RPC_STATUS_OK) + { + tools::fail_msg_writer() << make_error(fail_message, res.status); + return true; + } + } + tools::success_msg_writer() << "new height: " << res.height; + + return true; +} + }// namespace daemonize diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index 9e6010c5b..592584a5f 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -152,6 +152,8 @@ class t_rpc_command_executor final { bool relay_tx(const std::string &txid); bool sync_info(); + + bool pop_blocks(uint64_t num_blocks); }; } // namespace daemonize diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index f029d1d5a..2fb70c995 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -2021,6 +2021,18 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res) + { + PERF_TIMER(on_pop_blocks); + + m_core.get_blockchain_storage().pop_blocks(req.nblocks); + + res.height = m_core.get_current_blockchain_height(); + res.status = CORE_RPC_STATUS_OK; + + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp) { PERF_TIMER(on_relay_tx); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index 8ada0af15..9edbc71d7 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -118,6 +118,7 @@ namespace cryptonote MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS) MAP_URI_AUTO_JON2_IF("/update", on_update, COMMAND_RPC_UPDATE, !m_restricted) MAP_URI_AUTO_BIN2("/get_output_distribution.bin", on_get_output_distribution_bin, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION) + MAP_URI_AUTO_JON2_IF("/pop_blocks", on_pop_blocks, COMMAND_RPC_POP_BLOCKS, !m_restricted) BEGIN_JSON_RPC_MAP("/json_rpc") MAP_JON_RPC("get_block_count", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT) @@ -189,6 +190,7 @@ namespace cryptonote bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res); bool on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res); bool on_get_output_distribution_bin(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res); + bool on_pop_blocks(const COMMAND_RPC_POP_BLOCKS::request& req, COMMAND_RPC_POP_BLOCKS::response& res); //json_rpc bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index ce0be9c41..c5dbdcbc4 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -2326,4 +2326,27 @@ namespace cryptonote }; }; + struct COMMAND_RPC_POP_BLOCKS + { + struct request + { + uint64_t nblocks; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(nblocks); + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string status; + uint64_t height; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(status) + KV_SERIALIZE(height) + END_KV_SERIALIZE_MAP() + }; + }; + } From 318cc78457136ec778d6dff43b36f9447d95a43d Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Sun, 11 Nov 2018 20:07:25 +0100 Subject: [PATCH 0337/1007] device/trezor: passphrase entry on host - simple device callback object added. Device can request passphrase/PIN entry via the callback or notify user some action is required - callback is routed to wallet2, which routes the callback to i_wallet_callback so CLI or GUI wallets can support passphrase entry for HW tokens - wallet: device open needs wallet callback first - passphrase protected device needs wallet callback so user can enter passphrase --- src/device/device.hpp | 9 ++++ src/device_trezor/device_trezor_base.cpp | 6 +-- src/device_trezor/device_trezor_base.hpp | 19 +++------ src/simplewallet/simplewallet.cpp | 37 ++++++++++++++++- src/simplewallet/simplewallet.h | 3 ++ src/wallet/wallet2.cpp | 52 ++++++++++++++++++++++-- src/wallet/wallet2.h | 22 ++++++++++ src/wallet/wallet_errors.h | 8 ++++ 8 files changed, 134 insertions(+), 22 deletions(-) diff --git a/src/device/device.hpp b/src/device/device.hpp index dd9ad4332..3e782d21a 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -80,6 +80,14 @@ namespace hw { return false; } + class i_device_callback { + public: + virtual void on_button_request() {} + virtual void on_pin_request(epee::wipeable_string & pin) {} + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {} + virtual ~i_device_callback() = default; + }; + class device { protected: std::string name; @@ -129,6 +137,7 @@ namespace hw { virtual device_type get_type() const = 0; virtual device_protocol_t device_protocol() const { return PROTOCOL_DEFAULT; }; + virtual void set_callback(i_device_callback * callback) {}; /* ======================================================================= */ /* LOCKER */ diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index 38c20c30b..dcfc9cb67 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -39,7 +39,7 @@ namespace trezor { const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; - device_trezor_base::device_trezor_base() { + device_trezor_base::device_trezor_base(): m_callback(nullptr) { } @@ -332,10 +332,6 @@ namespace trezor { MDEBUG("on_passhprase_state_request"); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); - if (m_callback){ - m_callback->on_passphrase_state_request(msg->state()); - } - messages::common::PassphraseStateAck m; resp = call_raw(&m); } diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index 88d419494..a4e92bf78 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -57,17 +57,6 @@ namespace trezor { #ifdef WITH_DEVICE_TREZOR class device_trezor_base; - /** - * Trezor device callbacks - */ - class trezor_callback { - public: - virtual void on_button_request() {}; - virtual void on_pin_request(epee::wipeable_string & pin) {}; - virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {}; - virtual void on_passphrase_state_request(const std::string & state) {}; - }; - /** * TREZOR device template with basic functions */ @@ -79,7 +68,7 @@ namespace trezor { mutable boost::mutex command_locker; std::shared_ptr m_transport; - std::shared_ptr m_callback; + i_device_callback * m_callback; std::string full_name; @@ -218,7 +207,11 @@ namespace trezor { return m_transport; } - std::shared_ptr getCallback(){ + void set_callback(i_device_callback * callback) override { + m_callback = callback; + } + + i_device_callback * get_callback(){ return m_callback; } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d9fd0c13e..6d19235c5 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3786,6 +3786,7 @@ boost::optional simple_wallet::new_wallet(const boost::pr { auto rc = tools::wallet2::make_new(vm, false, password_prompter); m_wallet = std::move(rc.first); + m_wallet->callback(this); if (!m_wallet) { return {}; @@ -3893,7 +3894,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm) epee::wipeable_string password; try { - auto rc = tools::wallet2::make_from_file(vm, false, m_wallet_file, password_prompter); + auto rc = tools::wallet2::make_from_file(vm, false, "", password_prompter); m_wallet = std::move(rc.first); password = std::move(std::move(rc.second).password()); if (!m_wallet) @@ -3901,6 +3902,8 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm) return false; } + m_wallet->callback(this); + m_wallet->load(m_wallet_file, password); std::string prefix; bool ready; uint32_t threshold, total; @@ -4304,6 +4307,38 @@ boost::optional simple_wallet::on_get_password(const char return pwd_container->password(); } //---------------------------------------------------------------------------------------------------- +void simple_wallet::on_button_request() +{ + message_writer(console_color_white, false) << tr("Device requires attention"); +} +//---------------------------------------------------------------------------------------------------- +void simple_wallet::on_pin_request(epee::wipeable_string & pin) +{ +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif + std::string msg = tr("Enter device PIN"); + auto pwd_container = tools::password_container::prompt(false, msg.c_str()); + THROW_WALLET_EXCEPTION_IF(!pwd_container, tools::error::password_entry_failed, tr("Failed to read device PIN")); + pin = pwd_container->password(); +} +//---------------------------------------------------------------------------------------------------- +void simple_wallet::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (on_device){ + message_writer(console_color_white, true) << tr("Please enter the device passphrase on the device"); + return; + } + +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif + std::string msg = tr("Enter device passphrase"); + auto pwd_container = tools::password_container::prompt(false, msg.c_str()); + THROW_WALLET_EXCEPTION_IF(!pwd_container, tools::error::password_entry_failed, tr("Failed to read device passphrase")); + passphrase = pwd_container->password(); +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bool is_init) { if (!try_connect_to_daemon(is_init)) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 421afbeda..7e2edba7f 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -287,6 +287,9 @@ namespace cryptonote virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index); virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx); virtual boost::optional on_get_password(const char *reason); + virtual void on_button_request(); + virtual void on_pin_request(epee::wipeable_string & pin); + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); //---------------------------------------------------------- friend class refresh_progress_reporter_t; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 49aef4350..ae6ed0937 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -818,6 +818,24 @@ wallet_keys_unlocker::~wallet_keys_unlocker() w.encrypt_keys(key); } +void wallet_device_callback::on_button_request() +{ + if (wallet) + wallet->on_button_request(); +} + +void wallet_device_callback::on_pin_request(epee::wipeable_string & pin) +{ + if (wallet) + wallet->on_pin_request(pin); +} + +void wallet_device_callback::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (wallet) + wallet->on_passphrase_request(on_device, passphrase); +} + wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_multisig_rescan_info(NULL), m_multisig_rescan_k(NULL), @@ -929,7 +947,7 @@ std::pair, password_container> wallet2::make_from_file( return {nullptr, password_container{}}; } auto wallet = make_basic(vm, unattended, opts, password_prompter); - if (wallet) + if (wallet && !wallet_file.empty()) { wallet->load(wallet_file, pwd->password()); } @@ -1071,15 +1089,16 @@ bool wallet2::reconnect_device() hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); r = hwdev.init(); if (!r){ - LOG_PRINT_L2("Could not init device"); + MERROR("Could not init device"); return false; } r = hwdev.connect(); if (!r){ - LOG_PRINT_L2("Could not connect to the device"); + MERROR("Could not connect to the device"); return false; } @@ -3441,6 +3460,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ hw::device &hwdev = lookup_device(m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); THROW_WALLET_EXCEPTION_IF(!hwdev.init(), error::wallet_internal_error, "Could not initialize the device " + m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.connect(), error::wallet_internal_error, "Could not connect to the device " + m_device_name); m_account.set_device(hwdev); @@ -3947,6 +3967,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p auto &hwdev = lookup_device(device_name); hwdev.set_name(device_name); hwdev.set_network_type(m_nettype); + hwdev.set_callback(get_device_callback()); m_account.create_from_device(hwdev); m_key_device_type = m_account.get_device().get_type(); @@ -11940,4 +11961,29 @@ uint64_t wallet2::get_segregation_fork_height() const void wallet2::generate_genesis(cryptonote::block& b) const { cryptonote::generate_genesis_block(b, get_config(m_nettype).GENESIS_TX, get_config(m_nettype).GENESIS_NONCE); } +//---------------------------------------------------------------------------------------------------- +wallet_device_callback * wallet2::get_device_callback() +{ + if (!m_device_callback){ + m_device_callback.reset(new wallet_device_callback(this)); + } + return m_device_callback.get(); +}//---------------------------------------------------------------------------------------------------- +void wallet2::on_button_request() +{ + if (0 != m_callback) + m_callback->on_button_request(); +} +//---------------------------------------------------------------------------------------------------- +void wallet2::on_pin_request(epee::wipeable_string & pin) +{ + if (0 != m_callback) + m_callback->on_pin_request(pin); +} +//---------------------------------------------------------------------------------------------------- +void wallet2::on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) +{ + if (0 != m_callback) + m_callback->on_passphrase_request(on_device, passphrase); +} } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index eb0763131..c07054177 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -98,11 +98,26 @@ namespace tools virtual void on_lw_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount) {} virtual void on_lw_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount) {} virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount) {} + // Device callbacks + virtual void on_button_request() {} + virtual void on_pin_request(epee::wipeable_string & pin) {} + virtual void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) {} // Common callbacks virtual void on_pool_tx_removed(const crypto::hash &txid) {} virtual ~i_wallet2_callback() {} }; + class wallet_device_callback : public hw::i_device_callback + { + public: + wallet_device_callback(wallet2 * wallet): wallet(wallet) {}; + void on_button_request() override; + void on_pin_request(epee::wipeable_string & pin) override; + void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase) override; + private: + wallet2 * wallet; + }; + struct tx_dust_policy { uint64_t dust_threshold; @@ -154,6 +169,7 @@ namespace tools { friend class ::Serialization_portability_wallet_Test; friend class wallet_keys_unlocker; + friend class wallet_device_callback; public: static constexpr const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::chrono::seconds(30); @@ -1285,6 +1301,11 @@ namespace tools void setup_new_blockchain(); void create_keys_file(const std::string &wallet_, bool watch_only, const epee::wipeable_string &password, bool create_address_file); + wallet_device_callback * get_device_callback(); + void on_button_request(); + void on_pin_request(epee::wipeable_string & pin); + void on_passphrase_request(bool on_device, epee::wipeable_string & passphrase); + cryptonote::account_base m_account; boost::optional m_daemon_login; std::string m_daemon_address; @@ -1396,6 +1417,7 @@ namespace tools bool m_devices_registered; std::shared_ptr m_tx_notify; + std::unique_ptr m_device_callback; }; } BOOST_CLASS_VERSION(tools::wallet2, 26) diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index b3141985d..e2caee5d2 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -219,6 +219,14 @@ namespace tools } }; //---------------------------------------------------------------------------------------------------- + struct password_entry_failed : public wallet_runtime_error + { + explicit password_entry_failed(std::string&& loc, const std::string &msg = "Password entry failed") + : wallet_runtime_error(std::move(loc), msg) + { + } + }; + //---------------------------------------------------------------------------------------------------- const char* const file_error_messages[] = { "file already exists", "file not found", From ac665418f0a7ef92ce9b27ecdd88914482f19ee5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 13:33:29 +0000 Subject: [PATCH 0338/1007] ringct: fix dummy bulletproofs on ledger in fake mode Ledger does some basic checks on them --- src/ringct/rctSigs.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index dccd18867..5497b927e 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -46,13 +46,34 @@ using namespace std; namespace { - rct::Bulletproof make_dummy_bulletproof(size_t n_outs) + rct::Bulletproof make_dummy_bulletproof(const std::vector &outamounts, rct::keyV &C, rct::keyV &masks) { + const size_t n_outs = outamounts.size(); const rct::key I = rct::identity(); size_t nrl = 0; while ((1u << nrl) < n_outs) ++nrl; nrl += 6; + + C.resize(n_outs); + masks.resize(n_outs); + for (size_t i = 0; i < n_outs; ++i) + { + masks[i] = I; + rct::key sv8, sv; + sv = rct::zero(); + sv.bytes[0] = outamounts[i] & 255; + sv.bytes[1] = (outamounts[i] >> 8) & 255; + sv.bytes[2] = (outamounts[i] >> 16) & 255; + sv.bytes[3] = (outamounts[i] >> 24) & 255; + sv.bytes[4] = (outamounts[i] >> 32) & 255; + sv.bytes[5] = (outamounts[i] >> 40) & 255; + sv.bytes[6] = (outamounts[i] >> 48) & 255; + sv.bytes[7] = (outamounts[i] >> 56) & 255; + sc_mul(sv8.bytes, sv.bytes, rct::INV_EIGHT.bytes); + rct::addKeys2(C[i], rct::INV_EIGHT, sv8, rct::H); + } + return rct::Bulletproof{rct::keyV(n_outs, I), I, I, I, I, I, I, rct::keyV(nrl, I), rct::keyV(nrl, I), I, I, I}; } } @@ -769,9 +790,7 @@ namespace rct { if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed - rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts.size())); - C = rct::keyV(outamounts.size(), I); - masks = rct::keyV(outamounts.size(), I); + rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks)); } else { @@ -799,9 +818,7 @@ namespace rct { if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE) { // use a fake bulletproof for speed - rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts.size())); - C = rct::keyV(batch_amounts.size(), I); - masks = rct::keyV(batch_amounts.size(), I); + rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks)); } else { From aba9a9c27777cd0649e9946566d87030f78d8bec Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 14:53:38 +0000 Subject: [PATCH 0339/1007] daemon: stop miner before we bring the whole thing down This avoids the miner erroring out trying to submit blocks to a core that's already shut down (and avoids pegging the CPU while we're busy shutting down). --- src/cryptonote_core/cryptonote_core.cpp | 1 + src/daemon/daemon.cpp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 10ab3fe65..dd79c0e67 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -247,6 +247,7 @@ namespace cryptonote //----------------------------------------------------------------------------------- void core::stop() { + m_miner.stop(); m_blockchain_storage.cancel(); tools::download_async_handle handle; diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 49d6d49cf..85b8780f0 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -198,7 +198,6 @@ bool t_daemon::run(bool interactive) for(auto& rpc : mp_internals->rpcs) rpc->stop(); - mp_internals->core.get().get_miner().stop(); MGINFO("Node stopped."); return true; } @@ -220,7 +219,6 @@ void t_daemon::stop() { throw std::runtime_error{"Can't stop stopped daemon"}; } - mp_internals->core.get().get_miner().stop(); mp_internals->p2p.stop(); for(auto& rpc : mp_internals->rpcs) rpc->stop(); From 0c5dd3161b0f8c962a77cd27cff58043d85e509c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 14:54:46 +0000 Subject: [PATCH 0340/1007] cryptonote: add a set_null for transaction_prefix Since it's all inline, I suspect the compiler will merge the duplicate stores anyway. --- src/cryptonote_basic/cryptonote_basic.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index b0eabb0aa..645e99f91 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -175,7 +175,15 @@ namespace cryptonote END_SERIALIZE() public: - transaction_prefix(){} + transaction_prefix(){ set_null(); } + void set_null() + { + version = 1; + unlock_time = 0; + vin.clear(); + vout.clear(); + extra.clear(); + } }; class transaction: public transaction_prefix @@ -302,17 +310,12 @@ namespace cryptonote inline transaction::~transaction() { - //set_null(); } inline void transaction::set_null() { - version = 1; - unlock_time = 0; - vin.clear(); - vout.clear(); - extra.clear(); + transaction_prefix::set_null(); signatures.clear(); rct_signatures.type = rct::RCTTypeNull; set_hash_valid(false); From 4d71d463739fa20d21588266b70f58609d79cb2e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 16:52:50 +0000 Subject: [PATCH 0341/1007] mlocker: remove early page size log It comes before the logger is initialized, so gets displayed even though it should not be by default, and apparenly comes too early for (some versions of) Android, where it crashes. --- contrib/epee/src/mlocker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index c3262e8f4..4c48cbb58 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -47,7 +47,6 @@ static size_t query_page_size() MERROR("Failed to determine page size"); return 0; } - MINFO("Page size: " << ret); return ret; #else #warning Missing query_page_size implementation From 9b69a0ae019b366ad9511263680d6d08f50d6f25 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 17:55:16 +0000 Subject: [PATCH 0342/1007] daemon: print monero version at startup when calling a detached daemon So people who want a timstamp get a timestamp --- src/daemon/main.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index f483ba6c9..35017d9ef 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -216,6 +216,16 @@ int main(int argc, char const * argv[]) // after logs initialized tools::create_directories_if_necessary(data_dir.string()); +#ifdef STACK_TRACE + tools::set_stack_trace_log(log_file_path.filename().string()); +#endif // STACK_TRACE + + if (!command_line::is_arg_defaulted(vm, daemon_args::arg_max_concurrency)) + tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency)); + + // logging is now set up + MGINFO("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"); + // If there are positional options, we're running a daemon command { auto command = command_line::get_arg(vm, daemon_args::arg_command); @@ -276,16 +286,6 @@ int main(int argc, char const * argv[]) } } -#ifdef STACK_TRACE - tools::set_stack_trace_log(log_file_path.filename().string()); -#endif // STACK_TRACE - - if (!command_line::is_arg_defaulted(vm, daemon_args::arg_max_concurrency)) - tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency)); - - // logging is now set up - MGINFO("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"); - MINFO("Moving from main() into the daemonize now."); return daemonizer::daemonize(argc, argv, daemonize::t_executor{}, vm) ? 0 : 1; From ab783b1700fc14ed04bf14fc9df2c6c7b6e90a41 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 30 Nov 2018 17:58:58 +0000 Subject: [PATCH 0343/1007] easylogging++: ensure logger is initialized before main --- external/easylogging++/easylogging++.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index d57f3f3a0..00b8b830b 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2202,6 +2202,7 @@ el::base::type::StoragePointer el::base::Storage::getELPP() { return getresetELPP(false); } +static struct EnsureELPP { EnsureELPP() { el::base::Storage::getELPP(); } } ensureELPP; #if ELPP_ASYNC_LOGGING Storage::Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : #else From 4f74a31ecdaac3d338985fecc2de0882675745d2 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Sat, 24 Nov 2018 15:31:49 +0200 Subject: [PATCH 0344/1007] http -> https --- contrib/depends/packages/bdb.mk | 2 +- contrib/depends/packages/ldns.mk | 2 +- contrib/depends/packages/libICE.mk | 2 +- contrib/depends/packages/libSM.mk | 2 +- contrib/depends/packages/libusb.mk | 2 +- contrib/depends/packages/native_cdrkit.mk | 2 +- contrib/depends/packages/qt.mk | 2 +- contrib/depends/packages/unbound.mk | 2 +- contrib/depends/packages/unwind.mk | 2 +- contrib/depends/packages/xproto.mk | 2 +- contrib/depends/packages/zlib.mk | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/depends/packages/bdb.mk b/contrib/depends/packages/bdb.mk index 6c9876c2c..050a60add 100644 --- a/contrib/depends/packages/bdb.mk +++ b/contrib/depends/packages/bdb.mk @@ -1,6 +1,6 @@ package=bdb $(package)_version=4.8.30 -$(package)_download_path=http://download.oracle.com/berkeley-db +$(package)_download_path=https://download.oracle.com/berkeley-db $(package)_file_name=db-$($(package)_version).NC.tar.gz $(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef $(package)_build_subdir=build_unix diff --git a/contrib/depends/packages/ldns.mk b/contrib/depends/packages/ldns.mk index a9565a581..0b7c3806a 100644 --- a/contrib/depends/packages/ldns.mk +++ b/contrib/depends/packages/ldns.mk @@ -1,6 +1,6 @@ package=ldns $(package)_version=1.6.17 -$(package)_download_path=http://www.nlnetlabs.nl/downloads/ldns/ +$(package)_download_path=https://www.nlnetlabs.nl/downloads/ldns/ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=8b88e059452118e8949a2752a55ce59bc71fa5bc414103e17f5b6b06f9bcc8cd $(package)_dependencies=openssl diff --git a/contrib/depends/packages/libICE.mk b/contrib/depends/packages/libICE.mk index fc60323b1..a897d9aed 100644 --- a/contrib/depends/packages/libICE.mk +++ b/contrib/depends/packages/libICE.mk @@ -1,6 +1,6 @@ package=libICE $(package)_version=1.0.9 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ +$(package)_download_path=https://xorg.freedesktop.org/releases/individual/lib/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=8f7032f2c1c64352b5423f6b48a8ebdc339cc63064af34d66a6c9aa79759e202 $(package)_dependencies=xtrans xproto diff --git a/contrib/depends/packages/libSM.mk b/contrib/depends/packages/libSM.mk index 0f9307ca7..83fcd4cdb 100644 --- a/contrib/depends/packages/libSM.mk +++ b/contrib/depends/packages/libSM.mk @@ -1,6 +1,6 @@ package=libSM $(package)_version=1.2.2 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ +$(package)_download_path=https://xorg.freedesktop.org/releases/individual/lib/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=0baca8c9f5d934450a70896c4ad38d06475521255ca63b717a6510fdb6e287bd $(package)_dependencies=xtrans xproto libICE diff --git a/contrib/depends/packages/libusb.mk b/contrib/depends/packages/libusb.mk index e9663ace0..6d60cce26 100644 --- a/contrib/depends/packages/libusb.mk +++ b/contrib/depends/packages/libusb.mk @@ -1,6 +1,6 @@ package=libusb $(package)_version=1.0.22 -$(package)_download_path=http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-$($(package)_version)/ +$(package)_download_path=https://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-$($(package)_version)/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=75aeb9d59a4fdb800d329a545c2e6799f732362193b465ea198f2aa275518157 diff --git a/contrib/depends/packages/native_cdrkit.mk b/contrib/depends/packages/native_cdrkit.mk index cf694edb3..8243458ec 100644 --- a/contrib/depends/packages/native_cdrkit.mk +++ b/contrib/depends/packages/native_cdrkit.mk @@ -1,6 +1,6 @@ package=native_cdrkit $(package)_version=1.1.11 -$(package)_download_path=http://distro.ibiblio.org/fatdog/source/600/c +$(package)_download_path=https://distro.ibiblio.org/fatdog/source/600/c $(package)_file_name=cdrkit-$($(package)_version).tar.bz2 $(package)_sha256_hash=b50d64c214a65b1a79afe3a964c691931a4233e2ba605d793eb85d0ac3652564 $(package)_patches=cdrkit-deterministic.patch diff --git a/contrib/depends/packages/qt.mk b/contrib/depends/packages/qt.mk index 32ca4a84c..bca2926cb 100644 --- a/contrib/depends/packages/qt.mk +++ b/contrib/depends/packages/qt.mk @@ -1,6 +1,6 @@ PACKAGE=qt $(package)_version=5.7.1 -$(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(package)_version)/submodules +$(package)_download_path=https://download.qt.io/archive/qt/5.7/5.7.1/submodules $(package)_suffix=opensource-src-$($(package)_version).tar.gz $(package)_file_name=qtbase-$($(package)_suffix) $(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410 diff --git a/contrib/depends/packages/unbound.mk b/contrib/depends/packages/unbound.mk index beeeb54c1..733a7f232 100644 --- a/contrib/depends/packages/unbound.mk +++ b/contrib/depends/packages/unbound.mk @@ -1,6 +1,6 @@ package=unbound $(package)_version=1.6.8 -$(package)_download_path=http://www.unbound.net/downloads/ +$(package)_download_path=https://www.unbound.net/downloads/ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=e3b428e33f56a45417107448418865fe08d58e0e7fea199b855515f60884dd49 $(package)_dependencies=openssl expat ldns diff --git a/contrib/depends/packages/unwind.mk b/contrib/depends/packages/unwind.mk index e1bcb35b2..543f868a5 100644 --- a/contrib/depends/packages/unwind.mk +++ b/contrib/depends/packages/unwind.mk @@ -1,6 +1,6 @@ package=unwind $(package)_version=1.2 -$(package)_download_path=http://download.savannah.nongnu.org/releases/libunwind +$(package)_download_path=https://download.savannah.nongnu.org/releases/libunwind $(package)_file_name=lib$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=1de38ffbdc88bd694d10081865871cd2bfbb02ad8ef9e1606aee18d65532b992 diff --git a/contrib/depends/packages/xproto.mk b/contrib/depends/packages/xproto.mk index 50a90b268..52fe253c7 100644 --- a/contrib/depends/packages/xproto.mk +++ b/contrib/depends/packages/xproto.mk @@ -1,6 +1,6 @@ package=xproto $(package)_version=7.0.26 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/proto +$(package)_download_path=https://xorg.freedesktop.org/releases/individual/proto $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=636162c1759805a5a0114a369dffdeccb8af8c859ef6e1445f26a4e6e046514f diff --git a/contrib/depends/packages/zlib.mk b/contrib/depends/packages/zlib.mk index 589490800..1600b11a0 100644 --- a/contrib/depends/packages/zlib.mk +++ b/contrib/depends/packages/zlib.mk @@ -1,6 +1,6 @@ package=zlib $(package)_version=1.2.11 -$(package)_download_path=http://www.zlib.net +$(package)_download_path=https://www.zlib.net $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 From 6456cb415a16aab24694a246309f4c7f0ae5667c Mon Sep 17 00:00:00 2001 From: Tadeas Moravec Date: Sat, 1 Dec 2018 13:03:32 +0000 Subject: [PATCH 0345/1007] Bulletproof: Initialize members in default construtor. Fixing a build warning on g++ 7.3.0 --- src/ringct/rctTypes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index 18290637b..487ea6f32 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -187,7 +187,8 @@ namespace rct { rct::keyV L, R; rct::key a, b, t; - Bulletproof() {} + Bulletproof(): + A({}), S({}), T1({}), T2({}), taux({}), mu({}), a({}), b({}), t({}) {} Bulletproof(const rct::key &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t): V({V}), A(A), S(S), T1(T1), T2(T2), taux(taux), mu(mu), L(L), R(R), a(a), b(b), t(t) {} Bulletproof(const rct::keyV &V, const rct::key &A, const rct::key &S, const rct::key &T1, const rct::key &T2, const rct::key &taux, const rct::key &mu, const rct::keyV &L, const rct::keyV &R, const rct::key &a, const rct::key &b, const rct::key &t): From affff949f9aa32f329afc6f82f4ec119ef7ea6b5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 2 Dec 2018 13:06:41 +0000 Subject: [PATCH 0346/1007] blockchain: fix race between two external mining threads --- src/cryptonote_core/blockchain.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index bfc5dbbe0..21d1809ab 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1237,7 +1237,9 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m uint64_t already_generated_coins; uint64_t pool_cookie; - CRITICAL_REGION_BEGIN(m_blockchain_lock); + m_tx_pool.lock(); + const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); }); + CRITICAL_REGION_LOCAL(m_blockchain_lock); height = m_db->height(); if (m_btc_valid) { // The pool cookie is atomic. The lack of locking is OK, as if it changes @@ -1273,8 +1275,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m median_weight = m_current_block_cumul_weight_limit / 2; already_generated_coins = m_db->get_block_already_generated_coins(height - 1); - CRITICAL_REGION_END(); - size_t txs_weight; uint64_t fee; if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, m_hardfork->get_current_version())) @@ -1285,7 +1285,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) size_t real_txs_weight = 0; uint64_t real_fee = 0; - CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock); for(crypto::hash &cur_hash: b.tx_hashes) { auto cur_res = m_tx_pool.m_transactions.find(cur_hash); @@ -1329,7 +1328,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m { LOG_ERROR("Creating block template: error: wrongly calculated fee"); } - CRITICAL_REGION_END(); MDEBUG("Creating block template: height " << height << ", median weight " << median_weight << ", already generated coins " << already_generated_coins << From ea85de4f020e34264e8e5f7bb625126be87677d5 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 3 Dec 2018 19:07:59 +0000 Subject: [PATCH 0347/1007] CONTRIBUTING: mention not changing spelling/typoes in code --- CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3de9cd5ce..883d366aa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,7 +19,8 @@ posted to #monero-dev on irc.freenode.net). Patches should be self contained. A good rule of thumb is to have one patch per separate issue, feature, or logical change. Also, no -other changes, such as random whitespace changes or reindentation. +other changes, such as random whitespace changes, reindentation, +or fixing typoes, spelling, or wording, unless user visible. Following the code style of the particular chunk of code you're modifying is encouraged. Proper squashing should be done (eg, if you're making a buggy patch, then a later patch to fix the bug, From 7d9aeb71958ceb1efad488200ee8ccf92510b583 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 3 Dec 2018 21:33:49 +0000 Subject: [PATCH 0348/1007] easylogging++: avoid uneeded temporary std::string object --- external/easylogging++/easylogging++.cc | 15 +++++++-------- external/easylogging++/easylogging++.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index d57f3f3a0..800d9a4dd 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2130,24 +2130,23 @@ static int priority(Level level) { return 7; } -bool VRegistry::allowed(Level level, const char* category) { +bool VRegistry::allowed(Level level, const std::string &category) { base::threading::ScopedLock scopedLock(lock()); - const std::string scategory = category; - const std::map::const_iterator it = m_cached_allowed_categories.find(scategory); + const std::map::const_iterator it = m_cached_allowed_categories.find(category); if (it != m_cached_allowed_categories.end()) return priority(level) <= it->second; - if (m_categories.empty() || category == nullptr) { + if (m_categories.empty()) { return false; } else { std::vector>::const_reverse_iterator it = m_categories.rbegin(); for (; it != m_categories.rend(); ++it) { - if (base::utils::Str::wildCardMatch(category, it->first.c_str())) { + if (base::utils::Str::wildCardMatch(category.c_str(), it->first.c_str())) { const int p = priority(it->second); - m_cached_allowed_categories.insert(std::make_pair(std::move(scategory), p)); + m_cached_allowed_categories.insert(std::make_pair(category, p)); return priority(level) <= p; } } - m_cached_allowed_categories.insert(std::make_pair(std::move(scategory), -1)); + m_cached_allowed_categories.insert(std::make_pair(category, -1)); return false; } } @@ -2720,7 +2719,7 @@ void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool nee } if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : - ELPP->vRegistry()->allowed(m_level, loggerId.c_str()); + ELPP->vRegistry()->allowed(m_level, loggerId); } else { m_proceed = m_logger->enabled(m_level); } diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 046252a5b..9edec9317 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -2463,7 +2463,7 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe { void setModules(const char* modules); - bool allowed(Level level, const char* category); + bool allowed(Level level, const std::string &category); bool allowed(base::type::VerboseLevel vlevel, const char* file); From 5a76933903ef2f29532588d359862831a3644128 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Sat, 13 Oct 2018 17:07:56 +0200 Subject: [PATCH 0349/1007] Add glibc back compat code To ensure that the binaries compiled by gitian run across many linux distributions, enforce 2.17 as the minimum libc version supported. --- CMakeLists.txt | 9 +- README.md | 2 + contrib/gitian/gitian-linux.yml | 2 +- contrib/gitian/symbol-check.py | 163 ----------------------------- src/common/CMakeLists.txt | 4 + src/common/compat/glibc_compat.cpp | 98 +++++++++++++++++ 6 files changed, 113 insertions(+), 165 deletions(-) delete mode 100755 contrib/gitian/symbol-check.py create mode 100644 src/common/compat/glibc_compat.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c38c673a..78dc14acb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -696,6 +696,13 @@ else() set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap") endif() + if(BACKCOMPAT) + add_definitions(-DFDELT_TYPE=long\ int) + add_linker_flag_if_supported(-Wl,--wrap=__divmoddi4 LD_BACKCOMPAT_FLAGS) + add_linker_flag_if_supported(-Wl,--wrap=glob LD_BACKCOMPAT_FLAGS) + message(STATUS "Using Lib C back compat flags: ${LD_BACKCOMPAT_FLAGS}") + endif() + # some windows linker bits if (WIN32) add_linker_flag_if_supported(-Wl,--dynamicbase LD_SECURITY_FLAGS) @@ -708,7 +715,7 @@ else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${LD_BACKCOMPAT_FLAGS}") # With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that # is fixed in the code (Issue #847), force compiler to be conservative. diff --git a/README.md b/README.md index 472ca580c..d8a3a7844 100644 --- a/README.md +++ b/README.md @@ -521,6 +521,8 @@ The required packages are the names for each toolchain on apt. Depending on your Using `depends` might also be easier to compile Monero on Windows than using MSYS. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above. +The produced binaries still link libc dynamically. If the binary is compiled on a current distribution, it might not run on an older distribution with an older installation of libc. Passing `-DBACKCOMPAT=ON` to cmake will make sure that the binary will run on systems having at least libc version 2.17. + ## Installing Monero from a package **DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.** diff --git a/contrib/gitian/gitian-linux.yml b/contrib/gitian/gitian-linux.yml index 473a7720d..3bb25c314 100644 --- a/contrib/gitian/gitian-linux.yml +++ b/contrib/gitian/gitian-linux.yml @@ -152,7 +152,7 @@ script: | for i in ${HOSTS}; do export PATH=${BASEPREFIX}/${i}/native/bin:${ORIGPATH} mkdir build && cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake + cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake -DBACKCOMPAT=ON make DISTNAME=monero-${i} mv bin ${DISTNAME} diff --git a/contrib/gitian/symbol-check.py b/contrib/gitian/symbol-check.py deleted file mode 100755 index 6808e77da..000000000 --- a/contrib/gitian/symbol-check.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 -# 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. -''' -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 -still compatible with the minimum supported Linux distribution versions. - -Example usage: - - find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py -''' -import subprocess -import re -import sys -import os - -# Debian 6.0.9 (Squeeze) has: -# -# - g++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=g%2B%2B) -# - libc version 2.11.3 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libc6) -# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libstdc%2B%2B6) -# -# Ubuntu 10.04.4 (Lucid Lynx) has: -# -# - g++ version 4.4.3 (http://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=lucid§ion=all) -# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid§ion=all) -# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid§ion=all&arch=any&keywords=libstdc%2B%2B&searchon=names) -# -# Taking the minimum of these as our target. -# -# According to GNU ABI document (http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to: -# GCC 4.4.0: GCC_4.4.0 -# GCC 4.4.2: GLIBCXX_3.4.13, CXXABI_1.3.3 -# (glibc) GLIBC_2_11 -# -MAX_VERSIONS = { -'GCC': (4,4,0), -'CXXABI': (1,3,3), -'GLIBCXX': (3,4,13), -'GLIBC': (2,11) -} -# See here for a description of _IO_stdin_used: -# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109 - -# Ignore symbols that are exported as part of every executable -IGNORE_EXPORTS = { -'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr' -} -READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') -CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') -# Allowed NEEDED libraries -ALLOWED_LIBRARIES = { -# bitcoind and bitcoin-qt -'libgcc_s.so.1', # GCC base support -'libc.so.6', # C library -'libpthread.so.0', # threading -'libanl.so.1', # DNS resolve -'libm.so.6', # math library -'librt.so.1', # real-time (clock) -'ld-linux-x86-64.so.2', # 64-bit dynamic linker -'ld-linux.so.2', # 32-bit dynamic linker -# bitcoin-qt only -'libX11-xcb.so.1', # part of X11 -'libX11.so.6', # part of X11 -'libxcb.so.1', # part of X11 -'libfontconfig.so.1', # font support -'libfreetype.so.6', # font parsing -'libdl.so.2' # programming interface to dynamic linker -} - -class CPPFilt(object): - ''' - Demangle C++ symbol names. - - Use a pipe to the 'c++filt' command. - ''' - def __init__(self): - self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True) - - def __call__(self, mangled): - self.proc.stdin.write(mangled + '\n') - self.proc.stdin.flush() - return self.proc.stdout.readline().rstrip() - - def close(self): - self.proc.stdin.close() - self.proc.stdout.close() - self.proc.wait() - -def read_symbols(executable, imports=True): - ''' - Parse an ELF executable and return a list of (symbol,version) tuples - for dynamic, imported symbols. - ''' - p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True) - (stdout, stderr) = p.communicate() - if p.returncode: - raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip())) - syms = [] - for line in stdout.splitlines(): - line = line.split() - if len(line)>7 and re.match('[0-9]+:$', line[0]): - (sym, _, version) = line[7].partition('@') - is_import = line[6] == 'UND' - if version.startswith('@'): - version = version[1:] - if is_import == imports: - syms.append((sym, version)) - return syms - -def check_version(max_versions, version): - if '_' in version: - (lib, _, ver) = version.rpartition('_') - else: - lib = version - ver = '0' - ver = tuple([int(x) for x in ver.split('.')]) - if not lib in max_versions: - return False - return ver <= max_versions[lib] - -def read_libraries(filename): - p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True) - (stdout, stderr) = p.communicate() - if p.returncode: - raise IOError('Error opening file') - libraries = [] - for line in stdout.splitlines(): - tokens = line.split() - if len(tokens)>2 and tokens[1] == '(NEEDED)': - match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:])) - if match: - libraries.append(match.group(1)) - else: - raise ValueError('Unparseable (NEEDED) specification') - return libraries - -if __name__ == '__main__': - cppfilt = CPPFilt() - retval = 0 - for filename in sys.argv[1:]: - # Check imported symbols - for sym,version in read_symbols(filename, True): - if version and not check_version(MAX_VERSIONS, version): - print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version)) - retval = 1 - # Check exported symbols - for sym,version in read_symbols(filename, False): - if sym in IGNORE_EXPORTS: - continue - print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym))) - retval = 1 - # Check dependency libraries - for library_name in read_libraries(filename): - if library_name not in ALLOWED_LIBRARIES: - print('%s: NEEDED library %s is not allowed' % (filename, library_name)) - retval = 1 - - sys.exit(retval) - - diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index aed9bfee7..1aaab555d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -49,6 +49,10 @@ if (STACK_TRACE) list(APPEND common_sources stack_trace.cpp) endif() +if (BACKCOMPAT) + list(APPEND common_sources compat/glibc_compat.cpp) +endif() + set(common_headers) set(common_private_headers diff --git a/src/common/compat/glibc_compat.cpp b/src/common/compat/glibc_compat.cpp new file mode 100644 index 000000000..bf567987d --- /dev/null +++ b/src/common/compat/glibc_compat.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_SYS_SELECT_H) +#include +#endif + +// Prior to GLIBC_2.14, memcpy was aliased to memmove. +extern "C" void* memmove(void* a, const void* b, size_t c); +//extern "C" void* memset(void* a, int b, long unsigned int c); +extern "C" void* memcpy(void* a, const void* b, size_t c) +{ + return memmove(a, b, c); +} + +extern "C" void __chk_fail(void) __attribute__((__noreturn__)); + +#if defined(__i386__) || defined(__arm__) + +extern "C" int64_t __udivmoddi4(uint64_t u, uint64_t v, uint64_t* rp); + +extern "C" int64_t __wrap___divmoddi4(int64_t u, int64_t v, int64_t* rp) +{ + int32_t c1 = 0, c2 = 0; + int64_t uu = u, vv = v; + int64_t w; + int64_t r; + + if (uu < 0) { + c1 = ~c1, c2 = ~c2, uu = -uu; + } + if (vv < 0) { + c1 = ~c1, vv = -vv; + } + + w = __udivmoddi4(uu, vv, (uint64_t*)&r); + if (c1) + w = -w; + if (c2) + r = -r; + + *rp = r; + return w; +} +#endif + +/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero + redirects to that. */ +#undef explicit_bzero +/* Set LEN bytes of S to 0. The compiler will not delete a call to + this function, even if S is dead after the call. */ +void +explicit_bzero (void *s, size_t len) +{ + memset (s, '\0', len); + /* Compiler barrier. */ + asm volatile ("" ::: "memory"); +} + +// Redefine explicit_bzero_chk +void +__explicit_bzero_chk (void *dst, size_t len, size_t dstlen) +{ + /* Inline __memset_chk to avoid a PLT reference to __memset_chk. */ + if (__glibc_unlikely (dstlen < len)) + __chk_fail (); + memset (dst, '\0', len); + /* Compiler barrier. */ + asm volatile ("" ::: "memory"); +} +/* libc-internal references use the hidden + __explicit_bzero_chk_internal symbol. This is necessary if + __explicit_bzero_chk is implemented as an IFUNC because some + targets do not support hidden references to IFUNC symbols. */ +#define strong_alias (__explicit_bzero_chk, __explicit_bzero_chk_internal) + +#undef glob +extern "C" int glob_old(const char * pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob); +#ifdef __i386__ +__asm__(".symver glob_old,glob@GLIBC_2.1"); +#elif defined(__amd64__) +__asm__(".symver glob_old,glob@GLIBC_2.2.5"); +#elif defined(__arm__) +__asm(".symver glob_old,glob@GLIBC_2.4"); +#elif defined(__aarch64__) +__asm__(".symver glob_old,glob@GLIBC_2.17"); +#endif + +extern "C" int __wrap_glob(const char * pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob) +{ + return glob_old(pattern, flags, errfunc, pglob); +} + From 3cf85f0e835c951d32e3074f8f5f45bc9f35cbad Mon Sep 17 00:00:00 2001 From: Norman Moeschter Date: Tue, 4 Dec 2018 07:27:08 +0100 Subject: [PATCH 0350/1007] Changed RECIEVED to RECEIVED in log messages. --- contrib/epee/include/net/levin_client_async.h | 2 +- contrib/epee/include/net/levin_protocol_handler_async.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h index b3a46465b..ed92f4b95 100644 --- a/contrib/epee/include/net/levin_client_async.h +++ b/contrib/epee/include/net/levin_client_async.h @@ -431,7 +431,7 @@ namespace levin } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data <<", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); if(is_request) { diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 08aa1d468..4df7337cd 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -415,7 +415,7 @@ class async_protocol_handler bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE); - MDEBUG(m_connection_context << "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb + MDEBUG(m_connection_context << "LEVIN_PACKET_RECEIVED. [len=" << m_current_head.m_cb << ", flags" << m_current_head.m_flags << ", r?=" << m_current_head.m_have_to_return_data <<", cmd = " << m_current_head.m_command From ec1a62b50dedb65f14db30dbafb1035018cf3421 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 18 Nov 2018 10:17:24 +0000 Subject: [PATCH 0351/1007] move int-util.h to epee --- {src/common => contrib/epee/include}/int-util.h | 0 src/common/CMakeLists.txt | 1 - src/crypto/aesb.c | 2 +- src/crypto/chacha.c | 2 +- src/crypto/groestl_tables.h | 2 +- src/crypto/hash-ops.h | 2 +- src/crypto/keccak.c | 2 +- src/crypto/skein_port.h | 2 +- src/crypto/slow-hash.c | 2 +- src/cryptonote_basic/cryptonote_basic_impl.cpp | 2 +- src/cryptonote_basic/difficulty.cpp | 2 +- src/cryptonote_core/blockchain.cpp | 2 +- src/cryptonote_core/tx_pool.cpp | 2 +- src/device/device_default.cpp | 2 +- src/mnemonics/electrum-words.cpp | 2 +- tests/unit_tests/mul_div.cpp | 2 +- 16 files changed, 14 insertions(+), 15 deletions(-) rename {src/common => contrib/epee/include}/int-util.h (100%) diff --git a/src/common/int-util.h b/contrib/epee/include/int-util.h similarity index 100% rename from src/common/int-util.h rename to contrib/epee/include/int-util.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 3045c003c..5da23c944 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -63,7 +63,6 @@ set(common_private_headers error.h expect.h http_connection.h - int-util.h notify.h pod-class.h rpc_client.h diff --git a/src/crypto/aesb.c b/src/crypto/aesb.c index 8a22a4b93..efdeef8d1 100644 --- a/src/crypto/aesb.c +++ b/src/crypto/aesb.c @@ -19,7 +19,7 @@ Issue Date: 20/12/2007 */ #include -#include "common/int-util.h" +#include "int-util.h" #if defined(__cplusplus) extern "C" diff --git a/src/crypto/chacha.c b/src/crypto/chacha.c index 5d3edb98d..d734e8b1b 100644 --- a/src/crypto/chacha.c +++ b/src/crypto/chacha.c @@ -11,7 +11,7 @@ Public domain. #endif #include "chacha.h" -#include "common/int-util.h" +#include "int-util.h" #include "warnings.h" /* diff --git a/src/crypto/groestl_tables.h b/src/crypto/groestl_tables.h index 53594c569..12472dced 100644 --- a/src/crypto/groestl_tables.h +++ b/src/crypto/groestl_tables.h @@ -29,7 +29,7 @@ #ifndef __tables_h #define __tables_h -#include "common/int-util.h" +#include "int-util.h" #if BYTE_ORDER == LITTLE_ENDIAN diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index d77d55cf3..77b52e2d4 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -37,7 +37,7 @@ #include #include -#include "common/int-util.h" +#include "int-util.h" #include "warnings.h" static inline void *padd(void *p, size_t i) { diff --git a/src/crypto/keccak.c b/src/crypto/keccak.c index b095b5ce2..170911262 100644 --- a/src/crypto/keccak.c +++ b/src/crypto/keccak.c @@ -5,7 +5,7 @@ #include #include #include -#include "common/int-util.h" +#include "int-util.h" #include "hash-ops.h" #include "keccak.h" diff --git a/src/crypto/skein_port.h b/src/crypto/skein_port.h index a50a28e6b..8a1640e57 100644 --- a/src/crypto/skein_port.h +++ b/src/crypto/skein_port.h @@ -114,7 +114,7 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */ #ifndef SKEIN_NEED_SWAP /* compile-time "override" for endianness? */ -#include "common/int-util.h" +#include "int-util.h" #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index dcbabccab..ae0bd4e98 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -35,7 +35,7 @@ #include #include -#include "common/int-util.h" +#include "int-util.h" #include "hash-ops.h" #include "oaes_lib.h" #include "variant2_int_sqrt.h" diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index c4e10851e..41b5f19f0 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -40,7 +40,7 @@ using namespace epee; #include "misc_language.h" #include "common/base58.h" #include "crypto/hash.h" -#include "common/int-util.h" +#include "int-util.h" #include "common/dns_utils.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index cb2a00a12..55e3e93b3 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -34,7 +34,7 @@ #include #include -#include "common/int-util.h" +#include "int-util.h" #include "crypto/hash.h" #include "cryptonote_config.h" #include "difficulty.h" diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 80e0a983e..ca569a16f 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -44,7 +44,7 @@ #include "misc_language.h" #include "profile_tools.h" #include "file_io_utils.h" -#include "common/int-util.h" +#include "int-util.h" #include "common/threadpool.h" #include "common/boost_serialization_helper.h" #include "warnings.h" diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index e2900916b..d4b4e4d34 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -40,7 +40,7 @@ #include "blockchain.h" #include "blockchain_db/blockchain_db.h" #include "common/boost_serialization_helper.h" -#include "common/int-util.h" +#include "int-util.h" #include "misc_language.h" #include "warnings.h" #include "common/perf_timer.h" diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index 1e3d80949..2286998a4 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -31,7 +31,7 @@ #include "device_default.hpp" -#include "common/int-util.h" +#include "int-util.h" #include "cryptonote_basic/account.h" #include "cryptonote_basic/subaddress_index.h" #include "ringct/rctOps.h" diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index e6d2a6b76..b1e3bdcd5 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -42,7 +42,7 @@ #include #include "wipeable_string.h" #include "misc_language.h" -#include "common/int-util.h" +#include "int-util.h" #include "mnemonics/electrum-words.h" #include diff --git a/tests/unit_tests/mul_div.cpp b/tests/unit_tests/mul_div.cpp index 8408d0da1..768b95d4b 100644 --- a/tests/unit_tests/mul_div.cpp +++ b/tests/unit_tests/mul_div.cpp @@ -30,7 +30,7 @@ #include "gtest/gtest.h" -#include "common/int-util.h" +#include "int-util.h" namespace { From 9c923bad9b4a7a2dfaf949255cea9ac4ff33eee6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 18 Nov 2018 10:18:35 +0000 Subject: [PATCH 0352/1007] epee: fix network packet header field endianness --- contrib/epee/include/net/levin_client.inl | 41 ++++++------- contrib/epee/include/net/levin_helper.h | 41 +++++++++---- .../epee/include/net/levin_protocol_handler.h | 19 ++++-- .../net/levin_protocol_handler_async.h | 60 +++++++++++++------ .../epee/include/storages/portable_storage.h | 9 +-- 5 files changed, 113 insertions(+), 57 deletions(-) diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl index ab7c32c32..a580e81fd 100644 --- a/contrib/epee/include/net/levin_client.inl +++ b/contrib/epee/include/net/levin_client.inl @@ -80,10 +80,10 @@ int levin_client_impl::invoke(int command, const std::string& in_buff, std::stri return -1; bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_command = command; + head.m_command = SWAP32LE(command); if(!m_transport.send(&head, sizeof(head))) return -1; @@ -97,7 +97,7 @@ int levin_client_impl::invoke(int command, const std::string& in_buff, std::stri head = *(bucket_head*)local_buff.data(); - if(head.m_signature!=LEVIN_SIGNATURE) + if(head.m_signature!=SWAP64LE(LEVIN_SIGNATURE)) { LOG_PRINT_L1("Signature mismatch in response"); return -1; @@ -116,10 +116,10 @@ int levin_client_impl::notify(int command, const std::string& in_buff) return -1; bucket_head head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = false; - head.m_command = command; + head.m_command = SWAP32LE(command); if(!m_transport.send((const char*)&head, sizeof(head))) return -1; @@ -139,12 +139,13 @@ inline return -1; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_return_code = SWAP32LE(0); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); if(!m_transport.send(&head, sizeof(head))) return -1; @@ -157,14 +158,13 @@ inline head = *(bucket_head2*)local_buff.data(); - - if(head.m_signature!=LEVIN_SIGNATURE) + if(head.m_signature != SWAP64LE(LEVIN_SIGNATURE)) { LOG_PRINT_L1("Signature mismatch in response"); return -1; } - if(!m_transport.recv_n(buff_out, head.m_cb)) + if(!m_transport.recv_n(buff_out, SWAP64LE(head.m_cb))) return -1; return head.m_return_code; @@ -177,12 +177,13 @@ inline return -1; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = false; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_return_code = SWAP32LE(0); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); if(!m_transport.send((const char*)&head, sizeof(head))) return -1; diff --git a/contrib/epee/include/net/levin_helper.h b/contrib/epee/include/net/levin_helper.h index 05560dd90..da926a914 100644 --- a/contrib/epee/include/net/levin_helper.h +++ b/contrib/epee/include/net/levin_helper.h @@ -30,6 +30,7 @@ #include "levin_base.h" #include "serializeble_struct_helper.h" +#include "int-util.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" @@ -43,11 +44,11 @@ namespace levin { buff.resize(sizeof(levin::bucket_head)); levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_cb = 0; head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; + head.m_command = SWAP32LE(command_id); + head.m_return_code = SWAP32LE(1); head.m_reservedA = rand(); //probably some flags in future head.m_reservedB = rand(); //probably some check summ in future @@ -55,7 +56,7 @@ namespace levin if(!StorageNamed::save_struct_as_storage_to_buff_t(t, buff_strg)) return false; - head.m_cb = buff_strg.size(); + head.m_cb = SWAP64LE(buff_strg.size()); buff.append(buff_strg); return true; } @@ -65,15 +66,15 @@ namespace levin { buff.resize(sizeof(levin::bucket_head)); levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_cb = 0; head.m_have_to_return_data = true; - head.m_command = command_id; - head.m_return_code = 1; + head.m_command = SWAP32LE(command_id); + head.m_return_code = SWAP32LE(1); head.m_reservedA = rand(); //probably some flags in future head.m_reservedB = rand(); //probably some check summ in future - head.m_cb = data.size(); + head.m_cb = SWAP64LE(data.size()); buff.append(data); return true; } @@ -86,7 +87,17 @@ namespace levin return false; } - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); +#if BYTE_ORDER == LITTLE_ENDIAN + levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); +#else + levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_reservedA = SWAP32LE(head.m_reservedA); + head.m_reservedB = SWAP32LE(head.m_reservedB); +#endif if(head.m_signature != LEVIN_SIGNATURE) { LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); @@ -113,7 +124,17 @@ namespace levin return false; } - levin::bucket_head& head = *(levin::bucket_head*)(&buff[0]); +#if BYTE_ORDER == LITTLE_ENDIAN + levin::bucket_head &head = *(levin::bucket_head*)(&buff[0]); +#else + levin::bucket_head head = *(levin::bucket_head*)(&buff[0]); + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_reservedA = SWAP32LE(head.m_reservedA); + head.m_reservedB = SWAP32LE(head.m_reservedB); +#endif if(head.m_signature != LEVIN_SIGNATURE) { LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); diff --git a/contrib/epee/include/net/levin_protocol_handler.h b/contrib/epee/include/net/levin_protocol_handler.h index b3a75bedc..791766762 100644 --- a/contrib/epee/include/net/levin_protocol_handler.h +++ b/contrib/epee/include/net/levin_protocol_handler.h @@ -31,6 +31,7 @@ #include #include "levin_base.h" +#include "int-util.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" @@ -103,7 +104,7 @@ namespace levin case conn_state_reading_head: if(m_cach_in_buffer.size() < sizeof(bucket_head)) { - if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) + if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != SWAP64LE(LEVIN_SIGNATURE)) { LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); return false; @@ -112,13 +113,23 @@ namespace levin break; } { - bucket_head* phead = (bucket_head*)m_cach_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) +#if BYTE_ORDER == LITTLE_ENDIAN + bucket_head &phead = *(bucket_head*)m_cach_in_buffer.data(); +#else + bucket_head phead = *(bucket_head*)m_cach_in_buffer.data(); + phead.m_signature = SWAP64LE(phead.m_signature); + phead.m_cb = SWAP64LE(phead.m_cb); + phead.m_command = SWAP32LE(phead.m_command); + phead.m_return_code = SWAP32LE(phead.m_return_code); + phead.m_reservedA = SWAP32LE(phead.m_reservedA); + phead.m_reservedB = SWAP32LE(phead.m_reservedB); +#endif + if(LEVIN_SIGNATURE != phead.m_signature) { LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); return false; } - m_current_head = *phead; + m_current_head = phead; } m_cach_in_buffer.erase(0, sizeof(bucket_head)); m_state = conn_state_reading_body; diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 08aa1d468..6b1528caf 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -37,6 +37,7 @@ #include "misc_language.h" #include "syncobj.h" #include "misc_os_dependent.h" +#include "int-util.h" #include #include @@ -469,7 +470,18 @@ class async_protocol_handler m_current_head.m_have_to_return_data = false; m_current_head.m_protocol_version = LEVIN_PROTOCOL_VER_1; m_current_head.m_flags = LEVIN_PACKET_RESPONSE; +#if BYTE_ORDER == LITTLE_ENDIAN std::string send_buff((const char*)&m_current_head, sizeof(m_current_head)); +#else + bucket_head2 head = m_current_head; + head.m_signature = SWAP64LE(head.m_signature); + head.m_cb = SWAP64LE(head.m_cb); + head.m_command = SWAP32LE(head.m_command); + head.m_return_code = SWAP32LE(head.m_return_code); + head.m_flags = SWAP32LE(head.m_flags); + head.m_protocol_version = SWAP32LE(head.m_protocol_version); + std::string send_buff((const char*)&head, sizeof(head)); +#endif send_buff += return_buff; CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) @@ -491,7 +503,7 @@ class async_protocol_handler { if(m_cache_in_buffer.size() < sizeof(bucket_head2)) { - if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) + if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.data()) != SWAP64LE(LEVIN_SIGNATURE)) { MWARNING(m_connection_context << "Signature mismatch, connection will be closed"); return false; @@ -500,13 +512,23 @@ class async_protocol_handler break; } - bucket_head2* phead = (bucket_head2*)m_cache_in_buffer.data(); - if(LEVIN_SIGNATURE != phead->m_signature) +#if BYTE_ORDER == LITTLE_ENDIAN + bucket_head2& phead = *(bucket_head2*)m_cache_in_buffer.data(); +#else + bucket_head2 phead = *(bucket_head2*)m_cache_in_buffer.data(); + phead.m_signature = SWAP64LE(phead.m_signature); + phead.m_cb = SWAP64LE(phead.m_cb); + phead.m_command = SWAP32LE(phead.m_command); + phead.m_return_code = SWAP32LE(phead.m_return_code); + phead.m_flags = SWAP32LE(phead.m_flags); + phead.m_protocol_version = SWAP32LE(phead.m_protocol_version); +#endif + if(LEVIN_SIGNATURE != phead.m_signature) { LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); return false; } - m_current_head = *phead; + m_current_head = phead; m_cache_in_buffer.erase(0, sizeof(bucket_head2)); m_state = stream_state_body; @@ -566,13 +588,13 @@ class async_protocol_handler } bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); CRITICAL_REGION_BEGIN(m_send_lock); @@ -624,13 +646,13 @@ class async_protocol_handler return LEVIN_ERROR_CONNECTION_DESTROYED; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; - head.m_cb = in_buff.size(); + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); + head.m_cb = SWAP64LE(in_buff.size()); head.m_have_to_return_data = true; - head.m_flags = LEVIN_PACKET_REQUEST; - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); CRITICAL_REGION_BEGIN(m_send_lock); @@ -698,13 +720,13 @@ class async_protocol_handler return LEVIN_ERROR_CONNECTION_DESTROYED; bucket_head2 head = {0}; - head.m_signature = LEVIN_SIGNATURE; + head.m_signature = SWAP64LE(LEVIN_SIGNATURE); head.m_have_to_return_data = false; - head.m_cb = in_buff.size(); + head.m_cb = SWAP64LE(in_buff.size()); - head.m_command = command; - head.m_protocol_version = LEVIN_PROTOCOL_VER_1; - head.m_flags = LEVIN_PACKET_REQUEST; + head.m_command = SWAP32LE(command); + head.m_protocol_version = SWAP32LE(LEVIN_PROTOCOL_VER_1); + head.m_flags = SWAP32LE(LEVIN_PACKET_REQUEST); CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(&head, sizeof(head))) { diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index 2023e2f2a..0f0c6210f 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -35,6 +35,7 @@ #include "portable_storage_to_json.h" #include "portable_storage_from_json.h" #include "portable_storage_val_converters.h" +#include "int-util.h" namespace epee { @@ -135,8 +136,8 @@ namespace epee TRY_ENTRY(); std::stringstream ss; storage_block_header sbh = AUTO_VAL_INIT(sbh); - sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; - sbh.m_signature_b = PORTABLE_STORAGE_SIGNATUREB; + sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA); + sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB); sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER; ss.write((const char*)&sbh, sizeof(storage_block_header)); pack_entry_to_buff(ss, m_root); @@ -154,8 +155,8 @@ namespace epee return false; } storage_block_header* pbuff = (storage_block_header*)source.data(); - if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || - pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB + if(pbuff->m_signature_a != SWAP32LE(PORTABLE_STORAGE_SIGNATUREA) || + pbuff->m_signature_b != SWAP32LE(PORTABLE_STORAGE_SIGNATUREB) ) { LOG_ERROR("portable_storage: wrong binary format - signature mismatch"); From 243f010edc50bb588779d4d63e73e16e59bc27bc Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 20 Nov 2018 21:41:03 +0000 Subject: [PATCH 0353/1007] rpc: mask values that are nobody else's business in restricted RPC --- src/rpc/core_rpc_server.cpp | 53 ++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 1bb353bb4..715858583 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -182,20 +182,19 @@ namespace cryptonote res.target = m_core.get_blockchain_storage().get_difficulty_target(); res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase res.tx_pool_size = m_core.get_pool_transactions_count(); - res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); - uint64_t total_conn = m_p2p.get_connections_count(); - res.outgoing_connections_count = m_p2p.get_outgoing_connections_count(); - res.incoming_connections_count = total_conn - res.outgoing_connections_count; - res.rpc_connections_count = get_connections_count(); - res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); - res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); + res.alt_blocks_count = m_restricted ? 0 : m_core.get_blockchain_storage().get_alternative_blocks_count(); + uint64_t total_conn = m_restricted ? 0 : m_p2p.get_connections_count(); + res.outgoing_connections_count = m_restricted ? 0 : m_p2p.get_outgoing_connections_count(); + res.incoming_connections_count = m_restricted ? 0 : (total_conn - res.outgoing_connections_count); + res.rpc_connections_count = m_restricted ? 0 : get_connections_count(); + res.white_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_white_peers_count(); + res.grey_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_gray_peers_count(); cryptonote::network_type net_type = nettype(); res.mainnet = net_type == MAINNET; res.testnet = net_type == TESTNET; res.stagenet = net_type == STAGENET; res.nettype = net_type == MAINNET ? "mainnet" : net_type == TESTNET ? "testnet" : net_type == STAGENET ? "stagenet" : "fakechain"; - res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit(); res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median(); @@ -203,14 +202,17 @@ namespace cryptonote res.start_time = m_restricted ? 0 : (uint64_t)m_core.get_start_time(); res.free_space = m_restricted ? std::numeric_limits::max() : m_core.get_free_space(); res.offline = m_core.offline(); - res.bootstrap_daemon_address = m_bootstrap_daemon_address; - res.height_without_bootstrap = res.height; + res.bootstrap_daemon_address = m_restricted ? "" : m_bootstrap_daemon_address; + res.height_without_bootstrap = m_restricted ? 0 : res.height; + if (m_restricted) + res.was_bootstrap_ever_used = false; + else { boost::shared_lock lock(m_bootstrap_daemon_mutex); res.was_bootstrap_ever_used = m_was_bootstrap_ever_used; } - res.database_size = m_core.get_blockchain_storage().get_db().get_database_size(); - res.update_available = m_core.is_update_available(); + res.database_size = m_restricted ? 0 : m_core.get_blockchain_storage().get_db().get_database_size(); + res.update_available = m_restricted ? false : m_core.is_update_available(); res.version = m_restricted ? "" : MONERO_VERSION; return true; } @@ -1585,13 +1587,13 @@ namespace cryptonote res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase res.tx_pool_size = m_core.get_pool_transactions_count(); - res.alt_blocks_count = m_core.get_blockchain_storage().get_alternative_blocks_count(); - uint64_t total_conn = m_p2p.get_connections_count(); - res.outgoing_connections_count = m_p2p.get_outgoing_connections_count(); - res.incoming_connections_count = total_conn - res.outgoing_connections_count; - res.rpc_connections_count = get_connections_count(); - res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count(); - res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); + res.alt_blocks_count = m_restricted ? 0 : m_core.get_blockchain_storage().get_alternative_blocks_count(); + uint64_t total_conn = m_restricted ? 0 : m_p2p.get_connections_count(); + res.outgoing_connections_count = m_restricted ? 0 : m_p2p.get_outgoing_connections_count(); + res.incoming_connections_count = m_restricted ? 0 : (total_conn - res.outgoing_connections_count); + res.rpc_connections_count = m_restricted ? 0 : get_connections_count(); + res.white_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_white_peers_count(); + res.grey_peerlist_size = m_restricted ? 0 : m_p2p.get_peerlist_manager().get_gray_peers_count(); cryptonote::network_type net_type = nettype(); res.mainnet = net_type == MAINNET; @@ -1603,17 +1605,20 @@ namespace cryptonote res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit(); res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median(); res.status = CORE_RPC_STATUS_OK; - res.start_time = (uint64_t)m_core.get_start_time(); + res.start_time = m_restricted ? 0 : (uint64_t)m_core.get_start_time(); res.free_space = m_restricted ? std::numeric_limits::max() : m_core.get_free_space(); res.offline = m_core.offline(); - res.bootstrap_daemon_address = m_bootstrap_daemon_address; - res.height_without_bootstrap = res.height; + res.bootstrap_daemon_address = m_restricted ? "" : m_bootstrap_daemon_address; + res.height_without_bootstrap = m_restricted ? 0 : res.height; + if (m_restricted) + res.was_bootstrap_ever_used = false; + else { boost::shared_lock lock(m_bootstrap_daemon_mutex); res.was_bootstrap_ever_used = m_was_bootstrap_ever_used; } - res.database_size = m_core.get_blockchain_storage().get_db().get_database_size(); - res.update_available = m_core.is_update_available(); + res.database_size = m_restricted ? 0 : m_core.get_blockchain_storage().get_db().get_database_size(); + res.update_available = m_restricted ? false : m_core.is_update_available(); res.version = m_restricted ? "" : MONERO_VERSION; return true; } From d21dad70ddda771bf33a19f9a53c48cc91d8464f Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Mon, 12 Nov 2018 00:07:25 +0100 Subject: [PATCH 0354/1007] device: enable to use multiple independent device wallets - adds a new option `--hw-device-deriv-path` to the simple wallet. Enables to specify wallet derivation path / wallet code (path avoided so it can be misinterpreted as a file path). - devices can use different derivation mechanisms. Trezor uses standard SLIP-10 mechanism with fixed SLIP-44 prefix for Monero - Trezor: when empty, the default derivation mechanism is used with 44'/128'/0'. When entered the derivation path is 44'/128'/PATH. - Trezor: the path is always taken as elements are hardened (1<<31 bit turned on) --- src/device/device.hpp | 1 + src/device_trezor/device_trezor_base.cpp | 39 +++++++++++++++++++++++- src/device_trezor/device_trezor_base.hpp | 10 +++++- src/simplewallet/simplewallet.cpp | 2 ++ src/wallet/wallet2.cpp | 19 ++++++++++++ src/wallet/wallet2.h | 4 +++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/device/device.hpp b/src/device/device.hpp index 3e782d21a..399648f01 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -138,6 +138,7 @@ namespace hw { virtual device_protocol_t device_protocol() const { return PROTOCOL_DEFAULT; }; virtual void set_callback(i_device_callback * callback) {}; + virtual void set_derivation_path(const std::string &derivation_path) {}; /* ======================================================================= */ /* LOCKER */ diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index dcfc9cb67..fddc6082c 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -28,6 +28,9 @@ // #include "device_trezor_base.hpp" +#include +#include +#include namespace hw { namespace trezor { @@ -36,8 +39,9 @@ namespace trezor { #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "device.trezor" +#define TREZOR_BIP44_HARDENED_ZERO 0x80000000 - const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080, 0x80000000}; + const uint32_t device_trezor_base::DEFAULT_BIP44_PATH[] = {0x8000002c, 0x80000080}; device_trezor_base::device_trezor_base(): m_callback(nullptr) { @@ -252,6 +256,39 @@ namespace trezor { } } + void device_trezor_base::ensure_derivation_path() noexcept { + if (m_wallet_deriv_path.empty()){ + m_wallet_deriv_path.push_back(TREZOR_BIP44_HARDENED_ZERO); // default 0' + } + } + + void device_trezor_base::set_derivation_path(const std::string &deriv_path){ + this->m_wallet_deriv_path.clear(); + + if (deriv_path.empty() || deriv_path == "-"){ + ensure_derivation_path(); + return; + } + + CHECK_AND_ASSERT_THROW_MES(deriv_path.size() <= 255, "Derivation path is too long"); + + std::vector fields; + boost::split(fields, deriv_path, boost::is_any_of("/")); + CHECK_AND_ASSERT_THROW_MES(fields.size() <= 10, "Derivation path is too long"); + + boost::regex rgx("^([0-9]+)'?$"); + boost::cmatch match; + + this->m_wallet_deriv_path.reserve(fields.size()); + for(const std::string & cur : fields){ + const bool ok = boost::regex_match(cur.c_str(), match, rgx); + CHECK_AND_ASSERT_THROW_MES(ok, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur); + CHECK_AND_ASSERT_THROW_MES(match[0].length() > 0, "Invalid wallet code: " << deriv_path << ". Invalid path element: " << cur); + + const unsigned long cidx = std::stoul(match[0].str()) | TREZOR_BIP44_HARDENED_ZERO; + this->m_wallet_deriv_path.push_back((unsigned int)cidx); + } + } /* ======================================================================= */ /* TREZOR PROTOCOL */ diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index a4e92bf78..4d205ad7a 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -71,6 +71,7 @@ namespace trezor { i_device_callback * m_callback; std::string full_name; + std::vector m_wallet_deriv_path; cryptonote::network_type network_type; @@ -81,6 +82,7 @@ namespace trezor { void require_connected(); void call_ping_unsafe(); void test_ping(); + void ensure_derivation_path() noexcept; // Communication methods @@ -176,9 +178,13 @@ namespace trezor { msg->add_address_n(x); } } else { + ensure_derivation_path(); for (unsigned int i : DEFAULT_BIP44_PATH) { msg->add_address_n(i); } + for (unsigned int i : m_wallet_deriv_path) { + msg->add_address_n(i); + } } if (network_type){ @@ -201,7 +207,7 @@ namespace trezor { bool reset(); // Default derivation path for Monero - static const uint32_t DEFAULT_BIP44_PATH[3]; + static const uint32_t DEFAULT_BIP44_PATH[2]; std::shared_ptr getTransport(){ return m_transport; @@ -215,6 +221,8 @@ namespace trezor { return m_callback; } + void set_derivation_path(const std::string &deriv_path) override; + /* ======================================================================= */ /* SETUP/TEARDOWN */ /* ======================================================================= */ diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 6d19235c5..07084d15b 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3804,9 +3804,11 @@ boost::optional simple_wallet::new_wallet(const boost::pr m_wallet->set_refresh_from_block_height(m_restore_height); auto device_desc = tools::wallet2::device_name_option(vm); + auto device_derivation_path = tools::wallet2::device_derivation_path_option(vm); try { bool create_address_file = command_line::get_arg(vm, arg_create_address_file); + m_wallet->device_derivation_path(device_derivation_path); m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_desc.empty() ? "Ledger" : device_desc, create_address_file); message_writer(console_color_white, true) << tr("Generated new wallet on hw device: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index ae6ed0937..83aae6de3 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -207,6 +207,7 @@ struct options { }; const command_line::arg_descriptor kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1}; const command_line::arg_descriptor hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""}; + const command_line::arg_descriptor hw_device_derivation_path = {"hw-device-deriv-path", tools::wallet2::tr("HW device wallet derivation path (e.g., SLIP-10)"), ""}; const command_line::arg_descriptor tx_notify = { "tx-notify" , "Run a program for each new incoming transaction, '%s' will be replaced by the transaction hash" , "" }; }; @@ -259,6 +260,7 @@ std::unique_ptr make_basic(const boost::program_options::variabl auto daemon_host = command_line::get_arg(vm, opts.daemon_host); auto daemon_port = command_line::get_arg(vm, opts.daemon_port); auto device_name = command_line::get_arg(vm, opts.hw_device); + auto device_derivation_path = command_line::get_arg(vm, opts.hw_device_derivation_path); THROW_WALLET_EXCEPTION_IF(!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port, tools::error::wallet_internal_error, tools::wallet2::tr("can't specify daemon host or port more than once")); @@ -314,6 +316,7 @@ std::unique_ptr make_basic(const boost::program_options::variabl boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir); wallet->set_ring_database(ringdb_path.string()); wallet->device_name(device_name); + wallet->device_derivation_path(device_derivation_path); try { @@ -912,6 +915,11 @@ std::string wallet2::device_name_option(const boost::program_options::variables_ return command_line::get_arg(vm, options().hw_device); } +std::string wallet2::device_derivation_path_option(const boost::program_options::variables_map &vm) +{ + return command_line::get_arg(vm, options().hw_device_derivation_path); +} + void wallet2::init_options(boost::program_options::options_description& desc_params) { const options opts{}; @@ -928,6 +936,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par command_line::add_arg(desc_params, opts.shared_ringdb_dir); command_line::add_arg(desc_params, opts.kdf_rounds); command_line::add_arg(desc_params, opts.hw_device); + command_line::add_arg(desc_params, opts.hw_device_derivation_path); command_line::add_arg(desc_params, opts.tx_notify); } @@ -1089,6 +1098,7 @@ bool wallet2::reconnect_device() hw::device &hwdev = lookup_device(m_device_name); hwdev.set_name(m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_derivation_path(m_device_derivation_path); hwdev.set_callback(get_device_callback()); r = hwdev.init(); if (!r){ @@ -3160,6 +3170,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable value.SetString(m_device_name.c_str(), m_device_name.size()); json.AddMember("device_name", value, json.GetAllocator()); + value.SetString(m_device_derivation_path.c_str(), m_device_derivation_path.size()); + json.AddMember("device_derivation_path", value, json.GetAllocator()); + // Serialize the JSON object rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); @@ -3279,6 +3292,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR; m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR; m_device_name = ""; + m_device_derivation_path = ""; m_key_device_type = hw::device::device_type::SOFTWARE; encrypted_secret_keys = false; } @@ -3446,6 +3460,9 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_device_name = m_key_device_type == hw::device::device_type::LEDGER ? "Ledger" : "default"; } } + + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_derivation_path, std::string, String, false, std::string()); + m_device_derivation_path = field_device_derivation_path; } else { @@ -3460,6 +3477,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ hw::device &hwdev = lookup_device(m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.set_name(m_device_name), error::wallet_internal_error, "Could not set device name " + m_device_name); hwdev.set_network_type(m_nettype); + hwdev.set_derivation_path(m_device_derivation_path); hwdev.set_callback(get_device_callback()); THROW_WALLET_EXCEPTION_IF(!hwdev.init(), error::wallet_internal_error, "Could not initialize the device " + m_device_name); THROW_WALLET_EXCEPTION_IF(!hwdev.connect(), error::wallet_internal_error, "Could not connect to the device " + m_device_name); @@ -3967,6 +3985,7 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p auto &hwdev = lookup_device(device_name); hwdev.set_name(device_name); hwdev.set_network_type(m_nettype); + hwdev.set_derivation_path(m_device_derivation_path); hwdev.set_callback(get_device_callback()); m_account.create_from_device(hwdev); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c07054177..a588e8003 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -191,6 +191,7 @@ namespace tools static bool has_testnet_option(const boost::program_options::variables_map& vm); static bool has_stagenet_option(const boost::program_options::variables_map& vm); static std::string device_name_option(const boost::program_options::variables_map& vm); + static std::string device_derivation_path_option(const boost::program_options::variables_map &vm); static void init_options(boost::program_options::options_description& desc_params); //! Uses stdin and stdout. Returns a wallet2 if no errors. @@ -978,6 +979,8 @@ namespace tools void confirm_non_default_ring_size(bool always) { m_confirm_non_default_ring_size = always; } const std::string & device_name() const { return m_device_name; } void device_name(const std::string & device_name) { m_device_name = device_name; } + const std::string & device_derivation_path() const { return m_device_derivation_path; } + void device_derivation_path(const std::string &device_derivation_path) { m_device_derivation_path = device_derivation_path; } bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &additional_tx_keys) const; void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys); @@ -1384,6 +1387,7 @@ namespace tools std::unordered_set m_scanned_pool_txs[2]; size_t m_subaddress_lookahead_major, m_subaddress_lookahead_minor; std::string m_device_name; + std::string m_device_derivation_path; // Aux transaction data from device std::unordered_map m_tx_device; From 9cf636af696edfa5ad5d0679c95a67f9a15e0635 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Mon, 12 Nov 2018 04:13:54 +0100 Subject: [PATCH 0355/1007] device/trezor: ask for KI sync on first refresh When doing a first refresh on HW-token based wallet KI sync is required if money were received. Received money may indicate wallet was already used before the restore I.e., some transaction could have been already sent from the wallet. The spent UTXO would not be detected as spent which could lead to double spending errors on submitting a new transaction. Thus if the wallet is HW-token based with the cold signing protocol and the first refresh detected received money the user is asked to perform the key image sync. --- src/simplewallet/simplewallet.cpp | 53 ++++++++++++++++++++++++------- src/simplewallet/simplewallet.h | 2 ++ src/wallet/wallet2.cpp | 14 +++++--- src/wallet/wallet2.h | 7 +++- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 07084d15b..c85cbfb8a 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -4341,6 +4341,29 @@ void simple_wallet::on_passphrase_request(bool on_device, epee::wipeable_string passphrase = pwd_container->password(); } //---------------------------------------------------------------------------------------------------- +void simple_wallet::on_refresh_finished(uint64_t start_height, uint64_t fetched_blocks, bool is_init, bool received_money) +{ + // Key image sync after the first refresh + if (!m_wallet->get_account().get_device().has_tx_cold_sign()) { + return; + } + + if (!received_money || m_wallet->get_device_last_key_image_sync() != 0) { + return; + } + + // Finished first refresh for HW device and money received -> KI sync + message_writer() << "\n" << tr("The first refresh has finished for the HW-based wallet with received money. hw_key_images_sync is needed. "); + + std::string accepted = input_line(tr("Do you want to do it now? (Y/Yes/N/No): ")); + if (std::cin.eof() || !command_line::is_yes(accepted)) { + message_writer(console_color_red, false) << tr("hw_key_images_sync skipped. Run command manually before a transfer."); + return; + } + + key_images_sync_intern(); +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bool is_init) { if (!try_connect_to_daemon(is_init)) @@ -4358,13 +4381,14 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo message_writer() << tr("Starting refresh..."); uint64_t fetched_blocks = 0; + bool received_money = false; bool ok = false; std::ostringstream ss; try { m_in_manual_refresh.store(true, std::memory_order_relaxed); epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){m_in_manual_refresh.store(false, std::memory_order_relaxed);}); - m_wallet->refresh(m_wallet->is_trusted_daemon(), start_height, fetched_blocks); + m_wallet->refresh(m_wallet->is_trusted_daemon(), start_height, fetched_blocks, received_money); ok = true; // Clear line "Height xxx of xxx" std::cout << "\r \r"; @@ -4372,6 +4396,7 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo if (is_init) print_accounts(); show_balance_unlocked(); + on_refresh_finished(start_height, fetched_blocks, is_init, received_money); } catch (const tools::error::daemon_busy&) { @@ -8134,13 +8159,13 @@ bool simple_wallet::hw_key_images_sync(const std::vector &args) fail_msg_writer() << tr("hw wallet does not support cold KI sync"); return true; } - if (!m_wallet->is_trusted_daemon()) - { - fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); - return true; - } LOCK_IDLE_SCOPE(); + key_images_sync_intern(); + return true; +} +//---------------------------------------------------------------------------------------------------- +void simple_wallet::key_images_sync_intern(){ try { message_writer(console_color_white, false) << tr("Please confirm the key image sync on the device"); @@ -8149,19 +8174,23 @@ bool simple_wallet::hw_key_images_sync(const std::vector &args) uint64_t height = m_wallet->cold_key_image_sync(spent, unspent); if (height > 0) { - success_msg_writer() << tr("Signed key images imported to height ") << height << ", " - << print_money(spent) << tr(" spent, ") << print_money(unspent) << tr(" unspent"); - } else { + success_msg_writer() << tr("Key images synchronized to height ") << height; + if (!m_wallet->is_trusted_daemon()) + { + message_writer() << tr("Running untrusted daemon, cannot determine which transaction output is spent. Use a trusted daemon with --trusted-daemon and run rescan_spent"); + } else + { + success_msg_writer() << print_money(spent) << tr(" spent, ") << print_money(unspent) << tr(" unspent"); + } + } + else { fail_msg_writer() << tr("Failed to import key images"); } } catch (const std::exception &e) { fail_msg_writer() << tr("Failed to import key images: ") << e.what(); - return true; } - - return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::hw_reconnect(const std::vector &args) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 7e2edba7f..665879cac 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -241,6 +241,8 @@ namespace cryptonote bool print_ring_members(const std::vector& ptx_vector, std::ostream& ostr); std::string get_prompt() const; bool print_seed(bool encrypted); + void key_images_sync_intern(); + void on_refresh_finished(uint64_t start_height, uint64_t fetched_blocks, bool is_init, bool received_money); struct transfer_view { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 83aae6de3..46bd47353 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -892,7 +892,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended): m_ringdb(), m_last_block_reward(0), m_encrypt_keys_after_refresh(boost::none), - m_unattended(unattended) + m_unattended(unattended), + m_device_last_key_image_sync(0) { } @@ -3009,6 +3010,7 @@ bool wallet2::clear() m_subaddresses.clear(); m_subaddress_labels.clear(); m_multisig_rounds_passed = 0; + m_device_last_key_image_sync = 0; return true; } @@ -9235,9 +9237,7 @@ void wallet2::cold_sign_tx(const std::vector& ptx_vector, signed_tx_ //---------------------------------------------------------------------------------------------------- uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { auto & hwdev = get_account().get_device(); - if (!hwdev.has_ki_cold_sync()){ - throw std::invalid_argument("Device does not support cold ki sync protocol"); - } + CHECK_AND_ASSERT_THROW_MES(hwdev.has_ki_cold_sync(), "Device does not support cold ki sync protocol"); auto dev_cold = dynamic_cast<::hw::device_cold*>(&hwdev); CHECK_AND_ASSERT_THROW_MES(dev_cold, "Device does not implement cold signing interface"); @@ -9248,7 +9248,11 @@ uint64_t wallet2::cold_key_image_sync(uint64_t &spent, uint64_t &unspent) { dev_cold->ki_sync(&wallet_shim, m_transfers, ski); - return import_key_images(ski, 0, spent, unspent); + // Call COMMAND_RPC_IS_KEY_IMAGE_SPENT only if daemon is trusted. + uint64_t import_res = import_key_images(ski, 0, spent, unspent, is_trusted_daemon()); + m_device_last_key_image_sync = time(NULL); + + return import_res; } //---------------------------------------------------------------------------------------------------- void wallet2::get_hard_fork_info(uint8_t version, uint64_t &earliest_height) const diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index a588e8003..4d121598b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -810,6 +810,7 @@ namespace tools bool is_transfer_unlocked(uint64_t unlock_time, uint64_t block_height) const; uint64_t get_last_block_reward() const { return m_last_block_reward; } + uint64_t get_device_last_key_image_sync() const { return m_device_last_key_image_sync; } template inline void serialize(t_archive &a, const unsigned int ver) @@ -918,6 +919,9 @@ namespace tools if(ver < 26) return; a & m_tx_device; + if(ver < 27) + return; + a & m_device_last_key_image_sync; } /*! @@ -1388,6 +1392,7 @@ namespace tools size_t m_subaddress_lookahead_major, m_subaddress_lookahead_minor; std::string m_device_name; std::string m_device_derivation_path; + uint64_t m_device_last_key_image_sync; // Aux transaction data from device std::unordered_map m_tx_device; @@ -1424,7 +1429,7 @@ namespace tools std::unique_ptr m_device_callback; }; } -BOOST_CLASS_VERSION(tools::wallet2, 26) +BOOST_CLASS_VERSION(tools::wallet2, 27) BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 10) BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) From 65b9bca70e3aa0aabc135f952da3695fdab00918 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Thu, 29 Nov 2018 04:22:52 +0100 Subject: [PATCH 0356/1007] device/trezor: python2 compatibility - bundle dependencies --- src/device_trezor/trezor/tools/README.md | 22 ++- src/device_trezor/trezor/tools/pb2cpp.py | 14 +- .../trezor/tools/py2backports/__init__.py | 0 .../trezor/tools/py2backports/tempfile.py | 72 +++++++++ .../trezor/tools/py2backports/weakref.py | 148 ++++++++++++++++++ 5 files changed, 248 insertions(+), 8 deletions(-) create mode 100644 src/device_trezor/trezor/tools/py2backports/__init__.py create mode 100644 src/device_trezor/trezor/tools/py2backports/tempfile.py create mode 100644 src/device_trezor/trezor/tools/py2backports/weakref.py diff --git a/src/device_trezor/trezor/tools/README.md b/src/device_trezor/trezor/tools/README.md index b176017ac..0802e734a 100644 --- a/src/device_trezor/trezor/tools/README.md +++ b/src/device_trezor/trezor/tools/README.md @@ -10,14 +10,28 @@ Install `protoc` for your distribution. Requirements: Soft requirement: Python 3, can be easily installed with [pyenv]. +If Python 3 is used there are no additional python dependencies. -### Python 2 +Since Cmake 3.12 the `FindPython` module is used to locate the Python +interpreter in your system. It preferably searches for Python 3, if none +is found, it searches for Python 2. -Workaround if there is no Python3 available: +Lower version of the cmake uses another module which does not guarantee +ordering. If you want to override the selected python you can do it in +the following way: ```bash -pip install backports.tempfile -``` +export TREZOR_PYTHON=`which python3` +``` + + +### Python 2.7+ + +Python 3 has `tempfile.TemporaryDirectory` available but Python 2 lacks +this class so the message generation code uses `backports.tempfile` package +bundled in the repository. + +The minimal Python versions are 2.7 and 3.4 ### Regenerate messages diff --git a/src/device_trezor/trezor/tools/pb2cpp.py b/src/device_trezor/trezor/tools/pb2cpp.py index 4d7cc775f..3e0318ea5 100644 --- a/src/device_trezor/trezor/tools/pb2cpp.py +++ b/src/device_trezor/trezor/tools/pb2cpp.py @@ -14,12 +14,18 @@ try: from tempfile import TemporaryDirectory except: - # Py2 backward compatibility, optionally installed by user - # pip install backports.tempfile + # Py2 backward compatibility, using bundled sources. + # Original source: pip install backports.tempfile try: - from backports.tempfile import TemporaryDirectory + # Try bundled python version + import sys + sys.path.append(os.path.dirname(__file__)) + from py2backports.tempfile import TemporaryDirectory + except: - raise EnvironmentError('TemporaryDirectory could not be imported. Try: pip install backports.tempfile') + raise EnvironmentError('Python 2.7+ or 3.4+ is required. ' + 'TemporaryDirectory is not available in Python 2.' + 'Try to specify python to use, e.g.: "export TREZOR_PYTHON=`which python3`"') AUTO_HEADER = "# Automatically generated by pb2cpp\n" diff --git a/src/device_trezor/trezor/tools/py2backports/__init__.py b/src/device_trezor/trezor/tools/py2backports/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/device_trezor/trezor/tools/py2backports/tempfile.py b/src/device_trezor/trezor/tools/py2backports/tempfile.py new file mode 100644 index 000000000..e259dea3f --- /dev/null +++ b/src/device_trezor/trezor/tools/py2backports/tempfile.py @@ -0,0 +1,72 @@ +""" +https://github.com/pjdelport/backports.tempfile/blob/master/src/backports/tempfile.py +Partial backport of Python 3.5's tempfile module: + TemporaryDirectory +Backport modifications are marked with marked with "XXX backport". +""" +from __future__ import absolute_import + +import sys +import warnings as _warnings +from shutil import rmtree as _rmtree + +from py2backports.weakref import finalize + + +# XXX backport: Rather than backporting all of mkdtemp(), we just create a +# thin wrapper implementing its Python 3.5 signature. +if sys.version_info < (3, 5): + from tempfile import mkdtemp as old_mkdtemp + + def mkdtemp(suffix=None, prefix=None, dir=None): + """ + Wrap `tempfile.mkdtemp()` to make the suffix and prefix optional (like Python 3.5). + """ + kwargs = {k: v for (k, v) in + dict(suffix=suffix, prefix=prefix, dir=dir).items() + if v is not None} + return old_mkdtemp(**kwargs) + +else: + from tempfile import mkdtemp + + +# XXX backport: ResourceWarning was added in Python 3.2. +# For earlier versions, fall back to RuntimeWarning instead. +_ResourceWarning = RuntimeWarning if sys.version_info < (3, 2) else ResourceWarning + + +class TemporaryDirectory(object): + """Create and return a temporary directory. This has the same + behavior as mkdtemp but can be used as a context manager. For + example: + with TemporaryDirectory() as tmpdir: + ... + Upon exiting the context, the directory and everything contained + in it are removed. + """ + + def __init__(self, suffix=None, prefix=None, dir=None): + self.name = mkdtemp(suffix, prefix, dir) + self._finalizer = finalize( + self, self._cleanup, self.name, + warn_message="Implicitly cleaning up {!r}".format(self)) + + @classmethod + def _cleanup(cls, name, warn_message): + _rmtree(name) + _warnings.warn(warn_message, _ResourceWarning) + + + def __repr__(self): + return "<{} {!r}>".format(self.__class__.__name__, self.name) + + def __enter__(self): + return self.name + + def __exit__(self, exc, value, tb): + self.cleanup() + + def cleanup(self): + if self._finalizer.detach(): + _rmtree(self.name) diff --git a/src/device_trezor/trezor/tools/py2backports/weakref.py b/src/device_trezor/trezor/tools/py2backports/weakref.py new file mode 100644 index 000000000..eb646812b --- /dev/null +++ b/src/device_trezor/trezor/tools/py2backports/weakref.py @@ -0,0 +1,148 @@ +""" +https://github.com/pjdelport/backports.weakref/blob/master/src/backports/weakref.py +Partial backport of Python 3.6's weakref module: + finalize (new in Python 3.4) +Backport modifications are marked with "XXX backport". +""" +from __future__ import absolute_import + +import itertools +import sys +from weakref import ref + +__all__ = ['finalize'] + + +class finalize(object): + """Class for finalization of weakrefable objects + finalize(obj, func, *args, **kwargs) returns a callable finalizer + object which will be called when obj is garbage collected. The + first time the finalizer is called it evaluates func(*arg, **kwargs) + and returns the result. After this the finalizer is dead, and + calling it just returns None. + When the program exits any remaining finalizers for which the + atexit attribute is true will be run in reverse order of creation. + By default atexit is true. + """ + + # Finalizer objects don't have any state of their own. They are + # just used as keys to lookup _Info objects in the registry. This + # ensures that they cannot be part of a ref-cycle. + + __slots__ = () + _registry = {} + _shutdown = False + _index_iter = itertools.count() + _dirty = False + _registered_with_atexit = False + + class _Info(object): + __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index") + + def __init__(self, obj, func, *args, **kwargs): + if not self._registered_with_atexit: + # We may register the exit function more than once because + # of a thread race, but that is harmless + import atexit + atexit.register(self._exitfunc) + finalize._registered_with_atexit = True + info = self._Info() + info.weakref = ref(obj, self) + info.func = func + info.args = args + info.kwargs = kwargs or None + info.atexit = True + info.index = next(self._index_iter) + self._registry[self] = info + finalize._dirty = True + + def __call__(self, _=None): + """If alive then mark as dead and return func(*args, **kwargs); + otherwise return None""" + info = self._registry.pop(self, None) + if info and not self._shutdown: + return info.func(*info.args, **(info.kwargs or {})) + + def detach(self): + """If alive then mark as dead and return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None and self._registry.pop(self, None): + return (obj, info.func, info.args, info.kwargs or {}) + + def peek(self): + """If alive then return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None: + return (obj, info.func, info.args, info.kwargs or {}) + + @property + def alive(self): + """Whether finalizer is alive""" + return self in self._registry + + @property + def atexit(self): + """Whether finalizer should be called at exit""" + info = self._registry.get(self) + return bool(info) and info.atexit + + @atexit.setter + def atexit(self, value): + info = self._registry.get(self) + if info: + info.atexit = bool(value) + + def __repr__(self): + info = self._registry.get(self) + obj = info and info.weakref() + if obj is None: + return '<%s object at %#x; dead>' % (type(self).__name__, id(self)) + else: + return '<%s object at %#x; for %r at %#x>' % \ + (type(self).__name__, id(self), type(obj).__name__, id(obj)) + + @classmethod + def _select_for_exit(cls): + # Return live finalizers marked for exit, oldest first + L = [(f,i) for (f,i) in cls._registry.items() if i.atexit] + L.sort(key=lambda item:item[1].index) + return [f for (f,i) in L] + + @classmethod + def _exitfunc(cls): + # At shutdown invoke finalizers for which atexit is true. + # This is called once all other non-daemonic threads have been + # joined. + reenable_gc = False + try: + if cls._registry: + import gc + if gc.isenabled(): + reenable_gc = True + gc.disable() + pending = None + while True: + if pending is None or finalize._dirty: + pending = cls._select_for_exit() + finalize._dirty = False + if not pending: + break + f = pending.pop() + try: + # gc is disabled, so (assuming no daemonic + # threads) the following is the only line in + # this function which might trigger creation + # of a new finalizer + f() + except Exception: + sys.excepthook(*sys.exc_info()) + assert f not in cls._registry + finally: + # prevent any more finalizers from executing during shutdown + finalize._shutdown = True + if reenable_gc: + gc.enable() From d71f89e2a26720021f7509f8c1eee87645f48529 Mon Sep 17 00:00:00 2001 From: Dusan Klinec Date: Wed, 28 Nov 2018 22:22:11 +0100 Subject: [PATCH 0357/1007] device/trezor: device/trezor: correct device initialization, status check - checks if the device is in the correct usable state - implements check for the v2.0.9 firmware which does not support payment IDs - simple transacttion check, payment id fmt consistency - minor fixes, refactoring, webusb session counting fix --- cmake/CheckTrezor.cmake | 2 +- src/device_trezor/device_trezor.cpp | 77 +++++++++++++++++++++--- src/device_trezor/device_trezor.hpp | 5 +- src/device_trezor/device_trezor_base.cpp | 58 ++++++++++++++++-- src/device_trezor/device_trezor_base.hpp | 19 +++++- src/device_trezor/trezor/transport.cpp | 2 +- 6 files changed, 140 insertions(+), 23 deletions(-) diff --git a/cmake/CheckTrezor.cmake b/cmake/CheckTrezor.cmake index ea21237fd..bcd3cfc2c 100644 --- a/cmake/CheckTrezor.cmake +++ b/cmake/CheckTrezor.cmake @@ -56,7 +56,7 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON) endif() if(USE_DEVICE_TREZOR_UDP_RELEASE) - add_definitions(-DWITH_DEVICE_TREZOR_UDP_RELEASE=1) + add_definitions(-DUSE_DEVICE_TREZOR_UDP_RELEASE=1) endif() if (Protobuf_INCLUDE_DIR) diff --git a/src/device_trezor/device_trezor.cpp b/src/device_trezor/device_trezor.cpp index 5096fcea8..8868fb995 100644 --- a/src/device_trezor/device_trezor.cpp +++ b/src/device_trezor/device_trezor.cpp @@ -121,7 +121,8 @@ namespace trezor { const boost::optional & network_type){ AUTO_LOCK_CMD(); require_connected(); - test_ping(); + device_state_reset_unsafe(); + require_initialized(); auto req = std::make_shared(); this->set_msg_addr(req.get(), path, network_type); @@ -136,7 +137,8 @@ namespace trezor { const boost::optional & network_type){ AUTO_LOCK_CMD(); require_connected(); - test_ping(); + device_state_reset_unsafe(); + require_initialized(); auto req = std::make_shared(); this->set_msg_addr(req.get(), path, network_type); @@ -152,7 +154,8 @@ namespace trezor { { AUTO_LOCK_CMD(); require_connected(); - test_ping(); + device_state_reset_unsafe(); + require_initialized(); std::shared_ptr req; @@ -238,12 +241,11 @@ namespace trezor { cpend.construction_data = cdata.tx_data; // Transaction check - cryptonote::blobdata tx_blob; - cryptonote::transaction tx_deserialized; - bool r = cryptonote::t_serializable_object_to_blob(cpend.tx, tx_blob); - CHECK_AND_ASSERT_THROW_MES(r, "Transaction serialization failed"); - r = cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx_deserialized); - CHECK_AND_ASSERT_THROW_MES(r, "Transaction deserialization failed"); + try { + transaction_check(cdata, aux_data); + } catch(const std::exception &e){ + throw exc::ProtocolException(std::string("Transaction verification failed: ") + e.what()); + } std::string key_images; bool all_are_txin_to_key = std::all_of(cdata.tx.vin.begin(), cdata.tx.vin.end(), [&](const cryptonote::txin_v& s_e) -> bool @@ -283,7 +285,8 @@ namespace trezor { { AUTO_LOCK_CMD(); require_connected(); - test_ping(); + device_state_reset_unsafe(); + require_initialized(); CHECK_AND_ASSERT_THROW_MES(idx < unsigned_tx.txes.size(), "Invalid transaction index"); signer = std::make_shared(wallet, &unsigned_tx, idx, &aux_data); @@ -294,6 +297,7 @@ namespace trezor { // Step: Init auto init_msg = signer->step_init(); this->set_msg_addr(init_msg.get()); + transaction_pre_check(init_msg); auto response = this->client_exchange(init_msg); signer->step_init_ack(response); @@ -351,6 +355,59 @@ namespace trezor { signer->step_final_ack(ack_final); } + void device_trezor::transaction_pre_check(std::shared_ptr init_msg) + { + CHECK_AND_ASSERT_THROW_MES(init_msg, "TransactionInitRequest is empty"); + CHECK_AND_ASSERT_THROW_MES(init_msg->has_tsx_data(), "TransactionInitRequest has no transaction data"); + CHECK_AND_ASSERT_THROW_MES(m_features, "Device state not initialized"); // make sure the caller did not reset features + const bool nonce_required = init_msg->tsx_data().has_payment_id() && init_msg->tsx_data().payment_id().size() > 0; + + if (nonce_required){ + // Versions 2.0.9 and lower do not support payment ID + CHECK_AND_ASSERT_THROW_MES(m_features->has_major_version() && m_features->has_minor_version() && m_features->has_patch_version(), "Invalid Trezor firmware version information"); + const uint32_t vma = m_features->major_version(); + const uint32_t vmi = m_features->minor_version(); + const uint32_t vpa = m_features->patch_version(); + if (vma < 2 || (vma == 2 && vmi == 0 && vpa <= 9)) { + throw exc::TrezorException("Trezor firmware 2.0.9 and lower does not support transactions with short payment IDs or integrated addresses. Please update."); + } + } + } + + void device_trezor::transaction_check(const protocol::tx::TData & tdata, const hw::tx_aux_data & aux_data) + { + // Simple serialization check + cryptonote::blobdata tx_blob; + cryptonote::transaction tx_deserialized; + bool r = cryptonote::t_serializable_object_to_blob(tdata.tx, tx_blob); + CHECK_AND_ASSERT_THROW_MES(r, "Transaction serialization failed"); + r = cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx_deserialized); + CHECK_AND_ASSERT_THROW_MES(r, "Transaction deserialization failed"); + + // Extras check + std::vector tx_extra_fields; + cryptonote::tx_extra_nonce nonce; + + r = cryptonote::parse_tx_extra(tdata.tx.extra, tx_extra_fields); + CHECK_AND_ASSERT_THROW_MES(r, "tx.extra parsing failed"); + + const bool nonce_required = tdata.tsx_data.has_payment_id() && tdata.tsx_data.payment_id().size() > 0; + const bool has_nonce = cryptonote::find_tx_extra_field_by_type(tx_extra_fields, nonce); + CHECK_AND_ASSERT_THROW_MES(has_nonce == nonce_required, "Transaction nonce presence inconsistent"); + + if (nonce_required){ + const std::string & payment_id = tdata.tsx_data.payment_id(); + if (payment_id.size() == 32){ + crypto::hash payment_id_long{}; + CHECK_AND_ASSERT_THROW_MES(cryptonote::get_payment_id_from_tx_extra_nonce(nonce.nonce, payment_id_long), "Long payment ID not present"); + + } else if (payment_id.size() == 8){ + crypto::hash8 payment_id_short{}; + CHECK_AND_ASSERT_THROW_MES(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(nonce.nonce, payment_id_short), "Short payment ID not present"); + } + } + } + #else //WITH_DEVICE_TREZOR void register_all(std::map> ®istry) { diff --git a/src/device_trezor/device_trezor.hpp b/src/device_trezor/device_trezor.hpp index a2134574c..1f08be887 100644 --- a/src/device_trezor/device_trezor.hpp +++ b/src/device_trezor/device_trezor.hpp @@ -57,9 +57,8 @@ namespace trezor { */ class device_trezor : public hw::trezor::device_trezor_base, public hw::device_cold { protected: - // To speed up blockchain parsing the view key maybe handle here. - crypto::secret_key viewkey; - bool has_view_key; + void transaction_pre_check(std::shared_ptr init_msg); + void transaction_check(const protocol::tx::TData & tdata, const hw::tx_aux_data & aux_data); public: device_trezor(); diff --git a/src/device_trezor/device_trezor_base.cpp b/src/device_trezor/device_trezor_base.cpp index fddc6082c..5071932ee 100644 --- a/src/device_trezor/device_trezor_base.cpp +++ b/src/device_trezor/device_trezor_base.cpp @@ -65,7 +65,7 @@ namespace trezor { } bool device_trezor_base::set_name(const std::string & name) { - this->full_name = name; + this->m_full_name = name; this->name = ""; auto delim = name.find(':'); @@ -77,10 +77,10 @@ namespace trezor { } const std::string device_trezor_base::get_name() const { - if (this->full_name.empty()) { + if (this->m_full_name.empty()) { return std::string("name).append(">"); } - return this->full_name; + return this->m_full_name; } bool device_trezor_base::init() { @@ -139,6 +139,9 @@ namespace trezor { } bool device_trezor_base::disconnect() { + m_device_state.clear(); + m_features.reset(); + if (m_transport){ try { m_transport->close(); @@ -193,6 +196,25 @@ namespace trezor { } } + void device_trezor_base::require_initialized(){ + if (!m_features){ + throw exc::TrezorException("Device state not initialized"); + } + + if (m_features->has_bootloader_mode() && m_features->bootloader_mode()){ + throw exc::TrezorException("Device is in the bootloader mode"); + } + + if (m_features->has_firmware_present() && !m_features->firmware_present()){ + throw exc::TrezorException("Device has no firmware loaded"); + } + + // Hard requirement on initialized field, has to be there. + if (!m_features->has_initialized() || !m_features->initialized()){ + throw exc::TrezorException("Device is not initialized"); + } + } + void device_trezor_base::call_ping_unsafe(){ auto pingMsg = std::make_shared(); pingMsg->set_message("PING"); @@ -217,7 +239,7 @@ namespace trezor { void device_trezor_base::write_raw(const google::protobuf::Message * msg){ require_connected(); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); - this->getTransport()->write(*msg); + this->get_transport()->write(*msg); } GenericMessage device_trezor_base::read_raw(){ @@ -225,7 +247,7 @@ namespace trezor { std::shared_ptr msg_resp; hw::trezor::messages::MessageType msg_resp_type; - this->getTransport()->read(msg_resp, &msg_resp_type); + this->get_transport()->read(msg_resp, &msg_resp_type); return GenericMessage(msg_resp_type, msg_resp); } @@ -314,6 +336,25 @@ namespace trezor { return false; } + void device_trezor_base::device_state_reset_unsafe() + { + require_connected(); + auto initMsg = std::make_shared(); + + if(!m_device_state.empty()) { + initMsg->set_allocated_state(&m_device_state); + } + + m_features = this->client_exchange(initMsg); + initMsg->release_state(); + } + + void device_trezor_base::device_state_reset() + { + AUTO_LOCK_CMD(); + device_state_reset_unsafe(); + } + void device_trezor_base::on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg) { CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); @@ -361,7 +402,13 @@ namespace trezor { // TODO: remove passphrase from memory m.set_passphrase(passphrase.data(), passphrase.size()); } + + if (!m_device_state.empty()){ + m.set_allocated_state(&m_device_state); + } + resp = call_raw(&m); + m.release_state(); } void device_trezor_base::on_passphrase_state_request(GenericMessage & resp, const messages::common::PassphraseStateRequest * msg) @@ -369,6 +416,7 @@ namespace trezor { MDEBUG("on_passhprase_state_request"); CHECK_AND_ASSERT_THROW_MES(msg, "Empty message"); + m_device_state = msg->state(); messages::common::PassphraseStateAck m; resp = call_raw(&m); } diff --git a/src/device_trezor/device_trezor_base.hpp b/src/device_trezor/device_trezor_base.hpp index 4d205ad7a..3c35e8aca 100644 --- a/src/device_trezor/device_trezor_base.hpp +++ b/src/device_trezor/device_trezor_base.hpp @@ -70,8 +70,10 @@ namespace trezor { std::shared_ptr m_transport; i_device_callback * m_callback; - std::string full_name; + std::string m_full_name; std::vector m_wallet_deriv_path; + std::string m_device_state; // returned after passphrase entry, session + std::shared_ptr m_features; // features from the last device reset cryptonote::network_type network_type; @@ -80,8 +82,10 @@ namespace trezor { // void require_connected(); + void require_initialized(); void call_ping_unsafe(); void test_ping(); + void device_state_reset_unsafe(); void ensure_derivation_path() noexcept; // Communication methods @@ -130,7 +134,7 @@ namespace trezor { // Scoped session closer BOOST_SCOPE_EXIT_ALL(&, this) { if (open_session){ - this->getTransport()->close(); + this->get_transport()->close(); } }; @@ -209,7 +213,7 @@ namespace trezor { // Default derivation path for Monero static const uint32_t DEFAULT_BIP44_PATH[2]; - std::shared_ptr getTransport(){ + std::shared_ptr get_transport(){ return m_transport; } @@ -221,6 +225,10 @@ namespace trezor { return m_callback; } + std::shared_ptr & get_features() { + return m_features; + } + void set_derivation_path(const std::string &deriv_path) override; /* ======================================================================= */ @@ -250,6 +258,11 @@ namespace trezor { */ bool ping(); + /** + * Performs Initialize call to the Trezor, resets to known state. + */ + void device_state_reset(); + // Protocol callbacks void on_button_request(GenericMessage & resp, const messages::common::ButtonRequest * msg); void on_pin_request(GenericMessage & resp, const messages::common::PinMatrixRequest * msg); diff --git a/src/device_trezor/trezor/transport.cpp b/src/device_trezor/trezor/transport.cpp index 814537eb6..cd66e59e8 100644 --- a/src/device_trezor/trezor/transport.cpp +++ b/src/device_trezor/trezor/transport.cpp @@ -840,7 +840,7 @@ namespace trezor{ throw exc::DeviceAcquireException("Unable to claim libusb device"); } - m_conn_count += 1; + m_conn_count = 1; m_proto->session_begin(*this); #undef TREZOR_DESTROY_SESSION From 9e64a71e7d1fd70cdf94a3b78782ad06828362b3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 00:12:29 +0000 Subject: [PATCH 0358/1007] blockchain: call deinit in dtor This ensures the io service that runs in another thread cannot access data after it's deleted --- src/cryptonote_core/blockchain.cpp | 17 ++++++++++------- src/cryptonote_core/blockchain.h | 5 +++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 80e0a983e..97b8f0765 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -171,6 +171,11 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) : LOG_PRINT_L3("Blockchain::" << __func__); } //------------------------------------------------------------------ +Blockchain::~Blockchain() +{ + deinit(); +} +//------------------------------------------------------------------ bool Blockchain::have_tx(const crypto::hash &id) const { LOG_PRINT_L3("Blockchain::" << __func__); @@ -550,15 +555,13 @@ bool Blockchain::deinit() // as this should be called if handling a SIGSEGV, need to check // if m_db is a NULL pointer (and thus may have caused the illegal // memory operation), otherwise we may cause a loop. - if (m_db == NULL) - { - throw DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!"); - } - try { - m_db->close(); - MTRACE("Local blockchain read/write activity stopped successfully"); + if (m_db) + { + m_db->close(); + MTRACE("Local blockchain read/write activity stopped successfully"); + } } catch (const std::exception& e) { diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index dfe833fb4..835e5addc 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -120,6 +120,11 @@ namespace cryptonote */ Blockchain(tx_memory_pool& tx_pool); + /** + * @brief Blockchain destructor + */ + ~Blockchain(); + /** * @brief Initialize the Blockchain state * From 1cfd6f1060ca1a8f731638826c3a436a10ccb37e Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 00:30:39 +0000 Subject: [PATCH 0359/1007] unit_tests: strengthen notify test against OS scheduling --- tests/unit_tests/notify.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp index edc4eabdf..a5c570bf4 100644 --- a/tests/unit_tests/notify.cpp +++ b/tests/unit_tests/notify.cpp @@ -69,11 +69,22 @@ TEST(notify, works) tools::Notify notify(spec.c_str()); notify.notify("1111111111111111111111111111111111111111111111111111111111111111"); - epee::misc_utils::sleep_no_w(100); - - std::string s; - ASSERT_TRUE(epee::file_io_utils::load_file_to_string(name_template, s)); - ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111"); + bool ok = false; + for (int i = 0; i < 10; ++i) + { + epee::misc_utils::sleep_no_w(100); + std::string s; + if (epee::file_io_utils::load_file_to_string(name_template, s)) + { + if (s == "1111111111111111111111111111111111111111111111111111111111111111") + { + ok = true; + break; + } + std::cout << "got: [" << s << "]" << std::endl; + } + } boost::filesystem::remove(name_template); + ASSERT_TRUE(ok); } From 1505dd38c96172a7a6846b33a052b82a4e9f9a85 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 14:07:45 +0000 Subject: [PATCH 0360/1007] util: set MONERO_DEFAULT_LOG_CATEGORY Otherwise it'd end up with whatever was included last --- src/common/util.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/util.cpp b/src/common/util.cpp index 58b0d8210..ab84b3185 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -81,6 +81,9 @@ using namespace epee; #include #include +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "util" + namespace tools { std::function signal_handler::m_handler; From 6644b9b7b72919f43d05585a4c2590cec8a7beda Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 19:20:19 +0000 Subject: [PATCH 0361/1007] blockchain_db: remove a couple unused functions --- src/blockchain_db/berkeleydb/db_bdb.cpp | 23 ----------------------- src/blockchain_db/berkeleydb/db_bdb.h | 18 ------------------ src/blockchain_db/lmdb/db_lmdb.cpp | 23 ----------------------- src/blockchain_db/lmdb/db_lmdb.h | 18 ------------------ 4 files changed, 82 deletions(-) diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp index 6c79120e8..b27a00a69 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.cpp +++ b/src/blockchain_db/berkeleydb/db_bdb.cpp @@ -714,29 +714,6 @@ bool BlockchainBDB::for_all_outputs(std::function ba(ss); - tx_out o; - - if (!(::serialization::serialize(ba, o))) - throw1(DB_ERROR("Error deserializing tx output blob")); - - return o; -} - uint64_t BlockchainBDB::get_output_global_index(const uint64_t& amount, const uint64_t& index) { LOG_PRINT_L3("BlockchainBDB::" << __func__); diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h index 76d0a0517..e80adae9e 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.h +++ b/src/blockchain_db/berkeleydb/db_bdb.h @@ -391,24 +391,6 @@ class BlockchainBDB : public BlockchainDB virtual void check_hard_fork_info(); virtual void drop_hard_fork_info(); - /** - * @brief convert a tx output to a blob for storage - * - * @param output the output to convert - * - * @return the resultant blob - */ - blobdata output_to_blob(const tx_out& output) const; - - /** - * @brief convert a tx output blob to a tx output - * - * @param blob the blob to convert - * - * @return the resultant tx output - */ - tx_out output_from_blob(const blobdata& blob) const; - /** * @brief get the global index of the index-th output of the given amount * diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 5af5d1903..125eff88f 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1112,29 +1112,6 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image) } } -blobdata BlockchainLMDB::output_to_blob(const tx_out& output) const -{ - LOG_PRINT_L3("BlockchainLMDB::" << __func__); - blobdata b; - if (!t_serializable_object_to_blob(output, b)) - throw1(DB_ERROR("Error serializing output to blob")); - return b; -} - -tx_out BlockchainLMDB::output_from_blob(const blobdata& blob) const -{ - LOG_PRINT_L3("BlockchainLMDB::" << __func__); - std::stringstream ss; - ss << blob; - binary_archive ba(ss); - tx_out o; - - if (!(::serialization::serialize(ba, o))) - throw1(DB_ERROR("Error deserializing tx output blob")); - - return o; -} - void BlockchainLMDB::check_open() const { // LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 26159ab4d..12261dca3 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -357,24 +357,6 @@ class BlockchainLMDB : public BlockchainDB virtual void check_hard_fork_info(); virtual void drop_hard_fork_info(); - /** - * @brief convert a tx output to a blob for storage - * - * @param output the output to convert - * - * @return the resultant blob - */ - blobdata output_to_blob(const tx_out& output) const; - - /** - * @brief convert a tx output blob to a tx output - * - * @param blob the blob to convert - * - * @return the resultant tx output - */ - tx_out output_from_blob(const blobdata& blob) const; - void check_open() const; virtual bool is_read_only() const; From ce594f5af78e4722122735d67a019325f1c495cb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 19:21:43 +0000 Subject: [PATCH 0362/1007] blockchain_db: allocate known size vector only once --- src/blockchain_db/blockchain_db.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index be0ffeac3..c25798c1e 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -170,7 +170,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti uint64_t tx_id = add_transaction_data(blk_hash, tx, tx_hash, tx_prunable_hash); - std::vector amount_output_indices; + std::vector amount_output_indices(tx.vout.size()); // iterate tx.vout using indices instead of C++11 foreach syntax because // we need the index @@ -183,13 +183,13 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transacti cryptonote::tx_out vout = tx.vout[i]; rct::key commitment = rct::zeroCommit(vout.amount); vout.amount = 0; - amount_output_indices.push_back(add_output(tx_hash, vout, i, tx.unlock_time, - &commitment)); + amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time, + &commitment); } else { - amount_output_indices.push_back(add_output(tx_hash, tx.vout[i], i, tx.unlock_time, - tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL)); + amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time, + tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL); } } add_tx_amount_output_indices(tx_id, amount_output_indices); From 833269834d7a93d475df3091c362873501d1cb88 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 19:26:49 +0000 Subject: [PATCH 0363/1007] db_lmdb: inline check_open, it's trivial and called everywhere --- src/blockchain_db/lmdb/db_lmdb.cpp | 13 ++++++------- src/blockchain_db/lmdb/db_lmdb.h | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 125eff88f..30d5fae71 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -456,6 +456,12 @@ inline int lmdb_txn_renew(MDB_txn *txn) return res; } +inline void BlockchainLMDB::check_open() const +{ + if (!m_open) + throw0(DB_ERROR("DB operation attempted on a not-open DB instance")); +} + void BlockchainLMDB::do_resize(uint64_t increase_size) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -1112,13 +1118,6 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image) } } -void BlockchainLMDB::check_open() const -{ -// LOG_PRINT_L3("BlockchainLMDB::" << __func__); - if (!m_open) - throw0(DB_ERROR("DB operation attempted on a not-open DB instance")); -} - BlockchainLMDB::~BlockchainLMDB() { LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 12261dca3..9dad5fd01 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -357,7 +357,7 @@ class BlockchainLMDB : public BlockchainDB virtual void check_hard_fork_info(); virtual void drop_hard_fork_info(); - void check_open() const; + inline void check_open() const; virtual bool is_read_only() const; From 5511563e92ca9ef62008eab587ccb15aa6de7b11 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 19:27:39 +0000 Subject: [PATCH 0364/1007] db_lmdb: avoid pointless division --- src/blockchain_db/lmdb/db_lmdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 30d5fae71..5a0799367 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -3106,7 +3106,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, size_t block_weight, const check_open(); uint64_t m_height = height(); - if (m_height % 1000 == 0) + if (m_height % 1024 == 0) { // for batch mode, DB resize check is done at start of batch transaction if (! m_batch_active && need_resize()) From d1efe3d91c4b1bbb8178a67b445733f5560df1bb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 20:34:10 +0000 Subject: [PATCH 0365/1007] cryptonote: set tx hash on newly parsed txes when known --- src/cryptonote_basic/cryptonote_basic.h | 2 ++ src/cryptonote_basic/cryptonote_format_utils.cpp | 1 + src/cryptonote_core/tx_pool.cpp | 16 +++++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index b0eabb0aa..47674c9b3 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -203,6 +203,8 @@ namespace cryptonote void set_hash_valid(bool v) const { hash_valid.store(v,std::memory_order_release); } bool is_blob_size_valid() const { return blob_size_valid.load(std::memory_order_acquire); } void set_blob_size_valid(bool v) const { blob_size_valid.store(v,std::memory_order_release); } + void set_hash(const crypto::hash &h) { hash = h; set_hash_valid(true); } + void set_blob_size(size_t sz) { blob_size = sz; set_blob_size_valid(true); } BEGIN_SERIALIZE_OBJECT() if (!typename Archive::is_saving()) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index d41bc1087..ea420e046 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -184,6 +184,7 @@ namespace cryptonote CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); tx.invalidate_hashes(); + tx.set_blob_size(tx_blob.size()); return true; } //--------------------------------------------------------------- diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index e2900916b..120edd87b 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -480,6 +480,10 @@ namespace cryptonote MERROR("Failed to parse tx from txpool"); return false; } + else + { + tx.set_hash(id); + } tx_weight = meta.weight; fee = meta.fee; relayed = meta.relayed; @@ -782,6 +786,7 @@ namespace cryptonote // continue return true; } + tx.set_hash(txid); txi.tx_json = obj_to_json_str(tx); txi.blob_size = bd->size(); txi.weight = meta.weight; @@ -847,14 +852,13 @@ namespace cryptonote m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ cryptonote::rpc::tx_in_pool txi; txi.tx_hash = txid; - transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) + if (!parse_and_validate_tx_from_blob(*bd, txi.tx)) { MERROR("Failed to parse tx from txpool"); // continue return true; } - txi.tx = tx; + txi.tx.set_hash(txid); txi.blob_size = bd->size(); txi.weight = meta.weight; txi.fee = meta.fee; @@ -990,21 +994,23 @@ namespace cryptonote { struct transction_parser { - transction_parser(const cryptonote::blobdata &txblob, transaction &tx): txblob(txblob), tx(tx), parsed(false) {} + transction_parser(const cryptonote::blobdata &txblob, const crypto::hash &txid, transaction &tx): txblob(txblob), txid(txid), tx(tx), parsed(false) {} cryptonote::transaction &operator()() { if (!parsed) { if (!parse_and_validate_tx_from_blob(txblob, tx)) throw std::runtime_error("failed to parse transaction blob"); + tx.set_hash(txid); parsed = true; } return tx; } const cryptonote::blobdata &txblob; + const crypto::hash &txid; transaction &tx; bool parsed; - } lazy_tx(txblob, tx); + } lazy_tx(txblob, txid, tx); //not the best implementation at this time, sorry :( //check is ring_signature already checked ? From 9cc68a2f74f5722c0c0e9854825bcc24f17f6187 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 20:34:35 +0000 Subject: [PATCH 0366/1007] tx_pool: add a few std::move where it can make a difference --- src/cryptonote_core/tx_pool.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 120edd87b..16a86b19f 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -663,7 +663,8 @@ namespace cryptonote // continue return true; } - txs.push_back(tx); + tx.set_hash(txid); + txs.push_back(std::move(tx)); return true; }, true, include_unrelayed_txes); } @@ -803,7 +804,7 @@ namespace cryptonote txi.last_relayed_time = include_sensitive_data ? meta.last_relayed_time : 0; txi.do_not_relay = meta.do_not_relay; txi.double_spend_seen = meta.double_spend_seen; - tx_infos.push_back(txi); + tx_infos.push_back(std::move(txi)); return true; }, true, include_sensitive_data); @@ -885,7 +886,7 @@ namespace cryptonote } const crypto::key_image& k_image = kee.first; - key_image_infos[k_image] = tx_hashes; + key_image_infos[k_image] = std::move(tx_hashes); } return true; } From db5737413efda040a2095e12dea9256811682499 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 14:52:43 +0000 Subject: [PATCH 0367/1007] util: use fcntl instead of flock, for compatibility in particular with NFS --- src/common/util.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/common/util.cpp b/src/common/util.cpp index ab84b3185..99da737c4 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -84,6 +84,29 @@ using namespace epee; #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "util" +namespace +{ + +#ifndef _WIN32 +static int flock_exnb(int fd) +{ + struct flock fl; + int ret; + + memset(&fl, 0, sizeof(fl)); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + ret = fcntl(fd, F_SETLK, &fl); + if (ret < 0) + MERROR("Error locking fd " << fd << ": " << errno << " (" << strerror(errno) << ")"); + return ret; +} +#endif + +} + namespace tools { std::function signal_handler::m_handler; @@ -184,7 +207,7 @@ namespace tools struct stat wstats = {}; if (fstat(fdw, std::addressof(wstats)) == 0 && rstats.st_dev == wstats.st_dev && rstats.st_ino == wstats.st_ino && - flock(fdw, (LOCK_EX | LOCK_NB)) == 0 && ftruncate(fdw, 0) == 0) + flock_exnb(fdw) == 0 && ftruncate(fdw, 0) == 0) { std::FILE* file = fdopen(fdw, "w"); if (file) return {file, std::move(name)}; @@ -237,10 +260,10 @@ namespace tools MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); } #else - m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666); + m_fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0666); if (m_fd != -1) { - if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) + if (flock_exnb(m_fd) == -1) { MERROR("Failed to lock " << filename << ": " << std::strerror(errno)); close(m_fd); From 85807dfb25bad6f4606c9b81a98b1abb95da8335 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 7 Dec 2018 12:32:32 +0000 Subject: [PATCH 0368/1007] add a once_a_time_milliseconds class --- contrib/epee/include/math_helper.h | 39 +++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h index ef839f609..e22e8ee6e 100644 --- a/contrib/epee/include/math_helper.h +++ b/contrib/epee/include/math_helper.h @@ -230,35 +230,56 @@ namespace math_helper } } - template - class once_a_time_seconds + template + class once_a_time { + uint64_t get_time() const + { +#ifdef _WIN32 + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +#endif + } + public: - once_a_time_seconds():m_interval(default_interval) + once_a_time():m_interval(default_interval * scale) { m_last_worked_time = 0; if(!start_immediate) - time(&m_last_worked_time); + m_last_worked_time = get_time(); } template bool do_call(functor_t functr) { - time_t current_time = 0; - time(¤t_time); + uint64_t current_time = get_time(); if(current_time - m_last_worked_time > m_interval) { bool res = functr(); - time(&m_last_worked_time); + m_last_worked_time = get_time(); return res; } return true; } private: - time_t m_last_worked_time; - time_t m_interval; + uint64_t m_last_worked_time; + uint64_t m_interval; }; + + template + class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {}; + template + class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {}; } } From 1d892ec88122be46fe7592cfd1cd60e5b3adfa68 Mon Sep 17 00:00:00 2001 From: selsta Date: Fri, 7 Dec 2018 13:37:23 +0100 Subject: [PATCH 0369/1007] simplewallet: donate command validate amount --- src/simplewallet/simplewallet.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index bcf6acbd5..7e974bc50 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -5970,8 +5970,18 @@ bool simple_wallet::donate(const std::vector &args_) local_args.pop_back(); } // get amount and pop - amount_str = local_args.back(); - local_args.pop_back(); + uint64_t amount; + bool ok = cryptonote::parse_amount(amount, local_args.back()); + if (ok && amount != 0) + { + amount_str = local_args.back(); + local_args.pop_back(); + } + else + { + fail_msg_writer() << tr("amount is wrong: ") << local_args.back() << ", " << tr("expected number from 0 to ") << print_money(std::numeric_limits::max()); + return true; + } // push back address, amount, payment id local_args.push_back(MONERO_DONATION_ADDR); local_args.push_back(amount_str); From 5464725a29c7ea8bc917d447bf04ba481f791fe9 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 7 Dec 2018 12:32:50 +0000 Subject: [PATCH 0370/1007] protocol: change standby mode to not wait sleeping --- .../cryptonote_protocol_handler.h | 2 ++ .../cryptonote_protocol_handler.inl | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index d7b74c06d..618b635cc 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -131,6 +131,7 @@ namespace cryptonote bool should_download_next_span(cryptonote_connection_context& context) const; void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans); bool kick_idle_peers(); + bool check_standby_peers(); int try_add_next_blocks(cryptonote_connection_context &context); t_core& m_core; @@ -143,6 +144,7 @@ namespace cryptonote boost::mutex m_sync_lock; block_queue m_block_queue; epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker; + epee::math_helper::once_a_time_milliseconds<100> m_standby_checker; boost::mutex m_buffer_mutex; double get_avg_block_size(); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 6081ddd89..67baa9429 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1210,6 +1210,7 @@ skip: bool t_cryptonote_protocol_handler::on_idle() { m_idle_peer_kicker.do_call(boost::bind(&t_cryptonote_protocol_handler::kick_idle_peers, this)); + m_standby_checker.do_call(boost::bind(&t_cryptonote_protocol_handler::check_standby_peers, this)); return m_core.on_idle(); } //------------------------------------------------------------------------------------------------------------------------ @@ -1245,6 +1246,22 @@ skip: } //------------------------------------------------------------------------------------------------------------------------ template + bool t_cryptonote_protocol_handler::check_standby_peers() + { + m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool + { + if (context.m_state == cryptonote_connection_context::state_standby) + { + LOG_PRINT_CCONTEXT_L2("requesting callback"); + ++context.m_callback_request_count; + m_p2p->request_callback(context); + } + return true; + }); + return true; + } + //------------------------------------------------------------------------------------------------------------------------ + template int t_cryptonote_protocol_handler::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, cryptonote_connection_context& context) { MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_CHAIN (" << arg.block_ids.size() << " blocks"); @@ -1338,14 +1355,13 @@ skip: bool start_from_current_chain = false; if (!force_next_span) { - bool first = true; - while (1) + do { size_t nblocks = m_block_queue.get_num_filled_spans(); size_t size = m_block_queue.get_data_size(); if (nblocks < BLOCK_QUEUE_NBLOCKS_THRESHOLD || size < BLOCK_QUEUE_SIZE_THRESHOLD) { - if (!first) + if (context.m_state != cryptonote_connection_context::state_standby) { LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", resuming"); } @@ -1368,10 +1384,9 @@ skip: break; } - if (first) + if (context.m_state != cryptonote_connection_context::state_standby) { LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", pausing"); - first = false; context.m_state = cryptonote_connection_context::state_standby; } @@ -1385,13 +1400,8 @@ skip: return true; } - for (size_t n = 0; n < 50; ++n) - { - if (m_stopping) - return true; - boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); - } - } + return true; + } while(0); context.m_state = cryptonote_connection_context::state_synchronizing; } From b21a60efd98f32fe27d5aa16fe086c4bc9d403ed Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 7 Dec 2018 13:13:24 +0000 Subject: [PATCH 0371/1007] mlocker: set default log category --- contrib/epee/src/mlocker.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/epee/src/mlocker.cpp b/contrib/epee/src/mlocker.cpp index 8e24e8438..12dff7918 100644 --- a/contrib/epee/src/mlocker.cpp +++ b/contrib/epee/src/mlocker.cpp @@ -40,6 +40,9 @@ #include +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "mlocker" + // did an mlock operation previously fail? we only // want to log an error once and be done with it static std::atomic previously_failed{ false }; From 570dd3690e501b5c8a3ee8169456539d231b2536 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 5 Dec 2018 22:25:27 +0000 Subject: [PATCH 0372/1007] p2p: use vector instead of list for peer lists --- src/p2p/net_node.h | 6 +++--- src/p2p/net_node.inl | 10 +++++----- src/p2p/net_peerlist.h | 15 +++++++++------ src/p2p/p2p_protocol_defs.h | 20 ++++++++++---------- src/rpc/core_rpc_server.cpp | 7 ++++--- tests/unit_tests/test_peerlist.cpp | 6 +++--- 6 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 8930418bd..4db0a6cb7 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -197,12 +197,12 @@ namespace nodetool const boost::program_options::variables_map& vm ); bool idle_worker(); - bool handle_remote_peerlist(const std::list& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context); + bool handle_remote_peerlist(const std::vector& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context); bool get_local_node_data(basic_node_data& node_data); //bool get_local_handshake_data(handshake_data& hshd); - bool merge_peerlist_with_local(const std::list& bs); - bool fix_time_delta(std::list& local_peerlist, time_t local_time, int64_t& delta); + bool merge_peerlist_with_local(const std::vector& bs); + bool fix_time_delta(std::vector& local_peerlist, time_t local_time, int64_t& delta); bool connections_maker(); bool peer_sync_idle_maker(); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index fbf265fc9..5b845fe15 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1374,7 +1374,7 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::fix_time_delta(std::list& local_peerlist, time_t local_time, int64_t& delta) + bool node_server::fix_time_delta(std::vector& local_peerlist, time_t local_time, int64_t& delta) { //fix time delta time_t now = 0; @@ -1394,10 +1394,10 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::handle_remote_peerlist(const std::list& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context) + bool node_server::handle_remote_peerlist(const std::vector& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context) { int64_t delta = 0; - std::list peerlist_ = peerlist; + std::vector peerlist_ = peerlist; if(!fix_time_delta(peerlist_, local_time, delta)) return false; LOG_DEBUG_CC(context, "REMOTE PEERLIST: TIME_DELTA: " << delta << ", remote peerlist size=" << peerlist_.size()); @@ -1779,8 +1779,8 @@ namespace nodetool template bool node_server::log_peerlist() { - std::list pl_white; - std::list pl_gray; + std::vector pl_white; + std::vector pl_gray; m_peerlist.get_peerlist_full(pl_gray, pl_white); MINFO(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) ); return true; diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 1d609a37e..e7aad5abe 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -68,9 +68,9 @@ namespace nodetool bool deinit(); size_t get_white_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_white.size();} size_t get_gray_peers_count(){CRITICAL_REGION_LOCAL(m_peerlist_lock); return m_peers_gray.size();} - bool merge_peerlist(const std::list& outer_bs); - bool get_peerlist_head(std::list& bs_head, uint32_t depth = P2P_DEFAULT_PEERS_IN_HANDSHAKE); - bool get_peerlist_full(std::list& pl_gray, std::list& pl_white); + bool merge_peerlist(const std::vector& outer_bs); + bool get_peerlist_head(std::vector& bs_head, uint32_t depth = P2P_DEFAULT_PEERS_IN_HANDSHAKE); + bool get_peerlist_full(std::vector& pl_gray, std::vector& pl_white); bool get_white_peer_by_index(peerlist_entry& p, size_t i); bool get_gray_peer_by_index(peerlist_entry& p, size_t i); bool append_with_peer_white(const peerlist_entry& pr); @@ -265,7 +265,7 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::merge_peerlist(const std::list& outer_bs) + bool peerlist_manager::merge_peerlist(const std::vector& outer_bs) { CRITICAL_REGION_LOCAL(m_peerlist_lock); for(const peerlist_entry& be: outer_bs) @@ -315,12 +315,13 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::get_peerlist_head(std::list& bs_head, uint32_t depth) + bool peerlist_manager::get_peerlist_head(std::vector& bs_head, uint32_t depth) { CRITICAL_REGION_LOCAL(m_peerlist_lock); peers_indexed::index::type& by_time_index=m_peers_white.get(); uint32_t cnt = 0; + bs_head.reserve(depth); for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index)) { if(!vl.last_seen) @@ -335,16 +336,18 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::get_peerlist_full(std::list& pl_gray, std::list& pl_white) + bool peerlist_manager::get_peerlist_full(std::vector& pl_gray, std::vector& pl_white) { CRITICAL_REGION_LOCAL(m_peerlist_lock); peers_indexed::index::type& by_time_index_gr=m_peers_gray.get(); + pl_gray.resize(pl_gray.size() + by_time_index_gr.size()); for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index_gr)) { pl_gray.push_back(vl); } peers_indexed::index::type& by_time_index_wt=m_peers_white.get(); + pl_white.resize(pl_white.size() + by_time_index_wt.size()); for(const peers_indexed::value_type& vl: boost::adaptors::reverse(by_time_index_wt)) { pl_white.push_back(vl); diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index e793e19b6..bb9d2635c 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -114,7 +114,7 @@ namespace nodetool #pragma pack(pop) inline - std::string print_peerlist_to_string(const std::list& pl) + std::string print_peerlist_to_string(const std::vector& pl) { time_t now_time = 0; time(&now_time); @@ -189,7 +189,7 @@ namespace nodetool { basic_node_data node_data; t_playload_type payload_data; - std::list local_peerlist_new; + std::vector local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(node_data) @@ -198,7 +198,7 @@ namespace nodetool { // saving: save both, so old and new peers can understand it KV_SERIALIZE(local_peerlist_new) - std::list> local_peerlist; + std::vector> local_peerlist; for (const auto &p: this_ref.local_peerlist_new) { if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID) @@ -217,7 +217,7 @@ namespace nodetool // loading: load old list only if there is no new one if (!epee::serialization::selector::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) { - std::list> local_peerlist; + std::vector> local_peerlist; epee::serialization::selector::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); for (const auto &p: local_peerlist) ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); @@ -248,7 +248,7 @@ namespace nodetool { uint64_t local_time; t_playload_type payload_data; - std::list local_peerlist_new; + std::vector local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(local_time) @@ -257,7 +257,7 @@ namespace nodetool { // saving: save both, so old and new peers can understand it KV_SERIALIZE(local_peerlist_new) - std::list> local_peerlist; + std::vector> local_peerlist; for (const auto &p: this_ref.local_peerlist_new) { if (p.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID) @@ -276,7 +276,7 @@ namespace nodetool // loading: load old list only if there is no new one if (!epee::serialization::selector::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) { - std::list> local_peerlist; + std::vector> local_peerlist; epee::serialization::selector::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); for (const auto &p: local_peerlist) ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); @@ -389,9 +389,9 @@ namespace nodetool struct response { - std::list local_peerlist_white; - std::list local_peerlist_gray; - std::list connections_list; + std::vector local_peerlist_white; + std::vector local_peerlist_gray; + std::vector connections_list; peerid_type my_id; uint64_t local_time; BEGIN_KV_SERIALIZE_MAP() diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index cefba39f7..9c0f84450 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -857,11 +857,11 @@ namespace cryptonote bool core_rpc_server::on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request& req, COMMAND_RPC_GET_PEER_LIST::response& res) { PERF_TIMER(on_get_peer_list); - std::list white_list; - std::list gray_list; + std::vector white_list; + std::vector gray_list; m_p2p.get_peerlist_manager().get_peerlist_full(gray_list, white_list); - + res.white_list.reserve(white_list.size()); for (auto & entry : white_list) { if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID) @@ -871,6 +871,7 @@ namespace cryptonote res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen); } + res.gray_list.reserve(gray_list.size()); for (auto & entry : gray_list) { if (entry.adr.get_type_id() == epee::net_utils::ipv4_network_address::ID) diff --git a/tests/unit_tests/test_peerlist.cpp b/tests/unit_tests/test_peerlist.cpp index c6572c6c2..f638c6251 100644 --- a/tests/unit_tests/test_peerlist.cpp +++ b/tests/unit_tests/test_peerlist.cpp @@ -42,7 +42,7 @@ TEST(peer_list, peer_list_general) #define ADD_GRAY_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple; ple.last_seen=last_seen_;ple.adr = addr_; ple.id = id_;plm.append_with_peer_gray(ple);} #define ADD_WHITE_NODE(addr_, id_, last_seen_) { nodetool::peerlist_entry ple;ple.last_seen=last_seen_; ple.adr = addr_; ple.id = id_;plm.append_with_peer_white(ple);} -#define PRINT_HEAD(step) {std::list bs_head; bool r = plm.get_peerlist_head(bs_head, 100);std::cout << "step " << step << ": " << bs_head.size() << std::endl;} +#define PRINT_HEAD(step) {std::vector bs_head; bool r = plm.get_peerlist_head(bs_head, 100);std::cout << "step " << step << ": " << bs_head.size() << std::endl;} ADD_GRAY_NODE(MAKE_IPV4_ADDRESS(123,43,12,1, 8080), 121241, 34345); ADD_GRAY_NODE(MAKE_IPV4_ADDRESS(123,43,12,2, 8080), 121241, 34345); @@ -58,7 +58,7 @@ TEST(peer_list, peer_list_general) size_t gray_list_size = plm.get_gray_peers_count(); ASSERT_EQ(gray_list_size, 1); - std::list bs_head; + std::vector bs_head; bool r = plm.get_peerlist_head(bs_head, 100); std::cout << bs_head.size() << std::endl; ASSERT_TRUE(r); @@ -78,7 +78,7 @@ TEST(peer_list, merge_peer_lists) //ADD_NODE_TO_PL("\2", \3, 0x\1, (1353346618 -(\4*60*60*24+\5*60*60+\6*60+\7 )));\n nodetool::peerlist_manager plm; plm.init(false); - std::list outer_bs; + std::vector outer_bs; #define ADD_NODE_TO_PL(ip_, port_, id_, timestamp_) { nodetool::peerlist_entry ple; epee::string_tools::get_ip_int32_from_string(ple.adr.ip, ip_); ple.last_seen = timestamp_; ple.adr.port = port_; ple.id = id_;outer_bs.push_back(ple);} From 68f045de8ce886ce638289e34db4a2649e2ed23c Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 6 Dec 2018 00:38:24 +0000 Subject: [PATCH 0373/1007] easylogging++: check allowed categories before logging --- contrib/epee/include/misc_log_ex.h | 23 +++++++++++++++-------- external/easylogging++/easylogging++.cc | 19 +++++++++++++++++++ external/easylogging++/easylogging++.h | 2 ++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h index 9100a8db3..1ff9da3a7 100644 --- a/contrib/epee/include/misc_log_ex.h +++ b/contrib/epee/include/misc_log_ex.h @@ -38,14 +38,21 @@ #define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes #define MAX_LOG_FILES 50 -#define MCFATAL(cat,x) CLOG(FATAL,cat) << x -#define MCERROR(cat,x) CLOG(ERROR,cat) << x -#define MCWARNING(cat,x) CLOG(WARNING,cat) << x -#define MCINFO(cat,x) CLOG(INFO,cat) << x -#define MCDEBUG(cat,x) CLOG(DEBUG,cat) << x -#define MCTRACE(cat,x) CLOG(TRACE,cat) << x -#define MCLOG(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::NormalLog, cat) << x -#define MCLOG_FILE(level,cat,x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x +#define MCLOG_TYPE(level, cat, type, x) do { \ + if (ELPP->vRegistry()->allowed(level, cat)) { \ + el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \ + } \ + } while (0) + +#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x) +#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x) + +#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x) +#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x) +#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x) +#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x) +#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x) +#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x) #define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m") #define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x) diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index d57f3f3a0..aa8c80a8a 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2699,6 +2699,12 @@ Writer& Writer::construct(int count, const char* loggerIds, ...) { return *this; } +Writer& Writer::construct(const char *loggerId) { + initializeLogger(ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically))); + m_messageBuilder.initialize(m_logger); + return *this; +} + void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool needLock) { if (lookup) { m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); @@ -2727,6 +2733,19 @@ void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool nee } } +void Writer::initializeLogger(Logger *logger, bool needLock) { + m_logger = logger; + if (m_logger == nullptr) { + m_proceed = false; + } else { + if (needLock) { + m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because + // m_proceed can be changed by lines below + } + m_proceed = true; + } +} + void Writer::processDispatch() { #if ELPP_LOGGING_ENABLED if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 046252a5b..a642d2748 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -3290,6 +3290,7 @@ class Writer : base::NoCopy { Writer& construct(Logger* logger, bool needLock = true); Writer& construct(int count, const char* loggerIds, ...); + Writer& construct(const char *loggerId); protected: LogMessage* m_msg; Level m_level; @@ -3305,6 +3306,7 @@ class Writer : base::NoCopy { friend class el::Helpers; void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true); + void initializeLogger(Logger *logger, bool needLock = true); void processDispatch(); void triggerDispatch(void); }; From dbbb3ce9d8075eae564b6c62db81e063958ea065 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 29 Nov 2018 22:01:48 +0000 Subject: [PATCH 0374/1007] cryptonote: don't serialize for blob size if already known --- .../cryptonote_format_utils.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 55d7d23f8..f11031ed3 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -379,11 +379,19 @@ namespace cryptonote //--------------------------------------------------------------- uint64_t get_transaction_weight(const transaction &tx) { - std::ostringstream s; - binary_archive a(s); - ::serialization::serialize(a, const_cast(tx)); - const cryptonote::blobdata blob = s.str(); - return get_transaction_weight(tx, blob.size()); + size_t blob_size; + if (tx.is_blob_size_valid()) + { + blob_size = tx.blob_size; + } + else + { + std::ostringstream s; + binary_archive a(s); + ::serialization::serialize(a, const_cast(tx)); + blob_size = s.str().size(); + } + return get_transaction_weight(tx, blob_size); } //--------------------------------------------------------------- bool get_tx_fee(const transaction& tx, uint64_t & fee) From c1581a5bb8398936d0e388fc18a4c08d06883ca6 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Wed, 31 Oct 2018 13:26:54 +0000 Subject: [PATCH 0375/1007] perf_timer: only log to file --- src/common/perf_timer.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index d9f1f65c1..d287949ba 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -33,6 +33,9 @@ #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "perf" +#define PERF_LOG(level, cat, x) \ + ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x + namespace tools { uint64_t get_tick_count() @@ -108,7 +111,7 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std { if (!performance_timers) { - MCLOG(level, cat.c_str(), "PERF ----------"); + PERF_LOG(level, cat.c_str(), "PERF ----------"); performance_timers = new std::vector(); performance_timers->reserve(16); // how deep before realloc } @@ -118,7 +121,7 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std if (!pt->started && !pt->paused) { size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size; - MCLOG(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); + PERF_LOG(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); pt->started = true; } } @@ -138,7 +141,7 @@ LoggingPerformanceTimer::~LoggingPerformanceTimer() char s[12]; snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit))); size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size; - MCLOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); + PERF_LOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); if (performance_timers->empty()) { delete performance_timers; From 6a507dab6f935b0d8c417299ba4f5be4882582bb Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 11 Mar 2018 11:17:29 +0000 Subject: [PATCH 0376/1007] perf_timer: add a way to get and reset the current time --- src/common/perf_timer.cpp | 16 ++++++++++++++++ src/common/perf_timer.h | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index d287949ba..fc51dc7f7 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -165,4 +165,20 @@ void PerformanceTimer::resume() paused = false; } +void PerformanceTimer::reset() +{ + if (paused) + ticks = 0; + else + ticks = get_tick_count(); +} + +uint64_t PerformanceTimer::value() const +{ + uint64_t v = ticks; + if (!paused) + v = get_tick_count() - v; + return ticks_to_ns(v); +} + } diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index 584434a0d..c33aaae12 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -51,8 +51,8 @@ class PerformanceTimer ~PerformanceTimer(); void pause(); void resume(); - - uint64_t value() const { return ticks; } + void reset(); + uint64_t value() const; protected: uint64_t ticks; From 93c59b29a8638fcdeb15c1a6dd6efe954586a680 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 6 Dec 2018 01:07:34 +0000 Subject: [PATCH 0377/1007] perf_timer: check allowed categories before logging --- src/common/perf_timer.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index fc51dc7f7..3e1357833 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -33,8 +33,12 @@ #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "perf" +#define PERF_LOG_ALWAYS(level, cat, x) \ + el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::FileOnlyLog).construct(cat) << x #define PERF_LOG(level, cat, x) \ - ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x + do { \ + if (ELPP->vRegistry()->allowed(level, cat)) PERF_LOG_ALWAYS(level, cat, x); \ + } while(0) namespace tools { @@ -109,9 +113,11 @@ PerformanceTimer::PerformanceTimer(bool paused): started(true), paused(paused) LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l): PerformanceTimer(), name(s), cat(cat), unit(unit), level(l) { + const bool log = ELPP->vRegistry()->allowed(level, cat.c_str()); if (!performance_timers) { - PERF_LOG(level, cat.c_str(), "PERF ----------"); + if (log) + PERF_LOG_ALWAYS(level, cat.c_str(), "PERF ----------"); performance_timers = new std::vector(); performance_timers->reserve(16); // how deep before realloc } @@ -120,8 +126,11 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std LoggingPerformanceTimer *pt = performance_timers->back(); if (!pt->started && !pt->paused) { - size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size; - PERF_LOG(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); + if (log) + { + size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused) ++size; + PERF_LOG_ALWAYS(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name); + } pt->started = true; } } @@ -138,10 +147,14 @@ LoggingPerformanceTimer::~LoggingPerformanceTimer() { pause(); performance_timers->pop_back(); - char s[12]; - snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit))); - size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size; - PERF_LOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); + const bool log = ELPP->vRegistry()->allowed(level, cat.c_str()); + if (log) + { + char s[12]; + snprintf(s, sizeof(s), "%8llu ", (unsigned long long)(ticks_to_ns(ticks) / (1000000000 / unit))); + size_t size = 0; for (const auto *tmp: *performance_timers) if (!tmp->paused || tmp==this) ++size; + PERF_LOG_ALWAYS(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); + } if (performance_timers->empty()) { delete performance_timers; From 25e5a8539c7f78e4b63bfb155bd3c6508bfbcca3 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 7 Dec 2018 16:34:56 +0000 Subject: [PATCH 0378/1007] singleton: fix missing *this return value in operator= while there, disable both operator= and copy ctor, since they are not supposed to be around for a singleton --- src/mnemonics/singleton.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mnemonics/singleton.h b/src/mnemonics/singleton.h index a15c2b9ae..d317a2d8d 100644 --- a/src/mnemonics/singleton.h +++ b/src/mnemonics/singleton.h @@ -50,8 +50,8 @@ namespace Language class Singleton { Singleton() {} - Singleton(Singleton &s) {} - Singleton& operator=(const Singleton&) {} + Singleton(Singleton &s) = delete; + Singleton& operator=(const Singleton&) = delete; public: static T* instance() { From 3a3858dc908934be82ffe4f0d693ebb518397a28 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 26 Nov 2018 00:19:10 +0000 Subject: [PATCH 0379/1007] epee: avoid string allocation when parsing a pod from string --- contrib/epee/include/string_tools.h | 48 ++++++++--------------------- src/checkpoints/checkpoints.cpp | 4 +-- 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index 6a063cc36..0d8eca727 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -117,16 +117,12 @@ namespace string_tools return to_hex::string(to_byte_span(to_span(src))); } //---------------------------------------------------------------------------- - template - bool parse_hexstr_to_binbuff(const std::basic_string& s, std::basic_string& res) + inline bool parse_hexstr_to_binbuff(const epee::span s, epee::span& res) { - res.clear(); - if (s.size() & 1) - return false; - try - { - res.resize(s.size() / 2); - unsigned char *dst = (unsigned char *)res.data(); + if (s.size() != res.size() * 2) + return false; + + unsigned char *dst = (unsigned char *)&res[0]; const unsigned char *src = (const unsigned char *)s.data(); for(size_t i = 0; i < s.size(); i += 2) { @@ -140,28 +136,15 @@ namespace string_tools } return true; - } - catch(...) - { - return false; - } } //---------------------------------------------------------------------------- - template - bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod) + inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res) { - static_assert(std::is_pod::value, "expected pod type"); - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(t_pod_type)) - { + if (s.size() & 1) return false; - } - else - { - buf.copy(reinterpret_cast(&t_pod), sizeof(t_pod_type)); - return true; - } + res.resize(s.size() / 2); + epee::span rspan((char*)&res[0], res.size()); + return parse_hexstr_to_binbuff(epee::to_span(s), rspan); } //---------------------------------------------------------------------------- PUSH_WARNINGS @@ -360,17 +343,10 @@ POP_WARNINGS bool hex_to_pod(const std::string& hex_str, t_pod_type& s) { static_assert(std::is_pod::value, "expected pod type"); - std::string hex_str_tr = trim(hex_str); if(sizeof(s)*2 != hex_str.size()) return false; - std::string bin_buff; - if(!parse_hexstr_to_binbuff(hex_str_tr, bin_buff)) - return false; - if(bin_buff.size()!=sizeof(s)) - return false; - - s = *(t_pod_type*)bin_buff.data(); - return true; + epee::span rspan((char*)&s, sizeof(s)); + return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan); } //---------------------------------------------------------------------------- template diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index 1807d44d9..96f575b2d 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -74,7 +74,7 @@ namespace cryptonote bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str) { crypto::hash h = crypto::null_hash; - bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); + bool r = epee::string_tools::hex_to_pod(hash_str, h); CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); // return false if adding at a height we already have AND the hash is different @@ -292,7 +292,7 @@ namespace cryptonote // parse the second part as crypto::hash, // if this fails move on to the next record std::string hashStr = record.substr(pos + 1); - if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) + if (!epee::string_tools::hex_to_pod(hashStr, hash)) { continue; } From a13eb0a1a45b0ae255d97c2539c19e8bd701a1b8 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 26 Nov 2018 15:49:17 +0000 Subject: [PATCH 0380/1007] epee: speed up string matching a bit --- contrib/epee/include/storages/parserse_base_utils.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index 31495ae13..d73fbde3a 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -91,11 +91,15 @@ namespace misc_utils */ inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val) { - val.clear(); - val.reserve(std::distance(star_end_string, buf_end)); bool escape_mode = false; std::string::const_iterator it = star_end_string; ++it; + std::string::const_iterator fi = it; + while (fi != buf_end && *fi != '\\' && *fi != '\"') + ++fi; + val.assign(it, fi); + val.reserve(std::distance(star_end_string, buf_end)); + it = fi; for(;it != buf_end;it++) { if(escape_mode/*prev_ch == '\\'*/) From 2d7b0236eb85a767261611fb558c841a9f790293 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Fri, 7 Dec 2018 18:23:01 +0000 Subject: [PATCH 0381/1007] wallet2: clear all payments on soft rescan_bc They'll get duplicated otherwise --- src/wallet/wallet2.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index bbb801716..ee54faaa4 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -5139,6 +5139,10 @@ void wallet2::rescan_blockchain(bool hard, bool refresh) m_transfers.clear(); m_key_images.clear(); m_pub_keys.clear(); + m_unconfirmed_txs.clear(); + m_payments.clear(); + m_confirmed_txs.clear(); + m_unconfirmed_payments.clear(); m_scanned_pool_txs[0].clear(); m_scanned_pool_txs[1].clear(); From 0e2f5cb5fc84fb5d4afcfe020c9d6ae5fdaf3290 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sat, 8 Dec 2018 10:52:25 +0000 Subject: [PATCH 0382/1007] perf_timer: make all logs Info level and make them not default at log level 1 --- contrib/epee/src/mlog.cpp | 2 +- src/common/perf_timer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 00d848388..9b6b832d1 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -103,7 +103,7 @@ static const char *get_default_categories(int level) categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; break; case 1: - categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO"; + categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG"; break; case 2: categories = "*:DEBUG"; diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index 584434a0d..267f94161 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -63,7 +63,7 @@ class PerformanceTimer class LoggingPerformanceTimer: public PerformanceTimer { public: - LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Debug); + LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Info); ~LoggingPerformanceTimer(); private: From b56b5b52eb47ab1ad67de1cd09f8af1eff1c882d Mon Sep 17 00:00:00 2001 From: Jethro Grassie Date: Sat, 8 Dec 2018 20:52:54 -0500 Subject: [PATCH 0383/1007] ignore child process when exec --- src/common/spawn.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp index 0a2ce8387..b2d03f62f 100644 --- a/src/common/spawn.cpp +++ b/src/common/spawn.cpp @@ -35,6 +35,7 @@ #include #else #include +#include #endif #include "misc_log_ex.h" @@ -114,7 +115,10 @@ int spawn(const char *filename, const std::vector& args, bool wait) if (pid > 0) { if (!wait) + { + signal(SIGCHLD, SIG_IGN); return 0; + } while (1) { From 08bcbd65a574db3456eec948d27a7b206f120ebd Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Tue, 11 Dec 2018 20:30:42 +0000 Subject: [PATCH 0384/1007] update expiry date for both signing and encryption keys --- utils/gpg_keys/moneromooo.asc | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/utils/gpg_keys/moneromooo.asc b/utils/gpg_keys/moneromooo.asc index cce180937..4275b6c0e 100644 --- a/utils/gpg_keys/moneromooo.asc +++ b/utils/gpg_keys/moneromooo.asc @@ -13,18 +13,18 @@ p7gDvxXOGxzq0sqfPTWTBdCj1OPfunHbbeH8ypwBlNpwVG40fJdya+Dqjwu25qX6 Xh5vxLzeJTBmlawa97MCliPvzzJgW9qHRVCa9lLloGVYLiUOS0N+dZ/r/QARAQAB tD5tb25lcm9tb29vLW1vbmVybyA8bW9uZXJvbW9vby1tb25lcm9AdXNlcnMubm9y ZXBseS5naXRodWIuY29tPokCPwQTAQIAKQIbAwcLCQgHAwIBBhUIAgkKCwQWAgMB -Ah4BAheABQJbof8TBQkLMcqRAAoJEGhvB0VNbO/DOrcP/1eG3gkIgq+lXKlv/lta -ZFl8jS5iQUwxTHv8s+O7pbL2mwKt5oM8QmXVMFLlaanENmH0y/DhWRYIYuKTifDN -tXOxENCZhxgjlVxAtnMdD2J8MJANzV2MYGLbGQeFAuZHIL2LMfvUENLYx/jJpe7f -93kXZoQio7rIolnlbM1QoJLxi/7HlOt/VsopJlV2wAmOmlpyWDnOZtUtZgiCGV6a -apFzTs2m3n2GP7+8PG/W01/jVyFqixGW8cWVZORBMhjro2JqrRvw7U+Ypk2o7Em4 -SAnAJyzqpTDh9zf0QWkQXN83YThB3dk1M1FXOyKtZ8G+YVNfs5Ldr7tHNbqKi2v8 -lPaPIDQ7UmxZhy9vraKss0/3AEXaiE2eSvLc4eCcLiS4yVQ2KJpK5TUvz3cP1D5C -USsjxUZvolUELBtNaRVAsxX6OAyA8FjwJ8AKCqyR0NHvrbYhj54N1Js8PWtb+qqk -5sBLKOwEPaWM1uG6SJabrY1xu2VNLOGdJA9bRfyyzfpXksD0lFgwLKki6ReqqoMS -QiVdymhcp55J4tFwsDkzJX7296d1x3r7GAIQMLNc7YizukWfNtvUkSUsAwp+RKUx -TTwkwL1ztzSRpt3hGMJ9SfULTaQD7YAYfz4kitMBNpm90CLFa4CeINu98gE9Ogmc -R+CGQOHLUC3rXubgRCiQg5wfuQINBFQym34BEADHtTHduZFdu76RAzqTjT94F92L +Ah4BAheABQJcEB4SBQkLn+mRAAoJEGhvB0VNbO/DzSIQALXk6ST5Uoxh5+NLBJgI +GR2NOCFwsU+97VOkZWZnzpk+JdUrq/I9JmWWTegGKu3it5YvM8xY1zD1l+RXlnmY +Bg7oT6N63lL8hBhxGm9Hk2A1VJlEjtgtvjbg5yLSdvjxJL1vrmchWGwFWoHT9uIh +oefemb3TQ1U+ADVsW42jXca650/rqvsUMpmQbDfHxUBIfpbxgTWz8sHuMfhFB3R0 +nzSuZ1E1Pbg5jWYxd6sXpb1VFZ7TaQNVGB+4wMe8AH8/0qziLVTXvSkoer6qxU+r +e9M9/Rgue1FJSzZogUekIqyNLsvAeATSCYzi8NoywkUbAq6AqazJtdcOD+7M2/Vl +pdQEnIKSO/9xrziUQifRsPx4LOjf2d2Hvor/rBJYwoI1cFgR5pmH30Mi7OY0mMmm +2TMUPPz7YiVY+RPPpY3Mg5oPRe6sHVAdFYBmc0PTR4v92iYgfQXzoCd5HOJI9QB3 +SwrKz7cNLQwob2za1AXZ3sUp+yok6QMt8Tk6xIbMAjeR4jVeP8iQHhiVS1zx5z/g +lCAfb0hJnykoANgIZvJR/L+tuZjVStqnXjHgreY3IjlWTaNjZ/X5uMvd6zivqI9a +aEmqw/ZDCXRMAtjUCpUvpNlqAgqqbQsx6MFDnMbd4BuKQONeAFLm/Rp31nIvt1vb ++Iu3vkXBbbjb5yMu/dcpgSRUuQINBFQym34BEADHtTHduZFdu76RAzqTjT94F92L xSSopLSk7/sdLWTc2ERmjDId7dKmqrL1Kh2kqAtHY3Rq8Y839LGmbJCzI1kJyOHF o9jkEI93sqXcztLjizPVukqClOZNt3NV/nvefH6JSdqWcnC4V1mQr2Ztl0j+51i+ NYVwGjlsOMlBER+LW/s7egRqAQonrcEB5vsSAzd8mOlNKjRAnDCV+C21GDKxzb80 @@ -35,17 +35,17 @@ xRFfhoiiPyjjPRmJ+/iG3KXLzEiMfbyTFzGkX3Z9BJTxemUx8JOSVQXa++t4w39J UwzwBKNItDhtQqJpCaF43fJ4ykLMJi5gRpgqtb+T3CF0abXNII1IfS8a0fSpd48d 6hzoCVqpvWsI1fOY5Ui0BIgubNhkr4OJDCWBT5zhxjCJ3QiUSKyyqjfw1Fpuf/0Y CSA9Q9FSCq9qTppJs5ITHVjhWw2zxrJEG+P2+dvryBhV9l4T2xx1oHqlKX8zzLBG -kS8NmnxoRFQs5rZYvQARAQABiQIlBBgBAgAPAhsMBQJX3tl5BQkHbqT4AAoJEGhv -B0VNbO/DrN4QAJVTg2l91LSxb2dTikXbkRCPev1Eiqjd3d4TZIyE7yeYreHUyfcz -sytEsMUpd5nqqL/QMOwgC8Dm+77Yp480atI/c0wQh30EfJq1YP4q/gwv8EtriFo6 -ZaqYNzajmB8otz6yyb5RD9S6ocZX5b22nnNM/ihiTQJiqJKC2XHPQH3/grniU9if -WXUlY7Fo+8lRn/aRPMjYT2elsugru8GoplDMyfPRymnMJmTwNPYkg0Dnm2JUXYhH -VLO6Ebh7fUChsiGNmSp+siv7fcZIf20+LvoymgyT+49LrrQMvRleOqaJc1LBKaK6 -1yU+jLk1f9bFCMORQoTxvIVaSnjMWAeKDxi8nwuVfUJpQYXmbOOqMZgoFi6t+U7/ -T6Cz1CGKv3JgEveWyHeOvsjopej3a4Hmk7QGM/xJrd83roUjypjx5lTeMDvcPlPs -IQOy33qWguR1xoEnwAp9ov/meS7HtUOoC0m9ROZqWT6ArN+1ONplFP4GTsuW91Qz -pacQMl09F0KF1MacAdpauCOKj+wy9XPUW8v3kWZufUSgNtOLHS+kVumkqdJuJ0aB -7Ezc1yYY6DwRFOdlUpTJkRMozyPRvS15Lz/vPEhcbxMHRAg611CS2CqTEIbk2chJ -QBlj77a45lDTXGQHFVYXlbXx/HWb5zOGpNji0QhY1hOABRo78DT5yda+ -=ksQj +kS8NmnxoRFQs5rZYvQARAQABiQIlBBgBAgAPAhsMBQJcEB4eBQkLn+meAAoJEGhv +B0VNbO/DjzYP/2A6HtpvPkD+s/0+Ghmp5Rw7HIvZz0RnCsvM3qVQqVn3JTqHXyhD +5GmZrCxhliW1nRBITaKSRHXSGeE/O1BtK6eW/Z1P6bWJVd+R9vhaZlLU2sswiFzu +q3s7bL/Fo9VRc0SX6j6JDh1FZ3JcebUfY59sixHLqZuAk9m97z6H1NjS+f4pB5Tp +n1nnRgdvYk4tjlk4mmluIAwjq8Ll6gw6ntwjX9Gq9OblutTr2MZDyTIOxcG54ZN2 +2t5JA7Syh0He6dn/NLlb//bPPnic3GuYfkgKht8M1XCJfnDKju+I9qRGf1DYIjP7 +m24IDC0MM9Fo7KIUY+vcV0J/BIkkZtZ9xh0iEEnR/KqYXmClym+EiWCwPhLloKL3 +6cZr5MaiYJsodYa73x35pSGvioUrBDb78v8nCNhoTUXzZv8E0s/0YI2UZSGhVEC6 +ANNXPvKeOdibGNDM4JOwETabkEng38UE6Oa7Qonra2MWsPegh+mnZ7/sqrktQRMB +T/Xne6vapDONeLeY2hVcT0j9f/S8rgpHPjP4/hmYE9d38Euwa7TZ0lHWcmJzQy6F +7HfGR3oYAYAwRnvl+kYUGZ46u9Nodi4+wycFc4+IpwFtnlUzRBOcOilnR2X6KFJW +SiVss1i7ECcWaKCBNN1MrpwGWeuSbCQ00c3bxe6ZN6goB1t2u1KAZqMK +=HFHX -----END PGP PUBLIC KEY BLOCK----- From 118db4f357fd4a415bb80018bc5f58130ba64e61 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Sat, 24 Nov 2018 15:20:44 +0100 Subject: [PATCH 0385/1007] Cleanup leftovers from migrating depends from bitcoin Depends still contained some leftovers, like the `wallet` target that included bdb from bitcoin. This commit removes these unneeded targets, the miniupnpc package and the berkeley db package. Reflect the changes in the README as well. --- contrib/depends/Makefile | 18 +--------------- contrib/depends/README.md | 14 ++++-------- contrib/depends/config.site.in | 19 ---------------- contrib/depends/packages/bdb.mk | 31 --------------------------- contrib/depends/packages/miniupnpc.mk | 28 ------------------------ contrib/depends/packages/packages.mk | 2 -- 6 files changed, 5 insertions(+), 107 deletions(-) delete mode 100644 contrib/depends/packages/bdb.mk delete mode 100644 contrib/depends/packages/miniupnpc.mk diff --git a/contrib/depends/Makefile b/contrib/depends/Makefile index b0c032c09..bf33d706d 100644 --- a/contrib/depends/Makefile +++ b/contrib/depends/Makefile @@ -3,9 +3,6 @@ SOURCES_PATH ?= $(BASEDIR)/sources BASE_CACHE ?= $(BASEDIR)/built SDK_PATH ?= $(BASEDIR)/SDKs -NO_QT ?= -NO_WALLET ?= -NO_UPNP ?= FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources BUILD = $(shell ./config.guess) @@ -97,17 +94,10 @@ $(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null) $(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null) $(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null) -qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) -wallet_packages_$(NO_WALLET) = $(wallet_packages) -upnp_packages_$(NO_UPNP) = $(upnp_packages) -packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_) +packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) -ifneq ($(qt_packages_),) -native_packages += $(qt_native_packages) -endif - all_packages = $(packages) $(native_packages) meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk @@ -153,9 +143,6 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ - -e 's|@no_qt@|$(NO_QT)|' \ - -e 's|@no_wallet@|$(NO_WALLET)|' \ - -e 's|@no_upnp@|$(NO_UPNP)|' \ -e 's|@debug@|$(DEBUG)|' \ $< > $@ $(AT)touch $@ @@ -176,9 +163,6 @@ $(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_ -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \ - -e 's|@no_qt@|$(NO_QT)|' \ - -e 's|@no_wallet@|$(NO_WALLET)|' \ - -e 's|@no_upnp@|$(NO_UPNP)|' \ -e 's|@debug@|$(DEBUG)|' \ -e 's|@depends@|$(host_cmake)|' \ -e 's|@prefix@|$($(host_arch)_$(host_os)_prefix)|'\ diff --git a/contrib/depends/README.md b/contrib/depends/README.md index dd2824569..597398369 100644 --- a/contrib/depends/README.md +++ b/contrib/depends/README.md @@ -12,11 +12,11 @@ For example: make HOST=x86_64-w64-mingw32 -j4 -A prefix will be generated that's suitable for plugging into Bitcoin's -configure. In the above example, a dir named x86_64-w64-mingw32 will be -created. To use it for Bitcoin: +A toolchain will be generated that's suitable for plugging into Monero's +cmake. In the above example, a dir named x86_64-w64-mingw32 will be +created. To use it for Monero: - ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32 + cmake -DCMAKE_TOOLCHAIN=`pwd`/contrib/depends/x86_64-w64-mingw32 Common `host-platform-triplets` for cross compilation are: @@ -35,16 +35,10 @@ The following can be set when running make: make FOO=bar BASE_CACHE: built packages will be placed here SDK_PATH: Path where sdk's can be found (used by OSX) FALLBACK_DOWNLOAD_PATH: If a source file can't be fetched, try here before giving up - NO_QT: Don't download/build/cache qt and its dependencies - NO_WALLET: Don't download/build/cache libs needed to enable the wallet - NO_UPNP: Don't download/build/cache packages needed for enabling upnp DEBUG: disable some optimizations and enable more runtime checking HOST_ID_SALT: Optional salt to use when generating host package ids BUILD_ID_SALT: Optional salt to use when generating build package ids -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`. - Additional targets: download: run 'make download' to fetch all sources without building them diff --git a/contrib/depends/config.site.in b/contrib/depends/config.site.in index 0a4a9c327..dd91bcb2a 100644 --- a/contrib/depends/config.site.in +++ b/contrib/depends/config.site.in @@ -13,25 +13,6 @@ fi if test -z $with_qt_translationdir; then with_qt_translationdir=$depends_prefix/translations fi -if test -z $with_qt_bindir && test -z "@no_qt@"; then - with_qt_bindir=$depends_prefix/native/bin -fi -if test -z $with_protoc_bindir && test -z "@no_qt@"; then - with_protoc_bindir=$depends_prefix/native/bin -fi - - -if test -z $enable_wallet && test -n "@no_wallet@"; then - enable_wallet=no -fi - -if test -z $with_miniupnpc && test -n "@no_upnp@"; then - with_miniupnpc=no -fi - -if test -z $with_gui && test -n "@no_qt@"; then - with_gui=no -fi if test x@host_os@ = xdarwin; then BREW=no diff --git a/contrib/depends/packages/bdb.mk b/contrib/depends/packages/bdb.mk deleted file mode 100644 index 050a60add..000000000 --- a/contrib/depends/packages/bdb.mk +++ /dev/null @@ -1,31 +0,0 @@ -package=bdb -$(package)_version=4.8.30 -$(package)_download_path=https://download.oracle.com/berkeley-db -$(package)_file_name=db-$($(package)_version).NC.tar.gz -$(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef -$(package)_build_subdir=build_unix - -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)_cxxflags=-std=c++11 -endef - -define $(package)_preprocess_cmds - sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' dbinc/atomic.h && \ - sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c && \ - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist -endef - -define $(package)_config_cmds - ../dist/$($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) libdb_cxx-4.8.a libdb-4.8.a -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install_lib install_include -endef diff --git a/contrib/depends/packages/miniupnpc.mk b/contrib/depends/packages/miniupnpc.mk deleted file mode 100644 index 1bb8cb5d2..000000000 --- a/contrib/depends/packages/miniupnpc.mk +++ /dev/null @@ -1,28 +0,0 @@ -package=miniupnpc -$(package)_version=2.0.20170509 -$(package)_download_path=http://miniupnp.free.fr/files -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=d3c368627f5cdfb66d3ebd64ca39ba54d6ff14a61966dbecb8dd296b7039f16a - -define $(package)_set_vars -$(package)_build_opts=CC="$($(package)_cc)" -$(package)_build_opts_darwin=OS=Darwin LIBTOOL="$($(package)_libtool)" -$(package)_build_opts_mingw32=-f Makefile.mingw -$(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)" -endef - -define $(package)_preprocess_cmds - mkdir dll && \ - sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \ - sed -i.old "s|miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings|miniupnpcstrings.h: miniupnpcstrings.h.in|" Makefile.mingw -endef - -define $(package)_build_cmds - $(MAKE) libminiupnpc.a $($(package)_build_opts) -endef - -define $(package)_stage_cmds - mkdir -p $($(package)_staging_prefix_dir)/include/miniupnpc $($(package)_staging_prefix_dir)/lib &&\ - install *.h $($(package)_staging_prefix_dir)/include/miniupnpc &&\ - install libminiupnpc.a $($(package)_staging_prefix_dir)/lib -endef diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index f814c14d6..234adbdd4 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -1,8 +1,6 @@ packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt hidapi native_packages := native_ccache -wallet_packages=bdb - darwin_native_packages = native_biplist native_ds_store native_mac_alias darwin_packages = sodium-darwin From aaafa8a946211f5d5dc0e6e26f636f12a9700e70 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Sun, 24 Jun 2018 21:59:24 +0100 Subject: [PATCH 0386/1007] ringct: avoid repeated point conversion --- src/ringct/rctSigs.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index baa649f82..316f0e5e8 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -605,10 +605,19 @@ namespace rct { keyV tmp(rows + 1); size_t i; keyM M(cols, tmp); + ge_p3 Cp3; + CHECK_AND_ASSERT_MES_L1(ge_frombytes_vartime(&Cp3, C.bytes) == 0, false, "point conv failed"); + ge_cached Ccached; + ge_p3_to_cached(&Ccached, &Cp3); + ge_p1p1 p1; //create the matrix to mg sig for (i = 0; i < cols; i++) { M[i][0] = pubs[i].dest; - subKeys(M[i][1], pubs[i].mask, C); + ge_p3 p3; + CHECK_AND_ASSERT_MES_L1(ge_frombytes_vartime(&p3, pubs[i].mask.bytes) == 0, false, "point conv failed"); + ge_sub(&p1, &p3, &Ccached); + ge_p1p1_to_p3(&p3, &p1); + ge_p3_tobytes(M[i][1].bytes, &p3); } //DP(C); return MLSAG_Ver(message, M, mg, rows); From b97059fc8ef4ecb491b759a4aa5b3bc7754fb4e5 Mon Sep 17 00:00:00 2001 From: erciccione Date: Wed, 12 Dec 2018 14:44:43 +0100 Subject: [PATCH 0387/1007] add erciccione's pgp key --- utils/gpg_keys/erciccione.asc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 utils/gpg_keys/erciccione.asc diff --git a/utils/gpg_keys/erciccione.asc b/utils/gpg_keys/erciccione.asc new file mode 100644 index 000000000..109941d55 --- /dev/null +++ b/utils/gpg_keys/erciccione.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFohQ30BCADktKHeTg48Dm4oU9JPrfHXzY3sZtTQsqsQGmYiFT8nQjRnSzic +dZe4sh2W4UYQSLFw7pEb7a51ZYkz5+gFKcj3NmIaEpNra7+SEtszoS3IALHUyGGQ ++nFDxUHwTV5OeIUXPHs2AnCVZa4yEWmavXFiPL35+dcFkwyUA5psd97dFIbtkPQ4 +nT2RCc2emy6NHVE5L7pzlBe9CeFkFyovs847d3WDa/96TT4JMRm34qvUrSvOkqti +xrui8hGwNedAw64ObiJhQLa3rvQ8bCtTLNHhpdc+zhBi3L5nIdwquMd5Bd6zHfmW +HHyXEoRTZYMRabNBSR9FrsjGBiHG9wuEK2B7ABEBAAG0NWVyY2ljY2lvbmVAcHJv +dG9ubWFpbC5jb20gPGVyY2ljY2lvbmVAcHJvdG9ubWFpbC5jb20+iQE1BBABCAAp +BQJaIUN9BgsJBwgDAgkQdir4xgjlbN8EFQgKAgMWAgECGQECGwMCHgEAAFc+CAC2 +7BDCYPWfXCKtaqP/jzay46nai66hSyuIJ2sd4RSbQlVNCwFUQ2NtUwDxtzdzB3bk +AfsqrkdSS7V82bfZPOoYapWikjA3LGd2GHvClKNmIgIg3CvrAByD9okhLYOmxChU +5/FzMgSgDdbez4Z+XXzUothirHcHR7J+PtzqMZWusuyNqfXlWgPNPbAHG/hm5RLw +s6uGOLDqhJDiqi0HjC/p9ponPAJ3g0jfECnXFp7R32EgbBHExT/g8e3L4J3Q8y/E +WrZiQsIc89srANw5YIcjlr/i3PY8tyrelpLDVBj05802WYamYx10Zd2epM4NglBs ++YjiWpSM9fTi9QKFCHyAuQENBFohQ30BCADe4FJcus4e3FzsagKdAM/iFeZ4BE2l +gVgSg8CVWIYlTAmeK+SBPfsxvwOWxmx/KkirWn3hOSA2U6mp9+g6hr9rLqWNwatM +OsitrJlWG2aPcuAmlzLFvtH0Vbilh0m4B98g2XUa94HtrlGdPAoYPquS1HsfL284 +CHpQXXOypOS+/spTK/OlpdUaPaVyqVfE3kzXYqt24RbDcsOvUzSzVRCA8kBp6azm +1qoqDboP112Ax7OkV0FGc/kd5PNMPTOnVR+4wVXWhl6gAI1I2JFvo3EJlxtddyTB +Rkx06jbYRyPj9KCEC4CBx9qsNlo7TUHgObAr+CLX4I5hkEWW0pS98vlpABEBAAGJ +AR8EGAEIABMFAlohQ30JEHYq+MYI5WzfAhsMAAD1twgAxjbETzOUeq/bWwVoGzmh +SMJajZs2c5Pv0SAwi5QZCoRefp2HYfpWcBsfZG84B0EmJb9Wwu3wrXWBf96xMTFM +neU0+L2+RcH8uH7/C2MlVaZjFv5dPPJAtwbY2BQl1bX5DrEwZ8QH7IUXZmWfjmZ3 +ww5llfCAyVCxMn+tnIJnk/7HODY0t1LmusFvZsAVsWIgdndKImXM4CTzirfmDks8 +TxpXfaJzU3B3KTIzMgEvwtTLJfgf07Foy4ITIl+1zS7gLL0fXldtx6fJJMvANsLf +JrRjafh21qfJb3I9TUH8G7C0Ln3LspBGsWZ4f+fjq4LEg7SCOAJSeBwfOtMJeCrU +/Q== +=a70Z +-----END PGP PUBLIC KEY BLOCK----- From 1ebcd7b9b0b6c6a81d7439a4ba717df364c94db8 Mon Sep 17 00:00:00 2001 From: rbrunner7 Date: Sun, 28 Oct 2018 14:46:58 +0100 Subject: [PATCH 0388/1007] MMS (Multisig Messaging System): Initial version --- src/common/util.cpp | 12 + src/common/util.h | 2 + src/simplewallet/simplewallet.cpp | 1495 +++++++++++++++++++++++++--- src/simplewallet/simplewallet.h | 45 +- src/wallet/CMakeLists.txt | 9 +- src/wallet/message_store.cpp | 1445 +++++++++++++++++++++++++++ src/wallet/message_store.h | 420 ++++++++ src/wallet/message_transporter.cpp | 317 ++++++ src/wallet/message_transporter.h | 113 +++ src/wallet/wallet2.cpp | 117 ++- src/wallet/wallet2.h | 14 +- src/wallet/wallet_errors.h | 25 + 12 files changed, 3882 insertions(+), 132 deletions(-) create mode 100644 src/wallet/message_store.cpp create mode 100644 src/wallet/message_store.h create mode 100644 src/wallet/message_transporter.cpp create mode 100644 src/wallet/message_transporter.h diff --git a/src/common/util.cpp b/src/common/util.cpp index 58b0d8210..448f792ff 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -58,6 +58,7 @@ #include "include_base_utils.h" #include "file_io_utils.h" #include "wipeable_string.h" +#include "misc_os_dependent.h" using namespace epee; #include "crypto/crypto.h" @@ -1025,4 +1026,15 @@ std::string get_nix_version_display_string() #endif } + std::string get_human_readable_timestamp(uint64_t ts) + { + char buffer[64]; + if (ts < 1234567890) + return ""; + time_t tt = ts; + struct tm tm; + misc_utils::get_gmt_time(tt, tm); + strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm); + return std::string(buffer); + } } diff --git a/src/common/util.h b/src/common/util.h index 1c5c5f4e7..d5aca15d1 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -242,4 +242,6 @@ namespace tools #endif void closefrom(int fd); + + std::string get_human_readable_timestamp(uint64_t ts); } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b729c4bb7..281702774 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -65,6 +65,7 @@ #include "wallet/wallet_args.h" #include "version.h" #include +#include "wallet/message_store.h" #ifdef WIN32 #include @@ -102,12 +103,14 @@ typedef cryptonote::simple_wallet sw; m_auto_refresh_enabled.store(auto_refresh_enabled, std::memory_order_relaxed); \ }) -#define SCOPED_WALLET_UNLOCK() \ +#define SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(code) \ LOCK_IDLE_SCOPE(); \ boost::optional pwd_container = boost::none; \ - if (m_wallet->ask_password() && !(pwd_container = get_and_verify_password())) { return true; } \ + if (m_wallet->ask_password() && !(pwd_container = get_and_verify_password())) { code; } \ tools::wallet_keys_unlocker unlocker(*m_wallet, pwd_container); +#define SCOPED_WALLET_UNLOCK() SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return true;) + enum TransferType { Transfer, TransferLocked, @@ -835,66 +838,84 @@ bool simple_wallet::print_fee_info(const std::vector &args/* = std: } bool simple_wallet::prepare_multisig(const std::vector &args) +{ + prepare_multisig_main(args, false); + return true; +} + +bool simple_wallet::prepare_multisig_main(const std::vector &args, bool called_by_mms) { if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (m_wallet->multisig()) { fail_msg_writer() << tr("This wallet is already multisig"); - return true; + return false; } if (m_wallet->watch_only()) { fail_msg_writer() << tr("wallet is watch-only and cannot be made multisig"); - return true; + return false; } if(m_wallet->get_num_transfer_details()) { fail_msg_writer() << tr("This wallet has been used before, please use a new wallet to create a multisig wallet"); - return true; + return false; } - SCOPED_WALLET_UNLOCK(); + SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); std::string multisig_info = m_wallet->get_multisig_info(); success_msg_writer() << multisig_info; success_msg_writer() << tr("Send this multisig info to all other participants, then use make_multisig [...] with others' multisig info"); success_msg_writer() << tr("This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants "); + + if (called_by_mms) + { + get_message_store().process_wallet_created_data(get_multisig_wallet_state(), mms::message_type::key_set, multisig_info); + } + return true; } bool simple_wallet::make_multisig(const std::vector &args) +{ + make_multisig_main(args, false); + return true; +} + +bool simple_wallet::make_multisig_main(const std::vector &args, bool called_by_mms) { if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (m_wallet->multisig()) { fail_msg_writer() << tr("This wallet is already multisig"); - return true; + return false; } if (m_wallet->watch_only()) { fail_msg_writer() << tr("wallet is watch-only and cannot be made multisig"); - return true; + return false; } if(m_wallet->get_num_transfer_details()) { fail_msg_writer() << tr("This wallet has been used before, please use a new wallet to create a multisig wallet"); - return true; + return false; } if (args.size() < 2) { fail_msg_writer() << tr("usage: make_multisig [...]"); - return true; + return false; } // parse threshold @@ -902,14 +923,14 @@ bool simple_wallet::make_multisig(const std::vector &args) if (!string_tools::get_xtype_from_string(threshold, args[0])) { fail_msg_writer() << tr("Invalid threshold"); - return true; + return false; } const auto orig_pwd_container = get_and_verify_password(); if(orig_pwd_container == boost::none) { fail_msg_writer() << tr("Your original password was incorrect."); - return true; + return false; } LOCK_IDLE_SCOPE(); @@ -924,20 +945,24 @@ bool simple_wallet::make_multisig(const std::vector &args) success_msg_writer() << tr("Another step is needed"); success_msg_writer() << multisig_extra_info; success_msg_writer() << tr("Send this multisig info to all other participants, then use exchange_multisig_keys [...] with others' multisig info"); + if (called_by_mms) + { + get_message_store().process_wallet_created_data(get_multisig_wallet_state(), mms::message_type::additional_key_set, multisig_extra_info); + } return true; } } catch (const std::exception &e) { fail_msg_writer() << tr("Error creating multisig: ") << e.what(); - return true; + return false; } uint32_t total; if (!m_wallet->multisig(NULL, &threshold, &total)) { fail_msg_writer() << tr("Error creating multisig: new wallet is not multisig"); - return true; + return false; } success_msg_writer() << std::to_string(threshold) << "/" << total << tr(" multisig address: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); @@ -997,35 +1022,41 @@ bool simple_wallet::finalize_multisig(const std::vector &args) return true; } -bool simple_wallet::exchange_multisig_keys(const std::vector &args) { +bool simple_wallet::exchange_multisig_keys(const std::vector &args) +{ + exchange_multisig_keys_main(args, false); + return true; +} + +bool simple_wallet::exchange_multisig_keys_main(const std::vector &args, bool called_by_mms) { bool ready; if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (!m_wallet->multisig(&ready)) { fail_msg_writer() << tr("This wallet is not multisig"); - return true; + return false; } if (ready) { fail_msg_writer() << tr("This wallet is already finalized"); - return true; + return false; } const auto orig_pwd_container = get_and_verify_password(); if(orig_pwd_container == boost::none) { fail_msg_writer() << tr("Your original password was incorrect."); - return true; + return false; } if (args.size() < 2) { fail_msg_writer() << tr("usage: exchange_multisig_keys [...]"); - return true; + return false; } try @@ -1036,6 +1067,10 @@ bool simple_wallet::exchange_multisig_keys(const std::vector &args) message_writer() << tr("Another step is needed"); message_writer() << multisig_extra_info; message_writer() << tr("Send this multisig info to all other participants, then use exchange_multisig_keys [...] with others' multisig info"); + if (called_by_mms) + { + get_message_store().process_wallet_created_data(get_multisig_wallet_state(), mms::message_type::additional_key_set, multisig_extra_info); + } return true; } else { uint32_t threshold, total; @@ -1046,58 +1081,71 @@ bool simple_wallet::exchange_multisig_keys(const std::vector &args) catch (const std::exception &e) { fail_msg_writer() << tr("Failed to perform multisig keys exchange: ") << e.what(); - return true; + return false; } return true; } bool simple_wallet::export_multisig(const std::vector &args) +{ + export_multisig_main(args, false); + return true; +} + +bool simple_wallet::export_multisig_main(const std::vector &args, bool called_by_mms) { bool ready; if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (!m_wallet->multisig(&ready)) { fail_msg_writer() << tr("This wallet is not multisig"); - return true; + return false; } if (!ready) { fail_msg_writer() << tr("This multisig wallet is not yet finalized"); - return true; + return false; } if (args.size() != 1) { fail_msg_writer() << tr("usage: export_multisig_info "); - return true; + return false; } const std::string filename = args[0]; - if (m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) + if (!called_by_mms && m_wallet->confirm_export_overwrite() && !check_file_overwrite(filename)) return true; - SCOPED_WALLET_UNLOCK(); + SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); try { cryptonote::blobdata ciphertext = m_wallet->export_multisig(); - bool r = epee::file_io_utils::save_string_to_file(filename, ciphertext); - if (!r) + if (called_by_mms) { - fail_msg_writer() << tr("failed to save file ") << filename; - return true; + get_message_store().process_wallet_created_data(get_multisig_wallet_state(), mms::message_type::multisig_sync_data, ciphertext); + } + else + { + bool r = epee::file_io_utils::save_string_to_file(filename, ciphertext); + if (!r) + { + fail_msg_writer() << tr("failed to save file ") << filename; + return false; + } } } catch (const std::exception &e) { LOG_ERROR("Error exporting multisig info: " << e.what()); fail_msg_writer() << tr("Error exporting multisig info: ") << e.what(); - return true; + return false; } success_msg_writer() << tr("Multisig info exported to ") << filename; @@ -1105,45 +1153,58 @@ bool simple_wallet::export_multisig(const std::vector &args) } bool simple_wallet::import_multisig(const std::vector &args) +{ + import_multisig_main(args, false); + return true; +} + +bool simple_wallet::import_multisig_main(const std::vector &args, bool called_by_mms) { bool ready; uint32_t threshold, total; if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (!m_wallet->multisig(&ready, &threshold, &total)) { fail_msg_writer() << tr("This wallet is not multisig"); - return true; + return false; } if (!ready) { fail_msg_writer() << tr("This multisig wallet is not yet finalized"); - return true; + return false; } if (args.size() < threshold - 1) { fail_msg_writer() << tr("usage: import_multisig_info [...] - one for each other participant"); - return true; + return false; } std::vector info; for (size_t n = 0; n < args.size(); ++n) { - const std::string filename = args[n]; - std::string data; - bool r = epee::file_io_utils::load_file_to_string(filename, data); - if (!r) + if (called_by_mms) { - fail_msg_writer() << tr("failed to read file ") << filename; - return true; + info.push_back(args[n]); + } + else + { + const std::string &filename = args[n]; + std::string data; + bool r = epee::file_io_utils::load_file_to_string(filename, data); + if (!r) + { + fail_msg_writer() << tr("failed to read file ") << filename; + return false; + } + info.push_back(std::move(data)); } - info.push_back(std::move(data)); } - SCOPED_WALLET_UNLOCK(); + SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); // all read and parsed, actually import try @@ -1158,7 +1219,7 @@ bool simple_wallet::import_multisig(const std::vector &args) catch (const std::exception &e) { fail_msg_writer() << tr("Failed to import multisig info: ") << e.what(); - return true; + return false; } if (m_wallet->is_trusted_daemon()) { @@ -1169,11 +1230,13 @@ bool simple_wallet::import_multisig(const std::vector &args) catch (const std::exception &e) { message_writer() << tr("Failed to update spent status after importing multisig info: ") << e.what(); + return false; } } else { message_writer() << tr("Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run \"rescan_spent\""); + return false; } return true; } @@ -1185,52 +1248,94 @@ bool simple_wallet::accept_loaded_tx(const tools::wallet2::multisig_tx_set &txs) } bool simple_wallet::sign_multisig(const std::vector &args) +{ + sign_multisig_main(args, false); + return true; +} + +bool simple_wallet::sign_multisig_main(const std::vector &args, bool called_by_mms) { bool ready; if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if(!m_wallet->multisig(&ready)) { fail_msg_writer() << tr("This is not a multisig wallet"); - return true; + return false; } if (!ready) { fail_msg_writer() << tr("This multisig wallet is not yet finalized"); - return true; + return false; } if (args.size() != 1) { fail_msg_writer() << tr("usage: sign_multisig "); - return true; + return false; } - SCOPED_WALLET_UNLOCK(); + SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); std::string filename = args[0]; std::vector txids; uint32_t signers = 0; try { - bool r = m_wallet->sign_multisig_tx_from_file(filename, txids, [&](const tools::wallet2::multisig_tx_set &tx){ signers = tx.m_signers.size(); return accept_loaded_tx(tx); }); - if (!r) + if (called_by_mms) { - fail_msg_writer() << tr("Failed to sign multisig transaction"); - return true; + tools::wallet2::multisig_tx_set exported_txs; + std::string ciphertext; + bool r = m_wallet->load_multisig_tx(args[0], exported_txs, [&](const tools::wallet2::multisig_tx_set &tx){ signers = tx.m_signers.size(); return accept_loaded_tx(tx); }); + if (r) + { + r = m_wallet->sign_multisig_tx(exported_txs, txids); + } + if (r) + { + ciphertext = m_wallet->save_multisig_tx(exported_txs); + if (ciphertext.empty()) + { + r = false; + } + } + if (r) + { + mms::message_type message_type = mms::message_type::fully_signed_tx; + if (txids.empty()) + { + message_type = mms::message_type::partially_signed_tx; + } + get_message_store().process_wallet_created_data(get_multisig_wallet_state(), message_type, ciphertext); + filename = "MMS"; // for the messages below + } + else + { + fail_msg_writer() << tr("Failed to sign multisig transaction"); + return false; + } + } + else + { + bool r = m_wallet->sign_multisig_tx_from_file(filename, txids, [&](const tools::wallet2::multisig_tx_set &tx){ signers = tx.m_signers.size(); return accept_loaded_tx(tx); }); + if (!r) + { + fail_msg_writer() << tr("Failed to sign multisig transaction"); + return false; + } } } catch (const tools::error::multisig_export_needed& e) { fail_msg_writer() << tr("Multisig error: ") << e.what(); - return true; + return false; } catch (const std::exception &e) { fail_msg_writer() << tr("Failed to sign multisig transaction: ") << e.what(); - return true; + return false; } if (txids.empty()) @@ -1258,50 +1363,68 @@ bool simple_wallet::sign_multisig(const std::vector &args) } bool simple_wallet::submit_multisig(const std::vector &args) +{ + submit_multisig_main(args, false); + return true; +} + +bool simple_wallet::submit_multisig_main(const std::vector &args, bool called_by_mms) { bool ready; uint32_t threshold; if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); - return true; + return false; } if (!m_wallet->multisig(&ready, &threshold)) { fail_msg_writer() << tr("This is not a multisig wallet"); - return true; + return false; } if (!ready) { fail_msg_writer() << tr("This multisig wallet is not yet finalized"); - return true; + return false; } if (args.size() != 1) { fail_msg_writer() << tr("usage: submit_multisig "); - return true; + return false; } if (!try_connect_to_daemon()) - return true; + return false; - SCOPED_WALLET_UNLOCK(); + SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); std::string filename = args[0]; try { tools::wallet2::multisig_tx_set txs; - bool r = m_wallet->load_multisig_tx_from_file(filename, txs, [&](const tools::wallet2::multisig_tx_set &tx){ return accept_loaded_tx(tx); }); - if (!r) + if (called_by_mms) { - fail_msg_writer() << tr("Failed to load multisig transaction from file"); - return true; + bool r = m_wallet->load_multisig_tx(args[0], txs, [&](const tools::wallet2::multisig_tx_set &tx){ return accept_loaded_tx(tx); }); + if (!r) + { + fail_msg_writer() << tr("Failed to load multisig transaction from MMS"); + return false; + } + } + else + { + bool r = m_wallet->load_multisig_tx_from_file(filename, txs, [&](const tools::wallet2::multisig_tx_set &tx){ return accept_loaded_tx(tx); }); + if (!r) + { + fail_msg_writer() << tr("Failed to load multisig transaction from file"); + return false; + } } if (txs.m_signers.size() < threshold) { fail_msg_writer() << (boost::format(tr("Multisig transaction signed by only %u signers, needs %u more signatures")) % txs.m_signers.size() % (threshold - txs.m_signers.size())).str(); - return true; + return false; } // actually commit the transactions @@ -1320,6 +1443,7 @@ bool simple_wallet::submit_multisig(const std::vector &args) { LOG_ERROR("unknown error"); fail_msg_writer() << tr("unknown error"); + return false; } return true; @@ -2308,6 +2432,12 @@ bool simple_wallet::help(const std::vector &args/* = std::vector" + std::vector mms_args(1, args.front() + " " + args.back()); + success_msg_writer() << get_command_usage(mms_args); + } else { success_msg_writer() << get_command_usage(args); @@ -2655,6 +2785,89 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::export_raw_multisig, this, _1), tr("export_raw_multisig_tx "), tr("Export a signed multisig transaction to a file")); + m_cmd_binder.set_handler("mms", + boost::bind(&simple_wallet::mms, this, _1), + tr("mms [ []]"), + tr("Interface with the MMS (Multisig Messaging System)\n" + " is one of:\n" + " init, info, signer, list, next, sync, transfer, delete, send, receive, export, note, show, set, help\n" + " send_signer_config, start_auto_config, stop_auto_config, auto_config\n" + "Get help about a subcommand with: help mms , or mms help ")); + m_cmd_binder.set_handler("mms init", + boost::bind(&simple_wallet::mms, this, _1), + tr("mms init / "), + tr("Initialize and configure the MMS for M/N = number of required signers/number of authorized signers multisig")); + m_cmd_binder.set_handler("mms info", + boost::bind(&simple_wallet::mms, this, _1), + tr("mms info"), + tr("Display current MMS configuration")); + m_cmd_binder.set_handler("mms signer", + boost::bind(&simple_wallet::mms, this, _1), + tr("mms signer [