mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
- Add the LendingProtocol amendment
- Add Loan Broker and Loan ledger objects:
- Also add new SFields, Keylet functions, and an Invariant to verify no
illegal field modification
- Update list of "constant" fields from spec
- Also add a general check for all object types for the type and index
fields
- refactor: Check transaction flags in preflight0
- Adds a flagMask parameter to preflight1 so that it's impossible to
forget to check flags.
- Also adds a short hash prefix to all Transactor log messages.
- refactor: Generalize Transactor preflight:
- Derived classes no longer need to explicitly check amendments, nor
call into preflight1 or preflight2.
- implemeng LoanBrokerSet
- Transactions: LoanDelete, LoanManage, LoanDraw, LoanPay
- LoanBrokerSet creation mostly done. Need update.
- Also added a lookup table for pseudo account fields.
- Update changed field name.
- Modify modifiable fields in an update. Note there are only two.
- Add a node field to dirLink, defaulting sfOwnerNode, so other
relationships can be updated.
- Create some helper classes for transaction fields
- Test that they work by converting some of the existing classes
- Finish creating helper classes for JTx fields
- Also change the pseudo account field lookup to a function that uses
a switch
- Update tests, update pseudo-account checking
- Generalize some of the Invariant checks using macro files
- Valid ledger entry type
- Valid new account root and pseudo account check
- Enumerate transaction privileges for invariants
- Allows them to be defined in transactions.macro instead of needing to
scrutinize every existing Invariant class.
- List is not necessarily comprehensive, but does cover every check
where more than one transaction type is involved.
- Reserve a few values between Vault and Lending for future use
- Pseudo-account improvements
- Define pseudo-account fields with an sfield flag
- Pseudo-account invariant checks rules whenever a pseudo-account is
created or modified.
- Move some helper functions.
- Check the regular key in the pseudo-transaction invariant check.
- Transactor::checkSign will always fail for a pseudo-account, so even
if someone figures out how to get a good signature, it won't work.
- Fix account creation to check both amendments
- Add a validity range for sfDebtMaximum
- Change more "failed" messages. The goal here is to be able to search
the log for "failed" and ONLY get test failures.
- NoModifiedUnmodifiableFields and ValidPseudoAccounts
- Move the Invariants_test class into the test namespace
- Clang wants an explicit ctor to emplace in a vector
- Refactor: Add a Transactor base function to make it easier to get the
owner reserve increment as a fee.
- Refactor: Add an overload jtx::fee(increment) to pay an owner reserve.
- Initial implementation of LoanBrokerDelete
- Generalize the LoanBroker lifecycle test
- Refactor ApplyView::dirAdd to give access to low-level operations
- Takes a page from #5362, which may turn out to be useful!
- Start writing Loan Broker invariants and tests
- Specifically those mentioned for LoanBrokerDelete
- Move all detail namespaces to be under ripple
- Avoids problems with namespace collisions / ambiguous symbol issues
with unity builds, especially when adding or removing files.
- Add LoanBrokerCoverDeposit transaction
- Add LoanBrokerCoverWithdraw transaction
- Start writing tests for LoanBrokerCover*
- Add support for `Asset` and `MPTIssue` to some `jtx` helper classes
and functions (`balance`, `expectLine`)
- Add support for pseudo-accounts to `jtx::Account` by allowing directly
setting the AccountID without a matching key.
- Add Asset and MPTIssue support to more jtx objects / functions
- Unfortunately, to work around some ambiguous symbol compilation
errors, I had to change the implicit conversion from IOU to Asset to
a conversion from IOU to PrettyAsset, and add a more explicit
`asset()` function. This workaround only required changing two
existing tests, so seems acceptable.
- Ensure that an account is not deleted with an XRP balance
- Updates the AccountRootsDeletedClean invariant
- Finish up the Loan Broker tests
- Move inclusion of Transactor headers to transactions.macro
- Only need to update in one place when adding a new transaction.
- Start implementing LoanSet transactor
- Add some more values and functions to make it easier to work with
basis point values / bips.
- Fix several earlier mistakes.
- Generalize the check*Sign functions to support CounterParty
- checkSign, checkSingleSign, and checkMultiSign in STTx and Transactor
- Start writing Loan tests
- Required adding support for counterparty signature to jtx framework:
arbitrary signature field destination, multiple signer callbacks
- Get Counterparty signing working
- Add more LoanSet unit tests, added LoanBroker LoanSequence field
- LoanSequence will prevent loan key collisions
- Change Loan object indexing, fix several broken LoanSet unit tests
- Loan objects will now only be indexed by LoanBrokerID and
LoanSequence, which is a new field in LoanBroker. Also changes
Loan.Sequence to Loan.LoanSequence to match up.
- Several tests weren't working because of `PrettyAsset` scaling. Also,
`PrettyAsset` calculations could overflow. Made that less likely by
changing the type of `scale_`.
- LoanSet will fail if an account tries to loan to itself.
- Ensure that an account is not deleted with a non-zero owner count
- Updates the AccountRootsDeletedClean invariant
- Add unit tests to create a Loan successfully
- Fix a few field initializations in LoanSet
- Refactor issuance validity check in VaultCreate
- Utility function: canAddHolding
- Call canAddHolding from any transactor that call addEmptyHolding
(LoanBrokerSet, LoanSet)
- Start implementing LoanManage transaction
- Also add a ValidLoan invariant
- Finish `LoanManage` functionality and tests, modulo LoanDraw/Pay
- Allow existing trust lines to loan brokers to be managed (by issuer)
- Implement LoanDelete, and fix a bunch of math errors in LoanManage
- Update to match latest spec: compute interest, LoanBroker reserves
- refactor: Define getFlagsMask in the base Transactor class
- Returns tfUniversalMask for most transactors
- Only transactors that use other flags need to override
- Implement LoanDraw, and made good progress on related tests
- Start implementing LoanPay transaction
- Implement LoanPay
- Also add an XRPL_ASSERT2, which splits the parts of the assert message
so I don't have to remember the proper formatting.
488 lines
10 KiB
C++
488 lines
10 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of rippled: https://github.com/ripple/rippled
|
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#ifndef RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED
|
|
#define RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED
|
|
|
|
#include <xrpl/basics/Blob.h>
|
|
#include <xrpl/basics/Buffer.h>
|
|
#include <xrpl/basics/Slice.h>
|
|
#include <xrpl/basics/base_uint.h>
|
|
#include <xrpl/basics/contract.h>
|
|
#include <xrpl/basics/safe_cast.h>
|
|
#include <xrpl/basics/strHex.h>
|
|
#include <xrpl/beast/utility/instrumentation.h>
|
|
#include <xrpl/protocol/HashPrefix.h>
|
|
#include <xrpl/protocol/SField.h>
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <iomanip>
|
|
#include <type_traits>
|
|
|
|
namespace ripple {
|
|
|
|
class Serializer
|
|
{
|
|
private:
|
|
// DEPRECATED
|
|
Blob mData;
|
|
|
|
public:
|
|
explicit Serializer(int n = 256)
|
|
{
|
|
mData.reserve(n);
|
|
}
|
|
|
|
Serializer(void const* data, std::size_t size)
|
|
{
|
|
mData.resize(size);
|
|
|
|
if (size)
|
|
{
|
|
XRPL_ASSERT(
|
|
data,
|
|
"ripple::Serializer::Serializer(void const*) : non-null input");
|
|
std::memcpy(mData.data(), data, size);
|
|
}
|
|
}
|
|
|
|
Slice
|
|
slice() const noexcept
|
|
{
|
|
return Slice(mData.data(), mData.size());
|
|
}
|
|
|
|
std::size_t
|
|
size() const noexcept
|
|
{
|
|
return mData.size();
|
|
}
|
|
|
|
void const*
|
|
data() const noexcept
|
|
{
|
|
return mData.data();
|
|
}
|
|
|
|
// assemble functions
|
|
int
|
|
add8(unsigned char i);
|
|
int
|
|
add16(std::uint16_t i);
|
|
|
|
template <typename T>
|
|
requires(std::is_same_v<
|
|
std::make_unsigned_t<std::remove_cv_t<T>>,
|
|
std::uint32_t>)
|
|
int
|
|
add32(T i)
|
|
{
|
|
int ret = mData.size();
|
|
mData.push_back(static_cast<unsigned char>((i >> 24) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 16) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 8) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>(i & 0xff));
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
add32(HashPrefix p);
|
|
|
|
template <typename T>
|
|
requires(std::is_same_v<
|
|
std::make_unsigned_t<std::remove_cv_t<T>>,
|
|
std::uint64_t>)
|
|
int
|
|
add64(T i)
|
|
{
|
|
int ret = mData.size();
|
|
mData.push_back(static_cast<unsigned char>((i >> 56) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 48) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 40) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 32) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 24) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 16) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>((i >> 8) & 0xff));
|
|
mData.push_back(static_cast<unsigned char>(i & 0xff));
|
|
return ret;
|
|
}
|
|
|
|
template <typename Integer>
|
|
requires(!HasValue<Integer>)
|
|
int addInteger(Integer);
|
|
|
|
template <typename Integer>
|
|
requires HasValue<Integer>
|
|
int
|
|
addInteger(Integer i)
|
|
{
|
|
return addInteger(i.value());
|
|
}
|
|
|
|
template <std::size_t Bits, class Tag>
|
|
int
|
|
addBitString(base_uint<Bits, Tag> const& v)
|
|
{
|
|
return addRaw(v.data(), v.size());
|
|
}
|
|
|
|
int
|
|
addRaw(Blob const& vector);
|
|
int
|
|
addRaw(Slice slice);
|
|
int
|
|
addRaw(void const* ptr, int len);
|
|
int
|
|
addRaw(Serializer const& s);
|
|
|
|
int
|
|
addVL(Blob const& vector);
|
|
int
|
|
addVL(Slice const& slice);
|
|
template <class Iter>
|
|
int
|
|
addVL(Iter begin, Iter end, int len);
|
|
int
|
|
addVL(void const* ptr, int len);
|
|
|
|
// disassemble functions
|
|
bool
|
|
get8(int&, int offset) const;
|
|
|
|
template <typename Integer>
|
|
bool
|
|
getInteger(Integer& number, int offset)
|
|
{
|
|
static auto const bytes = sizeof(Integer);
|
|
if ((offset + bytes) > mData.size())
|
|
return false;
|
|
number = 0;
|
|
|
|
auto ptr = &mData[offset];
|
|
for (auto i = 0; i < bytes; ++i)
|
|
{
|
|
if (i)
|
|
number <<= 8;
|
|
number |= *ptr++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <std::size_t Bits, typename Tag = void>
|
|
bool
|
|
getBitString(base_uint<Bits, Tag>& data, int offset) const
|
|
{
|
|
auto success = (offset + (Bits / 8)) <= mData.size();
|
|
if (success)
|
|
memcpy(data.begin(), &(mData.front()) + offset, (Bits / 8));
|
|
return success;
|
|
}
|
|
|
|
int
|
|
addFieldID(int type, int name);
|
|
int
|
|
addFieldID(SerializedTypeID type, int name)
|
|
{
|
|
return addFieldID(safe_cast<int>(type), name);
|
|
}
|
|
|
|
// DEPRECATED
|
|
uint256
|
|
getSHA512Half() const;
|
|
|
|
// totality functions
|
|
Blob const&
|
|
peekData() const
|
|
{
|
|
return mData;
|
|
}
|
|
Blob
|
|
getData() const
|
|
{
|
|
return mData;
|
|
}
|
|
Blob&
|
|
modData()
|
|
{
|
|
return mData;
|
|
}
|
|
|
|
int
|
|
getDataLength() const
|
|
{
|
|
return mData.size();
|
|
}
|
|
void const*
|
|
getDataPtr() const
|
|
{
|
|
return mData.data();
|
|
}
|
|
void*
|
|
getDataPtr()
|
|
{
|
|
return mData.data();
|
|
}
|
|
int
|
|
getLength() const
|
|
{
|
|
return mData.size();
|
|
}
|
|
std::string
|
|
getString() const
|
|
{
|
|
return std::string(static_cast<char const*>(getDataPtr()), size());
|
|
}
|
|
void
|
|
erase()
|
|
{
|
|
mData.clear();
|
|
}
|
|
bool
|
|
chop(int num);
|
|
|
|
// vector-like functions
|
|
Blob ::iterator
|
|
begin()
|
|
{
|
|
return mData.begin();
|
|
}
|
|
Blob ::iterator
|
|
end()
|
|
{
|
|
return mData.end();
|
|
}
|
|
Blob ::const_iterator
|
|
begin() const
|
|
{
|
|
return mData.begin();
|
|
}
|
|
Blob ::const_iterator
|
|
end() const
|
|
{
|
|
return mData.end();
|
|
}
|
|
void
|
|
reserve(size_t n)
|
|
{
|
|
mData.reserve(n);
|
|
}
|
|
void
|
|
resize(size_t n)
|
|
{
|
|
mData.resize(n);
|
|
}
|
|
size_t
|
|
capacity() const
|
|
{
|
|
return mData.capacity();
|
|
}
|
|
|
|
bool
|
|
operator==(Blob const& v) const
|
|
{
|
|
return v == mData;
|
|
}
|
|
bool
|
|
operator!=(Blob const& v) const
|
|
{
|
|
return v != mData;
|
|
}
|
|
bool
|
|
operator==(Serializer const& v) const
|
|
{
|
|
return v.mData == mData;
|
|
}
|
|
bool
|
|
operator!=(Serializer const& v) const
|
|
{
|
|
return v.mData != mData;
|
|
}
|
|
|
|
static int
|
|
decodeLengthLength(int b1);
|
|
static int
|
|
decodeVLLength(int b1);
|
|
static int
|
|
decodeVLLength(int b1, int b2);
|
|
static int
|
|
decodeVLLength(int b1, int b2, int b3);
|
|
|
|
private:
|
|
static int
|
|
encodeLengthLength(int length); // length to encode length
|
|
int
|
|
addEncoded(int length);
|
|
};
|
|
|
|
template <class Iter>
|
|
int
|
|
Serializer::addVL(Iter begin, Iter end, int len)
|
|
{
|
|
int ret = addEncoded(len);
|
|
for (; begin != end; ++begin)
|
|
{
|
|
addRaw(begin->data(), begin->size());
|
|
#ifndef NDEBUG
|
|
len -= begin->size();
|
|
#endif
|
|
}
|
|
XRPL_ASSERT(
|
|
len == 0, "ripple::Serializer::addVL : length matches distance");
|
|
return ret;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// DEPRECATED
|
|
// Transitional adapter to new serialization interfaces
|
|
class SerialIter
|
|
{
|
|
private:
|
|
std::uint8_t const* p_;
|
|
std::size_t remain_;
|
|
std::size_t used_ = 0;
|
|
|
|
public:
|
|
SerialIter(void const* data, std::size_t size) noexcept;
|
|
|
|
SerialIter(Slice const& slice) : SerialIter(slice.data(), slice.size())
|
|
{
|
|
}
|
|
|
|
// Infer the size of the data based on the size of the passed array.
|
|
template <int N>
|
|
explicit SerialIter(std::uint8_t const (&data)[N]) : SerialIter(&data[0], N)
|
|
{
|
|
static_assert(N > 0, "");
|
|
}
|
|
|
|
std::size_t
|
|
empty() const noexcept
|
|
{
|
|
return remain_ == 0;
|
|
}
|
|
|
|
void
|
|
reset() noexcept;
|
|
|
|
int
|
|
getBytesLeft() const noexcept
|
|
{
|
|
return static_cast<int>(remain_);
|
|
}
|
|
|
|
// get functions throw on error
|
|
unsigned char
|
|
get8();
|
|
|
|
std::uint16_t
|
|
get16();
|
|
|
|
std::uint32_t
|
|
get32();
|
|
std::int32_t
|
|
geti32();
|
|
|
|
std::uint64_t
|
|
get64();
|
|
std::int64_t
|
|
geti64();
|
|
|
|
template <std::size_t Bits, class Tag = void>
|
|
base_uint<Bits, Tag>
|
|
getBitString();
|
|
|
|
uint128
|
|
get128()
|
|
{
|
|
return getBitString<128>();
|
|
}
|
|
|
|
uint160
|
|
get160()
|
|
{
|
|
return getBitString<160>();
|
|
}
|
|
|
|
uint192
|
|
get192()
|
|
{
|
|
return getBitString<192>();
|
|
}
|
|
|
|
uint256
|
|
get256()
|
|
{
|
|
return getBitString<256>();
|
|
}
|
|
|
|
void
|
|
getFieldID(int& type, int& name);
|
|
|
|
// Returns the size of the VL if the
|
|
// next object is a VL. Advances the iterator
|
|
// to the beginning of the VL.
|
|
int
|
|
getVLDataLength();
|
|
|
|
Slice
|
|
getSlice(std::size_t bytes);
|
|
|
|
// VFALCO DEPRECATED Returns a copy
|
|
Blob
|
|
getRaw(int size);
|
|
|
|
// VFALCO DEPRECATED Returns a copy
|
|
Blob
|
|
getVL();
|
|
|
|
void
|
|
skip(int num);
|
|
|
|
Buffer
|
|
getVLBuffer();
|
|
|
|
template <class T>
|
|
T
|
|
getRawHelper(int size);
|
|
};
|
|
|
|
template <std::size_t Bits, class Tag>
|
|
base_uint<Bits, Tag>
|
|
SerialIter::getBitString()
|
|
{
|
|
auto const n = Bits / 8;
|
|
|
|
if (remain_ < n)
|
|
Throw<std::runtime_error>("invalid SerialIter getBitString");
|
|
|
|
auto const x = p_;
|
|
|
|
p_ += n;
|
|
used_ += n;
|
|
remain_ -= n;
|
|
|
|
return base_uint<Bits, Tag>::fromVoid(x);
|
|
}
|
|
|
|
} // namespace ripple
|
|
|
|
#endif
|