mukan-core/x/poj/keeper/arbiter.go
2026-05-11 03:46:11 +03:00

64 lines
1.5 KiB
Go

package keeper
import (
"context"
"mukan/x/poj/types"
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
)
// ProcessBlockReward applies the PoJ logic (Micro/Macro Fren) for a miner.
// Returns true if the miner is allowed to receive a reward for this block.
func (k Keeper) ProcessBlockReward(ctx context.Context, minerAddr string) bool {
sdkCtx := sdk.UnwrapSDKContext(ctx)
// 0. Bootstrap check: No automatic proposer rewards in Phase 1
if k.IsBootstrapping(ctx) {
return false
}
state, found := k.GetMinerState(ctx, minerAddr)
if !found {
state = types.MinerState{
Address: minerAddr,
ConsecutiveWins: 0,
StreakCount: 0,
CooldownUntil: 0,
}
}
currentBlock := sdkCtx.BlockHeight()
params, _ := k.Params.Get(ctx)
// 1. Cooldown check
if state.CooldownUntil >= currentBlock {
// Solution rejected - no reward produced.
return false
}
// 2. Consecutive wins increment
state.ConsecutiveWins++
if state.ConsecutiveWins < 2 {
// No streak yet, award reward
k.SetMinerState(ctx, state)
return true
}
// 3. Micro Fren: 2nd consecutive win
state.StreakCount++
state.ConsecutiveWins = 0
if state.StreakCount >= params.MacroStreakLimit {
// 4. Macro Fren: 5th streak -> Big Break
state.CooldownUntil = currentBlock + params.MacroCooldown
state.StreakCount = 0 // RESET - penalty served, clean slate
} else {
// Micro Fren: 1 block wait
state.CooldownUntil = currentBlock + params.MicroCooldown
}
k.SetMinerState(ctx, state)
return true // Current block reward is given, cooldown affects the next one
}