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 The PIVX developers
  // Copyright (c) 2018 The socialcoin 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
  
  using namespace std;
  using namespace libzerocoin;
  
  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 (std::runtime_error &e) {
  			cout << "Unable to write to file:" << e.what() << endl;
  		}
  	}
  }
  