// Use a local variable for theToken, do NOT allocate it on the heap // unless you are going to delete it yourself. // Repeat: OTPurse is NOT responsible to delete it. We create our OWN internal // variable here, new that, and add it to the stack. We do not add the one passed in. bool OTPurse::Push(const OTPseudonym & theOwner, const OTToken & theToken) { if (theToken.GetAssetID() == m_AssetID) { OTString strToken(theToken); // OTLog::vError("$$$$$$$$$$$$$$$ PUSHING token to Purse:\n---------->%s<-------------\n", strToken.Get()); OTEnvelope theEnvelope; theEnvelope.Seal(theOwner, strToken); OTASCIIArmor * pArmor = new OTASCIIArmor(theEnvelope); // OTLog::vError("$$$$$$$$$$$$$$$ PUSHING token to Purse in armored form:\n---------->%s<-------------\n", // pArmor->Get()); m_dequeTokens.push_front(pArmor); // We keep track of the purse's total value. m_lTotalValue += theToken.GetDenomination(); return true; } else { OTString strPurseAssetType(m_AssetID), strTokenAssetType(theToken.GetAssetID()); OTLog::vError("ERROR: Tried to push token with wrong asset type in OTPurse::Push\nPurse Asset Type:\n%s\n" "Token Asset Type:\n%s\n", strPurseAssetType.Get(), strTokenAssetType.Get()); return false; } }
// Hypocritically (compared to Push) in the case of Pop(), we DO // allocate a OTToken and return the pointer. The caller IS // responsible to delete it when he's done with it. // // The apparent discrepancy is due to the fact that internally, // we aren't storing the token object but an encrypted string of it. // But this is hidden from the user of the purse, who perceives only // that he is passing tokens in and getting them back out again. OTToken * OTPurse::Pop(const OTPseudonym & theOwner) { if (m_dequeTokens.empty()) return NULL; // Grab a copy of the pointer and remove it from the deque OTASCIIArmor * pArmor = m_dequeTokens.front(); m_dequeTokens.pop_front(); // OTLog::vError("$$$$$$$$$$$$$$ ARMORED TEXT in PURSE POP:\n--------->%s<-----------\n", pArmor->Get()); // Copy the token contents into an Envelope, and delete the pointer. OTEnvelope theEnvelope(*pArmor); delete pArmor; pArmor = NULL; // Open the envelope into a string. OTString strToken; theEnvelope.Open(theOwner, strToken); // OTLog::vError("$$$$$$$$$$$$$$$ OPENED ENVELOPE TEXT in PURSE POP:\n--------->%s<-----------\n", strToken.Get()); // Create a new token with the same server and asset IDs as this purse. OTToken * pToken = new OTToken(*this); OT_ASSERT(NULL != pToken); // Load the token from the string we got out of the envelope. pToken->LoadContractFromString(strToken); if (pToken->GetAssetID() != m_AssetID || pToken->GetServerID() != m_ServerID) { delete pToken; pToken = NULL; OTLog::Error("ERROR: Token with wrong asset type in OTPurse::Pop\n"); } else { // We keep track of the purse's total value. m_lTotalValue -= pToken->GetDenomination(); } // CALLER is responsible to delete this token. return pToken; }
// Lucre step 3: the mint signs the token // bool OTMint_Lucre::SignToken(OTPseudonym & theNotary, OTToken & theToken, OTString & theOutput, int32_t nTokenIndex) { bool bReturnValue = false; //OTLog::Error("%s <bank file> <coin request> <coin signature> [<signature repeats>]\n", _OT_Lucre_Dumper setDumper; // OTLog::vError("OTMint::SignToken!!\nnTokenIndex: %d\n Denomination: %lld\n", nTokenIndex, theToken.GetDenomination()); OpenSSL_BIO bioBank = BIO_new(BIO_s_mem()); // input OpenSSL_BIO bioRequest = BIO_new(BIO_s_mem()); // input OpenSSL_BIO bioSignature = BIO_new(BIO_s_mem()); // output OTASCIIArmor thePrivate; GetPrivate(thePrivate, theToken.GetDenomination()); // The Mint private info is encrypted in m_mapPrivates[theToken.GetDenomination()]. // So I need to extract that first before I can use it. OTEnvelope theEnvelope(thePrivate); OTString strContents; // output from opening the envelope. // Decrypt the Envelope into strContents if (!theEnvelope.Open(theNotary, strContents)) return false; // copy strContents to a BIO BIO_puts(bioBank, strContents.Get()); // OTLog::vError("BANK CONTENTS:\n%s--------------------------------------\n", strContents.Get()); // Instantiate the Bank with its private key Bank bank(bioBank); // OTLog::vError("BANK INSTANTIATED.--------------------------------------\n"); // I need the request. the prototoken. OTASCIIArmor ascPrototoken; bool bFoundToken = theToken.GetPrototoken(ascPrototoken, nTokenIndex); if (bFoundToken) { // base64-Decode the prototoken OTString strPrototoken(ascPrototoken); // OTLog::vError("\n--------------------------------------\nDEBUG: PROTOTOKEN CONTENTS:\n" // "-----------------%s---------------------\n", strPrototoken.Get() ); // copy strPrototoken to a BIO BIO_puts(bioRequest, strPrototoken.Get()); // Load up the coin request from the bio (the prototoken) PublicCoinRequest req(bioRequest); // OTLog::Error("PROTOTOKEN INSTANTIATED.--------------------------------------\n"); // Sign it with the bank we previously instantiated. // results will be in bnSignature (BIGNUM) BIGNUM * bnSignature = bank.SignRequest(req); if (NULL == bnSignature) { OTLog::Error("MAJOR ERROR!: Bank.SignRequest failed in OTMint_Lucre::SignToken\n"); } else { // OTLog::Error("BANK.SIGNREQUEST SUCCESSFUL.--------------------------------------\n"); // Write the request contents, followed by the signature contents, // to the Signature bio. Then free the BIGNUM. req.WriteBIO(bioSignature); // the original request contents DumpNumber(bioSignature,"signature=", bnSignature); // the new signature contents BN_free(bnSignature); // Read the signature bio into a C-style buffer... char sig_buf[1024]; // todo stop hardcoding these string lengths // memset(sig_buf, 0, 1024); // zero it out. (I had this commented out, but the size was 2048, so maybe it's safe now at 1024.) int32_t sig_len = BIO_read(bioSignature, sig_buf, 1000); // cutting it a little short on purpose, with the buffer. Just makes me feel more comfortable for some reason. // Add the null terminator by hand (just in case.) sig_buf[sig_len] = '\0'; if (sig_len) { // *********************************************** // OTLog::vError("\n--------------------------------------\n" // "*** Siglen is %d. sig_str_len is %d.\nsig buf:\n------------%s------------\nLAST " // "CHARACTER IS '%c' SECOND TO LAST CHARACTER IS '%c'\n", // sig_len, sig_str_len, sig_buf, sig_buf[sig_str_len-1], sig_buf[sig_str_len-2]); // Copy the original coin request into the spendable field of the token object. // (It won't actually be spendable until the client processes it, though.) theToken.SetSpendable(ascPrototoken); // OTLog::vError("*** SPENDABLE:\n-----------%s---------------------\n", ascPrototoken.Get()); // Base64-encode the signature contents into theToken.m_Signature. OTString strSignature(sig_buf); // strSignature.Set(sig_buf, sig_len-1); // sig_len includes null terminator, whereas Set() adds 1 for it. // OTLog::vError("SIGNATURE:\n--------------------%s" // "------------------\n", strSignature.Get()); // Here we pass the signature back to the caller. // He will probably set it onto the token. theOutput.Set(sig_buf, sig_len); bReturnValue = true; // This is also where we set the expiration date on the token. // The client should have already done this, but we are explicitly // setting the values here to prevent any funny business. theToken.SetSeriesAndExpiration(m_nSeries, m_VALID_FROM, m_VALID_TO); } } } return bReturnValue; }