From a4d1bd1a55305dfc520ec0856fc6360dee3b771e Mon Sep 17 00:00:00 2001 From: TimothyBanks Date: Tue, 8 Sep 2026 20:58:16 -0400 Subject: [PATCH] fix: Port smart escrow tests to new design --- src/benchmarks/libxrpl/wasm/README.md | 8 +- src/test/app/EscrowSmart_test.cpp | 1360 --------------- src/test/app/Wasm_test.cpp | 1434 ---------------- src/test/app/wasm_fixtures/fixtures.cpp | 1507 ----------------- src/test/app/wasm_fixtures/fixtures.h | 155 -- src/test/app/wasm_fixtures/updateData.c | 11 - .../libxrpl/helpers/TestServiceRegistry.h | 32 + src/tests/libxrpl/helpers/TxTest.cpp | 35 +- src/tests/libxrpl/helpers/TxTest.h | 98 +- src/tests/libxrpl/tx/wasm/README.md | 47 +- .../libxrpl/tx/wasm/fixtures/EscrowWasm.cpp | 49 + .../libxrpl/tx/wasm/fixtures/EscrowWasm.h | 88 + .../tx/wasm/fixtures/ModuleBuilder.cpp | 175 ++ .../libxrpl/tx/wasm/fixtures/ModuleBuilder.h | 45 + .../tx/wasm/transactor/BytecodePreflight.cpp | 219 +++ .../tx/wasm/transactor/BytecodeRun.cpp | 211 +++ .../tx/wasm/transactor/BytecodeSize.cpp | 148 ++ .../tx/wasm/transactor/DataOnReject.cpp | 141 ++ .../tx/wasm/transactor/FinishFailures.cpp | 220 +++ .../libxrpl/tx/wasm/transactor/GasFees.cpp | 108 ++ 20 files changed, 1597 insertions(+), 4494 deletions(-) delete mode 100644 src/test/app/EscrowSmart_test.cpp delete mode 100644 src/test/app/Wasm_test.cpp delete mode 100644 src/test/app/wasm_fixtures/fixtures.cpp delete mode 100644 src/test/app/wasm_fixtures/fixtures.h delete mode 100644 src/test/app/wasm_fixtures/updateData.c create mode 100644 src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.cpp create mode 100644 src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.h create mode 100644 src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.cpp create mode 100644 src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.h create mode 100644 src/tests/libxrpl/tx/wasm/transactor/BytecodePreflight.cpp create mode 100644 src/tests/libxrpl/tx/wasm/transactor/BytecodeRun.cpp create mode 100644 src/tests/libxrpl/tx/wasm/transactor/BytecodeSize.cpp create mode 100644 src/tests/libxrpl/tx/wasm/transactor/DataOnReject.cpp create mode 100644 src/tests/libxrpl/tx/wasm/transactor/FinishFailures.cpp create mode 100644 src/tests/libxrpl/tx/wasm/transactor/GasFees.cpp diff --git a/src/benchmarks/libxrpl/wasm/README.md b/src/benchmarks/libxrpl/wasm/README.md index 65b7677762..27700b937f 100644 --- a/src/benchmarks/libxrpl/wasm/README.md +++ b/src/benchmarks/libxrpl/wasm/README.md @@ -143,9 +143,11 @@ Linear, at roughly **800 bytes per compile**. Within the suite this is why every 7.9 GB at 25 repetitions, after which every later case in the binary failed to compile — 720 errored rows, all blaming cases that were innocent. -**Outside the suite it is worth a look.** A validator compiles twice per programmable-escrow -transaction against that same static engine. Whether that is unbounded growth in production depends -on wasmi internals not checked here — this is the C++-visible symptom, not a diagnosis. +**Outside the suite it is worth a look.** A validator compiles once to screen an `EscrowCreate` +and again for every `EscrowFinish` that runs the contract — with no module cache between them, and +once per apply attempt rather than once per transaction — all against that same static engine. +Whether that is unbounded growth in production depends on wasmi internals not checked here (wasmi +2.0.0, wasmparser 0.228): this is the C++-visible symptom, not a diagnosis. ## Gotchas, each of which has already cost someone an afternoon diff --git a/src/test/app/EscrowSmart_test.cpp b/src/test/app/EscrowSmart_test.cpp deleted file mode 100644 index 03e3538a42..0000000000 --- a/src/test/app/EscrowSmart_test.cpp +++ /dev/null @@ -1,1360 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace xrpl::test { - -struct EscrowSmart_test : public beast::unit_test::Suite -{ - void - testCreateBytecodePreflight(FeatureBitset features) - { - testcase("Test preflight checks involving Bytecode"); - - using namespace jtx; - using namespace std::chrono; - - Account const alice{"alice"}; - Account const carol{"carol"}; - - // Tests whether the ledger index is >= 5 - // getLedgerSqn() >= 5} - - { - // featureSmartEscrow disabled - Env env(*this, features - featureSmartEscrow); - env.fund(XRP(5000), alice, carol); - XRPAmount const txnFees = env.current()->fees().base + 1000; - auto const escrowCreate = escrow::create(alice, carol, XRP(1000)); - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temDISABLED)); - env.close(); - - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - escrow::Data("00112233"), - Fee(txnFees), - Ter(temDISABLED)); - env.close(); - } - - { - // Bytecode > max length - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - cfg->fees.bytecodeSizeLimit = 10; // 10 bytes - return cfg; - }), - features); - XRPAmount const txnFees = env.current()->fees().base + 1000; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto const escrowCreate = escrow::create(alice, carol, XRP(500)); - - // 11-byte string - std::string const longWasmHex = "00112233445566778899AA"; - env(escrowCreate, - escrow::Bytecode(longWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temMALFORMED)); - env.close(); - } - - { - // compute limit set to 0 - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - // WASM runtime disabled - cfg->fees.gasLimit = 0; - return cfg; - }), - features); - XRPAmount const txnFees = env.current()->fees().base + 1000; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto const escrowCreate = escrow::create(alice, carol, XRP(500)); - - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - escrow::Gas(100), - Fee(txnFees), - Ter(temMALFORMED)); - env.close(); - } - - { - // size limit set to 0 - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - cfg->fees.bytecodeSizeLimit = 0; // WASM upload disabled - return cfg; - }), - features); - XRPAmount const txnFees = env.current()->fees().base + 1000; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto const escrowCreate = escrow::create(alice, carol, XRP(500)); - - // 2-byte string - env(escrowCreate, - escrow::Bytecode("AA"), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temTEMP_DISABLED)); - env.close(); - - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temTEMP_DISABLED)); - env.close(); - } - - { - // Data without Bytecode - Env env(*this, features); - XRPAmount const txnFees = env.current()->fees().base + 100000; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto const escrowCreate = escrow::create(alice, carol, XRP(500)); - - std::string const longData(4, 'A'); - env(escrowCreate, - escrow::Data(longData), - escrow::kFinishTime(env.now() + 100s), - Fee(txnFees), - Ter(temMALFORMED)); - env.close(); - } - - { - // Data > max length - Env env(*this, features); - XRPAmount const txnFees = env.current()->fees().base + 100000; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto const escrowCreate = escrow::create(alice, carol, XRP(500)); - - // string of length kMaxWasmDataLength * 2 + 2 - std::string const longData((kMaxWasmDataLength + 1) * 2, 'B'); - env(escrowCreate, - escrow::Data(longData), - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temMALFORMED)); - env.close(); - } - - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - cfg->startUp = StartUpType::Fresh; - return cfg; - }), - features); - XRPAmount const txnFees = - env.current()->fees().base * 10 + kLedgerSqnWasmHex.size() / 2 * 5; - // create escrow - env.fund(XRP(5000), alice, carol); - - auto escrowCreate = escrow::create(alice, carol, XRP(500)); - - // TODO: re-enable once kLedgerSqnWasmHex is regenerated. It is built from - // ledgerSqn.c, which imports `ldgr_index` from the `env` module. The Rust - // engine serves host functions from `host_lib` only (HOST_MODULE in - // crates/xrpl-wasm-vm/src/register.rs), so the module is refused at import - // screening and every case below gets temINVALID_BYTECODE instead of tesSUCCESS. - // The failure cases that follow still pass, because they are refused for a - // reason preflight reaches before it looks at the bytecode. - // - // Success situations - // { - // // Bytecode + CancelAfter - // env(escrowCreate, - // escrow::Bytecode(kLedgerSqnWasmHex), - // escrow::kCancelTime(env.now() + 20s), - // Fee(txnFees)); - // env.close(); - // } - // { - // // Bytecode + Condition + CancelAfter - // env(escrowCreate, - // escrow::Bytecode(kLedgerSqnWasmHex), - // escrow::kCancelTime(env.now() + 30s), - // escrow::kCondition(escrow::kCb1), - // Fee(txnFees)); - // env.close(); - // } - // { - // // Bytecode + FinishAfter + CancelAfter - // env(escrowCreate, - // escrow::Bytecode(kLedgerSqnWasmHex), - // escrow::kCancelTime(env.now() + 40s), - // escrow::kFinishTime(env.now() + 2s), - // Fee(txnFees)); - // env.close(); - // } - // { - // // Bytecode + FinishAfter + Condition + CancelAfter - // env(escrowCreate, - // escrow::Bytecode(kLedgerSqnWasmHex), - // escrow::kCancelTime(env.now() + 50s), - // escrow::kCondition(escrow::kCb1), - // escrow::kFinishTime(env.now() + 2s), - // Fee(txnFees)); - // env.close(); - // } - - // Failure situations (i.e. all other combinations) - { - // only Bytecode - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - Fee(txnFees), - Ter(temBAD_EXPIRATION)); - env.close(); - } - { - // Bytecode + FinishAfter - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kFinishTime(env.now() + 2s), - Fee(txnFees), - Ter(temBAD_EXPIRATION)); - env.close(); - } - { - // Bytecode + Condition - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCondition(escrow::kCb1), - Fee(txnFees), - Ter(temBAD_EXPIRATION)); - env.close(); - } - { - // Bytecode + FinishAfter + Condition - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCondition(escrow::kCb1), - escrow::kFinishTime(env.now() + 2s), - Fee(txnFees), - Ter(temBAD_EXPIRATION)); - env.close(); - } - { - // Bytecode 0 length - env(escrowCreate, - escrow::Bytecode(""), - escrow::kCancelTime(env.now() + 60s), - Fee(txnFees), - Ter(temMALFORMED)); - env.close(); - } - // TODO: re-enable with kLedgerSqnWasmHex (see above). The bytecode is - // refused before the fee is weighed, so this reports temINVALID_BYTECODE rather - // than telINSUF_FEE_P. - // { - // // Not enough fees - // env(escrowCreate, - // escrow::Bytecode(kLedgerSqnWasmHex), - // escrow::kCancelTime(env.now() + 70s), - // Fee(txnFees - 1), - // Ter(telINSUF_FEE_P)); - // env.close(); - // } - - { - // Bytecode nonexistent host function - // pub fn finish() -> bool { - // unsafe { host_lib::bad() >= 5 } - // } - auto const badWasmHex = - "0061736d010000000105016000017f02100108686f73745f6c696203626164" - "00000302010005030100100611027f00418080c0000b7f00418080c0000b07" - "2e04066d656d6f727902000666696e69736800010a5f5f646174615f656e64" - "03000b5f5f686561705f6261736503010a09010700100041044a0b004d0970" - "726f64756365727302086c616e6775616765010452757374000c70726f6365" - "737365642d6279010572757374631d312e38352e3120283465623136313235" - "3020323032352d30332d31352900490f7461726765745f6665617475726573" - "042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f72" - "65666572656e63652d74797065732b0a6d756c746976616c7565"; - env(escrowCreate, - escrow::Bytecode(badWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees), - Ter(temINVALID_BYTECODE)); - env.close(); - } - } - - void - testFinishWasmFailures(FeatureBitset features) - { - testcase("EscrowFinish Smart Escrow failures"); - - using namespace jtx; - using namespace std::chrono; - - Account const alice{"alice"}; - Account const carol{"carol"}; - - // Tests whether the ledger index is >= 5 - // getLedgerSqn() >= 5} - - { - // featureSmartEscrow disabled - Env env(*this, features - featureSmartEscrow); - env.fund(XRP(5000), alice, carol); - XRPAmount const txnFees = - env.current()->fees().base * 10 + kLedgerSqnWasmHex.size() / 2 * 5; - env(escrow::finish(carol, alice, 1), Fee(txnFees), escrow::Gas(4), Ter(temDISABLED)); - env.close(); - } - - { - // Gas > max compute limit - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - cfg->fees.gasLimit = 1'000; // in gas - return cfg; - }), - features); - env.fund(XRP(5000), alice, carol); - // Run past the flag ledger so that a Fee change vote occurs and - // updates FeeSettings. (It also activates all supported - // amendments.) - for (auto i = env.current()->seq(); i <= 257; ++i) - env.close(); - - auto const allowance = 1'001; - env(escrow::finish(carol, alice, 1), - Fee(env.current()->fees().base + allowance), - escrow::Gas(allowance), - Ter(temBAD_LIMIT)); - } - - { - // WASM compute disabled - using namespace test::jtx; - using namespace std::chrono; - Env env{*this, envconfig([](std::unique_ptr cfg) { - cfg->fees.gasLimit = 0; - return cfg; - })}; - - Account const alice{"alice"}; - env.fund(XRP(1000), alice); - env.close(); - - auto const seq = env.seq(alice); - auto const keylet = keylet::escrow(alice.id(), SeqProxy::rawSequence(seq)); - env(noop(alice)); // to align sequence numbers - - // This adds the Escrow ledger object by hand, bypassing normal - // transaction processing This is necessary because the config - // cannot be updated in the middle of a test, and we cannot easily - // create a Smart Escrow while the compute limit is set to 0 - env.app().getOpenLedger().modify([&](OpenView& view, beast::Journal j) { - auto sle = std::make_shared(keylet); - - sle->setAccountID(sfAccount, alice.id()); - sle->setFieldAmount(sfAmount, XRP(100)); - sle->setFieldU32(sfCancelAfter, 110); - sle->setAccountID(sfDestination, alice.id()); - sle->setFieldVL(sfBytecode, strUnHex(kLedgerSqnWasmHex).value()); - sle->setFieldU32(sfFlags, 0); - sle->setFieldU64(sfOwnerNode, 0); - uint256 tmp; - BEAST_EXPECT(tmp.parseHex( - "F63D1A452A96C19EFD77901FB37D236C59EAA746771A6" - "85D1BBA57A2238B9401")); - sle->setFieldH256(sfPreviousTxnID, tmp); - sle->setFieldU32(sfPreviousTxnLgrSeq, 4); - sle->setFieldU32(sfSequence, seq); - - view.rawInsert(sle); - return true; - }); - BEAST_EXPECT(env.le(keylet)); - - env(escrow::finish(alice, alice, seq), - escrow::Gas(1000), - Fee(env.current()->fees().base + 1000), - Ter(temTEMP_DISABLED)); - } - - Env env(*this, features); - - // Run past the flag ledger so that a Fee change vote occurs and - // updates FeeSettings. (It also activates all supported - // amendments.) - for (auto i = env.current()->seq(); i <= 257; ++i) - env.close(); - - XRPAmount const txnFees = - env.current()->fees().base * 10 + kLedgerSqnWasmHex.size() / 2 * 5; - env.fund(XRP(5000), alice, carol); - - // create escrow - auto const seq = env.seq(alice); - env(escrow::create(alice, carol, XRP(500)), - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees)); - env.close(); - - { - // no Gas field - env(escrow::finish(carol, alice, seq), Ter(tefBYTECODE_NOT_INCLUDED)); - } - - { - // Gas value of 0 - env(escrow::finish(carol, alice, seq), escrow::Gas(0), Ter(temBAD_LIMIT)); - } - - { - // not enough fees - // This function takes 4 gas - // In testing, 1 gas costs 1 drop - auto const finishFee = env.current()->fees().base + 3; - env(escrow::finish(carol, alice, seq), - Fee(finishFee), - escrow::Gas(4), - Ter(telINSUF_FEE_P)); - } - - { - // not enough gas - // This function takes 4 gas - // In testing, 1 gas costs 1 drop - auto const finishFee = env.current()->fees().base + 4; - env(escrow::finish(carol, alice, seq), - Fee(finishFee), - escrow::Gas(2), - Ter(tecOUT_OF_GAS)); - - // Running out of gas still reports the gas consumed, which is the - // whole allowance. The function did not run to completion, so - // there is no return code to report. - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == 2, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - BEAST_EXPECT(txMeta && !txMeta->isFieldPresent(sfVMReturnCode)); - } - - { - // Gas field included w/no Bytecode on - // escrow - auto const seq2 = env.seq(alice); - env(escrow::create(alice, carol, XRP(500)), - escrow::kFinishTime(env.now() + 10s), - escrow::kCancelTime(env.now() + 100s)); - env.close(); - - auto const allowance = 100; - env(escrow::finish(carol, alice, seq2), - Fee(env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1), - escrow::Gas(allowance), - Ter(tefNO_BYTECODE)); - } - - { - // a trap in the wasm code reports the gas it burned, which is only - // part of the allowance - auto const trapSeq = env.seq(alice); - env(escrow::create(alice, carol, XRP(500)), - escrow::Bytecode(kTrapUnreachableHex), - escrow::kCancelTime(env.now() + 100s), - Fee(env.current()->fees().base * 10 + kTrapUnreachableHex.size() / 2 * 5)); - env.close(); - - std::uint32_t const allowance = 1000; - env(escrow::finish(carol, alice, trapSeq), - Fee(env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1), - escrow::Gas(allowance), - Ter(tecFAILED_PROCESSING)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed))) - { - auto const gasUsed = txMeta->getFieldU32(sfGasUsed); - BEAST_EXPECTS(gasUsed < allowance, std::to_string(gasUsed)); - } - BEAST_EXPECT(txMeta && !txMeta->isFieldPresent(sfVMReturnCode)); - } - } - - void - testBytecode(FeatureBitset features) - { - testcase("Example escrow function"); - - using namespace jtx; - using namespace std::chrono; - - Account const alice{"alice"}; - Account const carol{"carol"}; - - // Tests whether the ledger index is >= 5 - // getLedgerSqn() >= 5} - std::uint32_t const allowance = 467; - auto escrowCreate = escrow::create(alice, carol, XRP(1000)); - auto [createFee, finishFee] = [&]() { - Env const env(*this, features); - auto createFee = env.current()->fees().base * 10 + kLedgerSqnWasmHex.size() / 2 * 5; - auto finishFee = env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1; - return std::make_pair(createFee, finishFee); - }(); - - { - // basic Bytecode situation - Env env(*this, features); - // create escrow - env.fund(XRP(5000), alice, carol); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(createFee)); - env.close(); - - if (BEAST_EXPECT(env.ownerCount(alice) == 2)) - { - env.require(Balance(alice, XRP(4000) - createFee)); - env.require(Balance(carol, XRP(5000))); - - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - env(escrow::finish(alice, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - env(escrow::finish(alice, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - env.close(); - - { - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - env.meta()->getFieldU32(sfGasUsed) == allowance, - std::to_string(env.meta()->getFieldU32(sfGasUsed))); - } - } - - env(escrow::finish(alice, alice, seq), - Fee(finishFee), - escrow::Gas(allowance), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == allowance, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == 5, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - - { - // Bytecode + Condition - Env env(*this, features); - env.fund(XRP(5000), alice, carol); - BEAST_EXPECT(env.ownerCount(alice) == 0); - auto const seq = env.seq(alice); - // create escrow - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCondition(escrow::kCb1), - escrow::kCancelTime(env.now() + 100s), - Fee(createFee)); - env.close(); - auto const conditionFinishFee = - finishFee + env.current()->fees().base * (32 + (escrow::kFb1.size() / 16)); - - if (BEAST_EXPECT(env.ownerCount(alice) == 2)) - { - env.require(Balance(alice, XRP(4000) - createFee)); - env.require(Balance(carol, XRP(5000))); - - // no fulfillment provided, function fails - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecCRYPTOCONDITION_ERROR)); - // fulfillment provided, function fails - env(escrow::finish(carol, alice, seq), - escrow::kCondition(escrow::kCb1), - escrow::kFulfillment(escrow::kFb1), - escrow::Gas(allowance), - Fee(conditionFinishFee), - Ter(tecBYTECODE_REJECTED)); - if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - env.meta()->getFieldU32(sfGasUsed) == allowance, - std::to_string(env.meta()->getFieldU32(sfGasUsed))); - } - env.close(); - // no fulfillment provided, function succeeds - env(escrow::finish(alice, alice, seq), - escrow::Gas(allowance), - Fee(conditionFinishFee), - Ter(tecCRYPTOCONDITION_ERROR)); - // wrong fulfillment provided, function succeeds - env(escrow::finish(alice, alice, seq), - escrow::kCondition(escrow::kCb1), - escrow::kFulfillment(escrow::kFb2), - escrow::Gas(allowance), - Fee(conditionFinishFee), - Ter(tecCRYPTOCONDITION_ERROR)); - // fulfillment provided, function succeeds, tx succeeds - env(escrow::finish(alice, alice, seq), - escrow::kCondition(escrow::kCb1), - escrow::kFulfillment(escrow::kFb1), - escrow::Gas(allowance), - Fee(conditionFinishFee), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == allowance, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == 5, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - env.close(); - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - - { - // Bytecode + FinishAfter - Env env(*this, features); - // create escrow - env.fund(XRP(5000), alice, carol); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - auto const ts = env.now() + 97s; - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kFinishTime(ts), - escrow::kCancelTime(env.now() + 1000s), - Fee(createFee)); - env.close(); - - if (BEAST_EXPECT(env.ownerCount(alice) == 2)) - { - env.require(Balance(alice, XRP(4000) - createFee)); - env.require(Balance(carol, XRP(5000))); - - // finish time hasn't passed, function fails - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee + 1), - Ter(tecNO_PERMISSION)); - env.close(); - // finish time hasn't passed, function succeeds - for (; env.now() < ts; env.close()) - { - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee + 2), - Ter(tecNO_PERMISSION)); - } - - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee + 1), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == 5, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - - { - // Bytecode + FinishAfter #2 - Env env(*this, features); - // create escrow - env.fund(XRP(5000), alice, carol); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kFinishTime(env.now() + 2s), - escrow::kCancelTime(env.now() + 100s), - Fee(createFee)); - // Don't close the ledger here - - if (BEAST_EXPECT(env.ownerCount(alice) == 2)) - { - env.require(Balance(alice, XRP(4000) - createFee)); - env.require(Balance(carol, XRP(5000))); - - // finish time hasn't passed, function fails - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecNO_PERMISSION)); - env.close(); - - // finish time has passed, function fails - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - if (BEAST_EXPECT(env.meta()->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - env.meta()->getFieldU32(sfGasUsed) == allowance, - std::to_string(env.meta()->getFieldU32(sfGasUsed))); - } - env.close(); - // finish time has passed, function succeeds, tx succeeds - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - BEAST_EXPECT(txMeta->getFieldU32(sfGasUsed) == allowance); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == 5, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - env.close(); - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - } - - void - testUpdateDataOnFailure(FeatureBitset features) - { - testcase("Update escrow data on failure"); - - using namespace jtx; - using namespace std::chrono; - - // wasm that always fails - Account const alice{"alice"}; - Account const carol{"carol"}; - - Env env(*this, features); - // create escrow - env.fund(XRP(5000), alice); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - auto escrowCreate = escrow::create(alice, alice, XRP(1000)); - XRPAmount const txnFees = - env.current()->fees().base * 10 + kUpdateDataWasmHex.size() / 2 * 5; - env(escrowCreate, - escrow::Bytecode(kUpdateDataWasmHex), - escrow::kFinishTime(env.now() + 2s), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees)); - env.close(); - env.close(); - env.close(); - - if (BEAST_EXPECT(env.ownerCount(alice) == (1 + (kUpdateDataWasmHex.size() / 2 / 500)))) - { - env.require(Balance(alice, XRP(4000) - txnFees)); - - auto const allowance = 1420; - XRPAmount const finishFee = env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1; - - // FinishAfter time hasn't passed - env(escrow::finish(alice, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecBYTECODE_REJECTED)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == allowance, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == -256, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - auto const sle = env.le(keylet::escrow(alice, SeqProxy::rawSequence(seq))); - if (BEAST_EXPECT(sle && sle->isFieldPresent(sfData))) - BEAST_EXPECTS(checkVL(sle, sfData, "Data"), strHex(sle->getFieldVL(sfData))); - } - } - - void - testFees(FeatureBitset features) - { - testcase("Fees"); - - using namespace jtx; - using namespace std::chrono; - - Account const alice{"alice"}; - Account const carol{"carol"}; - - // Tests whether the ledger index is >= 5 - // getLedgerSqn() >= 5} - uint64_t const allowance = 467; - auto escrowCreate = escrow::create(alice, carol, XRP(1000)); - auto createFee = [&]() { - Env const env(*this, features); - auto createFee = env.current()->fees().base * 10 + kLedgerSqnWasmHex.size() / 2 * 5; - return createFee; - }(); - - { - // ensure fees don't overflow - Env env( - *this, - envconfig([](std::unique_ptr cfg) { - cfg->fees.gasPrice = 1'000'000; // in gas - return cfg; - }), - features); - // Run past the flag ledger so that a Fee change vote occurs and - // updates FeeSettings. (It also activates all supported - // amendments.) - for (auto i = env.current()->seq(); i <= 257; ++i) - env.close(); - - // create escrow - env.fund(XRP(5000), alice, carol); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - env(escrowCreate, - escrow::Bytecode(kLedgerSqnWasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(createFee)); - env.close(); - - if (BEAST_EXPECT(env.ownerCount(alice) == 2)) - { - env.require(Balance(alice, XRP(4000) - createFee)); - env.require(Balance(carol, XRP(5000))); - env.close(); - - auto const bigAllowance = 996'433; - uint64_t const partialFeeCalc = - ((static_cast(bigAllowance) * 1'000'000) / microDropsPerDrop) + 1; - auto finishFee = env.current()->fees().base + partialFeeCalc; - BEAST_EXPECT(finishFee.drops() > bigAllowance); - - // Intentional low value to test overflow handling - auto finishFeeOverflow = drops(30); - - env(escrow::finish(alice, alice, seq), - Fee(finishFeeOverflow), // enough if there's an overflow - escrow::Gas(bigAllowance), - Ter(telINSUF_FEE_P)); - - env(escrow::finish(alice, alice, seq), - Fee(finishFee - 1), - escrow::Gas(bigAllowance), - Ter(telINSUF_FEE_P)); - - env(escrow::finish(alice, alice, seq), - Fee(finishFee), - escrow::Gas(bigAllowance), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == allowance, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - { - BEAST_EXPECTS( - txMeta->getFieldI32(sfVMReturnCode) == 5, - std::to_string(txMeta->getFieldI32(sfVMReturnCode))); - } - - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - } - - void - testAllHostFunctions(FeatureBitset features) - { - testcase("Test all host functions"); - - using namespace jtx; - using namespace std::chrono; - - Account const alice{"alice"}; - Account const carol{"carol"}; - - { - Env env(*this, features); - // create escrow - env.fund(XRP(5000), alice, carol); - auto const seq = env.seq(alice); - BEAST_EXPECT(env.ownerCount(alice) == 0); - auto escrowCreate = escrow::create(alice, carol, XRP(1000)); - XRPAmount const txnFees = - env.current()->fees().base * 10 + kAllHostFunctionsWasmHex.size() / 2 * 5; - env(escrowCreate, - escrow::Bytecode(kAllHostFunctionsWasmHex), - escrow::kFinishTime(env.now() + 11s), - escrow::kCancelTime(env.now() + 100s), - escrow::Data("1000000000"), // 1000 XRP in drops - Fee(txnFees)); - env.close(); - - if (BEAST_EXPECT( - env.ownerCount(alice) == (1 + (kAllHostFunctionsWasmHex.size() / 2 / 500)))) - { - env.require(Balance(alice, XRP(4000) - txnFees)); - env.require(Balance(carol, XRP(5000))); - - auto const allowance = 1'000'000; - XRPAmount const finishFee = env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1; - - // FinishAfter time hasn't passed - env(escrow::finish(carol, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tecNO_PERMISSION)); - env.close(); - env.close(); - env.close(); - - // reduce the destination balance - env(pay(carol, alice, XRP(4500))); - env.close(); - env.close(); - - env(escrow::finish(alice, alice, seq), - escrow::Gas(allowance), - Fee(finishFee), - Ter(tesSUCCESS)); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed))) - { - BEAST_EXPECTS( - txMeta->getFieldU32(sfGasUsed) == 49'964, - std::to_string(txMeta->getFieldU32(sfGasUsed))); - } - if (BEAST_EXPECT(txMeta->isFieldPresent(sfVMReturnCode))) - BEAST_EXPECT(txMeta->getFieldI32(sfVMReturnCode) == 1); - - env.close(); - BEAST_EXPECT(env.ownerCount(alice) == 0); - } - } - } - - // TODO: this test is disabled until the all_keylets fixture is - // regenerated; the call in run() is commented out. - // - // kAllKeyletsWasmHex was built against the old trace ABI, where the trace_* - // host functions returned i32 rather than void, so the module is rejected - // with temINVALID_BYTECODE and the escrow below is never created. - // - // Regenerating it is not just a rebuild: all_keylets/ is still pinned to - // xrpl-wasm-stdlib @ "renames" and uses modules that moved on - // xrpl-common-stdlib @ "error-and-trace" (core::keylets, - // core::ledger_objects::*, core::types::*, and trace_data/DataRepr). The - // fixture source has to be ported first, along with float_tests/ and - // float_0/, which are stale for the same reason. The gas expectations here - // will also need rechecking once the module runs again. - // - // Keylet coverage is not lost meanwhile: HostFuncImpl_test.cpp exercises - // every keylet host function directly. What is missing is the end-to-end - // path through a live escrow. - void - testKeyletHostFunctions(FeatureBitset features) - { - testcase("Test all keylet host functions"); - - using namespace jtx; - using namespace std::chrono; - - // TODO: create wasm module for all host functions - Account const alice{"alice"}; - Account const carol{"carol"}; - - { - Env env{*this}; - env.fund(XRP(10000), alice, carol); - - BEAST_EXPECT(env.seq(alice) == 4); - BEAST_EXPECT(env.ownerCount(alice) == 0); - - // base objects that need to be created first - auto const tokenId = token::getNextID(env, alice, 0, tfTransferable); - env(token::mint(alice, 0u), Txflags(tfTransferable)); - env(trust(alice, carol["USD"](1'000'000))); - env.close(); - BEAST_EXPECT(env.seq(alice) == 6); - BEAST_EXPECT(env.ownerCount(alice) == 2); - - // set up a bunch of objects to check their keylets - AMM const amm(env, carol, XRP(10), carol["USD"](1000)); - env(check::create(alice, carol, XRP(100))); - env(credentials::create(alice, alice, "termsandconditions")); - env(delegate::set(alice, carol, {"TrustSet"})); - env(deposit::auth(alice, carol)); - env(did::set(alice), did::Data("alice_did")); - env(escrow::create(alice, carol, XRP(100)), escrow::kFinishTime(env.now() + 100s)); - MPTTester mptTester{env, alice, {.fund = false}}; - mptTester.create(); - mptTester.authorize({.account = carol}); - env(token::createOffer(carol, tokenId, XRP(100)), token::Owner(alice)); - env(offer(alice, carol["GBP"](0.1), XRP(100))); - env(paychan::create(alice, carol, XRP(1000), 100s, alice.pk())); - pdomain::Credentials const credentials{ - {.issuer = alice, .credType = "first credential"}}; - env(pdomain::setTx(alice, credentials)); - env(signers(alice, 1, {{carol, 1}})); - env(ticket::create(alice, 1)); - Vault const vault{env}; - auto [tx, _keylet] = vault.create({.owner = alice, .asset = xrpIssue()}); - env(tx); - env.close(); - - BEAST_EXPECTS(env.ownerCount(alice) == 17, std::to_string(env.ownerCount(alice))); - if (BEAST_EXPECTS(env.seq(alice) == 20, std::to_string(env.seq(alice)))) - { - auto const seq = env.seq(alice); - XRPAmount const txnFees = - env.current()->fees().base * 10 + kAllKeyletsWasmHex.size() / 2 * 5; - env(escrow::create(alice, carol, XRP(1000)), - escrow::Bytecode(kAllKeyletsWasmHex), - escrow::kFinishTime(env.now() + 2s), - escrow::kCancelTime(env.now() + 100s), - Fee(txnFees)); - env.close(); - env.close(); - env.close(); - - auto const allowance = 184'375; - auto const finishFee = env.current()->fees().base + - (allowance * env.current()->fees().gasPrice) / microDropsPerDrop + 1; - env(escrow::finish(carol, alice, seq), escrow::Gas(allowance), Fee(finishFee)); - env.close(); - - auto const txMeta = env.meta(); - if (BEAST_EXPECT(txMeta && txMeta->isFieldPresent(sfGasUsed))) - { - auto const gasUsed = txMeta->getFieldU32(sfGasUsed); - BEAST_EXPECTS(gasUsed == allowance, std::to_string(gasUsed)); - } - BEAST_EXPECTS(env.ownerCount(alice) == 17, std::to_string(env.ownerCount(alice))); - } - } - } - - void - testLargeWasmModules(FeatureBitset features) - { - testcase("Test large wasm modules"); - - using namespace jtx; - using namespace std::chrono; - using namespace wasm_constants; - - enum class ExpectedStatus { Success, Malformed, Crash }; - - auto runTest = [&](std::vector const& wasm, - std::optional sizeLimit, - ExpectedStatus expectedStatus, - std::source_location const& loc = std::source_location::current()) { - auto makeEnv = [&]() -> Env { - if (sizeLimit) - { - return Env( - *this, - envconfig([&sizeLimit](std::unique_ptr cfg) { - cfg->fees.bytecodeSizeLimit = *sizeLimit; - return cfg; - }), - features); - } - return Env(*this, features); - }; - Env env = makeEnv(); - - auto const alice = Account("alice"); - env.fund(XRP(1'000'000), alice); - env.close(); - - auto const wasmHex = strHex(wasm); - try - { - env(escrow::create(alice, alice, XRP(1000)), - escrow::Bytecode(wasmHex), - escrow::kCancelTime(env.now() + 100s), - Fee(env.current()->fees().base * 10 + wasmHex.size() / 2 * 5), - Ter(expectedStatus == ExpectedStatus::Success ? TER{tesSUCCESS} - : TER{temMALFORMED})); - if (expectedStatus == ExpectedStatus::Crash) - { - fail("Expected crash", loc.file_name(), loc.line()); - } - else - { - pass(); - } - } - catch (std::exception const& e) - { - if (expectedStatus == ExpectedStatus::Crash) - { - pass(); - } - else - { - fail(e.what(), loc.file_name(), loc.line()); - } - } - }; - - // Table-driven test cases - struct TestCase - { - enum class BlobType { Code, Data }; - BlobType type; - uint32_t size; - std::optional sizeLimit; - ExpectedStatus expected; - }; - - std::vector const testCases = { - // Code blob tests - {.type = TestCase::BlobType::Code, - .size = 99'950, - .sizeLimit = std::nullopt, - .expected = ExpectedStatus::Success}, // just under 100kb - {.type = TestCase::BlobType::Code, - .size = 99'955, - .sizeLimit = std::nullopt, - .expected = ExpectedStatus::Malformed}, // just over 100kb - {.type = TestCase::BlobType::Code, - .size = 200'000, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Success}, // ~200kb - {.type = TestCase::BlobType::Code, - .size = 490'000, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Success}, // just under 1MB JSON - {.type = TestCase::BlobType::Code, - .size = 999'999, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Crash}, // just over 1MB JSON - // Data blob tests - {.type = TestCase::BlobType::Data, - .size = 99'939, - .sizeLimit = std::nullopt, - .expected = ExpectedStatus::Success}, // just under 100kb - {.type = TestCase::BlobType::Data, - .size = 99'941, - .sizeLimit = std::nullopt, - .expected = ExpectedStatus::Malformed}, // just over 100kb - {.type = TestCase::BlobType::Data, - .size = 200'000, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Success}, // ~200kb - {.type = TestCase::BlobType::Data, - .size = 490'000, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Success}, // just under 1MB JSON - {.type = TestCase::BlobType::Data, - .size = 999'950, - .sizeLimit = 10'000'000, - .expected = ExpectedStatus::Crash}, // just over 1MB JSON - }; - - for (auto const& tc : testCases) - { - auto const wasm = tc.type == TestCase::BlobType::Code ? generateCodeBlob(tc.size) - : generateDataBlob(tc.size); - runTest(wasm, tc.sizeLimit, tc.expected); - } - } - - void - testWithFeats(FeatureBitset features) - { - testCreateBytecodePreflight(features); - - // TODO: re-enable once the C-built fixtures are regenerated against the - // `host_lib` import module. ledgerSqn.c and updateData.c both import from - // `env`, which the old engine accepted (WasmVM.h declared wEnv alongside - // wHostLib) but the Rust engine does not: it serves `host_lib` only, so - // these modules are refused at import screening with temINVALID_BYTECODE. Each of - // these tests creates its escrow from one of those fixtures, so the - // creation fails and every later assertion cascades off it. The same - // regeneration would revive the blocks commented out in Wasm_test.cpp. - // testFinishWasmFailures(features); - // testBytecode(features); - // testUpdateDataOnFailure(features); - // testFees(features); - - // TODO: Update module with new host functions - testAllHostFunctions(features); - // TODO: re-enable once the all_keylets fixture is regenerated (see - // testKeyletHostFunctions) - // testKeyletHostFunctions(features); - - // TODO: re-enable once the expectations are refreshed for the Rust engine. - // Unrelated to the fixtures above: these modules are generated in-process - // and import nothing. wasmparser 0.228 (via wasmi 2.0.0-beta.10) caps a - // function body at MAX_WASM_FUNCTION_SIZE = 128 KiB, so the 200'000- and - // 490'000-instruction cases are now refused where the test expects them to - // be accepted. The >1MB cases also abort the run: the harness cannot carry - // a log message that large (multi_runner.cpp:398, recvdSize == 1). - // testLargeWasmModules(features); - } - -public: - void - run() override - { - using namespace test::jtx; - FeatureBitset const all{testableAmendments()}; - testWithFeats(all); - } -}; - -BEAST_DEFINE_TESTSUITE(EscrowSmart, app, xrpl); - -} // namespace xrpl::test diff --git a/src/test/app/Wasm_test.cpp b/src/test/app/Wasm_test.cpp deleted file mode 100644 index 3706428098..0000000000 --- a/src/test/app/Wasm_test.cpp +++ /dev/null @@ -1,1434 +0,0 @@ -#if 0 -#include -#ifdef _DEBUG -// #define DEBUG_OUTPUT 1 -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace xrpl::test { - -std::vector -hexToBytes(std::string const& hex) -{ - auto const ws = boost::algorithm::unhex(hex); - return Bytes(ws.begin(), ws.end()); -} - -template -unsigned -uleb128(IT& it, T val) -{ - unsigned count = 0; - do - { - std::uint8_t byte = val & 0x7f; - val >>= 7; - if (val) - byte |= 0x80; - *it++ = byte; - ++count; - } while (val != 0); - - return count; -} - -template -std::pair -uleb128(IT&& it) -{ - static_assert(sizeof(*it) == 1, "invalid iterator type"); - std::uint64_t val = 0; - std::uint64_t byte = 0; - unsigned shift = 0; - unsigned count = 0; - - do - { - if (shift > (sizeof(std::uint64_t) * 8) - 7) - return {0, 0}; - byte = *it++; - val |= (byte & 0x7F) << shift; - shift += 7; - ++count; - } while (byte >= 0x80); - - return {val, count}; -} - -// TODO: broken, fix after Rust re-arch. Only used by testImpExp, which is disabled -// below; kept (and kept compiling out) so it comes back with that test. -/* -static std::pair -getSection(Bytes const& module, std::uint8_t n) -{ - static std::uint8_t const kHdr[] = {0x00, 0x61, 0x73, 0x6D}; - static std::uint8_t const kVer[] = {0x01, 0x00, 0x00, 0x00}; - static std::uint8_t const kLastSec = 12; - - // sections: - // 0: "Custom", 1: "Type", 2: "Import", 3: "Function", 4: "Table", 5: "Memory", 6: "Global", - // 7: "Export", 8: "Start", 9: "Element", 10: "Code", 11: "Data", 12: "DataCount" - - if (module.size() < sizeof(kHdr) + sizeof(kVer) + 2) - return {0, 0}; - if (memcmp(module.data(), kHdr, sizeof(kHdr)) != 0) - return {0, 0}; - if (memcmp(module.data() + sizeof(kHdr), kVer, sizeof(kVer)) != 0) - return {0, 0}; - - unsigned pos = sizeof(kHdr) + sizeof(kVer); // sections start - for (; pos < module.size();) - { - auto const start = pos; - std::uint8_t const byte = module[pos++]; - if (byte > kLastSec) - return {0, 0}; - - auto [sz, cnt] = uleb128(module.cbegin() + pos); - if (cnt == 0u) - return {0, 0}; - if (pos + cnt + sz > module.size()) - return {0, 0}; - pos += cnt + sz; - - if (byte == n) - return {start, pos}; - } - return {0, 0}; -} -*/ - -static std::optional -runFinish(std::string const& code) -{ - auto const wasm = hexToBytes(code); - HostFunctions hfs; - auto const re = runEscrowWasm(wasm, hfs, 10'000'000, escrowFunctionName); - if (re.has_value()) - { - return std::optional(re->result); - } - - return std::nullopt; -} - -static bool -finishFunctionReturns(std::string const& code, int32_t expected) -{ - auto const result = runFinish(code); - return result.has_value() && *result == expected; -} - -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 - 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, env.journal, funcName); - BEAST_EXPECT(!isTesSuccess(re)); - } - - { - // Bytecode 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, env.journal, escrowFunctionName); - BEAST_EXPECT(!isTesSuccess(re)); - } - } - - // TODO: broken, fix after Rust re-arch. Both tests drive WasmEngine directly: - // testImpExp installs individually-priced imports via ImportVec/WASM_IMPORT_FUNC2, - // and both call arbitrary exports with parameters. runEscrowWasm calls a single - // export and takes no parameters, so neither can be expressed against it. - /* - void - testImpExp() - { - testcase("Wasm import/export functions"); - - auto impExpWasm = hexToBytes(kImpExpHex); - - using namespace test::jtx; - - Env env{*this}; - TestLedgerDataProvider hfs(env); - ImportVec imports; - WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", hfs, 33); - WASM_IMPORT_FUNC2(imports, getParentLedgerHash, "get_parent_ledger_hash", hfs, 60); - auto& engine = WasmEngine::instance(); - - // Test exp_func1() - should return 1 - auto re = engine.run(impExpWasm, hfs, 1'000'000, "exp_func1", {}, imports, env.journal); - checkResult(re, 1, 30); - - // Test exp_func2(5) - should return 2 * 5 = 10 - re = engine.run( - impExpWasm, hfs, 1'000'000, "exp_func2", wasmParams(5), imports, env.journal); - checkResult(re, 10, 52); - - // Test test_imports() - should call get_ledger_sqn and get_parent_ledger_hash - re = engine.run(impExpWasm, hfs, 1'000'000, "test_imports", {}, imports, env.journal); - // Should return the ledger sequence number (3 by default in test env) - checkResult(re, 3, 294); - - // Test corrupted import/export sections - invert each byte and expect failure - testcase("Wasm import/export section corruption"); - { - // Import section(#2): bytes [26, 79) - 53 bytes - // Export section(#7): bytes [90, 141) - 51 bytes - auto [importStart, importEnd] = getSection(impExpWasm, 2); - auto [exportStart, exportEnd] = getSection(impExpWasm, 7); - - BEAST_EXPECTS(importStart == 26, std::to_string(importStart)); - BEAST_EXPECTS(importEnd == 79, std::to_string(importEnd)); - BEAST_EXPECTS(exportStart == 90, std::to_string(exportStart)); - BEAST_EXPECTS(exportEnd == 141, std::to_string(exportEnd)); - - auto testInv = [&](unsigned i) { - auto corruptedWasm = impExpWasm; - corruptedWasm[i] = ~corruptedWasm[i]; // Invert byte - - // Try to run any function - should fail due to corruption - auto result = engine.run( - corruptedWasm, hfs, 1'000'000, "exp_func1", {}, imports, env.journal); - BEAST_EXPECT(!result); - }; - - // Test each byte in import section - for (unsigned i = importStart; i < importEnd; ++i) - testInv(i); - - // Test each byte in export section - for (unsigned i = exportStart; i < exportEnd; ++i) - testInv(i); - } - - env.close(); - } - - void - testWasmFib() - { - testcase("Wasm fibo"); - - auto const fibWasm = hexToBytes(kFibWasmHex); - auto& engine = WasmEngine::instance(); - HostFunctions hfs; - - auto const re = engine.run(fibWasm, hfs, 10'000'000, "fib", wasmParams(10)); - - checkResult(re, 55, 1'137); - } - */ - - 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, 50'207); - } - - { - // max() gas - TestHostFunctions hfs(env); - auto re = runEscrowWasm( - allHFWasm, hfs, std::numeric_limits::max(), escrowFunctionName); - checkResult(re, 1, 50'207); - } - - { // 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, 28'901); - } - - { // 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, 28'901); - } - -// This test use log output, so DEBUG_OUTPUT must be disabled. -#ifndef DEBUG_OUTPUT - { // fail because recursion too deep - - auto const deepWasm = hexToBytes(kDeepRecursionHex); - - TestHostFunctionsSink hfs(env); - std::string const funcName(escrowFunctionName); - auto re = runEscrowWasm(deepWasm, hfs, 1'000'000'000, funcName); - BEAST_EXPECT(!re && re.error().ter); - // std::cout << "bad case (deep recursion) result " << re.error() - // << std::endl; - - auto const& sink = hfs.getSink(); - auto countSubstr = [](std::string const& str, std::string const& substr) { - std::size_t pos = 0; - int occurrences = 0; - while ((pos = str.find(substr, pos)) != std::string::npos) - { - occurrences++; - pos += substr.length(); - } - return occurrences; - }; - - auto const s = sink.messages().str(); - BEAST_EXPECT(countSubstr(s, "wasm: ") == 1); - BEAST_EXPECT(countSubstr(s, "trap: call stack exhausted") > 0); - } -#endif - - { // infinite loop - auto const infiniteLoopWasm = hexToBytes(kInfiniteLoopWasmHex); - std::string const funcName("loop"); - TestHostFunctions hfs(env); - - // infinite loop should be caught and fail - auto const re = runEscrowWasm(infiniteLoopWasm, hfs, 1'000'000, funcName); - if (BEAST_EXPECT(!re.has_value())) - { - BEAST_EXPECT(re.error().ter == tecOUT_OF_GAS); - } - } - - // TODO: broken, fix after Rust re-arch. These three cases all build an - // ImportVec by hand and call WasmEngine::run; the import set is now fixed by - // the engine, so there is no way to under-provide it or desynchronise it from - // the HostFunctions the VM was given. - /* - { - // expected import not provided - auto const lgrSqnWasm = hexToBytes(kLedgerSqnWasmHex); - TestLedgerDataProvider hfs(env); - ImportVec imports; - WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn2", hfs); - - auto& engine = WasmEngine::instance(); - - auto re = engine.run( - lgrSqnWasm, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal); - - BEAST_EXPECT(!re); - } - - { - // HF unsync between import and VM - auto const lgrSqnWasm = hexToBytes(kLedgerSqnWasmHex); - TestLedgerDataProvider hfs(env); - TestLedgerDataProvider hfs2(env); - ImportVec imports; - WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", hfs2); - - auto& engine = WasmEngine::instance(); - - auto re = engine.run( - lgrSqnWasm, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal); - - BEAST_EXPECT(!re); - } - - { - // bad function name - auto const lgrSqnWasm = hexToBytes(kLedgerSqnWasmHex); - TestLedgerDataProvider hfs(env); - ImportVec imports; - WASM_IMPORT_FUNC2(imports, getLedgerSqn, "get_ledger_sqn", hfs); - - auto& engine = WasmEngine::instance(); - auto re = engine.run(lgrSqnWasm, hfs, 1'000'000, "func1", {}, imports, env.journal); - - BEAST_EXPECT(!re); - } - */ - } - - // TODO: testFloat is disabled until the float fixtures are regenerated. - // - // kFloatTestsWasmHex and kFloat0Hex were built against the old trace ABI, - // where the trace_* host functions returned i32. They now return void, so - // neither module instantiates and both blocks below fail with tecINTERNAL. - // - // Regenerating them is not just a rebuild: float_tests/ and float_0/ are - // still pinned to xrpl-wasm-stdlib @ "renames" and use APIs that no longer - // exist on xrpl-common-stdlib @ "error-and-trace" - // (FLOAT_ROUNDING_MODES_TO_NEAREST became RoundingMode, - // core::locator::Locator moved to fields::locator::Locator, and - // trace_data/DataRepr became trace_float/trace_hex). The fixture sources - // have to be ported first. The expected gas costs below are also stale and - // will need recomputing once the modules run again. - // - // void - // testFloat() - // { - // testcase("float point"); - // - // std::string const funcName(escrowFunctionName); - // - // using namespace test::jtx; - // - // Env env(*this); - // { - // auto const floatTestWasm = hexToBytes(kFloatTestsWasmHex); - // - // TestHostFunctions hfs(env); - // auto re = runEscrowWasm(floatTestWasm, hfs, 200'000, funcName, - // {}); checkResult(re, 1, 134'402); env.close(); - // } - // - // { - // auto const float0Wasm = hexToBytes(kFloat0Hex); - // - // TestHostFunctions hfs(env); - // auto re = runEscrowWasm(float0Wasm, hfs, 100'000, funcName); - // checkResult(re, 1, 2'775); - // env.close(); - // } - // } - - void - testCodecovWasm() - { - testcase("Codecov wasm test"); - - using namespace test::jtx; - - Env env{*this}; - - auto const codecovWasm = hexToBytes(kCodecovTestsWasmHex); - TestHostFunctions hfs(env); - - auto const allowance = 124'173; - auto re = runEscrowWasm(codecovWasm, hfs, allowance, escrowFunctionName); - - checkResult(re, 1, allowance); - } - - void - testDisabledFloat() - { - testcase("disabled float"); - - using namespace test::jtx; - Env env{*this}; - - auto disabledFloatWasm = hexToBytes(kDisabledFloatHex); - std::string const funcName(escrowFunctionName); - TestHostFunctions hfs(env); - - { - // f32 set constant, opcode disabled exception - auto const re = runEscrowWasm(disabledFloatWasm, hfs, 1'000'000, funcName); - if (BEAST_EXPECT(!re.has_value())) - { - BEAST_EXPECT(re.error().ter == tecFAILED_PROCESSING); - } - } - - { - // f32 add, can't create module exception - disabledFloatWasm[0x11e] = 0x92; - auto const re = runEscrowWasm(disabledFloatWasm, hfs, 1'000'000, funcName); - if (BEAST_EXPECT(!re.has_value())) - { - BEAST_EXPECT(re.error().ter == tecFAILED_PROCESSING); - } - } - } - - void - testWasmMemory() - { - testcase("Wasm additional memory limit tests"); - BEAST_EXPECT(finishFunctionReturns(kMemoryPointerAtLimitHex, 1)); - BEAST_EXPECT(!runFinish(kMemoryPointerOverLimitHex).has_value()); - BEAST_EXPECT(!runFinish(kMemoryOffsetOverLimitHex).has_value()); - BEAST_EXPECT(!runFinish(kMemoryEndOfWordOverLimitHex).has_value()); - BEAST_EXPECT(finishFunctionReturns(kMemoryGrow0To1PageHex, 1)); - BEAST_EXPECT(finishFunctionReturns(kMemoryGrow1To0PageHex, -1)); - BEAST_EXPECT(finishFunctionReturns(kMemoryLastByteOf8MbHex, 1)); - // Growing past the 8 MiB cap now traps ("growth operation limited") instead of - // letting memory.grow answer -1, so the run fails rather than returning. - BEAST_EXPECT(!runFinish(kMemoryGrow1MoreThan8MbHex).has_value()); - BEAST_EXPECT(finishFunctionReturns(kMemoryGrow0MoreThan8MbHex, 1)); - BEAST_EXPECT(!runFinish(kMemoryInit1MoreThan8MbHex).has_value()); - BEAST_EXPECT(!runFinish(kMemoryNegativeAddressHex).has_value()); - } - - void - testWasmTable() - { - testcase("Wasm table limit tests"); - BEAST_EXPECT(finishFunctionReturns(kTable64ElementsHex, 1)); - // 65 elements is no longer over the cap: MAX_TABLE_ELEMENTS is 1024. The - // boundary itself is covered by the engine's own test, since there is no - // 1025-element fixture here. - BEAST_EXPECT(finishFunctionReturns(kTable65ElementsHex, 1)); - BEAST_EXPECT(!runFinish(kTable2TablesHex).has_value()); - BEAST_EXPECT(finishFunctionReturns(kTable0ElementsHex, 1)); - BEAST_EXPECT(!runFinish(kTableUintMaxHex).has_value()); - } - - void - testWasmProposal() - { - testcase("Wasm disabled proposal tests"); - BEAST_EXPECT(!runFinish(kProposalMutableGlobalHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalGcStructNewHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalMultiValueHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalSignExtHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalFloatToIntHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalBulkMemoryHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalRefTypesHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalTailCallHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalExtendedConstHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalMultiMemoryHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalCustomPageSizesHex).has_value()); - BEAST_EXPECT(!runFinish(kProposalMemory64Hex).has_value()); - BEAST_EXPECT(!runFinish(kProposalWideArithmeticHex).has_value()); - } - - void - testWasmTrap() - { - testcase("Wasm trap tests"); - BEAST_EXPECT(!runFinish(kTrapDivideBy0Hex).has_value()); - BEAST_EXPECT(!runFinish(kTrapIntOverflowHex).has_value()); - BEAST_EXPECT(!runFinish(kTrapUnreachableHex).has_value()); - BEAST_EXPECT(!runFinish(kTrapNullCallHex).has_value()); - BEAST_EXPECT(!runFinish(kTrapFuncSigMismatchHex).has_value()); - } - - void - testWasmWasi() - { - testcase("Wasm Wasi tests"); - BEAST_EXPECT(!runFinish(kWasiGetTimeHex).has_value()); - BEAST_EXPECT(!runFinish(kWasiPrintHex).has_value()); - } - - void - testWasmSectionCorruption() - { - testcase("Wasm Section Corruption tests"); - BEAST_EXPECT(!runFinish(kBadMagicNumberHex).has_value()); - BEAST_EXPECT(!runFinish(kBadVersionNumberHex).has_value()); - BEAST_EXPECT(!runFinish(kLyingHeaderHex).has_value()); - BEAST_EXPECT(!runFinish(kNeverEndingNumberHex).has_value()); - BEAST_EXPECT(!runFinish(kVectorLieHex).has_value()); - BEAST_EXPECT(!runFinish(kSectionOrderingHex).has_value()); - BEAST_EXPECT(!runFinish(kGhostPayloadHex).has_value()); - BEAST_EXPECT(!runFinish(kJunkAfterSectionHex).has_value()); - BEAST_EXPECT(!runFinish(kInvalidSectionIdHex).has_value()); - BEAST_EXPECT(!runFinish(kLocalVariableBombHex).has_value()); - } - - // TODO: broken, fix after Rust re-arch. Needs WasmEngine::check, whose replacement - // preflightEscrowWasm takes no HostFunctions, and WasmEngine::run to observe that - // the start function - not the export - is what burns the gas. - /* - void - testStartFunctionLoop() - { - testcase("infinite loop in start function"); - - using namespace test::jtx; - Env env(*this); - - auto const startLoopWasm = hexToBytes(kStartLoopHex); - TestLedgerDataProvider hfs(env); - ImportVec const imports; - - auto& engine = WasmEngine::instance(); - auto checkRes = - engine.check(startLoopWasm, hfs, escrowFunctionName, {}, imports, env.journal); - BEAST_EXPECTS(checkRes == tesSUCCESS, transToken(checkRes)); - - auto result = - engine.run(startLoopWasm, hfs, 1'000'000, escrowFunctionName, {}, imports, env.journal); - auto resultTer = result.error().ter; - BEAST_EXPECTS(resultTer == tecFAILED_PROCESSING, transToken(resultTer)); - } - */ - - void - testReturnType() - { - using namespace test::jtx; - Env env(*this); - TestHostFunctions hfs(env); - - testcase("Wasm invalid return type"); - - // return int64. - { // (module - // (memory (export "memory") 1) - // (func (export "finish") (result i64) - // i64.const 0x100000000)) - auto const wasmHex = - "0061736d010000000105016000017e030201000503010001" - "071302066d656d6f727902000666696e69736800000a0a01" - "08004280808080100b"; - auto const wasm = hexToBytes(wasmHex); - auto const re = runEscrowWasm(wasm, hfs, 100'000, escrowFunctionName); - BEAST_EXPECT(!re); - } - - // return void. wasmi return execution error - { //(module - // (type (;0;) (func)) - // (func (;0;) (type 0) - // return) - // (memory (;0;) 1) - // (export "memory" (memory 0)) - // (export "finish" (func 0))) - auto const wasmHex = - "0061736d01000000010401600000030201000503010001071302066d656d6f" - "727902000666696e69736800000a050103000f0b"; - auto const wasm = hexToBytes(wasmHex); - auto const re = runEscrowWasm(wasm, hfs, 100'000, escrowFunctionName); - BEAST_EXPECT(!re); - } - - // return i32, i32. wasmi doesn't create module - { //(module - // (memory (export "memory") 1) - // (func (export "finish") (result i32 i32) - // i32.const 0x10000000 - // i32.const 0x100000FF)) - auto const wasmHex = - "0061736d010000000106016000027f7f030201000503010001071302066d65" - "6d6f727902000666696e69736800000a10010e0041808080800141ff818080" - "010b"; - auto const wasm = hexToBytes(wasmHex); - auto const re = runEscrowWasm(wasm, hfs, 100'000, escrowFunctionName); - BEAST_EXPECT(!re); - } - } - - void - testParameterType() - { - using namespace test::jtx; - Env env(*this); - TestHostFunctions hfs(env); - - testcase("Wasm invalid params"); - - // (module - // (memory (export "memory") 1) - // (func $test1 (export "test1") (param i32) (result i32) - // i32.const 1000) - // (func $test2 (export "test2") (param i32 i32) (result i32) - // i32.const 1001)) - auto const wasmHex = - "0061736d01000000010c0260017f017f60027f7f017f03030200010503010001071a03066d656d6f727902" - "00057465737431000005746573743200010a0d02050041e8070b050041e9070b"; - auto const wasm = hexToBytes(wasmHex); - - // no params. An export that wants any is refused, since runEscrowWasm has - // none to give it. - { - auto const re = runEscrowWasm(wasm, hfs, 100'000, "test1"); - BEAST_EXPECT(!re); - } - - { - auto const re = runEscrowWasm(wasm, hfs, 100'000, "test2"); - BEAST_EXPECT(!re); - } - - // TODO: broken, fix after Rust re-arch. The good-params control and the - // wrong-arity / wrong-type cases below all need to pass parameters, which - // runEscrowWasm cannot do. Without the positive case the two checks above - // only show that the export is refused, not that it would have run. - /* - // good params, module is working properly - { - auto const re = runEscrowWasm(wasm, hfs, 100'000, "test2", wasmParams(2, 10)); - BEAST_EXPECT(re && re->result == 1001 && re->cost == 37); - } - - // more params - { - auto const re = runEscrowWasm(wasm, hfs, 100'000, "test1", wasmParams(0, 1)); - BEAST_EXPECT(!re); - } - - // less params - { - auto const re = runEscrowWasm(wasm, hfs, 100'000, "test2", wasmParams(1)); - BEAST_EXPECT(!re); - } - - // invalid type - { - auto const re = - runEscrowWasm(wasm, hfs, 100'000, "test1", wasmParams(std::int64_t(15))); - BEAST_EXPECT(!re); - } - */ - } - - 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); - } - - // TODO: broken, fix after Rust re-arch. Builds a 1000-entry parameter vector and - // calls arbitrary exports through WasmEngine::run; runEscrowWasm passes no - // parameters, so the wasmi arity limit these cases straddle is unreachable. - /* - void - testManyParams() - { - testcase("Wasm Many params"); - - auto const params1k = hexToBytes(kThousandParamsHex); - auto const params1k1 = hexToBytes(kThousand1ParamsHex); - - using namespace test::jtx; - - Env env{*this}; - TestHostFunctions hfs(env); - auto imports = createWasmImport(hfs); - - // add 1k parameter (max that wasmi support) - std::vector params; - params.reserve(1000); - for (int i = 0; i < 1000; ++i) - params.push_back({.type = WasmTypes::WtI32, .of = {.i32 = 2 * i}}); - - auto& engine = WasmEngine::instance(); - { - auto re = engine.run(params1k, hfs, 1'000'000, "test", params, imports, env.journal); - BEAST_EXPECT(re && re->result == 999000); - } - - // add 1 more parameter, module can't be created now - params.push_back({.type = WasmTypes::WtI32, .of = {.i32 = 2 * 1000}}); - { - auto re = engine.run(params1k1, hfs, 1'000'000, "test", params, imports, env.journal); - BEAST_EXPECT(!re); - } - - // function that create 10k local variables - auto const locals10k = hexToBytes(kLocals10kHex); - { - auto re = engine.run( - locals10k, hfs, 1'000'000, "test", wasmParams(0, 1), imports, env.journal); - BEAST_EXPECT(re && re->result == 890'489'442); - } - - // module has 5k functions - auto const functions5k = hexToBytes(kFunctions5kHex); - { - auto re = engine.run( - functions5k, hfs, 1'000'000, "test0001", wasmParams(2, 3), imports, env.journal); - BEAST_EXPECT(re && re->result == 5); - } - - env.close(); - } - */ - - // TODO: broken, fix after Rust re-arch. Sweeps the reserved opcode space by - // patching a fixture and running its "all_instructions" export through - // WasmEngine::run with a hand-built import set. runEscrowWasm only calls - // escrow_finish, so the fixture cannot be driven. Restoring this needs - // and back at the top of the file. - // clang-format off - /* - void - testOpcodes() - { - using namespace test::jtx; - - unsigned const reserved = 64; - std::uint8_t const nop = 0x01; - std::array const codeMarker = { - nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop}; - auto const opcReserved = hexToBytes(kOpcReservedHex); - - Env env{*this}; - auto& engine = WasmEngine::instance(); - - TestHostFunctions hfs(env); - auto imports = createWasmImport(hfs); - env.close(); - - { - auto run = [&](std::vector const& code, - bool good = false, - int64_t cost = -1, - std::source_location const location = std::source_location::current()) { - auto const lineStr = " (" + std::to_string(location.line()) + ")"; - auto re = - engine.run(code, hfs, 1'000'000, "all_instructions", {}, imports, env.journal); - if (BEAST_EXPECTS(re.has_value() == good, transToken(re.error().ter) + lineStr) && - good) - BEAST_EXPECTS(re->cost == cost, std::to_string(re->cost) + lineStr); - }; - - // 1 byte instruction - auto test = [&](std::uint8_t start, - std::uint8_t finish, - bool good = false, - int64_t cost = -1, - std::source_location const location = std::source_location::current()) { - auto const lineStr = " (" + std::to_string(location.line()) + ")"; - auto code = opcReserved; - auto codeRange = std::ranges::search(code, codeMarker); - if (!BEAST_EXPECTS(!codeRange.empty(), lineStr)) - return; - - auto it = codeRange.begin(); - for (std::uint16_t i = start; i <= finish; ++i) - { - *it = i; - run(code, good, cost, location); - } - }; - - // 2 bytes instruction - auto test2 = [&](std::uint8_t major, - std::uint16_t start, - std::uint16_t finish, - bool good = false, - int64_t cost = -1, - std::source_location const location = - std::source_location::current()) { - auto const lineStr = " (" + std::to_string(location.line()) + ")"; - auto code = opcReserved; - auto codeRange = std::ranges::search(code, codeMarker); - if (!BEAST_EXPECTS(!codeRange.empty(), lineStr)) - return; - - auto it = codeRange.begin(); - *it++ = major; - for (std::uint16_t i = start; i <= finish; ++i) - { - auto it2 = it; - uleb128(it2, i); - run(code, good, cost, location); - } - }; - - // multibytes instructions - auto testMB = [&](std::vector const& codeSnap, - bool good = false, - int64_t cost = -1, - std::source_location const location = - std::source_location::current()) { - auto const lineStr = " (" + std::to_string(location.line()) + ")"; - auto code = opcReserved; - auto codeRange = std::ranges::search(code, codeMarker); - if (!BEAST_EXPECTS(!codeRange.empty(), lineStr)) - return; - - if (!BEAST_EXPECTS(codeSnap.size() < reserved, lineStr)) - return; - auto it = codeRange.begin(); - for (auto x : codeSnap) - *it++ = x; - run(code, good, cost, location); - }; - - // normal run - testcase("Wasm reserved opcodes main"); - test(nop, nop, true, 534); - - // reserved main - test(0x06, 0x0A); - test(0x12, 0x19); - test(0x25, 0x27); - test(0xC0, 0xFA); - test(0xFF, 0xFF); - - // reserved gc, string - testcase("Wasm reserved opcodes gc"); - test2(0xFB, 0x00, 0xBF); // not supported by compiler - - // reserved FC - testcase("Wasm reserved opcodes FC"); - test2(0xFC, 0x00, 0x07); // floats, disabled - test2(0xFC, 0x12, 0x1F); - - // reserved SIMD - testcase("Wasm reserved opcodes SIMD"); - test2(0xFD, 0x9A, 0x9A); - test2(0xFD, 0xA2, 0xA2); - test2(0xFD, 0xA5, 0xA6); - test2(0xFD, 0xAF, 0xB0); - test2(0xFD, 0xB2, 0xB4); - test2(0xFD, 0xB8, 0xB8); - test2(0xFD, 0xC2, 0xC2); - test2(0xFD, 0xC5, 0xC6); - test2(0xFD, 0xCF, 0xD0); - test2(0xFD, 0xD2, 0xD4); - test2(0xFD, 0xE2, 0xE2); - test2(0xFD, 0xEE, 0xEE); - test2(0xFD, 0x115, 0x12F); - - testcase("Wasm opcodes THREADS"); - test2(0xFE, 0x00, 0x4F); // not supported by compiler - - // FC mem instructions - testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x04, 0xFC, 0x08, 0x00, 0x00}); // memory.init - testMB({0xFC, 0x09, 0x00}); // data.drop - testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0A, 0x00, 0x00}); // memory.copy - testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0B, 0x00}); // memory.fill - testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0C, 0x00, 0x00}); // table.init - testMB({0xFC, 0x0D, 0x00}); // elem.drop - testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0E, 0x00, 0x00}); // table.copy - testMB({0xD2, 0x00, 0x41, 0x00, 0xFC, 0x0F, 0x00, 0x1A}); // table.grow - testMB({0x1A, 0xFC, 0x10, 0x00, 0x1A}); // table.size - testMB({0x41, 0x00, 0xD2, 0x00, 0x41, 0x00, 0xFC, 0x11, 0x00}); // table.fill - - testcase("Wasm opcodes SIMD"); - // clang-format off - - // generated by auggie - // SIMD instructions - testMB({0x41, 0x00, 0xFD, 0x00, 0x04, 0x00, 0x1A}); // v128.load - testMB({0x41, 0x00, 0xFD, 0x01, 0x03, 0x00, 0x1A}); // v128.load8x8_s - testMB({0x41, 0x00, 0xFD, 0x02, 0x03, 0x00, 0x1A}); // v128.load8x8_u - testMB({0x41, 0x00, 0xFD, 0x03, 0x03, 0x00, 0x1A}); // v128.load16x4_s - testMB({0x41, 0x00, 0xFD, 0x04, 0x03, 0x00, 0x1A}); // v128.load16x4_u - testMB({0x41, 0x00, 0xFD, 0x05, 0x03, 0x00, 0x1A}); // v128.load32x2_s - testMB({0x41, 0x00, 0xFD, 0x06, 0x03, 0x00, 0x1A}); // v128.load32x2_u - testMB({0x41, 0x00, 0xFD, 0x07, 0x00, 0x00, 0x1A}); // v128.load8_splat - testMB({0x41, 0x00, 0xFD, 0x08, 0x01, 0x00, 0x1A}); // v128.load16_splat - testMB({0x41, 0x00, 0xFD, 0x09, 0x02, 0x00, 0x1A}); // v128.load32_splat - testMB({0x41, 0x00, 0xFD, 0x0A, 0x03, 0x00, 0x1A}); // v128.load64_splat - testMB({0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0B, 0x04, 0x00}); // v128.store - testMB({0xFD, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1A}); // v128.const - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0D, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1A}); // i8x16.shuffle - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0E, 0x1A}); // i8x16.swizzle - testMB({0x41, 0x2A, 0xFD, 0x0F, 0x1A}); // i8x16.splat - testMB({0x41, 0x2A, 0xFD, 0x10, 0x1A}); // i16x8.splat - testMB({0x41, 0x2A, 0xFD, 0x11, 0x1A}); // i32x4.splat - testMB({0x42, 0x2A, 0xFD, 0x12, 0x1A}); // i64x2.splat - - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x15, 0x00, 0x1A}); // i8x16.extract_lane_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x16, 0x00, 0x1A}); // i8x16.extract_lane_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x17, 0x00, 0x1A}); // i8x16.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x18, 0x00, 0x1A}); // i16x8.extract_lane_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x19, 0x00, 0x1A}); // i16x8.extract_lane_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x1A, 0x00, 0x1A}); // i16x8.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1B, 0x00, 0x1A}); // i32x4.extract_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x1C, 0x00, 0x1A}); // i32x4.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1D, 0x00, 0x1A}); // i64x2.extract_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2A, 0xFD, 0x1E, 0x00, 0x1A}); // i64x2.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1F, 0x00, 0x1A}); // f32x4.extract_lane - testMB( - {0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x80, 0x3F, 0xFD, 0x20, 0x00, 0x1A}); // f32x4.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x21, 0x00, 0x1A}); // f64x2.extract_lane - testMB( - {0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0xFD, 0x22, 0x00, 0x1A}); // f64x2.replace_lane - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x23, 0x1A}); // i8x16.eq - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x24, 0x1A}); // i8x16.ne - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x25, 0x1A}); // i8x16.lt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x26, 0x1A}); // i8x16.lt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x27, 0x1A}); // i8x16.gt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x28, 0x1A}); // i8x16.gt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x29, 0x1A}); // i8x16.le_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2A, 0x1A}); // i8x16.le_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2B, 0x1A}); // i8x16.ge_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2C, 0x1A}); // i8x16.ge_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2D, 0x1A}); // i16x8.eq - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2E, 0x1A}); // i16x8.ne - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2F, 0x1A}); // i16x8.lt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x30, 0x1A}); // i16x8.lt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x31, 0x1A}); // i16x8.gt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x32, 0x1A}); // i16x8.gt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x33, 0x1A}); // i16x8.le_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x34, 0x1A}); // i16x8.le_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x35, 0x1A}); // i16x8.ge_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x36, 0x1A}); // i16x8.ge_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x37, 0x1A}); // i32x4.eq - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x38, 0x1A}); // i32x4.ne - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x39, 0x1A}); // i32x4.lt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3A, 0x1A}); // i32x4.lt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3B, 0x1A}); // i32x4.gt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3C, 0x1A}); // i32x4.gt_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3D, 0x1A}); // i32x4.le_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3E, 0x1A}); // i32x4.le_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3F, 0x1A}); // i32x4.ge_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x40, 0x1A}); // i32x4.ge_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4D, 0x1A}); // v128.not - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4E, 0x1A}); // v128.and - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4F, 0x1A}); // v128.andnot - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x50, 0x1A}); // v128.or - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x51, 0x1A}); // v128.xor - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x52, 0x1A}); // v128.bitselect - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x53, 0x1A}); // v128.any_true - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x60, 0x1A}); // i8x16.abs - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x61, 0x1A}); // i8x16.neg - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x62, 0x1A}); // i8x16.popcnt - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x63, 0x1A}); // i8x16.all_true - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x64, 0x1A}); // i8x16.bitmask - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6B, 0x1A}); // i8x16.shl - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6C, 0x1A}); // i8x16.shr_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6D, 0x1A}); // i8x16.shr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x6E, 0x1A}); // i8x16.add - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x6F, 0x1A}); // i8x16.add_sat_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x70, 0x1A}); // i8x16.add_sat_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x71, 0x1A}); // i8x16.sub - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x72, 0x1A}); // i8x16.sub_sat_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x73, 0x1A}); // i8x16.sub_sat_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x76, 0x1A}); // i8x16.min_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x77, 0x1A}); // i8x16.min_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x78, 0x1A}); // i8x16.max_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x79, 0x1A}); // i8x16.max_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x7B, 0x1A}); // i8x16.avgr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x80, 0x01, 0x1A}); // i16x8.abs - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x81, 0x01, 0x1A}); // i16x8.neg - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x83, 0x01, 0x1A}); // i16x8.all_true - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x84, 0x01, 0x1A}); // i16x8.bitmask - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8B, 0x01, 0x1A}); // i16x8.shl - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8C, 0x01, 0x1A}); // i16x8.shr_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8D, 0x01, 0x1A}); // i16x8.shr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x8E, 0x01, 0x1A}); // i16x8.add - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x01, 0x1A}); // i16x8.add_sat_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x90, 0x01, 0x1A}); // i16x8.add_sat_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x91, 0x01, 0x1A}); // i16x8.sub - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x92, 0x01, 0x1A}); // i16x8.sub_sat_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x93, 0x01, 0x1A}); // i16x8.sub_sat_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x95, 0x01, 0x1A}); // i16x8.mul - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x96, 0x01, 0x1A}); // i16x8.min_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x97, 0x01, 0x1A}); // i16x8.min_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x98, 0x01, 0x1A}); // i16x8.max_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x99, 0x01, 0x1A}); // i16x8.max_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x9B, 0x01, 0x1A}); // i16x8.avgr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA0, 0x01, 0x1A}); // i32x4.abs - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA1, 0x01, 0x1A}); // i32x4.neg - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA3, 0x01, 0x1A}); // i32x4.all_true - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA4, 0x01, 0x1A}); // i32x4.bitmask - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAB, 0x01, 0x1A}); // i32x4.shl - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAC, 0x01, 0x1A}); // i32x4.shr_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAD, 0x01, 0x1A}); // i32x4.shr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xAE, 0x01, 0x1A}); // i32x4.add - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB1, 0x01, 0x1A}); // i32x4.sub - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB5, 0x01, 0x1A}); // i32x4.mul - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB6, 0x01, 0x1A}); // i32x4.min_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB7, 0x01, 0x1A}); // i32x4.min_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB8, 0x01, 0x1A}); // i32x4.max_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB9, 0x01, 0x1A}); // i32x4.max_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xBA, 0x01, 0x1A}); // i32x4.dot_i16x8_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC0, 0x01, 0x1A}); // i64x2.abs - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC1, 0x01, 0x1A}); // i64x2.neg - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC3, 0x01, 0x1A}); // i64x2.all_true - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC4, 0x01, 0x1A}); // i64x2.bitmask - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCB, 0x01, 0x1A}); // i64x2.shl - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCC, 0x01, 0x1A}); // i64x2.shr_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCD, 0x01, 0x1A}); // i64x2.shr_u - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xCE, 0x01, 0x1A}); // i64x2.add - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD1, 0x01, 0x1A}); // i64x2.sub - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD5, 0x01, 0x1A}); // i64x2.mul - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD6, 0x01, 0x1A}); // i64x2.eq - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD7, 0x01, 0x1A}); // i64x2.ne - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD8, 0x01, 0x1A}); // i64x2.lt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD9, 0x01, 0x1A}); // i64x2.gt_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xDA, 0x01, 0x1A}); // i64x2.le_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xDB, 0x01, 0x1A}); // i64x2.ge_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF8, 0x01, 0x1A}); // i32x4.trunc_sat_f32x4_s - testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF9, 0x01, 0x1A}); // i32x4.trunc_sat_f32x4_u - - // clang-format on - } - } - */ - // clang-format on - - void - run() override - { - testBadWasm(); - testEscrowWasmDN(); - // TODO: re-enable once the float fixtures are regenerated (see above) - // testFloat(); - - testCodecovWasm(); - // TODO: broken, fix after Rust re-arch - // testDisabledFloat(); - - testWasmMemory(); - testWasmTable(); - testWasmProposal(); - testWasmTrap(); - testWasmWasi(); - testWasmSectionCorruption(); - - // TODO: broken, fix after Rust re-arch - // testStartFunctionLoop(); - testReturnType(); - testSwapBytes(); - // TODO: broken, fix after Rust re-arch - // testManyParams(); - testParameterType(); - - // TODO: broken, fix after Rust re-arch - // testOpcodes(); - } -}; - -BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl); - -} // namespace xrpl::test -#endif diff --git a/src/test/app/wasm_fixtures/fixtures.cpp b/src/test/app/wasm_fixtures/fixtures.cpp deleted file mode 100644 index b053043ff4..0000000000 --- a/src/test/app/wasm_fixtures/fixtures.cpp +++ /dev/null @@ -1,1507 +0,0 @@ -#include - -#include -#include -#include - -namespace wasm_constants { - -namespace { - -void -appendU32Leb(std::vector& out, uint32_t value) -{ - do - { - auto byte = static_cast(value & 0x7f); - value >>= 7; - if (value != 0u) - byte |= 0x80; - out.push_back(byte); - } while (value != 0u); -} - -void -appendSection(std::vector& out, uint8_t section, std::vector const& payload) -{ - out.push_back(section); - appendU32Leb(out, payload.size()); - out.insert(out.end(), payload.begin(), payload.end()); -} - -void -appendBytes(std::vector& out, auto const& bytes) -{ - for (auto byte : bytes) - out.push_back(byte); -} - -std::vector -baseModule() -{ - std::vector out; - appendBytes(out, kWasmHeader); - appendBytes(out, kTypeEmptyFunc); - appendBytes(out, kFuncTypE0); - appendBytes(out, kExportFinish); - return out; -} - -} // namespace - -std::vector -generateCodeBlob(uint32_t numInstructions) -{ - auto out = baseModule(); - - std::vector body; - body.push_back(0x00); - body.insert(body.end(), numInstructions, kInstrNop); - body.push_back(kInstrEnd); - - std::vector codePayload; - codePayload.push_back(0x01); - appendU32Leb(codePayload, body.size()); - codePayload.insert(codePayload.end(), body.begin(), body.end()); - - appendSection(out, kSectionCode, codePayload); - return out; -} - -std::vector -generateDataBlob(uint32_t dataSize) -{ - std::vector out; - appendBytes(out, kWasmHeader); - appendBytes(out, kTypeEmptyFunc); - appendBytes(out, kFuncTypE0); - - std::vector memoryPayload; - memoryPayload.push_back(0x01); - memoryPayload.push_back(0x00); - appendU32Leb(memoryPayload, (dataSize + 65'535) / 65'536); - appendSection(out, kSectionMemory, memoryPayload); - - appendBytes(out, kExportFinish); - - std::vector codePayload; - codePayload.push_back(0x01); - appendU32Leb(codePayload, sizeof(kEmptyBody)); - appendBytes(codePayload, kEmptyBody); - appendSection(out, kSectionCode, codePayload); - - std::vector dataPayload; - dataPayload.push_back(0x01); - dataPayload.push_back(0x00); - appendBytes(dataPayload, kDataOffsetZero); - appendU32Leb(dataPayload, dataSize); - dataPayload.insert(dataPayload.end(), dataSize, kDataFillByte); - appendSection(out, kSectionData, dataPayload); - - return out; -} - -} // namespace wasm_constants - -extern std::string const kFibWasmHex = - "0061736d0100000001090260000060017f017f030302000105030100020638097f004180080b7f004180080b7f0041" - "80080b7f00418088040b7f004180080b7f00418088040b7f00418080080b7f0041000b7f0041010b07a7010c066d65" - "6d6f72790200115f5f7761736d5f63616c6c5f63746f727300000366696200010c5f5f64736f5f68616e646c650300" - "0a5f5f646174615f656e6403010b5f5f737461636b5f6c6f7703020c5f5f737461636b5f6869676803030d5f5f676c" - "6f62616c5f6261736503040b5f5f686561705f6261736503050a5f5f686561705f656e6403060d5f5f6d656d6f7279" - "5f6261736503070c5f5f7461626c655f6261736503080a440202000b3f01017f200045044041000f0b200041034804" - "4041010f0b200041026a21000340200041036b100120016a2101200041026b220041044a0d000b200141016a0b007f" - "0970726f647563657273010c70726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b" - "202868747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162346235613264" - "62353832393538616631656533303861373930636664623432626432343732302900490f7461726765745f66656174" - "75726573042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d747970" - "65732b0a6d756c746976616c7565"; - -extern std::string const kLedgerSqnWasmHex = - "0061736d01000000010e0360027f7f017f6000006000017f02120103656e760a6c6467725f696e6465780000030302" - "01020503010002063f0a7f01418088040b7f004180080b7f004180080b7f004180080b7f00418088040b7f00418008" - "0b7f00418088040b7f00418080080b7f0041000b7f0041010b07b1010c066d656d6f72790200115f5f7761736d5f63" - "616c6c5f63746f727300010d657363726f775f66696e69736800020c5f5f64736f5f68616e646c6503010a5f5f6461" - "74615f656e6403020b5f5f737461636b5f6c6f7703030c5f5f737461636b5f6869676803040d5f5f676c6f62616c5f" - "6261736503050b5f5f686561705f6261736503060a5f5f686561705f656e6403070d5f5f6d656d6f72795f62617365" - "03080c5f5f7461626c655f6261736503090a3d0202000b3801037f230041106b220024002000410c6a410410002101" - "200028020c2102200041106a2400200141054100200241054f1b20014100481b0b007f0970726f647563657273010c" - "70726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b202868747470733a2f2f6769" - "746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162346235613264623538323935386166316565" - "33303861373930636664623432626432343732302900490f7461726765745f6665617475726573042b0f6d75746162" - "6c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c" - "7565"; - -extern std::string const kAllHostFunctionsWasmHex = - "0061736d0100000001550c60027f7f017f60037f7f7f017f60047f7f7f7f017f60017f017f60067f7f7f7f7f7f017f" - "60037f7f7f0060057f7f7f7f7f0060087f7f7f7f7f7f7f7f017f60057f7f7f7f7f017f60017f0060027f7f00600001" - "7f02b1041808686f73745f6c69620874785f6669656c64000108686f73745f6c6962057472616365000608686f7374" - "5f6c69620a6c6467725f696e646578000008686f73745f6c696210706172656e745f6c6467725f74696d6500000868" - "6f73745f6c696210706172656e745f6c6467725f68617368000008686f73745f6c69620874785f696e6e6572000208" - "686f73745f6c69620a74785f6172725f6c656e000308686f73745f6c69621074785f696e6e65725f6172725f6c656e" - "000008686f73745f6c69620d686f6d655f6c655f6669656c64000108686f73745f6c69620d686f6d655f6c655f696e" - "6e6572000208686f73745f6c69620f686f6d655f6c655f6172725f6c656e000308686f73745f6c696215686f6d655f" - "6c655f696e6e65725f6172725f6c656e000008686f73745f6c69620863616368655f6c65000108686f73745f6c6962" - "0d63726564656e7469616c5f6964000708686f73745f6c696209657363726f775f6964000408686f73745f6c696209" - "6f7261636c655f6964000408686f73745f6c69620b7368613531325f68616c66000208686f73745f6c6962076e6674" - "5f757269000408686f73745f6c6962087365745f64617461000008686f73745f6c69620a6c655f6172725f6c656e00" - "0008686f73745f6c69620e6163636f756e74726f6f745f6964000208686f73745f6c6962106c655f696e6e65725f61" - "72725f6c656e000108686f73745f6c6962086c655f6669656c64000208686f73745f6c6962086c655f696e6e657200" - "08030b0a090a05050b000101030005030100110619037f01418080c0000b7f0041c698c0000b7f0041d098c0000b07" - "3504066d656d6f727902000d657363726f775f66696e697368001c0a5f5f646174615f656e6403010b5f5f68656170" - "5f6261736503020acf210a9d0101027f230041206b2201240020014200370310200142003703082001410036021820" - "00027f024041818020200141086a41141000220241004e0440200241144b0d01200241144704402000418180808078" - "36020441010c030b20002001280218360011200020012903103700092000200129030837000141000c020b20002002" - "36020441010c010b2000417336020441010b3a0000200141206a24000b5a01017f230041106b2202240020012d0000" - "41014604402002200134020437030841df97c000410b4101200241086a41081001000b200020012800113600102000" - "200129000937000820002001290001370000200241106a24000b1900200241214f0440000b20002002360204200020" - "013602000b1900200241094f0440000b20002002360204200020013602000bdd1e01077f230041c0036b2200240041" - "ea97c000411b4107410141001001418598c0004119410741014100100141b583c000412b4107410141001001200041" - "003602500240024002400240024002400240200041d0006a41041002220141004a044020002000280250220141ff81" - "fc0771410878200141187841ff81fc077172ad3703c00141e083c00041174101200041c0016a220241081001200041" - "003602800120004180016a41041003220141004c0d012000200028028001220141ff81fc0771410878200141187841" - "ff81fc077172ad3703c00141f783c00041134101200241081001200042003703d801200042003703d0012000420037" - "03c801200042003703c0012002412010042201412047044020002001ac3703a00141bd84c000412b4101200041a001" - "6a4108100141997f21030c080b418a84c00041134106200041c0016a220441201001419d84c0004120410741014100" - "100141aa85c000412e4107410141001001200041003602b001200042003703a801200042003703a001418180202000" - "41a0016a22024114100022014114470d0241d885c00041144104200241141001200042003703384188801820004138" - "6a22024108100022014108470d03200042083703c00141ec85c00041174101200441081001418386c0004128410620" - "02410810012000410036027841848008200041f8006a22024104100022014104470d0441ab86c00041154106200241" - "04100120004100360051200041013a005020004100360054200042003703d801200042003703d001200042003703c8" - "01200042003703c0010240200041d0006a4108200441201005220141004e044020002001ad3703800141c086c00041" - "14410120004180016a41081001200041306a20042001101a41d486c000410d41062000280230200028023410010c01" - "0b20002001ac3703800141e186c0004129410120004180016a410810010b20004183803c1006ac37038001418a87c0" - "004115410120004180016a22024108100120004189803c1006ac37038001419f87c000411341012002410810010240" - "200041d0006a41081007220141004e044020002001ad3703800141b287c000411441012002410810010c010b200020" - "01ac3703800141c687c000412d410120004180016a410810010b41f387c0004123410741014100100141e792c00041" - "3341074101410010012000420037033841828018200041386a220141081008220241004c0d05200241084604402000" - "42083703c001419a93c000412b4101200041c0016a4108100141c593c000412f41062001410810010c070b20002002" - "ad3703c00141f493c000412f4101200041c0016a41081001200041286a200041386a2002101b41a394c00041174106" - "2000280228200028022c10010c060b20002001ac3703c001418d85c000411d4101200041c0016a41081001419b7f21" - "030c060b20002001ac3703c00141e884c00041254101200041c0016a41081001419a7f21030c050b20002001ac3703" - "c001418289c000412a4101200041c0016a4108100141b77e21030c040b20002001ac3703c00141c188c00041c10041" - "01200041c0016a4108100141b67e21030c030b20002001ac3703c001419688c000412b4101200041c0016a41081001" - "41b57e21030c020b20002002ac3703c00141ba94c00041c5004101200041c0016a410810010b200041003602b00120" - "0042003703a801200042003703a001024041818020200041a0016a220241141008220141004a044041ff94c000411e" - "41042002411410010c010b20002001ac3703c001419d95c00041334101200041c0016a410810010b20004100360051" - "200041013a005020004100360054200042003703d801200042003703d001200042003703c801200042003703c00102" - "40200041d0006a4108200041c0016a220141201009220241004e044020002002ad3703800141d095c000411c410120" - "004180016a41081001200041206a20012002101a41ec95c000411541062000280220200028022410010c010b200020" - "02ac37038001418196c0004139410120004180016a410810010b20004183803c100aac3703800141ba96c000412441" - "0120004180016a2201410810010240200041d0006a4108100b220241004e044020002002ad3703800141de96c00041" - "1c41012001410810010c010b20002002ac3703800141fa96c000413d410120004180016a410810010b41b797c00041" - "28410741014100100141ac89c000412f4107410141001001200041c0016a2204101820004180016a22012004101920" - "0042003703b801200042003703b001200042003703a801200042003703a001024002400240024002402001200041a0" - "016a2202101d22014120460440200241204100100c220541004a044020002005ad3703c00141db89c0004123410120" - "0441081001200042003703782005200041f8006a22014108101e220241004c0d0220024108460440200042083703c0" - "0141fe89c000412a410120044108100141a88ac000412e41062001410810010c060b20002002ad3703c00141d68ac0" - "00412e4101200041c0016a41081001200041186a200041f8006a2002101b41848bc000411641062000280218200028" - "021c10010c050b20002005ac3703c00141bc8dc000413c4101200041c0016a220141081001200042003703d8012000" - "42003703d001200042003703c801200042003703c001410120014120101e22014100480d020c030b20002001ac3703" - "c001419090c000412e4101200041c0016a4108100141ef7c21030c050b20002002ac3703c001419a8bc000412b4101" - "200041c0016a410810010c020b20002001ac37035041f88dc00041c1004101200041d0006a410810010b2000410036" - "0039200041013a00382000410036003c4101200041386a200041c0016a101f2201410048044020002001ac37035041" - "b98ec00041354101200041d0006a410810010b410110202201410048044020002001ac37035041ee8ec00041324101" - "200041d0006a410810010b4101200041386a10212201410048044020002001ac37035041a08fc00041394101200041" - "d0006a410810010b41d98fc000413741074101410010010c010b20004100360039200041013a00382000410036003c" - "200042003703d801200042003703d001200042003703c801200042003703c00102402005200041386a200041c0016a" - "2201101f220241004e044020002002ad37035041c58bc000411b4101200041d0006a41081001200041106a20012002" - "101a41e08bc000411441062000280210200028021410010c010b20002002ac37035041f48bc00041314101200041d0" - "006a410810010b200020051020ac37035041a58cc00041234101200041d0006a22014108100102402005200041386a" - "1021220241004e044020002002ad37035041c88cc000411b41012001410810010c010b20002002ac37035041e38cc0" - "0041354101200041d0006a410810010b41988dc000412441074101410010010b41be90c000412f4107410141001001" - "200041c0016a22011018200041386a2204200110192000420037036820004200370360200042003703582000420037" - "0350024002402004200041d0006a2202101d2201412046044041ed90c000410f410620024120100120004200370398" - "012000420037039001200042003703880120004200370380010240200441142004411441fc90c00041092000418001" - "6a22014120100d220241004a0440200041086a20012002101a418491c000411241062000280208200028020c10010c" - "010b20002002ac3703c001419691c000413c4101200041c0016a410810010b200042003703b801200042003703b001" - "200042003703a801200042003703a00120004180808cc07e360270200041386a22044114200041f0006a4104200041" - "a0016a22024120100e22014120470d0141d291c000410e4106200241201001200042003703d801200042003703d001" - "200042003703c801200042003703c001200041808080d00236027420044114200041f4006a4104200041c0016a4120" - "100f2201412047044020002001ac370378419292c000411c4101200041f8006a4108100141887c21030c040b41e091" - "c000410e4106200041c0016a22044120100141ee91c00041244107410141001001418080c000412541074101410010" - "0120004200370398012000420037039001200042003703880120004200370380010240024041a580c0004117200041" - "80016a2202412010102201412046044041bc80c000410b410641a580c0004117100141c780c0004111410620024120" - "100120041018200041d0006a220620041019200042003703b801200042003703b001200042003703a8012000420037" - "03a00102404100200422036b410371220220036a220520034d0d0020020440200221010340200341003a0000200341" - "016a2103200141016b22010d000b0b200241016b4107490d000340200341003a0000200341076a41003a0000200341" - "066a41003a0000200341056a41003a0000200341046a41003a0000200341036a41003a0000200341026a41003a0000" - "200341016a41003a0000200341086a22032005470d000b0b200541800220026b2201417c716a220320054b04400340" - "20054100360200200541046a22052003490d000b0b024020032001410371220120036a22024f0d0020012205044003" - "40200341003a0000200341016a2103200541016b22050d000b0b200141016b4107490d000340200341003a00002003" - "41076a41003a0000200341066a41003a0000200341056a41003a0000200341046a41003a0000200341036a41003a00" - "00200341026a41003a0000200341016a41003a0000200341086a22032002470d000b0b20064114200041a0016a4120" - "20044180021011220141004c0d0120002001ad37033841d880c00041104101200041386a4108100120014181024f0d" - "0541e880c000410941062004200110010c020b20002001ac3703c00141e381c00041224101200041c0016a41081001" - "41a77b21030c050b20002001ac37033841f180c000412e4101200041386a410810010b419f81c0004112410641b181" - "c000410710012000422a3703384101210341b881c00041114101200041386a4108100141c981c000411a4107410141" - "001001418582c0004129410741014100100141ae82c000412810122201412847044020002001ac3703c001419b83c0" - "00411a4101200041c0016a4108100141c37a21030c040b41d682c0004127410641ae82c0004128100141fd82c00041" - "1e4107410141001001419e98c000412841074101410010010c030b20002001ac3703c00141ca92c000411d41012000" - "41c0016a41081001418b7c21030c020b20002001ac3703c00141ae92c000411c4101200041c0016a4108100141897c" - "21030c010b000b200041c0036a240020030b0c00200041142001412010140b0e002000418280182001200210160b0e" - "002000200141082002412010170b0a0020004183803c10130b0a0020002001410810150b0bd0180100418080c0000b" - "c6182d2d2d2043617465676f727920363a205574696c6974792046756e6374696f6e73202d2d2d48656c6c6f2c2058" - "52504c205741534d20776f726c6421496e70757420646174613a5348413531322068616c6620686173683a4e465420" - "64617461206c656e6774683a4e465420646174613a494e464f3a206765745f6e6674206661696c6564202865787065" - "63746564202d206e6f2073756368204e4654293a54657374207472616365206d6573736167657061796c6f61645465" - "7374206e756d626572207472616365535543434553533a205574696c6974792066756e6374696f6e734552524f523a" - "20636f6d707574655f7368613531325f68616c66206661696c65643a2d2d2d2043617465676f727920373a20446174" - "61205570646174652046756e6374696f6e73202d2d2d55706461746564206c656467657220656e7472792064617461" - "2066726f6d205741534d20746573745375636365737366756c6c792075706461746564206c656467657220656e7472" - "7920776974683a535543434553533a2044617461207570646174652066756e6374696f6e734552524f523a20757064" - "6174655f64617461206661696c65643a2d2d2d2043617465676f727920313a204c6564676572204865616465722046" - "756e6374696f6e73202d2d2d4c65646765722073657175656e6365206e756d6265723a506172656e74206c65646765" - "722074696d653a506172656e74206c656467657220686173683a535543434553533a204c6564676572206865616465" - "722066756e6374696f6e734552524f523a206765745f706172656e745f6c65646765725f686173682077726f6e6720" - "6c656e6774683a4552524f523a206765745f706172656e745f6c65646765725f74696d65206661696c65643a455252" - "4f523a206765745f6c65646765725f73716e206661696c65643a2d2d2d2043617465676f727920323a205472616e73" - "616374696f6e20446174612046756e6374696f6e73202d2d2d5472616e73616374696f6e204163636f756e743a5472" - "616e73616374696f6e20466565206c656e6774683a5472616e73616374696f6e20466565202873657269616c697a65" - "642058525020616d6f756e74293a5472616e73616374696f6e2053657175656e63653a4e6573746564206669656c64" - "206c656e6774683a4e6573746564206669656c643a494e464f3a206765745f74785f6e65737465645f6669656c6420" - "6e6f74206170706c696361626c653a5369676e657273206172726179206c656e6774683a4d656d6f73206172726179" - "206c656e6774683a4e6573746564206172726179206c656e6774683a494e464f3a206765745f74785f6e6573746564" - "5f61727261795f6c656e206e6f74206170706c696361626c653a535543434553533a205472616e73616374696f6e20" - "646174612066756e6374696f6e734552524f523a206765745f74785f6669656c642853657175656e6365292077726f" - "6e67206c656e6774683a4552524f523a206765745f74785f6669656c6428466565292077726f6e67206c656e677468" - "20286578706563746564203820627974657320666f7220585250293a4552524f523a206765745f74785f6669656c64" - "284163636f756e74292077726f6e67206c656e6774683a2d2d2d2043617465676f727920343a20416e79204c656467" - "6572204f626a6563742046756e6374696f6e73202d2d2d5375636365737366756c6c7920636163686564206f626a65" - "637420696e20736c6f743a436163686564206f626a6563742062616c616e6365206c656e677468202858525020616d" - "6f756e74293a436163686564206f626a6563742062616c616e6365202873657269616c697a65642058525020616d6f" - "756e74293a436163686564206f626a6563742062616c616e6365206c656e67746820286e6f6e2d58525020616d6f75" - "6e74293a436163686564206f626a6563742062616c616e63653a494e464f3a206765745f6c65646765725f6f626a5f" - "6669656c642842616c616e636529206661696c65643a436163686564206e6573746564206669656c64206c656e6774" - "683a436163686564206e6573746564206669656c643a494e464f3a206765745f6c65646765725f6f626a5f6e657374" - "65645f6669656c64206e6f74206170706c696361626c653a436163686564206f626a656374205369676e6572732061" - "72726179206c656e6774683a436163686564206e6573746564206172726179206c656e6774683a494e464f3a206765" - "745f6c65646765725f6f626a5f6e65737465645f61727261795f6c656e206e6f74206170706c696361626c653a5355" - "43434553533a20416e79206c6564676572206f626a6563742066756e6374696f6e73494e464f3a2063616368655f6c" - "65646765725f6f626a206661696c65642028657870656374656420776974682074657374206669787475726573293a" - "494e464f3a206765745f6c65646765725f6f626a5f6669656c64206661696c65642061732065787065637465642028" - "6e6f20636163686564206f626a656374293a494e464f3a206765745f6c65646765725f6f626a5f6e65737465645f66" - "69656c64206661696c65642061732065787065637465643a494e464f3a206765745f6c65646765725f6f626a5f6172" - "7261795f6c656e206661696c65642061732065787065637465643a494e464f3a206765745f6c65646765725f6f626a" - "5f6e65737465645f61727261795f6c656e206661696c65642061732065787065637465643a535543434553533a2041" - "6e79206c6564676572206f626a6563742066756e6374696f6e732028696e7465726661636520746573746564294552" - "524f523a206163636f756e74726f6f745f6964206661696c656420666f722063616368696e6720746573743a2d2d2d" - "2043617465676f727920353a204b65796c65742047656e65726174696f6e2046756e6374696f6e73202d2d2d416363" - "6f756e74206b65796c65743a546573745479706543726564656e7469616c206b65796c65743a494e464f3a20637265" - "64656e7469616c5f6b65796c6574206661696c656420286578706563746564202d20696e7465726661636520697373" - "7565293a457363726f77206b65796c65743a4f7261636c65206b65796c65743a535543434553533a204b65796c6574" - "2067656e65726174696f6e2066756e6374696f6e734552524f523a206f7261636c655f6b65796c6574206661696c65" - "643a4552524f523a20657363726f775f6b65796c6574206661696c65643a4552524f523a206163636f756e74726f6f" - "745f6964206661696c65643a2d2d2d2043617465676f727920333a2043757272656e74204c6564676572204f626a65" - "63742046756e6374696f6e73202d2d2d43757272656e74206f626a6563742062616c616e6365206c656e6774682028" - "58525020616d6f756e74293a43757272656e74206f626a6563742062616c616e6365202873657269616c697a656420" - "58525020616d6f756e74293a43757272656e74206f626a6563742062616c616e6365206c656e67746820286e6f6e2d" - "58525020616d6f756e74293a43757272656e74206f626a6563742062616c616e63653a494e464f3a206765745f6375" - "7272656e745f6c65646765725f6f626a5f6669656c642842616c616e636529206661696c656420286d617920626520" - "6578706563746564293a43757272656e74206c6564676572206f626a656374206163636f756e743a494e464f3a2067" - "65745f63757272656e745f6c65646765725f6f626a5f6669656c64284163636f756e7429206661696c65643a437572" - "72656e74206e6573746564206669656c64206c656e6774683a43757272656e74206e6573746564206669656c643a49" - "4e464f3a206765745f63757272656e745f6c65646765725f6f626a5f6e65737465645f6669656c64206e6f74206170" - "706c696361626c653a43757272656e74206f626a656374205369676e657273206172726179206c656e6774683a4375" - "7272656e74206e6573746564206172726179206c656e6774683a494e464f3a206765745f63757272656e745f6c6564" - "6765725f6f626a5f6e65737465645f61727261795f6c656e206e6f74206170706c696361626c653a53554343455353" - "3a2043757272656e74206c6564676572206f626a6563742066756e6374696f6e736572726f725f636f64653d3d3d3d" - "20484f53542046554e4354494f4e532054455354203d3d3d54657374696e6720323620686f73742066756e6374696f" - "6e73535543434553533a20416c6c20686f73742066756e6374696f6e2074657374732070617373656421004d097072" - "6f64756365727302086c616e6775616765010452757374000c70726f6365737365642d6279010572757374631d312e" - "39352e30202835393830373631366520323032362d30342d313429002c0f7461726765745f6665617475726573022b" - "0f6d757461626c652d676c6f62616c732b087369676e2d657874"; - -extern std::string const kDeepRecursionHex = - "0061736d010000000105016000017f030201000608017f0141c0843d0b0711010d657363726f775f66696e69736800" - "000a16011400230045044041010f0b230041016b240010000b"; - -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 = - "0061736d01000000015c0c60067f7f7f7f7f7f017f60027f7f017f60047f7f7f7f017f60037f7f7f017f60077f7f7f" - "7f7f7f7f017f60087f7f7f7f7f7f7f7f017f60057f7f7f7f7f017f60017f017f60057f7f7f7f7f0060047f7f7f7f00" - "60017f006000017f02d8093608686f73745f6c6962057472616365000808686f73745f6c69620a6c6467725f696e64" - "6578000108686f73745f6c696210706172656e745f6c6467725f74696d65000108686f73745f6c696210706172656e" - "745f6c6467725f68617368000108686f73745f6c696208626173655f666565000108686f73745f6c696211616d656e" - "646d656e745f656e61626c6564000108686f73745f6c69620874785f6669656c64000308686f73745f6c69620e6163" - "636f756e74726f6f745f6964000208686f73745f6c69620863616368655f6c65000308686f73745f6c69620d686f6d" - "655f6c655f6669656c64000308686f73745f6c6962086c655f6669656c64000208686f73745f6c69620874785f696e" - "6e6572000208686f73745f6c69620d686f6d655f6c655f696e6e6572000208686f73745f6c6962086c655f696e6e65" - "72000608686f73745f6c69620a74785f6172725f6c656e000708686f73745f6c69620f686f6d655f6c655f6172725f" - "6c656e000708686f73745f6c69620a6c655f6172725f6c656e000108686f73745f6c69621074785f696e6e65725f61" - "72725f6c656e000108686f73745f6c696215686f6d655f6c655f696e6e65725f6172725f6c656e000108686f73745f" - "6c6962106c655f696e6e65725f6172725f6c656e000308686f73745f6c6962087365745f64617461000108686f7374" - "5f6c69620b7368613531325f68616c66000208686f73745f6c696209636865636b5f736967000008686f73745f6c69" - "62076e66745f757269000008686f73745f6c69620a6e66745f697373756572000208686f73745f6c6962096e66745f" - "7461786f6e000208686f73745f6c6962096e66745f666c616773000108686f73745f6c69620c6e66745f786665725f" - "666565000108686f73745f6c69620a6e66745f73657269616c000208686f73745f6c696208636865636b5f69640000" - "08686f73745f6c69620f666c6f61745f66726f6d5f75696e74000608686f73745f6c69620c74727573746c696e655f" - "6964000508686f73745f6c696206616d6d5f6964000008686f73745f6c69620d63726564656e7469616c5f69640005" - "08686f73745f6c69620a6d70746f6b656e5f6964000008686f73745f6c696209666c6f61745f636d70000208686f73" - "745f6c696209666c6f61745f616464000408686f73745f6c696209666c6f61745f737562000408686f73745f6c6962" - "0a666c6f61745f6d756c74000408686f73745f6c696209666c6f61745f646976000408686f73745f6c696209666c6f" - "61745f706f77000008686f73745f6c696209657363726f775f6964000008686f73745f6c69620f6d70745f69737375" - "616e63655f6964000008686f73745f6c69620c6e66745f6f666665725f6964000008686f73745f6c6962086f666665" - "725f6964000008686f73745f6c6962096f7261636c655f6964000008686f73745f6c69620a7061796368616e5f6964" - "000508686f73745f6c6962167065726d697373696f6e65645f646f6d61696e5f6964000008686f73745f6c69620974" - "69636b65745f6964000008686f73745f6c6962087661756c745f6964000008686f73745f6c69620b64656c65676174" - "655f6964000008686f73745f6c6962126465706f7369745f707265617574685f6964000008686f73745f6c69620664" - "69645f6964000208686f73745f6c69620a7369676e6572735f69640002030403090a0b05030100110619037f014180" - "80c0000b7f0041c698c0000b7f0041d098c0000b073504066d656d6f727902000d657363726f775f66696e69736800" - "380a5f5f646174615f656e6403010b5f5f686561705f6261736503020aa22e037201017f230041106b220424000240" - "02402000200147044020022003410741014100100020004100480d0120042000ad3703080c020b20042000ac370308" - "200220034101200441086a41081000200441106a24000f0b20042000ac3703080b418080c000410b4101200441086a" - "41081000000b2801017f230041106b2201240020012000ac37030841aa91c000410b4101200141086a41081000000b" - "832d02087f017e230041a0026b2200240041b591c0004123410741014100100020004100360260200041e0006a2201" - "41041001410441888ec000410a103620004100360260200141041002410441a683c000411010362000420037037820" - "0042003703702000420037036820004200370360200141201003412041a185c0004110103620004100360260200141" - "041004410441d888c000410810362000428182848890a0c080013703202000428182848890a0c08001370318200042" - "8182848890a0c080013703102000428182848890a0c0800137030841d891c000410e1005410141e691c00041111036" - "200041086a41201005410141e691c00041111036200041003602702000420037036820004200370360024002404181" - "802020014114100622014100480d00200141144b0440417321010c010b20014114460d0141808080807821010b2001" - "1037000b2000200029006c3700fd01200020002900673703f801200020002d00623a002e200020002f01603b012c20" - "00200028006336002f200020002903f801370033200020002900fd0137003820004200370378200042003703702000" - "42003703682000420037036002402000412c6a4114200041e0006a4120100722014120470440200141004e0d012001" - "1037000b200020002d00623a0042200020002f01603b01402000200029006f22083703800220002000280063360043" - "200020002900673700472000200837004f20002000290077370057200020002d007f3a005f200041406b4120410010" - "08410141f791c0004108103620004100360270200042003703682000420037036041818020200041e0006a22024114" - "1009411441a68fc000410d103620004100360270200042003703682000420037036041014181802020024114100a41" - "1441bf8cc0004108103602404100200041e4006a22046b410371220320046a220120044d0d00200304402003210503" - "40200441003a0000200441016a2104200541016b22050d000b0b200341016b4107490d000340200441003a00002004" - "41076a41003a0000200441066a41003a0000200441056a41003a0000200441046a41003a0000200441036a41003a00" - "00200441026a41003a0000200441016a41003a0000200441086a22042001470d000b0b2001413c20036b2203417c71" - "6a220420014b0440034020014100360200200141046a22012004490d000b0b024020042003410371220320046a2205" - "4f0d002003220104400340200441003a0000200441016a2104200141016b22010d000b0b200341016b4107490d0003" - "40200441003a0000200441076a41003a0000200441066a41003a0000200441056a41003a0000200441046a41003a00" - "00200441036a41003a0000200441026a41003a0000200441016a41003a0000200441086a22042005470d000b0b2000" - "41043602a00120004181802036026020004100360288022000420037038002200042003703f80120024104200041f8" - "016a22014114100b4114418388c0004108103620004100360288022000420037038002200042003703f80120022000" - "2802a00120014114100c411441e085c000410d103620004100360288022000420037038002200042003703f8014101" - "200220002802a00120014114100d4114418b86c000410810364189803c100e412041ff91c000410a10364189803c10" - "0f4120418992c000410f103641014189803c10104120419892c000410a1036200220002802a0011011412041a292c0" - "0041101036200220002802a0011012412041b292c000411510364101200220002802a0011013412041c792c0004110" - "10362000412c6a220341141014411441d792c000410810362000420037039002200042003703880220004200370380" - "02200042003703f801200220002802a001200141201015412041db82c000410b103641df92c000410c41eb92c00041" - "0b41f692c000410e10164101418493c00041091036200020002903203703c001200020002903183703b80120002000" - "2903103703b001200020002903083703a801200041003b0188022000420037038002200042003703f8012003411420" - "0041a8016a220541202001411210174112418c84c00041071036200041003602880220004200370380022000420037" - "03f801200541202001411410184114419386c000410a1036200041003602f80120054120200141041019410441c48a" - "c0004109103620054120101a4108418d93c0004109103620054120101b410a419693c000410c1036200041003602f8" - "012005412020014104101c410441818fc000410a103641a293c000410d410420034114100041a293c000410d410541" - "af93c0004108100041a293c000410d410541b793c00041081000417f41041003417141bf93c0004118103620004100" - "3602f8012001417f1003417141e686c00041181036200041003a00fa01200041003b01f801200141031003417d41f8" - "80c000411e1036200041003602f8012001418094ebdc0310034173419790c000411d10364102100e416f41d793c000" - "41191036417f20002802a0011011417141f093c000411810362002417f10114171418894c000411810362002418108" - "1011417441a094c00041191036200041e094ebdc036a220420002802a0011011417341b994c0004118103620004200" - "3703900220004200370388022000420037038002200042003703f801200341142004410820014120101d417341e283" - "c00041141036200042003703900220004200370388022000420037038002200042003703f801200341142003411420" - "014120101d417141eb84c00041161036200042003703900220004200370388022000420037038002200042003703f8" - "0120044108200141204100101e417341ea8ec000411710362000420037039002200042003703880220004200370380" - "02200042003703f801200220002802a001200141204100101e4171418185c00041201036200420002802a001410110" - "08417341d194c00041101036200220002802a00141011008417141e194c00041121036200042003703900220004200" - "370388022000420037038002200042003703f801200420002802a0012001412010074173418b8bc000411610362000" - "42003703900220004200370388022000420037038002200042003703f801200220002802a001200141201007417141" - "b683c00041181036200042003703900220004200370388022000420037038002200042003703f80120034114200341" - "14200420002802a00120014120101f417341c78cc000411d1036200042003703900220004200370388022000420037" - "038002200042003703f8012003411420034114200220002802a00120014120101f417141e489c000411f1036200042" - "003703900220004200370388022000420037038002200042003703f80141b298c0004114200420002802a001200141" - "201020417341a688c00041151036200042003703900220004200370388022000420037038002200042003703f80141" - "b298c0004114200220002802a001200141201020417141c787c000411b103620004200370390022000420037038802" - "2000420037038002200042003703f80141b298c000411441f394c0004114200141201020417141bb85c00041251036" - "200042003703900220004200370388022000420037038002200042003703f801418795c000412841b298c000411420" - "0141201020417141c98bc000412110362000200028013c3602dc01200020002901343702d4012000200029012c3702" - "cc01200041808080083602c801200041003b01f801200041c8016a2207411841b298c0004114200141021020417141" - "b185c000410a10362000422a3703e001200420002802a0014101200041e0016a41081000200041003b01f801410220" - "0141021006416f41af80c00041171036200041003b01f8014102200141021009416f419787c000411c103620004100" - "3b01f8014101410220014102100a416f41e682c000411710364102100e416f41d793c000411910364102100f416f41" - "af95c000411e1036410141021010416f41cd95c0004119103641d891c0004181081005417441e695c000411f103641" - "d891c00041c10010054174418596c000411a1036200041003b01f801200241810820014102100b417441f683c00041" - "161036200041003b01f801200241810820014102100c4174418b88c000411b1036200041003b01f801410120024181" - "0820014102100d4174419384c00041161036200241810810114174419f96c000411e103620024181081012417441bd" - "96c00041231036410120024181081013417441e096c000411e103620024181081014417441fe96c0004116103641a2" - "93c00041810841eb92c000410b41f692c000410e10164174418493c0004109103641a293c000410d41eb92c0004181" - "0841f692c000410e10164174418493c0004109103641a293c000410d41eb92c000410b41f692c00041810810164174" - "418493c00041091036200041003b01f8012002418108200141021015417441fe86c00041191036200041003b01f801" - "41b298c00041810841b298c0004114200141021020417441b58bc00041141036200041003b01f80120034114200341" - "142002418108200141021021417441c082c000411b1036200041003b01f80120074181082003411420014102102241" - "7441da80c000411e103641a293c000410d4107200420002802a0011000200042d487b6f4c7d4b1c0003700ec0141a2" - "93c000410d4103200041ec95ebdc036a22054108100041a293c000410d4105200420002802a0011000200541082000" - "41ec016a2204410810234173419497c0004114103620044108200541081023417341a897c00041141036200041003b" - "01f80120054108200441082001410241001024417341ac82c00041141036200041003b01f801200441082005410820" - "01410241001024417341ce83c00041141036200041003b01f80120054108200441082001410241001025417341a18b" - "c00041141036200041003b01f80120044108200541082001410241001025417341c680c00041141036200041003b01" - "f80120054108200441082001410241001026417341cd8ac00041151036200041003b01f80120044108200541082001" - "410241001026417341c781c00041151036200041003b01f80120054108200441082001410241001027417341b387c0" - "0041141036200041003b01f801200441082005410820014102410010274173419d86c00041141036200041003b01f8" - "0120054108410320014102410010284173419681c00041131036200042003703900220004200370388022000420037" - "038002200042003703f8012003411420034114200141201029417141ea8bc000411b10362000420037039002200042" - "00370388022000420037038002200042003703f801200341142003411420014120102a417141e287c0004121103620" - "0042003703900220004200370388022000420037038002200042003703f801200341142003411420014120102b4171" - "41a981c000411e1036200042003703900220004200370388022000420037038002200042003703f801200341142003" - "411420014120102c417141b48ec000411a103620004200370390022000420037038802200042003703800220004200" - "3703f801200341142003411420014120102d4171418b8fc000411b1036200042003703900220004200370388022000" - "420037038002200042003703f80120034114200341142003411420014120102e417141ce8ec000411c103620004200" - "3703900220004200370388022000420037038002200042003703f801200341142003411420014120102f417141e08d" - "c00041281036200042003703900220004200370388022000420037038002200042003703f801200341142003411420" - "0141201030417141b186c000411b1036200042003703900220004200370388022000420037038002200042003703f8" - "012003411420034114200141201031417141b490c000411a1036200220002802a00141001008417141bc97c000411b" - "1036200041003b01f80120034114200220002802a001200141021017417141cc86c000411a1036200041003b01f801" - "200220002802a001200141021018417141858cc000411d1036200041003b01f801200220002802a001200141021019" - "417141ce90c000411c1036200220002802a001101a417141d797c000411c1036200220002802a001101b417141f397" - "c000411f1036200041003602f801200220002802a00120014104101c417141a28cc000411d1036200041003b01f801" - "200220002802a0012001410210074171418b80c00041241036200041808080083602f401200041003b01f801200220" - "002802a001200041f4016a2205410420014102101d4171419f8dc000411e1036200041003b01f801200220002802a0" - "0122062003411420022006200141021021417141d28fc00041241036200041003b01f80120034114200220002802a0" - "01220620022006200141021021417141dc81c00041241036200041003b01f801200220002802a00120034114200141" - "021032417141838ac00041221036200041003b01f80120034114200220002802a001200141021032417141a984c000" - "41221036200041003b01f801200220002802a00120034114200141021033417141fd82c00041291036200041003b01" - "f80120034114200220002802a001200141021033417141e28ac00041291036200041003b01f801200220002802a001" - "2001410210344171418089c000411c1036200041003b01f801200220002802a00120054104200141021029417141b3" - "8fc000411f1036200041003b01f801200220002802a0012003411441f394c000411420014102101f417141c189c000" - "41231036200041003b01f80120034114200220002802a00141f394c000411420014102101f417141bd8dc000412310" - "36200041003b01f801200220002802a0012005410420014102102a4171419c89c00041251036200041003b01f80120" - "074118200220002802a001200141021022417141cb84c00041201036200041003b01f801200220002802a001200541" - "0420014102102b417141928ec00041221036200041003b01f801200220002802a0012005410420014102102c417141" - "ed85c000411e1036200041003b01f801200220002802a0012005410420014102102d417141a58ac000411f10362000" - "41003b01f801200220002802a001200341142005410420014102102e417141f68fc00041211036200041003b01f801" - "20034114200220002802a0012005410420014102102e417141ea90c00041211036200041003b01f801200220002802" - "a0012005410420014102102f4171418082c000412c1036200041003b01f801200220002802a0012001410210354171" - "41e088c00041201036200041003b01f801200220002802a001200541042001410210304171418b91c000411f103620" - "0041003b01f801200220002802a00120054104200141021031417141818dc000411e1036200041003b01f801200220" - "002802a001419298c0004120200141021017417141e48cc000411d103641a293c000410d4104200220002802a00110" - "0041a2a7abdd03410d4107419298c0004120100041a2a7abdd03410d410320044108100041a2a7abdd03410d410420" - "034114100041a2a7abdd03410d410541b793c00041081000200220002802a001410720024181081000200042013703" - "f8012002418108410120014108100041a293c000418108410320044108100041a293c0004181084104200341141000" - "41a293c000418108410541b793c0004108100041a293c000410d4105200220002802a0011000200041003b019e0220" - "0220002802a001200341142000419e026a41021022417141bb88c000411d103641a293c000410d41e3002002200028" - "02a0011000410141004104200341141000200041a0026a240041010f0b000b0b9d180200418080c0000b8715544553" - "54204641494c45446163636f756e74726f6f745f69645f77726f6e675f73697a655f6163636f756e745f696474785f" - "6669656c645f696e76616c69645f736669656c64666c6f61745f7375625f6f6f625f736c696365326d70746f6b656e" - "5f69645f746f6f5f6269675f736c6963655f6d70746964706172656e745f6c6467725f686173685f6275665f746f6f" - "5f736d616c6c666c6f61745f706f775f6f6f625f736c6963656e66745f6f666665725f69645f77726f6e675f73697a" - "655f75696e743332666c6f61745f6d756c745f6f6f625f736c6963653263726564656e7469616c5f69645f77726f6e" - "675f73697a655f6163636f756e745f6964327065726d697373696f6e65645f646f6d61696e5f69645f77726f6e675f" - "73697a655f6163636f756e745f6964666c6f61745f6164645f6f6f625f736c6963653163726564656e7469616c5f69" - "645f746f6f5f6269675f736c6963657368613531325f68616c666c655f6669656c645f696e76616c69645f73666965" - "6c646465706f7369745f707265617574685f69645f77726f6e675f73697a655f6163636f756e745f69643170617265" - "6e745f6c6467725f74696d656163636f756e74726f6f745f69645f77726f6e675f6c656e666c6f61745f6164645f6f" - "6f625f736c69636532636865636b5f69645f6f6f625f6c656e5f75333274785f696e6e65725f746f6f5f6269675f73" - "6c6963656e66745f7572696c655f696e6e65725f746f6f5f6269675f736c69636564656c65676174655f69645f7772" - "6f6e675f73697a655f6163636f756e745f6964326d70746f6b656e5f69645f77726f6e675f73697a655f6163636f75" - "6e745f6964636865636b5f69645f77726f6e675f6c656e5f753332666c6f61745f66726f6d5f75696e745f77726f6e" - "675f6c656e5f75696e743634706172656e745f6c6467725f68617368616d6d5f69645f6d7074616d6d5f69645f6c65" - "6e5f77726f6e675f6e6f6e5f7872705f63757272656e63795f6c656e686f6d655f6c655f696e6e65726f666665725f" - "69645f77726f6e675f73697a655f6163636f756e745f69646c655f696e6e65726e66745f697373756572666c6f6174" - "5f6469765f6f6f625f736c696365327469636b65745f69645f77726f6e675f73697a655f75696e7433326e66745f75" - "72695f77726f6e675f73697a655f75696e74323536706172656e745f6c6467725f686173685f6e65675f6c656e7368" - "613531325f68616c665f746f6f5f6269675f736c696365686f6d655f6c655f6669656c645f696e76616c69645f7366" - "69656c64666c6f61745f6469765f6f6f625f736c69636531616d6d5f69645f6c656e5f77726f6e675f6c656e5f6173" - "736574326d70745f69737375616e63655f69645f77726f6e675f73697a655f75696e74333274785f696e6e6572686f" - "6d655f6c655f696e6e65725f746f6f5f6269675f736c696365616d6d5f69645f6c656e5f6f6f625f6173736574326d" - "70746f6b656e5f69645f6d707469645f77726f6e675f6c656e677468626173655f6665657369676e6572735f69645f" - "77726f6e675f73697a655f6163636f756e745f69646469645f69645f77726f6e675f73697a655f6163636f756e745f" - "69646d70745f69737375616e63655f69645f77726f6e675f73697a655f6163636f756e745f696474727573746c696e" - "655f69645f77726f6e675f73697a655f6163636f756e745f69643174727573746c696e655f69645f77726f6e675f6c" - "656e5f63757272656e637964656c65676174655f69645f77726f6e675f73697a655f6163636f756e745f6964316f72" - "61636c655f69645f77726f6e675f73697a655f6163636f756e745f69646e66745f7461786f6e666c6f61745f6d756c" - "745f6f6f625f736c696365316465706f7369745f707265617574685f69645f77726f6e675f73697a655f6163636f75" - "6e745f6964326163636f756e74726f6f745f69645f6c656e5f6f6f62666c6f61745f7375625f6f6f625f736c696365" - "31616d6d5f69645f746f6f5f6269675f736c696365616d6d5f69645f6c656e5f77726f6e675f7872705f6375727265" - "6e63795f6c656e657363726f775f69645f77726f6e675f73697a655f75696e7433326e66745f6973737565725f7772" - "6f6e675f73697a655f75696e743235366e66745f73657269616c5f77726f6e675f73697a655f75696e743235366c65" - "5f6669656c6474727573746c696e655f69645f6c656e5f6f6f625f63757272656e63796e66745f7572695f77726f6e" - "675f73697a655f6163636f756e745f69647661756c745f69645f77726f6e675f73697a655f6163636f756e745f6964" - "636865636b5f69645f77726f6e675f73697a655f6163636f756e745f696474727573746c696e655f69645f77726f6e" - "675f73697a655f6163636f756e745f6964327065726d697373696f6e65645f646f6d61696e5f69645f77726f6e675f" - "73697a655f75696e7433326c6467725f696e6465786e66745f6f666665725f69645f77726f6e675f73697a655f6163" - "636f756e745f69646f666665725f69645f77726f6e675f73697a655f75696e7433327061796368616e5f69645f7772" - "6f6e675f73697a655f75696e743332666c6f61745f66726f6d5f75696e745f6c656e5f6f6f626e66745f7365726961" - "6c6f7261636c655f69645f77726f6e675f73697a655f75696e743332686f6d655f6c655f6669656c64657363726f77" - "5f69645f77726f6e675f73697a655f6163636f756e745f696463726564656e7469616c5f69645f77726f6e675f7369" - "7a655f6163636f756e745f6964317061796368616e5f69645f77726f6e675f73697a655f6163636f756e745f696431" - "706172656e745f6c6467725f686173685f6c656e5f746f6f5f6c6f6e677661756c745f69645f77726f6e675f73697a" - "655f75696e7433326e66745f7461786f6e5f77726f6e675f73697a655f75696e743235367061796368616e5f69645f" - "77726f6e675f73697a655f6163636f756e745f6964327469636b65745f69645f77726f6e675f73697a655f6163636f" - "756e745f69646572726f725f636f64653d2424242424205354415254494e47205741534d20455845435554494f4e20" - "2424242424746573745f616d656e646d656e74616d656e646d656e745f656e61626c656463616368655f6c6574785f" - "6172725f6c656e686f6d655f6c655f6172725f6c656e6c655f6172725f6c656e74785f696e6e65725f6172725f6c65" - "6e686f6d655f6c655f696e6e65725f6172725f6c656e6c655f696e6e65725f6172725f6c656e7365745f6461746174" - "657374206d65737361676574657374207075626b657974657374207369676e6174757265636865636b5f7369676e66" - "745f666c6167736e66745f786665725f66656574657374696e67207472616365400000000000005f40000000000000" - "00706172656e745f6c6467725f686173685f6e65675f70747274785f6172725f6c656e5f696e76616c69645f736669" - "656c6474785f696e6e65725f6172725f6c656e5f6e65675f70747274785f696e6e65725f6172725f6c656e5f6e6567" - "5f6c656e74785f696e6e65725f6172725f6c656e5f746f6f5f6c6f6e6774785f696e6e65725f6172725f6c656e5f70" - "74725f6f6f6263616368655f6c655f7074725f6f6f6263616368655f6c655f77726f6e675f6c656e55534430303030" - "303030303030303030303030300041af95c0000b8303686f6d655f6c655f6172725f6c656e5f696e76616c69645f73" - "6669656c646c655f6172725f6c656e5f696e76616c69645f736669656c64616d656e646d656e745f656e61626c6564" - "5f746f6f5f6269675f736c696365616d656e646d656e745f656e61626c65645f746f6f5f6c6f6e6774785f696e6e65" - "725f6172725f6c656e5f746f6f5f6269675f736c696365686f6d655f6c655f696e6e65725f6172725f6c656e5f746f" - "6f5f6269675f736c6963656c655f696e6e65725f6172725f6c656e5f746f6f5f6269675f736c6963657365745f6461" - "74615f746f6f5f6269675f736c696365666c6f61745f636d705f6f6f625f736c69636531666c6f61745f636d705f6f" - "6f625f736c6963653263616368655f6c655f77726f6e675f73697a655f75696e743235366e66745f666c6167735f77" - "726f6e675f73697a655f75696e743235366e66745f786665725f6665655f77726f6e675f73697a655f75696e743235" - "363030303030303030303030303030303030303030303030303030303030303031004d0970726f6475636572730208" - "6c616e6775616765010452757374000c70726f6365737365642d6279010572757374631d312e39352e302028353938" - "30373631366520323032362d30342d313429002c0f7461726765745f6665617475726573022b0f6d757461626c652d" - "676c6f62616c732b087369676e2d657874"; - -extern std::string const kFloatTestsWasmHex = - "0061736d0100000001490960057f7f7f7f7f017f60077f7f7f7f7f7f7f017f60067f7f7f7f7f7f017f60047e7f7f7f" - "017f60057e7f7f7f7f017f60047f7f7f7f017f60037f7f7e017f60037f7f7f006000017f02ea021008686f73745f6c" - "6962057472616365000008686f73745f6c69620e666c6f61745f66726f6d5f696e74000308686f73745f6c69620f66" - "6c6f61745f66726f6d5f75696e74000003656e7613666c6f61745f66726f6d5f6d616e745f657870000408686f7374" - "5f6c696209666c6f61745f636d70000508686f73745f6c696209666c6f61745f616464000108686f73745f6c696209" - "666c6f61745f737562000108686f73745f6c69620a666c6f61745f6d756c74000108686f73745f6c696209666c6f61" - "745f646976000108686f73745f6c696209666c6f61745f706f77000208686f73745f6c69620974726163655f6e756d" - "000608686f73745f6c69620a666c6f61745f726f6f74000203656e760c666c6f61745f746f5f696e74000003656e76" - "11666c6f61745f746f5f6d616e745f657870000203656e7613666c6f61745f66726f6d5f7374616d6f756e74000003" - "656e7613666c6f61745f66726f6d5f73746e756d6265720000030302070805030100110619037f01418080c0000b7f" - "00418599c0000b7f00419099c0000b073504066d656d6f727902000d657363726f775f66696e69736800110a5f5f64" - "6174615f656e6403010b5f5f686561705f6261736503020aec20021f002000200141014100410010001a418080c000" - "41022002410c410110001a0bc920020c7f017e230041f0006b2200240041ee8ac000411d41014100410010001a2000" - "4100360268200042003703600240428ce000200041e0006a2202410c410010012201410c460440418b8bc000411720" - "02101041a28bc000411e2002410c410110001a0c010b41c08bc000411e41014100410010001a0b2000428ce0003703" - "500240200041d0006a4108200041e0006a2202410c41001002410c4604402001410c46210741de8bc0004117200210" - "100c010b41f58bc000411e41014100410010001a0b024042fb004102200041e0006a2201410c41001003410c460440" - "41938cc0004121200110100c010b41b48cc000412841014100410010001a410021070b41dc8cc000411541be80c000" - "101041f18cc0004116418881c0001010418280c000411741014100410010001a200041003602682000420037036002" - "404201200041e0006a2202410c410010012201410c460440419980c000410f200210100c010b41a880c00041164101" - "4100410010001a0b027f200041e0006a410c41be80c000410c100445044041ca80c000411b41014100410010001a20" - "01410c460c010b41e580c000412341014100410010001a41000b21080240200041e0006a410c418881c000410c1004" - "4101460440419481c000412341014100410010001a0c010b4100210841b781c000412c41014100410010001a0b0240" - "418881c000410c200041e0006a410c1004410246044041e381c000412341014100410010001a0c010b410021084186" - "82c000412c41014100410010001a0b419c93c000412041014100410010001a200041c680c000280000360258200041" - "be80c000290000370350410921030340200041d0006a2201410c41be80c000410c2001410c410010051a200341016b" - "22030d000b2000410036026820004200370360420a200041e0006a410c41001001410c46220945044041bc93c00041" - "1741014100410010001a0b0240200041e0006a410c200041d0006a410c100445044041d393c0004114410141004100" - "10001a0c010b4100210941e793c000411641014100410010001a0b410b21030340200041d0006a2201410c41be80c0" - "00410c2001410c410010061a200341016b22030d000b02402001410c418881c000410c100445044041fd93c0004119" - "41014100410010001a0c010b41002109419694c000411b41014100410010001a0b41878dc000411f41014100410010" - "001a2000410036021020004200370308420a200041086a410c410010011a200041c680c000280000360220200041be" - "80c000290000370318410621030340200041186a2201410c200041086a410c2001410c410010071a200341016b2203" - "0d000b200041003602582000420037035042c0843d200041d0006a2202410c410010011a02402002410c2001410c10" - "04220145044041a68dc000411941014100410010001a0c010b41bf8dc000411b41014100410010001a0b200145210a" - "410721030340200041186a2201410c200041086a410c2001410c410010081a200341016b22030d000b200041003602" - "68200042003703604201417f200041e0006a2202410c410010031a02402001410c2002410c100445044041da8dc000" - "411741014100410010001a0c010b41f18dc000411941014100410010001a4100210a0b41b282c00041174101410041" - "0010001a200041003602202000420037031841be80c000410c4103200041186a2202410c410010091a41c982c00041" - "1220021010418881c000410c41062002410c410010091a41db82c00041182002101020004100360258200042003703" - "504209200041d0006a2201410c410010011a2001410c41022002410c410010091a41f382c000411420021010200141" - "0c41002002410c410010091a418783c00041172002101020004100360268200042003703604200200041e0006a2203" - "410c410010011a2003410c41022002410c410010091a419e83c00041142002101041b283c00041382003410c410020" - "02410c41001009ac100a1a41ea83c000411841014100410010001a200041003602202000420037031842092002410c" - "410010011a20004100360258200042003703502002410c41022001410c4100100b1a418284c0004112200110102002" - "410c41032001410c4100100b1a419484c000411220011010200041003602682000420037036042c0843d2003410c41" - "0010011a2003410c41032001410c4100100b1a41a684c0004118200110102003410c41062001410c4100100b1a41be" - "84c000411c2001101041da84c000411a41014100410010001a20004100360258200042003703502000410036026820" - "004200370360420a2003410c410010011a41be80c000410c2003410c2001410c410010081a41f484c0004119200110" - "1041be80c000410c2001410c2001410c410010081a418d85c000410f2001101002402003410c2001410c1004220b45" - "0440419c85c000411441014100410010001a0c010b41b085c000411641014100410010001a0b4100210141c685c000" - "411a41014100410010001a20004200370308024041be80c000410c200041086a41084100100c220241084604402000" - "290308220c42015104404101210141e085c000411741014100410010001a0c020b41f785c000411941014100410010" - "001a419086c0004108200c100a1a0c010b419886c000412441014100410010001a41bc86c000410f2002ac100a1a0b" - "410021030240418881c000410c200041086a41084100100c220241084604402000290308220c427f51044041cb86c0" - "00411841014100410010001a200121030c020b41e386c000411a41014100410010001a419086c0004108200c100a1a" - "0c010b41fd86c000412541014100410010001a41bc86c000410f2002ac100a1a0b4100210120004100360220200042" - "0037031842ffffffffffffffffff00200041186a2202410c410010011a02402002410c200041086a41084100100c22" - "0241084604402000290308220c42ffffffffffffffffff0051044041a287c000411e41014100410010001a20032101" - "0c020b41c087c000412041014100410010001a41e087c000410d42ffffffffffffffffff00100a1a419086c0004108" - "200c100a1a0c010b41ed87c000412b41014100410010001a41bc86c000410f2002ac100a1a0b410021022000410036" - "0258200042003703504200200041d0006a2203410c410010011a02402003410c200041086a41084100100c22034108" - "4604402000290308220c500440419888c000411741014100410010001a200121020c020b41af88c000411941014100" - "410010001a419086c0004108200c100a1a0c010b41c888c000412441014100410010001a41bc86c000410f2003ac10" - "0a1a0b4100210320004100360268200042003703604201417f200041e0006a2201410c410010031a02402001410c20" - "0041086a41084100100c220141084604402000290308220c50044041ec88c000412541014100410010001a20022103" - "0c020b419189c000412741014100410010001a419086c0004108200c100a1a0c010b41b889c0004132410141004100" - "10001a41bc86c000410f2001ac100a1a0b0240200041e0006a410c200041086a41084101100c220141084604402000" - "290308220c50044041ea89c000412741014100410010001a0c020b4100210341918ac000412941014100410010001a" - "419086c0004108200c100a1a0c010b4100210341ba8ac000413441014100410010001a41bc86c000410f2001ac100a" - "1a0b41002101418a8ec000411f41014100410010001a2000420037032820004100360234024041be80c000410c2000" - "41286a4108200041346a4104100d2202410c46044020002802342202416e462000290328220c42808090bbbad6adf0" - "0d517145044041c58ec000411e41014100410010001a41e38ec000412f200c100a1a41928fc000411f2002ac100a1a" - "0c020b4101210141a98ec000411c41014100410010001a0c010b41b18fc000412941014100410010001a41bc86c000" - "410f2002ac100a1a0b2000420037033841002102200041003602440240418881c000410c200041386a4108200041c4" - "006a4104100d2204410c46044020002802442204416e462000290338220c428080f0c4c5a9d28f72517145044041f7" - "8fc000411f41014100410010001a419690c0004130200c100a1a41928fc000411f2004ac100a1a0c020b41da8fc000" - "411d41014100410010001a200121020c010b41c690c000412a41014100410010001a41bc86c000410f2004ac100a1a" - "0b410021012000410036025820004200370350420a200041d0006a2204410c410010011a2000420037030820004100" - "36024802402004410c200041086a4108200041c8006a4104100d2204410c46044020002802482204416f4620002903" - "08220c42808090bbbad6adf00d5171450440418d91c000411f41014100410010001a41e38ec000412f200c100a1a41" - "ac91c000411f2004ac100a1a0c020b41f090c000411d41014100410010001a200221010c010b41cb91c000412a4101" - "4100410010001a41bc86c000410f2004ac100a1a0b4100210220004100360268200042003703604200200041e0006a" - "2204410c410010011a200042003703182000410036024c02402004410c200041186a4108200041cc006a4104100d22" - "04410c4604402000290318220c50200028024c22044180808080784671450440419192c000411e4101410041001000" - "1a41af92c000411d200c100a1a41cc92c00041272004ac100a1a0c020b41f591c000411c41014100410010001a2001" - "21020c010b41f392c000412941014100410010001a41bc86c000410f2004ac100a1a0b4100210141b194c000412141" - "014100410010001a200042c0808080d0a0fdf000370018200041003602682000420037036002400240200041186a41" - "08200041e0006a2205410c4100100e2204410c46044041d294c000412220051010200042003703502005410c200041" - "d0006a41084100100c22044108470d012000290350220c4280c2d72f5104404101210141f494c000411d4101410041" - "0010001a0c030b419195c000411f41014100410010001a41b095c000411c200c100a1a0c020b418096c000411f4101" - "4100410010001a419f96c00041102004ac100a1a0c010b41cc95c000413441014100410010001a41bc86c000410f20" - "04ac100a1a0b4100210441af96c000412141014100410010001a200041ffffff8f7f36005820004281eceedce494cc" - "f9c000370050200041003602682000420037036002400240200041d0006a410c200041e0006a2206410c4100100f22" - "05410c46044041d096c000411c20061010200042003703182006410c200041186a41084100100c22054108470d0120" - "00290318220c42fb005104404101210441ec96c000411b41014100410010001a0c030b418797c000411d4101410041" - "0010001a41a497c0004116200c100a1a0c020b41ec97c000411d41014100410010001a419f96c00041102005ac100a" - "1a0c010b41ba97c000413241014100410010001a41bc86c000410f2005ac100a1a0b41002105024041be80c000410c" - "200041e0006a2206410c4100100f410c460440418998c000411a200610102006410c41be80c000410c100445044041" - "a398c000412041014100410010001a200421050c020b41c398c000412241014100410010001a0c010b41e598c00041" - "2041014100410010001a0b200041f0006a2400200b452007200871200971200a71200371200271200171200571710b" - "0b8f190100418080c0000b851920200a24242420746573745f666c6f61745f636d70202424242020666c6f61742066" - "726f6d20313a2020666c6f61742066726f6d20313a206661696c65640de0b6b3a7640000ffffffee2020666c6f6174" - "2066726f6d2031203d3d20464c4f41545f4f4e452020666c6f61742066726f6d203120213d20464c4f41545f4f4e45" - "2c206661696c6564f21f494c589c0000ffffffee2020666c6f61742066726f6d2031203e20464c4f41545f4e454741" - "544956455f4f4e452020666c6f61742066726f6d203120213e20464c4f41545f4e454741544956455f4f4e452c2066" - "61696c65642020464c4f41545f4e454741544956455f4f4e45203c20666c6f61742066726f6d20312020464c4f4154" - "5f4e454741544956455f4f4e4520213c20666c6f61742066726f6d20312c206661696c65640a24242420746573745f" - "666c6f61745f706f77202424242020666c6f61742063756265206f6620313a2020666c6f61742036746820706f7765" - "72206f66202d313a2020666c6f617420737175617265206f6620393a2020666c6f61742030746820706f776572206f" - "6620393a2020666c6f617420737175617265206f6620303a2020666c6f61742030746820706f776572206f66203020" - "28657870656374696e6720494e56414c49445f504152414d53206572726f72293a0a24242420746573745f666c6f61" - "745f726f6f74202424242020666c6f61742073717274206f6620393a2020666c6f61742063627274206f6620393a20" - "20666c6f61742063627274206f6620313030303030303a2020666c6f61742036746820726f6f74206f662031303030" - "3030303a0a24242420746573745f666c6f61745f696e76657274202424242020696e76657274206120666c6f617420" - "66726f6d2031303a2020696e7665727420616761696e3a2020696e766572742074776963653a20676f6f642020696e" - "766572742074776963653a206661696c65640a24242420746573745f666c6f61745f746f5f696e7420242424202066" - "6c6f61745f746f5f696e742831293a20676f6f642020666c6f61745f746f5f696e742831293a206661696c65642020" - "2020676f743a2020666c6f61745f746f5f696e742831293a206661696c65642077697468206572726f722020202065" - "72726f7220636f64653a2020666c6f61745f746f5f696e74282d31293a20676f6f642020666c6f61745f746f5f696e" - "74282d31293a206661696c65642020666c6f61745f746f5f696e74282d31293a206661696c65642077697468206572" - "726f722020666c6f61745f746f5f696e74286936343a3a4d4158293a20676f6f642020666c6f61745f746f5f696e74" - "286936343a3a4d4158293a206661696c65642020202065787065637465643a2020666c6f61745f746f5f696e742869" - "36343a3a4d4158293a206661696c65642077697468206572726f722020666c6f61745f746f5f696e742830293a2067" - "6f6f642020666c6f61745f746f5f696e742830293a206661696c65642020666c6f61745f746f5f696e742830293a20" - "6661696c65642077697468206572726f722020666c6f61745f746f5f696e7428302e312c20746f5f6e656172657374" - "293a20676f6f642020666c6f61745f746f5f696e7428302e312c20746f5f6e656172657374293a206661696c656420" - "20666c6f61745f746f5f696e7428302e312c20746f5f6e656172657374293a206661696c6564207769746820657272" - "6f722020666c6f61745f746f5f696e7428302e312c20746f77617264735f7a65726f293a20676f6f642020666c6f61" - "745f746f5f696e7428302e312c20746f77617264735f7a65726f293a206661696c65642020666c6f61745f746f5f69" - "6e7428302e312c20746f77617264735f7a65726f293a206661696c65642077697468206572726f720a242424207465" - "73745f666c6f61745f66726f6d5f7761736d202424242020666c6f61742066726f6d206936342031323330303a2020" - "666c6f61742066726f6d20693634203132333030206173204845583a2020666c6f61742066726f6d20693634203132" - "3330303a206661696c65642020666c6f61742066726f6d207536342031323330303a2020666c6f61742066726f6d20" - "7536342031323330303a206661696c65642020666c6f61742066726f6d2065787020322c206d616e74697373612031" - "32333a2020666c6f61742066726f6d2065787020322c206d616e7469737361203132333a206661696c65642020666c" - "6f61742066726f6d20636f6e737420313a2020666c6f61742066726f6d20636f6e7374202d313a0a24242420746573" - "745f666c6f61745f6d756c745f6469766964652024242420207265706561746564206d756c7469706c793a20676f6f" - "6420207265706561746564206d756c7469706c793a206661696c656420207265706561746564206469766964653a20" - "676f6f6420207265706561746564206469766964653a206661696c65640a24242420746573745f666c6f61745f746f" - "5f6d616e745f657870202424242020666c6f61745f746f5f6d616e745f6578702831293a20676f6f642020666c6f61" - "745f746f5f6d616e745f6578702831293a206661696c6564202020206578706563746564206d616e74697373612031" - "3030303030303030303030303030303030302c20676f743a202020206578706563746564206578706f6e656e74202d" - "31382c20676f743a2020666c6f61745f746f5f6d616e745f6578702831293a206661696c6564207769746820657272" - "6f722020666c6f61745f746f5f6d616e745f657870282d31293a20676f6f642020666c6f61745f746f5f6d616e745f" - "657870282d31293a206661696c6564202020206578706563746564206d616e7469737361202d313030303030303030" - "303030303030303030302c20676f743a2020666c6f61745f746f5f6d616e745f657870282d31293a206661696c6564" - "2077697468206572726f722020666c6f61745f746f5f6d616e745f657870283130293a20676f6f642020666c6f6174" - "5f746f5f6d616e745f657870283130293a206661696c6564202020206578706563746564206578706f6e656e74202d" - "31372c20676f743a2020666c6f61745f746f5f6d616e745f657870283130293a206661696c65642077697468206572" - "726f722020666c6f61745f746f5f6d616e745f6578702830293a20676f6f642020666c6f61745f746f5f6d616e745f" - "6578702830293a206661696c6564202020206578706563746564206d616e746973736120302c20676f743a20202020" - "6578706563746564206578706f6e656e74202d323134373438333634382c20676f743a2020666c6f61745f746f5f6d" - "616e745f6578702830293a206661696c65642077697468206572726f720a24242420746573745f666c6f61745f6164" - "645f7375627472616374202424242020666c6f61742066726f6d2031303a206661696c656420207265706561746564" - "206164643a20676f6f6420207265706561746564206164643a206661696c6564202072657065617465642073756274" - "726163743a20676f6f64202072657065617465642073756274726163743a206661696c65640a24242420746573745f" - "666c6f61745f66726f6d5f7374616d6f756e74202424242020666c6f61742066726f6d2058525020616d6f756e7420" - "2831303020585250293a202058525020616d6f756e7420636f6e76657273696f6e3a20676f6f64202058525020616d" - "6f756e7420636f6e76657273696f6e3a206661696c6564202020206578706563746564203130303030303030302c20" - "676f743a202058525020616d6f756e7420636f6e76657273696f6e3a206661696c6564202d20666c6f61745f746f5f" - "696e74206572726f722020666c6f61742066726f6d2058525020616d6f756e743a206661696c656420202020726573" - "756c745f73697a653a0a24242420746573745f666c6f61745f66726f6d5f73746e756d626572202424242020666c6f" - "61742066726f6d2053544e756d6265722028313233293a202053544e756d62657220636f6e76657273696f6e3a2067" - "6f6f64202053544e756d62657220636f6e76657273696f6e3a206661696c6564202020206578706563746564203132" - "332c20676f743a202053544e756d62657220636f6e76657273696f6e3a206661696c6564202d20666c6f61745f746f" - "5f696e74206572726f722020666c6f61742066726f6d2053544e756d6265723a206661696c65642020666c6f617420" - "66726f6d2053544e756d626572202831293a202053544e756d626572283129203d3d20464c4f41545f4f4e453a2067" - "6f6f64202053544e756d626572283129203d3d20464c4f41545f4f4e453a206661696c65642020666c6f6174206672" - "6f6d2053544e756d6265722831293a206661696c6564004d0970726f64756365727302086c616e6775616765010452" - "757374000c70726f6365737365642d6279010572757374631d312e39352e3020283539383037363136652032303236" - "2d30342d313429002c0f7461726765745f6665617475726573022b0f6d757461626c652d676c6f62616c732b087369" - "676e2d657874"; - -extern std::string const kFloat0Hex = - "0061736d0100000001290560057f7f7f7f7f017f60047e7f7f7f017f60077f7f7f7f7f7f7f017f60047f7f7f7f017f" - "6000017f02560408686f73745f6c6962057472616365000008686f73745f6c69620e666c6f61745f66726f6d5f696e" - "74000108686f73745f6c696209666c6f61745f737562000208686f73745f6c696209666c6f61745f636d7000030302" - "010405030100110619037f01418080c0000b7f0041e980c0000b7f0041f080c0000b073504066d656d6f727902000d" - "657363726f775f66696e69736800040a5f5f646174615f656e6403010b5f5f686561705f6261736503020acc0101c9" - "0101027f230041206b22002400418080c000411541014100410010001a200041003602082000420037030020004100" - "3602182000420037031002400240420a2000410c41001001410c4604402000410c2000410c200041106a2201410c41" - "001002410c470d012001410c419580c000410c100345044041a180c000411a41014100410010001a0c030b41bb80c0" - "00411941014100410010001a0c020b41d480c000411541014100410010001a0c010b41d480c0004115410141004100" - "10001a0b200041206a240041010b0b720100418080c0000b690a24242420746573745f666c6f61745f302024242400" - "00000000000000800000002020464c4f41545f5a45524f20636f6d706172653a20676f6f642020464c4f41545f5a45" - "524f20636f6d706172653a206261642020666c6f61742031302d31303a206661696c6564004d0970726f6475636572" - "7302086c616e6775616765010452757374000c70726f6365737365642d6279010572757374631d312e39352e302028" - "35393830373631366520323032362d30342d313429002c0f7461726765745f6665617475726573022b0f6d75746162" - "6c652d676c6f62616c732b087369676e2d657874"; - -extern std::string const kDisabledFloatHex = - "0061736d010000000108026000006000017f03030200010503010002063e0a7f004180080b7f004180080b7f004180" - "100b7f004180100b7f00418090040b7f004180080b7f00418090040b7f00418080080b7f0041000b7f0041010b07b7" - "010d066d656d6f72790200115f5f7761736d5f63616c6c5f63746f727300000d657363726f775f66696e6973680001" - "0362756603000c5f5f64736f5f68616e646c6503010a5f5f646174615f656e6403020b5f5f737461636b5f6c6f7703" - "030c5f5f737461636b5f6869676803040d5f5f676c6f62616c5f6261736503050b5f5f686561705f6261736503060a" - "5f5f686561705f656e6403070d5f5f6d656d6f72795f6261736503080c5f5f7461626c655f6261736503090a150202" - "000b100043000000c54300200045931a41010b"; - -extern std::string const kMemoryPointerAtLimitHex = - "0061736d010000000105016000017f0302010005030100010711010d657363726f775f66696e69736800000a0e010c" - "0041ffff032d00001a41010b"; - -extern std::string const kMemoryPointerOverLimitHex = - "0061736d010000000105016000017f0302010005030100010711010d657363726f775f66696e69736800000a0e010c" - "00418080042d00001a41010b"; - -extern std::string const kMemoryOffsetOverLimitHex = - "0061736d010000000105016000017f030201000503010001071a02066d656d6f727902000d657363726f775f66696e" - "69736800000a0e010c00410028028080041a41010b"; - -extern std::string const kMemoryEndOfWordOverLimitHex = - "0061736d010000000105016000017f030201000503010001071a02066d656d6f727902000d657363726f775f66696e" - "69736800000a0e010c0041feff032802001a41010b"; - -extern std::string const kMemoryGrow0To1PageHex = - "0061736d010000000105016000017f030201000503010000071a02066d656d6f727902000d657363726f775f66696e" - "69736800000a0b010900410140001a41010b"; - -extern std::string const kMemoryGrow1To0PageHex = - "0061736d010000000105016000017f030201000503010001071a02066d656d6f727902000d657363726f775f66696e" - "69736800000a13011100417f4000417f460440417f0f0b41010b"; - -extern std::string const kMemoryLastByteOf8MbHex = - "0061736d010000000105016000017f030201000506010180018001071a02066d656d6f727902000d657363726f775f" - "66696e69736800000a0f010d0041ffffff032d00001a41010b"; - -extern std::string const kMemoryGrow1MoreThan8MbHex = - "0061736d010000000105016000017f03020100050401008001071a02066d656d6f727902000d657363726f775f6669" - "6e69736800000a1301110041014000417f460440417f0f0b41010b"; - -extern std::string const kMemoryGrow0MoreThan8MbHex = - "0061736d010000000105016000017f03020100050401008001071a02066d656d6f727902000d657363726f775f6669" - "6e69736800000a1301110041004000417f460440417f0f0b41010b"; - -extern std::string const kMemoryInit1MoreThan8MbHex = - "0061736d010000000105016000017f030201000506010181018101071a02066d656d6f727902000d657363726f775f" - "66696e69736800000a0f010d0041ffffff032d00001a41010b"; - -extern std::string const kMemoryNegativeAddressHex = - "0061736d010000000105016000017f030201000506010180018001071a02066d656d6f727902000d657363726f775f" - "66696e69736800000a0c010a00417f2d00001a41010b"; - -extern std::string const kTable64ElementsHex = - "0061736d010000000108026000006000017f03030200010404017000400711010d657363726f775f66696e69736800" - "010946010041000b400000000000000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000000000000000000000000a090202000b040041010b"; - -extern std::string const kTable65ElementsHex = - "0061736d010000000108026000006000017f03030200010404017000410711010d657363726f775f66696e69736800" - "010947010041000b410000000000000000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000a090202000b040041010b"; - -extern std::string const kTable2TablesHex = - "0061736d010000000108026000006000017f030302000104090270010101700101010711010d657363726f775f6669" - "6e6973680001090f020041000b0100020141000b0001000a090202000b040041010b"; - -extern std::string const kTable0ElementsHex = - "0061736d010000000105016000017f030201000404017000000711010d657363726f775f66696e69736800000a0601" - "040041010b"; - -extern std::string const kTableUintMaxHex = - "0061736d010000000105016000017f030201000408017000ffffffff0f0711010d657363726f775f66696e69736800" - "000a0601040041010b"; - -extern std::string const kProposalMutableGlobalHex = - "0061736d010000000105016000017f030201000606017f0141000b071b0207636f756e74657203000d657363726f77" - "5f66696e69736800000a0d010b00230041016a240041010b"; - -extern std::string const kProposalGcStructNewHex = - "0061736d01000000010b026000017f5f027f017f01030201000711010d657363726f775f66696e69736800000a0a01" - "0800fb01011a41010b"; - -extern std::string const kProposalMultiValueHex = - "0061736d010000000110036000027f7f6000017f60027f7f017f03030200010711010d657363726f775f66696e6973" - "6800010a14020600410a41140b0b00100002026a411e460b0b"; - -extern std::string const kProposalSignExtHex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a0b01090041ff01c0" - "417f460b"; - -extern std::string const kProposalFloatToIntHex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a1201100043f90215" - "50fc0041ffffffff07460b"; - -extern std::string const kProposalBulkMemoryHex = - "0061736d010000000105016000017f030201000503010001071a02066d656d6f727902000d657363726f775f66696e" - "69736800000a1f011d004100412a3a000041e40041004101fc0a000041e4002d0000412a460b"; - -extern std::string const kProposalRefTypesHex = - "0061736d010000000105016000017f020f0103656e76057461626c65016f0001030201000711010d657363726f775f" - "66696e69736800000a0c010a004100d06f260041010b"; - -extern std::string const kProposalTailCallHex = - "0061736d010000000105016000017f03030200000711010d657363726f775f66696e69736800010a0b02040041010b" - "040012000b"; - -extern std::string const kProposalExtendedConstHex = - "0061736d010000000105016000017f030201000609017f00410a41206a0b0711010d657363726f775f66696e697368" - "00000a090107002300412a460b"; - -extern std::string const kProposalMultiMemoryHex = - "0061736d010000000105016000017f03020100050502000000010711010d657363726f775f66696e69736800000a06" - "0104003f010b"; - -extern std::string const kProposalCustomPageSizesHex = - "0061736d010000000105016000017f030201000504010801000711010d657363726f775f66696e69736800000a0601" - "040041010b"; - -extern std::string const kProposalMemory64Hex = - "0061736d010000000105016000017f0302010005030104010711010d657363726f775f66696e69736800000a10010e" - "004200412a3a00003f004201510b"; - -extern std::string const kProposalWideArithmeticHex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a0e010c0042014202" - "fc161a1a41010b"; - -extern std::string const kTrapDivideBy0Hex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a0c010a00412a4100" - "6d1a41010b"; - -extern std::string const kTrapIntOverflowHex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a0d010b0041808080" - "8078417f6d0b"; - -extern std::string const kTrapUnreachableHex = - "0061736d010000000105016000017f030201000711010d657363726f775f66696e69736800000a070105000041010" - "b"; - -extern std::string const kTrapNullCallHex = - "0061736d010000000105016000017f030201000404017000010711010d657363726f775f66696e69736800000a0901" - "070041001100000b"; - -extern std::string const kTrapFuncSigMismatchHex = - "0061736d010000000108026000006000017f03030200010404017000010711010d657363726f775f66696e69736800" - "010907010041000b01000a0d020300010b070041001101000b"; - -extern std::string const kWasiGetTimeHex = - "0061736d01000000010c0260037f7e7f017f6000017f02290116776173695f736e617073686f745f70726576696577" - "310e636c6f636b5f74696d655f6765740000030201010503010001071a02066d656d6f727902000d657363726f775f" - "66696e69736800010a16011400410042e8074100100045047f410105417f0b0b"; - -extern std::string const kWasiPrintHex = - "0061736d01000000010d0260047f7f7f7f017f6000017f02230116776173695f736e617073686f745f707265766965" - "77310866645f77726974650000030201010503010001071a02066d656d6f727902000d657363726f775f66696e6973" - "6800010a1d011b01017f411821004101410041012000100045047f410105417f0b0b0b1e030041100b0648656c6c6f" - "0a0041000b04100000000041040b0406000000"; - -// The following several wasm hex strings are for testing wasm section -// corruption cases. They are illegal hence do not have corresponding -// rust or wat sources. -// Wasm code magic number is "0061736d", and the only valid version is 1. - -extern std::string const kBadMagicNumberHex = "1061736d01000000"; -extern std::string const kBadVersionNumberHex = "0061736d02000000"; - -// Corruption Test: lyingHeader -// Scenario: A section declares it is 2GB long, but the file ends immediately. -// Attack: Buffer pre-allocation DoS (OOM). -// # Magic (00 61 73 6d) + Version (01 00 00 00) -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Type Section (ID 1) -// # Size: LEB128 encoded 2GB (0x80 0x80 0x80 0x80 0x08) -// data += b'\x01\x80\x80\x80\x80\x08' -extern std::string const kLyingHeaderHex = "0061736d01000000018080808008"; - -// Corruption Test: neverEndingNumber -// Scenario: An LEB128 integer that never has a stop bit (byte < 0x80). -// Attack: Infinite loop in parser or read out of bounds. -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Type Section (ID 1), Size 5 -// data += b'\x01\x05' -// # Vector count: Infinite stream of 0x80 (100 bytes) -// data += b'\x80' * 100 -extern std::string const kNeverEndingNumberHex = - "0061736d01000000010580808080808080808080808080808080808080808080808080808080808080808080808080" - "8080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080" - "80808080808080808080808080808080"; - -// Corruption Test: vectorLie -// Scenario: A vector declares it has 4 billion items, but provides none. -// Attack: Vector pre-allocation DoS (OOM). -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Type Section (ID 1) -// # Size 5 (just enough for the count bytes) -// data += b'\x01\x05' -// # Vector Count: 0xFF 0xFF 0xFF 0xFF 0x0F (4,294,967,295 items) -// data += b'\xff\xff\xff\xff\x0f' -// # No actual items follow... -extern std::string const kVectorLieHex = "0061736d010000000105ffffffff0f"; - -// Corruption Test: sectionOrdering -// Scenario: Sections appear out of order -// (Code section before Function section). -// Attack: Parser state confusion / potential null pointer deref. -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Code Section (ID 10) - usually last -// # Size 2, Count 0 -// data += b'\x0a\x02\x00\x0b' -// # Function Section (ID 3) - usually 3rd -// data += b'\x03\x02\x00\x00' -extern std::string const kSectionOrderingHex = "0061736d010000000a02000b03020000"; - -// Corruption Test: ghostPayload -// Scenario: Valid headers, but file is truncated in the middle of a payload. -// Attack: Read out of bounds panic. -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Type Section (ID 1), Size 10 -// data += b'\x01\x0a' -// # Content: Count 1 -// data += b'\x01' -// # Start of a type definition (0x60 = func) -// data += b'\x60' -// # File ends abruptly here (missing params/results) -extern std::string const kGhostPayloadHex = "0061736d01000000010a0160"; - -// Corruption Test: junkAfterSection -// Scenario: Section declares size X, but logical content finishes at X-5. -// Attack: Validation bypass if parser stops early, -// or panic if strict check missing. -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Type Section (ID 1), Size 10 bytes -// data += b'\x01\x0a' -// # Real content: Count 1, (func -> void) = 4 bytes -// # \x01 (count) \x60 (func) \x00 (0 params) \x00 (0 results) -// data += b'\x01\x60\x00\x00' -// # Remaining 6 bytes are junk padding within the section size -// data += b'\x00' * 6 -extern std::string const kJunkAfterSectionHex = "0061736d01000000010a01600000000000000000"; - -// Corruption Test: invalidSectionId -// Scenario: A section ID that doesn't exist (0xFF). -// Attack: Default case handling / unhandled enum variant. -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # Section ID 0xFF, Size 1 -// data += b'\xff\x01\x00' -extern std::string const kInvalidSectionIdHex = "0061736d01000000ff0100"; - -// Corruption Test: localVariableBomb -// Scenario: A function declares 4 billion local variables. -// Attack: Stack Overflow / OOM during function init (memset). -// data = b'\x00\x61\x73\x6d\x01\x00\x00\x00' -// # 1. Type Section: (func) -> () -// data += b'\x01\x04\x01\x60\x00\x00' -// # 3. Function Section: 1 function of type 0 -// data += b'\x03\x02\x01\x00' -// # 10. Code Section -// # ID 10, Size 15 (estimated), Count 1 -// data += b'\x0a\x0f\x01' -// # Function Body Size: 13 bytes -// data += b'\x0d' -// # Local Declarations Count: 1 entry -// data += b'\x01' -// # The Bomb: 4,294,967,295 locals of type i32 -// # Count: 0xFF 0xFF 0xFF 0xFF 0x0F -// # Type: 0x7F (i32) -// data += b'\xff\xff\xff\xff\x0f\x7f' -// # Instruction: end (0x0b) -// data += b'\x0b' -extern std::string const kLocalVariableBombHex = - "0061736d01000000010401600000030201000a0f010d01ffffffff0f7f0b"; - -extern std::string const kInfiniteLoopWasmHex = - "0061736d010000000108026000006000017f030302000105030100020638097f004180080b7f004180080b7f004180" - "080b7f00418088040b7f004180080b7f00418088040b7f00418080080b7f0041000b7f0041010b07a8010c066d656d" - "6f72790200115f5f7761736d5f63616c6c5f63746f72730000046c6f6f7000010c5f5f64736f5f68616e646c650300" - "0a5f5f646174615f656e6403010b5f5f737461636b5f6c6f7703020c5f5f737461636b5f6869676803030d5f5f676c" - "6f62616c5f6261736503040b5f5f686561705f6261736503050a5f5f686561705f656e6403060d5f5f6d656d6f7279" - "5f6261736503070c5f5f7461626c655f6261736503080a270202000b220041fc87044100360200034041fc870441fc" - "870428020041016a3602000c000b000b007f0970726f647563657273010c70726f6365737365642d62790105636c61" - "6e675f31392e312e352d776173692d73646b202868747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c76" - "6d2d70726f6a6563742061623462356132646235383239353861663165653330386137393063666462343262643234" - "3732302900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f62616c732b087369676e2d" - "6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c7565"; - -extern std::string const kStartLoopHex = - "0061736d010000000108026000006000017f030302000107190205737461727400000d657363726f775f66696e6973" - "6800010801000a0e02070003400c000b0b040041010b"; - -extern std::string const kBadAlignWasmHex = - "0061736d01000000011b046000017f60057f7f7f7f7f017f60067f7f7f7f7f7f017f60000002260203656e760f666c" - "6f61745f66726f6d5f75696e74000103656e7608636865636b5f6964000203050403000000050301000306470b7f00" - "4180080b7f00418088020b7f004180080b7f00418088040b7f00418088040b7f00418088080b7f004180080b7f0041" - "8088080b7f004180800c0b7f0041000b7f0041010b07cc0110066d656d6f72790200115f5f7761736d5f63616c6c5f" - "63746f72730002057465737431000307655f64617461310300057465737432000407655f6461746132030104746573" - "7400050c5f5f64736f5f68616e646c6503020a5f5f646174615f656e6403030b5f5f737461636b5f6c6f7703040c5f" - "5f737461636b5f6869676803050d5f5f676c6f62616c5f6261736503060b5f5f686561705f6261736503070a5f5f68" - "6561705f656e6403080d5f5f6d656d6f72795f6261736503090c5f5f7461626c655f62617365030a0a99020402000b" - "2801017f418108427f370000418108410841a308410c41001000220041a40828020020004100481b0b5f01017f419a" - "88024191a4cca00136010041928802428994ace0d0c1c38710370100418a88024281848ca0d0c0c183083701004181" - "8802417f360000418a8802411441818802410441a3880241201001220041a4880228020020004100481b0b8a010103" - "7f418108427f370000418108410841a308410c410010002100419a88024191a4cca00136010041928802428994ace0" - "d0c1c38710370100418a88024281848ca0d0c0c1830837010041818802417f36000041a4082802002101418a880241" - "1441818802410441a3880241201001220241a4880228020020024100481b2000200120004100481b6a0b007f097072" - "6f647563657273010c70726f6365737365642d62790105636c616e675f31392e312e352d776173692d73646b202868" - "747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a656374206162346235613264623538" - "32393538616631656533303861373930636664623432626432343732302900490f7461726765745f66656174757265" - "73042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d74797065732b" - "0a6d756c746976616c7565"; - -extern std::string const kThousandParamsHex = - "0061736d0100000001f1070260000060e8077f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f017f030302000105030100020638097f" - "004180080b7f004180080b7f004180080b7f00418088040b7f004180080b7f00418088040b7f00418080080b7f0041" - "000b7f0041010b07a8010c066d656d6f72790200115f5f7761736d5f63616c6c5f63746f7273000004746573740001" - "0c5f5f64736f5f68616e646c6503000a5f5f646174615f656e6403010b5f5f737461636b5f6c6f7703020c5f5f7374" - "61636b5f6869676803030d5f5f676c6f62616c5f6261736503040b5f5f686561705f6261736503050a5f5f68656170" - "5f656e6403060d5f5f6d656d6f72795f6261736503070c5f5f7461626c655f6261736503080aa71e0202000ba11e00" - "200020016a20026a20036a20046a20056a20066a20076a20086a20096a200a6a200b6a200c6a200d6a200e6a200f6a" - "20106a20116a20126a20136a20146a20156a20166a20176a20186a20196a201a6a201b6a201c6a201d6a201e6a201f" - "6a20206a20216a20226a20236a20246a20256a20266a20276a20286a20296a202a6a202b6a202c6a202d6a202e6a20" - "2f6a20306a20316a20326a20336a20346a20356a20366a20376a20386a20396a203a6a203b6a203c6a203d6a203e6a" - "203f6a20406a20416a20426a20436a20446a20456a20466a20476a20486a20496a204a6a204b6a204c6a204d6a204e" - "6a204f6a20506a20516a20526a20536a20546a20556a20566a20576a20586a20596a205a6a205b6a205c6a205d6a20" - "5e6a205f6a20606a20616a20626a20636a20646a20656a20666a20676a20686a20696a206a6a206b6a206c6a206d6a" - "206e6a206f6a20706a20716a20726a20736a20746a20756a20766a20776a20786a20796a207a6a207b6a207c6a207d" - "6a207e6a207f6a2080016a2081016a2082016a2083016a2084016a2085016a2086016a2087016a2088016a2089016a" - "208a016a208b016a208c016a208d016a208e016a208f016a2090016a2091016a2092016a2093016a2094016a209501" - "6a2096016a2097016a2098016a2099016a209a016a209b016a209c016a209d016a209e016a209f016a20a0016a20a1" - "016a20a2016a20a3016a20a4016a20a5016a20a6016a20a7016a20a8016a20a9016a20aa016a20ab016a20ac016a20" - "ad016a20ae016a20af016a20b0016a20b1016a20b2016a20b3016a20b4016a20b5016a20b6016a20b7016a20b8016a" - "20b9016a20ba016a20bb016a20bc016a20bd016a20be016a20bf016a20c0016a20c1016a20c2016a20c3016a20c401" - "6a20c5016a20c6016a20c7016a20c8016a20c9016a20ca016a20cb016a20cc016a20cd016a20ce016a20cf016a20d0" - "016a20d1016a20d2016a20d3016a20d4016a20d5016a20d6016a20d7016a20d8016a20d9016a20da016a20db016a20" - "dc016a20dd016a20de016a20df016a20e0016a20e1016a20e2016a20e3016a20e4016a20e5016a20e6016a20e7016a" - "20e8016a20e9016a20ea016a20eb016a20ec016a20ed016a20ee016a20ef016a20f0016a20f1016a20f2016a20f301" - "6a20f4016a20f5016a20f6016a20f7016a20f8016a20f9016a20fa016a20fb016a20fc016a20fd016a20fe016a20ff" - "016a2080026a2081026a2082026a2083026a2084026a2085026a2086026a2087026a2088026a2089026a208a026a20" - "8b026a208c026a208d026a208e026a208f026a2090026a2091026a2092026a2093026a2094026a2095026a2096026a" - "2097026a2098026a2099026a209a026a209b026a209c026a209d026a209e026a209f026a20a0026a20a1026a20a202" - "6a20a3026a20a4026a20a5026a20a6026a20a7026a20a8026a20a9026a20aa026a20ab026a20ac026a20ad026a20ae" - "026a20af026a20b0026a20b1026a20b2026a20b3026a20b4026a20b5026a20b6026a20b7026a20b8026a20b9026a20" - "ba026a20bb026a20bc026a20bd026a20be026a20bf026a20c0026a20c1026a20c2026a20c3026a20c4026a20c5026a" - "20c6026a20c7026a20c8026a20c9026a20ca026a20cb026a20cc026a20cd026a20ce026a20cf026a20d0026a20d102" - "6a20d2026a20d3026a20d4026a20d5026a20d6026a20d7026a20d8026a20d9026a20da026a20db026a20dc026a20dd" - "026a20de026a20df026a20e0026a20e1026a20e2026a20e3026a20e4026a20e5026a20e6026a20e7026a20e8026a20" - "e9026a20ea026a20eb026a20ec026a20ed026a20ee026a20ef026a20f0026a20f1026a20f2026a20f3026a20f4026a" - "20f5026a20f6026a20f7026a20f8026a20f9026a20fa026a20fb026a20fc026a20fd026a20fe026a20ff026a208003" - "6a2081036a2082036a2083036a2084036a2085036a2086036a2087036a2088036a2089036a208a036a208b036a208c" - "036a208d036a208e036a208f036a2090036a2091036a2092036a2093036a2094036a2095036a2096036a2097036a20" - "98036a2099036a209a036a209b036a209c036a209d036a209e036a209f036a20a0036a20a1036a20a2036a20a3036a" - "20a4036a20a5036a20a6036a20a7036a20a8036a20a9036a20aa036a20ab036a20ac036a20ad036a20ae036a20af03" - "6a20b0036a20b1036a20b2036a20b3036a20b4036a20b5036a20b6036a20b7036a20b8036a20b9036a20ba036a20bb" - "036a20bc036a20bd036a20be036a20bf036a20c0036a20c1036a20c2036a20c3036a20c4036a20c5036a20c6036a20" - "c7036a20c8036a20c9036a20ca036a20cb036a20cc036a20cd036a20ce036a20cf036a20d0036a20d1036a20d2036a" - "20d3036a20d4036a20d5036a20d6036a20d7036a20d8036a20d9036a20da036a20db036a20dc036a20dd036a20de03" - "6a20df036a20e0036a20e1036a20e2036a20e3036a20e4036a20e5036a20e6036a20e7036a20e8036a20e9036a20ea" - "036a20eb036a20ec036a20ed036a20ee036a20ef036a20f0036a20f1036a20f2036a20f3036a20f4036a20f5036a20" - "f6036a20f7036a20f8036a20f9036a20fa036a20fb036a20fc036a20fd036a20fe036a20ff036a2080046a2081046a" - "2082046a2083046a2084046a2085046a2086046a2087046a2088046a2089046a208a046a208b046a208c046a208d04" - "6a208e046a208f046a2090046a2091046a2092046a2093046a2094046a2095046a2096046a2097046a2098046a2099" - "046a209a046a209b046a209c046a209d046a209e046a209f046a20a0046a20a1046a20a2046a20a3046a20a4046a20" - "a5046a20a6046a20a7046a20a8046a20a9046a20aa046a20ab046a20ac046a20ad046a20ae046a20af046a20b0046a" - "20b1046a20b2046a20b3046a20b4046a20b5046a20b6046a20b7046a20b8046a20b9046a20ba046a20bb046a20bc04" - "6a20bd046a20be046a20bf046a20c0046a20c1046a20c2046a20c3046a20c4046a20c5046a20c6046a20c7046a20c8" - "046a20c9046a20ca046a20cb046a20cc046a20cd046a20ce046a20cf046a20d0046a20d1046a20d2046a20d3046a20" - "d4046a20d5046a20d6046a20d7046a20d8046a20d9046a20da046a20db046a20dc046a20dd046a20de046a20df046a" - "20e0046a20e1046a20e2046a20e3046a20e4046a20e5046a20e6046a20e7046a20e8046a20e9046a20ea046a20eb04" - "6a20ec046a20ed046a20ee046a20ef046a20f0046a20f1046a20f2046a20f3046a20f4046a20f5046a20f6046a20f7" - "046a20f8046a20f9046a20fa046a20fb046a20fc046a20fd046a20fe046a20ff046a2080056a2081056a2082056a20" - "83056a2084056a2085056a2086056a2087056a2088056a2089056a208a056a208b056a208c056a208d056a208e056a" - "208f056a2090056a2091056a2092056a2093056a2094056a2095056a2096056a2097056a2098056a2099056a209a05" - "6a209b056a209c056a209d056a209e056a209f056a20a0056a20a1056a20a2056a20a3056a20a4056a20a5056a20a6" - "056a20a7056a20a8056a20a9056a20aa056a20ab056a20ac056a20ad056a20ae056a20af056a20b0056a20b1056a20" - "b2056a20b3056a20b4056a20b5056a20b6056a20b7056a20b8056a20b9056a20ba056a20bb056a20bc056a20bd056a" - "20be056a20bf056a20c0056a20c1056a20c2056a20c3056a20c4056a20c5056a20c6056a20c7056a20c8056a20c905" - "6a20ca056a20cb056a20cc056a20cd056a20ce056a20cf056a20d0056a20d1056a20d2056a20d3056a20d4056a20d5" - "056a20d6056a20d7056a20d8056a20d9056a20da056a20db056a20dc056a20dd056a20de056a20df056a20e0056a20" - "e1056a20e2056a20e3056a20e4056a20e5056a20e6056a20e7056a20e8056a20e9056a20ea056a20eb056a20ec056a" - "20ed056a20ee056a20ef056a20f0056a20f1056a20f2056a20f3056a20f4056a20f5056a20f6056a20f7056a20f805" - "6a20f9056a20fa056a20fb056a20fc056a20fd056a20fe056a20ff056a2080066a2081066a2082066a2083066a2084" - "066a2085066a2086066a2087066a2088066a2089066a208a066a208b066a208c066a208d066a208e066a208f066a20" - "90066a2091066a2092066a2093066a2094066a2095066a2096066a2097066a2098066a2099066a209a066a209b066a" - "209c066a209d066a209e066a209f066a20a0066a20a1066a20a2066a20a3066a20a4066a20a5066a20a6066a20a706" - "6a20a8066a20a9066a20aa066a20ab066a20ac066a20ad066a20ae066a20af066a20b0066a20b1066a20b2066a20b3" - "066a20b4066a20b5066a20b6066a20b7066a20b8066a20b9066a20ba066a20bb066a20bc066a20bd066a20be066a20" - "bf066a20c0066a20c1066a20c2066a20c3066a20c4066a20c5066a20c6066a20c7066a20c8066a20c9066a20ca066a" - "20cb066a20cc066a20cd066a20ce066a20cf066a20d0066a20d1066a20d2066a20d3066a20d4066a20d5066a20d606" - "6a20d7066a20d8066a20d9066a20da066a20db066a20dc066a20dd066a20de066a20df066a20e0066a20e1066a20e2" - "066a20e3066a20e4066a20e5066a20e6066a20e7066a20e8066a20e9066a20ea066a20eb066a20ec066a20ed066a20" - "ee066a20ef066a20f0066a20f1066a20f2066a20f3066a20f4066a20f5066a20f6066a20f7066a20f8066a20f9066a" - "20fa066a20fb066a20fc066a20fd066a20fe066a20ff066a2080076a2081076a2082076a2083076a2084076a208507" - "6a2086076a2087076a2088076a2089076a208a076a208b076a208c076a208d076a208e076a208f076a2090076a2091" - "076a2092076a2093076a2094076a2095076a2096076a2097076a2098076a2099076a209a076a209b076a209c076a20" - "9d076a209e076a209f076a20a0076a20a1076a20a2076a20a3076a20a4076a20a5076a20a6076a20a7076a20a8076a" - "20a9076a20aa076a20ab076a20ac076a20ad076a20ae076a20af076a20b0076a20b1076a20b2076a20b3076a20b407" - "6a20b5076a20b6076a20b7076a20b8076a20b9076a20ba076a20bb076a20bc076a20bd076a20be076a20bf076a20c0" - "076a20c1076a20c2076a20c3076a20c4076a20c5076a20c6076a20c7076a20c8076a20c9076a20ca076a20cb076a20" - "cc076a20cd076a20ce076a20cf076a20d0076a20d1076a20d2076a20d3076a20d4076a20d5076a20d6076a20d7076a" - "20d8076a20d9076a20da076a20db076a20dc076a20dd076a20de076a20df076a20e0076a20e1076a20e2076a20e307" - "6a20e4076a20e5076a20e6076a20e7076a0b007f0970726f647563657273010c70726f6365737365642d6279010563" - "6c616e675f31392e312e352d776173692d73646b202868747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c" - "6c766d2d70726f6a656374206162346235613264623538323935386166316565333038613739306366646234326264" - "32343732302900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f62616c732b08736967" - "6e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c7565"; - -extern std::string const kThousand1ParamsHex = - "0061736d0100000001f2070260000060e9077f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f" - "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f017f03030200010503010002063809" - "7f004180080b7f004180080b7f004180080b7f00418088040b7f004180080b7f00418088040b7f00418080080b7f00" - "41000b7f0041010b07a8010c066d656d6f72790200115f5f7761736d5f63616c6c5f63746f72730000047465737400" - "010c5f5f64736f5f68616e646c6503000a5f5f646174615f656e6403010b5f5f737461636b5f6c6f7703020c5f5f73" - "7461636b5f6869676803030d5f5f676c6f62616c5f6261736503040b5f5f686561705f6261736503050a5f5f686561" - "705f656e6403060d5f5f6d656d6f72795f6261736503070c5f5f7461626c655f6261736503080aab1e0202000ba51e" - "00200020016a20026a20036a20046a20056a20066a20076a20086a20096a200a6a200b6a200c6a200d6a200e6a200f" - "6a20106a20116a20126a20136a20146a20156a20166a20176a20186a20196a201a6a201b6a201c6a201d6a201e6a20" - "1f6a20206a20216a20226a20236a20246a20256a20266a20276a20286a20296a202a6a202b6a202c6a202d6a202e6a" - "202f6a20306a20316a20326a20336a20346a20356a20366a20376a20386a20396a203a6a203b6a203c6a203d6a203e" - "6a203f6a20406a20416a20426a20436a20446a20456a20466a20476a20486a20496a204a6a204b6a204c6a204d6a20" - "4e6a204f6a20506a20516a20526a20536a20546a20556a20566a20576a20586a20596a205a6a205b6a205c6a205d6a" - "205e6a205f6a20606a20616a20626a20636a20646a20656a20666a20676a20686a20696a206a6a206b6a206c6a206d" - "6a206e6a206f6a20706a20716a20726a20736a20746a20756a20766a20776a20786a20796a207a6a207b6a207c6a20" - "7d6a207e6a207f6a2080016a2081016a2082016a2083016a2084016a2085016a2086016a2087016a2088016a208901" - "6a208a016a208b016a208c016a208d016a208e016a208f016a2090016a2091016a2092016a2093016a2094016a2095" - "016a2096016a2097016a2098016a2099016a209a016a209b016a209c016a209d016a209e016a209f016a20a0016a20" - "a1016a20a2016a20a3016a20a4016a20a5016a20a6016a20a7016a20a8016a20a9016a20aa016a20ab016a20ac016a" - "20ad016a20ae016a20af016a20b0016a20b1016a20b2016a20b3016a20b4016a20b5016a20b6016a20b7016a20b801" - "6a20b9016a20ba016a20bb016a20bc016a20bd016a20be016a20bf016a20c0016a20c1016a20c2016a20c3016a20c4" - "016a20c5016a20c6016a20c7016a20c8016a20c9016a20ca016a20cb016a20cc016a20cd016a20ce016a20cf016a20" - "d0016a20d1016a20d2016a20d3016a20d4016a20d5016a20d6016a20d7016a20d8016a20d9016a20da016a20db016a" - "20dc016a20dd016a20de016a20df016a20e0016a20e1016a20e2016a20e3016a20e4016a20e5016a20e6016a20e701" - "6a20e8016a20e9016a20ea016a20eb016a20ec016a20ed016a20ee016a20ef016a20f0016a20f1016a20f2016a20f3" - "016a20f4016a20f5016a20f6016a20f7016a20f8016a20f9016a20fa016a20fb016a20fc016a20fd016a20fe016a20" - "ff016a2080026a2081026a2082026a2083026a2084026a2085026a2086026a2087026a2088026a2089026a208a026a" - "208b026a208c026a208d026a208e026a208f026a2090026a2091026a2092026a2093026a2094026a2095026a209602" - "6a2097026a2098026a2099026a209a026a209b026a209c026a209d026a209e026a209f026a20a0026a20a1026a20a2" - "026a20a3026a20a4026a20a5026a20a6026a20a7026a20a8026a20a9026a20aa026a20ab026a20ac026a20ad026a20" - "ae026a20af026a20b0026a20b1026a20b2026a20b3026a20b4026a20b5026a20b6026a20b7026a20b8026a20b9026a" - "20ba026a20bb026a20bc026a20bd026a20be026a20bf026a20c0026a20c1026a20c2026a20c3026a20c4026a20c502" - "6a20c6026a20c7026a20c8026a20c9026a20ca026a20cb026a20cc026a20cd026a20ce026a20cf026a20d0026a20d1" - "026a20d2026a20d3026a20d4026a20d5026a20d6026a20d7026a20d8026a20d9026a20da026a20db026a20dc026a20" - "dd026a20de026a20df026a20e0026a20e1026a20e2026a20e3026a20e4026a20e5026a20e6026a20e7026a20e8026a" - "20e9026a20ea026a20eb026a20ec026a20ed026a20ee026a20ef026a20f0026a20f1026a20f2026a20f3026a20f402" - "6a20f5026a20f6026a20f7026a20f8026a20f9026a20fa026a20fb026a20fc026a20fd026a20fe026a20ff026a2080" - "036a2081036a2082036a2083036a2084036a2085036a2086036a2087036a2088036a2089036a208a036a208b036a20" - "8c036a208d036a208e036a208f036a2090036a2091036a2092036a2093036a2094036a2095036a2096036a2097036a" - "2098036a2099036a209a036a209b036a209c036a209d036a209e036a209f036a20a0036a20a1036a20a2036a20a303" - "6a20a4036a20a5036a20a6036a20a7036a20a8036a20a9036a20aa036a20ab036a20ac036a20ad036a20ae036a20af" - "036a20b0036a20b1036a20b2036a20b3036a20b4036a20b5036a20b6036a20b7036a20b8036a20b9036a20ba036a20" - "bb036a20bc036a20bd036a20be036a20bf036a20c0036a20c1036a20c2036a20c3036a20c4036a20c5036a20c6036a" - "20c7036a20c8036a20c9036a20ca036a20cb036a20cc036a20cd036a20ce036a20cf036a20d0036a20d1036a20d203" - "6a20d3036a20d4036a20d5036a20d6036a20d7036a20d8036a20d9036a20da036a20db036a20dc036a20dd036a20de" - "036a20df036a20e0036a20e1036a20e2036a20e3036a20e4036a20e5036a20e6036a20e7036a20e8036a20e9036a20" - "ea036a20eb036a20ec036a20ed036a20ee036a20ef036a20f0036a20f1036a20f2036a20f3036a20f4036a20f5036a" - "20f6036a20f7036a20f8036a20f9036a20fa036a20fb036a20fc036a20fd036a20fe036a20ff036a2080046a208104" - "6a2082046a2083046a2084046a2085046a2086046a2087046a2088046a2089046a208a046a208b046a208c046a208d" - "046a208e046a208f046a2090046a2091046a2092046a2093046a2094046a2095046a2096046a2097046a2098046a20" - "99046a209a046a209b046a209c046a209d046a209e046a209f046a20a0046a20a1046a20a2046a20a3046a20a4046a" - "20a5046a20a6046a20a7046a20a8046a20a9046a20aa046a20ab046a20ac046a20ad046a20ae046a20af046a20b004" - "6a20b1046a20b2046a20b3046a20b4046a20b5046a20b6046a20b7046a20b8046a20b9046a20ba046a20bb046a20bc" - "046a20bd046a20be046a20bf046a20c0046a20c1046a20c2046a20c3046a20c4046a20c5046a20c6046a20c7046a20" - "c8046a20c9046a20ca046a20cb046a20cc046a20cd046a20ce046a20cf046a20d0046a20d1046a20d2046a20d3046a" - "20d4046a20d5046a20d6046a20d7046a20d8046a20d9046a20da046a20db046a20dc046a20dd046a20de046a20df04" - "6a20e0046a20e1046a20e2046a20e3046a20e4046a20e5046a20e6046a20e7046a20e8046a20e9046a20ea046a20eb" - "046a20ec046a20ed046a20ee046a20ef046a20f0046a20f1046a20f2046a20f3046a20f4046a20f5046a20f6046a20" - "f7046a20f8046a20f9046a20fa046a20fb046a20fc046a20fd046a20fe046a20ff046a2080056a2081056a2082056a" - "2083056a2084056a2085056a2086056a2087056a2088056a2089056a208a056a208b056a208c056a208d056a208e05" - "6a208f056a2090056a2091056a2092056a2093056a2094056a2095056a2096056a2097056a2098056a2099056a209a" - "056a209b056a209c056a209d056a209e056a209f056a20a0056a20a1056a20a2056a20a3056a20a4056a20a5056a20" - "a6056a20a7056a20a8056a20a9056a20aa056a20ab056a20ac056a20ad056a20ae056a20af056a20b0056a20b1056a" - "20b2056a20b3056a20b4056a20b5056a20b6056a20b7056a20b8056a20b9056a20ba056a20bb056a20bc056a20bd05" - "6a20be056a20bf056a20c0056a20c1056a20c2056a20c3056a20c4056a20c5056a20c6056a20c7056a20c8056a20c9" - "056a20ca056a20cb056a20cc056a20cd056a20ce056a20cf056a20d0056a20d1056a20d2056a20d3056a20d4056a20" - "d5056a20d6056a20d7056a20d8056a20d9056a20da056a20db056a20dc056a20dd056a20de056a20df056a20e0056a" - "20e1056a20e2056a20e3056a20e4056a20e5056a20e6056a20e7056a20e8056a20e9056a20ea056a20eb056a20ec05" - "6a20ed056a20ee056a20ef056a20f0056a20f1056a20f2056a20f3056a20f4056a20f5056a20f6056a20f7056a20f8" - "056a20f9056a20fa056a20fb056a20fc056a20fd056a20fe056a20ff056a2080066a2081066a2082066a2083066a20" - "84066a2085066a2086066a2087066a2088066a2089066a208a066a208b066a208c066a208d066a208e066a208f066a" - "2090066a2091066a2092066a2093066a2094066a2095066a2096066a2097066a2098066a2099066a209a066a209b06" - "6a209c066a209d066a209e066a209f066a20a0066a20a1066a20a2066a20a3066a20a4066a20a5066a20a6066a20a7" - "066a20a8066a20a9066a20aa066a20ab066a20ac066a20ad066a20ae066a20af066a20b0066a20b1066a20b2066a20" - "b3066a20b4066a20b5066a20b6066a20b7066a20b8066a20b9066a20ba066a20bb066a20bc066a20bd066a20be066a" - "20bf066a20c0066a20c1066a20c2066a20c3066a20c4066a20c5066a20c6066a20c7066a20c8066a20c9066a20ca06" - "6a20cb066a20cc066a20cd066a20ce066a20cf066a20d0066a20d1066a20d2066a20d3066a20d4066a20d5066a20d6" - "066a20d7066a20d8066a20d9066a20da066a20db066a20dc066a20dd066a20de066a20df066a20e0066a20e1066a20" - "e2066a20e3066a20e4066a20e5066a20e6066a20e7066a20e8066a20e9066a20ea066a20eb066a20ec066a20ed066a" - "20ee066a20ef066a20f0066a20f1066a20f2066a20f3066a20f4066a20f5066a20f6066a20f7066a20f8066a20f906" - "6a20fa066a20fb066a20fc066a20fd066a20fe066a20ff066a2080076a2081076a2082076a2083076a2084076a2085" - "076a2086076a2087076a2088076a2089076a208a076a208b076a208c076a208d076a208e076a208f076a2090076a20" - "91076a2092076a2093076a2094076a2095076a2096076a2097076a2098076a2099076a209a076a209b076a209c076a" - "209d076a209e076a209f076a20a0076a20a1076a20a2076a20a3076a20a4076a20a5076a20a6076a20a7076a20a807" - "6a20a9076a20aa076a20ab076a20ac076a20ad076a20ae076a20af076a20b0076a20b1076a20b2076a20b3076a20b4" - "076a20b5076a20b6076a20b7076a20b8076a20b9076a20ba076a20bb076a20bc076a20bd076a20be076a20bf076a20" - "c0076a20c1076a20c2076a20c3076a20c4076a20c5076a20c6076a20c7076a20c8076a20c9076a20ca076a20cb076a" - "20cc076a20cd076a20ce076a20cf076a20d0076a20d1076a20d2076a20d3076a20d4076a20d5076a20d6076a20d707" - "6a20d8076a20d9076a20da076a20db076a20dc076a20dd076a20de076a20df076a20e0076a20e1076a20e2076a20e3" - "076a20e4076a20e5076a20e6076a20e7076a20e8076a0b007f0970726f647563657273010c70726f6365737365642d" - "62790105636c616e675f31392e312e352d776173692d73646b202868747470733a2f2f6769746875622e636f6d2f6c" - "6c766d2f6c6c766d2d70726f6a65637420616234623561326462353832393538616631656533303861373930636664" - "623432626432343732302900490f7461726765745f6665617475726573042b0f6d757461626c652d676c6f62616c73" - "2b087369676e2d6578742b0f7265666572656e63652d74797065732b0a6d756c746976616c7565"; - -extern std::string const kOpcReservedHex = - "0061736d010000000105016000017f03030200000404017000010503010001060b027f0141000b7e0142000b071401" - "10616c6c5f696e737472756374696f6e7300010907010041000b01000a53020400412a0b4c02017f017e0101010101" - "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" - "01010101010101010101010101010101410b0b0b0a010041000b0474657374"; - -extern std::string const kImpExpHex = - "0061736d0100000001100360027f7f017f6000017f60017f017f02330203656e760e6765745f6c65646765725f7371" - "6e000003656e76166765745f706172656e745f6c65646765725f686173680000030403010201050301000107310406" - "6d656d6f72790200096578705f66756e63310002096578705f66756e633200030c746573745f696d706f7274730004" - "0a2b03040041010b0700200041026c0b1c01027f4120410410001a41202802002100410041201001210120000b"; - -extern std::string const kUpdateDataWasmHex = - "0061736d01000000010e0360027f7f017f6000006000017f02100103656e76087365745f6461746100000303020102" - "0503010002063f0a7f01419088040b7f004180080b7f004185080b7f004190080b7f00419088040b7f004180080b7f" - "00419088040b7f00418080080b7f0041000b7f0041010b07b1010c066d656d6f72790200115f5f7761736d5f63616c" - "6c5f63746f727300010d657363726f775f66696e69736800020c5f5f64736f5f68616e646c6503010a5f5f64617461" - "5f656e6403020b5f5f737461636b5f6c6f7703030c5f5f737461636b5f6869676803040d5f5f676c6f62616c5f6261" - "736503050b5f5f686561705f6261736503060a5f5f686561705f656e6403070d5f5f6d656d6f72795f626173650308" - "0c5f5f7461626c655f6261736503090a3f0202000b3a01017f230041106b220024002000410c6a4184082d00003a00" - "002000418008280000360208200041086a410410001a200041106a240041807e0b0b0b01004180080b044461746100" - "7f0970726f647563657273010c70726f6365737365642d62790105636c616e675f31392e312e352d776173692d7364" - "6b202868747470733a2f2f6769746875622e636f6d2f6c6c766d2f6c6c766d2d70726f6a6563742061623462356132" - "6462353832393538616631656533303861373930636664623432626432343732302900490f7461726765745f666561" - "7475726573042b0f6d757461626c652d676c6f62616c732b087369676e2d6578742b0f7265666572656e63652d7479" - "7065732b0a6d756c746976616c7565"; diff --git a/src/test/app/wasm_fixtures/fixtures.h b/src/test/app/wasm_fixtures/fixtures.h deleted file mode 100644 index 1393868d7b..0000000000 --- a/src/test/app/wasm_fixtures/fixtures.h +++ /dev/null @@ -1,155 +0,0 @@ -#pragma once - -#include -#include -#include - -// WASM binary format constants and helpers for building test modules -namespace wasm_constants { - -// Magic + version header -uint8_t const kWasmHeader[] = { - 0x00, - 0x61, - 0x73, - 0x6d, // magic: \0asm - 0x01, - 0x00, - 0x00, - 0x00 // version: 1 -}; - -// Type section: () -> () -uint8_t const kTypeEmptyFunc[] = {0x01, 0x04, 0x01, 0x60, 0x00, 0x00}; - -// Function section: one function using type 0 -uint8_t const kFuncTypE0[] = {0x03, 0x02, 0x01, 0x00}; - -// Export section: export func 0 as "escrow_finish" -uint8_t const kExportFinish[] = { - 0x07, - 0x11, - 0x01, - 0x0d, - 'e', - 's', - 'c', - 'r', - 'o', - 'w', - '_', - 'f', - 'i', - 'n', - 'i', - 's', - 'h', - 0x00, - 0x00}; - -// Empty function body: 0 locals, end -uint8_t const kEmptyBody[] = {0x00, 0x0b}; - -// Data segment offset: i32.const 0, end -uint8_t const kDataOffsetZero[] = {0x41, 0x00, 0x0b}; - -// Section IDs -uint8_t const kSectionMemory = 0x05; -uint8_t const kSectionCode = 0x0a; -uint8_t const kSectionData = 0x0b; - -// Instructions -uint8_t const kInstrNop = 0x01; -uint8_t const kInstrEnd = 0x0b; - -// Fill byte for data section bloat -uint8_t const kDataFillByte = 0xEE; - -// Generator for WASM module with large code section (many NOPs) -std::vector -generateCodeBlob(uint32_t numInstructions); - -// Generator for WASM module with large data section -std::vector -generateDataBlob(uint32_t dataSize); - -} // namespace wasm_constants - -extern std::string const kLedgerSqnWasmHex; -extern std::string const kAllHostFunctionsWasmHex; -extern std::string const kAllKeyletsWasmHex; -extern std::string const kCodecovTestsWasmHex; - -extern std::string const kFibWasmHex; - -extern std::string const kFloatTestsWasmHex; -extern std::string const kFloat0Hex; -extern std::string const kDisabledFloatHex; - -extern std::string const kMemoryPointerAtLimitHex; -extern std::string const kMemoryPointerOverLimitHex; -extern std::string const kMemoryOffsetOverLimitHex; -extern std::string const kMemoryEndOfWordOverLimitHex; -extern std::string const kMemoryGrow0To1PageHex; -extern std::string const kMemoryGrow1To0PageHex; -extern std::string const kMemoryLastByteOf8MbHex; -extern std::string const kMemoryGrow1MoreThan8MbHex; -extern std::string const kMemoryGrow0MoreThan8MbHex; -extern std::string const kMemoryInit1MoreThan8MbHex; -extern std::string const kMemoryNegativeAddressHex; - -extern std::string const kTable64ElementsHex; -extern std::string const kTable65ElementsHex; -extern std::string const kTable2TablesHex; -extern std::string const kTable0ElementsHex; -extern std::string const kTableUintMaxHex; - -extern std::string const kProposalMutableGlobalHex; -extern std::string const kProposalGcStructNewHex; -extern std::string const kProposalMultiValueHex; -extern std::string const kProposalSignExtHex; -extern std::string const kProposalFloatToIntHex; -extern std::string const kProposalBulkMemoryHex; -extern std::string const kProposalRefTypesHex; -extern std::string const kProposalTailCallHex; -extern std::string const kProposalExtendedConstHex; -extern std::string const kProposalMultiMemoryHex; -extern std::string const kProposalCustomPageSizesHex; -extern std::string const kProposalMemory64Hex; -extern std::string const kProposalWideArithmeticHex; - -extern std::string const kTrapDivideBy0Hex; -extern std::string const kTrapIntOverflowHex; -extern std::string const kTrapUnreachableHex; -extern std::string const kTrapNullCallHex; -extern std::string const kTrapFuncSigMismatchHex; - -extern std::string const kWasiGetTimeHex; -extern std::string const kWasiPrintHex; - -extern std::string const kBadMagicNumberHex; -extern std::string const kBadVersionNumberHex; -extern std::string const kLyingHeaderHex; -extern std::string const kNeverEndingNumberHex; -extern std::string const kVectorLieHex; -extern std::string const kSectionOrderingHex; -extern std::string const kGhostPayloadHex; -extern std::string const kJunkAfterSectionHex; -extern std::string const kInvalidSectionIdHex; -extern std::string const kLocalVariableBombHex; - -extern std::string const kDeepRecursionHex; -extern std::string const kInfiniteLoopWasmHex; -extern std::string const kStartLoopHex; - -extern std::string const kBadAlignWasmHex; - -extern std::string const kThousandParamsHex; -extern std::string const kThousand1ParamsHex; -extern std::string const kLocals10kHex; -extern std::string const kFunctions5kHex; - -extern std::string const kOpcReservedHex; - -extern std::string const kImpExpHex; -extern std::string const kUpdateDataWasmHex; diff --git a/src/test/app/wasm_fixtures/updateData.c b/src/test/app/wasm_fixtures/updateData.c deleted file mode 100644 index 6eb70666b9..0000000000 --- a/src/test/app/wasm_fixtures/updateData.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -int32_t set_data(uint8_t const *, int32_t); - -int escrow_finish() -{ - uint8_t buf[] = "Data"; - set_data(buf, sizeof(buf) - 1); - - return -256; -} diff --git a/src/tests/libxrpl/helpers/TestServiceRegistry.h b/src/tests/libxrpl/helpers/TestServiceRegistry.h index 9527827e34..451e47bc24 100644 --- a/src/tests/libxrpl/helpers/TestServiceRegistry.h +++ b/src/tests/libxrpl/helpers/TestServiceRegistry.h @@ -179,6 +179,17 @@ private: */ class TestServiceRegistry : public ServiceRegistry { +public: + /** + * @brief The fee settings a test environment starts with. + * + * Public and static because `TxTest` seeds its **genesis ledger** from the same values. + * The two have to agree: a transactor reads its limits from the registry + * (`EscrowCreate` checks `bytecodeSizeLimit` via `ctx.registry.get().getFees()`) but + * `Transactor::calculateBaseFee` reads `view.fees()`. Seeding them separately once left + * `gasPrice` at 1'000'000 in the registry and 0 in the view, which silently collapsed + * `EscrowFinish`'s gas-allowance fee to a single drop. + */ static Fees defaultFees() { @@ -189,6 +200,7 @@ class TestServiceRegistry : public ServiceRegistry return fees; } +private: TestLogs logs_{beast::Severity::Warning}; boost::asio::io_context ioContext_; TestFamily family_{logs_.journal("TestFamily")}; @@ -500,6 +512,26 @@ public: return fees_; } + /** + * @brief Override the fee settings the transactors see. + * + * For tests about a limit rather than about a transaction: `EscrowCreate` screens + * `sfBytecode` against `bytecodeSizeLimit` from here, so a size test sets it directly + * instead of standing up fee voting. + * + * @note This writes the `Fees` fields directly and so is **not** bounded by + * `kMaxBytecodeSizeLimit` / `kMaxGasLimit`, which only constrain config parsing + * (`Config.cpp`) and `FeeVoteImpl`. Do not use it to test behaviour above those + * ceilings: no ledger can reach such a configuration, so any expectation set there + * is unfalsifiable in production. Prefer `TxTest`'s constructor when the whole + * environment wants one fee set, so the view and the registry stay in step. + */ + void + setFees(Fees const& fees) + { + fees_ = fees; + } + // Temporary: Get the underlying Application Application& getApp() override diff --git a/src/tests/libxrpl/helpers/TxTest.cpp b/src/tests/libxrpl/helpers/TxTest.cpp index 4b4f407eeb..3305414b8a 100644 --- a/src/tests/libxrpl/helpers/TxTest.cpp +++ b/src/tests/libxrpl/helpers/TxTest.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -24,6 +26,7 @@ #include #include +#include #include #include @@ -59,7 +62,7 @@ allFeatures() // TxTest //------------------------------------------------------------------------------ -TxTest::TxTest(std::optional features) +TxTest::TxTest(std::optional features, std::optional feesOverride) { // Convert FeatureBitset to unordered_set for Rules constructor auto const featureBits = features.value_or(allFeatures()); @@ -68,8 +71,9 @@ TxTest::TxTest(std::optional features) // Create rules with the specified features rules_.emplace(featureSet_); - // Default fees for testing - Fees const fees{XRPAmount{10}, XRPAmount{10000000}, XRPAmount{2000000}}; + // One fee set for both the view and the registry — see the constructor's doc comment. + Fees const fees = feesOverride.value_or(TestServiceRegistry::defaultFees()); + registry_.setFees(fees); // Create a genesis ledger as the base closedLedger_ = std::make_shared( @@ -155,6 +159,18 @@ TxTest::getAccountRoot(AccountID const& id) const return ledger_entries::AccountRoot{std::const_pointer_cast(sle)}; } +std::uint32_t +TxTest::getOwnerCount(AccountID const& id) const +{ + return getAccountRoot(id).getOwnerCount(); +} + +XRPAmount +TxTest::getXrpBalance(AccountID const& id) const +{ + return getAccountRoot(id).getBalance().xrp(); +} + OpenView& TxTest::getOpenLedger() { @@ -194,6 +210,7 @@ TxTest::close() for (auto const& tx : pendingTxs_) txSet.insert(tx); + closedMetadata_.clear(); { OpenView accum(&*newLedger); for (auto const& [key, tx] : txSet) @@ -203,6 +220,9 @@ TxTest::close() { throw std::runtime_error("TxTest::close: failed to apply transaction"); } + // `accum` is not an open view, so this is the apply that produces metadata. + if (result.metadata.has_value()) + closedMetadata_.emplace(tx->getTransactionID(), *std::move(result).metadata); } accum.apply(*newLedger); } @@ -218,6 +238,15 @@ TxTest::close() std::make_shared(kOpenLedger, closedLedger_.get(), *rules_, closedLedger_); } +std::optional +TxTest::getMetadata(uint256 const& txId) const +{ + auto const it = closedMetadata_.find(txId); + if (it == closedMetadata_.end()) + return std::nullopt; + return it->second; +} + void TxTest::advanceTime(NetClock::duration duration) { diff --git a/src/tests/libxrpl/helpers/TxTest.h b/src/tests/libxrpl/helpers/TxTest.h index 98198e45f8..7d8d2425f3 100644 --- a/src/tests/libxrpl/helpers/TxTest.h +++ b/src/tests/libxrpl/helpers/TxTest.h @@ -4,12 +4,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -191,8 +192,16 @@ public: * * @param features Optional set of features to enable. If not specified, * uses all testable amendments. + * @param fees Optional fee settings. If not specified, uses + * `TestServiceRegistry::defaultFees()`. Applied to **both** the genesis + * ledger and the service registry, because transactors read limits from the + * registry (`ctx.registry.get().getFees()`) while `calculateBaseFee` reads + * `view.fees()` — a test whose fees disagree across the two is testing a + * state no ledger can be in. */ - explicit TxTest(std::optional features = std::nullopt); + explicit TxTest( + std::optional features = std::nullopt, + std::optional fees = std::nullopt); /** * @brief Check if a feature is enabled. @@ -241,6 +250,41 @@ public: return submit(builder.build(signer.pk(), signer.sk()).getSTTx()); } + /** + * @brief Submit a transaction from a builder, paying an explicit fee. + * + * The overload above pays a flat 10 drops, which is below what some transactions + * require: an `EscrowCreate` carrying `sfBytecode` owes `base * 10 + 5 * bytecodeBytes` + * (`EscrowCreate::calculateBaseFee`), and an `EscrowFinish` carrying `sfGas` owes the + * allowance priced at `gasPrice`. Those submissions would fail on the fee rather than on + * whatever they meant to test. + * + * @tparam T A type derived from TransactionBuilderBase. + * @param builder The transaction builder. + * @param signer The account to sign with. + * @param fee The fee to pay. + * @return TxResult containing the result code, applied status, and metadata. + */ + template + requires std:: + derived_from, transactions::TransactionBuilderBase>> + [[nodiscard]] TxResult + submit(T&& builder, Account const& signer, XRPAmount fee) + { + auto const& obj = builder.getSTObject(); + auto accountId = obj[sfAccount]; + if (!obj.isFieldPresent(sfTicketSequence)) + { + builder.setSequence(getAccountRoot(accountId).getSequence()); + } + else + { + builder.setSequence(0); + } + builder.setFee(fee); + return submit(builder.build(signer.pk(), signer.sk()).getSTTx()); + } + /** * @brief Submit a transaction to the open ledger. * @@ -281,6 +325,28 @@ public: [[nodiscard]] ledger_entries::AccountRoot getAccountRoot(AccountID const& id) const; + /** + * @brief Get an account's owner count. + * @param id The account ID. + * @return The number of ledger objects the account owns. + * @throws std::runtime_error if the account does not exist. + */ + [[nodiscard]] std::uint32_t + getOwnerCount(AccountID const& id) const; + + /** + * @brief Get an account's XRP balance. + * + * The IOU overload of `getBalance` covers trust lines; this covers the account's own + * drops, which is what a fee- or reserve-sensitive test needs to assert on. + * + * @param id The account ID. + * @return The balance in drops. + * @throws std::runtime_error if the account does not exist. + */ + [[nodiscard]] XRPAmount + getXrpBalance(AccountID const& id) const; + /** * @brief Get the current open ledger view. * @return A mutable reference to the open ledger. @@ -307,10 +373,26 @@ public: * * Creates a new closed ledger from the current open ledger. * All pending transactions are re-applied in canonical order. + * + * @note This is where transaction **metadata** comes into being: it is only built for a + * view that is not open (`ApplyStateTable::apply`), so `submit` cannot return any. + * Each closed transaction's metadata is retained for `getMetadata`. */ void close(); + /** + * @brief Get the metadata of a transaction in the most recently closed ledger. + * + * Metadata is a property of a *closed* ledger, so the sequence is submit → `close` → + * `getMetadata`. Only the latest close is retained. + * + * @param txId The transaction's ID (`TxResult::tx->getTransactionID()`). + * @return The metadata, or `std::nullopt` if that transaction was not in the last close. + */ + [[nodiscard]] std::optional + getMetadata(uint256 const& txId) const; + /** * @brief Advance time without closing the ledger. * @@ -345,9 +427,14 @@ public: /** * @brief Get the service registry. + * + * Returns the concrete test type so a test can reach its setters — `setFees` in + * particular, for the cases that need a limit to change *after* setup, which the + * constructor's `fees` parameter cannot express. + * * @return A reference to the service registry. */ - ServiceRegistry& + TestServiceRegistry& getServiceRegistry() { return registry_; @@ -365,6 +452,11 @@ private: */ std::vector> pendingTxs_; + /** + * Metadata from the most recent close, keyed by transaction ID. Replaced each close. + */ + std::map closedMetadata_; + /** * Current time (can be advanced arbitrarily for testing). */ diff --git a/src/tests/libxrpl/tx/wasm/README.md b/src/tests/libxrpl/tx/wasm/README.md index ed1621c8aa..75a25acf45 100644 --- a/src/tests/libxrpl/tx/wasm/README.md +++ b/src/tests/libxrpl/tx/wasm/README.md @@ -6,28 +6,29 @@ missing lives in a sibling layer. ## The layers -| Layer | Location | host | VM | ledger | Answers | -| ------------------------------------- | --------------------------------------------------- | ---- | --- | ------ | ----------------------------------------------------------------------------------- | -| Engine / gas / limits / ABI | `crates/xrpl-wasm-vm`, `crates/xrpl-host-functions` | mock | ✓ | ✗ | gas, transfer budget, memory/field limits, preflight, VM limits, generated ABI | -| `host_context/` (`HostContextTest`) | `.../host_context` | mock | ✗ | ✗ | the `HostContext` marshalling shim alone (byte order, buffer sizing, `SField` xlat) | -| `host_calls/` (`HostCallTest`) | `.../host_calls` | mock | ✓ | ✗ | per-function **wire contract** — what the host was asked, what came back | -| `host_functions/` (`RealHostFixture`) | `.../host_functions` | real | ✗ | real | each function's **actual answer** vs. a real `TxTest` ledger | -| `e2e/` (`RealVmTest`) | `.../e2e` | real | ✓ | real | **full-stack integration** — VM + `HostContext` + real impl + real ledger | +| Layer | Location | host | VM | ledger | Answers | +| ------------------------------------- | --------------------------------------------------- | ---- | --- | ------ | ---------------------------------------------------------------------------------------- | +| Engine / gas / limits / ABI | `crates/xrpl-wasm-vm`, `crates/xrpl-host-functions` | mock | ✓ | ✗ | gas, transfer budget, memory/field limits, preflight, VM limits, generated ABI | +| `host_context/` (`HostContextTest`) | `.../host_context` | mock | ✗ | ✗ | the `HostContext` marshalling shim alone (byte order, buffer sizing, `SField` xlat) | +| `host_calls/` (`HostCallTest`) | `.../host_calls` | mock | ✓ | ✗ | per-function **wire contract** — what the host was asked, what came back | +| `host_functions/` (`RealHostFixture`) | `.../host_functions` | real | ✗ | real | each function's **actual answer** vs. a real `TxTest` ledger | +| `e2e/` (`RealVmTest`) | `.../e2e` | real | ✓ | real | **full-stack integration** — VM + `HostContext` + real impl + real ledger | +| `transactor/` (`TxTest`) | `.../transactor` | real | ✓ | real | the **transactor** around a contract — fees, reserves, limits, what each failure reports | Run the C++ side with: ```bash -./build/xrpl_tests --gtest_filter='*Impl.*:*Call.*:*E2e.*:WasmVMTest.*:WasmVMDeathTest.*:PreflightTest.*' +./build/xrpl_tests --gtest_filter='*Impl.*:*Call.*:*E2e.*:WasmVMTest.*:WasmVMDeathTest.*:PreflightTest.*:BytecodeSize.*:BytecodePreflight.*:FinishFailures.*:BytecodeRun.*:GasFees.*:DataOnReject.*' ``` -(707 tests, 136 suites.) The engine-level coverage is Rust: `cd crates && cargo test`. +(744 tests, 142 suites.) The engine-level coverage is Rust: `cd crates && cargo test`. ## `fixtures/` — split by whether it needs a test framework -| | | -| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **No GTest** — the `xrpl.testkit.wasm` library | `WasmLedger` (real genesis ledger + the real host over it), `WasmRun` (WAT assembler), `NftSetup`, `FloatConstants` | -| **GTest** → `xrpl_tests` | `RealHostFixture` (`: testing::Test, WasmLedger` + `expectValue`/`expectError`/`expectKeyletMatches`), `FloatFixture`, `NFTFixture`, `MockHostFunctions`, `WasmFixture`, `RealVmTest`, `HostContextFixture` | +| | | +| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **No GTest** — the `xrpl.testkit.wasm` library | `WasmLedger` (real genesis ledger + the real host over it), `WasmRun` (WAT assembler), `NftSetup`, `FloatConstants` | +| **GTest** → `xrpl_tests` | `RealHostFixture` (`: testing::Test, WasmLedger` + `expectValue`/`expectError`/`expectKeyletMatches`), `FloatFixture`, `NFTFixture`, `MockHostFunctions`, `WasmFixture`, `RealVmTest`, `HostContextFixture`, `EscrowWasm` (transactor contracts + fee arithmetic), `ModuleBuilder` | A benchmark wants a ledger and a host, not GTest's lifecycle. Both binaries link the library; `xrpl.bench.wasm` links no GTest and no GMock at all. @@ -83,8 +84,18 @@ against the same spec. That would not catch a drift where both diverge on an amb closing it needs a **cross-repo integration test** (compiled guests against a real host) in CI where the Rust→wasm toolchain exists. -**Transactor-level (L5) tests** are deferred: the redesign does not yet wire `runEscrowWasm` into -the `EscrowFinish` transactor, so there is no caller under `src/xrpld`. When it is wired, these -need a home as C++ transactor tests over a real `Env` — `set_data` persistence (including on -`tecBYTECODE_REJECTED`), `sfGasUsed` / `sfVMReturnCode` in transaction metadata, and owner-reserve -accounting for a bytecode-bearing escrow. The layers here deliberately stop at the VM boundary. +**Transactor-level (L5) tests** now live in `transactor/`, over `TxTest` — which runs the real +pipeline (preflight → preclaim → doApply → invariants) without needing an `Application`. They +cover what the earlier `EscrowSmart_test.cpp` did on Beast: `set_data` persistence through a +`tecBYTECODE_REJECTED`, `sfGasUsed` / `sfVMReturnCode` in metadata, owner-reserve accounting for +a bytecode-bearing escrow, the `bytecodeSizeLimit` boundary, and the gas-allowance fee. + +Two things to know before adding to that folder: + +- **Metadata only exists after `close()`.** `ApplyStateTable::apply` builds it for a view that is + not open, so `TxResult::metadata` from `submit` is always `nullopt`. The idiom is submit → + `close()` → `TxTest::getMetadata(txId)`. +- **Fees live in two places and must agree.** A transactor reads its limits from the service + registry (`ctx.registry.get().getFees()`), while `calculateBaseFee` reads `view.fees()`. Pass a + `Fees` to `TxTest`'s constructor to set both; reach for `getServiceRegistry().setFees` only when + a limit has to change _after_ setup. diff --git a/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.cpp b/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.cpp new file mode 100644 index 0000000000..0157e13998 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.cpp @@ -0,0 +1,49 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include + +namespace xrpl::test { + +std::string +gatedOnLedgerSqn(std::uint32_t threshold) +{ + return std::format( + R"wat( +(module + (import "host_lib" "ldgr_index" (func $ldgr_index (param i32 i32) (result i32))) + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (drop (call $ldgr_index (i32.const 0) (i32.const 4))) + (if (result i32) (i32.ge_u (i32.load (i32.const 0)) (i32.const {})) + (then (i32.const 5)) + (else (i32.const 0))))) +)wat", + threshold); +} + +XRPAmount +escrowCreateFee(TxTest const& env, Bytes const& bytecode) +{ + return (env.getOpenLedger().fees().base * 10) + + XRPAmount{static_cast(bytecode.size()) * 5}; +} + +XRPAmount +escrowFinishFee(TxTest const& env, std::uint32_t allowance) +{ + auto const& fees = env.getOpenLedger().fees(); + // Integer division rounds down, so the transactor adds one drop; match it exactly or + // the submission fails on the fee rather than on what it meant to test. + auto const gasFee = ((std::uint64_t{allowance} * fees.gasPrice) / microDropsPerDrop) + 1; + return fees.base + XRPAmount{static_cast(gasFee)}; +} + +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.h b/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.h new file mode 100644 index 0000000000..7636721f5c --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/fixtures/EscrowWasm.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace xrpl::test { + +// Contracts and fee arithmetic shared by the transactor-level escrow tests. +// +// The contracts are WAT rather than compiled hex on purpose. The suite this replaced +// shipped hex built from C by an external toolchain, and when the engine moved to Rust and +// began serving host functions from `host_lib` instead of `env`, every one of those +// fixtures started failing import screening — with no way to regenerate them short of +// installing a wasi-sdk. Text assembles here, so an ABI change is a one-line edit. + +// Reads the ledger sequence and returns 5. A minimal *working* contract: it makes a real +// host call, so it exercises more than validation, but what it returns is uninteresting. +inline constexpr auto kReadsLedgerSqn = std::string_view{R"wat( +(module + (import "host_lib" "ldgr_index" (func $ldgr_index (param i32 i32) (result i32))) + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (drop (call $ldgr_index (i32.const 0) (i32.const 4))) + (i32.const 5))) +)wat"}; + +// Returns 0, which `EscrowFinish` reads as a contract-defined rejection. +inline constexpr auto kRejects = std::string_view{R"wat( +(module + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (i32.const 0))) +)wat"}; + +// Traps. A fault rather than a rejection: no return code, and nothing it wrote survives. +inline constexpr auto kTraps = std::string_view{R"wat( +(module + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (unreachable))) +)wat"}; + +// Loops forever, so the only way it stops is by exhausting its gas allowance. +inline constexpr auto kLoopsForever = std::string_view{R"wat( +(module + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (loop $forever (br $forever)) + (i32.const 1))) +)wat"}; + +// Imports a host function that does not exist, so screening refuses it. Well-formed wasm — +// the refusal is about the import list, not the bytes. +inline constexpr auto kImportsUnknownHostFunction = std::string_view{R"wat( +(module + (import "host_lib" "bad" (func $bad (result i32))) + (memory (export "memory") 1) + (func (export "escrow_finish") (result i32) + (call $bad))) +)wat"}; + +// A contract that approves only once the ledger has reached `threshold`: returns 5 at or +// past it, 0 (a rejection) before. +// +// The escrow's release condition is thus a real predicate over ledger state that changes +// from false to true while the escrow sits there — the shape the whole feature exists for, +// and the one a fixed contract cannot express. Built at runtime because the threshold has +// to be chosen relative to the environment's current sequence. +std::string +gatedOnLedgerSqn(std::uint32_t threshold); + +// What an `EscrowCreate` carrying this bytecode must pay: ten base fees plus five drops a +// byte (`EscrowCreate::calculateBaseFee`). +XRPAmount +escrowCreateFee(TxTest const& env, Bytes const& bytecode); + +// What an `EscrowFinish` carrying this gas allowance must pay: the base fee plus the +// allowance priced at `gasPrice`, rounded up (`EscrowFinish::calculateBaseFee`). +XRPAmount +escrowFinishFee(TxTest const& env, std::uint32_t allowance); + +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.cpp b/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.cpp new file mode 100644 index 0000000000..a8034fc016 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.cpp @@ -0,0 +1,175 @@ +#include + +#include +#include + +#include +#include + +namespace xrpl::test { +namespace { + +// Section ids, from the binary format's fixed table. +constexpr std::uint8_t kSectionType = 0x01; +constexpr std::uint8_t kSectionFunction = 0x03; +constexpr std::uint8_t kSectionMemory = 0x05; +constexpr std::uint8_t kSectionExport = 0x07; +constexpr std::uint8_t kSectionCode = 0x0A; +constexpr std::uint8_t kSectionData = 0x0B; + +constexpr std::uint8_t kOpcodeNop = 0x01; +constexpr std::uint8_t kOpcodeEnd = 0x0B; +constexpr std::uint8_t kOpcodeI32Const = 0x41; + +constexpr std::uint8_t kTypeI32 = 0x7F; +constexpr std::uint8_t kTypeFunc = 0x60; + +constexpr std::uint32_t kPageBytes = 65'536; + +// Anything that isn't obviously zero-filled is 0xEE, so a dump of a failing module shows at +// a glance which bytes are padding. +constexpr std::uint8_t kDataFillByte = 0xEE; + +void +appendU32Leb(Bytes& out, std::uint32_t value) +{ + do + { + auto byte = static_cast(value & 0x7F); + value >>= 7; + if (value != 0U) + byte |= 0x80; + out.push_back(byte); + } while (value != 0U); +} + +void +appendSection(Bytes& out, std::uint8_t section, Bytes const& payload) +{ + out.push_back(section); + appendU32Leb(out, static_cast(payload.size())); + out.insert(out.end(), payload.begin(), payload.end()); +} + +// A function body: no locals, `code`, `end` — prefixed by its own byte length. +void +appendBody(Bytes& out, Bytes const& code) +{ + auto body = Bytes{0x00}; // local declaration count + body.insert(body.end(), code.begin(), code.end()); + body.push_back(kOpcodeEnd); + + appendU32Leb(out, static_cast(body.size())); + out.insert(out.end(), body.begin(), body.end()); +} + +Bytes +header() +{ + return Bytes{0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00}; // "\0asm", version 1 +} + +// Two types: `() -> ()` for filler functions, `() -> i32` for the entry point. +constexpr std::uint8_t kTypeVoid = 0; +constexpr std::uint8_t kTypeReturnsI32 = 1; + +void +appendTypeSection(Bytes& out) +{ + auto payload = Bytes{0x02}; // two types + payload.insert(payload.end(), {kTypeFunc, 0x00, 0x00}); + payload.insert(payload.end(), {kTypeFunc, 0x00, 0x01, kTypeI32}); + appendSection(out, kSectionType, payload); +} + +// `fillerCount` functions of type `() -> ()`, then the entry point of type `() -> i32`. +void +appendFunctionSection(Bytes& out, std::uint32_t fillerCount) +{ + auto payload = Bytes{}; + appendU32Leb(payload, fillerCount + 1); + payload.insert(payload.end(), fillerCount, kTypeVoid); + payload.push_back(kTypeReturnsI32); + appendSection(out, kSectionFunction, payload); +} + +// Export the entry point, which is the last function declared. +void +appendExportSection(Bytes& out, std::uint32_t fillerCount, bool exportMemory) +{ + auto payload = Bytes{}; + appendU32Leb(payload, exportMemory ? 2 : 1); + + if (exportMemory) + { + static constexpr auto kMemory = std::string_view{"memory"}; + appendU32Leb(payload, static_cast(kMemory.size())); + payload.insert(payload.end(), kMemory.begin(), kMemory.end()); + payload.push_back(0x02); // export kind: memory + payload.push_back(0x00); // memory index + } + + appendU32Leb(payload, static_cast(escrowFunctionName.size())); + payload.insert(payload.end(), escrowFunctionName.begin(), escrowFunctionName.end()); + payload.push_back(0x00); // export kind: function + appendU32Leb(payload, fillerCount); + + appendSection(out, kSectionExport, payload); +} + +// `i32.const 1` — a completed run that the transactor reads as success. +Bytes +entryPointCode() +{ + return Bytes{kOpcodeI32Const, 0x01}; +} + +} // namespace + +Bytes +codeHeavyModule(std::uint32_t instructionCount) +{ + // One filler function holding every `nop`, plus the entry point. + constexpr std::uint32_t kFillerCount = 1; + + auto out = header(); + appendTypeSection(out); + appendFunctionSection(out, kFillerCount); + appendExportSection(out, kFillerCount, /*exportMemory*/ false); + + auto codePayload = Bytes{}; + appendU32Leb(codePayload, kFillerCount + 1); + appendBody(codePayload, Bytes(instructionCount, kOpcodeNop)); + appendBody(codePayload, entryPointCode()); + + appendSection(out, kSectionCode, codePayload); + return out; +} + +Bytes +dataHeavyModule(std::uint32_t dataBytes) +{ + auto out = header(); + appendTypeSection(out); + appendFunctionSection(out, /*fillerCount*/ 0); + + auto memoryPayload = Bytes{0x01, 0x00}; // one memory, minimum-only limits + appendU32Leb(memoryPayload, (dataBytes + kPageBytes - 1) / kPageBytes); + appendSection(out, kSectionMemory, memoryPayload); + + appendExportSection(out, /*fillerCount*/ 0, /*exportMemory*/ true); + + auto codePayload = Bytes{0x01}; // one function body + appendBody(codePayload, entryPointCode()); + appendSection(out, kSectionCode, codePayload); + + auto dataPayload = Bytes{0x01, 0x00}; // one segment, memory 0 + dataPayload.insert(dataPayload.end(), {kOpcodeI32Const, 0x00, kOpcodeEnd}); // offset 0 + appendU32Leb(dataPayload, dataBytes); + dataPayload.insert(dataPayload.end(), dataBytes, kDataFillByte); + appendSection(out, kSectionData, dataPayload); + + return out; +} + +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.h b/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.h new file mode 100644 index 0000000000..90cae42b97 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/fixtures/ModuleBuilder.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include + +namespace xrpl::test { + +// Modules built to a *byte size* rather than to a behaviour. +// +// Everything else in this tree writes WAT, which is the right default: it says what the +// contract does. These two say only how big it is, for the transactor's `bytecodeSizeLimit` +// screening, where the boundary cases sit five bytes apart (99'950 accepted, 99'955 +// refused). Assembling text cannot hit a byte count on the nose, and the WAT for a +// hundred thousand `nop`s would be a ~500 KB string, so these emit the binary directly. +// +// Both produce a module that *passes preflight* when it is under the size limit: a real +// `escrow_finish` exported with type `() -> i32`. That is not incidental — screening +// checks the entry point's signature (`PreflightTest.EntryPointOfTheWrongTypeIsRefused`), +// so a module that got it wrong would be refused for that reason at every size and the +// sweep would measure nothing. + +// A module of `instructionCount` `nop`s in a single function, doing nothing. +// +// One function however large, deliberately. wasmparser defines +// `MAX_WASM_FUNCTION_SIZE` = 128 KiB, but nothing on this path enforces it: a single body +// of a million instructions preflights clean (pinned by +// `BytecodeSize.ASingleFunctionBodyIsNotSeparatelyCapped`). So there is no second limit to +// design around, and splitting the `nop`s across functions would only obscure that. +// +// The returned module is a few dozen bytes larger than `instructionCount` (the sections +// around the code). Callers that care about an exact total should measure `.size()` rather +// than assume it. +Bytes +codeHeavyModule(std::uint32_t instructionCount); + +// A module carrying `dataBytes` bytes in a data segment, with memory declared to fit. +// +// The size lands in a data section rather than a code section, so the two builders +// together separate "large because there is a lot to translate" from "large because there +// is a lot to copy". +Bytes +dataHeavyModule(std::uint32_t dataBytes); + +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/BytecodePreflight.cpp b/src/tests/libxrpl/tx/wasm/transactor/BytecodePreflight.cpp new file mode 100644 index 0000000000..02f9dc6df1 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/BytecodePreflight.cpp @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace xrpl::test { +namespace { + +// What `EscrowCreate` refuses before a contract ever runs. Everything here is decided in +// preflight, so the shape of the transaction is the whole subject: no ledger state matters +// beyond the account existing. +struct BytecodePreflight : testing::Test +{ + Account const alice{"alice"}; + Account const carol{"carol"}; + + // Deadlines are relative to the environment's close time, which starts at genesis. + static std::uint32_t + after(TxTest const& env, std::uint32_t seconds) + { + return static_cast(env.getCloseTime().time_since_epoch().count()) + seconds; + } + + // An `EscrowCreate` with everything a valid one needs, for callers to spoil one field at + // a time. `cancelAfter` is set because without an expiry the transaction is refused for + // that reason first, and every bytecode case would report `temBAD_EXPIRATION` instead of + // what it meant to check. + transactions::EscrowCreateBuilder + escrowCreate(TxTest const& env, Bytes const& bytecode) + { + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(500)}}; + builder.setBytecode(makeSlice(bytecode)); + builder.setCancelAfter(after(env, 100)); + return builder; + } +}; + +TEST_F(BytecodePreflight, BytecodeIsRefusedWhileSmartEscrowIsDisabled) +{ + TxTest env{allFeatures() - featureSmartEscrow}; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + auto const fee = escrowCreateFee(env, wasm); + + EXPECT_EQ(env.submit(escrowCreate(env, wasm), alice, fee).ter, temDISABLED); + + // Also with a data field, which is the other half of the feature's surface. + auto builder = escrowCreate(env, wasm); + builder.setData(makeSlice(Bytes{0x00, 0x11, 0x22, 0x33})); + EXPECT_EQ(env.submit(builder, alice, fee).ter, temDISABLED); +} + +// A zero limit is how fee voting turns the runtime off, and it has to be distinguishable +// from "your contract is too big" — `temTEMP_DISABLED` says come back later, `temMALFORMED` +// says never. +TEST_F(BytecodePreflight, AZeroSizeLimitDisablesUploadsRatherThanRejectingThem) +{ + auto fees = TestServiceRegistry::defaultFees(); + fees.bytecodeSizeLimit = 0; + TxTest env{std::nullopt, fees}; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + EXPECT_EQ( + env.submit(escrowCreate(env, wasm), alice, escrowCreateFee(env, wasm)).ter, + temTEMP_DISABLED); +} + +TEST_F(BytecodePreflight, AZeroGasLimitDisablesUploads) +{ + auto fees = TestServiceRegistry::defaultFees(); + fees.gasLimit = 0; + TxTest env{std::nullopt, fees}; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + EXPECT_EQ( + env.submit(escrowCreate(env, wasm), alice, escrowCreateFee(env, wasm)).ter, + temTEMP_DISABLED); +} + +TEST_F(BytecodePreflight, EmptyBytecodeIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + EXPECT_EQ( + env.submit(escrowCreate(env, Bytes{}), alice, escrowCreateFee(env, Bytes{})).ter, + temMALFORMED); +} + +// Screening reaches into the module: this one is structurally valid wasm that asks for a +// host function nobody serves. +TEST_F(BytecodePreflight, BytecodeImportingAnUnknownHostFunctionIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kImportsUnknownHostFunction); + EXPECT_EQ( + env.submit(escrowCreate(env, wasm), alice, escrowCreateFee(env, wasm)).ter, + temINVALID_BYTECODE); +} + +TEST_F(BytecodePreflight, DataWithoutBytecodeIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(500)}}; + builder.setData(makeSlice(Bytes{0x41, 0x41, 0x41, 0x41})); + builder.setCancelAfter(after(env, 100)); + + EXPECT_EQ(env.submit(builder, alice, XRPAmount{100'000}).ter, temMALFORMED); +} + +TEST_F(BytecodePreflight, DataPastItsMaximumIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + auto builder = escrowCreate(env, wasm); + builder.setData(makeSlice(Bytes(kMaxWasmDataLength + 1, 0x42))); + + EXPECT_EQ(env.submit(builder, alice, XRPAmount{100'000}).ter, temMALFORMED); +} + +// A contract needs a deadline. Without `CancelAfter` the escrow could never be reclaimed if +// the contract never approves, so every combination lacking it is refused — including the +// ones that look complete because they carry a `FinishAfter` or a condition. +TEST_F(BytecodePreflight, BytecodeWithoutACancelTimeIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + auto const fee = escrowCreateFee(env, wasm); + + auto bare = [&] { + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(500)}}; + builder.setBytecode(makeSlice(wasm)); + return builder; + }; + + EXPECT_EQ(env.submit(bare(), alice, fee).ter, temBAD_EXPIRATION); + + auto withFinish = bare(); + withFinish.setFinishAfter(after(env, 2)); + EXPECT_EQ(env.submit(withFinish, alice, fee).ter, temBAD_EXPIRATION); +} + +// The success side, and the reason this file could not exist before: these cases need a +// module that actually passes screening, which the old compiled fixtures stopped doing. +TEST_F(BytecodePreflight, BytecodeWithACancelTimeIsAccepted) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + EXPECT_EQ( + env.submit(escrowCreate(env, wasm), alice, escrowCreateFee(env, wasm)).ter, tesSUCCESS); +} + +TEST_F(BytecodePreflight, BytecodeWithAFinishAndCancelTimeIsAccepted) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + auto builder = escrowCreate(env, wasm); + builder.setFinishAfter(after(env, 2)); + + EXPECT_EQ(env.submit(builder, alice, escrowCreateFee(env, wasm)).ter, tesSUCCESS); +} + +// The per-byte charge is enforced, not advisory. One drop short is refused — which also +// confirms the fee helper the other tests rely on is computing the real number rather than +// something merely generous. +TEST_F(BytecodePreflight, AFeeOneDropShortIsRefused) +{ + TxTest env; + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + auto const fee = escrowCreateFee(env, wasm); + + EXPECT_EQ(env.submit(escrowCreate(env, wasm), alice, fee - XRPAmount{1}).ter, telINSUF_FEE_P); +} + +} // namespace +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/BytecodeRun.cpp b/src/tests/libxrpl/tx/wasm/transactor/BytecodeRun.cpp new file mode 100644 index 0000000000..4589709b1d --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/BytecodeRun.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace xrpl::test { +namespace { + +// A contract deciding whether an escrow releases, end to end through the transactor. +// +// The other transactor files are about refusals. This one is about the feature working: a +// predicate over ledger state that is false, then true, with the escrow surviving the +// rejections and being destroyed on approval. + +constexpr std::uint32_t kAllowance = 10'000; + +// The preimage-sha256 condition/fulfillment pair the Beast suite used. Copied rather than +// shared because `src/test/jtx` is not linked here, and they are inert constants. +constexpr auto kFulfillment = std::array{{0xA0, 0x02, 0x80, 0x00}}; +constexpr auto kCondition = std::array{ + {0xA0, 0x25, 0x80, 0x20, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, + 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, + 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55, 0x81, 0x01, 0x00}}; + +struct BytecodeRun : testing::Test +{ + TxTest env; + Account const alice{"alice"}; + Account const carol{"carol"}; + + void + SetUp() override + { + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + } + + std::uint32_t + now() const + { + return static_cast(env.getCloseTime().time_since_epoch().count()); + } + + std::uint32_t + currentSeq() const + { + return env.getOpenLedger().header().seq; + } + + struct Created + { + std::uint32_t seq; + XRPAmount fee; + }; + + Created + createEscrow(Bytes const& wasm, bool withCondition = false) + { + auto const seq = env.getAccountRoot(alice).getSequence(); + + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(1'000)}}; + builder.setBytecode(makeSlice(wasm)); + builder.setCancelAfter(now() + 1'000); + if (withCondition) + builder.setCondition(makeSlice(kCondition)); + + auto const fee = escrowCreateFee(env, wasm); + EXPECT_EQ(env.submit(builder, alice, fee).ter, tesSUCCESS); + env.close(); + return Created{.seq = seq, .fee = fee}; + } + + struct Finished + { + TER ter; + std::optional meta; + }; + + [[nodiscard]] Finished + finish(std::uint32_t seq, bool withFulfillment = false) + { + auto builder = transactions::EscrowFinishBuilder{carol, alice, seq}; + builder.setGas(kAllowance); + + auto fee = escrowFinishFee(env, kAllowance); + if (withFulfillment) + { + builder.setCondition(makeSlice(kCondition)); + builder.setFulfillment(makeSlice(kFulfillment)); + fee += env.getOpenLedger().fees().base * (32 + (kFulfillment.size() / 16)); + } + + auto const result = env.submit(builder, carol, fee); + env.close(); + return Finished{.ter = result.ter, .meta = env.getMetadata(result.tx->getTransactionID())}; + } + + bool + escrowExists(std::uint32_t seq) const + { + return env.getOpenLedger().read(keylet::escrow(alice, SeqProxy::rawSequence(seq))) != + nullptr; + } +}; + +// The whole point of a programmable escrow: it refuses while its condition is false, and +// releases once the ledger makes it true — without anyone resubmitting anything different. +TEST_F(BytecodeRun, AContractRejectsUntilItsConditionHoldsThenReleases) +{ + auto const threshold = currentSeq() + 3; + auto const wasm = assembleWat(gatedOnLedgerSqn(threshold)); + auto const created = createEscrow(wasm); + + // Below the threshold: rejected, and the escrow survives to be tried again. + ASSERT_LT(currentSeq(), threshold); + auto const rejected = finish(created.seq); + EXPECT_EQ(rejected.ter, tecBYTECODE_REJECTED); + EXPECT_TRUE(escrowExists(created.seq)) << "a rejected escrow must survive"; + + ASSERT_TRUE(rejected.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + EXPECT_EQ(rejected.meta->getAsObject().getFieldI32(sfVMReturnCode), 0); + + while (currentSeq() < threshold) + env.close(); + + // At the threshold: approved, and the escrow is gone. + auto const approved = finish(created.seq); + EXPECT_EQ(approved.ter, tesSUCCESS); + EXPECT_FALSE(escrowExists(created.seq)) << "an approved escrow must be destroyed"; + + ASSERT_TRUE(approved.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const meta = approved.meta->getAsObject(); + EXPECT_EQ(meta.getFieldI32(sfVMReturnCode), 5); + EXPECT_TRUE(meta.isFieldPresent(sfGasUsed)); +} + +// The reserve a contract costs is released with it. +TEST_F(BytecodeRun, TheBytecodeReserveIsHeldWhileTheEscrowLivesAndReleasedWhenItGoes) +{ + EXPECT_EQ(env.getOwnerCount(alice), 0U); + + auto const threshold = currentSeq() + 2; + auto const wasm = assembleWat(gatedOnLedgerSqn(threshold)); + auto const created = createEscrow(wasm); + + // One increment for the escrow, plus one per 500 bytes of contract + // (`calculateAdditionalReserve`). + auto const expected = 1U + static_cast(wasm.size() / 500); + EXPECT_EQ(env.getOwnerCount(alice), expected); + + while (currentSeq() < threshold) + env.close(); + ASSERT_EQ(finish(created.seq).ter, tesSUCCESS); + + EXPECT_EQ(env.getOwnerCount(alice), 0U); +} + +// Creating a contract-bearing escrow costs the escrowed amount plus the fee, and the +// destination is untouched until it releases. +TEST_F(BytecodeRun, CreatingChargesTheAmountAndTheFee) +{ + auto const before = env.getXrpBalance(alice); + + auto const wasm = assembleWat(gatedOnLedgerSqn(currentSeq() + 2)); + auto const created = createEscrow(wasm); + + EXPECT_EQ(env.getXrpBalance(alice), before - XRP(1'000) - created.fee); + EXPECT_EQ(env.getXrpBalance(carol), XRP(5'000)); +} + +// A condition and a contract are both gates, and the condition is the outer one: without a +// fulfillment the contract is never reached, even though it would have approved. +TEST_F(BytecodeRun, AConditionIsCheckedBeforeTheContractRuns) +{ + auto const threshold = currentSeq() + 2; + auto const wasm = assembleWat(gatedOnLedgerSqn(threshold)); + auto const created = createEscrow(wasm, /*withCondition*/ true); + + while (currentSeq() < threshold) + env.close(); + + EXPECT_EQ(finish(created.seq).ter, tecCRYPTOCONDITION_ERROR); + EXPECT_TRUE(escrowExists(created.seq)); + + // With the fulfillment, both gates open. + auto const approved = finish(created.seq, /*withFulfillment*/ true); + EXPECT_EQ(approved.ter, tesSUCCESS); + EXPECT_FALSE(escrowExists(created.seq)); +} + +} // namespace +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/BytecodeSize.cpp b/src/tests/libxrpl/tx/wasm/transactor/BytecodeSize.cpp new file mode 100644 index 0000000000..bfe05ca611 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/BytecodeSize.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace xrpl::test { +namespace { + +// What a contract of a given size costs to submit: ten base fees plus five drops a byte +// (`EscrowCreate::calculateBaseFee`). Paying it exactly keeps a size test failing on the +// size rather than on the fee. +XRPAmount +createFee(TxTest const& env, Bytes const& bytecode) +{ + return (env.getOpenLedger().fees().base * 10) + + XRPAmount{static_cast(bytecode.size()) * 5}; +} + +TER +createEscrowWith(TxTest& env, Account const& account, Bytes const& bytecode) +{ + using namespace std::chrono_literals; + + auto builder = transactions::EscrowCreateBuilder{account, account, STAmount{XRP(1'000)}}; + builder.setBytecode(makeSlice(bytecode)); + builder.setCancelAfter( + static_cast(env.getCloseTime().time_since_epoch().count() + 100)); + + return env.submit(builder, account, createFee(env, bytecode)).ter; +} + +// An account rich enough for the owner reserve a large contract demands: one increment per +// 500 bytes (`calculateAdditionalReserve`), so 200 KB costs 401 increments — 802 XRP at the +// default 2 XRP increment. +Account +fundedAccount(TxTest& env) +{ + auto const alice = Account{"alice"}; + env.createAccount(alice, XRP(2'000'000)); + return alice; +} + +} // namespace + +// The transactor screens `sfBytecode` against `bytecodeSizeLimit` before the module ever +// reaches the engine. These pin that boundary, which is the one limit standing between an +// attacker-chosen module size and the *unmetered* work of compiling it: nothing charges for +// compilation, so size is the only thing bounding it. + +// The sweep's own footing: the builders have to produce something the engine accepts, or +// every "too big" result below would be indistinguishable from "malformed". +TEST(BytecodeSize, TheBuildersProduceAModuleTheEngineAccepts) +{ + TxTest env; + auto const alice = fundedAccount(env); + + EXPECT_EQ(createEscrowWith(env, alice, codeHeavyModule(1'000)), tesSUCCESS); + EXPECT_EQ(createEscrowWith(env, alice, dataHeavyModule(1'000)), tesSUCCESS); +} + +TEST(BytecodeSize, AModuleUnderTheLimitIsAccepted) +{ + TxTest env; + auto const alice = fundedAccount(env); + + auto const wasm = codeHeavyModule(90'000); + ASSERT_LT(wasm.size(), env.getOpenLedger().fees().bytecodeSizeLimit); + + EXPECT_EQ(createEscrowWith(env, alice, wasm), tesSUCCESS); +} + +TEST(BytecodeSize, AModuleOverTheLimitIsRefused) +{ + TxTest env; + auto const alice = fundedAccount(env); + + auto const wasm = codeHeavyModule(110'000); + ASSERT_GT(wasm.size(), env.getOpenLedger().fees().bytecodeSizeLimit); + + EXPECT_EQ(createEscrowWith(env, alice, wasm), temMALFORMED); +} + +// The size that counts is the module's, not the code's: a module made large by a data +// segment is screened the same way, so the limit cannot be walked around by moving the +// bulk out of the code section. +TEST(BytecodeSize, ADataSegmentCountsTowardTheLimit) +{ + TxTest env; + auto const alice = fundedAccount(env); + + auto const wasm = dataHeavyModule(110'000); + ASSERT_GT(wasm.size(), env.getOpenLedger().fees().bytecodeSizeLimit); + + EXPECT_EQ(createEscrowWith(env, alice, wasm), temMALFORMED); +} + +// The limit is a fee setting, so it moves. Raising it has to actually admit the module it +// now covers — otherwise some *other* cap is really in charge and the setting is decorative. +TEST(BytecodeSize, RaisingTheLimitAdmitsALargerModule) +{ + auto fees = TestServiceRegistry::defaultFees(); + fees.bytecodeSizeLimit = kMaxBytecodeSizeLimit; + TxTest env{std::nullopt, fees}; + auto const alice = fundedAccount(env); + + auto const wasm = codeHeavyModule(150'000); + ASSERT_GT(wasm.size(), TestServiceRegistry::defaultFees().bytecodeSizeLimit); + ASSERT_LT(wasm.size(), kMaxBytecodeSizeLimit); + + EXPECT_EQ(createEscrowWith(env, alice, wasm), tesSUCCESS); +} + +// `bytecodeSizeLimit` is the **only** thing bounding how much there is to compile. +// +// wasmparser defines `MAX_WASM_FUNCTION_SIZE` = 128 KiB, so it would be reasonable to +// assume a single function body is separately capped and that the size limit is a +// belt-and-braces second line. It is not: nothing on this path enforces that constant, and +// a lone body of a million instructions is accepted. Since compilation is unmetered — no +// gas is charged for it, and it happens once to screen the `EscrowCreate` and again on +// every `EscrowFinish` — the size limit is load-bearing on its own. +// +// If this ever starts failing, a second cap has appeared: good news, but the sweep above +// stops being the whole story and this comment is wrong. +TEST(BytecodeSize, ASingleFunctionBodyIsNotSeparatelyCapped) +{ + TxTest const env; + auto const wasm = codeHeavyModule(1'000'000); + ASSERT_GT(wasm.size(), 128U * 1024U) << "the module must exceed MAX_WASM_FUNCTION_SIZE"; + + EXPECT_EQ(preflightEscrowWasm(wasm, beast::Journal{beast::Journal::getNullSink()}), tesSUCCESS); +} + +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/DataOnReject.cpp b/src/tests/libxrpl/tx/wasm/transactor/DataOnReject.cpp new file mode 100644 index 0000000000..5a4c2dc143 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/DataOnReject.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace xrpl::test { +namespace { + +// Writes "Data" and then rejects. `set_data` stores through the host, and the `-256` return +// puts `EscrowFinish` on its `reValue <= 0` path — a contract-defined rejection, distinct +// from a fault. The escrow survives, so whether the write survives with it is the question. +constexpr auto kWritesThenRejects = std::string_view{R"wat( +(module + (import "host_lib" "set_data" (func $set_data (param i32 i32) (result i32))) + (memory (export "memory") 1) + (data (i32.const 0) "Data") + (func (export "escrow_finish") (result i32) + (drop (call $set_data (i32.const 0) (i32.const 4))) + (i32.const -256))) +)wat"}; + +constexpr std::int32_t kRejectCode = -256; + +// Enough to run the contract; the test is about persistence, not budgets. +constexpr std::uint32_t kAllowance = 100'000; + +struct DataOnReject : testing::Test +{ + TxTest env; + Account const alice{"alice"}; + std::uint32_t escrowSeq{}; + + void + SetUp() override + { + env.createAccount(alice, XRP(5'000)); + + auto const wasm = assembleWat(kWritesThenRejects); + escrowSeq = env.getAccountRoot(alice).getSequence(); + + auto builder = transactions::EscrowCreateBuilder{alice, alice, STAmount{XRP(1'000)}}; + builder.setBytecode(makeSlice(wasm)); + builder.setCancelAfter( + static_cast(env.getCloseTime().time_since_epoch().count() + 1'000)); + + auto const fee = (env.getOpenLedger().fees().base * 10) + + XRPAmount{static_cast(wasm.size()) * 5}; + ASSERT_EQ(env.submit(builder, alice, fee).ter, tesSUCCESS); + env.close(); + } + + // Submits the finish and closes, because metadata only exists for a closed ledger. + // Returns the result alongside its metadata. + struct Finished + { + TER ter; + std::optional meta; + }; + + [[nodiscard]] Finished + finish() + { + auto builder = transactions::EscrowFinishBuilder{alice, alice, escrowSeq}; + builder.setGas(kAllowance); + + auto const& fees = env.getOpenLedger().fees(); + auto const gasFee = XRPAmount{ + static_cast( + (std::uint64_t{kAllowance} * fees.gasPrice) / microDropsPerDrop) + + 1}; + auto const result = env.submit(builder, alice, fees.base + gasFee); + env.close(); + return Finished{.ter = result.ter, .meta = env.getMetadata(result.tx->getTransactionID())}; + } +}; + +// The point of the whole shape: a contract that rejects can still leave a record of why. +// `EscrowFinish` writes `sfData` *before* returning `tecBYTECODE_REJECTED`, and a `tec` +// keeps its ledger changes, so the escrow survives carrying what the contract wrote. +TEST_F(DataOnReject, ARejectingContractStillPersistsItsData) +{ + auto const result = finish(); + EXPECT_EQ(result.ter, tecBYTECODE_REJECTED); + + auto const sle = + env.getOpenLedger().read(keylet::escrow(alice, SeqProxy::rawSequence(escrowSeq))); + ASSERT_NE(sle, nullptr) << "a rejected finish must leave the escrow in place"; + ASSERT_TRUE(sle->isFieldPresent(sfData)); + + auto const data = sle->getFieldVL(sfData); + EXPECT_EQ(std::string(data.begin(), data.end()), "Data") << strHex(data); +} + +// The reject code reaches the metadata, which is the only way a client learns *which* +// rejection it was — every contract-defined reject shares one TER. +TEST_F(DataOnReject, TheRejectCodeIsReportedInTheMetadata) +{ + auto const result = finish(); + ASSERT_TRUE(result.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const meta = result.meta->getAsObject(); + ASSERT_TRUE(meta.isFieldPresent(sfVMReturnCode)); + + EXPECT_EQ(meta.getFieldI32(sfVMReturnCode), kRejectCode); +} + +// Gas is reported even though the run ended in a rejection: the engine has a trustworthy +// number whenever the contract ran to completion, and a reject is a completed run. +TEST_F(DataOnReject, GasIsChargedAndReportedForARejectedRun) +{ + auto const result = finish(); + ASSERT_TRUE(result.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const meta = result.meta->getAsObject(); + ASSERT_TRUE(meta.isFieldPresent(sfGasUsed)); + + auto const used = meta.getFieldU32(sfGasUsed); + EXPECT_GT(used, 0U); + EXPECT_LE(used, kAllowance) << "the engine cannot spend more than it was given"; +} + +} // namespace +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/FinishFailures.cpp b/src/tests/libxrpl/tx/wasm/transactor/FinishFailures.cpp new file mode 100644 index 0000000000..fe00a72f7f --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/FinishFailures.cpp @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace xrpl::test { +namespace { + +// The ways an `EscrowFinish` against a contract-bearing escrow fails, and what each one +// reports. The distinctions matter to a client: a rejection, a fault, and running out of gas +// are three different outcomes, and only one of them carries a return code. +struct FinishFailures : testing::Test +{ + TxTest env; + Account const alice{"alice"}; + Account const carol{"carol"}; + + void + SetUp() override + { + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + } + + std::uint32_t + createEscrow(std::string_view wat) + { + auto const wasm = assembleWat(wat); + auto const seq = env.getAccountRoot(alice).getSequence(); + + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(500)}}; + builder.setBytecode(makeSlice(wasm)); + builder.setCancelAfter( + static_cast(env.getCloseTime().time_since_epoch().count()) + 1'000); + + EXPECT_EQ(env.submit(builder, alice, escrowCreateFee(env, wasm)).ter, tesSUCCESS); + env.close(); + return seq; + } + + // An escrow with no contract at all, for the "gas without bytecode" case. + std::uint32_t + createPlainEscrow() + { + auto const seq = env.getAccountRoot(alice).getSequence(); + + auto const now = static_cast(env.getCloseTime().time_since_epoch().count()); + + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(500)}}; + // A contract-free escrow needs a `FinishAfter` or a condition — `CancelAfter` alone + // is `temMALFORMED`, because nothing would ever release it. + builder.setFinishAfter(now + 1); + builder.setCancelAfter(now + 1'000); + + EXPECT_EQ(env.submit(builder, alice, XRPAmount{100'000}).ter, tesSUCCESS); + env.close(); + env.close(); // past the finish time + return seq; + } + + struct Finished + { + TER ter; + std::optional meta; + }; + + [[nodiscard]] Finished + finish(std::uint32_t seq, std::optional allowance, XRPAmount fee) + { + auto builder = transactions::EscrowFinishBuilder{carol, alice, seq}; + if (allowance) + builder.setGas(*allowance); + + auto const result = env.submit(builder, carol, fee); + env.close(); + return Finished{.ter = result.ter, .meta = env.getMetadata(result.tx->getTransactionID())}; + } +}; + +TEST_F(FinishFailures, FinishIsRefusedWhileSmartEscrowIsDisabled) +{ + TxTest disabled{allFeatures() - featureSmartEscrow}; + disabled.createAccount(alice, XRP(5'000)); + disabled.createAccount(carol, XRP(5'000)); + + auto builder = transactions::EscrowFinishBuilder{carol, alice, 1}; + builder.setGas(4); + + EXPECT_EQ(disabled.submit(builder, carol, XRPAmount{100'000}).ter, temDISABLED); +} + +// The allowance is bounded by the voted gas limit, so a contract cannot buy unbounded +// execution by simply asking for it. +TEST_F(FinishFailures, AnAllowancePastTheGasLimitIsRefused) +{ + auto fees = TestServiceRegistry::defaultFees(); + fees.gasLimit = 1'000; + env.getServiceRegistry().setFees(fees); + + auto builder = transactions::EscrowFinishBuilder{carol, alice, 1}; + builder.setGas(1'001); + + EXPECT_EQ(env.submit(builder, carol, XRPAmount{10'000'000}).ter, temBAD_LIMIT); +} + +// A zero gas limit turns the runtime off. The old Beast test had to hand-insert an escrow +// ledger entry to reach this, because jtx cannot change its config mid-test; here the escrow +// is created normally and the limit drops afterwards. +TEST_F(FinishFailures, AZeroGasLimitDisablesFinishing) +{ + auto const seq = createEscrow(kReadsLedgerSqn); + + auto fees = TestServiceRegistry::defaultFees(); + fees.gasLimit = 0; + env.getServiceRegistry().setFees(fees); + + auto builder = transactions::EscrowFinishBuilder{carol, alice, seq}; + builder.setGas(1'000); + + EXPECT_EQ(env.submit(builder, carol, XRPAmount{10'000'000}).ter, temTEMP_DISABLED); +} + +TEST_F(FinishFailures, AFinishWithoutAGasFieldIsRefused) +{ + auto const seq = createEscrow(kReadsLedgerSqn); + + EXPECT_EQ(finish(seq, std::nullopt, XRPAmount{100'000}).ter, tefBYTECODE_NOT_INCLUDED); +} + +TEST_F(FinishFailures, AZeroAllowanceIsRefused) +{ + auto const seq = createEscrow(kReadsLedgerSqn); + + auto builder = transactions::EscrowFinishBuilder{carol, alice, seq}; + builder.setGas(0); + + EXPECT_EQ(env.submit(builder, carol, XRPAmount{100'000}).ter, temBAD_LIMIT); +} + +// The allowance is paid for up front, so under-paying is caught before anything runs. +TEST_F(FinishFailures, AFeeThatDoesNotCoverTheAllowanceIsRefused) +{ + auto const seq = createEscrow(kReadsLedgerSqn); + constexpr std::uint32_t kAllowance = 1'000; + + auto const fee = escrowFinishFee(env, kAllowance) - XRPAmount{1}; + EXPECT_EQ(finish(seq, kAllowance, fee).ter, telINSUF_FEE_P); +} + +// Gas on an escrow that has no contract: the transaction is about a thing that isn't there. +TEST_F(FinishFailures, GasAgainstAnEscrowWithoutBytecodeIsRefused) +{ + auto const seq = createPlainEscrow(); + constexpr std::uint32_t kAllowance = 100; + + EXPECT_EQ(finish(seq, kAllowance, escrowFinishFee(env, kAllowance)).ter, tefNO_BYTECODE); +} + +// Running out of gas: essentially the whole allowance is consumed, and there is no return +// code because the contract never reached a return. +// +// "Essentially" because the meter stops at the last instruction it could afford, which for +// this loop leaves a few units unspent — the reported figure is what was really burned, not +// the allowance rounded up. The band is what distinguishes this from a trap, which stops +// early and reports a small fraction. +TEST_F(FinishFailures, RunningOutOfGasConsumesEssentiallyTheWholeAllowanceAndReportsNoReturnCode) +{ + auto const seq = createEscrow(kLoopsForever); + constexpr std::uint32_t kAllowance = 10'000; + + auto const result = finish(seq, kAllowance, escrowFinishFee(env, kAllowance)); + EXPECT_EQ(result.ter, tecOUT_OF_GAS); + + ASSERT_TRUE(result.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const meta = result.meta->getAsObject(); + ASSERT_TRUE(meta.isFieldPresent(sfGasUsed)); + + auto const used = meta.getFieldU32(sfGasUsed); + EXPECT_LE(used, kAllowance) << "the engine cannot spend more than it was given"; + EXPECT_GT(used, kAllowance - (kAllowance / 100)); + EXPECT_FALSE(meta.isFieldPresent(sfVMReturnCode)); +} + +// A trap is a fault, not a rejection: it reports the gas actually burned — less than the +// whole allowance, which is what distinguishes it from running out — and no return code. +TEST_F(FinishFailures, ATrapReportsPartialGasAndNoReturnCode) +{ + auto const seq = createEscrow(kTraps); + constexpr std::uint32_t kAllowance = 1'000; + + auto const result = finish(seq, kAllowance, escrowFinishFee(env, kAllowance)); + EXPECT_EQ(result.ter, tecFAILED_PROCESSING); + + ASSERT_TRUE(result.meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const meta = result.meta->getAsObject(); + ASSERT_TRUE(meta.isFieldPresent(sfGasUsed)); + EXPECT_LT(meta.getFieldU32(sfGasUsed), kAllowance); + EXPECT_FALSE(meta.isFieldPresent(sfVMReturnCode)); +} + +} // namespace +} // namespace xrpl::test diff --git a/src/tests/libxrpl/tx/wasm/transactor/GasFees.cpp b/src/tests/libxrpl/tx/wasm/transactor/GasFees.cpp new file mode 100644 index 0000000000..b429bf5675 --- /dev/null +++ b/src/tests/libxrpl/tx/wasm/transactor/GasFees.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace xrpl::test { +namespace { + +// The gas allowance is paid for in drops up front, and the conversion is the arithmetic most +// likely to go wrong: allowance × gasPrice is a product of two 32-bit values, so a narrow +// intermediate would wrap and let a large allowance be bought for almost nothing. These pin +// that a big allowance costs a big fee. + +// Close to the default gas limit of 1'000'000, so the product is as large as the transactor +// will ever be asked to compute. +constexpr std::uint32_t kBigAllowance = 996'433; + +struct GasFees : testing::Test +{ + TxTest env; + Account const alice{"alice"}; + Account const carol{"carol"}; + std::uint32_t escrowSeq{}; + + void + SetUp() override + { + env.createAccount(alice, XRP(5'000)); + env.createAccount(carol, XRP(5'000)); + + auto const wasm = assembleWat(kReadsLedgerSqn); + escrowSeq = env.getAccountRoot(alice).getSequence(); + + auto builder = transactions::EscrowCreateBuilder{alice, carol, STAmount{XRP(1'000)}}; + builder.setBytecode(makeSlice(wasm)); + builder.setCancelAfter( + static_cast(env.getCloseTime().time_since_epoch().count()) + 1'000); + + ASSERT_EQ(env.submit(builder, alice, escrowCreateFee(env, wasm)).ter, tesSUCCESS); + env.close(); + } + + [[nodiscard]] TER + finishPaying(XRPAmount fee) + { + auto builder = transactions::EscrowFinishBuilder{carol, alice, escrowSeq}; + builder.setGas(kBigAllowance); + return env.submit(builder, carol, fee).ter; + } +}; + +// The fee owed dwarfs the allowance's own magnitude, so a token payment cannot cover it. If +// the product ever wrapped, this is the test that would notice: 30 drops would start +// looking sufficient. +TEST_F(GasFees, ALargeAllowanceCannotBeBoughtForAFewDrops) +{ + auto const owed = escrowFinishFee(env, kBigAllowance); + ASSERT_GT(owed.drops(), kBigAllowance) << "the fee must scale with the allowance"; + + EXPECT_EQ(finishPaying(XRPAmount{30}), telINSUF_FEE_P); +} + +TEST_F(GasFees, AFeeOneDropShortOfTheAllowanceIsRefused) +{ + EXPECT_EQ(finishPaying(escrowFinishFee(env, kBigAllowance) - XRPAmount{1}), telINSUF_FEE_P); +} + +// And the exact fee is sufficient — otherwise the two refusals above would prove nothing, +// since any fee at all might be being rejected. +TEST_F(GasFees, TheExactFeeIsAccepted) +{ + EXPECT_EQ(finishPaying(escrowFinishFee(env, kBigAllowance)), tesSUCCESS); +} + +// Only what the contract actually burned is charged against the allowance — asking for a +// near-limit budget does not mean spending it. +TEST_F(GasFees, OnlyTheGasActuallyUsedIsReported) +{ + auto builder = transactions::EscrowFinishBuilder{carol, alice, escrowSeq}; + builder.setGas(kBigAllowance); + + auto const result = env.submit(builder, carol, escrowFinishFee(env, kBigAllowance)); + ASSERT_EQ(result.ter, tesSUCCESS); + env.close(); + + auto const meta = env.getMetadata(result.tx->getTransactionID()); + ASSERT_TRUE(meta.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + auto const obj = meta->getAsObject(); + ASSERT_TRUE(obj.isFieldPresent(sfGasUsed)); + + EXPECT_LT(obj.getFieldU32(sfGasUsed), kBigAllowance); + EXPECT_EQ(obj.getFieldI32(sfVMReturnCode), 5); +} + +} // namespace +} // namespace xrpl::test