Example #1
0
// Look up the master public generator for a regular seed so we may index source accounts ids.
// --> naRegularSeed
// <-- naMasterGenerator
Json::Value getMasterGenerator (
    Ledger::ref lrLedger, const RippleAddress& naRegularSeed,
    RippleAddress& naMasterGenerator, NetworkOPs& netOps)
{
    RippleAddress       na0Public;      // To find the generator's index.
    RippleAddress       na0Private;     // To decrypt the master generator's cipher.
    RippleAddress       naGenerator = RippleAddress::createGeneratorPublic (naRegularSeed);

    na0Public.setAccountPublic (naGenerator, 0);
    na0Private.setAccountPrivate (naGenerator, naRegularSeed, 0);

    SLE::pointer        sleGen          = netOps.getGenerator (lrLedger, na0Public.getAccountID ());

    if (!sleGen)
    {
        // No account has been claimed or has had it password set for seed.
        return rpcError (rpcNO_ACCOUNT);
    }

    Blob    vucCipher           = sleGen->getFieldVL (sfGenerator);
    Blob    vucMasterGenerator  = na0Private.accountPrivateDecrypt (na0Public, vucCipher);

    if (vucMasterGenerator.empty ())
    {
        return rpcError (rpcFAIL_GEN_DECRYPT);
    }

    naMasterGenerator.setGenerator (vucMasterGenerator);

    return Json::Value (Json::objectValue);
}
Example #2
0
Blob RippleAddress::accountPrivateSign (Blob const& message) const
{
    if (vchData.size() == 33  &&  vchData[0] == 0xED)
    {
        uint8_t const*      secretKey = &vchData[1];
        ed25519_public_key  publicKey;
        Blob                signature (sizeof (ed25519_signature));

        ed25519_publickey (secretKey, publicKey);

        ed25519_sign (
            message.data(), message.size(), secretKey, publicKey,
            &signature[0]);

        assert (isCanonicalEd25519Signature (signature.data()));

        return signature;
    }

    Blob result = ECDSASign(
        sha512Half(makeSlice(message)), getAccountPrivate());
    bool const ok = !result.empty();

    CondLog (!ok, lsWARNING, RippleAddress)
            << "accountPrivateSign: Signing failed.";

    return result;
}
Example #3
0
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
{
    vchSig = ECDSASign (hash, getNodePrivate());

    if (vchSig.empty())
        Throw<std::runtime_error> ("Signing failed.");
}
	// create from a base58 encoded seed
	bool PaysharesPrivateKey::fromString(std::string& base58seed)
	{
		Blob vchTemp;
		Base58::decodeWithCheck(base58seed.c_str(), vchTemp, Base58::getRippleAlphabet());

		if (vchTemp.empty() &&
			vchTemp.size() == crypto_sign_SEEDBYTES + 1 &&
			vchTemp[0] == RippleAddress::VER_SEED)
		{
			return(false);
		}

		mSeed.resize(crypto_sign_SEEDBYTES);
		memcpy(&mSeed[0], vchTemp.data() + 1, crypto_sign_SEEDBYTES);
		mPair.setSeed(mSeed);
		return(true);
	}
Example #5
0
bool CBase58Data::SetString (const char* psz, unsigned char version, Base58::Alphabet const& alphabet)
{
    Blob vchTemp;
    Base58::decodeWithCheck (psz, vchTemp, alphabet);

    if (vchTemp.empty () || vchTemp[0] != version)
    {
        vchData.clear ();
        nVersion = 1;
        return false;
    }

    nVersion = vchTemp[0];
    vchData.resize (vchTemp.size () - 1);

    if (!vchData.empty ())
        memcpy (&vchData[0], &vchTemp[1], vchData.size ());

    memset (&vchTemp[0], 0, vchTemp.size ());
    return true;
}
Example #6
0
Blob
PublicKey::encrypt(const Blob& data) const
{
    if (!pk)
        throw CryptoException("Can't read public key !");

    unsigned key_len = 0;
    int err = gnutls_pubkey_get_pk_algorithm(pk, &key_len);
    if (err < 0)
        throw CryptoException("Can't read public key length !");
    if (err != GNUTLS_PK_RSA)
        throw CryptoException("Must be an RSA key");

    unsigned max_block_sz = key_len / 8 - 11;
    unsigned cypher_block_sz = key_len / 8;
    unsigned block_num = data.empty() ? 1 : 1 + (data.size() - 1) / max_block_sz;

    Blob ret;
    auto eb = data.cbegin();
    auto ee = data.cend();
    for (unsigned i=0; i<block_num; i++) {
        auto blk_sz = std::min<unsigned>(ee - eb, max_block_sz);
        const gnutls_datum_t dat {(uint8_t*)&(*eb), blk_sz};
        gnutls_datum_t encrypted;
        err = gnutls_pubkey_encrypt_data(pk, 0, &dat, &encrypted);
        if (err != GNUTLS_E_SUCCESS)
            throw CryptoException(std::string("Can't encrypt data: ") + gnutls_strerror(err));
        if (encrypted.size != cypher_block_sz)
            throw CryptoException("Unexpected cypherblock size");
        ret.insert(ret.end(), encrypted.data, encrypted.data+encrypted.size);
        eb += blk_sz;
        gnutls_free(encrypted.data);
    }

    return ret;
}
TER AccountSetTransactor::doApply ()
{
    WriteLog (lsINFO, AccountSetTransactor) << "AccountSet>";

    const uint32    uTxFlags    = mTxn.getFlags ();

    const uint32    uFlagsIn    = mTxnAccount->getFieldU32 (sfFlags);
    uint32          uFlagsOut   = uFlagsIn;

    const uint32    uSetFlag    = mTxn.getFieldU32 (sfSetFlag);
    const uint32    uClearFlag  = mTxn.getFieldU32 (sfClearFlag);

    // legacy AccountSet flags
    bool      bSetRequireDest   = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
    bool      bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
    bool      bSetRequireAuth   = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
    bool      bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
    bool      bSetDisallowXRP   = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
    bool      bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);

    if (uTxFlags & tfAccountSetMask)
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Invalid flags set.";

        return temINVALID_FLAG;
    }

    //
    // RequireAuth
    //

    if (bSetRequireAuth && bClearRequireAuth)
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";

        return temINVALID_FLAG;
    }

    if (bSetRequireAuth && !isSetBit (uFlagsIn, lsfRequireAuth))
    {
        if (mTxnAccount->getFieldU32 (sfOwnerCount))
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Retry: OwnerCount not zero.";

            return isSetBit(mParams, tapRETRY) ? terOWNERS : tecOWNERS;
        }

        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set RequireAuth.";

        uFlagsOut   |= lsfRequireAuth;
    }

    if (bClearRequireAuth && isSetBit (uFlagsIn, lsfRequireAuth))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear RequireAuth.";

        uFlagsOut   &= ~lsfRequireAuth;
    }

    //
    // RequireDestTag
    //

    if (bSetRequireDest && bClearRequireDest)
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";

        return temINVALID_FLAG;
    }

    if (bSetRequireDest && !isSetBit (uFlagsIn, lsfRequireDestTag))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfRequireDestTag.";

        uFlagsOut   |= lsfRequireDestTag;
    }

    if (bClearRequireDest && isSetBit (uFlagsIn, lsfRequireDestTag))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfRequireDestTag.";

        uFlagsOut   &= ~lsfRequireDestTag;
    }

    //
    // DisallowXRP
    //

    if (bSetDisallowXRP && bClearDisallowXRP)
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";

        return temINVALID_FLAG;
    }

    if (bSetDisallowXRP && !isSetBit (uFlagsIn, lsfDisallowXRP))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfDisallowXRP.";

        uFlagsOut   |= lsfDisallowXRP;
    }

    if (bClearDisallowXRP && isSetBit (uFlagsIn, lsfDisallowXRP))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfDisallowXRP.";

        uFlagsOut   &= ~lsfDisallowXRP;
    }

    //
    // DisableMaster
    //

    if ((uSetFlag == asfDisableMaster) && (uClearFlag == asfDisableMaster))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Malformed transaction: Contradictory flags set.";

        return temINVALID_FLAG;
    }

    if ((uSetFlag == asfDisableMaster) && !isSetBit (uFlagsIn, lsfDisableMaster))
    {
        if (!mTxnAccount->isFieldPresent (sfRegularKey))
            return tecNO_REGULAR_KEY;

        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Set lsfDisableMaster.";

        uFlagsOut   |= lsfDisableMaster;
    }

    if ((uClearFlag == asfDisableMaster) && isSetBit (uFlagsIn, lsfDisableMaster))
    {
        WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: Clear lsfDisableMaster.";

        uFlagsOut   &= ~lsfDisableMaster;
    }

    //
    // EmailHash
    //

    if (mTxn.isFieldPresent (sfEmailHash))
    {
        uint128     uHash   = mTxn.getFieldH128 (sfEmailHash);

        if (!uHash)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset email hash";

            mTxnAccount->makeFieldAbsent (sfEmailHash);
        }
        else
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set email hash";

            mTxnAccount->setFieldH128 (sfEmailHash, uHash);
        }
    }

    //
    // WalletLocator
    //

    if (mTxn.isFieldPresent (sfWalletLocator))
    {
        uint256     uHash   = mTxn.getFieldH256 (sfWalletLocator);

        if (!uHash)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset wallet locator";

            mTxnAccount->makeFieldAbsent (sfEmailHash);
        }
        else
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set wallet locator";

            mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
        }
    }

    //
    // MessageKey
    //

    if (mTxn.isFieldPresent (sfMessageKey))
    {
        Blob    vucPublic   = mTxn.getFieldVL (sfMessageKey);

        if (vucPublic.size () > PUBLIC_BYTES_MAX)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: message key too long";

            return telBAD_PUBLIC_KEY;
        }
        else
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set message key";

            mTxnAccount->setFieldVL (sfMessageKey, vucPublic);
        }
    }

    //
    // Domain
    //

    if (mTxn.isFieldPresent (sfDomain))
    {
        Blob    vucDomain   = mTxn.getFieldVL (sfDomain);

        if (vucDomain.empty ())
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset domain";

            mTxnAccount->makeFieldAbsent (sfDomain);
        }
        else if (vucDomain.size () > DOMAIN_BYTES_MAX)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: domain too long";

            return telBAD_DOMAIN;
        }
        else
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set domain";

            mTxnAccount->setFieldVL (sfDomain, vucDomain);
        }
    }

    //
    // TransferRate
    //

    if (mTxn.isFieldPresent (sfTransferRate))
    {
        uint32      uRate   = mTxn.getFieldU32 (sfTransferRate);

        if (!uRate || uRate == QUALITY_ONE)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: unset transfer rate";

            mTxnAccount->makeFieldAbsent (sfTransferRate);
        }
        else if (uRate > QUALITY_ONE)
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: set transfer rate";

            mTxnAccount->setFieldU32 (sfTransferRate, uRate);
        }
        else
        {
            WriteLog (lsINFO, AccountSetTransactor) << "AccountSet: bad transfer rate";

            return temBAD_TRANSFER_RATE;
        }
    }

    if (uFlagsIn != uFlagsOut)
        mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);

    WriteLog (lsINFO, AccountSetTransactor) << "AccountSet<";

    return tesSUCCESS;
}
// --> strIdent: public key, account ID, or regular seed.
// --> bStrict: Only allow account id or public key.
// <-- bIndex: true if iIndex > 0 and used the index.
Json::Value accountFromString (Ledger::ref lrLedger, RippleAddress& naAccount,
                               bool& bIndex, const std::string& strIdent,
                               const int iIndex, const bool bStrict, NetworkOPs& netOps)
{
    RippleAddress   naSeed;

    if (naAccount.setAccountPublic (strIdent) || naAccount.setAccountID (strIdent))
    {
        // Got the account.
        bIndex  = false;
    }
    else if (bStrict)
    {
        return naAccount.setAccountID (strIdent, Base58::getBitcoinAlphabet ())
               ? rpcError (rpcACT_BITCOIN)
               : rpcError (rpcACT_MALFORMED);
    }
    // Must be a seed.
    else if (!naSeed.setSeedGeneric (strIdent))
    {
        return rpcError (rpcBAD_SEED);
    }
    else
    {
        // We allow the use of the seeds to access #0.
        // This is poor practice and merely for debuging convenience.
        RippleAddress       naRegular0Public;
        RippleAddress       naRegular0Private;

        RippleAddress       naGenerator     = RippleAddress::createGeneratorPublic (naSeed);

        naRegular0Public.setAccountPublic (naGenerator, 0);
        naRegular0Private.setAccountPrivate (naGenerator, naSeed, 0);

        //      Account uGeneratorID    = naRegular0Public.getAccountID();
        SLE::pointer        sleGen          = netOps.getGenerator (lrLedger, naRegular0Public.getAccountID ());

        if (!sleGen)
        {
            // Didn't find a generator map, assume it is a master generator.
        }
        else
        {
            // Found master public key.
            Blob    vucCipher               = sleGen->getFieldVL (sfGenerator);
            Blob    vucMasterGenerator      = naRegular0Private.accountPrivateDecrypt (naRegular0Public, vucCipher);

            if (vucMasterGenerator.empty ())
            {
                rpcError (rpcNO_GEN_DECRYPT);
            }

            naGenerator.setGenerator (vucMasterGenerator);
        }

        bIndex  = !iIndex;

        naAccount.setAccountPublic (naGenerator, iIndex);
    }

    return Json::Value (Json::objectValue);
}
Example #9
0
    TER doApply () override
    {
        std::uint32_t const uTxFlags = mTxn.getFlags ();

        std::uint32_t const uFlagsIn = mTxnAccount->getFieldU32 (sfFlags);
        std::uint32_t uFlagsOut = uFlagsIn;

        std::uint32_t const uSetFlag = mTxn.getFieldU32 (sfSetFlag);
        std::uint32_t const uClearFlag  = mTxn.getFieldU32 (sfClearFlag);

        if ((uSetFlag != 0) && (uSetFlag == uClearFlag))
        {
            m_journal.trace << "Malformed transaction: Set and clear same flag";
            return temINVALID_FLAG;
        }

        // legacy AccountSet flags
        bool bSetRequireDest   = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
        bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
        bool bSetRequireAuth   = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
        bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
        bool bSetDisallowXRP   = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
        bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);

        if (uTxFlags & tfAccountSetMask)
        {
            m_journal.trace << "Malformed transaction: Invalid flags set.";
            return temINVALID_FLAG;
        }

        //
        // RequireAuth
        //

        if (bSetRequireAuth && bClearRequireAuth)
        {
            m_journal.trace << "Malformed transaction: Contradictory flags set.";
            return temINVALID_FLAG;
        }

        if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
        {
            if (!mEngine->view().dirIsEmpty (Ledger::getOwnerDirIndex (mTxnAccountID)))
            {
                m_journal.trace << "Retry: Owner directory not empty.";

                return (mParams & tapRETRY) ? terOWNERS : tecOWNERS;
            }

            m_journal.trace << "Set RequireAuth.";
            uFlagsOut   |= lsfRequireAuth;
        }

        if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
        {
            m_journal.trace << "Clear RequireAuth.";
            uFlagsOut &= ~lsfRequireAuth;
        }

        //
        // RequireDestTag
        //

        if (bSetRequireDest && bClearRequireDest)
        {
            m_journal.trace << "Malformed transaction: Contradictory flags set.";
            return temINVALID_FLAG;
        }

        if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
        {
            m_journal.trace << "Set lsfRequireDestTag.";
            uFlagsOut   |= lsfRequireDestTag;
        }

        if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
        {
            m_journal.trace << "Clear lsfRequireDestTag.";
            uFlagsOut   &= ~lsfRequireDestTag;
        }

        //
        // DisallowXRP
        //

        if (bSetDisallowXRP && bClearDisallowXRP)
        {
            m_journal.trace << "Malformed transaction: Contradictory flags set.";
            return temINVALID_FLAG;
        }

        if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
        {
            m_journal.trace << "Set lsfDisallowXRP.";
            uFlagsOut   |= lsfDisallowXRP;
        }

        if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
        {
            m_journal.trace << "Clear lsfDisallowXRP.";
            uFlagsOut   &= ~lsfDisallowXRP;
        }

        //
        // DisableMaster
        //

        if ((uSetFlag == asfDisableMaster) && (uClearFlag == asfDisableMaster))
        {
            m_journal.trace << "Malformed transaction: Contradictory flags set.";
            return temINVALID_FLAG;
        }

        if ((uSetFlag == asfDisableMaster) && !(uFlagsIn & lsfDisableMaster))
        {
            if (!mTxnAccount->isFieldPresent (sfRegularKey))
                return tecNO_REGULAR_KEY;

            m_journal.trace << "Set lsfDisableMaster.";
            uFlagsOut   |= lsfDisableMaster;
        }

        if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
        {
            m_journal.trace << "Clear lsfDisableMaster.";
            uFlagsOut   &= ~lsfDisableMaster;
        }

        if ((uSetFlag == asfNoFreeze) && (uClearFlag != asfNoFreeze))
        {
            m_journal.trace << "Set NoFreeze flag";
            uFlagsOut   |= lsfNoFreeze;
        }

        // Anyone may set global freeze
        if ((uSetFlag == asfGlobalFreeze) && (uClearFlag != asfGlobalFreeze))
        {
            m_journal.trace << "Set GlobalFreeze flag";
            uFlagsOut   |= lsfGlobalFreeze;
        }

        // If you have set NoFreeze, you may not clear GlobalFreeze
        // This prevents those who have set NoFreeze from using
        // GlobalFreeze strategically.
        if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
            ((uFlagsOut & lsfNoFreeze) == 0))
        {
            m_journal.trace << "Clear GlobalFreeze flag";
            uFlagsOut   &= ~lsfGlobalFreeze;
        }

        //
        // Track transaction IDs signed by this account in its root
        //

        if ((uSetFlag == asfAccountTxnID) && (uClearFlag != asfAccountTxnID) && !mTxnAccount->isFieldPresent (sfAccountTxnID))
        {
            m_journal.trace << "Set AccountTxnID";
            mTxnAccount->makeFieldPresent (sfAccountTxnID);
         }

        if ((uClearFlag == asfAccountTxnID) && (uSetFlag != asfAccountTxnID) && mTxnAccount->isFieldPresent (sfAccountTxnID))
        {
            m_journal.trace << "Clear AccountTxnID";
            mTxnAccount->makeFieldAbsent (sfAccountTxnID);
        }

        //
        // EmailHash
        //

        if (mTxn.isFieldPresent (sfEmailHash))
        {
            uint128     uHash   = mTxn.getFieldH128 (sfEmailHash);

            if (!uHash)
            {
                m_journal.trace << "unset email hash";
                mTxnAccount->makeFieldAbsent (sfEmailHash);
            }
            else
            {
                m_journal.trace << "set email hash";
                mTxnAccount->setFieldH128 (sfEmailHash, uHash);
            }
        }

        //
        // WalletLocator
        //

        if (mTxn.isFieldPresent (sfWalletLocator))
        {
            uint256     uHash   = mTxn.getFieldH256 (sfWalletLocator);

            if (!uHash)
            {
                m_journal.trace << "unset wallet locator";
                mTxnAccount->makeFieldAbsent (sfWalletLocator);
            }
            else
            {
                m_journal.trace << "set wallet locator";
                mTxnAccount->setFieldH256 (sfWalletLocator, uHash);
            }
        }

        //
        // MessageKey
        //

        if (mTxn.isFieldPresent (sfMessageKey))
        {
            Blob    vucPublic   = mTxn.getFieldVL (sfMessageKey);

            if (vucPublic.empty ())
            {
                m_journal.debug << "set message key";

                mTxnAccount->makeFieldAbsent (sfMessageKey);
            }
            if (vucPublic.size () > PUBLIC_BYTES_MAX)
            {
                m_journal.trace << "message key too long";

                return telBAD_PUBLIC_KEY;
            }
            else
            {
                m_journal.debug << "set message key";

                mTxnAccount->setFieldVL (sfMessageKey, vucPublic);
            }
        }

        //
        // Domain
        //

        if (mTxn.isFieldPresent (sfDomain))
        {
            Blob    vucDomain   = mTxn.getFieldVL (sfDomain);

            if (vucDomain.empty ())
            {
                m_journal.trace << "unset domain";

                mTxnAccount->makeFieldAbsent (sfDomain);
            }
            else if (vucDomain.size () > DOMAIN_BYTES_MAX)
            {
                m_journal.trace << "domain too long";

                return telBAD_DOMAIN;
            }
            else
            {
                m_journal.trace << "set domain";

                mTxnAccount->setFieldVL (sfDomain, vucDomain);
            }
        }

        //
        // TransferRate
        //

        if (mTxn.isFieldPresent (sfTransferRate))
        {
            std::uint32_t      uRate   = mTxn.getFieldU32 (sfTransferRate);

            if (!uRate || uRate == QUALITY_ONE)
            {
                m_journal.trace << "unset transfer rate";
                mTxnAccount->makeFieldAbsent (sfTransferRate);
            }
            else if (uRate > QUALITY_ONE)
            {
                m_journal.trace << "set transfer rate";
                mTxnAccount->setFieldU32 (sfTransferRate, uRate);
            }
            else
            {
                m_journal.trace << "bad transfer rate";
                return temBAD_TRANSFER_RATE;
            }
        }

        if (uFlagsIn != uFlagsOut)
            mTxnAccount->setFieldU32 (sfFlags, uFlagsOut);

        return tesSUCCESS;
    }
Example #10
0
TER
SetAccount::doApply ()
{
    std::uint32_t const uTxFlags = ctx_.tx.getFlags ();

    auto const sle = view().peek(
                         keylet::account(account_));

    std::uint32_t const uFlagsIn = sle->getFieldU32 (sfFlags);
    std::uint32_t uFlagsOut = uFlagsIn;

    std::uint32_t const uSetFlag = ctx_.tx.getFieldU32 (sfSetFlag);
    std::uint32_t const uClearFlag = ctx_.tx.getFieldU32 (sfClearFlag);

    // legacy AccountSet flags
    bool bSetRequireDest   = (uTxFlags & TxFlag::requireDestTag) || (uSetFlag == asfRequireDest);
    bool bClearRequireDest = (uTxFlags & tfOptionalDestTag) || (uClearFlag == asfRequireDest);
    bool bSetRequireAuth   = (uTxFlags & tfRequireAuth) || (uSetFlag == asfRequireAuth);
    bool bClearRequireAuth = (uTxFlags & tfOptionalAuth) || (uClearFlag == asfRequireAuth);
    bool bSetDisallowXRP   = (uTxFlags & tfDisallowXRP) || (uSetFlag == asfDisallowXRP);
    bool bClearDisallowXRP = (uTxFlags & tfAllowXRP) || (uClearFlag == asfDisallowXRP);

    bool sigWithMaster = false;

    {
        auto const blob = ctx_.tx.getSigningPubKey();

        if (!blob.empty ())
        {
            auto const signingPubKey =
                RippleAddress::createAccountPublic(blob);

            if (calcAccountID(signingPubKey) == account_)
                sigWithMaster = true;
        }
    }

    //
    // RequireAuth
    //
    if (bSetRequireAuth && !(uFlagsIn & lsfRequireAuth))
    {
        j_.trace << "Set RequireAuth.";
        uFlagsOut |= lsfRequireAuth;
    }

    if (bClearRequireAuth && (uFlagsIn & lsfRequireAuth))
    {
        j_.trace << "Clear RequireAuth.";
        uFlagsOut &= ~lsfRequireAuth;
    }

    //
    // RequireDestTag
    //
    if (bSetRequireDest && !(uFlagsIn & lsfRequireDestTag))
    {
        j_.trace << "Set lsfRequireDestTag.";
        uFlagsOut |= lsfRequireDestTag;
    }

    if (bClearRequireDest && (uFlagsIn & lsfRequireDestTag))
    {
        j_.trace << "Clear lsfRequireDestTag.";
        uFlagsOut &= ~lsfRequireDestTag;
    }

    //
    // DisallowXRP
    //
    if (bSetDisallowXRP && !(uFlagsIn & lsfDisallowXRP))
    {
        j_.trace << "Set lsfDisallowXRP.";
        uFlagsOut |= lsfDisallowXRP;
    }

    if (bClearDisallowXRP && (uFlagsIn & lsfDisallowXRP))
    {
        j_.trace << "Clear lsfDisallowXRP.";
        uFlagsOut &= ~lsfDisallowXRP;
    }

    //
    // DisableMaster
    //
    if ((uSetFlag == asfDisableMaster) && !(uFlagsIn & lsfDisableMaster))
    {
        if (!sigWithMaster)
        {
            j_.trace << "Must use master key to disable master key.";
            return tecNEED_MASTER_KEY;
        }

        if ((!sle->isFieldPresent (sfRegularKey)) &&
                (!view().peek (keylet::signers (account_))))
        {
            // Account has no regular key or multi-signer signer list.

            // Prevent transaction changes until we're ready.
            if (view().rules().enabled(featureMultiSign,
                                       ctx_.app.config().features))
                return tecNO_ALTERNATIVE_KEY;

            return tecNO_REGULAR_KEY;
        }

        j_.trace << "Set lsfDisableMaster.";
        uFlagsOut |= lsfDisableMaster;
    }

    if ((uClearFlag == asfDisableMaster) && (uFlagsIn & lsfDisableMaster))
    {
        j_.trace << "Clear lsfDisableMaster.";
        uFlagsOut &= ~lsfDisableMaster;
    }

    //
    // DefaultRipple
    //
    if (uSetFlag == asfDefaultRipple)
    {
        uFlagsOut   |= lsfDefaultRipple;
    }
    else if (uClearFlag == asfDefaultRipple)
    {
        uFlagsOut   &= ~lsfDefaultRipple;
    }

    //
    // NoFreeze
    //
    if (uSetFlag == asfNoFreeze)
    {
        if (!sigWithMaster && !(uFlagsIn & lsfDisableMaster))
        {
            j_.trace << "Can't use regular key to set NoFreeze.";
            return tecNEED_MASTER_KEY;
        }

        j_.trace << "Set NoFreeze flag";
        uFlagsOut |= lsfNoFreeze;
    }

    // Anyone may set global freeze
    if (uSetFlag == asfGlobalFreeze)
    {
        j_.trace << "Set GlobalFreeze flag";
        uFlagsOut |= lsfGlobalFreeze;
    }

    // If you have set NoFreeze, you may not clear GlobalFreeze
    // This prevents those who have set NoFreeze from using
    // GlobalFreeze strategically.
    if ((uSetFlag != asfGlobalFreeze) && (uClearFlag == asfGlobalFreeze) &&
            ((uFlagsOut & lsfNoFreeze) == 0))
    {
        j_.trace << "Clear GlobalFreeze flag";
        uFlagsOut &= ~lsfGlobalFreeze;
    }

    //
    // Track transaction IDs signed by this account in its root
    //
    if ((uSetFlag == asfAccountTxnID) && !sle->isFieldPresent (sfAccountTxnID))
    {
        j_.trace << "Set AccountTxnID";
        sle->makeFieldPresent (sfAccountTxnID);
    }

    if ((uClearFlag == asfAccountTxnID) && sle->isFieldPresent (sfAccountTxnID))
    {
        j_.trace << "Clear AccountTxnID";
        sle->makeFieldAbsent (sfAccountTxnID);
    }

    //
    // EmailHash
    //
    if (ctx_.tx.isFieldPresent (sfEmailHash))
    {
        uint128 const uHash = ctx_.tx.getFieldH128 (sfEmailHash);

        if (!uHash)
        {
            j_.trace << "unset email hash";
            sle->makeFieldAbsent (sfEmailHash);
        }
        else
        {
            j_.trace << "set email hash";
            sle->setFieldH128 (sfEmailHash, uHash);
        }
    }

    //
    // WalletLocator
    //
    if (ctx_.tx.isFieldPresent (sfWalletLocator))
    {
        uint256 const uHash = ctx_.tx.getFieldH256 (sfWalletLocator);

        if (!uHash)
        {
            j_.trace << "unset wallet locator";
            sle->makeFieldAbsent (sfWalletLocator);
        }
        else
        {
            j_.trace << "set wallet locator";
            sle->setFieldH256 (sfWalletLocator, uHash);
        }
    }

    //
    // MessageKey
    //
    if (ctx_.tx.isFieldPresent (sfMessageKey))
    {
        Blob const messageKey = ctx_.tx.getFieldVL (sfMessageKey);

        if (messageKey.empty ())
        {
            j_.debug << "set message key";
            sle->makeFieldAbsent (sfMessageKey);
        }
        else
        {
            j_.debug << "set message key";
            sle->setFieldVL (sfMessageKey, messageKey);
        }
    }

    //
    // Domain
    //
    if (ctx_.tx.isFieldPresent (sfDomain))
    {
        Blob const domain = ctx_.tx.getFieldVL (sfDomain);

        if (domain.empty ())
        {
            j_.trace << "unset domain";
            sle->makeFieldAbsent (sfDomain);
        }
        else
        {
            j_.trace << "set domain";
            sle->setFieldVL (sfDomain, domain);
        }
    }

    //
    // TransferRate
    //
    if (ctx_.tx.isFieldPresent (sfTransferRate))
    {
        std::uint32_t uRate = ctx_.tx.getFieldU32 (sfTransferRate);

        if (uRate == 0 || uRate == QUALITY_ONE)
        {
            j_.trace << "unset transfer rate";
            sle->makeFieldAbsent (sfTransferRate);
        }
        else if (uRate > QUALITY_ONE)
        {
            j_.trace << "set transfer rate";
            sle->setFieldU32 (sfTransferRate, uRate);
        }
    }

    if (uFlagsIn != uFlagsOut)
        sle->setFieldU32 (sfFlags, uFlagsOut);

    return tesSUCCESS;
}
    void run()
    {
        // Construct a seed.
        RippleAddress naSeed;

        expect (naSeed.setSeedGeneric ("masterpassphrase"));
        expect (naSeed.humanSeed () == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", naSeed.humanSeed ());

        // Create node public/private key pair
        RippleAddress naNodePublic    = RippleAddress::createNodePublic (naSeed);
        RippleAddress naNodePrivate   = RippleAddress::createNodePrivate (naSeed);

        expect (naNodePublic.humanNodePublic () == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9", naNodePublic.humanNodePublic ());
        expect (naNodePrivate.humanNodePrivate () == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe", naNodePrivate.humanNodePrivate ());

        // Check node signing.
        Blob vucTextSrc = strCopy ("Hello, nurse!");
        uint256 uHash   = sha512Half(makeSlice(vucTextSrc));
        Blob vucTextSig;

        naNodePrivate.signNodePrivate (uHash, vucTextSig);
        expect (naNodePublic.verifyNodePublic (uHash, vucTextSig, ECDSA::strict), "Verify failed.");

        // Construct a public generator from the seed.
        RippleAddress   generator     = RippleAddress::createGeneratorPublic (naSeed);

        expect (generator.humanGenerator () == "fhuJKrhSDzV2SkjLn9qbwm5AaRmrxDPfFsHDCP6yfDZWcxDFz4mt", generator.humanGenerator ());

        // Create ed25519 account public/private key pair.
        KeyPair keys = generateKeysFromSeed (KeyType::ed25519, naSeed);
        expectEquals (keys.publicKey.humanAccountPublic(), "aKGheSBjmCsKJVuLNKRAKpZXT6wpk2FCuEZAXJupXgdAxX5THCqR");

        // Check ed25519 account signing.
        vucTextSig = keys.secretKey.accountPrivateSign (vucTextSrc);

        expect (!vucTextSig.empty(), "ed25519 signing failed.");
        expect (keys.publicKey.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA()), "ed25519 verify failed.");

        // Create account #0 public/private key pair.
        RippleAddress   naAccountPublic0    = RippleAddress::createAccountPublic (generator, 0);
        RippleAddress   naAccountPrivate0   = RippleAddress::createAccountPrivate (generator, naSeed, 0);

        expect (toBase58(calcAccountID(naAccountPublic0)) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh");
        expect (naAccountPublic0.humanAccountPublic () == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw", naAccountPublic0.humanAccountPublic ());

        // Create account #1 public/private key pair.
        RippleAddress   naAccountPublic1    = RippleAddress::createAccountPublic (generator, 1);
        RippleAddress   naAccountPrivate1   = RippleAddress::createAccountPrivate (generator, naSeed, 1);

        expect (toBase58(calcAccountID(naAccountPublic1)) == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP");
        expect (naAccountPublic1.humanAccountPublic () == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPrw", naAccountPublic1.humanAccountPublic ());

        // Check account signing.
        vucTextSig = naAccountPrivate0.accountPrivateSign (vucTextSrc);

        expect (!vucTextSig.empty(), "Signing failed.");
        expect (naAccountPublic0.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::strict), "Verify failed.");
        expect (!naAccountPublic1.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::not_strict), "Anti-verify failed.");
        expect (!naAccountPublic1.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::strict), "Anti-verify failed.");

        vucTextSig = naAccountPrivate1.accountPrivateSign (vucTextSrc);

        expect (!vucTextSig.empty(), "Signing failed.");
        expect (naAccountPublic1.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::strict), "Verify failed.");
        expect (!naAccountPublic0.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::not_strict), "Anti-verify failed.");
        expect (!naAccountPublic0.accountPublicVerify (vucTextSrc, vucTextSig, ECDSA::strict), "Anti-verify failed.");

        // Check account encryption.
        Blob vucTextCipher
            = naAccountPrivate0.accountPrivateEncrypt (naAccountPublic1, vucTextSrc);
        Blob vucTextRecovered
            = naAccountPrivate1.accountPrivateDecrypt (naAccountPublic0, vucTextCipher);

        expect (vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed.");

        {
            RippleAddress nSeed;
            uint128 seed1, seed2;
            seed1.SetHex ("71ED064155FFADFA38782C5E0158CB26");
            nSeed.setSeed (seed1);
            expect (nSeed.humanSeed() == "shHM53KPZ87Gwdqarm1bAmPeXg8Tn",
                "Incorrect human seed");
            expect (nSeed.humanSeed1751() == "MAD BODY ACE MINT OKAY HUB WHAT DATA SACK FLAT DANA MATH",
                "Incorrect 1751 seed");
        }
    }