Add mining self-surgery for on-host recovery when AI control detects stalls.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
When ai_control_enabled and mining interrupts or hashrate drops, the server composes same-agent fix plans (container restart, chain reorder, GPU swap, idle tune, RandomX restart) with Seer and oath ledger audit — no spread or lateral escalation.
This commit is contained in:
@@ -33,6 +33,15 @@ func NewEngine() *Engine {
|
||||
return &Engine{cache: cache}
|
||||
}
|
||||
|
||||
// Reset clears the VM so the next SetJob reinitializes RandomX state.
|
||||
func (e *Engine) Reset() {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
e.vm = nil
|
||||
e.seedHex = ""
|
||||
e.blob = nil
|
||||
}
|
||||
|
||||
func (e *Engine) SetJob(seedHex, blobHex string) error {
|
||||
seed, err := hex.DecodeString(seedHex)
|
||||
if err != nil {
|
||||
|
||||
@@ -788,6 +788,31 @@ func (c *ChainController) SetChainOrderForTest(chain []MiningMethod) {
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// ReorderChain replaces the cascade order and optionally skips failed methods.
|
||||
func (c *ChainController) ReorderChain(chain []MiningMethod, skip []MiningMethod) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
skipSet := make(map[MiningMethod]bool, len(skip))
|
||||
for _, m := range skip {
|
||||
skipSet[m] = true
|
||||
}
|
||||
if len(chain) > 0 {
|
||||
c.chain = append([]MiningMethod(nil), chain...)
|
||||
} else if len(skip) > 0 {
|
||||
filtered := make([]MiningMethod, 0, len(c.chain))
|
||||
for _, m := range c.chain {
|
||||
if !skipSet[m] {
|
||||
filtered = append(filtered, m)
|
||||
}
|
||||
}
|
||||
c.chain = filtered
|
||||
}
|
||||
c.failures = nil
|
||||
c.chainExhausted = false
|
||||
c.lastError = ""
|
||||
c.lastFullPass = time.Time{}
|
||||
}
|
||||
|
||||
// Monitor watches container health and advances the chain on exit.
|
||||
func (c *ChainController) Monitor(ctx context.Context) {
|
||||
ticker := time.NewTicker(10 * time.Second)
|
||||
|
||||
29
agent/miner/fallback_chain_reorder_test.go
Normal file
29
agent/miner/fallback_chain_reorder_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package miner
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"crypto-miner-agent/config"
|
||||
)
|
||||
|
||||
func TestReorderChainSkipsFailedMethods(t *testing.T) {
|
||||
c := NewChainController(config.RuntimeConfig{}, ChainHooks{}, nil)
|
||||
c.SetChainOrderForTest([]MiningMethod{MethodContainer, MethodInProcess, MethodGPUSubprocess})
|
||||
c.ReorderChain(nil, []MiningMethod{MethodContainer})
|
||||
st := c.Status()
|
||||
if len(st.ChainOrder) != 2 {
|
||||
t.Fatalf("chain=%v", st.ChainOrder)
|
||||
}
|
||||
if st.ChainOrder[0] != MethodInProcess {
|
||||
t.Fatalf("first=%v want inprocess", st.ChainOrder[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReorderChainReplacesOrder(t *testing.T) {
|
||||
c := NewChainController(config.RuntimeConfig{}, ChainHooks{}, nil)
|
||||
c.ReorderChain([]MiningMethod{MethodInProcess, MethodWSL}, nil)
|
||||
st := c.Status()
|
||||
if len(st.ChainOrder) != 2 || st.ChainOrder[0] != MethodInProcess {
|
||||
t.Fatalf("chain=%v", st.ChainOrder)
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,22 @@ func (p *Pool) UpdateRuntimePolicy(cfg config.RuntimeConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// RestartRandomX reinitializes in-process RandomX engines and resumes hashing.
|
||||
func (p *Pool) RestartRandomX() {
|
||||
p.mu.Lock()
|
||||
job := p.currentJob
|
||||
engines := p.engines
|
||||
p.mu.Unlock()
|
||||
for _, engine := range engines {
|
||||
engine.Reset()
|
||||
}
|
||||
if job != nil {
|
||||
p.SetJob(job)
|
||||
}
|
||||
p.remotePause.Store(false)
|
||||
p.paused.Store(false)
|
||||
}
|
||||
|
||||
func (p *Pool) SetJob(job *job.Job) {
|
||||
p.mu.Lock()
|
||||
p.currentJob = job
|
||||
|
||||
Reference in New Issue
Block a user