From ae6d4edc988b609d001a844c662b4b631ed74ef8 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Wed, 25 Jul 2018 16:26:30 -0600 Subject: [PATCH 1/3] moved claimtrie_tests into claimtriebranching_tests to take advantage of the test fixture there --- src/Makefile.test.include | 1 - src/consensus/params.h | 3 + src/test/claimtrie_tests.cpp | 2831 ------------------------- src/test/claimtriebranching_tests.cpp | 2003 ++++++++++++++++- src/test/claimtriecache_tests.cpp | 141 +- 5 files changed, 2114 insertions(+), 2865 deletions(-) delete mode 100644 src/test/claimtrie_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 62944baff..05f88b3ea 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -60,7 +60,6 @@ BITCOIN_TESTS =\ test/merkle_tests.cpp \ test/miner_tests.cpp \ test/multisig_tests.cpp \ - test/claimtrie_tests.cpp \ test/claimtriecache_tests.cpp \ test/claimtriebranching_tests.cpp \ test/nameclaim_tests.cpp \ diff --git a/src/consensus/params.h b/src/consensus/params.h index 5356cd515..6e695b779 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -58,8 +58,11 @@ struct Params { bool fPowNoRetargeting; int64_t nPowTargetSpacing; int64_t nPowTargetTimespan; + /** how long it took claims to expire before the hard fork */ int64_t nOriginalClaimExpirationTime; + /** how long it takes claims to expire after the hard fork */ int64_t nExtendedClaimExpirationTime; + /** blocks before the hard fork that changed the expiration time */ int64_t nExtendedClaimExpirationForkHeight; int64_t GetExpirationTime(int64_t nHeight) const { return nHeight < nExtendedClaimExpirationForkHeight ? diff --git a/src/test/claimtrie_tests.cpp b/src/test/claimtrie_tests.cpp deleted file mode 100644 index 8fe6ff10e..000000000 --- a/src/test/claimtrie_tests.cpp +++ /dev/null @@ -1,2831 +0,0 @@ -// Copyright (c) 2015 The LBRY Foundation -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://opensource.org/licenses/mit-license.php - -#include "main.h" -#include "consensus/validation.h" -#include "consensus/merkle.h" -#include "primitives/transaction.h" -#include "miner.h" -#include "txmempool.h" -#include "claimtrie.h" -#include "nameclaim.h" -#include "coins.h" -#include "streams.h" -#include "chainparams.h" -#include "policy/policy.h" -#include -#include -#include "test/test_bitcoin.h" - -using namespace std; - -CScript scriptPubKey = CScript() << OP_TRUE; - -BOOST_FIXTURE_TEST_SUITE(claimtrie_tests, RegTestingSetup) - -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::max(); - tx.vout[0].scriptPubKey = CScript(); - tx.vout[0].nValue = 0; - - return tx; -} - -CMutableTransaction BuildTransaction(const CMutableTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1) -{ - CMutableTransaction tx; - tx.nVersion = 1; - tx.nLockTime = 0; - 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(); - tx.vin[0].nSequence = std::numeric_limits::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 CTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1) -{ - return BuildTransaction(CMutableTransaction(prev), prevout, numOutputs); -} - -void AddToMempool(CMutableTransaction& tx) -{ - //CCoinsView dummy; - //CCoinsViewCache view(&dummy); - //CAmount inChainInputValue; - //double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue); - //unsigned int nSigOps = GetLegacySigOpCount(tx); - //nSigOps += GetP2SHSigOpCount(tx, view); - //LockPoints lp; - //BOOST_CHECK(CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)); - //mempool.addUnchecked(tx.GetHash(), CTxMemPoolEntry(tx, 0, GetTime(), 111.1, chainActive.Height(), mempool.HasNoInputsOf(tx), 10000000000, false, nSigOps, lp)); - CValidationState state; - bool fMissingInputs; - CFeeRate txFeeRate = CFeeRate(0); - BOOST_CHECK(AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, &txFeeRate)); - //TestMemPoolEntryHelper entry; - //entry.nFee = 11; - //entry.dPriority = 111.0; - //entry.nHeight = 11; - //mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).Time(GetTime()).FromTx(tx)); -} - -bool CreateBlock(CBlockTemplate* pblocktemplate) -{ - static int unique_block_counter = 0; - CBlock* pblock = &pblocktemplate->block; - pblock->nVersion = 1; - pblock->nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing; - CMutableTransaction txCoinbase(pblock->vtx[0]); - txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(unique_block_counter++) << CScriptNum(chainActive.Height()); - txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); - pblock->vtx[0] = CTransaction(txCoinbase); - pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - for (int i = 0; ; ++i) - { - pblock->nNonce = i; - if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) - { - break; - } - } - CValidationState state; - bool success = (ProcessNewBlock(state, Params(), NULL, pblock, true, NULL) && state.IsValid() && pblock->GetHash() == chainActive.Tip()->GetBlockHash()); - pblock->hashPrevBlock = pblock->GetHash(); - return success; -} - -bool RemoveBlock(uint256& blockhash) -{ - CValidationState state; - if (mapBlockIndex.count(blockhash) == 0) - return false; - CBlockIndex* pblockindex = mapBlockIndex[blockhash]; - InvalidateBlock(state, Params().GetConsensus(), pblockindex); - if (state.IsValid()) - { - ActivateBestChain(state, Params()); - } - mempool.clear(); - return state.IsValid(); - -} - -bool CreateCoinbases(unsigned int num_coinbases, std::vector& coinbases) -{ - CBlockTemplate *pblocktemplate; - coinbases.clear(); - BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), scriptPubKey)); - BOOST_CHECK(pblocktemplate->block.vtx.size() == 1); - pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); - for (unsigned int i = 0; i < 100 + num_coinbases; ++i) - { - BOOST_CHECK(CreateBlock(pblocktemplate)); - if (coinbases.size() < num_coinbases) - coinbases.push_back(CTransaction(pblocktemplate->block.vtx[0])); - } - delete pblocktemplate; - return true; -} - -bool CreateBlocks(unsigned int num_blocks, unsigned int num_txs) -{ - CBlockTemplate *pblocktemplate; - BOOST_CHECK(pblocktemplate = CreateNewBlock(Params(), scriptPubKey)); - BOOST_CHECK(pblocktemplate->block.vtx.size() == num_txs); - pblocktemplate->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); - for (unsigned int i = 0; i < num_blocks; ++i) - { - BOOST_CHECK(CreateBlock(pblocktemplate)); - } - delete pblocktemplate; - return true; -} - -BOOST_AUTO_TEST_CASE(claimtrie_merkle_hash) -{ - fRequireStandard = false; - CClaimValue unused; - uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - uint160 hash160; - CMutableTransaction tx1 = BuildTransaction(hash0); - COutPoint tx1OutPoint(tx1.GetHash(), 0); - CMutableTransaction tx2 = BuildTransaction(tx1.GetHash()); - COutPoint tx2OutPoint(tx2.GetHash(), 0); - CMutableTransaction tx3 = BuildTransaction(tx2.GetHash()); - COutPoint tx3OutPoint(tx3.GetHash(), 0); - CMutableTransaction tx4 = BuildTransaction(tx3.GetHash()); - COutPoint tx4OutPoint(tx4.GetHash(), 0); - CMutableTransaction tx5 = BuildTransaction(tx4.GetHash()); - COutPoint tx5OutPoint(tx5.GetHash(), 0); - CMutableTransaction tx6 = BuildTransaction(tx5.GetHash()); - COutPoint tx6OutPoint(tx6.GetHash(), 0); - - uint256 hash1; - hash1.SetHex("71c7b8d35b9a3d7ad9a1272b68972979bbd18589f1efe6f27b0bf260a6ba78fa"); - - uint256 hash2; - hash2.SetHex("c4fc0e2ad56562a636a0a237a96a5f250ef53495c2cb5edd531f087a8de83722"); - - uint256 hash3; - hash3.SetHex("baf52472bd7da19fe1e35116cfb3bd180d8770ffbe3ae9243df1fb58a14b0975"); - - uint256 hash4; - hash4.SetHex("c73232a755bf015f22eaa611b283ff38100f2a23fb6222e86eca363452ba0c51"); - - BOOST_CHECK(pclaimTrie->empty()); - - CClaimTrieCache ntState(pclaimTrie, false); - ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200)); - ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2OutPoint, hash160, 50, 100, 200)); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(!ntState.empty()); - BOOST_CHECK(ntState.getMerkleHash() == hash1); - - ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); - BOOST_CHECK(ntState.getMerkleHash() == hash1); - ntState.insertClaimIntoTrie(std::string("tes"), CClaimValue(tx4OutPoint, hash160, 50, 100, 200)); - BOOST_CHECK(ntState.getMerkleHash() == hash2); - ntState.insertClaimIntoTrie(std::string("testtesttesttest"), CClaimValue(tx5OutPoint, hash160, 50, 100, 200)); - ntState.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused); - BOOST_CHECK(ntState.getMerkleHash() == hash2); - ntState.flush(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState1(pclaimTrie, false); - ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); - ntState1.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused); - ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); - ntState1.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); - - BOOST_CHECK(ntState1.getMerkleHash() == hash0); - - CClaimTrieCache ntState2(pclaimTrie, false); - ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200)); - ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); - - BOOST_CHECK(ntState2.getMerkleHash() == hash3); - - ntState2.flush(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState3(pclaimTrie, false); - ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200)); - BOOST_CHECK(ntState3.getMerkleHash() == hash4); - ntState3.flush(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState4(pclaimTrie, false); - ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused); - BOOST_CHECK(ntState4.getMerkleHash() == hash2); - ntState4.flush(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState5(pclaimTrie, false); - ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); - - BOOST_CHECK(ntState5.getMerkleHash() == hash2); - ntState5.flush(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState6(pclaimTrie, false); - ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); - - BOOST_CHECK(ntState6.getMerkleHash() == hash2); - ntState6.flush(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); - BOOST_CHECK(pclaimTrie->checkConsistency()); - - CClaimTrieCache ntState7(pclaimTrie, false); - ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); - ntState7.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); - ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); - ntState7.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused); - - BOOST_CHECK(ntState7.getMerkleHash() == hash0); - ntState7.flush(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); - BOOST_CHECK(pclaimTrie->checkConsistency()); -} - -BOOST_AUTO_TEST_CASE(claimtrie_insert_update_claim) -{ - - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); - LOCK(cs_main); - - std::string sName1("atest"); - std::string sName2("btest"); - std::string sName3("atest123"); - std::string sValue1("testa"); - std::string sValue2("testb"); - std::string sValue3("123testa"); - - std::vector vchName1(sName1.begin(), sName1.end()); - std::vector vchName2(sName2.begin(), sName2.end()); - std::vector vchName3(sName3.begin(), sName3.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - std::vector vchValue3(sValue3.begin(), sValue3.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(6, coinbases)); - - uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName1 << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); - std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName2 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx2.vout[0].nValue = tx1.vout[0].nValue - 1; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(tx1); - tx3.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName1 << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - tx3.vout[0].nValue -= 10000; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(tx2); - tx4.vout[0].scriptPubKey = CScript() << OP_TRUE; - COutPoint tx4OutPoint(tx4.GetHash(), 0); - - CMutableTransaction tx5 = BuildTransaction(coinbases[2]); - tx5.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName2 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx5OutPoint(tx5.GetHash(), 0); - - CMutableTransaction tx6 = BuildTransaction(tx3); - tx6.vout[0].scriptPubKey = CScript() << OP_TRUE; - COutPoint tx6OutPoint(tx6.GetHash(), 0); - - CMutableTransaction tx7 = BuildTransaction(coinbases[3]); - tx7.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName1 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx7.vout[0].nValue = tx1.vout[0].nValue - 10001; - uint160 tx7ClaimId = ClaimIdHash(tx7.GetHash(), 0); - std::vector vchTx7ClaimId(tx7ClaimId.begin(), tx7ClaimId.end()); - COutPoint tx7OutPoint(tx7.GetHash(), 0); - - CMutableTransaction tx8 = BuildTransaction(tx3, 0, 2); - tx8.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName1 << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - tx8.vout[0].nValue = tx8.vout[0].nValue - 1; - tx8.vout[1].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName1 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx8OutPoint0(tx8.GetHash(), 0); - COutPoint tx8OutPoint1(tx8.GetHash(), 1); - - CMutableTransaction tx9 = BuildTransaction(tx7); - tx9.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName1 << vchTx7ClaimId << vchValue2 << OP_2DROP << OP_2DROP << OP_TRUE; - tx9.vout[0].nValue -= 10000; - COutPoint tx9OutPoint(tx9.GetHash(), 0); - - CMutableTransaction tx10 = BuildTransaction(coinbases[4]); - tx10.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName1 << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - COutPoint tx10OutPoint(tx10.GetHash(), 0); - - CMutableTransaction tx11 = BuildTransaction(tx10); - tx11.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName1 << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - COutPoint tx11OutPoint(tx11.GetHash(), 0); - - CMutableTransaction tx12 = BuildTransaction(tx10); - tx12.vout[0].scriptPubKey = CScript() << OP_TRUE; - COutPoint tx12OutPoint(tx12.GetHash(), 0); - - CMutableTransaction tx13 = BuildTransaction(coinbases[5]); - tx13.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName3 << vchValue3 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx13OutPoint(tx13.GetHash(), 0); - - CClaimValue val; - - int nThrowaway; - - std::vector blocks_to_invalidate; - - // Verify claims for uncontrolled names go in immediately - - AddToMempool(tx7); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx7OutPoint); - - // Verify claims for controlled names are delayed, and that the bigger claim wins when inserted - - BOOST_CHECK(CreateBlocks(5, 1)); - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(5, 1)); - - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // Verify updates to the best claim get inserted immediately, and others don't. - - AddToMempool(tx3); - AddToMempool(tx9); - - BOOST_CHECK(CreateBlocks(1, 3)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx1OutPoint)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx7OutPoint)); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx9OutPoint, nThrowaway)); - - // Disconnect all blocks until the first block, and then reattach them, in memory only - - //FlushStateToDisk(); - - CCoinsViewCache coins(pcoinsTip); - CClaimTrieCache trieCache(pclaimTrie); - CBlockIndex* pindexState = chainActive.Tip(); - CValidationState state; - CBlockIndex* pindex; - for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex=pindex->pprev) - { - CBlock block; - BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); - if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) - { - bool fClean = true; - BOOST_CHECK(DisconnectBlock(block, state, pindex, coins, trieCache, &fClean)); - pindexState = pindex->pprev; - } - } - while (pindex != chainActive.Tip()) - { - pindex = chainActive.Next(pindex); - CBlock block; - BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); - BOOST_CHECK(ConnectBlock(block, state, pindex, coins, trieCache)); - } - - // Roll back the last block, make sure tx1 and tx7 are put back in the trie - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - BOOST_CHECK(pclaimTrie->haveClaim(sName1, tx7OutPoint)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->empty()); - - // Roll all the way back, make sure all txs are out of the trie - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->getInfoForName(sName1, val)); - - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Test undoing a claim before the claim gets into the trie - - // Put tx1 in the chain, then advance a few blocks. - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(10, 1)); - - // Put tx7 in the chain, verify it goes into the queue - - AddToMempool(tx7); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // Undo that block and make sure it's not in the queue - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // Make sure it's not in the queue - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Go back to the beginning - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Test spend a claim which was just inserted into the trie - - // Immediately spend tx2 with tx4, verify nothing gets put in the trie - - AddToMempool(tx2); - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 3)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Verify that if a claim in the queue is spent, it does not get into the trie - - // Put tx5 into the chain, advance until it's in the trie for a few blocks - - AddToMempool(tx5); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(CreateBlocks(5, 1)); - - // Put tx2 into the chain, and then advance a few blocks but not far enough for it to get into the trie - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName2, tx2OutPoint, nThrowaway)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(3, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // Spend tx2 with tx4, and then advance to where tx2 would be inserted into the trie and verify it hasn't happened - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(5, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->haveClaim(sName2, tx2OutPoint)); - - // Undo spending tx2 with tx4, and then advance and verify tx2 is inserted into the trie when it should be - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName2, tx2OutPoint, nThrowaway)); - - BOOST_CHECK(CreateBlocks(2, 1)); - - BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); - BOOST_CHECK(val.outPoint == tx5OutPoint); - BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); - - // Test undoing a spend which involves a claim in the trie - - // spend tx2, which is in the trie, with tx4 - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->haveClaim(sName2, tx2OutPoint)); - - // undo spending tx2 with tx4, and verify tx2 is back in the trie - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); - BOOST_CHECK(val.outPoint == tx5OutPoint); - BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); - - // roll back to the beginning - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Test undoing a spent update which updated a claim still in the queue - - // Create the claim that will cause the others to be in the queue - - AddToMempool(tx7); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(CreateBlocks(5, 1)); - - // Create the original claim (tx1) - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - //blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx1OutPoint, nThrowaway)); - - // move forward some, but not far enough for the claim to get into the trie - - BOOST_CHECK(CreateBlocks(2, 1)); - - // update the original claim (tx3 spends tx1) - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - //blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx1OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx1OutPoint)); - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx3OutPoint, nThrowaway)); - - // spend the update (tx6 spends tx3) - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx3OutPoint)); - - // undo spending the update (undo tx6 spending tx3) - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // make sure the update (tx3) still goes into effect when it's supposed to - - BOOST_CHECK(CreateBlocks(8, 1)); - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->haveClaim(sName1, tx3OutPoint)); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Test undoing an spent update which updated the best claim to a name - - // move forward until the original claim is inserted into the trie - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(5, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // update the original claim (tx3 spends tx1) - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - - // spend the update (tx6 spends tx3) - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // undo spending the update (undo tx6 spending tx3) - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - - // Test having two updates to a claim in the same transaction - - // Add both txouts (tx8 spends tx3) - - AddToMempool(tx8); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - // ensure txout 0 made it into the trie and txout 1 did not - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx8OutPoint0); - - // roll forward until tx8 output 1 gets into the trie - - BOOST_CHECK(CreateBlocks(6, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - // ensure txout 1 made it into the trie and is now in control - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx8OutPoint1); - - // roll back to before tx8 - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // make sure invalid updates don't wreak any havoc - - // put tx1 into the trie - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(5, 1)); - - // put in bad tx10 - - AddToMempool(tx10); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll back, make sure nothing bad happens - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // put it back in - - AddToMempool(tx10); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // update it - - AddToMempool(tx11); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(10, 1)); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll back to before the update - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // make sure tx10 would have gotten into the trie, then run tests again - - BOOST_CHECK(CreateBlocks(10, 1)); - - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // update it - - AddToMempool(tx11); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // make sure tx11 would have gotten into the trie - - BOOST_CHECK(CreateBlocks(20, 1)); - - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); - BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); - BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // Put tx10 and tx11 in without tx1 in - - AddToMempool(tx10); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // update with tx11 - - AddToMempool(tx11); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll back to before tx11 - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // spent tx10 with tx12 instead which is not a claim operation of any kind - - AddToMempool(tx12); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - // make sure all claim for names which exist in the trie but have no - // values get inserted immediately - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - AddToMempool(tx13); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // roll back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); -} - -BOOST_AUTO_TEST_CASE(claimtrie_claim_expiration) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); - - LOCK(cs_main); - - std::string sName("atest"); - std::string sValue("testa"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue(sValue.begin(), sValue.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(2, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(tx1); - tx2.vout[0].scriptPubKey = CScript() << OP_TRUE; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(coinbases[1]); - tx3.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue << OP_2DROP << OP_DROP << OP_TRUE; - tx3.vout[0].nValue = tx1.vout[0].nValue >> 1; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - int nThrowaway; - - std::vector blocks_to_invalidate; - // set expiration time to 200 blocks after the block is created - - pclaimTrie->setExpirationTime(200); - - // create a claim. verify the expiration event has been scheduled. - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // advance until the expiration event occurs. verify the expiration event occurs on time. - - BOOST_CHECK(CreateBlocks(100, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(CreateBlocks(99, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->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. - - BOOST_CHECK(CreateBlocks(100, 1)); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // advance until the expiration event occurs. verify the expiration event occurs on time. - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // roll back some more. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // spend the claim. verify the expiration event is removed. - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // roll back the spend. verify the expiration event is returned. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // advance until the expiration event occurs. verify the event occurs on time. - - BOOST_CHECK(CreateBlocks(100, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // spend the expired claim - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // undo the spend. verify everything remains empty. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // verify the expiration event happens at the right time again - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - - // roll back to before the expiration event. verify it gets reinserted and expiration gets scheduled. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // roll all the way back. verify the claim is removed and the expiration event is removed. - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(blocks_to_invalidate.empty()); - - // Make sure that when a claim expires, a lesser claim for the same name takes over - - CClaimValue val; - - // create one claim for the name - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // advance a little while and insert the second claim - - BOOST_CHECK(CreateBlocks(4, 1)); - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - // advance until tx3 is valid, ensure tx1 is winning - - BOOST_CHECK(CreateBlocks(4, 1)); - - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName, tx3OutPoint, nThrowaway)); - - BOOST_CHECK(CreateBlocks(1, 1)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll back to before tx3 is valid - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // advance again until tx3 is valid - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance until the expiration event occurs. verify the expiration event occurs on time. - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - BOOST_CHECK(CreateBlocks(188, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - - // spend tx1 - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - // roll back to when tx1 and tx3 are in the trie and tx1 is winning - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); - BOOST_CHECK(blocks_to_invalidate.empty()); -} - -BOOST_AUTO_TEST_CASE(claimtrie_supporting_claims) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); - - LOCK(cs_main); - - std::string sName("atest"); - std::string sValue1("testa"); - std::string sValue2("testb"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(3, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - tx1.vout[0].nValue = 1; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx2.vout[0].nValue = 5; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(coinbases[2]); - uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); - std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); - tx3.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchName << vchTx1ClaimId << OP_2DROP << OP_DROP << OP_TRUE; - tx3.vout[0].nValue = 5; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(tx1); - tx4.vout[0].scriptPubKey = CScript() << OP_TRUE; - - CMutableTransaction tx5 = BuildTransaction(tx2); - tx5.vout[0].scriptPubKey = CScript() << OP_TRUE; - - CMutableTransaction tx6 = BuildTransaction(tx3); - tx6.vout[0].scriptPubKey = CScript() << OP_TRUE; - - CMutableTransaction tx7 = BuildTransaction(tx1); - tx7.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - COutPoint tx7OutPoint(tx7.GetHash(), 0); - - CClaimValue val; - std::vector blocks_to_invalidate; - - // Test 1: create 1 LBC claim (tx1), create 5 LBC support (tx3), create 5 LBC claim (tx2) - // Verify that tx1 retains control throughout - // spend tx3, verify that tx2 gains control - // roll back to before tx3 is spent, verify tx1 regains control - // update tx1 with tx7, verify tx7 has control - // roll back to before tx7 is inserted, verify tx1 regains control - // roll back to before tx2 is valid, spend tx3 - // advance to tx2 valid, verify tx2 gains control - // roll back to before tx3 is valid, spend tx3 - // advance to tx2 valid, verify tx2 gains control - // roll back to insertion of tx3, and don't insert it - // insert tx2, advance until it is valid, verify tx2 gains control - - // Put tx1 in the blockchain - - AddToMempool(tx1); - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(5, 1)); - - // Put tx3 into the blockchain - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(3, 1)); - - // Put tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // advance until tx2 is valid - - BOOST_CHECK(CreateBlocks(9, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // spend tx3 - - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - // verify tx2 gains control - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // unspend tx3, verify tx1 regains control - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // update tx1 with tx7, verify tx7 has control - - AddToMempool(tx7); - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx7.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx7OutPoint); - - // roll back to before tx7 is inserted, verify tx1 has control - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll back to before tx2 is valid - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // spend tx3 - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - - // Verify tx2 gains control - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // roll back to before tx3 is inserted - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(4, 1)); - - // Put tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // advance until tx2 is valid - - BOOST_CHECK(CreateBlocks(9, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - // Make sure that when a support in the queue gets spent and then the spend is - // undone, it goes back into the queue in the right spot - - // put tx2 and tx1 into the trie - - AddToMempool(tx1); - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 3)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(5, 1)); - - // put tx3 into the support queue - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - - // advance a couple of blocks - - BOOST_CHECK(CreateBlocks(2, 1)); - - // spend tx3 - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // undo spend of tx3, verify it gets back in the right place in the queue - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - - BOOST_CHECK(CreateBlocks(3, 1)); - BOOST_CHECK(CreateBlocks(1, 1)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // spend tx3 again, then undo the spend and roll back until it's back in the queue - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance until tx3 is valid again - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(blocks_to_invalidate.empty()); -} - -BOOST_AUTO_TEST_CASE(claimtrie_supporting_claims2) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); - - LOCK(cs_main); - - std::string sName("atest"); - std::string sValue1("testa"); - std::string sValue2("testb"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(3, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - tx1.vout[0].nValue = 1; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx2.vout[0].nValue = 5; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(coinbases[2]); - uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); - std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); - tx3.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchName << vchTx1ClaimId << OP_2DROP << OP_DROP << OP_TRUE; - tx3.vout[0].nValue = 5; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(tx1); - tx4.vout[0].scriptPubKey = CScript() << OP_TRUE; - - CMutableTransaction tx5 = BuildTransaction(tx2); - tx5.vout[0].scriptPubKey = CScript() << OP_TRUE; - - CMutableTransaction tx6 = BuildTransaction(tx3); - tx6.vout[0].scriptPubKey = CScript() << OP_TRUE; - - int nThrowaway; - CClaimValue val; - std::vector blocks_to_invalidate; - - // Test 2: create 1 LBC claim (tx1), create 5 LBC claim (tx2), create 5 LBC support (tx3) - // Verify that tx1 loses control when tx2 becomes valid, and then tx1 gains control when tx3 becomes valid - // Then, verify that tx2 regains control when A) tx3 is spent and B) tx3 is undone - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(4, 1)); - - // put tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // advance until tx2 is in the trie - - BOOST_CHECK(CreateBlocks(4, 1)); - - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName, tx2OutPoint, nThrowaway)); - - BOOST_CHECK(CreateBlocks(1, 1)); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(4, 1)); - - // put tx3 into the blockchain - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - - // advance until tx3 is valid - - BOOST_CHECK(CreateBlocks(4, 1)); - - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // spend tx3 - - AddToMempool(tx6); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // undo spend - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll back to before tx3 is valid - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Test 4: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3) - // Verify that tx1 retains control throughout - - // put tx1 into the blockchain - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(5, 1)); - - // put tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance some, insert tx3, should be immediately valid - - BOOST_CHECK(CreateBlocks(2, 1)); - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance until tx2 is valid, verify tx1 retains control - - BOOST_CHECK(CreateBlocks(2, 1)); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - BOOST_CHECK(pclaimTrie->haveClaim(sName, tx2OutPoint)); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Test 5: create 5 LBC claim (tx2), wait till valid, create 1 LBC claim (tx1), create 5 LBC support (tx3) - // Verify that tx2 retains control until support becomes valid - - // insert tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(9, 1)); - - // insert tx1 into the block chain - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance some - - BOOST_CHECK(CreateBlocks(5, 1)); - - // insert tx3 into the block chain - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // advance until tx1 is valid - - BOOST_CHECK(CreateBlocks(4, 1)); - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - BOOST_CHECK(pclaimTrie->haveClaim(sName, tx1OutPoint)); - - // advance until tx3 is valid - - BOOST_CHECK(CreateBlocks(10, 1)); - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - - // Test 6: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3), spend tx1 - // Verify that tx1 retains control until it is spent - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance a few blocks - - BOOST_CHECK(CreateBlocks(5, 1)); - - // insert tx2 into the blockchain - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance some, insert tx3 - - BOOST_CHECK(CreateBlocks(2, 1)); - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // advance until tx2 is valid - - BOOST_CHECK(CreateBlocks(2, 1)); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // spend tx1 - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // undo spend of tx1 - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Test 7: create 1 LBC claim (tx1), wait till valid, create 5 LBC support (tx3), spend tx1 - // Verify name trie is empty - - // insert tx1 into blockchain - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // insert tx3 into blockchain - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // spent tx1 - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); -} - -BOOST_AUTO_TEST_CASE(claimtrie_invalid_claimid) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight = chainActive.Height() + 1); - - LOCK(cs_main); - - std::string sName("atest"); - std::string sValue1("testa"); - std::string sValue2("testb"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(2, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - tx1.vout[0].nValue = 1; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx2.vout[0].nValue = 5; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(tx2); - uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); - std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); - tx3.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName << vchTx1ClaimId << vchValue2 << OP_2DROP << OP_2DROP << OP_TRUE; - tx3.vout[0].nValue = 4; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(tx3); - tx4.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName << vchTx1ClaimId << vchValue2 << OP_2DROP << OP_2DROP << OP_TRUE; - tx4.vout[0].nValue = 3; - COutPoint tx4OutPoint(tx4.GetHash(), 0); - - CClaimValue val; - std::vector blocks_to_invalidate; - - // Verify that supports expire - - // Create a 1 LBC claim (tx1) - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Make sure it gets way in there - - BOOST_CHECK(CreateBlocks(100, 1)); - - // Create a 5 LBC claim (tx2) - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - - // Create a tx with a bogus claimId - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Verify it's not in the claim trie - - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); - - // Update the tx with the bogus claimId - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx4.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - // Verify it's not in the claim trie - - BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // Go forward a few hundred blocks and verify it's not in there - - BOOST_CHECK(CreateBlocks(300, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - - BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); - - // go all the way back - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); -} - -BOOST_AUTO_TEST_CASE(claimtrie_expiring_supports) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight = chainActive.Height() + 1); - - LOCK(cs_main); - - std::string sName("atest"); - std::string sValue1("testa"); - std::string sValue2("testb"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(3, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - tx1.vout[0].nValue = 1; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - tx2.vout[0].nValue = 5; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(coinbases[2]); - uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); - std::vector vchTx1ClaimId(tx1ClaimId.begin(), tx1ClaimId.end()); - tx3.vout[0].scriptPubKey = CScript() << OP_SUPPORT_CLAIM << vchName << vchTx1ClaimId << OP_2DROP << OP_DROP << OP_TRUE; - tx3.vout[0].nValue = 5; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(tx1); - tx4.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM << vchName << vchTx1ClaimId << vchValue1 << OP_2DROP << OP_2DROP << OP_TRUE; - COutPoint tx4OutPoint(tx4.GetHash(), 0); - - CMutableTransaction tx5 = BuildTransaction(tx3); - tx5.vout[0].scriptPubKey = CScript() << OP_TRUE; - COutPoint tx5OutPoint(tx5.GetHash(), 0); - - CClaimValue val; - std::vector blocks_to_invalidate; - - pclaimTrie->setExpirationTime(200); - - // Verify that supports expire - - // Create a 1 LBC claim (tx1) - - AddToMempool(tx1); - - BOOST_CHECK(CreateBlocks(1, 2)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Create a 5 LBC support (tx3) - - AddToMempool(tx3); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Advance some, then insert 5 LBC claim (tx2) - - BOOST_CHECK(CreateBlocks(49, 1)); - - AddToMempool(tx2); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - // Advance until tx2 is valid - - BOOST_CHECK(CreateBlocks(50, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(!pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - - // Update tx1 so that it expires after tx3 expires - - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - // Advance until the support expires - - BOOST_CHECK(CreateBlocks(50, 1)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(CreateBlocks(47, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - - BOOST_CHECK(CreateBlocks(1, 1)); - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // undo the block, make sure control goes back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - // redo the block, make sure it expires again - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // roll back some, spend the support, and make sure nothing unexpected - // happens at the time the support should have expired - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - AddToMempool(tx5); - - BOOST_CHECK(CreateBlocks(1, 2)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - BOOST_CHECK(CreateBlocks(50, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - //undo the spend, and make sure it still expires on time - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - BOOST_CHECK(CreateBlocks(48, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(!pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - BOOST_CHECK(CreateBlocks(1, 1)); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - - // roll all the way back - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->supportEmpty()); - BOOST_CHECK(pclaimTrie->supportQueueEmpty()); -} - -BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize) -{ - fRequireStandard = false; - CDataStream ss(SER_DISK, 0); - - uint160 hash160; - - CClaimTrieNode n1; - CClaimTrieNode n2; - CClaimValue throwaway; - - ss << n1; - ss >> n2; - BOOST_CHECK(n1 == n2); - - n1.hash.SetHex("0000000000000000000000000000000000000000000000000000000000000001"); - BOOST_CHECK(n1 != n2); - ss << n1; - ss >> n2; - BOOST_CHECK(n1 == n2); - - n1.hash.SetHex("a79e8a5b28f7fa5e8836a4b48da9988bdf56ce749f81f413cb754f963a516200"); - BOOST_CHECK(n1 != n2); - ss << n1; - ss >> n2; - BOOST_CHECK(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(n1 == n2); - - n1.insertClaim(v2); - BOOST_CHECK(n1 != n2); - ss << n1; - ss >> n2; - BOOST_CHECK(n1 == n2); - - n1.removeClaim(v1.outPoint, throwaway); - BOOST_CHECK(n1 != n2); - ss << n1; - ss >> n2; - BOOST_CHECK(n1 == n2); - - n1.removeClaim(v2.outPoint, throwaway); - BOOST_CHECK(n1 != n2); - ss << n1; - ss >> n2; - BOOST_CHECK(n1 == n2); -} - -bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::string& name) -{ - uint256 previousComputedHash; - std::string computedReverseName; - bool verifiedValue = false; - - for (std::vector::const_reverse_iterator itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) - { - bool foundChildInChain = false; - std::vector vchToHash; - for (std::vector >::const_iterator 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 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(claimtrievalue_proof) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight == chainActive.Height() + 1); - - LOCK(cs_main); - - 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(""); - - std::vector vchName1(sName1.begin(), sName1.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - - std::vector vchName2(sName2.begin(), sName2.end()); - std::vector vchValue2(sValue2.begin(), sValue2.end()); - - std::vector vchName3(sName3.begin(), sName3.end()); - std::vector vchValue3(sValue3.begin(), sValue3.end()); - - std::vector vchName4(sName4.begin(), sName4.end()); - std::vector vchValue4(sValue4.begin(), sValue4.end()); - - std::vector vchName7(sName7.begin(), sName7.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(5, coinbases)); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName1 << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - CMutableTransaction tx2 = BuildTransaction(coinbases[1]); - tx2.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName2 << vchValue2 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx2OutPoint(tx2.GetHash(), 0); - - CMutableTransaction tx3 = BuildTransaction(coinbases[2]); - tx3.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName3 << vchValue3 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx3OutPoint(tx3.GetHash(), 0); - - CMutableTransaction tx4 = BuildTransaction(coinbases[3]); - tx4.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName4 << vchValue4 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx4OutPoint(tx4.GetHash(), 0); - - CMutableTransaction tx5 = BuildTransaction(coinbases[4]); - tx5.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName7 << vchValue4 << OP_2DROP << OP_DROP << OP_TRUE; - COutPoint tx5OutPoint(tx5.GetHash(), 0); - - CClaimValue val; - - std::vector blocks_to_invalidate; - - // create a claim. verify the expiration event has been scheduled. - - AddToMempool(tx1); - AddToMempool(tx2); - AddToMempool(tx3); - AddToMempool(tx4); - - BOOST_CHECK(CreateBlocks(1, 5)); - - blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); - - BOOST_CHECK(!pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); - BOOST_CHECK(val.outPoint == tx1OutPoint); - BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); - BOOST_CHECK(val.outPoint == tx2OutPoint); - BOOST_CHECK(pclaimTrie->getInfoForName(sName3, val)); - BOOST_CHECK(val.outPoint == tx3OutPoint); - BOOST_CHECK(pclaimTrie->getInfoForName(sName4, val)); - BOOST_CHECK(val.outPoint == tx4OutPoint); - - CClaimTrieCache cache(pclaimTrie); - - CClaimTrieProof proof; - - proof = cache.getProofForName(sName1); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); - BOOST_CHECK(proof.outPoint == tx1OutPoint); - - proof = cache.getProofForName(sName2); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); - BOOST_CHECK(proof.outPoint == tx2OutPoint); - - proof = cache.getProofForName(sName3); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); - BOOST_CHECK(proof.outPoint == tx3OutPoint); - - proof = cache.getProofForName(sName4); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); - BOOST_CHECK(proof.outPoint == tx4OutPoint); - - proof = cache.getProofForName(sName5); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); - BOOST_CHECK(proof.hasValue == false); - - proof = cache.getProofForName(sName6); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); - BOOST_CHECK(proof.hasValue == false); - - proof = cache.getProofForName(sName7); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); - BOOST_CHECK(proof.hasValue == false); - - AddToMempool(tx5); - - BOOST_CHECK(CreateBlocks(1, 2)); - - BOOST_CHECK(pclaimTrie->getInfoForName(sName7, val)); - BOOST_CHECK(val.outPoint == tx5OutPoint); - - cache = CClaimTrieCache(pclaimTrie); - - proof = cache.getProofForName(sName1); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); - BOOST_CHECK(proof.outPoint == tx1OutPoint); - - proof = cache.getProofForName(sName2); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); - BOOST_CHECK(proof.outPoint == tx2OutPoint); - - proof = cache.getProofForName(sName3); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); - BOOST_CHECK(proof.outPoint == tx3OutPoint); - - proof = cache.getProofForName(sName4); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); - BOOST_CHECK(proof.outPoint == tx4OutPoint); - - proof = cache.getProofForName(sName5); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); - BOOST_CHECK(proof.hasValue == false); - - proof = cache.getProofForName(sName6); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); - BOOST_CHECK(proof.hasValue == false); - - proof = cache.getProofForName(sName7); - BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); - BOOST_CHECK(proof.outPoint == tx5OutPoint); - - BOOST_CHECK(RemoveBlock(blocks_to_invalidate.back())); - blocks_to_invalidate.pop_back(); - BOOST_CHECK(pclaimTrie->empty()); - BOOST_CHECK(pclaimTrie->queueEmpty()); - BOOST_CHECK(blocks_to_invalidate.empty()); - -} - -// Check that blocks with bogus calimtrie hash is rejected -BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash) -{ - fRequireStandard = false; - BOOST_CHECK(pclaimTrie->nCurrentHeight = chainActive.Height() + 1); - LOCK(cs_main); - std::string sName("test"); - std::string sValue1("test"); - - std::vector vchName(sName.begin(), sName.end()); - std::vector vchValue1(sValue1.begin(), sValue1.end()); - - std::vector coinbases; - - BOOST_CHECK(CreateCoinbases(3, coinbases)); - - int orig_chain_height = chainActive.Height(); - - CMutableTransaction tx1 = BuildTransaction(coinbases[0]); - tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME << vchName << vchValue1 << OP_2DROP << OP_DROP << OP_TRUE; - tx1.vout[0].nValue = 1; - COutPoint tx1OutPoint(tx1.GetHash(), 0); - - AddToMempool(tx1); - - CBlockTemplate *pblockTemp; - BOOST_CHECK(pblockTemp = CreateNewBlock(Params(), scriptPubKey)); - pblockTemp->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); - pblockTemp->block.nVersion = 1; - pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing; - CMutableTransaction txCoinbase(pblockTemp->block.vtx[0]); - txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(chainActive.Height()); - txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); - pblockTemp->block.vtx[0] = CTransaction(txCoinbase); - pblockTemp->block.hashMerkleRoot = BlockMerkleRoot(pblockTemp->block); - //create bogus hash - - uint256 bogusHashClaimTrie; - bogusHashClaimTrie.SetHex("aaa"); - pblockTemp->block.hashClaimTrie = bogusHashClaimTrie; - - for (int i = 0; ; ++i) - { - pblockTemp->block.nNonce = i; - if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) - { - break; - } - } - CValidationState state; - bool success = ProcessNewBlock(state, Params(), NULL, &pblockTemp->block, true, NULL); - // will process , but will not be connected - BOOST_CHECK(success); - BOOST_CHECK(state.IsValid()); - BOOST_CHECK(pblockTemp->block.GetHash() != chainActive.Tip()->GetBlockHash()); - BOOST_CHECK_EQUAL(orig_chain_height,chainActive.Height()); - delete pblockTemp; - -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 72252f00f..d8593e58e 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -27,7 +27,6 @@ BOOST_FIXTURE_TEST_SUITE(claimtriebranching_tests, RegTestingSetup) boost::test_tools::predicate_result is_claim_in_queue(std::string name, const CTransaction &tx) { - CClaimValue val; COutPoint outPoint(tx.GetHash(), 0); int validAtHeight; bool have_claim = pclaimTrie->haveClaimInQueue(name,outPoint,validAtHeight); @@ -84,7 +83,6 @@ best_claim_effective_amount_equals(std::string name, CAmount amount) return true; } } - } CMutableTransaction BuildTransaction(const CMutableTransaction& prev, uint32_t prevout=0, unsigned int numOutputs=1) @@ -123,7 +121,7 @@ bool CreateBlock(CBlockTemplate* pblocktemplate) txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); pblock->vtx[0] = CTransaction(txCoinbase); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - for (int i = 0; ; ++i) + for (uint32_t i = 0; ; ++i) { pblock->nNonce = i; if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) @@ -159,6 +157,7 @@ bool CreateCoinbases(unsigned int num_coinbases, std::vector& coin // Test Fixtures struct ClaimTrieChainFixture{ std::vector coinbase_txs; + std::vector marks; int coinbase_txs_used; unsigned int num_txs; unsigned int num_txs_for_next_block; @@ -181,7 +180,7 @@ struct ClaimTrieChainFixture{ num_txs = 0; coinbase_txs_used = 0; // generate coinbases to spend - CreateCoinbases(20,coinbase_txs); + CreateCoinbases(40,coinbase_txs); } ~ClaimTrieChainFixture() @@ -217,7 +216,6 @@ struct ClaimTrieChainFixture{ return tx; } - //make claim at the current block CMutableTransaction MakeClaim(const CTransaction &prev, std::string name, std::string value, CAmount quantity) @@ -232,6 +230,11 @@ struct ClaimTrieChainFixture{ return tx; } + CMutableTransaction MakeClaim(const CTransaction &prev, std::string name, std::string value) + { + return MakeClaim(prev, name, value, prev.vout[0].nValue); + } + //make support at the current block CMutableTransaction MakeSupport(const CTransaction &prev, const CTransaction &claimtx, std::string name, CAmount quantity) { @@ -268,8 +271,11 @@ struct ClaimTrieChainFixture{ } //create i blocks - void IncrementBlocks(int num_blocks) + void IncrementBlocks(int num_blocks, bool mark = false) { + if (mark) + marks.push_back(chainActive.Height()); + for (int i = 0; i < num_blocks; ++i) { CBlockTemplate *pblocktemplate; @@ -282,14 +288,13 @@ struct ClaimTrieChainFixture{ delete pblocktemplate; num_txs_for_next_block = 0 ; - } - + } } //disconnect i blocks from tip void DecrementBlocks(int num_blocks) { - for(int i = 0; i< num_blocks; i++){ + for(int i = 0; i< num_blocks; i++){ CValidationState state; CBlockIndex* pblockindex = chainActive.Tip(); InvalidateBlock(state, Params().GetConsensus(), pblockindex); @@ -307,6 +312,13 @@ struct ClaimTrieChainFixture{ num_txs_for_next_block = 0; } + // decrement back to last mark + void DecrementBlocks() + { + int mark = marks.back(); + marks.pop_back(); + DecrementBlocks(chainActive.Height() - mark); + } void WriteClearReadClaimTrie() { @@ -317,7 +329,6 @@ struct ClaimTrieChainFixture{ pclaimTrie->clear(); pclaimTrie->ReadFromDisk(true); } - }; @@ -333,7 +344,7 @@ struct ClaimTrieChainFixture{ check that a smaller amount does not win */ -BOOST_AUTO_TEST_CASE(claimtriebranching_claim) +BOOST_AUTO_TEST_CASE(claim_test) { // no competing bids ClaimTrieChainFixture fixture; @@ -390,8 +401,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_claim) BOOST_CHECK(is_best_claim("test",tx6)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx6)); - fixture.DecrementBlocks(10); - + fixture.DecrementBlocks(10); } /* @@ -400,7 +410,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_claim) spending winning claim will make inactive claim winner spending winning claim will empty out claim trie */ -BOOST_AUTO_TEST_CASE(claimtriebranching_spend_claim) +BOOST_AUTO_TEST_CASE(spend_claim_test) { ClaimTrieChainFixture fixture; @@ -457,7 +467,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_spend_claim) check claim with more support wins check support delay */ -BOOST_AUTO_TEST_CASE(claimtriebranching_support) +BOOST_AUTO_TEST_CASE(support_test) { ClaimTrieChainFixture fixture; // check claim with more support wins @@ -501,7 +511,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_support) make sure this doesn't happen in below three tests (https://github.com/lbryio/lbrycrd/issues/77) */ -BOOST_AUTO_TEST_CASE(claimtriebranching_support_on_abandon) +BOOST_AUTO_TEST_CASE(support_on_abandon_test) { ClaimTrieChainFixture fixture; CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); @@ -518,7 +528,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_support_on_abandon) } -BOOST_AUTO_TEST_CASE(claimtriebranching_support_on_abandon_2) +BOOST_AUTO_TEST_CASE(support_on_abandon_2_test) { ClaimTrieChainFixture fixture; CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); @@ -535,7 +545,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_support_on_abandon_2) BOOST_CHECK(is_best_claim("test",tx1)); } -BOOST_AUTO_TEST_CASE(claimtriebranching_update_on_support) +BOOST_AUTO_TEST_CASE(update_on_support_test) { // make sure that support on abandon bug does not affect // updates happening on the same block as a support @@ -555,15 +565,13 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_update_on_support) BOOST_CHECK(is_best_claim("test",tx1)); } - - /* support spend spending suport on winning claim will cause it to lose spending a support on txin[i] where i is not 0 */ -BOOST_AUTO_TEST_CASE(claimtriebranching_support_spend) +BOOST_AUTO_TEST_CASE(support_spend_test) { ClaimTrieChainFixture fixture; @@ -614,7 +622,6 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_support_spend) BOOST_CHECK(is_best_claim("test",tx4)); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx5)); - } /* update @@ -626,7 +633,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_support_spend) */ -BOOST_AUTO_TEST_CASE(claimtriebranching_update) +BOOST_AUTO_TEST_CASE(claimtrie_update_test) { //update preserves claim id ClaimTrieChainFixture fixture; @@ -700,7 +707,6 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_update) fixture.DecrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx7)); fixture.DecrementBlocks(11); - } /* @@ -709,7 +715,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_update) 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(claimtriebranching_expire) +BOOST_AUTO_TEST_CASE(claimtrie_expire_test) { ClaimTrieChainFixture fixture; pclaimTrie->setExpirationTime(5); @@ -767,8 +773,6 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_expire) BOOST_CHECK(is_best_claim("test",u4)); fixture.DecrementBlocks(pclaimTrie->nExpirationTime); BOOST_CHECK(is_best_claim("test",tx6)); - - } /* @@ -819,7 +823,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_get_effective_amount_for_claim) /* * tests for CClaimTrie::getClaimById basic consistency checks */ -BOOST_AUTO_TEST_CASE(claimtriebranching_get_claim_by_id) +BOOST_AUTO_TEST_CASE(get_claim_by_id_test) { ClaimTrieChainFixture fixture; const std::string name = "test"; @@ -869,7 +873,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_get_claim_by_id) check claims do not expire post ExpirationForkHeight check supports work post ExpirationForkHeight */ -BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_claim) +BOOST_AUTO_TEST_CASE(hardfork_claim_test) { ClaimTrieChainFixture fixture; @@ -950,7 +954,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_claim) /* support expiration for hard fork */ -BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_support) +BOOST_AUTO_TEST_CASE(hardfork_support_test) { ClaimTrieChainFixture fixture; @@ -1002,7 +1006,7 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_support) /* claim/support expiration for hard fork, but with checks for disk procedures */ -BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_disktest) +BOOST_AUTO_TEST_CASE(hardfork_disk_test) { ClaimTrieChainFixture fixture; @@ -1064,4 +1068,1941 @@ BOOST_AUTO_TEST_CASE(claimtriebranching_hardfork_disktest) BOOST_CHECK(best_claim_effective_amount_equals("test2",1)); // the support expires one block before } +BOOST_AUTO_TEST_CASE(insert_update_claim_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName1("atest"); + std::string sName2("btest"); + std::string sName3("atest123"); + std::string sValue1("testa"); + std::string sValue2("testb"); + std::string sValue3("123testa"); + + uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); + + + CMutableTransaction tx1 = BuildTransaction(fixture.GetCoinbase()); + tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME + << std::vector(sName1.begin(), sName1.end()) + << std::vector(sValue1.begin(), sValue2.end()) << OP_2DROP << OP_DROP << OP_TRUE; + uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); + COutPoint tx1OutPoint(tx1.GetHash(), 0); + + CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(), sName1, sValue2, tx1.vout[0].nValue - 10001); + uint160 tx7ClaimId = ClaimIdHash(tx7.GetHash(), 0); + COutPoint tx7OutPoint(tx7.GetHash(), 0); + + CClaimValue val; + int nThrowaway; + + // Verify claims (tx7) for uncontrolled names go in immediately + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx7OutPoint); + + // Verify claims for controlled names are delayed, and that the bigger claim wins when inserted + fixture.IncrementBlocks(5); + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(5); // 12 + + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(1); + + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // Verify updates to the best claim get inserted immediately, and others don't. + CMutableTransaction tx3 = fixture.MakeUpdate(tx1, sName1, sValue1, tx1ClaimId, tx1.vout[0].nValue - 10000); + COutPoint tx3OutPoint(tx3.GetHash(), 0); + CMutableTransaction tx9 = fixture.MakeUpdate(tx7, sName1, sValue2, tx7ClaimId, tx7.vout[0].nValue - 10000); + COutPoint tx9OutPoint(tx9.GetHash(), 0); + fixture.IncrementBlocks(1, true); // 14 + + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx1OutPoint)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx7OutPoint)); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx9OutPoint, nThrowaway)); + + // Disconnect all blocks until the first block, and then reattach them, in memory only + + CCoinsViewCache coins(pcoinsTip); + CClaimTrieCache trieCache(pclaimTrie); + CBlockIndex* pindexState = chainActive.Tip(); + CValidationState state; + CBlockIndex* pindex; + for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex=pindex->pprev) + { + CBlock block; + BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); + if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) + { + bool fClean = true; + BOOST_CHECK(DisconnectBlock(block, state, pindex, coins, trieCache, &fClean)); + pindexState = pindex->pprev; + } + } + while (pindex != chainActive.Tip()) + { + pindex = chainActive.Next(pindex); + CBlock block; + BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); + BOOST_CHECK(ConnectBlock(block, state, pindex, coins, trieCache)); + } + + // Roll back the last block, make sure tx1 and tx7 are put back in the trie + fixture.DecrementBlocks(); // 13 + + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + BOOST_CHECK(pclaimTrie->haveClaim(sName1, tx7OutPoint)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->empty()); + + // Roll all the way back, make sure all txs are out of the trie + fixture.DecrementBlocks(); + + BOOST_CHECK(!pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Test undoing a claim before the claim gets into the trie + + // Put tx1 in the chain, then advance a few blocks. + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(10); // 11 + + // Put tx7 in the chain, verify it goes into the queue + fixture.CommitTx(tx7); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // Undo that block and make sure it's not in the queue + fixture.DecrementBlocks(); + + // Make sure it's not in the queue + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Go back to the beginning + fixture.DecrementBlocks(); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Test spend a claim which was just inserted into the trie + + // Immediately spend tx2 with tx4, verify nothing gets put in the trie + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, tx1.vout[0].nValue - 1); + COutPoint tx2OutPoint(tx2.GetHash(), 0); + CMutableTransaction tx4 = fixture.Spend(tx2); + COutPoint tx4OutPoint(tx4.GetHash(), 0); + fixture.IncrementBlocks(1); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.DecrementBlocks(1); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Verify that if a claim in the queue is spent, it does not get into the trie + + // Put tx5 into the chain, advance until it's in the trie for a few blocks + + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2); + COutPoint tx5OutPoint(tx5.GetHash(), 0); + fixture.IncrementBlocks(6, true); + + // Put tx2 into the chain, and then advance a few blocks but not far enough for it to get into the trie + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); + + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName2, tx2OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(3); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // Spend tx2 with tx4, and then advance to where tx2 would be inserted into the trie and verify it hasn't happened + + fixture.CommitTx(tx4); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(5); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaim(sName2, tx2OutPoint)); + + // Undo spending tx2 with tx4, and then advance and verify tx2 is inserted into the trie when it should be + + fixture.DecrementBlocks(); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName2, tx2OutPoint, nThrowaway)); + + fixture.IncrementBlocks(2); + + BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); + BOOST_CHECK(val.outPoint == tx5OutPoint); + BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); + + // Test undoing a spend which involves a claim in the trie + + // spend tx2, which is in the trie, with tx4 + fixture.CommitTx(tx4); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaim(sName2, tx2OutPoint)); + + // undo spending tx2 with tx4, and verify tx2 is back in the trie + fixture.DecrementBlocks(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); + BOOST_CHECK(val.outPoint == tx5OutPoint); + BOOST_CHECK(pclaimTrie->haveClaim(sName2, tx2OutPoint)); + + // roll back to the beginning + fixture.DecrementBlocks(); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Test undoing a spent update which updated a claim still in the queue + + // Create the claim that will cause the others to be in the queue + + fixture.CommitTx(tx7); + fixture.IncrementBlocks(6, true); + + // Create the original claim (tx1) + + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx1OutPoint, nThrowaway)); + + // move forward some, but not far enough for the claim to get into the trie + fixture.IncrementBlocks(2); + + // update the original claim (tx3 spends tx1) + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx1OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx1OutPoint)); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName1, tx3OutPoint, nThrowaway)); + + // spend the update (tx6 spends tx3) + + CMutableTransaction tx6 = fixture.Spend(tx3); + COutPoint tx6OutPoint(tx6.GetHash(), 0); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx3OutPoint)); + + // undo spending the update (undo tx6 spending tx3) + fixture.DecrementBlocks(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // make sure the update (tx3) still goes into effect when it's supposed to + fixture.IncrementBlocks(9); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->haveClaim(sName1, tx3OutPoint)); + + // roll all the way back + fixture.DecrementBlocks(); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Test undoing an spent update which updated the best claim to a name + + // move forward until the original claim is inserted into the trie + + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(5); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // update the original claim (tx3 spends tx1) + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + + // spend the update (tx6 spends tx3) + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // undo spending the update (undo tx6 spending tx3) + fixture.DecrementBlocks(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + + // Test having two updates to a claim in the same transaction + + // Add both txouts (tx8 spends tx3) + CMutableTransaction tx8 = BuildTransaction(tx3, 0, 2); + tx8.vout[0].scriptPubKey = CScript() << OP_UPDATE_CLAIM + << std::vector(sName1.begin(), sName1.end()) + << std::vector(tx1ClaimId.begin(), tx1ClaimId.end()) + << std::vector(sValue1.begin(), sValue1.end()) << OP_2DROP << OP_2DROP << OP_TRUE; + tx8.vout[0].nValue = tx8.vout[0].nValue - 1; + tx8.vout[1].scriptPubKey = CScript() << OP_CLAIM_NAME + << std::vector(sName1.begin(), sName1.end()) + << std::vector(sValue2.begin(), sValue2.end()) << OP_2DROP << OP_DROP << OP_TRUE; + COutPoint tx8OutPoint0(tx8.GetHash(), 0); + COutPoint tx8OutPoint1(tx8.GetHash(), 1); + + fixture.CommitTx(tx8); + fixture.IncrementBlocks(1, true); + + // ensure txout 0 made it into the trie and txout 1 did not + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx8OutPoint0); + + // roll forward until tx8 output 1 gets into the trie + fixture.IncrementBlocks(6); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(1); + + // ensure txout 1 made it into the trie and is now in control + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx8OutPoint1); + + // roll back to before tx8 + fixture.DecrementBlocks(); + + // roll all the way back + fixture.DecrementBlocks(); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // make sure invalid updates don't wreak any havoc + + // put tx1 into the trie + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // advance a few blocks + fixture.IncrementBlocks(5); + + // put in bad tx10 + CMutableTransaction root = fixture.GetCoinbase(); + CMutableTransaction tx10 = fixture.MakeUpdate(root, sName1, sValue1, tx1ClaimId, root.vout[0].nValue); + COutPoint tx10OutPoint(tx10.GetHash(), 0); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll back, make sure nothing bad happens + fixture.DecrementBlocks(); + + // put it back in + fixture.CommitTx(tx10); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // update it + CMutableTransaction tx11 = fixture.MakeUpdate(tx10, sName1, sValue1, tx1ClaimId, tx10.vout[0].nValue); + COutPoint tx11OutPoint(tx11.GetHash(), 0); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(10); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll back to before the update + fixture.DecrementBlocks(); + + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // make sure tx10 would have gotten into the trie, then run tests again + + fixture.IncrementBlocks(10); + + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // update it + fixture.CommitTx(tx11); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // make sure tx11 would have gotten into the trie + + fixture.IncrementBlocks(20); + + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx11OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx11OutPoint)); + BOOST_CHECK(!pclaimTrie->haveClaimInQueue(sName1, tx10OutPoint, nThrowaway)); + BOOST_CHECK(!pclaimTrie->haveClaim(sName1, tx10OutPoint)); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll all the way back + fixture.DecrementBlocks(); + + // Put tx10 and tx11 in without tx1 in + fixture.CommitTx(tx10); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // update with tx11 + fixture.CommitTx(tx11); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll back to before tx11 + fixture.DecrementBlocks(); + + // spent tx10 with tx12 instead which is not a claim operation of any kind + CMutableTransaction tx12 = BuildTransaction(tx10); + COutPoint tx12OutPoint(tx12.GetHash(), 0); + + fixture.IncrementBlocks(1); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll all the way back + fixture.DecrementBlocks(); + + // make sure all claim for names which exist in the trie but have no + // values get inserted immediately + + CMutableTransaction tx13 = fixture.MakeClaim(fixture.GetCoinbase(), sName3, sValue3, 1); + fixture.IncrementBlocks(1, true); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // roll back + fixture.DecrementBlocks(); +} + +BOOST_AUTO_TEST_CASE(claim_expiration_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName("atest"); + std::string sValue("testa"); + + int nThrowaway; + + // set expiration time to 200 blocks after the block is created + pclaimTrie->setExpirationTime(200); + + // 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(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // advance until the expiration event occurs. verify the expiration event occurs on time. + + fixture.IncrementBlocks(199); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + fixture.IncrementBlocks(1); // 201 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->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(100); // 301 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + fixture.DecrementBlocks(101); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // advance until the expiration event occurs. verify the expiration event occurs on time. + fixture.IncrementBlocks(1); // 201 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again. + fixture.DecrementBlocks(2); // 199 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // roll back some more. + fixture.DecrementBlocks(99); // 100 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // spend the claim. verify the expiration event is removed. + CMutableTransaction tx2 = fixture.Spend(tx1); + COutPoint tx2OutPoint(tx2.GetHash(), 0); + + fixture.IncrementBlocks(1); // 101 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // roll back the spend. verify the expiration event is returned. + fixture.DecrementBlocks(1); // 100 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // advance until the expiration event occurs. verify the event occurs on time. + fixture.IncrementBlocks(100); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + fixture.IncrementBlocks(1); // 201 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // spend the expired claim + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 202 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // undo the spend. verify everything remains empty. + fixture.DecrementBlocks(1); // 201 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // roll back to before the expiration event. verify the claim is reinserted. verify the expiration event is scheduled again. + fixture.DecrementBlocks(1); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // verify the expiration event happens at the right time again + fixture.IncrementBlocks(1); // 201 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); + + // roll back to before the expiration event. verify it gets reinserted and expiration gets scheduled. + fixture.DecrementBlocks(1); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->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(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->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(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->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(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + // advance until tx3 is valid, ensure tx1 is winning + fixture.IncrementBlocks(4); // 10 + + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName, tx3OutPoint, nThrowaway)); + + fixture.IncrementBlocks(1); // 11 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // 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(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // advance until the expiration event occurs. verify the expiration event occurs on time. + fixture.IncrementBlocks(189, true); // 200 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + + fixture.IncrementBlocks(1); // 201 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + + // spend tx1 + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 202 + + // roll back to when tx1 and tx3 are in the trie and tx1 is winning + fixture.DecrementBlocks(); // 11 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + + // roll all the way back + fixture.DecrementBlocks(); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->expirationQueueEmpty()); +} + +BOOST_AUTO_TEST_CASE(claimtrienode_serialize_unserialize) +{ + CDataStream ss(SER_DISK, 0); + + uint160 hash160; + + CClaimTrieNode n1; + CClaimTrieNode n2; + CClaimValue throwaway; + + ss << n1; + ss >> n2; + BOOST_CHECK(n1 == n2); + + n1.hash.SetHex("0000000000000000000000000000000000000000000000000000000000000001"); + BOOST_CHECK(n1 != n2); + ss << n1; + ss >> n2; + BOOST_CHECK(n1 == n2); + + n1.hash.SetHex("a79e8a5b28f7fa5e8836a4b48da9988bdf56ce749f81f413cb754f963a516200"); + BOOST_CHECK(n1 != n2); + ss << n1; + ss >> n2; + BOOST_CHECK(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(n1 == n2); + + n1.insertClaim(v2); + BOOST_CHECK(n1 != n2); + ss << n1; + ss >> n2; + BOOST_CHECK(n1 == n2); + + n1.removeClaim(v1.outPoint, throwaway); + BOOST_CHECK(n1 != n2); + ss << n1; + ss >> n2; + BOOST_CHECK(n1 == n2); + + n1.removeClaim(v2.outPoint, throwaway); + BOOST_CHECK(n1 != n2); + ss << n1; + ss >> n2; + BOOST_CHECK(n1 == n2); +} + +BOOST_AUTO_TEST_CASE(invalid_claimid_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName("atest"); + std::string sValue1("testa"); + std::string sValue2("testb"); + + CClaimValue val; + std::vector blocks_to_invalidate; + + // Verify that supports expire + + // Create a 1 LBC claim (tx1) + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Make sure it gets way in there + fixture.IncrementBlocks(100); // 101 + + // Create a 5 LBC claim (tx2) + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5); + fixture.IncrementBlocks(1); // 102 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // Create a tx with a bogus claimId + uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); + CMutableTransaction tx3 = fixture.MakeUpdate(tx2, sName, sValue2, tx1ClaimId, 4); + CMutableTransaction tx4 = BuildTransaction(tx3); + COutPoint tx4OutPoint(tx4.GetHash(), 0); + + fixture.IncrementBlocks(1); // 103 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Verify it's not in the claim trie + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); + + // Update the tx with the bogus claimId + fixture.CommitTx(tx4); + fixture.IncrementBlocks(1); // 104 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx4.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + + // Verify it's not in the claim trie + + BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // Go forward a few hundred blocks and verify it's not in there + + fixture.IncrementBlocks(300); // 404 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->haveClaim(sName, tx4OutPoint)); + + // go all the way back + fixture.DecrementBlocks(404); + BOOST_CHECK(pclaimTrie->empty()); +} + + +BOOST_AUTO_TEST_CASE(supporting_claims_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName("atest"); + std::string sValue1("testa"); + std::string sValue2("testb"); + + CClaimValue val; + + // Test 1: create 1 LBC claim (tx1), create 5 LBC support (tx3), create 5 LBC claim (tx2) + // Verify that tx1 retains control throughout + // spend tx3, verify that tx2 gains control + // roll back to before tx3 is spent, verify tx1 regains control + // update tx1 with tx7, verify tx7 has control + // roll back to before tx7 is inserted, verify tx1 regains control + // roll back to before tx2 is valid, spend tx3 + // advance to tx2 valid, verify tx2 gains control + // roll back to before tx3 is valid, spend tx3 + // advance to tx2 valid, verify tx2 gains control + // roll back to insertion of tx3, and don't insert it + // insert tx2, advance until it is valid, verify tx2 gains control + + // Put tx1 in the blockchain + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // advance a few blocks + fixture.IncrementBlocks(5); // 6 + + // Put tx3 into the blockchain + CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName, 5); + fixture.IncrementBlocks(1); // 7 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // advance a few blocks + fixture.IncrementBlocks(3); // 10 + + // Put tx2 into the blockchain + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5); + fixture.IncrementBlocks(1); // 11 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // advance until tx2 is valid + fixture.IncrementBlocks(9); // 20 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(1); // 21 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + CMutableTransaction tx4 = BuildTransaction(tx1); + CMutableTransaction tx5 = BuildTransaction(tx2); + CMutableTransaction tx6 = BuildTransaction(tx3); + + // spend tx3 + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1); // 22 + + // verify tx2 gains control + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // unspend tx3, verify tx1 regains control + fixture.DecrementBlocks(1); // 21 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // update tx1 with tx7, verify tx7 has control + uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); + CMutableTransaction tx7 = fixture.MakeUpdate(tx1, sName, sValue1, claimId, tx1.vout[0].nValue); + fixture.IncrementBlocks(1); // 22 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx7.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx7.GetHash()); + + // roll back to before tx7 is inserted, verify tx1 has control + fixture.DecrementBlocks(1); // 21 + + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // roll back to before tx2 is valid + fixture.DecrementBlocks(1); // 20 + + // spend tx3 + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1); // 21 + + // Verify tx2 gains control + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // roll back to before tx3 is inserted + fixture.DecrementBlocks(15); // 6 + + // advance a few blocks + fixture.IncrementBlocks(4); // 10 + + // Put tx2 into the blockchain + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 11 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + // advance until tx2 is valid + fixture.IncrementBlocks(9); // 20 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + + fixture.IncrementBlocks(2); // 22 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(22); // 0 + + // Make sure that when a support in the queue gets spent and then the spend is + // undone, it goes back into the queue in the right spot + + // put tx2 and tx1 into the trie + + fixture.CommitTx(tx1); + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // advance a few blocks + fixture.IncrementBlocks(5); // 6 + + // put tx3 into the support queue + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); // 7 + + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + + // advance a couple of blocks + fixture.IncrementBlocks(2); // 9 + + // spend tx3 + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1); // 10 + + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // undo spend of tx3, verify it gets back in the right place in the queue + fixture.DecrementBlocks(1); // 9 + + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + + fixture.IncrementBlocks(4); // 13 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // spend tx3 again, then undo the spend and roll back until it's back in the queue + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1); // 14 + + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + fixture.DecrementBlocks(1); // 13 + + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(13); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); +} + +BOOST_AUTO_TEST_CASE(supporting_claims2_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName("atest"); + std::string sValue1("testa"); + std::string sValue2("testb"); + + CClaimValue val; + int nThrowaway; + + // Test 2: create 1 LBC claim (tx1), create 5 LBC claim (tx2), create 5 LBC support (tx3) + // Verify that tx1 loses control when tx2 becomes valid, and then tx1 gains control when tx3 becomes valid + // Then, verify that tx2 regains control when A) tx3 is spent and B) tx3 is undone + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // advance a few blocks + fixture.IncrementBlocks(4); // 5 + + // put tx2 into the blockchain + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5); + fixture.IncrementBlocks(1); // 6 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx2.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // advance until tx2 is in the trie + fixture.IncrementBlocks(4); // 10 + + BOOST_CHECK(!pclaimTrie->queueEmpty()); + COutPoint tx2cp(tx2.GetHash(), 0); + BOOST_CHECK(pclaimTrie->haveClaimInQueue(sName, tx2cp, nThrowaway)); + + fixture.IncrementBlocks(1); // 11 + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // advance a few blocks + fixture.IncrementBlocks(4); // 15 + + // put tx3 into the blockchain + + CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName, 5); + fixture.IncrementBlocks(1); // 16 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx3.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + + // advance until tx3 is valid + fixture.IncrementBlocks(4); // 20 + + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + + fixture.IncrementBlocks(1); // 21 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + CMutableTransaction tx4 = BuildTransaction(tx1); + CMutableTransaction tx5 = BuildTransaction(tx2); + CMutableTransaction tx6 = BuildTransaction(tx3); + + // spend tx3 + fixture.CommitTx(tx6); + fixture.IncrementBlocks(1); // 22 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // undo spend + fixture.DecrementBlocks(1); // 21 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // roll back to before tx3 is valid + fixture.DecrementBlocks(1); // 20 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(20); // 0 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Test 4: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3) + // Verify that tx1 retains control throughout + + // put tx1 into the blockchain + + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance a few blocks + fixture.IncrementBlocks(5);// 6 + + // put tx2 into the blockchain + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 7 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance some, insert tx3, should be immediately valid + fixture.IncrementBlocks(2); // 9 + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); // 10 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance until tx2 is valid, verify tx1 retains control + fixture.IncrementBlocks(3); // 13 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + BOOST_CHECK(pclaimTrie->haveClaim(sName, tx2cp)); + + // roll all the way back + fixture.DecrementBlocks(13); // 0 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Test 5: create 5 LBC claim (tx2), wait till valid, create 1 LBC claim (tx1), create 5 LBC support (tx3) + // Verify that tx2 retains control until support becomes valid + + // insert tx2 into the blockchain + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // advance a few blocks + fixture.IncrementBlocks(9); // 10 + + // insert tx1 into the block chain + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); // 11 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // advance some + fixture.IncrementBlocks(5); // 16 + + // insert tx3 into the block chain + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); // 17 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // advance until tx1 is valid + fixture.IncrementBlocks(5); // 22 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + COutPoint tx1cp(tx1.GetHash(), 0); + BOOST_CHECK(pclaimTrie->haveClaim(sName, tx1cp)); + + // advance until tx3 is valid + fixture.IncrementBlocks(11); // 33 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(33); // 0 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + + // Test 6: create 1 LBC claim (tx1), wait till valid, create 5 LBC claim (tx2), create 5 LBC support (tx3), spend tx1 + // Verify that tx1 retains control until it is spent + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance a few blocks + fixture.IncrementBlocks(5); // 6 + + // insert tx2 into the blockchain + fixture.CommitTx(tx2); + fixture.IncrementBlocks(1); // 7 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance some, insert tx3 + fixture.IncrementBlocks(2); // 9 + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); // 10 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // advance until tx2 is valid + fixture.IncrementBlocks(3); // 13 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // spend tx1 + fixture.CommitTx(tx4); + fixture.IncrementBlocks(1); // 14 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // undo spend of tx1 + fixture.DecrementBlocks(1); // 13 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(13); // 0 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Test 7: create 1 LBC claim (tx1), wait till valid, create 5 LBC support (tx3), spend tx1 + // Verify name trie is empty + + // insert tx1 into blockchain + fixture.CommitTx(tx1); + fixture.IncrementBlocks(1); // 1 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // insert tx3 into blockchain + fixture.CommitTx(tx3); + fixture.IncrementBlocks(1); // 2 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // spent tx1 + fixture.CommitTx(tx4); + fixture.IncrementBlocks(1); // 3 + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // roll all the way back + fixture.DecrementBlocks(3); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); +} + +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 blocks_to_invalidate; + + pclaimTrie->setExpirationTime(200); + + // 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 201 + + BOOST_CHECK(pcoinsTip->HaveCoins(tx1.GetHash())); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Create a 5 LBC support (tx3) + CMutableTransaction tx3 = fixture.MakeSupport(fixture.GetCoinbase(), tx1, sName, 5); + fixture.IncrementBlocks(1); // 2, expires at 202 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Advance some, then insert 5 LBC claim (tx2) + fixture.IncrementBlocks(49); // 51 + + CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue2, 5); + fixture.IncrementBlocks(1); // 52, activating in (52 - 2) / 1 = 50block (but not then active because support still holds tx1 up) + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + // Advance until tx2 is valid + fixture.IncrementBlocks(50); // 102 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(!pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + fixture.IncrementBlocks(1); // 103 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + + // 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(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + + // Advance until the support expires + fixture.IncrementBlocks(97); // 201 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + + fixture.IncrementBlocks(1); // 202 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // undo the block, make sure control goes back + fixture.DecrementBlocks(1); // 201 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + + // redo the block, make sure it expires again + fixture.IncrementBlocks(1); // 202 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // roll back some, spend the support, and make sure nothing unexpected + // happens at the time the support should have expired + + fixture.DecrementBlocks(49); // 153 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + + fixture.Spend(tx3); + fixture.IncrementBlocks(1); // 154 + + blocks_to_invalidate.push_back(chainActive.Tip()->GetBlockHash()); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + fixture.IncrementBlocks(50); // 204 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + //undo the spend, and make sure it still expires on time + + fixture.DecrementBlocks(51); // 153 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + + fixture.IncrementBlocks(48); // 201 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(!pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + + fixture.IncrementBlocks(1); // 202 + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); + BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + + // roll all the way back + fixture.DecrementBlocks(202); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->supportEmpty()); + BOOST_CHECK(pclaimTrie->supportQueueEmpty()); +} + +bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::string& name) +{ + uint256 previousComputedHash; + std::string computedReverseName; + bool verifiedValue = false; + + for (std::vector::const_reverse_iterator itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) + { + bool foundChildInChain = false; + std::vector vchToHash; + for (std::vector >::const_iterator 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 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(pclaimTrie->queueEmpty()); + BOOST_CHECK(pclaimTrie->getInfoForName(sName1, val)); + BOOST_CHECK(val.outPoint == tx1OutPoint); + BOOST_CHECK(pclaimTrie->getInfoForName(sName2, val)); + BOOST_CHECK(val.outPoint == tx2OutPoint); + BOOST_CHECK(pclaimTrie->getInfoForName(sName3, val)); + BOOST_CHECK(val.outPoint == tx3OutPoint); + BOOST_CHECK(pclaimTrie->getInfoForName(sName4, val)); + BOOST_CHECK(val.outPoint == tx4OutPoint); + + CClaimTrieCache cache(pclaimTrie); + + CClaimTrieProof proof; + + proof = cache.getProofForName(sName1); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); + BOOST_CHECK(proof.outPoint == tx1OutPoint); + + proof = cache.getProofForName(sName2); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); + BOOST_CHECK(proof.outPoint == tx2OutPoint); + + proof = cache.getProofForName(sName3); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); + BOOST_CHECK(proof.outPoint == tx3OutPoint); + + proof = cache.getProofForName(sName4); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); + BOOST_CHECK(proof.outPoint == tx4OutPoint); + + proof = cache.getProofForName(sName5); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); + BOOST_CHECK(proof.hasValue == false); + + proof = cache.getProofForName(sName6); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); + BOOST_CHECK(proof.hasValue == false); + + proof = cache.getProofForName(sName7); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); + BOOST_CHECK(proof.hasValue == false); + + CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(), sName7, sValue4); + COutPoint tx5OutPoint(tx5.GetHash(), 0); + + fixture.IncrementBlocks(1); + + BOOST_CHECK(pclaimTrie->getInfoForName(sName7, val)); + BOOST_CHECK(val.outPoint == tx5OutPoint); + + cache = CClaimTrieCache(pclaimTrie); + + proof = cache.getProofForName(sName1); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName1)); + BOOST_CHECK(proof.outPoint == tx1OutPoint); + + proof = cache.getProofForName(sName2); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName2)); + BOOST_CHECK(proof.outPoint == tx2OutPoint); + + proof = cache.getProofForName(sName3); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName3)); + BOOST_CHECK(proof.outPoint == tx3OutPoint); + + proof = cache.getProofForName(sName4); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName4)); + BOOST_CHECK(proof.outPoint == tx4OutPoint); + + proof = cache.getProofForName(sName5); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName5)); + BOOST_CHECK(proof.hasValue == false); + + proof = cache.getProofForName(sName6); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName6)); + BOOST_CHECK(proof.hasValue == false); + + proof = cache.getProofForName(sName7); + BOOST_CHECK(verify_proof(proof, chainActive.Tip()->hashClaimTrie, sName7)); + BOOST_CHECK(proof.outPoint == tx5OutPoint); + + fixture.DecrementBlocks(); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->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); + + CBlockTemplate *pblockTemp; + BOOST_CHECK(pblockTemp = CreateNewBlock(Params(), tx1.vout[0].scriptPubKey)); + pblockTemp->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); + pblockTemp->block.nVersion = 1; + pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing; + CMutableTransaction txCoinbase(pblockTemp->block.vtx[0]); + txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(chainActive.Height()); + txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); + pblockTemp->block.vtx[0] = CTransaction(txCoinbase); + pblockTemp->block.hashMerkleRoot = BlockMerkleRoot(pblockTemp->block); + //create bogus hash + + uint256 bogusHashClaimTrie; + bogusHashClaimTrie.SetHex("aaa"); + pblockTemp->block.hashClaimTrie = bogusHashClaimTrie; + + for (int i = 0; ; ++i) + { + pblockTemp->block.nNonce = i; + if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) + { + break; + } + } + CValidationState state; + bool success = ProcessNewBlock(state, Params(), NULL, &pblockTemp->block, true, NULL); + // will process , but will not be connected + BOOST_CHECK(success); + BOOST_CHECK(state.IsValid()); + BOOST_CHECK(pblockTemp->block.GetHash() != chainActive.Tip()->GetBlockHash()); + BOOST_CHECK_EQUAL(orig_chain_height,chainActive.Height()); + delete pblockTemp; +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/claimtriecache_tests.cpp b/src/test/claimtriecache_tests.cpp index 15ff033f3..e94624268 100644 --- a/src/test/claimtriecache_tests.cpp +++ b/src/test/claimtriecache_tests.cpp @@ -34,10 +34,27 @@ 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::max(); + tx.vout[0].scriptPubKey = CScript(); + tx.vout[0].nValue = 0; + + return tx; +} + BOOST_FIXTURE_TEST_SUITE(claimtriecache_tests, RegTestingSetup) -BOOST_AUTO_TEST_CASE(merklehash_test) +BOOST_AUTO_TEST_CASE(merkle_hash_single_test) { // check empty trie uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); @@ -50,7 +67,127 @@ BOOST_AUTO_TEST_CASE(merklehash_test) BOOST_CHECK(one == cc.getMerkleHash()); } -BOOST_AUTO_TEST_CASE(recursiveprune_test) +BOOST_AUTO_TEST_CASE(merkle_hash_multiple_test) +{ + CClaimValue unused; + uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + uint160 hash160; + CMutableTransaction tx1 = BuildTransaction(hash0); + COutPoint tx1OutPoint(tx1.GetHash(), 0); + CMutableTransaction tx2 = BuildTransaction(tx1.GetHash()); + COutPoint tx2OutPoint(tx2.GetHash(), 0); + CMutableTransaction tx3 = BuildTransaction(tx2.GetHash()); + COutPoint tx3OutPoint(tx3.GetHash(), 0); + CMutableTransaction tx4 = BuildTransaction(tx3.GetHash()); + COutPoint tx4OutPoint(tx4.GetHash(), 0); + CMutableTransaction tx5 = BuildTransaction(tx4.GetHash()); + COutPoint tx5OutPoint(tx5.GetHash(), 0); + CMutableTransaction tx6 = BuildTransaction(tx5.GetHash()); + COutPoint tx6OutPoint(tx6.GetHash(), 0); + + uint256 hash1; + hash1.SetHex("71c7b8d35b9a3d7ad9a1272b68972979bbd18589f1efe6f27b0bf260a6ba78fa"); + + uint256 hash2; + hash2.SetHex("c4fc0e2ad56562a636a0a237a96a5f250ef53495c2cb5edd531f087a8de83722"); + + uint256 hash3; + hash3.SetHex("baf52472bd7da19fe1e35116cfb3bd180d8770ffbe3ae9243df1fb58a14b0975"); + + uint256 hash4; + hash4.SetHex("c73232a755bf015f22eaa611b283ff38100f2a23fb6222e86eca363452ba0c51"); + + BOOST_CHECK(pclaimTrie->empty()); + + CClaimTrieCache ntState(pclaimTrie, false); + ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200)); + ntState.insertClaimIntoTrie(std::string("test2"), CClaimValue(tx2OutPoint, hash160, 50, 100, 200)); + + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(!ntState.empty()); + BOOST_CHECK(ntState.getMerkleHash() == hash1); + + ntState.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); + BOOST_CHECK(ntState.getMerkleHash() == hash1); + ntState.insertClaimIntoTrie(std::string("tes"), CClaimValue(tx4OutPoint, hash160, 50, 100, 200)); + BOOST_CHECK(ntState.getMerkleHash() == hash2); + ntState.insertClaimIntoTrie(std::string("testtesttesttest"), CClaimValue(tx5OutPoint, hash160, 50, 100, 200)); + ntState.removeClaimFromTrie(std::string("testtesttesttest"), tx5OutPoint, unused); + BOOST_CHECK(ntState.getMerkleHash() == hash2); + ntState.flush(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState1(pclaimTrie, false); + ntState1.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); + ntState1.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused); + ntState1.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); + ntState1.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); + + BOOST_CHECK(ntState1.getMerkleHash() == hash0); + + CClaimTrieCache ntState2(pclaimTrie, false); + ntState2.insertClaimIntoTrie(std::string("abab"), CClaimValue(tx6OutPoint, hash160, 50, 100, 200)); + ntState2.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); + + BOOST_CHECK(ntState2.getMerkleHash() == hash3); + + ntState2.flush(); + + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash3); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState3(pclaimTrie, false); + ntState3.insertClaimIntoTrie(std::string("test"), CClaimValue(tx1OutPoint, hash160, 50, 100, 200)); + BOOST_CHECK(ntState3.getMerkleHash() == hash4); + ntState3.flush(); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash4); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState4(pclaimTrie, false); + ntState4.removeClaimFromTrie(std::string("abab"), tx6OutPoint, unused); + BOOST_CHECK(ntState4.getMerkleHash() == hash2); + ntState4.flush(); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState5(pclaimTrie, false); + ntState5.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); + + BOOST_CHECK(ntState5.getMerkleHash() == hash2); + ntState5.flush(); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState6(pclaimTrie, false); + ntState6.insertClaimIntoTrie(std::string("test"), CClaimValue(tx3OutPoint, hash160, 50, 101, 201)); + + BOOST_CHECK(ntState6.getMerkleHash() == hash2); + ntState6.flush(); + BOOST_CHECK(!pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash2); + BOOST_CHECK(pclaimTrie->checkConsistency()); + + CClaimTrieCache ntState7(pclaimTrie, false); + ntState7.removeClaimFromTrie(std::string("test"), tx3OutPoint, unused); + ntState7.removeClaimFromTrie(std::string("test"), tx1OutPoint, unused); + ntState7.removeClaimFromTrie(std::string("tes"), tx4OutPoint, unused); + ntState7.removeClaimFromTrie(std::string("test2"), tx2OutPoint, unused); + + BOOST_CHECK(ntState7.getMerkleHash() == hash0); + ntState7.flush(); + BOOST_CHECK(pclaimTrie->empty()); + BOOST_CHECK(pclaimTrie->getMerkleHash() == hash0); + BOOST_CHECK(pclaimTrie->checkConsistency()); +} + +BOOST_AUTO_TEST_CASE(recursive_prune_test) { CClaimTrieCacheTest cc(pclaimTrie); BOOST_CHECK_EQUAL(0, cc.cacheSize()); -- 2.45.2 From c77a1cd708b443a9c2b3708afd8eab70b1fac3ad Mon Sep 17 00:00:00 2001 From: Brannon King Date: Thu, 26 Jul 2018 16:20:03 -0600 Subject: [PATCH 2/3] added counts & hash checks to tests also ran the code format tool --- src/claimtrie.cpp | 2 +- src/test/claimtriebranching_tests.cpp | 177 +++++++++++++++----------- 2 files changed, 104 insertions(+), 75 deletions(-) diff --git a/src/claimtrie.cpp b/src/claimtrie.cpp index 743bda4ed..2f43212e3 100644 --- a/src/claimtrie.cpp +++ b/src/claimtrie.cpp @@ -2681,7 +2681,7 @@ bool CClaimTrieCache::forkForExpirationChange(bool increment) const if (pcursor->GetKey(key)) { int height = key.second; - // if we've looked throught this in dirtyExprirationQueueRows, don't use it + // if we've looked through this in dirtyExprirationQueueRows, don't use it // because its stale if ((key.first == EXP_QUEUE_ROW) & (dirtyHeights.count(height) == 0)) { diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index d8593e58e..7b144be4f 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -121,8 +121,7 @@ bool CreateBlock(CBlockTemplate* pblocktemplate) txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); pblock->vtx[0] = CTransaction(txCoinbase); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); - for (uint32_t i = 0; ; ++i) - { + for (uint32_t i = 0;; ++i) { pblock->nNonce = i; if (CheckProofOfWork(pblock->GetPoWHash(), pblock->nBits, Params().GetConsensus())) { @@ -179,8 +178,8 @@ struct ClaimTrieChainFixture{ num_txs_for_next_block = 0; num_txs = 0; coinbase_txs_used = 0; - // generate coinbases to spend - CreateCoinbases(40,coinbase_txs); + // generate coinbases to spend + CreateCoinbases(40, coinbase_txs); } ~ClaimTrieChainFixture() @@ -230,7 +229,7 @@ struct ClaimTrieChainFixture{ return tx; } - CMutableTransaction MakeClaim(const CTransaction &prev, std::string name, std::string value) + CMutableTransaction MakeClaim(const CTransaction& prev, std::string name, std::string value) { return MakeClaim(prev, name, value, prev.vout[0].nValue); } @@ -270,7 +269,7 @@ struct ClaimTrieChainFixture{ return tx; } - //create i blocks + //create i blocks void IncrementBlocks(int num_blocks, bool mark = false) { if (mark) @@ -306,10 +305,9 @@ struct ClaimTrieChainFixture{ { BOOST_FAIL("removing block failed"); } - } mempool.clear(); - num_txs_for_next_block = 0; + num_txs_for_next_block = 0; } // decrement back to last mark @@ -354,17 +352,18 @@ BOOST_AUTO_TEST_CASE(claim_test) fixture.DecrementBlocks(1); BOOST_CHECK(!is_best_claim("test",tx1)); - // there is a competing bid inserted same height CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); CMutableTransaction tx3 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx3)); + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(1); BOOST_CHECK(!is_best_claim("test",tx2)); BOOST_CHECK(!is_best_claim("test",tx3)); + BOOST_CHECK_EQUAL(0U, pclaimTrie->getClaimsForName("test").claims.size()); // make two claims , one older CMutableTransaction tx4 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",1); @@ -376,6 +375,7 @@ BOOST_AUTO_TEST_CASE(claim_test) BOOST_CHECK(is_best_claim("test",tx4)); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx4)); + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx4)); @@ -392,9 +392,10 @@ BOOST_AUTO_TEST_CASE(claim_test) CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); fixture.IncrementBlocks(1); BOOST_CHECK(is_claim_in_queue("test",tx7)); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test",tx6)); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx7)); + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); fixture.DecrementBlocks(10); BOOST_CHECK(is_claim_in_queue("test",tx7)); @@ -562,7 +563,7 @@ BOOST_AUTO_TEST_CASE(update_on_support_test) BOOST_CHECK(best_claim_effective_amount_equals("test",2)); fixture.DecrementBlocks(1); - BOOST_CHECK(is_best_claim("test",tx1)); + BOOST_CHECK(is_best_claim("test", tx1)); } /* @@ -596,7 +597,7 @@ BOOST_AUTO_TEST_CASE(support_spend_test) CMutableTransaction s2 = fixture.MakeSupport(fixture.GetCoinbase(),tx5,"test",2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx5)); - + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); // build the spend where s2 is sppent on txin[1] and tx3 is spent on txin[0] uint32_t prevout = 0; @@ -661,14 +662,16 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) CMutableTransaction u3 = fixture.MakeUpdate(tx3,"test","one",ClaimIdHash(tx3.GetHash(),0),2); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",u3)); - fixture.DecrementBlocks(11); + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); + fixture.DecrementBlocks(11); // losing update on winning claim happens without delay CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx5)); - CMutableTransaction u4 = fixture.MakeUpdate(tx5,"test","one",ClaimIdHash(tx5.GetHash(),0),1); + BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); + CMutableTransaction u4 = fixture.MakeUpdate(tx5,"test","one",ClaimIdHash(tx5.GetHash(),0),1); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx6)); @@ -704,7 +707,7 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx)); - fixture.DecrementBlocks(10); + fixture.DecrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx7)); fixture.DecrementBlocks(11); } @@ -995,7 +998,7 @@ BOOST_AUTO_TEST_CASE(hardfork_support_test) // check that the support expires as expected fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork); - BOOST_CHECK(is_best_claim("test",u2)); + BOOST_CHECK(is_best_claim("test", u2)); fixture.DecrementBlocks(fixture.extendedExpiration - blocks_before_fork); fixture.IncrementBlocks(fixture.extendedExpiration - blocks_before_fork - 1); BOOST_CHECK(is_best_claim("test",u1)); @@ -1057,15 +1060,15 @@ BOOST_AUTO_TEST_CASE(hardfork_disk_test) // increment to original expiration, should not be expired fixture.IncrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); BOOST_CHECK(is_best_claim("test2", u2)); - BOOST_CHECK(best_claim_effective_amount_equals("test2",2)); + BOOST_CHECK(best_claim_effective_amount_equals("test2", 2)); fixture.DecrementBlocks(fixture.originalExpiration - height_of_update_before_expiration); // increment to extended expiration, should be expired and not one block before fixture.IncrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration); BOOST_CHECK(!is_best_claim("test2", u2)); fixture.DecrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration); - fixture.IncrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration-1); + fixture.IncrementBlocks(fixture.extendedExpiration - height_of_update_before_expiration - 1); BOOST_CHECK(is_best_claim("test2", u2)); - BOOST_CHECK(best_claim_effective_amount_equals("test2",1)); // the support expires one block before + BOOST_CHECK(best_claim_effective_amount_equals("test2", 1)); // the support expires one block before } BOOST_AUTO_TEST_CASE(insert_update_claim_test) @@ -1085,8 +1088,8 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) CMutableTransaction tx1 = BuildTransaction(fixture.GetCoinbase()); tx1.vout[0].scriptPubKey = CScript() << OP_CLAIM_NAME - << std::vector(sName1.begin(), sName1.end()) - << std::vector(sValue1.begin(), sValue2.end()) << OP_2DROP << OP_DROP << OP_TRUE; + << std::vector(sName1.begin(), sName1.end()) + << std::vector(sValue1.begin(), sValue2.end()) << OP_2DROP << OP_DROP << OP_TRUE; uint160 tx1ClaimId = ClaimIdHash(tx1.GetHash(), 0); COutPoint tx1OutPoint(tx1.GetHash(), 0); @@ -1141,19 +1144,16 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) CBlockIndex* pindexState = chainActive.Tip(); CValidationState state; CBlockIndex* pindex; - for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex=pindex->pprev) - { + for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { CBlock block; BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); - if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) - { + if (pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { bool fClean = true; BOOST_CHECK(DisconnectBlock(block, state, pindex, coins, trieCache, &fClean)); pindexState = pindex->pprev; } } - while (pindex != chainActive.Tip()) - { + while (pindex != chainActive.Tip()) { pindex = chainActive.Next(pindex); CBlock block; BOOST_CHECK(ReadBlockFromDisk(block, pindex, Params().GetConsensus())); @@ -1214,7 +1214,6 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) CMutableTransaction tx2 = fixture.MakeClaim(fixture.GetCoinbase(), sName2, sValue2, tx1.vout[0].nValue - 1); COutPoint tx2OutPoint(tx2.GetHash(), 0); CMutableTransaction tx4 = fixture.Spend(tx2); - COutPoint tx4OutPoint(tx4.GetHash(), 0); fixture.IncrementBlocks(1); BOOST_CHECK(pclaimTrie->empty()); @@ -1334,7 +1333,6 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) // spend the update (tx6 spends tx3) CMutableTransaction tx6 = fixture.Spend(tx3); - COutPoint tx6OutPoint(tx6.GetHash(), 0); fixture.IncrementBlocks(1, true); BOOST_CHECK(!pclaimTrie->empty()); @@ -1562,7 +1560,6 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) // spent tx10 with tx12 instead which is not a claim operation of any kind CMutableTransaction tx12 = BuildTransaction(tx10); - COutPoint tx12OutPoint(tx12.GetHash(), 0); fixture.IncrementBlocks(1); @@ -1591,6 +1588,23 @@ BOOST_AUTO_TEST_CASE(insert_update_claim_test) fixture.DecrementBlocks(); } +BOOST_AUTO_TEST_CASE(basic_merkle_test) +{ + ClaimTrieChainFixture fixture; + + std::string sName("atest"); + std::string sValue("testa"); + + CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue, 10); + fixture.IncrementBlocks(20); + uint256 tx1MerkleHash = pclaimTrie->getMerkleHash(); + fixture.DecrementBlocks(20); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); + fixture.CommitTx(tx1); + fixture.IncrementBlocks(20); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); +} + BOOST_AUTO_TEST_CASE(claim_expiration_test) { ClaimTrieChainFixture fixture; @@ -1662,8 +1676,6 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test) // spend the claim. verify the expiration event is removed. CMutableTransaction tx2 = fixture.Spend(tx1); - COutPoint tx2OutPoint(tx2.GetHash(), 0); - fixture.IncrementBlocks(1); // 101 BOOST_CHECK(pclaimTrie->empty()); @@ -1768,6 +1780,7 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test) BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint == tx1OutPoint); + uint256 tx1MerkleHash = pclaimTrie->getMerkleHash(); // roll back to before tx3 is valid fixture.DecrementBlocks(1); // 10 @@ -1780,6 +1793,7 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test) BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint == tx1OutPoint); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); // advance until the expiration event occurs. verify the expiration event occurs on time. fixture.IncrementBlocks(189, true); // 200 @@ -1795,6 +1809,7 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test) BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint == tx3OutPoint); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // spend tx1 fixture.CommitTx(tx2); @@ -1808,6 +1823,7 @@ BOOST_AUTO_TEST_CASE(claim_expiration_test) BOOST_CHECK(!pclaimTrie->expirationQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint == tx1OutPoint); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); // roll all the way back fixture.DecrementBlocks(); @@ -1959,6 +1975,8 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) std::string sValue1("testa"); std::string sValue2("testb"); + int initialHeight = chainActive.Height(); + CClaimValue val; // Test 1: create 1 LBC claim (tx1), create 5 LBC support (tx3), create 5 LBC claim (tx2) @@ -2022,6 +2040,8 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(val.outPoint.n == 0); + uint256 tx1MerkleHash = pclaimTrie->getMerkleHash(); CMutableTransaction tx4 = BuildTransaction(tx1); CMutableTransaction tx5 = BuildTransaction(tx2); @@ -2038,6 +2058,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // unspend tx3, verify tx1 regains control fixture.DecrementBlocks(1); // 21 @@ -2048,6 +2069,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); // update tx1 with tx7, verify tx7 has control uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); @@ -2061,12 +2083,14 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx7.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // roll back to before tx7 is inserted, verify tx1 has control fixture.DecrementBlocks(1); // 21 BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); // roll back to before tx2 is valid fixture.DecrementBlocks(1); // 20 @@ -2082,6 +2106,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // roll back to before tx3 is inserted fixture.DecrementBlocks(15); // 6 @@ -2109,9 +2134,11 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->queueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // roll all the way back fixture.DecrementBlocks(22); // 0 + BOOST_CHECK(initialHeight == chainActive.Height()); // Make sure that when a support in the queue gets spent and then the spend is // undone, it goes back into the queue in the right spot @@ -2128,6 +2155,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); // advance a few blocks fixture.IncrementBlocks(5); // 6 @@ -2163,6 +2191,8 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(val.outPoint.n == 0); + tx1MerkleHash = pclaimTrie->getMerkleHash(); // tx1MerkleHash doesn't match right here (but it should?) // spend tx3 again, then undo the spend and roll back until it's back in the queue fixture.CommitTx(tx6); @@ -2172,6 +2202,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(tx1MerkleHash != pclaimTrie->getMerkleHash()); fixture.DecrementBlocks(1); // 13 @@ -2179,6 +2210,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(tx1MerkleHash == pclaimTrie->getMerkleHash()); // roll all the way back fixture.DecrementBlocks(13); @@ -2325,18 +2357,21 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); // advance a few blocks - fixture.IncrementBlocks(5);// 6 + fixture.IncrementBlocks(5); // 6 // put tx2 into the blockchain fixture.CommitTx(tx2); fixture.IncrementBlocks(1); // 7 + uint256 rootMerkleHash = pclaimTrie->getMerkleHash(); + BOOST_CHECK(!pclaimTrie->empty()); BOOST_CHECK(!pclaimTrie->queueEmpty()); BOOST_CHECK(pclaimTrie->supportEmpty()); BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(rootMerkleHash == pclaimTrie->getMerkleHash()); // advance some, insert tx3, should be immediately valid fixture.IncrementBlocks(2); // 9 @@ -2349,6 +2384,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + BOOST_CHECK(rootMerkleHash == pclaimTrie->getMerkleHash()); // advance until tx2 is valid, verify tx1 retains control fixture.IncrementBlocks(3); // 13 @@ -2359,7 +2395,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); - + BOOST_CHECK(rootMerkleHash == pclaimTrie->getMerkleHash()); BOOST_CHECK(pclaimTrie->haveClaim(sName, tx2cp)); // roll all the way back @@ -2383,6 +2419,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); // advance a few blocks fixture.IncrementBlocks(9); // 10 @@ -2397,6 +2434,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); // advance some fixture.IncrementBlocks(5); // 16 @@ -2411,6 +2449,7 @@ BOOST_AUTO_TEST_CASE(supporting_claims2_test) BOOST_CHECK(!pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); // advance until tx1 is valid fixture.IncrementBlocks(5); // 22 @@ -2605,6 +2644,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(!pclaimTrie->queueEmpty()); BOOST_CHECK(!pclaimTrie->supportEmpty()); BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + uint256 rootMerkleHash = pclaimTrie->getMerkleHash(); // Advance until tx2 is valid fixture.IncrementBlocks(50); // 102 @@ -2613,6 +2653,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(!pclaimTrie->queueEmpty()); BOOST_CHECK(!pclaimTrie->supportEmpty()); BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + BOOST_CHECK(rootMerkleHash == pclaimTrie->getMerkleHash()); fixture.IncrementBlocks(1); // 103 @@ -2622,6 +2663,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx1.GetHash()); + rootMerkleHash = pclaimTrie->getMerkleHash(); // Update tx1 so that it expires after tx3 expires uint160 claimId = ClaimIdHash(tx1.GetHash(), 0); @@ -2635,6 +2677,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); // Advance until the support expires fixture.IncrementBlocks(97); // 201 @@ -2643,6 +2686,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->queueEmpty()); BOOST_CHECK(!pclaimTrie->supportEmpty()); BOOST_CHECK(pclaimTrie->supportQueueEmpty()); + rootMerkleHash = pclaimTrie->getMerkleHash(); fixture.IncrementBlocks(1); // 202 @@ -2652,6 +2696,8 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); + rootMerkleHash = pclaimTrie->getMerkleHash(); // undo the block, make sure control goes back fixture.DecrementBlocks(1); // 201 @@ -2662,6 +2708,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); // redo the block, make sure it expires again fixture.IncrementBlocks(1); // 202 @@ -2672,6 +2719,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx2.GetHash()); + rootMerkleHash = pclaimTrie->getMerkleHash(); // roll back some, spend the support, and make sure nothing unexpected // happens at the time the support should have expired @@ -2684,6 +2732,7 @@ BOOST_AUTO_TEST_CASE(expiring_supports_test) BOOST_CHECK(pclaimTrie->supportQueueEmpty()); BOOST_CHECK(pclaimTrie->getInfoForName(sName, val)); BOOST_CHECK(val.outPoint.hash == tx4.GetHash()); + BOOST_CHECK(rootMerkleHash != pclaimTrie->getMerkleHash()); fixture.Spend(tx3); fixture.IncrementBlocks(1); // 154 @@ -2750,64 +2799,48 @@ bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::stri std::string computedReverseName; bool verifiedValue = false; - for (std::vector::const_reverse_iterator itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) - { + for (std::vector::const_reverse_iterator itNodes = proof.nodes.rbegin(); itNodes != proof.nodes.rend(); ++itNodes) { bool foundChildInChain = false; std::vector vchToHash; - for (std::vector >::const_iterator itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) - { + for (std::vector >::const_iterator itChildren = itNodes->children.begin(); itChildren != itNodes->children.end(); ++itChildren) { vchToHash.push_back(itChildren->first); uint256 childHash; - if (itChildren->second.IsNull()) - { - if (previousComputedHash.IsNull()) - { + if (itChildren->second.IsNull()) { + if (previousComputedHash.IsNull()) { return false; } - if (foundChildInChain) - { + if (foundChildInChain) { return false; } foundChildInChain = true; computedReverseName += itChildren->first; childHash = previousComputedHash; - } - else - { + } else { childHash = itChildren->second; } vchToHash.insert(vchToHash.end(), childHash.begin(), childHash.end()); } - if (itNodes != proof.nodes.rbegin() && !foundChildInChain) - { + if (itNodes != proof.nodes.rbegin() && !foundChildInChain) { return false; } - if (itNodes->hasValue) - { + if (itNodes->hasValue) { uint256 valHash; - if (itNodes->valHash.IsNull()) - { - if (itNodes != proof.nodes.rbegin()) - { + if (itNodes->valHash.IsNull()) { + if (itNodes != proof.nodes.rbegin()) { return false; } - if (!proof.hasValue) - { + if (!proof.hasValue) { return false; } valHash = getValueHash(proof.outPoint, - proof.nHeightOfLastTakeover); + proof.nHeightOfLastTakeover); verifiedValue = true; - } - else - { + } else { valHash = itNodes->valHash; } vchToHash.insert(vchToHash.end(), valHash.begin(), valHash.end()); - } - else if (proof.hasValue && itNodes == proof.nodes.rbegin()) - { + } else if (proof.hasValue && itNodes == proof.nodes.rbegin()) { return false; } CHash256 hasher; @@ -2817,20 +2850,16 @@ bool verify_proof(const CClaimTrieProof proof, uint256 rootHash, const std::stri uint256 calculatedHash(vchHash); previousComputedHash = calculatedHash; } - if (previousComputedHash != rootHash) - { + if (previousComputedHash != rootHash) { return false; } - if (proof.hasValue && !verifiedValue) - { + 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) - { + for (; itName != name.end() && itComputedName != computedReverseName.rend(); ++itName, ++itComputedName) { + if (*itName != *itComputedName) { return false; } } @@ -2986,7 +3015,7 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) bogusHashClaimTrie.SetHex("aaa"); pblockTemp->block.hashClaimTrie = bogusHashClaimTrie; - for (int i = 0; ; ++i) + for (uint32_t i = 0; ; ++i) { pblockTemp->block.nNonce = i; if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) -- 2.45.2 From 13960ed96402289d6c4aff830a4b385ab1a7818a Mon Sep 17 00:00:00 2001 From: Brannon King Date: Fri, 27 Jul 2018 10:53:11 -0600 Subject: [PATCH 3/3] ran the formatting tool --- src/test/claimtriebranching_tests.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/test/claimtriebranching_tests.cpp b/src/test/claimtriebranching_tests.cpp index 7b144be4f..29c4a5675 100644 --- a/src/test/claimtriebranching_tests.cpp +++ b/src/test/claimtriebranching_tests.cpp @@ -293,7 +293,7 @@ struct ClaimTrieChainFixture{ //disconnect i blocks from tip void DecrementBlocks(int num_blocks) { - for(int i = 0; i< num_blocks; i++){ + for (int i = 0; i < num_blocks; i++) { CValidationState state; CBlockIndex* pblockindex = chainActive.Tip(); InvalidateBlock(state, Params().GetConsensus(), pblockindex); @@ -392,7 +392,7 @@ BOOST_AUTO_TEST_CASE(claim_test) CMutableTransaction tx7 = fixture.MakeClaim(fixture.GetCoinbase(),"test","two",2); fixture.IncrementBlocks(1); BOOST_CHECK(is_claim_in_queue("test",tx7)); - BOOST_CHECK(is_best_claim("test",tx6)); + BOOST_CHECK(is_best_claim("test", tx6)); fixture.IncrementBlocks(10); BOOST_CHECK(is_best_claim("test",tx7)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); @@ -669,9 +669,9 @@ BOOST_AUTO_TEST_CASE(claimtrie_update_test) CMutableTransaction tx5 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",3); CMutableTransaction tx6 = fixture.MakeClaim(fixture.GetCoinbase(),"test","one",2); fixture.IncrementBlocks(10); - BOOST_CHECK(is_best_claim("test",tx5)); + BOOST_CHECK(is_best_claim("test", tx5)); BOOST_CHECK_EQUAL(2U, pclaimTrie->getClaimsForName("test").claims.size()); - CMutableTransaction u4 = fixture.MakeUpdate(tx5,"test","one",ClaimIdHash(tx5.GetHash(),0),1); + CMutableTransaction u4 = fixture.MakeUpdate(tx5, "test", "one", ClaimIdHash(tx5.GetHash(), 0), 1); fixture.IncrementBlocks(1); BOOST_CHECK(is_best_claim("test",tx6)); @@ -2999,11 +2999,11 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) CMutableTransaction tx1 = fixture.MakeClaim(fixture.GetCoinbase(), sName, sValue1, 1); - CBlockTemplate *pblockTemp; + CBlockTemplate* pblockTemp; BOOST_CHECK(pblockTemp = CreateNewBlock(Params(), tx1.vout[0].scriptPubKey)); pblockTemp->block.hashPrevBlock = chainActive.Tip()->GetBlockHash(); pblockTemp->block.nVersion = 1; - pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime()+Params().GetConsensus().nPowTargetSpacing; + pblockTemp->block.nTime = chainActive.Tip()->GetBlockTime() + Params().GetConsensus().nPowTargetSpacing; CMutableTransaction txCoinbase(pblockTemp->block.vtx[0]); txCoinbase.vin[0].scriptSig = CScript() << CScriptNum(chainActive.Height()); txCoinbase.vout[0].nValue = GetBlockSubsidy(chainActive.Height() + 1, Params().GetConsensus()); @@ -3015,11 +3015,9 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) bogusHashClaimTrie.SetHex("aaa"); pblockTemp->block.hashClaimTrie = bogusHashClaimTrie; - for (uint32_t i = 0; ; ++i) - { + for (uint32_t i = 0;; ++i) { pblockTemp->block.nNonce = i; - if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) - { + if (CheckProofOfWork(pblockTemp->block.GetPoWHash(), pblockTemp->block.nBits, Params().GetConsensus())) { break; } } @@ -3029,7 +3027,7 @@ BOOST_AUTO_TEST_CASE(bogus_claimtrie_hash_test) BOOST_CHECK(success); BOOST_CHECK(state.IsValid()); BOOST_CHECK(pblockTemp->block.GetHash() != chainActive.Tip()->GetBlockHash()); - BOOST_CHECK_EQUAL(orig_chain_height,chainActive.Height()); + BOOST_CHECK_EQUAL(orig_chain_height, chainActive.Height()); delete pblockTemp; } -- 2.45.2