예제 #1
0
int main (int argc, char * const argv[])
{
	if (argc < 4)
	{
		printf("\n\nUsage:  createmint  server_id  server_user_id  asset_type_id \n\n"
			"For now, expiration dates are automatically set:\n"
			"-- FROM: Today, Now.\n"
			"-- TO: 6 months from now.\n\n"
			"It is recommended that you issue a new series (create a new mint) every 3 months for each\n"
			"asset type, so that there is a 3-month overlap. In the future, this will be configured inside\n"
			"the contracts themselves.\n\n"
			"Server ID needs to match the Server ID from notaryServer.xml\n"
			"Server user ID needs to match the Server User ID from notaryServer.xml\n"
			"Asset Type ID needs to match the Asset ID (aka Hashed Contract ID) of the currency contract.\n\n"
			//			   "The path to the data folder is necessary for initialization of the OT library.\n\n"
			//             "(You probably want to use ~/.ot/server_data as your data folder.)\n\n"
			);
		return 0;
	}
	// **************************************************************************

	class __OTcreatemint_RAII
	{
	public:
		__OTcreatemint_RAII()
		{
			if(!OTLog::Init(SERVER_CONFIG_KEY,0)) { assert(false); };  // setup the logger.

			OTLog::vOutput(0, "\n\nWelcome to Open Transactions -- 'createmint', version %s\n", 
				OTLog::Version());
			// ------------------------------------
#ifdef _WIN32
			WSADATA wsaData;
			WORD wVersionRequested = MAKEWORD( 2, 2 );
			int err = WSAStartup( wVersionRequested, &wsaData );

			/* Tell the user that we could not find a usable		*/
			/* Winsock DLL.											*/		

			OT_ASSERT_MSG((err == 0), "WSAStartup failed!\n");


			/*	Confirm that the WinSock DLL supports 2.2.			*/
			/*	Note that if the DLL supports versions greater		*/
			/*	than 2.2 in addition to 2.2, it will still return	*/
			/*	2.2 in wVersion since that is the version we		*/
			/*	requested.											*/

			bool bWinsock = (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2);

			/* Tell the user that we could not find a usable */
			/* WinSock DLL.                                  */

			if (!bWinsock) WSACleanup();  // do cleanup.
			OT_ASSERT_MSG((!bWinsock), "Could not find a usable version of Winsock.dll\n");

			/* The Winsock DLL is acceptable. Proceed to use it. */
			/* Add network programming using Winsock here */
			/* then call WSACleanup when done using the Winsock dll */
			OTLog::vOutput(0,"The Winsock 2.2 dll was found okay\n");
#endif
			// ------------------------------------
			// SIGNALS
			//
#if defined(OT_SIGNAL_HANDLING)
			//
			OTLog::SetupSignalHandler();  // <===== SIGNALS
			//
			// This is optional! You can always remove it using the OT_NO_SIGNAL_HANDLING
			//  option, and plus, the internals only execute once anyway. (It keeps count.)
#endif
			// ------------------------------------

			//
			// OT Server Path:
			//
			{
				bool bSetupPathsSuccess = false;
				if(!OTDataFolder::Init(SERVER_CONFIG_KEY)) { OT_ASSERT(false); }
				else
					bSetupPathsSuccess = true;

				OT_ASSERT_MSG(bSetupPathsSuccess, "main(): Assert failed: Failed to set OT Path");
			}

			// -----------------------------------------------------------------------    

			OTCrypto::It()->Init(); // (OpenSSL gets initialized here.)

			// ------------------------------------
		}
		~__OTcreatemint_RAII()
		{
			// We clean these up in reverse order from the Init function, which just seems
			// like the best default, in absence of any brighter ideas.
			//
			OTCrypto::It()->Cleanup();  // (OpenSSL gets cleaned up here.)

			// ------------------------------------
#ifdef _WIN32
			WSACleanup(); // Corresponds to WSAStartup() in InitOTAPI().
#endif
			// ------------------------------------
		}
	};
	// --------------------------------------------

	__OTcreatemint_RAII   the_createmint_cleanup;

	// **************************************************************************

	OTServer theServer;

	// -----------------------------------------

	int nReturnVal = 0;

	OTString		strServerID(argv[1]),
		strServerNymID(argv[2]),
		strAssetTypeID(argv[3]);

	OTIdentifier	ASSET_TYPE_ID(strAssetTypeID),
		SERVER_ID(strServerID);

	//	std::string strDataFolderPath(argv[4]), strNotaryFile("notaryServer.xml");

	OTLog::vOutput(0, 
		"\nNow loading the server nym, which will also ask you for a password, to unlock\n"
		"its private key. (Default password is \"%s\".)\n", KEY_PASSWORD);

	// Keys, etc are loaded here. ===> Assumes main path is set! <===
	//
	theServer.Init(true); //bool bReadOnly=false by default (We don't want to overwrite anything if the ACTUAL server is running...)


	//  NOTE: I copied some code in here from xmlrpcxx_server.cpp, including the above
	//  call to theServer.Init(), which has the InitDefaultStorage inside of it, and
	//  which uses OTLog::Path(), which the above new code should be setting properly
	//  before theServer.Init() actually gets called. (So this should work....)
	//  
	//	bool bSuccessInitDefault = OTDB::InitDefaultStorage(OTDB_DEFAULT_STORAGE, 
	//														OTDB_DEFAULT_PACKER, strDataFolderPath, strNotaryFile);
	//    if (!bSuccessInitDefault)
	//    {
	//        OTLog::vError("\n\n%s: Failed invoking OTDB::InitDefaultStorage with path: %s and main filename: %s\n\n",
	//                      __FUNCTION__, strDataFolderPath.c_str(), strNotaryFile.c_str());
	//        return 0;
	//    }
	// -----------------------------------------

	OTString strMintPath;
	bool bFileIsPresent = false;		
	int nSeries = 0;

	for (nSeries = 0; nSeries < 10000; ++nSeries)
	{
//		struct stat st;

		OTString strFilename;
		strFilename.Format("%s%s%d", strAssetTypeID.Get(), ".", nSeries);

		bFileIsPresent = OTDB::Exists(OTFolders::Mint().Get(),
                                      strServerID.Get(),
                                      strFilename.Get());

		// Old Code
		//strMintPath.Format("%s%s%s%s%s%s%s%s%d", 
		//	OTLog::Path(), 
		//	OTLog::PathSeparator(),
		//	OTFolders::Mint().Get(),
		//	OTLog::PathSeparator(),
		//	strServerID.Get(),
		//	OTLog::PathSeparator(),
		//	strAssetTypeID.Get(), ".", nSeries);
		//bFileIsPresent = (stat(strMintPath.Get(), &st) == 0);

		if (!bFileIsPresent)
			break;
	}

	// if bFileIsPresent is STILL true, that means we got all the way up to 1000 and the 
	// file was present every time.
	// Geez, there must be 10000 mints on this computer.  At one new Mint per 3 months,
	// that's 4 per year, that's 2500 years already!!
	//
	if (bFileIsPresent)
	{
		OTLog::Output(0, "\n\nThis program automatically finds the next series, up to 10000. You\n"
			"have reached 10000. You will have to change the source code of this\n"
			"program in order to continue. Sorry.\n\n");
		return 0;
	}
	// ---------------------------------------------------------------------

	// nSeries now contains the number we need to use for the next series.
	// and strMintPath now contains the correct file path.

	OTMint * pMint = new OTMint(strServerID, strServerNymID, strAssetTypeID);
	OT_ASSERT(NULL != pMint);

	OTString strSeries; strSeries.Format("%s%d", ".", nSeries);

	if (pMint->LoadMint(strSeries.Get()))
	{
		OTLog::Output(0, "\n\nSorry, that mint already exists. Delete it first if you wish to re-create it.\n\n");
	}
	else 
	{
		OTLog::vOutput(0, "\n\nMint file does not (yet) exist for series %d and asset type:\n%s\n Creating......\n\n", 
			nSeries, strAssetTypeID.Get());

		// TODO: read the denominations out of the asset contract itself, instead of hardcoding them here.


		// Calculate FROM as Today, Now, 
		// then calculate TO as 6 months from now, 
		// and EXPIRATION as 3 months from now.
		//
		// TODO: Let these numbers be configured either in server operator contract, or issuer contract.
		// In the meantime, 3 and 6 months are good enough.

		OTPseudonym theNym;
		theNym.SetIdentifier(strServerNymID);

		// 1 hour	==     3600 Seconds
		// 1 day	==    86400 Seconds
		// 30 days	==  2592000 Seconds
		// 3 months ==  7776000 Seconds
		// 6 months == 15552000 Seconds


		// This part requires the server operator to enter his passphrase.
		// Which is why the server can't just fire it off automatically and
		// make a mint available to the client.  The client has to wait a day or
		// until the operator is able to run this script and type the passphrase.
		if (theNym.Loadx509CertAndPrivateKey())
		{								
			const time_t	CURRENT_TIME	= time(NULL), 
				VALID_TO		= CURRENT_TIME + 15552000,	// Tokens generated by this mint are valid from today until 6 months from today
				MINT_EXPIRATION	= CURRENT_TIME + 7776000;	// The mint itself will expire in 3 months from today, and be replaced with a new one.

			pMint->GenerateNewMint(nSeries, CURRENT_TIME, VALID_TO, MINT_EXPIRATION, ASSET_TYPE_ID, SERVER_ID,
				// penny, nickel, dime, quarter, $1, $5, $10, $20, $100, $1000
				theNym, 1, 5, 10, 25, 100, 500, 1000, 2000, 10000, 100000);
			// should be: 1, 2, 4,   8,  16,  32,   64,  128,   256,    512, 1024, 2048, 4096, 8192, 16384, 32768, 65536

			// ---------------------------------------

			//			OTString strFilename;// strPUBLICFilename;		
			//			strFilename.		Format("%s%s%s",		strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get());
			//			strPUBLICFilename.	Format("%s%s%s%sPUBLIC",strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get(), ".");

			if (!OTDataFolder::IsInitialized()) { OT_ASSERT(false); };

			OTString strServerFolder(""), strMintFolder("");

			if (!OTPaths::AppendFolder(strMintFolder,	OTDataFolder::Get(),OTFolders::Mint())) { OT_ASSERT(false); }; // mint/
			if (!OTPaths::AppendFolder(strServerFolder,	strMintFolder,		strServerID.Get())) { OT_ASSERT(false); }; // mint/serverID

			bool bFolderCreated;
			if (OTPaths::BuildFolderPath(strServerFolder,bFolderCreated))
			{
				// -------------------------------------------------------------------
				// This causes the next serialization to save the private, not just public, keys.
				pMint->SetSavePrivateKeys(); // <== PRIVATE MINT VERSION.

				pMint->SignContract(theNym);
				pMint->SaveContract();

				pMint->SaveMint();		// save the private mint file as: path/mints/server_id/Asset_TypeID (overwriting the last "current mint"...)
				pMint->SaveMint(strSeries.Get()); // save the private mint file as: path/mints/server_id/Asset_TypeID.nSeries (These accumulate.)

				// When the server needs to reference the "current" private keys, then it just loads the
				// mint without specifying the series number. Since this file is overwritten with each new 
				// mint, it is thus always the latest one.  (Similarly, the latest public is always asset_id.PUBLIC)
				// On the other hand, if I need to load the keys for a specific series, (since more than one may be
				// redeemable, even if only the latest one is being issued) then they are all also saved by series
				// number, which is not overwritten with each new mint, but accumulates.
				// That is why above, you see me save the mint twice in two different files, and below you see
				// it being saved with the .PUBLIC appending to the filename.

				//				pMint->SaveContract(OTFolders::Mint().Get(), strFilename.Get());  // save the mint file.

				// -------------------------------------------------------------------
				// Now I sign it again, to get the private keys out of there.
				pMint->ReleaseSignatures();
				pMint->SignContract(theNym);
				pMint->SaveContract();

				pMint->SaveMint(".PUBLIC");  // save the public mint file.
				//				pMint->SaveContract(OTFolders::Mint().Get(), strPUBLICFilename.Get());  // save the public mint file.

				nReturnVal = 1;

				OTLog::Output(0, "\nDone.\n\n");
			}
			else
				OTLog::Output(0, "\n\nError calling OTLog::ConfirmOrCreateFolder() for path/mints/server_id\n\n");
		}
		else
			OTLog::Output(0, "\n\nError calling theNym.Loadx509CertAndPrivateKey()\n\n");
	} // Mint file doesn't exist yet (therefore the above block creates it...)

	return nReturnVal;
}
예제 #2
0
int main (int argc, char * const argv[])
{
	if (argc < 3)
	{
		printf("Usage:  createmint server_user_id asset_type_id\n\n"
			   "For now, expiration dates are automatically set:\n"
			   "FROM: Today, Now.\n"
			   "TO: 6 months from now.\n\n"
			   "It is recommended that you issue a new series (create a new mint) every 3 months for each\n"
			   "asset type, so that there is a 3-month overlap. In the future, this will be configured inside\n"
			   "the contracts themselves.\n\n"
			   "Server user ID needs to match the Server User ID from notaryServer.xml\n"
			   "Asset Type ID needs to match the Asset ID (aka Hashed Contract ID) of the currency contract.\n\n");
		exit(1);
	}
	
	SSL_library_init();
	SSL_load_error_strings();

	OTString strServerID(argv[1]), strAssetTypeID(argv[2]);
	OTIdentifier ASSET_TYPE_ID(strAssetTypeID);
	
	
	OTString strMintPath;
	bool bFileIsPresent = false;		
	int nSeries = 0;
	
	for (nSeries = 0; nSeries < 1000; nSeries++)
	{
		struct stat st;

		strMintPath.Format("%s%smints%s%s.%d", 
									 OTLog::Path(), OTLog::PathSeparator(),
									 OTLog::PathSeparator(),
									 strAssetTypeID.Get(), nSeries);
		
		bFileIsPresent = (stat(strMintPath.Get(), &st) == 0);
		
		if (!bFileIsPresent)
			break;
	}
	
	// if bFileIsPresent is STILL true, that means we got all the way up to 1000 and the 
	// file was present every time.
	// Geez, there must be 1000 mints on this computer.  At one new Mint per 3 months,
	// that's 4 per year, that's 250 years already!!
	if (bFileIsPresent)
	{
		fprintf(stdout, "This program automatically finds the next series, up to 1000. You\n"
				"have reached 1000. You will have to change the source code of this\n"
				"program in order to continue. Sorry.\n");
		exit(1);
	}
	
	
	// nSeries now contains the number we need to use for the next series.
	// and strMintPath now contains the correct file path.
	
	OTMint * pMint = new OTMint(strAssetTypeID, strMintPath, strAssetTypeID);
	
	if (pMint && pMint->LoadContract())
	{
		printf("The mint already exists. Delete it first if you wish to re-create it.\n");
	}
	else 
	{
		fprintf(stderr, "Mint file does not yet exist, for series %d and asset type:\n%s\nCreating......\n", 
				nSeries, strAssetTypeID.Get());
		
		if (pMint)
		{	
			// TODO: read the denominations out of the asset contract itself, instead of hardcoding them here.
			
			
			// Calculate FROM as Today, Now, 
			// then calculate TO as 6 months from now, 
			// and EXPIRATION as 3 months from now.
			//
			// TODO: Let these numbers be configured either in server operator contract, or issuer contract.
			// In the meantime, 3 and 6 months are good enough.
			
			OTPseudonym theNym;
			theNym.SetIdentifier(strServerID);
			
			// 1 hour	==     3600 Seconds
			// 1 day	==    86400 Seconds
			// 30 days	==  2592000 Seconds
			// 3 months ==  7776000 Seconds
			// 6 months == 15552000 Seconds
			
			
			// This part requires the server operator to enter his passphrase.
			// Which is why the server can't just fire it off automatically and
			// make a mint available to the client.  The client has to wait a day or
			// until the operator is able to run this script and type the passphrase.
			if (theNym.Loadx509CertAndPrivateKey())
			{								
				const time_t	CURRENT_TIME	= time(NULL), 
								VALID_TO		= CURRENT_TIME + 15552000,	// Tokens generated by this mint are valid from today until 6 months from today
								MINT_EXPIRATION	= CURRENT_TIME + 7776000;	// The mint itself will expire in 3 months from today, and be replaced with a new one.
				
				pMint->GenerateNewMint(nSeries, CURRENT_TIME, VALID_TO, MINT_EXPIRATION,
														// penny, nickel, dime, quarter, $1, $5, $10, $20, $100, $1000
									   ASSET_TYPE_ID, theNym, 1, 5, 10, 25, 100, 500, 1000, 2000, 10000, 100000);
												// should be: 1, 2, 4,   8,  16,  32,   64,  128,   256,    512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
				
				pMint->SetSavePrivateKeys(); // This causes the next serialization to save the private, not just public, keys.
				pMint->SignContract(theNym);
				pMint->SaveContract(strMintPath.Get());  // save the mint file.
				
				// Now I sign it again, to get the private keys out of there.
				pMint->ReleaseSignatures();
				pMint->SignContract(theNym);
				strMintPath.Format("%s%smints%s%s.PUBLIC", OTLog::Path(), OTLog::PathSeparator(),
								   OTLog::PathSeparator(), strAssetTypeID.Get());
				pMint->SaveContract(strMintPath.Get());
				printf("Done.\n");
			}
			else {
				printf("Error calling theNym.Loadx509CertAndPrivateKey()\n");
			}
		}
		else 
		{
			fprintf(stdout, "Error allocating memory for new OTMint.\n");
		}
	}
	
	return 0;
}
예제 #3
0
// Lucre step 4: client unblinds token -- now it's ready for use.
bool OTToken::ProcessToken(const OTPseudonym & theNym, OTMint & theMint, OTToken & theRequest)
{
//		OTLog::vError("%s <bank public info> <private coin request> <signed coin request> <coin>\n",
	bool bReturnValue = false;
	
	// When the Mint has signed a token and sent it back to the client,
	// the client must unblind the token and set it as spendable. Thus,
	// this function is only performed on tokens in the signedToken state.
	if (OTToken::signedToken != m_State)
	{
		OTLog::Error("Signed token expected in OTToken::ProcessToken\n");
		return false;
	}
	
	// Lucre
    SetDumper(stderr);
    BIO *bioBank			= BIO_new(BIO_s_mem()); // input
    BIO *bioSignature		= BIO_new(BIO_s_mem()); // input
    BIO *bioPrivateRequest	= BIO_new(BIO_s_mem()); // input
    BIO *bioCoin			= BIO_new(BIO_s_mem()); // output
	
	// Get the bank's public key (decoded into strPublicMint)
	// and put it into bioBank so we can use it with Lucre.
	OTASCIIArmor ascPublicMint;
	theMint.GetPublic(ascPublicMint, GetDenomination());
	OTString strPublicMint(ascPublicMint);
	BIO_puts(bioBank, strPublicMint.Get());

	// Get the existing signature into a bio.
//	OTLog::vError("DEBUGGING, m_Signature: -------------%s--------------\n", m_Signature.Get());
	OTString strSignature(m_Signature);
	BIO_puts(bioSignature, strSignature.Get());
	
	// I need the Private coin request also. (Only the client has this private coin request data.)
	OTASCIIArmor thePrototoken;		// The server sets m_nChosenIndex when it signs the token.
	bool bFoundToken = theRequest.GetPrivatePrototoken(thePrototoken, m_nChosenIndex);
	
	if (bFoundToken)
	{
//		OTLog::vError("THE PRIVATE REQUEST ARMORED CONTENTS:\n------------------>%s<-----------------------\n",
//				thePrototoken.Get());
		
		// Decrypt the prototoken
		OTString strPrototoken;
		OTEnvelope theEnvelope(thePrototoken);
		theEnvelope.Open(theNym, strPrototoken); // todo check return value.
		
//		OTLog::vError("THE PRIVATE REQUEST CONTENTS:\n------------------>%s<-----------------------\n",
//				strPrototoken.Get());
		
		// copy strPrototoken to a BIO
		BIO_puts(bioPrivateRequest, strPrototoken.Get());
		
		// ------- Okay, the BIOs are all loaded.... let's process...
		
		PublicBank	bank(bioBank);
		CoinRequest	req(bioPrivateRequest);
		
		// TODO make sure I'm not leaking memory with these ReadNumbers
		// Probably need to be calling some free function for each one.
		
		// Apparently reading the request id here and then just discarding it...
		ReadNumber(bioSignature,"request=");
		
		// Versus the signature data, which is read into bnSignature apparently.
		BIGNUM * bnSignature	= ReadNumber(bioSignature,"signature=");
		DumpNumber("signature=", bnSignature);
		
		// Produce the final unblinded token in Coin coin, and write it to bioCoin...
		Coin coin; // Coin Request, processes into Coin, with Bank and Signature passed in.
		req.ProcessResponse(&coin, bank, bnSignature); // Notice still apparently "request" info is discarded.
		coin.WriteBIO(bioCoin);
		
		// convert bioCoin to a C-style string...
		char CoinBuffer[1024];   // todo stop hardcoding these string lengths
		int coinLen	= BIO_read(bioCoin, CoinBuffer, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
		
		if (coinLen)
		{
			// ...to OTString...
			OTString strCoin;	
			strCoin.Set(CoinBuffer, coinLen);
			
//			OTLog::vError("Processing token...\n%s\n", strCoin.Get());
			
			// ...to Envelope stored in m_ascSpendable (encrypted and base64-encoded)
			OTEnvelope theEnvelope;
			theEnvelope.Seal(theNym, strCoin);	// Todo check the return values on these two functions
			theEnvelope.GetAsciiArmoredData(m_ascSpendable); // Here's the final product.
			
//			OTLog::vError("NEW SPENDABLE token...\n--------->%s<----------------\n", m_ascSpendable.Get());

			// Now the coin is encrypted from here on out, and otherwise ready-to-spend.
			m_State			= OTToken::spendableToken;
			bReturnValue	= true;
			
			// Lastly, we free the signature data, which is no longer needed, and which could be
			// otherwise used to trace the token. (Which we don't want.)
			m_Signature.Release();
		}
		
	}
	// Todo log error here if the private prototoken is not found. (Very strange if so!!)
	//  else {}
	
	// Cleanup openssl resources.
	BIO_free_all(bioBank);	
	BIO_free_all(bioSignature);	
	BIO_free_all(bioPrivateRequest);	
	BIO_free_all(bioCoin);	

	return bReturnValue;	
}
예제 #4
0
// Lucre step 2 (client generates coin request)
// nDenomination must be one of the denominations supported by the mint.
// sets m_nTokenCount and populates the maps with prototokens (in ASCII-armored format.)
bool OTToken::GenerateTokenRequest(const OTPseudonym & theNym, OTMint & theMint, 
								   long lDenomination, int nTokenCount/*=OTToken::nMinimumPrototokenCount*/)
{		
	//	OTLog::vError("%s <bank public info> <coin request private output file> <coin request public output file>\n", argv[0]);

	if (OTToken::blankToken != m_State)
	{
		OTLog::Error("Blank token expected in OTToken::GenerateTokenRequest\n");
		return false;
	}
	
	// We are supposed to set these values here.
	// The server actually sets them again, for security reasons.
	// But we should still set them since server may choose to reject the request.
	SetSeriesAndExpiration(theMint.GetSeries(), theMint.GetValidFrom(), theMint.GetValidTo());
	
    SetDumper(stderr);
	
    BIO *bioBank		=	BIO_new(BIO_s_mem()); // Input. We must supply the bank's public lucre info
    BIO *bioCoin		=	BIO_new(BIO_s_mem()); // These two are output. We must write these bios, after
    BIO *bioPublicCoin	=	BIO_new(BIO_s_mem()); // the operation, back into some form we can use
	
	// This version base64-DECODES the ascii-armored string passed in,
	// and then sets the decoded plaintext string onto the string.
	//OTString::OTString(const OTASCIIArmor & strValue)
	OTASCIIArmor ascPublicMint;
	
	theMint.GetPublic(ascPublicMint, lDenomination);
	
//	OTLog::vError("DEBUG: OTToken  public asc: \n%s\n", ascPublicMint.Get());

	
	OTString strPublicMint(ascPublicMint);

//	OTLog::vError("DEBUG: OTToken  public str: \n%s\n", strPublicMint.Get());
	

	// Get the bank's public key (now decoded in strPublicMint)
	// and put it into bioBank so we can use it with Lucre.
	BIO_puts(bioBank, strPublicMint.Get());
	
	// Instantiate a PublicBank (Lucre) object.
	// We will use it to generate all the prototokens in the loop below.
    PublicBank bank;
    bank.ReadBIO(bioBank);
	
	Release();

	const int nFinalTokenCount = (nTokenCount < OTToken::nMinimumPrototokenCount) ? 
					OTToken::nMinimumPrototokenCount : nTokenCount; 
	
	// Token count is actually 1 (always) with Lucre, although this lib has potential to work with 
	// multiple proto-tokens, you can see this loop as though it always executes just once.
	for (int i = 0; i < nFinalTokenCount; i++)
	{
		CoinRequest req(bank);

		// write the private coin request to BIO
		req.WriteBIO(bioCoin);
		
		// write the public coin request to BIO
		((PublicCoinRequest *)&req)->WriteBIO(bioPublicCoin);
		
		// Convert the two bios to our format
		char privateCoinBuffer[4096], publicCoinBuffer[4096];   // todo stop hardcoding these string lengths
		int privatecoinLen	= BIO_read(bioCoin, privateCoinBuffer, 4000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason.
		int publiccoinLen	= BIO_read(bioPublicCoin, publicCoinBuffer, 4000); 
		
		if (privatecoinLen && publiccoinLen)
		{
			// With this, we have the Lucre public and private bank info converted to OTStrings
			OTString strPublicCoin;		strPublicCoin.Set(publicCoinBuffer, publiccoinLen);
			OTString strPrivateCoin;	strPrivateCoin.Set(privateCoinBuffer, privatecoinLen);
			
			OTASCIIArmor * pArmoredPublic	= new OTASCIIArmor(strPublicCoin);
			OTASCIIArmor * pArmoredPrivate	= new OTASCIIArmor();
			
			OT_ASSERT_MSG(((NULL != pArmoredPublic) && (NULL != pArmoredPrivate)), "ERROR: Unable to allocate memory in OTToken::GenerateTokenRequest\n");
			
			// Change the state. It's no longer a blank token, but a prototoken.
			m_State = OTToken::protoToken;

			// Seal the private coin info up into an encrypted Envelope 
			// and set it onto pArmoredPrivate (which was just added to our internal map, above.)
			OTEnvelope theEnvelope;
			theEnvelope.Seal(theNym, strPrivateCoin);	// Todo check the return values on these two functions
			theEnvelope.GetAsciiArmoredData(*pArmoredPrivate);
			
			m_mapPublic[i]	= pArmoredPublic;
			m_mapPrivate[i]	= pArmoredPrivate;

			m_nTokenCount = nFinalTokenCount;
			SetDenomination(lDenomination);
		}
		else {
			// Error condition
		}

		// Free the Private and Public coins and allocate them fresh, for the next iteration of the loop.
		BIO_free_all(bioCoin);	
		BIO_free_all(bioPublicCoin);

		bioCoin			=	BIO_new(BIO_s_mem());
		bioPublicCoin	=	BIO_new(BIO_s_mem());
	}
	
	
	// Cleanup openssl resources.
	BIO_free_all(bioBank);	
    BIO_free_all(bioCoin);	
    BIO_free_all(bioPublicCoin);
	
	return true;
}
예제 #5
0
// **** VERIFY THE TOKEN WHEN REDEEMED AT THE SERVER
// Lucre step 5: token verifies when it is redeemed by merchant.
// IMPORTANT: while stored on the client side, the tokens are
// encrypted to the client side nym. But when he redeems them to
// the server, he re-encrypts them first to the SERVER's public nym.
// So by the time it comes to verify, we are opening this envelope
// with the Server's Nym.
bool OTToken::VerifyToken(OTPseudonym & theNotary, OTMint & theMint)
{
	//OTLog::vError("%s <bank info> <coin>\n",argv[0]);
    SetDumper(stderr);
	
	if (OTToken::spendableToken != m_State)
	{
		OTLog::Error("Expected spendable token in OTToken::VerifyToken\n");
		return false;
	}
	
	// load the bank and coin info into the bios
	// The Mint private info is encrypted in m_ascPrivate. So I need to extract that
	// first before I can use it.
	OTEnvelope theEnvelope(m_ascSpendable);
	
	OTString strContents; // output from opening the envelope.
	// Decrypt the Envelope into strContents    
	if (!theEnvelope.Open(theNotary, strContents))
		return false; // todo log error, etc.
	
	// Verify that the series is correct...
	// (Otherwise, someone passed us the wrong Mint and the
	// thing won't verify anyway, since we'd have the wrong keys.)
	if (m_nSeries		!= theMint.GetSeries() ||
		// Someone might, however, in a clever attack, choose to leave
		// the series intact, but change the expiration dates, so that the
		// mint keys continue to work properly for this token, but then
		// when we check the date, it APPEARS good, when really the dates
		// were altered! To prevent this, we explicitly verify the series
		// information on the token against the same info on the mint,
		// BEFORE checking the date.
		m_VALID_FROM	!= theMint.GetValidFrom() ||
		m_VALID_TO		!= theMint.GetValidTo())
	{
		OTLog::vOutput(0, "Token series information doesn't match Mint series information!\n");
		return false;
	}
	
	// Verify whether token has expired...expiration date is validated here.
	// We know the series is correct or the key wouldn't verify below... and
	// we know that the dates are correct because we compared them against the
	// mint of that series above. So now we just make sure that the CURRENT date
	// and time is within the range described on the token.
	if (!VerifyCurrentDate())
	{
		OTLog::Output(0, "Token is expired!\n");
		return false;
	}
	
	// pass the cleartext Lucre spendable coin data to the Mint to be verified.
    if (theMint.VerifyToken(theNotary, strContents, GetDenomination()))  // Here's the boolean output: coin is verified!
	{
		OTLog::Output(0, "Token verified!\n");
		return true;
	}
	else {
		OTLog::Output(0, "Bad coin!\n");
		return false;
	}
}
예제 #6
0
int main (int argc, char * const argv[])
{
	if (argc < 5)
	{
		printf("\n\nUsage:  createmint  server_id  server_user_id  asset_type_id  full_path_to_data_folder\n\n"
			   "For now, expiration dates are automatically set:\n"
			   "-- FROM: Today, Now.\n"
			   "-- TO: 6 months from now.\n\n"
			   "It is recommended that you issue a new series (create a new mint) every 3 months for each\n"
			   "asset type, so that there is a 3-month overlap. In the future, this will be configured inside\n"
			   "the contracts themselves.\n\n"
			   "Server ID needs to match the Server ID from notaryServer.xml\n"
			   "Server user ID needs to match the Server User ID from notaryServer.xml\n"
			   "Asset Type ID needs to match the Asset ID (aka Hashed Contract ID) of the currency contract.\n"
			   "The path to the data folder is necessary for initialization of the OT library.\n\n");
		exit(1);
	}
	
	SSL_library_init();
	SSL_load_error_strings();

	// -----------------------------------------
	
	OTString		strServerID(argv[1]), strServerNymID(argv[2]), strAssetTypeID(argv[3]);
	OTIdentifier	ASSET_TYPE_ID(strAssetTypeID), SERVER_ID(strServerID);
	
	std::string strDataFolderPath(argv[4]), strWalletFile("wallet.xml");
	
	bool bSuccessInitDefault = OTDB::InitDefaultStorage(OTDB_DEFAULT_STORAGE, 
														OTDB_DEFAULT_PACKER, strDataFolderPath, strWalletFile);
		
	// -----------------------------------------
	
	OTString strMintPath;
	bool bFileIsPresent = false;		
	int nSeries = 0;
	
	for (nSeries = 0; nSeries < 1000; nSeries++)
	{
		struct stat st;

		strMintPath.Format("%s%s%s%s%s%s%s%s%d", 
						   OTLog::Path(), 
						   OTLog::PathSeparator(),
						   OTLog::MintFolder(),
						   OTLog::PathSeparator(),
						   strServerID.Get(),
						   OTLog::PathSeparator(),
						   strAssetTypeID.Get(), ".", nSeries);
		
		bFileIsPresent = (stat(strMintPath.Get(), &st) == 0);
		
		if (!bFileIsPresent)
			break;
	}
	
	// if bFileIsPresent is STILL true, that means we got all the way up to 1000 and the 
	// file was present every time.
	// Geez, there must be 1000 mints on this computer.  At one new Mint per 3 months,
	// that's 4 per year, that's 250 years already!!
	if (bFileIsPresent)
	{
		OTLog::Output(0, "This program automatically finds the next series, up to 1000. You\n"
				"have reached 1000. You will have to change the source code of this\n"
				"program in order to continue. Sorry.\n");
		exit(1);
	}
	
	
	// nSeries now contains the number we need to use for the next series.
	// and strMintPath now contains the correct file path.
	
	OTMint * pMint = new OTMint(strServerID, strServerNymID, strAssetTypeID);
	
	OTString strSeries; strSeries.Format("%s%d", ".", nSeries);
	//
	if ((NULL != pMint) && pMint->LoadMint(strSeries.Get()))
	{
		OTLog::Output(0, "The mint already exists. Delete it first if you wish to re-create it.\n");
	}
	else 
	{
		OTLog::vOutput(0, "Mint file does not (yet) exist for series %d and asset type:\n%s\n Creating......\n", 
				nSeries, strAssetTypeID.Get());
		
		if (pMint)
		{	
			// TODO: read the denominations out of the asset contract itself, instead of hardcoding them here.
			
			
			// Calculate FROM as Today, Now, 
			// then calculate TO as 6 months from now, 
			// and EXPIRATION as 3 months from now.
			//
			// TODO: Let these numbers be configured either in server operator contract, or issuer contract.
			// In the meantime, 3 and 6 months are good enough.
			
			OTPseudonym theNym;
			theNym.SetIdentifier(strServerNymID);
			
			// 1 hour	==     3600 Seconds
			// 1 day	==    86400 Seconds
			// 30 days	==  2592000 Seconds
			// 3 months ==  7776000 Seconds
			// 6 months == 15552000 Seconds
			
			
			// This part requires the server operator to enter his passphrase.
			// Which is why the server can't just fire it off automatically and
			// make a mint available to the client.  The client has to wait a day or
			// until the operator is able to run this script and type the passphrase.
			if (theNym.Loadx509CertAndPrivateKey())
			{								
				const time_t	CURRENT_TIME	= time(NULL), 
								VALID_TO		= CURRENT_TIME + 15552000,	// Tokens generated by this mint are valid from today until 6 months from today
								MINT_EXPIRATION	= CURRENT_TIME + 7776000;	// The mint itself will expire in 3 months from today, and be replaced with a new one.
				
				pMint->GenerateNewMint(nSeries, CURRENT_TIME, VALID_TO, MINT_EXPIRATION, ASSET_TYPE_ID, SERVER_ID,
														// penny, nickel, dime, quarter, $1, $5, $10, $20, $100, $1000
													theNym, 1, 5, 10, 25, 100, 500, 1000, 2000, 10000, 100000);
												// should be: 1, 2, 4,   8,  16,  32,   64,  128,   256,    512, 1024, 2048, 4096, 8192, 16384, 32768, 65536
				
				// ---------------------------------------
				
//				OTString strFilename;// strPUBLICFilename;		
//				strFilename.		Format("%s%s%s",		strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get());
//				strPUBLICFilename.	Format("%s%s%s%sPUBLIC",strServerID.Get(), OTLog::PathSeparator(), strAssetTypeID.Get(), ".");
				
				OTString strServerFolder;
				strServerFolder.Format("%s%s%s", OTLog::MintFolder(), OTLog::PathSeparator(), strServerID.Get());
				
				if (OTLog::ConfirmOrCreateFolder(OTLog::MintFolder()) &&
					OTLog::ConfirmOrCreateFolder(strServerFolder.Get()))
				{
					// -------------------------------------------------------------------
					// This causes the next serialization to save the private, not just public, keys.
					pMint->SetSavePrivateKeys(); // <== PRIVATE MINT VERSION.
					
					pMint->SignContract(theNym);
					pMint->SaveContract();
					
					pMint->SaveMint();		// save the private mint file as: path/mints/server_id/Asset_TypeID (overwriting the last "current mint"...)
					pMint->SaveMint(strSeries.Get()); // save the private mint file as: path/mints/server_id/Asset_TypeID.nSeries (These accumulate.)
					
					// When the server needs to reference the "current" private keys, then it just loads the
					// mint without specifying the series number. Since this file is overwritten with each new 
					// mint, it is thus always the latest one.  (Similarly, the latest public is always asset_id.PUBLIC)
					// On the other hand, if I need to load the keys for a specific series, (since more than one may be
					// redeemable, even if only the latest one is being issued) then they are all also saved by series
					// number, which is not overwritten with each new mint, but accumulates.
					// That is why above, you see me save the mint twice in two different files, and below you see
					// it being saved with the .PUBLIC appending to the filename.
					
//					pMint->SaveContract(OTLog::MintFolder(), strFilename.Get());  // save the mint file.
					
					// -------------------------------------------------------------------
					// Now I sign it again, to get the private keys out of there.
					pMint->ReleaseSignatures();
					pMint->SignContract(theNym);
					pMint->SaveContract();
					
					pMint->SaveMint(".PUBLIC");  // save the public mint file.
//					pMint->SaveContract(OTLog::MintFolder(), strPUBLICFilename.Get());  // save the public mint file.
					
					OTLog::Output(0, "Done.\n");
				}
				else
					OTLog::Output(0, "Error calling OTLog::ConfirmOrCreateFolder() for path/mints/server_id\n");
			}
			else
				OTLog::Output(0, "Error calling theNym.Loadx509CertAndPrivateKey()\n");
		}
		else 
		{
			OTLog::Output(0, "Error allocating memory for new OTMint.\n");
		}
	}
	
	return 0;
}