Advertisement
Guest User

Untitled

a guest
Nov 18th, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.13 KB | None | 0 0
  1. #include "dag.h"
  2. #include "crypto/sph_blake.h"
  3. #include "crypto/Lyra2RE.h"
  4. #include "sync.h"
  5. #include "primitives/block.h"
  6. #include <fstream>
  7.  
  8. CHashimotoResult::CHashimotoResult(uint128 cmix, uint256 result) {
  9. this->cmix = cmix;
  10. this->result = result;
  11. }
  12.  
  13. uint128 CHashimotoResult::GetCmix() {
  14. return cmix;
  15. }
  16.  
  17. uint256 CHashimotoResult::GetResult() {
  18. return result;
  19. }
  20.  
  21. std::map<size_t, std::array<uint8_t, 32>> CDAGSystem::seedCache = std::map<size_t, std::array<uint8_t, 32>>();
  22. std::map<size_t, std::vector<uint32_t>> CDAGSystem::cacheCache = std::map<size_t, std::vector<uint32_t>>();
  23. std::map<size_t, std::vector<uint32_t>> CDAGSystem::graphCache = std::map<size_t, std::vector<uint32_t>>();
  24. CHashimotoResult CDAGSystem::lastwork = CHashimotoResult(uint128(), uint256());
  25. void CDAGSystem::PopulateSeedEpoch(uint64_t epoch) {
  26. if(!(seedCache.find(epoch) == seedCache.end())){
  27. return;
  28. }
  29. static CCriticalSection cs;
  30. {
  31. LOCK(cs);
  32. //Finds largest epoch, populates seed from it.
  33. seedCache[0].fill(0);
  34. uint64_t epoch_latest = seedCache.rbegin()->first;
  35. uint64_t start_epoch = ((epoch - epoch_latest) > epoch) ? 0 : epoch_latest;
  36. seedCache[epoch] = seedCache[start_epoch];
  37. for(uint64_t i = start_epoch; i < epoch; i++) {
  38. //Repeatedly hashes (seed_epoch - start_epoch) times
  39. sph_blake256_context ctx;
  40. sph_blake256_init(&ctx);
  41. sph_blake256(&ctx, seedCache[epoch].data(), HASH_BYTES);
  42. sph_blake256_close(&ctx,seedCache[epoch].data());
  43. }
  44. }
  45. }
  46.  
  47. uint32_t CDAGSystem::fnv(uint32_t v1, uint32_t v2) {
  48. return ((v1 * FNV_PRIME) ^ v2) % UINT32_MAX;
  49. }
  50.  
  51. bool CDAGSystem::is_prime(uint64_t num) {
  52. if (num < 2)
  53. return false;
  54. if ((num % 2 == 0) && num > 2)
  55. return false;
  56.  
  57. for(uint64_t i = 3; i < sqrt(num); i += 2) {
  58. if(num % i == 0)
  59. return false;
  60. }
  61. return true;
  62. }
  63.  
  64. uint64_t CDAGSystem::GetCacheSize(uint64_t epoch) {
  65. if(!cacheCache[epoch].empty())
  66. return cacheCache[epoch].size();
  67. uint64_t size = CACHE_BYTES_INIT + (CACHE_BYTES_GROWTH * round(sqrt(6*epoch)));
  68. size -= HASH_BYTES;
  69. while(!is_prime(size / HASH_BYTES)) {
  70. size -= MIX_BYTES;
  71. }
  72. return size;
  73. }
  74.  
  75. uint64_t CDAGSystem::GetGraphSize(uint64_t epoch) {
  76. if(!graphCache[epoch].empty())
  77. return graphCache[epoch].size();
  78. uint64_t size = DATASET_BYTES_INIT + (DATASET_BYTES_GROWTH * round(sqrt(6*epoch)));
  79. size -= MIX_BYTES;
  80. while(!is_prime(size / MIX_BYTES)) {
  81. size -= 2 * MIX_BYTES;
  82. }
  83. return size;
  84. }
  85.  
  86. void CDAGSystem::CreateCacheInPlace(uint64_t epoch) {
  87. PopulateSeedEpoch(epoch);
  88. uint64_t size = GetCacheSize(epoch);
  89. uint64_t items = size / HASH_BYTES;
  90. cacheCache[epoch].resize(size / sizeof(uint32_t), 0);
  91. sph_blake256_context ctx;
  92. sph_blake256_init(&ctx);
  93. sph_blake256(&ctx, seedCache[epoch].data(), HASH_BYTES);
  94. sph_blake256_close(&ctx, cacheCache[epoch].data());
  95. //First 32 bytes of cache are written to with hash of seed.
  96. for(uint64_t i = 1; i < items; i++){
  97. //Hash last item of the cache repeatedly the generate all items.
  98. uint8_t hasheditem[HASH_BYTES];
  99. sph_blake256_init(&ctx);
  100. sph_blake256(&ctx, cacheCache[epoch].data() + (i - 1)*(HASH_BYTES / sizeof(uint32_t)), HASH_BYTES);
  101. sph_blake256_close(&ctx, hasheditem);
  102. std::memcpy(cacheCache[epoch].data() + i*(HASH_BYTES / sizeof(uint32_t)), hasheditem, HASH_BYTES);
  103. }
  104. for(uint64_t round = 0; round < CACHE_ROUNDS; round++) {
  105. //3 round randmemohash.
  106. for(uint64_t i = 0; i < items; i++) {
  107. uint64_t target = cacheCache[epoch][(i * (HASH_BYTES / sizeof(uint32_t)))] % items;
  108. uint64_t mapper = (i - 1 + items) % items;
  109. /* Map target onto mapper, hash it,
  110. * then replace the current cache item with the 32 byte result. */
  111. uint32_t item[HASH_BYTES / sizeof(uint32_t)];
  112. for(uint64_t dword = 0; dword < (HASH_BYTES / sizeof(uint32_t)); dword++) {
  113. item[dword] = cacheCache[epoch][(mapper * (HASH_BYTES / sizeof(uint32_t))) + dword]
  114. ^ cacheCache[epoch][(target * (HASH_BYTES / sizeof(uint32_t))) + dword];
  115. }
  116. sph_blake256_init(&ctx);
  117. sph_blake256(&ctx, item, HASH_BYTES);
  118. sph_blake256_close(&ctx, item);
  119. std::memcpy(cacheCache[epoch].data() + (i * (HASH_BYTES / sizeof(uint32_t))), item, HASH_BYTES);
  120. }
  121. }
  122. }
  123.  
  124. void CDAGSystem::CreateGraphInPlace(uint64_t epoch) {
  125. uint64_t items = GetGraphSize(epoch) / HASH_BYTES;
  126. graphCache[epoch].resize(items * (HASH_BYTES / WORD_BYTES), 0);
  127. for(uint64_t i = 0; i < items; i++) {
  128. CDAGNode node = GetNode(i, epoch*EPOCH_LENGTH);
  129. memcpy(graphCache[epoch].data() + (i * (HASH_BYTES / sizeof(uint32_t))), node.ptr, HASH_BYTES);
  130. }
  131. std::fstream f("dag", std::ios_base::out);
  132. f.write((char*)graphCache[epoch].data(), items * HASH_BYTES);
  133. f.close();
  134. }
  135.  
  136. void CDAGSystem::PopulateCacheEpoch(uint64_t epoch) {
  137. if(!cacheCache[epoch].empty()) {
  138. return;
  139. }
  140. static CCriticalSection cs;
  141. {
  142. LOCK(cs);
  143. PopulateSeedEpoch(epoch);
  144. CreateCacheInPlace(epoch);
  145. }
  146. }
  147.  
  148. void CDAGSystem::PopulateGraphEpoch(uint64_t epoch) {
  149. if(!graphCache[epoch].empty()) {
  150. return;
  151. }
  152. static CCriticalSection cs;
  153. {
  154. LOCK(cs);
  155. PopulateSeedEpoch(epoch);
  156. PopulateCacheEpoch(epoch);
  157. CreateGraphInPlace(epoch);
  158. }
  159. }
  160.  
  161. CDAGNode CDAGSystem::GetNode(uint64_t i, int32_t height) {
  162. sph_blake256_context ctx;
  163. uint64_t epoch = height / EPOCH_LENGTH;
  164. PopulateCacheEpoch(epoch);
  165. uint64_t items = GetCacheSize(epoch) / HASH_BYTES;
  166. uint32_t *mix = new uint32_t[HASH_BYTES / sizeof(uint32_t)];
  167. std::memcpy(mix, cacheCache[epoch].data() + ((i % items) * (HASH_BYTES / sizeof(uint32_t))), HASH_BYTES);
  168. mix[0] ^= i;
  169. sph_blake256_init(&ctx);
  170. sph_blake256(&ctx, mix, HASH_BYTES);
  171. sph_blake256_close(&ctx, mix);
  172. for(uint64_t parent = 0; parent < DATASET_PARENTS; parent++) {
  173. uint64_t index = fnv(i ^ parent, mix[parent % (HASH_BYTES / sizeof(uint32_t))]) % items;
  174. for(uint64_t dword = 0; dword < (HASH_BYTES / sizeof(uint32_t)); dword++) {
  175. mix[dword] = fnv(mix[dword], cacheCache[epoch][index * (HASH_BYTES / sizeof(uint32_t))]);
  176. }
  177. }
  178. sph_blake256_init(&ctx);
  179. sph_blake256(&ctx, mix, HASH_BYTES);
  180. sph_blake256_close(&ctx, mix);
  181. CDAGNode node;
  182. node.ptr = mix;
  183. node.fGraphDerived = false;
  184. return node;
  185. }
  186.  
  187. CDAGNode CDAGSystem::GetNodeFromGraph(uint64_t i, int32_t height) {
  188. uint64_t epoch = height / EPOCH_LENGTH;
  189. PopulateGraphEpoch(epoch);
  190. CDAGNode node;
  191. node.ptr = graphCache[epoch].data() + (i * (HASH_BYTES / sizeof(uint32_t)));
  192. node.fGraphDerived = true;
  193. return node;
  194. }
  195.  
  196. CHashimotoResult CDAGSystem::Hashimoto(CBlockHeader header) {
  197. uint64_t epoch = header.height / EPOCH_LENGTH;
  198. uint64_t items = GetGraphSize(epoch) / HASH_BYTES;
  199. const uint64_t mixhashes = MIX_BYTES / HASH_BYTES;
  200. uint32_t headerhash[HASH_BYTES / sizeof(uint32_t)];
  201. uint32_t mix[MIX_BYTES / sizeof(uint32_t)];
  202. uint32_t cmix[(MIX_BYTES / sizeof(uint32_t)) / sizeof(uint32_t)];
  203. lyra2re2_hash((char*)&header, (char*)headerhash);
  204. for(uint64_t i = 0; i < mixhashes; i++) {
  205. std::memcpy(mix + (i * (HASH_BYTES / sizeof(uint32_t))), headerhash, HASH_BYTES);
  206. }
  207. for(uint64_t i = 0; i < ACCESSES; i++) {
  208. uint32_t target = fnv(i ^ headerhash[0], mix[i % (MIX_BYTES / sizeof(uint32_t))]) % (items / mixhashes) * mixhashes;
  209. std::cout << target << std::endl;
  210. uint32_t mapdata[MIX_BYTES / sizeof(uint32_t)];
  211. for(uint64_t mixhash = 0; mixhash < mixhashes; mixhash++) {
  212. CDAGNode node = GetNode(target + mixhash, header.height);
  213. assert((mixhash * (HASH_BYTES / sizeof(uint32_t))) < 16);
  214. std::memcpy(mapdata + (mixhash * (HASH_BYTES / sizeof(uint32_t))), node.ptr, HASH_BYTES);
  215. delete[] node.ptr;
  216. }
  217. for(uint64_t dword = 0; dword < (MIX_BYTES / sizeof(uint32_t)); dword++) {
  218. mix[dword] = fnv(mix[dword], mapdata[dword]);
  219. assert(dword < sizeof(mix));
  220. }
  221. }
  222. for(uint64_t i = 0; i < MIX_BYTES / sizeof(uint32_t); i += sizeof(uint32_t)) {
  223. cmix[i / sizeof(uint32_t)] = fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]);
  224. assert((i/4) < sizeof(cmix));
  225. }
  226. uint128 resmix;
  227. uint256 result;
  228. std::memcpy(resmix.begin(), cmix, MIX_BYTES / sizeof(uint32_t));
  229. std::array<uint8_t, HEADER_BYTES> fhash;
  230. std::memcpy(fhash.data(), headerhash, HASH_BYTES);
  231. std::memcpy(fhash.data() + HASH_BYTES, &header.height, sizeof(int32_t));
  232. std::memcpy(fhash.data() + HASH_BYTES + sizeof(int32_t), cmix, MIX_BYTES / sizeof(uint32_t));
  233. lyra2re2_hash52((char*)fhash.data(), (char*)result.begin());
  234. std::cout << result.ToString() << " " << resmix.ToString() << std::endl;
  235. return CHashimotoResult(resmix, result);
  236. }
  237.  
  238. CHashimotoResult CDAGSystem::FastHashimoto(CBlockHeader header) {
  239. uint64_t epoch = header.height / EPOCH_LENGTH;
  240. uint64_t items = GetGraphSize(epoch) / HASH_BYTES;
  241. const uint64_t mixhashes = MIX_BYTES / HASH_BYTES;
  242. uint32_t headerhash[HASH_BYTES / sizeof(uint32_t)];
  243. uint32_t mix[MIX_BYTES / sizeof(uint32_t)];
  244. uint32_t cmix[(MIX_BYTES / sizeof(uint32_t)) / sizeof(uint32_t)];
  245. lyra2re2_hash((char*)&header, (char*)headerhash);
  246. for(uint64_t i = 0; i < mixhashes; i++) {
  247. std::memcpy(mix + (i * (HASH_BYTES / sizeof(uint32_t))), headerhash, HASH_BYTES);
  248. }
  249. for(uint64_t i = 0; i < ACCESSES; i++) {
  250. uint32_t target = fnv(i ^ headerhash[0], mix[i % (MIX_BYTES / sizeof(uint32_t))]) % (items / mixhashes) * mixhashes;
  251. uint32_t mapdata[MIX_BYTES / sizeof(uint32_t)];
  252. for(uint64_t mixhash = 0; mixhash < mixhashes; mixhash++) {
  253. CDAGNode node = GetNodeFromGraph(target + mixhash, header.height);
  254. std::memcpy(mapdata + (mixhash * (HASH_BYTES / sizeof(uint32_t))), node.ptr, HASH_BYTES);
  255. }
  256. for(uint64_t dword = 0; dword < (MIX_BYTES / sizeof(uint32_t)); dword++) {
  257. mix[dword] = fnv(mix[dword], mapdata[dword]);
  258. }
  259. }
  260. for(uint64_t i = 0; i < MIX_BYTES / sizeof(uint32_t); i += sizeof(uint32_t)) {
  261. cmix[i / sizeof(uint32_t)] = fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]);
  262. }
  263. uint128 resmix;
  264. uint256 result;
  265. std::memcpy(resmix.begin(), cmix, MIX_BYTES / sizeof(uint32_t));
  266. std::array<uint8_t, HEADER_BYTES> fhash;
  267. std::memcpy(fhash.data(), headerhash, HASH_BYTES);
  268. std::memcpy(fhash.data() + HASH_BYTES, &header.height, sizeof(int32_t));
  269. std::memcpy(fhash.data() + HASH_BYTES + sizeof(int32_t), cmix, MIX_BYTES / sizeof(uint32_t));
  270. lyra2re2_hash52((char*)fhash.data(), (char*)result.begin());
  271. return CHashimotoResult(resmix, result);
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement