mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-15 05:35:07 +08:00
refactor: replace WASM-based PoW with a high-performance native Go implementation and add context support for cancellation.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package pow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Challenge 对应 /api/v0/chat/create_pow_challenge 返回的 data.biz_data.challenge。
|
||||
// Challenge 对应 /api/v0/chat/create_pow_challenge 返回 dem data.biz_data.challenge。
|
||||
type Challenge struct {
|
||||
Algorithm string `json:"algorithm"`
|
||||
Challenge string `json:"challenge"`
|
||||
@@ -27,7 +28,7 @@ func BuildPrefix(salt string, expireAt int64) string {
|
||||
|
||||
// SolvePow 搜索 nonce ∈ [0, difficulty) 使得 DeepSeekHashV1(prefix+str(nonce)) == challenge。
|
||||
// prefix 预吸收进 state,循环内零分配。
|
||||
func SolvePow(challengeHex, salt string, expireAt, difficulty int64) (int64, error) {
|
||||
func SolvePow(ctx context.Context, challengeHex, salt string, expireAt, difficulty int64) (int64, error) {
|
||||
if len(challengeHex) != 64 {
|
||||
return 0, errors.New("pow: challenge must be 64 hex chars")
|
||||
}
|
||||
@@ -59,6 +60,13 @@ func SolvePow(challengeHex, salt string, expireAt, difficulty int64) (int64, err
|
||||
|
||||
var numBuf [20]byte
|
||||
for n := int64(0); n < difficulty; n++ {
|
||||
// Periodically check if context is canceled to avoid wasting CPU
|
||||
if n&0x3FF == 0 {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
v := uint64(n)
|
||||
pos := 20
|
||||
if v == 0 {
|
||||
@@ -123,7 +131,7 @@ func BuildPowHeader(c *Challenge, answer int64) (string, error) {
|
||||
}
|
||||
|
||||
// SolveAndBuildHeader 端到端: Challenge → x-ds-pow-response header string。
|
||||
func SolveAndBuildHeader(c *Challenge) (string, error) {
|
||||
func SolveAndBuildHeader(ctx context.Context, c *Challenge) (string, error) {
|
||||
if c.Algorithm != "DeepSeekHashV1" {
|
||||
return "", errors.New("pow: unsupported algorithm: " + c.Algorithm)
|
||||
}
|
||||
@@ -131,7 +139,7 @@ func SolveAndBuildHeader(c *Challenge) (string, error) {
|
||||
if d == 0 {
|
||||
d = 144000
|
||||
}
|
||||
answer, err := SolvePow(c.Challenge, c.Salt, c.ExpireAt, d)
|
||||
answer, err := SolvePow(ctx, c.Challenge, c.Salt, c.ExpireAt, d)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package pow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@@ -36,7 +37,7 @@ func TestSolvePow(t *testing.T) {
|
||||
{"abc123salt", 1700000000, 12345, 20000},
|
||||
} {
|
||||
h := DeepSeekHashV1([]byte(BuildPrefix(tc.salt, tc.expire) + strconv.FormatInt(tc.answer, 10)))
|
||||
got, err := SolvePow(hex.EncodeToString(h[:]), tc.salt, tc.expire, tc.diff)
|
||||
got, err := SolvePow(context.Background(), hex.EncodeToString(h[:]), tc.salt, tc.expire, tc.diff)
|
||||
if err != nil || got != tc.answer {
|
||||
t.Errorf("salt=%q answer=%d: got=%d err=%v", tc.salt, tc.answer, got, err)
|
||||
}
|
||||
@@ -45,7 +46,7 @@ func TestSolvePow(t *testing.T) {
|
||||
|
||||
func TestSolveAndBuildHeader(t *testing.T) {
|
||||
t0 := DeepSeekHashV1([]byte("salt_1712345678_777"))
|
||||
header, err := SolveAndBuildHeader(&Challenge{
|
||||
header, err := SolveAndBuildHeader(context.Background(), &Challenge{
|
||||
Algorithm: "DeepSeekHashV1", Challenge: hex.EncodeToString(t0[:]),
|
||||
Salt: "salt", ExpireAt: 1712345678, Difficulty: 2000,
|
||||
Signature: "sig", TargetPath: "/api/v0/chat/completion",
|
||||
@@ -74,6 +75,6 @@ func BenchmarkSolve(b *testing.B) {
|
||||
h := DeepSeekHashV1([]byte("realisticsalt_1712345678_72000"))
|
||||
ch := hex.EncodeToString(h[:])
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = SolvePow(ch, "realisticsalt", 1712345678, 144000)
|
||||
_, _ = SolvePow(context.Background(), ch, "realisticsalt", 1712345678, 144000)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user