-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathmin_protocol_ratchet_test.cpp
More file actions
112 lines (95 loc) · 5.53 KB
/
Copy pathmin_protocol_ratchet_test.cpp
File metadata and controls
112 lines (95 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// dgb runtime P2P accept-floor RATCHET KAT.
//
// FENCED, additive (no production code touched -- pins the pure free function
// dgb::ratchet_min_protocol_version in coin/desired_version_tally.hpp). Mirrors
// the p2pool-dgb-scrypt update_min_protocol_version oracle (data.py:857-863):
// def update_min_protocol_version(counts, share):
// minpver = getattr(share.net, "MINIMUM_PROTOCOL_VERSION", 1400)
// newminpver = share.MINIMUM_PROTOCOL_VERSION
// if (counts is not None) and (minpver < newminpver):
// if counts.get(share.VERSION, 0) >= sum(counts.itervalues())*95//100:
// share.net.MINIMUM_PROTOCOL_VERSION = newminpver
//
// counts is the WORK-WEIGHTED get_desired_version_counts map (each share weighted
// by target_to_average_attempts, keyed by desired_version, looked up by the best
// share VERSION) -- c2pool exposes it as get_desired_version_weights. The cold
// floor 1400 / ratchet target 3500 are the oracle p2p.py:153 getattr fallback and
// data.py:81 BaseShare.MINIMUM_PROTOCOL_VERSION (== config_pool.hpp
// MINIMUM_PROTOCOL_VERSION / SHARE_MINIMUM_PROTOCOL_VERSION, step-1 #599).
//
// Every expectation is hand-derived from the oracle formula. MUST appear in BOTH
// this dir CMakeLists.txt AND the build.yml --target allowlist, or it becomes a
// #143 NOT_BUILT sentinel.
#include <impl/dgb/coin/desired_version_tally.hpp>
#include <core/uint256.hpp> // uint288
#include <gtest/gtest.h>
namespace {
uint288 u(uint64_t n) { return uint288(n); }
// 2^k as a uint288 -- the scale of a real target_to_average_attempts (ttaa(2^k-1)
// = 2^(256-k)), so the boundary/overflow cases run at consensus magnitudes.
uint288 pow2(unsigned k) {
uint288 v = u(1);
for (unsigned i = 0; i < k; ++i) v = v * uint32_t(2);
return v;
}
constexpr uint32_t COLD = 1400; // oracle p2p.py:153 getattr fallback
constexpr uint32_t TARGET = 3500; // oracle data.py:81 BaseShare.MINIMUM_PROTOCOL_VERSION
} // namespace
// --- guard: floor already at/above target -> no-op (minpver < newminpver false)
TEST(DgbMinProtocolRatchet, AlreadyAtTargetIsNoOp) {
EXPECT_EQ(dgb::ratchet_min_protocol_version({{36, u(100)}}, 36, TARGET, TARGET), TARGET);
EXPECT_EQ(dgb::ratchet_min_protocol_version({{36, u(100)}}, 36, TARGET + 1, TARGET), TARGET + 1);
}
// --- unanimous support -> ratchet cold floor up to target -------------------
TEST(DgbMinProtocolRatchet, UnanimousRatchets) {
EXPECT_EQ(dgb::ratchet_min_protocol_version({{36, u(100)}}, 36, COLD, TARGET), TARGET);
}
// --- exactly 95% (sum=100, best=95) -> 95 >= 100*95//100=95 -> ratchet -------
TEST(DgbMinProtocolRatchet, Exactly95PercentRatchets) {
auto w = std::map<uint64_t, uint288>{{36, u(95)}, {35, u(5)}};
EXPECT_EQ(dgb::ratchet_min_protocol_version(w, 36, COLD, TARGET), TARGET);
}
// --- just below 95% (sum=100, best=94) -> 94 >= 95 false -> stays cold -------
TEST(DgbMinProtocolRatchet, JustBelow95PercentStaysCold) {
auto w = std::map<uint64_t, uint288>{{36, u(94)}, {35, u(6)}};
EXPECT_EQ(dgb::ratchet_min_protocol_version(w, 36, COLD, TARGET), COLD);
}
// --- floor-div vs cross-multiply BOUNDARY: sum=101, best=95.
// oracle floor: 95 >= floor(101*95/100)=floor(95.95)=95 -> RATCHET.
// cross-mult (best*100 >= sum*95): 9500 >= 9595 false -> would NOT ratchet.
// This case proves the function floor-divides like the oracle, not cross-mults.
TEST(DgbMinProtocolRatchet, FloorDivBoundaryRatchets) {
auto w = std::map<uint64_t, uint288>{{36, u(95)}, {35, u(6)}}; // sum=101
EXPECT_EQ(dgb::ratchet_min_protocol_version(w, 36, COLD, TARGET), TARGET);
}
// --- best version absent from the map -> best_weight 0 -> stays cold ---------
TEST(DgbMinProtocolRatchet, BestVersionAbsentStaysCold) {
EXPECT_EQ(dgb::ratchet_min_protocol_version({{35, u(100)}}, 36, COLD, TARGET), COLD);
}
// --- empty window: 0 >= 0*95//100=0 -> oracle ratchets (counts={} != None).
// The None-guard is the CALL-SITE job (oracle main.py:216 only calls when
// len(shares) > CHAIN_LENGTH); the pure function mirrors the dict-branch.
TEST(DgbMinProtocolRatchet, EmptyWindowMirrorsOracleDictBranch) {
EXPECT_EQ(dgb::ratchet_min_protocol_version({}, 36, COLD, TARGET), TARGET);
}
// --- work-weighted, NOT flat count: version 35 has the most SHARES but version
// 36 holds the dominant WORK. ratchet keys on work (get_desired_version_weights).
// Build the map through accumulate_version_weights to exercise the real pipe.
TEST(DgbMinProtocolRatchet, WorkWeightedNotFlatCount) {
// ten tiny v35 shares (work 1 each = 10) + one heavy v36 share (work 1000).
std::vector<dgb::VersionWork> window;
for (int i = 0; i < 10; ++i) window.push_back({35, u(1)});
window.push_back({36, u(1000)}); // total=1010, best(36)=1000 >= 1010*95//100=959
auto w = dgb::accumulate_version_weights(window);
EXPECT_EQ(dgb::ratchet_min_protocol_version(w, 36, COLD, TARGET), TARGET);
// flat count would give v35 ten shares vs v36 one -> would NOT ratchet on 36.
}
// --- consensus-magnitude weights (2^256-scale), no overflow in total*95 ------
TEST(DgbMinProtocolRatchet, ConsensusMagnitudeNoOverflow) {
// 96 * 2^256 at v36, 4 * 2^256 at v35: total=100*2^256, best=96*2^256 >= 95% -> ratchet.
uint288 unit = pow2(256);
uint288 best = unit; for (int i = 1; i < 96; ++i) best = best + unit; // 96 * 2^256
uint288 rest = unit; for (int i = 1; i < 4; ++i) rest = rest + unit; // 4 * 2^256
auto w = std::map<uint64_t, uint288>{{36, best}, {35, rest}};
EXPECT_EQ(dgb::ratchet_min_protocol_version(w, 36, COLD, TARGET), TARGET);
}