1 // Copyright (c) 2026 The Limenka developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 5 #ifndef LIMENKA_POW_FORK_H
6 #define LIMENKA_POW_FORK_H
7 8 #include <arith_uint256.h>
9 #include <consensus/params.h>
10 11 #include <cstdint>
12 13 class CBlockIndex;
14 struct CBlockHeader;
15 16 /** Per-block fork DAA state (memory-only on CBlockIndex, not persisted). */
17 struct ForkDAAState {
18 arith_uint256 nForkTarget{};
19 int64_t nForkAvgError{}; // EMA accumulator (integral action)
20 int64_t nForkLastBlockTime{}; // nTime of the previous fork block
21 };
22 23 /** Compute the next required difficulty target for a fork block.
24 * Pure: does not mutate any state. `out` (if non-null) receives the
25 * DAA state to store on the new block when it is connected.
26 *
27 * Measurement basis: e = pblock->nTime - prev nTime (direct stamp
28 * delta). Controller: PI asymmetric with corrected naming -
29 * P (proportional, kp) acts on the instantaneous error, I (integral,
30 * ki_up/ki_down) acts on the EMA accumulator. Raise slow / lower
31 * fast. The setpoint nForkIntervalTarget is calibrated above 600s to
32 * cancel the asymmetric-integral rectification bias.
33 */
34 uint32_t CalculateForkTarget(const CBlockIndex* pindexPrev,
35 const CBlockHeader* pblock,
36 const Consensus::Params& params,
37 ForkDAAState* out = nullptr);
38 39 /** Initialize fork DAA state at activation, seeding from the block's own
40 * difficulty so the fork continues the parent chain's cadence. */
41 void InitForkDAAState(CBlockIndex* pindex);
42 43 /** Get the current DAA target. */
44 arith_uint256 GetForkTarget(const CBlockIndex* pindex);
45 46 #endif // LIMENKA_POW_FORK_H
47