// 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;
}
예제 #2
0
  /**
   * 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;
      }
    }
  }