Merge branch 'publictests' of https://github.com/xcthulhu/go-ethereum into xcthulhu-publictests
This commit is contained in:
		
						commit
						22b132e28f
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -6,6 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| /tmp | /tmp | ||||||
| */**/*un~ | */**/*un~ | ||||||
|  | */**/*.test | ||||||
| *un~ | *un~ | ||||||
| .DS_Store | .DS_Store | ||||||
| */**/.DS_Store | */**/.DS_Store | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								Godeps/Godeps.json
									
									
									
										generated
									
									
									
								
							| @ -15,6 +15,11 @@ | |||||||
| 			"Comment": "null-15", | 			"Comment": "null-15", | ||||||
| 			"Rev": "12e4b4183793ac4b061921e7980845e750679fd0" | 			"Rev": "12e4b4183793ac4b061921e7980845e750679fd0" | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"ImportPath": "github.com/ethereum/ethash", | ||||||
|  | 			"Comment": "v17-23-g2561e13", | ||||||
|  | 			"Rev": "2561e1322a7e8e3d4a2cc903c44b1e96340bcb27" | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"ImportPath": "github.com/ethereum/serpent-go", | 			"ImportPath": "github.com/ethereum/serpent-go", | ||||||
| 			"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443" | 			"Rev": "5767a0dbd759d313df3f404dadb7f98d7ab51443" | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | .idea/ | ||||||
|  | .DS_Store | ||||||
|  | */**/*un~ | ||||||
|  | .vagrant/ | ||||||
|  | cpp-build/ | ||||||
							
								
								
									
										14
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | cmake_minimum_required(VERSION 2.8.2) | ||||||
|  | project(ethash) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") | ||||||
|  | set(ETHHASH_LIBS ethash) | ||||||
|  | 
 | ||||||
|  | if (WIN32 AND WANT_CRYPTOPP) | ||||||
|  | 	add_subdirectory(cryptopp) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | add_subdirectory(libethash) | ||||||
|  | add_subdirectory(libethash-cl EXCLUDE_FROM_ALL) | ||||||
|  | add_subdirectory(benchmark EXCLUDE_FROM_ALL) | ||||||
|  | add_subdirectory(test EXCLUDE_FROM_ALL) | ||||||
							
								
								
									
										53
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/benchmark/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/benchmark/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | include_directories(..) | ||||||
|  | 
 | ||||||
|  | set(CMAKE_BUILD_TYPE Release) | ||||||
|  | 
 | ||||||
|  | if (MSVC) | ||||||
|  | 	add_definitions("/openmp") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (NOT MPI_FOUND) | ||||||
|  |     find_package(MPI) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (NOT CRYPTOPP_FOUND) | ||||||
|  | 	find_package(CryptoPP 5.6.2) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (CRYPTOPP_FOUND) | ||||||
|  | 	add_definitions(-DWITH_CRYPTOPP) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (NOT OpenCL_FOUND) | ||||||
|  | 	find_package(OpenCL) | ||||||
|  | endif() | ||||||
|  | if (OpenCL_FOUND) | ||||||
|  | 	add_definitions(-DWITH_OPENCL) | ||||||
|  | 	include_directories(${OpenCL_INCLUDE_DIRS}) | ||||||
|  | 	list(APPEND FILES ethash_cl_miner.cpp ethash_cl_miner.h) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (MPI_FOUND) | ||||||
|  |     include_directories(${MPI_INCLUDE_PATH}) | ||||||
|  |     add_executable (Benchmark_MPI_FULL benchmark.cpp) | ||||||
|  |     target_link_libraries (Benchmark_MPI_FULL ${ETHHASH_LIBS} ${MPI_LIBRARIES}) | ||||||
|  |     SET_TARGET_PROPERTIES(Benchmark_MPI_FULL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DFULL -DMPI") | ||||||
|  | 
 | ||||||
|  |     add_executable (Benchmark_MPI_LIGHT benchmark.cpp) | ||||||
|  |     target_link_libraries (Benchmark_MPI_LIGHT ${ETHHASH_LIBS} ${MPI_LIBRARIES}) | ||||||
|  |     SET_TARGET_PROPERTIES(Benchmark_MPI_LIGHT PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} ${MPI_COMPILE_FLAGS} -DMPI") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | add_executable (Benchmark_FULL benchmark.cpp) | ||||||
|  | target_link_libraries (Benchmark_FULL ${ETHHASH_LIBS}) | ||||||
|  | SET_TARGET_PROPERTIES(Benchmark_FULL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DFULL") | ||||||
|  | 
 | ||||||
|  | add_executable (Benchmark_LIGHT benchmark.cpp) | ||||||
|  | target_link_libraries (Benchmark_LIGHT ${ETHHASH_LIBS}) | ||||||
|  | 
 | ||||||
|  | if (OpenCL_FOUND) | ||||||
|  | 	add_executable (Benchmark_CL benchmark.cpp) | ||||||
|  | 	target_link_libraries (Benchmark_CL ${ETHHASH_LIBS} ethash-cl) | ||||||
|  | 	SET_TARGET_PROPERTIES(Benchmark_CL PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DOPENCL") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
							
								
								
									
										260
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/benchmark/benchmark.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/benchmark/benchmark.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,260 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file benchmark.cpp
 | ||||||
|  |  * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  |  * @date 2015 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <libethash/ethash.h> | ||||||
|  | #include <libethash/util.h> | ||||||
|  | #ifdef OPENCL | ||||||
|  | #include <libethash-cl/ethash_cl_miner.h> | ||||||
|  | #endif | ||||||
|  | #include <vector> | ||||||
|  | #include <algorithm> | ||||||
|  | 
 | ||||||
|  | #ifdef WITH_CRYPTOPP | ||||||
|  | #include <libethash/SHA3_cryptopp.h> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | #include "libethash/sha3.h" | ||||||
|  | #endif // WITH_CRYPTOPP
 | ||||||
|  | 
 | ||||||
|  | #undef min | ||||||
|  | #undef max | ||||||
|  | 
 | ||||||
|  | #if defined(OPENCL) | ||||||
|  | const unsigned trials = 1024*1024*32; | ||||||
|  | #elif defined(FULL) | ||||||
|  | const unsigned trials = 1024*1024/8; | ||||||
|  | #else | ||||||
|  | const unsigned trials = 1024*1024/1024; | ||||||
|  | #endif | ||||||
|  | uint8_t g_hashes[1024*32]; | ||||||
|  | 
 | ||||||
|  | static char nibbleToChar(unsigned nibble) | ||||||
|  | { | ||||||
|  | 	return (char) ((nibble >= 10 ? 'a'-10 : '0') + nibble); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint8_t charToNibble(char chr) | ||||||
|  | { | ||||||
|  | 	if (chr >= '0' && chr <= '9') | ||||||
|  | 	{ | ||||||
|  | 		return (uint8_t) (chr - '0'); | ||||||
|  | 	} | ||||||
|  | 	if (chr >= 'a' && chr <= 'z') | ||||||
|  | 	{ | ||||||
|  | 		return (uint8_t) (chr - 'a' + 10); | ||||||
|  | 	} | ||||||
|  | 	if (chr >= 'A' && chr <= 'Z') | ||||||
|  | 	{ | ||||||
|  | 		return (uint8_t) (chr - 'A' + 10); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static std::vector<uint8_t> hexStringToBytes(char const* str) | ||||||
|  | { | ||||||
|  | 	std::vector<uint8_t> bytes(strlen(str) >> 1); | ||||||
|  | 	for (unsigned i = 0; i != bytes.size(); ++i) | ||||||
|  | 	{ | ||||||
|  | 		bytes[i] = charToNibble(str[i*2 | 0]) << 4; | ||||||
|  | 		bytes[i] |= charToNibble(str[i*2 | 1]); | ||||||
|  | 	} | ||||||
|  | 	return bytes; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static std::string bytesToHexString(uint8_t const* bytes, unsigned size) | ||||||
|  | { | ||||||
|  | 	std::string str; | ||||||
|  | 	for (unsigned i = 0; i != size; ++i) | ||||||
|  | 	{ | ||||||
|  | 		str += nibbleToChar(bytes[i] >> 4); | ||||||
|  | 		str += nibbleToChar(bytes[i] & 0xf); | ||||||
|  | 	} | ||||||
|  | 	return str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | extern "C" int main(void) | ||||||
|  | { | ||||||
|  | 	// params for ethash
 | ||||||
|  | 	ethash_params params; | ||||||
|  | 	ethash_params_init(¶ms, 0); | ||||||
|  | 	//params.full_size = 262147 * 4096;	// 1GBish;
 | ||||||
|  | 	//params.full_size = 32771 * 4096;	// 128MBish;
 | ||||||
|  | 	//params.full_size = 8209 * 4096;	// 8MBish;
 | ||||||
|  | 	//params.cache_size = 8209*4096;
 | ||||||
|  | 	//params.cache_size = 2053*4096;
 | ||||||
|  | 	uint8_t seed[32], previous_hash[32]; | ||||||
|  | 
 | ||||||
|  | 	memcpy(seed, hexStringToBytes("9410b944535a83d9adf6bbdcc80e051f30676173c16ca0d32d6f1263fc246466").data(), 32); | ||||||
|  | 	memcpy(previous_hash, hexStringToBytes("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").data(), 32); | ||||||
|  | 	 | ||||||
|  | 	// allocate page aligned buffer for dataset
 | ||||||
|  | #ifdef FULL | ||||||
|  | 	void* full_mem_buf = malloc(params.full_size + 4095); | ||||||
|  | 	void* full_mem = (void*)((uintptr_t(full_mem_buf) + 4095) & ~4095); | ||||||
|  | #endif | ||||||
|  | 	void* cache_mem_buf = malloc(params.cache_size + 63); | ||||||
|  | 	void* cache_mem = (void*)((uintptr_t(cache_mem_buf) + 63) & ~63); | ||||||
|  | 
 | ||||||
|  | 	ethash_cache cache; | ||||||
|  | 	cache.mem = cache_mem; | ||||||
|  | 	 | ||||||
|  | 	// compute cache or full data
 | ||||||
|  | 	{ | ||||||
|  | 		clock_t startTime = clock(); | ||||||
|  | 		ethash_mkcache(&cache, ¶ms, seed); | ||||||
|  | 		clock_t time = clock() - startTime; | ||||||
|  | 
 | ||||||
|  | 		uint8_t cache_hash[32]; | ||||||
|  | 		SHA3_256(cache_hash, (uint8_t const*)cache_mem, params.cache_size); | ||||||
|  | 		debugf("ethash_mkcache: %ums, sha3: %s\n", (unsigned)((time*1000)/CLOCKS_PER_SEC), bytesToHexString(cache_hash,sizeof(cache_hash)).data()); | ||||||
|  | 
 | ||||||
|  | 		// print a couple of test hashes
 | ||||||
|  | 		{ | ||||||
|  | 			const clock_t startTime = clock(); | ||||||
|  | 			ethash_return_value hash; | ||||||
|  | 			ethash_light(&hash, &cache, ¶ms, previous_hash, 0); | ||||||
|  | 			const clock_t time = clock() - startTime; | ||||||
|  | 			debugf("ethash_light test: %ums, %s\n", (unsigned)((time*1000)/CLOCKS_PER_SEC), bytesToHexString(hash.result, 32).data()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		#ifdef FULL | ||||||
|  | 			startTime = clock(); | ||||||
|  | 			ethash_compute_full_data(full_mem, ¶ms, &cache); | ||||||
|  | 			time = clock() - startTime; | ||||||
|  | 			debugf("ethash_compute_full_data: %ums\n", (unsigned)((time*1000)/CLOCKS_PER_SEC)); | ||||||
|  | 		#endif // FULL
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #ifdef OPENCL | ||||||
|  | 	ethash_cl_miner miner; | ||||||
|  | 	{ | ||||||
|  | 		const clock_t startTime = clock(); | ||||||
|  | 		if (!miner.init(params, seed)) | ||||||
|  | 			exit(-1); | ||||||
|  | 		const clock_t time = clock() - startTime; | ||||||
|  |         debugf("ethash_cl_miner init: %ums\n", (unsigned)((time*1000)/CLOCKS_PER_SEC)); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef FULL | ||||||
|  |     { | ||||||
|  |         const clock_t startTime = clock(); | ||||||
|  | 		ethash_return_value hash; | ||||||
|  |         ethash_full(&hash, full_mem, ¶ms, previous_hash, 0); | ||||||
|  |         const clock_t time = clock() - startTime; | ||||||
|  |         debugf("ethash_full test: %uns, %s\n", (unsigned)((time*1000000)/CLOCKS_PER_SEC), bytesToHexString(hash.result, 32).data()); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef OPENCL | ||||||
|  | 	// validate 1024 hashes against CPU
 | ||||||
|  | 	miner.hash(g_hashes, previous_hash, 0, 1024); | ||||||
|  | 	for (unsigned i = 0; i != 1024; ++i) | ||||||
|  | 	{ | ||||||
|  | 		ethash_return_value hash; | ||||||
|  | 		ethash_light(&hash, &cache, ¶ms, previous_hash, i); | ||||||
|  | 		if (memcmp(hash.result, g_hashes + 32*i, 32) != 0) | ||||||
|  | 		{ | ||||||
|  | 			debugf("nonce %u failed: %s %s\n", i, bytesToHexString(g_hashes + 32*i, 32).c_str(), bytesToHexString(hash.result, 32).c_str()); | ||||||
|  | 			static unsigned c = 0; | ||||||
|  | 			if (++c == 16) | ||||||
|  | 			{ | ||||||
|  | 				exit(-1); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	clock_t startTime = clock(); | ||||||
|  | 	unsigned hash_count = trials; | ||||||
|  | 	 | ||||||
|  | 	#ifdef OPENCL | ||||||
|  | 	{ | ||||||
|  | 		struct search_hook : ethash_cl_miner::search_hook | ||||||
|  | 		{ | ||||||
|  | 			unsigned hash_count; | ||||||
|  | 			std::vector<uint64_t> nonce_vec; | ||||||
|  | 
 | ||||||
|  | 			virtual bool found(uint64_t const* nonces, uint32_t count) | ||||||
|  | 			{ | ||||||
|  | 				nonce_vec.assign(nonces, nonces + count); | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			virtual bool searched(uint64_t start_nonce, uint32_t count) | ||||||
|  | 			{ | ||||||
|  | 				// do nothing
 | ||||||
|  | 				hash_count += count; | ||||||
|  | 				return hash_count >= trials; | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  | 		search_hook hook; | ||||||
|  | 		hook.hash_count = 0; | ||||||
|  | 
 | ||||||
|  | 		miner.search(previous_hash, 0x000000ffffffffff, hook); | ||||||
|  | 
 | ||||||
|  | 		for (unsigned i = 0; i != hook.nonce_vec.size(); ++i) | ||||||
|  | 		{ | ||||||
|  | 			uint64_t nonce = hook.nonce_vec[i]; | ||||||
|  | 			ethash_return_value hash; | ||||||
|  | 			ethash_light(&hash, &cache, ¶ms, previous_hash, nonce); | ||||||
|  | 			debugf("found: %.8x%.8x -> %s\n", unsigned(nonce>>32), unsigned(nonce), bytesToHexString(hash.result, 32).c_str()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		hash_count = hook.hash_count; | ||||||
|  | 	} | ||||||
|  | 	#else | ||||||
|  | 	{ | ||||||
|  | 		//#pragma omp parallel for
 | ||||||
|  | 		for (int nonce = 0; nonce < trials; ++nonce) | ||||||
|  | 		{ | ||||||
|  | 			ethash_return_value hash; | ||||||
|  | 			#ifdef FULL | ||||||
|  | 				ethash_full(&hash, full_mem, ¶ms, previous_hash, nonce); | ||||||
|  | 			#else | ||||||
|  | 				ethash_light(&hash, &cache, ¶ms, previous_hash, nonce); | ||||||
|  | 			#endif // FULL
 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	#endif | ||||||
|  | 	 | ||||||
|  | 	clock_t time = std::max((clock_t)1u, clock() - startTime); | ||||||
|  | 	 | ||||||
|  | 	unsigned read_size = ACCESSES * MIX_BYTES; | ||||||
|  | 	debugf(			 | ||||||
|  | 		"hashrate: %8u, bw: %6u MB/s\n", | ||||||
|  | 		(unsigned)(((uint64_t)hash_count*CLOCKS_PER_SEC)/time), | ||||||
|  | 		(unsigned)((((uint64_t)hash_count*read_size*CLOCKS_PER_SEC)/time) / (1024*1024)) | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 	free(cache_mem_buf); | ||||||
|  | #ifdef FULL | ||||||
|  | 	free(full_mem_buf); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										108
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cmake/modules/FindCryptoPP.cmake
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cmake/modules/FindCryptoPP.cmake
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | # Module for locating the Crypto++ encryption library. | ||||||
|  | # | ||||||
|  | # Customizable variables: | ||||||
|  | #   CRYPTOPP_ROOT_DIR | ||||||
|  | #     This variable points to the CryptoPP root directory. On Windows the | ||||||
|  | #     library location typically will have to be provided explicitly using the | ||||||
|  | #     -D command-line option. The directory should include the include/cryptopp, | ||||||
|  | #     lib and/or bin sub-directories. | ||||||
|  | # | ||||||
|  | # Read-only variables: | ||||||
|  | #   CRYPTOPP_FOUND | ||||||
|  | #     Indicates whether the library has been found. | ||||||
|  | # | ||||||
|  | #   CRYPTOPP_INCLUDE_DIRS | ||||||
|  | #     Points to the CryptoPP include directory. | ||||||
|  | # | ||||||
|  | #   CRYPTOPP_LIBRARIES | ||||||
|  | #     Points to the CryptoPP libraries that should be passed to | ||||||
|  | #     target_link_libararies. | ||||||
|  | # | ||||||
|  | # | ||||||
|  | # Copyright (c) 2012 Sergiu Dotenco | ||||||
|  | # | ||||||
|  | # 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. | ||||||
|  | 
 | ||||||
|  | INCLUDE (FindPackageHandleStandardArgs) | ||||||
|  | 
 | ||||||
|  | FIND_PATH (CRYPTOPP_ROOT_DIR | ||||||
|  |   NAMES cryptopp/cryptlib.h include/cryptopp/cryptlib.h | ||||||
|  |   PATHS ENV CRYPTOPPROOT | ||||||
|  |   DOC "CryptoPP root directory") | ||||||
|  | 
 | ||||||
|  | # Re-use the previous path: | ||||||
|  | FIND_PATH (CRYPTOPP_INCLUDE_DIR | ||||||
|  |   NAMES cryptopp/cryptlib.h | ||||||
|  |   HINTS ${CRYPTOPP_ROOT_DIR} | ||||||
|  |   PATH_SUFFIXES include | ||||||
|  |   DOC "CryptoPP include directory") | ||||||
|  | 
 | ||||||
|  | FIND_LIBRARY (CRYPTOPP_LIBRARY_DEBUG | ||||||
|  |   NAMES cryptlibd cryptoppd | ||||||
|  |   HINTS ${CRYPTOPP_ROOT_DIR} | ||||||
|  |   PATH_SUFFIXES lib | ||||||
|  |   DOC "CryptoPP debug library") | ||||||
|  | 
 | ||||||
|  | FIND_LIBRARY (CRYPTOPP_LIBRARY_RELEASE | ||||||
|  |   NAMES cryptlib cryptopp | ||||||
|  |   HINTS ${CRYPTOPP_ROOT_DIR} | ||||||
|  |   PATH_SUFFIXES lib | ||||||
|  |   DOC "CryptoPP release library") | ||||||
|  | 
 | ||||||
|  | IF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) | ||||||
|  |   SET (CRYPTOPP_LIBRARY | ||||||
|  |     optimized ${CRYPTOPP_LIBRARY_RELEASE} | ||||||
|  |     debug ${CRYPTOPP_LIBRARY_DEBUG} CACHE DOC "CryptoPP library") | ||||||
|  | ELSEIF (CRYPTOPP_LIBRARY_RELEASE) | ||||||
|  |   SET (CRYPTOPP_LIBRARY ${CRYPTOPP_LIBRARY_RELEASE} CACHE DOC | ||||||
|  |     "CryptoPP library") | ||||||
|  | ENDIF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) | ||||||
|  | 
 | ||||||
|  | IF (CRYPTOPP_INCLUDE_DIR) | ||||||
|  |   SET (_CRYPTOPP_VERSION_HEADER ${CRYPTOPP_INCLUDE_DIR}/cryptopp/config.h) | ||||||
|  | 
 | ||||||
|  |   IF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) | ||||||
|  |     FILE (STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION_TMP REGEX | ||||||
|  |       "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") | ||||||
|  | 
 | ||||||
|  |     STRING (REGEX REPLACE | ||||||
|  |       "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION_TMP | ||||||
|  |       ${_CRYPTOPP_VERSION_TMP}) | ||||||
|  | 
 | ||||||
|  |     STRING (REGEX REPLACE "([0-9]+)[0-9][0-9]" "\\1" CRYPTOPP_VERSION_MAJOR | ||||||
|  |       ${_CRYPTOPP_VERSION_TMP}) | ||||||
|  |     STRING (REGEX REPLACE "[0-9]([0-9])[0-9]" "\\1" CRYPTOPP_VERSION_MINOR | ||||||
|  |       ${_CRYPTOPP_VERSION_TMP}) | ||||||
|  |     STRING (REGEX REPLACE "[0-9][0-9]([0-9])" "\\1" CRYPTOPP_VERSION_PATCH | ||||||
|  |       ${_CRYPTOPP_VERSION_TMP}) | ||||||
|  | 
 | ||||||
|  |     SET (CRYPTOPP_VERSION_COUNT 3) | ||||||
|  |     SET (CRYPTOPP_VERSION | ||||||
|  |       ${CRYPTOPP_VERSION_MAJOR}.${CRYPTOPP_VERSION_MINOR}.${CRYPTOPP_VERSION_PATCH}) | ||||||
|  |   ENDIF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) | ||||||
|  | ENDIF (CRYPTOPP_INCLUDE_DIR) | ||||||
|  | 
 | ||||||
|  | SET (CRYPTOPP_INCLUDE_DIRS ${CRYPTOPP_INCLUDE_DIR}) | ||||||
|  | SET (CRYPTOPP_LIBRARIES ${CRYPTOPP_LIBRARY}) | ||||||
|  | 
 | ||||||
|  | MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY CRYPTOPP_LIBRARY_DEBUG | ||||||
|  |   CRYPTOPP_LIBRARY_RELEASE) | ||||||
|  | 
 | ||||||
|  | FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP REQUIRED_VARS CRYPTOPP_ROOT_DIR | ||||||
|  |   CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY VERSION_VAR CRYPTOPP_VERSION) | ||||||
							
								
								
									
										91
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cmake/modules/FindOpenCL.cmake
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cmake/modules/FindOpenCL.cmake
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | # | ||||||
|  | #  This file taken from FindOpenCL project @ http://gitorious.com/findopencl | ||||||
|  | # | ||||||
|  | # - Try to find OpenCL | ||||||
|  | # This module tries to find an OpenCL implementation on your system. It supports | ||||||
|  | # AMD / ATI, Apple and NVIDIA implementations, but shoudl work, too. | ||||||
|  | # | ||||||
|  | # Once done this will define | ||||||
|  | #  OPENCL_FOUND        - system has OpenCL | ||||||
|  | #  OPENCL_INCLUDE_DIRS  - the OpenCL include directory | ||||||
|  | #  OPENCL_LIBRARIES    - link these to use OpenCL | ||||||
|  | # | ||||||
|  | # WIN32 should work, but is untested | ||||||
|  | 
 | ||||||
|  | FIND_PACKAGE( PackageHandleStandardArgs ) | ||||||
|  | 
 | ||||||
|  | SET (OPENCL_VERSION_STRING "0.1.0") | ||||||
|  | SET (OPENCL_VERSION_MAJOR 0) | ||||||
|  | SET (OPENCL_VERSION_MINOR 1) | ||||||
|  | SET (OPENCL_VERSION_PATCH 0) | ||||||
|  | 
 | ||||||
|  | IF (APPLE) | ||||||
|  | 
 | ||||||
|  |   FIND_LIBRARY(OPENCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX") | ||||||
|  |   FIND_PATH(OPENCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX") | ||||||
|  |   FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX") | ||||||
|  | 
 | ||||||
|  | ELSE (APPLE) | ||||||
|  | 
 | ||||||
|  | 	IF (WIN32) | ||||||
|  | 	 | ||||||
|  | 	    FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h) | ||||||
|  | 	    FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp) | ||||||
|  | 	 | ||||||
|  | 	    # The AMD SDK currently installs both x86 and x86_64 libraries | ||||||
|  | 	    # This is only a hack to find out architecture | ||||||
|  | 	    IF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) | ||||||
|  | 	    	SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86_64") | ||||||
|  | 			SET(OPENCL_LIB_DIR "$ENV{ATIINTERNALSTREAMSDKROOT}/lib/x86_64") | ||||||
|  | 	    ELSE (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64") | ||||||
|  | 	    	SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86") | ||||||
|  | 	   		SET(OPENCL_LIB_DIR "$ENV{ATIINTERNALSTREAMSDKROOT}/lib/x86") | ||||||
|  | 	    ENDIF( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" ) | ||||||
|  | 
 | ||||||
|  | 	    # find out if the user asked for a 64-bit build, and use the corresponding  | ||||||
|  | 	    # 64 or 32 bit NVIDIA library paths to the search: | ||||||
|  | 	    STRING(REGEX MATCH "Win64" ISWIN64 ${CMAKE_GENERATOR}) | ||||||
|  | 	    IF("${ISWIN64}" STREQUAL "Win64")  | ||||||
|  | 	    	FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib ${OPENCL_LIB_DIR} $ENV{CUDA_LIB_PATH} $ENV{CUDA_PATH}/lib/x64) | ||||||
|  | 	    ELSE("${ISWIN64}" STREQUAL "Win64")  | ||||||
|  | 	    	FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib ${OPENCL_LIB_DIR} $ENV{CUDA_LIB_PATH} $ENV{CUDA_PATH}/lib/Win32) | ||||||
|  | 	    ENDIF("${ISWIN64}" STREQUAL "Win64")  | ||||||
|  | 
 | ||||||
|  | 	    GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) | ||||||
|  | 	     | ||||||
|  | 	    # On Win32 search relative to the library | ||||||
|  | 	    FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS "${_OPENCL_INC_CAND}" $ENV{CUDA_INC_PATH} $ENV{CUDA_PATH}/include) | ||||||
|  | 	    FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS "${_OPENCL_INC_CAND}" $ENV{CUDA_INC_PATH} $ENV{CUDA_PATH}/include) | ||||||
|  | 	 | ||||||
|  | 	ELSE (WIN32) | ||||||
|  | 
 | ||||||
|  |             # Unix style platforms | ||||||
|  |             FIND_LIBRARY(OPENCL_LIBRARIES OpenCL | ||||||
|  |               ENV LD_LIBRARY_PATH | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |             GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIBRARIES} PATH) | ||||||
|  |             GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) | ||||||
|  | 
 | ||||||
|  |             # The AMD SDK currently does not place its headers | ||||||
|  |             # in /usr/include, therefore also search relative | ||||||
|  |             # to the library | ||||||
|  |             FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include") | ||||||
|  |             FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include") | ||||||
|  | 
 | ||||||
|  | 	ENDIF (WIN32) | ||||||
|  | 
 | ||||||
|  | ENDIF (APPLE) | ||||||
|  | 
 | ||||||
|  | FIND_PACKAGE_HANDLE_STANDARD_ARGS( OpenCL DEFAULT_MSG OPENCL_LIBRARIES OPENCL_INCLUDE_DIRS ) | ||||||
|  | 
 | ||||||
|  | IF( _OPENCL_CPP_INCLUDE_DIRS ) | ||||||
|  | 	SET( OPENCL_HAS_CPP_BINDINGS TRUE ) | ||||||
|  | 	LIST( APPEND OPENCL_INCLUDE_DIRS ${_OPENCL_CPP_INCLUDE_DIRS} ) | ||||||
|  | 	# This is often the same, so clean up | ||||||
|  | 	LIST( REMOVE_DUPLICATES OPENCL_INCLUDE_DIRS ) | ||||||
|  | ENDIF( _OPENCL_CPP_INCLUDE_DIRS ) | ||||||
|  | 
 | ||||||
|  | MARK_AS_ADVANCED( | ||||||
|  |   OPENCL_INCLUDE_DIRS | ||||||
|  | ) | ||||||
							
								
								
									
										13
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cryptopp/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/cryptopp/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | set(LIBRARY cryptopp) | ||||||
|  | 
 | ||||||
|  | include_directories(../../cryptopp) | ||||||
|  | 
 | ||||||
|  | # todo, subset | ||||||
|  | file(GLOB HEADERS "../../cryptopp/*.h") | ||||||
|  | file(GLOB SOURCE "../../cryptopp/*.cpp") | ||||||
|  | 
 | ||||||
|  | add_library(${LIBRARY} ${HEADERS} ${SOURCE}) | ||||||
|  | 
 | ||||||
|  | set(CRYPTOPP_INCLUDE_DIRS "../.." PARENT_SCOPE) | ||||||
|  | set(CRYPTOPP_LIBRARIES ${LIBRARY} PARENT_SCOPE) | ||||||
|  | set(CRYPTOPP_FOUND TRUE PARENT_SCOPE) | ||||||
							
								
								
									
										296
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/ethash.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,296 @@ | |||||||
|  | package ethash | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | #cgo CFLAGS: -std=gnu99 -Wall | ||||||
|  | #include "libethash/ethash.h" | ||||||
|  | #include "libethash/util.c" | ||||||
|  | #include "libethash/internal.c" | ||||||
|  | #include "libethash/sha3.c" | ||||||
|  | */ | ||||||
|  | import "C" | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"log" | ||||||
|  | 	"math/big" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"sync" | ||||||
|  | 	"time" | ||||||
|  | 	"unsafe" | ||||||
|  | 
 | ||||||
|  | 	"github.com/ethereum/go-ethereum/logger" | ||||||
|  | 	"github.com/ethereum/go-ethereum/pow" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var powlogger = logger.NewLogger("POW") | ||||||
|  | 
 | ||||||
|  | type DAG struct { | ||||||
|  | 	SeedBlockNum uint64 | ||||||
|  | 	dag          unsafe.Pointer // full GB of memory for dag
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ParamsAndCache struct { | ||||||
|  | 	params       *C.ethash_params | ||||||
|  | 	cache        *C.ethash_cache | ||||||
|  | 	SeedBlockNum uint64 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Ethash struct { | ||||||
|  | 	turbo          bool | ||||||
|  | 	HashRate       int64 | ||||||
|  | 	chainManager   pow.ChainManager | ||||||
|  | 	dag            *DAG | ||||||
|  | 	paramsAndCache *ParamsAndCache | ||||||
|  | 	nextdag        unsafe.Pointer | ||||||
|  | 	ret            *C.ethash_return_value | ||||||
|  | 	dagMutex       *sync.Mutex | ||||||
|  | 	cacheMutex     *sync.Mutex | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseNonce(nonce []byte) (uint64, error) { | ||||||
|  | 	nonceBuf := bytes.NewBuffer(nonce) | ||||||
|  | 	nonceInt, err := binary.ReadUvarint(nonceBuf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return 0, err | ||||||
|  | 	} | ||||||
|  | 	return nonceInt, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const epochLength uint64 = 30000 | ||||||
|  | 
 | ||||||
|  | func getSeedBlockNum(blockNum uint64) uint64 { | ||||||
|  | 	var seedBlockNum uint64 = 0 | ||||||
|  | 	if blockNum >= 2*epochLength { | ||||||
|  | 		seedBlockNum = ((blockNum / epochLength) - 1) * epochLength | ||||||
|  | 	} | ||||||
|  | 	return seedBlockNum | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func makeParamsAndCache(chainManager pow.ChainManager, blockNum uint64) *ParamsAndCache { | ||||||
|  | 	seedBlockNum := getSeedBlockNum(blockNum) | ||||||
|  | 	paramsAndCache := &ParamsAndCache{ | ||||||
|  | 		params:       new(C.ethash_params), | ||||||
|  | 		cache:        new(C.ethash_cache), | ||||||
|  | 		SeedBlockNum: seedBlockNum, | ||||||
|  | 	} | ||||||
|  | 	C.ethash_params_init(paramsAndCache.params, C.uint32_t(seedBlockNum)) | ||||||
|  | 	paramsAndCache.cache.mem = C.malloc(paramsAndCache.params.cache_size) | ||||||
|  | 	seedHash := chainManager.GetBlockByNumber(seedBlockNum).Header().Hash() | ||||||
|  | 	log.Println("Params", paramsAndCache.params) | ||||||
|  | 
 | ||||||
|  | 	log.Println("Making Cache") | ||||||
|  | 	start := time.Now() | ||||||
|  | 	C.ethash_mkcache(paramsAndCache.cache, paramsAndCache.params, (*C.uint8_t)((unsafe.Pointer)(&seedHash[0]))) | ||||||
|  | 	log.Println("Took:", time.Since(start)) | ||||||
|  | 	return paramsAndCache | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) updateCache() { | ||||||
|  | 	pow.cacheMutex.Lock() | ||||||
|  | 	seedNum := getSeedBlockNum(pow.chainManager.CurrentBlock().NumberU64()) | ||||||
|  | 	if pow.paramsAndCache.SeedBlockNum != seedNum { | ||||||
|  | 		pow.paramsAndCache = makeParamsAndCache(pow.chainManager, pow.chainManager.CurrentBlock().NumberU64()) | ||||||
|  | 	} | ||||||
|  | 	pow.cacheMutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func makeDAG(p *ParamsAndCache) *DAG { | ||||||
|  | 	d := &DAG{ | ||||||
|  | 		dag:          C.malloc(p.params.full_size), | ||||||
|  | 		SeedBlockNum: p.SeedBlockNum, | ||||||
|  | 	} | ||||||
|  | 	C.ethash_compute_full_data(d.dag, p.params, p.cache) | ||||||
|  | 	return d | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) updateDAG() { | ||||||
|  | 	pow.cacheMutex.Lock() | ||||||
|  | 	pow.dagMutex.Lock() | ||||||
|  | 
 | ||||||
|  | 	seedNum := getSeedBlockNum(pow.chainManager.CurrentBlock().NumberU64()) | ||||||
|  | 	if pow.dag == nil || pow.dag.SeedBlockNum != seedNum { | ||||||
|  | 		pow.dag = nil | ||||||
|  | 		log.Println("Making Dag") | ||||||
|  | 		start := time.Now() | ||||||
|  | 		pow.dag = makeDAG(pow.paramsAndCache) | ||||||
|  | 		log.Println("Took:", time.Since(start)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pow.dagMutex.Unlock() | ||||||
|  | 	pow.cacheMutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func New(chainManager pow.ChainManager) *Ethash { | ||||||
|  | 	return &Ethash{ | ||||||
|  | 		turbo:          false, | ||||||
|  | 		paramsAndCache: makeParamsAndCache(chainManager, chainManager.CurrentBlock().NumberU64()), | ||||||
|  | 		chainManager:   chainManager, | ||||||
|  | 		dag:            nil, | ||||||
|  | 		ret:            new(C.ethash_return_value), | ||||||
|  | 		cacheMutex:     new(sync.Mutex), | ||||||
|  | 		dagMutex:       new(sync.Mutex), | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) DAGSize() uint64 { | ||||||
|  | 	return uint64(pow.paramsAndCache.params.full_size) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) CacheSize() uint64 { | ||||||
|  | 	return uint64(pow.paramsAndCache.params.cache_size) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) GetSeedHash(blockNum uint64) []byte { | ||||||
|  | 	return pow.chainManager.GetBlockByNumber(getSeedBlockNum(blockNum)).Header().Hash() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) Stop() { | ||||||
|  | 	pow.cacheMutex.Lock() | ||||||
|  | 	pow.dagMutex.Lock() | ||||||
|  | 	if pow.paramsAndCache.cache != nil { | ||||||
|  | 		C.free(pow.paramsAndCache.cache.mem) | ||||||
|  | 	} | ||||||
|  | 	if pow.dag != nil { | ||||||
|  | 		C.free(pow.dag.dag) | ||||||
|  | 	} | ||||||
|  | 	pow.dagMutex.Unlock() | ||||||
|  | 	pow.cacheMutex.Unlock() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) Search(block pow.Block, stop <-chan struct{}) ([]byte, []byte, []byte) { | ||||||
|  | 	pow.updateDAG() | ||||||
|  | 
 | ||||||
|  | 	// Not very elegant, multiple mining instances are not supported
 | ||||||
|  | 	pow.dagMutex.Lock() | ||||||
|  | 	pow.cacheMutex.Lock() | ||||||
|  | 	defer pow.cacheMutex.Unlock() | ||||||
|  | 	defer pow.dagMutex.Unlock() | ||||||
|  | 
 | ||||||
|  | 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||||
|  | 	miningHash := block.HashNoNonce() | ||||||
|  | 	diff := block.Difficulty() | ||||||
|  | 	log.Println("difficulty", diff) | ||||||
|  | 	i := int64(0) | ||||||
|  | 	start := time.Now().UnixNano() | ||||||
|  | 	t := time.Now() | ||||||
|  | 
 | ||||||
|  | 	nonce := uint64(r.Int63()) | ||||||
|  | 
 | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case <-stop: | ||||||
|  | 			powlogger.Infoln("Breaking from mining") | ||||||
|  | 			pow.HashRate = 0 | ||||||
|  | 			pow.dagMutex.Unlock() | ||||||
|  | 			return nil, nil, nil | ||||||
|  | 		default: | ||||||
|  | 			i++ | ||||||
|  | 
 | ||||||
|  | 			if time.Since(t) > (1 * time.Second) { | ||||||
|  | 				elapsed := time.Now().UnixNano() - start | ||||||
|  | 				hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000 | ||||||
|  | 				pow.HashRate = int64(hashes) | ||||||
|  | 				powlogger.Infoln("Hashing @", pow.HashRate, "khash") | ||||||
|  | 
 | ||||||
|  | 				t = time.Now() | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash)) | ||||||
|  | 			cnonce := C.uint64_t(nonce) | ||||||
|  | 			log.Printf("seed hash, nonce: %x %x\n", miningHash, nonce) | ||||||
|  | 			// pow.hash is the output/return of ethash_full
 | ||||||
|  | 			C.ethash_full(pow.ret, pow.dag.dag, pow.paramsAndCache.params, cMiningHash, cnonce) | ||||||
|  | 			res := C.ethash_check_difficulty((*C.uint8_t)(&pow.ret.result[0]), (*C.uint8_t)(unsafe.Pointer(&diff.Bytes()[0]))) | ||||||
|  | 			if res == 1 { | ||||||
|  | 				mixDigest := C.GoBytes(unsafe.Pointer(&pow.ret.mix_hash[0]), 32) | ||||||
|  | 				// We don't really nead 32 bytes here
 | ||||||
|  | 				buf := make([]byte, 32) | ||||||
|  | 				binary.PutUvarint(buf, nonce) | ||||||
|  | 				return buf, mixDigest, pow.GetSeedHash(block.NumberU64()) | ||||||
|  | 			} | ||||||
|  | 			nonce += 1 | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if !pow.turbo { | ||||||
|  | 			time.Sleep(20 * time.Microsecond) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) Verify(block pow.Block) bool { | ||||||
|  | 	// Make sure the SeedHash is set correctly
 | ||||||
|  | 	if bytes.Compare(block.SeedHash(), pow.GetSeedHash(block.NumberU64())) != 0 { | ||||||
|  | 		log.Println("Block had wrong SeedHash") | ||||||
|  | 		log.Println("Expected: ", pow.GetSeedHash(block.NumberU64())) | ||||||
|  | 		log.Println("Actual: ", block.SeedHash()) | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	nonceInt, err := parseNonce(block.Nonce()) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println("nonce to int err:", err) | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return pow.verify(block.HashNoNonce(), block.MixDigest(), block.Difficulty(), block.NumberU64(), nonceInt) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) verify(hash []byte, mixDigest []byte, difficulty *big.Int, blockNum uint64, nonce uint64) bool { | ||||||
|  | 	// First check: make sure header, mixDigest, nonce are correct without hitting the DAG
 | ||||||
|  | 	// This is to prevent DOS attacks
 | ||||||
|  | 	chash := (*C.uint8_t)(unsafe.Pointer(&hash)) | ||||||
|  | 	cnonce := C.uint64_t(nonce) | ||||||
|  | 	cmixDigest := (*C.uint8_t)(unsafe.Pointer(&mixDigest)) | ||||||
|  | 	cdifficulty := (*C.uint8_t)(unsafe.Pointer(&difficulty.Bytes()[0])) | ||||||
|  | 	if C.ethash_quick_check_difficulty(chash, cnonce, cmixDigest, cdifficulty) != 1 { | ||||||
|  | 		log.Println("Failed to pass quick check.  Are you sure that the mix digest is correct?") | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var pAc *ParamsAndCache | ||||||
|  | 	// If its an old block (doesn't use the current cache)
 | ||||||
|  | 	// get the cache for it but don't update (so we don't need the mutex)
 | ||||||
|  | 	// Otherwise, it's the current block or a future.
 | ||||||
|  | 	// If current, updateCache will do nothing.
 | ||||||
|  | 	if getSeedBlockNum(blockNum) < pow.paramsAndCache.SeedBlockNum { | ||||||
|  | 		pAc = makeParamsAndCache(pow.chainManager, blockNum) | ||||||
|  | 	} else { | ||||||
|  | 		pow.updateCache() | ||||||
|  | 		pow.cacheMutex.Lock() | ||||||
|  | 		defer pow.cacheMutex.Unlock() | ||||||
|  | 		pAc = pow.paramsAndCache | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	C.ethash_light(pow.ret, pAc.cache, pAc.params, chash, cnonce) | ||||||
|  | 	res := C.ethash_check_difficulty((*C.uint8_t)(unsafe.Pointer(&pow.ret.result[0])), cdifficulty) | ||||||
|  | 	return res == 1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) GetHashrate() int64 { | ||||||
|  | 	return pow.HashRate | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) Turbo(on bool) { | ||||||
|  | 	pow.turbo = on | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) FullHash(nonce uint64, miningHash []byte) []byte { | ||||||
|  | 	pow.updateDAG() | ||||||
|  | 	pow.dagMutex.Lock() | ||||||
|  | 	defer pow.dagMutex.Unlock() | ||||||
|  | 	cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash)) | ||||||
|  | 	cnonce := C.uint64_t(nonce) | ||||||
|  | 	log.Println("seed hash, nonce:", miningHash, nonce) | ||||||
|  | 	// pow.hash is the output/return of ethash_full
 | ||||||
|  | 	C.ethash_full(pow.ret, pow.dag.dag, pow.paramsAndCache.params, cMiningHash, cnonce) | ||||||
|  | 	ghash_full := C.GoBytes(unsafe.Pointer(&pow.ret.result[0]), 32) | ||||||
|  | 	return ghash_full | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pow *Ethash) LightHash(nonce uint64, miningHash []byte) []byte { | ||||||
|  | 	cMiningHash := (*C.uint8_t)(unsafe.Pointer(&miningHash)) | ||||||
|  | 	cnonce := C.uint64_t(nonce) | ||||||
|  | 	C.ethash_light(pow.ret, pow.paramsAndCache.cache, pow.paramsAndCache.params, cMiningHash, cnonce) | ||||||
|  | 	ghash_light := C.GoBytes(unsafe.Pointer(&pow.ret.result[0]), 32) | ||||||
|  | 	return ghash_light | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | set(LIBRARY ethash-cl) | ||||||
|  | set(CMAKE_BUILD_TYPE Release) | ||||||
|  | 
 | ||||||
|  | if (NOT OPENCL_FOUND) | ||||||
|  | 	find_package(OpenCL) | ||||||
|  | endif() | ||||||
|  | if (OPENCL_FOUND) | ||||||
|  | 	include_directories(${OPENCL_INCLUDE_DIRS}) | ||||||
|  | 	include_directories(..) | ||||||
|  | 	add_library(${LIBRARY} ethash_cl_miner.cpp ethash_cl_miner.h) | ||||||
|  | 	TARGET_LINK_LIBRARIES(${LIBRARY} ${OPENCL_LIBRARIES} ethash) | ||||||
|  | endif() | ||||||
							
								
								
									
										12452
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/cl.hpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12452
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/cl.hpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										754
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/ethash_cl_miner.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										754
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/ethash_cl_miner.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,754 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of c-ethash. | ||||||
|  | 
 | ||||||
|  |   c-ethash is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   c-ethash is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file ethash_cl_miner.cpp
 | ||||||
|  | * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #define _CRT_SECURE_NO_WARNINGS | ||||||
|  | 
 | ||||||
|  | #include <assert.h> | ||||||
|  | #include <queue> | ||||||
|  | #include "ethash_cl_miner.h" | ||||||
|  | #include <libethash/util.h> | ||||||
|  | 
 | ||||||
|  | #undef min | ||||||
|  | #undef max | ||||||
|  | 
 | ||||||
|  | #define HASH_BYTES 32 | ||||||
|  | 
 | ||||||
|  | static char const ethash_inner_code[] = R"( | ||||||
|  | 
 | ||||||
|  | // author Tim Hughes <tim@twistedfury.com>
 | ||||||
|  | // Tested on Radeon HD 7850
 | ||||||
|  | // Hashrate: 15940347 hashes/s
 | ||||||
|  | // Bandwidth: 124533 MB/s
 | ||||||
|  | // search kernel should fit in <= 84 VGPRS (3 wavefronts)
 | ||||||
|  | 
 | ||||||
|  | #define THREADS_PER_HASH (128 / 16) | ||||||
|  | #define HASHES_PER_LOOP (GROUP_SIZE / THREADS_PER_HASH) | ||||||
|  | 
 | ||||||
|  | #define FNV_PRIME	0x01000193 | ||||||
|  | 
 | ||||||
|  | __constant uint2 const Keccak_f1600_RC[24] = { | ||||||
|  | 	(uint2)(0x00000001, 0x00000000), | ||||||
|  | 	(uint2)(0x00008082, 0x00000000), | ||||||
|  | 	(uint2)(0x0000808a, 0x80000000), | ||||||
|  | 	(uint2)(0x80008000, 0x80000000), | ||||||
|  | 	(uint2)(0x0000808b, 0x00000000), | ||||||
|  | 	(uint2)(0x80000001, 0x00000000), | ||||||
|  | 	(uint2)(0x80008081, 0x80000000), | ||||||
|  | 	(uint2)(0x00008009, 0x80000000), | ||||||
|  | 	(uint2)(0x0000008a, 0x00000000), | ||||||
|  | 	(uint2)(0x00000088, 0x00000000), | ||||||
|  | 	(uint2)(0x80008009, 0x00000000), | ||||||
|  | 	(uint2)(0x8000000a, 0x00000000), | ||||||
|  | 	(uint2)(0x8000808b, 0x00000000), | ||||||
|  | 	(uint2)(0x0000008b, 0x80000000), | ||||||
|  | 	(uint2)(0x00008089, 0x80000000), | ||||||
|  | 	(uint2)(0x00008003, 0x80000000), | ||||||
|  | 	(uint2)(0x00008002, 0x80000000), | ||||||
|  | 	(uint2)(0x00000080, 0x80000000), | ||||||
|  | 	(uint2)(0x0000800a, 0x00000000), | ||||||
|  | 	(uint2)(0x8000000a, 0x80000000), | ||||||
|  | 	(uint2)(0x80008081, 0x80000000), | ||||||
|  | 	(uint2)(0x00008080, 0x80000000), | ||||||
|  | 	(uint2)(0x80000001, 0x00000000), | ||||||
|  | 	(uint2)(0x80008008, 0x80000000), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void keccak_f1600_round(uint2* a, uint r, uint out_size) | ||||||
|  | { | ||||||
|  |    #if !__ENDIAN_LITTLE__ | ||||||
|  | 	for (uint i = 0; i != 25; ++i) | ||||||
|  | 		a[i] = a[i].yx; | ||||||
|  |    #endif | ||||||
|  | 
 | ||||||
|  | 	uint2 b[25]; | ||||||
|  | 	uint2 t; | ||||||
|  | 
 | ||||||
|  | 	// Theta
 | ||||||
|  | 	b[0] = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]; | ||||||
|  | 	b[1] = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]; | ||||||
|  | 	b[2] = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]; | ||||||
|  | 	b[3] = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]; | ||||||
|  | 	b[4] = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]; | ||||||
|  | 	t = b[4] ^ (uint2)(b[1].x << 1 | b[1].y >> 31, b[1].y << 1 | b[1].x >> 31); | ||||||
|  | 	a[0] ^= t; | ||||||
|  | 	a[5] ^= t; | ||||||
|  | 	a[10] ^= t; | ||||||
|  | 	a[15] ^= t; | ||||||
|  | 	a[20] ^= t; | ||||||
|  | 	t = b[0] ^ (uint2)(b[2].x << 1 | b[2].y >> 31, b[2].y << 1 | b[2].x >> 31); | ||||||
|  | 	a[1] ^= t; | ||||||
|  | 	a[6] ^= t; | ||||||
|  | 	a[11] ^= t; | ||||||
|  | 	a[16] ^= t; | ||||||
|  | 	a[21] ^= t; | ||||||
|  | 	t = b[1] ^ (uint2)(b[3].x << 1 | b[3].y >> 31, b[3].y << 1 | b[3].x >> 31); | ||||||
|  | 	a[2] ^= t; | ||||||
|  | 	a[7] ^= t; | ||||||
|  | 	a[12] ^= t; | ||||||
|  | 	a[17] ^= t; | ||||||
|  | 	a[22] ^= t; | ||||||
|  | 	t = b[2] ^ (uint2)(b[4].x << 1 | b[4].y >> 31, b[4].y << 1 | b[4].x >> 31); | ||||||
|  | 	a[3] ^= t; | ||||||
|  | 	a[8] ^= t; | ||||||
|  | 	a[13] ^= t; | ||||||
|  | 	a[18] ^= t; | ||||||
|  | 	a[23] ^= t; | ||||||
|  | 	t = b[3] ^ (uint2)(b[0].x << 1 | b[0].y >> 31, b[0].y << 1 | b[0].x >> 31); | ||||||
|  | 	a[4] ^= t; | ||||||
|  | 	a[9] ^= t; | ||||||
|  | 	a[14] ^= t; | ||||||
|  | 	a[19] ^= t; | ||||||
|  | 	a[24] ^= t; | ||||||
|  | 
 | ||||||
|  | 	// Rho Pi
 | ||||||
|  | 	b[0] = a[0]; | ||||||
|  | 	b[10] = (uint2)(a[1].x << 1 | a[1].y >> 31, a[1].y << 1 | a[1].x >> 31); | ||||||
|  | 	b[7] = (uint2)(a[10].x << 3 | a[10].y >> 29, a[10].y << 3 | a[10].x >> 29); | ||||||
|  | 	b[11] = (uint2)(a[7].x << 6 | a[7].y >> 26, a[7].y << 6 | a[7].x >> 26); | ||||||
|  | 	b[17] = (uint2)(a[11].x << 10 | a[11].y >> 22, a[11].y << 10 | a[11].x >> 22); | ||||||
|  | 	b[18] = (uint2)(a[17].x << 15 | a[17].y >> 17, a[17].y << 15 | a[17].x >> 17); | ||||||
|  | 	b[3] = (uint2)(a[18].x << 21 | a[18].y >> 11, a[18].y << 21 | a[18].x >> 11); | ||||||
|  | 	b[5] = (uint2)(a[3].x << 28 | a[3].y >> 4, a[3].y << 28 | a[3].x >> 4); | ||||||
|  | 	b[16] = (uint2)(a[5].y << 4 | a[5].x >> 28, a[5].x << 4 | a[5].y >> 28); | ||||||
|  | 	b[8] = (uint2)(a[16].y << 13 | a[16].x >> 19, a[16].x << 13 | a[16].y >> 19); | ||||||
|  | 	b[21] = (uint2)(a[8].y << 23 | a[8].x >> 9, a[8].x << 23 | a[8].y >> 9); | ||||||
|  | 	b[24] = (uint2)(a[21].x << 2 | a[21].y >> 30, a[21].y << 2 | a[21].x >> 30); | ||||||
|  | 	b[4] = (uint2)(a[24].x << 14 | a[24].y >> 18, a[24].y << 14 | a[24].x >> 18); | ||||||
|  | 	b[15] = (uint2)(a[4].x << 27 | a[4].y >> 5, a[4].y << 27 | a[4].x >> 5); | ||||||
|  | 	b[23] = (uint2)(a[15].y << 9 | a[15].x >> 23, a[15].x << 9 | a[15].y >> 23); | ||||||
|  | 	b[19] = (uint2)(a[23].y << 24 | a[23].x >> 8, a[23].x << 24 | a[23].y >> 8); | ||||||
|  | 	b[13] = (uint2)(a[19].x << 8 | a[19].y >> 24, a[19].y << 8 | a[19].x >> 24); | ||||||
|  | 	b[12] = (uint2)(a[13].x << 25 | a[13].y >> 7, a[13].y << 25 | a[13].x >> 7); | ||||||
|  | 	b[2] = (uint2)(a[12].y << 11 | a[12].x >> 21, a[12].x << 11 | a[12].y >> 21); | ||||||
|  | 	b[20] = (uint2)(a[2].y << 30 | a[2].x >> 2, a[2].x << 30 | a[2].y >> 2); | ||||||
|  | 	b[14] = (uint2)(a[20].x << 18 | a[20].y >> 14, a[20].y << 18 | a[20].x >> 14); | ||||||
|  | 	b[22] = (uint2)(a[14].y << 7 | a[14].x >> 25, a[14].x << 7 | a[14].y >> 25); | ||||||
|  | 	b[9] = (uint2)(a[22].y << 29 | a[22].x >> 3, a[22].x << 29 | a[22].y >> 3); | ||||||
|  | 	b[6] = (uint2)(a[9].x << 20 | a[9].y >> 12, a[9].y << 20 | a[9].x >> 12); | ||||||
|  | 	b[1] = (uint2)(a[6].y << 12 | a[6].x >> 20, a[6].x << 12 | a[6].y >> 20); | ||||||
|  | 
 | ||||||
|  | 	// Chi
 | ||||||
|  | 	a[0] = bitselect(b[0] ^ b[2], b[0], b[1]); | ||||||
|  | 	a[1] = bitselect(b[1] ^ b[3], b[1], b[2]); | ||||||
|  | 	a[2] = bitselect(b[2] ^ b[4], b[2], b[3]); | ||||||
|  | 	a[3] = bitselect(b[3] ^ b[0], b[3], b[4]); | ||||||
|  | 	if (out_size >= 4) | ||||||
|  | 	{ | ||||||
|  | 		a[4] = bitselect(b[4] ^ b[1], b[4], b[0]); | ||||||
|  | 		a[5] = bitselect(b[5] ^ b[7], b[5], b[6]); | ||||||
|  | 		a[6] = bitselect(b[6] ^ b[8], b[6], b[7]); | ||||||
|  | 		a[7] = bitselect(b[7] ^ b[9], b[7], b[8]); | ||||||
|  | 		a[8] = bitselect(b[8] ^ b[5], b[8], b[9]); | ||||||
|  | 		if (out_size >= 8) | ||||||
|  | 		{ | ||||||
|  | 			a[9] = bitselect(b[9] ^ b[6], b[9], b[5]); | ||||||
|  | 			a[10] = bitselect(b[10] ^ b[12], b[10], b[11]); | ||||||
|  | 			a[11] = bitselect(b[11] ^ b[13], b[11], b[12]); | ||||||
|  | 			a[12] = bitselect(b[12] ^ b[14], b[12], b[13]); | ||||||
|  | 			a[13] = bitselect(b[13] ^ b[10], b[13], b[14]); | ||||||
|  | 			a[14] = bitselect(b[14] ^ b[11], b[14], b[10]); | ||||||
|  | 			a[15] = bitselect(b[15] ^ b[17], b[15], b[16]); | ||||||
|  | 			a[16] = bitselect(b[16] ^ b[18], b[16], b[17]); | ||||||
|  | 			a[17] = bitselect(b[17] ^ b[19], b[17], b[18]); | ||||||
|  | 			a[18] = bitselect(b[18] ^ b[15], b[18], b[19]); | ||||||
|  | 			a[19] = bitselect(b[19] ^ b[16], b[19], b[15]); | ||||||
|  | 			a[20] = bitselect(b[20] ^ b[22], b[20], b[21]); | ||||||
|  | 			a[21] = bitselect(b[21] ^ b[23], b[21], b[22]); | ||||||
|  | 			a[22] = bitselect(b[22] ^ b[24], b[22], b[23]); | ||||||
|  | 			a[23] = bitselect(b[23] ^ b[20], b[23], b[24]); | ||||||
|  | 			a[24] = bitselect(b[24] ^ b[21], b[24], b[20]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Iota
 | ||||||
|  | 	a[0] ^= Keccak_f1600_RC[r]; | ||||||
|  | 
 | ||||||
|  |    #if !__ENDIAN_LITTLE__ | ||||||
|  | 	for (uint i = 0; i != 25; ++i) | ||||||
|  | 		a[i] = a[i].yx; | ||||||
|  |    #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void keccak_f1600_no_absorb(ulong* a, uint in_size, uint out_size, uint isolate) | ||||||
|  | { | ||||||
|  | 	for (uint i = in_size; i != 25; ++i) | ||||||
|  | 	{ | ||||||
|  | 		a[i] = 0; | ||||||
|  | 	} | ||||||
|  | #if __ENDIAN_LITTLE__ | ||||||
|  | 	a[in_size] ^= 0x0000000000000001; | ||||||
|  | 	a[24-out_size*2] ^= 0x8000000000000000; | ||||||
|  | #else | ||||||
|  | 	a[in_size] ^= 0x0100000000000000; | ||||||
|  | 	a[24-out_size*2] ^= 0x0000000000000080; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	// Originally I unrolled the first and last rounds to interface
 | ||||||
|  | 	// better with surrounding code, however I haven't done this
 | ||||||
|  | 	// without causing the AMD compiler to blow up the VGPR usage.
 | ||||||
|  | 	uint r = 0; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		// This dynamic branch stops the AMD compiler unrolling the loop
 | ||||||
|  | 		// and additionally saves about 33% of the VGPRs, enough to gain another
 | ||||||
|  | 		// wavefront. Ideally we'd get 4 in flight, but 3 is the best I can
 | ||||||
|  | 		// massage out of the compiler. It doesn't really seem to matter how
 | ||||||
|  | 		// much we try and help the compiler save VGPRs because it seems to throw
 | ||||||
|  | 		// that information away, hence the implementation of keccak here
 | ||||||
|  | 		// doesn't bother.
 | ||||||
|  | 		if (isolate)  | ||||||
|  | 		{ | ||||||
|  | 			keccak_f1600_round((uint2*)a, r++, 25); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while (r < 23); | ||||||
|  | 	 | ||||||
|  | 	// final round optimised for digest size
 | ||||||
|  | 	keccak_f1600_round((uint2*)a, r++, out_size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define copy(dst, src, count) for (uint i = 0; i != count; ++i) { (dst)[i] = (src)[i]; } | ||||||
|  | 
 | ||||||
|  | #define countof(x) (sizeof(x) / sizeof(x[0])) | ||||||
|  | 
 | ||||||
|  | uint fnv(uint x, uint y) | ||||||
|  | { | ||||||
|  | 	return x * FNV_PRIME ^ y; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint4 fnv4(uint4 x, uint4 y) | ||||||
|  | { | ||||||
|  | 	return x * FNV_PRIME ^ y; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint fnv_reduce(uint4 v) | ||||||
|  | { | ||||||
|  | 	return fnv(fnv(fnv(v.x, v.y), v.z), v.w); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef union | ||||||
|  | { | ||||||
|  | 	ulong ulongs[32 / sizeof(ulong)]; | ||||||
|  | 	uint uints[32 / sizeof(uint)]; | ||||||
|  | } hash32_t; | ||||||
|  | 
 | ||||||
|  | typedef union | ||||||
|  | { | ||||||
|  | 	ulong ulongs[64 / sizeof(ulong)]; | ||||||
|  | 	uint4 uint4s[64 / sizeof(uint4)]; | ||||||
|  | } hash64_t; | ||||||
|  | 
 | ||||||
|  | typedef union | ||||||
|  | { | ||||||
|  | 	uint uints[128 / sizeof(uint)]; | ||||||
|  | 	uint4 uint4s[128 / sizeof(uint4)]; | ||||||
|  | } hash128_t; | ||||||
|  | 
 | ||||||
|  | hash64_t init_hash(__constant hash32_t const* header, ulong nonce, uint isolate) | ||||||
|  | { | ||||||
|  | 	hash64_t init; | ||||||
|  | 	uint const init_size = countof(init.ulongs); | ||||||
|  | 	uint const hash_size = countof(header->ulongs); | ||||||
|  | 	 | ||||||
|  | 	// sha3_512(header .. nonce)
 | ||||||
|  | 	ulong state[25]; | ||||||
|  | 	copy(state, header->ulongs, hash_size); | ||||||
|  | 	state[hash_size] = nonce; | ||||||
|  | 	keccak_f1600_no_absorb(state, hash_size + 1, init_size, isolate); | ||||||
|  | 
 | ||||||
|  | 	copy(init.ulongs, state, init_size); | ||||||
|  | 	return init; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint inner_loop(uint4 init, uint thread_id, __local uint* share, __global hash128_t const* g_dag, uint isolate) | ||||||
|  | { | ||||||
|  | 	uint4 mix = init; | ||||||
|  | 
 | ||||||
|  | 	// share init0
 | ||||||
|  | 	if (thread_id == 0) | ||||||
|  | 		*share = mix.x; | ||||||
|  | 	barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 	uint init0 = *share; | ||||||
|  | 
 | ||||||
|  | 	uint a = 0; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		bool update_share = thread_id == (a/4) % THREADS_PER_HASH; | ||||||
|  | 
 | ||||||
|  | 		#pragma unroll | ||||||
|  | 		for (uint i = 0; i != 4; ++i) | ||||||
|  | 		{ | ||||||
|  | 			if (update_share) | ||||||
|  | 			{ | ||||||
|  | 				uint m[4] = { mix.x, mix.y, mix.z, mix.w }; | ||||||
|  | 				*share = fnv(init0 ^ (a+i), m[i]) % DAG_SIZE; | ||||||
|  | 			} | ||||||
|  | 			barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 
 | ||||||
|  | 			mix = fnv4(mix, g_dag[*share].uint4s[thread_id]); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while ((a += 4) != (ACCESSES & isolate)); | ||||||
|  | 
 | ||||||
|  | 	return fnv_reduce(mix); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | hash32_t final_hash(hash64_t const* init, hash32_t const* mix, uint isolate) | ||||||
|  | { | ||||||
|  | 	ulong state[25]; | ||||||
|  | 
 | ||||||
|  | 	hash32_t hash; | ||||||
|  | 	uint const hash_size = countof(hash.ulongs); | ||||||
|  | 	uint const init_size = countof(init->ulongs); | ||||||
|  | 	uint const mix_size = countof(mix->ulongs); | ||||||
|  | 
 | ||||||
|  | 	// keccak_256(keccak_512(header..nonce) .. mix);
 | ||||||
|  | 	copy(state, init->ulongs, init_size); | ||||||
|  | 	copy(state + init_size, mix->ulongs, mix_size); | ||||||
|  | 	keccak_f1600_no_absorb(state, init_size+mix_size, hash_size, isolate); | ||||||
|  | 
 | ||||||
|  | 	// copy out
 | ||||||
|  | 	copy(hash.ulongs, state, hash_size); | ||||||
|  | 	return hash; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | hash32_t compute_hash_simple( | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong nonce, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	hash64_t init = init_hash(g_header, nonce, isolate); | ||||||
|  | 
 | ||||||
|  | 	hash128_t mix; | ||||||
|  | 	for (uint i = 0; i != countof(mix.uint4s); ++i) | ||||||
|  | 	{ | ||||||
|  | 		mix.uint4s[i] = init.uint4s[i % countof(init.uint4s)]; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	uint mix_val = mix.uints[0]; | ||||||
|  | 	uint init0 = mix.uints[0]; | ||||||
|  | 	uint a = 0; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		uint pi = fnv(init0 ^ a, mix_val) % DAG_SIZE; | ||||||
|  | 		uint n = (a+1) % countof(mix.uints); | ||||||
|  | 
 | ||||||
|  | 		#pragma unroll | ||||||
|  | 		for (uint i = 0; i != countof(mix.uints); ++i) | ||||||
|  | 		{ | ||||||
|  | 			mix.uints[i] = fnv(mix.uints[i], g_dag[pi].uints[i]); | ||||||
|  | 			mix_val = i == n ? mix.uints[i] : mix_val; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	while (++a != (ACCESSES & isolate)); | ||||||
|  | 
 | ||||||
|  | 	// reduce to output
 | ||||||
|  | 	hash32_t fnv_mix; | ||||||
|  | 	for (uint i = 0; i != countof(fnv_mix.uints); ++i) | ||||||
|  | 	{ | ||||||
|  | 		fnv_mix.uints[i] = fnv_reduce(mix.uint4s[i]); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	return final_hash(&init, &fnv_mix, isolate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef union | ||||||
|  | { | ||||||
|  | 	struct | ||||||
|  | 	{ | ||||||
|  | 		hash64_t init; | ||||||
|  | 		uint pad; // avoid lds bank conflicts
 | ||||||
|  | 	}; | ||||||
|  | 	hash32_t mix; | ||||||
|  | } compute_hash_share; | ||||||
|  | 
 | ||||||
|  | hash32_t compute_hash( | ||||||
|  | 	__local compute_hash_share* share, | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong nonce, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	uint const gid = get_global_id(0); | ||||||
|  | 
 | ||||||
|  | 	// Compute one init hash per work item.
 | ||||||
|  | 	hash64_t init = init_hash(g_header, nonce, isolate); | ||||||
|  | 
 | ||||||
|  | 	// Threads work together in this phase in groups of 8.
 | ||||||
|  | 	uint const thread_id = gid % THREADS_PER_HASH; | ||||||
|  | 	uint const hash_id = (gid % GROUP_SIZE) / THREADS_PER_HASH; | ||||||
|  | 
 | ||||||
|  | 	hash32_t mix; | ||||||
|  | 	uint i = 0; | ||||||
|  | 	do | ||||||
|  | 	{ | ||||||
|  | 		// share init with other threads
 | ||||||
|  | 		if (i == thread_id) | ||||||
|  | 			share[hash_id].init = init; | ||||||
|  | 		barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 
 | ||||||
|  | 		uint4 thread_init = share[hash_id].init.uint4s[thread_id % (64 / sizeof(uint4))]; | ||||||
|  | 		barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 
 | ||||||
|  | 		uint thread_mix = inner_loop(thread_init, thread_id, share[hash_id].mix.uints, g_dag, isolate); | ||||||
|  | 
 | ||||||
|  | 		share[hash_id].mix.uints[thread_id] = thread_mix; | ||||||
|  | 		barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 
 | ||||||
|  | 		if (i == thread_id) | ||||||
|  | 			mix = share[hash_id].mix; | ||||||
|  | 		barrier(CLK_LOCAL_MEM_FENCE); | ||||||
|  | 	} | ||||||
|  | 	while (++i != (THREADS_PER_HASH & isolate)); | ||||||
|  | 
 | ||||||
|  | 	return final_hash(&init, &mix, isolate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) | ||||||
|  | __kernel void ethash_hash_simple( | ||||||
|  | 	__global hash32_t* g_hashes, | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong start_nonce, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	uint const gid = get_global_id(0); | ||||||
|  | 	g_hashes[gid] = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) | ||||||
|  | __kernel void ethash_search_simple( | ||||||
|  | 	__global volatile uint* restrict g_output, | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong start_nonce, | ||||||
|  | 	ulong target, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	uint const gid = get_global_id(0); | ||||||
|  | 	hash32_t hash = compute_hash_simple(g_header, g_dag, start_nonce + gid, isolate); | ||||||
|  | 
 | ||||||
|  | 	if (hash.ulongs[countof(hash.ulongs)-1] < target) | ||||||
|  | 	{ | ||||||
|  | 		uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1); | ||||||
|  | 		g_output[slot] = gid; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) | ||||||
|  | __kernel void ethash_hash( | ||||||
|  | 	__global hash32_t* g_hashes, | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong start_nonce, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	__local compute_hash_share share[HASHES_PER_LOOP]; | ||||||
|  | 
 | ||||||
|  | 	uint const gid = get_global_id(0); | ||||||
|  | 	g_hashes[gid] = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__((reqd_work_group_size(GROUP_SIZE, 1, 1))) | ||||||
|  | __kernel void ethash_search( | ||||||
|  | 	__global volatile uint* restrict g_output, | ||||||
|  | 	__constant hash32_t const* g_header, | ||||||
|  | 	__global hash128_t const* g_dag, | ||||||
|  | 	ulong start_nonce, | ||||||
|  | 	ulong target, | ||||||
|  | 	uint isolate | ||||||
|  | 	) | ||||||
|  | { | ||||||
|  | 	__local compute_hash_share share[HASHES_PER_LOOP]; | ||||||
|  | 
 | ||||||
|  | 	uint const gid = get_global_id(0); | ||||||
|  | 	hash32_t hash = compute_hash(share, g_header, g_dag, start_nonce + gid, isolate); | ||||||
|  | 
 | ||||||
|  | 	if (hash.ulongs[countof(hash.ulongs)-1] < target) | ||||||
|  | 	{ | ||||||
|  | 		uint slot = min(MAX_OUTPUTS, atomic_inc(&g_output[0]) + 1); | ||||||
|  | 		g_output[slot] = gid; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | )"; | ||||||
|  | 
 | ||||||
|  | static void add_definition(std::string& source, char const* id, unsigned value) | ||||||
|  | { | ||||||
|  | 	char buf[256]; | ||||||
|  | 	sprintf(buf, "#define %s %uu\n", id, value); | ||||||
|  | 	source.insert(source.begin(), buf, buf + strlen(buf)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ethash_cl_miner::ethash_cl_miner() | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool ethash_cl_miner::init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size) | ||||||
|  | { | ||||||
|  | 	// store params
 | ||||||
|  | 	m_params = params; | ||||||
|  | 
 | ||||||
|  | 	// get all platforms
 | ||||||
|  |     std::vector<cl::Platform> platforms; | ||||||
|  |     cl::Platform::get(&platforms); | ||||||
|  | 	if (platforms.empty()) | ||||||
|  | 	{ | ||||||
|  | 		debugf("No OpenCL platforms found.\n"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// use default platform
 | ||||||
|  | 	debugf("Using platform: %s\n", platforms[0].getInfo<CL_PLATFORM_NAME>().c_str()); | ||||||
|  | 
 | ||||||
|  |     // get GPU device of the default platform
 | ||||||
|  |     std::vector<cl::Device> devices; | ||||||
|  |     platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices); | ||||||
|  |     if (devices.empty()) | ||||||
|  | 	{ | ||||||
|  | 		debugf("No OpenCL devices found.\n"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// use default device
 | ||||||
|  | 	cl::Device& device = devices[0]; | ||||||
|  | 	debugf("Using device: %s\n", device.getInfo<CL_DEVICE_NAME>().c_str()); | ||||||
|  | 
 | ||||||
|  | 	// create context
 | ||||||
|  | 	m_context = cl::Context({device}); | ||||||
|  | 	m_queue = cl::CommandQueue(m_context, device); | ||||||
|  | 
 | ||||||
|  | 	// use requested workgroup size, but we require multiple of 8
 | ||||||
|  | 	m_workgroup_size = ((workgroup_size + 7) / 8) * 8; | ||||||
|  | 
 | ||||||
|  | 	// patch source code
 | ||||||
|  | 	std::string code = ethash_inner_code; | ||||||
|  | 	add_definition(code, "GROUP_SIZE", m_workgroup_size); | ||||||
|  | 	add_definition(code, "DAG_SIZE", (unsigned)(params.full_size / MIX_BYTES)); | ||||||
|  | 	add_definition(code, "ACCESSES", ACCESSES); | ||||||
|  | 	add_definition(code, "MAX_OUTPUTS", c_max_search_results); | ||||||
|  | 	//debugf("%s", code.c_str());
 | ||||||
|  | 
 | ||||||
|  | 	// create miner OpenCL program
 | ||||||
|  | 	cl::Program::Sources sources; | ||||||
|  | 	sources.push_back({code.c_str(), code.size()}); | ||||||
|  | 
 | ||||||
|  | 	cl::Program program(m_context, sources); | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		program.build({device}); | ||||||
|  | 	} | ||||||
|  | 	catch (cl::Error err) | ||||||
|  | 	{ | ||||||
|  | 		debugf("%s\n", program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device).c_str()); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 	m_hash_kernel = cl::Kernel(program, "ethash_hash"); | ||||||
|  | 	m_search_kernel = cl::Kernel(program, "ethash_search"); | ||||||
|  | 
 | ||||||
|  | 	// create buffer for dag
 | ||||||
|  | 	m_dag = cl::Buffer(m_context, CL_MEM_READ_ONLY, params.full_size); | ||||||
|  | 	 | ||||||
|  | 	// create buffer for header
 | ||||||
|  | 	m_header = cl::Buffer(m_context, CL_MEM_READ_ONLY, 32); | ||||||
|  | 
 | ||||||
|  | 	// compute dag on CPU
 | ||||||
|  | 	{ | ||||||
|  | 		void* cache_mem = malloc(params.cache_size + 63); | ||||||
|  | 		ethash_cache cache; | ||||||
|  | 		cache.mem = (void*)(((uintptr_t)cache_mem + 63) & ~63); | ||||||
|  | 		ethash_mkcache(&cache, ¶ms, seed); | ||||||
|  | 
 | ||||||
|  | 		// if this throws then it's because we probably need to subdivide the dag uploads for compatibility
 | ||||||
|  | 		void* dag_ptr = m_queue.enqueueMapBuffer(m_dag, true, CL_MAP_WRITE_INVALIDATE_REGION, 0, params.full_size); | ||||||
|  | 		ethash_compute_full_data(dag_ptr, ¶ms, &cache); | ||||||
|  | 		m_queue.enqueueUnmapMemObject(m_dag, dag_ptr); | ||||||
|  | 
 | ||||||
|  | 		free(cache_mem); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// create mining buffers
 | ||||||
|  | 	for (unsigned i = 0; i != c_num_buffers; ++i) | ||||||
|  | 	{ | ||||||
|  | 		m_hash_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY | CL_MEM_HOST_READ_ONLY, 32*c_hash_batch_size); | ||||||
|  | 		m_search_buf[i] = cl::Buffer(m_context, CL_MEM_WRITE_ONLY, (c_max_search_results + 1) * sizeof(uint32_t)); | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_cl_miner::hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count) | ||||||
|  | { | ||||||
|  | 	struct pending_batch | ||||||
|  | 	{ | ||||||
|  | 		unsigned base; | ||||||
|  | 		unsigned count; | ||||||
|  | 		unsigned buf; | ||||||
|  | 	}; | ||||||
|  | 	std::queue<pending_batch> pending; | ||||||
|  | 	 | ||||||
|  | 	// update header constant buffer
 | ||||||
|  | 	m_queue.enqueueWriteBuffer(m_header, true, 0, 32, header); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	__kernel void ethash_combined_hash( | ||||||
|  | 		__global hash32_t* g_hashes, | ||||||
|  | 		__constant hash32_t const* g_header, | ||||||
|  | 		__global hash128_t const* g_dag, | ||||||
|  | 		ulong start_nonce, | ||||||
|  | 		uint isolate | ||||||
|  | 		) | ||||||
|  | 	*/ | ||||||
|  | 	m_hash_kernel.setArg(1, m_header); | ||||||
|  | 	m_hash_kernel.setArg(2, m_dag); | ||||||
|  | 	m_hash_kernel.setArg(3, nonce); | ||||||
|  | 	m_hash_kernel.setArg(4, ~0u); // have to pass this to stop the compile unrolling the loop
 | ||||||
|  | 
 | ||||||
|  | 	unsigned buf = 0; | ||||||
|  | 	for (unsigned i = 0; i < count || !pending.empty(); ) | ||||||
|  | 	{ | ||||||
|  | 		// how many this batch
 | ||||||
|  | 		if (i < count) | ||||||
|  | 		{ | ||||||
|  | 			unsigned const this_count = std::min(count - i, c_hash_batch_size); | ||||||
|  | 			unsigned const batch_count = std::max(this_count, m_workgroup_size); | ||||||
|  | 
 | ||||||
|  | 			// supply output hash buffer to kernel
 | ||||||
|  | 			m_hash_kernel.setArg(0, m_hash_buf[buf]); | ||||||
|  | 
 | ||||||
|  | 			// execute it!
 | ||||||
|  | 			clock_t start_time = clock(); | ||||||
|  | 			m_queue.enqueueNDRangeKernel( | ||||||
|  | 				m_hash_kernel, | ||||||
|  | 				cl::NullRange, | ||||||
|  | 				cl::NDRange(batch_count), | ||||||
|  | 				cl::NDRange(m_workgroup_size) | ||||||
|  | 				); | ||||||
|  | 			m_queue.flush(); | ||||||
|  | 		 | ||||||
|  | 			pending.push({i, this_count, buf}); | ||||||
|  | 			i += this_count; | ||||||
|  | 			buf = (buf + 1) % c_num_buffers; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// read results
 | ||||||
|  | 		if (i == count || pending.size() == c_num_buffers) | ||||||
|  | 		{ | ||||||
|  | 			pending_batch const& batch = pending.front(); | ||||||
|  | 
 | ||||||
|  | 			// could use pinned host pointer instead, but this path isn't that important.
 | ||||||
|  | 			uint8_t* hashes = (uint8_t*)m_queue.enqueueMapBuffer(m_hash_buf[batch.buf], true, CL_MAP_READ, 0, batch.count * HASH_BYTES); | ||||||
|  | 			memcpy(ret + batch.base*HASH_BYTES, hashes, batch.count*HASH_BYTES); | ||||||
|  | 			m_queue.enqueueUnmapMemObject(m_hash_buf[batch.buf], hashes); | ||||||
|  | 
 | ||||||
|  | 			pending.pop(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void ethash_cl_miner::search(uint8_t const* header, uint64_t target, search_hook& hook) | ||||||
|  | { | ||||||
|  | 	struct pending_batch | ||||||
|  | 	{ | ||||||
|  | 		uint64_t start_nonce; | ||||||
|  | 		unsigned buf; | ||||||
|  | 	}; | ||||||
|  | 	std::queue<pending_batch> pending; | ||||||
|  | 
 | ||||||
|  | 	static uint32_t const c_zero = 0; | ||||||
|  | 
 | ||||||
|  | 	// update header constant buffer
 | ||||||
|  | 	m_queue.enqueueWriteBuffer(m_header, false, 0, 32, header); | ||||||
|  | 	for (unsigned i = 0; i != c_num_buffers; ++i) | ||||||
|  | 	{ | ||||||
|  | 		m_queue.enqueueWriteBuffer(m_search_buf[i], false, 0, 4, &c_zero); | ||||||
|  | 	} | ||||||
|  | 	cl::Event pre_return_event; | ||||||
|  | 	m_queue.enqueueBarrierWithWaitList(NULL, &pre_return_event); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	__kernel void ethash_combined_search( | ||||||
|  | 		__global hash32_t* g_hashes,			// 0
 | ||||||
|  | 		__constant hash32_t const* g_header,	// 1
 | ||||||
|  | 		__global hash128_t const* g_dag,		// 2
 | ||||||
|  | 		ulong start_nonce,						// 3
 | ||||||
|  | 		ulong target,							// 4
 | ||||||
|  | 		uint isolate							// 5
 | ||||||
|  | 	) | ||||||
|  | 	*/ | ||||||
|  | 	m_search_kernel.setArg(1, m_header); | ||||||
|  | 	m_search_kernel.setArg(2, m_dag); | ||||||
|  | 
 | ||||||
|  | 	// pass these to stop the compiler unrolling the loops
 | ||||||
|  | 	m_search_kernel.setArg(4, target); | ||||||
|  | 	m_search_kernel.setArg(5, ~0u); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	unsigned buf = 0; | ||||||
|  | 	for (uint64_t start_nonce = 0; ; start_nonce += c_search_batch_size) | ||||||
|  | 	{ | ||||||
|  | 		// supply output buffer to kernel
 | ||||||
|  | 		m_search_kernel.setArg(0, m_search_buf[buf]); | ||||||
|  | 		m_search_kernel.setArg(3, start_nonce); | ||||||
|  | 
 | ||||||
|  | 		// execute it!
 | ||||||
|  | 		m_queue.enqueueNDRangeKernel(m_search_kernel, cl::NullRange, c_search_batch_size, m_workgroup_size); | ||||||
|  | 		 | ||||||
|  | 		pending.push({start_nonce, buf}); | ||||||
|  | 		buf = (buf + 1) % c_num_buffers; | ||||||
|  | 
 | ||||||
|  | 		// read results
 | ||||||
|  | 		if (pending.size() == c_num_buffers) | ||||||
|  | 		{ | ||||||
|  | 			pending_batch const& batch = pending.front(); | ||||||
|  | 
 | ||||||
|  | 			// could use pinned host pointer instead
 | ||||||
|  | 			uint32_t* results = (uint32_t*)m_queue.enqueueMapBuffer(m_search_buf[batch.buf], true, CL_MAP_READ, 0, (1+c_max_search_results) * sizeof(uint32_t)); | ||||||
|  | 			unsigned num_found = std::min(results[0], c_max_search_results); | ||||||
|  | 
 | ||||||
|  | 			uint64_t nonces[c_max_search_results]; | ||||||
|  | 			for (unsigned i = 0; i != num_found; ++i) | ||||||
|  | 			{ | ||||||
|  | 				nonces[i] = batch.start_nonce + results[i+1]; | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			m_queue.enqueueUnmapMemObject(m_search_buf[batch.buf], results); | ||||||
|  | 			 | ||||||
|  | 			bool exit = num_found && hook.found(nonces, num_found); | ||||||
|  | 			exit |= hook.searched(batch.start_nonce, c_search_batch_size); // always report searched before exit
 | ||||||
|  | 			if (exit) | ||||||
|  | 				break; | ||||||
|  | 
 | ||||||
|  | 			pending.pop(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// not safe to return until this is ready
 | ||||||
|  | 	pre_return_event.wait(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										43
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/ethash_cl_miner.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cl/ethash_cl_miner.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #define __CL_ENABLE_EXCEPTIONS  | ||||||
|  | #define CL_USE_DEPRECATED_OPENCL_2_0_APIS | ||||||
|  | #include "cl.hpp" | ||||||
|  | #include <time.h> | ||||||
|  | #include <libethash/ethash.h> | ||||||
|  | 
 | ||||||
|  | class ethash_cl_miner | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	struct search_hook | ||||||
|  | 	{ | ||||||
|  | 		// reports progress, return true to abort
 | ||||||
|  | 		virtual bool found(uint64_t const* nonces, uint32_t count) = 0; | ||||||
|  | 		virtual bool searched(uint64_t start_nonce, uint32_t count) = 0; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	ethash_cl_miner(); | ||||||
|  | 
 | ||||||
|  | 	bool init(ethash_params const& params, const uint8_t seed[32], unsigned workgroup_size = 64); | ||||||
|  | 
 | ||||||
|  | 	void hash(uint8_t* ret, uint8_t const* header, uint64_t nonce, unsigned count); | ||||||
|  | 	void search(uint8_t const* header, uint64_t target, search_hook& hook); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	static unsigned const c_max_search_results = 63; | ||||||
|  | 	static unsigned const c_num_buffers = 2; | ||||||
|  | 	static unsigned const c_hash_batch_size = 1024; | ||||||
|  | 	static unsigned const c_search_batch_size = 1024*256; | ||||||
|  | 
 | ||||||
|  | 	ethash_params m_params; | ||||||
|  | 	cl::Context m_context; | ||||||
|  | 	cl::CommandQueue m_queue; | ||||||
|  | 	cl::Kernel m_hash_kernel; | ||||||
|  | 	cl::Kernel m_search_kernel; | ||||||
|  | 	cl::Buffer m_dag; | ||||||
|  | 	cl::Buffer m_header; | ||||||
|  | 	cl::Buffer m_hash_buf[c_num_buffers]; | ||||||
|  | 	cl::Buffer m_search_buf[c_num_buffers]; | ||||||
|  | 	unsigned m_workgroup_size; | ||||||
|  | }; | ||||||
							
								
								
									
										15
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | find_package(CUDA) | ||||||
|  |   | ||||||
|  | # Pass options to NVCC | ||||||
|  | 
 | ||||||
|  |   | ||||||
|  | if (CUDA_FOUND) | ||||||
|  | set(CUDA_NVCC_FLAGS "   -gencode;arch=compute_30,code=sm_30; | ||||||
|  |                         -gencode;arch=compute_20,code=sm_20; | ||||||
|  |                         -gencode;arch=compute_11,code=sm_11; | ||||||
|  |                         -gencode;arch=compute_12,code=sm_12; | ||||||
|  |                         -gencode;arch=compute_13,code=sm_13;") | ||||||
|  | cuda_add_executable( | ||||||
|  |     ethash-cuda | ||||||
|  |     libethash.cu) | ||||||
|  | endif() | ||||||
							
								
								
									
										879
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/cuPrintf.cu
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										879
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/cuPrintf.cu
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,879 @@ | |||||||
|  | /* | ||||||
|  | 	Copyright 2009 NVIDIA Corporation.  All rights reserved. | ||||||
|  | 
 | ||||||
|  | 	NOTICE TO LICENSEE:    | ||||||
|  | 
 | ||||||
|  | 	This source code and/or documentation ("Licensed Deliverables") are subject  | ||||||
|  | 	to NVIDIA intellectual property rights under U.S. and international Copyright  | ||||||
|  | 	laws.   | ||||||
|  | 
 | ||||||
|  | 	These Licensed Deliverables contained herein is PROPRIETARY and CONFIDENTIAL  | ||||||
|  | 	to NVIDIA and is being provided under the terms and conditions of a form of  | ||||||
|  | 	NVIDIA software license agreement by and between NVIDIA and Licensee ("License  | ||||||
|  | 	Agreement") or electronically accepted by Licensee.  Notwithstanding any terms  | ||||||
|  | 	or conditions to the contrary in the License Agreement, reproduction or  | ||||||
|  | 	disclosure of the Licensed Deliverables to any third party without the express  | ||||||
|  | 	written consent of NVIDIA is prohibited.      | ||||||
|  | 
 | ||||||
|  | 	NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE LICENSE AGREEMENT,  | ||||||
|  | 	NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THESE LICENSED  | ||||||
|  | 	DELIVERABLES FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED  | ||||||
|  | 	WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE  | ||||||
|  | 	LICENSED DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,  | ||||||
|  | 	NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.   NOTWITHSTANDING ANY  | ||||||
|  | 	TERMS OR CONDITIONS TO THE CONTRARY IN THE LICENSE AGREEMENT, IN NO EVENT SHALL  | ||||||
|  | 	NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,  | ||||||
|  | 	OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,	WHETHER  | ||||||
|  | 	IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF  | ||||||
|  | 	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THESE LICENSED DELIVERABLES.   | ||||||
|  | 
 | ||||||
|  | 	U.S. Government End Users. These Licensed Deliverables are a "commercial item"  | ||||||
|  | 	as that term is defined at  48 C.F.R. 2.101 (OCT 1995), consisting  of  | ||||||
|  | 	"commercial computer  software"  and "commercial computer software documentation"  | ||||||
|  | 	as such terms are  used in 48 C.F.R. 12.212 (SEPT 1995) and is provided to the  | ||||||
|  | 	U.S. Government only as a commercial end item.  Consistent with 48 C.F.R.12.212  | ||||||
|  | 	and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all U.S. Government  | ||||||
|  | 	End Users acquire the Licensed Deliverables with only those rights set forth  | ||||||
|  | 	herein.  | ||||||
|  | 
 | ||||||
|  | 	Any use of the Licensed Deliverables in individual and commercial software must  | ||||||
|  | 	include, in the user documentation and internal comments to the code, the above  | ||||||
|  | 	Disclaimer and U.S. Government End Users Notice. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  *	cuPrintf.cu | ||||||
|  |  * | ||||||
|  |  *	This is a printf command callable from within a kernel. It is set | ||||||
|  |  *	up so that output is sent to a memory buffer, which is emptied from | ||||||
|  |  *	the host side - but only after a cudaThreadSynchronize() on the host. | ||||||
|  |  * | ||||||
|  |  *	Currently, there is a limitation of around 200 characters of output | ||||||
|  |  *	and no more than 10 arguments to a single cuPrintf() call. Issue | ||||||
|  |  *	multiple calls if longer format strings are required. | ||||||
|  |  * | ||||||
|  |  *	It requires minimal setup, and is *NOT* optimised for performance. | ||||||
|  |  *	For example, writes are not coalesced - this is because there is an | ||||||
|  |  *	assumption that people will not want to printf from every single one | ||||||
|  |  *	of thousands of threads, but only from individual threads at a time. | ||||||
|  |  * | ||||||
|  |  *	Using this is simple - it requires one host-side call to initialise | ||||||
|  |  *	everything, and then kernels can call cuPrintf at will. Sample code | ||||||
|  |  *	is the easiest way to demonstrate: | ||||||
|  |  * | ||||||
|  | 	#include "cuPrintf.cu" | ||||||
|  |  	 | ||||||
|  | 	__global__ void testKernel(int val) | ||||||
|  | 	{ | ||||||
|  | 		cuPrintf("Value is: %d\n", val); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int main() | ||||||
|  | 	{ | ||||||
|  | 		cudaPrintfInit(); | ||||||
|  | 		testKernel<<< 2, 3 >>>(10); | ||||||
|  | 		cudaPrintfDisplay(stdout, true); | ||||||
|  | 		cudaPrintfEnd(); | ||||||
|  |         return 0; | ||||||
|  | 	} | ||||||
|  |  * | ||||||
|  |  *	See the header file, "cuPrintf.cuh" for more info, especially | ||||||
|  |  *	arguments to cudaPrintfInit() and cudaPrintfDisplay(); | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef CUPRINTF_CU | ||||||
|  | #define CUPRINTF_CU | ||||||
|  | 
 | ||||||
|  | #include "cuPrintf.cuh" | ||||||
|  | #if __CUDA_ARCH__ > 100      // Atomics only used with > sm_10 architecture | ||||||
|  | #include <sm_11_atomic_functions.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | // This is the smallest amount of memory, per-thread, which is allowed. | ||||||
|  | // It is also the largest amount of space a single printf() can take up | ||||||
|  | const static int CUPRINTF_MAX_LEN = 256; | ||||||
|  | 
 | ||||||
|  | // This structure is used internally to track block/thread output restrictions. | ||||||
|  | typedef struct __align__(8) { | ||||||
|  | 	int threadid;				// CUPRINTF_UNRESTRICTED for unrestricted | ||||||
|  | 	int blockid;				// CUPRINTF_UNRESTRICTED for unrestricted | ||||||
|  | } cuPrintfRestriction; | ||||||
|  | 
 | ||||||
|  | // The main storage is in a global print buffer, which has a known | ||||||
|  | // start/end/length. These are atomically updated so it works as a | ||||||
|  | // circular buffer. | ||||||
|  | // Since the only control primitive that can be used is atomicAdd(), | ||||||
|  | // we cannot wrap the pointer as such. The actual address must be | ||||||
|  | // calculated from printfBufferPtr by mod-ing with printfBufferLength. | ||||||
|  | // For sm_10 architecture, we must subdivide the buffer per-thread | ||||||
|  | // since we do not even have an atomic primitive. | ||||||
|  | __constant__ static char *globalPrintfBuffer = NULL;         // Start of circular buffer (set up by host) | ||||||
|  | __constant__ static int printfBufferLength = 0;              // Size of circular buffer (set up by host) | ||||||
|  | __device__ static cuPrintfRestriction restrictRules;         // Output restrictions | ||||||
|  | __device__ volatile static char *printfBufferPtr = NULL;     // Current atomically-incremented non-wrapped offset | ||||||
|  | 
 | ||||||
|  | // This is the header preceeding all printf entries. | ||||||
|  | // NOTE: It *must* be size-aligned to the maximum entity size (size_t) | ||||||
|  | typedef struct __align__(8) { | ||||||
|  |     unsigned short magic;                   // Magic number says we're valid | ||||||
|  |     unsigned short fmtoffset;               // Offset of fmt string into buffer | ||||||
|  |     unsigned short blockid;                 // Block ID of author | ||||||
|  |     unsigned short threadid;                // Thread ID of author | ||||||
|  | } cuPrintfHeader; | ||||||
|  | 
 | ||||||
|  | // Special header for sm_10 architecture | ||||||
|  | #define CUPRINTF_SM10_MAGIC   0xC810        // Not a valid ascii character | ||||||
|  | typedef struct __align__(16) { | ||||||
|  |     unsigned short magic;                   // sm_10 specific magic number | ||||||
|  |     unsigned short unused; | ||||||
|  |     unsigned int thread_index;              // thread ID for this buffer | ||||||
|  |     unsigned int thread_buf_len;            // per-thread buffer length | ||||||
|  |     unsigned int offset;                    // most recent printf's offset | ||||||
|  | } cuPrintfHeaderSM10; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Because we can't write an element which is not aligned to its bit-size, | ||||||
|  | // we have to align all sizes and variables on maximum-size boundaries. | ||||||
|  | // That means sizeof(double) in this case, but we'll use (long long) for | ||||||
|  | // better arch<1.3 support | ||||||
|  | #define CUPRINTF_ALIGN_SIZE      sizeof(long long) | ||||||
|  | 
 | ||||||
|  | // All our headers are prefixed with a magic number so we know they're ready | ||||||
|  | #define CUPRINTF_SM11_MAGIC  (unsigned short)0xC811        // Not a valid ascii character | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  getNextPrintfBufPtr | ||||||
|  | // | ||||||
|  | //  Grabs a block of space in the general circular buffer, using an | ||||||
|  | //  atomic function to ensure that it's ours. We handle wrapping | ||||||
|  | //  around the circular buffer and return a pointer to a place which | ||||||
|  | //  can be written to. | ||||||
|  | // | ||||||
|  | //  Important notes: | ||||||
|  | //      1. We always grab CUPRINTF_MAX_LEN bytes | ||||||
|  | //      2. Because of 1, we never worry about wrapping around the end | ||||||
|  | //      3. Because of 1, printfBufferLength *must* be a factor of CUPRINTF_MAX_LEN | ||||||
|  | // | ||||||
|  | //  This returns a pointer to the place where we own. | ||||||
|  | // | ||||||
|  | __device__ static char *getNextPrintfBufPtr() | ||||||
|  | { | ||||||
|  |     // Initialisation check | ||||||
|  |     if(!printfBufferPtr) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  | 	// Thread/block restriction check | ||||||
|  | 	if((restrictRules.blockid != CUPRINTF_UNRESTRICTED) && (restrictRules.blockid != (blockIdx.x + gridDim.x*blockIdx.y))) | ||||||
|  | 		return NULL; | ||||||
|  | 	if((restrictRules.threadid != CUPRINTF_UNRESTRICTED) && (restrictRules.threadid != (threadIdx.x + blockDim.x*threadIdx.y + blockDim.x*blockDim.y*threadIdx.z))) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	// Conditional section, dependent on architecture | ||||||
|  | #if __CUDA_ARCH__ == 100 | ||||||
|  |     // For sm_10 architectures, we have no atomic add - this means we must split the | ||||||
|  |     // entire available buffer into per-thread blocks. Inefficient, but what can you do. | ||||||
|  |     int thread_count = (gridDim.x * gridDim.y) * (blockDim.x * blockDim.y * blockDim.z); | ||||||
|  |     int thread_index = threadIdx.x + blockDim.x*threadIdx.y + blockDim.x*blockDim.y*threadIdx.z + | ||||||
|  |                        (blockIdx.x + gridDim.x*blockIdx.y) * (blockDim.x * blockDim.y * blockDim.z); | ||||||
|  |      | ||||||
|  |     // Find our own block of data and go to it. Make sure the per-thread length | ||||||
|  | 	// is a precise multiple of CUPRINTF_MAX_LEN, otherwise we risk size and | ||||||
|  | 	// alignment issues! We must round down, of course. | ||||||
|  |     unsigned int thread_buf_len = printfBufferLength / thread_count; | ||||||
|  | 	thread_buf_len &= ~(CUPRINTF_MAX_LEN-1); | ||||||
|  | 
 | ||||||
|  | 	// We *must* have a thread buffer length able to fit at least two printfs (one header, one real) | ||||||
|  | 	if(thread_buf_len < (CUPRINTF_MAX_LEN * 2)) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	// Now address our section of the buffer. The first item is a header. | ||||||
|  |     char *myPrintfBuffer = globalPrintfBuffer + (thread_buf_len * thread_index); | ||||||
|  |     cuPrintfHeaderSM10 hdr = *(cuPrintfHeaderSM10 *)(void *)myPrintfBuffer; | ||||||
|  |     if(hdr.magic != CUPRINTF_SM10_MAGIC) | ||||||
|  |     { | ||||||
|  |         // If our header is not set up, initialise it | ||||||
|  |         hdr.magic = CUPRINTF_SM10_MAGIC; | ||||||
|  |         hdr.thread_index = thread_index; | ||||||
|  |         hdr.thread_buf_len = thread_buf_len; | ||||||
|  |         hdr.offset = 0;         // Note we start at 0! We pre-increment below. | ||||||
|  |         *(cuPrintfHeaderSM10 *)(void *)myPrintfBuffer = hdr;       // Write back the header | ||||||
|  | 
 | ||||||
|  |         // For initial setup purposes, we might need to init thread0's header too | ||||||
|  |         // (so that cudaPrintfDisplay() below will work). This is only run once. | ||||||
|  |         cuPrintfHeaderSM10 *tophdr = (cuPrintfHeaderSM10 *)(void *)globalPrintfBuffer; | ||||||
|  |         tophdr->thread_buf_len = thread_buf_len; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Adjust the offset by the right amount, and wrap it if need be | ||||||
|  |     unsigned int offset = hdr.offset + CUPRINTF_MAX_LEN; | ||||||
|  |     if(offset >= hdr.thread_buf_len) | ||||||
|  |         offset = CUPRINTF_MAX_LEN; | ||||||
|  | 
 | ||||||
|  |     // Write back the new offset for next time and return a pointer to it | ||||||
|  |     ((cuPrintfHeaderSM10 *)(void *)myPrintfBuffer)->offset = offset; | ||||||
|  |     return myPrintfBuffer + offset; | ||||||
|  | #else | ||||||
|  |     // Much easier with an atomic operation! | ||||||
|  |     size_t offset = atomicAdd((unsigned int *)&printfBufferPtr, CUPRINTF_MAX_LEN) - (size_t)globalPrintfBuffer; | ||||||
|  |     offset %= printfBufferLength; | ||||||
|  |     return globalPrintfBuffer + offset; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  writePrintfHeader | ||||||
|  | // | ||||||
|  | //  Inserts the header for containing our UID, fmt position and | ||||||
|  | //  block/thread number. We generate it dynamically to avoid | ||||||
|  | //	issues arising from requiring pre-initialisation. | ||||||
|  | // | ||||||
|  | __device__ static void writePrintfHeader(char *ptr, char *fmtptr) | ||||||
|  | { | ||||||
|  |     if(ptr) | ||||||
|  |     { | ||||||
|  |         cuPrintfHeader header; | ||||||
|  |         header.magic = CUPRINTF_SM11_MAGIC; | ||||||
|  |         header.fmtoffset = (unsigned short)(fmtptr - ptr); | ||||||
|  |         header.blockid = blockIdx.x + gridDim.x*blockIdx.y; | ||||||
|  |         header.threadid = threadIdx.x + blockDim.x*threadIdx.y + blockDim.x*blockDim.y*threadIdx.z; | ||||||
|  |         *(cuPrintfHeader *)(void *)ptr = header; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  cuPrintfStrncpy | ||||||
|  | // | ||||||
|  | //  This special strncpy outputs an aligned length value, followed by the | ||||||
|  | //  string. It then zero-pads the rest of the string until a 64-aligned | ||||||
|  | //  boundary. The length *includes* the padding. A pointer to the byte | ||||||
|  | //  just after the \0 is returned. | ||||||
|  | // | ||||||
|  | //  This function could overflow CUPRINTF_MAX_LEN characters in our buffer. | ||||||
|  | //  To avoid it, we must count as we output and truncate where necessary. | ||||||
|  | // | ||||||
|  | __device__ static char *cuPrintfStrncpy(char *dest, const char *src, int n, char *end) | ||||||
|  | { | ||||||
|  |     // Initialisation and overflow check | ||||||
|  |     if(!dest || !src || (dest >= end)) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     // Prepare to write the length specifier. We're guaranteed to have | ||||||
|  |     // at least "CUPRINTF_ALIGN_SIZE" bytes left because we only write out in | ||||||
|  |     // chunks that size, and CUPRINTF_MAX_LEN is aligned with CUPRINTF_ALIGN_SIZE. | ||||||
|  |     int *lenptr = (int *)(void *)dest; | ||||||
|  |     int len = 0; | ||||||
|  |     dest += CUPRINTF_ALIGN_SIZE; | ||||||
|  | 
 | ||||||
|  |     // Now copy the string | ||||||
|  |     while(n--) | ||||||
|  |     { | ||||||
|  |         if(dest >= end)     // Overflow check | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         len++; | ||||||
|  |         *dest++ = *src; | ||||||
|  |         if(*src++ == '\0') | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Now write out the padding bytes, and we have our length. | ||||||
|  |     while((dest < end) && (((long)dest & (CUPRINTF_ALIGN_SIZE-1)) != 0)) | ||||||
|  |     { | ||||||
|  |         len++; | ||||||
|  |         *dest++ = 0; | ||||||
|  |     } | ||||||
|  |     *lenptr = len; | ||||||
|  |     return (dest < end) ? dest : NULL;        // Overflow means return NULL | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  copyArg | ||||||
|  | // | ||||||
|  | //  This copies a length specifier and then the argument out to the | ||||||
|  | //  data buffer. Templates let the compiler figure all this out at | ||||||
|  | //  compile-time, making life much simpler from the programming | ||||||
|  | //  point of view. I'm assuimg all (const char *) is a string, and | ||||||
|  | //  everything else is the variable it points at. I'd love to see | ||||||
|  | //  a better way of doing it, but aside from parsing the format | ||||||
|  | //  string I can't think of one. | ||||||
|  | // | ||||||
|  | //  The length of the data type is inserted at the beginning (so that | ||||||
|  | //  the display can distinguish between float and double), and the | ||||||
|  | //  pointer to the end of the entry is returned. | ||||||
|  | // | ||||||
|  | __device__ static char *copyArg(char *ptr, const char *arg, char *end) | ||||||
|  | { | ||||||
|  |     // Initialisation check | ||||||
|  |     if(!ptr || !arg) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     // strncpy does all our work. We just terminate. | ||||||
|  |     if((ptr = cuPrintfStrncpy(ptr, arg, CUPRINTF_MAX_LEN, end)) != NULL) | ||||||
|  |         *ptr = 0; | ||||||
|  | 
 | ||||||
|  |     return ptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | __device__ static char *copyArg(char *ptr, T &arg, char *end) | ||||||
|  | { | ||||||
|  |     // Initisalisation and overflow check. Alignment rules mean that | ||||||
|  |     // we're at least CUPRINTF_ALIGN_SIZE away from "end", so we only need | ||||||
|  |     // to check that one offset. | ||||||
|  |     if(!ptr || ((ptr+CUPRINTF_ALIGN_SIZE) >= end)) | ||||||
|  |         return NULL; | ||||||
|  | 
 | ||||||
|  |     // Write the length and argument | ||||||
|  |     *(int *)(void *)ptr = sizeof(arg); | ||||||
|  |     ptr += CUPRINTF_ALIGN_SIZE; | ||||||
|  |     *(T *)(void *)ptr = arg; | ||||||
|  |     ptr += CUPRINTF_ALIGN_SIZE; | ||||||
|  |     *ptr = 0; | ||||||
|  | 
 | ||||||
|  |     return ptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  cuPrintf | ||||||
|  | // | ||||||
|  | //  Templated printf functions to handle multiple arguments. | ||||||
|  | //  Note we return the total amount of data copied, not the number | ||||||
|  | //  of characters output. But then again, who ever looks at the | ||||||
|  | //  return from printf() anyway? | ||||||
|  | // | ||||||
|  | //  The format is to grab a block of circular buffer space, the | ||||||
|  | //  start of which will hold a header and a pointer to the format | ||||||
|  | //  string. We then write in all the arguments, and finally the | ||||||
|  | //  format string itself. This is to make it easy to prevent | ||||||
|  | //  overflow of our buffer (we support up to 10 arguments, each of | ||||||
|  | //  which can be 12 bytes in length - that means that only the | ||||||
|  | //  format string (or a %s) can actually overflow; so the overflow | ||||||
|  | //  check need only be in the strcpy function. | ||||||
|  | // | ||||||
|  | //  The header is written at the very last because that's what | ||||||
|  | //  makes it look like we're done. | ||||||
|  | // | ||||||
|  | //  Errors, which are basically lack-of-initialisation, are ignored | ||||||
|  | //  in the called functions because NULL pointers are passed around | ||||||
|  | // | ||||||
|  | 
 | ||||||
|  | // All printf variants basically do the same thing, setting up the | ||||||
|  | // buffer, writing all arguments, then finalising the header. For | ||||||
|  | // clarity, we'll pack the code into some big macros. | ||||||
|  | #define CUPRINTF_PREAMBLE \ | ||||||
|  |     char *start, *end, *bufptr, *fmtstart; \ | ||||||
|  |     if((start = getNextPrintfBufPtr()) == NULL) return 0; \ | ||||||
|  |     end = start + CUPRINTF_MAX_LEN; \ | ||||||
|  |     bufptr = start + sizeof(cuPrintfHeader); | ||||||
|  | 
 | ||||||
|  | // Posting an argument is easy | ||||||
|  | #define CUPRINTF_ARG(argname) \ | ||||||
|  | 	bufptr = copyArg(bufptr, argname, end); | ||||||
|  | 
 | ||||||
|  | // After args are done, record start-of-fmt and write the fmt and header | ||||||
|  | #define CUPRINTF_POSTAMBLE \ | ||||||
|  |     fmtstart = bufptr; \ | ||||||
|  |     end = cuPrintfStrncpy(bufptr, fmt, CUPRINTF_MAX_LEN, end); \ | ||||||
|  |     writePrintfHeader(start, end ? fmtstart : NULL); \ | ||||||
|  |     return end ? (int)(end - start) : 0; | ||||||
|  | 
 | ||||||
|  | __device__ int cuPrintf(const char *fmt) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1> __device__ int cuPrintf(const char *fmt, T1 arg1) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 	CUPRINTF_ARG(arg6); | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 	CUPRINTF_ARG(arg6); | ||||||
|  | 	CUPRINTF_ARG(arg7); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 	CUPRINTF_ARG(arg6); | ||||||
|  | 	CUPRINTF_ARG(arg7); | ||||||
|  | 	CUPRINTF_ARG(arg8); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 	CUPRINTF_ARG(arg6); | ||||||
|  | 	CUPRINTF_ARG(arg7); | ||||||
|  | 	CUPRINTF_ARG(arg8); | ||||||
|  | 	CUPRINTF_ARG(arg9); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) | ||||||
|  | { | ||||||
|  | 	CUPRINTF_PREAMBLE; | ||||||
|  | 	     | ||||||
|  | 	CUPRINTF_ARG(arg1); | ||||||
|  | 	CUPRINTF_ARG(arg2); | ||||||
|  | 	CUPRINTF_ARG(arg3); | ||||||
|  | 	CUPRINTF_ARG(arg4); | ||||||
|  | 	CUPRINTF_ARG(arg5); | ||||||
|  | 	CUPRINTF_ARG(arg6); | ||||||
|  | 	CUPRINTF_ARG(arg7); | ||||||
|  | 	CUPRINTF_ARG(arg8); | ||||||
|  | 	CUPRINTF_ARG(arg9); | ||||||
|  | 	CUPRINTF_ARG(arg10); | ||||||
|  | 
 | ||||||
|  | 	CUPRINTF_POSTAMBLE; | ||||||
|  | } | ||||||
|  | #undef CUPRINTF_PREAMBLE | ||||||
|  | #undef CUPRINTF_ARG | ||||||
|  | #undef CUPRINTF_POSTAMBLE | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //	cuPrintfRestrict | ||||||
|  | // | ||||||
|  | //	Called to restrict output to a given thread/block. | ||||||
|  | //	We store the info in "restrictRules", which is set up at | ||||||
|  | //	init time by the host. It's not the cleanest way to do this | ||||||
|  | //	because it means restrictions will last between | ||||||
|  | //	invocations, but given the output-pointer continuity, | ||||||
|  | //	I feel this is reasonable. | ||||||
|  | // | ||||||
|  | __device__ void cuPrintfRestrict(int threadid, int blockid) | ||||||
|  | { | ||||||
|  |     int thread_count = blockDim.x * blockDim.y * blockDim.z; | ||||||
|  | 	if(((threadid < thread_count) && (threadid >= 0)) || (threadid == CUPRINTF_UNRESTRICTED)) | ||||||
|  | 		restrictRules.threadid = threadid; | ||||||
|  | 
 | ||||||
|  | 	int block_count = gridDim.x * gridDim.y; | ||||||
|  | 	if(((blockid < block_count) && (blockid >= 0)) || (blockid == CUPRINTF_UNRESTRICTED)) | ||||||
|  | 		restrictRules.blockid = blockid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // HOST SIDE | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | static FILE *printf_fp; | ||||||
|  | 
 | ||||||
|  | static char *printfbuf_start=NULL; | ||||||
|  | static char *printfbuf_device=NULL; | ||||||
|  | static int printfbuf_len=0; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  outputPrintfData | ||||||
|  | // | ||||||
|  | //  Our own internal function, which takes a pointer to a data buffer | ||||||
|  | //  and passes it through libc's printf for output. | ||||||
|  | // | ||||||
|  | //  We receive the formate string and a pointer to where the data is | ||||||
|  | //  held. We then run through and print it out. | ||||||
|  | // | ||||||
|  | //  Returns 0 on failure, 1 on success | ||||||
|  | // | ||||||
|  | static int outputPrintfData(char *fmt, char *data) | ||||||
|  | { | ||||||
|  |     // Format string is prefixed by a length that we don't need | ||||||
|  |     fmt += CUPRINTF_ALIGN_SIZE; | ||||||
|  | 
 | ||||||
|  |     // Now run through it, printing everything we can. We must | ||||||
|  |     // run to every % character, extract only that, and use printf | ||||||
|  |     // to format it. | ||||||
|  |     char *p = strchr(fmt, '%'); | ||||||
|  |     while(p != NULL) | ||||||
|  |     { | ||||||
|  |         // Print up to the % character | ||||||
|  |         *p = '\0'; | ||||||
|  |         fputs(fmt, printf_fp); | ||||||
|  |         *p = '%';           // Put back the % | ||||||
|  | 
 | ||||||
|  |         // Now handle the format specifier | ||||||
|  |         char *format = p++;         // Points to the '%' | ||||||
|  |         p += strcspn(p, "%cdiouxXeEfgGaAnps"); | ||||||
|  |         if(*p == '\0')              // If no format specifier, print the whole thing | ||||||
|  |         { | ||||||
|  |             fmt = format; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Cut out the format bit and use printf to print it. It's prefixed | ||||||
|  |         // by its length. | ||||||
|  |         int arglen = *(int *)data; | ||||||
|  |         if(arglen > CUPRINTF_MAX_LEN) | ||||||
|  |         { | ||||||
|  |             fputs("Corrupt printf buffer data - aborting\n", printf_fp); | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         data += CUPRINTF_ALIGN_SIZE; | ||||||
|  |          | ||||||
|  |         char specifier = *p++; | ||||||
|  |         char c = *p;        // Store for later | ||||||
|  |         *p = '\0'; | ||||||
|  |         switch(specifier) | ||||||
|  |         { | ||||||
|  |             // These all take integer arguments | ||||||
|  |             case 'c': | ||||||
|  |             case 'd': | ||||||
|  |             case 'i': | ||||||
|  |             case 'o': | ||||||
|  |             case 'u': | ||||||
|  |             case 'x': | ||||||
|  |             case 'X': | ||||||
|  |             case 'p': | ||||||
|  |                 fprintf(printf_fp, format, *((int *)data)); | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             // These all take double arguments | ||||||
|  |             case 'e': | ||||||
|  |             case 'E': | ||||||
|  |             case 'f': | ||||||
|  |             case 'g': | ||||||
|  |             case 'G': | ||||||
|  |             case 'a': | ||||||
|  |             case 'A': | ||||||
|  |                 if(arglen == 4)     // Float vs. Double thing | ||||||
|  |                     fprintf(printf_fp, format, *((float *)data)); | ||||||
|  |                 else | ||||||
|  |                     fprintf(printf_fp, format, *((double *)data)); | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             // Strings are handled in a special way | ||||||
|  |             case 's': | ||||||
|  |                 fprintf(printf_fp, format, (char *)data); | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             // % is special | ||||||
|  |             case '%': | ||||||
|  |                 fprintf(printf_fp, "%%"); | ||||||
|  |                 break; | ||||||
|  | 
 | ||||||
|  |             // Everything else is just printed out as-is | ||||||
|  |             default: | ||||||
|  |                 fprintf(printf_fp, format); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         data += CUPRINTF_ALIGN_SIZE;         // Move on to next argument | ||||||
|  |         *p = c;                     // Restore what we removed | ||||||
|  |         fmt = p;                    // Adjust fmt string to be past the specifier | ||||||
|  |         p = strchr(fmt, '%');       // and get the next specifier | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Print out the last of the string | ||||||
|  |     fputs(fmt, printf_fp); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  doPrintfDisplay | ||||||
|  | // | ||||||
|  | //  This runs through the blocks of CUPRINTF_MAX_LEN-sized data, calling the | ||||||
|  | //  print function above to display them. We've got this separate from | ||||||
|  | //  cudaPrintfDisplay() below so we can handle the SM_10 architecture | ||||||
|  | //  partitioning. | ||||||
|  | // | ||||||
|  | static int doPrintfDisplay(int headings, int clear, char *bufstart, char *bufend, char *bufptr, char *endptr) | ||||||
|  | { | ||||||
|  |     // Grab, piece-by-piece, each output element until we catch | ||||||
|  |     // up with the circular buffer end pointer | ||||||
|  |     int printf_count=0; | ||||||
|  |     char printfbuf_local[CUPRINTF_MAX_LEN+1]; | ||||||
|  |     printfbuf_local[CUPRINTF_MAX_LEN] = '\0'; | ||||||
|  | 
 | ||||||
|  |     while(bufptr != endptr) | ||||||
|  |     { | ||||||
|  |         // Wrap ourselves at the end-of-buffer | ||||||
|  |         if(bufptr == bufend) | ||||||
|  |             bufptr = bufstart; | ||||||
|  | 
 | ||||||
|  |         // Adjust our start pointer to within the circular buffer and copy a block. | ||||||
|  |         cudaMemcpy(printfbuf_local, bufptr, CUPRINTF_MAX_LEN, cudaMemcpyDeviceToHost); | ||||||
|  | 
 | ||||||
|  |         // If the magic number isn't valid, then this write hasn't gone through | ||||||
|  |         // yet and we'll wait until it does (or we're past the end for non-async printfs). | ||||||
|  |         cuPrintfHeader *hdr = (cuPrintfHeader *)printfbuf_local; | ||||||
|  |         if((hdr->magic != CUPRINTF_SM11_MAGIC) || (hdr->fmtoffset >= CUPRINTF_MAX_LEN)) | ||||||
|  |         { | ||||||
|  |             //fprintf(printf_fp, "Bad magic number in printf header\n"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Extract all the info and get this printf done | ||||||
|  |         if(headings) | ||||||
|  |             fprintf(printf_fp, "[%d, %d]: ", hdr->blockid, hdr->threadid); | ||||||
|  |         if(hdr->fmtoffset == 0) | ||||||
|  |             fprintf(printf_fp, "printf buffer overflow\n"); | ||||||
|  |         else if(!outputPrintfData(printfbuf_local+hdr->fmtoffset, printfbuf_local+sizeof(cuPrintfHeader))) | ||||||
|  |             break; | ||||||
|  |         printf_count++; | ||||||
|  | 
 | ||||||
|  |         // Clear if asked | ||||||
|  |         if(clear) | ||||||
|  |             cudaMemset(bufptr, 0, CUPRINTF_MAX_LEN); | ||||||
|  | 
 | ||||||
|  |         // Now advance our start location, because we're done, and keep copying | ||||||
|  |         bufptr += CUPRINTF_MAX_LEN; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return printf_count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  cudaPrintfInit | ||||||
|  | // | ||||||
|  | //  Takes a buffer length to allocate, creates the memory on the device and | ||||||
|  | //  returns a pointer to it for when a kernel is called. It's up to the caller | ||||||
|  | //  to free it. | ||||||
|  | // | ||||||
|  | extern "C" cudaError_t cudaPrintfInit(size_t bufferLen) | ||||||
|  | { | ||||||
|  |     // Fix up bufferlen to be a multiple of CUPRINTF_MAX_LEN | ||||||
|  |     bufferLen = (bufferLen < CUPRINTF_MAX_LEN) ? CUPRINTF_MAX_LEN : bufferLen; | ||||||
|  |     if((bufferLen % CUPRINTF_MAX_LEN) > 0) | ||||||
|  |         bufferLen += (CUPRINTF_MAX_LEN - (bufferLen % CUPRINTF_MAX_LEN)); | ||||||
|  |     printfbuf_len = (int)bufferLen; | ||||||
|  | 
 | ||||||
|  |     // Allocate a print buffer on the device and zero it | ||||||
|  |     if(cudaMalloc((void **)&printfbuf_device, printfbuf_len) != cudaSuccess) | ||||||
|  | 		return cudaErrorInitializationError; | ||||||
|  |     cudaMemset(printfbuf_device, 0, printfbuf_len); | ||||||
|  |     printfbuf_start = printfbuf_device;         // Where we start reading from | ||||||
|  | 
 | ||||||
|  | 	// No restrictions to begin with | ||||||
|  | 	cuPrintfRestriction restrict; | ||||||
|  | 	restrict.threadid = restrict.blockid = CUPRINTF_UNRESTRICTED; | ||||||
|  | 	cudaMemcpyToSymbol(restrictRules, &restrict, sizeof(restrict)); | ||||||
|  | 
 | ||||||
|  |     // Initialise the buffer and the respective lengths/pointers. | ||||||
|  |     cudaMemcpyToSymbol(globalPrintfBuffer, &printfbuf_device, sizeof(char *)); | ||||||
|  |     cudaMemcpyToSymbol(printfBufferPtr, &printfbuf_device, sizeof(char *)); | ||||||
|  |     cudaMemcpyToSymbol(printfBufferLength, &printfbuf_len, sizeof(printfbuf_len)); | ||||||
|  | 
 | ||||||
|  |     return cudaSuccess; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  cudaPrintfEnd | ||||||
|  | // | ||||||
|  | //  Frees up the memory which we allocated | ||||||
|  | // | ||||||
|  | extern "C" void cudaPrintfEnd() | ||||||
|  | { | ||||||
|  |     if(!printfbuf_start || !printfbuf_device) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     cudaFree(printfbuf_device); | ||||||
|  |     printfbuf_start = printfbuf_device = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //  cudaPrintfDisplay | ||||||
|  | // | ||||||
|  | //  Each call to this function dumps the entire current contents | ||||||
|  | //	of the printf buffer to the pre-specified FILE pointer. The | ||||||
|  | //	circular "start" pointer is advanced so that subsequent calls | ||||||
|  | //	dumps only new stuff. | ||||||
|  | // | ||||||
|  | //  In the case of async memory access (via streams), call this | ||||||
|  | //  repeatedly to keep trying to empty the buffer. If it's a sync | ||||||
|  | //  access, then the whole buffer should empty in one go. | ||||||
|  | // | ||||||
|  | //	Arguments: | ||||||
|  | //		outputFP     - File descriptor to output to (NULL => stdout) | ||||||
|  | //		showThreadID - If true, prints [block,thread] before each line | ||||||
|  | // | ||||||
|  | extern "C" cudaError_t cudaPrintfDisplay(void *outputFP, bool showThreadID) | ||||||
|  | { | ||||||
|  | 	printf_fp = (FILE *)((outputFP == NULL) ? stdout : outputFP); | ||||||
|  | 
 | ||||||
|  |     // For now, we force "synchronous" mode which means we're not concurrent | ||||||
|  | 	// with kernel execution. This also means we don't need clearOnPrint. | ||||||
|  | 	// If you're patching it for async operation, here's where you want it. | ||||||
|  |     bool sync_printfs = true; | ||||||
|  | 	bool clearOnPrint = false; | ||||||
|  | 
 | ||||||
|  |     // Initialisation check | ||||||
|  |     if(!printfbuf_start || !printfbuf_device || !printf_fp) | ||||||
|  |         return cudaErrorMissingConfiguration; | ||||||
|  | 
 | ||||||
|  |     // To determine which architecture we're using, we read the | ||||||
|  |     // first short from the buffer - it'll be the magic number | ||||||
|  |     // relating to the version. | ||||||
|  |     unsigned short magic; | ||||||
|  |     cudaMemcpy(&magic, printfbuf_device, sizeof(unsigned short), cudaMemcpyDeviceToHost); | ||||||
|  | 
 | ||||||
|  |     // For SM_10 architecture, we've split our buffer into one-per-thread. | ||||||
|  |     // That means we must do each thread block separately. It'll require | ||||||
|  |     // extra reading. We also, for now, don't support async printfs because | ||||||
|  |     // that requires tracking one start pointer per thread. | ||||||
|  |     if(magic == CUPRINTF_SM10_MAGIC) | ||||||
|  |     { | ||||||
|  |         sync_printfs = true; | ||||||
|  | 	    clearOnPrint = false; | ||||||
|  |         int blocklen = 0; | ||||||
|  |         char *blockptr = printfbuf_device; | ||||||
|  |         while(blockptr < (printfbuf_device + printfbuf_len)) | ||||||
|  |         { | ||||||
|  |             cuPrintfHeaderSM10 hdr; | ||||||
|  |             cudaMemcpy(&hdr, blockptr, sizeof(hdr), cudaMemcpyDeviceToHost); | ||||||
|  | 
 | ||||||
|  |             // We get our block-size-step from the very first header | ||||||
|  |             if(hdr.thread_buf_len != 0) | ||||||
|  |                 blocklen = hdr.thread_buf_len; | ||||||
|  | 
 | ||||||
|  |             // No magic number means no printfs from this thread | ||||||
|  |             if(hdr.magic != CUPRINTF_SM10_MAGIC) | ||||||
|  |             { | ||||||
|  |                 if(blocklen == 0) | ||||||
|  |                 { | ||||||
|  |                     fprintf(printf_fp, "No printf headers found at all!\n"); | ||||||
|  |                     break;                              // No valid headers! | ||||||
|  |                 } | ||||||
|  |                 blockptr += blocklen; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // "offset" is non-zero then we can print the block contents | ||||||
|  |             if(hdr.offset > 0) | ||||||
|  |             { | ||||||
|  |                 // For synchronous printfs, we must print from endptr->bufend, then from start->end | ||||||
|  |                 if(sync_printfs) | ||||||
|  |                     doPrintfDisplay(showThreadID, clearOnPrint, blockptr+CUPRINTF_MAX_LEN, blockptr+hdr.thread_buf_len, blockptr+hdr.offset+CUPRINTF_MAX_LEN, blockptr+hdr.thread_buf_len); | ||||||
|  |                 doPrintfDisplay(showThreadID, clearOnPrint, blockptr+CUPRINTF_MAX_LEN, blockptr+hdr.thread_buf_len, blockptr+CUPRINTF_MAX_LEN, blockptr+hdr.offset+CUPRINTF_MAX_LEN); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Move on to the next block and loop again | ||||||
|  |             blockptr += hdr.thread_buf_len; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     // For SM_11 and up, everything is a single buffer and it's simple | ||||||
|  |     else if(magic == CUPRINTF_SM11_MAGIC) | ||||||
|  |     { | ||||||
|  | 	    // Grab the current "end of circular buffer" pointer. | ||||||
|  |         char *printfbuf_end = NULL; | ||||||
|  |         cudaMemcpyFromSymbol(&printfbuf_end, printfBufferPtr, sizeof(char *)); | ||||||
|  | 
 | ||||||
|  |         // Adjust our starting and ending pointers to within the block | ||||||
|  |         char *bufptr = ((printfbuf_start - printfbuf_device) % printfbuf_len) + printfbuf_device; | ||||||
|  |         char *endptr = ((printfbuf_end - printfbuf_device) % printfbuf_len) + printfbuf_device; | ||||||
|  | 
 | ||||||
|  |         // For synchronous (i.e. after-kernel-exit) printf display, we have to handle circular | ||||||
|  |         // buffer wrap carefully because we could miss those past "end". | ||||||
|  |         if(sync_printfs) | ||||||
|  |             doPrintfDisplay(showThreadID, clearOnPrint, printfbuf_device, printfbuf_device+printfbuf_len, endptr, printfbuf_device+printfbuf_len); | ||||||
|  |         doPrintfDisplay(showThreadID, clearOnPrint, printfbuf_device, printfbuf_device+printfbuf_len, bufptr, endptr); | ||||||
|  | 
 | ||||||
|  |         printfbuf_start = printfbuf_end; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |         ;//printf("Bad magic number in cuPrintf buffer header\n"); | ||||||
|  | 
 | ||||||
|  |     // If we were synchronous, then we must ensure that the memory is cleared on exit | ||||||
|  |     // otherwise another kernel launch with a different grid size could conflict. | ||||||
|  |     if(sync_printfs) | ||||||
|  |         cudaMemset(printfbuf_device, 0, printfbuf_len); | ||||||
|  | 
 | ||||||
|  |     return cudaSuccess; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Cleanup | ||||||
|  | #undef CUPRINTF_MAX_LEN | ||||||
|  | #undef CUPRINTF_ALIGN_SIZE | ||||||
|  | #undef CUPRINTF_SM10_MAGIC | ||||||
|  | #undef CUPRINTF_SM11_MAGIC | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										162
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/cuPrintf.cuh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/cuPrintf.cuh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | |||||||
|  | /* | ||||||
|  | 	Copyright 2009 NVIDIA Corporation.  All rights reserved. | ||||||
|  | 
 | ||||||
|  | 	NOTICE TO LICENSEE:    | ||||||
|  | 
 | ||||||
|  | 	This source code and/or documentation ("Licensed Deliverables") are subject  | ||||||
|  | 	to NVIDIA intellectual property rights under U.S. and international Copyright  | ||||||
|  | 	laws.   | ||||||
|  | 
 | ||||||
|  | 	These Licensed Deliverables contained herein is PROPRIETARY and CONFIDENTIAL  | ||||||
|  | 	to NVIDIA and is being provided under the terms and conditions of a form of  | ||||||
|  | 	NVIDIA software license agreement by and between NVIDIA and Licensee ("License  | ||||||
|  | 	Agreement") or electronically accepted by Licensee.  Notwithstanding any terms  | ||||||
|  | 	or conditions to the contrary in the License Agreement, reproduction or  | ||||||
|  | 	disclosure of the Licensed Deliverables to any third party without the express  | ||||||
|  | 	written consent of NVIDIA is prohibited.      | ||||||
|  | 
 | ||||||
|  | 	NOTWITHSTANDING ANY TERMS OR CONDITIONS TO THE CONTRARY IN THE LICENSE AGREEMENT,  | ||||||
|  | 	NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THESE LICENSED  | ||||||
|  | 	DELIVERABLES FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED  | ||||||
|  | 	WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THESE  | ||||||
|  | 	LICENSED DELIVERABLES, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY,  | ||||||
|  | 	NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.   NOTWITHSTANDING ANY  | ||||||
|  | 	TERMS OR CONDITIONS TO THE CONTRARY IN THE LICENSE AGREEMENT, IN NO EVENT SHALL  | ||||||
|  | 	NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,  | ||||||
|  | 	OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,	WHETHER  | ||||||
|  | 	IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF  | ||||||
|  | 	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THESE LICENSED DELIVERABLES.   | ||||||
|  | 
 | ||||||
|  | 	U.S. Government End Users. These Licensed Deliverables are a "commercial item"  | ||||||
|  | 	as that term is defined at  48 C.F.R. 2.101 (OCT 1995), consisting  of  | ||||||
|  | 	"commercial computer  software"  and "commercial computer software documentation"  | ||||||
|  | 	as such terms are  used in 48 C.F.R. 12.212 (SEPT 1995) and is provided to the  | ||||||
|  | 	U.S. Government only as a commercial end item.  Consistent with 48 C.F.R.12.212  | ||||||
|  | 	and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), all U.S. Government  | ||||||
|  | 	End Users acquire the Licensed Deliverables with only those rights set forth  | ||||||
|  | 	herein.  | ||||||
|  | 
 | ||||||
|  | 	Any use of the Licensed Deliverables in individual and commercial software must  | ||||||
|  | 	include, in the user documentation and internal comments to the code, the above  | ||||||
|  | 	Disclaimer and U.S. Government End Users Notice. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef CUPRINTF_H | ||||||
|  | #define CUPRINTF_H | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  *	This is the header file supporting cuPrintf.cu and defining both | ||||||
|  |  *	the host and device-side interfaces. See that file for some more | ||||||
|  |  *	explanation and sample use code. See also below for details of the | ||||||
|  |  *	host-side interfaces. | ||||||
|  |  * | ||||||
|  |  *  Quick sample code: | ||||||
|  |  * | ||||||
|  | 	#include "cuPrintf.cu" | ||||||
|  |  	 | ||||||
|  | 	__global__ void testKernel(int val) | ||||||
|  | 	{ | ||||||
|  | 		cuPrintf("Value is: %d\n", val); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	int main() | ||||||
|  | 	{ | ||||||
|  | 		cudaPrintfInit(); | ||||||
|  | 		testKernel<<< 2, 3 >>>(10); | ||||||
|  | 		cudaPrintfDisplay(stdout, true); | ||||||
|  | 		cudaPrintfEnd(); | ||||||
|  |         return 0; | ||||||
|  | 	} | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // DEVICE SIDE | ||||||
|  | // External function definitions for device-side code | ||||||
|  | 
 | ||||||
|  | // Abuse of templates to simulate varargs | ||||||
|  | __device__ int cuPrintf(const char *fmt); | ||||||
|  | template <typename T1> __device__ int cuPrintf(const char *fmt, T1 arg1); | ||||||
|  | template <typename T1, typename T2> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2); | ||||||
|  | template <typename T1, typename T2, typename T3> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); | ||||||
|  | template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> __device__ int cuPrintf(const char *fmt, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //	cuPrintfRestrict | ||||||
|  | // | ||||||
|  | //	Called to restrict output to a given thread/block. Pass | ||||||
|  | //	the constant CUPRINTF_UNRESTRICTED to unrestrict output | ||||||
|  | //	for thread/block IDs. Note you can therefore allow | ||||||
|  | //	"all printfs from block 3" or "printfs from thread 2 | ||||||
|  | //	on all blocks", or "printfs only from block 1, thread 5". | ||||||
|  | // | ||||||
|  | //	Arguments: | ||||||
|  | //		threadid - Thread ID to allow printfs from | ||||||
|  | //		blockid - Block ID to allow printfs from | ||||||
|  | // | ||||||
|  | //	NOTE: Restrictions last between invocations of | ||||||
|  | //	kernels unless cudaPrintfInit() is called again. | ||||||
|  | // | ||||||
|  | #define CUPRINTF_UNRESTRICTED	-1 | ||||||
|  | __device__ void cuPrintfRestrict(int threadid, int blockid); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // HOST SIDE | ||||||
|  | // External function definitions for host-side code | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //	cudaPrintfInit | ||||||
|  | // | ||||||
|  | //	Call this once to initialise the printf system. If the output | ||||||
|  | //	file or buffer size needs to be changed, call cudaPrintfEnd() | ||||||
|  | //	before re-calling cudaPrintfInit(). | ||||||
|  | // | ||||||
|  | //	The default size for the buffer is 1 megabyte. For CUDA | ||||||
|  | //	architecture 1.1 and above, the buffer is filled linearly and | ||||||
|  | //	is completely used;	however for architecture 1.0, the buffer | ||||||
|  | //	is divided into as many segments are there are threads, even | ||||||
|  | //	if some threads do not call cuPrintf(). | ||||||
|  | // | ||||||
|  | //	Arguments: | ||||||
|  | //		bufferLen - Length, in bytes, of total space to reserve | ||||||
|  | //		            (in device global memory) for output. | ||||||
|  | // | ||||||
|  | //	Returns: | ||||||
|  | //		cudaSuccess if all is well. | ||||||
|  | // | ||||||
|  | extern "C" cudaError_t cudaPrintfInit(size_t bufferLen=1048576);   // 1-meg - that's enough for 4096 printfs by all threads put together | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //	cudaPrintfEnd | ||||||
|  | // | ||||||
|  | //	Cleans up all memories allocated by cudaPrintfInit(). | ||||||
|  | //	Call this at exit, or before calling cudaPrintfInit() again. | ||||||
|  | // | ||||||
|  | extern "C" void cudaPrintfEnd(); | ||||||
|  | 
 | ||||||
|  | // | ||||||
|  | //	cudaPrintfDisplay | ||||||
|  | // | ||||||
|  | //	Dumps the contents of the output buffer to the specified | ||||||
|  | //	file pointer. If the output pointer is not specified, | ||||||
|  | //	the default "stdout" is used. | ||||||
|  | // | ||||||
|  | //	Arguments: | ||||||
|  | //		outputFP     - A file pointer to an output stream. | ||||||
|  | //		showThreadID - If "true", output strings are prefixed | ||||||
|  | //		               by "[blockid, threadid] " at output. | ||||||
|  | // | ||||||
|  | //	Returns: | ||||||
|  | //		cudaSuccess if all is well. | ||||||
|  | // | ||||||
|  | extern "C" cudaError_t cudaPrintfDisplay(void *outputFP=NULL, bool showThreadID=false); | ||||||
|  | 
 | ||||||
|  | #endif  // CUPRINTF_H | ||||||
							
								
								
									
										27
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/libethash.cu
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash-cuda/libethash.cu
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | #include "cuPrintf.cu" | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | __global__ void device_greetings(void) | ||||||
|  | { | ||||||
|  | 	cuPrintf("Hello, world from the device!\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  | 	// greet from the host | ||||||
|  | 	printf("Hello, world from the host!\n"); | ||||||
|  | 
 | ||||||
|  | 	// initialize cuPrintf | ||||||
|  | 	cudaPrintfInit(); | ||||||
|  | 
 | ||||||
|  | 	// launch a kernel with a single thread to greet from the device | ||||||
|  | 	device_greetings<<<1,1>>>(); | ||||||
|  | 
 | ||||||
|  | 	// display the device's greeting | ||||||
|  | 	cudaPrintfDisplay(); | ||||||
|  | 
 | ||||||
|  | 	// clean up after cuPrintf | ||||||
|  | 	cudaPrintfEnd(); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | set(LIBRARY ethash) | ||||||
|  | set(CMAKE_BUILD_TYPE Release) | ||||||
|  | 
 | ||||||
|  | if (NOT MSVC) | ||||||
|  | 	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | set(FILES 	util.c | ||||||
|  |           	util.h | ||||||
|  |           	internal.c | ||||||
|  |           	ethash.h | ||||||
|  |           	endian.h | ||||||
|  |           	compiler.h | ||||||
|  |           	fnv.h | ||||||
|  |           	data_sizes.h) | ||||||
|  | 
 | ||||||
|  | if (NOT CRYPTOPP_FOUND) | ||||||
|  | 	find_package(CryptoPP 5.6.2) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (CRYPTOPP_FOUND) | ||||||
|  | 	add_definitions(-DWITH_CRYPTOPP) | ||||||
|  | 	include_directories( ${CRYPTOPP_INCLUDE_DIRS} ) | ||||||
|  | 	list(APPEND FILES sha3_cryptopp.cpp sha3_cryptopp.h) | ||||||
|  | else() | ||||||
|  | 	list(APPEND FILES sha3.c sha3.h) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | add_library(${LIBRARY} ${FILES}) | ||||||
|  | 
 | ||||||
|  | if (CRYPTOPP_FOUND) | ||||||
|  | 	TARGET_LINK_LIBRARIES(${LIBRARY} ${CRYPTOPP_LIBRARIES}) | ||||||
|  | endif() | ||||||
							
								
								
									
										33
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/compiler.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/compiler.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file compiler.h
 | ||||||
|  |  * @date 2014 | ||||||
|  |  */ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | // Visual Studio doesn't support the inline keyword in C mode
 | ||||||
|  | #if defined(_MSC_VER) && !defined(__cplusplus) | ||||||
|  | #define inline __inline | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | // pretend restrict is a standard keyword
 | ||||||
|  | #if defined(_MSC_VER) | ||||||
|  | #define restrict __restrict | ||||||
|  | #else | ||||||
|  | #define restrict __restrict__ | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
							
								
								
									
										248
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/data_sizes.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/data_sizes.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,248 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software FoundationUUU,either version 3 of the LicenseUUU,or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be usefulU, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If notUUU,see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /** @file nth_prime.h
 | ||||||
|  | * @author Matthew Wampler-Doty <negacthulhu@gmail.com> | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | // TODO: Update this after ~7 years
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | //#include <Security/Security.h>
 | ||||||
|  | #include "compiler.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | // 500 Epochs worth of tabulated DAG sizes (~3.5 Years)
 | ||||||
|  | 
 | ||||||
|  | // Generated with the following Mathematica Code:
 | ||||||
|  | // GetDataSizes[n_] := Module[{
 | ||||||
|  | //        DAGSizeBytesInit = 2^30,
 | ||||||
|  | //        MixBytes = 128,
 | ||||||
|  | //        DAGGrowth = 113000000,
 | ||||||
|  | //        j = 0},
 | ||||||
|  | //        Reap[
 | ||||||
|  | //          While[j < n,
 | ||||||
|  | //            Module[{i =
 | ||||||
|  | //              Floor[(DAGSizeBytesInit + DAGGrowth * j) / MixBytes]},
 | ||||||
|  | //              While[! PrimeQ[i], i--];
 | ||||||
|  | //              Sow[i*MixBytes]; j++]]]][[2]][[1]]
 | ||||||
|  | 
 | ||||||
|  | static const size_t dag_sizes[] = { | ||||||
|  |         1073739904U, 1186739584U, 1299741568U, 1412741248U, 1525741696U, | ||||||
|  |         1638736768U, 1751741312U, 1864740736U, 1977740672U, 2090740864U, | ||||||
|  |         2203740544U, 2316741248U, 2429739392U, 2542740352U, 2655741824U, | ||||||
|  |         2768739712U, 2881740416U, 2994741632U, 3107740544U, 3220741504U, | ||||||
|  |         3333738112U, 3446741632U, 3559741312U, 3672740224U, 3785740928U, | ||||||
|  |         3898738304U, 4011741824U, 4124739712U, 4237735808U, 4350740864U, | ||||||
|  |         4463741824U, 4576741504U, 4689741184U, 4802739328U, 4915741568U, | ||||||
|  |         5028740224U, 5141740672U, 5254738304U, 5367741824U, 5480737664U, | ||||||
|  |         5593738112U, 5706741632U, 5819740544U, 5932734592U, 6045739904U, | ||||||
|  |         6158740096U, 6271740032U, 6384731776U, 6497732992U, 6610740352U, | ||||||
|  |         6723741056U, 6836741504U, 6949740416U, 7062740096U, 7175741824U, | ||||||
|  |         7288740224U, 7401741184U, 7514741632U, 7627741568U, 7740739712U, | ||||||
|  |         7853739136U, 7966740352U, 8079741568U, 8192739712U, 8305738624U, | ||||||
|  |         8418740864U, 8531740288U, 8644740736U, 8757735808U, 8870738816U, | ||||||
|  |         8983739264U, 9096740992U, 9209740928U, 9322739584U, 9435741824U, | ||||||
|  |         9548741504U, 9661739392U, 9774738304U, 9887741312U, 10000738688U, | ||||||
|  |         10113739136U, 10226741632U, 10339739776U, 10452741248U, 10565740928U, | ||||||
|  |         10678736512U, 10791734656U, 10904741248U, 11017738112U, 11130741632U, | ||||||
|  |         11243741312U, 11356739456U, 11469740416U, 11582734976U, 11695739008U, | ||||||
|  |         11808741248U, 11921734784U, 12034739072U, 12147741568U, 12260737408U, | ||||||
|  |         12373741696U, 12486738304U, 12599740544U, 12712740224U, 12825741184U, | ||||||
|  |         12938736256U, 13051741312U, 13164737408U, 13277738368U, 13390738048U, | ||||||
|  |         13503741824U, 13616741504U, 13729737088U, 13842740096U, 13955741312U, | ||||||
|  |         14068741504U, 14181740416U, 14294741632U, 14407739776U, 14520740224U, | ||||||
|  |         14633740928U, 14746736512U, 14859741824U, 14972740736U, 15085740928U, | ||||||
|  |         15198738304U, 15311732096U, 15424740736U, 15537739904U, 15650741632U, | ||||||
|  |         15763741568U, 15876737152U, 15989741696U, 16102740608U, 16215741056U, | ||||||
|  |         16328741248U, 16441740416U, 16554737792U, 16667740288U, 16780740992U, | ||||||
|  |         16893738112U, 17006741632U, 17119739008U, 17232735616U, 17345739392U, | ||||||
|  |         17458740352U, 17571736192U, 17684739712U, 17797739392U, 17910740096U, | ||||||
|  |         18023741312U, 18136740736U, 18249738112U, 18362738816U, 18475735424U, | ||||||
|  |         18588740224U, 18701738368U, 18814736768U, 18927737216U, 19040739968U, | ||||||
|  |         19153739648U, 19266736768U, 19379737984U, 19492739456U, 19605738368U, | ||||||
|  |         19718740352U, 19831741312U, 19944736384U, 20057741696U, 20170741376U, | ||||||
|  |         20283741824U, 20396737408U, 20509741696U, 20622741376U, 20735739008U, | ||||||
|  |         20848741504U, 20961740672U, 21074739328U, 21187740032U, 21300739456U, | ||||||
|  |         21413741696U, 21526740608U, 21639741824U, 21752737408U, 21865741696U, | ||||||
|  |         21978741376U, 22091741824U, 22204738432U, 22317740672U, 22430740096U, | ||||||
|  |         22543736704U, 22656741248U, 22769739904U, 22882739584U, 22995740288U, | ||||||
|  |         23108740736U, 23221740928U, 23334741376U, 23447737216U, 23560740992U, | ||||||
|  |         23673741184U, 23786740864U, 23899737728U, 24012741248U, 24125734784U, | ||||||
|  |         24238736512U, 24351741824U, 24464740736U, 24577737088U, 24690741632U, | ||||||
|  |         24803739776U, 24916740736U, 25029740416U, 25142740864U, 25255741568U, | ||||||
|  |         25368741248U, 25481740672U, 25594741376U, 25707741568U, 25820741504U, | ||||||
|  |         25933730432U, 26046739072U, 26159741824U, 26272741504U, 26385740672U, | ||||||
|  |         26498740096U, 26611741568U, 26724740992U, 26837739904U, 26950735232U, | ||||||
|  |         27063738496U, 27176741248U, 27289741184U, 27402740864U, 27515740544U, | ||||||
|  |         27628737152U, 27741740672U, 27854741632U, 27967740544U, 28080739712U, | ||||||
|  |         28193738368U, 28306741376U, 28419737728U, 28532739968U, 28645739648U, | ||||||
|  |         28758740096U, 28871741312U, 28984739456U, 29097740416U, 29210740864U, | ||||||
|  |         29323741312U, 29436740224U, 29549741696U, 29662738304U, 29775741568U, | ||||||
|  |         29888741504U, 30001740928U, 30114737024U, 30227735168U, 30340737664U, | ||||||
|  |         30453738368U, 30566737024U, 30679733632U, 30792740224U, 30905740928U, | ||||||
|  |         31018740352U, 31131740032U, 31244738944U, 31357737344U, 31470741376U, | ||||||
|  |         31583740544U, 31696740224U, 31809738112U, 31922739328U, 32035737472U, | ||||||
|  |         32148740992U, 32261741696U, 32374740352U, 32487741824U, 32600740736U, | ||||||
|  |         32713739648U, 32826740608U, 32939729792U, 33052740992U, 33165740672U, | ||||||
|  |         33278739584U, 33391741312U, 33504739712U, 33617740928U, 33730740608U, | ||||||
|  |         33843738496U, 33956739968U, 34069741696U, 34182739328U, 34295741824U, | ||||||
|  |         34408739968U, 34521740672U, 34634736512U, 34747741568U, 34860741248U, | ||||||
|  |         34973739392U, 35086738304U, 35199741056U, 35312736896U, 35425741184U, | ||||||
|  |         35538741376U, 35651740288U, 35764737152U, 35877741184U, 35990739584U, | ||||||
|  |         36103740544U, 36216740992U, 36329739392U, 36442737536U, 36555741568U, | ||||||
|  |         36668740736U, 36781741184U, 36894737024U, 37007741312U, 37120739456U, | ||||||
|  |         37233741184U, 37346736256U, 37459736192U, 37572734336U, 37685739904U, | ||||||
|  |         37798740352U, 37911737728U, 38024741504U, 38137739648U, 38250740608U, | ||||||
|  |         38363741824U, 38476740992U, 38589741184U, 38702740096U, 38815741312U, | ||||||
|  |         38928741248U, 39041738368U, 39154739584U, 39267741824U, 39380739712U, | ||||||
|  |         39493735808U, 39606741632U, 39719741312U, 39832741504U, 39945739648U, | ||||||
|  |         40058740352U, 40171740032U, 40284740992U, 40397740672U, 40510740352U, | ||||||
|  |         40623740288U, 40736738176U, 40849737856U, 40962741376U, 41075739776U, | ||||||
|  |         41188737664U, 41301735808U, 41414738048U, 41527741312U, 41640740992U, | ||||||
|  |         41753739904U, 41866739072U, 41979738496U, 42092740736U, 42205739648U, | ||||||
|  |         42318740608U, 42431741312U, 42544738688U, 42657741184U, 42770738048U, | ||||||
|  |         42883741568U, 42996741248U, 43109740928U, 43222736512U, 43335741056U, | ||||||
|  |         43448730496U, 43561740416U, 43674741632U, 43787740544U, 43900741504U, | ||||||
|  |         44013739648U, 44126740864U, 44239740544U, 44352741248U, 44465738368U, | ||||||
|  |         44578735232U, 44691739264U, 44804741504U, 44917741696U, 45030741376U, | ||||||
|  |         45143741824U, 45256740992U, 45369739136U, 45482740096U, 45595739776U, | ||||||
|  |         45708739712U, 45821740672U, 45934741376U, 46047741056U, 46160741248U, | ||||||
|  |         46273737088U, 46386740864U, 46499739008U, 46612739968U, 46725735296U, | ||||||
|  |         46838740864U, 46951741568U, 47064737152U, 47177741696U, 47290741376U, | ||||||
|  |         47403738752U, 47516741248U, 47629739648U, 47742741632U, 47855737984U, | ||||||
|  |         47968740224U, 48081738368U, 48194741632U, 48307739264U, 48420739712U, | ||||||
|  |         48533739136U, 48646738304U, 48759741824U, 48872741504U, 48985739392U, | ||||||
|  |         49098741376U, 49211741056U, 49324740992U, 49437738368U, 49550740864U, | ||||||
|  |         49663735424U, 49776737408U, 49889740672U, 50002738816U, 50115738752U, | ||||||
|  |         50228739712U, 50341741696U, 50454736768U, 50567738752U, 50680739968U, | ||||||
|  |         50793736832U, 50906734976U, 51019741568U, 51132739456U, 51245741696U, | ||||||
|  |         51358741376U, 51471741056U, 51584738944U, 51697734272U, 51810739072U, | ||||||
|  |         51923736448U, 52036740736U, 52149741184U, 52262737024U, 52375738496U, | ||||||
|  |         52488740992U, 52601739136U, 52714740352U, 52827736448U, 52940738176U, | ||||||
|  |         53053741696U, 53166740864U, 53279741824U, 53392741504U, 53505739136U, | ||||||
|  |         53618739584U, 53731741312U, 53844741248U, 53957741696U, 54070741376U, | ||||||
|  |         54183740288U, 54296741504U, 54409741696U, 54522739072U, 54635737472U, | ||||||
|  |         54748741504U, 54861736064U, 54974740096U, 55087741568U, 55200733568U, | ||||||
|  |         55313741696U, 55426734464U, 55539741056U, 55652741504U, 55765741184U, | ||||||
|  |         55878741376U, 55991730304U, 56104740992U, 56217740672U, 56330731648U, | ||||||
|  |         56443737472U, 56556724352U, 56669740672U, 56782739072U, 56895740032U, | ||||||
|  |         57008741248U, 57121741696U, 57234740096U, 57347741312U, 57460741504U | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 500 Epochs worth of tabulated DAG sizes (~3.5 Years)
 | ||||||
|  | 
 | ||||||
|  | // Generated with the following Mathematica Code:
 | ||||||
|  | // GetCacheSizes[n_] := Module[{
 | ||||||
|  | //        DAGSizeBytesInit = 2^30,
 | ||||||
|  | //        MixBytes = 128,
 | ||||||
|  | //        DAGGrowth = 113000000,
 | ||||||
|  | //        HashBytes = 64,
 | ||||||
|  | //        DAGParents = 1024,
 | ||||||
|  | //        j = 0},
 | ||||||
|  | //    Reap[
 | ||||||
|  | //      While[j < n,
 | ||||||
|  | //       Module[{i = Floor[(DAGSizeBytesInit + DAGGrowth * j) / (DAGParents * HashBytes)]},
 | ||||||
|  | //        While[! PrimeQ[i], i--];
 | ||||||
|  | //        Sow[i*HashBytes]; j++]]]][[2]][[1]]
 | ||||||
|  | 
 | ||||||
|  | const size_t cache_sizes[] = { | ||||||
|  |         1048384U, 1158208U, 1268416U, 1377856U, 1489856U, 1599296U, 1710656U, | ||||||
|  |         1820608U, 1930816U, 2041024U, 2151872U, 2261696U, 2371904U, 2482624U, | ||||||
|  |         2593216U, 2703296U, 2814016U, 2924224U, 3034816U, 3144896U, 3255488U, | ||||||
|  |         3365312U, 3475904U, 3586624U, 3696064U, 3806272U, 3917504U, 4027456U, | ||||||
|  |         4138304U, 4248512U, 4359104U, 4469312U, 4579264U, 4689728U, 4797376U, | ||||||
|  |         4909888U, 5020096U, 5131328U, 5241664U, 5351744U, 5461312U, 5572544U, | ||||||
|  |         5683264U, 5793472U, 5903552U, 6014144U, 6121664U, 6235072U, 6344896U, | ||||||
|  |         6454592U, 6565952U, 6675904U, 6786112U, 6896704U, 7006784U, 7117888U, | ||||||
|  |         7228096U, 7338304U, 7448768U, 7557952U, 7669184U, 7779776U, 7889216U, | ||||||
|  |         8000192U, 8110912U, 8220736U, 8331712U, 8441536U, 8552384U, 8662592U, | ||||||
|  |         8772928U, 8883136U, 8993728U, 9103168U, 9214528U, 9323968U, 9434816U, | ||||||
|  |         9545152U, 9655616U, 9766336U, 9876544U, 9986624U, 10097344U, 10207424U, | ||||||
|  |         10316864U, 10427968U, 10538432U, 10649152U, 10758976U, 10869568U, 10979776U, | ||||||
|  |         11089472U, 11200832U, 11309632U, 11420608U, 11531584U, 11641792U, 11751104U, | ||||||
|  |         11862976U, 11973184U, 12083264U, 12193856U, 12304064U, 12414656U, 12524608U, | ||||||
|  |         12635072U, 12745792U, 12855616U, 12965824U, 13076416U, 13187008U, 13297216U, | ||||||
|  |         13407808U, 13518016U, 13627072U, 13738688U, 13848256U, 13959488U, 14069696U, | ||||||
|  |         14180288U, 14290624U, 14399552U, 14511424U, 14621504U, 14732096U, 14841664U, | ||||||
|  |         14951744U, 15062336U, 15172672U, 15283264U, 15393088U, 15504448U, 15614272U, | ||||||
|  |         15723712U, 15834944U, 15945152U, 16055744U, 16165696U, 16277056U, 16387136U, | ||||||
|  |         16494784U, 16607936U, 16718272U, 16828736U, 16938176U, 17048384U, 17159872U, | ||||||
|  |         17266624U, 17380544U, 17490496U, 17600192U, 17711296U, 17821376U, 17931968U, | ||||||
|  |         18041152U, 18152896U, 18261952U, 18373568U, 18483392U, 18594112U, 18703936U, | ||||||
|  |         18814912U, 18924992U, 19034944U, 19145408U, 19256128U, 19366208U, 19477184U, | ||||||
|  |         19587136U, 19696576U, 19808192U, 19916992U, 20028352U, 20137664U, 20249024U, | ||||||
|  |         20358848U, 20470336U, 20580544U, 20689472U, 20801344U, 20911424U, 21020096U, | ||||||
|  |         21130688U, 21242176U, 21352384U, 21462208U, 21573824U, 21683392U, 21794624U, | ||||||
|  |         21904448U, 22013632U, 22125248U, 22235968U, 22344512U, 22456768U, 22566848U, | ||||||
|  |         22677056U, 22786496U, 22897984U, 23008064U, 23118272U, 23228992U, 23338816U, | ||||||
|  |         23449408U, 23560256U, 23670464U, 23780672U, 23891264U, 24001216U, 24110656U, | ||||||
|  |         24221888U, 24332608U, 24442688U, 24552512U, 24662464U, 24773696U, 24884032U, | ||||||
|  |         24994496U, 25105216U, 25215296U, 25324864U, 25435712U, 25546432U, 25655744U, | ||||||
|  |         25767232U, 25876672U, 25986368U, 26098112U, 26207936U, 26318912U, 26428736U, | ||||||
|  |         26539712U, 26650048U, 26760256U, 26869184U, 26979776U, 27091136U, 27201728U, | ||||||
|  |         27311552U, 27422272U, 27532352U, 27642304U, 27752896U, 27863744U, 27973952U, | ||||||
|  |         28082752U, 28194752U, 28305344U, 28415168U, 28524992U, 28636352U, 28746304U, | ||||||
|  |         28857152U, 28967104U, 29077184U, 29187904U, 29298496U, 29408576U, 29518912U, | ||||||
|  |         29628992U, 29739968U, 29850176U, 29960512U, 30070336U, 30180544U, 30290752U, | ||||||
|  |         30398912U, 30512192U, 30622784U, 30732992U, 30842176U, 30953536U, 31063744U, | ||||||
|  |         31174336U, 31284544U, 31395136U, 31504448U, 31615552U, 31725632U, 31835072U, | ||||||
|  |         31946176U, 32057024U, 32167232U, 32277568U, 32387008U, 32497984U, 32608832U, | ||||||
|  |         32719168U, 32829376U, 32939584U, 33050048U, 33160768U, 33271232U, 33381184U, | ||||||
|  |         33491648U, 33601856U, 33712576U, 33822016U, 33932992U, 34042816U, 34153024U, | ||||||
|  |         34263104U, 34373824U, 34485056U, 34594624U, 34704832U, 34816064U, 34926272U, | ||||||
|  |         35036224U, 35146816U, 35255104U, 35367104U, 35478208U, 35588416U, 35698496U, | ||||||
|  |         35808832U, 35918656U, 36029888U, 36139456U, 36250688U, 36360512U, 36471104U, | ||||||
|  |         36581696U, 36691136U, 36802112U, 36912448U, 37022912U, 37132864U, 37242944U, | ||||||
|  |         37354048U, 37464512U, 37574848U, 37684928U, 37794752U, 37904704U, 38015552U, | ||||||
|  |         38125888U, 38236864U, 38345792U, 38457152U, 38567744U, 38678336U, 38787776U, | ||||||
|  |         38897216U, 39009088U, 39117632U, 39230144U, 39340352U, 39450304U, 39560384U, | ||||||
|  |         39671488U, 39781312U, 39891392U, 40002112U, 40112704U, 40223168U, 40332608U, | ||||||
|  |         40443968U, 40553792U, 40664768U, 40774208U, 40884416U, 40993984U, 41105984U, | ||||||
|  |         41215424U, 41326528U, 41436992U, 41546048U, 41655872U, 41768128U, 41878336U, | ||||||
|  |         41988928U, 42098752U, 42209344U, 42319168U, 42429248U, 42540352U, 42649792U, | ||||||
|  |         42761024U, 42871616U, 42981824U, 43092032U, 43201856U, 43312832U, 43423552U, | ||||||
|  |         43533632U, 43643584U, 43753792U, 43864384U, 43974976U, 44084032U, 44195392U, | ||||||
|  |         44306368U, 44415296U, 44526016U, 44637248U, 44746816U, 44858048U, 44967872U, | ||||||
|  |         45078848U, 45188288U, 45299264U, 45409216U, 45518272U, 45630272U, 45740224U, | ||||||
|  |         45850432U, 45960896U, 46069696U, 46182208U, 46292416U, 46402624U, 46512064U, | ||||||
|  |         46623296U, 46733888U, 46843712U, 46953664U, 47065024U, 47175104U, 47285696U, | ||||||
|  |         47395904U, 47506496U, 47615296U, 47726912U, 47837632U, 47947712U, 48055232U, | ||||||
|  |         48168128U, 48277952U, 48387392U, 48499648U, 48609472U, 48720064U, 48830272U, | ||||||
|  |         48940096U, 49050944U, 49160896U, 49271744U, 49381568U, 49492288U, 49602752U, | ||||||
|  |         49712576U, 49822016U, 49934272U, 50042816U, 50154304U, 50264128U, 50374336U, | ||||||
|  |         50484416U, 50596288U, 50706752U, 50816704U, 50927168U, 51035456U, 51146944U, | ||||||
|  |         51258176U, 51366976U, 51477824U, 51589568U, 51699776U, 51809728U, 51920576U, | ||||||
|  |         52030016U, 52140736U, 52251328U, 52361152U, 52470592U, 52582592U, 52691776U, | ||||||
|  |         52803136U, 52912576U, 53020736U, 53132224U, 53242688U, 53354816U, 53465536U, | ||||||
|  |         53575232U, 53685568U, 53796544U, 53906752U, 54016832U, 54126656U, 54236992U, | ||||||
|  |         54347456U, 54457408U, 54569024U, 54679232U, 54789184U, 54899776U, 55008832U, | ||||||
|  |         55119296U, 55231168U, 55341248U, 55451584U, 55562048U, 55672256U, 55782208U, | ||||||
|  |         55893184U, 56002112U, 56113216U | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										74
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/endian.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/endian.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "compiler.h" | ||||||
|  | 
 | ||||||
|  | static const uint8_t BitReverseTable256[] = | ||||||
|  |         { | ||||||
|  |                 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, | ||||||
|  |                 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, | ||||||
|  |                 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, | ||||||
|  |                 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, | ||||||
|  |                 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, | ||||||
|  |                 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, | ||||||
|  |                 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, | ||||||
|  |                 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, | ||||||
|  |                 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, | ||||||
|  |                 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, | ||||||
|  |                 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, | ||||||
|  |                 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, | ||||||
|  |                 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, | ||||||
|  |                 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, | ||||||
|  |                 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, | ||||||
|  |                 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  | static inline uint32_t bitfn_swap32(uint32_t a) { | ||||||
|  |     return (BitReverseTable256[a & 0xff] << 24) | | ||||||
|  |             (BitReverseTable256[(a >> 8) & 0xff] << 16) | | ||||||
|  |             (BitReverseTable256[(a >> 16) & 0xff] << 8) | | ||||||
|  |             (BitReverseTable256[(a >> 24) & 0xff]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint64_t bitfn_swap64(uint64_t a) { | ||||||
|  |     return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) | | ||||||
|  |             (((uint64_t) bitfn_swap32((uint32_t) a)) << 32); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if defined(__MINGW32__) || defined(_WIN32) | ||||||
|  |   # define LITTLE_ENDIAN 1234 | ||||||
|  |   # define BYTE_ORDER    LITTLE_ENDIAN | ||||||
|  | #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) | ||||||
|  |   # include <sys/endian.h> | ||||||
|  | #elif defined(__OpenBSD__) || defined(__SVR4) | ||||||
|  |   # include <sys/types.h> | ||||||
|  | #elif defined(__APPLE__) | ||||||
|  | # include <machine/endian.h> | ||||||
|  | #elif defined( BSD ) && (BSD >= 199103) | ||||||
|  |   # include <machine/endian.h> | ||||||
|  | #elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ ) | ||||||
|  |   # define LITTLE_ENDIAN 1234 | ||||||
|  |   # define BYTE_ORDER    LITTLE_ENDIAN | ||||||
|  | #elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ ) | ||||||
|  |   # define BIG_ENDIAN 1234 | ||||||
|  |   # define BYTE_ORDER    BIG_ENDIAN | ||||||
|  | #else | ||||||
|  | 
 | ||||||
|  | # include <endian.h> | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #if LITTLE_ENDIAN == BYTE_ORDER | ||||||
|  | 
 | ||||||
|  | #define fix_endian32(x) (x) | ||||||
|  | #define fix_endian64(x) (x) | ||||||
|  | 
 | ||||||
|  | #elif BIG_ENDIAN == BYTE_ORDER | ||||||
|  | 
 | ||||||
|  | #define fix_endian32(x) bitfn_swap32(x) | ||||||
|  | #define fix_endian64(x) bitfn_swap64(x) | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | # error "endian not supported" | ||||||
|  | #endif // BYTE_ORDER
 | ||||||
							
								
								
									
										88
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/ethash.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/ethash.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file ethash.h
 | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include "compiler.h" | ||||||
|  | 
 | ||||||
|  | #define REVISION 18 | ||||||
|  | #define DAGSIZE_BYTES_INIT 1073741824U | ||||||
|  | #define DAG_GROWTH 113000000U | ||||||
|  | #define EPOCH_LENGTH 30000U | ||||||
|  | #define MIX_BYTES 128 | ||||||
|  | #define DAG_PARENTS 256 | ||||||
|  | #define CACHE_ROUNDS 3 | ||||||
|  | #define ACCESSES 64 | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | typedef struct ethash_params { | ||||||
|  |     size_t full_size;               // Size of full data set (in bytes, multiple of mix size (128)).
 | ||||||
|  |     size_t cache_size;              // Size of compute cache (in bytes, multiple of node size (64)).
 | ||||||
|  | } ethash_params; | ||||||
|  | 
 | ||||||
|  | typedef struct ethash_return_value { | ||||||
|  |     uint8_t result[32]; | ||||||
|  |     uint8_t mix_hash[32]; | ||||||
|  | } ethash_return_value; | ||||||
|  | 
 | ||||||
|  | size_t const ethash_get_datasize(const uint32_t block_number); | ||||||
|  | size_t const ethash_get_cachesize(const uint32_t block_number); | ||||||
|  | 
 | ||||||
|  | // initialize the parameters
 | ||||||
|  | static inline void ethash_params_init(ethash_params *params, const uint32_t block_number) { | ||||||
|  |     params->full_size = ethash_get_datasize(block_number); | ||||||
|  |     params->cache_size = ethash_get_cachesize(block_number); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | typedef struct ethash_cache { | ||||||
|  |     void *mem; | ||||||
|  | } ethash_cache; | ||||||
|  | 
 | ||||||
|  | void ethash_mkcache(ethash_cache *cache, ethash_params const *params, const uint8_t seed[32]); | ||||||
|  | void ethash_compute_full_data(void *mem, ethash_params const *params, ethash_cache const *cache); | ||||||
|  | void ethash_full(ethash_return_value *ret, void const *full_mem, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); | ||||||
|  | void ethash_light(ethash_return_value *ret, ethash_cache const *cache, ethash_params const *params, const uint8_t header_hash[32], const uint64_t nonce); | ||||||
|  | 
 | ||||||
|  | static inline int ethash_check_difficulty( | ||||||
|  |         const uint8_t hash[32], | ||||||
|  |         const uint8_t difficulty[32]) { | ||||||
|  |     // Difficulty is big endian
 | ||||||
|  |     for (int i = 0; i < 32; i++) { | ||||||
|  |         if (hash[i] == difficulty[i]) continue; | ||||||
|  |         return hash[i] < difficulty[i]; | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int ethash_quick_check_difficulty( | ||||||
|  |         const uint8_t header_hash[32], | ||||||
|  |         const uint64_t nonce, | ||||||
|  |         const uint8_t mix_hash[32], | ||||||
|  |         const uint8_t difficulty[32]); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										38
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/fnv.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/fnv.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file fnv.h
 | ||||||
|  | * @author Matthew Wampler-Doty <negacthulhu@gmail.com> | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "compiler.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define FNV_PRIME 0x01000193 | ||||||
|  | 
 | ||||||
|  | static inline uint32_t fnv_hash(const uint32_t x, const uint32_t y) { | ||||||
|  | 	return x*FNV_PRIME ^ y; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										297
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/internal.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/internal.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,297 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file dash.cpp
 | ||||||
|  | * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  | * @author Matthew Wampler-Doty | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <assert.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include "ethash.h" | ||||||
|  | #include "fnv.h" | ||||||
|  | #include "endian.h" | ||||||
|  | #include "internal.h" | ||||||
|  | #include "data_sizes.h" | ||||||
|  | 
 | ||||||
|  | #ifdef WITH_CRYPTOPP | ||||||
|  | 
 | ||||||
|  | #include "SHA3_cryptopp.h" | ||||||
|  | 
 | ||||||
|  | #else | ||||||
|  | #include "sha3.h" | ||||||
|  | #endif // WITH_CRYPTOPP
 | ||||||
|  | 
 | ||||||
|  | size_t const ethash_get_datasize(const uint32_t block_number) { | ||||||
|  |     assert(block_number / EPOCH_LENGTH < 500); | ||||||
|  |     return dag_sizes[block_number / EPOCH_LENGTH]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t const ethash_get_cachesize(const uint32_t block_number) { | ||||||
|  |     assert(block_number / EPOCH_LENGTH < 500); | ||||||
|  |     return cache_sizes[block_number / EPOCH_LENGTH]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Follows Sergio's "STRICT MEMORY HARD HASHING FUNCTIONS" (2014)
 | ||||||
|  | // https://bitslog.files.wordpress.com/2013/12/memohash-v0-3.pdf
 | ||||||
|  | // SeqMemoHash(s, R, N)
 | ||||||
|  | void static ethash_compute_cache_nodes( | ||||||
|  |         node *const nodes, | ||||||
|  |         ethash_params const *params, | ||||||
|  |         const uint8_t seed[32]) { | ||||||
|  |     assert((params->cache_size % sizeof(node)) == 0); | ||||||
|  |     uint32_t const num_nodes = (uint32_t)(params->cache_size / sizeof(node)); | ||||||
|  | 
 | ||||||
|  |     SHA3_512(nodes[0].bytes, seed, 32); | ||||||
|  | 
 | ||||||
|  |     for (unsigned i = 1; i != num_nodes; ++i) { | ||||||
|  |         SHA3_512(nodes[i].bytes, nodes[i - 1].bytes, 64); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (unsigned j = 0; j != CACHE_ROUNDS; j++) { | ||||||
|  |         for (unsigned i = 0; i != num_nodes; i++) { | ||||||
|  |             uint32_t const idx = nodes[i].words[0] % num_nodes; | ||||||
|  |             node data; | ||||||
|  |             data = nodes[(num_nodes - 1 + i) % num_nodes]; | ||||||
|  | 			for (unsigned w = 0; w != NODE_WORDS; ++w) | ||||||
|  | 			{ | ||||||
|  | 				data.words[w] ^= nodes[idx].words[w]; | ||||||
|  | 			} | ||||||
|  |             SHA3_512(nodes[i].bytes, data.bytes, sizeof(data)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // now perform endian conversion
 | ||||||
|  | #if BYTE_ORDER != LITTLE_ENDIAN | ||||||
|  |     for (unsigned w = 0; w != (num_nodes*NODE_WORDS); ++w) | ||||||
|  |     { | ||||||
|  |         nodes->words[w] = fix_endian32(nodes->words[w]); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_mkcache( | ||||||
|  |   ethash_cache *cache, | ||||||
|  |         ethash_params const *params, | ||||||
|  |         const uint8_t seed[32]) { | ||||||
|  |     node *nodes = (node *) cache->mem; | ||||||
|  |     ethash_compute_cache_nodes(nodes, params, seed); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_calculate_dag_item( | ||||||
|  |         node *const ret, | ||||||
|  |         const unsigned node_index, | ||||||
|  |         const struct ethash_params *params, | ||||||
|  |         const struct ethash_cache *cache) { | ||||||
|  | 
 | ||||||
|  |     uint32_t num_parent_nodes = (uint32_t)(params->cache_size / sizeof(node)); | ||||||
|  |     node const *cache_nodes = (node const *) cache->mem; | ||||||
|  |     node const *init = &cache_nodes[node_index % num_parent_nodes]; | ||||||
|  | 
 | ||||||
|  | 	memcpy(ret, init, sizeof(node)); | ||||||
|  | 	ret->words[0] ^= node_index; | ||||||
|  | 	SHA3_512(ret->bytes, ret->bytes, sizeof(node)); | ||||||
|  | 
 | ||||||
|  | #if defined(_M_X64) && ENABLE_SSE | ||||||
|  |     __m128i const fnv_prime = _mm_set1_epi32(FNV_PRIME); | ||||||
|  |     __m128i xmm0 = ret->xmm[0]; | ||||||
|  |     __m128i xmm1 = ret->xmm[1]; | ||||||
|  |     __m128i xmm2 = ret->xmm[2]; | ||||||
|  |     __m128i xmm3 = ret->xmm[3]; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     for (unsigned i = 0; i != DAG_PARENTS; ++i) | ||||||
|  | 	{ | ||||||
|  |         uint32_t parent_index = ((node_index ^ i)*FNV_PRIME ^ ret->words[i % NODE_WORDS]) % num_parent_nodes; | ||||||
|  |         node const *parent = &cache_nodes[parent_index]; | ||||||
|  | 
 | ||||||
|  | 		#if defined(_M_X64) && ENABLE_SSE | ||||||
|  |         { | ||||||
|  |             xmm0 = _mm_mullo_epi32(xmm0, fnv_prime); | ||||||
|  |             xmm1 = _mm_mullo_epi32(xmm1, fnv_prime); | ||||||
|  |             xmm2 = _mm_mullo_epi32(xmm2, fnv_prime); | ||||||
|  |             xmm3 = _mm_mullo_epi32(xmm3, fnv_prime); | ||||||
|  |             xmm0 = _mm_xor_si128(xmm0, parent->xmm[0]); | ||||||
|  |             xmm1 = _mm_xor_si128(xmm1, parent->xmm[1]); | ||||||
|  |             xmm2 = _mm_xor_si128(xmm2, parent->xmm[2]); | ||||||
|  |             xmm3 = _mm_xor_si128(xmm3, parent->xmm[3]); | ||||||
|  | 
 | ||||||
|  |             // have to write to ret as values are used to compute index
 | ||||||
|  |             ret->xmm[0] = xmm0; | ||||||
|  |             ret->xmm[1] = xmm1; | ||||||
|  |             ret->xmm[2] = xmm2; | ||||||
|  |             ret->xmm[3] = xmm3; | ||||||
|  |         } | ||||||
|  |         #else | ||||||
|  |         { | ||||||
|  |             for (unsigned w = 0; w != NODE_WORDS; ++w) { | ||||||
|  |                 ret->words[w] = fnv_hash(ret->words[w], parent->words[w]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 		#endif | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	SHA3_512(ret->bytes, ret->bytes, sizeof(node)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_compute_full_data( | ||||||
|  |         void *mem, | ||||||
|  |         ethash_params const *params, | ||||||
|  |         ethash_cache const *cache) { | ||||||
|  |     assert((params->full_size % (sizeof(uint32_t) * MIX_WORDS)) == 0); | ||||||
|  |     assert((params->full_size % sizeof(node)) == 0); | ||||||
|  |     node *full_nodes = mem; | ||||||
|  | 
 | ||||||
|  |     // now compute full nodes
 | ||||||
|  |     for (unsigned n = 0; n != (params->full_size / sizeof(node)); ++n) { | ||||||
|  |         ethash_calculate_dag_item(&(full_nodes[n]), n, params, cache); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void ethash_hash( | ||||||
|  |         ethash_return_value * ret, | ||||||
|  |         node const *full_nodes, | ||||||
|  |         ethash_cache const *cache, | ||||||
|  |         ethash_params const *params, | ||||||
|  |         const uint8_t header_hash[32], | ||||||
|  |         const uint64_t nonce) { | ||||||
|  | 
 | ||||||
|  |     assert((params->full_size % MIX_WORDS) == 0); | ||||||
|  | 
 | ||||||
|  |     // pack hash and nonce together into first 40 bytes of s_mix
 | ||||||
|  |     assert(sizeof(node)*8 == 512); | ||||||
|  |     node s_mix[MIX_NODES + 1]; | ||||||
|  |     memcpy(s_mix[0].bytes, header_hash, 32); | ||||||
|  | 
 | ||||||
|  | #if BYTE_ORDER != LITTLE_ENDIAN | ||||||
|  |     s_mix[0].double_words[4] = fix_endian64(nonce); | ||||||
|  | #else | ||||||
|  |     s_mix[0].double_words[4] = nonce; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     // compute sha3-512 hash and replicate across mix
 | ||||||
|  |     SHA3_512(s_mix->bytes, s_mix->bytes, 40); | ||||||
|  | 
 | ||||||
|  | #if BYTE_ORDER != LITTLE_ENDIAN | ||||||
|  |     for (unsigned w = 0; w != 16; ++w) { | ||||||
|  |         s_mix[0].words[w] = fix_endian32(s_mix[0].words[w]); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     node* const mix = s_mix + 1; | ||||||
|  |     for (unsigned w = 0; w != MIX_WORDS; ++w) { | ||||||
|  |         mix->words[w] = s_mix[0].words[w % NODE_WORDS]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     unsigned const | ||||||
|  |             page_size = sizeof(uint32_t) * MIX_WORDS, | ||||||
|  |             num_full_pages = (unsigned)(params->full_size / page_size); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     for (unsigned i = 0; i != ACCESSES; ++i) | ||||||
|  | 	{ | ||||||
|  |         uint32_t const index = ((s_mix->words[0] ^ i)*FNV_PRIME ^ mix->words[i % MIX_WORDS]) % num_full_pages; | ||||||
|  | 
 | ||||||
|  |         for (unsigned n = 0; n != MIX_NODES; ++n) | ||||||
|  | 		{ | ||||||
|  |             const node * dag_node = &full_nodes[MIX_NODES * index + n]; | ||||||
|  | 
 | ||||||
|  |             if (!full_nodes) { | ||||||
|  |                 node tmp_node; | ||||||
|  |                 ethash_calculate_dag_item(&tmp_node, index * MIX_NODES + n, params, cache); | ||||||
|  |                 dag_node = &tmp_node; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 			#if defined(_M_X64) && ENABLE_SSE | ||||||
|  |             { | ||||||
|  |                 __m128i fnv_prime = _mm_set1_epi32(FNV_PRIME); | ||||||
|  |                 __m128i xmm0 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[0]); | ||||||
|  |                 __m128i xmm1 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[1]); | ||||||
|  |                 __m128i xmm2 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[2]); | ||||||
|  |                 __m128i xmm3 = _mm_mullo_epi32(fnv_prime, mix[n].xmm[3]); | ||||||
|  |                 mix[n].xmm[0] = _mm_xor_si128(xmm0, dag_node->xmm[0]); | ||||||
|  |                 mix[n].xmm[1] = _mm_xor_si128(xmm1, dag_node->xmm[1]); | ||||||
|  |                 mix[n].xmm[2] = _mm_xor_si128(xmm2, dag_node->xmm[2]); | ||||||
|  |                 mix[n].xmm[3] = _mm_xor_si128(xmm3, dag_node->xmm[3]); | ||||||
|  |             } | ||||||
|  |             #else | ||||||
|  |             { | ||||||
|  |                 for (unsigned w = 0; w != NODE_WORDS; ++w) { | ||||||
|  |                     mix[n].words[w] = fnv_hash(mix[n].words[w], dag_node->words[w]); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	// compress mix
 | ||||||
|  | 	for (unsigned w = 0; w != MIX_WORDS; w += 4) | ||||||
|  | 	{ | ||||||
|  | 		uint32_t reduction = mix->words[w+0]; | ||||||
|  | 		reduction = reduction*FNV_PRIME ^ mix->words[w+1]; | ||||||
|  | 		reduction = reduction*FNV_PRIME ^ mix->words[w+2]; | ||||||
|  | 		reduction = reduction*FNV_PRIME ^ mix->words[w+3]; | ||||||
|  | 		mix->words[w/4] = reduction; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #if BYTE_ORDER != LITTLE_ENDIAN | ||||||
|  |     for (unsigned w = 0; w != MIX_WORDS/4; ++w) { | ||||||
|  |         mix->words[w] = fix_endian32(mix->words[w]); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     memcpy(ret->mix_hash, mix->bytes, 32); | ||||||
|  |     // final Keccak hash
 | ||||||
|  |     SHA3_256(ret->result, s_mix->bytes, 64+32);	// Keccak-256(s + compressed_mix)
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_quick_hash( | ||||||
|  |         uint8_t return_hash[32], | ||||||
|  |         const uint8_t header_hash[32], | ||||||
|  |         const uint64_t nonce, | ||||||
|  |         const uint8_t mix_hash[32]) { | ||||||
|  | 
 | ||||||
|  |     uint8_t buf[64+32]; | ||||||
|  |     memcpy(buf, header_hash, 32); | ||||||
|  | #if BYTE_ORDER != LITTLE_ENDIAN | ||||||
|  |     nonce = fix_endian64(nonce); | ||||||
|  | #endif | ||||||
|  |     memcpy(&(buf[32]), &nonce, 8); | ||||||
|  |     SHA3_512(buf, buf, 40); | ||||||
|  |     memcpy(&(buf[64]), mix_hash, 32); | ||||||
|  |     SHA3_256(return_hash, buf, 64+32); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int ethash_quick_check_difficulty( | ||||||
|  |         const uint8_t header_hash[32], | ||||||
|  |         const uint64_t nonce, | ||||||
|  |         const uint8_t mix_hash[32], | ||||||
|  |         const uint8_t difficulty[32]) { | ||||||
|  |     uint8_t return_hash[32]; | ||||||
|  |     ethash_quick_hash(return_hash, header_hash, nonce, mix_hash); | ||||||
|  |     return ethash_check_difficulty(return_hash, difficulty); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_full(ethash_return_value * ret, void const *full_mem, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { | ||||||
|  |     ethash_hash(ret, (node const *) full_mem, NULL, params, previous_hash, nonce); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ethash_light(ethash_return_value * ret, ethash_cache const *cache, ethash_params const *params, const uint8_t previous_hash[32], const uint64_t nonce) { | ||||||
|  |     ethash_hash(ret, NULL, cache, params, previous_hash, nonce); | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/internal.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/internal.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "compiler.h" | ||||||
|  | #include "endian.h" | ||||||
|  | #include "ethash.h" | ||||||
|  | 
 | ||||||
|  | #define ENABLE_SSE 1 | ||||||
|  | 
 | ||||||
|  | #if defined(_M_X64) && ENABLE_SSE | ||||||
|  | #include <smmintrin.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | // compile time settings
 | ||||||
|  | #define NODE_WORDS (64/4) | ||||||
|  | #define MIX_WORDS (MIX_BYTES/4) | ||||||
|  | #define MIX_NODES (MIX_WORDS / NODE_WORDS) | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | typedef union node { | ||||||
|  |     uint8_t bytes[NODE_WORDS * 4]; | ||||||
|  |     uint32_t words[NODE_WORDS]; | ||||||
|  |     uint64_t double_words[NODE_WORDS / 2]; | ||||||
|  | 
 | ||||||
|  | #if defined(_M_X64) && ENABLE_SSE | ||||||
|  | 	__m128i xmm[NODE_WORDS/4]; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | } node; | ||||||
|  | 
 | ||||||
|  | void ethash_calculate_dag_item( | ||||||
|  |         node *const ret, | ||||||
|  |         const unsigned node_index, | ||||||
|  |         ethash_params const *params, | ||||||
|  |         ethash_cache const *cache | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | void ethash_quick_hash( | ||||||
|  |         uint8_t return_hash[32], | ||||||
|  |         const uint8_t header_hash[32], | ||||||
|  |         const uint64_t nonce, | ||||||
|  |         const uint8_t mix_hash[32]); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										151
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,151 @@ | |||||||
|  | /** libkeccak-tiny
 | ||||||
|  | * | ||||||
|  | * A single-file implementation of SHA-3 and SHAKE. | ||||||
|  | * | ||||||
|  | * Implementor: David Leon Gil | ||||||
|  | * License: CC0, attribution kindly requested. Blame taken too, | ||||||
|  | * but not liability. | ||||||
|  | */ | ||||||
|  | #include "sha3.h" | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | /******** The Keccak-f[1600] permutation ********/ | ||||||
|  | 
 | ||||||
|  | /*** Constants. ***/ | ||||||
|  | static const uint8_t rho[24] = \ | ||||||
|  |   { 1,  3,   6, 10, 15, 21, | ||||||
|  |         28, 36, 45, 55,  2, 14, | ||||||
|  |         27, 41, 56,  8, 25, 43, | ||||||
|  |         62, 18, 39, 61, 20, 44}; | ||||||
|  | static const uint8_t pi[24] = \ | ||||||
|  |   {10,  7, 11, 17, 18, 3, | ||||||
|  |         5, 16,  8, 21, 24, 4, | ||||||
|  |         15, 23, 19, 13, 12, 2, | ||||||
|  |         20, 14, 22,  9, 6,  1}; | ||||||
|  | static const uint64_t RC[24] = \ | ||||||
|  |   {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, | ||||||
|  |         0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, | ||||||
|  |         0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, | ||||||
|  |         0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, | ||||||
|  |         0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, | ||||||
|  |         0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; | ||||||
|  | 
 | ||||||
|  | /*** Helper macros to unroll the permutation. ***/ | ||||||
|  | #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) | ||||||
|  | #define REPEAT6(e) e e e e e e | ||||||
|  | #define REPEAT24(e) REPEAT6(e e e e) | ||||||
|  | #define REPEAT5(e) e e e e e | ||||||
|  | #define FOR5(v, s, e) \ | ||||||
|  |   v = 0;            \ | ||||||
|  |   REPEAT5(e; v += s;) | ||||||
|  | 
 | ||||||
|  | /*** Keccak-f[1600] ***/ | ||||||
|  | static inline void keccakf(void* state) { | ||||||
|  |     uint64_t* a = (uint64_t*)state; | ||||||
|  |     uint64_t b[5] = {0}; | ||||||
|  |     uint64_t t = 0; | ||||||
|  |     uint8_t x, y; | ||||||
|  | 
 | ||||||
|  |     for (int i = 0; i < 24; i++) { | ||||||
|  |         // Theta
 | ||||||
|  |         FOR5(x, 1, | ||||||
|  |                 b[x] = 0; | ||||||
|  |                 FOR5(y, 5, | ||||||
|  |                         b[x] ^= a[x + y]; )) | ||||||
|  |         FOR5(x, 1, | ||||||
|  |                 FOR5(y, 5, | ||||||
|  |                         a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) | ||||||
|  |         // Rho and pi
 | ||||||
|  |         t = a[1]; | ||||||
|  |         x = 0; | ||||||
|  |         REPEAT24(b[0] = a[pi[x]]; | ||||||
|  |                 a[pi[x]] = rol(t, rho[x]); | ||||||
|  |                 t = b[0]; | ||||||
|  |                 x++; ) | ||||||
|  |         // Chi
 | ||||||
|  |         FOR5(y, | ||||||
|  |                 5, | ||||||
|  |                 FOR5(x, 1, | ||||||
|  |                         b[x] = a[y + x];) | ||||||
|  |                 FOR5(x, 1, | ||||||
|  |                 a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) | ||||||
|  |         // Iota
 | ||||||
|  |         a[0] ^= RC[i]; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /******** The FIPS202-defined functions. ********/ | ||||||
|  | 
 | ||||||
|  | /*** Some helper macros. ***/ | ||||||
|  | 
 | ||||||
|  | #define _(S) do { S } while (0) | ||||||
|  | #define FOR(i, ST, L, S) \ | ||||||
|  |   _(for (size_t i = 0; i < L; i += ST) { S; }) | ||||||
|  | #define mkapply_ds(NAME, S)                                          \ | ||||||
|  |   static inline void NAME(uint8_t* dst,                              \ | ||||||
|  |                           const uint8_t* src,                        \ | ||||||
|  |                           size_t len) {                              \ | ||||||
|  |     FOR(i, 1, len, S);                                               \ | ||||||
|  |   } | ||||||
|  | #define mkapply_sd(NAME, S)                                          \ | ||||||
|  |   static inline void NAME(const uint8_t* src,                        \ | ||||||
|  |                           uint8_t* dst,                              \ | ||||||
|  |                           size_t len) {                              \ | ||||||
|  |     FOR(i, 1, len, S);                                               \ | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | mkapply_ds(xorin, dst[i] ^= src[i])  // xorin
 | ||||||
|  | mkapply_sd(setout, dst[i] = src[i])  // setout
 | ||||||
|  | 
 | ||||||
|  | #define P keccakf | ||||||
|  | #define Plen 200 | ||||||
|  | 
 | ||||||
|  | // Fold P*F over the full blocks of an input.
 | ||||||
|  | #define foldP(I, L, F) \ | ||||||
|  |   while (L >= rate) {  \ | ||||||
|  |     F(a, I, rate);     \ | ||||||
|  |     P(a);              \ | ||||||
|  |     I += rate;         \ | ||||||
|  |     L -= rate;         \ | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | /** The sponge-based hash construction. **/ | ||||||
|  | static inline int hash(uint8_t* out, size_t outlen, | ||||||
|  |         const uint8_t* in, size_t inlen, | ||||||
|  |         size_t rate, uint8_t delim) { | ||||||
|  |     if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     uint8_t a[Plen] = {0}; | ||||||
|  |     // Absorb input.
 | ||||||
|  |     foldP(in, inlen, xorin); | ||||||
|  |     // Xor in the DS and pad frame.
 | ||||||
|  |     a[inlen] ^= delim; | ||||||
|  |     a[rate - 1] ^= 0x80; | ||||||
|  |     // Xor in the last block.
 | ||||||
|  |     xorin(a, in, inlen); | ||||||
|  |     // Apply P
 | ||||||
|  |     P(a); | ||||||
|  |     // Squeeze output.
 | ||||||
|  |     foldP(out, outlen, setout); | ||||||
|  |     setout(a, out, outlen); | ||||||
|  |     memset(a, 0, 200); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define defsha3(bits)                                             \ | ||||||
|  |   int sha3_##bits(uint8_t* out, size_t outlen,                    \ | ||||||
|  |                   const uint8_t* in, size_t inlen) {              \ | ||||||
|  |     if (outlen > (bits/8)) {                                      \ | ||||||
|  |       return -1;                                                  \ | ||||||
|  |     }                                                             \ | ||||||
|  |     return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01);  \ | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | /*** FIPS202 SHA3 FOFs ***/ | ||||||
|  | defsha3(256) | ||||||
|  | defsha3(512) | ||||||
							
								
								
									
										27
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include "compiler.h" | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | 
 | ||||||
|  | #define decsha3(bits) \ | ||||||
|  |   int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); | ||||||
|  | 
 | ||||||
|  | decsha3(256) | ||||||
|  | decsha3(512) | ||||||
|  | 
 | ||||||
|  | static inline void SHA3_256(uint8_t * const ret, uint8_t const *data, const size_t size) { | ||||||
|  |     sha3_256(ret, 32, data, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void SHA3_512(uint8_t * const ret, uint8_t const *data, const size_t size) { | ||||||
|  |     sha3_512(ret, 64, data, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										34
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3_cryptopp.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3_cryptopp.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /** @file sha3.cpp
 | ||||||
|  | * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  | * @date 2015 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <cryptopp/sha3.h> | ||||||
|  | 
 | ||||||
|  | extern "C" { | ||||||
|  | void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size) { | ||||||
|  |   CryptoPP::SHA3_256().CalculateDigest(ret, data, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size) { | ||||||
|  |   CryptoPP::SHA3_512().CalculateDigest(ret, data, size); | ||||||
|  | } | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3_cryptopp.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/sha3_cryptopp.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "compiler.h" | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | void SHA3_256(uint8_t *const ret, const uint8_t *data, size_t size); | ||||||
|  | void SHA3_512(uint8_t *const ret, const uint8_t *data, size_t size); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										41
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/util.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/util.c
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file util.c
 | ||||||
|  |  * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  |  * @date 2015 | ||||||
|  |  */ | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include "util.h" | ||||||
|  | 
 | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | 
 | ||||||
|  | // foward declare without all of Windows.h
 | ||||||
|  | __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString); | ||||||
|  | 
 | ||||||
|  | void debugf(const char *str, ...) | ||||||
|  | { | ||||||
|  | 	va_list args; | ||||||
|  |     va_start(args, str); | ||||||
|  | 
 | ||||||
|  | 	char buf[1<<16]; | ||||||
|  | 	_vsnprintf_s(buf, sizeof(buf), sizeof(buf), str, args); | ||||||
|  | 	buf[sizeof(buf)-1] = '\0'; | ||||||
|  | 	OutputDebugStringA(buf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										47
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/util.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/libethash/util.h
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | /*
 | ||||||
|  |   This file is part of cpp-ethereum. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is free software: you can redistribute it and/or modify | ||||||
|  |   it under the terms of the GNU General Public License as published by | ||||||
|  |   the Free Software Foundation, either version 3 of the License, or | ||||||
|  |   (at your option) any later version. | ||||||
|  | 
 | ||||||
|  |   cpp-ethereum is distributed in the hope that it will be useful, | ||||||
|  |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |   GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  |   You should have received a copy of the GNU General Public License | ||||||
|  |   along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /** @file util.h
 | ||||||
|  |  * @author Tim Hughes <tim@twistedfury.com> | ||||||
|  |  * @date 2015 | ||||||
|  |  */ | ||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "compiler.h" | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | void debugf(const char *str, ...); | ||||||
|  | #else | ||||||
|  | #define debugf printf | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static inline uint32_t min_u32(uint32_t a, uint32_t b) | ||||||
|  | { | ||||||
|  | 	return a < b ? a : b; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline uint32_t clamp_u32(uint32_t x, uint32_t min_, uint32_t max_) | ||||||
|  | { | ||||||
|  | 	return x < min_ ? min_ : (x > max_ ? max_ : x); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										29
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/binding.gyp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/binding.gyp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | { | ||||||
|  |   "targets": | ||||||
|  |     [{ | ||||||
|  |       "target_name": "ethash", | ||||||
|  |         "sources": [ | ||||||
|  |             './ethash.cc', | ||||||
|  |             '../libethash/ethash.h', | ||||||
|  |             '../libethash/util.c', | ||||||
|  |             '../libethash/util.h', | ||||||
|  |             '../libethash/blum_blum_shub.h', | ||||||
|  |             '../libethash/blum_blum_shub.c', | ||||||
|  |             '../libethash/sha3.h', | ||||||
|  |             '../libethash/sha3.c', | ||||||
|  |             '../libethash/internal.h', | ||||||
|  |             '../libethash/internal.c' | ||||||
|  |           ], | ||||||
|  |         "include_dirs": [ | ||||||
|  |           "../", | ||||||
|  |           "<!(node -e \"require('nan')\")" | ||||||
|  |         ], | ||||||
|  |         "cflags": [ | ||||||
|  |         "-Wall", | ||||||
|  |         "-Wno-maybe-uninitialized", | ||||||
|  |         "-Wno-uninitialized", | ||||||
|  |         "-Wno-unused-function", | ||||||
|  |         "-Wextra" | ||||||
|  |           ] | ||||||
|  |     }] | ||||||
|  | } | ||||||
							
								
								
									
										587
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/ethash.cc
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										587
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/ethash.cc
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,587 @@ | |||||||
|  | #include <nan.h> | ||||||
|  | #include <iostream> | ||||||
|  | #include <node.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include "../libethash/ethash.h" | ||||||
|  | 
 | ||||||
|  | using namespace v8; | ||||||
|  | 
 | ||||||
|  | class EthashValidator : public NanAsyncWorker { | ||||||
|  |  public: | ||||||
|  |   // Constructor
 | ||||||
|  |   EthashValidator(NanCallback *callback, const unsigned blocknumber, const unsigned char * seed) | ||||||
|  |     : NanAsyncWorker(callback), blocknumber(blocknumber), seed(seed) {} | ||||||
|  |   // Destructor
 | ||||||
|  |   ~EthashValidator() { | ||||||
|  |   	free(this->cache); | ||||||
|  | 	free(this->params); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Executed inside the worker-thread.
 | ||||||
|  |   // It is not safe to access V8, or V8 data structures
 | ||||||
|  |   // here, so everything we need for input and output
 | ||||||
|  |   // should go on `this`.
 | ||||||
|  |   void Execute () { | ||||||
|  | 	 | ||||||
|  |     /* this->result = secp256k1_ecdsa_sign(this->msg, this->sig , &this->sig_len, this->pk, NULL, NULL); */ | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Executed when the async work is complete
 | ||||||
|  |   // this function will be run inside the main event loop
 | ||||||
|  |   // so it is safe to use V8 again
 | ||||||
|  |   void HandleOKCallback () { | ||||||
|  |     NanScope(); | ||||||
|  |     Handle<Value> argv[] = { | ||||||
|  |       NanNew<Number>(this->result) | ||||||
|  |     }; | ||||||
|  |     callback->Call(2, argv); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |  protected: | ||||||
|  |   const unsigned blocknumber;  | ||||||
|  |   const unsigned char * seed; | ||||||
|  |   ethash_params * params; | ||||||
|  |   ethash_cache * cache; | ||||||
|  |   bool result; | ||||||
|  |   bool ready = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* class CompactSignWorker : public SignWorker { */ | ||||||
|  | /*  public: */ | ||||||
|  | /*   CompactSignWorker(NanCallback *callback, const unsigned char *msg, const unsigned char *pk ) */ | ||||||
|  | /*     : SignWorker(callback, msg, pk){} */ | ||||||
|  | 
 | ||||||
|  | /*   void Execute () { */ | ||||||
|  | /*     this->result = secp256k1_ecdsa_sign_compact(this->msg, this->sig , this->pk, NULL, NULL,  &this->sig_len); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   void HandleOKCallback () { */ | ||||||
|  | /*     NanScope(); */ | ||||||
|  | /*     Handle<Value> argv[] = { */ | ||||||
|  | /*       NanNew<Number>(this->result), */ | ||||||
|  | /*       NanNewBufferHandle((char *)this->sig, 64), */ | ||||||
|  | /*       NanNew<Number>(this->sig_len) */ | ||||||
|  | /*     }; */ | ||||||
|  | /*     callback->Call(3, argv); */ | ||||||
|  | /*   } */ | ||||||
|  | /* }; */ | ||||||
|  | 
 | ||||||
|  | /* class RecoverWorker : public NanAsyncWorker { */ | ||||||
|  | /*  public: */ | ||||||
|  | /*   // Constructor */ | ||||||
|  | /*   RecoverWorker(NanCallback *callback, const unsigned char *msg, const unsigned char *sig, int compressed, int rec_id) */ | ||||||
|  | /*     : NanAsyncWorker(callback), msg(msg), sig(sig), compressed(compressed), rec_id(rec_id) {} */ | ||||||
|  | /*   // Destructor */ | ||||||
|  | /*   ~RecoverWorker() {} */ | ||||||
|  | 
 | ||||||
|  | /*   void Execute () { */ | ||||||
|  | /*     if(this->compressed == 1){ */ | ||||||
|  | /*       this->pubkey = new unsigned char[33]; */  | ||||||
|  | /*     }else{ */ | ||||||
|  | /*       this->pubkey = new unsigned char[65]; */  | ||||||
|  | /*     } */ | ||||||
|  | 
 | ||||||
|  | /*     this->result = secp256k1_ecdsa_recover_compact(this->msg, this->sig, this->pubkey, &this->pubkey_len, this->compressed, this->rec_id); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   void HandleOKCallback () { */ | ||||||
|  | /*     NanScope(); */ | ||||||
|  | /*     Handle<Value> argv[] = { */ | ||||||
|  | /*       NanNew<Number>(this->result), */ | ||||||
|  | /*       NanNewBufferHandle((char *)this->pubkey, this->pubkey_len) */ | ||||||
|  | /*     }; */ | ||||||
|  | /*     callback->Call(2, argv); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*  protected: */ | ||||||
|  | /*   const unsigned char * msg; */ | ||||||
|  | /*   const unsigned char * sig; */  | ||||||
|  | /*   int compressed; */ | ||||||
|  | /*   int rec_id; */ | ||||||
|  | /*   int result; */ | ||||||
|  | /*   unsigned char * pubkey; */ | ||||||
|  | /*   int pubkey_len; */ | ||||||
|  | /* }; */ | ||||||
|  | 
 | ||||||
|  | /* class VerifyWorker : public NanAsyncWorker { */ | ||||||
|  | /*  public: */ | ||||||
|  | /*   // Constructor */ | ||||||
|  | /*   VerifyWorker(NanCallback *callback, const unsigned char *msg, const unsigned char *sig, int sig_len, const unsigned char *pub_key, int pub_key_len) */ | ||||||
|  | /*     : NanAsyncWorker(callback), msg(msg), sig(sig), sig_len(sig_len), pub_key(pub_key), pub_key_len(pub_key_len) {} */ | ||||||
|  | /*   // Destructor */ | ||||||
|  | /*   ~VerifyWorker() {} */ | ||||||
|  | 
 | ||||||
|  | /*   void Execute () { */ | ||||||
|  | /*     this->result = secp256k1_ecdsa_verify(this->msg, this->sig, this->sig_len,  this->pub_key, this->pub_key_len); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   void HandleOKCallback () { */ | ||||||
|  | /*     NanScope(); */ | ||||||
|  | /*     Handle<Value> argv[] = { */ | ||||||
|  | /*       NanNew<Number>(this->result), */ | ||||||
|  | /*     }; */ | ||||||
|  | /*     callback->Call(1, argv); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*  protected: */ | ||||||
|  | /*   int result; */ | ||||||
|  | /*   const unsigned char * msg; */ | ||||||
|  | /*   const unsigned char * sig; */ | ||||||
|  | /*   int sig_len; */  | ||||||
|  | /*   const unsigned char * pub_key; */ | ||||||
|  | /*   int pub_key_len; */ | ||||||
|  | /* }; */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Verify){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> pub_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pub_data = (unsigned char *) node::Buffer::Data(pub_buf); */ | ||||||
|  | /*   int pub_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> sig_buf = args[2].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sig_data = (unsigned char *) node::Buffer::Data(sig_buf); */ | ||||||
|  | /*   int sig_len = node::Buffer::Length(args[2]); */ | ||||||
|  | 
 | ||||||
|  | /*   int result = secp256k1_ecdsa_verify(msg_data, sig_data, sig_len, pub_data, pub_len ); */  | ||||||
|  | 
 | ||||||
|  | /*   NanReturnValue(NanNew<Number>(result)); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Verify_Async){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> pub_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pub_data = (unsigned char *) node::Buffer::Data(pub_buf); */ | ||||||
|  | /*   int pub_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> sig_buf = args[2].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sig_data = (unsigned char *) node::Buffer::Data(sig_buf); */ | ||||||
|  | /*   int sig_len = node::Buffer::Length(args[2]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Function> callback = args[3].As<Function>(); */ | ||||||
|  | /*   NanCallback* nanCallback = new NanCallback(callback); */ | ||||||
|  | 
 | ||||||
|  | /*   VerifyWorker* worker = new VerifyWorker(nanCallback, msg_data, sig_data, sig_len, pub_data, pub_len); */ | ||||||
|  | /*   NanAsyncQueueWorker(worker); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnUndefined(); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Sign){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Local<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pk_data = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | /*   int sec_len = node::Buffer::Length(args[0]); */ | ||||||
|  | /*   //the second argument is the message that we are signing */ | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char sig[72]; */ | ||||||
|  | /*   int sig_len = 72; */ | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[1]); */ | ||||||
|  | 
 | ||||||
|  | /*   if(sec_len != 32){ */ | ||||||
|  | /*     return NanThrowError("the secret key needs tobe 32 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   int result = secp256k1_ecdsa_sign(msg_data, sig , &sig_len, pk_data, NULL, NULL); */ | ||||||
|  | 
 | ||||||
|  | /*   if(result == 1){ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)sig, sig_len)); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     return NanThrowError("nonce invalid, try another one"); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Sign_Async){ */ | ||||||
|  | 
 | ||||||
|  | /*   NanScope(); */ | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Local<Object> sec_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sec_data = (unsigned char *) node::Buffer::Data(sec_buf); */ | ||||||
|  | /*   int sec_len = node::Buffer::Length(args[0]); */ | ||||||
|  | /*   //the second argument is the message that we are signing */ | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Function> callback = args[2].As<Function>(); */ | ||||||
|  | /*   NanCallback* nanCallback = new NanCallback(callback); */ | ||||||
|  | 
 | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[1]); */ | ||||||
|  | 
 | ||||||
|  | /*   if(sec_len != 32){ */ | ||||||
|  | /*     return NanThrowError("the secret key needs tobe 32 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   SignWorker* worker = new SignWorker(nanCallback, msg_data, sec_data); */ | ||||||
|  | /*   NanAsyncQueueWorker(worker); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnUndefined(); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Sign_Compact){ */ | ||||||
|  | 
 | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> seckey_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *seckey_data = (unsigned char *) node::Buffer::Data(seckey_buf); */ | ||||||
|  | /*   int sec_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[1]); */ | ||||||
|  | 
 | ||||||
|  | /*   if(sec_len != 32){ */ | ||||||
|  | /*     return NanThrowError("the secret key needs tobe 32 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char sig[64]; */ | ||||||
|  | /*   int rec_id; */ | ||||||
|  | 
 | ||||||
|  | /*   //TODO: change the nonce */ | ||||||
|  | /*   int valid_nonce = secp256k1_ecdsa_sign_compact(msg_data, sig, seckey_data, NULL, NULL, &rec_id ); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Array> array = NanNew<Array>(3); */ | ||||||
|  | /*   array->Set(0, NanNew<Integer>(valid_nonce)); */ | ||||||
|  | /*   array->Set(1, NanNew<Integer>(rec_id)); */ | ||||||
|  | /*   array->Set(2, NanNewBufferHandle((char *)sig, 64)); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnValue(array); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Sign_Compact_Async){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Local<Object> sec_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sec_data = (unsigned char *) node::Buffer::Data(sec_buf); */ | ||||||
|  | /*   int sec_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   //the second argument is the message that we are signing */ | ||||||
|  | /*   Local<Object> msg_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg_data = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*   Local<Function> callback = args[2].As<Function>(); */ | ||||||
|  | /*   NanCallback* nanCallback = new NanCallback(callback); */ | ||||||
|  | 
 | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[1]); */ | ||||||
|  | 
 | ||||||
|  | /*   if(sec_len != 32){ */ | ||||||
|  | /*     return NanThrowError("the secret key needs tobe 32 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   CompactSignWorker* worker = new CompactSignWorker(nanCallback, msg_data, sec_data); */  | ||||||
|  | /*   NanAsyncQueueWorker(worker); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnUndefined(); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Recover_Compact){ */ | ||||||
|  | 
 | ||||||
|  | /*   NanScope(); */ | ||||||
|  |    | ||||||
|  | /*   Local<Object> msg_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Object> sig_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sig = (unsigned char *) node::Buffer::Data(sig_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Number> compressed = args[2].As<Number>(); */ | ||||||
|  | /*   int int_compressed = compressed->IntegerValue(); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Number> rec_id = args[3].As<Number>(); */ | ||||||
|  | /*   int int_rec_id = rec_id->IntegerValue(); */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char pubKey[65]; */  | ||||||
|  | 
 | ||||||
|  | /*   int pubKeyLen; */ | ||||||
|  | 
 | ||||||
|  | /*   int result = secp256k1_ecdsa_recover_compact(msg, sig, pubKey, &pubKeyLen, int_compressed, int_rec_id); */ | ||||||
|  | /*   if(result == 1){ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)pubKey, pubKeyLen)); */ | ||||||
|  | /*   }else{ */ | ||||||
|  |      | ||||||
|  | /*     NanReturnValue(NanFalse()); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Recover_Compact_Async){ */ | ||||||
|  | 
 | ||||||
|  | /*   NanScope(); */ | ||||||
|  |    | ||||||
|  | /*   //the message */ | ||||||
|  | /*   Local<Object> msg_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *msg = (unsigned char *) node::Buffer::Data(msg_buf); */ | ||||||
|  | /*   int msg_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   //the signature length */ | ||||||
|  | /*   Local<Object> sig_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sig = (unsigned char *) node::Buffer::Data(sig_buf); */ | ||||||
|  | /*   //todo sig len needs tobe 64 */ | ||||||
|  | /*   int sig_len = node::Buffer::Length(args[1]); */ | ||||||
|  | 
 | ||||||
|  | /*   //to compress or not? */ | ||||||
|  | /*   Local<Number> compressed = args[2].As<Number>(); */ | ||||||
|  | /*   int int_compressed = compressed->IntegerValue(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the rec_id */ | ||||||
|  | /*   Local<Number> rec_id = args[3].As<Number>(); */ | ||||||
|  | /*   int int_rec_id = rec_id->IntegerValue(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the callback */ | ||||||
|  | /*   Local<Function> callback = args[4].As<Function>(); */ | ||||||
|  | /*   NanCallback* nanCallback = new NanCallback(callback); */ | ||||||
|  | 
 | ||||||
|  | /*   if(sig_len != 64){ */ | ||||||
|  | /*     return NanThrowError("the signature needs to be 64 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   if(msg_len == 0){ */ | ||||||
|  | /*     return NanThrowError("messgae cannot be null"); */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   RecoverWorker* worker = new RecoverWorker(nanCallback, msg, sig, int_compressed, int_rec_id); */ | ||||||
|  | /*   NanAsyncQueueWorker(worker); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnUndefined(); */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Seckey_Verify){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   const unsigned char *data = (const unsigned char*) node::Buffer::Data(args[0]); */ | ||||||
|  | /*   int result =  secp256k1_ec_seckey_verify(data); */  | ||||||
|  | /*   NanReturnValue(NanNew<Number>(result)); */  | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Pubkey_Verify){ */ | ||||||
|  | 
 | ||||||
|  | /*   NanScope(); */ | ||||||
|  |    | ||||||
|  | /*   Local<Object> pub_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pub_key = (unsigned char *) node::Buffer::Data(pub_buf); */ | ||||||
|  | /*   int pub_key_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   int result = secp256k1_ec_pubkey_verify(pub_key, pub_key_len); */ | ||||||
|  | 
 | ||||||
|  | /*   NanReturnValue(NanNew<Number>(result)); */  | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Pubkey_Create){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   Handle<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pk_data = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | /*   int pk_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Number> l_compact = args[1].As<Number>(); */ | ||||||
|  | /*   int compact = l_compact->IntegerValue(); */ | ||||||
|  | /*   int pubKeyLen; */ | ||||||
|  | 
 | ||||||
|  | /*   if(pk_len != 32){ */ | ||||||
|  | /*     return NanThrowError("the secert key need to be 32 bytes"); */ | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char *pubKey; */ | ||||||
|  | /*   if(compact == 1){ */ | ||||||
|  | /*     pubKey = new unsigned char[33]; */  | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     pubKey = new unsigned char[65]; */  | ||||||
|  | /*   } */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_pubkey_create(pubKey,&pubKeyLen, pk_data, compact ); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("secret was invalid, try again."); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)pubKey, pubKeyLen)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Pubkey_Decompress){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Local<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   unsigned char *pk_data = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int pk_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_pubkey_decompress(pk_data, &pk_len); */ | ||||||
|  | 
 | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid public key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)pk_data, pk_len)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Privkey_Import){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *pk_data = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int pk_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char sec_key[32]; */ | ||||||
|  | /*   int results = secp256k1_ec_privkey_import(sec_key, pk_data, pk_len); */ | ||||||
|  | 
 | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid private key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)sec_key, 32)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Privkey_Export){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> sk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   const unsigned char *sk_data = (unsigned char *) node::Buffer::Data(sk_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Local<Number> l_compressed = args[1].As<Number>(); */ | ||||||
|  | /*   int compressed = l_compressed->IntegerValue(); */ | ||||||
|  | 
 | ||||||
|  | /*   unsigned char *privKey; */ | ||||||
|  | /*   int pk_len; */ | ||||||
|  | /*   int results = secp256k1_ec_privkey_export(sk_data, privKey, &pk_len, compressed); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid private key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)privKey, pk_len)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Privkey_Tweak_Add){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> sk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   unsigned char *sk = (unsigned char *) node::Buffer::Data(sk_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Handle<Object> tweak_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *tweak= (unsigned char *) node::Buffer::Data(tweak_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_privkey_tweak_add(sk, tweak); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)sk, 32)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Privkey_Tweak_Mul){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> sk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   unsigned char *sk = (unsigned char *) node::Buffer::Data(sk_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   Handle<Object> tweak_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *tweak= (unsigned char *) node::Buffer::Data(tweak_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_privkey_tweak_mul(sk, tweak); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)sk, 32)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Pubkey_Tweak_Add){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   unsigned char *pk = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | /*   int pk_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Handle<Object> tweak_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *tweak= (unsigned char *) node::Buffer::Data(tweak_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_pubkey_tweak_add(pk, pk_len, tweak); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)pk, pk_len)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | /* NAN_METHOD(Pubkey_Tweak_Mul){ */ | ||||||
|  | /*   NanScope(); */ | ||||||
|  | 
 | ||||||
|  | /*   //the first argument should be the private key as a buffer */ | ||||||
|  | /*   Handle<Object> pk_buf = args[0].As<Object>(); */ | ||||||
|  | /*   unsigned char *pk = (unsigned char *) node::Buffer::Data(pk_buf); */ | ||||||
|  | /*   int pk_len = node::Buffer::Length(args[0]); */ | ||||||
|  | 
 | ||||||
|  | /*   Handle<Object> tweak_buf = args[1].As<Object>(); */ | ||||||
|  | /*   const unsigned char *tweak= (unsigned char *) node::Buffer::Data(tweak_buf); */ | ||||||
|  | 
 | ||||||
|  | /*   int results = secp256k1_ec_pubkey_tweak_mul(pk, pk_len, tweak); */ | ||||||
|  | /*   if(results == 0){ */ | ||||||
|  | /*     return NanThrowError("invalid key"); */ | ||||||
|  | /*   }else{ */ | ||||||
|  | /*     NanReturnValue(NanNewBufferHandle((char *)pk, pk_len)); */ | ||||||
|  | /*   } */ | ||||||
|  | /* } */ | ||||||
|  | 
 | ||||||
|  | void Init(Handle<Object> exports) { | ||||||
|  | 
 | ||||||
|  |   /* secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY); */ | ||||||
|  |   /* exports->Set(NanNew("seckeyVerify"), NanNew<FunctionTemplate>(Seckey_Verify)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("sign"), NanNew<FunctionTemplate>(Sign)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("signAsync"), NanNew<FunctionTemplate>(Sign_Async)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("signCompact"), NanNew<FunctionTemplate>(Sign_Compact)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("signCompactAsync"), NanNew<FunctionTemplate>(Sign_Compact_Async)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("recoverCompact"), NanNew<FunctionTemplate>(Recover_Compact)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("recoverCompactAsync"), NanNew<FunctionTemplate>(Recover_Compact_Async)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("verify"), NanNew<FunctionTemplate>(Verify)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("verifyAsync"), NanNew<FunctionTemplate>(Verify_Async)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("secKeyVerify"), NanNew<FunctionTemplate>(Seckey_Verify)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("pubKeyVerify"), NanNew<FunctionTemplate>(Pubkey_Verify)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("pubKeyCreate"), NanNew<FunctionTemplate>(Pubkey_Create)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("pubKeyDecompress"), NanNew<FunctionTemplate>(Pubkey_Decompress)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("privKeyExport"), NanNew<FunctionTemplate>(Privkey_Export)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("privKeyImport"), NanNew<FunctionTemplate>(Privkey_Import)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("privKeyTweakAdd"), NanNew<FunctionTemplate>(Privkey_Tweak_Add)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("privKeyTweakMul"), NanNew<FunctionTemplate>(Privkey_Tweak_Mul)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("pubKeyTweakAdd"), NanNew<FunctionTemplate>(Privkey_Tweak_Add)->GetFunction()); */ | ||||||
|  |   /* exports->Set(NanNew("pubKeyTweakMul"), NanNew<FunctionTemplate>(Privkey_Tweak_Mul)->GetFunction()); */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NODE_MODULE(secp256k1, Init) | ||||||
							
								
								
									
										13
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/package.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/package.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | { | ||||||
|  |   "name": "node-ethash", | ||||||
|  |   "version": "1.0.0", | ||||||
|  |   "description": "", | ||||||
|  |   "main": "index.js", | ||||||
|  |   "scripts": { | ||||||
|  |     "test": "echo \"Error: no test specified\" && exit 1", | ||||||
|  |     "install": "node-gyp rebuild" | ||||||
|  |   }, | ||||||
|  |   "author": "", | ||||||
|  |   "license": "ISC", | ||||||
|  |   "gypfile": true | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/readme.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/node-ethash/readme.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | # To Develop | ||||||
|  | `npm install -g node-gyp`   | ||||||
|  | `npm install .`   | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # To rebuild  | ||||||
|  | `node-gyp rebuild`   | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # notes | ||||||
|  | 
 | ||||||
|  | nan is good https://github.com/rvagg/nan | ||||||
							
								
								
									
										30
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/CMakeLists.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | IF( NOT Boost_FOUND ) | ||||||
|  |     find_package(Boost COMPONENTS unit_test_framework) | ||||||
|  | ENDIF() | ||||||
|  | 
 | ||||||
|  | IF( Boost_FOUND ) | ||||||
|  |     include_directories( ${Boost_INCLUDE_DIR} ) | ||||||
|  |     include_directories(..) | ||||||
|  | 
 | ||||||
|  |     link_directories ( ${Boost_LIBRARY_DIRS} ) | ||||||
|  |     file(GLOB HEADERS "*.h") | ||||||
|  |     ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) | ||||||
|  | 
 | ||||||
|  |     if (NOT CRYPTOPP_FOUND) | ||||||
|  | 	    find_package (CryptoPP) | ||||||
|  |     endif() | ||||||
|  | 
 | ||||||
|  |     if (CRYPTOPP_FOUND) | ||||||
|  | 	    add_definitions(-DWITH_CRYPTOPP) | ||||||
|  |     endif() | ||||||
|  | 
 | ||||||
|  |     add_executable (Test test.cpp ${HEADERS}) | ||||||
|  |     target_link_libraries (Test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${ETHHASH_LIBS}) | ||||||
|  | 
 | ||||||
|  |     if (CRYPTOPP_FOUND) | ||||||
|  | 	    TARGET_LINK_LIBRARIES(Test ${CRYPTOPP_LIBRARIES}) | ||||||
|  |     endif() | ||||||
|  | 
 | ||||||
|  |     enable_testing () | ||||||
|  |     add_test(NAME ethash COMMAND Test) | ||||||
|  | ENDIF() | ||||||
							
								
								
									
										54
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/go/ethash_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | package ethashTest | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"crypto/rand" | ||||||
|  | 	"log" | ||||||
|  | 	"math/big" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/ethereum/ethash" | ||||||
|  | 	"github.com/ethereum/go-ethereum/core" | ||||||
|  | 	"github.com/ethereum/go-ethereum/ethdb" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestEthash(t *testing.T) { | ||||||
|  | 	seedHash := make([]byte, 32) | ||||||
|  | 	_, err := rand.Read(seedHash) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	blockProcessor, err := core.NewCanonical(5, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Println("Block Number: ", blockProcessor.ChainManager().CurrentBlock().Number()) | ||||||
|  | 
 | ||||||
|  | 	e := ethash.New(blockProcessor.ChainManager()) | ||||||
|  | 
 | ||||||
|  | 	miningHash := make([]byte, 32) | ||||||
|  | 	if _, err := rand.Read(miningHash); err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	diff := big.NewInt(10000) | ||||||
|  | 	log.Println("difficulty", diff) | ||||||
|  | 
 | ||||||
|  | 	nonce := uint64(0) | ||||||
|  | 
 | ||||||
|  | 	ghash_full := e.FullHash(nonce, miningHash) | ||||||
|  | 	log.Printf("ethash full (on nonce): %x %x\n", ghash_full, nonce) | ||||||
|  | 
 | ||||||
|  | 	ghash_light := e.LightHash(nonce, miningHash) | ||||||
|  | 	log.Printf("ethash light (on nonce): %x %x\n", ghash_light, nonce) | ||||||
|  | 
 | ||||||
|  | 	if bytes.Compare(ghash_full, ghash_light) != 0 { | ||||||
|  | 		t.Errorf("full: %x, light: %x", ghash_full, ghash_light) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										233
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/test.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								Godeps/_workspace/src/github.com/ethereum/ethash/test/test.cpp
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,233 @@ | |||||||
|  | #include <iomanip> | ||||||
|  | #include <libethash/fnv.h> | ||||||
|  | #include <libethash/ethash.h> | ||||||
|  | #include <libethash/internal.h> | ||||||
|  | 
 | ||||||
|  | #ifdef WITH_CRYPTOPP | ||||||
|  | #include <libethash/sha3_cryptopp.h> | ||||||
|  | #else | ||||||
|  | #include <libethash/sha3.h> | ||||||
|  | #endif // WITH_CRYPTOPP
 | ||||||
|  | 
 | ||||||
|  | #define BOOST_TEST_MODULE Daggerhashimoto | ||||||
|  | #define BOOST_TEST_MAIN | ||||||
|  | 
 | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include <libethash/ethash.h> | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | std::string bytesToHexString(const uint8_t *str, const size_t s) { | ||||||
|  |     std::ostringstream ret; | ||||||
|  | 
 | ||||||
|  |     for (int i = 0; i < s; ++i) | ||||||
|  |         ret << std::hex << std::setfill('0') << std::setw(2) << std::nouppercase << (int) str[i]; | ||||||
|  | 
 | ||||||
|  |     return ret.str(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(fnv_hash_check) { | ||||||
|  |     uint32_t x = 1235U; | ||||||
|  |     const uint32_t | ||||||
|  |             y = 9999999U, | ||||||
|  |             expected = (FNV_PRIME * x) ^ y; | ||||||
|  | 
 | ||||||
|  |     x = fnv_hash(x, y); | ||||||
|  | 
 | ||||||
|  |     BOOST_REQUIRE_MESSAGE(x == expected, | ||||||
|  |             "\nexpected: " << expected << "\n" | ||||||
|  |                     << "actual: " << x << "\n"); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(SHA256_check) { | ||||||
|  |     uint8_t input[32], out[32]; | ||||||
|  |     memcpy(input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); | ||||||
|  |     SHA3_256(out, input, 32); | ||||||
|  |     const std::string | ||||||
|  |             expected = "2b5ddf6f4d21c23de216f44d5e4bdc68e044b71897837ea74c83908be7037cd7", | ||||||
|  |             actual = bytesToHexString(out, 32); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(expected == actual, | ||||||
|  |             "\nexpected: " << expected.c_str() << "\n" | ||||||
|  |                     << "actual: " << actual.c_str() << "\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(SHA512_check) { | ||||||
|  |     uint8_t input[64], out[64]; | ||||||
|  |     memcpy(input, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 64); | ||||||
|  |     SHA3_512(out, input, 64); | ||||||
|  |     const std::string | ||||||
|  |             expected = "0be8a1d334b4655fe58c6b38789f984bb13225684e86b20517a55ab2386c7b61c306f25e0627c60064cecd6d80cd67a82b3890bd1289b7ceb473aad56a359405", | ||||||
|  |             actual = bytesToHexString(out, 64); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(expected == actual, | ||||||
|  |             "\nexpected: " << expected.c_str() << "\n" | ||||||
|  |                     << "actual: " << actual.c_str() << "\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_check) { | ||||||
|  |     ethash_params params; | ||||||
|  |     ethash_params_init(¶ms, 0); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.full_size  < DAGSIZE_BYTES_INIT, | ||||||
|  |             "\nfull size: " << params.full_size << "\n" | ||||||
|  |                     << "should be less than or equal to: " << DAGSIZE_BYTES_INIT << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.full_size + 20*MIX_BYTES >= DAGSIZE_BYTES_INIT, | ||||||
|  |             "\nfull size + 20*MIX_BYTES: " << params.full_size + 20*MIX_BYTES << "\n" | ||||||
|  |                     << "should be greater than or equal to: " << DAGSIZE_BYTES_INIT << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.cache_size < DAGSIZE_BYTES_INIT / 32, | ||||||
|  |             "\ncache size: " << params.cache_size << "\n" | ||||||
|  |                     << "should be less than or equal to: " << DAGSIZE_BYTES_INIT / 32 << "\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ethash_params_init_genesis_calcifide_check) { | ||||||
|  |     ethash_params params; | ||||||
|  |     ethash_params_init(¶ms, 0); | ||||||
|  |     const uint32_t expected_full_size = 1073739904; | ||||||
|  |     const uint32_t expected_cache_size = 1048384; | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.full_size  == expected_full_size, | ||||||
|  |             "\nexpected: " << expected_cache_size << "\n" | ||||||
|  |                     << "actual: " << params.full_size << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.cache_size  == expected_cache_size, | ||||||
|  |             "\nexpected: " << expected_cache_size << "\n" | ||||||
|  |                     << "actual: " << params.cache_size << "\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ethash_params_init_check) { | ||||||
|  |     ethash_params params; | ||||||
|  |     ethash_params_init(¶ms, 1971000); | ||||||
|  |     const uint64_t nine_month_size = (uint64_t) 8*DAGSIZE_BYTES_INIT; | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.full_size  < nine_month_size, | ||||||
|  |             "\nfull size: " << params.full_size << "\n" | ||||||
|  |                     << "should be less than or equal to: " << nine_month_size << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.full_size + DAGSIZE_BYTES_INIT / 4 > nine_month_size, | ||||||
|  |             "\nfull size + DAGSIZE_BYTES_INIT / 4: " << params.full_size + DAGSIZE_BYTES_INIT / 4 << "\n" | ||||||
|  |                     << "should be greater than or equal to: " << nine_month_size << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.cache_size < nine_month_size / 1024, | ||||||
|  |             "\nactual cache size: " << params.cache_size << "\n" | ||||||
|  |                     << "expected: " << nine_month_size / 1024 << "\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE(params.cache_size + DAGSIZE_BYTES_INIT / 4 / 1024 > nine_month_size / 1024 , | ||||||
|  |             "\ncache size + DAGSIZE_BYTES_INIT / 4 / 1024: " << params.cache_size + DAGSIZE_BYTES_INIT / 4 / 1024 << "\n" | ||||||
|  |                     << "actual: " << nine_month_size / 32 << "\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(light_and_full_client_checks) { | ||||||
|  |     ethash_params params; | ||||||
|  |     uint8_t seed[32], hash[32]; | ||||||
|  |     ethash_return_value light_out, full_out; | ||||||
|  |     memcpy(seed, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); | ||||||
|  |     memcpy(hash, "~~~X~~~~~~~~~~~~~~~~~~~~~~~~~~~~", 32); | ||||||
|  |     ethash_params_init(¶ms, 0); | ||||||
|  |     params.cache_size = 1024; | ||||||
|  |     params.full_size = 1024 * 32; | ||||||
|  |     ethash_cache cache; | ||||||
|  |     cache.mem = alloca(params.cache_size); | ||||||
|  |     ethash_mkcache(&cache, ¶ms, seed); | ||||||
|  |     node * full_mem = (node *) alloca(params.full_size); | ||||||
|  |     ethash_compute_full_data(full_mem, ¶ms, &cache); | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         const std::string | ||||||
|  |                 expected = "2da2b506f21070e1143d908e867962486d6b0a02e31d468fd5e3a7143aafa76a14201f63374314e2a6aaf84ad2eb57105dea3378378965a1b3873453bb2b78f9a8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995ca8620b2ebeca41fbc773bb837b5e724d6eb2de570d99858df0d7d97067fb8103b21757873b735097b35d3bea8fd1c359a9e8a63c1540c76c9784cf8d975e995c259440b89fa3481c2c33171477c305c8e1e421f8d8f6d59585449d0034f3e421808d8da6bbd0b6378f567647cc6c4ba6c434592b198ad444e7284905b7c6adaf70bf43ec2daa7bd5e8951aa609ab472c124cf9eba3d38cff5091dc3f58409edcc386c743c3bd66f92408796ee1e82dd149eaefbf52b00ce33014a6eb3e50625413b072a58bc01da28262f42cbe4f87d4abc2bf287d15618405a1fe4e386fcdafbb171064bd99901d8f81dd6789396ce5e364ac944bbbd75a7827291c70b42d26385910cd53ca535ab29433dd5c5714d26e0dce95514c5ef866329c12e958097e84462197c2b32087849dab33e88b11da61d52f9dbc0b92cc61f742c07dbbf751c49d7678624ee60dfbe62e5e8c47a03d8247643f3d16ad8c8e663953bcda1f59d7e2d4a9bf0768e789432212621967a8f41121ad1df6ae1fa78782530695414c6213942865b2730375019105cae91a4c17a558d4b63059661d9f108362143107babe0b848de412e4da59168cce82bfbff3c99e022dd6ac1e559db991f2e3f7bb910cefd173e65ed00a8d5d416534e2c8416ff23977dbf3eb7180b75c71580d08ce95efeb9b0afe904ea12285a392aff0c8561ff79fca67f694a62b9e52377485c57cc3598d84cac0a9d27960de0cc31ff9bbfe455acaa62c8aa5d2cce96f345da9afe843d258a99c4eaf3650fc62efd81c7b81cd0d534d2d71eeda7a6e315d540b4473c80f8730037dc2ae3e47b986240cfc65ccc565f0d8cde0bc68a57e39a271dda57440b3598bee19f799611d25731a96b5dbbbefdff6f4f656161462633030d62560ea4e9c161cf78fc96a2ca5aaa32453a6c5dea206f766244e8c9d9a8dc61185ce37f1fc804459c5f07434f8ecb34141b8dcae7eae704c950b55556c5f40140c3714b45eddb02637513268778cbf937a33e4e33183685f9deb31ef54e90161e76d969587dd782eaa94e289420e7c2ee908517f5893a26fdb5873d68f92d118d4bcf98d7a4916794d6ab290045e30f9ea00ca547c584b8482b0331ba1539a0f2714fddc3a0b06b0cfbb6a607b8339c39bcfd6640b1f653e9d70ef6c985b", | ||||||
|  |                 actual = bytesToHexString((uint8_t const *) cache.mem, params.cache_size); | ||||||
|  | 
 | ||||||
|  |         BOOST_REQUIRE_MESSAGE(expected == actual, | ||||||
|  |                 "\nexpected: " << expected.c_str() << "\n" | ||||||
|  |                         << "actual: " << actual.c_str() << "\n"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         node node; | ||||||
|  |         ethash_calculate_dag_item(&node, 0, ¶ms, &cache); | ||||||
|  |         const std::string | ||||||
|  |                 actual = bytesToHexString((uint8_t const *) &node, sizeof(node)), | ||||||
|  |                 expected = "b1698f829f90b35455804e5185d78f549fcb1bdce2bee006d4d7e68eb154b596be1427769eb1c3c3e93180c760af75f81d1023da6a0ffbe321c153a7c0103597"; | ||||||
|  |         BOOST_REQUIRE_MESSAGE(actual == expected, | ||||||
|  |                 "\n" << "expected: " << expected.c_str() << "\n" | ||||||
|  |                         << "actual: " << actual.c_str() << "\n"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         for (int i = 0 ; i < params.full_size / sizeof(node) ; ++i ) { | ||||||
|  |             for (uint32_t j = 0; j < 32; ++j) { | ||||||
|  |                 node expected_node; | ||||||
|  |                 ethash_calculate_dag_item(&expected_node, j, ¶ms, &cache); | ||||||
|  |                 const std::string | ||||||
|  |                         actual = bytesToHexString((uint8_t const *) &(full_mem[j]), sizeof(node)), | ||||||
|  |                         expected = bytesToHexString((uint8_t const *) &expected_node, sizeof(node)); | ||||||
|  |                 BOOST_REQUIRE_MESSAGE(actual == expected, | ||||||
|  |                         "\ni: " << j << "\n" | ||||||
|  |                                 << "expected: " << expected.c_str() << "\n" | ||||||
|  |                                 << "actual: " << actual.c_str() << "\n"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         uint64_t nonce = 0x7c7c597c; | ||||||
|  |         ethash_full(&full_out, full_mem, ¶ms, hash, nonce); | ||||||
|  |         ethash_light(&light_out, &cache, ¶ms, hash, nonce); | ||||||
|  |         const std::string | ||||||
|  |                 light_result_string = bytesToHexString(light_out.result, 32), | ||||||
|  |                 full_result_string = bytesToHexString(full_out.result, 32); | ||||||
|  |         BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string, | ||||||
|  |                 "\nlight result: " << light_result_string.c_str() << "\n" | ||||||
|  |                         << "full result: " << full_result_string.c_str() << "\n"); | ||||||
|  |         const std::string | ||||||
|  |                 light_mix_hash_string = bytesToHexString(light_out.mix_hash, 32), | ||||||
|  |                 full_mix_hash_string = bytesToHexString(full_out.mix_hash, 32); | ||||||
|  |         BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string, | ||||||
|  |                 "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n" | ||||||
|  |                         << "full mix hash: " << full_mix_hash_string.c_str() << "\n"); | ||||||
|  |         uint8_t check_hash[32]; | ||||||
|  |         ethash_quick_hash(check_hash, hash, nonce, full_out.mix_hash); | ||||||
|  |         const std::string check_hash_string = bytesToHexString(check_hash, 32); | ||||||
|  |         BOOST_REQUIRE_MESSAGE(check_hash_string == full_result_string, | ||||||
|  |                 "\ncheck hash string: " << check_hash_string.c_str() << "\n" | ||||||
|  |                         << "full result: " << full_result_string.c_str() << "\n"); | ||||||
|  |     } | ||||||
|  |     { | ||||||
|  |         ethash_full(&full_out, full_mem, ¶ms, hash, 5); | ||||||
|  |         std::string | ||||||
|  |                 light_result_string = bytesToHexString(light_out.result, 32), | ||||||
|  |                 full_result_string = bytesToHexString(full_out.result, 32); | ||||||
|  | 
 | ||||||
|  |         BOOST_REQUIRE_MESSAGE(light_result_string != full_result_string, | ||||||
|  |                 "\nlight result and full result should differ: " << light_result_string.c_str() << "\n"); | ||||||
|  | 
 | ||||||
|  |         ethash_light(&light_out, &cache, ¶ms, hash, 5); | ||||||
|  |         light_result_string = bytesToHexString(light_out.result, 32); | ||||||
|  |         BOOST_REQUIRE_MESSAGE(light_result_string == full_result_string, | ||||||
|  |                 "\nlight result and full result should be the same\n" | ||||||
|  |                         << "light result: " << light_result_string.c_str() << "\n" | ||||||
|  |                         << "full result: " << full_result_string.c_str() << "\n"); | ||||||
|  |         std::string | ||||||
|  |                 light_mix_hash_string = bytesToHexString(light_out.mix_hash, 32), | ||||||
|  |                 full_mix_hash_string = bytesToHexString(full_out.mix_hash, 32); | ||||||
|  |         BOOST_REQUIRE_MESSAGE(full_mix_hash_string == light_mix_hash_string, | ||||||
|  |                 "\nlight mix hash: " << light_mix_hash_string.c_str() << "\n" | ||||||
|  |                         << "full mix hash: " << full_mix_hash_string.c_str() << "\n"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ethash_check_difficulty_check) { | ||||||
|  |     uint8_t hash[32], target[32]; | ||||||
|  |     memset(hash, 0, 32); | ||||||
|  |     memset(target, 0, 32); | ||||||
|  | 
 | ||||||
|  |     memcpy(hash, "11111111111111111111111111111111", 32); | ||||||
|  |     memcpy(target, "22222222222222222222222222222222", 32); | ||||||
|  |     BOOST_REQUIRE_MESSAGE( | ||||||
|  |             ethash_check_difficulty(hash, target), | ||||||
|  |             "\nexpected \"" << hash << "\" to have less difficulty than \"" << target << "\"\n"); | ||||||
|  |     BOOST_REQUIRE_MESSAGE( | ||||||
|  |             !ethash_check_difficulty(hash, hash), | ||||||
|  |             "\nexpected \"" << hash << "\" to have the same difficulty as \"" << hash << "\"\n"); | ||||||
|  |     memcpy(target, "11111111111111111111111111111112", 32); | ||||||
|  |     BOOST_REQUIRE_MESSAGE( | ||||||
|  |             ethash_check_difficulty(hash, target), | ||||||
|  |             "\nexpected \"" << hash << "\" to have less difficulty than \"" << target << "\"\n"); | ||||||
|  |     memcpy(target, "11111111111111111111111111111110", 32); | ||||||
|  |     BOOST_REQUIRE_MESSAGE( | ||||||
|  |             !ethash_check_difficulty(hash, target), | ||||||
|  |             "\nexpected \"" << hash << "\" to have more difficulty than \"" << target << "\"\n"); | ||||||
|  | } | ||||||
| @ -7,12 +7,12 @@ import ( | |||||||
| 	"sync" | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/ethereum/ethash" | ||||||
| 	"github.com/ethereum/go-ethereum/core/types" | 	"github.com/ethereum/go-ethereum/core/types" | ||||||
| 	"github.com/ethereum/go-ethereum/ethutil" | 	"github.com/ethereum/go-ethereum/ethutil" | ||||||
| 	"github.com/ethereum/go-ethereum/event" | 	"github.com/ethereum/go-ethereum/event" | ||||||
| 	"github.com/ethereum/go-ethereum/logger" | 	"github.com/ethereum/go-ethereum/logger" | ||||||
| 	"github.com/ethereum/go-ethereum/pow" | 	"github.com/ethereum/go-ethereum/pow" | ||||||
| 	"github.com/ethereum/go-ethereum/pow/ezp" |  | ||||||
| 	"github.com/ethereum/go-ethereum/state" | 	"github.com/ethereum/go-ethereum/state" | ||||||
| 	"gopkg.in/fatih/set.v0" | 	"gopkg.in/fatih/set.v0" | ||||||
| ) | ) | ||||||
| @ -50,7 +50,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM | |||||||
| 	sm := &BlockProcessor{ | 	sm := &BlockProcessor{ | ||||||
| 		db:       db, | 		db:       db, | ||||||
| 		mem:      make(map[string]*big.Int), | 		mem:      make(map[string]*big.Int), | ||||||
| 		Pow:      ezp.New(), | 		Pow:      ethash.New(chainManager), | ||||||
| 		bc:       chainManager, | 		bc:       chainManager, | ||||||
| 		eventMux: eventMux, | 		eventMux: eventMux, | ||||||
| 		txpool:   txpool, | 		txpool:   txpool, | ||||||
| @ -105,6 +105,9 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated | |||||||
| 
 | 
 | ||||||
| 	return receipt, txGas, err | 	return receipt, txGas, err | ||||||
| } | } | ||||||
|  | func (self *BlockProcessor) ChainManager() *ChainManager { | ||||||
|  | 	return self.bc | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { | func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, types.Transactions, types.Transactions, types.Transactions, error) { | ||||||
| 	var ( | 	var ( | ||||||
| @ -256,6 +259,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error { | |||||||
| 		return fmt.Errorf("GasLimit check failed for block %v", block.Header().GasLimit) | 		return fmt.Errorf("GasLimit check failed for block %v", block.Header().GasLimit) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// There can be at most one uncle
 | ||||||
|  | 	if len(block.Uncles()) > 1 { | ||||||
|  | 		return ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles())) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if block.Time() < parent.Time() { | 	if block.Time() < parent.Time() { | ||||||
| 		return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) | 		return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time) | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										142
									
								
								core/chain_makers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								core/chain_makers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,142 @@ | |||||||
|  | package core | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/ethereum/go-ethereum/core/types" | ||||||
|  | 	"github.com/ethereum/go-ethereum/ethutil" | ||||||
|  | 	"github.com/ethereum/go-ethereum/event" | ||||||
|  | 	"github.com/ethereum/go-ethereum/pow" | ||||||
|  | 	"github.com/ethereum/go-ethereum/state" | ||||||
|  | 	"math/big" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // So we can generate blocks easily
 | ||||||
|  | type FakePow struct{} | ||||||
|  | 
 | ||||||
|  | func (f FakePow) Search(block pow.Block, stop <-chan struct{}) ([]byte, []byte, []byte) { | ||||||
|  | 	return nil, nil, nil | ||||||
|  | } | ||||||
|  | func (f FakePow) Verify(block pow.Block) bool { return true } | ||||||
|  | func (f FakePow) GetHashrate() int64          { return 0 } | ||||||
|  | func (f FakePow) Turbo(bool)                  {} | ||||||
|  | 
 | ||||||
|  | // So we can deterministically seed different blockchains
 | ||||||
|  | var ( | ||||||
|  | 	CanonicalSeed = 1 | ||||||
|  | 	ForkSeed      = 2 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Utility functions for making chains on the fly
 | ||||||
|  | // Exposed for sake of testing from other packages (eg. go-ethash)
 | ||||||
|  | func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block { | ||||||
|  | 	return newBlockFromParent(addr, parent) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block { | ||||||
|  | 	return makeBlock(bman, parent, i, db, seed) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks { | ||||||
|  | 	return makeChain(bman, parent, max, db, seed) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewChainMan(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager { | ||||||
|  | 	return newChainManager(block, eventMux, db) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewBlockProc(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor { | ||||||
|  | 	return newBlockProcessor(db, txpool, cman, eventMux) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewCanonical(n int, db ethutil.Database) (*BlockProcessor, error) { | ||||||
|  | 	return newCanonical(n, db) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // block time is fixed at 10 seconds
 | ||||||
|  | func newBlockFromParent(addr []byte, parent *types.Block) *types.Block { | ||||||
|  | 	block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "") | ||||||
|  | 	block.SetUncles(nil) | ||||||
|  | 	block.SetTransactions(nil) | ||||||
|  | 	block.SetReceipts(nil) | ||||||
|  | 
 | ||||||
|  | 	header := block.Header() | ||||||
|  | 	header.Difficulty = CalcDifficulty(block, parent) | ||||||
|  | 	header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1) | ||||||
|  | 	header.Time = parent.Header().Time + 10 | ||||||
|  | 	header.GasLimit = CalcGasLimit(parent, block) | ||||||
|  | 
 | ||||||
|  | 	block.Td = parent.Td | ||||||
|  | 
 | ||||||
|  | 	return block | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Actually make a block by simulating what miner would do
 | ||||||
|  | // we seed chains by the first byte of the coinbase
 | ||||||
|  | func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database, seed int) *types.Block { | ||||||
|  | 	addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20) | ||||||
|  | 	addr[0] = byte(seed) | ||||||
|  | 	block := newBlockFromParent(addr, parent) | ||||||
|  | 	state := state.New(block.Root(), db) | ||||||
|  | 	cbase := state.GetOrNewStateObject(addr) | ||||||
|  | 	cbase.SetGasPool(CalcGasLimit(parent, block)) | ||||||
|  | 	cbase.AddBalance(BlockReward) | ||||||
|  | 	state.Update(ethutil.Big0) | ||||||
|  | 	block.SetRoot(state.Root()) | ||||||
|  | 	return block | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Make a chain with real blocks
 | ||||||
|  | // Runs ProcessWithParent to get proper state roots
 | ||||||
|  | func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database, seed int) types.Blocks { | ||||||
|  | 	bman.bc.currentBlock = parent | ||||||
|  | 	blocks := make(types.Blocks, max) | ||||||
|  | 	for i := 0; i < max; i++ { | ||||||
|  | 		block := makeBlock(bman, parent, i, db, seed) | ||||||
|  | 		td, err := bman.processWithParent(block, parent) | ||||||
|  | 		if err != nil { | ||||||
|  | 			fmt.Println("process with parent failed", err) | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 		block.Td = td | ||||||
|  | 		blocks[i] = block | ||||||
|  | 		parent = block | ||||||
|  | 	} | ||||||
|  | 	return blocks | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Create a new chain manager starting from given block
 | ||||||
|  | // Effectively a fork factory
 | ||||||
|  | func newChainManager(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager { | ||||||
|  | 	bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: eventMux} | ||||||
|  | 	if block == nil { | ||||||
|  | 		bc.Reset() | ||||||
|  | 	} else { | ||||||
|  | 		bc.currentBlock = block | ||||||
|  | 		bc.td = block.Td | ||||||
|  | 	} | ||||||
|  | 	return bc | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // block processor with fake pow
 | ||||||
|  | func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor { | ||||||
|  | 	bman := NewBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) | ||||||
|  | 	bman.Pow = FakePow{} | ||||||
|  | 	return bman | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Make a new, deterministic canonical chain by running InsertChain
 | ||||||
|  | // on result of makeChain
 | ||||||
|  | func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) { | ||||||
|  | 	eventMux := &event.TypeMux{} | ||||||
|  | 	txpool := NewTxPool(eventMux) | ||||||
|  | 
 | ||||||
|  | 	bman := newBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) | ||||||
|  | 	bman.bc.SetProcessor(bman) | ||||||
|  | 	parent := bman.bc.CurrentBlock() | ||||||
|  | 	if n == 0 { | ||||||
|  | 		return bman, nil | ||||||
|  | 	} | ||||||
|  | 	lchain := makeChain(bman, parent, n, db, CanonicalSeed) | ||||||
|  | 	err := bman.bc.InsertChain(lchain) | ||||||
|  | 	return bman, err | ||||||
|  | } | ||||||
| @ -3,6 +3,7 @@ package core | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"math/big" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| @ -21,6 +22,75 @@ func init() { | |||||||
| 	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") | 	ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Test fork of length N starting from block i
 | ||||||
|  | func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) { | ||||||
|  | 	// switch databases to process the new chain
 | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	// copy old chain up to i into new db with deterministic canonical
 | ||||||
|  | 	bman2, err := newCanonical(i, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("could not make new canonical in testFork", err) | ||||||
|  | 	} | ||||||
|  | 	// asert the bmans have the same block at i
 | ||||||
|  | 	bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash() | ||||||
|  | 	bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash() | ||||||
|  | 	if bytes.Compare(bi1, bi2) != 0 { | ||||||
|  | 		t.Fatal("chains do not have the same hash at height", i) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bman2.bc.SetProcessor(bman2) | ||||||
|  | 
 | ||||||
|  | 	// extend the fork
 | ||||||
|  | 	parent := bman2.bc.CurrentBlock() | ||||||
|  | 	chainB := makeChain(bman2, parent, N, db, ForkSeed) | ||||||
|  | 	err = bman2.bc.InsertChain(chainB) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Insert chain error for fork:", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	tdpre := bman.bc.Td() | ||||||
|  | 	// Test the fork's blocks on the original chain
 | ||||||
|  | 	td, err := testChain(chainB, bman) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("expected chainB not to give errors:", err) | ||||||
|  | 	} | ||||||
|  | 	// Compare difficulties
 | ||||||
|  | 	f(tdpre, td) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func printChain(bc *ChainManager) { | ||||||
|  | 	for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { | ||||||
|  | 		b := bc.GetBlockByNumber(uint64(i)) | ||||||
|  | 		fmt.Printf("\t%x\n", b.Hash()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // process blocks against a chain
 | ||||||
|  | func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { | ||||||
|  | 	td := new(big.Int) | ||||||
|  | 	for _, block := range chainB { | ||||||
|  | 		td2, err := bman.bc.processor.Process(block) | ||||||
|  | 		if err != nil { | ||||||
|  | 			if IsKnownBlockErr(err) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		block.Td = td2 | ||||||
|  | 		td = td2 | ||||||
|  | 
 | ||||||
|  | 		bman.bc.mu.Lock() | ||||||
|  | 		{ | ||||||
|  | 			bman.bc.write(block) | ||||||
|  | 		} | ||||||
|  | 		bman.bc.mu.Unlock() | ||||||
|  | 	} | ||||||
|  | 	return td, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func loadChain(fn string, t *testing.T) (types.Blocks, error) { | func loadChain(fn string, t *testing.T) (types.Blocks, error) { | ||||||
| 	fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) | 	fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -45,6 +115,130 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t * | |||||||
| 	done <- true | 	done <- true | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func TestExtendCanonical(t *testing.T) { | ||||||
|  | 	CanonicalLength := 5 | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	// make first chain starting from genesis
 | ||||||
|  | 	bman, err := newCanonical(CanonicalLength, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	f := func(td1, td2 *big.Int) { | ||||||
|  | 		if td2.Cmp(td1) <= 0 { | ||||||
|  | 			t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Start fork from current height (CanonicalLength)
 | ||||||
|  | 	testFork(t, bman, CanonicalLength, 1, f) | ||||||
|  | 	testFork(t, bman, CanonicalLength, 2, f) | ||||||
|  | 	testFork(t, bman, CanonicalLength, 5, f) | ||||||
|  | 	testFork(t, bman, CanonicalLength, 10, f) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestShorterFork(t *testing.T) { | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	// make first chain starting from genesis
 | ||||||
|  | 	bman, err := newCanonical(10, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	f := func(td1, td2 *big.Int) { | ||||||
|  | 		if td2.Cmp(td1) >= 0 { | ||||||
|  | 			t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Sum of numbers must be less than 10
 | ||||||
|  | 	// for this to be a shorter fork
 | ||||||
|  | 	testFork(t, bman, 0, 3, f) | ||||||
|  | 	testFork(t, bman, 0, 7, f) | ||||||
|  | 	testFork(t, bman, 1, 1, f) | ||||||
|  | 	testFork(t, bman, 1, 7, f) | ||||||
|  | 	testFork(t, bman, 5, 3, f) | ||||||
|  | 	testFork(t, bman, 5, 4, f) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestLongerFork(t *testing.T) { | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	// make first chain starting from genesis
 | ||||||
|  | 	bman, err := newCanonical(10, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	f := func(td1, td2 *big.Int) { | ||||||
|  | 		if td2.Cmp(td1) <= 0 { | ||||||
|  | 			t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Sum of numbers must be greater than 10
 | ||||||
|  | 	// for this to be a longer fork
 | ||||||
|  | 	testFork(t, bman, 0, 11, f) | ||||||
|  | 	testFork(t, bman, 0, 15, f) | ||||||
|  | 	testFork(t, bman, 1, 10, f) | ||||||
|  | 	testFork(t, bman, 1, 12, f) | ||||||
|  | 	testFork(t, bman, 5, 6, f) | ||||||
|  | 	testFork(t, bman, 5, 8, f) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestEqualFork(t *testing.T) { | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	bman, err := newCanonical(10, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	f := func(td1, td2 *big.Int) { | ||||||
|  | 		if td2.Cmp(td1) != 0 { | ||||||
|  | 			t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Sum of numbers must be equal to 10
 | ||||||
|  | 	// for this to be an equal fork
 | ||||||
|  | 	testFork(t, bman, 0, 10, f) | ||||||
|  | 	testFork(t, bman, 1, 9, f) | ||||||
|  | 	testFork(t, bman, 2, 8, f) | ||||||
|  | 	testFork(t, bman, 5, 5, f) | ||||||
|  | 	testFork(t, bman, 6, 4, f) | ||||||
|  | 	testFork(t, bman, 9, 1, f) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestBrokenChain(t *testing.T) { | ||||||
|  | 	db, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	bman, err := newCanonical(10, db) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	db2, err := ethdb.NewMemDatabase() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Failed to create db:", err) | ||||||
|  | 	} | ||||||
|  | 	bman2, err := newCanonical(10, db2) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal("Could not make new canonical chain:", err) | ||||||
|  | 	} | ||||||
|  | 	bman2.bc.SetProcessor(bman2) | ||||||
|  | 	parent := bman2.bc.CurrentBlock() | ||||||
|  | 	chainB := makeChain(bman2, parent, 5, db2, ForkSeed) | ||||||
|  | 	chainB = chainB[1:] | ||||||
|  | 	_, err = testChain(chainB, bman) | ||||||
|  | 	if err == nil { | ||||||
|  | 		t.Error("expected broken chain to return error") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestChainInsertions(t *testing.T) { | func TestChainInsertions(t *testing.T) { | ||||||
| 	t.Skip() // travil fails.
 | 	t.Skip() // travil fails.
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -117,8 +117,13 @@ func (self *TxPool) add(tx *types.Transaction) error { | |||||||
| 	} else { | 	} else { | ||||||
| 		to = "[NEW_CONTRACT]" | 		to = "[NEW_CONTRACT]" | ||||||
| 	} | 	} | ||||||
| 
 | 	var from string | ||||||
| 	txplogger.Debugf("(t) %x => %s (%v) %x\n", tx.From()[:4], to, tx.Value, tx.Hash()) | 	if len(tx.From()) > 0 { | ||||||
|  | 		from = ethutil.Bytes2Hex(tx.From()[:4]) | ||||||
|  | 	} else { | ||||||
|  | 		return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From())) | ||||||
|  | 	} | ||||||
|  | 	txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash()) | ||||||
| 
 | 
 | ||||||
| 	// Notify the subscribers
 | 	// Notify the subscribers
 | ||||||
| 	go self.eventMux.Post(TxPreEvent{tx}) | 	go self.eventMux.Post(TxPreEvent{tx}) | ||||||
|  | |||||||
| @ -41,12 +41,29 @@ type Header struct { | |||||||
| 	Extra string | 	Extra string | ||||||
| 	// Block Nonce for verification
 | 	// Block Nonce for verification
 | ||||||
| 	Nonce ethutil.Bytes | 	Nonce ethutil.Bytes | ||||||
|  | 	// Mix digest for quick checking to prevent DOS
 | ||||||
|  | 	MixDigest ethutil.Bytes | ||||||
|  | 	// SeedHash used for light client verification
 | ||||||
|  | 	SeedHash ethutil.Bytes | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *Header) rlpData(withNonce bool) []interface{} { | func (self *Header) rlpData(withNonce bool) []interface{} { | ||||||
| 	fields := []interface{}{self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra} | 	fields := []interface{}{ | ||||||
|  | 		self.ParentHash, | ||||||
|  | 		self.UncleHash, | ||||||
|  | 		self.Coinbase, | ||||||
|  | 		self.Root, | ||||||
|  | 		self.TxHash, | ||||||
|  | 		self.ReceiptHash, | ||||||
|  | 		self.Bloom, | ||||||
|  | 		self.Difficulty, | ||||||
|  | 		self.Number, | ||||||
|  | 		self.GasLimit, | ||||||
|  | 		self.GasUsed, | ||||||
|  | 		self.Time, | ||||||
|  | 		self.Extra} | ||||||
| 	if withNonce { | 	if withNonce { | ||||||
| 		fields = append(fields, self.Nonce) | 		fields = append(fields, self.Nonce, self.MixDigest, self.SeedHash) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return fields | 	return fields | ||||||
| @ -176,6 +193,8 @@ func (self *Block) RlpDataForStorage() interface{} { | |||||||
| // Header accessors (add as you need them)
 | // Header accessors (add as you need them)
 | ||||||
| func (self *Block) Number() *big.Int          { return self.header.Number } | func (self *Block) Number() *big.Int          { return self.header.Number } | ||||||
| func (self *Block) NumberU64() uint64         { return self.header.Number.Uint64() } | func (self *Block) NumberU64() uint64         { return self.header.Number.Uint64() } | ||||||
|  | func (self *Block) MixDigest() []byte         { return self.header.MixDigest } | ||||||
|  | func (self *Block) SeedHash() []byte          { return self.header.SeedHash } | ||||||
| func (self *Block) Nonce() []byte             { return self.header.Nonce } | func (self *Block) Nonce() []byte             { return self.header.Nonce } | ||||||
| func (self *Block) Bloom() []byte             { return self.header.Bloom } | func (self *Block) Bloom() []byte             { return self.header.Bloom } | ||||||
| func (self *Block) Coinbase() []byte          { return self.header.Coinbase } | func (self *Block) Coinbase() []byte          { return self.header.Coinbase } | ||||||
| @ -200,7 +219,6 @@ func (self *Block) GetUncle(i int) *Header { | |||||||
| 
 | 
 | ||||||
| // Implement pow.Block
 | // Implement pow.Block
 | ||||||
| func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } | func (self *Block) Difficulty() *big.Int { return self.header.Difficulty } | ||||||
| func (self *Block) N() []byte            { return self.header.Nonce } |  | ||||||
| func (self *Block) HashNoNonce() []byte  { return self.header.HashNoNonce() } | func (self *Block) HashNoNonce() []byte  { return self.header.HashNoNonce() } | ||||||
| 
 | 
 | ||||||
| func (self *Block) Hash() []byte { | func (self *Block) Hash() []byte { | ||||||
|  | |||||||
| @ -69,8 +69,8 @@ done: | |||||||
| 
 | 
 | ||||||
| func (self *CpuMiner) mine(block *types.Block) { | func (self *CpuMiner) mine(block *types.Block) { | ||||||
| 	minerlogger.Infof("(re)started agent[%d]. mining...\n", self.index) | 	minerlogger.Infof("(re)started agent[%d]. mining...\n", self.index) | ||||||
| 	nonce := self.pow.Search(block, self.quitCurrentOp) | 	nonce, mixDigest, seedHash := self.pow.Search(block, self.quitCurrentOp) | ||||||
| 	if nonce != nil { | 	if nonce != nil { | ||||||
| 		self.returnCh <- Work{block.Number().Uint64(), nonce} | 		self.returnCh <- Work{block.Number().Uint64(), nonce, mixDigest, seedHash} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -42,8 +42,10 @@ func env(block *types.Block, eth core.Backend) *environment { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Work struct { | type Work struct { | ||||||
| 	Number uint64 | 	Number    uint64 | ||||||
| 	Nonce  []byte | 	Nonce     []byte | ||||||
|  | 	MixDigest []byte | ||||||
|  | 	SeedHash  []byte | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Agent interface { | type Agent interface { | ||||||
| @ -138,9 +140,12 @@ out: | |||||||
| func (self *worker) wait() { | func (self *worker) wait() { | ||||||
| 	for { | 	for { | ||||||
| 		for work := range self.recv { | 		for work := range self.recv { | ||||||
|  | 			// Someone Successfully Mined!
 | ||||||
| 			block := self.current.block | 			block := self.current.block | ||||||
| 			if block.Number().Uint64() == work.Number && block.Nonce() == nil { | 			if block.Number().Uint64() == work.Number && block.Nonce() == nil { | ||||||
| 				self.current.block.Header().Nonce = work.Nonce | 				self.current.block.Header().Nonce = work.Nonce | ||||||
|  | 				self.current.block.Header().MixDigest = work.MixDigest | ||||||
|  | 				self.current.block.Header().SeedHash = work.SeedHash | ||||||
| 
 | 
 | ||||||
| 				if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil { | 				if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil { | ||||||
| 					self.mux.Post(core.NewMinedBlockEvent{self.current.block}) | 					self.mux.Post(core.NewMinedBlockEvent{self.current.block}) | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								pow/block.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								pow/block.go
									
									
									
									
									
								
							| @ -1,10 +1,20 @@ | |||||||
| package pow | package pow | ||||||
| 
 | 
 | ||||||
| import "math/big" | import ( | ||||||
|  | 	"github.com/ethereum/go-ethereum/core/types" | ||||||
|  | 	"math/big" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| type Block interface { | type Block interface { | ||||||
| 	Difficulty() *big.Int | 	Difficulty() *big.Int | ||||||
| 	HashNoNonce() []byte | 	HashNoNonce() []byte | ||||||
| 	N() []byte | 	Nonce() []byte | ||||||
| 	Number() *big.Int | 	MixDigest() []byte | ||||||
|  | 	SeedHash() []byte | ||||||
|  | 	NumberU64() uint64 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ChainManager interface { | ||||||
|  | 	GetBlockByNumber(uint64) *types.Block | ||||||
|  | 	CurrentBlock() *types.Block | ||||||
| } | } | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ func (dag *Dagger) Find(obj *big.Int, resChan chan int64) { | |||||||
| 	resChan <- 0 | 	resChan <- 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dag *Dagger) Search(hash, diff *big.Int) *big.Int { | func (dag *Dagger) Search(hash, diff *big.Int) ([]byte, []byte, []byte) { | ||||||
| 	// TODO fix multi threading. Somehow it results in the wrong nonce
 | 	// TODO fix multi threading. Somehow it results in the wrong nonce
 | ||||||
| 	amountOfRoutines := 1 | 	amountOfRoutines := 1 | ||||||
| 
 | 
 | ||||||
| @ -69,7 +69,7 @@ func (dag *Dagger) Search(hash, diff *big.Int) *big.Int { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return big.NewInt(res) | 	return big.NewInt(res).Bytes(), nil, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool { | func (dag *Dagger) Verify(hash, diff, nonce *big.Int) bool { | ||||||
|  | |||||||
| @ -1,5 +0,0 @@ | |||||||
| extern char *Sha3(char *, int); |  | ||||||
| char *sha3_cgo(char *data, int l) |  | ||||||
| { |  | ||||||
| 	return Sha3(data, l); |  | ||||||
| } |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| package dash |  | ||||||
| 
 |  | ||||||
| /* |  | ||||||
| char *sha3_cgo(char *, int); // Forward declaration
 |  | ||||||
| */ |  | ||||||
| import "C" |  | ||||||
| import ( |  | ||||||
| 	"github.com/ethereum/go-ethereum/crypto" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| //export Sha3
 |  | ||||||
| func Sha3(data []byte, l int) []byte { |  | ||||||
| 	return crypto.Sha3(data) |  | ||||||
| } |  | ||||||
| @ -32,7 +32,7 @@ func (pow *EasyPow) Turbo(on bool) { | |||||||
| 	pow.turbo = on | 	pow.turbo = on | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) []byte { | func (pow *EasyPow) Search(block pow.Block, stop <-chan struct{}) ([]byte, []byte, []byte) { | ||||||
| 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||||
| 	hash := block.HashNoNonce() | 	hash := block.HashNoNonce() | ||||||
| 	diff := block.Difficulty() | 	diff := block.Difficulty() | ||||||
| @ -57,7 +57,7 @@ empty: | |||||||
| 	for { | 	for { | ||||||
| 		select { | 		select { | ||||||
| 		case <-stop: | 		case <-stop: | ||||||
| 			return nil | 			return nil, nil, nil | ||||||
| 		default: | 		default: | ||||||
| 			i++ | 			i++ | ||||||
| 
 | 
 | ||||||
| @ -67,7 +67,7 @@ empty: | |||||||
| 
 | 
 | ||||||
| 			sha := crypto.Sha3(big.NewInt(r.Int63()).Bytes()) | 			sha := crypto.Sha3(big.NewInt(r.Int63()).Bytes()) | ||||||
| 			if verify(hash, diff, sha) { | 			if verify(hash, diff, sha) { | ||||||
| 				return sha | 				return sha, nil, nil | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -75,8 +75,6 @@ empty: | |||||||
| 			time.Sleep(20 * time.Microsecond) | 			time.Sleep(20 * time.Microsecond) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (pow *EasyPow) Verify(block pow.Block) bool { | func (pow *EasyPow) Verify(block pow.Block) bool { | ||||||
| @ -96,5 +94,5 @@ func verify(hash []byte, diff *big.Int, nonce []byte) bool { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func Verify(block pow.Block) bool { | func Verify(block pow.Block) bool { | ||||||
| 	return verify(block.HashNoNonce(), block.Difficulty(), block.N()) | 	return verify(block.HashNoNonce(), block.Difficulty(), block.Nonce()) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package pow | package pow | ||||||
| 
 | 
 | ||||||
| type PoW interface { | type PoW interface { | ||||||
| 	Search(block Block, stop <-chan struct{}) []byte | 	Search(block Block, stop <-chan struct{}) ([]byte, []byte, []byte) | ||||||
| 	Verify(block Block) bool | 	Verify(block Block) bool | ||||||
| 	GetHashrate() int64 | 	GetHashrate() int64 | ||||||
| 	Turbo(bool) | 	Turbo(bool) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user