From 68a88648473b1f1e6ad92ef01cfe9e7d64f77146 Mon Sep 17 00:00:00 2001 From: lbrynaut Date: Mon, 6 Aug 2018 15:40:20 -0400 Subject: [PATCH 01/18] Rebase lbry on to upstream (WIP) --- configure.ac | 37 +- reproducible_build.sh | 457 ++++++ src/Makefile.am | 18 +- src/Makefile.bench.include | 4 +- src/Makefile.qt.include | 4 +- src/Makefile.qttest.include | 4 +- src/Makefile.test.include | 9 +- src/amount.h | 2 +- src/chain.h | 18 +- src/chainparams.cpp | 269 ++-- src/chainparams.h | 3 + src/chainparamsbase.cpp | 6 +- src/chainparamsbase.h | 18 + src/chainparamsseeds.h | 1278 +-------------- src/claimtrie.cpp | 2804 +++++++++++++++++++++++++++++++++ src/claimtrie.h | 655 ++++++++ src/coins.h | 4 +- src/consensus/consensus.h | 4 +- src/consensus/params.h | 15 +- src/consensus/tx_verify.cpp | 13 +- src/dbwrapper.h | 2 +- src/hash.cpp | 37 + src/hash.h | 2 + src/index/txindex.cpp | 25 - src/index/txindex.h | 25 + src/init.cpp | 15 + src/lbry.cpp | 40 + src/lbry.h | 9 + src/miner.cpp | 129 +- src/miner.h | 2 +- src/nameclaim.cpp | 201 +++ src/nameclaim.h | 45 + src/net.cpp | 1 + src/net_processing.cpp | 15 +- src/policy/policy.cpp | 5 +- src/pow.cpp | 72 +- src/primitives/block.cpp | 12 +- src/primitives/block.h | 6 + src/protocol.cpp | 14 +- src/rpc/blockchain.cpp | 9 +- src/rpc/claimtrie.cpp | 802 ++++++++++ src/rpc/register.h | 4 + src/script/interpreter.cpp | 11 +- src/script/script.h | 6 +- src/test/bip32_tests.cpp | 66 +- src/test/blockchain_tests.cpp | 6 +- src/test/bloom_tests.cpp | 522 +++--- src/test/coins_tests.cpp | 63 +- src/test/main_tests.cpp | 62 +- src/test/rpc_tests.cpp | 19 + src/test/script_tests.cpp | 45 + src/test/test_bitcoin.cpp | 12 + src/test/test_bitcoin.h | 5 + src/txdb.cpp | 20 +- src/txdb.h | 4 + src/undo.h | 101 +- src/util.cpp | 12 +- src/validation.cpp | 679 +++++--- src/validation.h | 180 +++ 59 files changed, 6844 insertions(+), 2063 deletions(-) create mode 100755 reproducible_build.sh create mode 100644 src/claimtrie.cpp create mode 100644 src/claimtrie.h create mode 100644 src/lbry.cpp create mode 100644 src/lbry.h create mode 100644 src/nameclaim.cpp create mode 100644 src/nameclaim.h create mode 100644 src/rpc/claimtrie.cpp diff --git a/configure.ac b/configure.ac index 9cc01a402..96a937560 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,12 @@ AC_ARG_WITH([qrencode], [use_qr=$withval], [use_qr=auto]) +AC_ARG_WITH([icu], + [AS_HELP_STRING([--with-icu], + [Required ICU root path])], + [ICU_PREFIX=$withval], + [ICU_PREFIX=auto]) + AC_ARG_ENABLE([hardening], [AS_HELP_STRING([--disable-hardening], [do not attempt to harden the resulting executables (default is to harden when possible)])], @@ -640,6 +646,7 @@ if test x$ac_cv_sys_large_files != x && CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files" fi +AX_CHECK_LINK_FLAG([[-static-libstdc++]], [LDFLAGS="$LDFLAGS -static-libstdc++"]) AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"]) AX_GCC_FUNC_ATTRIBUTE([visibility]) @@ -895,6 +902,7 @@ AX_BOOST_SYSTEM AX_BOOST_FILESYSTEM AX_BOOST_THREAD AX_BOOST_CHRONO +AX_BOOST_LOCALE dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic dnl counter implementations. In 1.63 and later the std::atomic approach is default. @@ -961,7 +969,7 @@ fi if test x$use_boost = xyes; then -BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB" +BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB $BOOST_LOCALE_LIB" dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums @@ -1057,6 +1065,16 @@ if test x$use_pkgconfig = xyes; then m4_ifdef( [PKG_CHECK_MODULES], [ + ICU_CPPFLAGS="-I$ICU_PREFIX/include" + CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS" + ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl" + AC_MSG_WARN([Using ICU_CPPFLAGS $ICU_CPPFLAGS]) + AC_MSG_WARN([Using CPPFLAGS $CPPFLAGS]) + + AC_CHECK_HEADER([unicode/errorcode.h],,AC_MSG_ERROR(libicu headers missing)) + AC_CHECK_LIB([icudata], [main], ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl", + AC_CHECK_LIB([icu18n], [main],ICU_LIBS=$ICU_LIBS, ICU_LIBS="-L$ICU_PREFIX/lib -lsicudt -lsicuin -lsicuio -lsicule -lsiculx -lsicutest -lsicutu -lsicuuc")) + PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)]) PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [BITCOIN_QT_FAIL(libprotobuf not found)])]) @@ -1082,6 +1100,18 @@ if test x$use_pkgconfig = xyes; then ] ) else + ICU_CPPFLAGS="-I$ICU_PREFIX/include" + CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS" + ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl" + + AC_MSG_WARN([Using ICU_CPPFLAGS $ICU_CPPFLAGS]) + AC_MSG_WARN([Using ICU_LIBS $ICU_LIBS]) + AC_MSG_WARN([Using CPPFLAGS $CPPFLAGS]) + + AC_CHECK_HEADER([unicode/errorcode.h],,AC_MSG_ERROR(libicu headers missing)) + AC_CHECK_LIB([icudata], [main], ICU_LIBS="-L$ICU_PREFIX/lib -licui18n -licuuc -licudata -ldl", + AC_CHECK_LIB([icu18n], [main],ICU_LIBS=$ICU_LIBS, ICU_LIBS="-L$ICU_PREFIX/lib -lsicudt -lsicuin -lsicuio -lsicule -lsiculx -lsicutest -lsicutu -lsicuuc")) + AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing)) AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing)) @@ -1385,6 +1415,9 @@ AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_UPNP) AC_SUBST(USE_QRCODE) AC_SUBST(BOOST_LIBS) +AC_SUBST(ICU_PREFIX) +AC_SUBST(ICU_CPPFLAGS) +AC_SUBST(ICU_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) @@ -1431,7 +1464,7 @@ if test x$need_bundled_univalue = xyes; then AC_CONFIG_SUBDIRS([src/univalue]) fi -ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni" +ac_configure_args="${ac_configure_args} --enable-static --disable-shared --with-pic --with-bignum=no --enable-module-recovery --disable-jni" AC_CONFIG_SUBDIRS([src/secp256k1]) AC_OUTPUT diff --git a/reproducible_build.sh b/reproducible_build.sh new file mode 100755 index 000000000..4e64231a3 --- /dev/null +++ b/reproducible_build.sh @@ -0,0 +1,457 @@ +#!/bin/bash + +set -xeuo pipefail + +function HELP { + echo "Build lbrycrd" + echo "-----" + echo "When run without any arguments, this script expects the current directory" + echo "to be the lbrycrd repo and it builds what is in that directory" + echo + echo "This is a long build process so it can be split into two parts" + echo "Specify the -d flag to build only the dependencies" + echo "and the -l flag to build only lbrycrd. This will fail" + echo "if the dependencies weren't built earlier" + echo + echo "Optional arguments:" + echo + echo "-c: don't clone a fresh copy of the repo" + echo "-f: check formatting of committed code relative to master" + echo "-r: remove intermediate files." + echo "-l: build only lbrycrd" + echo "-d: build only the dependencies" + echo "-o: timeout build after 40 minutes" + echo "-t: turn trace on" + echo "-h: show help" + exit 1 +} + +CLONE=true +CLEAN=false +CHECK_CODE_FORMAT=false +BUILD_DEPENDENCIES=true +BUILD_LBRYCRD=true +TIMEOUT=false +THREE_MB=3145728 +# this flag gets set to False if +# the script exits due to a timeout +OUTPUT_LOG=true + +while getopts :crfldoth:w:d: FLAG; do + case $FLAG in + c) + CLONE=false + ;; + r) + CLEAN=true + ;; + f) + CHECK_CODE_FORMAT=true + ;; + l) + BUILD_DEPENDENCIES=false + ;; + d) + BUILD_LBRYCRD=false + ;; + o) + TIMEOUT=true + ;; + t) + set -o xtrace + ;; + h) + HELP + ;; + \?) #unrecognized option - show help + echo "Option -$OPTARG not allowed." + HELP + ;; + :) + echo "Option -$OPTARG requires an argument." + HELP + ;; + esac +done + +shift $((OPTIND-1)) + +SUDO='' +if (( EUID != 0 )); then + SUDO='sudo' +fi + +if [ "${CLONE}" = false ]; then + if [ "$(basename "$PWD")" != "lbrycrd" ]; then + echo "Not currently in the lbrycrd directory. Cowardly refusing to go forward" + exit 1 + fi + SOURCE_DIR=$PWD +fi + +if [ -z "${TRAVIS_OS_NAME+x}" ]; then + if [ "$(uname -s)" = "Darwin" ]; then + OS_NAME="osx" + else + OS_NAME="linux" + fi +else + OS_NAME="${TRAVIS_OS_NAME}" +fi + +if [ -z "${TRAVIS_BUILD_DIR+x}" ]; then + START_TIME_FILE="$PWD/start_time" +else + # if we are on travis (the primary use case for setting a timeout) + # this file is created when the build starts + START_TIME_FILE="$TRAVIS_BUILD_DIR/start_time" +fi +rm -f ${START_TIME_FILE} +date +%s > ${START_TIME_FILE} + +NEXT_TIME=60 +function exit_at_60() { + if [ -f "${START_TIME_FILE}" ]; then + NOW=$(date +%s) + START=$(cat "${START_TIME_FILE}") + TIMEOUT_SECS=3600 # 60 * 60 + TIME=$((NOW - START)) + if (( TIME > NEXT_TIME )); then + echo "Build has taken $((TIME / 60)) minutes: $1" + NEXT_TIME=$((TIME + 60)) + fi + if [ "$TIMEOUT" = true ] && (( TIME > TIMEOUT_SECS )); then + echo 'Exiting at 60 minutes to allow the cache to populate' + OUTPUT_LOG=false + exit 1 + fi + fi +} + +# two arguments +# - pid (probably from $!) +# - echo message +function wait_and_echo() { + PID=$1 + (set -o | grep xtrace | grep -q on) + TRACE_STATUS=$? + # disable xtrace or else this will get verbose, which is what + # I'm trying to avoid by going through all of this nonsense anyway + set +o xtrace + TIME=0 + SLEEP=5 + # loop until the process is no longer running + # check every $SLEEP seconds, echoing a message every minute + while (ps -p "${PID}" > /dev/null); do + exit_at_60 "$2" + sleep "${SLEEP}" + done + # restore the xtrace setting + if [ "${TRACE_STATUS}" -eq 0 ]; then + set -o xtrace + fi + wait "$PID" + return $? +} + +# run a command ($1) in the background +# logging its stdout and stderr to $2 +# and wait until it completed +function background() { + $1 >> "$2" 2>&1 & + BACKGROUND_PID=$! + wait_and_echo $BACKGROUND_PID "$3" +} + +function cleanup() { + rv=$? + # cat the log file if it exists + if [ -f "$2" ] && [ "${OUTPUT_LOG}" = true ]; then + echo + echo "Output of log file $2" + echo + tail -n 1000 "$2" + echo + fi + # delete the build directory + rm -rf "$1" + echo "Build failed. Removing $1" + exit $rv +} + +function cat_and_exit() { + rv=$? + # cat the log file if it exists + if [ -f "$1" ] && [ "${OUTPUT_LOG}" = true ]; then + echo + echo "Output of log file $1" + echo + # This used to be the last 3MB but outputing that + # caused problems on travis. + # Hopefully the last 1000 lines is enough + # to debug whatever went wrong + tail -n 1000 "$1" + echo + fi + exit $rv +} + +function brew_if_not_installed() { + if ! brew ls | grep $1 --quiet; then + brew install $1 + fi +} + +function install_brew_packages() { + brew update > /dev/null + brew unlink python + brew_if_not_installed autoconf + brew_if_not_installed automake + # something weird happened where glibtoolize was failing to find + # sed, and reinstalling fixes it. + brew reinstall -s libtool + brew_if_not_installed pkg-config + brew_if_not_installed protobuf + brew_if_not_installed gmp + + if [ "${CHECK_CODE_FORMAT}" = true ]; then + brew_if_not_installed clang-format + fi +} + +function install_apt_packages() { + if [ -z "${TRAVIS+x}" ]; then + # if not on travis, its nice to see progress + QUIET="" + else + QUIET="-qq" + fi + # get the required OS packages + $SUDO apt-get ${QUIET} update + $SUDO apt-get ${QUIET} install -y --no-install-recommends \ + build-essential python-dev libbz2-dev libtool \ + autotools-dev autoconf git pkg-config wget \ + ca-certificates automake bsdmainutils + + if [ "${CHECK_CODE_FORMAT}" = true ]; then + $SUDO apt-get ${QUIET} install -y --no-install-recommends \ + clang-format-3.4 + fi + +} + +function build_dependencies() { + if [ "${OS_NAME}" = "osx" ]; then + PARALLEL="-j $(sysctl -n hw.ncpu)" + install_brew_packages + else + PARALLEL="-j $(grep -c processor /proc/cpuinfo)" + install_apt_packages + fi + + if [ "$CLEAN" = true ]; then + rm -rf "${LBRYCRD_DEPENDENCIES}" + rm -rf "${OUTPUT_DIR}" + fi + + if [ ! -d "${LBRYCRD_DEPENDENCIES}" ]; then + git clone https://github.com/lbrynaut/lbrycrd-dependencies.git "${LBRYCRD_DEPENDENCIES}" + fi + # TODO: if the repo exists, make sure its clean: revert to head. + mkdir -p "${LOG_DIR}" + + build_dependency "${OPENSSL_PREFIX}" "${LOG_DIR}/openssl_build.log" build_openssl + build_dependency "${ICU_PREFIX}" "${LOG_DIR}/icu_build.log" build_icu + build_dependency "${BDB_PREFIX}" "${LOG_DIR}/bdb_build.log" build_bdb + + set +u + export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/" + set -u + + build_dependency "${BOOST_PREFIX}" "${LOG_DIR}/boost_build.log" build_boost + build_dependency "${LIBEVENT_PREFIX}" "${LOG_DIR}/libevent_build.log" build_libevent +} + +function build_bdb() { + BDB_LOG="$1" + if [ "${OS_NAME}" = "osx" ]; then + patch db-4.8.30.NC/dbinc/atomic.h < atomic.patch + fi + cd db-4.8.30.NC/build_unix + echo "Building bdb. tail -f $BDB_LOG to see the details and monitor progress" + ../dist/configure --prefix="${BDB_PREFIX}" --enable-cxx --disable-shared --with-pic > "${BDB_LOG}" + background "make ${PARALLEL}" "${BDB_LOG}" "Waiting for bdb to finish building" + make install >> "${BDB_LOG}" 2>&1 +} + +function build_openssl() { + OPENSSL_LOG="$1" + mkdir -p "${OPENSSL_PREFIX}/ssl" + cd openssl-1.0.1p + echo "Building openssl. tail -f $OPENSSL_LOG to see the details and monitor progress" + if [ "${OS_NAME}" = "osx" ]; then + ./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \ + -fPIC darwin64-x86_64-cc \ + no-shared no-dso no-engines > "${OPENSSL_LOG}" + else + [[ $(uname -m) = 'i686' ]] && OS_ARCH="linux-generic32" || OS_ARCH="linux-x86_64" + ./Configure --prefix="${OPENSSL_PREFIX}" --openssldir="${OPENSSL_PREFIX}/ssl" \ + ${OS_ARCH} -fPIC -static no-shared no-dso > "${OPENSSL_LOG}" + fi + background "make ${PARALLEL}" "${OPENSSL_LOG}" "Waiting for openssl to finish building" + make install >> "${OPENSSL_LOG}" 2>&1 +} + +function build_boost() { + BOOST_LOG="$1" + cd boost_1_67_0 + + echo "int main() { return 0; }" > libs/regex/build/has_icu_test.cpp + echo "int main() { return 0; }" > libs/locale/build/has_icu_test.cpp + + export BOOST_ICU_LIBS="$(pkg-config icu-i18n --libs) -dl" + export BOOST_LDFLAGS="${BOOST_PREFIX}/lib ${ICU_PREFIX}/lib ${BOOST_ICU_LIBS}" + + echo "BOOST_ICU_LIBS: $BOOST_ICU_LIBS" + echo "BOOST_LDFLAGS: $BOOST_ICU_LIBS" + + echo "Building Boost. tail -f ${BOOST_LOG} to see the details and monitor progress" + ./bootstrap.sh --prefix="${BOOST_PREFIX}" "--with-icu=${ICU_PREFIX}" > "${BOOST_LOG}" 2>&1 + b2cmd="./b2 link=static cxxflags=-fPIC install boost.locale.iconv=off boost.locale.posix=off -sICU_PATH=${ICU_PREFIX} -sICU_LINK=${BOOST_ICU_LIBS}" + background "${b2cmd}" "${BOOST_LOG}" "Waiting for boost to finish building" +} + +function build_icu() { + ICU_LOG="$1" + mkdir -p "${ICU_PREFIX}/icu" + wget http://download.icu-project.org/files/icu4c/55.1/icu4c-55_1-src.tgz + tar -xf icu4c-55_1-src.tgz + rm -f icu4c-55_1-src.tgz + pushd icu/source > /dev/null + echo "Building icu. tail -f $ICU_LOG to see the details and monitor progress" + ./configure --prefix="${ICU_PREFIX}" --enable-draft --enable-tools \ + --enable-static --enable-shared --disable-extras --disable-icuio \ + --disable-layout --disable-layoutex --disable-tests --disable-samples + if [ ! -z ${TARGET+x} ]; then + TMP_TARGET="${TARGET}" + unset TARGET + fi + set +e + background "make ${PARALLEL} VERBOSE=1" "${ICU_LOG}" "Waiting for icu to finish building" + make install >> "${ICU_LOG}" 2>&1 + if [ ! -z ${TARGET+x} ]; then + TARGET="${TMP_TARGET}" + fi + set -e + popd > /dev/null +} + +function build_libevent() { + LIBEVENT_LOG="$1" + if [ ! -d libevent ]; then + git clone --branch release-2.0.22-stable https://github.com/libevent/libevent.git + fi + cd libevent + echo "Building libevent. tail -f ${LIBEVENT_LOG} to see the details and monitor progress" + ./autogen.sh > "${LIBEVENT_LOG}" 2>&1 + ./configure --prefix="${LIBEVENT_PREFIX}" --enable-static --disable-shared --with-pic \ + LDFLAGS="-L${OPENSSL_PREFIX}/lib/" \ + CPPFLAGS="-I${OPENSSL_PREFIX}/include" >> "${LIBEVENT_LOG}" 2>&1 + background "make ${PARALLEL}" "${LIBEVENT_LOG}" "Waiting for libevent to finish building" + make install >> "${LIBEVENT_LOG}" +} + +function build_dependency() { + PREFIX=$1 + LOG=$2 + BUILD=$3 + if [ ! -d "${PREFIX}" ]; then + trap 'cleanup "${PREFIX}" "${LOG}"' INT TERM EXIT + cd "${LBRYCRD_DEPENDENCIES}" + rm -rf ${PREFIX} + mkdir -p "${PREFIX}" + "${BUILD}" "${LOG}" + trap - INT TERM EXIT + fi +} + +function build_lbrycrd() { + if [ "$CLONE" == true ]; then + cd "${LBRYCRD_DEPENDENCIES}" + git clone https://github.com/lbryio/lbrycrd + cd lbrycrd + else + cd "${SOURCE_DIR}" + fi + ./autogen.sh > "${LBRYCRD_LOG}" 2>&1 + LDFLAGS="-L${OPENSSL_PREFIX}/lib/ -L${BDB_PREFIX}/lib/ -L${LIBEVENT_PREFIX}/lib/ -L${ICU_PREFIX}/lib/ -static-libstdc++" + if [ "${OS_NAME}" = "osx" ]; then + OPTIONS="--enable-cxx --enable-static --disable-shared --with-pic" + CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/ -I${ICU_PREFIX}/include" + else + OPTIONS="" + CPPFLAGS="-I${OPENSSL_PREFIX}/include -I${BDB_PREFIX}/include -I${LIBEVENT_PREFIX}/include/ -I${ICU_PREFIX}/include -Wno-unused-local-typedefs" + fi + + CPPFLAGS="${CPPFLAGS}" LDFLAGS="${LDFLAGS}" \ + ./configure --without-gui ${OPTIONS} \ + --with-boost="${BOOST_PREFIX}" \ + --with-icu="${ICU_PREFIX}" >> "${LBRYCRD_LOG}" 2>&1 + + + background "make ${PARALLEL}" "${LBRYCRD_LOG}" "Waiting for lbrycrd to finish building" + if [ "${OS_NAME}" = "linux" ]; then + LD_LIBRARY_PATH="${ICU_PREFIX}/lib" src/test/test_lbrycrd + else + DYLD_LIBRARY_PATH="${ICU_PREFIX}/lib" src/test/test_lbrycrd + fi + strip src/lbrycrdd + strip src/lbrycrd-cli + strip src/lbrycrd-tx + strip src/test/test_lbrycrd +} + +function clang_format_diff(){ + # run a code formatting check on any commits not in master + # requires clang-format + if ! git config remote.origin2.url > /dev/null; then + git remote add origin2 https://github.com/lbryio/lbrycrd.git + fi + git fetch origin2 + git diff -U0 origin2/master -- '*.h' '*.cpp' | ./contrib/devtools/clang-format-diff.py -p1 +} + +# these variables are needed in both functions +LBRYCRD_DEPENDENCIES="$(pwd)/lbrycrd-dependencies" +OUTPUT_DIR="$(pwd)/build" +LOG_DIR="$(pwd)/logs" +ICU_PREFIX="${OUTPUT_DIR}/icu" +BDB_PREFIX="${OUTPUT_DIR}/bdb" +OPENSSL_PREFIX="${OUTPUT_DIR}/openssl" +BOOST_PREFIX="${OUTPUT_DIR}/boost" +LIBEVENT_PREFIX="${OUTPUT_DIR}/libevent" + +if [ "${BUILD_DEPENDENCIES}" = true ]; then + build_dependencies +fi + +if [ "${CHECK_CODE_FORMAT}" = true ]; then + LINES_W_FORMAT_REQUIRED=$(clang_format_diff | wc -l) + if [ ${LINES_W_FORMAT_REQUIRED} -ne 0 ]; then + echo "Failed to pass clang format diff: See below for the diff" + clang_format_diff + exit 1 + fi +fi + +set +u +export PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:${OPENSSL_PREFIX}/lib/pkgconfig/:${LIBEVENT_PREFIX}/lib/pkgconfig/" +set -u + +if [ "${BUILD_LBRYCRD}" = true ]; then + LBRYCRD_LOG="${LOG_DIR}/lbrycrd_build.log" + echo "Building lbrycrd. tail -f ${LBRYCRD_LOG} to see the details and monitor progress" + trap 'cat_and_exit "${LBRYCRD_LOG}"' INT TERM EXIT + build_lbrycrd + trap - INT TERM EXIT +fi diff --git a/src/Makefile.am b/src/Makefile.am index d1693fa85..4d2436bef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,7 @@ else LIBUNIVALUE = $(UNIVALUE_LIBS) endif -BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(ICU_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) $(ICU_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) @@ -102,6 +102,7 @@ BITCOIN_CORE_H = \ chainparamsseeds.h \ checkpoints.h \ checkqueue.h \ + claimtrie.h \ clientversion.h \ coins.h \ compat.h \ @@ -127,12 +128,14 @@ BITCOIN_CORE_H = \ key.h \ key_io.h \ keystore.h \ + lbry.h \ dbwrapper.h \ limitedmap.h \ logging.h \ memusage.h \ merkleblock.h \ miner.h \ + nameclaim.h \ net.h \ net_processing.h \ netaddress.h \ @@ -178,10 +181,12 @@ BITCOIN_CORE_H = \ txdb.h \ txmempool.h \ ui_interface.h \ + uint256.h \ undo.h \ util.h \ utilmemory.h \ utilmoneystr.h \ + utilstrencodings.h \ utiltime.h \ validation.h \ validationinterface.h \ @@ -221,6 +226,7 @@ libbitcoin_server_a_SOURCES = \ blockencodings.cpp \ chain.cpp \ checkpoints.cpp \ + claimtrie.cpp \ consensus/tx_verify.cpp \ httprpc.cpp \ httpserver.cpp \ @@ -228,8 +234,10 @@ libbitcoin_server_a_SOURCES = \ index/txindex.cpp \ init.cpp \ dbwrapper.cpp \ + lbry.cpp \ merkleblock.cpp \ miner.cpp \ + nameclaim.cpp \ net.cpp \ net_processing.cpp \ noui.cpp \ @@ -240,6 +248,7 @@ libbitcoin_server_a_SOURCES = \ pow.cpp \ rest.cpp \ rpc/blockchain.cpp \ + rpc/claimtrie.cpp \ rpc/mining.cpp \ rpc/misc.cpp \ rpc/net.cpp \ @@ -253,6 +262,8 @@ libbitcoin_server_a_SOURCES = \ txdb.cpp \ txmempool.cpp \ ui_interface.cpp \ + uint256.cpp \ + utilstrencodings.cpp \ validation.cpp \ validationinterface.cpp \ versionbits.cpp \ @@ -416,6 +427,7 @@ libbitcoin_util_a_SOURCES = \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ + uint256.cpp \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ @@ -441,7 +453,7 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h bitcoind_SOURCES = bitcoind.cpp bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +bitcoind_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoind_SOURCES += bitcoind-res.rc @@ -461,7 +473,7 @@ bitcoind_LDADD = \ $(LIBMEMENV) \ $(LIBSECP256K1) -bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) +bitcoind_LDADD += $(BOOST_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index f5293585a..37c5f2d55 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -55,8 +55,8 @@ if ENABLE_WALLET bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp endif -bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) -bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(ICU_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) +bench_bench_bitcoin_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index c7a196313..5ae355e18 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -409,9 +409,9 @@ if ENABLE_ZMQ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(ICU_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) -qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +qt_bitcoin_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX #locale/foo.ts -> locale/foo.qm diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 4b14212b2..b3db4204b 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -64,9 +64,9 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ - $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(ICU_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) -qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +qt_test_test_bitcoin_qt_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1b6827d45..497ec39bb 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -61,6 +61,9 @@ BITCOIN_TESTS =\ test/miner_tests.cpp \ test/multisig_tests.cpp \ test/net_tests.cpp \ + test/claimtriecache_tests.cpp \ + test/claimtriebranching_tests.cpp \ + test/nameclaim_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ test/policyestimator_tests.cpp \ @@ -117,8 +120,8 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) -test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static +test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(ICU_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +test_test_bitcoin_LDFLAGS = -L$(ICU_PREFIX)/lib $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ test_test_bitcoin_LDADD += $(ZMQ_LIBS) @@ -143,7 +146,7 @@ test_test_bitcoin_fuzzy_LDADD = \ $(LIBBITCOIN_CRYPTO_SHANI) \ $(LIBSECP256K1) -test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(ICU_LIBS) # nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/amount.h b/src/amount.h index 2bd367cba..fc32631e5 100644 --- a/src/amount.h +++ b/src/amount.h @@ -23,7 +23,7 @@ static const CAmount CENT = 1000000; * critical; in unusual circumstances like a(nother) overflow bug that allowed * for the creation of coins out of thin air modification could lead to a fork. * */ -static const CAmount MAX_MONEY = 21000000 * COIN; +static const CAmount MAX_MONEY = 21000000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } #endif // BITCOIN_AMOUNT_H diff --git a/src/chain.h b/src/chain.h index 01011d54f..9aa305444 100644 --- a/src/chain.h +++ b/src/chain.h @@ -209,6 +209,7 @@ public: //! block header int32_t nVersion; uint256 hashMerkleRoot; + uint256 hashClaimTrie; uint32_t nTime; uint32_t nBits; uint32_t nNonce; @@ -237,6 +238,7 @@ public: nVersion = 0; hashMerkleRoot = uint256(); + hashClaimTrie = uint256(); nTime = 0; nBits = 0; nNonce = 0; @@ -253,6 +255,7 @@ public: nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; + hashClaimTrie = block.hashClaimTrie; nTime = block.nTime; nBits = block.nBits; nNonce = block.nNonce; @@ -283,6 +286,7 @@ public: if (pprev) block.hashPrevBlock = pprev->GetBlockHash(); block.hashMerkleRoot = hashMerkleRoot; + block.hashClaimTrie = hashClaimTrie; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; @@ -294,6 +298,11 @@ public: return *phashBlock; } + uint256 GetBlockPoWHash() const + { + return GetBlockHeader().GetPoWHash(); + } + int64_t GetBlockTime() const { return (int64_t)nTime; @@ -322,9 +331,10 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, claimtrie=%s, hashBlock=%s)", pprev, nHeight, hashMerkleRoot.ToString(), + hashClaimTrie.ToString(), GetBlockHash().ToString()); } @@ -402,6 +412,7 @@ public: READWRITE(this->nVersion); READWRITE(hashPrev); READWRITE(hashMerkleRoot); + READWRITE(hashClaimTrie); READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); @@ -413,19 +424,20 @@ public: block.nVersion = nVersion; block.hashPrevBlock = hashPrev; block.hashMerkleRoot = hashMerkleRoot; + block.hashClaimTrie = hashClaimTrie; block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; return block.GetHash(); } - std::string ToString() const { std::string str = "CDiskBlockIndex("; str += CBlockIndex::ToString(); - str += strprintf("\n hashBlock=%s, hashPrev=%s)", + str += strprintf("\n hashBlock=%s, hashClaimTrie=%s, hashPrev=%s)", GetBlockHash().ToString(), + hashClaimTrie.ToString(), hashPrev.ToString()); return str; } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 93bb3e764..59cc0c17a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -14,6 +14,38 @@ #include +//#define FIND_GENESIS + +#define GENESIS_MERKLE_ROOT "b8211c82c3d15bcd78bba57005b86fed515149a53a425eb592c07af99fe559cc" + +#define MAINNET_GENESIS_HASH "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463" +#define MAINNET_GENESIS_NONCE 1287 + +#define TESTNET_GENESIS_HASH "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463" +#define TESTNET_GENESIS_NONCE 1287 + +#define REGTEST_GENESIS_HASH "6e3fcf1299d4ec5d79c3a4c91d624a4acf9e2e173d95a1a0504f677669687556" +#define REGTEST_GENESIS_NONCE 1 + +bool CheckProofOfWork2(uint256 hash, unsigned int nBits, const Consensus::Params& params) +{ + bool fNegative; + bool fOverflow; + arith_uint256 bnTarget; + + bnTarget.SetCompact(nBits, &fNegative, &fOverflow); + + // Check range + if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit)) + return error("CheckProofOfWork(): nBits below minimum work"); + + // Check proof of work matches claimed amount + if (UintToArith256(hash) > bnTarget) + return error("CheckProofOfWork(): hash doesn't match nBits"); + + return true; +} + static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; @@ -22,6 +54,9 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = genesisReward; + //txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + //txNew.vout[0].scriptPubKey = CScript() << ParseHex("0425caecb9fbf6cf50979644e85c11e3ec9007fd477fab9683648c6539e59b59c3a4d9b9c0b552c37eee6476f3e0d8425ac0346fe69ad61628b8c340d42fbfa3fd") << OP_CHECKSIG; + //txNew.vout[0].scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ParseHex("e5ff2d9e3a254622ae493573169c0fa94c82fe4f") << OP_EQUALVERIFY << OP_CHECKSIG; txNew.vout[0].scriptPubKey = genesisOutputScript; CBlock genesis; @@ -32,6 +67,21 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi genesis.vtx.push_back(MakeTransactionRef(std::move(txNew))); genesis.hashPrevBlock.SetNull(); genesis.hashMerkleRoot = BlockMerkleRoot(genesis); + genesis.hashClaimTrie = uint256S("0x0000000000000000000000000000000000000000000000000000000000000001"); + +#ifdef FIND_GENESIS + while (true) + { + genesis.nNonce += 1; + if (CheckProofOfWork2(genesis.GetPoWHash(), nBits, consensus)) + { + std::cout << "nonce: " << genesis.nNonce << std::endl; + std::cout << "hex: " << genesis.GetHash().GetHex() << std::endl; + std::cout << "pow hash: " << genesis.GetPoWHash().GetHex() << std::endl; + break; + } + } +#endif return genesis; } @@ -48,8 +98,8 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi */ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { - const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + const char* pszTimestamp = "insert timestamp string";//"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; + const CScript genesisOutputScript = CScript() << OP_DUP << OP_HASH160 << ParseHex("345991dbf57bfb014b87006acdfafbfc5fe8292f") << OP_EQUALVERIFY << OP_CHECKSIG; return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); } @@ -73,16 +123,23 @@ void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64 class CMainParams : public CChainParams { public: CMainParams() { - strNetworkID = "main"; - consensus.nSubsidyHalvingInterval = 210000; + strNetworkID = "lbrycrd"; + consensus.nSubsidyLevelInterval = 1<<5; + consensus.nMajorityEnforceBlockUpgrade = 750; + consensus.nMajorityRejectBlockOutdated = 950; + consensus.nMajorityWindow = 1000; consensus.BIP16Exception = uint256S("0x00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22"); - consensus.BIP34Height = 227931; - consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); - consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 - consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; + consensus.BIP34Height = 1; + consensus.BIP34Hash = uint256S("0xdecb9e2cca03a419fd9cca0cb2b1d5ad11b088f22f8f38556d93ac4358b86c24"); + consensus.BIP65Height = 1; + consensus.BIP66Height = 1; + consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetTimespan = 150; //retarget every block + consensus.nPowTargetSpacing = 150; + consensus.nOriginalClaimExpirationTime = 262974; + consensus.nExtendedClaimExpirationTime = 2102400; + consensus.nExtendedClaimExpirationForkHeight = 400155; + consensus.nNormalizedNameForkHeight = 1000000; // FIXME: pick a real fork height consensus.fPowAllowMinDifficultyBlocks = false; consensus.fPowNoRetargeting = false; consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 @@ -98,82 +155,77 @@ public: // Deployment of SegWit (BIP141, BIP143, and BIP147) consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1; - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016. - consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017. + // FIXME: Update times + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1634352575; //1479168000; // November 15th, 2016. + consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1634352575; //1510704000; // November 15th, 2017. // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000028822fef1c230963535a90d"); + consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000607ca7e806c4c1e9"); //400000 // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8"); //534292 + //consensus.defaultAssumeValid = uint256S("0xf0e56e70782af63ccb49c76e852540688755869ba59ec68cac9c04a6b4d9f5ca"); //400000 + consensus.defaultAssumeValid = uint256S("0xa6bbb48f5343eb9b0287c22f3ea8b29f36cf10794a37f8a925a894d6f4519913"); //4000 /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce * a large 32-bit integer with any alignment. */ - pchMessageStart[0] = 0xf9; - pchMessageStart[1] = 0xbe; - pchMessageStart[2] = 0xb4; - pchMessageStart[3] = 0xd9; - nDefaultPort = 8333; + pchMessageStart[0] = 0xfa; + pchMessageStart[1] = 0xe4; + pchMessageStart[2] = 0xaa; + pchMessageStart[3] = 0xf1; + nDefaultPort = 9246; nPruneAfterHeight = 100000; - genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1446058291, MAINNET_GENESIS_NONCE, 0x1f00ffff, 1, 400000000 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); +#ifdef FIND_GENESIS + std::cout << "hex: " << consensus.hashGenesisBlock.GetHex() << std::endl; + std::cout << "merkle root: " << genesis.hashMerkleRoot.GetHex() << std::endl; +#else + assert(consensus.hashGenesisBlock == uint256S(MAINNET_GENESIS_HASH)); + assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT)); +#endif + vSeeds.clear(); + vFixedSeeds.clear(); - // Note that of those which support the service bits prefix, most only support a subset of - // possible options. - // This is fine at runtime as we'll fall back to using them as a oneshot if they don't support the - // service bits we want, but we should get them updated to support all service bits wanted by any - // release ASAP to avoid it where possible. - vSeeds.emplace_back("seed.bitcoin.sipa.be"); // Pieter Wuille, only supports x1, x5, x9, and xd - vSeeds.emplace_back("dnsseed.bluematt.me"); // Matt Corallo, only supports x9 - vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org"); // Luke Dashjr - vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf - vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.bitcoin.sprovoost.nl"); // Sjors Provoost + vSeeds.emplace_back("dnsseed1.lbry.io"); // lbry.io + vSeeds.emplace_back("dnsseed2.lbry.io"); // lbry.io + vSeeds.emplace_back("dnsseed3.lbry.io"); // lbry.io - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); - base58Prefixes[SECRET_KEY] = std::vector(1,128); - base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; - base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; - - bech32_hrp = "bc"; + base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0x55); + base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,0x7a); + base58Prefixes[SECRET_KEY] = std::vector(1,0x1c); + base58Prefixes[EXT_PUBLIC_KEY] = {0x01, 0x9c, 0x35, 0x4F}; + base58Prefixes[EXT_SECRET_KEY] = {0x01, 0x9c, 0x31, 0x18}; vFixedSeeds = std::vector(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); + /* bech32_hrp = "bc"; */ + bech32_hrp = "lb"; // FIXME: change this? + + vFixedSeeds = std::vector(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); + + fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = true; fMineBlocksOnDemand = false; + // FIXME: update checkpoints? checkpointData = { { - { 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")}, - { 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")}, - { 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")}, - {105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")}, - {134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")}, - {168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")}, - {193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")}, - {210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")}, - {216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")}, - {225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")}, - {250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")}, - {279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")}, - {295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")}, + { 4000, uint256S("0xa6bbb48f5343eb9b0287c22f3ea8b29f36cf10794a37f8a925a894d6f4519913") }, } }; + // FIXME: chainTxData = ChainTxData{ - // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8 - /* nTime */ 1532884444, - /* nTxCount */ 331282217, - /* dTxRate */ 2.4 + 1467272478, 4146, 600.0 + /* // Data from rpc: getchaintxstats 4096 0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8 */ + /* /\* nTime *\/ 1532884444, */ + /* /\* nTxCount *\/ 331282217, */ + /* /\* dTxRate *\/ 2.4 */ }; /* disable fallback fee on mainnet */ @@ -187,18 +239,26 @@ public: class CTestNetParams : public CChainParams { public: CTestNetParams() { - strNetworkID = "test"; - consensus.nSubsidyHalvingInterval = 210000; + strNetworkID = "lbrycrdtest"; + consensus.nSubsidyLevelInterval = 1 << 5; + consensus.nMajorityEnforceBlockUpgrade = 51; + consensus.nMajorityRejectBlockOutdated = 75; + consensus.nMajorityWindow = 100; consensus.BIP16Exception = uint256S("0x00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105"); + // FIXME: adjust heights consensus.BIP34Height = 21111; consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; + consensus.powLimit = uint256S("0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetTimespan = 150; + consensus.nPowTargetSpacing = 150; + consensus.nOriginalClaimExpirationTime = 262974; + consensus.nExtendedClaimExpirationTime = 2102400; + consensus.nExtendedClaimExpirationForkHeight = 278160; consensus.fPowAllowMinDifficultyBlocks = true; consensus.fPowNoRetargeting = false; + consensus.nNormalizedNameForkHeight = 1000000; // FIXME: pick a real fork height consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; @@ -216,30 +276,32 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1493596800; // May 1st 2017 // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000007dbe94253893cbd463"); + consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000a0c3931735170"); // By default assume that the signatures in ancestors of this block are valid. consensus.defaultAssumeValid = uint256S("0x0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75"); //1354312 - pchMessageStart[0] = 0x0b; - pchMessageStart[1] = 0x11; - pchMessageStart[2] = 0x09; - pchMessageStart[3] = 0x07; - nDefaultPort = 18333; + pchMessageStart[0] = 0xfa; + pchMessageStart[1] = 0xe4; + pchMessageStart[2] = 0xaa; + pchMessageStart[3] = 0xe1; + nDefaultPort = 19246; nPruneAfterHeight = 1000; - genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1446058291, TESTNET_GENESIS_NONCE, 0x1f00ffff, 1, 400000000 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); +#ifdef FIND_GENESIS + std::cout << "testnet genesis hash: " << genesis.GetHash().GetHex() << std::endl; + std::cout << "testnet merkle hash: " << genesis.hashMerkleRoot.GetHex() << std::endl; +#else + assert(consensus.hashGenesisBlock == uint256S(TESTNET_GENESIS_HASH)); + assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT)); +#endif vFixedSeeds.clear(); vSeeds.clear(); - // nodes with support for servicebits filtering should be at the top - vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch"); - vSeeds.emplace_back("seed.tbtc.petertodd.org"); - vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl"); - vSeeds.emplace_back("testnet-seed.bluematt.me"); // Just a static list of stable node(s), only supports x9 + vSeeds.emplace_back("testdnsseed1.lbry.io"); + vSeeds.emplace_back("testdnsseed2.lbry.io"); base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); @@ -247,21 +309,24 @@ public: base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; - bech32_hrp = "tb"; + /* bech32_hrp = "tb"; */ + bech32_hrp = "lt"; // FIXME: change? vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); + fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; fMineBlocksOnDemand = false; - + fTestnetToBeDeprecatedFieldRPC = true; checkpointData = { { - {546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, + {0, uint256S(TESTNET_GENESIS_HASH)}, } }; + // FIXME: chainTxData = ChainTxData{ // Data from rpc: getchaintxstats 4096 0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75 /* nTime */ 1531929919, @@ -280,18 +345,23 @@ public: class CRegTestParams : public CChainParams { public: CRegTestParams() { - strNetworkID = "regtest"; - consensus.nSubsidyHalvingInterval = 150; + strNetworkID = "lbrycrdreg"; + consensus.nSubsidyLevelInterval = 1 << 5; consensus.BIP16Exception = uint256(); - consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests) + // FIXME: heights + consensus.BIP34Height = -1; // BIP34 has not necessarily activated on regtest consensus.BIP34Hash = uint256(); consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests) consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests) consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; - consensus.fPowNoRetargeting = true; + consensus.nPowTargetTimespan = 1;//14 * 24 * 60 * 60; // two weeks + consensus.nPowTargetSpacing = 1; + consensus.nOriginalClaimExpirationTime = 500; + consensus.nExtendedClaimExpirationTime = 600; + consensus.nExtendedClaimExpirationForkHeight = 800; + consensus.fPowAllowMinDifficultyBlocks = false; + consensus.fPowNoRetargeting = false; + consensus.nNormalizedNameForkHeight = 2000; // FIXME: pick a real fork height consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; @@ -311,27 +381,34 @@ public: consensus.defaultAssumeValid = uint256S("0x00"); pchMessageStart[0] = 0xfa; - pchMessageStart[1] = 0xbf; - pchMessageStart[2] = 0xb5; - pchMessageStart[3] = 0xda; - nDefaultPort = 18444; + pchMessageStart[1] = 0xe4; + pchMessageStart[2] = 0xaa; + pchMessageStart[3] = 0xd1; + nDefaultPort = 29246; nPruneAfterHeight = 1000; - genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); + genesis = CreateGenesisBlock(1446058291, REGTEST_GENESIS_NONCE, 0x207fffff, 1, 400000000 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); +#ifdef FIND_GENESIS + std::cout << "regtest genensis hash: " << genesis.GetHash().GetHex() << std::endl; + std::cout << "regtest hashmerkleroot: " << genesis.hashMerkleRoot.GetHex() << std::endl; +#else + assert(consensus.hashGenesisBlock == uint256S(REGTEST_GENESIS_HASH)); + assert(genesis.hashMerkleRoot == uint256S(GENESIS_MERKLE_ROOT)); +#endif vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. + fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; fRequireStandard = false; fMineBlocksOnDemand = true; + fTestnetToBeDeprecatedFieldRPC = false; checkpointData = { { - {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")}, + {0, uint256S(REGTEST_GENESIS_HASH)}, } }; diff --git a/src/chainparams.h b/src/chainparams.h index 722e52ff4..ad8bcafc2 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H +#include #include #include #include @@ -94,9 +95,11 @@ protected: std::string strNetworkID; CBlock genesis; std::vector vFixedSeeds; + bool fMiningRequiresPeers; bool fDefaultConsistencyChecks; bool fRequireStandard; bool fMineBlocksOnDemand; + bool fTestnetToBeDeprecatedFieldRPC; CCheckpointData checkpointData; ChainTxData chainTxData; bool m_fallback_fee_enabled; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index e9e8ce03b..bc4ea9d48 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -33,11 +33,11 @@ const CBaseChainParams& BaseParams() std::unique_ptr CreateBaseChainParams(const std::string& chain) { if (chain == CBaseChainParams::MAIN) - return MakeUnique("", 8332); + return MakeUnique("", 9246); else if (chain == CBaseChainParams::TESTNET) - return MakeUnique("testnet3", 18332); + return MakeUnique("testnet3", 19246); else if (chain == CBaseChainParams::REGTEST) - return MakeUnique("regtest", 18443); + return MakeUnique("regtest", 29246); else throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 355df043d..0031c21c5 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -44,6 +44,12 @@ std::unique_ptr CreateBaseChainParams(const std::string& chain */ void SetupChainParamsBaseOptions(); +/** + * Append the help messages for the chainparams options to the + * parameter string. + */ +void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true); + /** * Return the currently selected parameters. This won't change after app * startup, except for unit tests. @@ -53,4 +59,16 @@ const CBaseChainParams& BaseParams(); /** Sets the params returned by Params() to those for the given network. */ void SelectBaseParams(const std::string& chain); +/** + * Looks for -regtest, -testnet and returns the appropriate BIP70 chain name. + * @return CBaseChainParams::MAX_NETWORK_TYPES if an invalid combination is given. CBaseChainParams::MAIN by default. + */ +std::string ChainNameFromCommandLine(); + +/** + * Return true if SelectBaseParamsFromCommandLine() has been called to select + * a network. + */ +bool AreBaseParamsConfigured(); + #endif // BITCOIN_CHAINPARAMSBASE_H diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 4b982a471..91ad1df2c 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -8,1283 +8,11 @@ * IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly. */ static SeedSpec6 pnSeed6_main[] = { - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x84,0x64,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x01,0x61,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0xae,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x2d,0x4f,0x0e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x35,0x10,0x85}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x65,0x8b,0xa6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xb2,0x4e,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0xb0,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xe4,0x40,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x12,0x26,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0x73,0x60,0x3f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0x02,0x7c,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0e,0x03,0xaa,0x01}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x5e,0x1c,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x6f,0xac,0x6a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x7d,0xe0,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x98,0x00,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xaf,0x00,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe5,0x10,0xea}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xe9,0x06,0x46}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8e,0x22,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xab,0xcb,0x57}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xbc,0xc8,0xaa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xd8,0x41,0x29}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe3,0x45,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x21,0x0b,0xc1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x18,0x0b,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x1c,0x0a,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xa5,0x11,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xb3,0xcc,0x8e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xba,0x60,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd2,0xac,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xd3,0x66,0x81}, 62734}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x22,0xd9,0x7a,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xe6,0x40,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xe7,0xe1,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x24,0x03,0xac,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x24,0xfb,0xa3,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x88,0x61,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x99,0x01,0x96}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x99,0x01,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xe4,0x5c,0x6e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xfc,0x0e,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x1b,0x65,0xe0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x66,0x86,0x55}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x68,0xe1,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe5,0x4c,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x28,0x84,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x2d,0x22,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x30,0xb1,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x13,0x22,0xec}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0x42,0xc4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcd,0xa1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1e,0x2a,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x8a,0x8b,0xc3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa5,0xf5,0xdd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0x81,0x9b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa0,0x34}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa0,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x2c,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x7e,0x4a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa5,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa8,0xc9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x36,0xcc,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x4a,0x80,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x5e,0xe0,0x63}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x61,0x60,0xc6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xbb,0x24,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xda,0x10,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xdf,0x42,0xde}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfe,0x80,0x0f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x1f,0xaa,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x23,0x43,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x4c,0x60,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x52,0xb1,0x8e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x0f,0x03,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0xaf,0x8d,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0x90,0x2f,0x99}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xe8,0x26,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x26,0xc0,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x55,0x41,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0x5b,0xe3,0xbc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xb4,0x24,0x0e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3b,0x6a,0xd0,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3c,0x46,0x49,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0xa0,0xea,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2b,0xc6,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2d,0x00,0x0f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6b,0xc8,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x8a,0x03,0xe0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x92,0x46,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x4e,0xa3,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x78,0x6e,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0x83,0xa0,0x1f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x12,0xac,0x10}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x55,0x4a,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x6e,0x84,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x72,0x21,0x5a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xb4,0x40,0x5f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xde,0xa4,0xbc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x0b,0x8b,0x43}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x2b,0xbf,0x76}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0x3d,0x89,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xc1,0xb8,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd2,0xe4,0xcb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd7,0x0c,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xfd,0x48,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc9,0xe4,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xca,0x80,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x1e,0xda,0xe2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3d,0x23,0xaf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3d,0xab,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x7d,0xc2,0x19}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x23,0x62,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x67,0xab,0x42}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0xac,0xfc,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x22,0x60,0x87}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x44,0x30,0x95}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x5d,0xa1,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0xa2,0xc0,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0b,0xae,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x32,0xf0,0x7c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x46,0x20,0xd7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xd3,0xc4,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xea,0x70,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xfd,0xed,0x00}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0xf1,0xc0,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x0f,0xe6,0x70}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x53,0x4f,0x34}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x7e,0x0e,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x4c,0x89,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x40,0xa6,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xbf,0x4f,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x25,0xaa,0x6a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x46,0x6b,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x5f,0xe2,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x6f,0xac,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xa3,0x88,0x88}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xcb,0x0d,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xef,0x25,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf0,0xa8,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf4,0xdb,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1f,0x43,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x22,0x02,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6c,0xbb,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x6d,0xa3,0x99}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x1c,0xcd,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x42,0x46,0x59}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x84,0xe6,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd1,0xe0,0x4f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd3,0xfc,0x68}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xe5,0x1c,0x3c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0d,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x10,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x12,0xe0,0x3e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xab,0x1b,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xbb,0x50,0xdd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xd9,0x70,0xe1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xf5,0x8d,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x2b,0xab,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x66,0x0a,0xfb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0xea,0xb2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x90,0xc5,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa1,0x6d,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x66,0xe4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc1,0x6d,0xc7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd4,0x82,0x5e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd5,0xd0,0x10}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd9,0x43,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6c,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x85,0xae}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x37,0x82,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x4d,0x27,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x89,0x29,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x95,0x46,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x97,0xe9,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa2,0x2b,0x9a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa4,0x83,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xdd,0x0b,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf3,0x80,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x10,0x26,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x26,0x03,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x4b,0x1a,0xac}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc8,0x6a,0x80}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xfa,0xdb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd7,0x86,0xc3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf5,0x1b,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xfe,0x28,0x98}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xff,0xc1,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x0a,0x70,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5d,0x02,0x4c}, 54382}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x5e,0xac,0x21}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x81,0x00,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x91,0xa8,0x9f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xaa,0xee,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc3,0xe8,0xc5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x44,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xeb,0x89}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xda,0x30,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xdc,0xa5,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xe5,0x86,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf1,0x31,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x19,0x20,0x4d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x29,0x59,0xaa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x32,0x8f,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x3d,0x43,0xb7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x89,0x1a,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0xb1,0xc2,0xd7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x9d,0xb1,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe0,0xa3,0x42}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xec,0xc4,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xf6,0x2e,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x63,0x40,0x4c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x01,0x64,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x0a,0x9b,0x58}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x1b,0x3b,0xf6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xa3,0x84,0x49}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xb3,0xf0,0x83}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xcd,0x51,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0x4b,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd9,0x82,0x93}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xe6,0x60,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xf8,0xac,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x2e,0x39,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x6e,0x0b,0x65}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xf0,0x25,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0x04,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x41,0xc0,0x9f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x53,0xed,0xb9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6e,0x7d,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x79,0xa0,0x3b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x87,0x00,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x8f,0x6d,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc3,0x2a,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xdd,0x46,0x89}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x23,0x84,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x2a,0x25,0x8d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x36,0x10,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x3e,0x22,0xb8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xba,0xe7,0xf0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7b,0x50,0x2f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xaa,0x0d,0x0f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xab,0xc9,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb3,0xc5,0x98}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbe,0xce,0x97}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbf,0x83,0xb1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xd0,0x84,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x68,0x61,0xf7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9c,0x23,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc7,0xad,0x71}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x2a,0x02,0x71}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x5e,0xe1,0x3d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9a,0xed,0x18}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9e,0x27,0x40}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa3,0x47,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa3,0x6a,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd0,0xa3,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd5,0x8f,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xe2,0x4d,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x03,0x4a,0x42}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x17,0x80,0x41}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1b,0x08,0xf2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x1b,0x81,0x5e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x7e,0x64,0x94}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x4a,0x06,0x69}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x74,0xa0,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x07,0x40,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x0a,0x6a,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x19,0xc5,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x1d,0x07,0x67}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x7f,0x82,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe0,0xc0,0xc9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0xbe,0xac,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x23,0x97,0x4c}, 8334}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4a,0xc1,0x7f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x50,0x85,0xbf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x50,0xa8,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x63,0xa8,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xc2,0x2a,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xa8,0x65,0xcf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc8,0x43,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xcf,0x84,0x2a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xed,0x04,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x9b,0x48,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb7,0x25,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xaf,0x03,0x12}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xdc,0xc0,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x3d,0x66,0x05}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xce,0xb1,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xed,0x6f,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x44,0x2f,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0x58,0x4b,0x6e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x43,0xc9,0x28}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x1c,0x04,0xe6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x1c,0x82,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x1f,0x8f,0xa7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0xdc,0x0e,0x5c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0xdc,0x0e,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7c,0x12,0x85,0xdc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0xcf,0x27,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x4d,0x25,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x80,0x7d,0x64,0x02}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x9e,0x4a,0xed}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0xd5,0x20,0xb0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x71,0x29,0x77}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x71,0x29,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xe9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x28,0xbf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x2a,0x24}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x00,0x70,0x5c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x03,0x1a,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x17,0xc4,0x18}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x54,0xcf,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3b,0x81,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x3d,0xef,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0x75,0xa4,0x12}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x82,0x29,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x86,0x47,0xbc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xd5,0x06,0x39}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0xdf,0x52,0x8b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x00,0x82,0x31}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8e,0x00,0x82,0x35}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x76,0x8d,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x42,0x3a,0x92}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0x5f,0x82,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xbb,0x24,0xe9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x96,0xf9,0x4c,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0x81,0xbb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x7d,0xe0,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x30,0xec,0xfa}, 8887}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x42,0xcf,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x8f,0x8c,0xba}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x83,0x8e,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x40,0x4f,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x55,0x5d,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x8c,0x80,0xef}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xae,0x83,0xab}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x08,0x04,0x13}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xd9,0x90,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xd9,0x90,0xfc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x2f,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x9b,0x40,0xe2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xde,0x64,0x76}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0xa8,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xff,0xa8,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0x9e,0xe4,0x7d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0xe3,0x60,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0xe5,0xee,0x11}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x19,0xa5,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xab,0x21,0xb1,0x09}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x48,0xe4,0x5d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x60,0xa1,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x66,0xe4,0x96}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x76,0x88,0x62}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x2e,0x41,0x08}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd4,0xc1,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xef,0x21,0x55}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xf3,0x40,0x30}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x73,0x81,0x25}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0c,0x06,0x3b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6b,0xb8,0x1d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7b,0x0a,0xc0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7e,0xa7,0x0a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xb9,0xeb,0xa3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xdf,0x82,0xfe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x00,0x47,0x88}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x0c,0x20,0x27}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x55,0x40,0xd4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x7c,0xa2,0xd1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x80,0xc0,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x97,0x85,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xc1,0x60,0xc9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xf8,0xc8,0x7e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xfe,0x07,0x58}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0xe9,0x6a,0xab}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0xa6,0xa8,0xd2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x42,0xe3,0x46}, 12060}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x6f,0x6c,0x38}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x46,0x21,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x69,0x46,0x64}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x69,0x46,0x65}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0c,0x07,0x26}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x15,0xd8,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xb8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xd9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x3c,0xc7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x1c,0x4c,0xb3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x23,0x8b,0x36}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2c,0x4e,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x2f,0x84,0x37}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x33,0x80,0x1b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3b,0x64,0x6b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xaf,0x4b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xcc,0x4c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x43,0xcc,0x50}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x46,0x69,0x4a}, 8339}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x55,0x03,0x8c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x56,0x0f,0x17}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x56,0x0f,0x19}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x66,0x47,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x75,0x4a,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x79,0xad,0xdf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x80,0x28,0x7a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x91,0x83,0xda}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x93,0xed,0xa9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa2,0x80,0x53}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa5,0x4c,0xdc}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xac,0xa5,0x82}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb1,0x05,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb7,0x83,0x4b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xba,0xd0,0xd0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd7,0xe0,0x16}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe0,0x50,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe1,0x10,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf3,0x70,0xd6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf4,0xc1,0x12}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf8,0xa0,0x42}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xba,0x13,0x88,0x90}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x44,0x26,0xf3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x44,0xf0,0x59}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x06,0x54}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x4d,0x79}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x01,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd9,0x09,0xa8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x02,0x85,0x5b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xb8,0xc6,0x22}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd3,0xcc,0x44}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x8b,0x23,0x8f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0x64,0x9c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa2,0x65,0xfa}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xce,0xca,0x06}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcf,0x0c,0xf4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xcf,0x0c,0xf5}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe4,0x65,0x9d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x70,0xc0,0x49}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xaa,0xa6,0x0c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x0f,0xe7,0xec}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xa5,0x10,0x21}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xb5,0x50,0x4d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xba,0xa0,0xfd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf7,0x0d,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xf7,0x0d,0x20}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x00,0xcb,0x15}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x26,0xa8,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x2b,0x8d,0x1c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x5f,0xe1,0xf8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x7b,0xe0,0x07}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0xeb,0x4f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xa9,0x63,0x52}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xc9,0x00,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc5,0x9b,0x06,0x2b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x2c,0xe7,0xa0}, 6333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x3a,0x66,0x23}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x89,0xca,0xaf}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x7f,0xe0,0x32}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xb6,0x81,0x1a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xbc,0xcc,0x66}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xbc,0xcc,0x9b}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf4,0x31,0xe0}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf9,0xe6,0x25}, 15738}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x53,0x7b,0x2e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x6d,0x43,0x47}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x7a,0x80,0xb9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x99,0xc7,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x9f,0x88,0x36}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0xa8,0x10,0xe8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x0b,0x47,0x01}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xa2,0x50,0xdb}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0xb2,0x8f,0x0d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0f,0x0b,0x04}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7d,0xa9,0xa2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xae,0x37,0xa4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xb6,0x92,0x12}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x5d,0x42,0xc6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x62,0xc4,0xf9}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6b,0xe0,0xca}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6e,0x41,0x72}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x76,0xeb,0xbe}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7a,0xd0,0x83}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x7e,0x6e,0xc6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x83,0xee,0x50}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x38,0x6c,0x51}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x49,0x96,0x84}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x4d,0xe0,0x91}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x55,0x5a,0xc2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x5c,0x65,0x1e}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x70,0x85,0x5c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xe3,0x84,0xa7}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x0a,0x64,0xb6}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x39,0xf0,0x45}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x5b,0xcd,0x86}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x7d,0x43,0x6c}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x98,0xa1,0xaa}, 45893}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x9b,0x03,0xd8}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb4,0x46,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xb9,0xe2,0xe1}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x47,0xcb,0x4f}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xc2,0xa4,0xd3}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xf0,0xa8,0xe2}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x14,0x82,0x48}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x17,0x09,0xb4}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x40,0x2f,0x8a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xa9,0x0e,0x5a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0xf5,0x01,0xcd}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x82,0x80,0x3a}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x85,0x27,0x3d}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0x74}, 8333}, - {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xef,0xc1,0x78}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x1c,0xbd,0x3b,0xc0,0xad,0xe7,0xbf,0x44}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x20,0x46,0x15,0x0d,0x8d,0x65,0x0d,0xe4}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x2c,0x99,0x3f,0x36,0xd0,0x03,0xf4,0x7a}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x34,0xb6,0x39,0x10,0xa3,0xdc,0x7b,0xfa}, 8333}, - {{0x20,0x01,0x00,0x00,0x41,0x37,0x9e,0x76,0x3c,0xec,0x02,0xb5,0x52,0x5b,0xfb,0x3c}, 8333}, - {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x00,0xc5,0x23,0x5d,0xa1,0x0d,0x00,0xe0}, 8333}, - {{0x20,0x01,0x00,0x00,0x53,0xaa,0x06,0x4c,0x0c,0xbc,0x5a,0xce,0xa6,0x25,0x39,0xd1}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x38,0xe5,0x36,0xc1,0xd0,0xee,0x5d,0x98}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x3c,0x5c,0x0c,0x6c,0x39,0xcf,0x69,0xd3}, 8333}, - {{0x20,0x01,0x00,0x00,0x5e,0xf5,0x79,0xfb,0x08,0x96,0x0e,0xf4,0xba,0x63,0x8d,0x15}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x10,0x6a,0x21,0x12,0xe0,0x6b,0xb8,0x81}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x1c,0x99,0x16,0x55,0xe7,0x82,0x93,0x40}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x20,0xcd,0x1c,0xd9,0x54,0xe6,0x5a,0x6e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x24,0x5e,0x02,0xb3,0xa3,0x00,0x31,0x7e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x28,0x14,0x21,0x5c,0x88,0xe3,0x4e,0xe0}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x30,0xac,0x3a,0x51,0xb2,0xda,0x71,0x2d}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x34,0xa6,0x0e,0xeb,0xc3,0xed,0x5b,0xe7}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0x2f,0x16,0xd5,0x52,0x5a,0x10,0x7e}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xb8,0x0c,0xb1,0x25,0x57,0x43,0x1c,0xf3,0xe1}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x10,0x56,0x29,0x0d,0xa6,0x71,0x3d,0x90}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x18,0x65,0x14,0xfe,0xd0,0xa7,0x1f,0x72}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x3c,0x30,0x06,0xa4,0x86,0x93,0xc3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x2c,0x73,0x33,0x13,0xf2,0x1a,0x96,0xda}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x30,0x50,0xfb,0xff,0xa2,0x50,0x33,0x86}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x38,0x28,0x04,0x94,0xfd,0xaa,0x56,0xcd}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x6a,0xbd,0x04,0x54,0x18,0x7d,0x3e,0x75,0xb0,0x0b}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x78,0xcf,0x0c,0x2c,0x1d,0xcc,0xfa,0x42,0x41,0xa3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0x4a,0x20,0xd4,0x4d,0xaa,0xeb,0x5a}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x1c,0xa7,0x16,0x12,0x9a,0x18,0x31,0xe5}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x24,0xc8,0x3a,0x0a,0xa6,0x8d,0xf7,0x99}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0x37,0x32,0x4e,0xd0,0xcb,0x9f,0x45}, 22475}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x28,0xc1,0x36,0x1e,0xa6,0x9c,0xb0,0x99}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x30,0xfe,0x1c,0x89,0xd0,0xb4,0x4d,0x18}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0x74,0x1d,0xf1,0xe7,0x32,0xe5,0xe3}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x34,0xa8,0x0f,0xb1,0x88,0xe3,0xfb,0x19}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x19,0x3d,0x23,0xd0,0xb4,0xf8,0x31}, 18652}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x45,0x23,0x42,0xd0,0xcb,0xd6,0xca}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x3c,0x5f,0x31,0x05,0xd0,0xb4,0x60,0xb6}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x08,0xa1,0x02,0xfb,0xd0,0xcb,0x1e,0x8f}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0xa3,0x36,0xe0,0xe0,0x20,0x53,0xfa}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x90,0xd7,0x00,0xeb,0x3b,0x30,0xd0,0xa4,0x0a,0xa5}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x10,0x4e,0x08,0xaf,0xb3,0xaa,0xf3,0x00}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x14,0x34,0x07,0x1f,0xb8,0x50,0xba,0xb1}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x14,0x4a,0x36,0xe8,0x51,0x9a,0xbb,0x69}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x20,0xfc,0x26,0xef,0xed,0x26,0xc7,0x37}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x04,0x54,0x01,0x20,0x88,0xe8,0x02,0xfb}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0x01,0x16,0x20,0xbc,0x22,0x95,0xbc}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x08,0xa0,0x1f,0xdb,0xab,0x00,0x0b,0xc2}, 8333}, - {{0x20,0x01,0x00,0x00,0x9d,0x38,0x95,0x3c,0x0c,0xf6,0x3d,0x48,0x43,0x86,0x49,0x37}, 8333}, - {{0x20,0x01,0x13,0xd8,0x1c,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333}, - {{0x20,0x01,0x16,0x20,0x09,0x23,0x00,0x00,0x75,0xbe,0xed,0x92,0x1a,0x01,0x06,0x41}, 8333}, - {{0x20,0x01,0x16,0x80,0x01,0x01,0x00,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x19,0x70,0x5a,0xe2,0x2b,0x00,0x30,0xbd,0x79,0x10,0x0c,0x84,0x7a,0x8f}, 8333}, - {{0x20,0x01,0x19,0x70,0x5d,0x56,0xaa,0x01,0x1e,0x75,0x08,0xff,0xfe,0xad,0xda,0x48}, 8333}, - {{0x20,0x01,0x19,0xf0,0x03,0x00,0x10,0x45,0x02,0x25,0x90,0xff,0xfe,0xc9,0x29,0xb3}, 8333}, - {{0x20,0x01,0x19,0xf0,0x00,0x05,0x1f,0x93,0x54,0x00,0x01,0xff,0xfe,0x7a,0xc6,0x5a}, 8333}, - {{0x20,0x01,0x19,0xf0,0x6c,0x01,0x04,0xbd,0x54,0x00,0x01,0xff,0xfe,0x76,0x4d,0xb6}, 8333}, - {{0x20,0x01,0x19,0xf0,0xac,0x01,0x02,0xfb,0x54,0x00,0x00,0xff,0xfe,0x5b,0xc3,0xff}, 8333}, - {{0x20,0x01,0x1a,0x48,0x00,0x07,0xaf,0x1a,0x75,0xf8,0x2c,0x47,0x32,0x85,0xd5,0x0e}, 8333}, - {{0x20,0x01,0x1a,0xf8,0x40,0x10,0xa0,0x94,0x33,0x33,0x00,0x00,0x00,0x00,0x8c,0x38}, 8333}, - {{0x20,0x01,0x1a,0xf8,0x40,0x70,0xa0,0x16,0x33,0x33,0x00,0x00,0x00,0x00,0x5a,0xfb}, 8333}, - {{0x20,0x01,0x1a,0xf8,0x47,0x00,0xa0,0x71,0x44,0x44,0x00,0x00,0x00,0x00,0xe2,0x6e}, 8333}, - {{0x20,0x01,0x02,0x00,0x00,0x00,0x88,0x01,0x50,0x54,0x00,0xff,0xfe,0xf2,0x01,0xd0}, 8333}, - {{0x20,0x01,0x41,0x28,0x61,0x35,0x20,0x10,0x02,0x1e,0x0b,0xff,0xfe,0xe8,0xa3,0xc0}, 8333}, - {{0x20,0x01,0x41,0xd0,0x10,0x00,0x1f,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x10,0x04,0x18,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x10,0x04,0x19,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 18555}, - {{0x20,0x01,0x41,0xd0,0x10,0x04,0x1f,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x10,0x08,0x2b,0xed,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x45,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x53,0x95,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x85,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x86,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0x8b,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xa5,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xab,0x6b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xd2,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf8,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x01,0xf9,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x34,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x49,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x5c,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0x84,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xab,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x02,0xc3,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x19,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x25,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x41,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 58333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x4c,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x05,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x67,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x03,0x03,0x68,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x06,0x02,0x17,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x06,0x02,0x18,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x06,0x02,0x03,0xb7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x06,0x02,0x08,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x06,0x02,0x0b,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x08,0x00,0x01,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x08,0x00,0x03,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x10,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x1b,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x3f,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x43,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xbb,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xbe,0xd3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xc6,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xca,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xd4,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0x0d,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x08,0xea,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x12,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x27,0xed,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x29,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8139}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x2b,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x40,0x5c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x42,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8312}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x4c,0x49,0x00,0x00,0x00,0x00,0x0a,0xca,0x79,0x29}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x69,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x69,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6a,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0x6c,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf2,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0a,0xf9,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0d,0x0d,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x11,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x01,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x12,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x13,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xd0,0x00,0x0e,0x0e,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x41,0xf0,0x00,0x00,0x00,0x04,0x00,0x62,0x69,0x74,0x63,0x6f,0x69,0x6e}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x18,0x0b,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1c,0x62,0xb1,0x70,0xbb,0xff,0x53,0xf1,0xed,0xbf,0x99,0xdf}, 42434}, - {{0x20,0x01,0x04,0x70,0x1f,0x06,0x15,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x06,0x0c,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x07,0x08,0x03,0x02,0x0c,0x29,0xff,0xfe,0x2d,0x58,0x79}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x08,0x03,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x0a,0x18,0xdd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x15,0x11,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x15,0x0c,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x17,0x00,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x1a,0x01,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x1f,0x1b,0x05,0xa6,0x02,0x16,0x3e,0xff,0xfe,0x24,0x11,0x62}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x28,0x03,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x41,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x6c,0x80,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x04,0x70,0x6c,0x80,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x07,0x06,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x07,0x0b,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x08,0x0b,0xd3,0x4d,0x25,0xca,0x57,0xa5,0xb7,0xc6,0xc4}, 8333}, - {{0x20,0x01,0x04,0x70,0x00,0x0a,0x0c,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0xc1,0x44,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23}, 8333}, - {{0x20,0x01,0x04,0x70,0xc3,0xc4,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x02}, 8333}, - {{0x20,0x01,0x04,0x70,0xe6,0x96,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x48,0xf8,0x10,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xba}, 8333}, - {{0x20,0x01,0x48,0xf8,0x90,0x15,0x14,0x22,0x3d,0xc0,0xfc,0xf2,0x77,0x2f,0x57,0xbc}, 8333}, - {{0x20,0x01,0x4b,0xa0,0xba,0xbe,0x08,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x06,0x28,0x22,0xa0,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12}, 8333}, - {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91}, 8333}, - {{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x42,0x00,0x00,0x00,0x00,0xff,0x10,0xbe,0xd6}, 8333}, - {{0x20,0x01,0x06,0x7c,0x21,0xec,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333}, - {{0x20,0x01,0x08,0xd8,0x09,0x0b,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x2f,0xc0}, 8333}, - {{0x20,0x01,0x08,0xd8,0x09,0x1c,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0xd4,0x25}, 8333}, - {{0x20,0x01,0x09,0x80,0x23,0x1b,0x00,0x01,0x8e,0x89,0xa5,0xff,0xfe,0xe3,0xf8,0xbe}, 8333}, - {{0x20,0x01,0x09,0x80,0xad,0xe8,0x00,0x01,0x14,0xfc,0xfd,0x6d,0x60,0x8c,0xf6,0x69}, 8333}, - {{0x20,0x01,0x09,0x81,0xbd,0xbd,0x00,0x01,0xc5,0x06,0x7d,0x38,0x4b,0x47,0xda,0x15}, 8333}, - {{0x20,0x01,0x09,0x82,0x27,0xf2,0x00,0x01,0x72,0x71,0xbc,0xff,0xfe,0x94,0xd5,0xbb}, 8333}, - {{0x20,0x01,0x09,0x84,0x26,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x09,0x84,0xae,0xc7,0x00,0x01,0xdc,0xb7,0x02,0x9a,0x7e,0xda,0xb9,0xa2}, 8333}, - {{0x20,0x01,0x09,0x85,0x79,0xaf,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35}, 8333}, - {{0x20,0x01,0x09,0x85,0xcb,0x69,0x00,0x00,0x02,0x0c,0x29,0xff,0xfe,0xaf,0xdd,0x5e}, 8333}, - {{0x20,0x01,0xb0,0x11,0x30,0x0d,0x18,0x70,0x9c,0x87,0xd4,0xff,0xfe,0x9c,0x2d,0x0f}, 8333}, - {{0x20,0x01,0xb0,0x30,0x24,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x31,0xd7,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x32,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x33,0xac,0x19,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x39,0x9f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x3d,0xc1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x42}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x3b}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x44,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x35}, 8333}, - {{0x20,0x01,0x0b,0xc8,0x47,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x23}, 8333}, - {{0x20,0x01,0x0d,0xa8,0x80,0x01,0x23,0x03,0x1c,0xf4,0x44,0x66,0x3f,0x1a,0x7e,0xdb}, 8333}, - {{0x20,0x01,0x0d,0xa8,0xd8,0x00,0x07,0x41,0x65,0x2d,0x52,0xdb,0x57,0x13,0x45,0x15}, 8333}, - {{0x20,0x02,0x17,0xe5,0x10,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xe5,0x10,0xea}, 8333}, - {{0x20,0x02,0x1f,0x2b,0x8c,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x2b,0x8c,0xbe}, 8333}, - {{0x20,0x02,0x2f,0x59,0x30,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x59,0x30,0xf3}, 8333}, - {{0x20,0x02,0x2f,0x5a,0x56,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5a,0x56,0x2a}, 8333}, - {{0x20,0x02,0x3e,0x92,0x46,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x92,0x46,0xd8}, 8333}, - {{0x20,0x02,0x3f,0x62,0xe6,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x62,0xe6,0xbb}, 8333}, - {{0x20,0x02,0x40,0x4e,0xa3,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x4e,0xa3,0x0a}, 8333}, - {{0x20,0x02,0x43,0xdb,0x96,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xdb,0x96,0x16}, 8333}, - {{0x20,0x02,0x43,0xe5,0xa1,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xe5,0xa1,0xfa}, 8333}, - {{0x20,0x02,0x52,0x66,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x66,0x0a,0xfb}, 8333}, - {{0x20,0x02,0x5d,0xbd,0x91,0xa9,0x00,0x00,0x00,0x00,0x00,0x00,0x5d,0xbd,0x91,0xa9}, 8333}, - {{0x20,0x02,0x62,0x7e,0x33,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x7e,0x33,0x3d}, 8333}, - {{0x20,0x02,0x6b,0x9b,0x48,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0x9b,0x48,0x6c}, 8333}, - {{0x20,0x02,0x6d,0xcb,0x7c,0xba,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0xcb,0x7c,0xba}, 8333}, - {{0x20,0x02,0x7c,0xf8,0xe3,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x7c,0xf8,0xe3,0x3e}, 8333}, - {{0x20,0x02,0x8e,0x00,0x82,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x00,0x82,0x31}, 8333}, - {{0x20,0x02,0x8e,0x00,0x82,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0x00,0x82,0x33}, 8333}, - {{0x20,0x02,0xb0,0x7e,0xa7,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x7e,0xa7,0x0a}, 8333}, - {{0x20,0x02,0xb2,0xc9,0xe6,0xfc,0x00,0x10,0x3d,0x5c,0xe3,0xad,0x08,0x13,0x9c,0x46}, 8333}, - {{0x20,0x02,0xb4,0xb2,0x36,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0xb2,0x36,0x12}, 8333}, - {{0x20,0x02,0xb6,0x10,0x1c,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa2}, 8333}, - {{0x20,0x02,0xb6,0x10,0x1c,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa3}, 8333}, - {{0x20,0x02,0xb8,0x45,0x33,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x20,0x02,0xb9,0x46,0x69,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x46,0x69,0x4a}, 8339}, - {{0x20,0x02,0xb9,0x60,0x5e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xb9,0x60,0x5e,0x18}, 8333}, - {{0x20,0x02,0xc2,0x3f,0x8f,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x3f,0x8f,0xc5}, 8333}, - {{0x20,0x02,0xc2,0xa5,0x10,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa5,0x10,0x21}, 8333}, - {{0x20,0x02,0xc6,0x2c,0xe7,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0x2c,0xe7,0xa0}, 6333}, - {{0x20,0x02,0xca,0x99,0xc7,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x99,0xc7,0xb6}, 8333}, - {{0x20,0x02,0xd0,0x35,0x27,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x35,0x27,0x34}, 8333}, - {{0x20,0x02,0xd0,0x6e,0x5d,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x6e,0x5d,0x1a}, 8333}, - {{0x20,0x02,0xd8,0xda,0xb9,0x49,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0xda,0xb9,0x49}, 8333}, - {{0x24,0x00,0x24,0x10,0xa9,0x60,0x48,0x00,0x18,0xbe,0xd6,0x24,0x70,0x18,0xcd,0x2f}, 8333}, - {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0xe1,0xb0,0x01}, 8333}, - {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x5c,0xd2,0xa0,0x01}, 8333}, - {{0x24,0x00,0x61,0x80,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x04,0xc6,0x80,0x01}, 8333}, - {{0x24,0x00,0x61,0x80,0x01,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x07,0x97,0xa0,0x01}, 8333}, - {{0x24,0x00,0x85,0x00,0x13,0x02,0x08,0x17,0x01,0x50,0x00,0x95,0x01,0x30,0x00,0x17}, 8333}, - {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x06,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x18,0x79}, 8333}, - {{0x24,0x01,0x39,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x24,0x01,0xa4,0x00,0x32,0x00,0x56,0x00,0x3c,0x16,0x2d,0xeb,0xab,0xce,0x70,0xcd}, 8333}, - {{0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x01,0x00}, 8333}, - {{0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x01,0x02}, 8333}, - {{0x24,0x02,0x1f,0x00,0x81,0x00,0x02,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x24,0x03,0xbd,0x80,0xc0,0x00,0x00,0x01,0x01,0x03,0x02,0x02,0x02,0x16,0x01,0x82}, 8333}, - {{0x24,0x05,0x65,0x80,0xc5,0xc0,0x17,0x00,0x6c,0xd2,0xb7,0x2e,0x74,0x0e,0x43,0x11}, 8333}, - {{0x24,0x05,0x08,0x00,0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x20,0x01}, 8333}, - {{0x24,0x05,0x98,0x00,0xb5,0x60,0x09,0x6d,0x06,0x30,0xc2,0x8e,0xa7,0x9a,0xa1,0x82}, 8333}, - {{0x24,0x05,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333}, - {{0x24,0x09,0x00,0x10,0xca,0x20,0x1d,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x26,0x9a,0x34,0x52,0x2e,0xdf,0x10,0x11}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0x07,0xbc,0x58,0x79,0x44,0x63,0x15,0xdd}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa2,0x8b,0x5a,0x16,0x84,0x9c,0xfe,0x41}, 8333}, - {{0x26,0x00,0x1f,0x16,0x06,0x25,0x0e,0x00,0xa7,0x0f,0xe7,0x28,0xe8,0xe1,0x2c,0x2e}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x0c,0x4d,0x74}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x2b,0xbf,0x38}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x3e,0x49}, 8333}, - {{0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xb6,0x19,0xf2}, 8333}, - {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x91,0x6a,0x29}, 8333}, - {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xd8,0x85,0xa2}, 8333}, - {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xd8,0xdb,0x38}, 8333}, - {{0x26,0x00,0x3c,0x03,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0x28,0x14,0x45}, 8333}, - {{0x26,0x01,0x01,0x47,0x43,0x00,0x0e,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0c}, 8333}, - {{0x26,0x01,0x01,0x47,0x43,0x00,0x0e,0x61,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x91}, 8333}, - {{0x26,0x01,0x01,0x86,0xc1,0x00,0x6b,0xcd,0x16,0xbd,0xce,0xa1,0x23,0x5d,0x1c,0x19}, 8333}, - {{0x26,0x01,0x01,0x8d,0x46,0x00,0x5f,0x32,0x20,0xe7,0xb3,0xff,0xfe,0xcf,0x0a,0x99}, 8333}, - {{0x26,0x01,0x02,0x40,0x46,0x01,0xec,0xee,0x30,0x9a,0xf9,0xde,0xb6,0x4d,0x87,0xdf}, 8333}, - {{0x26,0x01,0x02,0x40,0x81,0x00,0x25,0x6b,0x02,0x0c,0x29,0xff,0xfe,0x5e,0xd7,0x07}, 8333}, - {{0x26,0x01,0x06,0x46,0xc2,0x02,0x53,0x01,0x10,0x1b,0xa0,0x96,0xef,0xba,0xc1,0x0a}, 8333}, - {{0x26,0x01,0x08,0x07,0x80,0x00,0x95,0x08,0x99,0x93,0xd2,0xb3,0x00,0x1a,0x82,0x25}, 8333}, - {{0x26,0x01,0x00,0xc8,0x41,0x00,0x07,0x70,0x0c,0x37,0x80,0x7b,0x98,0xcc,0xbd,0x7e}, 8333}, - {{0x26,0x02,0x01,0x00,0x61,0x54,0xd6,0xe3,0x2c,0x91,0xd0,0xde,0xb0,0x32,0xb0,0xa4}, 8333}, - {{0x26,0x02,0x01,0x00,0x61,0x54,0xd6,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60}, 8333}, - {{0x26,0x02,0x00,0x61,0x78,0x6c,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x02,0xff,0x83,0x0f,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75}, 8333}, - {{0x26,0x02,0xff,0x83,0x0f,0xff,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76}, 8333}, - {{0x26,0x03,0x30,0x05,0x30,0x00,0x50,0x00,0xbc,0x5a,0x72,0xac,0x36,0xe9,0x17,0x5e}, 8333}, - {{0x26,0x04,0x00,0x00,0x00,0xc1,0x01,0x00,0x6b,0xc1,0xf9,0x8a,0x97,0xf9,0x38,0x45}, 8333}, - {{0x26,0x04,0x2d,0x80,0xc8,0x08,0x85,0x7b,0x08,0xd6,0x9e,0x1c,0x71,0x31,0x4b,0xea}, 8333}, - {{0x26,0x04,0x40,0x80,0x10,0x08,0x00,0x00,0x96,0xde,0x80,0xff,0xfe,0x62,0xe6,0x50}, 8333}, - {{0x26,0x04,0x43,0x00,0x00,0x0a,0x01,0x04,0xb6,0x99,0xba,0xff,0xfe,0xaa,0x51,0x09}, 8333}, - {{0x26,0x04,0x55,0x00,0xc2,0x26,0x7f,0x00,0x2d,0x96,0xed,0x64,0xce,0x45,0x09,0xa6}, 8333}, - {{0x26,0x04,0x8d,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xf3,0x40,0x30}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf8,0xe0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf8,0xf0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x00,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0x10,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xc0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xd0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xf9,0xe0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x10,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x20,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x22,0xfa,0x30,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x38,0xf0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x06,0x62,0xc0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x1a,0xc4,0xb0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x40,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x50,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0x60,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xd0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x04,0xe0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x00,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x20,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x20,0x05,0x30,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x0c,0xd7,0x40,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x07,0x29,0xb0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x11,0xa9,0x80,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,0x59,0x90,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x0c,0xbb,0xf0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x08,0x00,0x00,0xa1,0x00,0x00,0x00,0x00,0x0e,0xe8,0xe0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0x70,0xf0,0x01}, 8333}, - {{0x26,0x04,0xa8,0x80,0x0c,0xad,0x00,0xd0,0x00,0x00,0x00,0x00,0x0a,0x52,0x60,0x01}, 8333}, - {{0x26,0x05,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333}, - {{0x26,0x05,0x98,0x80,0x00,0x00,0x01,0xcf,0x02,0x25,0x90,0xff,0xfe,0xc9,0x29,0xb3}, 8333}, - {{0x26,0x05,0x98,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x33}, 8333}, - {{0x26,0x05,0x98,0x80,0x02,0x01,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x7c}, 8333}, - {{0x26,0x05,0xa0,0x00,0x4a,0x87,0x95,0x01,0xd6,0x13,0xfb,0xf8,0x1e,0x82,0x8d,0x3c}, 8333}, - {{0x26,0x05,0xa0,0x00,0xf3,0x43,0xb7,0x00,0x50,0x54,0x00,0xff,0xfe,0xa7,0x01,0x31}, 8333}, - {{0x26,0x05,0xa6,0x01,0x0a,0x41,0x1a,0x00,0x0a,0x00,0x27,0xff,0xfe,0xfc,0x47,0x59}, 8333}, - {{0x26,0x05,0xae,0x00,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03}, 8333}, - {{0x26,0x05,0xc0,0x00,0x2a,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333}, - {{0x26,0x05,0xe0,0x00,0x1c,0x00,0x80,0xe8,0x98,0x4e,0xa6,0x97,0x97,0xa3,0x50,0xed}, 8333}, - {{0x26,0x05,0xe0,0x00,0x1c,0x0d,0x43,0x7b,0x50,0x54,0x00,0xff,0xfe,0x1b,0x29,0x13}, 8333}, - {{0x26,0x05,0xe0,0x00,0x90,0x93,0xa7,0x00,0x98,0x53,0x44,0x64,0x5f,0x78,0xc4,0x84}, 8333}, - {{0x26,0x05,0xf7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x10,0x4e,0x43,0xbd}, 8333}, - {{0x26,0x05,0xf7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x31,0x5b,0x54}, 8333}, - {{0x26,0x05,0xf7,0x00,0x01,0x00,0x0c,0x10,0x55,0x75,0x8e,0x73,0xb0,0x7c,0xbf,0x5a}, 8333}, - {{0x26,0x06,0x60,0x00,0xc1,0x49,0x88,0x30,0x50,0x54,0x00,0xff,0xfe,0x78,0x66,0xff}, 8333}, - {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x3c,0x1c,0x1b,0x0d,0x0b,0xa4,0x8e,0xa9}, 8333}, - {{0x26,0x07,0x1c,0x00,0x00,0x0a,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x01,0x20,0x0a,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x02,0x03,0x2f,0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x02,0x03,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x02,0x03,0x06,0xbc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 18333}, - {{0x26,0x07,0x53,0x00,0x02,0x03,0x00,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x10,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x12,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x13,0xbb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x3d,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x57,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x07,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0x09,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x26,0x07,0x53,0x00,0x00,0x60,0xcf,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 28633}, - {{0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0xbf,0x32}, 8333}, - {{0x26,0x07,0xf1,0x78,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06}, 8333}, - {{0x26,0x07,0xf1,0xc0,0x08,0x23,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0xbb,0xd1}, 8333}, - {{0x26,0x07,0xf2,0xc0,0xf0,0x0e,0x03,0x00,0x02,0x01,0x2e,0xff,0xfe,0x67,0x91,0x30}, 8333}, - {{0x26,0x07,0xfa,0x18,0x00,0x00,0xbe,0xef,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x12}, 8333}, - {{0x26,0x07,0xff,0x28,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x17,0x6e,0xc4,0xa5}, 8333}, - {{0x26,0x07,0xff,0x28,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x65,0xaf,0x9a,0xfb}, 8333}, - {{0x26,0x20,0x00,0x71,0x40,0x00,0x00,0x00,0x01,0x92,0x00,0x30,0x01,0x20,0x01,0x10}, 8333}, - {{0x28,0x01,0x00,0x84,0x00,0x00,0x10,0x34,0x76,0xd4,0x35,0xff,0xfe,0x7f,0x50,0x33}, 8333}, - {{0x28,0x03,0x15,0x00,0x12,0x00,0xc4,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x28,0x04,0x01,0x4c,0x65,0x82,0x60,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x28,0x04,0x01,0x4d,0xba,0xa6,0x96,0x2c,0x04,0x86,0x47,0xf6,0xc1,0x61,0xa7,0x9d}, 8333}, - {{0x2a,0x00,0x13,0xa0,0x30,0x15,0x00,0x01,0x00,0x85,0x00,0x14,0x00,0x79,0x00,0x26}, 8333}, - {{0x2a,0x00,0x16,0xd8,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0x6a,0xc2,0x61}, 8333}, - {{0x2a,0x00,0x17,0x68,0x20,0x01,0x00,0x24,0x00,0x00,0x00,0x00,0x01,0x48,0x02,0x18}, 8333}, - {{0x2a,0x00,0x18,0x38,0x00,0x36,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0xed,0x85}, 8333}, - {{0x2a,0x00,0x1a,0x28,0x11,0x57,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x6a}, 8333}, - {{0x2a,0x00,0x1c,0x48,0x00,0x06,0x02,0x03,0x0a,0x60,0x6e,0xff,0xfe,0x44,0x80,0x86}, 8333}, - {{0x2a,0x00,0x1f,0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x26}, 8333}, - {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x0e}, 8333}, - {{0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21}, 8333}, - {{0x2a,0x00,0xab,0x00,0x06,0x03,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333}, - {{0x2a,0x00,0xbb,0xe0,0x00,0xcc,0x00,0x00,0x66,0x51,0x06,0xff,0xfe,0x0e,0x94,0x18}, 8333}, - {{0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x30,0x25,0x41,0x21,0x5c,0xa1,0x00,0x3b,0x44,0x69}, 8333}, - {{0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x90,0x91,0x94,0x5e,0x80,0xa3,0x83,0x0a,0x78,0xcf}, 8333}, - {{0x2a,0x01,0x02,0x38,0x43,0x3c,0x53,0x00,0x7a,0x61,0x3e,0x1a,0x27,0xf4,0x9d,0xc2}, 8333}, - {{0x2a,0x01,0x42,0x40,0x0a,0x21,0x98,0x3b,0x00,0x00,0x00,0x00,0xc0,0xa8,0x00,0x32}, 8333}, - {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x53,0xa9,0x21,0xb8,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x4d,0x60,0x00,0x03,0x00,0x01,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0a,0x35,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x03,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0d,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x0b,0x0f,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x13,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x70,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x93,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x21,0x23,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x71,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x30,0x74,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x12,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x1d,0xcb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 21775}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3a,0x07,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x10,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x1a,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x01}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x27,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 10731}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x2d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x2d,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x3d,0xa8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x41,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x42,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x05,0xc7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x3b,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x23,0x6a,0xca,0xfe,0x00,0x00,0x00,0x00,0x00,0x05}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x32,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x53,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x53,0x29,0x00,0x00,0x00,0x00,0x00,0x50,0x01,0x09}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x93,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x40,0x93,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x41,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x53,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x50,0x72,0xee,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x41,0xf0,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x33}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x44,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x60,0x92,0xd7,0xbd,0x0a,0x39,0x3e,0x52,0xb6,0x5d}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x60,0xaa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x60,0x63,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x60,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x61,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x61,0x81,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x02,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x62,0x33,0xac,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x01,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x2b,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x32,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x04,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0d,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0e,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x71,0x0e,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x72,0x18,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x73,0x16,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x50,0xb6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x90,0x51,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x23}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x91,0x02,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x21,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x62,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x83}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x1c,0x0c,0x77,0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x10,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x00,0x44,0x2d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x11,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x04,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x53,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x80,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x37}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x01,0x80,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x02,0x32,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x03,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x11,0x0f,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x12,0x1e,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 15000}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x2e,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x2f,0xcf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x34,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x34,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x39,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8335}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x3c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x3c,0x82,0xfe,0xa1,0x00,0x00,0x00,0x00,0x06,0x66}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x06,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x02,0x21,0x0f,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x00,0xa0,0x61,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x42,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x0c,0x56,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf8,0x0c,0x17,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x10,0xd4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x18,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x19,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x1c,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x25,0x85,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x26,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x2d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x2d,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x03,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x06,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0x00,0x2a,0x0d,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x01,0x04,0xf9,0xc0,0x10,0x12,0xe7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x04,0xf9,0xc0,0x10,0x17,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x01,0x5d,0x00,0x00,0x01,0x04,0xb6,0xd2,0xbf,0x9c,0xff,0xfe,0x45,0xb8,0x34}, 8333}, - {{0x2a,0x01,0x07,0x9c,0xce,0xbe,0x70,0xcc,0x1a,0x03,0x73,0xff,0xfe,0x48,0xe6,0x91}, 8333}, - {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333}, - {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x18,0x0e,0xc4,0x7a,0xff,0xfe,0x83,0x83,0xc4}, 8333}, - {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x12,0x88,0xea,0x39,0x35,0xff,0xfe,0xf0,0xc4,0x29}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xaa,0xba,0x00,0x18,0x50,0x54,0x00,0xff,0xfe,0x2b,0xdf,0x20}, 8333}, - {{0x2a,0x01,0x07,0xc8,0xff,0xfa,0x05,0x0e,0x30,0x35,0x74,0x1b,0xbe,0x02,0xb5,0xde}, 8333}, - {{0x2a,0x01,0xbe,0x00,0x00,0x10,0x02,0x01,0x00,0x00,0x00,0x80,0xce,0xce,0x00,0x01}, 8333}, - {{0x2a,0x01,0xcb,0x00,0x05,0xbe,0xd5,0x00,0x02,0x27,0x0e,0xff,0xfe,0x28,0xc5,0x65}, 8333}, - {{0x2a,0x01,0xcb,0x00,0x00,0xb3,0xd3,0x00,0x92,0x76,0x8a,0x8c,0x74,0xbf,0x2a,0x88}, 8333}, - {{0x2a,0x01,0xcb,0x14,0x00,0xb8,0xa5,0x00,0xdd,0x9d,0x80,0xf5,0xd3,0x05,0x68,0xf9}, 8333}, - {{0x2a,0x01,0x0e,0x0a,0x00,0x20,0x91,0x20,0x7c,0x3f,0x56,0x43,0x99,0x78,0x18,0x25}, 8333}, - {{0x2a,0x01,0x0e,0x0a,0x00,0x0d,0x6e,0xa0,0x00,0x56,0xde,0xab,0x1b,0x2f,0x30,0x0b}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xec,0x16,0x93,0xf0,0x72,0x5d,0xd8,0xd2,0xbb,0x90,0xea,0xbf}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xee,0x33,0x16,0x40,0xc4,0x18,0x3c,0x3a,0x8f,0xf6,0x3e,0xab}, 8333}, - {{0x2a,0x01,0x0e,0x34,0xee,0xd7,0x66,0x70,0x28,0xc0,0x18,0x3c,0x77,0x83,0x7d,0xc3}, 8333}, - {{0x2a,0x01,0x0e,0x35,0x2f,0x7d,0xa0,0xb0,0x59,0xc2,0x3c,0x8a,0x95,0xa2,0xc4,0xd1}, 8333}, - {{0x2a,0x01,0x0e,0x35,0x87,0xba,0xd0,0xc0,0x75,0xa2,0x9f,0x39,0xef,0xcb,0xf5,0x9f}, 8333}, - {{0x2a,0x02,0x12,0x0b,0xc3,0xc5,0xce,0xf0,0xec,0x82,0xa4,0x3d,0x04,0xd6,0x0d,0xc2}, 8333}, - {{0x2a,0x02,0x12,0x0b,0xc3,0xd1,0xf2,0xd0,0xee,0xa8,0x6b,0xff,0xfe,0xfc,0x22,0x65}, 8333}, - {{0x2a,0x02,0x01,0x68,0x40,0x4c,0x00,0x00,0xee,0xa8,0x6b,0xff,0xfe,0xf3,0x7d,0x5c}, 8333}, - {{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x05,0x17,0x10,0xb6}, 8333}, - {{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x5b,0x8f,0x53,0x8c}, 8333}, - {{0x2a,0x02,0x01,0xb8,0x00,0x10,0x01,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x02,0x21,0x68,0x0d,0x05,0x2c,0x00,0x02,0x16,0x3e,0xff,0xfe,0xf7,0xa0,0x99}, 8333}, - {{0x2a,0x02,0x25,0x28,0x05,0x03,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14}, 8333}, - {{0x2a,0x02,0x25,0x28,0x00,0xfa,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x27,0x70,0x00,0x17,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x7b,0x17,0x5f}, 8333}, - {{0x2a,0x02,0x27,0x70,0x00,0x05,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x44,0x83,0x70}, 8333}, - {{0x2a,0x02,0x28,0x08,0x54,0x01,0x00,0x00,0x02,0x25,0x90,0xff,0xfe,0x4e,0xee,0x42}, 8333}, - {{0x2a,0x02,0x03,0x90,0x90,0x00,0x00,0x00,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333}, - {{0x2a,0x02,0x07,0x50,0x00,0x07,0x0c,0x11,0x50,0x54,0x00,0xff,0xfe,0x43,0xeb,0x81}, 8333}, - {{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x90,0xeb,0xa2}, 8333}, - {{0x2a,0x02,0x7b,0x40,0x3e,0x4d,0x9e,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0x50,0xd1,0xe0,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0x59,0x28,0x0f,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0x59,0x2f,0xa5,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x82,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x89,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x8b,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x8d,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x7b,0x40,0xd4,0x18,0x6f,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x81,0x08,0x23,0x40,0x1c,0x18,0x00,0x7a,0x23,0x1e,0x14,0x30,0x7f,0x12}, 8333}, - {{0x2a,0x02,0x81,0x08,0x9c,0x3f,0xdd,0x18,0x92,0x2b,0x34,0xff,0xfe,0x30,0xac,0x42}, 8333}, - {{0x2a,0x02,0x81,0x0d,0x8a,0x40,0x36,0xf8,0x9a,0xf2,0xb3,0xff,0xfe,0xe8,0x6d,0x7a}, 8333}, - {{0x2a,0x02,0x83,0x88,0xe3,0x01,0x71,0x80,0x02,0x01,0x2e,0xff,0xfe,0x82,0xb3,0xcc}, 8333}, - {{0x2a,0x02,0x09,0x08,0x02,0x13,0x54,0xa0,0x39,0xbf,0xd4,0xaa,0x60,0xb2,0xd9,0xc3}, 8333}, - {{0x2a,0x02,0x09,0x08,0x04,0xf0,0x7e,0x1c,0x50,0x54,0x00,0xff,0xfe,0xb7,0xce,0x4b}, 8333}, - {{0x2a,0x02,0x09,0x30,0x00,0x01,0x00,0x00,0x02,0x50,0x56,0xff,0xfe,0x8e,0x28,0x19}, 8333}, - {{0x2a,0x02,0x0a,0x80,0x00,0x00,0x20,0x52,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x00,0x00,0x51,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x08,0x02,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x10,0x62,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x16,0x43,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x17,0x21,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x18,0x17,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x20,0x18,0x82,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x30,0x02,0x27,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x05,0x30,0x02,0x65,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x00,0x00,0x38,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x07,0x46,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x09,0x02,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x10,0x77,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x12,0x48,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x41,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x56,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x14,0x99,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 18333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x37,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x39,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x59,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x15,0x66,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x16,0x23,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x16,0x93,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x19,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x37,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x44,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x47,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x58,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x73,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x81,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x17,0x89,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x14,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x30,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x32,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x37,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x47,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x18,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x10,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x14,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x20,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x02,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x20,0x19,0x35,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x01,0x93,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x12,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x41,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x71,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x72,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x76,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xc2,0x07,0x30,0x02,0x84,0x56,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0xce,0x80,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333}, - {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x01,0x00,0xd0,0x00,0x00,0x00,0x00,0x00,0x69,0x30,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x03,0xba,0xb0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xd0,0x00,0x00,0x00,0x00,0x08,0xce,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x01,0x16,0x50,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x01,0x2a,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x23,0xfb,0x60,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x04,0x09,0x10,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0x90,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xa0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xe0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb8,0xf0,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x00,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x10,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x20,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x44,0xb9,0x40,0x01}, 8333}, - {{0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x5e,0x48,0xd0,0x01}, 8333}, - {{0x2a,0x03,0xee,0x40,0x00,0x00,0x02,0x94,0x02,0x50,0x56,0xff,0xfe,0x8d,0x4a,0xd7}, 8333}, - {{0x2a,0x04,0x21,0x80,0x00,0x01,0x00,0x0c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333}, - {{0x2a,0x07,0x04,0x40,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x0c,0xa0,0x18,0x17}, 8333}, - {{0x2a,0x0a,0xc8,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xbc,0x4a,0x3c,0x6d,0x03,0xa9,0x4e,0x1f,0x55}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xec,0x32,0xc1,0x59,0x9c,0xd8,0x46,0xd5,0x48}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd0,0x4b,0x2b,0xe5,0x74,0xc4,0xb0,0x1c,0x49,0xb1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x79,0x73,0x7d,0x9b,0x37,0xab,0x3b,0xc0,0x43}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd2,0x3a,0x8f,0x2a,0xb7,0x71,0x8c,0xd3,0x67,0xdf}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xde,0xfc,0xb8,0x18,0xa5,0x0f,0x26,0x6e,0x99,0xec}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0x34,0xea,0x00,0x93,0xac,0x32,0x62,0x3d,0x37}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdb,0x29,0x3c,0xb5,0x05,0x98,0x81,0xdb,0x7d,0xd4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x1e,0x17,0xcf,0x86,0x53,0xf6,0x3b,0xb7,0x51}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x79,0xc1,0x8f,0x29,0x44,0xf2,0xdc,0x00,0xf6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdd,0xe8,0x28,0x36,0x77,0x7f,0x46,0x37,0x03,0x3d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0x2c,0x05,0xb5,0x95,0x59,0xc5,0x00,0x6c,0x5a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x0f,0x31,0xe2,0xb5,0xc9,0xc2,0x17,0x78,0x5d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0x48,0xa0,0x9f,0xe2,0x1a,0xca,0x30,0x6e,0xa4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x09,0x6b,0x3b,0x41,0x2d,0xd5,0xe5,0x9b,0x65}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0xe7,0x24,0xcf,0xd9,0x86,0xd0,0x09,0x57,0xb0}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x3c,0x49,0x0b,0xc1,0x74,0xc2,0x92,0x86,0xe1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0x73,0x9c,0xc9,0x5f,0x44,0x2b,0xe7,0xec,0x96}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0xa5,0x34,0x24,0x5e,0x50,0x8d,0x6f,0x15,0x6a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x17,0x9b,0x08,0xdc,0xbe,0x24,0xe3,0x01,0x6e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x79,0x89,0x41,0x5c,0x21,0x07,0xc4,0x8a,0xa9}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0xb6,0xeb,0xd2,0x5a,0x58,0x00,0x16,0x61,0x0f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0xe7,0x4c,0xbd,0x60,0xb0,0x77,0x2a,0xc9,0xd2}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xec,0x58,0xf9,0x46,0x23,0x0e,0xea,0xf2,0x9b,0x27}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0x9a,0xa8,0x65,0x39,0x49,0x0e,0xc8,0x7c,0xed}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0xef,0x28,0x1d,0xef,0x42,0x35,0xa7,0x98,0x92}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x0d,0x2c,0x85,0x41,0x08,0x29,0x94,0xdf,0xec}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x75,0x23,0x93,0x83,0xf1,0x6b,0x11,0xb5,0x84}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0x21,0x13,0xe2,0xe6,0x5e,0x12,0x93,0xa9,0xa4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf2,0x9b,0xff,0x28,0x09,0x12,0xa0,0x6d,0x68,0x0e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf3,0x34,0x88,0x19,0xb0,0x4d,0xcf,0xfa,0x2f,0x0a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf5,0x84,0x56,0x84,0x3b,0xab,0x01,0x6f,0x0a,0xc0}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf6,0x70,0xdb,0x84,0x34,0x79,0x58,0xda,0x8b,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0x9b,0x2f,0xc4,0x14,0x8b,0xd8,0xb5,0xe0,0x28}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfd,0x8e,0x09,0x64,0xda,0xd3,0xc6,0xaa,0x94,0x4a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x06,0xc1,0xe7,0xaf,0x38,0x13,0x99,0x7e,0x9a,0x16}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0xa5,0xf3,0xe1,0x60,0x00,0xd2,0xa9,0xfd,0x8a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x01,0x9f,0x61,0x55,0x17,0x00,0xc2,0x86,0xe0,0x93}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x61,0x59,0x61,0x66,0xed,0xc7,0xda,0xcb,0x78}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xa6,0x52,0x02,0x0a,0x0b,0x55,0xdd,0x04,0xb7}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xc3,0x22,0x35,0xb2,0x60,0x64,0x6b,0xae,0x5b}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xe3,0x4c,0xc4,0x79,0xfd,0xc4,0x45,0x7b,0xe5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x3c,0x08,0x6c,0x6b,0xa6,0x76,0xd4,0x89,0xb3}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x88,0x5c,0x5c,0xcd,0x79,0x80,0x8b,0x6a,0xe6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xf4,0x58,0x9b,0x4c,0x04,0x2e,0xf6,0x29,0x43}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xf9,0x9c,0xf1,0x0c,0xb8,0x46,0xbf,0x3d,0x71}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0xc2,0x1a,0x9d,0x5b,0xd3,0x31,0x41,0xb7,0x18}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x04,0x56,0xe1,0x55,0xd6,0xbc,0xda,0xb0,0xbd,0xdb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x47,0xe2,0x4c,0xab,0x4b,0x34,0xb4,0x93,0xb8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x08,0xed,0x51,0x58,0x05,0xcb,0xe5,0x28,0x09,0x49}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0x6d,0x02,0x65,0xbe,0x59,0x3b,0xcb,0x68,0x21}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0xef,0x55,0x07,0xe2,0xcc,0x6f,0x3a,0xe7,0x42}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0xa6,0xf8,0x28,0x19,0xe2,0x0e,0x9c,0xd8,0xc1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0x85,0x5d,0xea,0x21,0x08,0x53,0x8c,0x65,0xd6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x12,0x95,0x07,0xac,0xca,0xcb,0x8b,0xce,0x9f,0x58}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x13,0xf0,0x58,0x06,0x5c,0x2c,0xb7,0x56,0x85,0xe5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x14,0xf3,0x4c,0xdd,0xb5,0x58,0x3b,0x7a,0x87,0xf9}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x15,0xb8,0x88,0x54,0x43,0xc7,0xbe,0x1e,0xcd,0xf6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x2a,0xf3,0x4f,0x5d,0xd7,0xf8,0x8e,0x87,0xe2}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0x28,0x39,0x47,0xf7,0xf9,0x07,0x5c,0x19,0x73}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x82,0xde,0xec,0xba,0x1d,0x9e,0x7a,0xf5,0x97}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0xa5,0x01,0xa7,0xcf,0xbb,0x72,0xa9,0x9f,0xc8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xf2,0x12,0x3c,0xf5,0x14,0x19,0x91,0x41,0x51}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x27,0xb6,0x8f,0x8b,0xf0,0x06,0x42,0x39,0xa5,0x80}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x28,0x04,0xea,0x09,0xa8,0x5b,0xfd,0xfd,0xe7}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x23,0xf4,0xc4,0xe5,0xd7,0xda,0xaa,0x1f,0x02,0xfc}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0x2a,0x5b,0x90,0x85,0x8f,0x08,0xe5,0x10,0xb1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xda,0x54,0x38,0xfa,0xfa,0x75,0x75,0x94,0x9d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2f,0x49,0x9b,0xbc,0xe6,0x3a,0x9a,0x50,0xc6,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x28,0x09,0x61,0x65,0x34,0xcc,0xb9,0x62,0xdc,0xf5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x0a,0x89,0x09,0x50,0xa7,0x62,0x08,0x13,0x62}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x83,0x29,0x6f,0xbb,0xac,0xaa,0x06,0x8d,0xbf}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x56,0xa8,0xba,0xd2,0xc4,0x4a,0x4a,0x07,0xd2}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x5d,0xc0,0x01,0x4f,0x5f,0xa4,0x6f,0x63,0x9f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x5e,0xd4,0x8d,0x5a,0xe3,0xf2,0x61,0x3d,0x77}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0x89,0xcc,0x31,0x39,0xe1,0xd2,0x77,0x5a,0x83}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x17,0xcd,0xf9,0xb9,0xfc,0x06,0x89,0x6d,0xaa}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x4e,0x5a,0x0a,0xd6,0xed,0x4c,0x72,0xfc,0x55}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x63,0x72,0x16,0xbd,0x1a,0x23,0xd3,0xb3,0xeb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2d,0x04,0xa2,0x45,0xcb,0xc5,0x2b,0xf2,0x05,0x60}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0x7c,0xd9,0x21,0x3e,0x4a,0x31,0x4b,0x2e,0x42}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x37,0x20,0x5b,0x0a,0x9d,0xb3,0x3f,0x92,0x75,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x7b,0x87,0xc2,0x7e,0xd8,0xe9,0xbb,0x14,0xed}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0xb0,0x34,0xf5,0x03,0xda,0x45,0x7c,0x07,0x31}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x6a,0xd6,0xb6,0xc2,0x18,0xcb,0x97,0x48,0x15}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x33,0x96,0x4a,0xd7,0x00,0xc0,0xe4,0x3a,0x52,0xda}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x34,0x39,0x2a,0x7a,0x53,0x4b,0x5d,0x28,0x53,0xdf}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x78,0xe8,0x90,0xcb,0x74,0x7b,0x7d,0xdd,0xc0}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x68,0x04,0x47,0x7f,0x1d,0xda,0x15,0xd2,0x36}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xc1,0xf2,0xd7,0x30,0xdd,0x5c,0x7f,0xb2,0x9e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3b,0x6a,0xad,0xbc,0xd5,0x41,0x30,0x8b,0xe0,0x5a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x6d,0x7b,0x51,0xa9,0x07,0x1e,0x6b,0x60,0x66}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x42,0x58,0x16,0x65,0x14,0x68,0x65,0x9c,0xde,0x69}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x7f,0x1e,0xa0,0x8e,0xfb,0x8c,0xab,0x85,0xa4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0x71,0x2a,0x9c,0x0a,0x8d,0x16,0x6f,0x2e,0x72}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0xa3,0x60,0xda,0x52,0xfa,0xca,0x05,0x94,0xdc}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x48,0x3e,0x36,0x19,0x51,0x47,0xca,0x8e,0x7e,0xea}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0xd5,0x26,0xb9,0x54,0x90,0x72,0xc9,0x7e,0xcb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xaf,0x88,0x1d,0xfc,0xd0,0x99,0x63,0xc0,0xbb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xe2,0x50,0x4e,0x13,0x11,0x2b,0x9b,0x62,0xd9}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x3c,0xca,0xe4,0x3a,0x6c,0xe9,0x34,0x60,0x9e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x07,0x0a,0x5f,0x2b,0x41,0x13,0xe1,0xb3,0x5c}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x56,0x8c,0x3c,0xd6,0x38,0x8d,0xff,0x5f,0x2a,0x56}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0x86,0x09,0x6e,0x04,0x0a,0x9d,0x2c,0x1a,0x9d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0xac,0x5c,0x52,0x2d,0x32,0xd9,0xee,0xd3,0xe1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x9f,0x1a,0x66,0x3b,0x63,0x4e,0x82,0x52,0x86}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x94,0x61,0x0f,0x81,0x8a,0x58,0x78,0xc1,0xa0}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x95,0x50,0xd6,0x2e,0xf7,0xd2,0xe6,0x3a,0x56}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5a,0xd6,0x96,0x82,0x6a,0x91,0x4d,0x35,0x9d,0x4e}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x60,0xdf,0x3f,0x5b,0xb2,0x4d,0x84,0xdb,0xce,0xd8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x61,0xd2,0x22,0x3f,0x22,0xe1,0xb0,0x01,0xdb,0x56}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0x7f,0xce,0x1c,0x28,0x70,0x30,0xdd,0xb9,0x32}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0xc0,0xa7,0x9b,0x34,0xfd,0x18,0x6a,0x6f,0x24}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0x5c,0xcb,0x14,0x63,0x1c,0x0b,0x03,0x6d,0x70}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0xfa,0xa1,0x96,0xf6,0x75,0x85,0xbc,0x33,0x26}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x19,0xbd,0x64,0x4f,0xe9,0xea,0xe6,0x2a,0x7c}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0xf7,0x29,0x92,0x02,0x62,0x73,0xd3,0xd9,0xa8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xb4,0x13,0x28,0xf0,0x71,0xe2,0xcb,0x06,0xf1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xbd,0x95,0xca,0xd6,0x84,0x0d,0xf1,0x77,0x19}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0x5b,0x0d,0x91,0x66,0xd0,0xca,0x10,0x2d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0xc5,0x19,0x94,0x5b,0xcd,0x20,0xd9,0x73}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0xa6,0xaa,0x68,0x61,0x90,0xfc,0x8a,0x30,0x47}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0xf5,0x9c,0x66,0x35,0xff,0xc8,0x0d,0x06,0xd4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x71,0xcd,0x60,0x77,0x1e,0xee,0x78,0x42,0x33,0xe1}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x72,0xea,0x3a,0x77,0xe6,0xfc,0x6f,0x67,0x8a,0x3c}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0x57,0x97,0x7f,0xfd,0x71,0x86,0xf4,0xb7,0xb7}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0xe4,0x79,0xcc,0x23,0xf5,0x74,0xad,0xa5,0x79}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x75,0xa3,0xd9,0xb3,0xf8,0x35,0xbd,0xac,0xf2,0xab}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x8a,0x79,0x0e,0x19,0x97,0xa1,0xed,0xc7,0x14}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0x4b,0x68,0x5e,0xb4,0x58,0xc9,0x0e,0xf7,0x22}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0x9b,0x9f,0xaa,0xc2,0xdf,0xa2,0x2a,0x09,0xf4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0xf8,0x6f,0x87,0x89,0x96,0x28,0xd9,0xd6,0x3c}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0x4c,0x71,0x22,0xb9,0x53,0x89,0x19,0x12,0x43}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0x3f,0x6d,0xa4,0xb8,0x8e,0x5f,0xf9,0x5e,0x48}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0xea,0xa4,0xbf,0xd2,0x28,0x74,0x5f,0x95,0xc4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x80,0x2e,0xce,0xc9,0xec,0xbf,0x47,0xa5,0x6e,0x8f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0x1f,0x33,0xf7,0x83,0x06,0x24,0xc7,0xe3,0xb8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x7c,0x88,0xc1,0xba,0x47,0xf6,0x41,0x94,0xbd}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x5e,0x44,0x97,0x2b,0xb4,0x20,0xdc,0xc9,0xcb}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0xc9,0xb0,0xc1,0x2c,0x88,0x88,0xfb,0xbe,0xfc}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0xdc,0xd4,0xb3,0xf4,0x47,0x8a,0x3c,0x67,0x87}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8c,0xbd,0xbe,0xca,0x5a,0xe6,0x19,0x6c,0x41,0x56}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0x90,0x89,0xb8,0xc4,0x74,0x24,0xba,0xa9,0x35}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0xd0,0x32,0x45,0xa4,0x9a,0x18,0xc6,0x2a,0x67}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x7f,0x05,0xa0,0x51,0x9f,0xa2,0x3c,0xdf,0x23}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xc2,0x95,0x03,0xda,0x05,0xf3,0x4b,0x4d,0xb3}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0x8d,0x4a,0xe3,0xb4,0x7e,0x28,0x29,0xd0,0x77}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0xd8,0xfa,0xdd,0xd3,0x63,0x60,0xd9,0xe1,0xbd}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa0,0x84,0xcb,0x7b,0xeb,0xe2,0x8c,0xbf,0x73,0xd8}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0x1d,0xe8,0xbb,0x02,0xdf,0xff,0xd4,0x3a,0x1f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0x64,0x1d,0x40,0x49,0x57,0x27,0xed,0x6f,0x99}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa5,0x03,0xcd,0xbf,0x60,0x8c,0xd8,0xe8,0xb6,0xbd}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa5,0x43,0xde,0xb2,0xd5,0xa6,0x35,0xa6,0x19,0x9a}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa6,0x73,0x84,0x9a,0x0b,0x2f,0x3e,0x01,0x28,0x31}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0x4a,0x68,0xec,0xad,0xce,0xdb,0x6f,0x7b,0x73}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0x73,0x2d,0x48,0xc9,0xc4,0x76,0x65,0x9f,0xc2}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0xb7,0x04,0x8c,0x87,0xc6,0x38,0x3b,0x0a,0xf6}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xb1,0xeb,0x86,0xa4,0x4b,0xaf,0xcb,0x84,0x17}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0x11,0x6f,0xf5,0x46,0x78,0xa0,0xa2,0x71,0x95}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb6,0xe1,0xcf,0xd0,0x58,0x02,0x66,0x54,0x0b,0xfe}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xbd,0x5b,0x30,0x31,0xce,0x31,0x90,0x3e,0x8d}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0x9e,0x5b,0x5c,0xd8,0xd0,0xdd,0x64,0x11,0xad}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb2,0x66,0xca,0xcb,0x2d,0xa8,0xc4,0xb6,0x88,0x14}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0x03,0xce,0x85,0xec,0x64,0x57,0xd3,0x6c,0x38}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb8,0xd7,0x4d,0xd1,0x39,0x41,0x0e,0x47,0x51,0xdf}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0xb0,0xa6,0x00,0x1a,0x4a,0x41,0x8f,0x88,0xb4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0x57,0x4d,0xce,0xa0,0x53,0x4d,0x8f,0xcd,0x4f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbc,0x9b,0xd4,0x08,0x44,0xe7,0x4d,0x2d,0xc3,0x1f}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc0,0xdc,0xd7,0x19,0x2f,0x48,0xf6,0xc2,0x73,0xb5}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0x9b,0xfa,0xb8,0xbb,0xf8,0x41,0x5b,0x92,0x63}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0xfb,0xae,0x8e,0xc7,0xac,0x11,0x2f,0xc7,0x02}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x42,0x01,0x09,0xe1,0xc1,0x89,0xeb,0x80,0x20}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x29,0x70,0x15,0x68,0xf9,0x60,0x34,0x64,0xf0}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0xf6,0xda,0x2a,0x7f,0x69,0x90,0xad,0x89,0xe4}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0x9b,0xa0,0x84,0x5a,0x86,0x90,0x78,0x4f,0x82}, 8333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0x13,0x59,0xde,0x4a,0xbb,0x9b,0x4e,0x2b,0x35}, 8333} + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0x44,0xc6,0x8e}, 9246}, + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0xc5,0xe0,0xfc}, 9246} }; static SeedSpec6 pnSeed6_test[] = { - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xcb,0x26,0x31,0xba,0x48,0x51,0x31,0x39,0x0d}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0xf4,0xf4,0xf0,0xbf,0xf7,0x7e,0x6d,0xc4,0xe8}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x8b,0xd2,0x78,0x3f,0x7a,0xf8,0x92,0x8f,0x80}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe6,0x4e,0xa4,0x47,0x4e,0x2a,0xfe,0xe8,0x95,0xcc}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0xae,0x9f,0x59,0x0b,0x3f,0x31,0x3a,0x8a,0x5f}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x47,0xb1,0xe4,0x55,0xd1,0xb0,0x14,0x3f,0xb6,0xdb}, 18333}, - {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa0,0x60,0x9e,0x46,0x54,0xdb,0x61,0x3b,0xb2,0x6f}, 18333} + {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xcb,0x9a,0xdb}, 19246} }; #endif // BITCOIN_CHAINPARAMSSEEDS_H diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp new file mode 100644 index 000000000..845faa3e5 --- /dev/null +++ b/src/claimtrie.cpp @@ -0,0 +1,2804 @@ +#include "claimtrie.h" +#include "coins.h" +#include "hash.h" + +#include +#include +#include + +std::vector heightToVch(int n) +{ + std::vector vchHeight; + vchHeight.resize(8); + vchHeight[0] = 0; + vchHeight[1] = 0; + vchHeight[2] = 0; + vchHeight[3] = 0; + vchHeight[4] = n >> 24; + vchHeight[5] = n >> 16; + vchHeight[6] = n >> 8; + vchHeight[7] = n; + return vchHeight; +} + +uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover) +{ + CHash256 txHasher; + txHasher.Write(outPoint.hash.begin(), outPoint.hash.size()); + std::vector vchtxHash(txHasher.OUTPUT_SIZE); + txHasher.Finalize(&(vchtxHash[0])); + + CHash256 nOutHasher; + std::stringstream ss; + ss << outPoint.n; + std::string snOut = ss.str(); + nOutHasher.Write((unsigned char*) snOut.data(), snOut.size()); + std::vector vchnOutHash(nOutHasher.OUTPUT_SIZE); + nOutHasher.Finalize(&(vchnOutHash[0])); + + CHash256 takeoverHasher; + std::vector vchTakeoverHeightToHash = heightToVch(nHeightOfLastTakeover); + takeoverHasher.Write(vchTakeoverHeightToHash.data(), vchTakeoverHeightToHash.size()); + std::vector vchTakeoverHash(takeoverHasher.OUTPUT_SIZE); + takeoverHasher.Finalize(&(vchTakeoverHash[0])); + + CHash256 hasher; + hasher.Write(vchtxHash.data(), vchtxHash.size()); + hasher.Write(vchnOutHash.data(), vchnOutHash.size()); + hasher.Write(vchTakeoverHash.data(), vchTakeoverHash.size()); + std::vector vchHash(hasher.OUTPUT_SIZE); + hasher.Finalize(&(vchHash[0])); + + uint256 valueHash(vchHash); + return valueHash; +} + +bool CClaimTrieNode::insertClaim(CClaimValue claim) +{ + LogPrintf("%s: Inserting %s:%d (amount: %d) into the claim trie\n", __func__, claim.outPoint.hash.ToString(), claim.outPoint.n, claim.nAmount); + claims.push_back(claim); + return true; +} + +bool CClaimTrieNode::removeClaim(const COutPoint& outPoint, CClaimValue& claim) +{ + LogPrintf("%s: Removing txid: %s, nOut: %d from the claim trie\n", __func__, outPoint.hash.ToString(), outPoint.n); + + std::vector::iterator itClaims; + for (itClaims = claims.begin(); itClaims != claims.end(); ++itClaims) + { + if (itClaims->outPoint == outPoint) + { + claim = *itClaims; + break; + } + } + if (itClaims != claims.end()) + { + claims.erase(itClaims); + } + else + { + LogPrintf("CClaimTrieNode::%s() : asked to remove a claim that doesn't exist\n", __func__); + LogPrintf("CClaimTrieNode::%s() : claims that do exist:\n", __func__); + for (unsigned int i = 0; i < claims.size(); i++) + { + LogPrintf("\ttxhash: %s, nOut: %d:\n", claims[i].outPoint.hash.ToString(), claims[i].outPoint.n); + } + return false; + } + return true; +} + +bool CClaimTrieNode::getBestClaim(CClaimValue& claim) const +{ + if (claims.empty()) + { + return false; + } + else + { + claim = claims.front(); + return true; + } +} + +bool CClaimTrieNode::haveClaim(const COutPoint& outPoint) const +{ + for (std::vector::const_iterator itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) + { + if (itclaim->outPoint == outPoint) + return true; + } + return false; +} + +void CClaimTrieNode::reorderClaims(supportMapEntryType& supports) +{ + std::vector::iterator itclaim; + + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) + { + itclaim->nEffectiveAmount = itclaim->nAmount; + } + + for (supportMapEntryType::iterator itsupport = supports.begin(); itsupport != supports.end(); ++itsupport) + { + for (itclaim = claims.begin(); itclaim != claims.end(); ++itclaim) + { + if (itsupport->supportedClaimId == itclaim->claimId) + { + itclaim->nEffectiveAmount += itsupport->nAmount; + break; + } + } + } + + std::make_heap(claims.begin(), claims.end()); +} + +uint256 CClaimTrie::getMerkleHash() +{ + return root.hash; +} + +bool CClaimTrie::empty() const +{ + return root.empty(); +} + +template bool CClaimTrie::keyTypeEmpty(char keyType, K& dummy) const +{ + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + pcursor->SeekToFirst(); + + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + if (key.first == keyType) + { + return false; + } + } + else + { + break; + } + pcursor->Next(); + } + return true; +} + +bool CClaimTrie::queueEmpty() const +{ + for (claimQueueType::const_iterator itRow = dirtyQueueRows.begin(); itRow != dirtyQueueRows.end(); ++itRow) + { + if (!itRow->second.empty()) + return false; + } + int dummy; + return keyTypeEmpty(CLAIM_QUEUE_ROW, dummy); +} + +bool CClaimTrie::expirationQueueEmpty() const +{ + for (expirationQueueType::const_iterator itRow = dirtyExpirationQueueRows.begin(); itRow != dirtyExpirationQueueRows.end(); ++itRow) + { + if (!itRow->second.empty()) + return false; + } + int dummy; + return keyTypeEmpty(EXP_QUEUE_ROW, dummy); +} + +bool CClaimTrie::supportEmpty() const +{ + for (supportMapType::const_iterator itNode = dirtySupportNodes.begin(); itNode != dirtySupportNodes.end(); ++itNode) + { + if (!itNode->second.empty()) + return false; + } + std::string dummy; + return keyTypeEmpty(SUPPORT, dummy); +} + +bool CClaimTrie::supportQueueEmpty() const +{ + for (supportQueueType::const_iterator itRow = dirtySupportQueueRows.begin(); itRow != dirtySupportQueueRows.end(); ++itRow) + { + if (!itRow->second.empty()) + return false; + } + int dummy; + return keyTypeEmpty(SUPPORT_QUEUE_ROW, dummy); +} + +void CClaimTrie::setExpirationTime(int t) +{ + nExpirationTime = t; + LogPrintf("%s: Expiration time is now %d\n", __func__, nExpirationTime); +} + +void CClaimTrie::clear() +{ + clear(&root); +} + +void CClaimTrie::clear(CClaimTrieNode* current) +{ + for (nodeMapType::const_iterator itchildren = current->children.begin(); itchildren != current->children.end(); ++itchildren) + { + clear(itchildren->second); + delete itchildren->second; + } +} + +bool CClaimTrie::haveClaim(const std::string& name, const COutPoint& outPoint) const +{ + const CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) + { + nodeMapType::const_iterator itchildren = current->children.find(*itname); + if (itchildren == current->children.end()) + return false; + current = itchildren->second; + } + return current->haveClaim(outPoint); +} + +bool CClaimTrie::haveSupport(const std::string& name, const COutPoint& outPoint) const +{ + supportMapEntryType node; + if (!getSupportNode(name, node)) + { + return false; + } + for (supportMapEntryType::const_iterator itnode = node.begin(); itnode != node.end(); ++itnode) + { + if (itnode->outPoint == outPoint) + return true; + } + return false; +} + +bool CClaimTrie::haveClaimInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +{ + queueNameRowType nameRow; + if (!getQueueNameRow(name, nameRow)) + { + return false; + } + queueNameRowType::const_iterator itNameRow; + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) + { + if (itNameRow->outPoint == outPoint) + { + nValidAtHeight = itNameRow->nHeight; + break; + } + } + if (itNameRow == nameRow.end()) + { + return false; + } + claimQueueRowType row; + if (getQueueRow(nValidAtHeight, row)) + { + for (claimQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) + { + if (itRow->first == name && itRow->second.outPoint == outPoint) + { + if (itRow->second.nValidAtHeight != nValidAtHeight) + { + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nDifferent nValidAtHeight between named queue and height queue\n: name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, itRow->second.nValidAtHeight, nCurrentHeight); + } + return true; + } + } + } + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, nCurrentHeight); + return false; +} + +bool CClaimTrie::haveSupportInQueue(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +{ + queueNameRowType nameRow; + if (!getSupportQueueNameRow(name, nameRow)) + { + return false; + } + queueNameRowType::const_iterator itNameRow; + for (itNameRow = nameRow.begin(); itNameRow != nameRow.end(); ++itNameRow) + { + if (itNameRow->outPoint == outPoint) + { + nValidAtHeight = itNameRow->nHeight; + break; + } + } + if (itNameRow == nameRow.end()) + { + return false; + } + supportQueueRowType row; + if (getSupportQueueRow(nValidAtHeight, row)) + { + for (supportQueueRowType::const_iterator itRow = row.begin(); itRow != row.end(); ++itRow) + { + if (itRow->first == name && itRow->second.outPoint == outPoint) + { + if (itRow->second.nValidAtHeight != nValidAtHeight) + { + LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nDifferent nValidAtHeight between named queue and height queue\n: name: %s, txid: %s, nOut: %d, nValidAtHeight in named queue: %d, nValidAtHeight in height queue: %d current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, itRow->second.nValidAtHeight, nCurrentHeight); + } + return true; + } + } + } + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nValidAtHeight, nCurrentHeight); + return false; +} + +unsigned int CClaimTrie::getTotalNamesInTrie() const +{ + if (empty()) + return 0; + const CClaimTrieNode* current = &root; + return getTotalNamesRecursive(current); +} + +unsigned int CClaimTrie::getTotalNamesRecursive(const CClaimTrieNode* current) const +{ + unsigned int names_in_subtrie = 0; + if (!(current->claims.empty())) + names_in_subtrie += 1; + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) + { + names_in_subtrie += getTotalNamesRecursive(it->second); + } + return names_in_subtrie; +} + +unsigned int CClaimTrie::getTotalClaimsInTrie() const +{ + if (empty()) + return 0; + const CClaimTrieNode* current = &root; + return getTotalClaimsRecursive(current); +} + +unsigned int CClaimTrie::getTotalClaimsRecursive(const CClaimTrieNode* current) const +{ + unsigned int claims_in_subtrie = current->claims.size(); + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) + { + claims_in_subtrie += getTotalClaimsRecursive(it->second); + } + return claims_in_subtrie; +} + +CAmount CClaimTrie::getTotalValueOfClaimsInTrie(bool fControllingOnly) const +{ + if (empty()) + return 0; + const CClaimTrieNode* current = &root; + return getTotalValueOfClaimsRecursive(current, fControllingOnly); +} + +CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, bool fControllingOnly) const +{ + CAmount value_in_subtrie = 0; + for (std::vector::const_iterator itclaim = current->claims.begin(); itclaim != current->claims.end(); ++itclaim) + { + value_in_subtrie += itclaim->nAmount; + if (fControllingOnly) + break; + } + for (nodeMapType::const_iterator itchild = current->children.begin(); itchild != current->children.end(); ++itchild) + { + value_in_subtrie += getTotalValueOfClaimsRecursive(itchild->second, fControllingOnly); + } + return value_in_subtrie; +} + +bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const +{ + namedNodeType node(name, *current); + nodes.push_back(node); + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) + { + std::stringstream ss; + ss << name << it->first; + if (!recursiveFlattenTrie(ss.str(), it->second, nodes)) + return false; + } + return true; +} + +std::vector CClaimTrie::flattenTrie() const +{ + std::vector nodes; + if (!recursiveFlattenTrie("", &root, nodes)) + LogPrintf("%s: Something went wrong flattening the trie", __func__); + return nodes; +} + +const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const +{ + const CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) + { + nodeMapType::const_iterator itchildren = current->children.find(*itname); + if (itchildren == current->children.end()) + return NULL; + current = itchildren->second; + } + return current; +} + +bool CClaimTrie::getInfoForName(const std::string& name, CClaimValue& claim) const +{ + const CClaimTrieNode* current = getNodeForName(name); + if (current) + { + return current->getBestClaim(claim); + } + return false; +} + +bool CClaimTrie::getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const +{ + const CClaimTrieNode* current = getNodeForName(name); + if (current && !current->claims.empty()) + { + lastTakeoverHeight = current->nHeightOfLastTakeover; + return true; + } + return false; +} + +claimsForNameType CClaimTrie::getClaimsForName(const std::string& name) const +{ + std::vector claims; + std::vector supports; + int nLastTakeoverHeight = 0; + const CClaimTrieNode* current = getNodeForName(name); + if (current) + { + if (!current->claims.empty()) + { + nLastTakeoverHeight = current->nHeightOfLastTakeover; + } + for (std::vector::const_iterator itClaims = current->claims.begin(); itClaims != current->claims.end(); ++itClaims) + { + claims.push_back(*itClaims); + } + } + supportMapEntryType supportNode; + if (getSupportNode(name, supportNode)) + { + for (std::vector::const_iterator itSupports = supportNode.begin(); itSupports != supportNode.end(); ++itSupports) + { + supports.push_back(*itSupports); + } + } + queueNameRowType namedClaimRow; + if (getQueueNameRow(name, namedClaimRow)) + { + for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) + { + claimQueueRowType claimRow; + if (getQueueRow(itClaimsForName->nHeight, claimRow)) + { + for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) + { + if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) + { + claims.push_back(itClaimRow->second); + break; + } + } + } + } + } + queueNameRowType namedSupportRow; + if (getSupportQueueNameRow(name, namedSupportRow)) + { + for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) + { + supportQueueRowType supportRow; + if (getSupportQueueRow(itSupportsForName->nHeight, supportRow)) + { + for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) + { + if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) + { + supports.push_back(itSupportRow->second); + break; + } + } + } + } + } + claimsForNameType allClaims(claims, supports, nLastTakeoverHeight); + return allClaims; +} + +//return effective amount from claim, retuns 0 if claim is not found +CAmount CClaimTrie::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const +{ + return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); +} + +CAmount CClaimTrie::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const +{ + CAmount effectiveAmount = 0; + for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + if (supports) supports->push_back(*it); + } + } + break; + } + } + return effectiveAmount; +} + +bool CClaimTrie::checkConsistency() const +{ + if (empty()) + return true; + return recursiveCheckConsistency(&root); +} + +bool CClaimTrie::recursiveCheckConsistency(const CClaimTrieNode* node) const +{ + std::vector vchToHash; + + for (nodeMapType::const_iterator it = node->children.begin(); it != node->children.end(); ++it) + { + if (recursiveCheckConsistency(it->second)) + { + vchToHash.push_back(it->first); + vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); + } + else + return false; + } + + CClaimValue claim; + bool hasClaim = node->getBestClaim(claim); + + if (hasClaim) + { + uint256 valueHash = getValueHash(claim.outPoint, node->nHeightOfLastTakeover); + vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); + } + + CHash256 hasher; + std::vector vchHash(hasher.OUTPUT_SIZE); + hasher.Write(vchToHash.data(), vchToHash.size()); + hasher.Finalize(&(vchHash[0])); + uint256 calculatedHash(vchHash); + return calculatedHash == node->hash; +} + +void CClaimTrie::addToClaimIndex(const std::string& name, const CClaimValue& claim) +{ + CClaimIndexElement element = { name, claim }; + LogPrintf("%s: ClaimIndex[%s] updated %s\n", __func__, claim.claimId.GetHex(), name); + db.Write(std::make_pair(CLAIM_BY_ID, claim.claimId), element); +} + +void CClaimTrie::removeFromClaimIndex(const CClaimValue& claim) +{ + LogPrintf("%s: ClaimIndex[%s] removed\n", __func__, claim.claimId.GetHex()); + db.Erase(std::make_pair(CLAIM_BY_ID, claim.claimId)); +} + +bool CClaimTrie::getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const +{ + CClaimIndexElement element; + if (db.Read(std::make_pair(CLAIM_BY_ID, claimId), element)) + { + if (element.claim.claimId == claimId) { + name = element.name; + claim = element.claim; + return true; + } else { + LogPrintf("%s: ClaimIndex[%s] returned unmatched claimId %s when looking for %s\n", + __func__, claimId.GetHex(), element.claim.claimId.GetHex(), name); + } + } + return false; +} + +bool CClaimTrie::getQueueRow(int nHeight, claimQueueRowType& row) const +{ + claimQueueType::const_iterator itQueueRow = dirtyQueueRows.find(nHeight); + if (itQueueRow != dirtyQueueRows.end()) + { + row = itQueueRow->second; + return true; + } + return db.Read(std::make_pair(CLAIM_QUEUE_ROW, nHeight), row); +} + +bool CClaimTrie::getQueueNameRow(const std::string& name, queueNameRowType& row) const +{ + queueNameType::const_iterator itQueueNameRow = dirtyQueueNameRows.find(name); + if (itQueueNameRow != dirtyQueueNameRows.end()) + { + row = itQueueNameRow->second; + LogPrintf("%s: Found row of size %d for %s\n", __func__, row.size(), name); + return true; + } + return db.Read(std::make_pair(CLAIM_QUEUE_NAME_ROW, name), row); +} + +bool CClaimTrie::getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const +{ + expirationQueueType::const_iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); + if (itQueueRow != dirtyExpirationQueueRows.end()) + { + row = itQueueRow->second; + return true; + } + return db.Read(std::make_pair(EXP_QUEUE_ROW, nHeight), row); +} + +void CClaimTrie::updateQueueRow(int nHeight, claimQueueRowType& row) +{ + claimQueueType::iterator itQueueRow = dirtyQueueRows.find(nHeight); + if (itQueueRow == dirtyQueueRows.end()) + { + claimQueueRowType newRow; + std::pair ret; + ret = dirtyQueueRows.insert(std::pair(nHeight, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +void CClaimTrie::updateQueueNameRow(const std::string& name, queueNameRowType& row) +{ + queueNameType::iterator itQueueRow = dirtyQueueNameRows.find(name); + if (itQueueRow == dirtyQueueNameRows.end()) + { + queueNameRowType newRow; + std::pair ret; + ret = dirtyQueueNameRows.insert(std::pair(name, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +void CClaimTrie::updateExpirationRow(int nHeight, expirationQueueRowType& row) +{ + expirationQueueType::iterator itQueueRow = dirtyExpirationQueueRows.find(nHeight); + if (itQueueRow == dirtyExpirationQueueRows.end()) + { + expirationQueueRowType newRow; + std::pair ret; + ret = dirtyExpirationQueueRows.insert(std::pair(nHeight, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +void CClaimTrie::updateSupportMap(const std::string& name, supportMapEntryType& node) +{ + supportMapType::iterator itNode = dirtySupportNodes.find(name); + if (itNode == dirtySupportNodes.end()) + { + supportMapEntryType newNode; + std::pair ret; + ret = dirtySupportNodes.insert(std::pair(name, newNode)); + assert(ret.second); + itNode = ret.first; + } + claimtrie::swap(node, itNode->second); +} + +void CClaimTrie::updateSupportQueue(int nHeight, supportQueueRowType& row) +{ + supportQueueType::iterator itQueueRow = dirtySupportQueueRows.find(nHeight); + if (itQueueRow == dirtySupportQueueRows.end()) + { + supportQueueRowType newRow; + std::pair ret; + ret = dirtySupportQueueRows.insert(std::pair(nHeight, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +void CClaimTrie::updateSupportNameQueue(const std::string& name, queueNameRowType& row) +{ + queueNameType::iterator itQueueRow = dirtySupportQueueNameRows.find(name); + if (itQueueRow == dirtySupportQueueNameRows.end()) + { + queueNameRowType newRow; + std::pair ret; + ret = dirtySupportQueueNameRows.insert(std::pair(name, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +void CClaimTrie::updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row) +{ + expirationQueueType::iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); + if (itQueueRow == dirtySupportExpirationQueueRows.end()) + { + expirationQueueRowType newRow; + std::pair ret; + ret = dirtySupportExpirationQueueRows.insert(std::pair(nHeight, newRow)); + assert(ret.second); + itQueueRow = ret.first; + } + claimtrie::swap(row, itQueueRow->second); +} + +bool CClaimTrie::getSupportNode(std::string name, supportMapEntryType& node) const +{ + supportMapType::const_iterator itNode = dirtySupportNodes.find(name); + if (itNode != dirtySupportNodes.end()) + { + node = itNode->second; + return true; + } + return db.Read(std::make_pair(SUPPORT, name), node); +} + +bool CClaimTrie::getSupportQueueRow(int nHeight, supportQueueRowType& row) const +{ + supportQueueType::const_iterator itQueueRow = dirtySupportQueueRows.find(nHeight); + if (itQueueRow != dirtySupportQueueRows.end()) + { + row = itQueueRow->second; + return true; + } + return db.Read(std::make_pair(SUPPORT_QUEUE_ROW, nHeight), row); +} + +bool CClaimTrie::getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const +{ + queueNameType::const_iterator itQueueNameRow = dirtySupportQueueNameRows.find(name); + if (itQueueNameRow != dirtySupportQueueNameRows.end()) + { + row = itQueueNameRow->second; + return true; + } + return db.Read(std::make_pair(SUPPORT_QUEUE_NAME_ROW, name), row); +} + +bool CClaimTrie::getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const +{ + expirationQueueType::const_iterator itQueueRow = dirtySupportExpirationQueueRows.find(nHeight); + if (itQueueRow != dirtySupportExpirationQueueRows.end()) + { + row = itQueueRow->second; + return true; + } + return db.Read(std::make_pair(SUPPORT_EXP_QUEUE_ROW, nHeight), row); +} + +bool CClaimTrie::update(nodeCacheType& cache, hashMapType& hashes, std::map& takeoverHeights, const uint256& hashBlockIn, claimQueueType& queueCache, queueNameType& queueNameCache, expirationQueueType& expirationQueueCache, int nNewHeight, supportMapType& supportCache, supportQueueType& supportQueueCache, queueNameType& supportQueueNameCache, expirationQueueType& supportExpirationQueueCache) +{ + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) + { + if (!updateName(itcache->first, itcache->second)) + { + LogPrintf("%s: Failed to update name for:%s\n", __func__, itcache->first); + return false; + } + } + for (hashMapType::iterator ithash = hashes.begin(); ithash != hashes.end(); ++ithash) + { + if (!updateHash(ithash->first, ithash->second)) + { + LogPrintf("%s: Failed to update hash for:%s\n", __func__, ithash->first); + return false; + } + } + for (std::map::iterator itheight = takeoverHeights.begin(); itheight != takeoverHeights.end(); ++itheight) + { + if (!updateTakeoverHeight(itheight->first, itheight->second)) + { + LogPrintf("%s: Failed to update takeover height for:%s\n", __func__, itheight->first); + return false; + } + } + for (claimQueueType::iterator itQueueCacheRow = queueCache.begin(); itQueueCacheRow != queueCache.end(); ++itQueueCacheRow) + { + updateQueueRow(itQueueCacheRow->first, itQueueCacheRow->second); + } + for (queueNameType::iterator itQueueNameCacheRow = queueNameCache.begin(); itQueueNameCacheRow != queueNameCache.end(); ++itQueueNameCacheRow) + { + updateQueueNameRow(itQueueNameCacheRow->first, itQueueNameCacheRow->second); + } + for (expirationQueueType::iterator itExpirationRow = expirationQueueCache.begin(); itExpirationRow != expirationQueueCache.end(); ++itExpirationRow) + { + updateExpirationRow(itExpirationRow->first, itExpirationRow->second); + } + for (supportMapType::iterator itSupportCache = supportCache.begin(); itSupportCache != supportCache.end(); ++itSupportCache) + { + updateSupportMap(itSupportCache->first, itSupportCache->second); + } + for (supportQueueType::iterator itSupportQueue = supportQueueCache.begin(); itSupportQueue != supportQueueCache.end(); ++itSupportQueue) + { + updateSupportQueue(itSupportQueue->first, itSupportQueue->second); + } + for (queueNameType::iterator itSupportNameQueue = supportQueueNameCache.begin(); itSupportNameQueue != supportQueueNameCache.end(); ++itSupportNameQueue) + { + updateSupportNameQueue(itSupportNameQueue->first, itSupportNameQueue->second); + } + for (expirationQueueType::iterator itSupportExpirationQueue = supportExpirationQueueCache.begin(); itSupportExpirationQueue != supportExpirationQueueCache.end(); ++itSupportExpirationQueue) + { + updateSupportExpirationQueue(itSupportExpirationQueue->first, itSupportExpirationQueue->second); + } + hashBlock = hashBlockIn; + nCurrentHeight = nNewHeight; + return true; +} + +void CClaimTrie::markNodeDirty(const std::string &name, CClaimTrieNode* node) +{ + std::pair ret; + ret = dirtyNodes.insert(std::pair(name, node)); + if (ret.second == false) + ret.first->second = node; +} + +bool CClaimTrie::updateName(const std::string &name, CClaimTrieNode* updatedNode) +{ + CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) + { + nodeMapType::iterator itchild = current->children.find(*itname); + if (itchild == current->children.end()) + { + if (itname + 1 == name.end()) + { + CClaimTrieNode* newNode = new CClaimTrieNode(); + current->children[*itname] = newNode; + current = newNode; + } + else + return false; + } + else + { + current = itchild->second; + } + } + assert(current != NULL); + claimtrie::swap(updatedNode->claims, current->claims); + markNodeDirty(name, current); + for (nodeMapType::iterator itchild = current->children.begin(); itchild != current->children.end();) + { + nodeMapType::iterator itupdatechild = updatedNode->children.find(itchild->first); + if (itupdatechild == updatedNode->children.end()) + { + // This character has apparently been deleted, so delete + // all descendents from this child. + std::stringstream ss; + ss << name << itchild->first; + std::string newName = ss.str(); + if (!recursiveNullify(itchild->second, newName)) + return false; + current->children.erase(itchild++); + } + else + ++itchild; + } + return true; +} + +bool CClaimTrie::recursiveNullify(CClaimTrieNode* node, std::string& name) +{ + assert(node != NULL); + for (nodeMapType::iterator itchild = node->children.begin(); itchild != node->children.end(); ++itchild) + { + std::stringstream ss; + ss << name << itchild->first; + std::string newName = ss.str(); + if (!recursiveNullify(itchild->second, newName)) + return false; + } + node->children.clear(); + markNodeDirty(name, NULL); + delete node; + return true; +} + +bool CClaimTrie::updateHash(const std::string& name, uint256& hash) +{ + CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) + { + nodeMapType::iterator itchild = current->children.find(*itname); + if (itchild == current->children.end()) + return false; + current = itchild->second; + } + assert(current != NULL); + current->hash = hash; + markNodeDirty(name, current); + return true; +} + +bool CClaimTrie::updateTakeoverHeight(const std::string& name, int nTakeoverHeight) +{ + CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname != name.end(); ++itname) + { + nodeMapType::iterator itchild = current->children.find(*itname); + if (itchild == current->children.end()) + return false; + current = itchild->second; + } + assert(current != NULL); + current->nHeightOfLastTakeover = nTakeoverHeight; + markNodeDirty(name, current); + return true; +} + +void CClaimTrie::BatchWriteNode(CDBBatch& batch, const std::string& name, const CClaimTrieNode* pNode) const +{ + if (pNode) + batch.Write(std::make_pair(TRIE_NODE, name), *pNode); + else + batch.Erase(std::make_pair(TRIE_NODE, name)); +} + +void CClaimTrie::BatchWriteQueueRows(CDBBatch& batch) +{ + for (claimQueueType::iterator itQueue = dirtyQueueRows.begin(); itQueue != dirtyQueueRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(CLAIM_QUEUE_ROW, itQueue->first), itQueue->second); + } + } +} + +void CClaimTrie::BatchWriteQueueNameRows(CDBBatch& batch) +{ + for (queueNameType::iterator itQueue = dirtyQueueNameRows.begin(); itQueue != dirtyQueueNameRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(CLAIM_QUEUE_NAME_ROW, itQueue->first), itQueue->second); + } + } +} + +void CClaimTrie::BatchWriteExpirationQueueRows(CDBBatch& batch) +{ + for (expirationQueueType::iterator itQueue = dirtyExpirationQueueRows.begin(); itQueue != dirtyExpirationQueueRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(EXP_QUEUE_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(EXP_QUEUE_ROW, itQueue->first), itQueue->second); + } + } +} + +void CClaimTrie::BatchWriteSupportNodes(CDBBatch& batch) +{ + for (supportMapType::iterator itSupport = dirtySupportNodes.begin(); itSupport != dirtySupportNodes.end(); ++itSupport) + { + if (itSupport->second.empty()) + { + batch.Erase(std::make_pair(SUPPORT, itSupport->first)); + } + else + { + batch.Write(std::make_pair(SUPPORT, itSupport->first), itSupport->second); + } + } +} + +void CClaimTrie::BatchWriteSupportQueueRows(CDBBatch& batch) +{ + for (supportQueueType::iterator itQueue = dirtySupportQueueRows.begin(); itQueue != dirtySupportQueueRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(SUPPORT_QUEUE_ROW, itQueue->first), itQueue->second); + } + } +} + +void CClaimTrie::BatchWriteSupportQueueNameRows(CDBBatch& batch) +{ + for (queueNameType::iterator itQueue = dirtySupportQueueNameRows.begin(); itQueue != dirtySupportQueueNameRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(SUPPORT_QUEUE_NAME_ROW, itQueue->first), itQueue->second); + } + } +} + +void CClaimTrie::BatchWriteSupportExpirationQueueRows(CDBBatch& batch) +{ + for (expirationQueueType::iterator itQueue = dirtySupportExpirationQueueRows.begin(); itQueue != dirtySupportExpirationQueueRows.end(); ++itQueue) + { + if (itQueue->second.empty()) + { + batch.Erase(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first)); + } + else + { + batch.Write(std::make_pair(SUPPORT_EXP_QUEUE_ROW, itQueue->first), itQueue->second); + } + } +} + +bool CClaimTrie::WriteToDisk() +{ + CDBBatch batch(*const_cast(&db)); + for (nodeCacheType::iterator itcache = dirtyNodes.begin(); itcache != dirtyNodes.end(); ++itcache) + BatchWriteNode(batch, itcache->first, itcache->second); + dirtyNodes.clear(); + BatchWriteQueueRows(batch); + dirtyQueueRows.clear(); + BatchWriteQueueNameRows(batch); + dirtyQueueNameRows.clear(); + BatchWriteExpirationQueueRows(batch); + dirtyExpirationQueueRows.clear(); + BatchWriteSupportNodes(batch); + dirtySupportNodes.clear(); + BatchWriteSupportQueueRows(batch); + dirtySupportQueueRows.clear(); + BatchWriteSupportQueueNameRows(batch); + dirtySupportQueueNameRows.clear(); + BatchWriteSupportExpirationQueueRows(batch); + dirtySupportExpirationQueueRows.clear(); + batch.Write(HASH_BLOCK, hashBlock); + batch.Write(CURRENT_HEIGHT, nCurrentHeight); + return db.WriteBatch(batch); +} + +bool CClaimTrie::InsertFromDisk(const std::string& name, CClaimTrieNode* node) +{ + if (name.size() == 0) + { + root = *node; + return true; + } + CClaimTrieNode* current = &root; + for (std::string::const_iterator itname = name.begin(); itname + 1 != name.end(); ++itname) + { + nodeMapType::iterator itchild = current->children.find(*itname); + if (itchild == current->children.end()) + return false; + current = itchild->second; + } + current->children[name[name.size()-1]] = node; + return true; +} + +bool CClaimTrie::ReadFromDisk(bool check) +{ + if (!db.Read(HASH_BLOCK, hashBlock)) + LogPrintf("%s: Couldn't read the best block's hash\n", __func__); + if (!db.Read(CURRENT_HEIGHT, nCurrentHeight)) + LogPrintf("%s: Couldn't read the current height\n", __func__); + setExpirationTime(Params().GetConsensus().GetExpirationTime(nCurrentHeight-1)); + + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + + pcursor->SeekToFirst(); + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + if (key.first == TRIE_NODE) + { + CClaimTrieNode* node = new CClaimTrieNode(); + if (pcursor->GetValue(*node)) + { + if (!InsertFromDisk(key.second, node)) + { + return error("%s(): error restoring claim trie from disk", __func__); + } + } + else + { + return error("%s(): error reading claim trie from disk", __func__); + } + } + } + pcursor->Next(); + } + + if (check) + { + LogPrintf("Checking Claim trie consistency..."); + if (checkConsistency()) + { + LogPrintf("consistent\n"); + return true; + } + LogPrintf("inconsistent!\n"); + return false; + } + return true; +} + +bool CClaimTrieCache::recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, std::string sPos) const +{ + if (sPos == "" && tnCurrent->empty()) + { + cacheHashes[""] = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + return true; + } + std::vector vchToHash; + nodeCacheType::iterator cachedNode; + + for (nodeMapType::iterator it = tnCurrent->children.begin(); it != tnCurrent->children.end(); ++it) + { + std::stringstream ss; + ss << it->first; + std::string sNextPos = sPos + ss.str(); + if (dirtyHashes.count(sNextPos) != 0) + { + // the child might be in the cache, so look for it there + cachedNode = cache.find(sNextPos); + if (cachedNode != cache.end()) + recursiveComputeMerkleHash(cachedNode->second, sNextPos); + else + recursiveComputeMerkleHash(it->second, sNextPos); + } + vchToHash.push_back(it->first); + hashMapType::iterator ithash = cacheHashes.find(sNextPos); + if (ithash != cacheHashes.end()) + { + vchToHash.insert(vchToHash.end(), ithash->second.begin(), ithash->second.end()); + } + else + { + vchToHash.insert(vchToHash.end(), it->second->hash.begin(), it->second->hash.end()); + } + } + + CClaimValue claim; + bool hasClaim = tnCurrent->getBestClaim(claim); + + if (hasClaim) + { + int nHeightOfLastTakeover; + assert(getLastTakeoverForName(sPos, nHeightOfLastTakeover)); + uint256 valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); + vchToHash.insert(vchToHash.end(), valueHash.begin(), valueHash.end()); + } + + CHash256 hasher; + std::vector vchHash(hasher.OUTPUT_SIZE); + hasher.Write(vchToHash.data(), vchToHash.size()); + hasher.Finalize(&(vchHash[0])); + cacheHashes[sPos] = uint256(vchHash); + std::set::iterator itDirty = dirtyHashes.find(sPos); + if (itDirty != dirtyHashes.end()) + dirtyHashes.erase(itDirty); + return true; +} + +uint256 CClaimTrieCache::getMerkleHash() const +{ + if (empty()) + { + uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + return one; + } + if (dirty()) + { + recursiveComputeMerkleHash(getRoot(), ""); + } + hashMapType::iterator ithash = cacheHashes.find(""); + if (ithash != cacheHashes.end()) + return ithash->second; + else + return base->root.hash; +} + +bool CClaimTrieCache::empty() const +{ + return base->empty() && cache.empty(); +} + +CClaimTrieNode* CClaimTrieCache::addNodeToCache(const std::string& position, CClaimTrieNode* original) const +{ + // create a copy of the node in the cache, if new node, create empty node + CClaimTrieNode* cacheCopy; + if(!original) + cacheCopy = new CClaimTrieNode(); + else + cacheCopy = new CClaimTrieNode(*original); + cache[position] = cacheCopy; + + // check to see if there is the original node in block_originals, + // if not, add it to block_originals cache + nodeCacheType::const_iterator itOriginals = block_originals.find(position); + if (block_originals.end() == itOriginals) + { + CClaimTrieNode* originalCopy; + if(!original) + originalCopy = new CClaimTrieNode(); + else + originalCopy = new CClaimTrieNode(*original); + block_originals[position] = originalCopy; + } + return cacheCopy; +} + +bool CClaimTrieCache::getOriginalInfoForName(const std::string& name, CClaimValue& claim) const +{ + nodeCacheType::const_iterator itOriginalCache = block_originals.find(name); + if (itOriginalCache == block_originals.end()) + { + return base->getInfoForName(name, claim); + } + return itOriginalCache->second->getBestClaim(claim); +} + +bool CClaimTrieCache::insertClaimIntoTrie(const std::string& name, CClaimValue claim, bool fCheckTakeover) const +{ + assert(base); + CClaimTrieNode* currentNode = getRoot(); + nodeCacheType::iterator cachedNode; + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sCurrentSubstring(name.begin(), itCur); + std::string sNextSubstring(name.begin(), itCur + 1); + + cachedNode = cache.find(sNextSubstring); + if (cachedNode != cache.end()) + { + currentNode = cachedNode->second; + continue; + } + nodeMapType::iterator childNode = currentNode->children.find(*itCur); + if (childNode != currentNode->children.end()) + { + currentNode = childNode->second; + continue; + } + + // This next substring doesn't exist in the cache and the next + // character doesn't exist in current node's children, so check + // if the current node is in the cache, and if it's not, copy + // it and stick it in the cache, and then create a new node as + // its child and stick that in the cache. We have to have both + // this node and its child in the cache so that the current + // node's child map will contain the next letter, which will be + // used to find the child in the cache. This is necessary in + // order to calculate the merkle hash. + cachedNode = cache.find(sCurrentSubstring); + if (cachedNode != cache.end()) + { + assert(cachedNode->second == currentNode); + } + else + { + currentNode = addNodeToCache(sCurrentSubstring, currentNode); + } + CClaimTrieNode* newNode = addNodeToCache(sNextSubstring, NULL); + currentNode->children[*itCur] = newNode; + currentNode = newNode; + } + + cachedNode = cache.find(name); + if (cachedNode != cache.end()) + { + assert(cachedNode->second == currentNode); + } + else + { + currentNode = addNodeToCache(name, currentNode); + } + bool fChanged = false; + if (currentNode->claims.empty()) + { + fChanged = true; + currentNode->insertClaim(claim); + } + else + { + CClaimValue currentTop = currentNode->claims.front(); + currentNode->insertClaim(claim); + supportMapEntryType node; + getSupportsForName(name, node); + currentNode->reorderClaims(node); + if (currentTop != currentNode->claims.front()) + fChanged = true; + } + + if (fChanged) + { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sub(name.begin(), itCur); + dirtyHashes.insert(sub); + } + dirtyHashes.insert(name); + if (fCheckTakeover) + namesToCheckForTakeover.insert(name); + } + return true; +} + +bool CClaimTrieCache::removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, CClaimValue& claim, bool fCheckTakeover) const +{ + assert(base); + CClaimTrieNode* currentNode = getRoot(); + nodeCacheType::iterator cachedNode; + assert(currentNode != nullptr); // If there is no root in either the trie or the cache, how can there be any names to remove? + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sCurrentSubstring(name.begin(), itCur); + std::string sNextSubstring(name.begin(), itCur + 1); + + cachedNode = cache.find(sNextSubstring); + if (cachedNode != cache.end()) + { + currentNode = cachedNode->second; + continue; + } + nodeMapType::iterator childNode = currentNode->children.find(*itCur); + if (childNode != currentNode->children.end()) + { + currentNode = childNode->second; + continue; + } + LogPrintf("%s: The name %s does not exist in the trie\n", __func__, name.c_str()); + return false; + } + + cachedNode = cache.find(name); + if (cachedNode != cache.end()) + assert(cachedNode->second == currentNode); + else + { + currentNode = addNodeToCache(name, currentNode); + } + bool fChanged = false; + assert(currentNode != NULL); + bool success = false; + + if (currentNode->claims.empty()) + { + LogPrintf("%s: Asked to remove claim from node without claims\n", __func__); + return false; + } + CClaimValue currentTop = currentNode->claims.front(); + + success = currentNode->removeClaim(outPoint, claim); + if (!currentNode->claims.empty()) + { + supportMapEntryType node; + getSupportsForName(name, node); + currentNode->reorderClaims(node); + if (currentTop != currentNode->claims.front()) + fChanged = true; + } + else + fChanged = true; + + if (!success) + { + LogPrintf("%s: Removing a claim was unsuccessful. name = %s, txhash = %s, nOut = %d", __func__, name.c_str(), outPoint.hash.GetHex(), outPoint.n); + return false; + } + + if (fChanged) + { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sub(name.begin(), itCur); + dirtyHashes.insert(sub); + } + dirtyHashes.insert(name); + if (fCheckTakeover) + namesToCheckForTakeover.insert(name); + } + return recursivePruneName(getRoot(), 0, name); +} + +bool CClaimTrieCache::recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, std::string sName, bool* pfNullified) const +{ + // Recursively prune leaf node(s) without any claims in it and store + // the modified nodes in the cache + + bool fNullified = false; + std::string sCurrentSubstring = sName.substr(0, nPos); + if (nPos < sName.size()) + { + std::string sNextSubstring = sName.substr(0, nPos + 1); + unsigned char cNext = sName.at(nPos); + CClaimTrieNode* tnNext = NULL; + nodeCacheType::iterator cachedNode = cache.find(sNextSubstring); + if (cachedNode != cache.end()) + tnNext = cachedNode->second; + else + { + nodeMapType::iterator childNode = tnCurrent->children.find(cNext); + if (childNode != tnCurrent->children.end()) + tnNext = childNode->second; + } + if (tnNext == NULL) + return false; + bool fChildNullified = false; + if (!recursivePruneName(tnNext, nPos + 1, sName, &fChildNullified)) + return false; + if (fChildNullified) + { + // If the child nullified itself, the child should already be + // out of the cache, and the character must now be removed + // from the current node's map of child nodes to ensure that + // it isn't found when calculating the merkle hash. But + // tnCurrent isn't necessarily in the cache. If it's not, it + // has to be added to the cache, so nothing is changed in the + // trie. If the current node is added to the cache, however, + // that does not imply that the parent node must be altered to + // reflect that its child is now in the cache, since it + // already has a character in its child map which will be used + // when calculating the merkle root. + + // First, find out if this node is in the cache. + cachedNode = cache.find(sCurrentSubstring); + if (cachedNode == cache.end()) + { + // it isn't, so make a copy, stick it in the cache, + // and make it the new current node + tnCurrent = addNodeToCache(sCurrentSubstring, tnCurrent); + } + // erase the character from the current node, which is + // now guaranteed to be in the cache + nodeMapType::iterator childNode = tnCurrent->children.find(cNext); + if (childNode != tnCurrent->children.end()) + tnCurrent->children.erase(childNode); + else + return false; + } + } + if (!sCurrentSubstring.empty() && tnCurrent->empty()) + { + // If the current node is in the cache, remove it from there + nodeCacheType::iterator cachedNode = cache.find(sCurrentSubstring); + if (cachedNode != cache.end()) + { + assert(tnCurrent == cachedNode->second); + delete tnCurrent; + cache.erase(cachedNode); + } + fNullified = true; + } + if (pfNullified) + *pfNullified = fNullified; + return true; +} + +claimQueueType::iterator CClaimTrieCache::getQueueCacheRow(int nHeight, bool createIfNotExists) const +{ + claimQueueType::iterator itQueueRow = claimQueueCache.find(nHeight); + if (itQueueRow == claimQueueCache.end()) + { + // Have to make a new row it put in the cache, if createIfNotExists is true + claimQueueRowType queueRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->getQueueRow(nHeight, queueRow); + if (!exists) + if (!createIfNotExists) + return itQueueRow; + // Stick the new row in the cache + std::pair ret; + ret = claimQueueCache.insert(std::pair(nHeight, queueRow)); + assert(ret.second); + itQueueRow = ret.first; + } + return itQueueRow; +} + +queueNameType::iterator CClaimTrieCache::getQueueCacheNameRow(const std::string& name, bool createIfNotExists) const +{ + queueNameType::iterator itQueueNameRow = claimQueueNameCache.find(name); + if (itQueueNameRow == claimQueueNameCache.end()) + { + // Have to make a new name row and put it in the cache, if createIfNotExists is true + queueNameRowType queueNameRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->getQueueNameRow(name, queueNameRow); + if (!exists) + if (!createIfNotExists) + return itQueueNameRow; + // Stick the new row in the cache + std::pair ret; + ret = claimQueueNameCache.insert(std::pair(name, queueNameRow)); + assert(ret.second); + itQueueNameRow = ret.first; + } + return itQueueNameRow; +} + +bool CClaimTrieCache::addClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nCurrentHeight); + assert(nHeight == nCurrentHeight); + CClaimValue currentClaim; + int delayForClaim; + if (getOriginalInfoForName(name, currentClaim) && currentClaim.claimId == claimId) + { + LogPrintf("%s: This is an update to a best claim.\n", __func__); + delayForClaim = 0; + } + else + { + delayForClaim = getDelayForName(name); + } + CClaimValue newClaim(outPoint, claimId, nAmount, nHeight, nHeight + delayForClaim); + return addClaimToQueues(name, newClaim); +} + +bool CClaimTrieCache::undoSpendClaim(const std::string& name, const COutPoint& outPoint, uint160 claimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, claimId: %s, nAmount: %d, nHeight: %d, nValidAtHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, claimId.GetHex(), nAmount, nHeight, nValidAtHeight, nCurrentHeight); + CClaimValue claim(outPoint, claimId, nAmount, nHeight, nValidAtHeight); + if (nValidAtHeight < nCurrentHeight) + { + nameOutPointType entry(name, claim.outPoint); + addToExpirationQueue(claim.nHeight + base->nExpirationTime, entry); + CClaimIndexElement element = {name, claim}; + claimsToAdd.push_back(element); + return insertClaimIntoTrie(name, claim, false); + } + else + { + return addClaimToQueues(name, claim); + } +} + +bool CClaimTrieCache::addClaimToQueues(const std::string& name, CClaimValue& claim) const +{ + LogPrintf("%s: nValidAtHeight: %d\n", __func__, claim.nValidAtHeight); + claimQueueEntryType entry(name, claim); + claimQueueType::iterator itQueueRow = getQueueCacheRow(claim.nValidAtHeight, true); + queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, true); + itQueueRow->second.push_back(entry); + itQueueNameRow->second.push_back(outPointHeightType(claim.outPoint, claim.nValidAtHeight)); + nameOutPointType expireEntry(name, claim.outPoint); + addToExpirationQueue(claim.nHeight + base->nExpirationTime, expireEntry); + CClaimIndexElement element = {name, claim}; + claimsToAdd.push_back(element); + return true; +} + +bool CClaimTrieCache::removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, CClaimValue& claim) const +{ + queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(name, false); + if (itQueueNameRow == claimQueueNameCache.end()) + { + return false; + } + queueNameRowType::iterator itQueueName; + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) + { + if (itQueueName->outPoint == outPoint) + { + break; + } + } + if (itQueueName == itQueueNameRow->second.end()) + { + return false; + } + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); + if (itQueueRow != claimQueueCache.end()) + { + claimQueueRowType::iterator itQueue; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) + { + if (name == itQueue->first && itQueue->second.outPoint == outPoint) + { + break; + } + } + if (itQueue != itQueueRow->second.end()) + { + claim = itQueue->second; + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; + } + } + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named queue but not in height queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); + return false; +} + +bool CClaimTrieCache::undoAddClaim(const std::string& name, const COutPoint& outPoint) const +{ + int throwaway; + return removeClaim(name, outPoint, throwaway, false); +} + +bool CClaimTrieCache::spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const +{ + return removeClaim(name, outPoint, nValidAtHeight, true); +} + +bool CClaimTrieCache::removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %s, nCurrentHeight: %s\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nCurrentHeight); + bool removed = false; + CClaimValue claim; + if (removeClaimFromQueue(name, outPoint, claim)) + { + removed = true; + } + if (removed == false && removeClaimFromTrie(name, outPoint, claim, fCheckTakeover)) + { + removed = true; + } + if (removed == true) + { + nValidAtHeight = claim.nValidAtHeight; + int expirationHeight = claim.nHeight + base->nExpirationTime; + removeFromExpirationQueue(name, outPoint, expirationHeight); + claimsToDelete.insert(claim); + } + return removed; +} + +void CClaimTrieCache::addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +{ + expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(nExpirationHeight, true); + itQueueRow->second.push_back(entry); +} + +void CClaimTrieCache::removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +{ + expirationQueueType::iterator itQueueRow = getExpirationQueueCacheRow(expirationHeight, false); + expirationQueueRowType::iterator itQueue; + if (itQueueRow != expirationQueueCache.end()) + { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) + { + if (name == itQueue->name && outPoint == itQueue->outPoint) + break; + } + + if (itQueue != itQueueRow->second.end()) + { + itQueueRow->second.erase(itQueue); + } + } +} + +expirationQueueType::iterator CClaimTrieCache::getExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const +{ + expirationQueueType::iterator itQueueRow = expirationQueueCache.find(nHeight); + if (itQueueRow == expirationQueueCache.end()) + { + // Have to make a new row it put in the cache, if createIfNotExists is true + expirationQueueRowType queueRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->getExpirationQueueRow(nHeight, queueRow); + if (!exists) + if (!createIfNotExists) + return itQueueRow; + // Stick the new row in the cache + std::pair ret; + ret = expirationQueueCache.insert(std::pair(nHeight, queueRow)); + assert(ret.second); + itQueueRow = ret.first; + } + return itQueueRow; +} + +bool CClaimTrieCache::reorderTrieNode(const std::string& name, bool fCheckTakeover) const +{ + assert(base); + nodeCacheType::iterator cachedNode; + cachedNode = cache.find(name); + if (cachedNode == cache.end()) + { + CClaimTrieNode* currentNode = getRoot(); + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sCurrentSubstring(name.begin(), itCur); + std::string sNextSubstring(name.begin(), itCur + 1); + + cachedNode = cache.find(sNextSubstring); + if (cachedNode != cache.end()) + { + currentNode = cachedNode->second; + continue; + } + nodeMapType::iterator childNode = currentNode->children.find(*itCur); + if (childNode != currentNode->children.end()) + { + currentNode = childNode->second; + continue; + } + // The node doesn't exist, so it can't be reordered. + return true; + } + currentNode = new CClaimTrieNode(*currentNode); + std::pair ret; + ret = cache.insert(std::pair(name, currentNode)); + assert(ret.second); + cachedNode = ret.first; + } + bool fChanged = false; + if (cachedNode->second->claims.empty()) + { + // Nothing in there to reorder + return true; + } + else + { + CClaimValue currentTop = cachedNode->second->claims.front(); + supportMapEntryType node; + getSupportsForName(name, node); + cachedNode->second->reorderClaims(node); + if (cachedNode->second->claims.front() != currentTop) + fChanged = true; + } + if (fChanged) + { + for (std::string::const_iterator itCur = name.begin(); itCur != name.end(); ++itCur) + { + std::string sub(name.begin(), itCur); + dirtyHashes.insert(sub); + } + dirtyHashes.insert(name); + if (fCheckTakeover) + namesToCheckForTakeover.insert(name); + } + return true; +} + +bool CClaimTrieCache::getSupportsForName(const std::string& name, supportMapEntryType& node) const +{ + supportMapType::iterator cachedNode; + cachedNode = supportCache.find(name); + if (cachedNode != supportCache.end()) + { + node = cachedNode->second; + return true; + } + else + { + return base->getSupportNode(name, node); + } +} + +bool CClaimTrieCache::insertSupportIntoMap(const std::string& name, CSupportValue support, bool fCheckTakeover) const +{ + supportMapType::iterator cachedNode; + // If this node is already in the cache, use that + cachedNode = supportCache.find(name); + // If not, copy the one from base if it exists, and use that + if (cachedNode == supportCache.end()) + { + supportMapEntryType node; + base->getSupportNode(name, node); + std::pair ret; + ret = supportCache.insert(std::pair(name, node)); + assert(ret.second); + cachedNode = ret.first; + } + cachedNode->second.push_back(support); + // See if this changed the biggest bid + return reorderTrieNode(name, fCheckTakeover); +} + +bool CClaimTrieCache::removeSupportFromMap(const std::string& name, const COutPoint& outPoint, CSupportValue& support, bool fCheckTakeover) const +{ + supportMapType::iterator cachedNode; + cachedNode = supportCache.find(name); + if (cachedNode == supportCache.end()) + { + supportMapEntryType node; + if (!base->getSupportNode(name, node)) + { + // clearly, this support does not exist + return false; + } + std::pair ret; + ret = supportCache.insert(std::pair(name, node)); + assert(ret.second); + cachedNode = ret.first; + } + supportMapEntryType::iterator itSupport; + for (itSupport = cachedNode->second.begin(); itSupport != cachedNode->second.end(); ++itSupport) + { + if (itSupport->outPoint == outPoint) + { + break; + } + } + if (itSupport != cachedNode->second.end()) + { + claimtrie::swap(support, *itSupport); + cachedNode->second.erase(itSupport); + return reorderTrieNode(name, fCheckTakeover); + } + else + { + LogPrintf("CClaimTrieCache::%s() : asked to remove a support that doesn't exist\n", __func__); + return false; + } +} + +supportQueueType::iterator CClaimTrieCache::getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const +{ + supportQueueType::iterator itQueueRow = supportQueueCache.find(nHeight); + if (itQueueRow == supportQueueCache.end()) + { + supportQueueRowType queueRow; + bool exists = base->getSupportQueueRow(nHeight, queueRow); + if (!exists) + if (!createIfNotExists) + return itQueueRow; + // Stick the new row in the cache + std::pair ret; + ret = supportQueueCache.insert(std::pair(nHeight, queueRow)); + assert(ret.second); + itQueueRow = ret.first; + } + return itQueueRow; +} + +queueNameType::iterator CClaimTrieCache::getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const +{ + queueNameType::iterator itQueueNameRow = supportQueueNameCache.find(name); + if (itQueueNameRow == supportQueueNameCache.end()) + { + queueNameRowType queueNameRow; + bool exists = base->getSupportQueueNameRow(name, queueNameRow); + if (!exists) + if (!createIfNotExists) + return itQueueNameRow; + // Stick the new row in the name cache + std::pair ret; + ret = supportQueueNameCache.insert(std::pair(name, queueNameRow)); + assert(ret.second); + itQueueNameRow = ret.first; + } + return itQueueNameRow; +} + +bool CClaimTrieCache::addSupportToQueues(const std::string& name, CSupportValue& support) const +{ + LogPrintf("%s: nValidAtHeight: %d\n", __func__, support.nValidAtHeight); + supportQueueEntryType entry(name, support); + supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(support.nValidAtHeight, true); + queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, true); + itQueueRow->second.push_back(entry); + itQueueNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); + nameOutPointType expireEntry(name, support.outPoint); + addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, expireEntry); + return true; +} + +bool CClaimTrieCache::removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, CSupportValue& support) const +{ + queueNameType::iterator itQueueNameRow = getSupportQueueCacheNameRow(name, false); + if (itQueueNameRow == supportQueueNameCache.end()) + { + return false; + } + queueNameRowType::iterator itQueueName; + for (itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) + { + if (itQueueName->outPoint == outPoint) + { + break; + } + } + if (itQueueName == itQueueNameRow->second.end()) + { + return false; + } + supportQueueType::iterator itQueueRow = getSupportQueueCacheRow(itQueueName->nHeight, false); + if (itQueueRow != supportQueueCache.end()) + { + supportQueueRowType::iterator itQueue; + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) + { + CSupportValue& support = itQueue->second; + if (name == itQueue->first && support.outPoint == outPoint) + { + break; + } + } + if (itQueue != itQueueRow->second.end()) + { + claimtrie::swap(support, itQueue->second); + itQueueNameRow->second.erase(itQueueName); + itQueueRow->second.erase(itQueue); + return true; + } + } + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in named support queue but not in height support queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, itQueueName->nHeight, nCurrentHeight); + return false; +} + +bool CClaimTrieCache::addSupport(const std::string& name, const COutPoint& outPoint, CAmount nAmount, uint160 supportedClaimId, int nHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); + assert(nHeight == nCurrentHeight); + CClaimValue claim; + int delayForSupport; + if (getOriginalInfoForName(name, claim) && claim.claimId == supportedClaimId) + { + LogPrintf("%s: This is a support to a best claim.\n", __func__); + delayForSupport = 0; + } + else + { + delayForSupport = getDelayForName(name); + } + CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nHeight + delayForSupport); + return addSupportToQueues(name, support); +} + +bool CClaimTrieCache::undoSpendSupport(const std::string& name, const COutPoint& outPoint, uint160 supportedClaimId, CAmount nAmount, int nHeight, int nValidAtHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nAmount: %d, supportedClaimId: %s, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nAmount, supportedClaimId.GetHex(), nHeight, nCurrentHeight); + CSupportValue support(outPoint, supportedClaimId, nAmount, nHeight, nValidAtHeight); + if (nValidAtHeight < nCurrentHeight) + { + nameOutPointType entry(name, support.outPoint); + addSupportToExpirationQueue(support.nHeight + base->nExpirationTime, entry); + return insertSupportIntoMap(name, support, false); + } + else + { + return addSupportToQueues(name, support); + } +} + +bool CClaimTrieCache::removeSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight, bool fCheckTakeover) const +{ + bool removed = false; + CSupportValue support; + if (removeSupportFromQueue(name, outPoint, support)) + removed = true; + if (removed == false && removeSupportFromMap(name, outPoint, support, fCheckTakeover)) + removed = true; + if (removed) + { + int expirationHeight = nHeight + base->nExpirationTime; + removeSupportFromExpirationQueue(name, outPoint, expirationHeight); + nValidAtHeight = support.nValidAtHeight; + } + return removed; +} + +void CClaimTrieCache::addSupportToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const +{ + expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(nExpirationHeight, true); + itQueueRow->second.push_back(entry); +} + +void CClaimTrieCache::removeSupportFromExpirationQueue(const std::string& name, const COutPoint& outPoint, int expirationHeight) const +{ + expirationQueueType::iterator itQueueRow = getSupportExpirationQueueCacheRow(expirationHeight, false); + expirationQueueRowType::iterator itQueue; + if (itQueueRow != supportExpirationQueueCache.end()) + { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) + { + if (name == itQueue->name && outPoint == itQueue->outPoint) + break; + } + } + if (itQueue != itQueueRow->second.end()) + { + itQueueRow->second.erase(itQueue); + } +} + +expirationQueueType::iterator CClaimTrieCache::getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const +{ + expirationQueueType::iterator itQueueRow = supportExpirationQueueCache.find(nHeight); + if (itQueueRow == supportExpirationQueueCache.end()) + { + // Have to make a new row it put in the cache, if createIfNotExists is true + expirationQueueRowType queueRow; + // If the row exists in the base, copy its claims into the new row. + bool exists = base->getSupportExpirationQueueRow(nHeight, queueRow); + if (!exists) + if (!createIfNotExists) + return itQueueRow; + // Stick the new row in the cache + std::pair ret; + ret = supportExpirationQueueCache.insert(std::pair(nHeight, queueRow)); + assert(ret.second); + itQueueRow = ret.first; + } + return itQueueRow; +} + +bool CClaimTrieCache::undoAddSupport(const std::string& name, const COutPoint& outPoint, int nHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); + int throwaway; + return removeSupport(name, outPoint, nHeight, throwaway, false); +} + +bool CClaimTrieCache::spendSupport(const std::string& name, const COutPoint& outPoint, int nHeight, int& nValidAtHeight) const +{ + LogPrintf("%s: name: %s, txhash: %s, nOut: %d, nHeight: %d, nCurrentHeight: %d\n", __func__, name, outPoint.hash.GetHex(), outPoint.n, nHeight, nCurrentHeight); + return removeSupport(name, outPoint, nHeight, nValidAtHeight, true); +} + +bool CClaimTrieCache::incrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +{ + LogPrintf("%s: nCurrentHeight (before increment): %d, claimQueueCache size %d\n", __func__, nCurrentHeight, claimQueueCache.size()); + + claimQueueType::iterator itQueueRow = getQueueCacheRow(nCurrentHeight, false); + if (itQueueRow != claimQueueCache.end()) + { + for (claimQueueRowType::iterator itEntry = itQueueRow->second.begin(); itEntry != itQueueRow->second.end(); ++itEntry) + { + bool found = false; + queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itEntry->first, false); + if (itQueueNameRow != claimQueueNameCache.end()) + { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) + { + if (itQueueName->outPoint == itEntry->second.outPoint && itQueueName->nHeight == nCurrentHeight) + { + found = true; + itQueueNameRow->second.erase(itQueueName); + break; + } + } + } + if (!found) + { + LogPrintf("%s: An inconsistency was found in the claim queue. Please report this to the developers:\nFound in height queue but not in named queue: name: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itEntry->first, itEntry->second.outPoint.hash.GetHex(), itEntry->second.outPoint.n, itEntry->second.nValidAtHeight, nCurrentHeight); + if (itQueueNameRow != claimQueueNameCache.end()) + { + LogPrintf("Claims found for that name:\n"); + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) + { + LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight); + } + } + else + { + LogPrintf("No claims found for that name\n"); + } + } + assert(found); + insertClaimIntoTrie(itEntry->first, itEntry->second, true); + insertUndo.push_back(nameOutPointHeightType(itEntry->first, itEntry->second.outPoint, itEntry->second.nValidAtHeight)); + } + itQueueRow->second.clear(); + } + expirationQueueType::iterator itExpirationRow = getExpirationQueueCacheRow(nCurrentHeight, false); + if (itExpirationRow != expirationQueueCache.end()) + { + for (expirationQueueRowType::iterator itEntry = itExpirationRow->second.begin(); itEntry != itExpirationRow->second.end(); ++itEntry) + { + CClaimValue claim; + assert(removeClaimFromTrie(itEntry->name, itEntry->outPoint, claim, true)); + claimsToDelete.insert(claim); + expireUndo.push_back(std::make_pair(itEntry->name, claim)); + LogPrintf("Expiring claim %s: %s, nHeight: %d, nValidAtHeight: %d\n", claim.claimId.GetHex(), itEntry->name, claim.nHeight, claim.nValidAtHeight); + } + itExpirationRow->second.clear(); + } + supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(nCurrentHeight, false); + if (itSupportRow != supportQueueCache.end()) + { + for (supportQueueRowType::iterator itSupport = itSupportRow->second.begin(); itSupport != itSupportRow->second.end(); ++itSupport) + { + bool found = false; + queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupport->first, false); + if (itSupportNameRow != supportQueueNameCache.end()) + { + for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) + { + if (itSupportName->outPoint == itSupport->second.outPoint && itSupportName->nHeight == itSupport->second.nValidAtHeight) + { + found = true; + itSupportNameRow->second.erase(itSupportName); + break; + } + } + } + if (!found) + { + LogPrintf("%s: An inconsistency was found in the support queue. Please report this to the developers:\nFound in height queue but not in named queue: %s, txid: %s, nOut: %d, nValidAtHeight: %d, current height: %d\n", __func__, itSupport->first, itSupport->second.outPoint.hash.GetHex(), itSupport->second.outPoint.n, itSupport->second.nValidAtHeight, nCurrentHeight); + if (itSupportNameRow != supportQueueNameCache.end()) + { + LogPrintf("Supports found for that name:\n"); + for (queueNameRowType::iterator itSupportName = itSupportNameRow->second.begin(); itSupportName != itSupportNameRow->second.end(); ++itSupportName) + { + LogPrintf("\ttxid: %s, nOut: %d, nValidAtHeight: %d\n", itSupportName->outPoint.hash.GetHex(), itSupportName->outPoint.n, itSupportName->nHeight); + } + } + else + { + LogPrintf("No support found for that name\n"); + } + } + insertSupportIntoMap(itSupport->first, itSupport->second, true); + insertSupportUndo.push_back(nameOutPointHeightType(itSupport->first, itSupport->second.outPoint, itSupport->second.nValidAtHeight)); + } + itSupportRow->second.clear(); + } + expirationQueueType::iterator itSupportExpirationRow = getSupportExpirationQueueCacheRow(nCurrentHeight, false); + if (itSupportExpirationRow != supportExpirationQueueCache.end()) + { + for (expirationQueueRowType::iterator itEntry = itSupportExpirationRow->second.begin(); itEntry != itSupportExpirationRow->second.end(); ++itEntry) + { + CSupportValue support; + assert(removeSupportFromMap(itEntry->name, itEntry->outPoint, support, true)); + expireSupportUndo.push_back(std::make_pair(itEntry->name, support)); + LogPrintf("Expiring support %s: %s, nHeight: %d, nValidAtHeight: %d\n", support.supportedClaimId.GetHex(), itEntry->name, support.nHeight, support.nValidAtHeight); + } + itSupportExpirationRow->second.clear(); + } + // check each potentially taken over name to see if a takeover occurred. + // if it did, then check the claim and support insertion queues for + // the names that have been taken over, immediately insert all claim and + // supports for those names, and stick them in the insertUndo or + // insertSupportUndo vectors, with the nValidAtHeight they had prior to + // this block. + // Run through all names that have been taken over + for (std::set::iterator itNamesToCheck = namesToCheckForTakeover.begin(); itNamesToCheck != namesToCheckForTakeover.end(); ++itNamesToCheck) + { + // Check if a takeover has occurred + nodeCacheType::iterator itCachedNode = cache.find(*itNamesToCheck); + // many possibilities + // if this node is new, don't put it into the undo -- there will be nothing to restore, after all + // if all of this node's claims were deleted, it should be put into the undo -- there could be + // claims in the queue for that name and the takeover height should be the current height + // if the node is not in the cache, or getbestclaim fails, that means all of its claims were + // deleted + // if getOriginalInfoForName returns false, that means it's new and shouldn't go into the undo + // if both exist, and the current best claim is not the same as or the parent to the new best + // claim, then ownership has changed and the current height of last takeover should go into + // the queue + CClaimValue claimInCache; + CClaimValue claimInTrie; + bool haveClaimInCache; + bool haveClaimInTrie; + if (itCachedNode == cache.end()) + { + haveClaimInCache = false; + } + else + { + haveClaimInCache = itCachedNode->second->getBestClaim(claimInCache); + } + haveClaimInTrie = getOriginalInfoForName(*itNamesToCheck, claimInTrie); + bool takeoverHappened = false; + if (!haveClaimInTrie) + { + takeoverHappened = true; + } + else if (!haveClaimInCache) + { + takeoverHappened = true; + } + else if ((claimInCache != claimInTrie) && (claimInCache.claimId != claimInTrie.claimId)) + { + takeoverHappened = true; + } + if (takeoverHappened) + { + // Get all claims in the queue for that name + queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(*itNamesToCheck, false); + if (itQueueNameRow != claimQueueNameCache.end()) + { + for (queueNameRowType::iterator itQueueName = itQueueNameRow->second.begin(); itQueueName != itQueueNameRow->second.end(); ++itQueueName) + { + bool found = false; + // Pull those claims out of the height-based queue + claimQueueType::iterator itQueueRow = getQueueCacheRow(itQueueName->nHeight, false); + claimQueueRowType::iterator itQueue; + if (itQueueRow != claimQueueCache.end()) + { + for (itQueue = itQueueRow->second.begin(); itQueue != itQueueRow->second.end(); ++itQueue) + { + if (*itNamesToCheck == itQueue->first && itQueue->second.outPoint == itQueueName->outPoint && itQueue->second.nValidAtHeight == itQueueName->nHeight) + { + found = true; + break; + } + } + } + if (found) + { + // Insert them into the queue undo with their previous nValidAtHeight + insertUndo.push_back(nameOutPointHeightType(itQueue->first, itQueue->second.outPoint, itQueue->second.nValidAtHeight)); + // Insert them into the name trie with the new nValidAtHeight + itQueue->second.nValidAtHeight = nCurrentHeight; + insertClaimIntoTrie(itQueue->first, itQueue->second, false); + // Delete them from the height-based queue + itQueueRow->second.erase(itQueue); + } + else + { + LogPrintf("%s(): An inconsistency was found in the claim queue. Please report this to the developers:\nClaim found in name queue but not in height based queue:\nname: %s, txid: %s, nOut: %d, nValidAtHeight in name based queue: %d, current height: %d\n", __func__, *itNamesToCheck, itQueueName->outPoint.hash.GetHex(), itQueueName->outPoint.n, itQueueName->nHeight, nCurrentHeight); + } + assert(found); + } + // remove all claims from the queue for that name + itQueueNameRow->second.clear(); + } + // + // Then, get all supports in the queue for that name + queueNameType::iterator itSupportQueueNameRow = getSupportQueueCacheNameRow(*itNamesToCheck, false); + if (itSupportQueueNameRow != supportQueueNameCache.end()) + { + for (queueNameRowType::iterator itSupportQueueName = itSupportQueueNameRow->second.begin(); itSupportQueueName != itSupportQueueNameRow->second.end(); ++itSupportQueueName) + { + // Pull those supports out of the height-based queue + supportQueueType::iterator itSupportQueueRow = getSupportQueueCacheRow(itSupportQueueName->nHeight, false); + if (itSupportQueueRow != supportQueueCache.end()) + { + supportQueueRowType::iterator itSupportQueue; + for (itSupportQueue = itSupportQueueRow->second.begin(); itSupportQueue != itSupportQueueRow->second.end(); ++itSupportQueue) + { + if (*itNamesToCheck == itSupportQueue->first && itSupportQueue->second.outPoint == itSupportQueueName->outPoint && itSupportQueue->second.nValidAtHeight == itSupportQueueName->nHeight) + { + break; + } + } + if (itSupportQueue != itSupportQueueRow->second.end()) + { + // Insert them into the support queue undo with the previous nValidAtHeight + insertSupportUndo.push_back(nameOutPointHeightType(itSupportQueue->first, itSupportQueue->second.outPoint, itSupportQueue->second.nValidAtHeight)); + // Insert them into the support map with the new nValidAtHeight + itSupportQueue->second.nValidAtHeight = nCurrentHeight; + insertSupportIntoMap(itSupportQueue->first, itSupportQueue->second, false); + // Delete them from the height-based queue + itSupportQueueRow->second.erase(itSupportQueue); + } + else + { + // here be problems TODO: show error, assert false + } + } + else + { + // here be problems + } + } + // remove all supports from the queue for that name + itSupportQueueNameRow->second.clear(); + } + + // save the old last height so that it can be restored if the block is undone + if (haveClaimInTrie) + { + int nHeightOfLastTakeover; + assert(getLastTakeoverForName(*itNamesToCheck, nHeightOfLastTakeover)); + takeoverHeightUndo.push_back(std::make_pair(*itNamesToCheck, nHeightOfLastTakeover)); + } + itCachedNode = cache.find(*itNamesToCheck); + if (itCachedNode != cache.end()) + { + cacheTakeoverHeights[*itNamesToCheck] = nCurrentHeight; + } + } + } + for (nodeCacheType::const_iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) + { + delete itOriginals->second; + } + block_originals.clear(); + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) + { + block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); + } + namesToCheckForTakeover.clear(); + nCurrentHeight++; + return true; +} + +bool CClaimTrieCache::decrementBlock(insertUndoType& insertUndo, claimQueueRowType& expireUndo, insertUndoType& insertSupportUndo, supportQueueRowType& expireSupportUndo, std::vector >& takeoverHeightUndo) const +{ + LogPrintf("%s: nCurrentHeight (before decrement): %d\n", __func__, nCurrentHeight); + nCurrentHeight--; + + if (expireSupportUndo.begin() != expireSupportUndo.end()) + { + expirationQueueType::iterator itSupportExpireRow = getSupportExpirationQueueCacheRow(nCurrentHeight, true); + for (supportQueueRowType::iterator itSupportExpireUndo = expireSupportUndo.begin(); itSupportExpireUndo != expireSupportUndo.end(); ++itSupportExpireUndo) + { + insertSupportIntoMap(itSupportExpireUndo->first, itSupportExpireUndo->second, false); + itSupportExpireRow->second.push_back(nameOutPointType(itSupportExpireUndo->first, itSupportExpireUndo->second.outPoint)); + } + } + + for (insertUndoType::iterator itSupportUndo = insertSupportUndo.begin(); itSupportUndo != insertSupportUndo.end(); ++itSupportUndo) + { + supportQueueType::iterator itSupportRow = getSupportQueueCacheRow(itSupportUndo->nHeight, true); + CSupportValue support; + assert(removeSupportFromMap(itSupportUndo->name, itSupportUndo->outPoint, support, false)); + queueNameType::iterator itSupportNameRow = getSupportQueueCacheNameRow(itSupportUndo->name, true); + itSupportRow->second.push_back(std::make_pair(itSupportUndo->name, support)); + itSupportNameRow->second.push_back(outPointHeightType(support.outPoint, support.nValidAtHeight)); + } + + if (expireUndo.begin() != expireUndo.end()) + { + expirationQueueType::iterator itExpireRow = getExpirationQueueCacheRow(nCurrentHeight, true); + for (claimQueueRowType::iterator itExpireUndo = expireUndo.begin(); itExpireUndo != expireUndo.end(); ++itExpireUndo) + { + insertClaimIntoTrie(itExpireUndo->first, itExpireUndo->second, false); + CClaimIndexElement element = {itExpireUndo->first, itExpireUndo->second}; + claimsToAdd.push_back(element); + itExpireRow->second.push_back(nameOutPointType(itExpireUndo->first, itExpireUndo->second.outPoint)); + } + } + + for (insertUndoType::iterator itInsertUndo = insertUndo.begin(); itInsertUndo != insertUndo.end(); ++itInsertUndo) + { + claimQueueType::iterator itQueueRow = getQueueCacheRow(itInsertUndo->nHeight, true); + CClaimValue claim; + assert(removeClaimFromTrie(itInsertUndo->name, itInsertUndo->outPoint, claim, false)); + queueNameType::iterator itQueueNameRow = getQueueCacheNameRow(itInsertUndo->name, true); + itQueueRow->second.push_back(std::make_pair(itInsertUndo->name, claim)); + itQueueNameRow->second.push_back(outPointHeightType(itInsertUndo->outPoint, itInsertUndo->nHeight)); + } + + for (std::vector >::iterator itTakeoverHeightUndo = takeoverHeightUndo.begin(); itTakeoverHeightUndo != takeoverHeightUndo.end(); ++itTakeoverHeightUndo) + { + cacheTakeoverHeights[itTakeoverHeightUndo->first] = itTakeoverHeightUndo->second; + } + + return true; +} + +bool CClaimTrieCache::finalizeDecrement() const +{ + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) + { + delete itOriginals->second; + } + block_originals.clear(); + for (nodeCacheType::const_iterator itCache = cache.begin(); itCache != cache.end(); ++itCache) + { + block_originals[itCache->first] = new CClaimTrieNode(*(itCache->second)); + } + return true; +} + +bool CClaimTrieCache::getLastTakeoverForName(const std::string& name, int& nLastTakeoverForName) const +{ + if (!fRequireTakeoverHeights) + { + nLastTakeoverForName = 0; + return true; + } + std::map::iterator itHeights = cacheTakeoverHeights.find(name); + if (itHeights == cacheTakeoverHeights.end()) + { + return base->getLastTakeoverForName(name, nLastTakeoverForName); + } + nLastTakeoverForName = itHeights->second; + return true; +} + +int CClaimTrieCache::getNumBlocksOfContinuousOwnership(const std::string& name) const +{ + const CClaimTrieNode* node = getNodeForName(name); + if (node == nullptr || node->claims.empty()) + return 0; + int nLastTakeoverHeight; + if (!getLastTakeoverForName(name, nLastTakeoverHeight)) + return 0; + return nCurrentHeight - nLastTakeoverHeight; +} + +const CClaimTrieNode* CClaimTrieCache::getNodeForName(const std::string& name) const +{ + nodeCacheType::const_iterator itCache = cache.find(name); + return ((itCache != cache.end()) ? itCache->second : base->getNodeForName(name)); +} + +int CClaimTrieCache::getDelayForName(const std::string& name) const +{ + if (!fRequireTakeoverHeights) + { + return 0; + } + int nBlocksOfContinuousOwnership = getNumBlocksOfContinuousOwnership(name); + return std::min(nBlocksOfContinuousOwnership / base->nProportionalDelayFactor, 4032); +} + +uint256 CClaimTrieCache::getBestBlock() +{ + if (hashBlock.IsNull()) + if (base != NULL) + hashBlock = base->hashBlock; + return hashBlock; +} + +void CClaimTrieCache::setBestBlock(const uint256& hashBlockIn) +{ + hashBlock = hashBlockIn; +} + +bool CClaimTrieCache::clear() const +{ + for (nodeCacheType::iterator itcache = cache.begin(); itcache != cache.end(); ++itcache) + { + delete itcache->second; + } + cache.clear(); + for (nodeCacheType::iterator itOriginals = block_originals.begin(); itOriginals != block_originals.end(); ++itOriginals) + { + delete itOriginals->second; + } + block_originals.clear(); + dirtyHashes.clear(); + cacheHashes.clear(); + claimQueueCache.clear(); + claimQueueNameCache.clear(); + expirationQueueCache.clear(); + supportCache.clear(); + supportQueueCache.clear(); + supportQueueNameCache.clear(); + supportExpirationQueueCache.clear(); + namesToCheckForTakeover.clear(); + cacheTakeoverHeights.clear(); + return true; +} + +bool CClaimTrieCache::flush() +{ + if (dirty()) + getMerkleHash(); + + if (!claimsToDelete.empty()) { + for (claimIndexClaimListType::iterator it = claimsToDelete.begin(); it != claimsToDelete.end(); ++it) + base->removeFromClaimIndex(*it); + claimsToDelete.clear(); + } + if (!claimsToAdd.empty()) { + for (claimIndexElementListType::iterator it = claimsToAdd.begin(); it != claimsToAdd.end(); ++it) + base->addToClaimIndex(it->name, it->claim); + claimsToAdd.clear(); + } + + bool success = base->update(cache, cacheHashes, cacheTakeoverHeights, getBestBlock(), claimQueueCache, claimQueueNameCache, expirationQueueCache, nCurrentHeight, supportCache, supportQueueCache, supportQueueNameCache, supportExpirationQueueCache); + if (success) + { + success = clear(); + } + return success; +} + +uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, const CClaimTrieNode* currentNode) const +{ + std::stringstream leafPosition; + leafPosition << currentPosition << nodeChar; + hashMapType::iterator cachedHash = cacheHashes.find(leafPosition.str()); + return (cachedHash != cacheHashes.end()) ? cachedHash->second : currentNode->hash; +} + +void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const +{ + nodes.push_back(std::make_pair(name, *current)); + nodeCacheType::const_iterator cachedNode; + for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) { + const std::string str = name + char(it->first); + cachedNode = cache.find(str); + if (cachedNode != cache.end()) + recursiveFlattenTrie(str, cachedNode->second, nodes); + else + recursiveFlattenTrie(str, it->second, nodes); + } +} + +std::vector CClaimTrieCache::flattenTrie() const +{ + std::vector nodes; + recursiveFlattenTrie("", getRoot(), nodes); + return nodes; +} + +claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const +{ + int nLastTakeoverHeight = 0; + std::vector claims; + if (const CClaimTrieNode* node = getNodeForName(name)) { + claims = node->claims; + getLastTakeoverForName(name, nLastTakeoverHeight); + } + supportMapEntryType supports; + getSupportsForName(name, supports); + queueNameType::const_iterator itQueueNameCache = getQueueCacheNameRow(name, false); + if (itQueueNameCache != claimQueueNameCache.end()) { + const queueNameRowType& namedClaimRow = itQueueNameCache->second; + for (queueNameRowType::const_iterator itClaimsForName = namedClaimRow.begin(); itClaimsForName != namedClaimRow.end(); ++itClaimsForName) { + claimQueueType::const_iterator itQueueCache = getQueueCacheRow(itClaimsForName->nHeight, false); + if (itQueueCache != claimQueueCache.end()) { + const claimQueueRowType& claimRow = itQueueCache->second; + for (claimQueueRowType::const_iterator itClaimRow = claimRow.begin(); itClaimRow != claimRow.end(); ++itClaimRow) { + if (itClaimRow->first == name && itClaimRow->second.outPoint == itClaimsForName->outPoint) { + claims.push_back(itClaimRow->second); + break; + } + } + } + } + } + queueNameType::const_iterator itSupportQueueNameCache = getSupportQueueCacheNameRow(name, false); + if (itSupportQueueNameCache != supportQueueNameCache.end()) { + const queueNameRowType& namedSupportRow = itSupportQueueNameCache->second; + for (queueNameRowType::const_iterator itSupportsForName = namedSupportRow.begin(); itSupportsForName != namedSupportRow.end(); ++itSupportsForName) { + supportQueueType::const_iterator itSupportQueueCache = getSupportQueueCacheRow(itSupportsForName->nHeight, false); + if (itSupportQueueCache != supportQueueCache.end()) { + const supportQueueRowType& supportRow = itSupportQueueCache->second; + for (supportQueueRowType::const_iterator itSupportRow = supportRow.begin(); itSupportRow != supportRow.end(); ++itSupportRow) { + if (itSupportRow->first == name && itSupportRow->second.outPoint == itSupportsForName->outPoint) { + supports.push_back(itSupportRow->second); + break; + } + } + } + } + } + return claimsForNameType(claims, supports, nLastTakeoverHeight); +} + +CAmount CClaimTrieCache::getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports) const +{ + return getEffectiveAmountForClaim(getClaimsForName(name), claimId, supports); +} + +CAmount CClaimTrieCache::getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports) const +{ + CAmount effectiveAmount = 0; + for (std::vector::const_iterator it = claims.claims.begin(); it != claims.claims.end(); ++it) { + if (it->claimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + for (std::vector::const_iterator it = claims.supports.begin(); it != claims.supports.end(); ++it) { + if (it->supportedClaimId == claimId && it->nValidAtHeight < nCurrentHeight) { + effectiveAmount += it->nAmount; + if (supports) supports->push_back(*it); + } + } + break; + } + } + return effectiveAmount; +} + +bool CClaimTrieCache::getInfoForName(const std::string& name, CClaimValue& claim) const +{ + if (dirty()) + getMerkleHash(); + + CClaimTrieNode* current = getRoot(); + nodeCacheType::const_iterator cachedNode; + + for (std::string::const_iterator itName = name.begin(); current; ++itName) { + std::string currentPosition(name.begin(), itName); + cachedNode = cache.find(currentPosition); + if (cachedNode != cache.end()) + current = cachedNode->second; + + if (itName == name.end()) + return current->getBestClaim(claim); + + nodeMapType::const_iterator itChildren = current->children.find(*itName); + if (itChildren != current->children.end()) { + current = itChildren->second; + } + } + return false; +} + +bool CClaimTrieCache::getProofForName(const std::string& name, CClaimTrieProof& proof) const +{ + if (dirty()) + getMerkleHash(); + + std::vector nodes; + CClaimTrieNode* current = getRoot(); + nodeCacheType::const_iterator cachedNode; + bool fNameHasValue = false; + COutPoint outPoint; + int nHeightOfLastTakeover = 0; + for (std::string::const_iterator itName = name.begin(); current; ++itName) + { + std::string currentPosition(name.begin(), itName); + cachedNode = cache.find(currentPosition); + if (cachedNode != cache.end()) + current = cachedNode->second; + CClaimValue claim; + bool fNodeHasValue = current->getBestClaim(claim); + uint256 valueHash; + if (fNodeHasValue) + { + int nHeightOfLastTakeover; + if (!getLastTakeoverForName(currentPosition, nHeightOfLastTakeover)) + return false; + valueHash = getValueHash(claim.outPoint, nHeightOfLastTakeover); + } + std::vector > children; + CClaimTrieNode* nextCurrent = NULL; + for (nodeMapType::const_iterator itChildren = current->children.begin(); itChildren != current->children.end(); ++itChildren) + { + if (itName == name.end() || itChildren->first != *itName) // Leaf node + { + uint256 childHash = getLeafHashForProof(currentPosition, itChildren->first, itChildren->second); + children.push_back(std::make_pair(itChildren->first, childHash)); + } + else // Full node + { + nextCurrent = itChildren->second; + uint256 childHash; + children.push_back(std::make_pair(itChildren->first, childHash)); + } + } + if (currentPosition == name) + { + fNameHasValue = fNodeHasValue; + if (fNameHasValue) + { + outPoint = claim.outPoint; + if (!getLastTakeoverForName(name, nHeightOfLastTakeover)) + return false; + } + valueHash.SetNull(); + } + CClaimTrieProofNode node(children, fNodeHasValue, valueHash); + nodes.push_back(node); + current = nextCurrent; + } + proof = CClaimTrieProof(nodes, fNameHasValue, outPoint, nHeightOfLastTakeover); + return true; +} + + +void CClaimTrieCache::removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +{ + for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) + { + // remove and insert with new expiration time + removeFromExpirationQueue(e->name, e->outPoint, height); + int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; + int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration; + nameOutPointType entry(e->name, e->outPoint); + addToExpirationQueue(new_expiration_height, entry); + } + +} + +void CClaimTrieCache::removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const +{ + for (expirationQueueRowType::iterator e = row.begin(); e != row.end(); ++e) + { + // remove and insert with new expiration time + removeSupportFromExpirationQueue(e->name, e->outPoint, height); + int extend_expiration = Params().GetConsensus().nExtendedClaimExpirationTime - Params().GetConsensus().nOriginalClaimExpirationTime; + int new_expiration_height = increment ? height + extend_expiration : height - extend_expiration; + nameOutPointType entry(e->name, e->outPoint); + addSupportToExpirationQueue(new_expiration_height, entry); + } + +} + +bool CClaimTrieCache::forkForExpirationChange(bool increment) const +{ + /* + If increment is True, we have forked to extend the expiration time, thus items in the expiration queue + will have their expiration extended by "new expiration time - original expiration time" + + If increment is False, we are decremented a block to reverse the fork. Thus items in the expiration queue + will have their expiration extension removed. + */ + + // look through dirty expiration queues + std::set dirtyHeights; + for (expirationQueueType::const_iterator i = base->dirtyExpirationQueueRows.begin(); i != base->dirtyExpirationQueueRows.end(); ++i) + { + int height = i->first; + dirtyHeights.insert(height); + expirationQueueRowType row = i->second; + removeAndAddToExpirationQueue(row, height, increment); + } + + std::set dirtySupportHeights; + for (expirationQueueType::const_iterator i = base->dirtySupportExpirationQueueRows.begin(); i != base->dirtySupportExpirationQueueRows.end(); ++i) + { + int height = i->first; + dirtySupportHeights.insert(height); + expirationQueueRowType row = i->second; + removeAndAddSupportToExpirationQueue(row, height, increment); + } + + + //look through db for expiration queues, if we haven't already found it in dirty expiration queue + boost::scoped_ptr pcursor(const_cast(&base->db)->NewIterator()); + pcursor->SeekToFirst(); + while (pcursor->Valid()) + { + std::pair key; + if (pcursor->GetKey(key)) + { + int height = key.second; + // if we've looked through this in dirtyExprirationQueueRows, don't use it + // because its stale + if ((key.first == EXP_QUEUE_ROW) & (dirtyHeights.count(height) == 0)) + { + expirationQueueRowType row; + if (pcursor->GetValue(row)) + { + removeAndAddToExpirationQueue(row, height, increment); + } + else + { + return error("%s(): error reading expiration queue rows from disk", __func__); + } + } + else if ((key.first == SUPPORT_EXP_QUEUE_ROW) & (dirtySupportHeights.count(height) == 0)) + { + expirationQueueRowType row; + if (pcursor->GetValue(row)) + { + removeAndAddSupportToExpirationQueue(row, height, increment); + } + else + { + return error("%s(): error reading support expiration queue rows from disk", __func__); + } + } + + } + pcursor->Next(); + } + + return true; +} + diff --git a/src/claimtrie.h b/src/claimtrie.h new file mode 100644 index 000000000..8aa90e878 --- /dev/null +++ b/src/claimtrie.h @@ -0,0 +1,655 @@ +#ifndef BITCOIN_CLAIMTRIE_H +#define BITCOIN_CLAIMTRIE_H + +#include "amount.h" +#include "serialize.h" +#include "uint256.h" +#include "util.h" +#include "dbwrapper.h" +#include "chainparams.h" +#include "primitives/transaction.h" + +#include +#include +#include + +// leveldb keys +#define HASH_BLOCK 'h' +#define CURRENT_HEIGHT 't' +#define TRIE_NODE 'n' +#define CLAIM_BY_ID 'i' +#define CLAIM_QUEUE_ROW 'r' +#define CLAIM_QUEUE_NAME_ROW 'm' +#define EXP_QUEUE_ROW 'e' +#define SUPPORT 's' +#define SUPPORT_QUEUE_ROW 'u' +#define SUPPORT_QUEUE_NAME_ROW 'p' +#define SUPPORT_EXP_QUEUE_ROW 'x' + +uint256 getValueHash(COutPoint outPoint, int nHeightOfLastTakeover); + +// Provides pre-C++11 copy semantics of std::swap, rather than move +// semantics (available in C++11). +namespace claimtrie +{ + +template + static inline void swap(T& x, T& y) { + const auto tmp = x; + y = x; + x = tmp; +} + +} // namespace claimtrie + +class CClaimValue +{ +public: + COutPoint outPoint; + uint160 claimId; + CAmount nAmount; + CAmount nEffectiveAmount; + int nHeight; + int nValidAtHeight; + + CClaimValue() {}; + + CClaimValue(COutPoint outPoint, uint160 claimId, CAmount nAmount, int nHeight, + int nValidAtHeight) + : outPoint(outPoint), claimId(claimId) + , nAmount(nAmount), nEffectiveAmount(nAmount) + , nHeight(nHeight), nValidAtHeight(nValidAtHeight) + {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(outPoint); + READWRITE(claimId); + READWRITE(nAmount); + READWRITE(nHeight); + READWRITE(nValidAtHeight); + } + + bool operator<(const CClaimValue& other) const + { + if (nEffectiveAmount < other.nEffectiveAmount) + return true; + else if (nEffectiveAmount == other.nEffectiveAmount) + { + if (nHeight > other.nHeight) + return true; + else if (nHeight == other.nHeight) + { + if (outPoint != other.outPoint && !(outPoint < other.outPoint)) + return true; + } + } + return false; + } + + bool operator==(const CClaimValue& other) const + { + return outPoint == other.outPoint && claimId == other.claimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; + } + + bool operator!=(const CClaimValue& other) const + { + return !(*this == other); + } +}; + +class CSupportValue +{ +public: + COutPoint outPoint; + uint160 supportedClaimId; + CAmount nAmount; + int nHeight; + int nValidAtHeight; + + CSupportValue() {}; + CSupportValue(COutPoint outPoint, uint160 supportedClaimId, + CAmount nAmount, int nHeight, int nValidAtHeight) + : outPoint(outPoint), supportedClaimId(supportedClaimId) + , nAmount(nAmount), nHeight(nHeight) + , nValidAtHeight(nValidAtHeight) + {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(outPoint); + READWRITE(supportedClaimId); + READWRITE(nAmount); + READWRITE(nHeight); + READWRITE(nValidAtHeight); + } + + bool operator==(const CSupportValue& other) const + { + return outPoint == other.outPoint && supportedClaimId == other.supportedClaimId && nAmount == other.nAmount && nHeight == other.nHeight && nValidAtHeight == other.nValidAtHeight; + } + + bool operator!=(const CSupportValue& other) const + { + return !(*this == other); + } +}; + +class CClaimTrieNode; +class CClaimTrie; + +typedef std::vector supportMapEntryType; + +typedef std::map nodeMapType; + +typedef std::pair namedNodeType; + +class CClaimTrieNode +{ +public: + CClaimTrieNode() : nHeightOfLastTakeover(0) {} + CClaimTrieNode(uint256 hash) : hash(hash), nHeightOfLastTakeover(0) {} + uint256 hash; + nodeMapType children; + int nHeightOfLastTakeover; + std::vector claims; + + bool insertClaim(CClaimValue claim); + bool removeClaim(const COutPoint& outPoint, CClaimValue& claim); + bool getBestClaim(CClaimValue& claim) const; + bool empty() const {return children.empty() && claims.empty();} + bool haveClaim(const COutPoint& outPoint) const; + void reorderClaims(supportMapEntryType& supports); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(hash); + READWRITE(claims); + READWRITE(nHeightOfLastTakeover); + } + + bool operator==(const CClaimTrieNode& other) const + { + return hash == other.hash && claims == other.claims; + } + + bool operator!=(const CClaimTrieNode& other) const + { + return !(*this == other); + } +}; + +struct nodenamecompare +{ + bool operator() (const std::string& i, const std::string& j) const + { + if (i.size() == j.size()) + return i < j; + return i.size() < j.size(); + } +}; + +struct outPointHeightType +{ + COutPoint outPoint; + int nHeight; + + outPointHeightType() {} + + outPointHeightType(COutPoint outPoint, int nHeight) + : outPoint(outPoint), nHeight(nHeight) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(outPoint); + READWRITE(nHeight); + } + +}; + +struct nameOutPointHeightType +{ + std::string name; + COutPoint outPoint; + int nHeight; + + nameOutPointHeightType() {} + + nameOutPointHeightType(std::string name, COutPoint outPoint, int nHeight) + : name(name), outPoint(outPoint), nHeight(nHeight) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(name); + READWRITE(outPoint); + READWRITE(nHeight); + } +}; + +struct nameOutPointType +{ + std::string name; + COutPoint outPoint; + + nameOutPointType() {} + + nameOutPointType(std::string name, COutPoint outPoint) + : name(name), outPoint(outPoint) {} + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(name); + READWRITE(outPoint); + } +}; + +class CClaimIndexElement +{ + public: + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(name); + READWRITE(claim); + } + + std::string name; + CClaimValue claim; +}; + +typedef std::pair claimQueueEntryType; + +typedef std::pair supportQueueEntryType; + +typedef std::map supportMapType; + +typedef std::vector queueNameRowType; +typedef std::map queueNameType; + +typedef std::vector insertUndoType; + +typedef std::vector expirationQueueRowType; +typedef std::map expirationQueueType; + +typedef std::vector claimQueueRowType; +typedef std::map claimQueueType; + +typedef std::vector supportQueueRowType; +typedef std::map supportQueueType; + +typedef std::map nodeCacheType; + +typedef std::map hashMapType; + +typedef std::set claimIndexClaimListType; +typedef std::vector claimIndexElementListType; + +struct claimsForNameType +{ + std::vector claims; + std::vector supports; + int nLastTakeoverHeight; + + claimsForNameType(std::vector claims, std::vector supports, int nLastTakeoverHeight) + : claims(claims), supports(supports), nLastTakeoverHeight(nLastTakeoverHeight) {} +}; + +class CClaimTrieCache; + +class CClaimTrie +{ +public: + CClaimTrie(bool fMemory = false, bool fWipe = false, int nProportionalDelayFactor = 32) + : db(GetDataDir() / "claimtrie", 100, fMemory, fWipe, false) + , nCurrentHeight(0), nExpirationTime(Params().GetConsensus().nOriginalClaimExpirationTime) + , nProportionalDelayFactor(nProportionalDelayFactor) + , root(uint256S("0000000000000000000000000000000000000000000000000000000000000001")) + {} + + uint256 getMerkleHash(); + + bool empty() const; + void clear(); + + bool checkConsistency() const; + + bool WriteToDisk(); + bool ReadFromDisk(bool check = false); + + std::vector flattenTrie() const; + bool getInfoForName(const std::string& name, CClaimValue& claim) const; + bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; + + claimsForNameType getClaimsForName(const std::string& name) const; + + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = nullptr) const; + CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = nullptr) const; + + bool queueEmpty() const; + bool supportEmpty() const; + bool supportQueueEmpty() const; + bool expirationQueueEmpty() const; + bool supportExpirationQueueEmpty() const; + + void setExpirationTime(int t); + + void addToClaimIndex(const std::string& name, const CClaimValue& claim); + void removeFromClaimIndex(const CClaimValue& claim); + + bool getClaimById(const uint160 claimId, std::string& name, CClaimValue& claim) const; + bool getQueueRow(int nHeight, claimQueueRowType& row) const; + bool getQueueNameRow(const std::string& name, queueNameRowType& row) const; + bool getExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; + bool getSupportNode(std::string name, supportMapEntryType& node) const; + bool getSupportQueueRow(int nHeight, supportQueueRowType& row) const; + bool getSupportQueueNameRow(const std::string& name, queueNameRowType& row) const; + bool getSupportExpirationQueueRow(int nHeight, expirationQueueRowType& row) const; + + + bool haveClaim(const std::string& name, const COutPoint& outPoint) const; + bool haveClaimInQueue(const std::string& name, const COutPoint& outPoint, + int& nValidAtHeight) const; + + bool haveSupport(const std::string& name, const COutPoint& outPoint) const; + bool haveSupportInQueue(const std::string& name, const COutPoint& outPoint, + int& nValidAtHeight) const; + + unsigned int getTotalNamesInTrie() const; + unsigned int getTotalClaimsInTrie() const; + CAmount getTotalValueOfClaimsInTrie(bool fControllingOnly) const; + + friend class CClaimTrieCache; + + CDBWrapper db; + int nCurrentHeight; + int nExpirationTime; + int nProportionalDelayFactor; +private: + void clear(CClaimTrieNode* current); + + const CClaimTrieNode* getNodeForName(const std::string& name) const; + + bool update(nodeCacheType& cache, hashMapType& hashes, + std::map& takeoverHeights, + const uint256& hashBlock, claimQueueType& queueCache, + queueNameType& queueNameCache, + expirationQueueType& expirationQueueCache, int nNewHeight, + supportMapType& supportCache, + supportQueueType& supportQueueCache, + queueNameType& supportQueueNameCache, + expirationQueueType& supportExpirationQueueCache); + bool updateName(const std::string& name, CClaimTrieNode* updatedNode); + bool updateHash(const std::string& name, uint256& hash); + bool updateTakeoverHeight(const std::string& name, int nTakeoverHeight); + bool recursiveNullify(CClaimTrieNode* node, std::string& name); + + bool recursiveCheckConsistency(const CClaimTrieNode* node) const; + + bool InsertFromDisk(const std::string& name, CClaimTrieNode* node); + + unsigned int getTotalNamesRecursive(const CClaimTrieNode* current) const; + unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const; + CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current, + bool fControllingOnly) const; + bool recursiveFlattenTrie(const std::string& name, + const CClaimTrieNode* current, + std::vector& nodes) const; + + void markNodeDirty(const std::string& name, CClaimTrieNode* node); + void updateQueueRow(int nHeight, claimQueueRowType& row); + void updateQueueNameRow(const std::string& name, + queueNameRowType& row); + void updateExpirationRow(int nHeight, expirationQueueRowType& row); + void updateSupportMap(const std::string& name, supportMapEntryType& node); + void updateSupportQueue(int nHeight, supportQueueRowType& row); + void updateSupportNameQueue(const std::string& name, + queueNameRowType& row); + void updateSupportExpirationQueue(int nHeight, expirationQueueRowType& row); + + void BatchWriteNode(CDBBatch& batch, const std::string& name, + const CClaimTrieNode* pNode) const; + void BatchEraseNode(CDBBatch& batch, const std::string& nome) const; + void BatchWriteClaimIndex(CDBBatch& batch) const; + void BatchWriteQueueRows(CDBBatch& batch); + void BatchWriteQueueNameRows(CDBBatch& batch); + void BatchWriteExpirationQueueRows(CDBBatch& batch); + void BatchWriteSupportNodes(CDBBatch& batch); + void BatchWriteSupportQueueRows(CDBBatch& batch); + void BatchWriteSupportQueueNameRows(CDBBatch& batch); + void BatchWriteSupportExpirationQueueRows(CDBBatch& batch); + template bool keyTypeEmpty(char key, K& dummy) const; + + CClaimTrieNode root; + uint256 hashBlock; + + claimQueueType dirtyQueueRows; + queueNameType dirtyQueueNameRows; + expirationQueueType dirtyExpirationQueueRows; + + supportQueueType dirtySupportQueueRows; + queueNameType dirtySupportQueueNameRows; + expirationQueueType dirtySupportExpirationQueueRows; + + nodeCacheType dirtyNodes; + supportMapType dirtySupportNodes; +}; + +class CClaimTrieProofNode +{ +public: + CClaimTrieProofNode() {}; + CClaimTrieProofNode(std::vector > children, + bool hasValue, uint256 valHash) + : children(children), hasValue(hasValue), valHash(valHash) + {}; + std::vector > children; + bool hasValue; + uint256 valHash; +}; + +class CClaimTrieProof +{ +public: + CClaimTrieProof() {}; + CClaimTrieProof(std::vector nodes, bool hasValue, COutPoint outPoint, int nHeightOfLastTakeover) : nodes(nodes), hasValue(hasValue), outPoint(outPoint), nHeightOfLastTakeover(nHeightOfLastTakeover) {} + std::vector nodes; + bool hasValue; + COutPoint outPoint; + int nHeightOfLastTakeover; +}; + +class CClaimTrieCache +{ +public: + CClaimTrieCache(CClaimTrie* base, bool fRequireTakeoverHeights = true) + : base(base), + fRequireTakeoverHeights(fRequireTakeoverHeights) + { + assert(base); + nCurrentHeight = base->nCurrentHeight; + } + + uint256 getMerkleHash() const; + + bool empty() const; + bool flush(); + bool dirty() const { return !dirtyHashes.empty(); } + + CClaimTrieNode* getRoot() const + { + const auto iter = cache.find(""); + return iter == cache.end() ? &(base->root) : iter->second; + } + + bool addClaim(const std::string& name, const COutPoint& outPoint, + uint160 claimId, CAmount nAmount, int nHeight) const; + bool undoAddClaim(const std::string& name, const COutPoint& outPoint) const; + bool spendClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight) const; + bool undoSpendClaim(const std::string& name, const COutPoint& outPoint, + uint160 claimId, CAmount nAmount, int nHeight, + int nValidAtHeight) const; + + bool addSupport(const std::string& name, const COutPoint& outPoint, + CAmount nAmount, uint160 supportedClaimId, + int nHeight) const; + bool undoAddSupport(const std::string& name, const COutPoint& outPoint, + int nHeight) const; + bool spendSupport(const std::string& name, const COutPoint& outPoint, + int nHeight, int& nValidAtHeight) const; + bool undoSpendSupport(const std::string& name, const COutPoint& outPoint, + uint160 supportedClaimId, CAmount nAmount, + int nHeight, int nValidAtHeight) const; + + uint256 getBestBlock(); + void setBestBlock(const uint256& hashBlock); + + bool incrementBlock(insertUndoType& insertUndo, + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo) const; + bool decrementBlock(insertUndoType& insertUndo, + claimQueueRowType& expireUndo, + insertUndoType& insertSupportUndo, + supportQueueRowType& expireSupportUndo, + std::vector >& takeoverHeightUndo) const; + + ~CClaimTrieCache() { clear(); } + + bool insertClaimIntoTrie(const std::string& name, CClaimValue claim, + bool fCheckTakeover = false) const; + bool removeClaimFromTrie(const std::string& name, const COutPoint& outPoint, + CClaimValue& claim, + bool fCheckTakeover = false) const; + + bool getProofForName(const std::string& name, CClaimTrieProof& proof) const; + bool getInfoForName(const std::string& name, CClaimValue& claim) const; + + bool finalizeDecrement() const; + + void removeAndAddSupportToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; + void removeAndAddToExpirationQueue(expirationQueueRowType &row, int height, bool increment) const; + + bool forkForExpirationChange(bool increment) const; + + std::vector flattenTrie() const; + + claimsForNameType getClaimsForName(const std::string& name) const; + + CAmount getEffectiveAmountForClaim(const std::string& name, const uint160& claimId, std::vector* supports = nullptr) const; + CAmount getEffectiveAmountForClaim(const claimsForNameType& claims, const uint160& claimId, std::vector* supports = nullptr) const; + +protected: + CClaimTrie* base; + + bool fRequireTakeoverHeights; + + mutable nodeCacheType cache; + mutable nodeCacheType block_originals; + mutable std::set dirtyHashes; + mutable hashMapType cacheHashes; + mutable claimQueueType claimQueueCache; + mutable queueNameType claimQueueNameCache; + mutable expirationQueueType expirationQueueCache; + mutable supportMapType supportCache; + mutable supportQueueType supportQueueCache; + mutable queueNameType supportQueueNameCache; + mutable expirationQueueType supportExpirationQueueCache; + mutable std::set namesToCheckForTakeover; + mutable std::map cacheTakeoverHeights; + mutable int nCurrentHeight; // Height of the block that is being worked on, which is + // one greater than the height of the chain's tip + mutable claimIndexElementListType claimsToAdd; + mutable claimIndexClaimListType claimsToDelete; + + uint256 hashBlock; + + uint256 computeHash() const; + + bool reorderTrieNode(const std::string& name, bool fCheckTakeover) const; + bool recursiveComputeMerkleHash(CClaimTrieNode* tnCurrent, + std::string sPos) const; + bool recursivePruneName(CClaimTrieNode* tnCurrent, unsigned int nPos, + std::string sName, + bool* pfNullified = NULL) const; + + bool clear() const; + + bool removeClaim(const std::string& name, const COutPoint& outPoint, int& nValidAtHeight, bool fCheckTakeover) const; + bool addClaimToQueues(const std::string& name, CClaimValue& claim) const; + bool removeClaimFromQueue(const std::string& name, const COutPoint& outPoint, + CClaimValue& claim) const; + void addToExpirationQueue(int nExpirationHeight, nameOutPointType& entry) const; + void removeFromExpirationQueue(const std::string& name, const COutPoint& outPoint, + int nHeight) const; + + claimQueueType::iterator getQueueCacheRow(int nHeight, + bool createIfNotExists) const; + queueNameType::iterator getQueueCacheNameRow(const std::string& name, + bool createIfNotExists) const; + expirationQueueType::iterator getExpirationQueueCacheRow(int nHeight, + bool createIfNotExists) const; + + bool removeSupport(const std::string& name, const COutPoint& outPoint, + int nHeight, int& nValidAtHeight, + bool fCheckTakeover) const; + bool removeSupportFromMap(const std::string& name, const COutPoint& outPoint, + CSupportValue& support, + bool fCheckTakeover) const; + + bool insertSupportIntoMap(const std::string& name, + CSupportValue support, + bool fCheckTakeover) const; + + supportQueueType::iterator getSupportQueueCacheRow(int nHeight, bool createIfNotExists) const; + queueNameType::iterator getSupportQueueCacheNameRow(const std::string& name, bool createIfNotExists) const; + expirationQueueType::iterator getSupportExpirationQueueCacheRow(int nHeight, bool createIfNotExists) const; + + bool addSupportToQueues(const std::string& name, CSupportValue& support) const; + bool removeSupportFromQueue(const std::string& name, const COutPoint& outPoint, + CSupportValue& support) const; + + void addSupportToExpirationQueue(int nExpirationHeight, + nameOutPointType& entry) const; + void removeSupportFromExpirationQueue(const std::string& name, + const COutPoint& outPoint, + int nHeight) const; + + bool getSupportsForName(const std::string& name, + supportMapEntryType& node) const; + + bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const; + + int getDelayForName(const std::string& name) const; + + uint256 getLeafHashForProof(const std::string& currentPosition, unsigned char nodeChar, + const CClaimTrieNode* currentNode) const; + + CClaimTrieNode* addNodeToCache(const std::string& position, CClaimTrieNode* original) const; + + bool getOriginalInfoForName(const std::string& name, CClaimValue& claim) const; + + int getNumBlocksOfContinuousOwnership(const std::string& name) const; + + void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector& nodes) const; + + const CClaimTrieNode* getNodeForName(const std::string& name) const; +}; + +#endif // BITCOIN_CLAIMTRIE_H diff --git a/src/coins.h b/src/coins.h index 41a422f48..79e85cdcb 100644 --- a/src/coins.h +++ b/src/coins.h @@ -39,8 +39,8 @@ public: uint32_t nHeight : 31; //! construct a Coin from a CTxOut and height/coinbase information. - Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {} - Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn),nHeight(nHeightIn) {} + Coin(CTxOut&& outIn, int nHeightIn, bool fCoinBaseIn) : out(std::move(outIn)), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {} + Coin(const CTxOut& outIn, int nHeightIn, bool fCoinBaseIn) : out(outIn), fCoinBase(fCoinBaseIn), nHeight(nHeightIn) {} void Clear() { out.SetNull(); diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 788fa4e55..5a4cd9365 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -10,9 +10,9 @@ #include /** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */ -static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000; +static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 8000000; /** The maximum allowed weight for a block, see BIP 141 (network rule) */ -static const unsigned int MAX_BLOCK_WEIGHT = 4000000; +static const unsigned int MAX_BLOCK_WEIGHT = 8000000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const int64_t MAX_BLOCK_SIGOPS_COST = 80000; /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ diff --git a/src/consensus/params.h b/src/consensus/params.h index 6c3a201f4..3cbfba033 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -48,7 +48,11 @@ struct BIP9Deployment { */ struct Params { uint256 hashGenesisBlock; - int nSubsidyHalvingInterval; + int nSubsidyLevelInterval; + /** Used to check majorities for block version upgrade */ + int nMajorityEnforceBlockUpgrade; + int nMajorityRejectBlockOutdated; + int nMajorityWindow; /* Block hash that is excepted from BIP16 enforcement */ uint256 BIP16Exception; /** Block height and hash at which BIP34 becomes active */ @@ -70,8 +74,17 @@ struct Params { uint256 powLimit; bool fPowAllowMinDifficultyBlocks; bool fPowNoRetargeting; + int nNormalizedNameForkHeight; int64_t nPowTargetSpacing; int64_t nPowTargetTimespan; + int64_t nOriginalClaimExpirationTime; + int64_t nExtendedClaimExpirationTime; + int64_t nExtendedClaimExpirationForkHeight; + int64_t GetExpirationTime(int64_t nHeight) const { + return nHeight < nExtendedClaimExpirationForkHeight ? + nOriginalClaimExpirationTime : + nExtendedClaimExpirationTime; + } int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } uint256 nMinimumChainWork; uint256 defaultAssumeValid; diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index be73d0a2f..d80da5d1b 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -9,6 +9,8 @@ #include