fish2018/pansou · error
计算 Anubis 工作量证明失败
Error message
计算 Anubis 工作量证明失败: %w
What it means
solveAnubisChallenge brute-forces nonces until the SHA-256 of randomData+nonce has the required leading zero nibbles, checking ctx.Done() every 4096 iterations. This error wraps the context error (deadline/cancel) that aborts the PoW loop (miosou.go:281).
Solutions
- Increase gateTimeout to give slow hardware time to finish the PoW.
- Reduce concurrent work while solving (run gate completion serially, avoid competing CPU load).
- Upgrade the solver to check multiple nonces per hash or use a faster SHA-256 implementation / parallel workers.
- Cap handled difficulty: if the challenge difficulty keeps exceeding what the host can solve in time, treat it as a server misconfiguration and report it.
- Rely on ensureGate's retries — an easier challenge may be issued next attempt.
Example fix
// before ctx, cancel := context.WithTimeout(context.Background(), gateTimeout) // e.g. 5s // after ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // headroom for high difficulty
Defensive patterns
Strategy: retry
Validate before calling
// estimate feasibility before solving: expected hashes = 16^difficulty
expected := math.Pow(16, float64(difficulty))
if expected > 1e9 {
return fmt.Errorf("difficulty %d likely exceeds CPU budget", difficulty)
} Try / catch
err := p.ensureGate()
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), "计算 Anubis 工作量证明失败") {
// PoW budget exhausted: raise gateTimeout or reduce CPU contention and retry
}
return err
} Prevention
- Set gateTimeout generously for low-power hardware
- Check ctx.Err() diagnostics: DeadlineExceeded vs Canceled
- Avoid concurrent gate solves competing for CPU
- Consider a parallel/optimized SHA-256 solver for difficulty >= 5
- Cap the difficulty you attempt and report higher values as server misconfiguration
When it happens
Trigger: The gateTimeout context expires or is cancelled while the PoW loop is still running — difficulty is too high for the hardware, or the deadline is too tight.
Common situations: Difficulty 5–7 on low-power devices (routers, small VPS, shared CI runners); heavily loaded CPU; too-short gateTimeout; many concurrent gate attempts starving the CPU.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/6e170a40a787ca9c.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/miosou/miosou.go:281
}
if challenge.Challenge.ID == "" || challenge.Challenge.RandomData == "" || challenge.Rules.Difficulty < 1 || challenge.Rules.Difficulty > 7 {
return anubisChallengeDocument{}, true, fmt.Errorf("Anubis 验证题目无效")
}
if challenge.Rules.Algorithm != "fast" && challenge.Rules.Algorithm != "slow" {
return anubisChallengeDocument{}, true, fmt.Errorf("不支持的 Anubis 验证算法: %s", challenge.Rules.Algorithm)
}
return challenge, true, nil
}
func solveAnubisChallenge(ctx context.Context, randomData string, difficulty int) (string, uint64, error) {
prefix := []byte(randomData)
buffer := make([]byte, len(prefix), len(prefix)+20)
copy(buffer, prefix)
for nonce := uint64(0); ; nonce++ {
if nonce&4095 == 0 {
select {
case <-ctx.Done():
return "", 0, fmt.Errorf("计算 Anubis 工作量证明失败: %w", ctx.Err())
default:
}
}
candidate := strconv.AppendUint(buffer[:len(prefix)], nonce, 10)
hash := sha256.Sum256(candidate)
if hasLeadingZeroNibbles(hash[:], difficulty) {
return hex.EncodeToString(hash[:]), nonce, nil
}
}
}
func hasLeadingZeroNibbles(hash []byte, difficulty int) bool {
for i := 0; i < difficulty/2; i++ {
if hash[i] != 0 {
return false
}
}
return difficulty%2 == 0 || hash[difficulty/2]>>4 == 0View on GitHub (pinned to beaa561337)