Skip to content

Instantly share code, notes, and snippets.

@blockspacer
Created December 15, 2022 20:08
Show Gist options
  • Save blockspacer/bc2e4f921483031e16288abf6b91bc21 to your computer and use it in GitHub Desktop.
Save blockspacer/bc2e4f921483031e16288abf6b91bc21 to your computer and use it in GitHub Desktop.
spirit bignum
project(test_main)
cmake_minimum_required(VERSION 3.5)
add_executable(test_main
release_assert.cpp
#cbignum.cpp
main.cpp)
find_package(Threads)
#FIND_PACKAGE(Boost COMPONENTS thread REQUIRED)
target_include_directories(test_main PRIVATE ${Boost_INCLUDE_DIR} )
target_link_libraries(test_main PRIVATE
ssl
crypto
gtestd
Threads::Threads
${Boost_LIBRARIES}
#boost_system
# boost_filesystem
# boost_thread
# boost_date_time
# boost_chrono
# boost_regex
# boost_serialization
# boost_program_options
)
target_compile_options(test_main PRIVATE
-std=c++20 -Wall -Wextra -pedantic
#-fsanitize=address
-O0)
target_compile_features(test_main PUBLIC cxx_std_20)
// TODO: https://github.com/hmenke/boost_matheval/search?q=multiplicative
#define BOOST_TEST_MAIN
#include <boost/test/included/unit_test.hpp>
#include <boost/multiprecision/number.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <stdexcept>
#include "release_assert.h"
// absl
#include "absl/strings/str_cat.h"
// fmt
#include "fmt/core.h"
// std
#include <iostream>
#define UNUSED_PARAM(X) static_cast<void>(X)
namespace mp = boost::multiprecision;
using boost::multiprecision::cpp_dec_float_100;
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
//absl::StatusOr<BigNum>
/*BigNum process(std::string_view input)
{
return BigNum{};
}*/
/*int main(int argc, char **argv)
{
//auto s1 = absl::StrCat("A string ", " another string", "yet another string");
//fmt::print( "{}\n", s1);
UNUSED_PARAM(argc);
UNUSED_PARAM(argv);
//RELEASE_ASSERT(process("(+ 2 4)") == ) << " not equal";
}*/
namespace Ast
{
enum Command { NO_CMD, TARGET, SENSOR, PAIR };
enum Modifier { NO_MODIFIER, ON, OFF, ERASE };
struct ModifiedCommand
{
Command cmd = NO_CMD;
Modifier mod = NO_MODIFIER;
};
struct OtherCommand
{
std::string token;
OtherCommand(std::string token = "") : token(std::move(token))
{ }
};
typedef boost::variant<int, double> Operand;
typedef boost::variant<Operand, ModifiedCommand, OtherCommand> RpnMachineInstruction;
typedef std::vector<RpnMachineInstruction> RpnMachineProgram;
// for printing, you can adapt this to execute the stack instead
struct Print : boost::static_visitor<std::ostream&>
{
Print(std::ostream& os) : os(os) {}
std::ostream& os;
std::ostream& operator()(Ast::Command cmd) const {
switch(cmd) {
case TARGET: return os << "TARGET" << " ";
case SENSOR: return os << "SENSOR" << " ";
case PAIR: return os << "PAIR" << " ";
case NO_CMD: return os << "NO_CMD" << " ";
default: return os << "#INVALID_COMMAND#" << " ";
}
}
std::ostream& operator()(Ast::Modifier mod) const {
switch(mod) {
case ON: return os << "[ON]" << " ";
case OFF: return os << "[OFF]" << " ";
case ERASE: return os << "[ERASE]" << " ";
case NO_MODIFIER: return os << "[NO_MODIFIER]" << " ";
default: return os << "#INVALID_MODIFIER#" << " ";
}
}
std::ostream& operator()(double d) const { return os << "double:" << d << " "; }
std::ostream& operator()(int i) const { return os << "int:" << i << " "; }
std::ostream& operator()(Ast::OtherCommand const& cmd) const {
return os << "'" << cmd.token << "'\n";
}
std::ostream& operator()(Ast::ModifiedCommand const& cmd) const {
(*this)(cmd.cmd);
(*this)(cmd.mod);
return os << "\n";
}
template <typename... TVariant>
std::ostream& operator()(boost::variant<TVariant...> const& v) const {
return boost::apply_visitor(*this, v);
}
};
}
BOOST_FUSION_ADAPT_STRUCT(Ast::ModifiedCommand, (Ast::Command, cmd)(Ast::Modifier, mod))
template <typename It, typename Skipper = qi::space_type>
struct RpnGrammar : qi::grammar<It, Ast::RpnMachineProgram(), Skipper>
{
RpnGrammar() : RpnGrammar::base_type(_start)
{
_command.add("TARGET", Ast::TARGET)("SENSOR", Ast::SENSOR)("PAIR", Ast::PAIR);
_modifier.add("ON", Ast::ON)("OFF", Ast::OFF)("ERASE", Ast::ERASE);
_start = *_instruction;
_instruction = _operand | _mod_command | _other_command;
_operand = _strict_double | qi::int_;
_mod_command = _command >> _modifier;
_other_command = qi::as_string [ +qi::char_("A-Z") ];
}
private:
qi::rule<It, Ast::RpnMachineProgram(), Skipper> _start;
qi::rule<It, Ast::RpnMachineInstruction(), Skipper> _instruction;
qi::rule<It, Ast::ModifiedCommand(), Skipper> _mod_command;
qi::rule<It, Ast::Operand(), Skipper> _operand;
// note: omitting the Skipper has the same effect as wrapping with `qi::lexeme`
qi::rule<It, Ast::OtherCommand()> _other_command;
qi::real_parser<double, boost::spirit::qi::strict_real_policies<double> > _strict_double;
qi::symbols<char, Ast::Command> _command;
qi::symbols<char, Ast::Modifier> _modifier;
};
// forth-style reverse-polish notation parser in boost spirit?
BOOST_AUTO_TEST_CASE(reverse_polish_notation)
{
std::stringstream ifs(R"raw(
0 1 HSFF
41 SENSOR ON
1 12.0 BH 4 LNON)raw");
typedef boost::spirit::istream_iterator SpiritIt;
RpnGrammar<SpiritIt> grammar;
SpiritIt f(ifs), l;
Ast::RpnMachineProgram program;
bool ok = qi::phrase_parse(f, l, grammar, qi::space, program);
if (ok)
{
std::cout << "Parse succeeded, " << program.size() << " stack instructions\n";
std::for_each(
program.begin(),
program.end(),
Ast::Print(std::cout));
}
else
{
std::cout << "Parse failed\n";
}
if (f != l)
{
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
}
template <typename To, typename From>
bool can_be_converted_to(From const& value) {
return value >= std::numeric_limits<To>::min() &&
value <= std::numeric_limits<To>::max();
}
template <typename To, typename From> //
To converted_to(From const& value) {
if (not can_be_converted_to<To, From>(value))
throw std::range_error(__PRETTY_FUNCTION__);
auto result = value.template convert_to<To>();
if (result != value)
throw std::range_error(__PRETTY_FUNCTION__);
return result;
}
template <typename To, typename From> void test(From const& value) {
auto display = [](auto v) {
if constexpr (sizeof(v)==1)
// avoid int8_t stupidly printing as char
return static_cast<int>(v);
else
return v;
};
try {
std::cout << "To " << boost::core::demangle(typeid(To).name())
<< " from " << value << ": ";
std::cout << display(converted_to<To>(value)) << "\n";
try {
From noise = value / 1e-50;
/*auto should_fail =*/converted_to<To>(From{value + noise});
std::cout << " -- WARNING: Fractional noise not detected" << std::endl;
} catch (std::range_error const&) { }
} catch (std::range_error const&) {
std::cout << "RANGE ERROR\n";
}
}
BOOST_AUTO_TEST_CASE(mp_cpp_dec_float_100_cases)
{
cpp_dec_float_100 cases[]{
1, -1,
127, -127,
128, -128,
129, -129,
255, -255,
1e5, -1e5,
1e10, -1e10,
1e100, -1e100,
1e1000l, -1e1000l,
cpp_dec_float_100("1e10000"), cpp_dec_float_100("-1e10000"),
cpp_dec_float_100(std::numeric_limits<double>::max()),
cpp_dec_float_100(std::numeric_limits<long double>::max()),
cpp_dec_float_100(std::numeric_limits<double>::infinity()),
cpp_dec_float_100(-std::numeric_limits<double>::infinity()),
};
for (auto num : cases) test<int8_t>(num);
for (auto num : cases) test<uint8_t>(num);
for (auto num : cases) test<int32_t>(num);
for (auto num : cases) test<int64_t>(num);
for (auto num : cases) test<float>(num);
for (auto num : cases) test<double>(num);
for (auto num : cases) test<long double>(num);
// special cases
for (auto num :
{
cpp_dec_float_100{"inf"},
cpp_dec_float_100{"-inf"},
cpp_dec_float_100{"nan"},
}) //
{
test<long double>(num);
}
}
BOOST_AUTO_TEST_CASE(mp_cpp_int)
{
using Int = mp::cpp_int;
// let's think of a nice large number
Int n = 1;
for (Int f = 42; f>0; --f)
n *= f;
// let's convert it to cpp_dec_float
// and... do something with it
using Dec = mp::number<mp::cpp_dec_float<0> >;
BOOST_CHECK_EQUAL(n.str(), "1405006117752879898543142606244511569936384000000000");
BOOST_CHECK_EQUAL(n.convert_to<Dec>().str(), "1.4050061177514245973e+51");
}
bool testRandKBitBignum(int k_bits)
{
CBigNum x = CBigNum::randKBitBignum(k_bits);
return (x.bitSize() <= k_bits);
}
bool testRandBignum(CBigNum limit)
{
CBigNum x = CBigNum::randBignum(limit);
return 0 <= x && x < limit;
}
std::string zerocoinModulus = "25195908475657893494027183240048398571429282126204032027777137836043662020707595556264018525880784"
"4069182906412495150821892985591491761845028084891200728449926873928072877767359714183472702618963750149718246911"
"6507761337985909570009733045974880842840179742910064245869181719511874612151517265463228221686998754918242243363"
"7259085141865462043576798423387184774447920739934236584823824281198163815010674810451660377306056201619676256133"
"8441436038339044149526344321901146575444541784240209246165157233507787077498171257724679629263863563732899121548"
"31438167899885040445364023527381951378636564391212010397122822120720357";
std::string strHexModulus = "c7970ceedcc3b0754490201a7aa613cd73911081c790f5f1a8726f463550bb5b7ff0db8e1ea1189ec72f93d1650011bd721aeeacc2acde32a04107f0648c2813a31f5b0b7765ff8b44b4b6ffc93384b646eb09c7cf5e8592d40ea33c80039f35b4f14a04b51f7bfd781be4d1673164ba8eb991c2c4d730bbbe35f592bdef524af7e8daefd26c66fc02c479af89d64d373f442709439de66ceb955f3ea37d5159f6135809f85334b5cb1813addc80cd05609f10ac6a95ad65872c909525bdad32bc729592642920f24c61dc5b3c3b7923e56b16a4d9d373d8721f24a3fc0f1b3131f55615172866bccc30f95054c824e733a5eb6817f7bc16399d48c6361cc7e5";
BOOST_AUTO_TEST_CASE(bignum_setdecimal)
{
CBigNum bnDec;
bnDec.SetDec(zerocoinModulus);
CBigNum bnHex;
bnHex.SetHex(strHexModulus);
BOOST_CHECK_MESSAGE(bnDec == bnHex, "CBigNum.SetDec() does not work correctly");
}
std::string negstrHexModulus = "-c7970ceedcc3b0754490201a7aa613cd73911081c790f5f1a8726f463550bb5b7ff0db8e1ea1189ec72f93d1650011bd721aeeacc2acde32a04107f0648c2813a31f5b0b7765ff8b44b4b6ffc93384b646eb09c7cf5e8592d40ea33c80039f35b4f14a04b51f7bfd781be4d1673164ba8eb991c2c4d730bbbe35f592bdef524af7e8daefd26c66fc02c479af89d64d373f442709439de66ceb955f3ea37d5159f6135809f85334b5cb1813addc80cd05609f10ac6a95ad65872c909525bdad32bc729592642920f24c61dc5b3c3b7923e56b16a4d9d373d8721f24a3fc0f1b3131f55615172866bccc30f95054c824e733a5eb6817f7bc16399d48c6361cc7e5";
std::string str_a = "775897c5463939bf29a02816aba7b1741162e1f6b052cd32fec36c44dfee7d4b5162de78bb0b448cb305b0a9bd7e006aec62d7c1e94a31003c2decbdc6fd7c9b261cb88801c51e7cee71a215ff113ccbd02069cf29671e6302944ca5780a2f626eb9046fa6872968addc93c74d09cf6b2872bc4c6bd08e89324cc7e9fb921488";
std::string str_b = "-775897c5463939bf29a02816aba7b1741162e1f6b052cd32fec36c44dfee7d4b5162de78bb0b448cb305b0a9bd7e006aec62d7c1e94a31003c2decbdc6fd7c9b261cb88801c51e7cee71a215ff113ccbd02069cf29671e6302944ca5780a2f626eb9046fa6872968addc93c74d09cf6b2872bc4c6bd08e89324cc7e9fb921488";
BOOST_AUTO_TEST_CASE(bignum_basic_tests)
{
CBigNum bn, bn2;
std::vector<unsigned char> vch;
bn.SetHex(strHexModulus);
vch = bn.getvch();
bn2.setvch(vch);
BOOST_CHECK_MESSAGE(bn2 == bn, "CBigNum.setvch() or CBigNum.getvch() does not work correctly");
bn.SetHex(negstrHexModulus);
vch = bn.getvch();
bn2.setvch(vch);
BOOST_CHECK_MESSAGE(bn2 == bn, "CBigNum.setvch() or CBigNum.getvch() does not work correctly");
bn.SetHex(str_a);
vch = bn.getvch();
bn2.setvch(vch);
BOOST_CHECK_MESSAGE(bn2 == bn, "CBigNum.setvch() or CBigNum.getvch() does not work correctly");
bn.SetHex(str_b);
vch = bn.getvch();
bn2.setvch(vch);
BOOST_CHECK_MESSAGE(bn2 == bn, "CBigNum.setvch() or CBigNum.getvch() does not work correctly");
}
BOOST_AUTO_TEST_CASE(bignum_random_generation_tests)
{
for(int i=1; i<3000; i++) {
BOOST_CHECK_MESSAGE(testRandKBitBignum(i), strprintf("CBigNum::randKBitBignum(%d) failed", i));
}
for(int i=1; i<3000; i++) {
CBigNum x = 1 + CBigNum::randKBitBignum(i);
BOOST_CHECK_MESSAGE(testRandBignum(x), strprintf("CBigNum::randBignum(x) failed with x=%s", x.ToString()));
}
}
/** A selection of numbers that do not trigger int64_t overflow
* when added/subtracted. */
static const int64_t values[] = { 0, 1, -2, 127, 128, -255, 256, (1LL << 15) - 1, -(1LL << 16), (1LL << 24) - 1, (1LL << 31), 1 - (1LL << 32), 1LL << 40 };
static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000};
template<typename RHS, typename LHS>
static void CheckCompare(LHS num1, RHS num2)
{
const CBigNum bignum1(num1);
const CBigNum bignum2(num2);
BOOST_CHECK((bignum1 == bignum1) == (num1 == num1));
BOOST_CHECK((bignum1 != bignum1) == (num1 != num1));
BOOST_CHECK((bignum1 < bignum1) == (num1 < num1));
BOOST_CHECK((bignum1 > bignum1) == (num1 > num1));
BOOST_CHECK((bignum1 >= bignum1) == (num1 >= num1));
BOOST_CHECK((bignum1 <= bignum1) == (num1 <= num1));
BOOST_CHECK((bignum1 == bignum1) == (num1 == num1));
BOOST_CHECK((bignum1 != bignum1) == (num1 != num1));
BOOST_CHECK((bignum1 < bignum1) == (num1 < num1));
BOOST_CHECK((bignum1 > bignum1) == (num1 > num1));
BOOST_CHECK((bignum1 >= bignum1) == (num1 >= num1));
BOOST_CHECK((bignum1 <= bignum1) == (num1 <= num1));
BOOST_CHECK((bignum1 == bignum2) == (num1 == num2));
BOOST_CHECK((bignum1 != bignum2) == (num1 != num2));
BOOST_CHECK((bignum1 < bignum2) == (num1 < num2));
BOOST_CHECK((bignum1 > bignum2) == (num1 > num2));
BOOST_CHECK((bignum1 >= bignum2) == (num1 >= num2));
BOOST_CHECK((bignum1 <= bignum2) == (num1 <= num2));
BOOST_CHECK((bignum1 == bignum2) == (num1 == num2));
BOOST_CHECK((bignum1 != bignum2) == (num1 != num2));
BOOST_CHECK((bignum1 < bignum2) == (num1 < num2));
BOOST_CHECK((bignum1 > bignum2) == (num1 > num2));
BOOST_CHECK((bignum1 >= bignum2) == (num1 >= num2));
BOOST_CHECK((bignum1 <= bignum2) == (num1 <= num2));
}
static void RunOperators(const long& num1, const int64_t& num2)
{
CheckCompare(num1, num2);
}
BOOST_AUTO_TEST_CASE(operators)
{
for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
{
for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
{
RunOperators(values[i], values[i]);
RunOperators(values[i], -values[i]);
RunOperators(values[i], values[j]);
RunOperators(values[i], -values[j]);
RunOperators(values[i] + values[j], values[j]);
RunOperators(values[i] + values[j], -values[j]);
RunOperators(values[i] - values[j], values[j]);
RunOperators(values[i] - values[j], -values[j]);
RunOperators(values[i] + values[j], values[i] + values[j]);
RunOperators(values[i] + values[j], values[i] - values[j]);
RunOperators(values[i] - values[j], values[i] + values[j]);
RunOperators(values[i] - values[j], values[i] - values[j]);
}
}
}
#include "release_assert.h"
#include <cstdio>
#include <limits>
#include <cstdint>
#include <cinttypes>
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#include "arith_uint256.h"
#include "crypto/common.h"
#include "utilstrencodings.h"*/
#include <stdio.h>
#include <string.h>
template <unsigned int BITS>
base_uint<BITS>::base_uint(const std::string& str)
{
SetHex(str);
}
template <unsigned int BITS>
base_uint<BITS>::base_uint(const std::vector<unsigned char>& vch)
{
if (vch.size() != sizeof(pn))
throw uint_error("Converting vector of wrong size to base_uint");
memcpy(pn, &vch[0], sizeof(pn));
}
template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift)
{
base_uint<BITS> a(*this);
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
int k = shift / 32;
shift = shift % 32;
for (int i = 0; i < WIDTH; i++) {
if (i + k + 1 < WIDTH && shift != 0)
pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
if (i + k < WIDTH)
pn[i + k] |= (a.pn[i] << shift);
}
return *this;
}
template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift)
{
base_uint<BITS> a(*this);
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
int k = shift / 32;
shift = shift % 32;
for (int i = 0; i < WIDTH; i++) {
if (i - k - 1 >= 0 && shift != 0)
pn[i - k - 1] |= (a.pn[i] << (32 - shift));
if (i - k >= 0)
pn[i - k] |= (a.pn[i] >> shift);
}
return *this;
}
template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32)
{
uint64_t carry = 0;
for (int i = 0; i < WIDTH; i++) {
uint64_t n = carry + (uint64_t)b32 * pn[i];
pn[i] = n & 0xffffffff;
carry = n >> 32;
}
return *this;
}
template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b)
{
base_uint<BITS> a = *this;
*this = 0;
for (int j = 0; j < WIDTH; j++) {
uint64_t carry = 0;
for (int i = 0; i + j < WIDTH; i++) {
uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i];
pn[i + j] = n & 0xffffffff;
carry = n >> 32;
}
}
return *this;
}
template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b)
{
base_uint<BITS> div = b; // make a copy, so we can shift.
base_uint<BITS> num = *this; // make a copy, so we can subtract.
*this = 0; // the quotient.
int num_bits = num.bits();
int div_bits = div.bits();
if (div_bits == 0)
throw uint_error("Division by zero");
if (div_bits > num_bits) // the result is certainly 0.
return *this;
int shift = num_bits - div_bits;
div <<= shift; // shift so that div and num align.
while (shift >= 0) {
if (num >= div) {
num -= div;
pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
}
div >>= 1; // shift back.
shift--;
}
// num now contains the remainder of the division.
return *this;
}
template <unsigned int BITS>
int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const
{
for (int i = WIDTH - 1; i >= 0; i--) {
if (pn[i] < b.pn[i])
return -1;
if (pn[i] > b.pn[i])
return 1;
}
return 0;
}
template <unsigned int BITS>
bool base_uint<BITS>::EqualTo(uint64_t b) const
{
for (int i = WIDTH - 1; i >= 2; i--) {
if (pn[i])
return false;
}
if (pn[1] != (b >> 32))
return false;
if (pn[0] != (b & 0xfffffffful))
return false;
return true;
}
template <unsigned int BITS>
double base_uint<BITS>::getdouble() const
{
double ret = 0.0;
double fact = 1.0;
for (int i = 0; i < WIDTH; i++) {
ret += fact * pn[i];
fact *= 4294967296.0;
}
return ret;
}
template <unsigned int BITS>
std::string base_uint<BITS>::GetHex() const
{
char psz[sizeof(pn) * 2 + 1];
for (unsigned int i = 0; i < sizeof(pn); i++)
sprintf(psz + i * 2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
return std::string(psz, psz + sizeof(pn) * 2);
}
template <unsigned int BITS>
void base_uint<BITS>::SetHex(const char* psz)
{
memset(pn, 0, sizeof(pn));
// skip leading spaces
while (isspace(*psz))
psz++;
// skip 0x
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
// hex string to uint
const char* pbegin = psz;
while (::HexDigit(*psz) != -1)
psz++;
psz--;
unsigned char* p1 = (unsigned char*)pn;
unsigned char* pend = p1 + WIDTH * 4;
while (psz >= pbegin && p1 < pend) {
*p1 = ::HexDigit(*psz--);
if (psz >= pbegin) {
*p1 |= ((unsigned char)::HexDigit(*psz--) << 4);
p1++;
}
}
}
template <unsigned int BITS>
void base_uint<BITS>::SetHex(const std::string& str)
{
SetHex(str.c_str());
}
template <unsigned int BITS>
std::string base_uint<BITS>::ToString() const
{
return (GetHex());
}
template <unsigned int BITS>
std::string base_uint<BITS>::ToStringReverseEndian() const
{
char psz[sizeof(pn) * 2 + 1];
for (unsigned int i = 0; i < sizeof(pn); i++)
sprintf(psz + i * 2, "%02x", ((unsigned char*)pn)[i]);
return std::string(psz, psz + sizeof(pn) * 2);
}
template <unsigned int BITS>
unsigned int base_uint<BITS>::bits() const
{
for (int pos = WIDTH - 1; pos >= 0; pos--) {
if (pn[pos]) {
for (int bits = 31; bits > 0; bits--) {
if (pn[pos] & 1 << bits)
return 32 * pos + bits + 1;
}
return 32 * pos + 1;
}
}
return 0;
}
// Explicit instantiations for base_uint<160>
template base_uint<160>::base_uint(const std::string&);
template base_uint<160>::base_uint(const std::vector<unsigned char>&);
template base_uint<160>& base_uint<160>::operator<<=(unsigned int);
template base_uint<160>& base_uint<160>::operator>>=(unsigned int);
template base_uint<160>& base_uint<160>::operator*=(uint32_t b32);
template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b);
template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b);
template int base_uint<160>::CompareTo(const base_uint<160>&) const;
template bool base_uint<160>::EqualTo(uint64_t) const;
template double base_uint<160>::getdouble() const;
template std::string base_uint<160>::GetHex() const;
template std::string base_uint<160>::ToString() const;
template void base_uint<160>::SetHex(const char*);
template void base_uint<160>::SetHex(const std::string&);
template unsigned int base_uint<160>::bits() const;
// Explicit instantiations for base_uint<256>
template base_uint<256>::base_uint(const std::string&);
template base_uint<256>::base_uint(const std::vector<unsigned char>&);
template base_uint<256>& base_uint<256>::operator<<=(unsigned int);
template base_uint<256>& base_uint<256>::operator>>=(unsigned int);
template base_uint<256>& base_uint<256>::operator*=(uint32_t b32);
template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b);
template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b);
template int base_uint<256>::CompareTo(const base_uint<256>&) const;
template bool base_uint<256>::EqualTo(uint64_t) const;
template double base_uint<256>::getdouble() const;
template std::string base_uint<256>::GetHex() const;
template std::string base_uint<256>::ToString() const;
template void base_uint<256>::SetHex(const char*);
template void base_uint<256>::SetHex(const std::string&);
template unsigned int base_uint<256>::bits() const;
template std::string base_uint<256>::ToStringReverseEndian() const;
// Explicit instantiations for base_uint<512>
template base_uint<512>::base_uint(const std::string&);
template base_uint<512>& base_uint<512>::operator<<=(unsigned int);
template base_uint<512>& base_uint<512>::operator>>=(unsigned int);
template std::string base_uint<512>::GetHex() const;
template std::string base_uint<512>::ToString() const;
template std::string base_uint<512>::ToStringReverseEndian() const;
// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
arith_uint256& arith_uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow)
{
int nSize = nCompact >> 24;
uint32_t nWord = nCompact & 0x007fffff;
if (nSize <= 3) {
nWord >>= 8 * (3 - nSize);
*this = nWord;
} else {
*this = nWord;
*this <<= 8 * (nSize - 3);
}
if (pfNegative)
*pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
if (pfOverflow)
*pfOverflow = nWord != 0 && ((nSize > 34) ||
(nWord > 0xff && nSize > 33) ||
(nWord > 0xffff && nSize > 32));
return *this;
}
uint32_t arith_uint256::GetCompact(bool fNegative) const
{
int nSize = (bits() + 7) / 8;
uint32_t nCompact = 0;
if (nSize <= 3) {
nCompact = GetLow64() << 8 * (3 - nSize);
} else {
arith_uint256 bn = *this >> 8 * (nSize - 3);
nCompact = bn.GetLow64();
}
// The 0x00800000 bit denotes the sign.
// Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
if (nCompact & 0x00800000) {
nCompact >>= 8;
nSize++;
}
assert((nCompact & ~0x007fffff) == 0);
assert(nSize < 256);
nCompact |= nSize << 24;
nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
return nCompact;
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2019 The PIVX developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#include "bignum.h"
CBigNum::CBigNum()
{
bn = BN_new();
}
CBigNum::CBigNum(const CBigNum& b)
{
bn = BN_new();
if (!BN_copy(bn, b.bn))
{
BN_clear_free(bn);
throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed");
}
}
CBigNum& CBigNum::operator=(const CBigNum& b)
{
if (!BN_copy(bn, b.bn))
throw bignum_error("CBigNum::operator= : BN_copy failed");
return (*this);
}
CBigNum::~CBigNum()
{
BN_clear_free(bn);
}
//CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
CBigNum::CBigNum(signed char n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(short n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(int n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(long n) { bn = BN_new(); if (n >= 0) setulong(n); else setint64(n); }
CBigNum::CBigNum(long long n) { bn = BN_new(); setint64(n); }
CBigNum::CBigNum(unsigned char n) { bn = BN_new(); setulong(n); }
CBigNum::CBigNum(unsigned short n) { bn = BN_new(); setulong(n); }
CBigNum::CBigNum(unsigned int n) { bn = BN_new(); setulong(n); }
CBigNum::CBigNum(unsigned long n) { bn = BN_new(); setulong(n); }
CBigNum::CBigNum(unsigned long long n) { bn = BN_new(); setuint64(n); }
CBigNum::CBigNum(uint256 n) { bn = BN_new(); setuint256(n); }
CBigNum::CBigNum(const std::vector<unsigned char>& vch)
{
bn = BN_new();
setvch(vch);
}
/** Generates a cryptographically secure random number between zero and range-1 (inclusive)
* i.e. 0 <= returned number < range
* @param range The upper bound on the number.
* @return
*/
CBigNum CBigNum::randBignum(const CBigNum& range)
{
CBigNum ret;
if(!BN_rand_range(ret.bn, range.bn)){
throw bignum_error("CBigNum:rand element : BN_rand_range failed");
}
return ret;
}
/** Generates a cryptographically secure random k-bit number
* @param k The bit length of the number.
* @return
*/
CBigNum CBigNum::randKBitBignum(const uint32_t k)
{
CBigNum ret;
if(!BN_rand(ret.bn, k, -1, 0)){
throw bignum_error("CBigNum:rand element : BN_rand failed");
}
return ret;
}
/**Returns the size in bits of the underlying bignum.
*
* @return the size
*/
int CBigNum::bitSize() const
{
return BN_num_bits(bn);
}
void CBigNum::setulong(unsigned long n)
{
if (!BN_set_word(bn, n))
throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed");
}
unsigned long CBigNum::getulong() const
{
return BN_get_word(bn);
}
unsigned int CBigNum::getuint() const
{
return BN_get_word(bn);
}
int CBigNum::getint() const
{
unsigned long n = BN_get_word(bn);
if (!BN_is_negative(bn))
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::max() : n);
else
return (n > (unsigned long)std::numeric_limits<int>::max() ? std::numeric_limits<int>::min() : -(int)n);
}
void CBigNum::setint64(int64_t sn)
{
unsigned char pch[sizeof(sn) + 6];
unsigned char* p = pch + 4;
bool fNegative;
uint64_t n;
if (sn < (int64_t)0)
{
// Since the minimum signed integer cannot be represented as positive so long as its type is signed,
// and it's not well-defined what happens if you make it unsigned before negating it,
// we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate
n = -(sn + 1);
++n;
fNegative = true;
} else {
n = sn;
fNegative = false;
}
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = (fNegative ? 0x80 : 0);
else if (fNegative)
c |= 0x80;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, bn);
}
void CBigNum::setuint64(uint64_t n)
{
unsigned char pch[sizeof(n) + 6];
unsigned char* p = pch + 4;
bool fLeadingZeroes = true;
for (int i = 0; i < 8; i++)
{
unsigned char c = (n >> 56) & 0xff;
n <<= 8;
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = 0;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize) & 0xff;
BN_mpi2bn(pch, p - pch, bn);
}
void CBigNum::setuint256(uint256 n)
{
unsigned char pch[sizeof(n) + 6];
unsigned char* p = pch + 4;
bool fLeadingZeroes = true;
unsigned char* pbegin = (unsigned char*)&n;
unsigned char* psrc = pbegin + sizeof(n);
while (psrc != pbegin)
{
unsigned char c = *(--psrc);
if (fLeadingZeroes)
{
if (c == 0)
continue;
if (c & 0x80)
*p++ = 0;
fLeadingZeroes = false;
}
*p++ = c;
}
unsigned int nSize = p - (pch + 4);
pch[0] = (nSize >> 24) & 0xff;
pch[1] = (nSize >> 16) & 0xff;
pch[2] = (nSize >> 8) & 0xff;
pch[3] = (nSize >> 0) & 0xff;
BN_mpi2bn(pch, p - pch, bn);
}
uint256 CBigNum::getuint256() const
{
if(bitSize() > 256) {
throw std::range_error("cannot convert to uint256, bignum longer than 256 bits");
}
unsigned int nSize = BN_bn2mpi(bn, NULL);
if (nSize < 4)
return 0;
std::vector<unsigned char> vch(nSize);
BN_bn2mpi(bn, &vch[0]);
if (vch.size() > 4)
vch[4] &= 0x7f;
uint256 n = 0;
for (unsigned int i = 0, j = vch.size()-1; i < sizeof(n) && j >= 4; i++, j--)
((unsigned char*)&n)[i] = vch[j];
return n;
}
void CBigNum::setvch(const std::vector<unsigned char>& vch)
{
std::vector<unsigned char> vch2(vch.size() + 4);
unsigned int nSize = vch.size();
// BIGNUM's byte stream format expects 4 bytes of
// big endian size data info at the front
vch2[0] = (nSize >> 24) & 0xff;
vch2[1] = (nSize >> 16) & 0xff;
vch2[2] = (nSize >> 8) & 0xff;
vch2[3] = (nSize >> 0) & 0xff;
// swap data to big endian
reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4);
BN_mpi2bn(&vch2[0], vch2.size(), bn);
}
std::vector<unsigned char> CBigNum::getvch() const
{
unsigned int nSize = BN_bn2mpi(bn, NULL);
if (nSize <= 4)
return std::vector<unsigned char>();
std::vector<unsigned char> vch(nSize);
BN_bn2mpi(bn, &vch[0]);
vch.erase(vch.begin(), vch.begin() + 4);
reverse(vch.begin(), vch.end());
return vch;
}
void CBigNum::SetDec(const std::string& str)
{
BN_dec2bn(&bn, str.c_str());
}
bool CBigNum::SetHexBool(const std::string& str)
{
// skip 0x
const char* psz = str.c_str();
while (isspace(*psz))
psz++;
bool fNegative = false;
if (*psz == '-')
{
fNegative = true;
psz++;
}
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
while (isspace(*psz))
psz++;
// hex string to bignum
static const signed char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
*this = 0;
while (isxdigit(*psz))
{
*this <<= 4;
int n = phexdigit[(unsigned char)*psz++];
*this += n;
}
if (fNegative)
*this = 0 - *this;
return true;
}
std::string CBigNum::ToString(int nBase) const
{
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
CBigNum locBn = *this;
std::string str;
BN_set_negative(locBn.bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp(locBn.bn, bn0.bn) == 0)
return "0";
while (BN_cmp(locBn.bn, bn0.bn) > 0)
{
if (!BN_div(dv.bn, rem.bn, locBn.bn, bnBase.bn, pctx))
throw bignum_error("CBigNum::ToString() : BN_div failed");
locBn = dv;
unsigned int c = rem.getulong();
str += "0123456789abcdef"[c];
}
if (BN_is_negative(bn))
str += "-";
reverse(str.begin(), str.end());
return str;
}
/**
* exponentiation this^e
* @param e the exponent
* @return
*/
CBigNum CBigNum::pow(const CBigNum& e) const
{
CAutoBN_CTX pctx;
CBigNum ret;
if (!BN_exp(ret.bn, bn, e.bn, pctx))
throw bignum_error("CBigNum::pow : BN_exp failed");
return ret;
}
/**
* modular multiplication: (this * b) mod m
* @param b operand
* @param m modulus
*/
CBigNum CBigNum::mul_mod(const CBigNum& b, const CBigNum& m) const
{
CAutoBN_CTX pctx;
CBigNum ret;
if (!BN_mod_mul(ret.bn, bn, b.bn, m.bn, pctx))
throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed");
return ret;
}
/**
* modular exponentiation: this^e mod n
* @param e exponent
* @param m modulus
*/
CBigNum CBigNum::pow_mod(const CBigNum& e, const CBigNum& m) const
{
CAutoBN_CTX pctx;
CBigNum ret;
if( e < 0){
// g^-x = (g^-1)^x
CBigNum inv = this->inverse(m);
CBigNum posE = e * -1;
if (!BN_mod_exp(ret.bn, inv.bn, posE.bn, m.bn, pctx))
throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent");
}else
if (!BN_mod_exp(ret.bn, bn, e.bn, m.bn, pctx))
throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed");
return ret;
}
/**
* Calculates the inverse of this element mod m.
* i.e. i such this*i = 1 mod m
* @param m the modu
* @return the inverse
*/
CBigNum CBigNum::inverse(const CBigNum& m) const
{
CAutoBN_CTX pctx;
CBigNum ret;
if (!BN_mod_inverse(ret.bn, bn, m.bn, pctx))
throw bignum_error("CBigNum::inverse*= :BN_mod_inverse");
return ret;
}
/**
* Generates a random (safe) prime of numBits bits
* @param numBits the number of bits
* @param safe true for a safe prime
* @return the prime
*/
CBigNum CBigNum::generatePrime(const unsigned int numBits, bool safe)
{
CBigNum ret;
if(!BN_generate_prime_ex(ret.bn, numBits, (safe == true), NULL, NULL, NULL))
throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex");
return ret;
}
/**
* Calculates the greatest common divisor (GCD) of two numbers.
* @param m the second element
* @return the GCD
*/
CBigNum CBigNum::gcd( const CBigNum& b) const
{
CAutoBN_CTX pctx;
CBigNum ret;
if (!BN_gcd(ret.bn, bn, b.bn, pctx))
throw bignum_error("CBigNum::gcd*= :BN_gcd");
return ret;
}
/**
* Miller-Rabin primality test on this element
* @param checks: optional, the number of Miller-Rabin tests to run
* default causes error rate of 2^-80.
* @return true if prime
*/
/*bool CBigNum::isPrime(const int checks) const
{
CAutoBN_CTX pctx;
int ret = BN_is_prime_ex(bn, checks, pctx, NULL);
if(ret < 0){
throw bignum_error("CBigNum::isPrime :BN_is_prime");
}
return ret;
}*/
bool CBigNum::isOne() const
{
return BN_is_one(bn);
}
bool CBigNum::operator!() const
{
return BN_is_zero(bn);
}
CBigNum& CBigNum::operator+=(const CBigNum& b)
{
if (!BN_add(bn, bn, b.bn))
throw bignum_error("CBigNum::operator+= : BN_add failed");
return *this;
}
CBigNum& CBigNum::operator-=(const CBigNum& b)
{
if (!BN_sub(bn, bn, b.bn))
throw bignum_error("CBigNum::operator-= : BN_sub failed");
return *this;
}
CBigNum& CBigNum::operator*=(const CBigNum& b)
{
CAutoBN_CTX pctx;
if (!BN_mul(bn, bn, b.bn, pctx))
throw bignum_error("CBigNum::operator*= : BN_mul failed");
return *this;
}
CBigNum& CBigNum::operator<<=(unsigned int shift)
{
if (!BN_lshift(bn, bn, shift))
throw bignum_error("CBigNum:operator<<= : BN_lshift failed");
return *this;
}
CBigNum& CBigNum::operator>>=(unsigned int shift)
{
// Note: BN_rshift segfaults on 64-bit if 2^shift is greater than the number
// if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL
CBigNum a = 1;
a <<= shift;
if (BN_cmp(a.bn, bn) > 0)
{
bn = 0;
return *this;
}
if (!BN_rshift(bn, bn, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this;
}
CBigNum& CBigNum::operator++()
{
// prefix operator
if (!BN_add(bn, bn, BN_value_one()))
throw bignum_error("CBigNum::operator++ : BN_add failed");
return *this;
}
CBigNum& CBigNum::operator--()
{
// prefix operator
CBigNum r;
if (!BN_sub(r.bn, bn, BN_value_one()))
throw bignum_error("CBigNum::operator-- : BN_sub failed");
bn = r.bn;
return *this;
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2017-2019 The PIVX developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#include "uint256.h"
#include "crypto/common.h"*/
/** Old classes definitions **/
// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
uint256& uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow)
{
int nSize = nCompact >> 24;
uint32_t nWord = nCompact & 0x007fffff;
if (nSize <= 3) {
nWord >>= 8 * (3 - nSize);
*this = nWord;
} else {
*this = nWord;
*this <<= 8 * (nSize - 3);
}
if (pfNegative)
*pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
if (pfOverflow)
*pfOverflow = nWord != 0 && ((nSize > 34) ||
(nWord > 0xff && nSize > 33) ||
(nWord > 0xffff && nSize > 32));
return *this;
}
uint32_t uint256::GetCompact(bool fNegative) const
{
int nSize = (bits() + 7) / 8;
uint32_t nCompact = 0;
if (nSize <= 3) {
nCompact = GetLow64() << 8 * (3 - nSize);
} else {
uint256 bn = *this >> 8 * (nSize - 3);
nCompact = bn.GetLow64();
}
// The 0x00800000 bit denotes the sign.
// Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
if (nCompact & 0x00800000) {
nCompact >>= 8;
nSize++;
}
assert((nCompact & ~0x007fffff) == 0);
assert(nSize < 256);
nCompact |= nSize << 24;
nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
return nCompact;
}
uint256 ArithToUint256(const arith_uint256 &a)
{
uint256 b;
for(int x=0; x<a.WIDTH; ++x)
WriteLE32(b.begin() + x*4, a.pn[x]);
return b;
}
arith_uint256 UintToArith256(const uint256 &a)
{
arith_uint256 b;
for(int x=0; x<b.WIDTH; ++x)
b.pn[x] = ReadLE32(a.begin() + x*4);
return b;
}
uint512 ArithToUint512(const arith_uint512 &a)
{
uint512 b;
for(int x=0; x<a.WIDTH; ++x)
WriteLE32(b.begin() + x*4, a.pn[x]);
return b;
}
arith_uint512 UintToArith512(const uint512 &a)
{
arith_uint512 b;
for(int x=0; x<b.WIDTH; ++x)
b.pn[x] = ReadLE32(a.begin() + x*4);
return b;
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2016-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#include "utilstrencodings.h"
//#include "tinyformat.h"
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <limits>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static const std::string SAFE_CHARS[] =
{
CHARS_ALPHA_NUM + " .,;-_/:?@()", // SAFE_CHARS_DEFAULT
CHARS_ALPHA_NUM + " .,;-_?@", // SAFE_CHARS_UA_COMMENT
CHARS_ALPHA_NUM + ".-_", // SAFE_CHARS_FILENAME
};
std::string SanitizeString(const std::string& str, int rule)
{
std::string strResult;
for (std::string::size_type i = 0; i < str.size(); i++)
{
if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
strResult.push_back(str[i]);
}
return strResult;
}
bool validateURL(std::string strURL, std::string& strErr, unsigned int maxSize) {
// Check URL size
if (strURL.size() > maxSize) {
strErr = strprintf("Invalid URL: %d exceeds limit of %d characters.", strURL.size(), maxSize);
return false;
}
std::vector<std::string> reqPre;
// Required initial strings; URL must contain one
reqPre.push_back("http://");
reqPre.push_back("https://");
// check fronts
bool found = false;
for (int i=0; i < (int) reqPre.size() && !found; i++) {
if (strURL.find(reqPre[i]) == 0) found = true;
}
if ((!found) && (reqPre.size() > 0)) {
strErr = "Invalid URL, check scheme (e.g. https://)";
return false;
}
return true;
}
const signed char p_util_hexdigit[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
signed char HexDigit(char c)
{
return p_util_hexdigit[(unsigned char)c];
}
bool IsHex(const std::string& str)
{
for (std::string::const_iterator it(str.begin()); it != str.end(); ++it) {
if (HexDigit(*it) < 0)
return false;
}
return (str.size() > 0) && (str.size() % 2 == 0);
}
std::vector<unsigned char> ParseHex(const char* psz)
{
// convert hex dump to vector
std::vector<unsigned char> vch;
while (true) {
while (isspace(*psz))
psz++;
signed char c = HexDigit(*psz++);
if (c == (signed char)-1)
break;
unsigned char n = (c << 4);
c = HexDigit(*psz++);
if (c == (signed char)-1)
break;
n |= c;
vch.push_back(n);
}
return vch;
}
std::vector<unsigned char> ParseHex(const std::string& str)
{
return ParseHex(str.c_str());
}
std::string EncodeBase64(const unsigned char* pch, size_t len)
{
static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string str;
str.reserve(((len + 2) / 3) * 4);
ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, pch, pch + len);
while (str.size() % 4) str += '=';
return str;
}
std::string EncodeBase64(const std::string& str)
{
return EncodeBase64((const unsigned char*)str.c_str(), str.size());
}
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
{
static const int decode64_table[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
const char* e = p;
std::vector<uint8_t> val;
val.reserve(strlen(p));
while (*p != 0) {
int x = decode64_table[(unsigned char)*p];
if (x == -1) break;
val.push_back(x);
++p;
}
std::vector<unsigned char> ret;
ret.reserve((val.size() * 3) / 4);
bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
const char* q = p;
while (valid && *p != 0) {
if (*p != '=') {
valid = false;
break;
}
++p;
}
valid = valid && (p - e) % 4 == 0 && p - q < 4;
if (pfInvalid) *pfInvalid = !valid;
return ret;
}
std::string DecodeBase64(const std::string& str)
{
std::vector<unsigned char> vchRet = DecodeBase64(str.c_str());
return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size());
}
// Base64 encoding with secure memory allocation
SecureString EncodeBase64Secure(const SecureString& input)
{
// Init openssl BIO with base64 filter and memory output
BIO *b64, *mem;
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // No newlines in output
mem = BIO_new(BIO_s_mem());
BIO_push(b64, mem);
// Decode the string
BIO_write(b64, &input[0], input.size());
(void)BIO_flush(b64);
// Create output variable from buffer mem ptr
BUF_MEM* bptr;
BIO_get_mem_ptr(b64, &bptr);
SecureString output(bptr->data, bptr->length);
// Cleanse secure data buffer from memory
memory_cleanse((void*)bptr->data, bptr->length);
// Free memory
BIO_free_all(b64);
return output;
}
std::string EncodeBase32(const unsigned char* pch, size_t len)
{
static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
std::string str;
str.reserve(((len + 4) / 5) * 8);
ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, pch, pch + len);
while (str.size() % 8) str += '=';
return str;
}
std::string EncodeBase32(const std::string& str)
{
return EncodeBase32((const unsigned char*)str.c_str(), str.size());
}
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
{
static const int decode32_table[256] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
const char* e = p;
std::vector<uint8_t> val;
val.reserve(strlen(p));
while (*p != 0) {
int x = decode32_table[(unsigned char)*p];
if (x == -1) break;
val.push_back(x);
++p;
}
std::vector<unsigned char> ret;
ret.reserve((val.size() * 5) / 8);
bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
const char* q = p;
while (valid && *p != 0) {
if (*p != '=') {
valid = false;
break;
}
++p;
}
valid = valid && (p - e) % 8 == 0 && p - q < 8;
if (pfInvalid) *pfInvalid = !valid;
return ret;
}
std::string DecodeBase32(const std::string& str)
{
std::vector<unsigned char> vchRet = DecodeBase32(str.c_str());
return (vchRet.size() == 0) ? std::string() : std::string((const char*)&vchRet[0], vchRet.size());
}
static bool ParsePrechecks(const std::string& str)
{
if (str.empty()) // No empty string allowed
return false;
if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
return false;
if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
return false;
return true;
}
bool ParseInt32(const std::string& str, int32_t *out)
{
if (!ParsePrechecks(str))
return false;
char *endp = NULL;
errno = 0; // strtol will not set errno if valid
long int n = strtol(str.c_str(), &endp, 10);
if(out) *out = (int32_t)n;
// Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
// platforms the size of these types may be different.
return endp && *endp == 0 && !errno &&
n >= std::numeric_limits<int32_t>::min() &&
n <= std::numeric_limits<int32_t>::max();
}
bool ParseInt64(const std::string& str, int64_t *out)
{
if (!ParsePrechecks(str))
return false;
char *endp = NULL;
errno = 0; // strtoll will not set errno if valid
long long int n = strtoll(str.c_str(), &endp, 10);
if(out) *out = (int64_t)n;
// Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
// we still have to check that the returned value is within the range of an *int64_t*.
return endp && *endp == 0 && !errno &&
n >= std::numeric_limits<int64_t>::min() &&
n <= std::numeric_limits<int64_t>::max();
}
bool ParseDouble(const std::string& str, double *out)
{
if (!ParsePrechecks(str))
return false;
if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
return false;
std::istringstream text(str);
text.imbue(std::locale::classic());
double result;
text >> result;
if(out) *out = result;
return text.eof() && !text.fail();
}
std::string FormatParagraph(const std::string in, size_t width, size_t indent)
{
std::stringstream out;
size_t col = 0;
size_t ptr = 0;
while (ptr < in.size()) {
// Find beginning of next word
ptr = in.find_first_not_of(' ', ptr);
if (ptr == std::string::npos)
break;
// Find end of next word
size_t endword = in.find_first_of(' ', ptr);
if (endword == std::string::npos)
endword = in.size();
// Add newline and indentation if this wraps over the allowed width
if (col > 0) {
if ((col + endword - ptr) > width) {
out << '\n';
for (size_t i = 0; i < indent; ++i)
out << ' ';
col = 0;
} else
out << ' ';
}
// Append word
out << in.substr(ptr, endword - ptr);
col += endword - ptr + 1;
ptr = endword;
}
return out.str();
}
std::string i64tostr(int64_t n)
{
return strprintf("%d", n);
}
std::string itostr(int n)
{
return strprintf("%d", n);
}
int64_t atoi64(const char* psz)
{
#ifdef _MSC_VER
return _atoi64(psz);
#else
return strtoll(psz, NULL, 10);
#endif
}
int64_t atoi64(const std::string& str)
{
#ifdef _MSC_VER
return _atoi64(str.c_str());
#else
return strtoll(str.c_str(), NULL, 10);
#endif
}
int atoi(const std::string& str)
{
return atoi(str.c_str());
}
/** Upper bound for mantissa.
* 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
* Larger integers cannot consist of arbitrary combinations of 0-9:
*
* 999999999999999999 1^18-1
* 9223372036854775807 (1<<63)-1 (max int64_t)
* 9999999999999999999 1^19-1 (would overflow)
*/
static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
/** Helper function for ParseFixedPoint */
static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
{
if(ch == '0')
++mantissa_tzeros;
else {
for (int i=0; i<=mantissa_tzeros; ++i) {
if (mantissa > (UPPER_BOUND / 10LL))
return false; /* overflow */
mantissa *= 10;
}
mantissa += ch - '0';
mantissa_tzeros = 0;
}
return true;
}
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
{
int64_t mantissa = 0;
int64_t exponent = 0;
int mantissa_tzeros = 0;
bool mantissa_sign = false;
bool exponent_sign = false;
int ptr = 0;
int end = val.size();
int point_ofs = 0;
if (ptr < end && val[ptr] == '-') {
mantissa_sign = true;
++ptr;
}
if (ptr < end)
{
if (val[ptr] == '0') {
/* pass single 0 */
++ptr;
} else if (val[ptr] >= '1' && val[ptr] <= '9') {
while (ptr < end && IsDigit(val[ptr])) {
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
return false; /* overflow */
++ptr;
}
} else return false; /* missing expected digit */
} else return false; /* empty string or loose '-' */
if (ptr < end && val[ptr] == '.')
{
++ptr;
if (ptr < end && IsDigit(val[ptr]))
{
while (ptr < end && IsDigit(val[ptr])) {
if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
return false; /* overflow */
++ptr;
++point_ofs;
}
} else return false; /* missing expected digit */
}
if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
{
++ptr;
if (ptr < end && val[ptr] == '+')
++ptr;
else if (ptr < end && val[ptr] == '-') {
exponent_sign = true;
++ptr;
}
if (ptr < end && IsDigit(val[ptr])) {
while (ptr < end && IsDigit(val[ptr])) {
if (exponent > (UPPER_BOUND / 10LL))
return false; /* overflow */
exponent = exponent * 10 + val[ptr] - '0';
++ptr;
}
} else return false; /* missing expected digit */
}
if (ptr != end)
return false; /* trailing garbage */
/* finalize exponent */
if (exponent_sign)
exponent = -exponent;
exponent = exponent - point_ofs + mantissa_tzeros;
/* finalize mantissa */
if (mantissa_sign)
mantissa = -mantissa;
/* convert to one 64-bit fixed-point value */
exponent += decimals;
if (exponent < 0)
return false; /* cannot represent values smaller than 10^-decimals */
if (exponent >= 18)
return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
for (int i=0; i < exponent; ++i) {
if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
return false; /* overflow */
mantissa *= 10;
}
if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
return false; /* overflow */
if (amount_out)
*amount_out = mantissa;
return true;
}
void Downcase(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c){return ToLower(c);});
}
std::string Capitalize(std::string str)
{
if (str.empty()) return str;
str[0] = ToUpper(str.front());
return str;
}
// Based on http://www.zedwood.com/article/cpp-is-valid-utf8-string-function
bool IsValidUTF8(const std::string& str)
{
const unsigned int strLen = str.length();
int c,n;
for (unsigned i = 0; i < strLen; i++) {
c = (unsigned char) str[i];
if (0x00 <= c && c <= 0x7f) n=0; // 0bbbbbbb (ASCII)
else if ((c & 0xE0) == 0xC0) n=1; // 110bbbbb
else if ( c == 0xED && i < (strLen - 1) && ((unsigned char)str[i+1] & 0xA0) == 0xA0)
return false; //U+d800 to U+dfff
else if ((c & 0xF0) == 0xE0) n=2; // 1110bbbb
else if ((c & 0xF8) == 0xF0) n=3; // 11110bbb
else return false;
for (int j=0; j < n && i < strLen; j++) { // n bytes matching 10bbbbbb follow ?
if ((++i == strLen) || (( (unsigned char)str[i] & 0xC0) != 0x80))
return false;
}
}
return true;
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
/*#include "blob_uint256.h"
#include "utilstrencodings.h"*/
#include <stdio.h>
#include <string.h>
template <unsigned int BITS>
base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch)
{
assert(vch.size() == sizeof(data));
memcpy(data, &vch[0], sizeof(data));
}
template <unsigned int BITS>
std::string base_blob<BITS>::GetHex() const
{
char psz[sizeof(data) * 2 + 1];
for (unsigned int i = 0; i < sizeof(data); i++)
sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]);
return std::string(psz, psz + sizeof(data) * 2);
}
template <unsigned int BITS>
void base_blob<BITS>::SetHex(const char* psz)
{
memset(data, 0, sizeof(data));
// skip leading spaces
while (isspace(*psz))
psz++;
// skip 0x
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
// hex string to uint
const char* pbegin = psz;
while (::HexDigit(*psz) != -1)
psz++;
psz--;
unsigned char* p1 = (unsigned char*)data;
unsigned char* pend = p1 + WIDTH;
while (psz >= pbegin && p1 < pend) {
*p1 = ::HexDigit(*psz--);
if (psz >= pbegin) {
*p1 |= ((unsigned char)::HexDigit(*psz--) << 4);
p1++;
}
}
}
template <unsigned int BITS>
void base_blob<BITS>::SetHex(const std::string& str)
{
SetHex(str.c_str());
}
template <unsigned int BITS>
std::string base_blob<BITS>::ToString() const
{
return GetHex();
}
// Explicit instantiations for base_blob<160>
template base_blob<160>::base_blob(const std::vector<unsigned char>&);
template std::string base_blob<160>::GetHex() const;
template std::string base_blob<160>::ToString() const;
template void base_blob<160>::SetHex(const char*);
template void base_blob<160>::SetHex(const std::string&);
// Explicit instantiations for base_blob<256>
template base_blob<256>::base_blob(const std::vector<unsigned char>&);
template std::string base_blob<256>::GetHex() const;
template std::string base_blob<256>::ToString() const;
template void base_blob<256>::SetHex(const char*);
template void base_blob<256>::SetHex(const std::string&);
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#include "allocators.h"
#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
// This is used to attempt to keep keying material out of swap
// Note that VirtualLock does not provide this as a guarantee on Windows,
// but, in practice, memory that has been VirtualLock'd almost never gets written to
// the pagefile except in rare circumstances where memory is extremely low.
#else
#include <limits.h> // for PAGESIZE
#include <sys/mman.h>
#include <unistd.h> // for sysconf
#endif
LockedPageManager* LockedPageManager::_instance = NULL;
std::once_flag LockedPageManager::init_flag{};// = STD_ONCE_INIT;
/** Determine system page size in bytes */
static inline size_t GetSystemPageSize()
{
size_t page_size;
#if defined(WIN32)
SYSTEM_INFO sSysInfo;
GetSystemInfo(&sSysInfo);
page_size = sSysInfo.dwPageSize;
#elif defined(PAGESIZE) // defined in limits.h
page_size = PAGESIZE;
#else // assume some POSIX OS
page_size = sysconf(_SC_PAGESIZE);
#endif
return page_size;
}
bool MemoryPageLocker::Lock(const void* addr, size_t len)
{
#ifdef WIN32
return VirtualLock(const_cast<void*>(addr), len) != 0;
#else
return mlock(addr, len) == 0;
#endif
}
bool MemoryPageLocker::Unlock(const void* addr, size_t len)
{
#ifdef WIN32
return VirtualUnlock(const_cast<void*>(addr), len) != 0;
#else
return munlock(addr, len) == 0;
#endif
}
LockedPageManager::LockedPageManager() : LockedPageManagerBase<MemoryPageLocker>(GetSystemPageSize())
{
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#include "cleanse.h"
#include <cstring>
/* Compilers have a bad habit of removing "superfluous" memset calls that
* are trying to zero memory. For example, when memset()ing a buffer and
* then free()ing it, the compiler might decide that the memset is
* unobservable and thus can be removed.
*
* Previously we used OpenSSL which tried to stop this by a) implementing
* memset in assembly on x86 and b) putting the function in its own file
* for other platforms.
*
* This change removes those tricks in favour of using asm directives to
* scare the compiler away. As best as our compiler folks can tell, this is
* sufficient and will continue to be so.
*
* Adam Langley <agl@google.com>
* Commit: ad1907fe73334d6c696c8539646c21b11178f20f
* BoringSSL (LICENSE: ISC)
*/
void memory_cleanse(void *ptr, size_t len)
{
std::memset(ptr, 0, len);
/* As best as we can tell, this is sufficient to break any optimisations that
might try to eliminate "superfluous" memsets. If there's an easy way to
detect memset_s, it would be better to use that. */
#if defined(_MSC_VER)
__asm;
#else
__asm__ __volatile__("" : : "r"(ptr) : "memory");
#endif
}
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2019 The PIVX developers
// Copyright (c) 2020 The BLANK Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#include "bignum.h"
/*#if defined(USE_NUM_GMP)
#include "bignum_gmp.cpp"
#endif*/
//#if defined(USE_NUM_OPENSSL)
//#include "bignum_openssl.cpp"
//#endif
std::string CBigNum::GetHex() const
{
return ToString(16);
}
std::string CBigNum::GetDec() const
{
return ToString(10);
}
CBigNum CBigNum::pow(const int e) const
{
return this->pow(CBigNum(e));
}
void CBigNum::SetHex(const std::string& str)
{
SetHexBool(str);
}
CBigNum& CBigNum::operator/=(const CBigNum& b)
{
*this = *this / b;
return *this;
}
CBigNum& CBigNum::operator%=(const CBigNum& b)
{
*this = *this % b;
return *this;
}
const CBigNum CBigNum::operator++(int)
{
// postfix operator
const CBigNum ret = *this;
++(*this);
return ret;
}
const CBigNum CBigNum::operator--(int)
{
// postfix operator
const CBigNum ret = *this;
--(*this);
return ret;
}
#pragma once
// absl
#include <absl/base/macros.h>
// boost
#include <boost/stacktrace.hpp>
// std
#include <sstream>
#include <iostream>
#include <thread>
#include <mutex>
// Helper macro which avoids evaluating the arguments to a stream if
// the condition doesn't hold. Condition is evaluated once and only once.
#define LAZY_STREAM(stream, condition) \
!(condition) ? (void) 0 : ::LogMessageVoidify() & (stream)
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
LogMessageVoidify() = default;
void operator&(std::ostream&) { }
};
class AssertStream
: public std::ostringstream
{
public:
AssertStream()
: std::ostringstream()
{}
~AssertStream() {
std::cerr << (*this).str() << boost::stacktrace::stacktrace() << std::endl;
abort();
}
inline AssertStream& operator<<(AssertStream& (*m)(AssertStream&)) {
return m(*this);
}
inline AssertStream& operator<<(std::ostream& (*m)(std::ostream&)) {
m(*(std::ostream*)this);
return *this;
}
template <typename T> inline AssertStream& operator<<(T const& t) {
*(std::ostream*)this << t;
return *this;
}
std::ostream& ostream() const {
return *(std::ostream*)this;
}
};
// ordinary assert does not work in release builds
#define RELEASE_ASSERT(x) \
LAZY_STREAM( AssertStream().ostream(), ABSL_PREDICT_TRUE(!(x))) << std::string{( #x )}
// tinyformat.h
// Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com]
//
// Boost Software License - Version 1.0
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//------------------------------------------------------------------------------
// Tinyformat: A minimal type safe printf replacement
//
// tinyformat.h is a type safe printf replacement library in a single C++
// header file. Design goals include:
//
// * Type safety and extensibility for user defined types.
// * C99 printf() compatibility, to the extent possible using std::ostream
// * Simplicity and minimalism. A single header file to include and distribute
// with your projects.
// * Augment rather than replace the standard stream formatting mechanism
// * C++98 support, with optional C++11 niceties
//
//
// Main interface example usage
// ----------------------------
//
// To print a date to std::cout:
//
// std::string weekday = "Wednesday";
// const char* month = "July";
// size_t day = 27;
// long hour = 14;
// int min = 44;
//
// tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
//
// The strange types here emphasize the type safety of the interface; it is
// possible to print a std::string using the "%s" conversion, and a
// size_t using the "%d" conversion. A similar result could be achieved
// using either of the tfm::format() functions. One prints on a user provided
// stream:
//
// tfm::format(std::cerr, "%s, %s %d, %.2d:%.2d\n",
// weekday, month, day, hour, min);
//
// The other returns a std::string:
//
// std::string date = tfm::format("%s, %s %d, %.2d:%.2d\n",
// weekday, month, day, hour, min);
// std::cout << date;
//
// These are the three primary interface functions. There is also a
// convenience function printfln() which appends a newline to the usual result
// of printf() for super simple logging.
//
//
// User defined format functions
// -----------------------------
//
// Simulating variadic templates in C++98 is pretty painful since it requires
// writing out the same function for each desired number of arguments. To make
// this bearable tinyformat comes with a set of macros which are used
// internally to generate the API, but which may also be used in user code.
//
// The three macros TINYFORMAT_ARGTYPES(n), TINYFORMAT_VARARGS(n) and
// TINYFORMAT_PASSARGS(n) will generate a list of n argument types,
// type/name pairs and argument names respectively when called with an integer
// n between 1 and 16. We can use these to define a macro which generates the
// desired user defined function with n arguments. To generate all 16 user
// defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an
// example, see the implementation of printf() at the end of the source file.
//
// Sometimes it's useful to be able to pass a list of format arguments through
// to a non-template function. The FormatList class is provided as a way to do
// this by storing the argument list in a type-opaque way. Continuing the
// example from above, we construct a FormatList using makeFormatList():
//
// FormatListRef formatList = tfm::makeFormatList(weekday, month, day, hour, min);
//
// The format list can now be passed into any non-template function and used
// via a call to the vformat() function:
//
// tfm::vformat(std::cout, "%s, %s %d, %.2d:%.2d\n", formatList);
//
//
// Additional API information
// --------------------------
//
// Error handling: Define TINYFORMAT_ERROR to customize the error handling for
// format strings which are unsupported or have the wrong number of format
// specifiers (calls assert() by default).
//
// User defined types: Uses operator<< for user defined types by default.
// Overload formatValue() for more control.
#ifndef TINYFORMAT_H_INCLUDED
#define TINYFORMAT_H_INCLUDED
namespace tinyformat
{
}
//------------------------------------------------------------------------------
// Config section. Customize to your liking!
// Namespace alias to encourage brevity
namespace tfm = tinyformat;
// Error handling; calls assert() by default.
#define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
// Define for C++11 variadic templates which make the code shorter & more
// general. If you don't define this, C++11 support is autodetected below.
#define TINYFORMAT_USE_VARIADIC_TEMPLATES
//------------------------------------------------------------------------------
// Implementation details.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
#ifndef TINYFORMAT_ERROR
#define TINYFORMAT_ERROR(reason) assert(0 && reason)
#endif
#if !defined(TINYFORMAT_USE_VARIADIC_TEMPLATES) && !defined(TINYFORMAT_NO_VARIADIC_TEMPLATES)
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define TINYFORMAT_USE_VARIADIC_TEMPLATES
#endif
#endif
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
// std::showpos is broken on old libstdc++ as provided with OSX. See
// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
#define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
#endif
#ifdef __APPLE__
// Workaround OSX linker warning: xcode uses different default symbol
// visibilities for static libs vs executables (see bitcoin's issue #25)
# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
#else
# define TINYFORMAT_HIDDEN
#endif
namespace tinyformat
{
class format_error: public std::runtime_error
{
public:
format_error(const std::string &what): std::runtime_error(what) {
}
};
//------------------------------------------------------------------------------
namespace detail
{
// Test whether type T1 is convertible to type T2
template <typename T1, typename T2>
struct is_convertible {
private:
// two types of different size
struct fail {
char dummy[2];
};
struct succeed {
char dummy;
};
// Try to convert a T1 to a T2 by plugging into tryConvert
static fail tryConvert(...);
static succeed tryConvert(const T2&);
static const T1& makeT1();
public:
#ifdef _MSC_VER
// Disable spurious loss of precision warnings in tryConvert(makeT1())
#pragma warning(push)
#pragma warning(disable : 4244)
#pragma warning(disable : 4267)
#endif
// Standard trick: the (...) version of tryConvert will be chosen from
// the overload set only if the version taking a T2 doesn't match.
// Then we compare the sizes of the return types to check which
// function matched. Very neat, in a disgusting kind of way :)
static const bool value =
sizeof(tryConvert(makeT1())) == sizeof(succeed);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
};
// Detect when a type is not a wchar_t string
template <typename T>
struct is_wchar {
typedef int tinyformat_wchar_is_not_supported;
};
template <>
struct is_wchar<wchar_t*> {
};
template <>
struct is_wchar<const wchar_t*> {
};
template <int n>
struct is_wchar<const wchar_t[n]> {
};
template <int n>
struct is_wchar<wchar_t[n]> {
};
// Format the value by casting to type fmtT. This default implementation
// should never be called.
template <typename T, typename fmtT, bool convertible = is_convertible<T, fmtT>::value>
struct formatValueAsType {
static void invoke(std::ostream& /*out*/, const T& /*value*/) { assert(0); }
};
// Specialized version for types that can actually be converted to fmtT, as
// indicated by the "convertible" template parameter.
template <typename T, typename fmtT>
struct formatValueAsType<T, fmtT, true> {
static void invoke(std::ostream& out, const T& value)
{
out << static_cast<fmtT>(value);
}
};
#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
template <typename T, bool convertible = is_convertible<T, int>::value>
struct formatZeroIntegerWorkaround {
static bool invoke(std::ostream& /**/, const T& /**/) { return false; }
};
template <typename T>
struct formatZeroIntegerWorkaround<T, true> {
static bool invoke(std::ostream& out, const T& value)
{
if (static_cast<int>(value) == 0 && out.flags() & std::ios::showpos) {
out << "+0";
return true;
}
return false;
}
};
#endif // TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
// Convert an arbitrary type to integer. The version with convertible=false
// throws an error.
template <typename T, bool convertible = is_convertible<T, int>::value>
struct convertToInt {
static int invoke(const T& /*value*/)
{
TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to "
"integer for use as variable width or precision");
return 0;
}
};
// Specialization for convertToInt when conversion is possible
template <typename T>
struct convertToInt<T, true> {
static int invoke(const T& value) { return static_cast<int>(value); }
};
// Format at most ntrunc characters to the given stream.
template<typename T>
inline void formatTruncated(std::ostream& out, const T& value, int ntrunc)
{
std::ostringstream tmp;
tmp << value;
std::string result = tmp.str();
out.write(result.c_str(), (std::min)(ntrunc, static_cast<int>(result.size())));
}
#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
{ \
std::streamsize len = 0; \
while(len < ntrunc && value[len] != 0) \
++len; \
out.write(value, len); \
}
// Overload for const char* and char*. Could overload for signed & unsigned
// char too, but these are technically unneeded for printf compatibility.
TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(const char)
TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(char)
#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
} // namespace detail
//------------------------------------------------------------------------------
/// Format a value into a stream, delegating to operator<< by default.
///
/// Users may override this for their own types. When this function is called,
/// the stream flags will have been modified according to the format string.
/// The format specification is provided in the range [fmtBegin, fmtEnd). For
/// truncating conversions, ntrunc is set to the desired maximum number of
/// characters, for example "%.7s" calls formatValue with ntrunc = 7.
///
/// By default, formatValue() uses the usual stream insertion operator
/// operator<< to format the type T, with special cases for the %c and %p
/// conversions.
template <typename T>
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
const char* fmtEnd, int ntrunc, const T& value)
{
#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
// Since we don't support printing of wchar_t using "%ls", make it fail at
// compile time in preference to printing as a void* at runtime.
typedef typename detail::is_wchar<T>::tinyformat_wchar_is_not_supported DummyType;
(void)DummyType(); // avoid unused type warning with gcc-4.8
#endif
// The mess here is to support the %c and %p conversions: if these
// conversions are active we try to convert the type to a char or const
// void* respectively and format that instead of the value itself. For the
// %p conversion it's important to avoid dereferencing the pointer, which
// could otherwise lead to a crash when printing a dangling (const char*).
const bool canConvertToChar = detail::is_convertible<T, char>::value;
const bool canConvertToVoidPtr = detail::is_convertible<T, const void*>::value;
if (canConvertToChar && *(fmtEnd - 1) == 'c')
detail::formatValueAsType<T, char>::invoke(out, value);
else if (canConvertToVoidPtr && *(fmtEnd - 1) == 'p')
detail::formatValueAsType<T, const void*>::invoke(out, value);
#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
else if (detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/;
#endif
else if(ntrunc >= 0)
{
// Take care not to overread C strings in truncating conversions like
// "%.4s" where at most 4 characters may be read.
detail::formatTruncated(out, value, ntrunc);
}
else
out << value;
}
// Overloaded version for char types to support printing as an integer
#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \
const char* fmtEnd, int /**/, charType value) \
{ \
switch (*(fmtEnd - 1)) { \
case 'u': \
case 'd': \
case 'i': \
case 'o': \
case 'X': \
case 'x': \
out << static_cast<int>(value); \
break; \
default: \
out << value; \
break; \
} \
}
// per 3.9.1: char, signed char and unsigned char are all distinct types
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(char)
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(signed char)
TINYFORMAT_DEFINE_FORMATVALUE_CHAR(unsigned char)
#undef TINYFORMAT_DEFINE_FORMATVALUE_CHAR
//------------------------------------------------------------------------------
// Tools for emulating variadic templates in C++98. The basic idea here is
// stolen from the boost preprocessor metaprogramming library and cut down to
// be just general enough for what we need.
#define TINYFORMAT_ARGTYPES(n) TINYFORMAT_ARGTYPES_##n
#define TINYFORMAT_VARARGS(n) TINYFORMAT_VARARGS_##n
#define TINYFORMAT_PASSARGS(n) TINYFORMAT_PASSARGS_##n
#define TINYFORMAT_PASSARGS_TAIL(n) TINYFORMAT_PASSARGS_TAIL_##n
// To keep it as transparent as possible, the macros below have been generated
// using python via the excellent cog.py code generation script. This avoids
// the need for a bunch of complex (but more general) preprocessor tricks as
// used in boost.preprocessor.
//
// To rerun the code generation in place, use `cog.py -r tinyformat.h`
// (see http://nedbatchelder.com/code/cog). Alternatively you can just create
// extra versions by hand.
/*[[[cog
maxParams = 16
def makeCommaSepLists(lineTemplate, elemTemplate, startInd=1):
for j in range(startInd,maxParams+1):
std::list = ', '.join([elemTemplate % {'i':i} for i in range(startInd,j+1)])
cog.outl(lineTemplate % {'j':j, 'list':list})
makeCommaSepLists('#define TINYFORMAT_ARGTYPES_%(j)d %(list)s',
'class T%(i)d')
cog.outl()
makeCommaSepLists('#define TINYFORMAT_VARARGS_%(j)d %(list)s',
'const T%(i)d& v%(i)d')
cog.outl()
makeCommaSepLists('#define TINYFORMAT_PASSARGS_%(j)d %(list)s', 'v%(i)d')
cog.outl()
cog.outl('#define TINYFORMAT_PASSARGS_TAIL_1')
makeCommaSepLists('#define TINYFORMAT_PASSARGS_TAIL_%(j)d , %(list)s',
'v%(i)d', startInd = 2)
cog.outl()
cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' +
' '.join(['m(%d)' % (j,) for j in range(1,maxParams+1)]))
]]]*/
#define TINYFORMAT_ARGTYPES_1 class T1
#define TINYFORMAT_ARGTYPES_2 class T1, class T2
#define TINYFORMAT_ARGTYPES_3 class T1, class T2, class T3
#define TINYFORMAT_ARGTYPES_4 class T1, class T2, class T3, class T4
#define TINYFORMAT_ARGTYPES_5 class T1, class T2, class T3, class T4, class T5
#define TINYFORMAT_ARGTYPES_6 class T1, class T2, class T3, class T4, class T5, class T6
#define TINYFORMAT_ARGTYPES_7 class T1, class T2, class T3, class T4, class T5, class T6, class T7
#define TINYFORMAT_ARGTYPES_8 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8
#define TINYFORMAT_ARGTYPES_9 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9
#define TINYFORMAT_ARGTYPES_10 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10
#define TINYFORMAT_ARGTYPES_11 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11
#define TINYFORMAT_ARGTYPES_12 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12
#define TINYFORMAT_ARGTYPES_13 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13
#define TINYFORMAT_ARGTYPES_14 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14
#define TINYFORMAT_ARGTYPES_15 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15
#define TINYFORMAT_ARGTYPES_16 class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16
#define TINYFORMAT_VARARGS_1 const T1& v1
#define TINYFORMAT_VARARGS_2 const T1 &v1, const T2 &v2
#define TINYFORMAT_VARARGS_3 const T1 &v1, const T2 &v2, const T3 &v3
#define TINYFORMAT_VARARGS_4 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4
#define TINYFORMAT_VARARGS_5 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5
#define TINYFORMAT_VARARGS_6 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6
#define TINYFORMAT_VARARGS_7 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7
#define TINYFORMAT_VARARGS_8 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8
#define TINYFORMAT_VARARGS_9 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9
#define TINYFORMAT_VARARGS_10 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10
#define TINYFORMAT_VARARGS_11 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11
#define TINYFORMAT_VARARGS_12 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12
#define TINYFORMAT_VARARGS_13 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13
#define TINYFORMAT_VARARGS_14 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14
#define TINYFORMAT_VARARGS_15 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14, const T15 &v15
#define TINYFORMAT_VARARGS_16 const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9, const T10 &v10, const T11 &v11, const T12 &v12, const T13 &v13, const T14 &v14, const T15 &v15, const T16 &v16
#define TINYFORMAT_PASSARGS_1 v1
#define TINYFORMAT_PASSARGS_2 v1, v2
#define TINYFORMAT_PASSARGS_3 v1, v2, v3
#define TINYFORMAT_PASSARGS_4 v1, v2, v3, v4
#define TINYFORMAT_PASSARGS_5 v1, v2, v3, v4, v5
#define TINYFORMAT_PASSARGS_6 v1, v2, v3, v4, v5, v6
#define TINYFORMAT_PASSARGS_7 v1, v2, v3, v4, v5, v6, v7
#define TINYFORMAT_PASSARGS_8 v1, v2, v3, v4, v5, v6, v7, v8
#define TINYFORMAT_PASSARGS_9 v1, v2, v3, v4, v5, v6, v7, v8, v9
#define TINYFORMAT_PASSARGS_10 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10
#define TINYFORMAT_PASSARGS_11 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
#define TINYFORMAT_PASSARGS_12 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
#define TINYFORMAT_PASSARGS_13 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
#define TINYFORMAT_PASSARGS_14 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
#define TINYFORMAT_PASSARGS_15 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
#define TINYFORMAT_PASSARGS_16 v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
#define TINYFORMAT_PASSARGS_TAIL_1
#define TINYFORMAT_PASSARGS_TAIL_2 , v2
#define TINYFORMAT_PASSARGS_TAIL_3 , v2, v3
#define TINYFORMAT_PASSARGS_TAIL_4 , v2, v3, v4
#define TINYFORMAT_PASSARGS_TAIL_5 , v2, v3, v4, v5
#define TINYFORMAT_PASSARGS_TAIL_6 , v2, v3, v4, v5, v6
#define TINYFORMAT_PASSARGS_TAIL_7 , v2, v3, v4, v5, v6, v7
#define TINYFORMAT_PASSARGS_TAIL_8 , v2, v3, v4, v5, v6, v7, v8
#define TINYFORMAT_PASSARGS_TAIL_9 , v2, v3, v4, v5, v6, v7, v8, v9
#define TINYFORMAT_PASSARGS_TAIL_10 , v2, v3, v4, v5, v6, v7, v8, v9, v10
#define TINYFORMAT_PASSARGS_TAIL_11 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11
#define TINYFORMAT_PASSARGS_TAIL_12 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
#define TINYFORMAT_PASSARGS_TAIL_13 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
#define TINYFORMAT_PASSARGS_TAIL_14 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14
#define TINYFORMAT_PASSARGS_TAIL_15 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15
#define TINYFORMAT_PASSARGS_TAIL_16 , v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16
#define TINYFORMAT_FOREACH_ARGNUM(m) \
m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) m(10) m(11) m(12) m(13) m(14) m(15) m(16)
//[[[end]]]
namespace detail
{
// Type-opaque holder for an argument to format(), with associated actions on
// the type held as explicit function pointers. This allows FormatArg's for
// each argument to be allocated as a homogenous array inside FormatList
// whereas a naive implementation based on inheritance does not.
class FormatArg
{
public:
FormatArg() {}
template<typename T>
FormatArg(const T& value)
: m_value(static_cast<const void*>(&value)),
m_formatImpl(&formatImpl<T>),
m_toIntImpl(&toIntImpl<T>)
{ }
void format(std::ostream& out, const char* fmtBegin,
const char* fmtEnd, int ntrunc) const
{
m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
}
int toInt() const
{
return m_toIntImpl(m_value);
}
private:
template<typename T>
TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin,
const char* fmtEnd, int ntrunc, const void* value)
{
formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));
}
template <typename T>
TINYFORMAT_HIDDEN static int toIntImpl(const void* value)
{
return convertToInt<T>::invoke(*static_cast<const T*>(value));
}
const void* m_value;
void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,
const char* fmtEnd, int ntrunc, const void* value);
int (*m_toIntImpl)(const void* value);
};
// Parse and return an integer from the string c, as atoi()
// On return, c is set to one past the end of the integer.
inline int parseIntAndAdvance(const char*& c)
{
int i = 0;
for(;*c >= '0' && *c <= '9'; ++c)
i = 10*i + (*c - '0');
return i;
}
// Print literal part of format string and return next format spec
// position.
//
// Skips over any occurrences of '%%', printing a literal '%' to the
// output. The position of the first % character of the next
// nontrivial format spec is returned, or the end of string.
inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
{
const char* c = fmt;
for(;; ++c) {
switch(*c)
{
case '\0':
out.write(fmt, c - fmt);
return c;
case '%':
out.write(fmt, c - fmt);
if(*(c+1) != '%')
return c;
// for "%%", tack trailing % onto next literal section.
fmt = ++c;
break;
default:
break;
}
}
}
// Parse a format string and set the stream state accordingly.
//
// The format mini-language recognized here is meant to be the one from C99,
// with the form "%[flags][width][.precision][length]type".
//
// Formatting options which can't be natively represented using the ostream
// state are returned in spacePadPositive (for space padded positive numbers)
// and ntrunc (for truncating conversions). argIndex is incremented if
// necessary to pull out variable width and precision . The function returns a
// pointer to the character after the end of the current format spec.
inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive,
int& ntrunc, const char* fmtStart,
const detail::FormatArg* formatters,
int& argIndex, int numFormatters)
{
if (*fmtStart != '%') {
TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
return fmtStart;
}
// Reset stream state to defaults.
out.width(0);
out.precision(6);
out.fill(' ');
// Reset most flags; ignore irrelevant unitbuf & skipws.
out.unsetf(std::ios::adjustfield | std::ios::basefield |
std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
bool precisionSet = false;
bool widthSet = false;
int widthExtra = 0;
const char* c = fmtStart + 1;
// 1) Parse flags
for (;; ++c) {
switch (*c) {
case '#':
out.setf(std::ios::showpoint | std::ios::showbase);
continue;
case '0':
// overridden by left alignment ('-' flag)
if (!(out.flags() & std::ios::left)) {
// Use internal padding so that numeric values are
// formatted correctly, eg -00010 rather than 000-10
out.fill('0');
out.setf(std::ios::internal, std::ios::adjustfield);
}
continue;
case '-':
out.fill(' ');
out.setf(std::ios::left, std::ios::adjustfield);
continue;
case ' ':
// overridden by show positive sign, '+' flag.
if (!(out.flags() & std::ios::showpos))
spacePadPositive = true;
continue;
case '+':
out.setf(std::ios::showpos);
spacePadPositive = false;
widthExtra = 1;
continue;
default:
break;
}
break;
}
// 2) Parse width
if (*c >= '0' && *c <= '9') {
widthSet = true;
out.width(parseIntAndAdvance(c));
}
if (*c == '*') {
widthSet = true;
int width = 0;
if(argIndex < numFormatters)
width = formatters[argIndex++].toInt();
else
TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
if(width < 0) {
// negative widths correspond to '-' flag set
out.fill(' ');
out.setf(std::ios::left, std::ios::adjustfield);
width = -width;
}
out.width(width);
++c;
}
// 3) Parse precision
if (*c == '.') {
++c;
int precision = 0;
if (*c == '*') {
++c;
if(argIndex < numFormatters)
precision = formatters[argIndex++].toInt();
else
TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
} else {
if (*c >= '0' && *c <= '9')
precision = parseIntAndAdvance(c);
else if (*c == '-') // negative precisions ignored, treated as zero.
parseIntAndAdvance(++c);
}
out.precision(precision);
precisionSet = true;
}
// 4) Ignore any C99 length modifier
while (*c == 'l' || *c == 'h' || *c == 'L' ||
*c == 'j' || *c == 'z' || *c == 't')
++c;
// 5) We're up to the conversion specifier character.
// Set stream flags based on conversion specifier (thanks to the
// boost::format class for forging the way here).
bool intConversion = false;
switch (*c) {
case 'u':
case 'd':
case 'i':
out.setf(std::ios::dec, std::ios::basefield);
intConversion = true;
break;
case 'o':
out.setf(std::ios::oct, std::ios::basefield);
intConversion = true;
break;
case 'X':
out.setf(std::ios::uppercase);
case 'x':
case 'p':
out.setf(std::ios::hex, std::ios::basefield);
intConversion = true;
break;
case 'E':
out.setf(std::ios::uppercase);
case 'e':
out.setf(std::ios::scientific, std::ios::floatfield);
out.setf(std::ios::dec, std::ios::basefield);
break;
case 'F':
out.setf(std::ios::uppercase);
case 'f':
out.setf(std::ios::fixed, std::ios::floatfield);
break;
case 'G':
out.setf(std::ios::uppercase);
case 'g':
out.setf(std::ios::dec, std::ios::basefield);
// As in boost::format, let stream decide float format.
out.flags(out.flags() & ~std::ios::floatfield);
break;
case 'a':
case 'A':
TINYFORMAT_ERROR("tinyformat: the %a and %A conversion specs "
"are not supported");
break;
case 'c':
// Handled as special case inside formatValue()
break;
case 's':
if (precisionSet)
ntrunc = static_cast<int>(out.precision());
// Make %s print booleans as "true" and "false"
out.setf(std::ios::boolalpha);
break;
case 'n':
// Not supported - will cause problems!
TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported");
break;
case '\0':
TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
"terminated by end of string");
return c;
default:
break;
}
if (intConversion && precisionSet && !widthSet) {
// "precision" for integers gives the minimum number of digits (to be
// padded with zeros on the left). This isn't really supported by the
// iostreams, but we can approximately simulate it with the width if
// the width isn't otherwise used.
out.width(out.precision() + widthExtra);
out.setf(std::ios::internal, std::ios::adjustfield);
out.fill('0');
}
return c + 1;
}
//------------------------------------------------------------------------------
inline void formatImpl(std::ostream& out, const char* fmt,
const detail::FormatArg* formatters,
int numFormatters)
{
// Saved stream state
std::streamsize origWidth = out.width();
std::streamsize origPrecision = out.precision();
std::ios::fmtflags origFlags = out.flags();
char origFill = out.fill();
for (int argIndex = 0; argIndex < numFormatters; ++argIndex)
{
// Parse the format string
fmt = printFormatStringLiteral(out, fmt);
bool spacePadPositive = false;
int ntrunc = -1;
const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt,
formatters, argIndex, numFormatters);
if (argIndex >= numFormatters)
{
// Check args remain after reading any variable width/precision
TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
return;
}
const FormatArg& arg = formatters[argIndex];
// Format the arg into the stream.
if(!spacePadPositive)
arg.format(out, fmt, fmtEnd, ntrunc);
else
{
// The following is a special case with no direct correspondence
// between stream formatting and the printf() behaviour. Simulate
// it crudely by formatting into a temporary string stream and
// munging the resulting string.
std::ostringstream tmpStream;
tmpStream.copyfmt(out);
tmpStream.setf(std::ios::showpos);
arg.format(tmpStream, fmt, fmtEnd, ntrunc);
std::string result = tmpStream.str(); // allocates... yuck.
for(size_t i = 0, iend = result.size(); i < iend; ++i)
if(result[i] == '+') result[i] = ' ';
out << result;
}
fmt = fmtEnd;
}
// Print remaining part of format string.
fmt = printFormatStringLiteral(out, fmt);
if(*fmt != '\0')
TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
// Restore stream state
out.width(origWidth);
out.precision(origPrecision);
out.flags(origFlags);
out.fill(origFill);
}
} // namespace detail
/// List of template arguments format(), held in a type-opaque way.
///
/// A const reference to FormatList (typedef'd as FormatListRef) may be
/// conveniently used to pass arguments to non-template functions: All type
/// information has been stripped from the arguments, leaving just enough of a
/// common interface to perform formatting as required.
class FormatList
{
public:
FormatList(detail::FormatArg* formatters, int N)
: m_formatters(formatters), m_N(N) { }
friend void vformat(std::ostream& out, const char* fmt,
const FormatList& list);
private:
const detail::FormatArg* m_formatters;
int m_N;
};
/// Reference to type-opaque format list for passing to vformat()
typedef const FormatList& FormatListRef;
namespace detail {
// Format list subclass with fixed storage to avoid dynamic allocation
template<int N>
class FormatListN : public FormatList
{
public:
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
template<typename... Args>
FormatListN(const Args&... args)
: FormatList(&m_formatterStore[0], N),
m_formatterStore { FormatArg(args)... }
{ static_assert(sizeof...(args) == N, "Number of args must be N"); }
#else // C++98 version
void init(int) {}
# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
\
template<TINYFORMAT_ARGTYPES(n)> \
FormatListN(TINYFORMAT_VARARGS(n)) \
: FormatList(&m_formatterStore[0], n) \
{ assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
\
template<TINYFORMAT_ARGTYPES(n)> \
void init(int i, TINYFORMAT_VARARGS(n)) \
{ \
m_formatterStore[i] = FormatArg(v1); \
init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
}
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
#endif
private:
FormatArg m_formatterStore[N];
};
// Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard
template<> class FormatListN<0> : public FormatList
{
public: FormatListN() : FormatList(0, 0) {}
};
} // namespace detail
//------------------------------------------------------------------------------
// Primary API functions
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
/// Make type-agnostic format list from list of template arguments.
///
/// The exact return type of this function is an implementation detail and
/// shouldn't be relied upon. Instead it should be stored as a FormatListRef:
///
/// FormatListRef formatList = makeFormatList( /*...*/ );
template<typename... Args>
detail::FormatListN<sizeof...(Args)> makeFormatList(const Args&... args)
{
return detail::FormatListN<sizeof...(args)>(args...);
}
#else // C++98 version
inline detail::FormatListN<0> makeFormatList()
{
return detail::FormatListN<0>();
}
#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
template<TINYFORMAT_ARGTYPES(n)> \
detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
{ \
return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
}
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
#undef TINYFORMAT_MAKE_MAKEFORMATLIST
#endif
/// Format list of arguments to the stream according to the given format string.
///
/// The name vformat() is chosen for the semantic similarity to vprintf(): the
/// list of format arguments is held in a single function argument.
inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
{
detail::formatImpl(out, fmt, list.m_formatters, list.m_N);
}
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
/// Format list of arguments to the stream according to given format string.
template<typename... Args>
void format(std::ostream& out, const char* fmt, const Args&... args)
{
vformat(out, fmt, makeFormatList(args...));
}
/// Format list of arguments according to the given format string and return
/// the result as a string.
template<typename... Args>
std::string format(const char* fmt, const Args&... args)
{
std::ostringstream oss;
format(oss, fmt, args...);
return oss.str();
}
/// Format list of arguments to std::cout, according to the given format string
template<typename... Args>
void printf(const char* fmt, const Args&... args)
{
format(std::cout, fmt, args...);
}
template<typename... Args>
void printfln(const char* fmt, const Args&... args)
{
format(std::cout, fmt, args...);
std::cout << '\n';
}
#else // C++98 version
inline void format(std::ostream& out, const char* fmt)
{
vformat(out, fmt, makeFormatList());
}
inline std::string format(const char* fmt)
{
std::ostringstream oss;
format(oss, fmt);
return oss.str();
}
inline void printf(const char* fmt)
{
format(std::cout, fmt);
}
inline void printfln(const char* fmt)
{
format(std::cout, fmt);
std::cout << '\n';
}
#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
\
template <TINYFORMAT_ARGTYPES(n)> \
void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template <TINYFORMAT_ARGTYPES(n)> \
std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
std::ostringstream oss; \
format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
return oss.str(); \
} \
\
template <TINYFORMAT_ARGTYPES(n)> \
void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
} \
\
template <TINYFORMAT_ARGTYPES(n)> \
void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
std::cout << '\n'; \
}
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
#undef TINYFORMAT_MAKE_FORMAT_FUNCS
#endif
// Added for Bitcoin Core
template<typename... Args>
std::string format(const std::string &fmt, const Args&... args)
{
std::ostringstream oss;
format(oss, fmt.c_str(), args...);
return oss.str();
}
} // namespace tinyformat
#define strprintf tfm::format
#endif // TINYFORMAT_H_INCLUDED
//#ifndef DOGEC_CONFIG_H
#define DOGEC_CONFIG_H
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Version Build */
#undef CLIENT_VERSION_BUILD
/* Version is release */
#undef CLIENT_VERSION_IS_RELEASE
/* Major version */
#undef CLIENT_VERSION_MAJOR
/* Minor version */
#undef CLIENT_VERSION_MINOR
/* Build revision */
#undef CLIENT_VERSION_REVISION
/* Version is release */
#undef COPYRIGHT_YEAR
/* Define this symbol to build code that uses AVX2 intrinsics */
#undef ENABLE_AVX2
/* Define to 1 to enable mining rpc commands */
#undef ENABLE_MINING_RPC
/* Define this symbol to build code that uses SHA-NI intrinsics */
#undef ENABLE_SHANI
/* Define this symbol to build code that uses SSE4.1 intrinsics */
#undef ENABLE_SSE41
/* Define to 1 to enable wallet functions */
#undef ENABLE_WALLET
/* Define to 1 to enable ZMQ functions */
#undef ENABLE_ZMQ
/* define if the Boost library is available */
#undef HAVE_BOOST
/* define if the Boost::Chrono library is available */
#undef HAVE_BOOST_CHRONO
/* define if the Boost::Filesystem library is available */
#undef HAVE_BOOST_FILESYSTEM
/* define if the Boost::PROGRAM_OPTIONS library is available */
#undef HAVE_BOOST_PROGRAM_OPTIONS
/* define if the Boost::System library is available */
#undef HAVE_BOOST_SYSTEM
/* define if the Boost::Thread library is available */
#undef HAVE_BOOST_THREAD
/* define if the Boost::Unit_Test_Framework library is available */
#undef HAVE_BOOST_UNIT_TEST_FRAMEWORK
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define this symbol if the consensus lib has been built */
#undef HAVE_CONSENSUS_LIB
/* define if the compiler supports basic C++11 syntax */
#undef HAVE_CXX11
/* Define to 1 if you have the declaration of `be16toh', and to 0 if you
don't. */
#undef HAVE_DECL_BE16TOH
/* Define to 1 if you have the declaration of `be32toh', and to 0 if you
don't. */
#undef HAVE_DECL_BE32TOH
/* Define to 1 if you have the declaration of `be64toh', and to 0 if you
don't. */
#undef HAVE_DECL_BE64TOH
/* Define to 1 if you have the declaration of `bswap_16', and to 0 if you
don't. */
#undef HAVE_DECL_BSWAP_16
/* Define to 1 if you have the declaration of `bswap_32', and to 0 if you
don't. */
#undef HAVE_DECL_BSWAP_32
/* Define to 1 if you have the declaration of `bswap_64', and to 0 if you
don't. */
#undef HAVE_DECL_BSWAP_64
/* Define to 1 if you have the declaration of `daemon', and to 0 if you don't.
*/
#undef HAVE_DECL_DAEMON
/* Define to 1 if you have the declaration of `htobe16', and to 0 if you
don't. */
#undef HAVE_DECL_HTOBE16
/* Define to 1 if you have the declaration of `htobe32', and to 0 if you
don't. */
#undef HAVE_DECL_HTOBE32
/* Define to 1 if you have the declaration of `htobe64', and to 0 if you
don't. */
#undef HAVE_DECL_HTOBE64
/* Define to 1 if you have the declaration of `htole16', and to 0 if you
don't. */
#undef HAVE_DECL_HTOLE16
/* Define to 1 if you have the declaration of `htole32', and to 0 if you
don't. */
#undef HAVE_DECL_HTOLE32
/* Define to 1 if you have the declaration of `htole64', and to 0 if you
don't. */
#undef HAVE_DECL_HTOLE64
/* Define to 1 if you have the declaration of `le16toh', and to 0 if you
don't. */
#undef HAVE_DECL_LE16TOH
/* Define to 1 if you have the declaration of `le32toh', and to 0 if you
don't. */
#undef HAVE_DECL_LE32TOH
/* Define to 1 if you have the declaration of `le64toh', and to 0 if you
don't. */
#undef HAVE_DECL_LE64TOH
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
don't. */
#undef HAVE_DECL_STRERROR_R
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#undef HAVE_DECL_STRNLEN
/* Define to 1 if you have the declaration of `__builtin_clz', and to 0 if you
don't. */
#undef HAVE_DECL___BUILTIN_CLZ
/* Define to 1 if you have the declaration of `__builtin_clzl', and to 0 if
you don't. */
#undef HAVE_DECL___BUILTIN_CLZL
/* Define to 1 if you have the declaration of `__builtin_clzll', and to 0 if
you don't. */
#undef HAVE_DECL___BUILTIN_CLZLL
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if the system has the `dllexport' function attribute */
#undef HAVE_FUNC_ATTRIBUTE_DLLEXPORT
/* Define to 1 if the system has the `dllimport' function attribute */
#undef HAVE_FUNC_ATTRIBUTE_DLLIMPORT
/* Define to 1 if the system has the `visibility' function attribute */
#undef HAVE_FUNC_ATTRIBUTE_VISIBILITY
/* Define this symbol if the BSD getentropy system call is available */
#undef HAVE_GETENTROPY
/* Define this symbol if the BSD getentropy system call is available with
sys/random.h */
#undef HAVE_GETENTROPY_RAND
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `advapi32' library (-ladvapi32). */
#undef HAVE_LIBADVAPI32
/* Define to 1 if you have the `comctl32' library (-lcomctl32). */
#undef HAVE_LIBCOMCTL32
/* Define to 1 if you have the `comdlg32' library (-lcomdlg32). */
#undef HAVE_LIBCOMDLG32
/* Define to 1 if you have the `crypt32' library (-lcrypt32). */
#undef HAVE_LIBCRYPT32
/* Define to 1 if you have the `gdi32' library (-lgdi32). */
#undef HAVE_LIBGDI32
/* Define this symbol if libgmp is installed */
#undef HAVE_LIBGMP
/* Define to 1 if you have the `imm32' library (-limm32). */
#undef HAVE_LIBIMM32
/* Define to 1 if you have the `iphlpapi' library (-liphlpapi). */
#undef HAVE_LIBIPHLPAPI
/* Define to 1 if you have the `kernel32' library (-lkernel32). */
#undef HAVE_LIBKERNEL32
/* Define to 1 if you have the `mingwthrd' library (-lmingwthrd). */
#undef HAVE_LIBMINGWTHRD
/* Define to 1 if you have the `mswsock' library (-lmswsock). */
#undef HAVE_LIBMSWSOCK
/* Define to 1 if you have the `ole32' library (-lole32). */
#undef HAVE_LIBOLE32
/* Define to 1 if you have the `oleaut32' library (-loleaut32). */
#undef HAVE_LIBOLEAUT32
/* Define to 1 if you have the `rpcrt4' library (-lrpcrt4). */
#undef HAVE_LIBRPCRT4
/* Define to 1 if you have the `shell32' library (-lshell32). */
#undef HAVE_LIBSHELL32
/* Define to 1 if you have the `shlwapi' library (-lshlwapi). */
#undef HAVE_LIBSHLWAPI
/* Define to 1 if you have the `ssp' library (-lssp). */
#undef HAVE_LIBSSP
/* Define to 1 if you have the `user32' library (-luser32). */
#undef HAVE_LIBUSER32
/* Define to 1 if you have the `uuid' library (-luuid). */
#undef HAVE_LIBUUID
/* Define to 1 if you have the `winmm' library (-lwinmm). */
#undef HAVE_LIBWINMM
/* Define to 1 if you have the `winspool' library (-lwinspool). */
#undef HAVE_LIBWINSPOOL
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
#undef HAVE_LIBWS2_32
/* Define to 1 if you have the `z ' library (-lz ). */
#undef HAVE_LIBZ_
/* Define this symbol if you have malloc_info */
#undef HAVE_MALLOC_INFO
/* Define this symbol if you have mallopt with M_ARENA_MAX */
#undef HAVE_MALLOPT_ARENA_MAX
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <miniupnpc/miniupnpc.h> header file. */
#undef HAVE_MINIUPNPC_MINIUPNPC_H
/* Define to 1 if you have the <miniupnpc/miniwget.h> header file. */
#undef HAVE_MINIUPNPC_MINIWGET_H
/* Define to 1 if you have the <miniupnpc/upnpcommands.h> header file. */
#undef HAVE_MINIUPNPC_UPNPCOMMANDS_H
/* Define to 1 if you have the <miniupnpc/upnperrors.h> header file. */
#undef HAVE_MINIUPNPC_UPNPERRORS_H
/* Define this symbol if you have MSG_DONTWAIT */
#undef HAVE_MSG_DONTWAIT
/* Define this symbol if you have MSG_NOSIGNAL */
#undef HAVE_MSG_NOSIGNAL
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strerror_r' function. */
#undef HAVE_STRERROR_R
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define this symbol if the BSD sysctl(KERN_ARND) is available */
#undef HAVE_SYSCTL_ARND
/* Define to 1 if you have the <sys/endian.h> header file. */
#undef HAVE_SYS_ENDIAN_H
/* Define this symbol if the Linux getrandom system call is available */
#undef HAVE_SYS_GETRANDOM
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define if thread_local is supported. */
#undef HAVE_THREAD_LOCAL
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if the visibility attribute is supported. */
#undef HAVE_VISIBILITY_ATTRIBUTE
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#undef LT_OBJDIR
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Path to the zk params dir during unit tests on windows */
#undef PARAMS_DIR
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
/* Define this symbol if the Qt platform is Cocoa */
#undef QT_QPA_PLATFORM_COCOA
/* Define this symbol if the minimal Qt platform exists */
#undef QT_QPA_PLATFORM_MINIMAL
/* Define this symbol if the Qt platform is Windows */
#undef QT_QPA_PLATFORM_WINDOWS
/* Define this symbol if the Qt platform is XCB */
#undef QT_QPA_PLATFORM_XCB
/* Define this symbol if Qt plugins are static */
#undef QT_STATICPLUGIN
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if strerror_r returns char *. */
#undef STRERROR_R_CHAR_P
/* Define this symbol to build in assembly routines */
#undef USE_ASM
/* Define this symbol if coverage is enabled */
#undef USE_COVERAGE
/* Define if using a custom zk params path */
#undef USE_CUSTOM_PARAMS
/* Define if dbus support should be compiled in */
#undef USE_DBUS
/* Define this symbol to use the gmp implementation */
#undef USE_NUM_GMP
/* Define this symbol to use openssl implementation */
#undef USE_NUM_OPENSSL
/* Define if QTCHARTS support should be compiled in */
#undef USE_QTCHARTS
/* UPnP support not compiled if undefined, otherwise value (0 or 1) determines
default state */
#undef USE_UPNP
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
//#endif //DOGEC_CONFIG_H
// Copyright (c) 2014-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_COMPAT_BYTESWAP_H
#define BITCOIN_COMPAT_BYTESWAP_H*/
#if defined(HAVE_CONFIG_H)
#include <config/dogecash-config.h>
#endif
#include <stdint.h>
#if defined(HAVE_BYTESWAP_H)
#include <byteswap.h>
#endif
#if defined(__APPLE__)
#if !defined(bswap_16)
// Mac OS X / Darwin features; we include a check for bswap_16 because if it is already defined, protobuf has
// defined these macros for us already; if it isn't, we do it ourselves. In either case, we get the exact same
// result regardless which path was taken
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#endif // !defined(bswap_16)
#else
// Non-Mac OS X / non-Darwin
#if HAVE_DECL_BSWAP_16 == 0
inline uint16_t bswap_16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
#endif // HAVE_DECL_BSWAP16 == 0
#if HAVE_DECL_BSWAP_32 == 0
inline uint32_t bswap_32(uint32_t x)
{
return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) |
((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24));
}
#endif // HAVE_DECL_BSWAP32 == 0
#if HAVE_DECL_BSWAP_64 == 0
inline uint64_t bswap_64(uint64_t x)
{
return (((x & 0xff00000000000000ull) >> 56)
| ((x & 0x00ff000000000000ull) >> 40)
| ((x & 0x0000ff0000000000ull) >> 24)
| ((x & 0x000000ff00000000ull) >> 8)
| ((x & 0x00000000ff000000ull) << 8)
| ((x & 0x0000000000ff0000ull) << 24)
| ((x & 0x000000000000ff00ull) << 40)
| ((x & 0x00000000000000ffull) << 56));
}
#endif // HAVE_DECL_BSWAP64 == 0
#endif // defined(__APPLE__)
//#endif // BITCOIN_COMPAT_BYTESWAP_H
// Copyright (c) 2014-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_COMPAT_ENDIAN_H
#define BITCOIN_COMPAT_ENDIAN_H
#if defined(HAVE_CONFIG_H)
#include <config/dogecash-config.h>
#endif*/
//#include <compat/byteswap.h>
#include <stdint.h>
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
#elif defined(HAVE_SYS_ENDIAN_H)
#include <sys/endian.h>
#endif
#ifndef HAVE_CONFIG_H
// While not technically a supported configuration, defaulting to defining these
// DECLs when we were compiled without autotools makes it easier for other build
// systems to build things like libbitcoinconsensus for strange targets.
#ifdef htobe16
#define HAVE_DECL_HTOBE16 1
#endif
#ifdef htole16
#define HAVE_DECL_HTOLE16 1
#endif
#ifdef be16toh
#define HAVE_DECL_BE16TOH 1
#endif
#ifdef le16toh
#define HAVE_DECL_LE16TOH 1
#endif
#ifdef htobe32
#define HAVE_DECL_HTOBE32 1
#endif
#ifdef htole32
#define HAVE_DECL_HTOLE32 1
#endif
#ifdef be32toh
#define HAVE_DECL_BE32TOH 1
#endif
#ifdef le32toh
#define HAVE_DECL_LE32TOH 1
#endif
#ifdef htobe64
#define HAVE_DECL_HTOBE64 1
#endif
#ifdef htole64
#define HAVE_DECL_HTOLE64 1
#endif
#ifdef be64toh
#define HAVE_DECL_BE64TOH 1
#endif
#ifdef le64toh
#define HAVE_DECL_LE64TOH 1
#endif
#endif // HAVE_CONFIG_H
#if defined(WORDS_BIGENDIAN)
#if HAVE_DECL_HTOBE16 == 0
inline uint16_t htobe16(uint16_t host_16bits)
{
return host_16bits;
}
#endif // HAVE_DECL_HTOBE16
#if HAVE_DECL_HTOLE16 == 0
inline uint16_t htole16(uint16_t host_16bits)
{
return bswap_16(host_16bits);
}
#endif // HAVE_DECL_HTOLE16
#if HAVE_DECL_BE16TOH == 0
inline uint16_t be16toh(uint16_t big_endian_16bits)
{
return big_endian_16bits;
}
#endif // HAVE_DECL_BE16TOH
#if HAVE_DECL_LE16TOH == 0
inline uint16_t le16toh(uint16_t little_endian_16bits)
{
return bswap_16(little_endian_16bits);
}
#endif // HAVE_DECL_LE16TOH
#if HAVE_DECL_HTOBE32 == 0
inline uint32_t htobe32(uint32_t host_32bits)
{
return host_32bits;
}
#endif // HAVE_DECL_HTOBE32
#if HAVE_DECL_HTOLE32 == 0
inline uint32_t htole32(uint32_t host_32bits)
{
return bswap_32(host_32bits);
}
#endif // HAVE_DECL_HTOLE32
#if HAVE_DECL_BE32TOH == 0
inline uint32_t be32toh(uint32_t big_endian_32bits)
{
return big_endian_32bits;
}
#endif // HAVE_DECL_BE32TOH
#if HAVE_DECL_LE32TOH == 0
inline uint32_t le32toh(uint32_t little_endian_32bits)
{
return bswap_32(little_endian_32bits);
}
#endif // HAVE_DECL_LE32TOH
#if HAVE_DECL_HTOBE64 == 0
inline uint64_t htobe64(uint64_t host_64bits)
{
return host_64bits;
}
#endif // HAVE_DECL_HTOBE64
#if HAVE_DECL_HTOLE64 == 0
inline uint64_t htole64(uint64_t host_64bits)
{
return bswap_64(host_64bits);
}
#endif // HAVE_DECL_HTOLE64
#if HAVE_DECL_BE64TOH == 0
inline uint64_t be64toh(uint64_t big_endian_64bits)
{
return big_endian_64bits;
}
#endif // HAVE_DECL_BE64TOH
#if HAVE_DECL_LE64TOH == 0
inline uint64_t le64toh(uint64_t little_endian_64bits)
{
return bswap_64(little_endian_64bits);
}
#endif // HAVE_DECL_LE64TOH
#else // WORDS_BIGENDIAN
#if HAVE_DECL_HTOBE16 == 0
inline uint16_t htobe16(uint16_t host_16bits)
{
return bswap_16(host_16bits);
}
#endif // HAVE_DECL_HTOBE16
#if HAVE_DECL_HTOLE16 == 0
inline uint16_t htole16(uint16_t host_16bits)
{
return host_16bits;
}
#endif // HAVE_DECL_HTOLE16
#if HAVE_DECL_BE16TOH == 0
inline uint16_t be16toh(uint16_t big_endian_16bits)
{
return bswap_16(big_endian_16bits);
}
#endif // HAVE_DECL_BE16TOH
#if HAVE_DECL_LE16TOH == 0
inline uint16_t le16toh(uint16_t little_endian_16bits)
{
return little_endian_16bits;
}
#endif // HAVE_DECL_LE16TOH
#if HAVE_DECL_HTOBE32 == 0
inline uint32_t htobe32(uint32_t host_32bits)
{
return bswap_32(host_32bits);
}
#endif // HAVE_DECL_HTOBE32
#if HAVE_DECL_HTOLE32 == 0
inline uint32_t htole32(uint32_t host_32bits)
{
return host_32bits;
}
#endif // HAVE_DECL_HTOLE32
#if HAVE_DECL_BE32TOH == 0
inline uint32_t be32toh(uint32_t big_endian_32bits)
{
return bswap_32(big_endian_32bits);
}
#endif // HAVE_DECL_BE32TOH
#if HAVE_DECL_LE32TOH == 0
inline uint32_t le32toh(uint32_t little_endian_32bits)
{
return little_endian_32bits;
}
#endif // HAVE_DECL_LE32TOH
#if HAVE_DECL_HTOBE64 == 0
inline uint64_t htobe64(uint64_t host_64bits)
{
return bswap_64(host_64bits);
}
#endif // HAVE_DECL_HTOBE64
#if HAVE_DECL_HTOLE64 == 0
inline uint64_t htole64(uint64_t host_64bits)
{
return host_64bits;
}
#endif // HAVE_DECL_HTOLE64
#if HAVE_DECL_BE64TOH == 0
inline uint64_t be64toh(uint64_t big_endian_64bits)
{
return bswap_64(big_endian_64bits);
}
#endif // HAVE_DECL_BE64TOH
#if HAVE_DECL_LE64TOH == 0
inline uint64_t le64toh(uint64_t little_endian_64bits)
{
return little_endian_64bits;
}
#endif // HAVE_DECL_LE64TOH
#endif // WORDS_BIGENDIAN
//#endif // BITCOIN_COMPAT_ENDIAN_H
// Copyright (c) 2014-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_CRYPTO_COMMON_H
#define BITCOIN_CRYPTO_COMMON_H
#if defined(HAVE_CONFIG_H)
#include <config/dogecash-config.h>
#endif*/
#include <stdint.h>
#include <string.h>
//#include <compat/endian.h>
uint16_t static inline ReadLE16(const unsigned char* ptr)
{
uint16_t x;
memcpy((char*)&x, ptr, 2);
return le16toh(x);
}
uint32_t static inline ReadLE32(const unsigned char* ptr)
{
uint32_t x;
memcpy((char*)&x, ptr, 4);
return le32toh(x);
}
uint64_t static inline ReadLE64(const unsigned char* ptr)
{
uint64_t x;
memcpy((char*)&x, ptr, 8);
return le64toh(x);
}
void static inline WriteLE16(unsigned char* ptr, uint16_t x)
{
uint16_t v = htole16(x);
memcpy(ptr, (char*)&v, 2);
}
void static inline WriteLE32(unsigned char* ptr, uint32_t x)
{
uint32_t v = htole32(x);
memcpy(ptr, (char*)&v, 4);
}
void static inline WriteLE64(unsigned char* ptr, uint64_t x)
{
uint64_t v = htole64(x);
memcpy(ptr, (char*)&v, 8);
}
uint32_t static inline ReadBE32(const unsigned char* ptr)
{
uint32_t x;
memcpy((char*)&x, ptr, 4);
return be32toh(x);
}
uint64_t static inline ReadBE64(const unsigned char* ptr)
{
uint64_t x;
memcpy((char*)&x, ptr, 8);
return be64toh(x);
}
void static inline WriteBE32(unsigned char* ptr, uint32_t x)
{
uint32_t v = htobe32(x);
memcpy(ptr, (char*)&v, 4);
}
void static inline WriteBE64(unsigned char* ptr, uint64_t x)
{
uint64_t v = htobe64(x);
memcpy(ptr, (char*)&v, 8);
}
/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */
uint64_t static inline CountBits(uint64_t x)
{
#if HAVE_DECL___BUILTIN_CLZL
if (sizeof(unsigned long) >= sizeof(uint64_t)) {
return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0;
}
#endif
#if HAVE_DECL___BUILTIN_CLZLL
if (sizeof(unsigned long long) >= sizeof(uint64_t)) {
return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0;
}
#endif
int ret = 0;
while (x) {
x >>= 1;
++ret;
}
return ret;
}
//#endif // BITCOIN_CRYPTO_COMMON_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_SUPPORT_CLEANSE_H
#define BITCOIN_SUPPORT_CLEANSE_H*/
#include <stdlib.h>
// Attempt to overwrite data in the specified memory span.
void memory_cleanse(void *ptr, size_t len);
//#endif // BITCOIN_SUPPORT_CLEANSE_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_ALLOCATORS_H
#define BITCOIN_ALLOCATORS_H
#include "support/cleanse.h"*/
#include <map>
#include <string.h>
#include <string>
#include <vector>
//#include <boost/thread/mutex.hpp>
//#include <boost/thread/once.hpp>
/**
* Thread-safe class to keep track of locked (ie, non-swappable) memory pages.
*
* Memory locks do not stack, that is, pages which have been locked several times by calls to mlock()
* will be unlocked by a single call to munlock(). This can result in keying material ending up in swap when
* those functions are used naively. This class simulates stacking memory locks by keeping a counter per page.
*
* @note By using a map from each page base address to lock count, this class is optimized for
* small objects that span up to a few pages, mostly smaller than a page. To support large allocations,
* something like an interval tree would be the preferred data structure.
*/
template <class Locker>
class LockedPageManagerBase
{
public:
LockedPageManagerBase(size_t page_size) : page_size(page_size)
{
// Determine bitmask for extracting page from address
assert(!(page_size & (page_size - 1))); // size must be power of two
page_mask = ~(page_size - 1);
}
~LockedPageManagerBase()
{
}
// For all pages in affected range, increase lock count
void LockRange(void* p, size_t size)
{
std::scoped_lock lock(mutex);
if (!size)
return;
const size_t base_addr = reinterpret_cast<size_t>(p);
const size_t start_page = base_addr & page_mask;
const size_t end_page = (base_addr + size - 1) & page_mask;
for (size_t page = start_page; page <= end_page; page += page_size) {
Histogram::iterator it = histogram.find(page);
if (it == histogram.end()) // Newly locked page
{
locker.Lock(reinterpret_cast<void*>(page), page_size);
histogram.emplace(page, 1);
} else // Page was already locked; increase counter
{
it->second += 1;
}
}
}
// For all pages in affected range, decrease lock count
void UnlockRange(void* p, size_t size)
{
std::scoped_lock lock(mutex);
if (!size)
return;
const size_t base_addr = reinterpret_cast<size_t>(p);
const size_t start_page = base_addr & page_mask;
const size_t end_page = (base_addr + size - 1) & page_mask;
for (size_t page = start_page; page <= end_page; page += page_size) {
Histogram::iterator it = histogram.find(page);
assert(it != histogram.end()); // Cannot unlock an area that was not locked
// Decrease counter for page, when it is zero, the page will be unlocked
it->second -= 1;
if (it->second == 0) // Nothing on the page anymore that keeps it locked
{
// Unlock page and remove the count from histogram
locker.Unlock(reinterpret_cast<void*>(page), page_size);
histogram.erase(it);
}
}
}
// Get number of locked pages for diagnostics
int GetLockedPageCount()
{
std::scoped_lock lock(mutex);
return histogram.size();
}
private:
Locker locker;
std::mutex mutex;
size_t page_size, page_mask;
// map of page base address to lock count
typedef std::map<size_t, int> Histogram;
Histogram histogram;
};
/**
* OS-dependent memory page locking/unlocking.
* Defined as policy class to make stubbing for test possible.
*/
class MemoryPageLocker
{
public:
/** Lock memory pages.
* addr and len must be a multiple of the system page size
*/
bool Lock(const void* addr, size_t len);
/** Unlock memory pages.
* addr and len must be a multiple of the system page size
*/
bool Unlock(const void* addr, size_t len);
};
/**
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
* std::allocator templates.
*
* Some implementations of the STL allocate memory in some constructors (i.e., see
* MSVC's vector<T> implementation where it allocates 1 byte of memory in the allocator.)
* Due to the unpredictable order of static initializers, we have to make sure the
* LockedPageManager instance exists before any other STL-based objects that use
* secure_allocator are created. So instead of having LockedPageManager also be
* static-initialized, it is created on demand.
*/
class LockedPageManager : public LockedPageManagerBase<MemoryPageLocker>
{
public:
static LockedPageManager& Instance()
{
std::call_once(LockedPageManager::init_flag , LockedPageManager::CreateInstance);
return *LockedPageManager::_instance;
}
private:
LockedPageManager();
static void CreateInstance()
{
// Using a local static instance guarantees that the object is initialized
// when it's first needed and also deinitialized after all objects that use
// it are done with it. I can think of one unlikely scenario where we may
// have a static deinitialization order/problem, but the check in
// LockedPageManagerBase's destructor helps us detect if that ever happens.
static LockedPageManager instance;
LockedPageManager::_instance = &instance;
}
static LockedPageManager* _instance;
static std::once_flag init_flag;
};
//
// Allocator that locks its contents from being paged
// out of memory and clears its contents before deletion.
//
template <typename T>
struct secure_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> base;
typedef typename base::size_type size_type;
typedef typename base::difference_type difference_type;
typedef typename std::allocator_traits<base>::pointer pointer;
typedef typename std::allocator_traits<base>::const_pointer const_pointer;
typedef T& reference;
typedef const T& const_reference;
//typedef typename std::allocator_traits<base>::reference reference;
//typedef typename std::allocator_traits<base>::const_reference const_reference;
typedef typename base::value_type value_type;
secure_allocator() throw() {}
secure_allocator(const secure_allocator& a) throw() : base(a) {}
template <typename U>
secure_allocator(const secure_allocator<U>& a) throw() : base(a)
{
}
~secure_allocator() throw() {}
template <typename _Other>
struct rebind {
typedef secure_allocator<_Other> other;
};
T* allocate(std::size_t n)
{
T* p;
p = std::allocator<T>::allocate(n);
if (p != NULL)
LockedPageManager::Instance().LockRange(p, sizeof(T) * n);
return p;
}
void deallocate(T* p, std::size_t n)
{
if (p != NULL) {
memory_cleanse(p, sizeof(T) * n);
LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n);
}
std::allocator<T>::deallocate(p, n);
}
/*T* allocate(std::size_t n, const void* hint = 0)
{
T* p;
p = std::allocator<T>::allocate(n, hint);
if (p != NULL)
LockedPageManager::Instance().LockRange(p, sizeof(T) * n);
return p;
}
void deallocate(T* p, std::size_t n)
{
if (p != NULL) {
memory_cleanse(p, sizeof(T) * n);
LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n);
}
std::allocator<T>::deallocate(p, n);
}*/
};
//
// Allocator that clears its contents before deletion.
//
template <typename T>
struct zero_after_free_allocator : public std::allocator<T> {
// MSVC8 default copy constructor is broken
typedef std::allocator<T> base;
typedef typename base::size_type size_type;
typedef typename base::difference_type difference_type;
typedef typename base::pointer pointer;
typedef typename base::const_pointer const_pointer;
typedef typename base::reference reference;
typedef typename base::const_reference const_reference;
typedef typename base::value_type value_type;
zero_after_free_allocator() throw() {}
zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
template <typename U>
zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a)
{
}
~zero_after_free_allocator() throw() {}
template <typename _Other>
struct rebind {
typedef zero_after_free_allocator<_Other> other;
};
void deallocate(T* p, std::size_t n)
{
if (p != NULL)
memory_cleanse(p, sizeof(T) * n);
std::allocator<T>::deallocate(p, n);
}
};
// This is exactly like std::string, but with a custom allocator.
typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
// Byte-vector that clears its contents before deletion.
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
//#endif // BITCOIN_ALLOCATORS_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2017-2019 The PIVX developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/**
* Utilities for converting data from/to strings.
*/
/*#ifndef BITCOIN_UTILSTRENCODINGS_H
#define BITCOIN_UTILSTRENCODINGS_H
#include "allocators.h"*/
#include <stdint.h>
#include <string>
#include <vector>
#define BEGIN(a) ((char*)&(a))
#define END(a) ((char*)&((&(a))[1]))
#define UBEGIN(a) ((unsigned char*)&(a))
#define UEND(a) ((unsigned char*)&((&(a))[1]))
#define ARRAYLEN(array) (sizeof(array) / sizeof((array)[0]))
/** Used by SanitizeString() */
enum SafeChars
{
SAFE_CHARS_DEFAULT, //!< The full set of allowed chars
SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset
SAFE_CHARS_FILENAME, //!< Chars allowed in filenames
};
/**
* Remove unsafe chars. Safe chars chosen to allow simple messages/URLs/email
* addresses, but avoid anything even possibly remotely dangerous like & or >
* @param[in] str The string to sanitize
* @param[in] rule The set of safe chars to choose (default: least restrictive)
* @return A new string without unsafe chars
*/
std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT);
/**
* Check URL format for conformance for validity to a defined pattern
* @param[in] strURL The string to be processed for validity
* @param[in] stdErr A string that will be loaded with any validation error message
* @param[in] maxSize An unsigned int, defaulted to 64, to restrict the length
* @return A bool, true if valid, false if not (reason in stdErr)
*/
bool validateURL(std::string strURL, std::string& strErr, unsigned int maxSize = 64);
std::vector<unsigned char> ParseHex(const char* psz);
std::vector<unsigned char> ParseHex(const std::string& str);
signed char HexDigit(char c);
bool IsHex(const std::string& str);
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
std::string DecodeBase64(const std::string& str);
std::string EncodeBase64(const unsigned char* pch, size_t len);
std::string EncodeBase64(const std::string& str);
SecureString DecodeBase64Secure(const SecureString& input);
SecureString EncodeBase64Secure(const SecureString& input);
std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
std::string DecodeBase32(const std::string& str);
std::string EncodeBase32(const unsigned char* pch, size_t len);
std::string EncodeBase32(const std::string& str);
std::string i64tostr(int64_t n);
std::string itostr(int n);
int64_t atoi64(const char* psz);
int64_t atoi64(const std::string& str);
int atoi(const std::string& str);
/**
* Tests if the given character is a decimal digit.
* @param[in] c character to test
* @return true if the argument is a decimal digit; otherwise false.
*/
constexpr bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
/**
* Convert string to signed 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseInt32(const std::string& str, int32_t *out);
/**
* Convert string to signed 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseInt64(const std::string& str, int64_t *out);
/**
* Convert string to double with strict parse error feedback.
* @returns true if the entire string could be parsed as valid double,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
bool ParseDouble(const std::string& str, double *out);
/* Return iterator to first non zero element, or itend */
template <typename T>
T FindFirstNonZero(T itbegin, T itend)
{
return std::find_if(itbegin, itend, [](unsigned char v) { return v != 0; });
}
template <typename T>
std::string HexStr(const T itbegin, const T itend, bool fSpaces = false)
{
std::string rv;
static const char hexmap[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
rv.reserve((itend - itbegin) * 3);
for (T it = itbegin; it < itend; ++it) {
unsigned char val = (unsigned char)(*it);
if (fSpaces && it != itbegin)
rv.push_back(' ');
rv.push_back(hexmap[val >> 4]);
rv.push_back(hexmap[val & 15]);
}
return rv;
}
template <typename T>
inline std::string HexStr(const T& vch, bool fSpaces = false)
{
return HexStr(vch.begin(), vch.end(), fSpaces);
}
template <typename T>
inline std::string HexStrTrimmed(const T& vch, bool fSpaces = false)
{
return HexStr(vch.begin(), FindFirstNonZero(vch.rbegin(), vch.rend()).base(), fSpaces);
}
/** Reverse the endianess of a string */
inline std::string ReverseEndianString(std::string in)
{
std::string out = "";
unsigned int s = in.size();
for (unsigned int i = 0; i < s; i += 2) {
out += in.substr(s - i - 2, 2);
}
return out;
}
/**
* Format a paragraph of text to a fixed width, adding spaces for
* indentation to any added line.
*/
std::string FormatParagraph(const std::string in, size_t width = 79, size_t indent = 0);
/**
* Timing-attack-resistant comparison.
* Takes time proportional to length
* of first argument.
*/
template <typename T>
bool TimingResistantEqual(const T& a, const T& b)
{
if (b.size() == 0) return a.size() == 0;
size_t accumulator = a.size() ^ b.size();
for (size_t i = 0; i < a.size(); i++)
accumulator |= a[i] ^ b[i % b.size()];
return accumulator == 0;
}
/**
* Convert from one power-of-2 number base to another.
*
* Examples using ConvertBits<8, 5, true>():
* 000000 -> 0000000000
* 202020 -> 0400100200
* 757575 -> 0e151a170a
* abcdef -> 150f061e1e
* ffffff -> 1f1f1f1f1e
*/
template<int frombits, int tobits, bool pad, typename O, typename I>
bool ConvertBits(const O& outfn, I it, I end) {
size_t acc = 0;
size_t bits = 0;
constexpr size_t maxv = (1 << tobits) - 1;
constexpr size_t max_acc = (1 << (frombits + tobits - 1)) - 1;
while (it != end) {
acc = ((acc << frombits) | *it) & max_acc;
bits += frombits;
while (bits >= tobits) {
bits -= tobits;
outfn((acc >> bits) & maxv);
}
++it;
}
if (pad) {
if (bits) outfn((acc << (tobits - bits)) & maxv);
} else if (bits >= frombits || ((acc << (tobits - bits)) & maxv)) {
return false;
}
return true;
}
/** Parse number as fixed point according to JSON number syntax.
* See http://json.org/number.gif
* @returns true on success, false on error.
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
*/
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
/**
* Converts the given character to its lowercase equivalent.
* This function is locale independent. It only converts uppercase
* characters in the standard 7-bit ASCII range.
* @param[in] c the character to convert to lowercase.
* @return the lowercase equivalent of c; or the argument
* if no conversion is possible.
*/
constexpr unsigned char ToLower(unsigned char c)
{
return (c >= 'A' && c <= 'Z' ? (c - 'A') + 'a' : c);
}
/**
* Converts the given string to its lowercase equivalent.
* This function is locale independent. It only converts uppercase
* characters in the standard 7-bit ASCII range.
* @param[in,out] str the string to convert to lowercase.
*/
void Downcase(std::string& str);
/**
* Converts the given character to its uppercase equivalent.
* This function is locale independent. It only converts lowercase
* characters in the standard 7-bit ASCII range.
* @param[in] c the character to convert to uppercase.
* @return the uppercase equivalent of c; or the argument
* if no conversion is possible.
*/
constexpr unsigned char ToUpper(unsigned char c)
{
return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
}
/**
* Capitalizes the first character of the given string.
* This function is locale independent. It only capitalizes the
* first character of the argument if it has an uppercase equivalent
* in the standard 7-bit ASCII range.
* @param[in] str the string to capitalize.
* @return string with the first letter capitalized.
*/
std::string Capitalize(std::string str);
/**
* Checks for valid 4-byte UTF-8 encoding in a string
* @param[in] str the string to check.
* @return boolean. true for valid UTF-8 encoding.
*/
bool IsValidUTF8(const std::string& str);
//#endif // BITCOIN_UTILSTRENCODINGS_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2018 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef DOGEC_BLOB_UINT256_H
#define DOGEC_BLOB_UINT256_H*/
#include <assert.h>
#include <cstring>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
/** Template base class for fixed-sized opaque blobs. */
template<unsigned int BITS>
class base_blob
{
public:
// todo: make this protected
enum { WIDTH=BITS/8 };
uint8_t data[WIDTH];
base_blob()
{
SetNull();
}
explicit base_blob(const std::vector<unsigned char>& vch);
bool IsNull() const
{
for (int i = 0; i < WIDTH; i++)
if (data[i] != 0)
return false;
return true;
}
void SetNull()
{
memset(data, 0, sizeof(data));
}
friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; }
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; }
friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; }
std::string GetHex() const;
void SetHex(const char* psz);
void SetHex(const std::string& str);
std::string ToString() const;
unsigned char* begin()
{
return &data[0];
}
unsigned char* end()
{
return &data[WIDTH];
}
const unsigned char* begin() const
{
return &data[0];
}
const unsigned char* end() const
{
return &data[WIDTH];
}
unsigned int size() const
{
return sizeof(data);
}
uint64_t GetUint64(int pos) const
{
const uint8_t* ptr = data + pos * 8;
return ((uint64_t)ptr[0]) | \
((uint64_t)ptr[1]) << 8 | \
((uint64_t)ptr[2]) << 16 | \
((uint64_t)ptr[3]) << 24 | \
((uint64_t)ptr[4]) << 32 | \
((uint64_t)ptr[5]) << 40 | \
((uint64_t)ptr[6]) << 48 | \
((uint64_t)ptr[7]) << 56;
}
template<typename Stream>
void Serialize(Stream& s) const
{
s.write((char*)data, sizeof(data));
}
template<typename Stream>
void Unserialize(Stream& s)
{
s.read((char*)data, sizeof(data));
}
};
/** 88-bit opaque blob.
*/
class blob88 : public base_blob<88> {
public:
blob88() {}
blob88(const base_blob<88>& b) : base_blob<88>(b) {}
explicit blob88(const std::vector<unsigned char>& vch) : base_blob<88>(vch) {}
};
/** 256-bit opaque blob.
* @note This type is called uint256 for historical reasons only. It is an
* opaque blob of 256 bits and has no integer operations. Use arith_uint256 if
* those are required.
*/
class blob_uint256 : public base_blob<256> {
public:
blob_uint256() {}
blob_uint256(const base_blob<256>& b) : base_blob<256>(b) {}
explicit blob_uint256(const std::vector<unsigned char>& vch) : base_blob<256>(vch) {}
/** A cheap hash function that just returns 64 bits from the result, it can be
* used when the contents are considered uniformly random. It is not appropriate
* when the value can easily be influenced from outside as e.g. a network adversary could
* provide values to trigger worst-case behavior.
* @note The result of this function is not stable between little and big endian.
*/
uint64_t GetCheapHash() const
{
uint64_t result;
memcpy((void*)&result, (void*)data, 8);
return result;
}
};
/* uint256 from const char *.
* This is a separate function because the constructor uint256(const char*) can result
* in dangerously catching uint256(0).
*/
inline blob_uint256 blob_uint256S(const char *str)
{
blob_uint256 rv;
rv.SetHex(str);
return rv;
}
/* uint256 from std::string.
* This is a separate function because the constructor uint256(const std::string &str) can result
* in dangerously catching uint256(0) via std::string(const char*).
*/
inline blob_uint256 blob_uint256S(const std::string& str)
{
return blob_uint256S(str.c_str());
}
/** constant uint256 instances */
const blob_uint256 BLOB_UINT256_ZERO = blob_uint256();
const blob_uint256 BLOB_UINT256_ONE = blob_uint256S("0000000000000000000000000000000000000000000000000000000000000001");
//#endif // DOGEC_BLOB_UINT256_H
// Copyright (c) 2017-2020 The PIVX Developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef DOGEC_UINT512_H
#define DOGEC_UINT512_H*/
//#include "arith_uint256.h"
//#include "blob_uint256.h"
/** 512-bit unsigned big integer. */
class blob_uint512 : public base_blob<512>
{
public:
blob_uint512() {}
blob_uint512(const base_blob<512>& b) : base_blob<512>(b) {}
explicit blob_uint512(const std::vector<unsigned char>& vch) : base_blob<512>(vch) {}
blob_uint256 trim256() const
{
std::vector<unsigned char> vch;
const unsigned char* p = this->begin();
for (unsigned int i = 0; i < 32; i++) {
vch.push_back(*p++);
}
return blob_uint256(vch);
}
};
/* uint256 from const char *.
* This is a separate function because the constructor uint256(const char*) can result
* in dangerously catching UINT256_ZERO.
*/
inline blob_uint512 blob_uint512S(const char* str)
{
blob_uint512 rv;
rv.SetHex(str);
return rv;
}
//#endif // DOGEC_UINT512_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_ARITH_UINT256_H
#define BITCOIN_ARITH_UINT256_H*/
//#include "blob_uint256.h"
//#include "uint512.h"
#include <assert.h>
#include <cstring>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
class blob_uint512;
class blob_uint256;
class uint256;
class uint512;
class uint_error : public std::runtime_error {
public:
explicit uint_error(const std::string& str) : std::runtime_error(str) {}
};
/** Template base class for unsigned big integers. */
template<unsigned int BITS>
class base_uint
{
public:
enum { WIDTH=BITS/32 };
uint32_t pn[WIDTH];
base_uint()
{
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
}
base_uint(const base_uint& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] = b.pn[i];
}
base_uint& operator=(const base_uint& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] = b.pn[i];
return *this;
}
base_uint(uint64_t b)
{
pn[0] = (unsigned int)b;
pn[1] = (unsigned int)(b >> 32);
for (int i = 2; i < WIDTH; i++)
pn[i] = 0;
}
explicit base_uint(const std::string& str);
explicit base_uint(const std::vector<unsigned char>& vch);
bool operator!() const
{
for (int i = 0; i < WIDTH; i++)
if (pn[i] != 0)
return false;
return true;
}
const base_uint operator~() const
{
base_uint ret;
for (int i = 0; i < WIDTH; i++)
ret.pn[i] = ~pn[i];
return ret;
}
const base_uint operator-() const
{
base_uint ret;
for (int i = 0; i < WIDTH; i++)
ret.pn[i] = ~pn[i];
ret++;
return ret;
}
double getdouble() const;
base_uint& operator=(uint64_t b)
{
pn[0] = (unsigned int)b;
pn[1] = (unsigned int)(b >> 32);
for (int i = 2; i < WIDTH; i++)
pn[i] = 0;
return *this;
}
base_uint& operator^=(const base_uint& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] ^= b.pn[i];
return *this;
}
base_uint& operator&=(const base_uint& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] &= b.pn[i];
return *this;
}
base_uint& operator|=(const base_uint& b)
{
for (int i = 0; i < WIDTH; i++)
pn[i] |= b.pn[i];
return *this;
}
base_uint& operator^=(uint64_t b)
{
pn[0] ^= (unsigned int)b;
pn[1] ^= (unsigned int)(b >> 32);
return *this;
}
base_uint& operator|=(uint64_t b)
{
pn[0] |= (unsigned int)b;
pn[1] |= (unsigned int)(b >> 32);
return *this;
}
base_uint& operator<<=(unsigned int shift);
base_uint& operator>>=(unsigned int shift);
base_uint& operator+=(const base_uint& b)
{
uint64_t carry = 0;
for (int i = 0; i < WIDTH; i++)
{
uint64_t n = carry + pn[i] + b.pn[i];
pn[i] = n & 0xffffffff;
carry = n >> 32;
}
return *this;
}
base_uint& operator-=(const base_uint& b)
{
*this += -b;
return *this;
}
base_uint& operator+=(uint64_t b64)
{
base_uint b;
b = b64;
*this += b;
return *this;
}
base_uint& operator-=(uint64_t b64)
{
base_uint b;
b = b64;
*this += -b;
return *this;
}
base_uint& operator*=(uint32_t b32);
base_uint& operator*=(const base_uint& b);
base_uint& operator/=(const base_uint& b);
base_uint& operator++()
{
// prefix operator
int i = 0;
while (++pn[i] == 0 && i < WIDTH-1)
i++;
return *this;
}
const base_uint operator++(int)
{
// postfix operator
const base_uint ret = *this;
++(*this);
return ret;
}
base_uint& operator--()
{
// prefix operator
int i = 0;
while (--pn[i] == (uint32_t)-1 && i < WIDTH-1)
i++;
return *this;
}
const base_uint operator--(int)
{
// postfix operator
const base_uint ret = *this;
--(*this);
return ret;
}
int CompareTo(const base_uint& b) const;
bool EqualTo(uint64_t b) const;
friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; }
friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; }
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; }
friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; }
friend inline bool operator<=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) <= 0; }
friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); }
friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); }
std::string GetHex() const;
void SetHex(const char* psz);
void SetHex(const std::string& str);
std::string ToString() const;
std::string ToStringReverseEndian() const;
unsigned char* begin()
{
return (unsigned char*)&pn[0];
}
unsigned char* end()
{
return (unsigned char*)&pn[WIDTH];
}
const unsigned char* begin() const
{
return (unsigned char*)&pn[0];
}
const unsigned char* end() const
{
return (unsigned char*)&pn[WIDTH];
}
unsigned int size() const
{
return sizeof(pn);
}
uint64_t Get64(int n = 0) const
{
return pn[2 * n] | (uint64_t)pn[2 * n + 1] << 32;
}
uint32_t Get32(int n = 0) const
{
return pn[2 * n];
}
/**
* Returns the position of the highest bit set plus one, or zero if the
* value is zero.
*/
unsigned int bits() const;
uint64_t GetLow64() const
{
assert(WIDTH >= 2);
return pn[0] | (uint64_t)pn[1] << 32;
}
template<typename Stream>
void Serialize(Stream& s) const
{
s.write((char*)pn, sizeof(pn));
}
template<typename Stream>
void Unserialize(Stream& s)
{
s.read((char*)pn, sizeof(pn));
}
// Temporary for migration to blob160/256
uint64_t GetCheapHash() const
{
return GetLow64();
}
void SetNull()
{
memset(pn, 0, sizeof(pn));
}
bool IsNull() const
{
for (int i = 0; i < WIDTH; i++)
if (pn[i] != 0)
return false;
return true;
}
friend class uint160;
friend class uint256;
friend class uint512;
friend class arith_uint160;
friend class arith_uint256;
friend class arith_uint512;
};
/** 160-bit unsigned big integer. */
class arith_uint160 : public base_uint<160> {
public:
arith_uint160() {}
arith_uint160(const base_uint<160>& b) : base_uint<160>(b) {}
arith_uint160(uint64_t b) : base_uint<160>(b) {}
explicit arith_uint160(const std::string& str) : base_uint<160>(str) {}
explicit arith_uint160(const std::vector<unsigned char>& vch) : base_uint<160>(vch) {}
};
/** 256-bit unsigned big integer. */
class arith_uint256 : public base_uint<256> {
public:
arith_uint256() {}
arith_uint256(const base_uint<256>& b) : base_uint<256>(b) {}
arith_uint256(uint64_t b) : base_uint<256>(b) {}
explicit arith_uint256(const std::string& str) : base_uint<256>(str) {}
explicit arith_uint256(const std::vector<unsigned char>& vch) : base_uint<256>(vch) {}
/**
* The "compact" format is a representation of a whole
* number N using an unsigned 32bit number similar to a
* floating point format.
* The most significant 8 bits are the unsigned exponent of base 256.
* This exponent can be thought of as "number of bytes of N".
* The lower 23 bits are the mantissa.
* Bit number 24 (0x800000) represents the sign of N.
* N = (-1^sign) * mantissa * 256^(exponent-3)
*
* Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn().
* MPI uses the most significant bit of the first byte as sign.
* Thus 0x1234560000 is compact (0x05123456)
* and 0xc0de000000 is compact (0x0600c0de)
*
* Bitcoin only uses this "compact" format for encoding difficulty
* targets, which are unsigned 256bit quantities. Thus, all the
* complexities of the sign bit and using base 256 are probably an
* implementation accident.
*/
arith_uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL);
uint32_t GetCompact(bool fNegative = false) const;
uint32_t Get32(int n = 0) const { return pn[2 * n]; }
};
/** 512-bit unsigned big integer. */
class arith_uint512 : public base_uint<512> {
public:
arith_uint512() {}
arith_uint512(const base_uint<512>& b) : base_uint<512>(b) {}
arith_uint512(uint64_t b) : base_uint<512>(b) {}
explicit arith_uint512(const std::string& str) : base_uint<512>(str) {}
explicit arith_uint512(const std::vector<unsigned char>& vch) : base_uint<512>(vch) {}
//friend arith_uint512 UintToArith512(const blob_uint512 &a);
//friend blob_uint512 ArithToUint512(const arith_uint512 &a);
};
/** Old classes definitions */
/** End classes definitions */
const arith_uint256 ARITH_UINT256_ZERO = arith_uint256();
//#endif // BITCOIN_UINT256_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2017-2020 The PIVX Developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef DOGEC_UINT256_H
#define DOGEC_UINT256_H*/
//#include "arith_uint256.h"
#include <assert.h>
#include <cstring>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <vector>
//
// This is a migration file class, as soon as we move every
// uint256 field used, invalidly, as a number to the proper arith_uint256, this will be replaced
// with the blob_uint256 file.
//
/** 160-bit opaque blob.
* @note This type is called uint160 for historical reasons only. It is an opaque
* blob of 160 bits and has no integer operations.
*/
class uint160 : public base_blob<160> {
public:
uint160() {}
uint160(const base_blob<160>& b) : base_blob<160>(b) {}
explicit uint160(const std::vector<unsigned char>& vch) : base_blob<160>(vch) {}
};
/** 256-bit unsigned big integer. */
class uint256 : public base_uint<256>
{
public:
uint256() {}
uint256(const base_uint<256>& b) : base_uint<256>(b) {}
uint256(uint64_t b) : base_uint<256>(b) {}
explicit uint256(const std::string& str) : base_uint<256>(str) {}
explicit uint256(const std::vector<unsigned char>& vch) : base_uint<256>(vch) {}
/**
* The "compact" format is a representation of a whole
* number N using an unsigned 32bit number similar to a
* floating point format.
* The most significant 8 bits are the unsigned exponent of base 256.
* This exponent can be thought of as "number of bytes of N".
* The lower 23 bits are the mantissa.
* Bit number 24 (0x800000) represents the sign of N.
* N = (-1^sign) * mantissa * 256^(exponent-3)
*
* Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn().
* MPI uses the most significant bit of the first byte as sign.
* Thus 0x1234560000 is compact (0x05123456)
* and 0xc0de000000 is compact (0x0600c0de)
*
* Bitcoin only uses this "compact" format for encoding difficulty
* targets, which are unsigned 256bit quantities. Thus, all the
* complexities of the sign bit and using base 256 are probably an
* implementation accident.
*/
uint256& SetCompact(uint32_t nCompact, bool* pfNegative = nullptr, bool* pfOverflow = nullptr);
uint32_t GetCompact(bool fNegative = false) const;
uint64_t GetUint64(int pos) const
{
const uint8_t* ptr = (uint8_t*) pn + pos * 8;
return ((uint64_t)ptr[0]) | \
((uint64_t)ptr[1]) << 8 | \
((uint64_t)ptr[2]) << 16 | \
((uint64_t)ptr[3]) << 24 | \
((uint64_t)ptr[4]) << 32 | \
((uint64_t)ptr[5]) << 40 | \
((uint64_t)ptr[6]) << 48 | \
((uint64_t)ptr[7]) << 56;
}
};
/** 512-bit unsigned big integer. */
class uint512 : public base_uint<512>
{
public:
uint512() {}
uint512(const base_uint<512>& b) : base_uint<512>(b) {}
uint512(uint64_t b) : base_uint<512>(b) {}
explicit uint512(const std::string& str) : base_uint<512>(str) {}
explicit uint512(const std::vector<unsigned char>& vch) : base_uint<512>(vch) {}
uint256 trim256() const
{
uint256 ret;
for (unsigned int i = 0; i < uint256::WIDTH; i++) {
ret.pn[i] = pn[i];
}
return ret;
}
friend arith_uint512 UintToArith512(const uint512 &a);
friend uint512 ArithToUint512(const arith_uint512 &a);
};
/* uint256 from const char *.
* This is a separate function because the constructor uint256(const char*) can result
* in dangerously catching UINT256_ZERO.
*/
inline uint256 uint256S(const char* str)
{
uint256 rv;
rv.SetHex(str);
return rv;
}
/* uint256 from std::string.
* This is a separate function because the constructor uint256(const std::string &str) can result
* in dangerously catching UINT256_ZERO via std::string(const char*).
*/
inline uint256 uint256S(const std::string& str)
{
uint256 rv;
rv.SetHex(str);
return rv;
}
inline uint512 uint512S(const std::string& str)
{
uint512 rv;
rv.SetHex(str);
return rv;
}
uint256 ArithToUint256(const arith_uint256 &);
arith_uint256 UintToArith256(const uint256 &);
uint512 ArithToUint512(const arith_uint512 &);
arith_uint512 UintToArith512(const uint512 &);
/** constant uint256 instances */
const uint256 UINT256_ZERO = uint256();
const uint256 UINT256_ONE = uint256("0000000000000000000000000000000000000000000000000000000000000001");
const uint256 UINT256_MAX = uint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
//#endif // DOGEC_UINT256_H
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2017-2019 The PIVX developers
// Copyright (c) 2020 The DogeCash Developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
/*#ifndef BITCOIN_BIGNUM_H
#define BITCOIN_BIGNUM_H*/
/*#if defined HAVE_CONFIG_H
#include "config/dogecash-config.h"
#endif*/
/*#if defined(USE_NUM_OPENSSL)*/
#include <openssl/bn.h>
/*#endif
#if defined(USE_NUM_GMP)
#include <gmp.h>
#endif*/
#include <stdexcept>
#include <vector>
#include <limits.h>
/*#include "serialize.h"
#include "uint256.h"
#include "version.h"
#include "random.h"*/
/** Errors thrown by the bignum class */
class bignum_error : public std::runtime_error
{
public:
explicit bignum_error(const std::string& str) : std::runtime_error(str) {}
};
/** C++ wrapper for BIGNUM */
class CBigNum
{
//#if defined(USE_NUM_OPENSSL)
BIGNUM* bn;
/*#endif
#if defined(USE_NUM_GMP)
mpz_t bn;
#endif*/
public:
CBigNum();
CBigNum(const CBigNum& b);
CBigNum& operator=(const CBigNum& b);
~CBigNum();
//CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'.
CBigNum(signed char n);
CBigNum(short n);
CBigNum(int n);
CBigNum(long n);
CBigNum(long long n);
CBigNum(unsigned char n);
CBigNum(unsigned short n);
CBigNum(unsigned int n);
CBigNum(unsigned long n);
CBigNum(unsigned long long n);
explicit CBigNum(uint256 n);
explicit CBigNum(const std::vector<unsigned char>& vch);
/** Generates a cryptographically secure random number between zero and range exclusive
* i.e. 0 < returned number < range
* @param range The upper bound on the number.
* @return
*/
static CBigNum randBignum(const CBigNum& range);
/** Generates a cryptographically secure random k-bit number
* @param k The bit length of the number.
* @return
*/
static CBigNum randKBitBignum(const uint32_t k);
/**Returns the size in bits of the underlying bignum.
*
* @return the size
*/
int bitSize() const;
void setulong(unsigned long n);
unsigned long getulong() const;
unsigned int getuint() const;
int getint() const;
void setint64(int64_t sn);
void setuint64(uint64_t n);
void setuint256(uint256 n);
uint256 getuint256() const;
void setvch(const std::vector<unsigned char>& vch);
std::vector<unsigned char> getvch() const;
void SetDec(const std::string& str);
void SetHex(const std::string& str);
bool SetHexBool(const std::string& str);
std::string ToString(int nBase=10) const;
std::string GetHex() const;
std::string GetDec() const;
/*template<typename Stream>
void Serialize(Stream& s) const
{
::Serialize(s, getvch());
}
template<typename Stream>
void Unserialize(Stream& s)
{
std::vector<unsigned char> vch;
::Unserialize(s, vch);
setvch(vch);
}*/
/**
* exponentiation with an int. this^e
* @param e the exponent as an int
* @return
*/
CBigNum pow(const int e) const;
/**
* exponentiation this^e
* @param e the exponent
* @return
*/
CBigNum pow(const CBigNum& e) const;
/**
* modular multiplication: (this * b) mod m
* @param b operand
* @param m modulus
*/
CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const;
/**
* modular exponentiation: this^e mod n
* @param e exponent
* @param m modulus
*/
CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const;
/**
* Calculates the inverse of this element mod m.
* i.e. i such this*i = 1 mod m
* @param m the modu
* @return the inverse
*/
CBigNum inverse(const CBigNum& m) const;
/**
* Generates a random (safe) prime of numBits bits
* @param numBits the number of bits
* @param safe true for a safe prime
* @return the prime
*/
static CBigNum generatePrime(const unsigned int numBits, bool safe = false);
/**
* Calculates the greatest common divisor (GCD) of two numbers.
* @param m the second element
* @return the GCD
*/
CBigNum gcd( const CBigNum& b) const;
/**
* Miller-Rabin primality test on this element
* @param checks: optional, the number of Miller-Rabin tests to run
* default causes error rate of 2^-80.
* @return true if prime
*/
/*#if defined(USE_NUM_OPENSSL)
bool isPrime(const int checks=BN_prime_checks) const;
#endif
#if defined(USE_NUM_GMP)
bool isPrime(const int checks=15) const;
#endif*/
bool isOne() const;
bool operator!() const;
CBigNum& operator+=(const CBigNum& b);
CBigNum& operator-=(const CBigNum& b);
CBigNum& operator*=(const CBigNum& b);
CBigNum& operator/=(const CBigNum& b);
CBigNum& operator%=(const CBigNum& b);
CBigNum& operator<<=(unsigned int shift);
CBigNum& operator>>=(unsigned int shift);
CBigNum& operator++();
const CBigNum operator++(int);
CBigNum& operator--();
const CBigNum operator--(int);
friend inline const CBigNum operator+(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator*(const CBigNum& a, const CBigNum& b);
friend inline const CBigNum operator<<(const CBigNum& a, unsigned int shift);
friend inline const CBigNum operator-(const CBigNum& a);
friend inline bool operator==(const CBigNum& a, const CBigNum& b);
friend inline bool operator!=(const CBigNum& a, const CBigNum& b);
friend inline bool operator<=(const CBigNum& a, const CBigNum& b);
friend inline bool operator>=(const CBigNum& a, const CBigNum& b);
friend inline bool operator<(const CBigNum& a, const CBigNum& b);
friend inline bool operator>(const CBigNum& a, const CBigNum& b);
};
//#if defined(USE_NUM_OPENSSL)
class CAutoBN_CTX
{
protected:
BN_CTX* pctx;
BN_CTX* operator=(BN_CTX* pnew) { return pctx = pnew; }
public:
CAutoBN_CTX()
{
pctx = BN_CTX_new();
if (pctx == NULL)
throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL");
}
~CAutoBN_CTX()
{
if (pctx != NULL)
BN_CTX_free(pctx);
}
operator BN_CTX*() { return pctx; }
BN_CTX& operator*() { return *pctx; }
BN_CTX** operator&() { return &pctx; }
bool operator!() { return (pctx == NULL); }
};
inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) {
CBigNum r;
if (!BN_add(r.bn, a.bn, b.bn))
throw bignum_error("CBigNum::operator+ : BN_add failed");
return r;
}
inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) {
CBigNum r;
if (!BN_sub(r.bn, a.bn, b.bn))
throw bignum_error("CBigNum::operator- : BN_sub failed");
return r;
}
inline const CBigNum operator-(const CBigNum& a) {
CBigNum r(a);
BN_set_negative(r.bn, !BN_is_negative(r.bn));
return r;
}
inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) {
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_mul(r.bn, a.bn, b.bn, pctx))
throw bignum_error("CBigNum::operator* : BN_mul failed");
return r;
}
inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) {
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_div(r.bn, NULL, a.bn, b.bn, pctx))
throw bignum_error("CBigNum::operator/ : BN_div failed");
return r;
}
inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) {
CAutoBN_CTX pctx;
CBigNum r;
if (!BN_nnmod(r.bn, a.bn, b.bn, pctx))
throw bignum_error("CBigNum::operator% : BN_div failed");
return r;
}
inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) {
CBigNum r;
if (!BN_lshift(r.bn, a.bn, shift))
throw bignum_error("CBigNum:operator<< : BN_lshift failed");
return r;
}
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) {
CBigNum r = a;
r >>= shift;
return r;
}
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) == 0); }
inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) != 0); }
inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) <= 0); }
inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) >= 0); }
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) < 0); }
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.bn, b.bn) > 0); }
//#endif
/*#if defined(USE_NUM_GMP)
inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) {
CBigNum r;
mpz_add(r.bn, a.bn, b.bn);
return r;
}
inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) {
CBigNum r;
mpz_sub(r.bn, a.bn, b.bn);
return r;
}
inline const CBigNum operator-(const CBigNum& a) {
CBigNum r;
mpz_neg(r.bn, a.bn);
return r;
}
inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) {
CBigNum r;
mpz_mul(r.bn, a.bn, b.bn);
return r;
}
inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) {
CBigNum r;
mpz_tdiv_q(r.bn, a.bn, b.bn);
return r;
}
inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) {
CBigNum r;
mpz_mmod(r.bn, a.bn, b.bn);
return r;
}
inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) {
CBigNum r;
mpz_mul_2exp(r.bn, a.bn, shift);
return r;
}
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) {
CBigNum r = a;
r >>= shift;
return r;
}
inline bool operator==(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) == 0); }
inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) != 0); }
inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) <= 0); }
inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) >= 0); }
inline bool operator<(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) < 0); }
inline bool operator>(const CBigNum& a, const CBigNum& b) { return (mpz_cmp(a.bn, b.bn) > 0); }
#endif*/
inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); }
typedef CBigNum Bignum;
/** constant bignum instances */
const CBigNum BN_ZERO = CBigNum(0);
const CBigNum BN_ONE = CBigNum(1);
const CBigNum BN_TWO = CBigNum(2);
const CBigNum BN_THREE = CBigNum(3);
/*#endif*/
@blockspacer
Copy link
Author

https://godbolt.org/#z:OYLghAFBqd5QCxAFwE4FN0BoCWIIDGAtgIYDW6AgqsAM4gDkAtACIDCAspQNICiA%2BgCEAqgEkAMi34AVAJoAFXgFIAzCxboARgFdgDLAQD2RAA44ANulTiSAO2DaSwdKIAmIAkoBMg74IPatMjGAPLayCbhAGIW6LYkROgo6EH8pDi2WABmsfSw6K44wahuICrZsaUAnBWW8YkgGJYktOj8La2oyAB0CFigDN4qJqhOpADUhrYE6EoADJTzi14qGQTm2q7o495eGchWWSQztL27S0vrHeNsOKjrSeORmuY4BOOiAMoIJCbbSgB2XwLEY4ABuJAOICW41h43241GhUCqmBlGerwI0IWcJudweEARSJwgQAlKiLji4QjaNpUEcZvxaDgAF7oCCk8ZGWxBSZgqyoHBbCkLQEsEWUfQ4WiiaYbLbuBhzKW0DgkDKfQx0maMACMKpCf1sjGVWHMdmApU8Pj8pKwEAKRUMJXcXlqLncurdOTqCSSTXQLTaHSsPQIJhM/UYQzW8v%2BXi8BHxljOCcplFu90sIBAmYJRJIyNonJAiMLJNoEGJZJ2QIuAPFooWCLz2ZAtPpxzazLZHNraNxGGQdNsZaL4wAVGOK5PxioJWKlirZetNgUTSq1Rqtfckgx9bhaIa4huzRarX5bfbHcVSgA2d2lXUAFnd9SS6Vs3XDkYGy7la6Kqa0pbrYmranuB7SsexpKvo5r2KUDAMHaDqFLenqPp6ACsb5%2BrmaoUOI0rIKcyAAB7IFGDAjIYABW6AEMgEC0D8fzFumxDkG0RAZDgRDaEQ/AYAAjtodwFBAABqvAAEqfKIIQAHJzt02Hkk2lCFq4/DoORjHhCQLzsqxvwpGJJAYDCcKmexAD0SZZug34RtZsK2SkdkYExFopj%2BbnjJ%2BLkmBpiwLMglnOMg/CvLYZAxTgmijIKKQsWx5mOFZVKwlkRDIK4oX/quCqniB6pgTuOpwYeMGnghlruFxFCkna0qcNx8ioPRjHIKedEgLqWC2OgADuMSWKUXhzHa5iMNh%2BiwaahiMNIGDxioB69XBLVYGQA0qN0AAcuoAl4upVLqKgAs%2BKjYXMKivrNDDPgtp7LchWD0HMWBbcqqEwIgHiGFsvDoc6uD4D6cT4UFP7ZFMyCfAQJDZi%2B8O2MgwitPI5F9SAD71R4l4%2BJ96CWExOBTPgcSuGwhgbEQxrXVgNPEcNSmCZoVgDVgJiGMyyCU7YdMM0zr58wLQts%2BgHNEFzqA8605OC1MnwRV0IuCWLpPK0LauWcg0uy/Livq8gmuMyAzNBAbRuc9zup2rQlV7nZdnjNIIQsCEpYIMgET0G7wBFAg2iaN%2Bxh2QgiRxegdmaIY/PRaQyAIOgELmHZrSWQQCCqFEImqCwAnmILJiYpC4KzJpQxbDkw3jIIIQhJ80gyLwrf8FwohKRcKyxmuOwqGwCdJ3ZBxBHZA8KnZ2i2EU/ATz0CCuSoyg1/3AFbEPI%2BJ5PJdl950pC3Ztj26gvSr%2BvyyrFv/zD6P%2B/aKXOAjIxx9TA5Eb8Psl8mKo18Yx3x3o/ZAdkD6vyPsyT%2BP5%2BBbAIPwLI5hDCQj/gA9MQDir3zYEELY5EZgmGQOgjet8sE7ATAGIM7RaCdGXucTSbtxhGVoOYPupC4zkK8MwzOQRBT2FoFnNA/BkZ0LTAw92uUiGik3mQ3YkiHLOmcnnMRYVKCMNwWw6e2DKa8MDEQYhqja7oHrtsYQSlhCfF4FIeQlBZKUA4BAAAGpyG2gsEHIyCKoNgYJDBCgAU40KSx3y0BMF2QKJgh4sHGKAnMEC35JmgbYBcCxAgZGANEvevUQBxKgULHMsD4GIOQZCfguo5hzGSTfLRIDMl2SyKkz%2BhZfgHFcII1A2gmJoLXpo4BXjQFZzMIKMBWi7IiRwF0wBCxgmhJmOMMZkSMlJxzCEu4RQcxjMqW7bhOZ9bDiPKgLxggcDAFlgYpYdkJxHJOYJJ4XUTiVlwcstAaT%2BBghwKNeEthIjIECXWKkQ4RyN2OacusDYFwNgnHZdMFyESfkJBjJhNACBYC5D8VAk4JyRTBJyesA44RbPCIYcYtBdQLO2SANWqA2CQggLsSgxLnn2E4Si3YTDbCGFTlYBlfDgC7BZQmAAnugZAbKOVp3RbwtJuxyQqDxbCN2kicyggxhAThgJfBguwmwJJCYUUkplXK8YZiLFWP4DYuxDjIoEANQFY1ljrG2PsRALFNrso7DdW7WSvBxC8EoJY/gfrLGyWkBAWi9zaUJgjYIcYXhxjPnJAmHFagi7jCTWwLxnDxjspFegCyrC0yyvrCwSF6ZplhMoJ40Ufz6VwjiDcumRBSC2FcLCdV4wlIhH4JwFgKLpC2IAOK8GkCiyxSlPghFkiimxohZK1nFIWt1daiDjA4MDHAOQuVto7V3L2ogoiiDkii5SR6ohRBRXJP1vA52VNxLwjpIrV2FA3bTYwTbXABXVQFXEDa31ciIC2hZ27u0SlxLiR9673noqIMDQDnaOC7v3XJEDcJFwLtUbetA97xghE5VS19dh31us/W6jD7h2yMvScECgSS0OgbhDh8VP6CMsXyk8nl4wqNxAWecRN4xSycdsCxsj0H%2BQQAEy1L9KGgTXqI2CtDAVkACr%2BHXRZQQcwQkFHYIhw99gotcFqYyADsN/FGM2m9cJFPKeMaprJGmcBaa8ceUzrgUXgefUx5tR7cMeffWvcYskTC2DVLnDILgeSYYplMZDsJLMFGs48kA/ImLOi8QFoLxwEChdlHeyLNGr1peC5l4anVDDAFGPo%2BTHqJHOlufsNJKKBVai5HYJhrhmkccy7QDjRK9IGQOB17YNsCBkE%2BUEQMhGa3uQiyKzqCJSwxPI5XBBbyBYpeHglpOGAEjeDvAY3ExHJugdmyqjbujtteDvJMYsfGrsQH5ji0FjZDukZzJtvRO2rvmbo6dtA72LuTBM5CZ0HIIAVqyT5v9BUuRTF5Aduj32RpFFzoQf9D3DXw9Ax47YfbZKDukKWAFqBRz8x3hm3YOO8esq8WThMaraMY/h1j8Yo7x2yQJ8KwFJPqfD04SzidVPh409jecenDPMdBnGNOtncJCfE669ztgnCpestbYLnnVOC3o7F811o7bO3dvZ8OInV3Sfq4TEBjg4pacK8zSLrXYu64kGfr1UDsuTc254yoHuUlKDiFEFINgIQOBcCUlb%2Bc1u1eK4114aLDPFwkak09yTU2yNvfO5dwwgPigg7BzmNzkHArA05NyWH1btfEsR8gZH0Godw/L3CJnylSwM7d1zyParsJN17thK3sa4/t%2Bj7H8vjfT3N/h63%2BXA%2B0yd5CKepQPeVfw499bzXyeGdM4vZYsfg4OfG7b%2Bms3MfO%2Bb%2BUAv2ndHl/C9XwnsXTPt3wZYHug90uJ%2Bm6j9PwQ9%2BEPP/n73t/tvr9nttdHdndt9X9L8hhvdfd/cd1H9ENZIhgBcD938r8Y9Rc48wUb8ZN0N4cfstt9F/tM8rAgdUAQd9Mw5LBxgocS8RU21wCp8vByDjJoQI9kCqD/9B9ZVsCMc8C/sM8s9gdSR4URVqRi8YdaDpN6C2Ddh9gWC%2B9Vc2CcAOCV80Do148cDvtWMQA08CD%2BDiDs8hDc8QAGMrAIcaCPtiBqDxD%2Bw18d8jc5dlCvAwBBhWCM1LDugBNHDnD59tU7c191C19eD08Ad9DBDQc1MQB88CgzDxCLDUdodwsbCsDcQIAJxU5pQhD3DLDXUgC6NUj0jiwUdXBuga8cjy8pChcfCdVVD3VcjsC18DhTBzR%2BsvFYt3xugOiPYpJLJ7MMY9tcCtCdCPsiDRgDCIAFs7MHNh5pBujNMMYOjugjNzD/tsUEjS81DkiZdd9RwFtfhy4BVXlj5s80jOsUVsVURaiMd1D9s5M0Qi10wm4W424ogLFFIlIA0WBKB5A25W5ZJhA2AQ0jCoiX1G0CMUVwjwd8NPNIdDCIiojUAUVSjAlwp0AmjIRsE2i/QPgqIOMlNoZEhmcyBX4TMFkxllkZk2hYsDEcsRU0t%2B1ytSB0VSwySQAysEhGSvFRAcSjCCsMtQsSs2SiAOQR0iSIwrAzky84Q6SGTLI%2BxSxpT2TLIcxNAqFYsIAmQzZQobj7dxhhEoTijtII0vAKch0%2BVxgjCTTpAhDdg%2BcEDdVzSIjbTrSExld7SjCpcyj4c0g10N0L5DTdhlIzSjDlJnSvBZ8oggyIjwzQyT9IyskT8ci18NSDZ%2B8okJwf5wt2lcsh84QMyaShYUM1BdSRiCNaxFdvSdIjBQTm0yzizcM9TqzfM7isD%2BASyayL8iyNTBQmI4EDNKDARFcWT9h%2BAvtQMKyGzf1VcokJzSz0E/MKyINxT0DcRWz6yqzf0U0WSWguy0kdhO9yFBAWTc5LJ%2BAjTKAmAAAtaVPc%2BdQ1AIqkUECEKEAKFk9pSwTk7kiI3kkLYrLqQU4U0DT4UUkzIzZMroWPV85%2BWYYeLklFHkwLQrLLTM%2B9IWACoC4kpcq9PM6bIWCCvARoKCj8uCuEn095EEt9ACujdCsUg5ecmvGcszdAyC98mCz8rJJzZjO0evWEaikC%2Bctsps9MXERhbNR4YwIoQWJlTlQkjC9FH4LraS2gLE4xLIHqJhLrEaUYCMXcyvBAHYO8OYFkywfSRIJQAyl8/Ct86CtgWCh09i7zfUjkUCsVKwBiwSzSXEV8wMcwfgUJVAToLxJgywFFBbFZIZdZfCyVHsrbHyvmTEd5WgQKvs6Cq9UCqK6KIK6Cw1Fk2gAVOWemRK4eY8hEuynMHzIzXU9cgjPC5ZPKhOcwQqtgYq4irJeE0CmvRc2iu4246FarLoBAJgIIAVSgjAfkfy9AJgOK6UPS7NSuKYJ4SyToT5GzYlQZIofOJYR4zuSgYQT2duTuNgS9KsdOKwVoXy%2Bmaa/gWalWWwHFKtQ1BLSVfhX7BIeELISsO0rwUYEaWlBYOYcYUlAACU%2BDnwWGfFJVtOw17gWFJS9G6H%2BsEEBrjXGHEA7SUlJG%2BulVj1ixU1CrWqyRInwJ/gOFGJq0%2BHxq5NHIVNBNorYHJtWWQEpr80FI5Mq0O3pqGS5PGCyEJHeq4tYXQPgvSx/PQAFPK1uVK3K1j1HnMEmBG03PwpMAQFGDOr8taAgCyBRXMBRRZsshRRyopJRVokFMTLdXXXGDuzIC1Kkx1ISyMHCEcPkEWsGw6RmDixc1t3b2NvK26B7HZDTSFwZWOBGwyHzJhyqL8KwISyyGdF0gy1%2BrqIx29oSG6C5mDkEztFsPh2TqIG6BpmFKzro3dL4WYjtq1B%2BU9NbUwMOzJlaA/UlM0LI3ttoIYKdvGu5vVEsHfS1WqNj3vMO3No1vGDADABTXMGtqrttq0ObscNklRPKl3LnjVvXGHpcOF3b0eoow1rNADsP28J7sjsOwCOrvTEaPLnRJ3kxIJOkEMBRSvu2CiC6gq2vhlua1sH4C5j1NsDGpaUXkMAgEfuMDWKIRWJRm0HQDRwCjdwznAaHmUCLISzPkSG7ISl4lIi8RvoAViQyD7B2zwawJgewRTUQcEisDeFQaKEaswbXliRIHIicvkxPpRLRJaOHnvo9lvtxKNCxMAefvGDdiWBvoSJ/oKD/oAafuAY%2B0IcgbNqyAtuzTfo/raG5BEZ0mCAwc4d4f8WkYntA1Ti6hGgZTI1M2cF0lQC6lIP4DNS9WkDkH4BeKUgBLeKscrqYUJURBSGdwWUIY8NRPPv6xUdDD/o0f8VccHowFpFLmHtHqLOkYaOVsMEMYSxMbaAFGBysfkBsbsYcaceUhcdjzdwied3BST2Yf8YxLxPfA4bvsqZ4afqMx8SFA4xSGYl4ckdAY2AgaSMOyd2CCoOlHPoFW4071/2dXcdWLrzo3NpoL0hGAtr9sMB5vOOTTUEdkLv4fdhIEaZbX2EOkXgZW0DMFcHMCGeVUkvSRaFRUsnWbd1cXIY8W01uD6LXggGWZ1NrurkTq2PsPGDBD7p6o8os1QCGcmdAzLodsvyEaQIzQWyMAwBzC2CbWAEsDEzxKFAgBvtJG6HfA5F0e4sv25okehZ50IccNLEPp4OnvLv/0KBCXNAFUICmFUeCemMMG0bAYgd3pQIjsAIaOBe6fLzafZWlHviiVJfdl1AmruhzLowuV6aJVYi1HMB0iOAsEiUhUCa6FEfUdZf8S0aBFJb8CzV8TrobFccpabupYJaYCYHGAAHVbElIe5%2B1SxH7jgbqUZjWRXjWRUtgDgmIChiXFcEsaYBadSxRmsq89KhMcwUmzGLH2m7w0duDE9I3c55mtC420n0Vlik2BWBjLWIWGC7ElJB1xg5JZJ%2BcD7ACbik8mHKAtq24dq9rpAO425DrLEIBTBhFv5CkkEUFooyk5hhEgxrtcUAoClGIikB3SlykdcUh59fAF8G7QNBpxgmBBo18vQAQUUN2vAd2t2vBDpd2vRj3D2ah12vQag18vBsJcJ13b3cIt30B72N2X2sBn2ykT30Av3P3ylv2h2P2sDJWh25htbL2f3ykwOgO6jJ2EF%2B2Skh2jSQOoOKlE0UU4Pp3EPykjS33QO0OvBM6sDMOEPB2cOSHkHyHXg0HGrMqsHsk6HcWYOMcSPikyO5gY2QAkGyGEFqPKGvFkEmU6OaGGP6Gdo19WOZ2kOKOeOKH0Hh5hPeAcwMh64igGXxPiPe2p3SPZ2OPBqtDuOUG%2BP5O2BFPlPbBVPFMmP67byhK4QY70Uxm%2BmkGbssdrsl4vFdnF5/EkHXGHOLb5Ws0blSw3POQPPh5xIMY9ntNeAIBfPY9/OnOiUXOQvR2wuWnPOMYVAvBvOXn4v0DEvAuUv533OMudMMY7xnxcvYv8vDVCv3HivQvmnPFh5SOfPBI/Oaskugvl1UvWhSuWvTPkr2uiBOvHOivguSv0vBvBP0lFO4uOvRz1E/gkxPW3OAp6vnPgvbDQX18tP4O2PdPP0EwVPzgGxmPh99usP2PjuvAmBTu0xzv1muQrudOh3bv4he6nvkixROQBHZMdTwu2BZuqDhu8vFv0Dj7SmG3m5trdrO1W2Dqjru3YF9hflDVUkmVZQW6olTB8lv59glv3ZLBkBnCFKisRtFmmEs03hthzQaBtgkH5YApses0FldQEuuvWe5GU1nwaisgAEKkuCbWsg8W4RRwJwU0Be2bhLifhUyfhHQx4QRU%2BnJPIQApGECMFjQfiVjBhUit0ldLleApMf0kNB3gU08euPz4vEre1fHmhfUrulIe3VG2u1AbeA2BuB%2BBeAABFYQX3OL32tAAC3YF8OYO6OYO8XUE6AEbCI9gEKoQ6JP7CG6F8C7KPrwZ8Z8bCGP7CO8KoKoFQO8FQQ6Z8VDivrG9At3tgD3r3n3/3wPr8TV6KHVtgc30J4P0grisP7ocvyP6P2P3PvnnPqoAEFQWYHwXPqv7q6H1%2BpeWSAjbgI5ZAK5JB4Q8YeKTQSh9HgKNgK5WWcYciBZff4FQSWNpflftfwSCALfnfgp7Yi28iVOooT4Vkf203KJO/0iRM%2Bt%2Bflpxfs2mv5ClT%2B1yZdMZ135upQBh/Y/immgHn9GgBGYARAAgEP8fm/1bnFElgEXYPssAnnMZxKbphN67GNkHcl8RBZgYz8QINxgTC3tzo2EKoHMDL5x87w2EAEMnwehVBy%2B%2B7XUIdGy7l85gz4PgSnwBDp8qgR7M6Bdimjl9sucwfdgCAUGXR2BxfQQcXzvBTQpoAIOYHHyqB3t8%2BF2cvrwPj7YRDoh0bQWX3oTLAs%2BUfC6IdC8CMDKuXoZ8LoN1B3Q7BvA8QSnwYEvgLoAIaPmXzuhHsmBQgi6FNG0FHts%2BhfC7IdHH7iCzBp0GIQoLvDj8GBog8GnwOfCnQtBF2DwSXzj5zAfBoguwc%2BAL4x9LBuwVgdoL8GXQroKfRgboK0HlIx%2BKgFQIINSFCCzBZfCIQUMT7XR7BQ7SrlnxMGlDjooglwbwOujR8zoufXPqdFYElDsuEgs6HeEOgF8k%2BcfZwbwKz4JgboxfcPDHmkT7tb2jAw6MP14HzD1BqgtgckKT588WhMQ3gZkOujZ9E%2BmglQIXwegrBWBZfOwaX22HHRzox0EvsdDuhlJkhQgspDn11B3gDKV0cflHwj6XDoR50ZIeoPz41DyhCYMvuDRuiwi%2BB7wwQTiN0EXYHoN0M6IwJj4lC2BqfbPqnxOhdDuBcwcQSUOhEzDToLQu6AoJiFVDnBowr0GwNOglDE%2B6g8QcCJL758ro2XZPqENcFCDMRKwF8KX2hHsDC%2Bpgu6OX1pHF9uBt0fdkqJcFXRVhxffPjdBlFTQyk7w0QViITBehwh90NgYfSWDEDdyvCQGnpEfRUDJ8USXYAQF6FzA3argAgAQBUCaBtBNIxgWaJIAAgSAJAaPioAICuBYhMfJgbqB9GMCsg2ELILqBIAxCLsWQBYXezmCaBNA2ETQACCyBZA5grgTQIdB/aBgY%2ByfRiKdCyBF9XArI8pDH00AJizoJATAMcAIBcJ4x6AbLiQEEFlIyxUfIQf2OOgqASAG0dMSGNLF%2BCMxWQQ6JoGz5rjNAd4csQQCL6l9nwm4koVoCZE%2BiCA6Y9AKcPEGuBy%2BgYFoQQDMH3QqgWQW6GuMzHPgRx%2B43PlkABCaAsgCY46FzGfCtjkhG0SriqRrGaBC%2BKYxMIBPhFFiuYt0dMeIM7HGJ4%2Bb4r8eeLazGJXAF2AgDCKyAEA5BBATIVUBIAriqgrgSrq4ElF5i%2BeWgrge8K2AwiZgEEu9k%2BJvEAhXAMwx8bGJMFMiVx2EFoR%2BIICaBeBl0bSHeL9GuBERfEspMcDvAkBdBhYb4adB3FMjjBnYwsNl00A%2Bj7BDAgwfYKmhZAs%2BuE3UAGJLFxjgxrwifvnxEnyTAJ5EyUa4BzG6gjJb4lQPhLmCZjNAG0OcXe2j6zCj2MI7SYGNaHNi7oqfO8Vn3QDj8Zx2ELQCsJOhfjtJ0I94eRMnEl9o%2BgYgEC%2BwdELA3ezbBHm2y7RHVt%2BwAJBkyGFTwJ%2BIKMSAYdngHLpNAtgDvugUanm9ugnwYVObwgCkDDARgDIO6I2AcR0C9U6JLYFdHkRpaY0vSO1OFTjSWMqAcaQNLJCx4a%2Bdfb3hwA7ifBKAg6cYk1MYiRIU0jU8afyi8D1SZpyALqZyH0wpAfW4wEaM6BGxwtvIyAE5jP3uKaQnRTKYaHQDQCLTKBg0mgXd1TFaD/RIUkMRsOcFyCChkY6MbGPjGJiykx0VMZ5IzFZicxW4/MXdCLEliyxFYqsTWMlYkB6xVQRsV4GbEqAgJkfDsV2KzG9jAxA4rYMONHHaCKxlXQ6FOLEm%2BSFxSQ5cauPXH7itx%2BE3cWXwPF3gjxVQE8WeIvGMFrxs4uMfePeFPiSxz4V8e%2BOLEuTvxv49gbqAAlATx%2B0I/cdmK0CQT%2BxREhMa0LglDiMxek5CemKz6kTsph0TCb%2BJwl4SCJ0ExPqROT4UTAJ1E7PvuyZEmjGJd4ZiboIzET9ZxHEriVkB4lmDHxpwwScWOEmiSZxrgAMWYPjHSTHxsk3CQpOwhKSTBKk%2BoepLaxUSvA2k06LoNFF89xBnk4ydHzMneSgxpY8QdZLvC2SSA9kqiePycmnQXJ9s9yQRK8k%2BSXJfk1wSdECntzAxQYzyboIj7PhIpz4aKS0JIBxTNxowpKQQBSmF8rx7MjKSmJ9E5TACn09JLwnaCAyFBJgsfgQFT4l8i%2BVQH8fYJHFHtoRRkSMSJOugx91BP7GOSGPj7xjsuqlIMSHOz6uBVK0Uq8erPUFbB2BRYwsdn3ZneSI%2BIYhSZ2OynlJ5JjEaBQCC3noAuBs4odnGMYKMROxuErWTuM0A5DhJpgswSmNz7RS3aogkgNMPLEx84xwkqSVNAL6nj7ByQyViXzkFcCF5q89gXMGYUxyLsxswQVuJjE5iqgKw8SUXx9GATjxv8hPuXKIm4TOxTA88UX2MmHzHxEEs6B0MPonzuUH9QGUwEvnJ8cFt894e8MfkkS5BQIt%2Bd%2BJOjg1oRXgH%2Be3Ij6Jgy5QC4vkRMAngKOJH4zxTAtXELiEFwk1oSWLEUPyEx6ADBT2NwmMEcFkrfBRtHKREL4EpCrcQmIoVULqxpggoTfMlY4LMATClhZmMuiBjtFXCiWUZPkWiD0AAi%2Bwdn2RhsCzB4i9QWLIgnSKjgKwyuQorTk7i4x10KSY0vbnqLtJC89uVJJrEcD9F2UwxeIJfCmDcpMPJ4gGnh77V22JU45OVJVLMgEES8DiPdT34H8bkjUkKrYFUIBQEsSWYoF4jnjMgypBQK5rRSvRghc4o5RqedLmkui3R/05aegR%2BV6VDpX4KKOCoYaGpGpXgX2sKhhXgrXGq0z3utM2nbTYu8Kg6UWRuWcIzprQZADCs5A1Yzp0K5HFdMMA3SFG901AI9OdDPTXpiaP5V%2BA6nIA5p30oFeRCWlDTDU4KhZP8opUIBYVAUeFYiuJXI4UVK02Hu2zWldxMVO0nFUXEhUnTCVSKylZMHRTkqNVIqqlTSo5R3SHp0Ocxj1GZWEdWVAKvSPNPaCuMBVkK7oMKtFVupxVRK5FbnFRWyr3e6KhVZ8C2lKq7luKqJPit2DqrJVeqrVTcCuW50nV%2BqrrLSuNVPSzVAqN6YC1hD/L2VgKoRJoDtXpsHVsayaQirdVSqPVMq7ZbXx9UbS/VWK3aevXnTBrMgBK6NRKpJWRqdV4avsNdPjWGq6VDK01UxHNW/9oem1L1QVL2XFTO2pU8qc5mMD8BnAw0UYkLEXgtNzliwFdg5w344Ai4HPLgluuHitDykFxLdTaB8AyM6iaK%2BvlWv9WxcF%2Bl/IoMgJwBcVeEZzHmqGujUX9m0y/e9Ycpv7eBsIUOVVl3TNKPrXG/dXEBuoRB7qWAO66NHurYAHqhesG4mIIDPUY4RpeAqJKSiNb1SP1rgL9avx/VClH1MrRuF6orWXrFVN6gAUgMI0QByIT6tAC%2BqNI4bEBQA2jfRo7qxAW0RvCacmlvaJV7Sz/G%2BpSjSS4tQNJ9ethcinD0olYPUAslTyZ6nUOskIHXgo2eTABnA6KfYJV32aGAxq/bEaDCCnB3S04o4bSAUCzhhw0A7rAoN0EnBQoFgdzd4DQU%2BTIAdNIqQholRGY95uM0mb6ADV3ZugAa%2B7FFKe0C13sUUt7B8BbV1DiBxA/%2BVwZyFtZrsmAEAWLfFptzQiuKaWuLf/iz5JaAtMW3LTbg2hcVSUtrHLRlvbzZcytxW9vOX2vRs0nNwDVze5smDliiVXmpdl6KLJto12cwciInxRQDazBw28iMdDG2noxtAIU9GenGAjaoOk22bWNvw6oZmylAM%2Bs0WsrsNZIwNGptwwJLiBga1JCKG4l%2Ba%2BIW0bANOMNgbR%2BV2QR2z4D1zXa7bHtSDC1RcrdQuaRpU6wSLqAW5EA1m6BL7dGuiSEavA/2i1TLzhAXruAUAH7QDqDWg6ypv2pNPWvka/bEdSDR2J6vLVrS4dhG0lCPUOkE7UdKadHQjqJ1FksdEmavmRrx3jECdO8JHdTsR3k6sNPOanTjoOr074d7Oq9LztJ1Fk2dcDJ7TTsNQw78dyOhHXOWDUk7Wd/2vnSmk51lrud6KyXVjs/7M6Ud8ujXZgNF2m1DsEuhnVLvZ1o6BdiOhXZjpR1c65Vau43Rrsp2y6TdguqJMLsd366Vdtur3urox0ws5dKqoXZbozTK7aduOu3bzpF3m6A9ruoPX5hD3i66d4exnTLq10A6XdsIWPfAyiTx6AoRuiPXrqj0rMY9uutXNnut2jk89yeovansI467fd1et7WLtz2J7vd9ujHe7vh217o9Geh3TEzL1EBCONu71a3vz085O96e4XcHsEiD7Pdw%2B2HW3ul1%2BZx9dexfVekb1D7yN8%2B0fVnpr0T7M9Su6fU3td4t6t9Veg/E7sb0r72d5%2BnrjPqh2whK9JuxHcvu72T6G9h%2BjfTzsZ0d6wde%2B3vQfoH1H7DdJ%2Bn3YvsVwv7q9b%2BxXOvtn2b7QDfO3fVfpF0wHQ9qukfVXp30QG0db%2BnfSgYT1h70DT%2Bgvb/qQN668D701RM1u2b%2BY54HFYoJWBc2zcPsWOjDtYW01VcQGl2RveOygHXayAt2yyOyBYO36h1DxUdbssR77LO2JZeg7VPA3A4/a%2BzJQimkQ3wgmdCzJZhy2uzuwNDrzLQ4uwqQ94DUB5PwMRoB5r4N1ihkVHRAWSqGbDGaXQ4s3erCptDxKd/oszuwdaXDBh3/MYeQ10Qxek9dZrJFoMCF/Kehzpl1q3U94zi%2BhzvNEZYDmt4cIR2wHQedCVhPNi7BI7u0yPxHfDJG3ECkbSPhHcjRyX/LEciOLs6I%2BR5cskdCOhESjcRsozEfXalHqjRhgo1KXqOk1GjlRvIz5qNZtHyjvzJo%2B0cSOdHYQRRsIxkaaMJGDyIxvo4IDGM5HRjNRnUoUe6MkEZjixuY7ayGMtH9j4x2o3RimMNHtj4DKI7/nXYLGLjVR4Y0wEONJGTjmx%2BgxEduP9GvRPgG4wu07zLHvjlxgY18ceMTGaDqR6Y28Z%2BPNHPj0aQ4xUfeNQnrjwJ446BlOM9HzjkJ3Y/8buMHHZjVxwY6sY6PImNjYJs4xCYBNRI9jBJntFiY%2BOImqTTxlNlXTrZPYUIZoOaK9GqjLRYYEYH6BuFQhIAjAIMMGAiTwAa1Yg74AiNxGIhBAyIlEdGIjGRioxXwMdDGFjFFq4xqo/UQaITCajYBZNuWamM2gtjGhdUrMULMbAdjfQJYRQIWMaZAC6prTN1O2HLEtM6w5NqsM2Had1T6mbq%2BsLoM6ZNhfsbYGsemFrHtNuhgzhsc0%2BfAGjTRPoLsRgLRAYhMQxMLTNIOVGRKUBdTaQPiAJCEiiRxIGAVwNJDkgKRlIqkdSOmG0i6R9IBAQyMZFTOpBPwUDMmIGDOohgugwUD9CsGEmEauzbqbkyFHTD1wdIMyMgE4HZDSBla42VdUMH3Sh4zUGYbgDWsECZIbgQeeQMpF4BKRpAj2/RuNn8x%2B8xAXqcY5pHVhRQMyWCOBBJGSwpRKwS8dMxkElyyRRAPuVtuMAAAk6qVc0nH4A9w2A4gYQCwAECP4ECDYVNKfUijCoEocUBKElB6KpQHzn4Z86%2BcoCtsHlLCCdsC0IREoAowAJeBNlxBTmtsrgegCAGIszmAoX5oED%2BdSB%2B5BAdiF8x3GuIoYVgoCJkAKjGz6IiMKwdNZkkQS5BOLjRbsyoD4u/n9zhYES2JdSBtYDgi8fiJ832y8WbMwiBJuyiksqWMAzgCaTxdEsqXOg9mV4CyDmpJJdL0l6KDnVbKEIhYiVBYJmfPPQWqyZgSwFZZur3m0zyFzJqhfQtup9OvmFgNaF8A%2BApo67O1ijFlpMA7Wekazeu2UxaY3glxViyoCYDvU7ANptkEXG0gRN5cvlkINNEgsM9ooTl2IIgkDBG5ELHl8qJLmECCA/ciuAgORHIgakdIU0UkKyaejzQhob0SU0RBIiymqIv0VkxAAFPAx0AoMJ0CKchjin8IlCdszQlDDBR5TSMFGEkDRgqnMY2MDU6aH6hugdTyGt0waYdBGnQzlsDaCzGbQBnuYdg3CI6dtMnXjQZ1261MEusKxrrB13056fusgBXwPpvWGbBesgA3rkZu0z9f%2BvRmXTr129k7ATMuF2Eg8XYLNeDDzXOzyiA4YYhkQcIvEBAXBJTDOQY34bw8YzoVUAT43t4WNnG88xJtw2ybRVfYLFmJsYIFgjCOmCYAFSChgAfsC2tahjRNCmAZo/6p8CBysQlCSkcgAkA5Rssmb7sFm2zeOSc3CAnIMIVUD5sFDnwHsNOECirzkCqCJ1ZBCZlstqJ3YLAQmolHCAfK54WwdFNJQ4CiBpAuvLIMgBGiCHxgmIOIK0D1SYABsTCQMcYFCS2ABUUqKW9zViDrn5AsgZ1pGr9gRAQAbsEaHHe6BEEeQLsBOzQDsiu2eQnkNBkwHTutBugStEwIsQYSS9Sb8YLhEMgQD8BIuyAKLamDRs9JZECYAgNheCAKJG0UwWu/XcxsJhwgFgXRNMDXT8Ja7JaEhNUi8Q43DAZwbpNImpvYInqwASe5Mg21%2BMttO8V5Yco%2BUIhBAttz4AYmOVtAq7hybe/Rz3uV39gjLRIifI%2By8I5DcITNdauvuECzzy9i%2Bi8p5Dr2dmCKLe7ud3tUID7w8L%2BzvZE4n2q7593kI8p6hrY2Aa995S2mKroIVipaj7QPTkavNc4vtd/n2Hd26HAsEmLAvo0SbjAq78bYHKGqZahhdyTymrFT00pTBT57/brNEl/uE8WV6BRIEQHDAMtAs/KO8OCp8MtHsHt1UQ0/ZYbYJoHw0D%2ByKgAc/2zqf9/fkfe6T/ZgHhPf%2B/I6U7aEwjCuIuBADEcb2EUwth2zffTVMPnmcj7%2B35hID5FOsY3C2pBtsNHqmddrf3NIEBpHrkNgRp4EklpMqHY8CIeWgg0ywO3%2BGc4e5W6n0c49iUAT2gre2Cec9HOtj7x7uocdOOXHu6tx/mymYoPlDXx%2BWl8ev32tkn5CXbP9jCfRMVD7j3EIFiyPzGcn0aDngMYBA37nUedzxwibnJXoIA2Xa42E6AMY5B6WT6NH48VyOOWAzj8p3CEqfxHqneJhpymiacTPWnG9SJ%2BJqex2FAUJxaUI/dUSbaX7EXN%2BzA9c2NxVHSwJRyY6kcKPLsJzx5mc7UcyG1s8DLPdo72fiODn3Tng4dkueH2zHV6Cx%2Bs75Ubcuu8TosqoeUM85hnzj1xyepQ1r55ncxhJ4al8cLISn7sbLrHhKfENIn5CbCDE4K4AuEUILqJMC6ScjOUnSGyF6hvhx9PrjI2ZLXAxUOFOr7GL93flc2KwgYXVL643U69EzOiyczlp7C/bwdPY0trbpwycpe2s/HO%2B5l181Zd8uqX0zxpyQGadZG8TzvK9K88h7V1VnxuX55s6WDbPWGUDp57o8kdHOFgHzlR184%2BzmvTHgDm52Ecl5qBtH%2BwbLvs28nva11GPdg/s2RjmMQWQL2JzY7xd2PEnGaMFyS/hBpPducIKu21tHApofX/LI1k64q4cHSQbr2cDC9/wkbM3AxqnYU/m3kRyxRbotyRoTd%2Bvs9tLvzCi41crPvmazgorq7KYr3X7by555vdNeUBrX1zq18Y6ueqPXs9rrRy5o%2BeKPDHjDmR8o5tdGYSACyHV%2BgV%2BfBu6uuL6w4u/GD2HQXyTi4tUbJfpPQMMbjg81l9eLuLDy7tQ3C7PdfH13Qzzd6k53dRu6M%2B7/ZnG6LJlv5jbLo1mMfmPJu3NqbxV/M8/dThw4Ob2ziy48dVOP3Kritx9gG3Fvi3IJ190rsrdXpq34bTV4nhbM/M53s/U%2Bs/YNc6OJHhzy12a97efPbXPbid6c/7fqOGjUKR18O5I%2Bju3nuILt6o/6ZghBVFxWXoFG4jU8jArNvVEShGjbBkYo4MJ4XfeckeLXtrnrrO4bdcFGEpACgLx8zwCoBPd04Ty1lpCaBrNnSAKAu/PfcUuP0lMSByneTzEAoCII5ZQwWRIMX%2BpEZ1QPQRSFAwQH9azymmc92fKwYTFB859c%2BkREdUrjHPg8MZEPs2RpY2ytgLKaAhmPU1Ncg4tq%2Bft%2B/nozFZ5/4bMvbRTKJtKC5ChhyoJzebeJ4xxu4sPFnvRxi4AN%2BeustrRL/x3QLOe386L9dNpmjTqIMXzsZTb63BBsoW0LnFGIcsK9wgRomWSgmlCa%2BVuCX5LjJ%2BTvG9sfJvDOFzkwHc/ggQT8zpFzE/qeNPr9GaUb4E4%2BylbjD6iYVNTyS/taMvnjUuAN4vxoe6M9Xtpymhg3peSnKpYbJd7BaRObW/zWt/Kndgud2UhjbkBFFDpnfPwlt079JWc8fwvwGH%2Bt51kbdL2RHq9o1wR%2B7fNgEULHr52VV9uCGb6oDkVOj7I%2BjvJGSD%2BQ3E6Dcpow3HL%2BxynuBc2s5vuIQesB6Z1Ae%2BX%2BR0D27g3YkaGfLP3N/zqVcfGxnsIN3DBps7Q/jciGig3q9w%2BiOkfBzlH528Tiy18f9HXgHmhx%2BPu8fYhcLEx/s6nv8X%2BT4l5T5DfO8okNRHALT93f0%2BUHwHgXx4x%2BZHAGqWVEX7IwtrzPOXpTnl5oCQ/BPcHdRN3Pb7rroEuffDqJO7vGL5uYPsH8sc/B99FfH%2B/vx326jdyYYE/a66Hvq%2Bl%2BtvjXhHsjwsEyrjv97k765zmCiiZU%2Bw5hYn3CDz9DhbD8NWPHn4ZDhPdQtfnF6T5FR6/CXobm96S6CsoaLf3zEw0WQb8ZvufIHuokP4ddRIa5zg5Ibwub93lrvtvwFEODh/p/Efmf5Hx27MVK%2BRO/aWadas1%2BVoPXE7NFE8FoAshF2AjzkFOCvy1Os3Lfi2vh4Oft%2BqfPOS/xC57/uOQkJdHmiYDP/zGlC1/idJ/qcghNL2kUAI/7FUE4KSA4OF/u4Y/%2Bt1NcZKEyWmsai%2BonloRz2oaGf5G0f/kayX%2Bs4JDrYewjuUxr%2B79rL4du1Btv5qOd9vQwuakAaf4sgY7mw5EqoaI2r%2Bal/gbpcetAKKQu242M6IUkBtriBDeIdoSA0IFJKkS/%2BDAe44SByGkTzEo3AQNoWeVvmf7B%2BiOs4RzAzhPS7/YwQMghCepBNIGd4nLunrOE5EM4RSBOATaBFkIThoTpeacMfxz2DDgfafa1hHQEmAadE%2BYpo0gegRCBI3jmDjSxtsHDMQE4BIGcg7uhuxmB5/pC6x4EgR97oEEAWihTgJgKboP%2BMvpAHQBNGBjwpB8QU8A0wCyIkHzGFPlODPgseN4HbAmASyAzergegDp0mgZdh5BGaEaC14K7LiBBBSQb4F6Q/gUUDiBZ/rT6c%2BSgeUEp6lQenR0%2B8OC0Flkszo87r%2BnyqSBtB5EB0GBB0QUwBcscaAyYVOHPJEHImLFkyYS%2BTbjs6Gukwe25EelABQGSeU7iJzUBuPkYxsYUqMU5oAY7ucG8I34F2S4sK/lL4kB%2BzgcE5%2BYOGRj2BlATmDCaW9Af5SIR/on6P8EALv4cq%2B/kI5bOrwS26kBHwSdrfBFGPn6n2lHhj7kWhgCJr2Ac9GNStAvAM2i9EZfrEQV%2BsIMVT0BsAWyAeGODvgHzGnLgG4TBcIWT7%2BuRvsGxwBLAcYbHqH/oERMaEgf/74BQAbewgBZpOAGZBlkFAEwB/PmgKAoJ8mUHYB/QV8Z4B1/lCGS%2BCPrCHvBn9h26P%2BCIL8EgASXl55E%2BwIYdiJcCIBLALIFPsgFcEJodT4XEEsOb73ub1C74tOEsL4Z9%2BdGEaFo%2BbnkWQbQFxLqEi6qhrqG2hTQdrhB%2BneE6GAml2Ft5j69/KB6x%2BPzJ04JBXOF8Y%2BhRrML6gemwS3iP8cYU8AJht/hsEL%2BaYW7ji%2BVaNDyMIvAORDlwbwEUCjYEUBjD2YbltzQ1Y1rtCKO8yocQGNh5lEA69uFwZfYXYORKv5thjvMqSdhLmuA63mqoc85wO5zr2GvB/YfA4XOJwU2H0ctzrTSYC9IWqE/IEoH2Hzh7YcoCKOW4QOHUePRnd6OumoRjBThCPjOHnOyIbI4LhInEuET%2B37i654%2BNWhuHThe4bOFXhk7jeF2uDRveH0eFHo8xfhVrmeGthb4ZeEXh34T0a0eLABcHgRQES%2BEI%2BWoaBFqOAhhgA4%2Bf4QX4mOgET2GSMaGH2EK%2BH4ZhHbhOYCr6OA5gGr5euPyDhFogq/nn7gRxfpVLJUhIVr64RrwVv5IROYOCFzSgIfBHEBbEf%2BFeIX4X8EYhAIVREthK9scH8Rw8IJEUoe/jQHOB8QcBHiRF2gREARRETJEQhckRfboBFGDtiKRF9CeF4%2B7ETqGUMTES1zraJYWWHxUbfuFjxWJll1j%2Bc1rlFoGIm4ZJFsATkR2H/hXYdpE8oukTxEr2jkfnzH2Q4dYQjhzyrs6TBE4TuFJsfkRfQBRu2GBEnB7kRBEkEmjseEy%2BaPDFH9YcUe%2BHZRt4Ro6quWjgZF6RWUYlGBRCUa5FJRA7j%2BGFRzrjlxPhBAWJGxRpUfFFRRKkV4iVRB4SQS/h1hLlGtROaplHbAvUeR4YRjzB1FLhUETBHNROUcVHbAiERVFlRyEVj6oR/9OhEoho0QtG6RokTsFZR%2BEb1HERqvv/Tq%2B3ESxEI%2BtEVNEicJfoxHHR1EaxHeRu5HtEgAnEfv5bR8PrxF3RTKA9H/BPKKZHNejUf1gSRI0e1ELROyLJEXBqQQNHnaTTA9HnBw4e9G8oPYRDEGRbUcPAdRuoT9EQxfEYDEoxwMeiGYhwANiGnUY1viF2A6MWzQWR5YUmDWRNsDWF2R9YeijWuufGgTXwLkVjFsAjMUFGeRsMYiE%2BRCMSdEgRrkezHlRrMYLHJRYUcgSFR6UaeEQxDMV6A5RJwSLFVRh4QVFpR%2BwVLF8xK9pjFrRXiArGPRoMddF/Rg2HDHIxbMbLEicX0aJr6x20YbHcx90fLGmxajubFYhJ1ONR4hhQCTGWxqiIwhTm2XvxDlwqJHECnaBZIUBMqQzIEA3SYTl1ih0BwIWCnewAOQK8oQdvg66AelC1j7AVgIkBux/WBwDyAogB4xvwrQBjAmW4nj0Spwa0U5H/YJcRXZV2UWiDHmwWPimZV2j4VmgCGTECFQK%2BCQVkBKQVQZXD8gbcfTAdxIQPpo6BY7pZ5v8bIDZ4txLdPc4xoRQbEG1RT7nazOgLaErqTx4fuRDlIuMiW6B%2BKDmBD0OeuioDDBsILYCLxqAMvHKxUSIdCzgHTtca7xbIAyb6eVOifHuUR9OBYfMLoZOAFENnk/EkaD8eLFFkl8VOBxcY8dsC2sB8Z96KBLvp3HdxgsPyDuOQQVAnAAPcaKxZoT8e74EuNQfIyrx0HuvFMCFfCEF9682j45W%2BWQIPGHAw8WvjwJpCfSA6BX8UvFoJ82hglQAt8ffDIe8aGMEzO0YYZ4M4cXKglGYEfhgnMJIui0IPY6aBwnSuXCWLg8JdCXwmFuRbgInAJQiXfqGoxXnJ6EBqiI3F1RiKCHBlx%2BfBxHCok8eMT4RCCUgncRxIQc6CJszmjE4oXxgCB/c4wIdCx4GiU%2B5YJTIfC47xCifvGHxzcfXHhO4IeICJMlXLgzt4ACRbSiWtrMwnLO4wG/F2hlcTokXOz7mmSfxbTvYlXxgiaAkMmwsD4mCqX4H4kBJz4A561sGvO7BTm2wANrlI94lByg6vrHEAcoN0opT9eRSeraBAKKObSVh2XijAkWQzESp6Y4IEKDbA0lE2iCwNCDO7ReMaPnzdenyE3Ztm/SRrazMUwAHGveg9JkmmA7rGvHlJeCe/HLJMyFPEp6DicibMJMgTW4BQHZsxBxcWCf9gAAfmUksyxbunr5W6BCclAJe8TzhRarjFsmrJA5EroeJ7eFnyx47yUxBjBPLsYkwJ8YEU6XYZyVknYJG8bB5JoUQAW7rJqHDdj3JyiY/z/Jv0UWGM2htjcAqe7NvLbc2StirZlIzOELaZY7aGLbQY6jEHYy2uKSKgK2PNkyKEpsaCUma2fUqOBbA/IHranU5yNLY4pctrSn4pPQoSlVA6ttsA5xUkI4g62HKSMQG2zNrykc2/KYrZQyIqeMAsApWOgDUorECqm620qdykqpJtjoAtIhDs2hco1trbZ2QjiDHz22jts7Y522AMSie20lH2JY%2B/toHZYpUMKHbh2pbJHb%2BwJgDHZ2QcdiNAJ2RoM7AQQKdsABp2tPBnYCIWdral52K8OJ7cpmCF3blyfZqjbpgLGvVJOUZiY1ILIn%2BFdSjQDnv3QZp0ahcH1ScEdmkJJjcO8TDQP1N54W0I9Hml8eDLPirhwjUjH420a%2BI2nNAqAIghrQu0gybBeqesQ6kEb6mfxEAZVCWnA6Y6ZtGlgjaSp6caQGiw7z%2BzJumnRqH2CxpLhQ7tYRlpjHmYmD0Dae8RNpu0iFSp0gjvEwGMQ6WF6jpYAorEpRRZLOmHp86YBqBsS6agEW0vzkqELALGhcmZpY7l2mBgPaVkB9pbaXD5uwmaaSEIB2Xgox8wXQEZApgsIGqar0EUWigaBNWM4RxBlkM4TiexaWOksQpARBmcgS%2BNJg5pKaHmk1psKvaFxcM3tND2pw4LNxxcxhm/FEq7BgxkXE6hDhlgCaUM6AioCAfXhtoJGUWRkZBaeyE7x1GS4gc49GbdQXETGcKgsZUmVwTsZ76rmAlplnoRn4sxGZWlCZtaUeqiZ1PuJl0ZtDqxlcEMmZJQ/uRmWoTV0HGbLAoCtDlmhqZ5ePxmaZ1acJk6Z8jGJm0Zz8IZnyZ0aCZlyZfhpZlKZmaSDwg8vGVcQaZuac5naZXBMxkpu5mdgRWZN/BhnoooWTbSjSEWfmlRZ0aESqeZ9gHFmKZY6ROm4Zj/oqxdAdmaBiOZ6WeRnGG2WZJn%2BZT2AllCkSMSlmpZAmVEhaZFGTVleZdWUsANZq4c84hZ9mZPRpZpGZFkdZEmV1lsZAWQVnKZRWTL7BZtmQgEVZI2RlljZw4H5mTZ9WYFklp1ceMnNZRGdGitZVaStnVZHOPsBRaeWfWy9ZXMepgQOtNElnvh0qhWmVZLmegTFqIqtKqMMxYROBTgu/gurokXWDO5N2SmMEBskStG8DhWXSQZAYAZYM2hAMimvTHCoQnlxg9SEySkwbsgbquDMgsCUsBTg4yM5AMJeurLgfK8OUzopMOOeMAAAAn5SvUKTMqmHMJJAnAW2kwKODSU8OeJ5TgFObLg45DmhmAg6LGs5jICU6WAIfYKTGO4jSy/tvEQAB6cJAEYMufYDsgQ4KekooKTKekSYgYTFgJMhjPDrDpzGu%2BrOYUSZYAxwIqA%2Bly5OkLTnPp76K%2BmyYX3ov7G4EuWonnI32eMC/Z%2BhDdKA5zdpLS/AmWIqb5erQHWbQ5M6suhkATACd7w55OVTmWQr1CNjMpJ3nUD4WelFTys558OzmU5XOQsDD2vOWOlRq02c5j4agudYROJIqFbTa%2BsIOLnCoRCVLlgAeac5jHUPQPipkAJ7MNpq5gPJrmXp5jCQ4JgOGvrmtmRuTdjV5pZBblxehSSCE/M9udsFqI32XPT2E5PINj0OT5j6GJ5GthbZWAJzPdF9mRmkZqp5j/PUkZWOIBnktgSmUl7AJ6MWYlu4R2al6VgIGZ9npg1BixqdZuWY/4DZJeZRnS5RKvwB0qxZvipnpeDq3na5V6Z3kg6mrIkiEsQDI/m2ZJuW/kf5C6S%2BkNRGKZpBgFTKCxpRQOWcAAn5BoVq6jgeaReYf5/aXD5IxSBadkqopiegV1uxuFgXQWOBVfkO5qPiKgEFpmWgWgsCBekhOZc6hQVLxuBdvH1pVee8TSg%2BaYgkgp/ae45u4VGUZh9ZHyrNykgMnEZz8QtXk8wxctDGJxDwcKVIVUcMhSZzKOajqQCKFpYN5kBQHzGvjCFz7u05MFkhQZykM0hTRyZc8haJxBJyhWYWUcvHGoWNUGhdgwZ0N2Klpo8uhXAWqIt%2BUpkxZZmRRHEoUmWYlJZTwL8qd4uhrQCLZXxrtgL4sQSKGoACQbkF5qXxrPFwqRiV3H8FVcI4mBF6QXZywgg9FEVM6whO5qkggXh2lYEjCG/zTAMydsC8Q88HmZuGa4VUFcoIngoxcwecREwBxHypcy3W/ILrwu2tmZczWesWPCBdY6/hdyysmzDWRFACvLSpkw5gEwB1woWNxo/AIqGxDBp9oY1jaA3Hkp6Vhj/lzAOcjPNAm7kRQJMWgYjCEJ5VhB5msAYAveazknF/RWnGaa0SEMxrsLfMrx30pmpMl3FAcV7ZxcBDn0VdMBkS0X0xbxQw5OWbtuiRr4laalpFFyYQybIaeRVgTApVcAsjJ%2Bn3gbm64doZWlRFJGqiX9FUvCjAB%2By6fkWLIstFkDiAvAfYAXkVgNSqeiHGO0gp%2BJPoG5t%2Bq7iC6K4eyd362g9dDqShFFvDy5GFRmPnzWJl2BH4kaz7n/EXxvQRbSUl1JcAC0lXUCkDuOdoZb5c2AXjb64gAPhkDgMIJoPQW8/2AtqalcIEEHIaCyBrSZFSCUoUFuZgkikrBtaA76UZBJRAzPcDeICkEu42oWHiJcpeWA0ldJTdJElDviRpphzQf/CQuCyJ4BHJbqE1nfJUSBEgVaJgCkXRo8aFEHhFggIYY9aUSE8njxySflprx5YqmV5wBgZB7yM3ydPFZa%2BZdLyGoiZUWWCAR%2BJmWllzydPGHQopQW4Fl6BDWWLs84Lm5ZlESZWUrS7xKYA4A5coJg1lRtNcZjlo0p%2BlHBykXfmEFZmer52Zz%2BaEWdlERayHRF0aLEWj%2BuIEllJFHgUmVxo0tEYlUlvpQqX%2BlDJRiX3%2Bm6uyVM6XJRG5kuvJWvj8l5pUKV%2BYIpf2X7JDXv/EylGtCeWFAfpUqWrqYWesbUgKDgKVo65RdxTalZ8MyVBhYFWvFmCxpbCCml4ZXC7rMPpf%2BVnlgFQsjx%2BwZQv6hlZpfG7gJ0ZZLE8ZsZU8DXGoaAeUplHZWmUZlL5WWVGYeZdgntl1ZWmVu%2BszhYmquANHmwsVVZQFCrldZSWXZlLCUZgtlH5WxW1l3ZQ2UiVrZeKXV8g5WYAjlVFX0AUVtrJOVUF4%2Bb4XTZ2WWdn5837lFpLlIRQkVhFtZboYbl4wFuWOJCRXuVFkNZfMZpFYqseXylipfSXolTJdZXIZooU8BuBlaWIWwOCkTtjIlh2LuWn%2B9wLkG%2BV8xuZWuMJQS760A4Ve7qDBGQLox2hz5SmgTgEADay/%2B9wKK4oOGFWkiuVypf4Tq5oGPqUalrpSSEIwOpbBVi4ZVdgmIVFVZOBhlPfse6ge%2BVQBVuVgZSSXFVNuQRWoVL7sRUhVpFVmjkV8ZS77UVrjIJX0VnFYxV%2BYzFYaWyJhZYuwcVgpbNVXoFZXxVLVnePWUMVTZWJVyVi1bRVSVwlVxXTxNGZtUKVaQEpWNSKleOXqVucLcrTlO2Zdh0Fz1QwUrs66AzqIwGDkmhXorye/G4gg6ckwWgqTO3kjpjdnYAKMHxX0zPVIVIRqDF8uVbY/Ao4IZW6hQ%2Beh4kVqsWRXPJbWe8TwqQ5centowgHFp1pIlUzoplWBAWGouWhJQ53ZCRQ0zI4ESQOUf0dygTUhqF2Lw6d4GZaTXgq6Dr2C/VywWvic1ggEUFhhKhoNr8V0ZXpVcGrVYaFdcSMe34oo67mKxoOftByAc%2BzIW4YUhPNNEVgpa7jN5pF95T35K1PQVgTChXlYkUJod4FJleOsTGmVjGkocbjBV/dNpU3p7YLqpeRZGLTVjhHypFFSMiDiQUp4N2aOHhR%2BGWigM1CAODq81atdYnJlrjDGU41vzKrU/VseIwhb2/aOYgcACvNF79YZ2MugOcKcFEllhPUF1hq2OdTdKLMjSaVJRJxMaJ70OsljO4qcRKCprSUQGQjABQ4KkfjplJ1WtUzxB1axUd1ucF3UrVvZb3UbVC1QPVuondYuw7VM1XtV%2BY4lRdX8qQ9V2U9189VejnVE9ZLWHY6iE7YRIDdQw7V1NML0QtmOIcowqeqDggCp0VQTgxcUvNfnR31Q9dfXp0uDKkWoqilcOU3VO2NPVc1wxp3V81/tI9Vw%2BoUZA73ZfmHQWtq5foHVGpWNSNWJ1eafjVmAhNeYgk1RCY2U5lpeoLWU1j/CA101FtaEzU1Xtbdk%2B1AVdcx%2BYMKkzWXViDTgCE139XRUoBU9Wg7EE6tLzW%2BVAFKw031bhUaw0VKKWfWX1z9bfVnETDc2jPB6BNAy/K1%2BZpCu1ssLXFdS12eRg8xl2A/ZmJeafAjKVO2PioPBCCLwiiN1BfL70w2eW7XUBP5uYCe1VwfYBX2twc/nqI8gTpaHYtAVkE8hxDGgCPBOjTFXDepQdKAhIXYF0GSB0LsoHrB6RQY3OlOFcSU1VlGUEE4B1es4RMApgY%2BUollpSCnuVupcibSBgTU77xeZQSoHd6agRoF4MWgfTCJMVgFk3FlRhqoEMAJgShD%2BNcob4CWBxQR402OogT42RNfjVgRpNPfrIG2B3KLuR9M8Og8qBxzmiFFh1lkE8C2BhQAEEz1gUT2X9g82lgDfQ8zXM2LNCzcs1LNqzf5orNGzWs1bNKzbM2bNezds2rNszYNBug5QK%2BC4QD4DuzHsNQPs3rNczeRAkAdzZoB3NyKANouYA2tgAweBzfs27NXzb82bNuzfc2PNzzXc1vN%2BkHc2a0NzWs2NahqA/EEu9TcIHSg5EOM2dBLTe2lBGWBL/F66jlVgSWeuQWM3HI61J3j%2BVUwS00yBcRTqT6eFgdnqDVapRaWPFLpRi1JJQLtcYleaarbks5HlZI2GIjmkbEsajsagWWeggEGDEFoLIdSEoeaQCQSpiZRRCx432rYBCt2JVToKt4TXK0YCriZcpZ5yCAQCCAlaay2HYZirwjM1b%2Bd9JIJNmdq1fg%2BKvH6uMI0q4B/Mw0iDp3FaDRACNppgGa06tSuaNJzAqueVXYNPzLsAEc8LSN4utJgG60Wtjao1Jetbab6EpVJVfuncF15mCAQAtrR613FHrVq3utLafK1BgHrdK30aNvoOl/5YNbrnTZ/LXKRHZ9XoPlW5dROm2VptrSRpIx4FR4wxq42blkMmvCAP6fGZoisA58yQsnxGQg4gLwf4ngOS0ZNtLXmm8FJrQIVtpn/mgAdtnCIt41sWxHw0PBbDQxoXwD9a4y3MaAKBnfZm%2BXMnDQNMTdQdYGzthC8AilhznU5y6LUVF1fMAe1Ahs4JznbERmjzkjSLGnzA/UQuacj/YXTFA2itlAOK3vEkrWEUyt9rVnlj5zvpXl5pszLXket%2BKs5D4qubWi16Mv%2BYRo6516TI0gA77X3nvEszNAWW5sBYdiFM5eVy2O5kvHvmF4rgM/AjNcSBXA3UpYGJidYs4DmoUdgUJvkR54tJ74CUbHZe2BQFHR6LPtPWXzlKZJcBWSlpa6Yo6sGiRDumXYo3PqF/tAHV2jSAUrUxC8ahqGXnopmTdLn0UJcDB2ZtJ6fiq50CHSp1IdQXih1S6aHQAXTZInTXjYd45CXB4dcXm%2BngdqftCi7t5HTXhUd6KPu0BxtYXkjHtXmme0sdplvSgXtkeVe03t8yX0Tkd7Ha9TLoHnYNICdX6UJ3TZ77aJ2ftgkB9h2p6XboSBQIrSuxitwQBK1KdwHap0atYArb4V5USUzr5WJVYwi8op7UwAYaFtPV28AYQfPilha%2BCNIZA7HimgFEi3mvDddhMV2wMmI0hLBO8USNsBTgGtTqRxteafRTQdiufirddObfzC8AHrYZ2NqiHfm1md5Uv/mnSSmal014JufN1lheHczlZo9LRF13t6NUyb6FOLSg5adwMDWYhti3eG2Nq8HY2obdRtMZ3bdF6YW0WMxbW7WHdMGMd1PduHZW0EdTncR16NUmuTnUo5gHWZbaM%2BZ8hn1YPox095fxTZ2505OXjl2aShLSDpsBRBOB6%2BpKFj3h5PHcugDJlAuHlJ%2BGtoN3jU3OYJ1Z5LGvT3q02XR9iydv7fl3/thXYB3FdubbK0Ot0PRAmQdg5U92s9CucKiwdn3Tm0/d56QQ7/dHeft3TZEvRP58Yc3eL3f0hMTd3stFXSR1M2bnSF3O5cQK7kA5MOfpjLoLEKRJdMoIASQKagkCvxdYaNdF08dSDI71e2JOVTzO9RvTF3LoSlKpSMlsDP5wzu/vdsC2957Vvk/M0lOH2JdmeeV0EFf2QcCzYiQBcFNZDvZQx9xstKH1i5QvRp2W%2BovawWJ9bQOH01munY2pu9GffMzW9iOsn5cUKDeIAoo9fY33E14gCZ0WYO3YJAWdyvW7Xzqrucn3oAavSADkFRfb5SCgiQDWY69RHRp390sPeR3w9iPf9le2ZWGVYtM0OG3ZspvSc7COc/aO3ykqcjI7bJc58KcDcdYXbx2KUjEFMAtoGPVF0%2B9tPdsA79KzhnmvtSmcADxiqqOz2E%2BXPWp089hgEV3KdIHWp259TrdLmv9xZq923K%2BnZt1y9P%2BX92ode3UgXxig/VgXxik/Y/zOdM/Yb1TgHABYCWAqAEwCL82/KOC29fXopjNcIqPNSfx1/UCGhd4tLnCMQZAPQAA4HrOBxJ5ENqd7YD5gLgP4DRkE%2BZnKDDu0jBdxmhInw4IBFEzIwYcV1jZsZYP1hU8R%2BK11mCKeY%2B1R9TJfaEx96eTzkXIr9Cz20A/fRcEIgdA8NjXYX/Xvw/9f/SV0%2BOCKNX7LZvBSX3Wq%2BKgYMMD33RRDN9qDZLlWDPODV0t5sA%2BZ3wDSmdKD996vTwW0Ao/QpY69%2BYWgPC9RYRnnHO%2BEdoMhAw0O9UopPzOO3BD8yRwV6NWg0plLhI9IkNvpKQ/wA9S6Q%2BPnSdhjRh2bpVLWJ3Tpu6dA2zd7xIaR6d0SKrnuOBbXANFt6HQgLlDtTVEgm52kA51VtGBR/Gw%2B%2BvXH1ftL1VkNhG/XdBEf9FziPEPd8bVp6E1LaU0Py9Wua0MA97Q%2BOmdRxQJMO2dWnn0MEdAw3q1Fp4nWMPTZd4VulSdJw9Ehi5pg3z3/9pXRB1adz8IsPhtsvRRBt9Gud4O7dbQ5Z1u15w/elHZ9nRD2btj/EcOXZVwxun5RUpcS00gSzs/m1DMUGE4vDeqEs7NDHfUJC%2BDBWZumR4KaCbkNUGLsCOO1EvKonFDEI%2BMMNGR4dBFIxrzmYmMISkLUkm5/lG15VBRwM7hdY81JVwh5bSXIxyDJTtl7L96JEjUtYrA8zxVYoFdEjiQUTPNRhwc8MODjAVQPDRq2NWAqNfsEtCqQvAQzFsANB7I6OA4h8mnIwwQfquIBldh/DO73eseGaM4j/jk15OtwbU06ZtAtZBXvxh2V6UxhMPhs5Rl1gQiNMjTXsiMROTXh8MdYXw532YjN6diP3OuI0dk%2BjgToSNiNoIySPeFq6VUOnDfwxo6QuWadA2MIb8DkDH8m6Y8Pxt9Q290ooeaYQytkCQy1BojwYxiM/D3fWUNpjLVT0Npy%2BwyCOYeCYy52aQJQ5CMNGNrBmOgsWYxgA5jIRIeFQCDrcAPzDYcFWDS9xY%2B8SljaQxWMrDbeesO/DdY92O2sEBWHDNjk0gsgXwjUkSODDHo3o26p1KXylc2iqQyn82xKcEDC2ZKeOYUpktlinHj8qaeP0pytmaJq2zKSvyspkqWTA6pVKXKl4piqSdBCpyqWKkSp7KT%2BP62R4/%2BMKpPNiFbMpqqc4AapelBoBSpkE0HbG2kqAanm2xqUjXbANttIDmplqc7AO2TttDm2pHtte1OpKyS6kWNQdu6mB4YdhHY1YUdr6mx28donYhpu4GGkRpMwFGngIRQNnaRpudvnYJpBvUmnw23dtLUd209qPaN2Hua3bQYX4KjbRDBvVOAhAyrFyDmg81l1jLF88HWHfZPObqnexkcU0T%2BxhcUe3BxyaoQ79c/ow7aRx4WAeZU8cca6mMIScRzZsormunGOgF9NnG5xGAPnEBxRcUsDPVH2M9W1xBiYXneJKya3HklHcYk1VwmfQPFDxiTCPEIoXFdnouJ08b8lzxWXJonHx0iVTrnJYpTgmbxk9Zk1cVN%2BgfGbJvCefEpJgCWElwNd8T/FMt2et/E1uWJf8AlVsLSglLxzU4x2pRF8akkKJ6STS3ijoaM6VwJJgCE1K6qCUy6MJaKWsm4JqHPgloVEHVNNUJBmpNMkJyU4YwzTdCXNP5N4KWTVGYD0CImfJnCcIOgYUiafG%2BhsifIlNlc4FVOfJYiZdPCD102fEb1sieWL3TGDch5KJb6WCPQ8kU2FO6xdcdFPMQr9BNNydH1WlPkVX1XqFGstiUE5clJvPPE8ZLiXC2cFx05g1PTJVQtMpouSSNCBJSwSEnXx4ScAmRJ0SSVXPVw2UWQPxzZUNP0OI0/skYzo0t0CEzxM6NPfeyqdckVJc7Cd5bAolMj2tur3l7GhwtAC0lyMbSQDnmAnSbRk9JbyNvADJ8VsMmvFYyZdilktxdMle23neZ4Qd%2BMwtUIpUHF4n4ztUyjNYEByek3W5xycjanJBs5dhXJJUzCnlVDybbPYziuK8l/JWCdy7Z63yWwTZThqPjM%2BzspfFOElOAv9gQp4M4tOlTovNaW8zFfHaV7jaKXgXS15pOXY30wgNLUXBsSTTM7YJAGO40zmgLE4b8vGiwCqGvGtSjdAYbmxmQu9Gmvh2sQyOgA%2Bo2XOMQCNXDV8bkQE4K%2BBMIfPoIATShJkkOAoRc1y05zqc5nMYwN9NQAhw52S5q5zF2PnPP5o8xjCo1xcwiClz5c30hVzXfiYY%2BAdc1gTM%2Bi7P3MNlc9IWDNz4Ooq6rt8xp3M8Nb6cPN6NVdozFpzIcBnP7AjMdnPl2a0Y/N5zBc6/Neg0SKvMIo68xcQVzirtXMKZtc%2B44NzRQE3O8ALc62mcNr9dGjXzKKH%2B4tOR8y2NDzcPkvPIAj8%2BPPIAk8%2BXZvzs87/NX48kmO7YLj83fP/OpBGvNFwG8w/BbzxLjXM9%2Be83UQHzneEfMLIJ864Bnz9owgux1R/F3MYLxuFQuJjNcH%2BOs2NKc%2BMEpF44LZXjpKaLa3jEtlBOSLJ43SkyLqtsqmfj2tuBOcp/lCouy2T4%2BosFCd4MBPMpoE9%2BN6LMqUbb6pZti2jL5uEyui22VqaRN08Qk3amtAlEz7bUTAdrRNupIdgxOep/aN6nR2bE4GkcTyds6DhptqdGkCTsaSJO9U4k2Tbd2gsA1S/Y/dphWnAaaeIhJLpdpJQCoBdagjZL6NjPY7wKMHHHl2z9J3YE2TVLgivAw81Taj2RVHPZ42pS14gCg7KAvbVLNNsDxOFZyDJO9Iw8BxMsI8cJTBdLAy7IhDLwaSMs6A5YlYDjLVSIMss2btiMvpwBdnnBT2lBgM0taZirXy2InwAGjiA8gIDSUA/AJnWAy/bXXAc2OAHRBkA5gIzCZ4IkP5TDgYICNDkQAqCyANs7fLwBRA/aIDSiAAAFLcA4gBwAdo8gL7zyQ0gMIBSQdrI4iyAF5AULdt%2BfCqKbKzWvI32BW0lEACAey/JCLskHs/k4rBy77jHLpy%2BctGsrKN0AfssqEwD8AdkNCAqAUQBTlOU9pFUWUAWK%2B7z7L/AMBZRAO1OIDSAe/CcvyQhyyStnLwgBwDzGFK1SuCANK/nAU5ZpKyvsrhK/wAB8XaEHgbSO5gKucrxKycuir4q%2BSsJg3QDKssr7sJivYrgqwcv7oPqEpD2IgCACxbLNsUyiC2ek%2B/x4xZjQo3XBSjWgAtJlg1BRjuBrWgBz0kTHn06%2BjnCfLLI7/IvB4kZ7q4nRrwbC40x17/jyXmG93RbSmrHK7iud4VlL/jdAI5vNLKuZTVg5wxOYF8j3Y6zLwiBrzuHnaBAFds95kAeaxKGejAw%2BWvne0/X/z4RGcEKDokwgLJDiAnHPYG8I3aw32XB7qxY03BqALwDmMKKEjFaFFM90yNJV2vQNGoPa1rWKWY0wOs9rADUElXoM6%2B/xeJvCBOvoozjagBMauwLKAdrLaIOvkst7Ff34ImAKRYu2ahad5/qpDaMABs/lIsT2k66%2BICbrXFDutNTyJn75hNg1f01ENIdTghwxRmKJCdQKfo0lz0YkBJAf2Npp6xz2hVNGiDrgUIEAioAPlVbzJLZiJDQbVa6xAf0wdEaQsTfqagP4bGAIRs1rJG7sAsTgcFChVtjSQ4MgFGMAIFwgkM1qA1kXVeE1uhbfnQsv%2BiuMIScgUG1Rsx1GCSPQx0Ftomunq78YUVoAg6zmsZAYA7mjQb%2Ba4kYal9YUzm9dnLaSUQdleVJvNoopR9jHUlG85DibfCS1Dvx%2B6%2BYyAyZ6314XrPaxhx8GxKHQMEkDoI6p2a9G36kJoVgW6PG4uFZ6Nvpl5Xo3DhwzeigmAldqkv8A%2BLRM3bVUzZmXxNdRBuyN5l7KlspbaW5lsZb2Wylq5b6W3ltpba%2BDlv5bJW1lsFbxW2VulbKW0VvlbtW1Vt1blW41vFba%2BP5prsQWuUBxoKKPezRaO7PYkooF7BVuDbeWzVtjaDzQW5PNBbsigFuHtO81jamtE1sNbQ243kjbC2/Vtrbq26tsrbA2mNsDaE2wNpTbrzWNp2pnzRttLbm21gRnbl24tvXba2yttXb62/dunbm7Bds3bT2w9uvb1Wy9vvb3229vnbyWx9sA7P20tt3bgO79uPbzW19tg7oO%2BDvDbkOzDtA70O89v/bCOyjtQ7MHGtpEC4W%2BMB%2BBBLcxCkh1qM/lu4kWz3Y%2BUsW4S2CAxLcVSkgw7aP790r9KIC0Ac0uis6RY62O6JcYa0DDhYxNA0bK880m3O6NyvPQkPBD9cwumGlEXaGD0OOwEGpERQGmjzaNvoBtBlja6QWjgfOxZt%2BYm9XrVq7P1Zi4xoLs3o24NJDZ8pGYbdK0BM78kd5XBB1je7AfFXTZR2mADDt7WhONNcQ2h1%2BzpFFJ1Gy4aixVYmEyVeJPu141iBqLTb7tNl4MiYW1XIAshS7KLaHunqP5eBWzOFtaSBtdoHklCBgZAPW0mVflQKVsEN88RxR77Qbju%2BNbjvHsW6SeynviJae%2BQASl7pVyAkavNZEBEbta%2BZmjtKu57vANLu2BtgNV6KbvoA5u1pEOr8MZ6uoAY7m7i97WahfDaNIfEAb90ZiniGCm6AMq2BJs8zZWmVeqBGsiodQH6vbLDjSM1BBe9pVyAyXy9yt/LgK8CugrIQOCuQr0K7Cvwrly8YjXLty/cvsoJgE8tBA2gK8vvLLIIisPQyK8nx%2BAjG1YEgb5jafLbtr2S41dFqAKJhQAdQPMa16yLlf6C1w0mQ5dAjvV4jHsllXfSctsXHis4CPeBvwTM0mO21h7cZQfui1ggH8zktc6N92qV9lUaxb7gbaUEPBFm9E5sJxB1S2r0RcN4RxjPzIa3DDc%2BxkuL7QYMvshREG6zuE7j/PPujWS%2B/kmp9NlaYWT7TwWu0/r05Ybtu744eHV%2BY5vNIfCH%2BSbvuJFTwIlNPAWQPZuvABUM/lorbBk54X9jEhwZwZswPFtblB0smvI7aO24fw7b2yDuo7Hhz4d1bXh5lvqC62yXxdbQWgJJdb3cxFrjA%2BfF1u9bJgl1sXsBlCijR8JW/4dnbszbCBrsMaCihzg2R93NRH2R9FrjAvW31uwgF7KqMx8oWkFqXQoWq%2BBbs97NCKhavW7wKhaF7FNCRabW0ForAkWt3O3s3h21vRaIWjGhnsWBPYIoorQmMdrs2XGMcdbD0GMf3sxfGMe9bpfGMcXs5fCijg06x0Fo3Q6x93M586x9FqZC6x8Md1Ezgl1v%2BaufH0eXHaO6keI7Vx74fnFuIPcfuHtx39sY4Tx%2B8cvHEO64cfHdx7cc3HvxwCevH8OD8fPH9WyL736LWnQHIJ/8OAegbYsVXbRcDTCjCx4GcN0CQHomLwh1AoaD06DeDTeIH0J51bG2ALCyPAijW7mvYeLslO2iikgppSO0prdGojphB0SFtgZ7yJqieN7NG8Nh0aiJZC4wnem9YFqHeweFuQbkQ4R1S96J%2ByARGP67OBVT7sHnvvO7aw5sn8KBwRomc0WhgeBbOByMx4HVIyZXc2dBFL0cnxG1ycE7CmedwLG/O3fUowedCI0z7TgYkR0BIkLkGMHFtOesYJQQQSdeJg9B6fu63BywCmBANXCBunPGyCZV7rJ6h69VrFj358nre7CDBnsTEqeHTLvtcZdMf6sjTd6GAuHO1B1xk6cZo2LZk1TTph0KBX%2BhZ9/SJnRZCPTnro5FP0d7g%2B1qkL7Mh26stL4h2YmCn3e57tT5CyNodbAjZ1o1KHwi6rvgqU%2BdKcZnsKcOsYBJYOOdb0YMYFUc1ucFPnB%2BQjQgDDnMddOVp1uhzXWCmOlCHD2p/uXUWokzoEMzhWvUiZZLAHUnud4x5bIIcyH553SDsgLmrecYAeMR9gZA3yGO6MIsoJWHDLstFvYhAd0judkHwdqXBcopZGw6HnkwOEDfIueopCTgB4iigTgbDtLSH7pGYpArZv54gjEbrQMTOoqqF2/lIITgJfmVcxY6hdRA4gNtIHLggJeg6a26EpCt9FxHSPJco0LFA3ST5uXRQXA5qiS5pqF%2BRnoXwQ2w66N0F52gcn4xEReBQqJBwH4oRtjYfXtLS67yoXmlNAsiX3cztivn4QIuefI3yCoex4rzBdqkg6F0gjVrSlxJfczbAFtgyDkFw7STExkCAUNS2gHMtQYnF4QgHIrvMIBRACqhwCAeTlytKoXF5mw6%2BUIfHBeFOmgE5euMj5%2BgCXnbF%2BEDjETl/12gwkIGNvBXaALFdx5qcMZfpewPIGAZ2u53edUE8VxKP2XNl2JfQYwLAFBgXwLMIjNAGdlADbMUAYld4DACA3UhUMVwAgpXCAGleMIj9J7ZlXKanJedoQGZgDtAnA0Zd7jkV62vQ8Ahw2dBgLcyvsW1CQQ9Urr%2BzAwetnO%2Bxbvoo%2B%2B1Nd1qnCPftZAj%2B3csPLr%2B88sf7byx8tIryQpsovYI66AddU/TRfASnUACgJcY3DXYnqQs4C2WytKp2gfDwGB/eyXlWp0FZblBB8mzsHXQz5UbXi7JQe3k1B2vumV8xgwdeBeJ8wc67aZ%2BJXA3KaH6fcHg88bh8HBu0bFSHPZxtdNnLO8Puj7kh9ecE3ch7NcKHrjdPt6o8az9WqHne/Cf01Wh9JfKt016tcJBRh6Wfnr2%2B0tgtaCIKSeMydURSeOH%2BKy4dvHnx5LcAn/x6Cey38OzLcgnF2JFq9bR7JFoXs4x3OCA7CtwVvpHhWlkewgHW51uwg97JgewgxRxgfyjoWq1trsXoKFodbaMHUeha0WidChaGB%2BdCRa/mmdCRanRx1tZ8kWq%2BwvHut5kdugthIbd5HJt4Ufm32R2UfW3lR3bc1HoWvUfO3TR27etHntx0cPHcIF0czx/t4CcgnwO3DtS3ct38eF3ed0Xf3b2t2XdV3ld8XdV3hW6Xe13jdxXcN3%2Bd5Lfgn62lqUc3VXR4GENwdfCdecMXAsYon1p3deYncQNifuNwgT6cEJhJzN3En7ntJePhItxTtJZNJ//B0ndRIPQYaKaEydhn9e9adGnze3XMbBvJ8BvO7cJ6A3M3V6M512EaJykBWA0B6ifibU4C9fuwb1y1KKnZh8qda9qB7IX3sGp0BsvMuBwDf8lybIrmH3JG6acWZ1JqiertFRjafFmdp/Y1d3uZ3ZUunERk0xJn092U5ybKDtg8VngwGoABnqpUGflnUSIFsgV6aiyd4VkZ62in3yu3GdkPCxpg9ZnyZ7aypn0TpfEZnGCWNWoPnJU63c3DmyWcmHZZ1/do3YAFWcQnNZ/wdGx3Z0IetA7NwPsgHljSPsWHjN5ff4N5DfOdHeKaHI9s34On2duNA566faPPQOrsQVY59KGTn0oTOeihVtUOfl5v9QcamPWlzI983r9L3vQbDgwwaiHg%2Byo%2BzDGbOu2mAVnFZsMXUScE9dJSIcedCehFuPhx%2BgD24mBPI58b4A0jCYHs%2BNhrU48abz04rjpPMwPWuCAiN/zUc%2BRhqE/uw9IwtRpyu5NE%2BBsvrYCgUPIvUU8f8ha6gBYnhj9PtlP7aD1gumach8ooNnyjZr%2BUTCJwNFNsT3RiK73VSPmAoIW%2BPkePztNjyKPYDmIfD73q8gBNxE4OXQBPleZ4/eQfBg8i3BQhfE9K7hqKSETgNMBEgpo9fbHgdLuFjGvqIaANoH/nnA7dJEqUSeYzso9oVWduoIPLi1Hr2gXztT73fNw7nPVt9553Y4QFf5WsPLmjOkgwVVx70j/WKnAqavCI8%2By4ZvROA/PGMBOBqeJ1KODm0KLwY1dqtgM4Qio/k9xnU8emlYCzwOEwZqNJVxUEA4D4wD8D9FqvC5tIvKvBrZE5LaKSzZeulLwOcvINad4tYxPblOLwE4HZrxDllc%2BBcj97ZJdPAzRAXXCz9Dovn33XDDdKkAQzB0VPoqlBgB6zYpz8znP7p4a/cPSZyPQ3PNQTCUzeKhY4WWF5XGs91R9HPUWv1YKZa9661r3JzOFor9YVaFhaW2sGNve9jwiHSj5dcqPqz21obPEL/CNzDOz4xB7P80oGMTP4Tac/GvRZFc/oE5r%2Be73PXQPTCy0iOM88KMrz%2Ba/m0Xz4djzZTKL88IMDzzm8AvSh8C/NokYADTIpigeC%2BUREb%2BE4lFqbnC9yvCLzMnIvVb889ov1PBi%2B2ZmL8gDYvAxbi/2hBL7LREvJL3nHkvM7pS%2BoA1L5ba0vYo/S%2BpLstMy/9JRKCxvsvZ3vYQfKPLxpQhw/L9sC05VPMK8UR4r2%2BnGvrD2c/1vAXhJtgAGb1meuvKT%2B69E2Vhe5qOvt9Ra8Wzmup%2B99Ldrz%2B8icPr9OVzP41KqkUE9574/KPY63pjJUk4Js9RvXBTG/eP8b4c92%2BCT40903/NTN6kLKj9k3RNSoHk2sPmT4IAj1aNxU0BnYT7YGFg78KQAUlbHDLM6BtT775HPkz/q1aEJts9T4EzTJRDxv2NNFbdA/EDoAmQWhFq0rW%2BSFpMnKAl26hV%2BLa8J%2BUQXvpl7BrBRTzSbPyH0WxRIan3uMHAlEHnQeGxm/9gj0Bnz0CAavr%2BNdGxUQM6ApwbdE4BaUIqszvsYGQOvtsg%2BzIjiuAqcO5%2BUknyILPrhy14Pt51EF%2Bp8LXWGwY2rT%2BrRvtPAs7VF%2BCBeJ05dM6GQCofvxHV8pvRInDfPBMoCmtFZGqp8dC5xfRZCl8jmAls8tXUHKK2Q80Ggc4RG0VjciYM%2BRX2joc7Ja0BXa4e98ibpfNZDkG5fKnx/mBEMXzTBQFKaCV/KbZX6kAeGNX/oCxfqjw18oOQ3wVPNfRa1xwSwNvgt83TI31%2BAJrnX%2B7CUATYzWnMXEycpuBTR7ebSfxmlL8DsjY1F7Y1P3GkKCpwa%2BPqWRfGu14m0tjLLLRGs63y2jqVtwSLpefqV4Gd0YUL2wT702qBjeNV7OzF/P%2Bmtcd/PMahJC5mG4iRjjA/GaFN8gmndx9/qtqYa/FBlF06F//4aP7mG0P6XuiANB%2BX2M%2BgYKPzzgpfWnjo1OXKKF98Tl9XzqRGAH3xweM/P34eu5O2bk1811rgP18MPuveXRd8Vn0QJGxOAJVxXjIfLkUk3vB4xrf%2BRpM%2BtmkXhe2P2rIB8rybYG/MEXQNW7cesK/PGP%2BrK/05YEVA4Ev3odd3Vu0g4xgv4tZhdwnwGwD8AMkAgRTPxuO0DBAZv2UGJkKwHd36vUof2%2BmNEgS4NDrZSF78T8%2BIQLxiLlACb/u/Qb0s9%2BPLZwaHW/KmHb8O/Tv2%2Blu/viIEntP3fKH8%2B/Ta/781vbjUH%2BgvC4N7/h/4%2BQiCm/hN4o3cosv4ChV/2f/J%2Bq/rnVODCANFBkhM5/nIMleNiruTllI7XbwLo52XtJT08zgLyCWQSXslCajjH56z7vebxSVtJZmk0XPOnIyd7PF8y%2BTk2ADPFpoYwoJV1htFhqiXgkQQr6gCT/lkEMxVkhA7TFU8cwEwBVA2IJQBkdj/3CCF8r/2//v/b/xkcD/h0Bz7p5pRwmAtCU6D3QFYSp8axTaCDPQ7qZAgl8ZPakoC2haFVrSpucnLyjD/4oA9/5f/U9rnQdHIpEe6TPwFtBLvTaaM9Hlp83FzSBFYQDyARQCyQIQAhAMxANlfDgV8egFQcXLTJaOLSbIJ3KuicwAkkepDTAI9r%2BcXvYxAfSCuAeQDkCEVAZ5ZrQZAQ74ePO5ApAVUAqzJShzBQgAn%2Bea6BFHbDd/YZKrPQpyqApSiLwHqSzmD6o80PNQkfdQJVNLAjIaTQEkAbQF0lVDZ6FR0p2hPjYRuNQDAuTARmAiwFdQVDY7zI5CvfMaZmAkXQQAMgEUAqgE0AoJxlIEmpIVXXoUPfhhTgfAE0JDPLl4bwFq9fv5E/NfDeAkg6ooa4y5NQh46kZwHIAHQGy1YfK%2B/Y3AzPSP6QfVoD8AgoBCAs%2BwufXcjf1FGDqAqqRMfCWYIA/ZiYoaDCyjVsiRvPdIpufZjJArH6OeH9z7MXWbhOV0bUgBFBZAnIHxfDjb4RZwGtuUJrHPJyoGNAYFMgQ5QzArj70%2BBFBJfcYEFFBFA5BFNBP3FOqB%2BNYHCAqr4MlL0oi9dYE84bYGsPDOCLsLy49laj6xNFCDvxKYFLAnTYpNcNi8nMA78nWlpnAxXA0wGNozdFBxXAkMLbtW4EEPIwGeA%2BVAJBa4DMgewCUEf6gxA7XDIaLy5E/DqaUZQEGCAG4E9aHfTOEXUBkfPWpogjEGa6ZwhVAYh4lVBL7CBb4F8/DBIM7eQH4g4EGJGcEGlVaN5SAmhBqgGsLDJGkHInIEEHIFoxmAxEiyA8wHZAywGBjcoicfLKgRAvkBkJAhzwg/FjvA667Y/Yn4RsN%2BKJvei5TgXiA0IXcizMHqAfKZFoiAnnK1sFEHKg%2BTxTgPxikDewI1YZBD8wbYAxNDQLSgyjIUgi4F4gzkHogukHlNboBxNcW5L4WUE/le0HcbVh7Ugova0g7kH0g4qqUPEzTkgor4/A30F61f0HS7QMG%2BGBkG0tEeglYe5CsgoZJyAgMFOgjEF8gtkFKUbMFpggUE6A4UHa4Q0EteSIE7TezSNVREEfAysG8nQ4GLMKwHygnqoGg0UEqgwKBeNDUHF1ANgtoHUEVg62ZrTCMGUgpM4RGa4EugnJoMAdAB5NGZwNOIe5cg/FYEPXgCmBP4H%2BEL0FzfF3wDgh0FSMTMGjgkj5%2BAd0HiJKsFyguohvxRr6Hrc4FRgzcGsIWcEggkPzMAEkGhghYHTAl4HhNK4grgiM6PfK3zrg88H/YGMGdBOMGlPQH5hgkbw%2Bg5eJ%2Bg2gAcgy8HOgoMFWbEh5TeB0BlhSLpTxC2h%2BAuSABA0PBBAuYAhAxqoDDcIEXICUHUJKUF6gwzwDAhZDEQqcBEpfEwQQgkG2sdIHo/KM5%2BAJEGhgkMqpsJUEtgo0Ftg9UFMoTUFdg/pgBBXsEvxG3Ing%2BhK/AgwqsQ0sGMlTui7kRBKn/Ccx8QjXhTgeuB9eceKkQwiEafC2gPgw5TuOYiE73AYHXPeCF3tEiF6Qv4rqVOsHvUeYyjAywFLceSEZARSF1FfkF8Q2lpPAsqTuOboEUmMwGWQxXilZPpjzJKV4yvYOwCAyajCA74z2Q2tCGQhFApAuoHElJ1paQjwZYfep4JPcUEH/Ul7oAAKYIoTzTEoJj64DZTSjgfv4NdCKENUYKGqQuCG3tP4op6XgSxQgLbxQ3CGJQzor33VKFaGF2xQWIUbE4Lzp5oBhw5Q2LiD/PKHXYFSZy1Vvz2AsuaCbK7oBxUXY%2BAR9S4POAF2Q0QrIQygFNwQIESsDCGt9dhKK4boGK4VLTTQ1CFRIeaGYQtnyiQ8UFRAgiFJAuyHxAoYFbBCDrdAq9DrQ2aFoQnJ7ceHMGWjVaGXQ6gGh4cqGjgHCFlgyUGGMHqG0tcWytAlD4YtH6EYwNoHhONyFSPbfK6bLSrKRVVIjQaYBBgPtZE3Wv5qPMjDWaHkAF1PnZwPblAIPACgrtfhYsobzS6nCPYE7IEBu4G%2Bj%2BJXQIK2CkBmsWs7q/alBmACKBGWCT51nZRo1DFBzC7CJ64sXXrY3G67EfKJAZzGih87NupEFYx6cwyP7rnVoB4A0cBkbMJbdANkD8/RODFEKsh2QA2BvASwBfwEwD3cWgAPGBzZMAcIArifTg8oFKxzwbMhmufCIM7bohmHXahRAQ6DV/D1YIwsxIzXBkIioXhBUlXEouNVq4FJYYFYbIaB0hTUI3lBwxoAZ2EybXvx2hRtpUnSyAuIYEFQmH8rXJTXQGlPWo57cWpliQbI0YAaFcEC4ruwQsRwSOCQW0P1A2UUQCaQx0qD0QgBrxXgDnVavQDaNgA0ZcXjbqTjxceJMSZwouZYEY8EoOSPYZnciBWIDBIclQJ7OwjlwmfI6ar3Cj4chDioLVSgClwiCrkQEeEK7XaGvTWXjCAPwBOSOdh9MWeE%2BAMBQFlRuEFwlBxFw7BJRAUeHi1EuH2ZZOE1ENOEA0OuFwSNfBNwi2ibwhaqWwu5LkQbeH7wouDzgVOG1wmPhlIU%2BFrw3XAlgk9x9Q6owOArdxM6ONysPTuFOwuIBbuSNzSYESivFCeDceKNi7kV%2BH1w%2BsIjPXaYMrdZiFw5DT4uI9bOws6bTgqADJBJPYDwvEwLVCuErTIFyelIsHjPUSE9VWM669QoHN/cRbctB8bQTaRa82WRYkpEWzkpZRYSLQxYATF8aEpd8Ya2bRZPmOmDQ5XRa/jLFIYTZ5BYTexY4TL2z4TFxY2pdxYUTG77eLP2y%2BLBOL%2BLSgiBLJiZyUH1IMbANJBpN2yRLVOwxLfibIAQSa8TYSYrwcYCiTCfK5LThAvAQwCaAOJLSTEpayTLwAk7PuxbnQezKTQyYTLTGzrYfKBjLDZaNLJZZz2BZYGxN4JtudUKHBE%2Bz2I4eanBNRwxI5BCaAN1be1dQ6%2B1TQ6tRR7LQNR5LR1JG7V6XQwN1HE6wgNhwcOJNrxXbhzC1DMq%2BfDwyFI6cqr%2BI3bwhTZaaxWJGkeejhPRRQrGDT7Qn%2BfQKFPVkKFI6kLJhO/xLuRzgK1X2Gv%2BPpHxXdkIl7KOjchcwKwaPkJqoAUJeAUAJBaBurkhdAA1IyZGIBSnwDzN9LShQP70BKKoTIiKCIHSHr1sepFpIjfyHBAGIf0JJGtIs4KgxfQ4JBM/yMBVEjMBRq7pHApGTI9q46GbgLNATCqrULsDsbWEAB7Jpr5PYPbVNQ5Id3OV5cBV%2BAFuU4HKBLJ7lNIwEYJbQJFNPQKIoyj7OhMcGVNcIJztIA5ijLpr2BGGqE8e068gFwKRVDwLKBeG7CBGYLyA1Fr0JCvZJ0AJodNDsrdBfroZBWa5PAJIKhwy2prI%2BIpcosn4eBLDRfGMBbe7RL5RNHfRJVABF61OoI84BoJeJUYK4jEADR7eYLso3KpxVfoIpPaVEMgpVHBzc2rhbaYIqowvbS7Fpq2herT2lVlxrBVlFvgvsG0I16LNuS5FkBa5HKRRJEOI%2B5FUBR5FwfEN4J/UFj3BFxqAvJv790C5FCnNcLZ%2BBELq/N1FxIovy4xESKdI/IGjgdpGi/cRDlsSyIVhKmLVhQWC0xByJUIFpFSRbcLhIqNECRNSJRolJGu7UNEaHMhpRRGaJTndjBFo/NH7hJNEexVfzNIu5ENo%2BjiltZtGvBG5F5otgDSRGGIc3GtE9ottF9otSIDo4N7NnaKJkxd2ClhCmKL/amJZousI5os6i9opKKFo3NEjo1GIbohxFlorvZX3XyLqxC%2Bito91HYxFqJ6JDSKkxG6II%2BY9FxIjqKdol6Kr%2BYdEnotyI4xcdHkowKqHo/6Kuo7dG3o19FeoidFE3A3S9UbFKqLIxYCpc8YFCUSwfjJHA6LbVJoTMRG2LQ1IOLGRFmpC1KkoYibWpMiYKI%2B1JeLJyx2AVRG6peiaX7IJYhLVib%2BpdibBpQxHRLdxaxLUxHxLeNKJLEuxbXEZ4iIdIzOIzRA2/ORiOOJSAouGSacY3UjcYl1zcYjVbT2ZfJyMfgCCYnLjCY/lbT2Y%2BoR/G%2BC6TbYASYnuBCYnuA7meFKgiNhCKY/Jw8YnLg%2BoSgDvEAzFSADaQGYgGgcY41JyMDtA22JSBcARxBaY4xChYPXDWY2zFsIOTHdLbBCI4WHIjQLJYGIMWY%2BxLrBhxFtB9MSEBn0FXhEoCgDJQzfjoAVRHQIshiesalhU8WgB71XVI9vDrzjAKSB3AYcAowfxLDYUHgGqEVC0QRWYzJdpJm9BwCR5Xf7bAeah2sZTaJMCWa6pA1LerW5DusWniIkA878sfd7yUTL5cYDLFdAUiI5YsgDOEFtAowaDC8gYaDXfKKAaUIZAHAFnL3jVyYa2UJDOAd1J6QAhDWRMsDQ5RyB1mIgDUxE4AmaKwD7nYq5DMbLzRWX4r5eHQIJpb364/RZaTLXpY0cBezpeXgFYqBSAXkYJHXY3KjRpJtBhIpjGv2EiDFEIJH3YmrBvY7kDyYoYBuYzSD9YsoETmVkETmAw7g4wQGQ4uwDQ4nMDYUOwCzIS54t9CUAbYGopFIJwAo0XqQUAOHHOAKHGaaczgLwfC68oR7CogRhApoVuBSAZSBsAAQA9wW2ysAqcAaAEmj1FQbBCWRy4yQv2jLUcupdYUQHbLcQGOYqwzG9RGCc4ogBO0ZwDH5P1YxfBbHdgd/il/VYByMRTHFmSTG6MT4CyAVuC8ADgB/mJSBRAP860AT4CcWWUAx0WPDghI3FcWE3H/0HbCG443EWcQwCTVCcyLAjBpRIW3Eyge3HdAfn6S48K4K4%2BTAXY82gq4iAA2IQdBPY3gB/cd2Aq45ahE2M4BuoOXHO45BLB4juCiAZ7GK4t%2BLCDTXg0IUhi68AkibmBSASpFuACVJ3E844hicWIHHqke36LmEPHJ4sPGp48v4u/IgZF433EZDfCIcANrECob3Hg4hWAgAfrEXBGq6tYVwAlUEXFLXRP79wfjGSYt9I9YrLHmAHvE0EEdiDcGq7%2BILKz80OIDEIzGZ3EC7F10evGBQLVp1rLKxa0FfEBeWvFPoWZ4t4tvEd4vHHcwEADCAWwA743vEXaKcB748L48BbX4HYJP7WYcfFb4yfGkRa/G342fEPMLxAL4l5hL4/fEIBJlyp4y7EDDASA34vHHOoNOQlULfaH4v3Fh/Y/GR/WHHe4onGX4tAnw4%2BICaaMtpYEwnEI4zTTKtLxCt4g7Hn44bCYUMELCoC3GNEb3HS42qT90TFKypUDHcIjRZEpORb8wBRbsIylIMIlgkwTNglYuaDFa2QRGKISxaiIxhDiIwUCSIo1Kg%2BU1J22DDGuLB9bmIjxYOpDWxUTFREuTCRABLYjFaIpl4%2BpP1J6IiJahpKJY8TN2yZ2OJbuLONIF2RjFtLRuyVXXOzFLdzE7wbGw6RTZaO5bFJDlXAZdYbd7HeGOI/AE7xU8O4p6aKoEJgWkAmYAy5agATSxoJgJHeH3Lk8dXjkdZ2xoAGLF9MFHLdXOzS2fLzr3NUyYooIbxcYGInMQUkDVPfK46vbryb5TlCvQvtJFE8t44kaSjFWTKG8QJ8ZVSJWZrFL2wFEsYqb5OeAOIzoAQgay6lkVODUCETyZfJtqUvYogb5cjrQbN5CRE/LxXFQLHGYOIBGjMMGE9FKBBYhVjBACJCfxUZL5zeECmTI3KupWcDtEp8whgOWD5eeajjaDWY1kZjrfIc5he2LgG5YZajWeRJivQ2ICb5fzguUCLYKvOz7H9PfKb5YyZXMeXIjE/kDk8S0GMlN4AMDZahHAHxB0gU7ym8dSjLoSyYUwIEndYTfK0AH1zXteokgXJ2wCoOzQVoTL7j/dkbQkjEnooGOjmAcElDEg4CcDL4r%2BYlEl2XHIBJgP4qlkef4JESSiwMXpqDYCezjEo3p7fV6g2AGEHRYspbIsCnJxxUrB%2BQYwB7YKcA/oNZCtYc6AsyZeSCSCiS4SeRR3iASTyKEoT9iHWQvw9gRGSTySb5Vcw8oRYkQAOqzbmLfAfAe35akDPLUGbq4VXTK4sNZSJBBL1ZP44fGgsBLAFE0NAOk/zRw3aFEQgh0h4kkVCXMK4rkkhYpUkyOLjFWkkVhP4q9NFk5soIZiZ4QWBqg2mLsvZPCNEzmzJEhhxkwGQrxAFoihEw5hkJbQCRE1lAFE04AfAffrioCcEMAAHKjgNsxDMLEnIkm/B%2BsNSgFEpkAtJEVA4AjSYdFLmD%2BwE1JEoMOIdeOzTRDUfE62ExDFmFP6O/OSC6MKxgtACrDr4ifgQE3MjUIISD8AXUivIemCVwFyynkHjCxoUsBXrL6i7AN0kj7G7C7Abq6OdMv4oE%2B1EGLKRbGLCDHsE1hE3jcWw8E5glcI/gnMIxFZaLGDFPmERHwYh8kXkgVJATM0TCpcxavmMCZwYrlKcI78mKpOCb8Isi5KQbgBapVCYgUhDGYTOxYyEk1Ia2fCaETdDGLMTDFuLZQmKIx1LKI/DGaEoC7bATRFepZib6EqWFGEriYmE4xExpSwkJLHJZfYhMDw6djFiTAcmB4k1C6rfgD9obOKBIRikppczrAAUwBdmFRAg48P49QgRhsUhzHiOXwH%2BoTOr8AS/bGkz4B0XKWy2I3YDa5b87CUtGwSU5AnroMX51nFjRNo6GaY3UcCltLLRUwy66lDBATghS6RGUt9KmUpt6R/Z/opdRJh6DLYF5dYyn%2BdWK7vtCACZpTlhw%2BaRoICN9GOw5Z62w6BrGNBXxCfYYadjckaQRC4a8gEob9RMxLdTBdzuwURYJo/cYNg%2B1HRUs4ZpjbCBxU2gpXDRKnQNZKlJJaJxpUw4ZtjfujZdSymbDToZ%2BAYTbW7LMJBAQcZ5jZB6XDMDo6POmZtjJSw9%2BSxwZEPcboDetjVUrsY9GHsYZRWkbuwCWDIAFqkaOMlEFUjqnhOPVqPHVLQfpAaminMUDtWdkxdWTkyNAVsxUIE5KLWQaz8mIGBCmCawQwMUy%2BgBoCI2ahC0IXoBLWRUyrWZUwIwNUw4wPGDlAPayQud6x5II6wvoUWBlAV8BmmdmAxmQAHHsJ6yZJP6mzHMGkA2EGlfUj0wGwL0zfQX6xw0/0zg2E2Aw04GxfWNo6RmaGkGiaGwQQaMArAEYBjARd41FYDHcIJwleIbhDxwIMDgIY4CuAsJFB2UBAU0h%2BC1IIbBkAHTxKIK%2BDAYjRC%2BImpY0IF6hVLXmk9LHRAC01pZNLNgASWXzAvYvxFsAASAGffpZYpdgEkkUgBN2QTze5FOLbMSQYwMSuBSUNQk0AUhhsbBhwh9AWlvUXVJ1Ey/o2meaizvBgDrFemDFEbFL4hU75a0sBjokcWGzIUshTAU4k1Fc7EUyKSnbAMi4XkWQD8AX4i%2BoBxB51STroQIWA4oLVDWQHIbcgSOlTAMc46XYs4MJLcnd40rCt44ZLOAKSAXaddDqcfNzzSPRCZmPzH7/WT5jFayYfKPpizMKyL5eQ5SiEtKFnvBIgJ0%2BICsIIOzIIDTS7kFWn002EB/ErZgXaff6%2B2WIDooUibZfOgAPrJTy7AUlhOWOxa6pKDKGqQLGsoWcihE07RmTdYqXMD54qUHqC7AcTxXAGhC444ACZ0pSjZ03OlZAEFhl4DEBvAB/6wgfxIH06QETmHOlCgPOlBJKJCiDYNbUGcoZ3gTjhDEbCJtoKHiVIXeldYCtC0ISlDvYKkClgC%2BnvAPAhpIPOpvOCBlX0h0jAMgWkZjXEClgKBl8fPRDIMmwj1sWEAXJIBmhgEBkJAXBiBhO2gCgf/B9U4sAi/JYKhUCKDDYDmlPIYOgc0oJJsEENjNoMNiSYIyDcZd2FgaT5CHfPBldAAhk5dbEbIEcIiIM/AgmbBC6wkURl8EaCErsN3BCkVan04bhlC4huB8MxGCi0wghQjLxBf0mBkRzCRnaM9RlJsObzyM/Rn4EKAIFEYx5LU%2BohUgENHsMflZ%2BYZRnbAVRkCM4YiaM4eAYsRNgcYObwZVIIhEAMxn9TdvBhfFRJDDPFDcMnxnDEPOo/RPvzFeExl6IPxkHjayB/06dFaqf8rn/dSi0IPLHdqFsnGqJ8yI2CUYWAUiz2YkxCHmfTH%2BoQNByQENAcaHwgBQAOlB0kOlOoBBn4MpBlYsHQgAUBthKU6xhWIUQAAkGQB/EWLg5DPNpLBS%2BxAgVVBDAY/jkgethME92D5LQpZ0IUClqLNgCATNdhXaQUBdYWz5jYQ9ad4XOArMvngoOSECcgQSmd0BLxzASiJVkLNwqUoOy0WEVCagEibO2YiDKE64xSQU6gFkJvwVIc5lYpeQDpxdsHzUbLylk0ZJskXf4e0fq6VYuRjFUZwB30Zur%2B2bIL%2BUeahUOGgBpWYyw3UXVIOIwHyj05Tys2NHrskm5nQ5UsjqEgilCcXqQG0wOLzUIwBjUD5TReM2mMdW1IW0aSg2kTCmuLa8gw1d2ydFSgQzAHpJ0sEgCqefpiIUg4AwcRhC9YOsw8siZLIw2gBoML2zXMrCkoLGsh9MN%2BB3aHWyCgJ8holXtTsjEsmfMKop0swQySs1YlQs0VnpEU%2BKTUJWF1JNWlAMaSjisxQnZeepBE4aaiV02bER4hVicMcKzEoMODJmMLG3EnN6JMNJAP/f7hYpZlJNpKRbZoWnj2TMVnqs7FlSs9Ho1haHKuIVenerYqCEUx1IJwfopUs/5m1ExjoRMZ5D3E/oka2Ekk6BXci0sK4AKWBEi6pASC8gDopaID%2BzDPWWh8eBKgYs5nDBsu1JPmIbz0wSrE7/BahdATVm6pB1mW2cEBWlJVnVs01kaso1KWAPekE9PSiVsiurooTtkKs/kC6pHtnO2Z2CWAWuks5TNl2fU7wq0orATUfln1mSggOI51nQ4beC99UYhksnq5YpEPouwBqH2ARwDOACWj3IZ0DieL1lexD3jM4WfDSAB1heoU0nPmEIBSQf3DtwulCPaL4BmkRxzOOagF22F9klsOQDYYOFIGY2QDjAbgA9waky8ARxCZMTaTYYZ35YpUQDZxP3BWIFFD/mQCyP4L1IiAO2wdoO2x%2B4fCbtwz2AewB9kgcgzHSAA9CPaWfAroOSB7LHcwNsCQC22WQC8s92D7oaQBKQJDn642dD0oc1DUctgDE1WxDVWWSC543gC9oW2w%2Boc0hoQtGhMAHuBRAF8ylsbXHbmaQB2aHuB64ctgyQETFYpT4AnLXLTOOK9CBLF8x/LO2yA0EICSAUszIcmTmyALcwqpL4DSAF8z4ciOyGcx9lRAZ9m2IK9CCAK9B%2B4Btg%2BoXVK8cmzkqpexCPY6zkhAQzmzoXzlb2P3ByAFFB2sD3gRcj4AqQQPA7mOxAAkXtAToO2wTobDARcxxyWIdjnmkF8wKQL1KKcoPBHoXajgc6zkaclLncc3JgqQADlI0Vznjodzkvsq9DZc1zkmoMLkRc3VLAWaAilsX9kqQJrlPs1rnWIt2A2scbkTcyblTc6bkzc2blzc%2BbkLcxbxB2aQAZAApZ2fSEClgelD1FaqSy0UYqh9WrAYwORj%2BTc0AzAI3KJpROKrcmZm9AcukzuPbnV9F9R5xE7mr0h9bwWflhHEtwx8km4AyBIOxpwBj7Ek2IB2aLVLTAuOLElSZJxgT1kaDd2BTgaQBRrUPqkDUsjRWN2yJQCwBqcOmIV08dl%2B0oLF4kb4lYpCUmF8A7nTUwkIrJQWDb8V4CKYcFk6zSiB/FCWDMgay6wksJlB2KcBv8Jojpoo841kbblMfaUC50WEAyaNJCUEX7mg%2Bd1J9MapClkWlgSIs2y6pEFE7nbYoRbLqDOsnHmMIaTS6AXvKjEcVBZQx7lhIRSjVhNrA3TEL4zMm4mJAY8jzwEVm6pCUnIaJPiOsiMDcZXIk7nWMlCwT1jpoSFyWpeeAzAQWALsN5l3s92CgQTyadgWZB6QBIB%2BxayYTmXVKLc0PlLcw2xGTIlBnManiyWHd7DrZugQ8yXm1onSiYAMgBtYctycIKKyuAYaC0AdPmH0RhCVVB05ZBRSapwQGQArZ%2BApqQAgF8p/Hp8hZD7sCUDV8kHgIAHcDs8fM7V82FDuBIsjZ8BvmQ8izC5QJVD6/NMD8aflDYQeXDXrEfndARggsEbCCT87ui%2BEe0hI5NPkcsxEgIwVSrp8lFDN8ukCIkZKo98oyYa2XhCCvemxMvPbHhPJWgtAehzSUO7mqUUgYqvH3kMgMUHSzXVI08xKCUEaVkl0anhmKWEk0sofmj81lBAFIWCasphC6pEXFf8jWwG/fDoeQxJCA83nm8QengeMINbQ4XAHDEvkgnUCbCMIWEnoAEOBcoW/nTUzYYzMvsB3EtyyA8%2BIZh9Eug6janhhxWXnBEhUDACgWmJ8oOwxYfvkgAfAUkMydaLI0fkj8sfn/qCflT8v9Sz8nlgh3BgX14Rfnr8wvAYwNfnL8pl47gbfkq/T3nKpd4nstM3phrc7lYpIOoWU2PnolJgX4Cg34NAv9RcCj2h8C3gW3sfgXVsQQWqC6eHa4EQWSCkvkSCzlmb8kqj1FHIjV88Fgt0Ngix83fnLctOC64JIka2fcykC6qRvc3f6%2B87YCECmyyA8kpLQ5dpINUZuq6pQJjzwOICzIUIXzUF9TmANwpCBdNh7EGmBm9A76OYvpjSUQICkReAXFMIOxU8JjScgfzhhErlDMgUyaDFDun2AW9mQ83VJqmDHlDkumKF1JIU8gEPlh8xbkqCqor8QKjo3EyYiFAd4Dp%2BQNmO8nvwW87Lxvwf2CnMcqD1ILPprAWaJJQ%2BDYRMadlDIXcjUsRShYkDoVo8wMDpsLYDMgIsw9ceWAn/BwBG5IskcMXYqqsqZmMdLmCR5ay7TM9bkRfRIAnvUvkh9I7xU8Lukk4dIUpxaHIL0oOxpxInAQ5Bhz7si%2BjSUL4iiAEKgO0H4XceI87RC4YlzEp8yUC3dnOQXoXFJXwXTmWyGq0rrDUcpSCyAXjlcAJti44OQCKAT4AMZSTl4igkVoWR36OoXHBkihALVUZbk9wfEUToQkWLmatR0ihjJPPWWigi/rAzuV4C8gBTSIoM4URk7HkFc2LCnwLEihIO4AVkobH603vLBIeAUrcEFIzE74o%2B5D5RG8VOK7/TTS6pHYiI5TADZQiZLQiQHlRWN%2BgV0gbC64PpjaYmdxfCpYl6UXkV1JNOC6pA4UIbdHmDklYrc0Q2FHtI3hmaeUUBxC4VCMB0Xlsniro850WY8z0XcAqLxroFIBTrS0Ua2W0W4ilkWyQNkW8c31C18ANC44TOqA8zIlsoXVL%2B8nIk4Yr2y%2BxQ3InffUYE8nmicgFuqzJGsi38ziaJCgHloimtmJAOMksXUnjlkiunzCw%2BrbAew4MOUJB70/kXH/KngzM4UWEs8nhdQZOJm05urGsWwBMAVfwdC8IUa2TIkpwaUxYbMulTCrqBFYobFm9GslWim1n%2BdNWZBAZ0A9NPWkiihFACi1bG3cvEhMATPAkAMSDbALEmA8umA1hM%2BDHi64VF1APmUENurLoDhm9xdTzAMLMh%2Bk8YBLiyEAri6yad07iDASqMxBADkD0C8wWQSlcVz0ORgzM0CW9dJgWKedADwSkiAQAKwWcsmwV6YSQX2CmQVOC3vnMpYcXnis0V/eYYl9isWGuaCFlDMdlAziucVeigsilkf4VYpN5AzuQHIOsvIUa2MED4C8oXMSqmCNixgWbDPiVPCzjjN0fkIcCzFz6CngXuAQwVz86ogooZCUkQYiWNivb7N0z1gQiz5AzM3ChB2boVzcxsUHrZiYEYWKCgALVJFMxMVUituAVsbLmq8TDbiUceLSUKQbI1Y5i7kBziEYp4XdNfhB2ixFDbAV5T05bjIfKEyUsvDWw0OL6TnwU7wzM4AUrcTqhdYQgDhWAHJuzTkCjJV%2BlYsRsXNC90XPOemylgNUzsjVxmK4fzjIiyPFH81KXGIJ3AXeXVJUJYpAtoGZlmw8BgECmrDFXYTwIwLqDmAaxHmYlTBWS1kXUiwGi64gCxAWKxCFMxzHdS5MW9S/qU4coaWaQMtCzIR4WoAFOBvOdQhjcgyUrS1aVrS8blQTCzjHIXc43UR8UOS3iBOSolAy88elpIInQpo0WwvCikjDPezAKUHrD92OkAyQtPZvIRTBBIP0DeNWaW5QdEqXcp4WbIGdFg1Jl6mSqVBcEOIlpM0MB9gMqWsjSqXT2bTGjStkW2S2SDHUFoAemHlBhcVvJzSlOA5gGZk65LbDOwMCAUYYulSXIpn%2BccYV%2BAS1JDChKyjC3yXoSr2wL7CJxBSrn4ydRRC6pUEXtS2ECiAORjbFUHjEvG2lZS4rENAkmU%2BAIiaBS0rLtJQlD1k7iFcwM7HDShuCwy6kUcUn3AvmSgCP4B36tsdDloWZix0I5aXrS7WU6ywyVB2UQC7E0sVW04VCd0HHmqU4eDlLI8WpwQWlXYmWkeIWhBi0pZYi0sRluEr7HrYGBmuytpb%2BIvBArYhWnW/CzEewZkXWSn3iyQStgocoxCWSoOU9SmyWhyidCIy3GWVit2aZnPWo4yxOmuYuvEuIuRgj0QPGyytuDyy2xCiAJWVdM9uBqyxHi9w6Jg5yqOVjStuDboBWWFy5WUly%2BQBkXMuUcY5P5cUxxCOIH3gIcuSBoc1Tm%2B4LtAdyuYCdykcjQyv2mByykXRy5Vb%2BoOuVFylWXa4puXqyneyyYjOWiU08kcY3mXDkrin0WNgAdylxgYJKxj9obeW7yxckZoMIRmCM0SS8x6jN8kaAmhbLxJQQwDUYc7p20l7m4IQKxGsXoobivpJ3fUvktwRxCA8jqRvivQmhLOyCv9AgCOqM%2BDcTIgCZwepavy5DR2QMIQAgDdi6gcBC0AYABQcOPi9AZABQK6WXY4KuVsiizlSAeiw04tgBNyixCkKg5Z2sCdDLmStg0A9OVryvjFtyr4hNygQAjyrFInxcczjimsi/yh9axwYemWQUemlgfBCjWCuk6TddA6vP4qv04lB1UemC6pSLyk8m0w3SCoXbLGBW/MSQa1mTdk3SFiCe2JLyspBXheNWBhDAKGxsISvxjy3OX8Af5bqAbcxLkkLFSEs2xWMaq7HweRVWcOjZCgQWbSoH3wg4y7FDAExWRyieXVy8xX%2B4YCzQ0G%2BCg41RAzS/pLfS%2BaUJExP4LAABltCkpDZscBkUEBKzJMWUYKWYdKwM5JVYgahYpwHXKVAplA7YIbx7M1BmZsNJXj9MLxFK8XYrsRJnmROyC6y%2BpUNKjaVTIN6VXSv1id0N5xexVfp5E3DBqvD2CkobLwt8F/lx80YrSANGw2M2pjX0Ndi2MpmKOiabBjFL%2Bg/0IZXdMR8jokeBnczA/pqvZVn9Mey5/FP2g3XLDCAad%2BKkhe3ZEAFNTbVIZHt3fZUApAnr%2BiI5Un%2BE5UpqI5LoEL2LtY3d4qnanjSAUlDBYj2CxoUZLlwXQDp0dJD7AIlDJEp8U/0fpp83Q5WgqlU4QABYiuMZrQ3Ku9aMlAVBgqsGUuaUZUHoh6grXRIifKjnrcQT5WFpEEBZKh/5v48TEcACvFp/dCbSgHsUhIOkCUwagTIIPemlC3JDzUEenQM5ajQqn%2B7MQdCUEqjxWE00YAHMu6T8K0TQcnXinDAAVUTANlW5ZWlg9i0sAj8Cmo3wImmCqqVWoFGVXWXOVUXYWxJ0K3SlijfWDNoSyBBY7sh7Qf4pwq35hPMmFn79YFioq0rJMkjoq5wS0GVEsUlijaShLvGqW0ZZnK10lVlmq/ygFkCKBEkJlAzuUZUZM7mUioFOBoORpIlJUcABkpaIyXd/hbK6ShJ%2BbHkQlFzY/CxpI7CsNVpwe2npYqwD0SsqyNYmdy0sBwAMvJlD%2BqvAFyMGskgAXRiWHRIiv0Q1jJoKOishTlU/0Ltj4qv7QVjRHSRFV2h3rUP7roZP7kq1P5IYaexKqyVXCq3LJ8wIczLyteV2rYDGs4tSh5Epf6jFOemASkaDFUfZiyXB1G7BWxknaACXzKldUn%2BUFg40azAIgdGUlIPdUnkCdqVfMIkwZFpCECT9FEMJpFzK3gpnq2mjPqsV5GYV/F2rENHbqrDBPqicJNUawivqsd7vq6tAY7K2I7wSzzfqgFK/qzQ7/qxIiAaxdieOedCpUEDWfqmEJ2vLNCQatvzBDZ9VeIeDWd4RDXAa7Dxs0ALleS6SiksUZIPMHpogqqNaSINTk90xjqSK4sWr0085B2RVhICsbFcoO1XhWWzThI1ogTK7HD7afEghCvKDDockoeQknn9kYr7BDQZWGYaYjKSkTX0cQhiYa%2BJXIAeqVUAWgAw8v4C7uKgzKRbroPyhmGvYHRmXYC5Dl0SFCSdXkD8rf7AXIQhiQoZNiPJZFL1EO1ZVFWKU2Q7l7mq16E1YI/n7vIYnusUiL5eO1Uqna1nc0ETUoLaxb%2BfcHKGpUZLf8xMAqnIZWsoVfyXtYVAb/MDV8ag7QCatV5VMWjXKauqUcsCtCaa6yiia2jVYHFJrIarFV83agx6aigAxM4Ijl0czUioSzWXYOJgegoH5FsZhkDNOfGPMLLUvMOJhBbadUMK6zBmKghX8AIhXSAdgDkK8hUSYqhW2IJ6FPYcZVpaj2CZ9cTVLKkb7Sa2LWya9LmuaRTUcsbLVPC1yrY8UErsKyyBcbZeIrsZrSv0SrUGa7QhGaiIFmalrQNam7V2QMB67QmpW8athj8aj2A7aqJXIAPbXaiqwCHazhW%2BYDbW/XbTXbLc7Xf0fTXVawRnhAOrUfajpjgMJcH0nJzQdaqwrssTph3JDBLC/MnEIzG4JkYHRDLIa%2BWrfACFU/blg%2BAANpEmNvY0IsLLE/T%2BF2o0DUhK8P7peQbWSAYbWiAQQDEK8bWAWChVTamhWh4YDHWqv0m%2Bis/7tYqNbC837UXwejXbAPUasqnc4yaligsAXCqJxTXIVkt54WMcTxzaoTULasTWy65BK8FbXUYMVZ5bazpjKalvg30VnjOkwXF4ucHVVa9FUfYazUcsWzVJbDHBmK%2BGVGkE9Uu4alC2AKGrvKr8Uji%2B4oi63CwqICwWsWPYBi6tHk9ky5hWXSgj/fBPKy89%2BCJIHXoDDE6GOa0fzOa9%2BCKQkyxo8k3WGAVnjzqyAUFkKYX8wWnnvkFLVva%2BbV2M6%2BA0kcTWm6kxyia4HXm6vm6QaK3WwfHFUXg%2BHUzNLdpLYZHV2vVHXw6jbL3EJJmQSphChqpOBZoTDDTAAZ5vrW6VL9KuBoBfAhq6qXypajXXl6pYAOMyGK1Sp4WrQQ2Gu0yHXDEaHV3a1vV1stKZj6gnZBfQzUUYEL5YKmM5uoS/X/4JTWwndX5qfdEpCUtxqx4YX4KXA4DHUINbU3IF4ZsYTDJVOLjH62m6d6//Hd6l5hqfFQ4z7E%2BgrAGGV4K6kXcrHuACAYOWOcsxCHUVtgB4X4iosP4CDZVtAx01HyHfagwzMzfUwwlpA76wgh762LBTgQhjqAjGACDfU64Gj1xB6xg0OZeg0XXPOo842A4GeJg3lZFg24nWIAPXSUqj62g0YJJTWd4OoBXGJlzYG5g3poEwGQuMQ1Pwrg0SJKpluoN/WNzCEwgE4wwKGi/D0GpaXuwaqUoIdfU5sLu6lkSAKPipVh4AsahuqioWkBUKZI%2BWIUn%2BYICcMA1IWi7sXQ5f1gIAF3nAiueDDQd2ho8h7l4Yknko8xTDieMxXwG7jn2MSeXIGxxjqy9A2Oc2x6qPBYAhGn5YIG8I3%2BKyI2oG01B00WI1U7NhBiY8eVJitkWhGxA0RGv4hRGtA1doX4gYIcCwiUFpVhINpUWASZmNKxo06y7lIccryUzuHl4YwKcXh0nWyWALIpSUIlBCMmFjT/SGU9AFo0tGo1CdALrAavPCGCgFonmszzVpwO4CTAaGGbKk0XfFT%2BI7CgZXcalzDjGrXn8fLHXcigGX9FLmD5E0ig9FH2ynxKjWusr7XeS%2BezjG0iVeSkJDvwOkkZ69cXUC3RwZeQV6LsSRCCAThrya5ACuxLFiwgTIm7G2g0609JD/8mHAooGg2Gw8umvPHiXbAF0VHCrQr9C5dCe9eTFuwG3ZooQZ4NA/zj5iwPkG/boAAgKInNYTgb2RJ4Vqa/86l8mE3j6lNAAgBoWQ892CCAYY0VSnEg5azph9gCQZe2AoXIbE2mh0chwws2amG2d2CDGnnB9MYcWX8qNaiao3hPG1bgVs0dho87/nYQd4BL07CD/wKWw27FA6JIHHnq6qpjL6vA2OYgg0UmjlikGjPB76p5ERAn42cNMzUScLu6SIV2LUGwA376uHUMtEfFK4gOVmK33DiAEIB2sCTE4rYOmOc51hLyneomrRYV/i/TAhqy3nXqgnkbC8tWrqkVCwkg34NUM0jUyysKHK6JVceDEkcYBSzLUbMZ7Ymoq9ikujVPM3p94lTQCDFsWveQ9X79d7V1G2aAgAaDVkNAEj0cN3Xv5VdUXq6KBXqoKUtoFgCCQU5X5a7S7bMUkA9mxtACofLUUZTXjUGOeBzE0Yoqqqk32iwMRMAZ8BHQbVXyYrjzMpF4XeEk/nD/BVjCyjl7xgZU0TJP9QRISE08gUsBnfLwWrrbmYnmgHLYsxEn3i/pKvK8TVe2UYrfK0kI1YKBpcePvERMZUVVwfLwD5UjWtEqOKOTL1U8vUiBkwLIDZihY2Xm9LxHmvPXfMtsUmTa9VaYI2nUGS2zGIfM1JgXWlh9YQFWAXInq05jZmGyYC4YRHC64f5FG0rkAq0PSi56s5jFEtrAwg3chxGqAKveYdz4RETz86m%2BhXaEZoL3QHx1m3XVraligbayKLqYbbVA6HqKsWuwDsWwwAP0wQG8/Ws3KcVbVcquLVyalrSAEtRx36xJ4JSzJJcqji37q%2B94a0PKCuxHuHlNAgB7gjHByW5gXGmzph5avEj6643YicC7UtvOEwuldN7rwrmwSWlU430aS3yAOL56W%2B001kZLRGBGiCmWkQYmyiwCYyyy3gMay1/AWy0uaVS3mcHxBVa2rXfGHtX8YpnWEK1nXs6znUTayhWyQahUza6wG64QejmWmZk/ag4Caaf7XHajBj0cBy1JWnRgPao/E6qmujrwgA1CGvTKO6%2BHBexHjxok26ReQsagkWG4C3GwNnH68E1wWnkDj06C1ceQk3PgEk15E7FnD63kBq2Yqg4m2EXDEkiyveXEDFWjfVgmkg21WjljQm4/XLOAq0TWuEDE674xw%2BKqUWG/Q1HvdzWZ6%2Bw1Jqvpidm0rI0WgNXK69f7OXBTGmK2A1twQo0pGwkU%2B4QCxmrWxAKAyyD5ayQ34sHg2bA/A3KRdk0NSsJlkGnEgWmi5BWm9Oi3apQ2wcO00GW6EgIgKTR2QZzYg2qNbSMV6Zo27UiaG0m0IgiG1gsSvDpsVIj6WgE3%2BWgGgyM6NBk2sXDE2xnAS4dDLOEbfDM26eGs2ujBM4QbGc27m2MG3m3i4XXDOEHACC2oW0WCkW1aldm0MAQwCS2qW1E2im2y2sW0MARxCK2pW3CDGW0N4OW2VNLm1a2wzw62lrWuCv2HAGloCPMDQoQmDQ2aG422gYDr5M2w21cJO22v0g21O2vjIq2%2BHCnW9S3u2uPCe2ujAO2321G2/21zoIO1B6kW06GqFmqQFUYhcNFDr7d3Yn%2BViUmVZ2wdskiBrAFXjY8wRhfWrlZJGsI3WS/63CAQG0Iy7I0JG7O0/W/O2%2B4Qu3prPDIJ2sOFZ2vxUFG3O1FG6uUF2ou28osVW5GxI3zmZu1/Wyu1F2ho1NGwe0rSyPkFUXYUlwEa3kykYVS%2BMYXm8w6ALiwaLn894B9JGdylkjomsa7QJcYH3XSUUBC3IZKHMgrfpiXCKA50eorpIepZT/CZICs0HgrG%2B8mpU7YB0QTDbjAFmU11LUDuTfziVKv8XeGsYkkIGA0N26kUDoEkUdwLkWem4kUKADuAjkFYBDAYLoRykaXZ2hWUDoekWcgMxVwOukXgO8PAqAKB3QGz62/2tuA2IDkX9oBB15G4OW4OraQoOxAgrADB2%2B03xX5G6kXEO%2BB0yASgASAIB3Z22h0oOvtASAVB2QO4DFCMCLERISsKXMYVl3aBFC9FQvVDKr4pYi1wGZfGhI%2BEk42jgB0VoC92Cwk1mypweagcSynkzATgZ/FIwDz2dFm0y3kUFkVEmCgQhALi9pKa0ilnHFD5TB9CUbTABPIgs32zGUC2hOG5qWP2k3qjAcei72sNDSAzzVGqpKW6pREU7ETJB52fyb72m9mNioRgYAAQY0y4RV6O75lEDJ7mxi/4AGULR152IZhMAK2yRKlOBnAcyhB2LRXbASWGnwAoAqkKNhkwS2wRwIgAKILYAKIYABAm80jAXIEUqioZicyoYn328lFmXN8XHY9o3uap3pDMVyWjcyXjeaJdiCALR1LALQoOfLbHs8XbC5%2BazDoSpjAdSEwAriysDMXaQBS%2BBn6G5JZ0iOIA1dAWUD%2BWR2BrKtHk2GHJkg1FjAGwLZ1YAEZ1hdATSUfaYKBEST7H/aj4ooLDJ0QcgS0oTvA95NZ3EBNM7qocW2c2rdTgWfzhKEA53y5I52bOzzDbuS52s%2BdG3z2cuimNRZ0whaJyfOhgB0QTm10Qe50MAc8Wc288W/cYZ3cQGZ3JQ%2BZ1S5WGw/26h1Ei/tAAOg5Z/qCAABGECHYQFASqS2gC1fLCGr0OJWWa6l2PqVwB7gpJ1QujMbTO/DCzOvF3eETB1UO4OXIO/B3gO6l2UuzFw0uoICSFel14/WEDOEG3W3sQkCkgS3KNa8l2su9l2lYBOzhAUxqhQbl2gkXl19WfF3QOmWXMOwNB0O8l3iu8l3ni6V3TfZwh/MRV3qu4wFZmTV2cu0KAcu7V1GugV0wO7B3sikh0iuth3iAUpB7gvV2kAA10ymT12UO711Eu3110OgN2iuil3Ku8YAj8yV0/IOl36ABl12utV3Ku2r5B0YF1nxE3xuul10euwt2Quj138uyN0mun12pijMB9SgdCZ1Ybp7kdNAx0nui4gMj7rGKb7dAR504MRdjOEIUjPrUkBkfLFwUurADlCmrD7O0cApMNLSnOuhijOi51rMUp4XABfBLu4tCGTL12Vu6N3/20B0HLUlBMujnijywV2Tyzd2ki/gCxoXd0YcMukYq/d1Ru4OVHusB2iWM92aTa4CjK891Pu%2BcBXu9d03ukB3Huxa0Xu94oXuoLRMujrZMuooLvu3BU%2Bu290HLLFwPupl0Aei91Aei93dzJl15U0D2EOw91fusB2XYaD3/ul91706QDwep92Iei933sJl0TOj60Hu/xUQe/gAAgR924ev91Pu2D2vunD04iwj1Pu4j0Xu6LRMugEA4K1D0Ue9D0HLS%2BJYe%2Bj1Mej2D4e3D0se3D1sep90cei929bJl0OJFD3AOkl1bu/gDCpQT24ehj24e0T3Me4T3SAST24e6T1Pu2T0XujA5MuqoDcexT2ku2dg0enEV0e9T06erT0ewcT04ivT04igz24eoz1Pukz0Xui9i7u15lke691oepT3Huy1JqenEUaenEUOe6QBOej2Auej2BuenEUee3D1eep90%2Be393%2BaXd17u/z0fuwL2Wev%2Bahen5X2enT3Re3T06e%2BL0ewRL04i5L24e1L1Pu1UYZenT2yxBT3Z2yj2XQaz19KnT3hekT1FenT2xe6QBle6QAVej2BVenEU1e2j3pe3922emz2dez5VvurL1gejd18e0pA/u2r0dewr1teqL09e0r06ewb3SAYb0ewUb02e8b21eyb19K6b3VHdb0vgcz3Nexb2uCC72re9b2Re4r29e/r07evb3SAA719Ko720ek72fKs72RetGAXe5D1zenj1silr2Ye3933ewD3de9b3Pe7b06et70fez5Vfemz0/e224Xe/73Fe1wQNe0j1Xen13Cu7d13atYKNazL3Gu%2Bb1Cu2kUiu093WET5WFOMEDvFan2kLMEB12Nd1k%2ByeX4%2B/gD3u6n0ionhz0%2BnFWM%2BgD3U%2B0Szf1Wb2k%2BkH3Ui9n2LWrn20%2B3n0Wa/n0w6vD20%2BoD3U%2BtWzf1ED3A%2BpB0U%2ByD2E%2B6X3y%2BuX13aoX0c1JX04qlX0c1RD3U%2BrFzf1IH2i%2BjX2MWEV2YeqX3f1GX31avX3oqg308OI30Wak308OM304qi30c1Yj3U%2By7Df1HH0s%2BsX1twdn3Ue9FXc%2Bun26%2B2n0C%2BnFVu%2BsEAe%2B%2BrVe%2BsEA%2B%2BizV%2B%2BnhwB%2BnFVB%2Bjmoce6n3Ue7%2Bpcepr14%2BzX38AAT0O%2BjmpO%2Bn5Vx%2B%2BX2J%2B5P2Oe2n3p%2B%2BrWZ%2BsEDZ%2BizW5%2Bnhz5%2BnFWF%2Bjmqye6n1cPDmrye9X2wOsv2qeyv08%2B2P3f1eP0Wa%2Bv3y%2B1P3N%2BmL20%2B9v31azv1ggbv0Wa3v08Ofv04qwf08OEz3U%2B4VLf1Mz0l%2B6N3s%2BolJR%2BnX13al32C%2BxX3z%2Bpv3y%2B1v0r%2BuL20%2Bjf31arf1ggHf0Wavf1ggA/04qo/0c1Hz1c%2B5OV0%2Bvz3W%2B0f22%2B7d07uif0x%2B6/21%2B/X13%2Bu7UL%2Bx/3L%2B%2BX1r%2Bt/3le2n1f%2B%2BrU/%2Bv/0WagAM8OIAM4q8iFV%2B9L1c%2B6P1lCU/3k%2ByAOlIKn3EBq/3oqm/0J%2BxAPoq5AN3ap/1oB1/3y%2Bj/3YBob20%2BvAP1aggNggIgMWakgM8%2BsgPEBigPV%2B373S%2B5n0Vu1n3%2BK8/2c%2B%2BgOO%2Bqf0c1Gf31auf1IBh/3sB1AN3a9APcBrAPy%2B3APy%2BoQMiB%2BrViB0APy%2By1KO%2B6QN/zR30aBvpWJ%2By6C4%2Bs/1l%2Bl8Da%2B1QNwB6f11%2BlgPK%2BnQPoqjgP6BrgN3angPGB/gOmB2n3mBz73S%2BiQOiBqQPWBxn1o%2BqP3OBhv2fK1P2XeqgNs%2B9wNQemAPSBpgOz%2BvwPG%2BgIPm%2BvQPoqgwOhBowN3akwN3aswPWBkAN1e8gPS%2BuwNJBxwMze6X1pBjwOO%2Bxf2fK1v2uCVwPUBuh3QiTwNV%2BtQM8ONoNaB1gMlB331lBwP0hB9FVhB6oMRB2oNRB%2BoOxB6wMJBwn2tB6wOpB6wMZBnoO3ex33P%2Bz5Vr%2B6EQYIUP1mKlh0iu0lB0%2BgYOTyq4MHLWNCwBpn13B/xUPBjn2/MNdhM%2Bs4gi%2Bi4OmuvB0HLNWzPBoLRJ%2Bs4hq%2B8AM%2Bu94NYuYEM/BsENnEK31/ByENmulB3E%2Bs4gghjrZp%2B%2BENnEEP3yBsP0xulB3UemEO/MDEPdzNv3Yhs4jF%2Bkf1IhgEPl%2Bz4Noh2EO/MUkP3sdf0Uhs4jD%2BiEPRu94PCpIkOghxkNYh35jRaT/1shs4gn%2BqkOch5EPXB/6g8hkkP8hlkO/MXra/%2BkUNnEfv5ZBt4MShqAN0h35johuEO/MZkOChhUMYHYQPKh/zR0%2Bkn2Ih8UM0hv%2BbShnUNkhgUOsh35iGhi9hWBz4NfBxr1ihoh3qh0pCiWa0N8h3UPkh%2BUPCh35hOh1Uamh5UMghlwOqhtkXvBjwM%2BhzEN%2Bhu0MBhh0NKhz4Mmhio6fB8MMYhzIPuh%2B4Oeh272xhpkP%2BhoUNJhoMPGh5UOuhjMPKh0kP9ByMM0O3MOohrUMMhuMO2huUNFhxUMlhlMNlhsMPKhzMNVh5kNnB7%2B1YOi0N%2Bug5Zxus0O4hy4OehuN2xoNEOvBqMOThhh2Bu0Sz0h4kOzh2sM0huN1q2ZcO8htP2rhnB3zh9h1YuLcMyh3UO7h/EP%2BuhcP8AS7BHhm0N6h08PvBuN3Ue68O%2Bh5sP6hu8P7hwN2XxJ8NNhvUP2h3/1vh9cMXh4VJfhgsMJh1sOOh/8PDh%2Bh3sOolLAR2UP6hwMNGhlMMQR2N0Xhy1KwR%2BMMthg0PJh50Omh5COsO1CPThhsPEhm8OFhrCPthnCNphun1yBwl0ehgCPQRpcNER7cMgRzCMIR4MOph8sPdhvCPnh6CObhxiPHhl8O/hx0Olhl0Ndhz4M9hriMjh1COHhviMkR0CNkRxCMURjiNiRysPKhhEPjh/4OQR0cNXhmSPPhn8OJhtsMKRkMOURtH10%2BnsOqR5UM4%2BmsPPECdBpi2t2ZisVYNukW1CkR2CBQCAC16IUhVTIUhsJIUgvXIUh5sIUhIzIUjiVIUhVATkDORmjLORlyPOR9yNpaTyNpabyNpaXyNpaaKIqU/p2LsGmBZuZd2YpcJU62Hi0dK4pJXim8V3iqQXKsLlDB9X0Wnil1n8Sm3lvCmhC9SWsLnGusJRYRXX9JKNZpwDSaXMaunpoiMX3EvmCAigMWMdaJ6rMp4XUAYAAK8DyVB2PYW/CyqNdi8tknnQ1KXMFe3GANVLsoagSWQUYCHYt%2BzbwTCWH%2BS4qlkxaNZodUBPFQ2XmTKLxBgcWGfIcVBFAFHGImtyrZoHell0yCWjRzJUvAS%2BkBQJ6M0AIhkaoaHiA1BfWl6pfX9EYE0jRz6MKuxrUcsdxylgISCEMI51uILvWwa3kCqWiNA8OcGNEcOohCQGZkGy8uBIxjGNNEKq1rwVGMY4ISDBAbHiYx0xo7YYmMYwUmN4xmvEA8KxmHYI01fa002hfGHV0BZG1ufRqoWmvy0e0SzwHW/ULakJIGIIJ4Wkxxy3Ba1fh/G0WMOmwQ2GwxEivIcGNn3XoHdYbHhoFfmN1PY3BEx7PWUxpohdsWWNo6%2BWMrK58jX6v6MS097X6mw7BmKixVBKoOhnaBmMpwYWNw2s00I2jG1ix9OiZ3KCpOxyWM8x2g0w6vvFNal%2BI6kGG3sgJK1sxxtRcx/a1exycBI6kA3wx%2BrUOuWLg6MeWO/RlUL/RvU2AxvEMWxqxViAhFAUxxmhax2K3345K3tW8hE/MLPXY8amPxWiHUTgSOMW2rGzU%2B2OPW2w61stPONCgVUE6x14Ed1ZSKpEdGNCxpohCEe2PMxyE5ZBYOOux4QacxzG3cxo/XhxpuOuASg1yx/YG0pBC5/0EmM9xu/HNxguPX5YjVB2Xvao5R/haisq1lRiRh7G3chTbRaPu/DMaMISV6y4DDhwmo7xeQhuB9ivc2Ug2/lvW8Tyr640LzPDGCUAZtB7fCEA1FRi0WEVKZslDYF0xWlCyoCcAClLEGkfBgDuneOEEPYkEZA9wEn6ze7s8OYDE9L9xgJtIGQJ4x57qGHruwY7Cb7aBauOltnkDJCWPGqJ41kN3DDQFT7Di2U1P8/mCW0qHwe8k1aikK74gXSFm9Sf3K6vHbFU8fl15U29g5u560XMB9Yk0T1g8JjQIImpFkWXHoAS6pqn0J6tk5AZ5a67Ja1vratmUJoEIiUVqW9JT1jUJlbjl0rl4ooKC2PxuRihIlfU34xzEWms5iQSvGLEQYROmNPuNJW0eOBfaBoWmxtqSIYuYUgcBY9%2BfU4lVJLFI4EVRgJlUolVfm2DALVBGA3Z3I/cIDdAd/XsgSRBXx21iSIS1G69SMos/OW1/qTm3rMFQ2KXGJOR7OJN5QBJOfVDKqBWFyO%2BnFwjYQYK3cUN3BJJ9ZiMIfzgG/P9RmkGhkjYazQo8gpXROBGCMXFT5k84ghZ9d0wMJ70p5QGgSeJ0M7UPZEyu29ZgO2yhG06iZmbx52jU8ahNkJltDwm/fkm0yNne2OFiYVE5gNCvfkhCryXbc7OwWgC9nnvC/plSd/gtoVe3ZeRIDIWtkle2byE%2B6tgCF8ArlG8VurLs2pOd4LHWZRwQDR695OBOuPW4UJd2CAVq6/4KkgGrRsWQSm4l28mHC%2BSkTxzvDoqZk381DMIJ21QpDHQgyjAa2IYjr2i%2BjO2Ll7LUd6Wi0QsBCAyWD9FDWgA4q6WhIXp4toIErHC06ihQTXg1kGk3vAIlNW2ba1HxrU02Wap2RQLZ16QculazI3Ib2DE0/eRiB30x82RAZ57UsSPX3i%2B74pxGsjxISHxWI6RM7Cwd4kAWhOAihhx1E7E3KJ0iQk0HWY1ir1UcJv4raJxiAvx0xMNwC0151XZAYSp%2BiQSpmNJWmWhX2CkhO0QQF0JkFLDxoW3MOLgxOmhxN%2BmKiAMuoPUuacy0fR4ADyQp4Uk0OrGyuxg2up4UUcp8iDUGwSCgpqlOofVIiSIT1P0JURMPAu0LO62OUIy3YBu60sAIvZ%2B3JxUa2rUZ42QYQNlzJnmIHDOJ52%2BPKCeprmbpeQNZHeEL4rJq0XlStkaveN/USpiAAOUw7DC/aVOJICABTow1CY6nAb4u1eiuMRhB1p%2Ba0ioN5O7qMqSiEu4ABgH%2BMJmvSazLfNywokwDeY1tMRJ15TCoHmgJYPHUgAQsDNO6anvIDSYDkYdZ7pvewboE9MvTbii7p/mCYytjiXpk7VxrXHV3p9sDXyvey1kW9NkWGWgowM/ljBC6Zfp/HWJMPqNhQ6cGAZt9PAZrnBgZnj6vp%2BnJWALHCuMV%2Bg9pvWCdU8h44fF1T4RaPXsqZYHhNBEDR60sIxWIBPOJnCpVps2A0hVOoSsTkBbxt5NuoRLjuJ%2BH6eJvdZU26Nj%2BJo5UpJlYBpJ0DzC/IlQ7pmDNkWRVg3ywKGnp8DMCZvewJJ6Cptx4jhy20JNVJkU19W1xVcYUZKWAQJx9eMqS95fF33A7mjmgKp0oIuYYtvHNbaZ7HWerF9NkWZTMV0ACFceRDKAilumVPAFHtefd6GcBKxpQwQyNVapNBp32qMqZNQM/dJBMAKDhEpVXkoUlrBQcDdh%2BerhKDpoa7pAhJO4gbjPbpzjh7p6zM1As9Ovpg9OYbR9MJJpiF82qqowVUtxy2%2B4FhJr20RJn0CmNKb4JJmLOE88DNmZ2m4mZnMApZ5qnHp8w7k6wvksk58G62tW2r0fLNTFGY0KZnYhdJa%2BUyJpJqtuFF27gqBNk49a0UuPTOY6wzPOvJLP8ZgnX3YUIE4p%2B1P4pm0yElIsiU67XASZlrMkhdjOCATjPiJMrO8Z6rMQZwTN/OUDyLZvFOOptEohnRrP/nbz4IAAjOjAdnjweLLOSZuoijJ1PbDJ21FsLT7NUIxhC16LeOfJiDroJlPTpA6BOEghgBwJ/3YSp7DNPgkjRtpu7Ohod%2BPIAT%2BOuAb%2BM3RhWwNxzJrA5kj4TgO8Fr4LDOoZwPpbZg5zR63IHjZ51A0ASNP/wmNPuZ/yg2%2BUnNS8WnNdadlPGpUAIdNHvAeEDWOFEkjR5/bXDppsOWu69J0bcrp45oVaPuTSKCji/gYHmMVO3Zh779DcnMM5mKEAQkSiXdaPUD001QhIS/oMOa0EjZ7TO0ZdJOFZodMlZkEwHZuLOvpyrMzZmrOuAQ9NpZkEyK5ikyfJxIFYEeHOpwbCUSpnk6DJwX6MIKqZbx5DPNRrHMJ7Ah5ug1NMlVZDSVJnFprAllWVpJPW0tbHNo6Zwi45kPOMQyFzh58RKfVFnN4IanNEAWNN05xqp%2B5ytL68rlKd4DPN6QMlosATnNKxhJO857ij85uOVZpoXMu4XNM1JfNMS584VS5mOIy5/PMJ65iE2A0kFjTbHMQJlFFYPGBM3gyHN55qPO5BJHMo5tHO/xqB7rMc%2BGpEQPM3g%2B4Hh4i7pZFfor55yOIzposxYHFfpbi8YA9SMbNi4ZejY8afO2tdHNh5xEr4VE60RJ/POhoKPMMmfPMw5tbPgwu1FceNhKiAbfPdiyFl3J4VKtXCjqdUAKA%2B7OPPUfcwCTg0RKK4EAsEPBADgF09NQFm8HiAWAvXphnDwF1eiIuqBM3Q1AvOEFkBIFyAtL51ehtilUop5ijNRHTkBRWZwh/CjYkgqjWwnmwtNJgX0gT6kmiizE1b1pk2kHGvewXR2guymzqjUs5Grgk8RNijBbDDiuJX%2BcBziAqr2w1k0snpSjDMGNfYDWq4ArXZh6jMZ99JeJk55y27QB7Z1W1WghgBsuhgC7OoJMS2vQtr4U3PgZ%2BBBVZ5Tivpi9P1Z0VwYweQsFkWHPImcZOfaOW0K2owvO5iJM8Zs3NkWXqQ4kcDNWF4p02FuuI/3BQsv517MY4Jwv2NOW0a2twt1EEwt8ZnMBwZ%2B4DCtWPBBJ/W0TsOW0mATQsFZsx6xZ8DO2Bcwv1mywtBgW3MNfWwssp%2BagOFnUgRFrQur0BcExF8JM5F8rPxFkACJFhDMpFuW1lkjrOhfCVSHZiwv8Z%2Bkk1hOkkFFvdOkcEos6kOItHZswuW5nULFF6wskaaoutZ7QtRALIsm2noteFhIs0UNotA6OW1ZAFYuU/Dwu5F5os5jAoDDF19OjFuYuOFn7POFtW39oPYvRZg4tNFo7OtF5IvbFtW1jR%2BovZFtYumFxiCnF79OzFgIskaRhC4k%2BfKZIcK1fa/fHBU/j7NEkIVscFTVH57otY6/TOIl1soXJcDPnFgEuXF9PbtFtW0kAPYtBJygB3FuEC15zNMJgbNNe2P9ScS30HYQelBcFlbhj8tGxMG3YDO2At67mmAoMmBYvbZtW0mWj4udZwGimSnorjFFzXymwq1bR7ZNfatTWYMgO1XFyItq2tN1dFhnxR59lQ2%2BOlOIudrVRxq23dpqPNN/DHCMIQiD7mrrDR8mWg2k9SicIDEq04JelkyIDaB6z4ueFvwsK%2BX9M/AdkvSlmovOEbmVdFhi6Ow1kvffQ43iDXXC0QYyBbYs6V1EYkuC5/2wzMq9bYQUcC0l/aQslq3lasfDpOlrEuvF7Qs%2BEGTNYEEMv15sMtPC0sB2F%2BaiymyZKeZgdQgsa0vh20kufMzMmHswxO3G7vOC%2BR/ip5ja3Np0uBdFjkuMmSjJyF8osyoj7BP5nR6sPEegE5qpU6kKnEJgLvO04P51i6rrDBwJEkDJXMw3IdE08Q6zxiYIlBcwNfBZjczTfyvSg5AigYa2MzPVOv4nSgSM0xUX3JeltWacoFcvuwZ2V6IBoFOGgMktYPYhdQciDVSCkldJfoUr2SsKPJsKUSp02mVFG4Xipu7NjFSM3vEki3%2BSsWHwll3MiqTUs/JqYCILWXP3ZyiCjABkwTFvovmcEmgt034tW5m3MXF8YuG5iLOYJmtMVJ8jPDDblJD24ith8kxNQ2ppg4xrGN2J801Ox51NuxxIh%2Bp4GMBplTXBpuiv14Szw05r7XBp984mrLZgfKBtMr04A4KNS8vKvdmzVYv8spoMCvuwtQVsG0SvHILx4ypySu35rUvwqo4t5QA41Hi4ABRAQzMLISbMEXaSufKLVTHIcaCY/KJDhZnV2jkOwEl5prqqGaytZ5nPNuA5DTWVhHV1ERhBbxp5M3G9dUY4SRC5BEuiWJijDWJrpMix%2BJPzF/CLnZh1MEp5BINPCPM8ZY/ULIabq2movneVLmOql/Ahmp3hiWppK3hV5bNOpqWPTAf41sV322F5/ygoLSnOs56E2cVlODcVn8p2VlPRIMBysBJ0MHM2FzaRQLrB3FKqwaprlAkWap6QsmXPR6uyBd50DwZl0ksN5nNOGqZvOv2to1%2BitjY1l13BPtJ3Po2xIj%2Bpj7CRQHCpM5xdjWVi5XfloCUAWlw1Aqzo1e2POrwlz6oj0bKuXZ7HKgeSKA5rcSVBxvKD/GyWN0phkzV58rJ957mYPGxBGnFJQVCl%2Bdhzm41j9MZ6Qmqb82X9BIXHWzrMdkpHKz6vRAsVnqtBY%2BbEK/FKXoAZl70q8XXM4F8vQlUDyMISsJN2NcD%2BaoZj6804oHV27l%2BMZ0CpM/tYm0xkXiJBTxzwcQsJqltbOiCjDwli66bYaBkm0y/XOMm7Ns1gWkRwVmySIFt4JJzmtz620vNFgTOrfEExXV/AUC1vRAFViWPQkR6sgmMxSP63rqmAARmUM%2Bi6bMFjH/ZbXgCoDpBkARmshrPDIefQBNAuFpLbAosjgG7b7zIjNBmeJsjuAxH5cJT6p6fW2rx5lwi7Zh4GO1hZw3gzg43Z0616fBaveV/pNS8MeMJxuV54JptoL0JlB%2BUYhMqa242veHyseBPytPCqxMEJlGDBV3JMV5CcA%2BV4pOplspOgYYateAMks30IlBNoC/4dlugtxSiEmkJstM/I/zAtMUQkCV9GtdpiJPR6u7BiV93Ov65SuQVwTCaVhSuJIVxh6VugAt14yuGZvuvYV0xqaVkyvTlCNjVGy6W1G0K2t0%2BhGYmlGiDi/fqvBVvP%2BilTUAUdqNlsy8V/Aa8WhIYqMPisY0am80gtaAcYYWuPk7R2lJVmwbEmly%2BuISsKMcszL7jGuIVmeF6ShxGiXSs64Br1w2nOcKYCzi14IdCxgaUAZ55UkY%2BtN1L7UFkTrEyO7ppikWqUHxk8Wji/fFbMXciHpvNPuTS97P119AxOkmj383sWHAZdn41l60eMFYU8a2JWPRp4Uril6OYgXZ2X1pNpz1nMD%2BpwNNcV06jqA9Ghr4SGOCx5hvhGYqvFgGWNKQCADo0GZrcMnKApQGsjUGMSWMx6iuOxpKsGHGJPepzHDWES%2BsfYa12VIfWNJACdjWERitfa0aMtxnhsWDUNVnLW9W1K92CIS8%2BsqpwqP71oPpeS8iX%2BcaiVXGiRspwDMZVmlrRKN/7B314xCVIV6Uz12ZC1mudZB2QfXkSrTxxKo3jHFhZPFAGSHBY1C0CoeoAJWY84iIPSUbqg4BWFdtAGIOJWX1lSBJK16PvAJRtIOOBmtygbXZ2/OWKyhuWqyheWI8BTBGx%2B%2Bja8UaMM2N1DpNi4I1NnbDa8VqsQxnatfalcVIxruNcNtWBMyrJ6N9AmPw4LptVVqwA9N6HJtof1MU5ugBYsTohphNtBI6x5IaGBYiTNsdjV6JSAnSC0zooS940AKY0P2joq9wJdL1EDfHbAZmyz271Xx6qeq6avSbCbLBlJ4ZSygYGiOTyrgB8AX61oWP3AHUZSC/Ef4iewBGV7ZRt3yN920i29PwYMa71BewB3yZK9DS2im31Nm33wOhjJg2j23SGuoiusChtYSlQGcN4ZuoAUZsOHbuotGX5tL4Cm1toR5IJJS57shK5v%2BaCcMAhuFsbZFDAh2sO1%2B2xFuJx8pjAt8D18eozIQtnm0U2irVXNyDQUitwOQBuFvO2glvSYOlss2kO1DNkLEjN4oDYt/lxRICZt0%2Bm21SGx77ct0mV4h%2B8MLhqlvyG%2BlsZNAKBmK6t3piut0ORsxVPNnu2vNhzmqrMdDIGgEgToMVXw4Tu3Z241svN6QBvN9tgfNy1vfNlc1LANRs0NpiuBQdFsStzFtStxdjd4WnZ9a3TnfV2/6rVqXWjgW1jkqqSDBsDlldYHqSDUE5MDW9aOP1p8yV6uek2RfVUFfK2Lc4K9BpNlFtBAXuDDwR3g3YCBltN5cUkQZ/JwMytsgSkiD8Nyc60N9ZqQMCTS07IsLpeHKO1mge0kV3tuzc3VLJ9VJnaSwBvnBpXFdSwpvTyguWzyxuXNyjWWexXUs8eWLBMAJwDsoBl7vAMiXH/H3XkSxPKr16aukQBk33G2ZL3NAFKJqrTWL5c1mCSvF6vWk6NEstlJz1sonH1tjXKsSM0dFJoBkUQhy3tQHnZYaOI7MR2Gb8tsmGxRRD75mdzuNrIAQ8xk1wgUDsqalCVFkdCW0NiIELESFAQWO9WL69oidERpubLLRtVt4ttj2OAJLNmpsyobdYQSott47awiNNi7DNN7Zt1/Y3BYd%2Bts4d9bB4djojLNwjvLNuFXnWo5vpXU5tRt9MCr62jtQS5AAltiuFGYODskd3sayMx/h8dlcWCdx3jJo7MP%2BKh1vGt6yXOtrkXK2xFtAt6Yggt0l1stsm1o2yTsNtrxB5YK4W0NmFuciwRw4GxFttoEVuCthltt7PTv0d3wgvMClvDhjVuO2v5veFXVs2Rmt0ZijOqGt%2B1s8AAQCKd6OXOtju0emvzvPNwLvVy51ujt0JXjGgJvL133Xr1hE3coKGtOpS439G6fX8gDzWeVhmtH14U3KpKpgONmlCcgAZXN8guKKm/fnz0GsKQMmQr08VHl9MMEBlC/jBOi4%2BvbtkhM3G7%2Bv%2BeH5nFO5agh9PnkhCy9sJdvV6r68RssCwYjXa%2BxO0Vutv8dxCUPrKV3P5Ta1fa4WO3VnEjnikoh%2BtzsklV2bs9AISBsNwiv9auRhmKopv1y4uWlN2dvBm2LvWN%2BLsddqfV7GlLsXGgFF9MScub2yutpIefUiOVDt%2BgapvbNgxA2xmlBSNlmODxu6stacjt3gSjtTN5/KFd5iDLdvkEUAWhutVuFVrnDq6XdwUVyMa7urJpeJXG6ShPdrLuF1ewKlkNPJ5d2msICg6PGJvNvJxz7vod77sPqus74ChxMw6kHtg93QFYq1PAobE2mF62JyONwvXS1%2BHsdEYx6F61WvDDRetxdlHuDd/zwPWqlh761LsPd6gvbAbHvR19dXqd42Npar7t0AH7vKRJjR094HvfdijudEFpvP5UbuFsNk1A9nnvdAOpGVN/jUq92pszlJpgpCwTCa9lzQM93XtUd/XviSlwXc97Ztsd%2B/VAwVrWo/YJNg/DIHj5TxW64E5uQuC3ncdzSDDd6G2u9sbsGM/uMOJsdyQ91Os4kETvtNrCWQG6Hir6sxS09p2Pb7Fnvn6tns0IDns0oLnuixvns0IAXt6NSPs29hX7x9l3uSNiXtG99cLDDKvvkp7/ypCxi2l9uvuONt3ud9r3sz0G3Cg/bmXsd9SM%2Buh1vBynJgEOpW122qzuQtmzsxYNDVOMFlugthB0VULW0i237ul0GPtiM%2BG0A95KtA9kzv4OgVsR24Vsz92ftC1fAXQ9ozuidpzuwtwRwKt7g1z90O2n9s/uhp5/tatw2NJxxfsLe5fvadw20i2rPviSzXsH9hB3wt/bBCt1ztv9xQ0h2tBk/Sfj7s9zVsAtkO0X9mhDS1m/umdsXRcGu20T4U4Av6hAcit4/uu6SAfa22ltED4O2P9kNEWerd2/9tfuct9Xs19ybvADgVuXTY/sQD0gcItr%2BHd9hvuoDjSO39jAfMDoVuEDtgfg2x/tCDqAfkDhfuUD0kXUDqfu0D6vv7AJBB29hgcQB3gegDq4jgD0QdkDjgd/drgeix3lu0R5ztnpPAfsDqOgN9gn5%2B9oftGDoO0ED9MAedr1Bedg1sOII1v%2Bdx1v2MFA2fAELvjt0fvOD8ftuDj1spojSUWOmrACI0cBCIz5iK9qpuU91XvU99X7Z9gDHsYHbBZJh3va90HtO98Hun6q7X59uAeF9lvyc9lAeix7/UAUE3tl9nAfT7c61VGn7w1G2aUN50dvaY59Tf%2BDjBaCn6UkIOTGM67O19S7DmDS4dSayxjbumlTDewQdAO/FLn7oftDmKmodjy/oee8c1vDD0YdF2CyWOY82g6AfJmL0eeA4hT1jCEKwA2Z9qPK0umkO42SErAXI0ZgANDkAn1DKrJ1hO/LaSBukQASAL7LZqn1XzUQQCSjFtD9klQC5GgCwHoHcyjk%2BSDOMK4eSAVzq3D4ArZeXJnPD14cYcj4fnD5xhfAfgBeoEpmL2XCFqgR53ooKNt7Dl4cByt4eqcz4dlmd4hcAAFb84WYfYDdlCIjm63Aj1Eegj8P2lmZxjWY3EeexKcAPD/JkeMSLzzUYkcqYNEdgj8kd5ML1CfszEd/Dx5l3Dq9seMZoC64JkfWYYzmiAUzn8AWQC%2BocOUG9OYcNwT%2BK5UfKi7cpcuPDlEVpYrk2UAcVKxofYB8IE5T841d0ojlTDbmPzkCAdUeOIOuzSjjQBFMvphfKu6U9i7blMoY9aDNRsi6jnI0Byw0e1WALuM40thQj%2BQAWd80djyuUfSKxUd5MjSa0y/d5cmvTnnkJ1iuabUdvAZ0eiY10fWrd0fB0k5ZOsP4cWj3IWMdeUf1UQ%2BrKj0MetE8MeWIJc39Kmg2h0WMfIj3I1ujk4d%2BqXgDg0NMf%2BjolDWjmuo9ip2waOydOXtuMc3wCseJjk4cOsOLSmkWYfpj2UcNjtMnxAay4XkDgC%2B8HqP6TPUddjo0f8Acce%2B8P4faY883bAS5kvc8%2B0mOzug9ioUdyME5YyQKgFPEJcdjylceNwUEu5gNSxEoM%2B2pMzccWAbcczjgOV7jgQCrSStgdoI8dFMk8eXMhhuCWLizrj68cA5CEC3j6y47j7Hbqjp8deqS1YdwTXGqyt8fzDr1WfjkACZMEID9oC1DyU74hvER7RXjt7n/jrcdAT%2B8cqYR8cHjzuCIT5Cf2IVCfUcj5swThuAfjs8c0Ezi6YTw7HYTwCeUEYCcETt3ga4rXEcASiezROCdnjiiwxxeic3cgCfmgXCcuj/CegTwidtwZxx2Dm4fLjnidLIK/F6TGQBpmN1iJAXtS/jrCdMIISd3j0SfWYVideqMxC22cdSKcm1Y5W7gB1jy0fDj82icynwk0sh%2BACoCeB71O7EC8sqMA88scPj8SeCAWQCI8B1jyAGYfUjmUd8yqRUKj%2B0Lm0jOw8gBlWJQAGVO9A0XBj3UE6T3cfiTlLks4CxAs68yJTgWSeROzwlVC3c1O9Re1fcp3noY6JsRQY/gsTxKcdyygP%2BTwcdx8/pUcyprA2TjWzwIengZ6qnhmUQsQ/sO8DBAGAvTffolEof6hWTrUBuQCM0kvPsl4T3SfiT4CwAWIQC8AaESewFxwDj%2BsepPfqc7FeqeImxiBNTo9otTgyjwSfOuGALqeACvph9T2qfaAQadTAYaduTsSf7jiaeXD2BbGkEIBzTyqcLTmqfjAayd8Vr2yNTyPIbTnnhbT1pTPgTqc5unqcMJJacnTkNUjT%2BKcgTy6ee8a6eVcWafmT3IWWTo6dHG69rvTxdQWq/SiFiJLG/AUpB3gf6dSs3qdbFAafZQIac200Gfxji6cgWSGdCAT4A%2BTrGewzoceLThGcrTnWxXAFGfE4L6fozveoc%2BpwjdT3GeAzo6fAzs6elTiGeTTtnXUz3jEPTiyf0z56d1T16fg%2BNacfTssWtTzQAYzyLaVcHGdasw6dSz46eEz06fEz86djToWeXDqmdfES8Pghv0cSzp6cvT0KWrT5mfNTtmeYSRSZqzhhwazzmVEz0Y3ZQQWfkzyaefEbXGBkeafmz/GfLTmWcNTuWcszp9YGUP2AOI9qeOzg6cBz/me6zj2c52yaeA0T2Dec/sPizuGeSzy2dIzkOe2ztGcRz7afRzvGdAz7WcgzvWcJTg2fmKlOc3T2mfVTgOeIzt6c5zz6d5z4IBcwVWfcz9WexzkucCz0aflzz2eBu5OchAbzmVcGudtQuueMz5Ge5z1qcRzywDQiQue8zzWdxzqRMJzq6eVziznTTyyMT5AKejzpaf1z2Wc2zpudTzje3ZcOefOzgmeTYV2ckzzsfuTiucDzs%2BYjzq0djzoOfWz9acKz8Ocb2tuf7Toud8zrufxznufgzvuerzn1DDzv2cZzi2fSzq2dMzl%2Beoz1qczzjqe7Tk%2Bedz8%2Bc6zped/zgicrzn1AzTu6f3z%2BGeaz3efBz/eevzsDhDiHad7ToVlfzhec/zlBdgztBcUzs%2BYwzkBd0zsBeBziBcTzg%2BcGUSwCS/eBftzp2eILyvzILy%2BdDAXI00LyadAL58D0L9OeMLx%2BcsLxueEL3RBg1YSAIL4udIL0ufLzimch0jNNQj7BeZz8BfZzghfQLgyi8IG/FxARRffz5Rfdz6hfjTtReOc2i7bmLRdMLvBfPz%2BWf6L4dgf0SUaSUCq44F7hcxzpRd8LlReoLyxeTTqxg/D3EVdocQBXkBhe1znefjzmRfOLqxiLDl%2BDv0dYAsgMAteLr%2BduQF2f8Lsuf/zxOeBuoJdiAPlY9wUJcXkY0YRL7ecMzp%2BeQLpxesztGdxLtxcZADxecDExfpLprAXzrJfCL3JdCAfJchLgCzFLkpcSLyJflLiBeBUcwD4SJSZGYZyf/c%2BDLLz8QBRANgDvEe6fuEqqdlL3BeMz9pa11JyfjYFydTL/xf7j7cyP4AzF%2BTxZePTkKf788XFRT8ksGUY5jGUa9UaBHYU2K02z9YBOc5MANC2MJzm7UECx9jhDmZcuxcnLjnE/jzrE0sy5ecDX2LcZW5cDd%2B5dYTNpfiT55doWQM34cj5fEczczBoH5cnjt7GNEc5eAruYByKwI0CoMFeRi%2BagQrs2xQr/ccwr15es695eO/L4Cs6ljlyAe%2BeZjwMe/LxuCfAKJBRQAOJdQdFlorzi4%2B5QSc4T5ic7LgQB44VTmVsMOx0r7LxZj2QtwT5lfOO6bFoAedKcr5dDcrm8fCTqPUhwNyBvYryAEYYwDXchOeCr1LnEYqEdGYlFeDL69pWFemwbLv7lEUgRf7D6%2BcM4ncyWehZdmz0BdSLk1cGUQsAQgMwDHzqBMCTzKrmgc/MerwjhWr/Uf6zgQD0WJWU%2B4HOJizo5f%2BzqJcVL1qdVkAdSer9SdDMH1fxrl6Q1aQNdCL8SfbyoPAAkcQCRrx1eSLmNdDLxJ3GAY5jAARNfer7OxVkMtfpr4lchr1nWB4S3DiAftD5rzedLLh%2BdFrl1d%2BiZuwVrxKDn2lNc9rgNd1r1KdsAWSAKAPD1mjttfHLztcXLuYDAAQoC9r17nJr7OzzrnAC1rhOf0WftCP4Vte4Q9tf0r4Kfm0epaCU3h32TG2AaOp4f8r1KfcU%2BQBGrlZexrgyj8QIgCLr/teCTRtDrry9f0WNDkcAHdcs46dfGr2devwBAAcA34CGFpNcW0QSZK0YDdmAIE0br6lfHLI5YQi29dZz2dcUAInBkwZ9epMn1eob4aDmAd9cWL/cf0WPgCyQbjl5ryde7rv9d3r4tdzAE%2B0jQfRi6FsDc%2Brmjd0bmDcfr1nXWY/tB2sKSc3D9tc4L5DeYrrbHeYvHEaBStf3LJLHOwYbAsb/Df1rwQDkqu1jjoL3hIbnRezrxtkYb/lg%2BrlTdDr2DdNwO%2BelLjtf/rzFeNs3piqb5dfIIZoDhAPDekz4NepTtefNsH9dbzvTeUbrtcOjroDPgYTd9rzDfZ2ZzfIAeNAZrm1epTsTmjrqL2Kb5hddr1iALFYzfgb/EbhbzTesbtnUe8OLR2bnjfaLkLezr1iDmAPeqgbkTdpbjLeSbyze9z1Kd6c8QA%2BT0QDBbhxdoz0QJubpdeRb0QK5bq%2BdkzgrefAG9e6b3jdKbzFeUCiLc%2Br9rcxbqTepTk1CyQRLcUbvjdgCgyjaAcSD0bkTejb4s6%2Bb%2Brf0WYQBiAbjeDb1rfDbuYCeYxtCVbl9fpbjICNoWreCLvzf0WbjHB4UrerLgyieYzXP0wdbcebzbc8gPmD0wHbfWrmbes67jGNb5uB9LqNdOrmdeYr7zE5cDrfZ2L7eczu7dBr/Lf7bz4Dfbsje/r6Nf6b5bflBC7dqb7OzlBAHeZrgjes6i8isKt7eyj/dfZjmdcZQ3qQZkGOjDrrgBxaEIAO/BTkhAUVfjFBldY7486EIX6s64zznWrLuCUACVIJzgnfem74gZiw0cM7uzHNb5Ldlb23ht481eC81yfM7n2djrw5cFrgZeOb8kvDwbbmHML5AEAfibzwWXeJlAXdbL/HLM7xnFkApSA%2BjruAa7%2BQBa7h34OrqdcQ7yXe2T2Wl8QJXfy77bkjQKKAq7yZdq7y9fWY0QCa77XeO7u1h44MXdG797eQ77BAy7wLCJlWeB%2B7qqjNoHzF%2BYCZeWr/He67/XfKrPXc%2BjtVZGYg5aG78jfG7obc%2B783eB7gPdfIbNgh7q9Bh7qGDTbqzeO753cO/Z3fwyhPdk7oKeY7/9fkqkYfewHcwOsZxbM7z4A175SAecpnG6bjHcSryXfV7s5YtwUUfWreLSN7kYcdoBSAZ1X3Ajzmde540QASpSWldYTCdVs0si573ID57/LffEQGjSTv4d8l/oqr76SfWMVC49wD3gvmOjUJz7fe%2BoaxAvmTtD77nuUyY/pfLLlPc7wCmx0IUPebLu3fL77Jc04nuBtwRPfg7r3cm7sAXeywJHjL5/fh7hOfv7ztBf7%2BzctblLem7upaJQW3fAHy9c04%2Biwe7pPc/7u/etTuRcWMBRcjZy9uv7gifqLsOWaL7nf2L1Zf%2BInlDZ74/kWrvPfDr34hBm5A/f7wtfe7%2B/cM1v7GL77Zc9bmg9ej8A97rsVcU7yVeu40vEvSCABEbwzHEbjTZKr7Sd5bt/ea43NcZi3nVEH51dS7nBCcWOyDH1OwBwHqg8gHzXE%2B8UPCFy%2BZfl78Vey0E8dswbQDH8KKCB5KRU/jxVeMT5VeTdBA9aHvHAlsb2CcT%2BQ8fbv/dKHgRAjAAdTqHoXd2Hg5aZMGQ9cHxbdQHtw/qrn0zeHtg%2BSHvA9aHyxA%2BobpmBH5PdLb2ezKH1xDhH%2B3fsH6I99oT/dHb2NfrYZQ9mrlg9AHjQ%2B%2BHmQDKe%2BI%2BwToMbjYGKAnnQw%2BhkuMstIXA/iTqSen74bVE7sfcuHxg/fY3BCpHho/7jgyc04ug9bzk8fYrsnlHnf2C2K/rBirr0s9HgQCcj6lcxcoOmwrt5c%2BWG/dJdrTxLFG8zFAasmr2%2BpYOGrPpStgLHZfM9dd0dScJUV/d8reSmCAAFagWLReOpOAnSA3bHQ5HQDpIMl5dAck1I1KYXB0bnH/tltAdFAuJULyQ82IL3hYqTpfIT3gBIr6/do74ZWZs5%2BCy0Kpjntg0ufH5wCv7wE/LmQdBnLG1Y3H6E/5vLEilkJEfwnhajDYCczInpczAnjg/9oTE%2BVYhuAGHumWlZOE8lkj4%2BEnpE9ZLlE/AnnHDWrDaQUnqQUEkOXHldhk/jmJk/ATlk9onwdacnvE/0nhE%2BMntI8Ankk9on8Ee%2Bz/ydO0UvlJdlkAjYS9qiK8dl0qplBzwSsJ8DaXVeYjse7blTDmoexAHLa4/c74aD3IUmu8H/cU0EZC1cmmdwMS/TgEYA1WHRu3rBdOEDHS%2BVfInpo9KyrtB2D1tj8AHEc9wI0f6H60/SUX3gFYz4nzS8ul0wIwAzuYCe%2B8NuC%2B8GxBmoZuUEi1VaB4Bev0HwKfUnk8cc8z1gRn%2BV6QgAupF1PqxZLxM/8AZM%2BnLMpvpnx3cE70M8Hrr1WFn/xgln7LzVY/U/lnpM8pnms%2Bsi5TGh4H03nd8Xf7i3M9NnyM/Fn5dnZeRxD78Ts%2BVn7s9pn3s9TntKf2bjveGHuRjNnjYDp0G82GxPm4Jnn4iZHrpmkK/tA9wbI8QLgzEKQAa2sHlICv74hXmK0/elmW9cYH2OjooQd6nPa8%2BOc%2BGVQj9NZmoBs/Zj3prKjo4nzWE4nwp8uihYA0/3b6zAcUv1DOHlY8rn%2B0Iks4giXso7Gjj44/ATjimB4J35YqcfdyMWEmA5faUH51U/nOhail81C/%2BoITmtwIPCLmC1CDnz3dUT5XE6AWo/Rmp9s/HlqVZTstkkXkCwiAai8oH9Hc8H4KeMs69rHrnYl%2BxI3IZ69i%2BcU69c/ngxr8XkIg8gFhBCXksWnRxkd/zjilyUhSljoJSlYX8YCJnnFa7mKM3kvJi/DEjElsX5S/%2BobS%2BCrb%2ByzDsgG2AeQB6X2k%2BH/QenHH82hiYlYr6J4i3esUlgdpyNQuR%2BsnzS0C%2BDTxsvBUi%2BhiX53cjznK0sACi6ijvZe6H2/ct8jx11RiVD7H8n6vCvShU9Q/w2QQ5QQYETx4%2BeychCmUW0pV4BKeVdDFAFckTJRre2INgBTrUxNKefbXj0QNcB48MWHDphUnDgyfnD/uU/D25uiWeq%2BtCoJeij7Q/7L94io75SzaYsK8RXwdA6H0zFjhvn6NWoPufMbxXroAOUjXoQCRX8a/BK7xXIUrjETocK9LXsa/9X4xUxdk8nTX6Ud4hHsWj/WaLsobeDw5cgXBYbDCPaCVJlINSCA854fzX5P6fEWSDcYqeUCAHTRf2XXFewKmy8y3UivX968cUr6%2BGTnuC/XszGTqw6%2BbzjZuneH0Lvc91JOGbpLndUrv%2BeWa2BTsVfCoCKDGQV/f2MCQACAcMiWINuBSOUpf%2BcU69EUhoHzUBh2OIfTjDUXJ1JwIsnAT4bUDoRA143ri89DloduwCYeDD5SDTDw3d86xhHGLF8CEpaj1CEr8ahDsQmfkmxbcs7CayE1CnOLBQnyInCmFivCl4YmiZqI6pPaExiakU7RHAKwwmUY4wlGImjEmIsxFmEqwm9O/2UqYL%2ByB4QpeNrmxBE3rycdwamcLL0P1W3kIA23jczUizyfeT42eA0HqHW/DeUQAAidDD3q%2BA0MVXi0oHHHIOyD6YZwAeIAagR3%2BexBIvwcuIkJEBI%2BYiJ3kezK4zHmB3jycO3o2e%2BT0O/M0keA5X5WefYnSnA4vjEB3qxhNXlhWZmf2/ZyrO9KzjmdmUlNHXXluDjACVJG2SyCeY7mhlWO85uAq4oi81FCLrByLKzrGeZfX0vcTwXZRCuWYq4o2hdQFud2XKKdhi1oWcoXXBfCt4/WTYZ6dJVzLSzENW5E26OC7HcBKwIEnqcyslYCnNhBgfe/SrynmrJJSimUIOyP6rSwGqwdkaUdWlEXqi38O7iAUO8Wn1LbDd2QFuDMmg4AhAU%2BLzLdO/A%2Bxu%2BYz6ETcnG6%2BfAPerY8KB%2BsLUX0QPyLYtzDjQtwWB%2B/ABZ7g6RB%2Bh%2B5B8mz6B/oPuB%2BxZRB%2BQ3uRiMIeu9Dk8Yij35u8lLH34MXGcWt3269BOR08sALu8ZAUdvm0dpeUz6mfDBjM5kVxzFV2aESuuah%2Bf0wR93gfZiIP8Ts/MBk7JJRerYIvARsEd%2B4O5A69kP92BcPkWdfEXh9lwjh/5blecaP3yedOPh8GmhuCRTPB8tzSKaSPjyn3XbATFTcsT0A4QC/VJipsJU9NQAGx/wpTyQViKDgOPr3z2JM6ageVx%2BLTcpB2PuYDePm3C%2BP2sgBPqFIV8csShPn5LxoJUIqP9LzqPvO%2BGP7R8Z37Jd6PvO8mzw/HGP/yWBFPB%2BBJRcqWPr9DCFSJ9b1BgEMAmE%2BOPt8opRr5guPmR%2BGzDx8VP1DhVPr3zl8MZz1Ptx/XJIJ%2BePip%2BtP3MoKqlm3YIhp/FTegHBP%2BgH9P7ipvXTYidPwJ/RP3p9QcSZ%2BKPjp/DPrp84JCp/jPuYBLP0%2BWDPjAhCbEZ/uP5p9NPrZ%2BcDJYLtPrOizPqJ9HPnp/bPnnAilBJ9l3pJ8BLw2c%2BT5C5pP2h8M6xhCB4qu/HDmu82Ejm9Mm22zW3wDoe3%2B2/e3/O%2BTMkDGPkphFC3s0Qi3/hFvkkIeiEj8nwUiQmIYmW8oUvCby32tlKEswm4UtQn4UtW%2BEYzW8kYsim63ijEGIg2/UY5Qm0Yk28Z2M2%2BudC2/WYV2/u37OLUiqK8HL52%2B4hll8gvtl82Sla8e7/2%2BB4oO883kO9h3pZbx3qO9qpWO9MAeO%2Bl3uTHiUnofh3rHxgIPnGOTsB%2BF3h/cM0qpCZ3yh8ETjl/zL8V/XY1Q9jLz2Xpk3V8rFbO/7j9id9X3Q/mKo18y09Vcmv%2BV8ryvjF%2Bb4O8jD%2B6eMIO1gNNNTSxvDw2cDI862Xw1Lx3h6U3UPTABXq426TV8Wb4sRGQz1%2B9cYK4q6BFi/OWDUUhwaljysXY9TG7iCRxHNDn8sqNUOHpXxL%2BR0WHxohT64t/HtHyUFXtxZFiRF8l4N2zUCJRW05Byz7t/JtyMfOftT7j1cPgeepz8MJJ30lV6Extlpz0X3dvz2AYLvt%2BkPtt%2BZfaESdTrt/PPqaeYLpGhjh/a9jt6zCwL2d8oerh/jv2acQ3%2BnX0KnV8qYDt%2BRr0P2jvwec3T3d%2Bry6a%2Bj4w99Hz6iNjy099nzC98qPqd/bTjd/A%2B9R83Tnd/LvleXXvtd/ELt98jv%2Bd90Lu6dPvsu86Pm9%2BRz4Bfvv%2Bd89v3gCH7b99ry39/tv9%2Bfghk98wfsd9wftWwIfq9%2BrvuRitz36e7Tud8VzoediLkD/Yf4HFIfngKcLvOCbvoD%2BYfr9/9v0h9PP/ccevwV%2BSUyh%2BLX9OoGv2u8Dk09%2B9vnJ9R/I1N5PjGBCP9Yotz9qffuUT9SC1IDQiXULUdiWG/mWT%2B1eZR%2BPPxhB8f9ec6PjJ8Uz2%2BfrzgT%2Br6sR/7MaecSfgz%2B20mT/tyKMI6/R/h4PqB8o3rGdyf3VyJPtT/oftefDviu8fvxd96foT%2BEOfYBSfrmAzv3aeSf8R94%2BY5C6QWup2fiz%2BgsN3ClSUL9uxd%2BhKf%2BTgqfgF9af4Wfrz8Rfryrd%2BpfkD9GPwT%2BHfEz88Bfz8iqPL9k8l6SpMML/xfpnu3zER80u/2AuWE1/hfn/gOf1T9qPuj%2BLvzT/qf1J8QVfh8mPtGaDv7acPhTRK2frSQRfqR%2BAoQb8ppBL8S%2BRz/Nfm%2BdVz1tf%2B3h9/nv7L/6fnr9Gf8x8rf38xDfhr%2Bn5Kz%2Bj3luZjf%2Bz8kdKb/Jf/ucYfub%2B8f%2Bd/ec7Lg7vpb9ef0x//vgL%2BmPkL91fzb8VfrfHRf57/jfzKkBEI78fvq79YL9J8Zfv79I0G7%2B5fnr%2BWAbLidT/r%2BLXCSi1fsL8vf%2BT/RIXb/g6Yr%2Bw/2L%2Bczg7%2BJfz5/TfgBfAfvm/nfmb9nvt5%2Bdf3J/efzoFifyD/5JRcq2f0CTDfjynU//cTKfyb9Nf47%2Brzkj9tf5z%2BiLzz%2Bg/sn%2BDvjheU/wIr0/%2Bz/bfn5gFP/JKC/%2B/iHf5n8LfqD/pfi7/0frL/vP5b88//D%2BQ/xcrvfsL80/rb%2BWfkX9PfjX8M/ib%2BJjH79y/6Gf/fzOUs/0RfXfxX%2B3fwIp8/1X82/mH%2BlftH%2Ba/17/pU0X/Vfkr8xf3ogmzjH9M/pL8Zfk394/mcnB992Ccf5a%2B7XgH/Of/j8g/gR8%2BfoL%2B9f4z%2Bx/wz%2BKf8z9a/yL87fpu%2Bf02z/lfh59%2B/yP8afiP8E/8d9c/mP8ifuP9GfqB95frP8p/l38DDKv9o1SX%2B5/wv/5/s3/ufu8CW/4n85fkv/IAXz/tTu3%2Bl/11y6/tH/Z/iQ4i/qr/q/of/V/nP9Y/ln%2B9vtL9uflr9t/hX8d/pX/d/uP/rvh7%2BJ//BM1fx39e/4f/C/wFAo/nf92Aer9ffqA1S/hf9z/nV8s/2D8df7xwk/yKZHv8HQP/jb%2BffhH9mP8HT7fiX%2BY/p9DMfgBc3/ydfzfhz%2Bi35W/tz%2B9ryGfre%2BUP6mftFA8P4j/qN%2BL/71/t/%2B5tBOfk3%2BZ35K4jP%2Bn75L/nf%2Bnf7dfl68mXwQ/hv%2BuAHj/l7%2BMAH7/iIsSP7G6J7%2Bx/4wAQ3%2B0/6/frdOgf6cPnR%2BQP7F/jgBYAGb7Pd%2BhX5g/g7%2BlAHv0CQB2v4H/twBH34IAb7%2BtAFMAfQB7P4E/iR%2BLAHCfn0C5P74ft%2B4bWji/qn%2BI35kARzOgSRKAadmzfxG/pIBmH4SAX/%2BGH5E/lgBK/6KASh%2BCgEHuBoBCP4aAY1%2Bjf76AWvOMv7z/sR%2B8v7A/iABXf5taCr%2BBAGyAUjoPAHe/rT%2BlX5qAfkkRAHH/s7%2BU/4//sgBAC4kfpf%2BgAEVzhb%2BmAH%2BuPf%2BNv4/Tn3%2BngGH/t4BwQGwAcbgKQF1fs7%2B1gGiAdEBTgHRdtP%2Bof47Xroe/z7T/jy%2Bqqx8vra%2BnL6YpDUBdCK1AbwS0L6C3tK8ZoiXxKLe2tji3ii%2B%2BixUqtLeUiKy3li%2B8hI4vuRMyt4EvqreBGJ0TCS%2BuhJ5OnrelL5UUobeNL7G3vRi1hJF2Ey%2BcjDlAaOu46764GqseTBcvtpiawFjrt8QmwHB4NsBmn7CvolOor6evg6%2BNSySvtHejEAtAHHeUwA5AAnerSwKvj4itsp80qnej%2B7S0u8BPKDavtpSyr7E8ioe6y4avikgm/5WxglYq%2BrcLOO%2BFNzhbAkEVjQhFKCBDwyHYCUirNhQAODEF2BRpjN8kWjGPOv%2BIqjH3PfMPX6Zxod8kIE3TtCBtdoGHCFcy5Q9foiBuIDIgQywwNqW1DtgGIH0/EgcHlLg/iQu3JwpzDz%2BhIGOYsSBsfyLpoKicIHQNEU%2BseC0gaiBs5x3gEyBDpJKPm%2Bktv4BfniBEMJNMNyBDcBQLAcAUIGhVMyBeX7FPlLU/f4eaAsg5f6f0vKBHFzsOCiBzIH0gVAE39RYgf5SykRKgdsAKoEwLOY%2Bq%2BwagVSBP8y4AT10RZCrftg%2BrjCigaaBaIE8OOsc05TUGDaB9rCNzKIuvKKwgSVQRT4ugZ4BboFRIEZ%2BgSSGgUiBqJClIj6B4oFggCig0oGR/JFMQYHcLJd%2B4Oj2wmSB4YFRgU3E1IFwgKKBZoFW1JKBJVDynAMMr75ygU9UgRTZgeNgJH6kgZWi5IGCgYwUgRQlgcUiSYEogeWBjIF1fCVQGYGu/okBdYFWgYqBFuqHfHaBuYFhgZiBpP5sAUfwRYGaJDGB8f6oPl6BPYGcOA6SfYEc1P6BY4FhNg3qXn5TgZh%2BM4FOgTz%2BWoEhVIEUy4EdvvGBa4HGgRuBJVBbgX6Bvj47tFOAU%2BTTPPvyGUKr9CTkongdIClerRIyPtxUi2RlwhbQNWCH7CeOmWAc2Kv0a/yjgMfwGN7/Hv%2B0DYETgY5idMCyjI70ZgESPgwS%2BP4ALnkuEgDdLmEufS60tLoYJhRWvKyER0ReJG7geAhwpCEkhEFzZLQ4BWi1LhYA7i5JLqY0HGilgEnq335gfg4BWEGdLjhBNt54QfhBa6wkQTRBTKASFMRB2tRoQeZmdoTkQdaUVEGCQZMEZbxVOtcY9EEJLg0uzEGTnGxBZ/6hKqsCSUKDAug8lTIlVHgIEYxFkCmEdRDIaDfcGNTpUoNSxYTs3mUBQL5u3oB0%2BwF7UI2u8GB6HnUBrkENAWBSPCIsIvIsbCJKLDfaUL4eQQISr5LCEki%2BwiLAUl0BCFLi8khi0iJyEnIiWGJK3p4sSiKjAYRSRGJa3sEsZL5kYtMBSdhUvqYSfEy0UsoSDL7LAaPiAcrlAZ8AfgKZcqEuvqBjoAIAOwFjyiVBZUHBoBVBZ57VQX7ebsrgbG5K4cDAgVikG2ihYgw4S7xRJrlcEUAcqvvysUrPoEVc4FzeNL0mlpJt4taSdgC2kk0w9pKD4jF8npKlAaEBgL7SAMC%2BwdL1Qe2w%2BmJVQYK%2BczJgYmeMr4wFCALYN5KKLHeSe4qPjKwSz5Ktem0B75JhQWFqkhIPLhi%2BjixoUmhisUHYUni%2BwwHdioS%2BYwHqIsRSOhLa3kAqGUEUvllBswHUvmYStL6LAebeRUGW3rZBhS5emq0e3zZl7ih65QEIwagaE6DIwcneDdheAI9aYCAPALNBSiC7AC1BXsqy0r8AjsqvYswe5MGOvq4SXwE9LKkisI5Kvkss/SCS0uAgZtjP8CvAMJzXwH8BTMG1ICzBUwAzABMgLfy/EtOYhYCDUNX0cSp9MDw64kK5YlTwO%2BIfKISAdqSOnsrOoSDGQGFGbeILUGP8hXhP/LOApBLgXDviOkzJcIaobNJfFCpo0oBG0BOYr95vAHpQ0joxTnLBCybOxLP8ClhdOqSa%2BUJ9MFAqMBLmkocaHRRzwHbBasy9dp9y3K5uwT7BHsF2aH8SQxKP6k%2BYFAAxYinAcWKy0MfUWp68OqJ4e9S7Yu6eU4DKOrrggDZ%2BShXSPXhHRmTA2JLq2AMqZdLVCgMK4cQNJp3S6sH6wWrMPDrFEvbQQQpR2nLiWsFsdKJQjcDv1sUSpAARID7qU0YawQva3gp3HnvSfTA74ogKGMDBkm162Xh28gdKgQ7vWrOAIrIOstuyJdRpYhNBH7bkWqpQhjBy4g0CI2Jv1ulC3GpNQtTwDcGXCrjBDUIM8HNG8TZQmiiSevDpEMJBOABKeLvGD9yz/GtARqhICh0U0fRn1qao3YJ5XDSQd5xawTzkIaJxKp3iqTZl0vgS6AAYEqgAxBK5NsSq1TIX4gTiQCGEElYAyrQG1n58ceJ%2B0JOciCEYOCghTUzNakfCs6q%2BXg3ASXikAFwEuwpwVs1iEdYyQj7qWVjSAmvgjyQ5DGghoKQu%2BI3i48QBWhgO6iD0OEWyePjYWroEYPj3SNC4TuJ4IX44USAXJIjmpjA84gFawdY4MoAhwCFwIS5WeQJklEj26KAOsmvBPXZzLNxCKTDRsjjKdPB44kPBsrxxnMpE/WKACM4AydLTxoYcT%2BJIIYXGYLDoBHx4ojCDwbfictJ6QBqileTGITtC9hCluEM0htbIhFlY24yYCkEK0wpwxlYY/iBDmMiYYWwuIZGYvlAyQodI%2B1JwEvm4ceI8IU4hF9iDfM2gwSGXspYkYSED4kci9CEM2hEh3CEtAOGcX8LzMLLiISGVvAbA8SFigjyeeug0wIUh1oQhIRwc1CEMgoDQJECe5JsMydbFAILsKaCdYCDkPtC5rHLieSaZODjwzSG1IYKQmMKdPF3EI0CnYpAh3cHrMDBCoGBywRfAPeIYAICKXiFRxojGHSHmwYIhu6y0QrCALSF1IXnQaJD5PHLioWjpZjj8wf6S4DJCTtgyzHLMdsFHqNMAqiEaIeKQ2PyhgvT4piIAIH7kWuYpAsZBDmTX5qdC/ELSIa0asiHPPPIhRxKKIYakyiFMzpchg8G1wZoha%2BpGoNASw2C6IeyAfeINvCLi9iF%2Bxtc63wTmITpAliEwEtYhCYG9OHMMCKEigo4h/iHOIX58J9huISmgMyGeIUOA3iEb7L4hDJgBIX58QSHFIXioSSEMyt3B6ZhcBNEhYDixIaOYeSFZlESh4SG4BEzMaSFdlhkhrKHImJD8LiH0oa7iZsBlIRaEeSE36KUhcuLlIQkhlSF0Iamcr1bY7L0h5WDKcMImjSGVhD0hh4p9Ie0hE5gJJo8klYTu6OshfSEbtGrWNwCQ1PPSkKEjYLeWW2BpYscht0hnIRjWUlxTJBLgoKEFvhFsE5h4Wlxg0swH5nSUYjrdwV7B/kq2oex85eACTA8hF/T%2BWuaMN2Z9OPcha8CPIdxsZcKr5gi8BvDndNH0MkL4Yk46%2B7w8Orm%2BgxQUEhT8wFSuZu7AP%2BLqITye%2BPYHnBAuoKGFXGahUtB4/JMh3QBloVycpKEk0HMh1cbDwAshhqFLIfLi/6y3IXCAdaEp0Mw07ICy7CCYGWatlsI26XjghJSmmzZyML7B8iH%2BcG7EM6ZrtsCiBzi5JIWh3uLIQUQUJiGsGiihVR65YlYhbMEMmG7gg6G50BbW2rYggPKyqyoQIRQS6KCTIb3c2SBswRhs8tKvZLkhyyFsgD2hLKFZIWKM7cGneDyeH6ZkIf3Bl47qIaChCmB4kCpgLpJkwQx2htYG6n5gNSF6oVLQ6BDwYa0hr1CnoUY2TBKG9LOALcBLFMlCNMCY9OrBPJ474mkg1LxEYfUKm%2BRVTvvmU1AEABf8ZdJuwTx47%2By1vkyg/nBLwE1SReqoinvkPORxKrrBwLDkEqhuVDZvRh6gTuT9YmNB/LBrwetaD%2BLhIaWQsBwsIcgKGGwvwIHytYpnLjyeeyokYLaCr9Az4tYQpZpwEr58i1wr4qnUTuTNoSNg3VzdwTjyoGASYckhUmH5Ers23YpyYWXAW7JeqvKuwaEqYc9gamH4RIZhK8YGIY/iQ%2BJ6YevGaU7awUzyfXbBAFGWtGHhYpgAGxKvrJTwc6EjIQrB0Jp/1srB9hxqwQdiJmHKSjVgPZLsPuR0CWBxNiQQzTAiOKZh/mFNirNEN7bX/F6qrcDxaFlh/WDGYRm2evD/iveg6Rg2OHnQlKw4YpvksbZsAArwqSJNmvYyRWHeimcmfpIa1lAipKDl1Cuy6sGN0uVhN7KewT2aUJ6hoW/AwwpY3luyID6zoWCBS9rOrDZCm3ZXFDZORdb0YTlcp5bkdGIhMCE7/Nti2wB6QGWehxSiEvhiRFpq8qVhIeTnRpMAmgDy8qqOsb7TwVDkwYB9YTVgztjuofUeNbLXFDHEVPBI1kygu2E4EiBc8IrLlhlhAzT3cMth9MLcxlhqFFp75ud0iLBa8LH0v8GQIegSe2HltlkquOIbodgS0OLEEsPA3GHt4hOYf8FuEtWgeTbO7Hzc/2HQ4h9g37bo5pIhBbD5IOFYZYz5PGThxOL1mopOZOJJuujh%2BOLI4QDhXeKmXCv0lOE1FMehoIyM4ZfiyOKk0kFsl6FdsgbGh2BC4d3wo5A6ak0wPOHokHzh%2BTzU4Z1mWMDFElJ8ex77gQdhj9qZQFpgmADxEg/Gc8FQavZMSGwQ4WeWKcHK8ONGeV4XdD4aOLLwilsAfEBZohDhTCAO2IDhstBG4WL2%2BY4PYR1a55Z%2BksIi3kJG8EUAX7ZmihfBkWHM5KGh1b6%2B5LxMPRBq0ifyVxQavObhPhLG0nzcDuHg4ayAzU7zYQNWXUABllCKD8YsbOlhrlbuwNLhyrQK8AcK02DMTGTAv/ib3uLKbfglkipozsQAymKQPIDwls1o0uFVhDdGJGjS4UjiUcQ3RjQId4A94aLh/JwQqmdo0uFTgCLhMwDU1HzcmOKMgKzhjuHY4rygvmGJLEHYwDZSfI0h%2B7yVwdZ4APjr1j7qXMC7kHLiJb4JYnIwxmHGGt2kub4D0rv8htInYaFBJPBCwJsmJepK9gDGD6o7qn7kd5yDXKvhNWCZNpiAw6yjYbTQ5eq7uLqWnwBxtpfEkipNpDVht5jl0vfK1GBgYVZgRiZaED/h1Mb5%2BNjQ4GHWYOwwe9jhrIbWsPIb7DZa6BDONqgRQYAIsGIq59aRrFpq2rxEEVSQOBHIEdWa82qZYS9hPaRNJiZwe9j0cCBmmqbMEUuQhqC4Ee9qNBHv4XQRowCyFIwRInCz4qwRhhpc7EIRSBEwEbDql2AvwSDWYhFxYLY6Ler/YLPiUhGD4UUkHBHUEXARtBGLwLwRDBFBgPRwShGzIHoR4TRuwKoRGupcEfNGsdD0EY1Q/BFqOIoR6FqcJi1KXOwGETIRKmB4Ea0AwlqdMMQRkuocsB4RqLhPYW/hZhHd8EGMLlKttjbkL%2BEYAH4RrGKkEMOEvhHwERXEqMoGMGW0e9jOoMERFTaf9uwws8KbLLeg0RG0EV2EWRHcEV4g6RGtRNsSwXgJEbDCC8wYIWmEqJa5Ef4RfYDFEckRH/bvOuT2BJDyUrhgqcaV6hgAhAwnaoDwlBHZXGER8BHDwM0R4qBGYO8S4CQQnNIAD%2BJ9YZdqIuLa/CrGwZYJBNm4qpZkYH0RHWFqOOVhQhi2IREg7uj19Db4XeEgAErh/tDdADohhzpwoayEVpCzgCr8/mxEDCIh4KFbAKsRGLCc3OOcMXzTERUUm9xW%2BPQkWxEAQlaS%2BMFVXMcRYkGnEVOA5xHa4DsRexEcgE2htqHQoaGg1SI80H8RS5R%2B1jTh%2B6a0EWXGIAA3ERMREJEwkZ8C%2BKATgGMRx8HokH2sjxHexvnGRWCDAirhudZzEak0CxE1ZgiR0xD0cLcRjaiEkesRbxEt9NsRSOGY4UzhwJFYsIcRgLo/ERsiUJGIHACRRcaAoFfqHyFstKha3lCr4ZOY9xGPUI8RxJFfAgyRJNQfEdNBXxHq0FyRHhjQkXyRDOBAkdm2yuGgkTvi4JHKkTyRZxFX5sT8phEREYiRyJFikaiRapFigNEMobbqSrQRaWL4wUM8m%2BEIwOvWV%2BGrTjfh7dgqCrqaWJCmxpXqPUjtAK7hgGRrQOER2WGf4Skq6hF5EVSRfmB9jF7ygBFsAMARAV7Q4Do64hAASjVgd8pdQFAR1%2BrdEcaRd6TLEYgRFBHiES4RSQDtgFgRWmpWGNgR7BHdEYWRBBE7KljioxSkEXYR3hH5kbIRGWpYkGgRmHQ4WhFsHZFOESgR72ptkYIRHZHAMOdQgIrdkVQRGuptkQYRHjDiKsoRmZEFkb2R%2BBGc7KkAE5E2EVORE%2BFNkc4Rc5GuEYlgXhGjFKWM5BGGoH6RnVaBkQNcP%2BE1EZrkX0ZphAeRAZG9pMeR2REuaJeRJNDXkc9heRGxEYERtaQ3YIkR2xKfoAv4XpEEkAURAUD3ka5QQLLBkdngd5F0lP6RD5FAUUsRf5EvkbUR75GlEcSRFREAUUeRT5HVEXERQRE3NikRDREP4VUwAxGYUFcqSUIdEe/EzjZIUY%2BRwFGQOLhRXyjnYWwRlyrCkcpEZpHzRuKRhiGSkS4hTxHotC8RyZybEYyR6zCfEfYS7IB6kRiwvJFttOGR/hGmkaKRDFEWkZjmdOp78v5i74pFluNayfL2ALnhv1a4XoeK34q0EWrqWZFaEMco5DAtLEVQcdrx8migmhHqgCZwkUQe2HucZFG00B7sRmBhXM%2BcSTKAPhNQtNT2kafhyvDn4TKu0U5HFD0asmQekeFAmlEX3JZR%2BlEkUZBRlJFNUBkiIuh00LHB7/CsPhFAv0qXvqo%2BhHgbQWjBaFgYwcgePKR8EkwiV5InQd5Bt5J3jOeSaizgYkdBHga3QXe2cFLhQV%2BSeVGATIgqf5IgTIBSEt6ovqlRjQECpBBS2wAITOqkdwGwUhBMdVF6pD0ByFIvQdi%2BWLIfQRnY%2BL7fQUlBfiwa3hoiAMFpQTrewMHhLPreYME5Qf1wCwF0UgxiRdj5YcIAqSwKKhvegypCcHlcX4rjwGsSZB5fwY7kKwHxUXZByqzUcuIAIdKOMLug/XKHLi7ecMHvELtQEgCXUYHguHIiugwBvSAJgD/hPmIJgE9eKd7/lJ8Bmr40wYXe9MFjDkUy3nJHnvw22xJigXY8O2BJEWKq2mJ7LkkRF8K%2BgVAAsNH5zOSApTTBgih6NVi8ABDRSNEGogWBVtRw0dx6hdqh4PjRYYFE0UjGxNGY0XyquIa2IHYgsgBWrBTmG0acgPAhHhhptgKgdiS6GMzRHLIY0Ti2WNHUjq38NEqjJE6s6VjhXCJEGeRLoMSkqlCcWuFBfqJsrEXapp4/LLysompuwJToiuCkSjCe7qqXvIgi6SKLUAFAaaxKrCqsTkGqciigatExMIrgW9jyAL5mmiy0/OXkbqCG0easuN5WrDasZtF2QOrRNwBooKx8ozwQktNYLwr96n5h5ORz0CJgoaH7csVQRZKC2AH04dGooA6qRtKIIm4YNQobmhbBdkCDrAIg89D1Gn/8gGH9cEpRfdJNMPhiF8HpIJO8z/IajCMST5a5XIjUkRLyUcMQp4LXwDQM22DxGIhq3KBEWEsm7GAPWmlYgsC75M/8vvRZGI3RVlBElhV2UdZh0V7Ryap7wKUErto8BBba8AppsiCkoUAc5GfkDOD0oDWktxpzmtSwryjiwV7RhAJfBOr8otEd0eLR30T5KkPs3KDqAn3R1OIK0emsStE8rMTUVpDM4nD0LmzobMOK/nBA4utyBZr%2BcOesdXZTipHioSAbdoIMlOSXtD3RVxhfrP3RhsSt0UuWpAq9SNICk8HMPOhAR7J10fogDdEAMflAB6xwgDJoSIRz/Iy8HRQ1Smm%2Bbwq9Vg5sGepSDEnRzgDk9GF0/9E%2BaH%2Bs2wDmkKOABkQRviMaQWqiXH0wqbLdkA/GAKZ//EoMgKDl4PSgMtDFapPe56zKSmE09oQKMPHKMTpGMAess9E85LWquDEHAIOscMLsYF%2BsBRaTotygB6yVXrA0ZDELIJVwBuhtnFfchyHjUP3s76KW7C8iGOLqPHg0wpx%2BYOPs1qgH0f48GOJY7Kqi9IFcgDkQ9OyM7GYx3qLyMQ/YaGAaMZo8V6B6PLocHfYNvDLQHcRFnPm6RNSuDGiAZiieMVhc5vxxDjbCLjHBMbjcZNxhMS2BetHkgfNc3mEq/BNcOhxxMeYx4hxoYDZRSIShMT9OYVwXBNkxNfyqXE32aICFMbuQeNzyPHkxT2EFMU9hz5z/YMUxORBuMcYxHjGs3ATc5iZc3CI88ZxRIFsRBjF1nLkxizzBUvH8xNy9Mer8FTH6PPExL6xzXKpUyTGNMTExk1wKPHmBTjHwwlExelLq/Gb8Uvw0LDz%2BKTHi/BsxWvw5ENH8mfzhMbox5IH6MWhgBzEe/BkxwzFnMUI6p8aXMQjCZMSYYdDyK6iMrnL2Siaapu0kTM47cvOWbs4%2B9H/R8DE%2BaO8AWpRqppqmeQoZcNF089Hw4Mn4jK4ddjdynzFMfN8xFxCAVt6w8fiHUbEq4hCzMPTEJsJgQkXs%2BOwI/uAm1HxD5qw8I%2Bar0HAmz4Gb5Pzqy9EPWqQE2XC%2BQm9av1bpUC2yuuBSDOAoVYjB0FrBkfQjgApQKgwnjj50EbJIhPbQAHaMsQKWUDGeTJpozHBCDPH4/DGGqM5K4bLAMcymj8Fh9M7QeALD0t8U%2B0KGMKlhNLw0JOwmdIBFmKix%2BjSy0AG8uUzWwqOsKzyuaOs8KHwPMflhFLHEogqwpASr/Iv8e8bD0jucDLHL0CrqNWAssbWs7LGsMUTgXLGwMDyxsrHL0QKxzF5CsfvmbpxvWuKx9nB8MebQamjVioLAfLHsYEGxVEpKsZGouepqsZGoDiwGaJMAgYg6saQ2IXRiMfhEhrFmZHcxvCBhvAe4bbwG6LP0RvTWsagxRKB5%2BDKa09FCsW6xxJJ3rJ6xbHSDvFCx/rFxsXKxTKCJsR0Uy9ChsUqcmVARsTlAUbFyMDGxh2EBsfYEvbGKseNQyrEW4WmxGrGrvFqx2bGvwXqxxQLoANB8DZjFsQ6SefjlsawCNdY/MA0hnmpEoPImo2LzUCjkVAz6Jlpo02IXrq9q2FHekQYgdtgxAM2gMQDPLPSMtgCuVO4yRQC%2BVL2gyvDCQqQBaARkYKV8n1TfseLG0CzQkHis%2BByhFIQc0aDQMAScG2Rm9qkRJsYRohZS40iUoBcEdtigcS7Gd2p/sdCQkMzk0ECiOGa59g/qdrRlamdo%2BhzH8uRA7cHLVE4cKaDwukYCKLo4gra6DABczii6KgA5us4Qrm7McaUmzHHYzsxxAIAyunUQzhCHQBxxEOaicbiWzHGaAKJx3JYouroWKLplkii6uxaDAHasg4BggHfcPRKSnOBx3pZYcclUMpzWOF%2Bx4Tg6cekETSHU/DexI0Ir8F4k0HGesLM4q9wy7CUx74KylARxO2JJnCahBCRGcQrsanEQPFycxuYAbJ5x1azGnHWstgTUcZ3gGcBtPgw0vvh%2BcU3sJGxBcWTBIXHWcf9g/Qa7IrTqW%2BJQHC8ESHFl6gYgmfZGxGhxIfCgxp7si2pZAE5xAZSD%2BGE0CP45caQQHDQv1I/UV9QP1MpKRXGaAcGiC/ZbqpssWXF1nOVxq0CPrpJAeXHgqAVx9XFEcekBo4Dlcfw06MLPsa4Ar7HFtlMAn7G81Kf8OMKe7HfctpxYsIkRXFCFcfwEa5xO5ATE7dAysbF%2B9x6XvMvR%2B%2BRefmYoG3G4hLXUrqxmKDvy6Q5mgjp8iyJ%2BbNG4w1QMlDT8ewLDIrgiDsLRrGvisazEoFT4HBxd6CVUVrAcHDT8YcA6NFV4ahi2sJ0cklFb4uXQZLHkdIPqM7jU5KDkNjoCfC6yM7ihNjBWKCxVPEygOKZvHpvksPy3tkbSkLJrljwq7GF5sbMqdZyQSg58cPHGsftWOmEtkp%2BWdJoXsCLi2PG2GBWxjzEewBmSwADLtv7AwdCpOikAJEDIWnhiKzLeUUb00gA5vtma3J7srtxk9vJBjswxRvRDitbhHXZ6sT%2BR2OC72PhEK3In2oGsPPEYwCREKdZ5cWNseXFFUqCwg9DhwOY8ODxu4Iq4RvE9AregMXx9iIJAAwo1YCmgpvFI3Ke0jQznobRmXXD08WMiiuD28fzUgcLuOFbx49qNIZ8kRZCKpl44jvFFzJM4aZyG8SnUG9wDDL7xNvGngp1%2BgvaYYbOAFLE%2B6t5C77RWANeKWQB82DOh%2Bfi48e8SA3jawbOApYQfijdIsJL86p9ccZFdbFwxoTDwMlOA9ALrsHwkzT7WQNf4UMghWLFc82gCCEOwYQhN8UUc1Ihx8PXxGuw/sLnwRMhaCIqmVIAP4tpIKmBt8a4InkhR8CBwq6zyQrB4/fHrVJmIK/EuSJKwTfHfwUbGCIBfirqE6gItzpX0SGaFgIJqVTAhAMfxWJAlbpssWgwfXCZELmik7vDaWQCNqLnEZxQfAHz8c3gi4n2IZObuQDF8SYTm8Q3g6LFlhBKgMXxaFMuBaWj/4PvxaXjmhCc8//FzMCLiWhTtAIGI5pQRhEJsO/FueF8Y4AlA8djohvjiogi0IqDu6L8C78Qf8eMEhAnt4CgJaXhwFrLs%2BbhwCX2I8xaoCSDcpAmZUhjgPuw/8Tvo6AkMgj6EOwzoCSbmOsKCYM6gCAnJJHJ%2BlAl0MG8wEyYmQQj8YXxphAz4hYBenCg4Agnl0A/xUADECWwQi5bsCVUkxYCtlMAJlMyuWvDMM3j0CUtCF8KKCdt46AnXGHJ%2B6glCCYzaIkLYfLMCb%2BYU6q/mZ5KqTFoxuuAk5JcwyPHMEej2aXaUYESgAKzjoCpAJOS5UIXEz/Dd8QAqQMF%2BpHRAuMrcTGzkwcCrmg%2B07bEqDHmWXap5DpKx81DZsPnxlOTNwcykj%2BoyYSWyi7LnvIK8mVTtQs0c%2BQktlK5e4qBAVh5MabFSDEyS6miaaPnx%2BbH%2BvM7QpQIOphUCSzHxDhzUiWYC3DP8DVClsU0CAMLRQBaxgdFz9CqcyPSvMcCxXZIuUYMUugRM4Lmg4kAZwAskwsEXtviufI4a4WdeWox4YfMQ2JAeqiXWXKoBYpsWOhHkdG8xSmiN0tTEOvItoIgqJ3g5wqIAfkwg1F6xfzFHII3RgLHt9MJ4IwlW2G8qXKoMOGx8SRa52G2xj/AM4CP86KKTCfBsMwkIoFTwSSaRqI6ke7ab5BIk0bEvCUiOBerqgtjeCOHQCeigoRQkwuiivKK2MQNx6pQg5gwABJYYFkSx4OYXkHk0DKzqlNRC2InEPF8YzhASca5wa3FWsYMJGXZcYDaxYwnvCf8J0wkrWHq8s4B/Epsas%2B7VHssJuGHGpGsJXNCe0psJP9DbCSZgWOCb5PsJjpHZCUHQObYnCb5C5wmXCfLk1wnEMQ3RWAAQ8T5o7bQa5N2xHglPmgPBfwnZtLH01BhQwjDC6tDdhFcx/QlVsbSJWPYz6owWownWeM8WTLEAiayJPzHsiYx0nIkFoStY/ny8iQF86nLkDDfiQomhgFyJEwm7CUb0EolDWksmzp43TKcJlYTyiTDkSJ4n9FLQ/zFRIPcJmok2ic8JOondkjsJnwngsd8JpnT%2BSpmJh2GOiXUAUdYgiQYmHXYQifbWY7HQiTdasIlsYXqxMzAACTA0WOy8wiZgaImIJmn%2B0j74sQQ8lIlJnMSx2BaEiXCkRcIkiRJxAizOEDiJVImQ8VWxIG50wnGqtxLW4RKJ1bJy9qT2gvGuiQN22XhLCZ6JDQQLJOsJgonNYLTCNkIz5K8Sc4lPCdWyMLGtJGvSyur2iQWJLIlFiVjxUolHCS6eUYkioDGJKuTxifXRtwkIMeigKYkMicjAe4n0wl6xELGaEOxg75a5XgomJPCapj%2BJ10YQ4XqxuyxTiTZC0jH01rN85olJ8Xs8aPJunNK8g2EWwkwAl8QJCgPY%2B1Yf8jpELvTKie%2BJ6omztF%2BJNbFD3i94Xwk/MAzgRpZqHkTmqElKnJhJ2EkZLK92sfT2MWbCQoAWwlbC27GISStBSAFrQRtBj1EXUe%2BeV1GvUZjBkL6XQU%2BSGVGXjJwSPkHnQblRB0GeQZosRVG1UaVR9VEBQarYhKSCEhrYrD6apJ0BYWqSSTC%2B2ECEpK0BGtgWLPpJPXLovr0BmL5OLAMB/VG4voNRX0Ho9j4syUETAYDBUwEgwXWKzkDUUkbeeUGm3vRS1I7HUVzeQgDemoIAyqwf7lFot1G4hsFJtViDzuFJO5iRSb7erwHmyhqkt1Iavq1BLhI%2BRJ7K4tK4IMtiyUIxcIDR/1Gl3jlJQNFC0tggINErUR7Ar4S64CIW7rE4AP5CftB4ApY2g0RJIgzem/Hvdk6ijSLXwHEqRaJgIVk2uzquTMDAy0BXCvuKtED%2BsDeqi6AucG2gYCwsAAA4dkBcPCpx0bgD3ANBQfGCANXMG9xiqD%2BikpbvxOyoHMBDXGDxNdBpopTEyISxIruiTNzuMf7UbVx/KFixe0k6unzGzxHeVrr47vH6%2BOC4t7ichKB4RVrxXOpsnpyNVDTqHHzKDGEW5kHtxk0wu0kwnttJdoSukh8ibATHIujRVxFAZNbWPDKOYq/Q2Iz1qJNEK6J3IhXEMOpFooT4Bpw/MCUirrSKuB8i4cAfIroYhMnfIogS0DwbcKI2H9gSAvhE2Qx96GjJbQAtIpjJLWjYyTMM7eqP8PjJIbRkyRFAJ6QkyayEPMno0fBxZpw25PDJOQSr6sjJUIyMybci7qIsyatEzMnsybjJgKBcyU04RMme4uUiK6zs0erJJyJy7KoYk6FmKIZS5hBgqMpEQVKfKM8iDAQonCbJ/6Jx/PB8ZolCVvYE96JGyV6SjYkFgZl8VXE7oW3sO2BrIlk8VxGhVCLsGCEDDF7JX0md4OtJ25RAyXNSLsmtgYB4/Cz3SWxRFxGFON7J/NFXEfmBUcl8/MrGD0kVpoCgQcnRUSHJm7hR8eHJQ1SwNOJsH5oZyfyRWNwwyQdJO5SBFOCEeCyBJMaE92CxyUcqBeQD3OGBJJx5XEawJoRTgObM/0mAoOAEFETQBBHC3NS1kNP2eRDiQQPJ3IJYomU0NuALSVHgJA5XTGPJNwJCVFPJ7eC8PtOCI8nzyUdEi8nSVEsEWfDDyXPJKRALyRHCotTZPNVowuBryfvJcIB9yWT%2B48mLsHlSy8m57BgI58kiDpIkh8kTyVuUZz4zyW52SPwZ6K/Ji7BcevfJGaBlREPh9RFbaB92BJDs1tfAuIDUGB1ImmD0whAAzjLFOMQUMxE8EJEmqhrlgfzJYkG1IlcR4Q7vahApwMkXrBnYsCkYOAgpSjTSkTZAd9yFgNDRfKIayV8iOsnAbKG2Umj2JD/8ARLNSdEgSSJ1iWXSsSKmCKjhWTYnSSOiGyhRkUTh4CEuqEkipgjnkQv4XCncST1EP6LoHHskfUSTnPWicZFyKeMQdRGHSXOiePiiKVIpwbztYd3sl0kKKTIpX1zKKSioGFEYpJax6sy%2BQkVGsDCxIl6xaQmMdIuq%2B/zbGnOBhlT%2BcOsh3ZCesKnKY1qCiT6JN3KpwQDgt4pWKUkip3io1NZ4C%2B7r0kSgdLEyGGEKExouGtokNMyNWrOA6cEuGocmJDZf2kTxZDbXALEicSQ8KV/hiilJRMsqwinvOEkicSTiKTbkmSlvVPLJm6IbRIT482AGKS%2BiLUQqKSYpailWRGwpDiLFKfI0Oin7ogg4bVxwUejJz6JJRJfUqilyQtJoQ96/AFFOelA7Cvu8qDaDvIfsPoRb2py8LazNkmaKwOEuYdnBFuGhTm5RWcFH/GhaUiLroHZ8%2BXiB5N4pS6pMIBGA7K6aYEk2qmFrKbxKHLBmim2YFgCavGdeBlwg1nA2QDDl0MyA28CdRp5s1PDDQAf09KitYKsO/LBBsV%2BgCQSfytvAaUJ5CuzYLxR0qEEAsr4S4FzASNYhOhcpFOS2KYcmCAr4nm6JBbyzYYNE%2BopcYIf%2BEyRH1OsuQKkqQnOBbWjghAusvwB8lqxA6clxyba2gRS%2B1pkC64HVXPfiVtRqfOCQNVzKuhrJQ4HxyXSpF6EudA8xTinjJD7qFHE3vOR0e5ZKCslCH079dgsJ495O4HGK9hE0kKlhWcxPIsXgLWB6fOR075Ig1OOKLCAX/JCAP5DpIG9U00B6sRLJRSmFzMap0tRkikKpTMKgsGUpqcypcWI0anH%2BorxJKXGkcRQYuEI0zD7qJ8jssaKpH/LiqQeyU45ReLcBPZKhTvKpSImKqc0JIRJ3gNfYZoqqqUb06qkV0YEA%2BXgiILqp/Kmf0jRkqjrShEqphqleftapy8zjJNmp1dj58OapYakmsaFS7YlDzKapOal3gGSKjfzp9i38wDB2nqnMA%2BE7Yhnkw7jlqfmpl2CxSWFJYgAJSfnw845yQH%2Bch0itqedkORAtqa0pNMwdqfFJoyo9qXZyA6mjqWapRpDXPgupi6lLqYupawSQ9CpSR34xSaFJE6mJSfUBCklXQb%2BSSqQAUuKk7VFWLHupT5JNUSqkaqRITCepoiKWSd1RyGIxQQrecUGfQQlBKt7OpL9BY1H/QalBpGIGEp5JVGLzUeYSdGJLUUsBgUkwwdZgwUldqbp6XoBRSdpiEGkf7ozE5iqKvqpSn1EfzM9UziLcwdjBeak12I4S9gmMxL5CBxTbSs/GfEI9Sa2pj8yhke8AiikixPxh2SoiKbOpGMBvzKopzHikaV6A0sm9olRp1Sl8Kc%2BiIsQNKV%2BRNuRdRsdJealELN6iHSkXSV0p%2Bim9KXEi3GnGKbxpZJRYaeMkzyAD6PpUSCmlyaYhflFG7B7svDj4oYkQ6oHolJ1gsVyrtPiU8tTDVND8ltY84Ch4RtS2gABCDez%2Bcc3sKFSchLCRZck7EIOp%2BlQfZEPhNpHSjm6pEjBCqZ6pjHQfMa0A1OT9YDsKXMAT3pE6yFDgEeUpg6JRqUp8aqlspBqp0xLaqTAiTKCQaZFJz2KVsJmpEgLMab8qmWmFqTI2U4CWqSuwgml/zLapyiT2qaDEKzFOqaBk1kGrQSqkSE6TDpBpCGl83m5B9QFlUYpJbBKZUbJJ2VEcIu5B5VFKSYVRCL7BQapJD0FWST1RKGJ2SVhSDklMsq%2BpIwHvqa5J41HfqelBv6kzUTMBAsE%2BSfMBfkn0vgFJR1FgaasB91EZirbYfUrJaT2pNUFg0btpBcrOONupR2lIaXxScmmg9sUsGGnJpA/McNCOEq1BB1LpSSTBmUlAyrTBs9j5QHlJhCBUwe8BRUlvaSVJWUlfaTvAFUmqICRpdGk4LKbEaICQ6Y4iIUxoYHEqCOmw6WXSj2kEolmYqOnDkFIM5GnDrOWa6SpSDAdgxOFNKd1GoXhFtDxJ1jylKjWE5SpFtJGpMmmmKX5hVUnnhB6hZdJFSjL41dRvWm1JBsQNIlEinwQ9SSR4fUnUNnoUU0nSYDNJc0mGPotJsICRTPM4ocl/KJ2EZCk5QE9J57idwmKiFmlx7KB4jPhAJpOhlzjSyQfY1QzIKfDgdgImae9xKukchEms4iQa6XiovcwJGFcRI7h6EErEUwzSKfxEeukqaSyU15RK6US4r0nclGrp5ukj%2BIKoVulbVj3J2rjdUgXJzHidhGr%2B8ulgeEiiNnGkVGm42bgtOCPUz3FrhEIQnvjJJM%2BEIqGK6XU0mtQm6dMiPunfSZrp2DIhQuopKkQU8RYx6bxHSZWE2untKeWiuiliaddJBjT0yVSp78SG6c9J2ekPlB9JVvi%2B6RIav0kUIqrGHLSAye8hGjY1qr24Q4wkEPwhymnUqQHaw%2BlmQa6EGelvccrp28ym6d7puKH%2B6dM0FyTAeCRo0jzAKW1SxbLD6UuEqWjj6c6MU%2BminI9JfUJG6fPpTCxvSWbpy%2BkW6Xwh6%2BkAbOXkVsyB6RO6x%2Bkh6XwuMHzSrqX4HsSbSU7pdul3pFSM%2BT4R6fM401Q8uEVE5VLZ0PHpwlRFRGH4qenlpjPpp%2Bl18oNCrenvSbnpTtaEJPfprYzBMjypoek/6SPpzyintPlSbUTO6RPpoGDN6e7pnfgX6V7pULjq6b7p7XSHSCvpYcmOaRlSNukMeL/pzyg4CHR4jumAxEQZTemz6WgZpmnXuBQZqulUGSgZrTjsGcGo9Bkb6fGMmBnJcRJ4OBmbpD7MOunhpkVS%2BulwGayUr3F8GcbpC%2Bk56eXgGunBzOwskcLoGe6MDAmv6UY4chkaOPgZx4QAGR7JMrjZNBYZWZSgGXHpy1R4mHYZiemRIj8g0BncVGnpOpBBMvEyMhnYGVwZrBkpYAoZ4enWGZHp/NG17DCMp4RgGXRgrvjyuNHpWNTJ6V74XhkWCUYZzBlmGRSMVoz4wi9x6rhwqCwZuBl3ODLokRl/tgGMsunpGYeEFQyrRLrpMwyhGYuUCHi/8aoZbukxrOfpnulCGY1W6zCLlJWkCHhfGBrpiYQSGTdmN%2Bls8HxUkfjweOtGGfKvlH9MNDwpGUHp0hlCkdYEtun5GfVcHBlD6TgZyhku6SaUpVIg3CHkkhkYGb4Zsxnf6QEZCxkkHOJB0SBqMaEZlzj/zI4WgqjDzsiYlLQg3NEZc1Y7GcYZA%2BkuqHkZe%2Bk1RMr%2BpxkByRxsw%2Bn3Gcx4Vxn5nBjgtxk73L8ZbeyWMs8ZshkHGf8M/%2BmEAckZLxllGV1EBBnzGf1ELUivGWEYE0SVGUoZaVzzGXVSPgDgybV0k1IDjPVJhxkxVuoZMea8GiN4iII0GUBBLnEe6YDQTKJBhFCiUxnEjDMZUiERyecZOJkU7ONSiKHbVlNSM1IUjMRwnBlrRLb4sngsmZ6CvVIKMt4ZEQziCQXpphmQmRMM%2B%2BmhGf2MDmK5jEKavTiMhGvi%2BOZ4nFlUVJlo6JABMAIdwrSZ9Jm1VIyZvelMGWLh2%2BmGRP%2BECxljUlLEXxnczLyZRJmtUixwgplV2MKZ6VTB6XRgPYwSmUyZevRb6VpBHhJ3aGhELpmYmS9EzHj4RJrxZESHRAAZL0RUyQjJq%2BoYmUCJ9YyKGX0QcsnBmSmZismSEFZ%2BnYSfkRwcd8ytlmLJMxRefgmZ5AwTDMmZnBhMIFjJeRnMdErJIizZmUloh0h96rRm1MmIycamaZklmT%2BEZZkrVpWZKxlPaiL%2BdZmTgA2ZIsmxmeLJRZltmQsZdkCdmamZyxkHGdWZmZl9mZ5E2xJQRBcZlMlNmXGZo5nTmUKZ8hlsAJOZGszdmTOZvZlDzP2ZAfHBqI2ZhoTNmfGZY5kf0juZFZmsyVWZB5m1mQuZxmx4qKeZ4GjnmeuZO%2BlWmZukp7TXmTrxbZlARBzJ85kjREjRtBnPmUOZq5kjmYd8xZmHGaq4P5nqAt04AFmHmY%2BZSHiNeA7YL5n2cG%2BZkFmXmQVKsFkvOEs4CFkPmUBZn5GZGbZMzXj5mRhZZiZYWR2ZxZldmXOBTcSzmbBxWZlIWWr0eZlphAWZNMlIyXTJ%2BUSoydRZU5kfmfuZ%2BFmjgCrJqCwnpFw4msk80Kgs0ELaPmBZZ5lrmbTJ9elhGI7oOFk8WRmZDFl4yUmBBMnNOCJZjaikyc04VmxgEtJZr5myWRxZ8lkZGbFwylk3meZZ9Fm69Iq4KEToADj41Zka7GhZIjZGWTghnFkZGduZ5lm/mRuZVRnXDAJZPcy2WfZZuslOWYSwLlmDRG5ZSsQPOJ5Ze5laxDjJc5n1/N0AAVn/0A5ZkrjBWWxZLZlhWSZZSsTn6EpZf5mxWapZ8VmJWTxpmDR6yQv4aVkSyeFZf%2BmImXkZY2zh6X5ZirgRmYFZqVnkWa5ZmVkkEIpZUVnEqQe4Vllu4CPQ9VkHRCopp5n2yUiEhsmxEMbJIMnWyVhsjjSnMfyoVskXouTpD6EOycJE30QexKwaSIT8tEdxRMSxfpeiZJShVAZpdpm69BTRO2BAGQHprJmFyTCBackR6cIUu5RW1NLpeckMGXTGndzaaavsl8wlycQZAwyHWRdgx1n5yeCZj1m8gH7JtpyNyZJBoITXWUdZLTgy6eaZO5R3cTrsr1nvxLcwrIQwBBDZS0k8/uCEdclpTIzxgNklVETsLTixoP8R8rgP%2BP3J8zg42YMZ3Py5uGwQKHhYGUjZ84HghC3MFbwTeBjZkpk/MITZZxEnWeZBwlCJ8SaUB7GcsV7YYNLVsuBBXgrBfo7CR3j/KjqMdqQ1YCjkK45AqUFC2XiH5oSpJvDDVFYkMZnagZ4BHMz5JAfpMSRuzBT4KeiwGQ8ZApEtONNU2CKbyRAZpNkZoOTZfhkWYOb282p4KRc241lEKb2AJCnEoGrZ3iaoKYpc5YGiWewE2CkW2RrqVtn0xspE1%2BIGWHBJ9tltfG9Z5CkkWFQpYoTaWfDZhg5%2BmXK8bzok1vywXfzHIKHOvTRJIk2E8CqBRErZJKn6JL9yJgAUqRGoMNlA2T8wKtkGVmmE0CnCoLdJeJn0qVtiwqAsBMNokJFshJjmYZkGNAzs5dmO2f7GvBkd%2BBu4ghmL6cIZEaEd6d9JXel4/H9J8cnrZj9Z6FkIyUjpsf5J6mlZE9kVqQlwzZkz2dDp6OmGWTkEcSrYLDeEdXDz2WXS2CzuRBvZ49lb2ahpJCzoYZVJTYT4aWzphGli6pfOq9kH2aX%2B/1A46eBE%2BSn9Scck19mr/hxwjGlwgGvZBlCdme2iYETiaazEX4Q8aRTibqAf2RxwtVk1Ka5E/9n0WWmE/Gl8Os/ZTYQl6azsPSl/2duE8byNKbiA0Dl%2B4bEpk9lnSRo8zTF6KYg5WsTf2XHGHqiNKVJR9glRaKfZkwTs6RfZxGn72Zg5FanZKQlYvUQP2YLpQDnP2UOpqDnv2Ww5%2BlTUWaei00T4ObI4/SmQOQv429n6VKA5xsSCOW/ZsIDoOVokpcQRaRExxamRqWA5rMT9KbTpgDnE6cdJIjmf0lXpe6KiaY1qxDlKOQQ5dSnaMMQ5dOnWBJWxZmHKpN6IPiSsoMOKHzEIpn8euc4zuA2yxeorKSTkKkA4XpQxMvibftnx1Qq3jmmJo/ErKaRwe%2BGBQldyktnrmiPqrbiZXshal8Q%2BhD4KodGkBMRCXvQS4DXYYTno9KFCWGwtYE/Bm/JPjJe89JZzlnzip3j7NgioqTlqIewhvFixOa4a8Yr8guJhmtjZ8bvJHaaelMtMNUJ/Hkq8ZUiFOTU5KkCzOCU8vACtuIgccQLqzO10RUIIQkwAYCSqYZLZHBLC2ArwmlbWQoYeXWEFkHMSCDSs1Eg0lYo1kHN011QZ0DU5vkwiKm0SETkZXi8a7oRR1q3U1uGDYZcwIsypOdQIA2hegL/sBlCVJAMqWSQNORHwVzk9tHiwD%2BLtkPtslYhJKAnMdzlRzA85NzkESFsALzmS2cEOGwnbOaVSMWrgzDY5Xkp4mixJQnBiKm8AzuBHshY5Lb4NAjCKztiP%2BFFoJ3gWQDWEbvIDRs0kwYrbYSspTljGUBtR1bLTAid4rErIpjnxhlTO2P6WcGRs8pLZTGoiXke0fYh9JGyJzQREqZo5H2DsqBFMPX5opItq8CShzMgkTfRiapQk5YJo4kExqMy4AaSpPiSGJME0grlEcaGZlNlNxNTZ4Oi02fLsLWg1mUQM2NnM2VQcL2qVSXhpJ3gEaftWjrGX2bQ5sjkkLAw5FGl2xEzEzDkCYT0wz9kMaRw5sIAULCxpPDkmxDMqHGkyxEzEADnfRk/ZdDmL2ccZzHQGObI43GlCOXxp5ekYOea59GmuuUWph9GKOcbE3GmqOb65i6ARuTI5VcQkLNg5RjFkgQ9k%2BjkJufbEAykkOVVgaVkuubGgeCwELCHAQmk1qplphTgLzM8qdSDNmYVpsaBTzKnAL8zRuYsxiRAluTW5QGIMKU7k6kywOLJ8N0jRvtOOtamGWgAyg7lSUvQmBp5osR25XDmXYGdpB2kRST2pqWn9qYHxs7mEqhHyR37lAYdp4j6J7upJPWltaTJJ14xnQTlR%2B0FXQVeSfCKrjoi%2Bg2lnqTC%2BzQEFCNpJzVFtURZJp7lPkgepF6kWLChMHVFqSf5B%2B7mHqTpJV6ltUZ%2B5p6kpoo9B0hIPqXLeY2mKEkMBU2nDUTNpo1FaEnNppL5TUYtp%2BiKgwStpcwEQwYtR%2BUGbaaxSvQ7gabVpxe6LuTu53Hpwad2pO7lXabYSZdj%2BudhpmIgkwa9p/2k9LB9pFjTZSX9Rv2kFSWVJTB6A6Qx532kg6cDRruwMwdJRIZLU8I0Soc7upAAyoWq68ASuGlB1FJS8USRjUEey6AqpzI%2Bm2cHerOesJzASeQ6ekUpJdrRAJJCaOSPBtqqHJufQMwAlvsBJLSnw6Up5DYpvMqR0PFS3/Cwp/iktSQ4iNim1JAXBClBRrFsa565zgU2EaPKuKeDkstAeKTqMGybrCe0kxODNSZvksSKneF55sTk1kJ1iHzwRKVngYQoI4ZjpN9mWuZxpcSJfhLa5NGnngTfZJSmSuS/ZrGkjolhE7MkGOb2iEDmSOTe0zSliPhxw2jnnSbg5Ymn4OSV5yDnSaWo5pDkT5Nf4%2BfAUOaQEVDkmuTQ51wA0zHfZ50S2rGiAROlVyRWpOXlK2TPMf5m8OT/Z/DmTuBI5TrnJqYG5v9mGOXN5pjloOam5cjk2yT6ixNwzeSY4Kjm/fKt5hekVeaGp2inV6Z0pejndKcG5s3kLRAW5pjlDKSU5nCB4YkxAkLk3GnY5e9qIpo45JmiNspLZbjlgSgGqnjmTBN45vgk1diM0wWKS2UE5EdYhOU8KNTnhOeyhxyb7OSKgMTkhKZU58Tn7OIk5eH7JOfnw0PlpOcVCCKBDElk5L9qc2Lk5nCD5OcXehTnb0vd57wkxoKJYFTnXtGYCNTkr8HU5atgNOXzMNGT2OYl2%2B/JLAlTwSkAdOeaU3Tm9OQcSR0IDOd%2BZAwIjOYC5FykTOZlgUzns2DM58l7Make0Czl41Es5NDQrOS2gazmf1Bs5ktlbOVyaqV6Owns54OQHOXImxzk5XiaWZzkXKVOYFznkQE85%2BfCIpN852yQW0GUkjMTXOS85EySTbB85dfG2%2BaskvznlIP85rppmYUC5V7k7idr5/UyN2NY5o5ZQuTVgOEkAotq88LmlwIi5zQQcYFBYpEB4WlbBWcHouTZIlYRYuYLAOLkLini53ErNdoS5djpHYTi5pLlLAuS5NZCwkh%2Bm1LnQ5LS5JdF2AAy5czkEroGIrLnOiey5uXnlxJdg3LkyuZFMfLmxTMYc8rkH6JwMzIG%2BMcYcG0w0JAP5HALM/Ll5yrn6JDK5kMz9%2BSVxDvhf6RnZB7g1ySxk9clGDESE3JmLVn9ZLckzfOaUCJxivJyAgWBvuCTgXcnbGb3Jv8lZPCIkX8mGeFfJsgE3yTTR/%2BCfyevJB8mbyRHC9ZRLBKvJs8nPydwkl/mCANvJeWgq%2Bk/JFVR3%2BaUUi8nHyUsE4unf%2BSAFf/l3ySfJD8l7yT/5GOCgBam4i8nvyf/gQgiIBTAFb/kTyf/J8AWAKfFEbmnttq15URxegB15%2BzhdeaCUprm9eRa5/XkCxPbE1Gm7OmjpY3lZeQG5brnsaUV5ebneuWG5uXlvzGI5Xrn%2BIDwFKblF6cwF5Ok7eY8wibn7eWo5a3kiBRm51Xk4Odm5l4TGKZd5JjhSaSY5zXnjefJpY/TsOfnZ1Mw2qS/pDRmjImQZPOAgzEgZlmnjIeA8OplhGdbpDmk62XbkBgUPWWPZOQSduWW5hgDNuQgAlbk7%2BW25Xblz2QjJaOlPzC25hgB4LJ4Fkbnpud4F38xH2f5OnmlAMN5pcwlCee8KAWmSqfcSwWkyqeiSyZG1YSGpo3lKqVFpQay3ieXRmmjxaWmw6aHbub2paWmx9Cv%2BhlTPVDlpxzF5ae2BK7A0zMVpUDClaRei5WkWQc6p3hSuqUp5EjAeqXEFsLH%2BaRKpfqnzUCkFgak0FukF4WnHeZt59gQ24r984cHRaTGpsWlxqVqpRQW7kCUFy7m/MPZgClGoFBmp5QXW/vQ5VQXwOcMx8IH0OY0FifjNBRPsxjwnBfaiK/6PzGjp1QWDMbbJJan1BRa5lwWqcVao9DCtBQMMlwX90DTM7gWtuW2p78zUeeMkmKpLAJo5RqD7AOW5qcATedppqczAhSCB3gW/BUEFcgXWEJ25sIVaQA65f8yuBe4FIQVzgV/MvMQM6baeCKBxKZqRN0jNqc3J9DmrBX2pCyBvVMOpZIVtqUagRHnyUtxyVIVZzP60y6lsheyFS6mrqTSF0IXkhQyFtmLMhaN5ciCR%2BMKFIoWihWKF4oUShY5066nM/qR5k6nEeW5BLWlnuQVR7WlHudwSF0EC3vlRjKRBQV%2BMz7ndaa1pgqRVUUepQFIlUQZJGoXgUv9Q8EwAeZqkQHniElLekUHPQaNp6FLvQRNpKhK4YnB56t4IeV%2BpSHnBCRRSs1HoeeDBuUEWEth5y1GgaXh5O2nrQadR6dRyUsdpjmLlAVGFYqyIaa8BFyBCvuGKIr564iHeFNIh%2BVtK4aQ3ATK%2Bcr7PaWXe4lLF2GgB7FKyUgmFal5GjDSceo7i0t%2Bc8cCmvlzBxYUrvl1elr4qXgmF166XAT0sx64uvk%2BgxMElST7K%2BUnceWDp/HmF3tHinUHJhXxS/tl/iQWFriJoadOFH1FeAFG27GJ8Ugcp3iIjuWDUY4pPEieWGtjw6G16zamcKWsMH%2BFPAGjhqSpU6aDUFjCMBXoUqbmK9JERsbn%2BPDdgJ4UtijrkSbl6uYLR%2BU4tVBd87fz%2BcPGF4qx7hdcAZaRIOH8BFr7SUq2FOuIVhUpSujDfhYB4wVTjhRxBV/6lhQIAclLthaVcJgAsgK64ztQqPhnkw3lwgL%2BkgvS4ZNMM1wy4RcLkGjIZGQ7p7VJERdUZ6BA/pCWkPyLgZCf4kGSZMlmEsGTY3ghkspbhbKhk6KDoZAkUWGQmjDfwEexqkZmkJWQ8ZNa0KmRpTMJFuGRP5KB0nGTyQWiRPEWNZFnsYkWcZMVkzfK0ngpF1mRNZKpFiWRCQcwUGkVyRXJBI7wLZK4w0jmZpDTMapFGRZOkwmmnebo5nuztXE7kLuQHsmb0QOQ4WHDxvnm%2B5E9h5vRw5JFK4NYxTijk%2BPaCvMtig0jZFG6guOQNYQTkPOBYpiTkGaBk5EFFv9Gn9LTkzKSJFh38NYpSiWzkengcsUTgenhEqc1o4uQ0aFLolQzkRbGJzlrOyYwpdkWL9O7kwOSe5GDkPuSQ5Huc7kVB5L5CYeTRRb70m/DKpLHkcQDx5ComyeSpRd6x7p4mlJlF2yzZRZ%2BoV/C0aMQsuAHF5BCcUmivgT6xh1Zz5DsQjxJeqg4sq%2BQfROvkYzmIqXf0K6yy2WbQBznS4oq5WiGKgS20qBRMFDJFmNSkBCDwyBT0ZCtZt3GwNMgUZ9gXRZsCIqBRQDdFO0Xgof4UqNmeAVEUdqjWgfOUhT4y/JbJe0VrZKN5JkXx1KnM10WjebdFz0Ue1PIFWbmtgTm5V0le9iJpzTHSrpA0o1kzWeNZF0iMQAcF9zEoxS2gpsmmiZjFcwKy0OFS9MAYxR8FNkBGxKW0grQ6EaswNGROyUNZ7GAjWcxEzPbq/NZS6MVL%2BTvUaRCe2VUw3tlQKVbJttnsgIHZrdnsNjJEvMUsQDrQHtRFIo4F8/YdSfex4Cmi0hkRQZy%2B2YQphljEKbH2QdnWbIYx6mmhUZppOpA5gH7ZEVG9gA0CrmmBEB7UhsXW5F9CGJEF8XRgxoLpOb500urYMa5odmgNuKe0oNYPtDx017TEQotGeLw39ICZaUU9RZbFRKmjdC5SJAJuUorZbMUWxchUQ0KHtL6qsPhOxZLZTUVuxek5scUE9mZh/sUg6N5S%2BEU/tMjF0iHs2eHF8XTUdM7gr8C0dH50DHTZeIB4YUYwYNxYKylNRZx0gOBmYIipFPR8dAl0qmEpxVnk1nTAwHlFowzRIDDqJQyc9JnFbLTmOfH5ucVZEjj5i6J%2BdI7FgXQ2dL7F4cVxxRHFYKEuxaf0cXQgqKuhBUI1UlmEI0BpdNukVwxZdBvFyYy5dCHFbNlhxRKSKMAL9FAi0lAS9Gj0R2IKXsPqLaDY9NFFuPRqGMOy/nSoJvd4LHQVxfH5TUWU9PGK1PSNRWtFEvQZRbJFKPRDdPhFPcUMxVnFYcWzgCVFUCIzuOYeVvSqUEf5Y/TAsj1w7vTe9BY5TUUV9J7hjPCRSl70/HB1xaf0%2B3JQsZY6%2B3JqDJXFa0VEJcnFw%2BEJWCNIDoq6DCnJWfhoJVeWYVbV9DxsNkVgJYfFCPQlwUMJrTrkolg2G/QrYF1wD/R79Bxg90gzoaZhb8X1xef08dIG5KvSicXb5BrYD/QbRXVIIOigDO/028X5Rcx0NMV9xdnFWAw4DOnxBAxPmMQMIx5kDBmh6PSXxV1FPHTePKWA4KaoVh70mCVyMBwMXAy6JSzkzzH0MXPAqUVMGiARqQWSDP9KvqmyDO10WEletF1FSfjcsXIwpCW9RVtpJYVZ3iBFqE6KUspSCpyyFjoM8CWuUpNZ9AyFULNJ7xAl9N48X%2BnPvhXe8EXiXjxS%2BMVjFNQlVhxJJYYM26gvXOole77roGbFYlg1HiQK21kyFu7hClmQAGDFJQx1UksZ8VKFUjpFLjLdjAQZCVKdJcRFPRjdRGRFHcXImYAMO8XjRD0lHSWERR3F5Qx5Um0l81KqJX0lgRnLhKXoRRkkWYsl0FmGQVkZYaI5GbJFXSXlGb1SrjDVUhyZDVKSRdMl8pkGVkcl5yUZRBCcZVnvmfMlh/CdDO3FGXS8WfclzyUURbvZEFkUWUMlNyB76U8lOXReWe0lO8UjJcOZhZmYWd8ly6DjRH8lNFn4RcCl4FmgpV8lgKXldDMlUKUvJTVScEQFcM1ZcqmvJRCl9rgopbuZLWi9Jb4FnyWtmeCl0FnCMvhFNVl3cXCMGKWhWQSlIOi/JRSlfnCYpWJqKMkTJTvFAKXYpeilHyXwpS1ZDSUNGO1ZKiUdxRylaKWMeDSlxKUZWXylWVlspflFwqWEpWKlPKUSpRsl0qVCpV3FkyXypexZvKVkpXilFlmCpW8lBEXqpelZLKX5RGZZuqX/JaqlQKWiGNOiKYWUPpElYEUxJXEqBXS/9HcMsDLz3lqC8kqu8HcMc1wADLnonqXQWdBEf/QJBDWk95lEDCp0uQQ1pINZRKqP2VAItwyKdI4gFdnQuKGly2SStMdk3oKJpas2XFGgeC0MPgw1jI6lZgwm5MmlVWTstH086OLy5qPZODK5pXcM8aX0nLm0spExJeXgf/SPkVRU7wxXEUuER2SStBlUwaXmDAZZ0OjOpf0lXURfRrr0QQQqdMFZAaWRAmmMn9KdpUdZw6XdpdUlCxk5DJ2lTaXb3Km8XFHSWS15F5mkpY8lFKXmpQslu7ji5GOMeaSGkDuMjagXzK8M07QLjNeFgPQrjPsltnS9DLGMHlKHguoQ66WIpQ8lpZlbpXSlFqW7paOMWMyv5BOMR6UoLLB0ywwwDAr0B4Xg1LWMHQwTDLsMG4x3pU50mzhPpdil1pnapZ%2BR%2BXQOtEkRRrTQWJO0VcCTjPio0uQTtPS0WGVR2TBlXLRwZSvFd4SIZdulwyVzeBWlsaVdpaMl5XSHgomC8bQ6dH%2BlPcxLDEZ07wyVjMBl2aVLjGBltVL2uLZ0QIyd0GyWA1KwZXclJGVomWRl76U7pfJ0vPTUZQL0pyU3IPRlY0zS5M54%2BGXF/Cxlp6VQDOxl56UgZZel4GU0eLZ0FbSCZQmWwmVEZaJlI0jIpW%2BlMKWUZTGlQHRyZbRlh/CKZYVC0uSe6jXgqmXqZZAMTgx5tNplXGVK9CNSKUTROCbkhmVcaKgMo%2BQiZWClz6U/JdhZb6XUjHhZorRfpRpa0uT4jL6MzGUnpSiMAYwcZasMPmWgZThoopqK4HiMJTjQZSlxYWUIpfBl4Yz%2BINFlVKUBjJ%2BlYHRkoAUwyFnWjKhZPBxL%2BMVlmqWspXMlIqX4pVZlflnOtIekGlmsZYBBFjynmeVZrVnFAAKl4KXQpaal/5mauRbQdoypZY0MUbRd6dJZw2WSpTmRyqV6pbKlHSXdZbNlAGVRtHroDmqPpVmpFVlhRJFZk2Wopb0lW2W9ZdzJO2WAQZK43WQk/pLJ7lkSZV1lF2XCIH1lGmW6yXdl2AGKpeGMT2WnZezJL2XEAFdl/WWOjJ9l2lIxdrh5zYXARWWFOuJIRST%2BlyUUjLiZlmV/Zb5ZcWVgdCKBKEXtAGnIbmVzZa2kapGFMC1lWKViZd2Mv2XjZXlZ/8WOZeEgqEULDCll12UXBQTlkmUvpcTljKXVZXRl6OWoRd9I2OWq5CZlaiTEZeZluKVI5aTlKlnk5WzlaQDPDDTlwOXc5RQYvOX0peJlAuURZTl0kDkjjGjlrDgY5QEiLngiQJzlEuVNZXbk9OXw5eUZ1Lpy5ZylZOVK5azlKuWoRW3YYAwetDjlXOXa5RO6uuWmpWSlWjIVZUXJsWXIZcrlhqCmAOblz8Anugt0VuUetDslRWWmZeFlpWXGpeVlyOWUpS7lVWWo5XRltWViNPVlruKROJLl3hTLZX6la2VmpQzleqXdWaCEnuWvZUDl72X67NgQKeX0yWnlE2WC5SjlcVnG4F2wGOWA5faM%2BeWLZSuZX2VGpe5ZJeVnZZtl02VV5ahFNeXW5btlxVmfZUXloeXtZSUMG2Ufpe3lOeVd5bTlYmRDZYdlI2WQOCTl8uX/md1lY%2BVvZZAMH2VT5XJZK2XHZXPlRuX/ZaPl1eXL5fNlN2Xy7INZGEWvAa1xZ%2Brb9kslCuCQ6oU4vCBEAORlNyAaNJ2lt%2BX/4OHA9lKfZXq43REjSMAIzOJ1qe6EUujt4TUUHY7VUnmkawVwCCWknabAFe8Q06lFkJmkgOiw6Q7leaTPsiu5USCZpAR0kBUyAGvuvADjdDVSHThM8bFRft5NaYQVkoAzQFtSi0D6AMtA11KvabyY20B2gBMu%2BAB2gHtAd0BHQIKIpgiDCFdA2fCPQIwAL0CnOiAAd0DbUktAjAD6AF9A1BV/QPaAAMDDWCAAG7LFAOdSrVZO0Dhu3wBPEnqA%2BgD1EiZYchVkwAoV0MKngESSHgD1QNPx30BEkmEAiMDXymQVLMC1mDU2ghWmFYxAasD/lBYV61jLWEqY8pgvUltY%2BgBamGeA9gBEwJ9SMCrwAHFw%2BEDMIJgK2tBjUCgAAgxW0PaAEpigIFgAgRX7gGYIQ1gSmDEmgRVj6iEVPhUNAMKSyLBJakEAERXcwPuAZSAxFfhA35wZFQrAWRUpiChAdoCWJfQAzAAaIGoAb8rBWP9QkVgOspFY7TqxWAUA8VjvAEwAeVhCFTDYB4AU2GoV5gAaFbBAm0BrQDzAH4V8mGyYDACdWCYV70ClhH1gNWDnEkwAh%2BxXAEygrgjw0PDQFtACyv4AHsD3wUMAjsD6AEdStBXP7vQVu0BlADPyWSgGSAmABQiMCPHwBMBcFRyYAhUfQMIVOxUjFV4A1xXkFRYV9xVRtt9YQAA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment