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

  1. Increase gateTimeout to give slow hardware time to finish the PoW.
  2. Reduce concurrent work while solving (run gate completion serially, avoid competing CPU load).
  3. Upgrade the solver to check multiple nonces per hash or use a faster SHA-256 implementation / parallel workers.
  4. 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.
  5. 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

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 == 0

View on GitHub (pinned to beaa561337)