mirror of
https://github.com/XRPLF/rippled.git
synced 2026-02-19 05:12:33 +00:00
Compare commits
7 Commits
ripple/se/
...
pratik/Add
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f5c54a4cc | ||
|
|
ac0ad3627f | ||
|
|
cd218346ff | ||
|
|
5edd3566f7 | ||
|
|
11e8d1f8a2 | ||
|
|
9f17d10348 | ||
|
|
ef284692db |
@@ -4,14 +4,11 @@ Loop: test.jtx test.toplevel
|
||||
Loop: test.jtx test.unit_test
|
||||
test.unit_test == test.jtx
|
||||
|
||||
Loop: xrpld.app xrpld.core
|
||||
xrpld.app > xrpld.core
|
||||
|
||||
Loop: xrpld.app xrpld.overlay
|
||||
xrpld.overlay > xrpld.app
|
||||
xrpld.overlay ~= xrpld.app
|
||||
|
||||
Loop: xrpld.app xrpld.peerfinder
|
||||
xrpld.peerfinder ~= xrpld.app
|
||||
xrpld.peerfinder == xrpld.app
|
||||
|
||||
Loop: xrpld.app xrpld.rpc
|
||||
xrpld.rpc > xrpld.app
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
libxrpl.basics > xrpl.basics
|
||||
libxrpl.conditions > xrpl.basics
|
||||
libxrpl.conditions > xrpl.conditions
|
||||
libxrpl.core > xrpl.basics
|
||||
libxrpl.core > xrpl.core
|
||||
libxrpl.crypto > xrpl.basics
|
||||
@@ -17,12 +19,15 @@ libxrpl.nodestore > xrpl.protocol
|
||||
libxrpl.protocol > xrpl.basics
|
||||
libxrpl.protocol > xrpl.json
|
||||
libxrpl.protocol > xrpl.protocol
|
||||
libxrpl.rdb > xrpl.basics
|
||||
libxrpl.rdb > xrpl.rdb
|
||||
libxrpl.resource > xrpl.basics
|
||||
libxrpl.resource > xrpl.json
|
||||
libxrpl.resource > xrpl.resource
|
||||
libxrpl.server > xrpl.basics
|
||||
libxrpl.server > xrpl.json
|
||||
libxrpl.server > xrpl.protocol
|
||||
libxrpl.server > xrpl.rdb
|
||||
libxrpl.server > xrpl.server
|
||||
libxrpl.shamap > xrpl.basics
|
||||
libxrpl.shamap > xrpl.protocol
|
||||
@@ -41,7 +46,9 @@ test.app > xrpl.json
|
||||
test.app > xrpl.ledger
|
||||
test.app > xrpl.nodestore
|
||||
test.app > xrpl.protocol
|
||||
test.app > xrpl.rdb
|
||||
test.app > xrpl.resource
|
||||
test.app > xrpl.server
|
||||
test.basics > test.jtx
|
||||
test.basics > test.unit_test
|
||||
test.basics > xrpl.basics
|
||||
@@ -51,7 +58,7 @@ test.basics > xrpl.json
|
||||
test.basics > xrpl.protocol
|
||||
test.beast > xrpl.basics
|
||||
test.conditions > xrpl.basics
|
||||
test.conditions > xrpld.conditions
|
||||
test.conditions > xrpl.conditions
|
||||
test.consensus > test.csf
|
||||
test.consensus > test.toplevel
|
||||
test.consensus > test.unit_test
|
||||
@@ -67,6 +74,7 @@ test.core > xrpl.basics
|
||||
test.core > xrpl.core
|
||||
test.core > xrpld.core
|
||||
test.core > xrpl.json
|
||||
test.core > xrpl.rdb
|
||||
test.core > xrpl.server
|
||||
test.csf > xrpl.basics
|
||||
test.csf > xrpld.consensus
|
||||
@@ -95,8 +103,8 @@ test.nodestore > test.jtx
|
||||
test.nodestore > test.toplevel
|
||||
test.nodestore > test.unit_test
|
||||
test.nodestore > xrpl.basics
|
||||
test.nodestore > xrpld.core
|
||||
test.nodestore > xrpl.nodestore
|
||||
test.nodestore > xrpl.rdb
|
||||
test.overlay > test.jtx
|
||||
test.overlay > test.toplevel
|
||||
test.overlay > test.unit_test
|
||||
@@ -131,6 +139,7 @@ test.rpc > xrpld.rpc
|
||||
test.rpc > xrpl.json
|
||||
test.rpc > xrpl.protocol
|
||||
test.rpc > xrpl.resource
|
||||
test.rpc > xrpl.server
|
||||
test.server > test.jtx
|
||||
test.server > test.toplevel
|
||||
test.server > test.unit_test
|
||||
@@ -151,40 +160,52 @@ test.unit_test > xrpl.basics
|
||||
tests.libxrpl > xrpl.basics
|
||||
tests.libxrpl > xrpl.json
|
||||
tests.libxrpl > xrpl.net
|
||||
xrpl.conditions > xrpl.basics
|
||||
xrpl.conditions > xrpl.protocol
|
||||
xrpl.core > xrpl.basics
|
||||
xrpl.core > xrpl.json
|
||||
xrpl.core > xrpl.ledger
|
||||
xrpl.core > xrpl.protocol
|
||||
xrpl.json > xrpl.basics
|
||||
xrpl.ledger > xrpl.basics
|
||||
xrpl.ledger > xrpl.protocol
|
||||
xrpl.ledger > xrpl.server
|
||||
xrpl.net > xrpl.basics
|
||||
xrpl.nodestore > xrpl.basics
|
||||
xrpl.nodestore > xrpl.protocol
|
||||
xrpl.protocol > xrpl.basics
|
||||
xrpl.protocol > xrpl.json
|
||||
xrpl.rdb > xrpl.basics
|
||||
xrpl.rdb > xrpl.core
|
||||
xrpl.rdb > xrpl.protocol
|
||||
xrpl.resource > xrpl.basics
|
||||
xrpl.resource > xrpl.json
|
||||
xrpl.resource > xrpl.protocol
|
||||
xrpl.server > xrpl.basics
|
||||
xrpl.server > xrpl.core
|
||||
xrpl.server > xrpl.json
|
||||
xrpl.server > xrpl.protocol
|
||||
xrpl.server > xrpl.rdb
|
||||
xrpl.server > xrpl.resource
|
||||
xrpl.server > xrpl.shamap
|
||||
xrpl.shamap > xrpl.basics
|
||||
xrpl.shamap > xrpl.nodestore
|
||||
xrpl.shamap > xrpl.protocol
|
||||
xrpld.app > test.unit_test
|
||||
xrpld.app > xrpl.basics
|
||||
xrpld.app > xrpl.conditions
|
||||
xrpld.app > xrpl.core
|
||||
xrpld.app > xrpld.conditions
|
||||
xrpld.app > xrpld.consensus
|
||||
xrpld.app > xrpld.core
|
||||
xrpld.app > xrpl.json
|
||||
xrpld.app > xrpl.ledger
|
||||
xrpld.app > xrpl.net
|
||||
xrpld.app > xrpl.nodestore
|
||||
xrpld.app > xrpl.protocol
|
||||
xrpld.app > xrpl.rdb
|
||||
xrpld.app > xrpl.resource
|
||||
xrpld.app > xrpl.server
|
||||
xrpld.app > xrpl.shamap
|
||||
xrpld.conditions > xrpl.basics
|
||||
xrpld.conditions > xrpl.protocol
|
||||
xrpld.consensus > xrpl.basics
|
||||
xrpld.consensus > xrpl.json
|
||||
xrpld.consensus > xrpl.protocol
|
||||
@@ -193,17 +214,20 @@ xrpld.core > xrpl.core
|
||||
xrpld.core > xrpl.json
|
||||
xrpld.core > xrpl.net
|
||||
xrpld.core > xrpl.protocol
|
||||
xrpld.core > xrpl.rdb
|
||||
xrpld.overlay > xrpl.basics
|
||||
xrpld.overlay > xrpl.core
|
||||
xrpld.overlay > xrpld.core
|
||||
xrpld.overlay > xrpld.peerfinder
|
||||
xrpld.overlay > xrpl.json
|
||||
xrpld.overlay > xrpl.protocol
|
||||
xrpld.overlay > xrpl.rdb
|
||||
xrpld.overlay > xrpl.resource
|
||||
xrpld.overlay > xrpl.server
|
||||
xrpld.peerfinder > xrpl.basics
|
||||
xrpld.peerfinder > xrpld.core
|
||||
xrpld.peerfinder > xrpl.protocol
|
||||
xrpld.peerfinder > xrpl.rdb
|
||||
xrpld.perflog > xrpl.basics
|
||||
xrpld.perflog > xrpl.core
|
||||
xrpld.perflog > xrpld.rpc
|
||||
@@ -216,6 +240,7 @@ xrpld.rpc > xrpl.ledger
|
||||
xrpld.rpc > xrpl.net
|
||||
xrpld.rpc > xrpl.nodestore
|
||||
xrpld.rpc > xrpl.protocol
|
||||
xrpld.rpc > xrpl.rdb
|
||||
xrpld.rpc > xrpl.resource
|
||||
xrpld.rpc > xrpl.server
|
||||
xrpld.shamap > xrpl.shamap
|
||||
|
||||
@@ -103,7 +103,6 @@ find_package(OpenSSL REQUIRED)
|
||||
find_package(secp256k1 REQUIRED)
|
||||
find_package(SOCI REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(wasmi REQUIRED)
|
||||
find_package(xxHash REQUIRED)
|
||||
|
||||
target_link_libraries(
|
||||
|
||||
@@ -1272,39 +1272,6 @@
|
||||
# Example:
|
||||
# owner_reserve = 2000000 # 2 XRP
|
||||
#
|
||||
# extension_compute_limit = <gas>
|
||||
#
|
||||
# The extension compute limit is the maximum amount of gas that can be
|
||||
# consumed by a single transaction. The gas limit is used to prevent
|
||||
# transactions from consuming too many resources.
|
||||
#
|
||||
# If this parameter is unspecified, xrpld will use an internal
|
||||
# default. Don't change this without understanding the consequences.
|
||||
#
|
||||
# Example:
|
||||
# extension_compute_limit = 1000000 # 1 million gas
|
||||
#
|
||||
# extension_size_limit = <bytes>
|
||||
#
|
||||
# The extension size limit is the maximum size of a WASM extension in
|
||||
# bytes. The size limit is used to prevent extensions from consuming
|
||||
# too many resources.
|
||||
#
|
||||
# If this parameter is unspecified, xrpld will use an internal
|
||||
# default. Don't change this without understanding the consequences.
|
||||
#
|
||||
# Example:
|
||||
# extension_size_limit = 100000 # 100 kb
|
||||
#
|
||||
# gas_price = <bytes>
|
||||
#
|
||||
# The gas price is the conversion between WASM gas and its price in drops.
|
||||
#
|
||||
# If this parameter is unspecified, xrpld will use an internal
|
||||
# default. Don't change this without understanding the consequences.
|
||||
#
|
||||
# Example:
|
||||
# gas_price = 1000000 # 1 drop per gas
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 9. Misc Settings
|
||||
|
||||
@@ -466,11 +466,6 @@ function (add_code_coverage_to_target name scope)
|
||||
target_compile_options(${name} ${scope} $<$<COMPILE_LANGUAGE:CXX>:${COVERAGE_CXX_COMPILER_FLAGS}>
|
||||
$<$<COMPILE_LANGUAGE:C>:${COVERAGE_C_COMPILER_FLAGS}>)
|
||||
|
||||
target_link_libraries(
|
||||
${name}
|
||||
${scope}
|
||||
$<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}
|
||||
gcov>
|
||||
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}
|
||||
gcov>)
|
||||
target_link_libraries(${name} ${scope} $<$<LINK_LANGUAGE:CXX>:${COVERAGE_CXX_LINKER_FLAGS}>
|
||||
$<$<LINK_LANGUAGE:C>:${COVERAGE_C_LINKER_FLAGS}>)
|
||||
endfunction () # add_code_coverage_to_target
|
||||
|
||||
@@ -45,7 +45,6 @@ target_link_libraries(
|
||||
Xrpl::opts
|
||||
Xrpl::syslibs
|
||||
secp256k1::secp256k1
|
||||
wasmi::wasmi
|
||||
xrpl.libpb
|
||||
xxHash::xxhash
|
||||
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>)
|
||||
@@ -85,9 +84,6 @@ add_module(xrpl net)
|
||||
target_link_libraries(xrpl.libxrpl.net PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.resource)
|
||||
|
||||
add_module(xrpl server)
|
||||
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)
|
||||
|
||||
@@ -95,8 +91,25 @@ 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 rdb)
|
||||
target_link_libraries(xrpl.libxrpl.rdb PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.core)
|
||||
|
||||
add_module(xrpl server)
|
||||
target_link_libraries(xrpl.libxrpl.server PUBLIC xrpl.libxrpl.protocol xrpl.libxrpl.core xrpl.libxrpl.rdb
|
||||
xrpl.libxrpl.resource)
|
||||
|
||||
add_module(xrpl conditions)
|
||||
target_link_libraries(xrpl.libxrpl.conditions PUBLIC xrpl.libxrpl.server)
|
||||
|
||||
add_module(xrpl ledger)
|
||||
target_link_libraries(xrpl.libxrpl.ledger PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.json xrpl.libxrpl.protocol)
|
||||
target_link_libraries(
|
||||
xrpl.libxrpl.ledger
|
||||
PUBLIC xrpl.libxrpl.basics
|
||||
xrpl.libxrpl.json
|
||||
xrpl.libxrpl.protocol
|
||||
xrpl.libxrpl.rdb
|
||||
xrpl.libxrpl.server
|
||||
xrpl.libxrpl.conditions)
|
||||
|
||||
add_library(xrpl.libxrpl)
|
||||
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
|
||||
@@ -111,16 +124,18 @@ target_link_modules(
|
||||
PUBLIC
|
||||
basics
|
||||
beast
|
||||
conditions
|
||||
core
|
||||
crypto
|
||||
json
|
||||
ledger
|
||||
net
|
||||
nodestore
|
||||
protocol
|
||||
rdb
|
||||
resource
|
||||
server
|
||||
nodestore
|
||||
shamap
|
||||
net
|
||||
ledger)
|
||||
shamap)
|
||||
|
||||
# All headers in libxrpl are in modules.
|
||||
# Uncomment this stanza if you have not yet moved new headers into a module.
|
||||
|
||||
@@ -20,9 +20,11 @@ install(TARGETS common
|
||||
xrpl.libxrpl
|
||||
xrpl.libxrpl.basics
|
||||
xrpl.libxrpl.beast
|
||||
xrpl.libxrpl.conditions
|
||||
xrpl.libxrpl.core
|
||||
xrpl.libxrpl.crypto
|
||||
xrpl.libxrpl.json
|
||||
xrpl.libxrpl.rdb
|
||||
xrpl.libxrpl.ledger
|
||||
xrpl.libxrpl.net
|
||||
xrpl.libxrpl.nodestore
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"requires": [
|
||||
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
|
||||
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
|
||||
"wasmi/1.0.6#407c9db14601a8af1c7dd3b388f3e4cd%1768164779.349",
|
||||
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
|
||||
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
|
||||
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
|
||||
|
||||
@@ -35,7 +35,6 @@ class Xrpl(ConanFile):
|
||||
"openssl/3.5.5",
|
||||
"secp256k1/0.7.1",
|
||||
"soci/4.0.3",
|
||||
"wasmi/1.0.6",
|
||||
"zlib/1.3.1",
|
||||
]
|
||||
|
||||
@@ -216,7 +215,6 @@ class Xrpl(ConanFile):
|
||||
"soci::soci",
|
||||
"secp256k1::secp256k1",
|
||||
"sqlite3::sqlite",
|
||||
"wasmi::wasmi",
|
||||
"xxhash::xxhash",
|
||||
"zlib::zlib",
|
||||
]
|
||||
|
||||
@@ -6,8 +6,6 @@ ignorePaths:
|
||||
- docs/**/*.puml
|
||||
- cmake/**
|
||||
- LICENSE.md
|
||||
- src/test/app/wasm_fixtures/**/*.wat
|
||||
- src/test/app/wasm_fixtures/*.c
|
||||
language: en
|
||||
allowCompoundWords: true # TODO (#6334)
|
||||
ignoreRandomStrings: true
|
||||
@@ -61,7 +59,6 @@ words:
|
||||
- Britto
|
||||
- Btrfs
|
||||
- canonicality
|
||||
- cdylib
|
||||
- changespq
|
||||
- checkme
|
||||
- choco
|
||||
@@ -113,6 +110,7 @@ words:
|
||||
- gpgcheck
|
||||
- gpgkey
|
||||
- hotwallet
|
||||
- hwaddress
|
||||
- hwrap
|
||||
- ifndef
|
||||
- inequation
|
||||
@@ -290,7 +288,6 @@ words:
|
||||
- venv
|
||||
- vfalco
|
||||
- vinnie
|
||||
- wasmi
|
||||
- wextra
|
||||
- wptr
|
||||
- writeme
|
||||
|
||||
@@ -17,8 +17,8 @@ guideline is to maintain the standards that are used in those libraries.
|
||||
## Guidelines
|
||||
|
||||
If you want to do something contrary to these guidelines, understand
|
||||
why you're doing it. Think, use common sense, and consider that this
|
||||
your changes will probably need to be maintained long after you've
|
||||
why you're doing it. Think, use common sense, and consider that these
|
||||
changes will probably need to be maintained long after you've
|
||||
moved on to other projects.
|
||||
|
||||
- Use white space and blank lines to guide the eye and keep your intent clear.
|
||||
|
||||
@@ -716,10 +716,6 @@ abs(Number x) noexcept
|
||||
Number
|
||||
power(Number const& f, unsigned n);
|
||||
|
||||
// logarithm with base 10
|
||||
Number
|
||||
log10(Number const& value, int iterations = 50);
|
||||
|
||||
// Returns f^(1/d)
|
||||
// Uses Newton–Raphson iterations until the result stops changing
|
||||
// to find the root of the polynomial g(x) = x^d - f
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/sanitizers.h>
|
||||
#include <xrpl/beast/type_name.h>
|
||||
|
||||
#include <exception>
|
||||
@@ -24,7 +25,7 @@ LogThrow(std::string const& title);
|
||||
control to the next matching exception handler, if any.
|
||||
Otherwise, std::terminate will be called.
|
||||
*/
|
||||
[[noreturn]] inline void
|
||||
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
|
||||
Rethrow()
|
||||
{
|
||||
LogThrow("Re-throwing exception");
|
||||
@@ -32,7 +33,7 @@ Rethrow()
|
||||
}
|
||||
|
||||
template <class E, class... Args>
|
||||
[[noreturn]] inline void
|
||||
[[noreturn]] XRPL_NO_SANITIZE_ADDRESS inline void
|
||||
Throw(Args&&... args)
|
||||
{
|
||||
static_assert(std::is_convertible<E*, std::exception*>::value, "Exception must derive from std::exception.");
|
||||
|
||||
6
include/xrpl/basics/sanitizers.h
Normal file
6
include/xrpl/basics/sanitizers.h
Normal file
@@ -0,0 +1,6 @@
|
||||
// Helper to disable ASan/HwASan for specific functions
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define XRPL_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address", "hwaddress")))
|
||||
#else
|
||||
#define XRPL_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/conditions/detail/utils.h>
|
||||
|
||||
#include <xrpl/basics/Buffer.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/conditions/Condition.h>
|
||||
|
||||
#include <xrpl/basics/Buffer.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/Condition.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace cryptoconditions {
|
||||
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/conditions/Condition.h>
|
||||
#include <xrpld/conditions/Fulfillment.h>
|
||||
#include <xrpld/conditions/detail/error.h>
|
||||
|
||||
#include <xrpl/basics/Buffer.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/Condition.h>
|
||||
#include <xrpl/conditions/Fulfillment.h>
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
#include <xrpl/protocol/digest.h>
|
||||
|
||||
#include <memory>
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/conditions/detail/error.h>
|
||||
|
||||
#include <xrpl/basics/Buffer.h>
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
@@ -251,7 +251,4 @@ private:
|
||||
beast::aged_unordered_map<uint256, Entry, Stopwatch::clock_type, hardened_hash<strong_hash>> suppressionMap_;
|
||||
};
|
||||
|
||||
HashRouter::Setup
|
||||
setup_HashRouter(Config const&);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <xrpl/basics/TaggedCache.h>
|
||||
#include <xrpl/ledger/CachedSLEs.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
// Forward declarations
|
||||
@@ -18,6 +20,10 @@ namespace perf {
|
||||
class PerfLog;
|
||||
}
|
||||
|
||||
// This is temporary until we migrate all code to use ServiceRegistry.
|
||||
class Application;
|
||||
|
||||
// Forward declarations
|
||||
class AcceptedLedger;
|
||||
class AmendmentTable;
|
||||
class Cluster;
|
||||
@@ -194,6 +200,31 @@ public:
|
||||
|
||||
virtual perf::PerfLog&
|
||||
getPerfLog() = 0;
|
||||
|
||||
// Configuration and state
|
||||
virtual bool
|
||||
isStopping() const = 0;
|
||||
|
||||
virtual beast::Journal
|
||||
journal(std::string const& name) = 0;
|
||||
|
||||
virtual boost::asio::io_context&
|
||||
getIOContext() = 0;
|
||||
|
||||
virtual Logs&
|
||||
logs() = 0;
|
||||
|
||||
virtual std::optional<uint256> const&
|
||||
trapTxID() const = 0;
|
||||
|
||||
/** Retrieve the "wallet database" */
|
||||
virtual DatabaseCon&
|
||||
getWalletDB() = 0;
|
||||
|
||||
// Temporary: Get the underlying Application for functions that haven't
|
||||
// been migrated yet. This should be removed once all code is migrated.
|
||||
virtual Application&
|
||||
app() = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
16
include/xrpl/core/StartUpType.h
Normal file
16
include/xrpl/core/StartUpType.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum class StartUpType { FRESH, NORMAL, LOAD, LOAD_FILE, REPLAY, NETWORK };
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, StartUpType const& type)
|
||||
{
|
||||
return os << static_cast<std::underlying_type_t<StartUpType>>(type);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,15 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/ledger/Ledger.h>
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class Logs;
|
||||
|
||||
/**
|
||||
A transaction that is in a closed ledger.
|
||||
|
||||
@@ -48,18 +48,6 @@ public:
|
||||
deliver_ = amount;
|
||||
}
|
||||
|
||||
void
|
||||
setGasUsed(std::optional<std::uint32_t> const gasUsed)
|
||||
{
|
||||
gasUsed_ = gasUsed;
|
||||
}
|
||||
|
||||
void
|
||||
setWasmReturnCode(std::int32_t const wasmReturnCode)
|
||||
{
|
||||
wasmReturnCode_ = wasmReturnCode;
|
||||
}
|
||||
|
||||
/** Get the number of modified entries
|
||||
*/
|
||||
std::size_t
|
||||
@@ -78,8 +66,6 @@ public:
|
||||
|
||||
private:
|
||||
std::optional<STAmount> deliver_;
|
||||
std::optional<std::uint32_t> gasUsed_;
|
||||
std::optional<std::int32_t> wasmReturnCode_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/rpc/InfoSub.h>
|
||||
|
||||
#include <xrpl/protocol/MultiApiJson.h>
|
||||
#include <xrpl/server/InfoSub.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
93
include/xrpl/ledger/OrderBookDB.h
Normal file
93
include/xrpl/ledger/OrderBookDB.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/AcceptedLedgerTx.h>
|
||||
#include <xrpl/ledger/BookListeners.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/MultiApiJson.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/** Tracks order books in the ledger.
|
||||
|
||||
This interface provides access to order book information, including:
|
||||
- Which order books exist in the ledger
|
||||
- Querying order books by issue
|
||||
- Managing order book subscriptions
|
||||
|
||||
The order book database is updated as ledgers are accepted and provides
|
||||
efficient lookup of order book information for pathfinding and client
|
||||
subscriptions.
|
||||
*/
|
||||
class OrderBookDB
|
||||
{
|
||||
public:
|
||||
virtual ~OrderBookDB() = default;
|
||||
|
||||
/** Initialize or update the order book database with a new ledger.
|
||||
|
||||
This method should be called when a new ledger is accepted to update
|
||||
the order book database with the current state of all order books.
|
||||
|
||||
@param ledger The ledger to scan for order books
|
||||
*/
|
||||
virtual void
|
||||
setup(std::shared_ptr<ReadView const> const& ledger) = 0;
|
||||
|
||||
/** Add an order book to track.
|
||||
|
||||
@param book The order book to add
|
||||
*/
|
||||
virtual void
|
||||
addOrderBook(Book const& book) = 0;
|
||||
|
||||
/** Get all order books that want a specific issue.
|
||||
|
||||
Returns a list of all order books where the taker pays the specified
|
||||
issue. This is useful for pathfinding to find all possible next hops
|
||||
from a given currency.
|
||||
|
||||
@param issue The issue to search for
|
||||
@param domain Optional domain restriction for the order book
|
||||
@return Vector of books that want this issue
|
||||
*/
|
||||
virtual std::vector<Book>
|
||||
getBooksByTakerPays(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
|
||||
|
||||
/** Get the count of order books that want a specific issue.
|
||||
|
||||
@param issue The issue to search for
|
||||
@param domain Optional domain restriction for the order book
|
||||
@return Number of books that want this issue
|
||||
*/
|
||||
virtual int
|
||||
getBookSize(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
|
||||
|
||||
/** Check if an order book to XRP exists for the given issue.
|
||||
|
||||
@param issue The issue to check
|
||||
@param domain Optional domain restriction for the order book
|
||||
@return true if a book from this issue to XRP exists
|
||||
*/
|
||||
virtual bool
|
||||
isBookToXRP(Issue const& issue, std::optional<Domain> domain = std::nullopt) = 0;
|
||||
|
||||
virtual void
|
||||
processTxn(
|
||||
std::shared_ptr<ReadView const> const& ledger,
|
||||
AcceptedLedgerTx const& alTx,
|
||||
MultiApiJson const& jvObj) = 0;
|
||||
|
||||
virtual BookListeners::pointer
|
||||
getBookListeners(Book const&) = 0;
|
||||
virtual BookListeners::pointer
|
||||
makeBookListeners(Book const&) = 0;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -52,8 +52,6 @@ public:
|
||||
TER ter,
|
||||
std::optional<STAmount> const& deliver,
|
||||
std::optional<uint256 const> const& parentBatchId,
|
||||
std::optional<std::uint32_t> const& gasUsed,
|
||||
std::optional<std::int32_t> const& wasmReturnCode,
|
||||
bool isDryRun,
|
||||
beast::Journal j);
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
constexpr std::uint32_t MICRO_DROPS_PER_DROP{1'000'000};
|
||||
|
||||
/** Reflects the fee settings for a particular ledger.
|
||||
|
||||
The fees are always the same for any transactions applied
|
||||
@@ -13,12 +11,9 @@ constexpr std::uint32_t MICRO_DROPS_PER_DROP{1'000'000};
|
||||
*/
|
||||
struct Fees
|
||||
{
|
||||
XRPAmount base{0}; // Reference tx cost (drops)
|
||||
XRPAmount reserve{0}; // Reserve base (drops)
|
||||
XRPAmount increment{0}; // Reserve increment (drops)
|
||||
std::uint32_t extensionComputeLimit{0}; // Extension compute limit (instructions)
|
||||
std::uint32_t extensionSizeLimit{0}; // Extension size limit (bytes)
|
||||
std::uint32_t gasPrice{0}; // price of WASM gas (micro-drops)
|
||||
XRPAmount base{0}; // Reference tx cost (drops)
|
||||
XRPAmount reserve{0}; // Reserve base (drops)
|
||||
XRPAmount increment{0}; // Reserve increment (drops)
|
||||
|
||||
explicit Fees() = default;
|
||||
Fees(Fees const&) = default;
|
||||
|
||||
@@ -205,12 +205,6 @@ page(Keylet const& root, std::uint64_t index = 0) noexcept
|
||||
Keylet
|
||||
escrow(AccountID const& src, std::uint32_t seq) noexcept;
|
||||
|
||||
inline Keylet
|
||||
escrow(uint256 const& key) noexcept
|
||||
{
|
||||
return {ltESCROW, key};
|
||||
}
|
||||
|
||||
/** A PaymentChannel */
|
||||
Keylet
|
||||
payChan(AccountID const& src, AccountID const& dst, std::uint32_t seq) noexcept;
|
||||
|
||||
22
include/xrpl/protocol/LedgerShortcut.h
Normal file
22
include/xrpl/protocol/LedgerShortcut.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
/**
|
||||
* @brief Enumeration of ledger shortcuts for specifying which ledger to use.
|
||||
*
|
||||
* These shortcuts provide a convenient way to reference commonly used ledgers
|
||||
* without needing to specify their exact hash or sequence number.
|
||||
*/
|
||||
enum class LedgerShortcut {
|
||||
/** The current working ledger (open, not yet closed) */
|
||||
Current,
|
||||
|
||||
/** The most recently closed ledger (may not be validated) */
|
||||
Closed,
|
||||
|
||||
/** The most recently validated ledger */
|
||||
Validated
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -250,13 +250,6 @@ std::uint8_t constexpr vaultMaximumIOUScale = 18;
|
||||
* another vault; counted from 0 */
|
||||
std::uint8_t constexpr maxAssetCheckDepth = 5;
|
||||
|
||||
/** The maximum length of a Data field in Escrow object that can be updated by
|
||||
* Wasm code */
|
||||
std::size_t constexpr maxWasmDataLength = 4 * 1024;
|
||||
|
||||
/** The maximum length of a parameters passed from Wasm code*/
|
||||
std::size_t constexpr maxWasmParamLength = 1024;
|
||||
|
||||
/** A ledger index. */
|
||||
using LedgerIndex = std::uint32_t;
|
||||
|
||||
|
||||
@@ -121,9 +121,6 @@ enum TEMcodes : TERUnderlyingType {
|
||||
temARRAY_TOO_LARGE,
|
||||
temBAD_TRANSFER_FEE,
|
||||
temINVALID_INNER_BATCH,
|
||||
|
||||
temBAD_WASM,
|
||||
temTEMP_DISABLED,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -168,8 +165,6 @@ enum TEFcodes : TERUnderlyingType {
|
||||
tefNO_TICKET,
|
||||
tefNFTOKEN_IS_NOT_TRANSFERABLE,
|
||||
tefINVALID_LEDGER_FIX_TYPE,
|
||||
tefNO_WASM,
|
||||
tefWASM_FIELD_NOT_INCLUDED,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -351,7 +346,6 @@ enum TECcodes : TERUnderlyingType {
|
||||
// backward compatibility with historical data on non-prod networks, can be
|
||||
// reclaimed after those networks reset.
|
||||
tecNO_DELEGATE_PERMISSION = 198,
|
||||
tecWASM_REJECTED = 199,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -84,12 +84,6 @@ public:
|
||||
|
||||
if (obj.isFieldPresent(sfParentBatchID))
|
||||
parentBatchID_ = obj.getFieldH256(sfParentBatchID);
|
||||
|
||||
if (obj.isFieldPresent(sfGasUsed))
|
||||
gasUsed_ = obj.getFieldU32(sfGasUsed);
|
||||
|
||||
if (obj.isFieldPresent(sfWasmReturnCode))
|
||||
wasmReturnCode_ = obj.getFieldI32(sfWasmReturnCode);
|
||||
}
|
||||
|
||||
std::optional<STAmount> const&
|
||||
@@ -110,30 +104,6 @@ public:
|
||||
parentBatchID_ = id;
|
||||
}
|
||||
|
||||
void
|
||||
setGasUsed(std::optional<std::uint32_t> const gasUsed)
|
||||
{
|
||||
gasUsed_ = gasUsed;
|
||||
}
|
||||
|
||||
std::optional<std::uint32_t> const&
|
||||
getGasUsed() const
|
||||
{
|
||||
return gasUsed_;
|
||||
}
|
||||
|
||||
void
|
||||
setWasmReturnCode(std::optional<std::int32_t> const wasmReturnCode)
|
||||
{
|
||||
wasmReturnCode_ = wasmReturnCode;
|
||||
}
|
||||
|
||||
std::optional<std::int32_t> const&
|
||||
getWasmReturnCode() const
|
||||
{
|
||||
return wasmReturnCode_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint256 transactionID_;
|
||||
std::uint32_t ledgerSeq_;
|
||||
@@ -142,8 +112,6 @@ private:
|
||||
|
||||
std::optional<STAmount> deliveredAmount_;
|
||||
std::optional<uint256> parentBatchID_;
|
||||
std::optional<std::uint32_t> gasUsed_;
|
||||
std::optional<std::int32_t> wasmReturnCode_;
|
||||
|
||||
STArray nodes_;
|
||||
};
|
||||
|
||||
7
include/xrpl/protocol/TxSearched.h
Normal file
7
include/xrpl/protocol/TxSearched.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
enum class TxSearched { all, some, unknown };
|
||||
|
||||
}
|
||||
@@ -15,9 +15,7 @@
|
||||
|
||||
// Add new amendments to the top of this list.
|
||||
// Keep it sorted in reverse chronological order.
|
||||
|
||||
XRPL_FEATURE(SmartEscrow, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (ExpiredNFTokenOfferRemoval, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(LendingProtocol, Supported::yes, VoteBehavior::DefaultNo)
|
||||
@@ -34,8 +32,9 @@ XRPL_FIX (EnforceNFTokenTrustlineV2, Supported::yes, VoteBehavior::DefaultNo
|
||||
XRPL_FIX (AMMv1_3, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(SingleAssetVault, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo)
|
||||
// Check flags in Credential transactions
|
||||
XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FIX (FrozenLPTokenTransfer, Supported::yes, VoteBehavior::DefaultNo)
|
||||
XRPL_FEATURE(DeepFreeze, Supported::yes, VoteBehavior::DefaultNo)
|
||||
|
||||
@@ -302,11 +302,6 @@ LEDGER_ENTRY(ltFEE_SETTINGS, 0x0073, FeeSettings, fee, ({
|
||||
{sfBaseFeeDrops, soeOPTIONAL},
|
||||
{sfReserveBaseDrops, soeOPTIONAL},
|
||||
{sfReserveIncrementDrops, soeOPTIONAL},
|
||||
// Smart Escrow fields
|
||||
{sfExtensionComputeLimit, soeOPTIONAL},
|
||||
{sfExtensionSizeLimit, soeOPTIONAL},
|
||||
{sfGasPrice, soeOPTIONAL},
|
||||
|
||||
{sfPreviousTxnID, soeOPTIONAL},
|
||||
{sfPreviousTxnLgrSeq, soeOPTIONAL},
|
||||
}))
|
||||
@@ -337,8 +332,6 @@ LEDGER_ENTRY(ltESCROW, 0x0075, Escrow, escrow, ({
|
||||
{sfCondition, soeOPTIONAL},
|
||||
{sfCancelAfter, soeOPTIONAL},
|
||||
{sfFinishAfter, soeOPTIONAL},
|
||||
{sfFinishFunction, soeOPTIONAL},
|
||||
{sfData, soeOPTIONAL},
|
||||
{sfSourceTag, soeOPTIONAL},
|
||||
{sfDestinationTag, soeOPTIONAL},
|
||||
{sfOwnerNode, soeREQUIRED},
|
||||
@@ -585,7 +578,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
|
||||
// The unrounded true total value of the loan.
|
||||
//
|
||||
// - TrueTotalPrincipalOutstanding can be computed using the algorithm
|
||||
// in the xrpl::detail::loanPrincipalFromPeriodicPayment function.
|
||||
// in the ripple::detail::loanPrincipalFromPeriodicPayment function.
|
||||
//
|
||||
// - TrueTotalInterestOutstanding = TrueTotalLoanValue -
|
||||
// TrueTotalPrincipalOutstanding
|
||||
|
||||
@@ -114,11 +114,6 @@ TYPED_SFIELD(sfInterestRate, UINT32, 65) // 1/10 basis points (bi
|
||||
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)
|
||||
TYPED_SFIELD(sfExtensionComputeLimit, UINT32, 69)
|
||||
TYPED_SFIELD(sfExtensionSizeLimit, UINT32, 70)
|
||||
TYPED_SFIELD(sfGasPrice, UINT32, 71)
|
||||
TYPED_SFIELD(sfComputationAllowance, UINT32, 72)
|
||||
TYPED_SFIELD(sfGasUsed, UINT32, 73)
|
||||
|
||||
// 64-bit integers (common)
|
||||
TYPED_SFIELD(sfIndexNext, UINT64, 1)
|
||||
@@ -229,9 +224,8 @@ TYPED_SFIELD(sfTotalValueOutstanding, NUMBER, 15, SField::sMD_NeedsAsset
|
||||
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
|
||||
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17, SField::sMD_NeedsAsset | SField::sMD_Default)
|
||||
|
||||
// 32-bit signed (common)
|
||||
// int32
|
||||
TYPED_SFIELD(sfLoanScale, INT32, 1)
|
||||
TYPED_SFIELD(sfWasmReturnCode, INT32, 2)
|
||||
|
||||
// currency amount (common)
|
||||
TYPED_SFIELD(sfAmount, AMOUNT, 1)
|
||||
@@ -261,7 +255,7 @@ TYPED_SFIELD(sfBaseFeeDrops, AMOUNT, 22)
|
||||
TYPED_SFIELD(sfReserveBaseDrops, AMOUNT, 23)
|
||||
TYPED_SFIELD(sfReserveIncrementDrops, AMOUNT, 24)
|
||||
|
||||
// currency amount (more)
|
||||
// currency amount (AMM)
|
||||
TYPED_SFIELD(sfLPTokenOut, AMOUNT, 25)
|
||||
TYPED_SFIELD(sfLPTokenIn, AMOUNT, 26)
|
||||
TYPED_SFIELD(sfEPrice, AMOUNT, 27)
|
||||
@@ -303,7 +297,6 @@ TYPED_SFIELD(sfAssetClass, VL, 28)
|
||||
TYPED_SFIELD(sfProvider, VL, 29)
|
||||
TYPED_SFIELD(sfMPTokenMetadata, VL, 30)
|
||||
TYPED_SFIELD(sfCredentialType, VL, 31)
|
||||
TYPED_SFIELD(sfFinishFunction, VL, 32)
|
||||
|
||||
// account (common)
|
||||
TYPED_SFIELD(sfAccount, ACCOUNT, 1)
|
||||
|
||||
@@ -50,13 +50,11 @@ TRANSACTION(ttESCROW_CREATE, 1, EscrowCreate,
|
||||
noPriv,
|
||||
({
|
||||
{sfDestination, soeREQUIRED},
|
||||
{sfDestinationTag, soeOPTIONAL},
|
||||
{sfAmount, soeREQUIRED, soeMPTSupported},
|
||||
{sfCondition, soeOPTIONAL},
|
||||
{sfCancelAfter, soeOPTIONAL},
|
||||
{sfFinishAfter, soeOPTIONAL},
|
||||
{sfFinishFunction, soeOPTIONAL},
|
||||
{sfData, soeOPTIONAL},
|
||||
{sfDestinationTag, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This transaction type completes an existing escrow. */
|
||||
@@ -70,7 +68,6 @@ TRANSACTION(ttESCROW_FINISH, 2, EscrowFinish,
|
||||
{sfFulfillment, soeOPTIONAL},
|
||||
{sfCondition, soeOPTIONAL},
|
||||
{sfCredentialIDs, soeOPTIONAL},
|
||||
{sfComputationAllowance, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
|
||||
@@ -1095,10 +1092,6 @@ TRANSACTION(ttFEE, 101, SetFee,
|
||||
{sfBaseFeeDrops, soeOPTIONAL},
|
||||
{sfReserveBaseDrops, soeOPTIONAL},
|
||||
{sfReserveIncrementDrops, soeOPTIONAL},
|
||||
// Smart Escrow fields
|
||||
{sfExtensionComputeLimit, soeOPTIONAL},
|
||||
{sfExtensionSizeLimit, soeOPTIONAL},
|
||||
{sfGasPrice, soeOPTIONAL},
|
||||
}))
|
||||
|
||||
/** This system-generated transaction type is used to update the network's negative UNL
|
||||
|
||||
@@ -254,9 +254,6 @@ JSS(expected_date_UTC); // out: any (warnings)
|
||||
JSS(expected_ledger_size); // out: TxQ
|
||||
JSS(expiration); // out: AccountOffers, AccountChannels,
|
||||
// ValidatorList, amm_info
|
||||
JSS(extension_compute); // out: NetworkOps
|
||||
JSS(extension_size); // out: NetworkOps
|
||||
JSS(gas_price); // out: NetworkOps
|
||||
JSS(fail_hard); // in: Sign, Submit
|
||||
JSS(failed); // out: InboundLedger
|
||||
JSS(feature); // in: Feature
|
||||
@@ -711,11 +708,11 @@ JSS(write_load); // out: GetCounts
|
||||
#pragma push_macro("LEDGER_ENTRY_DUPLICATE")
|
||||
#undef LEDGER_ENTRY_DUPLICATE
|
||||
|
||||
#define LEDGER_ENTRY(tag, value, name, rpcName, fields) \
|
||||
JSS(name); \
|
||||
#define LEDGER_ENTRY(tag, value, name, rpcName, ...) \
|
||||
JSS(name); \
|
||||
JSS(rpcName);
|
||||
|
||||
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, fields) JSS(rpcName);
|
||||
#define LEDGER_ENTRY_DUPLICATE(tag, value, name, rpcName, ...) JSS(rpcName);
|
||||
|
||||
#include <xrpl/protocol/detail/ledger_entries.macro>
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/main/DBInit.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/core/PerfLog.h>
|
||||
#include <xrpl/core/StartUpType.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
@@ -68,7 +67,7 @@ public:
|
||||
{
|
||||
explicit Setup() = default;
|
||||
|
||||
Config::StartUpType startUp = Config::NORMAL;
|
||||
StartUpType startUp = StartUpType::NORMAL;
|
||||
bool standAlone = false;
|
||||
boost::filesystem::path dataDir;
|
||||
// Indicates whether or not to return the `globalPragma`
|
||||
@@ -105,8 +104,8 @@ public:
|
||||
beast::Journal journal)
|
||||
// Use temporary files or regular DB files?
|
||||
: DatabaseCon(
|
||||
setup.standAlone && setup.startUp != Config::LOAD && setup.startUp != Config::LOAD_FILE &&
|
||||
setup.startUp != Config::REPLAY
|
||||
setup.standAlone && setup.startUp != StartUpType::LOAD && setup.startUp != StartUpType::LOAD_FILE &&
|
||||
setup.startUp != StartUpType::REPLAY
|
||||
? ""
|
||||
: (setup.dataDir / dbName),
|
||||
setup.commonPragma(),
|
||||
@@ -229,7 +228,4 @@ private:
|
||||
std::shared_ptr<Checkpointer>
|
||||
checkpointerFromId(std::uintptr_t id);
|
||||
|
||||
DatabaseCon::Setup
|
||||
setup_DatabaseCon(Config const& c, std::optional<beast::Journal> j = std::nullopt);
|
||||
|
||||
} // namespace xrpl
|
||||
475
include/xrpl/rdb/RelationalDatabase.h
Normal file
475
include/xrpl/rdb/RelationalDatabase.h
Normal file
@@ -0,0 +1,475 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/RangeSet.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/LedgerShortcut.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/TxSearched.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class Transaction;
|
||||
class Ledger;
|
||||
|
||||
struct LedgerHashPair
|
||||
{
|
||||
uint256 ledgerHash;
|
||||
uint256 parentHash;
|
||||
};
|
||||
|
||||
struct LedgerRange
|
||||
{
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
};
|
||||
|
||||
class RelationalDatabase
|
||||
{
|
||||
public:
|
||||
struct CountMinMax
|
||||
{
|
||||
std::size_t numberOfRows;
|
||||
LedgerIndex minLedgerSequence;
|
||||
LedgerIndex maxLedgerSequence;
|
||||
};
|
||||
|
||||
struct AccountTxMarker
|
||||
{
|
||||
std::uint32_t ledgerSeq = 0;
|
||||
std::uint32_t txnSeq = 0;
|
||||
};
|
||||
|
||||
struct AccountTxOptions
|
||||
{
|
||||
AccountID const& account;
|
||||
std::uint32_t minLedger;
|
||||
std::uint32_t maxLedger;
|
||||
std::uint32_t offset;
|
||||
std::uint32_t limit;
|
||||
bool bUnlimited;
|
||||
};
|
||||
|
||||
struct AccountTxPageOptions
|
||||
{
|
||||
AccountID const& account;
|
||||
std::uint32_t minLedger;
|
||||
std::uint32_t maxLedger;
|
||||
std::optional<AccountTxMarker> marker;
|
||||
std::uint32_t limit;
|
||||
bool bAdmin;
|
||||
};
|
||||
|
||||
using AccountTx = std::pair<std::shared_ptr<Transaction>, std::shared_ptr<TxMeta>>;
|
||||
using AccountTxs = std::vector<AccountTx>;
|
||||
using txnMetaLedgerType = std::tuple<Blob, Blob, std::uint32_t>;
|
||||
using MetaTxsList = std::vector<txnMetaLedgerType>;
|
||||
|
||||
using LedgerSequence = uint32_t;
|
||||
using LedgerHash = uint256;
|
||||
using LedgerSpecifier = std::variant<LedgerRange, LedgerShortcut, LedgerSequence, LedgerHash>;
|
||||
|
||||
struct AccountTxArgs
|
||||
{
|
||||
AccountID account;
|
||||
std::optional<LedgerSpecifier> ledger;
|
||||
bool binary = false;
|
||||
bool forward = false;
|
||||
uint32_t limit = 0;
|
||||
std::optional<AccountTxMarker> marker;
|
||||
};
|
||||
|
||||
struct AccountTxResult
|
||||
{
|
||||
std::variant<AccountTxs, MetaTxsList> transactions;
|
||||
LedgerRange ledgerRange;
|
||||
uint32_t limit;
|
||||
std::optional<AccountTxMarker> marker;
|
||||
};
|
||||
|
||||
virtual ~RelationalDatabase() = default;
|
||||
|
||||
/**
|
||||
* @brief getMinLedgerSeq Returns the minimum ledger sequence in the Ledgers
|
||||
* table.
|
||||
* @return Ledger sequence or no value if no ledgers exist.
|
||||
*/
|
||||
virtual std::optional<LedgerIndex>
|
||||
getMinLedgerSeq() = 0;
|
||||
|
||||
/**
|
||||
* @brief getMaxLedgerSeq Returns the maximum ledger sequence in the Ledgers
|
||||
* table.
|
||||
* @return Ledger sequence or none if no ledgers exist.
|
||||
*/
|
||||
virtual std::optional<LedgerIndex>
|
||||
getMaxLedgerSeq() = 0;
|
||||
|
||||
/**
|
||||
* @brief getLedgerInfoByIndex Returns a ledger by its sequence.
|
||||
* @param ledgerSeq Ledger sequence.
|
||||
* @return The ledger if found, otherwise no value.
|
||||
*/
|
||||
virtual std::optional<LedgerHeader>
|
||||
getLedgerInfoByIndex(LedgerIndex ledgerSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief getNewestLedgerInfo Returns the info of the newest saved ledger.
|
||||
* @return Ledger info if found, otherwise no value.
|
||||
*/
|
||||
virtual std::optional<LedgerHeader>
|
||||
getNewestLedgerInfo() = 0;
|
||||
|
||||
/**
|
||||
* @brief getLedgerInfoByHash Returns the info of the ledger with given
|
||||
* hash.
|
||||
* @param ledgerHash Hash of the ledger.
|
||||
* @return Ledger if found, otherwise no value.
|
||||
*/
|
||||
virtual std::optional<LedgerHeader>
|
||||
getLedgerInfoByHash(uint256 const& ledgerHash) = 0;
|
||||
|
||||
/**
|
||||
* @brief getHashByIndex Returns the hash of the ledger with the given
|
||||
* sequence.
|
||||
* @param ledgerIndex Ledger sequence.
|
||||
* @return Hash of the ledger.
|
||||
*/
|
||||
virtual uint256
|
||||
getHashByIndex(LedgerIndex ledgerIndex) = 0;
|
||||
|
||||
/**
|
||||
* @brief getHashesByIndex Returns the hashes of the ledger and its parent
|
||||
* as specified by the ledgerIndex.
|
||||
* @param ledgerIndex Ledger sequence.
|
||||
* @return Struct LedgerHashPair which contains hashes of the ledger and
|
||||
* its parent.
|
||||
*/
|
||||
virtual std::optional<LedgerHashPair>
|
||||
getHashesByIndex(LedgerIndex ledgerIndex) = 0;
|
||||
|
||||
/**
|
||||
* @brief getHashesByIndex Returns hashes of each ledger and its parent for
|
||||
* all ledgers within the provided range.
|
||||
* @param minSeq Minimum ledger sequence.
|
||||
* @param maxSeq Maximum ledger sequence.
|
||||
* @return Container that maps the sequence number of a found ledger to the
|
||||
* struct LedgerHashPair which contains the hashes of the ledger and
|
||||
* its parent.
|
||||
*/
|
||||
virtual std::map<LedgerIndex, LedgerHashPair>
|
||||
getHashesByIndex(LedgerIndex minSeq, LedgerIndex maxSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief getTxHistory Returns the 20 most recent transactions starting from
|
||||
* the given number.
|
||||
* @param startIndex First number of returned entry.
|
||||
* @return Vector of shared pointers to transactions sorted in
|
||||
* descending order by ledger sequence.
|
||||
*/
|
||||
virtual std::vector<std::shared_ptr<Transaction>>
|
||||
getTxHistory(LedgerIndex startIndex) = 0;
|
||||
|
||||
/**
|
||||
* @brief getTransactionsMinLedgerSeq Returns the minimum ledger sequence
|
||||
* stored in the Transactions table.
|
||||
* @return Ledger sequence or no value if no ledgers exist.
|
||||
*/
|
||||
virtual std::optional<LedgerIndex>
|
||||
getTransactionsMinLedgerSeq() = 0;
|
||||
|
||||
/**
|
||||
* @brief getAccountTransactionsMinLedgerSeq Returns the minimum ledger
|
||||
* sequence stored in the AccountTransactions table.
|
||||
* @return Ledger sequence or no value if no ledgers exist.
|
||||
*/
|
||||
virtual std::optional<LedgerIndex>
|
||||
getAccountTransactionsMinLedgerSeq() = 0;
|
||||
|
||||
/**
|
||||
* @brief deleteTransactionByLedgerSeq Deletes transactions from the ledger
|
||||
* with the given sequence.
|
||||
* @param ledgerSeq Ledger sequence.
|
||||
*/
|
||||
virtual void
|
||||
deleteTransactionByLedgerSeq(LedgerIndex ledgerSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief deleteBeforeLedgerSeq Deletes all ledgers with a sequence number
|
||||
* less than or equal to the given ledger sequence.
|
||||
* @param ledgerSeq Ledger sequence.
|
||||
*/
|
||||
virtual void
|
||||
deleteBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief deleteTransactionsBeforeLedgerSeq Deletes all transactions with
|
||||
* a sequence number less than or equal to the given ledger
|
||||
* sequence.
|
||||
* @param ledgerSeq Ledger sequence.
|
||||
*/
|
||||
virtual void
|
||||
deleteTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief deleteAccountTransactionsBeforeLedgerSeq Deletes all account
|
||||
* transactions with a sequence number less than or equal to the
|
||||
* given ledger sequence.
|
||||
* @param ledgerSeq Ledger sequence.
|
||||
*/
|
||||
virtual void
|
||||
deleteAccountTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq) = 0;
|
||||
|
||||
/**
|
||||
* @brief getTransactionCount Returns the number of transactions.
|
||||
* @return Number of transactions.
|
||||
*/
|
||||
virtual std::size_t
|
||||
getTransactionCount() = 0;
|
||||
|
||||
/**
|
||||
* @brief getAccountTransactionCount Returns the number of account
|
||||
* transactions.
|
||||
* @return Number of account transactions.
|
||||
*/
|
||||
virtual std::size_t
|
||||
getAccountTransactionCount() = 0;
|
||||
|
||||
/**
|
||||
* @brief getLedgerCountMinMax Returns the minimum ledger sequence,
|
||||
* maximum ledger sequence and total number of saved ledgers.
|
||||
* @return Struct CountMinMax which contains the minimum sequence,
|
||||
* maximum sequence and number of ledgers.
|
||||
*/
|
||||
virtual struct CountMinMax
|
||||
getLedgerCountMinMax() = 0;
|
||||
|
||||
/**
|
||||
* @brief saveValidatedLedger Saves a ledger into the database.
|
||||
* @param ledger The ledger.
|
||||
* @param current True if the ledger is current.
|
||||
* @return True if saving was successful.
|
||||
*/
|
||||
virtual bool
|
||||
saveValidatedLedger(std::shared_ptr<Ledger const> const& ledger, bool current) = 0;
|
||||
|
||||
/**
|
||||
* @brief getLimitedOldestLedgerInfo Returns the info of the oldest ledger
|
||||
* whose sequence number is greater than or equal to the given
|
||||
* sequence number.
|
||||
* @param ledgerFirstIndex Minimum ledger sequence.
|
||||
* @return Ledger info if found, otherwise no value.
|
||||
*/
|
||||
virtual std::optional<LedgerHeader>
|
||||
getLimitedOldestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
|
||||
|
||||
/**
|
||||
* @brief getLimitedNewestLedgerInfo Returns the info of the newest ledger
|
||||
* whose sequence number is greater than or equal to the given
|
||||
* sequence number.
|
||||
* @param ledgerFirstIndex Minimum ledger sequence.
|
||||
* @return Ledger info if found, otherwise no value.
|
||||
*/
|
||||
virtual std::optional<LedgerHeader>
|
||||
getLimitedNewestLedgerInfo(LedgerIndex ledgerFirstIndex) = 0;
|
||||
|
||||
/**
|
||||
* @brief getOldestAccountTxs Returns the oldest transactions for the
|
||||
* account that matches the given criteria starting from the provided
|
||||
* offset.
|
||||
* @param options Struct AccountTxOptions which contains the criteria to
|
||||
* match: the account, ledger search range, the offset of the first
|
||||
* entry to return, the number of transactions to return, a flag if
|
||||
* this number is unlimited.
|
||||
* @return Vector of pairs of found transactions and their metadata
|
||||
* sorted in ascending order by account sequence.
|
||||
*/
|
||||
virtual AccountTxs
|
||||
getOldestAccountTxs(AccountTxOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief getNewestAccountTxs Returns the newest transactions for the
|
||||
* account that matches the given criteria starting from the provided
|
||||
* offset.
|
||||
* @param options Struct AccountTxOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the offset of the
|
||||
* first entry to return, the number of transactions to return, a
|
||||
* flag if this number unlimited.
|
||||
* @return Vector of pairs of found transactions and their metadata
|
||||
* sorted in descending order by account sequence.
|
||||
*/
|
||||
virtual AccountTxs
|
||||
getNewestAccountTxs(AccountTxOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief getOldestAccountTxsB Returns the oldest transactions in binary
|
||||
* form for the account that matches the given criteria starting from
|
||||
* the provided offset.
|
||||
* @param options Struct AccountTxOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the offset of the
|
||||
* first entry to return, the number of transactions to return, a
|
||||
* flag if this number unlimited.
|
||||
* @return Vector of tuples of found transactions, their metadata and
|
||||
* account sequences sorted in ascending order by account sequence.
|
||||
*/
|
||||
virtual MetaTxsList
|
||||
getOldestAccountTxsB(AccountTxOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief getNewestAccountTxsB Returns the newest transactions in binary
|
||||
* form for the account that matches the given criteria starting from
|
||||
* the provided offset.
|
||||
* @param options Struct AccountTxOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the offset of the
|
||||
* first entry to return, the number of transactions to return, a
|
||||
* flag if this number is unlimited.
|
||||
* @return Vector of tuples of found transactions, their metadata and
|
||||
* account sequences sorted in descending order by account
|
||||
* sequence.
|
||||
*/
|
||||
virtual MetaTxsList
|
||||
getNewestAccountTxsB(AccountTxOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief oldestAccountTxPage Returns the oldest transactions for the
|
||||
* account that matches the given criteria starting from the
|
||||
* provided marker.
|
||||
* @param options Struct AccountTxPageOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the marker of first
|
||||
* returned entry, the number of transactions to return, a flag if
|
||||
* this number is unlimited.
|
||||
* @return Vector of pairs of found transactions and their metadata
|
||||
* sorted in ascending order by account sequence and a marker
|
||||
* for the next search if the search was not finished.
|
||||
*/
|
||||
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
|
||||
oldestAccountTxPage(AccountTxPageOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief newestAccountTxPage Returns the newest transactions for the
|
||||
* account that matches the given criteria starting from the provided
|
||||
* marker.
|
||||
* @param options Struct AccountTxPageOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the marker of the
|
||||
* first returned entry, the number of transactions to return, a flag
|
||||
* if this number unlimited.
|
||||
* @return Vector of pairs of found transactions and their metadata
|
||||
* sorted in descending order by account sequence and a marker
|
||||
* for the next search if the search was not finished.
|
||||
*/
|
||||
virtual std::pair<AccountTxs, std::optional<AccountTxMarker>>
|
||||
newestAccountTxPage(AccountTxPageOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief oldestAccountTxPageB Returns the oldest transactions in binary
|
||||
* form for the account that matches the given criteria starting from
|
||||
* the provided marker.
|
||||
* @param options Struct AccountTxPageOptions which contains criteria to
|
||||
* match: the account, the ledger search range, the marker of the
|
||||
* first returned entry, the number of transactions to return, a flag
|
||||
* if this number unlimited.
|
||||
* @return Vector of tuples of found transactions, their metadata and
|
||||
* account sequences sorted in ascending order by account
|
||||
* sequence and a marker for the next search if the search was not
|
||||
* finished.
|
||||
*/
|
||||
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
|
||||
oldestAccountTxPageB(AccountTxPageOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief newestAccountTxPageB Returns the newest transactions in binary
|
||||
* form for the account that matches the given criteria starting from
|
||||
* the provided marker.
|
||||
* @param options Struct AccountTxPageOptions which contains the criteria to
|
||||
* match: the account, the ledger search range, the marker of the
|
||||
* first returned entry, the number of transactions to return, a flag
|
||||
* if this number is unlimited.
|
||||
* @return Vector of tuples of found transactions, their metadata and
|
||||
* account sequences sorted in descending order by account
|
||||
* sequence and a marker for the next search if the search was not
|
||||
* finished.
|
||||
*/
|
||||
virtual std::pair<MetaTxsList, std::optional<AccountTxMarker>>
|
||||
newestAccountTxPageB(AccountTxPageOptions const& options) = 0;
|
||||
|
||||
/**
|
||||
* @brief getTransaction Returns the transaction with the given hash. If a
|
||||
* range is provided but the transaction is not found, then check if
|
||||
* all ledgers in the range are present in the database.
|
||||
* @param id Hash of the transaction.
|
||||
* @param range Range of ledgers to check, if present.
|
||||
* @param ec Default error code value.
|
||||
* @return Transaction and its metadata if found, otherwise TxSearched::all
|
||||
* if a range is provided and all ledgers from the range are present
|
||||
* in the database, TxSearched::some if a range is provided and not
|
||||
* all ledgers are present, TxSearched::unknown if the range is not
|
||||
* provided or a deserializing error occurred. In the last case the
|
||||
* error code is returned via the ec parameter, in other cases the
|
||||
* default error code is not changed.
|
||||
*/
|
||||
virtual std::variant<AccountTx, TxSearched>
|
||||
getTransaction(uint256 const& id, std::optional<ClosedInterval<uint32_t>> const& range, error_code_i& ec) = 0;
|
||||
|
||||
/**
|
||||
* @brief getKBUsedAll Returns the amount of space used by all databases.
|
||||
* @return Space in kilobytes.
|
||||
*/
|
||||
virtual uint32_t
|
||||
getKBUsedAll() = 0;
|
||||
|
||||
/**
|
||||
* @brief getKBUsedLedger Returns the amount of space space used by the
|
||||
* ledger database.
|
||||
* @return Space in kilobytes.
|
||||
*/
|
||||
virtual uint32_t
|
||||
getKBUsedLedger() = 0;
|
||||
|
||||
/**
|
||||
* @brief getKBUsedTransaction Returns the amount of space used by the
|
||||
* transaction database.
|
||||
* @return Space in kilobytes.
|
||||
*/
|
||||
virtual uint32_t
|
||||
getKBUsedTransaction() = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes the ledger database
|
||||
*/
|
||||
virtual void
|
||||
closeLedgerDB() = 0;
|
||||
|
||||
/**
|
||||
* @brief Closes the transaction database
|
||||
*/
|
||||
virtual void
|
||||
closeTransactionDB() = 0;
|
||||
};
|
||||
|
||||
template <class T, class C>
|
||||
T
|
||||
rangeCheckedCast(C c)
|
||||
{
|
||||
if ((c > std::numeric_limits<T>::max()) || (!std::numeric_limits<T>::is_signed && c < 0) ||
|
||||
(std::numeric_limits<T>::is_signed && std::numeric_limits<C>::is_signed &&
|
||||
c < std::numeric_limits<T>::lowest()))
|
||||
{
|
||||
// This should never happen
|
||||
// LCOV_EXCL_START
|
||||
UNREACHABLE("xrpl::rangeCheckedCast : domain error");
|
||||
JLOG(debugLog().error()) << "rangeCheckedCast domain error:"
|
||||
<< " value = " << c << " min = " << std::numeric_limits<T>::lowest()
|
||||
<< " max: " << std::numeric_limits<T>::max();
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
return static_cast<T>(c);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
|
||||
#include <xrpl/basics/CountedObject.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/Book.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/resource/Consumer.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -132,6 +131,7 @@ public:
|
||||
|
||||
virtual bool
|
||||
subPeerStatus(ref ispListener) = 0;
|
||||
|
||||
virtual bool
|
||||
unsubPeerStatus(std::uint64_t uListener) = 0;
|
||||
virtual void
|
||||
@@ -1,13 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/consensus/RCLCxPeerPos.h>
|
||||
#include <xrpld/app/ledger/Ledger.h>
|
||||
#include <xrpld/rpc/InfoSub.h>
|
||||
|
||||
#include <xrpl/core/JobQueue.h>
|
||||
#include <xrpl/ledger/ReadView.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/protocol/STValidation.h>
|
||||
#include <xrpl/protocol/TER.h>
|
||||
#include <xrpl/protocol/messages.h>
|
||||
#include <xrpl/server/InfoSub.h>
|
||||
#include <xrpl/shamap/SHAMap.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
@@ -19,10 +18,13 @@ namespace xrpl {
|
||||
// Master operational handler, server sequencer, network tracker
|
||||
|
||||
class Peer;
|
||||
class STTx;
|
||||
class ReadView;
|
||||
class LedgerMaster;
|
||||
class Transaction;
|
||||
class ValidatorKeys;
|
||||
class CanonicalTXSet;
|
||||
class RCLCxPeerPos;
|
||||
|
||||
// This is the primary interface into the "client" portion of the program.
|
||||
// Code that wants to do normal operations on the network such as
|
||||
@@ -245,20 +247,4 @@ public:
|
||||
stateAccounting(Json::Value& obj) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<NetworkOPs>
|
||||
make_NetworkOPs(
|
||||
Application& app,
|
||||
NetworkOPs::clock_type& clock,
|
||||
bool standalone,
|
||||
std::size_t minPeerCount,
|
||||
bool start_valid,
|
||||
JobQueue& job_queue,
|
||||
LedgerMaster& ledgerMaster,
|
||||
ValidatorKeys const& validatorKeys,
|
||||
boost::asio::io_context& io_svc,
|
||||
beast::Journal journal,
|
||||
beast::insight::Collector::ptr const& collector);
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,10 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/ledger/Ledger.h>
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/peerfinder/detail/Store.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/overlay/PeerReservationTable.h>
|
||||
#include <xrpl/core/PeerReservationTable.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -254,7 +254,7 @@ Number::Guard::doRoundUp(
|
||||
}
|
||||
bringIntoRange(negative, mantissa, exponent, minMantissa);
|
||||
if (exponent > maxExponent)
|
||||
throw std::overflow_error(location);
|
||||
Throw<std::overflow_error>(std::string(location));
|
||||
}
|
||||
|
||||
template <UnsignedMantissa T>
|
||||
@@ -290,7 +290,7 @@ Number::Guard::doRound(rep& drops, std::string location)
|
||||
// or "(maxRep + 1) / 10", neither of which will round up when
|
||||
// converting to rep, though the latter might overflow _before_
|
||||
// rounding.
|
||||
throw std::overflow_error(location); // LCOV_EXCL_LINE
|
||||
Throw<std::overflow_error>(std::string(location)); // LCOV_EXCL_LINE
|
||||
}
|
||||
++drops;
|
||||
}
|
||||
@@ -925,73 +925,6 @@ power(Number const& f, unsigned n)
|
||||
return r;
|
||||
}
|
||||
|
||||
// Series expansion method approximation of ln(x)
|
||||
static Number
|
||||
ln(Number const& x, int iterations = 50)
|
||||
{
|
||||
static Number const N0(0);
|
||||
static Number const N2(2, 0);
|
||||
static Number const N05(5, -1);
|
||||
static Number const LN2(693'147'180'559'945'309ll, -18);
|
||||
|
||||
if (x <= 0)
|
||||
throw std::runtime_error("Not a positive value");
|
||||
else if (x == 1)
|
||||
return N0;
|
||||
|
||||
int exponent = 0;
|
||||
Number mantissa = x;
|
||||
|
||||
while (mantissa >= N2)
|
||||
{
|
||||
mantissa /= 2;
|
||||
exponent += 1;
|
||||
}
|
||||
while (mantissa < N05)
|
||||
{
|
||||
mantissa *= 2;
|
||||
exponent -= 1;
|
||||
}
|
||||
|
||||
Number z = (mantissa - 1) / (mantissa + 1);
|
||||
Number const zz = z * z;
|
||||
Number sum;
|
||||
|
||||
for (int i = 1; i <= iterations; ++i)
|
||||
{
|
||||
sum = sum + z / (2 * i - 1);
|
||||
z = z * zz;
|
||||
}
|
||||
|
||||
return 2 * sum + exponent * LN2;
|
||||
}
|
||||
|
||||
Number
|
||||
log10(Number const& x, int iterations)
|
||||
{
|
||||
static Number const N0(0);
|
||||
static Number const LN10(2'302'585'092'994'046ll, -15);
|
||||
|
||||
if (x <= 0)
|
||||
throw std::runtime_error("Not a positive value");
|
||||
else if (x == 1)
|
||||
return N0;
|
||||
|
||||
if (x <= Number(10))
|
||||
{
|
||||
auto const r = ln(x, iterations) / LN10;
|
||||
return r;
|
||||
}
|
||||
|
||||
// (1 <= normalX < 10)
|
||||
// ln(x) = ln(normalX * 10^norm) = ln(normalX) + norm * ln(10)
|
||||
int diffExp = 15 + x.exponent();
|
||||
Number const normalX = x / Number(1, diffExp);
|
||||
auto const lnX = ln(normalX, iterations) + diffExp * LN10;
|
||||
auto const lgX = lnX / LN10;
|
||||
return lgX;
|
||||
}
|
||||
|
||||
// Returns f^(1/d)
|
||||
// Uses Newton–Raphson iterations until the result stops changing
|
||||
// to find the non-negative root of the polynomial g(x) = x^d - f
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <xrpld/conditions/Condition.h>
|
||||
#include <xrpld/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpld/conditions/detail/utils.h>
|
||||
#include <xrpl/conditions/Condition.h>
|
||||
#include <xrpl/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace cryptoconditions {
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <xrpld/conditions/Condition.h>
|
||||
#include <xrpld/conditions/Fulfillment.h>
|
||||
#include <xrpld/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpld/conditions/detail/utils.h>
|
||||
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/conditions/Condition.h>
|
||||
#include <xrpl/conditions/Fulfillment.h>
|
||||
#include <xrpl/conditions/detail/PreimageSha256.h>
|
||||
#include <xrpl/conditions/detail/utils.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace cryptoconditions {
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <xrpld/conditions/detail/error.h>
|
||||
|
||||
#include <xrpl/basics/safe_cast.h>
|
||||
#include <xrpl/conditions/detail/error.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <xrpld/app/misc/HashRouter.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpl/core/HashRouter.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -108,38 +107,4 @@ HashRouter::shouldRelay(uint256 const& key) -> std::optional<std::set<PeerShortI
|
||||
return s.releasePeerSet();
|
||||
}
|
||||
|
||||
HashRouter::Setup
|
||||
setup_HashRouter(Config const& config)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
HashRouter::Setup setup;
|
||||
auto const& section = config.section("hashrouter");
|
||||
|
||||
std::int32_t tmp;
|
||||
|
||||
if (set(tmp, "hold_time", section))
|
||||
{
|
||||
if (tmp < 12)
|
||||
Throw<std::runtime_error>(
|
||||
"HashRouter hold time must be at least 12 seconds (the "
|
||||
"approximate validation time for three ledgers).");
|
||||
setup.holdTime = seconds(tmp);
|
||||
}
|
||||
if (set(tmp, "relay_time", section))
|
||||
{
|
||||
if (tmp < 8)
|
||||
Throw<std::runtime_error>(
|
||||
"HashRouter relay time must be at least 8 seconds (the "
|
||||
"approximate validation time for two ledgers).");
|
||||
setup.relayTime = seconds(tmp);
|
||||
}
|
||||
if (setup.relayTime > setup.holdTime)
|
||||
{
|
||||
Throw<std::runtime_error>("HashRouter relay time must be less than or equal to hold time");
|
||||
}
|
||||
|
||||
return setup;
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <xrpld/app/ledger/AcceptedLedgerTx.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/StringUtilities.h>
|
||||
#include <xrpl/ledger/AcceptedLedgerTx.h>
|
||||
#include <xrpl/ledger/View.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
@@ -89,8 +89,6 @@ ApplyStateTable::apply(
|
||||
TER ter,
|
||||
std::optional<STAmount> const& deliver,
|
||||
std::optional<uint256 const> const& parentBatchId,
|
||||
std::optional<std::uint32_t> const& gasUsed,
|
||||
std::optional<std::int32_t> const& wasmReturnCode,
|
||||
bool isDryRun,
|
||||
beast::Journal j)
|
||||
{
|
||||
@@ -105,8 +103,6 @@ ApplyStateTable::apply(
|
||||
|
||||
meta.setDeliveredAmount(deliver);
|
||||
meta.setParentBatchID(parentBatchId);
|
||||
meta.setGasUsed(gasUsed);
|
||||
meta.setWasmReturnCode(wasmReturnCode);
|
||||
|
||||
Mods newMod;
|
||||
for (auto& item : items_)
|
||||
|
||||
@@ -15,7 +15,7 @@ ApplyViewImpl::apply(
|
||||
bool isDryRun,
|
||||
beast::Journal j)
|
||||
{
|
||||
return items_.apply(to, tx, ter, deliver_, parentBatchId, gasUsed_, wasmReturnCode_, isDryRun, j);
|
||||
return items_.apply(to, tx, ter, deliver_, parentBatchId, isDryRun, j);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <xrpld/app/ledger/OrderBookDB.h>
|
||||
#include <xrpl/ledger/BookListeners.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -58,10 +58,6 @@ STValidation::validationFormat()
|
||||
{sfBaseFeeDrops, soeOPTIONAL},
|
||||
{sfReserveBaseDrops, soeOPTIONAL},
|
||||
{sfReserveIncrementDrops, soeOPTIONAL},
|
||||
// featureSmartEscrow
|
||||
{sfExtensionComputeLimit, soeOPTIONAL},
|
||||
{sfExtensionSizeLimit, soeOPTIONAL},
|
||||
{sfGasPrice, soeOPTIONAL},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ transResults()
|
||||
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
|
||||
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(tecWASM_REJECTED, "The custom WASM code that was run rejected your transaction."),
|
||||
|
||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||
@@ -130,8 +129,6 @@ transResults()
|
||||
MAKE_ERROR(tefNO_TICKET, "Ticket is not in ledger."),
|
||||
MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."),
|
||||
MAKE_ERROR(tefINVALID_LEDGER_FIX_TYPE, "The LedgerFixType field has an invalid value."),
|
||||
MAKE_ERROR(tefNO_WASM, "There is no WASM code to run, but a WASM-specific field was included."),
|
||||
MAKE_ERROR(tefWASM_FIELD_NOT_INCLUDED, "WASM code requires a field to be included that was not included."),
|
||||
|
||||
MAKE_ERROR(telLOCAL_ERROR, "Local failure."),
|
||||
MAKE_ERROR(telBAD_DOMAIN, "Domain too long."),
|
||||
@@ -201,8 +198,6 @@ transResults()
|
||||
MAKE_ERROR(temARRAY_TOO_LARGE, "Malformed: Array is too large."),
|
||||
MAKE_ERROR(temBAD_TRANSFER_FEE, "Malformed: Transfer fee is outside valid range."),
|
||||
MAKE_ERROR(temINVALID_INNER_BATCH, "Malformed: Invalid inner batch transaction."),
|
||||
MAKE_ERROR(temBAD_WASM, "Malformed: Provided WASM code is invalid."),
|
||||
MAKE_ERROR(temTEMP_DISABLED, "The transaction requires logic that is currently temporarily disabled."),
|
||||
|
||||
MAKE_ERROR(terRETRY, "Retry transaction."),
|
||||
MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."),
|
||||
|
||||
@@ -190,12 +190,6 @@ TxMeta::getAsObject() const
|
||||
if (parentBatchID_.has_value())
|
||||
metaData.setFieldH256(sfParentBatchID, *parentBatchID_);
|
||||
|
||||
if (gasUsed_.has_value())
|
||||
metaData.setFieldU32(sfGasUsed, *gasUsed_);
|
||||
|
||||
if (wasmReturnCode_.has_value())
|
||||
metaData.setFieldI32(sfWasmReturnCode, *wasmReturnCode_);
|
||||
|
||||
return metaData;
|
||||
}
|
||||
|
||||
|
||||
92
src/libxrpl/rdb/DatabaseCon.cpp
Normal file
92
src/libxrpl/rdb/DatabaseCon.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class CheckpointersCollection
|
||||
{
|
||||
std::uintptr_t nextId_{0};
|
||||
// Mutex protects the CheckpointersCollection
|
||||
std::mutex mutex_;
|
||||
// Each checkpointer is given a unique id. All the checkpointers that are
|
||||
// part of a DatabaseCon are part of this collection. When the DatabaseCon
|
||||
// is destroyed, its checkpointer is removed from the collection
|
||||
std::unordered_map<std::uintptr_t, std::shared_ptr<Checkpointer>> checkpointers_;
|
||||
|
||||
public:
|
||||
std::shared_ptr<Checkpointer>
|
||||
fromId(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard l{mutex_};
|
||||
auto it = checkpointers_.find(id);
|
||||
if (it != checkpointers_.end())
|
||||
return it->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
erase(std::uintptr_t id)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
checkpointers_.erase(id);
|
||||
}
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
create(std::shared_ptr<soci::session> const& session, JobQueue& jobQueue, Logs& logs)
|
||||
{
|
||||
std::lock_guard lock{mutex_};
|
||||
auto const id = nextId_++;
|
||||
auto const r = makeCheckpointer(id, session, jobQueue, logs);
|
||||
checkpointers_[id] = r;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
CheckpointersCollection checkpointers;
|
||||
|
||||
std::shared_ptr<Checkpointer>
|
||||
checkpointerFromId(std::uintptr_t id)
|
||||
{
|
||||
return checkpointers.fromId(id);
|
||||
}
|
||||
|
||||
DatabaseCon::~DatabaseCon()
|
||||
{
|
||||
if (checkpointer_)
|
||||
{
|
||||
checkpointers.erase(checkpointer_->id());
|
||||
|
||||
std::weak_ptr<Checkpointer> wk(checkpointer_);
|
||||
checkpointer_.reset();
|
||||
|
||||
// The references to our Checkpointer held by 'checkpointer_' and
|
||||
// 'checkpointers' have been removed, so if the use count is nonzero, a
|
||||
// checkpoint is currently in progress. Wait for it to end, otherwise
|
||||
// creating a new DatabaseCon to the same database may fail due to the
|
||||
// database being locked by our (now old) Checkpointer.
|
||||
while (wk.use_count())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<std::string> const> DatabaseCon::Setup::globalPragma;
|
||||
|
||||
void
|
||||
DatabaseCon::setupCheckpointing(JobQueue* q, Logs& l)
|
||||
{
|
||||
if (!q)
|
||||
Throw<std::logic_error>("No JobQueue");
|
||||
checkpointer_ = checkpointers.create(session_, *q, l);
|
||||
}
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -3,12 +3,10 @@
|
||||
#pragma clang diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/DatabaseCon.h>
|
||||
#include <xrpld/core/SociDB.h>
|
||||
|
||||
#include <xrpl/basics/ByteUtilities.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/rdb/DatabaseCon.h>
|
||||
#include <xrpl/rdb/SociDB.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <xrpld/rpc/InfoSub.h>
|
||||
#include <xrpl/server/InfoSub.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <xrpld/app/rdb/State.h>
|
||||
#include <xrpl/server/State.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <xrpld/app/rdb/Vacuum.h>
|
||||
#include <xrpl/server/Vacuum.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
bool
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
@@ -5904,7 +5904,7 @@ private:
|
||||
using namespace test::jtx;
|
||||
|
||||
auto const testCase = [&](std::string suffix, FeatureBitset features) {
|
||||
testcase("Pseudo-account allocation failure " + suffix);
|
||||
testcase("Fail pseudo-account allocation " + suffix);
|
||||
std::string logs;
|
||||
Env env{*this, features, std::make_unique<CaptureLogs>(&logs)};
|
||||
env.fund(XRP(30'000), gw, alice);
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
#include <test/jtx/TestHelpers.h>
|
||||
#include <test/jtx/utility.h>
|
||||
|
||||
#include <xrpld/app/misc/HashRouter.h>
|
||||
#include <xrpld/app/misc/NetworkOPs.h>
|
||||
#include <xrpld/app/misc/Transaction.h>
|
||||
#include <xrpld/app/tx/apply.h>
|
||||
#include <xrpld/app/tx/detail/Batch.h>
|
||||
|
||||
#include <xrpl/core/HashRouter.h>
|
||||
#include <xrpl/protocol/Batch.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/STParsedJSON.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/protocol/TxFlags.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
#include <xrpl/server/NetworkOPs.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace test {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1374,7 +1374,7 @@ struct Escrow_test : public beast::unit_test::suite
|
||||
Account const alice{"alice"};
|
||||
Account const bob{"bob"};
|
||||
Account const carol{"carol"};
|
||||
Account const dillon{"dillon"};
|
||||
Account const dillon{"dillon "};
|
||||
Account const zelda{"zelda"};
|
||||
|
||||
char const credType[] = "abcde";
|
||||
@@ -1524,8 +1524,6 @@ public:
|
||||
FeatureBitset const all{testable_amendments()};
|
||||
testWithFeats(all);
|
||||
testWithFeats(all - featureTokenEscrow);
|
||||
testWithFeats(all - featureSmartEscrow);
|
||||
testWithFeats(all - featureTokenEscrow - featureSmartEscrow);
|
||||
testTags(all - fixIncludeKeyletFields);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
|
||||
#include <source_location>
|
||||
|
||||
namespace xrpl {
|
||||
namespace test {
|
||||
|
||||
@@ -26,13 +24,10 @@ struct FeeSettingsFields
|
||||
std::optional<XRPAmount> baseFeeDrops = std::nullopt;
|
||||
std::optional<XRPAmount> reserveBaseDrops = std::nullopt;
|
||||
std::optional<XRPAmount> reserveIncrementDrops = std::nullopt;
|
||||
std::optional<std::uint32_t> extensionComputeLimit = std::nullopt;
|
||||
std::optional<std::uint32_t> extensionSizeLimit = std::nullopt;
|
||||
std::optional<std::uint32_t> gasPrice = std::nullopt;
|
||||
};
|
||||
|
||||
STTx
|
||||
createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fields, bool forceAllFields = false)
|
||||
createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fields)
|
||||
{
|
||||
auto fill = [&](auto& obj) {
|
||||
obj.setAccountID(sfAccount, AccountID());
|
||||
@@ -54,12 +49,6 @@ createFeeTx(Rules const& rules, std::uint32_t seq, FeeSettingsFields const& fiel
|
||||
obj.setFieldU32(sfReserveIncrement, fields.reserveIncrement ? *fields.reserveIncrement : 0);
|
||||
obj.setFieldU32(sfReferenceFeeUnits, fields.referenceFeeUnits ? *fields.referenceFeeUnits : 0);
|
||||
}
|
||||
if (rules.enabled(featureSmartEscrow) || forceAllFields)
|
||||
{
|
||||
obj.setFieldU32(sfExtensionComputeLimit, fields.extensionComputeLimit ? *fields.extensionComputeLimit : 0);
|
||||
obj.setFieldU32(sfExtensionSizeLimit, fields.extensionSizeLimit ? *fields.extensionSizeLimit : 0);
|
||||
obj.setFieldU32(sfGasPrice, fields.gasPrice ? *fields.gasPrice : 0);
|
||||
}
|
||||
};
|
||||
return STTx(ttFEE, fill);
|
||||
}
|
||||
@@ -108,12 +97,6 @@ createInvalidFeeTx(
|
||||
obj.setFieldU32(sfReserveIncrement, 50000);
|
||||
obj.setFieldU32(sfReferenceFeeUnits, 10);
|
||||
}
|
||||
if (rules.enabled(featureSmartEscrow))
|
||||
{
|
||||
obj.setFieldU32(sfExtensionComputeLimit, 100 + uniqueValue);
|
||||
obj.setFieldU32(sfExtensionSizeLimit, 200 + uniqueValue);
|
||||
obj.setFieldU32(sfGasPrice, 300 + uniqueValue);
|
||||
}
|
||||
}
|
||||
// If missingRequiredFields is true, we don't add the required fields
|
||||
// (default behavior)
|
||||
@@ -121,11 +104,11 @@ createInvalidFeeTx(
|
||||
return STTx(ttFEE, fill);
|
||||
}
|
||||
|
||||
TER
|
||||
bool
|
||||
applyFeeAndTestResult(jtx::Env& env, OpenView& view, STTx const& tx)
|
||||
{
|
||||
auto const res = apply(env.app(), view, tx, ApplyFlags::tapNONE, env.journal);
|
||||
return res.ter;
|
||||
return res.ter == tesSUCCESS;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -170,21 +153,6 @@ verifyFeeObject(std::shared_ptr<Ledger const> const& ledger, Rules const& rules,
|
||||
if (!checkEquality(sfReferenceFeeUnits, expected.referenceFeeUnits))
|
||||
return false;
|
||||
}
|
||||
if (rules.enabled(featureSmartEscrow))
|
||||
{
|
||||
if (!checkEquality(sfExtensionComputeLimit, expected.extensionComputeLimit.value_or(0)))
|
||||
return false;
|
||||
if (!checkEquality(sfExtensionSizeLimit, expected.extensionSizeLimit.value_or(0)))
|
||||
return false;
|
||||
if (!checkEquality(sfGasPrice, expected.gasPrice.value_or(0)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (feeObject->isFieldPresent(sfExtensionComputeLimit) || feeObject->isFieldPresent(sfExtensionSizeLimit) ||
|
||||
feeObject->isFieldPresent(sfGasPrice))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -207,7 +175,6 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
void
|
||||
testSetup()
|
||||
{
|
||||
testcase("FeeVote setup");
|
||||
FeeSetup const defaultSetup;
|
||||
{
|
||||
// defaults
|
||||
@@ -216,82 +183,43 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
|
||||
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
|
||||
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
|
||||
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
|
||||
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
|
||||
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
|
||||
}
|
||||
{
|
||||
Section config;
|
||||
config.append(
|
||||
{"reference_fee = 50",
|
||||
"account_reserve = 1234567",
|
||||
"owner_reserve = 1234",
|
||||
"extension_compute_limit = 100",
|
||||
"extension_size_limit = 200",
|
||||
" gas_price = 300"});
|
||||
config.append({"reference_fee = 50", "account_reserve = 1234567", "owner_reserve = 1234"});
|
||||
auto setup = setup_FeeVote(config);
|
||||
BEAST_EXPECT(setup.reference_fee == 50);
|
||||
BEAST_EXPECT(setup.account_reserve == 1234567);
|
||||
BEAST_EXPECT(setup.owner_reserve == 1234);
|
||||
BEAST_EXPECT(setup.extension_compute_limit == 100);
|
||||
BEAST_EXPECT(setup.extension_size_limit == 200);
|
||||
BEAST_EXPECT(setup.gas_price == 300);
|
||||
}
|
||||
{
|
||||
Section config;
|
||||
config.append(
|
||||
{"reference_fee = blah",
|
||||
"account_reserve = yada",
|
||||
"owner_reserve = foo",
|
||||
"extension_compute_limit = bar",
|
||||
"extension_size_limit = baz",
|
||||
"gas_price = qux"});
|
||||
config.append({"reference_fee = blah", "account_reserve = yada", "owner_reserve = foo"});
|
||||
// Illegal values are ignored, and the defaults left unchanged
|
||||
auto setup = setup_FeeVote(config);
|
||||
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
|
||||
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
|
||||
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
|
||||
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
|
||||
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
|
||||
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
|
||||
}
|
||||
{
|
||||
Section config;
|
||||
config.append(
|
||||
{"reference_fee = -50",
|
||||
"account_reserve = -1234567",
|
||||
"owner_reserve = -1234",
|
||||
"extension_compute_limit = -100",
|
||||
"extension_size_limit = -200",
|
||||
"gas_price = -300"});
|
||||
config.append({"reference_fee = -50", "account_reserve = -1234567", "owner_reserve = -1234"});
|
||||
// Illegal values are ignored, and the defaults left unchanged
|
||||
auto setup = setup_FeeVote(config);
|
||||
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
|
||||
BEAST_EXPECT(setup.account_reserve == static_cast<std::uint32_t>(-1234567));
|
||||
BEAST_EXPECT(setup.owner_reserve == static_cast<std::uint32_t>(-1234));
|
||||
BEAST_EXPECT(setup.extension_compute_limit == static_cast<std::uint32_t>(-100));
|
||||
BEAST_EXPECT(setup.extension_size_limit == static_cast<std::uint32_t>(-200));
|
||||
BEAST_EXPECT(setup.gas_price == static_cast<std::uint32_t>(-300));
|
||||
}
|
||||
{
|
||||
auto const big64 =
|
||||
std::to_string(static_cast<std::uint64_t>(std::numeric_limits<XRPAmount::value_type>::max()) + 1);
|
||||
Section config;
|
||||
config.append(
|
||||
{"reference_fee = " + big64,
|
||||
"account_reserve = " + big64,
|
||||
"owner_reserve = " + big64,
|
||||
"extension_compute_limit = " + big64,
|
||||
"extension_size_limit = " + big64,
|
||||
"gas_price = " + big64});
|
||||
config.append({"reference_fee = " + big64, "account_reserve = " + big64, "owner_reserve = " + big64});
|
||||
// Illegal values are ignored, and the defaults left unchanged
|
||||
auto setup = setup_FeeVote(config);
|
||||
BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee);
|
||||
BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve);
|
||||
BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve);
|
||||
BEAST_EXPECT(setup.extension_compute_limit == defaultSetup.extension_compute_limit);
|
||||
BEAST_EXPECT(setup.extension_size_limit == defaultSetup.extension_size_limit);
|
||||
BEAST_EXPECT(setup.gas_price == defaultSetup.gas_price);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +230,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
// Test with XRPFees disabled (legacy format)
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -316,7 +244,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
|
||||
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
|
||||
accum.apply(*ledger);
|
||||
|
||||
// Verify fee object was created/updated correctly
|
||||
@@ -325,7 +253,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
// Test with XRPFees enabled (new format)
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -340,63 +268,12 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
|
||||
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
|
||||
accum.apply(*ledger);
|
||||
|
||||
// Verify fee object was created/updated correctly
|
||||
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
|
||||
}
|
||||
|
||||
// Test with both XRPFees and SmartEscrow enabled
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments());
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
// Create the next ledger to apply transaction to
|
||||
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
|
||||
|
||||
FeeSettingsFields fields{
|
||||
.baseFeeDrops = XRPAmount{10},
|
||||
.reserveBaseDrops = XRPAmount{200000},
|
||||
.reserveIncrementDrops = XRPAmount{50000},
|
||||
.extensionComputeLimit = 100,
|
||||
.extensionSizeLimit = 200,
|
||||
.gasPrice = 300};
|
||||
// Test successful fee transaction with new fields
|
||||
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields);
|
||||
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
|
||||
accum.apply(*ledger);
|
||||
|
||||
// Verify fee object was created/updated correctly
|
||||
BEAST_EXPECT(verifyFeeObject(ledger, ledger->rules(), fields));
|
||||
}
|
||||
|
||||
// Test that the Smart Escrow fields are rejected if the
|
||||
// feature is disabled
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
// Create the next ledger to apply transaction to
|
||||
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
|
||||
|
||||
FeeSettingsFields fields{
|
||||
.baseFeeDrops = XRPAmount{10},
|
||||
.reserveBaseDrops = XRPAmount{200000},
|
||||
.reserveIncrementDrops = XRPAmount{50000},
|
||||
.extensionComputeLimit = 100,
|
||||
.extensionSizeLimit = 200,
|
||||
.gasPrice = 300};
|
||||
// Test successful fee transaction with new fields
|
||||
auto feeTx = createFeeTx(ledger->rules(), ledger->seq(), fields, true);
|
||||
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -405,7 +282,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
testcase("Fee Transaction Validation");
|
||||
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -415,15 +292,15 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
// Test transaction with missing required legacy fields
|
||||
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 1);
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
|
||||
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
|
||||
|
||||
// Test transaction with new format fields when XRPFees is disabled
|
||||
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 2);
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
|
||||
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
|
||||
}
|
||||
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -433,29 +310,11 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
// Test transaction with missing required new fields
|
||||
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 3);
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
|
||||
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
|
||||
|
||||
// Test transaction with legacy fields when XRPFees is enabled
|
||||
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 4);
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
|
||||
}
|
||||
|
||||
{
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees | featureSmartEscrow);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
// Create the next ledger to apply transaction to
|
||||
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
|
||||
|
||||
// Test transaction with missing required new fields
|
||||
auto invalidTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), true, false, 5);
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
|
||||
|
||||
// Test transaction with legacy fields when XRPFees is enabled
|
||||
auto disallowedTx = createInvalidFeeTx(ledger->rules(), ledger->seq(), false, true, 6);
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, disallowedTx)));
|
||||
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, disallowedTx));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,7 +323,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("Pseudo Transaction Properties");
|
||||
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments());
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -490,7 +349,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
// But can be applied to a closed ledger
|
||||
{
|
||||
OpenView closedAccum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, closedAccum, feeTx)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, closedAccum, feeTx));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +358,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("Multiple Fee Updates");
|
||||
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -513,7 +372,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
{
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
|
||||
accum.apply(*ledger);
|
||||
}
|
||||
|
||||
@@ -530,7 +389,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
{
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
|
||||
accum.apply(*ledger);
|
||||
}
|
||||
|
||||
@@ -543,7 +402,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("Wrong Ledger Sequence");
|
||||
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -562,7 +421,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
// The transaction should still succeed as long as other fields are
|
||||
// valid
|
||||
// The ledger sequence field is only used for informational purposes
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -570,7 +429,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("Partial Field Updates");
|
||||
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -584,7 +443,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
{
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx1)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx1));
|
||||
accum.apply(*ledger);
|
||||
}
|
||||
|
||||
@@ -598,7 +457,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
{
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(isTesSuccess(applyFeeAndTestResult(env, accum, feeTx2)));
|
||||
BEAST_EXPECT(applyFeeAndTestResult(env, accum, feeTx2));
|
||||
accum.apply(*ledger);
|
||||
}
|
||||
|
||||
@@ -611,7 +470,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
{
|
||||
testcase("Single Invalid Transaction");
|
||||
|
||||
jtx::Env env(*this, jtx::testable_amendments() - featureSmartEscrow);
|
||||
jtx::Env env(*this, jtx::testable_amendments() | featureXRPFees);
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
@@ -629,7 +488,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
});
|
||||
|
||||
OpenView accum(ledger.get());
|
||||
BEAST_EXPECT(!isTesSuccess(applyFeeAndTestResult(env, accum, invalidTx)));
|
||||
BEAST_EXPECT(!applyFeeAndTestResult(env, accum, invalidTx));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -646,7 +505,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
// Test with XRPFees enabled
|
||||
{
|
||||
Env env(*this, testable_amendments() - featureSmartEscrow);
|
||||
Env env(*this, testable_amendments() | featureXRPFees);
|
||||
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
|
||||
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
@@ -672,7 +531,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
|
||||
// Test with XRPFees disabled (legacy format)
|
||||
{
|
||||
Env env(*this, testable_amendments() - featureXRPFees - featureSmartEscrow);
|
||||
Env env(*this, testable_amendments() - featureXRPFees);
|
||||
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
|
||||
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
@@ -708,7 +567,7 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
setup.account_reserve = 1234567;
|
||||
setup.owner_reserve = 7654321;
|
||||
|
||||
Env env(*this, testable_amendments() - featureSmartEscrow);
|
||||
Env env(*this, testable_amendments() | featureXRPFees);
|
||||
|
||||
// establish what the current fees are
|
||||
BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
|
||||
@@ -778,127 +637,6 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve});
|
||||
}
|
||||
|
||||
void
|
||||
testDoVotingSmartEscrow()
|
||||
{
|
||||
testcase("doVoting with Smart Escrow");
|
||||
|
||||
using namespace jtx;
|
||||
|
||||
Env env(*this, testable_amendments() | featureXRPFees | featureSmartEscrow);
|
||||
|
||||
// establish what the current fees are
|
||||
BEAST_EXPECT(env.current()->fees().base == XRPAmount{UNIT_TEST_REFERENCE_FEE});
|
||||
BEAST_EXPECT(env.current()->fees().reserve == XRPAmount{200'000'000});
|
||||
BEAST_EXPECT(env.current()->fees().increment == XRPAmount{50'000'000});
|
||||
BEAST_EXPECT(env.current()->fees().extensionComputeLimit == 0);
|
||||
BEAST_EXPECT(env.current()->fees().extensionSizeLimit == 0);
|
||||
BEAST_EXPECT(env.current()->fees().gasPrice == 0);
|
||||
|
||||
auto const createFeeTxFromVoting = [&](FeeSetup const& setup) -> std::pair<STTx, std::shared_ptr<Ledger>> {
|
||||
auto feeVote = make_FeeVote(setup, env.app().journal("FeeVote"));
|
||||
auto ledger = std::make_shared<Ledger>(
|
||||
create_genesis, env.app().config(), std::vector<uint256>{}, env.app().getNodeFamily());
|
||||
|
||||
// doVoting requires a flag ledger (every 256th ledger)
|
||||
// We need to create a ledger at sequence 256 to make it a flag
|
||||
// ledger
|
||||
for (int i = 0; i < 256 - 1; ++i)
|
||||
{
|
||||
ledger = std::make_shared<Ledger>(*ledger, env.app().timeKeeper().closeTime());
|
||||
}
|
||||
BEAST_EXPECT(ledger->isFlagLedger());
|
||||
|
||||
// Create some mock validations with fee votes
|
||||
std::vector<std::shared_ptr<STValidation>> validations;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
auto sec = randomSecretKey();
|
||||
auto pub = derivePublicKey(KeyType::secp256k1, sec);
|
||||
|
||||
auto val = std::make_shared<STValidation>(
|
||||
env.app().timeKeeper().now(), pub, sec, calcNodeID(pub), [&](STValidation& v) {
|
||||
v.setFieldU32(sfLedgerSequence, ledger->seq());
|
||||
// Vote for different fees than current
|
||||
v.setFieldAmount(sfBaseFeeDrops, XRPAmount{setup.reference_fee});
|
||||
v.setFieldAmount(sfReserveBaseDrops, XRPAmount{setup.account_reserve});
|
||||
v.setFieldAmount(sfReserveIncrementDrops, XRPAmount{setup.owner_reserve});
|
||||
v.setFieldU32(sfExtensionComputeLimit, setup.extension_compute_limit);
|
||||
v.setFieldU32(sfExtensionSizeLimit, setup.extension_size_limit);
|
||||
v.setFieldU32(sfGasPrice, setup.gas_price);
|
||||
});
|
||||
if (i % 2)
|
||||
val->setTrusted();
|
||||
validations.push_back(val);
|
||||
}
|
||||
|
||||
auto txSet = std::make_shared<SHAMap>(SHAMapType::TRANSACTION, env.app().getNodeFamily());
|
||||
|
||||
// This should not throw since we have a flag ledger
|
||||
feeVote->doVoting(ledger, validations, txSet);
|
||||
|
||||
auto const txs = getTxs(txSet);
|
||||
BEAST_EXPECT(txs.size() == 1);
|
||||
return {txs[0], ledger};
|
||||
};
|
||||
|
||||
auto checkFeeTx = [&](FeeSetup const& setup,
|
||||
STTx const& feeTx,
|
||||
std::shared_ptr<Ledger> const& ledger,
|
||||
std::source_location const loc = std::source_location::current()) {
|
||||
auto const line = " (" + std::to_string(loc.line()) + ")";
|
||||
BEAST_EXPECTS(feeTx.getTxnType() == ttFEE, line);
|
||||
|
||||
BEAST_EXPECTS(feeTx.getAccountID(sfAccount) == AccountID(), line);
|
||||
BEAST_EXPECTS(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1, line);
|
||||
|
||||
BEAST_EXPECTS(feeTx.isFieldPresent(sfBaseFeeDrops), line);
|
||||
BEAST_EXPECTS(feeTx.isFieldPresent(sfReserveBaseDrops), line);
|
||||
BEAST_EXPECTS(feeTx.isFieldPresent(sfReserveIncrementDrops), line);
|
||||
|
||||
// The legacy fields should NOT be present
|
||||
BEAST_EXPECTS(!feeTx.isFieldPresent(sfBaseFee), line);
|
||||
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReserveBase), line);
|
||||
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReserveIncrement), line);
|
||||
BEAST_EXPECTS(!feeTx.isFieldPresent(sfReferenceFeeUnits), line);
|
||||
|
||||
// Check the values
|
||||
BEAST_EXPECTS(feeTx.getFieldAmount(sfBaseFeeDrops) == XRPAmount{setup.reference_fee}, line);
|
||||
BEAST_EXPECTS(feeTx.getFieldAmount(sfReserveBaseDrops) == XRPAmount{setup.account_reserve}, line);
|
||||
BEAST_EXPECTS(feeTx.getFieldAmount(sfReserveIncrementDrops) == XRPAmount{setup.owner_reserve}, line);
|
||||
BEAST_EXPECTS(feeTx.getFieldU32(sfExtensionComputeLimit) == setup.extension_compute_limit, line);
|
||||
BEAST_EXPECTS(feeTx.getFieldU32(sfExtensionSizeLimit) == setup.extension_size_limit, line);
|
||||
BEAST_EXPECTS(feeTx.getFieldU32(sfGasPrice) == setup.gas_price, line);
|
||||
};
|
||||
|
||||
{
|
||||
FeeSetup setup;
|
||||
setup.reference_fee = 42;
|
||||
setup.account_reserve = 1234567;
|
||||
setup.owner_reserve = 7654321;
|
||||
setup.extension_compute_limit = 100;
|
||||
setup.extension_size_limit = 200;
|
||||
setup.gas_price = 300;
|
||||
auto const [feeTx, ledger] = createFeeTxFromVoting(setup);
|
||||
|
||||
checkFeeTx(setup, feeTx, ledger);
|
||||
}
|
||||
|
||||
{
|
||||
FeeSetup setup;
|
||||
setup.reference_fee = 42;
|
||||
setup.account_reserve = 1234567;
|
||||
setup.owner_reserve = 7654321;
|
||||
setup.extension_compute_limit = 0;
|
||||
setup.extension_size_limit = 0;
|
||||
setup.gas_price = 300;
|
||||
auto const [feeTx, ledger] = createFeeTxFromVoting(setup);
|
||||
|
||||
checkFeeTx(setup, feeTx, ledger);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -912,7 +650,6 @@ class FeeVote_test : public beast::unit_test::suite
|
||||
testSingleInvalidTransaction();
|
||||
testDoValidation();
|
||||
testDoVoting();
|
||||
testDoVotingSmartEscrow();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include <xrpld/app/misc/HashRouter.h>
|
||||
#include <xrpld/app/misc/setup_HashRouter.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/core/HashRouter.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace test {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
std::unique_ptr<Config> cfg,
|
||||
std::string const& dbPath,
|
||||
std::string const& ledger,
|
||||
Config::StartUpType type,
|
||||
StartUpType type,
|
||||
std::optional<uint256> trapTxHash)
|
||||
{
|
||||
cfg->START_LEDGER = ledger;
|
||||
@@ -105,7 +105,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with the ledger file specified for startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, sd.ledgerFile, Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, sd.ledgerFile, StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -123,7 +123,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "", Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "", StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -132,7 +132,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "badfile.json", Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "badfile.json", StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -153,7 +153,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
except([&] {
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerFileCorrupt.string(), Config::LOAD_FILE, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerFileCorrupt.string(), StartUpType::LOAD_FILE, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
});
|
||||
@@ -170,7 +170,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -189,7 +189,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto const jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -213,7 +213,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
boost::erase_all(ledgerHash, "\"");
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, sd.trapTxHash),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, sd.trapTxHash),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto const jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -241,7 +241,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// replay when trapTxHash is set to an invalid transaction
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, Config::REPLAY, ~sd.trapTxHash),
|
||||
envconfig(ledgerConfig, sd.dbPath, ledgerHash, StartUpType::REPLAY, ~sd.trapTxHash),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
BEAST_EXPECT(false);
|
||||
@@ -265,7 +265,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with the ledger "latest" specified for startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "latest", Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "latest", StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
@@ -281,7 +281,7 @@ class LedgerLoad_test : public beast::unit_test::suite
|
||||
// create a new env with specific ledger index at startup
|
||||
Env env(
|
||||
*this,
|
||||
envconfig(ledgerConfig, sd.dbPath, "43", Config::LOAD, std::nullopt),
|
||||
envconfig(ledgerConfig, sd.dbPath, "43", StartUpType::LOAD, std::nullopt),
|
||||
nullptr,
|
||||
beast::severities::kDisabled);
|
||||
auto jrb = env.rpc("ledger", "current", "full")[jss::result];
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include <test/jtx.h>
|
||||
|
||||
#include <xrpld/app/main/DBInit.h>
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/misc/ValidatorList.h>
|
||||
#include <xrpld/app/rdb/Wallet.h>
|
||||
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/protocol/STExchange.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/Sign.h>
|
||||
#include <xrpl/rdb/DBInit.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
#include <xrpl/server/Wallet.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <test/jtx/CaptureLogs.h>
|
||||
#include <test/jtx/Env.h>
|
||||
|
||||
#include <xrpld/app/misc/HashRouter.h>
|
||||
#include <xrpl/core/HashRouter.h>
|
||||
|
||||
namespace xrpl {
|
||||
namespace test {
|
||||
|
||||
@@ -33,12 +33,6 @@ struct PseudoTx_test : public beast::unit_test::suite
|
||||
obj[sfReserveIncrement] = 0;
|
||||
obj[sfReferenceFeeUnits] = 0;
|
||||
}
|
||||
if (rules.enabled(featureSmartEscrow))
|
||||
{
|
||||
obj[sfExtensionComputeLimit] = 0;
|
||||
obj[sfExtensionSizeLimit] = 0;
|
||||
obj[sfGasPrice] = 0;
|
||||
}
|
||||
}));
|
||||
|
||||
res.emplace_back(STTx(ttAMENDMENT, [&](auto& obj) {
|
||||
@@ -103,9 +97,7 @@ struct PseudoTx_test : public beast::unit_test::suite
|
||||
FeatureBitset const all{testable_amendments()};
|
||||
FeatureBitset const xrpFees{featureXRPFees};
|
||||
|
||||
testPrevented(all - featureXRPFees - featureSmartEscrow);
|
||||
testPrevented(all - featureXRPFees);
|
||||
testPrevented(all - featureSmartEscrow);
|
||||
testPrevented(all);
|
||||
testAllowed();
|
||||
}
|
||||
|
||||
@@ -91,8 +91,7 @@ class SHAMapStore_test : public beast::unit_test::suite
|
||||
void
|
||||
ledgerCheck(jtx::Env& env, int const rows, int const first)
|
||||
{
|
||||
auto const [actualRows, actualFirst, actualLast] =
|
||||
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())->getLedgerCountMinMax();
|
||||
auto const [actualRows, actualFirst, actualLast] = env.app().getRelationalDatabase().getLedgerCountMinMax();
|
||||
|
||||
BEAST_EXPECT(actualRows == rows);
|
||||
BEAST_EXPECT(actualFirst == first);
|
||||
@@ -102,14 +101,13 @@ class SHAMapStore_test : public beast::unit_test::suite
|
||||
void
|
||||
transactionCheck(jtx::Env& env, int const rows)
|
||||
{
|
||||
BEAST_EXPECT(dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())->getTransactionCount() == rows);
|
||||
BEAST_EXPECT(env.app().getRelationalDatabase().getTransactionCount() == rows);
|
||||
}
|
||||
|
||||
void
|
||||
accountTransactionCheck(jtx::Env& env, int const rows)
|
||||
{
|
||||
BEAST_EXPECT(
|
||||
dynamic_cast<SQLiteDatabase*>(&env.app().getRelationalDatabase())->getAccountTransactionCount() == rows);
|
||||
BEAST_EXPECT(env.app().getRelationalDatabase().getAccountTransactionCount() == rows);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
||||
#include <test/jtx/Env.h>
|
||||
|
||||
#include <xrpld/app/misc/Manifest.h>
|
||||
#include <xrpld/app/misc/ValidatorKeys.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/core/ConfigSections.h>
|
||||
|
||||
#include <xrpl/basics/base64.h>
|
||||
#include <xrpl/beast/unit_test.h>
|
||||
#include <xrpl/server/Manifest.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -1,967 +0,0 @@
|
||||
#ifdef _DEBUG
|
||||
// #define DEBUG_OUTPUT 1
|
||||
#endif
|
||||
|
||||
#include <test/app/TestHostFunctions.h>
|
||||
|
||||
#include <xrpld/app/wasm/HostFuncWrapper.h>
|
||||
|
||||
#include <source_location>
|
||||
|
||||
namespace xrpl {
|
||||
namespace test {
|
||||
|
||||
bool
|
||||
testGetDataIncrement();
|
||||
|
||||
using Add_proto = int32_t(int32_t, int32_t);
|
||||
static wasm_trap_t*
|
||||
Add(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
||||
{
|
||||
int32_t Val1 = params->data[0].of.i32;
|
||||
int32_t Val2 = params->data[1].of.i32;
|
||||
// printf("Host function \"Add\": %d + %d\n", Val1, Val2);
|
||||
results->data[0] = WASM_I32_VAL(Val1 + Val2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> const
|
||||
hexToBytes(std::string const& hex)
|
||||
{
|
||||
auto const ws = boost::algorithm::unhex(hex);
|
||||
return Bytes(ws.begin(), ws.end());
|
||||
}
|
||||
|
||||
std::optional<int32_t>
|
||||
runFinishFunction(std::string const& code)
|
||||
{
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto const wasm = hexToBytes(code);
|
||||
auto const re = engine.run(wasm, "finish");
|
||||
if (re.has_value())
|
||||
{
|
||||
return std::optional<int32_t>(re->result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
struct Wasm_test : public beast::unit_test::suite
|
||||
{
|
||||
void
|
||||
checkResult(
|
||||
Expected<WasmResult<int32_t>, TER> re,
|
||||
int32_t expectedResult,
|
||||
int64_t expectedCost,
|
||||
std::source_location const location = std::source_location::current())
|
||||
{
|
||||
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
||||
if (BEAST_EXPECTS(re.has_value(), transToken(re.error()) + lineStr))
|
||||
{
|
||||
BEAST_EXPECTS(re->result == expectedResult, std::to_string(re->result) + lineStr);
|
||||
BEAST_EXPECTS(re->cost == expectedCost, std::to_string(re->cost) + lineStr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testGetDataHelperFunctions()
|
||||
{
|
||||
testcase("getData helper functions");
|
||||
BEAST_EXPECT(testGetDataIncrement());
|
||||
}
|
||||
|
||||
void
|
||||
testWasmLib()
|
||||
{
|
||||
testcase("wasmtime lib test");
|
||||
// clang-format off
|
||||
/* The WASM module buffer. */
|
||||
Bytes const wasm = {/* WASM header */
|
||||
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00,
|
||||
/* Type section */
|
||||
0x01, 0x07, 0x01,
|
||||
/* function type {i32, i32} -> {i32} */
|
||||
0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F,
|
||||
/* Import section */
|
||||
0x02, 0x13, 0x01,
|
||||
/* module name: "extern" */
|
||||
0x06, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6E,
|
||||
/* extern name: "func-add" */
|
||||
0x08, 0x66, 0x75, 0x6E, 0x63, 0x2D, 0x61, 0x64, 0x64,
|
||||
/* import desc: func 0 */
|
||||
0x00, 0x00,
|
||||
/* Function section */
|
||||
0x03, 0x02, 0x01, 0x00,
|
||||
/* Export section */
|
||||
0x07, 0x0A, 0x01,
|
||||
/* export name: "addTwo" */
|
||||
0x06, 0x61, 0x64, 0x64, 0x54, 0x77, 0x6F,
|
||||
/* export desc: func 0 */
|
||||
0x00, 0x01,
|
||||
/* Code section */
|
||||
0x0A, 0x0A, 0x01,
|
||||
/* code body */
|
||||
0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x0B};
|
||||
// clang-format on
|
||||
auto& vm = WasmEngine::instance();
|
||||
|
||||
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
WasmImpFunc<Add_proto>(*imports, "func-add", reinterpret_cast<void*>(&Add));
|
||||
|
||||
auto re = vm.run(wasm, "addTwo", wasmParams(1234, 5678), imports);
|
||||
|
||||
// if (res) printf("invokeAdd get the result: %d\n", res.value());
|
||||
|
||||
checkResult(re, 6'912, 59);
|
||||
}
|
||||
|
||||
void
|
||||
testBadWasm()
|
||||
{
|
||||
testcase("bad wasm test");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this};
|
||||
std::shared_ptr<HostFunctions> hfs(new HostFunctions(env.journal));
|
||||
|
||||
{
|
||||
auto wasm = hexToBytes("00000000");
|
||||
std::string funcName("mock_escrow");
|
||||
|
||||
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 15);
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
|
||||
{
|
||||
auto wasm = hexToBytes("00112233445566778899AA");
|
||||
std::string funcName("mock_escrow");
|
||||
|
||||
auto const re = preflightEscrowWasm(wasm, hfs, funcName);
|
||||
BEAST_EXPECT(!isTesSuccess(re));
|
||||
}
|
||||
|
||||
{
|
||||
// FinishFunction wrong function name
|
||||
// pub fn bad() -> bool {
|
||||
// unsafe { host_lib::getLedgerSqn() >= 5 }
|
||||
// }
|
||||
auto const badWasm = hexToBytes(
|
||||
"0061736d010000000105016000017f02190108686f73745f6c69620c6765"
|
||||
"744c656467657253716e00000302010005030100100611027f00418080c0"
|
||||
"000b7f00418080c0000b072b04066d656d6f727902000362616400010a5f"
|
||||
"5f646174615f656e6403000b5f5f686561705f6261736503010a09010700"
|
||||
"100041044a0b004d0970726f64756365727302086c616e67756167650104"
|
||||
"52757374000c70726f6365737365642d6279010572757374631d312e3835"
|
||||
"2e31202834656231363132353020323032352d30332d31352900490f7461"
|
||||
"726765745f6665617475726573042b0f6d757461626c652d676c6f62616c"
|
||||
"732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a"
|
||||
"6d756c746976616c7565");
|
||||
|
||||
auto const re = preflightEscrowWasm(badWasm, hfs, ESCROW_FUNCTION_NAME);
|
||||
BEAST_EXPECT(!isTesSuccess(re));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWasmLedgerSqn()
|
||||
{
|
||||
testcase("Wasm get ledger sequence");
|
||||
|
||||
auto ledgerSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this};
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
auto imports = std::make_shared<ImportVec>();
|
||||
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get(), 33);
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto re = engine.run(ledgerSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
||||
|
||||
checkResult(re, 0, 440);
|
||||
|
||||
env.close();
|
||||
env.close();
|
||||
|
||||
// empty module - run the same instance
|
||||
re = engine.run({}, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
||||
|
||||
checkResult(re, 5, 488);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmFib()
|
||||
{
|
||||
testcase("Wasm fibo");
|
||||
|
||||
auto const fibWasm = hexToBytes(fibWasmHex);
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto const re = engine.run(fibWasm, "fib", wasmParams(10));
|
||||
|
||||
checkResult(re, 55, 1'137);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmSha()
|
||||
{
|
||||
testcase("Wasm sha");
|
||||
|
||||
auto const sha512Wasm = hexToBytes(sha512PureWasmHex);
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto const re = engine.run(sha512Wasm, "sha512_process", wasmParams(sha512PureWasmHex));
|
||||
|
||||
checkResult(re, 34'432, 151'155);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmB58()
|
||||
{
|
||||
testcase("Wasm base58");
|
||||
auto const b58Wasm = hexToBytes(b58WasmHex);
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
Bytes outb;
|
||||
outb.resize(1024);
|
||||
|
||||
auto const minSize = std::min(static_cast<std::uint32_t>(512), static_cast<std::uint32_t>(b58WasmHex.size()));
|
||||
auto const s = std::string_view(b58WasmHex.c_str(), minSize);
|
||||
|
||||
auto const re = engine.run(b58Wasm, "b58enco", wasmParams(outb, s));
|
||||
|
||||
checkResult(re, 700, 2'886'069);
|
||||
}
|
||||
|
||||
void
|
||||
testHFCost()
|
||||
{
|
||||
testcase("wasm test host functions cost");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env(*this);
|
||||
{
|
||||
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto imp = createWasmImport(*hfs);
|
||||
for (auto& i : *imp)
|
||||
i.second.gas = 0;
|
||||
|
||||
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
|
||||
|
||||
checkResult(re, 1, 27'080);
|
||||
|
||||
env.close();
|
||||
}
|
||||
|
||||
env.close();
|
||||
env.close();
|
||||
env.close();
|
||||
env.close();
|
||||
env.close();
|
||||
|
||||
{
|
||||
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto const imp = createWasmImport(*hfs);
|
||||
|
||||
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
|
||||
|
||||
checkResult(re, 1, 65'840);
|
||||
|
||||
env.close();
|
||||
}
|
||||
|
||||
// not enough gas
|
||||
{
|
||||
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto const imp = createWasmImport(*hfs);
|
||||
|
||||
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 200, env.journal);
|
||||
|
||||
if (BEAST_EXPECT(!re))
|
||||
{
|
||||
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
|
||||
}
|
||||
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testEscrowWasmDN()
|
||||
{
|
||||
testcase("escrow wasm devnet test");
|
||||
|
||||
auto const allHFWasm = hexToBytes(allHostFunctionsWasmHex);
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env{*this};
|
||||
{
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
checkResult(re, 1, 65'840);
|
||||
}
|
||||
|
||||
{
|
||||
// max<int64_t>() gas
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, -1);
|
||||
checkResult(re, 1, 65'840);
|
||||
}
|
||||
|
||||
{ // fail because trying to access nonexistent field
|
||||
struct BadTestHostFunctions : public TestHostFunctions
|
||||
{
|
||||
explicit BadTestHostFunctions(Env& env) : TestHostFunctions(env)
|
||||
{
|
||||
}
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getTxField(SField const& fname) override
|
||||
{
|
||||
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
|
||||
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
checkResult(re, -201, 28'965);
|
||||
}
|
||||
|
||||
{ // fail because trying to allocate more than MAX_PAGES memory
|
||||
struct BadTestHostFunctions : public TestHostFunctions
|
||||
{
|
||||
explicit BadTestHostFunctions(Env& env) : TestHostFunctions(env)
|
||||
{
|
||||
}
|
||||
Expected<Bytes, HostFunctionError>
|
||||
getTxField(SField const& fname) override
|
||||
{
|
||||
return Bytes((128 + 1) * 64 * 1024, 1);
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new BadTestHostFunctions(env));
|
||||
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
checkResult(re, -201, 28'965);
|
||||
}
|
||||
|
||||
{ // fail because recursion too deep
|
||||
|
||||
auto const deepWasm = hexToBytes(deepRecursionHex);
|
||||
|
||||
std::shared_ptr<TestHostFunctionsSink> hfs(new TestHostFunctionsSink(env));
|
||||
std::string funcName("finish");
|
||||
auto re = runEscrowWasm(deepWasm, hfs, funcName, {}, 1'000'000'000);
|
||||
BEAST_EXPECT(!re && re.error());
|
||||
// std::cout << "bad case (deep recursion) result " << re.error()
|
||||
// << std::endl;
|
||||
|
||||
auto const& sink = hfs->getSink();
|
||||
auto countSubstr = [](std::string const& str, std::string const& substr) {
|
||||
std::size_t pos = 0;
|
||||
int occurrences = 0;
|
||||
while ((pos = str.find(substr, pos)) != std::string::npos)
|
||||
{
|
||||
occurrences++;
|
||||
pos += substr.length();
|
||||
}
|
||||
return occurrences;
|
||||
};
|
||||
|
||||
auto const s = sink.messages().str();
|
||||
BEAST_EXPECT(countSubstr(s, "WASMI Error: failure to call func") == 1);
|
||||
BEAST_EXPECT(countSubstr(s, "exception: <finish> failure") > 0);
|
||||
}
|
||||
|
||||
{ // infinite loop
|
||||
auto const infiniteLoopWasm = hexToBytes(infiniteLoopWasmHex);
|
||||
std::string const funcName("loop");
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
|
||||
// infinite loop should be caught and fail
|
||||
auto const re = runEscrowWasm(infiniteLoopWasm, hfs, funcName, {}, 1'000'000);
|
||||
if (BEAST_EXPECT(!re.has_value()))
|
||||
{
|
||||
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// expected import not provided
|
||||
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn2", hfs.get());
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
||||
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
|
||||
{
|
||||
// bad import format
|
||||
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
|
||||
(*imports)[0].first = nullptr;
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
||||
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
|
||||
{
|
||||
// bad function name
|
||||
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto re = engine.run(lgrSqnWasm, "func1", {}, imports, hfs, 1'000'000, env.journal);
|
||||
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testFloat()
|
||||
{
|
||||
testcase("float point");
|
||||
|
||||
std::string const funcName("finish");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env(*this);
|
||||
{
|
||||
auto const floatTestWasm = hexToBytes(floatTestsWasmHex);
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto re = runEscrowWasm(floatTestWasm, hfs, funcName, {}, 200'000);
|
||||
checkResult(re, 1, 110'699);
|
||||
env.close();
|
||||
}
|
||||
|
||||
{
|
||||
auto const float0Wasm = hexToBytes(float0Hex);
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto re = runEscrowWasm(float0Wasm, hfs, funcName, {}, 100'000);
|
||||
checkResult(re, 1, 4'259);
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
perfTest()
|
||||
{
|
||||
testcase("Perf test host functions");
|
||||
|
||||
using namespace jtx;
|
||||
using namespace std::chrono;
|
||||
|
||||
// std::string const funcName("test");
|
||||
auto const perfWasm = hexToBytes(hfPerfTest);
|
||||
|
||||
// std::string const credType = "abcde";
|
||||
// std::string const credType2 = "fghijk";
|
||||
// std::string const credType3 = "0123456";
|
||||
// char const uri[] = "uri";
|
||||
|
||||
Account const alan{"alan"};
|
||||
Account const bob{"bob"};
|
||||
Account const issuer{"issuer"};
|
||||
|
||||
{
|
||||
Env env(*this);
|
||||
// Env env(*this, envconfig(), {}, nullptr,
|
||||
// beast::severities::kTrace);
|
||||
env.fund(XRP(5000), alan, bob, issuer);
|
||||
env.close();
|
||||
|
||||
// // create escrow
|
||||
// auto const seq = env.seq(alan);
|
||||
// auto const k = keylet::escrow(alan, seq);
|
||||
// // auto const allowance = 3'600;
|
||||
// auto escrowCreate = escrow::create(alan, bob, XRP(1000));
|
||||
// XRPAmount txnFees = env.current()->fees().base + 1000;
|
||||
// env(escrowCreate,
|
||||
// escrow::finish_function(wasmHex),
|
||||
// escrow::finish_time(env.now() + 11s),
|
||||
// escrow::cancel_time(env.now() + 100s),
|
||||
// escrow::data("1000000000"), // 1000 XRP in drops
|
||||
// memodata("memo1234567"),
|
||||
// memodata("2memo1234567"),
|
||||
// fee(txnFees));
|
||||
|
||||
// // create depositPreauth
|
||||
// auto const k = keylet::depositPreauth(
|
||||
// bob,
|
||||
// {{issuer.id(), makeSlice(credType)},
|
||||
// {issuer.id(), makeSlice(credType2)},
|
||||
// {issuer.id(), makeSlice(credType3)}});
|
||||
// env(deposit::authCredentials(
|
||||
// bob,
|
||||
// {{issuer, credType},
|
||||
// {issuer, credType2},
|
||||
// {issuer, credType3}}));
|
||||
|
||||
// create nft
|
||||
[[maybe_unused]] uint256 const nft0{token::getNextID(env, alan, 0u)};
|
||||
env(token::mint(alan, 0u));
|
||||
auto const k = keylet::nftoffer(alan, 0);
|
||||
[[maybe_unused]] uint256 const nft1{token::getNextID(env, alan, 0u)};
|
||||
|
||||
env(token::mint(alan, 0u),
|
||||
token::uri("https://github.com/XRPLF/XRPL-Standards/discussions/"
|
||||
"279?id=github.com/XRPLF/XRPL-Standards/discussions/"
|
||||
"279&ut=github.com/XRPLF/XRPL-Standards/discussions/"
|
||||
"279&sid=github.com/XRPLF/XRPL-Standards/discussions/"
|
||||
"279&aot=github.com/XRPLF/XRPL-Standards/disc"));
|
||||
[[maybe_unused]] uint256 const nft2{token::getNextID(env, alan, 0u)};
|
||||
env(token::mint(alan, 0u));
|
||||
env.close();
|
||||
|
||||
std::shared_ptr<HostFunctions> hfs(new PerfHostFunctions(env, k, env.tx()));
|
||||
|
||||
auto re = runEscrowWasm(perfWasm, hfs, ESCROW_FUNCTION_NAME);
|
||||
if (BEAST_EXPECT(re.has_value()))
|
||||
{
|
||||
BEAST_EXPECT(re->result);
|
||||
std::cout << "Res: " << re->result << " cost: " << re->cost << std::endl;
|
||||
}
|
||||
|
||||
// env(escrow::finish(alan, alan, seq),
|
||||
// escrow::comp_allowance(allowance),
|
||||
// fee(txnFees),
|
||||
// ter(tesSUCCESS));
|
||||
|
||||
env.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testCodecovWasm()
|
||||
{
|
||||
testcase("Codecov wasm test");
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this};
|
||||
|
||||
auto const codecovWasm = hexToBytes(codecovTestsWasmHex);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
|
||||
auto const allowance = 339'303;
|
||||
auto re = runEscrowWasm(codecovWasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance);
|
||||
|
||||
checkResult(re, 1, allowance);
|
||||
}
|
||||
|
||||
void
|
||||
testDisabledFloat()
|
||||
{
|
||||
testcase("disabled float");
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env{*this};
|
||||
|
||||
auto disabledFloatWasm = hexToBytes(disabledFloatHex);
|
||||
std::string const funcName("finish");
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
|
||||
{
|
||||
// f32 set constant, opcode disabled exception
|
||||
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
|
||||
if (BEAST_EXPECT(!re.has_value()))
|
||||
{
|
||||
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// f32 add, can't create module exception
|
||||
disabledFloatWasm[0x117] = 0x92;
|
||||
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
|
||||
if (BEAST_EXPECT(!re.has_value()))
|
||||
{
|
||||
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testWasmMemory()
|
||||
{
|
||||
testcase("Wasm additional memory limit tests");
|
||||
BEAST_EXPECT(runFinishFunction(memoryPointerAtLimitHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryPointerOverLimitHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(memoryOffsetOverLimitHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(memoryEndOfWordOverLimitHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(memoryGrow0To1PageHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryGrow1To0PageHex).value() == -1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryLastByteOf8MBHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryGrow1MoreThan8MBHex).value() == -1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryGrow0MoreThan8MBHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(memoryInit1MoreThan8MBHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(memoryNegativeAddressHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmTable()
|
||||
{
|
||||
testcase("Wasm table limit tests");
|
||||
BEAST_EXPECT(runFinishFunction(table64ElementsHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(table65ElementsHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(table2TablesHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(table0ElementsHex).value() == 1);
|
||||
BEAST_EXPECT(runFinishFunction(tableUintMaxHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmProposal()
|
||||
{
|
||||
testcase("Wasm disabled proposal tests");
|
||||
BEAST_EXPECT(runFinishFunction(proposalMutableGlobalHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalGcStructNewHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalMultiValueHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalSignExtHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalFloatToIntHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalBulkMemoryHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalRefTypesHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalTailCallHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalExtendedConstHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalMultiMemoryHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalCustomPageSizesHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalMemory64Hex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(proposalWideArithmeticHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmTrap()
|
||||
{
|
||||
testcase("Wasm trap tests");
|
||||
BEAST_EXPECT(runFinishFunction(trapDivideBy0Hex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(trapIntOverflowHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(trapUnreachableHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(trapNullCallHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(trapFuncSigMismatchHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmWasi()
|
||||
{
|
||||
testcase("Wasm Wasi tests");
|
||||
BEAST_EXPECT(runFinishFunction(wasiGetTimeHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(wasiPrintHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testWasmSectionCorruption()
|
||||
{
|
||||
testcase("Wasm Section Corruption tests");
|
||||
BEAST_EXPECT(runFinishFunction(badMagicNumberHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(badVersionNumberHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(lyingHeaderHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(neverEndingNumberHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(vectorLieHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(sectionOrderingHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(ghostPayloadHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(junkAfterSectionHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(invalidSectionIdHex).has_value() == false);
|
||||
BEAST_EXPECT(runFinishFunction(localVariableBombHex).has_value() == false);
|
||||
}
|
||||
|
||||
void
|
||||
testStartFunctionLoop()
|
||||
{
|
||||
testcase("infinite loop in start function");
|
||||
|
||||
using namespace test::jtx;
|
||||
Env env(*this);
|
||||
|
||||
auto const startLoopWasm = hexToBytes(startLoopHex);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto checkRes = engine.check(startLoopWasm, "finish", {}, imports, hfs, env.journal);
|
||||
BEAST_EXPECTS(checkRes == tesSUCCESS, std::to_string(TERtoInt(checkRes)));
|
||||
|
||||
auto re = engine.run(startLoopWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
||||
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
|
||||
}
|
||||
|
||||
void
|
||||
testBadAlloc()
|
||||
{
|
||||
testcase("Wasm Bad Alloc");
|
||||
|
||||
// bad_alloc.c
|
||||
auto const badAllocWasm = hexToBytes(badAllocHex);
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this};
|
||||
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
||||
|
||||
// std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
||||
uint8_t buf1[8] = {7, 8, 9, 10, 11, 12, 13, 14};
|
||||
{ // forged "allocate" return valid address
|
||||
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = sizeof(buf1)}}}};
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
||||
if (BEAST_EXPECT(re))
|
||||
{
|
||||
BEAST_EXPECTS(re->result == 7, std::to_string(re->result));
|
||||
BEAST_EXPECTS(re->cost == 430, std::to_string(re->cost));
|
||||
}
|
||||
}
|
||||
|
||||
{ // return 0 whithout calling wasm
|
||||
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 0}}}};
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
||||
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
|
||||
{ // forged "allocate" return 8Mb (which is more than memory limit)
|
||||
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 1}}}};
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
||||
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
|
||||
{ // forged "allocate" return 0
|
||||
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 2}}}};
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
||||
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
|
||||
{ // forged "allocate" return -1
|
||||
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 3}}}};
|
||||
auto& engine = WasmEngine::instance();
|
||||
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
||||
|
||||
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
||||
}
|
||||
|
||||
{
|
||||
std::string what;
|
||||
try
|
||||
{
|
||||
char const test[] = "test";
|
||||
std::size_t sz = std::numeric_limits<int32_t>::max() + 1ull;
|
||||
auto p = wasmParams(std::string_view(test, sz));
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
what = e.what();
|
||||
}
|
||||
BEAST_EXPECT(what.find("can't allocate memory, size: 2147483648") != std::string::npos);
|
||||
}
|
||||
|
||||
env.close();
|
||||
}
|
||||
|
||||
void
|
||||
testBadAlign()
|
||||
{
|
||||
testcase("Wasm Bad Align");
|
||||
|
||||
// bad_align.c
|
||||
auto const badAlignWasm = hexToBytes(badAlignWasmHex);
|
||||
|
||||
using namespace test::jtx;
|
||||
|
||||
Env env{*this};
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
auto imports = createWasmImport(*hfs);
|
||||
|
||||
{ // Calls float_from_uint with bad alignment.
|
||||
// Can be checked through codecov
|
||||
auto& engine = WasmEngine::instance();
|
||||
|
||||
auto re = engine.run(badAlignWasm, "test", {}, imports, hfs, 1'000'000, env.journal);
|
||||
if (BEAST_EXPECTS(re, transToken(re.error())))
|
||||
{
|
||||
BEAST_EXPECTS(re->result == 0x684f7941, std::to_string(re->result));
|
||||
}
|
||||
}
|
||||
|
||||
env.close();
|
||||
}
|
||||
|
||||
void
|
||||
testReturnType()
|
||||
{
|
||||
using namespace test::jtx;
|
||||
Env env(*this);
|
||||
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
||||
|
||||
// return int64.
|
||||
{ // (module
|
||||
// (memory (export "memory") 1)
|
||||
// (func (export "finish") (result i64)
|
||||
// i64.const 0x100000000))
|
||||
auto const wasmHex =
|
||||
"0061736d010000000105016000017e030201000503010001"
|
||||
"071302066d656d6f727902000666696e69736800000a0a01"
|
||||
"08004280808080100b";
|
||||
auto const wasm = hexToBytes(wasmHex);
|
||||
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
|
||||
// return void. wasmi return execution error
|
||||
{ //(module
|
||||
// (type (;0;) (func))
|
||||
// (func (;0;) (type 0)
|
||||
// return)
|
||||
// (memory (;0;) 1)
|
||||
// (export "memory" (memory 0))
|
||||
// (export "finish" (func 0)))
|
||||
auto const wasmHex =
|
||||
"0061736d01000000010401600000030201000503010001071302066d656d6f"
|
||||
"727902000666696e69736800000a050103000f0b";
|
||||
auto const wasm = hexToBytes(wasmHex);
|
||||
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
|
||||
// return i32, i32. wasmi doesn't create module
|
||||
{ //(module
|
||||
// (memory (export "memory") 1)
|
||||
// (func (export "finish") (result i32 i32)
|
||||
// i32.const 0x10000000
|
||||
// i32.const 0x100000FF))
|
||||
auto const wasmHex =
|
||||
"0061736d010000000106016000027f7f030201000503010001071302066d65"
|
||||
"6d6f727902000666696e69736800000a10010e0041808080800141ff818080"
|
||||
"010b";
|
||||
auto const wasm = hexToBytes(wasmHex);
|
||||
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
||||
BEAST_EXPECT(!re);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testSwapBytes()
|
||||
{
|
||||
testcase("Wasm swap bytes");
|
||||
|
||||
uint64_t const SWAP_DATAU64 = 0x123456789abcdeffull;
|
||||
uint64_t const REVERSE_SWAP_DATAU64 = 0xffdebc9a78563412ull;
|
||||
int64_t const SWAP_DATAI64 = 0x123456789abcdeffll;
|
||||
int64_t const REVERSE_SWAP_DATAI64 = 0xffdebc9a78563412ll;
|
||||
|
||||
uint32_t const SWAP_DATAU32 = 0x12789aff;
|
||||
uint32_t const REVERSE_SWAP_DATAU32 = 0xff9a7812;
|
||||
int32_t const SWAP_DATAI32 = 0x12789aff;
|
||||
int32_t const REVERSE_SWAP_DATAI32 = 0xff9a7812;
|
||||
|
||||
uint16_t const SWAP_DATAU16 = 0x12ff;
|
||||
uint16_t const REVERSE_SWAP_DATAU16 = 0xff12;
|
||||
int16_t const SWAP_DATAI16 = 0x12ff;
|
||||
int16_t const REVERSE_SWAP_DATAI16 = 0xff12;
|
||||
|
||||
uint64_t b1 = SWAP_DATAU64;
|
||||
int64_t b2 = SWAP_DATAI64;
|
||||
b1 = adjustWasmEndianessHlp(b1);
|
||||
b2 = adjustWasmEndianessHlp(b2);
|
||||
BEAST_EXPECT(b1 == REVERSE_SWAP_DATAU64);
|
||||
BEAST_EXPECT(b2 == REVERSE_SWAP_DATAI64);
|
||||
b1 = adjustWasmEndianessHlp(b1);
|
||||
b2 = adjustWasmEndianessHlp(b2);
|
||||
BEAST_EXPECT(b1 == SWAP_DATAU64);
|
||||
BEAST_EXPECT(b2 == SWAP_DATAI64);
|
||||
|
||||
uint32_t b3 = SWAP_DATAU32;
|
||||
int32_t b4 = SWAP_DATAI32;
|
||||
b3 = adjustWasmEndianessHlp(b3);
|
||||
b4 = adjustWasmEndianessHlp(b4);
|
||||
BEAST_EXPECT(b3 == REVERSE_SWAP_DATAU32);
|
||||
BEAST_EXPECT(b4 == REVERSE_SWAP_DATAI32);
|
||||
b3 = adjustWasmEndianessHlp(b3);
|
||||
b4 = adjustWasmEndianessHlp(b4);
|
||||
BEAST_EXPECT(b3 == SWAP_DATAU32);
|
||||
BEAST_EXPECT(b4 == SWAP_DATAI32);
|
||||
|
||||
uint16_t b5 = SWAP_DATAU16;
|
||||
int16_t b6 = SWAP_DATAI16;
|
||||
b5 = adjustWasmEndianessHlp(b5);
|
||||
b6 = adjustWasmEndianessHlp(b6);
|
||||
BEAST_EXPECT(b5 == REVERSE_SWAP_DATAU16);
|
||||
BEAST_EXPECT(b6 == REVERSE_SWAP_DATAI16);
|
||||
b5 = adjustWasmEndianessHlp(b5);
|
||||
b6 = adjustWasmEndianessHlp(b6);
|
||||
BEAST_EXPECT(b5 == SWAP_DATAU16);
|
||||
BEAST_EXPECT(b6 == SWAP_DATAI16);
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
testGetDataHelperFunctions();
|
||||
testWasmLib();
|
||||
testBadWasm();
|
||||
testWasmLedgerSqn();
|
||||
|
||||
testWasmFib();
|
||||
testWasmSha();
|
||||
testWasmB58();
|
||||
|
||||
testHFCost();
|
||||
testEscrowWasmDN();
|
||||
testFloat();
|
||||
|
||||
testCodecovWasm();
|
||||
testDisabledFloat();
|
||||
|
||||
testWasmMemory();
|
||||
testWasmTable();
|
||||
testWasmProposal();
|
||||
testWasmTrap();
|
||||
testWasmWasi();
|
||||
testWasmSectionCorruption();
|
||||
|
||||
testStartFunctionLoop();
|
||||
testBadAlloc();
|
||||
testBadAlign();
|
||||
testReturnType();
|
||||
testSwapBytes();
|
||||
|
||||
// perfTest();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl);
|
||||
|
||||
} // namespace test
|
||||
} // namespace xrpl
|
||||
3
src/test/app/wasm_fixtures/.gitignore
vendored
3
src/test/app/wasm_fixtures/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
**/target
|
||||
**/debug
|
||||
*.wasm
|
||||
171
src/test/app/wasm_fixtures/all_host_functions/Cargo.lock
generated
171
src/test/app/wasm_fixtures/all_host_functions/Cargo.lock
generated
@@ -1,171 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "all_host_functions"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"xrpl-wasm-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-address-macro"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#1b27d310dedb4d1279407cf3a40f6858be0e3f14"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"quote",
|
||||
"sha2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-wasm-stdlib"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#1b27d310dedb4d1279407cf3a40f6858be0e3f14"
|
||||
dependencies = [
|
||||
"xrpl-address-macro",
|
||||
]
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
name = "all_host_functions"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
# This empty workspace definition keeps this project independent of the parent workspace
|
||||
[workspace]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
@@ -1,783 +0,0 @@
|
||||
#![cfg_attr(target_arch = "wasm32", no_std)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
extern crate std;
|
||||
|
||||
//
|
||||
// Host Functions Test
|
||||
// Tests 26 host functions (across 7 categories)
|
||||
//
|
||||
// With craft you can run this test with:
|
||||
// craft test --project host_functions_test --test-case host_functions_test
|
||||
//
|
||||
// Amount Format Update:
|
||||
// - XRP amounts now return as 8-byte serialized rippled objects
|
||||
// - IOU and MPT amounts return in variable-length serialized format
|
||||
// - Format details: https://xrpl.org/docs/references/protocol/binary-format#amount-fields
|
||||
//
|
||||
// Error Code Ranges:
|
||||
// -100 to -199: Ledger Header Functions (3 functions)
|
||||
// -200 to -299: Transaction Data Functions (5 functions)
|
||||
// -300 to -399: Current Ledger Object Functions (4 functions)
|
||||
// -400 to -499: Any Ledger Object Functions (5 functions)
|
||||
// -500 to -599: Keylet Generation Functions (4 functions)
|
||||
// -600 to -699: Utility Functions (4 functions)
|
||||
// -700 to -799: Data Update Functions (1 function)
|
||||
//
|
||||
|
||||
use xrpl_std::core::current_tx::escrow_finish::EscrowFinish;
|
||||
use xrpl_std::core::current_tx::traits::TransactionCommonFields;
|
||||
use xrpl_std::host;
|
||||
use xrpl_std::host::trace::{trace, trace_account_buf, trace_data, trace_num, DataRepr};
|
||||
use xrpl_std::sfield;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn finish() -> i32 {
|
||||
let _ = trace("=== HOST FUNCTIONS TEST ===");
|
||||
let _ = trace("Testing 26 host functions");
|
||||
|
||||
// Category 1: Ledger Header Data Functions (3 functions)
|
||||
// Error range: -100 to -199
|
||||
match test_ledger_header_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 2: Transaction Data Functions (5 functions)
|
||||
// Error range: -200 to -299
|
||||
match test_transaction_data_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 3: Current Ledger Object Functions (4 functions)
|
||||
// Error range: -300 to -399
|
||||
match test_current_ledger_object_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 4: Any Ledger Object Functions (5 functions)
|
||||
// Error range: -400 to -499
|
||||
match test_any_ledger_object_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 5: Keylet Generation Functions (4 functions)
|
||||
// Error range: -500 to -599
|
||||
match test_keylet_generation_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 6: Utility Functions (4 functions)
|
||||
// Error range: -600 to -699
|
||||
match test_utility_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
// Category 7: Data Update Functions (1 function)
|
||||
// Error range: -700 to -799
|
||||
match test_data_update_functions() {
|
||||
0 => (),
|
||||
err => return err,
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: All host function tests passed!");
|
||||
1 // Success return code for WASM finish function
|
||||
}
|
||||
|
||||
/// Test Category 1: Ledger Header Data Functions (3 functions)
|
||||
/// - get_ledger_sqn() - Get ledger sequence number
|
||||
/// - get_parent_ledger_time() - Get parent ledger timestamp
|
||||
/// - get_parent_ledger_hash() - Get parent ledger hash
|
||||
fn test_ledger_header_functions() -> i32 {
|
||||
let _ = trace("--- Category 1: Ledger Header Functions ---");
|
||||
|
||||
// Test 1.1: get_ledger_sqn() - should return current ledger sequence number
|
||||
let mut sqn_buffer = [0u8; 4];
|
||||
let sqn_result = unsafe { host::get_ledger_sqn(sqn_buffer.as_mut_ptr(), sqn_buffer.len()) };
|
||||
|
||||
if sqn_result <= 0 {
|
||||
let _ = trace_num("ERROR: get_ledger_sqn failed:", sqn_result as i64);
|
||||
return -101; // Ledger sequence number test failed
|
||||
}
|
||||
let ledger_sqn = u32::from_be_bytes(sqn_buffer);
|
||||
let _ = trace_num("Ledger sequence number:", ledger_sqn as i64);
|
||||
|
||||
// Test 1.2: get_parent_ledger_time() - should return parent ledger timestamp
|
||||
let mut time_buffer = [0u8; 4];
|
||||
let time_result =
|
||||
unsafe { host::get_parent_ledger_time(time_buffer.as_mut_ptr(), time_buffer.len()) };
|
||||
|
||||
if time_result <= 0 {
|
||||
let _ = trace_num("ERROR: get_parent_ledger_time failed:", time_result as i64);
|
||||
return -102; // Parent ledger time test failed
|
||||
}
|
||||
let parent_ledger_time = u32::from_be_bytes(time_buffer);
|
||||
let _ = trace_num("Parent ledger time:", parent_ledger_time as i64);
|
||||
|
||||
// Test 1.3: get_parent_ledger_hash() - should return parent ledger hash (32 bytes)
|
||||
let mut hash_buffer = [0u8; 32];
|
||||
let hash_result =
|
||||
unsafe { host::get_parent_ledger_hash(hash_buffer.as_mut_ptr(), hash_buffer.len()) };
|
||||
|
||||
if hash_result != 32 {
|
||||
let _ = trace_num(
|
||||
"ERROR: get_parent_ledger_hash wrong length:",
|
||||
hash_result as i64,
|
||||
);
|
||||
return -103; // Parent ledger hash test failed - should be exactly 32 bytes
|
||||
}
|
||||
let _ = trace_data("Parent ledger hash:", &hash_buffer, DataRepr::AsHex);
|
||||
|
||||
let _ = trace("SUCCESS: Ledger header functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 2: Transaction Data Functions (5 functions)
|
||||
/// Tests all functions for accessing current transaction data
|
||||
fn test_transaction_data_functions() -> i32 {
|
||||
let _ = trace("--- Category 2: Transaction Data Functions ---");
|
||||
|
||||
// Test 2.1: get_tx_field() - Basic transaction field access
|
||||
// Test with Account field (required, 20 bytes)
|
||||
let mut account_buffer = [0u8; 20];
|
||||
let account_len = unsafe {
|
||||
host::get_tx_field(
|
||||
sfield::Account,
|
||||
account_buffer.as_mut_ptr(),
|
||||
account_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if account_len != 20 {
|
||||
let _ = trace_num(
|
||||
"ERROR: get_tx_field(Account) wrong length:",
|
||||
account_len as i64,
|
||||
);
|
||||
return -201; // Basic transaction field test failed
|
||||
}
|
||||
let _ = trace_account_buf("Transaction Account:", &account_buffer);
|
||||
|
||||
// Test with Fee field (XRP amount - 8 bytes in new serialized format)
|
||||
// New format: XRP amounts are always 8 bytes (positive: value | cPositive flag, negative: just value)
|
||||
let mut fee_buffer = [0u8; 8];
|
||||
let fee_len =
|
||||
unsafe { host::get_tx_field(sfield::Fee, fee_buffer.as_mut_ptr(), fee_buffer.len()) };
|
||||
|
||||
if fee_len != 8 {
|
||||
let _ = trace_num(
|
||||
"ERROR: get_tx_field(Fee) wrong length (expected 8 bytes for XRP):",
|
||||
fee_len as i64,
|
||||
);
|
||||
return -202; // Fee field test failed - XRP amounts should be exactly 8 bytes
|
||||
}
|
||||
let _ = trace_num("Transaction Fee length:", fee_len as i64);
|
||||
let _ = trace_data(
|
||||
"Transaction Fee (serialized XRP amount):",
|
||||
&fee_buffer,
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
|
||||
// Test with Sequence field (required, 4 bytes uint32)
|
||||
let mut seq_buffer = [0u8; 4];
|
||||
let seq_len =
|
||||
unsafe { host::get_tx_field(sfield::Sequence, seq_buffer.as_mut_ptr(), seq_buffer.len()) };
|
||||
|
||||
if seq_len != 4 {
|
||||
let _ = trace_num(
|
||||
"ERROR: get_tx_field(Sequence) wrong length:",
|
||||
seq_len as i64,
|
||||
);
|
||||
return -203; // Sequence field test failed
|
||||
}
|
||||
let _ = trace_data("Transaction Sequence:", &seq_buffer, DataRepr::AsHex);
|
||||
|
||||
// NOTE: get_tx_field2() through get_tx_field6() have been deprecated.
|
||||
// Use get_tx_field() with appropriate parameters for all transaction field access.
|
||||
|
||||
// Test 2.2: get_tx_nested_field() - Nested field access with locator
|
||||
let locator = [0x01, 0x00]; // Simple locator for first element
|
||||
let mut nested_buffer = [0u8; 32];
|
||||
let nested_result = unsafe {
|
||||
host::get_tx_nested_field(
|
||||
locator.as_ptr(),
|
||||
locator.len(),
|
||||
nested_buffer.as_mut_ptr(),
|
||||
nested_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if nested_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_tx_nested_field not applicable:",
|
||||
nested_result as i64,
|
||||
);
|
||||
// Expected - locator may not match transaction structure
|
||||
} else {
|
||||
let _ = trace_num("Nested field length:", nested_result as i64);
|
||||
let _ = trace_data(
|
||||
"Nested field:",
|
||||
&nested_buffer[..nested_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 2.3: get_tx_array_len() - Get array length
|
||||
let signers_len = unsafe { host::get_tx_array_len(sfield::Signers) };
|
||||
let _ = trace_num("Signers array length:", signers_len as i64);
|
||||
|
||||
let memos_len = unsafe { host::get_tx_array_len(sfield::Memos) };
|
||||
let _ = trace_num("Memos array length:", memos_len as i64);
|
||||
|
||||
// Test 2.4: get_tx_nested_array_len() - Get nested array length with locator
|
||||
let nested_array_len =
|
||||
unsafe { host::get_tx_nested_array_len(locator.as_ptr(), locator.len()) };
|
||||
|
||||
if nested_array_len < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_tx_nested_array_len not applicable:",
|
||||
nested_array_len as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num("Nested array length:", nested_array_len as i64);
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: Transaction data functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 3: Current Ledger Object Functions (4 functions)
|
||||
/// Tests functions that access the current ledger object being processed
|
||||
fn test_current_ledger_object_functions() -> i32 {
|
||||
let _ = trace("--- Category 3: Current Ledger Object Functions ---");
|
||||
|
||||
// Test 3.1: get_current_ledger_obj_field() - Access field from current ledger object
|
||||
// Test with Balance field (XRP amount - 8 bytes in new serialized format)
|
||||
let mut balance_buffer = [0u8; 8];
|
||||
let balance_result = unsafe {
|
||||
host::get_current_ledger_obj_field(
|
||||
sfield::Balance,
|
||||
balance_buffer.as_mut_ptr(),
|
||||
balance_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if balance_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_current_ledger_obj_field(Balance) failed (may be expected):",
|
||||
balance_result as i64,
|
||||
);
|
||||
// This might fail if current ledger object doesn't have balance field
|
||||
} else if balance_result == 8 {
|
||||
let _ = trace_num(
|
||||
"Current object balance length (XRP amount):",
|
||||
balance_result as i64,
|
||||
);
|
||||
let _ = trace_data(
|
||||
"Current object balance (serialized XRP amount):",
|
||||
&balance_buffer,
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num(
|
||||
"Current object balance length (non-XRP amount):",
|
||||
balance_result as i64,
|
||||
);
|
||||
let _ = trace_data(
|
||||
"Current object balance:",
|
||||
&balance_buffer[..balance_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test with Account field
|
||||
let mut current_account_buffer = [0u8; 20];
|
||||
let current_account_result = unsafe {
|
||||
host::get_current_ledger_obj_field(
|
||||
sfield::Account,
|
||||
current_account_buffer.as_mut_ptr(),
|
||||
current_account_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if current_account_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_current_ledger_obj_field(Account) failed:",
|
||||
current_account_result as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_account_buf("Current ledger object account:", ¤t_account_buffer);
|
||||
}
|
||||
|
||||
// Test 3.2: get_current_ledger_obj_nested_field() - Nested field access
|
||||
let locator = [0x01, 0x00]; // Simple locator
|
||||
let mut current_nested_buffer = [0u8; 32];
|
||||
let current_nested_result = unsafe {
|
||||
host::get_current_ledger_obj_nested_field(
|
||||
locator.as_ptr(),
|
||||
locator.len(),
|
||||
current_nested_buffer.as_mut_ptr(),
|
||||
current_nested_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if current_nested_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_current_ledger_obj_nested_field not applicable:",
|
||||
current_nested_result as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num("Current nested field length:", current_nested_result as i64);
|
||||
let _ = trace_data(
|
||||
"Current nested field:",
|
||||
¤t_nested_buffer[..current_nested_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 3.3: get_current_ledger_obj_array_len() - Array length in current object
|
||||
let current_array_len = unsafe { host::get_current_ledger_obj_array_len(sfield::Signers) };
|
||||
let _ = trace_num(
|
||||
"Current object Signers array length:",
|
||||
current_array_len as i64,
|
||||
);
|
||||
|
||||
// Test 3.4: get_current_ledger_obj_nested_array_len() - Nested array length
|
||||
let current_nested_array_len =
|
||||
unsafe { host::get_current_ledger_obj_nested_array_len(locator.as_ptr(), locator.len()) };
|
||||
|
||||
if current_nested_array_len < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_current_ledger_obj_nested_array_len not applicable:",
|
||||
current_nested_array_len as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num(
|
||||
"Current nested array length:",
|
||||
current_nested_array_len as i64,
|
||||
);
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: Current ledger object functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 4: Any Ledger Object Functions (5 functions)
|
||||
/// Tests functions that work with cached ledger objects
|
||||
fn test_any_ledger_object_functions() -> i32 {
|
||||
let _ = trace("--- Category 4: Any Ledger Object Functions ---");
|
||||
|
||||
// First we need to cache a ledger object to test the other functions
|
||||
// Get the account from transaction and generate its keylet
|
||||
let escrow_finish = EscrowFinish;
|
||||
let account_id = escrow_finish.get_account().unwrap();
|
||||
|
||||
// Test 4.1: cache_ledger_obj() - Cache a ledger object
|
||||
let mut keylet_buffer = [0u8; 32];
|
||||
let keylet_result = unsafe {
|
||||
host::account_keylet(
|
||||
account_id.0.as_ptr(),
|
||||
account_id.0.len(),
|
||||
keylet_buffer.as_mut_ptr(),
|
||||
keylet_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if keylet_result != 32 {
|
||||
let _ = trace_num(
|
||||
"ERROR: account_keylet failed for caching test:",
|
||||
keylet_result as i64,
|
||||
);
|
||||
return -401; // Keylet generation failed for caching test
|
||||
}
|
||||
|
||||
let cache_result =
|
||||
unsafe { host::cache_ledger_obj(keylet_buffer.as_ptr(), keylet_result as usize, 0) };
|
||||
|
||||
if cache_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: cache_ledger_obj failed (expected with test fixtures):",
|
||||
cache_result as i64,
|
||||
);
|
||||
// Test fixtures may not contain the account object - this is expected
|
||||
// We'll test the interface but expect failures
|
||||
|
||||
// Test 4.2-4.5 with invalid slot (should fail gracefully)
|
||||
let mut test_buffer = [0u8; 32];
|
||||
|
||||
// Test get_ledger_obj_field with invalid slot
|
||||
let field_result = unsafe {
|
||||
host::get_ledger_obj_field(
|
||||
1,
|
||||
sfield::Balance,
|
||||
test_buffer.as_mut_ptr(),
|
||||
test_buffer.len(),
|
||||
)
|
||||
};
|
||||
if field_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_field failed as expected (no cached object):",
|
||||
field_result as i64,
|
||||
);
|
||||
}
|
||||
|
||||
// Test get_ledger_obj_nested_field with invalid slot
|
||||
let locator = [0x01, 0x00];
|
||||
let nested_result = unsafe {
|
||||
host::get_ledger_obj_nested_field(
|
||||
1,
|
||||
locator.as_ptr(),
|
||||
locator.len(),
|
||||
test_buffer.as_mut_ptr(),
|
||||
test_buffer.len(),
|
||||
)
|
||||
};
|
||||
if nested_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_nested_field failed as expected:",
|
||||
nested_result as i64,
|
||||
);
|
||||
}
|
||||
|
||||
// Test get_ledger_obj_array_len with invalid slot
|
||||
let array_result = unsafe { host::get_ledger_obj_array_len(1, sfield::Signers) };
|
||||
if array_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_array_len failed as expected:",
|
||||
array_result as i64,
|
||||
);
|
||||
}
|
||||
|
||||
// Test get_ledger_obj_nested_array_len with invalid slot
|
||||
let nested_array_result =
|
||||
unsafe { host::get_ledger_obj_nested_array_len(1, locator.as_ptr(), locator.len()) };
|
||||
if nested_array_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_nested_array_len failed as expected:",
|
||||
nested_array_result as i64,
|
||||
);
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: Any ledger object functions (interface tested)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we successfully cached an object, test the access functions
|
||||
let slot = cache_result;
|
||||
let _ = trace_num("Successfully cached object in slot:", slot as i64);
|
||||
|
||||
// Test 4.2: get_ledger_obj_field() - Access field from cached object
|
||||
let mut cached_balance_buffer = [0u8; 8];
|
||||
let cached_balance_result = unsafe {
|
||||
host::get_ledger_obj_field(
|
||||
slot,
|
||||
sfield::Balance,
|
||||
cached_balance_buffer.as_mut_ptr(),
|
||||
cached_balance_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if cached_balance_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_field(Balance) failed:",
|
||||
cached_balance_result as i64,
|
||||
);
|
||||
} else if cached_balance_result == 8 {
|
||||
let _ = trace_num(
|
||||
"Cached object balance length (XRP amount):",
|
||||
cached_balance_result as i64,
|
||||
);
|
||||
let _ = trace_data(
|
||||
"Cached object balance (serialized XRP amount):",
|
||||
&cached_balance_buffer,
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num(
|
||||
"Cached object balance length (non-XRP amount):",
|
||||
cached_balance_result as i64,
|
||||
);
|
||||
let _ = trace_data(
|
||||
"Cached object balance:",
|
||||
&cached_balance_buffer[..cached_balance_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 4.3: get_ledger_obj_nested_field() - Nested field from cached object
|
||||
let locator = [0x01, 0x00];
|
||||
let mut cached_nested_buffer = [0u8; 32];
|
||||
let cached_nested_result = unsafe {
|
||||
host::get_ledger_obj_nested_field(
|
||||
slot,
|
||||
locator.as_ptr(),
|
||||
locator.len(),
|
||||
cached_nested_buffer.as_mut_ptr(),
|
||||
cached_nested_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if cached_nested_result < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_nested_field not applicable:",
|
||||
cached_nested_result as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num("Cached nested field length:", cached_nested_result as i64);
|
||||
let _ = trace_data(
|
||||
"Cached nested field:",
|
||||
&cached_nested_buffer[..cached_nested_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 4.4: get_ledger_obj_array_len() - Array length from cached object
|
||||
let cached_array_len = unsafe { host::get_ledger_obj_array_len(slot, sfield::Signers) };
|
||||
let _ = trace_num(
|
||||
"Cached object Signers array length:",
|
||||
cached_array_len as i64,
|
||||
);
|
||||
|
||||
// Test 4.5: get_ledger_obj_nested_array_len() - Nested array length from cached object
|
||||
let cached_nested_array_len =
|
||||
unsafe { host::get_ledger_obj_nested_array_len(slot, locator.as_ptr(), locator.len()) };
|
||||
|
||||
if cached_nested_array_len < 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_ledger_obj_nested_array_len not applicable:",
|
||||
cached_nested_array_len as i64,
|
||||
);
|
||||
} else {
|
||||
let _ = trace_num(
|
||||
"Cached nested array length:",
|
||||
cached_nested_array_len as i64,
|
||||
);
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: Any ledger object functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 5: Keylet Generation Functions (4 functions)
|
||||
/// Tests keylet generation functions for different ledger entry types
|
||||
fn test_keylet_generation_functions() -> i32 {
|
||||
let _ = trace("--- Category 5: Keylet Generation Functions ---");
|
||||
|
||||
let escrow_finish = EscrowFinish;
|
||||
let account_id = escrow_finish.get_account().unwrap();
|
||||
|
||||
// Test 5.1: account_keylet() - Generate keylet for account
|
||||
let mut account_keylet_buffer = [0u8; 32];
|
||||
let account_keylet_result = unsafe {
|
||||
host::account_keylet(
|
||||
account_id.0.as_ptr(),
|
||||
account_id.0.len(),
|
||||
account_keylet_buffer.as_mut_ptr(),
|
||||
account_keylet_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if account_keylet_result != 32 {
|
||||
let _ = trace_num(
|
||||
"ERROR: account_keylet failed:",
|
||||
account_keylet_result as i64,
|
||||
);
|
||||
return -501; // Account keylet generation failed
|
||||
}
|
||||
let _ = trace_data("Account keylet:", &account_keylet_buffer, DataRepr::AsHex);
|
||||
|
||||
// Test 5.2: credential_keylet() - Generate keylet for credential
|
||||
let mut credential_keylet_buffer = [0u8; 32];
|
||||
let credential_keylet_result = unsafe {
|
||||
host::credential_keylet(
|
||||
account_id.0.as_ptr(), // Subject
|
||||
account_id.0.len(),
|
||||
account_id.0.as_ptr(), // Issuer - same account for test
|
||||
account_id.0.len(),
|
||||
b"TestType".as_ptr(), // Credential type
|
||||
9usize, // Length of "TestType"
|
||||
credential_keylet_buffer.as_mut_ptr(),
|
||||
credential_keylet_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if credential_keylet_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: credential_keylet failed (expected - interface issue):",
|
||||
credential_keylet_result as i64,
|
||||
);
|
||||
// This is expected to fail due to unusual parameter types
|
||||
} else {
|
||||
let _ = trace_data(
|
||||
"Credential keylet:",
|
||||
&credential_keylet_buffer[..credential_keylet_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 5.3: escrow_keylet() - Generate keylet for escrow
|
||||
let mut escrow_keylet_buffer = [0u8; 32];
|
||||
let sequence_number: i32 = 1000;
|
||||
let sequence_number_bytes = sequence_number.to_be_bytes();
|
||||
let escrow_keylet_result = unsafe {
|
||||
host::escrow_keylet(
|
||||
account_id.0.as_ptr(),
|
||||
account_id.0.len(),
|
||||
sequence_number_bytes.as_ptr(),
|
||||
sequence_number_bytes.len(),
|
||||
escrow_keylet_buffer.as_mut_ptr(),
|
||||
escrow_keylet_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if escrow_keylet_result != 32 {
|
||||
let _ = trace_num("ERROR: escrow_keylet failed:", escrow_keylet_result as i64);
|
||||
return -503; // Escrow keylet generation failed
|
||||
}
|
||||
let _ = trace_data("Escrow keylet:", &escrow_keylet_buffer, DataRepr::AsHex);
|
||||
|
||||
// Test 5.4: oracle_keylet() - Generate keylet for oracle
|
||||
let mut oracle_keylet_buffer = [0u8; 32];
|
||||
let document_id: i32 = 42;
|
||||
let document_id_bytes = document_id.to_be_bytes();
|
||||
let oracle_keylet_result = unsafe {
|
||||
host::oracle_keylet(
|
||||
account_id.0.as_ptr(),
|
||||
account_id.0.len(),
|
||||
document_id_bytes.as_ptr(),
|
||||
document_id_bytes.len(),
|
||||
oracle_keylet_buffer.as_mut_ptr(),
|
||||
oracle_keylet_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if oracle_keylet_result != 32 {
|
||||
let _ = trace_num("ERROR: oracle_keylet failed:", oracle_keylet_result as i64);
|
||||
return -504; // Oracle keylet generation failed
|
||||
}
|
||||
let _ = trace_data("Oracle keylet:", &oracle_keylet_buffer, DataRepr::AsHex);
|
||||
|
||||
let _ = trace("SUCCESS: Keylet generation functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 6: Utility Functions (4 functions)
|
||||
/// Tests utility functions for hashing, NFT access, and tracing
|
||||
fn test_utility_functions() -> i32 {
|
||||
let _ = trace("--- Category 6: Utility Functions ---");
|
||||
|
||||
// Test 6.1: compute_sha512_half() - SHA512 hash computation (first 32 bytes)
|
||||
let test_data = b"Hello, XRPL WASM world!";
|
||||
let mut hash_output = [0u8; 32];
|
||||
let hash_result = unsafe {
|
||||
host::compute_sha512_half(
|
||||
test_data.as_ptr(),
|
||||
test_data.len(),
|
||||
hash_output.as_mut_ptr(),
|
||||
hash_output.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if hash_result != 32 {
|
||||
let _ = trace_num("ERROR: compute_sha512_half failed:", hash_result as i64);
|
||||
return -601; // SHA512 half computation failed
|
||||
}
|
||||
let _ = trace_data("Input data:", test_data, DataRepr::AsHex);
|
||||
let _ = trace_data("SHA512 half hash:", &hash_output, DataRepr::AsHex);
|
||||
|
||||
// Test 6.2: get_nft() - NFT data retrieval
|
||||
let escrow_finish = EscrowFinish;
|
||||
let account_id = escrow_finish.get_account().unwrap();
|
||||
let nft_id = [0u8; 32]; // Dummy NFT ID for testing
|
||||
let mut nft_buffer = [0u8; 256];
|
||||
let nft_result = unsafe {
|
||||
host::get_nft(
|
||||
account_id.0.as_ptr(),
|
||||
account_id.0.len(),
|
||||
nft_id.as_ptr(),
|
||||
nft_id.len(),
|
||||
nft_buffer.as_mut_ptr(),
|
||||
nft_buffer.len(),
|
||||
)
|
||||
};
|
||||
|
||||
if nft_result <= 0 {
|
||||
let _ = trace_num(
|
||||
"INFO: get_nft failed (expected - no such NFT):",
|
||||
nft_result as i64,
|
||||
);
|
||||
// This is expected - test account likely doesn't own the dummy NFT
|
||||
} else {
|
||||
let _ = trace_num("NFT data length:", nft_result as i64);
|
||||
let _ = trace_data(
|
||||
"NFT data:",
|
||||
&nft_buffer[..nft_result as usize],
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
}
|
||||
|
||||
// Test 6.3: trace() - Debug logging with data
|
||||
let trace_message = b"Test trace message";
|
||||
let trace_data_payload = b"payload";
|
||||
let trace_result = unsafe {
|
||||
host::trace(
|
||||
trace_message.as_ptr(),
|
||||
trace_message.len(),
|
||||
trace_data_payload.as_ptr(),
|
||||
trace_data_payload.len(),
|
||||
1, // as_hex = true
|
||||
)
|
||||
};
|
||||
|
||||
if trace_result < 0 {
|
||||
let _ = trace_num("ERROR: trace() failed:", trace_result as i64);
|
||||
return -603; // Trace function failed
|
||||
}
|
||||
let _ = trace_num("Trace function bytes written:", trace_result as i64);
|
||||
|
||||
// Test 6.4: trace_num() - Debug logging with number
|
||||
let test_number = 42i64;
|
||||
let trace_num_result = trace_num("Test number trace", test_number);
|
||||
|
||||
use xrpl_std::host::Result;
|
||||
match trace_num_result {
|
||||
Result::Ok(_) => {
|
||||
let _ = trace_num("Trace_num function succeeded", 0);
|
||||
}
|
||||
Result::Err(_) => {
|
||||
let _ = trace_num("ERROR: trace_num() failed:", -604);
|
||||
return -604; // Trace number function failed
|
||||
}
|
||||
}
|
||||
|
||||
let _ = trace("SUCCESS: Utility functions");
|
||||
0
|
||||
}
|
||||
|
||||
/// Test Category 7: Data Update Functions (1 function)
|
||||
/// Tests the function for modifying the current ledger entry
|
||||
fn test_data_update_functions() -> i32 {
|
||||
let _ = trace("--- Category 7: Data Update Functions ---");
|
||||
|
||||
// Test 7.1: update_data() - Update current ledger entry data
|
||||
let update_payload = b"Updated ledger entry data from WASM test";
|
||||
|
||||
let update_result = unsafe { host::update_data(update_payload.as_ptr(), update_payload.len()) };
|
||||
|
||||
if update_result != update_payload.len() as i32 {
|
||||
let _ = trace_num("ERROR: update_data failed:", update_result as i64);
|
||||
return -701; // Data update failed
|
||||
}
|
||||
|
||||
let _ = trace_data(
|
||||
"Successfully updated ledger entry with:",
|
||||
update_payload,
|
||||
DataRepr::AsHex,
|
||||
);
|
||||
let _ = trace("SUCCESS: Data update functions");
|
||||
0
|
||||
}
|
||||
171
src/test/app/wasm_fixtures/all_keylets/Cargo.lock
generated
171
src/test/app/wasm_fixtures/all_keylets/Cargo.lock
generated
@@ -1,171 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "all_keylets"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"xrpl-wasm-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-address-macro"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=fix-keylets#591160f2dc794b7894e7402dc0c956fca746eedb"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"quote",
|
||||
"sha2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-wasm-stdlib"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=fix-keylets#591160f2dc794b7894e7402dc0c956fca746eedb"
|
||||
dependencies = [
|
||||
"xrpl-address-macro",
|
||||
]
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "all_keylets"
|
||||
version = "0.0.1"
|
||||
|
||||
# This empty workspace definition keeps this project independent of the parent workspace
|
||||
[workspace]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 's'
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "fix-keylets" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
@@ -1,181 +0,0 @@
|
||||
#![cfg_attr(target_arch = "wasm32", no_std)]
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
extern crate std;
|
||||
|
||||
use crate::host::{Error, Result, Result::Err, Result::Ok};
|
||||
use xrpl_std::core::ledger_objects::current_escrow::get_current_escrow;
|
||||
use xrpl_std::core::ledger_objects::current_escrow::CurrentEscrow;
|
||||
use xrpl_std::core::ledger_objects::ledger_object;
|
||||
use xrpl_std::core::ledger_objects::traits::CurrentEscrowFields;
|
||||
use xrpl_std::core::types::account_id::AccountID;
|
||||
use xrpl_std::core::types::currency::Currency;
|
||||
use xrpl_std::core::types::issue::{IouIssue, Issue, XrpIssue};
|
||||
use xrpl_std::core::types::keylets;
|
||||
use xrpl_std::core::types::mpt_id::MptId;
|
||||
use xrpl_std::core::types::uint::Hash256;
|
||||
use xrpl_std::host;
|
||||
use xrpl_std::host::trace::{trace, trace_account, trace_data, trace_num, DataRepr};
|
||||
use xrpl_std::sfield;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn object_exists(
|
||||
keylet_result: Result<keylets::KeyletBytes>,
|
||||
keylet_type: &str,
|
||||
field: i32,
|
||||
) -> Result<bool> {
|
||||
match keylet_result {
|
||||
Ok(keylet) => {
|
||||
let _ = trace_data(keylet_type, &keylet, DataRepr::AsHex);
|
||||
|
||||
let slot = unsafe { host::cache_ledger_obj(keylet.as_ptr(), keylet.len(), 0) };
|
||||
if slot <= 0 {
|
||||
let _ = trace_num("Error: ", slot.into());
|
||||
return Err(Error::from_code(slot));
|
||||
}
|
||||
if field == 0 {
|
||||
let new_field = sfield::PreviousTxnID;
|
||||
let _ = trace_num("Getting field: ", new_field.into());
|
||||
match ledger_object::get_field::<Hash256>(slot, new_field) {
|
||||
Ok(data) => {
|
||||
let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex);
|
||||
}
|
||||
Err(result_code) => {
|
||||
let _ = trace_num("Error getting field: ", result_code.into());
|
||||
return Err(result_code);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let _ = trace_num("Getting field: ", field.into());
|
||||
match ledger_object::get_field::<AccountID>(slot, field) {
|
||||
Ok(data) => {
|
||||
let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex);
|
||||
}
|
||||
Err(result_code) => {
|
||||
let _ = trace_num("Error getting field: ", result_code.into());
|
||||
return Err(result_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
Err(error) => {
|
||||
let _ = trace_num("Error getting keylet: ", error.into());
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn finish() -> i32 {
|
||||
let _ = trace("$$$$$ STARTING WASM EXECUTION $$$$$");
|
||||
|
||||
let escrow: CurrentEscrow = get_current_escrow();
|
||||
|
||||
let account = escrow.get_account().unwrap_or_panic();
|
||||
let _ = trace_account("Account:", &account);
|
||||
|
||||
let destination = escrow.get_destination().unwrap_or_panic();
|
||||
let _ = trace_account("Destination:", &destination);
|
||||
|
||||
let mut seq = 5;
|
||||
|
||||
macro_rules! check_object_exists {
|
||||
($keylet:expr, $type:expr, $field:expr) => {
|
||||
match object_exists($keylet, $type, $field) {
|
||||
Ok(_exists) => {
|
||||
// false isn't returned
|
||||
let _ = trace(concat!(
|
||||
$type,
|
||||
" object exists, proceeding with escrow finish."
|
||||
));
|
||||
}
|
||||
Err(error) => {
|
||||
let _ = trace_num("Current seq value:", seq.try_into().unwrap());
|
||||
return error.code();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let account_keylet = keylets::account_keylet(&account);
|
||||
check_object_exists!(account_keylet, "Account", sfield::Account);
|
||||
|
||||
let currency_code: &[u8; 3] = b"USD";
|
||||
let currency: Currency = Currency::from(*currency_code);
|
||||
let line_keylet = keylets::line_keylet(&account, &destination, ¤cy);
|
||||
check_object_exists!(line_keylet, "Trustline", sfield::Generic);
|
||||
seq += 1;
|
||||
|
||||
let asset1 = Issue::XRP(XrpIssue {});
|
||||
let asset2 = Issue::IOU(IouIssue::new(destination, currency));
|
||||
check_object_exists!(
|
||||
keylets::amm_keylet(&asset1, &asset2),
|
||||
"AMM",
|
||||
sfield::Account
|
||||
);
|
||||
|
||||
let check_keylet = keylets::check_keylet(&account, seq);
|
||||
check_object_exists!(check_keylet, "Check", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let cred_type: &[u8] = b"termsandconditions";
|
||||
let credential_keylet = keylets::credential_keylet(&account, &account, cred_type);
|
||||
check_object_exists!(credential_keylet, "Credential", sfield::Subject);
|
||||
seq += 1;
|
||||
|
||||
let delegate_keylet = keylets::delegate_keylet(&account, &destination);
|
||||
check_object_exists!(delegate_keylet, "Delegate", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let deposit_preauth_keylet = keylets::deposit_preauth_keylet(&account, &destination);
|
||||
check_object_exists!(deposit_preauth_keylet, "DepositPreauth", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let did_keylet = keylets::did_keylet(&account);
|
||||
check_object_exists!(did_keylet, "DID", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let escrow_keylet = keylets::escrow_keylet(&account, seq);
|
||||
check_object_exists!(escrow_keylet, "Escrow", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let mpt_issuance_keylet = keylets::mpt_issuance_keylet(&account, seq);
|
||||
let mpt_id = MptId::new(seq.try_into().unwrap(), account);
|
||||
check_object_exists!(mpt_issuance_keylet, "MPTIssuance", sfield::Issuer);
|
||||
seq += 1;
|
||||
|
||||
let mptoken_keylet = keylets::mptoken_keylet(&mpt_id, &destination);
|
||||
check_object_exists!(mptoken_keylet, "MPToken", sfield::Account);
|
||||
|
||||
let nft_offer_keylet = keylets::nft_offer_keylet(&destination, 6);
|
||||
check_object_exists!(nft_offer_keylet, "NFTokenOffer", sfield::Owner);
|
||||
|
||||
let offer_keylet = keylets::offer_keylet(&account, seq);
|
||||
check_object_exists!(offer_keylet, "Offer", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let paychan_keylet = keylets::paychan_keylet(&account, &destination, seq);
|
||||
check_object_exists!(paychan_keylet, "PayChannel", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let pd_keylet = keylets::permissioned_domain_keylet(&account, seq);
|
||||
check_object_exists!(pd_keylet, "PermissionedDomain", sfield::Owner);
|
||||
seq += 1;
|
||||
|
||||
let signers_keylet = keylets::signers_keylet(&account);
|
||||
check_object_exists!(signers_keylet, "SignerList", sfield::Generic);
|
||||
seq += 1;
|
||||
|
||||
seq += 1; // ticket sequence number is one greater
|
||||
let ticket_keylet = keylets::ticket_keylet(&account, seq);
|
||||
check_object_exists!(ticket_keylet, "Ticket", sfield::Account);
|
||||
seq += 1;
|
||||
|
||||
let vault_keylet = keylets::vault_keylet(&account, seq);
|
||||
check_object_exists!(vault_keylet, "Vault", sfield::Account);
|
||||
// seq += 1;
|
||||
|
||||
1 // All keylets exist, finish the escrow.
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
static char const b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
uint8_t e_data[32 * 1024];
|
||||
|
||||
void*
|
||||
allocate(int sz)
|
||||
{
|
||||
static int idx = 0;
|
||||
if (idx >= 32)
|
||||
return 0;
|
||||
if (sz > 1024)
|
||||
return 0;
|
||||
return &e_data[idx++ << 10];
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(void* p)
|
||||
{
|
||||
}
|
||||
|
||||
extern int32_t
|
||||
b58enco(char* b58, int32_t b58sz, void const* data, int32_t binsz)
|
||||
{
|
||||
uint8_t const* bin = data;
|
||||
int32_t carry;
|
||||
int32_t i, j, high, zcount = 0;
|
||||
int32_t size;
|
||||
|
||||
while (zcount < binsz && !bin[zcount])
|
||||
++zcount;
|
||||
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t* buf = allocate(size);
|
||||
if (!buf)
|
||||
return 0;
|
||||
// memset(buf, 0, size);
|
||||
for (i = 0; i < size; ++i)
|
||||
buf[i] = 0;
|
||||
|
||||
for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
|
||||
{
|
||||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
|
||||
{
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
if (!j)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < size && !buf[j]; ++j)
|
||||
;
|
||||
|
||||
if (b58sz <= zcount + size - j)
|
||||
return 0;
|
||||
|
||||
if (zcount)
|
||||
{
|
||||
// memset(b58, '1', zcount);
|
||||
for (i = 0; i < zcount; ++i)
|
||||
b58[i] = '1';
|
||||
}
|
||||
|
||||
for (i = zcount; j < size; ++i, ++j)
|
||||
b58[i] = b58digits_ordered[buf[j]];
|
||||
b58[i] = '\0';
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t
|
||||
float_from_uint(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
|
||||
int32_t
|
||||
check_keylet(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
|
||||
|
||||
uint8_t e_data1[32 * 1024];
|
||||
uint8_t e_data2[32 * 1024];
|
||||
|
||||
int32_t
|
||||
test1()
|
||||
{
|
||||
e_data1[1] = 0xFF;
|
||||
e_data1[2] = 0xFF;
|
||||
e_data1[3] = 0xFF;
|
||||
e_data1[4] = 0xFF;
|
||||
e_data1[5] = 0xFF;
|
||||
e_data1[6] = 0xFF;
|
||||
e_data1[7] = 0xFF;
|
||||
e_data1[8] = 0xFF;
|
||||
int32_t result = float_from_uint(&e_data1[1], 8, &e_data1[35], 12, 0);
|
||||
return result >= 0 ? *((int32_t*)(&e_data1[36])) : result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
test2()
|
||||
{
|
||||
// Set up misaligned uint32 (seq) at offset 1
|
||||
e_data2[1] = 0xFF;
|
||||
e_data2[2] = 0xFF;
|
||||
e_data2[3] = 0xFF;
|
||||
e_data2[4] = 0xFF;
|
||||
// Set up valid non-zero AccountID (20 bytes) at offset 10
|
||||
for (int i = 0; i < 20; i++)
|
||||
e_data2[10 + i] = i + 1;
|
||||
// Call check_keylet with misaligned uint32 at &e_data2[1] to hit line 72 in HostFuncWrapper.cpp
|
||||
int32_t result = check_keylet(&e_data2[10], 20, &e_data2[1], 4, &e_data2[35], 32);
|
||||
// Return the misaligned value directly to validate it was read correctly (-1 if all 0xFF)
|
||||
return result >= 0 ? *((int32_t*)(&e_data2[36])) : result;
|
||||
}
|
||||
|
||||
int32_t
|
||||
test()
|
||||
{
|
||||
return test1() + test2();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
char buf[1024];
|
||||
|
||||
void*
|
||||
allocate(int sz)
|
||||
{
|
||||
if (!sz)
|
||||
return 0;
|
||||
|
||||
if (sz == 1)
|
||||
return ((void*)(8 * 1024 * 1024));
|
||||
if (sz == 2)
|
||||
return 0;
|
||||
if (sz == 3)
|
||||
return ((void*)(0xFFFFFFFF));
|
||||
|
||||
return &buf[sz];
|
||||
}
|
||||
|
||||
int32_t
|
||||
test(char* p, int32_t sz)
|
||||
{
|
||||
if (!sz)
|
||||
return 0;
|
||||
return p[0];
|
||||
}
|
||||
171
src/test/app/wasm_fixtures/codecov_tests/Cargo.lock
generated
171
src/test/app/wasm_fixtures/codecov_tests/Cargo.lock
generated
@@ -1,171 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bs58"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "codecov_tests"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"xrpl-wasm-stdlib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-address-macro"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#1b27d310dedb4d1279407cf3a40f6858be0e3f14"
|
||||
dependencies = [
|
||||
"bs58",
|
||||
"quote",
|
||||
"sha2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrpl-wasm-stdlib"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#1b27d310dedb4d1279407cf3a40f6858be0e3f14"
|
||||
dependencies = [
|
||||
"xrpl-address-macro",
|
||||
]
|
||||
@@ -1,18 +0,0 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "codecov_tests"
|
||||
version = "0.0.1"
|
||||
|
||||
# This empty workspace definition keeps this project independent of the parent workspace
|
||||
[workspace]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = 's'
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib" }
|
||||
@@ -1,47 +0,0 @@
|
||||
//TODO add docs after discussing the interface
|
||||
//Note that Craft currently does not honor the rounding modes
|
||||
#[allow(unused)]
|
||||
pub const FLOAT_ROUNDING_MODES_TO_NEAREST: i32 = 0;
|
||||
#[allow(unused)]
|
||||
pub const FLOAT_ROUNDING_MODES_TOWARDS_ZERO: i32 = 1;
|
||||
#[allow(unused)]
|
||||
pub const FLOAT_ROUNDING_MODES_DOWNWARD: i32 = 2;
|
||||
#[allow(unused)]
|
||||
pub const FLOAT_ROUNDING_MODES_UPWARD: i32 = 3;
|
||||
|
||||
// pub enum RippledRoundingModes{
|
||||
// ToNearest = 0,
|
||||
// TowardsZero = 1,
|
||||
// DOWNWARD = 2,
|
||||
// UPWARD = 3
|
||||
// }
|
||||
|
||||
#[allow(unused)]
|
||||
#[link(wasm_import_module = "host_lib")]
|
||||
unsafe extern "C" {
|
||||
pub fn get_parent_ledger_hash(out_buff_ptr: i32, out_buff_len: i32) -> i32;
|
||||
|
||||
pub fn cache_ledger_obj(keylet_ptr: i32, keylet_len: i32, cache_num: i32) -> i32;
|
||||
|
||||
pub fn get_tx_nested_array_len(locator_ptr: i32, locator_len: i32) -> i32;
|
||||
|
||||
pub fn account_keylet(
|
||||
account_ptr: i32,
|
||||
account_len: i32,
|
||||
out_buff_ptr: *mut u8,
|
||||
out_buff_len: usize,
|
||||
) -> i32;
|
||||
|
||||
pub fn line_keylet(
|
||||
account1_ptr: *const u8,
|
||||
account1_len: usize,
|
||||
account2_ptr: *const u8,
|
||||
account2_len: usize,
|
||||
currency_ptr: i32,
|
||||
currency_len: i32,
|
||||
out_buff_ptr: *mut u8,
|
||||
out_buff_len: usize,
|
||||
) -> i32;
|
||||
|
||||
pub fn trace_num(msg_read_ptr: i32, msg_read_len: i32, number: i64) -> i32;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,125 +0,0 @@
|
||||
# cspell: disable
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
OPT = "-Oz"
|
||||
|
||||
|
||||
def update_fixture(project_name, wasm):
|
||||
fixture_name = (
|
||||
re.sub(r"_([a-z])", lambda m: m.group(1).upper(), project_name) + "WasmHex"
|
||||
)
|
||||
print(f"Updating fixture: {fixture_name}")
|
||||
|
||||
cpp_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures.cpp"))
|
||||
h_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "fixtures.h"))
|
||||
with open(cpp_path, "r", encoding="utf8") as f:
|
||||
cpp_content = f.read()
|
||||
|
||||
pattern = rf'extern std::string const {fixture_name} =[ \n]+"[^;]*;'
|
||||
if re.search(pattern, cpp_content, flags=re.MULTILINE):
|
||||
updated_cpp_content = re.sub(
|
||||
pattern,
|
||||
f'extern std::string const {fixture_name} = "{wasm}";',
|
||||
cpp_content,
|
||||
flags=re.MULTILINE,
|
||||
)
|
||||
else:
|
||||
with open(h_path, "r", encoding="utf8") as f:
|
||||
h_content = f.read()
|
||||
updated_h_content = (
|
||||
h_content.rstrip() + f"\n\n extern std::string const {fixture_name};\n"
|
||||
)
|
||||
with open(h_path, "w", encoding="utf8") as f:
|
||||
f.write(updated_h_content)
|
||||
updated_cpp_content = (
|
||||
cpp_content.rstrip()
|
||||
+ f'\n\nextern std::string const {fixture_name} = "{wasm}";\n'
|
||||
)
|
||||
|
||||
with open(cpp_path, "w", encoding="utf8") as f:
|
||||
f.write(updated_cpp_content)
|
||||
|
||||
|
||||
def process_rust(project_name):
|
||||
project_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), project_name)
|
||||
)
|
||||
wasm_location = f"target/wasm32v1-none/release/{project_name}.wasm"
|
||||
build_cmd = (
|
||||
f"(cd {project_path} "
|
||||
f"&& cargo build --target wasm32v1-none --release "
|
||||
f"&& wasm-opt {wasm_location} {OPT} -o {wasm_location}"
|
||||
")"
|
||||
)
|
||||
try:
|
||||
subprocess.run(build_cmd, shell=True, check=True)
|
||||
print(f"WASM file for {project_name} has been built and optimized.")
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"exec error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
src_path = os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
f"{project_name}/target/wasm32v1-none/release/{project_name}.wasm",
|
||||
)
|
||||
)
|
||||
with open(src_path, "rb") as f:
|
||||
data = f.read()
|
||||
wasm = data.hex()
|
||||
update_fixture(project_name, wasm)
|
||||
|
||||
|
||||
def process_c(project_name):
|
||||
project_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), f"{project_name}.c")
|
||||
)
|
||||
wasm_path = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), f"{project_name}.wasm")
|
||||
)
|
||||
build_cmd = (
|
||||
f"$CC --sysroot=$SYSROOT "
|
||||
f"-O3 -ffast-math --target=wasm32 -fno-exceptions -fno-threadsafe-statics -fvisibility=default -Wl,--export-all -Wl,--no-entry -Wl,--allow-undefined -DNDEBUG --no-standard-libraries -fno-builtin-memset "
|
||||
f"-o {wasm_path} {project_path}"
|
||||
f"&& wasm-opt {wasm_path} {OPT} -o {wasm_path}"
|
||||
)
|
||||
try:
|
||||
subprocess.run(build_cmd, shell=True, check=True)
|
||||
print(
|
||||
f"WASM file for {project_name} has been built with WASI support using clang."
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"exec error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
with open(wasm_path, "rb") as f:
|
||||
data = f.read()
|
||||
wasm = data.hex()
|
||||
update_fixture(project_name, wasm)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 2:
|
||||
print("Usage: python copyFixtures.py [<project_name>]")
|
||||
sys.exit(1)
|
||||
if len(sys.argv) == 2:
|
||||
if os.path.isdir(os.path.join(os.path.dirname(__file__), sys.argv[1])):
|
||||
process_rust(sys.argv[1])
|
||||
else:
|
||||
process_c(sys.argv[1])
|
||||
print("Fixture has been processed.")
|
||||
else:
|
||||
dirs = [
|
||||
d
|
||||
for d in os.listdir(os.path.dirname(__file__))
|
||||
if os.path.isdir(os.path.join(os.path.dirname(__file__), d))
|
||||
]
|
||||
c_files = [f for f in os.listdir(os.path.dirname(__file__)) if f.endswith(".c")]
|
||||
for d in dirs:
|
||||
process_rust(d)
|
||||
for c in c_files:
|
||||
process_c(c[:-2])
|
||||
print("All fixtures have been processed.")
|
||||
@@ -1,34 +0,0 @@
|
||||
(module
|
||||
(type (;0;) (func))
|
||||
(type (;1;) (func (result i32)))
|
||||
(func (;0;) (type 0))
|
||||
(func (;1;) (type 1) (result i32)
|
||||
f32.const -2048
|
||||
f32.const 2050
|
||||
f32.sub
|
||||
drop
|
||||
i32.const 1)
|
||||
(memory (;0;) 2)
|
||||
(global (;0;) i32 (i32.const 1024))
|
||||
(global (;1;) i32 (i32.const 1024))
|
||||
(global (;2;) i32 (i32.const 2048))
|
||||
(global (;3;) i32 (i32.const 2048))
|
||||
(global (;4;) i32 (i32.const 67584))
|
||||
(global (;5;) i32 (i32.const 1024))
|
||||
(global (;6;) i32 (i32.const 67584))
|
||||
(global (;7;) i32 (i32.const 131072))
|
||||
(global (;8;) i32 (i32.const 0))
|
||||
(global (;9;) i32 (i32.const 1))
|
||||
(export "memory" (memory 0))
|
||||
(export "__wasm_call_ctors" (func 0))
|
||||
(export "finish" (func 1))
|
||||
(export "buf" (global 0))
|
||||
(export "__dso_handle" (global 1))
|
||||
(export "__data_end" (global 2))
|
||||
(export "__stack_low" (global 3))
|
||||
(export "__stack_high" (global 4))
|
||||
(export "__global_base" (global 5))
|
||||
(export "__heap_base" (global 6))
|
||||
(export "__heap_end" (global 7))
|
||||
(export "__memory_base" (global 8))
|
||||
(export "__table_base" (global 9)))
|
||||
@@ -1,12 +0,0 @@
|
||||
// typedef long long mint;
|
||||
typedef int mint;
|
||||
|
||||
mint
|
||||
fib(mint n)
|
||||
{
|
||||
if (!n)
|
||||
return 0;
|
||||
if (n <= 2)
|
||||
return 1;
|
||||
return fib(n - 1) + fib(n - 2);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user