Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ We support various languages to help you solve the obnoxious PoW.
- [X] NodeJs
- [X] Browser-based
- [X] Ruby
- [X] Go (contributed by [Lee Xun](https://github.com/LeeXun))
- [X] Go (contributed by [Lee Xun](https://github.com/LeeXun), optimized by @RobinJadoul)
- [ ] Rust
- [ ] C/C++
- [ ] Java
Expand Down
75 changes: 24 additions & 51 deletions solver/go.go
Original file line number Diff line number Diff line change
@@ -1,68 +1,41 @@
package pow
package main

import (
"crypto/sha256"
"errors"
"fmt"
"os"
"strconv"
"encoding/binary"
"math/bits"
)

// Solver is a pow solver
type Solver struct {
SolverConfig
}

// SolverConfig is config struct for Solver
type SolverConfig struct {
Prefix string
Difficulty int
}

// New returns a POW solver
func New(c SolverConfig) (*Solver, error) {
if c.Difficulty <= 0 {
return nil, errors.New("Difficulty should > 0")
}
return &Solver{
SolverConfig{
Prefix: c.Prefix,
Difficulty: c.Difficulty,
},
}, nil
}

// Solve returns two fields,
// @ret1 the number of iteration after solving the pow.
// @ret2 binary form of the answer.
func (s *Solver) Solve() (attempts int, binaryString string) {
// Solve returns an integer, for which the decimal representation as a string is the solution to the PoW:
// binstr(sha256(prefix + str(i))).startswith("0"*difficulty)
// @arg prefix The prefix for hashing
// @arg difficulty The number of leading 0 bits wanted
// @ret The solution to the PoW.
func Solve(prefix string, difficulty int) int {
var i int
var ss string
for {
sum := sha256.Sum256([]byte(fmt.Sprintf("%s%v", s.Prefix, i)))
ss = toBinString(sum)
if isValid(ss, s.Difficulty) {
sum := sha256.Sum256([]byte(fmt.Sprintf("%s%v", prefix, i)))
if bits.LeadingZeros64(binary.BigEndian.Uint64(sum[:8])) >= difficulty {
break
}
i++
}
return i, ss
return i
}

func toBinString(s [sha256.Size]byte) string {
var ss string
for _, b := range s {
ss = fmt.Sprintf("%s%08b", ss, b)
func main() {
if len(os.Args) != 3 {
fmt.Printf("Usage: %s <prefix> <difficulty>\n", os.Args[0])
return
}
return ss
}

func isValid(ss string, d int) bool {
for i := range ss {
if i >= d {
break
}
if ss[i] != '0' {
return false
}
dif, err := strconv.Atoi(os.Args[2])
if err != nil {
fmt.Printf("Difficulty is not a valid integer: %s\n", os.Args[2])
return
}
return true
i := Solve(os.Args[1], dif)
fmt.Println(i)
}