parent
6fbf3e9bd7
commit
6abc6f4021
21
Makefile
21
Makefile
@ -1,9 +1,7 @@
|
|||||||
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
|
||||||
STATIC_DIR=$(REPO)/contrib/static
|
JS=$(REPO)/contrib/static/nntpchan.js
|
||||||
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
|
||||||
@ -17,12 +15,15 @@ NNTPD=$(REPO)/nntpd
|
|||||||
GOROOT=$(shell go env GOROOT)
|
GOROOT=$(shell go env GOROOT)
|
||||||
GO=$(GOROOT)/bin/go
|
GO=$(GOROOT)/bin/go
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
GOPHERJS_GOROOT ?= $(GOROOT)
|
GOPHERJS_GOROOT ?= $(GOROOT)
|
||||||
GOPHERJS_GO = $(GOPHERJS_GOROOT)/bin/go
|
GOPHERJS_GO = $(GOPHERJS_GOROOT)/bin/go
|
||||||
|
|
||||||
GOPHERJS_GOPATH=$(REPO)/gopherjs_go
|
GOPHERJS_GOPATH=$(REPO)/gopherjs_go
|
||||||
GOPHERJS=$(GOPHERJS_GOPATH)/bin/gopherjs
|
GOPHERJS=$(GOPHERJS_GOPATH)/bin/gopherjs
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> parent of c342687... re add pow captcha (initial)
|
||||||
all: clean build
|
all: clean build
|
||||||
|
|
||||||
build: js srnd
|
build: js srnd
|
||||||
@ -31,11 +32,12 @@ full: clean full-build
|
|||||||
|
|
||||||
full-build: srnd beta native
|
full-build: srnd beta native
|
||||||
|
|
||||||
js: $(JS) $(MINER_JS)
|
js: $(JS)
|
||||||
|
|
||||||
srnd: $(SRND)
|
srnd: $(SRND)
|
||||||
|
|
||||||
$(MINIFY):
|
$(MINIFY):
|
||||||
|
<<<<<<< HEAD
|
||||||
GOPATH=$(REPO_GOPATH) $(GO) get -v github.com/tdewolff/minify/cmd/minify
|
GOPATH=$(REPO_GOPATH) $(GO) get -v github.com/tdewolff/minify/cmd/minify
|
||||||
|
|
||||||
$(GOPHERJS):
|
$(GOPHERJS):
|
||||||
@ -48,6 +50,11 @@ $(MINER_JS): $(GOPHERJS) $(MINIFY)
|
|||||||
GOROOT=$(GOPHERJS_GOROOT) GOPATH=$(GOPHERJS_GOPATH) $(GOPHERJS) -m -v build github.com/ZiRo-/cuckgo/miner_js
|
GOROOT=$(GOPHERJS_GOROOT) GOPATH=$(GOPHERJS_GOPATH) $(GOPHERJS) -m -v build github.com/ZiRo-/cuckgo/miner_js
|
||||||
$(MINIFY) --mime=text/javascript > $(STATIC_DIR)/miner-js.js < miner_js.js
|
$(MINIFY) --mime=text/javascript > $(STATIC_DIR)/miner-js.js < miner_js.js
|
||||||
rm -f miner_js.js.map miner_js.js
|
rm -f miner_js.js.map miner_js.js
|
||||||
|
=======
|
||||||
|
GOPATH=$(REPO_GOPATH) go get -v github.com/tdewolff/minify/cmd/minify
|
||||||
|
|
||||||
|
js-deps: $(MINIFY)
|
||||||
|
>>>>>>> parent of c342687... re add pow captcha (initial)
|
||||||
|
|
||||||
$(JS): js-deps
|
$(JS): js-deps
|
||||||
rm -f $(JS)
|
rm -f $(JS)
|
||||||
@ -87,16 +94,16 @@ test-native:
|
|||||||
GOROOT=$(GOROOT) $(MAKE) -C $(NNTPCHAN_DAEMON_DIR) test
|
GOROOT=$(GOROOT) $(MAKE) -C $(NNTPCHAN_DAEMON_DIR) test
|
||||||
|
|
||||||
|
|
||||||
clean: clean-srnd clean-js
|
clean: clean-js clean-srnd
|
||||||
|
|
||||||
clean-full: clean clean-beta clean-native clean-js
|
clean-full: clean clean-beta clean-native
|
||||||
|
|
||||||
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) $(MINER_JS)
|
rm -f $(JS)
|
||||||
|
|
||||||
clean-beta:
|
clean-beta:
|
||||||
rm -f $(NNTPCHAND)
|
rm -f $(NNTPCHAND)
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
*.pyc
|
|
||||||
*~
|
|
||||||
*.ini
|
|
||||||
*.db
|
|
||||||
build.dir
|
|
||||||
\#*
|
|
||||||
.\#*
|
|
||||||
_obj
|
|
||||||
*.log
|
|
||||||
*.la
|
|
||||||
*.txt
|
|
@ -1,21 +0,0 @@
|
|||||||
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.
|
|
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
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.
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,232 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
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)
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
|
|
@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
}
|
|
@ -1,226 +0,0 @@
|
|||||||
/*
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,94 +0,0 @@
|
|||||||
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;
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
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