Initial merge

This commit is contained in:
jl777
2017-03-30 04:35:16 +03:00
633 changed files with 11230 additions and 184263 deletions

View File

@@ -1,14 +1,14 @@
#include "json_test_vectors.h"
Array
UniValue
read_json(const std::string& jsondata)
{
Value v;
UniValue v;
if (!read_string(jsondata, v) || v.type() != array_type)
if (!(v.read(jsondata) && v.isArray()))
{
ADD_FAILURE();
return Array();
return UniValue(UniValue::VARR);
}
return v.get_array();
}

View File

@@ -5,12 +5,9 @@
#include "serialize.h"
#include "streams.h"
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_writer_template.h"
#include <univalue.h>
using namespace json_spirit;
Array
UniValue
read_json(const std::string& jsondata);
// #define PRINT_JSON 1
@@ -34,7 +31,7 @@ void expect_deser_same(const T& expected)
}
template<typename T, typename U>
void expect_test_vector(T& it, const U& expected)
void expect_test_vector(T& v, const U& expected)
{
expect_deser_same(expected);
@@ -45,7 +42,7 @@ void expect_test_vector(T& it, const U& expected)
std::cout << "\t\"" ;
std::cout << HexStr(ss1.begin(), ss1.end()) << "\",\n";
#else
std::string raw = (it++)->get_str();
std::string raw = v.get_str();
CDataStream ss2(ParseHex(raw), SER_NETWORK, PROTOCOL_VERSION);
ASSERT_TRUE(ss1.size() == ss2.size());

View File

@@ -1,3 +1,7 @@
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#include <gtest/gtest.h>
#include <gmock/gmock.h>
@@ -76,6 +80,7 @@ TEST(equihash_tests, is_probably_duplicate) {
ASSERT_TRUE(IsProbablyDuplicate<4>(p3, 4));
}
#ifdef ENABLE_MINING
TEST(equihash_tests, check_basic_solver_cancelled) {
Equihash<48,5> Eh48_5;
crypto_generichash_blake2b_state state;
@@ -283,3 +288,4 @@ TEST(equihash_tests, check_optimised_solver_cancelled) {
}), EhSolverCancelledException);
}
}
#endif // ENABLE_MINING

View File

@@ -44,13 +44,22 @@ TEST(founders_reward_test, create_testnet_2of3multisig) {
for (int i = 0; i < numKeys; i++) {
ASSERT_TRUE(pWallet->GetKeyFromPool(newKey));
pubkeys[0] = newKey;
pWallet->SetAddressBook(newKey.GetID(), "", "receive");
ASSERT_TRUE(pWallet->GetKeyFromPool(newKey));
pubkeys[1] = newKey;
pWallet->SetAddressBook(newKey.GetID(), "", "receive");
ASSERT_TRUE(pWallet->GetKeyFromPool(newKey));
pubkeys[2] = newKey;
pWallet->SetAddressBook(newKey.GetID(), "", "receive");
CScript result = GetScriptForMultisig(2, pubkeys);
ASSERT_FALSE(result.size() > MAX_SCRIPT_ELEMENT_SIZE);
CScriptID innerID(result);
pWallet->AddCScript(result);
pWallet->SetAddressBook(innerID, "", "receive");
std::string address = CBitcoinAddress(innerID).ToString();
addresses.push_back(address);
}
@@ -92,12 +101,16 @@ TEST(founders_reward_test, general) {
CChainParams params = Params();
// First testnet reward:
// address = t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi
// script = OP_HASH160 ef775f1f997f122a062fff1a2d7443abd1f9c642 OP_EQUAL
// raw script = a914ef775f1f997f122a062fff1a2d7443abd1f9c64287
// Fourth testnet reward:
// address = t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy
// script.ToString() = OP_HASH160 55d64928e69829d9376c776550b6cc710d427153 OP_EQUAL
// HexStr(script) = a91455d64928e69829d9376c776550b6cc710d42715387
EXPECT_EQ(params.GetFoundersRewardScriptAtHeight(1), ParseHex("a914ef775f1f997f122a062fff1a2d7443abd1f9c64287"));
EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(1), "t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi");
EXPECT_EQ(params.GetFoundersRewardScriptAtHeight(53126), ParseHex("a914ac67f4c072668138d88a86ff21b27207b283212f87"));
EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(53126), "t2NGQjYMQhFndDHguvUw4wZdNdsssA6K7x2");
EXPECT_EQ(params.GetFoundersRewardScriptAtHeight(53127), ParseHex("a91455d64928e69829d9376c776550b6cc710d42715387"));
EXPECT_EQ(params.GetFoundersRewardAddressAtHeight(53127), "t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy");
int maxHeight = params.GetConsensus().GetLastFoundersRewardBlockHeight();

View File

@@ -1,17 +0,0 @@
#include <gtest/gtest.h>
#include "json/json_spirit_reader_template.h"
using namespace json_spirit;
// This test checks if we have fixed a stack overflow problem with json_spirit.
// It was possible to try and create an unlimited number of nested compound elements.
// Without the fix in json_spirit_reader_template.h, this test will segfault.
TEST(json_spirit_tests, nested_input_segfault) {
std::vector<char> v (100000);
std::fill (v.begin(),v.end(), '[');
std::string s(v.begin(), v.end());
Value value;
bool b = json_spirit::read_string(s, value);
ASSERT_FALSE(b);
}

View File

@@ -57,18 +57,15 @@ void expect_ser_test_vector(B& b, const C& c, const A& tree) {
template<typename Tree, typename Witness>
void test_tree(
Array commitment_tests,
Array root_tests,
Array ser_tests,
Array witness_ser_tests,
Array path_tests
UniValue commitment_tests,
UniValue root_tests,
UniValue ser_tests,
UniValue witness_ser_tests,
UniValue path_tests
)
{
Array::iterator commitment_iterator = commitment_tests.begin();
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();
size_t witness_ser_i = 0;
size_t path_i = 0;
Tree tree;
@@ -88,7 +85,7 @@ void test_tree(
vector<Witness> witnesses;
for (size_t i = 0; i < 16; i++) {
uint256 test_commitment = uint256S((commitment_iterator++)->get_str());
uint256 test_commitment = uint256S(commitment_tests[i].get_str());
// Witness here
witnesses.push_back(tree.witness());
@@ -103,10 +100,10 @@ void test_tree(
ASSERT_TRUE(tree.last() == test_commitment);
// Check tree root consistency
expect_test_vector(root_iterator, tree.root());
expect_test_vector(root_tests[i], tree.root());
// Check serialization of tree
expect_ser_test_vector(ser_iterator, tree, tree);
expect_ser_test_vector(ser_tests[i], tree, tree);
bool first = true; // The first witness can never form a path
BOOST_FOREACH(Witness& wit, witnesses)
@@ -121,7 +118,7 @@ void test_tree(
auto path = wit.path();
{
expect_test_vector(path_iterator, path);
expect_test_vector(path_tests[path_i++], path);
typedef Fr<default_r1cs_ppzksnark_pp> FieldT;
@@ -173,7 +170,7 @@ void test_tree(
}
// Check witness serialization
expect_ser_test_vector(witness_ser_iterator, wit, tree);
expect_ser_test_vector(witness_ser_tests[witness_ser_i++], wit, tree);
ASSERT_TRUE(wit.root() == tree.root());
@@ -192,24 +189,25 @@ void test_tree(
}
}
#define MAKE_STRING(x) std::string((x), (x)+sizeof(x))
TEST(merkletree, 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 commitment_tests = read_json(std::string(json_tests::merkle_commitments, json_tests::merkle_commitments + sizeof(json_tests::merkle_commitments)));
UniValue root_tests = read_json(MAKE_STRING(json_tests::merkle_roots));
UniValue ser_tests = read_json(MAKE_STRING(json_tests::merkle_serialization));
UniValue witness_ser_tests = read_json(MAKE_STRING(json_tests::merkle_witness_serialization));
UniValue path_tests = read_json(MAKE_STRING(json_tests::merkle_path));
UniValue commitment_tests = read_json(MAKE_STRING(json_tests::merkle_commitments));
test_tree<ZCTestingIncrementalMerkleTree, ZCTestingIncrementalWitness>(commitment_tests, root_tests, ser_tests, witness_ser_tests, path_tests);
}
TEST(merkletree, emptyroots) {
Array empty_roots = read_json(std::string(json_tests::merkle_roots_empty, json_tests::merkle_roots_empty + sizeof(json_tests::merkle_roots_empty)));
Array::iterator root_iterator = empty_roots.begin();
UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty));
libzcash::EmptyMerkleRoots<64, libzcash::SHA256Compress> emptyroots;
for (size_t depth = 0; depth <= 64; depth++) {
expect_test_vector(root_iterator, emptyroots.empty_root(depth));
expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth));
}
// Double check that we're testing (at least) all the empty roots we'll use.

View File

@@ -4,9 +4,57 @@
#include "utiltime.h"
TEST(Metrics, AtomicTimer) {
AtomicTimer t;
SetMockTime(100);
EXPECT_FALSE(t.running());
t.start();
EXPECT_TRUE(t.running());
t.start();
EXPECT_TRUE(t.running());
t.stop();
EXPECT_TRUE(t.running());
t.stop();
EXPECT_FALSE(t.running());
// Additional calls to stop() are ignored.
t.stop();
EXPECT_FALSE(t.running());
t.start();
EXPECT_TRUE(t.running());
AtomicCounter c;
EXPECT_EQ(0, t.rate(c));
c.increment();
EXPECT_EQ(0, t.rate(c));
SetMockTime(101);
EXPECT_EQ(1, t.rate(c));
c.decrement();
EXPECT_EQ(0, t.rate(c));
SetMockTime(102);
EXPECT_EQ(0, t.rate(c));
c.increment();
EXPECT_EQ(0.5, t.rate(c));
t.stop();
EXPECT_FALSE(t.running());
EXPECT_EQ(0.5, t.rate(c));
}
TEST(Metrics, GetLocalSolPS) {
SetMockTime(100);
MarkStartTime();
miningTimer.start();
// No time has passed
EXPECT_EQ(0, GetLocalSolPS());
@@ -27,4 +75,20 @@ TEST(Metrics, GetLocalSolPS) {
solutionTargetChecks.increment();
solutionTargetChecks.increment();
EXPECT_EQ(1.5, GetLocalSolPS());
// Stop timing
miningTimer.stop();
EXPECT_EQ(1.5, GetLocalSolPS());
// Increment time
SetMockTime(103);
EXPECT_EQ(1.5, GetLocalSolPS());
// Start timing again
miningTimer.start();
EXPECT_EQ(1.5, GetLocalSolPS());
// Increment time
SetMockTime(104);
EXPECT_EQ(1, GetLocalSolPS());
}

103
src/gtest/test_miner.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "chainparams.h"
#include "key.h"
#include "miner.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include <boost/optional.hpp>
using ::testing::Return;
#ifdef ENABLE_WALLET
class MockReserveKey : public CReserveKey {
public:
MockReserveKey() : CReserveKey(nullptr) { }
MOCK_METHOD1(GetReservedKey, bool(CPubKey &pubkey));
};
#endif
TEST(Miner, GetMinerScriptPubKey) {
SelectParams(CBaseChainParams::MAIN);
boost::optional<CScript> scriptPubKey;
#ifdef ENABLE_WALLET
MockReserveKey reservekey;
EXPECT_CALL(reservekey, GetReservedKey(::testing::_))
.WillRepeatedly(Return(false));
#endif
// No miner address set
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
mapArgs["-mineraddress"] = "notAnAddress";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Partial address
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqq";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Typo in address
mapArgs["-mineraddress"] = "t1TByaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Set up expected scriptPubKey for t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF
CKeyID keyID;
keyID.SetHex("eb88f1c65b39a823479ac9c7db2f4a865960a165");
CScript expectedScriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
// Valid address
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
// Valid address with leading whitespace
mapArgs["-mineraddress"] = " t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
// Valid address with trailing whitespace
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF ";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
}

View File

@@ -46,21 +46,25 @@ TEST(noteencryption, api)
ASSERT_TRUE(plaintext == message);
// Test wrong nonce
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), (i == 0) ? 1 : (i - 1)), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), (i == 0) ? 1 : (i - 1)),
libzcash::note_decryption_failed);
// Test wrong ephemeral key
{
ZCNoteEncryption c = ZCNoteEncryption(uint256());
ASSERT_THROW(decrypter.decrypt(ciphertext, c.get_epk(), uint256(), i), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, c.get_epk(), uint256(), i),
libzcash::note_decryption_failed);
}
// Test wrong seed
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256S("11035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a77"), i), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256S("11035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a77"), i),
libzcash::note_decryption_failed);
// Test corrupted ciphertext
ciphertext[10] ^= 0xff;
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i),
libzcash::note_decryption_failed);
ciphertext[10] ^= 0xff;
}
@@ -69,7 +73,8 @@ TEST(noteencryption, api)
uint256 sk_enc_2 = ZCNoteEncryption::generate_privkey(uint252());
ZCNoteDecryption decrypter(sk_enc_2);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i),
libzcash::note_decryption_failed);
}
{
@@ -81,7 +86,8 @@ TEST(noteencryption, api)
// Test wrong public key (test of KDF)
decrypter.change_pk_enc(uint256());
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i),
libzcash::note_decryption_failed);
}
}

View File

@@ -629,15 +629,14 @@ TEST(proofs, g2_deserialization)
TEST(proofs, g1_test_vectors)
{
Array v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed)));
Array::iterator v_iterator = v.begin();
UniValue v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed)));
curve_G1 e = curve_Fr("34958239045823") * curve_G1::one();
for (size_t i = 0; i < 10000; i++) {
e = (curve_Fr("34958239045823") ^ i) * e;
auto expected = CompressedG1(e);
expect_test_vector(v_iterator, expected);
expect_test_vector(v[i], expected);
ASSERT_TRUE(expected.to_libsnark_g1<curve_G1>() == e);
}
}
@@ -646,15 +645,14 @@ TEST(proofs, g1_test_vectors)
TEST(proofs, g2_test_vectors)
{
Array v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed)));
Array::iterator v_iterator = v.begin();
UniValue v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed)));
curve_G2 e = curve_Fr("34958239045823") * curve_G2::one();
for (size_t i = 0; i < 10000; i++) {
e = (curve_Fr("34958239045823") ^ i) * e;
auto expected = CompressedG2(e);
expect_test_vector(v_iterator, expected);
expect_test_vector(v[i], expected);
ASSERT_TRUE(expected.to_libsnark_g2<curve_G2>() == e);
}
}

View File

@@ -1,6 +1,5 @@
#include <gtest/gtest.h>
#include "json/json_spirit_value.h"
#include "json/json_spirit_utils.h"
#include <univalue.h>
#include "chain.h"
#include "chainparams.h"
@@ -10,7 +9,7 @@
#include "streams.h"
#include "utilstrencodings.h"
extern json_spirit::Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
TEST(rpc, check_blockToJSON_returns_minified_solution) {
SelectParams(CBaseChainParams::TESTNET);
@@ -24,6 +23,6 @@ TEST(rpc, check_blockToJSON_returns_minified_solution) {
CBlockIndex index {block};
index.nHeight = 1391;
json_spirit::Object obj = blockToJSON(block, &index);
EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", json_spirit::find_value(obj, "solution").get_str());
UniValue obj = blockToJSON(block, &index);
EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", find_value(obj, "solution").get_str());
}