From d1dd21b61cbdfc80c071e64fcb75293a4142c4fe Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 24 Jul 2026 16:24:21 -0500 Subject: [PATCH] concurrent solver --- main.go | 86 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/main.go b/main.go index 9e20b12..f01c1a4 100644 --- a/main.go +++ b/main.go @@ -1,33 +1,39 @@ package main import ( + "context" "crypto" _ "crypto/sha1" - "encoding/base64" + "encoding/hex" "fmt" "math/rand" "os" + "runtime" "time" ) func main() { g := Generator{ Difficulty: 25, + Timeout: 10 * time.Second, } c := g.RandomChallenge() c.Solve() - fmt.Println(c.String()) + if c.Validate() { + fmt.Println(c.String()) + } } type Challenge struct { - Input [48]byte - Date [20]byte - Difficulty byte - Solution int64 - bytes []byte + Input [48]byte + Date [20]byte + Solution int64 + bytes []byte + Generator } type Generator struct { Difficulty byte + Timeout time.Duration } func (g *Generator) RandomChallenge() Challenge { @@ -39,9 +45,9 @@ func (g *Generator) RandomChallenge() Challenge { date := today.Format("2006-01-02") hash := crypto.SHA1.New().Sum([]byte(date)) return Challenge{ - Input: [48]byte(bytes), - Date: [20]byte(hash), - Difficulty: g.Difficulty, + Input: [48]byte(bytes), + Date: [20]byte(hash), + Generator: *g, } } @@ -70,25 +76,59 @@ func (c *Challenge) Solve() { c.bytes = append(c.bytes, c.Input[:]...) c.bytes = append(c.bytes, c.Date[:]...) timer := time.Now() - for { - s := c.Validate() - if s { - fmt.Fprintf(os.Stderr, "%s: found solution %d in %dms\n", c.String(), c.Solution, time.Since(timer).Milliseconds()) - break - } - if c.Solution > 0xffffffffffffff { - fmt.Fprintf(os.Stderr, "%s: could not find solution!", c.String()) - } - c.Solution++ + solution := make(chan int64) + ctx, cancel := context.WithCancel(context.Background()) + count := runtime.NumCPU() + for i := range count { + go func(id int, ctx context.Context) { + i := int64(id) + defer cancel() + for { + select { + case <-ctx.Done(): + return + default: + s := c.CheckValue(i) + if s { + solution <- i + fmt.Fprintf(os.Stderr, "[thread %d] ", id) + cancel() + break + } + if c.Solution > 0xffffffffffffff { + fmt.Fprintf(os.Stderr, "%s (thread %d): could not find solution!\n", c.String(), id) + cancel() + break + } + if time.Since(timer) > c.Timeout { + fmt.Fprintf(os.Stderr, "%s (thread %d): timed out!\n", c.String(), id) + cancel() + break + } + i += int64(count) + } + } + }(i, ctx) + } + select { + case c.Solution = <-solution: + cancel() + fmt.Fprintf(os.Stderr, "%s: found solution %d in %dms\n", c.String(), c.Solution, time.Since(timer).Milliseconds()) + break + case <-ctx.Done(): + cancel() + break } } func (c *Challenge) CheckValue(v int64) bool { + bytes := make([]byte, len(c.bytes)) + copy(bytes, c.bytes) for i := range 8 { - c.bytes[75-i] = byte(v >> (i * 8)) + bytes[75-i] = byte(v >> (i * 8)) } sum := make([]byte, 20) hash := crypto.SHA1.New() - hash.Write(c.bytes) + hash.Write(bytes) sum = hash.Sum(nil) count := 0 for _, c := range sum { @@ -112,5 +152,5 @@ func (c *Challenge) String() string { for i := range 7 { bytes[75-i] = byte(c.Solution >> (i * 8)) } - return base64.URLEncoding.EncodeToString(bytes) + return hex.EncodeToString(bytes) }