refactor: Makes HashRouter flags more type-safe (#5371)

This change addresses the issue #5336: Refactor HashRouter flags to be more type-safe.

* Switched numeric flags to enum type.
* Updated unit tests
This commit is contained in:
Valentin Balaschenko
2025-07-23 13:03:12 +01:00
committed by GitHub
parent 7ff4f79d30
commit c233df720a
10 changed files with 219 additions and 107 deletions

View File

@@ -3652,14 +3652,18 @@ class Batch_test : public beast::unit_test::suite
{
// Submit a tx with tfInnerBatchTxn
uint256 const txBad = submitTx(tfInnerBatchTxn);
BEAST_EXPECT(env.app().getHashRouter().getFlags(txBad) == 0);
BEAST_EXPECT(
env.app().getHashRouter().getFlags(txBad) ==
HashRouterFlags::UNDEFINED);
}
// Validate: NetworkOPs::processTransaction()
{
uint256 const txid = processTxn(tfInnerBatchTxn);
// HashRouter::getFlags() should return SF_BAD
BEAST_EXPECT(env.app().getHashRouter().getFlags(txid) == SF_BAD);
// HashRouter::getFlags() should return LedgerFlags::BAD
BEAST_EXPECT(
env.app().getHashRouter().getFlags(txid) ==
HashRouterFlags::BAD);
}
}

View File

@@ -45,15 +45,19 @@ class HashRouter_test : public beast::unit_test::suite
TestStopwatch stopwatch;
HashRouter router(getSetup(2s, 1s), stopwatch);
uint256 const key1(1);
uint256 const key2(2);
uint256 const key3(3);
HashRouterFlags key1(HashRouterFlags::PRIVATE1);
HashRouterFlags key2(HashRouterFlags::PRIVATE2);
HashRouterFlags key3(HashRouterFlags::PRIVATE3);
auto const ukey1 = uint256{static_cast<std::uint64_t>(key1)};
auto const ukey2 = uint256{static_cast<std::uint64_t>(key2)};
auto const ukey3 = uint256{static_cast<std::uint64_t>(key3)};
// t=0
router.setFlags(key1, 11111);
BEAST_EXPECT(router.getFlags(key1) == 11111);
router.setFlags(key2, 22222);
BEAST_EXPECT(router.getFlags(key2) == 22222);
router.setFlags(ukey1, HashRouterFlags::PRIVATE1);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::PRIVATE1);
router.setFlags(ukey2, HashRouterFlags::PRIVATE2);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::PRIVATE2);
// key1 : 0
// key2 : 0
// key3: null
@@ -62,7 +66,7 @@ class HashRouter_test : public beast::unit_test::suite
// Because we are accessing key1 here, it
// will NOT be expired for another two ticks
BEAST_EXPECT(router.getFlags(key1) == 11111);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::PRIVATE1);
// key1 : 1
// key2 : 0
// key3 null
@@ -70,9 +74,9 @@ class HashRouter_test : public beast::unit_test::suite
++stopwatch;
// t=3
router.setFlags(key3, 33333); // force expiration
BEAST_EXPECT(router.getFlags(key1) == 11111);
BEAST_EXPECT(router.getFlags(key2) == 0);
router.setFlags(ukey3, HashRouterFlags::PRIVATE3); // force expiration
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::PRIVATE1);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::UNDEFINED);
}
void
@@ -83,15 +87,21 @@ class HashRouter_test : public beast::unit_test::suite
TestStopwatch stopwatch;
HashRouter router(getSetup(2s, 1s), stopwatch);
uint256 const key1(1);
uint256 const key2(2);
uint256 const key3(3);
uint256 const key4(4);
HashRouterFlags key1(HashRouterFlags::PRIVATE1);
HashRouterFlags key2(HashRouterFlags::PRIVATE2);
HashRouterFlags key3(HashRouterFlags::PRIVATE3);
HashRouterFlags key4(HashRouterFlags::PRIVATE4);
auto const ukey1 = uint256{static_cast<std::uint64_t>(key1)};
auto const ukey2 = uint256{static_cast<std::uint64_t>(key2)};
auto const ukey3 = uint256{static_cast<std::uint64_t>(key3)};
auto const ukey4 = uint256{static_cast<std::uint64_t>(key4)};
BEAST_EXPECT(key1 != key2 && key2 != key3 && key3 != key4);
// t=0
router.setFlags(key1, 12345);
BEAST_EXPECT(router.getFlags(key1) == 12345);
router.setFlags(ukey1, HashRouterFlags::BAD);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::BAD);
// key1 : 0
// key2 : null
// key3 : null
@@ -103,26 +113,27 @@ class HashRouter_test : public beast::unit_test::suite
// so key1 will be expired after the second
// call to setFlags.
// t=1
router.setFlags(key2, 9999);
BEAST_EXPECT(router.getFlags(key1) == 12345);
BEAST_EXPECT(router.getFlags(key2) == 9999);
router.setFlags(ukey2, HashRouterFlags::PRIVATE5);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::BAD);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::PRIVATE5);
// key1 : 1
// key2 : 1
// key3 : null
++stopwatch;
// t=2
BEAST_EXPECT(router.getFlags(key2) == 9999);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::PRIVATE5);
// key1 : 1
// key2 : 2
// key3 : null
++stopwatch;
// t=3
router.setFlags(key3, 2222);
BEAST_EXPECT(router.getFlags(key1) == 0);
BEAST_EXPECT(router.getFlags(key2) == 9999);
BEAST_EXPECT(router.getFlags(key3) == 2222);
router.setFlags(ukey3, HashRouterFlags::BAD);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::UNDEFINED);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::PRIVATE5);
BEAST_EXPECT(router.getFlags(ukey3) == HashRouterFlags::BAD);
// key1 : 3
// key2 : 3
// key3 : 3
@@ -130,10 +141,10 @@ class HashRouter_test : public beast::unit_test::suite
++stopwatch;
// t=4
// No insertion, no expiration
router.setFlags(key1, 7654);
BEAST_EXPECT(router.getFlags(key1) == 7654);
BEAST_EXPECT(router.getFlags(key2) == 9999);
BEAST_EXPECT(router.getFlags(key3) == 2222);
router.setFlags(ukey1, HashRouterFlags::SAVED);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::SAVED);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::PRIVATE5);
BEAST_EXPECT(router.getFlags(ukey3) == HashRouterFlags::BAD);
// key1 : 4
// key2 : 4
// key3 : 4
@@ -142,11 +153,11 @@ class HashRouter_test : public beast::unit_test::suite
++stopwatch;
// t=6
router.setFlags(key4, 7890);
BEAST_EXPECT(router.getFlags(key1) == 0);
BEAST_EXPECT(router.getFlags(key2) == 0);
BEAST_EXPECT(router.getFlags(key3) == 0);
BEAST_EXPECT(router.getFlags(key4) == 7890);
router.setFlags(ukey4, HashRouterFlags::TRUSTED);
BEAST_EXPECT(router.getFlags(ukey1) == HashRouterFlags::UNDEFINED);
BEAST_EXPECT(router.getFlags(ukey2) == HashRouterFlags::UNDEFINED);
BEAST_EXPECT(router.getFlags(ukey3) == HashRouterFlags::UNDEFINED);
BEAST_EXPECT(router.getFlags(ukey4) == HashRouterFlags::TRUSTED);
// key1 : 6
// key2 : 6
// key3 : 6
@@ -168,18 +179,18 @@ class HashRouter_test : public beast::unit_test::suite
uint256 const key4(4);
BEAST_EXPECT(key1 != key2 && key2 != key3 && key3 != key4);
int flags = 12345; // This value is ignored
HashRouterFlags flags(HashRouterFlags::BAD); // This value is ignored
router.addSuppression(key1);
BEAST_EXPECT(router.addSuppressionPeer(key2, 15));
BEAST_EXPECT(router.addSuppressionPeer(key3, 20, flags));
BEAST_EXPECT(flags == 0);
BEAST_EXPECT(flags == HashRouterFlags::UNDEFINED);
++stopwatch;
BEAST_EXPECT(!router.addSuppressionPeer(key1, 2));
BEAST_EXPECT(!router.addSuppressionPeer(key2, 3));
BEAST_EXPECT(!router.addSuppressionPeer(key3, 4, flags));
BEAST_EXPECT(flags == 0);
BEAST_EXPECT(flags == HashRouterFlags::UNDEFINED);
BEAST_EXPECT(router.addSuppressionPeer(key4, 5));
}
@@ -192,9 +203,9 @@ class HashRouter_test : public beast::unit_test::suite
HashRouter router(getSetup(2s, 1s), stopwatch);
uint256 const key1(1);
BEAST_EXPECT(router.setFlags(key1, 10));
BEAST_EXPECT(!router.setFlags(key1, 10));
BEAST_EXPECT(router.setFlags(key1, 20));
BEAST_EXPECT(router.setFlags(key1, HashRouterFlags::PRIVATE1));
BEAST_EXPECT(!router.setFlags(key1, HashRouterFlags::PRIVATE1));
BEAST_EXPECT(router.setFlags(key1, HashRouterFlags::PRIVATE2));
}
void
@@ -250,7 +261,7 @@ class HashRouter_test : public beast::unit_test::suite
HashRouter router(getSetup(5s, 1s), stopwatch);
uint256 const key(1);
HashRouter::PeerShortID peer = 1;
int flags;
HashRouterFlags flags;
BEAST_EXPECT(router.shouldProcess(key, peer, flags, 1s));
BEAST_EXPECT(!router.shouldProcess(key, peer, flags, 1s));
@@ -364,6 +375,39 @@ class HashRouter_test : public beast::unit_test::suite
}
}
void
testFlagsOps()
{
testcase("Bitwise Operations");
using HF = HashRouterFlags;
using UHF = std::underlying_type_t<HF>;
HF f1 = HF::BAD;
HF f2 = HF::SAVED;
HF combined = f1 | f2;
BEAST_EXPECT(
static_cast<UHF>(combined) ==
(static_cast<UHF>(f1) | static_cast<UHF>(f2)));
HF temp = f1;
temp |= f2;
BEAST_EXPECT(temp == combined);
HF intersect = combined & f1;
BEAST_EXPECT(intersect == f1);
HF temp2 = combined;
temp2 &= f1;
BEAST_EXPECT(temp2 == f1);
BEAST_EXPECT(any(f1));
BEAST_EXPECT(any(f2));
BEAST_EXPECT(any(combined));
BEAST_EXPECT(!any(HF::UNDEFINED));
}
public:
void
run() override
@@ -375,6 +419,7 @@ public:
testRelay();
testProcess();
testSetup();
testFlagsOps();
}
};