text: /**
   * @file       paramgen.cpp
   *
   * @brief      Parameter generation utility for Zerocoin.
   *
   * @author     Ian Miers, Christina Garman and Matthew Green
   * @date       June 2013
   *
   * @copyright  Copyright 2013 Ian Miers, Christina Garman and Matthew Green
   * @license    This project is released under the MIT license.
   **/
  // Copyright (c) 2017-2019 The PIVX developers
  // Copyright (c) 2021- The ORO developers
  
  #include <string>
  #include <iostream>
  #include <fstream>
  //#include <curses.h>
  #include <exception>
  #include "Zerocoin.h"
  
  #define DEFAULT_MODULUS_SIZE    3072
  #define MIN_MODULUS_SIZE        1026
  
  
  void
  PrintWarning()
  {
      cout << "Zerocoin parameter generation utility" << endl;
      cout << "-------------------------------------" << endl << endl;
      cout << "This utility generates an l-bit modulus N as the product of" << endl;
      cout << "two safe primes p, q. The values p and q are not stored." << endl;
      cout << "Call this program with no arguments to see usage options." << endl;
      cout << endl;
      cout << "SECURITY WARNING: ZEROCOIN PARAMETERS MUST BE GENERATED BY" << endl;
      cout << "A TRUSTED PARTY WHO DOES NOT STORE THE FACTORS. WHILE WE MAKE" << endl;
      cout << "A BEST EFFORT TO DESTROY THIS INFORMATION WE DO NOT TAKE" << endl;
      cout << "SPECIAL PRECAUTIONS TO ENSURE THAT THEY ARE DESTROYED." << endl;
      cout << endl;
      cout << "USE THIS UTILITY AT YOUR OWN RISK" << endl << endl;
  }
  
  void usage()
  {
      printf("Usage:\n");
      printf(" -b <numbits>\n");
      printf(" -o <output file>\n");
  
      exit (8);
  }
  
  int main(int argc, char **argv)
  {
      static CBigNum resultModulus(0);
      uint32_t numBits = DEFAULT_MODULUS_SIZE;
      ofstream outfile;
      char* outfileName;
      bool writeToFile = false;
  
      while ((argc > 1) && (argv[1][0] == '-'))
      {
          switch (argv[1][1])
          {
          case 'b':
              numBits = atoi(argv[2]);
              ++argv;
              --argc;
              break;
  
          case 'o':
              outfileName = argv[2];
              writeToFile = true;
              break;
  
          case 'h':
              usage();
              break;
  
          default:
              printf("Wrong Argument: %s\n", argv[1]);
              usage();
              break;
          }
  
          ++argv;
          --argc;
      }
  
      if (numBits < MIN_MODULUS_SIZE) {
          cout << "Modulus is below minimum length (" << MIN_MODULUS_SIZE << ") bits" << endl;
          return(0);
      }
  
      PrintWarning();
  
      cout << "Modulus size set to " << numBits << " bits." << endl;
      cout << "Generating parameters. This may take a few minutes..." << endl;
  
      // Generate two safe primes "p" and "q"
      CBigNum *p, *q;
      p = new CBigNum(0);
      q = new CBigNum(0);
      *p = CBigNum::generatePrime(numBits / 2, true);
      *q = CBigNum::generatePrime(numBits / 2, true);
  
      // Multiply to compute N
      resultModulus = (*p) * (*q);
  
      // Wipe out the factors
      delete p;
      delete q;
  
      // Convert to a hexidecimal string
      std::string resultHex = resultModulus.ToString(16);
  
      cout << endl << "N = " << endl << resultHex << endl;
  
      if (writeToFile) {
          try {
              outfile.open (outfileName);
              outfile << resultHex;
              outfile.close();
              cout << endl << "Result has been written to file '" << outfileName << "'." << endl;
          } catch (const std::runtime_error& e) {
              cout << "Unable to write to file:" << e.what() << endl;
          }
      }
  }
  