Compare commits

..

2 Commits

Author SHA1 Message Date
Ed Hennis
3f9c9fff88 Suppress "parse failed" message in Batch tests 2026-01-12 20:03:22 -05:00
Bart
4755bb8606 refactor: Remove unnecessary version number and options in cmake find_package (#6169)
This change removes unnecessary version numbers in the OpenSSL and Boost `find_package` CMake statements. An unnecessary OpenSSL definition is removed, while Conan options for SSL are updated to disable insecure ciphers. Moreover, the statements are now ordered alphabetically and more logically.
2026-01-12 19:14:39 -05:00
124 changed files with 166 additions and 20829 deletions

View File

@@ -262,7 +262,6 @@ words:
- venv
- vfalco
- vinnie
- wasmi
- wextra
- wptr
- writeme

6
.github/CODEOWNERS vendored
View File

@@ -1,2 +1,8 @@
# Allow anyone to review any change by default.
*
# Require the rpc-reviewers team to review changes to the rpc code.
include/xrpl/protocol/ @xrplf/rpc-reviewers
src/libxrpl/protocol/ @xrplf/rpc-reviewers
src/xrpld/rpc/ @xrplf/rpc-reviewers
src/xrpld/app/misc/ @xrplf/rpc-reviewers

View File

@@ -148,7 +148,8 @@ function extract_version {
}
# Define which recipes to export.
recipes=(ed25519 grpc secp256k1 snappy soci)
recipes=('ed25519' 'grpc' 'openssl' 'secp256k1' 'snappy' 'soci')
folders=('all' 'all' '3.x.x' 'all' 'all' 'all')
# Selectively check out the recipes from our CCI fork.
cd external
@@ -157,20 +158,24 @@ cd conan-center-index
git init
git remote add origin git@github.com:XRPLF/conan-center-index.git
git sparse-checkout init
for recipe in ${recipes[@]}; do
echo "Checking out ${recipe}..."
git sparse-checkout add recipes/${recipe}/all
for ((index = 1; index <= ${#recipes[@]}; index++)); do
recipe=${recipes[index]}
folder=${folders[index]}
echo "Checking out recipe '${recipe}' from folder '${folder}'..."
git sparse-checkout add recipes/${recipe}/${folder}
done
git fetch origin master
git checkout master
cd ../..
# Export the recipes into the local cache.
for recipe in ${recipes[@]}; do
for ((index = 1; index <= ${#recipes[@]}; index++)); do
recipe=${recipes[index]}
folder=${folders[index]}
version=$(extract_version ${recipe})
echo "Exporting ${recipe}/${version}..."
echo "Exporting '${recipe}/${version}' from '${recipe}/${folder}'..."
conan export --version $(extract_version ${recipe}) \
external/conan-center-index/recipes/${recipe}/all
external/conan-center-index/recipes/${recipe}/${folder}
done
```

View File

@@ -88,35 +88,18 @@ endif()
###
include(deps/Boost)
find_package(OpenSSL 1.1.1 REQUIRED)
set_target_properties(OpenSSL::SSL PROPERTIES
INTERFACE_COMPILE_DEFINITIONS OPENSSL_NO_SSL2
)
add_subdirectory(external/antithesis-sdk)
find_package(gRPC REQUIRED)
find_package(lz4 REQUIRED)
# Target names with :: are not allowed in a generator expression.
# We need to pull the include directories and imported location properties
# from separate targets.
find_package(LibArchive REQUIRED)
find_package(SOCI REQUIRED)
find_package(SQLite3 REQUIRED)
option(rocksdb "Enable RocksDB" ON)
if(rocksdb)
find_package(RocksDB REQUIRED)
set_target_properties(RocksDB::rocksdb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1
)
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
endif()
find_package(date REQUIRED)
find_package(ed25519 REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
find_package(nudb REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
find_package(wasmi REQUIRED)
find_package(SOCI REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(xxHash REQUIRED)
target_link_libraries(xrpl_libs INTERFACE
@@ -129,6 +112,15 @@ target_link_libraries(xrpl_libs INTERFACE
SQLite::SQLite3
)
option(rocksdb "Enable RocksDB" ON)
if(rocksdb)
find_package(RocksDB REQUIRED)
set_target_properties(RocksDB::rocksdb PROPERTIES
INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1
)
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
endif()
# Work around changes to Conan recipe for now.
if(TARGET nudb::core)
set(nudb nudb::core)

View File

@@ -1290,39 +1290,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

View File

@@ -1,19 +0,0 @@
#!/bin/bash
# cspell: ignore clangf
modified=$1
dir=`pwd`
clangf=clang-format-10
clangf=clang-format
if [ "$1" = "--all" ]
then
modified=`git status|egrep "modified|new file"|egrep "(cpp|h)$" | sed -E -e 's/modified://' -e 's/new file://' -e 's/^[[:space:]]+//'`
fi
for i in $modified
do
basedir=$(dirname "$i")
file=$(basename "$i")
echo "$basedir $file"
cd $basedir
$clangf -style=file -i "$file"
cd $dir
done

View File

@@ -63,7 +63,6 @@ target_link_libraries(xrpl.imports.main
Xrpl::opts
Xrpl::syslibs
secp256k1::secp256k1
wasmi::wasmi
xrpl.libpb
xxHash::xxhash
$<$<BOOL:${voidstar}>:antithesis-sdk-cpp>

View File

@@ -1,4 +1,4 @@
find_package(Boost 1.82 REQUIRED
find_package(Boost REQUIRED
COMPONENTS
chrono
container

View File

@@ -1,45 +1,44 @@
{
"version": "0.5",
"requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1756234289.683",
"wasmi/0.42.1#2a96357d4e6bf40dfe201106d849c24f%1764802092.014",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1756234266.869",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1756234262.318",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1756234314.246",
"secp256k1/0.7.0#9c4ab67bdc3860c16ea5b36aed8f74ea%1765202256.763",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1762797952.535",
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1764175362.029",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83",
"openssl/3.5.4#a1d5835cc6ed5c5b8f3cd5b9b5d24205%1760106486.594",
"nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1763150366.909",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1756234228.999",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1756223727.64",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1756230911.03",
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1764175360.142",
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1765850149.987",
"sqlite3/3.49.1#8631739a4c9b93bd3d6b753bac548a63%1765850149.926",
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1765850149.46",
"snappy/1.1.10#968fef506ff261592ec30c574d4a7809%1765850147.878",
"secp256k1/0.7.0#9c4ab67bdc3860c16ea5b36aed8f74ea%1765850147.928",
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
"openssl/3.5.4#58f5173c2ee51d6fc0f0c61b4eddadbb%1768259092.666",
"nudb/2.0.9#fb8dfd1a5557f5e0528114c2da17721e%1765850143.957",
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
"grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1763158050.628",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1764270189.893",
"doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1762797941.757",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1763584497.32",
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1764175359.429",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1764175359.429",
"boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1756223752.326",
"abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301"
"grpc/1.72.0#f244a57bff01e708c55a1100b12e1589%1765850193.734",
"ed25519/2015.03#ae761bdc52730a843f0809bdf6c1b1f6%1765850143.772",
"doctest/2.4.12#eb9fb352fb2fdfc8abb17ec270945165%1765850143.95",
"date/3.0.4#862e11e80030356b53c2c38599ceb32b%1765850143.772",
"c-ares/1.34.5#5581c2b62a608b40bb85d965ab3ec7c8%1765850144.336",
"bzip2/1.0.8#c470882369c2d95c5c77e970c0c7e321%1765850143.837",
"boost/1.88.0#8852c0b72ce8271fb8ff7c53456d4983%1765850172.862",
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
],
"build_requires": [
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1756234269.497",
"strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1756234281.733",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1764863245.83",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1756234232.901",
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
"strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196",
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
"msys2/cci.latest#1996656c3c98e5765b25b60ff5cf77b4%1764840888.758",
"m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846",
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1764175359.44",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1764175359.429",
"b2/5.3.3#107c15377719889654eb9a162a673975%1756234226.28",
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355",
"automake/1.16.5#b91b7c384c3deaa9d535be02da14d04f%1755524470.56",
"autoconf/2.71#51077f068e61700d65bb05541ea1e4b0%1731054366.86",
"abseil/20250127.0#9e8e8cfc89a1324139fc0ee3bd4d8c8c%1753819045.301"
"abseil/20250127.0#99262a368bd01c0ccca8790dfced9719%1766517936.993"
],
"python_requires": [],
"overrides": {

View File

@@ -35,7 +35,6 @@ class Xrpl(ConanFile):
"openssl/3.5.4",
"secp256k1/0.7.0",
"soci/4.0.3",
"wasmi/0.42.1",
"zlib/1.3.1",
]
@@ -88,7 +87,13 @@ class Xrpl(ConanFile):
"libarchive/*:with_xattr": False,
"libarchive/*:with_zlib": False,
"lz4/*:shared": False,
"openssl/*:no_dtls": True,
"openssl/*:no_ssl": True,
"openssl/*:no_ssl3": True,
"openssl/*:no_tls1": True,
"openssl/*:no_tls1_1": True,
"openssl/*:shared": False,
"openssl/*:tls_security_level": 2,
"protobuf/*:shared": False,
"protobuf/*:with_zlib": True,
"rocksdb/*:enable_sse": False,
@@ -211,7 +216,6 @@ class Xrpl(ConanFile):
"soci::soci",
"secp256k1::secp256k1",
"sqlite3::sqlite",
"wasmi::wasmi",
"xxhash::xxhash",
"zlib::zlib",
]

View File

@@ -339,10 +339,6 @@ abs(Number x) noexcept
Number
power(Number const& f, unsigned n);
// logarithm with base 10
Number
lg(Number const& value);
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the root of the polynomial g(x) = x^d - f

View File

@@ -55,18 +55,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
@@ -85,8 +73,6 @@ public:
private:
std::optional<STAmount> deliver_;
std::optional<std::uint32_t> gasUsed_;
std::optional<std::int32_t> wasmReturnCode_;
};
} // namespace xrpl

View File

@@ -53,8 +53,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);

View File

@@ -5,8 +5,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
@@ -17,10 +15,6 @@ 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)
explicit Fees() = default;
Fees(Fees const&) = default;

View File

@@ -39,13 +39,6 @@ private:
normalize();
public:
/* The range for the mantissa when normalized */
static std::int64_t constexpr minMantissa = 1000000000000000ull;
static std::int64_t constexpr maxMantissa = 9999999999999999ull;
/* The range for the exponent when normalized */
static int constexpr minExponent = -96;
static int constexpr maxExponent = 80;
IOUAmount() = default;
explicit IOUAmount(Number const& other);
IOUAmount(beast::Zero);

View File

@@ -212,12 +212,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;

View File

@@ -251,13 +251,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;

View File

@@ -122,8 +122,6 @@ enum TEMcodes : TERUnderlyingType {
temARRAY_TOO_LARGE,
temBAD_TRANSFER_FEE,
temINVALID_INNER_BATCH,
temBAD_WASM,
};
//------------------------------------------------------------------------------
@@ -168,8 +166,6 @@ enum TEFcodes : TERUnderlyingType {
tefNO_TICKET,
tefNFTOKEN_IS_NOT_TRANSFERABLE,
tefINVALID_LEDGER_FIX_TYPE,
tefNO_WASM,
tefWASM_FIELD_NOT_INCLUDED,
};
//------------------------------------------------------------------------------
@@ -351,7 +347,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,
};
//------------------------------------------------------------------------------

View File

@@ -85,12 +85,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&
@@ -111,30 +105,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_;
@@ -143,8 +113,6 @@ private:
std::optional<STAmount> deliveredAmount_;
std::optional<uint256> parentBatchID_;
std::optional<std::uint32_t> gasUsed_;
std::optional<std::int32_t> wasmReturnCode_;
STArray nodes_;
};

View File

@@ -16,7 +16,6 @@
// 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 (BatchInnerSigs, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(LendingProtocol, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionDelegationV1_1, Supported::no, VoteBehavior::DefaultNo)
@@ -34,6 +33,7 @@ XRPL_FEATURE(PermissionedDEX, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(Batch, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(SingleAssetVault, Supported::no, 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)

View File

@@ -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

View File

@@ -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)
TYPED_SFIELD(sfPeriodicPayment, NUMBER, 16)
TYPED_SFIELD(sfManagementFeeOutstanding, NUMBER, 17)
// 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)

View File

@@ -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

View File

@@ -255,9 +255,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
@@ -712,11 +709,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>

View File

@@ -631,48 +631,6 @@ power(Number const& f, unsigned n)
return r;
}
// Continued fraction approximation of ln(x)
static Number
ln(Number const& x, unsigned iterations = 50)
{
if (x <= 0)
throw std::runtime_error("Not positive value");
Number const z = (x - 1) / (x + 1);
Number const zz = z * z;
Number denom = Number(1, -10);
// Construct the fraction from the bottom up
for (int i = iterations; i > 0; --i)
{
Number k(2 * i - 1);
denom = k - (i * i * zz / denom);
}
auto const r = 2 * z / denom;
return r;
}
Number
lg(Number const& x)
{
static Number const ln10 = ln(Number(10));
if (x <= Number(10))
{
auto const r = ln(x) / ln10;
return r;
}
// ln(x) = ln(normX * 10^norm) = ln(normX) + norm * ln(10)
int diffExp = 15 + x.exponent();
Number const normalX = x / Number(1, diffExp); // (1 <= normalX < 10)
auto const lnX = ln(normalX) + diffExp * ln10;
auto const r = lnX / ln10;
return r;
}
// Returns f^(1/d)
// Uses NewtonRaphson iterations until the result stops changing
// to find the non-negative root of the polynomial g(x) = x^d - f

View File

@@ -97,8 +97,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)
{
@@ -113,8 +111,6 @@ ApplyStateTable::apply(
meta.setDeliveredAmount(deliver);
meta.setParentBatchID(parentBatchId);
meta.setGasUsed(gasUsed);
meta.setWasmReturnCode(wasmReturnCode);
Mods newMod;
for (auto& item : items_)

View File

@@ -16,16 +16,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

View File

@@ -39,6 +39,13 @@ setSTNumberSwitchover(bool v)
*getStaticSTNumberSwitchover() = v;
}
/* The range for the mantissa when normalized */
static std::int64_t constexpr minMantissa = 1000000000000000ull;
static std::int64_t constexpr maxMantissa = 9999999999999999ull;
/* The range for the exponent when normalized */
static int constexpr minExponent = -96;
static int constexpr maxExponent = 80;
IOUAmount
IOUAmount::minPositiveAmount()
{
@@ -286,8 +293,7 @@ mulRatio(
{
if (!result)
{
return IOUAmount(
-IOUAmount::minMantissa, IOUAmount::minExponent);
return IOUAmount(-minMantissa, minExponent);
}
// This subtraction cannot underflow because `result` is not zero
return IOUAmount(result.mantissa() - 1, result.exponent());

View File

@@ -58,10 +58,6 @@ STValidation::validationFormat()
{sfBaseFeeDrops, soeOPTIONAL},
{sfReserveBaseDrops, soeOPTIONAL},
{sfReserveIncrementDrops, soeOPTIONAL},
// featureSmartEscrow
{sfExtensionComputeLimit, soeOPTIONAL},
{sfExtensionSizeLimit, soeOPTIONAL},
{sfGasPrice, soeOPTIONAL},
};
// clang-format on

View File

@@ -108,7 +108,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."),
@@ -132,8 +131,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."),
@@ -203,7 +200,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(terRETRY, "Retry transaction."),
MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."),

View File

@@ -210,12 +210,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;
}

View File

@@ -7466,7 +7466,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);

View File

@@ -427,6 +427,7 @@ class Batch_test : public beast::unit_test::suite
auto const batchFee = batch::calcBatchFee(env, 0, 2);
auto tx1 = batch::inner(pay(alice, bob, XRP(1)), seq + 1);
tx1[jss::Fee] = "1.5";
env.set_parse_failure_expected(true);
try
{
env(batch::outer(alice, seq, batchFee, tfAllOrNothing),
@@ -438,6 +439,7 @@ class Batch_test : public beast::unit_test::suite
{
BEAST_EXPECT(true);
}
env.set_parse_failure_expected(false);
}
// temSEQ_AND_TICKET: Batch: inner txn cannot have both Sequence

File diff suppressed because it is too large Load Diff

View File

@@ -1507,7 +1507,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";
@@ -1674,8 +1674,6 @@ public:
FeatureBitset const all{testable_amendments()};
testWithFeats(all);
testWithFeats(all - featureTokenEscrow);
testWithFeats(all - featureSmartEscrow);
testWithFeats(all - featureTokenEscrow - featureSmartEscrow);
testTags(all - fixIncludeKeyletFields);
}
};

View File

@@ -24,17 +24,13 @@ 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)
FeeSettingsFields const& fields)
{
auto fill = [&](auto& obj) {
obj.setAccountID(sfAccount, AccountID());
@@ -68,17 +64,6 @@ createFeeTx(
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);
}
@@ -127,12 +112,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)
@@ -140,12 +119,12 @@ 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
@@ -201,25 +180,6 @@ verifyFeeObject(
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;
}
@@ -242,7 +202,6 @@ class FeeVote_test : public beast::unit_test::suite
void
testSetup()
{
testcase("FeeVote setup");
FeeSetup const defaultSetup;
{
// defaults
@@ -251,62 +210,36 @@ 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"});
"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"});
"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"});
"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);
@@ -314,12 +247,6 @@ class FeeVote_test : public beast::unit_test::suite
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(
@@ -330,22 +257,12 @@ class FeeVote_test : public beast::unit_test::suite
config.append(
{"reference_fee = " + big64,
"account_reserve = " + big64,
"owner_reserve = " + big64,
"extension_compute_limit = " + big64,
"extension_size_limit = " + big64,
"gas_price = " + 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);
}
}
@@ -356,10 +273,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(),
@@ -380,8 +294,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
@@ -390,8 +303,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(),
@@ -410,76 +322,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
@@ -488,10 +336,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(),
@@ -506,19 +351,16 @@ class FeeVote_test : public beast::unit_test::suite
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(),
@@ -533,43 +375,12 @@ class FeeVote_test : public beast::unit_test::suite
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));
}
}
@@ -578,7 +389,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(),
@@ -608,8 +419,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));
}
}
@@ -618,7 +428,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(),
@@ -636,8 +446,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);
}
@@ -655,8 +464,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);
}
@@ -669,7 +477,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(),
@@ -692,7 +500,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
@@ -700,7 +508,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(),
@@ -718,8 +526,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);
}
@@ -736,8 +543,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);
}
@@ -750,7 +556,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(),
@@ -773,8 +579,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
@@ -791,7 +596,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>(
@@ -826,9 +631,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>(
@@ -871,7 +674,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(
@@ -961,128 +764,6 @@ class FeeVote_test : public beast::unit_test::suite
XRPAmount{setup.owner_reserve});
}
void
testDoVotingSmartEscrow()
{
testcase("doVoting with Smart Escrow");
using namespace jtx;
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;
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 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);
auto const& feeTx = txs[0];
BEAST_EXPECT(feeTx.getTxnType() == ttFEE);
BEAST_EXPECT(feeTx.getAccountID(sfAccount) == AccountID());
BEAST_EXPECT(feeTx.getFieldU32(sfLedgerSequence) == ledger->seq() + 1);
BEAST_EXPECT(feeTx.isFieldPresent(sfBaseFeeDrops));
BEAST_EXPECT(feeTx.isFieldPresent(sfReserveBaseDrops));
BEAST_EXPECT(feeTx.isFieldPresent(sfReserveIncrementDrops));
// The legacy fields should NOT be present
BEAST_EXPECT(!feeTx.isFieldPresent(sfBaseFee));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveBase));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReserveIncrement));
BEAST_EXPECT(!feeTx.isFieldPresent(sfReferenceFeeUnits));
// Check the values
BEAST_EXPECT(
feeTx.getFieldAmount(sfBaseFeeDrops) ==
XRPAmount{setup.reference_fee});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveBaseDrops) ==
XRPAmount{setup.account_reserve});
BEAST_EXPECT(
feeTx.getFieldAmount(sfReserveIncrementDrops) ==
XRPAmount{setup.owner_reserve});
BEAST_EXPECT(
feeTx.getFieldU32(sfExtensionComputeLimit) ==
setup.extension_compute_limit);
BEAST_EXPECT(
feeTx.getFieldU32(sfExtensionSizeLimit) ==
setup.extension_size_limit);
BEAST_EXPECT(feeTx.getFieldU32(sfGasPrice) == setup.gas_price);
}
void
run() override
{
@@ -1096,7 +777,6 @@ class FeeVote_test : public beast::unit_test::suite
testSingleInvalidTransaction();
testDoValidation();
testDoVoting();
testDoVotingSmartEscrow();
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -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) {
@@ -107,9 +101,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();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,998 +0,0 @@
#ifdef _DEBUG
// #define DEBUG_OUTPUT 1
#endif
#include <test/app/TestHostFunctions.h>
#include <xrpld/app/wasm/HostFuncWrapper.h>
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::optional<int32_t>
runFinishFunction(std::string const& code)
{
auto& engine = WasmEngine::instance();
auto const ws = boost::algorithm::unhex(code);
Bytes const wasm(ws.begin(), ws.end());
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
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();
ImportVec imports;
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());
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 6'912, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 3, std::to_string(re->cost));
}
}
void
testBadWasm()
{
testcase("bad wasm test");
using namespace test::jtx;
Env env{*this};
HostFunctions hfs(env.journal);
{
auto wasmHex = "00000000";
auto wasmStr = boost::algorithm::unhex(std::string(wasmHex));
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
std::string funcName("mock_escrow");
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 15);
BEAST_EXPECT(!re);
}
{
auto wasmHex = "00112233445566778899AA";
auto wasmStr = boost::algorithm::unhex(std::string(wasmHex));
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
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 badWasmHex =
"0061736d010000000105016000017f02190108686f73745f6c69620c6765"
"744c656467657253716e00000302010005030100100611027f00418080c0"
"000b7f00418080c0000b072b04066d656d6f727902000362616400010a5f"
"5f646174615f656e6403000b5f5f686561705f6261736503010a09010700"
"100041044a0b004d0970726f64756365727302086c616e67756167650104"
"52757374000c70726f6365737365642d6279010572757374631d312e3835"
"2e31202834656231363132353020323032352d30332d31352900490f7461"
"726765745f6665617475726573042b0f6d757461626c652d676c6f62616c"
"732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a"
"6d756c746976616c7565";
auto wasmStr = boost::algorithm::unhex(std::string(badWasmHex));
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
auto const re =
preflightEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME);
BEAST_EXPECT(!isTesSuccess(re));
}
}
void
testWasmLedgerSqn()
{
testcase("Wasm get ledger sequence");
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
using namespace test::jtx;
Env env{*this};
TestLedgerDataProvider hf(env);
ImportVec imports;
WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", &hf, 33);
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
&hf,
1'000'000,
env.journal);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 0, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 38, std::to_string(re->cost));
}
env.close();
env.close();
// empty module - run the same instance
re = engine.run(
{}, ESCROW_FUNCTION_NAME, {}, imports, &hf, 1'000'000, env.journal);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 5, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 76, std::to_string(re->cost));
}
}
void
testWasmFib()
{
testcase("Wasm fibo");
auto const ws = boost::algorithm::unhex(fibWasmHex);
Bytes const wasm(ws.begin(), ws.end());
auto& engine = WasmEngine::instance();
auto const re = engine.run(wasm, "fib", wasmParams(10));
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 55, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 696, std::to_string(re->cost));
}
}
void
testWasmSha()
{
testcase("Wasm sha");
auto const ws = boost::algorithm::unhex(sha512PureWasmHex);
Bytes const wasm(ws.begin(), ws.end());
auto& engine = WasmEngine::instance();
auto const re =
engine.run(wasm, "sha512_process", wasmParams(sha512PureWasmHex));
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 34'432, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 145'573, std::to_string(re->cost));
}
}
void
testWasmB58()
{
testcase("Wasm base58");
auto const ws = boost::algorithm::unhex(b58WasmHex);
Bytes const wasm(ws.begin(), ws.end());
auto& engine = WasmEngine::instance();
Bytes outb;
outb.resize(1024);
auto const minsz = std::min(
static_cast<std::uint32_t>(512),
static_cast<std::uint32_t>(b58WasmHex.size()));
auto const s = std::string_view(b58WasmHex.c_str(), minsz);
auto const re = engine.run(wasm, "b58enco", wasmParams(outb, s));
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 700, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 2'701'528, std::to_string(re->cost));
}
}
void
testHFCost()
{
testcase("wasm test host functions cost");
using namespace test::jtx;
Env env(*this);
{
std::string const wasmHex = allHostFunctionsWasmHex;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec imp = createWasmImport(hfs);
for (auto& i : imp)
i.second.gas = 0;
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
1'000'000,
env.journal);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 842, std::to_string(re->cost));
}
env.close();
}
env.close();
env.close();
env.close();
env.close();
env.close();
{
std::string const wasmHex = allHostFunctionsWasmHex;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec const imp = createWasmImport(hfs);
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imp,
&hfs,
1'000'000,
env.journal);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 39'602, std::to_string(re->cost));
}
env.close();
}
// not enough gas
{
std::string const wasmHex = allHostFunctionsWasmHex;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
auto& engine = WasmEngine::instance();
TestHostFunctions hfs(env, 0);
ImportVec const imp = createWasmImport(hfs);
auto re = engine.run(
wasm, 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");
std::string const wasmStr =
boost::algorithm::unhex(allHostFunctionsWasmHex);
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
using namespace test::jtx;
Env env{*this};
{
TestHostFunctions nfs(env, 0);
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 39'602, std::to_string(re->cost));
}
}
{
// max<int64_t>() gas
TestHostFunctions nfs(env, 0);
auto re = runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, -1);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 39'602, std::to_string(re->cost));
}
}
{ // 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);
}
};
BadTestHostFunctions nfs(env);
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == -201, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 5'012, std::to_string(re->cost));
}
}
{ // 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);
}
};
BadTestHostFunctions nfs(env);
auto re =
runEscrowWasm(wasm, nfs, ESCROW_FUNCTION_NAME, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == -201, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 5'012, std::to_string(re->cost));
}
}
{ // fail because recursion too deep
auto const wasmStr = boost::algorithm::unhex(deepRecursionHex);
std::vector<uint8_t> wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctionsSink nfs(env);
std::string funcName("finish");
auto re = runEscrowWasm(wasm, nfs, funcName, {}, 1'000'000'000);
BEAST_EXPECT(!re && re.error());
// std::cout << "bad case (deep recursion) result " << re.error()
// << std::endl;
auto const& sink = nfs.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 wasmStr = boost::algorithm::unhex(infiniteLoopWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
std::string const funcName("loop");
TestHostFunctions hfs(env, 0);
// infinite loop should be caught and fail
auto const re = runEscrowWasm(wasm, hfs, funcName, {}, 1'000'000);
if (BEAST_EXPECT(!re.has_value()))
{
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
}
{
// expected import not provided
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn2", &ledgerDataProvider);
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
1'000'000,
env.journal);
BEAST_EXPECT(!re);
}
{
// bad import format
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn", &ledgerDataProvider);
imports[0].first = nullptr;
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
1'000'000,
env.journal);
BEAST_EXPECT(!re);
}
{
// bad function name
auto wasmStr = boost::algorithm::unhex(ledgerSqnWasmHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
WASM_IMPORT_FUNC2(
imports, getLedgerSqn, "get_ledger_sqn", &ledgerDataProvider);
auto& engine = WasmEngine::instance();
auto re = engine.run(
wasm,
"func1",
{},
imports,
&ledgerDataProvider,
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);
{
std::string const wasmHex = floatTestsWasmHex;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hf(env, 0);
auto re = runEscrowWasm(wasm, hf, funcName, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 97'356, std::to_string(re->cost));
}
env.close();
}
{
std::string const wasmHex = float0Hex;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hf(env, 0);
auto re = runEscrowWasm(wasm, hf, funcName, {}, 100'000);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECTS(re->result == 1, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 2'054, std::to_string(re->cost));
}
env.close();
}
}
void
perfTest()
{
testcase("Perf test host functions");
using namespace jtx;
using namespace std::chrono;
// std::string const funcName("test");
auto const& wasmHex = hfPerfTest;
std::string const wasmStr = boost::algorithm::unhex(wasmHex);
std::vector<uint8_t> const wasm(wasmStr.begin(), wasmStr.end());
// 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();
PerfHostFunctions nfs(env, k, env.tx());
auto re = runEscrowWasm(wasm, nfs, 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 wasmStr = boost::algorithm::unhex(codecovTestsWasmHex);
Bytes const wasm(wasmStr.begin(), wasmStr.end());
TestHostFunctions hfs(env, 0);
auto const allowance = 292'345;
auto re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance);
if (BEAST_EXPECT(re.has_value()))
{
BEAST_EXPECT(re->result);
BEAST_EXPECTS(re->cost == allowance, std::to_string(re->cost));
}
}
void
testDisabledFloat()
{
testcase("disabled float");
using namespace test::jtx;
Env env{*this};
auto const wasmStr = boost::algorithm::unhex(disabledFloatHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
std::string const funcName("finish");
TestHostFunctions hfs(env, 0);
{
// f32 set constant, opcode disabled exception
auto const re = runEscrowWasm(wasm, hfs, funcName, {}, 1'000'000);
if (BEAST_EXPECT(!re.has_value()))
{
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
}
{
// f32 add, can't create module exception
wasm[0x117] = 0x92;
auto const re = runEscrowWasm(wasm, 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);
}
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 wasmStr = boost::algorithm::unhex(startLoopHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
TestLedgerDataProvider ledgerDataProvider(env);
ImportVec imports;
auto& engine = WasmEngine::instance();
auto checkRes = engine.check(
wasm, "finish", {}, imports, &ledgerDataProvider, env.journal);
BEAST_EXPECTS(
checkRes == tesSUCCESS, std::to_string(TERtoInt(checkRes)));
auto re = engine.run(
wasm,
ESCROW_FUNCTION_NAME,
{},
imports,
&ledgerDataProvider,
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 wasmStr = boost::algorithm::unhex(badAllocHex);
Bytes wasm(wasmStr.begin(), wasmStr.end());
using namespace test::jtx;
Env env{*this};
TestLedgerDataProvider hf(env);
// ImportVec imports;
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(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
if (BEAST_EXPECT(re))
{
BEAST_EXPECTS(re->result == 7, std::to_string(re->result));
BEAST_EXPECTS(re->cost == 10, std::to_string(re->result));
}
}
{ // 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(
wasm, "test", params, {}, &hf, 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(
wasm, "test", params, {}, &hf, 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(
wasm, "test", params, {}, &hf, 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(
wasm, "test", params, {}, &hf, 1'000'000, env.journal);
BEAST_EXPECT(!re) &&
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
}
env.close();
}
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();
// perfTest();
}
};
BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl);
} // namespace test
} // namespace xrpl

View File

@@ -1,3 +0,0 @@
**/target
**/debug
*.wasm

View File

@@ -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#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -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

View File

@@ -1,772 +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 sqn_result = unsafe { host::get_ledger_sqn() };
if sqn_result <= 0 {
let _ = trace_num("ERROR: get_ledger_sqn failed:", sqn_result as i64);
return -101; // Ledger sequence number test failed
}
let _ = trace_num("Ledger sequence number:", sqn_result as i64);
// Test 1.2: get_parent_ledger_time() - should return parent ledger timestamp
let time_result = unsafe { host::get_parent_ledger_time() };
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 _ = trace_num("Parent ledger time:", time_result 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:", &current_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:",
&current_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 escrow_keylet_result = unsafe {
host::escrow_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
1000, // Sequence number
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 oracle_keylet_result = unsafe {
host::oracle_keylet(
account_id.0.as_ptr(),
account_id.0.len(),
42, // Document ID
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
}

View File

@@ -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.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#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -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" }
[profile.dev]
panic = "abort"

View File

@@ -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, &currency);
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.
}

View File

@@ -1,73 +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;
}

View File

@@ -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];
}

View File

@@ -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#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -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" }

View File

@@ -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

View File

@@ -1,134 +0,0 @@
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:
result = subprocess.run(
build_cmd, shell=True, check=True, capture_output=True, text=True
)
print(f"stdout: {result.stdout}")
if result.stderr:
print(f"stderr: {result.stderr}")
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:
result = subprocess.run(
build_cmd, shell=True, check=True, capture_output=True, text=True
)
print(f"stdout: {result.stdout}")
if result.stderr:
print(f"stderr: {result.stderr}")
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.")

View File

@@ -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)))

View File

@@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,84 +0,0 @@
#pragma once
// TODO: consider moving these to separate files (and figure out the build)
#include <string>
extern std::string const ledgerSqnWasmHex;
extern std::string const allHostFunctionsWasmHex;
extern std::string const deepRecursionHex;
extern std::string const fibWasmHex;
extern std::string const b58WasmHex;
extern std::string const sha512PureWasmHex;
extern std::string const hfPerfTest;
extern std::string const allKeyletsWasmHex;
extern std::string const codecovTestsWasmHex;
extern std::string const floatTestsWasmHex;
extern std::string const float0Hex;
extern std::string const disabledFloatHex;
extern std::string const memoryPointerAtLimitHex;
extern std::string const memoryPointerOverLimitHex;
extern std::string const memoryOffsetOverLimitHex;
extern std::string const memoryEndOfWordOverLimitHex;
extern std::string const memoryGrow0To1PageHex;
extern std::string const memoryGrow1To0PageHex;
extern std::string const memoryLastByteOf8MBHex;
extern std::string const memoryGrow1MoreThan8MBHex;
extern std::string const memoryGrow0MoreThan8MBHex;
extern std::string const memoryInit1MoreThan8MBHex;
extern std::string const memoryNegativeAddressHex;
extern std::string const table64ElementsHex;
extern std::string const table65ElementsHex;
extern std::string const table2TablesHex;
extern std::string const table0ElementsHex;
extern std::string const tableUintMaxHex;
extern std::string const proposalMutableGlobalHex;
extern std::string const proposalGcStructNewHex;
extern std::string const proposalMultiValueHex;
extern std::string const proposalSignExtHex;
extern std::string const proposalFloatToIntHex;
extern std::string const proposalBulkMemoryHex;
extern std::string const proposalRefTypesHex;
extern std::string const proposalTailCallHex;
extern std::string const proposalExtendedConstHex;
extern std::string const trapDivideBy0Hex;
extern std::string const trapIntOverflowHex;
extern std::string const trapUnreachableHex;
extern std::string const trapNullCallHex;
extern std::string const trapFuncSigMismatchHex;
extern std::string const wasiGetTimeHex;
extern std::string const wasiPrintHex;
extern std::string const badMagicNumberHex;
extern std::string const badVersionNumberHex;
extern std::string const lyingHeaderHex;
extern std::string const neverEndingNumberHex;
extern std::string const vectorLieHex;
extern std::string const sectionOrderingHex;
extern std::string const ghostPayloadHex;
extern std::string const junkAfterSectionHex;
extern std::string const invalidSectionIdHex;
extern std::string const localVariableBombHex;
extern std::string const infiniteLoopWasmHex;
extern std::string const startLoopHex;
extern std::string const badAllocHex;
extern std::string const updateDataWasmHex;

View File

@@ -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 = "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 = "float_tests"
version = "0.0.1"
dependencies = [
"xrpl-wasm-stdlib",
]
[[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#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git#d27d3e0b4abf3c0215aade729d89053805efe48e"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,21 +0,0 @@
[package]
name = "float_tests"
version = "0.0.1"
edition = "2024"
# 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" }
[profile.dev]
panic = "abort"

View File

@@ -1,461 +0,0 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
#![cfg_attr(target_arch = "wasm32", no_std)]
#[cfg(not(target_arch = "wasm32"))]
extern crate std;
use xrpl_std::core::locator::Locator;
use xrpl_std::core::types::opaque_float::{FLOAT_NEGATIVE_ONE, FLOAT_ONE};
use xrpl_std::decode_hex_32;
use xrpl_std::host::trace::DataRepr::AsHex;
use xrpl_std::host::trace::{trace, trace_data, trace_float, trace_num, DataRepr};
use xrpl_std::host::{
cache_ledger_obj, float_add, float_compare, float_divide, float_from_int, float_from_uint,
float_log, float_multiply, float_pow, float_root, float_set, float_subtract,
get_ledger_obj_array_len, get_ledger_obj_field, get_ledger_obj_nested_field,
trace_opaque_float, FLOAT_ROUNDING_MODES_TO_NEAREST,
};
use xrpl_std::sfield;
use xrpl_std::sfield::{
Account, AccountTxnID, Balance, Domain, EmailHash, Flags, LedgerEntryType, MessageKey,
OwnerCount, PreviousTxnID, PreviousTxnLgrSeq, RegularKey, Sequence, TicketCount, TransferRate,
};
fn test_float_from_wasm() {
let _ = trace("\n$$$ test_float_from_wasm $$$");
let mut f: [u8; 8] = [0u8; 8];
if 8 == unsafe { float_from_int(12300, f.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace_float(" float from i64 12300:", &f);
let _ = trace_data(" float from i64 12300 as HEX:", &f, AsHex);
} else {
let _ = trace(" float from i64 12300: failed");
}
let u64_value: u64 = 12300;
if 8 == unsafe {
float_from_uint(
&u64_value as *const u64 as *const u8,
8,
f.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
} {
let _ = trace_float(" float from u64 12300:", &f);
} else {
let _ = trace(" float from u64 12300: failed");
}
if 8 == unsafe { float_set(2, 123, f.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace_float(" float from exp 2, mantissa 123:", &f);
} else {
let _ = trace(" float from exp 2, mantissa 3: failed");
}
let _ = trace_float(" float from const 1:", &FLOAT_ONE);
let _ = trace_float(" float from const -1:", &FLOAT_NEGATIVE_ONE);
}
fn test_float_compare() {
let _ = trace("\n$$$ test_float_compare $$$");
let mut f1: [u8; 8] = [0u8; 8];
if 8 != unsafe { float_from_int(1, f1.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace(" float from 1: failed");
} else {
let _ = trace_float(" float from 1:", &f1);
}
if 0 == unsafe { float_compare(f1.as_ptr(), 8, FLOAT_ONE.as_ptr(), 8) } {
let _ = trace(" float from 1 == FLOAT_ONE");
} else {
let _ = trace(" float from 1 != FLOAT_ONE");
}
if 1 == unsafe { float_compare(f1.as_ptr(), 8, FLOAT_NEGATIVE_ONE.as_ptr(), 8) } {
let _ = trace(" float from 1 > FLOAT_NEGATIVE_ONE");
} else {
let _ = trace(" float from 1 !> FLOAT_NEGATIVE_ONE");
}
if 2 == unsafe { float_compare(FLOAT_NEGATIVE_ONE.as_ptr(), 8, f1.as_ptr(), 8) } {
let _ = trace(" FLOAT_NEGATIVE_ONE < float from 1");
} else {
let _ = trace(" FLOAT_NEGATIVE_ONE !< float from 1");
}
}
fn test_float_add_subtract() {
let _ = trace("\n$$$ test_float_add_subtract $$$");
let mut f_compute: [u8; 8] = FLOAT_ONE;
for i in 0..9 {
unsafe {
float_add(
f_compute.as_ptr(),
8,
FLOAT_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f10: [u8; 8] = [0u8; 8];
if 8 != unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
// let _ = trace(" float from 10: failed");
}
if 0 == unsafe { float_compare(f10.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" repeated add: good");
} else {
let _ = trace(" repeated add: bad");
}
for i in 0..11 {
unsafe {
float_subtract(
f_compute.as_ptr(),
8,
FLOAT_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
if 0 == unsafe { float_compare(f_compute.as_ptr(), 8, FLOAT_NEGATIVE_ONE.as_ptr(), 8) } {
let _ = trace(" repeated subtract: good");
} else {
let _ = trace(" repeated subtract: bad");
}
}
fn test_float_multiply_divide() {
let _ = trace("\n$$$ test_float_multiply_divide $$$");
let mut f10: [u8; 8] = [0u8; 8];
unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; 8] = FLOAT_ONE;
for i in 0..6 {
unsafe {
float_multiply(
f_compute.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if 0 == unsafe { float_compare(f1000000.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" repeated multiply: good");
} else {
let _ = trace(" repeated multiply: bad");
}
for i in 0..7 {
unsafe {
float_divide(
f_compute.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
let mut f01: [u8; 8] = [0u8; 8];
unsafe { float_set(-1, 1, f01.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
if 0 == unsafe { float_compare(f_compute.as_ptr(), 8, f01.as_ptr(), 8) } {
let _ = trace(" repeated divide: good");
} else {
let _ = trace(" repeated divide: bad");
}
}
fn test_float_pow() {
let _ = trace("\n$$$ test_float_pow $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_pow(
FLOAT_ONE.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cube of 1:", &f_compute);
unsafe {
float_pow(
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
6,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th power of -1:", &f_compute);
let mut f9: [u8; 8] = [0u8; 8];
unsafe { float_from_int(9, f9.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f9.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 9:", &f_compute);
unsafe {
float_pow(
f9.as_ptr(),
8,
0,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 0th power of 9:", &f_compute);
let mut f0: [u8; 8] = [0u8; 8];
unsafe { float_from_int(0, f0.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f0.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 0:", &f_compute);
let r = unsafe {
float_pow(
f0.as_ptr(),
8,
0,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_num(
" float 0th power of 0 (expecting INVALID_PARAMS error):",
r as i64,
);
}
fn test_float_root() {
let _ = trace("\n$$$ test_float_root $$$");
let mut f9: [u8; 8] = [0u8; 8];
unsafe { float_from_int(9, f9.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_root(
f9.as_ptr(),
8,
2,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float sqrt of 9:", &f_compute);
unsafe {
float_root(
f9.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 9:", &f_compute);
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
unsafe {
float_root(
f1000000.as_ptr(),
8,
3,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 1000000:", &f_compute);
unsafe {
float_root(
f1000000.as_ptr(),
8,
6,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th root of 1000000:", &f_compute);
}
fn test_float_log() {
let _ = trace("\n$$$ test_float_log $$$");
let mut f1000000: [u8; 8] = [0u8; 8];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_log(
f1000000.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" log_10 of 1000000:", &f_compute);
}
fn test_float_negate() {
let _ = trace("\n$$$ test_float_negate $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
unsafe {
float_multiply(
FLOAT_ONE.as_ptr(),
8,
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
if 0 == unsafe { float_compare(FLOAT_NEGATIVE_ONE.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" negate const 1: good");
} else {
let _ = trace(" negate const 1: bad");
}
unsafe {
float_multiply(
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
FLOAT_NEGATIVE_ONE.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
if 0 == unsafe { float_compare(FLOAT_ONE.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" negate const -1: good");
} else {
let _ = trace(" negate const -1: bad");
}
}
fn test_float_invert() {
let _ = trace("\n$$$ test_float_invert $$$");
let mut f_compute: [u8; 8] = [0u8; 8];
let mut f10: [u8; 8] = [0u8; 8];
unsafe { float_from_int(10, f10.as_mut_ptr(), 8, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
8,
f10.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" invert a float from 10:", &f_compute);
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
8,
f_compute.as_ptr(),
8,
f_compute.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" invert again:", &f_compute);
// if f10's value is 7, then invert twice won't match the original value
if 0 == unsafe { float_compare(f10.as_ptr(), 8, f_compute.as_ptr(), 8) } {
let _ = trace(" invert twice: good");
} else {
let _ = trace(" invert twice: bad");
}
}
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
test_float_from_wasm();
test_float_compare();
test_float_add_subtract();
test_float_multiply_divide();
test_float_pow();
test_float_root();
test_float_log();
test_float_negate();
test_float_invert();
1
}

View File

@@ -1,8 +0,0 @@
int
loop()
{
int volatile x = 0;
while (1)
x++;
return x;
}

View File

@@ -1,27 +0,0 @@
#include <stdint.h>
int32_t
get_ledger_sqn();
// int32_t trace(uint8_t const*, int32_t, uint8_t const*, int32_t, int32_t);
// int32_t trace_num(uint8_t const*, int32_t, int64_t);
// uint8_t buf[1024];
// char const test_res[] = "sqn: ";
// char const test_name[] = "TEST get_ledger_sqn";
int
finish()
{
// trace((uint8_t const *)test_name, sizeof(test_name) - 1, 0, 0, 0);
// memset(buf, 0, sizeof(buf));
// for(int i = 0; i < sizeof(buf); ++i) buf[i] = 0;
int x = get_ledger_sqn();
// if (x >= 0)
// x = *((int32_t*)buf);
// trace_num((uint8_t const *)test`_res, sizeof(test_res) - 1, x);
return x < 0 ? x : (x >= 5 ? x : 0);
}

View File

@@ -1,145 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
static uint64_t const K512[] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
#define ROTATE(x, y) (((x) >> (y)) | ((x) << (64 - (y))))
#define Sigma0(x) (ROTATE((x), 28) ^ ROTATE((x), 34) ^ ROTATE((x), 39))
#define Sigma1(x) (ROTATE((x), 14) ^ ROTATE((x), 18) ^ ROTATE((x), 41))
#define sigma0(x) (ROTATE((x), 1) ^ ROTATE((x), 8) ^ ((x) >> 7))
#define sigma1(x) (ROTATE((x), 19) ^ ROTATE((x), 61) ^ ((x) >> 6))
#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
static inline uint64_t
B2U64(uint8_t val, uint8_t sh)
{
return ((uint64_t)val) << sh;
}
void*
allocate(int sz)
{
return malloc(sz);
}
void
deallocate(void* p)
{
free(p);
}
uint8_t e_data[32 * 1024];
uint8_t*
sha512_process(uint8_t const* data, int32_t length)
{
static uint64_t state[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint64_t a, b, c, d, e, f, g, h, s0, s1, T1, T2;
uint64_t X[16];
uint64_t blocks = length / 128;
while (blocks--)
{
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
unsigned i;
for (i = 0; i < 16; i++)
{
X[i] = B2U64(data[0], 56) | B2U64(data[1], 48) |
B2U64(data[2], 40) | B2U64(data[3], 32) | B2U64(data[4], 24) |
B2U64(data[5], 16) | B2U64(data[6], 8) | B2U64(data[7], 0);
data += 8;
T1 = h;
T1 += Sigma1(e);
T1 += Ch(e, f, g);
T1 += K512[i];
T1 += X[i];
T2 = Sigma0(a);
T2 += Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
for (i = 16; i < 80; i++)
{
s0 = X[(i + 1) & 0x0f];
s0 = sigma0(s0);
s1 = X[(i + 14) & 0x0f];
s1 = sigma1(s1);
T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf];
T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i];
T2 = Sigma0(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
}
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
}
return (uint8_t*)(state);
}
// int main ()
//{
// return 0;
// }

View File

@@ -1,13 +0,0 @@
#include <stdint.h>
int32_t
update_data(uint8_t const*, int32_t);
int
finish()
{
uint8_t buf[] = "Data";
update_data(buf, sizeof(buf) - 1);
return -256;
}

View File

@@ -1,29 +0,0 @@
(module
;; Define a Mutable Global Variable to act as our counter.
;; We initialize it to 1,000,000.
(global $counter (mut i32) (i32.const 1000000))
(func $finish (result i32)
;; 1. Check if counter == 0 (Base Case)
global.get $counter
i32.eqz
if
;; If counter is 0, we are done. Return 1.
i32.const 1
return
end
;; 2. Decrement the Global Counter
global.get $counter
i32.const 1
i32.sub
global.set $counter
;; 3. Recursive Step: Call SELF
;; This puts an i32 (1) on the stack when it returns.
call $finish
)
;; Export the only function we have
(export "finish" (func $finish))
)

View File

@@ -1,28 +0,0 @@
(module
;; 1. Define Memory: 1 Page = 64KB = 65,536 bytes
(memory 1)
;; Export memory so the host can inspect it if needed
(export "memory" (memory 0))
(func $test_straddle (result i32)
;; Push the address onto the stack.
;; 65534 is valid, but it is only 2 bytes away from the end.
i32.const 65534
;; Attempt to load an i32 (4 bytes) from that address.
;; This requires bytes 65534, 65535, 65536, and 65537.
;; Since 65536 is the first invalid byte, this MUST trap.
i32.load
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export the function so you can call it from your host (JS, Python, etc.)
(export "finish" (func $test_straddle))
)

View File

@@ -1,29 +0,0 @@
(module
;; Start at your limit: 128 pages (8MB)
(memory 128)
(export "memory" (memory 0))
(func $try_grow_beyond_limit (result i32)
;; Attempt to grow by 0 page
i32.const 0
memory.grow
;; memory.grow returns:
;; -1 if the growth failed (Correct behavior for your limit)
;; 128 (old size) if growth succeeded (Means limit was bypassed)
;; Check if result == -1
i32.const -1
i32.eq
if
;; Growth FAILED (Host blocked it). Return -1.
i32.const -1
return
end
;; Growth SUCCEEDED (Host allowed it). Return 1.
i32.const 1
)
(export "finish" (func $try_grow_beyond_limit))
)

View File

@@ -1,26 +0,0 @@
(module
;; 1. Define Memory: Start with 0 pages
(memory 0)
;; Export memory to host
(export "memory" (memory 0))
(func $grow_from_zero (result i32)
;; We have 0 pages. We want to add 1 page.
;; Push delta (1) onto stack.
i32.const 1
;; Grow the memory.
;; If successful: memory becomes 64KB, returns old size (0).
;; If failed: memory stays 0, returns -1.
memory.grow
;; Drop the return value of memory.grow
drop
;; Return 1 (as requested)
i32.const 1
)
(export "finish" (func $grow_from_zero))
)

View File

@@ -1,29 +0,0 @@
(module
;; Start at your limit: 128 pages (8MB)
(memory 128)
(export "memory" (memory 0))
(func $try_grow_beyond_limit (result i32)
;; Attempt to grow by 1 page
i32.const 1
memory.grow
;; memory.grow returns:
;; -1 if the growth failed (Correct behavior for your limit)
;; 128 (old size) if growth succeeded (Means limit was bypassed)
;; Check if result == -1
i32.const -1
i32.eq
if
;; Growth FAILED (Host blocked it). Return -1.
i32.const -1
return
end
;; Growth SUCCEEDED (Host allowed it). Return 1.
i32.const 1
)
(export "finish" (func $try_grow_beyond_limit))
)

View File

@@ -1,33 +0,0 @@
(module
;; 1. Define Memory: Start with 1 page (64KB)
(memory 1)
;; Export memory to host
(export "memory" (memory 0))
(func $grow_negative (result i32)
;; The user pushed -1. In Wasm, this is interpreted as unsigned MAX_UINT32.
;; This is requesting to add 4,294,967,295 pages (approx 256 TB).
;; A secure runtime MUST fail this request (return -1) without crashing.
i32.const -1
;; Grow the memory.
;; Returns: old_size if success, -1 if failure.
memory.grow
;; Check if result == -1 (Failure)
i32.const -1
i32.eq
if
;; If memory.grow returned -1, we return -1 to signal "Correctly failed".
i32.const -1
return
end
;; If we are here, memory.grow somehow SUCCEEDED (Vulnerability).
;; We return 1 to signal "Unexpected Success".
i32.const 1
)
(export "finish" (func $grow_negative))
)

View File

@@ -1,27 +0,0 @@
(module
;; Define memory: 129 pages (> 8MB limit) min, 129 pages max
(memory 129 129)
;; Export memory so host can verify size
(export "memory" (memory 0))
;; access last byte of 8MB limit
(func $access_last_byte (result i32)
;; Math: 128 pages * 64,536 bytes/page = 8,388,608 bytes
;; Valid indices: 0 to 8,388,607
;; Push the address of the LAST valid byte
i32.const 8388607
;; Load byte from that address
i32.load8_u
;; Drop the value (we don't care what it is, just that we could read it)
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,26 +0,0 @@
(module
;; Define memory: 128 pages (8MB) min, 128 pages max
(memory 128 128)
;; Export memory so host can verify size
(export "memory" (memory 0))
(func $access_last_byte (result i32)
;; Math: 128 pages * 64,536 bytes/page = 8,388,608 bytes
;; Valid indices: 0 to 8,388,607
;; Push the address of the LAST valid byte
i32.const 8388607
;; Load byte from that address
i32.load8_u
;; Drop the value (we don't care what it is, just that we could read it)
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,23 +0,0 @@
(module
;; Define memory: 128 pages (8MB) min, 128 pages max
(memory 128 128)
;; Export memory so host can verify size
(export "memory" (memory 0))
(func $access_last_byte (result i32)
;; Push a negative address
i32.const -1
;; Load byte from that address
i32.load8_u
;; Drop the value
drop
;; Return 1 to indicate success
i32.const 1
)
(export "finish" (func $access_last_byte))
)

View File

@@ -1,27 +0,0 @@
(module
;; 1. Define Memory: 1 Page = 64KB
(memory 1)
(export "memory" (memory 0))
(func $test_offset_overflow (result i32)
;; 1. Push the base address onto the stack.
;; We use '0', which is the safest, most valid address possible.
i32.const 0
;; 2. Attempt to load using a static offset.
;; syntax: i32.load offset=N align=N
;; We set the offset to 65536 (the size of the memory).
;; The effective address becomes 0 + 65536 = 65536.
i32.load offset=65536
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
(export "finish" (func $test_offset_overflow))
)

View File

@@ -1,22 +0,0 @@
(module
;; Define 1 page of memory (64KB = 65,536 bytes)
(memory 1)
(func $read_edge (result i32)
;; Push the index of the LAST valid byte
i32.const 65535
;; Load 1 byte (unsigned)
i32.load8_u
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export as "finish" as requested
(export "finish" (func $read_edge))
)

View File

@@ -1,23 +0,0 @@
(module
;; Define 1 page of memory (64KB = 65,536 bytes)
(memory 1)
(func $read_overflow (result i32)
;; Push the index of the FIRST invalid byte
;; Memory is 0..65535, so 65536 is out of bounds.
i32.const 65536
;; Load 1 byte (unsigned)
i32.load8_u
;; Clean up the stack.
;; The load pushed a value, but we don't care what it is.
drop
;; Return 1 to signal "I survived the memory access"
i32.const 1
)
;; Export as "finish" as requested
(export "finish" (func $read_overflow))
)

View File

@@ -1,25 +0,0 @@
(module
;; Define 1 page of memory
(memory 1)
(export "memory" (memory 0))
(func $test_bulk_ops (result i32)
;; Setup: Write value 42 at index 0 so we have something to copy
(i32.store8 (i32.const 0) (i32.const 42))
;; Test memory.copy (Opcode 0xFC 0x0A)
;; Copy 1 byte from offset 0 to offset 100
(memory.copy
(i32.const 100) ;; Destination Offset
(i32.const 0) ;; Source Offset
(i32.const 1) ;; Size (bytes)
)
;; Verify: Read byte at offset 100. Should be 42.
(i32.load8_u (i32.const 100))
(i32.const 42)
i32.eq
)
(export "finish" (func $test_bulk_ops))
)

View File

@@ -1,15 +0,0 @@
(module
;; 1. Define a global using an EXTENDED constant expression.
;; MVP only allows (i32.const X).
;; This proposal allows (i32.add (i32.const X) (i32.const Y)).
(global $g i32 (i32.add (i32.const 10) (i32.const 32)))
(func $finish (result i32)
;; 2. verify the global equals 42
global.get $g
i32.const 42
i32.eq
)
(export "finish" (func $finish))
)

View File

@@ -1,18 +0,0 @@
(module
(func $test_saturation (result i32)
;; 1. Push a float that is too big for a 32-bit integer
;; 1e10 (10 billion) > 2.14 billion (Max i32)
f32.const 1.0e10
;; 2. Attempt saturating conversion (Opcode 0xFC 0x00)
;; If supported: Clamps to MAX_I32.
;; If disabled: Validation error (unknown instruction).
i32.trunc_sat_f32_s
;; 3. Check if result is MAX_I32 (2147483647)
i32.const 2147483647
i32.eq
)
(export "finish" (func $test_saturation))
)

View File

@@ -1,12 +0,0 @@
;; generated by wasm-tools print gc_test.wasm that has the following hex
;; 0061736d01000000010b026000017f5f027f017f0103020100070a010666696e69736800000a0a010800fb01011a41010b
(module
(type (;0;) (func (result i32)))
(type (;1;) (struct (field (mut i32)) (field (mut i32))))
(export "finish" (func 0))
(func (;0;) (type 0) (result i32)
struct.new_default 1
drop
i32.const 1
)
)

View File

@@ -1,22 +0,0 @@
(module
;; 1. Function returning TWO values (Multi-Value feature)
(func $get_numbers (result i32 i32)
i32.const 10
i32.const 20
)
(func $finish (result i32)
;; Call pushes [10, 20] onto the stack
call $get_numbers
;; 2. Block taking TWO parameters (Multi-Value feature)
;; It consumes the [10, 20] from the stack.
block (param i32 i32) (result i32)
i32.add ;; 10 + 20 = 30
i32.const 30 ;; Expected result
i32.eq ;; Compare: returns 1 if equal
end
)
(export "finish" (func $finish))
)

View File

@@ -1,25 +0,0 @@
(module
;; Define a mutable global initialized to 0
(global $counter (mut i32) (i32.const 0))
;; EXPORTING a mutable global is the key feature of this proposal.
;; In strict MVP, exported globals had to be immutable (const).
(export "counter" (global $counter))
(func $finish (result i32)
;; 1. Get current value
global.get $counter
;; 2. Add 1
i32.const 1
i32.add
;; 3. Set new value (Mutation)
global.set $counter
;; 4. Return 1 for success
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,18 +0,0 @@
(module
;; Import a table from the host that holds externrefs
(import "env" "table" (table 1 externref))
(func $test_ref_types (result i32)
;; Store a null externref into the table at index 0
;; If reference_types is disabled, 'externref' and 'ref.null' will fail parsing.
(table.set
(i32.const 0) ;; Index
(ref.null extern) ;; Value (Null External Reference)
)
;; Return 1 (Success)
i32.const 1
)
(export "finish" (func $test_ref_types))
)

View File

@@ -1,18 +0,0 @@
(module
(func $test_sign_ext (result i32)
;; Push 255 (0x000000FF) onto the stack
i32.const 255
;; Sign-extend from 8-bit to 32-bit
;; If 255 is treated as an i8, it is -1.
;; Result should be -1 (0xFFFFFFFF).
;; Without this proposal, this opcode (0xC0) causes a validation error.
i32.extend8_s
;; Check if result is -1
i32.const -1
i32.eq
)
(export "finish" (func $test_sign_ext))
)

View File

@@ -1 +0,0 @@
;;hard to generate

View File

@@ -1,15 +0,0 @@
(module
;; Define a simple function we can tail-call
(func $target (result i32)
i32.const 1
)
(func $finish (result i32)
;; Try to use the 'return_call' instruction (Opcode 0x12)
;; If Tail Call proposal is disabled, this fails to Compile/Validate.
;; If enabled, it jumps to $target, which returns 1.
return_call $target
)
(export "finish" (func $finish))
)

View File

@@ -1,22 +0,0 @@
(module
;; Function 1: The Infinite Loop
(func $run_forever
(loop $infinite
br $infinite
)
)
;; Function 2: Finish
(func $finish (result i32)
i32.const 1
)
;; 1. EXPORT the functions (optional, if you want to call them later)
(export "start" (func $run_forever))
(export "finish" (func $finish))
;; 2. The special start section
;; This tells the VM: "Run function $run_forever immediately
;; when this module is instantiated."
(start $run_forever)
)

View File

@@ -1,10 +0,0 @@
(module
;; Define a table with exactly 0 entries
(table 0 funcref)
;; Standard finish function
(func $finish (result i32)
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,24 +0,0 @@
(module
;; Define a dummy function to put in the tables
(func $dummy)
;; TABLE 0: The default table (allowed in MVP)
;; Size: 1 initial, 1 max
(table $t0 1 1 funcref)
;; Initialize Table 0 at index 0
(elem (table $t0) (i32.const 0) $dummy)
;; TABLE 1: The second table (Requires Reference Types proposal)
;; If strict MVP is enforced, the parser should error here.
(table $t1 1 1 funcref)
;; Initialize Table 1 at index 0
(elem (table $t1) (i32.const 0) $dummy)
(func $finish (result i32)
;; If we successfully loaded a module with 2 tables, return 1.
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,25 +0,0 @@
(module
;; Define a table with exactly 64 entries
(table 64 funcref)
;; A dummy function to reference
(func $dummy)
;; Initialize the table at offset 0 with 64 references to $dummy
(elem (i32.const 0)
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 8
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 16
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 24
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 32
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 40
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 48
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 56
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 64
)
;; Standard finish function
(func $finish (result i32)
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,25 +0,0 @@
(module
;; Define a table with exactly 65 entries
(table 65 funcref)
;; A dummy function to reference
(func $dummy)
;; Initialize the table at offset 0 with 65 references to $dummy
(elem (i32.const 0)
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 8
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 16
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 24
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 32
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 40
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 48
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 56
$dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy ;; 64
$dummy ;; 65 (The one that breaks the camel's back)
)
(func $finish (result i32)
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,15 +0,0 @@
(module
;; Definition: (table <min> <optional_max> <type>)
;; We use 0xFFFFFFFF (4,294,967,295), which is the unsigned equivalent of -1.
;; This tests if the runtime handles the maximum possible u32 value
;; without integer overflows or attempting a massive allocation.
;;
;; Note that using -1 as the table size cannot be parsed by wasm-tools or wat2wasm
(table 0xFFFFFFFF funcref)
(func $finish (result i32)
;; If the module loads despite the massive table, return 1.
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,15 +0,0 @@
(module
(func $finish (export "finish") (result i32)
;; Setup for Requirement 2: Divide an i32 by 0
i32.const 42 ;; Push numerator
i32.const 0 ;; Push denominator (0)
i32.div_s ;; Perform signed division (42 / 0)
;; --- NOTE: Execution usually traps (crashes) at the line above ---
;; Logic to satisfy Requirement 1: Return i32 = 1
;; If execution continued, we would drop the division result and return 1
drop ;; Clear the stack
i32.const 1 ;; Push the return value
)
)

View File

@@ -1,33 +0,0 @@
(module
;; Define a table with 1 slot
(table 1 funcref)
;; Define Type A: Takes nothing, returns nothing
(type $type_void (func))
;; Define Type B: Takes nothing, returns i32
(type $type_i32 (func (result i32)))
;; Define a function of Type A
(func $void_func (type $type_void)
nop
)
;; Put Type A function into Table[0]
(elem (i32.const 0) $void_func)
(func $finish (result i32)
;; Attempt to call Index 0, but CLAIM we expect Type B (result i32).
;; The function at Index 0 matches Type A.
;; TRAP: "indirect call type mismatch"
;; 1. Push the table index (0) onto the stack
i32.const 0
;; 2. Call indirect using Type B signature.
;; This pops the index (0) from the stack.
call_indirect (type $type_i32)
)
(export "finish" (func $finish))
)

View File

@@ -1,18 +0,0 @@
(module
(func $test_int_overflow (result i32)
;; 1. Push INT_MIN (-2147483648)
;; In Hex: 0x80000000
i32.const -2147483648
;; 2. Push -1
i32.const -1
;; 3. Signed Division
;; This specific case is the ONLY integer arithmetic operation
;; (besides divide by zero) that traps in the spec.
;; Result would be +2147483648, which is too big for signed i32.
i32.div_s
)
(export "finish" (func $test_int_overflow))
)

View File

@@ -1,22 +0,0 @@
(module
;; Table size is 1, so Index 0 is VALID bounds.
;; However, we do NOT initialize it, so it contains 'ref.null'.
(table 1 funcref)
(type $t (func (result i32)))
(func $finish (result i32)
;; Call Index 0.
;; Bounds check passes (0 < 1).
;; Null check fails.
;; TRAP: "uninitialized element" or "undefined element"
;; 1. Push the index (0) onto the stack first
i32.const 0
;; 2. Perform the call. This pops the index.
call_indirect (type $t)
)
(export "finish" (func $finish))
)

View File

@@ -1,12 +0,0 @@
(module
(func $finish (result i32)
;; This instruction explicitly causes a trap.
;; It consumes no fuel (beyond the instruction itself) and stops execution.
unreachable
;; This code is dead and never reached
i32.const 1
)
(export "finish" (func $finish))
)

View File

@@ -1,38 +0,0 @@
(module
;; Import clock_time_get from WASI
;; Signature: (param clock_id precision return_ptr) (result errno)
(import "wasi_snapshot_preview1" "clock_time_get"
(func $clock_time_get (param i32 i64 i32) (result i32))
)
(memory 1)
(export "memory" (memory 0))
(func $finish (result i32)
;; We will store the timestamp (a 64-bit integer) at address 0.
;; No setup required in memory beforehand!
;; Call the function
(call $clock_time_get
(i32.const 0) ;; clock_id: 0 = Realtime (Wallclock)
(i64.const 1000) ;; precision: 1000ns (hint to OS)
(i32.const 0) ;; result_ptr: Write the time to address 0
)
;; The function returns an 'errno' (error code).
;; 0 = Success. Anything else = Error.
;; Check if errno (top of stack) is 0
i32.eqz
if (result i32)
;; Success! The time is now stored in heap[0..8].
;; We return 1 as requested.
i32.const 1
else
;; Failed (maybe WASI is disabled or clock is missing)
i32.const -1
end
)
(export "finish" (func $finish))
)

View File

@@ -1,59 +0,0 @@
(module
;; Import WASI fd_write
;; Signature: (fd, iovs_ptr, iovs_len, nwritten_ptr) -> errno
(import "wasi_snapshot_preview1" "fd_write"
(func $fd_write (param i32 i32 i32 i32) (result i32))
)
(memory 1)
(export "memory" (memory 0))
;; --- DATA SEGMENTS ---
;; 1. The String Data "Hello\n" placed at offset 16
;; We assume offset 0-16 is reserved for the IOVec struct
(data (i32.const 16) "Hello\n")
;; 2. The IO Vector (struct iovec) placed at offset 0
;; Structure: { buf_ptr: u32, buf_len: u32 }
;; Field 1: buf_ptr = 16 (Location of "Hello\n")
;; Encoded in little-endian: 10 00 00 00
(data (i32.const 0) "\10\00\00\00")
;; Field 2: buf_len = 6 (Length of "Hello\n")
;; Encoded in little-endian: 06 00 00 00
(data (i32.const 4) "\06\00\00\00")
(func $finish (result i32)
(local $nwritten_ptr i32)
;; We will ask WASI to write the "number of bytes written" to address 24
;; (safely after our string data)
i32.const 24
local.set $nwritten_ptr
;; Call fd_write
(call $fd_write
(i32.const 1) ;; fd: 1 = STDOUT
(i32.const 0) ;; iovs_ptr: Address 0 (where we defined the struct)
(i32.const 1) ;; iovs_len: We are passing 1 vector
(local.get $nwritten_ptr) ;; nwritten_ptr: Address 24
)
;; The function returns an 'errno' (i32).
;; 0 means Success.
;; Check if errno == 0
i32.eqz
if (result i32)
;; Success: Return 1
i32.const 1
else
;; Failure: Return -1
i32.const -1
end
)
(export "finish" (func $finish))
)

Some files were not shown because too many files have changed in this diff Show More