/// Remove a transaction number from the Nym record once it's officially /// used/spent. bool Transactor::removeTransactionNumber(Nym& theNym, const int64_t& lTransactionNumber, bool bSave) { Identifier NYM_ID(theNym), NOTARY_NYM_ID(server_->m_nymServer); // If theNym has the same ID as server_->m_nymServer, then we'll use // server_->m_nymServer // instead of theNym. (Since it's the same nym anyway, we'll stick to the // one we already loaded so any changes don't get overwritten later.) Nym* pNym = nullptr; if (NYM_ID == NOTARY_NYM_ID) pNym = &server_->m_nymServer; else pNym = &theNym; bool bRemoved = false; if (bSave) bRemoved = pNym->RemoveTransactionNum( server_->m_nymServer, server_->m_strNotaryID, lTransactionNumber); // the version that passes in a signer nym -- // saves to local storage. else bRemoved = pNym->RemoveTransactionNum( server_->m_strNotaryID, lTransactionNumber); // the version that doesn't save. return bRemoved; }
bool OTEnvelope::Seal(const Nym& theRecipient, const String& theInput) { String strNymID; mapOfAsymmetricKeys theKeys; theRecipient.GetIdentifier(strNymID); theKeys.insert(std::pair<std::string, OTAsymmetricKey*>( strNymID.Get(), const_cast<OTAsymmetricKey*>(&(theRecipient.GetPublicEncrKey())))); return Seal(theKeys, theInput); }
bool Transactor::issueNextTransactionNumberToNym(Nym& theNym, int64_t& lTransactionNumber) { Identifier NYM_ID(theNym), NOTARY_NYM_ID(server_->m_nymServer); // If theNym has the same ID as server_->m_nymServer, then we'll use // server_->m_nymServer // instead of theNym. (Since it's the same nym anyway, we'll stick to the // one we already loaded so any changes don't get overwritten later.) Nym* pNym = nullptr; if (NYM_ID == NOTARY_NYM_ID) pNym = &server_->m_nymServer; else pNym = &theNym; if (!issueNextTransactionNumber(lTransactionNumber)) { return false; } // Each Nym stores the transaction numbers that have been issued to it. // (On client AND server side.) // // So whenever the server issues a new number, it's to a specific Nym, then // it is recorded in his Nym file before being sent to the client (where it // is also recorded in his Nym file.) That way the server always knows // which // numbers are valid for each Nym. if (!pNym->AddTransactionNum(server_->m_nymServer, server_->m_strNotaryID, transactionNumber_, true)) { Log::Error("Error adding transaction number to Nym file.\n"); transactionNumber_--; server_->mainFile_.SaveMainFile(); // Save it back how it was, since // we're not // issuing this // number after all. return false; } // SUCCESS? // Now the server main file has saved the latest transaction number, // NOW we set it onto the parameter and return true. lTransactionNumber = transactionNumber_; return true; }
String::String(Nym& theValue) : length_(0) , position_(0) , data_(nullptr) { // Initialize(); theValue.SavePseudonym(*this); }
bool OTEnvelope::Seal(setOfNyms& theRecipients, const String& theInput) { mapOfAsymmetricKeys RecipPubKeys; // Loop through theRecipients, and add the public key of each one to a set // of keys. for (auto& it : theRecipients) { Nym* pNym = it; OT_ASSERT_MSG(nullptr != pNym, "OTEnvelope::Seal: Assert: nullptr pseudonym pointer."); String strNymID; pNym->GetIdentifier(strNymID); RecipPubKeys.insert(std::pair<std::string, OTAsymmetricKey*>( strNymID.Get(), const_cast<OTAsymmetricKey*>(&(pNym->GetPublicEncrKey())))); } if (RecipPubKeys.empty()) return false; return Seal(RecipPubKeys, theInput); }
/// Transaction numbers are now stored in the nym file (on client and server /// side) for whichever nym /// they were issued to. This function verifies whether or not the transaction /// number is present and valid /// for any specific nym (i.e. for the nym passed in.) bool Transactor::verifyTransactionNumber( Nym& theNym, const int64_t& lTransactionNumber) // passed by // reference for // speed, but not a // return value. { Identifier NYM_ID(theNym), NOTARY_NYM_ID(server_->m_nymServer); // If theNym has the same ID as server_->m_nymServer, then we'll use // server_->m_nymServer // instead of theNym. (Since it's the same nym anyway, we'll stick to the // one we already loaded so any changes don't get overwritten later.) Nym* pNym = nullptr; if (NYM_ID == NOTARY_NYM_ID) pNym = &server_->m_nymServer; else pNym = &theNym; if (pNym->VerifyTransactionNum(server_->m_strNotaryID, lTransactionNumber)) return true; else { const String strNymID(NYM_ID); const String strIssued( pNym->VerifyIssuedNum(server_->m_strNotaryID, lTransactionNumber) ? "(However, that number IS issued to that Nym... He must have " "already used it.)\n" : "(In fact, that number isn't even issued to that Nym, though " "perhaps it was at some time in the past?)\n"); Log::vError("%s: %" PRId64 " not available for Nym %s to use. \n%s", __FUNCTION__, // " Oh, and FYI, tangentially, the // current Trns# counter is: %ld\n", lTransactionNumber, strNymID.Get(), strIssued.Get()); // transactionNumber_); } return false; }
/// Remove an issued number from the Nym record once that nym accepts the /// receipt from his inbox. bool Transactor::removeIssuedNumber(Nym& theNym, const int64_t& lTransactionNumber, bool bSave) { Identifier NYM_ID(theNym), NOTARY_NYM_ID(server_->m_nymServer); // If theNym has the same ID as server_->m_nymServer, then we'll use // server_->m_nymServer // instead of theNym. (Since it's the same nym anyway, we'll stick to the // one we already loaded so any changes don't get overwritten later.) Nym* pNym = nullptr; if (NYM_ID == NOTARY_NYM_ID) pNym = &server_->m_nymServer; else pNym = &theNym; bool bRemoved = pNym->RemoveIssuedNum(server_->m_nymServer, server_->m_strNotaryID, lTransactionNumber, bSave); return bRemoved; }
// This is called by OTCronItem::HookRemovalFromCron // (After calling this method, HookRemovalFromCron then calls // onRemovalFromCron.) // void OTTrade::onFinalReceipt(OTCronItem& origCronItem, const int64_t& newTransactionNumber, Nym& originator, Nym* remover) { const char* szFunc = "OTTrade::onFinalReceipt"; OTCron* cron = GetCron(); OT_ASSERT(cron != nullptr); Nym* serverNym = cron->GetServerNym(); OT_ASSERT(serverNym != nullptr); // First, we are closing the transaction number ITSELF, of this cron item, // as an active issued number on the originating nym. (Changing it to // CLOSED.) // // Second, we're verifying the CLOSING number, and using it as the closing // number // on the FINAL RECEIPT (with that receipt being "InReferenceTo" // GetTransactionNum()) // const int64_t openingNumber = origCronItem.GetTransactionNum(); const int64_t closingAssetNumber = (origCronItem.GetCountClosingNumbers() > 0) ? origCronItem.GetClosingTransactionNoAt(0) : 0; const int64_t closingCurrencyNumber = (origCronItem.GetCountClosingNumbers() > 1) ? origCronItem.GetClosingTransactionNoAt(1) : 0; const String notaryID(GetNotaryID()); // The marketReceipt ITEM's NOTE contains the UPDATED TRADE. // And the **UPDATED OFFER** is stored on the ATTACHMENT on the **ITEM.** // // BUT!!! This is not a marketReceipt Item, is it? ***This is a finalReceipt // ITEM!*** // I'm reversing note and attachment for finalReceipt, with the // intention of // eventually reversing them for marketReceipt as well. (Making them all in // line with paymentReceipt.) // // WHY? Because I want a standard convention: // 1. ORIGINAL (user-signed) Cron Items are always stored "in // reference to" on cron receipts in the Inbox (an OTTransaction). // 2. The UPDATED VERSION of that same cron item (a trade or // payment plan) is stored in the ATTACHMENT on the OTItem member. // 3. ADDITIONAL INFORMATION is stored in the NOTE field of the // OTItem member. // // Unfortunately, marketReceipt doesn't adhere to this convention, as it // stores the Updated Cron Item (the trade) in // the note instead of the attachment, and it stores the updated Offer (the // additional info) in the attachment instead // of the note. // Perhaps this is for the best -- it will certainly kick out any accidental // confusions between marketReceipt and finalReceipt! // todo: switch marketReceipt over to be like finalReceipt as described in // this paragraph. // // Once everything is consistent on the above convention -- starting here // and now with finalReceipt -- then we will ALWAYS // be able to count on a Cron Item being in the Transaction Item's // Attachment! We can load it using the existing factory class, // without regard to type, KNOWING it's a cron item every time. // todo: convert marketReceipt to do the same. // The finalReceipt Item's ATTACHMENT contains the UPDATED Cron Item. // (With the SERVER's signature on it!) // String updatedCronItem(*this); String* attachment = &updatedCronItem; // the Updated TRADE. String updatedOffer; String* note = nullptr; // the updated Offer (if available.) if (offer_) { offer_->SaveContractRaw(updatedOffer); note = &updatedOffer; } const String strOrigCronItem(origCronItem); Nym theActualNym; // unused unless it's really not already loaded. // (use actualNym.) // The OPENING transaction number must still be signed-out. // It is this act of placing the final receipt, which then finally closes // the opening number. // The closing number, by contrast, is not closed out until the final // Receipt is ACCEPTED // (which happens in a "process inbox" transaction.) // if ((openingNumber > 0) && originator.VerifyIssuedNum(notaryID, openingNumber)) { // The Nym (server side) stores a list of all opening and closing cron // #s. // So when the number is released from the Nym, we also take it off that // list. // std::set<int64_t>& idSet = originator.GetSetOpenCronItems(); idSet.erase(openingNumber); originator.RemoveIssuedNum(*serverNym, notaryID, openingNumber, false); // bSave=false originator.SaveSignedNymfile(*serverNym); // forcing a save here, // since multiple things // have changed. const Identifier& actualNymId = GetSenderNymID(); Nym* actualNym = nullptr; // use this. DON'T use theActualNym. if ((serverNym != nullptr) && serverNym->CompareID(actualNymId)) actualNym = serverNym; else if (originator.CompareID(actualNymId)) actualNym = &originator; else if ((remover != nullptr) && remover->CompareID(actualNymId)) actualNym = remover; else // We couldn't find the Nym among those already loaded--so we have // to load { // it ourselves (so we can update its NymboxHash value.) theActualNym.SetIdentifier(actualNymId); if (!theActualNym.LoadPublicKey()) // Note: this step may be // unnecessary since we // are only updating his // Nymfile, not his key. { String strNymID(actualNymId); otErr << szFunc << ": Failure loading public key for Nym : " << strNymID << ". " "(To update his NymboxHash.) \n"; } else if (theActualNym.VerifyPseudonym() && // this line may be // unnecessary. theActualNym.LoadSignedNymfile( *serverNym)) // ServerNym here is not theActualNym's // identity, but merely the signer on // this file. { otLog3 << szFunc << ": Loading actual Nym, since he wasn't already loaded. " "(To update his NymboxHash.)\n"; actualNym = &theActualNym; // <===== } else { String strNymID(actualNymId); otErr << szFunc << ": Failure loading or verifying Actual Nym public key: " << strNymID << ". " "(To update his NymboxHash.)\n"; } } if (!DropFinalReceiptToNymbox(GetSenderNymID(), newTransactionNumber, strOrigCronItem, note, attachment, actualNym)) { otErr << szFunc << ": Failure dropping receipt into nymbox.\n"; } } else { otErr << szFunc << ": Problem verifying Opening Number when calling " "VerifyIssuedNum(openingNumber)\n"; } // ASSET ACCT // if ((closingAssetNumber > 0) && originator.VerifyIssuedNum(notaryID, closingAssetNumber)) { DropFinalReceiptToInbox( GetSenderNymID(), GetSenderAcctID(), newTransactionNumber, closingAssetNumber, // The closing transaction number to put on the // receipt. strOrigCronItem, note, attachment); } else { otErr << szFunc << ": Failed verifying " "closingAssetNumber=origCronItem." "GetClosingTransactionNoAt(0)>0 && " "originator.VerifyTransactionNum(closingAssetNumber)\n"; } // CURRENCY ACCT // if ((closingCurrencyNumber > 0) && originator.VerifyIssuedNum(notaryID, closingCurrencyNumber)) { DropFinalReceiptToInbox( GetSenderNymID(), GetCurrencyAcctID(), newTransactionNumber, closingCurrencyNumber, // closing transaction number for the // receipt. strOrigCronItem, note, attachment); } else { otErr << szFunc << ": Failed verifying " "closingCurrencyNumber=origCronItem." "GetClosingTransactionNoAt(1)>0 " "&& " "originator.VerifyTransactionNum(closingCurrencyNumber)\n"; } // the RemoveIssued call means the original transaction# (to find this cron // item on cron) is now CLOSED. // But the Transaction itself is still OPEN. How? Because the CLOSING number // is still signed out. // The closing number is also USED, since the NotarizePaymentPlan or // NotarizeMarketOffer call, but it // remains ISSUED, until the final receipt itself is accepted during a // process inbox. // // if (bDroppedReceiptAssetAcct || bDroppedReceiptCurrencyAcct) // ASSET // ACCOUNT and CURRENCY ACCOUNT // { // This part below doesn't happen until you ACCEPT the finalReceipt (when // processing your inbox.) // // if (bDroppedReceiptAssetAcct) // originator.RemoveIssuedNum(notaryID, closingAssetNumber, // true); //bSave=false // else if (bDroppedReceiptCurrencyAcct) // originator.RemoveIssuedNum(notaryID, // closingCurrencyNumber, true); //bSave=false // } // else // { // otErr << "OTTrade::onFinalReceipt: Failure dropping receipt into // asset or currency inbox.\n"; // } // QUESTION: Won't there be Cron Items that have no asset account at all? // In which case, there'd be no need to drop a final receipt, but I don't // think // that's the case, since you have to use a transaction number to get onto // cron // in the first place. }
/// See if nym has rights to remove this item from Cron. /// bool OTTrade::CanRemoveItemFromCron(Nym& nym) { // I don't call the parent class' version of this function, in the case of // OTTrade, // since it would just be redundant. // You don't just go willy-nilly and remove a cron item from a market unless // you check first // and make sure the Nym who requested it actually has said trans# (and 2 // related closing #s) // signed out to him on his last receipt... // if (!nym.CompareID(GetSenderNymID())) { otLog5 << "OTTrade::CanRemoveItem: nym is not the originator of " "this CronItem. " "(He could be a recipient though, so this is normal.)\n"; return false; } // By this point, that means nym is DEFINITELY the originator (sender)... else if (GetCountClosingNumbers() < 2) { otOut << "OTTrade::CanRemoveItem Weird: Sender tried to remove a market " "trade; expected at " "least 2 closing numbers to be available--that weren't. (Found " << GetCountClosingNumbers() << ").\n"; return false; } const String notaryID(GetNotaryID()); if (!nym.VerifyIssuedNum(notaryID, GetAssetAcctClosingNum())) { otOut << "OTTrade::CanRemoveItemFromCron: Closing number didn't verify " "for asset account.\n"; return false; } if (!nym.VerifyIssuedNum(notaryID, GetCurrencyAcctClosingNum())) { otOut << "OTTrade::CanRemoveItemFromCron: Closing number didn't verify " "for currency account.\n"; return false; } // By this point, we KNOW nym is the sender, and we KNOW there are the // proper number of transaction // numbers available to close. We also know that this cron item really was // on the cron object, since // that is where it was looked up from, when this function got called! So // I'm pretty sure, at this point, // to authorize removal, as long as the transaction num is still issued to // nym (this check here.) // return nym.VerifyIssuedNum(notaryID, GetOpeningNum()); // Normally this will be all we need to check. The originator will have the // transaction // number signed-out to him still, if he is trying to close it. BUT--in some // cases, someone // who is NOT the originator can cancel. Like in a payment plan, the sender // is also the depositor, // who would normally be the person cancelling the plan. But technically, // the RECIPIENT should // also have the ability to cancel that payment plan. BUT: the transaction // number isn't signed // out to the RECIPIENT... In THAT case, the below VerifyIssuedNum() won't // work! In those cases, // expect that the special code will be in the subclasses override of this // function. (OTPaymentPlan::CanRemoveItem() etc) // P.S. If you override this function, MAKE SURE to call the parent // (OTCronItem::CanRemoveItem) first, // for the VerifyIssuedNum call above. Only if that fails, do you need to // dig deeper... }
bool Nym::CompareID(const Nym& rhs) const { sLock lock(shared_lock_); return rhs.CompareID(m_nymID); }