int main(int argc,char **argv) { if(argc != 4) { fprintf(stderr,"%s <bank public info> <coin request> <public coin requet>\n",argv[0]); exit(1); } const char *szBankFile=argv[1]; const char *szCoinFile=argv[2]; const char *szPublicCoinFile=argv[3]; SetDumper(stderr); BIO *bioBank=BIO_new_file(szBankFile,"r"); BIO *bioCoin=BIO_new_file(szCoinFile,"w"); BIO *bioPublicCoin=BIO_new_file(szPublicCoinFile,"w"); PublicBank bank; bank.ReadBIO(bioBank); CoinRequest req(bank); req.WriteBIO(bioCoin); ((PublicCoinRequest *)&req)->WriteBIO(bioPublicCoin); }
// 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; }