From 8f0eff4dc489c4dc1b5ae2ee3c13ca820457cca7 Mon Sep 17 00:00:00 2001 From: Sergey Kuznetsov Date: Fri, 7 Aug 2026 15:19:08 +0100 Subject: [PATCH] Bring tests back --- src/test/app/TestHostFunctions.h | 538 +++++ src/test/app/Wasm_test.cpp | 477 +++++ src/test/app/wasm_fixtures/.gitignore | 3 + .../all_host_functions/Cargo.lock | 171 ++ .../all_host_functions/Cargo.toml | 21 + .../all_host_functions/src/lib.rs | 799 ++++++++ .../app/wasm_fixtures/all_keylets/Cargo.lock | 171 ++ .../app/wasm_fixtures/all_keylets/Cargo.toml | 21 + .../app/wasm_fixtures/all_keylets/src/lib.rs | 176 ++ src/test/app/wasm_fixtures/bad_align.c | 42 + .../wasm_fixtures/codecov_tests/Cargo.lock | 171 ++ .../wasm_fixtures/codecov_tests/Cargo.toml | 18 + .../codecov_tests/src/host_bindings_loose.rs | 47 + .../wasm_fixtures/codecov_tests/src/lib.rs | 1782 +++++++++++++++++ src/test/app/wasm_fixtures/copyFixtures.py | 287 +++ src/test/app/wasm_fixtures/fixtures.cpp | 663 ++++++ src/test/app/wasm_fixtures/fixtures.h | 12 + src/test/app/wasm_fixtures/ledgerSqn.c | 14 + 18 files changed, 5413 insertions(+) create mode 100644 src/test/app/TestHostFunctions.h create mode 100644 src/test/app/Wasm_test.cpp create mode 100644 src/test/app/wasm_fixtures/.gitignore create mode 100644 src/test/app/wasm_fixtures/all_host_functions/Cargo.lock create mode 100644 src/test/app/wasm_fixtures/all_host_functions/Cargo.toml create mode 100644 src/test/app/wasm_fixtures/all_host_functions/src/lib.rs create mode 100644 src/test/app/wasm_fixtures/all_keylets/Cargo.lock create mode 100644 src/test/app/wasm_fixtures/all_keylets/Cargo.toml create mode 100644 src/test/app/wasm_fixtures/all_keylets/src/lib.rs create mode 100644 src/test/app/wasm_fixtures/bad_align.c create mode 100644 src/test/app/wasm_fixtures/codecov_tests/Cargo.lock create mode 100644 src/test/app/wasm_fixtures/codecov_tests/Cargo.toml create mode 100644 src/test/app/wasm_fixtures/codecov_tests/src/host_bindings_loose.rs create mode 100644 src/test/app/wasm_fixtures/codecov_tests/src/lib.rs create mode 100644 src/test/app/wasm_fixtures/copyFixtures.py create mode 100644 src/test/app/wasm_fixtures/fixtures.cpp create mode 100644 src/test/app/wasm_fixtures/fixtures.h create mode 100644 src/test/app/wasm_fixtures/ledgerSqn.c diff --git a/src/test/app/TestHostFunctions.h b/src/test/app/TestHostFunctions.h new file mode 100644 index 0000000000..a3ded89f33 --- /dev/null +++ b/src/test/app/TestHostFunctions.h @@ -0,0 +1,538 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace xrpl::test { + +class TestLedgerDataProvider : public HostFunctions +{ + jtx::Env& env_; + +public: + TestLedgerDataProvider(jtx::Env& env) : HostFunctions(env.journal), env_(env) + { + } + + [[nodiscard]] std::expected + getLedgerSqn() const override + { + return env_.current()->seq(); + } +}; + +class TestHostFunctions : public HostFunctions +{ +protected: + test::jtx::Env& env_; + AccountID accountID_; + Bytes data_; + +public: + TestHostFunctions(test::jtx::Env& env) : HostFunctions(env.journal), env_(env) + { + accountID_ = env.master.id(); + std::string t = "10000"; + data_ = Bytes{t.begin(), t.end()}; + } + + [[nodiscard]] std::expected + getLedgerSqn() const override + { + return 12345; + } + + [[nodiscard]] std::expected + getParentLedgerTime() const override + { + return 67890; + } + + [[nodiscard]] std::expected + getParentLedgerHash() const override + { + return env_.current()->header().parentHash; + } + + [[nodiscard]] std::expected + getBaseFee() const override + { + return 10; + } + + [[nodiscard]] std::expected + isAmendmentEnabled(uint256 const& amendmentId) const override + { + return 1; + } + + [[nodiscard]] std::expected + isAmendmentEnabled(std::string_view const& amendmentName) const override + { + return 1; + } + + std::expected + cacheLedgerObj(uint256 const& objId, int32_t cacheIdx) override + { + return 1; + } + + [[nodiscard]] std::expected + getTxField(SField const& fname) const override + { + if (fname == sfAccount) + return Bytes(accountID_.begin(), accountID_.end()); + + if (fname == sfFee) + { + int64_t x = 235; + auto const* p = reinterpret_cast(&x); + return Bytes{p, p + sizeof(x)}; + } + + if (fname == sfSequence) + { + auto const x = getLedgerSqn(); + if (!x) + return std::unexpected(x.error()); + std::uint32_t const data = x.value(); + auto const* b = reinterpret_cast(&data); + auto const* e = reinterpret_cast(&data + 1); + return Bytes{b, e}; + } + + return Bytes(); + } + + [[nodiscard]] std::expected + getCurrentLedgerObjField(SField const& fname) const override + { + auto const& sn = fname.getName(); + if (sn == "Destination" || sn == "Account") + return Bytes(accountID_.begin(), accountID_.end()); + if (sn == "Data") + return data_; + if (sn == "FinishAfter") + { + auto t = env_.current()->parentCloseTime().time_since_epoch().count(); + std::string s = std::to_string(t); + return Bytes{s.begin(), s.end()}; + } + + return std::unexpected(HostFunctionError::Unimplemented); + } + + [[nodiscard]] std::expected + getLedgerObjField(int32_t, SField const& fname) const override + { + if (fname == sfBalance) + { + int64_t x = 10'000; + auto const* p = reinterpret_cast(&x); + return Bytes{p, p + sizeof(x)}; + } + + if (fname == sfAccount) + return Bytes(accountID_.begin(), accountID_.end()); + + return data_; + } + + [[nodiscard]] std::expected + getTxNestedField(FieldLocator const& locator) const override + { + if (locator.size() == 1) + { + int32_t const* l = locator.data(); + int32_t const sfield = l[0]; + if (sfield == sfAccount.getCode()) + 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}; + return Bytes(&a[0], &a[sizeof(a)]); + } + + [[nodiscard]] std::expected + getCurrentLedgerObjNestedField(FieldLocator const& locator) const override + { + if (locator.size() == 1) + { + int32_t const* l = locator.data(); + int32_t const sfield = l[0]; + if (sfield == sfAccount.getCode()) + 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}; + return Bytes(&a[0], &a[sizeof(a)]); + } + + [[nodiscard]] std::expected + getLedgerObjNestedField(int32_t cacheIdx, FieldLocator const& locator) const override + { + if (locator.size() == 1) + { + int32_t const* l = locator.data(); + int32_t const sfield = l[0]; + if (sfield == sfAccount.getCode()) + 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}; + return Bytes(&a[0], &a[sizeof(a)]); + } + + [[nodiscard]] std::expected + getTxArrayLen(SField const& fname) const override + { + return 32; + } + + [[nodiscard]] std::expected + getCurrentLedgerObjArrayLen(SField const& fname) const override + { + return 32; + } + + [[nodiscard]] std::expected + getLedgerObjArrayLen(int32_t cacheIdx, SField const& fname) const override + { + return 32; + } + + [[nodiscard]] std::expected + getTxNestedArrayLen(FieldLocator const& locator) const override + { + return 32; + } + + [[nodiscard]] std::expected + getCurrentLedgerObjNestedArrayLen(FieldLocator const& locator) const override + { + return 32; + } + + [[nodiscard]] std::expected + getLedgerObjNestedArrayLen(int32_t cacheIdx, FieldLocator const& locator) const override + { + return 32; + } + + std::expected + updateData(Slice const& data) override + { + return data.size(); + } + + [[nodiscard]] std::expected + checkSignature(Slice const& message, Slice const& signature, Slice const& pubkey) const override + { + return 1; + } + + [[nodiscard]] std::expected + computeSha512HalfHash(Slice const& data) const override + { + return env_.current()->header().parentHash; + } + + [[nodiscard]] std::expected + accountKeylet(AccountID const& account) const override + { + if (!account) + return std::unexpected(HostFunctionError::InvalidAccount); + auto const keylet = keylet::account(account); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + ammKeylet(Asset const& issue1, Asset const& issue2) const override + { + if (issue1 == issue2) + return std::unexpected(HostFunctionError::InvalidParams); + if (issue1.holds() || issue2.holds()) + return std::unexpected(HostFunctionError::InvalidParams); + auto const keylet = keylet::amm(issue1, issue2); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + checkKeylet(AccountID const& account, std::uint32_t seq) const override + { + if (!account) + return std::unexpected(HostFunctionError::InvalidAccount); + auto const keylet = keylet::check(account, seq); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + credentialKeylet(AccountID const& subject, AccountID const& issuer, Slice const& credentialType) + const override + { + if (!subject || !issuer || credentialType.empty() || + credentialType.size() > kMaxCredentialTypeLength) + return std::unexpected(HostFunctionError::InvalidAccount); + auto const keylet = keylet::credential(subject, issuer, credentialType); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + escrowKeylet(AccountID const& account, std::uint32_t seq) const override + { + if (!account) + return std::unexpected(HostFunctionError::InvalidAccount); + auto const keylet = keylet::escrow(account, seq); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + oracleKeylet(AccountID const& account, std::uint32_t documentId) const override + { + if (!account) + return std::unexpected(HostFunctionError::InvalidAccount); + auto const keylet = keylet::oracle(account, documentId); + return Bytes{keylet.key.begin(), keylet.key.end()}; + } + + [[nodiscard]] std::expected + getNFT(AccountID const& account, uint256 const& nftId) const override + { + if (!account || !nftId) + return std::unexpected(HostFunctionError::InvalidParams); + + std::string s = "https://ripple.com"; + return Bytes(s.begin(), s.end()); + } + + [[nodiscard]] std::expected + getNFTIssuer(uint256 const& nftId) const override + { + return Bytes(accountID_.begin(), accountID_.end()); + } + + [[nodiscard]] std::expected + getNFTTaxon(uint256 const& nftId) const override + { + return 4; + } + + [[nodiscard]] std::expected + getNFTFlags(uint256 const& nftId) const override + { + return 8; + } + + [[nodiscard]] std::expected + getNFTTransferFee(uint256 const& nftId) const override + { + return 10; + } + + [[nodiscard]] std::expected + getNFTSequence(uint256 const& nftId) const override + { + return 4; + } + + template + void + log(std::string_view const& msg, F&& dataFn) const + { +#ifdef DEBUG_OUTPUT + auto& j = std::cerr; +#else + if (!getJournal().active(beast::Severity::Trace)) + return; + auto j = getJournal().trace(); +#endif + j << "WasmTrace: " << msg << " " << dataFn(); + +#ifdef DEBUG_OUTPUT + j << std::endl; +#endif + } + + [[nodiscard]] std::expected + trace(std::string_view const& msg, Slice const& data, bool asHex) const override + { + if (!asHex) + { + log(msg, [&data] { + return std::string_view(reinterpret_cast(data.data()), data.size()); + }); + } + else + { + log(msg, [&data] { + std::string hex; + hex.reserve(data.size() * 2); + boost::algorithm::hex(data.begin(), data.end(), std::back_inserter(hex)); + return hex; + }); + } + + return 0; + } + + [[nodiscard]] std::expected + traceNum(std::string_view const& msg, int64_t data) const override + { + log(msg, [data] { return data; }); + return 0; + } + + [[nodiscard]] std::expected + traceAccount(std::string_view const& msg, AccountID const& account) const override + { + log(msg, [&account] { return toBase58(account); }); + return 0; + } + + [[nodiscard]] std::expected + traceFloat(std::string_view const& msg, Slice const& data) const override + { + log(msg, [&data] { return wasm_float::floatToString(data); }); + return 0; + } + + [[nodiscard]] std::expected + traceAmount(std::string_view const& msg, STAmount const& amount) const override + { + log(msg, [&amount] { return amount.getFullText(); }); + return 0; + } + + [[nodiscard]] std::expected + floatFromInt(int64_t x, int32_t mode) const override + { + return wasm_float::floatFromIntImpl(x, mode); + } + + [[nodiscard]] std::expected + floatFromUint(uint64_t x, int32_t mode) const override + { + return wasm_float::floatFromUintImpl(x, mode); + } + + [[nodiscard]] std::expected + floatFromSTAmount(STAmount const& x, int32_t mode) const override + { + return wasm_float::floatFromSTAmountImpl(x, mode); + } + + [[nodiscard]] std::expected + floatFromSTNumber(STNumber const& x, int32_t mode) const override + { + return wasm_float::floatFromSTNumberImpl(x, mode); + } + + [[nodiscard]] std::expected + floatToInt(Slice const& x, int32_t mode) const override + { + return wasm_float::floatToIntImpl(x, mode); + } + + [[nodiscard]] std::expected + floatToMantExp(Slice const& x) const override + { + return wasm_float::floatToMantExpImpl(x); + } + + [[nodiscard]] std::expected + floatFromMantExp(int64_t mantissa, int32_t exponent, int32_t mode) const override + { + return wasm_float::floatFromMantExpImpl(mantissa, exponent, mode); + } + + [[nodiscard]] std::expected + floatCompare(Slice const& x, Slice const& y) const override + { + return wasm_float::floatCompareImpl(x, y); + } + + [[nodiscard]] std::expected + floatAdd(Slice const& x, Slice const& y, int32_t mode) const override + { + return wasm_float::floatAddImpl(x, y, mode); + } + + [[nodiscard]] std::expected + floatSubtract(Slice const& x, Slice const& y, int32_t mode) const override + { + return wasm_float::floatSubtractImpl(x, y, mode); + } + + [[nodiscard]] std::expected + floatMultiply(Slice const& x, Slice const& y, int32_t mode) const override + { + return wasm_float::floatMultiplyImpl(x, y, mode); + } + + [[nodiscard]] std::expected + floatDivide(Slice const& x, Slice const& y, int32_t mode) const override + { + return wasm_float::floatDivideImpl(x, y, mode); + } + + [[nodiscard]] std::expected + floatRoot(Slice const& x, int32_t n, int32_t mode) const override + { + return wasm_float::floatRootImpl(x, n, mode); + } + + [[nodiscard]] std::expected + floatPower(Slice const& x, int32_t n, int32_t mode) const override + { + return wasm_float::floatPowerImpl(x, n, mode); + } +}; + +class TestHostFunctionsSink : public TestHostFunctions +{ + test::StreamSink sink_; + +public: + explicit TestHostFunctionsSink(test::jtx::Env& env) + : TestHostFunctions(env), sink_(beast::Severity::Debug) + { + j_ = beast::Journal(sink_); + } + + test::StreamSink& + getSink() + { + return sink_; + } +}; + +} // namespace xrpl::test diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp new file mode 100644 index 0000000000..62bbba7995 --- /dev/null +++ b/src/test/app/Wasm_test.cpp @@ -0,0 +1,477 @@ +// Not built. These suites drive a C++ wasm engine interface -- WasmVM over the wasm.h C API, +// HostFuncWrapper, WasmImportsHelper -- that this tree does not provide; the VM lives in the +// Rust crates. Kept as the coverage target for the port. The body is one comment block, and +// the fixtures it reads (wasm_fixtures/fixtures.cpp) are disabled the same way; re-enabling +// the suites means uncommenting both. + +/* +#include +#ifdef _DEBUG +// #define DEBUG_OUTPUT 1 +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include // IWYU pragma: keep +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +namespace xrpl::test { + +bool +testGetDataIncrement(); + +using Add_proto = int32_t(int32_t, int32_t); +static wasm_trap_t* +add(HostFunctions&, wasm_val_vec_t const* params, wasm_val_vec_t* results) +{ + int32_t const val1 = params->data[0].of.i32; + int32_t const val2 = params->data[1].of.i32; + // printf("Host function \"Add\": %d + %d\n", Val1, Val2); + results->data[0] = WASM_I32_VAL(val1 + val2); + return nullptr; +} + +std::vector +hexToBytes(std::string const& hex) +{ + auto const ws = boost::algorithm::unhex(hex); + return Bytes(ws.begin(), ws.end()); +} + +struct Wasm_test : public beast::unit_test::Suite +{ + void + checkResult( + std::expected, WasmTER> re, + int32_t expectedResult, + int64_t expectedCost, + std::source_location const location = std::source_location::current()) + { + auto const lineStr = " (" + std::to_string(location.line()) + ")"; + if (BEAST_EXPECTS(re.has_value(), transToken(re.error().ter) + lineStr)) + { + BEAST_EXPECTS(re->result == expectedResult, std::to_string(re->result) + lineStr); + BEAST_EXPECTS(re->cost == expectedCost, std::to_string(re->cost) + lineStr); + } + } + + void + testGetDataHelperFunctions() + { + testcase("getData helper functions"); + BEAST_EXPECT(testGetDataIncrement()); + } + + void + testWasmLib() + { + testcase("wasm lib test"); + // clang-format off + // The WASM module buffer. // + Bytes const wasm = {// WASM header // + 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, + // Type section // + 0x01, 0x07, 0x01, + // function type {i32, i32} -> {i32} // + 0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F, + // Import section // + 0x02, 0x13, 0x01, + // module name: "extern" // + 0x06, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6E, + // extern name: "func-add" // + 0x08, 0x66, 0x75, 0x6E, 0x63, 0x2D, 0x61, 0x64, 0x64, + // import desc: func 0 // + 0x00, 0x00, + // Function section // + 0x03, 0x02, 0x01, 0x00, + // Export section // + 0x07, 0x0A, 0x01, + // export name: "addTwo" // + 0x06, 0x61, 0x64, 0x64, 0x54, 0x77, 0x6F, + // export desc: func 0 // + 0x00, 0x01, + // Code section // + 0x0A, 0x0A, 0x01, + // code body // + 0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x0B}; + // clang-format on + auto& vm = WasmEngine::instance(); + + HostFunctions hfs; + ImportVec imports; + WasmImpFunc(imports, "func-add", add, hfs); + + auto re = vm.run(wasm, hfs, 10'000'000, "addTwo", wasmParams(1234, 5678), imports); + + // if (res) printf("invokeAdd get the result: %d\n", res.value()); + + checkResult(re, 6'912, 59); + } + + void + testBadWasm() + { + testcase("bad wasm test"); + + using namespace test::jtx; + + Env const env{*this}; + HostFunctions hfs(env.journal); + + { + auto wasm = hexToBytes("00000000"); + std::string const funcName("mock_escrow"); + + auto re = runEscrowWasm(wasm, hfs, 15, funcName, {}); + BEAST_EXPECT(!re); + } + + { + auto wasm = hexToBytes("00112233445566778899AA"); + std::string const funcName("mock_escrow"); + + auto const re = preflightEscrowWasm(wasm, hfs, funcName); + BEAST_EXPECT(!isTesSuccess(re)); + } + + { + // FinishFunction wrong function name + // pub fn bad() -> bool { + // unsafe { host_lib::getLedgerSqn() >= 5 } + // } + auto const badWasm = hexToBytes( + "0061736d010000000105016000017f02190108686f73745f6c69620c6765" + "744c656467657253716e00000302010005030100100611027f00418080c0" + "000b7f00418080c0000b072b04066d656d6f727902000362616400010a5f" + "5f646174615f656e6403000b5f5f686561705f6261736503010a09010700" + "100041044a0b004d0970726f64756365727302086c616e67756167650104" + "52757374000c70726f6365737365642d6279010572757374631d312e3835" + "2e31202834656231363132353020323032352d30332d31352900490f7461" + "726765745f6665617475726573042b0f6d757461626c652d676c6f62616c" + "732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a" + "6d756c746976616c7565"); + + auto const re = preflightEscrowWasm(badWasm, hfs, escrowFunctionName); + BEAST_EXPECT(!isTesSuccess(re)); + } + } + + void + testWasmLedgerSqn() + { + testcase("Wasm get ledger sequence"); + + auto ledgerSqnWasm = hexToBytes(kLedgerSqnWasmHex); + + using namespace test::jtx; + + Env env{*this}; + TestLedgerDataProvider hfs(env); + ImportVec imports; + WASM_IMPORT_FUNC2(imports, getLedgerSqn, "ldgr_index", hfs, 33); + auto& engine = WasmEngine::instance(); + + auto re = + engine.run(ledgerSqnWasm, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal); + + checkResult(re, 0, 440); + + env.close(); + env.close(); + + // empty module, throwing exception + re = engine.run({}, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal); + BEAST_EXPECT(!re); + env.close(); + } + + void + testHFCost() + { + testcase("wasm test host functions cost"); + + using namespace test::jtx; + + Env env(*this); + { + auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex); + + auto& engine = WasmEngine::instance(); + + TestHostFunctions hfs(env); + auto imp = createWasmImport(hfs); + for (auto& i : imp) + i.second.second.gas = 0; + + auto re = engine.run( + allHostFuncWasm, hfs, 1'000'000, escrowFunctionName, {}, imp, env.journal); + + checkResult(re, 1, 27'617); + + env.close(); + } + + env.close(); + env.close(); + env.close(); + env.close(); + env.close(); + + { + auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex); + + auto& engine = WasmEngine::instance(); + + TestHostFunctions hfs(env); + auto const imp = createWasmImport(hfs); + + auto re = engine.run( + allHostFuncWasm, hfs, 1'000'000, escrowFunctionName, {}, imp, env.journal); + + checkResult(re, 1, 70'877); + + env.close(); + } + + // not enough gas + { + auto const allHostFuncWasm = hexToBytes(kAllHostFunctionsWasmHex); + + auto& engine = WasmEngine::instance(); + + TestHostFunctions hfs(env); + auto const imp = createWasmImport(hfs); + + auto re = + engine.run(allHostFuncWasm, hfs, 200, escrowFunctionName, {}, imp, env.journal); + + if (BEAST_EXPECT(!re)) + { + // Running out of gas now terminates with tecOUT_OF_GAS (was + // previously collapsed into tecFAILED_PROCESSING). + BEAST_EXPECTS( + re.error().ter == tecOUT_OF_GAS, std::to_string(TERtoInt(re.error().ter))); + } + + env.close(); + } + } + + void + testEscrowWasmDN() + { + testcase("escrow wasm devnet test"); + + auto const allHFWasm = hexToBytes(kAllHostFunctionsWasmHex); + + using namespace test::jtx; + Env env{*this}; + { + TestHostFunctions hfs(env); + auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {}); + checkResult(re, 1, 70'877); + } + + { + // Invalid gas limit (0) should be rejected (boundary condition) + TestHostFunctions hfs(env); + auto re = runEscrowWasm(allHFWasm, hfs, -1, escrowFunctionName, {}); + BEAST_EXPECT(!re.has_value()); + BEAST_EXPECT(re.error().ter == temBAD_AMOUNT); + } + + { + // Invalid gas limit (-1) should be rejected + TestHostFunctions hfs(env); + auto re = runEscrowWasm(allHFWasm, hfs, 0, escrowFunctionName, {}); + BEAST_EXPECT(!re.has_value()); + BEAST_EXPECT(re.error().ter == temBAD_AMOUNT); + } + + { + // max() gas + TestHostFunctions hfs(env); + auto re = runEscrowWasm( + allHFWasm, hfs, std::numeric_limits::max(), escrowFunctionName, {}); + checkResult(re, 1, 70'877); + } + + { // fail because trying to access nonexistent field + struct FieldNotFoundHostFunctions : public TestHostFunctions + { + explicit FieldNotFoundHostFunctions(Env& env) : TestHostFunctions(env) + { + } + [[nodiscard]] std::expected + getTxField(SField const& fname) const override + { + return std::unexpected(HostFunctionError::FieldNotFound); + } + }; + + FieldNotFoundHostFunctions hfs(env); + auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {}); + checkResult(re, -201, 29'502); + } + + { // fail because trying to allocate more than MAX_PAGES memory + struct OversizedFieldHostFunctions : public TestHostFunctions + { + explicit OversizedFieldHostFunctions(Env& env) : TestHostFunctions(env) + { + } + [[nodiscard]] std::expected + getTxField(SField const& fname) const override + { + return Bytes((128 + 1) * 64 * 1024, 1); + } + }; + + OversizedFieldHostFunctions hfs(env); + auto re = runEscrowWasm(allHFWasm, hfs, 100'000, escrowFunctionName, {}); + checkResult(re, -201, 29'502); + } + } + + void + testCodecovWasm() + { + testcase("Codecov wasm test"); + + using namespace test::jtx; + + Env env{*this}; + + auto const codecovWasm = hexToBytes(kCodecovTestsWasmHex); + TestHostFunctions hfs(env); + + auto const allowance = 204'624; + auto re = runEscrowWasm(codecovWasm, hfs, allowance, escrowFunctionName, {}); + + checkResult(re, 1, allowance); + } + + void + testBadAlign() + { + testcase("Wasm Bad Align"); + + // bad_align.c + auto const badAlignWasm = hexToBytes(kBadAlignWasmHex); + + using namespace test::jtx; + + Env env{*this}; + TestHostFunctions hfs(env); + auto imports = createWasmImport(hfs); + + { // Calls float_from_uint with bad alignment. + // Can be checked through codecov + auto& engine = WasmEngine::instance(); + + auto re = engine.run(badAlignWasm, hfs, 1'000'000, "test", {}, imports, env.journal); + if (BEAST_EXPECTS(re, transToken(re.error().ter))) + { + BEAST_EXPECTS(re->result == 0x47308594, std::to_string(re->result)); + } + } + + env.close(); + } + + void + testSwapBytes() + { + testcase("Wasm swap bytes"); + + uint64_t const swapDataU64 = 0x123456789abcdeffull; + uint64_t const reverseSwapDataU64 = 0xffdebc9a78563412ull; + int64_t const swapDataI64 = 0x123456789abcdeffll; + int64_t const reverseSwapDataI64 = 0xffdebc9a78563412ll; + + uint32_t const swapDataU32 = 0x12789aff; + uint32_t const reverseSwapDataU32 = 0xff9a7812; + int32_t const swapDataI32 = 0x12789aff; + int32_t const reverseSwapDataI32 = 0xff9a7812; + + uint16_t const swapDataU16 = 0x12ff; + uint16_t const reverseSwapDataU16 = 0xff12; + int16_t const swapDataI16 = 0x12ff; + int16_t const reverseSwapDataI16 = 0xff12; + + uint64_t b1 = swapDataU64; + int64_t b2 = swapDataI64; + b1 = adjustWasmEndianessHlp(b1); + b2 = adjustWasmEndianessHlp(b2); + BEAST_EXPECT(b1 == reverseSwapDataU64); + BEAST_EXPECT(b2 == reverseSwapDataI64); + b1 = adjustWasmEndianessHlp(b1); + b2 = adjustWasmEndianessHlp(b2); + BEAST_EXPECT(b1 == swapDataU64); + BEAST_EXPECT(b2 == swapDataI64); + + uint32_t b3 = swapDataU32; + int32_t b4 = swapDataI32; + b3 = adjustWasmEndianessHlp(b3); + b4 = adjustWasmEndianessHlp(b4); + BEAST_EXPECT(b3 == reverseSwapDataU32); + BEAST_EXPECT(b4 == reverseSwapDataI32); + b3 = adjustWasmEndianessHlp(b3); + b4 = adjustWasmEndianessHlp(b4); + BEAST_EXPECT(b3 == swapDataU32); + BEAST_EXPECT(b4 == swapDataI32); + + uint16_t b5 = swapDataU16; + int16_t b6 = swapDataI16; + b5 = adjustWasmEndianessHlp(b5); + b6 = adjustWasmEndianessHlp(b6); + BEAST_EXPECT(b5 == reverseSwapDataU16); + BEAST_EXPECT(b6 == reverseSwapDataI16); + b5 = adjustWasmEndianessHlp(b5); + b6 = adjustWasmEndianessHlp(b6); + BEAST_EXPECT(b5 == swapDataU16); + BEAST_EXPECT(b6 == swapDataI16); + } + + void + run() override + { + using namespace test::jtx; + + testGetDataHelperFunctions(); + testWasmLib(); + testBadWasm(); + testWasmLedgerSqn(); + + testHFCost(); + testEscrowWasmDN(); + + testCodecovWasm(); + + testBadAlign(); + testSwapBytes(); + } +}; + +BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl); + +} // namespace xrpl::test +*/ diff --git a/src/test/app/wasm_fixtures/.gitignore b/src/test/app/wasm_fixtures/.gitignore new file mode 100644 index 0000000000..08b2e8a256 --- /dev/null +++ b/src/test/app/wasm_fixtures/.gitignore @@ -0,0 +1,3 @@ +**/target +**/debug +*.wasm diff --git a/src/test/app/wasm_fixtures/all_host_functions/Cargo.lock b/src/test/app/wasm_fixtures/all_host_functions/Cargo.lock new file mode 100644 index 0000000000..48771d1506 --- /dev/null +++ b/src/test/app/wasm_fixtures/all_host_functions/Cargo.lock @@ -0,0 +1,171 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "all_host_functions" +version = "0.1.0" +dependencies = [ + "xrpl-wasm-stdlib", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[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.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[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-macros" +version = "0.1.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf" +dependencies = [ + "bs58", + "quote", + "sha2", + "syn", +] + +[[package]] +name = "xrpl-wasm-stdlib" +version = "0.8.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf" +dependencies = [ + "xrpl-macros", +] diff --git a/src/test/app/wasm_fixtures/all_host_functions/Cargo.toml b/src/test/app/wasm_fixtures/all_host_functions/Cargo.toml new file mode 100644 index 0000000000..fb0c44562a --- /dev/null +++ b/src/test/app/wasm_fixtures/all_host_functions/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "all_host_functions" +version = "0.1.0" +edition = "2024" + +# This empty workspace definition keeps this project independent of the parent workspace +[workspace] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" } + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" +opt-level = "z" +lto = true diff --git a/src/test/app/wasm_fixtures/all_host_functions/src/lib.rs b/src/test/app/wasm_fixtures/all_host_functions/src/lib.rs new file mode 100644 index 0000000000..a40aa91d6a --- /dev/null +++ b/src/test/app/wasm_fixtures/all_host_functions/src/lib.rs @@ -0,0 +1,799 @@ +#![cfg_attr(target_arch = "wasm32", no_std)] + +#[cfg(not(target_arch = "wasm32"))] +extern crate std; + +// +// Host Functions Test +// Tests 26 host functions (across 7 categories) +// +// With craft you can run this test with: +// craft test --project host_functions_test --test-case host_functions_test +// +// Amount Format Update: +// - XRP amounts now return as 8-byte serialized rippled objects +// - IOU and MPT amounts return in variable-length serialized format +// - Format details: https://xrpl.org/docs/references/protocol/binary-format#amount-fields +// +// Error Code Ranges: +// -100 to -199: Ledger Header Functions (3 functions) +// -200 to -299: Transaction Data Functions (5 functions) +// -300 to -399: Current Ledger Object Functions (4 functions) +// -400 to -499: Any Ledger Object Functions (5 functions) +// -500 to -599: Keylet Generation Functions (4 functions) +// -600 to -699: Utility Functions (4 functions) +// -700 to -799: Data Update Functions (1 function) +// + +use xrpl_std::core::current_tx::escrow_finish::EscrowFinish; +use xrpl_std::core::current_tx::traits::TransactionCommonFields; +use xrpl_std::host; +use xrpl_std::host::trace::{trace, trace_account_buf, trace_data, trace_num, DataRepr}; +use xrpl_std::sfield; + +#[unsafe(no_mangle)] +pub extern "C" fn escrow_finish() -> i32 { + let _ = trace("=== HOST FUNCTIONS TEST ==="); + let _ = trace("Testing 26 host functions"); + + // Category 1: Ledger Header Data Functions (3 functions) + // Error range: -100 to -199 + match test_ledger_header_functions() { + 0 => (), + err => return err, + } + + // Category 2: Transaction Data Functions (5 functions) + // Error range: -200 to -299 + match test_transaction_data_functions() { + 0 => (), + err => return err, + } + + // Category 3: Current Ledger Object Functions (4 functions) + // Error range: -300 to -399 + match test_current_ledger_object_functions() { + 0 => (), + err => return err, + } + + // Category 4: Any Ledger Object Functions (5 functions) + // Error range: -400 to -499 + match test_any_ledger_object_functions() { + 0 => (), + err => return err, + } + + // Category 5: Keylet Generation Functions (4 functions) + // Error range: -500 to -599 + match test_keylet_generation_functions() { + 0 => (), + err => return err, + } + + // Category 6: Utility Functions (4 functions) + // Error range: -600 to -699 + match test_utility_functions() { + 0 => (), + err => return err, + } + + // Category 7: Data Update Functions (1 function) + // Error range: -700 to -799 + match test_data_update_functions() { + 0 => (), + err => return err, + } + + let _ = trace("SUCCESS: All host function tests passed!"); + 1 // Success return code for WASM finish function +} + +/// Test Category 1: Ledger Header Data Functions (3 functions) +/// - get_ledger_sqn() - Get ledger sequence number +/// - get_parent_ledger_time() - Get parent ledger timestamp +/// - get_parent_ledger_hash() - Get parent ledger hash +fn test_ledger_header_functions() -> i32 { + let _ = trace("--- Category 1: Ledger Header Functions ---"); + + // Test 1.1: get_ledger_sqn() - should return current ledger sequence number + let mut sqn_buffer = [0u8; 4]; + let sqn_result = unsafe { host::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); + return -101; // Ledger sequence number test failed + } + let ledger_sqn = u32::from_be_bytes(sqn_buffer); + let _ = trace_num("Ledger sequence number:", ledger_sqn as i64); + + // Test 1.2: get_parent_ledger_time() - should return parent ledger timestamp + let mut time_buffer = [0u8; 4]; + let time_result = + unsafe { host::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); + return -102; // Parent ledger time test failed + } + let parent_ledger_time = u32::from_be_bytes(time_buffer); + let _ = trace_num("Parent ledger time:", parent_ledger_time as i64); + + // Test 1.3: get_parent_ledger_hash() - should return parent ledger hash (32 bytes) + let mut hash_buffer = [0u8; 32]; + let hash_result = + unsafe { host::parent_ldgr_hash(hash_buffer.as_mut_ptr(), hash_buffer.len()) }; + + if hash_result != 32 { + let _ = trace_num( + "ERROR: get_parent_ledger_hash wrong length:", + hash_result as i64, + ); + return -103; // Parent ledger hash test failed - should be exactly 32 bytes + } + let _ = trace_data("Parent ledger hash:", &hash_buffer, DataRepr::AsHex); + + let _ = trace("SUCCESS: Ledger header functions"); + 0 +} + +/// Test Category 2: Transaction Data Functions (5 functions) +/// Tests all functions for accessing current transaction data +fn test_transaction_data_functions() -> i32 { + let _ = trace("--- Category 2: Transaction Data Functions ---"); + + // Test 2.1: get_tx_field() - Basic transaction field access + // Test with Account field (required, 20 bytes) + let mut account_buffer = [0u8; 20]; + let account_len = unsafe { + host::tx_field( + sfield::Account.into(), + account_buffer.as_mut_ptr(), + account_buffer.len(), + ) + }; + + if account_len != 20 { + let _ = trace_num( + "ERROR: get_tx_field(Account) wrong length:", + account_len as i64, + ); + return -201; // Basic transaction field test failed + } + let _ = trace_account_buf("Transaction Account:", &account_buffer); + + // Test with Fee field (XRP amount - 8 bytes in new serialized format) + // New format: XRP amounts are always 8 bytes (positive: value | cPositive flag, negative: just value) + let mut fee_buffer = [0u8; 8]; + let fee_len = unsafe { + host::tx_field( + sfield::Fee.into(), + fee_buffer.as_mut_ptr(), + fee_buffer.len(), + ) + }; + + if fee_len != 8 { + let _ = trace_num( + "ERROR: get_tx_field(Fee) wrong length (expected 8 bytes for XRP):", + fee_len as i64, + ); + return -202; // Fee field test failed - XRP amounts should be exactly 8 bytes + } + let _ = trace_num("Transaction Fee length:", fee_len as i64); + let _ = trace_data( + "Transaction Fee (serialized XRP amount):", + &fee_buffer, + DataRepr::AsHex, + ); + + // Test with Sequence field (required, 4 bytes uint32) + let mut seq_buffer = [0u8; 4]; + let seq_len = unsafe { + host::tx_field( + sfield::Sequence.into(), + seq_buffer.as_mut_ptr(), + seq_buffer.len(), + ) + }; + + if seq_len != 4 { + let _ = trace_num( + "ERROR: get_tx_field(Sequence) wrong length:", + seq_len as i64, + ); + return -203; // Sequence field test failed + } + let _ = trace_data("Transaction Sequence:", &seq_buffer, DataRepr::AsHex); + + // NOTE: get_tx_field2() through get_tx_field6() have been deprecated. + // Use get_tx_field() with appropriate parameters for all transaction field access. + + // Test 2.2: get_tx_nested_field() - Nested field access with locator + let locator = [ + 0x01_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::tx_inner( + locator.as_ptr(), + locator.len(), + nested_buffer.as_mut_ptr(), + nested_buffer.len(), + ) + }; + + if nested_result < 0 { + let _ = trace_num( + "INFO: get_tx_nested_field not applicable:", + nested_result as i64, + ); + // Expected - locator may not match transaction structure + } else { + let _ = trace_num("Nested field length:", nested_result as i64); + let _ = trace_data( + "Nested field:", + &nested_buffer[..nested_result as usize], + DataRepr::AsHex, + ); + } + + // Test 2.3: get_tx_array_len() - Get array length + let signers_len = unsafe { host::tx_arr_len(sfield::Signers.into()) }; + let _ = trace_num("Signers array length:", signers_len as i64); + + 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::tx_inner_arr_len(locator.as_ptr(), locator.len()) }; + + if nested_array_len < 0 { + let _ = trace_num( + "INFO: get_tx_nested_array_len not applicable:", + nested_array_len as i64, + ); + } else { + let _ = trace_num("Nested array length:", nested_array_len as i64); + } + + let _ = trace("SUCCESS: Transaction data functions"); + 0 +} + +/// Test Category 3: Current Ledger Object Functions (4 functions) +/// Tests functions that access the current ledger object being processed +fn test_current_ledger_object_functions() -> i32 { + let _ = trace("--- Category 3: Current Ledger Object Functions ---"); + + // Test 3.1: get_current_ledger_obj_field() - Access field from current ledger object + // Test with Balance field (XRP amount - 8 bytes in new serialized format) + let mut balance_buffer = [0u8; 8]; + let balance_result = unsafe { + host::home_le_field( + sfield::Balance.into(), + balance_buffer.as_mut_ptr(), + balance_buffer.len(), + ) + }; + + if balance_result <= 0 { + let _ = trace_num( + "INFO: get_current_ledger_obj_field(Balance) failed (may be expected):", + balance_result as i64, + ); + // This might fail if current ledger object doesn't have balance field + } else if balance_result == 8 { + let _ = trace_num( + "Current object balance length (XRP amount):", + balance_result as i64, + ); + let _ = trace_data( + "Current object balance (serialized XRP amount):", + &balance_buffer, + DataRepr::AsHex, + ); + } else { + let _ = trace_num( + "Current object balance length (non-XRP amount):", + balance_result as i64, + ); + let _ = trace_data( + "Current object balance:", + &balance_buffer[..balance_result as usize], + DataRepr::AsHex, + ); + } + + // Test with Account field + let mut current_account_buffer = [0u8; 20]; + let current_account_result = unsafe { + host::home_le_field( + sfield::Account.into(), + current_account_buffer.as_mut_ptr(), + current_account_buffer.len(), + ) + }; + + if current_account_result <= 0 { + let _ = trace_num( + "INFO: get_current_ledger_obj_field(Account) failed:", + current_account_result as i64, + ); + } else { + let _ = trace_account_buf("Current ledger object account:", ¤t_account_buffer); + } + + // Test 3.2: get_current_ledger_obj_nested_field() - Nested field access + let locator = [ + 0x01_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::home_le_inner( + locator.as_ptr(), + locator.len(), + current_nested_buffer.as_mut_ptr(), + current_nested_buffer.len(), + ) + }; + + if current_nested_result < 0 { + let _ = trace_num( + "INFO: get_current_ledger_obj_nested_field not applicable:", + current_nested_result as i64, + ); + } else { + let _ = trace_num("Current nested field length:", current_nested_result as i64); + let _ = trace_data( + "Current nested field:", + ¤t_nested_buffer[..current_nested_result as usize], + DataRepr::AsHex, + ); + } + + // Test 3.3: get_current_ledger_obj_array_len() - Array length in current object + let current_array_len = unsafe { host::home_le_arr_len(sfield::Signers.into()) }; + let _ = trace_num( + "Current object Signers array length:", + current_array_len as i64, + ); + + // Test 3.4: get_current_ledger_obj_nested_array_len() - Nested array length + let current_nested_array_len = + unsafe { host::home_le_inner_arr_len(locator.as_ptr(), locator.len()) }; + + if current_nested_array_len < 0 { + let _ = trace_num( + "INFO: get_current_ledger_obj_nested_array_len not applicable:", + current_nested_array_len as i64, + ); + } else { + let _ = trace_num( + "Current nested array length:", + current_nested_array_len as i64, + ); + } + + let _ = trace("SUCCESS: Current ledger object functions"); + 0 +} + +/// Test Category 4: Any Ledger Object Functions (5 functions) +/// Tests functions that work with cached ledger objects +fn test_any_ledger_object_functions() -> i32 { + let _ = trace("--- Category 4: Any Ledger Object Functions ---"); + + // First we need to cache a ledger object to test the other functions + // Get the account from transaction and generate its keylet + let escrow_finish = EscrowFinish; + let account_id = escrow_finish.get_account().unwrap(); + + // Test 4.1: cache_ledger_obj() - Cache a ledger object + let mut keylet_buffer = [0u8; 32]; + let keylet_result = unsafe { + host::accountroot_id( + account_id.0.as_ptr(), + account_id.0.len(), + keylet_buffer.as_mut_ptr(), + keylet_buffer.len(), + ) + }; + + if keylet_result != 32 { + let _ = trace_num( + "ERROR: accountroot_id failed for caching test:", + keylet_result as i64, + ); + return -401; // Keylet generation failed for caching test + } + + let cache_result = unsafe { host::cache_le(keylet_buffer.as_ptr(), keylet_result as usize, 0) }; + + if cache_result <= 0 { + let _ = trace_num( + "INFO: cache_ledger_obj failed (expected with test fixtures):", + cache_result as i64, + ); + // Test fixtures may not contain the account object - this is expected + // We'll test the interface but expect failures + + // Test 4.2-4.5 with invalid slot (should fail gracefully) + let mut test_buffer = [0u8; 32]; + + // Test get_ledger_obj_field with invalid slot + let field_result = unsafe { + host::le_field( + 1, + sfield::Balance.into(), + test_buffer.as_mut_ptr(), + test_buffer.len(), + ) + }; + if field_result < 0 { + let _ = trace_num( + "INFO: get_ledger_obj_field failed as expected (no cached object):", + field_result as i64, + ); + } + + // Test get_ledger_obj_nested_field with invalid slot + let locator = [ + 0x01_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::le_inner( + 1, + locator.as_ptr(), + locator.len(), + test_buffer.as_mut_ptr(), + test_buffer.len(), + ) + }; + if nested_result < 0 { + let _ = trace_num( + "INFO: get_ledger_obj_nested_field failed as expected:", + nested_result as i64, + ); + } + + // Test get_ledger_obj_array_len with invalid slot + let array_result = unsafe { host::le_arr_len(1, sfield::Signers.into()) }; + if array_result < 0 { + let _ = trace_num( + "INFO: get_ledger_obj_array_len failed as expected:", + array_result as i64, + ); + } + + // Test get_ledger_obj_nested_array_len with invalid slot + let nested_array_result = + unsafe { host::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:", + nested_array_result as i64, + ); + } + + let _ = trace("SUCCESS: Any ledger object functions (interface tested)"); + return 0; + } + + // If we successfully cached an object, test the access functions + let slot = cache_result; + let _ = trace_num("Successfully cached object in slot:", slot as i64); + + // Test 4.2: get_ledger_obj_field() - Access field from cached object + let mut cached_balance_buffer = [0u8; 8]; + let cached_balance_result = unsafe { + host::le_field( + slot, + sfield::Balance.into(), + cached_balance_buffer.as_mut_ptr(), + cached_balance_buffer.len(), + ) + }; + + if cached_balance_result <= 0 { + let _ = trace_num( + "INFO: get_ledger_obj_field(Balance) failed:", + cached_balance_result as i64, + ); + } else if cached_balance_result == 8 { + let _ = trace_num( + "Cached object balance length (XRP amount):", + cached_balance_result as i64, + ); + let _ = trace_data( + "Cached object balance (serialized XRP amount):", + &cached_balance_buffer, + DataRepr::AsHex, + ); + } else { + let _ = trace_num( + "Cached object balance length (non-XRP amount):", + cached_balance_result as i64, + ); + let _ = trace_data( + "Cached object balance:", + &cached_balance_buffer[..cached_balance_result as usize], + DataRepr::AsHex, + ); + } + + // Test 4.3: get_ledger_obj_nested_field() - Nested field from cached object + let locator = [ + 0x01_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::le_inner( + slot, + locator.as_ptr(), + locator.len(), + cached_nested_buffer.as_mut_ptr(), + cached_nested_buffer.len(), + ) + }; + + if cached_nested_result < 0 { + let _ = trace_num( + "INFO: get_ledger_obj_nested_field not applicable:", + cached_nested_result as i64, + ); + } else { + let _ = trace_num("Cached nested field length:", cached_nested_result as i64); + let _ = trace_data( + "Cached nested field:", + &cached_nested_buffer[..cached_nested_result as usize], + DataRepr::AsHex, + ); + } + + // Test 4.4: get_ledger_obj_array_len() - Array length from cached object + let cached_array_len = unsafe { host::le_arr_len(slot, sfield::Signers.into()) }; + let _ = trace_num( + "Cached object Signers array length:", + cached_array_len as i64, + ); + + // Test 4.5: get_ledger_obj_nested_array_len() - Nested array length from cached object + let cached_nested_array_len = + unsafe { host::le_inner_arr_len(slot, locator.as_ptr(), locator.len()) }; + + if cached_nested_array_len < 0 { + let _ = trace_num( + "INFO: get_ledger_obj_nested_array_len not applicable:", + cached_nested_array_len as i64, + ); + } else { + let _ = trace_num( + "Cached nested array length:", + cached_nested_array_len as i64, + ); + } + + let _ = trace("SUCCESS: Any ledger object functions"); + 0 +} + +/// Test Category 5: Keylet Generation Functions (4 functions) +/// Tests keylet generation functions for different ledger entry types +fn test_keylet_generation_functions() -> i32 { + let _ = trace("--- Category 5: Keylet Generation Functions ---"); + + let escrow_finish = EscrowFinish; + let account_id = escrow_finish.get_account().unwrap(); + + // Test 5.1: 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(), + accountroot_id_buffer.as_mut_ptr(), + accountroot_id_buffer.len(), + ) + }; + + if accountroot_id_result != 32 { + let _ = trace_num( + "ERROR: accountroot_id failed:", + accountroot_id_result as i64, + ); + return -501; // Account keylet generation failed + } + 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_id( + account_id.0.as_ptr(), // Subject + account_id.0.len(), + account_id.0.as_ptr(), // Issuer - same account for test + account_id.0.len(), + b"TestType".as_ptr(), // Credential type + 9usize, // Length of "TestType" + credential_keylet_buffer.as_mut_ptr(), + credential_keylet_buffer.len(), + ) + }; + + if credential_keylet_result <= 0 { + let _ = trace_num( + "INFO: credential_keylet failed (expected - interface issue):", + credential_keylet_result as i64, + ); + // This is expected to fail due to unusual parameter types + } else { + let _ = trace_data( + "Credential keylet:", + &credential_keylet_buffer[..credential_keylet_result as usize], + DataRepr::AsHex, + ); + } + + // Test 5.3: escrow_keylet() - Generate keylet for escrow + let mut escrow_keylet_buffer = [0u8; 32]; + let sequence_number: i32 = 1000; + let sequence_number_bytes = sequence_number.to_be_bytes(); + let escrow_keylet_result = unsafe { + host::escrow_id( + account_id.0.as_ptr(), + account_id.0.len(), + sequence_number_bytes.as_ptr(), + sequence_number_bytes.len(), + escrow_keylet_buffer.as_mut_ptr(), + escrow_keylet_buffer.len(), + ) + }; + + if escrow_keylet_result != 32 { + let _ = trace_num("ERROR: escrow_keylet failed:", escrow_keylet_result as i64); + return -503; // Escrow keylet generation failed + } + let _ = trace_data("Escrow keylet:", &escrow_keylet_buffer, DataRepr::AsHex); + + // Test 5.4: oracle_keylet() - Generate keylet for oracle + let mut oracle_keylet_buffer = [0u8; 32]; + let document_id: i32 = 42; + let document_id_bytes = document_id.to_be_bytes(); + let oracle_keylet_result = unsafe { + host::oracle_id( + account_id.0.as_ptr(), + account_id.0.len(), + document_id_bytes.as_ptr(), + document_id_bytes.len(), + oracle_keylet_buffer.as_mut_ptr(), + oracle_keylet_buffer.len(), + ) + }; + + if oracle_keylet_result != 32 { + let _ = trace_num("ERROR: oracle_keylet failed:", oracle_keylet_result as i64); + return -504; // Oracle keylet generation failed + } + let _ = trace_data("Oracle keylet:", &oracle_keylet_buffer, DataRepr::AsHex); + + let _ = trace("SUCCESS: Keylet generation functions"); + 0 +} + +/// Test Category 6: Utility Functions (4 functions) +/// Tests utility functions for hashing, NFT access, and tracing +fn test_utility_functions() -> i32 { + let _ = trace("--- Category 6: Utility Functions ---"); + + // Test 6.1: compute_sha512_half() - SHA512 hash computation (first 32 bytes) + let test_data = b"Hello, XRPL WASM world!"; + let mut hash_output = [0u8; 32]; + let hash_result = unsafe { + host::sha512_half( + test_data.as_ptr(), + test_data.len(), + hash_output.as_mut_ptr(), + hash_output.len(), + ) + }; + + if hash_result != 32 { + let _ = trace_num("ERROR: compute_sha512_half failed:", hash_result as i64); + return -601; // SHA512 half computation failed + } + let _ = trace_data("Input data:", test_data, DataRepr::AsHex); + let _ = trace_data("SHA512 half hash:", &hash_output, DataRepr::AsHex); + + // Test 6.2: get_nft() - NFT data retrieval + let escrow_finish = EscrowFinish; + let account_id = escrow_finish.get_account().unwrap(); + let nft_id = [0u8; 32]; // Dummy NFT ID for testing + let mut nft_buffer = [0u8; 256]; + let nft_result = unsafe { + host::nft_uri( + account_id.0.as_ptr(), + account_id.0.len(), + nft_id.as_ptr(), + nft_id.len(), + nft_buffer.as_mut_ptr(), + nft_buffer.len(), + ) + }; + + if nft_result <= 0 { + let _ = trace_num( + "INFO: get_nft failed (expected - no such NFT):", + nft_result as i64, + ); + // This is expected - test account likely doesn't own the dummy NFT + } else { + let _ = trace_num("NFT data length:", nft_result as i64); + let _ = trace_data( + "NFT data:", + &nft_buffer[..nft_result as usize], + DataRepr::AsHex, + ); + } + + // Test 6.3: trace() - Debug logging with data + let trace_message = b"Test trace message"; + let trace_data_payload = b"payload"; + let trace_result = unsafe { + host::trace( + trace_message.as_ptr(), + trace_message.len(), + trace_data_payload.as_ptr(), + trace_data_payload.len(), + 1, // as_hex = true + ) + }; + + if trace_result < 0 { + let _ = trace_num("ERROR: trace() failed:", trace_result as i64); + return -603; // Trace function failed + } + let _ = trace_num("Trace function bytes written:", trace_result as i64); + + // Test 6.4: trace_num() - Debug logging with number + let test_number = 42i64; + let trace_num_result = trace_num("Test number trace", test_number); + + use xrpl_std::host::Result; + match trace_num_result { + Result::Ok(_) => { + let _ = trace_num("Trace_num function succeeded", 0); + } + Result::Err(_) => { + let _ = trace_num("ERROR: trace_num() failed:", -604); + return -604; // Trace number function failed + } + } + + let _ = trace("SUCCESS: Utility functions"); + 0 +} + +/// Test Category 7: Data Update Functions (1 function) +/// Tests the function for modifying the current ledger entry +fn test_data_update_functions() -> i32 { + let _ = trace("--- Category 7: Data Update Functions ---"); + + // Test 7.1: update_data() - Update current ledger entry data + let update_payload = b"Updated ledger entry data from WASM test"; + + let update_result = unsafe { host::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); + return -701; // Data update failed + } + + let _ = trace_data( + "Successfully updated ledger entry with:", + update_payload, + DataRepr::AsHex, + ); + let _ = trace("SUCCESS: Data update functions"); + 0 +} diff --git a/src/test/app/wasm_fixtures/all_keylets/Cargo.lock b/src/test/app/wasm_fixtures/all_keylets/Cargo.lock new file mode 100644 index 0000000000..5da5b26f66 --- /dev/null +++ b/src/test/app/wasm_fixtures/all_keylets/Cargo.lock @@ -0,0 +1,171 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "all_keylets" +version = "0.0.1" +dependencies = [ + "xrpl-wasm-stdlib", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[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.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[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-macros" +version = "0.1.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#21c522f34a24b460297ebb6be1822680459bf37e" +dependencies = [ + "bs58", + "quote", + "sha2", + "syn", +] + +[[package]] +name = "xrpl-wasm-stdlib" +version = "0.8.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#21c522f34a24b460297ebb6be1822680459bf37e" +dependencies = [ + "xrpl-macros", +] diff --git a/src/test/app/wasm_fixtures/all_keylets/Cargo.toml b/src/test/app/wasm_fixtures/all_keylets/Cargo.toml new file mode 100644 index 0000000000..ad53fd62b1 --- /dev/null +++ b/src/test/app/wasm_fixtures/all_keylets/Cargo.toml @@ -0,0 +1,21 @@ +[package] +edition = "2024" +name = "all_keylets" +version = "0.0.1" + +# This empty workspace definition keeps this project independent of the parent workspace +[workspace] + +[lib] +crate-type = ["cdylib"] + +[profile.release] +lto = true +opt-level = 's' +panic = "abort" + +[dependencies] +xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" } + +[profile.dev] +panic = "abort" diff --git a/src/test/app/wasm_fixtures/all_keylets/src/lib.rs b/src/test/app/wasm_fixtures/all_keylets/src/lib.rs new file mode 100644 index 0000000000..f0a4e5abb5 --- /dev/null +++ b/src/test/app/wasm_fixtures/all_keylets/src/lib.rs @@ -0,0 +1,176 @@ +#![cfg_attr(target_arch = "wasm32", no_std)] + +#[cfg(not(target_arch = "wasm32"))] +extern crate std; + +use crate::host::{Error, Result, Result::Err, Result::Ok}; +use xrpl_std::core::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::ledger_objects::LedgerObjectFieldGetter; +use xrpl_std::core::types::currency::Currency; +use xrpl_std::core::types::issue::{IouIssue, Issue, XrpIssue}; +use xrpl_std::core::types::mpt_id::MptId; +use xrpl_std::host; +use xrpl_std::host::trace::{trace, trace_acct, trace_data, trace_num, DataRepr}; +use xrpl_std::sfield; + +pub fn object_exists( + keylet_result: Result, + keylet_type: &str, + sfield: sfield::SField, +) -> Result { + let field = CODE; + match keylet_result { + Ok(keylet) => { + let _ = trace_data(keylet_type, &keylet, DataRepr::AsHex); + + 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.clone().into()); + match ledger_object::get_field(slot, new_field) { + Ok(data) => { + let _ = trace_data("Field data: ", &data.0, DataRepr::AsHex); + } + Err(result_code) => { + let _ = trace_num("Error getting field: ", result_code.into()); + return Err(result_code); + } + } + } else { + let _ = trace_num("Getting field: ", field.into()); + match ledger_object::get_field(slot, sfield) { + Ok(_data) => { + let _ = trace("Field data: retrieved"); + } + Err(result_code) => { + let _ = trace_num("Error getting field: ", result_code.into()); + return Err(result_code); + } + } + } + + Ok(true) + } + Err(error) => { + let _ = trace_num("Error getting keylet: ", error.into()); + Err(error) + } + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn escrow_finish() -> i32 { + let _ = trace("$$$$$ STARTING WASM EXECUTION $$$$$"); + + let escrow: CurrentEscrow = get_current_escrow(); + + let account = escrow.get_account().unwrap_or_panic(); + let _ = trace_acct("Account:", &account); + + let destination = escrow.get_destination().unwrap_or_panic(); + let _ = trace_acct("Destination:", &destination); + + let mut seq = 5; + + macro_rules! check_object_exists { + ($keylet:expr, $type:expr, $field:expr) => { + match object_exists($keylet, $type, $field) { + Ok(_exists) => { + // false isn't returned + let _ = trace(concat!( + $type, + " object exists, proceeding with escrow finish." + )); + } + Err(error) => { + let _ = trace_num("Current seq value:", seq.try_into().unwrap()); + return error.code(); + } + } + }; + } + + let 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 trustline_id = keylets::trustline_id(&account, &destination, ¤cy); + 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_id(&asset1, &asset2), "AMM", 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_id = keylets::credential_id(&account, &account, cred_type); + check_object_exists!(credential_id, "Credential", sfield::Subject); + seq += 1; + + let delegate_id = keylets::delegate_id(&account, &destination); + check_object_exists!(delegate_id, "Delegate", sfield::Account); + seq += 1; + + let deposit_preauth_id = keylets::deposit_preauth_id(&account, &destination); + check_object_exists!(deposit_preauth_id, "DepositPreauth", sfield::Account); + seq += 1; + + let did_id = keylets::did_id(&account); + check_object_exists!(did_id, "DID", sfield::Account); + seq += 1; + + let escrow_id = keylets::escrow_id(&account, seq); + check_object_exists!(escrow_id, "Escrow", sfield::Account); + seq += 1; + + 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_id, "MPTIssuance", sfield::Issuer); + seq += 1; + + let mptoken_id = keylets::mptoken_id(&mpt_id, &destination); + check_object_exists!(mptoken_id, "MPToken", sfield::Account); + + let nft_offer_id = keylets::nft_offer_id(&destination, 6); + check_object_exists!(nft_offer_id, "NFTokenOffer", sfield::Owner); + + let offer_id = keylets::offer_id(&account, seq); + check_object_exists!(offer_id, "Offer", sfield::Account); + seq += 1; + + let paychan_id = keylets::paychan_id(&account, &destination, seq); + check_object_exists!(paychan_id, "PayChannel", sfield::Account); + seq += 1; + + let pd_id = keylets::permissioned_domain_id(&account, seq); + check_object_exists!(pd_id, "PermissionedDomain", sfield::Owner); + seq += 1; + + 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_id = keylets::ticket_id(&account, seq); + check_object_exists!(ticket_id, "Ticket", sfield::Account); + seq += 1; + + 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. +} diff --git a/src/test/app/wasm_fixtures/bad_align.c b/src/test/app/wasm_fixtures/bad_align.c new file mode 100644 index 0000000000..560245e762 --- /dev/null +++ b/src/test/app/wasm_fixtures/bad_align.c @@ -0,0 +1,42 @@ +#include + +int32_t float_from_uint(uint8_t const *, int32_t, uint8_t *, int32_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]; + +int32_t test1() +{ + e_data1[1] = 0xFF; + e_data1[2] = 0xFF; + e_data1[3] = 0xFF; + e_data1[4] = 0xFF; + e_data1[5] = 0xFF; + e_data1[6] = 0xFF; + e_data1[7] = 0xFF; + e_data1[8] = 0xFF; + int32_t result = float_from_uint(&e_data1[1], 8, &e_data1[35], 12, 0); + return result >= 0 ? *((int32_t *)(&e_data1[36])) : result; +} + +int32_t test2() +{ + // Set up misaligned uint32 (seq) at offset 1 + e_data2[1] = 0xFF; + e_data2[2] = 0xFF; + e_data2[3] = 0xFF; + e_data2[4] = 0xFF; + // Set up valid non-zero AccountID (20 bytes) at offset 10 + for (int i = 0; i < 20; i++) + e_data2[10 + i] = i + 1; + // Call check_id with misaligned uint32 at &e_data2[1] to hit line 72 in + // HostFuncWrapper.cpp + 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; +} + +int32_t test() { return test1() + test2(); } diff --git a/src/test/app/wasm_fixtures/codecov_tests/Cargo.lock b/src/test/app/wasm_fixtures/codecov_tests/Cargo.lock new file mode 100644 index 0000000000..d7d91db071 --- /dev/null +++ b/src/test/app/wasm_fixtures/codecov_tests/Cargo.lock @@ -0,0 +1,171 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "codecov_tests" +version = "0.0.1" +dependencies = [ + "xrpl-wasm-stdlib", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[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.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[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-macros" +version = "0.1.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf" +dependencies = [ + "bs58", + "quote", + "sha2", + "syn", +] + +[[package]] +name = "xrpl-wasm-stdlib" +version = "0.8.0" +source = "git+https://github.com/ripple/xrpl-wasm-stdlib.git?branch=renames#9822d645870908a79d87a57b0244caa6359cb9cf" +dependencies = [ + "xrpl-macros", +] diff --git a/src/test/app/wasm_fixtures/codecov_tests/Cargo.toml b/src/test/app/wasm_fixtures/codecov_tests/Cargo.toml new file mode 100644 index 0000000000..1cc49ac490 --- /dev/null +++ b/src/test/app/wasm_fixtures/codecov_tests/Cargo.toml @@ -0,0 +1,18 @@ +[package] +edition = "2024" +name = "codecov_tests" +version = "0.0.1" + +# This empty workspace definition keeps this project independent of the parent workspace +[workspace] + +[lib] +crate-type = ["cdylib"] + +[profile.release] +lto = true +opt-level = 's' +panic = "abort" + +[dependencies] +xrpl-std = { git = "https://github.com/ripple/xrpl-wasm-stdlib.git", package = "xrpl-wasm-stdlib", branch = "renames" } diff --git a/src/test/app/wasm_fixtures/codecov_tests/src/host_bindings_loose.rs b/src/test/app/wasm_fixtures/codecov_tests/src/host_bindings_loose.rs new file mode 100644 index 0000000000..6204dff0a2 --- /dev/null +++ b/src/test/app/wasm_fixtures/codecov_tests/src/host_bindings_loose.rs @@ -0,0 +1,47 @@ +//TODO add docs after discussing the interface +//Note that Craft currently does not honor the rounding modes +#[allow(unused)] +pub const FLOAT_ROUNDING_MODES_TO_NEAREST: i32 = 0; +#[allow(unused)] +pub const FLOAT_ROUNDING_MODES_TOWARDS_ZERO: i32 = 1; +#[allow(unused)] +pub const FLOAT_ROUNDING_MODES_DOWNWARD: i32 = 2; +#[allow(unused)] +pub const FLOAT_ROUNDING_MODES_UPWARD: i32 = 3; + +// pub enum RippledRoundingModes{ +// ToNearest = 0, +// TowardsZero = 1, +// DOWNWARD = 2, +// UPWARD = 3 +// } + +#[allow(unused)] +#[link(wasm_import_module = "host_lib")] +unsafe extern "C" { + pub fn parent_ldgr_hash(out_buff_ptr: i32, out_buff_len: i32) -> i32; + + pub fn cache_le(keylet_ptr: i32, keylet_len: i32, cache_num: i32) -> i32; + + pub fn tx_inner_arr_len(locator_ptr: i32, locator_len: i32) -> i32; + + pub fn accountroot_id( + account_ptr: i32, + account_len: i32, + out_buff_ptr: *mut u8, + out_buff_len: usize, + ) -> i32; + + pub fn trustline_id( + account1_ptr: *const u8, + account1_len: usize, + account2_ptr: *const u8, + account2_len: usize, + currency_ptr: i32, + currency_len: i32, + out_buff_ptr: *mut u8, + out_buff_len: usize, + ) -> i32; + + pub fn trace_num(msg_read_ptr: i32, msg_read_len: i32, number: i64) -> i32; +} diff --git a/src/test/app/wasm_fixtures/codecov_tests/src/lib.rs b/src/test/app/wasm_fixtures/codecov_tests/src/lib.rs new file mode 100644 index 0000000000..59f16155d2 --- /dev/null +++ b/src/test/app/wasm_fixtures/codecov_tests/src/lib.rs @@ -0,0 +1,1782 @@ +#![cfg_attr(target_arch = "wasm32", no_std)] + +#[cfg(not(target_arch = "wasm32"))] +extern crate std; + +use core::panic; +use xrpl_std::core::current_tx::escrow_finish::{get_current_escrow_finish, EscrowFinish}; +use xrpl_std::core::current_tx::traits::TransactionCommonFields; +use xrpl_std::core::keylets; +use xrpl_std::core::locator::Locator; +use xrpl_std::core::types::blob::DEFAULT_BLOB_SIZE; +use xrpl_std::core::types::issue::Issue; +use xrpl_std::core::types::issue::XrpIssue; +use xrpl_std::core::types::mpt_id::MptId; +use xrpl_std::host; +use xrpl_std::host::error_codes; +use xrpl_std::host::trace::{trace, trace_num as trace_number}; +use xrpl_std::sfield; +use xrpl_std::types::XRPL_CONTRACT_DATA_SIZE; + +mod host_bindings_loose; +include!("host_bindings_loose.rs"); + +fn check_result(result: i32, expected: i32, test_name: &'static str) { + match result { + code if code == expected => { + let _ = trace_number(test_name, code.into()); + } + code if code >= 0 => { + let _ = trace(test_name); + let _ = trace_number("TEST FAILED", code.into()); + panic!("Unexpected success code: {}", code); + } + code => { + let _ = trace(test_name); + let _ = trace_number("TEST FAILED", code.into()); + panic!("Error code: {}", code); + } + } +} + +fn with_buffer(mut f: F) -> R +where + F: FnMut(*mut u8, usize) -> R, +{ + let mut buf = [0u8; N]; + f(buf.as_mut_ptr(), buf.len()) +} + +#[unsafe(no_mangle)] +pub extern "C" fn escrow_finish() -> i32 { + let _ = trace("$$$$$ STARTING WASM EXECUTION $$$$$"); + + // ######################################## + // Step #1: Test all host function happy paths + // Note: not testing all the keylet functions, + // that's in a separate test file (all_keylets). + // The float tests are also in a separate file (float_tests). + // ######################################## + with_buffer::<4, _, _>(|ptr, len| { + check_result(unsafe { host::ldgr_index(ptr, len) }, 4, "ldgr_index"); + }); + with_buffer::<4, _, _>(|ptr, len| { + check_result( + unsafe { host::parent_ldgr_time(ptr, len) }, + 4, + "parent_ldgr_time", + ); + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { host::parent_ldgr_hash(ptr, len) }, + 32, + "parent_ldgr_hash", + ); + }); + with_buffer::<4, _, _>(|ptr, len| { + check_result(unsafe { host::base_fee(ptr, len) }, 4, "base_fee"); + }); + let amendment_name: &[u8] = b"test_amendment"; + let amendment_id: [u8; 32] = [1; 32]; + check_result( + unsafe { host::amendment_enabled(amendment_name.as_ptr(), amendment_name.len()) }, + 1, + "amendment_enabled", + ); + check_result( + unsafe { host::amendment_enabled(amendment_id.as_ptr(), amendment_id.len()) }, + 1, + "amendment_enabled", + ); + let tx: EscrowFinish = get_current_escrow_finish(); + let account = tx.get_account().unwrap_or_panic(); // get_tx_field under the hood + let keylet = keylets::accountroot_id(&account).unwrap_or_panic(); // accountroot_id under the hood + check_result( + unsafe { host::cache_le(keylet.as_ptr(), keylet.len(), 0) }, + 1, + "cache_le", + ); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::home_le_field(sfield::Account.into(), ptr, len) }, + 20, + "home_le_field", + ); + }); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::le_field(1, sfield::Account.into(), ptr, len) }, + 20, + "le_field", + ); + }); + let mut locator = Locator::new(); + locator.pack(sfield::Account); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::tx_inner(locator.as_ptr(), locator.len(), ptr, len) }, + 20, + "tx_inner", + ); + }); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::home_le_inner(locator.as_ptr(), locator.len(), ptr, len) }, + 20, + "home_le_inner", + ); + }); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::le_inner(1, locator.as_ptr(), locator.len(), ptr, len) }, + 20, + "le_inner", + ); + }); + check_result( + unsafe { host::tx_arr_len(sfield::Memos.into()) }, + 32, + "tx_arr_len", + ); + check_result( + unsafe { host::home_le_arr_len(sfield::Memos.into()) }, + 32, + "home_le_arr_len", + ); + check_result( + unsafe { host::le_arr_len(1, sfield::Memos.into()) }, + 32, + "le_arr_len", + ); + check_result( + unsafe { host::tx_inner_arr_len(locator.as_ptr(), locator.len()) }, + 32, + "tx_inner_arr_len", + ); + check_result( + unsafe { host::home_le_inner_arr_len(locator.as_ptr(), locator.len()) }, + 32, + "home_le_inner_arr_len", + ); + check_result( + unsafe { host::le_inner_arr_len(1, locator.as_ptr(), locator.len()) }, + 32, + "le_inner_arr_len", + ); + check_result( + unsafe { host::set_data(account.0.as_ptr(), account.0.len()) }, + 20, + "set_data", + ); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { host::sha512_half(locator.as_ptr(), locator.len(), ptr, len) }, + 32, + "sha512_half", + ); + }); + let message: &[u8] = b"test message"; + let pubkey: &[u8] = b"test pubkey"; //tx.get_public_key().unwrap_or_panic(); + let signature: &[u8] = b"test signature"; + check_result( + unsafe { + host::check_sig( + message.as_ptr(), + message.len(), + pubkey.as_ptr(), + pubkey.len(), + signature.as_ptr(), + signature.len(), + ) + }, + 1, + "check_sig", + ); + + let nft_id: [u8; 32] = amendment_id; + with_buffer::<18, _, _>(|ptr, len| { + check_result( + unsafe { + host::nft_uri( + account.0.as_ptr(), + account.0.len(), + nft_id.as_ptr(), + nft_id.len(), + ptr, + len, + ) + }, + 18, + "nft_uri", + ) + }); + with_buffer::<20, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_issuer(nft_id.as_ptr(), nft_id.len(), ptr, len) }, + 20, + "nft_issuer", + ) + }); + with_buffer::<4, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_taxon(nft_id.as_ptr(), nft_id.len(), ptr, len) }, + 4, + "nft_taxon", + ) + }); + check_result( + unsafe { host::nft_flags(nft_id.as_ptr(), nft_id.len()) }, + 8, + "nft_flags", + ); + check_result( + unsafe { host::nft_xfer_fee(nft_id.as_ptr(), nft_id.len()) }, + 10, + "nft_xfer_fee", + ); + with_buffer::<4, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_serial(nft_id.as_ptr(), nft_id.len(), ptr, len) }, + 4, + "nft_serial", + ) + }); + let message = "testing trace"; + check_result( + unsafe { + host::trace_acct( + message.as_ptr(), + message.len(), + account.0.as_ptr(), + account.0.len(), + ) + }, + 0, + "trace_acct", + ); + let amount = &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F]; // 95 drops of XRP + check_result( + unsafe { + host::trace_amt( + message.as_ptr(), + message.len(), + amount.as_ptr(), + amount.len(), + ) + }, + 0, + "trace_amt", + ); + let amount = &[0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; // 0 drops of XRP + check_result( + unsafe { + host::trace_amt( + message.as_ptr(), + message.len(), + amount.as_ptr(), + amount.len(), + ) + }, + 0, + "trace_amt_zero", + ); + + // ######################################## + // Step #2: Test set_data edge cases + // ######################################## + check_result( + unsafe { host_bindings_loose::parent_ldgr_hash(-1, 4) }, + error_codes::INVALID_PARAMS, + "parent_ldgr_hash_neg_ptr", + ); + with_buffer::<4, _, _>(|ptr, _len| { + check_result( + unsafe { host_bindings_loose::parent_ldgr_hash(ptr as i32, -1) }, + error_codes::INVALID_PARAMS, + "parent_ldgr_hash_neg_len", + ) + }); + with_buffer::<3, _, _>(|ptr, len| { + check_result( + unsafe { host_bindings_loose::parent_ldgr_hash(ptr as i32, len as i32) }, + error_codes::BUFFER_TOO_SMALL, + "parent_ldgr_hash_buf_too_small", + ) + }); + with_buffer::<4, _, _>(|ptr, _len| { + check_result( + unsafe { host_bindings_loose::parent_ldgr_hash(ptr as i32, 1_000_000_000) }, + error_codes::POINTER_OUT_OF_BOUNDS, + "parent_ldgr_hash_len_too_long", + ) + }); + + // ######################################## + // Step #3: Test getData[Type] edge cases + // ######################################## + + // SField + check_result( + unsafe { host::tx_arr_len(2) }, // not a valid SField value + error_codes::INVALID_FIELD, + "tx_arr_len_invalid_sfield", + ); + + // Slice + check_result( + unsafe { host_bindings_loose::tx_inner_arr_len(-1, locator.len() as i32) }, + error_codes::INVALID_PARAMS, + "tx_inner_arr_len_neg_ptr", + ); + check_result( + unsafe { host_bindings_loose::tx_inner_arr_len(locator.as_ptr() as i32, -1) }, + error_codes::INVALID_PARAMS, + "tx_inner_arr_len_neg_len", + ); + let long_len = DEFAULT_BLOB_SIZE + 1; + check_result( + unsafe { host_bindings_loose::tx_inner_arr_len(locator.as_ptr() as i32, long_len as i32) }, + error_codes::DATA_FIELD_TOO_LARGE, + "tx_inner_arr_len_too_long", + ); + check_result( + unsafe { + host_bindings_loose::tx_inner_arr_len( + locator.as_ptr() as i32 + 1_000_000_000, + locator.len() as i32, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "tx_inner_arr_len_ptr_oob", + ); + + // uint32 + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::check_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr().wrapping_add(1_000_000_000), + 8, + ptr, + len, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "check_id_oob_len_u32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::check_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "check_id_wrong_len_u32", + ) + }); + + // uint64 + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_from_uint( + locator.as_ptr().wrapping_add(1_000_000_000), + 8, + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_from_uint_len_oob", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_from_uint( + locator.as_ptr(), + locator.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::INVALID_PARAMS, + "float_from_uint_wrong_len_uint64", + ) + }); + + // uint256 + check_result( + unsafe { + host_bindings_loose::cache_le( + locator.as_ptr() as i32 + 1_000_000_000, + locator.len() as i32, + 1, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "cache_le_ptr_oob", + ); + check_result( + unsafe { host_bindings_loose::cache_le(locator.as_ptr() as i32, locator.len() as i32, 1) }, + error_codes::INVALID_PARAMS, + "cache_le_wrong_len", + ); + + // AccountID + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host_bindings_loose::accountroot_id( + locator.as_ptr() as i32 + 1_000_000_000, + locator.len() as i32, + ptr, + len, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "accountroot_id_len_oob", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host_bindings_loose::accountroot_id( + locator.as_ptr() as i32, + locator.len() as i32, + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "accountroot_id_wrong_len", + ) + }); + + // Currency + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host_bindings_loose::trustline_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + locator.as_ptr() as i32 + 1_000_000_000, + locator.len() as i32, + ptr, + len, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trustline_id_len_oob_currency", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host_bindings_loose::trustline_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + locator.as_ptr() as i32, + locator.len() as i32, + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "trustline_id_wrong_len_currency", + ) + }); + + // Issue + let asset1_bytes = Issue::XRP(XrpIssue {}).as_bytes(); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + asset1_bytes.as_ptr(), + asset1_bytes.len(), + locator.as_ptr().wrapping_add(1_000_000_000), + locator.len(), + ptr, + len, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "amm_id_len_oob_asset2", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + asset1_bytes.as_ptr(), + asset1_bytes.len(), + locator.as_ptr(), + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "amm_id_len_wrong_len_asset2", + ) + }); + let currency: &[u8] = b"USD00000000000000000"; // 20 bytes + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + asset1_bytes.as_ptr(), + asset1_bytes.len(), + currency.as_ptr(), + currency.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "amm_id_len_wrong_non_xrp_currency_len", + ) + }); + let xrp_issue: &[u8] = &[0; 40]; // 40 bytes + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + xrp_issue.as_ptr(), + xrp_issue.len(), + asset1_bytes.as_ptr(), + asset1_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "amm_id_len_wrong_xrp_currency_len", + ) + }); + let mptid = MptId::new(1, account); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + mptid.as_ptr(), + mptid.len(), + asset1_bytes.as_ptr(), + asset1_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "amm_id_mpt", + ) + }); + + // string + check_result( + unsafe { + host_bindings_loose::trace_num( + locator.as_ptr() as i32 + 1_000_000_000, + locator.len() as i32, + 42, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_num_oob_str", + ); + + // ######################################## + // Step #4: Test other host function edge cases + // ######################################## + + // invalid SFields + + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::tx_field(2, ptr, len) }, + error_codes::INVALID_FIELD, + "tx_field_invalid_sfield", + ); + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::home_le_field(2, ptr, len) }, + error_codes::INVALID_FIELD, + "home_le_field_invalid_sfield", + ); + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::le_field(1, 2, ptr, len) }, + error_codes::INVALID_FIELD, + "le_field_invalid_sfield", + ); + }); + check_result( + unsafe { host::tx_arr_len(2) }, + error_codes::INVALID_FIELD, + "tx_arr_len_invalid_sfield", + ); + check_result( + unsafe { host::home_le_arr_len(2) }, + error_codes::INVALID_FIELD, + "home_le_arr_len_invalid_sfield", + ); + check_result( + unsafe { host::le_arr_len(1, 2) }, + error_codes::INVALID_FIELD, + "le_arr_len_invalid_sfield", + ); + + // invalid Slice + + check_result( + unsafe { host::amendment_enabled(amendment_name.as_ptr(), long_len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "amendment_enabled_too_big_slice", + ); + check_result( + unsafe { host::amendment_enabled(amendment_name.as_ptr(), 65) }, + error_codes::DATA_FIELD_TOO_LARGE, + "amendment_enabled_too_long", + ); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::tx_inner(locator.as_ptr(), long_len, ptr, len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "tx_inner_too_big_slice", + ); + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::home_le_inner(locator.as_ptr(), long_len, ptr, len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "home_le_inner_too_big_slice", + ); + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::le_inner(1, locator.as_ptr(), long_len, ptr, len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "le_inner_too_big_slice", + ); + }); + check_result( + unsafe { host::tx_inner_arr_len(locator.as_ptr(), long_len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "tx_inner_arr_len_too_big_slice", + ); + check_result( + unsafe { host::home_le_inner_arr_len(locator.as_ptr(), long_len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "home_le_inner_arr_len_too_big_slice", + ); + check_result( + unsafe { host::le_inner_arr_len(1, locator.as_ptr(), long_len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "le_inner_arr_len_too_big_slice", + ); + let too_big_data_len = XRPL_CONTRACT_DATA_SIZE + 1; + check_result( + unsafe { host::set_data(locator.as_ptr(), too_big_data_len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "set_data_too_big_slice", + ); + check_result( + unsafe { + host::check_sig( + message.as_ptr(), + long_len, + pubkey.as_ptr(), + pubkey.len(), + signature.as_ptr(), + signature.len(), + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "check_sig", + ); + check_result( + unsafe { + host::check_sig( + message.as_ptr(), + message.len(), + pubkey.as_ptr(), + long_len, + signature.as_ptr(), + signature.len(), + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "check_sig", + ); + check_result( + unsafe { + host::check_sig( + message.as_ptr(), + message.len(), + pubkey.as_ptr(), + pubkey.len(), + signature.as_ptr(), + long_len, + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "check_sig", + ); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::sha512_half(locator.as_ptr(), long_len, ptr, len) }, + error_codes::DATA_FIELD_TOO_LARGE, + "sha512_half_too_big_slice", + ); + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::amm_id( + asset1_bytes.as_ptr(), + long_len, + asset1_bytes.as_ptr(), + asset1_bytes.len(), + ptr, + len, + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "amm_id_too_big_slice", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::credential_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), + long_len, + ptr, + len, + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "credential_id_too_big_slice", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::mptoken_id( + mptid.as_ptr(), + long_len, + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "mptoken_id_too_big_slice_mptid", + ) + }); + check_result( + unsafe { + host::trace( + message.as_ptr(), + message.len(), + locator.as_ptr().wrapping_add(1_000_000_000), + locator.len(), + 0, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_oob_slice", + ); + let float: [u8; 8] = [0xD4, 0x83, 0x8D, 0x7E, 0xA4, 0xC6, 0x80, 0x00]; + check_result( + unsafe { + host::trace_xfloat( + message.as_ptr(), + message.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_xfloat_oob_slice", + ); + check_result( + unsafe { + host::trace_amt( + message.as_ptr(), + message.len(), + locator.as_ptr().wrapping_add(1_000_000_000), + locator.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_amt_oob_slice", + ); + check_result( + unsafe { + host::float_cmp( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + float.as_ptr(), + float.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_cmp_oob_slice1", + ); + check_result( + unsafe { + host::float_cmp( + float.as_ptr(), + float.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_cmp_oob_slice2", + ); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_add( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + float.as_ptr(), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_add_oob_slice1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_add( + float.as_ptr(), + float.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_add_oob_slice2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_sub( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + float.as_ptr(), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_sub_oob_slice1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_sub( + float.as_ptr(), + float.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_sub_oob_slice2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_mult( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + float.as_ptr(), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_mult_oob_slice1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_mult( + float.as_ptr(), + float.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_mult_oob_slice2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_div( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + float.as_ptr(), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_div_oob_slice1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_div( + float.as_ptr(), + float.len(), + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_div_oob_slice2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_root( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + 3, + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_root_oob_slice", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::float_pow( + float.as_ptr().wrapping_add(1_000_000_000), + float.len(), + 3, + ptr, + len, + FLOAT_ROUNDING_MODES_TO_NEAREST, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "float_pow_oob_slice", + ) + }); + + // invalid UInt32 + + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::escrow_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "escrow_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::mpt_issuance_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "mpt_issuance_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::nft_offer_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "nft_offer_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::offer_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "offer_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::oracle_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "oracle_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::paychan_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "paychan_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::permissioned_domain_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "permissioned_domain_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::ticket_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "ticket_id_wrong_size_uint32", + ) + }); + with_buffer::<32, _, _>(|ptr, len| { + check_result( + unsafe { + host::vault_id( + account.0.as_ptr(), + account.0.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "vault_id_wrong_size_uint32", + ) + }); + + // invalid UInt256 + + check_result( + unsafe { host::cache_le(locator.as_ptr(), locator.len(), 0) }, + error_codes::INVALID_PARAMS, + "cache_le_wrong_size_uint256", + ); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::nft_uri( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "nft_uri_wrong_size_uint256", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_issuer(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "nft_issuer_wrong_size_uint256", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_taxon(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "nft_taxon_wrong_size_uint256", + ) + }); + check_result( + unsafe { host::nft_flags(locator.as_ptr(), locator.len()) }, + error_codes::INVALID_PARAMS, + "nft_flags_wrong_size_uint256", + ); + check_result( + unsafe { host::nft_xfer_fee(locator.as_ptr(), locator.len()) }, + error_codes::INVALID_PARAMS, + "nft_xfer_fee_wrong_size_uint256", + ); + with_buffer::<4, _, _>(|ptr, len| { + check_result( + unsafe { host::nft_serial(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "nft_serial_wrong_size_uint256", + ) + }); + + // invalid AccountID + + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::accountroot_id(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "accountroot_id_wrong_size_account_id", + ) + }); + let seq: i32 = 1; + let seq_bytes = seq.to_be_bytes(); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::check_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "check_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::credential_id( + locator.as_ptr(), // invalid AccountID size + locator.len(), + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // valid slice size + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "credential_id_wrong_size_account_id1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::credential_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // invalid AccountID size + locator.len(), + locator.as_ptr(), // valid slice size + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "credential_id_wrong_size_account_id2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::delegate_id( + locator.as_ptr(), // invalid AccountID size + locator.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "delegate_id_wrong_size_account_id1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::delegate_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // invalid AccountID size + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "delegate_id_wrong_size_account_id2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::deposit_preauth_id( + locator.as_ptr(), // invalid AccountID size + locator.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "deposit_preauth_id_wrong_size_account_id1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::deposit_preauth_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // invalid AccountID size + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "deposit_preauth_id_wrong_size_account_id2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::did_id(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "did_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::escrow_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "escrow_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::trustline_id( + locator.as_ptr(), // invalid AccountID size + locator.len(), + account.0.as_ptr(), + account.0.len(), + currency.as_ptr(), + currency.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "trustline_id_wrong_size_account_id1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::trustline_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // invalid AccountID size + locator.len(), + currency.as_ptr(), + currency.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "trustline_id_wrong_size_account_id2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::mpt_issuance_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "mpt_issuance_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::mptoken_id( + mptid.as_ptr(), + mptid.len(), + locator.as_ptr(), + locator.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "mptoken_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::nft_offer_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "nft_offer_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::offer_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "offer_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::oracle_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "oracle_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::paychan_id( + locator.as_ptr(), // invalid AccountID size + locator.len(), + account.0.as_ptr(), + account.0.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "paychan_id_wrong_size_account_id1", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::paychan_id( + account.0.as_ptr(), + account.0.len(), + locator.as_ptr(), // invalid AccountID size + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "paychan_id_wrong_size_account_id2", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::permissioned_domain_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "permissioned_domain_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { host::signers_id(locator.as_ptr(), locator.len(), ptr, len) }, + error_codes::INVALID_PARAMS, + "signers_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::ticket_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "ticket_id_wrong_size_account_id", + ) + }); + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::vault_id( + locator.as_ptr(), + locator.len(), + seq_bytes.as_ptr(), + seq_bytes.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "vault_id_wrong_size_account_id", + ) + }); + let uint256: &[u8] = b"00000000000000000000000000000001"; + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::nft_uri( + locator.as_ptr(), + locator.len(), + uint256.as_ptr(), + uint256.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "nft_uri_wrong_size_account_id", + ) + }); + check_result( + unsafe { + host::trace_acct( + message.as_ptr(), + message.len(), + locator.as_ptr(), + locator.len(), + ) + }, + error_codes::INVALID_PARAMS, + "trace_acct_wrong_size_account_id", + ); + + // invalid Currency was already tested above + // invalid string + + check_result( + unsafe { + host::trace( + message.as_ptr().wrapping_add(1_000_000_000), + message.len(), + uint256.as_ptr(), + uint256.len(), + 0, + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_oob_string", + ); + check_result( + unsafe { + host::trace_xfloat( + message.as_ptr().wrapping_add(1_000_000_000), + message.len(), + float.as_ptr(), + float.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_xfloat_oob_string", + ); + check_result( + unsafe { + host::trace_acct( + message.as_ptr().wrapping_add(1_000_000_000), + message.len(), + account.0.as_ptr(), + account.0.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_acct_oob_string", + ); + check_result( + unsafe { + host::trace_amt( + message.as_ptr().wrapping_add(1_000_000_000), + message.len(), + amount.as_ptr(), + amount.len(), + ) + }, + error_codes::POINTER_OUT_OF_BOUNDS, + "trace_amt_oob_string", + ); + + // trace too large + + check_result( + unsafe { + host::trace( + locator.as_ptr(), + locator.len(), + locator.as_ptr(), + long_len, + 0, + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "trace_too_long", + ); + check_result( + unsafe { host::trace_num(locator.as_ptr(), long_len, 1) }, + error_codes::DATA_FIELD_TOO_LARGE, + "trace_num_too_long", + ); + check_result( + unsafe { host::trace_xfloat(message.as_ptr(), long_len, float.as_ptr(), float.len()) }, + error_codes::DATA_FIELD_TOO_LARGE, + "trace_xfloat_too_long", + ); + check_result( + unsafe { + host::trace_acct( + message.as_ptr(), + long_len, + account.0.as_ptr(), + account.0.len(), + ) + }, + error_codes::DATA_FIELD_TOO_LARGE, + "trace_acct_too_long", + ); + check_result( + unsafe { host::trace_amt(message.as_ptr(), long_len, amount.as_ptr(), amount.len()) }, + error_codes::DATA_FIELD_TOO_LARGE, + "trace_amt_too_long", + ); + + // trace amount errors + + check_result( + unsafe { + host::trace_amt( + message.as_ptr(), + message.len(), + locator.as_ptr(), + locator.len(), + ) + }, + error_codes::INVALID_PARAMS, + "trace_amt_wrong_length", + ); + + // other misc errors + + with_buffer::<2, _, _>(|ptr, len| { + check_result( + unsafe { + host::mptoken_id( + locator.as_ptr(), + locator.len(), + account.0.as_ptr(), + account.0.len(), + ptr, + len, + ) + }, + error_codes::INVALID_PARAMS, + "mptoken_id_mptid_wrong_length", + ) + }); + check_result( + unsafe { + host::trace( + message.as_ptr(), + message.len(), + locator.as_ptr(), + locator.len(), + 2, + ) + }, + error_codes::INVALID_PARAMS, + "trace_invalid_as_hex", + ); + + // ensure that the Slice index desync issue is fixed + let empty: &[u8] = b""; + check_result( + unsafe { + host::trace_acct( + empty.as_ptr(), + empty.len(), + account.0.as_ptr(), + account.0.len(), + ) + }, + 0, + "trace_acct_check_desync", + ); + + 1 // <-- If we get here, finish the escrow. +} diff --git a/src/test/app/wasm_fixtures/copyFixtures.py b/src/test/app/wasm_fixtures/copyFixtures.py new file mode 100644 index 0000000000..8e457b71e2 --- /dev/null +++ b/src/test/app/wasm_fixtures/copyFixtures.py @@ -0,0 +1,287 @@ +# cspell: disable +import os +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 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 = 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() + + pattern = rf'extern std::string const {fixture_name} =[ \n]+"[^;]*;' + if re.search(pattern, cpp_content, flags=re.MULTILINE): + updated_cpp_content = re.sub( + pattern, + f'extern std::string const {fixture_name} = "{wasm}";', + cpp_content, + flags=re.MULTILINE, + ) + else: + with open(h_path, "r", encoding="utf8") as f: + h_content = f.read() + updated_h_content = ( + h_content.rstrip() + f"\n\nextern std::string const {fixture_name};\n" + ) + with open(h_path, "w", encoding="utf8") as f: + f.write(updated_h_content) + updated_cpp_content = ( + cpp_content.rstrip() + + f'\n\nextern std::string const {fixture_name} = "{wasm}";\n' + ) + + with open(cpp_path, "w", encoding="utf8") as f: + f.write(updated_cpp_content) + + +def read_wasm_hex(path): + with open(path, "rb") as f: + return f.read().hex() + + +def process_rust(project_name): + 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( + ["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) + + update_fixture(project_name, read_wasm_hex(wasm_location)) + + +def process_c(project_name): + 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, 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) + + 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 []") + sys.exit(1) + + if len(sys.argv) == 2: + 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_wat(project_name) + print("Fixture has been processed.") + else: + dirs = [ + 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(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 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.") diff --git a/src/test/app/wasm_fixtures/fixtures.cpp b/src/test/app/wasm_fixtures/fixtures.cpp new file mode 100644 index 0000000000..d0cc1a2c13 --- /dev/null +++ b/src/test/app/wasm_fixtures/fixtures.cpp @@ -0,0 +1,663 @@ +// Not built. The only reader of these blobs is the disabled suite in Wasm_test.cpp, so they +// are left out of the build and cost neither a translation unit nor static-init time. +// Regenerate the hex with copyFixtures.py. +// +// TODO: consider moving these to separate files (and figure out the build) + +/* +#include + +#include + +extern std::string const kLedgerSqnWasmHex = + "0061736d01000000010e0360027f7f017f6000006000017f02120103656e760a6c6467725f696e6465780000030302" + "01020503010002063f0a7f01418088040b7f004180080b7f004180080b7f004180080b7f00418088040b7f00418008" + "0b7f00418088040b7f00418080080b7f0041000b7f0041010b07b1010c066d656d6f72790200115f5f7761736d5f63" + "616c6c5f63746f727300010d657363726f775f66696e69736800020c5f5f64736f5f68616e646c6503010a5f5f6461" + "74615f656e6403020b5f5f737461636b5f6c6f7703030c5f5f737461636b5f6869676803040d5f5f676c6f62616c5f" + "6261736503050b5f5f686561705f6261736503060a5f5f686561705f656e6403070d5f5f6d656d6f72795f62617365" + "03080c5f5f7461626c655f6261736503090a3d0202000b3801037f230041106b220024002000410c6a410410002101" + "200028020c2102200041106a2400200141054100200241054f1b20014100481b0b007f0970726f647563657273010c" + "70726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b202868747470733a2f2f6769" + "746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162346235613264623538323935386166316565" + "33303861373930636664623432626432343732302900490f7461726765745f6665617475726573042b0f6d75746162" + "6c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c" + "7565"; + +extern std::string const kAllHostFunctionsWasmHex = + "0061736d0100000001540c60027f7f017f60037f7f7f017f60047f7f7f7f017f60017f017f60067f7f7f7f7f7f017f" + "60037f7f7f0060057f7f7f7f7f017f60037f7f7e017f60087f7f7f7f7f7f7f7f017f60017f0060027f7f006000017f" + "02dc041a08686f73745f6c69620874785f6669656c64000108686f73745f6c69620974726163655f6e756d00070868" + "6f73745f6c6962057472616365000608686f73745f6c69620a6c6467725f696e646578000008686f73745f6c696210" + "706172656e745f6c6467725f74696d65000008686f73745f6c696210706172656e745f6c6467725f68617368000008" + "686f73745f6c69620874785f696e6e6572000208686f73745f6c69620a74785f6172725f6c656e000308686f73745f" + "6c69621074785f696e6e65725f6172725f6c656e000008686f73745f6c69620d686f6d655f6c655f6669656c640001" + "08686f73745f6c69620d686f6d655f6c655f696e6e6572000208686f73745f6c69620f686f6d655f6c655f6172725f" + "6c656e000308686f73745f6c696215686f6d655f6c655f696e6e65725f6172725f6c656e000008686f73745f6c6962" + "0863616368655f6c65000108686f73745f6c69620d63726564656e7469616c5f6964000808686f73745f6c69620965" + "7363726f775f6964000408686f73745f6c6962096f7261636c655f6964000408686f73745f6c69620b736861353132" + "5f68616c66000208686f73745f6c6962076e66745f757269000408686f73745f6c6962087365745f64617461000008" + "686f73745f6c6962086c655f6669656c64000208686f73745f6c6962086c655f696e6e6572000608686f73745f6c69" + "620a6c655f6172725f6c656e000008686f73745f6c6962106c655f696e6e65725f6172725f6c656e000108686f7374" + "5f6c69620e6163636f756e74726f6f745f6964000208686f73745f6c69620a74726163655f616363740002030c0b09" + "0a05050b05000101030005030100110619037f01418080c0000b7f0041af99c0000b7f0041b099c0000b073504066d" + "656d6f727902000d657363726f775f66696e697368001e0a5f5f646174615f656e6403010b5f5f686561705f626173" + "6503020a911e0b990101027f230041306b220124002000027f418180202001411c6a4114100022024114470440417f" + "20022002417f4e1b210241010c010b200020012f001c3b0001200041036a2001411e6a2d00003a0000200120012900" + "233703082001200141286a29000037000d200128001f21022000410d6a200129000d37000020002001290308370208" + "41000b3a000020002002360204200141306a24000b460020012d00004101460440418080c000410b20013402041001" + "000b20002001290001370000200041106a200141116a280000360000200041086a200141096a2900003700000b1900" + "200241094f0440000b20002002360204200020013602000b1900200241214f0440000b200020023602042000200136" + "02000ba91b01097f230041b0036b22002400418b80c000411b41014100410010021a41a680c0004119410141004100" + "10021a41e780c000412b41014100410010021a2000410036027002400240024002400240024002400240200041f000" + "6a220741041003220141004a0440419281c00041172000280270220141187420014180fe0371410874722001410876" + "4180fe037120014118767272ad10011a200041003602900120004190016a220341041004220141004c0d0141a981c0" + "004113200028029001220141187420014180fe03714108747220014108764180fe037120014118767272ad10011a20" + "0041c8016a22024200370300200041c0016a22054200370300200041b8016a22044200370300200042003703b00120" + "0041b0016a22064120100522014120470d0241bc81c000411320064120410110021a41cf81c0004120410141004100" + "10021a41dc82c000412e41014100410010021a200041a0016a410036020020004198016a4200370300200042003703" + "90014181802020034114100022014114470d03418a83c00041142003101f2000420037034841888018200041c8006a" + "22034108100022014108470d04419e83c0004117420810011a41b583c000412820034108410110021a200041003602" + "3041848008200041306a22034104100022014104470d0541dd83c000411520034104410110021a200041f4006a4100" + "36000020004100360071200041013a0070200242003703002005420037030020044200370300200042003703b00102" + "4020074108200641201006220141004e044041f283c00041142001ad10011a200041286a20062001101d418684c000" + "410d2000280228200028022c410110021a0c010b419384c00041292001ac10011a0b41bc84c00041154183803c1007" + "ac10011a41d184c00041134189803c1007ac10011a0240200041f0006a41081008220141004e044041e484c0004114" + "2001ad10011a0c010b41f884c000412d2001ac10011a0b41a585c000412341014100410010021a41de86c000413341" + "014100410010021a2000420037034841828018200041c8006a220141081009220341004c0d06200341084604404191" + "87c000412b420810011a41bc87c000412f20014108410110021a0c080b41eb87c000412f2003ad10011a200041206a" + "200041c8006a2003101c419a88c000411720002802202000280224410110021a0c070b41bf82c000411d2001ac1001" + "1a419b7f21020c070b419a82c00041252001ac10011a419a7f21020c060b41ef81c000412b2001ac10011a41997f21" + "020c050b41b486c000412a2001ac10011a41b77e21020c040b41f385c00041c1002001ac10011a41b67e21020c030b" + "41c885c000412b2001ac10011a41b57e21020c020b41b188c00041c5002003ac10011a0b200041a0016a4100360200" + "20004198016a4200370300200042003703900102404181802020004190016a220341141009220141004a044041f688" + "c000411e2003101f0c010b419489c00041332001ac10011a0b200041f4006a41003600002000410036007120004101" + "3a0070200041c8016a4200370300200041c0016a4200370300200041b8016a4200370300200042003703b001024020" + "0041f0006a4108200041b0016a22014120100a220341004e044041c789c000411c2003ad10011a200041186a200120" + "03101d41e389c00041152000280218200028021c410110021a0c010b41f889c00041392003ac10011a0b41b18ac000" + "41244183803c100bac10011a0240200041f0006a4108100c220141004e044041d58ac000411c2001ad10011a0c010b" + "41f18ac000413d2001ac10011a0b41ae8bc000412841014100410010021a41d68bc000412f41014100410010021a20" + "0041b0016a2203101a200041f0006a22012003101b200041a8016a4200370300200041a0016a420037030020004198" + "016a4200370300200042003703900102400240024002400240200120004190016a2203102022014120460440200341" + "204100100d220441004a044041858cc00041232004ad10011a200042003703302004200041306a2201410810212203" + "41004c0d022003410846044041a88cc000412a420810011a41d28cc000412e20014108410110021a0c060b41808dc0" + "00412e2003ad10011a200041106a200041306a2003101c41ae8dc000411620002802102000280214410110021a0c05" + "0b41e68fc000413c2004ac10011a200041c8016a4200370300200041c0016a4200370300200041b8016a4200370300" + "200042003703b0014101200041b0016a4120102122014100480d020c030b41ba92c000412e2001ac10011a41ef7c21" + "020c050b41c48dc000412b2003ac10011a0c020b41a290c00041c1002001ac10011a0b200041cc006a410036000020" + "004100360049200041013a00484101200041c8006a200041b0016a10222201410048044041e390c00041352001ac10" + "011a0b4101102322014100480440419891c00041322001ac10011a0b4101200041c8006a10242201410048044041ca" + "91c00041392001ac10011a0b418392c000413741014100410010021a0c010b200041cc006a41003600002000410036" + "0049200041013a0048200041c8016a4200370300200041c0016a4200370300200041b8016a42003703002000420037" + "03b00102402004200041c8006a200041b0016a22011022220341004e044041ef8dc000411b2003ad10011a20004108" + "6a20012003101d418a8ec00041142000280208200028020c410110021a0c010b419e8ec00041312003ac10011a0b41" + "cf8ec000412320041023ac10011a02402004200041c8006a1024220141004e044041f28ec000411b2001ad10011a0c" + "010b418d8fc00041352001ac10011a0b41c28fc000412441014100410010021a0b41e892c000412f41014100410010" + "021a200041b0016a2201101a200041306a22042001101b200041e0006a4200370300200041d8006a42003703002000" + "41d0006a420037030020004200370348024002400240024002402004200041c8006a22031020220141204604404197" + "93c000410f20034120410110021a20004188016a420037030020004180016a4200370300200041f8006a4200370300" + "200042003703700240200441142004411441a693c0004109200041f0006a22014120100e220341004a044020002001" + "2003101d41ae93c000411220002802002000280204410110021a0c010b41c093c000413c2003ac10011a0b200041a8" + "016a22064200370300200041a0016a2202420037030020004198016a22054200370300200042003703900120004180" + "808cc07e360268200041306a22034114200041e8006a410420004190016a22084120100f22014120470d0141fc93c0" + "00410e20084120410110021a200041c8016a4200370300200041c0016a4200370300200041b8016a42003703002000" + "42003703b001200041808080d00236026c20034114200041ec006a4104200041b0016a22044120101022014120470d" + "02418a94c000410e20044120410110021a419894c000412441014100410010021a419195c000412541014100410010" + "021a20004188016a420037030020004180016a4200370300200041f8006a42003703002000420037037041b695c000" + "4117200041f0006a22034120101122014120470d0341cd95c000410b41b695c0004117410110021a41d895c0004111" + "20034120410110021a2004101a200041c8006a22072004101b20064200370300200242003703002005420037030020" + "0042003703900102404100200422026b410371220320026a220520024d0d0020030440200321010340200241003a00" + "00200241016a2102200141016b22010d000b0b200341016b4107490d000340200241003a0000200241076a41003a00" + "00200241066a41003a0000200241056a41003a0000200241046a41003a0000200241036a41003a0000200241026a41" + "003a0000200241016a41003a0000200241086a22022005470d000b0b200541800220036b2201417c716a220220054b" + "0440034020054100360200200541046a22052002490d000b0b024020022001410371220120026a22034f0d00200122" + "0504400340200241003a0000200241016a2102200541016b22050d000b0b200141016b4107490d000340200241003a" + "0000200241076a41003a0000200241066a41003a0000200241056a41003a0000200241046a41003a0000200241036a" + "41003a0000200241026a41003a0000200241016a41003a0000200241086a22022003470d000b0b0240200741142008" + "412020044180021012220141004a044041e995c00041102001ad10011a20014181024f0d0641f995c0004109200420" + "01410110021a0c010b418296c000412e2001ac10011a0b41b096c000411241c296c00041074101100222014100480d" + "0541c996c000411d2001ad10011a41e696c0004111422a1001410048044041ad97c000411a42a47b10011a41a47b21" + "020c070b41f796c000411c420010011a41012102419397c000411a41014100410010021a41ff97c000412941014100" + "410010021a41a898c000412810132201412846044041d098c000412741a898c0004128410110021a41f798c000411e" + "41014100410010021a41bf80c000412841014100410010021a0c070b419599c000411a2001ac10011a41c37a21020c" + "060b41f494c000411d2001ac10011a418b7c21020c050b41d894c000411c2001ac10011a41897c21020c040b41bc94" + "c000411c2001ac10011a41887c21020c030b41dd97c00041222001ac10011a41a77b21020c020b000b41c797c00041" + "162001ac10011a41a57b21020b200041b0036a240020020b0d00200020012002411410191a0b0c0020004114200141" + "2010180b0e002000418280182001200210140b0e002000200141082002412010150b0a0020004183803c10160b0a00" + "20002001410810170b0bb9190100418080c0000baf196572726f725f636f64653d3d3d3d20484f53542046554e4354" + "494f4e532054455354203d3d3d54657374696e6720323620686f73742066756e6374696f6e73535543434553533a20" + "416c6c20686f73742066756e6374696f6e20746573747320706173736564212d2d2d2043617465676f727920313a20" + "4c6564676572204865616465722046756e6374696f6e73202d2d2d4c65646765722073657175656e6365206e756d62" + "65723a506172656e74206c65646765722074696d653a506172656e74206c656467657220686173683a535543434553" + "533a204c6564676572206865616465722066756e6374696f6e734552524f523a206765745f706172656e745f6c6564" + "6765725f686173682077726f6e67206c656e6774683a4552524f523a206765745f706172656e745f6c65646765725f" + "74696d65206661696c65643a4552524f523a206765745f6c65646765725f73716e206661696c65643a2d2d2d204361" + "7465676f727920323a205472616e73616374696f6e20446174612046756e6374696f6e73202d2d2d5472616e736163" + "74696f6e204163636f756e743a5472616e73616374696f6e20466565206c656e6774683a5472616e73616374696f6e" + "20466565202873657269616c697a65642058525020616d6f756e74293a5472616e73616374696f6e2053657175656e" + "63653a4e6573746564206669656c64206c656e6774683a4e6573746564206669656c643a494e464f3a206765745f74" + "785f6e65737465645f6669656c64206e6f74206170706c696361626c653a5369676e657273206172726179206c656e" + "6774683a4d656d6f73206172726179206c656e6774683a4e6573746564206172726179206c656e6774683a494e464f" + "3a206765745f74785f6e65737465645f61727261795f6c656e206e6f74206170706c696361626c653a535543434553" + "533a205472616e73616374696f6e20646174612066756e6374696f6e734552524f523a206765745f74785f6669656c" + "642853657175656e6365292077726f6e67206c656e6774683a4552524f523a206765745f74785f6669656c64284665" + "65292077726f6e67206c656e67746820286578706563746564203820627974657320666f7220585250293a4552524f" + "523a206765745f74785f6669656c64284163636f756e74292077726f6e67206c656e6774683a2d2d2d204361746567" + "6f727920333a2043757272656e74204c6564676572204f626a6563742046756e6374696f6e73202d2d2d4375727265" + "6e74206f626a6563742062616c616e6365206c656e677468202858525020616d6f756e74293a43757272656e74206f" + "626a6563742062616c616e6365202873657269616c697a65642058525020616d6f756e74293a43757272656e74206f" + "626a6563742062616c616e6365206c656e67746820286e6f6e2d58525020616d6f756e74293a43757272656e74206f" + "626a6563742062616c616e63653a494e464f3a206765745f63757272656e745f6c65646765725f6f626a5f6669656c" + "642842616c616e636529206661696c656420286d6179206265206578706563746564293a43757272656e74206c6564" + "676572206f626a656374206163636f756e743a494e464f3a206765745f63757272656e745f6c65646765725f6f626a" + "5f6669656c64284163636f756e7429206661696c65643a43757272656e74206e6573746564206669656c64206c656e" + "6774683a43757272656e74206e6573746564206669656c643a494e464f3a206765745f63757272656e745f6c656467" + "65725f6f626a5f6e65737465645f6669656c64206e6f74206170706c696361626c653a43757272656e74206f626a65" + "6374205369676e657273206172726179206c656e6774683a43757272656e74206e6573746564206172726179206c65" + "6e6774683a494e464f3a206765745f63757272656e745f6c65646765725f6f626a5f6e65737465645f61727261795f" + "6c656e206e6f74206170706c696361626c653a535543434553533a2043757272656e74206c6564676572206f626a65" + "63742066756e6374696f6e732d2d2d2043617465676f727920343a20416e79204c6564676572204f626a6563742046" + "756e6374696f6e73202d2d2d5375636365737366756c6c7920636163686564206f626a65637420696e20736c6f743a" + "436163686564206f626a6563742062616c616e6365206c656e677468202858525020616d6f756e74293a4361636865" + "64206f626a6563742062616c616e6365202873657269616c697a65642058525020616d6f756e74293a436163686564" + "206f626a6563742062616c616e6365206c656e67746820286e6f6e2d58525020616d6f756e74293a43616368656420" + "6f626a6563742062616c616e63653a494e464f3a206765745f6c65646765725f6f626a5f6669656c642842616c616e" + "636529206661696c65643a436163686564206e6573746564206669656c64206c656e6774683a436163686564206e65" + "73746564206669656c643a494e464f3a206765745f6c65646765725f6f626a5f6e65737465645f6669656c64206e6f" + "74206170706c696361626c653a436163686564206f626a656374205369676e657273206172726179206c656e677468" + "3a436163686564206e6573746564206172726179206c656e6774683a494e464f3a206765745f6c65646765725f6f62" + "6a5f6e65737465645f61727261795f6c656e206e6f74206170706c696361626c653a535543434553533a20416e7920" + "6c6564676572206f626a6563742066756e6374696f6e73494e464f3a2063616368655f6c65646765725f6f626a2066" + "61696c65642028657870656374656420776974682074657374206669787475726573293a494e464f3a206765745f6c" + "65646765725f6f626a5f6669656c64206661696c656420617320657870656374656420286e6f20636163686564206f" + "626a656374293a494e464f3a206765745f6c65646765725f6f626a5f6e65737465645f6669656c64206661696c6564" + "2061732065787065637465643a494e464f3a206765745f6c65646765725f6f626a5f61727261795f6c656e20666169" + "6c65642061732065787065637465643a494e464f3a206765745f6c65646765725f6f626a5f6e65737465645f617272" + "61795f6c656e206661696c65642061732065787065637465643a535543434553533a20416e79206c6564676572206f" + "626a6563742066756e6374696f6e732028696e7465726661636520746573746564294552524f523a206163636f756e" + "74726f6f745f6964206661696c656420666f722063616368696e6720746573743a2d2d2d2043617465676f72792035" + "3a204b65796c65742047656e65726174696f6e2046756e6374696f6e73202d2d2d4163636f756e74206b65796c6574" + "3a546573745479706543726564656e7469616c206b65796c65743a494e464f3a2063726564656e7469616c5f6b6579" + "6c6574206661696c656420286578706563746564202d20696e74657266616365206973737565293a457363726f7720" + "6b65796c65743a4f7261636c65206b65796c65743a535543434553533a204b65796c65742067656e65726174696f6e" + "2066756e6374696f6e734552524f523a206f7261636c655f6b65796c6574206661696c65643a4552524f523a206573" + "63726f775f6b65796c6574206661696c65643a4552524f523a206163636f756e74726f6f745f6964206661696c6564" + "3a2d2d2d2043617465676f727920363a205574696c6974792046756e6374696f6e73202d2d2d48656c6c6f2c205852" + "504c205741534d20776f726c6421496e70757420646174613a5348413531322068616c6620686173683a4e46542064" + "617461206c656e6774683a4e465420646174613a494e464f3a206765745f6e6674206661696c656420286578706563" + "746564202d206e6f2073756368204e4654293a54657374207472616365206d6573736167657061796c6f6164547261" + "63652066756e6374696f6e206279746573207772697474656e3a54657374206e756d62657220747261636554726163" + "655f6e756d2066756e6374696f6e20737563636565646564535543434553533a205574696c6974792066756e637469" + "6f6e734552524f523a2074726163655f6e756d2829206661696c65643a4552524f523a207472616365282920666169" + "6c65643a4552524f523a20636f6d707574655f7368613531325f68616c66206661696c65643a2d2d2d204361746567" + "6f727920373a2044617461205570646174652046756e6374696f6e73202d2d2d55706461746564206c656467657220" + "656e74727920646174612066726f6d205741534d20746573745375636365737366756c6c792075706461746564206c" + "656467657220656e74727920776974683a535543434553533a2044617461207570646174652066756e6374696f6e73" + "4552524f523a207570646174655f64617461206661696c65643a004d0970726f64756365727302086c616e67756167" + "65010452757374000c70726f6365737365642d6279010572757374631d312e38372e30202831373036376539616320" + "323032352d30352d303929002c0f7461726765745f6665617475726573022b0f6d757461626c652d676c6f62616c73" + "2b087369676e2d657874"; + +extern std::string const kAllKeyletsWasmHex = + "0061736d0100000001500a60067f7f7f7f7f7f017f60047f7f7f7f017f60087f7f7f7f7f7f7f7f017f60047f7f7f7f" + "0060037f7f7f017f60037f7f7e017f60057f7f7f7f7f017f6000017f60037f7f7f0060067f7f7f7f7f7e00029f0418" + "08686f73745f6c69620974726163655f6e756d000508686f73745f6c6962057472616365000608686f73745f6c6962" + "0863616368655f6c65000408686f73745f6c6962086c655f6669656c64000108686f73745f6c69620d686f6d655f6c" + "655f6669656c64000408686f73745f6c69620a74726163655f61636374000108686f73745f6c69620e6163636f756e" + "74726f6f745f6964000108686f73745f6c69620c74727573746c696e655f6964000208686f73745f6c696206616d6d" + "5f6964000008686f73745f6c696208636865636b5f6964000008686f73745f6c69620d63726564656e7469616c5f69" + "64000208686f73745f6c69620b64656c65676174655f6964000008686f73745f6c6962126465706f7369745f707265" + "617574685f6964000008686f73745f6c6962066469645f6964000108686f73745f6c696209657363726f775f696400" + "0008686f73745f6c69620f6d70745f69737375616e63655f6964000008686f73745f6c69620a6d70746f6b656e5f69" + "64000008686f73745f6c69620c6e66745f6f666665725f6964000008686f73745f6c6962086f666665725f69640000" + "08686f73745f6c69620a7061796368616e5f6964000208686f73745f6c6962167065726d697373696f6e65645f646f" + "6d61696e5f6964000008686f73745f6c69620a7369676e6572735f6964000108686f73745f6c6962097469636b6574" + "5f6964000008686f73745f6c6962087661756c745f6964000003070603030307080905030100110619037f01418080" + "c0000b7f0041c28ac0000b7f0041d08ac0000b073504066d656d6f727902000d657363726f775f66696e697368001b" + "0a5f5f646174615f656e6403010b5f5f686561705f6261736503020ae8370614002000200120022003418280204282" + "8020101d0b140020002001200220034181802042818020101d0bd10302017f017e230041a0016b2204240002402001" + "2d0000410146044041d780c000411620012802042201ac10001a200041013a0000200020013602040c010b20044118" + "6a200141196a290000370300200441106a200141116a290000370300200441086a200141096a290000370300200420" + "012900013703002002200320044120410110011a2004412041001002220141004c044041d080c00041072001ac1000" + "1a200041013a0000200020013602040c010b418b80c000410f4285801410001a20014185801420044180016a412010" + "032201412047044041af80c0004115417f20012001417f4e1b2201ac10001a200041013a0000200020013602040c01" + "0b200441c2006a20044182016a2d00003a0000200441f0006a20044197016a2900002205370300200441286a220120" + "04418f016a290000370300200441306a22022005370300200441386a22032004419f016a2d00003a0000200420042f" + "0080013b014020042004290087013703202004200428008301360043200441df006a20032d00003a0000200441d700" + "6a2002290300370000200441cf006a20012903003700002004200429032037004741c480c000410c200441406b4120" + "410110011a20004180023b01000b200441a0016a24000bd32c02097f027e23004180076b2200240041ed80c0004123" + "41014100410010011a02402000027f02404181802020004190016a220741141004220641144604402000410e6a2000" + "4192016a22032d00003a000020002000290097013703e80120002000419c016a22012900003700ed01200020002f00" + "90013b010c200020002903e8013703d806200020002900ed013700dd06200020002800930136000f200041186a2000" + "2900dd06370000200020002903d806370013419081c00041082000410c6a2204411410051a41838020200741141004" + "22064114470d03200041226a20032d00003a000020002000290097013703e801200020012900003700ed0120002000" + "2f0090013b0120200020002903e8013703d806200020002900ed013700dd0620002000280093013600232000412c6a" + "20002900dd06370000200020002903d806370027419881c000410c200041206a411410051a200041a8016a22034200" + "370300200041a0016a2201420037030020004198016a42003703002000420037039001200441142007412010062204" + "4120460d01024020044100480440200020043602380c010b2000417f3602380b41010c020b0c020b200041cd006a20" + "03290300370000200041c5006a20012903003700002000413d6a20004198016a290300370000200020002903900137" + "003541000b3a003420004190016a200041346a41a481c00041071019024020002d0090014101460440200028029401" + "2106419c8ac0004112420510001a0c010b4100210641ab81c000413541014100410010011a200041e6006a41c4003a" + "0000200041e0006a4100360200200041eb006a41003a0000200041d5a6013b01642000420037035820004100360067" + "200041a8016a22044200370300200041a0016a2203420037030020004198016a220142003703002000420037039001" + "02402000410c6a4114200041206a4114200041d8006a411420004190016a4120100722074120470440024020074100" + "480440200020073602700c010b2000417f3602700b410121060c010b20004185016a2004290300370000200041fd00" + "6a2003290300370000200041f5006a2001290300370000200020002903900137006d0b200020063a006c2000419001" + "6a200041ec006a41e081c0004109101a20002d00900141014604402000280294012106419c8ac0004112420510001a" + "0c010b4100210641e981c000413741014100410010011a200041f8016a200041306a2204280100360200200041f001" + "6a200041286a220329010037030020004184026a200041e0006a290300220a3702002000418c026a200041e8006a28" + "02002201360200200020002901203703e8012000200029035822093702fc01200041e8066a22052001360200200041" + "e0066a2207200a370300200020093703d806200041f4066a2003290100370200200041fc066a200428010036020020" + "0020002901203702ec0620004190026a200041d8066a22034128101c20004194016a200041e8016a41d000101c2000" + "410136029001200041f0066a220142003703002005420037030020074200370300200042003703d806024041ae8ac0" + "004114200041bc016a412820034120100822034120470440024020034100480440200020033602ec010c010b200041" + "7f3602ec010b410121060c010b20004181026a2001290300370000200041f9016a2005290300370000200041f1016a" + "2007290300370000200020002903d8063700e9010b200020063a00e801200041bc026a200041e8016a41a082c00041" + "03101920002d00bc02410146044020002802c0022106419c8ac0004112420610001a0c010b4100210641a382c00041" + "3141014100410010011a200041063602d80620004180026a22044200370300200041f8016a22034200370300200041" + "f0016a22014200370300200042003703e80102402000410c6a4114200041d8066a4104200041e8016a412010092207" + "4120470440024020074100480440200020073602c8020c010b2000417f3602c8020b410121060c010b200041dd026a" + "2004290300370000200041d5026a2003290300370000200041cd026a2001290300370000200020002903e8013700c5" + "020b200020063a00c402200041e8016a200041c4026a41d482c0004105101920002d00e801410146044020002802ec" + "012106419c8ac0004112420610001a0c010b41d982c000413341014100410010011a20004180026a42003703002000" + "41f8016a4200370300200041f0016a4200370300200042003703e801024002402000410c6a2201411420014114418c" + "83c0004112200041e8016a4120100a2201412047044041d780c0004116417f20012001417f4e1b2206ac10001a0c01" + "0b200041da066a20002d00ea013a0000200041f0026a200041f7016a290000220a370300200041f8026a200041ff01" + "6a290000220937030020004180036a20004187026a2d000022013a0000200041e7066a200a370000200041ef066a20" + "09370000200041f7066a20013a0000200020002f01e8013b01d806200020002900ef0122093703e802200020002800" + "eb013600db06200020093700df06419e83c000410a200041d8066a22014120410110011a2001412041001002220641" + "004c044041d080c00041072006ac10001a0c010b418b80c000410f4298802010001a200641988020200041e8016a41" + "14100322014114460d0141af80c0004115417f20012001417f4e1b2206ac10001a0b419c8ac0004112420710001a0c" + "010b419a80c000411541014100410010011a41a883c000413841014100410010011a230041206b2208240020084118" + "6a22074200370300200841106a22044200370300200841086a220342003703002008420037030020004184036a2201" + "027f2000410c6a22064114200041206a2202411420084120100b220541204704400240200541004804402001200536" + "02040c010b2001417f3602040b41010c010b20012008290300370001200141196a2007290300370000200141116a20" + "04290300370000200141096a200329030037000041000b3a0000200841206a2400200041e8016a2205200141e083c0" + "004108101920002d00e80145044041e883c000413641014100410010011a230041206b22082400200841186a220742" + "00370300200841106a22044200370300200841086a2203420037030020084200370300200041a8036a2201027f2006" + "41142002411420084120100c22024120470440024020024100480440200120023602040c010b2001417f3602040b41" + "010c010b20012008290300370001200141196a2007290300370000200141116a2004290300370000200141096a2003" + "29030037000041000b3a0000200841206a240020052001419e84c000410e101920002d00e801410146044020002802" + "ec012106419c8ac0004112420910001a0c020b41ac84c000413c41014100410010011a230041206b22022400200241" + "186a22074200370300200241106a22044200370300200241086a2203420037030020024200370300200041cc036a22" + "01027f2000410c6a411420024120100d22054120470440024020054100480440200120053602040c010b2001417f36" + "02040b41010c010b20012002290300370001200141196a2007290300370000200141116a2004290300370000200141" + "096a200329030037000041000b3a0000200241206a2400200041e8016a200141e884c0004103101920002d00e80141" + "0146044020002802ec012106419c8ac0004112420a10001a0c020b41eb84c000413141014100410010011a23004130" + "6b220224002002410b36020c200241286a22074200370300200241206a22044200370300200241186a220342003703" + "0020024200370310200041f0036a2201027f2000410c6a41142002410c6a4104200241106a4120100e220541204704" + "40024020054100480440200120053602040c010b2001417f3602040b41010c010b2001200229031037000120014119" + "6a2007290300370000200141116a2004290300370000200141096a200329030037000041000b3a0000200241306a24" + "00200041e8016a2001419c85c0004106101920002d00e801410146044020002802ec012106419c8ac0004112420b10" + "001a0c020b41a285c000413441014100410010011a230041306b220224002002410c36020c200241286a2207420037" + "0300200241206a22044200370300200241186a220342003703002002420037031020004194046a2201027f2000410c" + "6a41142002410c6a4104200241106a4120100f22054120470440024020054100480440200120053602040c010b2001" + "417f3602040b41010c010b20012002290310370001200141196a2007290300370000200141116a2004290300370000" + "200141096a200329030037000041000b3a0000200241306a2400200041fc016a2000411c6a280100360200200041f4" + "016a200041146a2901003702002000200029010c3702ec01200041808080e0003602e801200041d8066a2103230041" + "406a22042400024020012d0000410146044041d780c000411620012802042201ac10001a200341013a000020032001" + "3602040c010b200441206a200141196a290000370300200441186a200141116a290000370300200441106a20014109" + "6a2900003703002004200129000137030841d685c000410b200441086a22014120410110011a024002402001412041" + "001002220141004c044041d080c00041072001ac10001a0c010b418b80c000410f4284802010001a20014184802020" + "04412c6a4114100322014114460d0141af80c0004115417f20012001417f4e1b2201ac10001a0b200341013a000020" + "0320013602040c010b419a80c000411541014100410010011a20034180023b01000b200441406b240020002d00d806" + "410146044020002802dc062106419c8ac0004112420c10001a0c020b41e185c000413941014100410010011a230041" + "206b22022400200241186a22074200370300200241106a22044200370300200241086a220342003703002002420037" + "0300200041b8046a2201027f200041e8016a4118200041206a41142002412010102205412047044002402005410048" + "0440200120053602040c010b2001417f3602040b41010c010b20012002290300370001200141196a20072903003700" + "00200141116a2004290300370000200141096a200329030037000041000b3a0000200241206a2400200041d8066a20" + "01419a86c0004107101920002d00d806410146044020002802dc062106419c8ac0004112420d10001a0c020b41a186" + "c000413541014100410010011a230041306b220224002002410636020c200241286a22074200370300200241206a22" + "044200370300200241186a2203420037030020024200370310200041dc046a2201027f200041206a41142002410c6a" + "4104200241106a4120101122054120470440024020054100480440200120053602040c010b2001417f3602040b4101" + "0c010b20012002290310370001200141196a2007290300370000200141116a2004290300370000200141096a200329" + "030037000041000b3a0000200241306a2400200041d8066a200141d686c000410c101820002d00d806410146044020" + "002802dc062106419c8ac0004112420d10001a0c020b41e286c000413a41014100410010011a230041306b22022400" + "2002410d36020c200241286a22074200370300200241206a22044200370300200241186a2203420037030020024200" + "37031020004180056a2201027f2000410c6a41142002410c6a4104200241106a412010122205412047044002402005" + "4100480440200120053602040c010b2001417f3602040b41010c010b20012002290310370001200141196a20072903" + "00370000200141116a2004290300370000200141096a200329030037000041000b3a0000200241306a2400200041d8" + "066a2001419c87c0004105101920002d00d806410146044020002802dc062106419c8ac0004112420d10001a0c020b" + "41a187c000413341014100410010011a230041306b220224002002410e36020c200241286a22074200370300200241" + "206a22044200370300200241186a2203420037030020024200370310200041a4056a2201027f2000410c6a41142000" + "41206a41142002410c6a4104200241106a4120101322054120470440024020054100480440200120053602040c010b" + "2001417f3602040b41010c010b20012002290310370001200141196a2007290300370000200141116a200429030037" + "0000200141096a200329030037000041000b3a0000200241306a2400200041d8066a200141d487c000410a10192000" + "2d00d806410146044020002802dc062106419c8ac0004112420e10001a0c020b41de87c00041384101410041001001" + "1a230041306b220224002002410f36020c200241286a22074200370300200241206a22044200370300200241186a22" + "03420037030020024200370310200041c8056a2201027f2000410c6a41142002410c6a4104200241106a4120101422" + "054120470440024020054100480440200120053602040c010b2001417f3602040b41010c010b200120022903103700" + "01200141196a2007290300370000200141116a2004290300370000200141096a200329030037000041000b3a000020" + "0241306a2400200041d8066a2001419688c0004112101820002d00d806410146044020002802dc062106419c8ac000" + "4112420f10001a0c020b41a888c00041c00041014100410010011a230041206b22022400200241186a220742003703" + "00200241106a22044200370300200241086a2203420037030020024200370300200041ec056a2201027f2000410c6a" + "411420024120101522054120470440024020054100480440200120053602040c010b2001417f3602040b41010c010b" + "20012002290300370001200141196a2007290300370000200141116a2004290300370000200141096a200329030037" + "000041000b3a0000200241206a2400200041d8066a200141e888c000410a101a20002d00d806410146044020002802" + "dc062106419c8ac0004112421010001a0c020b41f288c000413841014100410010011a230041306b22022400200241" + "1236020c200241286a22074200370300200241206a22044200370300200241186a2203420037030020024200370310" + "20004190066a2201027f2000410c6a41142002410c6a4104200241106a412010162205412047044002402005410048" + "0440200120053602040c010b2001417f3602040b41010c010b20012002290310370001200141196a20072903003700" + "00200141116a2004290300370000200141096a200329030037000041000b3a0000200241306a2400200041d8066a20" + "0141aa89c0004106101920002d00d806410146044020002802dc062106419c8ac0004112421210001a0c020b410121" + "0641b089c000413441014100410010011a230041306b220224002002411336020c200241286a220742003703002002" + "41206a22044200370300200241186a2203420037030020024200370310200041b4066a2201027f2000410c6a411420" + "02410c6a4104200241106a4120101722054120470440024020054100480440200120053602040c010b2001417f3602" + "040b41010c010b20012002290310370001200141196a2007290300370000200141116a200429030037000020014109" + "6a200329030037000041000b3a0000200241306a2400200041d8066a200141e489c0004105101920002d00d8064101" + "46044020002802dc062106419c8ac0004112421310001a0c020b41e989c000413341014100410010011a0c010b2000" + "2802ec012106419c8ac0004112420810001a0b20004180076a240020060f0b418080c000410b417f20062006417f4e" + "1bac1000000bfd0401067f200241104f0440024020002000410020006b41037122056a22044f0d0020012103200504" + "40200521060340200020032d00003a0000200341016a2103200041016a2100200641016b22060d000b0b200541016b" + "4107490d000340200020032d00003a0000200041016a200341016a2d00003a0000200041026a200341026a2d00003a" + "0000200041036a200341036a2d00003a0000200041046a200341046a2d00003a0000200041056a200341056a2d0000" + "3a0000200041066a200341066a2d00003a0000200041076a200341076a2d00003a0000200341086a2103200041086a" + "22002004470d000b0b2004200220056b2207417c7122086a21000240200120056a2206410371450440200020044d0d" + "0120062101034020042001280200360200200141046a2101200441046a22042000490d000b0c010b200020044d0d00" + "2006410374220541187121032006417c71220241046a2101410020056b411871210520022802002102034020042002" + "2003762001280200220220057472360200200141046a2101200441046a22042000490d000b0b200741037121022006" + "20086a21010b02402000200020026a22064f0d002002410771220304400340200020012d00003a0000200141016a21" + "01200041016a2100200341016b22030d000b0b200241016b4107490d000340200020012d00003a0000200041016a20" + "0141016a2d00003a0000200041026a200141026a2d00003a0000200041036a200141036a2d00003a0000200041046a" + "200141046a2d00003a0000200041056a200141056a2d00003a0000200041066a200141066a2d00003a000020004107" + "6a200141076a2d00003a0000200141086a2101200041086a22002006470d000b0b0b940201017f230041406a220624" + "00024020012d0000410146044041d780c000411620012802042201ac10001a200041013a0000200020013602040c01" + "0b200641206a200141196a290000370300200641186a200141116a290000370300200641106a200141096a29000037" + "03002006200129000137030820022003200641086a22014120410110011a024002402001412041001002220141004c" + "044041d080c00041072001ac10001a0c010b418b80c000410f200510001a200120042006412c6a4114100322014114" + "460d0141af80c0004115417f20012001417f4e1b2201ac10001a0b200041013a0000200020013602040c010b419a80" + "c000411541014100410010011a20004180023b01000b200641406b24000b0bb80a0100418080c0000bae0a6572726f" + "725f636f64653d47657474696e67206669656c643a204669656c6420646174613a207265747269657665644572726f" + "722067657474696e67206669656c643a204669656c6420646174613a204572726f723a204572726f72206765747469" + "6e67206b65796c65743a202424242424205354415254494e47205741534d20455845435554494f4e20242424242441" + "63636f756e743a44657374696e6174696f6e3a4163636f756e744163636f756e74206f626a65637420657869737473" + "2c2070726f63656564696e67207769746820657363726f772066696e6973682e54727573746c696e6554727573746c" + "696e65206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f772066696e6973" + "682e414d4d414d4d206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f7720" + "66696e6973682e436865636b436865636b206f626a656374206578697374732c2070726f63656564696e6720776974" + "6820657363726f772066696e6973682e7465726d73616e64636f6e646974696f6e7343726564656e7469616c437265" + "64656e7469616c206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f772066" + "696e6973682e44656c656761746544656c6567617465206f626a656374206578697374732c2070726f63656564696e" + "67207769746820657363726f772066696e6973682e4465706f736974507265617574684465706f7369745072656175" + "7468206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f772066696e697368" + "2e444944444944206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f772066" + "696e6973682e457363726f77457363726f77206f626a656374206578697374732c2070726f63656564696e67207769" + "746820657363726f772066696e6973682e4d505449737375616e63654d505449737375616e6365206f626a65637420" + "6578697374732c2070726f63656564696e67207769746820657363726f772066696e6973682e4d50546f6b656e4d50" + "546f6b656e206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f772066696e" + "6973682e4e46546f6b656e4f666665724e46546f6b656e4f66666572206f626a656374206578697374732c2070726f" + "63656564696e67207769746820657363726f772066696e6973682e4f666665724f66666572206f626a656374206578" + "697374732c2070726f63656564696e67207769746820657363726f772066696e6973682e5061794368616e6e656c50" + "61794368616e6e656c206f626a656374206578697374732c2070726f63656564696e67207769746820657363726f77" + "2066696e6973682e5065726d697373696f6e6564446f6d61696e5065726d697373696f6e6564446f6d61696e206f62" + "6a656374206578697374732c2070726f63656564696e67207769746820657363726f772066696e6973682e5369676e" + "65724c6973745369676e65724c697374206f626a656374206578697374732c2070726f63656564696e672077697468" + "20657363726f772066696e6973682e5469636b65745469636b6574206f626a656374206578697374732c2070726f63" + "656564696e67207769746820657363726f772066696e6973682e5661756c745661756c74206f626a65637420657869" + "7374732c2070726f63656564696e67207769746820657363726f772066696e6973682e43757272656e742073657120" + "76616c75653a004d0970726f64756365727302086c616e6775616765010452757374000c70726f6365737365642d62" + "79010572757374631d312e38372e30202831373036376539616320323032352d30352d303929002c0f746172676574" + "5f6665617475726573022b0f6d757461626c652d676c6f62616c732b087369676e2d657874"; + +extern std::string const kCodecovTestsWasmHex = + "0061736d0100000001570b60067f7f7f7f7f7f017f60047f7f7f7f017f60027f7f017f60037f7f7f017f60077f7f7f" + "7f7f7f7f017f60057f7f7f7f7f017f60087f7f7f7f7f7f7f7f017f60017f017f60037f7f7e017f60047f7f7f7f0060" + "00017f02c60a3b08686f73745f6c6962057472616365000508686f73745f6c69620974726163655f6e756d00080868" + "6f73745f6c69620a6c6467725f696e646578000208686f73745f6c696210706172656e745f6c6467725f74696d6500" + "0208686f73745f6c696210706172656e745f6c6467725f68617368000208686f73745f6c696208626173655f666565" + "000208686f73745f6c696211616d656e646d656e745f656e61626c6564000208686f73745f6c69620874785f666965" + "6c64000308686f73745f6c69620e6163636f756e74726f6f745f6964000108686f73745f6c69620863616368655f6c" + "65000308686f73745f6c69620d686f6d655f6c655f6669656c64000308686f73745f6c6962086c655f6669656c6400" + "0108686f73745f6c69620874785f696e6e6572000108686f73745f6c69620d686f6d655f6c655f696e6e6572000108" + "686f73745f6c6962086c655f696e6e6572000508686f73745f6c69620a74785f6172725f6c656e000708686f73745f" + "6c69620f686f6d655f6c655f6172725f6c656e000708686f73745f6c69620a6c655f6172725f6c656e000208686f73" + "745f6c69621074785f696e6e65725f6172725f6c656e000208686f73745f6c696215686f6d655f6c655f696e6e6572" + "5f6172725f6c656e000208686f73745f6c6962106c655f696e6e65725f6172725f6c656e000308686f73745f6c6962" + "087365745f64617461000208686f73745f6c69620b7368613531325f68616c66000108686f73745f6c696209636865" + "636b5f736967000008686f73745f6c6962076e66745f757269000008686f73745f6c69620a6e66745f697373756572" + "000108686f73745f6c6962096e66745f7461786f6e000108686f73745f6c6962096e66745f666c616773000208686f" + "73745f6c69620c6e66745f786665725f666565000208686f73745f6c69620a6e66745f73657269616c000108686f73" + "745f6c69620a74726163655f61636374000108686f73745f6c69620974726163655f616d74000108686f73745f6c69" + "6208636865636b5f6964000008686f73745f6c69620f666c6f61745f66726f6d5f75696e74000508686f73745f6c69" + "620c74727573746c696e655f6964000608686f73745f6c696206616d6d5f6964000008686f73745f6c69620d637265" + "64656e7469616c5f6964000608686f73745f6c69620a6d70746f6b656e5f6964000008686f73745f6c69620c747261" + "63655f78666c6f6174000108686f73745f6c696209666c6f61745f636d70000108686f73745f6c696209666c6f6174" + "5f616464000408686f73745f6c696209666c6f61745f737562000408686f73745f6c69620a666c6f61745f6d756c74" + "000408686f73745f6c696209666c6f61745f646976000408686f73745f6c69620a666c6f61745f726f6f7400000868" + "6f73745f6c696209666c6f61745f706f77000008686f73745f6c696209657363726f775f6964000008686f73745f6c" + "69620f6d70745f69737375616e63655f6964000008686f73745f6c69620c6e66745f6f666665725f6964000008686f" + "73745f6c6962086f666665725f6964000008686f73745f6c6962096f7261636c655f6964000008686f73745f6c6962" + "0a7061796368616e5f6964000608686f73745f6c6962167065726d697373696f6e65645f646f6d61696e5f69640000" + "08686f73745f6c6962097469636b65745f6964000008686f73745f6c6962087661756c745f6964000008686f73745f" + "6c69620b64656c65676174655f6964000008686f73745f6c6962126465706f7369745f707265617574685f69640000" + "08686f73745f6c6962066469645f6964000108686f73745f6c69620a7369676e6572735f69640001030302090a0503" + "0100110619037f01418080c0000b7f0041cf9bc0000b7f0041d09bc0000b073504066d656d6f727902000d65736372" + "6f775f66696e697368003c0a5f5f646174615f656e6403010b5f5f686561705f6261736503020a8c2f024600024020" + "0020014704402002200341014100410010001a20004100480d01418b80c000410b2000ad1001000b200220032000ac" + "10011a0f0b418b80c000410b2000ac1001000bc22e020b7f017e23004190026b22002400419680c000412341014100" + "410010001a20004100360260200041e0006a220241041002410441888ac000410a103b200041003602602002410410" + "03410441928ac0004110103b200041f8006a22054200370300200041f0006a22014200370300200041e8006a220642" + "0037030020004200370360200241201004412041a28ac0004110103b20004100360260200241041005410441b28ac0" + "004108103b200041106a2208428182848890a0c08001370300200041186a2209428182848890a0c080013703002000" + "41206a220a428182848890a0c080013703002000428182848890a0c0800137030841b980c000410e1006410141c780" + "c0004111103b200041086a41201006410141c780c0004111103b418180202002411410072203411446044002402000" + "412e6a200041e2006a2d00003a0000200020002900673703e8012000200041ec006a2900003700ed01200020002f00" + "603b012c200020002903e8013703a801200020002900ed013700ad012000200028006336002f200041386a20002900" + "ad01370000200020002903a80137003320054200370300200142003703002006420037030020004200370360200041" + "2c6a2205411420024120100822034120470d00200041c2006a20002d00623a0000200041f0016a2207200041ef006a" + "290000220b370300200041cf006a200b370000200041d7006a200041f7006a290000370000200041df006a200041ff" + "006a2d00003a0000200020002f01603b01402000200028006336004320002000290067370047200041406b41204100" + "1009410141d880c0004108103b2001410036020020064200370300200042003703604181802020024114100a411441" + "ba8ac000410d103b20014100360200200642003703002000420037036041014181802020024114100b411441c78ac0" + "004108103b02404100200041e4006a22046b410371220320046a220120044d0d002003044020032106034020044100" + "3a0000200441016a2104200641016b22060d000b0b200341016b4107490d000340200441003a0000200441076a4100" + "3a0000200441066a41003a0000200441056a41003a0000200441046a41003a0000200441036a41003a000020044102" + "6a41003a0000200441016a41003a0000200441086a22042001470d000b0b2001413c20036b2203417c716a22042001" + "4b0440034020014100360200200141046a22012004490d000b0b024020042003410371220320046a22064f0d002003" + "220104400340200441003a0000200441016a2104200141016b22010d000b0b200341016b4107490d00034020044100" + "3a0000200441076a41003a0000200441066a41003a0000200441056a41003a0000200441046a41003a000020044103" + "6a41003a0000200441026a41003a0000200441016a41003a0000200441086a22042006470d000b0b200041043602a0" + "01200041818020360260200041f8016a2203410036020020074200370300200042003703e80120024104200041e801" + "6a22014114100c411441cf8ac0004108103b2003410036020020074200370300200042003703e801200220002802a0" + "0120014114100d411441d78ac000410d103b2003410036020020074200370300200042003703e80141012002200028" + "02a00120014114100e411441e48ac0004108103b4189803c100f412041e080c000410a103b4189803c1010412041ea" + "80c000410f103b41014189803c1011412041f980c000410a103b200220002802a00110124120418381c0004110103b" + "200220002802a00110134120419381c0004115103b4101200220002802a0011014412041a881c0004110103b200541" + "141015411441b881c0004108103b20004180026a220642003703002003420037030020074200370300200042003703" + "e801200220002802a001200141201016412041ec8ac000410b103b41c081c000410c41cc81c000410b41d781c00041" + "0e1017410141e581c0004109103b200041c0016a200a290300370300200041b8016a2009290300370300200041b001" + "6a2008290300370300200020002903083703a801200341003b010020074200370300200042003703e8012005411420" + "0041a8016a22044120200141121018411241f78ac0004107103b2003410036020020074200370300200042003703e8" + "0120044120200141141019411441fe8ac000410a103b200041003602e8012004412020014104101a410441888bc000" + "4109103b20044120101b410841ee81c0004109103b20044120101c410a41f781c000410c103b200041003602e80120" + "04412020014104101d410441918bc000410a103b418382c000410d20054114101e4100419082c000410a103b418382" + "c000410d419a82c0004108101f410041a282c0004109103b418382c000410d41ab82c0004108101f410041b382c000" + "410e103b417f41041004417141c182c0004118103b200041003602e8012001417f10044171419b8bc0004118103b20" + "0041ea016a41003a0000200041003b01e801200141031004417d41b38bc000411e103b200041003602e80120014180" + "94ebdc031004417341d18bc000411d103b4102100f416f41d982c0004119103b417f20002802a0011012417141f282" + "c0004118103b2002417f10124171418a83c0004118103b20024181081012417441a283c0004119103b200041e094eb" + "dc036a220820002802a0011012417341bb83c0004118103b2006420037030020034200370300200742003703002000" + "42003703e8012005411420084108200141201020417341ee8bc0004114103b20064200370300200342003703002007" + "4200370300200042003703e8012005411420054114200141201020417141828cc0004116103b200642003703002003" + "420037030020074200370300200042003703e801200841082001412041001021417341988cc0004117103b20064200" + "3703002003420037030020074200370300200042003703e801200220002802a0012001412041001021417141af8cc0" + "004120103b200820002802a00141011009417341d383c0004110103b200220002802a00141011009417141e383c000" + "4112103b200642003703002003420037030020074200370300200042003703e801200820002802a001200141201008" + "417341cf8cc0004116103b200642003703002003420037030020074200370300200042003703e801200220002802a0" + "01200141201008417141e58cc0004118103b200642003703002003420037030020074200370300200042003703e801" + "2005411420054114200820002802a001200141201022417341fd8cc000411d103b2006420037030020034200370300" + "20074200370300200042003703e8012005411420054114200220002802a0012001412010224171419a8dc000411f10" + "3b200642003703002003420037030020074200370300200042003703e80141bb9bc0004114200820002802a0012001" + "41201023417341b98dc0004115103b200642003703002003420037030020074200370300200042003703e80141bb9b" + "c0004114200220002802a001200141201023417141ce8dc000411b103b200642003703002003420037030020074200" + "370300200042003703e80141bb9bc000411441f583c0004114200141201023417141e98dc0004125103b2006420037" + "03002003420037030020074200370300200042003703e801418984c000412841bb9bc0004114200141201023417141" + "8e8ec0004121103b200041dc016a2000413c6a280100360200200041d4016a200041346a2901003702002000200029" + "012c3702cc01200041808080083602c801200041003b01e801200041c8016a2209411841bb9bc00041142001410210" + "23417141af8ec000410a103b200820002802a001422a1001417341b184c0004111103b200041003b01e80141022001" + "41021007416f41b98ec0004117103b200041003b01e801410220014102100a416f41d08ec000411c103b200041003b" + "01e8014101410220014102100b416f41ec8ec0004117103b4102100f416f41d982c0004119103b41021010416f41c2" + "84c000411e103b410141021011416f41e084c0004119103b41b980c0004181081006417441f984c000411f103b41b9" + "80c00041c10010064174419885c000411a103b200041003b01e801200241810820014102100c417441838fc0004116" + "103b200041003b01e801200241810820014102100d417441998fc000411b103b200041003b01e80141012002418108" + "20014102100e417441b48fc0004116103b20024181081012417441b285c000411e103b20024181081013417441d085" + "c0004123103b410120024181081014417441f385c000411e103b200241812010154174419186c0004116103b418382" + "c00041810841cc81c000410b41d781c000410e1017417441e581c0004109103b418382c000410d41cc81c000418108" + "41d781c000410e1017417441e581c0004109103b418382c000410d41cc81c000410b41d781c0004181081017417441" + "e581c0004109103b200041003b01e8012002418108200141021016417441ca8fc0004119103b200041003b01e80141" + "bb9bc00041810841bb9bc0004114200141021023417441e38fc0004114103b200041003b01e8012005411420054114" + "2002418108200141021024417441f78fc000411b103b200041003b01e8012009418108200541142001410210254174" + "419290c000411e103b418382c000410d200820002802a00141001000417341a786c000410f103b200042d487b6f4c7" + "d4b1c0003700e001418382c000410d200041e095ebdc036a220441081026417341b686c0004116103b418382c00041" + "0d200820002802a001101f417341cc86c0004113103b20044108200041e0016a220841081027417341df86c0004114" + "103b20084108200441081027417341f386c0004114103b200041003b01e80120044108200841082001410241001028" + "417341b090c0004114103b200041003b01e80120084108200441082001410241001028417341c490c0004114103b20" + "0041003b01e80120044108200841082001410241001029417341d890c0004114103b200041003b01e8012008410820" + "0441082001410241001029417341ec90c0004114103b200041003b01e8012004410820084108200141024100102a41" + "73418091c0004115103b200041003b01e8012008410820044108200141024100102a4173419591c0004115103b2000" + "41003b01e8012004410820084108200141024100102b417341aa91c0004114103b200041003b01e801200841082004" + "4108200141024100102b417341be91c0004114103b200041003b01e801200441084103200141024100102c417341d2" + "91c0004114103b200041003b01e801200441084103200141024100102d417341e691c0004113103b20064200370300" + "2003420037030020074200370300200042003703e801200541142005411420014120102e417141f991c000411b103b" + "200642003703002003420037030020074200370300200042003703e801200541142005411420014120102f41714194" + "92c0004121103b200642003703002003420037030020074200370300200042003703e8012005411420054114200141" + "201030417141b592c000411e103b200642003703002003420037030020074200370300200042003703e80120054114" + "20054114200141201031417141d392c000411a103b2006420037030020034200370300200742003703002000420037" + "03e8012005411420054114200141201032417141ed92c000411b103b20064200370300200342003703002007420037" + "0300200042003703e8012005411420054114200541142001412010334171418893c000411c103b2006420037030020" + "03420037030020074200370300200042003703e8012005411420054114200141201034417141a493c0004128103b20" + "0642003703002003420037030020074200370300200042003703e8012005411420054114200141201035417141cc93" + "c000411b103b200642003703002003420037030020074200370300200042003703e801200541142005411420014120" + "1036417141e793c000411a103b200220002802a001410010094171418787c000411b103b200041003b01e801200541" + "14200220002802a0012001410210184171418194c000411a103b200041003b01e801200220002802a0012001410210" + "194171419b94c000411d103b200041003b01e801200220002802a00120014102101a417141b894c000411c103b2002" + "20002802a001101b417141a287c000411c103b200220002802a001101c417141be87c000411f103b200041003602e8" + "01200220002802a00120014104101d417141d494c000411d103b200041003b01e801200220002802a0012001410210" + "08417141f194c0004124103b200041808080083602e801200041003b018e02200220002802a001200141042000418e" + "026a2203410210204171419595c000411e103b200041003b018e02200220002802a001220620054114200220062003" + "41021024417141b395c0004124103b200041003b018e0220054114200220002802a001220620022006200341021024" + "417141d795c0004124103b200041003b018e02200220002802a00120054114200341021037417141fb95c000412210" + "3b200041003b018e0220054114200220002802a0012003410210374171419d96c0004122103b200041003b018e0220" + "0220002802a00120054114200341021038417141bf96c0004129103b200041003b018e0220054114200220002802a0" + "01200341021038417141e896c0004129103b200041003b018e02200220002802a0012003410210394171419197c000" + "411c103b200041003b018e02200220002802a0012001410420034102102e417141ad97c000411f103b200041003b01" + "8e02200220002802a0012005411441f583c0004114200341021022417141cc97c0004123103b200041003b018e0220" + "054114200220002802a00141f583c0004114200341021022417141ef97c0004123103b200041003b018e0220022000" + "2802a0012001410420034102102f4171419298c0004125103b200041003b018e0220094118200220002802a0012003" + "41021025417141b798c0004120103b200041003b018e02200220002802a00120014104200341021030417141d798c0" + "004122103b200041003b018e02200220002802a00120014104200341021031417141f998c000411e103b200041003b" + "018e02200220002802a001200141042003410210324171419799c000411f103b200041003b018e02200220002802a0" + "012005411420014104200341021033417141b699c0004121103b200041003b018e0220054114200220002802a00120" + "014104200341021033417141d799c0004121103b200041003b018e02200220002802a0012001410420034102103441" + "7141f899c000412c103b200041003b018e02200220002802a00120034102103a417141a49ac0004120103b20004100" + "3b018e02200220002802a00120014104200341021035417141c49ac000411f103b200041003b018e02200220002802" + "a00120014104200341021036417141e39ac000411e103b200041003b018e02200220002802a00141dd87c000412020" + "0341021018417141819bc000411d103b418382c000410d200220002802a001101e417141fd87c0004120103b418396" + "abdd03410d41dd87c0004120410010004173419d88c0004110103b418396abdd03410d200841081026417341ad88c0" + "004117103b418396abdd03410d20054114101e417341c488c0004115103b418396abdd03410d41ab82c0004108101f" + "417341d988c0004114103b200220002802a001200241810841001000417441ed88c000410e103b2002418108420110" + "01417441fb88c0004112103b418382c0004181082008410810264174418d89c0004115103b418382c0004181082005" + "4114101e417441a289c0004113103b418382c00041810841ab82c0004108101f417441b589c0004112103b418382c0" + "00410d200220002802a001101f417141c789c0004116103b200041003b018e02200220002802a00120054114200341" + "0210254171419e9bc000411d103b418382c000410d200220002802a00141021000417141dd89c0004114103b410141" + "0020054114101e410041f189c0004117103b20004190026a240041010f0b0b418080c000410b417f20032003417f4e" + "1bac1001000b0ba61b0200418080c0000b89046572726f725f636f64653d54455354204641494c4544242424242420" + "5354415254494e47205741534d20455845435554494f4e202424242424746573745f616d656e646d656e74616d656e" + "646d656e745f656e61626c656463616368655f6c6574785f6172725f6c656e686f6d655f6c655f6172725f6c656e6c" + "655f6172725f6c656e74785f696e6e65725f6172725f6c656e686f6d655f6c655f696e6e65725f6172725f6c656e6c" + "655f696e6e65725f6172725f6c656e7365745f6461746174657374206d65737361676574657374207075626b657974" + "657374207369676e6174757265636865636b5f7369676e66745f666c6167736e66745f786665725f66656574657374" + "696e6720747261636574726163655f61636374400000000000005f74726163655f616d744000000000000000747261" + "63655f616d745f7a65726f706172656e745f6c6467725f686173685f6e65675f70747274785f6172725f6c656e5f69" + "6e76616c69645f736669656c6474785f696e6e65725f6172725f6c656e5f6e65675f70747274785f696e6e65725f61" + "72725f6c656e5f6e65675f6c656e74785f696e6e65725f6172725f6c656e5f746f6f5f6c6f6e6774785f696e6e6572" + "5f6172725f6c656e5f7074725f6f6f6263616368655f6c655f7074725f6f6f6263616368655f6c655f77726f6e675f" + "6c656e55534430303030303030303030303030303030300041b184c0000b8a1774726163655f6e756d5f6f6f625f73" + "7472686f6d655f6c655f6172725f6c656e5f696e76616c69645f736669656c646c655f6172725f6c656e5f696e7661" + "6c69645f736669656c64616d656e646d656e745f656e61626c65645f746f6f5f6269675f736c696365616d656e646d" + "656e745f656e61626c65645f746f6f5f6c6f6e6774785f696e6e65725f6172725f6c656e5f746f6f5f6269675f736c" + "696365686f6d655f6c655f696e6e65725f6172725f6c656e5f746f6f5f6269675f736c6963656c655f696e6e65725f" + "6172725f6c656e5f746f6f5f6269675f736c6963657365745f646174615f746f6f5f6269675f736c69636574726163" + "655f6f6f625f736c69636574726163655f78666c6f61745f6f6f625f736c69636574726163655f616d745f6f6f625f" + "736c696365666c6f61745f636d705f6f6f625f736c69636531666c6f61745f636d705f6f6f625f736c696365326361" + "6368655f6c655f77726f6e675f73697a655f75696e743235366e66745f666c6167735f77726f6e675f73697a655f75" + "696e743235366e66745f786665725f6665655f77726f6e675f73697a655f75696e7432353630303030303030303030" + "3030303030303030303030303030303030303030303174726163655f616363745f77726f6e675f73697a655f616363" + "6f756e745f696474726163655f6f6f625f737472696e6774726163655f78666c6f61745f6f6f625f737472696e6774" + "726163655f616363745f6f6f625f737472696e6774726163655f616d745f6f6f625f737472696e6774726163655f74" + "6f6f5f6c6f6e6774726163655f6e756d5f746f6f5f6c6f6e6774726163655f78666c6f61745f746f6f5f6c6f6e6774" + "726163655f616363745f746f6f5f6c6f6e6774726163655f616d745f746f6f5f6c6f6e6774726163655f616d745f77" + "726f6e675f6c656e67746874726163655f696e76616c69645f61735f68657874726163655f616363745f636865636b" + "5f646573796e636c6467725f696e646578706172656e745f6c6467725f74696d65706172656e745f6c6467725f6861" + "7368626173655f666565686f6d655f6c655f6669656c646c655f6669656c6474785f696e6e6572686f6d655f6c655f" + "696e6e65726c655f696e6e65727368613531325f68616c666e66745f7572696e66745f6973737565726e66745f7461" + "786f6e6e66745f73657269616c706172656e745f6c6467725f686173685f6e65675f6c656e706172656e745f6c6467" + "725f686173685f6275665f746f6f5f736d616c6c706172656e745f6c6467725f686173685f6c656e5f746f6f5f6c6f" + "6e67636865636b5f69645f6f6f625f6c656e5f753332636865636b5f69645f77726f6e675f6c656e5f753332666c6f" + "61745f66726f6d5f75696e745f6c656e5f6f6f62666c6f61745f66726f6d5f75696e745f77726f6e675f6c656e5f75" + "696e7436346163636f756e74726f6f745f69645f6c656e5f6f6f626163636f756e74726f6f745f69645f77726f6e67" + "5f6c656e74727573746c696e655f69645f6c656e5f6f6f625f63757272656e637974727573746c696e655f69645f77" + "726f6e675f6c656e5f63757272656e6379616d6d5f69645f6c656e5f6f6f625f617373657432616d6d5f69645f6c65" + "6e5f77726f6e675f6c656e5f617373657432616d6d5f69645f6c656e5f77726f6e675f6e6f6e5f7872705f63757272" + "656e63795f6c656e616d6d5f69645f6c656e5f77726f6e675f7872705f63757272656e63795f6c656e616d6d5f6964" + "5f6d707474785f6669656c645f696e76616c69645f736669656c64686f6d655f6c655f6669656c645f696e76616c69" + "645f736669656c646c655f6669656c645f696e76616c69645f736669656c6474785f696e6e65725f746f6f5f626967" + "5f736c696365686f6d655f6c655f696e6e65725f746f6f5f6269675f736c6963656c655f696e6e65725f746f6f5f62" + "69675f736c6963657368613531325f68616c665f746f6f5f6269675f736c696365616d6d5f69645f746f6f5f626967" + "5f736c69636563726564656e7469616c5f69645f746f6f5f6269675f736c6963656d70746f6b656e5f69645f746f6f" + "5f6269675f736c6963655f6d70746964666c6f61745f6164645f6f6f625f736c69636531666c6f61745f6164645f6f" + "6f625f736c69636532666c6f61745f7375625f6f6f625f736c69636531666c6f61745f7375625f6f6f625f736c6963" + "6532666c6f61745f6d756c745f6f6f625f736c69636531666c6f61745f6d756c745f6f6f625f736c69636532666c6f" + "61745f6469765f6f6f625f736c69636531666c6f61745f6469765f6f6f625f736c69636532666c6f61745f726f6f74" + "5f6f6f625f736c696365666c6f61745f706f775f6f6f625f736c696365657363726f775f69645f77726f6e675f7369" + "7a655f75696e7433326d70745f69737375616e63655f69645f77726f6e675f73697a655f75696e7433326e66745f6f" + "666665725f69645f77726f6e675f73697a655f75696e7433326f666665725f69645f77726f6e675f73697a655f7569" + "6e7433326f7261636c655f69645f77726f6e675f73697a655f75696e7433327061796368616e5f69645f77726f6e67" + "5f73697a655f75696e7433327065726d697373696f6e65645f646f6d61696e5f69645f77726f6e675f73697a655f75" + "696e7433327469636b65745f69645f77726f6e675f73697a655f75696e7433327661756c745f69645f77726f6e675f" + "73697a655f75696e7433326e66745f7572695f77726f6e675f73697a655f75696e743235366e66745f697373756572" + "5f77726f6e675f73697a655f75696e743235366e66745f7461786f6e5f77726f6e675f73697a655f75696e74323536" + "6e66745f73657269616c5f77726f6e675f73697a655f75696e743235366163636f756e74726f6f745f69645f77726f" + "6e675f73697a655f6163636f756e745f6964636865636b5f69645f77726f6e675f73697a655f6163636f756e745f69" + "6463726564656e7469616c5f69645f77726f6e675f73697a655f6163636f756e745f69643163726564656e7469616c" + "5f69645f77726f6e675f73697a655f6163636f756e745f69643264656c65676174655f69645f77726f6e675f73697a" + "655f6163636f756e745f69643164656c65676174655f69645f77726f6e675f73697a655f6163636f756e745f696432" + "6465706f7369745f707265617574685f69645f77726f6e675f73697a655f6163636f756e745f6964316465706f7369" + "745f707265617574685f69645f77726f6e675f73697a655f6163636f756e745f6964326469645f69645f77726f6e67" + "5f73697a655f6163636f756e745f6964657363726f775f69645f77726f6e675f73697a655f6163636f756e745f6964" + "74727573746c696e655f69645f77726f6e675f73697a655f6163636f756e745f69643174727573746c696e655f6964" + "5f77726f6e675f73697a655f6163636f756e745f6964326d70745f69737375616e63655f69645f77726f6e675f7369" + "7a655f6163636f756e745f69646d70746f6b656e5f69645f77726f6e675f73697a655f6163636f756e745f69646e66" + "745f6f666665725f69645f77726f6e675f73697a655f6163636f756e745f69646f666665725f69645f77726f6e675f" + "73697a655f6163636f756e745f69646f7261636c655f69645f77726f6e675f73697a655f6163636f756e745f696470" + "61796368616e5f69645f77726f6e675f73697a655f6163636f756e745f6964317061796368616e5f69645f77726f6e" + "675f73697a655f6163636f756e745f6964327065726d697373696f6e65645f646f6d61696e5f69645f77726f6e675f" + "73697a655f6163636f756e745f69647369676e6572735f69645f77726f6e675f73697a655f6163636f756e745f6964" + "7469636b65745f69645f77726f6e675f73697a655f6163636f756e745f69647661756c745f69645f77726f6e675f73" + "697a655f6163636f756e745f69646e66745f7572695f77726f6e675f73697a655f6163636f756e745f69646d70746f" + "6b656e5f69645f6d707469645f77726f6e675f6c656e677468004d0970726f64756365727302086c616e6775616765" + "010452757374000c70726f6365737365642d6279010572757374631d312e38372e3020283137303637653961632032" + "3032352d30352d303929002c0f7461726765745f6665617475726573022b0f6d757461626c652d676c6f62616c732b" + "087369676e2d657874"; + +extern std::string const kBadAlignWasmHex = + "0061736d01000000011b046000017f60057f7f7f7f7f017f60067f7f7f7f7f7f017f60000002260203656e760f666c" + "6f61745f66726f6d5f75696e74000103656e7608636865636b5f6964000203050403000000050301000306470b7f00" + "4180080b7f00418088020b7f004180080b7f00418088040b7f00418088040b7f00418088080b7f004180080b7f0041" + "8088080b7f004180800c0b7f0041000b7f0041010b07cc0110066d656d6f72790200115f5f7761736d5f63616c6c5f" + "63746f72730002057465737431000307655f64617461310300057465737432000407655f6461746132030104746573" + "7400050c5f5f64736f5f68616e646c6503020a5f5f646174615f656e6403030b5f5f737461636b5f6c6f7703040c5f" + "5f737461636b5f6869676803050d5f5f676c6f62616c5f6261736503060b5f5f686561705f6261736503070a5f5f68" + "6561705f656e6403080d5f5f6d656d6f72795f6261736503090c5f5f7461626c655f62617365030a0a99020402000b" + "2801017f418108427f370000418108410841a308410c41001000220041a40828020020004100481b0b5f01017f419a" + "88024191a4cca00136010041928802428994ace0d0c1c38710370100418a88024281848ca0d0c0c183083701004181" + "8802417f360000418a8802411441818802410441a3880241201001220041a4880228020020004100481b0b8a010103" + "7f418108427f370000418108410841a308410c410010002100419a88024191a4cca00136010041928802428994ace0" + "d0c1c38710370100418a88024281848ca0d0c0c1830837010041818802417f36000041a4082802002101418a880241" + "1441818802410441a3880241201001220241a4880228020020024100481b2000200120004100481b6a0b007f097072" + "6f647563657273010c70726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b202868" + "747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162346235613264623538" + "32393538616631656533303861373930636664623432626432343732302900490f7461726765745f66656174757265" + "73042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b" + "0a6d756c746976616c7565"; +*/ diff --git a/src/test/app/wasm_fixtures/fixtures.h b/src/test/app/wasm_fixtures/fixtures.h new file mode 100644 index 0000000000..4a3461a1fe --- /dev/null +++ b/src/test/app/wasm_fixtures/fixtures.h @@ -0,0 +1,12 @@ +#pragma once + +// TODO: consider moving these to separate files (and figure out the build) + +#include + +extern std::string const kLedgerSqnWasmHex; +extern std::string const kAllHostFunctionsWasmHex; +extern std::string const kAllKeyletsWasmHex; +extern std::string const kCodecovTestsWasmHex; + +extern std::string const kBadAlignWasmHex; diff --git a/src/test/app/wasm_fixtures/ledgerSqn.c b/src/test/app/wasm_fixtures/ledgerSqn.c new file mode 100644 index 0000000000..0f4c27af7d --- /dev/null +++ b/src/test/app/wasm_fixtures/ledgerSqn.c @@ -0,0 +1,14 @@ +#include + +int32_t ldgr_index(uint8_t *, int32_t); + +int escrow_finish() +{ + uint32_t sqn; + int32_t result = ldgr_index((uint8_t *)&sqn, sizeof(sqn)); + + if (result < 0) + return result; + + return sqn >= 5 ? 5 : 0; +}