From 291b191bd70b2afc285b71187c2f7eb85197f9f0 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 28 Mar 2016 00:16:22 -0600 Subject: [PATCH 01/12] Add serialization for primitive boost::optional. --- src/serialize.h | 54 ++++++++++++++++++++++++++++++++++++ src/test/serialize_tests.cpp | 27 ++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/serialize.h b/src/serialize.h index 8db53ecfd..0644a852e 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -21,6 +21,7 @@ #include #include +#include class CScript; @@ -508,6 +509,13 @@ extern inline unsigned int GetSerializeSize(const CScript& v, int nType, int nVe template void Serialize(Stream& os, const CScript& v, int nType, int nVersion); template void Unserialize(Stream& is, CScript& v, int nType, int nVersion); +/** + * optional + */ +template unsigned int GetSerializeSize(const boost::optional &item, int nType, int nVersion); +template void Serialize(Stream& os, const boost::optional& item, int nType, int nVersion); +template void Unserialize(Stream& is, boost::optional& item, int nType, int nVersion); + /** * array */ @@ -707,6 +715,52 @@ void Unserialize(Stream& is, CScript& v, int nType, int nVersion) } + +/** + * optional + */ +template +unsigned int GetSerializeSize(const boost::optional &item, int nType, int nVersion) +{ + if (item) { + return 1 + GetSerializeSize(*item, nType, nVersion); + } else { + return 1; + } +} + +template +void Serialize(Stream& os, const boost::optional& item, int nType, int nVersion) +{ + // If the value is there, put 0x01 and then serialize the value. + // If it's not, put 0x00. + if (item) { + unsigned char discriminant = 0x01; + Serialize(os, discriminant, nType, nVersion); + Serialize(os, *item, nType, nVersion); + } else { + unsigned char discriminant = 0x00; + Serialize(os, discriminant, nType, nVersion); + } +} + +template +void Unserialize(Stream& is, boost::optional& item, int nType, int nVersion) +{ + unsigned char discriminant = 0x00; + Unserialize(is, discriminant, nType, nVersion); + + if (discriminant == 0x00) { + item = boost::none; + } else { + T object; + Unserialize(is, object, nType, nVersion); + item = object; + } +} + + + /** * array */ diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index 56c9db2fd..f7240e4e3 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -11,11 +11,38 @@ #include #include +#include using namespace std; + +template +void check_ser_rep(T thing, std::vector expected) +{ + CDataStream ss(SER_DISK, 0); + ss << thing; + + BOOST_CHECK(GetSerializeSize(thing, 0, 0) == ss.size()); + + std::vector serialized_representation(ss.begin(), ss.end()); + + BOOST_CHECK(serialized_representation == expected); + + T thing_deserialized; + ss >> thing_deserialized; + + BOOST_CHECK(thing_deserialized == thing); +} + BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup) +BOOST_AUTO_TEST_CASE(boost_optional) +{ + check_ser_rep>(0xff, {0x01, 0xff}); + check_ser_rep>(boost::none, {0x00}); + check_ser_rep>(std::string("Test"), {0x01, 0x04, 'T', 'e', 's', 't'}); +} + BOOST_AUTO_TEST_CASE(boost_arrays) { boost::array test_case = {string("zub"), string("baz")}; From e1ff849d8d5c6adb2d5fc78abed35eb10ac71adf Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 28 Mar 2016 02:40:21 -0600 Subject: [PATCH 02/12] New implementation of incremental merkle tree This is a new implementation of the incremental merkle tree used by our scheme to witness commitments to spendable value. It serves as a fixed-sized accumulator. This new construction has a much simpler API surface area, avoids memory safety issues, remains pruned at all times, avoids serialization edge cases, has more efficient insertion, and is abstract over the depth and hash function used at the type level. Further, it lays the groundwork for efficient "fast-forwarding" of witnesses into the tree as the treestate is updated. --- src/Makefile.am | 3 + src/Makefile.test.include | 9 +- src/coins.h | 3 +- src/serialize.h | 4 +- src/test/data/merkle_path.json | 122 ++++++++ src/test/data/merkle_roots.json | 18 ++ src/test/data/merkle_serialization.json | 18 ++ .../data/merkle_witness_serialization.json | 138 +++++++++ src/test/merkle_tests.cpp | 154 ++++++++++ src/test/serialize_tests.cpp | 9 + src/zcash/IncrementalMerkleTree.cpp | 287 ++++++++++++++++++ src/zcash/IncrementalMerkleTree.hpp | 129 ++++++++ 12 files changed, 889 insertions(+), 5 deletions(-) create mode 100644 src/test/data/merkle_path.json create mode 100644 src/test/data/merkle_roots.json create mode 100644 src/test/data/merkle_serialization.json create mode 100644 src/test/data/merkle_witness_serialization.json create mode 100644 src/test/merkle_tests.cpp create mode 100644 src/zcash/IncrementalMerkleTree.cpp create mode 100644 src/zcash/IncrementalMerkleTree.hpp diff --git a/src/Makefile.am b/src/Makefile.am index ea6aa3692..1db63746a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,9 @@ if BUILD_BITCOIN_UTILS bin_PROGRAMS += zcash-cli bitcoin-tx endif +# TODO: rename to libzcash LIBZEROCASH_H = \ + zcash/IncrementalMerkleTree.h \ zerocash/Address.h \ zerocash/CoinCommitment.h \ zerocash/Coin.h \ @@ -411,6 +413,7 @@ bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # zerocash protocol primitives # libzerocash_a_SOURCES = \ + zcash/IncrementalMerkleTree.cpp \ zerocash/Address.cpp \ zerocash/CoinCommitment.cpp \ zerocash/Coin.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 72d38e7c0..f6065de59 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -25,7 +25,11 @@ JSON_TEST_FILES = \ test/data/script_invalid.json \ test/data/tx_invalid.json \ test/data/tx_valid.json \ - test/data/sighash.json + test/data/sighash.json \ + test/data/merkle_roots.json \ + test/data/merkle_serialization.json \ + test/data/merkle_witness_serialization.json \ + test/data/merkle_path.json RAW_TEST_FILES = test/data/alertTests.raw @@ -78,7 +82,8 @@ BITCOIN_TESTS =\ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ - test/sha256compress_tests.cpp + test/sha256compress_tests.cpp \ + test/merkle_tests.cpp if ENABLE_WALLET BITCOIN_TESTS += \ diff --git a/src/coins.h b/src/coins.h index d128eb9b3..53f047177 100644 --- a/src/coins.h +++ b/src/coins.h @@ -17,8 +17,7 @@ #include #include #include "zerocash/IncrementalMerkleTree.h" - -static const unsigned int INCREMENTAL_MERKLE_TREE_DEPTH = 20; +#include "zcash/IncrementalMerkleTree.hpp" /** * Pruned version of CTransaction: only retains metadata and unspent transaction outputs diff --git a/src/serialize.h b/src/serialize.h index 0644a852e..aca3ed076 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -752,10 +752,12 @@ void Unserialize(Stream& is, boost::optional& item, int nType, int nVersion) if (discriminant == 0x00) { item = boost::none; - } else { + } else if (discriminant == 0x01) { T object; Unserialize(is, object, nType, nVersion); item = object; + } else { + throw std::ios_base::failure("non-canonical optional discriminant"); } } diff --git a/src/test/data/merkle_path.json b/src/test/data/merkle_path.json new file mode 100644 index 000000000..91957c438 --- /dev/null +++ b/src/test/data/merkle_path.json @@ -0,0 +1,122 @@ +[ + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000100010101010001010101000001010101000100010000000001000000000100000000010000000100010000010101010000000100000001010100000000010001000001000000000101000000010000010001000101010000000100010100000001010100000101010101000000010001000101010001000101010001010101010001010001010101000101010000010100010101010101000000000101010101010001010100000000010100010100010001010001000101000001000101000001010100000101010000010000010000010000010001010000010100010001000101000100010100000000010100000100000101010101000100010001010101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101000100010001000100010100000001010101010100000100010001010001010100010100010101010100000000010001010000000101000001000101000001010101000001010100000100010001010000010001010000000100010000010001000100000101010101010100000100010100000101000000010000010000010000010101010001000100000001000101010001000101010101010100010100010100010101010000010101010001000100000100000100010100000101010000000000000000000000000101000100010000010100010001000101010101000001000101010101000101000100000001000000010101000000000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101000101000000000101010101000000000000010000000100000101010001010001010000010001010101000101000100000100000101000001010000010000000000000000010101010101000001000001000000000101000101010001010000010000000001010101000000010100000000010101000001000101000000010001010001000100010101000001010000000000000100010101010101010000010101010001000001010101000000000001010000010001000100000101000100010001000001010000000000010000000001010000000100000000010100010101010101000000010000000101000001000101010100000101010100010100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101010000010101010000000101010101010100010000010001010000000001010001010100010101010100000100000100010101010101010100010100010101010001010100000101010000000000000100010100000100010101010001000101000101010001010001000101010000000100000000000000000001010100010001000100000001000101010001010001000100010101010001000101000100010001010001000000000001000101010001000100000101000000000101000000000100010001010001000100000100010100010000010000010101010100000001010100010001010000010000010000000000000101010000000101000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101000101000000010000000100000000010101010100000100000001000101010001010101010001000100010101000100000001000000000100010001010101010101000101010001010100010100010001000100010100000000000101010100000100010100000101000001000000000001000000010100010100000101010001000000010100010000000100010000010000000001000101010000010100000001000000010100000101000001000000000101000000010100010001000000010000010100010101000100000101010100010000000000010101010101010101010100010101000001000101010000000101010001000001000101010000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010001010101010001010000000001000001000000010101000101000001010001010001010101000000000101000001010001000101010000010001010000010101010101010100010101010101010000010001000000010001000000000100010100000101000101010001010101010101000000000100010100010100010100000001000100000101010100000101000001010101010000010001000000000100010001000001010001010001010001010001000001010101010100000000000000000000010000000001000100000100000101010100000001010101010100000100010100010100000001000101010001000100000001000001010001fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101000100000101010000000100000000010001010101000100010100000000000100010001010101000101010100010100000001010000010000000100000100000000000100000000010001010101000001010100000100000100010101010000000000000101010000010101010001010100000100000001000100000001010100000101010001000100010000010100000101010100010100000100000001000001010100010000000100010100000000010101010100000000010101010100010000000100000001000000010001000100000100000101000001000101000000010100010000010000010100010100000000000000000001010101000100fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100000001010101000100010101000101000100010001010101000001010101000101010000010100000001000001000100000001010100010001000001010001010000000001000100010000000000010001000000010001000000000000000000010000010001010100010001000001010100010100010000000100000001000100010100010000000000000100000000010100000001010101000000000100000100010101010101000001000000010000000101010001000000010100000001000101000001010001000000000101010000010000000001000101000000010100000100000001000001010000010001010101010001010001000001010100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000101000000000101000100000101010000010000000101010000010100010101010000000101010001010101000101000100000001010000000001010000010001010001000100010000010001000001010000010000010100010101000101010001010101000000010100010000000100000001000000010101000101010101000101000000000001000000000001010100010000010100000101010101000101000100010001000000000000000001000001010101010100000001000100000101000001010101010001010100000001000000010100000101000101010101000001000001000101010100010001010100010000010100010001010001000000fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000100010101010001010000010001000000010100000001010100000000010001000000000101010101000001000100010100010000010001010001010101010000010101000101010100010001000000010100000001010100010001000000000100000101010001000000000100010100000001010000010001000000000000010101000000010101010001000101010101010100010100000000010100010101000101000100010101000000010101000000010101000001000001000101010000000101010000000000000001010101010001010001010100010000000001010100000101000000000101010001010100000101000101010000010000000100fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000100000000000100010001000001010101000000000000000101010001010000000001000000010101010001010001010101010001010001000001000000010000010001000000010101000001000100010100010101010100000001000100000001010001010001000000000100010101000000000100000100010001010101010001000100000001010001010001000100010101010100010000010101010000010001010100000101010100010100000001010101010101000101000001010001000000000100000001010001010101000101000100000001010100010100010101000100010001010001010101010000000001000001000000010000000001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400000101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010400010101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000100", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401000101", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010000", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010001", + "04fd000100010001000100010001010000010000010100010100000100010101000101010000010000000001000100000001000101010001000001000101010000010001000001010100010100000000000001000101000101010100000001000101000101000000010101000000010000000100010001010000000100000000010001000100000000000100000000000001010000000001000100000101010000000000010100010100000001000000010101000100010101010001010100010001000001000000010100010101000101010000000101010000000101010101000000000100010101000001010001010100010001000001000100000001000000000101fd000101010001010100000000010100000101010100000100010001000001000000000101010001000000000101000000000001000100010001010001010000010101000101010000000001010001010000000000010001000101010001000100000101000000010101010000010000000000010101000100010001010100000101000101000100010001010101000000010001010000010001000100000101000100000101000000010101010101000101000000010101010101000101000100000101000101000100000000000001010100000001010101000001010101000101010000010001010100000000010000010000000001010100010001010001010000fd000101000000000101000100000100010001010000000001010100000101010100010001010000000101010101000101000000000000010001010101000001010100010101000100010001010001010001010001000101000101010101010001000001010000010100000101000000010100000101010000010000000101010001000101000001000000000000000000010101010000000000010100000000000100000101000101010101010000000101010101000001010101010001010000010100010000010101010101000000010101000101000000000101000000000000000000010100000000000100010100010001010100000001000001010101010001fd0001000100010001000101000101010000000001000100000100000101010100000000000001010001010100000101000001010000010001000101000100000100000001000001010000010000010000010101000001010001010001010000010000010101000001000000010000000000010100010001010100000001000001010100000100000100000100010101000001000101000101010101000001010000010101000001000000010101010001000001010101010001010100000101000100000000010001000000000001010100000101010101010000010000010100000000010000000001000101000000010000010001010000000001010100000001010401010100" +] \ No newline at end of file diff --git a/src/test/data/merkle_roots.json b/src/test/data/merkle_roots.json new file mode 100644 index 000000000..0ed3a89e7 --- /dev/null +++ b/src/test/data/merkle_roots.json @@ -0,0 +1,18 @@ +[ + "caea625775792fb7553c4e21915b1713ae18b9d03d8e04786014dac6fd83bcd7", + "e2ef3d63416cec2325a7468cbc1eefc91575105620c7b76312fc3ce04d70be67", + "32dd56bb1128fba775a0dbd12a15e12378ade73d67e04c57ee6336e5d2a78530", + "432f637c762e1fe0d17d81d1e4e99c929ddcc7472d13c250897c9b693bd8d360", + "cc73383f18247923e9472ac7aa97851a9740d731956683eec67c6dff00427b47", + "3197598c9f2345402ac4e5b80ff7eda14e22a7fb954270846ceebb403c7f5c94", + "2d97b4feb3a45b79206315da4cf625d3ee739794344f51186b39d9d1c20b9526", + "ac42a2e51c799ee492f2ec961780ce87964e7baecea47b8ee77519140c3dd364", + "cd1a6cdc8a1db28aedcbd96bfbdcfde5429db68e1d38c4cfb5d0c91bc195ee0e", + "d20bb06d178f8a514620c7aa549c8467912abdd97c5e892ef5715ad9ed116c7b", + "f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516847e", + "54c1402e1dfc649dd38d23230ff1cb786f49c85c00e92b378c7b5f3312c5c628", + "976d045f7f84687ff64b95f5a686d943b6f2f4f2e4159d552f12ed7c907b65c8", + "4480b49acaff4f737d156f7c8dcbbd035f0c4a8450d70eed3c76d30f69d71ece", + "a867397884b157b1db4dd03dc2fd6c40c4650e70b61441d4325e0b18d5280fb6", + "52c8456d3538eed3b73778c596c1993ac6d6c337ae5e338391ce6cae58296dec" +] \ No newline at end of file diff --git a/src/test/data/merkle_serialization.json b/src/test/data/merkle_serialization.json new file mode 100644 index 000000000..9bb8ffee5 --- /dev/null +++ b/src/test/data/merkle_serialization.json @@ -0,0 +1,18 @@ +[ + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443" +] \ No newline at end of file diff --git a/src/test/data/merkle_witness_serialization.json b/src/test/data/merkle_witness_serialization.json new file mode 100644 index 000000000..327d833e9 --- /dev/null +++ b/src/test/data/merkle_witness_serialization.json @@ -0,0 +1,138 @@ +[ + "0000000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300", + "0000000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300010155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30000", + "0000000555b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300000455b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300038695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d0355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e301018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d02dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3020001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d5564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30002018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c0255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e35564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e302018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944300", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430355b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030000015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443028695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27ddc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e303018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba944301dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430255b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e38695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3030001dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba9443018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d00", + "0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e30003018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d01dc33ca90e860ab6770d82ba98f20eae6d5e2ca9a63f63f69b40e3cf72e121d6c015564d9772145d2e53b02de2d8e22b10a820614e0d88ebdd48ddc71f0b9ba94430155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300" +] \ No newline at end of file diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp new file mode 100644 index 000000000..883cda13a --- /dev/null +++ b/src/test/merkle_tests.cpp @@ -0,0 +1,154 @@ +#include "test/test_bitcoin.h" + +#include "data/merkle_roots.json.h" +#include "data/merkle_serialization.json.h" +#include "data/merkle_witness_serialization.json.h" +#include "data/merkle_path.json.h" + +#include + +#include "utilstrencodings.h" +#include "version.h" + +#include +#include "json/json_spirit_reader_template.h" +#include "json/json_spirit_utils.h" +#include "json/json_spirit_writer_template.h" +using namespace json_spirit; +extern Array read_json(const std::string& jsondata); + +#include "zcash/IncrementalMerkleTree.hpp" + +//#define PRINT_JSON 1 + +using namespace std; + +template +void expect_test_vector(T& it, const U& expected) +{ + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss1 << expected; + + #ifdef PRINT_JSON + std::cout << "\t\"" ; + std::cout << HexStr(ss1.begin(), ss1.end()) << "\",\n"; + #else + std::string raw = (it++)->get_str(); + CDataStream ss2(ParseHex(raw), SER_NETWORK, PROTOCOL_VERSION); + + BOOST_CHECK(ss1.size() == ss2.size()); + BOOST_CHECK(memcmp(&*ss1.begin(), &*ss2.begin(), ss1.size()) == 0); + #endif +} + +BOOST_FIXTURE_TEST_SUITE(merkle_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(tree_test_vectors) +{ + Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); + Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); + Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); + Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); + + Array::iterator root_iterator = root_tests.begin(); + Array::iterator ser_iterator = ser_tests.begin(); + Array::iterator witness_ser_iterator = witness_ser_tests.begin(); + Array::iterator path_iterator = path_tests.begin(); + + uint256 test_commitment = uint256S("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + + ZCTestingIncrementalMerkleTree tree; + + // The root of the tree at this point is expected to be null. + BOOST_CHECK(tree.root().IsNull()); + + // We need to witness at every single point in the tree, so + // that the consistency of the tree and the merkle paths can + // be checked. + vector witnesses; + + for (size_t i = 0; i < 16; i++) { + // Witness here + witnesses.push_back(tree.witness()); + + // Now append a commitment to the tree + tree.append(test_commitment); + + // Check tree root consistency + expect_test_vector(root_iterator, tree.root()); + + // Check serialization of tree + expect_test_vector(ser_iterator, tree); + + bool first = true; // The first witness can never form a path + BOOST_FOREACH(ZCTestingIncrementalWitness& wit, witnesses) + { + // Append the same commitment to all the witnesses + wit.append(test_commitment); + + if (first) { + BOOST_CHECK_THROW(wit.path(), std::runtime_error); + } else { + auto path = wit.path(); + + expect_test_vector(path_iterator, path); + } + + // Check witness serialization + expect_test_vector(witness_ser_iterator, wit); + + BOOST_CHECK(wit.root() == tree.root()); + + first = false; + } + } + + // Tree should be full now + BOOST_CHECK_THROW(tree.append(uint256()), std::runtime_error); + + BOOST_FOREACH(ZCTestingIncrementalWitness& wit, witnesses) + { + BOOST_CHECK_THROW(wit.append(uint256()), std::runtime_error); + } +} + +BOOST_AUTO_TEST_CASE( deserializeInvalid ) { + ZCIncrementalMerkleTree newTree; + + for (size_t i = 0; i < 16; i++) { + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + } + + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << newTree; + + ZCTestingIncrementalMerkleTree newTreeSmall; + BOOST_CHECK_THROW(ss >> newTreeSmall, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE( testZeroElements ) { + for (int start = 0; start < 20; start++) { + ZCIncrementalMerkleTree newTree; + + BOOST_CHECK(newTree.root() == uint256()); + + for (int i = start; i > 0; i--) { + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + } + + uint256 oldroot = newTree.root(); + + // At this point, appending tons of null objects to the tree + // should preserve its root. + + for (int i = 0; i < 100; i++) { + newTree.append(uint256()); + } + + BOOST_CHECK(newTree.root() == oldroot); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp index f7240e4e3..d3e51c7d1 100644 --- a/src/test/serialize_tests.cpp +++ b/src/test/serialize_tests.cpp @@ -41,6 +41,15 @@ BOOST_AUTO_TEST_CASE(boost_optional) check_ser_rep>(0xff, {0x01, 0xff}); check_ser_rep>(boost::none, {0x00}); check_ser_rep>(std::string("Test"), {0x01, 0x04, 'T', 'e', 's', 't'}); + + { + // Ensure that canonical optional discriminant is used + CDataStream ss(SER_DISK, 0); + ss.write("\x02\x04Test", 6); + boost::optional into; + + BOOST_CHECK_THROW(ss >> into, std::ios_base::failure); + } } BOOST_AUTO_TEST_CASE(boost_arrays) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp new file mode 100644 index 000000000..e2543cbe5 --- /dev/null +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -0,0 +1,287 @@ +#include + +#include + +#include "zcash/IncrementalMerkleTree.hpp" +#include "crypto/sha256.h" +#include "zerocash/utils/util.h" // TODO: remove these utilities + +namespace libzcash { + +SHA256Compress SHA256Compress::combine(const SHA256Compress& a, const SHA256Compress& b) +{ + // This is a performance optimization. + if (a.IsNull() && b.IsNull()) { + return a; + } + + SHA256Compress res = SHA256Compress(); + + CSHA256 hasher; + hasher.Write(a.begin(), 32); + hasher.Write(b.begin(), 32); + hasher.FinalizeNoPadding(res.begin()); + + return res; +} + + +template +class PathFiller { +private: + std::deque queue; +public: + PathFiller() : queue() { } + PathFiller(std::deque queue) : queue(queue) { } + + Hash next() { + if (queue.size() > 0) { + Hash h = queue.front(); + queue.pop_front(); + + return h; + } else { + return Hash(); + } + } +}; + +template +void IncrementalMerkleTree::wfcheck() const { + if (parents.size() >= Depth) { + throw std::ios_base::failure("tree has too many parents"); + } +} + +template +void IncrementalMerkleTree::append(Hash obj) { + if (is_complete(Depth)) { + throw std::runtime_error("tree is full"); + } + + if (!left) { + // Set the left leaf + left = obj; + } else if (!right) { + // Set the right leaf + right = obj; + } else { + // Combine the leaves and propagate it up the tree + boost::optional combined = Hash::combine(*left, *right); + + // Set the left leaf to the object and make the right object none + left = obj; + right = boost::none; + + // Propagate up the tree as much as needed + BOOST_FOREACH(boost::optional& parent, parents) { + if (parent) { + combined = Hash::combine(*parent, *combined); + parent = boost::none; + } else { + parent = *combined; + combined = boost::none; + break; + } + } + + if (combined) { + // Create a new parent + parents.push_back(combined); + } + } +} + +// This is for allowing the witness to determine if a subtree has filled +// to a particular depth, or for append() to ensure we're not appending +// to a full tree. +template +bool IncrementalMerkleTree::is_complete(size_t depth) const { + if (!left || !right) { + return false; + } + + if (parents.size() != (depth - 1)) { + return false; + } + + BOOST_FOREACH(const boost::optional& parent, parents) { + if (!parent) { + return false; + } + } + + return true; +} + +// This finds the next "depth" of an unfilled subtree, given that we've filled +// `skip` uncles/subtrees. +template +size_t IncrementalMerkleTree::next_depth(size_t skip) const { + if (!left) { + if (skip) { + skip--; + } else { + return 0; + } + } + + if (!right) { + if (skip) { + skip--; + } else { + return 0; + } + } + + size_t d = 1; + + BOOST_FOREACH(const boost::optional& parent, parents) { + if (!parent) { + if (skip) { + skip--; + } else { + return d; + } + } + + d++; + } + + return d + skip; +} + +// This calculates the root of the tree. +template +Hash IncrementalMerkleTree::root(size_t depth, + std::deque filler_hashes) const { + PathFiller filler(filler_hashes); + + Hash combine_left = left ? *left : filler.next(); + Hash combine_right = right ? *right : filler.next(); + + Hash root = Hash::combine(combine_left, combine_right); + + size_t d = 1; + + BOOST_FOREACH(const boost::optional& parent, parents) { + if (parent) { + root = Hash::combine(*parent, root); + } else { + root = Hash::combine(root, filler.next()); + } + + d++; + } + + // We may not have parents for ancestor trees, so we fill + // the rest in here. + while (d < depth) { + root = Hash::combine(root, filler.next()); + d++; + } + + return root; +} + +// This constructs an authentication path into the tree in the format that the circuit +// wants. The caller provides `filler_hashes` to fill in the uncle subtrees. +template +MerklePath IncrementalMerkleTree::path(std::deque filler_hashes) const { + if (!left) { + throw std::runtime_error("can't create an authentication path for the beginning of the tree"); + } + + PathFiller filler(filler_hashes); + + std::vector path; + std::vector index; + + if (right) { + index.push_back(true); + path.push_back(*left); + } else { + index.push_back(false); + path.push_back(filler.next()); + } + + size_t d = 1; + + BOOST_FOREACH(const boost::optional& parent, parents) { + if (parent) { + index.push_back(true); + path.push_back(*parent); + } else { + index.push_back(false); + path.push_back(filler.next()); + } + + d++; + } + + while (d < Depth) { + index.push_back(false); + path.push_back(filler.next()); + d++; + } + + std::vector> merkle_path; + BOOST_FOREACH(Hash b, path) + { + std::vector hashv(b.begin(), b.end()); + std::vector tmp_b; + + libzerocash::convertBytesVectorToVector(hashv, tmp_b); + + merkle_path.push_back(tmp_b); + } + + std::reverse(merkle_path.begin(), merkle_path.end()); + std::reverse(index.begin(), index.end()); + + return MerklePath(merkle_path, index); +} + +template +std::deque IncrementalWitness::uncle_train() const { + std::deque uncles(filled.begin(), filled.end()); + + if (cursor) { + uncles.push_back(cursor->root(cursor_depth)); + } + + return uncles; +} + +template +void IncrementalWitness::append(Hash obj) { + if (cursor) { + cursor->append(obj); + + if (cursor->is_complete(cursor_depth)) { + filled.push_back(cursor->root(cursor_depth)); + cursor = boost::none; + } + } else { + cursor_depth = tree.next_depth(filled.size()); + + if (cursor_depth >= Depth) { + throw std::runtime_error("tree is full"); + } + + if (cursor_depth == 0) { + filled.push_back(obj); + } else { + cursor = IncrementalMerkleTree(); + cursor->append(obj); + } + } +} + +template class IncrementalMerkleTree; +template class IncrementalMerkleTree; + +template class IncrementalWitness; +template class IncrementalWitness; + +} // end namespace `libzcash` diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp new file mode 100644 index 000000000..28cb81ea8 --- /dev/null +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -0,0 +1,129 @@ +#ifndef ZCINCREMENTALMERKLETREE_H_ +#define ZCINCREMENTALMERKLETREE_H_ + +#include +#include +#include + +#include "uint256.h" +#include "serialize.h" + +static const unsigned int INCREMENTAL_MERKLE_TREE_DEPTH = 20; +static const unsigned int INCREMENTAL_MERKLE_TREE_DEPTH_TESTING = 4; + +namespace libzcash { + +class MerklePath { +public: + std::vector> authentication_path; + std::vector index; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(authentication_path); + READWRITE(index); + } + + MerklePath(std::vector> authentication_path, std::vector index) + : authentication_path(authentication_path), index(index) { } +}; + +template +class IncrementalWitness; + +template +class IncrementalMerkleTree { + +friend class IncrementalWitness; + +public: + BOOST_STATIC_ASSERT(Depth >= 1); + + IncrementalMerkleTree() { } + + void append(Hash obj); + Hash root() const { + return root(Depth, std::deque()); + } + + IncrementalWitness witness() const { + return IncrementalWitness(*this); + } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(left); + READWRITE(right); + READWRITE(parents); + + wfcheck(); + } + +private: + boost::optional left; + boost::optional right; + std::vector> parents; + MerklePath path(std::deque filler_hashes = std::deque()) const; + Hash root(size_t depth, std::deque filler_hashes = std::deque()) const; + bool is_complete(size_t depth = Depth) const; + size_t next_depth(size_t skip) const; + void wfcheck() const; +}; + +template +class IncrementalWitness { +friend class IncrementalMerkleTree; + +public: + MerklePath path() const { + return tree.path(uncle_train()); + } + + Hash root() const { + return tree.root(Depth, uncle_train()); + } + + void append(Hash obj); + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(tree); + READWRITE(filled); + READWRITE(cursor); + + cursor_depth = tree.next_depth(filled.size()); + } + +private: + IncrementalMerkleTree tree; + std::vector filled; + boost::optional> cursor; + size_t cursor_depth; + std::deque uncle_train() const; + IncrementalWitness(IncrementalMerkleTree tree) : tree(tree) {} +}; + +class SHA256Compress : public uint256 { +public: + SHA256Compress() : uint256() {} + SHA256Compress(uint256 contents) : uint256(contents) { } + + static SHA256Compress combine(const SHA256Compress& a, const SHA256Compress& b); +}; + +} // end namespace `libzcash` + +typedef libzcash::IncrementalMerkleTree ZCIncrementalMerkleTree; +typedef libzcash::IncrementalMerkleTree ZCTestingIncrementalMerkleTree; + +typedef libzcash::IncrementalWitness ZCIncrementalWitness; +typedef libzcash::IncrementalWitness ZCTestingIncrementalWitness; + +#endif /* ZCINCREMENTALMERKLETREE_H_ */ + From 434f3284465daffaad124ac17b16798a3f152062 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 2 Apr 2016 23:31:26 -0600 Subject: [PATCH 03/12] Integrate new incremental merkle tree implementation into consensus. --- src/coins.cpp | 22 ++++---- src/coins.h | 12 ++-- src/main.cpp | 15 +---- src/test/coins_tests.cpp | 117 ++++++++++----------------------------- src/txdb.cpp | 22 +++----- src/txdb.h | 2 +- src/txmempool.cpp | 2 +- src/wallet/wallet.cpp | 2 +- src/zcbenchmarks.cpp | 2 + 9 files changed, 60 insertions(+), 136 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 7ccfc28d1..d177b8eef 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -40,7 +40,7 @@ bool CCoins::Spend(uint32_t nPos) Cleanup(); return true; } -bool CCoinsView::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return false; } +bool CCoinsView::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; } bool CCoinsView::GetSerial(const uint256 &serial) const { return false; } bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } @@ -56,7 +56,7 @@ bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; } CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } -bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); } +bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); } bool CCoinsViewBacked::GetSerial(const uint256 &serial) const { return base->GetSerial(serial); } bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } @@ -102,11 +102,11 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const } -bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { +bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { CAnchorsMap::const_iterator it = cacheAnchors.find(rt); if (it != cacheAnchors.end()) { if (it->second.entered) { - tree.setTo(it->second.tree); + tree = it->second.tree; return true; } else { return false; @@ -119,7 +119,7 @@ bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMer CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(rt, CAnchorsCacheEntry())).first; ret->second.entered = true; - ret->second.tree.setTo(tree); + ret->second.tree = tree; return true; } @@ -140,10 +140,8 @@ bool CCoinsViewCache::GetSerial(const uint256 &serial) const { return tmp; } -void CCoinsViewCache::PushAnchor(const libzerocash::IncrementalMerkleTree &tree) { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - uint256 newrt(newrt_v); +void CCoinsViewCache::PushAnchor(const ZCIncrementalMerkleTree &tree) { + uint256 newrt = tree.root(); auto currentRoot = GetBestAnchor(); @@ -156,7 +154,7 @@ void CCoinsViewCache::PushAnchor(const libzerocash::IncrementalMerkleTree &tree) CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(newrt, CAnchorsCacheEntry())).first; ret->second.entered = true; - ret->second.tree.setTo(tree); + ret->second.tree = tree; ret->second.flags = CAnchorsCacheEntry::DIRTY; hashAnchor = newrt; @@ -302,7 +300,7 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, CAnchorsCacheEntry& entry = cacheAnchors[child_it->first]; entry.entered = true; - entry.tree.setTo(child_it->second.tree); + entry.tree = child_it->second.tree; entry.flags = CAnchorsCacheEntry::DIRTY; // TODO: cache usage @@ -399,7 +397,7 @@ bool CCoinsViewCache::HavePourRequirements(const CTransaction& tx) const } } - libzerocash::IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; if (!GetAnchorAt(pour.anchor, tree)) { // If we do not have the anchor for the pour, // it is invalid. diff --git a/src/coins.h b/src/coins.h index 53f047177..4e547d525 100644 --- a/src/coins.h +++ b/src/coins.h @@ -300,14 +300,14 @@ struct CCoinsCacheEntry struct CAnchorsCacheEntry { bool entered; // This will be false if the anchor is removed from the cache - libzerocash::IncrementalMerkleTree tree; // The tree itself + ZCIncrementalMerkleTree tree; // The tree itself unsigned char flags; enum Flags { DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view. }; - CAnchorsCacheEntry() : entered(false), flags(0), tree(INCREMENTAL_MERKLE_TREE_DEPTH) {} + CAnchorsCacheEntry() : entered(false), flags(0) {} }; struct CSerialsCacheEntry @@ -345,7 +345,7 @@ class CCoinsView { public: //! Retrieve the tree at a particular anchored root in the chain - virtual bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const; + virtual bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; //! Determine whether a serial is spent or not virtual bool GetSerial(const uint256 &serial) const; @@ -387,7 +387,7 @@ protected: public: CCoinsViewBacked(CCoinsView *viewIn); - bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const; + bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetSerial(const uint256 &serial) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; @@ -451,7 +451,7 @@ public: ~CCoinsViewCache(); // Standard CCoinsView methods - bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const; + bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetSerial(const uint256 &serial) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; @@ -467,7 +467,7 @@ public: // Adds the tree to mapAnchors and sets the current commitment // root to this root. - void PushAnchor(const libzerocash::IncrementalMerkleTree &tree); + void PushAnchor(const ZCIncrementalMerkleTree &tree); // Removes the current commitment root from mapAnchors and sets // the new current root. diff --git a/src/main.cpp b/src/main.cpp index fe0969281..4860513b9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2013,7 +2013,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Construct the incremental merkle tree at the current // block position, auto old_tree_root = view.GetBestAnchor(); - libzerocash::IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; // This should never fail: we should always be able to get the root // that is on the tip of our chain assert(view.GetAnchorAt(old_tree_root, tree)); @@ -2021,11 +2021,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { // Consistency check: the root of the tree we're given should // match what we asked for. - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - uint256 anchor_received = uint256(newrt_v); - - assert(anchor_received == old_tree_root); + assert(tree.root() == old_tree_root); } for (unsigned int i = 0; i < block.vtx.size(); i++) @@ -2078,11 +2074,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments) { // Insert the bucket commitments into our temporary tree. - std::vector index; - std::vector commitment_value(bucket_commitment.begin(), bucket_commitment.end()); - std::vector commitment_bv(ZC_CM_SIZE * 8); - libzerocash::convertBytesVectorToVector(commitment_value, commitment_bv); - tree.insertElement(commitment_bv, index); + tree.append(bucket_commitment); } } @@ -2090,7 +2082,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } - tree.prune(); // prune it, so we don't cache intermediate states we don't need view.PushAnchor(tree); blockundo.old_tree_root = old_tree_root; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index d03863cc1..a599843f0 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -11,7 +11,7 @@ #include #include -#include "zerocash/IncrementalMerkleTree.h" +#include "zcash/IncrementalMerkleTree.hpp" namespace { @@ -20,22 +20,22 @@ class CCoinsViewTest : public CCoinsView uint256 hashBestBlock_; uint256 hashBestAnchor_; std::map map_; - std::map mapAnchors_; + std::map mapAnchors_; std::map mapSerials_; public: - bool GetAnchorAt(const uint256& rt, libzerocash::IncrementalMerkleTree &tree) const { + bool GetAnchorAt(const uint256& rt, ZCIncrementalMerkleTree &tree) const { if (rt.IsNull()) { - IncrementalMerkleTree new_tree(INCREMENTAL_MERKLE_TREE_DEPTH); - tree.setTo(new_tree); + ZCIncrementalMerkleTree new_tree; + tree = new_tree; return true; } - std::map::const_iterator it = mapAnchors_.find(rt); + std::map::const_iterator it = mapAnchors_.find(rt); if (it == mapAnchors_.end()) { return false; } else { - tree.setTo(it->second); + tree = it->second; return true; } } @@ -93,10 +93,10 @@ public: } for (CAnchorsMap::iterator it = mapAnchors.begin(); it != mapAnchors.end(); ) { if (it->second.entered) { - std::map::iterator ret = - mapAnchors_.insert(std::make_pair(it->first, IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH))).first; + std::map::iterator ret = + mapAnchors_.insert(std::make_pair(it->first, ZCIncrementalMerkleTree())).first; - ret->second.setTo(it->second.tree); + ret->second = it->second.tree; } else { mapAnchors_.erase(it->first); } @@ -164,16 +164,12 @@ BOOST_AUTO_TEST_CASE(serials_test) BOOST_CHECK(!cache3.GetSerial(myserial)); } -void appendRandomCommitment(IncrementalMerkleTree &tree) +void appendRandomCommitment(ZCIncrementalMerkleTree &tree) { Address addr = Address::CreateNewRandomAddress(); Coin coin(addr.getPublicAddress(), 100); - std::vector commitment(ZC_CM_SIZE * 8); - convertBytesVectorToVector(coin.getCoinCommitment().getCommitmentValue(), commitment); - - std::vector index; - tree.insertElement(commitment, index); + tree.append(uint256(coin.getCoinCommitment().getCommitmentValue())); } BOOST_AUTO_TEST_CASE(anchors_flush_test) @@ -182,15 +178,11 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test) uint256 newrt; { CCoinsViewCacheTest cache(&base); - IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree)); appendRandomCommitment(tree); - { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - newrt = uint256(newrt_v); - } + newrt = tree.root(); cache.PushAnchor(tree); cache.Flush(); @@ -198,18 +190,13 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test) { CCoinsViewCacheTest cache(&base); - IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree)); // Get the cached entry. BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree)); - uint256 check_rt; - { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - check_rt = uint256(newrt_v); - } + uint256 check_rt = tree.root(); BOOST_CHECK(check_rt == newrt); } @@ -226,7 +213,7 @@ BOOST_AUTO_TEST_CASE(anchors_test) BOOST_CHECK(cache.GetBestAnchor() == uint256()); { - IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree)); appendRandomCommitment(tree); @@ -236,96 +223,50 @@ BOOST_AUTO_TEST_CASE(anchors_test) appendRandomCommitment(tree); appendRandomCommitment(tree); appendRandomCommitment(tree); - tree.prune(); - IncrementalMerkleTree save_tree_for_later(INCREMENTAL_MERKLE_TREE_DEPTH); - save_tree_for_later.setTo(tree); + ZCIncrementalMerkleTree save_tree_for_later; + save_tree_for_later = tree; - uint256 newrt; + uint256 newrt = tree.root(); uint256 newrt2; - { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - - newrt = uint256(newrt_v); - } cache.PushAnchor(tree); BOOST_CHECK(cache.GetBestAnchor() == newrt); { - IncrementalMerkleTree confirm_same(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree confirm_same; BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), confirm_same)); - uint256 confirm_rt; - { - std::vector newrt_v(32); - confirm_same.getRootValue(newrt_v); - - confirm_rt = uint256(newrt_v); - } - - BOOST_CHECK(confirm_rt == newrt); + BOOST_CHECK(confirm_same.root() == newrt); } appendRandomCommitment(tree); appendRandomCommitment(tree); - tree.prune(); - { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - - newrt2 = uint256(newrt_v); - } + newrt2 = tree.root(); cache.PushAnchor(tree); BOOST_CHECK(cache.GetBestAnchor() == newrt2); - IncrementalMerkleTree test_tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree test_tree; BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), test_tree)); - { - std::vector a(32); - std::vector b(32); - tree.getRootValue(a); - test_tree.getRootValue(b); - - BOOST_CHECK(a == b); - } + BOOST_CHECK(tree.root() == test_tree.root()); { - std::vector a(32); - std::vector b(32); - IncrementalMerkleTree test_tree2(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree test_tree2; cache.GetAnchorAt(newrt, test_tree2); - uint256 recovered_rt; - { - std::vector newrt_v(32); - test_tree2.getRootValue(newrt_v); - - recovered_rt = uint256(newrt_v); - } - - BOOST_CHECK(recovered_rt == newrt); + BOOST_CHECK(test_tree2.root() == newrt); } { cache.PopAnchor(newrt); - IncrementalMerkleTree obtain_tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree obtain_tree; assert(!cache.GetAnchorAt(newrt2, obtain_tree)); // should have been popped off assert(cache.GetAnchorAt(newrt, obtain_tree)); - uint256 recovered_rt; - { - std::vector newrt_v(32); - obtain_tree.getRootValue(newrt_v); - - recovered_rt = uint256(newrt_v); - } - - assert(recovered_rt == newrt); + assert(obtain_tree.root() == newrt); } } } diff --git a/src/txdb.cpp b/src/txdb.cpp index ca335fb78..5ad5eb1f1 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -33,13 +33,13 @@ static const char DB_LAST_BLOCK = 'l'; void static BatchWriteAnchor(CLevelDBBatch &batch, const uint256 &croot, - const libzerocash::IncrementalMerkleTree &tree, + const ZCIncrementalMerkleTree &tree, const bool &entered) { if (!entered) batch.Erase(make_pair(DB_ANCHOR, croot)); else { - batch.Write(make_pair(DB_ANCHOR, croot), tree.serialize()); + batch.Write(make_pair(DB_ANCHOR, croot), tree); } } @@ -69,24 +69,16 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(Get } -bool CCoinsViewDB::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { +bool CCoinsViewDB::GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { if (rt.IsNull()) { - IncrementalMerkleTree new_tree(INCREMENTAL_MERKLE_TREE_DEPTH); - tree.setTo(new_tree); + ZCIncrementalMerkleTree new_tree; + tree = new_tree; return true; } - std::vector tree_serialized; + bool read = db.Read(make_pair(DB_ANCHOR, rt), tree); - bool read = db.Read(make_pair(DB_ANCHOR, rt), tree_serialized); - - if (!read) return read; - - auto tree_deserialized = IncrementalMerkleTreeCompact::deserialize(tree_serialized); - - tree.fromCompactRepresentation(tree_deserialized); - - return true; + return read; } bool CCoinsViewDB::GetSerial(const uint256 &serial) const { diff --git a/src/txdb.h b/src/txdb.h index bd401b801..0e20b0d9b 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -36,7 +36,7 @@ protected: public: CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); - bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const; + bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const; bool GetSerial(const uint256 &serial) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index d9e410a79..0a202229a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -320,7 +320,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const } // TODO: chained pours - libzerocash::IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; assert(pcoins->GetAnchorAt(pour.anchor, tree)); } if (fDependsWait) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f8b550c08..7c48c025b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1096,7 +1096,7 @@ bool CWallet::WitnessBucketCommitment(uint256 &commitment, // Consistency check: we should be able to find the current tree // in our CCoins view. - libzerocash::IncrementalMerkleTree dummy_tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree dummy_tree; assert(pcoinsTip->GetAnchorAt(current_anchor, dummy_tree)); pindex = chainActive.Next(pindex); diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 6a6bf6ae2..8fc04217b 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -1,3 +1,5 @@ +#include "zerocash/IncrementalMerkleTree.h" + #include #include #include "zerocash/ZerocashParams.h" From 482aefbd0da3bbc8cc0e5a0a26751b3c9e22d7f6 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 3 Apr 2016 15:39:08 -0600 Subject: [PATCH 04/12] Test old tree along with new tree as much as possible. --- src/test/merkle_tests.cpp | 201 +++++++++++++++++++++++++--- src/zcash/IncrementalMerkleTree.hpp | 2 + 2 files changed, 185 insertions(+), 18 deletions(-) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 883cda13a..cfdd9d1b2 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -18,6 +18,7 @@ using namespace json_spirit; extern Array read_json(const std::string& jsondata); #include "zcash/IncrementalMerkleTree.hpp" +#include "zerocash/IncrementalMerkleTree.h" //#define PRINT_JSON 1 @@ -41,15 +42,109 @@ void expect_test_vector(T& it, const U& expected) #endif } -BOOST_FIXTURE_TEST_SUITE(merkle_tests, BasicTestingSetup) +/* +This is a wrapper around the old incremental merkle tree which +attempts to mimic the new API as much as possible so that its +behavior can be compared with the test vectors we use. +*/ +class OldIncrementalMerkleTree { +private: + libzerocash::IncrementalMerkleTree* tree; + boost::optional> index; + bool witnessed; -BOOST_AUTO_TEST_CASE(tree_test_vectors) -{ - Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); - Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); - Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); - Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); +public: + OldIncrementalMerkleTree() : index(boost::none), witnessed(false) { + this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + } + ~OldIncrementalMerkleTree() + { + delete tree; + } + + OldIncrementalMerkleTree (const OldIncrementalMerkleTree& other) : index(boost::none), witnessed(false) + { + this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + this->tree->setTo(*other.tree); + index = other.index; + witnessed = other.witnessed; + } + + OldIncrementalMerkleTree& operator= (const OldIncrementalMerkleTree& other) + { + OldIncrementalMerkleTree tmp(other); // re-use copy-constructor + *this = std::move(tmp); // re-use move-assignment + return *this; + } + + OldIncrementalMerkleTree& operator= (OldIncrementalMerkleTree&& other) + { + tree->setTo(*other.tree); + index = other.index; + witnessed = other.witnessed; + return *this; + } + + libzcash::MerklePath path() { + assert(witnessed); + + if (!index) { + throw std::runtime_error("can't create an authentication path for the beginning of the tree"); + } + + merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + tree->getWitness(*index, path); + + libzcash::MerklePath ret; + ret.authentication_path = path; + ret.index = *index; + + return ret; + } + + uint256 root() { + std::vector newrt_v(32); + tree->getRootValue(newrt_v); + return uint256(newrt_v); + } + + void append(uint256 obj) { + std::vector new_index; + std::vector obj_bv(obj.begin(), obj.end()); + + std::vector commitment_bv(256); + libzerocash::convertBytesVectorToVector(obj_bv, commitment_bv); + + tree->insertElement(commitment_bv, new_index); + + if (!witnessed) { + index = new_index; + } + } + + OldIncrementalMerkleTree witness() { + OldIncrementalMerkleTree ret; + ret.tree->setTo(*tree); + ret.index = index; + ret.witnessed = true; + + return ret; + } +}; + +template +void expect_ser_test_vector(B& b, const C& c, const A& tree) { + expect_test_vector(b, c); +} + +template +void expect_ser_test_vector(B& b, const C& c, const OldIncrementalMerkleTree& tree) { + // Don't perform serialization tests on the old tree. +} + +template +void test_tree(Array root_tests, Array ser_tests, Array witness_ser_tests, Array path_tests) { Array::iterator root_iterator = root_tests.begin(); Array::iterator ser_iterator = ser_tests.begin(); Array::iterator witness_ser_iterator = witness_ser_tests.begin(); @@ -57,7 +152,7 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) uint256 test_commitment = uint256S("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - ZCTestingIncrementalMerkleTree tree; + Tree tree; // The root of the tree at this point is expected to be null. BOOST_CHECK(tree.root().IsNull()); @@ -65,7 +160,7 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) // We need to witness at every single point in the tree, so // that the consistency of the tree and the merkle paths can // be checked. - vector witnesses; + vector witnesses; for (size_t i = 0; i < 16; i++) { // Witness here @@ -78,10 +173,10 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) expect_test_vector(root_iterator, tree.root()); // Check serialization of tree - expect_test_vector(ser_iterator, tree); + expect_ser_test_vector(ser_iterator, tree, tree); bool first = true; // The first witness can never form a path - BOOST_FOREACH(ZCTestingIncrementalWitness& wit, witnesses) + BOOST_FOREACH(Witness& wit, witnesses) { // Append the same commitment to all the witnesses wit.append(test_commitment); @@ -91,11 +186,65 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) } else { auto path = wit.path(); - expect_test_vector(path_iterator, path); + // The old tree has some serious bugs which make it + // fail some of these test vectors. + // + // The new tree is strictly more correct in its + // behavior, as we demonstrate by constructing and + // evaluating the tree over a dummy circuit. + if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { + expect_test_vector(path_iterator, path); + + typedef Fr FieldT; + + protoboard pb; + pb_variable_array positions; + digest_variable commitment(pb, 256, "commitment"); + digest_variable root(pb, 256, "root"); + positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos"); + merkle_authentication_path_variable> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth"); + merkle_tree_check_read_gadget> auth( + pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path" + ); + commitment.generate_r1cs_constraints(); + root.generate_r1cs_constraints(); + authvars.generate_r1cs_constraints(); + auth.generate_r1cs_constraints(); + + std::vector commitment_bv; + { + std::vector commitment_v(test_commitment.begin(), test_commitment.end()); + convertBytesVectorToVector(commitment_v, commitment_bv); + } + + size_t path_index = libzerocash::convertVectorToInt(path.index); + + commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv)); + positions.fill_with_bits_of_ulong(pb, path_index); + + authvars.generate_r1cs_witness(path_index, path.authentication_path); + auth.generate_r1cs_witness(); + + std::vector root_bv; + { + uint256 witroot = wit.root(); + std::vector root_v(witroot.begin(), witroot.end()); + convertBytesVectorToVector(root_v, root_bv); + } + + root.bits.fill_with_bits(pb, bit_vector(root_bv)); + + BOOST_CHECK(pb.is_satisfied()); + + root_bv[0] = !root_bv[0]; + root.bits.fill_with_bits(pb, bit_vector(root_bv)); + + BOOST_CHECK(!pb.is_satisfied()); + } } // Check witness serialization - expect_test_vector(witness_ser_iterator, wit); + expect_ser_test_vector(witness_ser_iterator, wit, tree); BOOST_CHECK(wit.root() == tree.root()); @@ -103,15 +252,31 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) } } - // Tree should be full now - BOOST_CHECK_THROW(tree.append(uint256()), std::runtime_error); + // The old tree would silently ignore appending when it was full. + if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { + // Tree should be full now + BOOST_CHECK_THROW(tree.append(uint256()), std::runtime_error); - BOOST_FOREACH(ZCTestingIncrementalWitness& wit, witnesses) - { - BOOST_CHECK_THROW(wit.append(uint256()), std::runtime_error); + BOOST_FOREACH(Witness& wit, witnesses) + { + BOOST_CHECK_THROW(wit.append(uint256()), std::runtime_error); + } } } +BOOST_FIXTURE_TEST_SUITE(merkle_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(tree_test_vectors) +{ + Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); + Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); + Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); + Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); + + test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); + test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); +} + BOOST_AUTO_TEST_CASE( deserializeInvalid ) { ZCIncrementalMerkleTree newTree; diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp index 28cb81ea8..f170ffffa 100644 --- a/src/zcash/IncrementalMerkleTree.hpp +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -26,6 +26,8 @@ public: READWRITE(index); } + MerklePath() { } + MerklePath(std::vector> authentication_path, std::vector index) : authentication_path(authentication_path), index(index) { } }; From 1760b3cd88b970f1b68362afec774d3d52f03905 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 3 Apr 2016 16:05:08 -0600 Subject: [PATCH 05/12] Deprecate the old tree and remove old tree tests from the test suite. --- qa/zcash/full-test-suite.sh | 1 - src/Makefile.zcash.include | 10 +- src/coins.h | 1 - src/test/transaction_tests.cpp | 30 ++--- src/txdb.h | 2 - src/wallet/rpcwallet.cpp | 12 +- src/wallet/wallet.cpp | 45 +++---- src/wallet/wallet.h | 2 +- src/zerocash/PourInput.cpp | 24 ++-- src/zerocash/PourInput.h | 5 +- src/zerocash/tests/merkleTest.cpp | 199 ---------------------------- src/zerocash/tests/zerocashTest.cpp | 77 ++++++----- 12 files changed, 85 insertions(+), 323 deletions(-) delete mode 100644 src/zerocash/tests/merkleTest.cpp diff --git a/qa/zcash/full-test-suite.sh b/qa/zcash/full-test-suite.sh index 9c809d7fb..85387ff07 100755 --- a/qa/zcash/full-test-suite.sh +++ b/qa/zcash/full-test-suite.sh @@ -27,7 +27,6 @@ cd "${REPOROOT}" # Test phases: run_test_phase "${REPOROOT}/qa/zcash/ensure-no-dot-so-in-depends.py" -run_test_phase "${REPOROOT}/src/zerocash/tests/merkleTest" run_test_phase "${REPOROOT}/src/zerocash/tests/utilTest" # If make check fails, show test-suite.log as part of our run_test_phase diff --git a/src/Makefile.zcash.include b/src/Makefile.zcash.include index 68b0c69aa..7455ffff1 100644 --- a/src/Makefile.zcash.include +++ b/src/Makefile.zcash.include @@ -1,6 +1,5 @@ bin_PROGRAMS += \ zerocash/GenerateParamsForFiles \ - zerocash/tests/merkleTest \ zerocash/tests/utilTest \ zerocash/tests/zerocashTest \ zerocash/tests/test_zerocash_pour_ppzksnark @@ -13,14 +12,6 @@ zerocash_GenerateParamsForFiles_LDADD = \ $(LIBBITCOIN_CRYPTO) \ $(LIBZEROCASH_LIBS) -# tests for our incremental merkle tree -zerocash_tests_merkleTest_SOURCES = zerocash/tests/merkleTest.cpp -zerocash_tests_merkleTest_LDADD = \ - $(BOOST_LIBS) \ - $(LIBZEROCASH) \ - $(LIBBITCOIN_CRYPTO) \ - $(LIBZEROCASH_LIBS) - # tests for utilities that come with zerocash zerocash_tests_utilTest_SOURCES = zerocash/tests/utilTest.cpp zerocash_tests_utilTest_LDADD = \ @@ -38,6 +29,7 @@ zerocash_tests_zerocashTest_SOURCES = \ zerocash_tests_zerocashTest_LDADD = \ $(BOOST_LIBS) \ $(LIBZEROCASH) \ + $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZEROCASH_LIBS) diff --git a/src/coins.h b/src/coins.h index 4e547d525..2dffc3177 100644 --- a/src/coins.h +++ b/src/coins.h @@ -16,7 +16,6 @@ #include #include -#include "zerocash/IncrementalMerkleTree.h" #include "zcash/IncrementalMerkleTree.hpp" /** diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index c869e37ff..6192a2652 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -26,7 +26,6 @@ #include "json/json_spirit_writer_template.h" #include "zerocash/ZerocashParams.h" -#include "zerocash/IncrementalMerkleTree.h" #include "zerocash/PourInput.h" #include "zerocash/PourOutput.h" #include "zerocash/Address.h" @@ -311,44 +310,35 @@ BOOST_AUTO_TEST_CASE(test_basic_pour_verification) // Also, it's generally libzerocash's job to ensure // the integrity of the scheme through its own tests. - static const unsigned int TEST_TREE_DEPTH = 3; - // construct the r1cs keypair - auto keypair = ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH); + auto keypair = ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); ZerocashParams p( - TEST_TREE_DEPTH, + INCREMENTAL_MERKLE_TREE_DEPTH, &keypair ); // construct a merkle tree - IncrementalMerkleTree merkleTree(TEST_TREE_DEPTH); + ZCIncrementalMerkleTree merkleTree; Address addr = Address::CreateNewRandomAddress(); Coin coin(addr.getPublicAddress(), 100); // commitment from coin - std::vector commitment(ZC_CM_SIZE * 8); - convertBytesVectorToVector(coin.getCoinCommitment().getCommitmentValue(), commitment); + uint256 commitment(coin.getCoinCommitment().getCommitmentValue()); // insert commitment into the merkle tree - std::vector index; - merkleTree.insertElement(commitment, index); + merkleTree.append(commitment); // compute the merkle root we will be working with - vector rt(ZC_ROOT_SIZE); - { - vector root_bv(ZC_ROOT_SIZE * 8); - merkleTree.getRootValue(root_bv); - convertVectorToBytesVector(root_bv, rt); - } + uint256 rt = merkleTree.root(); - merkle_authentication_path path(TEST_TREE_DEPTH); - merkleTree.getWitness(index, path); + auto witness = merkleTree.witness(); + auto path = witness.path(); // create CPourTx CScript scriptPubKey; boost::array inputs = { - PourInput(coin, addr, convertVectorToInt(index), path), - PourInput(TEST_TREE_DEPTH) // dummy input of zero value + PourInput(coin, addr, path), + PourInput(INCREMENTAL_MERKLE_TREE_DEPTH) // dummy input of zero value }; boost::array outputs = { PourOutput(50), diff --git a/src/txdb.h b/src/txdb.h index 0e20b0d9b..8e6782141 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -14,8 +14,6 @@ #include #include -#include "zerocash/IncrementalMerkleTree.h" - class CBlockFileInfo; class CBlockIndex; struct CDiskTxPos; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bc82ffc79..8d2aea04f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2480,10 +2480,9 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp) uint256 commitment = uint256(commitment_v); assert(pwalletMain != NULL); - libsnark::merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH); // We don't care during receive... yet! :) - size_t path_index = 0; + libzcash::MerklePath path; uint256 anchor; - auto found_in_chain = pwalletMain->WitnessBucketCommitment(commitment, path, path_index, anchor); + auto found_in_chain = pwalletMain->WitnessBucketCommitment(commitment, path, anchor); CAmount value_of_bucket = decrypted_bucket.getValue(); @@ -2587,14 +2586,13 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp) std::vector commitment_v = input_coin.getCoinCommitment().getCommitmentValue(); uint256 commitment = uint256(commitment_v); - libsnark::merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH); - size_t path_index = 0; + libzcash::MerklePath path; assert(pwalletMain != NULL); - if (!pwalletMain->WitnessBucketCommitment(commitment, path, path_index, anchor)) { + if (!pwalletMain->WitnessBucketCommitment(commitment, path, anchor)) { throw std::runtime_error("Couldn't find bucket in the blockchain"); } - vpourin.push_back(PourInput(input_coin, zcaddress, path_index, path)); + vpourin.push_back(PourInput(input_coin, zcaddress, path)); } while (vpourin.size() < NUM_POUR_INPUTS) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7c48c025b..fbdbb25a8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1052,15 +1052,12 @@ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb) } bool CWallet::WitnessBucketCommitment(uint256 &commitment, - libsnark::merkle_authentication_path& path, - size_t &path_index, + libzcash::MerklePath &path, uint256 &final_anchor) { - bool res = false; - std::vector commitment_index; - CBlockIndex* pindex = chainActive.Genesis(); - libzerocash::IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH); + ZCIncrementalMerkleTree tree; + boost::optional witness = boost::none; uint256 current_anchor; while (pindex) { @@ -1073,25 +1070,23 @@ bool CWallet::WitnessBucketCommitment(uint256 &commitment, { BOOST_FOREACH(const uint256 &bucket_commitment, pour.commitments) { - std::vector commitment_bv(ZC_CM_SIZE * 8); - std::vector index; - std::vector commitment_value(bucket_commitment.begin(), bucket_commitment.end()); - libzerocash::convertBytesVectorToVector(commitment_value, commitment_bv); - assert(tree.insertElement(commitment_bv, index)); + if (witness) { + witness->append(bucket_commitment); + } else { + tree.append(bucket_commitment); - if (bucket_commitment == commitment) { - // We've found it! Now, we construct a witness. - res = true; - commitment_index = index; + if (bucket_commitment == commitment) { + witness = tree.witness(); + } } } } } - { - std::vector newrt_v(32); - tree.getRootValue(newrt_v); - current_anchor = uint256(newrt_v); + if (witness) { + current_anchor = witness->root(); + } else { + current_anchor = tree.root(); } // Consistency check: we should be able to find the current tree @@ -1102,14 +1097,14 @@ bool CWallet::WitnessBucketCommitment(uint256 &commitment, pindex = chainActive.Next(pindex); } - if (res) { - assert(tree.getWitness(commitment_index, path)); + if (witness) { + path = witness->path(); + final_anchor = current_anchor; + + return true; } - path_index = libzerocash::convertVectorToInt(commitment_index); - final_anchor = current_anchor; - - return res; + return false; } /** diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c5385c785..3d908ea25 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -616,7 +616,7 @@ public: void SyncTransaction(const CTransaction& tx, const CBlock* pblock); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); void EraseFromWallet(const uint256 &hash); - bool WitnessBucketCommitment(uint256 &commitment, libsnark::merkle_authentication_path& path, size_t &path_index, uint256 &final_anchor); + bool WitnessBucketCommitment(uint256 &commitment, libzcash::MerklePath& path, uint256 &final_anchor); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime); diff --git a/src/zerocash/PourInput.cpp b/src/zerocash/PourInput.cpp index 7601001d0..eeb087f0d 100644 --- a/src/zerocash/PourInput.cpp +++ b/src/zerocash/PourInput.cpp @@ -11,7 +11,6 @@ * @copyright MIT license (see LICENSE file) *****************************************************************************/ -#include "IncrementalMerkleTree.h" #include "PourInput.h" namespace libzerocash { @@ -21,27 +20,20 @@ PourInput::PourInput(int tree_depth): old_coin(), merkle_index(), path() { this->old_coin = Coin(this->old_address.getPublicAddress(), 0); - // dummy merkle tree - IncrementalMerkleTree merkleTree(tree_depth); + ZCIncrementalMerkleTree merkleTree; + merkleTree.append(uint256(this->old_coin.getCoinCommitment().getCommitmentValue())); - // commitment from coin - std::vector commitment(ZC_CM_SIZE * 8); - convertBytesVectorToVector(this->old_coin.getCoinCommitment().getCommitmentValue(), commitment); + auto witness = merkleTree.witness(); + auto merkle_path = witness.path(); - // insert commitment into the merkle tree - std::vector index; - merkleTree.insertElement(commitment, index); - - merkleTree.getWitness(index, this->path); - - this->merkle_index = 1; + this->path = merkle_path.authentication_path; + this->merkle_index = convertVectorToInt(merkle_path.index); } PourInput::PourInput(Coin old_coin, Address old_address, - size_t merkle_index, - merkle_authentication_path path) : old_coin(old_coin), merkle_index(merkle_index), path(path) { - this->old_address = old_address; + const libzcash::MerklePath &path) : old_address(old_address), old_coin(old_coin), path(path.authentication_path) { + this->merkle_index = convertVectorToInt(path.index); }; } /* namespace libzerocash */ \ No newline at end of file diff --git a/src/zerocash/PourInput.h b/src/zerocash/PourInput.h index 2bb924c79..6da31e9d3 100644 --- a/src/zerocash/PourInput.h +++ b/src/zerocash/PourInput.h @@ -15,6 +15,8 @@ #include "Coin.h" #include "ZerocashParams.h" +#include "zcash/IncrementalMerkleTree.hpp" + namespace libzerocash { class PourInput { @@ -23,8 +25,7 @@ public: PourInput(Coin old_coin, Address old_address, - size_t merkle_index, - merkle_authentication_path path); + const libzcash::MerklePath& path); Coin old_coin; Address old_address; diff --git a/src/zerocash/tests/merkleTest.cpp b/src/zerocash/tests/merkleTest.cpp deleted file mode 100644 index 9be66cc9f..000000000 --- a/src/zerocash/tests/merkleTest.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/** @file - ***************************************************************************** - - Test for Merkle tree. - - ***************************************************************************** - * @author This file is part of libzerocash, developed by the Zerocash - * project and contributors (see AUTHORS). - * @copyright MIT license (see LICENSE file) - *****************************************************************************/ - -#include "zerocash/IncrementalMerkleTree.h" - -#include -#include - -#define BOOST_TEST_MODULE merkleTest -#include - -using namespace libzerocash; -using namespace std; - -void constructNonzeroTestVector(std::vector< std::vector > &values, uint32_t size) -{ - values.resize(0); - std::vector dummy; - dummy.resize(256); - dummy[0] = true; - - for (uint32_t i = 0; i < size; i++) - { - values.push_back(dummy); - } -} - -void constructZeroTestVector(std::vector< std::vector > &values, uint32_t size) -{ - values.resize(0); - std::vector dummy; - dummy.resize(256); - - for (uint32_t i = 0; i < size; i++) - { - values.push_back(dummy); - } -} - -BOOST_AUTO_TEST_CASE( testRootOfTreeOfZerosIsZero ) { - IncrementalMerkleTree incTree; - std::vector< std::vector > values; - std::vector actual_root; - - constructZeroTestVector(values, 2); - - // Create an IncrementalMerkleTree over the values. - if (incTree.insertVector(values) == false) { - BOOST_ERROR("Could not insert into the tree."); - } - incTree.prune(); - incTree.getRootValue(actual_root); - - std::vector expected_root(32*8, 0); - BOOST_CHECK( expected_root == actual_root ); -} - -void add_values_to_reference(IncrementalMerkleTree &tree, std::vector< std::vector > &values) { - IncrementalMerkleTree newtree(20); - - if (newtree.insertVector(values) == false) { - BOOST_ERROR("Could not insert into the tree."); - } - - tree.setTo(newtree); -} - -BOOST_AUTO_TEST_CASE( test_add_values_to_reference ) { - IncrementalMerkleTree incTree(20); - IncrementalMerkleTree incTree2(20); - - std::vector< std::vector > values; - constructNonzeroTestVector(values, 2); - - if (incTree.insertVector(values) == false) { - BOOST_ERROR("Could not insert into the tree."); - } - - add_values_to_reference(incTree2, values); - - { - std::vector root1, root2; - incTree.getRootValue(root1); - incTree2.getRootValue(root2); - - BOOST_CHECK(root1 == root2); - } -} - -BOOST_AUTO_TEST_CASE( testRootOfTreeOfNonZeroIsNonZero ) { - IncrementalMerkleTree incTree; - std::vector< std::vector > values; - std::vector actual_root; - - constructNonzeroTestVector(values, 2); - - // Create an IncrementalMerkleTree over the values. - if (incTree.insertVector(values) == false) { - BOOST_ERROR("Could not insert into the tree."); - } - incTree.prune(); - incTree.getRootValue(actual_root); - - std::vector expected_root(32*8, 0); - BOOST_CHECK( expected_root != actual_root ); -} - -BOOST_AUTO_TEST_CASE( testSerializationEdgeCase ) { - -} - -BOOST_AUTO_TEST_CASE( testCompactRepresentation ) { - for (uint32_t num_entries = 0; num_entries < 100; num_entries++) { - size_t test_depth = 64; - - if (num_entries == 2) { - // This is a particular failure I'm testing with weird - // padding caused by this depth. - test_depth = 20; - } - - std::vector< std::vector > values; - std::vector root1, root2; - IncrementalMerkleTree incTree(test_depth); - - constructNonzeroTestVector(values, num_entries); - - BOOST_REQUIRE( incTree.insertVector(values) ); - BOOST_REQUIRE( incTree.prune() ); - - IncrementalMerkleTreeCompact compact = incTree.getCompactRepresentation(); - - BOOST_REQUIRE( compact.getTreeHeight() == test_depth ); - - // Calculate what the path to the next-added element should be. - std::vector path_bytes(8); - std::vector path_bits; - libzerocash::convertIntToBytesVector(num_entries, path_bytes); - libzerocash::convertBytesVectorToVector(path_bytes, path_bits); - - if (test_depth == 64) { - // Make sure the paths match. - BOOST_REQUIRE( compact.getHashList() == path_bits ); - } - - // Make sure there's a hash for every '1' bit down the path. - BOOST_REQUIRE( compact.getHashVec().size() == libzerocash::countOnes(path_bits) ); - - /* Test serializing and deserializing. */ - std::vector serializedCompact = compact.serialize(); - IncrementalMerkleTreeCompact deserializedCompact = IncrementalMerkleTreeCompact::deserialize(serializedCompact); - BOOST_REQUIRE(compact.getTreeHeight() == deserializedCompact.getTreeHeight()); - BOOST_REQUIRE(compact.getHashList() == deserializedCompact.getHashList()); - BOOST_REQUIRE(compact.getHashVec() == deserializedCompact.getHashVec()); - - // Make sure 'restoring' the tree results in the same root. - IncrementalMerkleTree newTree(compact); - incTree.getRootValue(root1); - incTree.getRootValue(root2); - BOOST_REQUIRE( root1 == root2 ); - } -} - -BOOST_AUTO_TEST_CASE( testCompactDeserializationFailures ) { - IncrementalMerkleTree incTree(64); - std::vector< std::vector > values; - constructNonzeroTestVector(values, 5); - BOOST_REQUIRE( incTree.insertVector(values) ); - BOOST_REQUIRE( incTree.prune() ); - IncrementalMerkleTreeCompact compact = incTree.getCompactRepresentation(); - - /* Base the following tests off of this valid serialization. */ - std::vector serialized = compact.serialize(); - - /* Should fail if we truncate any number of bytes off the end. */ - for (size_t trunc_len = 0; trunc_len < serialized.size(); trunc_len++) { - std::vector truncated(serialized.begin(), serialized.begin() + trunc_len); - BOOST_CHECK_THROW( - IncrementalMerkleTreeCompact::deserialize(truncated), - std::out_of_range - ); - } - - /* Should fail if we append any number of extra bytes on the end. */ - std::vector extra_byte = serialized; - extra_byte.push_back(0x00); - BOOST_CHECK_THROW( - IncrementalMerkleTreeCompact::deserialize(extra_byte), - std::runtime_error - ); -} diff --git a/src/zerocash/tests/zerocashTest.cpp b/src/zerocash/tests/zerocashTest.cpp index 912759eaa..6770ccb63 100644 --- a/src/zerocash/tests/zerocashTest.cpp +++ b/src/zerocash/tests/zerocashTest.cpp @@ -29,20 +29,20 @@ #include "zerocash/PourOutput.h" #include "zerocash/utils/util.h" +#include "uint256.h" + using namespace std; using namespace libsnark; -#define TEST_TREE_DEPTH 4 - BOOST_AUTO_TEST_CASE( SaveAndLoadKeysFromFiles ) { cout << "\nSaveAndLoadKeysFromFiles TEST\n" << endl; cout << "Creating Params...\n" << endl; libzerocash::timer_start("Param Generation"); - auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH); + auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::ZerocashParams p( - TEST_TREE_DEPTH, + INCREMENTAL_MERKLE_TREE_DEPTH, &keypair ); libzerocash::timer_stop("Param Generation"); @@ -72,11 +72,11 @@ BOOST_AUTO_TEST_CASE( SaveAndLoadKeysFromFiles ) { libzerocash::timer_stop("Saving Verification Key"); libzerocash::timer_start("Loading Proving Key"); - auto pk_loaded = libzerocash::ZerocashParams::LoadProvingKeyFromFile(pk_path, TEST_TREE_DEPTH); + auto pk_loaded = libzerocash::ZerocashParams::LoadProvingKeyFromFile(pk_path, INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::timer_stop("Loading Proving Key"); libzerocash::timer_start("Loading Verification Key"); - auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(vk_path, TEST_TREE_DEPTH); + auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(vk_path, INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::timer_stop("Loading Verification Key"); cout << "Comparing Proving and Verification key.\n" << endl; @@ -107,19 +107,19 @@ BOOST_AUTO_TEST_CASE( SaveAndLoadKeysFromFiles ) { } cout << "Creating Merkle Tree...\n" << endl; - libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH); + libzerocash::IncrementalMerkleTree merkleTree(coinValues, INCREMENTAL_MERKLE_TREE_DEPTH); cout << "Successfully created Merkle Tree.\n" << endl; std::vector index; cout << "Creating Witness 1...\n" << endl; - merkle_authentication_path witness_1(TEST_TREE_DEPTH); + merkle_authentication_path witness_1(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::convertIntToVector(1, index); merkleTree.getWitness(index, witness_1); cout << "Successfully created Witness 1.\n" << endl; cout << "Creating Witness 2...\n" << endl; - merkle_authentication_path witness_2(TEST_TREE_DEPTH); + merkle_authentication_path witness_2(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::convertIntToVector(3, index); merkleTree.getWitness(index, witness_2); cout << "Successfully created Witness 2.\n" << endl; @@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE( SaveAndLoadKeysFromFiles ) { BOOST_AUTO_TEST_CASE( PourInputOutputTest ) { // dummy input { - libzerocash::PourInput input(TEST_TREE_DEPTH); + libzerocash::PourInput input(INCREMENTAL_MERKLE_TREE_DEPTH); BOOST_CHECK(input.old_coin.getValue() == 0); BOOST_CHECK(input.old_address.getPublicAddress() == input.old_coin.getPublicAddress()); @@ -192,10 +192,10 @@ void test_pour(libzerocash::ZerocashParams& p, std::vector inputs, // values of the inputs (max 2) std::vector outputs) // values of the outputs (max 2) { - using pour_input_state = std::tuple>; + using pour_input_state = std::tuple; // Construct incremental merkle tree - libzerocash::IncrementalMerkleTree merkleTree(TEST_TREE_DEPTH); + ZCIncrementalMerkleTree merkleTree; // Dummy sig_pk vector as(ZC_SIG_PK_SIZE, 'a'); @@ -210,33 +210,30 @@ void test_pour(libzerocash::ZerocashParams& p, libzerocash::Coin coin(addr.getPublicAddress(), *it); // commitment from coin - std::vector commitment(ZC_CM_SIZE * 8); - libzerocash::convertBytesVectorToVector(coin.getCoinCommitment().getCommitmentValue(), commitment); + uint256 commitment(coin.getCoinCommitment().getCommitmentValue()); // insert commitment into the merkle tree - std::vector index; - merkleTree.insertElement(commitment, index); + merkleTree.append(commitment); + + // and append to any witnesses + for(vector::iterator wit = input_state.begin(); wit != input_state.end(); ++wit) { + std::get<2>(*wit).append(commitment); + } // store the state temporarily - input_state.push_back(std::make_tuple(addr, coin, index)); + input_state.push_back(std::make_tuple(addr, coin, merkleTree.witness())); } // compute the merkle root we will be working with - vector rt(ZC_ROOT_SIZE); - { - vector root_bv(ZC_ROOT_SIZE * 8); - merkleTree.getRootValue(root_bv); - libzerocash::convertVectorToBytesVector(root_bv, rt); - } + auto rt_u = merkleTree.root(); + std::vector rt(rt_u.begin(), rt_u.end()); // get witnesses for all the input coins and construct the pours for(vector::iterator it = input_state.begin(); it != input_state.end(); ++it) { - merkle_authentication_path path(TEST_TREE_DEPTH); + auto witness = std::get<2>(*it); + auto path = witness.path(); - auto index = std::get<2>(*it); - merkleTree.getWitness(index, path); - - pour_inputs.push_back(libzerocash::PourInput(std::get<1>(*it), std::get<0>(*it), libzerocash::convertVectorToInt(index), path)); + pour_inputs.push_back(libzerocash::PourInput(std::get<1>(*it), std::get<0>(*it), path)); } // construct dummy outputs with the given values @@ -250,9 +247,9 @@ void test_pour(libzerocash::ZerocashParams& p, } BOOST_AUTO_TEST_CASE( PourVpubInTest ) { - auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH); + auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::ZerocashParams p( - TEST_TREE_DEPTH, + INCREMENTAL_MERKLE_TREE_DEPTH, &keypair ); @@ -331,9 +328,9 @@ BOOST_AUTO_TEST_CASE( PourTxTest ) { cout << "Creating Params...\n" << endl; libzerocash::timer_start("Param Generation"); - auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH); + auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::ZerocashParams p( - TEST_TREE_DEPTH, + INCREMENTAL_MERKLE_TREE_DEPTH, &keypair ); libzerocash::timer_stop("Param Generation"); @@ -363,12 +360,12 @@ BOOST_AUTO_TEST_CASE( PourTxTest ) { cout << "Creating Merkle Tree...\n" << endl; libzerocash::timer_start("Merkle Tree"); - libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH); + libzerocash::IncrementalMerkleTree merkleTree(coinValues, INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::timer_stop("Merkle Tree"); cout << "Successfully created Merkle Tree.\n" << endl; - merkle_authentication_path witness_1(TEST_TREE_DEPTH); + merkle_authentication_path witness_1(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::timer_start("Witness"); std::vector index; @@ -384,7 +381,7 @@ BOOST_AUTO_TEST_CASE( PourTxTest ) { } cout << "\n" << endl; - merkle_authentication_path witness_2(TEST_TREE_DEPTH); + merkle_authentication_path witness_2(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::convertIntToVector(3, index); if (merkleTree.getWitness(index, witness_2) == false) { cout << "Could not get witness" << endl; @@ -539,9 +536,9 @@ BOOST_AUTO_TEST_CASE( SimpleTxTest ) { cout << "\nSIMPLE TRANSACTION TEST\n" << endl; libzerocash::timer_start("Param Generation"); - auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(TEST_TREE_DEPTH); + auto keypair = libzerocash::ZerocashParams::GenerateNewKeyPair(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::ZerocashParams p( - TEST_TREE_DEPTH, + INCREMENTAL_MERKLE_TREE_DEPTH, &keypair ); libzerocash::timer_stop("Param Generation"); @@ -571,13 +568,13 @@ BOOST_AUTO_TEST_CASE( SimpleTxTest ) { } cout << "Creating Merkle Tree...\n" << endl; - libzerocash::IncrementalMerkleTree merkleTree(coinValues, TEST_TREE_DEPTH); + libzerocash::IncrementalMerkleTree merkleTree(coinValues, INCREMENTAL_MERKLE_TREE_DEPTH); cout << "Successfully created Merkle Tree.\n" << endl; std::vector index; cout << "Creating Witness 1...\n" << endl; - merkle_authentication_path witness_1(TEST_TREE_DEPTH); + merkle_authentication_path witness_1(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::convertIntToVector(1, index); if (merkleTree.getWitness(index, witness_1) == false) { BOOST_ERROR("Could not get witness"); @@ -585,7 +582,7 @@ BOOST_AUTO_TEST_CASE( SimpleTxTest ) { cout << "Successfully created Witness 1.\n" << endl; cout << "Creating Witness 2...\n" << endl; - merkle_authentication_path witness_2(TEST_TREE_DEPTH); + merkle_authentication_path witness_2(INCREMENTAL_MERKLE_TREE_DEPTH); libzerocash::convertIntToVector(3, index); if (merkleTree.getWitness(index, witness_2) == false) { cout << "Could not get witness" << endl; From 6d71658673be34e559b8bf895651a597627a7737 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 12 Apr 2016 14:21:00 -0600 Subject: [PATCH 06/12] Initialize curve/field parameters in case another test hasn't done so. --- src/test/merkle_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index cfdd9d1b2..8010df798 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -268,6 +268,8 @@ BOOST_FIXTURE_TEST_SUITE(merkle_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(tree_test_vectors) { + libsnark::default_r1cs_ppzksnark_pp::init_public_params(); + Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); From 01e4ff0f74e2d9cad03bf8dbd811323262257c69 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 12 Apr 2016 14:58:54 -0600 Subject: [PATCH 07/12] Improve well-formedness checks and add additional serialization/deserialization tests. --- src/test/merkle_tests.cpp | 41 ++++++++++++++++++++++++++++- src/zcash/IncrementalMerkleTree.cpp | 10 +++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 8010df798..c98e6d703 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -24,9 +24,48 @@ extern Array read_json(const std::string& jsondata); using namespace std; +template +void expect_deser_same(const T& expected) +{ + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss1 << expected; + + auto serialized_size = ss1.size(); + + T object; + ss1 >> object; + + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << object; + + BOOST_CHECK(serialized_size == ss2.size()); + BOOST_CHECK(memcmp(&*ss1.begin(), &*ss2.begin(), serialized_size) == 0); +} + +template<> +void expect_deser_same(const ZCTestingIncrementalWitness& expected) +{ + // Cannot check this; IncrementalWitness cannot be + // deserialized because it can only be constructed by + // IncrementalMerkleTree, and it does not yet have a + // canonical serialized representation. +} + +template<> +void expect_deser_same(const libzcash::MerklePath& expected) +{ + // This deserialization check is pointless for MerklePath, + // since we only serialize it to check it against test + // vectors. See `expect_test_vector` for that. Also, + // it doesn't seem that vector can be properly + // deserialized by Bitcoin's serialization code. +} + template void expect_test_vector(T& it, const U& expected) { + expect_deser_same(expected); + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); ss1 << expected; @@ -292,7 +331,7 @@ BOOST_AUTO_TEST_CASE( deserializeInvalid ) { ss << newTree; ZCTestingIncrementalMerkleTree newTreeSmall; - BOOST_CHECK_THROW(ss >> newTreeSmall, std::ios_base::failure); + BOOST_CHECK_THROW({ss >> newTreeSmall;}, std::ios_base::failure); } BOOST_AUTO_TEST_CASE( testZeroElements ) { diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index e2543cbe5..d4e87824d 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -51,6 +51,16 @@ void IncrementalMerkleTree::wfcheck() const { if (parents.size() >= Depth) { throw std::ios_base::failure("tree has too many parents"); } + + // The last parent cannot be null. + bool wasnull = false; + BOOST_FOREACH(const boost::optional& parent, parents) { + wasnull = !parent; + } + + if (wasnull) { + throw std::ios_base::failure("tree has non-canonical representation of parent"); + } } template From d0c4b0e8505e739fc9eb28c847a0d64560ce773e Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 Apr 2016 11:44:16 -0600 Subject: [PATCH 08/12] Add more well-formedness checks/tests to tree. --- src/test/merkle_tests.cpp | 40 +++++++++++++++++++++++++++++ src/zcash/IncrementalMerkleTree.cpp | 10 ++++++++ 2 files changed, 50 insertions(+) diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index c98e6d703..c6b19cf2c 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -7,6 +7,8 @@ #include +#include + #include "utilstrencodings.h" #include "version.h" @@ -319,6 +321,8 @@ BOOST_AUTO_TEST_CASE(tree_test_vectors) } BOOST_AUTO_TEST_CASE( deserializeInvalid ) { + // attempt to deserialize a small tree from a serialized large tree + // (exceeds depth well-formedness check) ZCIncrementalMerkleTree newTree; for (size_t i = 0; i < 16; i++) { @@ -334,6 +338,42 @@ BOOST_AUTO_TEST_CASE( deserializeInvalid ) { BOOST_CHECK_THROW({ss >> newTreeSmall;}, std::ios_base::failure); } +BOOST_AUTO_TEST_CASE( deserializeInvalid2 ) { + // the most ancestral parent is empty + CDataStream ss( + ParseHex("0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3000100"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE( deserializeInvalid3 ) { + // left doesn't exist but right does + CDataStream ss( + ParseHex("000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + +BOOST_AUTO_TEST_CASE( deserializeInvalid4 ) { + // left doesn't exist but a parent does + CDataStream ss( + ParseHex("000001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); +} + BOOST_AUTO_TEST_CASE( testZeroElements ) { for (int start = 0; start < 20; start++) { ZCIncrementalMerkleTree newTree; diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index d4e87824d..0a391486a 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -61,6 +61,16 @@ void IncrementalMerkleTree::wfcheck() const { if (wasnull) { throw std::ios_base::failure("tree has non-canonical representation of parent"); } + + // Left cannot be empty when right exists. + if (!left && right) { + throw std::ios_base::failure("tree has non-canonical representation of tree"); + } + + // Left cannot be empty when parents is nonempty. + if (!left && parents.size() > 0) { + throw std::ios_base::failure("tree has non-canonical representation of tree"); + } } template From 9b92a9d5fbd9333bb1e3c79ba6ba6f6b479fe930 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Thu, 21 Apr 2016 12:02:43 -0600 Subject: [PATCH 09/12] Make appending algorithm more succinct. --- src/zcash/IncrementalMerkleTree.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index 0a391486a..c47862d1f 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -93,22 +93,20 @@ void IncrementalMerkleTree::append(Hash obj) { left = obj; right = boost::none; - // Propagate up the tree as much as needed - BOOST_FOREACH(boost::optional& parent, parents) { - if (parent) { - combined = Hash::combine(*parent, *combined); - parent = boost::none; + for (size_t i = 0; i < Depth; i++) { + if (i < parents.size()) { + if (parents[i]) { + combined = Hash::combine(*parents[i], *combined); + parents[i] = boost::none; + } else { + parents[i] = *combined; + break; + } } else { - parent = *combined; - combined = boost::none; + parents.push_back(combined); break; } } - - if (combined) { - // Create a new parent - parents.push_back(combined); - } } } From 6850b45e4dceffa811ab7906e8884e18fb0ff845 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Wed, 27 Apr 2016 11:01:50 -0600 Subject: [PATCH 10/12] Move incremental merkle tree tests to zcash-gtest. --- src/Makefile.test.include | 7 +- src/gtest/test_merkletree.cpp | 417 +++++++++++++++++++++++++++++++++- src/test/merkle_tests.cpp | 400 -------------------------------- 3 files changed, 418 insertions(+), 406 deletions(-) delete mode 100644 src/test/merkle_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index f6065de59..e5656eaac 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -82,8 +82,7 @@ BITCOIN_TESTS =\ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ - test/sha256compress_tests.cpp \ - test/merkle_tests.cpp + test/sha256compress_tests.cpp if ENABLE_WALLET BITCOIN_TESTS += \ @@ -95,12 +94,12 @@ endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(LIBZEROCASH) $(LIBZEROCASH_LIBS) + $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif -test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) +test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBZEROCASH) $(LIBZEROCASH_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index ca7b23b3b..a22885ff3 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -1,5 +1,418 @@ #include -TEST(tautologies, eight_eq_eight) { - ASSERT_EQ(8, 8); +#include "test/data/merkle_roots.json.h" +#include "test/data/merkle_serialization.json.h" +#include "test/data/merkle_witness_serialization.json.h" +#include "test/data/merkle_path.json.h" + +#include + +#include + +#include "utilstrencodings.h" +#include "version.h" +#include "serialize.h" +#include "streams.h" + +#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp" +#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp" +#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp" +#include "libsnark/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp" + +#include + +#include "json/json_spirit_reader_template.h" +#include "json/json_spirit_utils.h" +#include "json/json_spirit_writer_template.h" + +using namespace json_spirit; +Array +read_json(const std::string& jsondata) +{ + Value v; + + if (!read_string(jsondata, v) || v.type() != array_type) + { + ADD_FAILURE(); + return Array(); + } + return v.get_array(); +} + +#include "zcash/IncrementalMerkleTree.hpp" +#include "zerocash/IncrementalMerkleTree.h" +#include "zerocash/utils/util.h" + +//#define PRINT_JSON 1 + +using namespace std; +using namespace libzerocash; +using namespace libsnark; + +template +void expect_deser_same(const T& expected) +{ + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss1 << expected; + + auto serialized_size = ss1.size(); + + T object; + ss1 >> object; + + CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); + ss2 << object; + + ASSERT_TRUE(serialized_size == ss2.size()); + ASSERT_TRUE(memcmp(&*ss1.begin(), &*ss2.begin(), serialized_size) == 0); +} + +template<> +void expect_deser_same(const ZCTestingIncrementalWitness& expected) +{ + // Cannot check this; IncrementalWitness cannot be + // deserialized because it can only be constructed by + // IncrementalMerkleTree, and it does not yet have a + // canonical serialized representation. +} + +template<> +void expect_deser_same(const libzcash::MerklePath& expected) +{ + // This deserialization check is pointless for MerklePath, + // since we only serialize it to check it against test + // vectors. See `expect_test_vector` for that. Also, + // it doesn't seem that vector can be properly + // deserialized by Bitcoin's serialization code. +} + +template +void expect_test_vector(T& it, const U& expected) +{ + expect_deser_same(expected); + + CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); + ss1 << expected; + + #ifdef PRINT_JSON + std::cout << "\t\"" ; + std::cout << HexStr(ss1.begin(), ss1.end()) << "\",\n"; + #else + std::string raw = (it++)->get_str(); + CDataStream ss2(ParseHex(raw), SER_NETWORK, PROTOCOL_VERSION); + + ASSERT_TRUE(ss1.size() == ss2.size()); + ASSERT_TRUE(memcmp(&*ss1.begin(), &*ss2.begin(), ss1.size()) == 0); + #endif +} + +/* +This is a wrapper around the old incremental merkle tree which +attempts to mimic the new API as much as possible so that its +behavior can be compared with the test vectors we use. +*/ +class OldIncrementalMerkleTree { +private: + libzerocash::IncrementalMerkleTree* tree; + boost::optional> index; + bool witnessed; + +public: + OldIncrementalMerkleTree() : index(boost::none), witnessed(false) { + this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + } + + ~OldIncrementalMerkleTree() + { + delete tree; + } + + OldIncrementalMerkleTree (const OldIncrementalMerkleTree& other) : index(boost::none), witnessed(false) + { + this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + this->tree->setTo(*other.tree); + index = other.index; + witnessed = other.witnessed; + } + + OldIncrementalMerkleTree& operator= (const OldIncrementalMerkleTree& other) + { + OldIncrementalMerkleTree tmp(other); // re-use copy-constructor + *this = std::move(tmp); // re-use move-assignment + return *this; + } + + OldIncrementalMerkleTree& operator= (OldIncrementalMerkleTree&& other) + { + tree->setTo(*other.tree); + index = other.index; + witnessed = other.witnessed; + return *this; + } + + libzcash::MerklePath path() { + assert(witnessed); + + if (!index) { + throw std::runtime_error("can't create an authentication path for the beginning of the tree"); + } + + merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); + tree->getWitness(*index, path); + + libzcash::MerklePath ret; + ret.authentication_path = path; + ret.index = *index; + + return ret; + } + + uint256 root() { + std::vector newrt_v(32); + tree->getRootValue(newrt_v); + return uint256(newrt_v); + } + + void append(uint256 obj) { + std::vector new_index; + std::vector obj_bv(obj.begin(), obj.end()); + + std::vector commitment_bv(256); + libzerocash::convertBytesVectorToVector(obj_bv, commitment_bv); + + tree->insertElement(commitment_bv, new_index); + + if (!witnessed) { + index = new_index; + } + } + + OldIncrementalMerkleTree witness() { + OldIncrementalMerkleTree ret; + ret.tree->setTo(*tree); + ret.index = index; + ret.witnessed = true; + + return ret; + } +}; + +template +void expect_ser_test_vector(B& b, const C& c, const A& tree) { + expect_test_vector(b, c); +} + +template +void expect_ser_test_vector(B& b, const C& c, const OldIncrementalMerkleTree& tree) { + // Don't perform serialization tests on the old tree. +} + +template +void test_tree(Array root_tests, Array ser_tests, Array witness_ser_tests, Array path_tests) { + Array::iterator root_iterator = root_tests.begin(); + Array::iterator ser_iterator = ser_tests.begin(); + Array::iterator witness_ser_iterator = witness_ser_tests.begin(); + Array::iterator path_iterator = path_tests.begin(); + + uint256 test_commitment = uint256S("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + + Tree tree; + + // The root of the tree at this point is expected to be null. + ASSERT_TRUE(tree.root().IsNull()); + + // We need to witness at every single point in the tree, so + // that the consistency of the tree and the merkle paths can + // be checked. + vector witnesses; + + for (size_t i = 0; i < 16; i++) { + // Witness here + witnesses.push_back(tree.witness()); + + // Now append a commitment to the tree + tree.append(test_commitment); + + // Check tree root consistency + expect_test_vector(root_iterator, tree.root()); + + // Check serialization of tree + expect_ser_test_vector(ser_iterator, tree, tree); + + bool first = true; // The first witness can never form a path + BOOST_FOREACH(Witness& wit, witnesses) + { + // Append the same commitment to all the witnesses + wit.append(test_commitment); + + if (first) { + ASSERT_THROW(wit.path(), std::runtime_error); + } else { + auto path = wit.path(); + + // The old tree has some serious bugs which make it + // fail some of these test vectors. + // + // The new tree is strictly more correct in its + // behavior, as we demonstrate by constructing and + // evaluating the tree over a dummy circuit. + if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { + expect_test_vector(path_iterator, path); + + typedef Fr FieldT; + + protoboard pb; + pb_variable_array positions; + digest_variable commitment(pb, 256, "commitment"); + digest_variable root(pb, 256, "root"); + positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos"); + merkle_authentication_path_variable> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth"); + merkle_tree_check_read_gadget> auth( + pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path" + ); + commitment.generate_r1cs_constraints(); + root.generate_r1cs_constraints(); + authvars.generate_r1cs_constraints(); + auth.generate_r1cs_constraints(); + + std::vector commitment_bv; + { + std::vector commitment_v(test_commitment.begin(), test_commitment.end()); + convertBytesVectorToVector(commitment_v, commitment_bv); + } + + size_t path_index = libzerocash::convertVectorToInt(path.index); + + commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv)); + positions.fill_with_bits_of_ulong(pb, path_index); + + authvars.generate_r1cs_witness(path_index, path.authentication_path); + auth.generate_r1cs_witness(); + + std::vector root_bv; + { + uint256 witroot = wit.root(); + std::vector root_v(witroot.begin(), witroot.end()); + convertBytesVectorToVector(root_v, root_bv); + } + + root.bits.fill_with_bits(pb, bit_vector(root_bv)); + + ASSERT_TRUE(pb.is_satisfied()); + + root_bv[0] = !root_bv[0]; + root.bits.fill_with_bits(pb, bit_vector(root_bv)); + + ASSERT_TRUE(!pb.is_satisfied()); + } + } + + // Check witness serialization + expect_ser_test_vector(witness_ser_iterator, wit, tree); + + ASSERT_TRUE(wit.root() == tree.root()); + + first = false; + } + } + + // The old tree would silently ignore appending when it was full. + if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { + // Tree should be full now + ASSERT_THROW(tree.append(uint256()), std::runtime_error); + + BOOST_FOREACH(Witness& wit, witnesses) + { + ASSERT_THROW(wit.append(uint256()), std::runtime_error); + } + } +} + +TEST(merkletree, vectors) { + libsnark::default_r1cs_ppzksnark_pp::init_public_params(); + + Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); + Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); + Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); + Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); + + test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); + test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); +} + +TEST(merkletree, deserializeInvalid) { + // attempt to deserialize a small tree from a serialized large tree + // (exceeds depth well-formedness check) + ZCIncrementalMerkleTree newTree; + + for (size_t i = 0; i < 16; i++) { + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + } + + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << newTree; + + ZCTestingIncrementalMerkleTree newTreeSmall; + ASSERT_THROW({ss >> newTreeSmall;}, std::ios_base::failure); +} + +TEST(merkletree, deserializeInvalid2) { + // the most ancestral parent is empty + CDataStream ss( + ParseHex("0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3000100"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + ASSERT_THROW(ss >> tree, std::ios_base::failure); +} + +TEST(merkletree, deserializeInvalid3) { + // left doesn't exist but right does + CDataStream ss( + ParseHex("000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + ASSERT_THROW(ss >> tree, std::ios_base::failure); +} + +TEST(merkletree, deserializeInvalid4) { + // left doesn't exist but a parent does + CDataStream ss( + ParseHex("000001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d"), + SER_NETWORK, + PROTOCOL_VERSION + ); + + ZCIncrementalMerkleTree tree; + ASSERT_THROW(ss >> tree, std::ios_base::failure); +} + +TEST(merkletree, testZeroElements) { + for (int start = 0; start < 20; start++) { + ZCIncrementalMerkleTree newTree; + + ASSERT_TRUE(newTree.root() == uint256()); + + for (int i = start; i > 0; i--) { + newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); + } + + uint256 oldroot = newTree.root(); + + // At this point, appending tons of null objects to the tree + // should preserve its root. + + for (int i = 0; i < 100; i++) { + newTree.append(uint256()); + } + + ASSERT_TRUE(newTree.root() == oldroot); + } } diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp deleted file mode 100644 index c6b19cf2c..000000000 --- a/src/test/merkle_tests.cpp +++ /dev/null @@ -1,400 +0,0 @@ -#include "test/test_bitcoin.h" - -#include "data/merkle_roots.json.h" -#include "data/merkle_serialization.json.h" -#include "data/merkle_witness_serialization.json.h" -#include "data/merkle_path.json.h" - -#include - -#include - -#include "utilstrencodings.h" -#include "version.h" - -#include -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" -using namespace json_spirit; -extern Array read_json(const std::string& jsondata); - -#include "zcash/IncrementalMerkleTree.hpp" -#include "zerocash/IncrementalMerkleTree.h" - -//#define PRINT_JSON 1 - -using namespace std; - -template -void expect_deser_same(const T& expected) -{ - CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); - ss1 << expected; - - auto serialized_size = ss1.size(); - - T object; - ss1 >> object; - - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << object; - - BOOST_CHECK(serialized_size == ss2.size()); - BOOST_CHECK(memcmp(&*ss1.begin(), &*ss2.begin(), serialized_size) == 0); -} - -template<> -void expect_deser_same(const ZCTestingIncrementalWitness& expected) -{ - // Cannot check this; IncrementalWitness cannot be - // deserialized because it can only be constructed by - // IncrementalMerkleTree, and it does not yet have a - // canonical serialized representation. -} - -template<> -void expect_deser_same(const libzcash::MerklePath& expected) -{ - // This deserialization check is pointless for MerklePath, - // since we only serialize it to check it against test - // vectors. See `expect_test_vector` for that. Also, - // it doesn't seem that vector can be properly - // deserialized by Bitcoin's serialization code. -} - -template -void expect_test_vector(T& it, const U& expected) -{ - expect_deser_same(expected); - - CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); - ss1 << expected; - - #ifdef PRINT_JSON - std::cout << "\t\"" ; - std::cout << HexStr(ss1.begin(), ss1.end()) << "\",\n"; - #else - std::string raw = (it++)->get_str(); - CDataStream ss2(ParseHex(raw), SER_NETWORK, PROTOCOL_VERSION); - - BOOST_CHECK(ss1.size() == ss2.size()); - BOOST_CHECK(memcmp(&*ss1.begin(), &*ss2.begin(), ss1.size()) == 0); - #endif -} - -/* -This is a wrapper around the old incremental merkle tree which -attempts to mimic the new API as much as possible so that its -behavior can be compared with the test vectors we use. -*/ -class OldIncrementalMerkleTree { -private: - libzerocash::IncrementalMerkleTree* tree; - boost::optional> index; - bool witnessed; - -public: - OldIncrementalMerkleTree() : index(boost::none), witnessed(false) { - this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); - } - - ~OldIncrementalMerkleTree() - { - delete tree; - } - - OldIncrementalMerkleTree (const OldIncrementalMerkleTree& other) : index(boost::none), witnessed(false) - { - this->tree = new IncrementalMerkleTree(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); - this->tree->setTo(*other.tree); - index = other.index; - witnessed = other.witnessed; - } - - OldIncrementalMerkleTree& operator= (const OldIncrementalMerkleTree& other) - { - OldIncrementalMerkleTree tmp(other); // re-use copy-constructor - *this = std::move(tmp); // re-use move-assignment - return *this; - } - - OldIncrementalMerkleTree& operator= (OldIncrementalMerkleTree&& other) - { - tree->setTo(*other.tree); - index = other.index; - witnessed = other.witnessed; - return *this; - } - - libzcash::MerklePath path() { - assert(witnessed); - - if (!index) { - throw std::runtime_error("can't create an authentication path for the beginning of the tree"); - } - - merkle_authentication_path path(INCREMENTAL_MERKLE_TREE_DEPTH_TESTING); - tree->getWitness(*index, path); - - libzcash::MerklePath ret; - ret.authentication_path = path; - ret.index = *index; - - return ret; - } - - uint256 root() { - std::vector newrt_v(32); - tree->getRootValue(newrt_v); - return uint256(newrt_v); - } - - void append(uint256 obj) { - std::vector new_index; - std::vector obj_bv(obj.begin(), obj.end()); - - std::vector commitment_bv(256); - libzerocash::convertBytesVectorToVector(obj_bv, commitment_bv); - - tree->insertElement(commitment_bv, new_index); - - if (!witnessed) { - index = new_index; - } - } - - OldIncrementalMerkleTree witness() { - OldIncrementalMerkleTree ret; - ret.tree->setTo(*tree); - ret.index = index; - ret.witnessed = true; - - return ret; - } -}; - -template -void expect_ser_test_vector(B& b, const C& c, const A& tree) { - expect_test_vector(b, c); -} - -template -void expect_ser_test_vector(B& b, const C& c, const OldIncrementalMerkleTree& tree) { - // Don't perform serialization tests on the old tree. -} - -template -void test_tree(Array root_tests, Array ser_tests, Array witness_ser_tests, Array path_tests) { - Array::iterator root_iterator = root_tests.begin(); - Array::iterator ser_iterator = ser_tests.begin(); - Array::iterator witness_ser_iterator = witness_ser_tests.begin(); - Array::iterator path_iterator = path_tests.begin(); - - uint256 test_commitment = uint256S("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); - - Tree tree; - - // The root of the tree at this point is expected to be null. - BOOST_CHECK(tree.root().IsNull()); - - // We need to witness at every single point in the tree, so - // that the consistency of the tree and the merkle paths can - // be checked. - vector witnesses; - - for (size_t i = 0; i < 16; i++) { - // Witness here - witnesses.push_back(tree.witness()); - - // Now append a commitment to the tree - tree.append(test_commitment); - - // Check tree root consistency - expect_test_vector(root_iterator, tree.root()); - - // Check serialization of tree - expect_ser_test_vector(ser_iterator, tree, tree); - - bool first = true; // The first witness can never form a path - BOOST_FOREACH(Witness& wit, witnesses) - { - // Append the same commitment to all the witnesses - wit.append(test_commitment); - - if (first) { - BOOST_CHECK_THROW(wit.path(), std::runtime_error); - } else { - auto path = wit.path(); - - // The old tree has some serious bugs which make it - // fail some of these test vectors. - // - // The new tree is strictly more correct in its - // behavior, as we demonstrate by constructing and - // evaluating the tree over a dummy circuit. - if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { - expect_test_vector(path_iterator, path); - - typedef Fr FieldT; - - protoboard pb; - pb_variable_array positions; - digest_variable commitment(pb, 256, "commitment"); - digest_variable root(pb, 256, "root"); - positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos"); - merkle_authentication_path_variable> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth"); - merkle_tree_check_read_gadget> auth( - pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path" - ); - commitment.generate_r1cs_constraints(); - root.generate_r1cs_constraints(); - authvars.generate_r1cs_constraints(); - auth.generate_r1cs_constraints(); - - std::vector commitment_bv; - { - std::vector commitment_v(test_commitment.begin(), test_commitment.end()); - convertBytesVectorToVector(commitment_v, commitment_bv); - } - - size_t path_index = libzerocash::convertVectorToInt(path.index); - - commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv)); - positions.fill_with_bits_of_ulong(pb, path_index); - - authvars.generate_r1cs_witness(path_index, path.authentication_path); - auth.generate_r1cs_witness(); - - std::vector root_bv; - { - uint256 witroot = wit.root(); - std::vector root_v(witroot.begin(), witroot.end()); - convertBytesVectorToVector(root_v, root_bv); - } - - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - BOOST_CHECK(pb.is_satisfied()); - - root_bv[0] = !root_bv[0]; - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - BOOST_CHECK(!pb.is_satisfied()); - } - } - - // Check witness serialization - expect_ser_test_vector(witness_ser_iterator, wit, tree); - - BOOST_CHECK(wit.root() == tree.root()); - - first = false; - } - } - - // The old tree would silently ignore appending when it was full. - if (typeid(Tree) != typeid(OldIncrementalMerkleTree)) { - // Tree should be full now - BOOST_CHECK_THROW(tree.append(uint256()), std::runtime_error); - - BOOST_FOREACH(Witness& wit, witnesses) - { - BOOST_CHECK_THROW(wit.append(uint256()), std::runtime_error); - } - } -} - -BOOST_FIXTURE_TEST_SUITE(merkle_tests, BasicTestingSetup) - -BOOST_AUTO_TEST_CASE(tree_test_vectors) -{ - libsnark::default_r1cs_ppzksnark_pp::init_public_params(); - - Array root_tests = read_json(std::string(json_tests::merkle_roots, json_tests::merkle_roots + sizeof(json_tests::merkle_roots))); - Array ser_tests = read_json(std::string(json_tests::merkle_serialization, json_tests::merkle_serialization + sizeof(json_tests::merkle_serialization))); - Array witness_ser_tests = read_json(std::string(json_tests::merkle_witness_serialization, json_tests::merkle_witness_serialization + sizeof(json_tests::merkle_witness_serialization))); - Array path_tests = read_json(std::string(json_tests::merkle_path, json_tests::merkle_path + sizeof(json_tests::merkle_path))); - - test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); - test_tree(root_tests, ser_tests, witness_ser_tests, path_tests); -} - -BOOST_AUTO_TEST_CASE( deserializeInvalid ) { - // attempt to deserialize a small tree from a serialized large tree - // (exceeds depth well-formedness check) - ZCIncrementalMerkleTree newTree; - - for (size_t i = 0; i < 16; i++) { - newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); - } - - newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << newTree; - - ZCTestingIncrementalMerkleTree newTreeSmall; - BOOST_CHECK_THROW({ss >> newTreeSmall;}, std::ios_base::failure); -} - -BOOST_AUTO_TEST_CASE( deserializeInvalid2 ) { - // the most ancestral parent is empty - CDataStream ss( - ParseHex("0155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e3000100"), - SER_NETWORK, - PROTOCOL_VERSION - ); - - ZCIncrementalMerkleTree tree; - BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); -} - -BOOST_AUTO_TEST_CASE( deserializeInvalid3 ) { - // left doesn't exist but right does - CDataStream ss( - ParseHex("000155b852781b9995a44c939b64e441ae2724b96f99c8f4fb9a141cfc9842c4b0e300"), - SER_NETWORK, - PROTOCOL_VERSION - ); - - ZCIncrementalMerkleTree tree; - BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); -} - -BOOST_AUTO_TEST_CASE( deserializeInvalid4 ) { - // left doesn't exist but a parent does - CDataStream ss( - ParseHex("000001018695873d63ec0bceeadb5bf4ccc6723ac803c1826fc7cfb34fc76180305ae27d"), - SER_NETWORK, - PROTOCOL_VERSION - ); - - ZCIncrementalMerkleTree tree; - BOOST_CHECK_THROW(ss >> tree, std::ios_base::failure); -} - -BOOST_AUTO_TEST_CASE( testZeroElements ) { - for (int start = 0; start < 20; start++) { - ZCIncrementalMerkleTree newTree; - - BOOST_CHECK(newTree.root() == uint256()); - - for (int i = start; i > 0; i--) { - newTree.append(uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c")); - } - - uint256 oldroot = newTree.root(); - - // At this point, appending tons of null objects to the tree - // should preserve its root. - - for (int i = 0; i < 100; i++) { - newTree.append(uint256()); - } - - BOOST_CHECK(newTree.root() == oldroot); - } -} - -BOOST_AUTO_TEST_SUITE_END() From 6f1b70300de936f49d3a6d6df36f46be04f3b85a Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 29 Apr 2016 10:05:06 -0600 Subject: [PATCH 11/12] Small nit fixes --- src/zcash/IncrementalMerkleTree.cpp | 11 +++-------- src/zcash/IncrementalMerkleTree.hpp | 8 +++++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index c47862d1f..426abe1de 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -53,12 +53,7 @@ void IncrementalMerkleTree::wfcheck() const { } // The last parent cannot be null. - bool wasnull = false; - BOOST_FOREACH(const boost::optional& parent, parents) { - wasnull = !parent; - } - - if (wasnull) { + if (!(parents.empty()) && !(parents.back())) { throw std::ios_base::failure("tree has non-canonical representation of parent"); } @@ -89,7 +84,7 @@ void IncrementalMerkleTree::append(Hash obj) { // Combine the leaves and propagate it up the tree boost::optional combined = Hash::combine(*left, *right); - // Set the left leaf to the object and make the right object none + // Set the "left" leaf to the object and make the "right" leaf none left = obj; right = boost::none; @@ -261,7 +256,7 @@ MerklePath IncrementalMerkleTree::path(std::deque filler_hash } template -std::deque IncrementalWitness::uncle_train() const { +std::deque IncrementalWitness::partial_path() const { std::deque uncles(filled.begin(), filled.end()); if (cursor) { diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp index f170ffffa..ff31cc50b 100644 --- a/src/zcash/IncrementalMerkleTree.hpp +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -68,6 +68,8 @@ public: private: boost::optional left; boost::optional right; + + // Collapsed "left" subtrees ordered toward the root of the tree. std::vector> parents; MerklePath path(std::deque filler_hashes = std::deque()) const; Hash root(size_t depth, std::deque filler_hashes = std::deque()) const; @@ -82,11 +84,11 @@ friend class IncrementalMerkleTree; public: MerklePath path() const { - return tree.path(uncle_train()); + return tree.path(partial_path()); } Hash root() const { - return tree.root(Depth, uncle_train()); + return tree.root(Depth, partial_path()); } void append(Hash obj); @@ -107,7 +109,7 @@ private: std::vector filled; boost::optional> cursor; size_t cursor_depth; - std::deque uncle_train() const; + std::deque partial_path() const; IncrementalWitness(IncrementalMerkleTree tree) : tree(tree) {} }; From 26007222e89a69fed9c06ad05609774116ad13d4 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Tue, 3 May 2016 11:23:54 -0600 Subject: [PATCH 12/12] Distinguish the failure cases of wfcheck in tree. --- src/zcash/IncrementalMerkleTree.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index 426abe1de..58f6a0bdc 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -59,12 +59,12 @@ void IncrementalMerkleTree::wfcheck() const { // Left cannot be empty when right exists. if (!left && right) { - throw std::ios_base::failure("tree has non-canonical representation of tree"); + throw std::ios_base::failure("tree has non-canonical representation; right should not exist"); } // Left cannot be empty when parents is nonempty. if (!left && parents.size() > 0) { - throw std::ios_base::failure("tree has non-canonical representation of tree"); + throw std::ios_base::failure("tree has non-canonical representation; parents should not be unempty"); } }