64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
package keeper
|
|
|
|
import (
|
|
"context"
|
|
|
|
"mukan/x/poj/types"
|
|
|
|
sdk "github.com/cosmos/cosmos-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
|
|
}
|