Пример #1
0
Blob Manifest::getMasterSignature () const
{
    STObject st (sfGeneric);
    SerialIter sit (serialized.data (), serialized.size ());
    st.set (sit);
    return st.getFieldVL (sfMasterSignature);
}
Пример #2
0
uint256 Manifest::hash () const
{
    STObject st (sfGeneric);
    SerialIter sit (serialized.data (), serialized.size ());
    st.set (sit);
    return st.getHash (HashPrefix::manifest);
}
UPTR_T<SerializedType> STObject::deserialize (SerializerIterator& sit, SField::ref name)
{
    STObject* o;
    UPTR_T<SerializedType> object (o = new STObject (name));
    o->set (sit, 1);
    return object;
}
Пример #4
0
void
FeeVoteImpl::doValidation (Ledger::ref lastClosedLedger,
    STObject& baseValidation)
{
    if (lastClosedLedger->getBaseFee () != target_.reference_fee)
    {
        if (journal_.info) journal_.info <<
            "Voting for base fee of " << target_.reference_fee;

        baseValidation.setFieldU64 (sfBaseFee, target_.reference_fee);
    }

    if (lastClosedLedger->getReserve (0) != target_.account_reserve)
    {
        if (journal_.info) journal_.info <<
            "Voting for base resrve of " << target_.account_reserve;

        baseValidation.setFieldU32(sfReserveBase, target_.account_reserve);
    }

    if (lastClosedLedger->getReserveInc () != target_.owner_reserve)
    {
        if (journal_.info) journal_.info <<
            "Voting for reserve increment of " << target_.owner_reserve;

        baseValidation.setFieldU32 (sfReserveIncrement,
            target_.owner_reserve);
    }
}
Пример #5
0
void
FeeVoteImpl::doValidation(
    std::shared_ptr<ReadView const> const& lastClosedLedger,
        STObject& baseValidation)
{
    if (lastClosedLedger->fees().base != target_.reference_fee)
    {
        if (journal_.info) journal_.info <<
            "Voting for base fee of " << target_.reference_fee;

        baseValidation.setFieldU64 (sfBaseFee, target_.reference_fee);
    }

    if (lastClosedLedger->fees().accountReserve(0) != target_.account_reserve)
    {
        if (journal_.info) journal_.info <<
            "Voting for base resrve of " << target_.account_reserve;

        baseValidation.setFieldU32(sfReserveBase, target_.account_reserve);
    }

    if (lastClosedLedger->fees().increment != target_.owner_reserve)
    {
        if (journal_.info) journal_.info <<
            "Voting for reserve increment of " << target_.owner_reserve;

        baseValidation.setFieldU32 (sfReserveIncrement,
            target_.owner_reserve);
    }
}
Пример #6
0
 // make sure the node exists and force its type
 BOOST_FOREACH (STObject & it, mNodes)
 {
     if (it.getFieldH256 (sfLedgerIndex) == node)
     {
         it.setFName (type);
         it.setFieldU16 (sfLedgerEntryType, nodeType);
         return;
     }
 }
Пример #7
0
STObject TransactionMetaSet::getAsObject () const
{
    STObject metaData (sfTransactionMetaData);
    assert (mResult != 255);
    metaData.setFieldU8 (sfTransactionResult, mResult);
    metaData.setFieldU32 (sfTransactionIndex, mIndex);
    metaData.emplace_back (mNodes);
    if (hasDeliveredAmount ())
        metaData.setFieldAmount (sfDeliveredAmount, getDeliveredAmount ());
    return metaData;
}
Пример #8
0
// Ensure all account fields are 160-bits
static
bool
isAccountFieldOkay (STObject const& st)
{
    for (int i = 0; i < st.getCount(); ++i)
    {
        auto t = dynamic_cast<STAccount const*>(st.peekAtPIndex (i));
        if (t && t->isDefault ())
            return false;
    }

    return true;
}
Пример #9
0
bool STObject::equivalentSTObjectSameTemplate (
    STObject const& obj1, STObject const& obj2)
{
    assert (obj1.mType != nullptr);
    assert (obj1.mType == obj2.mType);

    return std::equal (obj1.begin (), obj1.end (), obj2.begin (), obj2.end (),
        [] (STBase const& st1, STBase const& st2)
        {
            return (st1.getSType() == st2.getSType()) &&
                st1.isEquivalent (st2);
        });
}
Пример #10
0
bool Manifest::verify () const
{
    STObject st (sfGeneric);
    SerialIter sit (serialized.data (), serialized.size ());
    st.set (sit);

    // Signing key and signature are not required for
    // master key revocations
    if (! revoked () && ! ripple::verify (st, HashPrefix::manifest, signingKey))
        return false;

    return ripple::verify (
        st, HashPrefix::manifest, masterKey, sfMasterSignature);
}
Пример #11
0
std::vector<STBase const*>
STObject::getSortedFields (STObject const& objToSort)
{
    std::vector<STBase const*> sf;
    sf.reserve (objToSort.getCount ());

    // Choose the fields that we need to sort.
    for (detail::STVar const& elem : objToSort.v_)
    {
        // Pick out the fields and sort them.
        STBase const& base = elem.get();
        if ((base.getSType () != STI_NOTPRESENT) &&
            base.getFName ().shouldInclude (true))
        {
            sf.push_back (&base);
        }
    }

    // Sort the fields by fieldCode.
    std::sort (sf.begin (), sf.end (),
        [] (STBase const* a, STBase const* b) -> bool
        {
            return a->getFName ().fieldCode < b->getFName ().fieldCode;
        });

    // There should never be duplicate fields in an STObject. Verify that
    // in debug mode.
    assert (std::adjacent_find (sf.cbegin (), sf.cend ()) == sf.cend ());

    return sf;
}
Пример #12
0
boost::optional<Manifest>
Manifest::make_Manifest (std::string s)
{
    try
    {
        STObject st (sfGeneric);
        SerialIter sit (s.data (), s.size ());
        st.set (sit);
        auto const pk = st.getFieldVL (sfPublicKey);
        if (! publicKeyType (makeSlice(pk)))
            return boost::none;

        auto const opt_seq = get (st, sfSequence);
        auto const opt_msig = get (st, sfMasterSignature);
        if (!opt_seq || !opt_msig)
            return boost::none;

        // Signing key and signature are not required for
        // master key revocations
        if (*opt_seq != std::numeric_limits<std::uint32_t>::max ())
        {
            auto const spk = st.getFieldVL (sfSigningPubKey);
            if (! publicKeyType (makeSlice(spk)))
                return boost::none;
            auto const opt_sig = get (st, sfSignature);
            if (! opt_sig)
                return boost::none;

            return Manifest (std::move (s), PublicKey (makeSlice(pk)),
                PublicKey (makeSlice(spk)), *opt_seq);
        }

        return Manifest (std::move (s), PublicKey (makeSlice(pk)),
            PublicKey(), *opt_seq);
    }
    catch (std::exception const&)
    {
        return boost::none;
    }
}
Пример #13
0
std::pair<std::vector<SignerEntries::SignerEntry>, TER>
SignerEntries::deserialize (
    STObject const& obj, beast::Journal journal, std::string const& annotation)
{
    std::pair<std::vector<SignerEntry>, TER> s;

    if (!obj.isFieldPresent (sfSignerEntries))
    {
        if (journal.trace) journal.trace <<
            "Malformed " << annotation << ": Need signer entry array.";
        s.second = temMALFORMED;
        return s;
    }

    auto& accountVec = s.first;
    accountVec.reserve (STTx::maxMultiSigners);

    STArray const& sEntries (obj.getFieldArray (sfSignerEntries));
    for (STObject const& sEntry : sEntries)
    {
        // Validate the SignerEntry.
        if (sEntry.getFName () != sfSignerEntry)
        {
            journal.trace <<
                "Malformed " << annotation << ": Expected SignerEntry.";
            s.second = temMALFORMED;
            return s;
        }

        // Extract SignerEntry fields.
        AccountID const account = sEntry.getAccountID (sfAccount);
        std::uint16_t const weight = sEntry.getFieldU16 (sfSignerWeight);
        accountVec.emplace_back (account, weight);
    }

    s.second = tesSUCCESS;
    return s;
}
Пример #14
0
void
AmendmentTableImpl::doValidation (Ledger::ref lastClosedLedger,
    STObject& baseValidation)
{
    amendmentList_t lAmendments = getDesired();

    if (lAmendments.empty())
        return;

    STVector256 vAmendments (sfAmendments);
    for (auto const& uAmendment : lAmendments)
        vAmendments.push_back (uAmendment);
    vAmendments.sort ();
    baseValidation.setFieldV256 (sfAmendments, vAmendments);
}
Пример #15
0
bool TransactionMetaSet::thread (STObject& node, uint256 const& prevTxID, std::uint32_t prevLgrID)
{
    if (node.getFieldIndex (sfPreviousTxnID) == -1)
    {
        assert (node.getFieldIndex (sfPreviousTxnLgrSeq) == -1);
        node.setFieldH256 (sfPreviousTxnID, prevTxID);
        node.setFieldU32 (sfPreviousTxnLgrSeq, prevLgrID);
        return true;
    }

    assert (node.getFieldH256 (sfPreviousTxnID) == prevTxID);
    assert (node.getFieldU32 (sfPreviousTxnLgrSeq) == prevLgrID);
    return false;
}
Пример #16
0
TxMeta::TxMeta (uint256 const& txid, std::uint32_t ledger, STObject const& obj,
    beast::Journal j)
    : mTransactionID (txid)
    , mLedger (ledger)
    , mNodes (obj.getFieldArray (sfAffectedNodes))
    , j_ (j)
{
    mResult = obj.getFieldU8 (sfTransactionResult);
    mIndex = obj.getFieldU32 (sfTransactionIndex);

    auto affectedNodes = dynamic_cast <STArray const*>
        (obj.peekAtPField (sfAffectedNodes));
    assert (affectedNodes);
    if (affectedNodes)
        mNodes = *affectedNodes;

    if (obj.isFieldPresent (sfDeliveredAmount))
        setDeliveredAmount (obj.getFieldAmount (sfDeliveredAmount));
}
Пример #17
0
static
bool
isMemoOkay (STObject const& st, std::string& reason)
{
    if (!st.isFieldPresent (sfMemos))
        return true;

    auto const& memos = st.getFieldArray (sfMemos);

    // The number 2048 is a preallocation hint, not a hard limit
    // to avoid allocate/copy/free's
    Serializer s (2048);
    memos.add (s);

    // FIXME move the memo limit into a config tunable
    if (s.getDataLength () > 1024)
    {
        reason = "The memo exceeds the maximum allowed size.";
        return false;
    }

    for (auto const& memo : memos)
    {
        auto memoObj = dynamic_cast <STObject const*> (&memo);

        if (!memoObj || (memoObj->getFName() != sfMemo))
        {
            reason = "A memo array may contain only Memo objects.";
            return false;
        }

        for (auto const& memoElement : *memoObj)
        {
            auto const& name = memoElement.getFName();

            if (name != sfMemoType &&
                name != sfMemoData &&
                name != sfMemoFormat)
            {
                reason = "A memo may contain only MemoType, MemoData or "
                         "MemoFormat fields.";
                return false;
            }

            // The raw data is stored as hex-octets, which we want to decode.
            auto data = strUnHex (memoElement.getText ());

            if (!data.second)
            {
                reason = "The MemoType, MemoData and MemoFormat fields may "
                         "only contain hex-encoded data.";
                return false;
            }

            if (name == sfMemoData)
                continue;

            // The only allowed characters for MemoType and MemoFormat are the
            // characters allowed in URLs per RFC 3986: alphanumerics and the
            // following symbols: -._~:/?#[]@!$&'()*+,;=%
            static std::array<char, 256> const allowedSymbols = []
            {
                std::array<char, 256> a;
                a.fill(0);

                std::string symbols (
                    "0123456789"
                    "-._~:/?#[]@!$&'()*+,;=%"
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                    "abcdefghijklmnopqrstuvwxyz");

                for(char c : symbols)
                    a[c] = 1;
                return a;
            }();

            for (auto c : data.first)
            {
                if (!allowedSymbols[c])
                {
                    reason = "The MemoType and MemoFormat fields may only "
                             "contain characters that are allowed in URLs "
                             "under RFC 3986.";
                    return false;
                }
            }
        }
    }

    return true;
}
Пример #18
0
    TER doApply () override
    {
        Account const refereeID (mTxn.getFieldAccount160 (sfDestination));
        Account const referenceID (mTxnAccountID);

        if (!refereeID)
        {
            m_journal.warning <<
                "Malformed transaction: Referee account not specified.";

            return temDST_NEEDED;
        }
        else if (referenceID == refereeID)
        {
            // You're referring yourself.
            m_journal.trace <<
                "Malformed transaction: Redundant transaction:" <<
                " reference=" << to_string(referenceID) <<
                " referee=" << to_string(refereeID);

            return temREDUNDANT;
        }

        //
        // Open a ledger for editing.
        SLE::pointer sleReferee(mEngine->entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(refereeID)));
        SLE::pointer sleReference(mEngine->entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(referenceID)));

        if (!sleReferee) {
            // Referee account does not exist.
            m_journal.trace <<
                "Malformed transaction: Referee account does not exist.";

            return tecNO_DST;
        } else if (!sleReference) {
            // Reference account does not exist.
            m_journal.trace <<
                "Malformed transaction: Reference account does not exist.";

            return terNO_ACCOUNT;
        } else if (sleReference->getFieldAccount(sfReferee).getAccountID().isNonZero())
        {
            // The tag is basically account-specific information we don't
            // understand, but we can require someone to fill it in.

            // We didn't make this test for a newly-formed account because there's
            // no way for this field to be set.
            m_journal.trace << "Malformed transaction: Referee has been set.";

            return tefREFEREE_EXIST;
        }
        else
        {
            // Tell the engine that we are intending to change the the destination
            // account.  The source account gets always charged a fee so it's always
            // marked as modified.
            STArray references = sleReferee->getFieldArray(sfReferences);
            for (auto it = references.begin(); it != references.end(); ++it) {
                Account id = it->getFieldAccount(sfReference).getAccountID();
                if (id == referenceID) {
                    m_journal.trace << "Malformed transaction: Reference has been set.";

                    return tefREFERENCE_EXIST;
                }
            }

            mEngine->entryModify(sleReference);
            mEngine->entryModify(sleReferee);
            sleReference->setFieldAccount(sfReferee, refereeID);
            STObject obj;
            obj.setFieldAccount(sfReference, referenceID);
            references.push_back(obj);
            sleReferee->setFieldArray(sfReferences, references);
        }

        return tesSUCCESS;
    }
Пример #19
0
static bool compare (const STObject& o1, const STObject& o2)
{
    return o1.getFieldH256 (sfLedgerIndex) < o2.getFieldH256 (sfLedgerIndex);
}
Пример #20
0
    void testSerialization ()
    {
        testcase ("serialization");

        unexpected (sfGeneric.isUseful (), "sfGeneric must not be useful");

        SField const& sfTestVL = SField::getField (STI_VL, 255);
        SField const& sfTestH256 = SField::getField (STI_HASH256, 255);
        SField const& sfTestU32 = SField::getField (STI_UINT32, 255);
        SField const& sfTestObject = SField::getField (STI_OBJECT, 255);

        SOTemplate elements;
        elements.push_back (SOElement (sfFlags, SOE_REQUIRED));
        elements.push_back (SOElement (sfTestVL, SOE_REQUIRED));
        elements.push_back (SOElement (sfTestH256, SOE_OPTIONAL));
        elements.push_back (SOElement (sfTestU32, SOE_REQUIRED));

        STObject object1 (elements, sfTestObject);
        STObject object2 (object1);

        unexpected (object1.getSerializer () != object2.getSerializer (),
            "STObject error 1");

        unexpected (object1.isFieldPresent (sfTestH256) ||
            !object1.isFieldPresent (sfTestVL), "STObject error");

        object1.makeFieldPresent (sfTestH256);

        unexpected (!object1.isFieldPresent (sfTestH256), "STObject Error 2");

        unexpected (object1.getFieldH256 (sfTestH256) != uint256 (),
            "STObject error 3");

        if (object1.getSerializer () == object2.getSerializer ())
        {
            WriteLog (lsINFO, STObject) << "O1: " << object1.getJson (0);
            WriteLog (lsINFO, STObject) << "O2: " << object2.getJson (0);
            fail ("STObject error 4");
        }
        else
        {
            pass ();
        }

        object1.makeFieldAbsent (sfTestH256);

        unexpected (object1.isFieldPresent (sfTestH256), "STObject error 5");

        unexpected (object1.getFlags () != 0, "STObject error 6");

        unexpected (object1.getSerializer () != object2.getSerializer (),
            "STObject error 7");

        STObject copy (object1);

        unexpected (object1.isFieldPresent (sfTestH256), "STObject error 8");

        unexpected (copy.isFieldPresent (sfTestH256), "STObject error 9");

        unexpected (object1.getSerializer () != copy.getSerializer (),
            "STObject error 10");

        copy.setFieldU32 (sfTestU32, 1);

        unexpected (object1.getSerializer () == copy.getSerializer (),
            "STObject error 11");

        for (int i = 0; i < 1000; i++)
        {
            Blob j (i, 2);

            object1.setFieldVL (sfTestVL, j);

            Serializer s;
            object1.add (s);
            SerialIter it (s.slice());

            STObject object3 (elements, it, sfTestObject);

            unexpected (object1.getFieldVL (sfTestVL) != j, "STObject error");

            unexpected (object3.getFieldVL (sfTestVL) != j, "STObject error");
        }
    }