bool CredentialSet::VerifyInternally() const { if (!m_MasterCredential) { otOut << __FUNCTION__ << ": This credential set does not have a master credential.\n"; return false; } // Check for a valid master credential, including whether or not the NymID // and MasterID in the CredentialSet match the master credentials's versions. if (!(m_MasterCredential->Validate())) { otOut << __FUNCTION__ << ": Master Credential failed to verify: " << GetMasterCredID() << "\nNymID: " << GetNymID() << "\n"; return false; } // Check each child credential for validity. for (const auto& it : m_mapCredentials) { std::string str_sub_id = it.first; Credential* pSub = it.second; OT_ASSERT(nullptr != pSub); if (!pSub->Validate()) { otOut << __FUNCTION__ << ": Child credential failed to verify: " << str_sub_id << "\nNymID: " << GetNymID() << "\n"; return false; } } return true; }
// OTAccount, OTTransaction, OTItem, and OTLedger are all derived from // this class (OTTransactionType). Therefore they can all quickly identify // whether one of the other components belongs to the same account, using // this method. // bool OTTransactionType::IsSameAccount(const OTTransactionType& rhs) const { if ((GetNymID() != rhs.GetNymID()) || (GetRealAccountID() != rhs.GetRealAccountID()) || (GetRealNotaryID() != rhs.GetRealNotaryID())) return false; return true; }
void OTSubkey::UpdateContents() { m_xmlUnsigned.Release(); Tag tag("keyCredential"); // a hash of the nymIDSource tag.add_attribute("nymID", GetNymID().Get()); // Hash of the master credential that signed this subcredential. tag.add_attribute("masterID", GetMasterCredID().Get()); if (GetNymIDSource().Exists()) { OTASCIIArmor ascSource; // A nym should always verify through its own // source. (Whatever that may be.) ascSource.SetString(GetNymIDSource()); tag.add_tag("nymIDSource", ascSource.Get()); } // MASTER-SIGNED INFO if (OTSubcredential::credMasterSigned == m_StoreAs || OTSubcredential::credPrivateInfo == m_StoreAs) { UpdatePublicContentsToTag(tag); } // PUBLIC INFO (signed by subkey, contains master signed info.) if (OTSubcredential::credPublicInfo == m_StoreAs || OTSubcredential::credPrivateInfo == m_StoreAs) { // GetMasterSigned() returns the contract // containing the master-signed contents // from the above block. OTASCIIArmor ascMasterSigned(GetMasterSigned()); // Contains all the public info, signed by the master key. // Packaged up here inside a final, subkey-signed credential. tag.add_tag("masterSigned", ascMasterSigned.Get()); } // PRIVATE INFO // // If we're saving the private credential info... if (OTSubcredential::credPrivateInfo == m_StoreAs) { UpdatePublicCredentialToTag(tag); UpdatePrivateContentsToTag(tag); } // <=== SET IT BACK TO DEFAULT BEHAVIOR. Any other state // processes ONCE, and then goes back to this again. m_StoreAs = OTSubcredential::credPrivateInfo; std::string str_result; tag.output(str_result); m_xmlUnsigned.Concatenate("%s", str_result.c_str()); }
void OTMasterkey::UpdateContents() { m_xmlUnsigned.Release(); Tag tag("masterCredential"); // a hash of the nymIDSource tag.add_attribute("nymID", GetNymID().Get()); if (GetNymIDSource().Exists()) { OTASCIIArmor ascSource; ascSource.SetString(GetNymIDSource()); // A nym should always // verify through its own // source. (Whatever that // may be.) tag.add_tag("nymIDSource", ascSource.Get()); } // PUBLIC INFO // // if (OTSubcredential::credPublicInfo == m_StoreAs) // PUBLIC INFO // (Always save this in every state.) { UpdatePublicContentsToTag(tag); } // PRIVATE INFO // // If we're saving the private credential info... // if (OTSubcredential::credPrivateInfo == m_StoreAs) // PRIVATE INFO { UpdatePublicCredentialToTag(tag); UpdatePrivateContentsToTag(tag); } // ------------------------------------------------- std::string str_result; tag.output(str_result); m_xmlUnsigned.Concatenate("%s", str_result.c_str()); m_StoreAs = OTSubcredential::credPrivateInfo; // <=== SET IT BACK TO DEFAULT // BEHAVIOR. Any other state // processes ONCE, and then // goes back to this again. }
// PayDividendVisitor::Trigger() is used in // OTUnitDefinition::VisitAccountRecords() // cppcheck-suppress unusedFunction bool PayDividendVisitor::Trigger( const Account& theSharesAccount) // theSharesAccount // is, say, a Pepsi // shares // account. Here, we'll send a dollars voucher // to its owner. { const std::int64_t lPayoutAmount = (theSharesAccount.GetBalance() * GetPayoutPerShare()); if (lPayoutAmount <= 0) { otOut << "PayDividendVisitor::Trigger: nothing to pay, " "since this account owns no shares. (Returning " "true.)"; return true; // nothing to pay, since this account owns no shares. // Success! } OT_ASSERT(false == GetNotaryID()->empty()); const auto theNotaryID = GetNotaryID(); OT_ASSERT(!GetPayoutUnitTypeId()->empty()); const Identifier& payoutUnitTypeId_ = (Identifier::Factory()); OT_ASSERT(!GetVoucherAcctID()->empty()); const Identifier& theVoucherAcctID = (GetVoucherAcctID()); Nym& theServerNym = const_cast<Nym&>(server_.GetServerNym()); const auto theServerNymID = Identifier::Factory(theServerNym); const Identifier& RECIPIENT_ID = theSharesAccount.GetNymID(); OT_ASSERT(!GetNymID()->empty()); const Identifier& theSenderNymID = (GetNymID()); OT_ASSERT(!GetMemo()->empty()); const String& strMemo = (GetMemo()); // Note: theSenderNymID is the originator of the Dividend Payout. // However, all the actual vouchers will be from "the server Nym" and // not from theSenderNymID. So then why is it even here? Because anytime // there's an error, the server will send to theSenderNymID instead of // RECIPIENT_ID (so the original sender can have his money back, instead of // just having it get lost in the ether.) bool bReturnValue = false; auto theVoucher{ server_.API().Factory().Cheque(theNotaryID, Identifier::Factory())}; OT_ASSERT(false != bool(theVoucher)); // 10 minutes == 600 Seconds // 1 hour == 3600 Seconds // 1 day == 86400 Seconds // 30 days == 2592000 Seconds // 3 months == 7776000 Seconds // 6 months == 15552000 Seconds const time64_t VALID_FROM = OTTimeGetCurrentTime(); // This time is set to TODAY NOW const time64_t VALID_TO = OTTimeAddTimeInterval( VALID_FROM, OTTimeGetSecondsFromTime(OT_TIME_SIX_MONTHS_IN_SECONDS)); // This time // occurs in // 180 days (6 months). // Todo hardcoding. TransactionNumber lNewTransactionNumber = 0; auto context = server_.API().Wallet().mutable_ClientContext( theServerNym.ID(), theServerNym.ID()); bool bGotNextTransNum = server_.GetTransactor().issueNextTransactionNumberToNym( context.It(), lNewTransactionNumber); // We save the transaction // number on the server Nym (normally we'd discard it) because // when the cheque is deposited, the server nym, as the owner of // the voucher account, needs to verify the transaction # on the // cheque (to prevent double-spending of cheques.) if (bGotNextTransNum) { const bool bIssueVoucher = theVoucher->IssueCheque( lPayoutAmount, // The amount of the cheque. lNewTransactionNumber, // Requiring a transaction number prevents // double-spending of cheques. VALID_FROM, // The expiration date (valid from/to dates) of the // cheque VALID_TO, // Vouchers are automatically starting today and lasting // 6 // months. theVoucherAcctID, // The asset account the cheque is drawn on. theServerNymID, // Nym ID of the sender (in this case the server // nym.) strMemo, // Optional memo field. Includes item note and request // memo. Identifier::Factory(RECIPIENT_ID)); // All account crediting / debiting happens in the caller, in // server::Server. // (AND it happens only ONCE, to cover ALL vouchers.) // Then in here, the voucher either gets send to the recipient, or if // error, sent back home to // the issuer Nym. (ALL the funds are removed, then the vouchers are // sent one way or the other.) // Any returned vouchers, obviously serve to notify the dividend payer // of where the errors were // (as well as give him the opportunity to get his money back.) // bool bSent = false; if (bIssueVoucher) { // All this does is set the voucher's internal contract string to // "VOUCHER" instead of "CHEQUE". We also set the server itself as // the remitter, which is unusual for vouchers, but necessary in the // case of dividends. // theVoucher->SetAsVoucher(theServerNymID, theVoucherAcctID); theVoucher->SignContract(theServerNym); theVoucher->SaveContract(); // Send the voucher to the payments inbox of the recipient. // const auto strVoucher = String::Factory(*theVoucher); auto thePayment{server_.API().Factory().Payment(strVoucher)}; OT_ASSERT(false != bool(thePayment)); // calls DropMessageToNymbox bSent = server_.SendInstrumentToNym( theNotaryID, theServerNymID, // sender nym RECIPIENT_ID, // recipient nym *thePayment, "payDividend"); // todo: hardcoding. bReturnValue = bSent; // <======= RETURN VALUE. if (bSent) m_lAmountPaidOut += lPayoutAmount; // At the end of iterating all accounts, if // m_lAmountPaidOut is less than // lTotalPayoutAmount, then we return to rest // to the sender. } else { const auto strPayoutUnitTypeId = String::Factory( Identifier::Factory(payoutUnitTypeId_)), strRecipientNymID = String::Factory(RECIPIENT_ID); otErr << "PayDividendVisitor::Trigger: ERROR failed issuing " << "voucher (to send to dividend payout recipient.) WAS " << "TRYING TO PAY " << lPayoutAmount << " of instrument definition " << strPayoutUnitTypeId << " to Nym " << strRecipientNymID << ".\n"; } // If we didn't send it, then we need to return the funds to where they // came from. // if (!bSent) { auto theReturnVoucher{server_.API().Factory().Cheque( theNotaryID, Identifier::Factory())}; OT_ASSERT(false != bool(theReturnVoucher)); const bool bIssueReturnVoucher = theReturnVoucher->IssueCheque( lPayoutAmount, // The amount of the cheque. lNewTransactionNumber, // Requiring a transaction number // prevents double-spending of cheques. VALID_FROM, // The expiration date (valid from/to dates) of the // cheque VALID_TO, // Vouchers are automatically starting today and // lasting 6 months. theVoucherAcctID, // The asset account the cheque is drawn on. theServerNymID, // Nym ID of the sender (in this case the // server nym.) strMemo, // Optional memo field. Includes item note and request // memo. Identifier::Factory(theSenderNymID)); // We're returning the // money to its original // sender. if (bIssueReturnVoucher) { // All this does is set the voucher's internal contract string // to // "VOUCHER" instead of "CHEQUE". // theReturnVoucher->SetAsVoucher( theServerNymID, theVoucherAcctID); theReturnVoucher->SignContract(theServerNym); theReturnVoucher->SaveContract(); // Return the voucher back to the payments inbox of the original // sender. // const auto strReturnVoucher = String::Factory(*theReturnVoucher); auto theReturnPayment{ server_.API().Factory().Payment(strReturnVoucher)}; OT_ASSERT(false != bool(theReturnPayment)); // calls DropMessageToNymbox bSent = server_.SendInstrumentToNym( theNotaryID, theServerNymID, // sender nym theSenderNymID, // recipient nym (original sender.) *theReturnPayment, "payDividend"); // todo: hardcoding. if (bSent) m_lAmountReturned += lPayoutAmount; // At the end of iterating all accounts, // if m_lAmountPaidOut+m_lAmountReturned // is less than lTotalPayoutAmount, then // we return the rest to the sender. } else { const auto strPayoutUnitTypeId = String::Factory(payoutUnitTypeId_), strSenderNymID = String::Factory(theSenderNymID); otErr << "PayDividendVisitor::Trigger: ERROR " "failed issuing voucher (to return back to " "the dividend payout initiator, after a failed " "payment attempt to the originally intended " "recipient.) WAS TRYING TO PAY " << lPayoutAmount << " of instrument definition " << strPayoutUnitTypeId << " to Nym " << strSenderNymID << ".\n"; } } // if !bSent } else // !bGotNextTransNum { const auto strPayoutUnitTypeId = String::Factory(payoutUnitTypeId_), strRecipientNymID = String::Factory(RECIPIENT_ID); otErr << OT_METHOD << __FUNCTION__ << ": ERROR!! Failed issuing next transaction number while " << "trying to send a voucher (while paying dividends.) " << "WAS TRYING TO PAY " << lPayoutAmount << " of instrument definition " << strPayoutUnitTypeId->Get() << " to Nym " << strRecipientNymID->Get() << ".\n"; } return bReturnValue; }
bool OTSubkey::VerifySignedByMaster() { // See if m_strMasterSigned was signed by my master credential. OTSubkey masterKey(*m_pOwner); if (m_strMasterSigned.Exists() && masterKey.LoadContractFromString(m_strMasterSigned)) { // Here we need to MAKE SURE that the "master signed" version contains // the same CONTENTS as the actual version. if (!GetNymID().Compare(masterKey.GetNymID())) { Log::vOutput(0, "%s: Failure, NymID of this key credential " "doesn't match NymID of master-signed version of " "this key credential.\n", __FUNCTION__); return false; } if (!GetNymIDSource().Compare(masterKey.GetNymIDSource())) { Log::vOutput(0, "%s: Failure, NymIDSource of this key credential " "doesn't match NymIDSource of master-signed " "version of this key credential.\n", __FUNCTION__); return false; } if (!GetMasterCredID().Compare(masterKey.GetMasterCredID())) { Log::vOutput(0, "%s: Failure, MasterCredID of this key " "credential doesn't match MasterCredID of " "master-signed version of this key credential.\n", __FUNCTION__); return false; } if (GetPublicMap().size() > 0 && GetPublicMap() != masterKey.GetPublicMap()) { Log::vOutput(0, "%s: Failure, public info of this key credential " "doesn't match public info of master-signed " "version of this key credential.\n", __FUNCTION__); return false; } // Master-signed version of subkey does not contain the private keys, // since normally the master is signing // the public version of the sub credential (to validate it) and you // don't want the public seeing your private keys. // So we would never expect these to match, since the master signed // version should have no private keys in it. // // if (GetPrivateMap() != masterKey.GetPrivateMap()) // { // OTLog::vOutput(0, "%s: Failure, private info of this key // credential doesn't match private info of master-signed version of // this key credential.\n", __FUNCTION__); // return false; // } bool verifiedWithKey = masterKey.VerifyWithKey( m_pOwner->GetMasterkey().m_SigningKey.GetPublicKey()); // ON SERVER SIDE, THE ACTUAL SUBKEY doesn't have any public key, only // the master-signed version of it. // (The master-signed version being basically the only contents of the // public version.) // So we need to be able to, after verifying, load up those contents so // they are available on the // subkey itself, and not just on some master-signed version of itself // hidden inside itself. // Otherwise I would have to load up the master-signed version anytime // the server-side wanted to // mess with any of the keys. // Thus: copy the public info from master signed, to* this, if the above // call was successful if (verifiedWithKey && GetPublicMap().size() == 0) { // For master credential. return SetPublicContents(masterKey.GetPublicMap()); } return verifiedWithKey; } return false; }