示例#1
0
// 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;
    }
}
// Take all the tokens from a purse and add them to this purse.
// Don't allow duplicates.
//
bool OTPurse::Merge(OTPseudonym & theOldNym, OTPseudonym & theNewNym, OTPurse & theNewPurse)
{
	mapOfTokenPointers theMap;
	
	while (this->Count() > 0) 
	{
		OTToken * pToken = this->Pop(theOldNym);
		OT_ASSERT_MSG(NULL != pToken, "OTPurse::Merge: Assert: NULL != this->Pop(theOldNym) \n");
				
		const OTASCIIArmor & ascTokenID = pToken->GetSpendable();
		
        std::list<mapOfTokenPointers::iterator> listOfTokenMapIterators;
        
		// I just popped a Token off of *this. Let's see if it's in my temporary map...
		// If it's already there, then just delete it (duplicate).
		//
		FOR_EACH(mapOfTokenPointers, theMap)
		{
			OTToken * pTempToken = (*it).second;
			OT_ASSERT(NULL != pTempToken);
			
			const OTASCIIArmor & ascTempTokenID = pTempToken->GetSpendable();
			
			// --------------------------------
			// It's already there. Delete the one that's already there.
			// (That way we can add it after, whether it was there originally or not.)
			if (ascTempTokenID == ascTokenID)
			{
                listOfTokenMapIterators.push_back(it);
//				theMap.erase(it);
//				delete pTempToken;
//              pTempToken = NULL;
				//break; // In case there are multiple duplicates, not just one.
			}
		}
        while (listOfTokenMapIterators.size() > 0)
        {
            OTToken * pTempToken = (listOfTokenMapIterators.back())->second;
            theMap.erase(listOfTokenMapIterators.back());
            delete pTempToken;
            pTempToken = NULL;
            listOfTokenMapIterators.pop_back();
        }
        
		// Now we know there aren't any duplicates on the temporary map, let's add the token to it.
		std::string theKey = ascTokenID.Get();		
		theMap.insert(std::pair<std::string, OTToken*>(theKey, pToken));
	}
示例#3
0
// 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;
}
示例#5
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;	
}
示例#6
0
// Take all the tokens from a purse and add them to this purse.
// Don't allow duplicates.
//
bool OTPurse::Merge(OTPseudonym & theNym, OTPurse & theNewPurse)
{
    mapOfTokenPointers theMap;

    while (this->Count() > 0)
    {
        OTToken * pToken = this->Pop(theNym);

        OT_ASSERT(NULL != pToken);

        const OTASCIIArmor & ascTokenID = pToken->GetSpendable();

        // I just popped a Token off of *this. Let's see if it's in my temporary map...
        // If it's already there, then just delete it (duplicate).
        for (mapOfTokenPointers::iterator ii = theMap.begin(); ii != theMap.end(); ++ii)
        {
            OTToken * pTempToken = (*ii).second;

            OT_ASSERT(NULL != pTempToken);

            const OTASCIIArmor & ascTempTokenID = pTempToken->GetSpendable();

            // --------------------------------
            // It's already there. Delete the one that's already there.
            // (That way we can add it after, whether it was there originally or not.)
            if (ascTempTokenID == ascTokenID)
            {
                theMap.erase(ii);
                delete pTempToken;
                //break; // In case there are multiple duplicates, not just one.
            }
        }

        // Now we know there aren't any duplicates on the temporary map, let's add the token to it.
        std::string theKey = ascTokenID.Get();
        theMap.insert(std::pair<std::string, OTToken*>(theKey, pToken));
    }

    // At this point, all of the tokens on *this have been popped, and added
    // to the temporary map as token pointers, with any duplicates removed.

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

    // Basically now I just want to do the exact same thing with the other purse.

    while (theNewPurse.Count() > 0)
    {
        OTToken * pToken = theNewPurse.Pop(theNym); // TODO:  This isn't necessarily the right nym. Need to fix purse to allow dummy nyms.

        OT_ASSERT(NULL != pToken);

        const OTASCIIArmor & ascTokenID = pToken->GetSpendable();

        // I just popped a Token off of theNewPurse. Let's see if it's in my temporary map...
        // If it's already there, then just delete it (duplicate).
        for (mapOfTokenPointers::iterator ii = theMap.begin(); ii != theMap.end(); ++ii)
        {
            OTToken * pTempToken = (*ii).second;

            OT_ASSERT(NULL != pTempToken);

            const OTASCIIArmor & ascTempTokenID = pTempToken->GetSpendable();

            // --------------------------------
            // It's already there. Delete the one that's already there.
            // (That way we can add it after, whether it was there originally or not.)
            if (ascTempTokenID == ascTokenID)
            {
                theMap.erase(ii);
                delete pTempToken;
                //break; // In case there are multiple duplicates, not just one.
            }
        }

        // Now we know there aren't any duplicates on the temporary map, let's add the token to it.
        std::string theKey = ascTokenID.Get();
        theMap.insert(std::pair<std::string, OTToken*>(theKey, pToken));
    }

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

    // At this point, all of the tokens on *this AND theNewPurse have been popped, and added
    // to the temporary map as token pointers, with any duplicates removed.

    // Now I just loop through that same map, and Push ALL of those tokens back onto *this.

    for (mapOfTokenPointers::iterator ii = theMap.begin(); ii != theMap.end(); ++ii)
    {
        OTToken * pToken = (*ii).second;

        OT_ASSERT(NULL != pToken);

        bool bPush = this->Push(theNym, *pToken); // purse makes it's own copy of the token into string form.

        if (!bPush)
            OTLog::Error("Failure pushing token in OTPurse::Merge.\n");
    }

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

    // Next I clean up all the tokens out of the temporary map, since they will leak otherwise.

    while (!theMap.empty())
    {
        OTToken * pToken = theMap.begin()->second;

        OT_ASSERT(NULL != pToken);

        delete pToken;
        pToken = NULL;

        theMap.erase(theMap.begin());
    }

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

    return true;
}