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