Compare commits

...

8 Commits

Author SHA1 Message Date
TimothyBanks
03511bf0ec feat: Smart Contract codec poc 2026-07-10 12:00:14 -04:00
pwang200
8022fc33cf host function error path refactor (#7639) 2026-07-02 13:35:46 -04:00
Olek
9767d86de4 Memory transfer limit (#7000)
Count bytes copied across the boundaries (Wasm VM <-> Hostfunctions) and return error if limit reached (1 mb default)
2026-06-17 12:45:01 -04:00
Mayukha Vadari
ca2d999618 refactor: rename host functions (#7338)
Co-authored-by: xrplf-ai-reviewer[bot] <266832837+xrplf-ai-reviewer[bot]@users.noreply.github.com>
2026-06-12 15:53:12 -04:00
Mayukha Vadari
5ee903befc remove wasm engine tests 2026-06-09 17:09:45 -04:00
Olek
d582ae7990 HF one entry point (#7393)
Add one entry point for all HF for centralized exceptions handling, gas calculation and general checks.
Add exception handling for HF
Add FieldLocator object
Switch pointers to references for HF and runtime
Max size for parameters and sfData field is 1 kb now
Fix Allhf unittest, to provide correct locator
2026-06-03 21:53:12 -04:00
Olek
0dbe51c740 Cleanup and some refactoring (#7383) 2026-06-02 21:15:58 -04:00
Olek
63fff4b518 Fix HF tests (#7365) 2026-05-29 17:49:03 -04:00
109 changed files with 4097 additions and 14224 deletions

View File

@@ -7,7 +7,6 @@ ignorePaths:
- cmake/**
- LICENSE.md
- .clang-tidy
- src/test/app/wasm_fixtures/**/*.wat
- src/test/app/wasm_fixtures/*.c
language: en
allowCompoundWords: true # TODO (#6334)
@@ -330,6 +329,7 @@ words:
- wthread
- xbridge
- xchain
- xfloat
- ximinez
- XMACRO
- xrpkuwait

View File

@@ -252,10 +252,10 @@ constexpr std::uint8_t kVaultMaximumIouScale = 18;
constexpr std::uint8_t kMaxAssetCheckDepth = 5;
/** Maximum length of a Data field in Escrow object that can be updated by WASM code. */
std::size_t constexpr maxWasmDataLength = 4 * 1024; // 4KB
constexpr std::size_t kMaxWasmDataLength = 1 * 1024; // 1KB
/** Maximum length of parameters passed from WASM code to host functions. */
std::size_t constexpr maxWasmParamLength = 1024; // 1KB
/** Maximum amount of data transfer across hostfunction<->wasm border. */
constexpr std::size_t kWasmTransferLimit = 1 << 20; // 1MB
/** A ledger index. */
using LedgerIndex = std::uint32_t;

View File

@@ -360,6 +360,7 @@ enum TECcodes : TERUnderlyingType {
tecLIMIT_EXCEEDED = 195,
tecPSEUDO_ACCOUNT = 196,
tecPRECISION_LOSS = 197,
tecOUT_OF_GAS = 200,
};
//------------------------------------------------------------------------------

View File

@@ -0,0 +1,37 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/tx/wasm/CodecEnvelope.h>
namespace xrpl::wasm {
// ─────────────────────────────────────────────────────────────────────────
// Public wasm codec API.
//
// This header is what host-function code includes. It intentionally contains
// NO codec machinery, NO registered-codec list, and NO concrete type
// registrations — only the two entry points. Their definitions are provided by
// explicit instantiation in src/libxrpl/tx/wasm/codecs/CodecRegistry.cpp, so
// including this header does not instantiate the (consteval) dispatch tables.
//
// A decode<T>/encode<T> for an unregistered T is a link error by design.
//
// To add a codec, see include/xrpl/tx/wasm/detail/codec_types.macro.
// ─────────────────────────────────────────────────────────────────────────
// Decode a value of the statically-known type T from a self-describing
// envelope. The envelope carries its own (type_code, version), so no revision
// context is needed here.
template <typename T>
[[nodiscard]] Expected<T, CodecError>
decode(CodecEnvelope const& env);
// Encode `value` toward a contract that declared codec revision
// `declaredRevision`. The wire version emitted is chosen by the revision policy
// (wireVersionFor); if the value cannot be represented in that version the
// result is NotRepresentable (the graceful-fail path).
template <typename T>
[[nodiscard]] Expected<CodecEnvelope, CodecError>
encode(CodecVersion declaredRevision, T const& value);
} // namespace xrpl::wasm

View File

@@ -0,0 +1,35 @@
#pragma once
#include <cstdint>
namespace xrpl::wasm {
using CodecTypeCode = std::uint16_t;
using CodecVersion = std::uint8_t;
using CodecLength = std::uint32_t;
enum class CodecError : std::uint8_t {
Ok = 0,
UnknownType = 1, // no type code registered for the type
UnsupportedVersion = 2, // The envelope's version has no registered codec
TypeMismatch = 3, // When decoding, the codec called does not match the type of the envelope
Truncated = 4, // payload size != fixed payload size
NotRepresentable = 5, // when encoding, the value doesn't fit within the requested version
TypeNotInRevision = 6, // There is no codec for the type in the requested version
UnknownCodecVersion = 7, // The codec version is not registered
};
// Defines the header of the binary payload for each parameter based through the host functions
struct CodecEnvelopeHeader {
CodecTypeCode type_code;
CodecVersion version;
CodecLength payload_size; // I would prefer a variable sized integer, will need to revisit this part.
};
// Defines the binary payload for each parameter based through the host functions
struct CodecEnvelope {
CodecEnvelopeHeader header;
std::uint8_t const* payload; // Unclear if this can be a pointer into the wasm payload or a vector holding a copy.
};
} // namespace xrpl::wasm

View File

@@ -8,43 +8,13 @@
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <stdexcept>
#include <string>
namespace xrpl {
enum class HostFunctionError : int32_t {
INTERNAL = -1,
FieldNotFound = -2,
BufferTooSmall = -3,
NoArray = -4,
NotLeafField = -5,
LocatorMalformed = -6,
SlotOutRange = -7,
SlotsFull = -8,
EmptySlot = -9,
LedgerObjNotFound = -10,
DECODING = -11,
DataFieldTooLarge = -12,
PointerOutOfBounds = -13,
NoMemExported = -14,
InvalidParams = -15,
InvalidAccount = -16,
InvalidField = -17,
IndexOutOfBounds = -18,
FloatInputMalformed = -19,
FloatComputationError = -20,
NoRuntime = -21,
OutOfGas = -22,
};
using FloatPair = std::pair<int64_t, int32_t>;
inline int32_t
HfErrorToInt(HostFunctionError e)
{
return static_cast<int32_t>(e);
}
namespace wasm_float {
std::string
@@ -95,32 +65,45 @@ floatPowerImpl(Slice const& x, int32_t n, int32_t mode);
} // namespace wasm_float
// Intended to work only through wasm runtime. Don't call them directly, except with unit tests
struct HostFunctions
class HostFunctions
{
beast::Journal j;
protected:
RTOptRef rt_;
beast::Journal j_;
HostFunctions(beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : j(j)
public:
HostFunctions(beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : j_(j)
{
}
// LCOV_EXCL_START
virtual void
setRT(void*)
void
setRT(WasmRuntimeWrapper& rt)
{
rt_ = rt;
}
[[nodiscard]] virtual void*
void
resetRT()
{
rt_ = std::nullopt;
}
[[nodiscard]] WasmRuntimeWrapper&
getRT() const
{
return nullptr;
if (!rt_)
Throw<std::logic_error>("Wasm runtime not set");
return rt_->get();
}
[[nodiscard]] beast::Journal
getJournal() const
{
return j;
return j_;
}
// LCOV_EXCL_START
[[nodiscard]] virtual bool
checkSelf() const
{
@@ -130,402 +113,404 @@ struct HostFunctions
virtual Expected<std::uint32_t, HostFunctionError>
getLedgerSqn() const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<std::uint32_t, HostFunctionError>
getParentLedgerTime() const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Hash, HostFunctionError>
getParentLedgerHash() const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<uint32_t, HostFunctionError>
getBaseFee() const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
isAmendmentEnabled(uint256 const& amendmentId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
isAmendmentEnabled(std::string_view const& amendmentName) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
cacheLedgerObj(uint256 const& objId, int32_t cacheIdx)
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getTxField(SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getCurrentLedgerObjField(SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getLedgerObjField(int32_t cacheIdx, SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getTxNestedField(Slice const& locator) const
getTxNestedField(FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getCurrentLedgerObjNestedField(Slice const& locator) const
getCurrentLedgerObjNestedField(FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getLedgerObjNestedField(int32_t cacheIdx, Slice const& locator) const
getLedgerObjNestedField(int32_t cacheIdx, FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getTxArrayLen(SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getCurrentLedgerObjArrayLen(SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getLedgerObjArrayLen(int32_t cacheIdx, SField const& fname) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getTxNestedArrayLen(Slice const& locator) const
getTxNestedArrayLen(FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getCurrentLedgerObjNestedArrayLen(Slice const& locator) const
getCurrentLedgerObjNestedArrayLen(FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getLedgerObjNestedArrayLen(int32_t cacheIdx, Slice const& locator) const
getLedgerObjNestedArrayLen(int32_t cacheIdx, FieldLocator const& locator) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
updateData(Slice const& data)
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
checkSignature(Slice const& message, Slice const& signature, Slice const& pubkey) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Hash, HostFunctionError>
computeSha512HalfHash(Slice const& data) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
accountKeylet(AccountID const& account) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
ammKeylet(Asset const& issue1, Asset const& issue2) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
checkKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
credentialKeylet(AccountID const& subject, AccountID const& issuer, Slice const& credentialType)
const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
didKeylet(AccountID const& account) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
delegateKeylet(AccountID const& account, AccountID const& authorize) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
depositPreauthKeylet(AccountID const& account, AccountID const& authorize) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
escrowKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
lineKeylet(AccountID const& account1, AccountID const& account2, Currency const& currency) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
mptIssuanceKeylet(AccountID const& issuer, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
mptokenKeylet(MPTID const& mptid, AccountID const& holder) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
nftOfferKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
offerKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
oracleKeylet(AccountID const& account, std::uint32_t docId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
paychanKeylet(AccountID const& account, AccountID const& destination, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
permissionedDomainKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
signersKeylet(AccountID const& account) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
ticketKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
vaultKeylet(AccountID const& account, std::uint32_t seq) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getNFT(AccountID const& account, uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
getNFTIssuer(uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<std::uint32_t, HostFunctionError>
getNFTTaxon(uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getNFTFlags(uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
getNFTTransferFee(uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<std::uint32_t, HostFunctionError>
getNFTSerial(uint256 const& nftId) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
trace(std::string_view const& msg, Slice const& data, bool asHex) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
traceNum(std::string_view const& msg, int64_t data) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
traceAccount(std::string_view const& msg, AccountID const& account) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
traceFloat(std::string_view const& msg, Slice const& data) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
traceAmount(std::string_view const& msg, STAmount const& amount) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatFromInt(int64_t x, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatFromUint(uint64_t x, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatFromSTAmount(STAmount const& x, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatFromSTNumber(STNumber const& x, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int64_t, HostFunctionError>
floatToInt(Slice const& x, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<FloatPair, HostFunctionError>
floatToMantExp(Slice const& x) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatFromMantExp(int64_t mantissa, int32_t exponent, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<int32_t, HostFunctionError>
floatCompare(Slice const& x, Slice const& y) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatAdd(Slice const& x, Slice const& y, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatSubtract(Slice const& x, Slice const& y, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatMultiply(Slice const& x, Slice const& y, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatDivide(Slice const& x, Slice const& y, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatRoot(Slice const& x, int32_t n, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual Expected<Bytes, HostFunctionError>
floatPower(Slice const& x, int32_t n, int32_t mode) const
{
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
virtual ~HostFunctions() = default;
// LCOV_EXCL_STOP
};
using HFRef = std::reference_wrapper<HostFunctions>;
} // namespace xrpl

View File

@@ -18,8 +18,7 @@ class WasmHostFunctionsImpl : public HostFunctions
std::optional<Bytes> data_;
void* rt_ = nullptr;
public:
Expected<std::shared_ptr<SLE const>, HostFunctionError>
getCurrentLedgerObj() const
{
@@ -65,18 +64,6 @@ public:
{
}
void
setRT(void* rt) override
{
rt_ = rt;
}
void*
getRT() const override
{
return rt_;
}
bool
checkSelf() const override
{
@@ -121,13 +108,13 @@ public:
getLedgerObjField(int32_t cacheIdx, SField const& fname) const override;
Expected<Bytes, HostFunctionError>
getTxNestedField(Slice const& locator) const override;
getTxNestedField(FieldLocator const& locator) const override;
Expected<Bytes, HostFunctionError>
getCurrentLedgerObjNestedField(Slice const& locator) const override;
getCurrentLedgerObjNestedField(FieldLocator const& locator) const override;
Expected<Bytes, HostFunctionError>
getLedgerObjNestedField(int32_t cacheIdx, Slice const& locator) const override;
getLedgerObjNestedField(int32_t cacheIdx, FieldLocator const& locator) const override;
Expected<int32_t, HostFunctionError>
getTxArrayLen(SField const& fname) const override;
@@ -139,13 +126,13 @@ public:
getLedgerObjArrayLen(int32_t cacheIdx, SField const& fname) const override;
Expected<int32_t, HostFunctionError>
getTxNestedArrayLen(Slice const& locator) const override;
getTxNestedArrayLen(FieldLocator const& locator) const override;
Expected<int32_t, HostFunctionError>
getCurrentLedgerObjNestedArrayLen(Slice const& locator) const override;
getCurrentLedgerObjNestedArrayLen(FieldLocator const& locator) const override;
Expected<int32_t, HostFunctionError>
getLedgerObjNestedArrayLen(int32_t cacheIdx, Slice const& locator) const override;
getLedgerObjNestedArrayLen(int32_t cacheIdx, FieldLocator const& locator) const override;
Expected<int32_t, HostFunctionError>
updateData(Slice const& data) override;

View File

@@ -1,6 +1,6 @@
#pragma once
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmImportsHelper.h>
#include <wasm.h>
@@ -8,110 +8,86 @@
namespace xrpl {
#define WASM_CB_PARAMS_LIST void *env, wasm_val_vec_t const *params, wasm_val_vec_t *results
#define WASM_SECONDARY_CB_PARAMS_LIST \
HostFunctions &hf, wasm_val_vec_t const *params, wasm_val_vec_t *results
wasm_trap_t* HostFuncMain_wrap(WASM_CB_PARAMS_LIST);
using getLedgerSqn_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getLedgerSqn_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getLedgerSqn_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getParentLedgerTime_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getParentLedgerTime_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getParentLedgerTime_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getParentLedgerHash_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getParentLedgerHash_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getParentLedgerHash_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getBaseFee_proto = int32_t(uint8_t*, int32_t);
wasm_trap_t*
getBaseFee_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getBaseFee_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using isAmendmentEnabled_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
isAmendmentEnabled_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* isAmendmentEnabled_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using cacheLedgerObj_proto = int32_t(uint8_t const*, int32_t, int32_t);
wasm_trap_t*
cacheLedgerObj_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* cacheLedgerObj_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getTxField_proto = int32_t(int32_t, uint8_t*, int32_t);
wasm_trap_t*
getTxField_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getTxField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getCurrentLedgerObjField_proto = int32_t(int32_t, uint8_t*, int32_t);
wasm_trap_t*
getCurrentLedgerObjField_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getCurrentLedgerObjField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getLedgerObjField_proto = int32_t(int32_t, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getLedgerObjField_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getLedgerObjField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getTxNestedField_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getTxNestedField_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getTxNestedField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getCurrentLedgerObjNestedField_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getCurrentLedgerObjNestedField_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
wasm_trap_t* getCurrentLedgerObjNestedField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getLedgerObjNestedField_proto = int32_t(int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getLedgerObjNestedField_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getLedgerObjNestedField_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getTxArrayLen_proto = int32_t(int32_t);
wasm_trap_t*
getTxArrayLen_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getTxArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getCurrentLedgerObjArrayLen_proto = int32_t(int32_t);
wasm_trap_t*
getCurrentLedgerObjArrayLen_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getCurrentLedgerObjArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getLedgerObjArrayLen_proto = int32_t(int32_t, int32_t);
wasm_trap_t*
getLedgerObjArrayLen_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getLedgerObjArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getTxNestedArrayLen_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
getTxNestedArrayLen_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getTxNestedArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getCurrentLedgerObjNestedArrayLen_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
getCurrentLedgerObjNestedArrayLen_wrap(
void* env,
wasm_val_vec_t const* params,
wasm_val_vec_t* results);
wasm_trap_t* getCurrentLedgerObjNestedArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getLedgerObjNestedArrayLen_proto = int32_t(int32_t, uint8_t const*, int32_t);
wasm_trap_t*
getLedgerObjNestedArrayLen_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getLedgerObjNestedArrayLen_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using updateData_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
updateData_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* updateData_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using checkSignature_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
checkSignature_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* checkSignature_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using computeSha512HalfHash_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
computeSha512HalfHash_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* computeSha512HalfHash_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using accountKeylet_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
accountKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* accountKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using ammKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
ammKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* ammKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using checkKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
checkKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* checkKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using credentialKeylet_proto = int32_t(
uint8_t const*,
@@ -122,27 +98,22 @@ using credentialKeylet_proto = int32_t(
int32_t,
uint8_t*,
int32_t);
wasm_trap_t*
credentialKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* credentialKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using delegateKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
delegateKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* delegateKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using depositPreauthKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
depositPreauthKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* depositPreauthKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using didKeylet_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
didKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* didKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using escrowKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
escrowKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* escrowKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using lineKeylet_proto = int32_t(
uint8_t const*,
@@ -153,33 +124,27 @@ using lineKeylet_proto = int32_t(
int32_t,
uint8_t*,
int32_t);
wasm_trap_t*
lineKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* lineKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using mptIssuanceKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
mptIssuanceKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* mptIssuanceKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using mptokenKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
mptokenKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* mptokenKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using nftOfferKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
nftOfferKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* nftOfferKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using offerKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
offerKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* offerKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using oracleKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
oracleKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* oracleKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using paychanKeylet_proto = int32_t(
uint8_t const*,
@@ -190,130 +155,100 @@ using paychanKeylet_proto = int32_t(
int32_t,
uint8_t*,
int32_t);
wasm_trap_t*
paychanKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* paychanKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using permissionedDomainKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
permissionedDomainKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* permissionedDomainKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using signersKeylet_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
signersKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* signersKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using ticketKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
ticketKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* ticketKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using vaultKeylet_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
vaultKeylet_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* vaultKeylet_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFT_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getNFT_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFT_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFTIssuer_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getNFTIssuer_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFTIssuer_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFTTaxon_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getNFTTaxon_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFTTaxon_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFTFlags_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
getNFTFlags_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFTFlags_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFTTransferFee_proto = int32_t(uint8_t const*, int32_t);
wasm_trap_t*
getNFTTransferFee_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFTTransferFee_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using getNFTSerial_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
getNFTSerial_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* getNFTSerial_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using trace_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, int32_t);
wasm_trap_t*
trace_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* trace_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using traceNum_proto = int32_t(uint8_t const*, int32_t, int64_t);
wasm_trap_t*
traceNum_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* traceNum_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using traceAccount_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
traceAccount_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* traceAccount_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using traceFloat_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
traceFloat_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* traceFloat_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using traceAmount_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
traceAmount_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* traceAmount_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatFromInt_proto = int32_t(int64_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromInt_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatFromInt_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatFromUint_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromUint_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatFromUint_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatFromSTAmount_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromSTAmount_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatFromSTAmount_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatFromSTNumber_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromSTNumber_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatFromSTNumber_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatToInt_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatToInt_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatToInt_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatToMantExp_proto = int32_t(uint8_t const*, int32_t, uint8_t*, int32_t, uint8_t*, int32_t);
wasm_trap_t*
floatToMantExp_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatToMantExp_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatFromMantExp_proto = int32_t(int64_t, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatFromMantExp_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatFromMantExp_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatCompare_proto = int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t);
wasm_trap_t*
floatCompare_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatCompare_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatAdd_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatAdd_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatAdd_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatSubtract_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatSubtract_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatSubtract_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatMultiply_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatMultiply_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatMultiply_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatDivide_proto =
int32_t(uint8_t const*, int32_t, uint8_t const*, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatDivide_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatDivide_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatRoot_proto = int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatRoot_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatRoot_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
using floatPower_proto = int32_t(uint8_t const*, int32_t, int32_t, uint8_t*, int32_t, int32_t);
wasm_trap_t*
floatPower_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
wasm_trap_t* floatPower_wrap(WASM_SECONDARY_CB_PARAMS_LIST);
} // namespace xrpl

View File

@@ -1,245 +0,0 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/mpl/vector.hpp>
#include <bit>
#include <cstdint>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
namespace bft = boost::function_types;
namespace xrpl {
template <typename>
inline constexpr bool wasmDependentFalse = false;
using Bytes = std::vector<std::uint8_t>;
using Hash = xrpl::uint256;
struct Wmem
{
std::uint8_t* p = nullptr;
std::size_t s = 0;
};
template <typename T>
struct WasmResult
{
T result;
int64_t cost;
};
using EscrowResult = WasmResult<int32_t>;
struct WasmRuntimeWrapper
{
virtual ~WasmRuntimeWrapper() = default;
virtual Wmem
getMem() = 0;
virtual std::int64_t
getGas() = 0;
virtual std::int64_t
setGas(std::int64_t gas) = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
enum class WasmTypes { WtI32, WtI64 };
struct WasmImportFunc
{
std::string_view name;
std::optional<WasmTypes> result;
std::vector<WasmTypes> params;
// void* udata = nullptr;
// wasm_func_callback_with_env_t
void* wrap = nullptr;
uint32_t gas = 0;
};
using WasmUserData = std::pair<void*, WasmImportFunc>;
using ImportVec = std::unordered_map<std::string_view, WasmUserData>;
#define WASM_IMPORT_FUNC(v, f, ...) \
WasmImpFunc<f##_proto>(v, #f, reinterpret_cast<void*>(&f##_wrap), ##__VA_ARGS__)
// n - string literal name, must have static lifetime
#define WASM_IMPORT_FUNC2(v, f, n, ...) \
WasmImpFunc<f##_proto>(v, n, reinterpret_cast<void*>(&f##_wrap), ##__VA_ARGS__)
template <int N, int C, typename Mpl>
void
WasmImpArgs(WasmImportFunc& e)
{
if constexpr (N < C)
{
using at = typename boost::mpl::at_c<Mpl, N>::type;
if constexpr (std::is_pointer_v<at>)
{
e.params.push_back(WasmTypes::WtI32);
}
else if constexpr (std::is_same_v<at, std::int32_t>)
{
e.params.push_back(WasmTypes::WtI32);
}
else if constexpr (std::is_same_v<at, std::int64_t>)
{
e.params.push_back(WasmTypes::WtI64);
}
else
{
static_assert(std::is_pointer_v<at>, "Unsupported argument type");
}
return WasmImpArgs<N + 1, C, Mpl>(e);
}
return;
}
template <typename Rt>
void
WasmImpRet(WasmImportFunc& e)
{
if constexpr (std::is_pointer_v<Rt>)
{
e.result = WasmTypes::WtI32;
}
else if constexpr (std::is_same_v<Rt, std::int32_t>)
{
e.result = WasmTypes::WtI32;
}
else if constexpr (std::is_same_v<Rt, std::int64_t>)
{
e.result = WasmTypes::WtI64;
}
else if constexpr (std::is_void_v<Rt>)
{
e.result.reset();
}
else
{
static_assert(wasmDependentFalse<Rt>, "Unsupported return type");
}
}
template <typename F>
void
WasmImpFuncHelper(WasmImportFunc& e)
{
using rt = typename bft::result_type<F>::type;
using pt = typename bft::parameter_types<F>::type;
// typename boost::mpl::at_c<mpl, N>::type
WasmImpRet<rt>(e);
WasmImpArgs<0, bft::function_arity<F>::value, pt>(e);
// WasmImpWrap(e, std::forward<F>(f));
}
// imp_name - string literal, must have static lifetime
template <typename F>
void
WasmImpFunc(
ImportVec& v,
std::string_view impName,
void* fWrap,
void* data = nullptr,
uint32_t gas = 0)
{
WasmImportFunc e;
e.name = impName;
e.wrap = fWrap;
e.gas = gas;
WasmImpFuncHelper<F>(e);
v.emplace(impName, std::make_pair(data, std::move(e)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct WasmParam
{
// We are not supporting float/double
WasmTypes type = WasmTypes::WtI32;
union
{
std::int32_t i32;
std::int64_t i64 = 0;
} of;
};
template <class... Types>
inline void
wasmParamsHlp(std::vector<WasmParam>& v, std::int32_t p, Types&&... args)
{
v.push_back({.type = WasmTypes::WtI32, .of = {.i32 = p}});
wasmParamsHlp(v, std::forward<Types>(args)...);
}
template <class... Types>
inline void
wasmParamsHlp(std::vector<WasmParam>& v, std::int64_t p, Types&&... args)
{
v.push_back({.type = WasmTypes::WtI64, .of = {.i64 = p}});
wasmParamsHlp(v, std::forward<Types>(args)...);
}
inline void
wasmParamsHlp(std::vector<WasmParam>& v)
{
return;
}
template <class... Types>
inline std::vector<WasmParam>
wasmParams(Types&&... args)
{
std::vector<WasmParam> v;
v.reserve(sizeof...(args));
wasmParamsHlp(v, std::forward<Types>(args)...);
return v;
}
template <typename T, size_t Size = sizeof(T)>
constexpr T
adjustWasmEndianessHlp(T x)
{
static_assert(std::is_integral_v<T>, "Only integral types");
if constexpr (Size > 1)
{
using U = std::make_unsigned_t<T>;
U u = static_cast<U>(x);
U const low = (u & 0xFF) << ((Size - 1) << 3);
u = adjustWasmEndianessHlp<U, Size - 1>(u >> 8);
return static_cast<T>(low | u);
}
return x;
}
template <typename T, size_t Size = sizeof(T)>
constexpr T
adjustWasmEndianess(T x)
{
// LCOV_EXCL_START
static_assert(std::is_integral_v<T>, "Only integral types");
if constexpr (std::endian::native == std::endian::big)
{
return adjustWasmEndianessHlp(x);
}
return x;
// LCOV_EXCL_STOP
}
} // namespace xrpl

View File

@@ -0,0 +1,237 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/protocol/TER.h>
#include <functional>
#include <optional>
#include <stdexcept>
#include <string_view>
#include <vector>
namespace xrpl {
using Bytes = std::vector<std::uint8_t>;
using Hash = xrpl::uint256;
using FloatPair = std::pair<int64_t, int32_t>;
// Error signals that cross the wasm boundary as trap messages (the C API has no
// trap code). WasmiEngine::call maps them to TER: hfErrInternal -> tecINTERNAL,
// hfErrOutOfGas / wasmi's OutOfFuel -> tecOUT_OF_GAS, anything else ->
// tecFAILED_PROCESSING.
//
// Matched as substrings, not by equality: the C API returns the Rust Debug form
// of the error, e.g. `Error { kind: Message("HfInternal") }` or
// `Error { kind: TrapCode(OutOfFuel) }`.
std::string_view inline constexpr hfErrInternal = "HfInternal";
std::string_view inline constexpr hfErrOutOfGas = "HfOutOfGas";
std::string_view inline constexpr wasmiTrapOutOfFuel = "OutOfFuel";
enum class HostFunctionError : int32_t {
Unimplemented = -1,
FieldNotFound = -2,
BufferTooSmall = -3,
NoArray = -4,
NotLeafField = -5,
LocatorMalformed = -6,
SlotOutRange = -7,
SlotsFull = -8,
EmptySlot = -9,
LedgerObjNotFound = -10,
OutOfTransferLimit = -11,
DataFieldTooLarge = -12,
PointerOutOfBounds = -13,
NoMemExported = -14,
InvalidParams = -15,
InvalidAccount = -16,
InvalidField = -17,
IndexOutOfBounds = -18,
FloatInputMalformed = -19,
FloatComputationError = -20,
};
enum class WasmTypes { WtI32, WtI64 };
struct Wmem
{
std::uint8_t* p = nullptr;
std::size_t s = 0;
Wmem() = default;
Wmem(void* ptr, std::size_t size) : p(reinterpret_cast<std::uint8_t*>(ptr)), s(size)
{
}
};
template <typename T>
struct WasmResult
{
T result;
int64_t cost;
};
using EscrowResult = WasmResult<int32_t>;
// Engine error when wasm does not run to completion. `cost` is the gas consumed
// when meaningful (tecOUT_OF_GAS / tecFAILED_PROCESSING; caller writes it to tx
// metadata); std::nullopt for tecINTERNAL and malformed input (no gas reported).
struct WasmTER
{
TER ter;
std::optional<int64_t> cost;
};
class FieldLocator
{
int32_t const* ptr_ = nullptr;
uint32_t size_ = 0;
std::vector<int32_t> buf_;
public:
FieldLocator(std::vector<int32_t>&& buf)
: ptr_(&buf[0]), size_(buf.size()), buf_(std::move(buf))
{
}
FieldLocator(int32_t const* ptr, uint32_t const size) : ptr_(ptr), size_(size)
{
}
FieldLocator(FieldLocator const&) = delete;
FieldLocator&
operator=(FieldLocator const&) = delete;
FieldLocator(FieldLocator&&) = default;
FieldLocator&
operator=(FieldLocator&&) = default;
int32_t
operator[](unsigned i) const
{
if (i >= size_)
Throw<std::runtime_error>("index out of bounds");
return ptr_[i];
}
[[nodiscard]] uint32_t
size() const
{
return size_;
}
[[nodiscard]] int32_t const*
data() const
{
return ptr_;
}
[[nodiscard]] bool
empty() const
{
return size_ == 0;
}
};
class WasmRuntimeWrapper
{
public:
virtual ~WasmRuntimeWrapper() = default;
virtual Wmem
getMem() = 0;
virtual std::int64_t
getGas() = 0;
virtual std::int64_t
setGas(std::int64_t gas) = 0;
virtual std::int64_t
getTransferLimit() = 0;
virtual std::int64_t
setTransferLimit(std::int64_t transferLimit) = 0;
};
using RTOptRef = std::optional<std::reference_wrapper<WasmRuntimeWrapper>>;
struct WasmParam
{
// We are not supporting float/double
WasmTypes type = WasmTypes::WtI32;
union
{
std::int32_t i32;
std::int64_t i64 = 0;
} of;
};
template <class... Types>
inline void
wasmParamsHlp(std::vector<WasmParam>& v, std::int32_t p, Types&&... args)
{
v.push_back({.type = WasmTypes::WtI32, .of = {.i32 = p}});
wasmParamsHlp(v, std::forward<Types>(args)...);
}
template <class... Types>
inline void
wasmParamsHlp(std::vector<WasmParam>& v, std::int64_t p, Types&&... args)
{
v.push_back({.type = WasmTypes::WtI64, .of = {.i64 = p}});
wasmParamsHlp(v, std::forward<Types>(args)...);
}
inline void
wasmParamsHlp(std::vector<WasmParam>& v)
{
return;
}
template <class... Types>
inline std::vector<WasmParam>
wasmParams(Types&&... args)
{
std::vector<WasmParam> v;
v.reserve(sizeof...(args));
wasmParamsHlp(v, std::forward<Types>(args)...);
return v;
}
template <typename T, size_t Size = sizeof(T)>
constexpr T
adjustWasmEndianessHlp(T x)
{
static_assert(std::is_integral_v<T>, "Only integral types");
if constexpr (Size > 1)
{
using U = std::make_unsigned_t<T>;
U u = static_cast<U>(x);
U const low = (u & 0xFF) << ((Size - 1) << 3);
u = adjustWasmEndianessHlp<U, Size - 1>(u >> 8);
return static_cast<T>(low | u);
}
return x;
}
template <typename T, size_t Size = sizeof(T)>
constexpr T
adjustWasmEndianess(T x)
{
// LCOV_EXCL_START
static_assert(std::is_integral_v<T>, "Only integral types");
if constexpr (std::endian::native == std::endian::big)
{
return adjustWasmEndianessHlp(x);
}
return x;
// LCOV_EXCL_STOP
}
constexpr int32_t
hfErrorToInt(HostFunctionError e)
{
return static_cast<int32_t>(e);
}
} // namespace xrpl

View File

@@ -0,0 +1,128 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/mpl/vector.hpp>
#include <wasm.h>
namespace bft = boost::function_types;
namespace xrpl {
using wasmSecondaryCbFuncType =
wasm_trap_t*(HostFunctions&, wasm_val_vec_t const*, wasm_val_vec_t*);
struct WasmImportFunc
{
std::string_view name;
std::optional<WasmTypes> result;
std::vector<WasmTypes> params;
wasmSecondaryCbFuncType* wrap = nullptr;
uint32_t gas = 0;
};
using WasmUserData = std::pair<HFRef, WasmImportFunc>;
// string - import function name
using ImportVec = std::unordered_map<std::string_view, WasmUserData>;
template <int N, int C, typename Mpl>
void
WasmImpArgs(WasmImportFunc& e)
{
if constexpr (N < C)
{
using at = typename boost::mpl::at_c<Mpl, N>::type;
if constexpr (std::is_pointer_v<at>)
{
e.params.push_back(WasmTypes::WtI32);
}
else if constexpr (std::is_same_v<at, std::int32_t>)
{
e.params.push_back(WasmTypes::WtI32);
}
else if constexpr (std::is_same_v<at, std::int64_t>)
{
e.params.push_back(WasmTypes::WtI64);
}
else
{
static_assert(std::is_pointer_v<at>, "Unsupported argument type");
}
return WasmImpArgs<N + 1, C, Mpl>(e);
}
return;
}
template <typename>
inline constexpr bool wasmDependentFalse = false;
template <typename Rt>
void
WasmImpRet(WasmImportFunc& e)
{
if constexpr (std::is_pointer_v<Rt>)
{
e.result = WasmTypes::WtI32;
}
else if constexpr (std::is_same_v<Rt, std::int32_t>)
{
e.result = WasmTypes::WtI32;
}
else if constexpr (std::is_same_v<Rt, std::int64_t>)
{
e.result = WasmTypes::WtI64;
}
else if constexpr (std::is_void_v<Rt>)
{
e.result.reset();
}
else
{
static_assert(wasmDependentFalse<Rt>, "Unsupported return type");
}
}
template <typename F>
void
WasmImpFuncHelper(WasmImportFunc& e)
{
using rt = typename bft::result_type<F>::type;
using pt = typename bft::parameter_types<F>::type;
// typename boost::mpl::at_c<mpl, N>::type
WasmImpRet<rt>(e);
WasmImpArgs<0, bft::function_arity<F>::value, pt>(e);
// WasmImpWrap(e, std::forward<F>(f));
}
// imp_name - string literal, must have static lifetime
template <typename F>
void
WasmImpFunc(
ImportVec& v,
std::string_view impName,
wasmSecondaryCbFuncType* fWrap,
HostFunctions& hf,
uint32_t gas = 0)
{
WasmImportFunc e;
e.name = impName;
e.wrap = fWrap;
e.gas = gas;
WasmImpFuncHelper<F>(e);
v.emplace(impName, std::make_pair(HFRef(hf), std::move(e)));
}
#define WASM_IMPORT_FUNC(v, f, ...) WasmImpFunc<f##_proto>(v, #f, &f##_wrap, ##__VA_ARGS__)
// n - string literal name, must have static lifetime
#define WASM_IMPORT_FUNC2(v, f, n, ...) WasmImpFunc<f##_proto>(v, n, &f##_wrap, ##__VA_ARGS__)
} // namespace xrpl

View File

@@ -1,6 +1,7 @@
#pragma once
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/WasmImportsHelper.h>
#include <string_view>
@@ -39,7 +40,7 @@ public:
static WasmEngine&
instance();
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
run(Bytes const& wasmCode,
HostFunctions& hfs,
int64_t gasLimit,
@@ -70,7 +71,7 @@ public:
ImportVec
createWasmImport(HostFunctions& hfs);
Expected<EscrowResult, TER>
Expected<EscrowResult, WasmTER>
runEscrowWasm(
Bytes const& wasmCode,
HostFunctions& hfs,

View File

@@ -1,10 +1,13 @@
#pragma once
#include <xrpl/protocol/Protocol.h>
#include <xrpl/tx/wasm/WasmVM.h>
#include <wasm.h>
#include <wasmi.h>
#include <optional>
namespace xrpl {
template <class T, void (*Create)(T*, size_t), void (*Destroy)(T*)>
@@ -119,7 +122,10 @@ using WasmImporttypeVec = WasmVec<
struct WasmiResult
{
WasmValVec r;
bool f{false}; // failure flag
// Set iff the call trapped. Holds the TER the trap was classified into
// (tecINTERNAL / tecOUT_OF_GAS / tecFAILED_PROCESSING); see
// WasmiEngine::call. std::nullopt means the call returned normally.
std::optional<TER> ter;
WasmiResult(unsigned n = 0) : r(n)
{
@@ -139,13 +145,14 @@ using StorePtr = std::unique_ptr<wasm_store_t, decltype(&wasm_store_delete)>;
using FuncInfo = std::pair<wasm_func_t const*, wasm_functype_t const*>;
struct InstanceWrapper
class InstanceWrapper
{
wasm_store_t* store = nullptr;
WasmExternVec exports;
mutable int memIdx = -1;
InstancePtr instance;
beast::Journal j = beast::Journal(beast::Journal::getNullSink());
wasm_store_t* store_ = nullptr;
WasmExternVec exports_;
mutable int memIdx_ = -1;
InstancePtr instance_;
beast::Journal j_ = beast::Journal(beast::Journal::getNullSink());
std::int64_t transferLimit_ = kWasmTransferLimit;
private:
static InstancePtr
@@ -157,13 +164,19 @@ private:
beast::Journal j);
public:
InstanceWrapper();
InstanceWrapper() : instance_(nullptr, &wasm_instance_delete) {};
InstanceWrapper(InstanceWrapper const&) = delete;
InstanceWrapper(InstanceWrapper&& o);
InstanceWrapper(InstanceWrapper&& o) : instance_(nullptr, &wasm_instance_delete)
{
*this = std::move(o); // LCOV_EXCL_LINE
}
InstanceWrapper(StorePtr& s, ModulePtr& m, WasmExternVec const& imports, beast::Journal j);
InstanceWrapper(StorePtr& s, ModulePtr& m, WasmExternVec const& imports, beast::Journal j)
: store_(s.get()), instance_(init(s, m, exports_, imports, j)), j_(j)
{
}
InstanceWrapper&
operator=(InstanceWrapper&& o);
@@ -171,7 +184,10 @@ public:
InstanceWrapper&
operator=(InstanceWrapper const&) = delete;
operator bool() const;
operator bool() const
{
return static_cast<bool>(instance_);
}
FuncInfo
getFunc(std::string_view funcName, WasmExporttypeVec const& exportTypes) const;
@@ -184,22 +200,33 @@ public:
std::int64_t
setGas(std::int64_t) const;
std::int64_t
getTransferLimit() const;
std::int64_t
setTransferLimit(std::int64_t);
};
struct ModuleWrapper
class ModuleWrapper
{
ModulePtr module;
InstanceWrapper instanceWrap;
WasmExporttypeVec exportTypes;
beast::Journal j = beast::Journal(beast::Journal::getNullSink());
private:
static ModulePtr
init(StorePtr& s, Bytes const& wasmBin, beast::Journal j);
ModulePtr module_;
InstanceWrapper instanceWrap_;
WasmExporttypeVec exportTypes_;
beast::Journal j_ = beast::Journal(beast::Journal::getNullSink());
public:
ModuleWrapper();
ModuleWrapper(ModuleWrapper&& o);
// LCOV_EXCL_START
ModuleWrapper() : module_(nullptr, &wasm_module_delete)
{
}
ModuleWrapper(ModuleWrapper&& o) : module_(nullptr, &wasm_module_delete)
{
*this = std::move(o);
}
// LCOV_EXCL_STOP
ModuleWrapper&
operator=(ModuleWrapper&& o);
ModuleWrapper(
@@ -210,27 +237,55 @@ public:
beast::Journal j);
~ModuleWrapper() = default;
operator bool() const;
operator bool() const
{
return instanceWrap_;
}
FuncInfo
getFunc(std::string_view funcName) const;
getFunc(std::string_view funcName) const
{
return instanceWrap_.getFunc(funcName, exportTypes_);
}
wasm_functype_t*
getFuncType(std::string_view funcName) const;
Wmem
getMem() const;
getMem() const
{
return instanceWrap_.getMem();
}
InstanceWrapper&
getInstance(int i = 0);
getInstance(int i = 0)
{
return instanceWrap_;
}
InstanceWrapper const&
getInstance(int i = 0) const
{
return instanceWrap_;
}
int
addInstance(StorePtr& s, WasmExternVec const& imports);
addInstance(StorePtr& s, WasmExternVec const& imports)
{
instanceWrap_ = {s, module_, imports, j_};
return 0;
}
std::int64_t
getGas() const;
getGas() const
{
return instanceWrap_ ? instanceWrap_.getGas() : -1;
}
private:
static ModulePtr
init(StorePtr& s, Bytes const& wasmBin, beast::Journal j);
WasmExternVec
buildImports(StorePtr& s, ImportVec const& imports) const;
};
@@ -245,13 +300,16 @@ class WasmiEngine
std::mutex m_; // 1 instance mutex
public:
WasmiEngine();
WasmiEngine() : engine_(init()), store_(nullptr, &wasm_store_delete)
{
}
~WasmiEngine() = default;
static EnginePtr
init();
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
run(Bytes const& wasmCode,
HostFunctions& hfs,
int64_t gas,
@@ -270,23 +328,39 @@ public:
beast::Journal j);
[[nodiscard]] std::int64_t
getGas() const;
getGas() const
{
return moduleWrap_ ? moduleWrap_->getGas() : -1; // LCOV_EXCL_LINE
}
// Host functions helper functionality
wasm_trap_t*
newTrap(std::string const& msg);
// LCOV_EXCL_START
[[nodiscard]] beast::Journal
getJournal() const;
getJournal() const
{
return j_;
}
// LCOV_EXCL_STOP
private:
[[nodiscard]] InstanceWrapper&
getRT(int m = 0, int i = 0) const;
getRT(int m = 0, int i = 0) const
{
if (!moduleWrap_)
Throw<std::runtime_error>("no module");
return moduleWrap_->getInstance(i);
}
[[nodiscard]] Wmem
getMem() const;
getMem() const
{
return moduleWrap_ ? moduleWrap_->getMem() : Wmem();
}
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
runHlp(
Bytes const& wasmCode,
HostFunctions& hfs,
@@ -319,7 +393,10 @@ private:
makeModule(Bytes const& wasmCode, WasmExternVec const& imports = {});
[[nodiscard]] FuncInfo
getFunc(std::string_view funcName) const;
getFunc(std::string_view funcName) const
{
return moduleWrap_->getFunc(funcName);
}
static std::vector<wasm_val_t>
convertParams(std::vector<WasmParam> const& params);

View File

@@ -0,0 +1,145 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/tx/wasm/CodecEnvelope.h>
#include <xrpl/tx/wasm/detail/CodecTypeCode.h>
#include <xrpl/tx/wasm/detail/CodecTypeTrait.h>
#include <array>
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
namespace xrpl::wasm::detail {
// Sentinel that lets the registry's X-macro expansion end with a trailing
// comma: CodecList<Trait0, Trait1, CodecEnd>. Its `void` CodecType never
// matches a real type, so every table builder simply skips it.
struct CodecEnd
{
using CodecType = void;
};
template <typename Trait, typename T>
inline constexpr bool traitIsV = std::is_same_v<typename Trait::CodecType, T>;
template <typename T>
using DecodeFn = Expected<T, CodecError> (*)(CodecEnvelope const&);
template <typename T>
using EncodeFn = Expected<CodecEnvelope, CodecError> (*)(T const&);
// Highest registered version of T within List. Unregistered T ⇒ build error.
template <typename T, typename List, std::size_t... I>
consteval CodecVersion
maxVersionImpl(std::index_sequence<I...>)
{
auto v = CodecVersion{};
auto found = false;
([&] {
using Trait = std::tuple_element_t<I, List>;
if constexpr (traitIsV<Trait, T>)
{
found = true;
v = std::max(v, Trait::kVersion);
}
}(), ...);
if (!found)
{
xrpl::Throw<std::runtime_error>("wasm codec: no codec registered for this type");
}
return v;
}
template <typename T, typename List>
consteval CodecVersion
maxVersion()
{
return maxVersionImpl<T, List>(
std::make_index_sequence<std::tuple_size_v<List>>{});
}
template <typename T, typename List, std::size_t... I>
consteval auto
makeDecoderTableImpl(std::index_sequence<I...>)
{
constexpr auto n = maxVersion<T, List>() + 1;
auto table = std::array<DecodeFn<T>, n>{};
([&] {
using Trait = std::tuple_element_t<I, List>;
if constexpr (traitIsV<Trait, T>)
{
table[Trait::kVersion] = &Trait::decode;
}
}(), ...);
for (const auto& entry : table)
{
if (!entry)
{
xrpl::Throw<std::runtime_error>("wasm codec: decoder versions must be contiguous from 0");
}
}
return table;
}
template <typename T, typename List>
inline constexpr auto decoderTableV = makeDecoderTableImpl<T, List>(
std::make_index_sequence<std::tuple_size_v<List>>{});
template <typename T, typename List, std::size_t... I>
consteval auto
makeEncoderTableImpl(std::index_sequence<I...>)
{
constexpr auto n = maxVersion<T, List>() + 1;
auto table = std::array<EncodeFn<T>, n>{};
([&] {
using Trait = std::tuple_element_t<I, List>;
if constexpr (traitIsV<Trait, T>)
{
table[Trait::kVersion] = &Trait::encode;
}
}(), ...);
for (const auto& entry : table)
{
if (!entry)
{
xrpl::Throw<std::runtime_error>("wasm codec: encoder versions must be contiguous from 0");
}
}
return table;
}
template <typename T, typename List>
inline constexpr auto encoderTableV = makeEncoderTableImpl<T, List>(
std::make_index_sequence<std::tuple_size_v<List>>{});
template <typename T, typename List>
Expected<T, CodecError>
decodeImpl(CodecEnvelope const& env)
{
if (env.header.type_code != codecTypeCodeV<T>)
{
return Unexpected{CodecError::TypeMismatch};
}
auto const& table = decoderTableV<T, List>;
if (env.header.version >= table.size())
{
return Unexpected{CodecError::UnsupportedVersion};
}
return table[env.header.version](env);
}
template <typename T, typename List>
Expected<CodecEnvelope, CodecError>
encodeAt(CodecVersion wireVersion, T const& value)
{
auto const& table = encoderTableV<T, List>;
if (wireVersion >= table.size())
{
return Unexpected{CodecError::UnsupportedVersion};
}
return table[wireVersion](value);
}
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,12 @@
#pragma once
#include <tuple>
namespace xrpl::wasm::detail {
template <typename... Traits>
struct CodecList {
using TupleType = std::tuple<Traits...>;
};
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,18 @@
#pragma once
#include <xrpl/basics/Expected.h>
#include <xrpl/tx/wasm/CodecEnvelope.h>
namespace xrpl::wasm::detail {
// Maps a contract's declared codec revision to the per-type wire version to
// emit for `code`. This is the revision/amendment POLICY layer, kept separate
// from both the generic dispatch machinery and the concrete value codecs.
//
// Defined in src/libxrpl/tx/wasm/codecs/CodecRevisions.cpp alongside the
// concrete CodecTrait<N> revision maps. (Amendment gating via Rules is a
// deliberate TODO there — see the .cpp.)
Expected<CodecVersion, CodecError>
wireVersionFor(CodecVersion declaredRevision, CodecTypeCode code);
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,18 @@
#pragma once
#include <xrpl/tx/wasm/CodecEnvelope.h>
namespace xrpl::wasm::detail {
template <CodecVersion Version>
struct CodecTrait;
// template <>
// struct CodecTrait<0> {
// static constexpr auto kVersion = CodecVersion{0};
// static constexpr auto versions = std::to_array<std::pair<CodecTypeCode, CodecVersion>>({
// {codecTypeCodeV<STNumber>, 0},
// });
// };
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,21 @@
#pragma once
#include <xrpl/tx/wasm/CodecEnvelope.h>
namespace xrpl::wasm::detail {
template <typename T>
struct CodecTypeCodeOf;
// Defines a type trait for registering a type code for each
// type in the codec.
template <typename T>
inline constexpr CodecTypeCode codecTypeCodeV = CodecTypeCodeOf<T>::kCodecTypeCode;
#define XRPL_WASM_CODEC_TYPE_CODE(CppType, Code) \
template <> \
struct CodecTypeCodeOf<CppType> { \
static constexpr CodecTypeCode kCodecTypeCode = Code; \
};
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,27 @@
#pragma once
#include <xrpl/tx/wasm/CodecEnvelope.h>
#include <limits>
namespace xrpl::wasm::detail {
// Defines a type trait for registering a specific type code and version
// encoding/decoding implementation for each type in the codec.
template <CodecTypeCode TypeCode, CodecVersion Version>
struct CodecTypeTrait;
#define XRPL_WASM_CODEC_TYPE_TRAIT(CppType, Version, PayloadSize) \
template <> \
struct CodecTypeTrait<codecTypeCodeV<CppType>, Version> { \
using CodecType = CppType; \
static constexpr auto kCodecTypeCode = codecTypeCodeV<CppType>; \
static constexpr auto kVersion = Version; \
static constexpr auto kPayloadSize = PayloadSize; \
static Expected<CodecType, CodecError> decode(CodecEnvelope const& env); \
static Expected<CodecEnvelope, CodecError> encode(CodecType const& value); \
};
inline constexpr auto kVariablePayloadSize = std::numeric_limits<CodecLength>::max();
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,48 @@
//
// codec_revisions.macro — the SINGLE registration point for codec
// REVISIONS (the "contract-declared codec revision -> per-type wire version"
// pinning). Included multiple times with different macro definitions, so NO
// include guard.
//
// A revision fixes, for every type, which wire version a contract that declared
// that revision receives. It is deliberately SEPARATE from the (type, version)
// registry: adding a codec version does not change any revision — bumping a
// revision is its own act, tied to the amendment that enables it.
//
// CODEC_REVISION_BEGIN(Revision)
// CODEC_REVISION_ENTRY(CppType, Version) // repeated, one per type
// CODEC_REVISION_END(Revision)
//
// HOW TO ADD A REVISION (e.g. revision 1 that emits the widened Number v1):
// 1. Add a block here:
// CODEC_REVISION_BEGIN(1)
// CODEC_REVISION_ENTRY(Number, 1) // widened
// CODEC_REVISION_ENTRY(AccountID, 0) // unchanged
// CODEC_REVISION_END(1)
// 2. Gate it behind its amendment in CodecRevisions.cpp (see the
// amendment-gating TODO in wireVersionFor).
// Both CodecTrait<1> and the wireVersionFor switch case regenerate from this.
//
#ifndef CODEC_REVISION_BEGIN
#define CODEC_REVISION_BEGIN(Revision)
#endif
#ifndef CODEC_REVISION_ENTRY
#define CODEC_REVISION_ENTRY(CppType, Version)
#endif
#ifndef CODEC_REVISION_END
#define CODEC_REVISION_END(Revision)
#endif
// clang-format off
CODEC_REVISION_BEGIN(0)
CODEC_REVISION_ENTRY(Number, 0)
CODEC_REVISION_ENTRY(AccountID, 0)
CODEC_REVISION_END(0)
// clang-format on
#undef CODEC_REVISION_BEGIN
#undef CODEC_REVISION_ENTRY
#undef CODEC_REVISION_END

View File

@@ -0,0 +1,58 @@
//
// codec_types.macro — the SINGLE registration point for wasm codecs.
//
// This file is #included multiple times with different macro definitions, so
// it has NO include guard. Every codec is declared here exactly once, on two
// axes, and everything else (the trait tuple, the dispatch tables, the
// explicit instantiations, the type-code map) is generated from it — so those
// can never drift apart.
//
// CODEC_TYPE(CppType, TypeCode)
// Once per C++ type. Assigns its stable 16-bit wire type code. Drives the
// type-code map and the per-type explicit instantiations of decode/encode.
//
// CODEC_VERSION(CppType, Version, PayloadSize)
// Once per (type, version). Declares a CodecTypeTrait specialization and
// adds it to the registered-codec tuple. Versions per type MUST be
// contiguous from 0 (enforced at compile time).
//
// HOW TO ADD A CODEC
//
// A) A new VERSION of an existing type (e.g. widen Number):
// 1. Add a line here: CODEC_VERSION(Number, 1, 20)
// 2. Define its bodies in the type's .cpp (codecs/NumberCodec.cpp):
// CodecTypeTrait<codecTypeCodeV<Number>, 1>::decode/encode
// 3. If a codec revision should emit it, add an entry in
// codec_revisions.macro.
// (Versions must stay contiguous from 0, or the build fails.)
//
// B) A brand-new TYPE (e.g. STAmount):
// 1. CODEC_TYPE(STAmount, 0x0003) and CODEC_VERSION(STAmount, 0, N) here.
// 2. Add its C++ header include to codecs/CodecTypes.h.
// 3. Create codecs/STAmountCodec.cpp with the decode/encode bodies.
// (GLOB_RECURSE picks up the new .cpp automatically — no CMake edit.)
// 4. Add a CODEC_REVISION_ENTRY(STAmount, 0) to each relevant revision
// block in codec_revisions.macro.
//
#ifndef CODEC_TYPE
#define CODEC_TYPE(CppType, TypeCode)
#endif
#ifndef CODEC_VERSION
#define CODEC_VERSION(CppType, Version, PayloadSize)
#endif
// clang-format off
// C++ type wire type code
CODEC_TYPE(Number, 0x0001)
CODEC_TYPE(AccountID, 0x0002)
// C++ type version payload bytes
CODEC_VERSION(Number, 0, 12) // int64 mantissa + int32 exponent
CODEC_VERSION(AccountID, 0, 20) // 20 raw bytes
// clang-format on
#undef CODEC_TYPE
#undef CODEC_VERSION

View File

@@ -106,6 +106,7 @@ 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(tecOUT_OF_GAS, "The WASM code ran out of gas during execution."),
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),

View File

@@ -5,8 +5,7 @@
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/PublicKey.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <cstdint>
@@ -19,10 +18,9 @@ namespace xrpl {
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::updateData(Slice const& data)
{
if (data.size() > maxWasmDataLength)
{
if (data.size() > kMaxWasmDataLength)
return Unexpected(HostFunctionError::DataFieldTooLarge);
}
data_ = Bytes(data.begin(), data.end());
return data_->size();
}

View File

@@ -6,7 +6,7 @@
#include <xrpl/protocol/Serializer.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncImpl.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <boost/algorithm/hex.hpp>

View File

@@ -1,21 +1,21 @@
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/basics/contract.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STBase.h>
#include <xrpl/protocol/STBitString.h>
#include <xrpl/protocol/STObject.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncImpl.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <string>
#include <utility>
#include <variant>
@@ -119,16 +119,14 @@ static Expected<Bytes, HostFunctionError>
getAnyFieldData(FieldValue const& variantObj)
{
if (STBase const* const* obj = std::get_if<STBase const*>(&variantObj))
{
return getAnyFieldData(*obj);
}
if (uint256 const* const* u = std::get_if<uint256 const*>(&variantObj))
{
return Bytes((*u)->begin(), (*u)->end());
}
return Unexpected(HostFunctionError::INTERNAL); // LCOV_EXCL_LINE
// Unreachable: the variant only holds the two alternatives above. If not,
// it's an xrpld bug -> tecINTERNAL (thrown, caught by HostFuncMain_wrap).
Throw<std::runtime_error>(std::string(hfErrInternal)); // LCOV_EXCL_LINE
}
static inline bool
@@ -139,33 +137,13 @@ noField(STBase const* field)
}
static Expected<FieldValue, HostFunctionError>
locateField(STObject const& obj, Slice const& locator)
locateField(STObject const& obj, FieldLocator const& locator)
{
if (locator.empty() || ((locator.size() & 3) != 0u)) // must be multiple of 4
return Unexpected(HostFunctionError::LocatorMalformed);
static_assert(maxWasmParamLength % sizeof(int32_t) == 0);
int32_t locBuf[maxWasmParamLength / sizeof(int32_t)];
int32_t const* locPtr = &locBuf[0];
int32_t const locSize = locator.size() / sizeof(int32_t);
{
uintptr_t const p = reinterpret_cast<uintptr_t>(locator.data());
if ((p & (alignof(int32_t) - 1)) != 0u)
{ // unaligned
memcpy(&locBuf[0], locator.data(), locator.size());
}
else
{
locPtr = reinterpret_cast<int32_t const*>(locator.data());
}
}
STBase const* field = nullptr;
auto const& knownSFields = SField::getKnownCodeToField();
{
int32_t const sfieldCode = adjustWasmEndianess(locPtr[0]);
int32_t const sfieldCode = adjustWasmEndianess(locator[0]);
auto const it = knownSFields.find(sfieldCode);
if (it == knownSFields.end())
return Unexpected(HostFunctionError::InvalidField);
@@ -176,9 +154,9 @@ locateField(STObject const& obj, Slice const& locator)
return Unexpected(HostFunctionError::FieldNotFound);
}
for (int i = 1; i < locSize; ++i)
for (unsigned i = 1; i < locator.size(); ++i)
{
int32_t const sfieldCode = adjustWasmEndianess(locPtr[i]);
int32_t const sfieldCode = adjustWasmEndianess(locator[i]);
if (STI_ARRAY == field->getSType())
{
@@ -290,7 +268,7 @@ WasmHostFunctionsImpl::getLedgerObjField(int32_t cacheIdx, SField const& fname)
// Subsection: nested getters
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::getTxNestedField(Slice const& locator) const
WasmHostFunctionsImpl::getTxNestedField(FieldLocator const& locator) const
{
auto const r = locateField(ctx_.tx, locator);
if (!r)
@@ -300,7 +278,7 @@ WasmHostFunctionsImpl::getTxNestedField(Slice const& locator) const
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::getCurrentLedgerObjNestedField(Slice const& locator) const
WasmHostFunctionsImpl::getCurrentLedgerObjNestedField(FieldLocator const& locator) const
{
auto const sle = getCurrentLedgerObj();
if (!sle.has_value())
@@ -314,7 +292,7 @@ WasmHostFunctionsImpl::getCurrentLedgerObjNestedField(Slice const& locator) cons
}
Expected<Bytes, HostFunctionError>
WasmHostFunctionsImpl::getLedgerObjNestedField(int32_t cacheIdx, Slice const& locator) const
WasmHostFunctionsImpl::getLedgerObjNestedField(int32_t cacheIdx, FieldLocator const& locator) const
{
auto const normalizedIdx = normalizeCacheIndex(cacheIdx);
if (!normalizedIdx.has_value())
@@ -379,7 +357,7 @@ WasmHostFunctionsImpl::getLedgerObjArrayLen(int32_t cacheIdx, SField const& fnam
// Subsection: nested array length getters
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::getTxNestedArrayLen(Slice const& locator) const
WasmHostFunctionsImpl::getTxNestedArrayLen(FieldLocator const& locator) const
{
auto const r = locateField(ctx_.tx, locator);
if (!r)
@@ -390,7 +368,7 @@ WasmHostFunctionsImpl::getTxNestedArrayLen(Slice const& locator) const
}
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::getCurrentLedgerObjNestedArrayLen(Slice const& locator) const
WasmHostFunctionsImpl::getCurrentLedgerObjNestedArrayLen(FieldLocator const& locator) const
{
auto const sle = getCurrentLedgerObj();
if (!sle.has_value())
@@ -404,7 +382,8 @@ WasmHostFunctionsImpl::getCurrentLedgerObjNestedArrayLen(Slice const& locator) c
}
Expected<int32_t, HostFunctionError>
WasmHostFunctionsImpl::getLedgerObjNestedArrayLen(int32_t cacheIdx, Slice const& locator) const
WasmHostFunctionsImpl::getLedgerObjNestedArrayLen(int32_t cacheIdx, FieldLocator const& locator)
const
{
auto const normalizedIdx = normalizeCacheIndex(cacheIdx);
if (!normalizedIdx.has_value())

View File

@@ -6,9 +6,8 @@
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/UintTypes.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncImpl.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <cstdint>

View File

@@ -1,9 +1,8 @@
#include <xrpl/basics/Expected.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/AmendmentTable.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncImpl.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <cstdint>
#include <string>

View File

@@ -5,9 +5,8 @@
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/nft.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/HostFuncImpl.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <cstdint>

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,8 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/tx/wasm/HostFuncWrapper.h> // IWYU pragma: keep
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <xrpl/tx/wasm/WasmImportsHelper.h>
#include <cstdint>
#include <string>
@@ -27,79 +28,79 @@ namespace xrpl {
// See XLS-0102 §6.5 (Future-Proofing):
// https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-0102-wasm-vm#65-future-proofing
static void
setCommonHostFunctions(HostFunctions* hfs, ImportVec& i)
setCommonHostFunctions(HostFunctions& hfs, ImportVec& i)
{
// clang-format off
WASM_IMPORT_FUNC2(i, getLedgerSqn, "get_ledger_sqn", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerTime, "get_parent_ledger_time", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerHash, "get_parent_ledger_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getBaseFee, "get_base_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, isAmendmentEnabled, "amendment_enabled", hfs, 100);
WASM_IMPORT_FUNC2(i, getLedgerSqn, "ldgr_index", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerTime, "parent_ldgr_time", hfs, 60);
WASM_IMPORT_FUNC2(i, getParentLedgerHash, "parent_ldgr_hash", hfs, 60);
WASM_IMPORT_FUNC2(i, getBaseFee, "base_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, isAmendmentEnabled, "amendment_enabled", hfs, 100);
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_ledger_obj", hfs, 5'000);
WASM_IMPORT_FUNC2(i, getTxField, "get_tx_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjField, "get_current_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjField, "get_ledger_obj_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getTxNestedField, "get_tx_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedField, "get_current_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedField, "get_ledger_obj_nested_field", hfs, 110);
WASM_IMPORT_FUNC2(i, getTxArrayLen, "get_tx_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjArrayLen, "get_current_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getLedgerObjArrayLen, "get_ledger_obj_array_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getTxNestedArrayLen, "get_tx_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedArrayLen, "get_current_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedArrayLen, "get_ledger_obj_nested_array_len", hfs, 70);
WASM_IMPORT_FUNC2(i, cacheLedgerObj, "cache_le", hfs, 5'000);
WASM_IMPORT_FUNC2(i, getTxField, "tx_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjField, "home_le_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjField, "le_field", hfs, 70);
WASM_IMPORT_FUNC2(i, getTxNestedField, "tx_inner", hfs, 110);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedField, "home_le_inner", hfs, 110);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedField, "le_inner", hfs, 110);
WASM_IMPORT_FUNC2(i, getTxArrayLen, "tx_arr_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjArrayLen, "home_le_arr_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getLedgerObjArrayLen, "le_arr_len", hfs, 40);
WASM_IMPORT_FUNC2(i, getTxNestedArrayLen, "tx_inner_arr_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getCurrentLedgerObjNestedArrayLen, "home_le_inner_arr_len", hfs, 70);
WASM_IMPORT_FUNC2(i, getLedgerObjNestedArrayLen, "le_inner_arr_len", hfs, 70);
WASM_IMPORT_FUNC2(i, checkSignature, "check_sig", hfs, 300);
WASM_IMPORT_FUNC2(i, computeSha512HalfHash, "compute_sha512_half", hfs, 2000);
WASM_IMPORT_FUNC2(i, checkSignature, "check_sig", hfs, 300);
WASM_IMPORT_FUNC2(i, computeSha512HalfHash, "sha512_half", hfs, 2000);
WASM_IMPORT_FUNC2(i, accountKeylet, "account_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, ammKeylet, "amm_keylet", hfs, 450);
WASM_IMPORT_FUNC2(i, checkKeylet, "check_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, credentialKeylet, "credential_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, delegateKeylet, "delegate_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, depositPreauthKeylet, "deposit_preauth_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, didKeylet, "did_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, escrowKeylet, "escrow_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, lineKeylet, "line_keylet", hfs, 400);
WASM_IMPORT_FUNC2(i, mptIssuanceKeylet, "mpt_issuance_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, mptokenKeylet, "mptoken_keylet", hfs, 500);
WASM_IMPORT_FUNC2(i, nftOfferKeylet, "nft_offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, offerKeylet, "offer_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, oracleKeylet, "oracle_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, paychanKeylet, "paychan_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, permissionedDomainKeylet, "permissioned_domain_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, signersKeylet, "signers_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, ticketKeylet, "ticket_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, vaultKeylet, "vault_keylet", hfs, 350);
WASM_IMPORT_FUNC2(i, accountKeylet, "accountroot_id", hfs, 350);
WASM_IMPORT_FUNC2(i, ammKeylet, "amm_id", hfs, 450);
WASM_IMPORT_FUNC2(i, checkKeylet, "check_id", hfs, 350);
WASM_IMPORT_FUNC2(i, credentialKeylet, "credential_id", hfs, 350);
WASM_IMPORT_FUNC2(i, delegateKeylet, "delegate_id", hfs, 350);
WASM_IMPORT_FUNC2(i, depositPreauthKeylet, "deposit_preauth_id", hfs, 350);
WASM_IMPORT_FUNC2(i, didKeylet, "did_id", hfs, 350);
WASM_IMPORT_FUNC2(i, escrowKeylet, "escrow_id", hfs, 350);
WASM_IMPORT_FUNC2(i, lineKeylet, "trustline_id", hfs, 400);
WASM_IMPORT_FUNC2(i, mptIssuanceKeylet, "mpt_issuance_id", hfs, 350);
WASM_IMPORT_FUNC2(i, mptokenKeylet, "mptoken_id", hfs, 500);
WASM_IMPORT_FUNC2(i, nftOfferKeylet, "nft_offer_id", hfs, 350);
WASM_IMPORT_FUNC2(i, offerKeylet, "offer_id", hfs, 350);
WASM_IMPORT_FUNC2(i, oracleKeylet, "oracle_id", hfs, 350);
WASM_IMPORT_FUNC2(i, paychanKeylet, "paychan_id", hfs, 350);
WASM_IMPORT_FUNC2(i, permissionedDomainKeylet, "permissioned_domain_id", hfs, 350);
WASM_IMPORT_FUNC2(i, signersKeylet, "signers_id", hfs, 350);
WASM_IMPORT_FUNC2(i, ticketKeylet, "ticket_id", hfs, 350);
WASM_IMPORT_FUNC2(i, vaultKeylet, "vault_id", hfs, 350);
WASM_IMPORT_FUNC2(i, getNFT, "get_nft", hfs, 5'000);
WASM_IMPORT_FUNC2(i, getNFTIssuer, "get_nft_issuer", hfs, 70);
WASM_IMPORT_FUNC2(i, getNFTTaxon, "get_nft_taxon", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTFlags, "get_nft_flags", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTransferFee, "get_nft_transfer_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTSerial, "get_nft_serial", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFT, "nft_uri", hfs, 5'000);
WASM_IMPORT_FUNC2(i, getNFTIssuer, "nft_issuer", hfs, 70);
WASM_IMPORT_FUNC2(i, getNFTTaxon, "nft_taxon", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTFlags, "nft_flags", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTTransferFee, "nft_xfer_fee", hfs, 60);
WASM_IMPORT_FUNC2(i, getNFTSerial, "nft_serial", hfs, 60);
WASM_IMPORT_FUNC (i, trace, hfs, 500);
WASM_IMPORT_FUNC2(i, traceNum, "trace_num", hfs, 500);
WASM_IMPORT_FUNC2(i, traceAccount, "trace_account", hfs, 500);
WASM_IMPORT_FUNC2(i, traceFloat, "trace_opaque_float", hfs, 500);
WASM_IMPORT_FUNC2(i, traceAmount, "trace_amount", hfs, 500);
WASM_IMPORT_FUNC (i, trace, hfs, 500);
WASM_IMPORT_FUNC2(i, traceNum, "trace_num", hfs, 500);
WASM_IMPORT_FUNC2(i, traceAccount, "trace_acct", hfs, 500);
WASM_IMPORT_FUNC2(i, traceFloat, "trace_xfloat", hfs, 500);
WASM_IMPORT_FUNC2(i, traceAmount, "trace_amt", hfs, 500);
WASM_IMPORT_FUNC2(i, floatFromInt, "float_from_int", hfs, 100);
WASM_IMPORT_FUNC2(i, floatFromUint, "float_from_uint", hfs, 130);
WASM_IMPORT_FUNC2(i, floatFromSTAmount, "float_from_stamount", hfs, 150);
WASM_IMPORT_FUNC2(i, floatFromSTNumber, "float_from_stnumber", hfs, 150);
WASM_IMPORT_FUNC2(i, floatToInt, "float_to_int", hfs, 130);
WASM_IMPORT_FUNC2(i, floatToMantExp, "float_to_mant_exp", hfs, 130);
WASM_IMPORT_FUNC2(i, floatFromMantExp, "float_from_mant_exp", hfs, 100);
WASM_IMPORT_FUNC2(i, floatCompare, "float_compare", hfs, 80);
WASM_IMPORT_FUNC2(i, floatAdd, "float_add", hfs, 160);
WASM_IMPORT_FUNC2(i, floatSubtract, "float_subtract", hfs, 160);
WASM_IMPORT_FUNC2(i, floatMultiply, "float_multiply", hfs, 300);
WASM_IMPORT_FUNC2(i, floatDivide, "float_divide", hfs, 300);
WASM_IMPORT_FUNC2(i, floatRoot, "float_root", hfs, 5'500);
WASM_IMPORT_FUNC2(i, floatPower, "float_pow", hfs, 5'500);
WASM_IMPORT_FUNC2(i, floatFromInt, "float_from_int", hfs, 100);
WASM_IMPORT_FUNC2(i, floatFromUint, "float_from_uint", hfs, 130);
WASM_IMPORT_FUNC2(i, floatFromSTAmount, "float_from_stamount", hfs, 150);
WASM_IMPORT_FUNC2(i, floatFromSTNumber, "float_from_stnumber", hfs, 150);
WASM_IMPORT_FUNC2(i, floatToInt, "float_to_int", hfs, 130);
WASM_IMPORT_FUNC2(i, floatToMantExp, "float_to_mant_exp", hfs, 130);
WASM_IMPORT_FUNC2(i, floatFromMantExp, "float_from_mant_exp", hfs, 100);
WASM_IMPORT_FUNC2(i, floatCompare, "float_cmp", hfs, 80);
WASM_IMPORT_FUNC2(i, floatAdd, "float_add", hfs, 160);
WASM_IMPORT_FUNC2(i, floatSubtract, "float_sub", hfs, 160);
WASM_IMPORT_FUNC2(i, floatMultiply, "float_mult", hfs, 300);
WASM_IMPORT_FUNC2(i, floatDivide, "float_div", hfs, 300);
WASM_IMPORT_FUNC2(i, floatRoot, "float_root", hfs, 5'500);
WASM_IMPORT_FUNC2(i, floatPower, "float_pow", hfs, 5'500);
// clang-format on
}
@@ -108,13 +109,13 @@ createWasmImport(HostFunctions& hfs)
{
ImportVec i;
setCommonHostFunctions(&hfs, i);
WASM_IMPORT_FUNC2(i, updateData, "update_data", &hfs, 1000);
setCommonHostFunctions(hfs, i);
WASM_IMPORT_FUNC2(i, updateData, "set_data", hfs, 1000);
return i;
}
Expected<EscrowResult, TER>
Expected<EscrowResult, WasmTER>
runEscrowWasm(
Bytes const& wasmCode,
HostFunctions& hfs,
@@ -132,15 +133,18 @@ runEscrowWasm(
if (!ret)
{
#ifdef DEBUG_OUTPUT
std::cout << ", error: " << ret.error() << std::endl;
std::cout << ", error: " << ret.error().ter << std::endl;
#endif
return Unexpected<TER>(ret.error());
// Carries the TER (tecOUT_OF_GAS / tecFAILED_PROCESSING / tecINTERNAL /
// temBAD_AMOUNT) and, when meaningful, the gas consumed. The caller is
// responsible for writing that gas to tx metadata.
return Unexpected(ret.error());
}
#ifdef DEBUG_OUTPUT
std::cout << ", ret: " << ret->result << ", gas spent: " << ret->cost << std::endl;
#endif
return EscrowResult{ret->result, ret->cost};
return EscrowResult{.result = ret->result, .cost = ret->cost};
}
NotTEC
@@ -173,7 +177,7 @@ WasmEngine::instance()
return e;
}
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
WasmEngine::run(
Bytes const& wasmCode,
HostFunctions& hfs,

View File

@@ -5,7 +5,8 @@
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/tx/wasm/HostFunc.h>
#include <xrpl/tx/wasm/ParamsHelper.h>
#include <xrpl/tx/wasm/WasmCommon.h>
#include <xrpl/tx/wasm/WasmImportsHelper.h>
#include <xrpl/tx/wasm/WasmVM.h>
#include <wasmi/config.h>
@@ -21,6 +22,7 @@
#include <limits>
#include <memory>
#include <mutex>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
@@ -34,6 +36,9 @@
namespace xrpl {
wasm_trap_t*
HostFuncMain_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
namespace {
void
@@ -74,32 +79,65 @@ printWasmError(std::string_view msg, wasm_trap_t* trap, beast::Journal jlog)
}
// LCOV_EXCL_STOP
// Extract a trap's message into a std::string (the only signal the C API gives
// for classification; see the trap-signal constants in WasmCommon.h). Does not
// take ownership of `trap`.
std::string
trapMessage(wasm_trap_t* trap)
{
if (trap == nullptr)
return {}; // LCOV_EXCL_LINE
wasm_byte_vec_t msg WASM_EMPTY_VEC;
wasm_trap_message(trap, &msg);
std::string out;
if (msg.size != 0u)
{
// wasm_trap_message NUL-terminates, so drop the trailing NUL.
out.assign(msg.data, msg.size - 1);
wasm_byte_vec_delete(&msg);
}
return out;
}
} // namespace
struct WasmiRuntimeWrapper : public WasmRuntimeWrapper
class WasmiRuntimeWrapper : public WasmRuntimeWrapper
{
InstanceWrapper& iw;
InstanceWrapper& iw_;
WasmiRuntimeWrapper(InstanceWrapper& iw) : iw(iw)
public:
WasmiRuntimeWrapper(InstanceWrapper& iw) : iw_(iw)
{
}
Wmem
getMem() override
{
return iw.getMem();
return iw_.getMem();
}
std::int64_t
getGas() override
{
return iw.getGas();
return iw_.getGas();
}
std::int64_t
setGas(std::int64_t gas) override
{
return iw.setGas(gas);
return iw_.setGas(gas);
}
std::int64_t
getTransferLimit() override
{
return iw_.getTransferLimit();
}
std::int64_t
setTransferLimit(std::int64_t x) override
{
return iw_.setTransferLimit(x);
}
};
@@ -118,69 +156,43 @@ InstanceWrapper::init(
if (!mi || (trap != nullptr))
{
printWasmError("can't create instance", trap, j);
throw std::runtime_error("can't create instance");
Throw<std::runtime_error>("can't create instance");
}
wasm_instance_exports(mi.get(), expt.get());
return mi;
}
InstanceWrapper::InstanceWrapper() : instance(nullptr, &wasm_instance_delete)
{
}
// LCOV_EXCL_START
InstanceWrapper::InstanceWrapper(InstanceWrapper&& o) : instance(nullptr, &wasm_instance_delete)
{
*this = std::move(o);
}
// LCOV_EXCL_STOP
InstanceWrapper::InstanceWrapper(
StorePtr& s,
ModulePtr& m,
WasmExternVec const& imports,
beast::Journal j)
: store(s.get()), instance(init(s, m, exports, imports, j)), j(j)
{
}
InstanceWrapper&
InstanceWrapper::operator=(InstanceWrapper&& o)
{
if (this == &o)
return *this; // LCOV_EXCL_LINE
store = o.store;
o.store = nullptr;
exports = std::move(o.exports);
memIdx = o.memIdx;
o.memIdx = -1;
instance = std::move(o.instance);
store_ = o.store_;
o.store_ = nullptr;
exports_ = std::move(o.exports_);
memIdx_ = o.memIdx_;
o.memIdx_ = -1;
instance_ = std::move(o.instance_);
j = o.j;
j_ = o.j_;
return *this;
}
InstanceWrapper::
operator bool() const
{
return static_cast<bool>(instance);
}
FuncInfo
InstanceWrapper::getFunc(std::string_view funcName, WasmExporttypeVec const& exportTypes) const
{
wasm_func_t const* f = nullptr;
wasm_functype_t const* ft = nullptr;
if (!instance)
throw std::runtime_error("no instance"); // LCOV_EXCL_LINE
if (!instance_)
Throw<std::runtime_error>("no instance"); // LCOV_EXCL_LINE
if (exportTypes.empty())
throw std::runtime_error("no export"); // LCOV_EXCL_LINE
if (exportTypes.size() != exports.size())
throw std::runtime_error("invalid export"); // LCOV_EXCL_LINE
Throw<std::runtime_error>("no export"); // LCOV_EXCL_LINE
if (exportTypes.size() != exports_.size())
Throw<std::runtime_error>("invalid export"); // LCOV_EXCL_LINE
for (unsigned i = 0; i < exportTypes.size(); ++i)
{
@@ -193,9 +205,9 @@ InstanceWrapper::getFunc(std::string_view funcName, WasmExporttypeVec const& exp
if (funcName != std::string_view(name->data, name->size))
continue;
auto const* exn(exports[i]);
auto const* exn(exports_[i]);
if (wasm_extern_kind(exn) != WASM_EXTERN_FUNC)
throw std::runtime_error("invalid export"); // LCOV_EXCL_LINE
Throw<std::runtime_error>("invalid export"); // LCOV_EXCL_LINE
ft = wasm_externtype_as_functype_const(exnType);
f = wasm_extern_as_func_const(exn);
@@ -204,7 +216,7 @@ InstanceWrapper::getFunc(std::string_view funcName, WasmExporttypeVec const& exp
}
if ((f == nullptr) || (ft == nullptr))
throw std::runtime_error("can't find function <" + std::string(funcName) + ">");
Throw<std::runtime_error>("can't find function <" + std::string(funcName) + ">");
return {f, ft};
}
@@ -212,22 +224,20 @@ InstanceWrapper::getFunc(std::string_view funcName, WasmExporttypeVec const& exp
Wmem
InstanceWrapper::getMem() const
{
if (memIdx >= 0)
if (memIdx_ >= 0)
{
auto* e(exports[memIdx]);
auto* e(exports_[memIdx_]);
wasm_memory_t* mem = wasm_extern_as_memory(e);
return {
.p = reinterpret_cast<std::uint8_t*>(wasm_memory_data(mem)),
.s = wasm_memory_data_size(mem)};
return Wmem(wasm_memory_data(mem), wasm_memory_data_size(mem));
}
wasm_memory_t* mem = nullptr;
for (int i = 0; i < exports.size(); ++i)
for (int i = 0; i < exports_.size(); ++i)
{
auto* e(exports[i]);
auto* e(exports_[i]);
if (wasm_extern_kind(e) == WASM_EXTERN_MEMORY)
{
memIdx = i;
memIdx_ = i;
mem = wasm_extern_as_memory(e);
break;
}
@@ -236,34 +246,32 @@ InstanceWrapper::getMem() const
if (mem == nullptr)
return {}; // LCOV_EXCL_LINE
return {
.p = reinterpret_cast<std::uint8_t*>(wasm_memory_data(mem)),
.s = wasm_memory_data_size(mem)};
return Wmem(wasm_memory_data(mem), wasm_memory_data_size(mem));
}
std::int64_t
InstanceWrapper::getGas() const
{
if (store == nullptr)
if (store_ == nullptr)
return -1; // LCOV_EXCL_LINE
std::uint64_t gas = 0;
wasm_store_get_fuel(store, &gas);
wasm_store_get_fuel(store_, &gas);
return static_cast<std::int64_t>(gas);
}
std::int64_t
InstanceWrapper::setGas(std::int64_t gas) const
{
if (store == nullptr)
if (store_ == nullptr)
return -1; // LCOV_EXCL_LINE
if (gas < 0)
gas = std::numeric_limits<decltype(gas)>::max();
wasmi_error_t* err = wasm_store_set_fuel(store, static_cast<std::uint64_t>(gas));
wasmi_error_t* err = wasm_store_set_fuel(store_, static_cast<std::uint64_t>(gas));
if (err != nullptr)
{
// LCOV_EXCL_START
printWasmError("Can't set instance gas", nullptr, j);
printWasmError("Can't set instance gas", nullptr, j_);
wasmi_error_delete(err);
return -1;
// LCOV_EXCL_STOP
@@ -272,12 +280,38 @@ InstanceWrapper::setGas(std::int64_t gas) const
return gas;
}
std::int64_t
InstanceWrapper::getTransferLimit() const
{
if (store_ == nullptr)
return -1; // LCOV_EXCL_LINE
return transferLimit_;
}
std::int64_t
InstanceWrapper::setTransferLimit(std::int64_t x)
{
if (store_ == nullptr)
return -1; // LCOV_EXCL_LINE
if (x < 0)
{
transferLimit_ = std::numeric_limits<decltype(transferLimit_)>::max();
}
else
{
transferLimit_ = x;
}
return transferLimit_;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
ModulePtr
ModuleWrapper::init(StorePtr& s, Bytes const& wasmBin, beast::Journal j)
{
wasm_byte_vec_t const code{wasmBin.size(), (char*)(wasmBin.data())};
wasm_byte_vec_t const code{.size = wasmBin.size(), .data = (char*)(wasmBin.data())};
ModulePtr m = ModulePtr(wasm_module_new(s.get(), &code), &wasm_module_delete);
if (!m)
throw std::runtime_error("can't create module");
@@ -285,26 +319,15 @@ ModuleWrapper::init(StorePtr& s, Bytes const& wasmBin, beast::Journal j)
return m;
}
// LCOV_EXCL_START
ModuleWrapper::ModuleWrapper() : module(nullptr, &wasm_module_delete)
{
}
ModuleWrapper::ModuleWrapper(ModuleWrapper&& o) : module(nullptr, &wasm_module_delete)
{
*this = std::move(o);
}
// LCOV_EXCL_STOP
ModuleWrapper::ModuleWrapper(
StorePtr& s,
Bytes const& wasmBin,
bool instantiate,
ImportVec const& imports,
beast::Journal j)
: module(init(s, wasmBin, j)), j(j)
: module_(init(s, wasmBin, j)), j_(j)
{
wasm_module_exports(module.get(), exportTypes.get());
wasm_module_exports(module_.get(), exportTypes_.get());
auto wimports = buildImports(s, imports);
if (instantiate)
{
@@ -319,20 +342,14 @@ ModuleWrapper::operator=(ModuleWrapper&& o)
if (this == &o)
return *this;
module = std::move(o.module);
instanceWrap = std::move(o.instanceWrap);
exportTypes = std::move(o.exportTypes);
j = o.j;
module_ = std::move(o.module_);
instanceWrap_ = std::move(o.instanceWrap_);
exportTypes_ = std::move(o.exportTypes_);
j_ = o.j_;
return *this;
}
ModuleWrapper::
operator bool() const
{
return instanceWrap;
}
// LCOV_EXCL_STOP
static WasmValtypeVec
@@ -391,7 +408,7 @@ WasmExternVec
ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) const
{
WasmImporttypeVec importTypes;
wasm_module_imports(module.get(), importTypes.get());
wasm_module_imports(module_.get(), importTypes.get());
if (importTypes.empty())
return {};
@@ -424,12 +441,12 @@ ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) const
auto const it = imports.find(fieldName);
if (it == imports.end())
{
printWasmError("Import not found: " + std::string(fieldName), nullptr, j);
printWasmError("Import not found: " + std::string(fieldName), nullptr, j_);
continue; // print all missed import
}
auto const& obj = it->second;
auto const& imp = obj.second;
WasmUserData const& obj = it->second;
WasmImportFunc const& imp = obj.second;
WasmValtypeVec params(makeImpParams(imp));
WasmValtypeVec results(makeImpReturn(imp));
@@ -440,12 +457,8 @@ ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) const
params.release();
results.release();
wasm_func_t* func = wasm_func_new_with_env(
s.get(),
ftype.get(),
reinterpret_cast<wasm_func_callback_with_env_t>(imp.wrap),
(void*)&obj,
nullptr);
wasm_func_t* func =
wasm_func_new_with_env(s.get(), ftype.get(), HostFuncMain_wrap, (void*)&obj, nullptr);
if (func == nullptr)
{
Throw<std::runtime_error>(
@@ -462,25 +475,19 @@ ModuleWrapper::buildImports(StorePtr& s, ImportVec const& imports) const
std::string("Imports not finished: ") + std::to_string(impCnt) + "/" +
std::to_string(importTypes.size()),
nullptr,
j);
j_);
Throw<std::runtime_error>("Missing imports");
}
return wimports;
}
FuncInfo
ModuleWrapper::getFunc(std::string_view funcName) const
{
return instanceWrap.getFunc(funcName, exportTypes);
}
wasm_functype_t*
ModuleWrapper::getFuncType(std::string_view funcName) const
{
for (size_t i = 0; i < exportTypes.size(); i++)
for (size_t i = 0; i < exportTypes_.size(); i++)
{
auto const* expType(exportTypes[i]);
auto const* expType(exportTypes_[i]);
wasm_name_t const* name = wasm_exporttype_name(expType);
wasm_externtype_t const* exnType = wasm_exporttype_type(expType);
if (wasm_externtype_kind(exnType) == WASM_EXTERN_FUNC &&
@@ -493,25 +500,6 @@ ModuleWrapper::getFuncType(std::string_view funcName) const
throw std::runtime_error("can't find function <" + std::string(funcName) + ">");
}
Wmem
ModuleWrapper::getMem() const
{
return instanceWrap.getMem();
}
InstanceWrapper&
ModuleWrapper::getInstance(int)
{
return instanceWrap;
}
int
ModuleWrapper::addInstance(StorePtr& s, WasmExternVec const& imports)
{
instanceWrap = {s, module, imports, j};
return 0;
}
// int
// my_module_t::delInstance(int i)
// {
@@ -522,12 +510,6 @@ ModuleWrapper::addInstance(StorePtr& s, WasmExternVec const& imports)
// return i;
// }
std::int64_t
ModuleWrapper::getGas() const
{
return instanceWrap ? instanceWrap.getGas() : -1;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// void
@@ -567,10 +549,6 @@ WasmiEngine::init()
wasm_engine_new_with_config(config), &wasm_engine_delete);
}
WasmiEngine::WasmiEngine() : engine_(init()), store_(nullptr, &wasm_store_delete)
{
}
int
WasmiEngine::addModule(
Bytes const& wasmCode,
@@ -608,12 +586,6 @@ WasmiEngine::addModule(
// return module->addInstance(store.get());
// }
FuncInfo
WasmiEngine::getFunc(std::string_view funcName) const
{
return moduleWrap_->getFunc(funcName);
}
std::vector<wasm_val_t>
WasmiEngine::convertParams(std::vector<WasmParam> const& params)
{
@@ -711,8 +683,8 @@ WasmiResult
WasmiEngine::call(FuncInfo const& f, std::vector<wasm_val_t>& in)
{
WasmiResult ret(NR);
wasm_val_vec_t const inv =
in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC : wasm_val_vec_t{in.size(), in.data()};
wasm_val_vec_t const inv = in.empty() ? wasm_val_vec_t WASM_EMPTY_VEC
: wasm_val_vec_t{.size = in.size(), .data = in.data()};
#ifdef SHOW_CALL_TIME
auto const start = usecs();
@@ -728,7 +700,24 @@ WasmiEngine::call(FuncInfo const& f, std::vector<wasm_val_t>& in)
if (trap)
{
ret.f = true;
// Classify the trap into a TER by matching tokens as substrings of the
// message (see the trap-signal constants in WasmCommon.h for why).
std::string const msg = trapMessage(trap);
auto const has = [&msg](std::string_view token) {
return msg.find(token) != std::string::npos;
};
if (has(hfErrInternal))
{
ret.ter = tecINTERNAL;
}
else if (has(hfErrOutOfGas) || has(wasmiTrapOutOfFuel))
{
ret.ter = tecOUT_OF_GAS;
}
else
{
ret.ter = tecFAILED_PROCESSING;
}
printWasmError("failure to call func", trap, j_);
}
@@ -763,12 +752,12 @@ checkImports(ImportVec const& imports, HostFunctions* hfs)
{
for (auto const& obj : imports)
{
if (hfs != obj.second.first)
if (hfs != &obj.second.first.get())
Throw<std::runtime_error>("Imports hf unsync");
}
}
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
WasmiEngine::run(
Bytes const& wasmCode,
HostFunctions& hfs,
@@ -779,7 +768,7 @@ WasmiEngine::run(
beast::Journal j)
{
if (gas <= 0)
return Unexpected<TER>(temBAD_AMOUNT);
return Unexpected(WasmTER{.ter = temBAD_AMOUNT, .cost = std::nullopt});
try
{
@@ -796,10 +785,12 @@ WasmiEngine::run(
printWasmError(std::string("exception: unknown"), nullptr, j);
}
// LCOV_EXCL_STOP
return Unexpected<TER>(tecFAILED_PROCESSING);
// An exception escaping the engine is an xrpld-side fault -> tecINTERNAL,
// no gas. Genuine wasm faults don't throw; they surface as traps in runHlp.
return Unexpected(WasmTER{.ter = tecINTERNAL, .cost = std::nullopt});
}
Expected<WasmResult<int32_t>, TER>
Expected<WasmResult<int32_t>, WasmTER>
WasmiEngine::runHlp(
Bytes const& wasmCode,
HostFunctions& hfs,
@@ -821,13 +812,13 @@ WasmiEngine::runHlp(
// Create and instantiate the module.
[[maybe_unused]] int const m = addModule(wasmCode, true, imports, gas);
if (!moduleWrap_ || !moduleWrap_->instanceWrap)
if (!moduleWrap_ || !moduleWrap_->getInstance())
throw std::runtime_error("no instance"); // LCOV_EXCL_LINE
auto clear = [](HostFunctions* p) { p->setRT(nullptr); };
std::unique_ptr<HostFunctions, decltype(clear)> const clearGuard(&hfs, clear);
auto clearRT = [](HostFunctions* p) { p->resetRT(); };
std::unique_ptr<HostFunctions, decltype(clearRT)> const clearGuard(&hfs, clearRT);
WasmiRuntimeWrapper iw(getRT());
hfs.setRT(&iw);
hfs.setRT(iw);
// Call main
auto const f = getFunc(!funcName.empty() ? funcName : "_start");
@@ -842,26 +833,38 @@ WasmiEngine::runHlp(
auto const res = call<1>(f, p);
if (res.f)
if (gas == -1)
gas = std::numeric_limits<decltype(gas)>::max();
if (res.ter.has_value())
{
throw std::runtime_error("<" + std::string(funcName) + "> failure");
// call() already classified the trap (see WasmiEngine::call).
// tecINTERNAL is an xrpld-side bug: report no gas.
if (*res.ter == tecINTERNAL)
return Unexpected(WasmTER{.ter = tecINTERNAL, .cost = std::nullopt});
// Out-of-gas / wasm faults report gas (caller writes it to metadata).
// Force fuel to 0 on out-of-gas so cost is the full limit (wasmi leaves
// nonzero leftover fuel on its own out-of-fuel trap).
if (*res.ter == tecOUT_OF_GAS)
iw.setGas(0);
return Unexpected(WasmTER{.ter = *res.ter, .cost = gas - moduleWrap_->getGas()});
}
if (res.r.empty())
{
throw std::runtime_error(
Throw<std::runtime_error>(
"<" + std::string(funcName) + "> return nothing"); // LCOV_EXCL_LINE
}
if (res.r[0].kind != WASM_I32)
{
throw std::runtime_error(
Throw<std::runtime_error>(
"<" + std::string(funcName) +
"> return type mismatch, ret: " + std::to_string(static_cast<int>(res.r[0].kind)));
}
if (gas == -1)
gas = std::numeric_limits<decltype(gas)>::max();
WasmResult<int32_t> const ret{.result = res.r[0].of.i32, .cost = gas - moduleWrap_->getGas()};
// #ifdef DEBUG_OUTPUT
@@ -934,33 +937,11 @@ WasmiEngine::checkHlp(
return tesSUCCESS;
}
// LCOV_EXCL_START
std::int64_t
WasmiEngine::getGas() const
{
return moduleWrap_ ? moduleWrap_->getGas() : -1;
}
// LCOV_EXCL_STOP
Wmem
WasmiEngine::getMem() const
{
return moduleWrap_ ? moduleWrap_->getMem() : Wmem();
}
InstanceWrapper&
WasmiEngine::getRT(int m, int i) const
{
if (!moduleWrap_)
throw std::runtime_error("no module");
return moduleWrap_->getInstance(i);
}
wasm_trap_t*
WasmiEngine::newTrap(std::string const& txt)
{
static char empty[1] = {0};
wasm_message_t msg = {1, empty};
wasm_message_t msg = {.size = 1, .data = empty};
if (!txt.empty())
wasm_name_new(&msg, txt.size() + 1, txt.c_str()); // include 0
@@ -973,12 +954,4 @@ WasmiEngine::newTrap(std::string const& txt)
return trap;
}
// LCOV_EXCL_START
beast::Journal
WasmiEngine::getJournal() const
{
return j_;
}
// LCOV_EXCL_STOP
} // namespace xrpl

View File

@@ -0,0 +1,38 @@
#include "CodecTypes.h"
#include <cstring>
// ───────────────────────────────────────────────────────────────────────────
// Codec bodies for AccountID. One decode/encode pair per registered version.
// ───────────────────────────────────────────────────────────────────────────
namespace xrpl::wasm::detail {
// ── AccountID, version 0 : 20 raw bytes ─────────────────────────────────────
template <>
Expected<AccountID, CodecError>
CodecTypeTrait<codecTypeCodeV<AccountID>, 0>::decode(CodecEnvelope const& env)
{
if (env.header.payload_size != kPayloadSize)
{
return Unexpected{CodecError::Truncated};
}
auto id = AccountID{};
std::memcpy(id.data(), env.payload, id.size());
return id;
}
template <>
Expected<CodecEnvelope, CodecError>
CodecTypeTrait<codecTypeCodeV<AccountID>, 0>::encode(AccountID const& value)
{
// AccountID is fixed-width, so it always fits v0 (no NotRepresentable path).
// TODO(payload-ownership): payload bytes (value.data(), value.size()) must
// be owned by the wire layer; deferred per the current encode signature.
(void)value;
return CodecEnvelope{.header={.type_code=kCodecTypeCode, .version=kVersion, .payload_size=kPayloadSize}, .payload=nullptr};
}
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,60 @@
#include <xrpl/tx/wasm/Codec.h>
#include <xrpl/tx/wasm/detail/CodecDispatch.h>
#include <xrpl/tx/wasm/detail/CodecList.h>
#include <xrpl/tx/wasm/detail/CodecRevisions.h>
#include "CodecTypes.h"
//
// The registry translation unit. This is the ONE place that:
// * assembles the complete registered-codec tuple from the .def, and
// * explicitly instantiates decode<T>/encode<T> for every registered type.
//
// Because the definitions live here (not in the public header), callers get the
// codec machinery out of their compiles, and an unregistered decode<T>/encode<T>
// fails at link time rather than with a template error.
//
namespace xrpl::wasm {
namespace {
// The single enumeration of every registered codec, built straight from the
// .def. The trailing detail::CodecEnd absorbs the final comma of the expansion.
using RegisteredCodecs = detail::CodecList<
#define CODEC_VERSION(CppType, Version, PayloadSize) \
detail::CodecTypeTrait<detail::codecTypeCodeV<CppType>, Version>,
#include <xrpl/tx/wasm/detail/codec_types.macro>
detail::CodecEnd>::TupleType;
} // namespace
template <typename T>
Expected<T, CodecError>
decode(CodecEnvelope const& env)
{
return detail::decodeImpl<T, RegisteredCodecs>(env);
}
template <typename T>
Expected<CodecEnvelope, CodecError>
encode(CodecVersion declaredRevision, T const& value)
{
auto const wire =
detail::wireVersionFor(declaredRevision, detail::codecTypeCodeV<T>);
if (!wire)
{
return Unexpected{wire.error()};
}
return detail::encodeAt<T, RegisteredCodecs>(*wire, value);
}
// Explicit instantiation for every registered type — the closed set.
#define CODEC_TYPE(CppType, TypeCode) \
template Expected<CppType, CodecError> decode<CppType>( \
CodecEnvelope const&); \
template Expected<CodecEnvelope, CodecError> encode<CppType>( \
CodecVersion, CppType const&);
#include <xrpl/tx/wasm/detail/codec_types.macro>
} // namespace xrpl::wasm

View File

@@ -0,0 +1,74 @@
#include <xrpl/tx/wasm/detail/CodecRevisions.h>
#include <xrpl/tx/wasm/detail/CodecTrait.h>
#include "CodecTypes.h"
#include <array>
#include <utility>
// ───────────────────────────────────────────────────────────────────────────
// Revision / amendment POLICY.
//
// The CodecTrait<N> revision maps and the wireVersionFor switch are BOTH
// generated from codec_revisions.macro, exactly as the (type, version)
// registry drives the dispatch tables — so the maps and the dispatch can't
// drift from the registration list.
// ───────────────────────────────────────────────────────────────────────────
namespace xrpl::wasm::detail {
// (1) Generate the CodecTrait<N> revision maps.
#define CODEC_REVISION_BEGIN(Revision) \
template <> \
struct CodecTrait<Revision> \
{ \
static constexpr CodecVersion kVersion = Revision; \
static constexpr auto versions = \
std::to_array<std::pair<CodecTypeCode, CodecVersion>>({
#define CODEC_REVISION_ENTRY(CppType, Version) \
{codecTypeCodeV<CppType>, Version},
#define CODEC_REVISION_END(Revision) \
}); \
};
#include <xrpl/tx/wasm/detail/codec_revisions.macro>
namespace {
template <CodecVersion N>
Expected<CodecVersion, CodecError>
versionFromRevision(CodecTypeCode code)
{
for (auto const& [c, v] : CodecTrait<N>::versions)
{
if (c == code)
{
return v;
}
}
return Unexpected{CodecError::TypeNotInRevision};
}
} // namespace
Expected<CodecVersion, CodecError>
wireVersionFor(CodecVersion declaredRevision, CodecTypeCode code)
{
// TODO(amendment-gating): each revision > 0 must additionally be gated
// behind its amendment (via Rules) before a node may emit it, so no node
// emits a wire version its peers can't agree on. Thread Rules in here.
// (2) Generate the runtime-revision -> CodecTrait<N> dispatch.
switch (declaredRevision)
{
#define CODEC_REVISION_BEGIN(Revision) \
case Revision: \
return versionFromRevision<Revision>(code);
#define CODEC_REVISION_ENTRY(CppType, Version)
#define CODEC_REVISION_END(Revision)
#include <xrpl/tx/wasm/detail/codec_revisions.macro>
default:
return Unexpected{CodecError::UnknownCodecVersion};
}
}
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,34 @@
#pragma once
//
// Internal aggregation header for the wasm codec registry (NOT public — lives
// under src/). Expands codec_types.macro to declare, in one shared place:
//
// * CODEC_TYPE -> the C++ type -> CodecTypeCode mapping
// * CODEC_VERSION -> each (type, version) CodecTypeTrait specialization
//
// Both the registry TU and every per-type codec .cpp include this, so the trait
// declarations they share are always generated from the same .def and can never
// drift.
//
#include <xrpl/basics/Expected.h> // used by the trait macro's decode/encode
#include <xrpl/tx/wasm/detail/CodecTypeCode.h>
#include <xrpl/tx/wasm/detail/CodecTypeTrait.h>
// One include per registered C++ *type* (not per version):
#include <xrpl/basics/Number.h>
#include <xrpl/protocol/AccountID.h>
namespace xrpl::wasm::detail {
// type -> type code
#define CODEC_TYPE(CppType, TypeCode) XRPL_WASM_CODEC_TYPE_CODE(CppType, TypeCode)
#include <xrpl/tx/wasm/detail/codec_types.macro>
// per-(type, version) trait declarations (bodies live in the type's .cpp)
#define CODEC_VERSION(CppType, Version, PayloadSize) \
XRPL_WASM_CODEC_TYPE_TRAIT(CppType, Version, PayloadSize)
#include <xrpl/tx/wasm/detail/codec_types.macro>
} // namespace xrpl::wasm::detail

View File

@@ -0,0 +1,54 @@
#include "CodecTypes.h"
#include <xrpl/protocol/Serializer.h>
#include <cstdint>
#include <limits>
// ───────────────────────────────────────────────────────────────────────────
// Codec bodies for Number. One decode/encode pair per registered version.
// (GLOB_RECURSE compiles this file automatically; it is wired into the dispatch
// tables by the explicit instantiations in CodecRegistry.cpp.)
// ───────────────────────────────────────────────────────────────────────────
namespace xrpl::wasm::detail {
// ── Number, version 0 : int64 mantissa + int32 exponent = 12 bytes ──────────
// Layout deliberately matches the frozen on-ledger STNumber serialization.
template <>
Expected<Number, CodecError>
CodecTypeTrait<codecTypeCodeV<Number>, 0>::decode(CodecEnvelope const& env)
{
if (env.header.payload_size != kPayloadSize)
{
return Unexpected{CodecError::Truncated};
}
auto sit = SerialIter{env.payload, env.header.payload_size};
auto const mantissa = sit.geti64();
auto const exponent = sit.geti32();
return Number{mantissa, exponent};
}
template <>
Expected<CodecEnvelope, CodecError>
CodecTypeTrait<codecTypeCodeV<Number>, 0>::encode(Number const& value)
{
// v0 carries an int64 mantissa; Number's mantissa is int64 today so it
// always fits. The guard documents the boundary for a future wider Number
// (the "graceful fail" path when a value can't be represented in v0).
if (value.exponent() < std::numeric_limits<std::int32_t>::min() ||
value.exponent() > std::numeric_limits<std::int32_t>::max())
{
return Unexpected{CodecError::NotRepresentable};
}
// TODO(payload-ownership): the returned envelope's payload must reference
// storage that outlives the call; that ownership belongs to the wire layer.
// The encode signature is intentionally left as-is for now, so the actual
// byte production is deferred there.
return CodecEnvelope{.header={.type_code=kCodecTypeCode, .version=kVersion, .payload_size=kPayloadSize}, .payload=nullptr};
}
} // namespace xrpl::wasm::detail

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,5 @@
#pragma once
#include <test/app/wasm_fixtures/fixtures.h>
#include <test/jtx/Env.h>
#include <test/unit_test/SuiteJournal.h>
@@ -18,62 +20,35 @@
namespace xrpl::test {
struct TestLedgerDataProvider : public HostFunctions
class TestLedgerDataProvider : public HostFunctions
{
jtx::Env& env;
void* rt = nullptr;
jtx::Env& env_;
public:
TestLedgerDataProvider(jtx::Env& env) : HostFunctions(env.journal), env(env)
TestLedgerDataProvider(jtx::Env& env) : HostFunctions(env.journal), env_(env)
{
}
void
setRT(void* rt) override
{
this->rt = rt;
}
[[nodiscard]] void*
getRT() const override
{
return rt;
}
Expected<std::uint32_t, HostFunctionError>
getLedgerSqn() const override
{
return env.current()->seq();
return env_.current()->seq();
}
};
struct TestHostFunctions : public HostFunctions
class TestHostFunctions : public HostFunctions
{
test::jtx::Env& env;
AccountID accountID;
Bytes data;
int clock_drift = 0;
void* rt = nullptr;
protected:
test::jtx::Env& env_;
AccountID accountID_;
Bytes data_;
public:
TestHostFunctions(test::jtx::Env& env, int cd = 0)
: HostFunctions(env.journal), env(env), clock_drift(cd)
TestHostFunctions(test::jtx::Env& env) : HostFunctions(env.journal), env_(env)
{
accountID = env.master.id();
accountID_ = env.master.id();
std::string t = "10000";
data = Bytes{t.begin(), t.end()};
}
void
setRT(void* rt) override
{
this->rt = rt;
}
[[nodiscard]] void*
getRT() const override
{
return rt;
data_ = Bytes{t.begin(), t.end()};
}
Expected<std::uint32_t, HostFunctionError>
@@ -91,7 +66,7 @@ public:
Expected<Hash, HostFunctionError>
getParentLedgerHash() const override
{
return env.current()->header().parentHash;
return env_.current()->header().parentHash;
}
Expected<std::uint32_t, HostFunctionError>
@@ -122,15 +97,15 @@ public:
getTxField(SField const& fname) const override
{
if (fname == sfAccount)
{
return Bytes(accountID.begin(), accountID.end());
}
return Bytes(accountID_.begin(), accountID_.end());
if (fname == sfFee)
{
int64_t x = 235;
uint8_t const* p = reinterpret_cast<uint8_t const*>(&x);
return Bytes{p, p + sizeof(x)};
}
if (fname == sfSequence)
{
auto const x = getLedgerSqn();
@@ -141,6 +116,7 @@ public:
auto const* e = reinterpret_cast<uint8_t const*>(&data + 1);
return Bytes{b, e};
}
return Bytes();
}
@@ -149,25 +125,21 @@ public:
{
auto const& sn = fname.getName();
if (sn == "Destination" || sn == "Account")
{
return Bytes(accountID.begin(), accountID.end());
}
return Bytes(accountID_.begin(), accountID_.end());
if (sn == "Data")
{
return data;
}
return data_;
if (sn == "FinishAfter")
{
auto t = env.current()->parentCloseTime().time_since_epoch().count();
auto t = env_.current()->parentCloseTime().time_since_epoch().count();
std::string s = std::to_string(t);
return Bytes{s.begin(), s.end()};
}
return Unexpected(HostFunctionError::INTERNAL);
return Unexpected(HostFunctionError::Unimplemented);
}
Expected<Bytes, HostFunctionError>
getLedgerObjField(int32_t cacheIdx, SField const& fname) const override
getLedgerObjField(int32_t, SField const& fname) const override
{
if (fname == sfBalance)
{
@@ -175,25 +147,24 @@ public:
uint8_t const* p = reinterpret_cast<uint8_t const*>(&x);
return Bytes{p, p + sizeof(x)};
}
if (fname == sfAccount)
{
return Bytes(accountID.begin(), accountID.end());
}
return data;
return Bytes(accountID_.begin(), accountID_.end());
return data_;
}
Expected<Bytes, HostFunctionError>
getTxNestedField(Slice const& locator) const override
getTxNestedField(FieldLocator const& locator) const override
{
if (locator.size() == 4)
if (locator.size() == 1)
{
int32_t const* l = reinterpret_cast<int32_t const*>(locator.data());
int32_t const* l = locator.data();
int32_t const sfield = l[0];
if (sfield == sfAccount.getCode())
{
return Bytes(accountID.begin(), accountID.end());
}
return Bytes(accountID_.begin(), accountID_.end());
}
uint8_t const a[] = {0x2b, 0x6a, 0x23, 0x2a, 0xa4, 0xc4, 0xbe, 0x41, 0xbf, 0x49, 0xd2,
0x45, 0x9f, 0xa4, 0xa0, 0x34, 0x7e, 0x1b, 0x54, 0x3a, 0x4c, 0x92,
0xfc, 0xee, 0x08, 0x21, 0xc0, 0x20, 0x1e, 0x2e, 0x9a, 0x00};
@@ -201,17 +172,16 @@ public:
}
Expected<Bytes, HostFunctionError>
getCurrentLedgerObjNestedField(Slice const& locator) const override
getCurrentLedgerObjNestedField(FieldLocator const& locator) const override
{
if (locator.size() == 4)
if (locator.size() == 1)
{
int32_t const* l = reinterpret_cast<int32_t const*>(locator.data());
int32_t const* l = locator.data();
int32_t const sfield = l[0];
if (sfield == sfAccount.getCode())
{
return Bytes(accountID.begin(), accountID.end());
}
return Bytes(accountID_.begin(), accountID_.end());
}
uint8_t const a[] = {0x2b, 0x6a, 0x23, 0x2a, 0xa4, 0xc4, 0xbe, 0x41, 0xbf, 0x49, 0xd2,
0x45, 0x9f, 0xa4, 0xa0, 0x34, 0x7e, 0x1b, 0x54, 0x3a, 0x4c, 0x92,
0xfc, 0xee, 0x08, 0x21, 0xc0, 0x20, 0x1e, 0x2e, 0x9a, 0x00};
@@ -219,17 +189,16 @@ public:
}
Expected<Bytes, HostFunctionError>
getLedgerObjNestedField(int32_t cacheIdx, Slice const& locator) const override
getLedgerObjNestedField(int32_t cacheIdx, FieldLocator const& locator) const override
{
if (locator.size() == 4)
if (locator.size() == 1)
{
int32_t const* l = reinterpret_cast<int32_t const*>(locator.data());
int32_t const* l = locator.data();
int32_t const sfield = l[0];
if (sfield == sfAccount.getCode())
{
return Bytes(accountID.begin(), accountID.end());
}
return Bytes(accountID_.begin(), accountID_.end());
}
uint8_t const a[] = {0x2b, 0x6a, 0x23, 0x2a, 0xa4, 0xc4, 0xbe, 0x41, 0xbf, 0x49, 0xd2,
0x45, 0x9f, 0xa4, 0xa0, 0x34, 0x7e, 0x1b, 0x54, 0x3a, 0x4c, 0x92,
0xfc, 0xee, 0x08, 0x21, 0xc0, 0x20, 0x1e, 0x2e, 0x9a, 0x00};
@@ -255,19 +224,19 @@ public:
}
Expected<int32_t, HostFunctionError>
getTxNestedArrayLen(Slice const& locator) const override
getTxNestedArrayLen(FieldLocator const& locator) const override
{
return 32;
}
Expected<int32_t, HostFunctionError>
getCurrentLedgerObjNestedArrayLen(Slice const& locator) const override
getCurrentLedgerObjNestedArrayLen(FieldLocator const& locator) const override
{
return 32;
}
Expected<int32_t, HostFunctionError>
getLedgerObjNestedArrayLen(int32_t cacheIdx, Slice const& locator) const override
getLedgerObjNestedArrayLen(int32_t cacheIdx, FieldLocator const& locator) const override
{
return 32;
}
@@ -287,7 +256,7 @@ public:
Expected<Hash, HostFunctionError>
computeSha512HalfHash(Slice const& data) const override
{
return env.current()->header().parentHash;
return env_.current()->header().parentHash;
}
Expected<Bytes, HostFunctionError>
@@ -352,9 +321,7 @@ public:
getNFT(AccountID const& account, uint256 const& nftId) const override
{
if (!account || !nftId)
{
return Unexpected(HostFunctionError::InvalidParams);
}
std::string s = "https://ripple.com";
return Bytes(s.begin(), s.end());
@@ -363,7 +330,7 @@ public:
Expected<Bytes, HostFunctionError>
getNFTIssuer(uint256 const& nftId) const override
{
return Bytes(accountID.begin(), accountID.end());
return Bytes(accountID_.begin(), accountID_.end());
}
Expected<std::uint32_t, HostFunctionError>
@@ -543,22 +510,21 @@ public:
}
};
struct TestHostFunctionsSink : public TestHostFunctions
class TestHostFunctionsSink : public TestHostFunctions
{
test::StreamSink sink;
void const* rt = nullptr;
test::StreamSink sink_;
public:
explicit TestHostFunctionsSink(test::jtx::Env& env, int cd = 0)
: TestHostFunctions(env, cd), sink(beast::Severity::Debug)
explicit TestHostFunctionsSink(test::jtx::Env& env)
: TestHostFunctions(env), sink_(beast::Severity::Debug)
{
j = beast::Journal(sink);
j_ = beast::Journal(sink_);
}
test::StreamSink&
getSink()
{
return sink;
return sink_;
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -44,9 +44,9 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
@@ -64,9 +64,9 @@ dependencies = [
[[package]]
name = "generic-array"
version = "0.14.9"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -74,24 +74,24 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.177"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "proc-macro2"
version = "1.0.103"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
@@ -109,9 +109,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.108"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -120,9 +120,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -135,15 +135,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "unicode-ident"
version = "1.0.22"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "version_check"
@@ -152,9 +152,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
name = "xrpl-macros"
version = "0.1.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf"
dependencies = [
"bs58",
"quote",
@@ -164,8 +164,8 @@ dependencies = [
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
version = "0.8.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf"
dependencies = [
"xrpl-address-macro",
"xrpl-macros",
]

View File

@@ -10,7 +10,7 @@ edition = "2024"
crate-type = ["cdylib"]
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "u32-buffer" }
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" }
[profile.dev]
panic = "abort"

View File

@@ -98,7 +98,7 @@ fn test_ledger_header_functions() -> i32 {
// Test 1.1: get_ledger_sqn() - should return current ledger sequence number
let mut sqn_buffer = [0u8; 4];
let sqn_result = unsafe { host::get_ledger_sqn(sqn_buffer.as_mut_ptr(), sqn_buffer.len()) };
let sqn_result = unsafe { host::ldgr_index(sqn_buffer.as_mut_ptr(), sqn_buffer.len()) };
if sqn_result <= 0 {
let _ = trace_num("ERROR: get_ledger_sqn failed:", sqn_result as i64);
@@ -110,7 +110,7 @@ fn test_ledger_header_functions() -> i32 {
// Test 1.2: get_parent_ledger_time() - should return parent ledger timestamp
let mut time_buffer = [0u8; 4];
let time_result =
unsafe { host::get_parent_ledger_time(time_buffer.as_mut_ptr(), time_buffer.len()) };
unsafe { host::parent_ldgr_time(time_buffer.as_mut_ptr(), time_buffer.len()) };
if time_result <= 0 {
let _ = trace_num("ERROR: get_parent_ledger_time failed:", time_result as i64);
@@ -122,7 +122,7 @@ fn test_ledger_header_functions() -> i32 {
// 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()) };
unsafe { host::parent_ldgr_hash(hash_buffer.as_mut_ptr(), hash_buffer.len()) };
if hash_result != 32 {
let _ = trace_num(
@@ -146,8 +146,8 @@ fn test_transaction_data_functions() -> i32 {
// Test with Account field (required, 20 bytes)
let mut account_buffer = [0u8; 20];
let account_len = unsafe {
host::get_tx_field(
sfield::Account,
host::tx_field(
sfield::Account.into(),
account_buffer.as_mut_ptr(),
account_buffer.len(),
)
@@ -165,8 +165,13 @@ fn test_transaction_data_functions() -> i32 {
// 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()) };
let fee_len = unsafe {
host::tx_field(
sfield::Fee.into(),
fee_buffer.as_mut_ptr(),
fee_buffer.len(),
)
};
if fee_len != 8 {
let _ = trace_num(
@@ -184,8 +189,13 @@ fn test_transaction_data_functions() -> i32 {
// 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()) };
let seq_len = unsafe {
host::tx_field(
sfield::Sequence.into(),
seq_buffer.as_mut_ptr(),
seq_buffer.len(),
)
};
if seq_len != 4 {
let _ = trace_num(
@@ -200,10 +210,10 @@ fn test_transaction_data_functions() -> i32 {
// 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 locator = [0x01_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8]; // Two int32s in little-endian: [1, 0]
let mut nested_buffer = [0u8; 32];
let nested_result = unsafe {
host::get_tx_nested_field(
host::tx_inner(
locator.as_ptr(),
locator.len(),
nested_buffer.as_mut_ptr(),
@@ -227,15 +237,14 @@ fn test_transaction_data_functions() -> i32 {
}
// Test 2.3: get_tx_array_len() - Get array length
let signers_len = unsafe { host::get_tx_array_len(sfield::Signers) };
let signers_len = unsafe { host::tx_arr_len(sfield::Signers.into()) };
let _ = trace_num("Signers array length:", signers_len as i64);
let memos_len = unsafe { host::get_tx_array_len(sfield::Memos) };
let memos_len = unsafe { host::tx_arr_len(sfield::Memos.into()) };
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()) };
let nested_array_len = unsafe { host::tx_inner_arr_len(locator.as_ptr(), locator.len()) };
if nested_array_len < 0 {
let _ = trace_num(
@@ -259,8 +268,8 @@ fn test_current_ledger_object_functions() -> i32 {
// 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,
host::home_le_field(
sfield::Balance.into(),
balance_buffer.as_mut_ptr(),
balance_buffer.len(),
)
@@ -297,8 +306,8 @@ fn test_current_ledger_object_functions() -> i32 {
// Test with Account field
let mut current_account_buffer = [0u8; 20];
let current_account_result = unsafe {
host::get_current_ledger_obj_field(
sfield::Account,
host::home_le_field(
sfield::Account.into(),
current_account_buffer.as_mut_ptr(),
current_account_buffer.len(),
)
@@ -314,10 +323,10 @@ fn test_current_ledger_object_functions() -> i32 {
}
// Test 3.2: get_current_ledger_obj_nested_field() - Nested field access
let locator = [0x01, 0x00]; // Simple locator
let locator = [0x01_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8]; // Two int32s in little-endian: [1, 0]
let mut current_nested_buffer = [0u8; 32];
let current_nested_result = unsafe {
host::get_current_ledger_obj_nested_field(
host::home_le_inner(
locator.as_ptr(),
locator.len(),
current_nested_buffer.as_mut_ptr(),
@@ -340,7 +349,7 @@ fn test_current_ledger_object_functions() -> i32 {
}
// 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 current_array_len = unsafe { host::home_le_arr_len(sfield::Signers.into()) };
let _ = trace_num(
"Current object Signers array length:",
current_array_len as i64,
@@ -348,7 +357,7 @@ fn test_current_ledger_object_functions() -> i32 {
// 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()) };
unsafe { host::home_le_inner_arr_len(locator.as_ptr(), locator.len()) };
if current_nested_array_len < 0 {
let _ = trace_num(
@@ -379,7 +388,7 @@ fn test_any_ledger_object_functions() -> i32 {
// Test 4.1: cache_ledger_obj() - Cache a ledger object
let mut keylet_buffer = [0u8; 32];
let keylet_result = unsafe {
host::account_keylet(
host::accountroot_id(
account_id.0.as_ptr(),
account_id.0.len(),
keylet_buffer.as_mut_ptr(),
@@ -389,14 +398,13 @@ fn test_any_ledger_object_functions() -> i32 {
if keylet_result != 32 {
let _ = trace_num(
"ERROR: account_keylet failed for caching test:",
"ERROR: accountroot_id 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) };
let cache_result = unsafe { host::cache_le(keylet_buffer.as_ptr(), keylet_result as usize, 0) };
if cache_result <= 0 {
let _ = trace_num(
@@ -411,9 +419,9 @@ fn test_any_ledger_object_functions() -> i32 {
// Test get_ledger_obj_field with invalid slot
let field_result = unsafe {
host::get_ledger_obj_field(
host::le_field(
1,
sfield::Balance,
sfield::Balance.into(),
test_buffer.as_mut_ptr(),
test_buffer.len(),
)
@@ -426,9 +434,9 @@ fn test_any_ledger_object_functions() -> i32 {
}
// Test get_ledger_obj_nested_field with invalid slot
let locator = [0x01, 0x00];
let locator = [0x01_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8]; // Two int32s in little-endian: [1, 0]
let nested_result = unsafe {
host::get_ledger_obj_nested_field(
host::le_inner(
1,
locator.as_ptr(),
locator.len(),
@@ -444,7 +452,7 @@ fn test_any_ledger_object_functions() -> i32 {
}
// Test get_ledger_obj_array_len with invalid slot
let array_result = unsafe { host::get_ledger_obj_array_len(1, sfield::Signers) };
let array_result = unsafe { host::le_arr_len(1, sfield::Signers.into()) };
if array_result < 0 {
let _ = trace_num(
"INFO: get_ledger_obj_array_len failed as expected:",
@@ -454,7 +462,7 @@ fn test_any_ledger_object_functions() -> i32 {
// 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()) };
unsafe { host::le_inner_arr_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:",
@@ -473,9 +481,9 @@ fn test_any_ledger_object_functions() -> i32 {
// 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(
host::le_field(
slot,
sfield::Balance,
sfield::Balance.into(),
cached_balance_buffer.as_mut_ptr(),
cached_balance_buffer.len(),
)
@@ -509,10 +517,10 @@ fn test_any_ledger_object_functions() -> i32 {
}
// Test 4.3: get_ledger_obj_nested_field() - Nested field from cached object
let locator = [0x01, 0x00];
let locator = [0x01_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8, 0x00_u8]; // Two int32s in little-endian: [1, 0]
let mut cached_nested_buffer = [0u8; 32];
let cached_nested_result = unsafe {
host::get_ledger_obj_nested_field(
host::le_inner(
slot,
locator.as_ptr(),
locator.len(),
@@ -536,7 +544,7 @@ fn test_any_ledger_object_functions() -> i32 {
}
// 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 cached_array_len = unsafe { host::le_arr_len(slot, sfield::Signers.into()) };
let _ = trace_num(
"Cached object Signers array length:",
cached_array_len as i64,
@@ -544,7 +552,7 @@ fn test_any_ledger_object_functions() -> i32 {
// 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()) };
unsafe { host::le_inner_arr_len(slot, locator.as_ptr(), locator.len()) };
if cached_nested_array_len < 0 {
let _ = trace_num(
@@ -570,30 +578,30 @@ fn test_keylet_generation_functions() -> i32 {
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(
// Test 5.1: accountroot_id() - Generate keylet for account
let mut accountroot_id_buffer = [0u8; 32];
let accountroot_id_result = unsafe {
host::accountroot_id(
account_id.0.as_ptr(),
account_id.0.len(),
account_keylet_buffer.as_mut_ptr(),
account_keylet_buffer.len(),
accountroot_id_buffer.as_mut_ptr(),
accountroot_id_buffer.len(),
)
};
if account_keylet_result != 32 {
if accountroot_id_result != 32 {
let _ = trace_num(
"ERROR: account_keylet failed:",
account_keylet_result as i64,
"ERROR: accountroot_id failed:",
accountroot_id_result as i64,
);
return -501; // Account keylet generation failed
}
let _ = trace_data("Account keylet:", &account_keylet_buffer, DataRepr::AsHex);
let _ = trace_data("Account keylet:", &accountroot_id_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(
host::credential_id(
account_id.0.as_ptr(), // Subject
account_id.0.len(),
account_id.0.as_ptr(), // Issuer - same account for test
@@ -624,7 +632,7 @@ fn test_keylet_generation_functions() -> i32 {
let sequence_number: i32 = 1000;
let sequence_number_bytes = sequence_number.to_be_bytes();
let escrow_keylet_result = unsafe {
host::escrow_keylet(
host::escrow_id(
account_id.0.as_ptr(),
account_id.0.len(),
sequence_number_bytes.as_ptr(),
@@ -645,7 +653,7 @@ fn test_keylet_generation_functions() -> i32 {
let document_id: i32 = 42;
let document_id_bytes = document_id.to_be_bytes();
let oracle_keylet_result = unsafe {
host::oracle_keylet(
host::oracle_id(
account_id.0.as_ptr(),
account_id.0.len(),
document_id_bytes.as_ptr(),
@@ -674,7 +682,7 @@ fn test_utility_functions() -> i32 {
let test_data = b"Hello, XRPL WASM world!";
let mut hash_output = [0u8; 32];
let hash_result = unsafe {
host::compute_sha512_half(
host::sha512_half(
test_data.as_ptr(),
test_data.len(),
hash_output.as_mut_ptr(),
@@ -695,7 +703,7 @@ fn test_utility_functions() -> i32 {
let nft_id = [0u8; 32]; // Dummy NFT ID for testing
let mut nft_buffer = [0u8; 256];
let nft_result = unsafe {
host::get_nft(
host::nft_uri(
account_id.0.as_ptr(),
account_id.0.len(),
nft_id.as_ptr(),
@@ -766,7 +774,7 @@ fn test_data_update_functions() -> i32 {
// 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()) };
let update_result = unsafe { host::set_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);

View File

@@ -44,9 +44,9 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
@@ -64,9 +64,9 @@ dependencies = [
[[package]]
name = "generic-array"
version = "0.14.9"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -74,24 +74,24 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.177"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "proc-macro2"
version = "1.0.103"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
@@ -109,9 +109,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.108"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -120,9 +120,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -135,15 +135,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "unicode-ident"
version = "1.0.22"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "version_check"
@@ -152,9 +152,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
name = "xrpl-macros"
version = "0.1.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#21c522f34a24b460297ebb6be1822680459bf37e"
dependencies = [
"bs58",
"quote",
@@ -164,8 +164,8 @@ dependencies = [
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
version = "0.8.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#21c522f34a24b460297ebb6be1822680459bf37e"
dependencies = [
"xrpl-address-macro",
"xrpl-macros",
]

View File

@@ -15,7 +15,7 @@ opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "u32-buffer" }
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" }
[profile.dev]
panic = "abort"

View File

@@ -4,39 +4,38 @@
extern crate std;
use crate::host::{Error, Result, Result::Err, Result::Ok};
use xrpl_std::core::keylets;
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::ledger_objects::LedgerObjectFieldGetter;
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::host::trace::{trace, trace_acct, trace_data, trace_num, DataRepr};
use xrpl_std::sfield;
#[unsafe(no_mangle)]
pub fn object_exists(
pub fn object_exists<T: LedgerObjectFieldGetter, const CODE: i32>(
keylet_result: Result<keylets::KeyletBytes>,
keylet_type: &str,
field: i32,
sfield: sfield::SField<T, CODE>,
) -> Result<bool> {
let field = CODE;
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) };
let slot = unsafe { host::cache_le(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) {
let _ = trace_num("Getting field: ", new_field.clone().into());
match ledger_object::get_field(slot, new_field) {
Ok(data) => {
let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex);
}
@@ -47,9 +46,9 @@ pub fn object_exists(
}
} 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);
match ledger_object::get_field(slot, sfield) {
Ok(_data) => {
let _ = trace("Field data: retrieved");
}
Err(result_code) => {
let _ = trace_num("Error getting field: ", result_code.into());
@@ -74,10 +73,10 @@ pub extern "C" fn finish() -> i32 {
let escrow: CurrentEscrow = get_current_escrow();
let account = escrow.get_account().unwrap_or_panic();
let _ = trace_account("Account:", &account);
let _ = trace_acct("Account:", &account);
let destination = escrow.get_destination().unwrap_or_panic();
let _ = trace_account("Destination:", &destination);
let _ = trace_acct("Destination:", &destination);
let mut seq = 5;
@@ -99,82 +98,78 @@ pub extern "C" fn finish() -> i32 {
};
}
let account_keylet = keylets::account_keylet(&account);
check_object_exists!(account_keylet, "Account", sfield::Account);
let accountroot_id = keylets::accountroot_id(&account);
check_object_exists!(accountroot_id, "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);
let trustline_id = keylets::trustline_id(&account, &destination, &currency);
check_object_exists!(trustline_id, "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
);
check_object_exists!(keylets::amm_id(&asset1, &asset2), "AMM", sfield::Account);
let check_keylet = keylets::check_keylet(&account, seq);
check_object_exists!(check_keylet, "Check", sfield::Account);
let check_id = keylets::check_id(&account, seq);
check_object_exists!(check_id, "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);
let credential_id = keylets::credential_id(&account, &account, cred_type);
check_object_exists!(credential_id, "Credential", sfield::Subject);
seq += 1;
let delegate_keylet = keylets::delegate_keylet(&account, &destination);
check_object_exists!(delegate_keylet, "Delegate", sfield::Account);
let delegate_id = keylets::delegate_id(&account, &destination);
check_object_exists!(delegate_id, "Delegate", sfield::Account);
seq += 1;
let deposit_preauth_keylet = keylets::deposit_preauth_keylet(&account, &destination);
check_object_exists!(deposit_preauth_keylet, "DepositPreauth", sfield::Account);
let deposit_preauth_id = keylets::deposit_preauth_id(&account, &destination);
check_object_exists!(deposit_preauth_id, "DepositPreauth", sfield::Account);
seq += 1;
let did_keylet = keylets::did_keylet(&account);
check_object_exists!(did_keylet, "DID", sfield::Account);
let did_id = keylets::did_id(&account);
check_object_exists!(did_id, "DID", sfield::Account);
seq += 1;
let escrow_keylet = keylets::escrow_keylet(&account, seq);
check_object_exists!(escrow_keylet, "Escrow", sfield::Account);
let escrow_id = keylets::escrow_id(&account, seq);
check_object_exists!(escrow_id, "Escrow", sfield::Account);
seq += 1;
let mpt_issuance_keylet = keylets::mpt_issuance_keylet(&account, seq);
let mpt_issuance_id = keylets::mpt_issuance_id(&account, seq);
let mpt_id = MptId::new(seq.try_into().unwrap(), account);
check_object_exists!(mpt_issuance_keylet, "MPTIssuance", sfield::Issuer);
check_object_exists!(mpt_issuance_id, "MPTIssuance", sfield::Issuer);
seq += 1;
let mptoken_keylet = keylets::mptoken_keylet(&mpt_id, &destination);
check_object_exists!(mptoken_keylet, "MPToken", sfield::Account);
let mptoken_id = keylets::mptoken_id(&mpt_id, &destination);
check_object_exists!(mptoken_id, "MPToken", sfield::Account);
let nft_offer_keylet = keylets::nft_offer_keylet(&destination, 6);
check_object_exists!(nft_offer_keylet, "NFTokenOffer", sfield::Owner);
let nft_offer_id = keylets::nft_offer_id(&destination, 6);
check_object_exists!(nft_offer_id, "NFTokenOffer", sfield::Owner);
let offer_keylet = keylets::offer_keylet(&account, seq);
check_object_exists!(offer_keylet, "Offer", sfield::Account);
let offer_id = keylets::offer_id(&account, seq);
check_object_exists!(offer_id, "Offer", sfield::Account);
seq += 1;
let paychan_keylet = keylets::paychan_keylet(&account, &destination, seq);
check_object_exists!(paychan_keylet, "PayChannel", sfield::Account);
let paychan_id = keylets::paychan_id(&account, &destination, seq);
check_object_exists!(paychan_id, "PayChannel", sfield::Account);
seq += 1;
let pd_keylet = keylets::permissioned_domain_keylet(&account, seq);
check_object_exists!(pd_keylet, "PermissionedDomain", sfield::Owner);
let pd_id = keylets::permissioned_domain_id(&account, seq);
check_object_exists!(pd_id, "PermissionedDomain", sfield::Owner);
seq += 1;
let signers_keylet = keylets::signers_keylet(&account);
check_object_exists!(signers_keylet, "SignerList", sfield::Generic);
let signers_id = keylets::signers_id(&account);
check_object_exists!(signers_id, "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);
let ticket_id = keylets::ticket_id(&account, seq);
check_object_exists!(ticket_id, "Ticket", sfield::Account);
seq += 1;
let vault_keylet = keylets::vault_keylet(&account, seq);
check_object_exists!(vault_keylet, "Vault", sfield::Account);
let vault_id = keylets::vault_id(&account, seq);
check_object_exists!(vault_id, "Vault", sfield::Account);
// seq += 1;
1 // All keylets exist, finish the escrow.

View File

@@ -1,8 +1,8 @@
#include <stdint.h>
int32_t float_from_uint(uint8_t const *, int32_t, uint8_t *, int32_t, int32_t);
int32_t check_keylet(uint8_t const *, int32_t, uint8_t const *, int32_t,
uint8_t *, int32_t);
int32_t check_id(uint8_t const *, int32_t, uint8_t const *, int32_t, uint8_t *,
int32_t);
uint8_t e_data1[32 * 1024];
uint8_t e_data2[32 * 1024];
@@ -31,10 +31,9 @@ int32_t test2()
// Set up valid non-zero AccountID (20 bytes) at offset 10
for (int i = 0; i < 20; i++)
e_data2[10 + i] = i + 1;
// Call check_keylet with misaligned uint32 at &e_data2[1] to hit line 72 in
// Call check_id with misaligned uint32 at &e_data2[1] to hit line 72 in
// HostFuncWrapper.cpp
int32_t result =
check_keylet(&e_data2[10], 20, &e_data2[1], 4, &e_data2[35], 32);
int32_t result = check_id(&e_data2[10], 20, &e_data2[1], 4, &e_data2[35], 32);
// Return the misaligned value directly to validate it was read correctly (-1
// if all 0xFF)
return result >= 0 ? *((int32_t *)(&e_data2[36])) : result;

View File

@@ -44,9 +44,9 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
@@ -64,9 +64,9 @@ dependencies = [
[[package]]
name = "generic-array"
version = "0.14.9"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
@@ -74,24 +74,24 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.177"
version = "0.2.186"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
[[package]]
name = "proc-macro2"
version = "1.0.103"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.41"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
@@ -109,9 +109,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.108"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -120,9 +120,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.10.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
dependencies = [
"tinyvec_macros",
]
@@ -135,15 +135,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "typenum"
version = "1.19.0"
version = "1.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"
[[package]]
name = "unicode-ident"
version = "1.0.22"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "version_check"
@@ -152,9 +152,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xrpl-address-macro"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
name = "xrpl-macros"
version = "0.1.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf"
dependencies = [
"bs58",
"quote",
@@ -164,8 +164,8 @@ dependencies = [
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
version = "0.8.0"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf"
dependencies = [
"xrpl-address-macro",
"xrpl-macros",
]

View File

@@ -15,4 +15,4 @@ opt-level = 's'
panic = "abort"
[dependencies]
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "u32-buffer" }
xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" }

View File

@@ -19,20 +19,20 @@ pub const FLOAT_ROUNDING_MODES_UPWARD: i32 = 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 parent_ldgr_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 cache_le(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 tx_inner_arr_len(locator_ptr: i32, locator_len: i32) -> i32;
pub fn account_keylet(
pub fn accountroot_id(
account_ptr: i32,
account_len: i32,
out_buff_ptr: *mut u8,
out_buff_len: usize,
) -> i32;
pub fn line_keylet(
pub fn trustline_id(
account1_ptr: *const u8,
account1_len: usize,
account2_ptr: *const u8,

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,87 @@
# cspell: disable
import os
import sys
import subprocess
import re
import shlex
import subprocess
import sys
import tempfile
import zipfile
from difflib import get_close_matches
OPT = "-Oz"
BASE_PATH = os.path.abspath(os.path.dirname(__file__))
def update_fixture(project_name, wasm):
fixture_name = (
re.sub(r"_([a-z])", lambda m: m.group(1).upper(), project_name) + "WasmHex"
)
def pascal_case(name):
return "".join(word[:1].upper() + word[1:] for word in re.split(r"[_\W]+", name))
def normalize_name(name):
name = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name)
return re.sub(r"[^a-z0-9]", "", name.lower())
def fixture_key(name):
name = normalize_name(name).removeprefix("k")
return name.removesuffix("wasmhex").removesuffix("hex")
def declared_fixtures():
h_path = os.path.join(BASE_PATH, "fixtures.h")
with open(h_path, "r", encoding="utf8") as f:
return re.findall(
r"extern std::string const ([A-Za-z_][A-Za-z0-9_]*);", f.read()
)
def find_fixture_name(project_name, suffix):
default = re.sub(r"_([a-z])", lambda m: m.group(1).upper(), project_name) + suffix
k_default = f"k{pascal_case(project_name)}{suffix}"
declarations = declared_fixtures()
normalized = {normalize_name(name): name for name in declarations}
fixture_keys = {fixture_key(name): name for name in declarations}
for name in (default, k_default):
if normalize_name(name) in normalized:
return normalized[normalize_name(name)]
project_key = normalize_name(project_name)
matches = [
name
for key, name in fixture_keys.items()
if key.endswith(project_key)
or key.startswith(project_key)
or project_key.endswith(key)
or project_key.startswith(key)
]
if len(matches) == 1:
return matches[0]
close = get_close_matches(project_key, fixture_keys.keys(), n=1, cutoff=0.82)
if close:
return fixture_keys[close[0]]
return k_default
def fixture_cpp_path(fixture_name):
pattern = rf"extern std::string const {fixture_name} ="
for file_name in os.listdir(BASE_PATH):
if not file_name.endswith(".cpp"):
continue
cpp_path = os.path.join(BASE_PATH, file_name)
with open(cpp_path, "r", encoding="utf8") as f:
if re.search(pattern, f.read()):
return cpp_path
return os.path.join(BASE_PATH, "fixtures.cpp")
def update_fixture(project_name, wasm, suffix="WasmHex"):
fixture_name = find_fixture_name(project_name, suffix)
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"))
cpp_path = fixture_cpp_path(fixture_name)
h_path = os.path.join(BASE_PATH, "fixtures.h")
with open(cpp_path, "r", encoding="utf8") as f:
cpp_content = f.read()
@@ -30,7 +97,7 @@ def update_fixture(project_name, wasm):
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"
h_content.rstrip() + f"\n\nextern std::string const {fixture_name};\n"
)
with open(h_path, "w", encoding="utf8") as f:
f.write(updated_h_content)
@@ -43,83 +110,178 @@ def update_fixture(project_name, wasm):
f.write(updated_cpp_content)
def read_wasm_hex(path):
with open(path, "rb") as f:
return f.read().hex()
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}"
")"
project_path = os.path.join(BASE_PATH, project_name)
wasm_location = os.path.join(
project_path, "target", "wasm32v1-none", "release", f"{project_name}.wasm"
)
try:
subprocess.run(build_cmd, shell=True, check=True)
subprocess.run(
["cargo", "build", "--target", "wasm32v1-none", "--release"],
cwd=project_path,
check=True,
)
subprocess.run(
["wasm-opt", wasm_location, OPT, "-o", wasm_location], check=True
)
print(f"WASM file for {project_name} has been built and optimized.")
except FileNotFoundError as e:
print(f"exec error: {e.filename} is required to build Rust fixtures")
sys.exit(1)
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)
update_fixture(project_name, read_wasm_hex(wasm_location))
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}"
)
project_path = os.path.join(BASE_PATH, f"{project_name}.c")
wasm_path = os.path.join(BASE_PATH, f"{project_name}.wasm")
cc = os.environ.get("CC")
sysroot = os.environ.get("SYSROOT")
if not cc or not sysroot:
print("exec error: CC and SYSROOT are required to build C fixtures")
sys.exit(1)
build_cmd = [
*shlex.split(cc),
f"--sysroot={sysroot}",
"-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",
"-o",
wasm_path,
project_path,
]
try:
subprocess.run(build_cmd, shell=True, check=True)
subprocess.run(build_cmd, check=True)
subprocess.run(["wasm-opt", wasm_path, OPT, "-o", wasm_path], check=True)
print(
f"WASM file for {project_name} has been built with WASI support using clang."
)
except FileNotFoundError as e:
print(f"exec error: {e.filename} is required to build C fixtures")
sys.exit(1)
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)
update_fixture(project_name, read_wasm_hex(wasm_path))
def wat_to_wasm(wat_path, wasm_path):
build_cmd = ["wat2wasm", wat_path, "-o", wasm_path]
try:
subprocess.run(build_cmd, check=True)
print(f"WASM file for {os.path.basename(wat_path)} has been built.")
except FileNotFoundError:
print("exec error: wat2wasm is required to build WAT fixtures")
sys.exit(1)
except subprocess.CalledProcessError as e:
print(f"exec error: {e}")
sys.exit(1)
def process_wat_file(wat_path):
project_name = os.path.splitext(os.path.basename(wat_path))[0]
with open(wat_path, "r", encoding="utf8") as f:
if "(module" not in f.read():
print(f"Skipping WAT fixture without a module: {project_name}")
return
with tempfile.TemporaryDirectory() as tmpdir:
wasm_path = os.path.join(tmpdir, f"{project_name}.wasm")
wat_to_wasm(wat_path, wasm_path)
update_fixture(project_name, read_wasm_hex(wasm_path), "Hex")
def process_wat_zip(zip_path):
project_name = os.path.splitext(os.path.basename(zip_path))[0]
with tempfile.TemporaryDirectory() as tmpdir:
with zipfile.ZipFile(zip_path) as archive:
wat_names = [name for name in archive.namelist() if name.endswith(".wat")]
if len(wat_names) != 1:
print(f"exec error: expected one .wat file in {zip_path}")
sys.exit(1)
archive.extract(wat_names[0], tmpdir)
wasm_path = os.path.join(tmpdir, f"{project_name}.wasm")
wat_to_wasm(os.path.join(tmpdir, wat_names[0]), wasm_path)
update_fixture(project_name, read_wasm_hex(wasm_path), "Hex")
def process_wat(project_name):
candidates = [
os.path.join(BASE_PATH, f"{project_name}.wat"),
os.path.join(BASE_PATH, "wat", f"{project_name}.wat"),
os.path.join(BASE_PATH, "wat", f"{project_name}.zip"),
]
for path in candidates:
if os.path.isfile(path):
if path.endswith(".zip"):
process_wat_zip(path)
else:
process_wat_file(path)
return
print(f"exec error: fixture {project_name} not found")
sys.exit(1)
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])
project_name = os.path.splitext(os.path.basename(sys.argv[1]))[0]
if os.path.isfile(os.path.join(BASE_PATH, project_name, "Cargo.toml")):
process_rust(project_name)
elif os.path.isfile(os.path.join(BASE_PATH, f"{project_name}.c")):
process_c(project_name)
else:
process_c(sys.argv[1])
process_wat(project_name)
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))
for d in os.listdir(BASE_PATH)
if os.path.isfile(os.path.join(BASE_PATH, d, "Cargo.toml"))
]
c_files = [f for f in os.listdir(os.path.dirname(__file__)) if f.endswith(".c")]
for d in dirs:
c_files = [f for f in os.listdir(BASE_PATH) if f.endswith(".c")]
wat_files = [f for f in os.listdir(BASE_PATH) if f.endswith(".wat")]
wat_path = os.path.join(BASE_PATH, "wat")
wat_fixture_files = [
f
for f in (os.listdir(wat_path) if os.path.isdir(wat_path) else [])
if f.endswith((".wat", ".zip"))
]
for d in sorted(dirs):
process_rust(d)
for c in c_files:
for c in sorted(c_files):
process_c(c[:-2])
for wat in sorted(wat_files):
process_wat_file(os.path.join(BASE_PATH, wat))
for wat_fixture in sorted(wat_fixture_files):
path = os.path.join(wat_path, wat_fixture)
if wat_fixture.endswith(".zip"):
process_wat_zip(path)
else:
process_wat_file(path)
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,11 +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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,75 +9,4 @@ extern std::string const kAllHostFunctionsWasmHex;
extern std::string const kAllKeyletsWasmHex;
extern std::string const kCodecovTestsWasmHex;
extern std::string const kFibWasmHex;
extern std::string const kFloatTestsWasmHex;
extern std::string const kFloat0Hex;
extern std::string const kDisabledFloatHex;
extern std::string const kMemoryPointerAtLimitHex;
extern std::string const kMemoryPointerOverLimitHex;
extern std::string const kMemoryOffsetOverLimitHex;
extern std::string const kMemoryEndOfWordOverLimitHex;
extern std::string const kMemoryGrow0To1PageHex;
extern std::string const kMemoryGrow1To0PageHex;
extern std::string const kMemoryLastByteOf8MbHex;
extern std::string const kMemoryGrow1MoreThan8MbHex;
extern std::string const kMemoryGrow0MoreThan8MbHex;
extern std::string const kMemoryInit1MoreThan8MbHex;
extern std::string const kMemoryNegativeAddressHex;
extern std::string const kTable64ElementsHex;
extern std::string const kTable65ElementsHex;
extern std::string const kTable2TablesHex;
extern std::string const kTable0ElementsHex;
extern std::string const kTableUintMaxHex;
extern std::string const kProposalMutableGlobalHex;
extern std::string const kProposalGcStructNewHex;
extern std::string const kProposalMultiValueHex;
extern std::string const kProposalSignExtHex;
extern std::string const kProposalFloatToIntHex;
extern std::string const kProposalBulkMemoryHex;
extern std::string const kProposalRefTypesHex;
extern std::string const kProposalTailCallHex;
extern std::string const kProposalExtendedConstHex;
extern std::string const kProposalMultiMemoryHex;
extern std::string const kProposalCustomPageSizesHex;
extern std::string const kProposalMemory64Hex;
extern std::string const kProposalWideArithmeticHex;
extern std::string const kTrapDivideBy0Hex;
extern std::string const kTrapIntOverflowHex;
extern std::string const kTrapUnreachableHex;
extern std::string const kTrapNullCallHex;
extern std::string const kTrapFuncSigMismatchHex;
extern std::string const kWasiGetTimeHex;
extern std::string const kWasiPrintHex;
extern std::string const kBadMagicNumberHex;
extern std::string const kBadVersionNumberHex;
extern std::string const kLyingHeaderHex;
extern std::string const kNeverEndingNumberHex;
extern std::string const kVectorLieHex;
extern std::string const kSectionOrderingHex;
extern std::string const kGhostPayloadHex;
extern std::string const kJunkAfterSectionHex;
extern std::string const kInvalidSectionIdHex;
extern std::string const kLocalVariableBombHex;
extern std::string const kDeepRecursionHex;
extern std::string const kInfiniteLoopWasmHex;
extern std::string const kStartLoopHex;
extern std::string const kBadAlignWasmHex;
extern std::string const kThousandParamsHex;
extern std::string const kThousand1ParamsHex;
extern std::string const kLocals10kHex;
extern std::string const kFunctions5kHex;
extern std::string const kOpcReservedHex;
extern std::string const kImpExpHex;

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.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "float_0"
version = "0.0.1"
dependencies = [
"xrpl-wasm-stdlib",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.183"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
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.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
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.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[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?rev=1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?rev=1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
dependencies = [
"xrpl-address-macro",
]

View File

@@ -1,21 +0,0 @@
[package]
name = "float_0"
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", rev = "1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8" }
[profile.dev]
panic = "abort"

View File

@@ -1,57 +0,0 @@
#![cfg_attr(target_arch = "wasm32", no_std)]
use xrpl_std::host::trace::trace;
use xrpl_std::host::{float_compare, float_from_int, float_subtract, FLOAT_ROUNDING_MODES_TO_NEAREST};
// Float size constant (8 bytes mantissa + 4 bytes exponent)
const FLOAT_SIZE: usize = 12;
// FLOAT_ZERO constant
const FLOAT_ZERO: [u8; FLOAT_SIZE] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00];
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
let _ = trace("\n$$$ test_float_0 $$$");
// Test: 10 - 10 should equal 0
let mut f10: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
let mut f_result: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
// Create float from 10
if FLOAT_SIZE as i32 != unsafe { float_from_int(10, f10.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace(" float 10-10: failed");
return 1;
}
// Subtract: 10 - 10 = 0
if FLOAT_SIZE as i32 != unsafe {
float_subtract(
f10.as_ptr(),
FLOAT_SIZE,
f10.as_ptr(),
FLOAT_SIZE,
f_result.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
} {
let _ = trace(" float 10-10: failed");
return 1;
}
// Compare result with zero
if 0 == unsafe { float_compare(f_result.as_ptr(), FLOAT_SIZE, f_result.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" float 0 compare: good");
} else {
let _ = trace(" float 0 compare: bad");
}
// Compare result with FLOAT_ZERO constant
if 0 == unsafe { float_compare(f_result.as_ptr(), FLOAT_SIZE, FLOAT_ZERO.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" FLOAT_ZERO compare: good");
} else {
let _ = trace(" FLOAT_ZERO compare: bad");
}
1
}

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?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
dependencies = [
"bs58",
"quote",
"sha2",
"syn",
]
[[package]]
name = "xrpl-wasm-stdlib"
version = "0.7.1"
source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=u32-buffer#1e5d096f46742ef7fcf1cb6f28a2526a72ed59d8"
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", branch = "u32-buffer" }
[profile.dev]
panic = "abort"

View File

@@ -1,954 +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::decode_hex_32;
use xrpl_std::host::trace::DataRepr::AsHex;
use xrpl_std::host::trace::{trace, trace_data, trace_num, DataRepr};
use xrpl_std::host::{
cache_ledger_obj, float_add, float_compare, float_divide, float_from_int, float_from_uint,
float_multiply, float_pow, float_root, float_subtract,
get_ledger_obj_array_len, get_ledger_obj_field, get_ledger_obj_nested_field,
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,
};
// External host functions not yet in xrpl_std
unsafe extern "C" {
#[link_name = "float_from_stamount"]
fn float_from_stamount(
amount_ptr: *const u8,
amount_len: i32,
out_ptr: *mut u8,
out_len: i32,
rounding: i32,
) -> i32;
#[link_name = "float_from_stnumber"]
fn float_from_stnumber(
number_ptr: *const u8,
number_len: i32,
out_ptr: *mut u8,
out_len: i32,
rounding: i32,
) -> i32;
#[link_name = "float_to_int"]
fn float_to_int(
float_ptr: *const u8,
float_len: i32,
out_ptr: *mut u8,
out_len: i32,
rounding: i32,
) -> i32;
#[link_name = "float_to_mant_exp"]
fn float_to_mant_exp(
float_ptr: *const u8,
float_len: i32,
mantissa_ptr: *mut u8,
mantissa_len: i32,
exponent_ptr: *mut u8,
exponent_len: i32,
) -> i32;
#[link_name = "float_from_mant_exp"]
fn float_from_mant_exp(
mantissa: i64,
exponent: i32,
out_ptr: *mut u8,
out_len: i32,
rounding: i32,
) -> i32;
}
// Float size constant (8 bytes mantissa + 4 bytes exponent)
const FLOAT_SIZE: usize = 12;
// Float constants (8 bytes mantissa + 4 bytes exponent, big-endian)
// FLOAT_ONE: mantissa=0x0DE0B6B3A7640000 (10^18), exponent=0xFFFFFFEE (-18)
const FLOAT_ONE: [u8; FLOAT_SIZE] = [0x0D, 0xE0, 0xB6, 0xB3, 0xA7, 0x64, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE];
// FLOAT_NEGATIVE_ONE: mantissa=0xF21F494C589C0000 (-10^18), exponent=0xFFFFFFEE (-18)
const FLOAT_NEGATIVE_ONE: [u8; FLOAT_SIZE] = [0xF2, 0x1F, 0x49, 0x4C, 0x58, 0x9C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xEE];
// Helper function to trace floats
fn trace_float(msg: &str, f: &[u8; FLOAT_SIZE]) {
let _ = trace(msg);
let _ = trace_data(" ", f, AsHex);
}
fn test_float_from_wasm() -> bool {
let _ = trace("\n$$$ test_float_from_wasm $$$");
let mut all_pass = true;
let mut f: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
if FLOAT_SIZE as i32 == unsafe { float_from_int(12300, f.as_mut_ptr(), FLOAT_SIZE, 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");
all_pass = false;
}
let u64_value: u64 = 12300;
if FLOAT_SIZE as i32 == unsafe {
float_from_uint(
&u64_value as *const u64 as *const u8,
8,
f.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
} {
let _ = trace_float(" float from u64 12300:", &f);
} else {
let _ = trace(" float from u64 12300: failed");
all_pass = false;
}
if FLOAT_SIZE as i32 == unsafe { float_from_mant_exp(123, 2, f.as_mut_ptr(), FLOAT_SIZE as i32, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace_float(" float from exp 2, mantissa 123:", &f);
} else {
let _ = trace(" float from exp 2, mantissa 123: failed");
all_pass = false;
}
let _ = trace_float(" float from const 1:", &FLOAT_ONE);
let _ = trace_float(" float from const -1:", &FLOAT_NEGATIVE_ONE);
all_pass
}
fn test_float_compare() -> bool {
let _ = trace("\n$$$ test_float_compare $$$");
let mut all_pass = true;
let mut f1: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
if FLOAT_SIZE as i32 != unsafe { float_from_int(1, f1.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace(" float from 1: failed");
all_pass = false;
} else {
let _ = trace_float(" float from 1:", &f1);
}
if 0 == unsafe { float_compare(f1.as_ptr(), FLOAT_SIZE, FLOAT_ONE.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" float from 1 == FLOAT_ONE");
} else {
let _ = trace(" float from 1 != FLOAT_ONE, failed");
all_pass = false;
}
if 1 == unsafe { float_compare(f1.as_ptr(), FLOAT_SIZE, FLOAT_NEGATIVE_ONE.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" float from 1 > FLOAT_NEGATIVE_ONE");
} else {
let _ = trace(" float from 1 !> FLOAT_NEGATIVE_ONE, failed");
all_pass = false;
}
if 2 == unsafe { float_compare(FLOAT_NEGATIVE_ONE.as_ptr(), FLOAT_SIZE, f1.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" FLOAT_NEGATIVE_ONE < float from 1");
} else {
let _ = trace(" FLOAT_NEGATIVE_ONE !< float from 1, failed");
all_pass = false;
}
all_pass
}
fn test_float_add_subtract() -> bool {
let _ = trace("\n$$$ test_float_add_subtract $$$");
let mut all_pass = true;
let mut f_compute: [u8; FLOAT_SIZE] = FLOAT_ONE;
for i in 0..9 {
unsafe {
float_add(
f_compute.as_ptr(),
FLOAT_SIZE,
FLOAT_ONE.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f10: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
if FLOAT_SIZE as i32 != unsafe { float_from_int(10, f10.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) } {
let _ = trace(" float from 10: failed");
all_pass = false;
}
if 0 == unsafe { float_compare(f10.as_ptr(), FLOAT_SIZE, f_compute.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" repeated add: good");
} else {
let _ = trace(" repeated add: failed");
all_pass = false;
}
for i in 0..11 {
unsafe {
float_subtract(
f_compute.as_ptr(),
FLOAT_SIZE,
FLOAT_ONE.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
if 0 == unsafe { float_compare(f_compute.as_ptr(), FLOAT_SIZE, FLOAT_NEGATIVE_ONE.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" repeated subtract: good");
} else {
let _ = trace(" repeated subtract: failed");
all_pass = false;
}
all_pass
}
fn test_float_multiply_divide() -> bool {
let _ = trace("\n$$$ test_float_multiply_divide $$$");
let mut all_pass = true;
let mut f10: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(10, f10.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; FLOAT_SIZE] = FLOAT_ONE;
for i in 0..6 {
unsafe {
float_multiply(
f_compute.as_ptr(),
FLOAT_SIZE,
f10.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
// let _ = trace_float(" float:", &f_compute);
}
let mut f1000000: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if 0 == unsafe { float_compare(f1000000.as_ptr(), FLOAT_SIZE, f_compute.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" repeated multiply: good");
} else {
let _ = trace(" repeated multiply: failed");
all_pass = false;
}
for i in 0..7 {
unsafe {
float_divide(
f_compute.as_ptr(),
FLOAT_SIZE,
f10.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
}
let mut f01: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_mant_exp(1, -1, f01.as_mut_ptr(), FLOAT_SIZE as i32, FLOAT_ROUNDING_MODES_TO_NEAREST) };
if 0 == unsafe { float_compare(f_compute.as_ptr(), FLOAT_SIZE, f01.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" repeated divide: good");
} else {
let _ = trace(" repeated divide: failed");
all_pass = false;
}
all_pass
}
fn test_float_pow() -> bool {
let _ = trace("\n$$$ test_float_pow $$$");
let mut all_pass = true;
let mut f_compute: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe {
float_pow(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE,
3,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cube of 1:", &f_compute);
unsafe {
float_pow(
FLOAT_NEGATIVE_ONE.as_ptr(),
FLOAT_SIZE,
6,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th power of -1:", &f_compute);
let mut f9: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(9, f9.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f9.as_ptr(),
FLOAT_SIZE,
2,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 9:", &f_compute);
unsafe {
float_pow(
f9.as_ptr(),
FLOAT_SIZE,
0,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 0th power of 9:", &f_compute);
let mut f0: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(0, f0.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_pow(
f0.as_ptr(),
FLOAT_SIZE,
2,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float square of 0:", &f_compute);
let r = unsafe {
float_pow(
f0.as_ptr(),
FLOAT_SIZE,
0,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_num(
" float 0th power of 0 (expecting INVALID_PARAMS error):",
r as i64,
);
all_pass
}
fn test_float_root() -> bool {
let _ = trace("\n$$$ test_float_root $$$");
let mut all_pass = true;
let mut f9: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(9, f9.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut f_compute: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe {
float_root(
f9.as_ptr(),
FLOAT_SIZE,
2,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float sqrt of 9:", &f_compute);
unsafe {
float_root(
f9.as_ptr(),
FLOAT_SIZE,
3,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 9:", &f_compute);
let mut f1000000: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe {
float_from_int(
1000000,
f1000000.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
unsafe {
float_root(
f1000000.as_ptr(),
FLOAT_SIZE,
3,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float cbrt of 1000000:", &f_compute);
unsafe {
float_root(
f1000000.as_ptr(),
FLOAT_SIZE,
6,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" float 6th root of 1000000:", &f_compute);
all_pass
}
fn test_float_invert() -> bool {
let _ = trace("\n$$$ test_float_invert $$$");
let mut all_pass = true;
let mut f_compute: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
let mut f10: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(10, f10.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE,
f10.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
let _ = trace_float(" invert a float from 10:", &f_compute);
unsafe {
float_divide(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE,
f_compute.as_ptr(),
FLOAT_SIZE,
f_compute.as_mut_ptr(),
FLOAT_SIZE,
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(), FLOAT_SIZE, f_compute.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" invert twice: good");
} else {
let _ = trace(" invert twice: failed");
all_pass = false;
}
all_pass
}
fn test_float_to_int() -> bool {
let _ = trace("\n$$$ test_float_to_int $$$");
let mut all_pass = true;
let mut result: [u8; 8] = [0u8; 8];
// Test converting FLOAT_ONE (value 1) to int
let ret = unsafe {
float_to_int(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let number = i64::from_le_bytes(result);
if number == 1 {
let _ = trace(" float_to_int(1): good");
} else {
let _ = trace(" float_to_int(1): failed");
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(1): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
// Test converting FLOAT_NEGATIVE_ONE (value -1) to int
let ret = unsafe {
float_to_int(
FLOAT_NEGATIVE_ONE.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let number = i64::from_le_bytes(result);
if number == -1 {
let _ = trace(" float_to_int(-1): good");
} else {
let _ = trace(" float_to_int(-1): failed");
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(-1): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
// Test converting a larger number (i64::MAX)
let test_val: i64 = i64::MAX;
let mut f_max: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(test_val, f_max.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let ret = unsafe {
float_to_int(
f_max.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let number = i64::from_le_bytes(result);
if number == test_val {
let _ = trace(" float_to_int(i64::MAX): good");
} else {
let _ = trace(" float_to_int(i64::MAX): failed");
let _ = trace_num(" expected:", test_val);
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(i64::MAX): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
// Test converting zero
let mut f0: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(0, f0.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let ret = unsafe {
float_to_int(
f0.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let number = i64::from_le_bytes(result);
if number == 0 {
let _ = trace(" float_to_int(0): good");
} else {
let _ = trace(" float_to_int(0): failed");
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(0): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
// Test rounding with fractional value (0.1)
let mut f01: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_mant_exp(1, -1, f01.as_mut_ptr(), FLOAT_SIZE as i32, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let ret = unsafe {
float_to_int(
f01.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8 as i32,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 as i32 {
let number = i64::from_le_bytes(result);
if number == 0 {
let _ = trace(" float_to_int(0.1, to_nearest): good");
} else {
let _ = trace(" float_to_int(0.1, to_nearest): failed");
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(0.1, to_nearest): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
// Test rounding mode 1 (towards_zero)
let ret = unsafe {
float_to_int(
f01.as_ptr(),
FLOAT_SIZE as i32,
result.as_mut_ptr(),
8 as i32,
1
)
};
if ret == 8 as i32 {
let number = i64::from_le_bytes(result);
if number == 0 {
let _ = trace(" float_to_int(0.1, towards_zero): good");
} else {
let _ = trace(" float_to_int(0.1, towards_zero): failed");
let _ = trace_num(" got:", number);
all_pass = false;
}
} else {
let _ = trace(" float_to_int(0.1, towards_zero): failed with error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
all_pass
}
fn test_float_to_mant_exp() -> bool {
let _ = trace("\n$$$ test_float_to_mant_exp $$$");
let mut all_pass = true;
// Test with FLOAT_ONE (value 1)
let mut mantissa_bytes: [u8; 8] = [0u8; 8];
let mut exponent_bytes: [u8; 4] = [0u8; 4];
let result = unsafe {
float_to_mant_exp(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE as i32,
mantissa_bytes.as_mut_ptr(),
8,
exponent_bytes.as_mut_ptr(),
4,
)
};
if result == FLOAT_SIZE as i32 {
let mantissa = i64::from_le_bytes(mantissa_bytes);
let exponent = i32::from_le_bytes(exponent_bytes);
if mantissa == 1000000000000000000 && exponent == -18 {
let _ = trace(" float_to_mant_exp(1): good");
} else {
let _ = trace(" float_to_mant_exp(1): failed");
let _ = trace_num(" expected mantissa 1000000000000000000, got:", mantissa);
let _ = trace_num(" expected exponent -18, got:", exponent as i64);
all_pass = false;
}
} else {
let _ = trace(" float_to_mant_exp(1): failed with error");
let _ = trace_num(" error code:", result as i64);
all_pass = false;
}
// Test with FLOAT_NEGATIVE_ONE (value -1)
let mut mantissa_bytes: [u8; 8] = [0u8; 8];
let mut exponent_bytes: [u8; 4] = [0u8; 4];
let result = unsafe {
float_to_mant_exp(
FLOAT_NEGATIVE_ONE.as_ptr(),
FLOAT_SIZE as i32,
mantissa_bytes.as_mut_ptr(),
8,
exponent_bytes.as_mut_ptr(),
4,
)
};
if result == FLOAT_SIZE as i32 {
let mantissa = i64::from_le_bytes(mantissa_bytes);
let exponent = i32::from_le_bytes(exponent_bytes);
if mantissa == -1000000000000000000 && exponent == -18 {
let _ = trace(" float_to_mant_exp(-1): good");
} else {
let _ = trace(" float_to_mant_exp(-1): failed");
let _ = trace_num(" expected mantissa -1000000000000000000, got:", mantissa);
let _ = trace_num(" expected exponent -18, got:", exponent as i64);
all_pass = false;
}
} else {
let _ = trace(" float_to_mant_exp(-1): failed with error");
let _ = trace_num(" error code:", result as i64);
all_pass = false;
}
// Test with a float created from int (10)
let mut f10: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(10, f10.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut mantissa_bytes: [u8; 8] = [0u8; 8];
let mut exponent_bytes: [u8; 4] = [0u8; 4];
let result = unsafe {
float_to_mant_exp(
f10.as_ptr(),
FLOAT_SIZE as i32,
mantissa_bytes.as_mut_ptr(),
8,
exponent_bytes.as_mut_ptr(),
4,
)
};
if result == FLOAT_SIZE as i32 {
let mantissa = i64::from_le_bytes(mantissa_bytes);
let exponent = i32::from_le_bytes(exponent_bytes);
if mantissa == 1000000000000000000 && exponent == -17 {
let _ = trace(" float_to_mant_exp(10): good");
} else {
let _ = trace(" float_to_mant_exp(10): failed");
let _ = trace_num(" expected mantissa 1000000000000000000, got:", mantissa);
let _ = trace_num(" expected exponent -17, got:", exponent as i64);
all_pass = false;
}
} else {
let _ = trace(" float_to_mant_exp(10): failed with error");
let _ = trace_num(" error code:", result as i64);
all_pass = false;
}
// Test with zero
let mut f0: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
unsafe { float_from_int(0, f0.as_mut_ptr(), FLOAT_SIZE, FLOAT_ROUNDING_MODES_TO_NEAREST) };
let mut mantissa_bytes: [u8; 8] = [0u8; 8];
let mut exponent_bytes: [u8; 4] = [0u8; 4];
let result = unsafe {
float_to_mant_exp(
f0.as_ptr(),
FLOAT_SIZE as i32,
mantissa_bytes.as_mut_ptr(),
8,
exponent_bytes.as_mut_ptr(),
4,
)
};
if result == FLOAT_SIZE as i32 {
let mantissa = i64::from_le_bytes(mantissa_bytes);
let exponent = i32::from_le_bytes(exponent_bytes);
if mantissa == 0 && exponent == -2147483648 {
let _ = trace(" float_to_mant_exp(0): good");
} else {
let _ = trace(" float_to_mant_exp(0): failed");
let _ = trace_num(" expected mantissa 0, got:", mantissa);
let _ = trace_num(" expected exponent -2147483648, got:", exponent as i64);
all_pass = false;
}
} else {
let _ = trace(" float_to_mant_exp(0): failed with error");
let _ = trace_num(" error code:", result as i64);
all_pass = false;
}
all_pass
}
fn test_float_from_stamount() -> bool {
let _ = trace("\n$$$ test_float_from_stamount $$$");
let mut all_pass = true;
// STAmount is serialized as:
// - 1 byte: type/flags
// - 8 bytes: amount (for XRP) or mantissa (for IOU)
// - For IOU: additional currency and issuer fields
// Create an XRP amount: 100 XRP = 100,000,000 drops
// XRP format: bit 62 clear (not IOU), bit 63 clear (not negative)
// Amount in drops: 100,000,000 = 0x05F5E100
let xrp_amount: [u8; 8] = [
0x40, 0x00, 0x00, 0x00, 0x05, 0xF5, 0xE1, 0x00
];
let mut f_result: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
let result_size = unsafe {
float_from_stamount(
xrp_amount.as_ptr(),
8,
f_result.as_mut_ptr(),
FLOAT_SIZE as i32,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if result_size == FLOAT_SIZE as i32 {
let _ = trace_float(" float from XRP amount (100 XRP):", &f_result);
// Convert back to int to verify
let mut int_bytes: [u8; 8] = [0u8; 8];
let ret = unsafe {
float_to_int(
f_result.as_ptr(),
FLOAT_SIZE as i32,
int_bytes.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let int_val = i64::from_le_bytes(int_bytes);
if int_val == 100000000 {
let _ = trace(" XRP amount conversion: good");
} else {
let _ = trace(" XRP amount conversion: failed");
let _ = trace_num(" expected 100000000, got:", int_val);
all_pass = false;
}
} else {
let _ = trace(" XRP amount conversion: failed - float_to_int error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
} else {
let _ = trace(" float from XRP amount: failed");
let _ = trace_num(" result_size:", result_size as i64);
all_pass = false;
}
all_pass
}
fn test_float_from_stnumber() -> bool {
let _ = trace("\n$$$ test_float_from_stnumber $$$");
let mut all_pass = true;
// STNumber is serialized as:
// - 8 bytes: mantissa (big-endian signed int64)
// - 4 bytes: exponent (big-endian signed int32)
// Create STNumber for value 123 (mantissa=123*10^18, exponent=-18)
// mantissa = 123000000000000000000 = 0x6ADF37F675EF6B28000
// But we need to fit in int64, so use mantissa=123*10^15, exponent=-15
// 123*10^15 = 123000000000000000 = 0x01B69B4BA630F34000
let stnumber_123: [u8; 12] = [
0x01, 0xB6, 0x9B, 0x4B, 0xA6, 0x30, 0xF3, 0x40, // mantissa
0xFF, 0xFF, 0xFF, 0xF1, // exponent = -15
];
let mut f_result: [u8; FLOAT_SIZE] = [0u8; FLOAT_SIZE];
let result_size = unsafe {
float_from_stnumber(
stnumber_123.as_ptr(),
12,
f_result.as_mut_ptr(),
FLOAT_SIZE as i32,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if result_size == FLOAT_SIZE as i32 {
let _ = trace_float(" float from STNumber (123):", &f_result);
// Convert back to int to verify
let mut int_bytes: [u8; 8] = [0u8; 8];
let ret = unsafe {
float_to_int(
f_result.as_ptr(),
FLOAT_SIZE as i32,
int_bytes.as_mut_ptr(),
8,
FLOAT_ROUNDING_MODES_TO_NEAREST
)
};
if ret == 8 {
let int_val = i64::from_le_bytes(int_bytes);
if int_val == 123 {
let _ = trace(" STNumber conversion: good");
} else {
let _ = trace(" STNumber conversion: failed");
let _ = trace_num(" expected 123, got:", int_val);
all_pass = false;
}
} else {
let _ = trace(" STNumber conversion: failed - float_to_int error");
let _ = trace_num(" error code:", ret as i64);
all_pass = false;
}
} else {
let _ = trace(" float from STNumber: failed");
let _ = trace_num(" result_size:", result_size as i64);
all_pass = false;
}
// Test with FLOAT_ONE constant (which is already in STNumber format)
let result_size = unsafe {
float_from_stnumber(
FLOAT_ONE.as_ptr(),
FLOAT_SIZE as i32,
f_result.as_mut_ptr(),
FLOAT_SIZE as i32,
FLOAT_ROUNDING_MODES_TO_NEAREST,
)
};
if result_size == FLOAT_SIZE as i32 {
let _ = trace_float(" float from STNumber (1):", &f_result);
// Should match FLOAT_ONE
if 0 == unsafe { float_compare(f_result.as_ptr(), FLOAT_SIZE, FLOAT_ONE.as_ptr(), FLOAT_SIZE) } {
let _ = trace(" STNumber(1) == FLOAT_ONE: good");
} else {
let _ = trace(" STNumber(1) == FLOAT_ONE: failed");
all_pass = false;
}
} else {
let _ = trace(" float from STNumber(1): failed");
all_pass = false;
}
all_pass
}
#[unsafe(no_mangle)]
pub extern "C" fn finish() -> i32 {
let mut all_pass = true;
all_pass &= test_float_from_wasm();
all_pass &= test_float_compare();
all_pass &= test_float_add_subtract();
all_pass &= test_float_multiply_divide();
all_pass &= test_float_pow();
all_pass &= test_float_root();
all_pass &= test_float_invert();
all_pass &= test_float_to_int();
all_pass &= test_float_to_mant_exp();
all_pass &= test_float_from_stamount();
all_pass &= test_float_from_stnumber();
if all_pass { 1 } else { 0 }
}

View File

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

View File

@@ -1,11 +1,11 @@
#include <stdint.h>
int32_t get_ledger_sqn(uint8_t *, int32_t);
int32_t ldgr_index(uint8_t *, int32_t);
int finish()
{
uint32_t sqn;
int32_t result = get_ledger_sqn((uint8_t *)&sqn, sizeof(sqn));
int32_t result = ldgr_index((uint8_t *)&sqn, sizeof(sqn));
if (result < 0)
return result;

View File

@@ -1,264 +0,0 @@
// clang-format off
#include <stdint.h>
int32_t test(
int32_t p0, int32_t p1, int32_t p2, int32_t p3, int32_t p4, int32_t p5, int32_t p6, int32_t p7
, int32_t p8, int32_t p9, int32_t p10, int32_t p11, int32_t p12, int32_t p13, int32_t p14, int32_t p15
, int32_t p16, int32_t p17, int32_t p18, int32_t p19, int32_t p20, int32_t p21, int32_t p22, int32_t p23
, int32_t p24, int32_t p25, int32_t p26, int32_t p27, int32_t p28, int32_t p29, int32_t p30, int32_t p31
, int32_t p32, int32_t p33, int32_t p34, int32_t p35, int32_t p36, int32_t p37, int32_t p38, int32_t p39
, int32_t p40, int32_t p41, int32_t p42, int32_t p43, int32_t p44, int32_t p45, int32_t p46, int32_t p47
, int32_t p48, int32_t p49, int32_t p50, int32_t p51, int32_t p52, int32_t p53, int32_t p54, int32_t p55
, int32_t p56, int32_t p57, int32_t p58, int32_t p59, int32_t p60, int32_t p61, int32_t p62, int32_t p63
, int32_t p64, int32_t p65, int32_t p66, int32_t p67, int32_t p68, int32_t p69, int32_t p70, int32_t p71
, int32_t p72, int32_t p73, int32_t p74, int32_t p75, int32_t p76, int32_t p77, int32_t p78, int32_t p79
, int32_t p80, int32_t p81, int32_t p82, int32_t p83, int32_t p84, int32_t p85, int32_t p86, int32_t p87
, int32_t p88, int32_t p89, int32_t p90, int32_t p91, int32_t p92, int32_t p93, int32_t p94, int32_t p95
, int32_t p96, int32_t p97, int32_t p98, int32_t p99, int32_t p100, int32_t p101, int32_t p102, int32_t p103
, int32_t p104, int32_t p105, int32_t p106, int32_t p107, int32_t p108, int32_t p109, int32_t p110, int32_t p111
, int32_t p112, int32_t p113, int32_t p114, int32_t p115, int32_t p116, int32_t p117, int32_t p118, int32_t p119
, int32_t p120, int32_t p121, int32_t p122, int32_t p123, int32_t p124, int32_t p125, int32_t p126, int32_t p127
, int32_t p128, int32_t p129, int32_t p130, int32_t p131, int32_t p132, int32_t p133, int32_t p134, int32_t p135
, int32_t p136, int32_t p137, int32_t p138, int32_t p139, int32_t p140, int32_t p141, int32_t p142, int32_t p143
, int32_t p144, int32_t p145, int32_t p146, int32_t p147, int32_t p148, int32_t p149, int32_t p150, int32_t p151
, int32_t p152, int32_t p153, int32_t p154, int32_t p155, int32_t p156, int32_t p157, int32_t p158, int32_t p159
, int32_t p160, int32_t p161, int32_t p162, int32_t p163, int32_t p164, int32_t p165, int32_t p166, int32_t p167
, int32_t p168, int32_t p169, int32_t p170, int32_t p171, int32_t p172, int32_t p173, int32_t p174, int32_t p175
, int32_t p176, int32_t p177, int32_t p178, int32_t p179, int32_t p180, int32_t p181, int32_t p182, int32_t p183
, int32_t p184, int32_t p185, int32_t p186, int32_t p187, int32_t p188, int32_t p189, int32_t p190, int32_t p191
, int32_t p192, int32_t p193, int32_t p194, int32_t p195, int32_t p196, int32_t p197, int32_t p198, int32_t p199
, int32_t p200, int32_t p201, int32_t p202, int32_t p203, int32_t p204, int32_t p205, int32_t p206, int32_t p207
, int32_t p208, int32_t p209, int32_t p210, int32_t p211, int32_t p212, int32_t p213, int32_t p214, int32_t p215
, int32_t p216, int32_t p217, int32_t p218, int32_t p219, int32_t p220, int32_t p221, int32_t p222, int32_t p223
, int32_t p224, int32_t p225, int32_t p226, int32_t p227, int32_t p228, int32_t p229, int32_t p230, int32_t p231
, int32_t p232, int32_t p233, int32_t p234, int32_t p235, int32_t p236, int32_t p237, int32_t p238, int32_t p239
, int32_t p240, int32_t p241, int32_t p242, int32_t p243, int32_t p244, int32_t p245, int32_t p246, int32_t p247
, int32_t p248, int32_t p249, int32_t p250, int32_t p251, int32_t p252, int32_t p253, int32_t p254, int32_t p255
, int32_t p256, int32_t p257, int32_t p258, int32_t p259, int32_t p260, int32_t p261, int32_t p262, int32_t p263
, int32_t p264, int32_t p265, int32_t p266, int32_t p267, int32_t p268, int32_t p269, int32_t p270, int32_t p271
, int32_t p272, int32_t p273, int32_t p274, int32_t p275, int32_t p276, int32_t p277, int32_t p278, int32_t p279
, int32_t p280, int32_t p281, int32_t p282, int32_t p283, int32_t p284, int32_t p285, int32_t p286, int32_t p287
, int32_t p288, int32_t p289, int32_t p290, int32_t p291, int32_t p292, int32_t p293, int32_t p294, int32_t p295
, int32_t p296, int32_t p297, int32_t p298, int32_t p299, int32_t p300, int32_t p301, int32_t p302, int32_t p303
, int32_t p304, int32_t p305, int32_t p306, int32_t p307, int32_t p308, int32_t p309, int32_t p310, int32_t p311
, int32_t p312, int32_t p313, int32_t p314, int32_t p315, int32_t p316, int32_t p317, int32_t p318, int32_t p319
, int32_t p320, int32_t p321, int32_t p322, int32_t p323, int32_t p324, int32_t p325, int32_t p326, int32_t p327
, int32_t p328, int32_t p329, int32_t p330, int32_t p331, int32_t p332, int32_t p333, int32_t p334, int32_t p335
, int32_t p336, int32_t p337, int32_t p338, int32_t p339, int32_t p340, int32_t p341, int32_t p342, int32_t p343
, int32_t p344, int32_t p345, int32_t p346, int32_t p347, int32_t p348, int32_t p349, int32_t p350, int32_t p351
, int32_t p352, int32_t p353, int32_t p354, int32_t p355, int32_t p356, int32_t p357, int32_t p358, int32_t p359
, int32_t p360, int32_t p361, int32_t p362, int32_t p363, int32_t p364, int32_t p365, int32_t p366, int32_t p367
, int32_t p368, int32_t p369, int32_t p370, int32_t p371, int32_t p372, int32_t p373, int32_t p374, int32_t p375
, int32_t p376, int32_t p377, int32_t p378, int32_t p379, int32_t p380, int32_t p381, int32_t p382, int32_t p383
, int32_t p384, int32_t p385, int32_t p386, int32_t p387, int32_t p388, int32_t p389, int32_t p390, int32_t p391
, int32_t p392, int32_t p393, int32_t p394, int32_t p395, int32_t p396, int32_t p397, int32_t p398, int32_t p399
, int32_t p400, int32_t p401, int32_t p402, int32_t p403, int32_t p404, int32_t p405, int32_t p406, int32_t p407
, int32_t p408, int32_t p409, int32_t p410, int32_t p411, int32_t p412, int32_t p413, int32_t p414, int32_t p415
, int32_t p416, int32_t p417, int32_t p418, int32_t p419, int32_t p420, int32_t p421, int32_t p422, int32_t p423
, int32_t p424, int32_t p425, int32_t p426, int32_t p427, int32_t p428, int32_t p429, int32_t p430, int32_t p431
, int32_t p432, int32_t p433, int32_t p434, int32_t p435, int32_t p436, int32_t p437, int32_t p438, int32_t p439
, int32_t p440, int32_t p441, int32_t p442, int32_t p443, int32_t p444, int32_t p445, int32_t p446, int32_t p447
, int32_t p448, int32_t p449, int32_t p450, int32_t p451, int32_t p452, int32_t p453, int32_t p454, int32_t p455
, int32_t p456, int32_t p457, int32_t p458, int32_t p459, int32_t p460, int32_t p461, int32_t p462, int32_t p463
, int32_t p464, int32_t p465, int32_t p466, int32_t p467, int32_t p468, int32_t p469, int32_t p470, int32_t p471
, int32_t p472, int32_t p473, int32_t p474, int32_t p475, int32_t p476, int32_t p477, int32_t p478, int32_t p479
, int32_t p480, int32_t p481, int32_t p482, int32_t p483, int32_t p484, int32_t p485, int32_t p486, int32_t p487
, int32_t p488, int32_t p489, int32_t p490, int32_t p491, int32_t p492, int32_t p493, int32_t p494, int32_t p495
, int32_t p496, int32_t p497, int32_t p498, int32_t p499, int32_t p500, int32_t p501, int32_t p502, int32_t p503
, int32_t p504, int32_t p505, int32_t p506, int32_t p507, int32_t p508, int32_t p509, int32_t p510, int32_t p511
, int32_t p512, int32_t p513, int32_t p514, int32_t p515, int32_t p516, int32_t p517, int32_t p518, int32_t p519
, int32_t p520, int32_t p521, int32_t p522, int32_t p523, int32_t p524, int32_t p525, int32_t p526, int32_t p527
, int32_t p528, int32_t p529, int32_t p530, int32_t p531, int32_t p532, int32_t p533, int32_t p534, int32_t p535
, int32_t p536, int32_t p537, int32_t p538, int32_t p539, int32_t p540, int32_t p541, int32_t p542, int32_t p543
, int32_t p544, int32_t p545, int32_t p546, int32_t p547, int32_t p548, int32_t p549, int32_t p550, int32_t p551
, int32_t p552, int32_t p553, int32_t p554, int32_t p555, int32_t p556, int32_t p557, int32_t p558, int32_t p559
, int32_t p560, int32_t p561, int32_t p562, int32_t p563, int32_t p564, int32_t p565, int32_t p566, int32_t p567
, int32_t p568, int32_t p569, int32_t p570, int32_t p571, int32_t p572, int32_t p573, int32_t p574, int32_t p575
, int32_t p576, int32_t p577, int32_t p578, int32_t p579, int32_t p580, int32_t p581, int32_t p582, int32_t p583
, int32_t p584, int32_t p585, int32_t p586, int32_t p587, int32_t p588, int32_t p589, int32_t p590, int32_t p591
, int32_t p592, int32_t p593, int32_t p594, int32_t p595, int32_t p596, int32_t p597, int32_t p598, int32_t p599
, int32_t p600, int32_t p601, int32_t p602, int32_t p603, int32_t p604, int32_t p605, int32_t p606, int32_t p607
, int32_t p608, int32_t p609, int32_t p610, int32_t p611, int32_t p612, int32_t p613, int32_t p614, int32_t p615
, int32_t p616, int32_t p617, int32_t p618, int32_t p619, int32_t p620, int32_t p621, int32_t p622, int32_t p623
, int32_t p624, int32_t p625, int32_t p626, int32_t p627, int32_t p628, int32_t p629, int32_t p630, int32_t p631
, int32_t p632, int32_t p633, int32_t p634, int32_t p635, int32_t p636, int32_t p637, int32_t p638, int32_t p639
, int32_t p640, int32_t p641, int32_t p642, int32_t p643, int32_t p644, int32_t p645, int32_t p646, int32_t p647
, int32_t p648, int32_t p649, int32_t p650, int32_t p651, int32_t p652, int32_t p653, int32_t p654, int32_t p655
, int32_t p656, int32_t p657, int32_t p658, int32_t p659, int32_t p660, int32_t p661, int32_t p662, int32_t p663
, int32_t p664, int32_t p665, int32_t p666, int32_t p667, int32_t p668, int32_t p669, int32_t p670, int32_t p671
, int32_t p672, int32_t p673, int32_t p674, int32_t p675, int32_t p676, int32_t p677, int32_t p678, int32_t p679
, int32_t p680, int32_t p681, int32_t p682, int32_t p683, int32_t p684, int32_t p685, int32_t p686, int32_t p687
, int32_t p688, int32_t p689, int32_t p690, int32_t p691, int32_t p692, int32_t p693, int32_t p694, int32_t p695
, int32_t p696, int32_t p697, int32_t p698, int32_t p699, int32_t p700, int32_t p701, int32_t p702, int32_t p703
, int32_t p704, int32_t p705, int32_t p706, int32_t p707, int32_t p708, int32_t p709, int32_t p710, int32_t p711
, int32_t p712, int32_t p713, int32_t p714, int32_t p715, int32_t p716, int32_t p717, int32_t p718, int32_t p719
, int32_t p720, int32_t p721, int32_t p722, int32_t p723, int32_t p724, int32_t p725, int32_t p726, int32_t p727
, int32_t p728, int32_t p729, int32_t p730, int32_t p731, int32_t p732, int32_t p733, int32_t p734, int32_t p735
, int32_t p736, int32_t p737, int32_t p738, int32_t p739, int32_t p740, int32_t p741, int32_t p742, int32_t p743
, int32_t p744, int32_t p745, int32_t p746, int32_t p747, int32_t p748, int32_t p749, int32_t p750, int32_t p751
, int32_t p752, int32_t p753, int32_t p754, int32_t p755, int32_t p756, int32_t p757, int32_t p758, int32_t p759
, int32_t p760, int32_t p761, int32_t p762, int32_t p763, int32_t p764, int32_t p765, int32_t p766, int32_t p767
, int32_t p768, int32_t p769, int32_t p770, int32_t p771, int32_t p772, int32_t p773, int32_t p774, int32_t p775
, int32_t p776, int32_t p777, int32_t p778, int32_t p779, int32_t p780, int32_t p781, int32_t p782, int32_t p783
, int32_t p784, int32_t p785, int32_t p786, int32_t p787, int32_t p788, int32_t p789, int32_t p790, int32_t p791
, int32_t p792, int32_t p793, int32_t p794, int32_t p795, int32_t p796, int32_t p797, int32_t p798, int32_t p799
, int32_t p800, int32_t p801, int32_t p802, int32_t p803, int32_t p804, int32_t p805, int32_t p806, int32_t p807
, int32_t p808, int32_t p809, int32_t p810, int32_t p811, int32_t p812, int32_t p813, int32_t p814, int32_t p815
, int32_t p816, int32_t p817, int32_t p818, int32_t p819, int32_t p820, int32_t p821, int32_t p822, int32_t p823
, int32_t p824, int32_t p825, int32_t p826, int32_t p827, int32_t p828, int32_t p829, int32_t p830, int32_t p831
, int32_t p832, int32_t p833, int32_t p834, int32_t p835, int32_t p836, int32_t p837, int32_t p838, int32_t p839
, int32_t p840, int32_t p841, int32_t p842, int32_t p843, int32_t p844, int32_t p845, int32_t p846, int32_t p847
, int32_t p848, int32_t p849, int32_t p850, int32_t p851, int32_t p852, int32_t p853, int32_t p854, int32_t p855
, int32_t p856, int32_t p857, int32_t p858, int32_t p859, int32_t p860, int32_t p861, int32_t p862, int32_t p863
, int32_t p864, int32_t p865, int32_t p866, int32_t p867, int32_t p868, int32_t p869, int32_t p870, int32_t p871
, int32_t p872, int32_t p873, int32_t p874, int32_t p875, int32_t p876, int32_t p877, int32_t p878, int32_t p879
, int32_t p880, int32_t p881, int32_t p882, int32_t p883, int32_t p884, int32_t p885, int32_t p886, int32_t p887
, int32_t p888, int32_t p889, int32_t p890, int32_t p891, int32_t p892, int32_t p893, int32_t p894, int32_t p895
, int32_t p896, int32_t p897, int32_t p898, int32_t p899, int32_t p900, int32_t p901, int32_t p902, int32_t p903
, int32_t p904, int32_t p905, int32_t p906, int32_t p907, int32_t p908, int32_t p909, int32_t p910, int32_t p911
, int32_t p912, int32_t p913, int32_t p914, int32_t p915, int32_t p916, int32_t p917, int32_t p918, int32_t p919
, int32_t p920, int32_t p921, int32_t p922, int32_t p923, int32_t p924, int32_t p925, int32_t p926, int32_t p927
, int32_t p928, int32_t p929, int32_t p930, int32_t p931, int32_t p932, int32_t p933, int32_t p934, int32_t p935
, int32_t p936, int32_t p937, int32_t p938, int32_t p939, int32_t p940, int32_t p941, int32_t p942, int32_t p943
, int32_t p944, int32_t p945, int32_t p946, int32_t p947, int32_t p948, int32_t p949, int32_t p950, int32_t p951
, int32_t p952, int32_t p953, int32_t p954, int32_t p955, int32_t p956, int32_t p957, int32_t p958, int32_t p959
, int32_t p960, int32_t p961, int32_t p962, int32_t p963, int32_t p964, int32_t p965, int32_t p966, int32_t p967
, int32_t p968, int32_t p969, int32_t p970, int32_t p971, int32_t p972, int32_t p973, int32_t p974, int32_t p975
, int32_t p976, int32_t p977, int32_t p978, int32_t p979, int32_t p980, int32_t p981, int32_t p982, int32_t p983
, int32_t p984, int32_t p985, int32_t p986, int32_t p987, int32_t p988, int32_t p989, int32_t p990, int32_t p991
, int32_t p992, int32_t p993, int32_t p994, int32_t p995, int32_t p996, int32_t p997, int32_t p998, int32_t p999
, int32_t p1000
)
{
int32_t x;
x = p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7
+ p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15
+ p16 + p17 + p18 + p19 + p20 + p21 + p22 + p23
+ p24 + p25 + p26 + p27 + p28 + p29 + p30 + p31
+ p32 + p33 + p34 + p35 + p36 + p37 + p38 + p39
+ p40 + p41 + p42 + p43 + p44 + p45 + p46 + p47
+ p48 + p49 + p50 + p51 + p52 + p53 + p54 + p55
+ p56 + p57 + p58 + p59 + p60 + p61 + p62 + p63
+ p64 + p65 + p66 + p67 + p68 + p69 + p70 + p71
+ p72 + p73 + p74 + p75 + p76 + p77 + p78 + p79
+ p80 + p81 + p82 + p83 + p84 + p85 + p86 + p87
+ p88 + p89 + p90 + p91 + p92 + p93 + p94 + p95
+ p96 + p97 + p98 + p99 + p100 + p101 + p102 + p103
+ p104 + p105 + p106 + p107 + p108 + p109 + p110 + p111
+ p112 + p113 + p114 + p115 + p116 + p117 + p118 + p119
+ p120 + p121 + p122 + p123 + p124 + p125 + p126 + p127
+ p128 + p129 + p130 + p131 + p132 + p133 + p134 + p135
+ p136 + p137 + p138 + p139 + p140 + p141 + p142 + p143
+ p144 + p145 + p146 + p147 + p148 + p149 + p150 + p151
+ p152 + p153 + p154 + p155 + p156 + p157 + p158 + p159
+ p160 + p161 + p162 + p163 + p164 + p165 + p166 + p167
+ p168 + p169 + p170 + p171 + p172 + p173 + p174 + p175
+ p176 + p177 + p178 + p179 + p180 + p181 + p182 + p183
+ p184 + p185 + p186 + p187 + p188 + p189 + p190 + p191
+ p192 + p193 + p194 + p195 + p196 + p197 + p198 + p199
+ p200 + p201 + p202 + p203 + p204 + p205 + p206 + p207
+ p208 + p209 + p210 + p211 + p212 + p213 + p214 + p215
+ p216 + p217 + p218 + p219 + p220 + p221 + p222 + p223
+ p224 + p225 + p226 + p227 + p228 + p229 + p230 + p231
+ p232 + p233 + p234 + p235 + p236 + p237 + p238 + p239
+ p240 + p241 + p242 + p243 + p244 + p245 + p246 + p247
+ p248 + p249 + p250 + p251 + p252 + p253 + p254 + p255
+ p256 + p257 + p258 + p259 + p260 + p261 + p262 + p263
+ p264 + p265 + p266 + p267 + p268 + p269 + p270 + p271
+ p272 + p273 + p274 + p275 + p276 + p277 + p278 + p279
+ p280 + p281 + p282 + p283 + p284 + p285 + p286 + p287
+ p288 + p289 + p290 + p291 + p292 + p293 + p294 + p295
+ p296 + p297 + p298 + p299 + p300 + p301 + p302 + p303
+ p304 + p305 + p306 + p307 + p308 + p309 + p310 + p311
+ p312 + p313 + p314 + p315 + p316 + p317 + p318 + p319
+ p320 + p321 + p322 + p323 + p324 + p325 + p326 + p327
+ p328 + p329 + p330 + p331 + p332 + p333 + p334 + p335
+ p336 + p337 + p338 + p339 + p340 + p341 + p342 + p343
+ p344 + p345 + p346 + p347 + p348 + p349 + p350 + p351
+ p352 + p353 + p354 + p355 + p356 + p357 + p358 + p359
+ p360 + p361 + p362 + p363 + p364 + p365 + p366 + p367
+ p368 + p369 + p370 + p371 + p372 + p373 + p374 + p375
+ p376 + p377 + p378 + p379 + p380 + p381 + p382 + p383
+ p384 + p385 + p386 + p387 + p388 + p389 + p390 + p391
+ p392 + p393 + p394 + p395 + p396 + p397 + p398 + p399
+ p400 + p401 + p402 + p403 + p404 + p405 + p406 + p407
+ p408 + p409 + p410 + p411 + p412 + p413 + p414 + p415
+ p416 + p417 + p418 + p419 + p420 + p421 + p422 + p423
+ p424 + p425 + p426 + p427 + p428 + p429 + p430 + p431
+ p432 + p433 + p434 + p435 + p436 + p437 + p438 + p439
+ p440 + p441 + p442 + p443 + p444 + p445 + p446 + p447
+ p448 + p449 + p450 + p451 + p452 + p453 + p454 + p455
+ p456 + p457 + p458 + p459 + p460 + p461 + p462 + p463
+ p464 + p465 + p466 + p467 + p468 + p469 + p470 + p471
+ p472 + p473 + p474 + p475 + p476 + p477 + p478 + p479
+ p480 + p481 + p482 + p483 + p484 + p485 + p486 + p487
+ p488 + p489 + p490 + p491 + p492 + p493 + p494 + p495
+ p496 + p497 + p498 + p499 + p500 + p501 + p502 + p503
+ p504 + p505 + p506 + p507 + p508 + p509 + p510 + p511
+ p512 + p513 + p514 + p515 + p516 + p517 + p518 + p519
+ p520 + p521 + p522 + p523 + p524 + p525 + p526 + p527
+ p528 + p529 + p530 + p531 + p532 + p533 + p534 + p535
+ p536 + p537 + p538 + p539 + p540 + p541 + p542 + p543
+ p544 + p545 + p546 + p547 + p548 + p549 + p550 + p551
+ p552 + p553 + p554 + p555 + p556 + p557 + p558 + p559
+ p560 + p561 + p562 + p563 + p564 + p565 + p566 + p567
+ p568 + p569 + p570 + p571 + p572 + p573 + p574 + p575
+ p576 + p577 + p578 + p579 + p580 + p581 + p582 + p583
+ p584 + p585 + p586 + p587 + p588 + p589 + p590 + p591
+ p592 + p593 + p594 + p595 + p596 + p597 + p598 + p599
+ p600 + p601 + p602 + p603 + p604 + p605 + p606 + p607
+ p608 + p609 + p610 + p611 + p612 + p613 + p614 + p615
+ p616 + p617 + p618 + p619 + p620 + p621 + p622 + p623
+ p624 + p625 + p626 + p627 + p628 + p629 + p630 + p631
+ p632 + p633 + p634 + p635 + p636 + p637 + p638 + p639
+ p640 + p641 + p642 + p643 + p644 + p645 + p646 + p647
+ p648 + p649 + p650 + p651 + p652 + p653 + p654 + p655
+ p656 + p657 + p658 + p659 + p660 + p661 + p662 + p663
+ p664 + p665 + p666 + p667 + p668 + p669 + p670 + p671
+ p672 + p673 + p674 + p675 + p676 + p677 + p678 + p679
+ p680 + p681 + p682 + p683 + p684 + p685 + p686 + p687
+ p688 + p689 + p690 + p691 + p692 + p693 + p694 + p695
+ p696 + p697 + p698 + p699 + p700 + p701 + p702 + p703
+ p704 + p705 + p706 + p707 + p708 + p709 + p710 + p711
+ p712 + p713 + p714 + p715 + p716 + p717 + p718 + p719
+ p720 + p721 + p722 + p723 + p724 + p725 + p726 + p727
+ p728 + p729 + p730 + p731 + p732 + p733 + p734 + p735
+ p736 + p737 + p738 + p739 + p740 + p741 + p742 + p743
+ p744 + p745 + p746 + p747 + p748 + p749 + p750 + p751
+ p752 + p753 + p754 + p755 + p756 + p757 + p758 + p759
+ p760 + p761 + p762 + p763 + p764 + p765 + p766 + p767
+ p768 + p769 + p770 + p771 + p772 + p773 + p774 + p775
+ p776 + p777 + p778 + p779 + p780 + p781 + p782 + p783
+ p784 + p785 + p786 + p787 + p788 + p789 + p790 + p791
+ p792 + p793 + p794 + p795 + p796 + p797 + p798 + p799
+ p800 + p801 + p802 + p803 + p804 + p805 + p806 + p807
+ p808 + p809 + p810 + p811 + p812 + p813 + p814 + p815
+ p816 + p817 + p818 + p819 + p820 + p821 + p822 + p823
+ p824 + p825 + p826 + p827 + p828 + p829 + p830 + p831
+ p832 + p833 + p834 + p835 + p836 + p837 + p838 + p839
+ p840 + p841 + p842 + p843 + p844 + p845 + p846 + p847
+ p848 + p849 + p850 + p851 + p852 + p853 + p854 + p855
+ p856 + p857 + p858 + p859 + p860 + p861 + p862 + p863
+ p864 + p865 + p866 + p867 + p868 + p869 + p870 + p871
+ p872 + p873 + p874 + p875 + p876 + p877 + p878 + p879
+ p880 + p881 + p882 + p883 + p884 + p885 + p886 + p887
+ p888 + p889 + p890 + p891 + p892 + p893 + p894 + p895
+ p896 + p897 + p898 + p899 + p900 + p901 + p902 + p903
+ p904 + p905 + p906 + p907 + p908 + p909 + p910 + p911
+ p912 + p913 + p914 + p915 + p916 + p917 + p918 + p919
+ p920 + p921 + p922 + p923 + p924 + p925 + p926 + p927
+ p928 + p929 + p930 + p931 + p932 + p933 + p934 + p935
+ p936 + p937 + p938 + p939 + p940 + p941 + p942 + p943
+ p944 + p945 + p946 + p947 + p948 + p949 + p950 + p951
+ p952 + p953 + p954 + p955 + p956 + p957 + p958 + p959
+ p960 + p961 + p962 + p963 + p964 + p965 + p966 + p967
+ p968 + p969 + p970 + p971 + p972 + p973 + p974 + p975
+ p976 + p977 + p978 + p979 + p980 + p981 + p982 + p983
+ p984 + p985 + p986 + p987 + p988 + p989 + p990 + p991
+ p992 + p993 + p994 + p995 + p996 + p997 + p998 + p999
+ p1000;
return x;
}
// clang-format on

View File

@@ -1,262 +0,0 @@
// clang-format off
#include <stdint.h>
int32_t test(
int32_t p0, int32_t p1, int32_t p2, int32_t p3, int32_t p4, int32_t p5, int32_t p6, int32_t p7
, int32_t p8, int32_t p9, int32_t p10, int32_t p11, int32_t p12, int32_t p13, int32_t p14, int32_t p15
, int32_t p16, int32_t p17, int32_t p18, int32_t p19, int32_t p20, int32_t p21, int32_t p22, int32_t p23
, int32_t p24, int32_t p25, int32_t p26, int32_t p27, int32_t p28, int32_t p29, int32_t p30, int32_t p31
, int32_t p32, int32_t p33, int32_t p34, int32_t p35, int32_t p36, int32_t p37, int32_t p38, int32_t p39
, int32_t p40, int32_t p41, int32_t p42, int32_t p43, int32_t p44, int32_t p45, int32_t p46, int32_t p47
, int32_t p48, int32_t p49, int32_t p50, int32_t p51, int32_t p52, int32_t p53, int32_t p54, int32_t p55
, int32_t p56, int32_t p57, int32_t p58, int32_t p59, int32_t p60, int32_t p61, int32_t p62, int32_t p63
, int32_t p64, int32_t p65, int32_t p66, int32_t p67, int32_t p68, int32_t p69, int32_t p70, int32_t p71
, int32_t p72, int32_t p73, int32_t p74, int32_t p75, int32_t p76, int32_t p77, int32_t p78, int32_t p79
, int32_t p80, int32_t p81, int32_t p82, int32_t p83, int32_t p84, int32_t p85, int32_t p86, int32_t p87
, int32_t p88, int32_t p89, int32_t p90, int32_t p91, int32_t p92, int32_t p93, int32_t p94, int32_t p95
, int32_t p96, int32_t p97, int32_t p98, int32_t p99, int32_t p100, int32_t p101, int32_t p102, int32_t p103
, int32_t p104, int32_t p105, int32_t p106, int32_t p107, int32_t p108, int32_t p109, int32_t p110, int32_t p111
, int32_t p112, int32_t p113, int32_t p114, int32_t p115, int32_t p116, int32_t p117, int32_t p118, int32_t p119
, int32_t p120, int32_t p121, int32_t p122, int32_t p123, int32_t p124, int32_t p125, int32_t p126, int32_t p127
, int32_t p128, int32_t p129, int32_t p130, int32_t p131, int32_t p132, int32_t p133, int32_t p134, int32_t p135
, int32_t p136, int32_t p137, int32_t p138, int32_t p139, int32_t p140, int32_t p141, int32_t p142, int32_t p143
, int32_t p144, int32_t p145, int32_t p146, int32_t p147, int32_t p148, int32_t p149, int32_t p150, int32_t p151
, int32_t p152, int32_t p153, int32_t p154, int32_t p155, int32_t p156, int32_t p157, int32_t p158, int32_t p159
, int32_t p160, int32_t p161, int32_t p162, int32_t p163, int32_t p164, int32_t p165, int32_t p166, int32_t p167
, int32_t p168, int32_t p169, int32_t p170, int32_t p171, int32_t p172, int32_t p173, int32_t p174, int32_t p175
, int32_t p176, int32_t p177, int32_t p178, int32_t p179, int32_t p180, int32_t p181, int32_t p182, int32_t p183
, int32_t p184, int32_t p185, int32_t p186, int32_t p187, int32_t p188, int32_t p189, int32_t p190, int32_t p191
, int32_t p192, int32_t p193, int32_t p194, int32_t p195, int32_t p196, int32_t p197, int32_t p198, int32_t p199
, int32_t p200, int32_t p201, int32_t p202, int32_t p203, int32_t p204, int32_t p205, int32_t p206, int32_t p207
, int32_t p208, int32_t p209, int32_t p210, int32_t p211, int32_t p212, int32_t p213, int32_t p214, int32_t p215
, int32_t p216, int32_t p217, int32_t p218, int32_t p219, int32_t p220, int32_t p221, int32_t p222, int32_t p223
, int32_t p224, int32_t p225, int32_t p226, int32_t p227, int32_t p228, int32_t p229, int32_t p230, int32_t p231
, int32_t p232, int32_t p233, int32_t p234, int32_t p235, int32_t p236, int32_t p237, int32_t p238, int32_t p239
, int32_t p240, int32_t p241, int32_t p242, int32_t p243, int32_t p244, int32_t p245, int32_t p246, int32_t p247
, int32_t p248, int32_t p249, int32_t p250, int32_t p251, int32_t p252, int32_t p253, int32_t p254, int32_t p255
, int32_t p256, int32_t p257, int32_t p258, int32_t p259, int32_t p260, int32_t p261, int32_t p262, int32_t p263
, int32_t p264, int32_t p265, int32_t p266, int32_t p267, int32_t p268, int32_t p269, int32_t p270, int32_t p271
, int32_t p272, int32_t p273, int32_t p274, int32_t p275, int32_t p276, int32_t p277, int32_t p278, int32_t p279
, int32_t p280, int32_t p281, int32_t p282, int32_t p283, int32_t p284, int32_t p285, int32_t p286, int32_t p287
, int32_t p288, int32_t p289, int32_t p290, int32_t p291, int32_t p292, int32_t p293, int32_t p294, int32_t p295
, int32_t p296, int32_t p297, int32_t p298, int32_t p299, int32_t p300, int32_t p301, int32_t p302, int32_t p303
, int32_t p304, int32_t p305, int32_t p306, int32_t p307, int32_t p308, int32_t p309, int32_t p310, int32_t p311
, int32_t p312, int32_t p313, int32_t p314, int32_t p315, int32_t p316, int32_t p317, int32_t p318, int32_t p319
, int32_t p320, int32_t p321, int32_t p322, int32_t p323, int32_t p324, int32_t p325, int32_t p326, int32_t p327
, int32_t p328, int32_t p329, int32_t p330, int32_t p331, int32_t p332, int32_t p333, int32_t p334, int32_t p335
, int32_t p336, int32_t p337, int32_t p338, int32_t p339, int32_t p340, int32_t p341, int32_t p342, int32_t p343
, int32_t p344, int32_t p345, int32_t p346, int32_t p347, int32_t p348, int32_t p349, int32_t p350, int32_t p351
, int32_t p352, int32_t p353, int32_t p354, int32_t p355, int32_t p356, int32_t p357, int32_t p358, int32_t p359
, int32_t p360, int32_t p361, int32_t p362, int32_t p363, int32_t p364, int32_t p365, int32_t p366, int32_t p367
, int32_t p368, int32_t p369, int32_t p370, int32_t p371, int32_t p372, int32_t p373, int32_t p374, int32_t p375
, int32_t p376, int32_t p377, int32_t p378, int32_t p379, int32_t p380, int32_t p381, int32_t p382, int32_t p383
, int32_t p384, int32_t p385, int32_t p386, int32_t p387, int32_t p388, int32_t p389, int32_t p390, int32_t p391
, int32_t p392, int32_t p393, int32_t p394, int32_t p395, int32_t p396, int32_t p397, int32_t p398, int32_t p399
, int32_t p400, int32_t p401, int32_t p402, int32_t p403, int32_t p404, int32_t p405, int32_t p406, int32_t p407
, int32_t p408, int32_t p409, int32_t p410, int32_t p411, int32_t p412, int32_t p413, int32_t p414, int32_t p415
, int32_t p416, int32_t p417, int32_t p418, int32_t p419, int32_t p420, int32_t p421, int32_t p422, int32_t p423
, int32_t p424, int32_t p425, int32_t p426, int32_t p427, int32_t p428, int32_t p429, int32_t p430, int32_t p431
, int32_t p432, int32_t p433, int32_t p434, int32_t p435, int32_t p436, int32_t p437, int32_t p438, int32_t p439
, int32_t p440, int32_t p441, int32_t p442, int32_t p443, int32_t p444, int32_t p445, int32_t p446, int32_t p447
, int32_t p448, int32_t p449, int32_t p450, int32_t p451, int32_t p452, int32_t p453, int32_t p454, int32_t p455
, int32_t p456, int32_t p457, int32_t p458, int32_t p459, int32_t p460, int32_t p461, int32_t p462, int32_t p463
, int32_t p464, int32_t p465, int32_t p466, int32_t p467, int32_t p468, int32_t p469, int32_t p470, int32_t p471
, int32_t p472, int32_t p473, int32_t p474, int32_t p475, int32_t p476, int32_t p477, int32_t p478, int32_t p479
, int32_t p480, int32_t p481, int32_t p482, int32_t p483, int32_t p484, int32_t p485, int32_t p486, int32_t p487
, int32_t p488, int32_t p489, int32_t p490, int32_t p491, int32_t p492, int32_t p493, int32_t p494, int32_t p495
, int32_t p496, int32_t p497, int32_t p498, int32_t p499, int32_t p500, int32_t p501, int32_t p502, int32_t p503
, int32_t p504, int32_t p505, int32_t p506, int32_t p507, int32_t p508, int32_t p509, int32_t p510, int32_t p511
, int32_t p512, int32_t p513, int32_t p514, int32_t p515, int32_t p516, int32_t p517, int32_t p518, int32_t p519
, int32_t p520, int32_t p521, int32_t p522, int32_t p523, int32_t p524, int32_t p525, int32_t p526, int32_t p527
, int32_t p528, int32_t p529, int32_t p530, int32_t p531, int32_t p532, int32_t p533, int32_t p534, int32_t p535
, int32_t p536, int32_t p537, int32_t p538, int32_t p539, int32_t p540, int32_t p541, int32_t p542, int32_t p543
, int32_t p544, int32_t p545, int32_t p546, int32_t p547, int32_t p548, int32_t p549, int32_t p550, int32_t p551
, int32_t p552, int32_t p553, int32_t p554, int32_t p555, int32_t p556, int32_t p557, int32_t p558, int32_t p559
, int32_t p560, int32_t p561, int32_t p562, int32_t p563, int32_t p564, int32_t p565, int32_t p566, int32_t p567
, int32_t p568, int32_t p569, int32_t p570, int32_t p571, int32_t p572, int32_t p573, int32_t p574, int32_t p575
, int32_t p576, int32_t p577, int32_t p578, int32_t p579, int32_t p580, int32_t p581, int32_t p582, int32_t p583
, int32_t p584, int32_t p585, int32_t p586, int32_t p587, int32_t p588, int32_t p589, int32_t p590, int32_t p591
, int32_t p592, int32_t p593, int32_t p594, int32_t p595, int32_t p596, int32_t p597, int32_t p598, int32_t p599
, int32_t p600, int32_t p601, int32_t p602, int32_t p603, int32_t p604, int32_t p605, int32_t p606, int32_t p607
, int32_t p608, int32_t p609, int32_t p610, int32_t p611, int32_t p612, int32_t p613, int32_t p614, int32_t p615
, int32_t p616, int32_t p617, int32_t p618, int32_t p619, int32_t p620, int32_t p621, int32_t p622, int32_t p623
, int32_t p624, int32_t p625, int32_t p626, int32_t p627, int32_t p628, int32_t p629, int32_t p630, int32_t p631
, int32_t p632, int32_t p633, int32_t p634, int32_t p635, int32_t p636, int32_t p637, int32_t p638, int32_t p639
, int32_t p640, int32_t p641, int32_t p642, int32_t p643, int32_t p644, int32_t p645, int32_t p646, int32_t p647
, int32_t p648, int32_t p649, int32_t p650, int32_t p651, int32_t p652, int32_t p653, int32_t p654, int32_t p655
, int32_t p656, int32_t p657, int32_t p658, int32_t p659, int32_t p660, int32_t p661, int32_t p662, int32_t p663
, int32_t p664, int32_t p665, int32_t p666, int32_t p667, int32_t p668, int32_t p669, int32_t p670, int32_t p671
, int32_t p672, int32_t p673, int32_t p674, int32_t p675, int32_t p676, int32_t p677, int32_t p678, int32_t p679
, int32_t p680, int32_t p681, int32_t p682, int32_t p683, int32_t p684, int32_t p685, int32_t p686, int32_t p687
, int32_t p688, int32_t p689, int32_t p690, int32_t p691, int32_t p692, int32_t p693, int32_t p694, int32_t p695
, int32_t p696, int32_t p697, int32_t p698, int32_t p699, int32_t p700, int32_t p701, int32_t p702, int32_t p703
, int32_t p704, int32_t p705, int32_t p706, int32_t p707, int32_t p708, int32_t p709, int32_t p710, int32_t p711
, int32_t p712, int32_t p713, int32_t p714, int32_t p715, int32_t p716, int32_t p717, int32_t p718, int32_t p719
, int32_t p720, int32_t p721, int32_t p722, int32_t p723, int32_t p724, int32_t p725, int32_t p726, int32_t p727
, int32_t p728, int32_t p729, int32_t p730, int32_t p731, int32_t p732, int32_t p733, int32_t p734, int32_t p735
, int32_t p736, int32_t p737, int32_t p738, int32_t p739, int32_t p740, int32_t p741, int32_t p742, int32_t p743
, int32_t p744, int32_t p745, int32_t p746, int32_t p747, int32_t p748, int32_t p749, int32_t p750, int32_t p751
, int32_t p752, int32_t p753, int32_t p754, int32_t p755, int32_t p756, int32_t p757, int32_t p758, int32_t p759
, int32_t p760, int32_t p761, int32_t p762, int32_t p763, int32_t p764, int32_t p765, int32_t p766, int32_t p767
, int32_t p768, int32_t p769, int32_t p770, int32_t p771, int32_t p772, int32_t p773, int32_t p774, int32_t p775
, int32_t p776, int32_t p777, int32_t p778, int32_t p779, int32_t p780, int32_t p781, int32_t p782, int32_t p783
, int32_t p784, int32_t p785, int32_t p786, int32_t p787, int32_t p788, int32_t p789, int32_t p790, int32_t p791
, int32_t p792, int32_t p793, int32_t p794, int32_t p795, int32_t p796, int32_t p797, int32_t p798, int32_t p799
, int32_t p800, int32_t p801, int32_t p802, int32_t p803, int32_t p804, int32_t p805, int32_t p806, int32_t p807
, int32_t p808, int32_t p809, int32_t p810, int32_t p811, int32_t p812, int32_t p813, int32_t p814, int32_t p815
, int32_t p816, int32_t p817, int32_t p818, int32_t p819, int32_t p820, int32_t p821, int32_t p822, int32_t p823
, int32_t p824, int32_t p825, int32_t p826, int32_t p827, int32_t p828, int32_t p829, int32_t p830, int32_t p831
, int32_t p832, int32_t p833, int32_t p834, int32_t p835, int32_t p836, int32_t p837, int32_t p838, int32_t p839
, int32_t p840, int32_t p841, int32_t p842, int32_t p843, int32_t p844, int32_t p845, int32_t p846, int32_t p847
, int32_t p848, int32_t p849, int32_t p850, int32_t p851, int32_t p852, int32_t p853, int32_t p854, int32_t p855
, int32_t p856, int32_t p857, int32_t p858, int32_t p859, int32_t p860, int32_t p861, int32_t p862, int32_t p863
, int32_t p864, int32_t p865, int32_t p866, int32_t p867, int32_t p868, int32_t p869, int32_t p870, int32_t p871
, int32_t p872, int32_t p873, int32_t p874, int32_t p875, int32_t p876, int32_t p877, int32_t p878, int32_t p879
, int32_t p880, int32_t p881, int32_t p882, int32_t p883, int32_t p884, int32_t p885, int32_t p886, int32_t p887
, int32_t p888, int32_t p889, int32_t p890, int32_t p891, int32_t p892, int32_t p893, int32_t p894, int32_t p895
, int32_t p896, int32_t p897, int32_t p898, int32_t p899, int32_t p900, int32_t p901, int32_t p902, int32_t p903
, int32_t p904, int32_t p905, int32_t p906, int32_t p907, int32_t p908, int32_t p909, int32_t p910, int32_t p911
, int32_t p912, int32_t p913, int32_t p914, int32_t p915, int32_t p916, int32_t p917, int32_t p918, int32_t p919
, int32_t p920, int32_t p921, int32_t p922, int32_t p923, int32_t p924, int32_t p925, int32_t p926, int32_t p927
, int32_t p928, int32_t p929, int32_t p930, int32_t p931, int32_t p932, int32_t p933, int32_t p934, int32_t p935
, int32_t p936, int32_t p937, int32_t p938, int32_t p939, int32_t p940, int32_t p941, int32_t p942, int32_t p943
, int32_t p944, int32_t p945, int32_t p946, int32_t p947, int32_t p948, int32_t p949, int32_t p950, int32_t p951
, int32_t p952, int32_t p953, int32_t p954, int32_t p955, int32_t p956, int32_t p957, int32_t p958, int32_t p959
, int32_t p960, int32_t p961, int32_t p962, int32_t p963, int32_t p964, int32_t p965, int32_t p966, int32_t p967
, int32_t p968, int32_t p969, int32_t p970, int32_t p971, int32_t p972, int32_t p973, int32_t p974, int32_t p975
, int32_t p976, int32_t p977, int32_t p978, int32_t p979, int32_t p980, int32_t p981, int32_t p982, int32_t p983
, int32_t p984, int32_t p985, int32_t p986, int32_t p987, int32_t p988, int32_t p989, int32_t p990, int32_t p991
, int32_t p992, int32_t p993, int32_t p994, int32_t p995, int32_t p996, int32_t p997, int32_t p998, int32_t p999
)
{
int32_t x;
x = p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7
+ p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15
+ p16 + p17 + p18 + p19 + p20 + p21 + p22 + p23
+ p24 + p25 + p26 + p27 + p28 + p29 + p30 + p31
+ p32 + p33 + p34 + p35 + p36 + p37 + p38 + p39
+ p40 + p41 + p42 + p43 + p44 + p45 + p46 + p47
+ p48 + p49 + p50 + p51 + p52 + p53 + p54 + p55
+ p56 + p57 + p58 + p59 + p60 + p61 + p62 + p63
+ p64 + p65 + p66 + p67 + p68 + p69 + p70 + p71
+ p72 + p73 + p74 + p75 + p76 + p77 + p78 + p79
+ p80 + p81 + p82 + p83 + p84 + p85 + p86 + p87
+ p88 + p89 + p90 + p91 + p92 + p93 + p94 + p95
+ p96 + p97 + p98 + p99 + p100 + p101 + p102 + p103
+ p104 + p105 + p106 + p107 + p108 + p109 + p110 + p111
+ p112 + p113 + p114 + p115 + p116 + p117 + p118 + p119
+ p120 + p121 + p122 + p123 + p124 + p125 + p126 + p127
+ p128 + p129 + p130 + p131 + p132 + p133 + p134 + p135
+ p136 + p137 + p138 + p139 + p140 + p141 + p142 + p143
+ p144 + p145 + p146 + p147 + p148 + p149 + p150 + p151
+ p152 + p153 + p154 + p155 + p156 + p157 + p158 + p159
+ p160 + p161 + p162 + p163 + p164 + p165 + p166 + p167
+ p168 + p169 + p170 + p171 + p172 + p173 + p174 + p175
+ p176 + p177 + p178 + p179 + p180 + p181 + p182 + p183
+ p184 + p185 + p186 + p187 + p188 + p189 + p190 + p191
+ p192 + p193 + p194 + p195 + p196 + p197 + p198 + p199
+ p200 + p201 + p202 + p203 + p204 + p205 + p206 + p207
+ p208 + p209 + p210 + p211 + p212 + p213 + p214 + p215
+ p216 + p217 + p218 + p219 + p220 + p221 + p222 + p223
+ p224 + p225 + p226 + p227 + p228 + p229 + p230 + p231
+ p232 + p233 + p234 + p235 + p236 + p237 + p238 + p239
+ p240 + p241 + p242 + p243 + p244 + p245 + p246 + p247
+ p248 + p249 + p250 + p251 + p252 + p253 + p254 + p255
+ p256 + p257 + p258 + p259 + p260 + p261 + p262 + p263
+ p264 + p265 + p266 + p267 + p268 + p269 + p270 + p271
+ p272 + p273 + p274 + p275 + p276 + p277 + p278 + p279
+ p280 + p281 + p282 + p283 + p284 + p285 + p286 + p287
+ p288 + p289 + p290 + p291 + p292 + p293 + p294 + p295
+ p296 + p297 + p298 + p299 + p300 + p301 + p302 + p303
+ p304 + p305 + p306 + p307 + p308 + p309 + p310 + p311
+ p312 + p313 + p314 + p315 + p316 + p317 + p318 + p319
+ p320 + p321 + p322 + p323 + p324 + p325 + p326 + p327
+ p328 + p329 + p330 + p331 + p332 + p333 + p334 + p335
+ p336 + p337 + p338 + p339 + p340 + p341 + p342 + p343
+ p344 + p345 + p346 + p347 + p348 + p349 + p350 + p351
+ p352 + p353 + p354 + p355 + p356 + p357 + p358 + p359
+ p360 + p361 + p362 + p363 + p364 + p365 + p366 + p367
+ p368 + p369 + p370 + p371 + p372 + p373 + p374 + p375
+ p376 + p377 + p378 + p379 + p380 + p381 + p382 + p383
+ p384 + p385 + p386 + p387 + p388 + p389 + p390 + p391
+ p392 + p393 + p394 + p395 + p396 + p397 + p398 + p399
+ p400 + p401 + p402 + p403 + p404 + p405 + p406 + p407
+ p408 + p409 + p410 + p411 + p412 + p413 + p414 + p415
+ p416 + p417 + p418 + p419 + p420 + p421 + p422 + p423
+ p424 + p425 + p426 + p427 + p428 + p429 + p430 + p431
+ p432 + p433 + p434 + p435 + p436 + p437 + p438 + p439
+ p440 + p441 + p442 + p443 + p444 + p445 + p446 + p447
+ p448 + p449 + p450 + p451 + p452 + p453 + p454 + p455
+ p456 + p457 + p458 + p459 + p460 + p461 + p462 + p463
+ p464 + p465 + p466 + p467 + p468 + p469 + p470 + p471
+ p472 + p473 + p474 + p475 + p476 + p477 + p478 + p479
+ p480 + p481 + p482 + p483 + p484 + p485 + p486 + p487
+ p488 + p489 + p490 + p491 + p492 + p493 + p494 + p495
+ p496 + p497 + p498 + p499 + p500 + p501 + p502 + p503
+ p504 + p505 + p506 + p507 + p508 + p509 + p510 + p511
+ p512 + p513 + p514 + p515 + p516 + p517 + p518 + p519
+ p520 + p521 + p522 + p523 + p524 + p525 + p526 + p527
+ p528 + p529 + p530 + p531 + p532 + p533 + p534 + p535
+ p536 + p537 + p538 + p539 + p540 + p541 + p542 + p543
+ p544 + p545 + p546 + p547 + p548 + p549 + p550 + p551
+ p552 + p553 + p554 + p555 + p556 + p557 + p558 + p559
+ p560 + p561 + p562 + p563 + p564 + p565 + p566 + p567
+ p568 + p569 + p570 + p571 + p572 + p573 + p574 + p575
+ p576 + p577 + p578 + p579 + p580 + p581 + p582 + p583
+ p584 + p585 + p586 + p587 + p588 + p589 + p590 + p591
+ p592 + p593 + p594 + p595 + p596 + p597 + p598 + p599
+ p600 + p601 + p602 + p603 + p604 + p605 + p606 + p607
+ p608 + p609 + p610 + p611 + p612 + p613 + p614 + p615
+ p616 + p617 + p618 + p619 + p620 + p621 + p622 + p623
+ p624 + p625 + p626 + p627 + p628 + p629 + p630 + p631
+ p632 + p633 + p634 + p635 + p636 + p637 + p638 + p639
+ p640 + p641 + p642 + p643 + p644 + p645 + p646 + p647
+ p648 + p649 + p650 + p651 + p652 + p653 + p654 + p655
+ p656 + p657 + p658 + p659 + p660 + p661 + p662 + p663
+ p664 + p665 + p666 + p667 + p668 + p669 + p670 + p671
+ p672 + p673 + p674 + p675 + p676 + p677 + p678 + p679
+ p680 + p681 + p682 + p683 + p684 + p685 + p686 + p687
+ p688 + p689 + p690 + p691 + p692 + p693 + p694 + p695
+ p696 + p697 + p698 + p699 + p700 + p701 + p702 + p703
+ p704 + p705 + p706 + p707 + p708 + p709 + p710 + p711
+ p712 + p713 + p714 + p715 + p716 + p717 + p718 + p719
+ p720 + p721 + p722 + p723 + p724 + p725 + p726 + p727
+ p728 + p729 + p730 + p731 + p732 + p733 + p734 + p735
+ p736 + p737 + p738 + p739 + p740 + p741 + p742 + p743
+ p744 + p745 + p746 + p747 + p748 + p749 + p750 + p751
+ p752 + p753 + p754 + p755 + p756 + p757 + p758 + p759
+ p760 + p761 + p762 + p763 + p764 + p765 + p766 + p767
+ p768 + p769 + p770 + p771 + p772 + p773 + p774 + p775
+ p776 + p777 + p778 + p779 + p780 + p781 + p782 + p783
+ p784 + p785 + p786 + p787 + p788 + p789 + p790 + p791
+ p792 + p793 + p794 + p795 + p796 + p797 + p798 + p799
+ p800 + p801 + p802 + p803 + p804 + p805 + p806 + p807
+ p808 + p809 + p810 + p811 + p812 + p813 + p814 + p815
+ p816 + p817 + p818 + p819 + p820 + p821 + p822 + p823
+ p824 + p825 + p826 + p827 + p828 + p829 + p830 + p831
+ p832 + p833 + p834 + p835 + p836 + p837 + p838 + p839
+ p840 + p841 + p842 + p843 + p844 + p845 + p846 + p847
+ p848 + p849 + p850 + p851 + p852 + p853 + p854 + p855
+ p856 + p857 + p858 + p859 + p860 + p861 + p862 + p863
+ p864 + p865 + p866 + p867 + p868 + p869 + p870 + p871
+ p872 + p873 + p874 + p875 + p876 + p877 + p878 + p879
+ p880 + p881 + p882 + p883 + p884 + p885 + p886 + p887
+ p888 + p889 + p890 + p891 + p892 + p893 + p894 + p895
+ p896 + p897 + p898 + p899 + p900 + p901 + p902 + p903
+ p904 + p905 + p906 + p907 + p908 + p909 + p910 + p911
+ p912 + p913 + p914 + p915 + p916 + p917 + p918 + p919
+ p920 + p921 + p922 + p923 + p924 + p925 + p926 + p927
+ p928 + p929 + p930 + p931 + p932 + p933 + p934 + p935
+ p936 + p937 + p938 + p939 + p940 + p941 + p942 + p943
+ p944 + p945 + p946 + p947 + p948 + p949 + p950 + p951
+ p952 + p953 + p954 + p955 + p956 + p957 + p958 + p959
+ p960 + p961 + p962 + p963 + p964 + p965 + p966 + p967
+ p968 + p969 + p970 + p971 + p972 + p973 + p974 + p975
+ p976 + p977 + p978 + p979 + p980 + p981 + p982 + p983
+ p984 + p985 + p986 + p987 + p988 + p989 + p990 + p991
+ p992 + p993 + p994 + p995 + p996 + p997 + p998 + p999;
return x;
}
// clang-format on

View File

@@ -1,13 +0,0 @@
(module
;; Define a memory with 1 initial page.
;; CRITICAL: We explicitly set the page size to 1 kilobyte.
;; Standard Wasm implies (pagesize 65536).
(memory 1 (pagesize 1024))
(func $finish (result i32)
;; If this module instantiates, the runtime accepted the custom page size.
i32.const 1
)
(export "finish" (func $finish))
)

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,21 +0,0 @@
(module
;; Define a 64-bit memory (index type i64)
;; Start with 1 page.
(memory i64 1)
(func $finish (result i32)
;; 1. Perform a store using a 64-bit address.
;; Even if the value is small (0), the type MUST be i64.
i64.const 0 ;; Address (64-bit)
i32.const 42 ;; Value (32-bit)
i32.store8 ;; Opcode doesn't change, but validation rules do.
;; 2. check memory size
;; memory.size now returns an i64.
memory.size
i64.const 1
i64.eq ;; Returns i32 (1 if true)
)
(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,16 +0,0 @@
(module
;; Memory 0: Index 0 (Empty)
(memory 0)
;; Memory 1: Index 1 (Size 1 page)
;; If multi-memory is disabled, this line causes a validation error (max 1 memory).
(memory 1)
(func $finish (result i32)
;; Query size of Memory Index 1.
;; Should return 1 (success).
memory.size 1
)
(export "finish" (func $finish))
)

View File

@@ -1,98 +0,0 @@
(module
;; Type for call_indirect
(type (func (result i32)))
;; Memory and table declarations
(memory 1)
(table 1 funcref)
(data (i32.const 0) "test")
(elem (i32.const 0) $test_func)
;; Global declarations
(global $g0 (mut i32) (i32.const 0))
(global $g1 (mut i64) (i64.const 0))
;; Test function for call/call_indirect
(func $test_func (result i32)
i32.const 42
)
;; Main function with all instructions in hex order
(func $all_instructions (export "all_instructions") (result i32)
(local $l0 i32)
(local $l1 i64)
;; 0x01: nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
i32.const 11
)
)

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

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