// partly copied from https://github.com/zcash/zcash/blob/master/src/miner.cpp#L581 bool equihash_(std::string solver, CBlock *pblock, int n, int k) { arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); // Hash state crypto_generichash_blake2b_state state; EhInitialiseState(n, k, state); // I = the block header minus nonce and solution. CEquihashInput I{*pblock}; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << I; // H(I||... crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size()); // H(I||V||... crypto_generichash_blake2b_state curr_state; curr_state = state; crypto_generichash_blake2b_update(&curr_state, pblock->nNonce.begin(), pblock->nNonce.size()); // (x_1, x_2, ...) = A(I, V, n, k) LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n", solver, pblock->nNonce.ToString()); std::function<bool(std::vector<unsigned char>)> validBlock = [&pblock, &hashTarget](std::vector<unsigned char> soln) { // Write the solution to the hash and compute the result. pblock->nSolution = soln; if (UintToArith256(pblock->GetHash()) > hashTarget) { return false; } // Found a solution LogPrintf("CMMMiner:\n"); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); return true; }; if (solver == "tromp") { // Create solver and initialize it. equi eq(1); eq.setstate(&curr_state); // Intialization done, start algo driver. eq.digit0(0); eq.xfull = eq.bfull = eq.hfull = 0; eq.showbsizes(0); for (u32 r = 1; r < WK; r++) { (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0); eq.xfull = eq.bfull = eq.hfull = 0; eq.showbsizes(r); } eq.digitK(0); // Convert solution indices to byte array (decompress) and pass it to validBlock method. for (size_t s = 0; s < eq.nsols; s++) { std::vector<eh_index> index_vector(PROOFSIZE); for (size_t i = 0; i < PROOFSIZE; i++) { index_vector[i] = eq.sols[s][i]; } std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS); if (validBlock(sol_char)) return true; } } else { try { if (EhOptimisedSolve(n, k, curr_state, validBlock)) return true; } catch (std::exception&) { LogPrintf("pow/nano.cpp: ", "execption catched..."); } } return false; }
/** * Refit the coefficients based on the new estimates. This is sequential * for now ... we can think about making this parallel later. */ void refit () { /** Create some variables for BLAS */ int DIM = X.size(); int UNIQ_COLS = shadow_X.size(); int int_M = static_cast<int>(M); int int_K = static_cast<int>(K); /* Create all the required buffers */ RandomAccessContainer A_aug (M * DIM); RandomAccessContainer Y_aug (M * UNIQ_COLS); RandomAccessContainer A_aug_T_A_aug (DIM*DIM); RandomAccessContainer A_aug_T_Y (DIM*K); RandomAccessContainer W_effects (DIM*UNIQ_COLS); RandomAccessContainer index_vector (DIM); /* Create all the pointers */ double* Y_ptr = const_cast<double*>(&(Y[0])); double* A_aug_ptr = &(A_aug[0]); double* Y_aug_ptr = &(Y_aug[0]); double* A_aug_T_A_aug_ptr = &(A_aug_T_A_aug[0]); double* A_aug_T_Y_ptr = &(A_aug_T_Y[0]); double* W_effects_ptr = &(W_effects[0]); if (ROOT==mpi_rank) { /* Create A_aug */ ColMapIterType outer_iter = shadow_X.begin(); int col_number = 0; int W_col_index = 0; /* Iterate over one column of X at at time */ while (outer_iter != shadow_X.end()) { EdgeListIteratorType inner_iter=(*outer_iter).second.begin(); const EdgeListIteratorType inner_end = (*outer_iter).second.end(); /* Add one row at a time to A_aug */ while (inner_iter != inner_end) { const int A_column = (*inner_iter).source; const int A_aug_col_index = M*col_number; materializer (snp_map(A_column), A_aug.begin()+A_aug_col_index); index_vector[col_number] = W_col_index; ++col_number; ++inner_iter; } /* Add the corresponding column of Y to Y_aug */ const int Y_col = (*outer_iter).first; dcopy_ (&int_M, Y_ptr+(Y_col*M), &ONE_STEP, Y_aug_ptr+(M*W_col_index), &ONE_STEP); ++W_col_index; ++outer_iter; } /* Create A_aug'A_aug */ dsyrk_ (&UPPER, &TRANS, &DIM, &int_M, &PLUS_ONE, A_aug_ptr, &int_M, &ZERO, A_aug_T_A_aug_ptr, &DIM); /* Create A_aug'Y */ dgemm_ (&TRANS, &NO_TRANS, &DIM, &int_K, &int_M, &PLUS_ONE, A_aug_ptr, &int_M, Y_aug_ptr, &int_M, &ZERO, A_aug_T_Y_ptr, &DIM); /* Create the required columns of W */ { ColMapIterType outer_iter = shadow_X.begin(); int col=0; while (outer_iter != shadow_X.end()) { fill_in_W (W_effects.begin()+(DIM*col), (*outer_iter).first); ++outer_iter; ++col; } } /* Add in the effects of W to A_aug_T_A_aug and A_aug_T_Y */ for (int i=0; i<DIM; ++i) for (int j=0; j<DIM; ++j) A_aug_T_A_aug [i*DIM+j] = W_effects[(index_vector[i]*DIM)+j]; for (int i=0; i<UNIQ_COLS; ++i) for (int j=0; j<DIM; ++j) A_aug_T_Y [j] += (A_aug_T_Y [(i*DIM)+j] * W_effects[(i*DIM)+j]); /* Factorize A_aug_T_A_aug */ int result; dpotrf_ (&UPPER, &DIM, A_aug_T_A_aug_ptr, &DIM, &result); /* x = forwardsolve (C,x) */ dtrsm_(&LEFT, &UPPER, &TRANS, &NO_DIAG, &DIM, &ONE_STEP, &PLUS_ONE, A_aug_T_A_aug_ptr, &DIM, A_aug_T_Y_ptr, &DIM); /* x = backsolve (C,x) */ dtrsm_(&LEFT, &UPPER, &NO_TRANS, &NO_DIAG, &DIM, &ONE_STEP, &PLUS_ONE, A_aug_T_A_aug_ptr, &DIM, A_aug_T_Y_ptr, &DIM); } /* Broadcast coordinates to everyone */ MPI_Bcast (A_aug_T_Y_ptr, DIM, MPI_DOUBLE, ROOT, MPI_COMM_WORLD); /* Re-populate these coordinates into the selected set */ { ColMapIterType outer_iter = shadow_X.begin(); int col_number = 0; while (outer_iter != shadow_X.end()) { EdgeListIteratorType inner_iter=(*outer_iter).second.begin(); EdgeListIteratorType inner_end = (*outer_iter).second.end(); while (inner_iter != inner_end) { edge_type current_X = (*inner_iter); X.erase (current_X); current_X.weight = A_aug_T_Y [col_number]; X.insert (current_X); ++col_number; ++inner_iter; } ++outer_iter; } } }