Logic fixes, unit test

Signed-off-by: Anthony Fieroni <bvbfan@abv.bg>
This commit is contained in:
Anthony Fieroni 2019-08-14 19:56:21 +03:00 committed by Brannon King
parent 3a0b4232a5
commit a98288aa80
3 changed files with 254 additions and 81 deletions

View file

@ -100,7 +100,7 @@ S3(" ", T_AMOUNT, " (numeric) the amount of the support") \
S1(" ]") \
S3(" ", T_LASTTAKEOVERHEIGHT, " (numeric) the last height at which ownership of the name changed") \
S3(" ", T_BID, " (numeric) lower value means a higher bid rate, ordered by effective amount") \
S3(" ", T_SEQUENCE, " (numeric) lower value means latest in sequence, ordered by height of insertion")
S3(" ", T_SEQUENCE, " (numeric) lower value means an older one in sequence, ordered by height of insertion")
#define PROOF_OUTPUT \
S3(" ", T_NODES, ": [ (array of object, pre-fork) full nodes\n" \
@ -194,7 +194,7 @@ S3(" ", T_VALIDATHEIGHT, " (numeric) the height at which the support
S3(" ", T_AMOUNT, " (numeric) the amount of the support")
S1(" ]")
S3(" ", T_BID, " (numeric) lower value means a higher bid rate, ordered by effective amount")
S3(" ", T_SEQUENCE, " (numeric) lower value means latest in sequence, ordered by height of insertion")
S3(" ", T_SEQUENCE, " (numeric) lower value means an older one in sequence, ordered by height of insertion")
S1(" ]")
S3(" ", T_LASTTAKEOVERHEIGHT, " (numeric) the last height at which ownership of the name changed")
S3(" ", T_SUPPORTSWITHOUTCLAIM, ": [")

View file

@ -19,21 +19,22 @@
#include <boost/thread.hpp>
#include <cmath>
void ParseClaimtrieId(const UniValue& v, std::string& partialId, uint160& claimId, const std::string& strName)
{
static constexpr size_t claimIdHexLength = 40;
std::string strHex;
if (v.isStr())
strHex = v.get_str();
if (!IsHex(strHex))
uint160 uint160S(const std::string& str)
{
uint160 s;
s.SetHex(str);
return s;
}
void ParseClaimtrieId(const UniValue& v, std::string& claimId, const std::string& strName)
{
// use IsHexNumber which verify odd strings size
if (!v.isStr() || !IsHexNumber(claimId = v.get_str()))
throw JSONRPCError(RPC_INVALID_PARAMETER, strName + " must be a hexadecimal string");
if (strHex.length() > claimIdHexLength)
if (claimId.length() > claimIdHexLength)
throw JSONRPCError(RPC_INVALID_PARAMETER, strName + " must be max 20-character hexadecimal string");
if (strHex.length() == claimIdHexLength)
claimId.SetHex(strHex);
else
partialId = strHex;
}
static CBlockIndex* BlockHashIndex(const uint256& blockHash)
@ -107,7 +108,7 @@ std::string escapeNonUtf8(const std::string& name)
}
}
static bool getValueForOutPoint(const CScript& scriptPubKey, std::string& sValue)
static bool extractValue(const CScript& scriptPubKey, std::string& sValue)
{
int op;
std::vector<std::vector<unsigned char> > vvchParams;
@ -174,11 +175,9 @@ std::vector<CClaimNsupports> seqSort(const std::vector<CClaimNsupports>& source)
auto claimsNsupports = source;
std::sort(claimsNsupports.begin(), claimsNsupports.end(), [](const CClaimNsupports& lhs, const CClaimNsupports& rhs) {
if (lhs.claim.nHeight > rhs.claim.nHeight)
return true;
if (lhs.claim.nHeight != rhs.claim.nHeight)
return false;
return lhs.claim.outPoint.n > rhs.claim.outPoint.n;
auto& lc = lhs.claim;
auto& rc = rhs.claim;
return lc.nHeight < rc.nHeight || (lc.nHeight == rc.nHeight && lc.outPoint.n < rc.outPoint.n);
});
return claimsNsupports;
@ -204,7 +203,7 @@ UniValue claimToJSON(const CCoinsViewCache& coinsCache, const CClaimValue& claim
auto& coin = coinsCache.AccessCoin(claim.outPoint);
if (!coin.IsSpent()) {
std::string value;
if (getValueForOutPoint(coin.out.scriptPubKey, value))
if (extractValue(coin.out.scriptPubKey, value))
result.pushKV(T_VALUE, value);
CTxDestination address;
@ -229,7 +228,7 @@ UniValue supportToJSON(const CCoinsViewCache& coinsCache, const CSupportValue& s
auto& coin = coinsCache.AccessCoin(support.outPoint);
if (!coin.IsSpent()) {
std::string value;
if (getValueForOutPoint(coin.out.scriptPubKey, value))
if (extractValue(coin.out.scriptPubKey, value))
ret.pushKV(T_VALUE, value);
CTxDestination address;
@ -286,7 +285,6 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
throw JSONRPCError(RPC_METHOD_DEPRECATED, msg);
}
UniValue ret(UniValue::VARR);
LOCK(cs_main);
CCoinsViewCache coinsCache(pcoinsTip.get());
CClaimTrieCache trieCache(pclaimTrie);
@ -296,6 +294,7 @@ static UniValue getclaimsintrie(const JSONRPCRequest& request)
RollBackTo(blockIndex, coinsCache, trieCache);
}
UniValue ret(UniValue::VARR);
trieCache.recurseNodes({}, [&ret, &trieCache, &coinsCache] (const std::string& name, const CClaimTrieData& data) {
if (ShutdownRequested())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
@ -335,8 +334,8 @@ static UniValue getnamesintrie(const JSONRPCRequest& request)
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[0], T_BLOCKHASH " (optional parameter 1)"));
RollBackTo(blockIndex, coinsCache, trieCache);
}
UniValue ret(UniValue::VARR);
UniValue ret(UniValue::VARR);
trieCache.recurseNodes({}, [&ret](const std::string &name, const CClaimTrieData &data) {
if (!data.empty())
ret.push_back(escapeNonUtf8(name));
@ -362,10 +361,9 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
RollBackTo(blockIndex, coinsCache, trieCache);
}
uint160 claimId;
std::string partialId;
std::string claimId;
if (request.params.size() > 2)
ParseClaimtrieId(request.params[2], partialId, claimId, T_CLAIMID " (optional parameter 3)");
ParseClaimtrieId(request.params[2], claimId, T_CLAIMID " (optional parameter 3)");
const auto name = request.params[0].get_str();
UniValue ret(UniValue::VOBJ);
@ -375,8 +373,8 @@ static UniValue getvalueforname(const JSONRPCRequest& request)
return ret;
auto& claimNsupports =
!claimId.IsNull() ? csToName.find(claimId) :
!partialId.empty() ? csToName.find(partialId) : csToName.claimsNsupports[0];
claimId.length() == claimIdHexLength ? csToName.find(uint160S(claimId)) :
!claimId.empty() ? csToName.find(claimId) : csToName.claimsNsupports[0];
if (claimNsupports.IsNull())
return ret;
@ -451,7 +449,7 @@ UniValue getclaimbybid(const JSONRPCRequest& request)
bid = request.params[1].get_int();
if (bid < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, T_BID " (parameter 2) should be greater than 0");
throw JSONRPCError(RPC_INVALID_PARAMETER, T_BID " (parameter 2) should not be a negative value");
if (request.params.size() > 2) {
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[2], T_BLOCKHASH " (optional parameter 3)"));
@ -494,7 +492,7 @@ UniValue getclaimbyseq(const JSONRPCRequest& request)
seq = request.params[1].get_int();
if (seq < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, T_SEQUENCE " (parameter 2) should be greater than 0");
throw JSONRPCError(RPC_INVALID_PARAMETER, T_SEQUENCE " (parameter 2) should not be a negative value");
if (request.params.size() > 2) {
CBlockIndex* blockIndex = BlockHashIndex(ParseHashV(request.params[2], T_BLOCKHASH " (optional parameter 3)"));
@ -534,34 +532,34 @@ UniValue getclaimbyid(const JSONRPCRequest& request)
CClaimTrieCache trieCache(pclaimTrie);
CCoinsViewCache coinsCache(pcoinsTip.get());
uint160 claimId;
std::string partialId;
ParseClaimtrieId(request.params[0], partialId, claimId, T_CLAIMID " (parameter 1)");
std::string claimId;
ParseClaimtrieId(request.params[0], claimId, T_CLAIMID " (parameter 1)");
if (claimId.IsNull() && partialId.length() < 3)
if (claimId.length() < 3)
throw JSONRPCError(RPC_INVALID_PARAMETER, T_CLAIMID " (parameter 1) should be at least 3 chars");
UniValue claim(UniValue::VOBJ);
std::string name;
CClaimValue claimValue;
if (getClaimById(claimId, name, &claimValue) || getClaimById(partialId, name, &claimValue)) {
CClaimValue claim;
UniValue ret(UniValue::VOBJ);
bool found = claimId.length() == claimIdHexLength && getClaimById(uint160S(claimId), name, &claim);
if (found || getClaimById(claimId, name, &claim)) {
auto csToName = trieCache.getClaimsForName(name);
auto& claimNsupports = !claimId.IsNull() ? csToName.find(claimId) : csToName.find(partialId);
auto& claimNsupports = csToName.find(claim.claimId);
if (!claimNsupports.IsNull()) {
std::size_t seq = 0, bid = 0;
if (csToName.claimsNsupports.size() > 1) {
auto seqOrder = seqSort(csToName.claimsNsupports);
seq = indexOf(seqOrder, claimNsupports.claim.claimId);
bid = indexOf(csToName.claimsNsupports, claimNsupports.claim.claimId);
seq = indexOf(seqOrder, claim.claimId);
bid = indexOf(csToName.claimsNsupports, claim.claimId);
}
claim.pushKV(T_NORMALIZEDNAME, escapeNonUtf8(csToName.name));
claim.pushKVs(claimAndSupportsToJSON(coinsCache, claimNsupports));
claim.pushKV(T_LASTTAKEOVERHEIGHT, csToName.nLastTakeoverHeight);
claim.pushKV(T_BID, (int)bid);
claim.pushKV(T_SEQUENCE, (int)seq);
ret.pushKV(T_NORMALIZEDNAME, escapeNonUtf8(csToName.name));
ret.pushKVs(claimAndSupportsToJSON(coinsCache, claimNsupports));
ret.pushKV(T_LASTTAKEOVERHEIGHT, csToName.nLastTakeoverHeight);
ret.pushKV(T_BID, (int)bid);
ret.pushKV(T_SEQUENCE, (int)seq);
}
}
return claim;
return ret;
}
UniValue gettotalclaimednames(const JSONRPCRequest& request)
@ -734,20 +732,21 @@ UniValue getnameproof(const JSONRPCRequest& request)
RollBackTo(pblockIndex, coinsCache, trieCache);
}
uint160 claimId;
std::string partialId;
std::string claimId;
if (request.params.size() > 2)
ParseClaimtrieId(request.params[2], partialId, claimId, T_CLAIMID " (optional parameter 3)");
ParseClaimtrieId(request.params[2], claimId, T_CLAIMID " (optional parameter 3)");
std::function<bool(const CClaimValue&)> comp;
if (!claimId.IsNull())
if (claimId.length() == claimIdHexLength) {
auto claimIdx = uint160S(claimId);
comp = [claimIdx](const CClaimValue& claim) {
return claim.claimId == claimIdx;
};
} else if (!claimId.empty()) {
comp = [&claimId](const CClaimValue& claim) {
return claim.claimId == claimId;
};
else
comp = [&partialId](const CClaimValue& claim) {
return claim.claimId.GetHex().find(partialId) == 0;
return claim.claimId.GetHex().find(claimId) == 0;
};
}
CClaimTrieProof proof;
std::string name = request.params[0].get_str();
@ -770,7 +769,7 @@ UniValue getclaimproofbybid(const JSONRPCRequest& request)
bid = request.params[1].get_int();
if (bid < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, T_BID " (parameter 2) should be greater than 0");
throw JSONRPCError(RPC_INVALID_PARAMETER, T_BID " (parameter 2) should not be a negative value");
if (request.params.size() > 2) {
CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(request.params[2], T_BLOCKHASH " (optional parameter 3)"));
@ -810,7 +809,7 @@ UniValue getclaimproofbyseq(const JSONRPCRequest& request)
seq = request.params[1].get_int();
if (seq < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, T_SEQUENCE " (parameter 2) should be greater than 0");
throw JSONRPCError(RPC_INVALID_PARAMETER, T_SEQUENCE " (parameter 2) should not be a negative value");
if (request.params.size() > 2) {
CBlockIndex* pblockIndex = BlockHashIndex(ParseHashV(request.params[2], T_BLOCKHASH " (optional parameter 3"));
@ -838,9 +837,20 @@ UniValue getclaimproofbyseq(const JSONRPCRequest& request)
extern bool UndoReadFromDisk(CBlockUndo&, const CBlockIndex*);
template <typename T>
UniValue removedToJSON(const std::vector<queueEntryType<T>>& undo)
{
UniValue ret(UniValue::VARR);
for (auto& u : undo) {
auto& outPoint = u.second.outPoint;
ret.push_back(ClaimIdHash(outPoint.hash, outPoint.n).ToString());
}
return ret;
}
UniValue getchangesinblock(const JSONRPCRequest& request)
{
validateRequest(request, GETCHANGESINBLOCK, 1, 0);
validateRequest(request, GETCHANGESINBLOCK, 0, 1);
CBlockUndo undo;
{
@ -861,25 +871,11 @@ UniValue getchangesinblock(const JSONRPCRequest& request)
return added;
};
auto removedClaims = [](const claimQueueRowType& expireUndo) {
UniValue removed(UniValue::VARR);
for (auto& r : expireUndo)
removed.push_back(r.second.claimId.ToString());
return removed;
};
auto removedSupports = [](const supportQueueRowType& expireUndo) {
UniValue removed(UniValue::VARR);
for (auto& r : expireUndo)
removed.push_back(r.second.supportedClaimId.ToString());
return removed;
};
UniValue result(UniValue::VOBJ);
result.pushKV(T_CLAIMSADDEDORUPDATED, addedUpdated(undo.insertUndo));
result.pushKV(T_CLAIMSREMOVED, removedClaims(undo.expireUndo));
result.pushKV(T_CLAIMSREMOVED, removedToJSON(undo.expireUndo));
result.pushKV(T_SUPPORTSADDEDORUPDATED, addedUpdated(undo.insertSupportUndo));
result.pushKV(T_SUPPORTSREMOVED, removedSupports(undo.expireSupportUndo));
result.pushKV(T_SUPPORTSREMOVED, removedToJSON(undo.expireSupportUndo));
return result;
}

View file

@ -4135,9 +4135,9 @@ BOOST_AUTO_TEST_CASE(update_on_support2_test)
BOOST_CHECK_EQUAL(node.nHeightOfLastTakeover, height + 1);
}
void ValidatePairs(CClaimTrieCache& cache, const CClaimTrieProof& proof, uint256 claimHash)
void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash)
{
for (auto& pair : proof.pairs)
for (auto& pair : pairs)
if (pair.first) // we're on the right because we were an odd index number
claimHash = Hash(pair.second.begin(), pair.second.end(), claimHash.begin(), claimHash.end());
else
@ -4182,7 +4182,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_single_test)
BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, outPoint);
auto claimHash = getValueHash(outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof, claimHash);
ValidatePairs(fixture, proof.pairs, claimHash);
}
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test)
@ -4212,7 +4212,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test)
BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof, claimHash);
ValidatePairs(fixture, proof.pairs, claimHash);
}
}
}
@ -4243,7 +4243,7 @@ BOOST_AUTO_TEST_CASE(hash_includes_all_claims_branched_test)
BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof, claimHash);
ValidatePairs(fixture, proof.pairs, claimHash);
}
}
}
@ -4278,9 +4278,186 @@ BOOST_AUTO_TEST_CASE(hash_claims_children_fuzzer_test)
BOOST_CHECK(proof.hasValue);
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
ValidatePairs(fixture, proof, claimHash);
ValidatePairs(fixture, proof.pairs, claimHash);
}
}
}
std::vector<std::pair<bool, uint256>> jsonToPairs(const UniValue& jsonPair)
{
std::vector<std::pair<bool, uint256>> pairs;
for (std::size_t i = 0; i < jsonPair.size(); ++i) {
auto& jpair = jsonPair[i];
pairs.emplace_back(jpair[T_ODD].get_bool(), uint256S(jpair[T_HASH].get_str()));
}
return pairs;
}
BOOST_AUTO_TEST_CASE(hash_bid_seq_claim_changes_test)
{
ClaimTrieChainFixture fixture;
fixture.setHashForkHeight(2);
fixture.IncrementBlocks(4);
std::string name = "toa";
std::string value1 = "one", value2 = "two", value3 = "tre", value4 = "for";
auto tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, value1, 1);
fixture.IncrementBlocks(1);
CMutableTransaction tx2 = BuildTransaction(fixture.GetCoinbase(), 0, 2);
tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME
<< std::vector<unsigned char>(name.begin(), name.end())
<< std::vector<unsigned char>(value2.begin(), value2.end()) << OP_2DROP << OP_DROP << OP_TRUE;
tx2.vout[0].nValue = 3;
tx2.vout[1].scriptPubKey = CScript() << OP_CLAIM_NAME
<< std::vector<unsigned char>(name.begin(), name.end())
<< std::vector<unsigned char>(value3.begin(), value3.end()) << OP_2DROP << OP_DROP << OP_TRUE;
tx2.vout[1].nValue = 2;
fixture.CommitTx(tx2);
fixture.IncrementBlocks(1);
auto tx3 = fixture.MakeClaim(fixture.GetCoinbase(), name, value4, 4);
fixture.IncrementBlocks(1);
int height = chainActive.Height();
auto claimId1 = ClaimIdHash(tx1.GetHash(), 0);
auto claimId2 = ClaimIdHash(tx2.GetHash(), 0);
auto claimId3 = ClaimIdHash(tx2.GetHash(), 1);
auto claimId4 = ClaimIdHash(tx3.GetHash(), 0);
int claim1bid = 3, claim1seq = 0;
int claim2bid = 1, claim2seq = 1;
int claim3bid = 2, claim3seq = 2;
int claim4bid = 0, claim4seq = 3;
auto getclaimsforname = tableRPC["getclaimsforname"]->actor;
JSONRPCRequest req;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
auto result = getclaimsforname(req);
auto claims = result[T_CLAIMS];
BOOST_CHECK_EQUAL(claims.size(), 4U);
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 4);
BOOST_CHECK_EQUAL(claims[0][T_BID].get_int(), claim4bid);
BOOST_CHECK_EQUAL(claims[0][T_SEQUENCE].get_int(), claim4seq);
BOOST_CHECK_EQUAL(claims[0][T_CLAIMID].get_str(), claimId4.GetHex());
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 3);
BOOST_CHECK_EQUAL(claims[1][T_BID].get_int(), claim2bid);
BOOST_CHECK_EQUAL(claims[1][T_SEQUENCE].get_int(), claim2seq);
BOOST_CHECK_EQUAL(claims[1][T_CLAIMID].get_str(), claimId2.GetHex());
BOOST_CHECK_EQUAL(claims[2][T_EFFECTIVEAMOUNT].get_int(), 2);
BOOST_CHECK_EQUAL(claims[2][T_BID].get_int(), claim3bid);
BOOST_CHECK_EQUAL(claims[2][T_SEQUENCE].get_int(), claim3seq);
BOOST_CHECK_EQUAL(claims[2][T_CLAIMID].get_str(), claimId3.GetHex());
BOOST_CHECK_EQUAL(claims[3][T_EFFECTIVEAMOUNT].get_int(), 1);
BOOST_CHECK_EQUAL(claims[3][T_BID].get_int(), claim1bid);
BOOST_CHECK_EQUAL(claims[3][T_SEQUENCE].get_int(), claim1seq);
BOOST_CHECK_EQUAL(claims[3][T_CLAIMID].get_str(), claimId1.GetHex());
auto getclaimbybid = tableRPC["getclaimbybid"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(claim3bid));
result = getclaimbybid(req);
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 2);
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim3bid);
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim3seq);
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId3.GetHex());
auto getclaimbyseq = tableRPC["getclaimbyseq"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(claim2seq));
result = getclaimbyseq(req);
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 3);
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim2bid);
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim2seq);
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId2.GetHex());
auto getclaimbyid = tableRPC["getclaimbyid"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(claimId1.GetHex()));
result = getclaimbyid(req);
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 1);
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim1bid);
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim1seq);
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId1.GetHex());
// check by partial id (at least 3 chars)
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(claimId3.GetHex().substr(0, 3)));
result = getclaimbyid(req);
BOOST_CHECK_EQUAL(result[T_LASTTAKEOVERHEIGHT].get_int(), height);
BOOST_CHECK_EQUAL(result[T_EFFECTIVEAMOUNT].get_int(), 2);
BOOST_CHECK_EQUAL(result[T_BID].get_int(), claim3bid);
BOOST_CHECK_EQUAL(result[T_SEQUENCE].get_int(), claim3seq);
BOOST_CHECK_EQUAL(result[T_CLAIMID].get_str(), claimId3.GetHex());
auto blockhash = chainActive.Tip()->GetBlockHash();
auto getnameproof = tableRPC["getnameproof"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(blockhash.GetHex()));
req.params.push_back(UniValue(claimId3.GetHex()));
result = getnameproof(req);
auto claimHash = getValueHash(COutPoint(tx2.GetHash(), 1), result[T_LASTTAKEOVERHEIGHT].get_int());
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
// check by partial id (can be even 1 char)
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(blockhash.GetHex()));
req.params.push_back(UniValue(claimId2.GetHex().substr(0, 2)));
result = getnameproof(req);
claimHash = getValueHash(COutPoint(tx2.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
auto getclaimproofbybid = tableRPC["getclaimproofbybid"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(claim1bid));
result = getclaimproofbybid(req);
claimHash = getValueHash(COutPoint(tx1.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
auto getclaimproofbyseq = tableRPC["getclaimproofbyseq"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(name));
req.params.push_back(UniValue(claim4seq));
result = getclaimproofbyseq(req);
claimHash = getValueHash(COutPoint(tx3.GetHash(), 0), result[T_LASTTAKEOVERHEIGHT].get_int());
ValidatePairs(fixture, jsonToPairs(result[T_PAIRS]), claimHash);
auto getchangesinblock = tableRPC["getchangesinblock"]->actor;
req.params = UniValue(UniValue::VARR);
req.params.push_back(UniValue(blockhash.GetHex()));
result = getchangesinblock(req);
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED].size(), 3);
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][0].get_str(), claimId2.GetHex());
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][1].get_str(), claimId3.GetHex());
BOOST_CHECK_EQUAL(result[T_CLAIMSADDEDORUPDATED][2].get_str(), claimId4.GetHex());
BOOST_CHECK_EQUAL(result[T_CLAIMSREMOVED].size(), 0);
BOOST_CHECK_EQUAL(result[T_SUPPORTSADDEDORUPDATED].size(), 0);
BOOST_CHECK_EQUAL(result[T_SUPPORTSREMOVED].size(), 0);
}
BOOST_AUTO_TEST_SUITE_END()