@@ -567,38 +567,47 @@ constexpr CAmount VALUE1{100};
567
567
constexpr CAmount VALUE2{200 };
568
568
constexpr CAmount VALUE3{300 };
569
569
570
- constexpr char DIRTY{CCoinsCacheEntry::DIRTY};
571
- constexpr char FRESH{CCoinsCacheEntry::FRESH};
572
- constexpr char CLEAN{0 };
573
-
574
570
struct CoinEntry {
571
+ enum class State { CLEAN, DIRTY, FRESH, DIRTY_FRESH };
572
+
575
573
const CAmount value;
576
- const char flags ;
574
+ const State state ;
577
575
578
- constexpr CoinEntry (const CAmount v, const char s) : value{v}, flags {s} {}
576
+ constexpr CoinEntry (const CAmount v, const State s) : value{v}, state {s} {}
579
577
580
578
bool operator ==(const CoinEntry& o) const = default ;
581
- friend std::ostream& operator <<(std::ostream& os, const CoinEntry& e) { return os << e.value << " , " << e.flags ; }
579
+ friend std::ostream& operator <<(std::ostream& os, const CoinEntry& e) { return os << e.value << " , " << e.state ; }
580
+
581
+ constexpr bool IsDirtyFresh () const { return state == State::DIRTY_FRESH; }
582
+ constexpr bool IsDirty () const { return state == State::DIRTY || IsDirtyFresh (); }
583
+ constexpr bool IsFresh () const { return state == State::FRESH || IsDirtyFresh (); }
584
+
585
+ static constexpr State ToState (const bool is_dirty, const bool is_fresh) {
586
+ if (is_dirty && is_fresh) return State::DIRTY_FRESH;
587
+ if (is_dirty) return State::DIRTY;
588
+ if (is_fresh) return State::FRESH;
589
+ return State::CLEAN;
590
+ }
582
591
};
583
592
584
593
using MaybeCoin = std::optional<CoinEntry>;
585
594
using CoinOrError = std::variant<MaybeCoin, std::string>;
586
595
587
596
constexpr MaybeCoin MISSING {std::nullopt};
588
- constexpr MaybeCoin SPENT_DIRTY {{SPENT, DIRTY}};
589
- constexpr MaybeCoin SPENT_DIRTY_FRESH {{SPENT, DIRTY | FRESH }};
590
- constexpr MaybeCoin SPENT_FRESH {{SPENT, FRESH}};
591
- constexpr MaybeCoin SPENT_CLEAN {{SPENT, CLEAN}};
592
- constexpr MaybeCoin VALUE1_DIRTY {{VALUE1, DIRTY}};
593
- constexpr MaybeCoin VALUE1_DIRTY_FRESH{{VALUE1, DIRTY | FRESH }};
594
- constexpr MaybeCoin VALUE1_FRESH {{VALUE1, FRESH}};
595
- constexpr MaybeCoin VALUE1_CLEAN {{VALUE1, CLEAN}};
596
- constexpr MaybeCoin VALUE2_DIRTY {{VALUE2, DIRTY}};
597
- constexpr MaybeCoin VALUE2_DIRTY_FRESH{{VALUE2, DIRTY | FRESH }};
598
- constexpr MaybeCoin VALUE2_FRESH {{VALUE2, FRESH}};
599
- constexpr MaybeCoin VALUE2_CLEAN {{VALUE2, CLEAN}};
600
- constexpr MaybeCoin VALUE3_DIRTY {{VALUE3, DIRTY}};
601
- constexpr MaybeCoin VALUE3_DIRTY_FRESH{{VALUE3, DIRTY | FRESH }};
597
+ constexpr MaybeCoin SPENT_DIRTY {{SPENT, CoinEntry::State:: DIRTY}};
598
+ constexpr MaybeCoin SPENT_DIRTY_FRESH {{SPENT, CoinEntry::State::DIRTY_FRESH }};
599
+ constexpr MaybeCoin SPENT_FRESH {{SPENT, CoinEntry::State:: FRESH}};
600
+ constexpr MaybeCoin SPENT_CLEAN {{SPENT, CoinEntry::State:: CLEAN}};
601
+ constexpr MaybeCoin VALUE1_DIRTY {{VALUE1, CoinEntry::State:: DIRTY}};
602
+ constexpr MaybeCoin VALUE1_DIRTY_FRESH{{VALUE1, CoinEntry::State::DIRTY_FRESH }};
603
+ constexpr MaybeCoin VALUE1_FRESH {{VALUE1, CoinEntry::State:: FRESH}};
604
+ constexpr MaybeCoin VALUE1_CLEAN {{VALUE1, CoinEntry::State:: CLEAN}};
605
+ constexpr MaybeCoin VALUE2_DIRTY {{VALUE2, CoinEntry::State:: DIRTY}};
606
+ constexpr MaybeCoin VALUE2_DIRTY_FRESH{{VALUE2, CoinEntry::State::DIRTY_FRESH }};
607
+ constexpr MaybeCoin VALUE2_FRESH {{VALUE2, CoinEntry::State:: FRESH}};
608
+ constexpr MaybeCoin VALUE2_CLEAN {{VALUE2, CoinEntry::State:: CLEAN}};
609
+ constexpr MaybeCoin VALUE3_DIRTY {{VALUE3, CoinEntry::State:: DIRTY}};
610
+ constexpr MaybeCoin VALUE3_DIRTY_FRESH{{VALUE3, CoinEntry::State::DIRTY_FRESH }};
602
611
603
612
constexpr auto EX_OVERWRITE_UNSPENT{" Attempted to overwrite an unspent coin (when possible_overwrite is false)" };
604
613
constexpr auto EX_FRESH_MISAPPLIED {" FRESH flag misapplied to coin that exists in parent cache" };
@@ -621,22 +630,22 @@ static size_t InsertCoinsMapEntry(CCoinsMap& map, CoinsCachePair& sentinel, cons
621
630
SetCoinsValue (cache_coin.value , entry.coin );
622
631
auto [iter, inserted] = map.emplace (OUTPOINT, std::move (entry));
623
632
assert (inserted);
624
- if (cache_coin.flags & DIRTY ) CCoinsCacheEntry::SetDirty (*iter, sentinel);
625
- if (cache_coin.flags & FRESH ) CCoinsCacheEntry::SetFresh (*iter, sentinel);
633
+ if (cache_coin.IsDirty () ) CCoinsCacheEntry::SetDirty (*iter, sentinel);
634
+ if (cache_coin.IsFresh () ) CCoinsCacheEntry::SetFresh (*iter, sentinel);
626
635
return iter->second .coin .DynamicMemoryUsage ();
627
636
}
628
637
629
- MaybeCoin GetCoinsMapEntry (const CCoinsMap& map, const COutPoint& outp = OUTPOINT)
638
+ static MaybeCoin GetCoinsMapEntry (const CCoinsMap& map, const COutPoint& outp = OUTPOINT)
630
639
{
631
640
if (auto it{map.find (outp)}; it != map.end ()) {
632
641
return CoinEntry{
633
642
it->second .coin .IsSpent () ? SPENT : it->second .coin .out .nValue ,
634
- static_cast < char >(( it->second .IsDirty () ? DIRTY : 0 ) | ( it->second .IsFresh () ? FRESH : 0 ))};
643
+ CoinEntry::ToState ( it->second .IsDirty (), it->second .IsFresh ())};
635
644
}
636
645
return MISSING;
637
646
}
638
647
639
- void WriteCoinsViewEntry (CCoinsView& view, const MaybeCoin& cache_coin)
648
+ static void WriteCoinsViewEntry (CCoinsView& view, const MaybeCoin& cache_coin)
640
649
{
641
650
CoinsCachePair sentinel{};
642
651
sentinel.second .SelfRef (sentinel);
@@ -652,7 +661,7 @@ class SingleEntryCacheTest
652
661
public:
653
662
SingleEntryCacheTest (const CAmount base_value, const MaybeCoin& cache_coin)
654
663
{
655
- auto base_cache_coin{base_value == ABSENT ? MISSING : CoinEntry{base_value, DIRTY}};
664
+ auto base_cache_coin{base_value == ABSENT ? MISSING : CoinEntry{base_value, CoinEntry::State:: DIRTY}};
656
665
WriteCoinsViewEntry (base, base_cache_coin);
657
666
if (cache_coin) cache.usage () += InsertCoinsMapEntry (cache.map (), cache.sentinel (), *cache_coin);
658
667
}
@@ -800,7 +809,7 @@ BOOST_AUTO_TEST_CASE(ccoins_add)
800
809
}
801
810
}
802
811
803
- void CheckWriteCoins (const MaybeCoin& parent, const MaybeCoin& child, const CoinOrError& expected)
812
+ static void CheckWriteCoins (const MaybeCoin& parent, const MaybeCoin& child, const CoinOrError& expected)
804
813
{
805
814
SingleEntryCacheTest test{ABSENT, parent};
806
815
auto write_coins{[&] { WriteCoinsViewEntry (test.cache , child); }};
@@ -870,7 +879,7 @@ BOOST_AUTO_TEST_CASE(ccoins_write)
870
879
CheckWriteCoins (VALUE1_DIRTY_FRESH, VALUE2_DIRTY, VALUE2_DIRTY_FRESH );
871
880
CheckWriteCoins (VALUE1_DIRTY_FRESH, VALUE2_DIRTY_FRESH, EX_FRESH_MISAPPLIED);
872
881
873
- // The checks above omit cases where the child flags are not DIRTY, since
882
+ // The checks above omit cases where the child state is not DIRTY, since
874
883
// they would be too repetitive (the parent cache is never updated in these
875
884
// cases). The loop below covers these cases and makes sure the parent cache
876
885
// is always left unchanged.
@@ -946,7 +955,7 @@ void TestFlushBehavior(
946
955
BOOST_CHECK (!base.HaveCoin (outp));
947
956
BOOST_CHECK (view->HaveCoin (outp));
948
957
949
- BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , DIRTY|FRESH ));
958
+ BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , CoinEntry::State::DIRTY_FRESH ));
950
959
951
960
// --- 2. Flushing all caches (without erasing)
952
961
//
@@ -958,7 +967,7 @@ void TestFlushBehavior(
958
967
959
968
// --- 3. Ensuring the entry still exists in the cache and has been written to parent
960
969
//
961
- BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , CLEAN)); // Flags should have been wiped.
970
+ BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , CoinEntry::State:: CLEAN)); // State should have been wiped.
962
971
963
972
// Both views should now have the coin.
964
973
BOOST_CHECK (base.HaveCoin (outp));
@@ -978,7 +987,7 @@ void TestFlushBehavior(
978
987
//
979
988
BOOST_CHECK (!GetCoinsMapEntry (view->map (), outp));
980
989
view->AccessCoin (outp);
981
- BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , CLEAN));
990
+ BOOST_CHECK_EQUAL (GetCoinsMapEntry (view->map (), outp), CoinEntry (coin.out .nValue , CoinEntry::State:: CLEAN));
982
991
}
983
992
984
993
// Can't overwrite an entry without specifying that an overwrite is
@@ -1043,7 +1052,7 @@ void TestFlushBehavior(
1043
1052
all_caches[0 ]->AddCoin (outp, std::move (coin), false );
1044
1053
1045
1054
// Coin should be FRESH in the cache.
1046
- BOOST_CHECK_EQUAL (GetCoinsMapEntry (all_caches[0 ]->map (), outp), CoinEntry (coin_val, DIRTY|FRESH ));
1055
+ BOOST_CHECK_EQUAL (GetCoinsMapEntry (all_caches[0 ]->map (), outp), CoinEntry (coin_val, CoinEntry::State::DIRTY_FRESH ));
1047
1056
// Base shouldn't have seen coin.
1048
1057
BOOST_CHECK (!base.HaveCoin (outp));
1049
1058
0 commit comments