mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Compare commits
28 Commits
Bronek/len
...
ab9644267d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab9644267d | ||
|
|
25c5e3b17f | ||
|
|
8eb233c2ea | ||
|
|
50fc93f742 | ||
|
|
ab45a8a737 | ||
|
|
dfafb141cc | ||
|
|
4e32d2ed98 | ||
|
|
fa69918124 | ||
|
|
cbbb2b1be0 | ||
|
|
cf2d763fa1 | ||
|
|
2dd1d682ac | ||
|
|
4cb1084c02 | ||
|
|
8d1b3b3994 | ||
|
|
b39d7a6519 | ||
|
|
b0910e359e | ||
|
|
44e027e516 | ||
|
|
a10f42a3aa | ||
|
|
efd4c1b95d | ||
|
|
415a412d42 | ||
|
|
2cc54c7c3f | ||
|
|
33e1a19a2e | ||
|
|
12aa7c877a | ||
|
|
bcf9a1ae38 | ||
|
|
f9c642c2b5 | ||
|
|
ba7b561a29 | ||
|
|
265284249c | ||
|
|
6050b84151 | ||
|
|
9006bbda9d |
@@ -17,7 +17,7 @@ Loop: xrpld.app xrpld.rpc
|
|||||||
xrpld.rpc > xrpld.app
|
xrpld.rpc > xrpld.app
|
||||||
|
|
||||||
Loop: xrpld.app xrpld.shamap
|
Loop: xrpld.app xrpld.shamap
|
||||||
xrpld.app > xrpld.shamap
|
xrpld.shamap ~= xrpld.app
|
||||||
|
|
||||||
Loop: xrpld.core xrpld.perflog
|
Loop: xrpld.core xrpld.perflog
|
||||||
xrpld.perflog == xrpld.core
|
xrpld.perflog == xrpld.core
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ libxrpl.ledger > xrpl.ledger
|
|||||||
libxrpl.ledger > xrpl.protocol
|
libxrpl.ledger > xrpl.protocol
|
||||||
libxrpl.net > xrpl.basics
|
libxrpl.net > xrpl.basics
|
||||||
libxrpl.net > xrpl.net
|
libxrpl.net > xrpl.net
|
||||||
|
libxrpl.nodestore > xrpl.basics
|
||||||
|
libxrpl.nodestore > xrpl.json
|
||||||
|
libxrpl.nodestore > xrpl.nodestore
|
||||||
|
libxrpl.nodestore > xrpl.protocol
|
||||||
libxrpl.protocol > xrpl.basics
|
libxrpl.protocol > xrpl.basics
|
||||||
libxrpl.protocol > xrpl.json
|
libxrpl.protocol > xrpl.json
|
||||||
libxrpl.protocol > xrpl.protocol
|
libxrpl.protocol > xrpl.protocol
|
||||||
@@ -18,6 +22,9 @@ libxrpl.server > xrpl.basics
|
|||||||
libxrpl.server > xrpl.json
|
libxrpl.server > xrpl.json
|
||||||
libxrpl.server > xrpl.protocol
|
libxrpl.server > xrpl.protocol
|
||||||
libxrpl.server > xrpl.server
|
libxrpl.server > xrpl.server
|
||||||
|
libxrpl.shamap > xrpl.basics
|
||||||
|
libxrpl.shamap > xrpl.protocol
|
||||||
|
libxrpl.shamap > xrpl.shamap
|
||||||
test.app > test.jtx
|
test.app > test.jtx
|
||||||
test.app > test.rpc
|
test.app > test.rpc
|
||||||
test.app > test.toplevel
|
test.app > test.toplevel
|
||||||
@@ -25,11 +32,11 @@ test.app > test.unit_test
|
|||||||
test.app > xrpl.basics
|
test.app > xrpl.basics
|
||||||
test.app > xrpld.app
|
test.app > xrpld.app
|
||||||
test.app > xrpld.core
|
test.app > xrpld.core
|
||||||
test.app > xrpld.nodestore
|
|
||||||
test.app > xrpld.overlay
|
test.app > xrpld.overlay
|
||||||
test.app > xrpld.rpc
|
test.app > xrpld.rpc
|
||||||
test.app > xrpl.json
|
test.app > xrpl.json
|
||||||
test.app > xrpl.ledger
|
test.app > xrpl.ledger
|
||||||
|
test.app > xrpl.nodestore
|
||||||
test.app > xrpl.protocol
|
test.app > xrpl.protocol
|
||||||
test.app > xrpl.resource
|
test.app > xrpl.resource
|
||||||
test.basics > test.jtx
|
test.basics > test.jtx
|
||||||
@@ -86,8 +93,7 @@ test.nodestore > test.toplevel
|
|||||||
test.nodestore > test.unit_test
|
test.nodestore > test.unit_test
|
||||||
test.nodestore > xrpl.basics
|
test.nodestore > xrpl.basics
|
||||||
test.nodestore > xrpld.core
|
test.nodestore > xrpld.core
|
||||||
test.nodestore > xrpld.nodestore
|
test.nodestore > xrpl.nodestore
|
||||||
test.nodestore > xrpld.unity
|
|
||||||
test.overlay > test.jtx
|
test.overlay > test.jtx
|
||||||
test.overlay > test.toplevel
|
test.overlay > test.toplevel
|
||||||
test.overlay > test.unit_test
|
test.overlay > test.unit_test
|
||||||
@@ -95,8 +101,8 @@ test.overlay > xrpl.basics
|
|||||||
test.overlay > xrpld.app
|
test.overlay > xrpld.app
|
||||||
test.overlay > xrpld.overlay
|
test.overlay > xrpld.overlay
|
||||||
test.overlay > xrpld.peerfinder
|
test.overlay > xrpld.peerfinder
|
||||||
test.overlay > xrpld.shamap
|
|
||||||
test.overlay > xrpl.protocol
|
test.overlay > xrpl.protocol
|
||||||
|
test.overlay > xrpl.shamap
|
||||||
test.peerfinder > test.beast
|
test.peerfinder > test.beast
|
||||||
test.peerfinder > test.unit_test
|
test.peerfinder > test.unit_test
|
||||||
test.peerfinder > xrpl.basics
|
test.peerfinder > xrpl.basics
|
||||||
@@ -131,19 +137,22 @@ test.server > xrpl.json
|
|||||||
test.server > xrpl.server
|
test.server > xrpl.server
|
||||||
test.shamap > test.unit_test
|
test.shamap > test.unit_test
|
||||||
test.shamap > xrpl.basics
|
test.shamap > xrpl.basics
|
||||||
test.shamap > xrpld.nodestore
|
test.shamap > xrpl.nodestore
|
||||||
test.shamap > xrpld.shamap
|
|
||||||
test.shamap > xrpl.protocol
|
test.shamap > xrpl.protocol
|
||||||
|
test.shamap > xrpl.shamap
|
||||||
test.toplevel > test.csf
|
test.toplevel > test.csf
|
||||||
test.toplevel > xrpl.json
|
test.toplevel > xrpl.json
|
||||||
test.unit_test > xrpl.basics
|
test.unit_test > xrpl.basics
|
||||||
tests.libxrpl > xrpl.basics
|
tests.libxrpl > xrpl.basics
|
||||||
|
tests.libxrpl > xrpl.ledger
|
||||||
tests.libxrpl > xrpl.json
|
tests.libxrpl > xrpl.json
|
||||||
tests.libxrpl > xrpl.net
|
tests.libxrpl > xrpl.net
|
||||||
xrpl.json > xrpl.basics
|
xrpl.json > xrpl.basics
|
||||||
xrpl.ledger > xrpl.basics
|
xrpl.ledger > xrpl.basics
|
||||||
xrpl.ledger > xrpl.protocol
|
xrpl.ledger > xrpl.protocol
|
||||||
xrpl.net > xrpl.basics
|
xrpl.net > xrpl.basics
|
||||||
|
xrpl.nodestore > xrpl.basics
|
||||||
|
xrpl.nodestore > xrpl.protocol
|
||||||
xrpl.protocol > xrpl.basics
|
xrpl.protocol > xrpl.basics
|
||||||
xrpl.protocol > xrpl.json
|
xrpl.protocol > xrpl.json
|
||||||
xrpl.resource > xrpl.basics
|
xrpl.resource > xrpl.basics
|
||||||
@@ -152,17 +161,21 @@ xrpl.resource > xrpl.protocol
|
|||||||
xrpl.server > xrpl.basics
|
xrpl.server > xrpl.basics
|
||||||
xrpl.server > xrpl.json
|
xrpl.server > xrpl.json
|
||||||
xrpl.server > xrpl.protocol
|
xrpl.server > xrpl.protocol
|
||||||
|
xrpl.shamap > xrpl.basics
|
||||||
|
xrpl.shamap > xrpl.nodestore
|
||||||
|
xrpl.shamap > xrpl.protocol
|
||||||
xrpld.app > test.unit_test
|
xrpld.app > test.unit_test
|
||||||
xrpld.app > xrpl.basics
|
xrpld.app > xrpl.basics
|
||||||
xrpld.app > xrpld.conditions
|
xrpld.app > xrpld.conditions
|
||||||
xrpld.app > xrpld.consensus
|
xrpld.app > xrpld.consensus
|
||||||
xrpld.app > xrpld.nodestore
|
|
||||||
xrpld.app > xrpld.perflog
|
xrpld.app > xrpld.perflog
|
||||||
xrpld.app > xrpl.json
|
xrpld.app > xrpl.json
|
||||||
xrpld.app > xrpl.ledger
|
xrpld.app > xrpl.ledger
|
||||||
xrpld.app > xrpl.net
|
xrpld.app > xrpl.net
|
||||||
|
xrpld.app > xrpl.nodestore
|
||||||
xrpld.app > xrpl.protocol
|
xrpld.app > xrpl.protocol
|
||||||
xrpld.app > xrpl.resource
|
xrpld.app > xrpl.resource
|
||||||
|
xrpld.app > xrpl.shamap
|
||||||
xrpld.conditions > xrpl.basics
|
xrpld.conditions > xrpl.basics
|
||||||
xrpld.conditions > xrpl.protocol
|
xrpld.conditions > xrpl.protocol
|
||||||
xrpld.consensus > xrpl.basics
|
xrpld.consensus > xrpl.basics
|
||||||
@@ -172,11 +185,6 @@ xrpld.core > xrpl.basics
|
|||||||
xrpld.core > xrpl.json
|
xrpld.core > xrpl.json
|
||||||
xrpld.core > xrpl.net
|
xrpld.core > xrpl.net
|
||||||
xrpld.core > xrpl.protocol
|
xrpld.core > xrpl.protocol
|
||||||
xrpld.nodestore > xrpl.basics
|
|
||||||
xrpld.nodestore > xrpld.core
|
|
||||||
xrpld.nodestore > xrpld.unity
|
|
||||||
xrpld.nodestore > xrpl.json
|
|
||||||
xrpld.nodestore > xrpl.protocol
|
|
||||||
xrpld.overlay > xrpl.basics
|
xrpld.overlay > xrpl.basics
|
||||||
xrpld.overlay > xrpld.core
|
xrpld.overlay > xrpld.core
|
||||||
xrpld.overlay > xrpld.peerfinder
|
xrpld.overlay > xrpld.peerfinder
|
||||||
@@ -192,13 +200,11 @@ xrpld.perflog > xrpl.basics
|
|||||||
xrpld.perflog > xrpl.json
|
xrpld.perflog > xrpl.json
|
||||||
xrpld.rpc > xrpl.basics
|
xrpld.rpc > xrpl.basics
|
||||||
xrpld.rpc > xrpld.core
|
xrpld.rpc > xrpld.core
|
||||||
xrpld.rpc > xrpld.nodestore
|
|
||||||
xrpld.rpc > xrpl.json
|
xrpld.rpc > xrpl.json
|
||||||
xrpld.rpc > xrpl.ledger
|
xrpld.rpc > xrpl.ledger
|
||||||
xrpld.rpc > xrpl.net
|
xrpld.rpc > xrpl.net
|
||||||
|
xrpld.rpc > xrpl.nodestore
|
||||||
xrpld.rpc > xrpl.protocol
|
xrpld.rpc > xrpl.protocol
|
||||||
xrpld.rpc > xrpl.resource
|
xrpld.rpc > xrpl.resource
|
||||||
xrpld.rpc > xrpl.server
|
xrpld.rpc > xrpl.server
|
||||||
xrpld.shamap > xrpl.basics
|
xrpld.shamap > xrpl.shamap
|
||||||
xrpld.shamap > xrpld.nodestore
|
|
||||||
xrpld.shamap > xrpl.protocol
|
|
||||||
|
|||||||
2
.github/workflows/reusable-build.yml
vendored
2
.github/workflows/reusable-build.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
|
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||||
with:
|
with:
|
||||||
disable_ccache: false
|
disable_ccache: false
|
||||||
|
|
||||||
|
|||||||
9
.github/workflows/reusable-test.yml
vendored
9
.github/workflows/reusable-test.yml
vendored
@@ -100,3 +100,12 @@ jobs:
|
|||||||
"$test_file"
|
"$test_file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
- name: Debug failure (Linux)
|
||||||
|
if: ${{ failure() && runner.os == 'Linux' && inputs.run_tests }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "IPv4 local port range:"
|
||||||
|
cat /proc/sys/net/ipv4/ip_local_port_range
|
||||||
|
echo "Netstat:"
|
||||||
|
netstat -an
|
||||||
|
|||||||
2
.github/workflows/upload-conan-deps.yml
vendored
2
.github/workflows/upload-conan-deps.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
|||||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||||
|
|
||||||
- name: Prepare runner
|
- name: Prepare runner
|
||||||
uses: XRPLF/actions/.github/actions/prepare-runner@638e0dc11ea230f91bd26622fb542116bb5254d5
|
uses: XRPLF/actions/.github/actions/prepare-runner@99685816bb60a95a66852f212f382580e180df3a
|
||||||
with:
|
with:
|
||||||
disable_ccache: false
|
disable_ccache: false
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ if (static OR APPLE OR MSVC)
|
|||||||
set (OPENSSL_USE_STATIC_LIBS ON)
|
set (OPENSSL_USE_STATIC_LIBS ON)
|
||||||
endif ()
|
endif ()
|
||||||
set (OPENSSL_MSVC_STATIC_RT ON)
|
set (OPENSSL_MSVC_STATIC_RT ON)
|
||||||
find_dependency (OpenSSL 1.1.1 REQUIRED)
|
find_dependency (OpenSSL REQUIRED)
|
||||||
find_dependency (ZLIB)
|
find_dependency (ZLIB)
|
||||||
find_dependency (date)
|
find_dependency (date)
|
||||||
if (TARGET ZLIB::ZLIB)
|
if (TARGET ZLIB::ZLIB)
|
||||||
|
|||||||
@@ -53,14 +53,15 @@ add_library(xrpl.imports.main INTERFACE)
|
|||||||
|
|
||||||
target_link_libraries(xrpl.imports.main
|
target_link_libraries(xrpl.imports.main
|
||||||
INTERFACE
|
INTERFACE
|
||||||
LibArchive::LibArchive
|
|
||||||
OpenSSL::Crypto
|
|
||||||
Ripple::boost
|
|
||||||
Ripple::opts
|
|
||||||
Ripple::syslibs
|
|
||||||
absl::random_random
|
absl::random_random
|
||||||
date::date
|
date::date
|
||||||
ed25519::ed25519
|
ed25519::ed25519
|
||||||
|
LibArchive::LibArchive
|
||||||
|
OpenSSL::Crypto
|
||||||
|
Ripple::boost
|
||||||
|
Ripple::libs
|
||||||
|
Ripple::opts
|
||||||
|
Ripple::syslibs
|
||||||
secp256k1::secp256k1
|
secp256k1::secp256k1
|
||||||
xrpl.libpb
|
xrpl.libpb
|
||||||
xxHash::xxhash
|
xxHash::xxhash
|
||||||
@@ -111,6 +112,21 @@ target_link_libraries(xrpl.libxrpl.net PUBLIC
|
|||||||
add_module(xrpl server)
|
add_module(xrpl server)
|
||||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
|
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol)
|
||||||
|
|
||||||
|
add_module(xrpl nodestore)
|
||||||
|
target_link_libraries(xrpl.libxrpl.nodestore PUBLIC
|
||||||
|
xrpl.libxrpl.basics
|
||||||
|
xrpl.libxrpl.json
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
)
|
||||||
|
|
||||||
|
add_module(xrpl shamap)
|
||||||
|
target_link_libraries(xrpl.libxrpl.shamap PUBLIC
|
||||||
|
xrpl.libxrpl.basics
|
||||||
|
xrpl.libxrpl.crypto
|
||||||
|
xrpl.libxrpl.protocol
|
||||||
|
xrpl.libxrpl.nodestore
|
||||||
|
)
|
||||||
|
|
||||||
add_module(xrpl ledger)
|
add_module(xrpl ledger)
|
||||||
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
|
target_link_libraries(xrpl.libxrpl.ledger PUBLIC
|
||||||
xrpl.libxrpl.basics
|
xrpl.libxrpl.basics
|
||||||
@@ -136,6 +152,8 @@ target_link_modules(xrpl PUBLIC
|
|||||||
protocol
|
protocol
|
||||||
resource
|
resource
|
||||||
server
|
server
|
||||||
|
nodestore
|
||||||
|
shamap
|
||||||
net
|
net
|
||||||
ledger
|
ledger
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,20 +8,23 @@ install (
|
|||||||
TARGETS
|
TARGETS
|
||||||
common
|
common
|
||||||
opts
|
opts
|
||||||
ripple_syslibs
|
|
||||||
ripple_boost
|
ripple_boost
|
||||||
|
ripple_libs
|
||||||
|
ripple_syslibs
|
||||||
xrpl.imports.main
|
xrpl.imports.main
|
||||||
xrpl.libpb
|
xrpl.libpb
|
||||||
|
xrpl.libxrpl
|
||||||
xrpl.libxrpl.basics
|
xrpl.libxrpl.basics
|
||||||
xrpl.libxrpl.beast
|
xrpl.libxrpl.beast
|
||||||
xrpl.libxrpl.crypto
|
xrpl.libxrpl.crypto
|
||||||
xrpl.libxrpl.json
|
xrpl.libxrpl.json
|
||||||
|
xrpl.libxrpl.ledger
|
||||||
|
xrpl.libxrpl.net
|
||||||
|
xrpl.libxrpl.nodestore
|
||||||
xrpl.libxrpl.protocol
|
xrpl.libxrpl.protocol
|
||||||
xrpl.libxrpl.resource
|
xrpl.libxrpl.resource
|
||||||
xrpl.libxrpl.ledger
|
|
||||||
xrpl.libxrpl.server
|
xrpl.libxrpl.server
|
||||||
xrpl.libxrpl.net
|
xrpl.libxrpl.shamap
|
||||||
xrpl.libxrpl
|
|
||||||
antithesis-sdk-cpp
|
antithesis-sdk-cpp
|
||||||
EXPORT RippleExports
|
EXPORT RippleExports
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ public:
|
|||||||
explicit Number(rep mantissa, int exponent);
|
explicit Number(rep mantissa, int exponent);
|
||||||
explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
|
explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
|
||||||
|
|
||||||
static Number const zero;
|
|
||||||
|
|
||||||
constexpr rep
|
constexpr rep
|
||||||
mantissa() const noexcept;
|
mantissa() const noexcept;
|
||||||
constexpr int
|
constexpr int
|
||||||
|
|||||||
@@ -170,9 +170,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
retrieve(key_type const& key, T& data);
|
retrieve(key_type const& key, T& data);
|
||||||
|
|
||||||
mutex_type&
|
|
||||||
peekMutex();
|
|
||||||
|
|
||||||
std::vector<key_type>
|
std::vector<key_type>
|
||||||
getKeys() const;
|
getKeys() const;
|
||||||
|
|
||||||
|
|||||||
@@ -668,29 +668,6 @@ TaggedCache<
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
|
||||||
class Key,
|
|
||||||
class T,
|
|
||||||
bool IsKeyCache,
|
|
||||||
class SharedWeakUnionPointer,
|
|
||||||
class SharedPointerType,
|
|
||||||
class Hash,
|
|
||||||
class KeyEqual,
|
|
||||||
class Mutex>
|
|
||||||
inline auto
|
|
||||||
TaggedCache<
|
|
||||||
Key,
|
|
||||||
T,
|
|
||||||
IsKeyCache,
|
|
||||||
SharedWeakUnionPointer,
|
|
||||||
SharedPointerType,
|
|
||||||
Hash,
|
|
||||||
KeyEqual,
|
|
||||||
Mutex>::peekMutex() -> mutex_type&
|
|
||||||
{
|
|
||||||
return m_mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class Key,
|
class Key,
|
||||||
class T,
|
class T,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||||||
// The duplication is because Visual Studio 2019 cannot compile that header
|
// The duplication is because Visual Studio 2019 cannot compile that header
|
||||||
// even with the option -Zc:__cplusplus added.
|
// even with the option -Zc:__cplusplus added.
|
||||||
#define ALWAYS(cond, message, ...) assert((message) && (cond))
|
#define ALWAYS(cond, message, ...) assert((message) && (cond))
|
||||||
#define ALWAYS_OR_UNREACHABLE(cond, message) assert((message) && (cond))
|
#define ALWAYS_OR_UNREACHABLE(cond, message, ...) assert((message) && (cond))
|
||||||
#define SOMETIMES(cond, message, ...)
|
#define SOMETIMES(cond, message, ...)
|
||||||
#define REACHABLE(message, ...)
|
#define REACHABLE(message, ...)
|
||||||
#define UNREACHABLE(message, ...) assert((message) && false)
|
#define UNREACHABLE(message, ...) assert((message) && false)
|
||||||
|
|||||||
@@ -395,9 +395,6 @@ public:
|
|||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
bool
|
bool
|
||||||
isMember(std::string const& key) const;
|
isMember(std::string const& key) const;
|
||||||
/// Return true if the object has a member named key.
|
|
||||||
bool
|
|
||||||
isMember(StaticString const& key) const;
|
|
||||||
|
|
||||||
/// \brief Return a list of the member names.
|
/// \brief Return a list of the member names.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -387,45 +387,6 @@ public:
|
|||||||
emptyDirDelete(Keylet const& directory);
|
emptyDirDelete(Keylet const& directory);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace directory {
|
|
||||||
/** Helper functions for managing low-level directory operations.
|
|
||||||
These are not part of the ApplyView interface.
|
|
||||||
|
|
||||||
Don't use them unless you really, really know what you're doing.
|
|
||||||
Instead use dirAdd, dirInsert, etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::uint64_t
|
|
||||||
createRoot(
|
|
||||||
ApplyView& view,
|
|
||||||
Keylet const& directory,
|
|
||||||
uint256 const& key,
|
|
||||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
|
||||||
|
|
||||||
auto
|
|
||||||
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start);
|
|
||||||
|
|
||||||
std::uint64_t
|
|
||||||
insertKey(
|
|
||||||
ApplyView& view,
|
|
||||||
SLE::ref node,
|
|
||||||
std::uint64_t page,
|
|
||||||
bool preserveOrder,
|
|
||||||
STVector256& indexes,
|
|
||||||
uint256 const& key);
|
|
||||||
|
|
||||||
std::optional<std::uint64_t>
|
|
||||||
insertPage(
|
|
||||||
ApplyView& view,
|
|
||||||
std::uint64_t page,
|
|
||||||
SLE::pointer node,
|
|
||||||
std::uint64_t nextPage,
|
|
||||||
SLE::ref next,
|
|
||||||
uint256 const& key,
|
|
||||||
Keylet const& directory,
|
|
||||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
|
|
||||||
|
|
||||||
} // namespace directory
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
138
include/xrpl/ledger/LedgerIndexMap.h
Normal file
138
include/xrpl/ledger/LedgerIndexMap.h
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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_APP_LEDGER_INDEX_MAP_H_INCLUDED
|
||||||
|
#define RIPPLE_APP_LEDGER_INDEX_MAP_H_INCLUDED
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
|
||||||
|
template <class Key, class Mapped>
|
||||||
|
class LedgerIndexMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LedgerIndexMap() = default;
|
||||||
|
explicit LedgerIndexMap(std::size_t reserve_capacity)
|
||||||
|
{
|
||||||
|
data_.reserve(reserve_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
LedgerIndexMap(LedgerIndexMap const&) = delete;
|
||||||
|
LedgerIndexMap&
|
||||||
|
operator=(LedgerIndexMap const&) = delete;
|
||||||
|
LedgerIndexMap(LedgerIndexMap&&) = delete;
|
||||||
|
LedgerIndexMap&
|
||||||
|
operator=(LedgerIndexMap&&) = delete;
|
||||||
|
|
||||||
|
Mapped&
|
||||||
|
operator[](Key const& k)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
return data_[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
Mapped&
|
||||||
|
operator[](Key&& k)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
return data_[std::move(k)];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Mapped*
|
||||||
|
get(Key const& k)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
auto it = data_.find(k);
|
||||||
|
return it == data_.end() ? nullptr : &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Mapped const*
|
||||||
|
get(Key const& k) const
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
auto it = data_.find(k);
|
||||||
|
return it == data_.end() ? nullptr : &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
Mapped&
|
||||||
|
put(Key const& k, Args&&... args)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
auto [it, inserted] = data_.try_emplace(k, std::forward<Args>(args)...);
|
||||||
|
if (!inserted)
|
||||||
|
it->second = Mapped(std::forward<Args>(args)...);
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
contains(Key const& k) const
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
return data_.find(k) != data_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
size() const noexcept
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
return data_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
empty() const noexcept
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
return data_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reserve(std::size_t n)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
data_.reserve(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rehash(std::size_t n)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
data_.rehash(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
eraseBefore(Key const& cutoff)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
auto const before = data_.size();
|
||||||
|
std::erase_if(data_, [&](auto const& kv) { return kv.first < cutoff; });
|
||||||
|
return before - data_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<Key, Mapped> data_;
|
||||||
|
mutable std::mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ripple
|
||||||
|
|
||||||
|
#endif // RIPPLE_APP_LEDGER_INDEX_MAP_H_INCLUDED
|
||||||
@@ -242,80 +242,6 @@ isDeepFrozen(
|
|||||||
Currency const& currency,
|
Currency const& currency,
|
||||||
AccountID const& issuer);
|
AccountID const& issuer);
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue,
|
|
||||||
int = 0 /*ignored*/)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, issue.currency, issue.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
int depth = 0)
|
|
||||||
{
|
|
||||||
// Unlike IOUs, frozen / locked MPTs are not allowed to send or receive
|
|
||||||
// funds, so checking "deep frozen" is the same as checking "frozen".
|
|
||||||
return isFrozen(view, account, mptIssue, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* isFrozen check is recursive for MPT shares in a vault, descending to
|
|
||||||
* assets in the vault, up to maxAssetCheckDepth recursion depth. This is
|
|
||||||
* purely defensive, as we currently do not allow such vaults to be created.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] inline bool
|
|
||||||
isDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Asset const& asset,
|
|
||||||
int depth = 0)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) {
|
|
||||||
return isDeepFrozen(view, account, issue, depth);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, issue) ? (TER)tecFROZEN
|
|
||||||
: (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue)
|
|
||||||
{
|
|
||||||
return isDeepFrozen(view, account, mptIssue) ? (TER)tecLOCKED
|
|
||||||
: (TER)tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline TER
|
|
||||||
checkDeepFrozen(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Asset const& asset)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& issue) {
|
|
||||||
return checkDeepFrozen(view, account, issue);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
isLPTokenFrozen(
|
isLPTokenFrozen(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
@@ -361,49 +287,6 @@ accountHolds(
|
|||||||
AuthHandling zeroIfUnauthorized,
|
AuthHandling zeroIfUnauthorized,
|
||||||
beast::Journal j);
|
beast::Journal j);
|
||||||
|
|
||||||
// Returns the amount an account can spend total.
|
|
||||||
//
|
|
||||||
// These functions use accountHolds, but unlike accountHolds:
|
|
||||||
// * The account can go into debt.
|
|
||||||
// * If the account is the asset issuer the only limit is defined by the asset /
|
|
||||||
// issuance.
|
|
||||||
//
|
|
||||||
// <-- saAmount: amount of currency held by account. May be negative.
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Asset const& asset,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j);
|
|
||||||
|
|
||||||
// Returns the amount an account can spend of the currency type saDefault, or
|
// Returns the amount an account can spend of the currency type saDefault, or
|
||||||
// returns saDefault if this account is the issuer of the currency in
|
// returns saDefault if this account is the issuer of the currency in
|
||||||
// question. Should be used in favor of accountHolds when questioning how much
|
// question. Should be used in favor of accountHolds when questioning how much
|
||||||
@@ -650,11 +533,7 @@ dirNext(
|
|||||||
describeOwnerDir(AccountID const& account);
|
describeOwnerDir(AccountID const& account);
|
||||||
|
|
||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
dirLink(
|
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object);
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& owner,
|
|
||||||
std::shared_ptr<SLE>& object,
|
|
||||||
SF_UINT64 const& node = sfOwnerNode);
|
|
||||||
|
|
||||||
AccountID
|
AccountID
|
||||||
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
||||||
@@ -694,7 +573,7 @@ isPseudoAccount(std::shared_ptr<SLE const> sleAcct);
|
|||||||
getPseudoAccountFields();
|
getPseudoAccountFields();
|
||||||
|
|
||||||
[[nodiscard]] inline bool
|
[[nodiscard]] inline bool
|
||||||
isPseudoAccount(ReadView const& view, AccountID const& accountId)
|
isPseudoAccount(ReadView const& view, AccountID accountId)
|
||||||
{
|
{
|
||||||
return isPseudoAccount(view.read(keylet::account(accountId)));
|
return isPseudoAccount(view.read(keylet::account(accountId)));
|
||||||
}
|
}
|
||||||
@@ -702,68 +581,6 @@ isPseudoAccount(ReadView const& view, AccountID const& accountId)
|
|||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
canAddHolding(ReadView const& view, Asset const& asset);
|
canAddHolding(ReadView const& view, Asset const& asset);
|
||||||
|
|
||||||
/** Validates that the destination SLE and tag are valid
|
|
||||||
|
|
||||||
- Checks that the SLE is not null.
|
|
||||||
- If the SLE requires a destination tag, checks that there is a tag.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag);
|
|
||||||
|
|
||||||
/** Checks that can withdraw funds from an object to itself or a destination.
|
|
||||||
*
|
|
||||||
* The receiver may be either the submitting account (sfAccount) or a different
|
|
||||||
* destination account (sfDestination).
|
|
||||||
*
|
|
||||||
* - Checks that the receiver account exists.
|
|
||||||
* - If the receiver requires a destination tag, check that one exists, even
|
|
||||||
* if withdrawing to self.
|
|
||||||
* - If withdrawing to self, succeed.
|
|
||||||
* - If not, checks if the receiver requires deposit authorization, and if
|
|
||||||
* the sender has it.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(
|
|
||||||
AccountID const& from,
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& to,
|
|
||||||
SLE::const_ref toSle,
|
|
||||||
bool hasDestinationTag);
|
|
||||||
|
|
||||||
/** Checks that can withdraw funds from an object to itself or a destination.
|
|
||||||
*
|
|
||||||
* The receiver may be either the submitting account (sfAccount) or a different
|
|
||||||
* destination account (sfDestination).
|
|
||||||
*
|
|
||||||
* - Checks that the receiver account exists.
|
|
||||||
* - If the receiver requires a destination tag, check that one exists, even
|
|
||||||
* if withdrawing to self.
|
|
||||||
* - If withdrawing to self, succeed.
|
|
||||||
* - If not, checks if the receiver requires deposit authorization, and if
|
|
||||||
* the sender has it.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(
|
|
||||||
AccountID const& from,
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& to,
|
|
||||||
bool hasDestinationTag);
|
|
||||||
|
|
||||||
/** Checks that can withdraw funds from an object to itself or a destination.
|
|
||||||
*
|
|
||||||
* The receiver may be either the submitting account (sfAccount) or a different
|
|
||||||
* destination account (sfDestination).
|
|
||||||
*
|
|
||||||
* - Checks that the receiver account exists.
|
|
||||||
* - If the receiver requires a destination tag, check that one exists, even
|
|
||||||
* if withdrawing to self.
|
|
||||||
* - If withdrawing to self, succeed.
|
|
||||||
* - If not, checks if the receiver requires deposit authorization, and if
|
|
||||||
* the sender has it.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(ReadView const& view, STTx const& tx);
|
|
||||||
|
|
||||||
/// Any transactors that call addEmptyHolding() in doApply must call
|
/// Any transactors that call addEmptyHolding() in doApply must call
|
||||||
/// canAddHolding() in preflight with the same View and Asset
|
/// canAddHolding() in preflight with the same View and Asset
|
||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
@@ -933,22 +750,6 @@ accountSend(
|
|||||||
beast::Journal j,
|
beast::Journal j,
|
||||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
||||||
|
|
||||||
using MultiplePaymentDestinations = std::vector<std::pair<AccountID, Number>>;
|
|
||||||
/** Like accountSend, except one account is sending multiple payments (with the
|
|
||||||
* same asset!) simultaneously
|
|
||||||
*
|
|
||||||
* Calls static accountSendMultiIOU if saAmount represents Issue.
|
|
||||||
* Calls static accountSendMultiMPT if saAmount represents MPTIssue.
|
|
||||||
*/
|
|
||||||
[[nodiscard]] TER
|
|
||||||
accountSendMulti(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee = WaiveTransferFee::No);
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
issueIOU(
|
issueIOU(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_BACKEND_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_BACKEND_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_BACKEND_H_INCLUDED
|
#define RIPPLE_NODESTORE_BACKEND_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Types.h>
|
#include <xrpl/nodestore/Types.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -20,13 +20,12 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DATABASE_H_INCLUDED
|
#define RIPPLE_NODESTORE_DATABASE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Backend.h>
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
|
||||||
#include <xrpld/nodestore/Scheduler.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/BasicConfig.h>
|
#include <xrpl/basics/BasicConfig.h>
|
||||||
#include <xrpl/basics/Log.h>
|
#include <xrpl/basics/Log.h>
|
||||||
#include <xrpl/basics/TaggedCache.ipp>
|
#include <xrpl/basics/TaggedCache.ipp>
|
||||||
|
#include <xrpl/nodestore/Backend.h>
|
||||||
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
#include <xrpl/nodestore/Scheduler.h>
|
||||||
#include <xrpl/protocol/SystemParameters.h>
|
#include <xrpl/protocol/SystemParameters.h>
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
|
#define RIPPLE_NODESTORE_DATABASEROTATING_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Database.h>
|
#include <xrpl/nodestore/Database.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
|
#define RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Scheduler.h>
|
#include <xrpl/nodestore/Scheduler.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -20,11 +20,10 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_FACTORY_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_FACTORY_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_FACTORY_H_INCLUDED
|
#define RIPPLE_NODESTORE_FACTORY_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Backend.h>
|
|
||||||
#include <xrpld/nodestore/Scheduler.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/BasicConfig.h>
|
#include <xrpl/basics/BasicConfig.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/nodestore/Backend.h>
|
||||||
|
#include <xrpl/nodestore/Scheduler.h>
|
||||||
|
|
||||||
#include <nudb/store.hpp>
|
#include <nudb/store.hpp>
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_MANAGER_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_MANAGER_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_MANAGER_H_INCLUDED
|
#define RIPPLE_NODESTORE_MANAGER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/DatabaseRotating.h>
|
#include <xrpl/nodestore/DatabaseRotating.h>
|
||||||
#include <xrpld/nodestore/Factory.h>
|
#include <xrpl/nodestore/Factory.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
|
#define RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Task.h>
|
#include <xrpl/nodestore/Task.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_TYPES_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_TYPES_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_TYPES_H_INCLUDED
|
#define RIPPLE_NODESTORE_TYPES_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
|
#define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Scheduler.h>
|
#include <xrpl/nodestore/Scheduler.h>
|
||||||
#include <xrpld/nodestore/Task.h>
|
#include <xrpl/nodestore/Task.h>
|
||||||
#include <xrpld/nodestore/Types.h>
|
#include <xrpl/nodestore/Types.h>
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -20,10 +20,9 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
|
#define RIPPLE_NODESTORE_DATABASENODEIMP_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Database.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/TaggedCache.h>
|
#include <xrpl/basics/TaggedCache.h>
|
||||||
#include <xrpl/basics/chrono.h>
|
#include <xrpl/basics/chrono.h>
|
||||||
|
#include <xrpl/nodestore/Database.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
|
#define RIPPLE_NODESTORE_DATABASEROTATINGIMP_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/DatabaseRotating.h>
|
#include <xrpl/nodestore/DatabaseRotating.h>
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
|
#define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -20,9 +20,8 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
|
#define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
|
||||||
|
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
|
||||||
#include <boost/align/align_up.hpp>
|
#include <boost/align/align_up.hpp>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
|
#ifndef RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
|
||||||
#define RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
|
#define RIPPLE_NODESTORE_MANAGERIMP_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Manager.h>
|
#include <xrpl/nodestore/Manager.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
static void
|
static void
|
||||||
missing_backend();
|
missing_backend();
|
||||||
|
|
||||||
ManagerImp() = default;
|
ManagerImp();
|
||||||
|
|
||||||
~ManagerImp() = default;
|
~ManagerImp() = default;
|
||||||
|
|
||||||
@@ -23,11 +23,10 @@
|
|||||||
// Disable lz4 deprecation warning due to incompatibility with clang attributes
|
// Disable lz4 deprecation warning due to incompatibility with clang attributes
|
||||||
#define LZ4_DISABLE_DEPRECATE_WARNINGS
|
#define LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
|
||||||
#include <xrpld/nodestore/detail/varint.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/basics/safe_cast.h>
|
#include <xrpl/basics/safe_cast.h>
|
||||||
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
#include <xrpl/nodestore/detail/varint.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
|
|
||||||
#include <nudb/detail/field.hpp>
|
#include <nudb/detail/field.hpp>
|
||||||
@@ -103,12 +103,6 @@ public:
|
|||||||
return holds<Issue>() && get<Issue>().native();
|
return holds<Issue>() && get<Issue>().native();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const
|
|
||||||
{
|
|
||||||
return !holds<Issue>() || get<Issue>().native();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
operator==(Asset const& lhs, Asset const& rhs);
|
operator==(Asset const& lhs, Asset const& rhs);
|
||||||
|
|
||||||
|
|||||||
@@ -346,24 +346,6 @@ vault(uint256 const& vaultKey)
|
|||||||
return {ltVAULT, vaultKey};
|
return {ltVAULT, vaultKey};
|
||||||
}
|
}
|
||||||
|
|
||||||
Keylet
|
|
||||||
loanbroker(AccountID const& owner, std::uint32_t seq) noexcept;
|
|
||||||
|
|
||||||
inline Keylet
|
|
||||||
loanbroker(uint256 const& key)
|
|
||||||
{
|
|
||||||
return {ltLOAN_BROKER, key};
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
|
||||||
loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept;
|
|
||||||
|
|
||||||
inline Keylet
|
|
||||||
loan(uint256 const& key)
|
|
||||||
{
|
|
||||||
return {ltLOAN, key};
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
Keylet
|
||||||
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
|
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -205,11 +205,6 @@ enum LedgerSpecificFlags {
|
|||||||
|
|
||||||
// ltVAULT
|
// ltVAULT
|
||||||
lsfVaultPrivate = 0x00010000,
|
lsfVaultPrivate = 0x00010000,
|
||||||
|
|
||||||
// ltLOAN
|
|
||||||
lsfLoanDefault = 0x00010000,
|
|
||||||
lsfLoanImpaired = 0x00020000,
|
|
||||||
lsfLoanOverpayment = 0x00040000, // True, loan allows overpayments
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <xrpl/basics/ByteUtilities.h>
|
#include <xrpl/basics/ByteUtilities.h>
|
||||||
#include <xrpl/basics/base_uint.h>
|
#include <xrpl/basics/base_uint.h>
|
||||||
#include <xrpl/protocol/Units.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -56,7 +55,10 @@ std::size_t constexpr oversizeMetaDataCap = 5200;
|
|||||||
/** The maximum number of entries per directory page */
|
/** The maximum number of entries per directory page */
|
||||||
std::size_t constexpr dirNodeMaxEntries = 32;
|
std::size_t constexpr dirNodeMaxEntries = 32;
|
||||||
|
|
||||||
/** The maximum number of pages allowed in a directory */
|
/** The maximum number of pages allowed in a directory
|
||||||
|
|
||||||
|
Made obsolete by fixDirectoryLimit amendment.
|
||||||
|
*/
|
||||||
std::uint64_t constexpr dirNodeMaxPages = 262144;
|
std::uint64_t constexpr dirNodeMaxPages = 262144;
|
||||||
|
|
||||||
/** The maximum number of items in an NFT page */
|
/** The maximum number of items in an NFT page */
|
||||||
@@ -82,136 +84,6 @@ std::size_t constexpr maxDeletableTokenOfferEntries = 500;
|
|||||||
*/
|
*/
|
||||||
std::uint16_t constexpr maxTransferFee = 50000;
|
std::uint16_t constexpr maxTransferFee = 50000;
|
||||||
|
|
||||||
/** There are 10,000 basis points (bips) in 100%.
|
|
||||||
*
|
|
||||||
* Basis points represent 0.01%.
|
|
||||||
*
|
|
||||||
* Given a value X, to find the amount for B bps,
|
|
||||||
* use X * B / bipsPerUnity
|
|
||||||
*
|
|
||||||
* Example: If a loan broker has 999 XRP of debt, and must maintain 1,000 bps of
|
|
||||||
* that debt as cover (10%), then the minimum cover amount is 999,000,000 drops
|
|
||||||
* * 1000 / bipsPerUnity = 99,900,00 drops or 99.9 XRP.
|
|
||||||
*
|
|
||||||
* Given a percentage P, to find the number of bps that percentage represents,
|
|
||||||
* use P * bipsPerUnity.
|
|
||||||
*
|
|
||||||
* Example: 50% is 0.50 * bipsPerUnity = 5,000 bps.
|
|
||||||
*/
|
|
||||||
Bips32 constexpr bipsPerUnity(100 * 100);
|
|
||||||
TenthBips32 constexpr tenthBipsPerUnity(bipsPerUnity.value() * 10);
|
|
||||||
|
|
||||||
constexpr Bips32
|
|
||||||
percentageToBips(std::uint32_t percentage)
|
|
||||||
{
|
|
||||||
return Bips32(percentage * bipsPerUnity.value() / 100);
|
|
||||||
}
|
|
||||||
constexpr TenthBips32
|
|
||||||
percentageToTenthBips(std::uint32_t percentage)
|
|
||||||
{
|
|
||||||
return TenthBips32(percentage * tenthBipsPerUnity.value() / 100);
|
|
||||||
}
|
|
||||||
template <typename T, class TBips>
|
|
||||||
constexpr T
|
|
||||||
bipsOfValue(T value, Bips<TBips> bips)
|
|
||||||
{
|
|
||||||
return value * bips.value() / bipsPerUnity.value();
|
|
||||||
}
|
|
||||||
template <typename T, class TBips>
|
|
||||||
constexpr T
|
|
||||||
tenthBipsOfValue(T value, TenthBips<TBips> bips)
|
|
||||||
{
|
|
||||||
return value * bips.value() / tenthBipsPerUnity.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The maximum management fee rate allowed by a loan broker in 1/10 bips.
|
|
||||||
|
|
||||||
Valid values are between 0 and 10% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips16 constexpr maxManagementFeeRate(
|
|
||||||
unsafe_cast<std::uint16_t>(percentageToTenthBips(10).value()));
|
|
||||||
static_assert(maxManagementFeeRate == TenthBips16(std::uint16_t(10'000u)));
|
|
||||||
|
|
||||||
/** The maximum coverage rate required of a loan broker in 1/10 bips.
|
|
||||||
|
|
||||||
Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxCoverRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxCoverRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum overpayment fee on a loan in 1/10 bips.
|
|
||||||
*
|
|
||||||
Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxOverpaymentFee = percentageToTenthBips(100);
|
|
||||||
static_assert(maxOverpaymentFee == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** Annualized interest rate of the Loan in 1/10 bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum premium added to the interest rate for late payments on a loan
|
|
||||||
* in 1/10 bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxLateInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxLateInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum close interest rate charged for repaying a loan early in 1/10
|
|
||||||
* bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxCloseInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxCloseInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** The maximum overpayment interest rate charged on loan overpayments in 1/10
|
|
||||||
* bips.
|
|
||||||
*
|
|
||||||
* Valid values are between 0 and 100% inclusive.
|
|
||||||
*/
|
|
||||||
TenthBips32 constexpr maxOverpaymentInterestRate = percentageToTenthBips(100);
|
|
||||||
static_assert(maxOverpaymentInterestRate == TenthBips32(100'000u));
|
|
||||||
|
|
||||||
/** LoanPay transaction cost will be one base fee per X combined payments
|
|
||||||
*
|
|
||||||
* The number of payments is estimated based on the Amount paid and the Loan's
|
|
||||||
* Fixed Payment size. Overpayments (indicated with the tfLoanOverpayment flag)
|
|
||||||
* count as one more payment.
|
|
||||||
*
|
|
||||||
* This number was chosen arbitrarily, but should not be changed once released
|
|
||||||
* without an amendment
|
|
||||||
*/
|
|
||||||
static constexpr int loanPaymentsPerFeeIncrement = 5;
|
|
||||||
|
|
||||||
/** Maximum number of combined payments that a LoanPay transaction will process
|
|
||||||
*
|
|
||||||
* This limit is enforced during the loan payment process, and thus is not
|
|
||||||
* estimated. If the limit is hit, no further payments or overpayments will be
|
|
||||||
* processed, no matter how much of the transation Amount is left, but the
|
|
||||||
* transaction will succeed with the payments that have been processed up to
|
|
||||||
* that point.
|
|
||||||
*
|
|
||||||
* This limit is independent of loanPaymentsPerFeeIncrement, so a transaction
|
|
||||||
* could potentially be charged for many more payments than actually get
|
|
||||||
* processed. Users should take care not to submit a transaction paying more
|
|
||||||
* than loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment. Because
|
|
||||||
* overpayments are charged as a payment, if submitting
|
|
||||||
* loanMaximumPaymentsPerTransaction * Loan.PeriodicPayment, users should not
|
|
||||||
* set the tfLoanOverpayment flag.
|
|
||||||
*
|
|
||||||
* Even though they're independent, loanMaximumPaymentsPerTransaction should be
|
|
||||||
* a multiple of loanPaymentsPerFeeIncrement.
|
|
||||||
*
|
|
||||||
* This number was chosen arbitrarily, but should not be changed once released
|
|
||||||
* without an amendment
|
|
||||||
*/
|
|
||||||
static constexpr int loanMaximumPaymentsPerTransaction = 100;
|
|
||||||
|
|
||||||
/** The maximum length of a URI inside an NFT */
|
/** The maximum length of a URI inside an NFT */
|
||||||
std::size_t constexpr maxTokenURILength = 256;
|
std::size_t constexpr maxTokenURILength = 256;
|
||||||
|
|
||||||
|
|||||||
@@ -139,8 +139,8 @@ field_code(int id, int index)
|
|||||||
SFields are created at compile time.
|
SFields are created at compile time.
|
||||||
|
|
||||||
Each SField, once constructed, lives until program termination, and there
|
Each SField, once constructed, lives until program termination, and there
|
||||||
is only one instance per fieldType/fieldValue pair which serves the
|
is only one instance per fieldType/fieldValue pair which serves the entire
|
||||||
entire application.
|
application.
|
||||||
*/
|
*/
|
||||||
class SField
|
class SField
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,15 +66,15 @@ public:
|
|||||||
static int const cMaxOffset = 80;
|
static int const cMaxOffset = 80;
|
||||||
|
|
||||||
// Maximum native value supported by the code
|
// Maximum native value supported by the code
|
||||||
static std::uint64_t const cMinValue = 1'000'000'000'000'000ull;
|
static std::uint64_t const cMinValue = 1000000000000000ull;
|
||||||
static std::uint64_t const cMaxValue = 9'999'999'999'999'999ull;
|
static std::uint64_t const cMaxValue = 9999999999999999ull;
|
||||||
static std::uint64_t const cMaxNative = 9'000'000'000'000'000'000ull;
|
static std::uint64_t const cMaxNative = 9000000000000000000ull;
|
||||||
|
|
||||||
// Max native value on network.
|
// Max native value on network.
|
||||||
static std::uint64_t const cMaxNativeN = 100'000'000'000'000'000ull;
|
static std::uint64_t const cMaxNativeN = 100000000000000000ull;
|
||||||
static std::uint64_t const cIssuedCurrency = 0x8'000'000'000'000'000ull;
|
static std::uint64_t const cIssuedCurrency = 0x8000000000000000ull;
|
||||||
static std::uint64_t const cPositive = 0x4'000'000'000'000'000ull;
|
static std::uint64_t const cPositive = 0x4000000000000000ull;
|
||||||
static std::uint64_t const cMPToken = 0x2'000'000'000'000'000ull;
|
static std::uint64_t const cMPToken = 0x2000000000000000ull;
|
||||||
static std::uint64_t const cValueMask = ~(cPositive | cMPToken);
|
static std::uint64_t const cValueMask = ~(cPositive | cMPToken);
|
||||||
|
|
||||||
static std::uint64_t const uRateOne;
|
static std::uint64_t const uRateOne;
|
||||||
@@ -174,9 +174,6 @@ public:
|
|||||||
int
|
int
|
||||||
exponent() const noexcept;
|
exponent() const noexcept;
|
||||||
|
|
||||||
bool
|
|
||||||
integral() const noexcept;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
native() const noexcept;
|
native() const noexcept;
|
||||||
|
|
||||||
@@ -457,12 +454,6 @@ STAmount::exponent() const noexcept
|
|||||||
return mOffset;
|
return mOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
STAmount::integral() const noexcept
|
|
||||||
{
|
|
||||||
return mAsset.integral();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
STAmount::native() const noexcept
|
STAmount::native() const noexcept
|
||||||
{
|
{
|
||||||
@@ -704,53 +695,6 @@ divRoundStrict(
|
|||||||
std::uint64_t
|
std::uint64_t
|
||||||
getRate(STAmount const& offerOut, STAmount const& offerIn);
|
getRate(STAmount const& offerOut, STAmount const& offerIn);
|
||||||
|
|
||||||
/** Round an arbitrary precision Amount to the precision of an STAmount that has
|
|
||||||
* a given exponent.
|
|
||||||
*
|
|
||||||
* This is used to ensure that calculations involving IOU amounts do not collect
|
|
||||||
* dust beyond the precision of the reference value.
|
|
||||||
*
|
|
||||||
* @param value The value to be rounded
|
|
||||||
* @param scale An exponent value to establish the precision limit of
|
|
||||||
* `value`. Should be larger than `value.exponent()`.
|
|
||||||
* @param rounding Optional Number rounding mode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
STAmount
|
|
||||||
roundToScale(
|
|
||||||
STAmount value,
|
|
||||||
std::int32_t scale,
|
|
||||||
Number::rounding_mode rounding = Number::getround());
|
|
||||||
|
|
||||||
/** Round an arbitrary precision Number to the precision of a given Asset.
|
|
||||||
*
|
|
||||||
* This is used to ensure that calculations do not collect dust beyond the
|
|
||||||
* precision of the reference value for IOUs, or fractional amounts for the
|
|
||||||
* integral types XRP and MPT.
|
|
||||||
*
|
|
||||||
* @param asset The relevant asset
|
|
||||||
* @param value The value to be rounded
|
|
||||||
* @param scale Only relevant to IOU assets. An exponent value to establish the
|
|
||||||
* precision limit of `value`. Should be larger than `value.exponent()`.
|
|
||||||
* @param rounding Optional Number rounding mode
|
|
||||||
*/
|
|
||||||
template <AssetType A>
|
|
||||||
Number
|
|
||||||
roundToAsset(
|
|
||||||
A const& asset,
|
|
||||||
Number const& value,
|
|
||||||
std::int32_t scale,
|
|
||||||
Number::rounding_mode rounding = Number::getround())
|
|
||||||
{
|
|
||||||
NumberRoundModeGuard mg(rounding);
|
|
||||||
STAmount const ret{asset, value};
|
|
||||||
if (ret.integral())
|
|
||||||
return ret;
|
|
||||||
// Not that the ctor will round integral types (XRP, MPT) via canonicalize,
|
|
||||||
// so no extra work is needed for those.
|
|
||||||
return roundToScale(ret, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
|||||||
@@ -524,26 +524,7 @@ protected:
|
|||||||
// Constraint += and -= ValueProxy operators
|
// Constraint += and -= ValueProxy operators
|
||||||
// to value types that support arithmetic operations
|
// to value types that support arithmetic operations
|
||||||
template <typename U>
|
template <typename U>
|
||||||
concept IsArithmeticNumber = std::is_arithmetic_v<U> ||
|
concept IsArithmetic = std::is_arithmetic_v<U> || std::is_same_v<U, STAmount>;
|
||||||
std::is_same_v<U, Number> || std::is_same_v<U, STAmount>;
|
|
||||||
template <
|
|
||||||
typename U,
|
|
||||||
typename Value = typename U::value_type,
|
|
||||||
typename Unit = typename U::unit_type>
|
|
||||||
concept IsArithmeticValueUnit =
|
|
||||||
std::is_same_v<U, unit::ValueUnit<Unit, Value>> &&
|
|
||||||
IsArithmeticNumber<Value> && std::is_class_v<Unit>;
|
|
||||||
template <typename U, typename Value = typename U::value_type>
|
|
||||||
concept IsArithmeticST = !IsArithmeticValueUnit<U> && IsArithmeticNumber<Value>;
|
|
||||||
template <typename U>
|
|
||||||
concept IsArithmetic =
|
|
||||||
IsArithmeticNumber<U> || IsArithmeticST<U> || IsArithmeticValueUnit<U>;
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
concept Addable = requires(T t, U u) { t = t + u; };
|
|
||||||
template <typename T, typename U>
|
|
||||||
concept IsArithmeticCompatible =
|
|
||||||
IsArithmetic<typename T::value_type> && Addable<typename T::value_type, U>;
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class STObject::ValueProxy : public Proxy<T>
|
class STObject::ValueProxy : public Proxy<T>
|
||||||
@@ -563,12 +544,10 @@ public:
|
|||||||
// Convenience operators for value types supporting
|
// Convenience operators for value types supporting
|
||||||
// arithmetic operations
|
// arithmetic operations
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
ValueProxy&
|
ValueProxy&
|
||||||
operator+=(U const& u);
|
operator+=(U const& u);
|
||||||
|
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
ValueProxy&
|
ValueProxy&
|
||||||
operator-=(U const& u);
|
operator-=(U const& u);
|
||||||
|
|
||||||
@@ -804,7 +783,6 @@ STObject::ValueProxy<T>::operator=(U&& u)
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
STObject::ValueProxy<T>&
|
STObject::ValueProxy<T>&
|
||||||
STObject::ValueProxy<T>::operator+=(U const& u)
|
STObject::ValueProxy<T>::operator+=(U const& u)
|
||||||
{
|
{
|
||||||
@@ -814,7 +792,6 @@ STObject::ValueProxy<T>::operator+=(U const& u)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
template <IsArithmetic U>
|
template <IsArithmetic U>
|
||||||
requires IsArithmeticCompatible<T, U>
|
|
||||||
STObject::ValueProxy<T>&
|
STObject::ValueProxy<T>&
|
||||||
STObject::ValueProxy<T>::operator-=(U const& u)
|
STObject::ValueProxy<T>::operator-=(U const& u)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,14 +73,8 @@ static constexpr std::uint32_t XRP_LEDGER_EARLIEST_SEQ{32570u};
|
|||||||
* used in asserts and tests. */
|
* used in asserts and tests. */
|
||||||
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u};
|
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES{562177u};
|
||||||
|
|
||||||
/** The minimum amount of support an amendment should have.
|
/** The minimum amount of support an amendment should have. */
|
||||||
|
constexpr std::ratio<80, 100> amendmentMajorityCalcThreshold;
|
||||||
@note This value is used by legacy code and will become obsolete
|
|
||||||
once the fixAmendmentMajorityCalc amendment activates.
|
|
||||||
*/
|
|
||||||
constexpr std::ratio<204, 256> preFixAmendmentMajorityCalcThreshold;
|
|
||||||
|
|
||||||
constexpr std::ratio<80, 100> postFixAmendmentMajorityCalcThreshold;
|
|
||||||
|
|
||||||
/** The minimum amount of time an amendment must hold a majority */
|
/** The minimum amount of time an amendment must hold a majority */
|
||||||
constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2};
|
constexpr std::chrono::seconds const defaultAmendmentMajorityTime = weeks{2};
|
||||||
|
|||||||
@@ -225,8 +225,9 @@ enum TERcodes : TERUnderlyingType {
|
|||||||
terQUEUED, // Transaction is being held in TxQ until fee drops
|
terQUEUED, // Transaction is being held in TxQ until fee drops
|
||||||
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
|
terPRE_TICKET, // Ticket is not yet in ledger but might be on its way
|
||||||
terNO_AMM, // AMM doesn't exist for the asset pair
|
terNO_AMM, // AMM doesn't exist for the asset pair
|
||||||
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
|
terADDRESS_COLLISION, // Failed to allocate AccountID when trying to
|
||||||
// create a pseudo-account
|
// create a pseudo-account
|
||||||
|
terNO_DELEGATE_PERMISSION, // Delegate does not have permission
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -361,6 +362,9 @@ enum TECcodes : TERUnderlyingType {
|
|||||||
tecLIMIT_EXCEEDED = 195,
|
tecLIMIT_EXCEEDED = 195,
|
||||||
tecPSEUDO_ACCOUNT = 196,
|
tecPSEUDO_ACCOUNT = 196,
|
||||||
tecPRECISION_LOSS = 197,
|
tecPRECISION_LOSS = 197,
|
||||||
|
// DEPRECATED: This error code tecNO_DELEGATE_PERMISSION is reserved for
|
||||||
|
// backward compatibility with historical data on non-prod networks, can be
|
||||||
|
// reclaimed after those networks reset.
|
||||||
tecNO_DELEGATE_PERMISSION = 198,
|
tecNO_DELEGATE_PERMISSION = 198,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -285,25 +285,6 @@ constexpr std::uint32_t tfIndependent = 0x00080000;
|
|||||||
constexpr std::uint32_t const tfBatchMask =
|
constexpr std::uint32_t const tfBatchMask =
|
||||||
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
~(tfUniversal | tfAllOrNothing | tfOnlyOne | tfUntilFailure | tfIndependent) | tfInnerBatchTxn;
|
||||||
|
|
||||||
// LoanSet and LoanPay flags:
|
|
||||||
// LoanSet: True, indicates the loan supports overpayments
|
|
||||||
// LoanPay: True, indicates any excess in this payment can be used
|
|
||||||
// as an overpayment. False, no overpayments will be taken.
|
|
||||||
constexpr std::uint32_t const tfLoanOverpayment = 0x00010000;
|
|
||||||
// LoanPay exclusive flags:
|
|
||||||
// tfLoanFullPayment: True, indicates that the payment is
|
|
||||||
constexpr std::uint32_t const tfLoanFullPayment = 0x00020000;
|
|
||||||
constexpr std::uint32_t const tfLoanSetMask = ~(tfUniversal |
|
|
||||||
tfLoanOverpayment);
|
|
||||||
constexpr std::uint32_t const tfLoanPayMask = ~(tfUniversal |
|
|
||||||
tfLoanOverpayment | tfLoanFullPayment);
|
|
||||||
|
|
||||||
// LoanManage flags:
|
|
||||||
constexpr std::uint32_t const tfLoanDefault = 0x00010000;
|
|
||||||
constexpr std::uint32_t const tfLoanImpair = 0x00020000;
|
|
||||||
constexpr std::uint32_t const tfLoanUnimpair = 0x00040000;
|
|
||||||
constexpr std::uint32_t const tfLoanManageMask = ~(tfUniversal | tfLoanDefault | tfLoanImpair | tfLoanUnimpair);
|
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -33,51 +33,35 @@ namespace ripple {
|
|||||||
|
|
||||||
class TxMeta
|
class TxMeta
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
struct CtorHelper
|
|
||||||
{
|
|
||||||
explicit CtorHelper() = default;
|
|
||||||
};
|
|
||||||
template <class T>
|
|
||||||
TxMeta(
|
|
||||||
uint256 const& txID,
|
|
||||||
std::uint32_t ledger,
|
|
||||||
T const& data,
|
|
||||||
CtorHelper);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TxMeta(
|
TxMeta(uint256 const& transactionID, std::uint32_t ledger);
|
||||||
uint256 const& transactionID,
|
|
||||||
std::uint32_t ledger,
|
|
||||||
std::optional<uint256> parentBatchId = std::nullopt);
|
|
||||||
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
|
TxMeta(uint256 const& txID, std::uint32_t ledger, Blob const&);
|
||||||
TxMeta(uint256 const& txID, std::uint32_t ledger, std::string const&);
|
|
||||||
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
|
TxMeta(uint256 const& txID, std::uint32_t ledger, STObject const&);
|
||||||
|
|
||||||
uint256 const&
|
uint256 const&
|
||||||
getTxID() const
|
getTxID() const
|
||||||
{
|
{
|
||||||
return mTransactionID;
|
return transactionID_;
|
||||||
}
|
}
|
||||||
std::uint32_t
|
std::uint32_t
|
||||||
getLgrSeq() const
|
getLgrSeq() const
|
||||||
{
|
{
|
||||||
return mLedger;
|
return ledgerSeq_;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
getResult() const
|
getResult() const
|
||||||
{
|
{
|
||||||
return mResult;
|
return result_;
|
||||||
}
|
}
|
||||||
TER
|
TER
|
||||||
getResultTER() const
|
getResultTER() const
|
||||||
{
|
{
|
||||||
return TER::fromInt(mResult);
|
return TER::fromInt(result_);
|
||||||
}
|
}
|
||||||
std::uint32_t
|
std::uint32_t
|
||||||
getIndex() const
|
getIndex() const
|
||||||
{
|
{
|
||||||
return mIndex;
|
return index_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -104,66 +88,52 @@ public:
|
|||||||
STArray&
|
STArray&
|
||||||
getNodes()
|
getNodes()
|
||||||
{
|
{
|
||||||
return (mNodes);
|
return nodes_;
|
||||||
}
|
}
|
||||||
STArray const&
|
STArray const&
|
||||||
getNodes() const
|
getNodes() const
|
||||||
{
|
{
|
||||||
return (mNodes);
|
return nodes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setDeliveredAmount(STAmount const& delivered)
|
setAdditionalFields(STObject const& obj)
|
||||||
{
|
{
|
||||||
mDelivered = delivered;
|
if (obj.isFieldPresent(sfDeliveredAmount))
|
||||||
|
deliveredAmount_ = obj.getFieldAmount(sfDeliveredAmount);
|
||||||
|
|
||||||
|
if (obj.isFieldPresent(sfParentBatchID))
|
||||||
|
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
std::optional<STAmount> const&
|
||||||
getDeliveredAmount() const
|
getDeliveredAmount() const
|
||||||
{
|
{
|
||||||
XRPL_ASSERT(
|
return deliveredAmount_;
|
||||||
hasDeliveredAmount(),
|
|
||||||
"ripple::TxMeta::getDeliveredAmount : non-null delivered amount");
|
|
||||||
return *mDelivered;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
hasDeliveredAmount() const
|
|
||||||
{
|
|
||||||
return static_cast<bool>(mDelivered);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
setParentBatchId(uint256 const& parentBatchId)
|
setDeliveredAmount(std::optional<STAmount> const& amount)
|
||||||
{
|
{
|
||||||
mParentBatchId = parentBatchId;
|
deliveredAmount_ = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256
|
void
|
||||||
getParentBatchId() const
|
setParentBatchID(std::optional<uint256> const& id)
|
||||||
{
|
{
|
||||||
XRPL_ASSERT(
|
parentBatchID_ = id;
|
||||||
hasParentBatchId(),
|
|
||||||
"ripple::TxMeta::getParentBatchId : non-null batch id");
|
|
||||||
return *mParentBatchId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
hasParentBatchId() const
|
|
||||||
{
|
|
||||||
return static_cast<bool>(mParentBatchId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mTransactionID;
|
uint256 transactionID_;
|
||||||
std::uint32_t mLedger;
|
std::uint32_t ledgerSeq_;
|
||||||
std::uint32_t mIndex;
|
std::uint32_t index_;
|
||||||
int mResult;
|
int result_;
|
||||||
|
|
||||||
std::optional<STAmount> mDelivered;
|
std::optional<STAmount> deliveredAmount_;
|
||||||
std::optional<uint256> mParentBatchId;
|
std::optional<uint256> parentBatchID_;
|
||||||
|
|
||||||
STArray mNodes;
|
STArray nodes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|||||||
@@ -27,16 +27,14 @@
|
|||||||
#error "undefined macro: XRPL_RETIRE"
|
#error "undefined macro: XRPL_RETIRE"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
// Add new amendments to the top of this list.
|
// Add new amendments to the top of this list.
|
||||||
// Keep it sorted in reverse chronological order.
|
// Keep it sorted in reverse chronological order.
|
||||||
|
|
||||||
XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
|
||||||
|
XRPL_FIX (DirectoryLimit, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (IncludeKeyletFields, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(DynamicMPT, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (TokenEscrowV1, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (DelegateV1_1, Supported::no, VoteBehavior::DefaultNo)
|
|
||||||
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (PriceOracleOrder, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (MPTDeliveredAmount, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (AMMClawbackRounding, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
@@ -46,7 +44,6 @@ XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo
|
|||||||
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(SingleAssetVault, Supported::no, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(PermissionDelegation, Supported::no, VoteBehavior::DefaultNo)
|
|
||||||
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
// Check flags in Credential transactions
|
// Check flags in Credential transactions
|
||||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
@@ -80,7 +77,6 @@ XRPL_FIX (DisallowIncomingV1, Supported::yes, VoteBehavior::DefaultNo
|
|||||||
XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(XChainBridge, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (ReducedOffersV1, Supported::yes, VoteBehavior::DefaultNo)
|
|
||||||
XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (NFTokenRemint, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (NonFungibleTokensV1_2, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo)
|
XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo)
|
||||||
@@ -95,17 +91,12 @@ XRPL_FEATURE(CheckCashMakesTrustLine, Supported::yes, VoteBehavior::DefaultNo
|
|||||||
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(TicketBatch, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FIX (AmendmentMajorityCalc, Supported::yes, VoteBehavior::DefaultYes)
|
|
||||||
XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(HardenedValidations, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FIX (QualityUpperBound, Supported::yes, VoteBehavior::DefaultYes)
|
|
||||||
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FIX (PayChanRecipientOwnerDir, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FIX (MasterKeyAsRegularKey, Supported::yes, VoteBehavior::DefaultYes)
|
|
||||||
XRPL_FIX (TakerDryOfferRemoval, Supported::yes, VoteBehavior::DefaultYes)
|
|
||||||
XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(MultiSignReserve, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(DepositPreauth, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FIX (1623, Supported::yes, VoteBehavior::DefaultYes)
|
|
||||||
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(DepositAuth, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
|
XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes)
|
||||||
@@ -128,8 +119,10 @@ XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete)
|
|||||||
|
|
||||||
// The following amendments have been active for at least two years. Their
|
// The following amendments have been active for at least two years. Their
|
||||||
// pre-amendment code has been removed and the identifiers are deprecated.
|
// pre-amendment code has been removed and the identifiers are deprecated.
|
||||||
// All known amendments and amendments that may appear in a validated
|
// All known amendments and amendments that may appear in a validated ledger
|
||||||
// ledger must be registered either here or above with the "active" amendments
|
// must be registered either here or above with the "active" amendments
|
||||||
|
//
|
||||||
|
// Please keep this list sorted alphabetically for convenience.
|
||||||
XRPL_RETIRE(fix1201)
|
XRPL_RETIRE(fix1201)
|
||||||
XRPL_RETIRE(fix1368)
|
XRPL_RETIRE(fix1368)
|
||||||
XRPL_RETIRE(fix1373)
|
XRPL_RETIRE(fix1373)
|
||||||
@@ -141,10 +134,16 @@ XRPL_RETIRE(fix1528)
|
|||||||
XRPL_RETIRE(fix1543)
|
XRPL_RETIRE(fix1543)
|
||||||
XRPL_RETIRE(fix1571)
|
XRPL_RETIRE(fix1571)
|
||||||
XRPL_RETIRE(fix1578)
|
XRPL_RETIRE(fix1578)
|
||||||
|
XRPL_RETIRE(fix1623)
|
||||||
XRPL_RETIRE(fix1781)
|
XRPL_RETIRE(fix1781)
|
||||||
|
XRPL_RETIRE(fixAmendmentMajorityCalc)
|
||||||
XRPL_RETIRE(fixCheckThreading)
|
XRPL_RETIRE(fixCheckThreading)
|
||||||
|
XRPL_RETIRE(fixMasterKeyAsRegularKey)
|
||||||
|
XRPL_RETIRE(fixQualityUpperBound)
|
||||||
|
XRPL_RETIRE(fixReducedOffersV1)
|
||||||
XRPL_RETIRE(fixRmSmallIncreasedQOffers)
|
XRPL_RETIRE(fixRmSmallIncreasedQOffers)
|
||||||
XRPL_RETIRE(fixSTAmountCanonicalize)
|
XRPL_RETIRE(fixSTAmountCanonicalize)
|
||||||
|
XRPL_RETIRE(fixTakerDryOfferRemoval)
|
||||||
XRPL_RETIRE(CryptoConditions)
|
XRPL_RETIRE(CryptoConditions)
|
||||||
XRPL_RETIRE(Escrow)
|
XRPL_RETIRE(Escrow)
|
||||||
XRPL_RETIRE(EnforceInvariants)
|
XRPL_RETIRE(EnforceInvariants)
|
||||||
@@ -155,5 +154,3 @@ XRPL_RETIRE(PayChan)
|
|||||||
XRPL_RETIRE(SortedDirectories)
|
XRPL_RETIRE(SortedDirectories)
|
||||||
XRPL_RETIRE(TickSize)
|
XRPL_RETIRE(TickSize)
|
||||||
XRPL_RETIRE(TrustSetAuth)
|
XRPL_RETIRE(TrustSetAuth)
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ LEDGER_ENTRY(ltACCOUNT_ROOT, 0x0061, AccountRoot, account, ({
|
|||||||
{sfFirstNFTokenSequence, soeOPTIONAL},
|
{sfFirstNFTokenSequence, soeOPTIONAL},
|
||||||
{sfAMMID, soeOPTIONAL}, // pseudo-account designator
|
{sfAMMID, soeOPTIONAL}, // pseudo-account designator
|
||||||
{sfVaultID, soeOPTIONAL}, // pseudo-account designator
|
{sfVaultID, soeOPTIONAL}, // pseudo-account designator
|
||||||
{sfLoanBrokerID, soeOPTIONAL}, // pseudo-account designator
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
/** A ledger object which contains a list of object identifiers.
|
/** A ledger object which contains a list of object identifiers.
|
||||||
@@ -458,7 +457,7 @@ LEDGER_ENTRY(ltCREDENTIAL, 0x0081, Credential, credential, ({
|
|||||||
{sfExpiration, soeOPTIONAL},
|
{sfExpiration, soeOPTIONAL},
|
||||||
{sfURI, soeOPTIONAL},
|
{sfURI, soeOPTIONAL},
|
||||||
{sfIssuerNode, soeREQUIRED},
|
{sfIssuerNode, soeREQUIRED},
|
||||||
{sfSubjectNode, soeREQUIRED},
|
{sfSubjectNode, soeOPTIONAL},
|
||||||
{sfPreviousTxnID, soeREQUIRED},
|
{sfPreviousTxnID, soeREQUIRED},
|
||||||
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
||||||
}))
|
}))
|
||||||
@@ -510,117 +509,5 @@ LEDGER_ENTRY(ltVAULT, 0x0084, Vault, vault, ({
|
|||||||
// no PermissionedDomainID ever (use MPTIssuance.sfDomainID)
|
// no PermissionedDomainID ever (use MPTIssuance.sfDomainID)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
/** Reserve 0x0084-0x0087 for future Vault-related objects. */
|
|
||||||
|
|
||||||
/** A ledger object representing a loan broker
|
|
||||||
|
|
||||||
\sa keylet::loanbroker
|
|
||||||
*/
|
|
||||||
LEDGER_ENTRY(ltLOAN_BROKER, 0x0088, LoanBroker, loan_broker, ({
|
|
||||||
{sfPreviousTxnID, soeREQUIRED},
|
|
||||||
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
|
||||||
{sfSequence, soeREQUIRED},
|
|
||||||
{sfOwnerNode, soeREQUIRED},
|
|
||||||
{sfVaultNode, soeREQUIRED},
|
|
||||||
{sfVaultID, soeREQUIRED},
|
|
||||||
{sfAccount, soeREQUIRED},
|
|
||||||
{sfOwner, soeREQUIRED},
|
|
||||||
{sfLoanSequence, soeREQUIRED},
|
|
||||||
{sfData, soeDEFAULT},
|
|
||||||
{sfManagementFeeRate, soeDEFAULT},
|
|
||||||
{sfOwnerCount, soeDEFAULT},
|
|
||||||
{sfDebtTotal, soeDEFAULT},
|
|
||||||
{sfDebtMaximum, soeDEFAULT},
|
|
||||||
{sfCoverAvailable, soeDEFAULT},
|
|
||||||
{sfCoverRateMinimum, soeDEFAULT},
|
|
||||||
{sfCoverRateLiquidation, soeDEFAULT},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** A ledger object representing a loan between a Borrower and a Loan Broker
|
|
||||||
|
|
||||||
\sa keylet::loan
|
|
||||||
*/
|
|
||||||
LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
|
|
||||||
{sfPreviousTxnID, soeREQUIRED},
|
|
||||||
{sfPreviousTxnLgrSeq, soeREQUIRED},
|
|
||||||
{sfOwnerNode, soeREQUIRED},
|
|
||||||
{sfLoanBrokerNode, soeREQUIRED},
|
|
||||||
{sfLoanBrokerID, soeREQUIRED},
|
|
||||||
{sfLoanSequence, soeREQUIRED},
|
|
||||||
{sfBorrower, soeREQUIRED},
|
|
||||||
{sfLoanOriginationFee, soeDEFAULT},
|
|
||||||
{sfLoanServiceFee, soeDEFAULT},
|
|
||||||
{sfLatePaymentFee, soeDEFAULT},
|
|
||||||
{sfClosePaymentFee, soeDEFAULT},
|
|
||||||
{sfOverpaymentFee, soeDEFAULT},
|
|
||||||
{sfInterestRate, soeDEFAULT},
|
|
||||||
{sfLateInterestRate, soeDEFAULT},
|
|
||||||
{sfCloseInterestRate, soeDEFAULT},
|
|
||||||
{sfOverpaymentInterestRate, soeDEFAULT},
|
|
||||||
{sfStartDate, soeREQUIRED},
|
|
||||||
{sfPaymentInterval, soeREQUIRED},
|
|
||||||
{sfGracePeriod, soeREQUIRED},
|
|
||||||
{sfPreviousPaymentDate, soeDEFAULT},
|
|
||||||
{sfNextPaymentDueDate, soeOPTIONAL},
|
|
||||||
// The loan object tracks these values:
|
|
||||||
//
|
|
||||||
// - PaymentRemaining: The number of payments left in the loan. When it
|
|
||||||
// reaches 0, the loan is paid off, and all other relevant values
|
|
||||||
// must also be 0.
|
|
||||||
//
|
|
||||||
// - PeriodicPayment: The fixed, unrounded amount to be paid each
|
|
||||||
// interval. Stored with as much precision as possible.
|
|
||||||
// Payment transactions must round this value *UP*.
|
|
||||||
//
|
|
||||||
// - TotalValueOutstanding: The rounded total amount owed by the
|
|
||||||
// borrower to the lender / vault.
|
|
||||||
//
|
|
||||||
// - PrincipalOutstanding: The rounded portion of the
|
|
||||||
// TotalValueOutstanding that is from the principal borrowed.
|
|
||||||
//
|
|
||||||
// - ManagementFeeOutstanding: The rounded portion of the
|
|
||||||
// TotalValueOutstanding that represents management fees
|
|
||||||
// specifically owed to the broker based on the initial
|
|
||||||
// loan parameters.
|
|
||||||
//
|
|
||||||
// There are additional values that can be computed from these:
|
|
||||||
//
|
|
||||||
// - InterestOutstanding = TotalValueOutstanding - PrincipalOutstanding
|
|
||||||
// The total amount of interest still pending on the loan,
|
|
||||||
// independent of management fees.
|
|
||||||
//
|
|
||||||
// - InterestOwedToVault = InterestOutstanding - ManagementFeeOutstanding
|
|
||||||
// The amount of the total interest that is owed to the vault, and
|
|
||||||
// will be sent to as part of a payment.
|
|
||||||
//
|
|
||||||
// - TrueTotalLoanValue = PaymentRemaining * PeriodicPayment
|
|
||||||
// The unrounded true total value of the loan.
|
|
||||||
//
|
|
||||||
// - TrueTotalPrincialOutstanding can be computed using the algorithm
|
|
||||||
// in the ripple::detail::loanPrincipalFromPeriodicPayment function.
|
|
||||||
//
|
|
||||||
// - TrueTotalInterestOutstanding = TrueTotalLoanValue -
|
|
||||||
// TrueTotalPrincipalOutstanding
|
|
||||||
// The unrounded true total interest remaining.
|
|
||||||
//
|
|
||||||
// - TrueTotalManagementFeeOutstanding = TrueTotalInterestOutstanding *
|
|
||||||
// LoanBroker.ManagementFeeRate
|
|
||||||
// The unrounded true total fee still owed to the broker.
|
|
||||||
//
|
|
||||||
// Note the the "True" values may differ significantly from the tracked
|
|
||||||
// rounded values.
|
|
||||||
{sfPaymentRemaining, soeDEFAULT},
|
|
||||||
{sfPeriodicPayment, soeREQUIRED},
|
|
||||||
{sfPrincipalOutstanding, soeDEFAULT},
|
|
||||||
{sfTotalValueOutstanding, soeDEFAULT},
|
|
||||||
{sfManagementFeeOutstanding, soeDEFAULT},
|
|
||||||
// Based on the computed total value at creation, used for
|
|
||||||
// rounding calculated values so they are all on a
|
|
||||||
// consistent scale - that is, they all have the same
|
|
||||||
// number of digits after the decimal point (excluding
|
|
||||||
// trailing zeros).
|
|
||||||
{sfLoanScale, soeDEFAULT},
|
|
||||||
}))
|
|
||||||
|
|
||||||
#undef EXPAND
|
#undef EXPAND
|
||||||
#undef LEDGER_ENTRY_DUPLICATE
|
#undef LEDGER_ENTRY_DUPLICATE
|
||||||
|
|||||||
@@ -24,8 +24,6 @@
|
|||||||
#error "undefined macro: TYPED_SFIELD"
|
#error "undefined macro: TYPED_SFIELD"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
// untyped
|
// untyped
|
||||||
UNTYPED_SFIELD(sfLedgerEntry, LEDGERENTRY, 257)
|
UNTYPED_SFIELD(sfLedgerEntry, LEDGERENTRY, 257)
|
||||||
UNTYPED_SFIELD(sfTransaction, TRANSACTION, 257)
|
UNTYPED_SFIELD(sfTransaction, TRANSACTION, 257)
|
||||||
@@ -61,7 +59,6 @@ TYPED_SFIELD(sfHookEmitCount, UINT16, 18)
|
|||||||
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
|
TYPED_SFIELD(sfHookExecutionIndex, UINT16, 19)
|
||||||
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
|
TYPED_SFIELD(sfHookApiVersion, UINT16, 20)
|
||||||
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
|
TYPED_SFIELD(sfLedgerFixType, UINT16, 21)
|
||||||
TYPED_SFIELD(sfManagementFeeRate, UINT16, 22) // 1/10 basis points (bips)
|
|
||||||
|
|
||||||
// 32-bit integers (common)
|
// 32-bit integers (common)
|
||||||
TYPED_SFIELD(sfNetworkID, UINT32, 1)
|
TYPED_SFIELD(sfNetworkID, UINT32, 1)
|
||||||
@@ -118,21 +115,6 @@ TYPED_SFIELD(sfFirstNFTokenSequence, UINT32, 50)
|
|||||||
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
|
TYPED_SFIELD(sfOracleDocumentID, UINT32, 51)
|
||||||
TYPED_SFIELD(sfPermissionValue, UINT32, 52)
|
TYPED_SFIELD(sfPermissionValue, UINT32, 52)
|
||||||
TYPED_SFIELD(sfMutableFlags, UINT32, 53)
|
TYPED_SFIELD(sfMutableFlags, UINT32, 53)
|
||||||
TYPED_SFIELD(sfStartDate, UINT32, 54)
|
|
||||||
TYPED_SFIELD(sfPaymentInterval, UINT32, 55)
|
|
||||||
TYPED_SFIELD(sfGracePeriod, UINT32, 56)
|
|
||||||
TYPED_SFIELD(sfPreviousPaymentDate, UINT32, 57)
|
|
||||||
TYPED_SFIELD(sfNextPaymentDueDate, UINT32, 58)
|
|
||||||
TYPED_SFIELD(sfPaymentRemaining, UINT32, 59)
|
|
||||||
TYPED_SFIELD(sfPaymentTotal, UINT32, 60)
|
|
||||||
TYPED_SFIELD(sfLoanSequence, UINT32, 61)
|
|
||||||
TYPED_SFIELD(sfCoverRateMinimum, UINT32, 62) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfCoverRateLiquidation, UINT32, 63) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfOverpaymentFee, UINT32, 64) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfLateInterestRate, UINT32, 66) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfCloseInterestRate, UINT32, 67) // 1/10 basis points (bips)
|
|
||||||
TYPED_SFIELD(sfOverpaymentInterestRate, UINT32, 68) // 1/10 basis points (bips)
|
|
||||||
|
|
||||||
// 64-bit integers (common)
|
// 64-bit integers (common)
|
||||||
TYPED_SFIELD(sfIndexNext, UINT64, 1)
|
TYPED_SFIELD(sfIndexNext, UINT64, 1)
|
||||||
@@ -164,8 +146,6 @@ TYPED_SFIELD(sfMPTAmount, UINT64, 26, SField::sMD_BaseTen|SFie
|
|||||||
TYPED_SFIELD(sfIssuerNode, UINT64, 27)
|
TYPED_SFIELD(sfIssuerNode, UINT64, 27)
|
||||||
TYPED_SFIELD(sfSubjectNode, UINT64, 28)
|
TYPED_SFIELD(sfSubjectNode, UINT64, 28)
|
||||||
TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default)
|
TYPED_SFIELD(sfLockedAmount, UINT64, 29, SField::sMD_BaseTen|SField::sMD_Default)
|
||||||
TYPED_SFIELD(sfVaultNode, UINT64, 30)
|
|
||||||
TYPED_SFIELD(sfLoanBrokerNode, UINT64, 31)
|
|
||||||
|
|
||||||
// 128-bit
|
// 128-bit
|
||||||
TYPED_SFIELD(sfEmailHash, UINT128, 1)
|
TYPED_SFIELD(sfEmailHash, UINT128, 1)
|
||||||
@@ -220,9 +200,6 @@ TYPED_SFIELD(sfDomainID, UINT256, 34)
|
|||||||
TYPED_SFIELD(sfVaultID, UINT256, 35,
|
TYPED_SFIELD(sfVaultID, UINT256, 35,
|
||||||
SField::sMD_PseudoAccount | SField::sMD_Default)
|
SField::sMD_PseudoAccount | SField::sMD_Default)
|
||||||
TYPED_SFIELD(sfParentBatchID, UINT256, 36)
|
TYPED_SFIELD(sfParentBatchID, UINT256, 36)
|
||||||
TYPED_SFIELD(sfLoanBrokerID, UINT256, 37,
|
|
||||||
SField::sMD_PseudoAccount | SField::sMD_Default)
|
|
||||||
TYPED_SFIELD(sfLoanID, UINT256, 38)
|
|
||||||
|
|
||||||
// number (common)
|
// number (common)
|
||||||
TYPED_SFIELD(sfNumber, NUMBER, 1)
|
TYPED_SFIELD(sfNumber, NUMBER, 1)
|
||||||
@@ -230,21 +207,12 @@ TYPED_SFIELD(sfAssetsAvailable, NUMBER, 2)
|
|||||||
TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
|
TYPED_SFIELD(sfAssetsMaximum, NUMBER, 3)
|
||||||
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
|
TYPED_SFIELD(sfAssetsTotal, NUMBER, 4)
|
||||||
TYPED_SFIELD(sfLossUnrealized, NUMBER, 5)
|
TYPED_SFIELD(sfLossUnrealized, NUMBER, 5)
|
||||||
TYPED_SFIELD(sfDebtTotal, NUMBER, 6)
|
|
||||||
TYPED_SFIELD(sfDebtMaximum, NUMBER, 7)
|
|
||||||
TYPED_SFIELD(sfCoverAvailable, NUMBER, 8)
|
|
||||||
TYPED_SFIELD(sfLoanOriginationFee, NUMBER, 9)
|
|
||||||
TYPED_SFIELD(sfLoanServiceFee, NUMBER, 10)
|
|
||||||
TYPED_SFIELD(sfLatePaymentFee, NUMBER, 11)
|
|
||||||
TYPED_SFIELD(sfClosePaymentFee, NUMBER, 12)
|
|
||||||
TYPED_SFIELD(sfPrincipalOutstanding, NUMBER, 13)
|
|
||||||
TYPED_SFIELD(sfPrincipalRequested, NUMBER, 14)
|
|
||||||
TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15)
|
|
||||||
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
|
|
||||||
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17)
|
|
||||||
|
|
||||||
// int32
|
// int32
|
||||||
TYPED_SFIELD(sfLoanScale, INT32, 1)
|
// NOTE: Do not use `sfDummyInt32`. It's so far the only use of INT32
|
||||||
|
// in this file and has been defined here for test only.
|
||||||
|
// TODO: Replace `sfDummyInt32` with actually useful field.
|
||||||
|
TYPED_SFIELD(sfDummyInt32, INT32, 1) // for tests only
|
||||||
|
|
||||||
// currency amount (common)
|
// currency amount (common)
|
||||||
TYPED_SFIELD(sfAmount, AMOUNT, 1)
|
TYPED_SFIELD(sfAmount, AMOUNT, 1)
|
||||||
@@ -340,8 +308,6 @@ TYPED_SFIELD(sfAttestationRewardAccount, ACCOUNT, 21)
|
|||||||
TYPED_SFIELD(sfLockingChainDoor, ACCOUNT, 22)
|
TYPED_SFIELD(sfLockingChainDoor, ACCOUNT, 22)
|
||||||
TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23)
|
TYPED_SFIELD(sfIssuingChainDoor, ACCOUNT, 23)
|
||||||
TYPED_SFIELD(sfSubject, ACCOUNT, 24)
|
TYPED_SFIELD(sfSubject, ACCOUNT, 24)
|
||||||
TYPED_SFIELD(sfBorrower, ACCOUNT, 25)
|
|
||||||
TYPED_SFIELD(sfCounterparty, ACCOUNT, 26)
|
|
||||||
|
|
||||||
// vector of 256-bit
|
// vector of 256-bit
|
||||||
TYPED_SFIELD(sfIndexes, VECTOR256, 1, SField::sMD_Never)
|
TYPED_SFIELD(sfIndexes, VECTOR256, 1, SField::sMD_Never)
|
||||||
@@ -405,7 +371,6 @@ UNTYPED_SFIELD(sfCredential, OBJECT, 33)
|
|||||||
UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34)
|
UNTYPED_SFIELD(sfRawTransaction, OBJECT, 34)
|
||||||
UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35)
|
UNTYPED_SFIELD(sfBatchSigner, OBJECT, 35)
|
||||||
UNTYPED_SFIELD(sfBook, OBJECT, 36)
|
UNTYPED_SFIELD(sfBook, OBJECT, 36)
|
||||||
UNTYPED_SFIELD(sfCounterpartySignature, OBJECT, 37, SField::sMD_Default, SField::notSigning)
|
|
||||||
|
|
||||||
// array of objects (common)
|
// array of objects (common)
|
||||||
// ARRAY/1 is reserved for end of array
|
// ARRAY/1 is reserved for end of array
|
||||||
@@ -440,5 +405,3 @@ UNTYPED_SFIELD(sfAcceptedCredentials, ARRAY, 28)
|
|||||||
UNTYPED_SFIELD(sfPermissions, ARRAY, 29)
|
UNTYPED_SFIELD(sfPermissions, ARRAY, 29)
|
||||||
UNTYPED_SFIELD(sfRawTransactions, ARRAY, 30)
|
UNTYPED_SFIELD(sfRawTransactions, ARRAY, 30)
|
||||||
UNTYPED_SFIELD(sfBatchSigners, ARRAY, 31, SField::sMD_Default, SField::notSigning)
|
UNTYPED_SFIELD(sfBatchSigners, ARRAY, 31, SField::sMD_Default, SField::notSigning)
|
||||||
|
|
||||||
// clang-format on
|
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ TRANSACTION(ttTRUST_SET, 20, TrustSet,
|
|||||||
#endif
|
#endif
|
||||||
TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
|
TRANSACTION(ttACCOUNT_DELETE, 21, AccountDelete,
|
||||||
Delegation::notDelegatable,
|
Delegation::notDelegatable,
|
||||||
uint256{},
|
featureDeletableAccounts,
|
||||||
mustDeleteAcct,
|
mustDeleteAcct,
|
||||||
({
|
({
|
||||||
{sfDestination, soeREQUIRED},
|
{sfDestination, soeREQUIRED},
|
||||||
@@ -837,7 +837,7 @@ TRANSACTION(ttPERMISSIONED_DOMAIN_DELETE, 63, PermissionedDomainDelete,
|
|||||||
#endif
|
#endif
|
||||||
TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
|
TRANSACTION(ttDELEGATE_SET, 64, DelegateSet,
|
||||||
Delegation::notDelegatable,
|
Delegation::notDelegatable,
|
||||||
featurePermissionDelegation,
|
featurePermissionDelegationV1_1,
|
||||||
noPriv,
|
noPriv,
|
||||||
({
|
({
|
||||||
{sfAuthorize, soeREQUIRED},
|
{sfAuthorize, soeREQUIRED},
|
||||||
@@ -944,139 +944,6 @@ TRANSACTION(ttBATCH, 71, Batch,
|
|||||||
{sfBatchSigners, soeOPTIONAL},
|
{sfBatchSigners, soeOPTIONAL},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
/** Reserve 72-73 for future Vault-related transactions */
|
|
||||||
|
|
||||||
/** This transaction creates and updates a Loan Broker */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanBrokerSet.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_BROKER_SET, 74, LoanBrokerSet,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
createPseudoAcct | mayAuthorizeMPT, ({
|
|
||||||
{sfVaultID, soeREQUIRED},
|
|
||||||
{sfLoanBrokerID, soeOPTIONAL},
|
|
||||||
{sfData, soeOPTIONAL},
|
|
||||||
{sfManagementFeeRate, soeOPTIONAL},
|
|
||||||
{sfDebtMaximum, soeOPTIONAL},
|
|
||||||
{sfCoverRateMinimum, soeOPTIONAL},
|
|
||||||
{sfCoverRateLiquidation, soeOPTIONAL},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction deletes a Loan Broker */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanBrokerDelete.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_BROKER_DELETE, 75, LoanBrokerDelete,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
mustDeleteAcct | mayAuthorizeMPT, ({
|
|
||||||
{sfLoanBrokerID, soeREQUIRED},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction deposits First Loss Capital into a Loan Broker */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanBrokerCoverDeposit.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_BROKER_COVER_DEPOSIT, 76, LoanBrokerCoverDeposit,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
noPriv, ({
|
|
||||||
{sfLoanBrokerID, soeREQUIRED},
|
|
||||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction withdraws First Loss Capital from a Loan Broker */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanBrokerCoverWithdraw.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_BROKER_COVER_WITHDRAW, 77, LoanBrokerCoverWithdraw,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
mayAuthorizeMPT, ({
|
|
||||||
{sfLoanBrokerID, soeREQUIRED},
|
|
||||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
|
||||||
{sfDestination, soeOPTIONAL},
|
|
||||||
{sfDestinationTag, soeOPTIONAL},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction claws back First Loss Capital from a Loan Broker to
|
|
||||||
the issuer of the capital */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanBrokerCoverClawback.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_BROKER_COVER_CLAWBACK, 78, LoanBrokerCoverClawback,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
noPriv, ({
|
|
||||||
{sfLoanBrokerID, soeOPTIONAL},
|
|
||||||
{sfAmount, soeOPTIONAL, soeMPTSupported},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction creates a Loan */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanSet.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_SET, 80, LoanSet,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
mayAuthorizeMPT | mustModifyVault, ({
|
|
||||||
{sfLoanBrokerID, soeREQUIRED},
|
|
||||||
{sfData, soeOPTIONAL},
|
|
||||||
{sfCounterparty, soeOPTIONAL},
|
|
||||||
{sfCounterpartySignature, soeOPTIONAL},
|
|
||||||
{sfLoanOriginationFee, soeOPTIONAL},
|
|
||||||
{sfLoanServiceFee, soeOPTIONAL},
|
|
||||||
{sfLatePaymentFee, soeOPTIONAL},
|
|
||||||
{sfClosePaymentFee, soeOPTIONAL},
|
|
||||||
{sfOverpaymentFee, soeOPTIONAL},
|
|
||||||
{sfInterestRate, soeOPTIONAL},
|
|
||||||
{sfLateInterestRate, soeOPTIONAL},
|
|
||||||
{sfCloseInterestRate, soeOPTIONAL},
|
|
||||||
{sfOverpaymentInterestRate, soeOPTIONAL},
|
|
||||||
{sfPrincipalRequested, soeREQUIRED},
|
|
||||||
{sfPaymentTotal, soeOPTIONAL},
|
|
||||||
{sfPaymentInterval, soeOPTIONAL},
|
|
||||||
{sfGracePeriod, soeOPTIONAL},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction deletes an existing Loan */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanDelete.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_DELETE, 81, LoanDelete,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
noPriv, ({
|
|
||||||
{sfLoanID, soeREQUIRED},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This transaction is used to change the delinquency status of an existing Loan */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanManage.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_MANAGE, 82, LoanManage,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
// All of the LoanManage options will modify the vault, but the
|
|
||||||
// transaction can succeed without options, essentially making it
|
|
||||||
// a noop.
|
|
||||||
mayModifyVault, ({
|
|
||||||
{sfLoanID, soeREQUIRED},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** The Borrower uses this transaction to make a Payment on the Loan. */
|
|
||||||
#if TRANSACTION_INCLUDE
|
|
||||||
# include <xrpld/app/tx/detail/LoanPay.h>
|
|
||||||
#endif
|
|
||||||
TRANSACTION(ttLOAN_PAY, 84, LoanPay,
|
|
||||||
Delegation::delegatable,
|
|
||||||
featureLendingProtocol,
|
|
||||||
mayAuthorizeMPT | mustModifyVault, ({
|
|
||||||
{sfLoanID, soeREQUIRED},
|
|
||||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
|
||||||
}))
|
|
||||||
|
|
||||||
/** This system-generated transaction type is used to update the status of the various amendments.
|
/** This system-generated transaction type is used to update the status of the various amendments.
|
||||||
|
|
||||||
For details, see: https://xrpl.org/amendments.html
|
For details, see: https://xrpl.org/amendments.html
|
||||||
|
|||||||
@@ -59,8 +59,6 @@ JSS(BaseAsset); // in: Oracle
|
|||||||
JSS(BidMax); // in: AMM Bid
|
JSS(BidMax); // in: AMM Bid
|
||||||
JSS(BidMin); // in: AMM Bid
|
JSS(BidMin); // in: AMM Bid
|
||||||
JSS(ClearFlag); // field.
|
JSS(ClearFlag); // field.
|
||||||
JSS(Counterparty); // field.
|
|
||||||
JSS(CounterpartySignature);// field.
|
|
||||||
JSS(DeliverMax); // out: alias to Amount
|
JSS(DeliverMax); // out: alias to Amount
|
||||||
JSS(DeliverMin); // in: TransactionSign
|
JSS(DeliverMin); // in: TransactionSign
|
||||||
JSS(Destination); // in: TransactionSign; field.
|
JSS(Destination); // in: TransactionSign; field.
|
||||||
@@ -394,8 +392,6 @@ JSS(load_factor_local); // out: NetworkOPs
|
|||||||
JSS(load_factor_net); // out: NetworkOPs
|
JSS(load_factor_net); // out: NetworkOPs
|
||||||
JSS(load_factor_server); // out: NetworkOPs
|
JSS(load_factor_server); // out: NetworkOPs
|
||||||
JSS(load_fee); // out: LoadFeeTrackImp, NetworkOPs
|
JSS(load_fee); // out: LoadFeeTrackImp, NetworkOPs
|
||||||
JSS(loan_broker_id); // in: LedgerEntry
|
|
||||||
JSS(loan_seq); // in: LedgerEntry
|
|
||||||
JSS(local); // out: resource/Logic.h
|
JSS(local); // out: resource/Logic.h
|
||||||
JSS(local_txs); // out: GetCounts
|
JSS(local_txs); // out: GetCounts
|
||||||
JSS(local_static_keys); // out: ValidatorList
|
JSS(local_static_keys); // out: ValidatorList
|
||||||
@@ -508,7 +504,6 @@ JSS(propose_seq); // out: LedgerPropose
|
|||||||
JSS(proposers); // out: NetworkOPs, LedgerConsensus
|
JSS(proposers); // out: NetworkOPs, LedgerConsensus
|
||||||
JSS(protocol); // out: NetworkOPs, PeerImp
|
JSS(protocol); // out: NetworkOPs, PeerImp
|
||||||
JSS(proxied); // out: RPC ping
|
JSS(proxied); // out: RPC ping
|
||||||
JSS(pseudo_account); // out: AccountInfo
|
|
||||||
JSS(pubkey_node); // out: NetworkOPs
|
JSS(pubkey_node); // out: NetworkOPs
|
||||||
JSS(pubkey_publisher); // out: ValidatorList
|
JSS(pubkey_publisher); // out: ValidatorList
|
||||||
JSS(pubkey_validator); // out: NetworkOPs, ValidatorList
|
JSS(pubkey_validator); // out: NetworkOPs, ValidatorList
|
||||||
|
|||||||
@@ -20,11 +20,10 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_FAMILY_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_FAMILY_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_FAMILY_H_INCLUDED
|
#define RIPPLE_SHAMAP_FAMILY_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Database.h>
|
|
||||||
#include <xrpld/shamap/FullBelowCache.h>
|
|
||||||
#include <xrpld/shamap/TreeNodeCache.h>
|
|
||||||
|
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
|
#include <xrpl/nodestore/Database.h>
|
||||||
|
#include <xrpl/shamap/FullBelowCache.h>
|
||||||
|
#include <xrpl/shamap/TreeNodeCache.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -20,21 +20,19 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAP_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/nodestore/Database.h>
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
|
||||||
#include <xrpld/shamap/Family.h>
|
|
||||||
#include <xrpld/shamap/SHAMapAddNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapInnerNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
|
||||||
#include <xrpld/shamap/SHAMapLeafNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapMissingNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
|
||||||
#include <xrpld/shamap/TreeNodeCache.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.h>
|
#include <xrpl/basics/IntrusivePointer.h>
|
||||||
#include <xrpl/basics/UnorderedContainers.h>
|
#include <xrpl/basics/UnorderedContainers.h>
|
||||||
#include <xrpl/beast/utility/Journal.h>
|
#include <xrpl/beast/utility/Journal.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/nodestore/Database.h>
|
||||||
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
#include <xrpl/shamap/Family.h>
|
||||||
|
#include <xrpl/shamap/SHAMapAddNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapInnerNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapMissingNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
@@ -20,12 +20,11 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPACCOUNTSTATELEAFNODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
|
||||||
#include <xrpld/shamap/SHAMapLeafNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/CountedObject.h>
|
#include <xrpl/basics/CountedObject.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/digest.h>
|
#include <xrpl/protocol/digest.h>
|
||||||
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -20,10 +20,9 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapNodeID.h>
|
|
||||||
#include <xrpld/shamap/detail/TaggedPointer.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.h>
|
#include <xrpl/basics/IntrusivePointer.h>
|
||||||
|
#include <xrpl/shamap/SHAMapNodeID.h>
|
||||||
|
#include <xrpl/shamap/detail/TaggedPointer.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPLEAFNODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -20,9 +20,8 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPMISSINGNODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/base_uint.h>
|
#include <xrpl/basics/base_uint.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPSYNCFILTER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
@@ -20,13 +20,12 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPTREENODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
|
||||||
#include <xrpld/shamap/SHAMapNodeID.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.h>
|
#include <xrpl/basics/IntrusivePointer.h>
|
||||||
#include <xrpl/basics/IntrusiveRefCounts.h>
|
#include <xrpl/basics/IntrusiveRefCounts.h>
|
||||||
#include <xrpl/basics/SHAMapHash.h>
|
#include <xrpl/basics/SHAMapHash.h>
|
||||||
#include <xrpl/protocol/Serializer.h>
|
#include <xrpl/protocol/Serializer.h>
|
||||||
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
|
#include <xrpl/shamap/SHAMapNodeID.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -20,12 +20,11 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPTXLEAFNODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
|
||||||
#include <xrpld/shamap/SHAMapLeafNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/CountedObject.h>
|
#include <xrpl/basics/CountedObject.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/digest.h>
|
#include <xrpl/protocol/digest.h>
|
||||||
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -20,12 +20,11 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
|
#define RIPPLE_SHAMAP_SHAMAPLEAFTXPLUSMETANODE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapItem.h>
|
|
||||||
#include <xrpld/shamap/SHAMapLeafNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/CountedObject.h>
|
#include <xrpl/basics/CountedObject.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/digest.h>
|
#include <xrpl/protocol/digest.h>
|
||||||
|
#include <xrpl/shamap/SHAMapItem.h>
|
||||||
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -20,10 +20,9 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
|
#define RIPPLE_SHAMAP_TREENODECACHE_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.h>
|
#include <xrpl/basics/IntrusivePointer.h>
|
||||||
#include <xrpl/basics/TaggedCache.h>
|
#include <xrpl/basics/TaggedCache.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -20,9 +20,8 @@
|
|||||||
#ifndef RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
|
#ifndef RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
|
||||||
#define RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
|
#define RIPPLE_SHAMAP_TAGGEDPOINTER_H_INCLUDED
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.h>
|
#include <xrpl/basics/IntrusivePointer.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapInnerNode.h>
|
|
||||||
#include <xrpld/shamap/detail/TaggedPointer.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/ByteUtilities.h>
|
#include <xrpl/basics/ByteUtilities.h>
|
||||||
|
#include <xrpl/shamap/SHAMapInnerNode.h>
|
||||||
|
#include <xrpl/shamap/detail/TaggedPointer.h>
|
||||||
|
|
||||||
#include <boost/pool/pool_alloc.hpp>
|
#include <boost/pool/pool_alloc.hpp>
|
||||||
|
|
||||||
@@ -43,8 +43,6 @@ namespace ripple {
|
|||||||
|
|
||||||
thread_local Number::rounding_mode Number::mode_ = Number::to_nearest;
|
thread_local Number::rounding_mode Number::mode_ = Number::to_nearest;
|
||||||
|
|
||||||
Number const Number::zero{};
|
|
||||||
|
|
||||||
Number::rounding_mode
|
Number::rounding_mode
|
||||||
Number::getround()
|
Number::getround()
|
||||||
{
|
{
|
||||||
@@ -95,18 +93,6 @@ public:
|
|||||||
// tie, round towards even.
|
// tie, round towards even.
|
||||||
int
|
int
|
||||||
round() noexcept;
|
round() noexcept;
|
||||||
|
|
||||||
// Modify the result to the correctly rounded value
|
|
||||||
void
|
|
||||||
doRoundUp(rep& mantissa, int& exponent, std::string location);
|
|
||||||
|
|
||||||
// Modify the result to the correctly rounded value
|
|
||||||
void
|
|
||||||
doRoundDown(rep& mantissa, int& exponent);
|
|
||||||
|
|
||||||
// Modify the result to the correctly rounded value
|
|
||||||
void
|
|
||||||
doRound(rep& drops);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
@@ -184,61 +170,6 @@ Number::Guard::round() noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Number::Guard::doRoundUp(rep& mantissa, int& exponent, std::string location)
|
|
||||||
{
|
|
||||||
auto r = round();
|
|
||||||
if (r == 1 || (r == 0 && (mantissa & 1) == 1))
|
|
||||||
{
|
|
||||||
++mantissa;
|
|
||||||
if (mantissa > maxMantissa)
|
|
||||||
{
|
|
||||||
mantissa /= 10;
|
|
||||||
++exponent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exponent < minExponent)
|
|
||||||
{
|
|
||||||
mantissa = 0;
|
|
||||||
exponent = Number{}.exponent_;
|
|
||||||
}
|
|
||||||
if (exponent > maxExponent)
|
|
||||||
throw std::overflow_error(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Number::Guard::doRoundDown(rep& mantissa, int& exponent)
|
|
||||||
{
|
|
||||||
auto r = round();
|
|
||||||
if (r == 1 || (r == 0 && (mantissa & 1) == 1))
|
|
||||||
{
|
|
||||||
--mantissa;
|
|
||||||
if (mantissa < minMantissa)
|
|
||||||
{
|
|
||||||
mantissa *= 10;
|
|
||||||
--exponent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exponent < minExponent)
|
|
||||||
{
|
|
||||||
mantissa = 0;
|
|
||||||
exponent = Number{}.exponent_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify the result to the correctly rounded value
|
|
||||||
void
|
|
||||||
Number::Guard::doRound(rep& drops)
|
|
||||||
{
|
|
||||||
auto r = round();
|
|
||||||
if (r == 1 || (r == 0 && (drops & 1) == 1))
|
|
||||||
{
|
|
||||||
++drops;
|
|
||||||
}
|
|
||||||
if (is_negative())
|
|
||||||
drops = -drops;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number
|
// Number
|
||||||
|
|
||||||
constexpr Number one{1000000000000000, -15, Number::unchecked{}};
|
constexpr Number one{1000000000000000, -15, Number::unchecked{}};
|
||||||
@@ -278,7 +209,18 @@ Number::normalize()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.doRoundUp(mantissa_, exponent_, "Number::normalize 2");
|
auto r = g.round();
|
||||||
|
if (r == 1 || (r == 0 && (mantissa_ & 1) == 1))
|
||||||
|
{
|
||||||
|
++mantissa_;
|
||||||
|
if (mantissa_ > maxMantissa)
|
||||||
|
{
|
||||||
|
mantissa_ /= 10;
|
||||||
|
++exponent_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exponent_ > maxExponent)
|
||||||
|
throw std::overflow_error("Number::normalize 2");
|
||||||
|
|
||||||
if (negative)
|
if (negative)
|
||||||
mantissa_ = -mantissa_;
|
mantissa_ = -mantissa_;
|
||||||
@@ -350,7 +292,18 @@ Number::operator+=(Number const& y)
|
|||||||
xm /= 10;
|
xm /= 10;
|
||||||
++xe;
|
++xe;
|
||||||
}
|
}
|
||||||
g.doRoundUp(xm, xe, "Number::addition overflow");
|
auto r = g.round();
|
||||||
|
if (r == 1 || (r == 0 && (xm & 1) == 1))
|
||||||
|
{
|
||||||
|
++xm;
|
||||||
|
if (xm > maxMantissa)
|
||||||
|
{
|
||||||
|
xm /= 10;
|
||||||
|
++xe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xe > maxExponent)
|
||||||
|
throw std::overflow_error("Number::addition overflow");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -370,7 +323,21 @@ Number::operator+=(Number const& y)
|
|||||||
xm -= g.pop();
|
xm -= g.pop();
|
||||||
--xe;
|
--xe;
|
||||||
}
|
}
|
||||||
g.doRoundDown(xm, xe);
|
auto r = g.round();
|
||||||
|
if (r == 1 || (r == 0 && (xm & 1) == 1))
|
||||||
|
{
|
||||||
|
--xm;
|
||||||
|
if (xm < minMantissa)
|
||||||
|
{
|
||||||
|
xm *= 10;
|
||||||
|
--xe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xe < minExponent)
|
||||||
|
{
|
||||||
|
xm = 0;
|
||||||
|
xe = Number{}.exponent_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mantissa_ = xm * xn;
|
mantissa_ = xm * xn;
|
||||||
exponent_ = xe;
|
exponent_ = xe;
|
||||||
@@ -450,10 +417,25 @@ Number::operator*=(Number const& y)
|
|||||||
}
|
}
|
||||||
xm = static_cast<rep>(zm);
|
xm = static_cast<rep>(zm);
|
||||||
xe = ze;
|
xe = ze;
|
||||||
g.doRoundUp(
|
auto r = g.round();
|
||||||
xm,
|
if (r == 1 || (r == 0 && (xm & 1) == 1))
|
||||||
xe,
|
{
|
||||||
"Number::multiplication overflow : exponent is " + std::to_string(xe));
|
++xm;
|
||||||
|
if (xm > maxMantissa)
|
||||||
|
{
|
||||||
|
xm /= 10;
|
||||||
|
++xe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xe < minExponent)
|
||||||
|
{
|
||||||
|
xm = 0;
|
||||||
|
xe = Number{}.exponent_;
|
||||||
|
}
|
||||||
|
if (xe > maxExponent)
|
||||||
|
throw std::overflow_error(
|
||||||
|
"Number::multiplication overflow : exponent is " +
|
||||||
|
std::to_string(xe));
|
||||||
mantissa_ = xm * zn;
|
mantissa_ = xm * zn;
|
||||||
exponent_ = xe;
|
exponent_ = xe;
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
@@ -518,7 +500,13 @@ Number::operator rep() const
|
|||||||
throw std::overflow_error("Number::operator rep() overflow");
|
throw std::overflow_error("Number::operator rep() overflow");
|
||||||
drops *= 10;
|
drops *= 10;
|
||||||
}
|
}
|
||||||
g.doRound(drops);
|
auto r = g.round();
|
||||||
|
if (r == 1 || (r == 0 && (drops & 1) == 1))
|
||||||
|
{
|
||||||
|
++drops;
|
||||||
|
}
|
||||||
|
if (g.is_negative())
|
||||||
|
drops = -drops;
|
||||||
}
|
}
|
||||||
return drops;
|
return drops;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1001,12 +1001,6 @@ Value::isMember(std::string const& key) const
|
|||||||
return isMember(key.c_str());
|
return isMember(key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Value::isMember(StaticString const& key) const
|
|
||||||
{
|
|
||||||
return isMember(key.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Members
|
Value::Members
|
||||||
Value::getMemberNames() const
|
Value::getMemberNames() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -126,10 +126,10 @@ ApplyStateTable::apply(
|
|||||||
std::optional<TxMeta> metadata;
|
std::optional<TxMeta> metadata;
|
||||||
if (!to.open() || isDryRun)
|
if (!to.open() || isDryRun)
|
||||||
{
|
{
|
||||||
TxMeta meta(tx.getTransactionID(), to.seq(), parentBatchId);
|
TxMeta meta(tx.getTransactionID(), to.seq());
|
||||||
|
|
||||||
if (deliver)
|
meta.setDeliveredAmount(deliver);
|
||||||
meta.setDeliveredAmount(*deliver);
|
meta.setParentBatchID(parentBatchId);
|
||||||
|
|
||||||
Mods newMod;
|
Mods newMod;
|
||||||
for (auto& item : items_)
|
for (auto& item : items_)
|
||||||
|
|||||||
@@ -22,130 +22,11 @@
|
|||||||
#include <xrpl/ledger/ApplyView.h>
|
#include <xrpl/ledger/ApplyView.h>
|
||||||
#include <xrpl/protocol/Protocol.h>
|
#include <xrpl/protocol/Protocol.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
namespace directory {
|
|
||||||
|
|
||||||
std::uint64_t
|
|
||||||
createRoot(
|
|
||||||
ApplyView& view,
|
|
||||||
Keylet const& directory,
|
|
||||||
uint256 const& key,
|
|
||||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
|
||||||
{
|
|
||||||
auto newRoot = std::make_shared<SLE>(directory);
|
|
||||||
newRoot->setFieldH256(sfRootIndex, directory.key);
|
|
||||||
describe(newRoot);
|
|
||||||
|
|
||||||
STVector256 v;
|
|
||||||
v.push_back(key);
|
|
||||||
newRoot->setFieldV256(sfIndexes, v);
|
|
||||||
|
|
||||||
view.insert(newRoot);
|
|
||||||
return std::uint64_t{0};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start)
|
|
||||||
{
|
|
||||||
std::uint64_t page = start->getFieldU64(sfIndexPrevious);
|
|
||||||
|
|
||||||
auto node = start;
|
|
||||||
|
|
||||||
if (page)
|
|
||||||
{
|
|
||||||
node = view.peek(keylet::page(directory, page));
|
|
||||||
if (!node)
|
|
||||||
LogicError("Directory chain: root back-pointer broken.");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto indexes = node->getFieldV256(sfIndexes);
|
|
||||||
return std::make_tuple(page, node, indexes);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint64_t
|
|
||||||
insertKey(
|
|
||||||
ApplyView& view,
|
|
||||||
SLE::ref node,
|
|
||||||
std::uint64_t page,
|
|
||||||
bool preserveOrder,
|
|
||||||
STVector256& indexes,
|
|
||||||
uint256 const& key)
|
|
||||||
{
|
|
||||||
if (preserveOrder)
|
|
||||||
{
|
|
||||||
if (std::find(indexes.begin(), indexes.end(), key) != indexes.end())
|
|
||||||
LogicError("dirInsert: double insertion");
|
|
||||||
|
|
||||||
indexes.push_back(key);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We can't be sure if this page is already sorted because
|
|
||||||
// it may be a legacy page we haven't yet touched. Take
|
|
||||||
// the time to sort it.
|
|
||||||
std::sort(indexes.begin(), indexes.end());
|
|
||||||
|
|
||||||
auto pos = std::lower_bound(indexes.begin(), indexes.end(), key);
|
|
||||||
|
|
||||||
if (pos != indexes.end() && key == *pos)
|
|
||||||
LogicError("dirInsert: double insertion");
|
|
||||||
|
|
||||||
indexes.insert(pos, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
node->setFieldV256(sfIndexes, indexes);
|
|
||||||
view.update(node);
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::uint64_t>
|
|
||||||
insertPage(
|
|
||||||
ApplyView& view,
|
|
||||||
std::uint64_t page,
|
|
||||||
SLE::pointer node,
|
|
||||||
std::uint64_t nextPage,
|
|
||||||
SLE::ref next,
|
|
||||||
uint256 const& key,
|
|
||||||
Keylet const& directory,
|
|
||||||
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
|
|
||||||
{
|
|
||||||
// Check whether we're out of pages.
|
|
||||||
if (++page >= dirNodeMaxPages)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are about to create a new node; we'll link it to
|
|
||||||
// the chain first:
|
|
||||||
node->setFieldU64(sfIndexNext, page);
|
|
||||||
view.update(node);
|
|
||||||
|
|
||||||
next->setFieldU64(sfIndexPrevious, page);
|
|
||||||
view.update(next);
|
|
||||||
|
|
||||||
// Insert the new key:
|
|
||||||
STVector256 indexes;
|
|
||||||
indexes.push_back(key);
|
|
||||||
|
|
||||||
node = std::make_shared<SLE>(keylet::page(directory, page));
|
|
||||||
node->setFieldH256(sfRootIndex, directory.key);
|
|
||||||
node->setFieldV256(sfIndexes, indexes);
|
|
||||||
|
|
||||||
// Save some space by not specifying the value 0 since
|
|
||||||
// it's the default.
|
|
||||||
if (page != 1)
|
|
||||||
node->setFieldU64(sfIndexPrevious, page - 1);
|
|
||||||
if (nextPage)
|
|
||||||
node->setFieldU64(sfIndexNext, nextPage);
|
|
||||||
describe(node);
|
|
||||||
view.insert(node);
|
|
||||||
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace directory
|
|
||||||
|
|
||||||
std::optional<std::uint64_t>
|
std::optional<std::uint64_t>
|
||||||
ApplyView::dirAdd(
|
ApplyView::dirAdd(
|
||||||
bool preserveOrder,
|
bool preserveOrder,
|
||||||
@@ -158,21 +39,102 @@ ApplyView::dirAdd(
|
|||||||
if (!root)
|
if (!root)
|
||||||
{
|
{
|
||||||
// No root, make it.
|
// No root, make it.
|
||||||
return directory::createRoot(*this, directory, key, describe);
|
root = std::make_shared<SLE>(directory);
|
||||||
|
root->setFieldH256(sfRootIndex, directory.key);
|
||||||
|
describe(root);
|
||||||
|
|
||||||
|
STVector256 v;
|
||||||
|
v.push_back(key);
|
||||||
|
root->setFieldV256(sfIndexes, v);
|
||||||
|
|
||||||
|
insert(root);
|
||||||
|
return std::uint64_t{0};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [page, node, indexes] =
|
std::uint64_t page = root->getFieldU64(sfIndexPrevious);
|
||||||
directory::findPreviousPage(*this, directory, root);
|
|
||||||
|
auto node = root;
|
||||||
|
|
||||||
|
if (page)
|
||||||
|
{
|
||||||
|
node = peek(keylet::page(directory, page));
|
||||||
|
if (!node)
|
||||||
|
LogicError("Directory chain: root back-pointer broken.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto indexes = node->getFieldV256(sfIndexes);
|
||||||
|
|
||||||
// If there's space, we use it:
|
// If there's space, we use it:
|
||||||
if (indexes.size() < dirNodeMaxEntries)
|
if (indexes.size() < dirNodeMaxEntries)
|
||||||
{
|
{
|
||||||
return directory::insertKey(
|
if (preserveOrder)
|
||||||
*this, node, page, preserveOrder, indexes, key);
|
{
|
||||||
|
if (std::find(indexes.begin(), indexes.end(), key) != indexes.end())
|
||||||
|
LogicError("dirInsert: double insertion");
|
||||||
|
|
||||||
|
indexes.push_back(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We can't be sure if this page is already sorted because
|
||||||
|
// it may be a legacy page we haven't yet touched. Take
|
||||||
|
// the time to sort it.
|
||||||
|
std::sort(indexes.begin(), indexes.end());
|
||||||
|
|
||||||
|
auto pos = std::lower_bound(indexes.begin(), indexes.end(), key);
|
||||||
|
|
||||||
|
if (pos != indexes.end() && key == *pos)
|
||||||
|
LogicError("dirInsert: double insertion");
|
||||||
|
|
||||||
|
indexes.insert(pos, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
node->setFieldV256(sfIndexes, indexes);
|
||||||
|
update(node);
|
||||||
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
return directory::insertPage(
|
// We rely on modulo arithmetic of unsigned integers (guaranteed in
|
||||||
*this, page, node, 0, root, key, directory, describe);
|
// [basic.fundamental] paragraph 2) to detect page representation overflow.
|
||||||
|
// For signed integers this would be UB, hence static_assert here.
|
||||||
|
static_assert(std::is_unsigned_v<decltype(page)>);
|
||||||
|
// Defensive check against breaking changes in compiler.
|
||||||
|
static_assert([]<typename T>(std::type_identity<T>) constexpr -> T {
|
||||||
|
T tmp = std::numeric_limits<T>::max();
|
||||||
|
return ++tmp;
|
||||||
|
}(std::type_identity<decltype(page)>{}) == 0);
|
||||||
|
++page;
|
||||||
|
// Check whether we're out of pages.
|
||||||
|
if (page == 0)
|
||||||
|
return std::nullopt;
|
||||||
|
if (!rules().enabled(fixDirectoryLimit) &&
|
||||||
|
page >= dirNodeMaxPages) // Old pages limit
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
// We are about to create a new node; we'll link it to
|
||||||
|
// the chain first:
|
||||||
|
node->setFieldU64(sfIndexNext, page);
|
||||||
|
update(node);
|
||||||
|
|
||||||
|
root->setFieldU64(sfIndexPrevious, page);
|
||||||
|
update(root);
|
||||||
|
|
||||||
|
// Insert the new key:
|
||||||
|
indexes.clear();
|
||||||
|
indexes.push_back(key);
|
||||||
|
|
||||||
|
node = std::make_shared<SLE>(keylet::page(directory, page));
|
||||||
|
node->setFieldH256(sfRootIndex, directory.key);
|
||||||
|
node->setFieldV256(sfIndexes, indexes);
|
||||||
|
|
||||||
|
// Save some space by not specifying the value 0 since
|
||||||
|
// it's the default.
|
||||||
|
if (page != 1)
|
||||||
|
node->setFieldU64(sfIndexPrevious, page - 1);
|
||||||
|
describe(node);
|
||||||
|
insert(node);
|
||||||
|
|
||||||
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -383,99 +383,6 @@ isLPTokenFrozen(
|
|||||||
isFrozen(view, account, asset2.currency, asset2.account);
|
isFrozen(view, account, asset2.currency, asset2.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SLE::const_pointer
|
|
||||||
getLineIfUsable(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
auto const sle = view.read(keylet::line(account, issuer, currency));
|
|
||||||
|
|
||||||
if (!sle)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zeroIfFrozen == fhZERO_IF_FROZEN)
|
|
||||||
{
|
|
||||||
if (isFrozen(view, account, currency, issuer) ||
|
|
||||||
isDeepFrozen(view, account, currency, issuer))
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when fixFrozenLPTokenTransfer is enabled, if currency is lptoken,
|
|
||||||
// we need to check if the associated assets have been frozen
|
|
||||||
if (view.rules().enabled(fixFrozenLPTokenTransfer))
|
|
||||||
{
|
|
||||||
auto const sleIssuer = view.read(keylet::account(issuer));
|
|
||||||
if (!sleIssuer)
|
|
||||||
{
|
|
||||||
return nullptr; // LCOV_EXCL_LINE
|
|
||||||
}
|
|
||||||
else if (sleIssuer->isFieldPresent(sfAMMID))
|
|
||||||
{
|
|
||||||
auto const sleAmm =
|
|
||||||
view.read(keylet::amm((*sleIssuer)[sfAMMID]));
|
|
||||||
|
|
||||||
if (!sleAmm ||
|
|
||||||
isLPTokenFrozen(
|
|
||||||
view,
|
|
||||||
account,
|
|
||||||
(*sleAmm)[sfAsset].get<Issue>(),
|
|
||||||
(*sleAmm)[sfAsset2].get<Issue>()))
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static STAmount
|
|
||||||
getTrustLineBalance(
|
|
||||||
ReadView const& view,
|
|
||||||
SLE::const_ref sle,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer,
|
|
||||||
bool includeOppositeLimit,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
STAmount amount;
|
|
||||||
if (sle)
|
|
||||||
{
|
|
||||||
amount = sle->getFieldAmount(sfBalance);
|
|
||||||
bool const accountHigh = account > issuer;
|
|
||||||
auto const& oppositeField = accountHigh ? sfLowLimit : sfHighLimit;
|
|
||||||
if (accountHigh)
|
|
||||||
{
|
|
||||||
// Put balance in account terms.
|
|
||||||
amount.negate();
|
|
||||||
}
|
|
||||||
if (includeOppositeLimit)
|
|
||||||
{
|
|
||||||
amount += sle->getFieldAmount(oppositeField);
|
|
||||||
}
|
|
||||||
amount.setIssuer(issuer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
amount.clear(Issue{currency, issuer});
|
|
||||||
}
|
|
||||||
|
|
||||||
JLOG(j.trace()) << "getTrustLineBalance:"
|
|
||||||
<< " account=" << to_string(account)
|
|
||||||
<< " amount=" << amount.getFullText();
|
|
||||||
|
|
||||||
return view.balanceHook(account, issuer, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
accountHolds(
|
accountHolds(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
@@ -492,10 +399,71 @@ accountHolds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IOU: Return balance on trust line modulo freeze
|
// IOU: Return balance on trust line modulo freeze
|
||||||
SLE::const_pointer const sle =
|
auto const sle = view.read(keylet::line(account, issuer, currency));
|
||||||
getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j);
|
auto const allowBalance = [&]() {
|
||||||
|
if (!sle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return getTrustLineBalance(view, sle, account, currency, issuer, false, j);
|
if (zeroIfFrozen == fhZERO_IF_FROZEN)
|
||||||
|
{
|
||||||
|
if (isFrozen(view, account, currency, issuer) ||
|
||||||
|
isDeepFrozen(view, account, currency, issuer))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// when fixFrozenLPTokenTransfer is enabled, if currency is lptoken,
|
||||||
|
// we need to check if the associated assets have been frozen
|
||||||
|
if (view.rules().enabled(fixFrozenLPTokenTransfer))
|
||||||
|
{
|
||||||
|
auto const sleIssuer = view.read(keylet::account(issuer));
|
||||||
|
if (!sleIssuer)
|
||||||
|
{
|
||||||
|
return false; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
else if (sleIssuer->isFieldPresent(sfAMMID))
|
||||||
|
{
|
||||||
|
auto const sleAmm =
|
||||||
|
view.read(keylet::amm((*sleIssuer)[sfAMMID]));
|
||||||
|
|
||||||
|
if (!sleAmm ||
|
||||||
|
isLPTokenFrozen(
|
||||||
|
view,
|
||||||
|
account,
|
||||||
|
(*sleAmm)[sfAsset].get<Issue>(),
|
||||||
|
(*sleAmm)[sfAsset2].get<Issue>()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (allowBalance)
|
||||||
|
{
|
||||||
|
amount = sle->getFieldAmount(sfBalance);
|
||||||
|
if (account > issuer)
|
||||||
|
{
|
||||||
|
// Put balance in account terms.
|
||||||
|
amount.negate();
|
||||||
|
}
|
||||||
|
amount.setIssuer(issuer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
amount.clear(Issue{currency, issuer});
|
||||||
|
}
|
||||||
|
|
||||||
|
JLOG(j.trace()) << "accountHolds:"
|
||||||
|
<< " account=" << to_string(account)
|
||||||
|
<< " amount=" << amount.getFullText();
|
||||||
|
|
||||||
|
return view.balanceHook(account, issuer, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
@@ -582,96 +550,6 @@ accountHolds(
|
|||||||
asset.value());
|
asset.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Currency const& currency,
|
|
||||||
AccountID const& issuer,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
if (isXRP(currency))
|
|
||||||
return accountHolds(view, account, currency, issuer, zeroIfFrozen, j);
|
|
||||||
|
|
||||||
if (account == issuer)
|
|
||||||
// If the account is the issuer, then their limit is effectively
|
|
||||||
// infinite
|
|
||||||
return STAmount{
|
|
||||||
Issue{currency, issuer}, STAmount::cMaxValue, STAmount::cMaxOffset};
|
|
||||||
|
|
||||||
// IOU: Return balance on trust line modulo freeze
|
|
||||||
SLE::const_pointer const sle =
|
|
||||||
getLineIfUsable(view, account, currency, issuer, zeroIfFrozen, j);
|
|
||||||
|
|
||||||
return getTrustLineBalance(view, sle, account, currency, issuer, true, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Issue const& issue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
return accountCanSend(
|
|
||||||
view, account, issue.currency, issue.account, zeroIfFrozen, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
MPTIssue const& mptIssue,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
if (account == mptIssue.getIssuer())
|
|
||||||
{
|
|
||||||
// if the account is the issuer, and the issuance exists, their limit is
|
|
||||||
// the issuance limit minus the outstanding value
|
|
||||||
auto const issuance =
|
|
||||||
view.read(keylet::mptIssuance(mptIssue.getMptID()));
|
|
||||||
|
|
||||||
if (!issuance)
|
|
||||||
{
|
|
||||||
return STAmount{mptIssue};
|
|
||||||
}
|
|
||||||
return STAmount{
|
|
||||||
mptIssue,
|
|
||||||
issuance->at(~sfMaximumAmount).value_or(maxMPTokenAmount) -
|
|
||||||
issuance->at(sfOutstandingAmount)};
|
|
||||||
}
|
|
||||||
|
|
||||||
return accountHolds(
|
|
||||||
view, account, mptIssue, zeroIfFrozen, zeroIfUnauthorized, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] STAmount
|
|
||||||
accountCanSend(
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& account,
|
|
||||||
Asset const& asset,
|
|
||||||
FreezeHandling zeroIfFrozen,
|
|
||||||
AuthHandling zeroIfUnauthorized,
|
|
||||||
beast::Journal j)
|
|
||||||
{
|
|
||||||
return std::visit(
|
|
||||||
[&](auto const& value) {
|
|
||||||
if constexpr (std::is_same_v<
|
|
||||||
std::remove_cvref_t<decltype(value)>,
|
|
||||||
Issue>)
|
|
||||||
{
|
|
||||||
return accountCanSend(view, account, value, zeroIfFrozen, j);
|
|
||||||
}
|
|
||||||
return accountCanSend(
|
|
||||||
view, account, value, zeroIfFrozen, zeroIfUnauthorized, j);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
accountFunds(
|
accountFunds(
|
||||||
ReadView const& view,
|
ReadView const& view,
|
||||||
@@ -1177,17 +1055,13 @@ describeOwnerDir(AccountID const& account)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
dirLink(
|
dirLink(ApplyView& view, AccountID const& owner, std::shared_ptr<SLE>& object)
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& owner,
|
|
||||||
std::shared_ptr<SLE>& object,
|
|
||||||
SF_UINT64 const& node)
|
|
||||||
{
|
{
|
||||||
auto const page = view.dirInsert(
|
auto const page = view.dirInsert(
|
||||||
keylet::ownerDir(owner), object->key(), describeOwnerDir(owner));
|
keylet::ownerDir(owner), object->key(), describeOwnerDir(owner));
|
||||||
if (!page)
|
if (!page)
|
||||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||||
object->setFieldU64(node, *page);
|
object->setFieldU64(sfOwnerNode, *page);
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1260,8 +1134,7 @@ createPseudoAccount(
|
|||||||
uint256 const& pseudoOwnerKey,
|
uint256 const& pseudoOwnerKey,
|
||||||
SField const& ownerField)
|
SField const& ownerField)
|
||||||
{
|
{
|
||||||
[[maybe_unused]]
|
[[maybe_unused]] auto const& fields = getPseudoAccountFields();
|
||||||
auto const& fields = getPseudoAccountFields();
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
std::count_if(
|
std::count_if(
|
||||||
fields.begin(),
|
fields.begin(),
|
||||||
@@ -1283,10 +1156,9 @@ createPseudoAccount(
|
|||||||
// Pseudo-accounts can't submit transactions, so set the sequence number
|
// Pseudo-accounts can't submit transactions, so set the sequence number
|
||||||
// to 0 to make them easier to spot and verify, and add an extra level
|
// to 0 to make them easier to spot and verify, and add an extra level
|
||||||
// of protection.
|
// of protection.
|
||||||
std::uint32_t const seqno = //
|
std::uint32_t const seqno = //
|
||||||
view.rules().enabled(featureSingleAssetVault) || //
|
view.rules().enabled(featureSingleAssetVault) //
|
||||||
view.rules().enabled(featureLendingProtocol) //
|
? 0 //
|
||||||
? 0 //
|
|
||||||
: view.seq();
|
: view.seq();
|
||||||
account->setFieldU32(sfSequence, seqno);
|
account->setFieldU32(sfSequence, seqno);
|
||||||
// Ignore reserves requirement, disable the master key, allow default
|
// Ignore reserves requirement, disable the master key, allow default
|
||||||
@@ -1340,64 +1212,6 @@ canAddHolding(ReadView const& view, Asset const& asset)
|
|||||||
asset.value());
|
asset.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
|
|
||||||
{
|
|
||||||
if (toSle == nullptr)
|
|
||||||
return tecNO_DST;
|
|
||||||
|
|
||||||
// The tag is basically account-specific information we don't
|
|
||||||
// understand, but we can require someone to fill it in.
|
|
||||||
if (toSle->isFlag(lsfRequireDestTag) && !hasDestinationTag)
|
|
||||||
return tecDST_TAG_NEEDED; // Cannot send without a tag
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(
|
|
||||||
AccountID const& from,
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& to,
|
|
||||||
SLE::const_ref toSle,
|
|
||||||
bool hasDestinationTag)
|
|
||||||
{
|
|
||||||
if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (from == to)
|
|
||||||
return tesSUCCESS;
|
|
||||||
|
|
||||||
if (toSle->isFlag(lsfDepositAuth))
|
|
||||||
{
|
|
||||||
if (!view.exists(keylet::depositPreauth(to, from)))
|
|
||||||
return tecNO_PERMISSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(
|
|
||||||
AccountID const& from,
|
|
||||||
ReadView const& view,
|
|
||||||
AccountID const& to,
|
|
||||||
bool hasDestinationTag)
|
|
||||||
{
|
|
||||||
auto const toSle = view.read(keylet::account(to));
|
|
||||||
|
|
||||||
return canWithdraw(from, view, to, toSle, hasDestinationTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
|
||||||
canWithdraw(ReadView const& view, STTx const& tx)
|
|
||||||
{
|
|
||||||
auto const from = tx[sfAccount];
|
|
||||||
auto const to = tx[~sfDestination].value_or(from);
|
|
||||||
|
|
||||||
return canWithdraw(from, view, to, tx.isFieldPresent(sfDestinationTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] TER
|
[[nodiscard]] TER
|
||||||
addEmptyHolding(
|
addEmptyHolding(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -1406,8 +1220,8 @@ addEmptyHolding(
|
|||||||
Issue const& issue,
|
Issue const& issue,
|
||||||
beast::Journal journal)
|
beast::Journal journal)
|
||||||
{
|
{
|
||||||
// Every account can hold XRP. An issuer can issue directly.
|
// Every account can hold XRP.
|
||||||
if (issue.native() || accountID == issue.getIssuer())
|
if (issue.native())
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
|
|
||||||
auto const& issuerId = issue.getIssuer();
|
auto const& issuerId = issue.getIssuer();
|
||||||
@@ -1468,8 +1282,6 @@ addEmptyHolding(
|
|||||||
return tefINTERNAL; // LCOV_EXCL_LINE
|
return tefINTERNAL; // LCOV_EXCL_LINE
|
||||||
if (view.peek(keylet::mptoken(mptID, accountID)))
|
if (view.peek(keylet::mptoken(mptID, accountID)))
|
||||||
return tecDUPLICATE;
|
return tecDUPLICATE;
|
||||||
if (accountID == mptIssue.getIssuer())
|
|
||||||
return tesSUCCESS;
|
|
||||||
|
|
||||||
return authorizeMPToken(view, priorBalance, mptID, accountID, journal);
|
return authorizeMPToken(view, priorBalance, mptID, accountID, journal);
|
||||||
}
|
}
|
||||||
@@ -1533,18 +1345,6 @@ authorizeMPToken(
|
|||||||
if (priorBalance < reserveCreate)
|
if (priorBalance < reserveCreate)
|
||||||
return tecINSUFFICIENT_RESERVE;
|
return tecINSUFFICIENT_RESERVE;
|
||||||
|
|
||||||
// Defensive check before we attempt to create MPToken for the issuer
|
|
||||||
auto const mpt = view.read(keylet::mptIssuance(mptIssuanceID));
|
|
||||||
if (!mpt || mpt->getAccountID(sfIssuer) == account)
|
|
||||||
{
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
UNREACHABLE(
|
|
||||||
"ripple::authorizeMPToken : invalid issuance or issuers token");
|
|
||||||
if (view.rules().enabled(featureLendingProtocol))
|
|
||||||
return tecINTERNAL;
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
auto const mptokenKey = keylet::mptoken(mptIssuanceID, account);
|
||||||
auto mptoken = std::make_shared<SLE>(mptokenKey);
|
auto mptoken = std::make_shared<SLE>(mptokenKey);
|
||||||
if (auto ter = dirLink(view, account, mptoken))
|
if (auto ter = dirLink(view, account, mptoken))
|
||||||
@@ -1620,14 +1420,6 @@ trustCreate(
|
|||||||
|
|
||||||
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
auto const& uLowAccountID = !bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||||
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
auto const& uHighAccountID = bSrcHigh ? uSrcAccountID : uDstAccountID;
|
||||||
if (uLowAccountID == uHighAccountID)
|
|
||||||
{
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
UNREACHABLE("ripple::trustCreate : trust line to self");
|
|
||||||
if (view.rules().enabled(featureLendingProtocol))
|
|
||||||
return tecINTERNAL;
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const sleRippleState = std::make_shared<SLE>(ltRIPPLE_STATE, uIndex);
|
auto const sleRippleState = std::make_shared<SLE>(ltRIPPLE_STATE, uIndex);
|
||||||
view.insert(sleRippleState);
|
view.insert(sleRippleState);
|
||||||
@@ -2118,87 +1910,6 @@ rippleSendIOU(
|
|||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send regardless of limits.
|
|
||||||
// --> receivers: Amount/currency/issuer to deliver to receivers.
|
|
||||||
// <-- saActual: Amount actually cost to sender. Sender pays fees.
|
|
||||||
static TER
|
|
||||||
rippleSendMultiIOU(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
STAmount& actual,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee)
|
|
||||||
{
|
|
||||||
auto const issuer = asset.getIssuer();
|
|
||||||
|
|
||||||
XRPL_ASSERT(
|
|
||||||
!isXRP(senderID), "ripple::rippleSendMultiIOU : sender is not XRP");
|
|
||||||
|
|
||||||
// These may diverge
|
|
||||||
STAmount takeFromSender{asset};
|
|
||||||
actual = takeFromSender;
|
|
||||||
|
|
||||||
// Failures return immediately.
|
|
||||||
for (auto const& r : receivers)
|
|
||||||
{
|
|
||||||
auto const& receiverID = r.first;
|
|
||||||
STAmount amount{asset, r.second};
|
|
||||||
|
|
||||||
/* If we aren't sending anything or if the sender is the same as the
|
|
||||||
* receiver then we don't need to do anything.
|
|
||||||
*/
|
|
||||||
if (!amount || (senderID == receiverID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
XRPL_ASSERT(
|
|
||||||
!isXRP(receiverID),
|
|
||||||
"ripple::rippleSendMultiIOU : receiver is not XRP");
|
|
||||||
|
|
||||||
if (senderID == issuer || receiverID == issuer || issuer == noAccount())
|
|
||||||
{
|
|
||||||
// Direct send: redeeming IOUs and/or sending own IOUs.
|
|
||||||
if (auto const ter = rippleCreditIOU(
|
|
||||||
view, senderID, receiverID, amount, false, j))
|
|
||||||
return ter;
|
|
||||||
actual += amount;
|
|
||||||
// Do not add amount to takeFromSender, because rippleCreditIOU took
|
|
||||||
// it.
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending 3rd party IOUs: transit.
|
|
||||||
|
|
||||||
// Calculate the amount to transfer accounting
|
|
||||||
// for any transfer fees if the fee is not waived:
|
|
||||||
STAmount actualSend = (waiveFee == WaiveTransferFee::Yes)
|
|
||||||
? amount
|
|
||||||
: multiply(amount, transferRate(view, issuer));
|
|
||||||
actual += actualSend;
|
|
||||||
takeFromSender += actualSend;
|
|
||||||
|
|
||||||
JLOG(j.debug()) << "rippleSendMultiIOU> " << to_string(senderID)
|
|
||||||
<< " - > " << to_string(receiverID)
|
|
||||||
<< " : deliver=" << amount.getFullText()
|
|
||||||
<< " cost=" << actual.getFullText();
|
|
||||||
|
|
||||||
if (TER const terResult =
|
|
||||||
rippleCreditIOU(view, issuer, receiverID, amount, true, j))
|
|
||||||
return terResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (senderID != issuer && takeFromSender)
|
|
||||||
{
|
|
||||||
if (TER const terResult = rippleCreditIOU(
|
|
||||||
view, senderID, issuer, takeFromSender, true, j))
|
|
||||||
return terResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TER
|
static TER
|
||||||
accountSendIOU(
|
accountSendIOU(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -2323,165 +2034,6 @@ accountSendIOU(
|
|||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TER
|
|
||||||
accountSendMultiIOU(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee)
|
|
||||||
{
|
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
receivers.size() > 1,
|
|
||||||
"ripple::accountSendMultiIOU",
|
|
||||||
"multiple recipients provided");
|
|
||||||
|
|
||||||
if (view.rules().enabled(fixAMMv1_1))
|
|
||||||
{
|
|
||||||
if (asset.holds<MPTIssue>())
|
|
||||||
{
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XRPL_ASSERT(
|
|
||||||
!asset.holds<MPTIssue>(), "ripple::accountSendMultiIOU : not MPT");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!asset.native())
|
|
||||||
{
|
|
||||||
STAmount actual;
|
|
||||||
JLOG(j.trace()) << "accountSendMultiIOU: " << to_string(senderID)
|
|
||||||
<< " sending " << receivers.size() << " IOUs";
|
|
||||||
|
|
||||||
return rippleSendMultiIOU(
|
|
||||||
view, senderID, asset, receivers, actual, j, waiveFee);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XRP send which does not check reserve and can do pure adjustment.
|
|
||||||
* Note that sender or receiver may be null and this not a mistake; this
|
|
||||||
* setup could be used during pathfinding and it is carefully controlled to
|
|
||||||
* ensure that transfers are balanced.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SLE::pointer sender = senderID != beast::zero
|
|
||||||
? view.peek(keylet::account(senderID))
|
|
||||||
: SLE::pointer();
|
|
||||||
|
|
||||||
if (auto stream = j.trace())
|
|
||||||
{
|
|
||||||
std::string sender_bal("-");
|
|
||||||
|
|
||||||
if (sender)
|
|
||||||
sender_bal = sender->getFieldAmount(sfBalance).getFullText();
|
|
||||||
|
|
||||||
stream << "accountSendMultiIOU> " << to_string(senderID) << " ("
|
|
||||||
<< sender_bal << ") -> " << receivers.size() << " receivers.";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failures return immediately.
|
|
||||||
STAmount takeFromSender{asset};
|
|
||||||
for (auto const& r : receivers)
|
|
||||||
{
|
|
||||||
auto const& receiverID = r.first;
|
|
||||||
STAmount amount{asset, r.second};
|
|
||||||
|
|
||||||
takeFromSender += amount;
|
|
||||||
|
|
||||||
if (view.rules().enabled(fixAMMv1_1))
|
|
||||||
{
|
|
||||||
if (amount < beast::zero)
|
|
||||||
{
|
|
||||||
return tecINTERNAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XRPL_ASSERT(
|
|
||||||
amount >= beast::zero,
|
|
||||||
"ripple::accountSendMultiIOU : minimum amount");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we aren't sending anything or if the sender is the same as the
|
|
||||||
* receiver then we don't need to do anything.
|
|
||||||
*/
|
|
||||||
if (!amount || (senderID == receiverID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SLE::pointer receiver = receiverID != beast::zero
|
|
||||||
? view.peek(keylet::account(receiverID))
|
|
||||||
: SLE::pointer();
|
|
||||||
|
|
||||||
if (auto stream = j.trace())
|
|
||||||
{
|
|
||||||
std::string receiver_bal("-");
|
|
||||||
|
|
||||||
if (receiver)
|
|
||||||
receiver_bal =
|
|
||||||
receiver->getFieldAmount(sfBalance).getFullText();
|
|
||||||
|
|
||||||
stream << "accountSendMultiIOU> " << to_string(senderID) << " -> "
|
|
||||||
<< to_string(receiverID) << " (" << receiver_bal
|
|
||||||
<< ") : " << amount.getFullText();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (receiver)
|
|
||||||
{
|
|
||||||
// Increment XRP balance.
|
|
||||||
auto const rcvBal = receiver->getFieldAmount(sfBalance);
|
|
||||||
receiver->setFieldAmount(sfBalance, rcvBal + amount);
|
|
||||||
view.creditHook(xrpAccount(), receiverID, amount, -rcvBal);
|
|
||||||
|
|
||||||
view.update(receiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto stream = j.trace())
|
|
||||||
{
|
|
||||||
std::string receiver_bal("-");
|
|
||||||
|
|
||||||
if (receiver)
|
|
||||||
receiver_bal =
|
|
||||||
receiver->getFieldAmount(sfBalance).getFullText();
|
|
||||||
|
|
||||||
stream << "accountSendMultiIOU< " << to_string(senderID) << " -> "
|
|
||||||
<< to_string(receiverID) << " (" << receiver_bal
|
|
||||||
<< ") : " << amount.getFullText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sender)
|
|
||||||
{
|
|
||||||
if (sender->getFieldAmount(sfBalance) < takeFromSender)
|
|
||||||
{
|
|
||||||
return TER{tecFAILED_PROCESSING};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto const sndBal = sender->getFieldAmount(sfBalance);
|
|
||||||
view.creditHook(senderID, xrpAccount(), takeFromSender, sndBal);
|
|
||||||
|
|
||||||
// Decrement XRP balance.
|
|
||||||
sender->setFieldAmount(sfBalance, sndBal - takeFromSender);
|
|
||||||
view.update(sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto stream = j.trace())
|
|
||||||
{
|
|
||||||
std::string sender_bal("-");
|
|
||||||
std::string receiver_bal("-");
|
|
||||||
|
|
||||||
if (sender)
|
|
||||||
sender_bal = sender->getFieldAmount(sfBalance).getFullText();
|
|
||||||
|
|
||||||
stream << "accountSendMultiIOU< " << to_string(senderID) << " ("
|
|
||||||
<< sender_bal << ") -> " << receivers.size() << " receivers.";
|
|
||||||
}
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TER
|
static TER
|
||||||
rippleCreditMPT(
|
rippleCreditMPT(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -2610,102 +2162,6 @@ rippleSendMPT(
|
|||||||
return rippleCreditMPT(view, uSenderID, issuer, saActual, j);
|
return rippleCreditMPT(view, uSenderID, issuer, saActual, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TER
|
|
||||||
rippleSendMultiMPT(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
STAmount& actual,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee)
|
|
||||||
{
|
|
||||||
// Safe to get MPT since rippleSendMultiMPT is only called by
|
|
||||||
// accountSendMultiMPT
|
|
||||||
auto const issuer = asset.getIssuer();
|
|
||||||
|
|
||||||
auto const sle =
|
|
||||||
view.read(keylet::mptIssuance(asset.get<MPTIssue>().getMptID()));
|
|
||||||
if (!sle)
|
|
||||||
return tecOBJECT_NOT_FOUND;
|
|
||||||
|
|
||||||
// These may diverge
|
|
||||||
STAmount takeFromSender{asset};
|
|
||||||
actual = takeFromSender;
|
|
||||||
|
|
||||||
for (auto const& r : receivers)
|
|
||||||
{
|
|
||||||
auto const& receiverID = r.first;
|
|
||||||
STAmount amount{asset, r.second};
|
|
||||||
|
|
||||||
XRPL_ASSERT(
|
|
||||||
senderID != receiverID,
|
|
||||||
"ripple::rippleSendMultiMPT : sender is not receiver");
|
|
||||||
|
|
||||||
XRPL_ASSERT(
|
|
||||||
amount >= beast::zero,
|
|
||||||
"ripple::rippleSendMultiMPT : minimum amount ");
|
|
||||||
|
|
||||||
/* If we aren't sending anything or if the sender is the same as the
|
|
||||||
* receiver then we don't need to do anything.
|
|
||||||
*/
|
|
||||||
if (!amount || (senderID == receiverID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (senderID == issuer || receiverID == issuer)
|
|
||||||
{
|
|
||||||
// if sender is issuer, check that the new OutstandingAmount will
|
|
||||||
// not exceed MaximumAmount
|
|
||||||
if (senderID == issuer)
|
|
||||||
{
|
|
||||||
auto const sendAmount = amount.mpt().value();
|
|
||||||
auto const maximumAmount =
|
|
||||||
sle->at(~sfMaximumAmount).value_or(maxMPTokenAmount);
|
|
||||||
if (sendAmount > maximumAmount - takeFromSender ||
|
|
||||||
sle->getFieldU64(sfOutstandingAmount) >
|
|
||||||
maximumAmount - sendAmount - takeFromSender)
|
|
||||||
return tecPATH_DRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Direct send: redeeming MPTs and/or sending own MPTs.
|
|
||||||
if (auto const ter =
|
|
||||||
rippleCreditMPT(view, senderID, receiverID, amount, j))
|
|
||||||
return ter;
|
|
||||||
actual += amount;
|
|
||||||
// Do not add amount to takeFromSender, because rippleCreditMPT took
|
|
||||||
// it
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending 3rd party MPTs: transit.
|
|
||||||
STAmount actualSend = (waiveFee == WaiveTransferFee::Yes)
|
|
||||||
? amount
|
|
||||||
: multiply(
|
|
||||||
amount,
|
|
||||||
transferRate(view, amount.get<MPTIssue>().getMptID()));
|
|
||||||
actual += actualSend;
|
|
||||||
takeFromSender += actualSend;
|
|
||||||
|
|
||||||
JLOG(j.debug()) << "rippleSendMultiMPT> " << to_string(senderID)
|
|
||||||
<< " - > " << to_string(receiverID)
|
|
||||||
<< " : deliver=" << amount.getFullText()
|
|
||||||
<< " cost=" << actualSend.getFullText();
|
|
||||||
|
|
||||||
if (auto const terResult =
|
|
||||||
rippleCreditMPT(view, issuer, receiverID, amount, j))
|
|
||||||
return terResult;
|
|
||||||
}
|
|
||||||
if (senderID != issuer && takeFromSender)
|
|
||||||
{
|
|
||||||
if (TER const terResult =
|
|
||||||
rippleCreditMPT(view, senderID, issuer, takeFromSender, j))
|
|
||||||
return terResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tesSUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TER
|
static TER
|
||||||
accountSendMPT(
|
accountSendMPT(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -2731,23 +2187,6 @@ accountSendMPT(
|
|||||||
view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee);
|
view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TER
|
|
||||||
accountSendMultiMPT(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee)
|
|
||||||
{
|
|
||||||
XRPL_ASSERT(asset.holds<MPTIssue>(), "ripple::accountSendMultiMPT : MPT");
|
|
||||||
|
|
||||||
STAmount actual;
|
|
||||||
|
|
||||||
return rippleSendMultiMPT(
|
|
||||||
view, senderID, asset, receivers, actual, j, waiveFee);
|
|
||||||
}
|
|
||||||
|
|
||||||
TER
|
TER
|
||||||
accountSend(
|
accountSend(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
@@ -2769,31 +2208,6 @@ accountSend(
|
|||||||
saAmount.asset().value());
|
saAmount.asset().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
|
||||||
accountSendMulti(
|
|
||||||
ApplyView& view,
|
|
||||||
AccountID const& senderID,
|
|
||||||
Asset const& asset,
|
|
||||||
MultiplePaymentDestinations const& receivers,
|
|
||||||
beast::Journal j,
|
|
||||||
WaiveTransferFee waiveFee)
|
|
||||||
{
|
|
||||||
XRPL_ASSERT_PARTS(
|
|
||||||
receivers.size() > 1,
|
|
||||||
"ripple::accountSendMulti",
|
|
||||||
"multiple recipients provided");
|
|
||||||
return std::visit(
|
|
||||||
[&]<ValidIssueType TIss>(TIss const& issue) {
|
|
||||||
if constexpr (std::is_same_v<TIss, Issue>)
|
|
||||||
return accountSendMultiIOU(
|
|
||||||
view, senderID, asset, receivers, j, waiveFee);
|
|
||||||
else
|
|
||||||
return accountSendMultiMPT(
|
|
||||||
view, senderID, asset, receivers, j, waiveFee);
|
|
||||||
},
|
|
||||||
asset.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
updateTrustLine(
|
updateTrustLine(
|
||||||
ApplyView& view,
|
ApplyView& view,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/detail/BatchWriter.h>
|
#include <xrpl/nodestore/detail/BatchWriter.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -17,11 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/Database.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/chrono.h>
|
#include <xrpl/basics/chrono.h>
|
||||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||||
#include <xrpl/json/json_value.h>
|
#include <xrpl/json/json_value.h>
|
||||||
|
#include <xrpl/nodestore/Database.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/jss.h>
|
#include <xrpl/protocol/jss.h>
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/detail/DatabaseNodeImp.h>
|
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/detail/DatabaseRotatingImp.h>
|
#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/detail/DecodedBlob.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/safe_cast.h>
|
#include <xrpl/basics/safe_cast.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/nodestore/detail/DecodedBlob.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/DummyScheduler.h>
|
#include <xrpl/nodestore/DummyScheduler.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/detail/DatabaseNodeImp.h>
|
#include <xrpl/nodestore/detail/DatabaseNodeImp.h>
|
||||||
#include <xrpld/nodestore/detail/ManagerImp.h>
|
#include <xrpl/nodestore/detail/ManagerImp.h>
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
@@ -41,6 +41,27 @@ ManagerImp::missing_backend()
|
|||||||
"please see the rippled-example.cfg file!");
|
"please see the rippled-example.cfg file!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We shouldn't rely on global variables for lifetime management because their
|
||||||
|
// lifetime is not well-defined. ManagerImp may get destroyed before the Factory
|
||||||
|
// classes, and then, calling Manager::instance().erase() in the destructors of
|
||||||
|
// the Factory classes is an undefined behaviour.
|
||||||
|
void
|
||||||
|
registerNuDBFactory(Manager& manager);
|
||||||
|
void
|
||||||
|
registerRocksDBFactory(Manager& manager);
|
||||||
|
void
|
||||||
|
registerNullFactory(Manager& manager);
|
||||||
|
void
|
||||||
|
registerMemoryFactory(Manager& manager);
|
||||||
|
|
||||||
|
ManagerImp::ManagerImp()
|
||||||
|
{
|
||||||
|
registerNuDBFactory(*this);
|
||||||
|
registerRocksDBFactory(*this);
|
||||||
|
registerNullFactory(*this);
|
||||||
|
registerMemoryFactory(*this);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Backend>
|
std::unique_ptr<Backend>
|
||||||
ManagerImp::make_Backend(
|
ManagerImp::make_Backend(
|
||||||
Section const& parameters,
|
Section const& parameters,
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/NodeObject.h>
|
#include <xrpl/nodestore/NodeObject.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/Factory.h>
|
|
||||||
#include <xrpld/nodestore/Manager.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
|
#include <xrpl/nodestore/Factory.h>
|
||||||
|
#include <xrpl/nodestore/Manager.h>
|
||||||
|
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/core/ignore_unused.hpp>
|
#include <boost/core/ignore_unused.hpp>
|
||||||
@@ -46,10 +45,10 @@ class MemoryFactory : public Factory
|
|||||||
private:
|
private:
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::map<std::string, MemoryDB, boost::beast::iless> map_;
|
std::map<std::string, MemoryDB, boost::beast::iless> map_;
|
||||||
|
Manager& manager_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemoryFactory();
|
explicit MemoryFactory(Manager& manager);
|
||||||
~MemoryFactory() override;
|
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
getName() const override;
|
getName() const override;
|
||||||
@@ -75,7 +74,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static MemoryFactory memoryFactory;
|
MemoryFactory* memoryFactory = nullptr;
|
||||||
|
|
||||||
|
void
|
||||||
|
registerMemoryFactory(Manager& manager)
|
||||||
|
{
|
||||||
|
static MemoryFactory instance{manager};
|
||||||
|
memoryFactory = &instance;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -112,9 +118,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
open(bool createIfMissing) override
|
open(bool) override
|
||||||
{
|
{
|
||||||
db_ = &memoryFactory.open(name_);
|
db_ = &memoryFactory->open(name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -219,14 +225,9 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
MemoryFactory::MemoryFactory()
|
MemoryFactory::MemoryFactory(Manager& manager) : manager_(manager)
|
||||||
{
|
{
|
||||||
Manager::instance().insert(*this);
|
manager_.insert(*this);
|
||||||
}
|
|
||||||
|
|
||||||
MemoryFactory::~MemoryFactory()
|
|
||||||
{
|
|
||||||
Manager::instance().erase(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -17,15 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/Factory.h>
|
|
||||||
#include <xrpld/nodestore/Manager.h>
|
|
||||||
#include <xrpld/nodestore/detail/DecodedBlob.h>
|
|
||||||
#include <xrpld/nodestore/detail/EncodedBlob.h>
|
|
||||||
#include <xrpld/nodestore/detail/codec.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/beast/core/LexicalCast.h>
|
#include <xrpl/beast/core/LexicalCast.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
|
#include <xrpl/nodestore/Factory.h>
|
||||||
|
#include <xrpl/nodestore/Manager.h>
|
||||||
|
#include <xrpl/nodestore/detail/DecodedBlob.h>
|
||||||
|
#include <xrpl/nodestore/detail/EncodedBlob.h>
|
||||||
|
#include <xrpl/nodestore/detail/codec.h>
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
@@ -427,15 +426,13 @@ private:
|
|||||||
|
|
||||||
class NuDBFactory : public Factory
|
class NuDBFactory : public Factory
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
NuDBFactory()
|
Manager& manager_;
|
||||||
{
|
|
||||||
Manager::instance().insert(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NuDBFactory() override
|
public:
|
||||||
|
explicit NuDBFactory(Manager& manager) : manager_(manager)
|
||||||
{
|
{
|
||||||
Manager::instance().erase(*this);
|
manager_.insert(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -470,7 +467,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static NuDBFactory nuDBFactory;
|
void
|
||||||
|
registerNuDBFactory(Manager& manager)
|
||||||
|
{
|
||||||
|
static NuDBFactory instance{manager};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NodeStore
|
} // namespace NodeStore
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/nodestore/Factory.h>
|
#include <xrpl/nodestore/Factory.h>
|
||||||
#include <xrpld/nodestore/Manager.h>
|
#include <xrpl/nodestore/Manager.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -111,15 +111,13 @@ private:
|
|||||||
|
|
||||||
class NullFactory : public Factory
|
class NullFactory : public Factory
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
NullFactory()
|
Manager& manager_;
|
||||||
{
|
|
||||||
Manager::instance().insert(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NullFactory() override
|
public:
|
||||||
|
explicit NullFactory(Manager& manager) : manager_(manager)
|
||||||
{
|
{
|
||||||
Manager::instance().erase(*this);
|
manager_.insert(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -140,7 +138,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static NullFactory nullFactory;
|
void
|
||||||
|
registerNullFactory(Manager& manager)
|
||||||
|
{
|
||||||
|
static NullFactory instance{manager};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NodeStore
|
} // namespace NodeStore
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
@@ -17,20 +17,18 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/unity/rocksdb.h>
|
#include <xrpl/basics/rocksdb.h>
|
||||||
|
|
||||||
#if RIPPLE_ROCKSDB_AVAILABLE
|
#if RIPPLE_ROCKSDB_AVAILABLE
|
||||||
#include <xrpld/core/Config.h> // VFALCO Bad dependency
|
|
||||||
#include <xrpld/nodestore/Factory.h>
|
|
||||||
#include <xrpld/nodestore/Manager.h>
|
|
||||||
#include <xrpld/nodestore/detail/BatchWriter.h>
|
|
||||||
#include <xrpld/nodestore/detail/DecodedBlob.h>
|
|
||||||
#include <xrpld/nodestore/detail/EncodedBlob.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/ByteUtilities.h>
|
#include <xrpl/basics/ByteUtilities.h>
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/basics/safe_cast.h>
|
#include <xrpl/basics/safe_cast.h>
|
||||||
#include <xrpl/beast/core/CurrentThreadName.h>
|
#include <xrpl/beast/core/CurrentThreadName.h>
|
||||||
|
#include <xrpl/nodestore/Factory.h>
|
||||||
|
#include <xrpl/nodestore/Manager.h>
|
||||||
|
#include <xrpl/nodestore/detail/BatchWriter.h>
|
||||||
|
#include <xrpl/nodestore/detail/DecodedBlob.h>
|
||||||
|
#include <xrpl/nodestore/detail/EncodedBlob.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -461,17 +459,15 @@ public:
|
|||||||
|
|
||||||
class RocksDBFactory : public Factory
|
class RocksDBFactory : public Factory
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
Manager& manager_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RocksDBEnv m_env;
|
RocksDBEnv m_env;
|
||||||
|
|
||||||
RocksDBFactory()
|
RocksDBFactory(Manager& manager) : manager_(manager)
|
||||||
{
|
{
|
||||||
Manager::instance().insert(*this);
|
manager_.insert(*this);
|
||||||
}
|
|
||||||
|
|
||||||
~RocksDBFactory() override
|
|
||||||
{
|
|
||||||
Manager::instance().erase(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -493,7 +489,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static RocksDBFactory rocksDBFactory;
|
void
|
||||||
|
registerRocksDBFactory(Manager& manager)
|
||||||
|
{
|
||||||
|
static RocksDBFactory instance{manager};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace NodeStore
|
} // namespace NodeStore
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
@@ -96,8 +96,6 @@ enum class LedgerNameSpace : std::uint16_t {
|
|||||||
PERMISSIONED_DOMAIN = 'm',
|
PERMISSIONED_DOMAIN = 'm',
|
||||||
DELEGATE = 'E',
|
DELEGATE = 'E',
|
||||||
VAULT = 'V',
|
VAULT = 'V',
|
||||||
LOAN_BROKER = 'l', // lower-case L
|
|
||||||
LOAN = 'L',
|
|
||||||
|
|
||||||
// No longer used or supported. Left here to reserve the space
|
// No longer used or supported. Left here to reserve the space
|
||||||
// to avoid accidental reuse.
|
// to avoid accidental reuse.
|
||||||
@@ -568,18 +566,6 @@ vault(AccountID const& owner, std::uint32_t seq) noexcept
|
|||||||
return vault(indexHash(LedgerNameSpace::VAULT, owner, seq));
|
return vault(indexHash(LedgerNameSpace::VAULT, owner, seq));
|
||||||
}
|
}
|
||||||
|
|
||||||
Keylet
|
|
||||||
loanbroker(AccountID const& owner, std::uint32_t seq) noexcept
|
|
||||||
{
|
|
||||||
return loanbroker(indexHash(LedgerNameSpace::LOAN_BROKER, owner, seq));
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
|
||||||
loan(uint256 const& loanBrokerID, std::uint32_t loanSeq) noexcept
|
|
||||||
{
|
|
||||||
return loan(indexHash(LedgerNameSpace::LOAN, loanBrokerID, loanSeq));
|
|
||||||
}
|
|
||||||
|
|
||||||
Keylet
|
Keylet
|
||||||
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept
|
permissionedDomain(AccountID const& account, std::uint32_t seq) noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -172,14 +172,6 @@ InnerObjectFormats::InnerObjectFormats()
|
|||||||
{sfBookDirectory, soeREQUIRED},
|
{sfBookDirectory, soeREQUIRED},
|
||||||
{sfBookNode, soeREQUIRED},
|
{sfBookNode, soeREQUIRED},
|
||||||
});
|
});
|
||||||
|
|
||||||
add(sfCounterpartySignature.jsonName,
|
|
||||||
sfCounterpartySignature.getCode(),
|
|
||||||
{
|
|
||||||
{sfSigningPubKey, soeOPTIONAL},
|
|
||||||
{sfTxnSignature, soeOPTIONAL},
|
|
||||||
{sfSigners, soeOPTIONAL},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerObjectFormats const&
|
InnerObjectFormats const&
|
||||||
|
|||||||
@@ -174,21 +174,22 @@ Permission::isDelegatable(
|
|||||||
auto const txType = permissionToTxType(permissionValue);
|
auto const txType = permissionToTxType(permissionValue);
|
||||||
auto const it = delegatableTx_.find(txType);
|
auto const it = delegatableTx_.find(txType);
|
||||||
|
|
||||||
if (rules.enabled(fixDelegateV1_1))
|
if (it == delegatableTx_.end())
|
||||||
{
|
return false;
|
||||||
if (it == delegatableTx_.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto const feature = getTxFeature(txType);
|
auto const txFeaturesIt = txFeatureMap_.find(txType);
|
||||||
|
XRPL_ASSERT(
|
||||||
|
txFeaturesIt != txFeatureMap_.end(),
|
||||||
|
"ripple::Permissions::isDelegatable : tx exists in txFeatureMap_");
|
||||||
|
|
||||||
// fixDelegateV1_1: Delegation is only allowed if the required amendment
|
// Delegation is only allowed if the required amendment for the transaction
|
||||||
// for the transaction is enabled. For transactions that do not require
|
// is enabled. For transactions that do not require an amendment, delegation
|
||||||
// an amendment, delegation is always allowed.
|
// is always allowed.
|
||||||
if (feature && !rules.enabled(*feature))
|
if (txFeaturesIt->second != uint256{} &&
|
||||||
return false;
|
!rules.enabled(txFeaturesIt->second))
|
||||||
}
|
return false;
|
||||||
|
|
||||||
if (it != delegatableTx_.end() && it->second == Delegation::notDelegatable)
|
if (it->second == Delegation::notDelegatable)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ STAmount::xrp() const
|
|||||||
IOUAmount
|
IOUAmount
|
||||||
STAmount::iou() const
|
STAmount::iou() const
|
||||||
{
|
{
|
||||||
if (integral())
|
if (native() || !holds<Issue>())
|
||||||
Throw<std::logic_error>("Cannot return non-IOU STAmount as IOUAmount");
|
Throw<std::logic_error>("Cannot return non-IOU STAmount as IOUAmount");
|
||||||
|
|
||||||
auto mantissa = static_cast<std::int64_t>(mValue);
|
auto mantissa = static_cast<std::int64_t>(mValue);
|
||||||
@@ -1480,31 +1480,6 @@ canonicalizeRoundStrict(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
|
||||||
roundToScale(STAmount value, std::int32_t scale, Number::rounding_mode rounding)
|
|
||||||
{
|
|
||||||
// Nothing to do for intgral types.
|
|
||||||
if (value.integral())
|
|
||||||
return value;
|
|
||||||
|
|
||||||
// If the value's exponent is greater than or equal to the scale, then
|
|
||||||
// rounding will do nothing, and might even lose precision, so just return
|
|
||||||
// the value.
|
|
||||||
if (value.exponent() >= scale)
|
|
||||||
return value;
|
|
||||||
|
|
||||||
STAmount referenceValue{
|
|
||||||
value.asset(), STAmount::cMinValue, scale, value.negative()};
|
|
||||||
|
|
||||||
NumberRoundModeGuard mg(rounding);
|
|
||||||
// With an IOU, the total will be truncated to the precision of the
|
|
||||||
// larger value: referenceValue
|
|
||||||
value += referenceValue;
|
|
||||||
// Remove the reference value, and we're left with the rounded value.
|
|
||||||
value -= referenceValue;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// We need a class that has an interface similar to NumberRoundModeGuard
|
// We need a class that has an interface similar to NumberRoundModeGuard
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ STTx::checkSign(
|
|||||||
if (auto const ret = checkSign(requireCanonicalSig, rules, *this); !ret)
|
if (auto const ret = checkSign(requireCanonicalSig, rules, *this); !ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Placeholder for field that will be added by Lending Protocol
|
||||||
if (isFieldPresent(sfCounterpartySignature))
|
if (isFieldPresent(sfCounterpartySignature))
|
||||||
{
|
{
|
||||||
auto const counterSig = getFieldObject(sfCounterpartySignature);
|
auto const counterSig = getFieldObject(sfCounterpartySignature);
|
||||||
@@ -293,6 +294,7 @@ STTx::checkSign(
|
|||||||
!ret)
|
!ret)
|
||||||
return Unexpected("Counterparty: " + ret.error());
|
return Unexpected("Counterparty: " + ret.error());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ transResults()
|
|||||||
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
|
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
|
||||||
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
|
MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."),
|
||||||
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
|
MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."),
|
||||||
MAKE_ERROR(tecNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
|
|
||||||
|
|
||||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||||
@@ -235,6 +234,7 @@ transResults()
|
|||||||
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
|
MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."),
|
||||||
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
|
MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."),
|
||||||
MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."),
|
MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."),
|
||||||
|
MAKE_ERROR(terNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."),
|
||||||
|
|
||||||
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
|
MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,35 +39,13 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
template <class T>
|
|
||||||
TxMeta::TxMeta(
|
|
||||||
uint256 const& txid,
|
|
||||||
std::uint32_t ledger,
|
|
||||||
T const& data,
|
|
||||||
CtorHelper)
|
|
||||||
: mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
|
|
||||||
{
|
|
||||||
SerialIter sit(makeSlice(data));
|
|
||||||
|
|
||||||
STObject obj(sit, sfMetadata);
|
|
||||||
mResult = obj.getFieldU8(sfTransactionResult);
|
|
||||||
mIndex = obj.getFieldU32(sfTransactionIndex);
|
|
||||||
mNodes = *dynamic_cast<STArray*>(&obj.getField(sfAffectedNodes));
|
|
||||||
|
|
||||||
if (obj.isFieldPresent(sfDeliveredAmount))
|
|
||||||
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
|
|
||||||
|
|
||||||
if (obj.isFieldPresent(sfParentBatchID))
|
|
||||||
setParentBatchId(obj.getFieldH256(sfParentBatchID));
|
|
||||||
}
|
|
||||||
|
|
||||||
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
||||||
: mTransactionID(txid)
|
: transactionID_(txid)
|
||||||
, mLedger(ledger)
|
, ledgerSeq_(ledger)
|
||||||
, mNodes(obj.getFieldArray(sfAffectedNodes))
|
, nodes_(obj.getFieldArray(sfAffectedNodes))
|
||||||
{
|
{
|
||||||
mResult = obj.getFieldU8(sfTransactionResult);
|
result_ = obj.getFieldU8(sfTransactionResult);
|
||||||
mIndex = obj.getFieldU32(sfTransactionIndex);
|
index_ = obj.getFieldU32(sfTransactionIndex);
|
||||||
|
|
||||||
auto affectedNodes =
|
auto affectedNodes =
|
||||||
dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
|
dynamic_cast<STArray const*>(obj.peekAtPField(sfAffectedNodes));
|
||||||
@@ -75,40 +53,32 @@ TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, STObject const& obj)
|
|||||||
affectedNodes,
|
affectedNodes,
|
||||||
"ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
|
"ripple::TxMeta::TxMeta(STObject) : type cast succeeded");
|
||||||
if (affectedNodes)
|
if (affectedNodes)
|
||||||
mNodes = *affectedNodes;
|
nodes_ = *affectedNodes;
|
||||||
|
|
||||||
if (obj.isFieldPresent(sfDeliveredAmount))
|
setAdditionalFields(obj);
|
||||||
setDeliveredAmount(obj.getFieldAmount(sfDeliveredAmount));
|
|
||||||
|
|
||||||
if (obj.isFieldPresent(sfParentBatchID))
|
|
||||||
setParentBatchId(obj.getFieldH256(sfParentBatchID));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
|
TxMeta::TxMeta(uint256 const& txid, std::uint32_t ledger, Blob const& vec)
|
||||||
: TxMeta(txid, ledger, vec, CtorHelper())
|
: transactionID_(txid), ledgerSeq_(ledger), nodes_(sfAffectedNodes, 32)
|
||||||
{
|
{
|
||||||
|
SerialIter sit(makeSlice(vec));
|
||||||
|
|
||||||
|
STObject obj(sit, sfMetadata);
|
||||||
|
result_ = obj.getFieldU8(sfTransactionResult);
|
||||||
|
index_ = obj.getFieldU32(sfTransactionIndex);
|
||||||
|
nodes_ = obj.getFieldArray(sfAffectedNodes);
|
||||||
|
|
||||||
|
setAdditionalFields(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
TxMeta::TxMeta(
|
TxMeta::TxMeta(uint256 const& transactionID, std::uint32_t ledger)
|
||||||
uint256 const& txid,
|
: transactionID_(transactionID)
|
||||||
std::uint32_t ledger,
|
, ledgerSeq_(ledger)
|
||||||
std::string const& data)
|
, index_(std::numeric_limits<std::uint32_t>::max())
|
||||||
: TxMeta(txid, ledger, data, CtorHelper())
|
, result_(255)
|
||||||
|
, nodes_(sfAffectedNodes)
|
||||||
{
|
{
|
||||||
}
|
nodes_.reserve(32);
|
||||||
|
|
||||||
TxMeta::TxMeta(
|
|
||||||
uint256 const& transactionID,
|
|
||||||
std::uint32_t ledger,
|
|
||||||
std::optional<uint256> parentBatchId)
|
|
||||||
: mTransactionID(transactionID)
|
|
||||||
, mLedger(ledger)
|
|
||||||
, mIndex(static_cast<std::uint32_t>(-1))
|
|
||||||
, mResult(255)
|
|
||||||
, mParentBatchId(parentBatchId)
|
|
||||||
, mNodes(sfAffectedNodes)
|
|
||||||
{
|
|
||||||
mNodes.reserve(32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -118,7 +88,7 @@ TxMeta::setAffectedNode(
|
|||||||
std::uint16_t nodeType)
|
std::uint16_t nodeType)
|
||||||
{
|
{
|
||||||
// make sure the node exists and force its type
|
// make sure the node exists and force its type
|
||||||
for (auto& n : mNodes)
|
for (auto& n : nodes_)
|
||||||
{
|
{
|
||||||
if (n.getFieldH256(sfLedgerIndex) == node)
|
if (n.getFieldH256(sfLedgerIndex) == node)
|
||||||
{
|
{
|
||||||
@@ -128,8 +98,8 @@ TxMeta::setAffectedNode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mNodes.push_back(STObject(type));
|
nodes_.push_back(STObject(type));
|
||||||
STObject& obj = mNodes.back();
|
STObject& obj = nodes_.back();
|
||||||
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
obj.getFName() == type,
|
obj.getFName() == type,
|
||||||
@@ -146,14 +116,15 @@ TxMeta::getAffectedAccounts() const
|
|||||||
|
|
||||||
// This code should match the behavior of the JS method:
|
// This code should match the behavior of the JS method:
|
||||||
// Meta#getAffectedAccounts
|
// Meta#getAffectedAccounts
|
||||||
for (auto const& it : mNodes)
|
for (auto const& node : nodes_)
|
||||||
{
|
{
|
||||||
int index = it.getFieldIndex(
|
int index = node.getFieldIndex(
|
||||||
(it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
|
(node.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields);
|
||||||
|
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
auto inner = dynamic_cast<STObject const*>(&it.peekAtIndex(index));
|
auto const* inner =
|
||||||
|
dynamic_cast<STObject const*>(&node.peekAtIndex(index));
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
inner,
|
inner,
|
||||||
"ripple::getAffectedAccounts : STObject type cast succeeded");
|
"ripple::getAffectedAccounts : STObject type cast succeeded");
|
||||||
@@ -213,13 +184,13 @@ STObject&
|
|||||||
TxMeta::getAffectedNode(SLE::ref node, SField const& type)
|
TxMeta::getAffectedNode(SLE::ref node, SField const& type)
|
||||||
{
|
{
|
||||||
uint256 index = node->key();
|
uint256 index = node->key();
|
||||||
for (auto& n : mNodes)
|
for (auto& n : nodes_)
|
||||||
{
|
{
|
||||||
if (n.getFieldH256(sfLedgerIndex) == index)
|
if (n.getFieldH256(sfLedgerIndex) == index)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
mNodes.push_back(STObject(type));
|
nodes_.push_back(STObject(type));
|
||||||
STObject& obj = mNodes.back();
|
STObject& obj = nodes_.back();
|
||||||
|
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
obj.getFName() == type,
|
obj.getFName() == type,
|
||||||
@@ -233,7 +204,7 @@ TxMeta::getAffectedNode(SLE::ref node, SField const& type)
|
|||||||
STObject&
|
STObject&
|
||||||
TxMeta::getAffectedNode(uint256 const& node)
|
TxMeta::getAffectedNode(uint256 const& node)
|
||||||
{
|
{
|
||||||
for (auto& n : mNodes)
|
for (auto& n : nodes_)
|
||||||
{
|
{
|
||||||
if (n.getFieldH256(sfLedgerIndex) == node)
|
if (n.getFieldH256(sfLedgerIndex) == node)
|
||||||
return n;
|
return n;
|
||||||
@@ -241,7 +212,7 @@ TxMeta::getAffectedNode(uint256 const& node)
|
|||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
|
UNREACHABLE("ripple::TxMeta::getAffectedNode(uint256) : node not found");
|
||||||
Throw<std::runtime_error>("Affected node not found");
|
Throw<std::runtime_error>("Affected node not found");
|
||||||
return *(mNodes.begin()); // Silence compiler warning.
|
return *(nodes_.begin()); // Silence compiler warning.
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,15 +220,15 @@ STObject
|
|||||||
TxMeta::getAsObject() const
|
TxMeta::getAsObject() const
|
||||||
{
|
{
|
||||||
STObject metaData(sfTransactionMetaData);
|
STObject metaData(sfTransactionMetaData);
|
||||||
XRPL_ASSERT(mResult != 255, "ripple::TxMeta::getAsObject : result is set");
|
XRPL_ASSERT(result_ != 255, "ripple::TxMeta::getAsObject : result_ is set");
|
||||||
metaData.setFieldU8(sfTransactionResult, mResult);
|
metaData.setFieldU8(sfTransactionResult, result_);
|
||||||
metaData.setFieldU32(sfTransactionIndex, mIndex);
|
metaData.setFieldU32(sfTransactionIndex, index_);
|
||||||
metaData.emplace_back(mNodes);
|
metaData.emplace_back(nodes_);
|
||||||
if (hasDeliveredAmount())
|
if (deliveredAmount_.has_value())
|
||||||
metaData.setFieldAmount(sfDeliveredAmount, getDeliveredAmount());
|
metaData.setFieldAmount(sfDeliveredAmount, *deliveredAmount_);
|
||||||
|
|
||||||
if (hasParentBatchId())
|
if (parentBatchID_.has_value())
|
||||||
metaData.setFieldH256(sfParentBatchID, getParentBatchId());
|
metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
|
||||||
|
|
||||||
return metaData;
|
return metaData;
|
||||||
}
|
}
|
||||||
@@ -265,13 +236,13 @@ TxMeta::getAsObject() const
|
|||||||
void
|
void
|
||||||
TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index)
|
TxMeta::addRaw(Serializer& s, TER result, std::uint32_t index)
|
||||||
{
|
{
|
||||||
mResult = TERtoInt(result);
|
result_ = TERtoInt(result);
|
||||||
mIndex = index;
|
index_ = index;
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
(mResult == 0) || ((mResult > 100) && (mResult <= 255)),
|
(result_ == 0) || ((result_ > 100) && (result_ <= 255)),
|
||||||
"ripple::TxMeta::addRaw : valid TER input");
|
"ripple::TxMeta::addRaw : valid TER input");
|
||||||
|
|
||||||
mNodes.sort([](STObject const& o1, STObject const& o2) {
|
nodes_.sort([](STObject const& o1, STObject const& o2) {
|
||||||
return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
|
return o1.getFieldH256(sfLedgerIndex) < o2.getFieldH256(sfLedgerIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -17,15 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMap.h>
|
|
||||||
#include <xrpld/shamap/SHAMapAccountStateLeafNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapNodeID.h>
|
|
||||||
#include <xrpld/shamap/SHAMapSyncFilter.h>
|
|
||||||
#include <xrpld/shamap/SHAMapTxLeafNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapTxPlusMetaLeafNode.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/TaggedCache.ipp>
|
#include <xrpl/basics/TaggedCache.ipp>
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
|
#include <xrpl/shamap/SHAMap.h>
|
||||||
|
#include <xrpl/shamap/SHAMapAccountStateLeafNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapNodeID.h>
|
||||||
|
#include <xrpl/shamap/SHAMapSyncFilter.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTxLeafNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTxPlusMetaLeafNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMap.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.ipp>
|
#include <xrpl/basics/IntrusivePointer.ipp>
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
|
#include <xrpl/shamap/SHAMap.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
@@ -17,16 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapInnerNode.h>
|
|
||||||
#include <xrpld/shamap/SHAMapTreeNode.h>
|
|
||||||
#include <xrpld/shamap/detail/TaggedPointer.ipp>
|
|
||||||
|
|
||||||
#include <xrpl/basics/IntrusivePointer.ipp>
|
#include <xrpl/basics/IntrusivePointer.ipp>
|
||||||
#include <xrpl/basics/Slice.h>
|
#include <xrpl/basics/Slice.h>
|
||||||
#include <xrpl/basics/contract.h>
|
#include <xrpl/basics/contract.h>
|
||||||
#include <xrpl/basics/spinlock.h>
|
#include <xrpl/basics/spinlock.h>
|
||||||
#include <xrpl/protocol/HashPrefix.h>
|
#include <xrpl/protocol/HashPrefix.h>
|
||||||
#include <xrpl/protocol/digest.h>
|
#include <xrpl/protocol/digest.h>
|
||||||
|
#include <xrpl/shamap/SHAMapInnerNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapTreeNode.h>
|
||||||
|
#include <xrpl/shamap/detail/TaggedPointer.ipp>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMapLeafNode.h>
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -17,12 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMap.h>
|
|
||||||
#include <xrpld/shamap/SHAMapNodeID.h>
|
|
||||||
|
|
||||||
#include <xrpl/beast/core/LexicalCast.h>
|
#include <xrpl/beast/core/LexicalCast.h>
|
||||||
#include <xrpl/beast/utility/instrumentation.h>
|
#include <xrpl/beast/utility/instrumentation.h>
|
||||||
#include <xrpl/protocol/Serializer.h>
|
#include <xrpl/protocol/Serializer.h>
|
||||||
|
#include <xrpl/shamap/SHAMap.h>
|
||||||
|
#include <xrpl/shamap/SHAMapNodeID.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <xrpld/shamap/SHAMap.h>
|
|
||||||
#include <xrpld/shamap/SHAMapSyncFilter.h>
|
|
||||||
|
|
||||||
#include <xrpl/basics/random.h>
|
#include <xrpl/basics/random.h>
|
||||||
|
#include <xrpl/shamap/SHAMap.h>
|
||||||
|
#include <xrpl/shamap/SHAMapLeafNode.h>
|
||||||
|
#include <xrpl/shamap/SHAMapSyncFilter.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -591,16 +591,16 @@ SHAMap::addKnownNode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto const generation = f_.getFullBelowCache()->getGeneration();
|
auto const generation = f_.getFullBelowCache()->getGeneration();
|
||||||
SHAMapNodeID iNodeID;
|
SHAMapNodeID currNodeID;
|
||||||
auto iNode = root_.get();
|
auto currNode = root_.get();
|
||||||
|
|
||||||
while (iNode->isInner() &&
|
while (currNode->isInner() &&
|
||||||
!static_cast<SHAMapInnerNode*>(iNode)->isFullBelow(generation) &&
|
!static_cast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
|
||||||
(iNodeID.getDepth() < node.getDepth()))
|
(currNodeID.getDepth() < node.getDepth()))
|
||||||
{
|
{
|
||||||
int branch = selectBranch(iNodeID, node.getNodeID());
|
int const branch = selectBranch(currNodeID, node.getNodeID());
|
||||||
XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch");
|
XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch");
|
||||||
auto inner = static_cast<SHAMapInnerNode*>(iNode);
|
auto inner = static_cast<SHAMapInnerNode*>(currNode);
|
||||||
if (inner->isEmptyBranch(branch))
|
if (inner->isEmptyBranch(branch))
|
||||||
{
|
{
|
||||||
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
|
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
|
||||||
@@ -614,58 +614,84 @@ SHAMap::addKnownNode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto prevNode = inner;
|
auto prevNode = inner;
|
||||||
std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
|
std::tie(currNode, currNodeID) =
|
||||||
|
descend(inner, currNodeID, branch, filter);
|
||||||
|
|
||||||
if (iNode == nullptr)
|
if (currNode != nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
|
||||||
|
|
||||||
|
if (!newNode || childHash != newNode->getHash())
|
||||||
{
|
{
|
||||||
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
|
JLOG(journal_.warn()) << "Corrupt node received";
|
||||||
|
return SHAMapAddNode::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
if (!newNode || childHash != newNode->getHash())
|
// In rare cases, a node can still be corrupt even after hash
|
||||||
|
// validation. For leaf nodes, we perform an additional check to
|
||||||
|
// ensure the node's position in the tree is consistent with its
|
||||||
|
// content to prevent inconsistencies that could
|
||||||
|
// propagate further down the line.
|
||||||
|
if (newNode->isLeaf())
|
||||||
|
{
|
||||||
|
auto const& actualKey =
|
||||||
|
static_cast<SHAMapLeafNode const*>(newNode.get())
|
||||||
|
->peekItem()
|
||||||
|
->key();
|
||||||
|
|
||||||
|
// Validate that this leaf belongs at the target position
|
||||||
|
auto const expectedNodeID =
|
||||||
|
SHAMapNodeID::createID(node.getDepth(), actualKey);
|
||||||
|
if (expectedNodeID.getNodeID() != node.getNodeID())
|
||||||
{
|
{
|
||||||
JLOG(journal_.warn()) << "Corrupt node received";
|
JLOG(journal_.debug())
|
||||||
|
<< "Leaf node position mismatch: "
|
||||||
|
<< "expected=" << expectedNodeID.getNodeID()
|
||||||
|
<< ", actual=" << node.getNodeID();
|
||||||
return SHAMapAddNode::invalid();
|
return SHAMapAddNode::invalid();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Inner nodes must be at a level strictly less than 64
|
// Inner nodes must be at a level strictly less than 64
|
||||||
// but leaf nodes (while notionally at level 64) can be
|
// but leaf nodes (while notionally at level 64) can be
|
||||||
// at any depth up to and including 64:
|
// at any depth up to and including 64:
|
||||||
if ((iNodeID.getDepth() > leafDepth) ||
|
if ((currNodeID.getDepth() > leafDepth) ||
|
||||||
(newNode->isInner() && iNodeID.getDepth() == leafDepth))
|
(newNode->isInner() && currNodeID.getDepth() == leafDepth))
|
||||||
{
|
{
|
||||||
// Map is provably invalid
|
// Map is provably invalid
|
||||||
state_ = SHAMapState::Invalid;
|
state_ = SHAMapState::Invalid;
|
||||||
return SHAMapAddNode::useful();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iNodeID != node)
|
|
||||||
{
|
|
||||||
// Either this node is broken or we didn't request it (yet)
|
|
||||||
JLOG(journal_.warn()) << "unable to hook node " << node;
|
|
||||||
JLOG(journal_.info()) << " stuck at " << iNodeID;
|
|
||||||
JLOG(journal_.info()) << "got depth=" << node.getDepth()
|
|
||||||
<< ", walked to= " << iNodeID.getDepth();
|
|
||||||
return SHAMapAddNode::useful();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backed_)
|
|
||||||
canonicalize(childHash, newNode);
|
|
||||||
|
|
||||||
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
|
|
||||||
|
|
||||||
if (filter)
|
|
||||||
{
|
|
||||||
Serializer s;
|
|
||||||
newNode->serializeWithPrefix(s);
|
|
||||||
filter->gotNode(
|
|
||||||
false,
|
|
||||||
childHash,
|
|
||||||
ledgerSeq_,
|
|
||||||
std::move(s.modData()),
|
|
||||||
newNode->getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
return SHAMapAddNode::useful();
|
return SHAMapAddNode::useful();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currNodeID != node)
|
||||||
|
{
|
||||||
|
// Either this node is broken or we didn't request it (yet)
|
||||||
|
JLOG(journal_.warn()) << "unable to hook node " << node;
|
||||||
|
JLOG(journal_.info()) << " stuck at " << currNodeID;
|
||||||
|
JLOG(journal_.info()) << "got depth=" << node.getDepth()
|
||||||
|
<< ", walked to= " << currNodeID.getDepth();
|
||||||
|
return SHAMapAddNode::useful();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backed_)
|
||||||
|
canonicalize(childHash, newNode);
|
||||||
|
|
||||||
|
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
|
||||||
|
|
||||||
|
if (filter)
|
||||||
|
{
|
||||||
|
Serializer s;
|
||||||
|
newNode->serializeWithPrefix(s);
|
||||||
|
filter->gotNode(
|
||||||
|
false,
|
||||||
|
childHash,
|
||||||
|
ledgerSeq_,
|
||||||
|
std::move(s.modData()),
|
||||||
|
newNode->getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHAMapAddNode::useful();
|
||||||
}
|
}
|
||||||
|
|
||||||
JLOG(journal_.trace()) << "got node, already had it (late)";
|
JLOG(journal_.trace()) << "got node, already had it (late)";
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user