예제 #1
0
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;
}
예제 #3
0
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());
}
예제 #4
0
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;
}
예제 #6
0
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;
}