Organize unit tests by type
Signed-off-by: Anthony Fieroni <bvbfan@abv.bg> moved a few more tests out
This commit is contained in:
parent
476eae3e93
commit
8b98a9a4e9
10 changed files with 2805 additions and 2684 deletions
|
@ -66,6 +66,11 @@ BITCOIN_TESTS =\
|
||||||
test/net_tests.cpp \
|
test/net_tests.cpp \
|
||||||
test/claimtriecache_tests.cpp \
|
test/claimtriecache_tests.cpp \
|
||||||
test/claimtriebranching_tests.cpp \
|
test/claimtriebranching_tests.cpp \
|
||||||
|
test/claimtrieexpirationfork_tests.cpp \
|
||||||
|
test/claimtriefixture.cpp \
|
||||||
|
test/claimtriehashfork_tests.cpp \
|
||||||
|
test/claimtrienormalization_tests.cpp \
|
||||||
|
test/claimtrierpc_tests.cpp \
|
||||||
test/nameclaim_tests.cpp \
|
test/nameclaim_tests.cpp \
|
||||||
test/netbase_tests.cpp \
|
test/netbase_tests.cpp \
|
||||||
test/pmt_tests.cpp \
|
test/pmt_tests.cpp \
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,7 @@
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include <boost/scope_exit.hpp>
|
#include <boost/scope_exit.hpp>
|
||||||
|
@ -42,23 +43,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CMutableTransaction BuildTransaction(const uint256& prevhash)
|
|
||||||
{
|
|
||||||
CMutableTransaction tx;
|
|
||||||
tx.nVersion = 1;
|
|
||||||
tx.nLockTime = 0;
|
|
||||||
tx.vin.resize(1);
|
|
||||||
tx.vout.resize(1);
|
|
||||||
tx.vin[0].prevout.hash = prevhash;
|
|
||||||
tx.vin[0].prevout.n = 0;
|
|
||||||
tx.vin[0].scriptSig = CScript();
|
|
||||||
tx.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
|
|
||||||
tx.vout[0].scriptPubKey = CScript();
|
|
||||||
tx.vout[0].nValue = 0;
|
|
||||||
|
|
||||||
return tx;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(claimtriecache_tests, RegTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(claimtriecache_tests, RegTestingSetup)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(merkle_hash_single_test)
|
BOOST_AUTO_TEST_CASE(merkle_hash_single_test)
|
||||||
|
@ -403,4 +387,67 @@ BOOST_AUTO_TEST_CASE(verify_basic_serialization)
|
||||||
BOOST_CHECK_EQUAL(cv.nEffectiveAmount, cv2.nEffectiveAmount);
|
BOOST_CHECK_EQUAL(cv.nEffectiveAmount, cv2.nEffectiveAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize)
|
||||||
|
{
|
||||||
|
CDataStream ss(SER_DISK, 0);
|
||||||
|
|
||||||
|
uint160 hash160;
|
||||||
|
|
||||||
|
CClaimTrieData n1;
|
||||||
|
CClaimTrieData n2;
|
||||||
|
CClaimValue throwaway;
|
||||||
|
|
||||||
|
ss << n1;
|
||||||
|
ss >> n2;
|
||||||
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
|
||||||
|
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
||||||
|
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
||||||
|
|
||||||
|
n1.insertClaim(v1);
|
||||||
|
BOOST_CHECK(n1 != n2);
|
||||||
|
ss << n1;
|
||||||
|
ss >> n2;
|
||||||
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
|
||||||
|
n1.insertClaim(v2);
|
||||||
|
BOOST_CHECK(n1 != n2);
|
||||||
|
ss << n1;
|
||||||
|
ss >> n2;
|
||||||
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
|
||||||
|
n1.removeClaim(v1.outPoint, throwaway);
|
||||||
|
BOOST_CHECK(n1 != n2);
|
||||||
|
ss << n1;
|
||||||
|
ss >> n2;
|
||||||
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
|
||||||
|
n1.removeClaim(v2.outPoint, throwaway);
|
||||||
|
BOOST_CHECK(n1 != n2);
|
||||||
|
ss << n1;
|
||||||
|
ss >> n2;
|
||||||
|
BOOST_CHECK_EQUAL(n1, n2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claimtrienode_remove_invalid_claim)
|
||||||
|
{
|
||||||
|
uint160 hash160;
|
||||||
|
|
||||||
|
CClaimTrieData n1;
|
||||||
|
CClaimTrieData n2;
|
||||||
|
CClaimValue throwaway;
|
||||||
|
|
||||||
|
CClaimValue v1(COutPoint(uint256S("0000000000000000000000000000000000000000000000000000000000000001"), 0), hash160, 50, 0, 100);
|
||||||
|
CClaimValue v2(COutPoint(uint256S("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), 1), hash160, 100, 1, 101);
|
||||||
|
|
||||||
|
n1.insertClaim(v1);
|
||||||
|
n2.insertClaim(v2);
|
||||||
|
|
||||||
|
bool invalidClaim = n2.removeClaim(v1.outPoint, throwaway);
|
||||||
|
BOOST_CHECK_EQUAL(invalidClaim, false);
|
||||||
|
|
||||||
|
invalidClaim = n1.removeClaim(v2.outPoint, throwaway);
|
||||||
|
BOOST_CHECK_EQUAL(invalidClaim, false);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
803
src/test/claimtrieexpirationfork_tests.cpp
Normal file
803
src/test/claimtrieexpirationfork_tests.cpp
Normal file
|
@ -0,0 +1,803 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(claimtrieexpirationfork_tests, RegTestingSetup)
|
||||||
|
|
||||||
|
/*
|
||||||
|
expiration
|
||||||
|
check claims expire and loses claim
|
||||||
|
check claims expire and is not updateable (may be changed in future soft fork)
|
||||||
|
check supports expire and can cause supported bid to lose claim
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE(claimtrie_expire_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setExpirationForkHeight(1000000, 5, 1000000);
|
||||||
|
|
||||||
|
// check claims expire and loses claim
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 2);
|
||||||
|
fixture.IncrementBlocks(fixture.expirationTime());
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx2));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||||
|
fixture.DecrementBlocks(fixture.expirationTime());
|
||||||
|
|
||||||
|
// check claims expire and is not updateable (may be changed in future soft fork)
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test", "one", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx3));
|
||||||
|
fixture.IncrementBlocks(fixture.expirationTime());
|
||||||
|
CMutableTransaction u1 = fixture.MakeUpdate(tx3, "test", "two", ClaimIdHash(tx3.GetHash(), 0), 2);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(fixture.expirationTime());
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx3));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
|
||||||
|
// check supports expire and can cause supported bid to lose claim
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||||
|
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2);
|
||||||
|
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "test", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx4));
|
||||||
|
CMutableTransaction u2 = fixture.MakeUpdate(tx4, "test", "two", ClaimIdHash(tx4.GetHash(),0), 1);
|
||||||
|
CMutableTransaction u3 = fixture.MakeUpdate(tx5, "test", "two", ClaimIdHash(tx5.GetHash(),0), 2);
|
||||||
|
fixture.IncrementBlocks(fixture.expirationTime());
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u3));
|
||||||
|
fixture.DecrementBlocks(fixture.expirationTime());
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx4));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
|
||||||
|
// check updated claims will extend expiration
|
||||||
|
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx6));
|
||||||
|
CMutableTransaction u4 = fixture.MakeUpdate(tx6, "test", "two", ClaimIdHash(tx6.GetHash(), 0), 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||||
|
fixture.IncrementBlocks(fixture.expirationTime()-1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test", u4));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u4));
|
||||||
|
fixture.DecrementBlocks(fixture.expirationTime());
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx6));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
claim expiration for hard fork
|
||||||
|
check claims do not expire post ExpirationForkHeight
|
||||||
|
check supports work post ExpirationForkHeight
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE(hardfork_claim_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setExpirationForkHeight(7, 3, 6);
|
||||||
|
|
||||||
|
// First create a claim and make sure it expires pre-fork
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||||
|
|
||||||
|
// Create a claim 1 block before the fork height that will expire after the fork height
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||||
|
|
||||||
|
// Disable future expirations and fast-forward past the fork height
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||||
|
// make sure decrementing to before the fork height will apppropriately set back the
|
||||||
|
// expiration time to the original expiraiton time
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||||
|
|
||||||
|
// make sure that claim created 1 block before the fork expires as expected
|
||||||
|
// at the extended expiration times
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test2", tx2));
|
||||||
|
fixture.IncrementBlocks(5);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test2", tx2));
|
||||||
|
fixture.DecrementBlocks(5);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test2", tx2));
|
||||||
|
|
||||||
|
// This first claim is still expired since it's pre-fork, even
|
||||||
|
// after fork activation
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test", tx1));
|
||||||
|
|
||||||
|
// This new claim created at the fork height cannot expire at original expiration
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx3));
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
|
||||||
|
// but it expires at the extended expiration, and not a single block below
|
||||||
|
fixture.IncrementBlocks(6);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",tx3));
|
||||||
|
fixture.DecrementBlocks(6);
|
||||||
|
fixture.IncrementBlocks(5);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx3));
|
||||||
|
fixture.DecrementBlocks(5);
|
||||||
|
|
||||||
|
// Ensure that we cannot update the original pre-fork expired claim
|
||||||
|
CMutableTransaction u1 = fixture.MakeUpdate(tx1,"test","two",ClaimIdHash(tx1.GetHash(),0), 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||||
|
|
||||||
|
// Ensure that supports for the expired claim don't support it
|
||||||
|
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(),u1,"test",10);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",u1));
|
||||||
|
|
||||||
|
// Ensure that we can update the new post-fork claim
|
||||||
|
CMutableTransaction u2 = fixture.MakeUpdate(tx3,"test","two",ClaimIdHash(tx3.GetHash(),0), 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",u2));
|
||||||
|
|
||||||
|
// Ensure that supports for the new post-fork claim
|
||||||
|
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),u2,"test",3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",u2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
support expiration for hard fork
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE(hardfork_support_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setExpirationForkHeight(2, 2, 4);
|
||||||
|
|
||||||
|
// Create claim and support it before the fork height
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||||
|
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 2);
|
||||||
|
// this claim will win without the support
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
|
||||||
|
// check that the claim expires as expected at the extended time, as does the support
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||||
|
fixture.DecrementBlocks(2);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test",tx1));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",tx1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
|
||||||
|
// update the claims at fork
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
CMutableTransaction u1 = fixture.MakeUpdate(tx1, "test", "two", ClaimIdHash(tx1.GetHash(),0), 1);
|
||||||
|
CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test", "two", ClaimIdHash(tx2.GetHash(),0), 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(Params().GetConsensus().nExtendedClaimExpirationForkHeight, chainActive.Height());
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||||
|
BOOST_CHECK(!fixture.is_claim_in_queue("test", tx1));
|
||||||
|
BOOST_CHECK(!fixture.is_claim_in_queue("test", tx2));
|
||||||
|
|
||||||
|
// check that the support expires as expected
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", u2));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test",u1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
activation_fall_through and supports_fall_through
|
||||||
|
Tests for where claims/supports in queues would be undone properly in a decrement.
|
||||||
|
See https://github.com/lbryio/lbrycrd/issues/243 for more details
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(activations_fall_through)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.proportionalDelayFactor(), 1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
fixture.Spend(tx1); // this will trigger early activation on tx2 claim
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
fixture.DecrementBlocks(1); //reorg the early activation
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||||
|
fixture.Spend(tx1);
|
||||||
|
fixture.IncrementBlocks(1); // this should not cause tx2 to activate again and crash
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(supports_fall_through)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 3);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 1);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "3", 2);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.proportionalDelayFactor(), 1);
|
||||||
|
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "A", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
fixture.Spend(tx1); // this will trigger early activation
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
fixture.DecrementBlocks(1); // reorg the early activation
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1));
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1)); //tx2 support should not be active
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx1)); //tx2 support should not be active
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2)); //tx2 support should be active now
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
claim/support expiration for hard fork, but with checks for disk procedures
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE(hardfork_disk_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setExpirationForkHeight(7, 3, 6);
|
||||||
|
|
||||||
|
// Check that incrementing to fork height, reseting to disk will get proper expiration time
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||||
|
fixture.IncrementBlocks(7, true);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||||
|
fixture.ReadFromDisk(chainActive.Tip());
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||||
|
|
||||||
|
// Create a claim and support 1 block before the fork height that will expire after the fork height.
|
||||||
|
// Reset to disk, increment past the fork height and make sure we get
|
||||||
|
// proper behavior
|
||||||
|
fixture.DecrementBlocks(2);
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||||
|
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "test", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
fixture.ReadFromDisk(chainActive.Tip());
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(fixture.expirationTime(), 6);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",2));
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test", tx1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test",2));
|
||||||
|
fixture.DecrementBlocks(2);
|
||||||
|
fixture.IncrementBlocks(5);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test", tx1));
|
||||||
|
|
||||||
|
// Create a claim and support before the fork height, reset to disk, update the claim
|
||||||
|
// increment past the fork height and make sure we get proper behavior
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
fixture.setExpirationForkHeight(3, 5, 6);
|
||||||
|
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test2","one",1);
|
||||||
|
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx2,"test2",1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
fixture.ReadFromDisk(chainActive.Tip());
|
||||||
|
CMutableTransaction u2 = fixture.MakeUpdate(tx2, "test2", "two", ClaimIdHash(tx2.GetHash(), 0), 1);
|
||||||
|
// increment to fork
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2",2));
|
||||||
|
// increment to original expiration, should not be expired
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2", 2));
|
||||||
|
fixture.DecrementBlocks(2);
|
||||||
|
// increment to extended expiration, should be expired and not one block before
|
||||||
|
fixture.IncrementBlocks(5);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("test2", u2));
|
||||||
|
fixture.DecrementBlocks(5);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("test2", u2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("test2", 1)); // the support expires one block before
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claim_expiration_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
std::string sName("atest");
|
||||||
|
std::string sValue("testa");
|
||||||
|
|
||||||
|
int nThrowaway;
|
||||||
|
|
||||||
|
// set expiration time to 80 blocks after the block is created
|
||||||
|
fixture.setExpirationForkHeight(1000000, 80, 1000000);
|
||||||
|
|
||||||
|
// create a claim. verify the expiration event has been scheduled.
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 10);
|
||||||
|
COutPoint tx1OutPoint(tx1.GetHash(), 0);
|
||||||
|
fixture.IncrementBlocks(1, true);
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(79); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll forward a bit and then roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||||
|
fixture.IncrementBlocks(20); // 101
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(21); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||||
|
fixture.IncrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||||
|
fixture.DecrementBlocks(2); // 79
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll back some more.
|
||||||
|
fixture.DecrementBlocks(39); // 40
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// spend the claim. verify the expiration event is removed.
|
||||||
|
CMutableTransaction tx2 = fixture.Spend(tx1);
|
||||||
|
fixture.IncrementBlocks(1); // 41
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll back the spend. verify the expiration event is returned.
|
||||||
|
fixture.DecrementBlocks(1); // 40
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// advance until the expiration event occurs. verify the event occurs on time.
|
||||||
|
fixture.IncrementBlocks(40); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// spend the expired claim
|
||||||
|
fixture.CommitTx(tx2);
|
||||||
|
fixture.IncrementBlocks(1); // 82
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// undo the spend. verify everything remains empty.
|
||||||
|
fixture.DecrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again.
|
||||||
|
fixture.DecrementBlocks(1); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// verify the expiration event happens at the right time again
|
||||||
|
fixture.IncrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll back to before the expiration event. verify it gets reinserted and expiration gets scheduled.
|
||||||
|
fixture.DecrementBlocks(1); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// roll all the way back. verify the claim is removed and the expiration event is removed.
|
||||||
|
fixture.DecrementBlocks(); // 0
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// Make sure that when a claim expires, a lesser claim for the same name takes over
|
||||||
|
|
||||||
|
CClaimValue val;
|
||||||
|
|
||||||
|
// create one claim for the name
|
||||||
|
fixture.CommitTx(tx1);
|
||||||
|
fixture.IncrementBlocks(1, true); // 1
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// advance a little while and insert the second claim
|
||||||
|
fixture.IncrementBlocks(4); // 5
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 5);
|
||||||
|
COutPoint tx3OutPoint(tx3.GetHash(), 0);
|
||||||
|
fixture.IncrementBlocks(1); // 6
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
// advance until tx3 is valid, ensure tx1 is winning
|
||||||
|
fixture.IncrementBlocks(4); // 10
|
||||||
|
|
||||||
|
BOOST_CHECK(!fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.haveClaimInQueue(sName, tx3OutPoint, nThrowaway));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 11
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||||
|
uint256 tx1MerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
// roll back to before tx3 is valid
|
||||||
|
fixture.DecrementBlocks(1); // 10
|
||||||
|
|
||||||
|
// advance again until tx is valid
|
||||||
|
fixture.IncrementBlocks(1); // 11
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||||
|
BOOST_CHECK_EQUAL(tx1MerkleHash, fixture.getMerkleHash());
|
||||||
|
|
||||||
|
// advance until the expiration event occurs. verify the expiration event occurs on time.
|
||||||
|
fixture.IncrementBlocks(69, true); // 80
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx3OutPoint);
|
||||||
|
BOOST_CHECK(tx1MerkleHash != fixture.getMerkleHash());
|
||||||
|
|
||||||
|
// spend tx1
|
||||||
|
fixture.CommitTx(tx2);
|
||||||
|
fixture.IncrementBlocks(1); // 82
|
||||||
|
|
||||||
|
// roll back to when tx1 and tx3 are in the trie and tx1 is winning
|
||||||
|
fixture.DecrementBlocks(); // 11
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.expirationQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||||
|
BOOST_CHECK_EQUAL(tx1MerkleHash, fixture.getMerkleHash());
|
||||||
|
|
||||||
|
// roll all the way back
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.expirationQueueEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(expiring_supports_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
std::string sName("atest");
|
||||||
|
std::string sValue1("testa");
|
||||||
|
std::string sValue2("testb");
|
||||||
|
|
||||||
|
CClaimValue val;
|
||||||
|
std::vector<uint256> blocks_to_invalidate;
|
||||||
|
|
||||||
|
fixture.setExpirationForkHeight(1000000, 80, 1000000);
|
||||||
|
|
||||||
|
// to be active bid must have: a higher block number and current block >= (current height - block number) / 32
|
||||||
|
|
||||||
|
// Verify that supports expire
|
||||||
|
|
||||||
|
// Create a 1 LBC claim (tx1)
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1);
|
||||||
|
fixture.IncrementBlocks(1); // 1, expires at 81
|
||||||
|
|
||||||
|
BOOST_CHECK(pcoinsTip->HaveCoin(COutPoint(tx1.GetHash(), 0)));
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
|
||||||
|
// Create a 5 LBC support (tx3)
|
||||||
|
CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName, 5);
|
||||||
|
fixture.IncrementBlocks(1); // 2, expires at 82
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
|
||||||
|
// Advance some, then insert 5 LBC claim (tx2)
|
||||||
|
fixture.IncrementBlocks(19); // 21
|
||||||
|
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5);
|
||||||
|
fixture.IncrementBlocks(1); // 22, activating in (22 - 2) / 1 = 20block (but not then active because support still holds tx1 up)
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
uint256 rootMerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
// Advance until tx2 is valid
|
||||||
|
fixture.IncrementBlocks(20); // 42
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(!fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK_EQUAL(rootMerkleHash, fixture.getMerkleHash());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 43
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx1.GetHash());
|
||||||
|
rootMerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
// Update tx1 so that it expires after tx3 expires
|
||||||
|
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||||
|
CMutableTransaction tx4 = fixture.MakeUpdate(tx1, sName, sValue1, claimId, tx1.vout[0].nValue);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 104
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||||
|
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||||
|
|
||||||
|
// Advance until the support expires
|
||||||
|
fixture.IncrementBlocks(37); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
rootMerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 82
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||||
|
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||||
|
rootMerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
// undo the block, make sure control goes back
|
||||||
|
fixture.DecrementBlocks(1); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||||
|
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||||
|
|
||||||
|
// redo the block, make sure it expires again
|
||||||
|
fixture.IncrementBlocks(1); // 82
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||||
|
rootMerkleHash = fixture.getMerkleHash();
|
||||||
|
|
||||||
|
// roll back some, spend the support, and make sure nothing unexpected
|
||||||
|
// happens at the time the support should have expired
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(19); // 63
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||||
|
BOOST_CHECK(rootMerkleHash != fixture.getMerkleHash());
|
||||||
|
|
||||||
|
fixture.Spend(tx3);
|
||||||
|
fixture.IncrementBlocks(1); // 64
|
||||||
|
|
||||||
|
blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash());
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(20); // 84
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||||
|
|
||||||
|
//undo the spend, and make sure it still expires on time
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(21); // 63
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(18); // 81
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(!fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx4.GetHash());
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1); // 82
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint.hash, tx2.GetHash());
|
||||||
|
|
||||||
|
// roll all the way back
|
||||||
|
fixture.DecrementBlocks(82);
|
||||||
|
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportEmpty());
|
||||||
|
BOOST_CHECK(fixture.supportQueueEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(get_claim_by_id_test_3)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setExpirationForkHeight(1000000, 5, 1000000);
|
||||||
|
const std::string name = "test";
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1);
|
||||||
|
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
CClaimValue claimValue;
|
||||||
|
std::string claimName;
|
||||||
|
BOOST_CHECK(getClaimById(claimId, claimName, &claimValue));
|
||||||
|
BOOST_CHECK_EQUAL(claimName, name);
|
||||||
|
BOOST_CHECK_EQUAL(claimValue.claimId, claimId);
|
||||||
|
// make second claim with activation delay 1
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 2);
|
||||||
|
uint160 claimId2 = ClaimIdHash(tx2.GetHash(), 0);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
// second claim is not activated yet, but can still access by claim id
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(name, tx1));
|
||||||
|
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||||
|
BOOST_CHECK_EQUAL(claimName, name);
|
||||||
|
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
// second claim has activated
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(name, tx2));
|
||||||
|
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||||
|
BOOST_CHECK_EQUAL(claimName, name);
|
||||||
|
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||||
|
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
// second claim has been deactivated via decrement
|
||||||
|
// should still be accesible via claim id
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(name, tx1));
|
||||||
|
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||||
|
BOOST_CHECK_EQUAL(claimName, name);
|
||||||
|
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
// second claim should have been re activated via increment
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(name, tx2));
|
||||||
|
BOOST_CHECK(getClaimById(claimId2, claimName, &claimValue));
|
||||||
|
BOOST_CHECK_EQUAL(claimName, name);
|
||||||
|
BOOST_CHECK_EQUAL(claimValue.claimId, claimId2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
409
src/test/claimtriefixture.cpp
Normal file
409
src/test/claimtriefixture.cpp
Normal file
|
@ -0,0 +1,409 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CMutableTransaction BuildTransaction(const CTransaction& prev, uint32_t prevout, unsigned int numOutputs, int locktime)
|
||||||
|
{
|
||||||
|
CMutableTransaction tx;
|
||||||
|
tx.nVersion = CTransaction::CURRENT_VERSION;
|
||||||
|
tx.vin.resize(1);
|
||||||
|
tx.vout.resize(numOutputs);
|
||||||
|
tx.vin[0].prevout.hash = prev.GetHash();
|
||||||
|
tx.vin[0].prevout.n = prevout;
|
||||||
|
tx.vin[0].scriptSig = CScript();
|
||||||
|
if (locktime != 0) {
|
||||||
|
// Use a relative locktime for validity X blocks in the future
|
||||||
|
tx.nLockTime = chainActive.Height() + locktime;
|
||||||
|
tx.vin[0].nSequence = 0xffffffff - 1;
|
||||||
|
} else {
|
||||||
|
tx.nLockTime = 1 << 31; // Disable BIP68
|
||||||
|
tx.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
|
||||||
|
}
|
||||||
|
CAmount valuePerOutput = prev.vout[prevout].nValue;
|
||||||
|
unsigned int numOutputsCopy = numOutputs;
|
||||||
|
while ((numOutputsCopy = numOutputsCopy >> 1) > 0)
|
||||||
|
valuePerOutput = valuePerOutput >> 1;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < numOutputs; ++i) {
|
||||||
|
tx.vout[i].scriptPubKey = CScript();
|
||||||
|
tx.vout[i].nValue = valuePerOutput;
|
||||||
|
}
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMutableTransaction BuildTransaction(const uint256& prevhash)
|
||||||
|
{
|
||||||
|
CMutableTransaction tx;
|
||||||
|
tx.nVersion = 1;
|
||||||
|
tx.nLockTime = 0;
|
||||||
|
tx.vin.resize(1);
|
||||||
|
tx.vout.resize(1);
|
||||||
|
tx.vin[0].prevout.hash = prevhash;
|
||||||
|
tx.vin[0].prevout.n = 0;
|
||||||
|
tx.vin[0].scriptSig = CScript();
|
||||||
|
tx.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
|
||||||
|
tx.vout[0].scriptPubKey = CScript();
|
||||||
|
tx.vout[0].nValue = 0;
|
||||||
|
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockAssembler AssemblerForTest()
|
||||||
|
{
|
||||||
|
BlockAssembler::Options options;
|
||||||
|
options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
|
||||||
|
options.blockMinFeeRate = CFeeRate(0);
|
||||||
|
return BlockAssembler(Params(), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClaimTrieChainFixture::ClaimTrieChainFixture() : CClaimTrieCache(pclaimTrie),
|
||||||
|
unique_block_counter(0), normalization_original(-1), expirationForkHeight(-1), forkhash_original(-1)
|
||||||
|
{
|
||||||
|
fRequireStandard = false;
|
||||||
|
BOOST_CHECK_EQUAL(nNextHeight, chainActive.Height() + 1);
|
||||||
|
setNormalizationForkHeight(1000000);
|
||||||
|
|
||||||
|
gArgs.ForceSetArg("-limitancestorcount", "1000000");
|
||||||
|
gArgs.ForceSetArg("-limitancestorsize", "1000000");
|
||||||
|
gArgs.ForceSetArg("-limitdescendantcount", "1000000");
|
||||||
|
gArgs.ForceSetArg("-limitdescendantsize", "1000000");
|
||||||
|
|
||||||
|
num_txs_for_next_block = 0;
|
||||||
|
coinbase_txs_used = 0;
|
||||||
|
unique_block_counter = 0;
|
||||||
|
added_unchecked = false;
|
||||||
|
// generate coinbases to spend
|
||||||
|
CreateCoinbases(40, coinbase_txs);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClaimTrieChainFixture::~ClaimTrieChainFixture()
|
||||||
|
{
|
||||||
|
added_unchecked = false;
|
||||||
|
DecrementBlocks(chainActive.Height());
|
||||||
|
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||||
|
if (normalization_original >= 0)
|
||||||
|
consensus.nNormalizedNameForkHeight = normalization_original;
|
||||||
|
|
||||||
|
if (expirationForkHeight >= 0) {
|
||||||
|
consensus.nExtendedClaimExpirationForkHeight = expirationForkHeight;
|
||||||
|
consensus.nExtendedClaimExpirationTime = extendedExpiration;
|
||||||
|
consensus.nOriginalClaimExpirationTime = originalExpiration;
|
||||||
|
}
|
||||||
|
if (forkhash_original >= 0)
|
||||||
|
consensus.nAllClaimsInMerkleForkHeight = forkhash_original;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClaimTrieChainFixture::setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime)
|
||||||
|
{
|
||||||
|
int target = chainActive.Height() + targetMinusCurrent;
|
||||||
|
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||||
|
if (expirationForkHeight < 0) {
|
||||||
|
expirationForkHeight = consensus.nExtendedClaimExpirationForkHeight;
|
||||||
|
originalExpiration = consensus.nOriginalClaimExpirationTime;
|
||||||
|
extendedExpiration = consensus.nExtendedClaimExpirationTime;
|
||||||
|
}
|
||||||
|
consensus.nExtendedClaimExpirationForkHeight = target;
|
||||||
|
consensus.nExtendedClaimExpirationTime = postForkExpirationTime;
|
||||||
|
consensus.nOriginalClaimExpirationTime = preForkExpirationTime;
|
||||||
|
setExpirationTime(targetMinusCurrent >= 0 ? preForkExpirationTime : postForkExpirationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClaimTrieChainFixture::setNormalizationForkHeight(int targetMinusCurrent)
|
||||||
|
{
|
||||||
|
int target = chainActive.Height() + targetMinusCurrent;
|
||||||
|
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||||
|
if (normalization_original < 0)
|
||||||
|
normalization_original = consensus.nNormalizedNameForkHeight;
|
||||||
|
consensus.nNormalizedNameForkHeight = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClaimTrieChainFixture::setHashForkHeight(int targetMinusCurrent)
|
||||||
|
{
|
||||||
|
int target = chainActive.Height() + targetMinusCurrent;
|
||||||
|
auto& consensus = const_cast<Consensus::Params&>(Params().GetConsensus());
|
||||||
|
if (forkhash_original < 0)
|
||||||
|
forkhash_original = consensus.nAllClaimsInMerkleForkHeight;
|
||||||
|
consensus.nAllClaimsInMerkleForkHeight = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate)
|
||||||
|
{
|
||||||
|
CBlock* pblock = &pblocktemplate->block;
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
pblock->nVersion = 5;
|
||||||
|
pblock->hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
pblock->nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing;
|
||||||
|
CMutableTransaction txCoinbase(*pblock->vtx[0]);
|
||||||
|
txCoinbase.vin[0].scriptSig = CScript() << int(chainActive.Height() + 1) << int(++unique_block_counter);
|
||||||
|
txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
|
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||||
|
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||||
|
for (uint32_t i = 0;; ++i) {
|
||||||
|
pblock->nNonce = i;
|
||||||
|
if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus()))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto success = ProcessNewBlock(Params(), std::make_shared<const CBlock>(*pblock), true, nullptr);
|
||||||
|
return success && pblock->GetHash() == chainActive.Tip()->GetBlockHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::CreateCoinbases(unsigned int num_coinbases, std::vector<CTransaction>& coinbases)
|
||||||
|
{
|
||||||
|
std::unique_ptr<CBlockTemplate> pblocktemplate;
|
||||||
|
coinbases.clear();
|
||||||
|
BOOST_CHECK(pblocktemplate = AssemblerForTest().CreateNewBlock(CScript() << OP_TRUE));
|
||||||
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1);
|
||||||
|
for (unsigned int i = 0; i < 100 + num_coinbases; ++i) {
|
||||||
|
BOOST_CHECK(CreateBlock(pblocktemplate));
|
||||||
|
if (coinbases.size() < num_coinbases)
|
||||||
|
coinbases.push_back(std::move(*pblocktemplate->block.vtx[0]));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClaimTrieChainFixture::CommitTx(const CMutableTransaction &tx, bool has_locktime)
|
||||||
|
{
|
||||||
|
num_txs_for_next_block++;
|
||||||
|
if (has_locktime) {
|
||||||
|
added_unchecked = true;
|
||||||
|
TestMemPoolEntryHelper entry;
|
||||||
|
LOCK(mempool.cs);
|
||||||
|
mempool.addUnchecked(tx.GetHash(), entry.Fee(0).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
|
||||||
|
} else {
|
||||||
|
CValidationState state;
|
||||||
|
CAmount txFeeRate = CAmount(0);
|
||||||
|
LOCK(cs_main);
|
||||||
|
BOOST_CHECK_EQUAL(AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr, nullptr, false, txFeeRate, false), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// spend a bid into some non claimtrie related unspent
|
||||||
|
CMutableTransaction ClaimTrieChainFixture::Spend(const CTransaction &prev)
|
||||||
|
{
|
||||||
|
CMutableTransaction tx = BuildTransaction(prev, 0);
|
||||||
|
tx.vout[0].scriptPubKey = CScript() << OP_TRUE;
|
||||||
|
tx.vout[0].nValue = prev.vout[0].nValue;
|
||||||
|
|
||||||
|
CommitTx(tx);
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make claim at the current block
|
||||||
|
CMutableTransaction ClaimTrieChainFixture::MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value, CAmount quantity, int locktime)
|
||||||
|
{
|
||||||
|
uint32_t prevout = prev.vout.size() - 1;
|
||||||
|
while (prevout > 0 && prev.vout[prevout].nValue < quantity)
|
||||||
|
--prevout;
|
||||||
|
CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1, locktime);
|
||||||
|
tx.vout[0].scriptPubKey = ClaimNameScript(name, value);
|
||||||
|
tx.vout[0].nValue = quantity;
|
||||||
|
if (tx.vout.size() > 1) {
|
||||||
|
tx.vout[1].scriptPubKey = CScript() << OP_TRUE;
|
||||||
|
tx.vout[1].nValue = prev.vout[prevout].nValue - quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommitTx(tx, locktime != 0);
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMutableTransaction ClaimTrieChainFixture::MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value)
|
||||||
|
{
|
||||||
|
return MakeClaim(prev, name, value, prev.vout[0].nValue, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make support at the current block
|
||||||
|
CMutableTransaction ClaimTrieChainFixture::MakeSupport(const CTransaction &prev, const CTransaction &claimtx, const std::string& name, CAmount quantity)
|
||||||
|
{
|
||||||
|
uint32_t prevout = prev.vout.size() - 1;
|
||||||
|
while (prevout > 0 && prev.vout[prevout].nValue < quantity)
|
||||||
|
--prevout;
|
||||||
|
CMutableTransaction tx = BuildTransaction(prev, prevout, prev.vout[prevout].nValue > quantity ? 2 : 1);
|
||||||
|
tx.vout[0].scriptPubKey = SupportClaimScript(name, ClaimIdHash(claimtx.GetHash(), 0));
|
||||||
|
tx.vout[0].nValue = quantity;
|
||||||
|
if (tx.vout.size() > 1) {
|
||||||
|
tx.vout[1].scriptPubKey = CScript() << OP_TRUE;
|
||||||
|
tx.vout[1].nValue = prev.vout[prevout].nValue - quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommitTx(tx);
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make update at the current block
|
||||||
|
CMutableTransaction ClaimTrieChainFixture::MakeUpdate(const CTransaction &prev, const std::string& name, const std::string& value, const uint160& claimId, CAmount quantity)
|
||||||
|
{
|
||||||
|
CMutableTransaction tx = BuildTransaction(prev, 0);
|
||||||
|
tx.vout[0].scriptPubKey = UpdateClaimScript(name, claimId, value);
|
||||||
|
tx.vout[0].nValue = quantity;
|
||||||
|
|
||||||
|
CommitTx(tx);
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTransaction ClaimTrieChainFixture::GetCoinbase()
|
||||||
|
{
|
||||||
|
return coinbase_txs.at(coinbase_txs_used++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create i blocks
|
||||||
|
void ClaimTrieChainFixture::IncrementBlocks(int num_blocks, bool mark)
|
||||||
|
{
|
||||||
|
if (mark)
|
||||||
|
marks.push_back(chainActive.Height());
|
||||||
|
|
||||||
|
clear(); // clears the internal cache
|
||||||
|
for (int i = 0; i < num_blocks; ++i) {
|
||||||
|
CScript coinbase_scriptpubkey;
|
||||||
|
coinbase_scriptpubkey << CScriptNum(chainActive.Height());
|
||||||
|
std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest().CreateNewBlock(coinbase_scriptpubkey);
|
||||||
|
BOOST_CHECK(pblocktemplate != nullptr);
|
||||||
|
if (!added_unchecked)
|
||||||
|
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), num_txs_for_next_block + 1);
|
||||||
|
BOOST_CHECK_EQUAL(CreateBlock(pblocktemplate), true);
|
||||||
|
num_txs_for_next_block = 0;
|
||||||
|
nNextHeight = chainActive.Height() + 1;
|
||||||
|
}
|
||||||
|
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// disconnect i blocks from tip
|
||||||
|
void ClaimTrieChainFixture::DecrementBlocks(int num_blocks)
|
||||||
|
{
|
||||||
|
clear(); // clears the internal cache
|
||||||
|
CValidationState state;
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
CBlockIndex* pblockindex = chainActive[chainActive.Height() - num_blocks + 1];
|
||||||
|
BOOST_CHECK_EQUAL(InvalidateBlock(state, Params(), pblockindex), true);
|
||||||
|
}
|
||||||
|
BOOST_CHECK_EQUAL(state.IsValid(), true);
|
||||||
|
BOOST_CHECK_EQUAL(ActivateBestChain(state, Params()), true);
|
||||||
|
mempool.clear();
|
||||||
|
num_txs_for_next_block = 0;
|
||||||
|
nNextHeight = chainActive.Height() + 1;
|
||||||
|
setExpirationTime(Params().GetConsensus().GetExpirationTime(nNextHeight - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrement back to last mark
|
||||||
|
void ClaimTrieChainFixture::DecrementBlocks()
|
||||||
|
{
|
||||||
|
int mark = marks.back();
|
||||||
|
marks.pop_back();
|
||||||
|
DecrementBlocks(chainActive.Height() - mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
bool ClaimTrieChainFixture::keyTypeEmpty(uint8_t keyType)
|
||||||
|
{
|
||||||
|
boost::scoped_ptr<CDBIterator> pcursor(base->db->NewIterator());
|
||||||
|
pcursor->SeekToFirst();
|
||||||
|
|
||||||
|
while (pcursor->Valid()) {
|
||||||
|
std::pair<uint8_t, K> key;
|
||||||
|
if (pcursor->GetKey(key))
|
||||||
|
if (key.first == keyType)
|
||||||
|
return false;
|
||||||
|
pcursor->Next();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::queueEmpty()
|
||||||
|
{
|
||||||
|
for (const auto& claimQueue: claimQueueCache)
|
||||||
|
if (!claimQueue.second.empty())
|
||||||
|
return false;
|
||||||
|
return keyTypeEmpty<int>(CLAIM_QUEUE_ROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::expirationQueueEmpty()
|
||||||
|
{
|
||||||
|
for (const auto& expirationQueue: expirationQueueCache)
|
||||||
|
if (!expirationQueue.second.empty())
|
||||||
|
return false;
|
||||||
|
return keyTypeEmpty<int>(CLAIM_EXP_QUEUE_ROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::supportEmpty()
|
||||||
|
{
|
||||||
|
for (const auto& entry: supportCache)
|
||||||
|
if (!entry.second.empty())
|
||||||
|
return false;
|
||||||
|
return supportCache.empty() && keyTypeEmpty<std::string>(SUPPORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClaimTrieChainFixture::supportQueueEmpty()
|
||||||
|
{
|
||||||
|
for (const auto& support: supportQueueCache)
|
||||||
|
if (!support.second.empty())
|
||||||
|
return false;
|
||||||
|
return keyTypeEmpty<int>(SUPPORT_QUEUE_ROW);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClaimTrieChainFixture::proportionalDelayFactor()
|
||||||
|
{
|
||||||
|
return base->nProportionalDelayFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::test_tools::predicate_result negativeResult(const std::function<void(boost::wrap_stringstream&)>& callback)
|
||||||
|
{
|
||||||
|
boost::test_tools::predicate_result res(false);
|
||||||
|
callback(res.message());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::test_tools::predicate_result negativeResult(const std::string& message)
|
||||||
|
{
|
||||||
|
return negativeResult([&message](boost::wrap_stringstream& stream) {
|
||||||
|
stream << message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// is a claim in queue
|
||||||
|
boost::test_tools::predicate_result ClaimTrieChainFixture::is_claim_in_queue(const std::string& name, const CTransaction &tx)
|
||||||
|
{
|
||||||
|
COutPoint outPoint(tx.GetHash(), 0);
|
||||||
|
int validAtHeight;
|
||||||
|
if (haveClaimInQueue(name, outPoint, validAtHeight))
|
||||||
|
return true;
|
||||||
|
return negativeResult("Is not a claim in queue");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if tx is best claim based on outpoint
|
||||||
|
boost::test_tools::predicate_result ClaimTrieChainFixture::is_best_claim(const std::string& name, const CTransaction &tx)
|
||||||
|
{
|
||||||
|
CClaimValue val;
|
||||||
|
COutPoint outPoint(tx.GetHash(), 0);
|
||||||
|
bool have_claim = haveClaim(name, outPoint);
|
||||||
|
bool have_info = getInfoForName(name, val);
|
||||||
|
if (have_claim && have_info && val.outPoint == outPoint)
|
||||||
|
return true;
|
||||||
|
return negativeResult("Is not best claim");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check effective quantity of best claim
|
||||||
|
boost::test_tools::predicate_result ClaimTrieChainFixture::best_claim_effective_amount_equals(const std::string& name, CAmount amount)
|
||||||
|
{
|
||||||
|
CClaimValue val;
|
||||||
|
bool have_info = getInfoForName(name, val);
|
||||||
|
if (!have_info)
|
||||||
|
return negativeResult("No claim found");
|
||||||
|
CAmount effective_amount = getClaimsForName(name).find(val.claimId).effectiveAmount;
|
||||||
|
if (effective_amount != amount)
|
||||||
|
return negativeResult([amount, effective_amount](boost::wrap_stringstream& stream) {
|
||||||
|
stream << amount << " != " << effective_amount;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ClaimTrieChainFixture::getTotalNamesInTrie() const
|
||||||
|
{
|
||||||
|
return base->getTotalNamesInTrie();
|
||||||
|
}
|
124
src/test/claimtriefixture.h
Normal file
124
src/test/claimtriefixture.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#ifndef _CLAIMTRIEFIXTURE_H_
|
||||||
|
#define _CLAIMTRIEFIXTURE_H_
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <claimtrie.h>
|
||||||
|
#include <coins.h>
|
||||||
|
#include <consensus/merkle.h>
|
||||||
|
#include <consensus/validation.h>
|
||||||
|
#include <miner.h>
|
||||||
|
#include <nameclaim.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
|
#include <pow.h>
|
||||||
|
#include <primitives/transaction.h>
|
||||||
|
#include <random.h>
|
||||||
|
#include <rpc/claimrpchelp.h>
|
||||||
|
#include <rpc/server.h>
|
||||||
|
#include <streams.h>
|
||||||
|
#include <test/test_bitcoin.h>
|
||||||
|
#include <txmempool.h>
|
||||||
|
#include <validation.h>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
extern ::CChainState g_chainstate;
|
||||||
|
extern ::ArgsManager gArgs;
|
||||||
|
extern std::vector<std::string> random_strings(std::size_t count);
|
||||||
|
extern bool getClaimById(const uint160&, std::string&, CClaimValue*);
|
||||||
|
|
||||||
|
CMutableTransaction BuildTransaction(const uint256& prevhash);
|
||||||
|
CMutableTransaction BuildTransaction(const CTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1, int locktime=0);
|
||||||
|
|
||||||
|
BlockAssembler AssemblerForTest();
|
||||||
|
|
||||||
|
// Test Fixtures
|
||||||
|
struct ClaimTrieChainFixture: public CClaimTrieCache
|
||||||
|
{
|
||||||
|
std::vector<CTransaction> coinbase_txs;
|
||||||
|
std::vector<int> marks;
|
||||||
|
int coinbase_txs_used;
|
||||||
|
int unique_block_counter;
|
||||||
|
int normalization_original;
|
||||||
|
unsigned int num_txs_for_next_block;
|
||||||
|
bool added_unchecked;
|
||||||
|
|
||||||
|
int64_t expirationForkHeight;
|
||||||
|
int64_t originalExpiration;
|
||||||
|
int64_t extendedExpiration;
|
||||||
|
int64_t forkhash_original;
|
||||||
|
|
||||||
|
using CClaimTrieCache::getSupportsForName;
|
||||||
|
|
||||||
|
ClaimTrieChainFixture();
|
||||||
|
|
||||||
|
~ClaimTrieChainFixture();
|
||||||
|
|
||||||
|
void setExpirationForkHeight(int targetMinusCurrent, int64_t preForkExpirationTime, int64_t postForkExpirationTime);
|
||||||
|
|
||||||
|
void setNormalizationForkHeight(int targetMinusCurrent);
|
||||||
|
|
||||||
|
void setHashForkHeight(int targetMinusCurrent);
|
||||||
|
|
||||||
|
bool CreateBlock(const std::unique_ptr<CBlockTemplate>& pblocktemplate);
|
||||||
|
|
||||||
|
bool CreateCoinbases(unsigned int num_coinbases, std::vector<CTransaction>& coinbases);
|
||||||
|
|
||||||
|
void CommitTx(const CMutableTransaction &tx, bool has_locktime=false);
|
||||||
|
|
||||||
|
// spend a bid into some non claimtrie related unspent
|
||||||
|
CMutableTransaction Spend(const CTransaction &prev);
|
||||||
|
|
||||||
|
// make claim at the current block
|
||||||
|
CMutableTransaction MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value, CAmount quantity, int locktime=0);
|
||||||
|
|
||||||
|
CMutableTransaction MakeClaim(const CTransaction& prev, const std::string& name, const std::string& value);
|
||||||
|
|
||||||
|
// make support at the current block
|
||||||
|
CMutableTransaction MakeSupport(const CTransaction &prev, const CTransaction &claimtx, const std::string& name, CAmount quantity);
|
||||||
|
|
||||||
|
// make update at the current block
|
||||||
|
CMutableTransaction MakeUpdate(const CTransaction &prev, const std::string& name, const std::string& value, const uint160& claimId, CAmount quantity);
|
||||||
|
|
||||||
|
CTransaction GetCoinbase();
|
||||||
|
|
||||||
|
// create i blocks
|
||||||
|
void IncrementBlocks(int num_blocks, bool mark = false);
|
||||||
|
|
||||||
|
// disconnect i blocks from tip
|
||||||
|
void DecrementBlocks(int num_blocks);
|
||||||
|
|
||||||
|
// decrement back to last mark
|
||||||
|
void DecrementBlocks();
|
||||||
|
|
||||||
|
bool queueEmpty();
|
||||||
|
|
||||||
|
bool expirationQueueEmpty();
|
||||||
|
|
||||||
|
bool supportEmpty();
|
||||||
|
|
||||||
|
bool supportQueueEmpty();
|
||||||
|
|
||||||
|
int proportionalDelayFactor();
|
||||||
|
|
||||||
|
// is a claim in queue
|
||||||
|
boost::test_tools::predicate_result is_claim_in_queue(const std::string& name, const CTransaction &tx);
|
||||||
|
|
||||||
|
// check if tx is best claim based on outpoint
|
||||||
|
boost::test_tools::predicate_result is_best_claim(const std::string& name, const CTransaction &tx);
|
||||||
|
|
||||||
|
// check effective quantity of best claim
|
||||||
|
boost::test_tools::predicate_result best_claim_effective_amount_equals(const std::string& name, CAmount amount);
|
||||||
|
|
||||||
|
std::size_t getTotalNamesInTrie() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename K>
|
||||||
|
bool keyTypeEmpty(uint8_t keyType);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _CLAIMTRIEFIXTURE_H_
|
390
src/test/claimtriehashfork_tests.cpp
Normal file
390
src/test/claimtriehashfork_tests.cpp
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
claimHash = Hash(claimHash.begin(), claimHash.end(), pair.second.begin(), pair.second.end());
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(cache.getMerkleHash(), claimHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(claimtriehashfork_tests, RegTestingSetup)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_rollback_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setHashForkHeight(5);
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
uint256 currentRoot = fixture.getMerkleHash();
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash());
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK_NE(currentRoot, fixture.getMerkleHash());
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
BOOST_CHECK_EQUAL(currentRoot, fixture.getMerkleHash());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_single_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setHashForkHeight(2);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "test", "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
COutPoint outPoint(tx1.GetHash(), 0);
|
||||||
|
uint160 claimId = ClaimIdHash(tx1.GetHash(), 0);
|
||||||
|
|
||||||
|
CClaimTrieProof proof;
|
||||||
|
BOOST_CHECK(fixture.getProofForName("test", proof, [&claimId](const CClaimValue& claim) {
|
||||||
|
return claim.claimId == claimId;
|
||||||
|
}));
|
||||||
|
BOOST_CHECK(proof.hasValue);
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, outPoint);
|
||||||
|
auto claimHash = getValueHash(outPoint, proof.nHeightOfLastTakeover);
|
||||||
|
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_triple_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setHashForkHeight(2);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
|
||||||
|
std::string names[] = {"test", "tester", "tester2"};
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "one", 1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "two", 2);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "thr", 3);
|
||||||
|
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "for", 4);
|
||||||
|
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), names[0], "fiv", 5);
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), names[1], "two", 2);
|
||||||
|
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), names[1], "thr", 3);
|
||||||
|
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), names[2], "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
for (const auto& name : names) {
|
||||||
|
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||||
|
CClaimTrieProof proof;
|
||||||
|
auto& claim = claimSupports.claim;
|
||||||
|
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||||
|
return claim.claimId == value.claimId;
|
||||||
|
}));
|
||||||
|
BOOST_CHECK(proof.hasValue);
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||||
|
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||||
|
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hash_includes_all_claims_branched_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setHashForkHeight(2);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
|
||||||
|
std::string names[] = {"test", "toast", "tot", "top", "toa", "toad"};
|
||||||
|
for (const auto& name : names)
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), name, "one", 1);
|
||||||
|
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "two", 2);
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "tre", 3);
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "qua", 4);
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), "toa", "cin", 5);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
for (const auto& name : names) {
|
||||||
|
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||||
|
CClaimTrieProof proof;
|
||||||
|
auto& claim = claimSupports.claim;
|
||||||
|
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||||
|
return claim.claimId == value.claimId;
|
||||||
|
}));
|
||||||
|
BOOST_CHECK(proof.hasValue);
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||||
|
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||||
|
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hash_claims_children_fuzzer_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setHashForkHeight(2);
|
||||||
|
fixture.IncrementBlocks(4);
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
auto names = random_strings(300);
|
||||||
|
auto lastTx = MakeTransactionRef(fixture.GetCoinbase());
|
||||||
|
for (const auto& name : names) {
|
||||||
|
auto tx = fixture.MakeClaim(*lastTx, name, "one", 1);
|
||||||
|
lastTx = MakeTransactionRef(std::move(tx));
|
||||||
|
if (++i % 5 == 0)
|
||||||
|
for (std::size_t j = 0; j < (i / 5); ++j) {
|
||||||
|
auto tx = fixture.MakeClaim(*lastTx, name, "one", 1);
|
||||||
|
lastTx = MakeTransactionRef(std::move(tx));
|
||||||
|
}
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& name : names) {
|
||||||
|
for (auto& claimSupports : fixture.getClaimsForName(name).claimsNsupports) {
|
||||||
|
CClaimTrieProof proof;
|
||||||
|
auto& claim = claimSupports.claim;
|
||||||
|
BOOST_CHECK(fixture.getProofForName(name, proof, [&claim](const CClaimValue& value) {
|
||||||
|
return claim.claimId == value.claimId;
|
||||||
|
}));
|
||||||
|
BOOST_CHECK(proof.hasValue);
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, claim.outPoint);
|
||||||
|
uint256 claimHash = getValueHash(claim.outPoint, proof.nHeightOfLastTakeover);
|
||||||
|
ValidatePairs(fixture, proof.pairs, claimHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::string& name)
|
||||||
|
{
|
||||||
|
uint256 previousComputedHash;
|
||||||
|
std::string computedReverseName;
|
||||||
|
bool verifiedValue = false;
|
||||||
|
|
||||||
|
for (auto itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) {
|
||||||
|
bool foundChildInChain = false;
|
||||||
|
std::vector<unsigned char> vchToHash;
|
||||||
|
for (auto itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) {
|
||||||
|
vchToHash.push_back(itChildren->first);
|
||||||
|
uint256 childHash;
|
||||||
|
if (itChildren->second.IsNull()) {
|
||||||
|
if (previousComputedHash.IsNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (foundChildInChain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foundChildInChain = true;
|
||||||
|
computedReverseName += itChildren->first;
|
||||||
|
childHash = previousComputedHash;
|
||||||
|
} else {
|
||||||
|
childHash = itChildren->second;
|
||||||
|
}
|
||||||
|
vchToHash.insert(vchToHash.end(), childHash.begin(), childHash.end());
|
||||||
|
}
|
||||||
|
if (itNodes != proof.nodes.rbegin() && !foundChildInChain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (itNodes->hasValue) {
|
||||||
|
uint256 valHash;
|
||||||
|
if (itNodes->valHash.IsNull()) {
|
||||||
|
if (itNodes != proof.nodes.rbegin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!proof.hasValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
valHash = getValueHash(proof.outPoint,
|
||||||
|
proof.nHeightOfLastTakeover);
|
||||||
|
|
||||||
|
verifiedValue = true;
|
||||||
|
} else {
|
||||||
|
valHash = itNodes->valHash;
|
||||||
|
}
|
||||||
|
vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end());
|
||||||
|
} else if (proof.hasValue && itNodes == proof.nodes.rbegin()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CHash256 hasher;
|
||||||
|
std::vector<unsigned char> vchHash(hasher.OUTPUT_SIZE);
|
||||||
|
hasher.Write(vchToHash.data(), vchToHash.size());
|
||||||
|
hasher.Finalize(&(vchHash[0]));
|
||||||
|
uint256 calculatedHash(vchHash);
|
||||||
|
previousComputedHash = calculatedHash;
|
||||||
|
}
|
||||||
|
if (previousComputedHash != rootHash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (proof.hasValue && !verifiedValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::string::reverse_iterator itComputedName = computedReverseName.rbegin();
|
||||||
|
std::string::const_iterator itName = name.begin();
|
||||||
|
for (; itName != name.end() && itComputedName != computedReverseName.rend(); ++itName, ++itComputedName) {
|
||||||
|
if (*itName != *itComputedName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (!proof.hasValue || itName == name.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(value_proof_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
std::string sName1("a");
|
||||||
|
std::string sValue1("testa");
|
||||||
|
|
||||||
|
std::string sName2("abc");
|
||||||
|
std::string sValue2("testabc");
|
||||||
|
|
||||||
|
std::string sName3("abd");
|
||||||
|
std::string sValue3("testabd");
|
||||||
|
|
||||||
|
std::string sName4("zyx");
|
||||||
|
std::string sValue4("testzyx");
|
||||||
|
|
||||||
|
std::string sName5("zyxa");
|
||||||
|
std::string sName6("omg");
|
||||||
|
std::string sName7("");
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1);
|
||||||
|
COutPoint tx1OutPoint(tx1.GetHash(), 0);
|
||||||
|
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2);
|
||||||
|
COutPoint tx2OutPoint(tx2.GetHash(), 0);
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), sName3, sValue3);
|
||||||
|
COutPoint tx3OutPoint(tx3.GetHash(), 0);
|
||||||
|
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), sName4, sValue4);
|
||||||
|
COutPoint tx4OutPoint(tx4.GetHash(), 0);
|
||||||
|
CClaimValue val;
|
||||||
|
|
||||||
|
// create a claim. verify the expiration event has been scheduled.
|
||||||
|
fixture.IncrementBlocks(5, true);
|
||||||
|
|
||||||
|
BOOST_CHECK(!pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName1, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx1OutPoint);
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName2, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx2OutPoint);
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName3, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx3OutPoint);
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName4, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx4OutPoint);
|
||||||
|
|
||||||
|
CClaimTrieProof proof;
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName1, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx1OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName2, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx2OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName3, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx3OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName4, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx4OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName5, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||||
|
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName6, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||||
|
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName7, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||||
|
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||||
|
|
||||||
|
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), sName7, sValue4);
|
||||||
|
COutPoint tx5OutPoint(tx5.GetHash(), 0);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(sName7, val));
|
||||||
|
BOOST_CHECK_EQUAL(val.outPoint, tx5OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName1, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx1OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName2, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx2OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName3, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx3OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName4, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx4OutPoint);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName5, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5));
|
||||||
|
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName6, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6));
|
||||||
|
BOOST_CHECK_EQUAL(proof.hasValue, false);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.getProofForName(sName7, proof));
|
||||||
|
BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7));
|
||||||
|
BOOST_CHECK_EQUAL(proof.outPoint, tx5OutPoint);
|
||||||
|
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
BOOST_CHECK(pclaimTrie->empty());
|
||||||
|
BOOST_CHECK(fixture.queueEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that blocks with bogus calimtrie hash is rejected
|
||||||
|
BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName("test");
|
||||||
|
std::string sValue1("test");
|
||||||
|
|
||||||
|
int orig_chain_height = chainActive.Height();
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1);
|
||||||
|
|
||||||
|
std::unique_ptr<CBlockTemplate> pblockTemp;
|
||||||
|
BOOST_CHECK(pblockTemp = AssemblerForTest().CreateNewBlock(tx1.vout[0].scriptPubKey));
|
||||||
|
pblockTemp->block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
|
||||||
|
pblockTemp->block.nVersion = 5;
|
||||||
|
pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing;
|
||||||
|
CMutableTransaction txCoinbase(*pblockTemp->block.vtx[0]);
|
||||||
|
txCoinbase.vin[0].scriptSig = CScript() << int(chainActive.Height() + 1) << 1;
|
||||||
|
txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
|
pblockTemp->block.vtx[0] = MakeTransactionRef(std::move(txCoinbase));
|
||||||
|
pblockTemp->block.hashMerkleRoot = BlockMerkleRoot(pblockTemp->block);
|
||||||
|
//create bogus hash
|
||||||
|
|
||||||
|
uint256 bogusHashClaimTrie;
|
||||||
|
bogusHashClaimTrie.SetHex("aaa");
|
||||||
|
pblockTemp->block.hashClaimTrie = bogusHashClaimTrie;
|
||||||
|
|
||||||
|
for (uint32_t i = 0;; ++i) {
|
||||||
|
pblockTemp->block.nNonce = i;
|
||||||
|
if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool success = ProcessNewBlock(Params(), std::make_shared<const CBlock>(pblockTemp->block), true, nullptr);
|
||||||
|
// will process , but will not be connected
|
||||||
|
BOOST_CHECK(success);
|
||||||
|
BOOST_CHECK(pblockTemp->block.GetHash() != chainActive.Tip()->GetBlockHash());
|
||||||
|
BOOST_CHECK_EQUAL(orig_chain_height, chainActive.Height());
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
495
src/test/claimtrienormalization_tests.cpp
Normal file
495
src/test/claimtrienormalization_tests.cpp
Normal file
|
@ -0,0 +1,495 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(claimtrienormalization_tests, RegTestingSetup)
|
||||||
|
|
||||||
|
/*
|
||||||
|
normalization
|
||||||
|
test normalization function indpendent from rest of the code
|
||||||
|
*/
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_only)
|
||||||
|
{
|
||||||
|
CClaimTrieCache ccache(pclaimTrie);
|
||||||
|
|
||||||
|
// basic ASCII casing tests
|
||||||
|
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TESt", true));
|
||||||
|
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("tesT", true));
|
||||||
|
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("TesT", true));
|
||||||
|
BOOST_CHECK_EQUAL("test", ccache.normalizeClaimName("test", true));
|
||||||
|
BOOST_CHECK_EQUAL("test this", ccache.normalizeClaimName("Test This", true));
|
||||||
|
|
||||||
|
// test invalid utf8 bytes are returned as is
|
||||||
|
BOOST_CHECK_EQUAL("\xFF", ccache.normalizeClaimName("\xFF", true));
|
||||||
|
BOOST_CHECK_EQUAL("\xC3\x28", ccache.normalizeClaimName("\xC3\x28", true));
|
||||||
|
|
||||||
|
// ohm sign unicode code point \x2126 should be transformed to equivalent
|
||||||
|
// unicode code point \x03C9 , greek small letter omega
|
||||||
|
BOOST_CHECK_EQUAL("\xCF\x89", ccache.normalizeClaimName("\xE2\x84\xA6", true));
|
||||||
|
|
||||||
|
// cyrillic capital ef code point \x0424 should be transformed to lower case
|
||||||
|
// \x0444
|
||||||
|
BOOST_CHECK_EQUAL("\xD1\x84", ccache.normalizeClaimName("\xD0\xA4", true));
|
||||||
|
|
||||||
|
// armenian capital ben code point \x0532 should be transformed to lower case
|
||||||
|
// \x0562
|
||||||
|
BOOST_CHECK_EQUAL("\xD5\xA2", ccache.normalizeClaimName("\xD4\xB2", true));
|
||||||
|
|
||||||
|
// japanese pbu code point \x3076 should be transformed by NFD decomposition
|
||||||
|
// into \x3075 and \x3099
|
||||||
|
BOOST_CHECK_EQUAL("\xE3\x81\xB5\xE3\x82\x99",
|
||||||
|
ccache.normalizeClaimName("\xE3\x81\xB6", true));
|
||||||
|
|
||||||
|
// hangul ggwalg unicode code point \xAF51 should be transformed by NFD
|
||||||
|
// decomposition into unicode code points \x1101 \x116A \x11B0
|
||||||
|
// source: http://unicode.org/L2/L2009/09052-tr47.html
|
||||||
|
BOOST_CHECK_EQUAL("\xE1\x84\x81\xE1\x85\xAA\xE1\x86\xB0",
|
||||||
|
ccache.normalizeClaimName("\xEA\xBD\x91", true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
normalization
|
||||||
|
check claim name normalization before the fork
|
||||||
|
check claim name normalization after the fork
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_CASE(claimtriebranching_normalization)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
// check claim names are not normalized
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "normalizeTest", "one", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.getTotalNamesInTrie() == 0);
|
||||||
|
fixture.CommitTx(tx1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||||
|
|
||||||
|
CMutableTransaction tx2a = fixture.MakeClaim(fixture.GetCoinbase(), "Normalizetest", "one_a", 2);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeUpdate(tx2a, "Normalizetest", "one", ClaimIdHash(tx2a.GetHash(), 0), 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||||
|
|
||||||
|
// Activate the fork (which rebuilds the existing claimtrie and
|
||||||
|
// cache), flattening all previously existing name clashes due to
|
||||||
|
// the normalization
|
||||||
|
fixture.setNormalizationForkHeight(2);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1, true);
|
||||||
|
|
||||||
|
// Post-fork, tx1 (the previous winning claim) assumes all name
|
||||||
|
// variants of what it originally was ...
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 3));
|
||||||
|
|
||||||
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(!pclaimTrie->find("normalizeTest", data));
|
||||||
|
|
||||||
|
// Check equivalence of normalized claim names
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "NORMALIZETEST", "one", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("normalizetest", tx3));
|
||||||
|
|
||||||
|
CMutableTransaction s1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "NoRmAlIzEtEsT", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
// Ensure that supports work for normalized claim names
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // effective amount is 5
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("normalizetest", 5));
|
||||||
|
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "foo", "bar", 1);
|
||||||
|
CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(), tx4, "Foo", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("foo", tx4));
|
||||||
|
|
||||||
|
CMutableTransaction u1 = fixture.MakeUpdate(tx4, "foo", "baz", ClaimIdHash(tx4.GetHash(), 0), 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("foo", u1));
|
||||||
|
|
||||||
|
CMutableTransaction u2 = fixture.MakeUpdate(tx1, "nOrmalIzEtEst", "two", ClaimIdHash(tx1.GetHash(), 0), 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", u2));
|
||||||
|
|
||||||
|
// Add another set of unicode claims that will collapse after the fork
|
||||||
|
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "Ame\u0301lie", "amelie", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
CClaimValue nval1;
|
||||||
|
fixture.getInfoForName("amélie", nval1);
|
||||||
|
BOOST_CHECK(nval1.claimId == ClaimIdHash(tx5.GetHash(), 0));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("amélie", 2));
|
||||||
|
|
||||||
|
// Check equivalence of normalized claim names
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("amélie", tx5));
|
||||||
|
|
||||||
|
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "あてはまる", "jn1", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("あてはまる", tx7));
|
||||||
|
|
||||||
|
CMutableTransaction tx8 = fixture.MakeClaim(fixture.GetCoinbase(), "AÑEJO", "es1", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("añejo", tx8));
|
||||||
|
|
||||||
|
// Rewind to 1 block before the fork and be sure that the fork is no longer active
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
|
||||||
|
// Now check that our old (non-normalized) claims are 'alive' again
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizeTest", tx1));
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("Normalizetest", tx1)); // no longer equivalent
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||||
|
|
||||||
|
// Create new claim
|
||||||
|
CMutableTransaction tx9 = fixture.MakeClaim(fixture.GetCoinbase(), "blah", "blah", 1);
|
||||||
|
std::string invalidUtf8("\xFF\xFF");
|
||||||
|
CMutableTransaction tx10 = fixture.MakeClaim(fixture.GetCoinbase(), invalidUtf8, "blah", 1); // invalid UTF8
|
||||||
|
|
||||||
|
// Roll forward to fork height again and check again that we're normalized
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(invalidUtf8, tx10));
|
||||||
|
|
||||||
|
// Rewind to 1 block before the fork and be sure that the fork is
|
||||||
|
// no longer active
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("Normalizetest", tx2));
|
||||||
|
|
||||||
|
// Roll forward to fork height again and check again that we're normalized
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(chainActive.Height() == Params().GetConsensus().nNormalizedNameForkHeight);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("normalizetest", tx1)); // collapsed tx2
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claimtriecache_normalization)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
std::string name = "Ame\u0301lie";
|
||||||
|
|
||||||
|
std::string name_upper = "Amélie";
|
||||||
|
std::string name_normd = "amélie"; // this accented e is not actually the same as the one above; this has been "normalized"
|
||||||
|
|
||||||
|
BOOST_CHECK(name != name_upper);
|
||||||
|
|
||||||
|
// Add another set of unicode claims that will collapse after the fork
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), name, "amilie", 2);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), name_upper, "amelie", 2);
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), "amelie1", "amelie", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
CClaimValue lookupClaim;
|
||||||
|
std::string lookupName;
|
||||||
|
BOOST_CHECK(getClaimById(ClaimIdHash(tx2.GetHash(), 0), lookupName, &lookupClaim));
|
||||||
|
CClaimValue nval1;
|
||||||
|
BOOST_CHECK(fixture.getInfoForName("amelie1", nval1));
|
||||||
|
// amélie is not found cause normalization still not appear
|
||||||
|
BOOST_CHECK(!fixture.getInfoForName(name_normd, nval1));
|
||||||
|
|
||||||
|
// Activate the fork (which rebuilds the existing claimtrie and
|
||||||
|
// cache), flattening all previously existing name clashes due to
|
||||||
|
// the normalization
|
||||||
|
fixture.setNormalizationForkHeight(1);
|
||||||
|
int currentHeight = chainActive.Height();
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
// Ok normalization fix the name problem
|
||||||
|
BOOST_CHECK(fixture.getInfoForName(name_normd, nval1));
|
||||||
|
BOOST_CHECK(nval1.nHeight == currentHeight);
|
||||||
|
BOOST_CHECK(lookupClaim == nval1);
|
||||||
|
|
||||||
|
CCoinsViewCache coins(pcoinsTip.get());
|
||||||
|
CClaimTrieCache trieCache(pclaimTrie);
|
||||||
|
CBlockIndex* pindex = chainActive.Tip();
|
||||||
|
CBlock block;
|
||||||
|
int amelieValidHeight;
|
||||||
|
BOOST_CHECK(trieCache.shouldNormalize());
|
||||||
|
BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus()));
|
||||||
|
BOOST_CHECK(g_chainstate.DisconnectBlock(block, pindex, coins, trieCache) == DisconnectResult::DISCONNECT_OK);
|
||||||
|
BOOST_CHECK(!trieCache.shouldNormalize());
|
||||||
|
BOOST_CHECK(!trieCache.spendClaim(name_normd, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
||||||
|
BOOST_CHECK(trieCache.spendClaim(name_upper, COutPoint(tx2.GetHash(), 0), currentHeight, amelieValidHeight));
|
||||||
|
|
||||||
|
CClaimTrieData data;
|
||||||
|
BOOST_CHECK(!pclaimTrie->find(name, data));
|
||||||
|
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||||
|
BOOST_CHECK(trieCache.addClaim(name, COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), CAmount(2), currentHeight + 1));
|
||||||
|
BOOST_CHECK(trieCache.getInfoForName(name, nval1));
|
||||||
|
insertUndoType insertUndo;
|
||||||
|
claimQueueRowType expireUndo;
|
||||||
|
insertUndoType insertSupportUndo;
|
||||||
|
supportQueueRowType expireSupportUndo;
|
||||||
|
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
|
||||||
|
BOOST_CHECK(trieCache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
||||||
|
BOOST_CHECK(trieCache.shouldNormalize());
|
||||||
|
|
||||||
|
CClaimTrieDataNode node;
|
||||||
|
BOOST_CHECK(!pclaimTrie->find(name, node));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(undo_normalization_does_not_kill_claim_order)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(5);
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
fixture.IncrementBlocks(3, true);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalized_activations_fall_through)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(5);
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.proportionalDelayFactor() == 1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 4);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "2", 3);
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "ab", "2", 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("AB", tx1));
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("ab", tx2));
|
||||||
|
BOOST_CHECK(fixture.getClaimsForName("ab").claimsNsupports.size() == 4U);
|
||||||
|
fixture.DecrementBlocks(3);
|
||||||
|
fixture.Spend(tx1);
|
||||||
|
fixture.Spend(tx2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("ab", tx3));
|
||||||
|
BOOST_CHECK(fixture.getClaimsForName("ab").claimsNsupports.size() == 2U);
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("AB", tx1));
|
||||||
|
fixture.Spend(tx1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("ab", tx2));
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; ++i) {
|
||||||
|
fixture.IncrementBlocks(i, true); // well into normalized teritory
|
||||||
|
CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), "CD", "a", 1 + i);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(), "Cd", "b", 2 + i);
|
||||||
|
CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), "cD", "c", 3 + i);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("cd", tx5));
|
||||||
|
fixture.Spend(tx5);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("cd", tx7));
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_removal_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(2);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "AB", "1", 1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "Ab", "2", 2);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "aB", "3", 3);
|
||||||
|
CMutableTransaction sx1 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, "AB", 1);
|
||||||
|
CMutableTransaction sx2 = fixture.MakeSupport(fixture.GetCoinbase(), tx2, "Ab", 1);
|
||||||
|
|
||||||
|
CClaimTrieCache cache(pclaimTrie);
|
||||||
|
int height = chainActive.Height() + 1;
|
||||||
|
cache.addClaim("AB", COutPoint(tx1.GetHash(), 0), ClaimIdHash(tx1.GetHash(), 0), 1, height);
|
||||||
|
cache.addClaim("Ab", COutPoint(tx2.GetHash(), 0), ClaimIdHash(tx2.GetHash(), 0), 2, height);
|
||||||
|
cache.addClaim("aB", COutPoint(tx3.GetHash(), 0), ClaimIdHash(tx3.GetHash(), 0), 3, height);
|
||||||
|
cache.addSupport("AB", COutPoint(sx1.GetHash(), 0), 1, ClaimIdHash(tx1.GetHash(), 0), height);
|
||||||
|
cache.addSupport("Ab", COutPoint(sx2.GetHash(), 0), 1, ClaimIdHash(tx2.GetHash(), 0), height);
|
||||||
|
insertUndoType insertUndo;
|
||||||
|
claimQueueRowType expireUndo;
|
||||||
|
insertUndoType insertSupportUndo;
|
||||||
|
supportQueueRowType expireSupportUndo;
|
||||||
|
std::vector<std::pair<std::string, int> > takeoverHeightUndo;
|
||||||
|
BOOST_CHECK(cache.incrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo, takeoverHeightUndo));
|
||||||
|
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 3U);
|
||||||
|
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[0].supports.size() == 1U);
|
||||||
|
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[1].supports.size() == 0U);
|
||||||
|
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports[2].supports.size() == 1U);
|
||||||
|
BOOST_CHECK(cache.decrementBlock(insertUndo, expireUndo, insertSupportUndo, expireSupportUndo));
|
||||||
|
BOOST_CHECK(cache.finalizeDecrement(takeoverHeightUndo));
|
||||||
|
BOOST_CHECK(cache.undoAddSupport("AB", COutPoint(sx1.GetHash(), 0), height));
|
||||||
|
BOOST_CHECK(cache.undoAddSupport("Ab", COutPoint(sx2.GetHash(), 0), height));
|
||||||
|
BOOST_CHECK(cache.undoAddClaim("AB", COutPoint(tx1.GetHash(), 0), height));
|
||||||
|
BOOST_CHECK(cache.undoAddClaim("Ab", COutPoint(tx2.GetHash(), 0), height));
|
||||||
|
BOOST_CHECK(cache.undoAddClaim("aB", COutPoint(tx3.GetHash(), 0), height));
|
||||||
|
BOOST_CHECK(cache.getClaimsForName("ab").claimsNsupports.size() == 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_supports)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(3);
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 3));
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 4));
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 5));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 4));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 3));
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
fixture.IncrementBlocks(5);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("a", 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_does_not_fail_on_spend)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(2);
|
||||||
|
|
||||||
|
std::string sName1("testN");
|
||||||
|
std::string sName2("testn");
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "1", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(sName1, tx1));
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, "2", 2);
|
||||||
|
CMutableTransaction tx1s = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 2);
|
||||||
|
fixture.IncrementBlocks(2, true);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(sName2, tx1));
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
|
||||||
|
CMutableTransaction tx3s = fixture.Spend(tx1s);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(sName2, tx2));
|
||||||
|
fixture.DecrementBlocks();
|
||||||
|
BOOST_CHECK(fixture.is_best_claim(sName1, tx1));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_sort_order)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
fixture.setNormalizationForkHeight(2);
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "2", 2);
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "a", "3", 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.is_best_claim("A", tx2));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||||
|
BOOST_CHECK(fixture.getClaimsForName("a").claimsNsupports.size() == 3U);
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("A", tx2));
|
||||||
|
BOOST_CHECK(fixture.is_best_claim("a", tx3));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(normalization_does_not_kill_expirations)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
auto& consensus = Params().GetConsensus();
|
||||||
|
fixture.setExpirationForkHeight(consensus.nExtendedClaimExpirationForkHeight, 3, consensus.nExtendedClaimExpirationTime);
|
||||||
|
fixture.setNormalizationForkHeight(4);
|
||||||
|
// need to see that claims expiring on the frame when we normalize aren't kept
|
||||||
|
// need to see that supports expiring on the frame when we normalize aren't kept
|
||||||
|
// need to see that claims & supports carried through the normalization fork do expire
|
||||||
|
// and that they come back correctly when we roll backwards
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), "A", "1", 1);
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, "A", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), "B", "1", 1);
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx2, "B", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(), "C", "1", 1);
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx3, "C", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("C", 2));
|
||||||
|
|
||||||
|
CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(), "D", "1", 1);
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx4, "D", 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(2);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.DecrementBlocks(1);
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("A", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("B", 2));
|
||||||
|
BOOST_CHECK(fixture.best_claim_effective_amount_equals("C", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2));
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("a", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("b", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("c", 2));
|
||||||
|
BOOST_CHECK(!fixture.best_claim_effective_amount_equals("d", 2)); // (not re-added)
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
407
src/test/claimtrierpc_tests.cpp
Normal file
407
src/test/claimtrierpc_tests.cpp
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
// Copyright (c) 2015-2019 The LBRY Foundation
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
extern void ValidatePairs(CClaimTrieCache& cache, const std::vector<std::pair<bool, uint256>>& pairs, uint256 claimHash);
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(claimtrierpc_tests, RegTestingSetup)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(getnamesintrie_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("test");
|
||||||
|
std::string sValue1("test");
|
||||||
|
|
||||||
|
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||||
|
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 42);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
rpcfn_type getnamesintrie = tableRPC["getnamesintrie"]->actor;
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
|
||||||
|
UniValue results = getnamesintrie(req);
|
||||||
|
BOOST_CHECK_EQUAL(results.size(), 1U);
|
||||||
|
|
||||||
|
req.params.push_back(blockHash.GetHex());
|
||||||
|
|
||||||
|
results = getnamesintrie(req);
|
||||||
|
BOOST_CHECK_EQUAL(results.size(), 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(getvalueforname_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("testN");
|
||||||
|
std::string sValue1("testV");
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||||
|
|
||||||
|
fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName1, 3);
|
||||||
|
fixture.IncrementBlocks(10);
|
||||||
|
|
||||||
|
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
req.params.push_back(UniValue(sName1));
|
||||||
|
|
||||||
|
UniValue results = getvalueforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_VALUE].get_str(), HexStr(sValue1));
|
||||||
|
BOOST_CHECK_EQUAL(results[T_AMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_EFFECTIVEAMOUNT].get_int(), 5);
|
||||||
|
|
||||||
|
req.params.push_back(blockHash.GetHex());
|
||||||
|
|
||||||
|
results = getvalueforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_AMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(getclaimsforname_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("testN");
|
||||||
|
std::string sValue1("test1");
|
||||||
|
std::string sValue2("test2");
|
||||||
|
|
||||||
|
int height = chainActive.Height();
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||||
|
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
req.params.push_back(UniValue(sName1));
|
||||||
|
|
||||||
|
UniValue results = getclaimsforname(req);
|
||||||
|
UniValue claims = results[T_CLAIMS];
|
||||||
|
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
results = getclaimsforname(req);
|
||||||
|
claims = results[T_CLAIMS];
|
||||||
|
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 3);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 3);
|
||||||
|
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||||
|
BOOST_CHECK_EQUAL(claims[1][T_SUPPORTS].size(), 0U);
|
||||||
|
|
||||||
|
req.params.push_back(blockHash.GetHex());
|
||||||
|
|
||||||
|
results = getclaimsforname(req);
|
||||||
|
claims = results[T_CLAIMS];
|
||||||
|
BOOST_CHECK_EQUAL(claims.size(), 1U);
|
||||||
|
BOOST_CHECK_EQUAL(results[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_SUPPORTS].size(), 0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback2_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("testN");
|
||||||
|
std::string sValue1("test1");
|
||||||
|
std::string sValue2("test2");
|
||||||
|
|
||||||
|
int height = chainActive.Height();
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||||
|
fixture.IncrementBlocks(3);
|
||||||
|
|
||||||
|
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sValue1, 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||||
|
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
req.params.push_back(UniValue(sName1));
|
||||||
|
req.params.push_back(blockHash.GetHex());
|
||||||
|
|
||||||
|
UniValue claimsResults = getclaimsforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(claimsResults[T_LASTTAKEOVERHEIGHT].get_int(), height + 5);
|
||||||
|
BOOST_CHECK_EQUAL(claimsResults[T_CLAIMS][0][T_SUPPORTS].size(), 0U);
|
||||||
|
BOOST_CHECK_EQUAL(claimsResults[T_CLAIMS][1][T_SUPPORTS].size(), 0U);
|
||||||
|
|
||||||
|
UniValue valueResults = getvalueforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(valueResults[T_VALUE].get_str(), HexStr(sValue2));
|
||||||
|
BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(claim_rpcs_rollback3_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("testN");
|
||||||
|
std::string sValue1("test1");
|
||||||
|
std::string sValue2("test2");
|
||||||
|
|
||||||
|
int height = chainActive.Height();
|
||||||
|
|
||||||
|
CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 3);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||||
|
fixture.IncrementBlocks(2);
|
||||||
|
|
||||||
|
uint256 blockHash = chainActive.Tip()->GetBlockHash();
|
||||||
|
|
||||||
|
CMutableTransaction tx3 = fixture.Spend(tx1); // abandon the claim
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||||
|
rpcfn_type getvalueforname = tableRPC["getvalueforname"]->actor;
|
||||||
|
rpcfn_type getblocktemplate = tableRPC["getblocktemplate"]->actor;
|
||||||
|
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
UniValue templateResults = getblocktemplate(req);
|
||||||
|
BOOST_CHECK_EQUAL(templateResults["claimtrie"].get_str(), chainActive.Tip()->hashClaimTrie.GetHex());
|
||||||
|
|
||||||
|
req.params.push_back(UniValue(sName1));
|
||||||
|
req.params.push_back(blockHash.GetHex());
|
||||||
|
|
||||||
|
UniValue claimsResults = getclaimsforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(claimsResults[T_LASTTAKEOVERHEIGHT].get_int(), height + 1);
|
||||||
|
|
||||||
|
UniValue valueResults = getvalueforname(req);
|
||||||
|
BOOST_CHECK_EQUAL(valueResults[T_VALUE].get_str(), HexStr(sValue1));
|
||||||
|
BOOST_CHECK_EQUAL(valueResults[T_AMOUNT].get_int(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_CASE(claim_rpc_pending_amount_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
std::string sName1("test");
|
||||||
|
std::string sValue1("test1");
|
||||||
|
std::string sValue2("test2");
|
||||||
|
|
||||||
|
rpcfn_type getclaimsforname = tableRPC["getclaimsforname"]->actor;
|
||||||
|
|
||||||
|
JSONRPCRequest req;
|
||||||
|
req.params = UniValue(UniValue::VARR);
|
||||||
|
req.params.push_back(UniValue(sName1));
|
||||||
|
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue1, 1);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, 2);
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
auto claims = getclaimsforname(req)[T_CLAIMS];
|
||||||
|
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||||
|
BOOST_CHECK(!claims[0].exists(T_PENDINGAMOUNT));
|
||||||
|
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 0);
|
||||||
|
BOOST_CHECK(claims[1].exists(T_PENDINGAMOUNT));
|
||||||
|
BOOST_CHECK_EQUAL(claims[1][T_PENDINGAMOUNT].get_int(), 2);
|
||||||
|
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
|
||||||
|
claims = getclaimsforname(req)[T_CLAIMS];
|
||||||
|
BOOST_CHECK_EQUAL(claims.size(), 2U);
|
||||||
|
BOOST_CHECK_EQUAL(claims[0][T_EFFECTIVEAMOUNT].get_int(), 2);
|
||||||
|
BOOST_CHECK(!claims[0].exists(T_PENDINGAMOUNT));
|
||||||
|
BOOST_CHECK_EQUAL(claims[1][T_EFFECTIVEAMOUNT].get_int(), 1);
|
||||||
|
BOOST_CHECK(!claims[1].exists(T_PENDINGAMOUNT));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -3,6 +3,7 @@
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <test/claimtriefixture.h>
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
@ -37,7 +38,79 @@ std::vector<std::string> random_strings(std::size_t count)
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
BOOST_FIXTURE_TEST_SUITE(prefixtrie_tests, BasicTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(prefixtrie_tests, RegTestingSetup)
|
||||||
|
|
||||||
|
#ifndef MAC_OSX // can't find a random number generator that produces the same sequence on OSX
|
||||||
|
BOOST_AUTO_TEST_CASE(triehash_fuzzer_test)
|
||||||
|
{
|
||||||
|
ClaimTrieChainFixture fixture;
|
||||||
|
|
||||||
|
auto envClaims = std::getenv("TRIEHASH_FUZZER_CLAIMS");
|
||||||
|
auto envBlocks = std::getenv("TRIEHASH_FUZZER_BLOCKS");
|
||||||
|
|
||||||
|
const int claimsPerBlock = envClaims ? std::atoi(envClaims) : 100;
|
||||||
|
const int blocks = envBlocks ? std::atoi(envBlocks) : 13;
|
||||||
|
|
||||||
|
auto names = random_strings(blocks * claimsPerBlock);
|
||||||
|
|
||||||
|
FastRandomContext frc(true);
|
||||||
|
std::unordered_map<std::string, std::vector<CMutableTransaction>> existingClaims;
|
||||||
|
std::vector<CMutableTransaction> existingSupports;
|
||||||
|
std::string value(1024, 'c');
|
||||||
|
|
||||||
|
std::vector<CTransaction> cb {fixture.GetCoinbase()};
|
||||||
|
for (int i = 0; i < blocks; ++i) {
|
||||||
|
for (int j = 0; j < claimsPerBlock; ++j) {
|
||||||
|
auto name = names[i * claimsPerBlock + j];
|
||||||
|
auto supportFront = frc.randrange(4) == 0;
|
||||||
|
auto supportBack = frc.randrange(4) == 0;
|
||||||
|
auto removeClaim = frc.randrange(4) == 0;
|
||||||
|
auto removeSupport = frc.randrange(4) == 0;
|
||||||
|
auto hit = existingClaims.find(name);
|
||||||
|
if (supportFront && hit != existingClaims.end() && hit->second.size()) {
|
||||||
|
auto tx = fixture.MakeSupport(cb.back(), hit->second[frc.rand64() % hit->second.size()], name, 2);
|
||||||
|
existingSupports.push_back(tx);
|
||||||
|
cb.emplace_back(std::move(tx));
|
||||||
|
}
|
||||||
|
if (removeClaim && hit != existingClaims.end() && hit->second.size()) {
|
||||||
|
auto idx = frc.rand64() % hit->second.size();
|
||||||
|
fixture.Spend(hit->second[idx]);
|
||||||
|
hit->second.erase(hit->second.begin() + idx);
|
||||||
|
} else {
|
||||||
|
auto tx = fixture.MakeClaim(cb.back(), name, value, 2);
|
||||||
|
existingClaims[name].push_back(tx);
|
||||||
|
hit = existingClaims.find(name);
|
||||||
|
cb.emplace_back(std::move(tx));
|
||||||
|
}
|
||||||
|
if (supportBack && hit != existingClaims.end() && hit->second.size()) {
|
||||||
|
auto tx = fixture.MakeSupport(cb.back(), hit->second[frc.rand64() % hit->second.size()], name, 2);
|
||||||
|
existingSupports.push_back(tx);
|
||||||
|
cb.emplace_back(std::move(tx));
|
||||||
|
}
|
||||||
|
if (removeSupport && (i & 7) == 7 && !existingSupports.empty()) {
|
||||||
|
const auto tidx = frc.rand64() % existingSupports.size();
|
||||||
|
const auto tx = existingSupports[tidx];
|
||||||
|
fixture.Spend(tx);
|
||||||
|
existingSupports.erase(existingSupports.begin() + tidx);
|
||||||
|
}
|
||||||
|
if (cb.back().GetValueOut() < 10 || cb.size() > 40000) {
|
||||||
|
cb.clear();
|
||||||
|
cb.push_back(fixture.GetCoinbase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixture.IncrementBlocks(1);
|
||||||
|
if (blocks > 13 && i % 50 == 0) // travisCI needs some periodic output
|
||||||
|
std::cerr << "In triehash_fuzzer_test with " << fixture.getTotalNamesInTrie() << " names at block " << i << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blocks == 1000 && claimsPerBlock == 100)
|
||||||
|
BOOST_CHECK_EQUAL(fixture.getMerkleHash().GetHex(), "28825257a129eef69cab87d6255c8359fc6dc083ca7f09222526e3a7971f382d");
|
||||||
|
else if (blocks == 13 && claimsPerBlock == 100)
|
||||||
|
BOOST_CHECK_EQUAL(fixture.getMerkleHash().GetHex(), "4e5984d6984f5f05d50e821e6228d56bcfbd16ca2093cd0308f6ff1c2bc8689a");
|
||||||
|
else
|
||||||
|
std::cerr << "Hash: " << fixture.getMerkleHash().GetHex() << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(insert_erase_test)
|
BOOST_AUTO_TEST_CASE(insert_erase_test)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue