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=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
REPO_GOPATH=$(REPO)/go
|
REPO_GOPATH=$(REPO)/go
|
||||||
MINIFY=$(REPO_GOPATH)/bin/minify
|
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
|
CONTRIB_JS=$(REPO)/contrib/js/contrib
|
||||||
LOCAL_JS=$(REPO)/contrib/js/nntpchan
|
LOCAL_JS=$(REPO)/contrib/js/nntpchan
|
||||||
VENDOR_JS=$(REPO)/contrib/js/vendor
|
VENDOR_JS=$(REPO)/contrib/js/vendor
|
||||||
@ -15,6 +17,11 @@ NNTPD=$(REPO)/nntpd
|
|||||||
GOROOT=$(shell go env GOROOT)
|
GOROOT=$(shell go env GOROOT)
|
||||||
GO=$(GOROOT)/bin/go
|
GO=$(GOROOT)/bin/go
|
||||||
|
|
||||||
|
GOPHERJS_GOROOT ?= $(GOROOT)
|
||||||
|
GOPHERJS_GO = $(GOPHERJS_GOROOT)/bin/go
|
||||||
|
|
||||||
|
GOPHERJS=$(REPO_GOPATH)/bin/gopherjs
|
||||||
|
|
||||||
all: clean build
|
all: clean build
|
||||||
|
|
||||||
build: js srnd
|
build: js srnd
|
||||||
@ -23,14 +30,23 @@ full: clean full-build
|
|||||||
|
|
||||||
full-build: srnd beta native
|
full-build: srnd beta native
|
||||||
|
|
||||||
js: $(JS)
|
js: $(JS) $(MINER_JS)
|
||||||
|
|
||||||
srnd: $(SRND)
|
srnd: $(SRND)
|
||||||
|
|
||||||
$(MINIFY):
|
$(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
|
$(JS): js-deps
|
||||||
rm -f $(JS)
|
rm -f $(JS)
|
||||||
@ -70,16 +86,16 @@ test-native:
|
|||||||
GOROOT=$(GOROOT) $(MAKE) -C $(NNTPCHAN_DAEMON_DIR) test
|
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:
|
clean-srnd:
|
||||||
rm -f $(SRND)
|
rm -f $(SRND)
|
||||||
GOROOT=$(GOROOT) $(MAKE) -C $(SRND_DIR) clean
|
GOROOT=$(GOROOT) $(MAKE) -C $(SRND_DIR) clean
|
||||||
|
|
||||||
clean-js:
|
clean-js:
|
||||||
rm -f $(JS)
|
rm -f $(JS) $(MINER_JS)
|
||||||
|
|
||||||
clean-beta:
|
clean-beta:
|
||||||
rm -f $(NNTPCHAND)
|
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