re add pow captcha (initial)
This commit is contained in:
parent
2bb4540118
commit
c3426871d2
30
Makefile
30
Makefile
@ -1,7 +1,9 @@
|
||||
REPO=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
REPO_GOPATH=$(REPO)/go
|
||||
MINIFY=$(REPO_GOPATH)/bin/minify
|
||||
JS=$(REPO)/contrib/static/nntpchan.js
|
||||
STATIC_DIR=$(REPO)/contrib/static
|
||||
JS=$(STATIC_DIR)/nntpchan.js
|
||||
MINER_JS=$(STATIC_DIR)/miner-js.js
|
||||
CONTRIB_JS=$(REPO)/contrib/js/contrib
|
||||
LOCAL_JS=$(REPO)/contrib/js/nntpchan
|
||||
VENDOR_JS=$(REPO)/contrib/js/vendor
|
||||
@ -15,6 +17,11 @@ NNTPD=$(REPO)/nntpd
|
||||
GOROOT=$(shell go env GOROOT)
|
||||
GO=$(GOROOT)/bin/go
|
||||
|
||||
GOPHERJS_GOROOT ?= $(GOROOT)
|
||||
GOPHERJS_GO = $(GOPHERJS_GOROOT)/bin/go
|
||||
|
||||
GOPHERJS=$(REPO_GOPATH)/bin/gopherjs
|
||||
|
||||
all: clean build
|
||||
|
||||
build: js srnd
|
||||
@ -23,14 +30,23 @@ full: clean full-build
|
||||
|
||||
full-build: srnd beta native
|
||||
|
||||
js: $(JS)
|
||||
js: $(JS) $(MINER_JS)
|
||||
|
||||
srnd: $(SRND)
|
||||
|
||||
$(MINIFY):
|
||||
GOPATH=$(REPO_GOPATH) go get -v github.com/tdewolff/minify/cmd/minify
|
||||
GOPATH=$(REPO_GOPATH) $(GO) get -v github.com/tdewolff/minify/cmd/minify
|
||||
|
||||
js-deps: $(MINIFY)
|
||||
$(GOPHERJS):
|
||||
GOPATH=$(REPO_GOPATH) $(GOPHERJS_GO) get -v github.com/gopherjs/gopherjs
|
||||
|
||||
js-deps: $(MINIFY) $(MINER_JS)
|
||||
|
||||
$(MINER_JS): $(GOPHERJS) $(MINIFY)
|
||||
cp -rf $(SRND_DIR)/src/github.com $(REPO_GOPATH)/src/
|
||||
GOROOT=$(GOPHERJS_GOROOT) GOPATH=$(REPO_GOPATH) $(GOPHERJS) -m -v build github.com/ZiRo-/cuckgo/miner_js
|
||||
$(MINIFY) --mime=text/javascript > $(STATIC_DIR)/miner-js.js < miner_js.js
|
||||
rm -f miner_js.js.map miner_js.js
|
||||
|
||||
$(JS): js-deps
|
||||
rm -f $(JS)
|
||||
@ -70,16 +86,16 @@ test-native:
|
||||
GOROOT=$(GOROOT) $(MAKE) -C $(NNTPCHAN_DAEMON_DIR) test
|
||||
|
||||
|
||||
clean: clean-js clean-srnd
|
||||
clean: clean-srnd clean-js
|
||||
|
||||
clean-full: clean clean-beta clean-native
|
||||
clean-full: clean clean-beta clean-native clean-js
|
||||
|
||||
clean-srnd:
|
||||
rm -f $(SRND)
|
||||
GOROOT=$(GOROOT) $(MAKE) -C $(SRND_DIR) clean
|
||||
|
||||
clean-js:
|
||||
rm -f $(JS)
|
||||
rm -f $(JS) $(MINER_JS)
|
||||
|
||||
clean-beta:
|
||||
rm -f $(NNTPCHAND)
|
||||
|
11
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/.gitignore
vendored
Normal file
11
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.pyc
|
||||
*~
|
||||
*.ini
|
||||
*.db
|
||||
build.dir
|
||||
\#*
|
||||
.\#*
|
||||
_obj
|
||||
*.log
|
||||
*.la
|
||||
*.txt
|
21
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/LICENSE
Normal file
21
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo-
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,41 @@
|
||||
|
||||
Cuckoo Cycle
|
||||
============
|
||||
# Go implementation
|
||||
This is a Go implementation of the cuckoo Proof of Work algorith "cuckoo cycle" by John Tromp.
|
||||
This implementation includes the verification function as a library, and a simple multi-threaded miner.
|
||||
|
||||
# Installation
|
||||
To install this miner just run
|
||||
`go get github.com/ZiRo-/cuckgo/miner`
|
||||
|
||||
# Usage
|
||||
|
||||
```
|
||||
Usage of miner:
|
||||
-e float
|
||||
easiness in percentage (default 50)
|
||||
-m int
|
||||
maximum number of solutions (default 8)
|
||||
-t int
|
||||
number of miner threads (default 4)
|
||||
```
|
||||
# Algorithm
|
||||
|
||||
For details about the algorith, see: https://github.com/tromp/cuckoo
|
||||
|
||||
# Benchmarks
|
||||
#### N = 100, Easiness = 55, Average time = 0.9 s, CPU = i5-4210U
|
||||
![N = 100, Easiness = 55, Average time = 0.9 s, CPU = i5-4210U] (https://raw.githubusercontent.com/ZiRo-/cuckgo/master/bench/bench_N_100_e_55_avg_0.9.png)
|
||||
|
||||
#### N = 100, Easiness = 50, Average time = 2.3 s, CPU = i5-4210U
|
||||
![N = 100, Easiness = 50, Average time = 2.3 s, CPU = i5-4210U] (https://raw.githubusercontent.com/ZiRo-/cuckgo/master/bench/bench_N_100_e_50_avg_2.3.png)
|
||||
|
||||
#### N = 300, Easiness = 46, Average time = 56.2 s, CPU = i5-4210U
|
||||
![N = 300, Easiness = 46, Average time = 56.2 s, CPU = i5-4210U] (https://raw.githubusercontent.com/ZiRo-/cuckgo/master/bench/bench_N_300_e_46_avg_56.2.png)
|
||||
|
||||
# JavaScript version
|
||||
Using [GopherJS](https://github.com/gopherjs/gopherjs) the Go implementation can be transpiled to JavaScript,
|
||||
which is also included in this repo. This file currently exports one function:
|
||||
`cuckoo["mine_cuckoo"](easiness)`
|
||||
which returns the same base64 representation of a proof as the Go CLI miner.
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,56 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/ZiRo-/cuckgo/cuckoo"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
data, err := base64.StdEncoding.DecodeString(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
cuck, err := cuckoo.DecodeCuckooJSON(data)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
//fmt.Println(cuck)
|
||||
|
||||
if cuckoo.VerifyJSON(*cuck) {
|
||||
fmt.Println("Valid")
|
||||
os.Exit(0)
|
||||
} else {
|
||||
fmt.Println("Invalid")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package cuckoo
|
||||
|
||||
import "crypto/sha256"
|
||||
|
||||
const (
|
||||
SIZESHIFT uint64 = 20
|
||||
PROOFSIZE uint64 = 42
|
||||
SIZE uint64 = 1 << SIZESHIFT
|
||||
HALFSIZE uint64 = SIZE / 2
|
||||
NODEMASK uint64 = HALFSIZE - 1
|
||||
)
|
||||
|
||||
type Cuckoo struct {
|
||||
v [4]uint64
|
||||
}
|
||||
|
||||
func u8(b byte) uint64 {
|
||||
return (uint64)(b) & 0xff
|
||||
}
|
||||
|
||||
func u8to64(p [sha256.Size]byte, i int) uint64 {
|
||||
return u8(p[i]) | u8(p[i+1])<<8 |
|
||||
u8(p[i+2])<<16 | u8(p[i+3])<<24 |
|
||||
u8(p[i+4])<<32 | u8(p[i+5])<<40 |
|
||||
u8(p[i+6])<<48 | u8(p[i+7])<<56
|
||||
}
|
||||
|
||||
func NewCuckoo(header []byte) *Cuckoo {
|
||||
hdrkey := sha256.Sum256(header)
|
||||
|
||||
return NewCuckooSHA(hdrkey)
|
||||
}
|
||||
|
||||
func NewCuckooSHA(hdrkey [sha256.Size]byte) *Cuckoo {
|
||||
self := new(Cuckoo)
|
||||
k0 := u8to64(hdrkey, 0)
|
||||
k1 := u8to64(hdrkey, 8)
|
||||
self.v[0] = k0 ^ 0x736f6d6570736575
|
||||
self.v[1] = k1 ^ 0x646f72616e646f6d
|
||||
self.v[2] = k0 ^ 0x6c7967656e657261
|
||||
self.v[3] = k1 ^ 0x7465646279746573
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
type Edge struct {
|
||||
U uint64
|
||||
V uint64
|
||||
}
|
||||
|
||||
func (self *Edge) HashCode() int {
|
||||
return int(self.U) ^ int(self.V)
|
||||
}
|
||||
|
||||
func (self *Cuckoo) Sipedge(nonce uint64) *Edge {
|
||||
return &Edge{self.Sipnode(nonce, 0), self.Sipnode(nonce, 1)}
|
||||
}
|
||||
|
||||
func (self *Cuckoo) siphash24(nonce uint64) uint64 {
|
||||
v0 := self.v[0]
|
||||
v1 := self.v[1]
|
||||
v2 := self.v[2]
|
||||
v3 := self.v[3] ^ nonce
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
|
||||
v0 ^= nonce
|
||||
v2 ^= 0xff
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
|
||||
v0 += v1
|
||||
v2 += v3
|
||||
v1 = (v1 << 13) | v1>>51
|
||||
v3 = (v3 << 16) | v3>>48
|
||||
v1 ^= v0
|
||||
v3 ^= v2
|
||||
v0 = (v0 << 32) | v0>>32
|
||||
v2 += v1
|
||||
v0 += v3
|
||||
v1 = (v1 << 17) | v1>>47
|
||||
v3 = (v3 << 21) | v3>>43
|
||||
v1 ^= v2
|
||||
v3 ^= v0
|
||||
v2 = (v2 << 32) | v2>>32
|
||||
return v0 ^ v1 ^ v2 ^ v3
|
||||
}
|
||||
|
||||
// generate edge in cuckoo graph
|
||||
func (self *Cuckoo) Sipnode(nonce uint64, uorv uint32) uint64 {
|
||||
return self.siphash24(2*nonce+uint64(uorv)) & NODEMASK
|
||||
}
|
||||
|
||||
// verify that (ascending) nonces, all less than easiness, form a cycle in graph
|
||||
func (self *Cuckoo) Verify(nonces []uint64, easiness uint64) bool {
|
||||
us := make([]uint64, PROOFSIZE)
|
||||
vs := make([]uint64, PROOFSIZE)
|
||||
i := 0
|
||||
var n uint64
|
||||
|
||||
for n = 0; n < PROOFSIZE; n++ {
|
||||
if nonces[n] >= easiness || (n != 0 && nonces[n] <= nonces[n-1]) {
|
||||
return false
|
||||
}
|
||||
us[n] = self.Sipnode(nonces[n], 0)
|
||||
vs[n] = self.Sipnode(nonces[n], 1)
|
||||
}
|
||||
|
||||
loop := true
|
||||
for loop { // follow cycle until we return to i==0; n edges left to visit
|
||||
j := i
|
||||
for k := 0; uint64(k) < PROOFSIZE; k++ { // find unique other j with same vs[j]
|
||||
if k != i && vs[k] == vs[i] {
|
||||
if j != i {
|
||||
return false
|
||||
}
|
||||
j = k
|
||||
}
|
||||
}
|
||||
if j == i {
|
||||
return false
|
||||
}
|
||||
i = j
|
||||
for k := 0; uint64(k) < PROOFSIZE; k++ { // find unique other i with same us[i]
|
||||
if k != j && us[k] == us[j] {
|
||||
if i != j {
|
||||
return false
|
||||
}
|
||||
i = k
|
||||
}
|
||||
}
|
||||
if i == j {
|
||||
return false
|
||||
}
|
||||
n -= 2
|
||||
loop = (i != 0)
|
||||
}
|
||||
return n == 0
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package cuckoo
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type CuckooJSON struct {
|
||||
Parameter map[string]uint64 `json:"parameters"`
|
||||
InputData []byte `json:"header"` //sha256 bytes
|
||||
Cycle []uint64 `json:"cycle"`
|
||||
}
|
||||
|
||||
func DecodeCuckooJSON(jsonBlob []byte) (*CuckooJSON, error) {
|
||||
res := new(CuckooJSON)
|
||||
err := json.Unmarshal(jsonBlob, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func EncodeCuckooJSON(cuck CuckooJSON) ([]byte, error) {
|
||||
return json.Marshal(cuck)
|
||||
}
|
||||
|
||||
func VerifyJSON(cuck CuckooJSON) bool {
|
||||
easy := cuck.Parameter["easiness"]
|
||||
|
||||
if easy <= 0 || easy >= SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(cuck.InputData) != sha256.Size {
|
||||
return false
|
||||
}
|
||||
|
||||
if uint64(len(cuck.Cycle)) != PROOFSIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
var sha [sha256.Size]byte
|
||||
copy(sha[:], cuck.InputData)
|
||||
|
||||
c := NewCuckooSHA(sha)
|
||||
return c.Verify(cuck.Cycle, easy)
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/ZiRo-/cuckgo/miner/miner_lib"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var nthreads int
|
||||
var maxsols int
|
||||
var easipct float64
|
||||
|
||||
//var header string
|
||||
|
||||
func init() {
|
||||
flag.IntVar(&nthreads, "t", 0, "number of miner threads")
|
||||
flag.IntVar(&maxsols, "m", 8, "maximum number of solutions")
|
||||
flag.Float64Var(&easipct, "e", 50.0, "easiness in percentage")
|
||||
//flag.StringVar(&header, "h", "cuck", "Header")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if (nthreads < 1) {
|
||||
nthreads = runtime.NumCPU()
|
||||
}
|
||||
//fmt.Println("Looking for", cuckoo.PROOFSIZE, "-cycle on cuckoo", cuckoo.SIZESHIFT, "with", easipct, "% edges and", nthreads, "threads")
|
||||
c := miner_lib.Mine(easipct, maxsols, nthreads)
|
||||
fmt.Println(c.String())
|
||||
}
|
||||
|
@ -0,0 +1,292 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package miner_lib
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"github.com/ZiRo-/cuckgo/cuckoo"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const MAXPATHLEN = 4096
|
||||
const RANDOFFS = 64
|
||||
const MAXLEN = 1024
|
||||
|
||||
type CuckooSolve struct {
|
||||
graph *cuckoo.Cuckoo
|
||||
easiness int
|
||||
cuckoo []int
|
||||
sols [][]int
|
||||
nsols int
|
||||
nthreads int
|
||||
}
|
||||
|
||||
type CuckooProof struct {
|
||||
solve *CuckooSolve
|
||||
b []byte
|
||||
}
|
||||
|
||||
func NewCuckooSolve(hdr []byte, en, ms, nt int) *CuckooSolve {
|
||||
self := &CuckooSolve{
|
||||
graph: cuckoo.NewCuckoo(hdr),
|
||||
easiness: en,
|
||||
sols: make([][]int, 2*ms), //this isn't completley safe for high easiness
|
||||
cuckoo: make([]int, 1+int(cuckoo.SIZE)),
|
||||
nsols: 0,
|
||||
nthreads: 1,
|
||||
}
|
||||
for i := range self.sols {
|
||||
self.sols[i] = make([]int, cuckoo.PROOFSIZE)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *CuckooSolve) path(u int, us []int, done chan int) int {
|
||||
nu := 0
|
||||
for nu = 0; u != 0; u = self.cuckoo[u] {
|
||||
nu++
|
||||
if nu >= MAXPATHLEN {
|
||||
for nu != 0 && us[nu-1] != u {
|
||||
nu--
|
||||
}
|
||||
if nu < 0 {
|
||||
//fmt.Println("maximum path length exceeded")
|
||||
} else {
|
||||
//fmt.Println("illegal", (MAXPATHLEN - nu), "-cycle")
|
||||
}
|
||||
close(done)
|
||||
return -1
|
||||
}
|
||||
us[nu] = u
|
||||
}
|
||||
return nu
|
||||
}
|
||||
|
||||
func (self *CuckooSolve) solution(us []int, nu int, vs []int, nv int) {
|
||||
cycle := make(map[int]*cuckoo.Edge)
|
||||
n := 0
|
||||
edg := &cuckoo.Edge{uint64(us[0]), uint64(vs[0]) - cuckoo.HALFSIZE}
|
||||
cycle[edg.HashCode()] = edg
|
||||
for nu != 0 { // u's in even position; v's in odd
|
||||
nu--
|
||||
edg := &cuckoo.Edge{uint64(us[(nu+1)&^1]), uint64(us[nu|1]) - cuckoo.HALFSIZE}
|
||||
_, has := cycle[edg.HashCode()]
|
||||
if !has {
|
||||
cycle[edg.HashCode()] = edg
|
||||
}
|
||||
}
|
||||
for nv != 0 { // u's in odd position; v's in even
|
||||
nv--
|
||||
edg := &cuckoo.Edge{uint64(vs[nv|1]), uint64(vs[(nv+1)&^1]) - cuckoo.HALFSIZE}
|
||||
_, has := cycle[edg.HashCode()]
|
||||
if !has {
|
||||
cycle[edg.HashCode()] = edg
|
||||
}
|
||||
}
|
||||
n = 0
|
||||
for nonce := 0; nonce < self.easiness; nonce++ {
|
||||
e := self.graph.Sipedge(uint64(nonce))
|
||||
has, key := contains(cycle, e)
|
||||
if has {
|
||||
self.sols[self.nsols][n] = nonce
|
||||
n++
|
||||
delete(cycle, key)
|
||||
}
|
||||
}
|
||||
if uint64(n) == cuckoo.PROOFSIZE {
|
||||
self.nsols++
|
||||
} else {
|
||||
//fmt.Println("Only recovered ", n, " nonces")
|
||||
}
|
||||
}
|
||||
|
||||
func contains(m map[int]*cuckoo.Edge, e *cuckoo.Edge) (bool, int) {
|
||||
h := e.HashCode()
|
||||
for k, v := range m {
|
||||
if k == h && v.U == e.U && v.V == e.V { //fuck Java for making me waste time just to figure out that that's how Java does contains
|
||||
return true, k
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
func worker(id int, solve *CuckooSolve, done chan int) {
|
||||
cuck := solve.cuckoo
|
||||
us := make([]int, MAXPATHLEN)
|
||||
vs := make([]int, MAXPATHLEN)
|
||||
for nonce := id; nonce < solve.easiness; nonce += solve.nthreads {
|
||||
us[0] = (int)(solve.graph.Sipnode(uint64(nonce), 0))
|
||||
u := cuck[us[0]]
|
||||
vs[0] = (int)(cuckoo.HALFSIZE + solve.graph.Sipnode(uint64(nonce), 1))
|
||||
v := cuck[vs[0]]
|
||||
if u == vs[0] || v == us[0] {
|
||||
continue // ignore duplicate edges
|
||||
}
|
||||
nu := solve.path(u, us, done)
|
||||
nv := solve.path(v, vs, done)
|
||||
|
||||
if nu == -1 || nv == -1 {
|
||||
return
|
||||
}
|
||||
|
||||
if us[nu] == vs[nv] {
|
||||
min := 0
|
||||
if nu < nv {
|
||||
min = nu
|
||||
} else {
|
||||
min = nv
|
||||
}
|
||||
nu -= min
|
||||
nv -= min
|
||||
for us[nu] != vs[nv] {
|
||||
nu++
|
||||
nv++
|
||||
}
|
||||
length := nu + nv + 1
|
||||
//fmt.Println(" " , length , "-cycle found at " , id , ":" , (int)(nonce*100/solve.easiness) , "%")
|
||||
if uint64(length) == cuckoo.PROOFSIZE && solve.nsols < len(solve.sols) {
|
||||
solve.solution(us, nu, vs, nv)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if nu < nv {
|
||||
for nu != 0 {
|
||||
nu--
|
||||
cuck[us[nu+1]] = us[nu]
|
||||
}
|
||||
cuck[us[0]] = vs[0]
|
||||
} else {
|
||||
for nv != 0 {
|
||||
nv--
|
||||
cuck[vs[nv+1]] = vs[nv]
|
||||
}
|
||||
cuck[vs[0]] = us[0]
|
||||
}
|
||||
}
|
||||
close(done)
|
||||
}
|
||||
|
||||
func Mine(easipct float64, maxsols, nthreads int) *CuckooProof {
|
||||
b := make([]byte, RANDOFFS)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
easy := int(easipct * float64(cuckoo.SIZE) / 100.0)
|
||||
solve := NewCuckooSolve(b, easy, maxsols, 1)
|
||||
|
||||
for k := 0; k < MAXLEN-RANDOFFS; k++ {
|
||||
b = append(b, 0)
|
||||
for i := 0; i < 256; i += nthreads {
|
||||
|
||||
cs := make([]chan int, nthreads)
|
||||
solvers := make([]*CuckooSolve, nthreads)
|
||||
for n := 0; n < nthreads; n++ {
|
||||
cs[n] = make(chan int)
|
||||
}
|
||||
out := merge(cs...)
|
||||
|
||||
for n := 0; n < nthreads; n++ {
|
||||
if i+n < 256 {
|
||||
b[RANDOFFS+k] = byte(i + n)
|
||||
solvers[n] = NewCuckooSolve(b, easy, maxsols, 1)
|
||||
go worker(i, solvers[n], cs[n])
|
||||
} else {
|
||||
close(cs[n])
|
||||
}
|
||||
}
|
||||
|
||||
<-out
|
||||
|
||||
for n, s := range solvers {
|
||||
if s.nsols > 0 {
|
||||
b[RANDOFFS+k] = byte(i + n)
|
||||
solve = s
|
||||
goto done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
/* for s := 0; s < solve.nsols; s++ {
|
||||
//fmt.Print("Solution")
|
||||
for i := 0; uint64(i) < cuckoo.PROOFSIZE; i++ {
|
||||
fmt.Printf(" %x", solve.sols[s][i])
|
||||
}
|
||||
fmt.Println()
|
||||
}*/
|
||||
if solve.nsols <= 0 {
|
||||
solve = nil
|
||||
}
|
||||
return &CuckooProof{solve, b}
|
||||
}
|
||||
|
||||
func (self *CuckooProof)String() string {
|
||||
c := formatProof(self.solve, self.b)
|
||||
json, _ := cuckoo.EncodeCuckooJSON(c)
|
||||
return base64.StdEncoding.EncodeToString(json)
|
||||
}
|
||||
|
||||
|
||||
func formatProof(solve *CuckooSolve, b []byte) cuckoo.CuckooJSON {
|
||||
sha := sha256.Sum256(b)
|
||||
easy := uint64(solve.easiness)
|
||||
cycle := make([]uint64, len(solve.sols[0]))
|
||||
m := make(map[string]uint64)
|
||||
m["easiness"] = easy
|
||||
|
||||
for i, n := range solve.sols[0] {
|
||||
cycle[i] = uint64(n)
|
||||
}
|
||||
|
||||
return cuckoo.CuckooJSON{m, sha[:], cycle}
|
||||
}
|
||||
|
||||
func merge(cs ...chan int) chan int {
|
||||
var wg sync.WaitGroup
|
||||
out := make(chan int)
|
||||
|
||||
// Start an output goroutine for each input channel in cs. output
|
||||
// copies values from c to out until c is closed, then calls wg.Done.
|
||||
output := func(c chan int) {
|
||||
for n := range c {
|
||||
out <- n
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
wg.Add(len(cs))
|
||||
for _, c := range cs {
|
||||
go output(c)
|
||||
}
|
||||
|
||||
// Start a goroutine to close out once all the output goroutines are
|
||||
// done. This must start after the wg.Add call.
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(out)
|
||||
}()
|
||||
return out
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "crypto/sha256"
|
||||
import "github.com/gopherjs/gopherjs/js"
|
||||
|
||||
const (
|
||||
SIZESHIFT uint64 = 20
|
||||
PROOFSIZE uint64 = 42
|
||||
SIZE uint64 = 1 << SIZESHIFT
|
||||
HALFSIZE uint64 = SIZE / 2
|
||||
NODEMASK uint64 = HALFSIZE - 1
|
||||
)
|
||||
|
||||
type Cuckoo struct {
|
||||
v [4]uint64
|
||||
vh [4]uint32
|
||||
vl [4]uint32
|
||||
key []byte
|
||||
}
|
||||
|
||||
func u8(b byte) uint64 {
|
||||
return (uint64)(b) & 0xff
|
||||
}
|
||||
|
||||
func u8to64(p [sha256.Size]byte, i int) uint64 {
|
||||
return u8(p[i]) | u8(p[i+1])<<8 |
|
||||
u8(p[i+2])<<16 | u8(p[i+3])<<24 |
|
||||
u8(p[i+4])<<32 | u8(p[i+5])<<40 |
|
||||
u8(p[i+6])<<48 | u8(p[i+7])<<56
|
||||
}
|
||||
|
||||
func NewCuckoo(header []byte) *Cuckoo {
|
||||
hdrkey := sha256.Sum256(header)
|
||||
|
||||
return NewCuckooSHA(hdrkey)
|
||||
}
|
||||
|
||||
func NewCuckooSHA(hdrkey [sha256.Size]byte) *Cuckoo {
|
||||
self := new(Cuckoo)
|
||||
k0 := u8to64(hdrkey, 0)
|
||||
k1 := u8to64(hdrkey, 8)
|
||||
self.v[0] = k0 ^ 0x736f6d6570736575
|
||||
self.v[1] = k1 ^ 0x646f72616e646f6d
|
||||
self.v[2] = k0 ^ 0x6c7967656e657261
|
||||
self.v[3] = k1 ^ 0x7465646279746573
|
||||
self.key = hdrkey[:]
|
||||
|
||||
for i,h := range(self.v) {
|
||||
self.vl[i] = uint32 (h & 0xFFFFFFFF);
|
||||
self.vh[i] = uint32((h & (0xFFFFFFFF << 32) ) >> 32);
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
type Edge struct {
|
||||
U uint64
|
||||
V uint64
|
||||
}
|
||||
|
||||
func (self *Edge) HashCode() int {
|
||||
return int(self.U) ^ int(self.V)
|
||||
}
|
||||
|
||||
func (self *Cuckoo) Sipedge(nonce uint64) *Edge {
|
||||
return &Edge{self.Sipnode(nonce, 0), self.Sipnode(nonce, 1)}
|
||||
}
|
||||
|
||||
func (self *Cuckoo) siphash24(nonce uint64) uint64 {
|
||||
return siphash24_js(self.vh, self.vl, nonce)
|
||||
}
|
||||
|
||||
var sh *js.Object = js.Global.Get("SipHash")
|
||||
|
||||
func siphash24_js(vh, vl [4]uint32, nonce uint64) uint64 {
|
||||
arr := sh.Call("hash", vh[0], vl[0], vh[1], vl[1], vh[2], vl[2], vh[3], vl[3], 0, nonce)
|
||||
high := arr.Index(0).Uint64();
|
||||
low := arr.Index(1).Uint64();
|
||||
|
||||
return (high << 32) | low;
|
||||
}
|
||||
|
||||
// generate edge in cuckoo graph
|
||||
func (self *Cuckoo) Sipnode(nonce uint64, uorv uint32) uint64 {
|
||||
return self.siphash24(2*nonce+uint64(uorv)) & NODEMASK
|
||||
}
|
||||
|
||||
// verify that (ascending) nonces, all less than easiness, form a cycle in graph
|
||||
func (self *Cuckoo) Verify(nonces []uint64, easiness uint64) bool {
|
||||
us := make([]uint64, PROOFSIZE)
|
||||
vs := make([]uint64, PROOFSIZE)
|
||||
i := 0
|
||||
var n uint64
|
||||
|
||||
for n = 0; n < PROOFSIZE; n++ {
|
||||
if nonces[n] >= easiness || (n != 0 && nonces[n] <= nonces[n-1]) {
|
||||
return false
|
||||
}
|
||||
us[n] = self.Sipnode(nonces[n], 0)
|
||||
vs[n] = self.Sipnode(nonces[n], 1)
|
||||
}
|
||||
|
||||
loop := true
|
||||
for loop { // follow cycle until we return to i==0; n edges left to visit
|
||||
j := i
|
||||
for k := 0; uint64(k) < PROOFSIZE; k++ { // find unique other j with same vs[j]
|
||||
if k != i && vs[k] == vs[i] {
|
||||
if j != i {
|
||||
return false
|
||||
}
|
||||
j = k
|
||||
}
|
||||
}
|
||||
if j == i {
|
||||
return false
|
||||
}
|
||||
i = j
|
||||
for k := 0; uint64(k) < PROOFSIZE; k++ { // find unique other i with same us[i]
|
||||
if k != j && us[k] == us[j] {
|
||||
if i != j {
|
||||
return false
|
||||
}
|
||||
i = k
|
||||
}
|
||||
}
|
||||
if i == j {
|
||||
return false
|
||||
}
|
||||
n -= 2
|
||||
loop = (i != 0)
|
||||
}
|
||||
return n == 0
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"github.com/gopherjs/gopherjs/js"
|
||||
)
|
||||
|
||||
const MAXPATHLEN = 4096
|
||||
const RANDOFFS = 64
|
||||
const MAXLEN = 1024
|
||||
|
||||
type CuckooSolve struct {
|
||||
graph *Cuckoo
|
||||
easiness int
|
||||
cuckoo []int
|
||||
sols [][]int
|
||||
nsols int
|
||||
nthreads int
|
||||
}
|
||||
|
||||
func NewCuckooSolve(hdr []byte, en, ms, nt int) *CuckooSolve {
|
||||
self := &CuckooSolve{
|
||||
graph: NewCuckoo(hdr),
|
||||
easiness: en,
|
||||
sols: make([][]int, 2*ms), //this isn't completley safe for high easiness
|
||||
cuckoo: make([]int, 1+int(SIZE)),
|
||||
nsols: 0,
|
||||
nthreads: 1,
|
||||
}
|
||||
for i := range self.sols {
|
||||
self.sols[i] = make([]int, PROOFSIZE)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *CuckooSolve) path(u int, us []int) int {
|
||||
nu := 0
|
||||
for nu = 0; u != 0; u = self.cuckoo[u] {
|
||||
nu++
|
||||
if nu >= MAXPATHLEN {
|
||||
for nu != 0 && us[nu-1] != u {
|
||||
nu--
|
||||
}
|
||||
if nu < 0 {
|
||||
//fmt.Println("maximum path length exceeded")
|
||||
} else {
|
||||
//fmt.Println("illegal", (MAXPATHLEN - nu), "-cycle")
|
||||
}
|
||||
return -1
|
||||
}
|
||||
us[nu] = u
|
||||
}
|
||||
return nu
|
||||
}
|
||||
|
||||
func (self *CuckooSolve) solution(us []int, nu int, vs []int, nv int) bool {
|
||||
cycle := make(map[int]*Edge)
|
||||
n := 0
|
||||
edg := &Edge{uint64(us[0]), uint64(vs[0]) - HALFSIZE}
|
||||
cycle[edg.HashCode()] = edg
|
||||
for nu != 0 { // u's in even position; v's in odd
|
||||
nu--
|
||||
edg := &Edge{uint64(us[(nu+1)&^1]), uint64(us[nu|1]) - HALFSIZE}
|
||||
_, has := cycle[edg.HashCode()]
|
||||
if !has {
|
||||
cycle[edg.HashCode()] = edg
|
||||
}
|
||||
}
|
||||
for nv != 0 { // u's in odd position; v's in even
|
||||
nv--
|
||||
edg := &Edge{uint64(vs[nv|1]), uint64(vs[(nv+1)&^1]) - HALFSIZE}
|
||||
_, has := cycle[edg.HashCode()]
|
||||
if !has {
|
||||
cycle[edg.HashCode()] = edg
|
||||
}
|
||||
}
|
||||
n = 0
|
||||
for nonce := 0; nonce < self.easiness; nonce++ {
|
||||
e := self.graph.Sipedge(uint64(nonce))
|
||||
has, key := contains(cycle, e)
|
||||
if has {
|
||||
self.sols[self.nsols][n] = nonce
|
||||
n++
|
||||
delete(cycle, key)
|
||||
}
|
||||
}
|
||||
if uint64(n) == PROOFSIZE {
|
||||
self.nsols++
|
||||
return true
|
||||
} else {
|
||||
//fmt.Println("Only recovered ", n, " nonces")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func contains(m map[int]*Edge, e *Edge) (bool, int) {
|
||||
h := e.HashCode()
|
||||
for k, v := range m {
|
||||
if k == h && v.U == e.U && v.V == e.V { //fuck Java for making me waste time just to figure out that that's how Java does contains
|
||||
return true, k
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
func worker(id int, solve *CuckooSolve) {
|
||||
cuck := solve.cuckoo
|
||||
us := make([]int, MAXPATHLEN)
|
||||
vs := make([]int, MAXPATHLEN)
|
||||
for nonce := id; nonce < solve.easiness; nonce += solve.nthreads {
|
||||
us[0] = (int)(solve.graph.Sipnode(uint64(nonce), 0))
|
||||
u := cuck[us[0]]
|
||||
vs[0] = (int)(HALFSIZE + solve.graph.Sipnode(uint64(nonce), 1))
|
||||
v := cuck[vs[0]]
|
||||
if u == vs[0] || v == us[0] {
|
||||
continue // ignore duplicate edges
|
||||
}
|
||||
nu := solve.path(u, us)
|
||||
nv := solve.path(v, vs)
|
||||
|
||||
if nu == -1 || nv == -1 {
|
||||
return
|
||||
}
|
||||
|
||||
if us[nu] == vs[nv] {
|
||||
min := 0
|
||||
if nu < nv {
|
||||
min = nu
|
||||
} else {
|
||||
min = nv
|
||||
}
|
||||
nu -= min
|
||||
nv -= min
|
||||
for us[nu] != vs[nv] {
|
||||
nu++
|
||||
nv++
|
||||
}
|
||||
length := nu + nv + 1
|
||||
//fmt.Println(" " , length , "-cycle found at " , id , ":" , (int)(nonce*100/solve.easiness) , "%")
|
||||
if uint64(length) == PROOFSIZE && solve.nsols < len(solve.sols) {
|
||||
if solve.solution(us, nu, vs, nv) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if nu < nv {
|
||||
for nu != 0 {
|
||||
nu--
|
||||
cuck[us[nu+1]] = us[nu]
|
||||
}
|
||||
cuck[us[0]] = vs[0]
|
||||
} else {
|
||||
for nv != 0 {
|
||||
nv--
|
||||
cuck[vs[nv+1]] = vs[nv]
|
||||
}
|
||||
cuck[vs[0]] = us[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mine_cuckoo(b []byte, easipct float64) []string {
|
||||
easy := int(easipct * float64(SIZE) / 100.0)
|
||||
|
||||
solve := NewCuckooSolve(b, easy, 8, 1)
|
||||
worker(0, solve)
|
||||
|
||||
|
||||
res := make([]string, 2)
|
||||
if solve.nsols > 0 {
|
||||
c := formatProof(solve, b)
|
||||
json, _ := EncodeCuckooJSON(c)
|
||||
str := base64.StdEncoding.EncodeToString(json)
|
||||
res[0] = "ok"
|
||||
res[1] = str
|
||||
} else {
|
||||
res[0] = "D^:"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func formatProof(solve *CuckooSolve, b []byte) CuckooJSON {
|
||||
sha := sha256.Sum256(b)
|
||||
easy := uint64(solve.easiness)
|
||||
cycle := make([]uint64, len(solve.sols[0]))
|
||||
m := make(map[string]uint64)
|
||||
m["easiness"] = easy
|
||||
|
||||
for i, n := range solve.sols[0] {
|
||||
cycle[i] = uint64(n)
|
||||
}
|
||||
|
||||
return CuckooJSON{m, sha[:], cycle}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func main() {
|
||||
js.Global.Set("cuckoo", map[string]interface{}{
|
||||
"mine_cuckoo": mine_cuckoo,
|
||||
})
|
||||
}
|
23312
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/miner_js/miner_js.js
Normal file
23312
contrib/backends/srndv2/src/github.com/ZiRo-/cuckgo/miner_js/miner_js.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,94 @@
|
||||
var SipHash = (function() {
|
||||
function u8to64(p , i) {
|
||||
return { l: (p[i] | p[i+1]<<8 | p[i+2]<<16 | p[i+3]<<24) , h: (p[i+4] | p[i+5]<<8 | p[i+6]<<16 | p[i+7]<<24) };
|
||||
}
|
||||
|
||||
|
||||
function _add(a, b) {
|
||||
var rl = a.l + b.l,
|
||||
a2 = { h: a.h + b.h + (rl / 2 >>> 31) >>> 0,
|
||||
l: rl >>> 0 };
|
||||
a.h = a2.h; a.l = a2.l;
|
||||
}
|
||||
|
||||
function _xor(a, b) {
|
||||
a.h ^= b.h; a.h >>>= 0;
|
||||
a.l ^= b.l; a.l >>>= 0;
|
||||
}
|
||||
|
||||
function _rotl(a, n) {
|
||||
var a2 = {
|
||||
h: a.h << n | a.l >>> (32 - n),
|
||||
l: a.l << n | a.h >>> (32 - n)
|
||||
};
|
||||
a.h = a2.h; a.l = a2.l;
|
||||
}
|
||||
|
||||
function _rotl32(a) {
|
||||
var al = a.l;
|
||||
a.l = a.h; a.h = al;
|
||||
}
|
||||
|
||||
function _compress(v0, v1, v2, v3) {
|
||||
_add(v0, v1);
|
||||
_add(v2, v3);
|
||||
_rotl(v1, 13);
|
||||
_rotl(v3, 16);
|
||||
_xor(v1, v0);
|
||||
_xor(v3, v2);
|
||||
_rotl32(v0);
|
||||
_add(v2, v1);
|
||||
_add(v0, v3);
|
||||
_rotl(v1, 17);
|
||||
_rotl(v3, 21);
|
||||
_xor(v1, v2);
|
||||
_xor(v3, v0);
|
||||
_rotl32(v2);
|
||||
}
|
||||
|
||||
|
||||
function hash(v0h, v0l, v1h, v1l, v2h, v2l, v3h, v3l, mh, ml) {
|
||||
var mi = { h: mh, l: ml };
|
||||
|
||||
var v0 = { h: v0h, l: v0l };
|
||||
var v1 = { h: v1h, l: v1l };
|
||||
var v2 = { h: v2h, l: v2l };
|
||||
var v3 = { h: v3h, l: v3l };
|
||||
|
||||
/*var k0 = u8to64(key, 0);
|
||||
var k1 = u8to64(key, 8);
|
||||
|
||||
var v0 = { h: k0.h, l: k0.l }, v2 = k0;
|
||||
var v1 = { h: k1.h, l: k1.l }, v3 = k1;
|
||||
|
||||
_xor(v0, { h: 0x736f6d65, l: 0x70736575 });
|
||||
_xor(v1, { h: 0x646f7261, l: 0x6e646f6d });
|
||||
_xor(v2, { h: 0x6c796765, l: 0x6e657261 });
|
||||
_xor(v3, { h: 0x74656462, l: 0x79746573 });*/
|
||||
|
||||
_xor(v3, mi);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_xor(v0, mi);
|
||||
_xor(v2, { h: 0, l: 0xff });
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
_compress(v0, v1, v2, v3);
|
||||
|
||||
var h = v0;
|
||||
_xor(h, v1);
|
||||
_xor(h, v2);
|
||||
_xor(h, v3);
|
||||
|
||||
var res = new Uint32Array(2);
|
||||
res[0]=h.h; res[1]=h.l;
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
hash: hash,
|
||||
};
|
||||
})();
|
||||
|
||||
var module = module || { }, exports = module.exports = SipHash;
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 ZiRo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type CuckooJSON struct {
|
||||
Parameter map[string]uint64 `json:"parameters"`
|
||||
InputData []byte `json:"header"` //sha256 bytes
|
||||
Cycle []uint64 `json:"cycle"`
|
||||
}
|
||||
|
||||
func DecodeCuckooJSON(jsonBlob []byte) (*CuckooJSON, error) {
|
||||
res := new(CuckooJSON)
|
||||
err := json.Unmarshal(jsonBlob, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func EncodeCuckooJSON(cuck CuckooJSON) ([]byte, error) {
|
||||
return json.Marshal(cuck)
|
||||
}
|
||||
|
||||
func VerifyJSON(cuck CuckooJSON) bool {
|
||||
easy := cuck.Parameter["easiness"]
|
||||
|
||||
if easy <= 0 || easy >= SIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(cuck.InputData) != sha256.Size {
|
||||
return false
|
||||
}
|
||||
|
||||
if uint64(len(cuck.Cycle)) != PROOFSIZE {
|
||||
return false
|
||||
}
|
||||
|
||||
var sha [sha256.Size]byte
|
||||
copy(sha[:], cuck.InputData)
|
||||
|
||||
c := NewCuckooSHA(sha)
|
||||
return c.Verify(cuck.Cycle, easy)
|
||||
}
|
Reference in New Issue
Block a user