Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/impl/dgb/run_loop_mint.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

// run_loop_mint.hpp — DGB Phase B pool/share: the live create_local_share()
// caller that the AutoRatchet {mint, vote} selector feeds.
//
// auto_ratchet_wire.hpp resolves the {share_version_to_mint,
// desired_version_to_vote} pair (oracle baseline 35, target 36). Until now that
// pair was computed only in tests; the share-mint path still defaulted
// create_local_share()'s trailing version arguments to a hardcoded 36/36, which
// would make a freshly-started node skip ahead of the network and mint V36
// shares the older DGB sharechain cannot accept.
//
// This seam closes that gap: it is the ONE place the run-loop asks the ratchet
// for the version pair and stamps it onto the share it is about to create. It
// adds NO new policy — get_share_version() already owns the work-weighted gate
// (#249/#289). The create step is injected (CreateFn) rather than called
// directly so this glue stays free of the ~30-argument create_local_share()
// surface: the run-loop binds every other field, this helper only chooses, and
// forwards, the version pair. Fenced, header-only, non-consensus glue over the
// already-tap-reviewed selector.

#include <cstdint>
#include <utility>

#include "auto_ratchet_wire.hpp" // dgb_select_mint_versions, AutoRatchet
#include <core/uint256.hpp> // uint256 (also via auto_ratchet_wire)

namespace dgb
{

// Ask the ratchet for {mint, vote}, then hand them to the caller-supplied
// create step (which binds them to create_local_share's trailing
// share_version / desired_version arguments). Returns the create step's result
// verbatim — typically the new share hash. The chosen versions are NEVER a
// hardcoded constant: a VOTING node mints DGB_BASE_VERSION (35) while voting
// DGB_TARGET_VERSION (36), and follows the state machine thereafter.
//
// CreateFn signature: R(int64_t share_version, uint64_t desired_version).
template <class CreateFn>
inline auto mint_local_share_with_ratchet(
AutoRatchet& ratchet,
ShareTracker& tracker,
const uint256& best_share_hash,
CreateFn&& create_with_versions)
-> decltype(create_with_versions(int64_t{0}, uint64_t{0}))
{
auto [mint, vote] = dgb_select_mint_versions(ratchet, tracker, best_share_hash);
return std::forward<CreateFn>(create_with_versions)(
mint, static_cast<uint64_t>(vote));
}

} // namespace dgb
60 changes: 60 additions & 0 deletions src/impl/dgb/test/share_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <impl/dgb/coin/rpc_conf.hpp> // #82 external-daemon RPC creds (digibyte.conf)
#include <impl/dgb/auto_ratchet.hpp> // Phase B: mint-side share-version ratchet
#include <impl/dgb/auto_ratchet_wire.hpp> // Phase B: production wire-in (base_version=35)
#include <impl/dgb/run_loop_mint.hpp> // Phase B: run-loop {mint,vote} binding
#include <unistd.h> // getpid (AutoRatchet KAT temp state file)

#include <cstdio>
Expand Down Expand Up @@ -465,3 +466,62 @@ TEST(DGB_share_test, AutoRatchetWireBootstrapMints35Votes36)
EXPECT_EQ(vote, 36); // always vote target
EXPECT_EQ(ar.state(), dgb::RatchetState::VOTING);
}

// ---------------------------------------------------------------------------
// Run-loop mint binding (run_loop_mint.hpp) — Phase B pool/share.
// Proves the live create_local_share() caller stamps the version pair the
// AutoRatchet selector returns, NOT a hardcoded 36/36. A bootstrap (VOTING,
// empty tracker) node must mint the DGB baseline 35 while voting 36.
// ---------------------------------------------------------------------------
TEST(DGB_share_test, RunLoopMintBindsRatchetVersionsNotHardcoded)
{
auto ar = dgb::make_dgb_ratchet();
dgb::ShareTracker tracker;

int64_t seen_share_version = -1;
uint64_t seen_desired_version = 0;
uint256 sentinel; sentinel.SetHex(
"00000000000000000000000000000000000000000000000000000000deadbeef");

// Inject a spy create-step: capture the version pair the helper forwards,
// return a sentinel hash so we can also confirm pass-through.
uint256 got = dgb::mint_local_share_with_ratchet(
ar, tracker, uint256{},
[&](int64_t sv, uint64_t dv) -> uint256 {
seen_share_version = sv;
seen_desired_version = dv;
return sentinel;
});

EXPECT_EQ(seen_share_version, 35); // ratchet baseline (oracle), NOT 36
EXPECT_EQ(seen_desired_version, 36u); // always vote target
EXPECT_NE(seen_share_version, seen_desired_version); // 35 != 36: both fields
// independently threaded
EXPECT_EQ(got, sentinel); // result returned verbatim
EXPECT_EQ(ar.state(), dgb::RatchetState::VOTING);
}

// The helper must not consult/alter the ratchet beyond get_share_version — a
// second call on the same VOTING state yields the same pair (idempotent stamp).
TEST(DGB_share_test, RunLoopMintStampIsStableWhileVoting)
{
auto ar = dgb::make_dgb_ratchet();
dgb::ShareTracker tracker;

auto stamp = [&]() {
std::pair<int64_t, uint64_t> p{0, 0};
dgb::mint_local_share_with_ratchet(
ar, tracker, uint256{},
[&](int64_t sv, uint64_t dv) -> uint256 {
p = {sv, dv};
return uint256{};
});
return p;
};

auto a = stamp();
auto b = stamp();
EXPECT_EQ(a, b);
EXPECT_EQ(a.first, 35);
EXPECT_EQ(a.second, 36u);
}
Loading