concurrent solver
This commit is contained in:
@@ -1,33 +1,39 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
_ "crypto/sha1"
|
_ "crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
g := Generator{
|
g := Generator{
|
||||||
Difficulty: 25,
|
Difficulty: 25,
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
}
|
}
|
||||||
c := g.RandomChallenge()
|
c := g.RandomChallenge()
|
||||||
c.Solve()
|
c.Solve()
|
||||||
|
if c.Validate() {
|
||||||
fmt.Println(c.String())
|
fmt.Println(c.String())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Challenge struct {
|
type Challenge struct {
|
||||||
Input [48]byte
|
Input [48]byte
|
||||||
Date [20]byte
|
Date [20]byte
|
||||||
Difficulty byte
|
|
||||||
Solution int64
|
Solution int64
|
||||||
bytes []byte
|
bytes []byte
|
||||||
|
Generator
|
||||||
}
|
}
|
||||||
type Generator struct {
|
type Generator struct {
|
||||||
Difficulty byte
|
Difficulty byte
|
||||||
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Generator) RandomChallenge() Challenge {
|
func (g *Generator) RandomChallenge() Challenge {
|
||||||
@@ -41,7 +47,7 @@ func (g *Generator) RandomChallenge() Challenge {
|
|||||||
return Challenge{
|
return Challenge{
|
||||||
Input: [48]byte(bytes),
|
Input: [48]byte(bytes),
|
||||||
Date: [20]byte(hash),
|
Date: [20]byte(hash),
|
||||||
Difficulty: g.Difficulty,
|
Generator: *g,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,25 +76,59 @@ func (c *Challenge) Solve() {
|
|||||||
c.bytes = append(c.bytes, c.Input[:]...)
|
c.bytes = append(c.bytes, c.Input[:]...)
|
||||||
c.bytes = append(c.bytes, c.Date[:]...)
|
c.bytes = append(c.bytes, c.Date[:]...)
|
||||||
timer := time.Now()
|
timer := time.Now()
|
||||||
|
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 {
|
for {
|
||||||
s := c.Validate()
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
s := c.CheckValue(i)
|
||||||
if s {
|
if s {
|
||||||
fmt.Fprintf(os.Stderr, "%s: found solution %d in %dms\n", c.String(), c.Solution, time.Since(timer).Milliseconds())
|
solution <- i
|
||||||
|
fmt.Fprintf(os.Stderr, "[thread %d] ", id)
|
||||||
|
cancel()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if c.Solution > 0xffffffffffffff {
|
if c.Solution > 0xffffffffffffff {
|
||||||
fmt.Fprintf(os.Stderr, "%s: could not find solution!", c.String())
|
fmt.Fprintf(os.Stderr, "%s (thread %d): could not find solution!\n", c.String(), id)
|
||||||
|
cancel()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
c.Solution++
|
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 {
|
func (c *Challenge) CheckValue(v int64) bool {
|
||||||
|
bytes := make([]byte, len(c.bytes))
|
||||||
|
copy(bytes, c.bytes)
|
||||||
for i := range 8 {
|
for i := range 8 {
|
||||||
c.bytes[75-i] = byte(v >> (i * 8))
|
bytes[75-i] = byte(v >> (i * 8))
|
||||||
}
|
}
|
||||||
sum := make([]byte, 20)
|
sum := make([]byte, 20)
|
||||||
hash := crypto.SHA1.New()
|
hash := crypto.SHA1.New()
|
||||||
hash.Write(c.bytes)
|
hash.Write(bytes)
|
||||||
sum = hash.Sum(nil)
|
sum = hash.Sum(nil)
|
||||||
count := 0
|
count := 0
|
||||||
for _, c := range sum {
|
for _, c := range sum {
|
||||||
@@ -112,5 +152,5 @@ func (c *Challenge) String() string {
|
|||||||
for i := range 7 {
|
for i := range 7 {
|
||||||
bytes[75-i] = byte(c.Solution >> (i * 8))
|
bytes[75-i] = byte(c.Solution >> (i * 8))
|
||||||
}
|
}
|
||||||
return base64.URLEncoding.EncodeToString(bytes)
|
return hex.EncodeToString(bytes)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user