git / moonbite-core / src/libmw/test/tests/node/Test_CoinsView.cpp · raw

#include <mw/crypto/SecretKeys.h>#include <mw/node/BlockValidator.h>#include <mw/node/CoinsView.h>#include <test_framework/Miner.h>#include <test_framework/TestMWEB.h>#include <test_framework/models/Tx.h>BOOST_FIXTURE_TEST_SUITE(TestCoinsView, MWEBTestingSetup)static CAmount SumPegOuts(const std::vector<PegOutCoin>& pegouts){    CAmount total = 0;    for (const PegOutCoin& pegout : pegouts) {        total += pegout.GetAmount();    }    return total;}static void CheckAmountAccounting(const mw::Block::CPtr& pBlock){    const auto pegin_amount = pBlock->GetPegInAmount();    const auto fee_amount = pBlock->GetTotalFee();    const auto supply_change = pBlock->GetSupplyChange();    BOOST_REQUIRE(pegin_amount);    BOOST_REQUIRE(fee_amount);    BOOST_REQUIRE(supply_change);    BOOST_CHECK_EQUAL(*supply_change, *pegin_amount - SumPegOuts(pBlock->GetPegOuts()) - *fee_amount);}static void CheckMMRRoots(const mw::CoinsViewCache& view){    BOOST_REQUIRE(view.GetBestHeader() != nullptr);    BOOST_CHECK(view.GetBestHeader()->GetOutputRoot() == view.GetOutputPMMR()->Root());    BOOST_CHECK_EQUAL(view.GetBestHeader()->GetNumTXOs(), view.GetOutputPMMR()->GetNumLeaves());    BOOST_CHECK(view.GetBestHeader()->GetLeafsetRoot() == view.GetLeafSet()->Root());}BOOST_AUTO_TEST_CASE(ApplyBlock_AmountAccountingAndMMRRoots){    auto pDBView = mw::CoinsViewDB::Open(GetDataDir(), nullptr, GetDB());    auto pCachedView = std::make_shared<mw::CoinsViewCache>(pDBView);    test::Miner miner(GetDataDir());    CAmount expected_mweb_amount = 0;    test::Tx pegin_tx = test::Tx::CreatePegIn(5'000'000);    mw::Block::CPtr pBlock1 = miner.MineBlock(1, {pegin_tx}).GetBlock();    BOOST_REQUIRE(BlockValidator::ValidateBlock(pBlock1, pegin_tx.GetPegIns(), pegin_tx.GetPegOuts()));    CheckAmountAccounting(pBlock1);    expected_mweb_amount += *pBlock1->GetSupplyChange();    BOOST_CHECK_EQUAL(expected_mweb_amount, 5'000'000);    pCachedView->ApplyBlock(pBlock1, false);    CheckMMRRoots(*pCachedView);    test::Tx pegout_tx = test::Tx::CreatePegOut(pegin_tx.GetOutputs().front(), 1'000);    mw::Block::CPtr pBlock2 = miner.MineBlock(2, {pegout_tx}).GetBlock();    BOOST_REQUIRE(BlockValidator::ValidateBlock(pBlock2, pegout_tx.GetPegIns(), pegout_tx.GetPegOuts()));    CheckAmountAccounting(pBlock2);    expected_mweb_amount += *pBlock2->GetSupplyChange();    BOOST_CHECK_EQUAL(expected_mweb_amount, 0);    pCachedView->ApplyBlock(pBlock2, false);    CheckMMRRoots(*pCachedView);}BOOST_AUTO_TEST_CASE(ApplyBlock_RejectedBlockDoesNotMutateCache){    auto pDBView = mw::CoinsViewDB::Open(GetDataDir(), nullptr, GetDB());    auto pCachedView = std::make_shared<mw::CoinsViewCache>(pDBView);    test::Miner miner(GetDataDir());    test::Tx pegin_tx = test::Tx::CreatePegIn(5'000'000);    mw::Block::CPtr pBlock1 = miner.MineBlock(1, {pegin_tx}).GetBlock();    BOOST_REQUIRE(BlockValidator::ValidateBlock(pBlock1, pegin_tx.GetPegIns(), pegin_tx.GetPegOuts()));    pCachedView->ApplyBlock(pBlock1, false);    const mw::Header::CPtr best_header_before = pCachedView->GetBestHeader();    const mw::Hash output_root_before = pCachedView->GetOutputPMMR()->Root();    const uint64_t num_txos_before = pCachedView->GetOutputPMMR()->GetNumLeaves();    const mw::Hash leafset_root_before = pCachedView->GetLeafSet()->Root();    test::Tx next_pegin_tx = test::Tx::CreatePegIn(2'000'000);    mw::Block::CPtr pBlock2 = miner.MineBlock(2, {next_pegin_tx}).GetBlock();    BOOST_REQUIRE(BlockValidator::ValidateBlock(pBlock2, next_pegin_tx.GetPegIns(), next_pegin_tx.GetPegOuts()));    mw::Block::CPtr pBadBlock = std::make_shared<mw::Block>(        mw::MutHeader(pBlock2->GetHeader())            .SetOutputRoot(SecretKey::Random().GetBigInt())            .Build(),        pBlock2->GetTxBody()    );    BOOST_CHECK_THROW(pCachedView->ApplyBlock(pBadBlock, false), std::exception);    BOOST_REQUIRE(pCachedView->GetBestHeader() != nullptr);    BOOST_CHECK(pCachedView->GetBestHeader()->GetHash() == best_header_before->GetHash());    BOOST_CHECK(pCachedView->GetOutputPMMR()->Root() == output_root_before);    BOOST_CHECK_EQUAL(pCachedView->GetOutputPMMR()->GetNumLeaves(), num_txos_before);    BOOST_CHECK(pCachedView->GetLeafSet()->Root() == leafset_root_before);    BOOST_CHECK(pCachedView->GetUTXO(pegin_tx.GetOutputs().front().GetOutputID()) != nullptr);    BOOST_CHECK(pCachedView->GetUTXO(next_pegin_tx.GetOutputs().front().GetOutputID()) == nullptr);}BOOST_AUTO_TEST_SUITE_END()